diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Sun Apr 14 12:16:56 2002
+++ b/CREDITS	Sun Apr 14 12:16:56 2002
@@ -1916,6 +1916,7 @@
 N: Petko Manolov
 E: petkan@users.sourceforge.net
 D: USB ethernet pegasus/pegasus-II driver
+D: USB ethernet rtl8150 driver
 D: optimizing i[45]86 string routines
 D: i386 task switching hacks
 S: 482 Shadowgraph Dr.
@@ -2132,7 +2133,7 @@
 S: Germany
 
 N: Thomas Molina
-E: tmolina@home.com
+E: tmolina@cox.net
 D: bug fixes, documentation, minor hackery
 
 N: David Mosberger-Tang
@@ -2536,6 +2537,7 @@
 
 N: Thiago Berlitz Rondon
 E: maluco@mileniumnet.com.br
+W: http://vivaldi.linuxms.com.br/~maluco
 D: Miscellaneous kernel hacker
 S: R. Anhanguera, 1487 - Ipiranga
 S: 79080-740 - Campo Grande - Mato Grosso do Sul
@@ -3288,9 +3290,10 @@
 S: USA
 
 N: Richard Zidlicky
-E: rdzidlic@geocities.com,rdzidlic@cip.informatik.uni-erlangen.de
-W: http://www.geocities.com/SiliconValley/Bay/2602/
+E: rz@linux-m68k.org, rdzidlic@geocities.com
+W: http://www.geocities.com/rdzidlic
 D: Q40 port - see arch/m68k/q40/README
+D: various m68k hacks
 S: Germany
 
 N: Werner Zimmermann
diff -Nru a/Documentation/00-INDEX b/Documentation/00-INDEX
--- a/Documentation/00-INDEX	Sun Apr 14 12:16:56 2002
+++ b/Documentation/00-INDEX	Sun Apr 14 12:16:56 2002
@@ -12,14 +12,14 @@
 
 00-INDEX
 	- this file.
+BK-usage/
+	- directory with info on BitKeeper.
 BUG-HUNTING
 	- brute force method of doing binary search of patches to find bug.
 Changes
 	- list of changes that break older software packages.
 CodingStyle
 	- how the boss likes the C code in the kernel to look.
-Configure.help
-	- text file that is used for help when you run "make config"
 DMA-mapping.txt
 	- info for PCI drivers using DMA portably across all platforms.
 DocBook/
@@ -34,6 +34,10 @@
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
 README.moxa
 	- release notes for Moxa mutiport serial card.
+README.nsp_cs.eng
+	- info on WorkBiT NinjaSCSI-3/32Bi driver.
+SAK.txt
+	- info on Secure Attention Keys.
 SubmittingDrivers
 	- procedure to get a new driver source included into the kernel tree.
 SubmittingPatches
@@ -44,6 +48,8 @@
 	- directory with info about Linux on the ARM architecture.
 binfmt_misc.txt
 	- info on the kernel support for extra binary formats.
+block/
+	- info on the Block I/O (BIO) layer.
 cachetlb.txt
 	- describes the cache/TLB flushing interfaces Linux uses.
 cciss.txt
@@ -54,6 +60,8 @@
 	- info on Computone Intelliport II/Plus Multiport Serial Driver
 cpqarray.txt
 	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
+cris/
+	- directory with info about Linux on CRIS architecture.
 devices.txt
 	- plain ASCII listing of all the nodes in /dev/ with major minor #'s
 digiboard.txt
@@ -62,6 +70,8 @@
 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 dnotify.txt
 	- info about directory notification in Linux.
+driver-model.txt
+	- info about Linux driver model.
 exception.txt
 	- how Linux v2.2 handles exceptions without verify_area etc.
 fb/
@@ -80,12 +90,16 @@
 	- directory with info about the I2C bus/protocol (2 wire, kHz speed)
 i386/
 	- directory with info about Linux on intel 32 bit architecture.
+i810_rng.txt
+	- info on Linux support for random number generator in i8xx chipsets.
 ia64/
 	- directory with info about Linux on intel 64 bit architecture.
 ide.txt
 	- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS)
 initrd.txt
 	- how to use the RAM disk as an initial/temporary root filesystem.
+input/
+	- info on Linux input device support.
 ioctl-number.txt
 	- how to implement and register device/driver ioctl calls.
 isapnp.txt
@@ -94,12 +108,6 @@
 	- directory with info on the Linux ISDN support, and supported cards.
 java.txt
 	- info on the in-kernel binary support for Java(tm)
-joystick-api.txt
-	- API specification for applications that will be using the joystick.
-joystick-parport.txt 
-	- info on how to hook joysticks/gamepads to the parallel port.
-joystick.txt
-	- info on using joystick devices (and driver) with Linux.
 kbuild/
 	- directory with info about the kernel build process
 kernel-doc-nano-HOWTO.txt
@@ -128,6 +136,8 @@
 	- info on boot arguments for the multiple devices driver
 memory.txt
 	- info on typical Linux memory problems.
+mips/
+	- directory with info about Linux on MIPS architecture.
 mkdev.cciss
 	- script to make /dev entries for SMART controllers (see cciss.txt)
 mkdev.ida
@@ -161,9 +171,13 @@
 pcwd-watchdog.txt
 	- info and sample code for using with the PC Watchdog reset card.
 pm.txt
-	- info on Linux power management support
+	- info on Linux power management support.
+power/
+	- directory with info on Linux PCI power management.
 powerpc/
 	- directory with info on using Linux with the PowerPC.
+preempt-locking.txt
+	- info on locking under a preemptive kernel.
 ramdisk.txt
 	- short guide on how to set up and use the RAM disk.
 riscom8.txt
@@ -172,6 +186,8 @@
 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
 s390/
 	- directory with info on using Linux on the IBM S390.
+sh/
+	- directory with info on porting Linux to a new architecture.
 scsi-generic.txt
 	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
 scsi.txt
@@ -186,6 +202,8 @@
 	- LaTeX document describing implementation of Multiprocessor Linux
 smp.txt
 	- a few more notes on symmetric multi-processing
+sonypi.txt
+	- info on Linux Sony Programmable I/O Device support.
 sound/
 	- directory with info on sound card support
 sparc/
@@ -216,6 +234,8 @@
 	- directory with info on the Linux vm code.
 watchdog.txt
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
+x86_64/
+	- directory with info on Linux support for AMD x86-64 (Hammer) machines.
 xterm-linux.xpm
 	- XPM image of penguin logo (see logo.txt) sitting on an xterm.
 zorro.txt
diff -Nru a/Documentation/BK-usage/bksend b/Documentation/BK-usage/bksend
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/BK-usage/bksend	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,36 @@
+#!/bin/sh
+# A script to format BK changeset output in a manner that is easy to read.
+# Andreas Dilger <adilger@turbolabs.com>  13/02/2002
+#
+# Add diffstat output after Changelog <adilger@turbolabs.com>   21/02/2002
+
+PROG=bksend
+
+usage() {
+	echo "usage: $PROG -r<rev>"
+	echo -e "\twhere <rev> is of the form '1.23', '1.23..', '1.23..1.27',"
+	echo -e "\tor '+' to indicate the most recent revision"
+
+	exit 1
+}
+
+case $1 in
+-r) REV=$2; shift ;;
+-r*) REV=`echo $1 | sed 's/^-r//'` ;;
+*) echo "$PROG: no revision given, you probably don't want that";;
+esac
+
+[ -z "$REV" ] && usage
+
+echo "You can import this changeset into BK by piping this whole message to:"
+echo "'| bk receive [path to repository]' or apply the patch as usual."
+
+SEP="\n===================================================================\n\n"
+echo -e $SEP
+bk changes -r$REV
+echo
+bk export -tpatch -du -h -r$REV | diffstat
+echo; echo
+bk export -tpatch -du -h -r$REV
+echo -e $SEP
+bk send -wgzip_uu -r$REV -
diff -Nru a/Documentation/BK-usage/bz64wrap b/Documentation/BK-usage/bz64wrap
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/BK-usage/bz64wrap	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# bz64wrap - the sending side of a bzip2 | base64 stream
+# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
+
+
+PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
+
+# A program to generate base64 encoding on stdout
+BASE64_ENCODE="uuencode -m /dev/stdout"
+BASE64_BEGIN=
+BASE64_END=
+
+BZIP=NO
+BASE64=NO
+
+# Test if we have the bzip program installed
+bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES
+
+# Test if uuencode can handle the -m (MIME) encoding option
+$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
+
+if [ $BASE64 = NO ]; then
+	BASE64_ENCODE=mimencode
+	BASE64_BEGIN="begin-base64 644 -"
+	BASE64_END="===="
+
+	$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
+fi
+
+if [ $BZIP = NO -o $BASE64 = NO ]; then
+	echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64"
+	exit 1
+fi
+
+# Sadly, mimencode does not appear to have good "begin" and "end" markers
+# like uuencode does, and it is picky about getting the right start/end of
+# the base64 stream, so we handle this internally.
+echo "$BASE64_BEGIN"
+bzip2 -9 | $BASE64_ENCODE
+echo "$BASE64_END"
diff -Nru a/Documentation/BK-usage/cset-to-linus b/Documentation/BK-usage/cset-to-linus
--- a/Documentation/BK-usage/cset-to-linus	Sun Apr 14 12:16:55 2002
+++ b/Documentation/BK-usage/cset-to-linus	Sun Apr 14 12:16:55 2002
@@ -1,4 +1,4 @@
-#!/usr/bin/perl5.6.1 -w
+#!/usr/bin/perl -w
 
 use strict;
 
diff -Nru a/Documentation/BK-usage/csets-to-patches b/Documentation/BK-usage/csets-to-patches
--- a/Documentation/BK-usage/csets-to-patches	Sun Apr 14 12:16:59 2002
+++ b/Documentation/BK-usage/csets-to-patches	Sun Apr 14 12:16:59 2002
@@ -1,4 +1,4 @@
-#!/usr/bin/perl5.6.1 -w
+#!/usr/bin/perl -w
 
 use strict;
 
diff -Nru a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/BK-usage/unbz64wrap	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# unbz64wrap - the receiving side of a bzip2 | base64 stream
+# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
+
+# Sadly, mimencode does not appear to have good "begin" and "end" markers
+# like uuencode does, and it is picky about getting the right start/end of
+# the base64 stream, so we handle this explicitly here.
+
+PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
+
+if mimencode -u < /dev/null > /dev/null 2>&1 ; then
+	SHOW=
+	while read LINE; do
+		case $LINE in
+		begin-base64*) SHOW=YES ;;
+		====) SHOW= ;;
+		*) [ "$SHOW" ] && echo $LINE ;;
+		esac
+	done | mimencode -u | bunzip2
+	exit $?
+else
+	cat - | uudecode -o /dev/stdout | bunzip2
+	exit $?
+fi
diff -Nru a/Documentation/Changes b/Documentation/Changes
--- a/Documentation/Changes	Sun Apr 14 12:16:59 2002
+++ b/Documentation/Changes	Sun Apr 14 12:16:59 2002
@@ -55,7 +55,7 @@
 o  modutils               2.4.2                   # insmod -V
 o  e2fsprogs              1.25                    # tune2fs
 o  jfsutils               1.0.14                  # fsck.jfs -V
-o  reiserfsprogs          3.x.0j                  # reiserfsck 2>&1|grep reiserfsprogs
+o  reiserfsprogs          3.x.1b                  # reiserfsck 2>&1|grep reiserfsprogs
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
@@ -107,8 +107,8 @@
 your kernel.  This change does, however, mean that you need a recent
 release of binutils.
 
-System utililities
-==================
+System utilities
+================
 
 Architectural changes
 ---------------------
@@ -320,7 +320,7 @@
 
 Reiserfsprogs
 -------------
-o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.0j.tar.gz>
+o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.x.0b.tar.gz>
 
 LVM toolset
 -----------
diff -Nru a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
--- a/Documentation/DMA-mapping.txt	Sun Apr 14 12:16:59 2002
+++ b/Documentation/DMA-mapping.txt	Sun Apr 14 12:16:59 2002
@@ -759,13 +759,10 @@
    Struct scatterlist must contain, at a minimum, the following
    members:
 
-	char *address;
 	struct page *page;
 	unsigned int offset;
 	unsigned int length;
 
-   The "address" member will disappear in 2.5.x
-
    This means that your pci_{map,unmap}_sg() and all other
    interfaces dealing with scatterlists must be able to cope
    properly with page being non NULL.
@@ -774,9 +771,6 @@
    either specified by "address" or by a "page+offset" pair.
    If "address" is NULL, then "page+offset" is being used.
    If "page" is NULL, then "address" is being used.
-
-   In 2.5.x, all scatterlists will use "page+offset".  But during
-   2.4.x we still have to support the old method.
 
 2) More to come...
 
diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile	Sun Apr 14 12:16:58 2002
+++ b/Documentation/DocBook/Makefile	Sun Apr 14 12:16:58 2002
@@ -59,8 +59,8 @@
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/net/wan/z85230.c \
 		<z8530book.tmpl >z8530book.sgml
 
-via-audio.sgml: via-audio.tmpl $(TOPDIR)/drivers/sound/via82cxxx_audio.c
-	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/sound/via82cxxx_audio.c \
+via-audio.sgml: via-audio.tmpl $(TOPDIR)/sound/oss/via82cxxx_audio.c
+	$(TOPDIR)/scripts/docgen $(TOPDIR)/sound/oss/via82cxxx_audio.c \
 		<via-audio.tmpl >via-audio.sgml
 
 tulip-user.sgml: tulip-user.tmpl
@@ -100,12 +100,12 @@
 		$(TOPDIR)/drivers/hotplug/pci_hotplug_core.c \
 		$(TOPDIR)/drivers/hotplug/pci_hotplug_util.c \
 		$(TOPDIR)/drivers/block/ll_rw_blk.c \
-		$(TOPDIR)/drivers/sound/sound_core.c \
-		$(TOPDIR)/drivers/sound/sound_firmware.c \
+		$(TOPDIR)/sound/sound_core.c \
+		$(TOPDIR)/sound/sound_firmware.c \
 		$(TOPDIR)/drivers/net/wan/syncppp.c \
 		$(TOPDIR)/drivers/net/wan/z85230.c \
-		$(TOPDIR)/drivers/usb/hcd.c \
-		$(TOPDIR)/drivers/usb/usb.c \
+		$(TOPDIR)/drivers/usb/core/hcd.c \
+		$(TOPDIR)/drivers/usb/core/usb.c \
 		$(TOPDIR)/drivers/video/fbmem.c \
 		$(TOPDIR)/drivers/video/fbcmap.c \
 		$(TOPDIR)/drivers/video/fbcon.c \
diff -Nru a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
--- a/Documentation/DocBook/kernel-api.tmpl	Sun Apr 14 12:16:54 2002
+++ b/Documentation/DocBook/kernel-api.tmpl	Sun Apr 14 12:16:54 2002
@@ -203,8 +203,8 @@
 
   <chapter id="snddev">
      <title>Sound Devices</title>
-!Edrivers/sound/sound_core.c
-!Idrivers/sound/sound_firmware.c
+!Esound/sound_core.c
+!Isound/sound_firmware.c
   </chapter>
 
   <chapter id="usb">
@@ -282,7 +282,7 @@
     </sect1>
 
     <sect1><title>USB Core APIs</title>
-!Edrivers/usb/usb.c
+!Edrivers/usb/core/usb.c
     </sect1>
 
     <sect1><title>Host Controller APIs</title>
@@ -290,7 +290,7 @@
     most of which implement standard register interfaces such as
     EHCI, OHCI, or UHCI.
     </para>
-!Edrivers/usb/hcd.c
+!Edrivers/usb/core/hcd.c
     </sect1>
 
   </chapter>
diff -Nru a/Documentation/DocBook/via-audio.tmpl b/Documentation/DocBook/via-audio.tmpl
--- a/Documentation/DocBook/via-audio.tmpl	Sun Apr 14 12:16:59 2002
+++ b/Documentation/DocBook/via-audio.tmpl	Sun Apr 14 12:16:59 2002
@@ -537,7 +537,7 @@
    </listitem>
    <listitem>
     <para>
- Optimize included headers to eliminate headers found in linux/drivers/sound
+ Optimize included headers to eliminate headers found in linux/sound
 	</para>
    </listitem>
   </itemizedlist>
@@ -587,7 +587,9 @@
   
   <chapter id="intfunctions">
      <title>Internal Functions</title>
-!Idrivers/sound/via82cxxx_audio.c
+!Isound/oss/via82cxxx_audio.c
   </chapter>
 
 </book>
+
+
diff -Nru a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
--- a/Documentation/SubmittingDrivers	Sun Apr 14 12:16:59 2002
+++ b/Documentation/SubmittingDrivers	Sun Apr 14 12:16:59 2002
@@ -3,7 +3,7 @@
 
 This document is intended to explain how to submit device drivers to the
 Linux 2.2 and 2.4 kernel trees. Note that if you are interested in video
-card drivers you should probably talk to XFree86 (http://wwww.xfree86.org) 
+card drivers you should probably talk to XFree86 (http://www.xfree86.org) 
 instead.
 
 Also read the Documentation/SubmittingPatches document.
diff -Nru a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
--- a/Documentation/filesystems/Locking	Sun Apr 14 12:16:57 2002
+++ b/Documentation/filesystems/Locking	Sun Apr 14 12:16:57 2002
@@ -65,7 +65,7 @@
 readlink:	no	no
 follow_link:	no	no
 truncate:	no	yes		(see below)
-setattr:	yes	if ATTR_SIZE
+setattr:	no	yes
 permission:	yes	no
 getattr:				(see below)
 revalidate:	no			(see below)
@@ -140,6 +140,10 @@
 	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*bmap)(struct address_space *, long);
+	int (*flushpage) (struct page *, unsigned long);
+	int (*releasepage) (struct page *, int);
+	int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int);
+
 locking rules:
 	All may block
 		BKL	PageLocked(page)
@@ -149,6 +153,8 @@
 prepare_write:	no	yes
 commit_write:	no	yes
 bmap:		yes
+flushpage:	no	yes
+releasepage:	no	yes
 
 	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
@@ -161,6 +167,15 @@
 filesystems and by the swapper. The latter will eventually go away. All
 instances do not actually need the BKL. Please, keep it that way and don't
 breed new callers.
+	->flushpage() is called when the filesystem must attempt to drop
+some or all of the buffers from the page when it is being truncated.  It
+returns zero on success.  If ->flushpage is zero, the kernel uses
+block_flushpage() instead.
+	->releasepage() is called when the kernel is about to try to drop the
+buffers from the page in preparation for freeing it.  It returns zero to
+indicate that the buffers are (or may be) freeable.  If ->releasepage is zero,
+the kernel assumes that the fs has no private interest in the buffers.
+
 	Note: currently almost all instances of address_space methods are
 using BKL for internal serialization and that's one of the worst sources
 of contention. Normally they are calling library functions (in fs/buffer.c)
diff -Nru a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog
--- a/Documentation/filesystems/devfs/ChangeLog	Sun Apr 14 12:16:56 2002
+++ b/Documentation/filesystems/devfs/ChangeLog	Sun Apr 14 12:16:56 2002
@@ -1885,3 +1885,23 @@
 - Cleaned up declaration of <stat_read>
 
 - Updated README from master HTML file
+===============================================================================
+Changes for patch v209
+
+- Updated README from master HTML file
+
+- Removed silently introduced calls to lock_kernel() and
+  unlock_kernel() due to recent VFS locking changes. BKL isn't
+  required in devfs 
+
+- Changed <devfs_rmdir> to allow later additions if not yet empty
+
+- Added calls to <devfs_register_partitions> in drivers/block/blkpc.c
+  <add_partition> and <del_partition>
+
+- Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
+  bitfield
+
+- Fixed bitfield data type for <devfs_*alloc_devnum>
+
+- Made major bitfield type and initialiser 64 bit safe
diff -Nru a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README
--- a/Documentation/filesystems/devfs/README	Sun Apr 14 12:16:58 2002
+++ b/Documentation/filesystems/devfs/README	Sun Apr 14 12:16:58 2002
@@ -3,7 +3,7 @@
 
 Linux Devfs (Device File System) FAQ
 Richard Gooch
-24-JAN-2002
+4-APR-2002
 
 
 Document languages:
@@ -803,12 +803,19 @@
 
 add the following lines to your /etc/devfsd.conf file:
 
-REGISTER	^pt[sy]/.*	IGNORE
-CHANGE		^pt[sy]/.*	IGNORE
+REGISTER	^pt[sy]		IGNORE
+CREATE		^pt[sy]		IGNORE
+CHANGE		^pt[sy]		IGNORE
+DELETE		^pt[sy]		IGNORE
 REGISTER	.*		COPY	/dev-state/$devname $devpath
-CHANGE		.*		COPY	$devpath /dev-state/$devname
 CREATE		.*		COPY	$devpath /dev-state/$devname
+CHANGE		.*		COPY	$devpath /dev-state/$devname
+DELETE		.*		CFUNCTION GLOBAL unlink /dev-state/$devname
+RESTORE		/dev-state
 
+Note that the sample devfsd.conf file contains these lines,
+as well as other sample configurations you may find useful. See the
+devfsd distribution
 
 
 reboot.
@@ -872,7 +879,8 @@
 (for example, by starting with /etc/fstab), and then limiting the
 compatibility entries that devfsd creates.
 
-MAKE SURE YOU INSTALL DEVFSD BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
+IF YOU CONFIGURE TO MOUNT DEVFS AT BOOT, MAKE SURE YOU INSTALL DEVFSD
+BEFORE YOU BOOT A DEVFS-ENABLED KERNEL!
 
 Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of
 reports back. Many of these are because people are trying to run
@@ -1565,6 +1573,24 @@
 the existence of the entry should be relied upon.
 
 
+When I start devfsd, I see the error:
+Error opening file: ".devfsd"   No such file or directory?
+
+This means that devfs is not mounted. Make sure you have devfs mounted.
+
+
+How do I mount devfs?
+
+First make sure you have devfs compiled into your kernel (see
+above). Then you will either need to:
+
+set CONFIG_DEVFS_MOUNT=y in your kernel config
+pass devfs=mount to your boot loader
+mount devfs manually in your boot scripts with:
+mount -t none devfs /dev
+
+
+
 
 
 
@@ -1760,6 +1786,15 @@
 
 
 
+make sure you have enabled debugging output when configuring your
+kernel. You will need to set (at least) the following config options:
+
+CONFIG_DEVFS_DEBUG=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SLAB=y
+
+
+
 please make sure you have the latest devfs patches applied. The
 latest kernel version might not have the latest devfs patches applied
 yet (Linus is very busy)
@@ -1768,7 +1803,10 @@
 save a copy of your complete kernel logs (preferably by
 using the dmesg programme) for later inclusion in your bug
 report. You may need to use the -s switch to increase the
-internal buffer size so you can capture all the boot messages
+internal buffer size so you can capture all the boot messages.
+Don't edit or trim the dmesg output
+
+
 
 
 try booting with devfs=dall passed to the kernel boot
@@ -1925,7 +1963,7 @@
 
 A Korean translation by viatoris@nownuri.net is available at
 
-http://viatoris.new21.org/devfs/devfs.html
+http://your.destiny.pe.kr/devfs/devfs.html
 
 
 
diff -Nru a/Documentation/filesystems/porting b/Documentation/filesystems/porting
--- a/Documentation/filesystems/porting	Sun Apr 14 12:16:57 2002
+++ b/Documentation/filesystems/porting	Sun Apr 14 12:16:57 2002
@@ -116,3 +116,10 @@
 	FS_SINGLE is gone (actually, that had happened back when ->get_sb()
 went in - and hadn't been documented ;-/).  Just remove it from fs_flags
 (and see ->get_sb() entry for other actions).
+
+---
+[mandatory]
+
+->setattr() is called without BKL now.  Caller _always_ holds ->i_sem, so
+watch for ->i_sem-grabbing code that might be used by your ->setattr().
+Callers of notify_change() need ->i_sem now.
diff -Nru a/Documentation/i810_rng.txt b/Documentation/i810_rng.txt
--- a/Documentation/i810_rng.txt	Sun Apr 14 12:16:59 2002
+++ b/Documentation/i810_rng.txt	Sun Apr 14 12:16:59 2002
@@ -70,6 +70,10 @@
 
 Change history:
 
+	Version 0.9.7:
+	* Support other i8xx chipsets too (by adding 82801BA(M) and
+	  82801CA(M) detection)
+
 	Version 0.9.6:
 	* Internal driver cleanups, prep for 1.0.0 release.
 
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Sun Apr 14 12:16:59 2002
+++ b/Documentation/kernel-parameters.txt	Sun Apr 14 12:16:59 2002
@@ -17,6 +17,7 @@
 	CD	Appropriate CD support is enabled.
 	DEVFS   devfs support is enabled. 
 	DRM	Direct Rendering Management support is enabled. 
+	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
 	FB	The frame buffer device is enabled.
 	HW	Appropriate hardware is enabled.
@@ -218,6 +219,9 @@
 	gc_3=		[HW,JOY]
  
 	gdth=		[HW,SCSI]
+
+	gpt             [EFI] Forces disk with valid GPT signature but
+			invalid Protective MBR to be treated as GPT.
 
 	gscd=		[HW,CD]
 
diff -Nru a/Documentation/networking/dl2k.txt b/Documentation/networking/dl2k.txt
--- a/Documentation/networking/dl2k.txt	Sun Apr 14 12:16:55 2002
+++ b/Documentation/networking/dl2k.txt	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Jan 02, 2002
+    Jan 29, 2002
 
 Contents
 ========
@@ -199,8 +199,8 @@
 				  6          	1000Mbps full duplex.
 
 				  By default, the NIC operates at autosense.
-				  Note that only 1000mbps_fd and 1000mbps_hd
-				  types are available for fiber adapter.
+				  1000mbps_fd and 1000mbps_hd types are only
+				  available for fiber adapter.
 
 vlan=[0|1]			- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
--- a/Documentation/networking/ip-sysctl.txt	Sun Apr 14 12:16:58 2002
+++ b/Documentation/networking/ip-sysctl.txt	Sun Apr 14 12:16:58 2002
@@ -126,7 +126,13 @@
 	if network conditions require more than default value.
 
 tcp_tw_recycle - BOOLEAN
-	Enable fast recycling TIME-WAIT sockets. Default value is 1.
+	Enable fast recycling TIME-WAIT sockets. Default value is 0.
+	It should not be changed without advice/request of technical
+	experts.
+
+tcp_tw_reuse - BOOLEAN
+	Allow to reuse TIME-WAIT sockets for new connections when it is
+	safe from protocol viewpoint. Default value is 0.
 	It should not be changed without advice/request of technical
 	experts.
 
@@ -182,10 +188,7 @@
 	still did not receive an acknowledgement from connecting client.
 	Default value is 1024 for systems with more than 128Mb of memory,
 	and 128 for low memory machines. If server suffers of overload,
-	try to increase this number. Warning! If you make it greater
-	than 1024, it would be better to change TCP_SYNQ_HSIZE in
-	include/net/tcp.h to keep TCP_SYNQ_HSIZE*16<=tcp_max_syn_backlog
-	and to recompile kernel.
+	try to increase this number.
 
 tcp_window_scaling - BOOLEAN
 	Enable window scaling as defined in RFC1323.
@@ -357,6 +360,17 @@
 mc_forwarding - BOOLEAN
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
+
+medium_id - INTEGER
+	Integer value used to differentiate the devices by the medium they
+	are attached to. Two devices can have different id values when
+	the broadcast packets are received only on one of them.
+	The default value 0 means that the device is the only interface
+	to its medium, value of -1 means that medium is not known.
+	
+	Currently, it is used to change the proxy_arp behavior:
+	the proxy_arp feature is enabled for packets forwarded between
+	two devices attached to different media.
 
 proxy_arp - BOOLEAN
 	Do proxy arp.
diff -Nru a/Documentation/networking/ppp_generic.txt b/Documentation/networking/ppp_generic.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/networking/ppp_generic.txt	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,432 @@
+		PPP Generic Driver and Channel Interface
+		----------------------------------------
+
+			    Paul Mackerras
+			   paulus@samba.org
+			      7 Feb 2002
+
+The generic PPP driver in linux-2.4 provides an implementation of the
+functionality which is of use in any PPP implementation, including:
+
+* the network interface unit (ppp0 etc.)
+* the interface to the networking code
+* PPP multilink: splitting datagrams between multiple links, and
+  ordering and combining received fragments
+* the interface to pppd, via a /dev/ppp character device
+* packet compression and decompression
+* TCP/IP header compression and decompression
+* detecting network traffic for demand dialling and for idle timeouts
+* simple packet filtering
+
+For sending and receiving PPP frames, the generic PPP driver calls on
+the services of PPP `channels'.  A PPP channel encapsulates a
+mechanism for transporting PPP frames from one machine to another.  A
+PPP channel implementation can be arbitrarily complex internally but
+has a very simple interface with the generic PPP code: it merely has
+to be able to send PPP frames, receive PPP frames, and optionally
+handle ioctl requests.  Currently there are PPP channel
+implementations for asynchronous serial ports, synchronous serial
+ports, and for PPP over ethernet.
+
+This architecture makes it possible to implement PPP multilink in a
+natural and straightforward way, by allowing more than one channel to
+be linked to each ppp network interface unit.  The generic layer is
+responsible for splitting datagrams on transmit and recombining them
+on receive.
+
+
+PPP channel API
+---------------
+
+See include/linux/ppp_channel.h for the declaration of the types and
+functions used to communicate between the generic PPP layer and PPP
+channels.
+
+Each channel has to provide two functions to the generic PPP layer,
+via the ppp_channel.ops pointer:
+
+* start_xmit() is called by the generic layer when it has a frame to
+  send.  The channel has the option of rejecting the frame for
+  flow-control reasons.  In this case, start_xmit() should return 0
+  and the channel should call the ppp_output_wakeup() function at a
+  later time when it can accept frames again, and the generic layer
+  will then attempt to retransmit the rejected frame(s).  If the frame
+  is accepted, the start_xmit() function should return 1.
+
+* ioctl() provides an interface which can be used by a user-space
+  program to control aspects of the channel's behaviour.  This
+  procedure will be called when a user-space program does an ioctl
+  system call on an instance of /dev/ppp which is bound to the
+  channel.  (Usually it would only be pppd which would do this.)
+
+The generic PPP layer provides seven functions to channels:
+
+* ppp_register_channel() is called when a channel has been created, to
+  notify the PPP generic layer of its presence.  For example, setting
+  a serial port to the PPPDISC line discipline causes the ppp_async
+  channel code to call this function.
+
+* ppp_unregister_channel() is called when a channel is to be
+  destroyed.  For example, the ppp_async channel code calls this when
+  a hangup is detected on the serial port.
+
+* ppp_output_wakeup() is called by a channel when it has previously
+  rejected a call to its start_xmit function, and can now accept more
+  packets.
+
+* ppp_input() is called by a channel when it has received a complete
+  PPP frame.
+
+* ppp_input_error() is called by a channel when it has detected that a
+  frame has been lost or dropped (for example, because of a FCS (frame
+  check sequence) error).
+
+* ppp_channel_index() returns the channel index assigned by the PPP
+  generic layer to this channel.  The channel should provide some way
+  (e.g. an ioctl) to transmit this back to user-space, as user-space
+  will need it to attach an instance of /dev/ppp to this channel.
+
+* ppp_unit_number() returns the unit number of the ppp network
+  interface to which this channel is connected, or -1 if the channel
+  is not connected.
+
+Connecting a channel to the ppp generic layer is initiated from the
+channel code, rather than from the generic layer.  The channel is
+expected to have some way for a user-level process to control it
+independently of the ppp generic layer.  For example, with the
+ppp_async channel, this is provided by the file descriptor to the
+serial port.
+
+Generally a user-level process will initialize the underlying
+communications medium and prepare it to do PPP.  For example, with an
+async tty, this can involve setting the tty speed and modes, issuing
+modem commands, and then going through some sort of dialog with the
+remote system to invoke PPP service there.  We refer to this process
+as `discovery'.  Then the user-level process tells the medium to
+become a PPP channel and register itself with the generic PPP layer.
+The channel then has to report the channel number assigned to it back
+to the user-level process.  From that point, the PPP negotiation code
+in the PPP daemon (pppd) can take over and perform the PPP
+negotiation, accessing the channel through the /dev/ppp interface.
+
+At the interface to the PPP generic layer, PPP frames are stored in
+skbuff structures and start with the two-byte PPP protocol number.
+The frame does *not* include the 0xff `address' byte or the 0x03
+`control' byte that are optionally used in async PPP.  Nor is there
+any escaping of control characters, nor are there any FCS or framing
+characters included.  That is all the responsibility of the channel
+code, if it is needed for the particular medium.  That is, the skbuffs
+presented to the start_xmit() function contain only the 2-byte
+protocol number and the data, and the skbuffs presented to ppp_input()
+must be in the same format.
+
+The channel must provide an instance of a ppp_channel struct to
+represent the channel.  The channel is free to use the `private' field
+however it wishes.  The channel should initialize the `mtu' and
+`hdrlen' fields before calling ppp_register_channel() and not change
+them until after ppp_unregister_channel() returns.  The `mtu' field
+represents the maximum size of the data part of the PPP frames, that
+is, it does not include the 2-byte protocol number.
+
+If the channel needs some headroom in the skbuffs presented to it for
+transmission (i.e., some space free in the skbuff data area before the
+start of the PPP frame), it should set the `hdrlen' field of the
+ppp_channel struct to the amount of headroom required.  The generic
+PPP layer will attempt to provide that much headroom but the channel
+should still check if there is sufficient headroom and copy the skbuff
+if there isn't.
+
+On the input side, channels should ideally provide at least 2 bytes of
+headroom in the skbuffs presented to ppp_input().  The generic PPP
+code does not require this but will be more efficient if this is done.
+
+
+Buffering and flow control
+--------------------------
+
+The generic PPP layer has been designed to minimize the amount of data
+that it buffers in the transmit direction.  It maintains a queue of
+transmit packets for the PPP unit (network interface device) plus a
+queue of transmit packets for each attached channel.  Normally the
+transmit queue for the unit will contain at most one packet; the
+exceptions are when pppd sends packets by writing to /dev/ppp, and
+when the core networking code calls the generic layer's start_xmit()
+function with the queue stopped, i.e. when the generic layer has
+called netif_stop_queue(), which only happens on a transmit timeout.
+The start_xmit function always accepts and queues the packet which it
+is asked to transmit.
+
+Transmit packets are dequeued from the PPP unit transmit queue and
+then subjected to TCP/IP header compression and packet compression
+(Deflate or BSD-Compress compression), as appropriate.  After this
+point the packets can no longer be reordered, as the decompression
+algorithms rely on receiving compressed packets in the same order that
+they were generated.
+
+If multilink is not in use, this packet is then passed to the attached
+channel's start_xmit() function.  If the channel refuses to take
+the packet, the generic layer saves it for later transmission.  The
+generic layer will call the channel's start_xmit() function again
+when the channel calls  ppp_output_wakeup() or when the core
+networking code calls the generic layer's start_xmit() function
+again.  The generic layer contains no timeout and retransmission
+logic; it relies on the core networking code for that.
+
+If multilink is in use, the generic layer divides the packet into one
+or more fragments and puts a multilink header on each fragment.  It
+decides how many fragments to use based on the length of the packet
+and the number of channels which are potentially able to accept a
+fragment at the moment.  A channel is potentially able to accept a
+fragment if it doesn't have any fragments currently queued up for it
+to transmit.  The channel may still refuse a fragment; in this case
+the fragment is queued up for the channel to transmit later.  This
+scheme has the effect that more fragments are given to higher-
+bandwidth channels.  It also means that under light load, the generic
+layer will tend to fragment large packets across all the channels,
+thus reducing latency, while under heavy load, packets will tend to be
+transmitted as single fragments, thus reducing the overhead of
+fragmentation.
+
+
+SMP safety
+----------
+
+The PPP generic layer has been designed to be SMP-safe.  Locks are
+used around accesses to the internal data structures where necessary
+to ensure their integrity.  As part of this, the generic layer
+requires that the channels adhere to certain requirements and in turn
+provides certain guarantees to the channels.  Essentially the channels
+are required to provide the appropriate locking on the ppp_channel
+structures that form the basis of the communication between the
+channel and the generic layer.  This is because the channel provides
+the storage for the ppp_channel structure, and so the channel is
+required to provide the guarantee that this storage exists and is
+valid at the appropriate times.
+
+The generic layer requires these guarantees from the channel:
+
+* The ppp_channel object must exist from the time that
+  ppp_register_channel() is called until after the call to
+  ppp_unregister_channel() returns.
+
+* No thread may be in a call to any of ppp_input(), ppp_input_error(),
+  ppp_output_wakeup(), ppp_channel_index() or ppp_unit_number() for a
+  channel at the time that ppp_unregister_channel() is called for that
+  channel.
+
+* ppp_register_channel() and ppp_unregister_channel() must be called
+  from process context, not interrupt or softirq/BH context.
+
+* The remaining generic layer functions may be called at softirq/BH
+  level but must not be called from a hardware interrupt handler.
+
+* The generic layer may call the channel start_xmit() function at
+  softirq/BH level but will not call it at interrupt level.  Thus the
+  start_xmit() function may not block.
+
+* The generic layer will only call the channel ioctl() function in
+  process context.
+
+The generic layer provides these guarantees to the channels:
+
+* The generic layer will not call the start_xmit() function for a
+  channel while any thread is already executing in that function for
+  that channel.
+
+* The generic layer will not call the ioctl() function for a channel
+  while any thread is already executing in that function for that
+  channel.
+
+* By the time a call to ppp_unregister_channel() returns, no thread
+  will be executing in a call from the generic layer to that channel's
+  start_xmit() or ioctl() function, and the generic layer will not
+  call either of those functions subsequently.
+
+
+Interface to pppd
+-----------------
+
+The PPP generic layer exports a character device interface called
+/dev/ppp.  This is used by pppd to control PPP interface units and
+channels.  Although there is only one /dev/ppp, each open instance of
+/dev/ppp acts independently and can be attached either to a PPP unit
+or a PPP channel.  This is achieved using the file->private_data field
+to point to a separate object for each open instance of /dev/ppp.  In
+this way an effect similar to Solaris' clone open is obtained,
+allowing us to control an arbitrary number of PPP interfaces and
+channels without having to fill up /dev with hundreds of device names.
+
+When /dev/ppp is opened, a new instance is created which is initially
+unattached.  Using an ioctl call, it can then be attached to an
+existing unit, attached to a newly-created unit, or attached to an
+existing channel.  An instance attached to a unit can be used to send
+and receive PPP control frames, using the read() and write() system
+calls, along with poll() if necessary.  Similarly, an instance
+attached to a channel can be used to send and receive PPP frames on
+that channel.
+
+In multilink terms, the unit represents the bundle, while the channels
+represent the individual physical links.  Thus, a PPP frame sent by a
+write to the unit (i.e., to an instance of /dev/ppp attached to the
+unit) will be subject to bundle-level compression and to fragmentation
+across the individual links (if multilink is in use).  In contrast, a
+PPP frame sent by a write to the channel will be sent as-is on that
+channel, without any multilink header.
+
+A channel is not initially attached to any unit.  In this state it can
+be used for PPP negotiation but not for the transfer of data packets.
+It can then be connected to a PPP unit with an ioctl call, which
+makes it available to send and receive data packets for that unit.
+
+The ioctl calls which are available on an instance of /dev/ppp depend
+on whether it is unattached, attached to a PPP interface, or attached
+to a PPP channel.  The ioctl calls which are available on an
+unattached instance are:
+
+* PPPIOCNEWUNIT creates a new PPP interface and makes this /dev/ppp
+  instance the "owner" of the interface.  The argument should point to
+  an int which is the desired unit number if >= 0, or -1 to assign the
+  lowest unused unit number.  Being the owner of the interface means
+  that the interface will be shut down if this instance of /dev/ppp is
+  closed.
+
+* PPPIOCATTACH attaches this instance to an existing PPP interface.
+  The argument should point to an int containing the unit number.
+  This does not make this instance the owner of the PPP interface.
+
+* PPPIOCATTCHAN attaches this instance to an existing PPP channel.
+  The argument should point to an int containing the channel number.
+
+The ioctl calls available on an instance of /dev/ppp attached to a
+channel are:
+
+* PPPIOCDETACH detaches the instance from the channel.  This ioctl is
+  deprecated since the same effect can be achieved by closing the
+  instance.  In order to prevent possible races this ioctl will fail
+  with an EINVAL error if more than one file descriptor refers to this
+  instance (i.e. as a result of dup(), dup2() or fork()).
+
+* PPPIOCCONNECT connects this channel to a PPP interface.  The
+  argument should point to an int containing the interface unit
+  number.  It will return an EINVAL error if the channel is already
+  connected to an interface, or ENXIO if the requested interface does
+  not exist.
+
+* PPPIOCDISCONN disconnects this channel from the PPP interface that
+  it is connected to.  It will return an EINVAL error if the channel
+  is not connected to an interface.
+
+* All other ioctl commands are passed to the channel ioctl() function.
+
+The ioctl calls that are available on an instance that is attached to
+an interface unit are:
+
+* PPPIOCSMRU sets the MRU (maximum receive unit) for the interface.
+  The argument should point to an int containing the new MRU value.
+
+* PPPIOCSFLAGS sets flags which control the operation of the
+  interface.  The argument should be a pointer to an int containing
+  the new flags value.  The bits in the flags value that can be set
+  are:
+	SC_COMP_TCP		enable transmit TCP header compression
+	SC_NO_TCP_CCID		disable connection-id compression for
+				TCP header compression
+	SC_REJ_COMP_TCP		disable receive TCP header decompression
+	SC_CCP_OPEN		Compression Control Protocol (CCP) is
+				open, so inspect CCP packets
+	SC_CCP_UP		CCP is up, may (de)compress packets
+	SC_LOOP_TRAFFIC		send IP traffic to pppd
+	SC_MULTILINK		enable PPP multilink fragmentation on
+				transmitted packets
+	SC_MP_SHORTSEQ		expect short multilink sequence
+				numbers on received multilink fragments
+	SC_MP_XSHORTSEQ		transmit short multilink sequence nos.
+
+  The values of these flags are defined in <linux/if_ppp.h>.  Note
+  that the values of the SC_MULTILINK, SC_MP_SHORTSEQ and
+  SC_MP_XSHORTSEQ bits are ignored if the CONFIG_PPP_MULTILINK option
+  is not selected.
+
+* PPPIOCGFLAGS returns the value of the status/control flags for the
+  interface unit.  The argument should point to an int where the ioctl
+  will store the flags value.  As well as the values listed above for
+  PPPIOCSFLAGS, the following bits may be set in the returned value:
+	SC_COMP_RUN		CCP compressor is running
+	SC_DECOMP_RUN		CCP decompressor is running
+	SC_DC_ERROR		CCP decompressor detected non-fatal error
+	SC_DC_FERROR		CCP decompressor detected fatal error
+
+* PPPIOCSCOMPRESS sets the parameters for packet compression or
+  decompression.  The argument should point to a ppp_option_data
+  structure (defined in <linux/if_ppp.h>), which contains a
+  pointer/length pair which should describe a block of memory
+  containing a CCP option specifying a compression method and its
+  parameters.  The ppp_option_data struct also contains a `transmit'
+  field.  If this is 0, the ioctl will affect the receive path,
+  otherwise the transmit path.
+
+* PPPIOCGUNIT returns, in the int pointed to by the argument, the unit
+  number of this interface unit.
+
+* PPPIOCSDEBUG sets the debug flags for the interface to the value in
+  the int pointed to by the argument.  Only the least significant bit
+  is used; if this is 1 the generic layer will print some debug
+  messages during its operation.  This is only intended for debugging
+  the generic PPP layer code; it is generally not helpful for working
+  out why a PPP connection is failing.
+
+* PPPIOCGDEBUG returns the debug flags for the interface in the int
+  pointed to by the argument.
+
+* PPPIOCGIDLE returns the time, in seconds, since the last data
+  packets were sent and received.  The argument should point to a
+  ppp_idle structure (defined in <linux/ppp_defs.h>).  If the
+  CONFIG_PPP_FILTER option is enabled, the set of packets which reset
+  the transmit and receive idle timers is restricted to those which
+  pass the `active' packet filter.
+
+* PPPIOCSMAXCID sets the maximum connection-ID parameter (and thus the
+  number of connection slots) for the TCP header compressor and
+  decompressor.  The lower 16 bits of the int pointed to by the
+  argument specify the maximum connection-ID for the compressor.  If
+  the upper 16 bits of that int are non-zero, they specify the maximum
+  connection-ID for the decompressor, otherwise the decompressor's
+  maximum connection-ID is set to 15.
+
+* PPPIOCSNPMODE sets the network-protocol mode for a given network
+  protocol.  The argument should point to an npioctl struct (defined
+  in <linux/if_ppp.h>).  The `protocol' field gives the PPP protocol
+  number for the protocol to be affected, and the `mode' field
+  specifies what to do with packets for that protocol:
+
+	NPMODE_PASS	normal operation, transmit and receive packets
+	NPMODE_DROP	silently drop packets for this protocol
+	NPMODE_ERROR	drop packets and return an error on transmit
+	NPMODE_QUEUE	queue up packets for transmit, drop received
+			packets
+
+  At present NPMODE_ERROR and NPMODE_QUEUE have the same effect as
+  NPMODE_DROP.
+
+* PPPIOCGNPMODE returns the network-protocol mode for a given
+  protocol.  The argument should point to an npioctl struct with the
+  `protocol' field set to the PPP protocol number for the protocol of
+  interest.  On return the `mode' field will be set to the network-
+  protocol mode for that protocol.
+
+* PPPIOCSPASS and PPPIOCSACTIVE set the `pass' and `active' packet
+  filters.  These ioctls are only available if the CONFIG_PPP_FILTER
+  option is selected.  The argument should point to a sock_fprog
+  structure (defined in <linux/filter.h>) containing the compiled BPF
+  instructions for the filter.  Packets are dropped if they fail the
+  `pass' filter; otherwise, if they fail the `active' filter they are
+  passed but they do not reset the transmit or receive idle timer.
+
+* PPPIOCSMRRU enables or disables multilink processing for received
+  packets and sets the multilink MRRU (maximum reconstructed receive
+  unit).  The argument should point to an int containing the new MRRU
+  value.  If the MRRU value is 0, processing of received multilink
+  fragments is disabled.  This ioctl is only available if the
+  CONFIG_PPP_MULTILINK option is selected.
+
+Last modified: 7-feb-2002
diff -Nru a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt
--- a/Documentation/networking/vortex.txt	Sun Apr 14 12:16:56 2002
+++ b/Documentation/networking/vortex.txt	Sun Apr 14 12:16:56 2002
@@ -117,6 +117,12 @@
   will force full-duplex 100base-TX, rather than allowing the usual
   autonegotiation.
 
+global_options=N
+
+  Sets the `options' parameter for all 3c59x NICs in the machine. 
+  Entries in the `options' array above will override any setting of
+  this.
+
 full_duplex=N1,N2,N3...
 
   Similar to bit 9 of 'options'.  Forces the corresponding card into
@@ -126,6 +132,11 @@
   In fact, please don't use this at all! You're better off getting
   autonegotiation working properly.
 
+global_full_duplex=N1
+
+  Sets full duplex mode for all 3c59x NICs in the machine.  Entries
+  in the `full_duplex' array above will override any setting of this.
+
 flow_ctrl=N1,N2,N3...
 
   Use 802.3x MAC-layer flow control.  The 3com cards only support the
@@ -211,6 +222,12 @@
   Becker's `ether-wake' application may be used to wake suspended
   machines.
 
+  Also enables the NIC's power management support.
+
+global_enable_wol=N
+
+  Sets enable_wol mode for all 3c59x NICs in the machine.  Entries in
+  the `enable_wol' array above will override any setting of this.
 
 Media selection
 ---------------
diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt
--- a/Documentation/sonypi.txt	Sun Apr 14 12:16:54 2002
+++ b/Documentation/sonypi.txt	Sun Apr 14 12:16:54 2002
@@ -25,7 +25,8 @@
 can be downloaded at: <http://www.alcove-labs.org/en/software/sonypi/>
 
 This driver supports also some ioctl commands for setting the LCD screen
-brightness (some more commands may be added in the future).
+brightness and querying the batteries charge information (some more 
+commands may be added in the future).
 
 This driver can also be used to set the camera controls on Picturebook series
 (brightness, contrast etc), and is used by the video4linux driver for the 
diff -Nru a/Documentation/sound/oss/AudioExcelDSP16 b/Documentation/sound/oss/AudioExcelDSP16
--- a/Documentation/sound/oss/AudioExcelDSP16	Sun Apr 14 12:16:54 2002
+++ b/Documentation/sound/oss/AudioExcelDSP16	Sun Apr 14 12:16:54 2002
@@ -2,7 +2,7 @@
 ------
 
 Informations about Audio Excel DSP 16 driver can be found in the source
-file lowlevel/aedsp16.c
+file aedsp16.c
 Please, read the head of the source before using it. It contain useful
 informations.
 
diff -Nru a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt
--- a/Documentation/usb/hiddev.txt	Sun Apr 14 12:16:57 2002
+++ b/Documentation/usb/hiddev.txt	Sun Apr 14 12:16:57 2002
@@ -18,10 +18,10 @@
 The data flow for a HID event produced by a device is something like
 the following :
 
- usb.c ---> hid.c  ----> input.c ----> [keyboard/mouse/joystick/event]
-                    |
-                    |
-                    --> hiddev.c ----> POWER / MONITOR CONTROL 
+ usb.c ---> hid-core.c  ----> input.c ----> [keyboard/mouse/joystick/event]
+                         |
+                         |
+                          --> hiddev.c ----> POWER / MONITOR CONTROL 
 
 In addition, other subsystems (apart from USB) can potentially feed
 events into the input subsystem, but these have no effect on the hid
@@ -63,12 +63,18 @@
 
 The hiddev API uses a read() interface, and a set of ioctl() calls.
 
+HID devices exchange data with the host computer using data
+bundles called "reports".  Each report is divided into "fields",
+each of which can have one or more "usages".  In the hid-core,
+each one of these usages has a single signed 32 bit value.
 
 read():
-This is the event interface. When the HID device performs an
-interrupt transfer, indicating a change of state, data will be made
-available at the associated hiddev device with the content of a struct
-hiddev_event: 
+This is the event interface.  When the HID device's state changes,
+it performs an interrupt transfer containing a report which contains
+the changed value.  The hid-core.c module parses the report, and
+returns to hiddev.c the individual usages that have changed within
+the report.  In its basic mode, the hiddev will make these individual
+usage changes available to the reader using a struct hiddev_event:
 
        struct hiddev_event {
            unsigned hid;
@@ -78,7 +84,10 @@
 containing the HID usage identifier for the status that changed, and
 the value that it was changed to. Note that the structure is defined
 within <linux/hiddev.h>, along with some other useful #defines and
-structures. 
+structures.  The HID usage identifier is a composite of the HID usage
+page shifted to the 16 high order bits ORed with the usage code.  The
+behavior of the read() function can be modified using the HIDIOCSFLAG
+ioctl() described below.
 
 
 ioctl(): 
@@ -108,7 +117,9 @@
 Instructs the kernel to retrieve all input and feature report values
 from the device. At this point, all the usage structures will contain
 current values for the device, and will maintain it as the device
-changes.
+changes.  Note that the use of this ioctl is unnecessary in general,
+since later kernels automatically initialize the reports from the
+device at attach time.
 
 HIDIOCGNAME - string (variable length)
 Gets the device name
@@ -116,12 +127,12 @@
 HIDIOCGREPORT - struct hiddev_report_info (write)
 Instructs the kernel to get a feature or input report from the device,
 in order to selectively update the usage structures (in contrast to
-INITREPORT). 
+INITREPORT).
 
 HIDIOCSREPORT - struct hiddev_report_info (write)
 Instructs the kernel to send a report to the device. This report can
 be filled in by the user through HIDIOCSUSAGE calls (below) to fill in
-individual usage values in the report beforesending the report in full
+individual usage values in the report before sending the report in full
 to the device. 
 
 HIDIOCGREPORTINFO - struct hiddev_report_info (read/write)
@@ -157,6 +168,25 @@
 usage if it is found. 
 
 HIDIOCSUSAGE - struct hiddev_usage_ref (write)
-Sets the value of a usage in an output report.
-
-
+Sets the value of a usage in an output report.  The user fills in
+the hiddev_usage_ref structure as above, but additionally fills in
+the value field.
+
+HIDIOCGFLAG - int (read)
+HIDIOCSFLAG - int (write)
+These operations respectively inspect and replace the mode flags
+that influence the read() call above.  The flags are as follows:
+
+    HIDDEV_FLAG_UREF - read() calls will now return 
+        struct hiddev_usage_ref instead of struct hiddev_event.
+        This is a larger structure, but in situations where the
+        device has more than one usage in its reports with the
+        same usage code, this mode serves to resolve such
+        ambiguity.
+
+    HIDDEV_FLAG_REPORT - This flag can only be used in conjunction
+        with HIDDEV_FLAG_UREF.  With this flag set, when the device
+        sends a report, a struct hiddev_usage_ref will be returned
+        to read() filled in with the report_type and report_id, but 
+        with field_index set to FIELD_INDEX_NONE.  This serves as
+        additional notification when the device has sent a report.
diff -Nru a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
--- a/Documentation/usb/proc_usb_info.txt	Sun Apr 14 12:16:55 2002
+++ b/Documentation/usb/proc_usb_info.txt	Sun Apr 14 12:16:55 2002
@@ -1,32 +1,99 @@
 /proc/bus/usb filesystem output
 ===============================
-(version 2000.08.15)
+(version 2002.03.19)
 
 
-The /proc filesystem for USB devices generates
-/proc/bus/usb/drivers and /proc/bus/usb/devices.
+The /proc filesystem for USB devices provides /proc/bus/usb/drivers
+and /proc/bus/usb/devices, as well as /proc/bus/usb/BBB/DDD files.
 
-/proc/bus/usb/drivers lists the registered drivers,
-one per line, with each driver's USB minor dev node
-number range if applicable.
 
-**NOTE**: If /proc/bus/usb appears empty, you need
-          to mount the filesystem, issue the command (as root):
+**NOTE**: If /proc/bus/usb appears empty, and a host controller
+	  driver has been linked, then you need to mount the
+	  filesystem.  Issue the command (as root):
 
-      mount -t usbdevfs none /proc/bus/usb
+      mount -t usbfs none /proc/bus/usb
 
 	  An alternative and more permanent method would be to add
 
-      none  /proc/bus/usb  usbdevfs  defaults  0  0
+      none  /proc/bus/usb  usbfs  defaults  0  0
 
-	  to /etc/fstab.  This will mount usbdevfs at each reboot.
+	  to /etc/fstab.  This will mount usbfs at each reboot.
 	  You can then issue `cat /proc/bus/usb/devices` to extract
-	  USB device information.
+	  USB device information, and user mode drivers can use usbfs 
+	  to interact with USB devices.
 
-For more information on mounting the usbdevfs file system, see the
+	  There are a number of mount options supported by usbfs.
+	  Consult the source code (linux/drivers/usb/inode.c) for
+	  information about those options.
+
+**NOTE**: The filesystem has been renamed from "usbdevfs" to
+	  "usbfs", to reduce confusion with "devfs".  You may
+	  still see references to the older "usbdevfs" name.
+
+For more information on mounting the usbfs file system, see the
 "USB Device Filesystem" section of the USB Guide. The latest copy 
 of the USB Guide can be found at http://www.linux-usb.org/
 
+
+THE /proc/bus/usb/BBB/DDD FILES:
+--------------------------------
+Each connected USB device has one file.  The BBB indicates the bus
+number.  The DDD indicates the device address on that bus.  Both
+of these numbers are assigned sequentially, and can be reused, so
+you can't rely on them for stable access to devices.  For example,
+it's relatively common for devices to re-enumerate while they are
+still connected (perhaps someone jostled their power supply, hub,
+or USB cable), so a device might be 002/027 when you first connect
+it and 002/048 sometime later.
+
+These files can be read as binary data.  The binary data consists
+of first the device descriptor, then the descriptors for each
+configuration of the device.  That information is also shown in
+text form by the /proc/bus/usb/devices file, described later.
+
+These files may also be used to write user-level drivers for the USB
+devices.  You would open the /proc/bus/usb/BBB/DDD file read/write,
+read its descriptors to make sure it's the device you expect, and then
+bind to an interface (or perhaps several) using an ioctl call.  You
+would issue more ioctls to the device to communicate to it using
+control, bulk, or other kinds of USB transfers.  The IOCTLs are
+listed in the <linux/usbdevice_fs.h> file, and at this writing the
+source code (linux/drivers/usb/devio.c) is the primary reference
+for how to access devices through those files.
+
+Note that since by default these BBB/DDD files are writable only by
+root, only root can write such user mode drivers.  You can selectively
+grant read/write permissions to other users by using "chmod".  Also,
+usbfs mount options such as "devmode=0666" may be helpful.
+
+
+
+THE /proc/bus/usb/drivers FILE:
+-------------------------------
+Each of the USB device drivers linked into your kernel (statically,
+or dynamically using "modprobe") is listed in the "drivers" file.
+Here's an example from one system:
+
+         usbdevfs
+         hub
+  0- 15: usblp
+         usbnet
+         serial
+         usb-storage
+         pegasus
+
+If you see this file, "usbdevfs" and "hub" will always be listed,
+since those are part of the "usbcore" framework.
+
+Drivers that use the USB major number (180) to provide character devices
+will include a range of minor numbers, as shown above for the "usblp"
+(actually "printer.o") module.  USB device drivers can of course use any
+major number, but it's easy to use the USB range since there's explicit
+support for subdividing it in the USB device driver framework.
+
+
+THE /proc/bus/usb/devices FILE:
+-------------------------------
 In /proc/bus/usb/devices, each device's output has multiple
 lines of ASCII output.
 I made it ASCII instead of binary on purpose, so that someone
@@ -34,8 +101,6 @@
 auxiliary program.  However, with an auxiliary program, the numbers
 in the first 4 columns of each "T:" line (topology info:
 Lev, Prnt, Port, Cnt) can be used to build a USB topology diagram.
-(I think.  I haven't proved this, but I have tested it with 3
-different topo/connections and it looked possible.)
 
 Each line is tagged with a one-character ID for that line:
 
@@ -73,14 +138,30 @@
 |   |__Bus number
 |__Topology info tag
 
+    Speed may be:
+    	1.5	Mbit/s for low speed USB
+	12	Mbit/s for full speed USB
+	480	Mbit/s for high speed USB (added for USB 2.0)
+
 
 Bandwidth info:
 B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
-|   |                       |         |__Number if isochronous requests
+|   |                       |         |__Number of isochronous requests
 |   |                       |__Number of interrupt requests
 |   |__Total Bandwidth allocated to this bus
 |__Bandwidth info tag
 
+    Bandwidth allocation is an approximation of how much of one frame
+    (millisecond) is in use.  It reflects only periodic transfers, which
+    are the only transfers that reserve bandwidth.  Control and bulk
+    transfers use all other bandwidth, including reserved bandwidth that
+    is not used for transfers (such as for short packets).
+    
+    The percentage is how much of the "reserved" bandwidth is scheduled by
+    those transfers.  For a low or full speed bus (loosely, "USB 1.1"),
+    90% of the bus bandwidth is reserved.  For a high speed bus (loosely,
+    "USB 2.0") 80% is reserved.
+
 
 Device descriptor info & Product ID info:
 
@@ -109,37 +190,55 @@
 
 S:  Manufacturer=ssss
 |   |__Manufacturer of this device as read from the device.
+|      For USB host controller drivers (virtual root hubs) this may
+|      be omitted, or (for newer drivers) will identify the kernel
+|      version and the driver which provides this hub emulation.
 |__String info tag
 
 S:  Product=ssss
-|   |__Product description of this device as read from the device,
-|      except that it is a generated string for USB host controllers
-|      (virtual root hubs), in the form "USB *HCI Root Hub".
+|   |__Product description of this device as read from the device.
+|      For older USB host controller drivers (virtual root hubs) this
+|      indicates the driver; for newer ones, it's a product (and vendor)
+|      description that often comes from the kernel's PCI ID database.
 |__String info tag
 
 S:  SerialNumber=ssss
-|   |__Serial Number of this device as read from the device,
-|      except that it is a generated string for USB host controllers
-|      (virtual root hubs), and represents the host controller's
-|      unique identification in the system (currently I/O or
-|      memory-mapped base address).
+|   |__Serial Number of this device as read from the device.
+|      For USB host controller drivers (virtual root hubs) this is
+|      some unique ID, normally a bus ID (address or slot name) that
+|      can't be shared with any other device.
 |__String info tag
 
 
+
 Configuration descriptor info:
 
-C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
-|   |       |       |      |__MaxPower in mA
-|   |       |       |__Attributes
-|   |       |__ConfiguratioNumber
-|   |__NumberOfInterfaces
+C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
+| | |       |       |      |__MaxPower in mA
+| | |       |       |__Attributes
+| | |       |__ConfiguratioNumber
+| | |__NumberOfInterfaces
+| |__ "*" indicates the active configuration (others are " ")
 |__Config info tag
+    
+    USB devices may have multiple configurations, each of which act
+    rather differently.  For example, a bus-powered configuration
+    might be much less capable than one that is self-powered.  Only
+    one device configuration can be active at a time; most devices
+    have only one configuration.
+
+    Each configuration consists of one or more interfaces.  Each
+    interface serves a distinct "function", which is typically bound
+    to a different USB device driver.  One common example is a USB
+    speaker with an audio interface for playback, and a HID interface
+    for use with software volume control.
 
 
 Interface descriptor info (can be multiple per Config):
 
 I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
 |   |      |      |       |             |      |       |__Driver name
+|   |      |      |       |             |      |          or "(none)"
 |   |      |      |       |             |      |__InterfaceProtocol
 |   |      |      |       |             |__InterfaceSubClass
 |   |      |      |       |__InterfaceClass
@@ -148,16 +247,38 @@
 |   |__InterfaceNumber
 |__Interface info tag
 
+    A given interface may have one or more "alternate" settings.
+    For example, default settings may not use more than a small
+    amount of periodic bandwidth.  To use significant fractions
+    of bus bandwidth, drivers must select a non-default altsetting.
+    
+    Only one setting for an interface may be active at a time, and
+    only one driver may bind to an interface at a time.  Most devices
+    have only one alternate setting per interface.
+
 
 Endpoint descriptor info (can be multiple per Interface):
 
-E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms
-E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms
-|   |        |            |         |__Interval
+E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddss
+|   |        |            |         |__Interval (max) between transfers
 |   |        |            |__EndpointMaxPacketSize
 |   |        |__Attributes(EndpointType)
 |   |__EndpointAddress(I=In,O=Out)
 |__Endpoint info tag
+
+    The interval is nonzero for all periodic (interrupt or isochronous)
+    endpoints.  For high speed endpoints the transfer interval may be
+    measured in microseconds rather than milliseconds.
+
+    For high speed periodic endpoints, the "MaxPacketSize" reflects
+    the per-microframe data transfer size.  For "high bandwidth"
+    endpoints, that can reflect two or three packets (for up to
+    3KBytes every 125 usec) per endpoint.
+
+    With the Linux-USB stack, periodic bandwidth reservations use the
+    transfer intervals and sizes provided by URBs, which can be less
+    than those found in endpoint descriptor.
+
 
 =======================================================================
 
diff -Nru a/Documentation/usb/se401.txt b/Documentation/usb/se401.txt
--- a/Documentation/usb/se401.txt	Sun Apr 14 12:16:55 2002
+++ b/Documentation/usb/se401.txt	Sun Apr 14 12:16:55 2002
@@ -40,7 +40,7 @@
 KNOWN PROBLEMS:
 
 The driver works fine with the usb-ohci and uhci host controller drivers,
-the default settings also work with usb-uhci. But sending more then one bulk
+the default settings also work with usb-uhci. But sending more than one bulk
 transfer at a time with usb-uhci doesn't work yet.
 Users of usb-ohci and uhci can safely enlarge SE401_NUMSBUF in se401.h in
 order to increase the throughput (and thus framerate).
diff -Nru a/Documentation/usb/silverlink.txt b/Documentation/usb/silverlink.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/usb/silverlink.txt	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,76 @@
+-------------------------------------------------------------------------
+Readme for Linux device driver for the Texas Instruments SilverLink cable
+-------------------------------------------------------------------------
+
+Author: Romain Liévin & Julien Blache
+Homepage: http://lpg.ticalc.org/prj_usb
+
+INTRODUCTION:
+
+This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable 
+designed by TI for connecting their TI8x/9x calculators to a computer 
+(PC or Mac usually).
+
+If you need more information, please visit the 'SilverLink drivers' homepage 
+at the above URL.
+
+WHAT YOU NEED:
+
+A TI calculator of course and a program capable to communicate with your 
+calculator.
+TiLP will work for sure (since I am his developer !). yal92 may be able to use
+it by changing tidev for tiglusb (may require some hacking...).
+
+HOW TO USE IT:
+
+You must have first compiled USB support, support for your specific USB host
+controller (UHCI or OHCI).
+
+Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX):
+
+       insmod usb/usbcore.o
+       insmod usb/usb-uhci.o  <OR>  insmod usb/ohci-hcd.o
+       insmod tiglusb.o
+
+If it is not already there (it usually is), create the device:
+
+       mknod /dev/tiglusb0 c 115 16
+
+You will have to set permissions on this device to allow you to read/write
+from it:
+
+       chmod 666 /dev/tiglusb0
+       
+Now you are ready to run a linking program such as TiLP. Be sure to configure 
+it properly (RTFM).
+       
+MODULE PARAMETERS:
+
+  You can set these with:  insmod tiglusb NAME=VALUE
+  There is currently no way to set these on a per-cable basis.
+
+  NAME: timeout
+  TYPE: integer
+  DEFAULT: 15
+  DESC: Timeout value in tenth of seconds. If no data is available once this 
+       time has expired then the driver will return with a timeout error.
+
+QUIRKS:
+
+The following problem seems to be specific to the link cable since it appears 
+on all platforms (Linux, Windows, Mac OS-X). 
+
+In some very particular cases, the driver returns with success but
+without any data. The application should retry a read operation at least once.
+
+HOW TO CONTACT US:
+
+You can email me at roms@lpg.ticalc.org. Please prefix the subject line
+with "TIGLUSB: " so that I am certain to notice your message.
+You can also mail JB at jb@jblache.org: he has written the first release of 
+this driver but he better knows the Mac OS-X driver.
+
+CREDITS:
+
+The code is based on dabusb.c, printer.c and scanner.c !
+The driver has been developed independantly of Texas Instruments.
diff -Nru a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
--- a/Documentation/video4linux/Zoran	Sun Apr 14 12:16:59 2002
+++ b/Documentation/video4linux/Zoran	Sun Apr 14 12:16:59 2002
@@ -160,9 +160,9 @@
   set aside the necessary memory during boot time. There seem to be
   several versions of this patch against various kernel versions
   floating around in the net, you may obtain one e.g. from:
-  http://www.polyware.nl/~middelin/patch/bigphysarea-2.2.1.tar.gz You
-  also have to compile your driver AFTER installing that patch in order
-  to get it working
+  http://www.polyware.nl/~middelin/hob-v4l.html#bigphysarea
+  You also have to compile your driver AFTER installing that patch in
+  order to get it working
 
   or
 
diff -Nru a/Documentation/video4linux/bttv/README.freeze b/Documentation/video4linux/bttv/README.freeze
--- a/Documentation/video4linux/bttv/README.freeze	Sun Apr 14 12:16:55 2002
+++ b/Documentation/video4linux/bttv/README.freeze	Sun Apr 14 12:16:55 2002
@@ -46,10 +46,6 @@
 the PCI bus. The bt848/878 chips have a few workarounds for known
 incompatibilities, see README.quirks.
 
-Some folks report that increasing the pci latency helps too,
-althrought I'm not sure whenever this really fixes the problems or
-only makes it less likely to happen.
-
 Some mainboard have problems to deal correctly with multiple devices
 doing DMA at the same time.  bttv + ide seems to cause this sometimes,
 if this is the case you likely see freezes only with video and hard disk
diff -Nru a/Documentation/video4linux/w9966.txt b/Documentation/video4linux/w9966.txt
--- a/Documentation/video4linux/w9966.txt	Sun Apr 14 12:16:58 2002
+++ b/Documentation/video4linux/w9966.txt	Sun Apr 14 12:16:58 2002
@@ -1,37 +1,33 @@
+W9966 Camera driver, written by Jakob Kemi (jakob.kemi@telia.com)
 
-W9966 Camera driver, written by Jakob Kemi (jakob.kemi@post.utfors.se)
+After a lot of work in softice & wdasm, reading .pdf-files and tiresome
+trial-and-error work I've finally got everything to work. I needed vision for a
+robotics project so I borrowed this camera from a friend and started hacking.
+Anyway I've converted my original code from the AVR 8bit RISC C/ASM code into
+a working Linux driver.
 
-Ok, after a lot of work in softice, wdasm, reading pdf-files
-and trial-and-error work I've finally got everything to work.
-Since I needed some vision for a robotics project I borrowed
-this camera from a friend and started hacking. Anyway I've
-converted my original code from the AVR 8bit RISC C/asm
-into a working linux driver. I would really appreciate _any_
-kind of feedback regarding this driver.
-
-To get it working quickly configure your kernel
-to support parport, ieee1284, video4linux, experimental drivers
-and w9966
+To get it working simply configure your kernel to support
+parport, ieee1284, video4linux and w9966
 
-If w9966 is statically linked it will perform aggressive probing
-for the camera. If built as a module you'll have more configuration options.
+If w9966 is statically linked it will always perform aggressive probing for
+the camera. If built as a module you'll have more configuration options.
 
 Options:
-modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
- 
+ modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
 voila!
 
 you can also type 'modinfo -p w9966.o' for option usage
 (or checkout w9966.c)
 
-I've only tested it with custom built testprograms
-(http://hem.fyristorg.com/mogul/w9966.html) and with gqcam.
-(you'll need to tweak the code to qcam a bit to make it work,
-dimensions and such)
+The only thing to keep in mind is that the image format is in Y-U-Y-V format
+where every two pixels take 4 bytes. In SDL (www.libsdl.org) this format
+is called VIDEO_PALETTE_YUV422 (16 bpp).
+
+A minimal test application (with source) is available from:
+  http://hem.fyristorg.com/mogul/w9966.html
 
 The slow framerate is due to missing DMA ECP read support in the 
 parport drivers. I might add working EPP support later.
 
 Good luck!
-
-    /Jakob
+    /Jakob Kemi
diff -Nru a/Documentation/watchdog-api.txt b/Documentation/watchdog-api.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/watchdog-api.txt	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,390 @@
+The Linux Watchdog driver API.
+
+Copyright 2002 Christer Weingel <wingel@nano-system.com>
+
+Some parts of this document are copied verbatim from the sbc60xxwdt
+driver which is (c) Copyright 2000 Jakob Oestergaard <jakob@ostenfeld.dk>
+
+This document describes the state of the Linux 2.4.18 kernel.
+
+Introduction:
+
+A Watchdog Timer (WDT) is a hardware circuit that can reset the
+computer system in case of a software fault.  You probably knew that
+already.
+
+Usually a userspace daemon will notify the kernel watchdog driver via the
+/dev/watchdog special device file that userspace is still alive, at
+regular intervals.  When such a notification occurs, the driver will
+usually tell the hardware watchdog that everything is in order, and
+that the watchdog should wait for yet another little while to reset
+the system.  If userspace fails (RAM error, kernel bug, whatever), the
+notifications cease to occur, and the hardware watchdog will reset the
+system (causing a reboot) after the timeout occurs.
+
+The Linux watchdog API is a rather AD hoc construction and different
+drivers implement different, and sometimes incompatible, parts of it.
+This file is an attempt to document the existing usage and allow
+future driver writers to use it as a reference.
+
+The simplest API:
+
+All drivers support the basic mode of operation, where the watchdog
+activates as soon as /dev/watchdog is opened and will reboot unless
+the watchdog is pinged within a certain time, this time is called the
+timeout or margin.  The simplest way to ping the watchdog is to write
+some data to the device.  So a very simple watchdog daemon would look
+like this:
+
+int main(int argc, const char *argv[]) {
+	int fd=open("/dev/watchdog",O_WRONLY);
+	if (fd==-1) {
+		perror("watchdog");
+		exit(1);
+	}
+	while(1) {
+		write(fd, "\0", 1);
+		sleep(10);
+	}
+}
+
+A more advanced driver could for example check that a HTTP server is
+still responding before doing the write call to ping the watchdog.
+
+When the device is closed, the watchdog is disabled.  This is not
+always such a good idea, since if there is a bug in the watchdog
+daemon and it crashes the system will not reboot.  Because of this,
+some of the drivers support the configuration option "Disable watchdog
+shutdown on close", CONFIG_WATCHDOG_NOWAYOUT.  If it is set to Y when
+compiling the kernel, there is no way of disabling the watchdog once
+it has been started.  So, if the watchdog dameon crashes, the system
+will reboot after the timeout has passed.
+
+Some other drivers will not disable the watchdog, unless a specific
+magic character 'V' has been sent /dev/watchdog just before closing
+the file.  If the userspace daemon closes the file without sending
+this special character, the driver will assume that the daemon (and
+userspace in general) died, and will stop pinging the watchdog without
+disabling it first.  This will then cause a reboot.
+
+The ioctl API:
+
+All conforming drivers also support an ioctl API.
+
+Pinging the watchdog using an ioctl:
+
+All drivers that have an ioctl interface support at least one ioctl,
+KEEPALIVE.  This ioctl does exactly the same thing as a write to the
+watchdog device, so the main loop in the above program could be
+replaced with:
+
+	while (1) {
+		ioctl(fd, WDIOC_KEEPALIVE, 0);
+		sleep(10);
+	}
+
+the argument to the ioctl is ignored.
+
+Setting and getting the timeout:
+
+For some drivers it is possible to modify the watchdog timeout on the
+fly with the SETTIMEOUT ioctl, those drivers have the WDIOF_SETTIMEOUT
+flag set in their option field.  The argument is an integer
+representing the timeout in seconds.  The driver returns the real
+timeout used in the same variable, and this timeout might differ from
+the requested one due to limitation of the hardware.
+
+    int timeout = 45;
+    ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
+    printf("The timeout was set to %d seconds\n", timeout);
+
+This example might actually print "The timeout was set to 60 seconds"
+if the device has a granularity of minutes for its timeout.
+
+Starting with the Linux 2.4.18 kernel, it is possible to query the
+current timeout using the GETTIMEOUT ioctl.
+
+    ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
+    printf("The timeout was is %d seconds\n", timeout);
+
+Envinronmental monitoring:
+
+All watchdog drivers are required return more information about the system,
+some do temperature, fan and power level monitoring, some can tell you
+the reason for the last reboot of the system.  The GETSUPPORT ioctl is
+available to ask what the device can do:
+
+	struct watchdog_info ident;
+	ioctl(fd, WDIOC_GETSUPPORT, &ident);
+
+the fields returned in the ident struct are:
+
+        identity		a string identifying the watchdog driver
+	firmware_version	the firmware version of the card if available
+	options			a flags describing what the device supports
+
+the options field can have the following bits set, and describes what
+kind of information that the GET_STATUS and GET_BOOT_STATUS ioctls can
+return.   [FIXME -- Is this correct?]
+
+	WDIOF_OVERHEAT		Reset due to CPU overheat
+
+The machine was last rebooted by the watchdog because the thermal limit was
+exceeded
+
+	WDIOF_FANFAULT		Fan failed
+
+A system fan monitored by the watchdog card has failed
+
+	WDIOF_EXTERN1		External relay 1
+
+External monitoring relay/source 1 was triggered. Controllers intended for
+real world applications include external monitoring pins that will trigger
+a reset.
+
+	WDIOF_EXTERN2		External relay 2
+
+External monitoring relay/source 2 was triggered
+
+	WDIOF_POWERUNDER	Power bad/power fault
+
+The machine is showing an undervoltage status
+
+	WDIOF_CARDRESET		Card previously reset the CPU
+
+The last reboot was caused by the watchdog card
+
+	WDIOF_POWEROVER		Power over voltage
+
+The machine is showing an overvoltage status. Note that if one level is
+under and one over both bits will be set - this may seem odd but makes
+sense.
+
+	WDIOF_KEEPALIVEPING	Keep alive ping reply
+
+The watchdog saw a keepalive ping since it was last queried.
+
+	WDIOF_SETTIMEOUT	Can set/get the timeout
+
+
+For those drivers that return any bits set in the option field, the
+GETSTATUS and GETBOOTSTATUS ioctls can be used to ask for the current
+status, and the status at the last reboot, respectively.  
+
+    int flags;
+    ioctl(fd, WDIOC_GETSTATUS, &flags);
+
+    or
+
+    ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
+
+Note that not all devices support these two calls, and some only
+support the GETBOOTSTATUS call.
+
+Some drivers can measure the temperature using the GETTEMP ioctl.  The
+returned value is the temperature in degrees farenheit.
+
+    int temperature;
+    ioctl(fd, WDIOC_GETTEMP, &temperature);
+
+Finally the SETOPTIONS ioctl can be used to control some aspects of
+the cards operation; right now the pcwd driver is the only one
+supporting thiss ioctl.
+
+    int options = 0;
+    ioctl(fd, WDIOC_SETOPTIONS, options);
+
+The following options are available:
+
+	WDIOS_DISABLECARD	Turn off the watchdog timer
+	WDIOS_ENABLECARD	Turn on the watchdog timer
+	WDIOS_TEMPPANIC		Kernel panic on temperature trip
+
+[FIXME -- better explanations]
+
+Implementations in the current drivers in the kernel tree:
+
+Here I have tried to summarize what the different drivers support and
+where they do strange things compared to the other drivers.
+
+acquirewdt.c -- Acquire Single Board Computer
+
+	This driver has a hardcoded timeout of 1 minute
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns KEEPALIVEPING.  GETSTATUS will return 1 if
+	the device is open, 0 if not.  [FIXME -- isn't this rather
+	silly?  To be able to use the ioctl, the device must be open
+	and so GETSTATUS will always return 1].
+
+advantechwdt.c -- Advantech Single Board Computer
+
+	Timeout that defaults to 60 seconds, supports SETTIMEOUT.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
+	The GETSTATUS call returns if the device is open or not.
+	[FIXME -- silliness again?]
+	
+eurotechwdt.c -- Eurotech CPU-1220/1410
+
+	The timeout can be set using the SETTIMEOUT ioctl and defaults
+	to 60 seconds.
+
+	Also has a module parameter "ev", event type which controls
+	what should happen on a timeout, the string "int" or anything
+	else that causes a reboot.  [FIXME -- better description]
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns CARDRESET and WDIOF_SETTIMEOUT but
+	GETSTATUS is not supported and GETBOOTSTATUS just returns 0.
+
+i810-tco.c -- Intel 810 chipset
+
+	Also has support for a lot of other i8x0 stuff, but the
+	watchdog is one of the things.
+
+	The timeout is set using the module parameter "i810_margin",
+	which is in steps of 0.6 seconds where 2<i810_margin<64.  The
+	driver supports the SETTIMEOUT ioctl.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT.
+
+	GETSUPPORT returns WDIOF_SETTIMEOUT.  The GETSTATUS call
+	returns some kind of timer value which ist not compatible with
+	the other drivers.  GETBOOT status returns some kind of
+	hardware specific boot status.  [FIXME -- describe this]
+
+ib700wdt.c -- IB700 Single Board Computer
+
+	Default timeout of 30 seconds and the timeout is settable
+	using the SETTIMEOUT ioctl.  Note that only a few timeout
+	values are supported.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
+	The GETSTATUS call returns if the device is open or not.
+	[FIXME -- silliness again?]
+
+machzwd.c -- MachZ ZF-Logic
+
+	Hardcoded timeout of 10 seconds
+
+	Has a module parameter "action" that controls what happens
+	when the timeout runs out which can be 0 = RESET (default), 
+	1 = SMI, 2 = NMI, 3 = SCI.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT and the the magic character
+	'V' close handling.
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call
+	returns if the device is open or not.  [FIXME -- silliness
+	again?]
+
+mixcomwd.c -- MixCom Watchdog
+
+	[FIXME -- I'm unable to tell what the timeout is]
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING, GETSTATUS returns if
+	the device is opened or not [FIXME -- I'm not really sure how
+	this works, there seems to be some magic connected to
+	CONFIG_WATCHDOG_NOWAYOUT]
+
+pcwd.c -- Berkshire PC Watchdog
+
+	Hardcoded timeout of 1.5 seconds
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_OVERHEAT|WDIOF_CARDRESET and both
+	GETSTATUS and GETBOOTSTATUS return something useful.
+
+	The SETOPTIONS call can be used to enable and disable the card
+	and to ask the driver to call panic if the system overheats.
+
+sbc60xxwdt.c -- 60xx Single Board Computer
+
+	Hardcoded timeout of 10 seconds
+
+	Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic
+	character 'V' close handling.
+
+	No bits set in GETSUPPORT
+
+scx200.c -- National SCx200 CPUs
+
+	Not in the kernel yet.
+
+	The timeout is set using a module parameter "margin" which
+	defaults to 60 seconds.  The timeout can also be set using
+	SETTIMEOUT and read using GETTIMEOUT.
+
+	Supports a module parameter "nowayout" that is initialized
+	with the value of CONFIG_WATCHDOG_NOWAYOUT.  Also supports the
+	magic character 'V' handling.
+
+shwdt.c -- SuperH 3/4 processors
+
+	[FIXME -- I'm unable to tell what the timeout is]
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call
+	returns if the device is open or not.  [FIXME -- silliness
+	again?]
+
+softdog.c -- Software watchdog
+
+	The timeout is set with the module parameter "soft_margin"
+	which defaults to 60 seconds, the timeout is also settable
+	using the SETTIMEOUT ioctl.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	WDIOF_SETTIMEOUT bit set in GETSUPPORT
+
+w83877f_wdt.c -- W83877F Computer
+
+	Hardcoded timeout of 30 seconds
+
+	Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic
+	character 'V' close handling.
+
+	No bits set in GETSUPPORT
+
+wdt.c -- ICS WDT500/501 ISA and
+wdt_pci.c -- ICS WDT500/501 PCI
+
+	Default timeout of 60 seconds.  The timeout is also settable
+        using the SETTIMEOUT ioctl.
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	GETSUPPORT returns with bits set depending on the actual
+	card. The WDT501 supports a lot of external monitoring, the
+	WDT500 much less.
+
+wdt285.c -- Footbridge watchdog
+
+	The timeout is set with the module parameter "soft_margin"
+	which defaults to 60 seconds.  The timeout is also settable
+	using the SETTIMEOUT ioctl.
+
+	Does not support CONFIG_WATCHDOG_NOWAYOUT
+
+	WDIOF_SETTIMEOUT bit set in GETSUPPORT
+
+wdt977.c -- Netwinder W83977AF chip
+
+	Hardcoded timeout of 3 minutes
+
+	Supports CONFIG_WATCHDOG_NOWAYOUT
+
+	Does not support any ioctls at all.
+
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Sun Apr 14 12:16:55 2002
+++ b/MAINTAINERS	Sun Apr 14 12:16:55 2002
@@ -1386,6 +1386,13 @@
 M:	mingo@redhat.com
 S:	Maintained
 
+SIS 5513 IDE CONTROLLER DRIVER
+P:      Lionel Bouton
+M:      Lionel.Bouton@inet6.fr
+W:      http://inet6.dyn.dhs.org/sponsoring/sis5513/index.html
+W:      http://gyver.homeip.net/sis5513/index.html
+S:      Maintained
+
 SIS 900/7016 FAST ETHERNET DRIVER
 P:	Ollie Lho
 M:	ollie@sis.com.tw
@@ -1437,8 +1444,6 @@
 M:	anton@samba.org
 L:	sparclinux@vger.kernel.org
 L:	ultralinux@vger.kernel.org
-W:	http://ultra.linux.cz
-W:	http://www.geog.ubc.ca/s_linux.html
 S:	Maintained
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
@@ -1502,6 +1507,13 @@
 M:	hch@infradead.org
 S:	Maintained
 
+TI GRAPH LINK USB (SilverLink) CABLE DRIVER
+P:     Romain Lievin
+M:     roms@lpg.ticalc.org
+P:     Julien Blache
+M:     jb@technologeek.org
+S:     Maintained
+
 TLAN NETWORK DRIVER
 P:	Torben Mathiasen
 M:	torben.mathiasen@compaq.com
@@ -1660,6 +1672,7 @@
 M:	petkan@users.sourceforge.net
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
+W:	http://pegasus2.sourceforge.net/
 S:	Maintained
 
 USB PRINTER DRIVER
@@ -1667,6 +1680,14 @@
 M:	vojtech@suse.cz
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
+S:	Maintained
+
+USB RTL8150 DRIVER
+P:	Petko Manolov
+M:	petkan@users.sourceforge.net
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://pegasus2.sourceforge.net/
 S:	Maintained
 
 USB SE401 DRIVER
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Sun Apr 14 12:16:55 2002
+++ b/Makefile	Sun Apr 14 12:16:55 2002
@@ -1,12 +1,12 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 7
+SUBLEVEL = 8
 EXTRAVERSION =
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
-KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//")
+KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
 
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
@@ -341,7 +341,7 @@
 	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $*.o $<
 
 init/do_mounts.o: init/do_mounts.c include/config/MARKER
-	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
+	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) -c -o $*.o $<
 
 fs lib mm ipc kernel drivers net sound: dummy
 	$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
diff -Nru a/Rules.make b/Rules.make
--- a/Rules.make	Sun Apr 14 12:16:57 2002
+++ b/Rules.make	Sun Apr 14 12:16:57 2002
@@ -50,10 +50,10 @@
 #
 
 %.s: %.c
-	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -S $< -o $@
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -S $< -o $@
 
 %.i: %.c
-	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) $< > $@
+	$(CPP) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) $< > $@
 
 %.o: %.c
 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F))) $(CFLAGS_$@) -c -o $@ $<
@@ -126,11 +126,23 @@
 
 # for make >= 3.78 the following is cleaner:
 # multi-used := $(foreach m,$(obj-y) $(obj-m), $(if $($(basename $(m))-objs), $(m)))
-multi-used := $(sort $(foreach m,$(obj-y) $(obj-m),$(patsubst %,$(m),$($(basename $(m))-objs))))
-ld-multi-used := $(filter-out $(list-multi),$(multi-used))
-ld-multi-objs := $(foreach m, $(ld-multi-used), $($(basename $(m))-objs))
+multi-used-y := $(sort $(foreach m,$(obj-y),$(patsubst %,$(m),$($(basename $(m))-objs))))
+multi-used-m := $(sort $(foreach m,$(obj-m),$(patsubst %,$(m),$($(basename $(m))-objs))))
+ld-multi-used-y := $(filter-out $(list-multi),$(multi-used-y))
+ld-multi-used-m := $(filter-out $(list-multi),$(multi-used-m))
+ld-multi-objs-y := $(foreach m, $(ld-multi-used-y), $($(basename $(m))-objs))
+ld-multi-objs-m := $(foreach m, $(ld-multi-used-m), $($(basename $(m))-objs))
 
-$(ld-multi-used) : %.o: $(ld-multi-objs)
+$(ld-multi-used-y) : %.o: $(ld-multi-objs-y)
+	rm -f $@
+	$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(filter $($(basename $@)-objs), $^)
+	@ ( \
+	    echo 'ifeq ($(strip $(subst $(comma),:,$(LD) $(EXTRA_LDFLAGS) $($(basename $@)-objs)),$$(strip $$(subst $$(comma),:,$$(LD) $$(EXTRA_LDFLAGS) $$($(basename $@)-objs)))))' ; \
+	    echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
+	    echo 'endif' \
+	) > $(dir $@)/.$(notdir $@).flags
+
+$(ld-multi-used-m) : %.o: $(ld-multi-objs-m)
 	rm -f $@
 	$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(filter $($(basename $@)-objs), $^)
 	@ ( \
@@ -153,7 +165,7 @@
 	$(MAKE) -C $(patsubst _sfdep_%,%,$@) fastdep
 endif
 
-	
+
 #
 # A rule to make subdirectories
 #
@@ -250,7 +262,7 @@
 		if [ -r $@ ] && cmp -s $@ $@.tmp; then echo $@ is unchanged; rm -f $@.tmp; \
 		else echo mv $@.tmp $@; mv -f $@.tmp $@; fi; \
 	fi; touch $(MODINCL)/$(MODPREFIX)$*.stamp
-	
+
 $(addprefix $(MODINCL)/$(MODPREFIX),$(export-objs:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h
 
 # updates .ver files but not modversions.h
diff -Nru a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
--- a/arch/alpha/kernel/alpha_ksyms.c	Sun Apr 14 12:16:55 2002
+++ b/arch/alpha/kernel/alpha_ksyms.c	Sun Apr 14 12:16:55 2002
@@ -103,7 +103,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
diff -Nru a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
--- a/arch/alpha/kernel/core_irongate.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/core_irongate.c	Sun Apr 14 12:16:56 2002
@@ -19,6 +19,8 @@
 #include <asm/system.h>
 #include <asm/pci.h>
 #include <asm/hwrpb.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
diff -Nru a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
--- a/arch/alpha/kernel/setup.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/setup.c	Sun Apr 14 12:16:56 2002
@@ -472,6 +472,7 @@
 	struct percpu_struct *cpu;
 	char *type_name, *var_name, *p;
 	void *kernel_end = _end; /* end of kernel */
+	char *args = command_line;
 
 	hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
 	boot_cpuid = hard_smp_processor_id();
@@ -509,7 +510,8 @@
 	/* 
 	 * Process command-line arguments.
 	 */
-	for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
+	while ((p = strsep(&args, " \t")) != NULL) {
+		if (!*p) continue;
 		if (strncmp(p, "alpha_mv=", 9) == 0) {
 			vec = get_sysvec_byname(p+9);
 			continue;
@@ -528,7 +530,7 @@
 		}
 	}
 
-	/* Replace the command line, now that we've killed it with strtok.  */
+	/* Replace the command line, now that we've killed it with strsep.  */
 	strcpy(command_line, saved_command_line);
 
 	/* If we want SRM console printk echoing early, do it now. */
diff -Nru a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
--- a/arch/alpha/kernel/sys_alcor.c	Sun Apr 14 12:16:58 2002
+++ b/arch/alpha/kernel/sys_alcor.c	Sun Apr 14 12:16:58 2002
@@ -26,6 +26,7 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
--- a/arch/alpha/kernel/sys_cabriolet.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/sys_cabriolet.c	Sun Apr 14 12:16:56 2002
@@ -28,6 +28,7 @@
 #include <asm/core_apecs.h>
 #include <asm/core_cia.h>
 #include <asm/core_lca.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
--- a/arch/alpha/kernel/sys_dp264.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/sys_dp264.c	Sun Apr 14 12:16:56 2002
@@ -30,6 +30,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_tsunami.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
--- a/arch/alpha/kernel/sys_eb64p.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/sys_eb64p.c	Sun Apr 14 12:16:56 2002
@@ -27,6 +27,7 @@
 #include <asm/core_apecs.h>
 #include <asm/core_lca.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
--- a/arch/alpha/kernel/sys_eiger.c	Sun Apr 14 12:16:55 2002
+++ b/arch/alpha/kernel/sys_eiger.c	Sun Apr 14 12:16:55 2002
@@ -27,6 +27,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_tsunami.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
--- a/arch/alpha/kernel/sys_jensen.c	Sun Apr 14 12:16:55 2002
+++ b/arch/alpha/kernel/sys_jensen.c	Sun Apr 14 12:16:55 2002
@@ -26,6 +26,7 @@
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
--- a/arch/alpha/kernel/sys_miata.c	Sun Apr 14 12:16:59 2002
+++ b/arch/alpha/kernel/sys_miata.c	Sun Apr 14 12:16:59 2002
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
--- a/arch/alpha/kernel/sys_mikasa.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/sys_mikasa.c	Sun Apr 14 12:16:56 2002
@@ -26,6 +26,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_apecs.h>
 #include <asm/core_cia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
--- a/arch/alpha/kernel/sys_nautilus.c	Sun Apr 14 12:16:57 2002
+++ b/arch/alpha/kernel/sys_nautilus.c	Sun Apr 14 12:16:57 2002
@@ -43,6 +43,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_irongate.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
--- a/arch/alpha/kernel/sys_noritake.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/sys_noritake.c	Sun Apr 14 12:16:56 2002
@@ -27,6 +27,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_apecs.h>
 #include <asm/core_cia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
--- a/arch/alpha/kernel/sys_rawhide.c	Sun Apr 14 12:16:59 2002
+++ b/arch/alpha/kernel/sys_rawhide.c	Sun Apr 14 12:16:59 2002
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_mcpcia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
--- a/arch/alpha/kernel/sys_ruffian.c	Sun Apr 14 12:16:55 2002
+++ b/arch/alpha/kernel/sys_ruffian.c	Sun Apr 14 12:16:55 2002
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
--- a/arch/alpha/kernel/sys_rx164.c	Sun Apr 14 12:16:54 2002
+++ b/arch/alpha/kernel/sys_rx164.c	Sun Apr 14 12:16:54 2002
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_polaris.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
--- a/arch/alpha/kernel/sys_sable.c	Sun Apr 14 12:16:55 2002
+++ b/arch/alpha/kernel/sys_sable.c	Sun Apr 14 12:16:55 2002
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_t2.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
--- a/arch/alpha/kernel/sys_sio.c	Sun Apr 14 12:16:55 2002
+++ b/arch/alpha/kernel/sys_sio.c	Sun Apr 14 12:16:55 2002
@@ -29,6 +29,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_apecs.h>
 #include <asm/core_lca.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
--- a/arch/alpha/kernel/sys_sx164.c	Sun Apr 14 12:16:58 2002
+++ b/arch/alpha/kernel/sys_sx164.c	Sun Apr 14 12:16:58 2002
@@ -25,6 +25,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
--- a/arch/alpha/kernel/sys_takara.c	Sun Apr 14 12:16:56 2002
+++ b/arch/alpha/kernel/sys_takara.c	Sun Apr 14 12:16:56 2002
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
--- a/arch/alpha/kernel/sys_titan.c	Sun Apr 14 12:16:59 2002
+++ b/arch/alpha/kernel/sys_titan.c	Sun Apr 14 12:16:59 2002
@@ -28,6 +28,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_titan.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c
--- a/arch/alpha/kernel/sys_wildfire.c	Sun Apr 14 12:16:58 2002
+++ b/arch/alpha/kernel/sys_wildfire.c	Sun Apr 14 12:16:58 2002
@@ -23,6 +23,7 @@
 #include <asm/pgtable.h>
 #include <asm/core_wildfire.h>
 #include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
 
 #include "proto.h"
 #include "irq_impl.h"
diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
--- a/arch/alpha/mm/fault.c	Sun Apr 14 12:16:57 2002
+++ b/arch/alpha/mm/fault.c	Sun Apr 14 12:16:57 2002
@@ -12,7 +12,7 @@
 
 #define __EXTERN_INLINE inline
 #include <asm/mmu_context.h>
-#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 #undef  __EXTERN_INLINE
 
 #include <linux/signal.h>
diff -Nru a/arch/arm/Config.help b/arch/arm/Config.help
--- a/arch/arm/Config.help	Sun Apr 14 12:16:54 2002
+++ b/arch/arm/Config.help	Sun Apr 14 12:16:54 2002
@@ -678,23 +678,6 @@
   Say Y if you want support for the ARM922T processor.
   Otherwise, say N.
 
-CONFIG_CPU_ARM922_CPU_IDLE
-  Saying Y here will allow the processor to enter a low power
-  mode whilst waiting for an interrupt in idle. If you're unsure
-  say Y.
-
-CONFIG_CPU_ARM922_I_CACHE_ON
-  Say Y here to enable the processor instruction cache. Unless
-  you have a reason not to, say Y.
-
-CONFIG_CPU_ARM922_D_CACHE_ON
-  Say Y here to enable the processor data cache. Unless
-  you have a reason not to, say Y.
-
-CONFIG_CPU_ARM922_WRITETHROUGH
-  Say Y here to use the data cache in writethough mode. Unless you
-  specifically require this, say N.
-
 CONFIG_CPU_ARM1020
   The ARM1020 is the cached version of the ARM10 processor,
   with an addition of a floating-point unit.
@@ -710,6 +693,25 @@
 
   Say Y if you want support for the SA-110 processor.
   Otherwise, say N.
+
+CONFIG_CPU_ICACHE_DISABLE
+  Say Y here to disable the processor instruction cache. Unless
+  you have a reason not to or are unsure, say N.
+
+CONFIG_CPU_DCACHE_DISABLE
+  Say Y here to disable the processor data cache. Unless
+  you have a reason not to or are unsure, say N.
+
+CONFIG_CPU_DCACHE_WRITETHROUGH
+  Say Y here to use the data cache in writethough mode. Unless you
+  specifically require this or are unsure, say N.
+
+CONFIG_CPU_CACHE_ROUND_ROBIN
+  Say Y here to use the predictable round-robin cache replacement
+  policy.  Unless you specifically require this or are unsure, say N.
+
+CONFIG_CPU_BPREDICT_DISABLE
+  Say Y here to disable branch prediction.  If unsure, say N.
 
 CONFIG_FPE_NWFPE
   Say Y to include the NWFPE floating point emulator in the kernel.
diff -Nru a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
--- a/arch/arm/boot/compressed/head.S	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/boot/compressed/head.S	Sun Apr 14 12:16:59 2002
@@ -18,14 +18,14 @@
  * Please select one of the following when turning on debugging.
  */
 #ifdef DEBUG
-#if 0 /* DC21285-type */
+#if defined(CONFIG_DEBUG_DC21285_PORT)
 		.macro	loadsp,	rb
 		mov	\rb, #0x7c000000
 		.endm
 		.macro	writeb,	rb
 		strb	\rb, [r3, #0x3f8]
 		.endm
-#elif 0 /* RiscPC-type */
+#elif defined(CONFIG_ARCH_RPC)
 		.macro	loadsp,	rb
 		mov	\rb, #0x03000000
 		orr	\rb, \rb, #0x00010000
@@ -33,7 +33,7 @@
 		.macro	writeb,	rb
 		strb	\rb, [r3, #0x3f8 << 2]
 		.endm
-#elif 0 /* integrator-type */
+#elif defined(CONFIG_ARCH_INTEGRATOR)
 		.macro	loadsp, rb
 		mov	\rb, #0x16000000
 		.endm
diff -Nru a/arch/arm/config.in b/arch/arm/config.in
--- a/arch/arm/config.in	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/config.in	Sun Apr 14 12:16:56 2002
@@ -218,7 +218,7 @@
 comment 'Processor Type'
 
 # Firstly, figure out what processor architecture version we should be using.
-# This depends more on the machine type than anything else.
+# This defines the compiler instruction set which depends on the machine type.
 
 if [ "$CONFIG_ARCH_RPC"        = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
    define_bool CONFIG_CPU_32v3 y
@@ -235,10 +235,15 @@
 else
    define_bool CONFIG_CPU_32v4 n
 fi
+if [ "$CONFIG_ARCH_IOP310" = "y" -o "$CONFIG_ARCH_ADIFCC" = "y" ]; then
+   define_bool CONFIG_CPU_32v5 y
+else
+   define_bool CONFIG_CPU_32v5 n
+fi
 
-# Select CPU types depending on the architecture selected.
-# We use this to select which CPUs are supported, and to select
-# the compiler tuning options.
+# Select CPU types depending on the architecture selected.  This selects
+# which CPUs we support in the kernel image, and the compiler instruction
+# optimiser behaviour.
 
 # ARM610
 if [ "$CONFIG_ARCH_RPC" = "y" ]; then
@@ -277,14 +282,6 @@
 else
    define_bool CONFIG_CPU_ARM920T n
 fi
-if [ "$CONFIG_CPU_ARM920T" = "y" ]; then
-   bool '  ARM920T CPU idle' CONFIG_CPU_ARM920_CPU_IDLE
-   bool '  ARM920T I-Cache on' CONFIG_CPU_ARM920_I_CACHE_ON
-   bool '  ARM920T D-Cache on' CONFIG_CPU_ARM920_D_CACHE_ON
-   if [ "$CONFIG_CPU_ARM920_D_CACHE_ON" = "y" ] ; then
-      bool '  Force write through caches on ARM920T' CONFIG_CPU_ARM920_WRITETHROUGH
-   fi
-fi
 
 # ARM922T
 if [ "$CONFIG_ARCH_CAMELOT" = "y" ]; then
@@ -292,14 +289,6 @@
 else
          define_bool CONFIG_CPU_ARM922T n
 fi
-if [ "$CONFIG_CPU_ARM922T" = "y" ]; then
-   bool '  ARM922T CPU idle' CONFIG_CPU_ARM922_CPU_IDLE
-   bool '  ARM922T I-Cache on' CONFIG_CPU_ARM922_I_CACHE_ON
-   bool '  ARM922T D-Cache on' CONFIG_CPU_ARM922_D_CACHE_ON
-   if [ "$CONFIG_CPU_ARM922_D_CACHE_ON" = "y" ] ; then
-      bool '  Force write through caches on ARM922T' CONFIG_CPU_ARM922_WRITETHROUGH
-   fi
-fi
 
 # ARM926T
 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
@@ -307,18 +296,6 @@
 else
    define_bool CONFIG_CPU_ARM926T n
 fi
-if [ "$CONFIG_CPU_ARM926T" = "y" ]; then
-   bool '  ARM926T CPU idle' CONFIG_CPU_ARM926_CPU_IDLE
-   bool '  ARM926T I-Cache on' CONFIG_CPU_ARM926_I_CACHE_ON
-   bool '  ARM926T D-Cache on' CONFIG_CPU_ARM926_D_CACHE_ON
-   if [ "$CONFIG_CPU_ARM926_D_CACHE_ON" = "y" ] ; then
-      bool '  Force write through caches on ARM926T' CONFIG_CPU_ARM926_WRITETHROUGH
-   fi
-   if [ "$CONFIG_CPU_ARM926_I_CACHE_ON" = "y" -o \
-        "$CONFIG_CPU_ARM926_D_CACHE_ON" = "y" ]; then
-      bool '  Round robin I and D cache replacement algorithm' CONFIG_CPU_ARM926_ROUND_ROBIN
-   fi
-fi
 
 # ARM1020
 if [ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then
@@ -326,17 +303,6 @@
 else
     define_bool CONFIG_CPU_ARM1020 n
 fi
-if [ "$CONFIG_CPU_ARM1020" = "y" ]; then
-   bool '  ARM1020 I-Cache on' CONFIG_CPU_ARM1020_I_CACHE_ON
-   bool '  ARM10 D-Cache on' CONFIG_CPU_ARM1020_D_CACHE_ON
-   if [ "$CONFIG_CPU_ARM1020_D_CACHE_ON" = "y" ] ; then
-      bool '  Force write through caches on ARM1020' CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH
-   fi
-   if [ "$CONFIG_CPU_ARM1020_I_CACHE_ON" = "y" -o \
-        "$CONFIG_CPU_ARM1020_D_CACHE_ON" = "y" ]; then
-      bool '  Round robin I and D cache replacement algorithm' CONFIG_CPU_ARM1020_ROUND_ROBIN
-   fi
-fi
 
 # SA110
 if [ "$CONFIG_ARCH_EBSA110"  = "y" -o "$CONFIG_FOOTBRIDGE" = "y" -o \
@@ -360,8 +326,9 @@
 
 # XScale
 if [ "$CONFIG_ARCH_IOP310" = "y" -o "$CONFIG_ARCH_ADIFCC" = "y" ]; then
-   define_bool CONFIG_CPU_32v5 y
    define_bool CONFIG_CPU_XSCALE y
+else
+   define_bool CONFIG_CPU_XSCALE n
 fi
 
 #if [ "$CONFIG_CPU_XSCALE" = "y" ]; then
@@ -374,9 +341,34 @@
    define_bool CONFIG_XSCALE_PMU n
 fi
 
-if [ "$CONFIG_CPU_32" = "y" ]; then
+comment 'Processor Features'
+
+if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
+     "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
+     "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_XSCALE" = "y" ]; then
    dep_bool 'Support Thumb instructions (experimental)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
 fi
+if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
+     "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" ]; then
+   bool 'Disable I-Cache' CONFIG_CPU_ICACHE_DISABLE
+   bool 'Disable D-Cache' CONFIG_CPU_DCACHE_DISABLE
+   if [ "$CONFIG_CPU_DISABLE_DCACHE" = "n" ]; then
+      bool 'Force write through D-cache' CONFIG_CPU_DCACHE_WRITETHROUGH
+   fi
+fi
+if [ "$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" ]; then
+   if [ "$CONFIG_CPU_ICACHE_DISABLE" = "n" -o "$CONFIG_CPU_DCACHE_DISABLE" = "n" ]; then
+      bool 'Round robin I and D cache replacement algorithm' CONFIG_CPU_CACHE_ROUND_ROBIN
+   fi
+fi
+if [ "$CONFIG_CPU_ARM1020" = "y" ]; then
+   bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE
+fi
+
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
 
 # Select various configuration options depending on the machine type
 if [ "$CONFIG_ARCH_EDB7211" = "y" -o \
@@ -386,11 +378,6 @@
    define_bool CONFIG_DISCONTIGMEM n
 fi
 
-endmenu
-
-mainmenu_option next_comment
-comment 'General setup'
-
 # Now handle the bus types
 if [ "$CONFIG_ARCH_FTVPCI" = "y" -o \
      "$CONFIG_ARCH_SHARK" = "y" -o \
@@ -693,7 +680,6 @@
 dep_bool '  Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
 dep_bool '    Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
 dep_bool '    Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
-dep_bool '    Kernel low-level debugging messages via SA1100 Ser3 (otherwise Ser1)' CONFIG_DEBUG_LL_SER3 $CONFIG_DEBUG_LL $CONFIG_ARCH_SA1100
 endmenu
 
 source lib/Config.in
diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
--- a/arch/arm/kernel/armksyms.c	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/kernel/armksyms.c	Sun Apr 14 12:16:57 2002
@@ -64,6 +64,7 @@
 extern void __muldi3(void);
 extern void __ucmpdi2(void);
 extern void __udivdi3(void);
+extern void __umoddi3(void);
 extern void __udivmoddi4(void);
 extern void __udivsi3(void);
 extern void __umodsi3(void);
@@ -84,7 +85,7 @@
     __MODULE_STRING(sym);			\
  const struct module_symbol __ksymtab_##sym	\
   __attribute__((section("__ksymtab"))) =	\
-    { (unsigned long)&##orig, __kstrtab_##sym };
+    { (unsigned long)&orig, __kstrtab_##sym };
 
 /*
  * floating point math emulator support.
@@ -180,7 +181,7 @@
 EXPORT_SYMBOL_NOVERS(strlen);
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
 EXPORT_SYMBOL_NOVERS(memset);
@@ -227,6 +228,7 @@
 EXPORT_SYMBOL_NOVERS(__muldi3);
 EXPORT_SYMBOL_NOVERS(__ucmpdi2);
 EXPORT_SYMBOL_NOVERS(__udivdi3);
+EXPORT_SYMBOL_NOVERS(__umoddi3);
 EXPORT_SYMBOL_NOVERS(__udivmoddi4);
 EXPORT_SYMBOL_NOVERS(__udivsi3);
 EXPORT_SYMBOL_NOVERS(__umodsi3);
diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
--- a/arch/arm/kernel/bios32.c	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/kernel/bios32.c	Sun Apr 14 12:16:57 2002
@@ -348,7 +348,7 @@
 
 	if (dev) {
 		for (i = 0; i < 3; i++) {
-			if(root->resource[i]) {
+			if (root->resource[i]) {
 				bus->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
 				bus->resource[i]->end  = root->resource[i]->end;
 				bus->resource[i]->name = bus->name;
@@ -357,13 +357,8 @@
 		bus->resource[0]->flags |= pci_bridge_check_io(dev);
 		bus->resource[1]->flags |= IORESOURCE_MEM;
 
-		if (root->resource[2])
+		if (bus->resource[2] && root->resource[2])
 			bus->resource[2]->flags = root->resource[2]->flags;
-		else {
-			/* no prefetchable memory region - disable it */
-			bus->resource[2]->start = 1024*1024;
-			bus->resource[2]->end   = bus->resource[2]->start - 1;
-		}
 	} else {
 		/*
 		 * Assign root bus resources.
@@ -552,12 +547,12 @@
 				panic("PCI: unable to scan bus!");
 
 			busnr = sys->bus->subordinate + 1;
-		} else if (ret < 0)
-			break;
+		} else {
+			kfree(sys);
+			if (ret < 0)
+				break;
+		}
 	}
-
-	kfree(sys);
-
 }
 
 extern struct hw_pci ebsa285_pci;
diff -Nru a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
--- a/arch/arm/kernel/debug.S	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/kernel/debug.S	Sun Apr 14 12:16:57 2002
@@ -210,6 +210,31 @@
 		bne	1001b
 		.endm
 
+#elif defined(CONFIG_ARCH_PXA)
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x40000000	@ physical
+		movne	\rx, #0xfc000000	@ virtual
+		orr	\rx, \rx, #0x00100000
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x14]
+		tst	\rd, #(1 << 6)
+		beq	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #0x14]
+		tst	\rd, #(1 << 5)
+		beq	1001b
+		.endm
 #elif defined(CONFIG_ARCH_CLPS7500)
 		.macro	addruart,rx
 		mov	\rx, #0xe0000000
@@ -385,6 +410,55 @@
 		bne	1001b
 		.endm
 
+#elif defined(CONFIG_ARCH_IQ80310)
+
+		.macro	addruart,rx
+		mov	\rx, #0xfe000000	@ physical
+		orr	\rx, \rx, #0x00810000
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldrb	\rd, [\rx, #0x5]
+		and	\rd, \rd, #0x60
+		teq	\rd, #0x60
+		bne	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldrb	\rd, [\rx, #0x6]
+		tst	\rd, #0x10
+		beq	1001b
+		.endm
+
+#elif defined(CONFIG_ARCH_ADI_EVB)
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		mov	\rx, #0x00400000	@ physical base address
+		orrne	\rx, \rx, #0xff000000	@ virtual base
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldrb	\rd, [\rx, #0x5]
+		and	\rd, \rd, #0x60
+		teq	\rd, #0x60
+		bne	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldrb	\rd, [\rx, #0x6]
+		tst	\rd, #0x10
+		beq	1001b
+		.endm
 #else
 #error Unknown architecture
 #endif
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/kernel/ecard.c	Sun Apr 14 12:16:59 2002
@@ -248,24 +248,16 @@
 	 * FIXME: we don't follow this 100% yet.
 	 */
 	pgd_t *src_pgd, *dst_pgd;
-	unsigned int dst_addr = IO_START;
 
 	src_pgd = pgd_offset(mm, IO_BASE);
-	dst_pgd = pgd_offset(mm, dst_addr);
+	dst_pgd = pgd_offset(mm, IO_START);
 
-	while (dst_addr < IO_START + IO_SIZE) {
-		*dst_pgd++ = *src_pgd++;
-		dst_addr += PGDIR_SIZE;
-	}
+	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
 
-	dst_addr = EASI_START;
 	src_pgd = pgd_offset(mm, EASI_BASE);
-	dst_pgd = pgd_offset(mm, dst_addr);
+	dst_pgd = pgd_offset(mm, EASI_START);
 
-	while (dst_addr < EASI_START + EASI_SIZE) {
-		*dst_pgd++ = *src_pgd++;
-		dst_addr += PGDIR_SIZE;
-	}
+	memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE));
 
 	vma.vm_mm = mm;
 
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/kernel/entry-armv.S	Sun Apr 14 12:16:57 2002
@@ -583,6 +583,40 @@
 
   		.macro	irq_prio_table
  		.endm
+
+#elif defined(CONFIG_ARCH_PXA)
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov	\base, #0xfc000000		@ IIR Ctl = 0xfcd00000
+		add	\base, \base, #0x00d00000
+		ldr	\irqstat, [\base, #0]		@ ICIP
+		ldr	\irqnr, [\base, #4]		@ ICMR
+		ands	\irqstat, \irqstat, \irqnr
+		mov	\irqnr, #0
+		beq	1001f
+		tst	\irqstat, #0xff00
+		moveq	\irqstat, \irqstat, lsr #8
+		addeq	\irqnr, \irqnr, #8
+		tsteq	\irqstat, #0xff00
+		moveq	\irqstat, \irqstat, lsr #8
+		addeq	\irqnr, \irqnr, #8
+		tst	\irqstat, #0x0f00
+		moveq	\irqstat, \irqstat, lsr #4
+		addeq	\irqnr, \irqnr, #4
+		tst	\irqstat, #0x0300
+		moveq	\irqstat, \irqstat, lsr #2
+		addeq	\irqnr, \irqnr, #2
+		tst	\irqstat, #0x0100
+		addeqs	\irqnr, \irqnr, #1
+1001:
+		.endm
+
+		.macro	irq_prio_table
+		.endm
+
 #else
 #error Unknown architecture
 #endif
diff -Nru a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
--- a/arch/arm/kernel/entry-header.S	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/kernel/entry-header.S	Sun Apr 14 12:16:58 2002
@@ -6,7 +6,6 @@
 #include <asm/errno.h>
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
-#include <asm/proc-fns.h>
 
 #ifndef MODE_SVC
 #define MODE_SVC 0x13
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	Sun Apr 14 12:16:54 2002
+++ b/arch/arm/kernel/irq.c	Sun Apr 14 12:16:54 2002
@@ -325,9 +325,8 @@
 				   !check_irq_lock(desc, irq, regs)))
 				desc->chip->unmask(irq);
 		}
+		irq_exit(cpu, irq);
 	}
-
-	irq_exit(cpu, irq);
 }
 
 /*
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c	Sun Apr 14 12:16:55 2002
+++ b/arch/arm/kernel/ptrace.c	Sun Apr 14 12:16:55 2002
@@ -620,15 +620,9 @@
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED && request != PTRACE_KILL)
-		goto out_tsk;
-	if (child->p_pptr != current)
-		goto out_tsk;
-
-	ret = do_ptrace(request, child, addr, data);
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret == 0)
+		ret = do_ptrace(request, child, addr, data);
 
 out_tsk:
 	put_task_struct(child);
diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
--- a/arch/arm/kernel/signal.c	Sun Apr 14 12:16:54 2002
+++ b/arch/arm/kernel/signal.c	Sun Apr 14 12:16:54 2002
@@ -589,8 +589,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -626,13 +626,18 @@
 					continue;
 				/* FALLTHRU */
 
-			case SIGSTOP:
-				current->state = TASK_STOPPED;
+			case SIGSTOP: {
+				struct signal_struct *sig;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+				sig = current->parent->sig;
+				preempt_disable();
+				current->state = TASK_STOPPED;
+				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
+				preempt_enable();
 				continue;
+			}
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
 			case SIGABRT: case SIGFPE: case SIGSEGV:
diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
--- a/arch/arm/kernel/traps.c	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/kernel/traps.c	Sun Apr 14 12:16:58 2002
@@ -27,6 +27,7 @@
 
 #include <asm/atomic.h>
 #include <asm/io.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -131,7 +132,7 @@
 	} else if (verify_stack(fp)) {
 		printk("invalid frame pointer 0x%08x", fp);
 		ok = 0;
-	} else if (fp < 4096+(unsigned long)tsk)
+	} else if (fp < 4096+(unsigned long)tsk->thread_info)
 		printk("frame pointer underflow");
 	printk("\n");
 
@@ -335,6 +336,25 @@
 	return regs->ARM_r0;
 }
 
+static inline void
+do_cache_op(unsigned long start, unsigned long end, int flags)
+{
+	struct vm_area_struct *vma;
+
+	if (end < start)
+		return;
+
+	vma = find_vma(current->active_mm, start);
+	if (vma && vma->vm_start < end) {
+		if (start < vma->vm_start)
+			start = vma->vm_start;
+		if (end > vma->vm_end)
+			end = vma->vm_end;
+
+		flush_cache_range(vma, start, end);
+	}
+}
+
 /*
  * Handle all unrecognised system calls.
  *  0x9f0000 - 0x9fffff are some more esoteric system calls
@@ -392,7 +412,7 @@
 	 * the specified region).
 	 */
 	case NR(cacheflush):
-		cpu_cache_clean_invalidate_range(regs->ARM_r0, regs->ARM_r1, 1);
+		do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
 		return 0;
 
 	case NR(usr26):
diff -Nru a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
--- a/arch/arm/lib/findbit.S	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/lib/findbit.S	Sun Apr 14 12:16:58 2002
@@ -6,6 +6,12 @@
  * 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.
+ *
+ * 16th March 2001 - John Ripley <jripley@sonicblue.com>
+ *   Fixed so that "size" is an exclusive not an inclusive quantity.
+ *   All users of these functions expect exclusive sizes, and may
+ *   also call with zero size.
+ * Reworked by rmk.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -13,58 +19,64 @@
 
 /*
  * Purpose  : Find a 'zero' bit
- * Prototype: int find_first_zero_bit(void *addr, int maxbit);
+ * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
  */
 ENTRY(_find_first_zero_bit_le)
+		teq	r1, #0	
+		beq	3f
 		mov	r2, #0
 1:		ldrb	r3, [r0, r2, lsr #3]
 		eors	r3, r3, #0xff		@ invert bits
 		bne	.found			@ any now set - found zero bit
 		add	r2, r2, #8		@ next bit pointer
-		cmp	r2, r1			@ any more?
-		bcc	1b
-		add	r0, r1, #1		@ no free bits
+2:		cmp	r2, r1			@ any more?
+		blo	1b
+3:		mov	r0, r1			@ no free bits
 		RETINSTR(mov,pc,lr)
 
 /*
  * Purpose  : Find next 'zero' bit
- * Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset)
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
  */
 ENTRY(_find_next_zero_bit_le)
+		teq	r1, #0
+		beq	2b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
-		ldrb	r3, [r0, r2, lsr#3]
+		ldrb	r3, [r0, r2, lsr #3]
 		eor	r3, r3, #0xff		@ now looking for a 1 bit
 		movs	r3, r3, lsr ip		@ shift off unused bits
 		bne	.found
 		orr	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
-		b	1b			@ loop for next bit
+		b	2b			@ loop for next bit
 
 #ifdef __ARMEB__
 
 ENTRY(_find_first_zero_bit_be)
+		teq	r1, #0
+		beq	3f
 		mov	r2, #0
 1:		eor	r3, r2, #0x18		@ big endian byte ordering
 		ldrb	r3, [r0, r3, lsr #3]
 		eors	r3, r3, #0xff		@ invert bits
 		bne	.found			@ any now set - found zero bit
 		add	r2, r2, #8		@ next bit pointer
-		cmp	r2, r1			@ any more?
-		bcc	1b
-		add	r0, r1, #1		@ no free bits
+2:		cmp	r2, r1			@ any more?
+		blo	1b
+3:		mov	r0, r1			@ no free bits
 		RETINSTR(mov,pc,lr)
 
 ENTRY(_find_next_zero_bit_be)
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
 		eor	r3, r2, #0x18		@ big endian byte ordering
-		ldrb	r3, [r0, r3, lsr#3]
+		ldrb	r3, [r0, r3, lsr #3]
 		eor	r3, r3, #0xff		@ now looking for a 1 bit
 		movs	r3, r3, lsr ip		@ shift off unused bits
 		orreq	r2, r2, #7		@ if zero, then no bits here
 		addeq	r2, r2, #1		@ align bit pointer
-		beq	1b			@ loop for next bit
+		beq	2b			@ loop for next bit
 
 #endif
 
diff -Nru a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S
--- a/arch/arm/lib/memchr.S	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/lib/memchr.S	Sun Apr 14 12:16:59 2002
@@ -15,11 +15,11 @@
 	.text
 	.align	5
 ENTRY(memchr)
-1:	ldrb	r3, [r0], #1
+1:	subs	r2, r2, #1
+	bmi	2f
+	ldrb	r3, [r0], #1
 	teq	r3, r1
-	beq	2f
-	subs	r2, r2, #1
-	bpl	1b
+	bne	1b
+	sub	r0, r0, #1
 2:	movne	r0, #0
-	subeq	r0, r0, #1
 	RETINSTR(mov,pc,lr)
diff -Nru a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c
--- a/arch/arm/lib/udivdi3.c	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/lib/udivdi3.c	Sun Apr 14 12:16:59 2002
@@ -229,3 +229,14 @@
 {
   return __udivmoddi4 (n, d, (UDItype *) 0);
 }
+
+UDItype
+__umoddi3 (UDItype u, UDItype v)
+{
+  UDItype w;
+
+  (void) __udivmoddi4 (u ,v, &w);
+
+  return w;
+}
+
diff -Nru a/arch/arm/mach-arc/dma.c b/arch/arm/mach-arc/dma.c
--- a/arch/arm/mach-arc/dma.c	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/mach-arc/dma.c	Sun Apr 14 12:16:59 2002
@@ -100,7 +100,7 @@
 	/* 10/1/1999 DAG - Presume whether there is an outstanding command? */
 	extern unsigned int fdc1772_fdc_int_done;
 
-	* Explicit! If the int done is 0 then 1 int to go */
+	/* Explicit! If the int done is 0 then 1 int to go */
 	return (fdc1772_fdc_int_done==0)?1:0;
 }
 
diff -Nru a/arch/arm/mach-footbridge/arch.c b/arch/arm/mach-footbridge/arch.c
--- a/arch/arm/mach-footbridge/arch.c	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/mach-footbridge/arch.c	Sun Apr 14 12:16:57 2002
@@ -41,10 +41,12 @@
 fixup_ebsa285(struct machine_desc *desc, struct param_struct *params,
 	      char **cmdline, struct meminfo *mi)
 {
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 	ORIG_X		 = params->u1.s.video_x;
 	ORIG_Y		 = params->u1.s.video_y;
 	ORIG_VIDEO_COLS  = params->u1.s.video_num_cols;
 	ORIG_VIDEO_LINES = params->u1.s.video_num_rows;
+#endif
 }
 
 MACHINE_START(EBSA285, "EBSA285")
diff -Nru a/arch/arm/mach-iop310/iq80310-time.c b/arch/arm/mach-iop310/iq80310-time.c
--- a/arch/arm/mach-iop310/iq80310-time.c	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/mach-iop310/iq80310-time.c	Sun Apr 14 12:16:59 2002
@@ -62,7 +62,7 @@
  */
 static unsigned long iq80310_gettimeoffset (void)
 {
-	unsigned long elapsed, usec, tmp1;
+	unsigned long elapsed, usec;
 	unsigned int stat1, stat2;
 
 	stat1 = *(volatile u8 *)IQ80310_INT_STAT;
diff -Nru a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,34 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+USE_STANDARD_AS_RULE := true
+
+O_TARGET		:= pxa.o
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj-  :=
+
+export-objs := generic.o irq.o dma.o sa1111.o
+
+# Common support (must be linked before board specific support)
+obj-y += generic.o irq.o dma.o
+obj-$(CONFIG_SA1111) += sa1111.o
+
+# Specific board support
+obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
+
+# Support for blinky lights
+leds-y := leds.o
+leds-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o
+leds-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o
+
+obj-$(CONFIG_LEDS) += $(leds-y)
+
+include $(TOPDIR)/Rules.make
diff -Nru a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/dma.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,131 @@
+/*
+ *  linux/arch/arm/mach-pxa/dma.c
+ *
+ *  PXA DMA registration and IRQ dispatching
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Nov 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+
+
+static struct dma_channel {
+	char *name;
+	void (*irq_handler)(int, void *, struct pt_regs *);
+	void *data;
+} dma_channels[16];
+
+
+int pxa_request_dma (char *name, pxa_dma_prio prio,
+			 void (*irq_handler)(int, void *, struct pt_regs *),
+		 	 void *data)
+{
+	unsigned long flags;
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name || !irq_handler)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	/* try grabbing a DMA channel with the requested priority */
+	for (i = prio; i < prio + (prio == DMA_PRIO_LOW) ? 8 : 4; i++) {
+		if (!dma_channels[i].name) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		/* requested prio group is full, try hier priorities */
+		for (i = prio-1; i >= 0; i--) {
+			if (!dma_channels[i].name) {
+				found = 1;
+				break;
+			}
+		}
+	}
+
+	if (found) {
+		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].data = data;
+	} else {
+		printk (KERN_WARNING "No more available DMA channels for %s\n", name);
+		i = -ENODEV;
+	}
+
+	local_irq_restore(flags);
+	return i;
+}
+
+void pxa_free_dma (int dma_ch)
+{
+	unsigned long flags;
+
+	if (!dma_channels[dma_ch].name) {
+		printk (KERN_CRIT __FUNCTION__
+			": trying to free channel %d which is already freed\n",
+			dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+	dma_channels[dma_ch].name = NULL;
+	local_irq_restore(flags);
+}
+
+static void dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int i, dint = DINT;
+
+	for (i = 0; i < 16; i++) {
+		if (dint & (1 << i)) {
+			struct dma_channel *channel = &dma_channels[i];
+			if (channel->name && channel->irq_handler) {
+				channel->irq_handler(i, channel->data, regs);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel:
+				 * let's clear the interrupts and disable it.
+				 */
+				printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);
+				DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
+			}
+		}
+	}
+}
+
+static int __init pxa_dma_init (void)
+{
+	int ret;
+
+	ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
+	if (ret)
+		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+	return ret;
+}
+
+__initcall(pxa_dma_init);
+
+EXPORT_SYMBOL(pxa_request_dma);
+EXPORT_SYMBOL(pxa_free_dma);
+
diff -Nru a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/generic.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,103 @@
+/*
+ *  linux/arch/arm/mach-pxa/generic.c
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * Code common to all PXA machines.
+ *
+ * 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.
+ *
+ * Since this file should be linked before any other machine specific file,
+ * the __initcall() here will be executed first.  This serves as default
+ * initialization stuff for PXA machines which can be overriden later if
+ * need be.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/mach/map.h>
+
+#include "generic.h"
+
+/*
+ * Return the current lclk requency in units of 10kHz
+ */
+unsigned int get_lclk_frequency_10khz(void)
+{
+	unsigned int l;
+
+	l = CCCR & 0x1f;
+
+	switch(l)
+	{
+		case 1:
+			return 9953;
+		case 2:
+			return 11796;
+		case 3:
+			return 13271;
+		case 4:
+			return 14746;
+		case 5:
+			return 16589;
+		case 0xf:
+			return 3320;
+		default:
+			return 0;
+	}
+}
+
+EXPORT_SYMBOL(get_lclk_frequency_10khz);
+
+/*
+ * Handy function to set GPIO alternate functions
+ */
+
+void pxa_gpio_mode(int gpio_mode)
+{
+	long flags;
+	int gpio = gpio_mode & GPIO_MD_MASK_NR;
+	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+	int gafr;
+
+	local_irq_save(flags);
+	if (gpio_mode & GPIO_MD_MASK_DIR)
+		GPDR(gpio) |= GPIO_bit(gpio);
+	else
+		GPDR(gpio) &= ~GPIO_bit(gpio);
+	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(pxa_gpio_mode);
+
+/*
+ * Note that 0xfffe0000-0xffffffff is reserved for the vector table and
+ * cache flush area.
+ */
+static struct map_desc standard_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+  { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
+  { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
+  { 0xfc000000, 0x40000000, 0x01400000, DOMAIN_IO, 0, 1, 0, 0 }, /* Devs */
+  { 0xfe000000, 0x44000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
+  { 0xff000000, 0x48000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Mem Ctl */
+  LAST_DESC
+};
+
+void __init pxa_map_io(void)
+{
+	iotable_init(standard_io_desc);
+}
diff -Nru a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/generic.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,19 @@
+/*
+ *  linux/arch/arm/mach-pxa/generic.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+extern void __init pxa_map_io(void);
+extern void __init pxa_init_irq(void);
+
+#define SET_BANK(__nr,__start,__size) \
+	mi->bank[__nr].start = (__start), \
+	mi->bank[__nr].size = (__size), \
+	mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
+
diff -Nru a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/idp.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,138 @@
+/*
+ *  linux/arch/arm/mach-pxa/idp.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
+ *
+ *  2001-09-13: Cliff Brake <cbrake@accelent.com>
+ *              Initial code
+ */
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "generic.h"
+
+#define PXA_IDP_REV02
+
+#ifndef PXA_IDP_REV02
+/* shadow registers for write only registers */
+unsigned int idp_cpld_led_control_shadow = 0x1;
+unsigned int idp_cpld_periph_pwr_shadow = 0xd;
+unsigned int ipd_cpld_cir_shadow = 0;
+unsigned int idp_cpld_kb_col_high_shadow = 0;
+unsigned int idp_cpld_kb_col_low_shadow = 0;
+unsigned int idp_cpld_pccard_en_shadow = 0xC3;
+unsigned int idp_cpld_gpioh_dir_shadow = 0;
+unsigned int idp_cpld_gpioh_value_shadow = 0;
+unsigned int idp_cpld_gpiol_dir_shadow = 0;
+unsigned int idp_cpld_gpiol_value_shadow = 0;
+
+/*
+ * enable all LCD signals -- they should still be on
+ * write protect flash
+ * enable all serial port transceivers
+ */
+
+unsigned int idp_control_port_shadow = ((0x7 << 21) | 		/* LCD power */
+					(0x1 << 19) |		/* disable flash write enable */
+					(0x7 << 9));		/* enable serial port transeivers */
+
+#endif
+
+static int __init idp_init(void)
+{
+	printk("idp_init()\n");
+	return 0;
+}
+
+__initcall(idp_init);
+
+static void __init idp_init_irq(void)
+{
+	pxa_init_irq();
+}
+
+static void __init
+fixup_idp(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+#ifdef PXA_IDP_REV02
+	SET_BANK (0, 0xa0000000, 64*1024*1024);
+#else
+	SET_BANK (0, 0xa0000000, 32*1024*1024);
+#endif
+	mi->nr_banks      = 1;
+#if 0
+	setup_ramdisk (1, 0, 0, 8192);
+	setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+}
+
+static struct map_desc idp_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+
+
+#ifndef PXA_IDP_REV02
+  { IDP_CTRL_PORT_BASE,
+    IDP_CTRL_PORT_PHYS,
+    IDP_CTRL_PORT_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+#endif
+
+  { IDP_IDE_BASE,
+    IDP_IDE_PHYS,
+    IDP_IDE_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+  { IDP_ETH_BASE,
+    IDP_ETH_PHYS,
+    IDP_ETH_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+  { IDP_COREVOLT_BASE,
+    IDP_COREVOLT_PHYS,
+    IDP_COREVOLT_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+  { IDP_CPLD_BASE,
+    IDP_CPLD_PHYS,
+    IDP_CPLD_SIZE,
+    DOMAIN_IO,
+    0, 1, 0, 0 },
+
+  LAST_DESC
+};
+
+static void __init idp_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(idp_io_desc);
+
+	set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
+}
+
+MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
+	MAINTAINER("Accelent Systems Inc.")
+	BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
+	FIXUP(fixup_idp)
+	MAPIO(idp_map_io)
+	INITIRQ(idp_init_irq)
+MACHINE_END
diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/irq.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,265 @@
+/*
+ *  linux/arch/arm/mach-pxa/irq.c
+ *
+ *  Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include "generic.h"
+
+
+/*
+ * This is for IRQs known as PXA_IRQ([8...31]).
+ */
+
+static void pxa_mask_irq(unsigned int irq)
+{
+	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+}
+
+static void pxa_unmask_irq(unsigned int irq)
+{
+	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+}
+
+static struct irqchip pxa_internal_chip = {
+	ack:		pxa_mask_irq,
+	mask:		pxa_mask_irq,
+	unmask:		pxa_unmask_irq,
+};
+
+/*
+ * PXA GPIO edge detection for IRQs:
+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+ * Use this instead of directly setting GRER/GFER.
+ */
+
+static int GPIO_IRQ_rising_edge[3];
+static int GPIO_IRQ_falling_edge[3];
+static int GPIO_IRQ_mask[3];
+
+static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+	int gpio, idx;
+
+	gpio = irq - ((irq >= IRQ_GPIO(2)) ? IRQ_GPIO(2) + 2 : IRQ_GPIO(0));
+
+	printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio);
+
+	pxa_gpio_mode(gpio | GPIO_IN);
+
+	if (type & __IRQT_RISEDGE) {
+		printk("rising ");
+		__set_bit (gpio, GPIO_IRQ_rising_edge);
+	} else
+		__clear_bit (gpio, GPIO_IRQ_rising_edge);
+
+	if (type & __IRQT_FALEDGE) {
+		printk("falling ");
+		__set_bit (gpio, GPIO_IRQ_falling_edge);
+	} else
+		__clear_bit (gpio, GPIO_IRQ_falling_edge);
+
+	printk("edges\n");
+
+	idx = gpio >> 5;
+	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+
+	return 0;
+}
+
+/*
+ * Since we can't actually physically mask edge triggered interrupts
+ * without the risk of missing transitions, we therefore logically mask
+ * them and defer their processing through tis function.
+ */
+
+static void pxa_manual_rerun(unsigned int irq)
+{
+	struct pt_regs regs;
+	memset(&regs, 0, sizeof(regs));
+	irq_desc[irq].handle(irq, &irq_desc[irq], &regs);
+}
+
+/*
+ * GPIO IRQs must be acknoledged.  This is for GPIO 0 and 1.
+ */
+
+static void pxa_ack_low_gpio(unsigned int irq)
+{
+	GEDR0 = (1 << (irq - IRQ_GPIO0));
+}
+
+static struct irqchip pxa_low_gpio_chip = {
+	ack:		pxa_ack_low_gpio,
+	mask:           pxa_mask_irq,
+	unmask:         pxa_unmask_irq,
+	rerun:          pxa_manual_rerun,
+	type:           pxa_gpio_irq_type,
+};
+
+/*
+ * Demux handler for GPIO 2-80 edge detect interrupts
+ */
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
+				   struct pt_regs *regs)
+{
+	unsigned int mask;
+	int loop;
+
+	do {
+		loop = 0;
+
+		mask = GEDR0 & ~3;
+		if (mask) {
+			GEDR0 = mask;
+			irq = IRQ_GPIO(2);
+			desc = irq_desc + irq;
+			mask >>= 2;
+			do {
+				if (mask & 1)
+					desc->handle(irq, desc, regs);
+				irq++;
+				desc++;
+				mask >>= 1;
+			} while (mask);
+			loop = 1;
+		}
+
+		mask = GEDR1;
+		if (mask) {
+			GEDR1 = mask;
+			irq = IRQ_GPIO(32);
+			desc = irq_desc + irq;
+			do {
+				if (mask & 1)
+					desc->handle(irq, desc, regs);
+				irq++;
+				desc++;
+				mask >>= 1;
+			} while (mask);
+			loop = 1;
+		}
+
+		mask = GEDR2;
+		if (mask) {
+			GEDR2 = mask;
+			irq = IRQ_GPIO(64);
+			desc = irq_desc + irq;
+			do {
+				if (mask & 1)
+					desc->handle(irq, desc, regs);
+				irq++;
+				desc++;
+				mask >>= 1;
+			} while (mask);
+			loop = 1;
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(unsigned int irq)
+{
+	int gpio = irq - IRQ_GPIO(2) + 2;
+	GEDR(gpio) = GPIO_bit(gpio);
+}
+
+static void pxa_mask_muxed_gpio(unsigned int irq)
+{
+	int gpio = irq - IRQ_GPIO(2) + 2;
+	__clear_bit(gpio, GPIO_IRQ_mask);
+	GRER(gpio) &= ~GPIO_bit(gpio);
+	GFER(gpio) &= ~GPIO_bit(gpio);
+}
+
+static void pxa_unmask_muxed_gpio(unsigned int irq)
+{
+	int gpio = irq - IRQ_GPIO(2) + 2;
+	int idx = gpio >> 5;
+	__set_bit(gpio, GPIO_IRQ_mask);
+	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
+	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
+}
+
+static struct irqchip pxa_muxed_gpio_chip = {
+	ack:		pxa_ack_muxed_gpio,
+	mask:		pxa_mask_muxed_gpio,
+	unmask:		pxa_unmask_muxed_gpio,
+	rerun:		pxa_manual_rerun,
+	type:		pxa_gpio_irq_type,
+};
+
+
+void __init pxa_init_irq(void)
+{
+	int irq;
+
+	/* disable all IRQs */
+	ICMR = 0;
+
+	/* all IRQs are IRQ, not FIQ */
+	ICLR = 0;
+
+	/* clear all GPIO edge detects */
+	GFER0 = GFER1 = GFER2 = 0;
+	GRER0 = GRER1 = GRER2 = 0;
+	GEDR0 = GEDR0;
+	GEDR1 = GEDR1;
+	GEDR2 = GEDR2;
+
+	/* only unmasked interrupts kick us out of idle */
+	ICCR = 1;
+
+	/* GPIO 0 and 1 must have their mask bit always set */
+	GPIO_IRQ_mask[0] = 3;
+
+	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
+		set_irq_chip(irq, &pxa_low_gpio_chip);
+		set_irq_handler(irq, do_edge_IRQ);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	for (irq = PXA_IRQ(11); irq <= PXA_IRQ(31); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+	/* Those are reserved */
+	set_irq_flags(PXA_IRQ(15), 0);
+	set_irq_flags(PXA_IRQ(16), 0);
+
+	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
+		set_irq_chip(irq, &pxa_muxed_gpio_chip);
+		set_irq_handler(irq, do_edge_IRQ);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Install handler for GPIO 2-80 edge detect interrupts */
+	set_irq_chip(IRQ_GPIO_2_80, &pxa_internal_chip);
+	set_irq_chained_handler(IRQ_GPIO_2_80, pxa_gpio_demux_handler);
+
+	/*
+	 * We generally don't want the LCD IRQ being
+	 * enabled as soon as we request it.
+	 */
+	set_irq_flags(IRQ_LCD, IRQF_VALID | IRQF_NOAUTOEN);
+}
diff -Nru a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/leds-idp.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,112 @@
+/*
+ * linux/arch/arm/mach-pxa/leds-idp.c
+ *
+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
+ *
+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
+ *
+ * Original (leds-footbridge.c) by Russell King
+ *
+ * Macros for actual LED manipulation should be in machine specific
+ * files in this 'mach' directory.
+ */
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void idp_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
+		led_state = LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= IDP_HB_LED;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= IDP_BUSY_LED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~IDP_BUSY_LED;
+		break;
+#endif
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~IDP_HB_LED;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= IDP_HB_LED;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~IDP_BUSY_LED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= IDP_BUSY_LED;
+		break;
+
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+		IDP_WRITE_LEDS(hw_led_state);
+
+	local_irq_restore(flags);
+}
diff -Nru a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/leds-lubbock.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/arm/mach-pxa/leds-lubbock.c
+ *
+ * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
+ *
+ * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
+ *
+ * Original (leds-footbridge.c) by Russell King
+ *
+ * See leds.h for bit definitions.  The first version defines D28 on the
+ * Lubbock dev board as the heartbeat, and D27 as the Sys_busy led.
+ * There's plenty more if you're interested in adding them :)
+ */
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED	1
+#define LED_STATE_CLAIMED	2
+
+static unsigned int led_state;
+static unsigned int hw_led_state;
+
+void lubbock_leds_event(led_event_t evt)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (evt) {
+	case led_start:
+		hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
+		led_state = LED_STATE_ENABLED;
+		break;
+
+	case led_stop:
+		led_state &= ~LED_STATE_ENABLED;
+		break;
+
+	case led_claim:
+		led_state |= LED_STATE_CLAIMED;
+		hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
+		break;
+
+	case led_release:
+		led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state = HEARTBEAT_LED | SYS_BUSY_LED;
+		break;
+
+#ifdef CONFIG_LEDS_TIMER
+	case led_timer:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state ^= HEARTBEAT_LED;
+		break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+	case led_idle_start:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state |= SYS_BUSY_LED;
+		break;
+
+	case led_idle_end:
+		if (!(led_state & LED_STATE_CLAIMED))
+			hw_led_state &= ~SYS_BUSY_LED;
+		break;
+#endif
+
+	case led_halted:
+		break;
+
+	case led_green_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~HEARTBEAT_LED;
+		break;
+
+	case led_green_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= HEARTBEAT_LED;
+		break;
+
+	case led_amber_on:
+		break;
+
+	case led_amber_off:
+		break;
+
+	case led_red_on:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state &= ~SYS_BUSY_LED;
+		break;
+
+	case led_red_off:
+		if (led_state & LED_STATE_CLAIMED)
+			hw_led_state |= SYS_BUSY_LED;
+		break;
+
+	default:
+		break;
+	}
+
+	if  (led_state & LED_STATE_ENABLED)
+	{
+		switch (hw_led_state) {
+		case 0: // all on
+			HEARTBEAT_LED_ON;
+			SYS_BUSY_LED_ON;
+			break;
+		case 1: // turn off heartbeat, status on:
+			HEARTBEAT_LED_OFF;
+			SYS_BUSY_LED_ON;
+			break;
+		case 2: // status off, heartbeat on:
+			HEARTBEAT_LED_ON;
+			SYS_BUSY_LED_OFF;
+			break;
+		case 3: // turn them both off...
+			HEARTBEAT_LED_OFF;
+			SYS_BUSY_LED_OFF;
+			break;
+		default:
+			break;
+		}
+	}
+	local_irq_restore(flags);
+}
diff -Nru a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/leds.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/arm/mach-pxa/leds.c
+ *
+ * xscale LEDs dispatcher
+ *
+ * Copyright (C) 2001 Nicolas Pitre
+ *
+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include "leds.h"
+
+static int __init
+pxa_leds_init(void)
+{
+	if (machine_is_lubbock())
+		leds_event = lubbock_leds_event;
+	if (machine_is_pxa_idp())
+		leds_event = idp_leds_event;
+
+	leds_event(led_start);
+	return 0;
+}
+
+__initcall(pxa_leds_init);
diff -Nru a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/leds.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,11 @@
+/*
+ * include/asm-arm/arch-pxa/leds.h
+ *
+ * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
+ *
+ * blinky lights for various PXA-based systems:
+ *
+ */
+
+extern void lubbock_leds_event(led_event_t evt);
+extern void idp_leds_event(led_event_t evt);
diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-pxa/lubbock.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,166 @@
+/*
+ *  linux/arch/arm/mach-pxa/lubbock.c
+ *
+ *  Support for the Intel DBPXA250 Development Platform.
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/irq.h>
+#include <asm/hardware/sa1111.h>
+
+#include "generic.h"
+#include "sa1111.h"
+
+static void lubbock_ack_irq(unsigned int irq)
+{
+	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
+}
+
+static void lubbock_mask_irq(unsigned int irq)
+{
+	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	LUB_IRQ_MASK_EN &= ~(1 << lubbock_irq);
+}
+
+static void lubbock_unmask_irq(unsigned int irq)
+{
+	int lubbock_irq = (irq - LUBBOCK_IRQ(0));
+	LUB_IRQ_MASK_EN |= (1 << lubbock_irq);
+}
+
+static struct irqchip lubbock_irq_chip = {
+	ack:		lubbock_ack_irq,
+	mask:		lubbock_mask_irq,
+	unmask:		lubbock_unmask_irq,
+};
+
+void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
+			 struct pt_regs *regs)
+{
+	unsigned int enabled, pending;
+
+	/* get active pending irq mask */
+	enabled = LUB_IRQ_MASK_EN & 0x003f;
+	pending = LUB_IRQ_SET_CLR & enabled;
+
+	do {
+//printk("%s a: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 );
+		/* clear our parent irq */
+		GEDR(0) = GPIO_bit(0);
+
+		/* process them */
+		irq = LUBBOCK_IRQ(0);
+		desc = irq_desc + irq;
+		do {
+			if (pending & 1)
+				desc->handle(irq, desc, regs);
+			irq++;
+			desc++;
+			pending >>= 1;
+		} while (pending);
+//printk("%s b: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 );
+		enabled = LUB_IRQ_MASK_EN & 0x003f;
+		pending = LUB_IRQ_SET_CLR & enabled;
+	} while (pending);
+}
+
+static void __init lubbock_init_irq(void)
+{
+	int irq;
+
+	pxa_init_irq();
+
+	/* setup extra lubbock irqs */
+	for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_IRQ(5); irq++) {
+		set_irq_chip(irq, &lubbock_irq_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
+	set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
+}
+
+static int __init lubbock_init(void)
+{
+	int ret;
+
+	ret = sa1111_probe(LUBBOCK_SA1111_BASE);
+	if (ret)
+		return ret;
+	sa1111_wake();
+	sa1111_init_irq(LUBBOCK_SA1111_IRQ);
+	return 0;
+}
+
+__initcall(lubbock_init);
+
+static void __init
+fixup_lubbock(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline, struct meminfo *mi)
+{
+	SET_BANK (0, 0xa0000000, 64*1024*1024);
+	mi->nr_banks      = 1;
+#if 0
+	setup_ramdisk (1, 0, 0, 8192);
+	setup_initrd (__phys_to_virt(0xa1000000), 4*1024*1024);
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+#endif
+}
+
+static struct map_desc lubbock_io_desc[] __initdata = {
+ /* virtual     physical    length      domain     r  w  c  b */
+  { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+  { 0xf1000000, 0x0c000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 IO */
+  { 0xf1100000, 0x0e000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN91C96 Attr */
+  { 0xf4000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
+  LAST_DESC
+};
+
+static void __init lubbock_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(lubbock_io_desc);
+
+	/* This enables the BTUART */
+	CKEN |= CKEN7_BTUART;
+	pxa_gpio_mode(GPIO42_BTRXD_MD);
+	pxa_gpio_mode(GPIO43_BTTXD_MD);
+	pxa_gpio_mode(GPIO44_BTCTS_MD);
+	pxa_gpio_mode(GPIO45_BTRTS_MD);
+
+	/* This is for the SMC chip select */
+	pxa_gpio_mode(GPIO79_nCS_3_MD);
+}
+
+MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform")
+	MAINTAINER("MontaVista Software Inc.")
+	BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
+	FIXUP(fixup_lubbock)
+	MAPIO(lubbock_map_io)
+	INITIRQ(lubbock_init_irq)
+MACHINE_END
diff -Nru a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
--- a/arch/arm/mach-sa1100/badge4.c	Sun Apr 14 12:16:55 2002
+++ b/arch/arm/mach-sa1100/badge4.c	Sun Apr 14 12:16:55 2002
@@ -187,9 +187,9 @@
 
 static struct map_desc badge4_io_desc[] __initdata = {
   /*  virtual    physical    length      domain     r w c b		   */
-  {0xf1000000, 0x08000000, 0x00100000, DOMAIN_IO, 1,1,0,0},/* SRAM  bank 1 */
-  {0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 1,1,0,0},/* SRAM  bank 2 */
-  {0xf4000000, 0x48000000, 0x00100000, DOMAIN_IO, 1,1,0,0},/* SA-1111      */
+  {0xf1000000, 0x08000000, 0x00100000, DOMAIN_IO, 0,1,0,0},/* SRAM  bank 1 */
+  {0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 0,1,0,0},/* SRAM  bank 2 */
+  {0xf4000000, 0x48000000, 0x00100000, DOMAIN_IO, 0,1,0,0},/* SA-1111      */
   LAST_DESC
 };
 
diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
--- a/arch/arm/mach-sa1100/generic.c	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/mach-sa1100/generic.c	Sun Apr 14 12:16:56 2002
@@ -162,3 +162,47 @@
 {
 	iotable_init(standard_io_desc);
 }
+
+/*
+ * Disable the memory bus request/grant signals on the SA1110 to
+ * ensure that we don't receive spurious memory requests.  We set
+ * the MBGNT signal false to ensure the SA1111 doesn't own the
+ * SDRAM bus.
+ */
+void __init sa1110_mb_disable(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	
+	PGSR &= ~GPIO_MBGNT;
+	GPCR = GPIO_MBGNT;
+	GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+
+	GAFR &= ~(GPIO_MBGNT | GPIO_MBREQ);
+
+	local_irq_restore(flags);
+}
+
+/*
+ * If the system is going to use the SA-1111 DMA engines, set up
+ * the memory bus request/grant pins.
+ */
+void __init sa1110_mb_enable(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	PGSR &= ~GPIO_MBGNT;
+	GPCR = GPIO_MBGNT;
+	GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+
+	GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
+	TUCR |= TUCR_MR;
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(sa1111_wake);
+EXPORT_SYMBOL(sa1111_doze);
diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
--- a/arch/arm/mach-sa1100/generic.h	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/mach-sa1100/generic.h	Sun Apr 14 12:16:59 2002
@@ -15,3 +15,5 @@
 extern void (*sa1100fb_backlight_power)(int on);
 extern void (*sa1100fb_lcd_power)(int on);
 
+extern void sa1110_mb_enable(void);
+extern void sa1110_mb_disable(void);
diff -Nru a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
--- a/arch/arm/mach-sa1100/h3600.c	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/mach-sa1100/h3600.c	Sun Apr 14 12:16:56 2002
@@ -399,24 +399,6 @@
 	return ret;
 }
 
-static void h3600_dcd_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct uart_info *info = dev_id;
-	/* Note: should only call this if something has changed */
-	spin_lock_irq(&info->lock);
-	uart_handle_dcd_change(info, !(GPLR & GPIO_H3600_COM_DCD));
-	spin_unlock_irq(&info->lock);
-}
-
-static void h3600_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct uart_info *info = dev_id;
-	/* Note: should only call this if something has changed */
-	spin_lock_irq(&info->lock);
-	uart_handle_cts_change(info, !(GPLR & GPIO_H3600_COM_CTS));
-	spin_unlock_irq(&info->lock);
-}
-
 static void h3600_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 {
 	if (port->mapbase == _Ser2UTCR0) {
@@ -444,47 +426,11 @@
 	return err;
 }
 
-static int h3600_uart_open(struct uart_port *port, struct uart_info *info)
-{
-	int ret = 0;
-
-	if (port->mapbase == _Ser2UTCR0) {
-		Ser2UTCR4 = UTCR4_HSE;
-		Ser2HSCR0 = 0;
-		Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR |
-			    HSSR0_RAB | HSSR0_FRE;
-	} else if (port->mapbase == _Ser3UTCR0) {
-		set_GPIO_IRQ_edge(GPIO_H3600_COM_DCD|GPIO_H3600_COM_CTS,
-				  GPIO_BOTH_EDGES);
-
-		ret = request_irq(IRQ_GPIO_H3600_COM_DCD, h3600_dcd_intr,
-				  0, "RS232 DCD", info);
-		if (ret)
-			return ret;
-
-		ret = request_irq(IRQ_GPIO_H3600_COM_CTS, h3600_cts_intr,
-				  0, "RS232 CTS", info);
-		if (ret)
-			free_irq(IRQ_GPIO_H3600_COM_DCD, info);
-	}
-	return ret;
-}
-
-static void h3600_uart_close(struct uart_port *port, struct uart_info *info)
-{
-	if (port->mapbase == _Ser3UTCR0) {
-		free_irq(IRQ_GPIO_H3600_COM_DCD, info);
-		free_irq(IRQ_GPIO_H3600_COM_CTS, info);
-	}
-}
-
 static struct sa1100_port_fns h3600_port_fns __initdata = {
 	set_mctrl:	h3600_uart_set_mctrl,
 	get_mctrl:	h3600_uart_get_mctrl,
 	pm:		h3600_uart_pm,
 	set_wake:	h3600_uart_set_wake,
-	open:		h3600_uart_open,
-	close:		h3600_uart_close,
 };
 
 static struct map_desc h3600_io_desc[] __initdata = {
diff -Nru a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c
--- a/arch/arm/mach-sa1100/leds.c	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/mach-sa1100/leds.c	Sun Apr 14 12:16:56 2002
@@ -17,6 +17,8 @@
 {
 	if (machine_is_assabet())
 		leds_event = assabet_leds_event;
+ 	if (machine_is_consus())
+ 	        leds_event = consus_leds_event;
 	if (machine_is_brutus())
 		leds_event = brutus_leds_event;
 	if (machine_is_cerf())
diff -Nru a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h
--- a/arch/arm/mach-sa1100/leds.h	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/mach-sa1100/leds.h	Sun Apr 14 12:16:56 2002
@@ -1,4 +1,5 @@
 extern void assabet_leds_event(led_event_t evt);
+extern void consus_leds_event(led_event_t evt);
 extern void brutus_leds_event(led_event_t evt);
 extern void cerf_leds_event(led_event_t evt);
 extern void flexanet_leds_event(led_event_t evt);
diff -Nru a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c
--- a/arch/arm/mach-sa1100/sa1111.c	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/mach-sa1100/sa1111.c	Sun Apr 14 12:16:57 2002
@@ -367,50 +367,6 @@
 	SBI_SMCR = smcr;
 }
 
-/*
- * Disable the memory bus request/grant signals on the SA1110 to
- * ensure that we don't receive spurious memory requests.  We set
- * the MBGNT signal false to ensure the SA1111 doesn't own the
- * SDRAM bus.
- */
-void __init sa1110_mb_disable(void)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	
-	PGSR &= ~GPIO_MBGNT;
-	GPCR = GPIO_MBGNT;
-	GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
-
-	GAFR &= ~(GPIO_MBGNT | GPIO_MBREQ);
-
-	local_irq_restore(flags);
-}
-
-/*
- * If the system is going to use the SA-1111 DMA engines, set up
- * the memory bus request/grant pins.
- */
-void __init sa1110_mb_enable(void)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	PGSR &= ~GPIO_MBGNT;
-	GPCR = GPIO_MBGNT;
-	GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
-
-	GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
-	TUCR |= TUCR_MR;
-
-	local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(sa1111_wake);
-EXPORT_SYMBOL(sa1111_doze);
-
 /* According to the "Intel StrongARM SA-1111 Microprocessor Companion
  * Chip Specification Update" (June 2000), erratum #7, there is a
  * significant bug in Serial Audio Controller DMA. If the SAC is
diff -Nru a/arch/arm/mach-sa1100/sa1111.h b/arch/arm/mach-sa1100/sa1111.h
--- a/arch/arm/mach-sa1100/sa1111.h	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/mach-sa1100/sa1111.h	Sun Apr 14 12:16:58 2002
@@ -3,12 +3,6 @@
  */
 
 /*
- * These two don't really belong in here.
- */
-extern void sa1110_mb_enable(void);
-extern void sa1110_mb_disable(void);
-
-/*
  * Probe for a SA1111 chip.
  */
 extern int sa1111_probe(unsigned long phys);
@@ -27,8 +21,4 @@
  * Configure the SA1111 shared memory controller.
  */
 extern void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency);
-
-
 extern void sa1111_init_irq(int irq_nr);
-extern void sa1111_IRQ_demux(int irq, void *dev_id, struct pt_regs *regs);
-
diff -Nru a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
--- a/arch/arm/mm/fault-armv.c	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/mm/fault-armv.c	Sun Apr 14 12:16:56 2002
@@ -243,10 +243,8 @@
 	struct page *page = pte_page(pte);
 
 	if (VALID_PAGE(page) && page->mapping) {
-		if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
-			unsigned long kvirt = (unsigned long)page_address(page);
-			cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
-		}
+		if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+			__flush_dcache_page(page);
 
 		make_coherent(vma, addr, page);
 	}
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	Sun Apr 14 12:16:55 2002
+++ b/arch/arm/mm/init.c	Sun Apr 14 12:16:55 2002
@@ -548,7 +548,7 @@
 	}
 
 	if (size && s)
-		printk("Freeing %s memory: %dK\n", s, size);
+		printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
 }
 
 /*
diff -Nru a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
--- a/arch/arm/mm/mm-armv.c	Sun Apr 14 12:16:55 2002
+++ b/arch/arm/mm/mm-armv.c	Sun Apr 14 12:16:55 2002
@@ -60,10 +60,6 @@
 
 #define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
 
-#define clean_cache_area(start,size) \
-	cpu_cache_clean_invalidate_range((unsigned long)start, ((unsigned long)start) + size, 0);
-
-
 /*
  * need to get a 16k page for level 1
  */
@@ -114,10 +110,7 @@
 	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
 		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
 
-	/*
-	 * FIXME: this should not be necessary
-	 */
-	clean_cache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
 
 	return new_pgd;
 
diff -Nru a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
--- a/arch/arm/mm/proc-arm1020.S	Sun Apr 14 12:16:55 2002
+++ b/arch/arm/mm/proc-arm1020.S	Sun Apr 14 12:16:55 2002
@@ -21,6 +21,8 @@
  *
  * These are the low level assembler for performing cache and TLB
  * functions on the arm1020.
+ *
+ *  CONFIG_CPU_ARM1020_CPU_IDLE -> nohlt
  */
 #include <linux/linkage.h>
 #include <linux/config.h>
@@ -107,10 +109,6 @@
 	.align	5
 ENTRY(cpu_arm1020_do_idle)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */
@@ -128,7 +126,7 @@
 ENTRY(cpu_arm1020_cache_clean_invalidate_all)
 	mov	r2, #1
 cpu_arm1020_cache_clean_invalidate_all_r2:
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, ip, c7, c10, 4
 
 	mov	r1, #0xf			@ 16 segments
@@ -137,9 +135,6 @@
 	orr	ip, ip, r1, LSL #5		@ shift in/up index
 	mcr	p15, 0, ip, c7, c14, 2		@ Clean & Inval DCache entry
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB 
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	ip, ip
-#endif
 	subs	r3, r3, #1
 	cmp	r3, #0
 	bge	2b				@ entries 3F to 0
@@ -147,16 +142,11 @@
 	cmp	r1, #0
 	bge	1b				@ segments 7 to 0
 #endif
-        
-#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	teq	r2, #0
 	mcrne	p15, 0, ip, c7, c5, 0		@ invalidate I cache
 #endif
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	ip, ip
-	mov	ip, ip
-#endif
 	mov	pc, lr
 
 /*
@@ -175,60 +165,21 @@
 	cmp	r3, #MAX_AREA_SIZE
 	bgt	cpu_arm1020_cache_clean_invalidate_all_r2
 	mcr	p15, 0, r3, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
 	add	r0, r0, #DCACHELINESIZE
 	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-#endif
 	add	r0, r0, #DCACHELINESIZE
 	cmp	r0, r1
 	blt	1b
 #endif
 
-#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	teq	r2, #0
 	movne	r0, #0
 	mcrne	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
-#endif
-	mov	pc, lr
-
-/*
- * cpu_arm1020_flush_ram_page(page)
- *
- * clean and invalidate all cache lines associated with this area of memory
- *
- * page: page to clean and invalidate
- */
-	.align	5
-ENTRY(cpu_arm1020_flush_ram_page)
-	mcr	p15, 0, r1, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-	mov	r0, #0
-
-#endif
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
 #endif
 	mov	pc, lr
 
@@ -247,41 +198,25 @@
  */
 	.align	5
 ENTRY(cpu_arm1020_dcache_invalidate_range)
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	/* D cache are on */
 	tst	r0, #DCACHELINESIZE - 1
 	bic	r0, r0, #DCACHELINESIZE - 1
 	mcrne	p15, 0, r0, c7, c10, 4
 	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry at start
 	mcrne	p15, 0, r0, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	tst	r1, #DCACHELINESIZE - 1
 	mcrne	p15, 0, r1, c7, c10, 4
 	mcrne	p15, 0, r1, c7, c10, 1		@ clean D entry at end
 	mcrne	p15, 0, r1, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r1, r1
-	mov	r1, r1
-	mov	r1, r1
-#endif
         
 1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-#endif
 	add	r0, r0, #DCACHELINESIZE
 	cmp	r0, r1
 	blt	1b
 #else
 	/* D cache off, but still drain the write buffer */
 	mcr	p15, 0, r0, c7, c10, 4		@ Drain write buffer
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 #endif
 	mov	pc, lr
 
@@ -302,24 +237,16 @@
 	cmp	r3, #MAX_AREA_SIZE
 	bgt	cpu_arm1020_cache_clean_invalidate_all_r2
 	mcr	p15, 0, r3, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
 	add	r0, r0, #DCACHELINESIZE
 	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
 	mcr	p15, 0, r3, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-#endif
 	add	r0, r0, #DCACHELINESIZE
 	cmp	r0, r1
 	blt	1b
 #endif
-
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	mov	pc, lr
 
 /*
@@ -339,26 +266,16 @@
 ENTRY(cpu_arm1020_dcache_clean_page)
 	mov	r1, #PAGESIZE
 	mcr	p15, 0, r0, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  (drain is done by TLB fns)
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-#endif
 	add	r0, r0, #DCACHELINESIZE
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-#endif
 	add	r0, r0, #DCACHELINESIZE
 	subs	r1, r1, #2 * DCACHELINESIZE
 	bhi	1b
 #endif
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	mov	pc, lr
 
 /*
@@ -373,17 +290,13 @@
 ENTRY(cpu_arm1020_dcache_clean_entry)
 	mov	r1, #0
 	mcr	p15, 0, r1, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r0, c7, c10, 1		@ clean single D entry
 	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
 #endif
-#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	mcr	p15, 0, r1, c7, c5, 1		@ invalidate I entry
 #endif
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r1, r1
-	mov	r1, r1
-#endif
 	mov	pc, lr
 
 /* ================================ I-CACHE =============================== */
@@ -399,25 +312,18 @@
 	.align	5
 ENTRY(cpu_arm1020_icache_invalidate_range)
 1:	mcr	p15, 0, r0, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 	add	r0, r0, #DCACHELINESIZE
 	mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 #endif
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-#endif
 	add	r0, r0, #DCACHELINESIZE
 	cmp	r0, r1
 	blo	1b
 ENTRY(cpu_arm1020_icache_invalidate_page)
 	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	mov	pc, lr
 
 /* =============================== PageTable ============================== */
@@ -431,7 +337,7 @@
  */
 	.align	5
 ENTRY(cpu_arm1020_set_pgd)
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r3, c7, c10, 4
 	mov	r1, #0xF			@ 16 segments
 1:	mov	r3, #0x3F			@ 64 entries
@@ -440,9 +346,6 @@
 	mcr	p15, 0, ip, c7, c14, 2		@ Clean & Inval DCache entry
 	mov	ip, #0
 	mcr	p15, 0, ip, c7, c10, 4
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	ip, ip
-#endif
 	subs	r3, r3, #1
 	cmp	r3, #0
 	bge	2b				@ entries 3F to 0
@@ -452,16 +355,12 @@
 
 #endif
 	mov	r1, #0
-#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	mcr	p15, 0, r1, c7, c5, 0		@ invalidate I cache
 #endif
 	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
 	mcr	p15, 0, r0, c2, c0, 0		@ load page table pointer
 	mcr	p15, 0, r1, c8, c7, 0		@ invalidate I & D TLBs
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	ip, ip
-	mov	ip, ip
-#endif
 	mov	pc, lr
         
 /*
@@ -475,21 +374,17 @@
  */
 	.align	5
 ENTRY(cpu_arm1020_set_pmd)
-#ifdef CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r2, r1, #0x0a			@ C & Section
 	tst	r2, #0x0b
 	biceq	r1, r1, #4			@ clear bufferable bit
 #endif
 	str	r1, [r0]
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r0, c7, c10, 4
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry  (drain is done by TLB fns)
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	mov	pc, lr
 
 /*
@@ -518,22 +413,18 @@
 	tst	r1, #LPTE_PRESENT | LPTE_YOUNG	@ Present and Young?
 	movne	r2, #0
 
-#ifdef CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r3, r1, #0x0a			@ C & small page?
 	tst	r3, #0x0b
 	biceq	r2, r2, #4
 #endif
 	str	r2, [r0]			@ hardware version
 	mov	r0, r0
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	mcr	p15, 0, r0, c7, c10, 4
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
-	mov	r0, r0
-	mov	r0, r0
-#endif
 	mov	pc, lr
 
 
@@ -541,24 +432,21 @@
 	.asciz	"ARM/VLSI"
 ENTRY(cpu_arm1020_name)
 	.ascii	"Arm1020"
-#if defined(CONFIG_CPU_ARM1020_CPU_IDLE)
-	.ascii	"s"
-#endif
-#if defined(CONFIG_CPU_ARM1020_I_CACHE_ON)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	.ascii	"i"
 #endif
-#if defined(CONFIG_CPU_ARM1020_D_CACHE_ON)
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	.ascii	"d"
-#if defined(CONFIG_CPU_ARM1020_FORCE_WRITE_THROUGH)
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	.ascii	"(wt)"
 #else
 	.ascii	"(wb)"
 #endif
 #endif
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+#ifndef CONFIG_CPU_BPREDICT_DISABLE
 	.ascii	"B"
 #endif
-#ifdef CONFIG_CPU_ARM1020_ROUND_ROBIN
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	.ascii	"RR"
 #endif
 	.ascii	"\0"
@@ -588,16 +476,16 @@
 	orr	r0, r0, #0x0031 		@ ..........DP...M
 	orr	r0, r0, #0x0100 		@ .......S........
 
-#ifdef CONFIG_CPU_ARM1020_ROUND_ROBIN
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000 		@ .R..............
 #endif
-#ifdef CONFIG_CPU_ARM1020_BRANCH_PREDICTION
+#ifndef CONFIG_CPU_BPREDICT_DISABLE
 	orr	r0, r0, #0x0800 		@ ....Z...........
 #endif
-#ifdef CONFIG_CPU_ARM1020_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	orr	r0, r0, #0x0004 		@ Enable D cache
 #endif
-#ifdef CONFIG_CPU_ARM1020_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	orr	r0, r0, #0x1000 		@ I Cache on
 #endif
 	mov	pc, lr
@@ -620,7 +508,6 @@
 	/* cache */
 	.word	cpu_arm1020_cache_clean_invalidate_all
 	.word	cpu_arm1020_cache_clean_invalidate_range
-	.word	cpu_arm1020_flush_ram_page
 
 	/* dcache */
 	.word	cpu_arm1020_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S
--- a/arch/arm/mm/proc-arm6,7.S	Sun Apr 14 12:16:59 2002
+++ b/arch/arm/mm/proc-arm6,7.S	Sun Apr 14 12:16:59 2002
@@ -43,8 +43,6 @@
 ENTRY(cpu_arm7_dcache_clean_page)
 ENTRY(cpu_arm6_dcache_clean_entry)
 ENTRY(cpu_arm7_dcache_clean_entry)
-ENTRY(cpu_arm6_flush_ram_page)
-ENTRY(cpu_arm7_flush_ram_page)
 		mov	pc, lr
 
 /*
@@ -358,7 +356,6 @@
 		/* cache */
 		.word	cpu_arm6_cache_clean_invalidate_all
 		.word	cpu_arm6_cache_clean_invalidate_range
-		.word	cpu_arm6_flush_ram_page
 
 		/* dcache */
 		.word	cpu_arm6_dcache_invalidate_range
@@ -393,7 +390,6 @@
 		/* cache */
 		.word	cpu_arm7_cache_clean_invalidate_all
 		.word	cpu_arm7_cache_clean_invalidate_range
-		.word	cpu_arm7_flush_ram_page
 
 		/* dcache */
 		.word	cpu_arm7_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
--- a/arch/arm/mm/proc-arm720.S	Sun Apr 14 12:16:55 2002
+++ b/arch/arm/mm/proc-arm720.S	Sun Apr 14 12:16:55 2002
@@ -63,7 +63,6 @@
 ENTRY(cpu_arm720_dcache_clean_range)
 ENTRY(cpu_arm720_dcache_clean_page)
 ENTRY(cpu_arm720_dcache_clean_entry)
-ENTRY(cpu_arm720_flush_ram_page)
 		mov	pc, lr
 
 /*
@@ -211,7 +210,6 @@
 		/* cache */
 		.word	cpu_arm720_cache_clean_invalidate_all
 		.word	cpu_arm720_cache_clean_invalidate_range
-		.word	cpu_arm720_flush_ram_page
 
 		/* dcache */
 		.word	cpu_arm720_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
--- a/arch/arm/mm/proc-arm920.S	Sun Apr 14 12:16:54 2002
+++ b/arch/arm/mm/proc-arm920.S	Sun Apr 14 12:16:54 2002
@@ -21,6 +21,8 @@
  *
  * These are the low level assembler for performing cache and TLB
  * functions on the arm920.
+ *
+ *  CONFIG_CPU_ARM920_CPU_IDLE -> nohlt
  */
 #include <linux/linkage.h>
 #include <linux/config.h>
@@ -106,9 +108,7 @@
  */
 	.align	5
 ENTRY(cpu_arm920_do_idle)
-#if defined(CONFIG_CPU_ARM920_CPU_IDLE)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-#endif
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */
@@ -127,7 +127,7 @@
 	mov	r2, #1
 cpu_arm920_cache_clean_invalidate_all_r2:
 	mov	ip, #0
-#ifdef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 /*
@@ -165,7 +165,7 @@
 	cmp	r3, #MAX_AREA_SIZE
 	bgt	cpu_arm920_cache_clean_invalidate_all_r2
 1:	teq	r2, #0
-#ifdef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
 	add	r0, r0, #DCACHELINESIZE
@@ -186,32 +186,6 @@
 	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/*
- * cpu_arm920_flush_ram_page(page)
- *
- * clean and invalidate all cache lines associated with this area of memory
- *
- * page: page to clean and invalidate
- */
-	.align	5
-ENTRY(cpu_arm920_flush_ram_page)
-	mov	r1, #PAGESIZE
-#ifdef CONFIG_CPU_ARM920_WRITETHROUGH
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-#else
-1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-#endif
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
 /* ================================ D-CACHE =============================== */
 
 /*
@@ -227,7 +201,7 @@
  */
 	.align	5
 ENTRY(cpu_arm920_dcache_invalidate_range)
-#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	tst	r0, #DCACHELINESIZE - 1
 	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
 	tst	r1, #DCACHELINESIZE - 1
@@ -253,7 +227,7 @@
  */
 	.align	5
 ENTRY(cpu_arm920_dcache_clean_range)
-#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	bic	r0, r0, #DCACHELINESIZE - 1
 	sub	r1, r1, r0
 	cmp	r1, #MAX_AREA_SIZE
@@ -286,7 +260,7 @@
  */
 	.align	5
 ENTRY(cpu_arm920_dcache_clean_page)
-#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mov	r1, #PAGESIZE
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #DCACHELINESIZE
@@ -307,7 +281,7 @@
  */
 	.align	5
 ENTRY(cpu_arm920_dcache_clean_entry)
-#ifndef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
@@ -370,7 +344,7 @@
 	.align	5
 ENTRY(cpu_arm920_set_pgd)
 	mov	ip, #0
-#ifdef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	/* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
@@ -403,7 +377,7 @@
  */
 	.align	5
 ENTRY(cpu_arm920_set_pmd)
-#ifdef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r2, r1, #0x0a			@ C & Section
 	tst	r2, #0x0b
 	biceq	r1, r1, #4			@ clear bufferable bit
@@ -439,7 +413,7 @@
 	tst	r1, #LPTE_PRESENT | LPTE_YOUNG	@ Present and Young?
 	movne	r2, #0
 
-#ifdef CONFIG_CPU_ARM920_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r3, r2, #0x0a			@ C & small page?
 	tst	r3, #0x0b
 	biceq	r2, r2, #4
@@ -455,15 +429,12 @@
 	.asciz	"ARM/CIRRUS"
 ENTRY(cpu_arm920_name)
 	.ascii	"Arm920T"
-#if defined(CONFIG_CPU_ARM920_CPU_IDLE)
-	.ascii	"s"
-#endif
-#if defined(CONFIG_CPU_ARM920_I_CACHE_ON)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	.ascii	"i"
 #endif
-#if defined(CONFIG_CPU_ARM920_D_CACHE_ON)
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	.ascii	"d"
-#if defined(CONFIG_CPU_ARM920_WRITETHROUGH)
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	.ascii	"(wt)"
 #else
 	.ascii	"(wb)"
@@ -497,10 +468,10 @@
 	orr	r0, r0, #0x0031
 	orr	r0, r0, #0x2100			@ ..1. ...1 ..11 ...1
 
-#ifdef CONFIG_CPU_ARM920_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	orr	r0, r0, #0x0004			@ .... .... .... .1..
 #endif
-#ifdef CONFIG_CPU_ARM920_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	orr	r0, r0, #0x1000			@ ...1 .... .... ....
 #endif
 	mov	pc, lr
@@ -523,7 +494,6 @@
 	/* cache */
 	.word	cpu_arm920_cache_clean_invalidate_all
 	.word	cpu_arm920_cache_clean_invalidate_range
-	.word	cpu_arm920_flush_ram_page
 
 	/* dcache */
 	.word	cpu_arm920_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
--- a/arch/arm/mm/proc-arm922.S	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/mm/proc-arm922.S	Sun Apr 14 12:16:57 2002
@@ -22,6 +22,8 @@
  *
  * These are the low level assembler for performing cache and TLB
  * functions on the arm922.
+ *
+ *  CONFIG_CPU_ARM922_CPU_IDLE -> nohlt
  */
 #include <linux/linkage.h>
 #include <linux/config.h>
@@ -107,9 +109,7 @@
  */
 	.align	5
 ENTRY(cpu_arm922_do_idle)
-#if defined(CONFIG_CPU_ARM922_CPU_IDLE)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-#endif
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */
@@ -128,7 +128,7 @@
 	mov	r2, #1
 cpu_arm922_cache_clean_invalidate_all_r2:
 	mov	ip, #0
-#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 /*
@@ -166,7 +166,7 @@
 	cmp	r3, #MAX_AREA_SIZE
 	bgt	cpu_arm922_cache_clean_invalidate_all_r2
 1:	teq	r2, #0
-#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
 	add	r0, r0, #DCACHELINESIZE
@@ -187,32 +187,6 @@
 	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
 	mov	pc, lr
 
-/*
- * cpu_arm922_flush_ram_page(page)
- *
- * clean and invalidate all cache lines associated with this area of memory
- *
- * page: page to clean and invalidate
- */
-	.align	5
-ENTRY(cpu_arm922_flush_ram_page)
-	mov	r1, #PAGESIZE
-#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-#else
-1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-#endif
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
 /* ================================ D-CACHE =============================== */
 
 /*
@@ -228,7 +202,7 @@
  */
 	.align	5
 ENTRY(cpu_arm922_dcache_invalidate_range)
-#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	tst	r0, #DCACHELINESIZE - 1
 	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
 	tst	r1, #DCACHELINESIZE - 1
@@ -254,7 +228,7 @@
  */
 	.align	5
 ENTRY(cpu_arm922_dcache_clean_range)
-#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	bic	r0, r0, #DCACHELINESIZE - 1
 	sub	r1, r1, r0
 	cmp	r1, #MAX_AREA_SIZE
@@ -287,7 +261,7 @@
  */
 	.align	5
 ENTRY(cpu_arm922_dcache_clean_page)
-#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mov	r1, #PAGESIZE
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #DCACHELINESIZE
@@ -308,7 +282,7 @@
  */
 	.align	5
 ENTRY(cpu_arm922_dcache_clean_entry)
-#ifndef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
@@ -371,7 +345,7 @@
 	.align	5
 ENTRY(cpu_arm922_set_pgd)
 	mov	ip, #0
-#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	/* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
@@ -404,7 +378,7 @@
  */
 	.align	5
 ENTRY(cpu_arm922_set_pmd)
-#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r2, r1, #0x0a			@ C & Section
 	tst	r2, #0x0b
 	biceq	r1, r1, #4			@ clear bufferable bit
@@ -440,7 +414,7 @@
 	tst	r1, #LPTE_PRESENT | LPTE_YOUNG	@ Present and Young?
 	movne	r2, #0
 
-#ifdef CONFIG_CPU_ARM922_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r3, r2, #0x0a			@ C & small page?
 	tst	r3, #0x0b
 	biceq	r2, r2, #4
@@ -456,15 +430,12 @@
 	.asciz	"ARM/ALTERA"
 ENTRY(cpu_arm922_name)
 	.ascii	"Arm922T"
-#if defined(CONFIG_CPU_ARM922_CPU_IDLE)
-	.ascii	"s"
-#endif
-#if defined(CONFIG_CPU_ARM922_I_CACHE_ON)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	.ascii	"i"
 #endif
-#if defined(CONFIG_CPU_ARM922_D_CACHE_ON)
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	.ascii	"d"
-#if defined(CONFIG_CPU_ARM922_WRITETHROUGH)
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	.ascii	"(wt)"
 #else
 	.ascii	"(wb)"
@@ -498,10 +469,10 @@
 	orr	r0, r0, #0x0031
 	orr	r0, r0, #0x2100			@ ..1. ...1 ..11 ...1
 
-#ifdef CONFIG_CPU_ARM922_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	orr	r0, r0, #0x0004			@ .... .... .... .1..
 #endif
-#ifdef CONFIG_CPU_ARM922_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	orr	r0, r0, #0x1000			@ ...1 .... .... ....
 #endif
 	mov	pc, lr
@@ -524,7 +495,6 @@
 	/* cache */
 	.word	cpu_arm922_cache_clean_invalidate_all
 	.word	cpu_arm922_cache_clean_invalidate_range
-	.word	cpu_arm922_flush_ram_page
 
 	/* dcache */
 	.word	cpu_arm922_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
--- a/arch/arm/mm/proc-arm926.S	Sun Apr 14 12:16:54 2002
+++ b/arch/arm/mm/proc-arm926.S	Sun Apr 14 12:16:54 2002
@@ -21,6 +21,8 @@
  *
  * These are the low level assembler for performing cache and TLB
  * functions on the arm926.
+ *
+ *  CONFIG_CPU_ARM926_CPU_IDLE -> nohlt
  */
 #include <linux/linkage.h>
 #include <linux/config.h>
@@ -53,45 +55,6 @@
 	.text
 
 /*
- * cpu_arm926_data_abort()
- *
- * obtain information about current aborted instruction
- * Note: we read user space.  This means we might cause a data
- * abort here if the I-TLB and D-TLB aren't seeing the same
- * picture.  Unfortunately, this does happen.  We live with it.
- *
- * Inputs:
- *  r2 = address of abort 
- *  r3 = cpsr of abort
- *
- * Returns:
- *  r0 = address of abort
- *  r1 != 0 if writing
- *  r3 = FSR
- *  r4 = corrupted
- */
-	.align	5
-ENTRY(cpu_arm926_data_abort)
-	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	mrc	p15, 0, r4, c5, c0, 0		@ get FSR
-
-	tst	r1, #1<<24			@ Check for Jbit (NE -> found)
-	movne	r1, #-1 			@ Mark as writing
-	bne	2f
-
-	tst	r3, #1<<5			@ Check for Thumb-bit (NE -> found)
-	ldrneh	r1, [r2]			@ Read aborted Thumb instruction        
-	tstne	r1, r1, lsr #12 		@ C = bit 11
-
-	ldreq	r1, [r2]			@ Read aborted ARM instruction
-	tsteq	r1, r1, lsr #21 		@ C = bit 20
-
-	sbc	r1, r1, r1			@ r1 = C - 1
-2:
-	and	r3, r4, #255
-	mov	pc, lr
-
-/*
  * cpu_arm926_check_bugs()
  */
 ENTRY(cpu_arm926_check_bugs)
@@ -146,9 +109,7 @@
  */
 	.align	5
 ENTRY(cpu_arm926_do_idle)
-#if defined(CONFIG_CPU_ARM926_CPU_IDLE)
 	mcr	p15, 0, r0, c7, c0, 4		@ Wait for interrupt
-#endif
 	mov	pc, lr
 
 /* ================================= CACHE ================================ */
@@ -167,7 +128,7 @@
 	mov	r2, #1
 cpu_arm926_cache_clean_invalidate_all_r2:
 	mov	ip, #0
-#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 1:	mrc	p15, 0, r15, c7, c14, 3 	@ test,clean,invalidate
@@ -203,7 +164,7 @@
 	bgt	cpu_arm926_cache_clean_invalidate_all_r2
 
 1:	teq	r2, #0
-#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	mcrne	p15, 0, r0, c7, c5, 1		@ invalidate I entry
 	add	r0, r0, #DCACHELINESIZE
@@ -226,32 +187,6 @@
 
 	mov	pc, lr
 
-/*
- * cpu_arm926_flush_ram_page(page)
- *
- * clean and invalidate all cache lines associated with this area of memory
- *
- * page: page to clean and invalidate
- */
-	.align	5
-ENTRY(cpu_arm926_flush_ram_page)
-	mov	r1, #PAGESIZE
-#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
-1:	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-#else
-1:	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D entry
-	add	r0, r0, #DCACHELINESIZE
-#endif
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
 /* ================================ D-CACHE =============================== */
 
 /*
@@ -267,7 +202,7 @@
  */
 	.align	5
 ENTRY(cpu_arm926_dcache_invalidate_range)
-#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	tst	r0, #DCACHELINESIZE - 1
 	mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
 	tst	r1, #DCACHELINESIZE - 1
@@ -293,7 +228,7 @@
  */
 	.align	5
 ENTRY(cpu_arm926_dcache_clean_range)
-#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	bic	r0, r0, #DCACHELINESIZE - 1
 	sub	r1, r1, r0
 	cmp	r1, #MAX_AREA_SIZE
@@ -326,7 +261,7 @@
  */
 	.align	5
 ENTRY(cpu_arm926_dcache_clean_page)
-#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mov	r1, #PAGESIZE
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #DCACHELINESIZE
@@ -347,7 +282,7 @@
  */
 	.align	5
 ENTRY(cpu_arm926_dcache_clean_entry)
-#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
@@ -399,7 +334,7 @@
 	.align	5
 ENTRY(cpu_arm926_set_pgd)
 	mov	ip, #0
-#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	/* Any reason why we don't use mcr p15, 0, r0, c7, c7, 0 here? --rmk */
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
@@ -424,13 +359,13 @@
  */
 	.align	5
 ENTRY(cpu_arm926_set_pmd)
-#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r2, r1, #0x0a			@ C & Section
 	tst	r2, #0x0b
 	biceq	r1, r1, #4			@ clear bufferable bit
 #endif
 	str	r1, [r0]
-#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
@@ -462,14 +397,14 @@
 	tst	r1, #LPTE_PRESENT | LPTE_YOUNG	@ Present and Young?
 	movne	r2, #0
 
-#ifdef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	eor	r3, r2, #0x0a			@ C & small page?
 	tst	r3, #0x0b
 	biceq	r2, r2, #4
 #endif
 	str	r2, [r0]			@ hardware version
 	mov	r0, r0
-#ifndef CONFIG_CPU_ARM926_WRITETHROUGH
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 #endif
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
@@ -480,20 +415,17 @@
 	.asciz	"ARM"
 ENTRY(cpu_arm926_name)
 	.ascii	"ARM926EJ-S"
-#if defined(CONFIG_CPU_ARM926_CPU_IDLE)
-	.ascii	"s"
-#endif
-#if defined(CONFIG_CPU_ARM926_I_CACHE_ON)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	.ascii	"i"
 #endif
-#if defined(CONFIG_CPU_ARM926_D_CACHE_ON)
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	.ascii	"d"
-#if defined(CONFIG_CPU_ARM926_WRITETHROUGH)
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	.ascii	"(wt)"
 #else
 	.ascii	"(wb)"
 #endif
-#ifdef CONFIG_CPU_ARM926_ROUND_ROBIN
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	.ascii	"RR"
 #endif
 #endif
@@ -510,7 +442,7 @@
 	mcr	p15, 0, r4, c2, c0		@ load page table pointer
 
 
-#if defined(CONFIG_CPU_ARM926_WRITETHROUGH) 
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH 
 	mov	r0, #4				@ disable write-back on caches explicitly
 	mcr	p15, 7, r0, c15, c0, 0
 #endif 
@@ -532,13 +464,13 @@
 	orr	r0, r0, #0x0031
 	orr	r0, r0, #0x2100 		@ ..1. ...1 ..11 ...1
 
-#ifdef CONFIG_CPU_ARM926_ROUND_ROBIN
+#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
 	orr	r0, r0, #0x4000 		@ .1.. .... .... ....
 #endif
-#ifdef CONFIG_CPU_ARM926_D_CACHE_ON
+#ifndef CONFIG_CPU_DCACHE_DISABLE
 	orr	r0, r0, #0x0004 		@ .... .... .... .1..
 #endif
-#ifdef CONFIG_CPU_ARM926_I_CACHE_ON
+#ifndef CONFIG_CPU_ICACHE_DISABLE
 	orr	r0, r0, #0x1000 		@ ...1 .... .... ....
 #endif
 	mov	pc, lr
@@ -561,7 +493,6 @@
 	/* cache */
 	.word	cpu_arm926_cache_clean_invalidate_all
 	.word	cpu_arm926_cache_clean_invalidate_range
-	.word	cpu_arm926_flush_ram_page
 
 	/* dcache */
 	.word	cpu_arm926_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
--- a/arch/arm/mm/proc-macros.S	Sun Apr 14 12:16:56 2002
+++ b/arch/arm/mm/proc-macros.S	Sun Apr 14 12:16:56 2002
@@ -1,3 +1,10 @@
+/*
+ * We need constants.h for:
+ *  VMA_VM_MM
+ *  VMA_VM_FLAGS
+ *  VM_EXEC
+ */
+#include <asm/constants.h>
 #include <asm/thread_info.h>
 
 /*
@@ -12,6 +19,11 @@
  */
 	.macro	vma_vm_flags, rd, rn
 	ldr	\rd, [\rn, #VMA_VM_FLAGS]
+	.endm
+
+	.macro	tsk_mm, rd, rn
+	ldr	\rd, [\rn, #TI_TASK]
+	ldr	\rd, [\rd, #TSK_ACTIVE_MM]
 	.endm
 
 /*
diff -Nru a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
--- a/arch/arm/mm/proc-sa110.S	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/mm/proc-sa110.S	Sun Apr 14 12:16:58 2002
@@ -262,26 +262,6 @@
 	bhi	cpu_sa1100_cache_clean_invalidate_all_r2
 	b	1b
 
-/*
- * cpu_sa110_flush_ram_page(page)
- *
- * clean and invalidate all cache lines associated with this area of memory
- *
- * page: page to clean and invalidate
- */
-	.align	5
-ENTRY(cpu_sa110_flush_ram_page)
-ENTRY(cpu_sa1100_flush_ram_page)
-	mov	r1, #PAGESIZE
-1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-	add	r0, r0, #DCACHELINESIZE
-	subs	r1, r1, #2 * DCACHELINESIZE
-	bne	1b
-	mcr	p15, 0, r1, c7, c10, 4		@ drain WB
-	mov	pc, lr
-
 /* ================================ D-CACHE =============================== */
 
 /*
@@ -550,7 +530,6 @@
 	/* cache */
 	.word	cpu_sa110_cache_clean_invalidate_all
 	.word	cpu_sa110_cache_clean_invalidate_range
-	.word	cpu_sa110_flush_ram_page
 
 	/* dcache */
 	.word	cpu_sa110_dcache_invalidate_range
@@ -591,7 +570,6 @@
 	/* cache */
 	.word	cpu_sa1100_cache_clean_invalidate_all
 	.word	cpu_sa1100_cache_clean_invalidate_range
-	.word	cpu_sa1100_flush_ram_page
 
 	/* dcache */
 	.word	cpu_sa1100_dcache_invalidate_range
diff -Nru a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
--- a/arch/arm/mm/proc-syms.c	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/mm/proc-syms.c	Sun Apr 14 12:16:58 2002
@@ -16,7 +16,6 @@
 #ifndef MULTI_CPU
 EXPORT_SYMBOL(cpu_cache_clean_invalidate_all);
 EXPORT_SYMBOL(cpu_cache_clean_invalidate_range);
-EXPORT_SYMBOL(cpu_flush_ram_page);
 EXPORT_SYMBOL(cpu_dcache_clean_page);
 EXPORT_SYMBOL(cpu_dcache_clean_entry);
 EXPORT_SYMBOL(cpu_dcache_clean_range);
diff -Nru a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
--- a/arch/arm/mm/proc-xscale.S	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/mm/proc-xscale.S	Sun Apr 14 12:16:57 2002
@@ -769,7 +769,7 @@
 	.type	__pxa250_proc_info,#object
 __pxa250_proc_info:
 	.long	0x69052100
-	.long	0xfffffff0
+	.long	0xfffff7f0
 	.long	0x00000c0e
 	b	__xscale_setup
 	.long	cpu_arch_name
diff -Nru a/arch/arm/mm/tlb-v3.S b/arch/arm/mm/tlb-v3.S
--- a/arch/arm/mm/tlb-v3.S	Sun Apr 14 12:16:54 2002
+++ b/arch/arm/mm/tlb-v3.S	Sun Apr 14 12:16:54 2002
@@ -79,10 +79,13 @@
 	mcr	p15, 0, r0, c6, c0, 0		@ invalidate TLB entry
 	mov	pc, lr
 
-ENTRY(v3_tlb_fns)
-	.word	v3_flush_kern_tlb_all
-	.word	v3_flush_user_tlb_mm
-	.word	v3_flush_user_tlb_range
-	.word	v3_flush_user_tlb_page
-	.word	v3_flush_kern_tlb_page
+	.section ".text.init", #alloc, #execinstr
 
+	.type	v3_tlb_fns, #object
+ENTRY(v3_tlb_fns)
+	.long	v3_flush_kern_tlb_all
+	.long	v3_flush_user_tlb_mm
+	.long	v3_flush_user_tlb_range
+	.long	v3_flush_user_tlb_page
+	.long	v3_flush_kern_tlb_page
+	.size	v3_tlb_fns, . - v3_tlb_fns
diff -Nru a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
--- a/arch/arm/mm/tlb-v4.S	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/mm/tlb-v4.S	Sun Apr 14 12:16:57 2002
@@ -98,9 +98,13 @@
 	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
 	mov	pc, lr
 
+	.section ".text.init", #alloc, #execinstr
+
+	.type	v4_tlb_fns, #object
 ENTRY(v4_tlb_fns)
-	.word	v4_flush_kern_tlb_all
-	.word	v4_flush_user_tlb_mm
-	.word	v4_flush_user_tlb_range
-	.word	v4_flush_user_tlb_page
-	.word	v4_flush_kern_tlb_page
+	.long	v4_flush_kern_tlb_all
+	.long	v4_flush_user_tlb_mm
+	.long	v4_flush_user_tlb_range
+	.long	v4_flush_user_tlb_page
+	.long	v4_flush_kern_tlb_page
+	.size	v4_tlb_fns, . - v4_tlb_fns
diff -Nru a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
--- a/arch/arm/mm/tlb-v4wb.S	Sun Apr 14 12:16:57 2002
+++ b/arch/arm/mm/tlb-v4wb.S	Sun Apr 14 12:16:57 2002
@@ -144,17 +144,22 @@
 	mcr	p15, 0, r0, c8, c6, 1		@ invalidate D TLB entry
 	mov	pc, lr
 
+	.section ".text.init", #alloc, #execinstr
+
+	.type	v4wb_tlb_fns, #object
 ENTRY(v4wb_tlb_fns)
-	.word	v4wb_flush_kern_tlb_all
-	.word	v4wb_flush_user_tlb_mm
-	.word	v4wb_flush_user_tlb_range
-	.word	v4wb_flush_user_tlb_page
-	.word	v4wb_flush_kern_tlb_page
+	.long	v4wb_flush_kern_tlb_all
+	.long	v4wb_flush_user_tlb_mm
+	.long	v4wb_flush_user_tlb_range
+	.long	v4wb_flush_user_tlb_page
+	.long	v4wb_flush_kern_tlb_page
+	.size	v4wb_tlb_fns, . - v4wb_tlb_fns
 
+	.type	v4wbi_tlb_fns, #object
 ENTRY(v4wbi_tlb_fns)
-	.word	v4wbi_flush_kern_tlb_all
-	.word	v4wbi_flush_user_tlb_mm
-	.word	v4wbi_flush_user_tlb_range
-	.word	v4wbi_flush_user_tlb_page
-	.word	v4wbi_flush_kern_tlb_page
-
+	.long	v4wbi_flush_kern_tlb_all
+	.long	v4wbi_flush_user_tlb_mm
+	.long	v4wbi_flush_user_tlb_range
+	.long	v4wbi_flush_user_tlb_page
+	.long	v4wbi_flush_kern_tlb_page
+	.size	v4wbi_tlb_fns, . - v4wbi_tlb_fns
diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types	Sun Apr 14 12:16:58 2002
+++ b/arch/arm/tools/mach-types	Sun Apr 14 12:16:58 2002
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Sun Feb 24 17:43:42 2002
+# Last update: Sun Mar 24 11:48:10 2002
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -147,7 +147,7 @@
 h3100			SA1100_H3100		H3100			136
 h3800			SA1100_H3800		H3800			137
 blue_v1			ARCH_BLUE_V1		BLUE_V1			138
-xscale_cerf		ARCH_XSCALE_CERF	XSCALE_CERF		139
+pxa_cerf		ARCH_PXA_CERF		PXA_CERF		139
 arm7tevb		ARCH_ARM7TEVB		ARM7TEVB		140
 d7400			ARCH_D7400		D7400			141
 piranha			ARCH_PIRANHA		PIRANHA			142
@@ -174,3 +174,8 @@
 amico			ARCH_AMICO		AMICO			163
 iam			SA1100_IAM		IAM			164
 tt530			SA1100_TT530		TT530			165
+sam2400			ARCH_SAM2400		SAM2400			166
+jornada56x		ARCH_JORNADA56X		JORNADA56X		167
+active			SA1100_ACTIVE		ACTIVE			168
+iq80321			ARCH_IQ80321		IQ80321			169
+wid			SA1100_WID		WID			170
diff -Nru a/arch/cris/drivers/ethernet.c b/arch/cris/drivers/ethernet.c
--- a/arch/cris/drivers/ethernet.c	Sun Apr 14 12:16:58 2002
+++ b/arch/cris/drivers/ethernet.c	Sun Apr 14 12:16:58 2002
@@ -996,7 +996,7 @@
 	int i;
 #endif
 
-	if (!led_active && jiffies > led_next_time) {
+	if (!led_active && time_after(jiffies, led_next_time)) {
 		/* light the network leds depending on the current speed. */
 		e100_set_network_leds(NETWORK_ACTIVITY);
 
@@ -1288,7 +1288,7 @@
 {
 	D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
 
-	if (!led_active && jiffies > led_next_time) {
+	if (!led_active && time_after(jiffies, led_next_time)) {
 		/* light the network leds depending on the current speed. */
 		e100_set_network_leds(NETWORK_ACTIVITY);
 
@@ -1313,7 +1313,7 @@
 static void
 e100_clear_network_leds(unsigned long dummy)
 {
-	if (led_active && jiffies > led_next_time) {
+	if (led_active && time_after(jiffies, led_next_time)) {
 		e100_set_network_leds(NO_NETWORK_ACTIVITY);
 
 		/* Set the earliest time we may set the LED */
diff -Nru a/arch/cris/drivers/gpio.c b/arch/cris/drivers/gpio.c
--- a/arch/cris/drivers/gpio.c	Sun Apr 14 12:16:54 2002
+++ b/arch/cris/drivers/gpio.c	Sun Apr 14 12:16:54 2002
@@ -217,7 +217,7 @@
 gpio_open(struct inode *inode, struct file *filp)
 {
 	struct gpio_private *priv;
-	int p = MINOR(inode->i_rdev);
+	int p = minor(inode->i_rdev);
 
 	if (p >= NUM_PORTS && p != LEDS)
 		return -EINVAL;
diff -Nru a/arch/cris/drivers/ide.c b/arch/cris/drivers/ide.c
--- a/arch/cris/drivers/ide.c	Sun Apr 14 12:16:56 2002
+++ b/arch/cris/drivers/ide.c	Sun Apr 14 12:16:56 2002
@@ -271,10 +271,10 @@
 
 	printk("ide: ETRAX 100LX built-in ATA DMA controller\n");
 
-	/* first fill in some stuff in the ide_hwifs fields */
+	/* first initialize the channel interface data */
 	
 	for(h = 0; h < MAX_HWIFS; h++) {
-		ide_hwif_t *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 		hwif->chipset = ide_etrax100;
 		hwif->tuneproc = &tune_e100_ide;
 		hwif->dmaproc = &e100_dmaproc;
@@ -355,7 +355,7 @@
 	printk("ide: waiting %d seconds for drives to regain consciousness\n", CONFIG_ETRAX_IDE_DELAY);
 
 	h = jiffies + (CONFIG_ETRAX_IDE_DELAY * HZ);
-	while(jiffies < h) ;
+	while(time_before(jiffies, h)) ;
 
   /* reset the dma channels we will use */
 
@@ -717,7 +717,7 @@
 	LED_DISK_READ(0);
 	LED_DISK_WRITE(0);
 
-	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -798,7 +798,7 @@
 	 * not a diskdrive.
 	 */
 
-        if (drive->media != ide_disk)
+        if (drive->type != ATA_DISK)
                 return 0;
 
  dma_begin:
@@ -809,7 +809,7 @@
 		WAIT_DMA(ATA_RX_DMA_NBR);
 
 		/* set up the Etrax DMA descriptors */
-		
+
 		if(e100_ide_build_dmatable (drive))
 			return 1;
 
@@ -902,7 +902,7 @@
  * --- Marcin Dalecki
  */
 
-void ide_release_dma (ide_hwif_t *hwif)
+void ide_release_dma(struct ata_channel *hwif)
 {
 	/* empty */
 }
diff -Nru a/arch/cris/kernel/ksyms.c b/arch/cris/kernel/ksyms.c
--- a/arch/cris/kernel/ksyms.c	Sun Apr 14 12:16:59 2002
+++ b/arch/cris/kernel/ksyms.c	Sun Apr 14 12:16:59 2002
@@ -38,9 +38,7 @@
 /* String functions */
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(simple_strtol);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strchr);
diff -Nru a/arch/i386/Config.help b/arch/i386/Config.help
--- a/arch/i386/Config.help	Sun Apr 14 12:16:55 2002
+++ b/arch/i386/Config.help	Sun Apr 14 12:16:55 2002
@@ -128,6 +128,12 @@
 
   If unsure, say "off".
 
+CONFIG_HIGHPTE
+  The VM uses one page table entry for each page of physical memory.
+  For systems with a lot of RAM, this can be wasteful of precious
+  low memory.  Setting this option will put user-space page table
+  entries in high memory.
+
 CONFIG_HIGHMEM4G
   Select this if you have a 32-bit processor and between 1 and 4
   gigabytes of physical RAM.
@@ -797,6 +803,30 @@
   a work-around for a number of buggy BIOSes. Switch this option on if
   your computer crashes instead of powering off properly.
 
+CONFIG_X86_MCE
+  Machine Check Exception support allows the processor to notify the
+  kernel if it detects a problem (e.g. overheating, component failure).
+  The action the kernel takes depends on the severity of the problem,
+  ranging from a warning message on the console, to halting the machine.
+  Your processor must be a Pentium or newer to support this - check the
+  flags in /proc/cpuinfo for mce.  Note that some older Pentium systems
+  have a design flaw which leads to false MCE events - hence MCE is
+  disabled on all P5 processors, unless explicitly enabled with "mce"
+  as a boot argument.  Similarly, if MCE is built in and creates a
+  problem on some new non-standard machine, you can boot with "nomce"
+  to disable it.  MCE support simply ignores non-MCE processors like
+  the 386 and 486, so nearly everyone can say Y here.
+
+CONFIG_X86_MCE_NONFATAL
+  Enabling this feature starts a timer that triggers every 5 seconds which
+  will look at the machine check registers to see if anything happened.
+  Non-fatal problems automatically get corrected (but still logged).
+  Disable this if you don't want to see these messages.
+  Seeing the messages this option prints out may be indicative of dying hardware,
+  or out-of-spec (ie, overclocked) hardware.
+  This option only does something on hardware with Intel P6 style MCE.
+  (Pentium Pro and above, AMD Athlon/Duron)
+				 
 CONFIG_TOSHIBA
   This adds a driver to safely access the System Management Mode of
   the CPU on Toshiba portables with a genuine Toshiba BIOS. It does
@@ -903,3 +933,6 @@
   of the BUG call as well as the EIP and oops trace.  This aids
   debugging but costs about 70-100K of memory.
 
+CONFIG_DEBUG_OBSOLETE
+  Say Y here if you want to reduce the chances of the tree compiling,
+  and are prepared to dig into driver internals to fix compile errors.
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Sun Apr 14 12:16:57 2002
+++ b/arch/i386/config.in	Sun Apr 14 12:16:57 2002
@@ -25,6 +25,7 @@
 	 Pentium-4				CONFIG_MPENTIUM4 \
 	 K6/K6-II/K6-III			CONFIG_MK6 \
 	 Athlon/Duron/K7			CONFIG_MK7 \
+	 Elan					CONFIG_MELAN \
 	 Crusoe					CONFIG_MCRUSOE \
 	 Winchip-C6				CONFIG_MWINCHIPC6 \
 	 Winchip-2				CONFIG_MWINCHIP2 \
@@ -119,6 +120,11 @@
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
 fi
+if [ "$CONFIG_MELAN" = "y" ]; then
+   define_int  CONFIG_X86_L1_CACHE_SHIFT 4
+   define_bool CONFIG_X86_USE_STRING_486 y
+   define_bool CONFIG_X86_ALIGNMENT_16 y
+fi
 if [ "$CONFIG_MCYRIXIII" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
    define_bool CONFIG_X86_TSC y
@@ -150,6 +156,10 @@
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
    define_bool CONFIG_X86_OOSTORE y
 fi
+
+bool 'Machine Check Exception' CONFIG_X86_MCE
+dep_bool 'Check for non-fatal errors' CONFIG_X86_MCE_NONFATAL $CONFIG_X86_MCE
+
 tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
 tristate 'Dell laptop support' CONFIG_I8K
 
@@ -160,23 +170,18 @@
 choice 'High Memory Support' \
 	"off           CONFIG_NOHIGHMEM \
 	 4GB           CONFIG_HIGHMEM4G \
-	 4GB-highpte   CONFIG_HIGHMEM4G_HIGHPTE \
-	 64GB          CONFIG_HIGHMEM64G \
-	 64GB-highpte  CONFIG_HIGHMEM64G_HIGHPTE" off
-if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
-   define_bool CONFIG_HIGHMEM y
+	 64GB          CONFIG_HIGHMEM64G" off
+
+if [ "$CONFIG_HIGHMEM4G" = "y" -o "$CONFIG_HIGHMEM64G" = "y" ]; then
+   bool 'Use high memory pte support' CONFIG_HIGHPTE
 fi
-if [ "$CONFIG_HIGHMEM4G_HIGHPTE" = "y" ]; then
+
+if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
    define_bool CONFIG_HIGHMEM y
-   define_bool CONFIG_HIGHPTE y
 fi
+
 if [ "$CONFIG_HIGHMEM64G" = "y" ]; then
    define_bool CONFIG_HIGHMEM y
-   define_bool CONFIG_X86_PAE y
-fi
-if [ "$CONFIG_HIGHMEM64G_HIGHPTE" = "y" ]; then
-   define_bool CONFIG_HIGHMEM y
-   define_bool CONFIG_HIGHPTE y
    define_bool CONFIG_X86_PAE y
 fi
 
diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	Sun Apr 14 12:16:55 2002
+++ b/arch/i386/defconfig	Sun Apr 14 12:16:55 2002
@@ -39,6 +39,7 @@
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
+# CONFIG_MELAN is not set
 # CONFIG_MCRUSOE is not set
 # CONFIG_MWINCHIPC6 is not set
 # CONFIG_MWINCHIP2 is not set
@@ -57,6 +58,8 @@
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_PGE=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_NONFATAL is not set
 # CONFIG_TOSHIBA is not set
 # CONFIG_I8K is not set
 # CONFIG_MICROCODE is not set
@@ -64,9 +67,7 @@
 # CONFIG_X86_CPUID is not set
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
-# CONFIG_HIGHMEM4G_HIGHPTE is not set
 # CONFIG_HIGHMEM64G is not set
-# CONFIG_HIGHMEM64G_HIGHPTE is not set
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
@@ -103,7 +104,6 @@
 # CONFIG_I82092 is not set
 # CONFIG_I82365 is not set
 # CONFIG_TCIC is not set
-# CONFIG_PCMCIA_SA1100 is not set
 
 #
 # PCI Hotplug Support
@@ -261,6 +261,8 @@
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_BLK_DEV_IDE_TCQ is not set
+# CONFIG_BLK_DEV_IDE_TCQ_DEFAULT is not set
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
@@ -268,7 +270,6 @@
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
@@ -276,7 +277,6 @@
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
 CONFIG_BLK_DEV_PIIX=y
-CONFIG_PIIX_TUNING=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC_ADMA is not set
@@ -291,7 +291,6 @@
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
 # CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
@@ -829,13 +828,15 @@
 # CONFIG_USB_OHCI_HCD is not set
 CONFIG_USB_UHCI_ALT=y
 # CONFIG_USB_OHCI is not set
+CONFIG_USB_HOST=y
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_AUDIO is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
@@ -845,16 +846,20 @@
 # CONFIG_USB_STORAGE_HP8200e is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
 
 #
 # USB Human Interface Devices (HID)
 #
+# CONFIG_USB_HID is not set
 
 #
-#   Input core support is needed for USB HID
+#     Input core support is needed for USB HID input layer or HIDBP support
 #
+# CONFIG_USB_HIDINPUT is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_WACOM is not set
 
 #
 # USB Imaging devices
@@ -868,18 +873,28 @@
 #
 # USB Multimedia devices
 #
+# CONFIG_USB_DABUSB is not set
 
 #
 #   Video4Linux support is needed for USB Multimedia device support
 #
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_STV680 is not set
 
 #
 # USB Network adaptors
 #
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
 
 #
@@ -911,9 +926,11 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
@@ -921,8 +938,10 @@
 #
 # USB Miscellaneous drivers
 #
-# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/kernel/Makefile	Sun Apr 14 12:16:56 2002
@@ -18,7 +18,8 @@
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
-		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
+		pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \
+		bootflag.o
 
 
 ifdef CONFIG_PCI
diff -Nru a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
--- a/arch/i386/kernel/acpi.c	Sun Apr 14 12:16:59 2002
+++ b/arch/i386/kernel/acpi.c	Sun Apr 14 12:16:59 2002
@@ -43,10 +43,15 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/io_apic.h>
+#include <asm/tlbflush.h>
 
 
 #define PREFIX			"ACPI: "
 
+extern struct acpi_boot_flags	acpi_boot;
+
+int				acpi_mp_config = 0;
+
 
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
@@ -103,13 +108,15 @@
 
 /* From mpparse.c */
 extern void __init MP_processor_info(struct mpc_config_processor *);
+extern void __init MP_ioapic_info (struct mpc_config_ioapic *);
+extern void __init MP_lintsrc_info(struct mpc_config_lintsrc *);
 
 int __init
 acpi_parse_lapic (
 	acpi_table_entry_header *header)
 {
 	struct acpi_table_lapic	*cpu = NULL;
-	struct mpc_config_processor proc_entry;
+	struct mpc_config_processor processor;
 
 	cpu = (struct acpi_table_lapic*) header;
 	if (!cpu)
@@ -133,21 +140,21 @@
 	 * the processor ID.  Processor features aren't present in
 	 * the table.
 	 */
-	proc_entry.mpc_type = MP_PROCESSOR;
-	proc_entry.mpc_apicid = cpu->id;
-	proc_entry.mpc_cpuflag = CPU_ENABLED;
+	processor.mpc_type = MP_PROCESSOR;
+	processor.mpc_apicid = cpu->id;
+	processor.mpc_cpuflag = CPU_ENABLED;
 	if (cpu->id == boot_cpu_physical_apicid) {
 		/* TBD: Circular reference trying to establish BSP */
-		proc_entry.mpc_cpuflag |= CPU_BOOTPROCESSOR;
+		processor.mpc_cpuflag |= CPU_BOOTPROCESSOR;
 	}
-	proc_entry.mpc_cpufeature = (boot_cpu_data.x86 << 8)
+	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8)
 		| (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
-	proc_entry.mpc_featureflag = boot_cpu_data.x86_capability[0];
-	proc_entry.mpc_reserved[0] = 0;
-	proc_entry.mpc_reserved[1] = 0;
-	proc_entry.mpc_apicver = 0x10;	/* integrated APIC */
+	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+	processor.mpc_reserved[0] = 0;
+	processor.mpc_reserved[1] = 0;
+	processor.mpc_apicver = 0x10;	/* Integrated APIC */
 
-	MP_processor_info(&proc_entry);
+	MP_processor_info(&processor);
 
 	total_cpus++;
 
@@ -183,7 +190,7 @@
 
 	acpi_table_print_madt_entry(header);
 
-	/* TBD: Support local APIC NMI entries */
+	/* TBD: Support lapic_nmi entries */
 
 	return 0;
 }
@@ -198,18 +205,102 @@
 	acpi_table_entry_header *header)
 {
 	struct acpi_table_ioapic *ioapic = NULL;
-	
+	/*
+	struct mpc_config_ioapic mp_ioapic;
+	struct IO_APIC_reg_01	reg_01;
+	*/
+
 	ioapic = (struct acpi_table_ioapic*) header;
 	if (!ioapic)
 		return -EINVAL;
+ 
+	acpi_table_print_madt_entry(header);
+ 
+	/*
+	 * Cobble up an entry for the IOAPIC (just as we do for LAPIC entries).
+	 * Note that we aren't doing anything with ioapic->vector, and 
+	 * mpc_apicver gets read directly from ioapic.
+	 */
+
+	/*
+	 * TBD: Complete I/O APIC support.
+	 *
+	mp_ioapic.mpc_type = MP_IOAPIC;
+	mp_ioapic.mpc_apicid = ioapic->id;
+	mp_ioapic.mpc_flags = MPC_APIC_USABLE;
+	mp_ioapic.mpc_apicaddr = ioapic->address;
+	set_fixmap_nocache(nr_ioapics + FIX_IO_APIC_BASE_0,
+		mp_ioapic.mpc_apicaddr);
+
+	printk("mapped IOAPIC to %08lx (%08lx)\n",
+		__fix_to_virt(nr_ioapics), mp_ioapic.mpc_apicaddr);
+
+	*(int *)&reg_01 = io_apic_read(nr_ioapics, 1);
+	mp_ioapic.mpc_apicver = reg_01.version;
+	MP_ioapic_info(&mp_ioapic);
+	 */
+
+	return 0;
+}
+
+
+int __init
+acpi_parse_int_src_ovr (
+	acpi_table_entry_header *header)
+{
+	struct acpi_table_int_src_ovr *int_src_ovr = NULL;
+	/*
+	struct mpc_config_intsrc my_intsrc;
+	int			i = 0;
+	*/
+
+	int_src_ovr = (struct acpi_table_int_src_ovr*) header;
+	if (!int_src_ovr)
+		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
 
-	/* TBD: Support ioapic entries */
+	/*
+	 * TBD: Complete I/O APIC support.
+	 *
+	my_intsrc.mpc_type = MP_INTSRC;
+	my_intsrc.mpc_irqtype = mp_INT;
+	my_intsrc.mpc_irqflag = *(unsigned short*)(&(int_src_ovr->flags));
+	my_intsrc.mpc_srcbus = int_src_ovr->bus;
+	my_intsrc.mpc_srcbusirq = int_src_ovr->bus_irq;
+	my_intsrc.mpc_dstapic = 0;
+	my_intsrc.mpc_dstirq = int_src_ovr->global_irq;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (mp_irqs[i].mpc_srcbusirq == my_intsrc.mpc_srcbusirq) {
+			mp_irqs[i] = my_intsrc;
+			break;
+		}
+	}
+	 */
+
+	return 0;
+}
+
+
+int __init
+acpi_parse_nmi_src (
+	acpi_table_entry_header *header)
+{
+	struct acpi_table_nmi_src *nmi_src = NULL;
+
+	nmi_src = (struct acpi_table_nmi_src*) header;
+	if (!nmi_src)
+		return -EINVAL;
+
+	acpi_table_print_madt_entry(header);
+
+	/* TBD: Support nimsrc entries */
 
 	return 0;
 }
 
+
 #endif /*CONFIG_X86_IO_APIC*/
 
 
@@ -287,14 +378,115 @@
 }
 
 
-#endif /*CONFIG_ACPI_BOOT*/
+int __init
+acpi_boot_init (
+	char			*cmdline)
+{
+	int			result = 0;
 
+	/* Initialize the ACPI boot-time table parser */
+	result = acpi_table_init(cmdline);
+	if (0 != result)
+		return result;
+
+#ifdef CONFIG_X86_LOCAL_APIC
+#ifdef CONFIG_X86_IO_APIC
+
+	/* 
+	 * MADT
+	 * ----
+	 * Parse the Multiple APIC Description Table (MADT), if exists.
+	 * Note that this table provides platform SMP configuration 
+	 * information -- the successor to MPS tables.
+	 */
+
+	if (!acpi_boot.madt) {
+		printk(KERN_INFO PREFIX "MADT parsing disabled via command-line\n");
+		return 0;
+	}
+
+	result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
+	if (0 == result) {
+		printk(KERN_WARNING PREFIX "MADT not present\n");
+		return 0;
+	}
+	else if (0 > result) {
+		printk(KERN_ERR PREFIX "Error parsing MADT\n");
+		return result;
+	}
+	else if (1 < result) 
+		printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n");
+
+	/* Local APIC */
+
+	result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
+	if (0 > result) {
+		printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
+		return result;
+	}
+
+	result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
+	if (1 > result) {
+		printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries!\n");
+		return -ENODEV;
+	}
+
+	result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
+	if (0 > result) {
+		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
+		return result;
+	}
+
+	/* I/O APIC */
+
+	result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
+	if (1 > result) {
+		printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries!\n");
+		return -ENODEV;
+	}
+
+	acpi_mp_config = 1;
+
+	/*
+	 * TBD: Complete I/O APIC support.
+	 *
+	construct_default_ACPI_table();
+	 */
+
+	result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
+	if (0 > result) {
+		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
+		return result;
+	}
+
+	result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
+	if (0 > result) {
+		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
+		return result;
+	}
+
+	/* Make boot-up look pretty */
+	printk("%d CPUs total\n", total_cpus);
+
+#endif /*CONFIG_X86_IO_APIC*/
+#endif /*CONFIG_X86_LOCAL_APIC*/
+
+#ifdef CONFIG_SERIAL_ACPI
+	/*
+	 * TBD: Need phased approach to table parsing (only do those absolutely
+	 *      required during boot-up).  Recommend expanding concept of fix-
+	 *      feature devices (ACPI Bus driver) to include table-based devices 
+	 *      such as serial ports, EC, SMBus, etc.
+	 */
+	/* acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);*/
+#endif /*CONFIG_SERIAL_ACPI*/
+
+	return 0;
+}
+
+#endif /*CONFIG_ACPI_BOOT*/
 
-/* --------------------------------------------------------------------------
-                            PCI Interrupt Routing Support
-   -------------------------------------------------------------------------- */
 
-#ifdef CONFIG_ACPI_PCI
 int __init
 acpi_get_interrupt_model (
 	int		*type)
@@ -303,15 +495,13 @@
 		return -EINVAL;
 
 #ifdef CONFIG_X86_IO_APIC
-	if (io_apic_assign_pci_irqs)
-		*type = ACPI_PCI_ROUTING_IOAPIC;
-	else
+	*type = ACPI_INT_MODEL_IOAPIC;
+#else
+	*type = ACPI_INT_MODEL_PIC;
 #endif
-		*type = ACPI_PCI_ROUTING_PIC;
 
 	return 0;
 }
-#endif
 
 
 /* --------------------------------------------------------------------------
diff -Nru a/arch/i386/kernel/acpi_wakeup.S b/arch/i386/kernel/acpi_wakeup.S
--- a/arch/i386/kernel/acpi_wakeup.S	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/kernel/acpi_wakeup.S	Sun Apr 14 12:16:56 2002
@@ -18,6 +18,8 @@
 
 	addw	$(wakeup_data - wakeup_code) >> 4, %ax
 	movw	%ax, %ds
+	movw	%ax, %ss
+	mov	$(wakeup_stack - wakeup_data), %sp		# Private stack is needed for ASUS board
 
 	# set up page table
 	movl	(real_save_cr3 - wakeup_data), %eax
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/apic.c	Sun Apr 14 12:16:58 2002
@@ -90,7 +90,7 @@
 		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
 	v = GET_APIC_VERSION(apic_read(APIC_LVR));
 	if (APIC_INTEGRATED(v)) {	/* !82489DX */
-		if (maxlvt > 3)
+		if (maxlvt > 3)		/* Due to Pentium errata 3AP and 11AP. */
 			apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
 	}
@@ -449,6 +449,7 @@
 	unsigned int apic_lvterr;
 	unsigned int apic_tmict;
 	unsigned int apic_tdcr;
+	unsigned int apic_thmr;
 } apic_pm_state;
 
 static void apic_pm_suspend(void *data)
@@ -470,6 +471,7 @@
 	apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
 	apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
 	apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
+	apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
 	__save_flags(flags);
 	__cli();
 	disable_local_APIC();
@@ -498,6 +500,7 @@
 	apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
 	apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
 	apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
+	apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
 	apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
 	apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
 	apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
@@ -634,7 +637,7 @@
 		printk("Could not enable APIC!\n");
 		return -1;
 	}
-	set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability);
+	set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
 	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 	boot_cpu_physical_apicid = 0;
 	if (nmi_watchdog != NMI_NONE)
diff -Nru a/arch/i386/kernel/bluesmoke.c b/arch/i386/kernel/bluesmoke.c
--- a/arch/i386/kernel/bluesmoke.c	Sun Apr 14 12:16:57 2002
+++ b/arch/i386/kernel/bluesmoke.c	Sun Apr 14 12:16:57 2002
@@ -3,16 +3,129 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/config.h>
+#include <linux/irq.h>
 #include <asm/processor.h> 
+#include <asm/system.h>
 #include <asm/msr.h>
+#include <asm/apic.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_X86_MCE
 
 static int mce_disabled __initdata = 0;
 
+static int banks;
+
 /*
- *	Machine Check Handler For PII/PIII
+ * If we get an MCE, we don't know what state the caches/TLB's are
+ * going to be in, so we throw them all away.
  */
+static void inline flush_all (void)
+{   
+	__asm__ __volatile__ ("invd": : );
+	__flush_tlb();
+}
 
-static int banks;
+/*
+ *	P4/Xeon Thermal transition interrupt handler
+ */
+
+static void intel_thermal_interrupt(struct pt_regs *regs)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	u32 l, h;
+	unsigned int cpu = smp_processor_id();
+
+	ack_APIC_irq();
+
+	rdmsr(MSR_IA32_THERM_STATUS, l, h);
+	if (l & 1) {
+		printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu);
+		printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu);
+	} else {
+		printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu);
+	}
+#endif
+}
+
+static void unexpected_thermal_interrupt(struct pt_regs *regs)
+{	
+	printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id());
+}
+
+/*
+ *	Thermal interrupt handler for this CPU setup
+ */
+
+static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt;
+
+asmlinkage void smp_thermal_interrupt(struct pt_regs regs)
+{
+	vendor_thermal_interrupt(&regs);
+}
+
+/* P4/Xeon Thermal regulation detect and init */
+
+static void __init intel_init_thermal(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	u32 l, h;
+	unsigned int cpu = smp_processor_id();
+
+	/* Thermal monitoring */
+	if (!test_bit(X86_FEATURE_ACPI, &c->x86_capability))
+		return;	/* -ENODEV */
+	
+	/* Clock modulation */
+	if (!test_bit(X86_FEATURE_ACC, &c->x86_capability))
+		return;	/* -ENODEV */
+
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+	/* first check if its enabled already, in which case there might
+	 * be some SMM goo which handles it, so we can't even put a handler
+	 * since it might be delivered via SMI already -zwanem.
+	 */
+
+	if (l & (1<<3)) {
+		printk(KERN_DEBUG "CPU#%d: Thermal monitoring already enabled\n", cpu);
+	} else {
+		wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
+		printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
+	}
+
+	/* check wether a vector already exists */	
+	l = apic_read(APIC_LVTTHMR);
+	if (l & 0xff) {
+		printk(KERN_DEBUG "CPU#%d: Thermal LVT already handled\n", cpu);
+		return; /* -EBUSY */
+	}
+	
+	wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
+	printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu);
+	
+	/* The temperature transition interrupt handler setup */
+	l = THERMAL_APIC_VECTOR;		/* our delivery vector */
+	l |= (APIC_DM_FIXED | APIC_LVT_MASKED);	/* we'll mask till we're ready */
+	apic_write_around(APIC_LVTTHMR, l);
+
+	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
+	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x3 , h);
+
+	/* ok we're good to go... */
+	vendor_thermal_interrupt = intel_thermal_interrupt;
+	l = apic_read(APIC_LVTTHMR);
+	apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+	return;
+#endif
+}
+
+/*
+ *	Machine Check Handler For PII/PIII
+ */
 
 static void intel_machine_check(struct pt_regs * regs, long error_code)
 {
@@ -20,7 +133,9 @@
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
 	int i;
-	
+
+	flush_all();
+
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 	if(mcgstl&(1<<0))	/* Recoverable ? */
 		recover=0;
@@ -41,13 +156,12 @@
 			if(high&(1<<27))
 			{
 				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
-				printk("[%08x%08x]", alow, ahigh);
+				printk("[%08x%08x]", ahigh, alow);
 			}
 			if(high&(1<<26))
 			{
 				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
-				printk(" at %08x%08x", 
-					ahigh, alow);
+				printk(" at %08x%08x", ahigh, alow);
 			}
 			printk("\n");
 			/* Clear it */
@@ -109,8 +223,55 @@
 	machine_check_vector(regs, error_code);
 }
 
+
+#ifdef CONFIG_X86_MCE_NONFATAL
+struct timer_list mce_timer;
+
+static void mce_checkregs (unsigned int cpu)
+{
+	u32 low, high;
+	int i;
+
+	if (cpu!=smp_processor_id())
+		BUG();
+
+	for (i=0; i<banks; i++) {
+		rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
+
+		if ((low | high) != 0) {
+			flush_all();
+			printk (KERN_EMERG "MCE: The hardware reports a non fatal, correctable incident occured on CPU %d.\n", smp_processor_id());
+			printk (KERN_EMERG "Bank %d: %08x%08x\n", i, high, low);
+
+			/* Scrub the error so we don't pick it up in 5 seconds time. */
+			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
+
+			/* Serialize */
+			wmb();
+		}
+	}
+
+	/* Refresh the timer. */
+	mce_timer.expires = jiffies + 5 * HZ;
+	add_timer (&mce_timer);
+}
+
+static void mce_timerfunc (unsigned long data)
+{
+	int i;
+
+	for (i=0; i<smp_num_cpus; i++) {
+		if (i == smp_processor_id())
+			mce_checkregs(i);
+		else
+			smp_call_function (mce_checkregs, i, 1, 1);
+	}
+}
+#endif
+
+
 /*
- *	Set up machine check reporting for Intel processors
+ *	Set up machine check reporting for processors with Intel style MCE
  */
 
 static void __init intel_mcheck_init(struct cpuinfo_x86 *c)
@@ -123,7 +284,7 @@
 	 *	Check for MCE support
 	 */
 
-	if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
+	if( !test_bit(X86_FEATURE_MCE, c->x86_capability) )
 		return;	
 	
 	/*
@@ -153,7 +314,7 @@
 	 *	Check for PPro style MCA
 	 */
 	 		
-	if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
+	if( !test_bit(X86_FEATURE_MCA, c->x86_capability) )
 		return;
 		
 	/* Ok machine check is available */
@@ -164,19 +325,27 @@
 	if(done==0)
 		printk(KERN_INFO "Intel machine check architecture supported.\n");
 	rdmsr(MSR_IA32_MCG_CAP, l, h);
-	if(l&(1<<8))
+	if(l&(1<<8))	/* Control register present ? */
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
 	banks = l&0xff;
-	for(i=1;i<banks;i++)
-	{
-		wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+
+	/* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */
+	if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6) {
+		for(i=1; i<banks; i++)
+			wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
+	} else {
+		for(i=0; i<banks; i++)
+			wrmsr(MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
 	}
-	for(i=0;i<banks;i++)
-	{
+
+	for(i=0; i<banks; i++)
 		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
-	}
+
 	set_in_cr4(X86_CR4_MCE);
 	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+	
+	intel_init_thermal(c);
+
 	done=1;
 }
 
@@ -206,28 +375,36 @@
  *	This has to be run for each processor
  */
 
-
-
 void __init mcheck_init(struct cpuinfo_x86 *c)
 {
 	if(mce_disabled==1)
 		return;
-		
+
 	switch(c->x86_vendor)
 	{
 		case X86_VENDOR_AMD:
-			/*
-			 *	AMD K7 machine check is Intel like
-			 */
-			if(c->x86 == 6)
+			/* AMD K7 machine check is Intel like */
+			if(c->x86 == 6) {
 				intel_mcheck_init(c);
+#ifdef CONFIG_X86_MCE_NONFATAL
+				/* Set the timer to check for non-fatal errors every 5 seconds */
+				init_timer (&mce_timer);
+				mce_timer.expires = jiffies + 5 * HZ;
+				mce_timer.data = 0;
+				mce_timer.function = &mce_timerfunc;
+				add_timer (&mce_timer);
+#endif
+			}
 			break;
+
 		case X86_VENDOR_INTEL:
 			intel_mcheck_init(c);
 			break;
+
 		case X86_VENDOR_CENTAUR:
 			winchip_mcheck_init(c);
 			break;
+
 		default:
 			break;
 	}
@@ -247,3 +424,9 @@
 
 __setup("nomce", mcheck_disable);
 __setup("mce", mcheck_enable);
+
+#else
+asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) {}
+asmlinkage void smp_thermal_interrupt(struct pt_regs regs) {}
+void __init mcheck_init(struct cpuinfo_x86 *c) {}
+#endif
diff -Nru a/arch/i386/kernel/bootflag.c b/arch/i386/kernel/bootflag.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/i386/kernel/bootflag.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,253 @@
+/*
+ *	Implement 'Simple Boot Flag Specification 1.0'
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#include <linux/mc146818rtc.h>
+
+
+#define SBF_RESERVED (0x78)
+#define SBF_PNPOS    (1<<0)
+#define SBF_BOOTING  (1<<1)
+#define SBF_DIAG     (1<<2)
+#define SBF_PARITY   (1<<7)
+
+
+struct sbf_boot
+{
+	u8 sbf_signature[4];
+	u32 sbf_len;
+	u8 sbf_revision __attribute((packed));
+	u8 sbf_csum __attribute((packed));
+	u8 sbf_oemid[6] __attribute((packed));
+	u8 sbf_oemtable[8] __attribute((packed));
+	u8 sbf_revdata[4] __attribute((packed));
+	u8 sbf_creator[4] __attribute((packed));
+	u8 sbf_crearev[4] __attribute((packed));
+	u8 sbf_cmos __attribute((packed));
+	u8 sbf_spare[3] __attribute((packed));
+};
+
+
+static int sbf_port __initdata = -1;
+
+static int __init sbf_struct_valid(unsigned long tptr)
+{
+	u8 *ap;
+	u8 v;
+	unsigned int i;
+	struct sbf_boot sb;
+	
+	memcpy_fromio(&sb, tptr, sizeof(sb));
+
+	if(sb.sbf_len != 40 && sb.sbf_len != 39)
+		// 39 on IBM ThinkPad A21m, BIOS version 1.02b (KXET24WW; 2000-12-19).
+		return 0;
+
+	ap = (u8 *)&sb;
+	v= 0;
+	
+	for(i=0;i<sb.sbf_len;i++)
+		v+=*ap++;
+		
+	if(v)
+		return 0;
+
+	if(memcmp(sb.sbf_signature, "BOOT", 4))
+		return 0;
+
+	if (sb.sbf_len == 39)
+		printk (KERN_WARNING "SBF: ACPI BOOT descriptor is wrong length (%d)\n",
+			sb.sbf_len);
+
+	sbf_port = sb.sbf_cmos;	/* Save CMOS port */
+	return 1;
+}
+
+static int __init parity(u8 v)
+{
+	int x = 0;
+	int i;
+	
+	for(i=0;i<8;i++)
+	{
+		x^=(v&1);
+		v>>=1;
+	}
+	return x;
+}
+
+static void __init sbf_write(u8 v)
+{
+	unsigned long flags;
+	if(sbf_port != -1)
+	{
+		v &= ~SBF_PARITY;
+		if(!parity(v))
+			v|=SBF_PARITY;
+
+		printk(KERN_INFO "SBF: Setting boot flags 0x%x\n",v);
+
+		spin_lock_irqsave(&rtc_lock, flags);
+		CMOS_WRITE(v, sbf_port);
+		spin_unlock_irqrestore(&rtc_lock, flags);
+	}
+}
+
+static u8 __init sbf_read(void)
+{
+	u8 v;
+	unsigned long flags;
+	if(sbf_port == -1)
+		return 0;
+	spin_lock_irqsave(&rtc_lock, flags);
+	v = CMOS_READ(sbf_port);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return v;
+}
+
+static int __init sbf_value_valid(u8 v)
+{
+	if(v&SBF_RESERVED)		/* Reserved bits */
+		return 0;
+	if(!parity(v))
+		return 0;
+	return 1;
+}
+
+
+static void __init sbf_bootup(void)
+{
+	u8 v;
+	if(sbf_port == -1)
+		return;
+	v = sbf_read();
+	if(!sbf_value_valid(v))
+		printk(KERN_WARNING "SBF: Simple boot flag value 0x%x read from CMOS RAM was invalid\n",v);
+	v &= ~SBF_RESERVED;
+	v &= ~SBF_BOOTING;
+	v &= ~SBF_DIAG;
+#if defined(CONFIG_ISAPNP)
+	v |= SBF_PNPOS;
+#endif
+	sbf_write(v);
+}
+
+static int __init sbf_init(void)
+{
+	unsigned int i;
+	void *rsdt;
+	u32 rsdtlen = 0;
+	u32 rsdtbase = 0;
+	u8 sum = 0;
+	int n;
+	
+	u8 *p;
+	
+	for(i=0xE0000; i <= 0xFFFE0; i+=16)
+	{
+		p = phys_to_virt(i);
+		
+		if(memcmp(p, "RSD PTR ", 8))
+			continue;
+		
+		sum = 0;
+		for(n=0; n<20; n++)
+			sum+=p[n];
+			
+		if(sum != 0)
+			continue;
+			
+		/* So it says RSD PTR and it checksums... */
+
+		/*
+		 *	Process the RDSP pointer
+		 */
+	 
+		rsdtbase = *(u32 *)(p+16);
+		
+		/*
+		 *	RSDT length is ACPI 2 only, for ACPI 1 we must map
+		 *	and remap.
+		 */
+		 
+		if(p[15]>1)
+			rsdtlen = *(u32 *)(p+20);
+		else
+			rsdtlen = 36;
+
+		if(rsdtlen < 36 || rsdtlen > 1024)
+			continue;
+		break;
+	}
+	if(i>0xFFFE0)
+		return 0;
+		
+		
+	rsdt = ioremap(rsdtbase, rsdtlen);
+	if(rsdt == 0)
+		return 0;
+		
+	i = readl(rsdt + 4);
+	
+	/*
+	 *	Remap if needed
+	 */
+	 
+	if(i > rsdtlen)
+	{
+		rsdtlen = i;
+		iounmap(rsdt);
+		rsdt = ioremap(rsdtbase, rsdtlen);
+		if(rsdt == 0)
+			return 0;
+	}
+	
+	for(n = 0; n < i; n++)
+		sum += readb(rsdt + n);
+		
+	if(sum)
+	{
+		iounmap(rsdt);
+		return 0;
+	}
+	
+	/* Ok the RSDT checksums too */
+	
+	for(n = 36; n+3 < i; n += 4)
+	{
+		unsigned long rp = readl(rsdt+n);
+		int len = 4096;
+
+		if(rp > 0xFFFFFFFFUL - len)
+			len = 0xFFFFFFFFUL - rp;
+			
+		/* Too close to the end!! */
+		if(len < 20)
+			continue;
+		rp = (unsigned long)ioremap(rp, 4096);
+		if(rp == 0)
+			continue;
+		if(sbf_struct_valid(rp))
+		{
+			/* Found the BOOT table and processed it */
+			printk(KERN_INFO "SBF: Simple Boot Flag extension found and enabled.\n");
+		}
+		iounmap((void *)rp);
+	}
+	iounmap(rsdt);
+	sbf_bootup();
+	return 0;
+}
+
+module_init(sbf_init);
diff -Nru a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
--- a/arch/i386/kernel/cpuid.c	Sun Apr 14 12:16:54 2002
+++ b/arch/i386/kernel/cpuid.c	Sun Apr 14 12:16:54 2002
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/smp.h>
 #include <linux/major.h>
+#include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/fs.h>
 
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Sun Apr 14 12:16:57 2002
+++ b/arch/i386/kernel/dmi_scan.c	Sun Apr 14 12:16:57 2002
@@ -295,6 +295,22 @@
 	return 0;
 }
 
+/*
+ * Work around broken HP Pavilion Notebooks which assign USB to
+ * IRQ 9 even though it is actually wired to IRQ 11
+ */
+static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_PCI
+	extern int broken_hp_bios_irq9;
+	if (broken_hp_bios_irq9 == 0)
+	{
+		broken_hp_bios_irq9 = 1;
+		printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
+	}
+#endif
+	return 0;
+}
 
 /*
  *  Check for clue free BIOS implementations who use
@@ -438,6 +454,25 @@
 }
 
 /*
+ * The Microstar 6163-2 (a.k.a Pro) mainboard will hang shortly after
+ * resumes, and also at what appears to be asynchronous APM events,
+ * if the local APIC is enabled.
+ */
+static int __init apm_kills_local_apic(struct dmi_blacklist *d)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	extern int dont_enable_local_apic;
+	if (apm_info.bios.version && !dont_enable_local_apic) {
+		dont_enable_local_apic = 1;
+		printk(KERN_WARNING "%s with broken BIOS detected. "
+		       "Refusing to enable the local APIC.\n",
+		       d->ident);
+	}
+#endif
+	return 0;
+}
+
+/*
  * The Intel AL440LX mainboard will hang randomly if the local APIC
  * timer is running and the APM BIOS hasn't been disabled.
  */
@@ -483,10 +518,10 @@
 			} },
 #endif			
 	{ broken_ps2_resume, "Dell Latitude C600", {	/* Handle problems with APM on the C600 */
-		        MATCH(DMI_SYS_VENDOR, "Dell"),
+			MATCH(DMI_SYS_VENDOR, "Dell"),
 			MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
 			NO_MATCH, NO_MATCH
-	                } },
+			} },
 	{ broken_apm_power, "Dell Inspiron 5000e", {	/* Handle problems with APM on Inspiron 5000e */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "A04"),
@@ -512,6 +547,11 @@
 			MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
 			NO_MATCH, NO_MATCH
 			} },
+	{ set_bios_reboot, "Dell PowerEdge 2400", {  /* Handle problems with rebooting on Dell 300/800's */
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
+			NO_MATCH, NO_MATCH
+			} },
 	{ set_apm_ints, "Dell Inspiron", {	/* Allow interrupts during suspend on Dell Inspiron laptops*/
 			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
 			MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
@@ -533,12 +573,23 @@
 			MATCH(DMI_PRODUCT_NAME, "Delhi3"),
 			NO_MATCH, NO_MATCH,
 			} },
+	{ apm_is_horked, "Fujitsu-Siemens", { /* APM crashes */
+			MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
+			MATCH(DMI_BIOS_VERSION, "Version1.01"),
+			NO_MATCH, NO_MATCH,
+			} },
 	{ apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
 			MATCH(DMI_SYS_VENDOR, "SHARP"),
 			MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
 			MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
 			MATCH(DMI_BIOS_VERSION,"Version R2.08")
 			} },
+	{ apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
+			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
+			MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION,"A11")
+			} },
 	{ sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
 			MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 			MATCH(DMI_PRODUCT_NAME, "PCG-"),
@@ -548,7 +599,7 @@
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0206H"),
 			MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
-	} },
+			} },
 
 	{ swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
@@ -574,6 +625,12 @@
 			MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
 			} },
 
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "R0206Z3"),
+			MATCH(DMI_BIOS_DATE, "12/25/00"), NO_MATCH
+			} },
+
 	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0203D0"),
@@ -617,6 +674,17 @@
 			NO_MATCH, NO_MATCH
 			} },
 
+	{ local_apic_kills_bios, "IBM Thinkpad T20", {
+			MATCH(DMI_BOARD_VENDOR, "IBM"),
+			MATCH(DMI_BOARD_NAME, "264741U"),
+			NO_MATCH, NO_MATCH
+			} },
+
+	{ apm_kills_local_apic, "Microstar 6163", {
+			MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			MATCH(DMI_BOARD_NAME, "MS-6163"),
+			NO_MATCH, NO_MATCH } },
+
 	{ apm_kills_local_apic_timer, "Intel AL440LX", {
 			MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
 			MATCH(DMI_BOARD_NAME, "AL440LX"),
@@ -678,7 +746,14 @@
 			NO_MATCH, NO_MATCH
 			} },
 	 
-			
+	{ fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
+			MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
+			MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
+			MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
+			} },
+ 
+
 	/*
 	 *	Generic per vendor APM settings
 	 */
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/kernel/entry.S	Sun Apr 14 12:16:56 2002
@@ -47,6 +47,7 @@
 #include <asm/errno.h>
 #include <asm/segment.h>
 #include <asm/smp.h>
+#include <asm/irq_vectors.h>
 
 EBX		= 0x00
 ECX		= 0x04
@@ -94,12 +95,12 @@
 
 #ifdef CONFIG_PREEMPT
 #define preempt_stop cli
-#define init_ret_intr \
-	cli; \
-	decl TI_PRE_COUNT(%ebx);
+#define INC_PRE_COUNT(reg) incl TI_PRE_COUNT(reg);
+#define DEC_PRE_COUNT(reg) decl TI_PRE_COUNT(reg);
 #else
 #define preempt_stop
-#define init_ret_intr
+#define INC_PRE_COUNT(reg)
+#define DEC_PRE_COUNT(reg)
 #define resume_kernel restore_all
 #endif
 
@@ -210,9 +211,9 @@
 
 	# userspace resumption stub bypassing syscall exit tracing
 	ALIGN
-ENTRY(ret_from_intr)
-	GET_THREAD_INFO(%ebx)
-	init_ret_intr
+ret_from_intr:
+	preempt_stop
+	DEC_PRE_COUNT(%ebx)
 ret_from_exception:
 	movl EFLAGS(%esp), %eax		# mix EFLAGS and CS
 	movb CS(%esp), %al
@@ -238,12 +239,11 @@
 	movl SYMBOL_NAME(irq_stat)+local_bh_count CPU_IDX, %ecx
 	addl SYMBOL_NAME(irq_stat)+local_irq_count CPU_IDX, %ecx
 	jnz restore_all
-	incl TI_PRE_COUNT(%ebx)
+	movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebx)
 	sti
-	movl TI_TASK(%ebx), %ecx		# ti->task
-	movl $0,(%ecx)			# current->state = TASK_RUNNING
 	call SYMBOL_NAME(schedule)
-	jmp ret_from_intr
+	movl $0,TI_PRE_COUNT(%ebx) 
+	jmp restore_all
 #endif
 
 	# system call handler stub
@@ -336,6 +336,67 @@
 	movl $-ENOSYS,EAX(%esp)
 	jmp resume_userspace
 
+/*
+ * Build the entry stubs and pointer table with
+ * some assembler magic.
+ */
+.data
+ENTRY(interrupt)
+.text
+
+vector=0
+ENTRY(irq_entries_start)
+.rept NR_IRQS
+	ALIGN
+1:	pushl $vector-256
+	jmp common_interrupt
+.data
+	.long 1b
+.text
+vector=vector+1
+.endr
+
+	ALIGN
+common_interrupt:
+	SAVE_ALL
+	GET_THREAD_INFO(%ebx)
+	INC_PRE_COUNT(%ebx)
+	call SYMBOL_NAME(do_IRQ)
+	jmp ret_from_intr
+
+#define BUILD_INTERRUPT(name, nr)	\
+ENTRY(name)				\
+	pushl $nr-256;			\
+	SAVE_ALL			\
+	GET_THREAD_INFO(%ebx);		\
+	INC_PRE_COUNT(%ebx)		\
+	call SYMBOL_NAME(smp_/**/name);	\
+	jmp ret_from_intr;
+
+/*
+ * The following vectors are part of the Linux architecture, there
+ * is no hardware IRQ pin equivalent for them, they are triggered
+ * through the ICC by us (IPIs)
+ */
+#ifdef CONFIG_SMP
+BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
+BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
+BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
+#endif
+
+/*
+ * every pentium local APIC has two 'local interrupts', with a
+ * soft-definable vector attached to both interrupts, one of
+ * which is a timer interrupt, the other one is error counter
+ * overflow. Linux uses the local APIC timer interrupt to get
+ * a much simpler SMP time architecture:
+ */
+#ifdef CONFIG_X86_LOCAL_APIC
+BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
+BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
+#endif
+
 ENTRY(divide_error)
 	pushl $0			# no error code
 	pushl $ SYMBOL_NAME(do_divide_error)
@@ -718,6 +779,8 @@
 	.long SYMBOL_NAME(sys_tkill)
 	.long SYMBOL_NAME(sys_sendfile64)
 	.long SYMBOL_NAME(sys_futex)		/* 240 */
+	.long SYMBOL_NAME(sys_sched_setaffinity)
+	.long SYMBOL_NAME(sys_sched_getaffinity)
 
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/i386_ksyms.c	Sun Apr 14 12:16:58 2002
@@ -28,6 +28,7 @@
 #include <asm/desc.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
@@ -93,7 +94,6 @@
 EXPORT_SYMBOL_NOVERS(__get_user_2);
 EXPORT_SYMBOL_NOVERS(__get_user_4);
 
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
@@ -143,6 +143,10 @@
 
 /* TLB flushing */
 EXPORT_SYMBOL(flush_tlb_page);
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 #endif
 
 #ifdef CONFIG_MCA
diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	Sun Apr 14 12:16:59 2002
+++ b/arch/i386/kernel/i8259.c	Sun Apr 14 12:16:59 2002
@@ -25,102 +25,6 @@
 #include <linux/irq.h>
 
 /*
- * Common place to define all x86 IRQ vectors
- *
- * This builds up the IRQ handler stubs using some ugly macros in irq.h
- *
- * These macros create the low-level assembly IRQ routines that save
- * register context and call do_IRQ(). do_IRQ() then does all the
- * operations that are needed to keep the AT (or SMP IOAPIC)
- * interrupt-controller happy.
- */
-
-BUILD_COMMON_IRQ()
-
-#define BI(x,y) \
-	BUILD_IRQ(x##y)
-
-#define BUILD_16_IRQS(x) \
-	BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
-	BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
-	BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
-	BI(x,c) BI(x,d) BI(x,e) BI(x,f)
-
-/*
- * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
- * (these are usually mapped to vectors 0x20-0x2f)
- */
-BUILD_16_IRQS(0x0)
-
-#ifdef CONFIG_X86_IO_APIC
-/*
- * The IO-APIC gives us many more interrupt sources. Most of these 
- * are unused but an SMP system is supposed to have enough memory ...
- * sometimes (mostly wrt. hw bugs) we get corrupted vectors all
- * across the spectrum, so we really want to be prepared to get all
- * of these. Plus, more powerful systems might have more than 64
- * IO-APIC registers.
- *
- * (these are usually mapped into the 0x30-0xff vector range)
- */
-		   BUILD_16_IRQS(0x1) BUILD_16_IRQS(0x2) BUILD_16_IRQS(0x3)
-BUILD_16_IRQS(0x4) BUILD_16_IRQS(0x5) BUILD_16_IRQS(0x6) BUILD_16_IRQS(0x7)
-BUILD_16_IRQS(0x8) BUILD_16_IRQS(0x9) BUILD_16_IRQS(0xa) BUILD_16_IRQS(0xb)
-BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
-#endif
-
-#undef BUILD_16_IRQS
-#undef BI
-
-
-/*
- * The following vectors are part of the Linux architecture, there
- * is no hardware IRQ pin equivalent for them, they are triggered
- * through the ICC by us (IPIs)
- */
-#ifdef CONFIG_SMP
-BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
-BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
-BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
-#endif
-
-/*
- * every pentium local APIC has two 'local interrupts', with a
- * soft-definable vector attached to both interrupts, one of
- * which is a timer interrupt, the other one is error counter
- * overflow. Linux uses the local APIC timer interrupt to get
- * a much simpler SMP time architecture:
- */
-#ifdef CONFIG_X86_LOCAL_APIC
-BUILD_SMP_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
-BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
-BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
-#endif
-
-#define IRQ(x,y) \
-	IRQ##x##y##_interrupt
-
-#define IRQLIST_16(x) \
-	IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
-	IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
-	IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
-	IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
-
-void (*interrupt[NR_IRQS])(void) = {
-	IRQLIST_16(0x0),
-
-#ifdef CONFIG_X86_IO_APIC
-			 IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
-	IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
-	IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
-	IRQLIST_16(0xc), IRQLIST_16(0xd)
-#endif
-};
-
-#undef IRQ
-#undef IRQLIST_16
-
-/*
  * This is the 'legacy' 8259A Programmable Interrupt Controller,
  * present in the majority of PC/AT boxes.
  * plus some generic x86 specific things if generic specifics makes
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Sun Apr 14 12:16:57 2002
+++ b/arch/i386/kernel/io_apic.c	Sun Apr 14 12:16:57 2002
@@ -597,7 +597,6 @@
 	return current_vector;
 }
 
-extern void (*interrupt[NR_IRQS])(void);
 static struct hw_interrupt_type ioapic_level_irq_type;
 static struct hw_interrupt_type ioapic_edge_irq_type;
 
diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
--- a/arch/i386/kernel/microcode.c	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/kernel/microcode.c	Sun Apr 14 12:16:56 2002
@@ -51,6 +51,12 @@
  *		Bugfix for HT (Hyper-Threading) enabled processors
  *		whereby processor resources are shared by all logical processors
  *		in a single CPU package.
+ *	1.10	28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
+ *		Tigran Aivazian <tigran@veritas.com>,
+ *		Serialize updates as required on HT processors due to speculative
+ *		nature of implementation.
+ *	1.11	22 Mar 2001 Tigran Aivazian <tigran@veritas.com>
+ *		Fix the panic when writing zero-length microcode chunk.
  */
 
 #include <linux/init.h>
@@ -60,12 +66,16 @@
 #include <linux/vmalloc.h>
 #include <linux/miscdevice.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/spinlock.h>
 
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-#define MICROCODE_VERSION 	"1.09"
+
+static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED;
+
+#define MICROCODE_VERSION 	"1.11"
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
@@ -195,7 +205,8 @@
 	struct cpuinfo_x86 *c = cpu_data + cpu_num;
 	struct update_req *req = update_req + cpu_num;
 	unsigned int pf = 0, val[2], rev, sig;
-	int i,found=0;
+	unsigned long flags;
+	int i;
 
 	req->err = 1; /* assume update will fail on this cpu */
 
@@ -216,8 +227,9 @@
 	for (i=0; i<microcode_num; i++)
 		if (microcode[i].sig == sig && microcode[i].pf == pf &&
 		    microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
-
-			found=1;
+			int sum = 0;
+			struct microcode *m = &microcode[i];
+			unsigned int *sump = (unsigned int *)(m+1);
 
 			printf("Microcode\n");
 			printf("   Header Revision %d\n",microcode[i].hdrver);
@@ -234,54 +246,69 @@
 			printf("   Loader Revision %x\n",microcode[i].ldrver);
 			printf("   Processor Flags %x\n\n",microcode[i].pf);
 
+			req->slot = i;
+
+			/* serialize access to update decision */
+			spin_lock_irqsave(&microcode_update_lock, flags);          
+
 			/* trick, to work even if there was no prior update by the BIOS */
 			wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 			__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
 
 			/* get current (on-cpu) revision into rev (ignore val[0]) */
 			rdmsr(MSR_IA32_UCODE_REV, val[0], rev);
+			
 			if (microcode[i].rev < rev) {
+				spin_unlock_irqrestore(&microcode_update_lock, flags);
 				printk(KERN_ERR 
-					"microcode: CPU%d not 'upgrading' to earlier revision"
+				       "microcode: CPU%d not 'upgrading' to earlier revision"
+				       " %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
+				return;
+			} else if (microcode[i].rev == rev) {
+				/* notify the caller of success on this cpu */
+				req->err = 0;
+				spin_unlock_irqrestore(&microcode_update_lock, flags);
+				printk(KERN_ERR 
+					"microcode: CPU%d already at revision"
 					" %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
-			} else {
-				int sum = 0;
-				struct microcode *m = &microcode[i];
-				unsigned int *sump = (unsigned int *)(m+1);
-
-				while (--sump >= (unsigned int *)m)
-					sum += *sump;
-				if (sum != 0) {
-					printk(KERN_ERR "microcode: CPU%d aborting, "
-							"bad checksum\n", cpu_num);
-					break;
-				}
-
-				/* write microcode via MSR 0x79 */
-				wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
+				return;
+			}
 
-				/* serialize */
-				__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+			/* Verify the checksum */
+			while (--sump >= (unsigned int *)m)
+				sum += *sump;
+			if (sum != 0) {
+				req->err = 1;
+				spin_unlock_irqrestore(&microcode_update_lock, flags);
+				printk(KERN_ERR "microcode: CPU%d aborting, "
+				       "bad checksum\n", cpu_num);
+				return;
+			}
+			
+			/* write microcode via MSR 0x79 */
+			wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
 
-				/* get the current revision from MSR 0x8B */
-				rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+			/* serialize */
+			__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
 
-				/* notify the caller of success on this cpu */
-				req->err = 0;
-				req->slot = i;
+			/* get the current revision from MSR 0x8B */
+			rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-				printk(KERN_INFO "microcode: CPU%d updated from revision "
-						"%d to %d, date=%08x\n", 
-						cpu_num, rev, val[1], m->date);
-			}
-			break;
+			/* notify the caller of success on this cpu */
+			req->err = 0;
+			spin_unlock_irqrestore(&microcode_update_lock, flags);
+			printk(KERN_INFO "microcode: CPU%d updated from revision "
+			       "%d to %d, date=%08x\n", 
+			       cpu_num, rev, val[1], microcode[i].date);
+			return;
 		}
-
-	if(!found)
-		printk(KERN_ERR "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n",
-				cpu_num, sig, pf);
+	
+	printk(KERN_ERR
+	       "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n", 
+	       cpu_num, sig, pf);
 }
 
+
 static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
 {
 	ssize_t ret = 0;
@@ -305,9 +332,13 @@
 {
 	ssize_t ret;
 
-	if (len % sizeof(struct microcode) != 0) {
+	if (!len || len % sizeof(struct microcode) != 0) {
 		printk(KERN_ERR "microcode: can only write in N*%d bytes units\n", 
 			sizeof(struct microcode));
+		return -EINVAL;
+	}
+	if ((len >> PAGE_SHIFT) > num_physpages) {
+		printk(KERN_ERR "microcode: too much data (max %d pages)\n", num_physpages);
 		return -EINVAL;
 	}
 	down_write(&microcode_rwsem);
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
--- a/arch/i386/kernel/mpparse.c	Sun Apr 14 12:16:57 2002
+++ b/arch/i386/kernel/mpparse.c	Sun Apr 14 12:16:57 2002
@@ -14,7 +14,6 @@
 
 #include <linux/mm.h>
 #include <linux/irq.h>
-#include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/config.h>
@@ -24,6 +23,7 @@
 #include <linux/mc146818rtc.h>
 
 #include <asm/smp.h>
+#include <asm/acpi.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
@@ -31,9 +31,6 @@
 /* Have we found an MP table */
 int smp_found_config;
 
-/* Have we found an ACPI MADT table */
-int acpi_found_madt = 0;
-
 /*
  * Various Linux-internal data structures created from the
  * MP-table.
@@ -41,8 +38,6 @@
 int apic_version [MAX_APICS];
 int mp_bus_id_to_type [MAX_MP_BUSSES];
 int mp_bus_id_to_node [MAX_MP_BUSSES];
-int mp_bus_id_to_local [MAX_MP_BUSSES];
-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_current_pci_id;
 
@@ -69,19 +64,6 @@
 /* Bitmask of physically existing CPUs */
 unsigned long phys_cpu_present_map;
 
-/* ACPI MADT entry parsing functions */
-#ifdef CONFIG_ACPI_BOOT
-extern struct acpi_boot_flags acpi_boot;
-#ifdef CONFIG_X86_LOCAL_APIC
-extern int acpi_parse_lapic (acpi_table_entry_header *header);
-extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
-extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
-#endif /*CONFIG_X86_LOCAL_APIC*/
-#ifdef CONFIG_X86_IO_APIC
-extern int acpi_parse_ioapic (acpi_table_entry_header *header);
-#endif /*CONFIG_X86_IO_APIC*/
-#endif /*CONFIG_ACPI_BOOT*/
-
 /*
  * Intel MP BIOS table parsing routines:
  */
@@ -139,7 +121,7 @@
 	return n;
 }
 
-/*
+/* 
  * Have to match translation table entries to main table entries by counter
  * hence the mpc_record variable .... can't see a less disgusting way of
  * doing this ....
@@ -232,6 +214,7 @@
 	if (m->mpc_apicid > MAX_APICS) {
 		printk("Processor #%d INVALID. (Max ID: %d).\n",
 			m->mpc_apicid, MAX_APICS);
+		--num_processors;
 		return;
 	}
 	ver = m->mpc_apicver;
@@ -254,17 +237,13 @@
 static void __init MP_bus_info (struct mpc_config_bus *m)
 {
 	char str[7];
-	int quad;
 
 	memcpy(str, m->mpc_bustype, 6);
 	str[6] = 0;
 	
 	if (clustered_apic_mode) {
-		quad = translation_table[mpc_record]->trans_quad;
-		mp_bus_id_to_node[m->mpc_busid] = quad;
-		mp_bus_id_to_local[m->mpc_busid] = translation_table[mpc_record]->trans_local;
-		quad_local_to_mp_bus_id[quad][translation_table[mpc_record]->trans_local] = m->mpc_busid;
-		printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, quad);
+		mp_bus_id_to_node[m->mpc_busid] = translation_table[mpc_record]->trans_quad;
+		printk("Bus #%d is %s (node %d)\n", m->mpc_busid, str, mp_bus_id_to_node[m->mpc_busid]);
 	} else {
 		Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
 	}
@@ -341,14 +320,13 @@
 
 static void __init MP_translation_info (struct mpc_config_translation *m)
 {
-	printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
+	printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, 
+		m->trans_quad, m->trans_global, m->trans_local);
 
 	if (mpc_record >= MAX_MPC_ENTRY) 
 		printk("MAX_MPC_ENTRY exceeded!\n");
 	else
 		translation_table[mpc_record] = m; /* stash this for later */
-	if (m->trans_quad+1 > numnodes)
-		numnodes = m->trans_quad+1;
 }
 
 /*
@@ -438,11 +416,11 @@
 
 	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
 
-	/*
-	 * Save the local APIC address, it might be non-default,
-	 * but only if we're not using the ACPI tables
+	/* 
+	 * Save the local APIC address (it might be non-default), but only 
+	 * if we're not using the ACPI tables.
 	 */
-	if (!acpi_found_madt)
+	if (!acpi_mp_config)
 		mp_lapic_addr = mpc->mpc_lapic;
 
 	if (clustered_apic_mode && mpc->mpc_oemptr) {
@@ -463,7 +441,7 @@
 					(struct mpc_config_processor *)mpt;
 
 				/* ACPI may already have provided this one for us */
-				if (!acpi_found_madt)
+				if (!acpi_mp_config)
 					MP_processor_info(m);
 				mpt += sizeof(*m);
 				count += sizeof(*m);
@@ -514,6 +492,10 @@
 		}
 		++mpc_record;
 	}
+	if (clustered_apic_mode && nr_ioapics > 2) {
+		/* don't initialise IO apics on secondary quads */
+		nr_ioapics = 2;
+	}
 	if (!num_processors)
 		printk(KERN_ERR "SMP mptable: no processors registered!\n");
 	return num_processors;
@@ -685,20 +667,6 @@
 {
 	struct intel_mp_floating *mpf = mpf_found;
 
-#ifdef CONFIG_ACPI_BOOT
-	/*
-	 * Check if the MADT exists, and if so, use it to get processor
-	 * information (ACPI_MADT_LAPIC).  The MADT supports the concept
-	 * of both logical (e.g. HT) and physical processor(s); where the
-	 * MPS only supports physical.
-	 */
-	if (acpi_boot.madt) {
-		acpi_found_madt = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
-		if (acpi_found_madt > 0)
-			acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
-	}
-#endif /*CONFIG_ACPI_BOOT*/
-	
 	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
 	if (mpf->mpf_feature2 & (1<<7)) {
 		printk("    IMCR and PIC compatibility mode.\n");
@@ -816,11 +784,13 @@
 	 * trustworthy, simply because the SMP table may have been
 	 * stomped on during early boot. These loaders are buggy and
 	 * should be fixed.
+	 *
+	 * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
 	 */
 
 	address = *(unsigned short *)phys_to_virt(0x40E);
 	address <<= 4;
-	smp_scan_config(address, 0x1000);
+	smp_scan_config(address, 0x400);
 	if (smp_found_config)
 		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n");
 }
diff -Nru a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
--- a/arch/i386/kernel/mtrr.c	Sun Apr 14 12:16:55 2002
+++ b/arch/i386/kernel/mtrr.c	Sun Apr 14 12:16:55 2002
@@ -387,7 +387,7 @@
 	 return;
 
     /*  Save value of CR4 and clear Page Global Enable (bit 7)  */
-    if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) {
+    if ( test_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability) ) {
 	ctxt->cr4val = read_cr4();
 	write_cr4(ctxt->cr4val & (unsigned char) ~(1<<7));
     }
@@ -448,7 +448,7 @@
     write_cr0( read_cr0() & 0xbfffffff );
 
     /*  Restore value of CR4  */
-    if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) )
+    if ( test_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability) )
 	write_cr4(ctxt->cr4val);
 
     /*  Re-enable interrupts locally (if enabled previously)  */
@@ -498,7 +498,6 @@
     case MTRR_IF_INTEL:
 	rdmsr (MTRRcap_MSR, config, dummy);
 	return (config & (1<<10));
-	return 1;
     case MTRR_IF_AMD_K6:
     case MTRR_IF_CENTAUR_MCR:
     case MTRR_IF_CYRIX_ARR:
@@ -2123,7 +2122,7 @@
 
 static int __init mtrr_setup(void)
 {
-    if ( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ) {
+    if ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ) {
 	/* Intel (P6) standard MTRRs */
 	mtrr_if = MTRR_IF_INTEL;
 	get_mtrr = intel_get_mtrr;
@@ -2167,14 +2166,14 @@
 		break;
 	}
 
-    } else if ( test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ) {
+    } else if ( test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ) {
 	/* Pre-Athlon (K6) AMD CPU MTRRs */
 	mtrr_if = MTRR_IF_AMD_K6;
 	get_mtrr = amd_get_mtrr;
 	set_mtrr_up = amd_set_mtrr_up;
 	size_or_mask  = 0xfff00000; /* 32 bits */
 	size_and_mask = 0;
-    } else if ( test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ) {
+    } else if ( test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ) {
 	/* Cyrix ARRs */
 	mtrr_if = MTRR_IF_CYRIX_ARR;
 	get_mtrr = cyrix_get_arr;
@@ -2183,7 +2182,7 @@
 	cyrix_arr_init();
 	size_or_mask  = 0xfff00000; /* 32 bits */
 	size_and_mask = 0;
-    } else if ( test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) {
+    } else if ( test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) {
 	/* Centaur MCRs */
 	mtrr_if = MTRR_IF_CENTAUR_MCR;
 	get_mtrr = centaur_get_mcr;
diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
--- a/arch/i386/kernel/nmi.c	Sun Apr 14 12:16:54 2002
+++ b/arch/i386/kernel/nmi.c	Sun Apr 14 12:16:54 2002
@@ -8,6 +8,7 @@
  *  Fixes:
  *  Mikael Pettersson	: AMD K7 support for local APIC NMI watchdog.
  *  Mikael Pettersson	: Power Management for local APIC NMI watchdog.
+ *  Mikael Pettersson	: Pentium 4 support for local APIC NMI watchdog.
  */
 
 #include <linux/config.h>
@@ -43,6 +44,32 @@
 #define P6_EVENT_CPU_CLOCKS_NOT_HALTED	0x79
 #define P6_NMI_EVENT		P6_EVENT_CPU_CLOCKS_NOT_HALTED
 
+#define MSR_P4_MISC_ENABLE	0x1A0
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL	(1<<7)
+#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL	(1<<12)
+#define MSR_P4_PERFCTR0		0x300
+#define MSR_P4_CCCR0		0x360
+#define P4_ESCR_EVENT_SELECT(N)	((N)<<25)
+#define P4_ESCR_OS		(1<<3)
+#define P4_ESCR_USR		(1<<2)
+#define P4_CCCR_OVF_PMI		(1<<26)
+#define P4_CCCR_THRESHOLD(N)	((N)<<20)
+#define P4_CCCR_COMPLEMENT	(1<<19)
+#define P4_CCCR_COMPARE		(1<<18)
+#define P4_CCCR_REQUIRED	(3<<16)
+#define P4_CCCR_ESCR_SELECT(N)	((N)<<13)
+#define P4_CCCR_ENABLE		(1<<12)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+#define MSR_P4_IQ_COUNTER0	0x30C
+#define MSR_P4_IQ_CCCR0		0x36C
+#define MSR_P4_CRU_ESCR0	0x3B8
+#define P4_NMI_CRU_ESCR0	(P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
+#define P4_NMI_IQ_CCCR0	\
+	(P4_CCCR_OVF_PMI|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
+	 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+
 int __init check_nmi_watchdog (void)
 {
 	irq_cpustat_t tmp[NR_CPUS];
@@ -84,11 +111,11 @@
 	/*
 	 * If any other x86 CPU has a local APIC, then
 	 * please test the NMI stuff there and send me the
-	 * missing bits. Right now Intel P6 and AMD K7 only.
+	 * missing bits. Right now Intel P6/P4 and AMD K7 only.
 	 */
 	if ((nmi == NMI_LOCAL_APIC) &&
 			(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
-			(boot_cpu_data.x86 == 6))
+			(boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
 		nmi_watchdog = nmi;
 	if ((nmi == NMI_LOCAL_APIC) &&
 			(boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
@@ -118,7 +145,15 @@
 		wrmsr(MSR_K7_EVNTSEL0, 0, 0);
 		break;
 	case X86_VENDOR_INTEL:
-		wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
+		switch (boot_cpu_data.x86) {
+		case 6:
+			wrmsr(MSR_P6_EVNTSEL0, 0, 0);
+			break;
+		case 15:
+			wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
+			wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+			break;
+		}
 		break;
 	}
 }
@@ -157,17 +192,22 @@
  * Original code written by Keith Owens.
  */
 
+static void __pminit clear_msr_range(unsigned int base, unsigned int n)
+{
+	unsigned int i;
+
+	for(i = 0; i < n; ++i)
+		wrmsr(base+i, 0, 0);
+}
+
 static void __pminit setup_k7_watchdog(void)
 {
-	int i;
 	unsigned int evntsel;
 
 	nmi_perfctr_msr = MSR_K7_PERFCTR0;
 
-	for(i = 0; i < 4; ++i) {
-		wrmsr(MSR_K7_EVNTSEL0+i, 0, 0);
-		wrmsr(MSR_K7_PERFCTR0+i, 0, 0);
-	}
+	clear_msr_range(MSR_K7_EVNTSEL0, 4);
+	clear_msr_range(MSR_K7_PERFCTR0, 4);
 
 	evntsel = K7_EVNTSEL_INT
 		| K7_EVNTSEL_OS
@@ -184,27 +224,54 @@
 
 static void __pminit setup_p6_watchdog(void)
 {
-	int i;
 	unsigned int evntsel;
 
-	nmi_perfctr_msr = MSR_IA32_PERFCTR0;
+	nmi_perfctr_msr = MSR_P6_PERFCTR0;
 
-	for(i = 0; i < 2; ++i) {
-		wrmsr(MSR_IA32_EVNTSEL0+i, 0, 0);
-		wrmsr(MSR_IA32_PERFCTR0+i, 0, 0);
-	}
+	clear_msr_range(MSR_P6_EVNTSEL0, 2);
+	clear_msr_range(MSR_P6_PERFCTR0, 2);
 
 	evntsel = P6_EVNTSEL_INT
 		| P6_EVNTSEL_OS
 		| P6_EVNTSEL_USR
 		| P6_NMI_EVENT;
 
-	wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0);
-	Dprintk("setting IA32_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
-	wrmsr(MSR_IA32_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
+	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+	Dprintk("setting P6_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
+	wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= P6_EVNTSEL0_ENABLE;
-	wrmsr(MSR_IA32_EVNTSEL0, evntsel, 0);
+	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+}
+
+static int __pminit setup_p4_watchdog(void)
+{
+	unsigned int misc_enable, dummy;
+
+	rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+	if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+		return 0;
+
+	nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
+
+	if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
+		clear_msr_range(0x3F1, 2);
+	/* MSR 0x3F0 seems to have a default value of 0xFC00, but current
+	   docs doesn't fully define it, so leave it alone for now. */
+	clear_msr_range(0x3A0, 31);
+	clear_msr_range(0x3C0, 6);
+	clear_msr_range(0x3C8, 6);
+	clear_msr_range(0x3E0, 2);
+	clear_msr_range(MSR_P4_CCCR0, 18);
+	clear_msr_range(MSR_P4_PERFCTR0, 18);
+
+	wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
+	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
+	Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
+	wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
+	return 1;
 }
 
 void __pminit setup_apic_nmi_watchdog (void)
@@ -216,9 +283,17 @@
 		setup_k7_watchdog();
 		break;
 	case X86_VENDOR_INTEL:
-		if (boot_cpu_data.x86 != 6)
+		switch (boot_cpu_data.x86) {
+		case 6:
+			setup_p6_watchdog();
+			break;
+		case 15:
+			if (!setup_p4_watchdog())
+				return;
+			break;
+		default:
 			return;
-		setup_p6_watchdog();
+		}
 		break;
 	default:
 		return;
@@ -296,6 +371,18 @@
 		last_irq_sums[cpu] = sum;
 		alert_counter[cpu] = 0;
 	}
-	if (nmi_perfctr_msr)
+	if (nmi_perfctr_msr) {
+		if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
+			/*
+			 * P4 quirks:
+			 * - An overflown perfctr will assert its interrupt
+			 *   until the OVF flag in its CCCR is cleared.
+			 * - LVTPC is masked on interrupt and must be
+			 *   unmasked by the LVTPC handler.
+			 */
+			wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0, 0);
+			apic_write(APIC_LVTPC, APIC_DM_NMI);
+		}
 		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+	}
 }
diff -Nru a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
--- a/arch/i386/kernel/pci-dma.c	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/kernel/pci-dma.c	Sun Apr 14 12:16:56 2002
@@ -19,7 +19,7 @@
 	void *ret;
 	int gfp = GFP_ATOMIC;
 
-	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+	if (hwdev == NULL || ((u32)hwdev->dma_mask != 0xffffffff))
 		gfp |= GFP_DMA;
 	ret = (void *)__get_free_pages(gfp, get_order(size));
 
diff -Nru a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
--- a/arch/i386/kernel/pci-irq.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/pci-irq.c	Sun Apr 14 12:16:58 2002
@@ -23,6 +23,7 @@
 #define PIRQ_VERSION 0x0100
 
 int pci_use_acpi_routing = 0;
+int broken_hp_bios_irq9;
 
 static struct irq_routing_table *pirq_table;
 
@@ -208,6 +209,24 @@
 }
 
 /*
+ * ITE 8330G pirq rules are nibble-based
+ * FIXME: pirqmap may be { 1, 0, 3, 2 },
+ * 	  2+3 are both mapped to irq 9 on my system
+ */
+static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
+}
+
+static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
+	return 1;
+}
+
+/*
  * OPTI: high four bits are nibble pointer..
  * I wonder what the low bits do?
  */
@@ -227,12 +246,12 @@
  */
 static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	return read_config_nybble(router, 0x5C, pirq-1);
+	return read_config_nybble(router, 0x5C, (pirq-1)^1);
 }
 
 static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	write_config_nybble(router, 0x5C, pirq-1, irq);
+	write_config_nybble(router, 0x5C, (pirq-1)^1, irq);
 	return 1;
 }
 
@@ -445,10 +464,17 @@
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX,   pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, pirq_piix_get, pirq_piix_set },
 
 	{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
 
+	{ "ITE", PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8330G_0, pirq_ite_get, pirq_ite_set },
+
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
@@ -514,6 +540,18 @@
 		pirq_router_dev->slot_name);
 }
 
+static struct irq_info *pirq_get_info(struct pci_dev *dev)
+{
+	struct irq_routing_table *rt = pirq_table;
+	int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+	struct irq_info *info;
+
+	for (info = rt->slots; entries--; info++)
+		if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
+			return info;
+	return NULL;
+}
+
 static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 }
@@ -531,55 +569,77 @@
 	/* TBD: Select IRQ from possible to improve routing performance. */
 
 	result = acpi_prt_get_irq(dev, pin, &irq);
-	if ((0 != result) || !irq) {
-		printk(KERN_ERR "PCI: Unable to resolve IRQ for device %s\n",
-			dev->slot_name);
+	if (!irq)
+		result = -ENODEV;
+	if (0 != result) {
+		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s\n",
+		       'A'+pin, dev->slot_name);
 		return result;
 	}
 
-	printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", irq, 
-		dev->slot_name);
-
 	dev->irq = irq;
 
-	pirq_penalty[irq]++;
+	if (!assign) {
+		/* only check for the IRQ */
+		printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", irq, 
+		       dev->slot_name);
+		return 1;
+	}
+
+	/* also assign an IRQ */
+	if (irq && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+		result = acpi_prt_set_irq(dev, pin, irq);
+		if (0 != result) {
+			printk(KERN_WARNING "PCI: Could not assign IRQ %d to device %s\n", irq, dev->slot_name);
+			return result;
+		}
+
+		eisa_set_level_irq(irq);
+
+		printk(KERN_INFO "PCI: Assigned IRQ %d for device %s\n", irq, dev->slot_name);
+	}
 
 	return 1;
 }
 
 #endif /* CONFIG_ACPI_PCI */
 
-static struct irq_info *pirq_get_info(struct pci_dev *dev)
+static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 {
-	struct irq_routing_table *rt = pirq_table;
-	int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
+	u8 pin;
 	struct irq_info *info;
-
-	for (info = rt->slots; entries--; info++)
-		if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
-			return info;
-	return NULL;
-}
-
-static int pirq_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
-{
+	int i, pirq, newirq;
+	int irq = 0;
+	u32 mask;
 	struct irq_router *r = pirq_router;
-	struct irq_info *info;
-	int  newirq, pirq, i, irq = 0;
 	struct pci_dev *dev2;
 	char *msg = NULL;
-	u32 mask;
 
-	if (!pirq_table)
+	/* Find IRQ pin */
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (!pin) {
+		DBG(" -> no interrupt pin\n");
 		return 0;
+	}
+	pin = pin - 1;
+
+#ifdef CONFIG_ACPI_PCI
+	/* Use ACPI to lookup IRQ */
+	if (pci_use_acpi_routing)
+		return acpi_lookup_irq(dev, pin, assign);
+#endif
+
+	/* Find IRQ routing entry */
 
+	if (!pirq_table)
+		return 0;
+	
 	DBG("IRQ for %s:%d", dev->slot_name, pin);
 	info = pirq_get_info(dev);
 	if (!info) {
 		DBG(" -> not found in routing table\n");
 		return 0;
 	}
-
 	pirq = info->irq[pin].link;
 	mask = info->irq[pin].bitmap;
 	if (!pirq) {
@@ -589,6 +649,15 @@
 	DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
 	mask &= pcibios_irq_mask;
 
+	/* Work around broken HP Pavilion Notebooks which assign USB to
+	   IRQ 9 even though it is actually wired to IRQ 11 */
+
+	if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
+		dev->irq = 11;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		r->set(pirq_router_dev, dev, pirq, 11);
+	}
+
 	/*
 	 * Find the best IRQ to assign: use the one
 	 * reported by the device if possible.
@@ -667,38 +736,20 @@
 	return 1;
 }
 
-static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
-{
-	u8 pin;
-
-	/* Find IRQ routing entry */
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-	if (!pin) {
-		DBG("PCI: %s: no interrupt pin\n", dev->slot_name);
-		return 0;
-	}
-	pin -= 1;
-
-#ifdef CONFIG_ACPI_PCI
-	if (pci_use_acpi_routing)
-		return acpi_lookup_irq(dev, pin, assign);
-	else
-#endif
-		return pirq_lookup_irq(dev, pin, assign);
-}
-
 void __init pcibios_irq_init(void)
 {
 	DBG("PCI: IRQ init\n");
 
 #ifdef CONFIG_ACPI_PCI
-	if (acpi_prts.count && !(pci_probe & PCI_NO_ACPI_ROUTING)) {
-		printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-		pci_use_acpi_routing = 1;
-		return;
+	if (!(pci_probe & PCI_NO_ACPI_ROUTING)) {
+		if (acpi_prts.count) {
+			printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
+			pci_use_acpi_routing = 1;
+			return;
+		}
+		else
+			printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
 	}
-	if (!acpi_prts.count)
-		printk(KERN_INFO "PCI: Invalid acpi_prts [%d]\n", acpi_prts.count);
 #endif
 
 	pirq_table = pirq_find_routing_table();
diff -Nru a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
--- a/arch/i386/kernel/pci-pc.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/pci-pc.c	Sun Apr 14 12:16:58 2002
@@ -1205,7 +1205,8 @@
 
         pci_read_config_byte(d, where, &v);
 	if (v & 0xe0) {
-		printk("Disabling broken memory write queue.\n");
+		printk("Disabling broken memory write queue: [%02x] %02x->%02x\n",
+			where, v, v & 0x1f);
 		v &= 0x1f; /* clear bits 5, 6, 7 */
 		pci_write_config_byte(d, where, v);
 	}
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	Sun Apr 14 12:16:57 2002
+++ b/arch/i386/kernel/ptrace.c	Sun Apr 14 12:16:57 2002
@@ -455,11 +455,9 @@
 	   between a syscall stop and SIGTRAP delivery */
 	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
 					? 0x80 : 0);
-	preempt_disable();
 	current->state = TASK_STOPPED;
 	notify_parent(current, SIGCHLD);
 	schedule();
-	preempt_enable();
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/setup.c	Sun Apr 14 12:16:58 2002
@@ -99,6 +99,8 @@
 #endif
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
 #include <linux/seq_file.h>
 #include <linux/console.h>
 #include <asm/processor.h>
@@ -127,9 +129,6 @@
 /*
  * Bus types ..
  */
-#ifdef CONFIG_EISA
-int EISA_bus;
-#endif
 int MCA_bus;
 
 /* for MCA, but anyone else can use it if they want */
@@ -210,6 +209,10 @@
 	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 	{ "fpu", 0xf0, 0xff, IORESOURCE_BUSY }
 };
+#ifdef CONFIG_MELAN
+standard_io_resources[1] = { "pic1", 0x20, 0x21, IORESOURCE_BUSY };
+standard_io_resources[5] = { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY };
+#endif
 
 #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
 
@@ -609,7 +612,7 @@
 				to--;
 			if (!memcmp(from+4, "nopentium", 9)) {
 				from += 9+4;
-				clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability);
+				clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
 			} else if (!memcmp(from+4, "exactmap", 8)) {
 				from += 8+4;
 				e820.nr_map = 0;
@@ -911,7 +914,7 @@
 	 * the bootmem allocator) but before get_smp_config (to allow parsing
 	 * of MADT).
 	 */
-	acpi_table_init(*cmdline_p);
+	acpi_boot_init(*cmdline_p);
 #endif
 #ifdef CONFIG_X86_LOCAL_APIC
 	/*
@@ -1118,7 +1121,7 @@
 
 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
-	clear_bit(0*32+31, &c->x86_capability);
+	clear_bit(0*32+31, c->x86_capability);
 	
 	r = get_model_name(c);
 
@@ -1129,8 +1132,8 @@
 			{
 				/* Based on AMD doc 20734R - June 2000 */
 				if ( c->x86_model == 0 ) {
-					clear_bit(X86_FEATURE_APIC, &c->x86_capability);
-					set_bit(X86_FEATURE_PGE, &c->x86_capability);
+					clear_bit(X86_FEATURE_APIC, c->x86_capability);
+					set_bit(X86_FEATURE_PGE, c->x86_capability);
 				}
 				break;
 			}
@@ -1210,7 +1213,7 @@
 				/*  Set MTRR capability flag if appropriate */
 				if (c->x86_model == 13 || c->x86_model == 9 ||
 				   (c->x86_model == 8 && c->x86_mask >= 8))
-					set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability);
+					set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
 				break;
 			}
 			break;
@@ -1223,12 +1226,12 @@
 			 * here.
 			 */
 			if (c->x86_model == 6 || c->x86_model == 7) {
-				if (!test_bit(X86_FEATURE_XMM, &c->x86_capability)) {
+				if (!test_bit(X86_FEATURE_XMM, c->x86_capability)) {
 					printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
 					rdmsr(MSR_K7_HWCR, l, h);
 					l &= ~0x00008000;
 					wrmsr(MSR_K7_HWCR, l, h);
-					set_bit(X86_FEATURE_XMM, &c->x86_capability);
+					set_bit(X86_FEATURE_XMM, c->x86_capability);
 				}
 			}
 			break;
@@ -1240,7 +1243,7 @@
 }
 
 /*
- * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
+ * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
  */
 static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
 {
@@ -1315,7 +1318,7 @@
 static void __init check_cx686_slop(struct cpuinfo_x86 *c)
 {
 	unsigned long flags;
-	
+
 	if (Cx86_dir0_msb == 3) {
 		unsigned char ccr3, ccr5;
 
@@ -1325,7 +1328,7 @@
 		ccr5 = getCx86(CX86_CCR5);
 		if (ccr5 & 2)
 			setCx86(CX86_CCR5, ccr5 & 0xfd);  /* reset SLOP */
-		setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
+		setCx86(CX86_CCR3, ccr3);		  /* disable MAPEN */
 		local_irq_restore(flags);
 
 		if (ccr5 & 2) { /* possible wrong calibration done */
@@ -1336,6 +1339,7 @@
 	}
 }
 
+
 static void __init init_cyrix(struct cpuinfo_x86 *c)
 {
 	unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
@@ -1344,12 +1348,12 @@
 
 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
-	clear_bit(0*32+31, &c->x86_capability);
+	clear_bit(0*32+31, c->x86_capability);
 
 	/* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */
-	if ( test_bit(1*32+24, &c->x86_capability) ) {
-		clear_bit(1*32+24, &c->x86_capability);
-		set_bit(X86_FEATURE_CXMMX, &c->x86_capability);
+	if ( test_bit(1*32+24, c->x86_capability) ) {
+		clear_bit(1*32+24, c->x86_capability);
+		set_bit(X86_FEATURE_CXMMX, c->x86_capability);
 	}
 
 	do_cyrix_devid(&dir0, &dir1);
@@ -1396,23 +1400,18 @@
 		} else             /* 686 */
 			p = Cx86_cb+1;
 		/* Emulate MTRRs using Cyrix's ARRs. */
-		set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);
+		set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
 		/* 6x86's contain this bug */
 		c->coma_bug = 1;
 		break;
 
 	case 4: /* MediaGX/GXm */
-		/*
-		 *	Life sometimes gets weiiiiiiiird if we use this
-		 *	on the MediaGX. So we turn it off for now. 
-		 */
-		
 #ifdef CONFIG_PCI
-		/* It isnt really a PCI quirk directly, but the cure is the
+		/* It isn't really a PCI quirk directly, but the cure is the
 		   same. The MediaGX has deep magic SMM stuff that handles the
 		   SB emulation. It thows away the fifo on disable_dma() which
 		   is wrong and ruins the audio. 
-                   
+
 		   Bug2: VSA1 has a wrap bug so that using maximum sized DMA 
 		   causes bad things. According to NatSemi VSA2 has another
 		   bug to do with 'hlt'. I've not seen any boards using VSA2
@@ -1427,15 +1426,26 @@
 
 		/* GXm supports extended cpuid levels 'ala' AMD */
 		if (c->cpuid_level == 2) {
+			/* Enable Natsemi MMX extensions */
+			setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1);
+
 			get_model_name(c);  /* get CPU marketing name */
-			clear_bit(X86_FEATURE_TSC, c->x86_capability);
+			/*
+			 *  The 5510/5520 companion chips have a funky PIT
+			 *  that breaks the TSC synchronizing, so turn it off
+			 */
+			if(pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) ||
+				pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL))
+				clear_bit(X86_FEATURE_TSC, c->x86_capability);
 			return;
 		}
 		else {  /* MediaGX */
 			Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
 			p = Cx86_cb+2;
 			c->x86_model = (dir1 & 0x20) ? 1 : 2;
-			clear_bit(X86_FEATURE_TSC, &c->x86_capability);
+#ifndef CONFIG_CS5520
+			clear_bit(X86_FEATURE_TSC, c->x86_capability);
+#endif
 		}
 		break;
 
@@ -1453,10 +1463,10 @@
 		tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
 		Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
 		p = Cx86_cb+tmp;
-        	if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
+	 	if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
 			(c->x86_model)++;
 		/* Emulate MTRRs using Cyrix's ARRs. */
-		set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability);
+		set_bit(X86_FEATURE_CYRIX_ARR, c->x86_capability);
 		break;
 
 	case 0xf:  /* Cyrix 486 without DEVID registers */
@@ -1755,7 +1765,7 @@
 
 	/* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
 	   3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
-	clear_bit(0*32+31, &c->x86_capability);
+	clear_bit(0*32+31, c->x86_capability);
 
 	switch (c->x86) {
 
@@ -1766,7 +1776,7 @@
 				fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
 				fcr_clr=DPDC;
 				printk(KERN_NOTICE "Disabling bugged TSC.\n");
-				clear_bit(X86_FEATURE_TSC, &c->x86_capability);
+				clear_bit(X86_FEATURE_TSC, c->x86_capability);
 #ifdef CONFIG_X86_OOSTORE
 				winchip_create_optimal_mcr();
 				/* Enable
@@ -1845,12 +1855,12 @@
 				printk(KERN_INFO "Centaur FCR is 0x%X\n",lo);
 			}
 			/* Emulate MTRRs using Centaur's MCR. */
-			set_bit(X86_FEATURE_CENTAUR_MCR, &c->x86_capability);
+			set_bit(X86_FEATURE_CENTAUR_MCR, c->x86_capability);
 			/* Report CX8 */
-			set_bit(X86_FEATURE_CX8, &c->x86_capability);
+			set_bit(X86_FEATURE_CX8, c->x86_capability);
 			/* Set 3DNow! on Winchip 2 and above. */
 			if (c->x86_model >=8)
-				set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
+				set_bit(X86_FEATURE_3DNOW, c->x86_capability);
 			/* See if we can find out some more. */
 			if ( cpuid_eax(0x80000000) >= 0x80000005 ) {
 				/* Yes, we can. */
@@ -1868,8 +1878,8 @@
 					lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
 					wrmsr (MSR_VIA_FCR, lo, hi);
 
-					set_bit(X86_FEATURE_CX8, &c->x86_capability);
-					set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
+					set_bit(X86_FEATURE_CX8, c->x86_capability);
+					set_bit(X86_FEATURE_3DNOW, c->x86_capability);
 
 					get_model_name(c);
 					display_cacheinfo(c);
@@ -1963,7 +1973,7 @@
 		"movl $0x2333313a, %%edx\n\t"
 		"cpuid\n\t" : : : "eax", "ebx", "ecx", "edx"
 	);
-	set_bit(X86_FEATURE_CX8, &c->x86_capability);
+	set_bit(X86_FEATURE_CX8, c->x86_capability);
 }
 
 
@@ -2096,7 +2106,7 @@
 		}
 		if ( l1i || l1d )
 			printk(KERN_INFO "CPU: L1 I cache: %dK, L1 D cache: %dK\n",
-			       l1i, l1d);
+			      l1i, l1d);
 		if ( l2 )
 			printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
 		if ( l3 )
@@ -2113,7 +2123,7 @@
 
 	/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it */
 	if ( c->x86 == 6 && c->x86_model < 3 && c->x86_mask < 3 )
-		clear_bit(X86_FEATURE_SEP, &c->x86_capability);
+		clear_bit(X86_FEATURE_SEP, c->x86_capability);
 	
 	/* Names for the Pentium II/Celeron processors 
 	   detectable only by also checking the cache size.
@@ -2143,7 +2153,7 @@
 		strcpy(c->x86_model_id, p);
 	
 #ifdef CONFIG_SMP
-	if (test_bit(X86_FEATURE_HT, &c->x86_capability)) {
+	if (test_bit(X86_FEATURE_HT, c->x86_capability)) {
 		extern	int phys_proc_id[NR_CPUS];
 		
 		u32 	eax, ebx, ecx, edx;
@@ -2203,6 +2213,8 @@
 		c->x86_vendor = X86_VENDOR_AMD;
 	else if (!strcmp(v, "CyrixInstead"))
 		c->x86_vendor = X86_VENDOR_CYRIX;
+	else if (!strcmp(v, "Geode by NSC"))
+		c->x86_vendor = X86_VENDOR_NSC;
 	else if (!strcmp(v, "UMC UMC UMC "))
 		c->x86_vendor = X86_VENDOR_UMC;
 	else if (!strcmp(v, "CentaurHauls"))
@@ -2310,7 +2322,7 @@
 
 static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
 {
-	if( test_bit(X86_FEATURE_PN, &c->x86_capability) &&
+	if( test_bit(X86_FEATURE_PN, c->x86_capability) &&
 	    disable_x86_serial_nr ) {
 		/* Disable processor serial number */
 		unsigned long lo,hi;
@@ -2318,7 +2330,7 @@
 		lo |= 0x200000;
 		wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi);
 		printk(KERN_NOTICE "CPU serial number disabled.\n");
-		clear_bit(X86_FEATURE_PN, &c->x86_capability);
+		clear_bit(X86_FEATURE_PN, c->x86_capability);
 
 		/* Disabling the serial number may affect the cpuid level */
 		c->cpuid_level = cpuid_eax(0);
@@ -2484,8 +2496,9 @@
 
 		/* Intel-defined flags: level 0x00000001 */
 		if ( c->cpuid_level >= 0x00000001 ) {
-			cpuid(0x00000001, &tfms, &junk, &junk,
-			      &c->x86_capability[0]);
+			u32 capability;
+			cpuid(0x00000001, &tfms, &junk, &junk, &capability);
+			c->x86_capability[0] = capability;
 			c->x86 = (tfms >> 8) & 15;
 			c->x86_model = (tfms >> 4) & 15;
 			c->x86_mask = tfms & 15;
@@ -2511,7 +2524,7 @@
 		}
 	}
 
-	printk(KERN_DEBUG "CPU: Before vendor init, caps: %08x %08x %08x, vendor = %d\n",
+	printk(KERN_DEBUG "CPU: Before vendor init, caps: %08lx %08lx %08lx, vendor = %d\n",
 	       c->x86_capability[0],
 	       c->x86_capability[1],
 	       c->x86_capability[2],
@@ -2528,24 +2541,6 @@
 	 * indicate the features this CPU genuinely supports!
 	 */
 	switch ( c->x86_vendor ) {
-	case X86_VENDOR_UNKNOWN:
-	default:
-		/* Not much we can do here... */
-		/* Check if at least it has cpuid */
-		if (c->cpuid_level == -1)
-		{
-			/* No cpuid. It must be an ancient CPU */
-			if (c->x86 == 4)
-				strcpy(c->x86_model_id, "486");
-			else if (c->x86 == 3)
-				strcpy(c->x86_model_id, "386");
-		}
-		break;
-
-	case X86_VENDOR_CYRIX:
-		init_cyrix(c);
-		break;
-
 	case X86_VENDOR_AMD:
 		init_amd(c);
 		break;
@@ -2554,6 +2549,10 @@
 		init_centaur(c);
 		break;
 
+	case X86_VENDOR_CYRIX:
+		init_cyrix(c);
+		break;
+
 	case X86_VENDOR_INTEL:
 		init_intel(c);
 		break;
@@ -2562,16 +2561,35 @@
 		c->x86_cache_size = 256; /* A few had 1 MB... */
 		break;
 
-	case X86_VENDOR_TRANSMETA:
-		init_transmeta(c);
+	case X86_VENDOR_NSC:
+        init_cyrix(c);
 		break;
 
 	case X86_VENDOR_RISE:
 		init_rise(c);
 		break;
+
+	case X86_VENDOR_TRANSMETA:
+		init_transmeta(c);
+		break;
+
+	case X86_VENDOR_UNKNOWN:
+	default:
+		/* Not much we can do here... */
+		/* Check if at least it has cpuid */
+		if (c->cpuid_level == -1)
+		{
+			/* No cpuid. It must be an ancient CPU */
+			if (c->x86 == 4)
+				strcpy(c->x86_model_id, "486");
+			else if (c->x86 == 3)
+				strcpy(c->x86_model_id, "386");
+		}
+		break;
+
 	}
 
-	printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
+	printk(KERN_DEBUG "CPU: After vendor init, caps: %08lx %08lx %08lx %08lx\n",
 	       c->x86_capability[0],
 	       c->x86_capability[1],
 	       c->x86_capability[2],
@@ -2585,13 +2603,13 @@
 	/* TSC disabled? */
 #ifndef CONFIG_X86_TSC
 	if ( tsc_disable )
-		clear_bit(X86_FEATURE_TSC, &c->x86_capability);
+		clear_bit(X86_FEATURE_TSC, c->x86_capability);
 #endif
 
 	/* FXSR disabled? */
 	if (disable_x86_fxsr) {
-		clear_bit(X86_FEATURE_FXSR, &c->x86_capability);
-		clear_bit(X86_FEATURE_XMM, &c->x86_capability);
+		clear_bit(X86_FEATURE_FXSR, c->x86_capability);
+		clear_bit(X86_FEATURE_XMM, c->x86_capability);
 	}
 
 	/* Disable the PN if appropriate */
@@ -2614,7 +2632,7 @@
 
 	/* Now the feature flags better reflect actual CPU features! */
 
-	printk(KERN_DEBUG "CPU:     After generic, caps: %08x %08x %08x %08x\n",
+	printk(KERN_DEBUG "CPU:     After generic, caps: %08lx %08lx %08lx %08lx\n",
 	       c->x86_capability[0],
 	       c->x86_capability[1],
 	       c->x86_capability[2],
@@ -2632,7 +2650,7 @@
 			boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
 	}
 
-	printk(KERN_DEBUG "CPU:             Common caps: %08x %08x %08x %08x\n",
+	printk(KERN_DEBUG "CPU:             Common caps: %08lx %08lx %08lx %08lx\n",
 	       boot_cpu_data.x86_capability[0],
 	       boot_cpu_data.x86_capability[1],
 	       boot_cpu_data.x86_capability[2],
@@ -2646,14 +2664,15 @@
 {
 	get_cpu_vendor(&boot_cpu_data);
 
-	if ( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX )
+	if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
+	    ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC   ))
 		init_cyrix(&boot_cpu_data);
 }
 
 
 /* These need to match <asm/processor.h> */
 static char *cpu_vendor_names[] __initdata = {
-	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" };
+	"Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta", "NSC" };
 
 
 void __init print_cpu_info(struct cpuinfo_x86 *c)
@@ -2694,10 +2713,10 @@
 	 */
 	static char *x86_cap_flags[] = {
 		/* Intel-defined */
-	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
-	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
+		"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+		"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+		"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+		"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
 
 		/* AMD-defined */
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -2741,7 +2760,7 @@
 	else
 		seq_printf(m, "stepping\t: unknown\n");
 
-	if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
+	if ( test_bit(X86_FEATURE_TSC, c->x86_capability) ) {
 		seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
 			cpu_khz / 1000, (cpu_khz % 1000));
 	}
@@ -2771,7 +2790,7 @@
 		     c->wp_works_ok ? "yes" : "no");
 
 	for ( i = 0 ; i < 32*NCAPINTS ; i++ )
-		if ( test_bit(i, &c->x86_capability) &&
+		if ( test_bit(i, c->x86_capability) &&
 		     x86_cap_flags[i] != NULL )
 			seq_printf(m, " %s", x86_cap_flags[i]);
 
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/signal.c	Sun Apr 14 12:16:58 2002
@@ -610,11 +610,9 @@
 		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			/* Let the debugger run.  */
 			current->exit_code = signr;
-			preempt_disable();
 			current->state = TASK_STOPPED;
 			notify_parent(current, SIGCHLD);
 			schedule();
-			preempt_enable();
 
 			/* We're back.  Did the debugger cancel the sig?  */
 			if (!(signr = current->exit_code))
@@ -669,14 +667,12 @@
 
 			case SIGSTOP: {
 				struct signal_struct *sig;
+				current->state = TASK_STOPPED;
 				current->exit_code = signr;
 				sig = current->parent->sig;
-				preempt_disable();
-				current->state = TASK_STOPPED;
 				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
-				preempt_enable();
 				continue;
 			}
 
diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	Sun Apr 14 12:16:55 2002
+++ b/arch/i386/kernel/smp.c	Sun Apr 14 12:16:55 2002
@@ -21,6 +21,7 @@
 
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 #include <asm/smpboot.h>
 
 /*
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c	Sun Apr 14 12:16:58 2002
+++ b/arch/i386/kernel/smpboot.c	Sun Apr 14 12:16:58 2002
@@ -47,6 +47,7 @@
 #include <linux/mc146818rtc.h>
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 #include <asm/smpboot.h>
 
 /* Set if we find a B stepping CPU			*/
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/kernel/traps.c	Sun Apr 14 12:16:56 2002
@@ -25,6 +25,10 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 
+#ifdef CONFIG_EISA
+#include <linux/ioport.h>
+#endif
+
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
 #include <asm/processor.h>
@@ -951,11 +955,20 @@
 	printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
 }
 #endif
+
+#ifdef CONFIG_EISA
+int EISA_bus;
+static struct resource eisa_id = { "EISA ID", 0xc80, 0xc83, IORESOURCE_BUSY };
+#endif
+
 void __init trap_init(void)
 {
 #ifdef CONFIG_EISA
-	if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24))
+	if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) {
 		EISA_bus = 1;
+		if (request_resource(&ioport_resource, &eisa_id) == -EBUSY)
+			printk ("EISA port was EBUSY :-(\n");
+	}
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c	Sun Apr 14 12:16:55 2002
+++ b/arch/i386/kernel/vm86.c	Sun Apr 14 12:16:55 2002
@@ -12,10 +12,12 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/highmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
+#include <asm/tlbflush.h>
 
 /*
  * Known problems:
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/mm/init.c	Sun Apr 14 12:16:56 2002
@@ -37,6 +37,7 @@
 #include <asm/e820.h>
 #include <asm/apic.h>
 #include <asm/tlb.h>
+#include <asm/tlbflush.h>
 
 mmu_gather_t mmu_gathers[NR_CPUS];
 unsigned long highstart_pfn, highend_pfn;
@@ -573,7 +574,8 @@
 }
 
 #if defined(CONFIG_X86_PAE)
-struct kmem_cache_s *pae_pgd_cachep;
+static struct kmem_cache_s *pae_pgd_cachep;
+
 void __init pgtable_cache_init(void)
 {
 	/*
@@ -584,4 +586,96 @@
 	if (!pae_pgd_cachep)
 		panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
 }
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	int i;
+	pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
+
+	if (pgd) {
+		for (i = 0; i < USER_PTRS_PER_PGD; i++) {
+			unsigned long pmd = __get_free_page(GFP_KERNEL);
+			if (!pmd)
+				goto out_oom;
+			clear_page(pmd);
+			set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
+		}
+		memcpy(pgd + USER_PTRS_PER_PGD,
+			swapper_pg_dir + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+	}
+	return pgd;
+out_oom:
+	for (i--; i >= 0; i--)
+		free_page((unsigned long)__va(pgd_val(pgd[i])-1));
+	kmem_cache_free(pae_pgd_cachep, pgd);
+	return NULL;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+	int i;
+
+	for (i = 0; i < USER_PTRS_PER_PGD; i++)
+		free_page((unsigned long)__va(pgd_val(pgd[i])-1));
+	kmem_cache_free(pae_pgd_cachep, pgd);
+}
+
+#else
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+	if (pgd) {
+		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+		memcpy(pgd + USER_PTRS_PER_PGD,
+			swapper_pg_dir + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+	}
+	return pgd;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
 #endif /* CONFIG_X86_PAE */
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+	int count = 0;
+	pte_t *pte;
+   
+   	do {
+		pte = (pte_t *) __get_free_page(GFP_KERNEL);
+		if (pte)
+			clear_page(pte);
+		else {
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+	} while (!pte && (count++ < 10));
+	return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	int count = 0;
+	struct page *pte;
+   
+   	do {
+#if CONFIG_HIGHPTE
+		pte = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+#else
+		pte = alloc_pages(GFP_KERNEL, 0);
+#endif
+		if (pte)
+			clear_highpage(pte);
+		else {
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+	} while (!pte && (count++ < 10));
+	return pte;
+}
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	Sun Apr 14 12:16:56 2002
+++ b/arch/i386/mm/ioremap.c	Sun Apr 14 12:16:56 2002
@@ -11,6 +11,10 @@
 #include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
+#include <asm/fixmap.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
 
 static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
 	unsigned long phys_addr, unsigned long flags)
@@ -162,7 +166,6 @@
 		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
 
-#include <asm/fixmap.h>
 void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
 {
 	unsigned long offset, last_addr;
diff -Nru a/arch/ia64/kernel/efivars.c b/arch/ia64/kernel/efivars.c
--- a/arch/ia64/kernel/efivars.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ia64/kernel/efivars.c	Sun Apr 14 12:16:58 2002
@@ -29,6 +29,9 @@
  *
  * Changelog:
  *
+ *  25 Mar 2002 - Matt Domsch <Matt_Domsch@dell.com>
+ *   move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse()
+ *
  *  12 Feb 2002 - Matt Domsch <Matt_Domsch@dell.com>
  *   use list_for_each_safe when deleting vars.
  *   remove ifdef CONFIG_SMP around include <linux/smp.h>
@@ -70,7 +73,7 @@
 MODULE_DESCRIPTION("/proc interface to EFI Variables");
 MODULE_LICENSE("GPL");
 
-#define EFIVARS_VERSION "0.04 2002-Feb-12"
+#define EFIVARS_VERSION "0.05 2002-Mar-26"
 
 static int
 efivar_read(char *page, char **start, off_t off,
@@ -141,20 +144,6 @@
 	return len;
 }
 
-
-static void
-uuid_unparse(efi_guid_t *guid, char *out)
-{
-	sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-		guid->data1, guid->data2, guid->data3,
-		guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3],
-		guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]);
-}
-
-
-
-
-
 /*
  * efivar_create_proc_entry()
  * Requires:
@@ -197,7 +186,7 @@
 	   private variables from another's.         */
 
 	*(short_name + strlen(short_name)) = '-';
-	uuid_unparse(vendor_guid, short_name + strlen(short_name));
+	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
 
 
 	/* Create the entry in proc */
diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
--- a/arch/ia64/kernel/ia64_ksyms.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ia64/kernel/ia64_ksyms.c	Sun Apr 14 12:16:58 2002
@@ -23,7 +23,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 
 #include <linux/irq.h>
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ia64/kernel/mca.c	Sun Apr 14 12:16:58 2002
@@ -3,6 +3,9 @@
  * Purpose:	Generic MCA handling layer
  *
  * Updated for latest kernel
+ * Copyright (C) 2002 Dell Computer Corporation
+ * Copyright (C) Matt Domsch (Matt_Domsch@dell.com)
+ *
  * Copyright (C) 2002 Intel
  * Copyright (C) Jenna Hall (jenna.s.hall@intel.com)
  *
@@ -15,6 +18,8 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) Vijay Chander(vijay@engr.sgi.com)
  *
+ * 02/03/25 M. Domsch	GUID cleanups
+ *
  * 02/01/04 J. Hall	Aligned MCA stack to 16 bytes, added platform vs. CPU
  *			error flag, set SAL default return values, changed
  *			error record structure to linked list, added init call
@@ -348,17 +353,13 @@
 verify_guid (efi_guid_t *test, efi_guid_t *target)
 {
 	int     rc;
+	char out[40];
 
-	if ((rc = memcmp((void *)test, (void *)target, sizeof(efi_guid_t)))) {
-		IA64_MCA_DEBUG("ia64_mca_print: invalid guid = "
-			       "{ %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
-			       "%#02x, %#02x, %#02x, %#02x, } } \n ",
-			       test->data1, test->data2, test->data3, test->data4[0],
-			       test->data4[1], test->data4[2], test->data4[3],
-			       test->data4[4], test->data4[5], test->data4[6],
-			       test->data4[7]);
+	if ((rc = efi_guidcmp(*test, *target))) {
+		IA64_MCA_DEBUG(KERN_DEBUG
+			       "verify_guid: invalid GUID = %s\n",
+			       efi_guid_unparse(test, out));
 	}
-
 	return rc;
 }
 
@@ -856,11 +857,8 @@
 void
 ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc)
 {
-	printk("GUID = { %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
-	       "%#02x, %#02x, %#02x, %#02x, } } \n ", p_guid->data1,
-	       p_guid->data2, p_guid->data3, p_guid->data4[0], p_guid->data4[1],
-	       p_guid->data4[2], p_guid->data4[3], p_guid->data4[4],
-	       p_guid->data4[5], p_guid->data4[6], p_guid->data4[7]);
+	char out[40];
+	printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out));
 }
 
 static void
@@ -1754,7 +1752,7 @@
 		ia64_log_prt_section_header(slsh, prfunc);
 #endif  // MCA_PRT_XTRA_DATA for test only @FVL
 
-		if (verify_guid((void *)&slsh->guid, (void *)&(SAL_PROC_DEV_ERR_SECT_GUID))) {
+		if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) {
 			IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
 			continue;
 		}
diff -Nru a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
--- a/arch/m68k/atari/config.c	Sun Apr 14 12:16:55 2002
+++ b/arch/m68k/atari/config.c	Sun Apr 14 12:16:55 2002
@@ -205,14 +205,16 @@
     char switches[len+1];
     char *p;
     int ovsc_shift;
+    char *args = switches;
 
-    /* copy string to local array, strtok works destructively... */
+    /* copy string to local array, strsep works destructively... */
     strncpy( switches, str, len );
     switches[len] = 0;
     atari_switches = 0;
 
     /* parse the options */
-    for( p = strtok( switches, "," ); p; p = strtok( NULL, "," ) ) {
+    while ((p = strsep(&args, ",")) != NULL) {
+	if (!*p) continue;
 	ovsc_shift = 0;
 	if (strncmp( p, "ov_", 3 ) == 0) {
 	    p += 3;
diff -Nru a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
--- a/arch/m68k/kernel/m68k_ksyms.c	Sun Apr 14 12:16:57 2002
+++ b/arch/m68k/kernel/m68k_ksyms.c	Sun Apr 14 12:16:57 2002
@@ -54,7 +54,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
diff -Nru a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
--- a/arch/m68k/mac/baboon.c	Sun Apr 14 12:16:56 2002
+++ b/arch/m68k/mac/baboon.c	Sun Apr 14 12:16:56 2002
@@ -27,7 +27,7 @@
 
 void baboon_irq(int, void *, struct pt_regs *);
 
-extern int macide_ack_intr(ide_hwif_t *);
+extern int macide_ack_intr(struct ata_channel *);
 
 /*
  * Baboon initialization.
diff -Nru a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
--- a/arch/mips/kernel/mips_ksyms.c	Sun Apr 14 12:16:56 2002
+++ b/arch/mips/kernel/mips_ksyms.c	Sun Apr 14 12:16:56 2002
@@ -51,7 +51,6 @@
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL(simple_strtol);
 EXPORT_SYMBOL_NOVERS(strcat);
 EXPORT_SYMBOL_NOVERS(strchr);
 EXPORT_SYMBOL_NOVERS(strlen);
@@ -60,7 +59,7 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 
 EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(enable_irq);
diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
--- a/arch/mips/kernel/signal.c	Sun Apr 14 12:16:59 2002
+++ b/arch/mips/kernel/signal.c	Sun Apr 14 12:16:59 2002
@@ -204,7 +204,7 @@
 #define restore_gp_reg(i) do {						\
 	err |= __get_user(reg, &sc->sc_regs[i]);			\
 	regs->regs[i] = reg;						\
-} while(0);
+} while(0)
 	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
 	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
 	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
diff -Nru a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
--- a/arch/mips/kernel/smp.c	Sun Apr 14 12:16:56 2002
+++ b/arch/mips/kernel/smp.c	Sun Apr 14 12:16:56 2002
@@ -156,7 +156,7 @@
 		sprintf(p->comm, "%s%d", "Idle", i);
 		init_tasks[i] = p;
 		p->processor = i;
-		p->cpus_runnable = 1 << i; /* we schedule the first task manually *
+		p->cpus_runnable = 1 << i; /* we schedule the first task manually */
 		del_from_runqueue(p);
 		unhash_process(p);
 		/* Attach to the address space of init_task. */
diff -Nru a/arch/mips/sni/pci.c b/arch/mips/sni/pci.c
--- a/arch/mips/sni/pci.c	Sun Apr 14 12:16:59 2002
+++ b/arch/mips/sni/pci.c	Sun Apr 14 12:16:59 2002
@@ -25,7 +25,7 @@
 		 ((dev->bus->number    & 0xff) << 0x10) |                    \
 	         ((dev->devfn & 0xff) << 0x08) |                             \
 	         (where  & 0xfc);                                            \
-} while(0);
+} while(0)
 
 #if 0
 /* To do:  Bring this uptodate ...  */
diff -Nru a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c
--- a/arch/mips64/kernel/mips64_ksyms.c	Sun Apr 14 12:16:57 2002
+++ b/arch/mips64/kernel/mips64_ksyms.c	Sun Apr 14 12:16:57 2002
@@ -48,14 +48,13 @@
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL(simple_strtol);
 EXPORT_SYMBOL_NOVERS(strcat);
 EXPORT_SYMBOL_NOVERS(strchr);
 EXPORT_SYMBOL_NOVERS(strlen);
 EXPORT_SYMBOL_NOVERS(strncat);
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 EXPORT_SYMBOL(_clear_page);
diff -Nru a/arch/mips64/math-emu/cp1emu.c b/arch/mips64/math-emu/cp1emu.c
--- a/arch/mips64/math-emu/cp1emu.c	Sun Apr 14 12:16:55 2002
+++ b/arch/mips64/math-emu/cp1emu.c	Sun Apr 14 12:16:55 2002
@@ -29,7 +29,7 @@
  * Notes: 
  *  1) the IEEE754 library (-le) performs the actual arithmetic;
  *  2) if you know that you won't have an fpu, then you'll get much 
- *     better performance by compiling with -msoft-float!  */
+ *     better performance by compiling with -msoft-float!
  *
  *  Nov 7, 2000
  *  Massive changes to integrate with Linux kernel.
diff -Nru a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
--- a/arch/parisc/kernel/parisc_ksyms.c	Sun Apr 14 12:17:00 2002
+++ b/arch/parisc/kernel/parisc_ksyms.c	Sun Apr 14 12:17:00 2002
@@ -20,7 +20,6 @@
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strtok);
 
 #include <linux/pci.h>
 EXPORT_SYMBOL(hppa_dma_ops);
diff -Nru a/arch/ppc/4xx_io/stb_kb.c b/arch/ppc/4xx_io/stb_kb.c
--- a/arch/ppc/4xx_io/stb_kb.c	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc/4xx_io/stb_kb.c	Sun Apr 14 12:16:54 2002
@@ -19,7 +19,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kbd_kern.h>
 
 /* the following are borrowed from pc_keyb.c, thanks to those involved! */
diff -Nru a/arch/ppc/Config.help b/arch/ppc/Config.help
--- a/arch/ppc/Config.help	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc/Config.help	Sun Apr 14 12:16:56 2002
@@ -1033,6 +1033,16 @@
   Include in-kernel hooks for the xmon kernel monitor/debugger
   supported by the PPC port.
 
+Include BDI2000 debugger support
+CONFIG_BDI_SWITCH
+  Include in-kernel support for the Abatron BDI2000 debugger.
+
+Add additional CFLAGS to the kernel build
+CONFIG_MORE_COMPILE_OPTIONS
+  If you want to add additional CFLAGS to the kernel build, such as
+  -g for KGDB, XMON or the BDI2000, enable this option and then
+  enter what you would like to add in the next question.
+
 CONFIG_ADVANCED_OPTIONS
   This option will enable prompting for a variety of advanced kernel
   configuration options.  These options can cause the kernel to not
diff -Nru a/arch/ppc/config.in b/arch/ppc/config.in
--- a/arch/ppc/config.in	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc/config.in	Sun Apr 14 12:16:54 2002
@@ -24,27 +24,27 @@
 	 iSeries		CONFIG_PPC_ISERIES"	6xx
 
 if [ "$CONFIG_6xx" = "y" ]; then
-  bool 'MPC8260 CPM Support' CONFIG_8260
+   bool 'MPC8260 CPM Support' CONFIG_8260
 fi
 
 if [ "$CONFIG_POWER3" = "y" ]; then
-  define_bool CONFIG_PPC64BRIDGE y
-  define_bool CONFIG_ALL_PPC y
+   define_bool CONFIG_PPC64BRIDGE y
+   define_bool CONFIG_ALL_PPC y
 fi
 
 if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
-  define_bool CONFIG_PPC64BRIDGE y
+   define_bool CONFIG_PPC64BRIDGE y
 fi
 
 if [ "$CONFIG_6xx" = "y" -o "$CONFIG_POWER3" = "y" ]; then
-  define_bool CONFIG_PPC_STD_MMU y
+   define_bool CONFIG_PPC_STD_MMU y
 else
-  define_bool CONFIG_PPC_STD_MMU n
+   define_bool CONFIG_PPC_STD_MMU n
 fi
 
 if [ "$CONFIG_8260" = "y" ]; then
-  define_bool CONFIG_SERIAL_CONSOLE y
-  choice 'Machine Type'	\
+   define_bool CONFIG_SERIAL_CONSOLE y
+   choice 'Machine Type'	\
 	"EST8260	CONFIG_EST8260	\
 	 SBS8260	CONFIG_SBS8260	\
 	 RPXSUPER	CONFIG_RPX6	\
@@ -66,10 +66,10 @@
 fi
 
 if [ "$CONFIG_8xx" = "y" ]; then
-  define_bool CONFIG_SERIAL_CONSOLE y
-  define_bool CONFIG_NOT_COHERENT_CACHE y
+   define_bool CONFIG_SERIAL_CONSOLE y
+   define_bool CONFIG_NOT_COHERENT_CACHE y
 
-  choice 'Machine Type'		\
+   choice 'Machine Type'		\
 	"RPX-Lite	CONFIG_RPXLITE		\
 	 RPX-Classic	CONFIG_RPXCLASSIC	\
 	 BSE-IP		CONFIG_BSEIP		\
@@ -92,18 +92,18 @@
 	 MBX		CONFIG_MBX		\
 	 WinCept	CONFIG_WINCEPT"		RPX-Lite
 
-  if [ "$CONFIG_TQM823L" = "y" -o \
+   if [ "$CONFIG_TQM823L" = "y" -o \
        "$CONFIG_TQM850L" = "y" -o \
        "$CONFIG_FPS850L" = "y" -o \
        "$CONFIG_TQM855L" = "y" -o \
        "$CONFIG_TQM860L" = "y" -o \
        "$CONFIG_SM850"   = "y" ]; then
- 	define_bool	CONFIG_TQM8xxL	y
-  fi
+      define_bool CONFIG_TQM8xxL y
+   fi
 fi
 
 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
-  choice 'Machine Type'		\
+   choice 'Machine Type'		\
 	"CHRP/PowerMac/PReP	CONFIG_ALL_PPC		\
 	 Amiga-APUS		CONFIG_APUS		\
 	 Cogent-Willow		CONFIG_WILLOW		\
@@ -125,133 +125,130 @@
 	 Zynx-ZX4500		CONFIG_ZX4500"		CHRP/PowerMac/PReP
 fi
 
-if [ "$CONFIG_PCORE" = "y" \
-  -o "$CONFIG_POWERPMC250" = "y" ]; then
-  define_bool CONFIG_FORCE y
+if [ "$CONFIG_PCORE" = "y" -o "$CONFIG_POWERPMC250" = "y" ]; then
+   define_bool CONFIG_FORCE y
 fi
 
-if [ "$CONFIG_FORCE" = "y" \
-  -o "$CONFIG_MENF1" = "y" \
-  -o "$CONFIG_SANDPOINT" = "y" \
-  -o "$CONFIG_ZX4500" = "y" ]; then
-  bool 'Enable MPC10x store gathering' CONFIG_MPC10X_STORE_GATHERING
+if [ "$CONFIG_FORCE" = "y" -o "$CONFIG_MENF1" = "y" \
+     -o "$CONFIG_SANDPOINT" = "y" -o "$CONFIG_ZX4500" = "y" ]; then
+   bool 'Enable MPC10x store gathering' CONFIG_MPC10X_STORE_GATHERING
 fi
 
 if [ "$CONFIG_EV64260" = "y" ]; then
-  define_bool CONFIG_GT64260 y
-  define_int CONFIG_SERIAL_CONSOLE_BAUD 115200
+   define_bool CONFIG_GT64260 y
+   define_int CONFIG_SERIAL_CONSOLE_BAUD 115200
 fi
 
 if [ "$CONFIG_K2" = "y" ]; then
-  bool 'Enable CPC710 data gathering' CONFIG_CPC710_DATA_GATHERING
+   bool 'Enable CPC710 data gathering' CONFIG_CPC710_DATA_GATHERING
 fi
 
 if [ "$CONFIG_MVME5100" = "y" ]; then
-  bool 'MVME5100 configured with an IPMC761' CONFIG_MVME5100_IPMC761_PRESENT
+   bool 'MVME5100 configured with an IPMC761' CONFIG_MVME5100_IPMC761_PRESENT
 fi
 
 if [ "$CONFIG_SANDPOINT" = "y" ]; then
-  bool 'Sandpoint X3' CONFIG_SANDPOINT_X3
-  if [ "$CONFIG_SANDPOINT_X3" = "y" ]; then
-    define_bool CONFIG_EPIC_SERIAL_MODE y
-  fi
+   bool 'Sandpoint X3' CONFIG_SANDPOINT_X3
+   if [ "$CONFIG_SANDPOINT_X3" = "y" ]; then
+      define_bool CONFIG_EPIC_SERIAL_MODE y
+   fi
 fi
 
 if [ "$CONFIG_SPRUCE" = "y" ]; then
-  bool 'Spruce baud clock support' CONFIG_SPRUCE_BAUD_33M
+   bool 'Spruce baud clock support' CONFIG_SPRUCE_BAUD_33M
 fi
 
 if [ "$CONFIG_PPC_STD_MMU" != "y" ]; then
-  define_bool CONFIG_ALL_PPC n
+   define_bool CONFIG_ALL_PPC n
 fi
 
 bool 'Symmetric multi-processing support' CONFIG_SMP
 if [ "$CONFIG_SMP" = "y" ]; then
-  bool '  Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
+   bool '  Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
 fi
 define_bool CONFIG_PREEMPT n
 
 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
-  bool 'AltiVec Support' CONFIG_ALTIVEC
-  bool 'Thermal Management Support' CONFIG_TAU
-  if [ "$CONFIG_TAU" = "y" ]; then
-    bool '    Interrupt driven TAU driver (DANGEROUS)' CONFIG_TAU_INT
-    bool '    Average high and low temp' CONFIG_TAU_AVERAGE
-  fi
+   bool 'AltiVec Support' CONFIG_ALTIVEC
+   bool 'Thermal Management Support' CONFIG_TAU
+   if [ "$CONFIG_TAU" = "y" ]; then
+      bool '    Interrupt driven TAU driver (DANGEROUS)' CONFIG_TAU_INT
+      bool '    Average high and low temp' CONFIG_TAU_AVERAGE
+   fi
 fi
 
 if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8xx" = "y" ]; then
-  bool 'Math emulation' CONFIG_MATH_EMULATION
+   bool 'Math emulation' CONFIG_MATH_EMULATION
 fi
 
 if [ "$CONFIG_4xx" = "y" ]; then
 # It's often necessary to know the specific 4xx processor type.
 # Fortunately, it is impled (so far) from the board type, so we
 # don't need to ask more redundant questions.
- if [ "$CONFIG_ASH" = "y" ]; then
-    define_bool CONFIG_NP405H y
-    define_bool CONFIG_TREEBOOT y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
-  if [ "$CONFIG_CEDER" = "y" ]; then
-    define_bool CONFIG_NP405L y
-    define_bool CONFIG_BIOS_FIXUP y
-    define_bool CONFIG_TREEBOOT y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
-  if [ "$CONFIG_CPCI405" = "y" ]; then
-    define_bool CONFIG_405GP y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
-  if [ "$CONFIG_EP405" = "y" ]; then
-    define_bool CONFIG_405GP y
-    define_bool CONFIG_BIOS_FIXUP y
-    define_bool CONFIG_EMBEDDEDBOOT y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
-  if [ "$CONFIG_OAK" = "y" -o "$CONFIG_TIVO" = "y" ]; then
-    define_bool CONFIG_403GCX y
-    define_bool CONFIG_TREEBOOT y
-  fi
-  if [ "$CONFIG_REDWOOD_4" = "y" ]; then
-    define_bool CONFIG_STB03xxx y
-    define_bool CONFIG_TREEBOOT y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
-  if [ "$CONFIG_REDWOOD_5" = "y" ]; then
-    define_bool CONFIG_STB03xxx y
-    define_bool CONFIG_TREEBOOT y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
-  if [ "$CONFIG_WALNUT" = "y" ]; then
-    define_bool CONFIG_405GP y
-    define_bool CONFIG_BIOS_FIXUP y
-    define_bool CONFIG_TREEBOOT y
-    define_bool CONFIG_IBM405_ERR77 y
-    define_bool CONFIG_IBM_OCP y
-  fi
+   if [ "$CONFIG_ASH" = "y" ]; then
+      define_bool CONFIG_NP405H y
+      define_bool CONFIG_TREEBOOT y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
+   if [ "$CONFIG_CEDER" = "y" ]; then
+      define_bool CONFIG_NP405L y
+      define_bool CONFIG_BIOS_FIXUP y
+      define_bool CONFIG_TREEBOOT y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
+   if [ "$CONFIG_CPCI405" = "y" ]; then
+      define_bool CONFIG_405GP y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
+   if [ "$CONFIG_EP405" = "y" ]; then
+      define_bool CONFIG_405GP y
+      define_bool CONFIG_BIOS_FIXUP y
+      define_bool CONFIG_EMBEDDEDBOOT y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
+   if [ "$CONFIG_OAK" = "y" -o "$CONFIG_TIVO" = "y" ]; then
+      define_bool CONFIG_403GCX y
+      define_bool CONFIG_TREEBOOT y
+   fi
+   if [ "$CONFIG_REDWOOD_4" = "y" ]; then
+      define_bool CONFIG_STB03xxx y
+      define_bool CONFIG_TREEBOOT y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
+   if [ "$CONFIG_REDWOOD_5" = "y" ]; then
+      define_bool CONFIG_STB03xxx y
+      define_bool CONFIG_TREEBOOT y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
+   if [ "$CONFIG_WALNUT" = "y" ]; then
+      define_bool CONFIG_405GP y
+      define_bool CONFIG_BIOS_FIXUP y
+      define_bool CONFIG_TREEBOOT y
+      define_bool CONFIG_IBM405_ERR77 y
+      define_bool CONFIG_IBM_OCP y
+   fi
 
-  bool 'Blue Logic DMA' CONFIG_405_DMA
-  dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
+   bool 'Blue Logic DMA' CONFIG_405_DMA
+   dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
 
-  if [ "$CONFIG_4xx" = "y" ]; then
-    choice 'TTYS0 device and default console'	\
+   if [ "$CONFIG_4xx" = "y" ]; then
+      choice 'TTYS0 device and default console'	\
 	"UART0  CONFIG_UART0_TTYS0		\
 	 UART1	CONFIG_UART0_TTYS1"		UART0
-  fi
+   fi
 
-  define_bool CONFIG_IBM405_ERR51 y
-  define_bool CONFIG_NOT_COHERENT_CACHE y
+   define_bool CONFIG_IBM405_ERR51 y
+   define_bool CONFIG_NOT_COHERENT_CACHE y
 fi
 
 if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then
-    define_bool CONFIG_EMBEDDEDBOOT y
+      define_bool CONFIG_EMBEDDEDBOOT y
 fi
 endmenu
 
@@ -262,43 +259,43 @@
 dep_bool '  Support for PTEs in high memory' CONFIG_HIGHPTE $CONFIG_HIGHMEM
 bool 'Prompt for advanced kernel configuration options' CONFIG_ADVANCED_OPTIONS
 if [ "$CONFIG_ADVANCED_OPTIONS" = "y" ]; then
-  if [ "$CONFIG_HIGHMEM" = "y" ]; then
-    bool "  Set high memory pool address" CONFIG_HIGHMEM_START_BOOL
-    if [ "$CONFIG_HIGHMEM_START_BOOL" = "y" ]; then
-      hex "    Virtual start address of high memory pool" CONFIG_HIGHMEM_START 0xfe000000
-    fi
-    bool "  Set maximum low memory" CONFIG_LOWMEM_SIZE_BOOL
-    if [ "$CONFIG_LOWMEM_SIZE_BOOL" = "y" ]; then
-      hex "    Maximum low memory size (in bytes)" CONFIG_LOWMEM_SIZE 0x20000000
-    fi
-  fi
-
-  bool "Set custom kernel base address" CONFIG_KERNEL_START_BOOL
-  if [ "$CONFIG_KERNEL_START_BOOL" = "y" ]; then
-    hex "  Virtual address of kernel base" CONFIG_KERNEL_START 0xc0000000
-  fi
-  bool "Set custom user task size" CONFIG_TASK_SIZE_BOOL
-  if [ "$CONFIG_TASK_SIZE_BOOL" = "y" ]; then
-    hex "  Size of user task space" CONFIG_TASK_SIZE 0x80000000
-  fi
-  if [ "$CONFIG_8xx" = "y" ]; then
-    bool "Pinned Kernel TLBs (860 ONLY)" CONFIG_PIN_TLB
-  fi
-  if [ "$CONFIG_4xx" = "y" ]; then
-    bool "Pinned Kernel TLBs" CONFIG_PIN_TLB
-  fi
-  if [ "$CONFIG_ALL_PPC" = "n" ]; then
-    bool "Set the boot link/load address" CONFIG_BOOT_LOAD_BOOL
-    if [ "$CONFIG_BOOT_LOAD_BOOL" = "y" ]; then
-      hex "  Link/load address for booting" CONFIG_BOOT_LOAD 0x00400000
-    fi
-  fi
+   if [ "$CONFIG_HIGHMEM" = "y" ]; then
+      bool "  Set high memory pool address" CONFIG_HIGHMEM_START_BOOL
+      if [ "$CONFIG_HIGHMEM_START_BOOL" = "y" ]; then
+         hex "    Virtual start address of high memory pool" CONFIG_HIGHMEM_START 0xfe000000
+      fi
+      bool "  Set maximum low memory" CONFIG_LOWMEM_SIZE_BOOL
+      if [ "$CONFIG_LOWMEM_SIZE_BOOL" = "y" ]; then
+         hex "    Maximum low memory size (in bytes)" CONFIG_LOWMEM_SIZE 0x20000000
+      fi
+   fi
+
+   bool "Set custom kernel base address" CONFIG_KERNEL_START_BOOL
+   if [ "$CONFIG_KERNEL_START_BOOL" = "y" ]; then
+      hex "  Virtual address of kernel base" CONFIG_KERNEL_START 0xc0000000
+   fi
+   bool "Set custom user task size" CONFIG_TASK_SIZE_BOOL
+   if [ "$CONFIG_TASK_SIZE_BOOL" = "y" ]; then
+      hex "  Size of user task space" CONFIG_TASK_SIZE 0x80000000
+   fi
+   if [ "$CONFIG_8xx" = "y" ]; then
+      bool "Pinned Kernel TLBs (860 ONLY)" CONFIG_PIN_TLB
+   fi
+   if [ "$CONFIG_4xx" = "y" ]; then
+      bool "Pinned Kernel TLBs" CONFIG_PIN_TLB
+   fi
+   if [ "$CONFIG_ALL_PPC" != "y" ]; then
+      bool "Set the boot link/load address" CONFIG_BOOT_LOAD_BOOL
+      if [ "$CONFIG_BOOT_LOAD_BOOL" = "y" ]; then
+         hex "  Link/load address for booting" CONFIG_BOOT_LOAD 0x00400000
+      fi
+   fi
 fi
 
 if [ "$CONFIG_ALL_PPC" = "y" ]; then
-  bool 'Support for ISA-bus hardware' CONFIG_ISA
+   bool 'Support for ISA-bus hardware' CONFIG_ISA
 else
-  define_bool CONFIG_ISA n
+   define_bool CONFIG_ISA n
 fi
 define_bool CONFIG_EISA n
 define_bool CONFIG_SBUS n
@@ -307,30 +304,30 @@
 define_bool CONFIG_MCA n
 
 if [ "$CONFIG_4xx" = "y" -o "$CONFIG_8260" = "y" ]; then
-  bool "Enable PCI" CONFIG_PCI
-  bool 'PC PS/2 style Keyboard' CONFIG_PC_KEYBOARD
+   bool "Enable PCI" CONFIG_PCI
+   bool 'PC PS/2 style Keyboard' CONFIG_PC_KEYBOARD
 else
-  if [ "$CONFIG_8xx" = "y" ]; then
-     bool 'QSpan PCI' CONFIG_PCI_QSPAN
-     define_bool CONFIG_PCI $CONFIG_PCI_QSPAN
-  else
-     if [ "$CONFIG_APUS" = "y" ]; then
-       bool 'PCI for Permedia2' CONFIG_PCI_PERMEDIA
-       define_bool CONFIG_PCI $CONFIG_PCI_PERMEDIA
-     else
-	if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
-	   bool "IBM iSeries Native I/O Support" CONFIG_PCI_ISERIES
-	   define_bool CONFIG_PCI $CONFIG_PCI_ISERIES
-	else
-	   define_bool CONFIG_PCI y
-	fi
-     fi
-  fi
+   if [ "$CONFIG_8xx" = "y" ]; then
+      bool 'QSpan PCI' CONFIG_PCI_QSPAN
+      define_bool CONFIG_PCI $CONFIG_PCI_QSPAN
+   else
+      if [ "$CONFIG_APUS" = "y" ]; then
+        bool 'PCI for Permedia2' CONFIG_PCI_PERMEDIA
+        define_bool CONFIG_PCI $CONFIG_PCI_PERMEDIA
+      else
+         if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
+	    bool "IBM iSeries Native I/O Support" CONFIG_PCI_ISERIES
+	    define_bool CONFIG_PCI $CONFIG_PCI_ISERIES
+	 else
+	    define_bool CONFIG_PCI y
+	 fi
+      fi
+   fi
 fi
 
 # only elf supported, a.out is not -- Cort
 if [ "$CONFIG_PROC_FS" = "y" ]; then
-  define_bool CONFIG_KCORE_ELF y
+   define_bool CONFIG_KCORE_ELF y
 fi
 define_bool CONFIG_BINFMT_ELF y
 define_bool CONFIG_KERNEL_ELF y
@@ -341,70 +338,70 @@
 bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
 
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
-  source drivers/pcmcia/Config.in
+   source drivers/pcmcia/Config.in
 else
-  define_bool CONFIG_PCMCIA n
+   define_bool CONFIG_PCMCIA n
 fi
 
 source drivers/parport/Config.in
 
 if [ "$CONFIG_PPC_ISERIES" != "y" ]; then
-  if [ "$CONFIG_APUS" != "y" ]; then
-    tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
-  else
-    bool 'Generic /dev/rtc emulation' CONFIG_GEN_RTC
-  fi
+   if [ "$CONFIG_APUS" != "y" ]; then
+      tristate 'Support for /dev/rtc' CONFIG_PPC_RTC
+   else
+      bool 'Generic /dev/rtc emulation' CONFIG_GEN_RTC
+   fi
 fi
 
 if [ "$CONFIG_ALL_PPC" = "y" -a "$CONFIG_POWER3" = "n" ] ; then
-  bool 'Workarounds for PPC601 bugs' CONFIG_PPC601_SYNC_FIX
+   bool 'Workarounds for PPC601 bugs' CONFIG_PPC601_SYNC_FIX
 fi
 
 if [ "$CONFIG_ALL_PPC" = "y" ]; then
-  bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
-  bool 'Support for RTAS (RunTime Abstraction Services) in /proc' CONFIG_PPC_RTAS
-  bool 'Support for PReP Residual Data' CONFIG_PREP_RESIDUAL
+   bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
+   bool 'Support for RTAS (RunTime Abstraction Services) in /proc' CONFIG_PPC_RTAS
+   bool 'Support for PReP Residual Data' CONFIG_PREP_RESIDUAL
 fi
 
 bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL
 if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
-  string 'Initial kernel command string' CONFIG_CMDLINE "console=ttyS0,9600 console=tty0 root=/dev/sda2"
+   string 'Initial kernel command string' CONFIG_CMDLINE "console=ttyS0,9600 console=tty0 root=/dev/sda2"
 fi
 
 if [ "$CONFIG_APUS" = "y" ]; then
-  define_bool CONFIG_FB_CONSOLE y
-  define_bool CONFIG_AMIGA y
-  define_bool CONFIG_ZORRO y
-  define_bool CONFIG_AMIGAMOUSE y
-  define_bool CONFIG_ABSTRACT_CONSOLE y
-  define_bool CONFIG_FB y
-  define_bool CONFIG_MOUSE y
-  define_bool CONFIG_BUSMOUSE y
-  define_bool CONFIG_APUS_FAST_EXCEPT y
-
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    bool 'Amiga 1200/600 PCMCIA support' CONFIG_AMIGA_PCMCIA
-  fi
-
-  tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
-  tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
-  dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
-  dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
-  tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   define_bool CONFIG_FB_CONSOLE y
+   define_bool CONFIG_AMIGA y
+   define_bool CONFIG_ZORRO y
+   define_bool CONFIG_AMIGAMOUSE y
+   define_bool CONFIG_ABSTRACT_CONSOLE y
+   define_bool CONFIG_FB y
+   define_bool CONFIG_MOUSE y
+   define_bool CONFIG_BUSMOUSE y
+   define_bool CONFIG_APUS_FAST_EXCEPT y
+
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      bool 'Amiga 1200/600 PCMCIA support' CONFIG_AMIGA_PCMCIA
+   fi
+
+   tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
+   tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
+   dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
+   dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
+   tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
-  fi
-  if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
-    tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL
-    tristate 'PCMCIA NE2000 support' CONFIG_APNE
-  fi
-  if [ "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o "$CONFIG_GVPIOEXT" = "y" -o \
-       "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
-    bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
-  fi
-  bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT
-  bool '/proc/hardware support' CONFIG_PROC_HARDWARE
-  source drivers/zorro/Config.in
+   fi
+   if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
+      tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL
+      tristate 'PCMCIA NE2000 support' CONFIG_APNE
+   fi
+   if [ "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o "$CONFIG_GVPIOEXT" = "y" -o \
+        "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
+      bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
+   fi
+   bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT
+   bool '/proc/hardware support' CONFIG_PROC_HARDWARE
+   source drivers/zorro/Config.in
 fi
 
 endmenu
@@ -414,18 +411,17 @@
 source drivers/md/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-  source net/Config.in
+   source net/Config.in
 fi
 
 mainmenu_option next_comment
 comment 'ATA/IDE/MFM/RLL support'
 
 tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
-
 if [ "$CONFIG_IDE" != "n" ]; then
-  source drivers/ide/Config.in
+   source drivers/ide/Config.in
 else
-  define_bool CONFIG_BLK_DEV_HD n
+   define_bool CONFIG_BLK_DEV_HD n
 fi
 endmenu
 
@@ -433,7 +429,7 @@
 comment 'SCSI support'
 tristate 'SCSI support' CONFIG_SCSI
 if [ "$CONFIG_SCSI" != "n" ]; then
-  source drivers/scsi/Config.in
+   source drivers/scsi/Config.in
 fi
 endmenu
 
@@ -444,17 +440,17 @@
 source drivers/message/i2o/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-  mainmenu_option next_comment
-  comment 'Network device support'
+   mainmenu_option next_comment
+   comment 'Network device support'
 
-  bool 'Network device support' CONFIG_NETDEVICES
-  if [ "$CONFIG_NETDEVICES" = "y" ]; then
-    source drivers/net/Config.in
-    if [ "$CONFIG_ATM" = "y" ]; then
-      source drivers/atm/Config.in
-    fi
-  fi
-  endmenu
+   bool 'Network device support' CONFIG_NETDEVICES
+   if [ "$CONFIG_NETDEVICES" = "y" ]; then
+      source drivers/net/Config.in
+      if [ "$CONFIG_ATM" = "y" ]; then
+         source drivers/atm/Config.in
+      fi
+   fi
+   endmenu
 fi
 
 source net/ax25/Config.in
@@ -466,27 +462,26 @@
 
 tristate 'ISDN support' CONFIG_ISDN
 if [ "$CONFIG_ISDN" != "n" ]; then
-  source drivers/isdn/Config.in
+   source drivers/isdn/Config.in
 fi
 endmenu
 
 mainmenu_option next_comment
 comment 'Old CD-ROM drivers (not SCSI, not IDE)'
-
 bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-  source drivers/cdrom/Config.in
+   source drivers/cdrom/Config.in
 fi
 endmenu
 
 mainmenu_option next_comment
 comment 'Console drivers'
 if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
-  bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
+   bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
 fi
- source drivers/video/Config.in
+source drivers/video/Config.in
 if [ "$CONFIG_FB" = "y" -a "$CONFIG_ALL_PPC" = "y" ]; then
-  bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
+   bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
 fi
 endmenu
 
@@ -509,57 +504,56 @@
 	-o "$CONFIG_VIOTAPE" != "n" -o "$CONFIG_VIOCD" != "n" ]; then
       define_bool CONFIG_VIOPATH y
    fi
+   if [ "$CONFIG_VIOCD" = "y" ]; then
+      define_bool CONFIG_CD_NO_IDESCSI y
+      define_bool CONFIG_BLK_DEV_IDECD y
+   fi
    endmenu
 fi
 
-if [ "$CONFIG_VIOCD" = "y" ]; then
-   define_bool CONFIG_CD_NO_IDESCSI y
-   define_bool CONFIG_BLK_DEV_IDECD y
-fi
-
 source drivers/input/Config.in
 
 mainmenu_option next_comment
 comment 'Macintosh device drivers'
 
 if [ "$CONFIG_ALL_PPC" = "y" ]; then
-  # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU
-  bool 'Support for CUDA based PowerMacs' CONFIG_ADB_CUDA
-  bool 'Support for PMU  based PowerMacs' CONFIG_ADB_PMU
-  if [ "$CONFIG_ADB_PMU" = "y" ]; then
-    bool '   Power management support for PowerBooks' CONFIG_PMAC_PBOOK
-    if [ "$CONFIG_PMAC_PBOOK" = "y" ]; then
-      define_bool CONFIG_PM y
-      tristate '     APM emulation' CONFIG_PMAC_APM_EMU
-    fi
-    # made a separate option since backlight may end up beeing used
-    # on non-powerbook machines (but only on PMU based ones AFAIK)
-    bool '   Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT
-  fi
-  bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
-  tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
-  if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
-    bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
-  fi
-  bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
-  if [ "$CONFIG_ADB" = "y" ]; then
-    bool '   Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO
-    dep_bool '   Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT
-    if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then
-      bool '     Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES
-      bool '     Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN
-    else
-      bool '   Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD
-    fi
-  fi
-  # This is for drivers/macintosh/mac_hid.o, which is needed if the input
-  # layer is used.
-  if [ "$CONFIG_INPUT" != "n" ]; then
-    define_bool CONFIG_MAC_HID y
-  fi
-  if [ "$CONFIG_ADB_CUDA" != "n" ]; then
-    bool 'Support for ANS LCD display' CONFIG_ANSLCD
-  fi
+   # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU
+   bool 'Support for CUDA based PowerMacs' CONFIG_ADB_CUDA
+   bool 'Support for PMU  based PowerMacs' CONFIG_ADB_PMU
+   if [ "$CONFIG_ADB_PMU" = "y" ]; then
+      bool '   Power management support for PowerBooks' CONFIG_PMAC_PBOOK
+      if [ "$CONFIG_PMAC_PBOOK" = "y" ]; then
+         define_bool CONFIG_PM y
+         tristate '     APM emulation' CONFIG_PMAC_APM_EMU
+      fi
+      # made a separate option since backlight may end up beeing used
+      # on non-powerbook machines (but only on PMU based ones AFAIK)
+      bool '   Backlight control for LCD screens' CONFIG_PMAC_BACKLIGHT
+   fi
+   bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
+   tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
+   if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
+      bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
+   fi
+   bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
+   if [ "$CONFIG_ADB" = "y" ]; then
+      bool '   Include MacIO (CHRP) ADB driver' CONFIG_ADB_MACIO
+      dep_bool '   Use input layer for ADB devices' CONFIG_INPUT_ADBHID $CONFIG_INPUT
+      if [ "$CONFIG_INPUT_ADBHID" = "y" ]; then
+         bool '     Support for ADB raw keycodes' CONFIG_MAC_ADBKEYCODES
+         bool '     Support for mouse button 2+3 emulation' CONFIG_MAC_EMUMOUSEBTN
+      else
+         bool '   Support for ADB keyboard (old driver)' CONFIG_ADB_KEYBOARD
+      fi
+   fi
+   # This is for drivers/macintosh/mac_hid.o, which is needed if the input
+   # layer is used.
+   if [ "$CONFIG_INPUT" != "n" ]; then
+      define_bool CONFIG_MAC_HID y
+   fi
+   if [ "$CONFIG_ADB_CUDA" != "n" ]; then
+      bool 'Support for ANS LCD display' CONFIG_ANSLCD
+   fi
 fi
 endmenu
 
@@ -573,32 +567,31 @@
 comment 'Sound'
 tristate 'Sound card support' CONFIG_SOUND
 if [ "$CONFIG_SOUND" != "n" ]; then
-  source sound/oss/dmasound/Config.in
-  source sound/Config.in
+   source sound/oss/dmasound/Config.in
+   source sound/Config.in
 fi
-
 endmenu
 
 if [ "$CONFIG_8xx" = "y" ]; then
-source arch/ppc/8xx_io/Config.in
+   source arch/ppc/8xx_io/Config.in
 fi
 
 if [ "$CONFIG_8260" = "y" ]; then
-source arch/ppc/8260_io/Config.in
+   source arch/ppc/8260_io/Config.in
 fi
 
 if [ "$CONFIG_4xx" = "y"]; then
-  mainmenu_option next_comment
-  comment 'IBM 4xx options'
-  if [ "$CONFIG_STB03xxx" = "y" ]; then
-    bool 'STB IR Keyboard' CONFIG_STB_KB
-    bool 'SICC Serial port' CONFIG_SERIAL_SICC
-    if [ "$CONFIG_SERIAL_SICC" = "y" -a "$CONFIG_UART0_TTYS1" = "y" ]; then
-      define_bool CONFIG_UART1_DFLT_CONSOLE y	
-      define_bool CONFIG_SERIAL_SICC_CONSOLE y
+   mainmenu_option next_comment
+   comment 'IBM 4xx options'
+   if [ "$CONFIG_STB03xxx" = "y" ]; then
+      bool 'STB IR Keyboard' CONFIG_STB_KB
+      bool 'SICC Serial port' CONFIG_SERIAL_SICC
+      if [ "$CONFIG_SERIAL_SICC" = "y" -a "$CONFIG_UART0_TTYS1" = "y" ]; then
+         define_bool CONFIG_UART1_DFLT_CONSOLE y	
+         define_bool CONFIG_SERIAL_SICC_CONSOLE y
+      fi
    fi
-  fi
-  endmenu
+   endmenu
 fi
 
 source drivers/usb/Config.in
@@ -615,7 +608,7 @@
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 bool 'Include kgdb kernel debugger' CONFIG_KGDB
 if [ "$CONFIG_KGDB" = "y" ]; then
-  choice 'Serial Port'			\
+   choice 'Serial Port'			\
 	"ttyS0	CONFIG_KGDB_TTYS0	\
 	 ttyS1	CONFIG_KGDB_TTYS1	\
 	 ttyS2	CONFIG_KGDB_TTYS2	\
@@ -624,19 +617,19 @@
 bool 'Include xmon kernel debugger' CONFIG_XMON
 bool 'Include BDI-2000 user context switcher' CONFIG_BDI_SWITCH
 if [ "$CONFIG_KGDB" = "y" -o "$CONFIG_XMON" = "y" \
-	-o "$CONFIG_BDI_SWITCH" = "y" ]; then
-  bool 'Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
-  if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
-    string 'Additional compile arguments' CONFIG_COMPILE_OPTIONS "-g -ggdb"
-  fi
+     -o "$CONFIG_BDI_SWITCH" = "y" ]; then
+   bool 'Add any additional compile options' CONFIG_MORE_COMPILE_OPTIONS
+   if [ "$CONFIG_MORE_COMPILE_OPTIONS" = "y" ]; then
+      string 'Additional compile arguments' CONFIG_COMPILE_OPTIONS "-g -ggdb"
+   fi
 fi
 
 if [ "$CONFIG_ALL_PPC" = "y" ]; then
-  bool 'Support for early boot text console (BootX or OpenFirmware only)' CONFIG_BOOTX_TEXT
+   bool 'Support for early boot text console (BootX or OpenFirmware only)' CONFIG_BOOTX_TEXT
 fi
 if [ "$CONFIG_MCPN765" = "y" -o "$CONFIG_SANDPOINT" = "y" \
-	-o "$CONFIG_ZX4500" = "y" -o "$CONFIG_PRPMC800" = "y" \
-	-o "$CONFIG_4xx" = "y" -o "$CONFIG_GT64260" = "y" ]; then
-  bool 'Support for early boot texts over serial port' CONFIG_SERIAL_TEXT_DEBUG
+     -o "$CONFIG_ZX4500" = "y" -o "$CONFIG_PRPMC800" = "y" \
+     -o "$CONFIG_4xx" = "y" -o "$CONFIG_GT64260" = "y" ]; then
+   bool 'Support for early boot texts over serial port' CONFIG_SERIAL_TEXT_DEBUG
 fi
 endmenu
diff -Nru a/arch/ppc/iSeries/iSeries_irq.c b/arch/ppc/iSeries/iSeries_irq.c
--- a/arch/ppc/iSeries/iSeries_irq.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc/iSeries/iSeries_irq.c	Sun Apr 14 12:16:58 2002
@@ -36,7 +36,7 @@
 
 #include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvCallXm.h>
diff -Nru a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
--- a/arch/ppc/kernel/idle.c	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc/kernel/idle.c	Sun Apr 14 12:16:54 2002
@@ -52,49 +52,45 @@
 unsigned long zero_paged_on;
 unsigned long powersave_nap;
 
-int idled(void)
+void default_idle(void)
 {
 	int do_power_save = 0;
 
 	if (cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_CAN_DOZE)
 		do_power_save = 1;
 
-	/* endless loop with no priority at all */
-	for (;;) {
 #ifdef CONFIG_PPC_ISERIES
-		if (!current->need_resched) {
-			/* Turn off the run light */
-			run_light_on(0);
-                	yield_shared_processor(); 
-		}
-		HMT_low();
+	if (!current->need_resched) {
+		/* Turn off the run light */
+		run_light_on(0);
+		yield_shared_processor(); 
+	}
+	HMT_low();
 #endif
 #ifdef CONFIG_SMP
-		if (!do_power_save) {
-			if (!need_resched()) {
-				set_thread_flag(TIF_POLLING_NRFLAG);
-				while (!test_thread_flag(TIF_NEED_RESCHED))
-					barrier();
-				clear_thread_flag(TIF_POLLING_NRFLAG);
-			}
+	if (!do_power_save) {
+		if (!need_resched()) {
+			set_thread_flag(TIF_POLLING_NRFLAG);
+			while (!test_thread_flag(TIF_NEED_RESCHED))
+				barrier();
+			clear_thread_flag(TIF_POLLING_NRFLAG);
 		}
+	}
 #endif
-		if (do_power_save && !need_resched())
-			power_save();
+	if (do_power_save && !need_resched())
+		power_save();
 
-		if (need_resched()) {
-			run_light_on(1);
-			schedule();
-		}
+	if (need_resched()) {
+		run_light_on(1);
+		schedule();
+	}
 #ifdef CONFIG_PPC_ISERIES
-		else {
-			run_light_on(0);
-			yield_shared_processor();
-			HMT_low();
-		}
-#endif /* CONFIG_PPC_ISERIES */
+	else {
+		run_light_on(0);
+		yield_shared_processor();
+		HMT_low();
 	}
-	return 0;
+#endif /* CONFIG_PPC_ISERIES */
 }
 
 /*
@@ -103,7 +99,8 @@
  */
 int cpu_idle(void)
 {
-	idled();
+	for (;;)
+		default_idle();
 	return 0; 
 }
 
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc/kernel/misc.S	Sun Apr 14 12:16:57 2002
@@ -1290,6 +1290,8 @@
 	.long sys_lremovexattr
 	.long sys_fremovexattr	/* 220 */
 	.long sys_futex
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
 	.rept NR_syscalls-(.-sys_call_table)/4
 		.long sys_ni_syscall
 	.endr
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc/kernel/ppc_ksyms.c	Sun Apr 14 12:16:59 2002
@@ -79,6 +79,10 @@
 extern unsigned long ret_to_user_hook;
 extern unsigned long mm_ptov (unsigned long paddr);
 
+extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+extern void consistent_free(void *vaddr);
+extern void consistent_sync(void *vaddr, size_t size, int direction);
+
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(do_syscall_trace);
@@ -123,7 +127,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
diff -Nru a/arch/ppc/kernel/prom_init.c b/arch/ppc/kernel/prom_init.c
--- a/arch/ppc/kernel/prom_init.c	Sun Apr 14 12:17:00 2002
+++ b/arch/ppc/kernel/prom_init.c	Sun Apr 14 12:17:00 2002
@@ -32,6 +32,7 @@
 #include <asm/btext.h>
 #include <asm/pci-bridge.h>
 #include <asm/open_pic.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_FB
 #include <asm/linux_logo.h>
diff -Nru a/arch/ppc/kernel/semaphore.c b/arch/ppc/kernel/semaphore.c
--- a/arch/ppc/kernel/semaphore.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc/kernel/semaphore.c	Sun Apr 14 12:16:59 2002
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
+#include <asm/errno.h>
 
 /*
  * Atomically update sem->count.
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc/kernel/signal.c	Sun Apr 14 12:16:58 2002
@@ -34,6 +34,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/cacheflush.h>
 
 #define DEBUG_SIG 0
 
@@ -594,8 +595,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -634,7 +635,7 @@
 			case SIGSTOP:
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+				if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
--- a/arch/ppc/kernel/smp.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc/kernel/smp.c	Sun Apr 14 12:16:59 2002
@@ -38,6 +38,7 @@
 #include <asm/residual.h>
 #include <asm/time.h>
 #include <asm/thread_info.h>
+#include <asm/tlbflush.h>
 
 int smp_threads_ready;
 volatile int smp_commenced;
diff -Nru a/arch/ppc/math-emu/op-4.h b/arch/ppc/math-emu/op-4.h
--- a/arch/ppc/math-emu/op-4.h	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc/math-emu/op-4.h	Sun Apr 14 12:16:58 2002
@@ -279,7 +279,7 @@
     X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);   \
     X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
     X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
-  } while (0);
+  } while (0)
 
 #define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)                               \
    do {                                                                 \
diff -Nru a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
--- a/arch/ppc/mm/mmu_decl.h	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc/mm/mmu_decl.h	Sun Apr 14 12:16:59 2002
@@ -22,6 +22,7 @@
  *  2 of the License, or (at your option) any later version.
  *
  */
+#include <asm/tlbflush.h>
 
 extern void mapin_ram(void);
 extern void bat_mapin_ram(void);
diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
--- a/arch/ppc/mm/pgtable.c	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc/mm/pgtable.c	Sun Apr 14 12:16:56 2002
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/highmem.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -55,6 +56,70 @@
 #define v_mapped_by_bats(x)	(0UL)
 #define p_mapped_by_bats(x)	(0UL)
 #endif /* HAVE_BATS */
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *ret;
+
+	if ((ret = (pgd_t *)__get_free_page(GFP_KERNEL)) != NULL)
+		clear_page(ret);
+	return ret;
+}
+
+void pgd_free(pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+	pte_t *pte;
+	extern int mem_init_done;
+	extern void *early_get_page(void);
+	int timeout = 0;
+
+	if (mem_init_done) {
+		while ((pte = (pte_t *) __get_free_page(GFP_KERNEL)) == NULL
+		       && ++timeout < 10) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ);
+		}
+	} else
+		pte = (pte_t *) early_get_page();
+	if (pte != NULL)
+		clear_page(pte);
+	return pte;
+}
+
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	struct page *pte;
+	int timeout = 0;
+#ifdef CONFIG_HIGHPTE
+	int flags = GFP_KERNEL | __GFP_HIGHMEM;
+#else
+	int flags = GFP_KERNEL;
+#endif
+
+	while ((pte = alloc_pages(flags, 0)) == NULL) {
+		if (++timeout >= 10)
+			return NULL;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ);
+	}
+	clear_highpage(pte);
+	return pte;
+}
+
+void pte_free_kernel(pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+void pte_free(struct page *pte)
+{
+	__free_page(pte);
+}
 
 #ifndef CONFIG_PPC_ISERIES
 void *
diff -Nru a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
--- a/arch/ppc/mm/tlb.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc/mm/tlb.c	Sun Apr 14 12:16:59 2002
@@ -41,6 +41,7 @@
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  *  - flush_tlb_page(vma, vmaddr) flushes one page
  *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes kernel pages
  *
  * since the hardware hash table functions as an extension of the
  * tlb as far as the linux tables are concerned, flush it too.
@@ -48,28 +49,78 @@
  */
 
 /*
+ * 750 SMP is a Bad Idea because the 750 doesn't broadcast all
+ * the cache operations on the bus.  Hence we need to use an IPI
+ * to get the other CPU(s) to invalidate their TLBs.
+ */
+#ifdef CONFIG_SMP_750
+#define FINISH_FLUSH	smp_send_tlb_invalidate(0)
+#else
+#define FINISH_FLUSH	do { } while (0)
+#endif
+
+static void flush_range(struct mm_struct *mm, unsigned long start,
+			unsigned long end)
+{
+	pmd_t *pmd;
+	unsigned long pmd_end;
+	int count;
+	unsigned int ctx = mm->context;
+
+	if (Hash == 0) {
+		_tlbia();
+		return;
+	}
+	start &= PAGE_MASK;
+	if (start >= end)
+		return;
+	end = (end - 1) | ~PAGE_MASK;
+	pmd = pmd_offset(pgd_offset(mm, start), start);
+	for (;;) {
+		pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
+		if (pmd_end > end)
+			pmd_end = end;
+		if (!pmd_none(*pmd)) {
+			count = ((pmd_end - start) >> PAGE_SHIFT) + 1;
+			flush_hash_pages(ctx, start, pmd_val(*pmd), count);
+		}
+		if (pmd_end == end)
+			break;
+		start = pmd_end + 1;
+		++pmd;
+	}
+}
+
+/*
  * Flush all tlb/hash table entries (except perhaps for those
  * mapping RAM starting at PAGE_OFFSET, since they never change).
  */
 void
-local_flush_tlb_all(void)
+flush_tlb_all(void)
 {
-	struct vm_area_struct vma;
-
-	/* aargh!!! */
 	/*
 	 * Just flush the kernel part of the address space, that's
 	 * all that the current callers of this require.
 	 * Eventually I hope to persuade the powers that be that
 	 * we can and should dispense with flush_tlb_all().
 	 *  -- paulus.
+	 *
+	 * In fact this should never get called now that we
+	 * have flush_tlb_kernel_range.  -- paulus
 	 */
-	vma.vm_mm = &init_mm;
-	local_flush_tlb_range(&vma, TASK_SIZE, ~0UL);
+	printk(KERN_ERR "flush_tlb_all called from %p\n",
+	       __builtin_return_address(0));
+	flush_range(&init_mm, TASK_SIZE, ~0UL);
+	FINISH_FLUSH;
+}
 
-#ifdef CONFIG_SMP
-	smp_send_tlb_invalidate(0);
-#endif /* CONFIG_SMP */
+/*
+ * Flush kernel TLB entries in the given range
+ */
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	flush_range(&init_mm, start, end);
+	FINISH_FLUSH;
 }
 
 /*
@@ -77,8 +128,7 @@
  * by mm.  We can't rely on mm->mmap describing all the entries
  * that might be in the hash table.
  */
-void
-local_flush_tlb_mm(struct mm_struct *mm)
+void flush_tlb_mm(struct mm_struct *mm)
 {
 	if (Hash == 0) {
 		_tlbia();
@@ -88,20 +138,14 @@
 	if (mm->map_count) {
 		struct vm_area_struct *mp;
 		for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
-			local_flush_tlb_range(mp, mp->vm_start, mp->vm_end);
+			flush_range(mp->vm_mm, mp->vm_start, mp->vm_end);
 	} else {
-		struct vm_area_struct vma;
-		vma.vm_mm = mm;
-		local_flush_tlb_range(&vma, 0, TASK_SIZE);
+		flush_range(mm, 0, TASK_SIZE);
 	}
-
-#ifdef CONFIG_SMP
-	smp_send_tlb_invalidate(0);
-#endif	
+	FINISH_FLUSH;
 }
 
-void
-local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
 	struct mm_struct *mm;
 	pmd_t *pmd;
@@ -114,9 +158,7 @@
 	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
 	if (!pmd_none(*pmd))
 		flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
-#ifdef CONFIG_SMP
-	smp_send_tlb_invalidate(0);
-#endif	
+	FINISH_FLUSH;
 }
 
 
@@ -125,39 +167,9 @@
  * and check _PAGE_HASHPTE bit; if it is set, find and destroy
  * the corresponding HPTE.
  */
-void
-local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+		     unsigned long end)
 {
-	struct mm_struct *mm = vma->vm_mm;
-	pmd_t *pmd;
-	unsigned long pmd_end;
-	int count;
-	unsigned int ctx = mm->context;
-
-	if (Hash == 0) {
-		_tlbia();
-		return;
-	}
-	start &= PAGE_MASK;
-	if (start >= end)
-		return;
-	end = (end - 1) | ~PAGE_MASK;
-	pmd = pmd_offset(pgd_offset(mm, start), start);
-	for (;;) {
-		pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
-		if (pmd_end > end)
-			pmd_end = end;
-		if (!pmd_none(*pmd)) {
-			count = ((pmd_end - start) >> PAGE_SHIFT) + 1;
-			flush_hash_pages(ctx, start, pmd_val(*pmd), count);
-		}
-		if (pmd_end == end)
-			break;
-		start = pmd_end + 1;
-		++pmd;
-	}
-
-#ifdef CONFIG_SMP
-	smp_send_tlb_invalidate(0);
-#endif	
+	flush_range(vma->vm_mm, start, end);
+	FINISH_FLUSH;
 }
diff -Nru a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
--- a/arch/ppc/platforms/chrp_setup.c	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc/platforms/chrp_setup.c	Sun Apr 14 12:16:57 2002
@@ -607,7 +607,7 @@
 	 * Print the banner, then scroll down so boot progress
 	 * can be printed.  -- Cort 
 	 */
-	if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
+	if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
 }
 
 void __chrp
diff -Nru a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c
--- a/arch/ppc/platforms/pmac_pic.c	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc/platforms/pmac_pic.c	Sun Apr 14 12:16:57 2002
@@ -492,7 +492,7 @@
  * and disables all interrupts except for the nominated one.
  * sleep_restore_intrs() restores the states of all interrupt enables.
  */
-unsigned int sleep_save_mask[2];
+unsigned long sleep_save_mask[2];
 
 void __pmac
 pmac_sleep_save_intrs(int viaint)
diff -Nru a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
--- a/arch/ppc/platforms/pmac_smp.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc/platforms/pmac_smp.c	Sun Apr 14 12:16:59 2002
@@ -30,6 +30,7 @@
 #include <linux/unistd.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/errno.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -47,6 +48,7 @@
 #include <asm/pmac_feature.h>
 #include <asm/time.h>
 #include <asm/open_pic.h>
+#include <asm/cacheflush.h>
 
 /*
  * Powersurge (old powermac SMP) support.
diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/Makefile	Sun Apr 14 12:16:56 2002
@@ -15,9 +15,10 @@
 
 KERNELLOAD	=0xc000000000000000
 
-LINKFLAGS	= -T arch/ppc64/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
+LINKFLAGS	= -T arch/ppc64/vmlinux.lds -Bstatic \
+		-e $(KERNELLOAD) -Ttext $(KERNELLOAD)
 CFLAGS		:= $(CFLAGS) -fsigned-char -msoft-float -pipe \
-		-Wno-uninitialized -mminimal-toc -fno-builtin
+		-Wno-uninitialized -mminimal-toc -mtraceback=full
 CPP		= $(CC) -E $(CFLAGS)
 
 
diff -Nru a/arch/ppc64/config.in b/arch/ppc64/config.in
--- a/arch/ppc64/config.in	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/config.in	Sun Apr 14 12:16:56 2002
@@ -147,6 +147,7 @@
 source drivers/video/Config.in
 endmenu
 
+source drivers/input/Config.in
 
 if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
 mainmenu_option next_comment
diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig
--- a/arch/ppc64/defconfig	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/defconfig	Sun Apr 14 12:16:56 2002
@@ -449,7 +449,6 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_INTEL_RNG is not set
-CONFIG_NVRAM=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
diff -Nru a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
--- a/arch/ppc64/kernel/ItLpQueue.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/ItLpQueue.c	Sun Apr 14 12:16:55 2002
@@ -53,6 +53,8 @@
 	struct HvLpEvent * nextLpEvent = 
 		(struct HvLpEvent *)lpQueue->xSlicCurEventPtr;
 	if ( nextLpEvent->xFlags.xValid ) {
+		/* rmb() needed only for weakly consistent machines (regatta) */
+		rmb();
 		/* Set pointer to next potential event */
 		lpQueue->xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 +
 				      LpEventAlign ) /
diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
--- a/arch/ppc64/kernel/LparData.c	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/kernel/LparData.c	Sun Apr 14 12:16:56 2002
@@ -144,7 +144,9 @@
 
 struct ItIplParmsReal xItIplParmsReal = {};
 
-struct IoHriProcessorVpd xIoHriProcessorVpd[maxProcessors] = {
+#define maxPhysicalProcessors 32
+
+struct IoHriProcessorVpd xIoHriProcessorVpd[maxPhysicalProcessors] = {
 	{
 		xInstCacheOperandSize: 32,
 		xDataCacheOperandSize: 32,
@@ -172,7 +174,7 @@
 	0, 0,
 	26,		/* # VPD array entries */
 	10,		/* # DMA array entries */
-	maxProcessors*2, maxProcessors,	/* Max logical, physical procs */
+	maxProcessors*2, maxPhysicalProcessors,	/* Max logical, physical procs */
 	offsetof(struct ItVpdAreas,xPlicDmaToks),/* offset to DMA toks */
 	offsetof(struct ItVpdAreas,xSlicVpdAdrs),/* offset to VPD addrs */
 	offsetof(struct ItVpdAreas,xPlicDmaLens),/* offset to DMA lens */
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc64/kernel/Makefile	Sun Apr 14 12:16:58 2002
@@ -27,7 +27,7 @@
 			pmc.o mf_proc.o proc_pmc.o iSeries_setup.o \
 			ItLpQueue.o hvCall.o mf.o HvLpEvent.o ras.o \
 			iSeries_proc.o HvCall.o HvLpConfig.o \
-			rtc.o init_task.o
+			rtc.o init_task.o pSeries_htab.o
 
 obj-$(CONFIG_PCI) +=  pci.o pci_dn.o pci_dma.o
 obj-$(CONFIG_PPC_EEH) += eeh.o
@@ -38,17 +38,12 @@
 ifeq ($(CONFIG_PPC_PSERIES),y)
 obj-$(CONFIG_PCI) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o
 
-obj-y += rtasd.o 
+obj-y += rtasd.o nvram.o
 endif
 
 obj-$(CONFIG_KGDB) += ppc-stub.o
 
 obj-$(CONFIG_SMP) += smp.o
-
-# tibit: for matrox_init2()
-ifeq ($(CONFIG_NVRAM),y)
-   obj-$(CONFIG_NVRAM) += pmac_nvram.o
-endif
 
 obj-y += prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o
 
diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c
--- a/arch/ppc64/kernel/align.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc64/kernel/align.c	Sun Apr 14 12:16:58 2002
@@ -1,12 +1,12 @@
-/*
- * align.c - handle alignment exceptions for the Power PC.
+/* align.c - handle alignment exceptions for the Power PC.
  *
  * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  * Copyright (c) 1998-1999 TiVo, Inc.
  *   PowerPC 403GCX modifications.
  * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *   PowerPC 403GCX/405GP modifications.
- * Copyright (c) 2001 PPC64 team, IBM Corp
+ * Copyright (c) 2001-2002 PPC64 team, IBM Corp
+ *   64-bit and Power4 support
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,10 +27,8 @@
 	unsigned char flags;
 };
 
-#define	OPCD(inst)	(((inst) & 0xFC000000) >> 26)
-#define	RS(inst)	(((inst) & 0x03E00000) >> 21)
-#define	RA(inst)	(((inst) & 0x001F0000) >> 16)
-#define	IS_DFORM(code)	((code) >= 32 && (code) <= 47)
+#define IS_XFORM(inst)	(((inst) >> 26) == 31)
+#define IS_DSFORM(inst)	(((inst) >> 26) >= 56)
 
 #define INVALID	{ 0, 0 }
 
@@ -40,9 +38,7 @@
 #define F	8	/* to/from fp regs */
 #define U	0x10	/* update index register */
 #define M	0x20	/* multiple load/store */
-#define S	0x40	/* single-precision fp, or byte-swap value */
-#define HARD	0x80	/* string, stwcx. */
-#define D	0x100	/* double-word load/store */
+#define SW	0x40	/* byte swap */
 
 #define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
 
@@ -61,9 +57,9 @@
 	{ 2, LD+SE },		/* 00 0 0101: lha */
 	{ 2, ST },		/* 00 0 0110: sth */
 	{ 4, LD+M },		/* 00 0 0111: lmw */
-	{ 4, LD+F+S },		/* 00 0 1000: lfs */
+	{ 4, LD+F },		/* 00 0 1000: lfs */
 	{ 8, LD+F },		/* 00 0 1001: lfd */
-	{ 4, ST+F+S },		/* 00 0 1010: stfs */
+	{ 4, ST+F },		/* 00 0 1010: stfs */
 	{ 8, ST+F },		/* 00 0 1011: stfd */
 	INVALID,		/* 00 0 1100 */
 	{ 8, LD },		/* 00 0 1101: ld */
@@ -77,12 +73,12 @@
 	{ 2, LD+SE+U },		/* 00 1 0101: lhau */
 	{ 2, ST+U },		/* 00 1 0110: sthu */
 	{ 4, ST+M },		/* 00 1 0111: stmw */
-	{ 4, LD+F+S+U },	/* 00 1 1000: lfsu */
+	{ 4, LD+F+U },		/* 00 1 1000: lfsu */
 	{ 8, LD+F+U },		/* 00 1 1001: lfdu */
-	{ 4, ST+F+S+U },	/* 00 1 1010: stfsu */
+	{ 4, ST+F+U },		/* 00 1 1010: stfsu */
 	{ 8, ST+F+U },		/* 00 1 1011: stfdu */
 	INVALID,		/* 00 1 1100 */
-	{ 8, ST },		/* 00 1 1101: std */
+	INVALID,		/* 00 1 1101 */
 	INVALID,		/* 00 1 1110 */
 	INVALID,		/* 00 1 1111 */
 	{ 8, LD },		/* 01 0 0000: ldx */
@@ -90,13 +86,13 @@
 	{ 8, ST },		/* 01 0 0010: stdx */
 	INVALID,		/* 01 0 0011 */
 	INVALID,		/* 01 0 0100 */
-	INVALID,		/* 01 0 0101: lwax?? */
+	{ 4, LD+SE },		/* 01 0 0101: lwax */
 	INVALID,		/* 01 0 0110 */
 	INVALID,		/* 01 0 0111 */
-	{ 0, LD+HARD },		/* 01 0 1000: lswx */
-	{ 0, LD+HARD },		/* 01 0 1001: lswi */
-	{ 0, ST+HARD },		/* 01 0 1010: stswx */
-	{ 0, ST+HARD },		/* 01 0 1011: stswi */
+	{ 0, LD },		/* 01 0 1000: lswx */
+	{ 0, LD },		/* 01 0 1001: lswi */
+	{ 0, ST },		/* 01 0 1010: stswx */
+	{ 0, ST },		/* 01 0 1011: stswi */
 	INVALID,		/* 01 0 1100 */
 	{ 8, LD+U },		/* 01 0 1101: ldu */
 	INVALID,		/* 01 0 1110 */
@@ -106,7 +102,7 @@
 	{ 8, ST+U },		/* 01 1 0010: stdux */
 	INVALID,		/* 01 1 0011 */
 	INVALID,		/* 01 1 0100 */
-	INVALID,		/* 01 1 0101: lwaux?? */
+	{ 4, LD+SE+U },		/* 01 1 0101: lwaux */
 	INVALID,		/* 01 1 0110 */
 	INVALID,		/* 01 1 0111 */
 	INVALID,		/* 01 1 1000 */
@@ -119,19 +115,19 @@
 	INVALID,		/* 01 1 1111 */
 	INVALID,		/* 10 0 0000 */
 	INVALID,		/* 10 0 0001 */
-	{ 0, ST+HARD },		/* 10 0 0010: stwcx. */
+	{ 0, ST },		/* 10 0 0010: stwcx. */
 	INVALID,		/* 10 0 0011 */
 	INVALID,		/* 10 0 0100 */
 	INVALID,		/* 10 0 0101 */
 	INVALID,		/* 10 0 0110 */
 	INVALID,		/* 10 0 0111 */
-	{ 4, LD+S },		/* 10 0 1000: lwbrx */
+	{ 4, LD+SW },		/* 10 0 1000: lwbrx */
 	INVALID,		/* 10 0 1001 */
-	{ 4, ST+S },		/* 10 0 1010: stwbrx */
+	{ 4, ST+SW },		/* 10 0 1010: stwbrx */
 	INVALID,		/* 10 0 1011 */
-	{ 2, LD+S },		/* 10 0 1100: lhbrx */
-	INVALID,		/* 10 0 1101 */
-	{ 2, ST+S },		/* 10 0 1110: sthbrx */
+	{ 2, LD+SW },		/* 10 0 1100: lhbrx */
+	{ 4, LD+SE },		/* 10 0 1101  lwa */
+	{ 2, ST+SW },		/* 10 0 1110: sthbrx */
 	INVALID,		/* 10 0 1111 */
 	INVALID,		/* 10 1 0000 */
 	INVALID,		/* 10 1 0001 */
@@ -148,7 +144,7 @@
 	INVALID,		/* 10 1 1100 */
 	INVALID,		/* 10 1 1101 */
 	INVALID,		/* 10 1 1110 */
-	{ 0, ST+HARD },		/* 10 1 1111: dcbz */
+	{ L1_CACHE_BYTES, ST },	/* 10 1 1111: dcbz */
 	{ 4, LD },		/* 11 0 0000: lwzx */
 	INVALID,		/* 11 0 0001 */
 	{ 4, ST },		/* 11 0 0010: stwx */
@@ -157,14 +153,14 @@
 	{ 2, LD+SE },		/* 11 0 0101: lhax */
 	{ 2, ST },		/* 11 0 0110: sthx */
 	INVALID,		/* 11 0 0111 */
-	{ 4, LD+F+S },		/* 11 0 1000: lfsx */
+	{ 4, LD+F },		/* 11 0 1000: lfsx */
 	{ 8, LD+F },		/* 11 0 1001: lfdx */
-	{ 4, ST+F+S },		/* 11 0 1010: stfsx */
+	{ 4, ST+F },		/* 11 0 1010: stfsx */
 	{ 8, ST+F },		/* 11 0 1011: stfdx */
 	INVALID,		/* 11 0 1100 */
-	INVALID,		/* 11 0 1101 */
+	{ 8, LD+M },		/* 11 0 1101: lmd */
 	INVALID,		/* 11 0 1110 */
-	INVALID,		/* 11 0 1111 */
+	{ 8, ST+M },		/* 11 0 1111: stmd */
 	{ 4, LD+U },		/* 11 1 0000: lwzux */
 	INVALID,		/* 11 1 0001 */
 	{ 4, ST+U },		/* 11 1 0010: stwux */
@@ -173,9 +169,9 @@
 	{ 2, LD+SE+U },		/* 11 1 0101: lhaux */
 	{ 2, ST+U },		/* 11 1 0110: sthux */
 	INVALID,		/* 11 1 0111 */
-	{ 4, LD+F+S+U },	/* 11 1 1000: lfsux */
+	{ 4, LD+F+U },		/* 11 1 1000: lfsux */
 	{ 8, LD+F+U },		/* 11 1 1001: lfdux */
-	{ 4, ST+F+S+U },	/* 11 1 1010: stfsux */
+	{ 4, ST+F+U },		/* 11 1 1010: stfsux */
 	{ 8, ST+F+U },		/* 11 1 1011: stfdux */
 	INVALID,		/* 11 1 1100 */
 	INVALID,		/* 11 1 1101 */
@@ -185,178 +181,203 @@
 
 #define SWAP(a, b)	(t = (a), (a) = (b), (b) = t)
 
+unsigned static inline make_dsisr( unsigned instr )
+{
+	unsigned dsisr;
+	
+	/* create a DSISR value from the instruction */
+	dsisr = (instr & 0x03ff0000) >> 16;			/* bits  6:15 --> 22:31 */
+	
+	if ( IS_XFORM(instr) ) {
+		dsisr |= (instr & 0x00000006) << 14;		/* bits 29:30 --> 15:16 */
+		dsisr |= (instr & 0x00000040) << 8;		/* bit     25 -->    17 */
+		dsisr |= (instr & 0x00000780) << 3;		/* bits 21:24 --> 18:21 */
+	}
+	else {
+		dsisr |= (instr & 0x04000000) >> 12;		/* bit      5 -->    17 */
+		dsisr |= (instr & 0x78000000) >> 17;		/* bits  1: 4 --> 18:21 */
+		if ( IS_DSFORM(instr) ) {
+			dsisr |= (instr & 0x00000003) << 18;	/* bits 30:31 --> 12:13 */
+		}
+	}
+	
+	return dsisr;
+}
+
 int
 fix_alignment(struct pt_regs *regs)
 {
-	int instr, nb, flags;
-	int opcode, f1, f2, f3;
-	int i, t;
-	int reg, areg;
-	unsigned char *addr;
+	unsigned int instr, nb, flags;
+	int t;
+	unsigned long reg, areg;
+	unsigned long i;
+	int ret;
+	unsigned dsisr;
+	unsigned char *addr, *p;
+	unsigned long *lp;
 	union {
-		int l;
 		long ll;
-		float f;
-		double d;
+		double dd;
 		unsigned char v[8];
+		struct {
+			unsigned hi32;
+			int	 low32;
+		} x32;
+		struct {
+			unsigned char hi48[6];
+			short	      low16;
+		} x16;
 	} data;
 
-	if (__is_processor(PV_POWER4)) {
-		/* 
-		 * The POWER4 has a DSISR register but doesn't set it on
-		 * an alignment fault.  -- paulus
-		 */
-
-		instr = *((unsigned int *)regs->nip);
-		opcode = OPCD(instr);
-		reg = RS(instr);
-		areg = RA(instr);
-
-		if (IS_DFORM(opcode)) {
-			f1 = 0;
-			f2 = (instr & 0x04000000) >> 26;
-			f3 = (instr & 0x78000000) >> 27;
-		} else {
-			f1 = (instr & 0x00000006) >> 1;
-			f2 = (instr & 0x00000040) >> 6;
-			f3 = (instr & 0x00000780) >> 7;
-		}
-
-		instr = ((f1 << 5) | (f2 << 4) | f3);
-	} else {
-		reg = (regs->dsisr >> 5) & 0x1f;	/* source/dest register */
-		areg = regs->dsisr & 0x1f;		/* register to update */
-		instr = (regs->dsisr >> 10) & 0x7f;
-		instr |= (regs->dsisr >> 13) & 0x60;
-	}
+	/*
+	 * Return 1 on success
+	 * Return 0 if unable to handle the interrupt
+	 * Return -EFAULT if data address is bad
+	 */
+
+	dsisr = regs->dsisr;
+
+	/* Power4 doesn't set DSISR for an alignment interrupt */
+	if (__is_processor(PV_POWER4))
+		dsisr = make_dsisr( *((unsigned *)regs->nip) );
+
+	/* extract the operation and registers from the dsisr */
+	reg = (dsisr >> 5) & 0x1f;	/* source/dest register */
+	areg = dsisr & 0x1f;		/* register to update */
+	instr = (dsisr >> 10) & 0x7f;
+	instr |= (dsisr >> 13) & 0x60;
 
+	/* Lookup the operation in our table */
 	nb = aligninfo[instr].len;
-	if (nb == 0) {
-		long *p;
-		int i;
-
-		if (instr != DCBZ)
-			return 0;	/* too hard or invalid instruction */
-		/*
-		 * The dcbz (data cache block zero) instruction
-		 * gives an alignment fault if used on non-cacheable
-		 * memory.  We handle the fault mainly for the
-		 * case when we are running with the cache disabled
-		 * for debugging.
-		 */
-		p = (long *) (regs->dar & -L1_CACHE_BYTES);
-		for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
-			p[i] = 0;
-		return 1;
-	}
-
 	flags = aligninfo[instr].flags;
+
+	/* DAR has the operand effective address */
 	addr = (unsigned char *)regs->dar;
 
+	/* A size of 0 indicates an instruction we don't support */
+	/* we also don't support the multiples (lmw, stmw, lmd, stmd) */
+	if ((nb == 0) || (flags & M))
+		return 0;		/* too hard or invalid instruction */
+
+	/*
+	 * Special handling for dcbz
+	 * dcbz may give an alignment exception for accesses to caching inhibited
+	 * storage
+	 */
+	if (instr == DCBZ)
+		addr = (unsigned char *) ((unsigned long)addr & -L1_CACHE_BYTES);
+
 	/* Verify the address of the operand */
 	if (user_mode(regs)) {
 		if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
 			return -EFAULT;	/* bad address */
 	}
 
+	/* Force the fprs into the save area so we can reference them */
 	if ((flags & F) && (regs->msr & MSR_FP))
 		giveup_fpu(current);
-	if (flags & M)
-		return 0;		/* too hard for now */
-
-	/* If we read the operand, copy it in */
+	
+	/* If we are loading, get the data from user space */
 	if (flags & LD) {
-		if (nb == 2) {
-			data.v[0] = data.v[1] = 0;
-			if (__get_user(data.v[2], addr)
-			    || __get_user(data.v[3], addr+1))
+		data.ll = 0;
+		ret = 0;
+		p = addr;
+		switch (nb) {
+		case 8:
+			ret |= __get_user(data.v[0], p++);
+			ret |= __get_user(data.v[1], p++);
+			ret |= __get_user(data.v[2], p++);
+			ret |= __get_user(data.v[3], p++);
+		case 4:
+			ret |= __get_user(data.v[4], p++);
+			ret |= __get_user(data.v[5], p++);
+		case 2:
+			ret |= __get_user(data.v[6], p++);
+			ret |= __get_user(data.v[7], p++);
+			if (ret)
 				return -EFAULT;
-		} else {
-			for (i = 0; i < nb; ++i)
-				if (__get_user(data.v[i], addr+i))
-					return -EFAULT;
 		}
 	}
-	/* Unfortunately D (== 0x100) doesn't fit in the aligninfo[n].flags
-	   field.  So synthesize it here. */
-	if ((flags & F) == 0 && nb == 8)
-		flags |= D;
-
-	switch (flags & ~U) {
-	case LD+SE:
-		if (data.v[2] >= 0x80)
-			data.v[0] = data.v[1] = -1;
-		/* fall through */
-	case LD:
-		regs->gpr[reg] = data.l;
-		break;
-	case LD+D:
-		regs->gpr[reg] = data.ll;
-		break;
-	case LD+S:
-		if (nb == 2) {
-			SWAP(data.v[2], data.v[3]);
-		} else {
-			SWAP(data.v[0], data.v[3]);
-			SWAP(data.v[1], data.v[2]);
+	
+	/* If we are storing, get the data from the saved gpr or fpr */
+	if (flags & ST) {
+		if (flags & F) {
+			if (nb == 4) {
+				/* Doing stfs, have to convert to single */
+				enable_kernel_fp();
+				cvt_df(&current->thread.fpr[reg], (float *)&data.v[4], &current->thread.fpscr);
+			}
+			else
+				data.dd = current->thread.fpr[reg];
 		}
-		regs->gpr[reg] = data.l;
-		break;
-	case ST:
-		data.l = regs->gpr[reg];
-		break;
-	case ST+D:
-		data.ll = regs->gpr[reg];
-		break;
-	case ST+S:
-		data.l = regs->gpr[reg];
-		if (nb == 2) {
-			SWAP(data.v[2], data.v[3]);
-		} else {
-			SWAP(data.v[0], data.v[3]);
-			SWAP(data.v[1], data.v[2]);
+		else 
+			data.ll = regs->gpr[reg];
+	}
+	
+	/* Swap bytes as needed */
+	if (flags & SW) {
+		if (nb == 2)
+			SWAP(data.v[6], data.v[7]);
+		else {	/* nb must be 4 */
+			SWAP(data.v[4], data.v[7]);
+			SWAP(data.v[5], data.v[6]);
 		}
-		break;
-	case LD+F:
-		current->thread.fpr[reg] = data.d;
-		break;
-	case ST+F:
-		data.d = current->thread.fpr[reg];
-		break;
-	/* these require some floating point conversions... */
-	/* we'd like to use the assignment, but we have to compile
-	 * the kernel with -msoft-float so it doesn't use the
-	 * fp regs for copying 8-byte objects. */
-	case LD+F+S:
-		enable_kernel_fp();
-		cvt_fd(&data.f, &current->thread.fpr[reg], &current->thread.fpscr);
-		/* current->thread.fpr[reg] = data.f; */
-		break;
-	case ST+F+S:
-		enable_kernel_fp();
-		cvt_df(&current->thread.fpr[reg], &data.f, &current->thread.fpscr);
-		/* data.f = current->thread.fpr[reg]; */
-		break;
-	default:
-		printk("align: can't handle flags=%x\n", flags);
-		return 0;
 	}
-
+	
+	/* Sign extend as needed */
+	if (flags & SE) {
+		if ( nb == 2 )
+			data.ll = data.x16.low16;
+		else	/* nb must be 4 */
+			data.ll = data.x32.low32;
+	}
+	
+	/* If we are loading, move the data to the gpr or fpr */
+	if (flags & LD) {
+		if (flags & F) {
+			if (nb == 4) {
+				/* Doing lfs, have to convert to double */
+				enable_kernel_fp();
+				cvt_fd((float *)&data.v[4], &current->thread.fpr[reg], &current->thread.fpscr);
+			}
+			else
+				current->thread.fpr[reg] = data.dd;
+		}
+		else
+			regs->gpr[reg] = data.ll;
+	}
+	
+	/* If we are storing, copy the data to the user */
 	if (flags & ST) {
-		if (nb == 2) {
-			if (__put_user(data.v[2], addr)
-			    || __put_user(data.v[3], addr+1))
-				return -EFAULT;
-		} else {
-			for (i = 0; i < nb; ++i)
-				if (__put_user(data.v[i], addr+i))
-					return -EFAULT;
+		ret = 0;
+		p = addr;
+		switch (nb) {
+		case 128:	/* Special case - must be dcbz */
+			lp = (unsigned long *)p;
+			for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+				ret |= __put_user(0, lp++);
+			break;
+		case 8:
+			ret |= __put_user(data.v[0], p++);
+			ret |= __put_user(data.v[1], p++);
+			ret |= __put_user(data.v[2], p++);
+			ret |= __put_user(data.v[3], p++);
+		case 4:
+			ret |= __put_user(data.v[4], p++);
+			ret |= __put_user(data.v[5], p++);
+		case 2:
+			ret |= __put_user(data.v[6], p++);
+			ret |= __put_user(data.v[7], p++);
 		}
+		if (ret)
+			return -EFAULT;
 	}
-
+	
+	/* Update RA as needed */
 	if (flags & U) {
 		regs->gpr[areg] = regs->dar;
 	}
 
 	return 1;
 }
+
diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c
--- a/arch/ppc64/kernel/chrp_setup.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/chrp_setup.c	Sun Apr 14 12:16:55 2002
@@ -342,12 +342,15 @@
 
 extern void setup_default_decr(void);
 
+extern unsigned long ppc_proc_freq;
+extern unsigned long ppc_tb_freq;
+
 void __init pSeries_calibrate_decr(void)
 {
 	struct device_node *cpu;
 	struct div_result divres;
 	int *fp;
-	unsigned long freq;
+	unsigned long freq, processor_freq;
 
 	/*
 	 * The cpu node should have a timebase-frequency property
@@ -360,8 +363,19 @@
 		if (fp != 0)
 			freq = *fp;
 	}
+	ppc_tb_freq = freq;
+	processor_freq = freq;
+	if (cpu != 0) {
+		fp = (int *) get_property(cpu, "clock-frequency", NULL);
+		if (fp != 0)
+			processor_freq = *fp;
+	}
+	ppc_proc_freq = processor_freq;
+	
         printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", 
 	       freq/1000000, freq%1000000 );
+	printk("time_init: processor frequency   = %lu.%.6lu MHz\n",
+		processor_freq/1000000, processor_freq%1000000 );
 
 	tb_ticks_per_jiffy = freq / HZ;
 	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
--- a/arch/ppc64/kernel/entry.S	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc64/kernel/entry.S	Sun Apr 14 12:16:54 2002
@@ -42,10 +42,19 @@
 	.long	-1
 #endif
 
+	.section	".toc","aw"
+.SYS_CALL_TABLE:
+	.tc .sys_call_table[TC],.sys_call_table
+
+.SYS_CALL_TABLE32:
+	.tc .sys_call_table32[TC],.sys_call_table32
+
+	.section	".text"
+	.align 3
+
 /*
  * Handle a system call.
  */
-	.text
 _GLOBAL(DoSyscall)
 	std	r0,THREAD+LAST_SYSCALL(r13)
 	ld	r11,_CCR(r1)	/* Clear SO bit in CR */
@@ -94,7 +103,7 @@
 #ifdef CONFIG_BINFMT_ELF32
 	andi.	r11,r10,_TIF_32BIT
 	beq-	15f
-	LOADADDR(r10,.sys_call_table32)
+	ld	r10,.SYS_CALL_TABLE32@toc(2)
 /*
  * Now mung the first 4 parameters into shape, by making certain that
  * the high bits (most significant 32 bits in 64 bit reg) are 0
@@ -111,7 +120,7 @@
 	b	17f
 15:
 #endif
-	LOADADDR(r10,.sys_call_table)
+	ld	r10,.SYS_CALL_TABLE@toc(2)
 17:	slwi	r0,r0,3
 	ldx	r10,r10,r0	/* Fetch system call handler [ptr] */
 	mtlr	r10
@@ -167,7 +176,7 @@
 	ld	r10,TI_FLAGS(r10)
 	andi.	r11,r10,_TIF_32BIT
 	beq-	55f
-	LOADADDR(r10,.sys_call_table32)
+	ld	r10,.SYS_CALL_TABLE32@toc(2)
 /*
  * Now mung the first 4 parameters into shape, by making certain that
  * the high bits (most significant 32 bits in 64 bit reg) are 0
@@ -184,7 +193,7 @@
 	b	57f
 55:
 #endif
-	LOADADDR(r10,.sys_call_table)
+	ld	r10,.SYS_CALL_TABLE@toc(2)
 57:
 	slwi	r0,r0,3
 	ldx	r10,r10,r0	/* Fetch system call handler [ptr] */
@@ -255,38 +264,33 @@
  * Note: there are two ways to get to the "going out" portion
  * of this code; either by coming in via the entry (_switch)
  * or via "fork" which must set up an environment equivalent
- * to the "_switch" path.  If you change this (or in particular, the
- * SAVE_REGS macro), you'll have to change the fork code also.
+ * to the "_switch" path.  If you change this you'll have to change
+ * the fork code also.
  *
  * The code which creates the new task context is in 'copy_thread'
- * in arch/ppc/kernel/process.c
+ * in arch/ppc64/kernel/process.c
  */
 _GLOBAL(_switch)
-	stdu	r1,-INT_FRAME_SIZE(r1)
-	ld	r6,0(r1)
-	std	r6,GPR1(r1)
+	mflr	r0
+	std	r0,16(r1)
+	stdu	r1,-SWITCH_FRAME_SIZE(r1)
 	/* r3-r13 are caller saved -- Cort */
-	SAVE_GPR(2, r1)
 	SAVE_8GPRS(14, r1)
 	SAVE_10GPRS(22, r1)
 	mflr	r20		/* Return to switch caller */
 	mfmsr	r22
+	andi.	r21, r22, MSR_FP
+	beq+	1f
 	li	r6,MSR_FP	/* Disable floating-point */
 	andc	r22,r22,r6
 	mtmsrd	r22
 	isync
-	std	r20,_NIP(r1)
-	std	r22,_MSR(r1)
-	std	r20,_LINK(r1)
-	mfcr	r20
-	std	r20,_CCR(r1)
-	li	r6,0x0ff0
-	std	r6,TRAP(r1)
+1:	std	r20,_NIP(r1)
+	mfcr	r23
+	std	r23,_CCR(r1)
 	std	r1,KSP(r3)	/* Set old stack pointer */
 
 	mfspr	r5,SPRG3	/* Get Paca */
-	/* XXX remove - Anton */
-	addi	r3,r3,-THREAD	/* old 'current' for return value */
 	addi	r13,r4,-THREAD	/* Convert THREAD to 'current' */
 	std	r13,PACACURRENT(r5)	/* Set new 'current' */
 
@@ -298,6 +302,7 @@
 	insrdi	r9,r7,1,63	/* Insert run light into CTRL */
 	mtspr	CTRLT,r9
 #endif
+
 	ld	r1,KSP(r4)	/* Load new stack pointer */
 	ld	r6,_CCR(r1)
 	mtcrf	0xFF,r6
@@ -306,8 +311,8 @@
 	REST_10GPRS(22, r1)
 
 	ld	r7,_NIP(r1)	/* Return to _switch caller in new task */
-	ld	r1,GPR1(r1)
 	mtlr	r7
+	addi	r1,r1,SWITCH_FRAME_SIZE
 	blr
 
 _GLOBAL(ret_from_fork)
@@ -377,6 +382,7 @@
 	mtlr	r0
 	ld	r3,_XER(r1)
 	mtspr	XER,r3
+
 	REST_8GPRS(5, r1)
 	REST_10GPRS(14, r1)
 	REST_8GPRS(24, r1)
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/head.S	Sun Apr 14 12:16:59 2002
@@ -993,6 +993,7 @@
 	li      r21,0
 	rldimi  r21,r20,12,0
 	ori     r20,r21,1024
+	ori	r20,r20,128    /* set class bit for kernel region */
 #ifndef CONFIG_PPC_ISERIES
 	ori	r20,r20,256    /* map kernel region with large ptes */
 #endif
@@ -1824,10 +1825,10 @@
 hardware_int_paca0:
 	.space	8*4096
 
-/* 1 page segment table per cpu (max 48) */
+/* 1 page segment table per cpu (max 48, cpu0 allocated at 0x5000) */
 	.globl	stab_array
 stab_array:
-	.space	4096 * 48
+	.space	4096 * 47
 	
 /*
  * This space gets a copy of optional info passed to us by the bootstrap
diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c
--- a/arch/ppc64/kernel/htab.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/htab.c	Sun Apr 14 12:16:55 2002
@@ -1,10 +1,11 @@
 /*
- * 
- *
  * PowerPC64 port by Mike Corrigan and Dave Engebretsen
  *   {mikejc|engebret}@us.ibm.com
  *
  *    Copyright (c) 2000 Mike Corrigan <mikejc@us.ibm.com>
+ *
+ * SMP scalability work:
+ *    Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
  * 
  *    Module name: htab.c
  *
@@ -18,17 +19,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/pgtable.h>
-#include <asm/mmu.h>
-#include <asm/mmu_context.h>
-#include <asm/page.h>
-#include <asm/types.h>
-#include <asm/init.h>
-#include <asm/system.h>
-#include <asm/iSeries/LparData.h>
 #include <linux/spinlock.h>
-#include <asm/ppcdebug.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
@@ -36,56 +27,43 @@
 #include <linux/sysctl.h>
 #include <linux/ctype.h>
 #include <linux/cache.h>
+
+#include <asm/ppcdebug.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/page.h>
+#include <asm/types.h>
+#include <asm/init.h>
+#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/Naca.h>
 #include <asm/system.h>
 #include <asm/pmc.h>
 #include <asm/machdep.h>
 #include <asm/lmb.h>
+#include <asm/abs_addr.h>
+#include <asm/tlbflush.h>
 #ifdef CONFIG_PPC_EEH
 #include <asm/eeh.h>
 #endif
 
-/* For iSeries */
-#include <asm/iSeries/HvCallHpt.h>
-
-/* Note:  pte   --> Linux PTE
+/*
+ * Note:  pte   --> Linux PTE
  *        HPTE  --> PowerPC Hashed Page Table Entry
  */
 
 HTAB htab_data = {NULL, 0, 0, 0, 0};
 
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-		   void *buffer, size_t *lenp);
-
-void htab_initialize(void);
-void make_pte_LPAR(HPTE *htab,
-	      unsigned long va, unsigned long pa, int mode,
-	      unsigned long hash_mask, int large);
-
-extern unsigned long reloc_offset(void);
-extern unsigned long get_kernel_vsid( unsigned long ea );
-extern void cacheable_memzero( void *, unsigned int );
-
 extern unsigned long _SDR1;
 extern unsigned long klimit;
-extern struct Naca *naca;
-
-extern unsigned long _ASR;
-extern inline void make_ste(unsigned long stab,
-			    unsigned long esid, unsigned long vsid);
-
-extern char _stext[], _etext[], __start_naca[], __end_stab[];
-
-static spinlock_t hash_table_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
+extern unsigned long reloc_offset(void);
 #define PTRRELOC(x)	((typeof(x))((unsigned long)(x) - offset))
 #define PTRUNRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
 #define RELOC(x)	(*PTRRELOC(&(x)))
 
-extern unsigned long htab_size( unsigned long );
-unsigned long hpte_getword0_iSeries( unsigned long slot );
-
 #define KB (1024)
 #define MB (1024*KB)
 static inline void
@@ -94,7 +72,7 @@
 {
 	unsigned long addr, offset = reloc_offset();
 	HTAB *_htab_data = PTRRELOC(&htab_data);
-	HPTE  *htab  = (HPTE *)__v2a(_htab_data->htab);
+	HPTE *htab = (HPTE *)__v2a(_htab_data->htab);
 	unsigned int step;
 
 	if (large)
@@ -105,8 +83,12 @@
 	for (addr = start; addr < end; addr += step) {
 		unsigned long vsid = get_kernel_vsid(addr);
 		unsigned long va = (vsid << 28) | (addr & 0xfffffff);
-		make_pte(htab, va, (unsigned long)__v2a(addr), mode, mask,
-				large);
+		if (_machine == _MACH_pSeriesLP)
+			pSeries_lpar_make_pte(htab, va,
+				(unsigned long)__v2a(addr), mode, mask, large);
+		else
+			pSeries_make_pte(htab, va,
+				(unsigned long)__v2a(addr), mode, mask, large);
 	}
 }
 
@@ -115,7 +97,7 @@
 {
 	unsigned long table, htab_size_bytes;
 	unsigned long pteg_count;
-	unsigned long mode_ro, mode_rw, mask;
+	unsigned long mode_rw, mask;
 	unsigned long offset = reloc_offset();
 	struct Naca *_naca = RELOC(naca);
 	HTAB *_htab_data = PTRRELOC(&htab_data);
@@ -136,7 +118,7 @@
 	_htab_data->htab_num_ptegs = pteg_count;
 	_htab_data->htab_hash_mask = pteg_count - 1;
 
-	if(_machine == _MACH_pSeries) {
+	if (_machine == _MACH_pSeries) {
 		/* Find storage for the HPT.  Must be contiguous in
 		 * the absolute address space.
 		 */
@@ -149,697 +131,235 @@
 		RELOC(_SDR1) = table + __ilog2(pteg_count) - 11;
 
 		/* Initialize the HPT with no entries */
-		cacheable_memzero((void *)table, htab_size_bytes);
+		memset((void *)table, 0, htab_size_bytes);
 	} else {
 		_htab_data->htab = NULL;
 		RELOC(_SDR1) = 0; 
 	}
 
-	mode_ro = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RXRX;
 	mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
 	mask = pteg_count-1;
 
-	/* Create PTE's for the kernel text and data sections plus
-	 * the HPT and HPTX arrays.  Make the assumption that
-	 * (addr & KERNELBASE) == 0 (ie they are disjoint).
-	 * We also assume that the va is <= 64 bits.
-	 */
-#if 0
-	create_pte_mapping((unsigned long)_stext,       (unsigned long)__start_naca,                 mode_ro, mask);
-	create_pte_mapping((unsigned long)__start_naca, (unsigned long)__end_stab,                   mode_rw, mask);
-	create_pte_mapping((unsigned long)__end_stab,   (unsigned long)_etext,                       mode_ro, mask);
-	create_pte_mapping((unsigned long)_etext,       RELOC(klimit),                               mode_rw, mask);
-	create_pte_mapping((unsigned long)__a2v(table), (unsigned long)__a2v(table+htab_size_bytes), mode_rw, mask);
-#else
-#ifndef CONFIG_PPC_ISERIES
+	/* XXX we currently map kernel text rw, should fix this */
 	if (__is_processor(PV_POWER4) && _naca->physicalMemorySize > 256*MB) {
 		create_pte_mapping((unsigned long)KERNELBASE, 
 				   KERNELBASE + 256*MB, mode_rw, mask, 0);
 		create_pte_mapping((unsigned long)KERNELBASE + 256*MB, 
 				   KERNELBASE + (_naca->physicalMemorySize), 
 				   mode_rw, mask, 1);
-		return;
+	} else {
+		create_pte_mapping((unsigned long)KERNELBASE, 
+				   KERNELBASE+(_naca->physicalMemorySize), 
+				   mode_rw, mask, 0);
 	}
-#endif
-	create_pte_mapping((unsigned long)KERNELBASE, 
-			   KERNELBASE+(_naca->physicalMemorySize), 
-			   mode_rw, mask, 0);
-#endif
 }
 #undef KB
 #undef MB
 
 /*
- * Create a pte.  Used during initialization only.
- * We assume the PTE will fit in the primary PTEG.
- */
-void make_pte(HPTE *htab,
-	      unsigned long va, unsigned long pa, int mode,
-	      unsigned long hash_mask, int large)
-{
-	HPTE  *hptep;
-	unsigned long hash, i;
-	volatile unsigned long x = 1;
-	unsigned long vpn;
-
-#ifdef CONFIG_PPC_PSERIES
-	if(_machine == _MACH_pSeriesLP) {
-		make_pte_LPAR(htab, va, pa, mode, hash_mask, large); 
-		return;
-	}
-#endif
-
-	if (large)
-		vpn = va >> 24;
-	else
-		vpn = va >> 12;
-
-	hash = hpt_hash(vpn, large);
-
-	hptep  = htab +  ((hash & hash_mask)*HPTES_PER_GROUP);
-
-	for (i = 0; i < 8; ++i, ++hptep) {
-		if ( hptep->dw0.dw0.v == 0 ) {		/* !valid */
-			hptep->dw1.dword1 = pa | mode;
-			hptep->dw0.dword0 = 0;
-			hptep->dw0.dw0.avpn = va >> 23;
-			hptep->dw0.dw0.bolted = 1;	/* bolted */
-			hptep->dw0.dw0.v = 1;		/* make valid */
-			return;
-		}
-	}
-
-	/* We should _never_ get here and too early to call xmon. */
-	for(;x;x|=1);
-}
-
-/* Functions to invalidate a HPTE */
-static void hpte_invalidate_iSeries( unsigned long slot )
-{
-	HvCallHpt_invalidateSetSwBitsGet( slot, 0, 0 );
-}
-
-static void hpte_invalidate_pSeries( unsigned long slot )
-{
-	/* Local copy of the first doubleword of the HPTE */
-	union {
-		unsigned long d;
-		Hpte_dword0   h;
-	} hpte_dw0;
-
-	/* Locate the HPTE */
-	HPTE  * hptep  = htab_data.htab  + slot;
-
-	/* Get the first doubleword of the HPTE */
-	hpte_dw0.d = hptep->dw0.dword0;
-
-	/* Invalidate the hpte */
-	hptep->dw0.dword0 = 0;
-
-	/* Invalidate the tlb   */
-	{
-		unsigned long vsid, group, pi, pi_high;
-
-		vsid = hpte_dw0.h.avpn >> 5;
-		group = slot >> 3;
-		if(hpte_dw0.h.h) {
-			group = ~group;
-		} 
-		pi = (vsid ^ group) & 0x7ff;
-		pi_high = (hpte_dw0.h.avpn & 0x1f) << 11;
-		pi |= pi_high;
-		_tlbie(pi << 12);
-	}
-}
-
-
-/* Select an available HPT slot for a new HPTE
- *   return slot index (if in primary group)
- *   return -slot index (if in secondary group) 
- */
-static long hpte_selectslot_iSeries( unsigned long vpn )
-{
-	HPTE hpte;
-	long ret_slot, orig_slot;
-	unsigned long primary_hash;
-	unsigned long hpteg_slot;
-	unsigned long slot;
-	unsigned i, k;
-	union {
-		unsigned long	d;
-		Hpte_dword0	h;
-	} hpte_dw0;
-
-	ret_slot = orig_slot = HvCallHpt_findValid( &hpte, vpn );
-	if ( hpte.dw0.dw0.v ) {		/* If valid ...what do we do now? */
-		udbg_printf( "hpte_selectslot_iSeries: vpn 0x%016lx already valid at slot 0x%016lx\n", vpn, ret_slot );
-		udbg_printf( "hpte_selectslot_iSeries: returned hpte 0x%016lx 0x%016lx\n", hpte.dw0.dword0, hpte.dw1.dword1 );
-
-		return (0x8000000000000000); 
-		/*			panic("select_hpte_slot found entry already valid\n"); */
-	}
-	if ( ret_slot == -1 ) {		/* -1 indicates no available slots */
-
-		/* No available entry found in secondary group */
-
-		PMC_SW_SYSTEM(htab_capacity_castouts);
-
-		primary_hash = hpt_hash(vpn, 0);
-		hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-		k = htab_data.next_round_robin++ & 0x7;
-
-		for ( i=0; i<HPTES_PER_GROUP; ++i ) {
-			if ( k == HPTES_PER_GROUP )
-				k = 0;
-			slot = hpteg_slot + k;
-			hpte_dw0.d = hpte_getword0_iSeries( slot );
-			if ( !hpte_dw0.h.bolted ) {
-				hpte_invalidate_iSeries( slot );
-				ret_slot = slot;
-			}
-			++k;
-		}
-	} else {
-		if ( ret_slot < 0 ) {
-			PMC_SW_SYSTEM(htab_primary_overflows);
-			ret_slot &= 0x7fffffffffffffff;
-			ret_slot = -ret_slot;
-		}
-	}
-	if ( ret_slot == -1 ) {
-		/* No non-bolted entry found in primary group - time to panic */
-        	udbg_printf("hpte_selectslot_pSeries - No non-bolted HPTE in group 0x%lx! \n", hpteg_slot/HPTES_PER_GROUP);
-        	panic("No non-bolted HPTE in group %lx", (unsigned long)hpteg_slot/HPTES_PER_GROUP);
-	}
-	PPCDBG(PPCDBG_MM, "hpte_selectslot_iSeries: vpn=0x%016lx, orig_slot=0x%016lx, ret_slot=0x%016lx \n",
-	       vpn, orig_slot, ret_slot );	
-	return ret_slot;
-}
-
-static long hpte_selectslot_pSeries(unsigned long vpn)
-{
-	HPTE * hptep;
-	unsigned long primary_hash;
-	unsigned long hpteg_slot;
-	unsigned i, k;
-
-	/* Search the primary group for an available slot */
-
-	primary_hash = hpt_hash(vpn, 0);
-	hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-	hptep = htab_data.htab + hpteg_slot;
-	
-	for (i=0; i<HPTES_PER_GROUP; ++i) {
-		if ( hptep->dw0.dw0.v == 0 ) {
-			/* If an available slot found, return it */
-			return hpteg_slot + i;
-		}
-		hptep++;
-	}
-
-	/* No available entry found in primary group */
-
-	PMC_SW_SYSTEM(htab_primary_overflows);
-
-	/* Search the secondary group */
-
-	hpteg_slot = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-	hptep = htab_data.htab + hpteg_slot;
-
-	for (i=0; i<HPTES_PER_GROUP; ++i) {
-		if ( hptep->dw0.dw0.v == 0 ) {
-			/* If an available slot found, return it */
-			return -(hpteg_slot + i);
-		}
-		hptep++;
-	}
-
-	/* No available entry found in secondary group */
-
-	PMC_SW_SYSTEM(htab_capacity_castouts);
-
-	/* Select an entry in the primary group to replace */
-
-	hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-	hptep = htab_data.htab + hpteg_slot;
-	k = htab_data.next_round_robin++ & 0x7;
-
-	for (i=0; i<HPTES_PER_GROUP; ++i) {
-		if (k == HPTES_PER_GROUP)
-			k = 0;
-
-		if (!hptep[k].dw0.dw0.bolted) {
-			hpteg_slot += k;
-			/* Invalidate the current entry */
-			ppc_md.hpte_invalidate(hpteg_slot); 
-			return hpteg_slot;
-		}
-		++k;
-	}
-
-	/* No non-bolted entry found in primary group - time to panic */
-        udbg_printf("hpte_selectslot_pSeries - No non-bolted HPTE in group 0x%lx! \n", hpteg_slot/HPTES_PER_GROUP);
-	/*      xmon(0); */
-        panic("No non-bolted HPTE in group %lx", (unsigned long)hpteg_slot/HPTES_PER_GROUP);
-
-	/* keep the compiler happy */
-	return 0;
-}
-
-unsigned long hpte_getword0_iSeries( unsigned long slot )
-{
-	unsigned long dword0;
-
-	HPTE hpte;
-	HvCallHpt_get( &hpte, slot );
-	dword0 = hpte.dw0.dword0;
-
-	return dword0;
-}
-
-unsigned long hpte_getword0_pSeries( unsigned long slot )
-{
-	unsigned long dword0;
-	HPTE * hptep = htab_data.htab + slot;
-
-	dword0 = hptep->dw0.dword0;
-	return dword0;
-}
-
-static long hpte_find_iSeries(unsigned long vpn)
-{
-	HPTE hpte;
-	long slot;
-
-	slot = HvCallHpt_findValid( &hpte, vpn );
-	if ( hpte.dw0.dw0.v ) {
-		if ( slot < 0 ) {
-			slot &= 0x7fffffffffffffff;
-			slot = -slot;
-		}
-	} else
-		slot = -1;
-	return slot;
-}
-
-static long hpte_find_pSeries(unsigned long vpn)
-{
-	union {
-		unsigned long d;
-		Hpte_dword0   h;
-	} hpte_dw0;
-	long slot;
-	unsigned long hash;
-	unsigned long i,j;
-
-	hash = hpt_hash(vpn, 0);
-	for ( j=0; j<2; ++j ) {
-		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-		for ( i=0; i<HPTES_PER_GROUP; ++i ) {
-			hpte_dw0.d = hpte_getword0_pSeries( slot );
-			if ( ( hpte_dw0.h.avpn == ( vpn >> 11 ) ) &&
-			     ( hpte_dw0.h.v ) &&
-			     ( hpte_dw0.h.h == j ) ) {
-				/* HPTE matches */
-				if ( j )
-					slot = -slot;
-				return slot;
-			}
-			++slot;
-		}
-		hash = ~hash;
-	}
-	return -1;
-} 
-
-/* This function is called by iSeries setup when initializing the hpt */
-void build_valid_hpte( unsigned long vsid, unsigned long ea, unsigned long pa,
-		       pte_t * ptep, unsigned hpteflags, unsigned bolted )
-{
-	unsigned long vpn, flags;
-	long hpte_slot;
-	unsigned hash;
-	pte_t pte;
-
-	vpn = ((vsid << 28) | ( ea & 0xffff000 )) >> 12;
-
-	spin_lock_irqsave( &hash_table_lock, flags );
-
-	hpte_slot = ppc_md.hpte_selectslot( vpn );
-	hash = 0;
-	if ( hpte_slot < 0 ) {
-		if ( hpte_slot == 0x8000000000000000 ) {
-			udbg_printf("hash_page: ptep    = 0x%016lx\n", 
-				    (unsigned long)ptep );
-			udbg_printf("hash_page: ea      = 0x%016lx\n", ea );
-			udbg_printf("hash_page: vpn     = 0x%016lx\n", vpn );
-               
-			panic("hash_page: hpte already exists\n");
-		}
-		hash = 1;
-		hpte_slot = -hpte_slot;
-	}
-	ppc_md.hpte_create_valid( hpte_slot, vpn, pa >> 12, hash, ptep,
-				  hpteflags, bolted );
-
-	if ( ptep ) {
-		/* Get existing pte flags */
-		pte = *ptep;
-		pte_val(pte) &= ~_PAGE_HPTEFLAGS;
-
-		/* Add in the has hpte flag */
-		pte_val(pte) |= _PAGE_HASHPTE;
-
-		/* Add in the _PAGE_SECONDARY flag */
-		pte_val(pte) |= hash << 15;
-
-		/* Add in the hpte slot */
-		pte_val(pte) |= (hpte_slot << 12) & _PAGE_GROUP_IX;
-               
-		/* Save the new pte.  */
-		*ptep = pte;
-               
-	}
-	spin_unlock_irqrestore( &hash_table_lock, flags );
-}
-
-
-/* Create an HPTE and validate it
- *   It is assumed that the HPT slot currently is invalid.
- *   The HPTE is set with the vpn, rpn (converted to absolute)
- *   and flags
- */
-static void hpte_create_valid_iSeries(unsigned long slot, unsigned long vpn,
-				      unsigned long prpn, unsigned hash, 
-				      void * ptep, unsigned hpteflags, 
-				      unsigned bolted )
-{
-	/* Local copy of HPTE */
-	struct {
-		/* Local copy of first doubleword of HPTE */
-		union {
-			unsigned long d;
-			Hpte_dword0   h;
-		} dw0;
-		/* Local copy of second doubleword of HPTE */
-		union {
-			unsigned long     d;
-			Hpte_dword1       h;
-			Hpte_dword1_flags f;
-		} dw1;
-	} lhpte;
-	
-	unsigned long avpn = vpn >> 11;
-	unsigned long arpn = physRpn_to_absRpn( prpn );
-
-	/* Fill in the local HPTE with absolute rpn, avpn and flags */
-	lhpte.dw1.d        = 0;
-	lhpte.dw1.h.rpn    = arpn;
-	lhpte.dw1.f.flags  = hpteflags;
-
-	lhpte.dw0.d        = 0;
-	lhpte.dw0.h.avpn   = avpn;
-	lhpte.dw0.h.h      = hash;
-	lhpte.dw0.h.bolted = bolted;
-	lhpte.dw0.h.v      = 1;
-
-	/* Now fill in the actual HPTE */
-	HvCallHpt_addValidate( slot, hash, (HPTE *)&lhpte );
-}
-
-static void hpte_create_valid_pSeries(unsigned long slot, unsigned long vpn,
-				      unsigned long prpn, unsigned hash, 
-				      void * ptep, unsigned hpteflags, 
-				      unsigned bolted)
-{
-	/* Local copy of HPTE */
-	struct {
-		/* Local copy of first doubleword of HPTE */
-		union {
-			unsigned long d;
-			Hpte_dword0   h;
-		} dw0;
-		/* Local copy of second doubleword of HPTE */
-		union {
-			unsigned long     d;
-			Hpte_dword1       h;
-			Hpte_dword1_flags f;
-		} dw1;
-	} lhpte;
-	
-	unsigned long avpn = vpn >> 11;
-	unsigned long arpn = physRpn_to_absRpn( prpn );
-
-	HPTE *hptep;
-
-	/* Fill in the local HPTE with absolute rpn, avpn and flags */
-	lhpte.dw1.d        = 0;
-	lhpte.dw1.h.rpn    = arpn;
-	lhpte.dw1.f.flags  = hpteflags;
-
-	lhpte.dw0.d        = 0;
-	lhpte.dw0.h.avpn   = avpn;
-	lhpte.dw0.h.h      = hash;
-	lhpte.dw0.h.bolted = bolted;
-	lhpte.dw0.h.v      = 1;
-
-	/* Now fill in the actual HPTE */
-	hptep  = htab_data.htab  + slot;
-
-	/* Set the second dword first so that the valid bit
-	 * is the last thing set
-	 */
-	
-	hptep->dw1.dword1 = lhpte.dw1.d;
-
-	/* Guarantee the second dword is visible before
-	 * the valid bit
-	 */
-	
-	__asm__ __volatile__ ("eieio" : : : "memory");
-
-	/* Now set the first dword including the valid bit */
-	hptep->dw0.dword0 = lhpte.dw0.d;
-
-	__asm__ __volatile__ ("ptesync" : : : "memory");
-}
-
-/* find_linux_pte returns the address of a linux pte for a given 
+ * find_linux_pte returns the address of a linux pte for a given 
  * effective address and directory.  If not found, it returns zero.
  */
-
-pte_t  * find_linux_pte( pgd_t * pgdir, unsigned long ea )
+pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
 {
 	pgd_t *pg;
 	pmd_t *pm;
 	pte_t *pt = NULL;
 	pte_t pte;
-	pg = pgdir + pgd_index( ea );
-	if ( ! pgd_none( *pg ) ) {
 
-		pm = pmd_offset( pg, ea );
-		if ( ! pmd_none( *pm ) ) { 
-			pt = pte_offset( pm, ea );
+	pg = pgdir + pgd_index(ea);
+	if (!pgd_none(*pg)) {
+
+		pm = pmd_offset(pg, ea);
+		if (!pmd_none(*pm)) { 
+			pt = pte_offset_kernel(pm, ea);
 			pte = *pt;
-			if ( ! pte_present( pte ) )
+			if (!pte_present(pte))
 				pt = NULL;
 		}
 	}
 
 	return pt;
-
-}
-
-static inline unsigned long computeHptePP( unsigned long pte )
-{
-	return (     pte & _PAGE_USER )           |
-		( ( ( pte & _PAGE_USER )    >> 1 ) &
-		  ( ( ~( ( pte >> 2 ) &		/* _PAGE_RW */
-		         ( pte >> 7 ) ) ) &     /* _PAGE_DIRTY */
-			 1 ) );
 }
 
-static void hpte_updatepp_iSeries(long slot, unsigned long newpp, unsigned long va)
+static inline unsigned long computeHptePP(unsigned long pte)
 {
-	HvCallHpt_setPp( slot, newpp );
-}
-
-static void hpte_updatepp_pSeries(long slot, unsigned long newpp, unsigned long va)
-{
-	/* Local copy of first doubleword of HPTE */
-	union {
-		unsigned long d;
-		Hpte_dword0   h;
-	} hpte_dw0;
-	
-	/* Local copy of second doubleword of HPTE */
-	union {
-		unsigned long     d;
-		Hpte_dword1       h;
-		Hpte_dword1_flags f;
-	} hpte_dw1;	
-
-	HPTE *  hptep  = htab_data.htab  + slot;
-
-	/* Turn off valid bit in HPTE */
-	hpte_dw0.d = hptep->dw0.dword0;
-	hpte_dw0.h.v = 0;
-	hptep->dw0.dword0 = hpte_dw0.d;
-
-	/* Ensure it is out of the tlb too */
-	_tlbie( va );
-
-	/* Insert the new pp bits into the HPTE */
-	hpte_dw1.d = hptep->dw1.dword1;
-	hpte_dw1.h.pp = newpp;
-	hptep->dw1.dword1 = hpte_dw1.d;
-
-	/* Ensure it is visible before validating */
-	__asm__ __volatile__ ("eieio" : : : "memory");
-
-	/* Turn the valid bit back on in HPTE */
-	hpte_dw0.h.v = 1;
-	hptep->dw0.dword0 = hpte_dw0.d;
-
-	__asm__ __volatile__ ("ptesync" : : : "memory");
+	return (pte & _PAGE_USER) |
+		(((pte & _PAGE_USER) >> 1) &
+		 ((~((pte >> 2) &	/* _PAGE_RW */
+		     (pte >> 7))) &	/* _PAGE_DIRTY */
+		  1));
 }
 
 /*
- * Update the page protection bits.  Intended to be used to create
- * guard pages for kernel data structures on pages which are bolted
- * in the HPT.  Assumes pages being operated on will not be stolen. 
+ * Handle a fault by adding an HPTE. If the address can't be determined
+ * to be valid via Linux page tables, return 1. If handled return 0
  */
-void hpte_updateboltedpp_iSeries(unsigned long newpp, unsigned long ea )
+int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
+		pte_t *ptep)
 {
-	unsigned long vsid,va,vpn;
+	unsigned long va, vpn;
+	unsigned long newpp, prpn;
+	unsigned long hpteflags;
 	long slot;
+	pte_t old_pte, new_pte;
 
-	vsid = get_kernel_vsid( ea );
-	va = ( vsid << 28 ) | ( ea & 0x0fffffff );
+	/* Search the Linux page table for a match with va */
+	va = (vsid << 28) | (ea & 0x0fffffff);
 	vpn = va >> PAGE_SHIFT;
 
-	slot = ppc_md.hpte_find( vpn );
-	HvCallHpt_setPp( slot, newpp );
-}
-
-
-static __inline__ void set_pp_bit(unsigned long  pp, HPTE *addr)
-{
-	unsigned long old;
-	unsigned long *p = (unsigned long *)(&(addr->dw1));
-
-	__asm__ __volatile__(
-        "1:	ldarx	%0,0,%3\n\
-                rldimi  %0,%2,0,62\n\
-                stdcx.	%0,0,%3\n\
-            	bne	1b"
-        : "=&r" (old), "=m" (*p)
-        : "r" (pp), "r" (p), "m" (*p)
-        : "cc");
-}
+	/*
+	 * If no pte found or not present, send the problem up to
+	 * do_page_fault
+	 */
+	if (!ptep || !pte_present(*ptep))
+		return 1;
 
-/*
- * Update the page protection bits.  Intended to be used to create
- * guard pages for kernel data structures on pages which are bolted
- * in the HPT.  Assumes pages being operated on will not be stolen. 
- */
-void hpte_updateboltedpp_pSeries(unsigned long newpp, unsigned long ea)
-{
-	unsigned long vsid,va,vpn,flags;
-	long slot;
-	HPTE *hptep;
+	/* 
+	 * Check the user's access rights to the page.  If access should be
+	 * prevented then send the problem up to do_page_fault.
+	 */
+	access |= _PAGE_PRESENT;
+	if (access & ~(pte_val(*ptep)))
+		return 1;
 
-	vsid = get_kernel_vsid( ea );
-	va = ( vsid << 28 ) | ( ea & 0x0fffffff );
-	vpn = va >> PAGE_SHIFT;
+	/*
+	 * At this point, we have a pte (old_pte) which can be used to build
+	 * or update an HPTE. There are 2 cases:
+	 *
+	 * 1. There is a valid (present) pte with no associated HPTE (this is 
+	 *	the most common case)
+	 * 2. There is a valid (present) pte with an associated HPTE. The
+	 *	current values of the pp bits in the HPTE prevent access
+	 *	because we are doing software DIRTY bit management and the
+	 *	page is currently not DIRTY. 
+	 */
 
-	slot = ppc_md.hpte_find( vpn );
-	hptep = htab_data.htab  + slot;
+	old_pte = *ptep;
+	new_pte = old_pte;
+	/* If the attempted access was a store */
+	if (access & _PAGE_RW)
+		pte_val(new_pte) |= _PAGE_ACCESSED | _PAGE_DIRTY;
+	else
+		pte_val(new_pte) |= _PAGE_ACCESSED;
 
-	set_pp_bit(newpp , hptep);
+	newpp = computeHptePP(pte_val(new_pte));
 
-	/* Ensure it is out of the tlb too */
-	spin_lock_irqsave( &hash_table_lock, flags );
-	_tlbie( va );
-	spin_unlock_irqrestore( &hash_table_lock, flags );
-}
+	/* Check if pte already has an hpte (case 2) */
+	if (pte_val(old_pte) & _PAGE_HASHPTE) {
+		/* There MIGHT be an HPTE for this pte */
+		unsigned long hash, slot, secondary;
+
+		/* XXX fix large pte flag */
+		hash = hpt_hash(vpn, 0);
+		secondary = (pte_val(old_pte) & _PAGE_SECONDARY) >> 15;
+		if (secondary)
+			hash = ~hash;
+		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+		slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
 
+		/* XXX fix large pte flag */
+		if (ppc_md.hpte_updatepp(slot, newpp, va, 0) == -1)
+			pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
+		else
+			if (!pte_same(old_pte, new_pte))
+				*ptep = new_pte;
+	}
 
+	if (!(pte_val(old_pte) & _PAGE_HASHPTE)) {
+		/* XXX fix large pte flag */
+		unsigned long hash = hpt_hash(vpn, 0);
+		unsigned long hpte_group;
+		prpn = pte_val(old_pte) >> PTE_SHIFT;
+
+repeat:
+		hpte_group = ((hash & htab_data.htab_hash_mask) *
+			      HPTES_PER_GROUP) & ~0x7UL;
+
+		/* Update the linux pte with the HPTE slot */
+		pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
+		pte_val(new_pte) |= _PAGE_HASHPTE;
+
+		/* copy appropriate flags from linux pte */
+		hpteflags = (pte_val(new_pte) & 0x1f8) | newpp;
+
+		/* XXX fix large pte flag */
+		slot = ppc_md.insert_hpte(hpte_group, vpn, prpn, 0,
+					  hpteflags, 0, 0);
+
+		/* Primary is full, try the secondary */
+		if (slot == -1) {
+			pte_val(new_pte) |= 1 << 15;
+			hpte_group = ((~hash & htab_data.htab_hash_mask) *
+				      HPTES_PER_GROUP) & ~0x7UL; 
+			/* XXX fix large pte flag */
+			slot = ppc_md.insert_hpte(hpte_group, vpn, prpn,
+						  1, hpteflags, 0, 0);
+			if (slot == -1) {
+				if (mftb() & 0x1)
+					hpte_group = ((hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
+
+				ppc_md.remove_hpte(hpte_group);
+				goto repeat;
+                        }
+		}
+
+		pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
+
+		/* 
+		 * No need to use ldarx/stdcx here because all who
+		 * might be updating the pte will hold the
+		 * page_table_lock or the hash_table_lock
+		 * (we hold both)
+		 */
+		*ptep = new_pte;
+	}
 
-/* This is called very early. */
-void hpte_init_iSeries(void)
-{
-	ppc_md.hpte_invalidate   = hpte_invalidate_iSeries;
-	ppc_md.hpte_updatepp     = hpte_updatepp_iSeries;
-	ppc_md.hpte_updateboltedpp = hpte_updateboltedpp_iSeries;
-	ppc_md.hpte_getword0     = hpte_getword0_iSeries;
-	ppc_md.hpte_selectslot   = hpte_selectslot_iSeries;
-	ppc_md.hpte_create_valid = hpte_create_valid_iSeries;
-	ppc_md.hpte_find	 = hpte_find_iSeries;
-}
-void hpte_init_pSeries(void)
-{
-	ppc_md.hpte_invalidate   = hpte_invalidate_pSeries;
-	ppc_md.hpte_updatepp     = hpte_updatepp_pSeries;
-	ppc_md.hpte_updateboltedpp = hpte_updateboltedpp_pSeries;
-	ppc_md.hpte_getword0     = hpte_getword0_pSeries;
-	ppc_md.hpte_selectslot   = hpte_selectslot_pSeries;
-	ppc_md.hpte_create_valid = hpte_create_valid_pSeries;
-	ppc_md.hpte_find	 = hpte_find_pSeries;
+	return 0;
 }
 
-/* Handle a fault by adding an HPTE 
- * If the address can't be determined to be valid
- * via Linux page tables, return 1.  If handled
- * return 0
- */
-int hash_page( unsigned long ea, unsigned long access )
+int hash_page(unsigned long ea, unsigned long access)
 {
-	int rc = 1;
-	void * pgdir = NULL;
-	unsigned long va, vsid, vpn;
-	unsigned long newpp, hash_ind, prpn;
-	unsigned long hpteflags, regionid;
-	long slot;
-	struct mm_struct * mm;
-	pte_t old_pte, new_pte, *ptep;
+	void *pgdir;
+	unsigned long vsid;
+	struct mm_struct *mm;
+	pte_t *ptep;
+	int ret;
 
 	/* Check for invalid addresses. */
-	if (!IS_VALID_EA(ea)) {
+	if (!IS_VALID_EA(ea))
 		return 1;
-	}
 
-	regionid =  REGION_ID(ea);
-	switch ( regionid ) {
+ 	switch (REGION_ID(ea)) {
 	case USER_REGION_ID:
 		mm = current->mm;
-		if ( mm == NULL ) {
-			PPCDBG(PPCDBG_MM, "hash_page returning; mm = 0\n"); 
+		if (mm == NULL)
 			return 1;
-		}
-		vsid = get_vsid(mm->context, ea );
+
+		vsid = get_vsid(mm->context, ea);
 		break;
 	case IO_REGION_ID:
 		mm = &ioremap_mm;
-		vsid = get_kernel_vsid( ea );
+		vsid = get_kernel_vsid(ea);
 		break;
 	case VMALLOC_REGION_ID:
 		mm = &init_mm;
-		vsid = get_kernel_vsid( ea );
+		vsid = get_kernel_vsid(ea);
 		break;
 #ifdef CONFIG_PPC_EEH
 	case IO_UNMAPPED_REGION_ID:
 		udbg_printf("EEH Error ea = 0x%lx\n", ea);
- 		PPCDBG_ENTER_DEBUGGER();
+		PPCDBG_ENTER_DEBUGGER();
 		panic("EEH Error ea = 0x%lx\n", ea);
 		break;
 #endif
 	case KERNEL_REGION_ID:
-		/* As htab_initialize is now, we shouldn't ever get here since
+		/*
+		 * As htab_initialize is now, we shouldn't ever get here since
 		 * we're bolting the entire 0xC0... region.
 		 */
 		udbg_printf("Little faulted on kernel address 0x%lx\n", ea);
- 		PPCDBG_ENTER_DEBUGGER();
+		PPCDBG_ENTER_DEBUGGER();
 		panic("Little faulted on kernel address 0x%lx\n", ea);
 		break;
 	default:
@@ -848,383 +368,63 @@
 		break;
 	}
 
-	/* Search the Linux page table for a match with va */
-        va = ( vsid << 28 ) | ( ea & 0x0fffffff );
-	vpn = va >> PAGE_SHIFT;
 	pgdir = mm->pgd;
-	PPCDBG(PPCDBG_MM, "hash_page ea = 0x%16.16lx, va = 0x%16.16lx\n          current = 0x%16.16lx, access = %lx\n", ea, va, current, access); 
-                if ( pgdir == NULL ) {
-                return 1;
-	}
-	
-	/* Lock the Linux page table to prevent mmap and kswapd
-	 * from modifying entries while we search and update
-	 */
-	
-	spin_lock( &mm->page_table_lock );
-	
-	ptep = find_linux_pte( pgdir, ea );
-	/* If no pte found, send the problem up to do_page_fault */
-	if ( ! ptep ) {
-	  spin_unlock( &mm->page_table_lock );
-	  return 1;
-	}
-	
-	/* Acquire the hash table lock to guarantee that the linux
-	 * pte we fetch will not change
-	 */
-	spin_lock( &hash_table_lock );
-	
-	old_pte = *ptep;
-	
-	/* If the pte is not "present" (valid), send the problem
-	 * up to do_page_fault.
-	 */
-	if ( ! pte_present( old_pte ) ) {
-	  spin_unlock( &hash_table_lock );
-	  spin_unlock( &mm->page_table_lock );
-	  return 1;
-	}
-	
-	/* At this point we have found a pte (which was present).
-	 * The spinlocks prevent this status from changing
-	 * The hash_table_lock prevents the _PAGE_HASHPTE status
-	 * from changing (RPN, DIRTY and ACCESSED too)
-	 * The page_table_lock prevents the pte from being 
-	 * invalidated or modified
-	 */
-
-/* At this point, we have a pte (old_pte) which can be used to build or update
- * an HPTE.   There are 5 cases:
- *
- * 1. There is a valid (present) pte with no associated HPTE (this is 
- *	the most common case)
- * 2. There is a valid (present) pte with an associated HPTE.  The
- *	current values of the pp bits in the HPTE prevent access because the
- *	user doesn't have appropriate access rights.
- * 3. There is a valid (present) pte with an associated HPTE.  The
- *	current values of the pp bits in the HPTE prevent access because we are
- *	doing software DIRTY bit management and the page is currently not DIRTY. 
- * 4. This is a Kernel address (0xC---) for which there is no page directory.
- *	There is an HPTE for this page, but the pp bits prevent access.
- *      Since we always set up kernel pages with R/W access for the kernel
- *	this case only comes about for users trying to access the kernel.
- *	This case is always an error and is not dealt with further here.
- * 5. This is a Kernel address (0xC---) for which there is no page directory.
- *	There is no HPTE for this page.
-
- * Check the user's access rights to the page.  If access should be prevented
- * then send the problem up to do_page_fault.
- */
-
-	access |= _PAGE_PRESENT;
-	if ( 0 == ( access & ~(pte_val(old_pte)) ) ) {
-		/*
-		 * Check if pte might have an hpte, but we have
-		 * no slot information
-		 */
-		if ( pte_val(old_pte) & _PAGE_HPTENOIX ) {
-			unsigned long slot;	
-			pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
-			slot = ppc_md.hpte_find( vpn );
-			if ( slot != -1 ) {
-				if ( slot < 0 ) {
-					pte_val(old_pte) |= _PAGE_SECONDARY;
-					slot = -slot;
-				}
-				pte_val(old_pte) |= ((slot << 12) & _PAGE_GROUP_IX) | _PAGE_HASHPTE;
-				
-			}
-		}
-
-		/* User has appropriate access rights. */
-		new_pte = old_pte;
-		/* If the attempted access was a store */
-		if ( access & _PAGE_RW )
-			pte_val(new_pte) |= _PAGE_ACCESSED |
-				_PAGE_DIRTY;
-		else
-			pte_val(new_pte) |= _PAGE_ACCESSED;
 
-		/* Only cases 1, 3 and 5 still in play */
-
-		newpp = computeHptePP( pte_val(new_pte) );
-
-		/* Check if pte already has an hpte (case 3) */
-		if ( pte_val(old_pte) & _PAGE_HASHPTE ) {
-			/* There MIGHT be an HPTE for this pte */
-			unsigned long hash, slot, secondary;
-			/* Local copy of first doubleword of HPTE */
-			union {
-				unsigned long d;
-				Hpte_dword0   h;
-			} hpte_dw0;
-			hash = hpt_hash(vpn, 0);
-			secondary = (pte_val(old_pte) & _PAGE_SECONDARY) >> 15;
-			if ( secondary )
-				hash = ~hash;
-			slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-			slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
-			/* If there is an HPTE for this page it is indexed by slot */
-			hpte_dw0.d = ppc_md.hpte_getword0( slot );
-			if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&
-			     (hpte_dw0.h.v) && 
-			     (hpte_dw0.h.h == secondary ) ){
-				/* HPTE matches */
-				ppc_md.hpte_updatepp( slot, newpp, va );
-				if ( !pte_same( old_pte, new_pte ) )
-					*ptep = new_pte;
-			}
-			else {
-				/* HPTE is not for this pte */
-				pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
-			}
-		}
-		if ( !( pte_val(old_pte) & _PAGE_HASHPTE ) ) {
-			/* Cases 1 and 5 */
-			/* For these cases we need to create a new
-			 * HPTE and update the linux pte (for
-			 * case 1).  For case 5 there is no linux pte.
-			 *
-			 * Find an available HPTE slot
- 			 */
-			slot = ppc_md.hpte_selectslot( vpn );
-
-			/* Debug code */
-			if ( slot == 0x8000000000000000 ) {
-				unsigned long xold_pte = pte_val(old_pte);
-				unsigned long xnew_pte = pte_val(new_pte);
-				
-				udbg_printf("hash_page: ptep    = 0x%016lx\n", (unsigned long)ptep );
-				udbg_printf("hash_page: old_pte = 0x%016lx\n", xold_pte );
-				udbg_printf("hash_page: new_pte = 0x%016lx\n", xnew_pte );
-				udbg_printf("hash_page: ea      = 0x%016lx\n", ea );
-				udbg_printf("hash_page: va      = 0x%016lx\n", va );
-				udbg_printf("hash_page: access  = 0x%016lx\n", access );
-			
-				panic("hash_page: hpte already exists\n");
-			}
-
-			hash_ind = 0;
-			if ( slot < 0 ) {
-				slot = -slot;
-				hash_ind = 1;
-			}
-
-			/* Set the physical address */
-			prpn = pte_val(old_pte) >> PTE_SHIFT;
-			
-			if ( ptep ) {
-				/* Update the linux pte with the HPTE slot */
-				pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
-				pte_val(new_pte) |= hash_ind << 15;
-				pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
-				pte_val(new_pte) |= _PAGE_HASHPTE;
-				/* No need to use ldarx/stdcx here because all
-				 * who might be updating the pte will hold the page_table_lock
-				 * or the hash_table_lock (we hold both)
-				 */
-				*ptep = new_pte;
-			}
-
-			/* copy appropriate flags from linux pte */
-			hpteflags = (pte_val(new_pte) & 0x1f8) | newpp;
-
-			/* Create the HPTE */
-			ppc_md.hpte_create_valid( slot, vpn, prpn, hash_ind, ptep, hpteflags, 0 ); 
-
-		}
+	if (pgdir == NULL)
+		return 1;
 
-		/* Indicate success */
-		rc = 0;
-	}		
-	
-	spin_unlock( &hash_table_lock );
-	if (ptep)
-		spin_unlock( &mm->page_table_lock );
+	/*
+	 * Lock the Linux page table to prevent mmap and kswapd
+	 * from modifying entries while we search and update
+	 */
+	spin_lock(&mm->page_table_lock);
+	ptep = find_linux_pte(pgdir, ea);
+	ret = __hash_page(ea, access, vsid, ptep);
+	spin_unlock(&mm->page_table_lock);
 
-	return rc;
+	return ret;
 }
 
-void flush_hash_page( unsigned long context, unsigned long ea, pte_t pte )
+void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
+		     int local)
 {
-	unsigned long vsid, vpn, va, hash, secondary, slot, flags;
-	/* Local copy of first doubleword of HPTE */
-	union {
-		unsigned long d;
-		Hpte_dword0   h;
-	} hpte_dw0;
+	unsigned long vsid, vpn, va, hash, secondary, slot;
 
-	if ( (ea >= USER_START ) && ( ea <= USER_END ) )
-		vsid = get_vsid( context, ea );
+	/* XXX fix for large ptes */
+	unsigned long large = 0;
+
+	if ((ea >= USER_START) && (ea <= USER_END))
+		vsid = get_vsid(context, ea);
 	else
-		vsid = get_kernel_vsid( ea );
+		vsid = get_kernel_vsid(ea);
+
 	va = (vsid << 28) | (ea & 0x0fffffff);
-	vpn = va >> PAGE_SHIFT;
-	hash = hpt_hash(vpn, 0);
+	if (large)
+		vpn = va >> LARGE_PAGE_SHIFT;
+	else
+		vpn = va >> PAGE_SHIFT;
+	hash = hpt_hash(vpn, large);
 	secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;
-	if ( secondary )
+	if (secondary)
 		hash = ~hash;
 	slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
 	slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;
-	/* If there is an HPTE for this page it is indexed by slot */
 
-	spin_lock_irqsave( &hash_table_lock, flags);
-	hpte_dw0.d = ppc_md.hpte_getword0( slot );
-	if ( (hpte_dw0.h.avpn == (vpn >> 11) ) &&
-	     (hpte_dw0.h.v) && 
-	     (hpte_dw0.h.h == secondary ) ){
-		/* HPTE matches */
-		ppc_md.hpte_invalidate( slot );	
-	}
-	else {
-		unsigned k;
-		/* Temporarily lets check for the hpte in all possible slots */
-		for ( secondary = 0; secondary < 2; ++secondary ) {
-			hash = hpt_hash(vpn, 0);
-			if ( secondary )
-				hash = ~hash;
-			slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-			for ( k=0; k<8; ++k ) {
-				hpte_dw0.d = ppc_md.hpte_getword0( slot+k );
-				if ( ( hpte_dw0.h.avpn == (vpn >> 11) ) &&
-				     ( hpte_dw0.h.v ) &&
-				     ( hpte_dw0.h.h == secondary ) ) {
-					while (1) ;
-				}
-			}
-		}
-		
-	}
-	spin_unlock_irqrestore( &hash_table_lock, flags );
+	ppc_md.hpte_invalidate(slot, va, large, local);
 }
 
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-		   void *buffer, size_t *lenp)
+void flush_hash_range(unsigned long context, unsigned long number, int local)
 {
-	int vleft, first=1, len, left, val;
-#define TMPBUFLEN 256
-	char buf[TMPBUFLEN], *p;
-	static const char *sizestrings[4] = {
-		"2MB", "256KB", "512KB", "1MB"
-	};
-	static const char *clockstrings[8] = {
-		"clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
-		"+2 clock", "+2.5 clock", "+3 clock", "reserved(7)"
-	};
-	static const char *typestrings[4] = {
-		"flow-through burst SRAM", "reserved SRAM",
-		"pipelined burst SRAM", "pipelined late-write SRAM"
-	};
-	static const char *holdstrings[4] = {
-		"0.5", "1.0", "(reserved2)", "(reserved3)"
-	};
-
-	if ( ((_get_PVR() >> 16) != 8) && ((_get_PVR() >> 16) != 12))
-		return -EFAULT;
-	
-	if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {
-		*lenp = 0;
-		return 0;
-	}
-	
-	vleft = table->maxlen / sizeof(int);
-	left = *lenp;
-	
-	for (; left /*&& vleft--*/; first=0) {
-		if (write) {
-			while (left) {
-				char c;
-				if(get_user(c,(char *) buffer))
-					return -EFAULT;
-				if (!isspace(c))
-					break;
-				left--;
-				((char *) buffer)++;
-			}
-			if (!left)
-				break;
-			len = left;
-			if (len > TMPBUFLEN-1)
-				len = TMPBUFLEN-1;
-			if(copy_from_user(buf, buffer, len))
-				return -EFAULT;
-			buf[len] = 0;
-			p = buf;
-			if (*p < '0' || *p > '9')
-				break;
-			val = simple_strtoul(p, &p, 0);
-			len = p-buf;
-			if ((len < left) && *p && !isspace(*p))
-				break;
-			buffer += len;
-			left -= len;
-#if 0
-			/* DRENG need a def */
-			_set_L2CR(0);
-			_set_L2CR(val);
-			while ( _get_L2CR() & 0x1 )
-				/* wait for invalidate to finish */;
-#endif
-			  
-		} else {
-			p = buf;
-			if (!first)
-				*p++ = '\t';
-#if 0
-			/* DRENG need a def */
-			val = _get_L2CR();
-#endif
-			p += sprintf(p, "0x%08x: ", val);
-			p += sprintf(p, " %s", (val >> 31) & 1 ? "enabled" :
-				     "disabled");
-			p += sprintf(p, ", %sparity", (val>>30)&1 ? "" : "no ");
-			p += sprintf(p, ", %s", sizestrings[(val >> 28) & 3]);
-			p += sprintf(p, ", %s", clockstrings[(val >> 25) & 7]);
-			p += sprintf(p, ", %s", typestrings[(val >> 23) & 2]);
-			p += sprintf(p, "%s", (val>>22)&1 ? ", data only" : "");
-			p += sprintf(p, "%s", (val>>20)&1 ? ", ZZ enabled": "");
-			p += sprintf(p, ", %s", (val>>19)&1 ? "write-through" :
-				     "copy-back");
-			p += sprintf(p, "%s", (val>>18)&1 ? ", testing" : "");
-			p += sprintf(p, ", %sns hold",holdstrings[(val>>16)&3]);
-			p += sprintf(p, "%s", (val>>15)&1 ? ", DLL slow" : "");
-			p += sprintf(p, "%s", (val>>14)&1 ? ", diff clock" :"");
-			p += sprintf(p, "%s", (val>>13)&1 ? ", DLL bypass" :"");
-			
-			p += sprintf(p,"\n");
-			
-			len = strlen(buf);
-			if (len > left)
-				len = left;
-			if(copy_to_user(buffer, buf, len))
-				return -EFAULT;
-			left -= len;
-			buffer += len;
-			break;
-		}
-	}
-
-	if (!write && !first && left) {
-		if(put_user('\n', (char *) buffer))
-			return -EFAULT;
-		left--, buffer++;
-	}
-	if (write) {
-		p = (char *) buffer;
-		while (left) {
-			char c;
-			if(get_user(c, p++))
-				return -EFAULT;
-			if (!isspace(c))
-				break;
-			left--;
+	if (ppc_md.flush_hash_range) {
+		ppc_md.flush_hash_range(context, number, local);
+	} else {
+		int i;
+		struct tlb_batch_data *ptes =
+			&tlb_batch_array[smp_processor_id()][0];
+
+		for (i = 0; i < number; i++) {
+			flush_hash_page(context, ptes->addr, ptes->pte, local);
+			ptes++;
 		}
 	}
-	if (write && first)
-		return -EINVAL;
-	*lenp -= left;
-	filp->f_pos += *lenp;
-	return 0;
 }
-
diff -Nru a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
--- a/arch/ppc64/kernel/iSeries_irq.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/iSeries_irq.c	Sun Apr 14 12:16:59 2002
@@ -106,7 +106,7 @@
 {
 	u8 idsel = (deviceId >> 4);
 	u8 function = deviceId & 0x0F;
-	int irq = ((((busNumber-1)*16 + (idsel-1)*8 + function)*9/8) % 254) + 1;
+	int irq = ((((busNumber-1)*16 + (idsel-1)*8 + function)*9/8) % 253) + 2;
 	return irq;
 }
 
diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
--- a/arch/ppc64/kernel/iSeries_pci.c	Sun Apr 14 12:17:00 2002
+++ b/arch/ppc64/kernel/iSeries_pci.c	Sun Apr 14 12:17:00 2002
@@ -21,6 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h> 
 #include <linux/string.h>
@@ -36,12 +37,12 @@
 #include <asm/ppcdebug.h>
 #include <asm/Naca.h>
 #include <asm/flight_recorder.h>
+#include <asm/pci_dma.h>
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvCallSm.h>
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/LparData.h>
-#include <asm/iSeries/iSeries_dma.h>
 #include <asm/iSeries/iSeries_irq.h>
 #include <asm/iSeries/iSeries_pci.h>
 #include <asm/iSeries/mf.h>
@@ -92,12 +93,12 @@
 
 void  iSeries_Scan_PHBs_Slots(struct pci_controller* Phb);
 void  iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
-int   iSeries_Scan_Bridge_Slot(HvBusNumber Bus, HvSubBusNumber SubBus, int MaxAgents);
+int   iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* Info);
 void  list_device_nodes(void);
 
 struct pci_dev;
 
-LIST_HEAD(Global_Device_List);
+extern struct list_head iSeries_Global_Device_List;
 
 int DeviceCount = 0;
 
@@ -138,6 +139,9 @@
 		    ISERIES_SUBBUS(DevNode),
 		    DevNode->AgentId,
 		    DevNode->DevFn);
+	udbg_printf("     - LSlot     = 0x%02X\n",DevNode->LogicalSlot);
+	udbg_printf("     - TceTable  = 0x%p\n  ",DevNode->DevTceTable);
+
 	udbg_printf("     - DSA       = 0x%04X\n",ISERIES_DSA(DevNode)>>32 );
 
 	udbg_printf("                 = Irq:0x%02X Vendor:0x%04X  Flags:0x%02X\n",
@@ -145,14 +149,16 @@
 		    DevNode->Vendor,
 		    DevNode->Flags );
 	udbg_printf("     - Location  = %s\n",DevNode->CardLocation);
+
+
 }
 /**********************************************************************************
  * Walk down the device node chain 
  **********************************************************************************/
 void  list_device_nodes(void)
 {
-	struct list_head* Device_Node_Ptr = Global_Device_List.next;
-	while(Device_Node_Ptr != &Global_Device_List) {
+	struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next;
+	while(Device_Node_Ptr != &iSeries_Global_Device_List) {
 		dumpDevice_Node( (struct iSeries_Device_Node*)Device_Node_Ptr );
 		Device_Node_Ptr = Device_Node_Ptr->next;
 	}
@@ -167,13 +173,13 @@
 {
 	struct iSeries_Device_Node*  DeviceNode;
 
-	PPCDBG(PPCDBG_BUSWALK,"- "__FUNCTION__" 0x%02X.%02X.%02X Function: %02X\n",Bus,SubBus,AgentId, Function);
+	PPCDBG(PPCDBG_BUSWALK,"-build_device_node 0x%02X.%02X.%02X Function: %02X\n",Bus,SubBus,AgentId, Function);
 
 	DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
 	if(DeviceNode == NULL) return NULL;
 
 	memset(DeviceNode,0,sizeof(struct iSeries_Device_Node) );
-	list_add_tail(&DeviceNode->Device_List,&Global_Device_List);
+	list_add_tail(&DeviceNode->Device_List,&iSeries_Global_Device_List);
 	/*DeviceNode->DsaAddr      = ((u64)Bus<<48)+((u64)SubBus<<40)+((u64)0x10<<32); */
 	ISERIES_BUS(DeviceNode)       = Bus;
 	ISERIES_SUBBUS(DeviceNode)    = SubBus;
@@ -224,7 +230,7 @@
 	struct      pci_controller* phb;
 	HvBusNumber BusNumber;
 
-	PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry\n");
+	PPCDBG(PPCDBG_BUSWALK,"find_and_init_phbs Entry\n");
 
 	/* Check all possible buses. */
 	for (BusNumber = 0; BusNumber < 256; BusNumber++) {
@@ -239,7 +245,7 @@
 			phb->pci_mem_offset = phb->local_number = BusNumber;
 			phb->first_busno  = BusNumber;
 			phb->last_busno   = BusNumber;
-			phb->ops = &iSeries_pci_ops;
+			phb->ops          = &iSeries_pci_ops;
 
 			PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",phb,BusNumber);
 			PCIFR("Create iSeries PHB controller: %04X",BusNumber);
@@ -276,26 +282,15 @@
  ***********************************************************************/
 void iSeries_pcibios_init(void)
 {
-	struct pci_controller *phb;
-	PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry.\n"); 
+	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Entry.\n"); 
 
 	iSeries_IoMmTable_Initialize();
 
 	find_and_init_phbs();
 
-	/* Create the TCE Tables */
-	phb = hose_head;
-	while(phb != NULL) {
-		create_pci_bus_tce_table(phb->local_number);
-		PCIFR("Bus 0x%04X TCE Table %p",phb->local_number,tceTables[phb->local_number] );
-		phb = phb->next;
-	}
-
-
 	pci_assign_all_busses = 0;
-	PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Exit.\n"); 
+	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Exit.\n"); 
 }
-
 /***********************************************************************
  * iSeries_pcibios_fixup(void)  
  ***********************************************************************/
@@ -306,11 +301,12 @@
 	char   Buffer[256];
     	int    DeviceCount = 0;
 
-	PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" Entry.\n"); 
-
+	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup Entry.\n"); 
 	/******************************************************/
 	/* Fix up at the device node and pci_dev relationship */
 	/******************************************************/
+	mf_displaySrc(0xC9000100);
+
 	pci_for_each_dev(PciDev) {
 		DeviceNode = find_Device_Node(PciDev);
 		if(DeviceNode != NULL) {
@@ -327,6 +323,7 @@
 			iSeries_Device_Information(PciDev,Buffer, sizeof(Buffer) );
 			printk("%d. %s\n",DeviceCount,Buffer);
 
+			create_pci_bus_tce_table((unsigned long)DeviceNode);
 		} else {
 			printk("PCI: Device Tree not found for 0x%016lX\n",(unsigned long)PciDev);
 		}
@@ -335,37 +332,18 @@
 
 	iSeries_activate_IRQs();
 
-	// This is test code. 
-	//mf_displaySrc(0xC9000100);
-	//Pci_IoTest();
-	// Pci_CfgIoTest(); 
-	// mf_displaySrc(0xC9000500);
-	// Pci_MMIoTest(); 
-	//mf_displaySrc(0xC9000999);
-}	
+	mf_displaySrc(0xC9000200);
+}
+
 /***********************************************************************
  * iSeries_pcibios_fixup_bus(int Bus)
  *
  ***********************************************************************/
 void iSeries_pcibios_fixup_bus(struct pci_bus* PciBus)
 {
-	PPCDBG(PPCDBG_BUSWALK,__FUNCTION__"(0x%04X) Entry.\n",PciBus->number); 
+	PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",PciBus->number); 
 
 }
-/***********************************************************************
- * find_floppy(void) 
- *	
- * Finds the default floppy device, if the system has one, and returns 
- * the pci_dev for the isa bridge for the floppy device.  
- *
- * Note: On iSeries there will only be a virtual diskette. 
- ***********************************************************************/
-struct pci_dev*
-find_floppy(void)
-{
-	PPCDBG(PPCDBG_BUSWALK,"- Find Floppy pci_dev.. None on iSeries.\n");
-	return NULL;
-}
 
 
 /***********************************************************************
@@ -374,7 +352,7 @@
  ***********************************************************************/
 void fixup_resources(struct pci_dev *PciDev)
 {
-	PPCDBG(PPCDBG_BUSWALK,__FUNCTION__" PciDev %p\n",PciDev);
+	PPCDBG(PPCDBG_BUSWALK,"fixup_resources PciDev %p\n",PciDev);
 }   
 
 
@@ -409,7 +387,6 @@
 	kfree(DevInfo);
 }
 
-
 /********************************************************************************
 * 
 *********************************************************************************/
@@ -432,18 +409,26 @@
  		if (HvRc == 0) {
   			/*  Connect EADs: 0x18.00.12 = 0x00 */
 			PPCDBG(PPCDBG_BUSWALK,"PCI:Connect EADs: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId);
-			PCIFR(                "Connect EADs: 0x%02X.%02X.%02X",  Bus, SubBus, AgentId);
+			PCIFR(                    "Connect EADs: 0x%02X.%02X.%02X",  Bus, SubBus, AgentId);
 	    		HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId, 
 			                                REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo));
 	 		if (HvRc == 0) {
-				PPCDBG(PPCDBG_BUSWALK,"PCI: BridgeInfo, Type: 0x%02X, SubBus 0x%02X, MaxAgents 0x%02X\n",
-				                        BridgeInfo->busUnitInfo.deviceType,
-				                         BridgeInfo->subBusNumber,
-				                          BridgeInfo->maxAgents);
+				PPCDBG(PPCDBG_BUSWALK,"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
+				       BridgeInfo->busUnitInfo.deviceType,
+				       BridgeInfo->subBusNumber,
+				       BridgeInfo->maxAgents,
+				       BridgeInfo->maxSubBusNumber,
+				       BridgeInfo->logicalSlotNumber);
+				PCIFR(                     "BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X",
+				       BridgeInfo->busUnitInfo.deviceType,
+				       BridgeInfo->subBusNumber,
+				       BridgeInfo->maxAgents,
+				       BridgeInfo->maxSubBusNumber,
+				       BridgeInfo->logicalSlotNumber);
 
 				if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice)  {
 					/* Scan_Bridge_Slot...: 0x18.00.12 */
-					iSeries_Scan_Bridge_Slot(Bus,BridgeInfo->subBusNumber,BridgeInfo->maxAgents);
+					iSeries_Scan_Bridge_Slot(Bus,BridgeInfo);
 				}
 				else printk("PCI: Invalid Bridge Configuration(0x%02X)",BridgeInfo->busUnitInfo.deviceType);
 			}
@@ -458,17 +443,18 @@
 * This assumes that the node slot is always on the primary bus!
 *
 *********************************************************************************/
-int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, HvSubBusNumber SubBus, int MaxAgents)
+int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* BridgeInfo)
 {
-     struct iSeries_Device_Node* DeviceNode;
-	u16       VendorId   = 0;
-	int       HvRc       = 0;
-	int       Irq        = 0;
-	int       IdSel      = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
-	int       Function   = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
-	HvAgentId AgentId    = ISERIES_PCI_AGENTID(IdSel, Function);
-	HvAgentId EADsIdSel  = ISERIES_PCI_AGENTID(IdSel, Function);
-	int       FirstSlotId= 0; 	
+	struct iSeries_Device_Node* DeviceNode;
+	HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
+	u16       VendorId    = 0;
+	int       HvRc        = 0;
+	int       Irq         = 0;
+	int       IdSel       = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
+	int       Function    = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
+	HvAgentId AgentId     = ISERIES_PCI_AGENTID(IdSel, Function);
+	HvAgentId EADsIdSel   = ISERIES_PCI_AGENTID(IdSel, Function);
+	int       FirstSlotId = 0; 	
 
 	/**********************************************************/
 	/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3)                */
@@ -480,7 +466,7 @@
 	/****************************************************************************
 	 * Connect all functions of any device found.  
 	 ****************************************************************************/
-  	for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) {
+  	for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
     		for (Function = 0; Function < 8; ++Function) {
 			AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
 			HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq);
@@ -494,10 +480,13 @@
 					PPCDBG(PPCDBG_BUSWALK,"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n",
 					                                       Bus, SubBus, AgentId, VendorId);
 					++DeviceCount;
-					PCIFR("Device(%4d): 0x%02X.%02X.%02X",DeviceCount,Bus, SubBus, AgentId);
 					DeviceNode = build_device_node(Bus, SubBus, EADsIdSel, Function);
-					DeviceNode->Vendor = VendorId;
-					DeviceNode->Irq    = Irq;
+					DeviceNode->Vendor      = VendorId;
+					DeviceNode->Irq         = Irq;
+					DeviceNode->LogicalSlot = BridgeInfo->logicalSlotNumber;
+					PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X",
+					      DeviceCount,Bus, SubBus, AgentId,
+					      DeviceNode->LogicalSlot,DeviceNode->Vendor);
 
 					/***********************************************************
 					 * On the first device/function, assign irq to slot
@@ -557,11 +546,11 @@
  **********************************************************************************/
 struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev)
 {
-	struct list_head* Device_Node_Ptr = Global_Device_List.next;
+	struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next;
 	int Bus   = PciDev->bus->number;
 	int DevFn = PciDev->devfn;
 	
-	while(Device_Node_Ptr != &Global_Device_List) { 
+	while(Device_Node_Ptr != &iSeries_Global_Device_List) { 
 		struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)Device_Node_Ptr;
 		if(Bus == ISERIES_BUS(DevNode) && DevFn == DevNode->DevFn) {
 			return DevNode;
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/kernel/iSeries_setup.c	Sun Apr 14 12:16:56 2002
@@ -26,6 +26,7 @@
 #include <linux/string.h>
 #include <linux/bootmem.h>
 #include <linux/blk.h>
+#include <linux/seq_file.h>
 
 #include <asm/processor.h>
 #include <asm/machdep.h>
@@ -587,6 +588,7 @@
 
 	lmb_init();
 	lmb_add( 0, naca->physicalMemorySize );
+	lmb_analyze();	/* ?? */
 	lmb_reserve( 0, __pa(klimit));
 
 	/* 
@@ -603,8 +605,10 @@
 static void __init setup_iSeries_cache_sizes(void)
 {
 	unsigned i,n;
-	naca->iCacheL1LineSize = xIoHriProcessorVpd[0].xInstCacheOperandSize;
-	naca->dCacheL1LineSize = xIoHriProcessorVpd[0].xDataCacheOperandSize;
+	unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
+
+	naca->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
+	naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
 	naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize;
 	naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize;
 	i = naca->iCacheL1LineSize;
@@ -652,6 +656,9 @@
 }
 #endif /* CONFIG_PPC_ISERIES */
 
+extern unsigned long ppc_proc_freq;
+extern unsigned long ppc_tb_freq;
+
 /*
  * Document me.
  */
@@ -659,7 +666,8 @@
 iSeries_setup_arch(void)
 {
 	void *	eventStack;
-	
+	unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex;
+
 	/* Setup the Lp Event Queue */
 
 	/* Allocate a page for the Event Stack
@@ -685,15 +693,19 @@
 	xItLpQueue.xIndex = 0;
 	
 	/* Compute processor frequency */
-	procFreqHz = (((1UL<<34) * 1000000) / xIoHriProcessorVpd[0].xProcFreq );
+	procFreqHz = (((1UL<<34) * 1000000) / xIoHriProcessorVpd[procIx].xProcFreq );
 	procFreqMhz = procFreqHz / 1000000;
 	procFreqMhzHundreths = (procFreqHz/10000) - (procFreqMhz*100);
 
+	ppc_proc_freq = procFreqHz;
+
 	/* Compute time base frequency */
-	tbFreqHz = (((1UL<<32) * 1000000) / xIoHriProcessorVpd[0].xTimeBaseFreq );
+	tbFreqHz = (((1UL<<32) * 1000000) / xIoHriProcessorVpd[procIx].xTimeBaseFreq );
 	tbFreqMhz = tbFreqHz / 1000000;
 	tbFreqMhzHundreths = (tbFreqHz/10000) - (tbFreqMhz*100);
 
+	ppc_tb_freq = tbFreqHz;
+
 	printk("Max  logical processors = %d\n", 
 			itVpdAreas.xSlicMaxLogicalProcs );
 	printk("Max physical processors = %d\n",
@@ -705,12 +717,12 @@
 			tbFreqMhz,
 			tbFreqMhzHundreths );
 	printk("Processor version = %x\n",
-			xIoHriProcessorVpd[0].xPVR );
+			xIoHriProcessorVpd[procIx].xPVR );
 
 }
 
 /*
- * int iSeries_setup_residual()
+ * int as400_setup_residual()
  *
  * Description:
  *   This routine pretty-prints CPU information gathered from the VPD    
@@ -726,20 +738,25 @@
  *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
  *   on error.
  */
-void
-iSeries_setup_residual(struct seq_file *m, unsigned long cpu_id)
+void iSeries_setup_residual(struct seq_file *m)
 {
-	seq_printf(m, "clock\t\t: %lu.%02luMhz\n", procFreqMhz,
-			procFreqMhzHundreths);
-	seq_printf(m, "time base\t: %lu.%02luMHz\n", tbFreqMhz,
-			tbFreqMhzHundreths);
-	seq_printf(m, "i-cache\t\t: %d\n", naca->iCacheL1LineSize);
-	seq_printf(m, "d-cache\t\t: %d\n", naca->dCacheL1LineSize);
+	
+	seq_printf(m,"clock\t\t: %lu.%02luMhz\n",
+		procFreqMhz, procFreqMhzHundreths );
+	seq_printf(m,"time base\t: %lu.%02luMHz\n",
+		tbFreqMhz, tbFreqMhzHundreths );
+	seq_printf(m,"i-cache\t\t: %d\n",
+		naca->iCacheL1LineSize);
+	seq_printf(m,"d-cache\t\t: %d\n",
+		naca->dCacheL1LineSize);
+
 }
 
 void iSeries_get_cpuinfo(struct seq_file *m)
 {
-	seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
+
+	seq_printf(m,"machine\t\t: 64-bit iSeries Logical Partition\n");
+
 }
 
 /*
@@ -805,29 +822,29 @@
 void __init
 iSeries_calibrate_decr(void)
 {
-	unsigned long	freq;
 	unsigned long	cyclesPerUsec;
-	unsigned long	tbf;
 
 	struct div_result divres;
 	
 	/* Compute decrementer (and TB) frequency 
 	 * in cycles/sec 
 	 */
-	
-	tbf = xIoHriProcessorVpd[0].xTimeBaseFreq;
-	
-	freq = 0x0100000000;
-	freq *= 1000000;		/* 2^32 * 10^6 */
-	freq = freq / tbf;		/* cycles / sec */
-	cyclesPerUsec = freq / 1000000;	/* cycles / usec */
+
+	cyclesPerUsec = ppc_tb_freq / 1000000;	/* cycles / usec */
 
 	/* Set the amount to refresh the decrementer by.  This
 	 * is the number of decrementer ticks it takes for 
 	 * 1/HZ seconds.
 	 */
 
-	tb_ticks_per_jiffy = freq / HZ;
+	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+
+#if 0
+	/* TEST CODE FOR ADJTIME */
+	tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
+	/* END OF TEST CODE */
+#endif
+
 	/*
 	 * tb_ticks_per_sec = freq; would give better accuracy
 	 * but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
@@ -836,7 +853,7 @@
 	 */
 	tb_ticks_per_sec   = tb_ticks_per_jiffy * HZ;
 	tb_ticks_per_usec = cyclesPerUsec;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
 	div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres );
 	tb_to_xs = divres.result_low;
 	setup_default_decr();
diff -Nru a/arch/ppc64/kernel/iSeries_setup.h b/arch/ppc64/kernel/iSeries_setup.h
--- a/arch/ppc64/kernel/iSeries_setup.h	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/kernel/iSeries_setup.h	Sun Apr 14 12:16:56 2002
@@ -19,8 +19,6 @@
 #ifndef	__ISERIES_SETUP_H__
 #define	__ISERIES_SETUP_H__
 
-#include <linux/seq_file.h>
-
 extern void		 iSeries_init_early(void);
 extern void		 iSeries_init(unsigned long r3,
 			            unsigned long ird_start,
@@ -28,8 +26,7 @@
 				    unsigned long cline_start,
 				    unsigned long cline_end);
 extern void		 iSeries_setup_arch(void);
-extern void		 iSeries_setup_residual(struct seq_file *m,
-						unsigned long cpu_id);
+extern void		 iSeries_setup_residual(struct seq_file *m);
 extern void		 iSeries_get_cpuinfo(struct seq_file *m);
 extern void		 iSeries_init_IRQ(void);
 extern int		 iSeries_get_irq(struct pt_regs *regs);
diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
--- a/arch/ppc64/kernel/idle.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/idle.c	Sun Apr 14 12:16:59 2002
@@ -1,14 +1,12 @@
 /*
- * Idle daemon for PowerPC.  Idle daemon will handle any action
- * that needs to be taken when the system becomes idle.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu)
+ * idle.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.
  */
+
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -28,8 +26,10 @@
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/cache.h>
-
 #include <asm/time.h>
+
+#ifdef CONFIG_PPC_ISERIES
+
 #include <asm/iSeries/LparData.h>
 #include <asm/iSeries/HvCall.h>
 #include <asm/iSeries/ItLpQueue.h>
@@ -37,105 +37,109 @@
 unsigned long maxYieldTime = 0;
 unsigned long minYieldTime = 0xffffffffffffffffUL;
 
-#ifdef CONFIG_PPC_ISERIES
 static void yield_shared_processor(void)
 {
-	struct Paca *paca;
 	unsigned long tb;
 	unsigned long yieldTime;
 
-	paca = (struct Paca *)mfspr(SPRG3);
-	HvCall_setEnabledInterrupts( HvCall_MaskIPI |
-				     HvCall_MaskLpEvent |
-				     HvCall_MaskLpProd |
-				     HvCall_MaskTimeout );
+	HvCall_setEnabledInterrupts(HvCall_MaskIPI |
+				    HvCall_MaskLpEvent |
+				    HvCall_MaskLpProd |
+				    HvCall_MaskTimeout);
 
 	tb = get_tb();
 	/* Compute future tb value when yield should expire */
-	HvCall_yieldProcessor( HvCall_YieldTimed, tb+tb_ticks_per_jiffy );
+	HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
 
 	yieldTime = get_tb() - tb;
-	if ( yieldTime > maxYieldTime )
+	if (yieldTime > maxYieldTime)
 		maxYieldTime = yieldTime;
 
-	if ( yieldTime < minYieldTime )
+	if (yieldTime < minYieldTime)
 		minYieldTime = yieldTime;
 	
-	/* The decrementer stops during the yield.  Force a fake decrementer
+	/*
+	 * The decrementer stops during the yield.  Force a fake decrementer
 	 * here and let the timer_interrupt code sort out the actual time.
 	 */
-	paca->xLpPaca.xIntDword.xFields.xDecrInt = 1;
+	get_paca()->xLpPaca.xIntDword.xFields.xDecrInt = 1;
 	process_iSeries_events();
 }
-#endif /* CONFIG_PPC_ISERIES */
 
-int idled(void)
+int cpu_idle(void)
 {
 	struct Paca *paca;
 	long oldval;
-#ifdef CONFIG_PPC_ISERIES
 	unsigned long CTRL;
-#endif
 
-	/* endless loop with no priority at all */
-#ifdef CONFIG_PPC_ISERIES
 	/* ensure iSeries run light will be out when idle */
 	current->thread.flags &= ~PPC_FLAG_RUN_LIGHT;
 	CTRL = mfspr(CTRLF);
 	CTRL &= ~RUNLATCH;
 	mtspr(CTRLT, CTRL);
-#endif
-
-	printk("cpu %d hits idle loop\n", smp_processor_id());
-
-	paca = (struct Paca *)mfspr(SPRG3);
 
-	while(1) {
-		if (need_resched()) {
-			schedule();
-			check_pgt_cache();
-		}
-	}
+	paca = get_paca();
 
-	for (;;) {
-#ifdef CONFIG_PPC_ISERIES
-		if ( paca->xLpPaca.xSharedProc ) {
-			if ( ItLpQueue_isLpIntPending( paca->lpQueuePtr ) )
+	while (1) {
+		if (paca->xLpPaca.xSharedProc) {
+			if (ItLpQueue_isLpIntPending(paca->lpQueuePtr))
 				process_iSeries_events();
 			if (!need_resched())
 				yield_shared_processor();
-		}
-		else 
-#endif
-		{
-			if (!need_resched()) {
+		} else {
+			oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+
+			if (!oldval) {
 				set_thread_flag(TIF_POLLING_NRFLAG);
-				while (!test_thread_flag(TIF_NEED_RESCHED)) {
-#ifdef CONFIG_PPC_ISERIES
+
+				while (!need_resched()) {
 					HMT_medium();
 					if (ItLpQueue_isLpIntPending(paca->lpQueuePtr))
 						process_iSeries_events();
-#endif
 					HMT_low();
 				}
+
+				HMT_medium();
 				clear_thread_flag(TIF_POLLING_NRFLAG);
+			} else {
+				set_need_resched();
 			}
 		}
-		HMT_medium();
-		if (need_resched()) {
+
+		if (need_resched())
 			schedule();
-			check_pgt_cache();
-		}
 	}
+
 	return 0;
 }
 
-/*
- * SMP entry into the idle task - calls the same thing as the
- * non-smp versions. -- Cort
- */
+#else /* CONFIG_PPC_ISERIES */
+
 int cpu_idle(void)
 {
-	idled();
-	return 0; 
+	long oldval;
+
+	while (1) {
+		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+
+		if (!oldval) {
+			set_thread_flag(TIF_POLLING_NRFLAG);
+
+			while (!need_resched()) {
+				barrier();
+				HMT_low();
+			}
+
+			HMT_medium();
+			clear_thread_flag(TIF_POLLING_NRFLAG);
+		} else {
+			set_need_resched();
+		}
+
+		schedule();
+	}
+
+	return 0;
 }
+
+#endif /* CONFIG_PPC_ISERIES */
diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
--- a/arch/ppc64/kernel/ioctl32.c	Sun Apr 14 12:17:00 2002
+++ b/arch/ppc64/kernel/ioctl32.c	Sun Apr 14 12:17:00 2002
@@ -3736,8 +3736,6 @@
 COMPATIBLE_IOCTL(BLKROGET),
 COMPATIBLE_IOCTL(BLKRRPART),
 COMPATIBLE_IOCTL(BLKFLSBUF),
-COMPATIBLE_IOCTL(BLKRASET),
-COMPATIBLE_IOCTL(BLKFRASET),
 COMPATIBLE_IOCTL(BLKSECTSET),
 COMPATIBLE_IOCTL(BLKSSZGET),
 COMPATIBLE_IOCTL(BLKBSZGET),
@@ -4310,10 +4308,8 @@
 HANDLE_IOCTL(SIOCRTMSG, ret_einval),
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp),
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo),
-HANDLE_IOCTL(BLKRAGET, w_long),
 HANDLE_IOCTL(BLKGETSIZE, w_long),
 HANDLE_IOCTL(0x1260, broken_blkgetsize),
-HANDLE_IOCTL(BLKFRAGET, w_long),
 HANDLE_IOCTL(BLKSECTGET, w_long),
 HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans),
 HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans),
diff -Nru a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
--- a/arch/ppc64/kernel/lmb.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/lmb.c	Sun Apr 14 12:16:59 2002
@@ -28,8 +28,8 @@
 
 struct lmb lmb = {
 	0,
-	{0,0,0,{{0,0,0}}},
-	{0,0,0,{{0,0,0}}}
+	{0,0,0,0,{{0,0,0}}},
+	{0,0,0,0,{{0,0,0}}}
 };
 
 
@@ -91,24 +91,54 @@
 void
 lmb_analyze(void)
 {
-	unsigned long i, physbase = 0;
-	unsigned long total_size = 0;
+	unsigned long i;
+	unsigned long mem_size = 0;
+	unsigned long io_size = 0;
 	unsigned long size_mask = 0;
 	unsigned long offset = reloc_offset();
 	struct lmb *_lmb = PTRRELOC(&lmb);
+#ifdef CONFIG_MSCHUNKS
+	unsigned long physbase = 0;
+#endif
 
 	for (i=0; i < _lmb->memory.cnt ;i++) {
-		unsigned long lmb_size = _lmb->memory.region[i].size;
+		unsigned long lmb_type = _lmb->memory.region[i].type;
+		unsigned long lmb_size;
+
+		if ( lmb_type != LMB_MEMORY_AREA )
+			continue;
+
+		lmb_size = _lmb->memory.region[i].size;
+
 #ifdef CONFIG_MSCHUNKS
 		_lmb->memory.region[i].physbase = physbase;
-		physbase   += lmb_size;
+		physbase += lmb_size;
 #else
 		_lmb->memory.region[i].physbase = _lmb->memory.region[i].base;
 #endif
-		total_size += lmb_size;
-		size_mask  |= lmb_size;
+		mem_size += lmb_size;
+		size_mask |= lmb_size;
+	}
+
+#ifdef CONFIG_MSCHUNKS
+	for (i=0; i < _lmb->memory.cnt ;i++) {
+		unsigned long lmb_type = _lmb->memory.region[i].type;
+		unsigned long lmb_size;
+
+		if ( lmb_type != LMB_IO_AREA )
+			continue;
+
+		lmb_size = _lmb->memory.region[i].size;
+
+		_lmb->memory.region[i].physbase = physbase;
+		physbase += lmb_size;
+		io_size += lmb_size;
+		size_mask |= lmb_size;
 	}
-	_lmb->memory.size = total_size;
+#endif /* CONFIG_MSCHUNKS */
+
+	_lmb->memory.size = mem_size;
+	_lmb->memory.iosize = io_size;
 	_lmb->memory.lcd_size = (1UL << cnt_trailing_zeros(size_mask));
 }
 
@@ -124,6 +154,7 @@
 
 }
 
+#ifdef CONFIG_MSCHUNKS
 /* This routine called with relocation disabled. */
 long
 lmb_add_io(unsigned long base, unsigned long size)
@@ -135,6 +166,7 @@
 	return lmb_add_region(_rgn, base, size, LMB_IO_AREA);
 
 }
+#endif /* CONFIG_MSCHUNKS */
 
 long
 lmb_reserve(unsigned long base, unsigned long size)
@@ -268,12 +300,16 @@
 {
 	unsigned long offset = reloc_offset();
 	struct lmb *_lmb = PTRRELOC(&lmb);
+#ifdef CONFIG_MSCHUNKS
+	return _lmb->memory.size;
+#else
 	struct lmb_region *_mem = &(_lmb->memory);
 	unsigned long idx = _mem->cnt-1;
 	unsigned long lastbase = _mem->region[idx].physbase;
 	unsigned long lastsize = _mem->region[idx].size;
-
+	
 	return (lastbase + lastsize);
+#endif /* CONFIG_MSCHUNKS */
 }
 
 unsigned long
@@ -282,22 +318,26 @@
 	unsigned long offset = reloc_offset();
 	struct lmb *_lmb = PTRRELOC(&lmb);
 	struct lmb_region *_mem = &(_lmb->memory);
-	unsigned long idx = _mem->cnt-1;
+	unsigned long idx;
+
+	for(idx=_mem->cnt-1; idx >= 0 ;idx--) {
+		if ( _mem->region[idx].type != LMB_MEMORY_AREA )
+			continue;
 #ifdef CONFIG_MSCHUNKS
-	unsigned long lastbase = _mem->region[idx].physbase;
+		return (_mem->region[idx].physbase + _mem->region[idx].size);
 #else
-	unsigned long lastbase = _mem->region[idx].base;
+		return (_mem->region[idx].base + _mem->region[idx].size);
 #endif /* CONFIG_MSCHUNKS */
-	unsigned long lastsize = _mem->region[idx].size;
+	}
 
-	return (lastbase + lastsize);
+	return 0;
 }
 
 
 unsigned long
 lmb_abs_to_phys(unsigned long aa)
 {
-	unsigned long i, pa = 0;
+	unsigned long i, pa = aa;
 	unsigned long offset = reloc_offset();
 	struct lmb *_lmb = PTRRELOC(&lmb);
 	struct lmb_region *_mem = &(_lmb->memory);
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc64/kernel/misc.S	Sun Apr 14 12:16:57 2002
@@ -496,25 +496,15 @@
  *   kernel_thread(fn, arg, flags)
  */
 _GLOBAL(kernel_thread)
+	/* XXX fix this when we optimise syscall entry to not save volatiles */
 	mr	r6,r3		/* function */
 	ori	r3,r5,CLONE_VM	/* flags */
 	li	r0,__NR_clone
 	sc
 	cmpi	0,r3,0		/* parent or child? */
 	bnelr			/* return if parent */
-
-	li	r0,0		/* clear out p->thread.regs */
-	std	r0,THREAD+PT_REGS(r13)	/* since we don't have user ctx */
-
-	clrrdi	r5,r1,THREAD_SHIFT
-	ld	r0,TI_FLAGS(r5)
-	li	r7,_TIF_32BIT
-	andc	r0,r0,r7
-#ifdef CONFIG_PPC_ISERIES
-	ori	r0,r0,_TIF_RUN_LIGHT	/* Run light on */
-#endif
-	std	r0,TI_FLAGS(r5)
-
+	li	r0,0
+	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
 	ld	r2,8(r6)
 	ld	r6,0(r6)
 	mtlr	r6              /* fn addr in lr */
@@ -526,8 +516,7 @@
 
 #ifdef CONFIG_BINFMT_ELF32
 /* Why isn't this a) automatic, b) written in 'C'? */	
-	.data
-	.align 8
+	.balign 8
 _GLOBAL(sys_call_table32)
 	.llong .sys_ni_syscall	/* 0  -  old "setup()" system call */
 	.llong .sys32_exit
@@ -554,7 +543,7 @@
 	.llong .sys_oldumount
 	.llong .sys_setuid
 	.llong .sys_getuid
-	.llong .ppc64_sys_stime		/* 25 */
+	.llong .ppc64_sys32_stime       /* 25 */
 	.llong .sys32_ptrace
 	.llong .sys_alarm
 	.llong .sys32_fstat
@@ -738,12 +727,25 @@
 	.llong .sys_mincore		/* 206 */
 	.llong .sys_gettid		/* 207 */
 	.llong .sys_tkill		/* 208 */
-	.rept NR_syscalls-208
+	.llong .sys_setxattr
+	.llong .sys_lsetxattr	/* 210 */
+	.llong .sys_fsetxattr
+	.llong .sys_getxattr
+	.llong .sys_lgetxattr
+	.llong .sys_fgetxattr
+	.llong .sys_listxattr	/* 215 */
+	.llong .sys_llistxattr
+	.llong .sys_flistxattr
+	.llong .sys_removexattr
+	.llong .sys_lremovexattr
+	.llong .sys_fremovexattr	/* 220 */
+	.llong .sys_futex
+	.rept NR_syscalls-221
 		.llong .sys_ni_syscall
 	.endr
 #endif
-	.data
-	.align 8
+
+	.balign 8
 _GLOBAL(sys_call_table)
 	.llong .sys_ni_syscall	/* 0  -  old "setup()" system call */
 	.llong .sys_exit
@@ -954,6 +956,19 @@
 	.llong .sys_mincore		/* 206 */
 	.llong .sys_gettid		/* 207 */
 	.llong .sys_tkill		/* 208 */
-	.rept NR_syscalls-208
+	.llong .sys_setxattr
+	.llong .sys_lsetxattr	/* 210 */
+	.llong .sys_fsetxattr
+	.llong .sys_getxattr
+	.llong .sys_lgetxattr
+	.llong .sys_fgetxattr
+	.llong .sys_listxattr	/* 215 */
+	.llong .sys_llistxattr
+	.llong .sys_flistxattr
+	.llong .sys_removexattr
+	.llong .sys_lremovexattr
+	.llong .sys_fremovexattr	/* 220 */
+	.llong .sys_futex
+	.rept NR_syscalls-221
 	.llong .sys_ni_syscall
 	.endr
diff -Nru a/arch/ppc64/kernel/mk_defs.c b/arch/ppc64/kernel/mk_defs.c
--- a/arch/ppc64/kernel/mk_defs.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/mk_defs.c	Sun Apr 14 12:16:55 2002
@@ -115,12 +115,14 @@
 	/* Interrupt register frame */
 	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
 
+	DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+
 	/* 288 = # of volatile regs, int & fp, for leaf routines */
 	/* which do not stack a frame.  See the PPC64 ABI.       */
 	DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288);
 	/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
-	DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16 + 288);
-	DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16 + 288);
+	DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+	DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
 	DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
 	DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
 	DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
diff -Nru a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc64/kernel/nvram.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,140 @@
+/*
+ *  c 2001 PPC 64 Team, IBM Corp
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ * /dev/nvram driver for PPC64
+ *
+ * This perhaps should live in drivers/char
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/fcntl.h>
+#include <linux/nvram.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/nvram.h>
+#include <asm/rtas.h>
+#include <asm/prom.h>
+
+static unsigned int rtas_nvram_size;
+static unsigned int nvram_fetch, nvram_store;
+static char nvram_buf[4];	/* assume this is in the first 4GB */
+
+static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
+{
+	switch (origin) {
+	case 1:
+		offset += file->f_pos;
+		break;
+	case 2:
+		offset += rtas_nvram_size;
+		break;
+	}
+	if (offset < 0)
+		return -EINVAL;
+	file->f_pos = offset;
+	return file->f_pos;
+}
+
+
+static ssize_t read_nvram(struct file *file, char *buf,
+			  size_t count, loff_t *ppos)
+{
+	unsigned int i;
+	unsigned long len;
+	char *p = buf;
+
+	if (verify_area(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+	if (*ppos >= rtas_nvram_size)
+		return 0;
+	for (i = *ppos; count > 0 && i < rtas_nvram_size; ++i, ++p, --count) {
+		if ((rtas_call(nvram_fetch, 3, 2, &len, i, __pa(nvram_buf), 1) != 0) ||
+		    len != 1)
+			return -EIO;
+		if (__put_user(nvram_buf[0], p))
+			return -EFAULT;
+	}
+	*ppos = i;
+	return p - buf;
+}
+
+static ssize_t write_nvram(struct file *file, const char *buf,
+			   size_t count, loff_t *ppos)
+{
+	unsigned int i;
+	unsigned long len;
+	const char *p = buf;
+	char c;
+
+	if (verify_area(VERIFY_READ, buf, count))
+		return -EFAULT;
+	if (*ppos >= rtas_nvram_size)
+		return 0;
+	for (i = *ppos; count > 0 && i < rtas_nvram_size; ++i, ++p, --count) {
+		if (__get_user(c, p))
+			return -EFAULT;
+		nvram_buf[0] = c;
+		if ((rtas_call(nvram_store, 3, 2, &len, i, __pa(nvram_buf), 1) != 0) ||
+		    len != 1)
+			return -EIO;
+	}
+	*ppos = i;
+	return p - buf;
+}
+
+static int nvram_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+struct file_operations nvram_fops = {
+	owner:		THIS_MODULE,
+	llseek:		nvram_llseek,
+	read:		read_nvram,
+	write:		write_nvram,
+	ioctl:		nvram_ioctl,
+};
+
+static struct miscdevice nvram_dev = {
+	NVRAM_MINOR,
+	"nvram",
+	&nvram_fops
+};
+
+int __init nvram_init(void)
+{
+	struct device_node *nvram;
+	unsigned int *nbytes_p, proplen;
+	if ((nvram = find_type_devices("nvram")) != NULL) {
+		nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen);
+		if (nbytes_p && proplen == sizeof(unsigned int)) {
+			rtas_nvram_size = *nbytes_p;
+		}
+	}
+	nvram_fetch = rtas_token("nvram-fetch");
+	nvram_store = rtas_token("nvram-store");
+	printk(KERN_INFO "PPC64 nvram contains %d bytes\n", rtas_nvram_size);
+
+	misc_register(&nvram_dev);
+	return 0;
+}
+
+void __exit nvram_cleanup(void)
+{
+        misc_deregister( &nvram_dev );
+}
+
+module_init(nvram_init);
+module_exit(nvram_cleanup);
+MODULE_LICENSE("GPL");
diff -Nru a/arch/ppc64/kernel/pSeries_htab.c b/arch/ppc64/kernel/pSeries_htab.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc64/kernel/pSeries_htab.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,471 @@
+/*
+ * pSeries hashtable management.
+ *
+ * SMP scalability work:
+ *    Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+
+#include <asm/abs_addr.h>
+#include <asm/machdep.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Create a pte. Used during initialization only.
+ * We assume the PTE will fit in the primary PTEG.
+ */
+void pSeries_make_pte(HPTE *htab, unsigned long va, unsigned long pa,
+		      int mode, unsigned long hash_mask, int large)
+{
+	HPTE *hptep;
+	unsigned long hash, i;
+	unsigned long vpn;
+
+	if (large)
+		vpn = va >> LARGE_PAGE_SHIFT;
+	else
+		vpn = va >> PAGE_SHIFT;
+
+	hash = hpt_hash(vpn, large);
+
+	hptep  = htab + ((hash & hash_mask)*HPTES_PER_GROUP);
+
+	for (i = 0; i < 8; ++i, ++hptep) {
+		if (hptep->dw0.dw0.v == 0) {		/* !valid */
+			hptep->dw1.dword1 = pa | mode;
+			hptep->dw0.dword0 = 0;
+			hptep->dw0.dw0.avpn = va >> 23;
+			hptep->dw0.dw0.bolted = 1;	/* bolted */
+			if (large) {
+				hptep->dw0.dw0.l = 1;
+				hptep->dw0.dw0.avpn &= ~0x1UL;
+			}
+			hptep->dw0.dw0.v = 1;		/* make valid */
+			return;
+		}
+	}
+
+	/* We should _never_ get here and too early to call xmon. */
+	while(1)
+		;
+}
+
+#define HPTE_LOCK_BIT 3
+
+static inline void pSeries_lock_hpte(HPTE *hptep)
+{
+	unsigned long *word = &hptep->dw0.dword0;
+
+	while (1) {
+		if (!test_and_set_bit(HPTE_LOCK_BIT, word))
+			break;
+		while(test_bit(HPTE_LOCK_BIT, word))
+			barrier();
+	}
+}
+
+static inline void pSeries_unlock_hpte(HPTE *hptep)
+{
+	unsigned long *word = &hptep->dw0.dword0;
+
+	asm volatile("lwsync":::"memory");
+	clear_bit(HPTE_LOCK_BIT, word);
+}
+
+static spinlock_t pSeries_tlbie_lock = SPIN_LOCK_UNLOCKED;
+
+static long pSeries_insert_hpte(unsigned long hpte_group, unsigned long vpn,
+				unsigned long prpn, int secondary,
+				unsigned long hpteflags, int bolted, int large)
+{
+	unsigned long avpn = vpn >> 11;
+	unsigned long arpn = physRpn_to_absRpn(prpn);
+	HPTE *hptep = htab_data.htab + hpte_group;
+	Hpte_dword0 dw0;
+	HPTE lhpte;
+	int i;
+
+	for (i = 0; i < HPTES_PER_GROUP; i++) {
+		dw0 = hptep->dw0.dw0;
+
+		if (!dw0.v) {
+			/* retry with lock held */
+			pSeries_lock_hpte(hptep);
+			dw0 = hptep->dw0.dw0;
+			if (!dw0.v)
+				break;
+			pSeries_unlock_hpte(hptep);
+		}
+
+		hptep++;
+	}
+
+	if (i == HPTES_PER_GROUP)
+		return -1;
+
+	lhpte.dw1.dword1      = 0;
+	lhpte.dw1.dw1.rpn     = arpn;
+	lhpte.dw1.flags.flags = hpteflags;
+
+	lhpte.dw0.dword0      = 0;
+	lhpte.dw0.dw0.avpn    = avpn;
+	lhpte.dw0.dw0.h       = secondary;
+	lhpte.dw0.dw0.bolted  = bolted;
+	lhpte.dw0.dw0.v       = 1;
+
+	if (large)
+		lhpte.dw0.dw0.l = 1;
+
+	hptep->dw1.dword1 = lhpte.dw1.dword1;
+
+	/* Guarantee the second dword is visible before the valid bit */
+	__asm__ __volatile__ ("eieio" : : : "memory");
+
+	/*
+	 * Now set the first dword including the valid bit
+	 * NOTE: this also unlocks the hpte
+	 */
+	hptep->dw0.dword0 = lhpte.dw0.dword0;
+
+	__asm__ __volatile__ ("ptesync" : : : "memory");
+
+	return i;
+}
+
+static long pSeries_remove_hpte(unsigned long hpte_group)
+{
+	HPTE *hptep;
+	Hpte_dword0 dw0;
+	int i;
+	int slot_offset;
+	unsigned long vsid, group, pi, pi_high;
+	unsigned long slot;
+	unsigned long flags;
+	int large;
+	unsigned long va;
+
+	/* pick a random slot to start at */
+	slot_offset = mftb() & 0x7;
+
+	udbg_printf("remove_hpte in %d\n", slot_offset);
+
+	for (i = 0; i < HPTES_PER_GROUP; i++) {
+		hptep = htab_data.htab + hpte_group + slot_offset;
+		dw0 = hptep->dw0.dw0;
+
+		if (dw0.v && !dw0.bolted) {
+			/* retry with lock held */
+			pSeries_lock_hpte(hptep);
+			dw0 = hptep->dw0.dw0;
+			if (dw0.v && !dw0.bolted)
+				break;
+			pSeries_unlock_hpte(hptep);
+		}
+
+		slot_offset++;
+		slot_offset &= 0x7;
+	}
+
+	if (i == HPTES_PER_GROUP)
+		return -1;
+
+	large = dw0.l;
+
+	/* Invalidate the hpte. NOTE: this also unlocks it */
+	hptep->dw0.dword0 = 0;
+
+	/* Invalidate the tlb */
+	vsid = dw0.avpn >> 5;
+	slot = hptep - htab_data.htab;
+	group = slot >> 3;
+	if (dw0.h)
+		group = ~group;
+	pi = (vsid ^ group) & 0x7ff;
+	pi_high = (dw0.avpn & 0x1f) << 11;
+	pi |= pi_high;
+
+	if (large)
+		va = pi << LARGE_PAGE_SHIFT;
+	else
+		va = pi << PAGE_SHIFT;
+
+	spin_lock_irqsave(&pSeries_tlbie_lock, flags);
+	_tlbie(va, large);
+	spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
+
+	return i;
+}
+
+static inline void set_pp_bit(unsigned long pp, HPTE *addr)
+{
+	unsigned long old;
+	unsigned long *p = &addr->dw1.dword1;
+
+	__asm__ __volatile__(
+	"1:	ldarx	%0,0,%3\n\
+		rldimi	%0,%2,0,62\n\
+		stdcx.	%0,0,%3\n\
+		bne	1b"
+	: "=&r" (old), "=m" (*p)
+	: "r" (pp), "r" (p), "m" (*p)
+	: "cc");
+}
+
+/*
+ * Only works on small pages. Yes its ugly to have to check each slot in
+ * the group but we only use this during bootup.
+ */
+static long pSeries_hpte_find(unsigned long vpn)
+{
+	HPTE *hptep;
+	unsigned long hash;
+	unsigned long i, j;
+	long slot;
+	Hpte_dword0 dw0;
+
+	hash = hpt_hash(vpn, 0);
+
+	for (j = 0; j < 2; j++) {
+		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+		for (i = 0; i < HPTES_PER_GROUP; i++) {
+			hptep = htab_data.htab + slot;
+			dw0 = hptep->dw0.dw0;
+
+			if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
+			    (dw0.h == j)) {
+				/* HPTE matches */
+				if (j)
+					slot = -slot;
+				return slot;
+			}
+			++slot;
+		}
+		hash = ~hash;
+	}
+
+	return -1;
+}
+
+static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
+				  unsigned long va, int large)
+{
+	HPTE *hptep = htab_data.htab + slot;
+	Hpte_dword0 dw0;
+	unsigned long vpn, avpn;
+	unsigned long flags;
+
+	udbg_printf("updatepp\n");
+
+	if (large)
+		vpn = va >> LARGE_PAGE_SHIFT;
+	else
+		vpn = va >> PAGE_SHIFT;
+
+	avpn = vpn >> 11;
+
+	pSeries_lock_hpte(hptep);
+
+	dw0 = hptep->dw0.dw0;
+
+	if ((dw0.avpn != avpn) || !dw0.v) {
+		pSeries_unlock_hpte(hptep);
+		udbg_printf("updatepp missed\n");
+		return -1;
+	}
+
+	set_pp_bit(newpp, hptep);
+
+	pSeries_unlock_hpte(hptep);
+
+	/* Ensure it is out of the tlb too */
+	/* XXX use tlbiel where possible */
+	spin_lock_irqsave(&pSeries_tlbie_lock, flags);
+	_tlbie(va, large);
+	spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
+
+	return 0;
+}
+
+/*
+ * Update the page protection bits. Intended to be used to create
+ * guard pages for kernel data structures on pages which are bolted
+ * in the HPT. Assumes pages being operated on will not be stolen.
+ * Does not work on large pages.
+ *
+ * No need to lock here because we should be the only user.
+ */
+static void pSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
+{
+	unsigned long vsid, va, vpn, flags;
+	long slot;
+	HPTE *hptep;
+
+	vsid = get_kernel_vsid(ea);
+	va = (vsid << 28) | (ea & 0x0fffffff);
+	vpn = va >> PAGE_SHIFT;
+
+	slot = pSeries_hpte_find(vpn);
+	if (slot == -1)
+		panic("could not find page to bolt\n");
+	hptep = htab_data.htab + slot;
+
+	set_pp_bit(newpp, hptep);
+
+	/* Ensure it is out of the tlb too */
+	/* XXX use tlbiel where possible */
+	spin_lock_irqsave(&pSeries_tlbie_lock, flags);
+	_tlbie(va, 0);
+	spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
+}
+
+static void pSeries_hpte_invalidate(unsigned long slot, unsigned long va,
+				    int large, int local)
+{
+	HPTE *hptep = htab_data.htab + slot;
+	Hpte_dword0 dw0;
+	unsigned long vpn, avpn;
+	unsigned long flags;
+
+	if (large)
+		vpn = va >> LARGE_PAGE_SHIFT;
+	else
+		vpn = va >> PAGE_SHIFT;
+
+	avpn = vpn >> 11;
+
+	pSeries_lock_hpte(hptep);
+
+	dw0 = hptep->dw0.dw0;
+
+	if ((dw0.avpn != avpn) || !dw0.v) {
+		pSeries_unlock_hpte(hptep);
+		udbg_printf("invalidate missed\n");
+		return;
+	}
+
+	/* Invalidate the hpte. NOTE: this also unlocks it */
+	hptep->dw0.dword0 = 0;
+
+	/* Invalidate the tlb */
+	if (!large && local && __is_processor(PV_POWER4)) {
+		_tlbiel(va, large);
+	} else {
+		spin_lock_irqsave(&pSeries_tlbie_lock, flags);
+		_tlbie(va, large);
+		spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
+	}
+}
+
+static void pSeries_flush_hash_range(unsigned long context,
+				     unsigned long number, int local)
+{
+	unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
+	int i, j;
+	unsigned long va_array[MAX_BATCH_FLUSH];
+	HPTE *hptep;
+	Hpte_dword0 dw0;
+	struct tlb_batch_data *ptes = &tlb_batch_array[smp_processor_id()][0];
+	/* XXX fix for large ptes */
+	unsigned long large = 0;
+	j = 0;
+	for (i = 0; i < number; i++) {
+		if ((ptes->addr >= USER_START) && (ptes->addr <= USER_END))
+			vsid = get_vsid(context, ptes->addr);
+		else
+			vsid = get_kernel_vsid(ptes->addr);
+
+		va = (vsid << 28) | (ptes->addr & 0x0fffffff);
+		va_array[j] = va;
+		if (large)
+			vpn = va >> LARGE_PAGE_SHIFT;
+		else
+			vpn = va >> PAGE_SHIFT;
+		hash = hpt_hash(vpn, large);
+		secondary = (pte_val(ptes->pte) & _PAGE_SECONDARY) >> 15;
+		if (secondary)
+			hash = ~hash;
+		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+		slot += (pte_val(ptes->pte) & _PAGE_GROUP_IX) >> 12;
+
+		hptep = htab_data.htab + slot;
+		avpn = vpn >> 11;
+
+		pSeries_lock_hpte(hptep);
+
+		dw0 = hptep->dw0.dw0;
+
+		ptes++;
+
+		if ((dw0.avpn != avpn) || !dw0.v) {
+			pSeries_unlock_hpte(hptep);
+			udbg_printf("invalidate missed\n");
+			continue;
+		}
+
+		j++;
+
+		/* Invalidate the hpte. NOTE: this also unlocks it */
+		hptep->dw0.dword0 = 0;
+	}
+
+	if (!large && local && __is_processor(PV_POWER4)) {
+		asm volatile("ptesync":::"memory");
+
+		for (i = 0; i < j; i++) {
+			asm volatile("\n\
+			clrldi  %0,%0,16\n\
+			tlbiel   %0"
+			: : "r" (va_array[i]) : "memory" );
+		}
+
+		asm volatile("ptesync":::"memory");
+	} else {
+		/* XXX double check that it is safe to take this late */
+		spin_lock_irqsave(&pSeries_tlbie_lock, flags);
+
+		asm volatile("ptesync":::"memory");
+
+		for (i = 0; i < j; i++) {
+			asm volatile("\n\
+			clrldi  %0,%0,16\n\
+			tlbie   %0"
+			: : "r" (va_array[i]) : "memory" );
+		}
+
+		asm volatile("eieio; tlbsync; ptesync":::"memory");
+
+		spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
+	}
+}
+
+void hpte_init_pSeries(void)
+{
+	struct device_node *root;
+	const char *model;
+
+	ppc_md.hpte_invalidate	= pSeries_hpte_invalidate;
+	ppc_md.hpte_updatepp	= pSeries_hpte_updatepp;
+	ppc_md.hpte_updateboltedpp = pSeries_hpte_updateboltedpp;
+	ppc_md.insert_hpte	= pSeries_insert_hpte;
+	ppc_md.remove_hpte	= pSeries_remove_hpte;
+	ppc_md.make_pte		= pSeries_make_pte;
+
+	/* Disable TLB batching on nighthawk */
+	root = find_path_device("/");
+	if (root) {
+		model = get_property(root, "model", NULL);
+		if (strcmp(model, "CHRP IBM,9076-N81"))
+			ppc_md.flush_hash_range = pSeries_flush_hash_range;
+	}
+}
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	Sun Apr 14 12:17:00 2002
+++ b/arch/ppc64/kernel/pSeries_lpar.c	Sun Apr 14 12:17:00 2002
@@ -32,6 +32,7 @@
 #include <asm/pci_dma.h>
 #include <linux/pci.h>
 #include <asm/Naca.h>
+#include <asm/tlbflush.h>
 
 /* Status return values */
 #define H_Success	0
@@ -51,6 +52,7 @@
 #define H_R_XLATE		(1UL<<(63-25))	/* include a valid logical page num in the pte if the valid bit is set */
 #define H_READ_4		(1UL<<(63-26))	/* Return 4 PTEs */
 #define H_AVPN			(1UL<<(63-32))	/* An avpn is provided as a sanity test */
+#define H_ANDCOND		(1UL<<(63-33))
 #define H_ICACHE_INVALIDATE	(1UL<<(63-40))	/* icbi, etc.  (ignored for IO pages) */
 #define H_ICACHE_SYNCHRONIZE	(1UL<<(63-41))	/* dcbst, icbi, etc (ignored for IO pages */
 #define H_ZERO_PAGE		(1UL<<(63-48))	/* zero the page before mapping (ignored for IO pages) */
@@ -214,357 +216,6 @@
 			   xirr_ret, &dummy, &dummy);
 }
 
-/*
- * The following section contains code that ultimately should
- * be put in the relavent file (htab.c, xics.c, etc).  It has
- * been put here for the time being in order to ease maintainence
- * of the pSeries LPAR code until it can all be put into CVS.
- */
-static void hpte_invalidate_pSeriesLP(unsigned long slot)
-{
-	HPTE old_pte;
-	unsigned long lpar_rc;
-	unsigned long flags = 0;
-			
-	lpar_rc = plpar_pte_remove(flags,
-				   slot,
-				   0,
-				   &old_pte.dw0.dword0, 
-				   &old_pte.dw1.dword1);
-	if (lpar_rc != H_Success) BUG();
-}
-
-/* NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
- * the low 3 bits of flags happen to line up.  So no transform is needed.
- * We can probably optimize here and assume the high bits of newpp are
- * already zero.  For now I am paranoid.
- */
-static void hpte_updatepp_pSeriesLP(long slot, unsigned long newpp, unsigned long va)
-{
-	unsigned long lpar_rc;
-	unsigned long flags;
-	flags =   newpp & 3;
-	lpar_rc = plpar_pte_protect( flags,
-				     slot,
-				     0);
-	if (lpar_rc != H_Success) {
-		udbg_printf( " bad return code from pte protect rc = %lx \n", lpar_rc); 
-		for (;;);
-	}
-}
-
-static void hpte_updateboltedpp_pSeriesLP(unsigned long newpp, unsigned long ea)
-{
-	unsigned long lpar_rc;
-	unsigned long vsid,va,vpn,flags;
-	long slot;
-
-	vsid = get_kernel_vsid( ea );
-	va = ( vsid << 28 ) | ( ea & 0x0fffffff );
-	vpn = va >> PAGE_SHIFT;
-
-	slot = ppc_md.hpte_find( vpn );
-	flags =   newpp & 3;
-	lpar_rc = plpar_pte_protect( flags,
-				     slot,
-				     0);
-	if (lpar_rc != H_Success) {
-		udbg_printf( " bad return code from pte bolted protect rc = %lx \n", lpar_rc); 
-		for (;;);
-	}
-}
-
-
-static unsigned long hpte_getword0_pSeriesLP(unsigned long slot)
-{
-	unsigned long dword0;
-	unsigned long lpar_rc;
-	unsigned long dummy_word1;
-	unsigned long flags;
-	/* Read 1 pte at a time                        */
-	/* Do not need RPN to logical page translation */
-	/* No cross CEC PFT access                     */
-	flags = 0;
-	
-	lpar_rc = plpar_pte_read(flags,
-				 slot,
-				 &dword0, &dummy_word1);
-	if (lpar_rc != H_Success) {
-		udbg_printf(" error on pte read in get_hpte0 rc = %lx \n", lpar_rc);
-		for (;;);
-	}
-
-	return(dword0);
-}
-
-static long hpte_selectslot_pSeriesLP(unsigned long vpn)
-{
-	unsigned long primary_hash;
-	unsigned long hpteg_slot;
-	unsigned i, k;
-	unsigned long flags;
-	HPTE  pte_read;
-	unsigned long lpar_rc;
-
-	/* Search the primary group for an available slot */
-	primary_hash = hpt_hash(vpn, 0);
-
-	hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-
-	/* Read 1 pte at a time                        */
-	/* Do not need RPN to logical page translation */
-	/* No cross CEC PFT access                     */
-	flags = 0;
-	for (i=0; i<HPTES_PER_GROUP; ++i) {
-		/* read the hpte entry from the slot */
-		lpar_rc = plpar_pte_read(flags,
-					 hpteg_slot + i,
-					 &pte_read.dw0.dword0, &pte_read.dw1.dword1);
-		if (lpar_rc != H_Success) {
-			udbg_printf(" read of hardware page table failed rc = %lx \n", lpar_rc); 
-			for (;;);
-		}
-		if ( pte_read.dw0.dw0.v == 0 ) {
-			/* If an available slot found, return it */
-			return hpteg_slot + i;
-		}
-
-	}
-
-
-	/* Search the secondary group for an available slot */
-	hpteg_slot = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-
-
-	for (i=0; i<HPTES_PER_GROUP; ++i) {
-		/* read the hpte entry from the slot */
-		lpar_rc = plpar_pte_read(flags,
-					 hpteg_slot + i,
-					 &pte_read.dw0.dword0, &pte_read.dw1.dword1);
-		if (lpar_rc != H_Success) {
-			udbg_printf(" read of hardware page table failed2 rc = %lx  \n", lpar_rc); 
-			for (;;);
-		}
-		if ( pte_read.dw0.dw0.v == 0 ) {
-			/* If an available slot found, return it */
-			return hpteg_slot + i;
-		}
-
-	}
-
-	/* No available entry found in secondary group */
-
-
-	/* Select an entry in the primary group to replace */
-
-	hpteg_slot = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP;
-
-	k = htab_data.next_round_robin++ & 0x7;
-
-	for (i=0; i<HPTES_PER_GROUP; ++i) {
-		if (k == HPTES_PER_GROUP)
-			k = 0;
-
-		lpar_rc = plpar_pte_read(flags,
-					 hpteg_slot + k,
-					 &pte_read.dw0.dword0, &pte_read.dw1.dword1);
-		if (lpar_rc != H_Success) {
-			udbg_printf( " pte read failed - rc = %lx", lpar_rc); 
-			for (;;);
-		}
-		if (  ! pte_read.dw0.dw0.bolted)
-		{
-			hpteg_slot += k;
-			/* Invalidate the current entry */
-			ppc_md.hpte_invalidate(hpteg_slot); 
-			return hpteg_slot;
-		}
-		++k;
-	}
-
-	/* No non-bolted entry found in primary group - time to panic */
-	udbg_printf("select_hpte_slot - No non-bolted HPTE in group 0x%lx! \n", hpteg_slot/HPTES_PER_GROUP);
-	udbg_printf("No non-bolted HPTE in group %lx", (unsigned long)hpteg_slot/HPTES_PER_GROUP);
-	for (;;);
-
-	/* never executes - avoid compiler errors */
-	return 0;
-}
-
-
-static void hpte_create_valid_pSeriesLP(unsigned long slot, unsigned long vpn,
-					unsigned long prpn, unsigned hash, 
-					void *ptep, unsigned hpteflags, 
-					unsigned bolted)
-{
-	/* Local copy of HPTE */
-	struct {
-		/* Local copy of first doubleword of HPTE */
-		union {
-			unsigned long d;
-			Hpte_dword0   h;
-		} dw0;
-		/* Local copy of second doubleword of HPTE */
-		union {
-			unsigned long     d;
-			Hpte_dword1       h;
-			Hpte_dword1_flags f;
-		} dw1;
-	} lhpte;
-	
-	unsigned long avpn = vpn >> 11;
-	unsigned long arpn = physRpn_to_absRpn( prpn );
-
-	unsigned long lpar_rc;
-	unsigned long flags;
-	HPTE ret_hpte;
-
-	/* Fill in the local HPTE with absolute rpn, avpn and flags */
-	lhpte.dw1.d        = 0;
-	lhpte.dw1.h.rpn    = arpn;
-	lhpte.dw1.f.flags  = hpteflags;
-
-	lhpte.dw0.d        = 0;
-	lhpte.dw0.h.avpn   = avpn;
-	lhpte.dw0.h.h      = hash;
-	lhpte.dw0.h.bolted = bolted;
-	lhpte.dw0.h.v      = 1;
-
-	/* Now fill in the actual HPTE */
-	/* Set CEC cookie to 0                  */
-	/* Large page = 0                       */
-	/* Zero page = 0                        */
-	/* I-cache Invalidate = 0               */
-	/* I-cache synchronize = 0              */
-	/* Exact = 1 - only modify exact entry  */
-	flags = H_EXACT;
-
-	if (hpteflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
-		lhpte.dw1.f.flags &= ~_PAGE_COHERENT;
-#if 1
-	__asm__ __volatile__ (
-		 H_ENTER_r3
-		 "mr	4, %1\n"
-		 "mr	5, %2\n"
-		 "mr	6, %3\n"
-		 "mr	7, %4\n"
-		 HSC
-		 "mr	%0, 3\n"
-		 : "=r" (lpar_rc)
-		 : "r" (flags), "r" (slot), "r" (lhpte.dw0.d), "r" (lhpte.dw1.d)
-		 : "r3", "r4", "r5", "r6", "r7", "cc");
-#else
-	lpar_rc =  plpar_pte_enter(flags,
-				   slot,
-				   lhpte.dw0.d,
-				   lhpte.dw1.d,
-				   &ret_hpte.dw0.dword0,
-				   &ret_hpte.dw1.dword1);
-#endif
-	if (lpar_rc != H_Success) {
-		udbg_printf("error on pte enter lapar rc = %ld\n",lpar_rc);
-		udbg_printf("ent: s=%lx, dw0=%lx, dw1=%lx\n", slot, lhpte.dw0.d, lhpte.dw1.d);
-		/* xmon_backtrace("backtrace"); */
-		for (;;);
-	}
-}
-
-static long hpte_find_pSeriesLP(unsigned long vpn)
-{
-	union {
-		unsigned long d;
-		Hpte_dword0   h;
-	} hpte_dw0;
-	long slot;
-	unsigned long hash;
-	unsigned long i,j;
-
-	hash = hpt_hash(vpn, 0);
-	for ( j=0; j<2; ++j ) {
-		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-		for ( i=0; i<HPTES_PER_GROUP; ++i ) {
-			hpte_dw0.d = hpte_getword0_pSeriesLP( slot );
-			if ( ( hpte_dw0.h.avpn == ( vpn >> 11 ) ) &&
-			     ( hpte_dw0.h.v ) &&
-			     ( hpte_dw0.h.h == j ) ) {
-				/* HPTE matches */
-				if ( j )
-					slot = -slot;
-				return slot;
-			}
-			++slot;
-		}
-		hash = ~hash;
-	}
-	return -1;
-} 
-
-/*
- * Create a pte - LPAR .  Used during initialization only.
- * We assume the PTE will fit in the primary PTEG.
- */
-void make_pte_LPAR(HPTE *htab,
-		   unsigned long va, unsigned long pa, int mode,
-		   unsigned long hash_mask, int large)
-{
-	HPTE  local_hpte, ret_hpte;
-	unsigned long hash, slot, flags,lpar_rc, vpn;
-
-	if (large)
-		vpn = va >> 24;
-	else
-		vpn = va >> 12;
-
-	hash = hpt_hash(vpn, large);
-
-	slot = ((hash & hash_mask)*HPTES_PER_GROUP);
-
-	local_hpte.dw1.dword1 = pa | mode;
-	local_hpte.dw0.dword0 = 0;
-	local_hpte.dw0.dw0.avpn = va >> 23;
-	local_hpte.dw0.dw0.bolted = 1;				/* bolted */
-	local_hpte.dw0.dw0.v = 1;
-
-	/* Set CEC cookie to 0                   */
-	/* Large page = 0                        */
-	/* Zero page = 0                         */
-	/* I-cache Invalidate = 0                */
-	/* I-cache synchronize = 0               */
-	/* Exact = 0 - modify any entry in group */
-	flags = 0;
-#if 1
-	__asm__ __volatile__ (
-		 H_ENTER_r3
-		 "mr	4, %1\n"
-		 "mr	5, %2\n"
-		 "mr	6, %3\n"
-		 "mr	7, %4\n"
-		 HSC
-		 "mr	%0, 3\n"
-		 : "=r" (lpar_rc)
-		 : "r" (flags), "r" (slot), "r" (local_hpte.dw0.dword0), "r" (local_hpte.dw1.dword1)
-		 : "r3", "r4", "r5", "r6", "r7", "cc");
-#else
-	lpar_rc =  plpar_pte_enter(flags,
-				   slot,
-				   local_hpte.dw0.dword0,
-				   local_hpte.dw1.dword1,
-				   &ret_hpte.dw0.dword0,
-				   &ret_hpte.dw1.dword1);
-#endif
-#if 0 /* NOTE: we explicitly do not check return status here because it is
-       * "normal" for early boot code to map io regions for which a partition
-       * has no access.  However, we will die if we actually fault on these
-       * "permission denied" pages.
-       */
-	if (lpar_rc != H_Success) {
-		/* pSeriesLP_init_early(); */
-		udbg_printf("flags=%lx, slot=%lx, dword0=%lx, dword1=%lx, rc=%d\n", flags, slot, local_hpte.dw0.dword0,local_hpte.dw1.dword1, lpar_rc);
-		BUG();
-	}
-#endif
-}
-
 static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, 
 				unsigned long uaddr, int direction )
 {
@@ -785,19 +436,14 @@
 	}
 }
 
+void pSeries_lpar_mm_init(void);
 
 /* This is called early in setup.c.
  * Use it to setup page table ppc_md stuff as well as udbg.
  */
 void pSeriesLP_init_early(void)
 {
-	ppc_md.hpte_invalidate   = hpte_invalidate_pSeriesLP;
-	ppc_md.hpte_updatepp     = hpte_updatepp_pSeriesLP;
-	ppc_md.hpte_updateboltedpp  = hpte_updateboltedpp_pSeriesLP;
-	ppc_md.hpte_getword0     = hpte_getword0_pSeriesLP;
-	ppc_md.hpte_selectslot   = hpte_selectslot_pSeriesLP;
-	ppc_md.hpte_create_valid = hpte_create_valid_pSeriesLP;
-	ppc_md.hpte_find	 = hpte_find_pSeriesLP;
+	pSeries_lpar_mm_init();
 
 	ppc_md.tce_build	 = tce_build_pSeriesLP;
 	ppc_md.tce_free		 = tce_free_pSeriesLP;
@@ -890,4 +536,319 @@
 		}
 	}
 	return 0;
+}
+
+
+
+
+
+
+/*
+ * Create a pte - LPAR .  Used during initialization only.
+ * We assume the PTE will fit in the primary PTEG.
+ */
+void pSeries_lpar_make_pte(HPTE *htab, unsigned long va, unsigned long pa,
+			   int mode, unsigned long hash_mask, int large)
+{
+	HPTE local_hpte;
+	unsigned long hash, slot, flags, lpar_rc, vpn;
+	unsigned long dummy1, dummy2;
+
+	if (large)
+		vpn = va >> LARGE_PAGE_SHIFT;
+	else
+		vpn = va >> PAGE_SHIFT;
+
+	hash = hpt_hash(vpn, large);
+
+	slot = ((hash & hash_mask)*HPTES_PER_GROUP);
+
+	local_hpte.dw1.dword1 = pa | mode;
+	local_hpte.dw0.dword0 = 0;
+	local_hpte.dw0.dw0.avpn = va >> 23;
+	local_hpte.dw0.dw0.bolted = 1;		/* bolted */
+	if (large) {
+		local_hpte.dw0.dw0.l = 1;	/* large page */
+		local_hpte.dw0.dw0.avpn &= ~0x1UL;
+	}
+	local_hpte.dw0.dw0.v = 1;
+
+	/* Set CEC cookie to 0                   */
+	/* Zero page = 0                         */
+	/* I-cache Invalidate = 0                */
+	/* I-cache synchronize = 0               */
+	/* Exact = 0 - modify any entry in group */
+	flags = 0;
+
+	lpar_rc =  plpar_pte_enter(flags, slot, local_hpte.dw0.dword0,
+				   local_hpte.dw1.dword1, &dummy1, &dummy2);
+
+	if (lpar_rc == H_PTEG_Full) {
+		while(1)
+			;
+	}
+
+	/*
+	 * NOTE: we explicitly do not check return status here because it is
+	 * "normal" for early boot code to map io regions for which a partition
+	 * has no access.  However, we will die if we actually fault on these
+	 * "permission denied" pages.
+	 */
+}
+
+static long pSeries_lpar_insert_hpte(unsigned long hpte_group,
+				     unsigned long vpn, unsigned long prpn,
+				     int secondary, unsigned long hpteflags,
+				     int bolted, int large)
+{
+	unsigned long avpn = vpn >> 11;
+	unsigned long arpn = physRpn_to_absRpn(prpn);
+	unsigned long lpar_rc;
+	unsigned long flags;
+	unsigned long slot;
+	HPTE lhpte;
+
+	/* Fill in the local HPTE with absolute rpn, avpn and flags */
+	lhpte.dw1.dword1      = 0;
+	lhpte.dw1.dw1.rpn     = arpn;
+	lhpte.dw1.flags.flags = hpteflags;
+
+	lhpte.dw0.dword0      = 0;
+	lhpte.dw0.dw0.avpn    = avpn;
+	lhpte.dw0.dw0.h       = secondary;
+	lhpte.dw0.dw0.bolted  = bolted;
+	lhpte.dw0.dw0.v       = 1;
+
+	if (large)
+		lhpte.dw0.dw0.l = 1;
+
+	/* Now fill in the actual HPTE */
+	/* Set CEC cookie to 0         */
+	/* Large page = 0              */
+	/* Zero page = 0               */
+	/* I-cache Invalidate = 0      */
+	/* I-cache synchronize = 0     */
+	/* Exact = 0                   */
+	flags = 0;
+
+	/* XXX why is this here? - Anton */
+	if (hpteflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
+		lhpte.dw1.flags.flags &= ~_PAGE_COHERENT;
+
+	__asm__ __volatile__ (
+		H_ENTER_r3
+		"mr    4, %2\n"
+                "mr    5, %3\n"
+                "mr    6, %4\n"
+                "mr    7, %5\n"
+                HSC    
+                "mr    %0, 3\n"
+                "mr    %1, 4\n"
+		: "=r" (lpar_rc), "=r" (slot)
+		: "r" (flags), "r" (hpte_group), "r" (lhpte.dw0.dword0),
+		"r" (lhpte.dw1.dword1)
+		: "r3", "r4", "r5", "r6", "r7", "cc");
+
+	if (lpar_rc == H_PTEG_Full)
+		return -1;
+
+	if (lpar_rc != H_Success)
+		panic("Bad return code from pte enter rc = %lx\n", lpar_rc);
+
+	return slot;
+}
+
+static spinlock_t pSeries_lpar_tlbie_lock = SPIN_LOCK_UNLOCKED;
+
+static long pSeries_lpar_remove_hpte(unsigned long hpte_group)
+{
+	unsigned long slot_offset;
+	unsigned long lpar_rc;
+	int i;
+	unsigned long dummy1, dummy2;
+
+	/* pick a random slot to start at */
+	slot_offset = mftb() & 0x7;
+
+	for (i = 0; i < HPTES_PER_GROUP; i++) {
+
+		/* dont remove a bolted entry */
+		lpar_rc = plpar_pte_remove(H_ANDCOND, hpte_group + slot_offset,
+					   (0x1UL << 4), &dummy1, &dummy2);
+
+		if (lpar_rc == H_Success)
+			return i;
+
+		if (lpar_rc != H_Not_Found)
+			panic("Bad return code from pte remove rc = %lx\n",
+			      lpar_rc);
+
+		slot_offset++;
+		slot_offset &= 0x7;
+	}
+
+	return -1;
+}
+
+/*
+ * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
+ * the low 3 bits of flags happen to line up.  So no transform is needed.
+ * We can probably optimize here and assume the high bits of newpp are
+ * already zero.  For now I am paranoid.
+ */
+static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
+				       unsigned long va, int large)
+{
+	unsigned long lpar_rc;
+	unsigned long flags;
+	flags = (newpp & 3) | H_AVPN;
+	unsigned long vpn = va >> PAGE_SHIFT;
+
+	udbg_printf("updatepp\n");
+
+	lpar_rc = plpar_pte_protect(flags, slot, (vpn >> 4) & ~0x7fUL);
+
+	if (lpar_rc == H_Not_Found) {
+		udbg_printf("updatepp missed\n");
+		return -1;
+	}
+
+	if (lpar_rc != H_Success)
+		panic("bad return code from pte protect rc = %lx\n", lpar_rc);
+
+	return 0;
+}
+
+static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
+{
+	unsigned long dword0;
+	unsigned long lpar_rc;
+	unsigned long dummy_word1;
+	unsigned long flags;
+
+	/* Read 1 pte at a time                        */
+	/* Do not need RPN to logical page translation */
+	/* No cross CEC PFT access                     */
+	flags = 0;
+	
+	lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
+
+	if (lpar_rc != H_Success)
+		panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc);
+
+	return dword0;
+}
+
+static long pSeries_lpar_hpte_find(unsigned long vpn)
+{
+	unsigned long hash;
+	unsigned long i, j;
+	long slot;
+	union {
+		unsigned long dword0;
+		Hpte_dword0 dw0;
+	} hpte_dw0;
+	Hpte_dword0 dw0;
+
+	hash = hpt_hash(vpn, 0);
+
+	for (j = 0; j < 2; j++) {
+		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
+		for (i = 0; i < HPTES_PER_GROUP; i++) {
+			hpte_dw0.dword0 = pSeries_lpar_hpte_getword0(slot);
+			dw0 = hpte_dw0.dw0;
+
+			if ((dw0.avpn == (vpn >> 11)) && dw0.v &&
+			    (dw0.h == j)) {
+				/* HPTE matches */
+				if (j)
+					slot = -slot;
+				return slot;
+			}
+			++slot;
+		}
+		hash = ~hash;
+	}
+
+	return -1;
+} 
+
+static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
+					     unsigned long ea)
+{
+	unsigned long lpar_rc;
+	unsigned long vsid, va, vpn, flags;
+	long slot;
+
+	vsid = get_kernel_vsid(ea);
+	va = (vsid << 28) | (ea & 0x0fffffff);
+	vpn = va >> PAGE_SHIFT;
+
+	slot = pSeries_lpar_hpte_find(vpn);
+	if (slot == -1)
+		panic("updateboltedpp: Could not find page to bolt\n");
+
+	flags = newpp & 3;
+	lpar_rc = plpar_pte_protect(flags, slot, 0);
+
+	if (lpar_rc != H_Success)
+		panic("Bad return code from pte bolted protect rc = %lx\n",
+		      lpar_rc); 
+}
+
+static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+					 int large, int local)
+{
+	unsigned long vpn, avpn;
+	unsigned long lpar_rc;
+	unsigned long dummy1, dummy2;
+
+	if (large)
+		vpn = va >> LARGE_PAGE_SHIFT;
+	else
+		vpn = va >> PAGE_SHIFT;
+
+	avpn = vpn >> 11;
+
+	lpar_rc = plpar_pte_remove(H_AVPN, slot, (vpn >> 4) & ~0x7fUL, &dummy1,
+				   &dummy2);
+
+	if (lpar_rc == H_Not_Found) {
+		udbg_printf("invalidate missed\n");
+		return;
+	}
+
+	if (lpar_rc != H_Success)
+		panic("Bad return code from invalidate rc = %lx\n", lpar_rc);
+}
+
+/*
+ * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
+ * lock.
+ */
+void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
+				   int local)
+{
+	int i;
+	struct tlb_batch_data *ptes =
+		&tlb_batch_array[smp_processor_id()][0];
+	unsigned long flags;
+
+	spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
+	for (i = 0; i < number; i++) {
+		flush_hash_page(context, ptes->addr, ptes->pte, local);
+		ptes++;
+	}
+	spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
+}
+
+void pSeries_lpar_mm_init(void)
+{
+	ppc_md.hpte_invalidate  = pSeries_lpar_hpte_invalidate;
+	ppc_md.hpte_updatepp    = pSeries_lpar_hpte_updatepp;
+	ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
+	ppc_md.insert_hpte      = pSeries_lpar_insert_hpte;
+	ppc_md.remove_hpte      = pSeries_lpar_remove_hpte;
+	ppc_md.make_pte         = pSeries_lpar_make_pte;
+	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
 }
diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
--- a/arch/ppc64/kernel/pSeries_pci.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/pSeries_pci.c	Sun Apr 14 12:16:59 2002
@@ -757,34 +757,6 @@
 	return NULL;
 }
 
-/***********************************************************************
- * find_floppy(void) 
- *	
- * Finds the default floppy device, if the system has one, and returns 
- * the pci_dev for the isa bridge for the floppy device.  
- *
- * Note: This functions finds the first "fdc" device and then looks to 
- * the parent device which should be the isa bridge device.  If there 
- * is more than one floppy on the system, it will find the first one 
- * and maybe that is okay. 
- ***********************************************************************/
-struct pci_dev*
-find_floppy(void)
-{
-	struct device_node *floppy_dn;
-	struct pci_dev *floppy_dev = NULL;
-	int *reg; 
-
-	floppy_dn = find_type_devices("fdc");
-	if (floppy_dn && floppy_dn->parent) {
-		if ((reg = (unsigned int *)get_property(floppy_dn->parent,"reg", 0)) != NULL)
-			floppy_dev  = pci_find_slot((reg[0] & 0x00ff0000) >> 16, (reg[0] & 0x0000ff00) >> 8);
-	}
-	PPCDBG(PPCDBG_BUSWALK,"\tFloppy pci_dev\n");
-	PPCDBGCALL(PPCDBG_BUSWALK, dumpPci_Dev(floppy_dev) );
-	return floppy_dev;
-}
-
 /*********************************************************************** 
  * ppc64_pcibios_init
  *  
diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
--- a/arch/ppc64/kernel/pacaData.c	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/kernel/pacaData.c	Sun Apr 14 12:16:56 2002
@@ -42,9 +42,9 @@
                 next_round_robin: 1     /* Round robin index */             \
         },                                                                  \
         lpQueuePtr: (lpq),              /* &xItLpQueue,                  */ \
-        xRtas: {                                                            \
+        /* xRtas: {                                                            \
                 lock: SPIN_LOCK_UNLOCKED                                    \
-        },                                                                  \
+        }, */                                                                  \
         xProcStart: (start),            /* Processor start */               \
         xLpPaca: {                                                          \
                 xDesc: 0xd397d781,      /* "LpPa"          */               \
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc64/kernel/pci.c	Sun Apr 14 12:16:57 2002
@@ -58,7 +58,6 @@
 static void fixup_windbond_82c105(struct pci_dev* dev);
 void        fixup_resources(struct pci_dev* dev);
 
-struct pci_dev *find_floppy(void);
 void   iSeries_pcibios_init(void);
 void   pSeries_pcibios_init(void);
 
@@ -94,8 +93,8 @@
 
 static int pci_bus_count;
 
-/* Floppy dev for ppc64_fd_dma_setup().  May be null if no floppy in the system. */
-struct pci_dev *ppc64_floppy_dev = NULL;
+/* Cached ISA bridge dev. */
+struct pci_dev *ppc64_isabridge_dev = NULL;
 
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TRIDENT,	PCI_ANY_ID, fixup_broken_pcnet32 },
@@ -492,7 +491,10 @@
 	create_tce_tables();
 	PPCDBG(PPCDBG_BUSWALK,"pSeries create_tce_tables()\n");
 #endif
-	ppc64_floppy_dev = find_floppy();
+
+	/* Cache the location of the ISA bridge (if we have one) */
+	if (ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL))
+		printk("ISA bridge at %s\n", ppc64_isabridge_dev->slot_name);
 
 	printk("PCI: Probing PCI hardware done\n");
 	PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware done.\n");
diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc64/kernel/pci.h	Sun Apr 14 12:16:54 2002
@@ -46,7 +46,7 @@
 extern int    device_Location(struct pci_dev*,char*);
 extern int    format_device_location(struct pci_dev*,char*, int );
 
-extern struct pci_dev *ppc64_floppy_dev;
+extern struct pci_dev *ppc64_isabridge_dev;	/* may be NULL if no ISA bus */
 
 /*******************************************************************
  * PCI device_node operations
diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c
--- a/arch/ppc64/kernel/pci_dma.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/pci_dma.c	Sun Apr 14 12:16:59 2002
@@ -131,8 +131,12 @@
 	return 0;
 }
 
-static inline struct TceTable *get_tce_table(struct pci_dev *dev) {
-
+static inline struct TceTable *get_tce_table(struct pci_dev *dev)
+{
+	if (!dev)
+		dev = ppc64_isabridge_dev;
+	if (!dev)
+		return NULL;
 	if ( ( _machine == _MACH_iSeries ) && ( dev->bus ) ) 
 		return tceTables[dev->bus->number];
 	/* On the iSeries, the virtual bus will take this path.  There is a */
diff -Nru a/arch/ppc64/kernel/pmac_nvram.c b/arch/ppc64/kernel/pmac_nvram.c
--- a/arch/ppc64/kernel/pmac_nvram.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,358 +0,0 @@
-/*
- *  c 2001 PPC 64 Team, IBM Corp
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- *
- * Miscellaneous procedures for dealing with the PowerMac hardware.
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/nvram.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <asm/init.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-#undef DEBUG
-
-/*
- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
- */
-static int nvram_naddrs;
-static volatile unsigned char *nvram_addr;
-static volatile unsigned char *nvram_data;
-static int nvram_mult, is_core_99;
-static char* nvram_image;
-static int core99_bank = 0;
-sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
-
-#define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
- 
-#define CORE99_SIGNATURE	0x5a
-#define CORE99_ADLER_START	0x14
-
-/* Core99 nvram is a flash */
-#define CORE99_FLASH_STATUS_DONE	0x80
-#define CORE99_FLASH_STATUS_ERR		0x38
-#define CORE99_FLASH_CMD_ERASE_CONFIRM	0xd0
-#define CORE99_FLASH_CMD_ERASE_SETUP	0x20
-#define CORE99_FLASH_CMD_RESET		0xff
-#define CORE99_FLASH_CMD_WRITE_SETUP	0x40
-
-/* CHRP NVRAM header */
-struct chrp_header {
-	u8		signature;
-	u8		cksum;
-	u16		len;
-	char		name[12];
-	u8		data[0];
-};
-
-struct core99_header {
-	struct chrp_header	hdr;
-	u32			adler;
-	u32			generation;
-	u32			reserved[2];
-};
-
-static int nvram_partitions[3];
-
-static u8
-chrp_checksum(struct chrp_header* hdr)
-{
-	u8 *ptr;
-	u16 sum = hdr->signature;
-	for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
-		sum += *ptr;
-	while (sum > 0xFF)
-		sum = (sum & 0xFF) + (sum>>8);
-	return sum;
-}
-
-static u32
-core99_calc_adler(u8 *buffer)
-{
-	int cnt;
-	u32 low, high;
-
-   	buffer += CORE99_ADLER_START;
-	low = 1;
-	high = 0;
-	for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
-		if ((cnt % 5000) == 0) {
-			high  %= 65521UL;
-			high %= 65521UL;
-		}
-		low += buffer[cnt];
-		high += low;
-	}
-	low  %= 65521UL;
-	high %= 65521UL;
-  
-	return (high << 16) | low;
-}
-
-static u32
-core99_check(u8* datas)
-{
-	struct core99_header* hdr99 = (struct core99_header*)datas;
-
-	if (hdr99->hdr.signature != CORE99_SIGNATURE) {
-#ifdef DEBUG
-		printk("Invalid signature\n");
-#endif		
-		return 0;
-	}
-	if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
-#ifdef DEBUG
-		printk("Invalid checksum\n");
-#endif
-		return 0;
-	}
-	if (hdr99->adler != core99_calc_adler(datas)) {
-#ifdef DEBUG
-		printk("Invalid adler\n");
-#endif
-		return 0;
-	}
-	return hdr99->generation;
-}
-
-static int
-core99_erase_bank(int bank)
-{
-	int stat, i;
-	
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-	
-	out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
-	out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
-	do { stat = in_8(base); }
-	while(!(stat & CORE99_FLASH_STATUS_DONE));
-	out_8(base, CORE99_FLASH_CMD_RESET);
-	if (stat & CORE99_FLASH_STATUS_ERR) {
-		printk("nvram: flash error 0x%02x on erase !\n", stat);
-		return -ENXIO;
-	}
-	for (i=0; i<NVRAM_SIZE; i++)
-		if (base[i] != 0xff) {
-			printk("nvram: flash erase failed !\n");
-			return -ENXIO;
-		}
-	return 0;
-}
-
-static int
-core99_write_bank(int bank, u8* datas)
-{
-	int i, stat = 0;
-	
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-	
-	for (i=0; i<NVRAM_SIZE; i++) {
-		out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
-		out_8(base+i, datas[i]);
-		do { stat = in_8(base); }
-		while(!(stat & CORE99_FLASH_STATUS_DONE));
-		if (stat & CORE99_FLASH_STATUS_ERR)
-			break;
-	}
-	out_8(base, CORE99_FLASH_CMD_RESET);
-	if (stat & CORE99_FLASH_STATUS_ERR) {
-		printk("nvram: flash error 0x%02x on write !\n", stat);
-		return -ENXIO;
-	}
-	for (i=0; i<NVRAM_SIZE; i++)
-		if (base[i] != datas[i]) {
-			printk("nvram: flash write failed !\n");
-			return -ENXIO;
-		}
-	return 0;	
-}
-
-
-__init
-void pmac_nvram_init(void)
-{
-	struct device_node *dp;
-
-	nvram_naddrs = 0;
-
-	dp = find_devices("nvram");
-	if (dp == NULL) {
-		printk(KERN_ERR "Can't find NVRAM device\n");
-		return;
-	}
-	nvram_naddrs = dp->n_addrs;
-	is_core_99 = device_is_compatible(dp, "nvram,flash");
-	if (is_core_99) {
-		int i;
-		u32 gen_bank0, gen_bank1;
-		
-		if (nvram_naddrs < 1) {
-			printk(KERN_ERR "nvram: no address\n");
-			return;
-		}
-		nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
-		if (!nvram_image) {
-			printk(KERN_ERR "nvram: can't allocate image\n");
-			return;
-		}
-		nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
-#ifdef DEBUG
-		printk("nvram: Checking bank 0...\n");
-#endif
-		gen_bank0 = core99_check((u8 *)nvram_data);
-		gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
-		core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
-#ifdef DEBUG
-		printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
-		printk("nvram: Active bank is: %d\n", core99_bank);
-#endif
-		for (i=0; i<NVRAM_SIZE; i++)
-			nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
-	} else if (_machine == _MACH_pSeries && nvram_naddrs == 1) {
-		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
-		nvram_mult = 1;
-	} else if (nvram_naddrs == 1) {
-		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
-		nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
-	} else if (nvram_naddrs == 2) {
-		nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
-		nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
-	} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
-		nvram_naddrs = -1;
-	} else {
-		printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
-		       nvram_naddrs);
-	}
-}
-
-void
-pmac_nvram_update(void)
-{
-	struct core99_header* hdr99;
-	
-	if (!is_core_99 || !nvram_data || !nvram_image)
-		return;
-	if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
-		NVRAM_SIZE))
-		return;
-#ifdef DEBUG
-	printk("Updating nvram...\n");
-#endif
-	hdr99 = (struct core99_header*)nvram_image;
-	hdr99->generation++;
-	hdr99->hdr.signature = CORE99_SIGNATURE;
-	hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
-	hdr99->adler = core99_calc_adler(nvram_image);
-	core99_bank = core99_bank ? 0 : 1;
-	if (core99_erase_bank(core99_bank)) {
-		printk("nvram: Error erasing bank %d\n", core99_bank);
-		return;
-	}
-	if (core99_write_bank(core99_bank, nvram_image))
-		printk("nvram: Error writing bank %d\n", core99_bank);
-}
-
-__openfirmware
-unsigned char nvram_read_byte(int addr)
-{
-	#ifdef CONFIG_ADB_PMU  // -aglitke
-	  struct adb_request req;
-	#endif
-
-	switch (nvram_naddrs) {
-#ifdef CONFIG_ADB_PMU
-	case -1:
-		if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
-				(addr >> 8) & 0xff, addr & 0xff))
-			break;
-		while (!req.complete)
-			pmu_poll();
-		return req.reply[1];
-#endif
-	case 1:
-		if (is_core_99)
-			return nvram_image[addr];
-		return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
-	case 2:
-		*nvram_addr = addr >> 5;
-		eieio();
-		return nvram_data[(addr & 0x1f) << 4];
-	}
-	return 0;
-}
-
-__openfirmware
-void nvram_write_byte(unsigned char val, int addr)
-{
-	#ifdef CONFIG_ADB_PMU  // -aglitke
-	   struct adb_request req;
-	#endif
-	switch (nvram_naddrs) {
-#ifdef CONFIG_ADB_PMU
-	case -1:
-		if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
-				(addr >> 8) & 0xff, addr & 0xff, val))
-			break;
-		while (!req.complete)
-			pmu_poll();
-		break;
-#endif
-	case 1:
-		if (is_core_99) {
-			nvram_image[addr] = val;
-			break;
-		}
-		nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
-		break;
-	case 2:
-		*nvram_addr = addr >> 5;
-		eieio();
-		nvram_data[(addr & 0x1f) << 4] = val;
-		break;
-	}
-	eieio();
-}
-
-int
-pmac_get_partition(int partition)
-{
-	return nvram_partitions[partition];
-}
-
-u8
-pmac_xpram_read(int xpaddr)
-{
-	int offset = nvram_partitions[pmac_nvram_XPRAM];
-	
-	if (offset < 0)
-		return 0;
-		
-	return nvram_read_byte(xpaddr + offset);
-}
-
-void
-pmac_xpram_write(int xpaddr, u8 data)
-{
-	int offset = nvram_partitions[pmac_nvram_XPRAM];
-	
-	if (offset < 0)
-		return;
-		
-	nvram_write_byte(xpaddr + offset, data);
-}
-
-
diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
--- a/arch/ppc64/kernel/ppc_ksyms.c	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/kernel/ppc_ksyms.c	Sun Apr 14 12:16:56 2002
@@ -34,9 +34,6 @@
 #include <asm/bitops.h>
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
 #include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/pci-bridge.h>
@@ -45,9 +42,8 @@
 #include <asm/machdep.h>
 #include <asm/hw_irq.h>
 #include <asm/abs_addr.h>
-#ifdef CONFIG_SMP
 #include <asm/smplock.h>
-#endif /* CONFIG_SMP */
+#include <asm/cacheflush.h>
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iSeries/iSeries_pci.h>
 #include <asm/iSeries/iSeries_proc.h>
@@ -109,7 +105,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
@@ -238,9 +233,6 @@
 EXPORT_SYMBOL(find_all_nodes);
 EXPORT_SYMBOL(get_property);
 
-#ifndef CONFIG_PPC_ISERIES
-EXPORT_SYMBOL_NOVERS(sys_ctrler); /* tibit */
-#endif
 #ifdef CONFIG_NVRAM
 EXPORT_SYMBOL(nvram_read_byte);
 EXPORT_SYMBOL(nvram_write_byte);
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/process.c	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/ppc/kernel/process.c
+ *  linux/arch/ppc64/kernel/process.c
  *
  *  Derived from "arch/i386/kernel/process.c"
  *    Copyright (C) 1995  Linus Torvalds
@@ -45,19 +45,18 @@
 #include <asm/iSeries/HvCallHpt.h>
 #include <asm/Naca.h>
 
+#include "ppc_defs.h"
+
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
-extern unsigned long _get_SP(void);
 
 struct task_struct *last_task_used_math = NULL;
 
 struct mm_struct ioremap_mm = { pgd             : ioremap_dir  
                                ,page_table_lock : SPIN_LOCK_UNLOCKED };
 
-char *sysmap = NULL; 
+char *sysmap = NULL;
 unsigned long sysmap_size = 0;
 
-extern char __toc_start;
-
 void
 enable_kernel_fp(void)
 {
@@ -84,10 +83,7 @@
 _switch_to(struct task_struct *prev, struct task_struct *new)
 {
 	struct thread_struct *new_thread, *old_thread;
-	unsigned long s;
-	
-	__save_flags(s);
-	__cli();
+	unsigned long flags;
 
 #ifdef CONFIG_SMP
 	/* avoid complexity of lazy save/restore of fpu
@@ -99,14 +95,16 @@
 	 * every switch, just a save.
 	 *  -- Cort
 	 */
-	if ( prev->thread.regs && (prev->thread.regs->msr & MSR_FP) )
+	if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
 		giveup_fpu(prev);
 #endif /* CONFIG_SMP */
 
 	new_thread = &new->thread;
 	old_thread = &current->thread;
+
+	__save_and_cli(flags);
 	_switch(old_thread, new_thread);
-	__restore_flags(s);
+	__restore_flags(flags);
 }
 
 void show_regs(struct pt_regs * regs)
@@ -172,45 +170,50 @@
 int
 copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 	    unsigned long unused,
-	    struct task_struct * p, struct pt_regs * regs)
+	    struct task_struct *p, struct pt_regs *regs)
 {
-	unsigned long msr;
 	struct pt_regs *childregs, *kregs;
 	extern void ret_from_fork(void);
-
-	/* XXX get rid of the -2 Anton */
+	unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
 
 	/* Copy registers */
-	childregs = ((struct pt_regs *)
-		     ((unsigned long)p->thread_info + THREAD_SIZE 
-		      - STACK_FRAME_OVERHEAD)) - 2;
+	sp -= sizeof(struct pt_regs);
+	childregs = (struct pt_regs *) sp;
 	*childregs = *regs;
+	if ((childregs->msr & MSR_PR) == 0) {
+		/* for kernel thread, set `current' and stackptr in new task */
+		childregs->gpr[1] = sp + sizeof(struct pt_regs);
+		childregs->gpr[13] = (unsigned long) p;
+		p->thread.regs = NULL;	/* no user register state */
+		clear_ti_thread_flag(p->thread_info, TIF_32BIT);
+#ifdef CONFIG_PPC_ISERIES
+		set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT);
+#endif
+	} else
+		p->thread.regs = childregs;
 	childregs->gpr[3] = 0;  /* Result from fork() */
-	p->thread.regs = childregs;
-	p->thread.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
-	p->thread.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
-	kregs = (struct pt_regs *)(p->thread.ksp + STACK_FRAME_OVERHEAD);
-	/* The PPC64 compiler makes use of a TOC to contain function 
+	sp -= STACK_FRAME_OVERHEAD;
+
+	/*
+	 * The way this works is that at some point in the future
+	 * some task will call _switch to switch to the new task.
+	 * That will pop off the stack frame created below and start
+	 * the new task running at ret_from_fork.  The new task will
+	 * do some house keeping and then return from the fork or clone
+	 * system call, using the stack frame created above.
+	 */
+	sp -= sizeof(struct pt_regs);
+	kregs = (struct pt_regs *) sp;
+	sp -= STACK_FRAME_OVERHEAD;
+	p->thread.ksp = sp;
+
+	/*
+	 * The PPC64 ABI makes use of a TOC to contain function 
 	 * pointers.  The function (ret_from_except) is actually a pointer
 	 * to the TOC entry.  The first entry is a pointer to the actual
 	 * function.
  	 */
 	kregs->nip = *((unsigned long *)ret_from_fork);
-	asm volatile("mfmsr %0" : "=r" (msr):);
-	kregs->msr = msr;
-	kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
-	kregs->gpr[2] = (((unsigned long)&__toc_start) + 0x8000);
-
-	if (usp >= (unsigned long) regs) {
-		/* Stack is in kernel space - must adjust */
-		childregs->gpr[1] = (unsigned long)(childregs + 1);
-		*((unsigned long *) childregs->gpr[1]) = 0;
-		childregs->gpr[13] = (unsigned long) p;
-	} else {
-		/* Provided stack is in user space */
-		childregs->gpr[1] = usp;
-	}
-	p->thread.last_syscall = -1;
 
 	/*
 	 * copy fpu info - assume lazy fpu switch now always
@@ -223,6 +226,8 @@
 	memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
 	p->thread.fpscr = current->thread.fpscr;
 
+	p->thread.last_syscall = -1;
+
 	return 0;
 }
 
@@ -239,7 +244,6 @@
 	unsigned long *entry = (unsigned long *)nip;
 	unsigned long *toc   = entry + 1;
 
-
 	set_fs(USER_DS);
 	memset(regs->gpr, 0, sizeof(regs->gpr));
 	memset(&regs->ctr, 0, 4 * sizeof(regs->ctr));
@@ -252,53 +256,27 @@
 	current->thread.fpscr = 0;
 }
 
-asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
-			 struct pt_regs *regs)
+int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
+	      struct pt_regs *regs)
 {
-	unsigned long clone_flags = p1;
-	int res;
-
-	res = do_fork(clone_flags, regs->gpr[1], regs, 0);
-#ifdef CONFIG_SMP
-	/* When we clone the idle task we keep the same pid but
-	 * the return value of 0 for both causes problems.
-	 * -- Cort
-	 */
-	if ((current->pid == 0) && (current == &init_task))
-		res = 1;
-#endif /* CONFIG_SMP */
-
-	return res;
+	return do_fork(p1, regs->gpr[1], regs, 0);
 }
 
-asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
-			struct pt_regs *regs)
+int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+	     struct pt_regs *regs)
 {
-	int res;
-	
-	res = do_fork(SIGCHLD, regs->gpr[1], regs, 0);
-  
-#ifdef CONFIG_SMP
-	/* When we clone the idle task we keep the same pid but
-	 * the return value of 0 for both causes problems.
-	 * -- Cort
-	 */
-	if ((current->pid == 0) && (current == &init_task))
-		res = 1;
-#endif /* CONFIG_SMP */
-	
-	return res;
+	return do_fork(SIGCHLD, regs->gpr[1], regs, 0);
 }
 
-asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
+int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
 			 struct pt_regs *regs)
 {
 	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
 }
 
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-			  unsigned long a3, unsigned long a4, unsigned long a5,
-			  struct pt_regs *regs)
+int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
+	       unsigned long a3, unsigned long a4, unsigned long a5,
+	       struct pt_regs *regs)
 {
 	int error;
 	char * filename;
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/prom.c	Sun Apr 14 12:16:59 2002
@@ -204,7 +204,13 @@
 
 #ifdef CONFIG_MSCHUNKS
 static unsigned long prom_initialize_mschunks(unsigned long);
+#ifdef DEBUG_PROM
+void prom_dump_mschunks_mapping(void);
+#endif /* DEBUG_PROM */
 #endif /* CONFIG_MSCHUNKS */
+#ifdef DEBUG_PROM
+void prom_dump_lmb(void);
+#endif
 
 extern unsigned long reloc_offset(void);
 
@@ -536,10 +542,11 @@
         unsigned long i, offset = reloc_offset();
 	struct prom_t *_prom = PTRRELOC(&prom);
 	union lmb_reg_property reg;
-	unsigned long mem_size, lmb_base, lmb_size;
+	unsigned long lmb_base, lmb_size;
 	unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
 
 #ifdef CONFIG_MSCHUNKS
+	unsigned long max_addr = 0;
 #if 1
 	/* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
 	unsigned long io_base = 3UL<<30;
@@ -550,7 +557,7 @@
 	unsigned long io_base = <real io base here>;
 	unsigned long io_size = <real io size here>;
 #endif
-#endif
+#endif /* CONFIG_MSCHUNKS */
 
 	lmb_init();
 
@@ -582,24 +589,32 @@
 			 	 */
 				have_630 = 0;
 			}
-#endif
+#endif /* CONFIG_MSCHUNKS */
 			if ( lmb_add(lmb_base, lmb_size) < 0 )
 				prom_print(RELOC("Too many LMB's, discarding this one...\n"));
-			else
-				mem_size =+ lmb_size;
+#ifdef CONFIG_MSCHUNKS
+			else if ( max_addr < (lmb_base+lmb_size-1) )
+				max_addr = lmb_base+lmb_size-1;
+#endif /* CONFIG_MSCHUNKS */
 		}
 
 	}
 
 #ifdef CONFIG_MSCHUNKS
-	if ( have_630 && lmb_addrs_overlap(0,mem_size,io_base,io_size) )
+	if ( have_630 && lmb_addrs_overlap(0,max_addr,io_base,io_size) )
 		lmb_add_io(io_base, io_size);
-#endif
+#endif /* CONFIG_MSCHUNKS */
 
 	lmb_analyze();
+#ifdef DEBUG_PROM
+	prom_dump_lmb();
+#endif /* DEBUG_PROM */
 
 #ifdef CONFIG_MSCHUNKS
 	mem = prom_initialize_mschunks(mem);
+#ifdef DEBUG_PROM
+	prom_dump_mschunks_mapping();
+#endif /* DEBUG_PROM */
 #endif /* CONFIG_MSCHUNKS */
 
 	return mem;
@@ -711,52 +726,151 @@
 	struct lmb *_lmb  = PTRRELOC(&lmb);
 	struct msChunks *_msChunks = PTRRELOC(&msChunks);
 	unsigned long i, pchunk = 0;
-	unsigned long mem_size = _lmb->memory.size;
+	unsigned long addr_range = _lmb->memory.size + _lmb->memory.iosize;
 	unsigned long chunk_size = _lmb->memory.lcd_size;
 
-#if 1
-	/* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
-	unsigned long io_base = 3UL<<30;
-	unsigned long io_size = 1UL<<30;
 
+	mem = msChunks_alloc(mem, addr_range / chunk_size, chunk_size);
+
+	/* First create phys -> abs mapping for memory/dram */
 	for (i=0; i < _lmb->memory.cnt ;i++) {
 		unsigned long base = _lmb->memory.region[i].base;
 		unsigned long size = _lmb->memory.region[i].size;
-		if ( lmb_addrs_overlap(base,size,io_base,io_size) ) {
-			/* If we really have dram here, then we don't
-			 * have a 630! -Peter
-			 */
-			io_base = mem_size;
-			io_size = 1;
-			break;
-		}
-	}
-#else
-	unsigned long io_base = <real io base here>;
-	unsigned long io_size = <real io size here>;
-#endif
+		unsigned long achunk = addr_to_chunk(base);
+		unsigned long end_achunk = addr_to_chunk(base+size);
 
-	if ( lmb_addrs_overlap(0,mem_size,io_base,io_size) ) {
-		lmb_add(io_base, io_size);
-		lmb_reserve(io_base, io_size);
-	}
+		if(_lmb->memory.region[i].type != LMB_MEMORY_AREA)
+			continue;
 
-	mem = msChunks_alloc(mem, mem_size / chunk_size, chunk_size);
+		_lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
+		for (; achunk < end_achunk ;) {
+			PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
+		}
+	}
 
+#ifdef CONFIG_MSCHUNKS
+	/* Now create phys -> abs mapping for IO */
 	for (i=0; i < _lmb->memory.cnt ;i++) {
 		unsigned long base = _lmb->memory.region[i].base;
 		unsigned long size = _lmb->memory.region[i].size;
 		unsigned long achunk = addr_to_chunk(base);
 		unsigned long end_achunk = addr_to_chunk(base+size);
+
+		if(_lmb->memory.region[i].type != LMB_IO_AREA)
+			continue;
+
 		_lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
 		for (; achunk < end_achunk ;) {
 			PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
 		}
 	}
+#endif /* CONFIG_MSCHUNKS */
 
 	return mem;
 }
+
+#ifdef DEBUG_PROM
+void
+prom_dump_mschunks_mapping(void)
+{
+        unsigned long offset = reloc_offset();
+	struct msChunks *_msChunks = PTRRELOC(&msChunks);
+	unsigned long chunk;
+
+        prom_print(RELOC("\nprom_dump_mschunks_mapping:\n"));
+        prom_print(RELOC("    msChunks.num_chunks         = 0x"));
+        prom_print_hex(_msChunks->num_chunks);
+	prom_print_nl();
+        prom_print(RELOC("    msChunks.chunk_size         = 0x"));
+        prom_print_hex(_msChunks->chunk_size);
+	prom_print_nl();
+        prom_print(RELOC("    msChunks.chunk_shift        = 0x"));
+        prom_print_hex(_msChunks->chunk_shift);
+	prom_print_nl();
+        prom_print(RELOC("    msChunks.chunk_mask         = 0x"));
+        prom_print_hex(_msChunks->chunk_mask);
+	prom_print_nl();
+        prom_print(RELOC("    msChunks.abs                = 0x"));
+        prom_print_hex(_msChunks->abs);
+	prom_print_nl();
+
+        prom_print(RELOC("    msChunks mapping:\n"));
+	for(chunk=0; chunk < _msChunks->num_chunks ;chunk++) {
+        	prom_print(RELOC("        phys 0x"));
+        	prom_print_hex(chunk);
+        	prom_print(RELOC(" -> abs 0x"));
+        	prom_print_hex(PTRRELOC(_msChunks->abs)[chunk]);
+		prom_print_nl();
+	}
+
+}
+#endif /* DEBUG_PROM */
 #endif /* CONFIG_MSCHUNKS */
+
+#ifdef DEBUG_PROM
+void
+prom_dump_lmb(void)
+{
+        unsigned long i;
+        unsigned long offset = reloc_offset();
+	struct lmb *_lmb  = PTRRELOC(&lmb);
+
+        prom_print(RELOC("\nprom_dump_lmb:\n"));
+        prom_print(RELOC("    memory.cnt                  = 0x"));
+        prom_print_hex(_lmb->memory.cnt);
+	prom_print_nl();
+        prom_print(RELOC("    memory.size                 = 0x"));
+        prom_print_hex(_lmb->memory.size);
+	prom_print_nl();
+        prom_print(RELOC("    memory.lcd_size             = 0x"));
+        prom_print_hex(_lmb->memory.lcd_size);
+	prom_print_nl();
+        for (i=0; i < _lmb->memory.cnt ;i++) {
+                prom_print(RELOC("    memory.region[0x"));
+		prom_print_hex(i);
+		prom_print(RELOC("].base       = 0x"));
+                prom_print_hex(_lmb->memory.region[i].base);
+		prom_print_nl();
+                prom_print(RELOC("                      .physbase = 0x"));
+                prom_print_hex(_lmb->memory.region[i].physbase);
+		prom_print_nl();
+                prom_print(RELOC("                      .size     = 0x"));
+                prom_print_hex(_lmb->memory.region[i].size);
+		prom_print_nl();
+                prom_print(RELOC("                      .type     = 0x"));
+                prom_print_hex(_lmb->memory.region[i].type);
+		prom_print_nl();
+        }
+
+	prom_print_nl();
+        prom_print(RELOC("    reserved.cnt                  = 0x"));
+        prom_print_hex(_lmb->reserved.cnt);
+	prom_print_nl();
+        prom_print(RELOC("    reserved.size                 = 0x"));
+        prom_print_hex(_lmb->reserved.size);
+	prom_print_nl();
+        prom_print(RELOC("    reserved.lcd_size             = 0x"));
+        prom_print_hex(_lmb->reserved.lcd_size);
+	prom_print_nl();
+        for (i=0; i < _lmb->reserved.cnt ;i++) {
+                prom_print(RELOC("    reserved.region[0x"));
+		prom_print_hex(i);
+		prom_print(RELOC("].base       = 0x"));
+                prom_print_hex(_lmb->reserved.region[i].base);
+		prom_print_nl();
+                prom_print(RELOC("                      .physbase = 0x"));
+                prom_print_hex(_lmb->reserved.region[i].physbase);
+		prom_print_nl();
+                prom_print(RELOC("                      .size     = 0x"));
+                prom_print_hex(_lmb->reserved.region[i].size);
+		prom_print_nl();
+                prom_print(RELOC("                      .type     = 0x"));
+                prom_print_hex(_lmb->reserved.region[i].type);
+		prom_print_nl();
+        }
+}
+#endif /* DEBUG_PROM */
+
 
 void
 prom_initialize_tce_table(void)
diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
--- a/arch/ppc64/kernel/rtasd.c	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc64/kernel/rtasd.c	Sun Apr 14 12:16:57 2002
@@ -224,7 +224,6 @@
 
 	cpu = 0;
 	set_cpus_allowed(current, 1UL << cpu_logical_map(cpu));
-	schedule();
 
 	while(1) {
 		do {
@@ -262,9 +261,7 @@
 
 
 		/* Check all cpus for pending events before sleeping*/
-		if (first_pass) {
-			schedule();
-		} else {
+		if (!first_pass) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((HZ*60/rtas_event_scan_rate) / 2);
 		}
@@ -277,7 +274,7 @@
 	return -EINVAL;
 }
 
-static void __init rtas_init(void)
+static int __init rtas_init(void)
 {
 	struct proc_dir_entry *rtas_dir, *entry;
 
@@ -296,6 +293,8 @@
 		printk(KERN_ERR "Failed to start RTAS daemon\n");
 
 	printk(KERN_ERR "RTAS daemon started\n");
+
+	return 0;
 }
 
 static int __init surveillance_setup(char *str)
diff -Nru a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c
--- a/arch/ppc64/kernel/semaphore.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/semaphore.c	Sun Apr 14 12:16:55 2002
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
+#include <asm/errno.h>
 
 /*
  * Atomically update sem->count.
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc64/kernel/setup.c	Sun Apr 14 12:16:58 2002
@@ -277,6 +277,9 @@
 	ppc_md.halt();
 }
 
+unsigned long ppc_proc_freq;
+unsigned long ppc_tb_freq;
+
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
 	unsigned long cpu_id = (unsigned long)v - 1;
@@ -286,10 +289,6 @@
 
 #ifdef CONFIG_SMP
 	if (cpu_id == NR_CPUS) {
-		unsigned long bogosum = smp_num_cpus * loops_per_jiffy;
-		seq_printf(m, "total bogomips\t: %lu.%02lu\n",
-			   bogosum/(500000/HZ),
-			   bogosum/(5000/HZ) % 100);
 
 		if (ppc_md.get_cpuinfo != NULL)
 			ppc_md.get_cpuinfo(m);
@@ -357,10 +356,6 @@
 
 	seq_printf(m, "revision\t: %hd.%hd\n", maj, min);
 	
-	seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
-		   loops_per_jiffy/(500000/HZ),
-		   loops_per_jiffy/(5000/HZ) % 100);
-
 	return 0;
 }
 
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc64/kernel/signal.c	Sun Apr 14 12:16:54 2002
@@ -35,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/ppcdebug.h>
 #include <asm/unistd.h>
+#include <asm/cacheflush.h>
 
 #define DEBUG_SIG 0
 
@@ -676,8 +677,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -722,7 +723,7 @@
 			case SIGSTOP:
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+				if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/signal32.c	Sun Apr 14 12:16:59 2002
@@ -1375,8 +1375,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -1416,7 +1416,7 @@
 			case SIGSTOP:
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+				if (!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
--- a/arch/ppc64/kernel/smp.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/smp.c	Sun Apr 14 12:16:59 2002
@@ -86,7 +86,11 @@
 /*
  * XICS only has a single IPI, so encode the messages per CPU
  */
-volatile unsigned long xics_ipi_message[NR_CPUS] = {0};
+struct xics_ipi_struct {
+	        volatile unsigned long value;
+} ____cacheline_aligned;
+
+struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
 #define smp_message_pass(t,m,d,w) ppc_md.smp_message_pass((t),(m),(d),(w))
 
@@ -322,10 +326,10 @@
 		if (target == MSG_ALL || target == i
 		    || (target == MSG_ALL_BUT_SELF
 			&& i != smp_processor_id())) {
-			set_bit(msg, &xics_ipi_message[i]);
+			set_bit(msg, &xics_ipi_message[i].value);
 			mb();
 			xics_cause_IPI(i);
-			}
+		}
 	}
 }
 
@@ -360,37 +364,6 @@
 	}
 }
 
-static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
-static task_t *new_task;
-
-/*
- * This function sends a 'task migration' IPI to another CPU.
- * Must be called from syscall contexts, with interrupts *enabled*.
- */
-void smp_migrate_task(int cpu, task_t *p)
-{
-	/*
-	 * The target CPU will unlock the migration spinlock:
-	 */
-	spin_lock(&migration_lock);
-	new_task = p;
-
-	smp_message_pass(cpu, PPC_MSG_MIGRATE_TASK, 0, 0);
-}
-
-/*
- * Task migration callback.
- */
-static void smp_task_migration_interrupt(void)
-{
-	task_t *p;
-
-	/* Should we ACK the IPI interrupt early? */
-	p = new_task;
-	spin_unlock(&migration_lock);
-	sched_task_migrated(p);
-}
-
 void smp_message_recv(int msg, struct pt_regs *regs)
 {
 	switch( msg ) {
@@ -401,9 +374,11 @@
 		/* XXX Do we have to do this? */
 		set_need_resched();
 		break;
+#if 0
 	case PPC_MSG_MIGRATE_TASK:
-		smp_task_migration_interrupt();
+		/* spare */
 		break;
+#endif
 #ifdef CONFIG_XMON
 	case PPC_MSG_XMON_BREAK:
 		xmon(regs);
@@ -418,17 +393,6 @@
 
 void smp_send_reschedule(int cpu)
 {
-	/*
-	 * This is only used if `cpu' is running an idle task,
-	 * so it will reschedule itself anyway...
-	 *
-	 * This isn't the case anymore since the other CPU could be
-	 * sleeping and won't reschedule until the next interrupt (such
-	 * as the timer).
-	 *  -- Cort
-	 */
-	/* This is only used if `cpu' is running an idle task,
-	   so it will reschedule itself anyway... */
 	smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0);
 }
 
diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c
--- a/arch/ppc64/kernel/stab.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/stab.c	Sun Apr 14 12:16:59 2002
@@ -18,10 +18,10 @@
 #include <asm/Naca.h>
 #include <asm/pmc.h>
 
-inline int make_ste(unsigned long stab, 
-		    unsigned long esid, unsigned long vsid);
-inline void make_slbe(unsigned long esid, unsigned long vsid,
-		      int large);
+int make_ste(unsigned long stab, 
+	     unsigned long esid, unsigned long vsid);
+void make_slbe(unsigned long esid, unsigned long vsid,
+	       int large);
 extern struct Naca *naca;
 
 /*
@@ -56,8 +56,7 @@
 /*
  * Create a segment table entry for the given esid/vsid pair.
  */ 
-inline int
-make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
+int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
 {
 	unsigned long entry, group, old_esid, castout_entry, i;
 	unsigned int global_entry;
@@ -146,11 +145,11 @@
 
 /*
  * Create a segment buffer entry for the given esid/vsid pair.
- */ 
-inline void make_slbe(unsigned long esid, unsigned long vsid, int large)
+ */
+void make_slbe(unsigned long esid, unsigned long vsid, int large)
 {
+	int kernel_segment = 0;
 	unsigned long entry, castout_entry;
-	slb_dword0 castout_esid_data;
 	union {
 		unsigned long word0;
 		slb_dword0    data;
@@ -159,7 +158,10 @@
 		unsigned long word0;
 		slb_dword1    data;
 	} vsid_data;
-	
+
+	if (REGION_ID(esid << SID_SHIFT) >= KERNEL_REGION_ID)
+		kernel_segment = 1;
+
 	/*
 	 * Find an empty entry, if one exists.
 	 */
@@ -175,6 +177,8 @@
 			vsid_data.data.kp = 1;
 			if (large)
 				vsid_data.data.l = 1;
+			if (kernel_segment)
+				vsid_data.data.c = 1;
 
 			esid_data.word0 = 0;
 			esid_data.data.esid = esid;
@@ -200,21 +204,13 @@
 	PMC_SW_PROCESSOR(stab_capacity_castouts); 
 
 	castout_entry = get_paca()->xStab_data.next_round_robin;
-	__asm__ __volatile__("slbmfee  %0,%1" 
-			     : "=r" (castout_esid_data) 
-			     : "r" (castout_entry)); 
-
 	entry = castout_entry; 
 	castout_entry++; 
-	if(castout_entry >= naca->slb_size) {
+	if (castout_entry >= naca->slb_size)
 		castout_entry = 1; 
-	}
 	get_paca()->xStab_data.next_round_robin = castout_entry;
 
-	/* Invalidate the old entry. */
-	castout_esid_data.v = 0; /* Set the class to 0 */
 	/* slbie not needed as the previous mapping is still valid. */
-	__asm__ __volatile__("slbie  %0" : : "r" (castout_esid_data)); 
 	
 	/* 
 	 * Write the new SLB entry.
@@ -224,6 +220,8 @@
 	vsid_data.data.kp = 1;
 	if (large)
 		vsid_data.data.l = 1;
+	if (kernel_segment)
+		vsid_data.data.c = 1;
 	
 	esid_data.word0 = 0;
 	esid_data.data.esid = esid;
@@ -300,7 +298,7 @@
 
 #define STAB_PRESSURE 0
 
-void flush_stab(void)
+void flush_stab(struct task_struct *tsk, struct mm_struct *mm)
 {
 	STE *stab = (STE *) get_paca()->xStab_data.virt;
 	unsigned char *segments = get_paca()->xSegments;
@@ -349,12 +347,57 @@
 		/* Force flush to complete.  */
 		__asm__ __volatile__ ("sync" : : : "memory");  
 	} else {
+/* XXX The commented out code will only work for 32 bit tasks */
+#if 1
 		unsigned long flags;
-
-		PMC_SW_PROCESSOR(stab_invalidations); 
-
 		__save_and_cli(flags);
 		__asm__ __volatile__("isync; slbia; isync":::"memory");
 		__restore_flags(flags);
+#else
+		union {
+			unsigned long word0;
+			slb_dword0 data;
+		} esid_data;
+		unsigned long esid;
+
+		__asm__ __volatile__("isync" : : : "memory");
+		for (esid = 0; esid < 16; esid++) {
+			esid_data.word0 = 0;
+			esid_data.data.esid = esid;
+			__asm__ __volatile__("slbie %0" : : "r" (esid_data));
+		}
+		__asm__ __volatile__("isync" : : : "memory");
+#endif
+
+		PMC_SW_PROCESSOR(stab_invalidations);
+
+		if (test_tsk_thread_flag(tsk, TIF_32BIT)) {
+			unsigned long esid, vsid;
+
+			for (esid = 0; esid < 16; esid++) {
+				vsid = get_vsid(mm->context, esid << SID_SHIFT);
+				make_slbe(esid, vsid, 0);
+			}
+		} else {
+			unsigned long pc = KSTK_EIP(tsk);
+			unsigned long stack = KSTK_ESP(tsk);
+			unsigned long pc_segment = pc & ~SID_MASK;
+			unsigned long stack_segment = stack & ~SID_MASK;
+			unsigned long vsid;
+
+			if (pc) {
+				if (REGION_ID(pc) >= KERNEL_REGION_ID)
+					BUG();
+				vsid = get_vsid(mm->context, pc);
+				make_slbe(GET_ESID(pc), vsid, 0);
+			}
+
+			if (stack && (pc_segment != stack_segment)) {
+				if (REGION_ID(stack) >= KERNEL_REGION_ID)
+					BUG();
+				vsid = get_vsid(mm->context, stack);
+				make_slbe(GET_ESID(stack), vsid, 0);
+			}
+		}
 	}
 }
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/sys_ppc32.c	Sun Apr 14 12:16:59 2002
@@ -932,8 +932,8 @@
 	err |= put_user(stat->ino, &statbuf->st_ino);
 	err |= put_user(stat->mode, &statbuf->st_mode);
 	err |= put_user(stat->nlink, &statbuf->st_nlink);
-	err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
-	err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
+	err |= put_user(stat->uid, &statbuf->st_uid);
+	err |= put_user(stat->gid, &statbuf->st_gid);
 	err |= put_user(stat->rdev, &statbuf->st_rdev);
 	if (stat->size > MAX_NON_LFS)
 		return -EOVERFLOW;
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c	Sun Apr 14 12:16:59 2002
+++ b/arch/ppc64/kernel/time.c	Sun Apr 14 12:16:59 2002
@@ -53,6 +53,7 @@
 #include <asm/nvram.h>
 #include <asm/cache.h>
 #include <asm/machdep.h>
+#include <asm/init.h>
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iSeries/HvCallXm.h>
 #endif
@@ -83,6 +84,7 @@
 unsigned long xtime_sync_interval;
 unsigned long tb_to_xs;
 unsigned      tb_to_us;
+unsigned long processor_freq;
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 
 struct gettimeofday_struct do_gtod;
@@ -97,6 +99,10 @@
 extern unsigned long prof_shift;
 extern char _stext;
 
+void ppc_adjtimex(void);
+
+static unsigned adjusting_time = 0;
+
 static inline void ppc_do_profile (unsigned long nip)
 {
 	if (!prof_buffer)
@@ -269,6 +275,8 @@
 			timer_sync_xtime( cur_tb );
 			timer_check_rtc();
 			write_unlock(&xtime_lock);
+			if ( adjusting_time && (time_adjust == 0) )
+				ppc_adjtimex();
 		}
 		paca->next_jiffy_update_tb += tb_ticks_per_jiffy;
 	}
@@ -386,13 +394,35 @@
  * fields itself.  This way, the fields which are used for 
  * do_settimeofday get updated too.
  */
-
-long ppc64_sys_stime(int * tptr)
+long ppc64_sys32_stime(int* tptr)
 {
 	int value;
 	struct timeval myTimeval;
 
-	PPCDBG(PPCDBG_SYS32, "ppc64_sys_stime - entered - tptr=%p, *tptr=0x%x \n", tptr, *tptr);
+	if (!capable(CAP_SYS_TIME))
+		return -EPERM;
+
+	if (get_user(value, tptr))
+		return -EFAULT;
+
+	myTimeval.tv_sec = value;
+	myTimeval.tv_usec = 0;
+
+	do_settimeofday(&myTimeval);
+
+	return 0;
+}
+
+/*
+ * This function is a copy of the architecture independent function
+ * but which calls do_settimeofday rather than setting the xtime
+ * fields itself.  This way, the fields which are used for 
+ * do_settimeofday get updated too.
+ */
+long ppc64_sys_stime(long* tptr)
+{
+	long value;
+	struct timeval myTimeval;
 
 	if (!capable(CAP_SYS_TIME))
 		return -EPERM;
@@ -405,7 +435,6 @@
 
 	do_settimeofday(&myTimeval);
 
-	PPCDBG(PPCDBG_SYS32, "ppc64_sys_stime - exiting w/ 0 \n");
 	return 0;
 }
 
@@ -426,6 +455,7 @@
 	tb_last_stamp = get_tb();
 	do_gtod.tb_orig_stamp = tb_last_stamp;
 	do_gtod.varp = &do_gtod.vars[0];
+	do_gtod.var_idx = 0;
 	do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
 	do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 	do_gtod.varp->tb_to_xs = tb_to_xs;
@@ -434,6 +464,8 @@
 	xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);
 	next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;
 
+	time_freq = 0;
+
 	xtime.tv_usec = 0;
 	last_rtc_update = xtime.tv_sec;
 	write_unlock_irqrestore(&xtime_lock, flags);
@@ -452,10 +484,12 @@
  * to microseconds to keep do_gettimeofday synchronized 
  * with ntpd.
 
- * Use the time_freq and time_offset computed by adjtimex to 
+ * Use the time_adjust, time_freq and time_offset computed by adjtimex to 
  * adjust the frequency.
 */
 
+/* #define DEBUG_PPC_ADJTIMEX 1 */
+
 void ppc_adjtimex(void)
 {
 	unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, new_tb_to_xs, new_xsec, new_stamp_xsec;
@@ -464,7 +498,12 @@
 	struct div_result divres; 
 	unsigned long flags;
 	struct gettimeofday_vars * temp_varp;
+	unsigned temp_idx;
+	long singleshot_ppm = 0;
 
+	/* Compute parts per million frequency adjustment to accomplish the time adjustment
+	   implied by time_offset to be applied over the elapsed time indicated by time_constant.
+	   Use SHIFT_USEC to get it into the same units as time_freq. */
 	if ( time_offset < 0 ) {
 		ltemp = -time_offset;
 		ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
@@ -476,8 +515,40 @@
 		ltemp <<= SHIFT_USEC - SHIFT_UPDATE;
 		ltemp >>= SHIFT_KG + time_constant;
 	}
-	delta_freq = time_freq + ltemp;
-
+	
+	/* If there is a single shot time adjustment in progress */
+	if ( time_adjust ) {
+#ifdef DEBUG_PPC_ADJTIMEX
+		printk("ppc_adjtimex: ");
+		if ( adjusting_time == 0 )
+			printk("starting ");
+		printk("single shot time_adjust = %ld\n", time_adjust);
+#endif	
+	
+		adjusting_time = 1;
+		
+		/* Compute parts per million frequency adjustment to match time_adjust */
+		singleshot_ppm = tickadj * HZ;	
+		/* The adjustment should be tickadj*HZ to match the code in linux/kernel/timer.c, but
+		   experiments show that this is too large. 3/4 of tickadj*HZ seems about right */
+		singleshot_ppm -= singleshot_ppm / 4;
+		/* Use SHIFT_USEC to get it into the same units as time_freq */	
+		singleshot_ppm <<= SHIFT_USEC;
+		if ( time_adjust < 0 )
+			singleshot_ppm = -singleshot_ppm;
+	}
+	else {
+#ifdef DEBUG_PPC_ADJTIMEX
+		if ( adjusting_time )
+			printk("ppc_adjtimex: ending single shot time_adjust\n");
+#endif
+		adjusting_time = 0;
+	}
+	
+	/* Add up all of the frequency adjustments */
+	delta_freq = time_freq + ltemp + singleshot_ppm;
+	
+	/* Compute a new value for tb_ticks_per_sec based on the frequency adjustment */
 	den = 1000000 * (1 << (SHIFT_USEC - 8));
 	if ( delta_freq < 0 ) {
 		tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den;
@@ -487,6 +558,16 @@
 		tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den;
 		new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta;
 	}
+	
+#ifdef DEBUG_PPC_ADJTIMEX
+	printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm);
+	printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld  new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec);
+#endif
+				
+	/* Compute a new value of tb_to_xs (used to convert tb to microseconds and a new value of 
+	   stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp.  This 
+	   new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs)
+	   which guarantees that the current time remains the same */ 
 	tb_ticks = get_tb() - do_gtod.tb_orig_stamp;
 	div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres );
 	new_tb_to_xs = divres.result_low;
@@ -496,14 +577,23 @@
 	old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );
 	new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
 
-	if (do_gtod.varp == &do_gtod.vars[0])
+	/* There are two copies of tb_to_xs and stamp_xsec so that no lock is needed to access and use these
+	   values in do_gettimeofday.  We alternate the copies and as long as a reasonable time elapses between
+	   changes, there will never be inconsistent values.  ntpd has a minimum of one minute between updates */
+
+	if (do_gtod.var_idx == 0) {
 		temp_varp = &do_gtod.vars[1];
-	else
+		temp_idx  = 1;
+	}
+	else {
 		temp_varp = &do_gtod.vars[0];
+		temp_idx  = 0;
+	}
 	temp_varp->tb_to_xs = new_tb_to_xs;
 	temp_varp->stamp_xsec = new_stamp_xsec;
 	mb();
 	do_gtod.varp = temp_varp;
+	do_gtod.var_idx = temp_idx;
 
 	write_unlock_irqrestore( &xtime_lock, flags );
 
diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
--- a/arch/ppc64/kernel/udbg.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/kernel/udbg.c	Sun Apr 14 12:16:55 2002
@@ -209,10 +209,10 @@
 
 /* Special print used by PPCDBG() macro */
 void
-udbg_ppcdbg(unsigned long flags, const char *fmt, ...)
+udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...)
 {
 	unsigned long flags;
-	unsigned long active_debugs = flags & naca->debug_switch;
+	unsigned long active_debugs = debug_flags & naca->debug_switch;
 
 	if ( active_debugs ) {
 		va_list ap;
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	Sun Apr 14 12:16:54 2002
+++ b/arch/ppc64/kernel/xics.c	Sun Apr 14 12:16:54 2002
@@ -84,7 +84,7 @@
 unsigned long long intr_base = 0;
 int xics_irq_8259_cascade = 0;
 int xics_irq_8259_cascade_real = 0;
-unsigned int default_server = 0;
+unsigned int default_server = 0xFF;
 unsigned int default_distrib_server = 0;
 
 /* RTAS service tokens */
@@ -197,9 +197,7 @@
 }
 
 void
-xics_mask_and_ack_irq(
-	u_int	irq
-	)
+xics_mask_and_ack_irq(u_int	irq)
 {
 	int cpu = smp_processor_id();
 
@@ -241,27 +239,39 @@
 	return irq;
 }
 
+struct xics_ipi_struct {
+	volatile unsigned long value;
+} ____cacheline_aligned;
+
+extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
 #ifdef CONFIG_SMP
 void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
 {
-	extern volatile unsigned long xics_ipi_message[];
 	int cpu = smp_processor_id();
 
 	ops->qirr_info(cpu, 0xff);
-	while (xics_ipi_message[cpu]) {
-		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu])) {
+	while (xics_ipi_message[cpu].value) {
+		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu].value)) {
 			mb();
 			smp_message_recv(PPC_MSG_CALL_FUNCTION, regs);
 		}
-		if (test_and_clear_bit(PPC_MSG_RESCHEDULE, &xics_ipi_message[cpu])) {
+		if (test_and_clear_bit(PPC_MSG_RESCHEDULE, &xics_ipi_message[cpu].value)) {
 			mb();
 			smp_message_recv(PPC_MSG_RESCHEDULE, regs);
 		}
-		if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, &xics_ipi_message[cpu])) {
+#if 0
+		if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, &xics_ipi_message[cpu].value)) {
 			mb();
 			smp_message_recv(PPC_MSG_MIGRATE_TASK, regs);
 		}
+#endif
+#ifdef CONFIG_XMON
+		if (test_and_clear_bit(PPC_MSG_XMON_BREAK, &xics_ipi_message[cpu].value)) {
+			mb();
+			smp_message_recv(PPC_MSG_XMON_BREAK, regs);
+		}
+#endif
 	}
 }
 
diff -Nru a/arch/ppc64/lib/checksum.S b/arch/ppc64/lib/checksum.S
--- a/arch/ppc64/lib/checksum.S	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc64/lib/checksum.S	Sun Apr 14 12:16:58 2002
@@ -17,8 +17,6 @@
 #include <asm/errno.h>
 #include "../kernel/ppc_asm.tmpl"
 
-	.text
-
 /*
  * ip_fast_csum(r3=buf, r4=len) -- Optimized for IP header
  * len is in words and is always >= 5.
diff -Nru a/arch/ppc64/lib/string.S b/arch/ppc64/lib/string.S
--- a/arch/ppc64/lib/string.S	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/lib/string.S	Sun Apr 14 12:16:56 2002
@@ -120,54 +120,6 @@
 	subf	r3,r3,r4
 	blr
 
-/*
- * Use dcbz on the complete cache lines in the destination
- * to set them to zero.  This requires that the destination
- * area is cacheable.  -- paulus
- */
-_GLOBAL(cacheable_memzero)
-	mr	r5,r4
-	li	r4,0
-	addi	r6,r3,-4
-	cmplwi	0,r5,4
-	blt	7f
-	stwu	r4,4(r6)
-	beqlr
-	andi.	r0,r6,3
-	add	r5,r0,r5
-	subf	r6,r0,r6
-	clrlwi	r7,r6,32-LG_CACHELINE_BYTES
-	add	r8,r7,r5
-	srwi	r9,r8,LG_CACHELINE_BYTES
-	addic.	r9,r9,-1	/* total number of complete cachelines */
-	ble	2f
-	xori	r0,r7,CACHELINE_MASK & ~3
-	srwi.	r0,r0,2
-	beq	3f
-	mtctr	r0
-4:	stwu	r4,4(r6)
-	bdnz	4b
-3:	mtctr	r9
-	li	r7,4
-10:	dcbz	r7,r6
-	addi	r6,r6,CACHELINE_BYTES
-	bdnz	10b
-	clrlwi	r5,r8,32-LG_CACHELINE_BYTES
-	addi	r5,r5,4
-2:	srwi	r0,r5,2
-	mtctr	r0
-	bdz	6f
-1:	stwu	r4,4(r6)
-	bdnz	1b
-6:	andi.	r5,r5,3
-7:	cmpwi	0,r5,0
-	beqlr
-	mtctr	r5
-	addi	r6,r6,3
-8:	stbu	r4,1(r6)
-	bdnz	8b
-	blr
-
 _GLOBAL(memset)
 	rlwimi	r4,r4,8,16,23
 	rlwimi	r4,r4,16,0,15
@@ -192,91 +144,6 @@
 8:	stbu	r4,1(r6)
 	bdnz	8b
 	blr
-
-_GLOBAL(bcopy)
-	mr	r6,r3
-	mr	r3,r4
-	mr	r4,r6
-	b	.memcpy
-
-/*
- * This version uses dcbz on the complete cache lines in the
- * destination area to reduce memory traffic.  This requires that
- * the destination area is cacheable.
- * We only use this version if the source and dest don't overlap.
- * -- paulus.
- */
-_GLOBAL(cacheable_memcpy)
-	add	r7,r3,r5		/* test if the src & dst overlap */
-	add	r8,r4,r5
-	cmplw	0,r4,r7
-	cmplw	1,r3,r8
-	crand	0,0,4			/* cr0.lt &= cr1.lt */
-	blt	.memcpy			/* if regions overlap */
-
-	addi	r4,r4,-4
-	addi	r6,r3,-4
-	neg	r0,r3
-	andi.	r0,r0,CACHELINE_MASK	/* # bytes to start of cache line */
-	beq	58f
-
-	cmplw	0,r5,r0			/* is this more than total to do? */
-	blt	63f			/* if not much to do */
-	andi.	r8,r0,3			/* get it word-aligned first */
-	subf	r5,r0,r5
-	mtctr	r8
-	beq+	61f
-70:	lbz	r9,4(r4)		/* do some bytes */
-	stb	r9,4(r6)
-	addi	r4,r4,1
-	addi	r6,r6,1
-	bdnz	70b
-61:	srwi.	r0,r0,2
-	mtctr	r0
-	beq	58f
-72:	lwzu	r9,4(r4)		/* do some words */
-	stwu	r9,4(r6)
-	bdnz	72b
-
-58:	srwi.	r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
-	clrlwi	r5,r5,32-LG_CACHELINE_BYTES
-	li	r11,4
-	mtctr	r0
-	beq	63f
-53:
-	dcbz	r11,r6
-	COPY_16_BYTES
-#if CACHE_LINE_SIZE >= 32
-	COPY_16_BYTES
-#if CACHE_LINE_SIZE >= 64
-	COPY_16_BYTES
-	COPY_16_BYTES
-#if CACHE_LINE_SIZE >= 128
-	COPY_16_BYTES
-	COPY_16_BYTES
-	COPY_16_BYTES
-	COPY_16_BYTES
-#endif
-#endif
-#endif
-	bdnz	53b
-
-63:	srwi.	r0,r5,2
-	mtctr	r0
-	beq	64f
-30:	lwzu	r0,4(r4)
-	stwu	r0,4(r6)
-	bdnz	30b
-
-64:	andi.	r0,r5,3
-	mtctr	r0
-	beq+	65f
-40:	lbz	r0,4(r4)
-	stb	r0,4(r6)
-	addi	r4,r4,1
-	addi	r6,r6,1
-	bdnz	40b
-65:	blr
 
 _GLOBAL(memmove)
 	cmplw	0,r3,r4
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	Sun Apr 14 12:16:55 2002
+++ b/arch/ppc64/mm/init.c	Sun Apr 14 12:16:55 2002
@@ -113,23 +113,6 @@
  */
 mmu_gather_t     mmu_gathers[NR_CPUS];
 
-int do_check_pgt_cache(int low, int high)
-{
-	int freed = 0;
-
-	if (pgtable_cache_size > high) {
-		do {
-			if (pgd_quicklist)
-				free_page((unsigned long)pgd_alloc_one_fast(0)), ++freed;
-			if (pmd_quicklist)
-				free_page((unsigned long)pmd_alloc_one_fast(0, 0)), ++freed;
-			if (pte_quicklist)
-				free_page((unsigned long)pte_alloc_one_fast(0, 0)), ++freed;
-		} while (pgtable_cache_size > low);
-	}
-	return freed;	
-}
-
 void show_mem(void)
 {
 	int i,free = 0,total = 0,reserved = 0;
@@ -155,7 +138,6 @@
 	printk("%d reserved pages\n",reserved);
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
-	printk("%d pages in page table cache\n",(int)pgtable_cache_size);
 	show_buffers();
 }
 
@@ -260,7 +242,7 @@
 		spin_lock(&ioremap_mm.page_table_lock);
 		pgdp = pgd_offset_i(ea);
 		pmdp = pmd_alloc(&ioremap_mm, pgdp, ea);
-		ptep = pte_alloc(&ioremap_mm, pmdp, ea);
+		ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
 
 		pa = absolute_to_phys(pa);
 		set_pte(ptep, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
@@ -271,7 +253,7 @@
 		 * entry in the hardware page table. 
  		 */
 		vsid = get_kernel_vsid(ea);
-		make_pte(htab_data.htab,
+		ppc_md.make_pte(htab_data.htab,
 			(vsid << 28) | (ea & 0xFFFFFFF), // va (NOT the ea)
 			pa, 
 			_PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX,
@@ -280,42 +262,37 @@
 }
 
 void
-local_flush_tlb_all(void)
-{
-	/* Implemented to just flush the vmalloc area.
-	 * vmalloc is the only user of flush_tlb_all.
-	 */
-	local_flush_tlb_range( NULL, VMALLOC_START, VMALLOC_END );
-}
-
-void
-local_flush_tlb_mm(struct mm_struct *mm)
+flush_tlb_mm(struct mm_struct *mm)
 {
-	if ( mm->map_count ) {
+	if (mm->map_count) {
 		struct vm_area_struct *mp;
-		for ( mp = mm->mmap; mp != NULL; mp = mp->vm_next )
-			local_flush_tlb_range( mm, mp->vm_start, mp->vm_end );
-	}
-	else	/* MIKEC: It is not clear why this is needed */
+		for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
+			__flush_tlb_range(mm, mp->vm_start, mp->vm_end);
+	} else {
+		/* MIKEC: It is not clear why this is needed */
 		/* paulus: it is needed to clear out stale HPTEs
 		 * when an address space (represented by an mm_struct)
 		 * is being destroyed. */
-		local_flush_tlb_range( mm, USER_START, USER_END );
-}
+		__flush_tlb_range(mm, USER_START, USER_END);
+	}
 
+	/* XXX are there races with checking cpu_vm_mask? - Anton */
+	mm->cpu_vm_mask = 0;
+}
 
 /*
  * Callers should hold the mm->page_table_lock
  */
 void
-local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
 	unsigned long context = 0;
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *ptep;
 	pte_t pte;
-	
+	int local = 0;
+
 	switch( REGION_ID(vmaddr) ) {
 	case VMALLOC_REGION_ID:
 		pgd = pgd_offset_k( vmaddr );
@@ -326,28 +303,34 @@
 	case USER_REGION_ID:
 		pgd = pgd_offset( vma->vm_mm, vmaddr );
 		context = vma->vm_mm->context;
+
+		/* XXX are there races with checking cpu_vm_mask? - Anton */
+		if (vma->vm_mm->cpu_vm_mask == (1 << smp_processor_id()))
+			local = 1;
+
 		break;
 	default:
-		panic("local_flush_tlb_page: invalid region 0x%016lx", vmaddr);
+		panic("flush_tlb_page: invalid region 0x%016lx", vmaddr);
 	
 	}
 
-
 	if (!pgd_none(*pgd)) {
 		pmd = pmd_offset(pgd, vmaddr);
 		if (!pmd_none(*pmd)) {
-			ptep = pte_offset(pmd, vmaddr);
+			ptep = pte_offset_kernel(pmd, vmaddr);
 			/* Check if HPTE might exist and flush it if so */
 			pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0));
 			if ( pte_val(pte) & _PAGE_HASHPTE ) {
-				flush_hash_page(context, vmaddr, pte);
+				flush_hash_page(context, vmaddr, pte, local);
 			}
 		}
 	}
 }
 
+struct tlb_batch_data tlb_batch_array[NR_CPUS][MAX_BATCH_FLUSH];
+
 void
-local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
+__flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -355,6 +338,9 @@
 	pte_t pte;
 	unsigned long pgd_end, pmd_end;
 	unsigned long context;
+	int i = 0;
+	struct tlb_batch_data *ptes = &tlb_batch_array[smp_processor_id()][0];
+	int local = 0;
 
 	if ( start >= end )
 		panic("flush_tlb_range: start (%016lx) greater than end (%016lx)\n", start, end );
@@ -374,6 +360,12 @@
 	case USER_REGION_ID:
 		pgd = pgd_offset( mm, start );
 		context = mm->context;
+
+		/* XXX are there races with checking cpu_vm_mask? - Anton */
+		if (mm->cpu_vm_mask == (1 << smp_processor_id())) {
+			local = 1;
+		}
+
 		break;
 	default:
 		panic("flush_tlb_range: invalid region for start (%016lx) and end (%016lx)\n", start, end);
@@ -391,12 +383,21 @@
 				if ( pmd_end > end )
 					pmd_end = end;
 				if ( !pmd_none( *pmd ) ) {
-					ptep = pte_offset( pmd, start );
+					ptep = pte_offset_kernel( pmd, start );
 					do {
 						if ( pte_val(*ptep) & _PAGE_HASHPTE ) {
 							pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0));
-							if ( pte_val(pte) & _PAGE_HASHPTE )
-								flush_hash_page( context, start, pte );
+							if ( pte_val(pte) & _PAGE_HASHPTE ) {
+								ptes->pte = pte;
+								ptes->addr = start;
+								ptes++;
+								i++;
+								if (i == MAX_BATCH_FLUSH) {
+									flush_hash_range(context, MAX_BATCH_FLUSH, local);
+									i = 0;
+									ptes = &tlb_batch_array[smp_processor_id()][0];
+								}
+							}
 						}
 						start += PAGE_SIZE;
 						++ptep;
@@ -411,6 +412,9 @@
 			start = pgd_end;
 		++pgd;
 	} while ( start < end );
+
+	if (i)
+		flush_hash_range(context, i, local);
 }
 
 
@@ -517,8 +521,14 @@
 
 	/* add all physical memory to the bootmem map */
 	for (i=0; i < lmb.memory.cnt ;i++) {
-		unsigned long physbase = lmb.memory.region[i].physbase;
-		unsigned long size = lmb.memory.region[i].size;
+		unsigned long physbase, size;
+		unsigned long type = lmb.memory.region[i].type;
+
+		if ( type != LMB_MEMORY_AREA )
+			continue;
+
+		physbase = lmb.memory.region[i].physbase;
+		size = lmb.memory.region[i].size;
 		free_bootmem(physbase, size);
 	}
 	/* reserve the sections we're already using */
@@ -559,6 +569,8 @@
 extern unsigned long dprof_len;
 extern unsigned int * dprof_buffer;
 
+void initialize_paca_hardware_interrupt_stack(void);
+
 void __init mem_init(void)
 {
 	extern char *sysmap; 
@@ -611,8 +623,8 @@
 	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
 	mem_init_done = 1;
 
-    /* set the last page of each hardware interrupt stack to be protected       */
-    initialize_paca_hardware_interrupt_stack();
+	/* set the last page of each hardware interrupt stack to be protected */
+	initialize_paca_hardware_interrupt_stack();
 
 #ifdef CONFIG_PPC_ISERIES
 	create_virtual_bus_tce_table();
@@ -660,4 +672,35 @@
 
 	maddr = (unsigned long)page_address(page) + (addr & ~PAGE_MASK);
 	flush_icache_range(maddr, maddr + len);
+}
+
+extern pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea);
+int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
+		pte_t *ptep);
+
+/*
+ * This is called at the end of handling a user page fault, when the
+ * fault has been handled by updating a PTE in the linux page tables.
+ * We use it to preload an HPTE into the hash table corresponding to
+ * the updated linux PTE.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
+		      pte_t pte)
+{
+	unsigned long vsid;
+	void *pgdir;
+	pte_t *ptep;
+
+	/* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
+	if (!pte_young(pte))
+		return;
+
+	pgdir = vma->vm_mm->pgd;
+	if (pgdir == NULL)
+		return;
+
+	ptep = find_linux_pte(pgdir, ea);
+	vsid = get_vsid(vma->vm_mm->context, ea);
+
+	__hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep);
 }
diff -Nru a/arch/ppc64/vmlinux.lds b/arch/ppc64/vmlinux.lds
--- a/arch/ppc64/vmlinux.lds	Sun Apr 14 12:16:56 2002
+++ b/arch/ppc64/vmlinux.lds	Sun Apr 14 12:16:56 2002
@@ -109,8 +109,10 @@
 	*(.initcall7.init)
   }
   __initcall_end = .;
-
-
+  . = ALIGN(32);
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
   . = ALIGN(4096);
   __init_end = .;
 
diff -Nru a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
--- a/arch/ppc64/xmon/start.c	Sun Apr 14 12:16:58 2002
+++ b/arch/ppc64/xmon/start.c	Sun Apr 14 12:16:58 2002
@@ -7,12 +7,11 @@
  *      2 of the License, or (at your option) any later version.
  */
 #include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sysrq.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/page.h>
-#include <linux/pmu.h>
-#include <linux/kernel.h>
-#include <linux/sysrq.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
 
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	Sun Apr 14 12:16:57 2002
+++ b/arch/ppc64/xmon/xmon.c	Sun Apr 14 12:16:57 2002
@@ -12,6 +12,8 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
+#include <linux/mm.h>
+#include <linux/reboot.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
 #include <asm/prom.h>
@@ -22,13 +24,9 @@
 #include <asm/mmu_context.h>
 #include <asm/Naca.h>
 #include <asm/Paca.h>
+#include <asm/ppcdebug.h>
 #include "nonstdio.h"
 #include "privinst.h"
-#include <linux/mm.h>
-
-#include <asm/ppcdebug.h>
-
-#include <asm/Paca.h>
 
 #define scanhex	xmon_scanhex
 #define skipbl	xmon_skipbl
@@ -132,8 +130,6 @@
 static void mem_map_lock_pages(void);
 static void mem_map_check_hash(void);
 static void mem_check_dup_rpn (void);
-static void show_task(struct task_struct * p);
-static void xmon_show_state(void);
 static void debug_trace(void);
 
 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);
@@ -181,6 +177,7 @@
   T	Enable/Disable PPCDBG flags\n\
   x	exit monitor\n\
   z	reboot\n\
+  Z	halt\n\
 ";
 
 static int xmon_trace[NR_CPUS];
@@ -262,8 +259,10 @@
 
 static inline void disable_surveillance(void)
 {
+#ifndef CONFIG_PPC_ISERIES
         rtas_call(rtas_token("set-indicator"), 3, 1, NULL, SURVEILLANCE_TOKEN,
 		  0, 0);
+#endif
 }
 
 void
@@ -620,8 +619,13 @@
 		}
 		switch (cmd) {
 		case 'z':
+			printf("Rebooting machine now...");
 			machine_restart(NULL);
 			break;
+		case 'Z':
+			printf("Halting machine now...");
+			machine_halt();
+			break;
 		case 'm':
 			cmd = inchar();
 			switch (cmd) {
@@ -710,7 +714,7 @@
 			printf(help_string);
 			break;
 		case 'p':
-			xmon_show_state();
+			show_state();
 			break;
 		case 'b':
 			bpt_cmds();
@@ -1211,7 +1215,7 @@
 
 	instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
 	instrs[1] = 0x4e800020;
-	opd[0] = instrs;
+	opd[0] = (unsigned long)instrs;
 	opd[1] = 0;
 	opd[2] = 0;
 	store_inst(instrs);
@@ -1230,7 +1234,7 @@
 
 	instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
 	instrs[1] = 0x4e800020;
-	opd[0] = instrs;
+	opd[0] = (unsigned long)instrs;
 	opd[1] = 0;
 	opd[2] = 0;
 	store_inst(instrs);
@@ -2797,111 +2801,6 @@
 	}
 
 	printf("\nDone -------------------\n");
-}
-
-
-
-static void show_task(struct task_struct * p)
-{
-	/* unsigned long free = 0;  --Unused */
-	int state;
-	static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" };
-
-	printf("--------------------------------------------------------------------------\n");
-	printf("%-11.11s pid: %5.5lx ppid: %5.5lx state: ", 
-	       p->comm, p->pid, p->p_pptr->pid);
-	state = p->state ? ffz(~p->state) + 1 : 0;
-	if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *))
-		printf(stat_nam[state]);
-	else
-		printf(" ");
-	if (p == current)
-		printf(" pc: current task       ");
-	else
-		printf(" pc: 0x%16.16lx ", thread_saved_pc(&p->thread));
-
-	if (p->p_cptr)
-		printf("%5d ", p->p_cptr->pid);
-	else
-		printf("      ");
-	if (!p->mm)
-		printf(" (L-TLB) ");
-	else
-		printf(" (NOTLB) ");
-	if (p->p_ysptr)
-		printf("%7d", p->p_ysptr->pid);
-	else
-		printf("       ");
-	if (p->p_osptr)
-		printf(" %5d\n", p->p_osptr->pid);
-	else
-		printf("\n");
-
-	{
-		struct sigqueue *q;
-		char s[sizeof(sigset_t)*2+1], b[sizeof(sigset_t)*2+1]; 
-
-		render_sigset_t(&p->pending.signal, s);
-		render_sigset_t(&p->blocked, b);
-		printf("            sig: %d %s %s :", signal_pending(p), s, b);
-		for (q = p->pending.head; q ; q = q->next)
-			printf(" %d", q->info.si_signo);
-		printf(" X\n");
-	}
-
-	printf("            pers   : %lx  current : %lx", 
-	       p->personality, p);
-	printf("\n");
-
-	printf("            thread : 0x%16.16lx  ksp   : 0x%16.16lx\n", 
-	       &(p->thread), (p->thread.ksp));
-	printf("            pgdir : 0x%16.16lx\n", (p->thread.pgdir));
-	printf("            regs   : 0x%16.16lx  sysc  : 0x%16.16lx\n", 
-	       (p->thread.regs), (p->thread.last_syscall));
-	if(p->thread.regs) {
-	  printf("            nip    : 0x%16.16lx  msr   : 0x%16.16lx\n", 
-		 ((p->thread.regs)->nip), ((p->thread.regs)->msr)); 
-	  printf("            ctr    : 0x%16.16lx  link  : 0x%16.16lx\n", 
-		 ((p->thread.regs)->ctr), ((p->thread.regs)->link));
-	  printf("            xer    : 0x%16.16lx  ccr   : 0x%16.16lx\n", 
-		 ((p->thread.regs)->xer), ((p->thread.regs)->ccr)); 
-	  printf("            trap   : 0x%16.16lx\n", 
-		 ((p->thread.regs)->trap));
-	  printf("            dar    : 0x%16.16lx  dsis  : 0x%16.16lx\n", 
-		 ((p->thread.regs)->dar), ((p->thread.regs)->dsisr));
-	  printf("            rslt   : 0x%16.16lx  org3  : 0x%16.16lx\n", 
-		 ((p->thread.regs)->result), (p->thread.regs->orig_gpr3));
-	}
-
-	if(p->mm) {
-	  struct mm_struct *mm = p->mm; 
-	  printf("            mm     : 0x%16.16lx  pgd   : 0x%16.16lx\n", 
-		 mm, mm->pgd);
-	  printf("            context: 0x%16.16lx  mmap  : 0x%16.16lx\n", 
-		 mm->context, mm->mmap);
-	  
-	  printf("\n");
-	}
-
-}
-
-static void xmon_show_state(void)
-{
-	struct task_struct *p;
-
-#if (BITS_PER_LONG == 32)
-	printf("\n"
-	       "                         free                        sibling\n");
-	printf("task name   st PC              stack   pid father child younger older\n");
-#else
-	printf("\n"
-	       "                                 free                        sibling\n");
-	printf("  task                 PC        stack   pid father child younger older\n");
-#endif
-	read_lock(&tasklist_lock);
-	for_each_task(p)
-		show_task(p);
-	read_unlock(&tasklist_lock);
 }
 
 static void debug_trace(void) {
diff -Nru a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
--- a/arch/s390/kernel/s390_ksyms.c	Sun Apr 14 12:16:55 2002
+++ b/arch/s390/kernel/s390_ksyms.c	Sun Apr 14 12:16:55 2002
@@ -44,7 +44,7 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 /*
diff -Nru a/arch/s390x/kernel/s390_ksyms.c b/arch/s390x/kernel/s390_ksyms.c
--- a/arch/s390x/kernel/s390_ksyms.c	Sun Apr 14 12:16:57 2002
+++ b/arch/s390x/kernel/s390_ksyms.c	Sun Apr 14 12:16:57 2002
@@ -47,7 +47,7 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strsep);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 /*
diff -Nru a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
--- a/arch/sh/kernel/sh_ksyms.c	Sun Apr 14 12:16:56 2002
+++ b/arch/sh/kernel/sh_ksyms.c	Sun Apr 14 12:16:56 2002
@@ -39,9 +39,6 @@
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 
-EXPORT_SYMBOL(simple_strtol);
-
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
diff -Nru a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
--- a/arch/sparc/kernel/ioport.c	Sun Apr 14 12:17:00 2002
+++ b/arch/sparc/kernel/ioport.c	Sun Apr 14 12:17:00 2002
@@ -161,7 +161,7 @@
 static void *_sparc_alloc_io(unsigned int busno, unsigned long phys,
     unsigned long size, char *name)
 {
-	static int printed_full = 0;
+	static int printed_full;
 	struct xresource *xres;
 	struct resource *res;
 	char *tack;
diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
--- a/arch/sparc/kernel/irq.c	Sun Apr 14 12:16:55 2002
+++ b/arch/sparc/kernel/irq.c	Sun Apr 14 12:16:55 2002
@@ -91,7 +91,7 @@
  */
 #define MAX_STATIC_ALLOC	4
 struct irqaction static_irqaction[MAX_STATIC_ALLOC];
-int static_irq_count = 0;
+int static_irq_count;
 
 struct irqaction *irq_action[NR_IRQS+1] = {
 	  NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
--- a/arch/sparc/kernel/pcic.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc/kernel/pcic.c	Sun Apr 14 12:16:54 2002
@@ -185,7 +185,7 @@
  * Only one PCIC per IIep,
  * and since we have no SMP IIep, only one per system.
  */
-static int pcic0_up = 0;
+static int pcic0_up;
 static struct linux_pcic pcic0;
 
 unsigned int pcic_regs;
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c	Sun Apr 14 12:16:56 2002
+++ b/arch/sparc/kernel/process.c	Sun Apr 14 12:16:56 2002
@@ -63,9 +63,9 @@
 	for (;;) {
 		if (ARCH_SUN4C_SUN4) {
 			static int count = HZ;
-			static unsigned long last_jiffies = 0;
-			static unsigned long last_faults = 0;
-			static unsigned long fps = 0;
+			static unsigned long last_jiffies;
+			static unsigned long last_faults;
+			static unsigned long fps;
 			unsigned long now;
 			unsigned long faults;
 			unsigned long flags;
@@ -83,7 +83,7 @@
 				fps = (fps + (faults - last_faults)) >> 1;
 				last_faults = faults;
 #if 0
-				printk("kernel faults / second = %d\n", fps);
+				printk("kernel faults / second = %ld\n", fps);
 #endif
 				if (fps >= SUN4C_FAULT_HIGH) {
 					sun4c_grow_kernel_ring();
diff -Nru a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
--- a/arch/sparc/kernel/ptrace.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc/kernel/ptrace.c	Sun Apr 14 12:16:58 2002
@@ -278,6 +278,7 @@
 	unsigned long data = regs->u_regs[UREG_I3];
 	unsigned long addr2 = regs->u_regs[UREG_I4];
 	struct task_struct *child;
+	int ret;
 
 	lock_kernel();
 #ifdef DEBUG_PTRACE
@@ -335,20 +336,13 @@
 		pt_succ_return(regs, 0);
 		goto out_tsk;
 	}
-	if (!(child->ptrace & PT_PTRACED)) {
-		pt_error_return(regs, ESRCH);
-		goto out_tsk;
-	}
-	if(child->state != TASK_STOPPED) {
-		if(request != PTRACE_KILL) {
-			pt_error_return(regs, ESRCH);
-			goto out_tsk;
-		}
-	}
-	if(child->p_pptr != current) {
-		pt_error_return(regs, ESRCH);
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0) {
+		pt_error_return(regs, -ret);
 		goto out_tsk;
 	}
+
 	switch(request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
diff -Nru a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
--- a/arch/sparc/kernel/setup.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc/kernel/setup.c	Sun Apr 14 12:16:54 2002
@@ -47,8 +47,6 @@
 #include <asm/hardirq.h>
 #include <asm/machines.h>
 
-#undef PROM_DEBUG_CONSOLE
-
 struct screen_info screen_info = {
 	0, 0,			/* orig-x, orig-y */
 	0,			/* unused */
@@ -134,6 +132,19 @@
 	}
 }
 
+static void
+prom_console_write(struct console *con, const char *s, unsigned n)
+{
+	prom_printf("%s", s);
+}
+
+static struct console prom_debug_console = {
+	name:		"debug",
+	write:		prom_console_write,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
 int obp_system_intr(void)
 {
 	if (boot_flags & BOOTME_KGDB) {
@@ -166,6 +177,10 @@
 		prom_printf("boot_flags_init: Halt!\n");
 		prom_halt();
 		break;
+	case 'p':
+		/* Use PROM debug console. */
+		register_console(&prom_debug_console);
+		break;
 	default:
 		printk("Unknown boot switch (-%c)\n", c);
 		break;
@@ -280,21 +295,6 @@
 
 struct pt_regs fake_swapper_regs;
 
-#ifdef PROM_DEBUG_CONSOLE
-static void
-prom_console_write(struct console *con, const char *s, unsigned n)
-{
-	prom_printf("%s", s);
-}
-
-static struct console prom_console = {
-	name:		"debug",
-	write:		prom_console_write,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
-};
-#endif
-
 extern void paging_init(void);
 
 void __init setup_arch(char **cmdline_p)
@@ -348,9 +348,6 @@
 		printk("UNKNOWN!\n");
 		break;
 	};
-#ifdef PROM_DEBUG_CONSOLE
-	register_console(&prom_console);
-#endif
 
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
@@ -381,7 +378,7 @@
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
 	ROOT_DEV = to_kdev_t(root_dev);
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 	rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
 	rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);	
diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
--- a/arch/sparc/kernel/signal.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc/kernel/signal.c	Sun Apr 14 12:16:59 2002
@@ -1195,8 +1195,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -1245,7 +1245,7 @@
 				current->exit_code = signr;
 
 				/* notify_parent() is SMP safe */
-				if(!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
+				if(!(current->parent->sig->action[SIGCHLD-1].sa.sa_flags &
 				     SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
@@ -1280,7 +1280,10 @@
 #endif
 				/* fall through */
 			default:
-				sig_exit(signr, exit_code, &info);
+				sigaddset(&current->pending.signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
 				/* NOT REACHED */
 			}
 		}
diff -Nru a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
--- a/arch/sparc/kernel/sparc_ksyms.c	Sun Apr 14 12:16:55 2002
+++ b/arch/sparc/kernel/sparc_ksyms.c	Sun Apr 14 12:16:55 2002
@@ -250,7 +250,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(page_kernel);
 
diff -Nru a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
--- a/arch/sparc/kernel/sun4d_smp.c	Sun Apr 14 12:16:55 2002
+++ b/arch/sparc/kernel/sun4d_smp.c	Sun Apr 14 12:16:55 2002
@@ -47,7 +47,7 @@
 extern volatile int smp_processors_ready;
 extern unsigned long cpu_present_map;
 extern int smp_num_cpus;
-static int smp_highest_cpu = 0;
+static int smp_highest_cpu;
 extern int smp_threads_ready;
 extern unsigned char mid_xlate[NR_CPUS];
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc/kernel/time.c	Sun Apr 14 12:16:59 2002
@@ -115,7 +115,7 @@
 void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	/* last time the cmos clock got updated */
-	static long last_rtc_update=0;
+	static long last_rtc_update;
 
 #ifndef CONFIG_SMP
 	if(!user_mode(regs))
diff -Nru a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
--- a/arch/sparc/kernel/traps.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc/kernel/traps.c	Sun Apr 14 12:16:59 2002
@@ -272,7 +272,7 @@
 void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		 unsigned long psr)
 {
-	static int calls = 0;
+	static int calls;
 	siginfo_t info;
 	unsigned long fsr;
 	int ret = 0;
diff -Nru a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
--- a/arch/sparc/mm/iommu.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc/mm/iommu.c	Sun Apr 14 12:16:58 2002
@@ -25,7 +25,7 @@
 BTFIXUPDEF_CALL(void, flush_page_for_dma, unsigned long)
 #define flush_page_for_dma(page) BTFIXUP_CALL(flush_page_for_dma)(page)
 extern int flush_page_for_dma_global;
-static int viking_flush = 0;
+static int viking_flush;
 /* viking.S */
 extern void viking_flush_page(unsigned long page);
 extern void viking_mxcc_flush_page(unsigned long page);
diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
--- a/arch/sparc/mm/srmmu.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc/mm/srmmu.c	Sun Apr 14 12:16:54 2002
@@ -1739,7 +1739,7 @@
 static void __init poke_viking(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
-	static int smp_catch = 0;
+	static int smp_catch;
 
 	if(viking_mxcc_present) {
 		unsigned long mxcc_control = mxcc_get_creg();
@@ -1963,7 +1963,7 @@
 		iaddr = &(insn); \
 		daddr = &(dest); \
 		*iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
-	} while(0);
+	} while(0)
 
 static void __init patch_window_trap_handlers(void)
 {
diff -Nru a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
--- a/arch/sparc/mm/sun4c.c	Sun Apr 14 12:16:56 2002
+++ b/arch/sparc/mm/sun4c.c	Sun Apr 14 12:16:56 2002
@@ -425,7 +425,7 @@
 		daddr = &(dst);		\
 		iaddr = &(src);		\
 		*daddr = *iaddr;	\
-	} while (0);
+	} while (0)
 
 static void patch_kernel_fault_handler(void)
 {
diff -Nru a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S
--- a/arch/sparc/mm/swift.S	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc/mm/swift.S	Sun Apr 14 12:16:58 2002
@@ -53,11 +53,9 @@
 
 	.globl	swift_flush_cache_mm
 swift_flush_cache_mm:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	swift_flush_cache_mm_out
-#endif
 	WINDOW_FLUSH(%g4, %g5)
 	rd	%psr, %g1
 	andn	%g1, PSR_ET, %g3
@@ -121,11 +119,9 @@
 swift_flush_cache_page:
 	ld	[%o0 + 0x0], %o0		/* XXX vma->vm_mm, GROSS XXX */
 70:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	swift_flush_cache_page_out
-#endif
 	WINDOW_FLUSH(%g4, %g5)
 	rd	%psr, %g1
 	andn	%g1, PSR_ET, %g3
@@ -226,11 +222,9 @@
 swift_flush_tlb_range:
 	ld	[%o0 + 0x00], %o0	/* XXX vma->vm_mm GROSS XXX */
 swift_flush_tlb_mm:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	swift_flush_tlb_all_out
-#endif
 swift_flush_tlb_all:
 	mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
@@ -244,11 +238,9 @@
 	mov	SRMMU_CTX_REG, %g1
 	ld	[%o0 + AOFF_mm_context], %o3
 	andn	%o1, (PAGE_SIZE - 1), %o1
-#ifndef CONFIG_SMP
 	cmp	%o3, -1
 	be	swift_flush_tlb_page_out
 	 nop
-#endif
 #if 1
 	mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE	
diff -Nru a/arch/sparc/mm/tsunami.S b/arch/sparc/mm/tsunami.S
--- a/arch/sparc/mm/tsunami.S	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc/mm/tsunami.S	Sun Apr 14 12:16:57 2002
@@ -27,10 +27,8 @@
 	ld	[%o0 + 0x0], %o0	/* XXX vma->vm_mm, GROSS XXX */
 tsunami_flush_cache_mm:
 	ld	[%o0 + AOFF_mm_context], %g2
-#ifndef CONFIG_SMP
 	cmp	%g2, -1
 	be	tsunami_flush_cache_out
-#endif
 tsunami_flush_cache_all:
 	WINDOW_FLUSH(%g4, %g5)
 tsunami_flush_page_for_dma:
@@ -50,11 +48,9 @@
 tsunami_flush_tlb_range:
 	ld	[%o0 + 0x00], %o0	/* XXX vma->vm_mm GROSS XXX */
 tsunami_flush_tlb_mm:
-#ifndef CONFIG_SMP
 	ld	[%o0 + AOFF_mm_context], %g2
 	cmp	%g2, -1
 	be	tsunami_flush_tlb_out
-#endif
 tsunami_flush_tlb_all:
 	 mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
@@ -73,10 +69,8 @@
 	mov	SRMMU_CTX_REG, %g1
 	ld	[%o0 + AOFF_mm_context], %o3
 	andn	%o1, (PAGE_SIZE - 1), %o1
-#ifndef CONFIG_SMP
 	cmp	%o3, -1
 	be	tsunami_flush_tlb_page_out
-#endif
 	 lda	[%g1] ASI_M_MMUREGS, %g5
 	sta	%o3, [%g1] ASI_M_MMUREGS
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/defconfig	Sun Apr 14 12:16:57 2002
@@ -248,7 +248,7 @@
 CONFIG_IDE=y
 
 #
-# IDE, ATA and ATAPI Block devices
+# ATA and ATAPI Block devices
 #
 CONFIG_BLK_DEV_IDE=y
 
@@ -283,9 +283,9 @@
 # CONFIG_BLK_DEV_ISAPNP is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_IDEPCI_SHARE_IRQ is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_IDEDMA_ONLYDISK=y
 CONFIG_BLK_DEV_IDEDMA=y
@@ -296,13 +296,13 @@
 CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
 CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_PIIX is not set
 CONFIG_BLK_DEV_NS87415=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC_ADMA is not set
@@ -314,10 +314,9 @@
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
@@ -789,6 +788,7 @@
 # USB Device Class drivers
 #
 # CONFIG_USB_AUDIO is not set
+# CONFIG_USB_EMI26 is not set
 CONFIG_USB_BLUETOOTH=m
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -909,6 +909,7 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_DCFLUSH is not set
+# CONFIG_STACK_DEBUG is not set
 
 #
 # Library routines
diff -Nru a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
--- a/arch/sparc64/kernel/ebus.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/ebus.c	Sun Apr 14 12:16:57 2002
@@ -275,6 +275,25 @@
 	printk("]");
 }
 
+static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
+{
+	struct pci_dev *pdev = start;
+
+	do {
+		pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev);
+		if (pdev &&
+		    (pdev->device == PCI_DEVICE_ID_SUN_EBUS ||
+		     pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
+			break;
+	} while (pdev != NULL);
+
+	if (pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
+		*is_rio_p = 1;
+	else
+		*is_rio_p = 0;
+
+	return pdev;
+}
 
 void __init ebus_init(void)
 {
@@ -289,12 +308,7 @@
 	if (!pci_present())
 		return;
 
-	is_rio = 0;
-	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
-	if (!pdev) {
-		pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_RIO_EBUS, 0);
-		is_rio = 1;
-	}
+	pdev = find_next_ebus(NULL, &is_rio);
 	if (!pdev) {
 		printk("ebus: No EBus's found.\n");
 		return;
@@ -315,16 +329,7 @@
 		   we'd have to tweak with the ebus_chain
 		   in the runtime after initialization. -jj */
 		if (!prom_getchild (ebusnd)) {
-			struct pci_dev *orig_pdev = pdev;
-
-			is_rio = 0;
-			pdev = pci_find_device(PCI_VENDOR_ID_SUN, 
-					       PCI_DEVICE_ID_SUN_EBUS, orig_pdev);
-			if (!pdev) {
-				pdev = pci_find_device(PCI_VENDOR_ID_SUN, 
-						       PCI_DEVICE_ID_SUN_RIO_EBUS, orig_pdev);
-				is_rio = 1;
-			}
+			pdev = find_next_ebus(pdev, &is_rio);
 			if (!pdev) {
 				if (ebus == ebus_chain) {
 					ebus_chain = NULL;
@@ -374,20 +379,9 @@
 	next_ebus:
 		printk("\n");
 
-		{
-			struct pci_dev *orig_pdev = pdev;
-
-			is_rio = 0;
-			pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-					       PCI_DEVICE_ID_SUN_EBUS, orig_pdev);
-			if (!pdev) {
-				pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-						       PCI_DEVICE_ID_SUN_RIO_EBUS, orig_pdev);
-				is_rio = 1;
-			}
-			if (!pdev)
-				break;
-		}
+		pdev = find_next_ebus(pdev, &is_rio);
+		if (!pdev)
+			break;
 
 		cookie = pdev->sysdata;
 		ebusnd = cookie->prom_node;
diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
--- a/arch/sparc64/kernel/head.S	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/head.S	Sun Apr 14 12:16:57 2002
@@ -565,13 +565,6 @@
 #define KERN_HIGHBITS		((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
 #define KERN_LOWBITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
 
-#define VPTE_BASE_SPITFIRE	0xfffffffe00000000
-#if 1
-#define VPTE_BASE_CHEETAH	VPTE_BASE_SPITFIRE
-#else
-#define VPTE_BASE_CHEETAH	0xffe0000000000000
-#endif
-
 	mov	TSB_REG, %g1
 	stxa	%g0, [%g1] ASI_DMMU
 	membar	#Sync
@@ -602,8 +595,6 @@
 	clr	%g7
 #undef KERN_HIGHBITS
 #undef KERN_LOWBITS
-#undef VPTE_BASE_SPITFIRE
-#undef VPTE_BASE_CHEETAH
 
 	/* Setup Interrupt globals */
 	wrpr	%o1, (PSTATE_IG|PSTATE_IE), %pstate
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/ioctl32.c	Sun Apr 14 12:16:57 2002
@@ -1061,7 +1061,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("%s: Unknown fb ioctl cmd fd(%d) "
 				       "cmd(%08x) arg(%08lx)\n",
@@ -1714,7 +1714,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("ppp_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1824,7 +1824,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("mt_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -1942,7 +1942,7 @@
 		break;
 	default:
 		do {
-			static int count = 0;
+			static int count;
 			if (++count <= 20)
 				printk("cdrom_ioctl: Unknown cmd fd(%d) "
 				       "cmd(%08x) arg(%08x)\n",
@@ -2029,7 +2029,7 @@
 		}
 		break;
 	default: {
-		static int count = 0;
+		static int count;
 		if (++count <= 20)
 			printk("%s: Unknown loop ioctl cmd, fd(%d) "
 			       "cmd(%08x) arg(%08lx)\n",
@@ -4882,7 +4882,7 @@
 		handler = (void *)(long)t->handler;
 		error = handler(fd, cmd, arg, filp);
 	} else {
-		static int count = 0;
+		static int count;
 		if (++count <= 20)
 			printk("sys32_ioctl(%s:%d): Unknown cmd fd(%d) "
 			       "cmd(%08x) arg(%08x)\n",
diff -Nru a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
--- a/arch/sparc64/kernel/irq.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/irq.c	Sun Apr 14 12:16:57 2002
@@ -82,7 +82,7 @@
  */
 #define MAX_STATIC_ALLOC	4
 static struct irqaction static_irqaction[MAX_STATIC_ALLOC];
-static int static_irq_count = 0;
+static int static_irq_count;
 
 /* This is exported so that fast IRQ handlers can get at it... -DaveM */
 struct irqaction *irq_action[NR_IRQS+1] = {
diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
--- a/arch/sparc64/kernel/pci.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc64/kernel/pci.c	Sun Apr 14 12:16:54 2002
@@ -234,33 +234,63 @@
 	return request_resource(root, res);
 }
 
+/*
+ * Given the PCI bus a device resides on, try to
+ * find an acceptable resource allocation for a
+ * specific device resource..
+ */
+static int pci_assign_bus_resource(const struct pci_bus *bus,
+	struct pci_dev *dev,
+	struct resource *res,
+	unsigned long size,
+	unsigned long min,
+	int resno)
+{
+	unsigned int type_mask;
+	int i;
+
+	type_mask = IORESOURCE_IO | IORESOURCE_MEM;
+	for (i = 0 ; i < 4; i++) {
+		struct resource *r = bus->resource[i];
+		if (!r)
+			continue;
+
+		/* type_mask must match */
+		if ((res->flags ^ r->flags) & type_mask)
+			continue;
+
+		/* Ok, try it out.. */
+		if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0)
+			continue;
+
+		/* PCI config space updated by caller.  */
+		return 0;
+	}
+	return -EBUSY;
+}
+
 int pci_assign_resource(struct pci_dev *pdev, int resource)
 {
 	struct pcidev_cookie *pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = pcp->pbm;
 	struct resource *res = &pdev->resource[resource];
-	struct resource *root;
-	unsigned long min, max, size, align;
+	unsigned long min, size;
 	int err;
 
-	if (res->flags & IORESOURCE_IO) {
-		root = &pbm->io_space;
-		min = root->start + 0x400UL;
-		max = root->end;
-	} else {
-		root = &pbm->mem_space;
-		min = root->start;
-		max = min + 0x80000000UL;
-	}
+	if (res->flags & IORESOURCE_IO)
+		min = pbm->io_space.start + 0x400UL;
+	else
+		min = pbm->mem_space.start;
+
+	size = res->end - res->start + 1;
 
-	size = res->end - res->start;
-	align = size + 1;
+	err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource);
 
-	err = allocate_resource(root, res, size + 1, min, max, align, NULL, NULL);
 	if (err < 0) {
 		printk("PCI: Failed to allocate resource %d for %s\n",
 		       resource, pdev->name);
 	} else {
+		/* Update PCI config space. */
 		pbm->parent->base_address_update(pdev, resource);
 	}
 
diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
--- a/arch/sparc64/kernel/pci_common.c	Sun Apr 14 12:16:56 2002
+++ b/arch/sparc64/kernel/pci_common.c	Sun Apr 14 12:16:56 2002
@@ -571,14 +571,12 @@
 	struct pci_pbm_info *pbm = dev_pcp->pbm;
 	struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs;
 	unsigned int hi, mid, lo, irq;
-	int i, num_intmap;
-
-	if (pbm->num_pbm_intmap == 0)
-		return 0;
+	int i, num_intmap, map_slot;
 
 	intmap = &pbm->pbm_intmap[0];
 	intmask = &pbm->pbm_intmask;
 	num_intmap = pbm->num_pbm_intmap;
+	map_slot = 0;
 
 	/* If we are underneath a PCI bridge, use PROM register
 	 * property of the parent bridge which is closest to
@@ -639,11 +637,21 @@
 				printk("pci_intmap_match: Trying to recover.\n");
 				return 0;
 			}
+
+			if (pdev->bus->self != bus_dev)
+				map_slot = 1;
 		} else {
 			pregs = bus_pcp->prom_regs;
+			map_slot = 1;
 		}
 	}
 
+	if (map_slot) {
+		*interrupt = ((*interrupt
+			       - 1
+			       + PCI_SLOT(pdev->devfn)) & 0x3) + 1;
+	}
+
 	hi   = pregs->phys_hi & intmask->phys_hi;
 	mid  = pregs->phys_mid & intmask->phys_mid;
 	lo   = pregs->phys_lo & intmask->phys_lo;
@@ -655,24 +663,33 @@
 		    intmap[i].phys_lo  == lo	&&
 		    intmap[i].interrupt == irq) {
 			*interrupt = intmap[i].cinterrupt;
+			printk("PCI-IRQ: Routing bus[%2x] slot[%2x] map[%d] to INO[%02x]\n",
+			       pdev->bus->number, PCI_SLOT(pdev->devfn),
+			       map_slot, *interrupt);
 			return 1;
 		}
 	}
 
-	/* Print it both to OBP console and kernel one so that if bootup
-	 * hangs here the user has the information to report.
+	/* We will run this code even if pbm->num_pbm_intmap is zero, just so
+	 * we can apply the slot mapping to the PROM interrupt property value.
+	 * So do not spit out these warnings in that case.
 	 */
-	prom_printf("pci_intmap_match: bus %02x, devfn %02x: ",
-		    pdev->bus->number, pdev->devfn);
-	prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
-		    pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
-	prom_printf("Please email this information to davem@redhat.com\n");
-
-	printk("pci_intmap_match: bus %02x, devfn %02x: ",
-	       pdev->bus->number, pdev->devfn);
-	printk("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
-	       pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
-	printk("Please email this information to davem@redhat.com\n");
+	if (num_intmap != 0) {
+		/* Print it both to OBP console and kernel one so that if bootup
+		 * hangs here the user has the information to report.
+		 */
+		prom_printf("pci_intmap_match: bus %02x, devfn %02x: ",
+			    pdev->bus->number, pdev->devfn);
+		prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
+			    pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
+		prom_printf("Please email this information to davem@redhat.com\n");
+
+		printk("pci_intmap_match: bus %02x, devfn %02x: ",
+		       pdev->bus->number, pdev->devfn);
+		printk("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
+		       pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
+		printk("Please email this information to davem@redhat.com\n");
+	}
 
 	return 0;
 }
@@ -718,20 +735,6 @@
 	if ((prom_irq & PCI_IRQ_INO) & 0x20) {
 		pdev->irq = p->irq_build(pbm, pdev, (portid << 6 | prom_irq));
 		goto have_irq;
-	}
-
-	/* Firmware gets quad-hme interrupts property totally
-	 * wrong.  It is 4 EBUS+HME devices behind a Digital bridge.
-	 * For each of the 4 instances the EBUS has interrupt property
-	 * '1' and the HME has interrupt property '2'.  So we have to
-	 * fix this up.
-	 */
-	if (!strcmp(pcp->prom_name, "SUNW,qfe") ||
-	    !strcmp(pcp->prom_name, "qfe")) {
-		if (PCI_SLOT(pdev->devfn) & ~3)
-			BUG();
-
-		prom_irq = PCI_SLOT(pdev->devfn) + 1;
 	}
 
 	/* Can we find a matching entry in the interrupt-map? */
diff -Nru a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
--- a/arch/sparc64/kernel/pci_psycho.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc64/kernel/pci_psycho.c	Sun Apr 14 12:16:59 2002
@@ -1101,7 +1101,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1117,6 +1124,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - root->start)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
diff -Nru a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
--- a/arch/sparc64/kernel/pci_sabre.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc64/kernel/pci_sabre.c	Sun Apr 14 12:16:58 2002
@@ -1067,7 +1067,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1083,6 +1090,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - base)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
@@ -1148,7 +1159,7 @@
 
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
-	static int once = 0;
+	static int once;
 	struct pci_bus *sabre_bus;
 	struct pci_pbm_info *pbm;
 	struct pcidev_cookie *cookie;
diff -Nru a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
--- a/arch/sparc64/kernel/pci_schizo.c	Sun Apr 14 12:16:55 2002
+++ b/arch/sparc64/kernel/pci_schizo.c	Sun Apr 14 12:16:55 2002
@@ -383,7 +383,7 @@
 	struct ino_bucket *bucket;
 	unsigned long imap, iclr, pbm_off;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int pil;
 
 	if (pbm == &p->pbm_A)
 		pbm_off = SCHIZO_PBM_A_REGS_OFF;
@@ -406,10 +406,13 @@
 	iclr = p->controller_regs + pbm_off + iclr_off;
 	iclr += 4;
 
-	if (ino < 0x18)
-		inofixup = ino & 0x03;
-
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+	/* On Schizo, no inofixup occurs.  This is because each
+	 * INO has it's own IMAP register.  On Psycho and Sabre
+	 * there is only one IMAP register for each PCI slot even
+	 * though four different INOs can be generated by each
+	 * PCI slot.
+	 */
+	bucket = __bucket(build_irq(pil, 0, iclr, imap));
 	bucket->flags |= IBF_PCI;
 
 	return __irq(bucket);
@@ -1423,7 +1426,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1439,6 +1449,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - root->start)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
@@ -1469,24 +1483,12 @@
 #define SCHIZO_PCI_B_IO_MATCH		0x00070UL
 #define SCHIZO_PCI_B_IO_MASK		0x00078UL
 
-/* VAL must be non-zero. */
-static unsigned long strip_to_lowest_bit_set(unsigned long val)
-{
-	unsigned long tmp;
-
-	tmp = 1UL;
-	while (!(tmp & val))
-		tmp <<= 1UL;
-
-	return tmp;
-}
-
 static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
 					  int is_pbm_a, unsigned long reg_base)
 {
 	u64 mem_match, mem_mask;
 	u64 io_match;
-	u64 long a, b;
+	u64 a;
 
 	if (is_pbm_a) {
 		mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH;
@@ -1498,11 +1500,12 @@
 	mem_mask = mem_match + 0x8UL;
 
 	a = schizo_read(mem_match) & ~0x8000000000000000UL;
-	b = strip_to_lowest_bit_set(schizo_read(mem_mask));
 
-	/* It should be 2GB in size. */
+	/* It should be 2GB in size but the decode is set for the full
+	 * 4GB so we have to add the 2G by hand.
+	 */
 	pbm->mem_space.start = a;
-	pbm->mem_space.end = a + (b - 1UL);
+	pbm->mem_space.end = a + 0x80000000;
 	pbm->mem_space.flags = IORESOURCE_MEM;
 
 	/* This 32MB area is divided into two pieces.  The first
diff -Nru a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
--- a/arch/sparc64/kernel/power.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/power.c	Sun Apr 14 12:16:57 2002
@@ -22,7 +22,7 @@
 #define POWER_COURTESY_OFF (1 << 1)
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
-static int button_pressed = 0;
+static int button_pressed;
 
 static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -81,7 +81,7 @@
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
-	static int invoked = 0;
+	static int invoked;
 
 	if (invoked)
 		return;
diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
--- a/arch/sparc64/kernel/process.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc64/kernel/process.c	Sun Apr 14 12:16:58 2002
@@ -424,10 +424,10 @@
 	struct thread_info *t = current_thread_info();
 
 	if (t->task->mm) {
+		unsigned long pgd_cache = 0UL;
 		if (test_thread_flag(TIF_32BIT)) {
 			struct mm_struct *mm = t->task->mm;
 			pgd_t *pgd0 = &mm->pgd[0];
-			unsigned long pgd_cache;
 
 			if (pgd_none(*pgd0)) {
 				pmd_t *page = pmd_alloc_one_fast(NULL, 0);
@@ -436,13 +436,13 @@
 				pgd_set(pgd0, page);
 			}
 			pgd_cache = pgd_val(*pgd0) << 11UL;
-			__asm__ __volatile__("stxa %0, [%1] %2\n\t"
-					     "membar #Sync"
-					     : /* no outputs */
-					     : "r" (pgd_cache),
-					       "r" (TSB_REG),
-					       "i" (ASI_DMMU));
 		}
+		__asm__ __volatile__("stxa %0, [%1] %2\n\t"
+				     "membar #Sync"
+				     : /* no outputs */
+				     : "r" (pgd_cache),
+				     "r" (TSB_REG),
+				     "i" (ASI_DMMU));
 	}
 	set_thread_wsaved(0);
 
diff -Nru a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
--- a/arch/sparc64/kernel/ptrace.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc64/kernel/ptrace.c	Sun Apr 14 12:16:58 2002
@@ -122,6 +122,7 @@
 	unsigned long data = regs->u_regs[UREG_I3];
 	unsigned long addr2 = regs->u_regs[UREG_I4];
 	struct task_struct *child;
+	int ret;
 
 	if (test_thread_flag(TIF_32BIT)) {
 		addr &= 0xffffffffUL;
@@ -184,18 +185,10 @@
 		pt_succ_return(regs, 0);
 		goto out_tsk;
 	}
-	if (!(child->ptrace & PT_PTRACED)) {
-		pt_error_return(regs, ESRCH);
-		goto out_tsk;
-	}
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL) {
-			pt_error_return(regs, ESRCH);
-			goto out_tsk;
-		}
-	}
-	if (child->p_pptr != current) {
-		pt_error_return(regs, ESRCH);
+
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0) {
+		pt_error_return(regs, -ret);
 		goto out_tsk;
 	}
 
diff -Nru a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c
--- a/arch/sparc64/kernel/semaphore.c	Sun Apr 14 12:16:56 2002
+++ b/arch/sparc64/kernel/semaphore.c	Sun Apr 14 12:16:56 2002
@@ -7,6 +7,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/errno.h>
 
 /*
  * Atomically update sem->count.
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc64/kernel/signal.c	Sun Apr 14 12:16:59 2002
@@ -729,8 +729,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -772,7 +772,7 @@
 				struct signal_struct *sig;
 
 				current->exit_code = signr;
-				sig = current->p_pptr->sig;
+				sig = current->parent->sig;
 				preempt_disable();
 				current->state = TASK_STOPPED;
 				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags &
diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
--- a/arch/sparc64/kernel/signal32.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc64/kernel/signal32.c	Sun Apr 14 12:16:54 2002
@@ -1403,8 +1403,8 @@
 				info.si_signo = signr;
 				info.si_errno = 0;
 				info.si_code = SI_USER;
-				info.si_pid = current->p_pptr->pid;
-				info.si_uid = current->p_pptr->uid;
+				info.si_pid = current->parent->pid;
+				info.si_uid = current->parent->uid;
 			}
 
 			/* If the (new) signal is now blocked, requeue it.  */
@@ -1446,7 +1446,7 @@
 				struct signal_struct *sig;
 
 				current->exit_code = signr;
-				sig = current->p_pptr->sig;
+				sig = current->parent->sig;
 				preempt_disable();
 				current->state = TASK_STOPPED;
 				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags &
diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
--- a/arch/sparc64/kernel/smp.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc64/kernel/smp.c	Sun Apr 14 12:16:54 2002
@@ -46,8 +46,8 @@
 volatile int __cpu_logical_map[NR_CPUS] __attribute__ ((aligned (SMP_CACHE_BYTES)));
 
 /* Please don't make this stuff initdata!!!  --DaveM */
-static unsigned char boot_cpu_id = 0;
-static int smp_activated = 0;
+static unsigned char boot_cpu_id;
+static int smp_activated;
 
 /* Kernel spinlock */
 spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
@@ -898,7 +898,7 @@
 
 static atomic_t smp_capture_depth = ATOMIC_INIT(0);
 static atomic_t smp_capture_registry = ATOMIC_INIT(0);
-static unsigned long penguins_are_doing_time = 0;
+static unsigned long penguins_are_doing_time;
 
 void smp_capture(void)
 {
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	Sun Apr 14 12:16:57 2002
@@ -303,7 +303,6 @@
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strstr);
 
 #ifdef CONFIG_SOLARIS_EMUL_MODULE
diff -Nru a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
--- a/arch/sparc64/kernel/sys_sparc.c	Sun Apr 14 12:16:54 2002
+++ b/arch/sparc64/kernel/sys_sparc.c	Sun Apr 14 12:16:54 2002
@@ -380,7 +380,7 @@
 asmlinkage unsigned long
 c_sys_nis_syscall (struct pt_regs *regs)
 {
-	static int count=0;
+	static int count;
 	
 	/* Don't make the system unusable, if someone goes stuck */
 	if (count++ > 5)
@@ -450,7 +450,7 @@
 
 asmlinkage int solaris_syscall(struct pt_regs *regs)
 {
-	static int count = 0;
+	static int count;
 
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
@@ -470,7 +470,7 @@
 #ifndef CONFIG_SUNOS_EMUL
 asmlinkage int sunos_syscall(struct pt_regs *regs)
 {
-	static int count = 0;
+	static int count;
 
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
--- a/arch/sparc64/kernel/sys_sunos32.c	Sun Apr 14 12:16:55 2002
+++ b/arch/sparc64/kernel/sys_sunos32.c	Sun Apr 14 12:16:55 2002
@@ -210,7 +210,7 @@
 
 asmlinkage void sunos_vadvise(u32 strategy)
 {
-	static int count = 0;
+	static int count;
 
 	/* I wanna see who uses this... */
 	if (count++ < 5)
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc64/kernel/time.c	Sun Apr 14 12:16:58 2002
@@ -62,7 +62,7 @@
 static __inline__ void timer_check_rtc(void)
 {
 	/* last time the cmos clock got updated */
-	static long last_rtc_update=0;
+	static long last_rtc_update;
 
 	/* Determine when to update the Mostek clock. */
 	if ((time_status & STA_UNSYNC) == 0 &&
@@ -410,7 +410,7 @@
 	struct linux_ebus *ebus = NULL;
 	struct isa_bridge *isa_br = NULL;
 #endif
-	static int invoked = 0;
+	static int invoked;
 
 	if (invoked)
 		return;
diff -Nru a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
--- a/arch/sparc64/kernel/trampoline.S	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/kernel/trampoline.S	Sun Apr 14 12:16:57 2002
@@ -215,13 +215,6 @@
 #define KERN_HIGHBITS		((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
 #define KERN_LOWBITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
 
-#define VPTE_BASE_SPITFIRE	0xfffffffe00000000
-#if 1
-#define VPTE_BASE_CHEETAH	VPTE_BASE_SPITFIRE
-#else
-#define VPTE_BASE_CHEETAH	0xffe0000000000000
-#endif
-
 	mov		TSB_REG, %g1
 	stxa		%g0, [%g1] ASI_DMMU
 	membar		#Sync
@@ -252,8 +245,6 @@
 	clr	%g7
 #undef KERN_HIGHBITS
 #undef KERN_LOWBITS
-#undef VPTE_BASE_SPITFIRE
-#undef VPTE_BASE_CHEETAH
 
 	wrpr		%o1, 0x0, %pstate
 	ldx		[%g6 + TI_TASK], %g4
diff -Nru a/arch/sparc64/math-emu/math.c b/arch/sparc64/math-emu/math.c
--- a/arch/sparc64/math-emu/math.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc64/math-emu/math.c	Sun Apr 14 12:16:59 2002
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/errno.h>
 
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/mm/init.c	Sun Apr 14 12:16:57 2002
@@ -699,7 +699,7 @@
 	}
 }
 
-static int prom_ditlb_set = 0;
+static int prom_ditlb_set;
 struct prom_tlb_entry {
 	int		tlb_ent;
 	unsigned long	tlb_tag;
diff -Nru a/arch/sparc64/prom/bootstr.c b/arch/sparc64/prom/bootstr.c
--- a/arch/sparc64/prom/bootstr.c	Sun Apr 14 12:16:55 2002
+++ b/arch/sparc64/prom/bootstr.c	Sun Apr 14 12:16:55 2002
@@ -9,6 +9,11 @@
 #include <linux/init.h>
 #include <asm/oplib.h>
 
+/* WARNING: The boot loader knows that these next three variables come one right
+ *          after another in the .data section.  Do not move this stuff into
+ *          the .bss section or it will break things.
+ */
+
 #define BARG_LEN  256
 int bootstr_len = BARG_LEN;
 static int bootstr_valid = 0;
diff -Nru a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
--- a/arch/sparc64/prom/misc.c	Sun Apr 14 12:16:59 2002
+++ b/arch/sparc64/prom/misc.c	Sun Apr 14 12:16:59 2002
@@ -171,7 +171,7 @@
 
 static int prom_get_memory_ihandle(void)
 {
-	static int memory_ihandle_cache = 0;
+	static int memory_ihandle_cache;
 	int node, ret;
 
 	if (memory_ihandle_cache != 0)
diff -Nru a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
--- a/arch/sparc64/solaris/misc.c	Sun Apr 14 12:16:58 2002
+++ b/arch/sparc64/solaris/misc.c	Sun Apr 14 12:16:58 2002
@@ -57,7 +57,7 @@
 	/* Do we need it here? */
 	set_personality(PER_SVR4);
 	if (flags & MAP_NORESERVE) {
-		static int cnt = 0;
+		static int cnt;
 		
 		if (cnt < 5) {
 			printk("%s:  unimplemented Solaris MAP_NORESERVE mmap() flag\n",
diff -Nru a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
--- a/arch/sparc64/solaris/timod.c	Sun Apr 14 12:16:57 2002
+++ b/arch/sparc64/solaris/timod.c	Sun Apr 14 12:16:57 2002
@@ -46,7 +46,7 @@
 void * mykmalloc(size_t s, int gfp)
 {
 	static char * page;
-	static size_t free = 0;
+	static size_t free;
 	void * r;
 	s = ((s + 63) & ~63);
 	if( s > PAGE_SIZE ) {
diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
--- a/arch/x86_64/kernel/x8664_ksyms.c	Sun Apr 14 12:16:56 2002
+++ b/arch/x86_64/kernel/x8664_ksyms.c	Sun Apr 14 12:16:56 2002
@@ -87,7 +87,6 @@
 EXPORT_SYMBOL_NOVERS(__put_user_2);
 EXPORT_SYMBOL_NOVERS(__put_user_4);
 
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
--- a/drivers/acorn/scsi/eesox.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acorn/scsi/eesox.c	Sun Apr 14 12:16:58 2002
@@ -151,14 +151,14 @@
 	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
 	unsigned long flags;
 
-	save_flags_cli(flags);
+	spin_lock_irqsave(host->host_lock, flags);
 	if (on_off)
 		info->control.control |= EESOX_TERM_ENABLE;
 	else
 		info->control.control &= ~EESOX_TERM_ENABLE;
-	restore_flags(flags);
 
 	outb(info->control.control, info->control.io_port);
+	spin_unlock_irqrestore(host->host_lock, flags);
 }
 
 /* Prototype: void eesoxscsi_intr(irq, *dev_id, *regs)
diff -Nru a/drivers/acpi/Makefile b/drivers/acpi/Makefile
--- a/drivers/acpi/Makefile	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/Makefile	Sun Apr 14 12:16:58 2002
@@ -9,7 +9,7 @@
 ACPI_CFLAGS	:= -D_LINUX -I$(CURDIR)/include
 
 ifdef CONFIG_ACPI_DEBUG
-  ACPI_CFLAGS	+= -DACPI_DEBUG -Wno-unused
+  ACPI_CFLAGS	+= -DACPI_DEBUG
 endif
 
 EXTRA_CFLAGS	+= $(ACPI_CFLAGS)
diff -Nru a/drivers/acpi/acpi_ac.c b/drivers/acpi/acpi_ac.c
--- a/drivers/acpi/acpi_ac.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/acpi_ac.c	Sun Apr 14 12:16:58 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_ac.c - ACPI AC Adapter Driver ($Revision: 22 $)
+ *  acpi_ac.c - ACPI AC Adapter Driver ($Revision: 23 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -296,6 +296,7 @@
 	struct acpi_ac		*ac = NULL;
 
 	ACPI_FUNCTION_TRACE("acpi_ac_remove");
+
 	if (!device || !acpi_driver_data(device))
 		return_VALUE(-EINVAL);
 
diff -Nru a/drivers/acpi/acpi_battery.c b/drivers/acpi/acpi_battery.c
--- a/drivers/acpi/acpi_battery.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/acpi_battery.c	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_battery.c - ACPI Battery Driver ($Revision: 31 $)
+ *  acpi_battery.c - ACPI Battery Driver ($Revision: 32 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -112,8 +112,9 @@
 	struct acpi_battery	*battery,
 	struct acpi_battery_info **bif)
 {
+	int			result = 0;
 	acpi_status 		status = 0;
-	acpi_buffer 		buffer = {0, NULL};
+	acpi_buffer 		buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_buffer		format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
 						ACPI_BATTERY_FORMAT_BIF};
 	acpi_buffer		data = {0, NULL};
@@ -126,9 +127,11 @@
 
 	/* Evalute _BIF */
 
-	status = acpi_evaluate(battery->handle, "_BIF", NULL, &buffer);
-	if (ACPI_FAILURE(status))
+	status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n"));
 		return_VALUE(-ENODEV);
+	}
 
 	package = (acpi_object *) buffer.pointer;
 
@@ -136,29 +139,33 @@
 
 	status = acpi_extract_package(package, &format, &data);
 	if (status != AE_BUFFER_OVERFLOW) {
-		kfree(buffer.pointer);
-		return_VALUE(-ENODEV);
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
+		result = -ENODEV;
+		goto end;
 	}
 
 	data.pointer = kmalloc(data.length, GFP_KERNEL);
 	if (!data.pointer) {
-		kfree(buffer.pointer);
-		return_VALUE(-ENOMEM);
+		result = -ENOMEM;
+		goto end;
 	}
 	memset(data.pointer, 0, data.length);
 
 	status = acpi_extract_package(package, &format, &data);
 	if (ACPI_FAILURE(status)) {
-		kfree(buffer.pointer);
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
 		kfree(data.pointer);
-		return_VALUE(-ENODEV);
+		result = -ENODEV;
+		goto end;
 	}
 
+end:
 	kfree(buffer.pointer);
 
-	(*bif) = data.pointer;
+	if (0 == result)
+		(*bif) = (struct acpi_battery_info *) data.pointer;
 
-	return_VALUE(0);
+	return_VALUE(result);
 }
 
 static int
@@ -166,8 +173,9 @@
 	struct acpi_battery	*battery,
 	struct acpi_battery_status **bst)
 {
+	int			result = 0;
 	acpi_status 		status = 0;
-	acpi_buffer 		buffer = {0, NULL};
+	acpi_buffer 		buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_buffer		format = {sizeof(ACPI_BATTERY_FORMAT_BST),
 						ACPI_BATTERY_FORMAT_BST};
 	acpi_buffer		data = {0, NULL};
@@ -180,9 +188,11 @@
 
 	/* Evalute _BST */
 
-	status = acpi_evaluate(battery->handle, "_BST", NULL, &buffer);
-	if (ACPI_FAILURE(status))
+	status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n"));
 		return_VALUE(-ENODEV);
+	}
 
 	package = (acpi_object *) buffer.pointer;
 
@@ -190,29 +200,33 @@
 
 	status = acpi_extract_package(package, &format, &data);
 	if (status != AE_BUFFER_OVERFLOW) {
-		kfree(buffer.pointer);
-		return_VALUE(-ENODEV);
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
+		result = -ENODEV;
+		goto end;
 	}
 
 	data.pointer = kmalloc(data.length, GFP_KERNEL);
 	if (!data.pointer) {
-		kfree(buffer.pointer);
-		return_VALUE(-ENOMEM);
+		result = -ENOMEM;
+		goto end;
 	}
 	memset(data.pointer, 0, data.length);
 
 	status = acpi_extract_package(package, &format, &data);
 	if (ACPI_FAILURE(status)) {
-		kfree(buffer.pointer);
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
 		kfree(data.pointer);
-		return_VALUE(-ENODEV);
+		result = -ENODEV;
+		goto end;
 	}
 
+end:
 	kfree(buffer.pointer);
 
-	(*bst) = data.pointer;
+	if (0 == result)
+		(*bst) = (struct acpi_battery_status *) data.pointer;
 
-	return_VALUE(0);
+	return_VALUE(result);
 }
 
 
@@ -328,7 +342,7 @@
 {
 	int			result = 0;
 	struct acpi_battery	*battery = (struct acpi_battery *) data;
-	struct acpi_battery_info *bif = 0;
+	struct acpi_battery_info *bif = NULL;
 	char			*units = "?";
 	char			*p = page;
 	int			len = 0;
@@ -403,8 +417,7 @@
 		bif->oem_info);
 
 end:
-	if (bif)
-		kfree(bif);
+	kfree(bif);
 
 	len = (p - page);
 	if (len <= off+count) *eof = 1;
@@ -490,8 +503,7 @@
 			(u32) bst->present_voltage);
 
 end:
-	if (bst)
-		kfree(bst);
+	kfree(bst);
 
 	len = (p - page);
 	if (len <= off+count) *eof = 1;
diff -Nru a/drivers/acpi/acpi_bus.c b/drivers/acpi/acpi_bus.c
--- a/drivers/acpi/acpi_bus.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/acpi_bus.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_bus.c - ACPI Bus Driver ($Revision: 56 $)
+ *  acpi_bus.c - ACPI Bus Driver ($Revision: 66 $)
  *
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *
@@ -77,6 +77,8 @@
 	{"SONY  ", "U0      ", 0x20010313, ACPI_TABLE_DSDT, less_than_or_equal, "ACPI driver problem", 1},
 	/* Compaq Presario 800, Insyde BIOS */
 	{"INT440", "SYSFexxx", 0x00001001, ACPI_TABLE_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1},
+	/* IBM 600E - _ADR should return 7, but it returns 1 */
+	{"IBM   ", "TP600E  ", 0x00000105, ACPI_TABLE_DSDT, less_than_or_equal, "Incorrect _ADR", 1},
 	{""}
 };
 
@@ -266,34 +268,6 @@
 }
 
 
-static void
-acpi_bus_data_handler_powerf (
-	acpi_handle		handle,
-	u32			function,
-	void			*context)
-{
-	ACPI_FUNCTION_TRACE("acpi_bus_data_handler_powerf");
-
-	/* TBD */
-
-	return_VOID;
-}
-
-
-static void
-acpi_bus_data_handler_sleepf (
-	acpi_handle		handle,
-	u32			function,
-	void			*context)
-{
-	ACPI_FUNCTION_TRACE("acpi_bus_data_handler_sleepf");
-
-	/* TBD */
-
-	return_VOID;
-}
-
-
 int
 acpi_bus_get_device (
 	acpi_handle		handle,
@@ -1044,8 +1018,10 @@
 	if (!device || !driver)
 		return -EINVAL;
 
-	if (0 != strstr(driver->ids, device->pnp.hardware_id))
-		return 0;
+	if (device->flags.hardware_id) {
+		if (0 != strstr(driver->ids, device->pnp.hardware_id))
+			return 0;
+	}
 
 	if (device->flags.compatible_ids) {
 		acpi_status	status = AE_OK;
@@ -1055,8 +1031,8 @@
 
 		memset(cid, 0, sizeof(cid));
 
-		status = acpi_evaluate_object(device->handle, "_CID", 
-			NULL, &buffer);
+		status = acpi_evaluate_object(device->handle, "_CID", NULL, 
+			&buffer);
 		if (ACPI_FAILURE(status) || !buffer.pointer)
 			return -ENOENT;
 
@@ -1072,10 +1048,11 @@
 			break;
 		case ACPI_TYPE_PACKAGE:
 			/* TBD: Support CID packages */
-		default:
-			return -ENOENT;
 		}
 
+		if (!cid[0])
+			return -ENOENT;
+
 		if (0 != strstr(cid, device->pnp.hardware_id))
 			return 0;
 	}
@@ -1144,13 +1121,13 @@
 
 
 /**
- * acpi_bus_bind 
+ * acpi_bus_attach 
  * -------------
  * Callback for acpi_bus_walk() used to find devices that match a specific 
- * driver's criteria and bind the driver to the device.
+ * driver's criteria and then attach the driver.
  */
 static int
-acpi_bus_bind (
+acpi_bus_attach (
 	struct acpi_device	*device, 
 	int			level, 
 	void			*data)
@@ -1158,7 +1135,7 @@
 	int			result = 0;
 	struct acpi_driver	*driver = NULL;
 
-	ACPI_FUNCTION_TRACE("acpi_bus_bind");
+	ACPI_FUNCTION_TRACE("acpi_bus_attach");
 
 	if (!device || !data)
 		return_VALUE(-EINVAL);
@@ -1191,13 +1168,13 @@
 
 
 /**
- * acpi_bus_unbind 
- * ---------------
+ * acpi_bus_unattach 
+ * -----------------
  * Callback for acpi_bus_walk() used to find devices that match a specific 
- * driver's criteria and unbind the driver from the device.
+ * driver's criteria and unattach the driver.
  */
 static int
-acpi_bus_unbind (
+acpi_bus_unattach (
 	struct acpi_device	*device, 
 	int			level, 
 	void			*data)
@@ -1205,7 +1182,7 @@
 	int			result = 0;
 	struct acpi_driver	*driver = (struct acpi_driver *) data;
 
-	ACPI_FUNCTION_TRACE("acpi_bus_unbind");
+	ACPI_FUNCTION_TRACE("acpi_bus_unattach");
 
 	if (!device || !driver)
 		return_VALUE(-EINVAL);
@@ -1291,7 +1268,7 @@
 	list_add_tail(&driver->node, &acpi_bus_drivers);
 	up(&acpi_bus_drivers_lock);
 
-	acpi_bus_walk(acpi_root, acpi_bus_bind, 
+	acpi_bus_walk(acpi_root, acpi_bus_attach, 
 		WALK_DOWN, driver);
 
 	return_VALUE(driver->references);
@@ -1313,7 +1290,7 @@
 	if (!driver)
 		return_VALUE(-EINVAL);
 
-	acpi_bus_walk(acpi_root, acpi_bus_unbind, WALK_UP, driver);
+	acpi_bus_walk(acpi_root, acpi_bus_unattach, WALK_UP, driver);
 
 	if (driver->references)
 		return_VALUE(driver->references);
@@ -1395,8 +1372,8 @@
 	char			bus_id[5] = {'?',0};
 	acpi_buffer		buffer = {sizeof(bus_id), bus_id};
 	acpi_device_info	info;
-	char			*hid = "?";
-	char			*uid = "0";
+	char			*hid = NULL;
+	char			*uid = NULL;
 	int			i = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_bus_add");
@@ -1414,6 +1391,37 @@
 	device->handle = handle;
 	device->parent = parent;
 
+	memset(&info, 0, sizeof(acpi_device_info));
+
+	/*
+	 * Bus ID
+	 * ------
+	 * The device's Bus ID is simply the object name.
+	 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
+	 */
+	switch (type) {
+	case ACPI_BUS_TYPE_SYSTEM:
+		sprintf(device->pnp.bus_id, "%s", "ACPI");
+		break;
+	case ACPI_BUS_TYPE_POWER_BUTTON:
+		sprintf(device->pnp.bus_id, "%s", "PWRF");
+		break;
+	case ACPI_BUS_TYPE_SLEEP_BUTTON:
+		sprintf(device->pnp.bus_id, "%s", "SLPF");
+		break;
+	default:
+		acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
+		/* Clean up trailing underscores (if any) */
+		for (i = 3; i > 1; i--) {
+			if (bus_id[i] == '_')
+				bus_id[i] = '\0';
+			else
+				break;
+		}
+		sprintf(device->pnp.bus_id, "%s", bus_id);
+		break;
+	}
+
 	/*
 	 * Flags
 	 * -----
@@ -1457,35 +1465,6 @@
 	 */
 
 	/*
-	 * Bus ID
-	 * ------
-	 * The device's Bus ID is simply the object name.
-	 * TBD: Shouldn't this value be unique (within the ACPI namespace)?
-	 */
-	switch (type) {
-	case ACPI_BUS_TYPE_SYSTEM:
-		sprintf(device->pnp.bus_id, "%s", "ACPI");
-		break;
-	case ACPI_BUS_TYPE_POWER_BUTTON:
-		sprintf(device->pnp.bus_id, "%s", "PWRF");
-		break;
-	case ACPI_BUS_TYPE_SLEEP_BUTTON:
-		sprintf(device->pnp.bus_id, "%s", "SLPF");
-		break;
-	default:
-		acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
-		/* Clean up trailing underscores (if any) */
-		for (i = 3; i > 1; i--) {
-			if (bus_id[i] == '_')
-				bus_id[i] = '\0';
-			else
-				break;
-		}
-		sprintf(device->pnp.bus_id, "%s", bus_id);
-		break;
-	}
-
-	/*
 	 * Hardware ID, Unique ID, & Bus Address
 	 * -------------------------------------
 	 */
@@ -1505,8 +1484,10 @@
 			hid = info.hardware_id;
 		if (info.valid & ACPI_VALID_UID)
 			uid = info.unique_id;
-		if (info.valid & ACPI_VALID_ADR)
+		if (info.valid & ACPI_VALID_ADR) {
 			device->pnp.bus_address = info.address;
+			device->flags.bus_address = 1;
+		}
 		break;
 	case ACPI_BUS_TYPE_POWER:
 		hid = ACPI_POWER_HID;
@@ -1528,8 +1509,25 @@
 		break;
 	}
 
-	sprintf(device->pnp.hardware_id, "%s", hid);
-	sprintf(device->pnp.unique_id, "%s", uid);
+	/* 
+	 * \_SB
+	 * ----
+	 * Fix for the system root bus device -- the only root-level device.
+	 */
+	if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
+		hid = ACPI_BUS_HID;
+		sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
+		sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
+	}
+
+	if (hid) {
+		sprintf(device->pnp.hardware_id, "%s", hid);
+		device->flags.hardware_id = 1;
+	}
+	if (uid) {
+		sprintf(device->pnp.unique_id, "%s", uid);
+		device->flags.unique_id = 1;
+	}
 
 	/*
 	 * Power Management
@@ -1555,18 +1553,13 @@
 	 * Context
 	 * -------
 	 * Attach this 'struct acpi_device' to the ACPI object.  This makes
-	 * resolutions from handle->device very efficient.  Note that since we
-	 * attach multiple context to the root object (system device plus all
-	 * fixed-feature devices) we must use alternate handlers.
+	 * resolutions from handle->device very efficient.  Note that we need
+	 * to be careful with fixed-feature devices as they all attach to the
+	 * root object.
 	 */
 	switch (type) {
 	case ACPI_BUS_TYPE_POWER_BUTTON:
-		status = acpi_attach_data(device->handle,
-			acpi_bus_data_handler_powerf, device);
-		break;
 	case ACPI_BUS_TYPE_SLEEP_BUTTON:
-		status = acpi_attach_data(device->handle,
-			acpi_bus_data_handler_sleepf, device);
 		break;
 	default:
 		status = acpi_attach_data(device->handle,
@@ -1591,21 +1584,9 @@
 	else
 		list_add_tail(&device->node, &device->parent->children);
 
-	/* 
-	 * \_SB
-	 * ----
-	 * Fix for the system root bus device -- the only root-level device.
-	 */
-	if ((type == ACPI_BUS_TYPE_DEVICE) && (parent == ACPI_ROOT_OBJECT)) {
-		sprintf(device->pnp.hardware_id, "%s", ACPI_BUS_HID);
-		sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
-		sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
-	}
-
 #ifdef CONFIG_ACPI_DEBUG
 	{
 		char		*type_string = NULL;
-		char		*message = NULL;
 		char		name[80] = {'?','\0'};
 		acpi_buffer	buffer = {sizeof(name), name};
 
@@ -1640,7 +1621,7 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s %s [%p]\n", 
 			type_string, name, handle));
 	}
-#endif
+#endif /*CONFIG_ACPI_DEBUG*/
 
 	/*
 	 * Global Device Hierarchy:
@@ -1650,14 +1631,30 @@
 	acpi_device_register(device, parent);
 
 	/*
-	 * Find Driver
-	 * -----------
-	 * Check to see if there's a driver installed for this kind of device.
+	 * Bind _ADR-Based Devices
+	 * -----------------------
+	 * If there's a a bus address (_ADR) then we utilize the parent's 
+	 * 'bind' function (if exists) to bind the ACPI- and natively-
+	 * enumerated device representations.
 	 */
-	acpi_bus_find_driver(device);
+	if (device->flags.bus_address) {
+		if (device->parent && device->parent->ops.bind)
+			device->parent->ops.bind(device);
+	}
 
-end:
+	/*
+	 * Locate & Attach Driver
+	 * ----------------------
+	 * If there's a hardware id (_HID) or compatible ids (_CID) we check
+	 * to see if there's a driver installed for this kind of device.  Note
+	 * that drivers can install before or after a device in enumerated.
+	 *
+	 * TBD: Assumes LDM provides driver hot-plug capability.
+	 */
+	if (device->flags.hardware_id || device->flags.compatible_ids)
+		acpi_bus_find_driver(device);
 
+end:
 	if (0 != result) {
 		kfree(device);
 		return_VALUE(result);
@@ -1774,13 +1771,11 @@
 		 * If the device is present, enabled, and functioning then
 		 * parse its scope (depth-first).  Note that we need to
 		 * represent absent devices to facilitate PnP notifications
-		 * -- but we only the subtree head (not all of its children,
+		 * -- but only the subtree head (not all of its children,
 		 * which will be enumerated when the parent is inserted).
 		 *
 		 * TBD: Need notifications and other detection mechanisms
 		 *	in place before we can fully implement this.
-		 *
-		 * if (STRUCT_TO_INT(child->status) & 0x0B) {
 		 */
 		if (child->status.present) {
 			status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
@@ -1884,6 +1879,55 @@
 
 
 static int __init
+acpi_bus_init_irq (void)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	acpi_object		arg = {ACPI_TYPE_INTEGER};
+	acpi_object_list        arg_list = {1, &arg};
+	int			irq_model = 0;
+	char			*message = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_bus_init_irq");
+
+	/* 
+	 * Let the system know what interrupt model we are using by
+	 * evaluating the \_PIC object, if exists.
+	 */
+	result = acpi_get_interrupt_model(&irq_model);
+	if (0 != result)
+		return_VALUE(result);
+
+	switch (irq_model) {
+	case ACPI_INT_MODEL_PIC:
+		message = "PIC";
+		break;
+	case ACPI_INT_MODEL_IOAPIC:
+		message = "IOAPIC";
+		break;
+	case ACPI_INT_MODEL_IOSAPIC:
+		message = "IOSAPIC";
+		break;
+	default:
+		message = "UNKNOWN";
+		break;
+	}
+
+	printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);
+
+	arg.integer.value = irq_model;
+
+	status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
+	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	return_VALUE(0);
+}
+
+
+static int __init
 acpi_bus_init (void)
 {
 	int			result = 0;
@@ -1928,7 +1972,7 @@
 	progress++;
 
 	/*
-	 * [2] Get a separate copy of the FADT for use by other drivers.
+	 * [3] Get a separate copy of the FADT for use by other drivers.
 	 */
 	status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
 	if (ACPI_FAILURE(status)) {
@@ -1940,7 +1984,7 @@
 	progress++;
 
 	/*
-	 * [3] Enable the ACPI Core Subsystem.
+	 * [4] Enable the ACPI Core Subsystem.
 	 */
 	status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
 	if (ACPI_FAILURE(status)) {
@@ -1954,7 +1998,14 @@
 	progress++;
 
 	/*
-	 * [4] Register for all standard device notifications.
+	 * [5] Register for all standard device notifications.
+	 */
+	result = acpi_bus_init_irq();
+	if (0 != result)
+		goto end;
+
+	/*
+	 * [6] Register for all standard device notifications.
 	 */
 	status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
 	if (ACPI_FAILURE(status)) {
@@ -1966,7 +2017,7 @@
 	progress++;
 
 	/*
-	 * [5] Create the root device.
+	 * [7] Create the root device.
 	 */
 	result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 
 		ACPI_BUS_TYPE_SYSTEM);
@@ -1976,7 +2027,7 @@
 	progress++;
 
 	/*
-	 * [6] Create the root file system.
+	 * [8] Create the root file system.
 	 */
 	acpi_device_dir(acpi_root) = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
 	if (!acpi_root) {
@@ -1988,7 +2039,7 @@
 	progress++;
 
 	/*
-	 * [7] Install drivers required for proper enumeration of the
+	 * [9] Install drivers required for proper enumeration of the
 	 *     ACPI namespace.
 	 */
 	acpi_system_init();	/* ACPI System */
@@ -2003,7 +2054,7 @@
 	progress++;
 
 	/*
-	 * [8] Enumerate devices in the ACPI namespace.
+	 * [10] Enumerate devices in the ACPI namespace.
 	 */
 
 	result = acpi_bus_scan_fixed(acpi_root);
@@ -2017,11 +2068,12 @@
 end:
 	if (0 != result) {
 		switch (progress) {
-		case 9:
-		case 8: remove_proc_entry("ACPI", NULL);
-		case 7: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
-		case 6: acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
+		case 10:
+		case 9: remove_proc_entry("ACPI", NULL);
+		case 8: acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+		case 7: acpi_remove_notify_handler(ACPI_ROOT_OBJECT,
 				ACPI_SYSTEM_NOTIFY, &acpi_bus_notify);
+		case 6:
 		case 5:
 		case 4:
 		case 3:
@@ -2085,6 +2137,9 @@
 	printk(KERN_INFO PREFIX "Core Subsystem revision %08x\n",
 		ACPI_CA_VERSION);
 
+	/* Initial core debug level excludes drivers, so include them now */
+	acpi_set_debug(ACPI_DEBUG_LOW);
+
 	if (acpi_disabled) {
 		printk(KERN_INFO PREFIX "Disabled via command line (acpi=off)\n");
 		return -ENODEV;
@@ -2143,3 +2198,4 @@
 #endif
 
 __setup("acpi=", acpi_setup);
+
diff -Nru a/drivers/acpi/acpi_bus.h b/drivers/acpi/acpi_bus.h
--- a/drivers/acpi/acpi_bus.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/acpi_bus.h	Sun Apr 14 12:16:58 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_bus.h - ACPI Bus Driver ($Revision: 17 $)
+ *  acpi_bus.h - ACPI Bus Driver ($Revision: 19 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -96,8 +96,9 @@
 typedef int (*acpi_op_suspend)	(struct acpi_device *device, int state);
 typedef int (*acpi_op_resume)	(struct acpi_device *device, int state);
 typedef int (*acpi_op_scan)	(struct acpi_device *device);
+typedef int (*acpi_op_bind)	(struct acpi_device *device);
 
-struct acpi_driver_ops {
+struct acpi_device_ops {
 	acpi_op_add		add;
 	acpi_op_remove		remove;
 	acpi_op_lock		lock;
@@ -106,6 +107,7 @@
 	acpi_op_suspend		suspend;
 	acpi_op_resume		resume;
 	acpi_op_scan		scan;
+	acpi_op_bind		bind;
 };
 
 struct acpi_driver {
@@ -114,7 +116,7 @@
 	char			class[80];
 	int			references;
 	char			*ids;		/* Supported Hardware IDs */
-	struct acpi_driver_ops	ops;
+	struct acpi_device_ops	ops;
 };
 
 enum acpi_blacklist_predicates
@@ -157,14 +159,18 @@
 /* Flags */
 
 struct acpi_device_flags {
-	u8			dynamic_status:1;
-	u8			compatible_ids:1;
-	u8			removable:1;
-	u8			ejectable:1;
-	u8			lockable:1;
-	u8			suprise_removal_ok:1;
-	u8			power_manageable:1;
-	u8			performance_manageable:1;
+	u32			dynamic_status:1;
+	u32			hardware_id:1;
+	u32			compatible_ids:1;
+	u32			bus_address:1;
+	u32			unique_id:1;
+	u32			removable:1;
+	u32			ejectable:1;
+	u32			lockable:1;
+	u32			suprise_removal_ok:1;
+	u32			power_manageable:1;
+	u32			performance_manageable:1;
+	u32			reserved:21;
 };
 
 
@@ -206,13 +212,13 @@
 /* Power Management */
 
 struct acpi_device_power_flags {
-	u8			explicit_get:1;		     /* _PSC present? */
-	u8			power_resources:1;	   /* Power resources */
-	u8			inrush_current:1;	  /* Serialize Dx->D0 */
-	u8			wake_capable:1;		 /* Wakeup supported? */
-	u8			wake_enabled:1;		/* Enabled for wakeup */
-	u8			power_removed:1;	   /* Optimize Dx->D0 */
-	u8			reserved:2;
+	u32			explicit_get:1;		     /* _PSC present? */
+	u32			power_resources:1;	   /* Power resources */
+	u32			inrush_current:1;	  /* Serialize Dx->D0 */
+	u32			wake_capable:1;		 /* Wakeup supported? */
+	u32			wake_enabled:1;		/* Enabled for wakeup */
+	u32			power_removed:1;	   /* Optimize Dx->D0 */
+	u32			reserved:26;
 };
 
 struct acpi_device_power_state {
@@ -270,6 +276,7 @@
 	struct acpi_device_power power;
 	struct acpi_device_perf	performance;
 	struct acpi_device_dir	dir;
+	struct acpi_device_ops	ops;
 	struct acpi_driver	*driver;
 	void			*driver_data;
 #ifdef CONFIG_LDM
diff -Nru a/drivers/acpi/acpi_button.c b/drivers/acpi/acpi_button.c
--- a/drivers/acpi/acpi_button.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/acpi_button.c	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_button.c - ACPI Button Driver ($Revision: 22 $)
+ *  acpi_button.c - ACPI Button Driver ($Revision: 24 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -69,7 +69,7 @@
 #include <linux/compatmac.h>
 #include <linux/proc_fs.h>
 
-struct proc_dir_entry		*acpi_button_dir = NULL;
+static struct proc_dir_entry	*acpi_button_dir = NULL;
 
 
 static int
@@ -81,7 +81,6 @@
 	int 			*eof,
 	void			*data)
 {
-	int			result = 0;
 	struct acpi_button	*button = (struct acpi_button *) data;
 	char			*p = page;
 	int			len = 0;
@@ -111,22 +110,42 @@
 	struct acpi_device	*device)
 {
 	struct proc_dir_entry	*entry = NULL;
+	struct acpi_button	*button = NULL;
 
 	ACPI_FUNCTION_TRACE("acpi_button_add_fs");
 
+	if (!device || !acpi_driver_data(device))
+		return_VALUE(-EINVAL);
+
+	button = acpi_driver_data(device);
+
 	if (!acpi_button_dir) {
 		acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
 		if (!acpi_button_dir)
 			return_VALUE(-ENODEV);
 	}
 
-	if (!acpi_device_dir(device)) {
-		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+	switch (button->type) {
+	case ACPI_BUTTON_TYPE_POWER:
+	case ACPI_BUTTON_TYPE_POWERF:
+		entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER, 
 			acpi_button_dir);
-		if (!acpi_device_dir(device))
-			return_VALUE(-ENODEV);
+		break;
+	case ACPI_BUTTON_TYPE_SLEEP:
+	case ACPI_BUTTON_TYPE_SLEEPF:
+		entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP, 
+			acpi_button_dir);
+		break;
+	case ACPI_BUTTON_TYPE_LID:
+		entry = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, 
+			acpi_button_dir);
+		break;
 	}
 
+	acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
+	if (!acpi_device_dir(device))
+		return_VALUE(-ENODEV);
+
 	/* 'info' [R] */
 	entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
 		S_IRUGO, acpi_device_dir(device));
@@ -227,37 +246,46 @@
 
 	button->device = device;
 	button->handle = device->handle;
-	sprintf(acpi_device_class(device), "%s", ACPI_BUTTON_CLASS);
 	acpi_driver_data(device) = button;
 
 	/*
 	 * Determine the button type (via hid), as fixed-feature buttons
 	 * need to be handled a bit differently than generic-space.
 	 */
-	if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
-		button->type = ACPI_BUTTON_TYPE_POWERF;
-		sprintf(acpi_device_name(device), "%s",
-			ACPI_BUTTON_DEVICE_NAME_POWERF);
-	}
-	else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
-		button->type = ACPI_BUTTON_TYPE_SLEEPF;
-		sprintf(acpi_device_name(device), "%s",
-			ACPI_BUTTON_DEVICE_NAME_SLEEPF);
-	}
-	else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
+	if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWER)) {
 		button->type = ACPI_BUTTON_TYPE_POWER;
 		sprintf(acpi_device_name(device), "%s",
 			ACPI_BUTTON_DEVICE_NAME_POWER);
+		sprintf(acpi_device_class(device), "%s/%s", 
+			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
+	}
+	else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) {
+		button->type = ACPI_BUTTON_TYPE_POWERF;
+		sprintf(acpi_device_name(device), "%s",
+			ACPI_BUTTON_DEVICE_NAME_POWERF);
+		sprintf(acpi_device_class(device), "%s/%s", 
+			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
 	}
 	else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEP)) {
 		button->type = ACPI_BUTTON_TYPE_SLEEP;
 		sprintf(acpi_device_name(device), "%s",
 			ACPI_BUTTON_DEVICE_NAME_SLEEP);
+		sprintf(acpi_device_class(device), "%s/%s", 
+			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
+	}
+	else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) {
+		button->type = ACPI_BUTTON_TYPE_SLEEPF;
+		sprintf(acpi_device_name(device), "%s",
+			ACPI_BUTTON_DEVICE_NAME_SLEEPF);
+		sprintf(acpi_device_class(device), "%s/%s", 
+			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
 	}
 	else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_LID)) {
 		button->type = ACPI_BUTTON_TYPE_LID;
 		sprintf(acpi_device_name(device), "%s",
 			ACPI_BUTTON_DEVICE_NAME_LID);
+		sprintf(acpi_device_class(device), "%s/%s", 
+			ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
 	}
 	else {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported hid [%s]\n",
diff -Nru a/drivers/acpi/acpi_drivers.h b/drivers/acpi/acpi_drivers.h
--- a/drivers/acpi/acpi_drivers.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/acpi_drivers.h	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_drivers.h  ($Revision: 17 $)
+ *  acpi_drivers.h  ($Revision: 23 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -30,7 +30,7 @@
 #include "acpi_bus.h"
 
 
-#define ACPI_DRIVER_VERSION		0x20020308
+#define ACPI_DRIVER_VERSION		0x20020404
 #define ACPI_MAX_STRING			80
 
 
@@ -84,26 +84,32 @@
    -------------------------------------------------------------------------- */
 
 #define ACPI_BUTTON_COMPONENT		0x00080000
-#define ACPI_BUTTON_CLASS		"button"
-#define ACPI_BUTTON_HID_LID		"PNP0C0D"
-#define ACPI_BUTTON_HID_POWER		"PNP0C0C"	
-#define ACPI_BUTTON_HID_POWERF		"ACPI_FPB"
-#define ACPI_BUTTON_HID_SLEEP		"PNP0C0E"
-#define ACPI_BUTTON_HID_SLEEPF		"ACPI_FSB"
 #define ACPI_BUTTON_DRIVER_NAME		"ACPI Button Driver"
-#define ACPI_BUTTON_DEVICE_NAME_POWER	"Power Button"
-#define ACPI_BUTTON_DEVICE_NAME_POWERF	"Power Button"
-#define ACPI_BUTTON_DEVICE_NAME_SLEEP	"Sleep Button"
-#define ACPI_BUTTON_DEVICE_NAME_SLEEPF	"Sleep Button"
-#define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
+#define ACPI_BUTTON_CLASS		"button"
 #define ACPI_BUTTON_FILE_INFO		"info"
 #define ACPI_BUTTON_TYPE_UNKNOWN	0x00
+#define ACPI_BUTTON_NOTIFY_STATUS	0x80
+
+#define ACPI_BUTTON_SUBCLASS_POWER	"power"
+#define ACPI_BUTTON_HID_POWER		"PNP0C0C"	
+#define ACPI_BUTTON_HID_POWERF		"ACPI_FPB"
+#define ACPI_BUTTON_DEVICE_NAME_POWER	"Power Button (CM)"
+#define ACPI_BUTTON_DEVICE_NAME_POWERF	"Power Button (FF)"
 #define ACPI_BUTTON_TYPE_POWER		0x01
 #define ACPI_BUTTON_TYPE_POWERF		0x02
+
+#define ACPI_BUTTON_SUBCLASS_SLEEP	"sleep"
+#define ACPI_BUTTON_HID_SLEEP		"PNP0C0E"
+#define ACPI_BUTTON_HID_SLEEPF		"ACPI_FSB"
+#define ACPI_BUTTON_DEVICE_NAME_SLEEP	"Sleep Button (CM)"
+#define ACPI_BUTTON_DEVICE_NAME_SLEEPF	"Sleep Button (FF)"
 #define ACPI_BUTTON_TYPE_SLEEP		0x03
 #define ACPI_BUTTON_TYPE_SLEEPF		0x04
+
+#define ACPI_BUTTON_SUBCLASS_LID	"lid"
+#define ACPI_BUTTON_HID_LID		"PNP0C0D"
+#define ACPI_BUTTON_DEVICE_NAME_LID	"Lid Switch"
 #define ACPI_BUTTON_TYPE_LID		0x05
-#define ACPI_BUTTON_NOTIFY_STATUS	0x80
 
 
 /* --------------------------------------------------------------------------
@@ -217,7 +223,7 @@
 #define ACPI_PROCESSOR_LIMIT_INCREMENT	0x01
 #define ACPI_PROCESSOR_LIMIT_DECREMENT	0x02
 
-int acpi_processor_set_limit(acpi_handle handle, int flags, int *state);
+int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
 
 
 /* --------------------------------------------------------------------------
diff -Nru a/drivers/acpi/acpi_ec.c b/drivers/acpi/acpi_ec.c
--- a/drivers/acpi/acpi_ec.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/acpi_ec.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 27 $)
+ *  acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 28 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -345,7 +345,7 @@
 	if (0 != acpi_ec_query(ec, &value))
 		return;
 
-	query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_KERNEL);
+	query_data = kmalloc(sizeof(struct acpi_ec_query_data), GFP_ATOMIC);
 	if (!query_data)
 		return;
 	query_data->handle = ec->handle;
diff -Nru a/drivers/acpi/acpi_osl.c b/drivers/acpi/acpi_osl.c
--- a/drivers/acpi/acpi_osl.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/acpi_osl.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_osl.c - OS-dependent functions ($Revision: 65 $)
+ *  acpi_osl.c - OS-dependent functions ($Revision: 69 $)
  *
  *  Copyright (C) 2000 Andrew Henroid
  *  Copyright (C) 2001 Andrew Grover
@@ -125,13 +125,13 @@
 }
 
 void *
-acpi_os_allocate(u32 size)
+acpi_os_allocate(ACPI_SIZE size)
 {
 	return kmalloc(size, GFP_KERNEL);
 }
 
 void *
-acpi_os_callocate(u32 size)
+acpi_os_callocate(ACPI_SIZE size)
 {
 	void *ptr = acpi_os_allocate(size);
 	if (ptr)
@@ -148,21 +148,22 @@
 
 
 acpi_status
-acpi_os_get_root_pointer(u32 flags, ACPI_PHYSICAL_ADDRESS *phys_addr)
+acpi_os_get_root_pointer(u32 flags, ACPI_POINTER *addr)
 {
 #ifndef CONFIG_ACPI_EFI
-	if (ACPI_FAILURE(acpi_find_root_pointer(flags, phys_addr))) {
+	if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
 		printk(KERN_ERR PREFIX "System description tables not found\n");
 		return AE_NOT_FOUND;
 	}
 #else /*CONFIG_ACPI_EFI*/
+	addr->pointer_type = ACPI_PHYSICAL_POINTER;
 	if (efi.acpi20)
-		*phys_addr = (ACPI_PHYSICAL_ADDRESS) efi.acpi20;
+		addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) efi.acpi20;
 	else if (efi.acpi)
-		*phys_addr = (ACPI_PHYSICAL_ADDRESS) efi.acpi;
+		addr->pointer.physical = (ACPI_PHYSICAL_ADDRESS) efi.acpi;
 	else {
 		printk(KERN_ERR PREFIX "System description tables not found\n");
-		*phys_addr = 0;
+		addr->pointer.physical = 0;
 		return AE_NOT_FOUND;
 	}
 #endif /*CONFIG_ACPI_EFI*/
@@ -171,7 +172,7 @@
 }
 
 acpi_status
-acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, u32 size, void **virt)
+acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size, void **virt)
 {
 	if (phys > ULONG_MAX) {
 		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
@@ -189,7 +190,7 @@
 }
 
 void
-acpi_os_unmap_memory(void *virt, u32 size)
+acpi_os_unmap_memory(void *virt, ACPI_SIZE size)
 {
 	iounmap(virt);
 }
@@ -441,14 +442,14 @@
 	ACPI_FUNCTION_TRACE ("os_load_module");
 
 	if (!module_name)
-		return AE_BAD_PARAMETER;
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 
 	if (0 > request_module(module_name)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to load module [%s].\n", module_name));
-		return AE_ERROR;
+		return_ACPI_STATUS (AE_ERROR);
 	}
 
-	return AE_OK;
+	return_ACPI_STATUS (AE_OK);
 }
 
 acpi_status
@@ -481,7 +482,7 @@
 	strcpy(current->comm, "kacpidpc");
 
 	if (!dpc || !dpc->function)
-		return AE_BAD_PARAMETER;
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing function [%p(%p)].\n", dpc->function, dpc->context));
 
@@ -489,7 +490,7 @@
 
 	kfree(dpc);
 
-	return 1;
+	return_ACPI_STATUS (AE_OK);
 }
 
 static void
@@ -504,7 +505,7 @@
 	dpc = (ACPI_OS_DPC*)context;
 	if (!dpc) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
-		return;
+		return_VOID;
 	}
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating new thread to run function [%p(%p)].\n", dpc->function, dpc->context));
@@ -515,6 +516,7 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to kernel_thread() failed.\n"));
 		acpi_os_free(dpc);
 	}
+    return_VOID;
 }
 
 acpi_status
@@ -531,7 +533,7 @@
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Scheduling function [%p(%p)] for deferred execution.\n", function, context));
 
 	if (!function)
-		return AE_BAD_PARAMETER;
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 
 	/*
 	 * Queue via DPC:
@@ -554,7 +556,7 @@
 		 */
 		dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_ATOMIC);
 		if (!dpc)
-			return AE_NO_MEMORY;
+			return_ACPI_STATUS (AE_NO_MEMORY);
 
 		dpc->function = function;
 		dpc->context = context;
@@ -578,7 +580,7 @@
 		 */
 		dpc = kmalloc(sizeof(ACPI_OS_DPC), GFP_KERNEL);
 		if (!dpc)
-			return AE_NO_MEMORY;
+			return_ACPI_STATUS (AE_NO_MEMORY);
 
 		dpc->function = function;
 		dpc->context = context;
@@ -587,7 +589,7 @@
 		break;
 	}
 
-	return status;
+	return_ACPI_STATUS (status);
 }
 
 
@@ -603,7 +605,7 @@
 
 	sem = acpi_os_callocate(sizeof(struct semaphore));
 	if (!sem)
-		return AE_NO_MEMORY;
+		return_ACPI_STATUS (AE_NO_MEMORY);
 
 	sema_init(sem, initial_units);
 
@@ -611,7 +613,7 @@
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Creating semaphore[%p|%d].\n", *handle, initial_units));
 
-	return AE_OK;
+	return_ACPI_STATUS (AE_OK);
 }
 
 
@@ -631,13 +633,13 @@
 	ACPI_FUNCTION_TRACE ("os_delete_semaphore");
 
 	if (!sem)
-		return AE_BAD_PARAMETER;
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting semaphore[%p].\n", handle));
 
 	acpi_os_free(sem); sem =  NULL;
 
-	return AE_OK;
+	return_ACPI_STATUS (AE_OK);
 }
 
 
@@ -663,10 +665,10 @@
 	ACPI_FUNCTION_TRACE ("os_wait_semaphore");
 
 	if (!sem || (units < 1))
-		return AE_BAD_PARAMETER;
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 
 	if (units > 1)
-		return AE_SUPPORT;
+		return_ACPI_STATUS (AE_SUPPORT);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout));
 
@@ -724,7 +726,7 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired semaphore[%p|%d|%d]\n", handle, units, timeout));
 	}
 
-	return status;
+	return_ACPI_STATUS (status);
 }
 
 
@@ -741,16 +743,16 @@
 	ACPI_FUNCTION_TRACE ("os_signal_semaphore");
 
 	if (!sem || (units < 1))
-		return AE_BAD_PARAMETER;
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 
 	if (units > 1)
-		return AE_SUPPORT;
+		return_ACPI_STATUS (AE_SUPPORT);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Signaling semaphore[%p|%d]\n", handle, units));
 
 	up(sem);
 
-	return AE_OK;
+	return_ACPI_STATUS (AE_OK);
 }
 
 u32
diff -Nru a/drivers/acpi/acpi_pci_link.c b/drivers/acpi/acpi_pci_link.c
--- a/drivers/acpi/acpi_pci_link.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/acpi_pci_link.c	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 19 $)
+ *  acpi_pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 22 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -92,35 +92,23 @@
    -------------------------------------------------------------------------- */
 
 static int
-acpi_pci_link_get_current (
+acpi_pci_link_get_possible (
 	struct acpi_pci_link	*link)
 {
-	int			result = 0;
+	int                     result = 0;
 	acpi_status		status = AE_OK;
-	acpi_buffer		buffer = {0, NULL};
+	acpi_buffer		buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_resource		*resource = NULL;
+	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
+	ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
 
-	if (!link || !link->handle)
+	if (!link)
 		return_VALUE(-EINVAL);
 
-	link->irq.active = 0;
-
-	status = acpi_get_current_resources(link->handle, &buffer);
-	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
-		return_VALUE(-ENODEV);
-	}
-
-	buffer.pointer = kmalloc(buffer.length, GFP_KERNEL);
-	if (!buffer.pointer)
-		return_VALUE(-ENOMEM);
-	memset(buffer.pointer, 0, buffer.length);
-
-	status = acpi_get_current_resources(link->handle, &buffer);
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
+	status = acpi_get_possible_resources(link->handle, &buffer);
+	if (ACPI_FAILURE(status) || !buffer.pointer) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
 		result = -ENODEV;
 		goto end;
 	}
@@ -131,69 +119,84 @@
 	case ACPI_RSTYPE_IRQ:
 	{
 		acpi_resource_irq *p = &resource->data.irq;
-		if (p->number_of_interrupts > 0)
-			link->irq.active = p->interrupts[0];
-		else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Blank IRQ resource\n"));
+
+		if (!p || !p->number_of_interrupts) {
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
+				"Blank IRQ resource\n"));
 			result = -ENODEV;
 			goto end;
 		}
+
+		for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) {
+			link->irq.possible[i] = p->interrupts[i];
+			link->irq.possible_count++;
+		}
+
+		link->irq.flags.trigger = p->edge_level;
+		link->irq.flags.polarity = p->active_high_low;
+		link->irq.flags.shareable = p->shared_exclusive;
+
 		break;
 	}
 	case ACPI_RSTYPE_EXT_IRQ:
 	{
 		acpi_resource_ext_irq *p = &resource->data.extended_irq;
-		if (p->number_of_interrupts > 0)
-			link->irq.active = p->interrupts[0];
-		else {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Blank IRQ resource\n"));
+
+		if (!p || !p->number_of_interrupts) {
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
+				"Blank IRQ resource\n"));
 			result = -ENODEV;
 			goto end;
 		}
+
+		for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) {
+			link->irq.possible[i] = p->interrupts[i];
+			link->irq.possible_count++;
+		}
+
+		link->irq.flags.trigger = p->edge_level;
+		link->irq.flags.polarity = p->active_high_low;
+		link->irq.flags.shareable = p->shared_exclusive;
+
 		break;
 	}
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
-			"First resource is not an IRQ entry\n"));
+			"Resource is not an IRQ entry\n"));
+		result = -ENODEV;
+		goto end;
 		break;
 	}
+	
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Found %d possible IRQs\n", link->irq.possible_count));
 
 end:
 	kfree(buffer.pointer);
 
-	return_VALUE(0);
+	return_VALUE(result);
 }
 
 
 static int
-acpi_pci_link_get_possible (
+acpi_pci_link_get_current (
 	struct acpi_pci_link	*link)
 {
-	int                     result = 0;
+	int			result = 0;
 	acpi_status		status = AE_OK;
-	acpi_buffer		buffer = {0, NULL};
+	acpi_buffer		buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_resource		*resource = NULL;
-	int			i = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_link_get_possible");
+	ACPI_FUNCTION_TRACE("acpi_pci_link_get_current");
 
-	if (!link)
+	if (!link || !link->handle)
 		return_VALUE(-EINVAL);
 
-	status = acpi_get_possible_resources(link->handle, &buffer);
-	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
-		return_VALUE(-ENODEV);
-	}
-
-	buffer.pointer = kmalloc(buffer.length, GFP_KERNEL);
-	if (!buffer.pointer)
-		return_VALUE(-ENOMEM);
-	memset(buffer.pointer, 0, buffer.length);
+	link->irq.active = 0;
 
-	status = acpi_get_possible_resources(link->handle, &buffer);
+	status = acpi_get_current_resources(link->handle, &buffer);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRS\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _CRS\n"));
 		result = -ENODEV;
 		goto end;
 	}
@@ -205,20 +208,14 @@
 	{
 		acpi_resource_irq *p = &resource->data.irq;
 
-		for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) {
-			link->irq.possible[i] = p->interrupts[i];
-			link->irq.possible_count++;
-		}
-
-		if (!p->number_of_interrupts) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Blank IRQ resource\n"));
+		if (!p || !p->number_of_interrupts) {
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
+				"Blank IRQ resource\n"));
 			result = -ENODEV;
 			goto end;
 		}
 
-		link->irq.flags.trigger = p->edge_level;
-		link->irq.flags.polarity = p->active_high_low;
-		link->irq.flags.shareable = p->shared_exclusive;
+		link->irq.active = p->interrupts[0];
 
 		break;
 	}
@@ -226,32 +223,36 @@
 	{
 		acpi_resource_ext_irq *p = &resource->data.extended_irq;
 
-		for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_IRQS); i++) {
-			link->irq.possible[i] = p->interrupts[i];
-			link->irq.possible_count++;
-		}
-
-		if (!p->number_of_interrupts) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Blank IRQ resource\n"));
+		if (!p || !p->number_of_interrupts) {
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+				"Blank IRQ resource\n"));
 			result = -ENODEV;
 			goto end;
 		}
 
-		link->irq.flags.trigger = p->edge_level;
-		link->irq.flags.polarity = p->active_high_low;
-		link->irq.flags.shareable = p->shared_exclusive;
+		link->irq.active = p->interrupts[0];
 
 		break;
 	}
 	default:
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
-			"First resource is not an IRQ entry\n"));
+			"Resource is not an IRQ entry\n"));
 		break;
 	}
 
+	if (!link->irq.active) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Invalid IRQ %d\n", link->irq.active));
+		result = -ENODEV;
+	}
+
 end:
 	kfree(buffer.pointer);
 
+	if (0 == result)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n",
+			link->irq.active));
+	
 	return_VALUE(result);
 }
 
@@ -259,7 +260,7 @@
 static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
-	u32			irq)
+	int			irq)
 {
 	acpi_status		status = AE_OK;
 	struct {
@@ -290,6 +291,8 @@
 		return_VALUE(-ENODEV);
 	}
 
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", irq));
+	
 	return_VALUE(0);
 }
 
@@ -328,8 +331,10 @@
 		return_VALUE(-ENODEV);
 	}
 
-	if (!link->irq.flags.valid) 
+	if (!link->irq.flags.valid) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ invalid\n"));
 		return_VALUE(-ENODEV);
+	}
 
 	/* TBD: Support multiple index (IRQ) entries per Link Device */
 	if (0 != entry->source.index) {
@@ -361,7 +366,7 @@
 	if (!entry || !entry->source.handle || !irq)
 		return_VALUE(-EINVAL);
 
-	/* TBD: Support multiple index values (not just first). */
+	/* TBD: Support multiple index (IRQ) entries per Link Device */
 	if (0 != entry->source.index) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 			"Unsupported resource index [%d]\n", 
@@ -386,7 +391,8 @@
 
 	/* Is the target IRQ the same as the currently enabled IRQ? */
 	if (link->irq.flags.enabled && (irq == link->irq.active)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link IRQ already at target\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link already at IRQ %d\n",
+			irq));
 		return_VALUE(0);
 	}
 
@@ -413,6 +419,85 @@
 }
 
 
+static int
+acpi_pci_link_enable (
+	struct acpi_device	*device,
+	struct acpi_pci_link	*link)
+{
+	int			result = -ENODEV;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_link_enable");
+
+	if (!device || !link)
+		return_VALUE(-EINVAL);
+
+	result = acpi_pci_link_get_possible(link);
+	if (0 != result)
+		return_VALUE(result);
+
+	result = acpi_bus_get_status(device);
+	if (0 != result) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	/*
+	 * If this link device isn't enabled (_STA bit 1) then we enable it
+	 * by setting an IRQ.
+	 */
+	if (!device->status.enabled) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"Attempting to enable at IRQ [%d]\n", 
+			link->irq.possible[0]));
+
+		result = acpi_pci_link_set(link, link->irq.possible[0]);
+		if (0 != result)
+			return_VALUE(result);
+
+		result = acpi_bus_get_status(device);
+		if (0 != result) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Unable to read status\n"));
+			return_VALUE(-ENODEV);
+		}
+
+		if (!device->status.enabled) {
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Enable failed\n"));
+			return_VALUE(-ENODEV);
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link enabled at IRQ %d\n", 
+			link->irq.possible[0]));
+	}
+
+	/*
+	 * Now we get the current IRQ just to make sure everything is kosher.
+	 */
+	result = acpi_pci_link_get_current(link);
+	if (0 != result) {
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
+			"Current IRQ invalid, setting to default\n"));
+
+		result = acpi_pci_link_set(link, link->irq.possible[0]);
+		if (0 != result)
+			return_VALUE(result);
+
+		result = acpi_pci_link_get_current(link);
+		if (0 != result) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Unable to read current IRQ\n"));
+			return_VALUE(result);
+		}
+	}
+
+  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using IRQ %d\n", link->irq.active));
+
+	link->irq.flags.valid = 1;
+
+	return_VALUE(0);
+}
+
+
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -440,34 +525,9 @@
 	sprintf(acpi_device_class(device), "%s", ACPI_PCI_LINK_CLASS);
 	acpi_driver_data(device) = link;
 
-	result = acpi_pci_link_get_possible(link);
-	if (0 != result)
-		return_VALUE(result);
-
-	if (!device->status.enabled) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Enabling at IRQ [%d]\n",
-			link->irq.possible[0]));
-
-		result = acpi_pci_link_set(link, link->irq.possible[0]);
-		if (0 != result)
-			return_VALUE(result);
-
-		result = acpi_bus_get_status(device);
-		if (0 != result)
-			return_VALUE(result);
-
-		if (!device->status.enabled) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
-				"Enable failed\n"));
-			return_VALUE(-EFAULT);
-		}
-	}
-
-	result = acpi_pci_link_get_current(link);
+	result = acpi_pci_link_enable(device, link);
 	if (0 != result)
-		return_VALUE(result);
-
-	link->irq.flags.valid = 1;
+		goto end;
 
 	printk(PREFIX "%s [%s] (IRQs", 
 		acpi_device_name(device), acpi_device_bid(device));
@@ -477,7 +537,11 @@
 			link->irq.possible[i]);
 	printk(")\n");
 
-	return_VALUE(0);
+end:
+	if (0 != result)
+		kfree(link);
+
+	return_VALUE(result);
 }
 
 
diff -Nru a/drivers/acpi/acpi_pci_root.c b/drivers/acpi/acpi_pci_root.c
--- a/drivers/acpi/acpi_pci_root.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/acpi_pci_root.c	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 22 $)
+ *  acpi_pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 30 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -48,6 +48,7 @@
 
 static int acpi_pci_root_add (struct acpi_device *device);
 static int acpi_pci_root_remove (struct acpi_device *device, int type);
+static int acpi_pci_root_bind (struct acpi_device *device);
 
 static struct acpi_driver acpi_pci_root_driver = {
         name:                   ACPI_PCI_ROOT_DRIVER_NAME,
@@ -56,20 +57,20 @@
         ops:                    {
                                         add:    acpi_pci_root_add,
                                         remove: acpi_pci_root_remove,
+					bind:	acpi_pci_root_bind,
                                 },
 };
 
-struct acpi_pci_root_context {
-	acpi_handle		handle;
-	struct {
-		u8			seg;	/* Root's segment number */
-		u8			bus;	/* Root's bus number */
-		u8			sub;	/* Max subordinate bus */
-	}			id;
-	struct pci_bus		*bus;
+struct acpi_pci_data {
+	acpi_pci_id		id;
 	struct pci_dev		*dev;
 };
 
+struct acpi_pci_root {
+	acpi_handle		handle;
+	struct acpi_pci_data	data;
+};
+
 struct acpi_prt_list		acpi_prts;
 
 
@@ -77,25 +78,33 @@
                         PCI Routing Table (PRT) Support
    -------------------------------------------------------------------------- */
 
-static struct acpi_prt_entry *
+static int
 acpi_prt_find_entry (
-	struct pci_dev		*dev,
-	u8			pin)
+	acpi_pci_id		*id,
+	u8			pin,
+	struct acpi_prt_entry	**entry)
 {
-	struct acpi_prt_entry	*entry = NULL;
 	struct list_head	*node = NULL;
 
 	ACPI_FUNCTION_TRACE("acpi_prt_find_entry");
 
+	if (!id || !entry)
+		return_VALUE(-ENODEV);
+
 	/* TBD: Locking */
 	list_for_each(node, &acpi_prts.entries) {
-		entry = list_entry(node, struct acpi_prt_entry, node);
-		if ((entry->id.dev == PCI_SLOT(dev->devfn)) 
-			&& (entry->id.pin == pin))
-			return_PTR(entry);
+		(*entry) = list_entry(node, struct acpi_prt_entry, node);
+		/* TBD: Include check for segment when supported by pci_dev */
+		if ((id->bus == (*entry)->id.bus) 
+			&& (id->device == (*entry)->id.dev)
+			&& (pin == (*entry)->id.pin)) {
+			return_VALUE(0);
+		}
 	}
 
-	return_PTR(NULL);
+	(*entry) = NULL;
+
+	return_VALUE(-ENODEV);
 }
 
 
@@ -107,23 +116,49 @@
 {
 	int			result = 0;
 	struct acpi_prt_entry	*entry = NULL;
+	acpi_pci_id		id = {0, 0, 0, 0};
 
-	ACPI_FUNCTION_TRACE("acpi_pci_get_current_irq");
+	ACPI_FUNCTION_TRACE("acpi_prt_get_irq");
 
 	if (!dev || !irq)
 		return_VALUE(-ENODEV);
 
-	entry = acpi_prt_find_entry(dev, pin);
-	if (!entry)
-		return_VALUE(-ENODEV);
+	if (!dev->bus) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Device has invalid 'bus' field\n"));
+		return_VALUE(-EFAULT);
+	}
+
+	id.segment = 0;
+	id.bus = dev->bus->number;
+	id.device = PCI_SLOT(dev->devfn);
+	id.function = PCI_FUNC(dev->devfn);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Resolving IRQ for %02x:%02x:%02x.%02x[%c]\n",
+		id.segment, id.bus, id.device, id.function, ('A'+pin)));
+
+	result = acpi_prt_find_entry(&id, pin, &entry);
+	if (0 != result)
+		return_VALUE(result);
 
 	/* Type 1: Dynamic (e.g. PCI Link Device) */
 	if (entry->source.handle)
 		result = acpi_pci_link_get_irq(entry, irq);
+
 	/* Type 2: Static (e.g. I/O [S]APIC Direct) */
-	else
-		*irq = entry->source.index;
+	else {
+		if (entry->source.index)
+			*irq = entry->source.index;
+		else
+			result = -ENODEV;
+	}
 	
+	if (0 == result)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", *irq));
+	else
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to reslove IRQ\n"));
+
 	return_VALUE(0);
 }
 
@@ -135,18 +170,32 @@
 	int			irq)
 {
 	int			result = 0;
-	int			i = 0;
-	int			valid = 0;
 	struct acpi_prt_entry	*entry = NULL;
+	acpi_pci_id		id = {0, 0, 0, 0};
 
-	ACPI_FUNCTION_TRACE("acpi_pci_set_current_irq");
+	ACPI_FUNCTION_TRACE("acpi_pci_set_irq");
 
 	if (!dev || !irq)
 		return_VALUE(-EINVAL);
 
-	entry = acpi_prt_find_entry(dev, pin);
-	if (!entry)
-		return_VALUE(-ENODEV);
+	if (!dev->bus) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Device has invalid 'bus' field\n"));
+		return_VALUE(-EFAULT);
+	}
+
+	id.segment = 0;
+	id.bus = dev->bus->number;
+	id.device = PCI_SLOT(dev->devfn);
+	id.function = PCI_FUNC(dev->devfn);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Setting %02x:%02x:%02x.%02x[%c] to IRQ%d\n",
+		id.segment, id.bus, id.device, id.function, ('A'+pin), irq));
+
+	result = acpi_prt_find_entry(&id, pin, &entry);
+	if (0 != result)
+		return_VALUE(result);
 
 	/* Type 1: Dynamic (e.g. PCI Link Device) */
 	if (entry->source.handle)
@@ -155,6 +204,11 @@
 	else
 		result = -EFAULT;
 	
+	if (0 == result)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "IRQ set\n"));
+	else
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set IRQ\n"));
+
 	return_VALUE(result);
 }
 
@@ -212,9 +266,9 @@
 	 *       namespace).
 	 */
 
-	printk(KERN_INFO "      %02X:%02X:%02X[%c] -> %s[%d]\n", 
+	ACPI_DEBUG_PRINT_RAW((ACPI_DB_OK, "      %02X:%02X:%02X[%c] -> %s[%d]\n", 
 		entry->id.seg, entry->id.bus, entry->id.dev, 
-		('A' + entry->id.pin), prt->source, entry->source.index);
+		('A' + entry->id.pin), prt->source, entry->source.index));
 
 	/* TBD: Acquire/release lock */
 	list_add_tail(&entry->node, &acpi_prts.entries);
@@ -225,57 +279,23 @@
 }
 
 
-static acpi_status
-acpi_prt_callback (
-	acpi_handle             handle,
-	u32                     nesting_level,
-	void                    *context,
-	void                    **return_value)
+static int
+acpi_prt_parse (
+	acpi_handle		handle,
+	u8			seg,
+	u8			bus)
 {
 	acpi_status		status = AE_OK;
-	acpi_handle		prt_handle = NULL;
 	char			pathname[PATHNAME_MAX] = {0};
 	acpi_buffer		buffer = {0, NULL};
 	acpi_pci_routing_table	*prt = NULL;
-	unsigned long		sta = 0;
-	struct acpi_pci_root_context *root = (struct acpi_pci_root_context *) context;
-	u8			bus_number = 0;
-
-	ACPI_FUNCTION_TRACE("acpi_prt_callback");
 
-	if (!root)
-		return_VALUE(AE_BAD_PARAMETER);
-
-	status = acpi_get_handle(handle, METHOD_NAME__PRT, &prt_handle);
-	if (ACPI_FAILURE(status))
-		return_VALUE(AE_OK);
+	ACPI_FUNCTION_TRACE("acpi_prt_parse");
 
 	buffer.length = sizeof(pathname);
 	buffer.pointer = pathname;
 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
-	/* 
-	 * Evalute _STA to see if the device containing this _PRT is present.
-	 */
-	status = acpi_evaluate_integer(handle, METHOD_NAME__STA, NULL, &sta);
-	switch (status) {
-	case AE_OK:
-		if (!(sta & 0x01)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				"Found _PRT but device [%s] not present\n", 
-				pathname));
-			return_VALUE(AE_OK);
-		}
-		break;
-	case AE_NOT_FOUND:
-		/* assume present */
-		break;
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating %s._STA [%s]\n", 
-			pathname, acpi_format_exception(status)));
-		return_VALUE(status);
-	}
-
 	printk(KERN_INFO PREFIX "%s [%s._PRT]\n", ACPI_PCI_PRT_DEVICE_NAME, 
 		pathname);
 
@@ -287,9 +307,10 @@
 	buffer.pointer = NULL;
 	status = acpi_get_irq_routing_table(handle, &buffer);
 	if (status != AE_BUFFER_OVERFLOW) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PRT [%s]\n", 
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Error evaluating _PRT [%s]\n",
 			acpi_format_exception(status)));
-		return_VALUE(status);
+		return_VALUE(-ENODEV);
 	}
 
 	prt = kmalloc(buffer.length, GFP_KERNEL);
@@ -300,144 +321,401 @@
 
 	status = acpi_get_irq_routing_table(handle, &buffer);
 	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PRT [%s]\n", 
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Error evaluating _PRT [%s]\n",
 			acpi_format_exception(status)));
 		kfree(buffer.pointer);
-		return_VALUE(status);
-	}
-
-	if (root->handle == handle)
-		bus_number = root->id.bus;
-	else {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Need to get subordinate bus number!\n"));
-		/* get the bus number for this device */
+		return_VALUE(-ENODEV);
 	}
 
 	while (prt && (prt->length > 0)) {
-		acpi_prt_add_entry(handle, root->id.seg, bus_number, prt);
+		acpi_prt_add_entry(handle, seg, bus, prt);
 		prt = (acpi_pci_routing_table*)((unsigned long)prt + prt->length);
 	}
 
-	return_VALUE(AE_OK);
+	return_VALUE(0);
 }
 
 
 /* --------------------------------------------------------------------------
-                                Driver Interface
+                             PCI Device Binding
    -------------------------------------------------------------------------- */
 
-int
-acpi_pci_root_add (
+static void
+acpi_pci_data_handler (
+	acpi_handle		handle,
+	u32			function,
+	void			*context)
+{
+	ACPI_FUNCTION_TRACE("acpi_pci_data_handler");
+
+	/* TBD: Anything we need to do here? */
+
+	return_VOID;
+}
+
+
+/**
+ * acpi_os_get_pci_id
+ * ------------------
+ * This function gets used by the ACPI Interpreter (a.k.a. Core Subsystem)
+ * to resolve PCI information for ACPI-PCI devices defined in the namespace.
+ */
+acpi_status
+acpi_os_get_pci_id (
+	acpi_handle		handle,
+	acpi_pci_id		*id)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	struct acpi_device	*device = NULL;
+	struct acpi_pci_data	*data = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");
+
+	if (!id)
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+
+	result = acpi_bus_get_device(handle, &device);
+	if (0 != result) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Invalid ACPI Bus context for device %s\n",
+			acpi_device_bid(device)));
+		return_ACPI_STATUS(AE_NOT_EXIST);
+	}
+
+	status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
+	if (ACPI_FAILURE(status) || !data || !data->dev) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Invalid ACPI-PCI context for device %s\n",
+			acpi_device_bid(device)));
+		return_ACPI_STATUS(status);
+	}
+	
+	id->segment = data->id.segment;
+	id->bus = data->id.bus;
+	id->device = data->id.device;
+	id->function = data->id.function;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Device %s has PCI address %02x:%02x:%02x.%02x\n", 
+		acpi_device_bid(device), id->segment, id->bus, 
+		id->device, id->function));
+
+	return_ACPI_STATUS(AE_OK);
+}
+
+	
+static int
+acpi_pci_root_bind (
 	struct acpi_device	*device)
 {
+	int			result = 0;
 	acpi_status		status = AE_OK;
-	struct acpi_pci_root_context *context = NULL;
-	unsigned long		temp = 0;
+	struct acpi_pci_data	*data = NULL;
+	struct acpi_pci_data	*parent_data = NULL;
+	acpi_handle		handle = NULL;
 
-	ACPI_FUNCTION_TRACE("acpi_pci_root_add");
+	ACPI_FUNCTION_TRACE("acpi_pci_root_bind");
 
-	if (!device)
+	if (!device || !device->parent)
 		return_VALUE(-EINVAL);
 
-	context = kmalloc(sizeof(struct acpi_pci_root_context), GFP_KERNEL);
-	if (!context)
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to bind PCI device %s.%s\n", 
+		acpi_device_bid(device->parent), acpi_device_bid(device)));
+
+	data = kmalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
+	if (!data)
 		return_VALUE(-ENOMEM);
-	memset(context, 0, sizeof(struct acpi_pci_root_context));
+	memset(data, 0, sizeof(struct acpi_pci_data));
 
-	context->handle = device->handle;
-	sprintf(acpi_device_name(device), "%s", ACPI_PCI_ROOT_DEVICE_NAME);
-	sprintf(acpi_device_class(device), "%s", ACPI_PCI_ROOT_CLASS);
-	acpi_driver_data(device) = context;
+	/* 
+	 * Segment & Bus
+	 * -------------
+	 * These are obtained via the parent device's ACPI-PCI context..
+	 * Note that PCI root bridge devices don't have a 'dev->subordinate'.
+	 */
+	status = acpi_get_data(device->parent->handle, acpi_pci_data_handler, 
+		(void**) &parent_data);
+	if (ACPI_FAILURE(status) || !parent_data || !parent_data->dev) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Invalid ACPI-PCI context for parent device %s\n",
+			acpi_device_bid(device->parent)));
+		result = -ENODEV;
+		goto end;
+	}
 
-	status = acpi_evaluate_integer(context->handle, METHOD_NAME__SEG, 
-		NULL, &temp);
-	if (ACPI_SUCCESS(status))
-		context->id.seg = temp;
-	else
-		context->id.seg = 0;
+	data->id.segment = parent_data->id.segment;
 
-	status = acpi_evaluate_integer(context->handle, METHOD_NAME__BBN, 
-		NULL, &temp);
-	if (ACPI_SUCCESS(status))
-		context->id.bus = temp;
-	else
-		context->id.bus = 0;
+	if (parent_data->dev->subordinate)	       /* e.g. PCI-PCI bridge */
+		data->id.bus = parent_data->dev->subordinate->number;
+	else if (parent_data->dev->bus)			   /* PCI root bridge */
+		data->id.bus = parent_data->dev->bus->number;
+	else {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Parent device %s is not a PCI bridge\n",
+			acpi_device_bid(device->parent)));
+		result = -ENODEV;
+		goto end;
+	}
 
-	/* TBD: Evaluate _CRS for bus range of child P2P (bus min/max/len) */
+	/*
+	 * Device & Function
+	 * -----------------
+	 * These are simply obtained from the device's _ADR method.  Note
+	 * that a value of zero is valid.
+	 */
+	data->id.device = device->pnp.bus_address >> 16;
+	data->id.function = device->pnp.bus_address & 0xFFFF;
 
-	printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n", 
-		acpi_device_name(device), acpi_device_bid(device),
-		context->id.seg, context->id.bus);
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Binding device %s.%s to %02x:%02x:%02x.%02x\n", 
+		acpi_device_bid(device->parent), acpi_device_bid(device), 
+		data->id.segment, data->id.bus, data->id.device, 
+		data->id.function));
+
+	/* 
+	 * Locate PCI Device
+	 * -----------------
+	 * Locate matching device in PCI namespace.  If it doesn't exist
+	 * this typically means that the device isn't currently inserted
+	 * (e.g. docking station, port replicator, etc.).
+	 */
+	data->dev = pci_find_slot(data->id.bus, 
+		PCI_DEVFN(data->id.device, data->id.function));
+	if (!data->dev) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
+			data->id.segment, data->id.bus, 
+			data->id.device, data->id.function));
+		result = -ENODEV;
+		goto end;
+	}
+	if (!data->dev->bus) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
+			data->id.segment, data->id.bus, 
+			data->id.device, data->id.function));
+		result = -ENODEV;
+		goto end;
+	}
 
 	/*
-	 * Scan all devices on this root bridge.  Note that this must occur
-	 * now to get the correct bus number assignments for subordinate
-	 * PCI-PCI bridges.
+	 * Attach ACPI-PCI Context
+	 * -----------------------
+	 * Thus binding the ACPI and PCI devices.
 	 */
-	pci_scan_bus(context->id.bus, pci_root_ops, NULL);
+	status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unable to attach ACPI-PCI context to device %s\n",
+			acpi_device_bid(device)));
+		result = -ENODEV;
+		goto end;
+	}
 
-	/* Evaluate _PRT for this root bridge. */
-	acpi_prt_callback(context->handle, 0, context, NULL);
+	/*
+	 * PCI Bridge?
+	 * -----------
+	 * If so, install the 'bind' function to facilitate callbacks for
+	 * all of its children.
+	 */
+	if (data->dev->subordinate)
+		device->ops.bind = acpi_pci_root_bind;
 
-	/* Evaluate all subordinate _PRTs. */
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, context->handle, ACPI_UINT32_MAX, 
-		acpi_prt_callback, context, NULL);
+	/*
+	 * PCI Routing Table
+	 * -----------------
+	 * Evaluate and parse _PRT, if exists.  This code is independent of 
+	 * PCI bridges (above) to allow parsing of _PRT objects within the
+	 * scope of non-bridge devices.  Note that _PRTs within the scope of
+	 * a PCI bridge assume the bridge's subordinate bus number.
+	 *
+	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
+	 */
+	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
+	if (ACPI_SUCCESS(status)) {
+		if (data->dev->subordinate)		    /* PCI-PCI bridge */
+			acpi_prt_parse(device->handle, data->id.segment, 
+				data->dev->subordinate->number);
+		else				     /* non-bridge PCI device */
+			acpi_prt_parse(device->handle, data->id.segment,
+				data->id.bus);
+	}
 
-	return_VALUE(0);
+end:
+	if (0 != result)
+		kfree(data);
+
+	return_VALUE(result);
 }
 
 
-int
-acpi_pci_root_remove (
-	struct acpi_device	*device,
-	int			type)
+/* --------------------------------------------------------------------------
+                                Driver Interface
+   -------------------------------------------------------------------------- */
+
+static int
+acpi_pci_root_add (
+	struct acpi_device	*device)
 {
-	struct acpi_pci_dev_context *context = NULL;
+	int			result = 0;
+	struct acpi_pci_root	*root = NULL;
+	acpi_status		status = AE_OK;
+	unsigned long		value = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_root_add");
 
 	if (!device)
-		return -EINVAL;
+		return_VALUE(-EINVAL);
 
-	if (device->driver_data)
-		/* Root bridge */
-		kfree(device->driver_data);
-	else {
-		/* Standard PCI device */
-		context = acpi_driver_data(device);
-		if (context)
-			kfree(context);
+	root = kmalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
+	if (!root)
+		return_VALUE(-ENOMEM);
+	memset(root, 0, sizeof(struct acpi_pci_root));
+
+	root->handle = device->handle;
+	sprintf(acpi_device_name(device), "%s", ACPI_PCI_ROOT_DEVICE_NAME);
+	sprintf(acpi_device_class(device), "%s", ACPI_PCI_ROOT_CLASS);
+	acpi_driver_data(device) = root;
+
+	/*
+	 * TBD: Doesn't the bus driver automatically set this?
+	 */
+	device->ops.bind = acpi_pci_root_bind;
+
+	/* 
+	 * Segment
+	 * -------
+	 * Obtained via _SEG, if exists, otherwise assumed to be zero (0).
+	 */
+	status = acpi_evaluate_integer(root->handle, METHOD_NAME__SEG, NULL, 
+		&value);
+	switch (status) {
+	case AE_OK:
+		root->data.id.segment = (u16) value;
+		break;
+	case AE_NOT_FOUND:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming segment 0 (no _SEG)\n"));
+		root->data.id.segment = 0;
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SEG\n"));
+		result = -ENODEV;
+		goto end;
 	}
 
-	return 0;
-}
+	/* 
+	 * Bus
+	 * ---
+	 * Obtained via _BBN, if exists, otherwise assumed to be zero (0).
+	 */
+	status = acpi_evaluate_integer(root->handle, METHOD_NAME__BBN, NULL, 
+		&value);
+	switch (status) {
+	case AE_OK:
+		root->data.id.bus = (u16) value;
+		break;
+	case AE_NOT_FOUND:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Assuming bus 0 (no _BBN)\n"));
+		root->data.id.bus = 0;
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BBN\n"));
+		result = -ENODEV;
+		goto end;
+	}
 
+	/*
+	 * Device & Function
+	 * -----------------
+	 * Obtained from _ADR (which has already been evaluated for us).
+	 */
+	root->data.id.device = device->pnp.bus_address >> 16;
+	root->data.id.function = device->pnp.bus_address & 0xFFFF;
 
-int __init 
-acpi_pci_irq_init (void)
-{
-	int			result = 0;
-	acpi_status		status = AE_OK;
-	acpi_object		arg = {ACPI_TYPE_INTEGER};
-	acpi_object_list        arg_list = {1, &arg};
-	int			irq_model = 0;
+	/*
+	 * TBD: Evaluate _CRS to get root bridge resources
+	 * TBD: Need PCI interface for enumeration/configuration of roots.
+	 */
+
+	printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x:%02x.%02x)\n", 
+		acpi_device_name(device), acpi_device_bid(device),
+		root->data.id.segment, root->data.id.bus, 
+		root->data.id.device, root->data.id.function);
 
-	ACPI_FUNCTION_TRACE("acpi_pci_irq_init");
+	/*
+	 * Scan the Root Bridge
+	 * --------------------
+	 * Must do this prior to any attempt to bind the root device, as the
+	 * PCI namespace does not get created until this call is made (and 
+	 * thus the root bridge's pci_dev does not exist).
+	 */
+	pci_scan_bus(root->data.id.bus, pci_root_ops, NULL);
 
 	/* 
-	 * Let the system know what interrupt model we are using by
-	 * evaluating the \_PIC object, if exists.
+	 * Locate PCI Device
+	 * -----------------
+	 * Locate the matching PCI root bridge device in the PCI namespace.
+	 */
+	root->data.dev = pci_find_slot(root->data.id.bus, 
+		PCI_DEVFN(root->data.id.device, root->data.id.function));
+	if (!root->data.dev) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Device %02x:%02x:%02x.%02x not present\n", 
+			root->data.id.segment, root->data.id.bus, 
+			root->data.id.device, root->data.id.function));
+		result = -ENODEV;
+		goto end;
+	}
+
+	/*
+	 * Attach ACPI-PCI Context
+	 * -----------------------
+	 * Thus binding the ACPI and PCI devices.
+	 */
+	status = acpi_attach_data(root->handle, acpi_pci_data_handler, 
+		&root->data);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unable to attach ACPI-PCI context to device %s\n",
+			acpi_device_bid(device)));
+		result = -ENODEV;
+		goto end;
+	}
+
+	/*
+	 * PCI Routing Table
+	 * -----------------
+	 * Evaluate and parse _PRT, if exists.  Note that root bridges
+	 * must have a _PRT (optional for subordinate bridges).
 	 */
+	result = acpi_prt_parse(device->handle, root->data.id.segment, 
+		root->data.id.bus);
 
-	result = acpi_get_interrupt_model(&irq_model);
+end:
 	if (0 != result)
-		return_VALUE(result);
+		kfree(root);
 
-	arg.integer.value = irq_model;
+	return_VALUE(result);
+}
 
-	status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
-	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PIC\n"));
-		return_VALUE(-ENODEV);
-	}
+
+static int
+acpi_pci_root_remove (
+	struct acpi_device	*device,
+	int			type)
+{
+	struct acpi_pci_root	*root = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_pci_root_remove");
+
+	if (!device || !acpi_driver_data(device))
+		return_VALUE(-EINVAL);
+
+	root = (struct acpi_pci_root *) acpi_driver_data(device);
+
+	kfree(root);
 
 	return_VALUE(0);
 }
@@ -446,17 +724,11 @@
 int __init
 acpi_pci_root_init (void)
 {
-	int			result = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_pci_root_init");
 
 	acpi_prts.count = 0;
 	INIT_LIST_HEAD(&acpi_prts.entries);
 
-	result = acpi_pci_irq_init();
-	if (0 != result)
-		return_VALUE(result);
-
 	if (0 > acpi_bus_register_driver(&acpi_pci_root_driver))
 		return_VALUE(-ENODEV);
 
@@ -470,5 +742,6 @@
 	ACPI_FUNCTION_TRACE("acpi_pci_root_exit");
 
 	acpi_bus_unregister_driver(&acpi_pci_root_driver);
-}
 
+	return_VOID;
+}
diff -Nru a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
--- a/drivers/acpi/acpi_processor.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/acpi_processor.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- * acpi_processor.c - ACPI Processor Driver ($Revision: 50 $)
+ * acpi_processor.c - ACPI Processor Driver ($Revision: 57 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -23,16 +23,12 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *  TBD:
  *	1. Make # power/performance states dynamic.
- *	2. Includes support for _real_ performance states (not just throttle).
- *	3. Support duty_cycle values that span bit 4.
- *	4. Optimize by having scheduler determine business instead of
- *         having us try to calculate it here.
- *      5. Need C1 timing -- must modify kernel (IRQ handler) to get this.
- *	6. Convert time values to ticks (initially) to avoid having to do
- *         the math (acpi_get_timer_duration).
- *      7. What is a good default value for the OS busy_metric?
- *      8. Support both thermal and power limits.
- *      9. Resolve PIIX4 BMISX errata issue (getting an I/O port value of 0).
+ *	2. Support duty_cycle values that span bit 4.
+ *	3. Optimize by having scheduler determine business instead of
+ *	   having us try to calculate it here.
+ *	4. Need C1 timing -- must modify kernel (IRQ handler) to get this.
+ *	5. Convert time values to ticks (initially) to avoid having to do
+ *	   the math (acpi_get_timer_duration).
  */
 
 #include <linux/kernel.h>
@@ -43,6 +39,7 @@
 #include <linux/pm.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/delay.h>
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
@@ -56,20 +53,22 @@
 
 #define PREFIX				"ACPI: "
 
+#define ACPI_PROCESSOR_BUSY_METRIC	10
 
 #define ACPI_PROCESSOR_MAX_POWER	ACPI_C_STATE_COUNT
 #define ACPI_PROCESSOR_MAX_C2_LATENCY	100
 #define ACPI_PROCESSOR_MAX_C3_LATENCY	1000
 
-#define ACPI_PROCESSOR_MAX_PERFORMANCE	4
+#define ACPI_PROCESSOR_MAX_PERFORMANCE	8
 
 #define ACPI_PROCESSOR_MAX_THROTTLING	16
-#define ACPI_PROCESSOR_MAX_THROTTLE	500	/* 50% */
+#define ACPI_PROCESSOR_MAX_THROTTLE	250	/* 25% */
 #define ACPI_PROCESSOR_MAX_DUTY_WIDTH	4
 
 const u32 POWER_OF_2[] = {1,2,4,8,16,32,64};
 
-#define ACPI_PROCESSOR_MAX_LIMIT	20
+#define ACPI_PROCESSOR_LIMIT_USER	0
+#define ACPI_PROCESSOR_LIMIT_THERMAL	1
 
 static int acpi_processor_add (struct acpi_device *device);
 static int acpi_processor_remove (struct acpi_device *device, int type);
@@ -110,24 +109,35 @@
 	int			state;
 	int			default_state;
 	u32			bm_activity;
-	u32			busy_metric;
 	struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
 };
 
 /* Performance Management */
 
+struct acpi_pct_register {
+	u8			descriptor;
+	u16			length;
+	u8			space_id;
+	u8			bit_width;
+	u8			bit_offset;
+	u8			reserved;
+	u64			address;
+} __attribute__ ((packed));
+
 struct acpi_processor_px {
-	u8			valid;
-	u32			core_frequency;
-	u32			power;
-	u32			transition_latency;
-	u32			bus_master_latency;
-	u32			control;
-	u32			status;
+	acpi_integer		core_frequency;		/* megahertz */
+	acpi_integer		power;			/* milliWatts */
+	acpi_integer		transition_latency;	/* microseconds */
+	acpi_integer		bus_master_latency;	/* microseconds */
+	acpi_integer		control;		/* control value */
+	acpi_integer		status;			/* success indicator */
 };
 
 struct acpi_processor_performance {
 	int			state;
+	int			platform_limit;
+	u16			control_register;
+	u16			status_register;
 	int			state_count;
 	struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
 };
@@ -136,7 +146,6 @@
 /* Throttling Control */
 
 struct acpi_processor_tx {
-	u8			valid;
 	u16			power;
 	u16			performance;
 };
@@ -153,37 +162,25 @@
 /* Limit Interface */
 
 struct acpi_processor_lx {
-	u8			valid;
-	u16			performance;
-	int			px;
-	int			tx;
+	int			px;		/* performace state */	
+	int			tx;		/* throttle level */
 };
 
 struct acpi_processor_limit {
-	int			state;
-	int			state_count;
-	struct {
-		u8			valid;
-		u16			performance;
-		int			px;
-		int			tx;
-	}			states[ACPI_PROCESSOR_MAX_LIMIT];
+	struct acpi_processor_lx state;		/* current limit */
+	struct acpi_processor_lx thermal;	/* thermal limit */
+	struct acpi_processor_lx user;		/* user limit */
 };
 
+
 struct acpi_processor_flags {
-	u8			bm_control:1;
 	u8			power:1;
 	u8			performance:1;
 	u8			throttling:1;
 	u8			limit:1;
-	u8			reserved:3;
-};
-
-struct acpi_processor_errata {
-	struct {
-		u8			reverse_throttle;
-		u32			bmisx;
-	}			piix4;
+	u8			bm_control:1;
+	u8			bm_check:1;
+	u8			reserved:2;
 };
 
 struct acpi_processor {
@@ -191,15 +188,25 @@
 	u32			acpi_id;
 	u32			id;
 	struct acpi_processor_flags flags;
-	struct acpi_processor_errata errata;
 	struct acpi_processor_power power;
 	struct acpi_processor_performance performance;
 	struct acpi_processor_throttling throttling;
 	struct acpi_processor_limit limit;
 };
 
+struct acpi_processor_errata {
+	u8			smp;
+	struct {
+		u8			throttle:1;
+		u8			fdma:1;
+		u8			reserved:6;
+		u32			bmisx;
+	}			piix4;
+};
 
-static u8			acpi_processor_smp = 0;
+static struct acpi_processor	*processors[NR_CPUS];
+static struct acpi_processor_errata errata;
+static void (*pm_idle_save)(void) = NULL;
 
 
 /* --------------------------------------------------------------------------
@@ -207,68 +214,138 @@
    -------------------------------------------------------------------------- */
 
 int
-acpi_processor_get_errata (
-	struct acpi_processor	*pr)
+acpi_processor_errata_piix4 (
+	struct pci_dev		*dev)
 {
-	struct pci_dev		*dev = NULL;
+	u8			rev = 0;
+	u8			value1 = 0;
+	u8			value2 = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_get_errata");
+	ACPI_FUNCTION_TRACE("acpi_processor_errata_piix4");
 
-	if (!pr)
+	if (!dev)
 		return_VALUE(-EINVAL);
 
 	/*
-	 * PIIX4
-	 * -----
+	 * Note that 'dev' references the PIIX4 ACPI Controller.
 	 */
-	dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
-		PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, dev);
-	if (dev) {
-		u8		rev = 0;
-
-		pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PIIX4 ACPI rev %d\n", rev));
-
-		switch (rev) {
-
-		case 0:		/* PIIX4 A-step */
-		case 1:		/* PIIX4 B-step */
-			/*
-			 * Workaround for reverse-notation on throttling states
-			 * used by early PIIX4 models.
-			 */
-			pr->errata.piix4.reverse_throttle = 1;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				"Reverse-throttle errata enabled\n"));
 
-		case 2:		/* PIIX4E */
-		case 3:		/* PIIX4M */
-			/*
-			 * Workaround for errata #18 "C3 Power State/BMIDE and
-			 * Type-F DMA Livelock" from the July 2001 PIIX4
-			 * specification update.  Applies to all PIIX4 models.
-			 */
-			/* TBD: Why is the bmisx value always ZERO? */
-			pr->errata.piix4.bmisx = pci_resource_start(dev, 4);
-			if (pr->errata.piix4.bmisx)
-				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
-					"BM-IDE errata enabled\n"));
-			break;
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+	switch (rev) {
+	case 0:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
+		break;
+	case 1:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 B-step\n"));
+		break;
+	case 2:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4E\n"));
+		break;
+	case 3:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4M\n"));
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found unknown PIIX4\n"));
+		break;
+	}
+
+	switch (rev) {
+
+	case 0:		/* PIIX4 A-step */
+	case 1:		/* PIIX4 B-step */
+		/*
+		 * See specification changes #13 ("Manual Throttle Duty Cycle")
+		 * and #14 ("Enabling and Disabling Manual Throttle"), plus
+		 * erratum #5 ("STPCLK# Deassertion Time") from the January 
+		 * 2002 PIIX4 specification update.  Applies to only older 
+		 * PIIX4 models.
+		 */
+		errata.piix4.throttle = 1;
+
+	case 2:		/* PIIX4E */
+	case 3:		/* PIIX4M */
+		/*
+		 * See erratum #18 ("C3 Power State/BMIDE and Type-F DMA 
+		 * Livelock") from the January 2002 PIIX4 specification update.
+		 * Applies to all PIIX4 models.
+		 */
+
+		/* 
+		 * BM-IDE
+		 * ------
+		 * Find the PIIX4 IDE Controller and get the Bus Master IDE 
+		 * Status register address.  We'll use this later to read 
+		 * each IDE controller's DMA status to make sure we catch all
+		 * DMA activity.
+		 */
+		dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
+		           PCI_DEVICE_ID_INTEL_82371AB, 
+                           PCI_ANY_ID, PCI_ANY_ID, NULL);
+		if (dev)
+			errata.piix4.bmisx = pci_resource_start(dev, 4);
+
+		/* 
+		 * Type-F DMA
+		 * ----------
+		 * Find the PIIX4 ISA Controller and read the Motherboard
+		 * DMA controller's status to see if Type-F (Fast) DMA mode
+		 * is enabled (bit 7) on either channel.  Note that we'll 
+		 * disable C3 support if this is enabled, as some legacy 
+		 * devices won't operate well if fast DMA is disabled.
+		 */
+		dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, 
+			PCI_DEVICE_ID_INTEL_82371AB_0, 
+			PCI_ANY_ID, PCI_ANY_ID, NULL);
+		if (dev) {
+			pci_read_config_byte(dev, 0x76, &value1);
+			pci_read_config_byte(dev, 0x77, &value2);
+			if ((value1 & 0x80) || (value2 & 0x80))
+				errata.piix4.fdma = 1;
 		}
+
+		break;
 	}
 
+	if (errata.piix4.bmisx)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"Bus master activity detection (BM-IDE) erratum enabled\n"));
+	if (errata.piix4.fdma)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"Type-F DMA livelock erratum (C3 disabled)\n"));
+
 	return_VALUE(0);
 }
 
 
+int
+acpi_processor_errata (
+	struct acpi_processor	*pr)
+{
+	int			result = 0;
+	struct pci_dev		*dev = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_errata");
+
+	if (!pr)
+		return_VALUE(-EINVAL);
+
+	/*
+	 * PIIX4
+	 */
+	dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, 
+		PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
+	if (dev)
+		result = acpi_processor_errata_piix4(dev);
+
+	return_VALUE(result);
+}
+
+
 /* --------------------------------------------------------------------------
                                 Power Management
    -------------------------------------------------------------------------- */
 
-static struct acpi_processor *acpi_processor_list[NR_CPUS];
-static void (*pm_idle_save)(void) = NULL;
-
 static void
 acpi_processor_power_activate (
 	struct acpi_processor	*pr,
@@ -311,9 +388,8 @@
 	u32			start_ticks = 0;
 	u32			end_ticks = 0;
 	u32			time_elapsed = 0;
-	static unsigned long	last_idle_jiffies = 0;
 
-	pr = acpi_processor_list[smp_processor_id()];
+	pr = processors[smp_processor_id()];
 	if (!pr)
 		return;
 
@@ -323,55 +399,47 @@
 	 */
 	__cli();
 
-	next_state = pr->power.state;
+	cx = &(pr->power.states[pr->power.state]);
 
 	/*
-	 * Check OS Idleness:
-	 * ------------------
-	 * If the OS has been busy (hasn't called the idle handler in a while)
-	 * then automatically demote to the default power state (e.g. C1).
-	 *
-	 * TBD: Optimize by having scheduler determine business instead
-	 *      of having us try to calculate it here.
+	 * Check BM Activity
+	 * -----------------
+	 * Check for bus mastering activity (if required), record, and check
+	 * for demotion.
 	 */
-	if (pr->power.state != pr->power.default_state) {
-		if ((jiffies - last_idle_jiffies) >= pr->power.busy_metric) {
-			next_state = pr->power.default_state;
-			if (next_state != pr->power.state)
-				acpi_processor_power_activate(pr, next_state);
-		}
-	}
+	if (pr->flags.bm_check) {
 
-	/*
-	 * Log BM Activity:
-	 * ----------------
-	 * Read BM_STS and record its value for later use by C3 policy.
-	 * (Note that we save the BM_STS values for the last 32 cycles).
-	 */
-	if (pr->flags.bm_control) {
 		pr->power.bm_activity <<= 1;
+		pr->power.bm_activity &= 0xFFFFFFFE;
+
 		if (acpi_hw_bit_register_read(ACPI_BITREG_BUS_MASTER_STATUS, ACPI_MTX_DO_NOT_LOCK)) {
-			pr->power.bm_activity |= 1;
-			acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_STATUS,
-				1, ACPI_MTX_DO_NOT_LOCK);
+			pr->power.bm_activity++;
+			acpi_hw_bit_register_write(ACPI_BITREG_BUS_MASTER_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
 		}
 		/*
-		 * PIIX4 Errata:
-		 * -------------
-		 * This code is a workaround for errata #18 "C3 Power State/
-		 * BMIDE and Type-F DMA Livelock" from the July '01 PIIX4
-		 * specification update.  Note that BM_STS doesn't always
-		 * reflect the true state of bus mastering activity; forcing
-		 * us to manually check the BMIDEA bit of each IDE channel.
+		 * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
+		 * the true state of bus mastering activity; forcing us to 
+		 * manually check the BMIDEA bit of each IDE channel.
 		 */
-		else if (pr->errata.piix4.bmisx) {
-			if ((inb_p(pr->errata.piix4.bmisx + 0x02) & 0x01) ||
-				(inb_p(pr->errata.piix4.bmisx + 0x0A) & 0x01))
-				pr->power.bm_activity |= 1;
+		else if (errata.piix4.bmisx) {
+			if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) 
+				|| (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
+				pr->power.bm_activity++;
+		}
+
+		/*
+		 * Apply bus mastering demotion policy.  Automatically demote
+		 * to avoid a faulty transition.  Note that the processor 
+		 * won't enter a low-power state during this call (to this 
+		 * funciton) but should upon the next.
+		 */
+		if (pr->power.bm_activity & cx->demotion.threshold.bm) {
+			__sti();
+			next_state = cx->demotion.state;
+			goto end;
 		}
 	}
 
-	cx = &(pr->power.states[pr->power.state]);
 	cx->usage++;
 
 	/*
@@ -416,7 +484,7 @@
 		acpi_hw_bit_register_write(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
 		/* See how long we're asleep for */
 		start_ticks = inl(acpi_fadt.Xpm_tmr_blk.address);
-		/* Invoke C2 */
+		/* Invoke C3 */
 		inb(pr->power.states[ACPI_STATE_C3].address);
 		/* Dummy op - must do something useless after P_LVL3 read */
 		end_ticks = inl(acpi_fadt.Xpm_tmr_blk.address);
@@ -439,6 +507,8 @@
 		return;
 	}
 
+	next_state = pr->power.state;
+
 	/*
 	 * Promotion?
 	 * ----------
@@ -451,12 +521,16 @@
 			cx->promotion.count++;
  			cx->demotion.count = 0;
 			if (cx->promotion.count >= cx->promotion.threshold.count) {
-				if (pr->flags.bm_control) {
-					if (!(pr->power.bm_activity & cx->promotion.threshold.bm))
+				if (pr->flags.bm_check) {
+					if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) {
 						next_state = cx->promotion.state;
+						goto end;
+					}
 				}
-				else
+				else {
 					next_state = cx->promotion.state;
+					goto end;
+				}
 			}
 		}
 	}
@@ -466,21 +540,20 @@
 	 * ---------
 	 * Track the number of shorts (time asleep is less than time threshold)
 	 * and demote when the usage threshold is reached.  Note that bus
-	 * mastering activity may cause immediate demotions.
+	 * mastering demotions are checked prior to state transitions (above).
 	 */
 	if (cx->demotion.state) {
 		if (time_elapsed < cx->demotion.threshold.time) {
 			cx->demotion.count++;
 			cx->promotion.count = 0;
-			if (cx->demotion.count >= cx->demotion.threshold.count)
-				next_state = cx->demotion.state;
-		}
-		if (pr->flags.bm_control) {
-			if (pr->power.bm_activity & cx->demotion.threshold.bm)
+			if (cx->demotion.count >= cx->demotion.threshold.count) {
 				next_state = cx->demotion.state;
+				goto end;
+			}
 		}
 	}
 
+end:
 	/*
 	 * New Cx State?
 	 * -------------
@@ -490,14 +563,6 @@
 	if (next_state != pr->power.state)
 		acpi_processor_power_activate(pr, next_state);
 
-	/*
-	 * Track OS Idleness:
-	 * ------------------
-	 * Record a jiffies timestamp to compute time elapsed between calls
-	 * to the idle handler.
-	 */
-	last_idle_jiffies = jiffies;
-
 	return;
 }
 
@@ -521,46 +586,30 @@
 		return_VALUE(-EINVAL);
 
 	/*
-	 * The Busy Metric is used to determine when the OS has been busy
-	 * and thus when policy should return to using the default Cx state
-	 * (e.g. C1).  On Linux we use the number of jiffies (scheduler
-	 * quantums) that transpire between calls to the idle handler.
-	 *
-	 * TBD: What is a good value for the OS busy_metric?
-	 */
-	pr->power.busy_metric = 2;
-
-	/*
 	 * C0/C1
 	 * -----
 	 */
-	if (pr->power.states[ACPI_STATE_C1].valid) {
-		pr->power.state = ACPI_STATE_C1;
-		pr->power.default_state = ACPI_STATE_C1;
-	}
-	else {
-		pr->power.state = ACPI_STATE_C0;
-		pr->power.default_state = ACPI_STATE_C0;
-		return_VALUE(0);
-	}
+	pr->power.state = ACPI_STATE_C1;
+	pr->power.default_state = ACPI_STATE_C1;
 
 	/*
 	 * C1/C2
 	 * -----
 	 * Set the default C1 promotion and C2 demotion policies, where we
-	 * promote from C1 to C2 anytime we're asleep in C1 for longer than
-	 * two times the C2 latency (to amortize cost of transitions). Demote
-	 * from C2 to C1 anytime we're asleep in C2 for less than this time.
+	 * promote from C1 to C2 after several (10) successive C1 transitions,
+	 * as we cannot (currently) measure the time spent in C1. Demote from
+	 * C2 to C1 after experiencing several (3) 'shorts' (time spent in C2
+	 * is less than the C2 transtional latency).
 	 */
 	if (pr->power.states[ACPI_STATE_C2].valid) {
 		pr->power.states[ACPI_STATE_C1].promotion.threshold.count = 10;
 		pr->power.states[ACPI_STATE_C1].promotion.threshold.time =
-			(2 * pr->power.states[ACPI_STATE_C2].latency);
+			pr->power.states[ACPI_STATE_C2].latency;
 		pr->power.states[ACPI_STATE_C1].promotion.state = ACPI_STATE_C2;
 
-		pr->power.states[ACPI_STATE_C2].demotion.threshold.count = 1;
+		pr->power.states[ACPI_STATE_C2].demotion.threshold.count = 3;
 		pr->power.states[ACPI_STATE_C2].demotion.threshold.time =
-			(2 * pr->power.states[ACPI_STATE_C2].latency);
+			pr->power.states[ACPI_STATE_C2].latency;
 		pr->power.states[ACPI_STATE_C2].demotion.state = ACPI_STATE_C1;
 	}
 
@@ -576,13 +625,13 @@
 		(pr->power.states[ACPI_STATE_C3].valid)) {
 		pr->power.states[ACPI_STATE_C2].promotion.threshold.count = 1;
 		pr->power.states[ACPI_STATE_C2].promotion.threshold.time =
-			(2 * pr->power.states[ACPI_STATE_C3].latency);
+			pr->power.states[ACPI_STATE_C3].latency;
 		pr->power.states[ACPI_STATE_C2].promotion.threshold.bm = 0x0F;
 		pr->power.states[ACPI_STATE_C2].promotion.state = ACPI_STATE_C3;
 
 		pr->power.states[ACPI_STATE_C3].demotion.threshold.count = 1;
 		pr->power.states[ACPI_STATE_C3].demotion.threshold.time =
-			(2 * pr->power.states[ACPI_STATE_C3].latency);
+			pr->power.states[ACPI_STATE_C3].latency;
 		pr->power.states[ACPI_STATE_C3].demotion.threshold.bm = 0x0F;
 		pr->power.states[ACPI_STATE_C3].demotion.state = ACPI_STATE_C2;
 	}
@@ -614,7 +663,7 @@
 	 * --
 	 * This state exists only as filler in our array.
 	 */
-	pr->power.states[ACPI_STATE_C0].valid = TRUE;
+	pr->power.states[ACPI_STATE_C0].valid = 1;
 
 	/*
 	 * C1
@@ -623,7 +672,7 @@
 	 *
 	 * TBD: What about PROC_C1?
 	 */
-	pr->power.states[ACPI_STATE_C1].valid = TRUE;
+	pr->power.states[ACPI_STATE_C1].valid = 1;
 
 	/*
 	 * C2
@@ -633,32 +682,82 @@
 	 * TBD: Support for C2 on MP (P_LVL2_UP).
 	 */
 	if (pr->power.states[ACPI_STATE_C2].address) {
+
 		pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat;
-		if (acpi_fadt.plvl2_lat > ACPI_PROCESSOR_MAX_C2_LATENCY)
+
+		/*
+		 * C2 latency must be less than or equal to 100 microseconds.
+		 */
+		if (acpi_fadt.plvl2_lat >= ACPI_PROCESSOR_MAX_C2_LATENCY)
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				"C2 latency too large [%d]\n",
 				acpi_fadt.plvl2_lat));
-		else if (!acpi_processor_smp)
-			pr->power.states[ACPI_STATE_C2].valid = TRUE;
+		/*
+		 * Only support C2 on UP systems (see TBD above).
+		 */
+		else if (errata.smp)
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"C2 not supported in SMP mode\n"));
+		/*
+		 * Otherwise we've met all of our C2 requirements.
+		 */
+		else
+			pr->power.states[ACPI_STATE_C2].valid = 1;
 	}
 
 	/*
 	 * C3
 	 * --
-	 * We're (currently) only supporting C3 on UP systems that include
-	 * bus mastering arbitration control.  Note that this method of
-	 * maintaining cache coherency (disabling of bus mastering) cannot be
-	 * used on SMP systems, and flushing caches (e.g. WBINVD) is simply
-	 * too costly (at this time).
+	 * TBD: Investigate use of WBINVD on UP/SMP system in absence of
+	 *	bm_control.
 	 */
 	if (pr->power.states[ACPI_STATE_C3].address) {
+
 		pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat;
-		if (acpi_fadt.plvl3_lat > ACPI_PROCESSOR_MAX_C3_LATENCY)
+
+		/*
+		 * C3 latency must be less than or equal to 1000 microseconds.
+		 */
+		if (acpi_fadt.plvl3_lat >= ACPI_PROCESSOR_MAX_C3_LATENCY)
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				"C3 latency too large [%d]\n", 
 				acpi_fadt.plvl3_lat));
-		else if (!acpi_processor_smp && pr->flags.bm_control)
+		/*
+		 * Only support C3 when bus mastering arbitration control
+		 * is present (able to disable bus mastering to maintain
+		 * cache coherency while in C3).
+		 */
+		else if (!pr->flags.bm_control)
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"C3 support requires bus mastering control\n"));
+		/*
+		 * Only support C3 on UP systems, as bm_control is only viable
+		 * on a UP system and flushing caches (e.g. WBINVD) is simply 
+		 * too costly (at this time).
+		 */
+		else if (errata.smp)
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"C3 not supported in SMP mode\n"));
+		/*
+		 * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) 
+		 * DMA transfers are used by any ISA device to avoid livelock.
+		 * Note that we could disable Type-F DMA (as recommended by
+		 * the erratum), but this is known to disrupt certain ISA 
+		 * devices thus we take the conservative approach.
+		 */
+		else if (errata.piix4.fdma) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"C3 not supported on PIIX4 with Type-F DMA\n"));
+		}
+		/*
+		 * Otherwise we've met all of our C3 requirements.  Enable
+		 * checking of bus mastering status (bm_check) so we can 
+		 * use this in our C3 policy.
+		 */
+		else {
 			pr->power.states[ACPI_STATE_C3].valid = 1;
+			pr->flags.bm_check = 1;
+		}
 	}
 
 	/*
@@ -678,7 +777,7 @@
 	 * manageable'.  Note that there's really no policy involved for
 	 * when only C1 is supported.
 	 */
-	if (pr->power.states[ACPI_STATE_C2].valid
+	if (pr->power.states[ACPI_STATE_C2].valid 
 		|| pr->power.states[ACPI_STATE_C3].valid)
 		pr->flags.power = 1;
 
@@ -690,30 +789,214 @@
                               Performance Management
    -------------------------------------------------------------------------- */
 
-static int
-acpi_processor_get_performance (
-	struct acpi_processor	*pr)
+static int 
+acpi_processor_get_platform_limit (
+	struct acpi_processor*	pr)
 {
-	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_state");
+	acpi_status		status = 0;
+	unsigned long		ppc = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
 
 	if (!pr)
 		return_VALUE(-EINVAL);
 
-	if (!pr->flags.performance)
-		return_VALUE(0);
+	/*
+	 * _PPC indicates the maximum state currently supported by the platform
+	 * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
+	 */
+	status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
+	if(ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
+		return_VALUE(-ENODEV);
+	}
 
-	/* TBD */
+	pr->performance.platform_limit = (int) ppc;
 
 	return_VALUE(0);
 }
 
 
+static int 
+acpi_processor_get_performance_control (
+	struct acpi_processor	*pr)
+{
+	int			result = 0;
+	acpi_status		status = 0;
+	acpi_buffer		buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_object		*pct = NULL;
+	acpi_object		obj = {0};
+	struct acpi_pct_register *reg = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
+
+	status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
+	if(ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	pct = (acpi_object *) buffer.pointer;
+	if (!pct || (pct->type != ACPI_TYPE_PACKAGE) 
+		|| (pct->package.count != 2)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	/*
+	 * control_register
+	 */
+
+	obj = pct->package.elements[0];
+
+	if ((obj.type != ACPI_TYPE_BUFFER) 
+		|| (obj.buffer.length < sizeof(struct acpi_pct_register)) 
+		|| (obj.buffer.pointer == NULL)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Invalid _PCT data (control_register)\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	reg = (struct acpi_pct_register *) (obj.buffer.pointer);
+
+	if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unsupported address space [%d] (control_register)\n",
+			(u32) reg->space_id));
+		result = -EFAULT;
+		goto end;
+	}
+
+	pr->performance.control_register = (u16) reg->address;
+
+	/*
+	 * status_register
+	 */
+
+	obj = pct->package.elements[1];
+
+	if ((obj.type != ACPI_TYPE_BUFFER) 
+		|| (obj.buffer.length < sizeof(struct acpi_pct_register)) 
+		|| (obj.buffer.pointer == NULL)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Invalid _PCT data (status_register)\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	reg = (struct acpi_pct_register *) (obj.buffer.pointer);
+
+	if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Unsupported address space [%d] (status_register)\n",
+			(u32) reg->space_id));
+		result = -EFAULT;
+		goto end;
+	}
+
+	pr->performance.status_register = (u16) reg->address;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"control_register[0x%04x] status_register[0x%04x]\n",
+		pr->performance.control_register,
+		pr->performance.status_register));
+
+end:
+	kfree(buffer.pointer);
+
+	return_VALUE(result);
+}
+
+
+static int 
+acpi_processor_get_performance_states (
+	struct acpi_processor*	pr)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	acpi_buffer		buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_buffer		format = {sizeof("NNNNNN"), "NNNNNN"};
+	acpi_buffer		state = {0, NULL};
+	acpi_object 		*pss = NULL;
+	int			i = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
+
+	status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
+	if(ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	pss = (acpi_object *) buffer.pointer;
+	if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n", 
+		pss->package.count));
+
+	if (pss->package.count > ACPI_PROCESSOR_MAX_PERFORMANCE) {
+		pr->performance.state_count = ACPI_PROCESSOR_MAX_PERFORMANCE;
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"Limiting number of states to max (%d)\n", 
+			ACPI_PROCESSOR_MAX_PERFORMANCE));
+	}
+	else
+		pr->performance.state_count = pss->package.count;
+
+	if (pr->performance.state_count > 1)
+		pr->flags.performance = 1;
+
+	for (i = 0; i < pr->performance.state_count; i++) {
+
+		struct acpi_processor_px *px = &(pr->performance.states[i]);
+
+		state.length = sizeof(struct acpi_processor_px);
+		state.pointer = px;
+
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
+
+		status = acpi_extract_package(&(pss->package.elements[i]), 
+			&format, &state);
+		if (ACPI_FAILURE(status)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
+			result = -EFAULT;
+			goto end;
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
+			i, 
+			(u32) px->core_frequency, 
+			(u32) px->power, 
+			(u32) px->transition_latency, 
+			(u32) px->bus_master_latency,
+			(u32) px->control, 
+			(u32) px->status));
+	}
+
+end:
+	kfree(buffer.pointer);
+
+	return_VALUE(result);
+}
+
+
 static int
 acpi_processor_set_performance (
 	struct acpi_processor	*pr,
 	int			state)
 {
-	ACPI_FUNCTION_TRACE("acpi_processor_set_performance_state");
+	u16			port = 0;
+	u8			value = 0;
+	int			i = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
 
 	if (!pr)
 		return_VALUE(-EINVAL);
@@ -721,13 +1004,71 @@
 	if (!pr->flags.performance)
 		return_VALUE(-ENODEV);
 
-	if (state >= pr->performance.state_count)
+	if (state >= pr->performance.state_count) {
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
+			"Invalid target state (P%d)\n", state));
 		return_VALUE(-ENODEV);
+	}
 
-	if (state == pr->performance.state)
+	if (state < pr->performance.platform_limit) {
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
+			"Platform limit (P%d) overrides target state (P%d)\n",
+			pr->performance.platform_limit, state));
+		return_VALUE(-ENODEV);
+	}
+
+	if (state == pr->performance.state) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"Already at target state (P%d)\n", state));
 		return_VALUE(0);
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
+		pr->performance.state, state));
+
+	/*
+	 * First we write the target state's 'control' value to the
+	 * control_register.
+	 */
 
-	/* TBD */
+	port = pr->performance.control_register;
+	value = (u16) pr->performance.states[state].control;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Writing 0x%02x to port 0x%04x\n", value, port));
+
+	outb(value, port); 
+
+	/*
+	 * Then we read the 'status_register' and compare the value with the
+	 * target state's 'status' to make sure the transition was successful.
+	 * Note that we'll poll for up to 1ms (100 cycles of 10us) before
+	 * giving up.
+	 */
+
+	port = pr->performance.status_register;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Looking for 0x%02x from port 0x%04x\n",
+		(u8) pr->performance.states[state].status, port));
+
+	for (i=0; i<100; i++) {
+		value = inb(port);
+		if (value == (u8) pr->performance.states[state].status)
+			break;
+		udelay(10);
+	}
+
+	if (value != pr->performance.states[state].status) {
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
+		return_VALUE(-ENODEV);
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Transition successful after %d microseconds\n",
+		i * 10));
+
+	pr->performance.state = state;
 
 	return_VALUE(0);
 }
@@ -738,13 +1079,37 @@
 	struct acpi_processor	*pr)
 {
 	int			result = 0;
+	acpi_status		status = AE_OK;
+	acpi_handle		handle = NULL;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
 
 	if (!pr)
 		return_VALUE(-EINVAL);
 
-	/* TBD: Support ACPI 2.0 objects */
+	status = acpi_get_handle(pr->handle, "_PCT", &handle);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"ACPI-based processor performance control unavailable\n"));
+		return_VALUE(0);
+	}
+
+	result = acpi_processor_get_performance_control(pr);
+	if (0 != result)
+		return_VALUE(result);
+
+	result = acpi_processor_get_performance_states(pr);
+	if (0 != result)
+		return_VALUE(result);
+
+	result = acpi_processor_get_platform_limit(pr);
+	if (0 != result)
+		return_VALUE(result);
+
+	/* 
+	 * TBD: Don't trust the latency values we get from BIOS, but rather
+	 *      measure the latencies during run-time (e.g. get_latencies).
+	 */
 
 	return_VALUE(0);
 }
@@ -776,32 +1141,29 @@
 	__cli();
 
 	duty_mask = pr->throttling.state_count - 1;
+
 	duty_mask <<= pr->throttling.duty_offset;
 
-	value = inb(pr->throttling.address);
+	value = inl(pr->throttling.address);
 
 	/*
 	 * Compute the current throttling state when throttling is enabled
-	 * (bit 4 is on).  Note that the reverse_throttling flag indicates
-	 * that the duty_value is opposite of that specified by ACPI.
+	 * (bit 4 is on).
 	 */
 	if (value & 0x10) {
 		duty_value = value & duty_mask;
 		duty_value >>= pr->throttling.duty_offset;
 
-		if (duty_value) {
-			if (pr->errata.piix4.reverse_throttle)
-				state = duty_value;
-			else
-				state = pr->throttling.state_count-duty_value;
-		}
+		if (duty_value)
+			state = pr->throttling.state_count-duty_value;
 	}
 
 	pr->throttling.state = state;
 
 	__sti();
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling state is T%d (%d%% throttling applied)\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Throttling state is T%d (%d%% throttling applied)\n",
 		state, pr->throttling.states[state].performance));
 
 	return_VALUE(0);
@@ -825,7 +1187,7 @@
 	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
 		return_VALUE(-EINVAL);
 
-	if (!pr->flags.throttling || !pr->throttling.states[state].valid)
+	if (!pr->flags.throttling)
 		return_VALUE(-ENODEV);
 
 	if (state == pr->throttling.state)
@@ -834,20 +1196,16 @@
 	__cli();
 
 	/*
-	 * Calculate the duty_value and duty_mask.  Note that the
-	 * reverse_throttling flag indicates that the duty_value is
-	 * opposite of that specified by ACPI.
+	 * Calculate the duty_value and duty_mask.
 	 */
 	if (state) {
-		if (pr->errata.piix4.reverse_throttle)
-			duty_value = state;
-		else
-			duty_value = pr->throttling.state_count - state;
+		duty_value = pr->throttling.state_count - state;
 
 		duty_value <<= pr->throttling.duty_offset;
 
 		/* Used to clear all duty_value bits */
-		duty_mask = pr->performance.state_count - 1;
+		duty_mask = pr->throttling.state_count - 1;
+
 		duty_mask <<= acpi_fadt.duty_offset;
 		duty_mask = ~duty_mask;
 	}
@@ -856,7 +1214,7 @@
 	 * Disable throttling by writing a 0 to bit 4.  Note that we must
 	 * turn it off before you can change the duty_value.
 	 */
-	value = inb(pr->throttling.address);
+	value = inl(pr->throttling.address);
 	if (value & 0x10) {
 		value &= 0xFFFFFFEF;
 		outl(value, pr->throttling.address);
@@ -879,8 +1237,9 @@
 
 	__sti();
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling state set to T%d (%d%%)\n",
-		state, (pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0)));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+		"Throttling state set to T%d (%d%%)\n", state, 
+		(pr->throttling.states[state].performance?pr->throttling.states[state].performance/10:0)));
 
 	return_VALUE(0);
 }
@@ -912,13 +1271,24 @@
 		return_VALUE(0);
 	}
 	else if (!pr->throttling.duty_width) {
-		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid duty_width\n"));
-		return_VALUE(-EFAULT);
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states\n"));
+		return_VALUE(0);
 	}
 	/* TBD: Support duty_cycle values that span bit 4. */
 	else if ((pr->throttling.duty_offset
 		+ pr->throttling.duty_width) > 4) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "duty_cycle spans bit 4\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "duty_cycle spans bit 4\n"));
+		return_VALUE(0);
+	}
+
+	/*
+	 * PIIX4 Errata: We don't support throttling on the original PIIX4.
+	 * This shouldn't be an issue as few (if any) mobile systems ever
+	 * used this part.
+	 */
+	if (errata.piix4.throttle) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"Throttling not supported on PIIX4 A- or B-step\n"));
 		return_VALUE(0);
 	}
 
@@ -935,7 +1305,6 @@
 	for (i=0; i<pr->throttling.state_count; i++) {
 		pr->throttling.states[i].performance = step * i;
 		pr->throttling.states[i].power = step * i;
-		pr->throttling.states[i].valid = 1;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", 
@@ -973,19 +1342,76 @@
                                  Limit Interface
    -------------------------------------------------------------------------- */
 
+static int
+acpi_processor_apply_limit (
+	struct acpi_processor* 	pr)
+{
+	int			result = 0;
+	u16			px = 0;
+	u16			tx = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_processor_apply_limit");
+
+	if (!pr)
+		return_VALUE(-EINVAL);
+
+	if (!pr->flags.limit)
+		return_VALUE(-ENODEV);
+
+	if (pr->flags.performance) {
+		px = pr->performance.platform_limit;
+		if (pr->limit.user.px > px)
+			px = pr->limit.user.px;
+		if (pr->limit.thermal.px > px)
+			px = pr->limit.thermal.px;
+
+		result = acpi_processor_set_performance(pr, px);
+		if (0 != result)
+			goto end;
+	}
+
+	if (pr->flags.throttling) {
+		if (pr->limit.user.tx > tx)
+			tx = pr->limit.user.tx;
+		if (pr->limit.thermal.tx > tx)
+			tx = pr->limit.thermal.tx;
+
+		result = acpi_processor_set_throttling(pr, tx);
+		if (0 != result)
+			goto end;
+	}
+
+	pr->limit.state.px = px;
+	pr->limit.state.tx = tx;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit set to (P%d:T%d)\n",
+		pr->id,
+		pr->limit.state.px,
+		pr->limit.state.tx));
+
+end:
+	if (0 != result)
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
+
+	return_VALUE(result);
+}
+
+
 int
-acpi_processor_set_limit (
+acpi_processor_set_thermal_limit (
 	acpi_handle		handle,
-	int			type,
-	int			*state)
+	int			type)
 {
 	int			result = 0;
 	struct acpi_processor	*pr = NULL;
 	struct acpi_device	*device = NULL;
+	int			px = 0;
+	int			tx = 0;
 
-	ACPI_FUNCTION_TRACE("acpi_processor_set_limit");
+	ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
 
-	if (!state)
+	if ((type < ACPI_PROCESSOR_LIMIT_NONE) 
+		|| (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
 		return_VALUE(-EINVAL);
 
 	result = acpi_bus_get_device(handle, &device);
@@ -999,56 +1425,75 @@
 	if (!pr->flags.limit)
 		return_VALUE(-ENODEV);
 
+	/* Thermal limits are always relative to the current Px/Tx state. */
+	if (pr->flags.performance)
+		pr->limit.thermal.px = pr->performance.state;
+	if (pr->flags.throttling)
+		pr->limit.thermal.tx = pr->throttling.state;
+
+	/*
+	 * Our default policy is to only use throttling at the lowest
+	 * performance state.
+	 */
+
 	switch (type) {
+
 	case ACPI_PROCESSOR_LIMIT_NONE:
-		*state = 0;
-		pr->limit.state = 0;
+		px = 0;
+		tx = 0;
 		break;
+
 	case ACPI_PROCESSOR_LIMIT_INCREMENT:
-		if (*state == (pr->limit.state_count - 1)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Already at maximum limit state\n"));
-			return_VALUE(1);
+		if (pr->flags.performance) {
+			if (px == (pr->performance.state_count - 1))
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+					"At maximum performance state\n"));
+			else {
+				px++;
+				goto end;
+			}
+		}
+		if (pr->flags.throttling) {
+			if (tx == (pr->throttling.state_count - 1))
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+					"At maximum throttling state\n"));
+			else
+				tx++;
 		}
-		*state = ++pr->limit.state;
 		break;
+
 	case ACPI_PROCESSOR_LIMIT_DECREMENT:
-		if (*state == 0) {
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Already at minimum limit state\n"));
-			return_VALUE(1);
+		if (pr->flags.performance) {
+			if (px == pr->performance.platform_limit)
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+					"At minimum performance state\n"));
+			else  {
+				px--;
+				goto end;
+			}
+		}
+		if (pr->flags.throttling) {
+			if (tx == 0)
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+					"At minimum throttling state\n"));
+			else
+				tx--;
 		}
-		*state = --pr->limit.state;
-		break;
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid limit type [%d]\n",
-			type));
-		*state = pr->limit.state;
-		return_VALUE(-EINVAL);
 		break;
 	}
 
-	if (pr->flags.performance) {
-		result = acpi_processor_set_performance(pr, 
-			pr->limit.states[*state].px);
-		if (0 != result)
-			goto end;
-	}
-
-	if (pr->flags.throttling) {
-		result = acpi_processor_set_throttling(pr, 
-			pr->limit.states[*state].tx);
-		if (0 != result)
-			goto end;
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d] limit now %d%% (P%d:T%d)\n",
-		pr->id,
-		pr->limit.states[*state].performance / 10,
-		pr->limit.states[*state].px,
-		pr->limit.states[*state].tx));
-
 end:
+	pr->limit.thermal.px = px;
+	pr->limit.thermal.tx = tx;
+
+	result = acpi_processor_apply_limit(pr);
 	if (0 != result)
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+			"Unable to set thermal limit\n"));
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
+		pr->limit.thermal.px,
+		pr->limit.thermal.tx));
 
 	return_VALUE(result);
 }
@@ -1058,58 +1503,12 @@
 acpi_processor_get_limit_info (
 	struct acpi_processor	*pr)
 {
-	int			i = 0;
-	int			px = 0;
-	int			tx = 0;
-	int			base_perf = 1000;
-	int			throttle = 0;
-
 	ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info");
 
 	if (!pr)
 		return_VALUE(-EINVAL);
 
-	/*
-	 * Limit
-	 * -----
-	 * Our default policy is to only use throttling at the lowest
-	 * performance state.  This is enforced by adding throttling states 
-	 * after perormance states.  We also only expose throttling states 
-	 * less than the maximum throttle value (e.g. 50%).
-	 */
-
-	if (pr->flags.performance) {
-		for (px=0; px<pr->performance.state_count; px++) {
-			if (!pr->performance.states[px].valid)
-				continue;
-			i = pr->limit.state_count++;
-			pr->limit.states[i].px = px;
-			pr->limit.states[i].performance = (pr->performance.states[px].core_frequency / pr->performance.states[0].core_frequency) * 1000;
-			pr->limit.states[i].valid = 1;
-		}
-		px--;
-		base_perf = pr->limit.states[i].performance;
-	}
-
-	if (pr->flags.throttling) {
-		for (tx=0; tx<pr->throttling.state_count; tx++) {
-			if (!pr->throttling.states[tx].valid)
-				continue;
-			if (pr->throttling.states[tx].performance > ACPI_PROCESSOR_MAX_THROTTLE)
-				continue;
-			i = pr->limit.state_count++;
-			pr->limit.states[i].px = px;
-			pr->limit.states[i].tx = tx;
-			throttle = (base_perf * pr->throttling.states[tx].performance) / 1000;
-			pr->limit.states[i].performance = base_perf - throttle;
-			pr->limit.states[i].valid = 1;
-		}
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d limit states\n", 
-		pr->limit.state_count));
-
-	if (pr->limit.state_count)
+	if (pr->flags.performance || pr->flags.throttling)
 		pr->flags.limit = 1;
 
 	return_VALUE(0);
@@ -1278,11 +1677,11 @@
 	p += sprintf(p, "states:\n");
 
 	for (i=0; i<pr->performance.state_count; i++)
-		p += sprintf(p, "   %cP%d:                %d Mhz, %d mW %s\n",
+		p += sprintf(p, "   %cP%d:                  %d Mhz, %d mW, %d uS\n",
 			(i == pr->performance.state?'*':' '), i,
-			pr->performance.states[i].core_frequency,
-			pr->performance.states[i].power,
-			(pr->performance.states[i].valid?"":"(disabled)"));
+			(u32) pr->performance.states[i].core_frequency,
+			(u32) pr->performance.states[i].power,
+			(u32) pr->performance.states[i].transition_latency);
 
 end:
 	len = (p - page);
@@ -1316,8 +1715,8 @@
 		return_VALUE(-EFAULT);
 	
 	state_string[count] = '\0';
-	
-	result = acpi_processor_set_throttling(pr, 
+
+	result = acpi_processor_set_performance(pr, 
 		simple_strtoul(state_string, NULL, 0));
 	if (0 != result)
 		return_VALUE(result);
@@ -1339,6 +1738,7 @@
 	char			*p = page;
 	int			len = 0;
 	int			i = 0;
+	int                     result = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_read_throttling");
 
@@ -1350,6 +1750,13 @@
 		goto end;
 	}
 
+	result = acpi_processor_get_throttling(pr);
+
+	if (result) {
+		p += sprintf(p, "Could not determine current throttling state.\n");
+		goto end;
+	}
+
 	p += sprintf(p, "state count:             %d\n",
 		pr->throttling.state_count);
 
@@ -1359,10 +1766,9 @@
 	p += sprintf(p, "states:\n");
 
 	for (i=0; i<pr->throttling.state_count; i++)
-		p += sprintf(p, "   %cT%d:                  %02d%% %s\n",
+		p += sprintf(p, "   %cT%d:                  %02d%%\n",
 			(i == pr->throttling.state?'*':' '), i,
-			(pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0),
-			(pr->throttling.states[i].valid?"":"(disabled)"));
+			(pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
 
 end:
 	len = (p - page);
@@ -1418,7 +1824,6 @@
 	struct acpi_processor	*pr = (struct acpi_processor *) data;
 	char			*p = page;
 	int			len = 0;
-	int			i = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_read_limit");
 
@@ -1430,22 +1835,17 @@
 		goto end;
 	}
 
-	p += sprintf(p, "state count:             %d\n",
-		pr->limit.state_count);
+	p += sprintf(p, "active limit:            P%d:T%d\n",
+		pr->limit.state.px, pr->limit.state.tx);
 
-	p += sprintf(p, "active state:            L%d\n",
-		pr->limit.state);
+	p += sprintf(p, "platform limit:          P%d:T0\n",
+		pr->flags.performance?pr->performance.platform_limit:0);
 
-	p += sprintf(p, "states:\n");
+	p += sprintf(p, "user limit:              P%d:T%d\n",
+		pr->limit.user.px, pr->limit.user.tx);
 
-	for (i=0; i<pr->limit.state_count; i++)
-		p += sprintf(p, "   %cL%d:                  %02d%% [P%d:T%d] %s\n",
-			(i == pr->limit.state?'*':' '),
-			i,
-			pr->limit.states[i].performance / 10,
-			pr->limit.states[i].px,
-			pr->limit.states[i].tx,
-			pr->limit.states[i].valid?"":"(disabled)");
+	p += sprintf(p, "thermal limit:           P%d:T%d\n",
+		pr->limit.thermal.px, pr->limit.thermal.tx);
 
 end:
 	len = (p - page);
@@ -1468,25 +1868,47 @@
 {
 	int			result = 0;
 	struct acpi_processor	*pr = (struct acpi_processor *) data;
-	char			limit_string[12] = {'\0'};
-	int			limit = 0;
-	int			state = 0;
+	char			limit_string[25] = {'\0'};
+	int			px = 0;
+	int			tx = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_write_limit");
 
-	if (!pr || (count > sizeof(limit_string) - 1))
+	if (!pr || (count > sizeof(limit_string) - 1)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
 		return_VALUE(-EINVAL);
+	}
 	
-	if (copy_from_user(limit_string, buffer, count))
+	if (copy_from_user(limit_string, buffer, count)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
 		return_VALUE(-EFAULT);
+	}
 	
 	limit_string[count] = '\0';
 
-	limit = simple_strtoul(limit_string, NULL, 0);
-	
-	result = acpi_processor_set_limit(pr->handle, limit, &state);
-	if (0 != result)
-		return_VALUE(result);
+	if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
+		return_VALUE(-EINVAL);
+	}
+
+	if (pr->flags.performance) {
+		if ((px < pr->performance.platform_limit) 
+			|| (px > (pr->performance.state_count - 1))) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid px\n"));
+			return_VALUE(-EINVAL);
+		}
+		pr->limit.user.px = px;
+	}
+
+	if (pr->flags.throttling) {
+		if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid tx\n"));
+			return_VALUE(-EINVAL);
+		}
+		pr->limit.user.tx = tx;
+	}
+
+	result = acpi_processor_apply_limit(pr);
 
 	return_VALUE(count);
 }
@@ -1564,7 +1986,7 @@
 		entry->data = acpi_driver_data(device);
 	}
 
-	/* 'thermal_limit' [R/W] */
+	/* 'limit' [R/W] */
 	entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
 		S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
 	if (!entry)
@@ -1617,10 +2039,10 @@
 
 #ifdef CONFIG_SMP
 	if (smp_num_cpus > 1)
-		acpi_processor_smp = smp_num_cpus;
+		errata.smp = smp_num_cpus;
 #endif
 
-	acpi_processor_get_errata(pr);
+	acpi_processor_errata(pr);
 
 	/*
 	 * Check to see if we have bus mastering arbitration control.  This
@@ -1687,6 +2109,7 @@
 	u32			event,
 	void			*data)
 {
+	int			result = 0;
 	struct acpi_processor	*pr = (struct acpi_processor *) data;
 	struct acpi_device	*device = NULL;
 
@@ -1700,7 +2123,15 @@
 
 	switch (event) {
 	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
+		result = acpi_processor_get_platform_limit(pr);
+		if (0 == result)
+			acpi_processor_apply_limit(pr);
+
+		acpi_bus_generate_event(device, event, 
+			pr->performance.platform_limit);
+		break;
 	case ACPI_PROCESSOR_NOTIFY_POWER:
+		/* TBD */
 		acpi_bus_generate_event(device, event, 0);
 		break;
 	default:
@@ -1745,9 +2176,6 @@
 	if (0 != result)
 		goto end;
 
-	/*
-	 * TBD: Fix notify handler installation for processors.
-	 *
 	status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, 
 		acpi_processor_notify, pr);
 	if (ACPI_FAILURE(status)) {
@@ -1756,16 +2184,13 @@
 		result = -ENODEV;
 		goto end;
 	}
-	*/
 
-	acpi_processor_list[pr->id] = pr;
+	processors[pr->id] = pr;
 
 	/*
-	 * Set Idle Handler
-	 * ----------------
-	 * Install the idle handler if power management (states other than C1)
-	 * is supported.  Note that the default idle handler (default_idle)
-	 * will be used on platforms that only support C1.
+	 * Install the idle handler if processor power management is supported.
+	 * Note that the default idle handler (default_idle) will be used on 
+	 * platforms that only support C1.
 	 */
 	if ((pr->id == 0) && (pr->flags.power)) {
 		pm_idle_save = pm_idle;
@@ -1781,8 +2206,6 @@
 		printk(", %d performance states", pr->performance.state_count);
 	if (pr->flags.throttling)
 		printk(", %d throttling states", pr->throttling.state_count);
-	if (pr->errata.piix4.bmisx)
-		printk(", PIIX4 errata");
 	printk(")\n");
 
 end:
@@ -1810,7 +2233,10 @@
 
 	pr = (struct acpi_processor *) acpi_driver_data(device);
 
-	/*
+	/* Unregister the idle handler when processor #0 is removed. */
+	if (pr->id == 0)
+		pm_idle = pm_idle_save;
+
 	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, 
 		acpi_processor_notify);
 	if (ACPI_FAILURE(status)) {
@@ -1818,15 +2244,10 @@
 			"Error removing notify handler\n"));
 		return_VALUE(-ENODEV);
 	}
-	*/
-
-	/* Unregister the idle handler when processor #0 is removed. */
-	if (pr->id == 0)
-		pm_idle = pm_idle_save;
 
 	acpi_processor_remove_fs(device);
 
-	acpi_processor_list[pr->id] = NULL;
+	processors[pr->id] = NULL;
 
 	kfree(pr);
 
@@ -1841,7 +2262,8 @@
 
 	ACPI_FUNCTION_TRACE("acpi_processor_init");
 
-	memset(&acpi_processor_list, 0, sizeof(acpi_processor_list));
+	memset(&processors, 0, sizeof(processors));
+	memset(&errata, 0, sizeof(errata));
 
 	result = acpi_bus_register_driver(&acpi_processor_driver);
 	if (0 > result)
diff -Nru a/drivers/acpi/acpi_system.c b/drivers/acpi/acpi_system.c
--- a/drivers/acpi/acpi_system.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/acpi_system.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_system.c - ACPI System Driver ($Revision: 40 $)
+ *  acpi_system.c - ACPI System Driver ($Revision: 45 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/poll.h>
 #include <linux/delay.h>
+#include <linux/sysrq.h>
 #include <linux/pm.h>
 #include <asm/uaccess.h>
 #include <asm/acpi.h>
@@ -86,9 +87,8 @@
 acpi_power_off (void)
 {
 	acpi_enter_sleep_state_prep(ACPI_STATE_S5);
-	acpi_disable_irqs();
+	ACPI_DISABLE_IRQS();
 	acpi_enter_sleep_state(ACPI_STATE_S5);
-	acpi_disable_irqs();
 }
 
 #endif /*CONFIG_PM*/
@@ -123,7 +123,7 @@
 	device_resume(RESUME_POWER_ON);
 
 	/* enable interrupts once again */
-	acpi_enable_irqs();
+	ACPI_ENABLE_IRQS();
 
 	/* restore device context */
 	device_resume(RESUME_RESTORE_STATE);
@@ -200,7 +200,7 @@
 	 * But, we want it done early, so we don't get any suprises during
 	 * the device suspend sequence.
 	 */
-	acpi_disable_irqs();
+	ACPI_DISABLE_IRQS();
 
 	/* Unconditionally turn off devices.
 	 * Obvious if we enter a sleep state.
@@ -304,7 +304,7 @@
 		return status;
 
 	/* disable interrupts and flush caches */
-	acpi_disable_irqs();
+	ACPI_DISABLE_IRQS();
 	wbinvd();
 
 	/* perform OS-specific sleep actions */
@@ -318,7 +318,7 @@
 	acpi_leave_sleep_state(state);
 
 	/* make sure interrupts are enabled */
-	acpi_enable_irqs();
+	ACPI_ENABLE_IRQS();
 
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((ACPI_PHYSICAL_ADDRESS) 0);
@@ -570,7 +570,6 @@
 {
 	char			*p = page;
 	int 			size = 0;
-	u32                     var;
 
 	if (off != 0)
 		goto end;
@@ -607,7 +606,6 @@
         void                    *data)
 {
 	char			debug_string[12] = {'\0'};
-	u32                     *pvar;
 
 	ACPI_FUNCTION_TRACE("acpi_system_write_debug");
 
@@ -1126,6 +1124,23 @@
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
+#if defined(CONFIG_MAGIC_SYSRQ) && defined(CONFIG_PM)
+
+/* Simple wrapper calling power down function. */
+static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs,
+	struct kbd_struct *kbd, struct tty_struct *tty)
+{
+	acpi_power_off();
+}
+
+struct sysrq_key_op sysrq_acpi_poweroff_op = {
+	handler:	&acpi_sysrq_power_off,
+	help_msg:	"Off",
+	action_msg:	"Power Off\n"
+};
+
+#endif  /* CONFIG_MAGIC_SYSRQ */
+
 static int
 acpi_system_add (
 	struct acpi_device	*device)
@@ -1168,8 +1183,10 @@
 
 #ifdef CONFIG_PM
 	/* Install the soft-off (S5) handler. */
-	if (system->states[ACPI_STATE_S5])
+	if (system->states[ACPI_STATE_S5]) {
 		pm_power_off = acpi_power_off;
+		register_sysrq_key('o', &sysrq_acpi_poweroff_op);
+	}
 #endif
 
 end:
@@ -1196,8 +1213,10 @@
 
 #ifdef CONFIG_PM
 	/* Remove the soft-off (S5) handler. */
-	if (system->states[ACPI_STATE_S5])
+	if (system->states[ACPI_STATE_S5]) {
+		unregister_sysrq_key('o', &sysrq_acpi_poweroff_op);
 		pm_power_off = NULL;
+	}
 #endif
 
 	acpi_system_remove_fs(device);
diff -Nru a/drivers/acpi/acpi_tables.c b/drivers/acpi/acpi_tables.c
--- a/drivers/acpi/acpi_tables.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/acpi_tables.c	Sun Apr 14 12:16:57 2002
@@ -32,6 +32,7 @@
 #include <linux/types.h>
 #include <linux/irq.h>
 #include <linux/acpi.h>
+#include <linux/err.h>
 
 #define PREFIX			"ACPI: "
 
diff -Nru a/drivers/acpi/acpi_thermal.c b/drivers/acpi/acpi_thermal.c
--- a/drivers/acpi/acpi_thermal.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/acpi_thermal.c	Sun Apr 14 12:16:57 2002
@@ -1,5 +1,5 @@
 /*
- *  acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 33 $)
+ *  acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 36 $)
  *
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -78,7 +78,6 @@
 	u8			passive:1;
 	u8			active:1;
 	u8			reserved:4;
-	int			passive_index;		/* a.k.a. limit state */
 	int			active_index;
 };
 
@@ -467,15 +466,23 @@
 	 */
 	if (tz->temperature >= passive->temperature) {
 		trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", trend, passive->tc1, tz->temperature, tz->last_temperature, passive->tc2, tz->temperature, passive->temperature));
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+			"trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", 
+			trend, passive->tc1, tz->temperature, 
+			tz->last_temperature, passive->tc2, 
+			tz->temperature, passive->temperature));
 		/* Heating up? */
 		if (trend > 0)
 			for (i=0; i<passive->devices.count; i++)
-				acpi_processor_set_limit(passive->devices.handles[i], ACPI_PROCESSOR_LIMIT_INCREMENT, &tz->state.passive_index);
+				acpi_processor_set_thermal_limit(
+					passive->devices.handles[i], 
+					ACPI_PROCESSOR_LIMIT_INCREMENT);
 		/* Cooling off? */
 		else if (trend < 0)
 			for (i=0; i<passive->devices.count; i++)
-				acpi_processor_set_limit(passive->devices.handles[i], ACPI_PROCESSOR_LIMIT_DECREMENT, &tz->state.passive_index);
+				acpi_processor_set_thermal_limit(
+					passive->devices.handles[i], 
+					ACPI_PROCESSOR_LIMIT_DECREMENT);
 	}
 
 	/*
@@ -487,10 +494,13 @@
 	 */
 	else if (tz->trips.passive.flags.enabled) {
 		for (i=0; i<passive->devices.count; i++)
-			acpi_processor_set_limit(passive->devices.handles[i], ACPI_PROCESSOR_LIMIT_DECREMENT, &tz->state.passive_index);
-		if (0 == tz->state.passive_index) {
+			result = acpi_processor_set_thermal_limit(
+				passive->devices.handles[i], 
+				ACPI_PROCESSOR_LIMIT_DECREMENT);
+		if (1 == result) {
 			tz->trips.passive.flags.enabled = 0;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling passive cooling (zone is cool)\n"));
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
+				"Disabling passive cooling (zone is cool)\n"));
 		}
 	}
 
@@ -671,7 +681,7 @@
 		if (timer_pending(&(tz->timer)))
 			mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
 		else {
-			tz->timer.data = (u32) tz;
+			tz->timer.data = (unsigned long) tz;
 			tz->timer.function = acpi_thermal_run;
 			tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
 			add_timer(&(tz->timer));
@@ -720,7 +730,7 @@
 		if (tz->state.hot)
 			p += sprintf(p, "hot ");
 		if (tz->state.passive)
-			p += sprintf(p, "passive[%d] ", tz->state.passive_index);
+			p += sprintf(p, "passive ");
 		if (tz->state.active)
 			p += sprintf(p, "active[%d]", tz->state.active_index);
 		p += sprintf(p, "\n");
@@ -810,9 +820,10 @@
 			tz->trips.passive.tc1,
 			tz->trips.passive.tc2, 
 			tz->trips.passive.tsp);
-		for (j=0; j<tz->trips.passive.devices.count; j++) 
-			p += sprintf(p, "0x%p ", 
-				tz->trips.passive.devices.handles[j]);
+		for (j=0; j<tz->trips.passive.devices.count; j++) {
+
+			p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]);
+		}
 		p += sprintf(p, "\n");
 	}
 
diff -Nru a/drivers/acpi/debugger/dbdisply.c b/drivers/acpi/debugger/dbdisply.c
--- a/drivers/acpi/debugger/dbdisply.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/debugger/dbdisply.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: dbdisply - debug display commands
- *              $Revision: 66 $
+ *              $Revision: 67 $
  *
  ******************************************************************************/
 
@@ -298,6 +298,7 @@
 
 
 	if (!obj_desc) {
+		acpi_os_printf (" Uninitialized\n");
 		return;
 	}
 
@@ -420,10 +421,10 @@
 				break;
 
 			case AML_LOCAL_OP:
-				acpi_os_printf ("[Local%d]", obj_desc->reference.offset);
+				acpi_os_printf ("[Local%d] ", obj_desc->reference.offset);
 				if (walk_state) {
 					obj_desc = walk_state->local_variables[obj_desc->reference.offset].object;
-					acpi_os_printf (" %p", obj_desc);
+					acpi_os_printf ("%p", obj_desc);
 					acpi_db_decode_internal_object (obj_desc);
 				}
 				break;
@@ -432,7 +433,7 @@
 				acpi_os_printf ("[Arg%d] ", obj_desc->reference.offset);
 				if (walk_state) {
 					obj_desc = walk_state->arguments[obj_desc->reference.offset].object;
-					acpi_os_printf (" %p", obj_desc);
+					acpi_os_printf ("%p", obj_desc);
 					acpi_db_decode_internal_object (obj_desc);
 				}
 				break;
@@ -466,7 +467,6 @@
 		acpi_os_printf ("<Not a valid ACPI Object Descriptor> ");
 		break;
 	}
-
 
 	acpi_os_printf ("\n");
 }
diff -Nru a/drivers/acpi/debugger/dbfileio.c b/drivers/acpi/debugger/dbfileio.c
--- a/drivers/acpi/debugger/dbfileio.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/debugger/dbfileio.c	Sun Apr 14 12:16:55 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: dbfileio - Debugger file I/O commands.  These can't usually
  *              be used when running the debugger in Ring 0 (Kernel mode)
- *              $Revision: 59 $
+ *              $Revision: 60 $
  *
  ******************************************************************************/
 
@@ -308,27 +308,14 @@
 }
 
 
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_db_load_acpi_table
- *
- * PARAMETERS:  Filname         - File where table is located
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Load an ACPI table from a file
- *
- ******************************************************************************/
-
+#ifdef ACPI_APPLICATION
 acpi_status
-acpi_db_load_acpi_table (
+acpi_db_get_acpi_table (
 	NATIVE_CHAR             *filename)
 {
-#ifdef ACPI_APPLICATION
 	FILE                    *fp;
-	acpi_status             status;
 	u32                     table_length;
-
+	acpi_status             status;
 
 	/* Open the file */
 
@@ -350,7 +337,35 @@
 		return (status);
 	}
 
-	/* Attempt to recognize and install the table */
+	return (AE_OK);
+ }
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_load_acpi_table
+ *
+ * PARAMETERS:  Filname         - File where table is located
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Load an ACPI table from a file
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_db_load_acpi_table (
+	NATIVE_CHAR             *filename) {
+#ifdef ACPI_APPLICATION
+	acpi_status             status;
+
+
+	status = acpi_db_get_acpi_table (filename);
+	if (ACPI_FAILURE (status)) {
+		return (status);
+	}
+
+   /* Attempt to recognize and install the table */
 
 	status = ae_local_load_table (acpi_gbl_db_table_ptr);
 	if (ACPI_FAILURE (status)) {
diff -Nru a/drivers/acpi/debugger/dbutils.c b/drivers/acpi/debugger/dbutils.c
--- a/drivers/acpi/debugger/dbutils.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/debugger/dbutils.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: dbutils - AML debugger utilities
- *              $Revision: 51 $
+ *              $Revision: 52 $
  *
  ******************************************************************************/
 
@@ -151,7 +151,7 @@
 
 	case ACPI_TYPE_BUFFER:
 
-		acpi_os_printf ("[Buffer] = ");
+		acpi_os_printf ("[Buffer] Length %.2X = ", obj_desc->buffer.length);
 		acpi_ut_dump_buffer ((u8 *) obj_desc->buffer.pointer, obj_desc->buffer.length, DB_DWORD_DISPLAY, _COMPONENT);
 		break;
 
diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
--- a/drivers/acpi/dispatcher/dsmethod.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/dispatcher/dsmethod.c	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
- *              $Revision: 79 $
+ *              $Revision: 81 $
  *
  *****************************************************************************/
 
@@ -77,7 +77,7 @@
 		return_ACPI_STATUS (AE_NULL_ENTRY);
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Parsing [%4.4s] **** Named_obj=%p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** Named_obj=%p\n",
 		(char *) &((acpi_namespace_node *) obj_handle)->name, obj_handle));
 
 	/* Extract the method object from the method Node */
@@ -111,7 +111,7 @@
 
 	/* Init new op with the method name and pointer back to the Node */
 
-	acpi_ps_set_name (op, node->name);
+	acpi_ps_set_name (op, node->name.integer);
 	op->node = node;
 
 	/*
@@ -152,7 +152,7 @@
 		return_ACPI_STATUS (status);
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** [%4.4s] Parsed **** Named_obj=%p Op=%p\n",
 		(char *) &((acpi_namespace_node *) obj_handle)->name, obj_handle, op));
 
 	acpi_ps_delete_parse_tree (op);
@@ -413,7 +413,6 @@
 		"Method=%p Return=%p Return_used?=%X Res_stack=%p State=%p\n",
 		walk_state->method_call_op, return_desc, walk_state->return_used,
 		walk_state->results, walk_state));
-
 
 	return_ACPI_STATUS (AE_OK);
 }
diff -Nru a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
--- a/drivers/acpi/dispatcher/dsmthdat.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/dispatcher/dsmthdat.c	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: dsmthdat - control method arguments and local variables
- *              $Revision: 58 $
+ *              $Revision: 59 $
  *
  ******************************************************************************/
 
@@ -72,10 +72,10 @@
 	for (i = 0; i < MTH_NUM_ARGS; i++) {
 		ACPI_MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name,
 				 NAMEOF_ARG_NTE);
-		walk_state->arguments[i].name     |= (i << 24);
-		walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
-		walk_state->arguments[i].type      = ACPI_TYPE_ANY;
-		walk_state->arguments[i].flags     = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
+		walk_state->arguments[i].name.integer |= (i << 24);
+		walk_state->arguments[i].descriptor   = ACPI_DESC_TYPE_NAMED;
+		walk_state->arguments[i].type         = ACPI_TYPE_ANY;
+		walk_state->arguments[i].flags        = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
 	}
 
 	/* Init the method locals */
@@ -84,10 +84,10 @@
 		ACPI_MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name,
 				 NAMEOF_LOCAL_NTE);
 
-		walk_state->local_variables[i].name    |= (i << 24);
-		walk_state->local_variables[i].descriptor = ACPI_DESC_TYPE_NAMED;
-		walk_state->local_variables[i].type     = ACPI_TYPE_ANY;
-		walk_state->local_variables[i].flags    = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
+		walk_state->local_variables[i].name.integer |= (i << 24);
+		walk_state->local_variables[i].descriptor  = ACPI_DESC_TYPE_NAMED;
+		walk_state->local_variables[i].type        = ACPI_TYPE_ANY;
+		walk_state->local_variables[i].flags       = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
 	}
 
 	return_ACPI_STATUS (AE_OK);
diff -Nru a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
--- a/drivers/acpi/dispatcher/dsobject.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/acpi/dispatcher/dsobject.c	Sun Apr 14 12:16:54 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dsobject - Dispatcher object management routines
- *              $Revision: 90 $
+ *              $Revision: 91 $
  *
  *****************************************************************************/
 
@@ -47,11 +47,11 @@
  * RETURN:      Status
  *
  * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
- *              within the  namespace.
+ *              within the namespace.
  *
  *              Currently, the only objects that require initialization are:
  *              1) Methods
- *              2) Op Regions
+ *              2) Operation Regions
  *
  ******************************************************************************/
 
@@ -83,7 +83,6 @@
 		return (AE_OK);
 	}
 
-
 	/* And even then, we are only interested in a few object types */
 
 	type = acpi_ns_get_type (obj_handle);
@@ -152,12 +151,13 @@
  *
  * FUNCTION:    Acpi_ds_initialize_objects
  *
- * PARAMETERS:  None
+ * PARAMETERS:  Table_desc      - Descriptor for parent ACPI table
+ *              Start_node      - Root of subtree to be initialized.
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Walk the entire namespace and perform any necessary
- *              initialization on the objects found therein
+ * DESCRIPTION: Walk the namespace starting at "Start_node" and perform any
+ *              necessary initialization on the objects found therein
  *
  ******************************************************************************/
 
@@ -183,7 +183,6 @@
 	info.object_count   = 0;
 	info.table_desc     = table_desc;
 
-
 	/* Walk entire namespace from the supplied root */
 
 	status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
@@ -208,9 +207,10 @@
  *
  * FUNCTION:    Acpi_ds_init_object_from_op
  *
- * PARAMETERS:  Op              - Parser op used to init the internal object
+ * PARAMETERS:  Walk_state      - Current walk state
+ *              Op              - Parser op used to init the internal object
  *              Opcode          - AML opcode associated with the object
- *              Obj_desc        - Namespace object to be initialized
+ *              Ret_obj_desc    - Namespace object to be initialized
  *
  * RETURN:      Status
  *
@@ -227,10 +227,6 @@
 	u16                     opcode,
 	acpi_operand_object     **ret_obj_desc)
 {
-	acpi_status             status;
-	acpi_parse_object       *arg;
-	acpi_parse2_object      *byte_list;
-	acpi_operand_object     *arg_desc;
 	const acpi_opcode_info  *op_info;
 	acpi_operand_object     *obj_desc;
 
@@ -246,100 +242,39 @@
 		return (AE_TYPE);
 	}
 
-
-	/* Get and prepare the first argument */
+	/* Perform per-object initialization */
 
 	switch (obj_desc->common.type) {
 	case ACPI_TYPE_BUFFER:
 
-		obj_desc->buffer.node = (acpi_namespace_node *) walk_state->operands[0];
-
-		/* First arg is a number */
-
-		acpi_ds_create_operand (walk_state, op->value.arg, 0);
-		arg_desc = walk_state->operands [walk_state->num_operands - 1];
-		acpi_ds_obj_stack_pop (1, walk_state);
-
-		/* Resolve the object (could be an arg or local) */
-
-		status = acpi_ex_resolve_to_value (&arg_desc, walk_state);
-		if (ACPI_FAILURE (status)) {
-			acpi_ut_remove_reference (arg_desc);
-			return (status);
-		}
-
-		/* We are expecting a number */
-
-		if (arg_desc->common.type != ACPI_TYPE_INTEGER) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-				"Expecting number, got obj: %p type %X\n",
-				arg_desc, arg_desc->common.type));
-			acpi_ut_remove_reference (arg_desc);
-			return (AE_TYPE);
-		}
-
-		/* Get the value, delete the internal object */
-
-		obj_desc->buffer.length = (u32) arg_desc->integer.value;
-		acpi_ut_remove_reference (arg_desc);
-
-		/* Allocate the buffer */
-
-		if (obj_desc->buffer.length == 0) {
-			obj_desc->buffer.pointer = NULL;
-			ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n"));
-			break;
-		}
-
-		else {
-			obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
-					   obj_desc->buffer.length);
-
-			if (!obj_desc->buffer.pointer) {
-				return (AE_NO_MEMORY);
-			}
-		}
-
 		/*
-		 * Second arg is the buffer data (optional) Byte_list can be either
-		 * individual bytes or a string initializer.
+		 * Defer evaluation of Buffer Term_arg operand
 		 */
-		arg = op->value.arg;         /* skip first arg */
-
-		byte_list = (acpi_parse2_object *) arg->next;
-		if (byte_list) {
-			if (byte_list->opcode != AML_INT_BYTELIST_OP) {
-				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Expecting bytelist, got: %p\n",
-					byte_list));
-				return (AE_TYPE);
-			}
-
-			ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->data,
-					  obj_desc->buffer.length);
-		}
-
+		obj_desc->buffer.node     = (acpi_namespace_node *) walk_state->operands[0];
+		obj_desc->buffer.aml_start = ((acpi_parse2_object *) op)->data;
+		obj_desc->buffer.aml_length = ((acpi_parse2_object *) op)->length;
 		break;
 
 
 	case ACPI_TYPE_PACKAGE:
 
 		/*
-		 * When called, an internal package object has already been built and
-		 * is pointed to by Obj_desc. Acpi_ds_build_internal_object builds another
-		 * internal package object, so remove reference to the original so
-		 * that it is deleted.  Error checking is done within the remove
-		 * reference function.
+		 * Defer evaluation of Package Term_arg operand
 		 */
-		acpi_ut_remove_reference (obj_desc);
-		status = acpi_ds_build_internal_object (walk_state, op, ret_obj_desc);
+		obj_desc->package.node     = (acpi_namespace_node *) walk_state->operands[0];
+		obj_desc->package.aml_start = ((acpi_parse2_object *) op)->data;
+		obj_desc->package.aml_length = ((acpi_parse2_object *) op)->length;
 		break;
 
+
 	case ACPI_TYPE_INTEGER:
+
 		obj_desc->integer.value = op->value.integer;
 		break;
 
 
 	case ACPI_TYPE_STRING:
+
 		obj_desc->string.pointer = op->value.string;
 		obj_desc->string.length = ACPI_STRLEN (op->value.string);
 
@@ -387,7 +322,6 @@
 			obj_desc->reference.opcode = opcode;
 			break;
 		}
-
 		break;
 
 
@@ -405,9 +339,10 @@
 
 /*****************************************************************************
  *
- * FUNCTION:    Acpi_ds_build_internal_simple_obj
+ * FUNCTION:    Acpi_ds_build_internal_object
  *
- * PARAMETERS:  Op              - Parser object to be translated
+ * PARAMETERS:  Walk_state      - Current walk state
+ *              Op              - Parser object to be translated
  *              Obj_desc_ptr    - Where the ACPI internal object is returned
  *
  * RETURN:      Status
@@ -417,8 +352,8 @@
  *
  ****************************************************************************/
 
-static acpi_status
-acpi_ds_build_internal_simple_obj (
+acpi_status
+acpi_ds_build_internal_object (
 	acpi_walk_state         *walk_state,
 	acpi_parse_object       *op,
 	acpi_operand_object     **obj_desc_ptr)
@@ -428,7 +363,7 @@
 	char                    *name;
 
 
-	ACPI_FUNCTION_TRACE ("Ds_build_internal_simple_obj");
+	ACPI_FUNCTION_TRACE ("Ds_build_internal_object");
 
 
 	if (op->opcode == AML_INT_NAMEPATH_OP) {
@@ -453,7 +388,6 @@
 								 name, op->aml_offset));
 						ACPI_MEM_FREE (name);
 					}
-
 					else {
 						ACPI_REPORT_WARNING (("Reference %s at AML %X not found\n",
 								   op->value.string, op->aml_offset));
@@ -461,7 +395,6 @@
 
 					*obj_desc_ptr = NULL;
 				}
-
 				else {
 					return_ACPI_STATUS (status);
 				}
@@ -483,14 +416,13 @@
 	}
 
 	*obj_desc_ptr = obj_desc;
-
 	return_ACPI_STATUS (AE_OK);
 }
 
 
 /*****************************************************************************
  *
- * FUNCTION:    Acpi_ds_build_internal_package_obj
+ * FUNCTION:    Acpi_ds_build_internal_buffer_obj
  *
  * PARAMETERS:  Op              - Parser object to be translated
  *              Obj_desc_ptr    - Where the ACPI internal object is returned
@@ -503,114 +435,212 @@
  ****************************************************************************/
 
 acpi_status
-acpi_ds_build_internal_package_obj (
+acpi_ds_build_internal_buffer_obj (
 	acpi_walk_state         *walk_state,
 	acpi_parse_object       *op,
+	u32                     buffer_length,
 	acpi_operand_object     **obj_desc_ptr)
 {
 	acpi_parse_object       *arg;
 	acpi_operand_object     *obj_desc;
-	acpi_status             status = AE_OK;
+	acpi_parse2_object      *byte_list;
+	u32                     byte_list_length = 0;
 
 
-	ACPI_FUNCTION_TRACE ("Ds_build_internal_package_obj");
+	ACPI_FUNCTION_TRACE ("Ds_build_internal_buffer_obj");
 
 
-	obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
-	*obj_desc_ptr = obj_desc;
-	if (!obj_desc) {
-		return_ACPI_STATUS (AE_NO_MEMORY);
-	}
-
-	if (op->opcode == AML_VAR_PACKAGE_OP) {
+	obj_desc = *obj_desc_ptr;
+	if (obj_desc) {
 		/*
-		 * Variable length package parameters are evaluated JIT
+		 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
+		 * The buffer object already exists (from the NS node)
 		 */
-		return_ACPI_STATUS (AE_OK);
 	}
+	else {
+		/* Create a new buffer object */
 
-	/* The first argument must be the package length */
-
-	arg = op->value.arg;
-	obj_desc->package.count = arg->value.integer32;
+		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+		*obj_desc_ptr = obj_desc;
+		if (!obj_desc) {
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
+	}
 
 	/*
-	 * Allocate the array of pointers (ptrs to the
-	 * individual objects) Add an extra pointer slot so
-	 * that the list is always null terminated.
+	 * Second arg is the buffer data (optional) Byte_list can be either
+	 * individual bytes or a string initializer.  In either case, a
+	 * Byte_list appears in the AML.
 	 */
-	obj_desc->package.elements = ACPI_MEM_CALLOCATE (
-			 (obj_desc->package.count + 1) * sizeof (void *));
+	arg = op->value.arg;         /* skip first arg */
 
-	if (!obj_desc->package.elements) {
-		acpi_ut_delete_object_desc (obj_desc);
-		return_ACPI_STATUS (AE_NO_MEMORY);
-	}
+	byte_list = (acpi_parse2_object *) arg->next;
+	if (byte_list) {
+		if (byte_list->opcode != AML_INT_BYTELIST_OP) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+				"Expecting bytelist, got AML opcode %X in op %p\n",
+				byte_list->opcode, byte_list));
 
-	obj_desc->package.next_element = obj_desc->package.elements;
+			acpi_ut_remove_reference (obj_desc);
+			return (AE_TYPE);
+		}
+
+		byte_list_length = byte_list->value.integer32;
+	}
 
 	/*
-	 * Now init the elements of the package
+	 * The buffer length (number of bytes) will be the larger of:
+	 * 1) The specified buffer length and
+	 * 2) The length of the initializer byte list
 	 */
-	arg = arg->next;
-	while (arg) {
-		if (arg->opcode == AML_PACKAGE_OP) {
-			status = acpi_ds_build_internal_package_obj (walk_state, arg,
-					  obj_desc->package.next_element);
-		}
+	obj_desc->buffer.length = buffer_length;
+	if (byte_list_length > buffer_length) {
+		obj_desc->buffer.length = byte_list_length;
+	}
 
-		else {
-			status = acpi_ds_build_internal_simple_obj (walk_state, arg,
-					  obj_desc->package.next_element);
-		}
+	/* Allocate the buffer */
 
-		obj_desc->package.next_element++;
-		arg = arg->next;
+	if (obj_desc->buffer.length == 0) {
+		obj_desc->buffer.pointer = NULL;
+		ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n"));
+		return_ACPI_STATUS (AE_OK);
 	}
 
-	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
-	return_ACPI_STATUS (status);
+	obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
+			   obj_desc->buffer.length);
+	if (!obj_desc->buffer.pointer) {
+		acpi_ut_delete_object_desc (obj_desc);
+		return_ACPI_STATUS (AE_NO_MEMORY);
+	}
+
+	/* Initialize buffer from the Byte_list (if present) */
+
+	if (byte_list) {
+		ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->data,
+				  byte_list_length);
+	}
+
+	obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
+	op->node = (acpi_namespace_node *) obj_desc;
+	return_ACPI_STATUS (AE_OK);
 }
 
 
 /*****************************************************************************
  *
- * FUNCTION:    Acpi_ds_build_internal_object
+ * FUNCTION:    Acpi_ds_build_internal_package_obj
  *
  * PARAMETERS:  Op              - Parser object to be translated
  *              Obj_desc_ptr    - Where the ACPI internal object is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Translate a parser Op object to the equivalent namespace
- *              object
+ * DESCRIPTION: Translate a parser Op package object to the equivalent
+ *              namespace object
  *
  ****************************************************************************/
 
 acpi_status
-acpi_ds_build_internal_object (
+acpi_ds_build_internal_package_obj (
 	acpi_walk_state         *walk_state,
 	acpi_parse_object       *op,
+	u32                     package_length,
 	acpi_operand_object     **obj_desc_ptr)
 {
-	acpi_status             status;
+	acpi_parse_object       *arg;
+	acpi_parse_object       *parent;
+	acpi_operand_object     *obj_desc = NULL;
+	u32                     package_list_length;
+	acpi_status             status = AE_OK;
+	u32                     i;
 
 
-	switch (op->opcode) {
-	case AML_PACKAGE_OP:
-	case AML_VAR_PACKAGE_OP:
+	ACPI_FUNCTION_TRACE ("Ds_build_internal_package_obj");
 
-		status = acpi_ds_build_internal_package_obj (walk_state, op, obj_desc_ptr);
-		break;
 
+	/* Find the parent of a possibly nested package */
 
-	default:
 
-		status = acpi_ds_build_internal_simple_obj (walk_state, op, obj_desc_ptr);
-		break;
+	parent = op->parent;
+	while ((parent->opcode == AML_PACKAGE_OP)     ||
+		   (parent->opcode == AML_VAR_PACKAGE_OP)) {
+		parent = parent->parent;
 	}
 
-	return (status);
+	obj_desc = *obj_desc_ptr;
+	if (obj_desc) {
+		/*
+		 * We are evaluating a Named package object "Name (xxxx, Package)".
+		 * Get the existing package object from the NS node
+		 */
+	}
+	else {
+		obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
+		*obj_desc_ptr = obj_desc;
+		if (!obj_desc) {
+			return_ACPI_STATUS (AE_NO_MEMORY);
+		}
+
+		obj_desc->package.node = parent->node;
+	}
+
+	obj_desc->package.count = package_length;
+
+	/* Count the number of items in the package list */
+
+	package_list_length = 0;
+	arg = op->value.arg;
+	arg = arg->next;
+	while (arg) {
+		package_list_length++;
+		arg = arg->next;
+	}
+
+	/*
+	 * The package length (number of elements) will be the greater
+	 * of the specified length and the length of the initializer list
+	 */
+	if (package_list_length > package_length) {
+		obj_desc->package.count = package_list_length;
+	}
+
+	/*
+	 * Allocate the pointer array (array of pointers to the
+	 * individual objects). Add an extra pointer slot so
+	 * that the list is always null terminated.
+	 */
+	obj_desc->package.elements = ACPI_MEM_CALLOCATE (
+			 (obj_desc->package.count + 1) * sizeof (void *));
+
+	if (!obj_desc->package.elements) {
+		acpi_ut_delete_object_desc (obj_desc);
+		return_ACPI_STATUS (AE_NO_MEMORY);
+	}
+
+	/*
+	 * Now init the elements of the package
+	 */
+	i = 0;
+	arg = op->value.arg;
+	arg = arg->next;
+	while (arg) {
+		if (arg->opcode == AML_INT_RETURN_VALUE_OP) {
+			/* Object (package or buffer) is already built */
+
+			obj_desc->package.elements[i] = (acpi_operand_object *) arg->node;
+		}
+		else {
+			status = acpi_ds_build_internal_object (walk_state, arg,
+					  &obj_desc->package.elements[i]);
+		}
+
+		i++;
+		arg = arg->next;
+	}
+
+	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
+	op->node = (acpi_namespace_node *) obj_desc;
+	return_ACPI_STATUS (status);
 }
 
 
@@ -666,7 +696,7 @@
 
 	node->type = obj_desc->common.type;
 
-	/* Init obj */
+	/* Attach obj to node */
 
 	status = acpi_ns_attach_object (node, obj_desc, node->type);
 
diff -Nru a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
--- a/drivers/acpi/dispatcher/dsopcode.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/dispatcher/dsopcode.c	Sun Apr 14 12:16:57 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: dsopcode - Dispatcher Op Region support and handling of
  *                         "control" opcodes
- *              $Revision: 73 $
+ *              $Revision: 74 $
  *
  *****************************************************************************/
 
@@ -54,7 +54,9 @@
 acpi_status
 acpi_ds_execute_arguments (
 	acpi_namespace_node     *node,
-	acpi_operand_object     *extra_desc)
+	acpi_namespace_node     *scope_node,
+	u32                     aml_length,
+	u8                      *aml_start)
 {
 	acpi_status             status;
 	acpi_parse_object       *op;
@@ -66,17 +68,16 @@
 
 
 	/*
-	 * Allocate a new parser op to be the root of the parsed
-	 * Buffer_field tree
+	 * Allocate a new parser op to be the root of the parsed tree
 	 */
-	op = acpi_ps_alloc_op (AML_SCOPE_OP);
+	op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
 	if (!op) {
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
 	/* Save the Node for use in Acpi_ps_parse_aml */
 
-	op->node = acpi_ns_get_parent_node (node);
+	op->node = scope_node;
 
 	/* Create and initialize a new parser state */
 
@@ -85,8 +86,8 @@
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start,
-			  extra_desc->extra.aml_length, NULL, NULL, 1);
+	status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
+			  aml_length, NULL, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
@@ -94,7 +95,7 @@
 
 	walk_state->parse_flags = 0;
 
-	/* Pass1: Parse the entire Buffer_field declaration */
+	/* Pass1: Parse the entire declaration */
 
 	status = acpi_ps_parse_aml (walk_state);
 	if (ACPI_FAILURE (status)) {
@@ -102,7 +103,7 @@
 		return_ACPI_STATUS (status);
 	}
 
-	/* Get and init the actual Field_unit Op created above */
+	/* Get and init the Op created above */
 
 	arg = op->value.arg;
 	op->node = node;
@@ -111,12 +112,12 @@
 
 	/* Evaluate the address and length arguments for the Buffer Field */
 
-	op = acpi_ps_alloc_op (AML_SCOPE_OP);
+	op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
 	if (!op) {
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	op->node = acpi_ns_get_parent_node (node);
+	op->node = scope_node;
 
 	/* Create and initialize a new parser state */
 
@@ -125,8 +126,8 @@
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, NULL, extra_desc->extra.aml_start,
-			  extra_desc->extra.aml_length, NULL, NULL, 3);
+	status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
+			  aml_length, NULL, NULL, 3);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
@@ -178,7 +179,102 @@
 
 	/* Execute the AML code for the Term_arg arguments */
 
-	status = acpi_ds_execute_arguments (node, extra_desc);
+	status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
+			 extra_desc->extra.aml_length, extra_desc->extra.aml_start);
+	return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_get_buffer_arguments
+ *
+ * PARAMETERS:  Obj_desc        - A valid Bufferobject
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get Buffer length and initializer byte list.  This implements
+ *              the late evaluation of these attributes.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_buffer_arguments (
+	acpi_operand_object     *obj_desc)
+{
+	acpi_namespace_node     *node;
+	acpi_status             status;
+
+
+	ACPI_FUNCTION_TRACE_PTR ("Ds_get_buffer_arguments", obj_desc);
+
+
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS (AE_OK);
+	}
+
+	/* Get the Buffer node */
+
+	node = obj_desc->buffer.node;
+	if (!node) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+				"No pointer back to NS node in buffer %p\n", obj_desc));
+		return_ACPI_STATUS (AE_AML_INTERNAL);
+	}
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer JIT Init\n"));
+
+	/* Execute the AML code for the Term_arg arguments */
+
+	status = acpi_ds_execute_arguments (node, node,
+			 obj_desc->buffer.aml_length, obj_desc->buffer.aml_start);
+	return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_get_package_arguments
+ *
+ * PARAMETERS:  Obj_desc        - A valid Packageobject
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get Package length and initializer byte list.  This implements
+ *              the late evaluation of these attributes.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_package_arguments (
+	acpi_operand_object     *obj_desc)
+{
+	acpi_namespace_node     *node;
+	acpi_status             status;
+
+
+	ACPI_FUNCTION_TRACE_PTR ("Ds_get_package_arguments", obj_desc);
+
+
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS (AE_OK);
+	}
+
+	/* Get the Package node */
+
+	node = obj_desc->package.node;
+	if (!node) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+				"No pointer back to NS node in package %p\n", obj_desc));
+		return_ACPI_STATUS (AE_AML_INTERNAL);
+	}
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package JIT Init\n"));
+
+	/* Execute the AML code for the Term_arg arguments */
+
+	status = acpi_ds_execute_arguments (node, node,
+			 obj_desc->package.aml_length, obj_desc->package.aml_start);
 	return_ACPI_STATUS (status);
 }
 
@@ -202,7 +298,7 @@
 {
 	acpi_namespace_node     *node;
 	acpi_status             status;
-	acpi_operand_object     *region_obj2;
+	acpi_operand_object     *extra_desc;
 
 
 	ACPI_FUNCTION_TRACE_PTR ("Ds_get_region_arguments", obj_desc);
@@ -212,22 +308,23 @@
 		return_ACPI_STATUS (AE_OK);
 	}
 
-	region_obj2 = acpi_ns_get_secondary_object (obj_desc);
-	if (!region_obj2) {
+	extra_desc = acpi_ns_get_secondary_object (obj_desc);
+	if (!extra_desc) {
 		return_ACPI_STATUS (AE_NOT_EXIST);
 	}
 
-	/* Get the AML pointer (method object) and region node */
+	/* Get the Region node */
 
 	node = obj_desc->region.node;
 
 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (node, " [Operation Region]"));
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] Op_region Init at AML %p\n",
-		(char *) &node->name, region_obj2->extra.aml_start));
+		(char *) &node->name, extra_desc->extra.aml_start));
 
 
-	status = acpi_ds_execute_arguments (node, region_obj2);
+	status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
+			 extra_desc->extra.aml_length, extra_desc->extra.aml_start);
 	return_ACPI_STATUS (status);
 }
 
@@ -306,7 +403,7 @@
 
 	next_op = op->value.arg;
 
-	/* Acpi_evaluate/create the address and length operands */
+	/* Evaluate/create the address and length operands */
 
 	status = acpi_ds_create_operands (walk_state, next_op);
 	if (ACPI_FAILURE (status)) {
@@ -556,7 +653,7 @@
 
 	next_op = next_op->next;
 
-	/* Acpi_evaluate/create the address and length operands */
+	/* Evaluate/create the address and length operands */
 
 	status = acpi_ds_create_operands (walk_state, next_op);
 	if (ACPI_FAILURE (status)) {
@@ -605,6 +702,95 @@
 	/* Now the address and length are valid for this opregion */
 
 	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
+
+	return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_eval_data_object_operands
+ *
+ * PARAMETERS:  Op              - A valid Data_object Op object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get the operands and complete the following data objec types:
+ *              Buffer
+ *              Package
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_eval_data_object_operands (
+	acpi_walk_state         *walk_state,
+	acpi_parse_object       *op,
+	acpi_operand_object     *obj_desc)
+{
+	acpi_status             status;
+	acpi_operand_object     *arg_desc;
+	u32                     length;
+
+
+	ACPI_FUNCTION_TRACE ("Ds_eval_data_object_operands");
+
+
+	/* The first operand (for all of these data objects) is the length */
+
+	status = acpi_ds_create_operand (walk_state, op->value.arg, 1);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	status = acpi_ex_resolve_operands (walk_state->opcode,
+			  &(walk_state->operands [walk_state->num_operands -1]),
+			  walk_state);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/* Extract length operand */
+
+	arg_desc = walk_state->operands [walk_state->num_operands - 1];
+	length = (u32) arg_desc->integer.value;
+
+	/* Cleanup for length operand */
+
+	acpi_ds_obj_stack_pop (1, walk_state);
+	acpi_ut_remove_reference (arg_desc);
+
+	/*
+	 * Create the actual data object
+	 */
+	switch (op->opcode) {
+	case AML_BUFFER_OP:
+
+		status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc);
+		break;
+
+	case AML_PACKAGE_OP:
+	case AML_VAR_PACKAGE_OP:
+
+		status = acpi_ds_build_internal_package_obj (walk_state, op, length, &obj_desc);
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+	}
+
+	if (ACPI_SUCCESS (status)) {
+		/*
+		 * Return the object in the Walk_state, unless the parent is a package --
+		 * in this case, the return object will be stored in the parse tree
+		 * for the package.
+		 */
+		if ((!op->parent) ||
+			((op->parent->opcode != AML_PACKAGE_OP) &&
+			 (op->parent->opcode != AML_VAR_PACKAGE_OP) &&
+			 (op->parent->opcode != AML_NAME_OP))) {
+			walk_state->result_obj = obj_desc;
+		}
+	}
 
 	return_ACPI_STATUS (status);
 }
diff -Nru a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
--- a/drivers/acpi/dispatcher/dsutils.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/dispatcher/dsutils.c	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: dsutils - Dispatcher utilities
- *              $Revision: 88 $
+ *              $Revision: 89 $
  *
  ******************************************************************************/
 
@@ -133,7 +133,11 @@
 	case AML_CLASS_NAMED_OBJECT:
 
 		if ((op->parent->opcode == AML_REGION_OP)       ||
-			(op->parent->opcode == AML_DATA_REGION_OP)) {
+			(op->parent->opcode == AML_DATA_REGION_OP)  ||
+			(op->parent->opcode == AML_PACKAGE_OP)      ||
+			(op->parent->opcode == AML_VAR_PACKAGE_OP)  ||
+			(op->parent->opcode == AML_BUFFER_OP)       ||
+			(op->parent->opcode == AML_INT_EVAL_SUBTREE_OP)) {
 			/*
 			 * These opcodes allow Term_arg(s) as operands and therefore
 			 * the operands can be method calls.  The result is used.
@@ -144,11 +148,12 @@
 		goto result_not_used;
 
 
-	/*
-	 * In all other cases. the parent will actually use the return
-	 * object, so keep it.
-	 */
 	default:
+
+		/*
+		 * In all other cases. the parent will actually use the return
+		 * object, so keep it.
+		 */
 		goto result_used;
 	}
 
diff -Nru a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
--- a/drivers/acpi/dispatcher/dswexec.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/dispatcher/dswexec.c	Sun Apr 14 12:16:58 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: dswexec - Dispatcher method execution callbacks;
  *                        dispatch to interpreter.
- *              $Revision: 89 $
+ *              $Revision: 90 $
  *
  *****************************************************************************/
 
@@ -495,6 +495,50 @@
 			}
 
 			status = acpi_ds_eval_buffer_field_operands (walk_state, op);
+			break;
+
+
+		case AML_TYPE_CREATE_OBJECT:
+
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+				"Executing Create_object (Buffer/Package) Op=%p\n", op));
+
+			switch (op->parent->opcode) {
+			case AML_NAME_OP:
+
+				/*
+				 * Put the Node on the object stack (Contains the ACPI Name of
+				 * this object)
+				 */
+				walk_state->operands[0] = (void *) op->parent->node;
+				walk_state->num_operands = 1;
+
+				status = acpi_ds_create_node (walk_state, op->parent->node, op->parent);
+				if (ACPI_FAILURE (status)) {
+					break;
+				}
+
+				/* Fall through */
+
+			case AML_INT_EVAL_SUBTREE_OP:
+
+				status = acpi_ds_eval_data_object_operands (walk_state, op, acpi_ns_get_attached_object (op->parent->node));
+				break;
+
+			default:
+
+				status = acpi_ds_eval_data_object_operands (walk_state, op, NULL);
+				break;
+			}
+
+			/*
+			 * If a result object was returned from above, push it on the
+			 * current result stack
+			 */
+			if (ACPI_SUCCESS (status) &&
+				walk_state->result_obj) {
+				status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+			}
 			break;
 
 
diff -Nru a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
--- a/drivers/acpi/dispatcher/dswload.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/dispatcher/dswload.c	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dswload - Dispatcher namespace load callbacks
- *              $Revision: 61 $
+ *              $Revision: 62 $
  *
  *****************************************************************************/
 
@@ -167,7 +167,7 @@
 
 	/* Initialize */
 
-	((acpi_parse2_object *)op)->name = node->name;
+	((acpi_parse2_object *)op)->name = node->name.integer;
 
 	/*
 	 * Put the Node in the "op" object that the parser uses, so we
@@ -381,7 +381,7 @@
 
 			/* Initialize the new op */
 
-			((acpi_parse2_object *)op)->name = node->name;
+			((acpi_parse2_object *)op)->name = node->name.integer;
 			*out_op = op;
 		}
 
diff -Nru a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
--- a/drivers/acpi/events/evevent.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/events/evevent.c	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evevent - Fixed and General Purpose Even handling and dispatch
- *              $Revision: 71 $
+ *              $Revision: 78 $
  *
  *****************************************************************************/
 
@@ -326,11 +326,14 @@
 	 *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
 	 *  to be the same size."
 	 */
-	acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_2 (acpi_gbl_FADT->gpe0_blk_len);
-	acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_2 (acpi_gbl_FADT->gpe1_blk_len);
+	acpi_gbl_gpe_block_info[0].address_space_id = acpi_gbl_FADT->Xgpe0_blk.address_space_id;
+	acpi_gbl_gpe_block_info[1].address_space_id = acpi_gbl_FADT->Xgpe1_blk.address_space_id;
 
-	acpi_gbl_gpe_block_info[0].block_address = (u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0_blk.address);
-	acpi_gbl_gpe_block_info[1].block_address = (u16) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address);
+	acpi_gbl_gpe_block_info[0].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe0_blk.register_bit_width);
+	acpi_gbl_gpe_block_info[1].register_count = (u16) ACPI_DIV_16 (acpi_gbl_FADT->Xgpe1_blk.register_bit_width);
+
+	acpi_gbl_gpe_block_info[0].block_address = &acpi_gbl_FADT->Xgpe0_blk;
+	acpi_gbl_gpe_block_info[1].block_address = &acpi_gbl_FADT->Xgpe1_blk;
 
 	acpi_gbl_gpe_block_info[0].block_base_number = 0;
 	acpi_gbl_gpe_block_info[1].block_base_number = acpi_gbl_FADT->gpe1_base;
@@ -421,9 +424,20 @@
 			/* Init the Register info for this entire GPE register (8 GPEs) */
 
 			gpe_register_info->base_gpe_number = (u8) (acpi_gbl_gpe_block_info[gpe_block].block_base_number + (ACPI_MUL_8 (i)));
-			gpe_register_info->status_addr = (u16) (acpi_gbl_gpe_block_info[gpe_block].block_address + i);
-			gpe_register_info->enable_addr = (u16) (acpi_gbl_gpe_block_info[gpe_block].block_address + i +
-					  acpi_gbl_gpe_block_info[gpe_block].register_count);
+
+			ACPI_STORE_ADDRESS (gpe_register_info->status_address.address,
+					   (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + i));
+
+			ACPI_STORE_ADDRESS (gpe_register_info->enable_address.address,
+					   (ACPI_GET_ADDRESS (acpi_gbl_gpe_block_info[gpe_block].block_address->address) + i +
+							  acpi_gbl_gpe_block_info[gpe_block].register_count));
+
+			gpe_register_info->status_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id;
+			gpe_register_info->enable_address.address_space_id = acpi_gbl_gpe_block_info[gpe_block].address_space_id;
+			gpe_register_info->status_address.register_bit_width = 8;
+			gpe_register_info->enable_address.register_bit_width = 8;
+			gpe_register_info->status_address.register_bit_offset = 8;
+			gpe_register_info->enable_address.register_bit_offset = 8;
 
 			/* Init the Index mapping info for each GPE number within this register */
 
@@ -440,18 +454,24 @@
 			 * are cleared by writing a '1', while enable registers are cleared
 			 * by writing a '0'.
 			 */
-			acpi_os_write_port (gpe_register_info->enable_addr, 0x00, 8);
-			acpi_os_write_port (gpe_register_info->status_addr, 0xFF, 8);
+
+			acpi_hw_low_level_write (8, 0x00, &gpe_register_info->enable_address, 0);
+			acpi_hw_low_level_write (8, 0xFF, &gpe_register_info->status_address, 0);
 
 			gpe_register++;
 		}
-	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE registers: %X@%8.8X%8.8X (Blk0) %X@%8.8X%8.8X (Blk1)\n",
-		acpi_gbl_gpe_block_info[0].register_count,
-		ACPI_HIDWORD (acpi_gbl_FADT->Xgpe0_blk.address), ACPI_LODWORD (acpi_gbl_FADT->Xgpe0_blk.address),
-		acpi_gbl_gpe_block_info[1].register_count,
-		ACPI_HIDWORD (acpi_gbl_FADT->Xgpe1_blk.address), ACPI_LODWORD (acpi_gbl_FADT->Xgpe1_blk.address)));
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d: %X registers at %8.8X%8.8X\n",
+			gpe_block, acpi_gbl_gpe_block_info[0].register_count,
+			ACPI_HIDWORD (acpi_gbl_gpe_block_info[gpe_block].block_address->address),
+			ACPI_LODWORD (acpi_gbl_gpe_block_info[gpe_block].block_address->address)));
+
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d Range GPE #%2.2X to GPE #%2.2X\n",
+			gpe_block,
+			acpi_gbl_gpe_block_info[gpe_block].block_base_number,
+			acpi_gbl_gpe_block_info[gpe_block].block_base_number +
+				((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1)));
+	}
 
 	return_ACPI_STATUS (AE_OK);
 
@@ -645,17 +665,18 @@
 	for (i = 0; i < acpi_gbl_gpe_register_count; i++) {
 		gpe_register_info = &acpi_gbl_gpe_register_info[i];
 
-		acpi_os_read_port (gpe_register_info->status_addr,
-				  &gpe_register_info->status, 8);
+		gpe_register_info->status = (u8) acpi_hw_low_level_read (8,
+				   &gpe_register_info->status_address, 0);
 
-		acpi_os_read_port (gpe_register_info->enable_addr,
-				  &gpe_register_info->enable, 8);
+		gpe_register_info->enable = (u8) acpi_hw_low_level_read (8,
+				   &gpe_register_info->enable_address, 0);
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
-			"GPE block at %X - Enable %08X Status %08X\n",
-			gpe_register_info->enable_addr,
-			gpe_register_info->status,
-			gpe_register_info->enable));
+			"GPE block at %8.8X%8.8X - Enable %08X Status %08X\n",
+			ACPI_HIDWORD (gpe_register_info->enable_address.address),
+			ACPI_LODWORD (gpe_register_info->enable_address.address),
+			gpe_register_info->enable,
+			gpe_register_info->status));
 
 		/* First check if there is anything active at all in this register */
 
@@ -816,18 +837,18 @@
 	}
 	else if (gpe_info->method_handle) {
 		/*
+		 * Disable GPE, so it doesn't keep firing before the method has a
+		 * chance to run.
+		 */
+		acpi_hw_disable_gpe (gpe_number);
+
+		/*
 		 * Execute the method associated with the GPE.
 		 */
 		if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
 				 acpi_ev_asynch_execute_gpe_method,
 				 ACPI_TO_POINTER (gpe_number)))) {
-			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%X], disabling event\n", gpe_number));
-
-			/*
-			 * Disable the GPE on error.  The GPE will remain disabled until the ACPI
-			 * Core Subsystem is restarted, or the handler is reinstalled.
-			 */
-			acpi_hw_disable_gpe (gpe_number);
+			ACPI_REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%X], event is disabled\n", gpe_number));
 		}
 	}
 	else {
diff -Nru a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
--- a/drivers/acpi/events/evmisc.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/events/evmisc.c	Sun Apr 14 12:16:55 2002
@@ -1,8 +1,7 @@
 /******************************************************************************
  *
- * Module Name: evmisc - ACPI device notification handler dispatch
- *                       and ACPI Global Lock support
- *              $Revision: 47 $
+ * Module Name: evmisc - Miscellaneous event manager support functions
+ *              $Revision: 48 $
  *
  *****************************************************************************/
 
@@ -32,6 +31,40 @@
 
 #define _COMPONENT          ACPI_EVENTS
 	 ACPI_MODULE_NAME    ("evmisc")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ev_is_notify_object
+ *
+ * PARAMETERS:  Node            - Node to check
+ *
+ * RETURN:      TRUE if notifies allowed on this object
+ *
+ * DESCRIPTION: Check type of node for a object that supports notifies.
+ *
+ *              TBD: This could be replaced by a flag bit in the node.
+ *
+ ******************************************************************************/
+
+u8
+acpi_ev_is_notify_object (
+	acpi_namespace_node     *node)
+{
+	switch (node->type) {
+	case ACPI_TYPE_DEVICE:
+	case ACPI_TYPE_PROCESSOR:
+	case ACPI_TYPE_POWER:
+	case ACPI_TYPE_THERMAL:
+		/*
+		 * These are the ONLY objects that can receive ACPI notifications
+		 */
+		return (TRUE);
+
+	default:
+		return (FALSE);
+	}
+}
 
 
 /*******************************************************************************
diff -Nru a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
--- a/drivers/acpi/events/evxface.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/events/evxface.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evxface - External interfaces for ACPI events
- *              $Revision: 125 $
+ *              $Revision: 126 $
  *
  *****************************************************************************/
 
@@ -191,7 +191,7 @@
 {
 	acpi_operand_object     *obj_desc;
 	acpi_operand_object     *notify_obj;
-	acpi_namespace_node     *device_node;
+	acpi_namespace_node     *node;
 	acpi_status             status;
 
 
@@ -200,7 +200,8 @@
 
 	/* Parameter validation */
 
-	if ((!handler) ||
+	if ((!device)  ||
+		(!handler) ||
 		(handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
@@ -212,8 +213,8 @@
 
 	/* Convert and validate the device handle */
 
-	device_node = acpi_ns_map_handle_to_node (device);
-	if (!device_node) {
+	node = acpi_ns_map_handle_to_node (device);
+	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
 	}
@@ -236,12 +237,12 @@
 		}
 
 		if (handler_type == ACPI_SYSTEM_NOTIFY) {
-			acpi_gbl_sys_notify.node = device_node;
+			acpi_gbl_sys_notify.node = node;
 			acpi_gbl_sys_notify.handler = handler;
 			acpi_gbl_sys_notify.context = context;
 		}
 		else /* ACPI_DEVICE_NOTIFY */ {
-			acpi_gbl_drv_notify.node = device_node;
+			acpi_gbl_drv_notify.node = node;
 			acpi_gbl_drv_notify.handler = handler;
 			acpi_gbl_drv_notify.context = context;
 		}
@@ -255,28 +256,24 @@
 	 * Note that only certain object types can receive notifications.
 	 */
 	else {
-		/*
-		 * These are the ONLY objects that can receive ACPI notifications
-		 */
-		if ((device_node->type != ACPI_TYPE_DEVICE)    &&
-			(device_node->type != ACPI_TYPE_PROCESSOR) &&
-			(device_node->type != ACPI_TYPE_POWER)     &&
-			(device_node->type != ACPI_TYPE_THERMAL)) {
-			status = AE_BAD_PARAMETER;
+		/* Notifies allowed on this object? */
+
+		if (!acpi_ev_is_notify_object (node)) {
+			status = AE_TYPE;
 			goto unlock_and_exit;
 		}
 
 		/* Check for an existing internal object */
 
-		obj_desc = acpi_ns_get_attached_object (device_node);
+		obj_desc = acpi_ns_get_attached_object (node);
 		if (obj_desc) {
 
 			/* Object exists - make sure there's no handler */
 
 			if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
-				  obj_desc->device.sys_handler) ||
+				  obj_desc->common_notify.sys_handler) ||
 				((handler_type == ACPI_DEVICE_NOTIFY) &&
-				  obj_desc->device.drv_handler)) {
+				  obj_desc->common_notify.drv_handler)) {
 				status = AE_ALREADY_EXISTS;
 				goto unlock_and_exit;
 			}
@@ -284,7 +281,7 @@
 		else {
 			/* Create a new object */
 
-			obj_desc = acpi_ut_create_internal_object (device_node->type);
+			obj_desc = acpi_ut_create_internal_object (node->type);
 			if (!obj_desc) {
 				status = AE_NO_MEMORY;
 				goto unlock_and_exit;
@@ -292,7 +289,7 @@
 
 			/* Attach new object to the Node */
 
-			status = acpi_ns_attach_object (device, obj_desc, device_node->type);
+			status = acpi_ns_attach_object (device, obj_desc, node->type);
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
@@ -306,16 +303,15 @@
 			goto unlock_and_exit;
 		}
 
-		notify_obj->notify_handler.node = device_node;
+		notify_obj->notify_handler.node = node;
 		notify_obj->notify_handler.handler = handler;
 		notify_obj->notify_handler.context = context;
 
-
 		if (handler_type == ACPI_SYSTEM_NOTIFY) {
-			obj_desc->device.sys_handler = notify_obj;
+			obj_desc->common_notify.sys_handler = notify_obj;
 		}
 		else /* ACPI_DEVICE_NOTIFY */ {
-			obj_desc->device.drv_handler = notify_obj;
+			obj_desc->common_notify.drv_handler = notify_obj;
 		}
 	}
 
@@ -349,7 +345,7 @@
 {
 	acpi_operand_object     *notify_obj;
 	acpi_operand_object     *obj_desc;
-	acpi_namespace_node     *device_node;
+	acpi_namespace_node     *node;
 	acpi_status             status;
 
 
@@ -358,7 +354,8 @@
 
 	/* Parameter validation */
 
-	if ((!handler) ||
+	if ((!device)  ||
+		(!handler) ||
 		(handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
@@ -370,8 +367,8 @@
 
 	/* Convert and validate the device handle */
 
-	device_node = acpi_ns_map_handle_to_node (device);
-	if (!device_node) {
+	node = acpi_ns_map_handle_to_node (device);
+	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
 	}
@@ -406,20 +403,16 @@
 	 * All Other Objects
 	 */
 	else {
-		/*
-		 * These are the ONLY objects that can receive ACPI notifications
-		 */
-		if ((device_node->type != ACPI_TYPE_DEVICE)    &&
-			(device_node->type != ACPI_TYPE_PROCESSOR) &&
-			(device_node->type != ACPI_TYPE_POWER)     &&
-			(device_node->type != ACPI_TYPE_THERMAL)) {
-			status = AE_BAD_PARAMETER;
+		/* Notifies allowed on this object? */
+
+		if (!acpi_ev_is_notify_object (node)) {
+			status = AE_TYPE;
 			goto unlock_and_exit;
 		}
 
 		/* Check for an existing internal object */
 
-		obj_desc = acpi_ns_get_attached_object (device_node);
+		obj_desc = acpi_ns_get_attached_object (node);
 		if (!obj_desc) {
 			status = AE_NOT_EXIST;
 			goto unlock_and_exit;
@@ -428,10 +421,10 @@
 		/* Object exists - make sure there's an existing handler */
 
 		if (handler_type == ACPI_SYSTEM_NOTIFY) {
-			notify_obj = obj_desc->device.sys_handler;
+			notify_obj = obj_desc->common_notify.sys_handler;
 		}
 		else {
-			notify_obj = obj_desc->device.drv_handler;
+			notify_obj = obj_desc->common_notify.drv_handler;
 		}
 
 		if ((!notify_obj) ||
@@ -443,10 +436,10 @@
 		/* Remove the handler */
 
 		if (handler_type == ACPI_SYSTEM_NOTIFY) {
-			obj_desc->device.sys_handler = NULL;
+			obj_desc->common_notify.sys_handler = NULL;
 		}
 		else {
-			obj_desc->device.drv_handler = NULL;
+			obj_desc->common_notify.drv_handler = NULL;
 		}
 
 		acpi_ut_remove_reference (notify_obj);
diff -Nru a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
--- a/drivers/acpi/executer/exconfig.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/executer/exconfig.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
- *              $Revision: 59 $
+ *              $Revision: 60 $
  *
  *****************************************************************************/
 
@@ -329,7 +329,7 @@
 		 * Read the entire field and thus the entire table.  Buffer is
 		 * allocated during the read.
 		 */
-		status = acpi_ex_read_data_from_field (obj_desc, &buffer_desc);
+		status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
 		if (ACPI_FAILURE (status)) {
 			goto cleanup;
 		}
diff -Nru a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
--- a/drivers/acpi/executer/exconvrt.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/executer/exconvrt.c	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exconvrt - Object conversion routines
- *              $Revision: 30 $
+ *              $Revision: 32 $
  *
  *****************************************************************************/
 
@@ -215,8 +215,7 @@
 		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
 			/*
 			 * We are running a method that exists in a 32-bit ACPI table.
-			 * Truncate the value to 32 bits by zeroing out the upper
-			 * 32-bit field
+			 * Use only 32 bits of the Integer for conversion.
 			 */
 			integer_size = sizeof (u32);
 		}
@@ -259,6 +258,9 @@
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
+	/* Mark buffer initialized */
+
+	(*result_desc)->common.flags |= AOPOBJ_DATA_VALID;
 	return_ACPI_STATUS (AE_OK);
 }
 
@@ -399,8 +401,7 @@
 		if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
 			/*
 			 * We are running a method that exists in a 32-bit ACPI table.
-			 * Truncate the value to 32 bits by zeroing out the upper
-			 * 32-bit field
+			 * Use only 32 bits of the Integer
 			 */
 			integer_size = sizeof (u32);
 		}
diff -Nru a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
--- a/drivers/acpi/executer/exdump.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/executer/exdump.c	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exdump - Interpreter debug output routines
- *              $Revision: 145 $
+ *              $Revision: 147 $
  *
  *****************************************************************************/
 
@@ -149,7 +149,7 @@
 	ACPI_FUNCTION_NAME ("Ex_dump_operand")
 
 
-	if (!((ACPI_LV_INFO & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
+	if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
 		return (AE_OK);
 	}
 
@@ -159,25 +159,25 @@
 		 * since most (if not all)
 		 * code that dumps the stack expects something to be there!
 		 */
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null stack entry ptr\n"));
+		acpi_os_printf ("Null stack entry ptr\n");
 		return (AE_OK);
 	}
 
 	if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%p NS Node: ", obj_desc));
-		ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_INFO);
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p NS Node: ", obj_desc));
+		ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC);
 		return (AE_OK);
 	}
 
 	if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_INTERNAL) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%p is not a local object\n", obj_desc));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is not a local object\n", obj_desc));
 		ACPI_DUMP_BUFFER (obj_desc, sizeof (acpi_operand_object));
 		return (AE_OK);
 	}
 
 	/*  Obj_desc is a valid object */
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%p ", obj_desc));
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc));
 
 	switch (obj_desc->common.type) {
 	case INTERNAL_TYPE_REFERENCE:
@@ -427,7 +427,7 @@
 
 		if (!obj_desc->buffer_field.buffer_obj)
 		{
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "*NULL* \n"));
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n"));
 		}
 
 		else if (ACPI_TYPE_BUFFER !=
@@ -541,7 +541,7 @@
 	}
 
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 		"************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
 		ident, num_levels));
 
@@ -562,7 +562,7 @@
 		}
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 		"************* Stack dump from %s(%d), %s\n",
 		module_name, line_number, note));
 	return;
@@ -734,7 +734,6 @@
 		acpi_ex_out_integer ("Flags",        obj_desc->package.flags);
 		acpi_ex_out_integer ("Count",        obj_desc->package.count);
 		acpi_ex_out_pointer ("Elements",     obj_desc->package.elements);
-		acpi_ex_out_pointer ("Next_element", obj_desc->package.next_element);
 
 		/* Dump the package contents */
 
diff -Nru a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
--- a/drivers/acpi/executer/exfield.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/executer/exfield.c	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
- *              $Revision: 105 $
+ *              $Revision: 108 $
  *
  *****************************************************************************/
 
@@ -41,7 +41,8 @@
  *
  * FUNCTION:    Acpi_ex_read_data_from_field
  *
- * PARAMETERS:  Obj_desc            - The named field
+ * PARAMETERS:  Walk_state          - Current execution state
+ *              Obj_desc            - The named field
  *              Ret_buffer_desc     - Where the return data object is stored
  *
  * RETURN:      Status
@@ -53,12 +54,14 @@
 
 acpi_status
 acpi_ex_read_data_from_field (
+	acpi_walk_state         *walk_state,
 	acpi_operand_object     *obj_desc,
 	acpi_operand_object     **ret_buffer_desc)
 {
 	acpi_status             status;
 	acpi_operand_object     *buffer_desc;
 	u32                     length;
+	u32                     integer_size;
 	void                    *buffer;
 	u8                      locked;
 
@@ -97,7 +100,18 @@
 	 */
 	length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length);
 
-	if (length > sizeof (acpi_integer)) {
+	/* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
+
+	integer_size = sizeof (acpi_integer);
+	if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+		/*
+		 * We are running a method that exists in a 32-bit ACPI table.
+		 * Integer size is 4.
+		 */
+		integer_size = sizeof (u32);
+	}
+
+	if (length > integer_size) {
 		/* Field is too large for an Integer, create a Buffer instead */
 
 		buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
@@ -113,6 +127,7 @@
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
+		buffer_desc->common.flags = AOPOBJ_DATA_VALID;
 		buffer_desc->buffer.length = length;
 		buffer = buffer_desc->buffer.pointer;
 	}
@@ -124,14 +139,15 @@
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
-		length = sizeof (buffer_desc->integer.value);
+		length = integer_size;
+		buffer_desc->integer.value = 0;
 		buffer = &buffer_desc->integer.value;
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 		"Obj=%p Type=%X Buf=%p Len=%X\n",
 		obj_desc, obj_desc->common.type, buffer, length));
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 		"Field_write: Bit_len=%X Bit_off=%X Byte_off=%X\n",
 		obj_desc->common_field.bit_length,
 		obj_desc->common_field.start_field_bit_offset,
@@ -257,10 +273,10 @@
 		length = required_length;
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 		"Obj=%p Type=%X Buf=%p Len=%X\n",
 		obj_desc, obj_desc->common.type, buffer, length));
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 		"Field_read: Bit_len=%X Bit_off=%X Byte_off=%X\n",
 		obj_desc->common_field.bit_length,
 		obj_desc->common_field.start_field_bit_offset,
diff -Nru a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
--- a/drivers/acpi/executer/exfldio.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/executer/exfldio.c	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exfldio - Aml Field I/O
- *              $Revision: 82 $
+ *              $Revision: 84 $
  *
  *****************************************************************************/
 
@@ -148,7 +148,7 @@
 	ACPI_PHYSICAL_ADDRESS   address;
 
 
-	ACPI_FUNCTION_TRACE ("Acpi_ex_access_region");
+	ACPI_FUNCTION_TRACE ("Ex_access_region");
 
 
 	/*
@@ -672,7 +672,7 @@
 	 */
 	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
 	if (byte_field_length > buffer_length) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 			"Field size %X (bytes) too large for buffer (%X)\n",
 			byte_field_length, buffer_length));
 
@@ -684,7 +684,7 @@
 	datum_count = ACPI_ROUND_UP_TO (byte_field_length,
 			   obj_desc->common_field.access_byte_width);
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 		"Byte_len=%x, Datum_len=%x, Byte_gran=%x\n",
 		byte_field_length, datum_count,obj_desc->common_field.access_byte_width));
 
@@ -852,7 +852,7 @@
 	 */
 	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
 	if (buffer_length < byte_field_length) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Buffer length %X too small for field %X\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Buffer length %X too small for field %X\n",
 			buffer_length, byte_field_length));
 
 		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
@@ -862,7 +862,7 @@
 
 	datum_count = ACPI_ROUND_UP_TO (byte_field_length, obj_desc->common_field.access_byte_width);
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 		"Byte_len=%x, Datum_len=%x, Byte_gran=%x\n",
 		byte_field_length, datum_count, obj_desc->common_field.access_byte_width));
 
diff -Nru a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
--- a/drivers/acpi/executer/exoparg1.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/executer/exoparg1.c	Sun Apr 14 12:16:59 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exoparg1 - AML execution - opcodes with 1 argument
- *              $Revision: 134 $
+ *              $Revision: 135 $
  *
  *****************************************************************************/
 
@@ -791,10 +791,21 @@
 				 */
 				switch (operand[0]->reference.target_type) {
 				case ACPI_TYPE_BUFFER_FIELD:
+
+					/* Ensure that the Buffer arguments are evaluated */
+
+					temp_desc = operand[0]->reference.object;
+#if 0
+
+					status = acpi_ds_get_buffer_arguments (temp_desc);
+					if (ACPI_FAILURE (status)) {
+						goto cleanup;
+					}
+#endif
+
 					/*
-					 * The target is a buffer, we must create a new object that
-					 * contains one element of the buffer, the element pointed
-					 * to by the index.
+					 * Create a new object that contains one element of the
+					 * buffer -- the element pointed to by the index.
 					 *
 					 * NOTE: index into a buffer is NOT a pointer to a
 					 * sub-buffer of the main buffer, it is only a pointer to a
@@ -811,7 +822,6 @@
 					 * indexed location, we don't need to add an additional
 					 * reference to the buffer itself.
 					 */
-					temp_desc = operand[0]->reference.object;
 					return_desc->integer.value =
 						temp_desc->buffer.pointer[operand[0]->reference.offset];
 					break;
@@ -819,10 +829,17 @@
 
 				case ACPI_TYPE_PACKAGE:
 
+#if 0
+					/* Ensure that the Package arguments are evaluated */
+
+					status = acpi_ds_get_package_arguments (operand[0]->reference.object);
+					if (ACPI_FAILURE (status)) {
+						goto cleanup;
+					}
+#endif
 					/*
-					 * The target is a package, we want to return the referenced
-					 * element of the package.  We must add another reference to
-					 * this object, however.
+					 * Return the referenced element of the package.  We must add
+					 * another reference to the referenced object, however.
 					 */
 					return_desc = *(operand[0]->reference.where);
 					if (!return_desc) {
diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
--- a/drivers/acpi/executer/exoparg2.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/executer/exoparg2.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
- *              $Revision: 104 $
+ *              $Revision: 105 $
  *
  *****************************************************************************/
 
@@ -84,49 +84,45 @@
 	acpi_status             status = AE_OK;
 
 
-	ACPI_FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode));
+	ACPI_FUNCTION_TRACE_STR ("Ex_opcode_2A_0T_0R",
+			acpi_ps_get_opcode_name (walk_state->opcode));
 
 
 	/* Examine the opcode */
 
 	switch (walk_state->opcode) {
-
 	case AML_NOTIFY_OP:         /* Notify (Notify_object, Notify_value) */
 
 		/* The first operand is a namespace node */
 
 		node = (acpi_namespace_node *) operand[0];
 
-		/* The node must refer to a device or thermal zone or processor */
-
-		switch (node->type) {
-		case ACPI_TYPE_DEVICE:
-		case ACPI_TYPE_THERMAL:
-		case ACPI_TYPE_PROCESSOR:
-
-			/*
-			 * Dispatch the notify to the appropriate handler
-			 * NOTE: the request is queued for execution after this method
-			 * completes.  The notify handlers are NOT invoked synchronously
-			 * from this thread -- because handlers may in turn run other
-			 * control methods.
-			 */
-			status = acpi_ev_queue_notify_request (node,
-					 (u32) operand[1]->integer.value);
-			break;
+		/* Notifies allowed on this object? */
 
-		default:
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type %X\n",
-				node->type));
+		if (!acpi_ev_is_notify_object (node)) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
+					acpi_ut_get_type_name (node->type)));
 
 			status = AE_AML_OPERAND_TYPE;
 			break;
 		}
+
+		/*
+		 * Dispatch the notify to the appropriate handler
+		 * NOTE: the request is queued for execution after this method
+		 * completes.  The notify handlers are NOT invoked synchronously
+		 * from this thread -- because handlers may in turn run other
+		 * control methods.
+		 */
+		status = acpi_ev_queue_notify_request (node,
+				  (u32) operand[1]->integer.value);
 		break;
 
+
 	default:
 
-		ACPI_REPORT_ERROR (("Acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode));
+		ACPI_REPORT_ERROR (("Acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
+				walk_state->opcode));
 		status = AE_AML_BAD_OPCODE;
 	}
 
diff -Nru a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
--- a/drivers/acpi/executer/exprep.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/executer/exprep.c	Sun Apr 14 12:16:56 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
- *              $Revision: 114 $
+ *              $Revision: 115 $
  *
  *****************************************************************************/
 
@@ -204,61 +204,77 @@
 	 * two pieces of information - the width of each field access and the
 	 * necessary Byte_alignment (address granularity) of the access.
 	 *
-	 * For Any_acc, the Access_bit_width is the largest width that is both necessary
-	 * and possible in an attempt to access the whole field in one
-	 * I/O operation.  However, for Any_acc, the Byte_alignment is always one byte.
+	 * For Any_acc, the Access_bit_width is the largest width that is both
+	 * necessary and possible in an attempt to access the whole field in one
+	 * I/O operation.  However, for Any_acc, the Byte_alignment is always one
+	 * byte.
 	 *
 	 * For all Buffer Fields, the Byte_alignment is always one byte.
 	 *
-	 * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is the
-	 * same (equivalent) as the Byte_alignment.
+	 * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
+	 * the same (equivalent) as the Byte_alignment.
 	 */
-	access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags, &byte_alignment);
+	access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags,
+			  &byte_alignment);
 	if (!access_bit_width) {
 		return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
 	}
 
 	/* Setup width (access granularity) fields */
 
-	obj_desc->common_field.access_byte_width = (u8) ACPI_DIV_8 (access_bit_width); /* 1, 2, 4,  8 */
+	obj_desc->common_field.access_byte_width = (u8)
+			ACPI_DIV_8 (access_bit_width); /* 1, 2, 4,  8 */
 
 	/*
-	 * Base_byte_offset is the address of the start of the field within the region. It is
-	 * the byte address of the first *datum* (field-width data unit) of the field.
-	 * (i.e., the first datum that contains at least the first *bit* of the field.)
-	 * Note: Byte_alignment is always either equal to the Access_bit_width or 8 (Byte access),
-	 * and it defines the addressing granularity of the parent region or buffer.
+	 * Base_byte_offset is the address of the start of the field within the
+	 * region.  It is the byte address of the first *datum* (field-width data
+	 * unit) of the field. (i.e., the first datum that contains at least the
+	 * first *bit* of the field.)
+	 *
+	 * Note: Byte_alignment is always either equal to the Access_bit_width or 8
+	 * (Byte access), and it defines the addressing granularity of the parent
+	 * region or buffer.
 	 */
-	nearest_byte_address                     = ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
-	obj_desc->common_field.base_byte_offset  = ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);
+	nearest_byte_address =
+			ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
+	obj_desc->common_field.base_byte_offset =
+			ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);
 
 	/*
-	 * Start_field_bit_offset is the offset of the first bit of the field within a field datum.
+	 * Start_field_bit_offset is the offset of the first bit of the field within
+	 * a field datum.
 	 */
-	obj_desc->common_field.start_field_bit_offset = (u8) (field_bit_position -
-			  ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
+	obj_desc->common_field.start_field_bit_offset = (u8)
+		(field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
 
 	/*
 	 * Valid bits -- the number of bits that compose a partial datum,
-	 * 1) At the end of the field within the region (arbitrary starting bit offset)
-	 * 2) At the end of a buffer used to contain the field (starting offset always zero)
+	 * 1) At the end of the field within the region (arbitrary starting bit
+	 *    offset)
+	 * 2) At the end of a buffer used to contain the field (starting offset
+	 *    always zero)
 	 */
-	obj_desc->common_field.end_field_valid_bits = (u8) ((obj_desc->common_field.start_field_bit_offset + field_bit_length) %
-			   access_bit_width);
-	obj_desc->common_field.end_buffer_valid_bits = (u8) (field_bit_length % access_bit_width); /* Start_buffer_bit_offset always = 0 */
+	obj_desc->common_field.end_field_valid_bits = (u8)
+		((obj_desc->common_field.start_field_bit_offset + field_bit_length) %
+				  access_bit_width);
+	/* Start_buffer_bit_offset always = 0 */
+
+	obj_desc->common_field.end_buffer_valid_bits = (u8)
+		(field_bit_length % access_bit_width);
 
 	/*
-	 * Datum_valid_bits is the number of valid field bits in the first field datum.
+	 * Datum_valid_bits is the number of valid field bits in the first
+	 * field datum.
 	 */
-	obj_desc->common_field.datum_valid_bits  = (u8) (access_bit_width -
-			  obj_desc->common_field.start_field_bit_offset);
+	obj_desc->common_field.datum_valid_bits  = (u8)
+		(access_bit_width - obj_desc->common_field.start_field_bit_offset);
 
 	/*
 	 * Does the entire field fit within a single field access element? (datum)
 	 * (i.e., without crossing a datum boundary)
 	 */
 	if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <=
-		(u16) access_bit_width) {
+			(u16) access_bit_width) {
 		obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
 	}
 
@@ -341,7 +357,7 @@
 
 		acpi_ut_add_reference (obj_desc->field.region_obj);
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
 			"Region_field: Bitoff=%X Off=%X Gran=%X Region %p\n",
 			obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
 			obj_desc->field.access_byte_width, obj_desc->field.region_obj));
@@ -359,9 +375,12 @@
 		acpi_ut_add_reference (obj_desc->bank_field.region_obj);
 		acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Bank Field: Bit_off=%X Off=%X Gran=%X Region %p Bank_reg %p\n",
-			obj_desc->bank_field.start_field_bit_offset, obj_desc->bank_field.base_byte_offset,
-			obj_desc->field.access_byte_width, obj_desc->bank_field.region_obj,
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Bank Field: Bit_off=%X Off=%X Gran=%X Region %p Bank_reg %p\n",
+			obj_desc->bank_field.start_field_bit_offset,
+			obj_desc->bank_field.base_byte_offset,
+			obj_desc->field.access_byte_width,
+			obj_desc->bank_field.region_obj,
 			obj_desc->bank_field.bank_obj));
 		break;
 
@@ -370,8 +389,8 @@
 
 		obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node);
 		obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node);
-		obj_desc->index_field.value  = (u32) (info->field_bit_position /
-				  ACPI_MUL_8 (obj_desc->field.access_byte_width));
+		obj_desc->index_field.value  = (u32)
+			(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));
 
 		if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n"));
@@ -383,9 +402,12 @@
 		acpi_ut_add_reference (obj_desc->index_field.data_obj);
 		acpi_ut_add_reference (obj_desc->index_field.index_obj);
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n",
-			obj_desc->index_field.start_field_bit_offset, obj_desc->index_field.base_byte_offset,
-			obj_desc->field.access_byte_width, obj_desc->index_field.index_obj,
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n",
+			obj_desc->index_field.start_field_bit_offset,
+			obj_desc->index_field.base_byte_offset,
+			obj_desc->field.access_byte_width,
+			obj_desc->index_field.index_obj,
 			obj_desc->index_field.data_obj));
 		break;
 	}
@@ -397,7 +419,7 @@
 	status = acpi_ns_attach_object (info->field_node, obj_desc,
 			  acpi_ns_get_type (info->field_node));
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "set Named_obj %p (%4.4s) val = %p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set Named_obj %p (%4.4s) val = %p\n",
 			info->field_node, (char *) &(info->field_node->name), obj_desc));
 
 	/* Remove local reference to the object */
diff -Nru a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
--- a/drivers/acpi/executer/exregion.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/executer/exregion.c	Sun Apr 14 12:16:56 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exregion - ACPI default Op_region (address space) handlers
- *              $Revision: 72 $
+ *              $Revision: 74 $
  *
  *****************************************************************************/
 
@@ -69,7 +69,6 @@
 	acpi_mem_space_context  *mem_info = region_context;
 	u32                     length;
 	u32                     window_size;
-	u32                     remaining;
 
 
 	ACPI_FUNCTION_TRACE ("Ex_system_memory_space_handler");
@@ -123,12 +122,9 @@
 		 * Don't attempt to map memory beyond the end of the region, and
 		 * constrain the maximum mapping size to something reasonable.
 		 */
-		remaining = (u32) ((mem_info->address + (ACPI_PHYSICAL_ADDRESS) mem_info->length) - address);
-		if (remaining > SYSMEM_REGION_WINDOW_SIZE) {
+		window_size = (u32) ((mem_info->address + mem_info->length) - address);
+		if (window_size > SYSMEM_REGION_WINDOW_SIZE) {
 			window_size = SYSMEM_REGION_WINDOW_SIZE;
-		}
-		else {
-			window_size = remaining;
 		}
 
 		/* Create a new mapping starting at the address given */
diff -Nru a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
--- a/drivers/acpi/executer/exresnte.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/executer/exresnte.c	Sun Apr 14 12:16:56 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exresnte - AML Interpreter object resolution
- *              $Revision: 50 $
+ *              $Revision: 52 $
  *
  *****************************************************************************/
 
@@ -122,10 +122,13 @@
 			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 		}
 
-		/* Return an additional reference to the object */
+		status = acpi_ds_get_package_arguments (source_desc);
+		if (ACPI_SUCCESS (status)) {
+			/* Return an additional reference to the object */
 
-		obj_desc = source_desc;
-		acpi_ut_add_reference (obj_desc);
+			obj_desc = source_desc;
+			acpi_ut_add_reference (obj_desc);
+		}
 		break;
 
 
@@ -137,10 +140,13 @@
 			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 		}
 
-		/* Return an additional reference to the object */
+		status = acpi_ds_get_buffer_arguments (source_desc);
+		if (ACPI_SUCCESS (status)) {
+			/* Return an additional reference to the object */
 
-		obj_desc = source_desc;
-		acpi_ut_add_reference (obj_desc);
+			obj_desc = source_desc;
+			acpi_ut_add_reference (obj_desc);
+		}
 		break;
 
 
@@ -182,7 +188,7 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Field_read Node=%p Source_desc=%p Type=%X\n",
 			node, source_desc, entry_type));
 
-		status = acpi_ex_read_data_from_field (source_desc, &obj_desc);
+		status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc);
 		break;
 
 	/*
diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
--- a/drivers/acpi/executer/exresolv.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/executer/exresolv.c	Sun Apr 14 12:16:57 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exresolv - AML Interpreter object resolution
- *              $Revision: 106 $
+ *              $Revision: 109 $
  *
  *****************************************************************************/
 
@@ -94,7 +94,7 @@
 		}
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Resolved object %p\n", *stack_ptr));
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
 	return_ACPI_STATUS (AE_OK);
 }
 
@@ -177,7 +177,7 @@
 			acpi_ut_remove_reference (stack_desc);
 			*stack_ptr = obj_desc;
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[Arg/Local %d] Value_obj is %p\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %d] Value_obj is %p\n",
 				stack_desc->reference.offset, obj_desc));
 			break;
 
@@ -290,6 +290,19 @@
 
 		break; /* case INTERNAL_TYPE_REFERENCE */
 
+
+	case ACPI_TYPE_BUFFER:
+
+		status = acpi_ds_get_buffer_arguments (stack_desc);
+		break;
+
+
+	case ACPI_TYPE_PACKAGE:
+
+		status = acpi_ds_get_package_arguments (stack_desc);
+		break;
+
+
 	/*
 	 * These cases may never happen here, but just in case..
 	 */
@@ -301,7 +314,7 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Field_read Source_desc=%p Type=%X\n",
 			stack_desc, stack_desc->common.type));
 
-		status = acpi_ex_read_data_from_field (stack_desc, &obj_desc);
+		status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc);
 		*stack_ptr = (void *) obj_desc;
 		break;
 
diff -Nru a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
--- a/drivers/acpi/executer/exresop.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/executer/exresop.c	Sun Apr 14 12:16:57 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exresop - AML Interpreter operand/object resolution
- *              $Revision: 47 $
+ *              $Revision: 48 $
  *
  *****************************************************************************/
 
@@ -69,7 +69,7 @@
 	}
 
 	if (type_needed != this_type) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Needed [%s], found [%s] %p\n",
 			acpi_ut_get_type_name (type_needed),
 			acpi_ut_get_type_name (this_type), object));
@@ -135,8 +135,8 @@
 		return_ACPI_STATUS (AE_AML_INTERNAL);
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X Operand_types=%X \n",
-		opcode, arg_types));
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] Operand_types=%X \n",
+		opcode, op_info->name, arg_types));
 
 	/*
 	 * Normal exit is with (Arg_types == 0) at end of argument list.
@@ -203,7 +203,7 @@
 				case AML_LOCAL_OP:
 				case AML_REVISION_OP:
 
-					ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+					ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 						"Reference Opcode: %s\n", op_info->name)));
 					break;
 
diff -Nru a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
--- a/drivers/acpi/executer/exstore.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/executer/exstore.c	Sun Apr 14 12:16:58 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exstore - AML Interpreter object store support
- *              $Revision: 162 $
+ *              $Revision: 163 $
  *
  *****************************************************************************/
 
@@ -150,7 +150,7 @@
 		 * Storing to the Debug object causes the value stored to be
 		 * displayed and otherwise has no effect -- see ACPI Specification
 		 */
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Write to Debug Object: ****:\n\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Write to Debug Object: ****:\n\n"));
 
 		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ",
 				  acpi_ut_get_type_name (source_desc->common.type)));
@@ -191,7 +191,7 @@
 			break;
 		}
 
-		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "\n"));
+		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
 		break;
 
 
@@ -404,7 +404,7 @@
 	target_type = acpi_ns_get_type (node);
 	target_desc = acpi_ns_get_attached_object (node);
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Storing %p(%s) into node %p(%s)\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
 		source_desc, acpi_ut_get_type_name (source_desc->common.type),
 			  node, acpi_ut_get_type_name (target_type)));
 
@@ -456,7 +456,7 @@
 			 */
 			status = acpi_ns_attach_object (node, new_desc, target_type);
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 				"Store %s into %s via Convert/Attach\n",
 				acpi_ut_get_type_name (source_desc->common.type),
 				acpi_ut_get_type_name (new_desc->common.type)));
@@ -466,7 +466,7 @@
 
 	default:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 			"Storing %s (%p) directly into node (%p), no implicit conversion\n",
 			acpi_ut_get_type_name (source_desc->common.type), source_desc, node));
 
diff -Nru a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
--- a/drivers/acpi/executer/exstoren.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/executer/exstoren.c	Sun Apr 14 12:16:55 2002
@@ -3,7 +3,7 @@
  *
  * Module Name: exstoren - AML Interpreter object store support,
  *                        Store to Node (namespace object)
- *              $Revision: 46 $
+ *              $Revision: 47 $
  *
  *****************************************************************************/
 
@@ -145,7 +145,7 @@
  * FUNCTION:    Acpi_ex_store_object_to_object
  *
  * PARAMETERS:  Source_desc         - Object to store
- *              Dest_desc           - Object to recieve a copy of the source
+ *              Dest_desc           - Object to receive a copy of the source
  *              New_desc            - New object if Dest_desc is obsoleted
  *              Walk_state          - Current walk state
  *
diff -Nru a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
--- a/drivers/acpi/executer/exstorob.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/executer/exstorob.c	Sun Apr 14 12:16:58 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: exstorob - AML Interpreter object store support, store to object
- *              $Revision: 41 $
+ *              $Revision: 42 $
  *
  *****************************************************************************/
 
@@ -103,6 +103,10 @@
 			"Truncating src buffer from %X to %X\n",
 			length, target_desc->buffer.length));
 	}
+
+	/* Copy flags */
+
+	target_desc->buffer.flags = source_desc->buffer.flags;
 
 	return (AE_OK);
 }
diff -Nru a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
--- a/drivers/acpi/hardware/hwgpe.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/acpi/hardware/hwgpe.c	Sun Apr 14 12:16:54 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
- *              $Revision: 39 $
+ *              $Revision: 40 $
  *
  *****************************************************************************/
 
@@ -89,10 +89,10 @@
 	 * Read the current value of the register, set the appropriate bit
 	 * to enable the GPE, and write out the new register.
 	 */
-	in_byte = 0;
-	acpi_os_read_port (acpi_gbl_gpe_register_info[register_index].enable_addr, &in_byte, 8);
-	acpi_os_write_port (acpi_gbl_gpe_register_info[register_index].enable_addr,
-			  (in_byte | bit_mask), 8);
+	in_byte = acpi_hw_low_level_read (8,
+			 &acpi_gbl_gpe_register_info[register_index].enable_address, 0);
+	acpi_hw_low_level_write (8, (in_byte | bit_mask),
+			 &acpi_gbl_gpe_register_info[register_index].enable_address, 0);
 }
 
 
@@ -171,10 +171,10 @@
 	 * Read the current value of the register, clear the appropriate bit,
 	 * and write out the new register value to disable the GPE.
 	 */
-	in_byte = 0;
-	acpi_os_read_port (acpi_gbl_gpe_register_info[register_index].enable_addr, &in_byte, 8);
-	acpi_os_write_port (acpi_gbl_gpe_register_info[register_index].enable_addr,
-			 (in_byte & ~bit_mask), 8);
+	in_byte = acpi_hw_low_level_read (8,
+			 &acpi_gbl_gpe_register_info[register_index].enable_address, 0);
+	acpi_hw_low_level_write (8, (in_byte & ~bit_mask),
+			 &acpi_gbl_gpe_register_info[register_index].enable_address, 0);
 
 	acpi_hw_disable_gpe_for_wakeup(gpe_number);
 }
@@ -254,7 +254,8 @@
 	 * Write a one to the appropriate bit in the status register to
 	 * clear this GPE.
 	 */
-	acpi_os_write_port (acpi_gbl_gpe_register_info[register_index].status_addr, bit_mask, 8);
+	acpi_hw_low_level_write (8, bit_mask,
+			   &acpi_gbl_gpe_register_info[register_index].status_address, 0);
 }
 
 
@@ -301,8 +302,7 @@
 
 	/* GPE Enabled? */
 
-	in_byte = 0;
-	acpi_os_read_port (gpe_register_info->enable_addr, &in_byte, 8);
+	in_byte = acpi_hw_low_level_read (8, &gpe_register_info->enable_address, 0);
 	if (bit_mask & in_byte) {
 		(*event_status) |= ACPI_EVENT_FLAG_ENABLED;
 	}
@@ -315,8 +315,7 @@
 
 	/* GPE active (set)? */
 
-	in_byte = 0;
-	acpi_os_read_port (gpe_register_info->status_addr, &in_byte, 8);
+	in_byte = acpi_hw_low_level_read (8, &gpe_register_info->status_address, 0);
 	if (bit_mask & in_byte) {
 		(*event_status) |= ACPI_EVENT_FLAG_SET;
 	}
@@ -357,14 +356,14 @@
 		 * Read the enabled status of all GPEs. We
 		 * will be using it to restore all the GPEs later.
 		 */
-		acpi_os_read_port (gpe_register_info->enable_addr,
-				  &gpe_register_info->enable, 8);
+		gpe_register_info->enable = (u8) acpi_hw_low_level_read (8,
+				 &gpe_register_info->enable_address, 0);
 
 		/*
 		 * Disable all GPEs except wakeup GPEs.
 		 */
-		acpi_os_write_port(gpe_register_info->enable_addr,
-				  gpe_register_info->wake_enable, 8);
+		acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
+				&gpe_register_info->enable_address, 0);
 	}
 }
 
@@ -399,7 +398,7 @@
 		 * We previously stored the enabled status of all GPEs.
 		 * Blast them back in.
 		 */
-		acpi_os_write_port(gpe_register_info->enable_addr,
-				  gpe_register_info->enable, 8);
+		acpi_hw_low_level_write (8, gpe_register_info->enable, &
+				gpe_register_info->enable_address, 0);
 	}
 }
diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
--- a/drivers/acpi/hardware/hwregs.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/hardware/hwregs.c	Sun Apr 14 12:16:57 2002
@@ -3,7 +3,7 @@
  *
  * Module Name: hwregs - Read/write access functions for the various ACPI
  *                       control and status registers.
- *              $Revision: 120 $
+ *              $Revision: 121 $
  *
  ******************************************************************************/
 
@@ -73,18 +73,16 @@
 	/* Clear the fixed events */
 
 	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) {
-		acpi_os_write_port ((ACPI_IO_ADDRESS)
-			ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address),
-			ACPI_BITMASK_ALL_FIXED_STATUS, 16);
+		acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS,
+				&acpi_gbl_FADT->Xpm1b_evt_blk, 0);
 	}
 
 	/* Clear the GPE Bits */
 
 	for (gpe_block = 0; gpe_block < ACPI_MAX_GPE_BLOCKS; gpe_block++) {
 		for (i = 0; i < acpi_gbl_gpe_block_info[gpe_block].register_count; i++) {
-			acpi_os_write_port ((ACPI_IO_ADDRESS)
-				(acpi_gbl_gpe_block_info[gpe_block].block_address + i),
-				0xFF, 8);
+			acpi_hw_low_level_write (8, 0xFF,
+				acpi_gbl_gpe_block_info[gpe_block].block_address, i);
 		}
 	}
 
diff -Nru a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
--- a/drivers/acpi/hardware/hwsleep.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/hardware/hwsleep.c	Sun Apr 14 12:16:55 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
- *              $Revision: 35 $
+ *              $Revision: 37 $
  *
  *****************************************************************************/
 
@@ -237,6 +237,7 @@
 	PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;
 
 	/* Write #2: SLP_TYP + SLP_EN */
+	ACPI_FLUSH_CPU_CACHE();
 
 	acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1A_CONTROL, PM1Acontrol);
 	acpi_hw_register_write (ACPI_MTX_LOCK, ACPI_REGISTER_PM1B_CONTROL, PM1Bcontrol);
diff -Nru a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
--- a/drivers/acpi/hardware/hwtimer.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/hardware/hwtimer.c	Sun Apr 14 12:16:55 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Name: hwtimer.c - ACPI Power Management Timer Interface
- *              $Revision: 19 $
+ *              $Revision: 20 $
  *
  *****************************************************************************/
 
@@ -88,8 +88,7 @@
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	acpi_os_read_port ((ACPI_IO_ADDRESS)
-		ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address), ticks, 32);
+	*ticks = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0);
 
 	return_ACPI_STATUS (AE_OK);
 }
diff -Nru a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h
--- a/drivers/acpi/include/acconfig.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/include/acconfig.h	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acconfig.h - Global configuration constants
- *       $Revision: 94 $
+ *       $Revision: 96 $
  *
  *****************************************************************************/
 
@@ -54,7 +54,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION             0x20020308
+#define ACPI_CA_VERSION             0x20020403
 
 /* Version of ACPI supported */
 
diff -Nru a/drivers/acpi/include/acdebug.h b/drivers/acpi/include/acdebug.h
--- a/drivers/acpi/include/acdebug.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/include/acdebug.h	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acdebug.h - ACPI/AML debugger
- *       $Revision: 57 $
+ *       $Revision: 58 $
  *
  *****************************************************************************/
 
@@ -271,6 +271,9 @@
 acpi_db_load_acpi_table (
 	NATIVE_CHAR             *filename);
 
+acpi_status
+acpi_db_get_acpi_table (
+	NATIVE_CHAR             *filename);
 
 /*
  * dbhistry - debugger HISTORY command
diff -Nru a/drivers/acpi/include/acdispat.h b/drivers/acpi/include/acdispat.h
--- a/drivers/acpi/include/acdispat.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/include/acdispat.h	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acdispat.h - dispatcher (parser to interpreter interface)
- *       $Revision: 51 $
+ *       $Revision: 52 $
  *
  *****************************************************************************/
 
@@ -65,6 +65,14 @@
 acpi_ds_get_region_arguments (
 	acpi_operand_object     *rgn_desc);
 
+acpi_status
+acpi_ds_get_buffer_arguments (
+	acpi_operand_object     *obj_desc);
+
+acpi_status
+acpi_ds_get_package_arguments (
+	acpi_operand_object     *obj_desc);
+
 
 /* dsctrl - Parser/Interpreter interface, control stack routines */
 
@@ -267,9 +275,17 @@
 	acpi_namespace_node     *start_node);
 
 acpi_status
+acpi_ds_build_internal_buffer_obj (
+	acpi_walk_state         *walk_state,
+	acpi_parse_object       *op,
+	u32                     buffer_length,
+	acpi_operand_object     **obj_desc_ptr);
+
+acpi_status
 acpi_ds_build_internal_package_obj (
 	acpi_walk_state         *walk_state,
 	acpi_parse_object       *op,
+	u32                     package_length,
 	acpi_operand_object     **obj_desc);
 
 acpi_status
@@ -303,6 +319,12 @@
 acpi_ds_eval_region_operands (
 	acpi_walk_state         *walk_state,
 	acpi_parse_object       *op);
+
+acpi_status
+acpi_ds_eval_data_object_operands (
+	acpi_walk_state         *walk_state,
+	acpi_parse_object       *op,
+	acpi_operand_object     *obj_desc);
 
 acpi_status
 acpi_ds_initialize_region (
diff -Nru a/drivers/acpi/include/acevents.h b/drivers/acpi/include/acevents.h
--- a/drivers/acpi/include/acevents.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/include/acevents.h	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acevents.h - Event subcomponent prototypes and defines
- *       $Revision: 75 $
+ *       $Revision: 76 $
  *
  *****************************************************************************/
 
@@ -56,6 +56,10 @@
 /*
  * Evmisc
  */
+
+u8
+acpi_ev_is_notify_object (
+	acpi_namespace_node     *node);
 
 acpi_status
 acpi_ev_acquire_global_lock(
diff -Nru a/drivers/acpi/include/acexcep.h b/drivers/acpi/include/acexcep.h
--- a/drivers/acpi/include/acexcep.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/include/acexcep.h	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acexcep.h - Exception codes returned by the ACPI subsystem
- *       $Revision: 57 $
+ *       $Revision: 59 $
  *
  *****************************************************************************/
 
@@ -74,8 +74,9 @@
 #define AE_ALREADY_ACQUIRED             (acpi_status) (0x0018 | AE_CODE_ENVIRONMENTAL)
 #define AE_NO_HARDWARE_RESPONSE         (acpi_status) (0x0019 | AE_CODE_ENVIRONMENTAL)
 #define AE_NO_GLOBAL_LOCK               (acpi_status) (0x001A | AE_CODE_ENVIRONMENTAL)
+#define AE_LOGICAL_ADDRESS              (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
 
-#define AE_CODE_ENV_MAX                 0x001A
+#define AE_CODE_ENV_MAX                 0x001B
 
 /*
  * Programmer exceptions
@@ -86,8 +87,11 @@
 #define AE_BAD_DATA                     (acpi_status) (0x0004 | AE_CODE_PROGRAMMER)
 #define AE_BAD_ADDRESS                  (acpi_status) (0x0005 | AE_CODE_PROGRAMMER)
 #define AE_ALIGNMENT                    (acpi_status) (0x0006 | AE_CODE_PROGRAMMER)
+#define AE_BAD_HEX_CONSTANT             (acpi_status) (0x0007 | AE_CODE_PROGRAMMER)
+#define AE_BAD_OCTAL_CONSTANT           (acpi_status) (0x0008 | AE_CODE_PROGRAMMER)
+#define AE_BAD_DECIMAL_CONSTANT         (acpi_status) (0x0009 | AE_CODE_PROGRAMMER)
 
-#define AE_CODE_PGM_MAX                 0x0006
+#define AE_CODE_PGM_MAX                 0x0009
 
 
 /*
@@ -188,7 +192,8 @@
 	"AE_NOT_ACQUIRED",
 	"AE_ALREADY_ACQUIRED",
 	"AE_NO_HARDWARE_RESPONSE",
-	"AE_NO_GLOBAL_LOCK"
+	"AE_NO_GLOBAL_LOCK",
+	"AE_LOGICAL_ADDRESS"
 };
 
 NATIVE_CHAR const   *acpi_gbl_exception_names_pgm[] =
@@ -198,7 +203,10 @@
 	"AE_BAD_PATHNAME",
 	"AE_BAD_DATA",
 	"AE_BAD_ADDRESS",
-	"AE_ALIGNMENT"
+	"AE_ALIGNMENT",
+	"AE_BAD_HEX_CONSTANT",
+	"AE_BAD_OCTAL_CONSTANT",
+	"AE_BAD_DECIMAL_CONSTANT"
 };
 
 NATIVE_CHAR const   *acpi_gbl_exception_names_tbl[] =
diff -Nru a/drivers/acpi/include/acglobal.h b/drivers/acpi/include/acglobal.h
--- a/drivers/acpi/include/acglobal.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/acpi/include/acglobal.h	Sun Apr 14 12:16:54 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acglobal.h - Declarations for global variables
- *       $Revision: 120 $
+ *       $Revision: 121 $
  *
  *****************************************************************************/
 
@@ -71,6 +71,7 @@
  * of each in the system.  Each global points to the actual table.
  *
  */
+ACPI_EXTERN u32                         acpi_gbl_table_flags;
 ACPI_EXTERN RSDP_DESCRIPTOR            *acpi_gbl_RSDP;
 ACPI_EXTERN xsdt_descriptor            *acpi_gbl_XSDT;
 ACPI_EXTERN FADT_DESCRIPTOR            *acpi_gbl_FADT;
diff -Nru a/drivers/acpi/include/acinterp.h b/drivers/acpi/include/acinterp.h
--- a/drivers/acpi/include/acinterp.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/include/acinterp.h	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acinterp.h - Interpreter subcomponent prototypes and defines
- *       $Revision: 132 $
+ *       $Revision: 133 $
  *
  *****************************************************************************/
 
@@ -147,6 +147,7 @@
 
 acpi_status
 acpi_ex_read_data_from_field (
+	acpi_walk_state         *walk_state,
 	acpi_operand_object     *obj_desc,
 	acpi_operand_object     **ret_buffer_desc);
 
diff -Nru a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h
--- a/drivers/acpi/include/aclocal.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/include/aclocal.h	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: aclocal.h - Internal data types used across the ACPI subsystem
- *       $Revision: 159 $
+ *       $Revision: 162 $
  *
  *****************************************************************************/
 
@@ -182,12 +182,18 @@
  * be the first byte in this structure.
  */
 
+typedef union acpi_name_union
+{
+	u32                     integer;
+	char                    ascii[4];
+} ACPI_NAME_UNION;
+
 typedef struct acpi_node
 {
 	u8                      descriptor;     /* Used to differentiate object descriptor types */
 	u8                      type;           /* Type associated with this name */
 	u16                     owner_id;
-	u32                     name;           /* ACPI Name, always 4 chars per ACPI spec */
+	ACPI_NAME_UNION         name;           /* ACPI Name, always 4 chars per ACPI spec */
 
 
 	union acpi_operand_obj  *object;        /* Pointer to attached ACPI object (optional) */
@@ -314,8 +320,9 @@
 
 typedef struct
 {
+	u8                      address_space_id;
+	acpi_generic_address    *block_address;
 	u16                     register_count;
-	u16                     block_address;
 	u8                      block_base_number;
 
 } ACPI_GPE_BLOCK_INFO;
@@ -324,8 +331,8 @@
 
 typedef struct
 {
-	u16                     status_addr;    /* Address of status reg */
-	u16                     enable_addr;    /* Address of enable reg */
+	acpi_generic_address    status_address; /* Address of status reg */
+	acpi_generic_address    enable_address; /* Address of enable reg */
 	u8                      status;         /* Current value of status reg */
 	u8                      enable;         /* Current value of enable reg */
 	u8                      wake_enable;    /* Mask of bits to keep enabled when sleeping */
@@ -410,11 +417,11 @@
 
 #define ACPI_STATE_COMMON                  /* Two 32-bit fields and a pointer */\
 	u8                      data_type;          /* To differentiate various internal objs */\
-	u8                      flags; \
-	u16                     value; \
-	u16                     state; \
-	u16                     acpi_eval; \
-	void                    *next; \
+	u8                      flags;      \
+	u16                     value;      \
+	u16                     state;      \
+	u16                     reserved;   \
+	void                    *next;      \
 
 typedef struct acpi_common_state
 {
diff -Nru a/drivers/acpi/include/acobject.h b/drivers/acpi/include/acobject.h
--- a/drivers/acpi/include/acobject.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/include/acobject.h	Sun Apr 14 12:16:55 2002
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Name: acobject.h - Definition of acpi_operand_object  (Internal object only)
- *       $Revision: 106 $
+ *       $Revision: 110 $
  *
  *****************************************************************************/
 
@@ -32,23 +32,14 @@
  * The acpi_operand_object  is used to pass AML operands from the dispatcher
  * to the interpreter, and to keep track of the various handlers such as
  * address space handlers and notify handlers.  The object is a constant
- * size in order to allow them to be cached and reused.
- *
- * All variants of the acpi_operand_object  are defined with the same
- * sequence of field types, with fields that are not used in a particular
- * variant being named "Reserved".  This is not strictly necessary, but
- * may in some circumstances simplify understanding if these structures
- * need to be displayed in a debugger having limited (or no) support for
- * union types.  It also simplifies some debug code in Dump_table() which
- * dumps multi-level values: fetching Buffer.Pointer suffices to pick up
- * the value or next level for any of several types.
+ * size in order to allow it to be cached and reused.
  */
 
-/******************************************************************************
+/*******************************************************************************
  *
  * Common Descriptors
  *
- *****************************************************************************/
+ ******************************************************************************/
 
 /*
  * Common area for all objects.
@@ -56,8 +47,6 @@
  * Data_type is used to differentiate between internal descriptors, and MUST
  * be the first byte in this structure.
  */
-
-
 #define ACPI_OBJECT_COMMON_HEADER           /* SIZE/ALIGNMENT: 32 bits, one ptr plus trailing 8-bit flag */\
 	u8                          descriptor;         /* To differentiate various internal objs */\
 	u8                          type;               /* acpi_object_type */\
@@ -65,7 +54,7 @@
 	union acpi_operand_obj      *next_object;       /* Objects linked to parent NS node */\
 	u8                          flags; \
 
-/* Defines for flag byte above */
+/* Values for flag byte above */
 
 #define AOPOBJ_RESERVED             0x01
 #define AOPOBJ_STATIC_POINTER       0x02
@@ -101,29 +90,29 @@
 	u32                         length;
 
 
+/*
+ * Common fields for objects that support ASL notifications
+ */
+#define ACPI_COMMON_NOTIFY_INFO \
+	union acpi_operand_obj      *sys_handler;        /* Handler for system notifies */\
+	union acpi_operand_obj      *drv_handler;        /* Handler for driver notifies */\
+	union acpi_operand_obj      *addr_handler;       /* Handler for Address space */
+
+
 /******************************************************************************
  *
- * Individual Object Descriptors
+ * Basic data types
  *
  *****************************************************************************/
 
-
-typedef struct /* COMMON */
+typedef struct acpi_object_common
 {
 	ACPI_OBJECT_COMMON_HEADER
 
 } ACPI_OBJECT_COMMON;
 
 
-typedef struct /* CACHE_LIST */
-{
-	ACPI_OBJECT_COMMON_HEADER
-	union acpi_operand_obj      *next;              /* Link for object cache and internal lists*/
-
-} ACPI_OBJECT_CACHE_LIST;
-
-
-typedef struct /* NUMBER - has value */
+typedef struct acpi_object_integer
 {
 	ACPI_OBJECT_COMMON_HEADER
 
@@ -132,48 +121,47 @@
 } ACPI_OBJECT_INTEGER;
 
 
-typedef struct /* STRING - has length and pointer - Null terminated, ASCII characters only */
+typedef struct acpi_object_string                   /* Null terminated, ASCII characters only */
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_BUFFER_INFO
-	NATIVE_CHAR                 *pointer;           /* String value in AML stream or in allocated space */
+	NATIVE_CHAR                 *pointer;           /* String in AML stream or allocated string */
 
 } ACPI_OBJECT_STRING;
 
 
-typedef struct /* BUFFER - has length and pointer - not null terminated */
+typedef struct acpi_object_buffer
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_BUFFER_INFO
-	u8                          *pointer;           /* Buffer value in AML stream or in allocated space */
+	u8                          *pointer;           /* Buffer in AML stream or allocated buffer */
 	acpi_namespace_node         *node;              /* Link back to parent node */
+	u8                          *aml_start;
+	u32                         aml_length;
 
 } ACPI_OBJECT_BUFFER;
 
 
-typedef struct /* PACKAGE - has count, elements, next element */
+typedef struct acpi_object_package
 {
 	ACPI_OBJECT_COMMON_HEADER
 
 	u32                         count;              /* # of elements in package */
+	u32                         aml_length;
+	u8                          *aml_start;
+	acpi_namespace_node         *node;              /* Link back to parent node */
 	union acpi_operand_obj      **elements;         /* Array of pointers to Acpi_objects */
-	union acpi_operand_obj      **next_element;     /* used only while initializing */
 
 } ACPI_OBJECT_PACKAGE;
 
 
-typedef struct /* DEVICE - has handle and notification handler/context */
-{
-	ACPI_OBJECT_COMMON_HEADER
-
-	union acpi_operand_obj      *sys_handler;        /* Handler for system notifies */
-	union acpi_operand_obj      *drv_handler;        /* Handler for driver notifies */
-	union acpi_operand_obj      *addr_handler;       /* Handler for Address space */
-
-} ACPI_OBJECT_DEVICE;
-
+/******************************************************************************
+ *
+ * Complex data types
+ *
+ *****************************************************************************/
 
-typedef struct /* EVENT */
+typedef struct acpi_object_event
 {
 	ACPI_OBJECT_COMMON_HEADER
 	void                        *semaphore;
@@ -183,7 +171,7 @@
 
 #define INFINITE_CONCURRENCY        0xFF
 
-typedef struct /* METHOD */
+typedef struct acpi_object_method
 {
 	ACPI_OBJECT_COMMON_HEADER
 	u8                          method_flags;
@@ -201,7 +189,7 @@
 } ACPI_OBJECT_METHOD;
 
 
-typedef struct acpi_obj_mutex /* MUTEX */
+typedef struct acpi_object_mutex
 {
 	ACPI_OBJECT_COMMON_HEADER
 	u16                         sync_level;
@@ -215,65 +203,82 @@
 } ACPI_OBJECT_MUTEX;
 
 
-typedef struct /* REGION */
+typedef struct acpi_object_region
 {
 	ACPI_OBJECT_COMMON_HEADER
 
 	u8                          space_id;
-	u32                         length;
-	ACPI_PHYSICAL_ADDRESS       address;
 
 	union acpi_operand_obj      *addr_handler;      /* Handler for system notifies */
 	acpi_namespace_node         *node;              /* containing object */
 	union acpi_operand_obj      *next;
+	u32                         length;
+	ACPI_PHYSICAL_ADDRESS       address;
 
 } ACPI_OBJECT_REGION;
 
 
-typedef struct /* POWER RESOURCE - has Handle and notification handler/context*/
+/******************************************************************************
+ *
+ * Objects that can be notified.  All share a common Notify_info area.
+ *
+ *****************************************************************************/
+
+typedef struct acpi_object_notify_common            /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
+{
+	ACPI_OBJECT_COMMON_HEADER
+	ACPI_COMMON_NOTIFY_INFO
+
+} ACPI_OBJECT_NOTIFY_COMMON;
+
+
+typedef struct acpi_object_device
+{
+	ACPI_OBJECT_COMMON_HEADER
+	ACPI_COMMON_NOTIFY_INFO
+
+} ACPI_OBJECT_DEVICE;
+
+
+typedef struct acpi_object_power_resource
 {
 	ACPI_OBJECT_COMMON_HEADER
+	ACPI_COMMON_NOTIFY_INFO
 
 	u32                         system_level;
 	u32                         resource_order;
 
-	union acpi_operand_obj      *sys_handler;       /* Handler for system notifies */
-	union acpi_operand_obj      *drv_handler;       /* Handler for driver notifies */
-
 } ACPI_OBJECT_POWER_RESOURCE;
 
 
-typedef struct /* PROCESSOR - has Handle and notification handler/context*/
+typedef struct acpi_object_processor
 {
 	ACPI_OBJECT_COMMON_HEADER
+	ACPI_COMMON_NOTIFY_INFO
 
 	u32                         proc_id;
 	u32                         length;
 	ACPI_IO_ADDRESS             address;
 
-	union acpi_operand_obj      *sys_handler;       /* Handler for system notifies */
-	union acpi_operand_obj      *drv_handler;       /* Handler for driver notifies */
-	union acpi_operand_obj      *addr_handler;      /* Handler for Address space */
-
 } ACPI_OBJECT_PROCESSOR;
 
 
-typedef struct /* THERMAL ZONE - has Handle and Handler/Context */
+typedef struct acpi_object_thermal_zone
 {
 	ACPI_OBJECT_COMMON_HEADER
+	ACPI_COMMON_NOTIFY_INFO
 
-	union acpi_operand_obj      *sys_handler;       /* Handler for system notifies */
-	union acpi_operand_obj      *drv_handler;       /* Handler for driver notifies */
-	union acpi_operand_obj      *addr_handler;      /* Handler for Address space */
 
 } ACPI_OBJECT_THERMAL_ZONE;
 
 
-/*
+/******************************************************************************
+ *
  * Fields.  All share a common header/info field.
- */
+ *
+ *****************************************************************************/
 
-typedef struct /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
+typedef struct acpi_object_field_common             /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_FIELD_INFO
@@ -282,7 +287,7 @@
 } ACPI_OBJECT_FIELD_COMMON;
 
 
-typedef struct /* REGION FIELD */
+typedef struct acpi_object_region_field
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_FIELD_INFO
@@ -291,7 +296,7 @@
 } ACPI_OBJECT_REGION_FIELD;
 
 
-typedef struct /* BANK FIELD */
+typedef struct acpi_object_bank_field
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_FIELD_INFO
@@ -302,7 +307,7 @@
 } ACPI_OBJECT_BANK_FIELD;
 
 
-typedef struct /* INDEX FIELD */
+typedef struct acpi_object_index_field
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_FIELD_INFO
@@ -320,7 +325,7 @@
 
 /* The Buffer_field is different in that it is part of a Buffer, not an Op_region */
 
-typedef struct /* BUFFER FIELD */
+typedef struct acpi_object_buffer_field
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_COMMON_FIELD_INFO
@@ -330,11 +335,13 @@
 } ACPI_OBJECT_BUFFER_FIELD;
 
 
-/*
- * Handlers
- */
+/******************************************************************************
+ *
+ * Objects for handlers
+ *
+ *****************************************************************************/
 
-typedef struct /* NOTIFY HANDLER */
+typedef struct acpi_object_notify_handler
 {
 	ACPI_OBJECT_COMMON_HEADER
 
@@ -350,7 +357,7 @@
 #define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED  0x1
 
 
-typedef struct /* ADDRESS HANDLER */
+typedef struct acpi_object_addr_handler
 {
 	ACPI_OBJECT_COMMON_HEADER
 
@@ -367,12 +374,17 @@
 } ACPI_OBJECT_ADDR_HANDLER;
 
 
+/******************************************************************************
+ *
+ * Special internal objects
+ *
+ *****************************************************************************/
+
 /*
  * The Reference object type is used for these opcodes:
  * Arg[0-6], Local[0-7], Index_op, Name_op, Zero_op, One_op, Ones_op, Debug_op
  */
-
-typedef struct /* Reference - Local object type */
+typedef struct acpi_object_reference
 {
 	ACPI_OBJECT_COMMON_HEADER
 
@@ -394,8 +406,7 @@
  *
  * Currently: Region and Field_unit types
  */
-
-typedef struct /* EXTRA */
+typedef struct acpi_object_extra
 {
 	ACPI_OBJECT_COMMON_HEADER
 	u8                          byte_fill1;
@@ -408,7 +419,9 @@
 } ACPI_OBJECT_EXTRA;
 
 
-typedef struct /* DATA */
+/* Additional data that can be attached to namespace nodes */
+
+typedef struct acpi_object_data
 {
 	ACPI_OBJECT_COMMON_HEADER
 	ACPI_OBJECT_HANDLER         handler;
@@ -417,38 +430,55 @@
 } ACPI_OBJECT_DATA;
 
 
+/* Structure used when objects are cached for reuse */
+
+typedef struct acpi_object_cache_list
+{
+	ACPI_OBJECT_COMMON_HEADER
+	union acpi_operand_obj      *next;              /* Link for object cache and internal lists*/
+
+} ACPI_OBJECT_CACHE_LIST;
+
+
 /******************************************************************************
  *
- * acpi_operand_object  Descriptor - a giant union of all of the above
+ * acpi_operand_object Descriptor - a giant union of all of the above
  *
  *****************************************************************************/
 
 typedef union acpi_operand_obj
 {
 	ACPI_OBJECT_COMMON          common;
-	ACPI_OBJECT_CACHE_LIST      cache;
+
 	ACPI_OBJECT_INTEGER         integer;
 	ACPI_OBJECT_STRING          string;
 	ACPI_OBJECT_BUFFER          buffer;
 	ACPI_OBJECT_PACKAGE         package;
-	ACPI_OBJECT_BUFFER_FIELD    buffer_field;
-	ACPI_OBJECT_DEVICE          device;
+
 	ACPI_OBJECT_EVENT           event;
 	ACPI_OBJECT_METHOD          method;
 	ACPI_OBJECT_MUTEX           mutex;
 	ACPI_OBJECT_REGION          region;
+
+	ACPI_OBJECT_NOTIFY_COMMON   common_notify;
+	ACPI_OBJECT_DEVICE          device;
 	ACPI_OBJECT_POWER_RESOURCE  power_resource;
 	ACPI_OBJECT_PROCESSOR       processor;
 	ACPI_OBJECT_THERMAL_ZONE    thermal_zone;
+
 	ACPI_OBJECT_FIELD_COMMON    common_field;
 	ACPI_OBJECT_REGION_FIELD    field;
+	ACPI_OBJECT_BUFFER_FIELD    buffer_field;
 	ACPI_OBJECT_BANK_FIELD      bank_field;
 	ACPI_OBJECT_INDEX_FIELD     index_field;
-	ACPI_OBJECT_REFERENCE       reference;
+
 	ACPI_OBJECT_NOTIFY_HANDLER  notify_handler;
 	ACPI_OBJECT_ADDR_HANDLER    addr_handler;
+
+	ACPI_OBJECT_REFERENCE       reference;
 	ACPI_OBJECT_EXTRA           extra;
 	ACPI_OBJECT_DATA            data;
+	ACPI_OBJECT_CACHE_LIST      cache;
 
 } acpi_operand_object;
 
diff -Nru a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h
--- a/drivers/acpi/include/acpiosxf.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/acpi/include/acpiosxf.h	Sun Apr 14 12:16:54 2002
@@ -83,10 +83,20 @@
 acpi_os_terminate (
 	void);
 
+
+/*
+ * ACPI Table interfaces
+ */
+
 acpi_status
 acpi_os_get_root_pointer (
 	u32                     flags,
-	ACPI_PHYSICAL_ADDRESS   *rsdp_physical_address);
+	ACPI_POINTER            *address);
+
+acpi_status
+acpi_os_table_override (
+	acpi_table_header       *existing_table,
+	acpi_table_header       **new_table);
 
 
 /*
diff -Nru a/drivers/acpi/include/acpixf.h b/drivers/acpi/include/acpixf.h
--- a/drivers/acpi/include/acpixf.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/acpi/include/acpixf.h	Sun Apr 14 12:16:54 2002
@@ -96,7 +96,7 @@
 acpi_status
 acpi_find_root_pointer (
 	u32                     flags,
-	ACPI_PHYSICAL_ADDRESS   *rsdp_physical_address);
+	ACPI_POINTER            *rsdp_address);
 
 acpi_status
 acpi_load_tables (
diff -Nru a/drivers/acpi/include/acstruct.h b/drivers/acpi/include/acstruct.h
--- a/drivers/acpi/include/acstruct.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/include/acstruct.h	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acstruct.h - Internal structs
- *       $Revision: 16 $
+ *       $Revision: 17 $
  *
  *****************************************************************************/
 
@@ -104,8 +104,12 @@
 	u16                     method_count;
 	u16                     op_region_count;
 	u16                     field_count;
+	u16                     buffer_count;
+	u16                     package_count;
 	u16                     op_region_init;
 	u16                     field_init;
+	u16                     buffer_init;
+	u16                     package_init;
 	u16                     object_count;
 	acpi_table_desc         *table_desc;
 
diff -Nru a/drivers/acpi/include/actables.h b/drivers/acpi/include/actables.h
--- a/drivers/acpi/include/actables.h	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/include/actables.h	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: actables.h - ACPI table management
- *       $Revision: 35 $
+ *       $Revision: 36 $
  *
  *****************************************************************************/
 
@@ -71,22 +71,16 @@
 
 acpi_status
 acpi_tb_get_table (
-	ACPI_PHYSICAL_ADDRESS   physical_address,
-	acpi_table_header       *buffer_ptr,
+	ACPI_POINTER            *address,
 	acpi_table_desc         *table_info);
 
 acpi_status
 acpi_tb_verify_rsdp (
-	ACPI_PHYSICAL_ADDRESS   RSDP_physical_address);
+	ACPI_POINTER            *address);
 
-acpi_status
-acpi_tb_get_table_facs (
-	acpi_table_header       *buffer_ptr,
-	acpi_table_desc         *table_info);
-
-ACPI_PHYSICAL_ADDRESS
+void
 acpi_tb_get_rsdt_address (
-	void);
+	ACPI_POINTER            *out_address);
 
 acpi_status
 acpi_tb_validate_rsdt (
@@ -94,7 +88,7 @@
 
 acpi_status
 acpi_tb_get_table_pointer (
-	ACPI_PHYSICAL_ADDRESS   physical_address,
+	ACPI_POINTER            *address,
 	u32                     flags,
 	u32                     *size,
 	acpi_table_header       **table_ptr);
diff -Nru a/drivers/acpi/include/actypes.h b/drivers/acpi/include/actypes.h
--- a/drivers/acpi/include/actypes.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/include/actypes.h	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: actypes.h - Common data types for the entire ACPI subsystem
- *       $Revision: 224 $
+ *       $Revision: 227 $
  *
  *****************************************************************************/
 
@@ -57,12 +57,13 @@
 typedef unsigned short                  UINT16;
 typedef int                             INT32;
 typedef unsigned int                    UINT32;
+typedef COMPILER_DEPENDENT_INT64        INT64;
 typedef COMPILER_DEPENDENT_UINT64       UINT64;
 
 typedef UINT64                          NATIVE_UINT;
 typedef UINT64                          NATIVE_INT;
 
-typedef NATIVE_UINT                     ACPI_TBLPTR;
+typedef UINT64                          ACPI_TBLPTR;
 typedef UINT64                          ACPI_IO_ADDRESS;
 typedef UINT64                          ACPI_PHYSICAL_ADDRESS;
 typedef UINT64                          ACPI_SIZE;
@@ -119,12 +120,13 @@
 typedef unsigned short                  UINT16;
 typedef int                             INT32;
 typedef unsigned int                    UINT32;
+typedef COMPILER_DEPENDENT_INT64        INT64;
 typedef COMPILER_DEPENDENT_UINT64       UINT64;
 
 typedef UINT32                          NATIVE_UINT;
 typedef INT32                           NATIVE_INT;
 
-typedef NATIVE_UINT                     ACPI_TBLPTR;
+typedef UINT64                          ACPI_TBLPTR;
 typedef UINT32                          ACPI_IO_ADDRESS;
 typedef UINT64                          ACPI_PHYSICAL_ADDRESS;
 typedef UINT32                          ACPI_SIZE;
@@ -148,7 +150,6 @@
 /*
  * Data type ranges
  */
-
 #define ACPI_UINT8_MAX                  (UINT8)  0xFF
 #define ACPI_UINT16_MAX                 (UINT16) 0xFFFF
 #define ACPI_UINT32_MAX                 (UINT32) 0xFFFFFFFF
@@ -168,6 +169,31 @@
 typedef UINT64                          u64;
 #endif
 /*! [End] no source code translation !*/
+
+
+/*
+ * Pointer overlays to avoid lots of typecasting for
+ * code that accepts both physical and logical pointers.
+ */
+typedef union acpi_pointers
+{
+	ACPI_PHYSICAL_ADDRESS       physical;
+	void                        *logical;
+	ACPI_TBLPTR                 value;
+
+} ACPI_POINTERS;
+
+typedef struct acpi_pointer
+{
+	u32                         pointer_type;
+	ACPI_POINTERS               pointer;
+
+} ACPI_POINTER;
+
+/* Pointer_types for above */
+
+#define ACPI_LOGICAL_POINTER            0x01
+#define ACPI_PHYSICAL_POINTER           0x02
 
 
 /*
diff -Nru a/drivers/acpi/include/amlcode.h b/drivers/acpi/include/amlcode.h
--- a/drivers/acpi/include/amlcode.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/include/amlcode.h	Sun Apr 14 12:16:59 2002
@@ -3,7 +3,7 @@
  * Name: amlcode.h - Definitions for AML, as included in "definition blocks"
  *                   Declarations and definitions contained herein are derived
  *                   directly from the ACPI specification.
- *       $Revision: 66 $
+ *       $Revision: 67 $
  *
  *****************************************************************************/
 
@@ -185,6 +185,7 @@
 #define AML_INT_STATICSTRING_OP     (u16) 0x0034
 #define AML_INT_METHODCALL_OP       (u16) 0x0035
 #define AML_INT_RETURN_VALUE_OP     (u16) 0x0036
+#define AML_INT_EVAL_SUBTREE_OP     (u16) 0x0037
 
 
 #define ARG_NONE                    0x0
@@ -335,15 +336,16 @@
 /* Misc */
 
 #define AML_TYPE_CREATE_FIELD       0x11
-#define AML_TYPE_CONTROL            0x12
-#define AML_TYPE_NAMED_NO_OBJ       0x13
-#define AML_TYPE_NAMED_FIELD        0x14
-#define AML_TYPE_NAMED_SIMPLE       0x15
-#define AML_TYPE_NAMED_COMPLEX      0x16
-#define AML_TYPE_RETURN             0x17
+#define AML_TYPE_CREATE_OBJECT      0x12
+#define AML_TYPE_CONTROL            0x13
+#define AML_TYPE_NAMED_NO_OBJ       0x14
+#define AML_TYPE_NAMED_FIELD        0x15
+#define AML_TYPE_NAMED_SIMPLE       0x16
+#define AML_TYPE_NAMED_COMPLEX      0x17
+#define AML_TYPE_RETURN             0x18
 
-#define AML_TYPE_UNDEFINED          0x18
-#define AML_TYPE_BOGUS              0x19
+#define AML_TYPE_UNDEFINED          0x19
+#define AML_TYPE_BOGUS              0x1A
 
 
 /*
diff -Nru a/drivers/acpi/include/platform/acenv.h b/drivers/acpi/include/platform/acenv.h
--- a/drivers/acpi/include/platform/acenv.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/include/platform/acenv.h	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acenv.h - Generation environment specific items
- *       $Revision: 85 $
+ *       $Revision: 86 $
  *
  *****************************************************************************/
 
@@ -284,11 +284,9 @@
 #define ACPI_INTERNAL_VAR_XFACE
 
 #define ACPI_ASM_MACROS
-#define causeinterrupt(level)
 #define BREAKPOINT3
-#define acpi_disable_irqs()
-#define acpi_enable_irqs()
-#define halt()
+#define ACPI_DISABLE_IRQS()
+#define ACPI_ENABLE_IRQS()
 #define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq)
 #define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq)
 
@@ -299,9 +297,7 @@
 
 /* Don't want software interrupts within a ring3 application */
 
-#undef causeinterrupt
 #undef BREAKPOINT3
-#define causeinterrupt(level)
 #define BREAKPOINT3
 #endif
 
diff -Nru a/drivers/acpi/include/platform/acgcc.h b/drivers/acpi/include/platform/acgcc.h
--- a/drivers/acpi/include/platform/acgcc.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/include/platform/acgcc.h	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acgcc.h - GCC specific defines, etc.
- *       $Revision: 19 $
+ *       $Revision: 22 $
  *
  *****************************************************************************/
 
@@ -30,7 +30,8 @@
 #ifdef __ia64__
 #define _IA64
 
-#define COMPILER_DEPENDENT_UINT64   unsigned long
+#define COMPILER_DEPENDENT_INT64   long
+#define COMPILER_DEPENDENT_UINT64  unsigned long
 
 /*
  * Calling conventions:
@@ -52,10 +53,9 @@
 /* Asm macros */
 
 #define ACPI_ASM_MACROS
-#define causeinterrupt(level)
 #define BREAKPOINT3
-#define acpi_disable_irqs() __cli()
-#define acpi_enable_irqs()  __sti()
+#define ACPI_DISABLE_IRQS() __cli()
+#define ACPI_ENABLE_IRQS()  __sti()
 
 /*! [Begin] no source code translation */
 
@@ -111,7 +111,8 @@
 
 #else /* DO IA32 */
 
-#define COMPILER_DEPENDENT_UINT64   unsigned long long
+#define COMPILER_DEPENDENT_INT64   long long
+#define COMPILER_DEPENDENT_UINT64  unsigned long long
 
 /*
  * Calling conventions:
@@ -129,11 +130,9 @@
 /* Asm macros */
 
 #define ACPI_ASM_MACROS
-#define causeinterrupt(level)
 #define BREAKPOINT3
-#define acpi_disable_irqs() __cli()
-#define acpi_enable_irqs()  __sti()
-#define halt()    __asm__ __volatile__ ("sti; hlt":::"memory")
+#define ACPI_DISABLE_IRQS() __cli()
+#define ACPI_ENABLE_IRQS()  __sti()
 
 /*! [Begin] no source code translation
  *
diff -Nru a/drivers/acpi/include/platform/aclinux.h b/drivers/acpi/include/platform/aclinux.h
--- a/drivers/acpi/include/platform/aclinux.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/include/platform/aclinux.h	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: aclinux.h - OS specific defines, etc.
- *       $Revision: 15 $
+ *       $Revision: 19 $
  *
  *****************************************************************************/
 
@@ -42,14 +42,20 @@
 
 #define strtoul simple_strtoul
 
+#ifdef _IA64
+#define ACPI_FLUSH_CPU_CACHE()
 #else
+#define ACPI_FLUSH_CPU_CACHE()	wbinvd()
+#endif
+
+#else /* !__KERNEL__ */
 
 #include <stdarg.h>
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 
-#endif
+#endif /* __KERNEL__ */
 
 /* Linux uses GCC */
 
diff -Nru a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
--- a/drivers/acpi/namespace/nsaccess.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/namespace/nsaccess.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
- *              $Revision: 152 $
+ *              $Revision: 153 $
  *
  ******************************************************************************/
 
@@ -522,8 +522,9 @@
 				return_ACPI_STATUS (status);
 			}
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-				"Setting global scope to %p\n", this_node));
+			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
+				"Setting current scope to [%4.4s] (%p)\n",
+				this_node->name.ascii, this_node));
 		}
 	}
 
diff -Nru a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
--- a/drivers/acpi/namespace/nsalloc.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/namespace/nsalloc.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: nsalloc - Namespace allocation and deletion utilities
- *              $Revision: 70 $
+ *              $Revision: 72 $
  *
  ******************************************************************************/
 
@@ -62,7 +62,7 @@
 
 	ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++);
 
-	node->name           = name;
+	node->name.integer   = name;
 	node->reference_count = 1;
 	ACPI_SET_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED);
 
@@ -206,7 +206,7 @@
 		 * We will fill in the actual type when the
 		 * real definition is found later.
 		 */
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[%4.4s] is a forward reference\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] is a forward reference\n",
 			(char *) &node->name));
 	}
 
@@ -302,7 +302,7 @@
 
 		ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object %p, Remaining %X\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
 			child_node, acpi_gbl_current_node_count));
 
 		/*
diff -Nru a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
--- a/drivers/acpi/namespace/nsdump.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/namespace/nsdump.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: nsdump - table dumping routines for debug
- *              $Revision: 127 $
+ *              $Revision: 129 $
  *
  *****************************************************************************/
 
@@ -53,7 +53,7 @@
 	u32                     num_segments,
 	char                    *pathname)
 {
-	ACPI_FUNCTION_NAME ("Acpi_ns_print_pathname");
+	ACPI_FUNCTION_NAME ("Ns_print_pathname");
 
 
 	if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
@@ -228,7 +228,7 @@
 		type = INTERNAL_TYPE_DEF_ANY;  /* prints as *ERROR* */
 	}
 
-	if (!acpi_ut_valid_acpi_name (this_node->name)) {
+	if (!acpi_ut_valid_acpi_name (this_node->name.integer)) {
 		ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", this_node->name));
 	}
 
@@ -255,59 +255,87 @@
 
 		switch (type) {
 		case ACPI_TYPE_PROCESSOR:
+
 			acpi_os_printf (" ID %d Addr %.4X Len %.4X\n",
 					 obj_desc->processor.proc_id,
 					 obj_desc->processor.address,
 					 obj_desc->processor.length);
 			break;
 
+
 		case ACPI_TYPE_DEVICE:
+
 			acpi_os_printf (" Notification object: %p", obj_desc);
 			break;
 
+
 		case ACPI_TYPE_METHOD:
+
 			acpi_os_printf (" Args %d Len %.4X Aml %p \n",
 					 obj_desc->method.param_count,
 					 obj_desc->method.aml_length,
 					 obj_desc->method.aml_start);
 			break;
 
+
 		case ACPI_TYPE_INTEGER:
+
 			acpi_os_printf (" = %8.8X%8.8X\n",
 					 ACPI_HIDWORD (obj_desc->integer.value),
 					 ACPI_LODWORD (obj_desc->integer.value));
 			break;
 
+
 		case ACPI_TYPE_PACKAGE:
-			acpi_os_printf (" Elements %.2X\n",
-					 obj_desc->package.count);
+
+			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+				acpi_os_printf (" Elements %.2X\n",
+						 obj_desc->package.count);
+			}
+			else {
+				acpi_os_printf (" [Length not yet evaluated]\n");
+			}
 			break;
 
-		case ACPI_TYPE_BUFFER:
-			acpi_os_printf (" Len %.2X",
-					 obj_desc->buffer.length);
 
-			/* Dump some of the buffer */
+		case ACPI_TYPE_BUFFER:
 
-			if (obj_desc->buffer.length > 0) {
-				acpi_os_printf (" =");
-				for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) {
-					acpi_os_printf (" %.2X", obj_desc->buffer.pointer[i]);
+			if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+				acpi_os_printf (" Len %.2X",
+						 obj_desc->buffer.length);
+
+				/* Dump some of the buffer */
+
+				if (obj_desc->buffer.length > 0) {
+					acpi_os_printf (" =");
+					for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) {
+						acpi_os_printf (" %.2X", obj_desc->buffer.pointer[i]);
+					}
 				}
+				acpi_os_printf ("\n");
+			}
+			else {
+				acpi_os_printf (" [Length not yet evaluated]\n");
 			}
-			acpi_os_printf ("\n");
 			break;
 
+
 		case ACPI_TYPE_STRING:
+
 			acpi_os_printf (" Len %.2X", obj_desc->string.length);
 
 			if (obj_desc->string.length > 0) {
-				 acpi_os_printf (" = \"%.32s\"...", obj_desc->string.pointer);
+				acpi_os_printf (" = \"%.32s\"", obj_desc->string.pointer);
+				if (obj_desc->string.length > 32) {
+					acpi_os_printf ("...");
+				}
 			}
 			acpi_os_printf ("\n");
 			break;
 
+
 		case ACPI_TYPE_REGION:
+
 			acpi_os_printf (" [%s]", acpi_ut_get_region_name (obj_desc->region.space_id));
 			if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
 				acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n",
@@ -316,16 +344,20 @@
 						 obj_desc->region.length);
 			}
 			else {
-				acpi_os_printf (" [Address/Length not evaluated]\n");
+				acpi_os_printf (" [Address/Length not yet evaluated]\n");
 			}
 			break;
 
+
 		case INTERNAL_TYPE_REFERENCE:
+
 			acpi_os_printf (" [%s]\n",
 					acpi_ps_get_opcode_name (obj_desc->reference.opcode));
 			break;
 
+
 		case ACPI_TYPE_BUFFER_FIELD:
+
 			if (obj_desc->buffer_field.buffer_obj &&
 				obj_desc->buffer_field.buffer_obj->buffer.node) {
 				acpi_os_printf (" Buf [%4.4s]",
@@ -333,24 +365,32 @@
 			}
 			break;
 
+
 		case INTERNAL_TYPE_REGION_FIELD:
+
 			acpi_os_printf (" Rgn [%4.4s]",
 					(char *) &obj_desc->common_field.region_obj->region.node->name);
 			break;
 
+
 		case INTERNAL_TYPE_BANK_FIELD:
+
 			acpi_os_printf (" Rgn [%4.4s] Bnk [%4.4s]",
 					(char *) &obj_desc->common_field.region_obj->region.node->name,
 					(char *) &obj_desc->bank_field.bank_obj->common_field.node->name);
 			break;
 
+
 		case INTERNAL_TYPE_INDEX_FIELD:
+
 			acpi_os_printf (" Idx [%4.4s] Dat [%4.4s]",
 					(char *) &obj_desc->index_field.index_obj->common_field.node->name,
 					(char *) &obj_desc->index_field.data_obj->common_field.node->name);
 			break;
 
+
 		default:
+
 			acpi_os_printf (" Object %p\n", obj_desc);
 			break;
 		}
diff -Nru a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
--- a/drivers/acpi/namespace/nseval.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/namespace/nseval.c	Sun Apr 14 12:16:58 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nseval - Object evaluation interfaces -- includes control
  *                       method lookup and execution.
- *              $Revision: 109 $
+ *              $Revision: 112 $
  *
  ******************************************************************************/
 
@@ -113,7 +113,7 @@
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object [%s] not found [%s]\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
 			pathname, acpi_format_exception (status)));
 		goto cleanup;
 	}
@@ -122,12 +122,12 @@
 	 * Now that we have a handle to the object, we can attempt
 	 * to evaluate it.
 	 */
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s [%p] Value %p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
 		pathname, node, acpi_ns_get_attached_object (node)));
 
 	status = acpi_ns_evaluate_by_handle (node, params, return_object);
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "*** Completed eval of object %s ***\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
 		pathname));
 
 cleanup:
@@ -192,7 +192,7 @@
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object at [%s] was not found, status=%.4X\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object at [%s] was not found, status=%.4X\n",
 			pathname, status));
 		goto cleanup;
 	}
@@ -201,12 +201,12 @@
 	 * Now that we have a handle to the object, we can attempt
 	 * to evaluate it.
 	 */
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s [%p] Value %p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
 		pathname, node, acpi_ns_get_attached_object (node)));
 
 	status = acpi_ns_evaluate_by_handle (node, params, return_object);
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "*** Completed eval of object %s ***\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
 		pathname));
 
 
@@ -390,16 +390,11 @@
 		return_ACPI_STATUS (AE_NULL_OBJECT);
 	}
 
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Control method at Offset %p Length %x]\n",
-		obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
-
 	ACPI_DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing",
-		ACPI_LV_NAMES, _COMPONENT);
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "At offset %p\n",
-			obj_desc->method.aml_start + 1));
+		ACPI_LV_INFO, _COMPONENT);
 
+	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %x\n",
+		obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
 
 	/*
 	 * Unlock the namespace before execution.  This allows namespace access
@@ -497,7 +492,7 @@
 		if (ACPI_SUCCESS (status)) {
 			status = AE_CTRL_RETURN_VALUE;
 			*return_obj_desc = obj_desc;
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Returning obj %p\n", *return_obj_desc));
+			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning obj %p\n", *return_obj_desc));
 		}
 	}
 
diff -Nru a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
--- a/drivers/acpi/namespace/nsinit.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/namespace/nsinit.c	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: nsinit - namespace initialization
- *              $Revision: 41 $
+ *              $Revision: 43 $
  *
  *****************************************************************************/
 
@@ -59,15 +59,11 @@
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 		"**** Starting initialization of namespace objects ****\n"));
-	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Completing Region and Field initialization:"));
+	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Completing Region/Field/Buffer/Package initialization:"));
 
+	/* Set all init info to zero */
 
-	info.field_count = 0;
-	info.field_init = 0;
-	info.op_region_count = 0;
-	info.op_region_init = 0;
-	info.object_count = 0;
-
+	ACPI_MEMSET (&info, 0, sizeof (acpi_init_walk_info));
 
 	/* Walk entire namespace from the supplied root */
 
@@ -79,9 +75,11 @@
 	}
 
 	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
-		"\n%d/%d Regions, %d/%d Fields initialized (%d nodes total)\n",
-		info.op_region_init, info.op_region_count, info.field_init,
-		info.field_count, info.object_count));
+		"\n Initialized %d/%d Regions %d/%d Fields %d/%d Buffers %d/%d Packages (%d nodes)\n",
+		info.op_region_init, info.op_region_count,
+		info.field_init,    info.field_count,
+		info.buffer_init,   info.buffer_count,
+		info.package_init,  info.package_count, info.object_count));
 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 		"%d Control Methods found\n", info.method_count));
 	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
@@ -118,12 +116,15 @@
 	ACPI_FUNCTION_TRACE ("Ns_initialize_devices");
 
 
+	/* Init counters */
+
 	info.device_count = 0;
 	info.num_STA = 0;
 	info.num_INI = 0;
 
+	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Executing all Device _STA and_INI methods:"));
 
-	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Executing device _INI methods:"));
+	/* Walk namespace for all objects of type Device */
 
 	status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
 			  ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL);
@@ -132,9 +133,8 @@
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status));
 	}
 
-
 	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
-		"\n%d Devices found: %d _STA, %d _INI\n",
+		"\n%d Devices found containing: %d _STA, %d _INI methods\n",
 		info.device_count, info.num_STA, info.num_INI));
 
 	return_ACPI_STATUS (status);
@@ -180,7 +180,6 @@
 
 	info->object_count++;
 
-
 	/* And even then, we are only interested in a few object types */
 
 	type = acpi_ns_get_type (obj_handle);
@@ -189,11 +188,37 @@
 		return (AE_OK);
 	}
 
-	if ((type != ACPI_TYPE_REGION) &&
-		(type != ACPI_TYPE_BUFFER_FIELD)) {
+	/* Increment counters for object types we are looking for */
+
+	switch (type) {
+	case ACPI_TYPE_REGION:
+		info->op_region_count++;
+		break;
+
+	case ACPI_TYPE_BUFFER_FIELD:
+		info->field_count++;
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		info->buffer_count++;
+		break;
+
+	case ACPI_TYPE_PACKAGE:
+		info->package_count++;
+		break;
+
+	default:
+
+		/* No init required, just exit now */
 		return (AE_OK);
 	}
 
+	/*
+	 * If the object is already initialized, nothing else to do
+	 */
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return (AE_OK);
+	}
 
 	/*
 	 * Must lock the interpreter before executing AML code
@@ -203,61 +228,53 @@
 		return (status);
 	}
 
+	/*
+	 * Each of these types can contain executable AML code within
+	 * the declaration.
+	 */
 	switch (type) {
-
 	case ACPI_TYPE_REGION:
 
-		info->op_region_count++;
-		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
-			break;
-		}
-
 		info->op_region_init++;
 		status = acpi_ds_get_region_arguments (obj_desc);
-		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-					"%s while getting region arguments [%4.4s]\n",
-					acpi_format_exception (status), (char *) &node->name));
-		}
-
-		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
-		}
-
 		break;
 
 
 	case ACPI_TYPE_BUFFER_FIELD:
 
-		info->field_count++;
-		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
-			break;
-		}
-
 		info->field_init++;
 		status = acpi_ds_get_buffer_field_arguments (obj_desc);
-		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-					"%s while getting buffer field arguments [%4.4s]\n",
-					acpi_format_exception (status), (char *) &node->name));
-		}
-		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
-			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
-		}
+		break;
 
 
+	case ACPI_TYPE_BUFFER:
+
+		info->buffer_init++;
+		status = acpi_ds_get_buffer_arguments (obj_desc);
 		break;
 
-	default:
+
+	case ACPI_TYPE_PACKAGE:
+
+		info->package_init++;
+		status = acpi_ds_get_package_arguments (obj_desc);
 		break;
 	}
 
+	if (ACPI_FAILURE (status)) {
+		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+				"Could not execute arguments for [%4.4s] (%s), %s\n",
+				(char *) &node->name, acpi_ut_get_type_name (type), acpi_format_exception (status)));
+	}
+
+	if (!(acpi_dbg_level & ACPI_LV_INIT)) {
+		ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
+	}
 
 	/*
 	 * We ignore errors from above, and always return OK, since
-	 * we don't want to abort the walk on a single error.
+	 * we don't want to abort the walk on any single error.
 	 */
 	acpi_ex_exit_interpreter ();
 	return (AE_OK);
@@ -334,7 +351,6 @@
 
 		return_ACPI_STATUS(AE_CTRL_DEPTH);
 	}
-
 
 	/*
 	 * The device is present. Run _INI.
diff -Nru a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
--- a/drivers/acpi/namespace/nsobject.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/acpi/namespace/nsobject.c	Sun Apr 14 12:16:57 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nsobject - Utilities for objects attached to namespace
  *                         table entries
- *              $Revision: 78 $
+ *              $Revision: 80 $
  *
  ******************************************************************************/
 
@@ -221,7 +221,7 @@
 
 	node->type = ACPI_TYPE_ANY;
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Node %p [%4.4s] Object %p\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
 		node, (char *) &node->name, obj_desc));
 
 	/* Remove one reference on the object (and all subobjects) */
@@ -280,7 +280,7 @@
 acpi_ns_get_secondary_object (
 	acpi_operand_object     *obj_desc)
 {
-	ACPI_FUNCTION_TRACE_PTR ("Acpi_ns_get_secondary_object", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR ("Ns_get_secondary_object", obj_desc);
 
 
 	if ((!obj_desc)                                  ||
diff -Nru a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
--- a/drivers/acpi/namespace/nssearch.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/namespace/nssearch.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: nssearch - Namespace search
- *              $Revision: 83 $
+ *              $Revision: 84 $
  *
  ******************************************************************************/
 
@@ -95,7 +95,7 @@
 	while (next_node) {
 		/* Check for match against the name */
 
-		if (next_node->name == target_name) {
+		if (next_node->name.integer == target_name) {
 			/*
 			 * Found matching entry.  Capture the type if appropriate, before
 			 * returning the entry.
@@ -146,8 +146,8 @@
 
 	/* Searched entire table, not found */
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name %4.4s (type %X) not found at %p\n",
-		(char *) &target_name, type, next_node));
+	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name %4.4s Type [%s] not found at %p\n",
+		(char *) &target_name, acpi_ut_get_type_name (type), next_node));
 
 	return_ACPI_STATUS (AE_NOT_FOUND);
 }
@@ -206,8 +206,8 @@
 		}
 
 		if (acpi_ns_local (type)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] type %X is local(no search)\n",
-				(char *) &target_name, type));
+			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
+				(char *) &target_name, acpi_ut_get_type_name (type)));
 		}
 
 		return_ACPI_STATUS (AE_NOT_FOUND);
diff -Nru a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
--- a/drivers/acpi/namespace/nsutils.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/namespace/nsutils.c	Sun Apr 14 12:16:58 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
  *                        parents and siblings and Scope manipulation
- *              $Revision: 104 $
+ *              $Revision: 105 $
  *
  *****************************************************************************/
 
@@ -254,7 +254,6 @@
 			result = &internal_name[3];
 		}
 	}
-
 	else {
 		/*
 		 * Not fully qualified.
@@ -281,7 +280,6 @@
 		}
 	}
 
-
 	/* Build the name (minus path separators) */
 
 	for (; num_segments; num_segments--) {
@@ -319,11 +317,11 @@
 
 	if (info->fully_qualified) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "returning [%p] (abs) \"\\%s\"\n",
-			internal_name, &internal_name[0]));
+			internal_name, internal_name));
 	}
 	else {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "returning [%p] (rel) \"%s\"\n",
-			internal_name, &internal_name[2]));
+			internal_name, internal_name));
 	}
 
 	return_ACPI_STATUS (AE_OK);
@@ -823,8 +821,8 @@
 				child_node, (char *) &child_node->name,
 				parent_node, (char *) &parent_node->name));
 
-			if (parent_node->name) {
-				return_VALUE (parent_node->name);
+			if (parent_node->name.integer) {
+				return_VALUE (parent_node->name.integer);
 			}
 		}
 
@@ -863,7 +861,7 @@
 		return (FALSE);
 	}
 
-	if (node->name) {
+	if (node->name.integer) {
 		return (TRUE);
 	}
 
diff -Nru a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
--- a/drivers/acpi/namespace/nsxfname.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/namespace/nsxfname.c	Sun Apr 14 12:16:56 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: nsxfname - Public interfaces to the ACPI subsystem
  *                         ACPI Namespace oriented interfaces
- *              $Revision: 89 $
+ *              $Revision: 90 $
  *
  *****************************************************************************/
 
@@ -243,8 +243,8 @@
 		return (AE_BAD_PARAMETER);
 	}
 
-	info->type      = node->type;
-	info->name      = node->name;
+	info->type = node->type;
+	info->name = node->name.integer;
 
 	status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE (status)) {
diff -Nru a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
--- a/drivers/acpi/parser/psopcode.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/parser/psopcode.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: psopcode - Parser/Interpreter opcode information table
- *              $Revision: 64 $
+ *              $Revision: 66 $
  *
  *****************************************************************************/
 
@@ -219,7 +219,7 @@
 #define ARGI_BIT_XOR_OP                 ARGI_LIST3 (ARGI_INTEGER,    ARGI_INTEGER,       ARGI_TARGETREF)
 #define ARGI_BREAK_OP                   ARG_NONE
 #define ARGI_BREAK_POINT_OP             ARG_NONE
-#define ARGI_BUFFER_OP                  ARGI_INVALID_OPCODE
+#define ARGI_BUFFER_OP                  ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_BYTE_OP                    ARGI_INVALID_OPCODE
 #define ARGI_BYTELIST_OP                ARGI_INVALID_OPCODE
 #define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA,   ARGI_TARGETREF)
@@ -284,7 +284,7 @@
 #define ARGI_NOTIFY_OP                  ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
 #define ARGI_ONE_OP                     ARG_NONE
 #define ARGI_ONES_OP                    ARG_NONE
-#define ARGI_PACKAGE_OP                 ARGI_INVALID_OPCODE
+#define ARGI_PACKAGE_OP                 ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_POWER_RES_OP               ARGI_INVALID_OPCODE
 #define ARGI_PROCESSOR_OP               ARGI_INVALID_OPCODE
 #define ARGI_QWORD_OP                   ARGI_INVALID_OPCODE
@@ -315,7 +315,7 @@
 #define ARGI_TO_STRING_OP               ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_FIXED_TARGET)
 #define ARGI_TYPE_OP                    ARGI_LIST1 (ARGI_ANYTYPE)
 #define ARGI_UNLOAD_OP                  ARGI_LIST1 (ARGI_DDBHANDLE)
-#define ARGI_VAR_PACKAGE_OP             ARGI_INVALID_OPCODE
+#define ARGI_VAR_PACKAGE_OP             ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_WAIT_OP                    ARGI_LIST2 (ARGI_EVENT,      ARGI_INTEGER)
 #define ARGI_WHILE_OP                   ARGI_INVALID_OPCODE
 #define ARGI_WORD_OP                    ARGI_INVALID_OPCODE
@@ -422,6 +422,7 @@
 	AML_CREATE_DWORD_FIELD_OP
 	AML_CREATE_QWORD_FIELD_OP
 	AML_REGION_OP
+	AML_BUFFER_OP
 
   Field opcodes
 
@@ -461,8 +462,8 @@
 /* 06 */ ACPI_OP ("DwordConst",         ARGP_DWORD_OP,             ARGI_DWORD_OP,              ACPI_TYPE_INTEGER,       AML_CLASS_ARGUMENT,        AML_TYPE_LITERAL,         0),
 /* 07 */ ACPI_OP ("String",             ARGP_STRING_OP,            ARGI_STRING_OP,             ACPI_TYPE_STRING,        AML_CLASS_ARGUMENT,        AML_TYPE_LITERAL,         0),
 /* 08 */ ACPI_OP ("Scope",              ARGP_SCOPE_OP,             ARGI_SCOPE_OP,              INTERNAL_TYPE_SCOPE,     AML_CLASS_NAMED_OBJECT,    AML_TYPE_NAMED_NO_OBJ,    AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
-/* 09 */ ACPI_OP ("Buffer",             ARGP_BUFFER_OP,            ARGI_BUFFER_OP,             ACPI_TYPE_BUFFER,        AML_CLASS_ARGUMENT,        AML_TYPE_DATA_TERM,       AML_HAS_ARGS),
-/* 0A */ ACPI_OP ("Package",            ARGP_PACKAGE_OP,           ARGI_PACKAGE_OP,            ACPI_TYPE_PACKAGE,       AML_CLASS_ARGUMENT,        AML_TYPE_DATA_TERM,       AML_HAS_ARGS),
+/* 09 */ ACPI_OP ("Buffer",             ARGP_BUFFER_OP,            ARGI_BUFFER_OP,             ACPI_TYPE_BUFFER,        AML_CLASS_CREATE,          AML_TYPE_CREATE_OBJECT,   AML_HAS_ARGS | AML_DEFER),
+/* 0A */ ACPI_OP ("Package",            ARGP_PACKAGE_OP,           ARGI_PACKAGE_OP,            ACPI_TYPE_PACKAGE,       AML_CLASS_CREATE,          AML_TYPE_CREATE_OBJECT,   AML_HAS_ARGS | AML_DEFER),
 /* 0B */ ACPI_OP ("Method",             ARGP_METHOD_OP,            ARGI_METHOD_OP,             ACPI_TYPE_METHOD,        AML_CLASS_NAMED_OBJECT,    AML_TYPE_NAMED_COMPLEX,   AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 0C */ ACPI_OP ("Local0",             ARGP_LOCAL0,               ARGI_LOCAL0,                INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT,        AML_TYPE_LOCAL_VARIABLE,  0),
 /* 0D */ ACPI_OP ("Local1",             ARGP_LOCAL1,               ARGI_LOCAL1,                INTERNAL_TYPE_REFERENCE, AML_CLASS_ARGUMENT,        AML_TYPE_LOCAL_VARIABLE,  0),
@@ -573,7 +574,7 @@
 /* ACPI 2.0 opcodes */
 
 /* 6E */ ACPI_OP ("QwordConst",         ARGP_QWORD_OP,             ARGI_QWORD_OP,              ACPI_TYPE_INTEGER,       AML_CLASS_ARGUMENT,        AML_TYPE_LITERAL,         0),
-/* 6F */ ACPI_OP ("Package /*Var*/",    ARGP_VAR_PACKAGE_OP,       ARGI_VAR_PACKAGE_OP,        ACPI_TYPE_PACKAGE,       AML_CLASS_ARGUMENT,        AML_TYPE_DATA_TERM,       AML_HAS_ARGS | AML_DEFER),
+/* 6F */ ACPI_OP ("Package /*Var*/",    ARGP_VAR_PACKAGE_OP,       ARGI_VAR_PACKAGE_OP,        ACPI_TYPE_PACKAGE,       AML_CLASS_CREATE,          AML_TYPE_CREATE_OBJECT,   AML_HAS_ARGS | AML_DEFER),
 /* 70 */ ACPI_OP ("ConcatenateResTemplate", ARGP_CONCAT_RES_OP,    ARGI_CONCAT_RES_OP,         ACPI_TYPE_ANY,           AML_CLASS_EXECUTE,         AML_TYPE_EXEC_2A_1T_1R,   AML_FLAGS_EXEC_2A_1T_1R),
 /* 71 */ ACPI_OP ("Mod",                ARGP_MOD_OP,               ARGI_MOD_OP,                ACPI_TYPE_ANY,           AML_CLASS_EXECUTE,         AML_TYPE_EXEC_2A_1T_1R,   AML_FLAGS_EXEC_2A_1T_1R),
 /* 72 */ ACPI_OP ("CreateQWordField",   ARGP_CREATE_QWORD_FIELD_OP,ARGI_CREATE_QWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,  AML_CLASS_CREATE,          AML_TYPE_CREATE_FIELD,    AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
@@ -587,6 +588,7 @@
 /* 7A */ ACPI_OP ("Continue",           ARGP_CONTINUE_OP,          ARGI_CONTINUE_OP,           ACPI_TYPE_ANY,           AML_CLASS_CONTROL,         AML_TYPE_CONTROL,         0),
 /* 7B */ ACPI_OP ("LoadTable",          ARGP_LOAD_TABLE_OP,        ARGI_LOAD_TABLE_OP,         ACPI_TYPE_ANY,           AML_CLASS_EXECUTE,         AML_TYPE_EXEC_6A_0T_1R,   AML_FLAGS_EXEC_6A_0T_1R),
 /* 7C */ ACPI_OP ("DataTableRegion",    ARGP_DATA_REGION_OP,       ARGI_DATA_REGION_OP,        ACPI_TYPE_REGION,        AML_CLASS_NAMED_OBJECT,    AML_TYPE_NAMED_SIMPLE,    AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+/* 7D */ ACPI_OP ("[EvalSubTree]",      ARGP_SCOPE_OP,             ARGI_SCOPE_OP,              INTERNAL_TYPE_SCOPE,     AML_CLASS_NAMED_OBJECT,    AML_TYPE_NAMED_NO_OBJ,    AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE)
 
 /*! [End] no source code translation !*/
 };
@@ -606,7 +608,7 @@
 /* 0x18 */	_UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x20 */	_UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x28 */	_UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX,
-/* 0x30 */	0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, _UNK,
+/* 0x30 */	0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, 0x7D,
 /* 0x38 */	_UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0x40 */	_UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
 /* 0x48 */	_ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC,
diff -Nru a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
--- a/drivers/acpi/parser/psparse.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/parser/psparse.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: psparse - Parser top level AML parse routines
- *              $Revision: 119 $
+ *              $Revision: 121 $
  *
  *****************************************************************************/
 
@@ -220,7 +220,7 @@
 
 				/*
 				 * These opcodes contain Term_arg operands. The current
-				 * op must be replace by a placeholder return op
+				 * op must be replaced by a placeholder return op
 				 */
 				replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
 				if (!replacement_op) {
@@ -232,15 +232,35 @@
 
 				/*
 				 * These opcodes contain Term_arg operands. The current
-				 * op must be replace by a placeholder return op
+				 * op must be replaced by a placeholder return op
 				 */
-				if ((op->parent->opcode == AML_REGION_OP)               ||
-					(op->parent->opcode == AML_DATA_REGION_OP)) {
+				if ((op->parent->opcode == AML_REGION_OP)       ||
+					(op->parent->opcode == AML_DATA_REGION_OP)  ||
+					(op->parent->opcode == AML_BUFFER_OP)       ||
+					(op->parent->opcode == AML_PACKAGE_OP)      ||
+					(op->parent->opcode == AML_VAR_PACKAGE_OP)) {
 					replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
 					if (!replacement_op) {
 						return_VALUE (FALSE);
 					}
 				}
+
+				if ((op->parent->opcode == AML_NAME_OP) &&
+					(walk_state->descending_callback != acpi_ds_exec_begin_op)) {
+					if ((op->opcode == AML_BUFFER_OP) ||
+						(op->opcode == AML_PACKAGE_OP) ||
+						(op->opcode == AML_VAR_PACKAGE_OP)) {
+						replacement_op = acpi_ps_alloc_op (op->opcode);
+						if (!replacement_op) {
+							return_VALUE (FALSE);
+						}
+
+						((acpi_parse2_object *) replacement_op)->data =
+							((acpi_parse2_object *) op)->data;
+						((acpi_parse2_object *) replacement_op)->length =
+							((acpi_parse2_object *) op)->length;
+					}
+				}
 				break;
 
 			default:
@@ -259,6 +279,7 @@
 				if (replacement_op) {
 					replacement_op->parent   = op->parent;
 					replacement_op->value.arg = NULL;
+					replacement_op->node     = op->node;
 					op->parent->value.arg    = replacement_op;
 					replacement_op->next     = op->next;
 				}
@@ -275,10 +296,11 @@
 				next = prev->next;
 				if (next == op) {
 					if (replacement_op) {
-						replacement_op->parent = op->parent;
+						replacement_op->parent   = op->parent;
 						replacement_op->value.arg = NULL;
-						prev->next = replacement_op;
-						replacement_op->next = op->next;
+						replacement_op->node     = op->node;
+						prev->next               = replacement_op;
+						replacement_op->next     = op->next;
 						next = NULL;
 					}
 					else {
@@ -312,9 +334,10 @@
  *
  * PARAMETERS:  Parser_state        - Current parser state object
  *
- * RETURN:
+ * RETURN:      Status
  *
- * DESCRIPTION:
+ * DESCRIPTION: Update the parser state based upon the return exception from
+ *              the parser callback.
  *
  ******************************************************************************/
 
@@ -441,7 +464,7 @@
 	acpi_parse_object       *arg = NULL;
 	acpi_parse_object       pre_op;
 	acpi_parse_state        *parser_state;
-	u8                      *aml_op_start;
+	u8                      *aml_op_start = NULL;
 
 
 	ACPI_FUNCTION_TRACE_PTR ("Ps_parse_loop", walk_state);
@@ -465,7 +488,6 @@
 				(walk_state->control_state) &&
 				(walk_state->control_state->common.state ==
 					ACPI_CONTROL_PREDICATE_EXECUTING)) {
-
 				/*
 				 * A predicate was just completed, get the value of the
 				 * predicate and branch based on that value
@@ -491,7 +513,6 @@
 			acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, &walk_state->arg_count);
 			ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
 		}
-
 		else if (walk_state->prev_op) {
 			/* We were in the middle of an op */
 
@@ -535,8 +556,8 @@
 				/* The opcode is unrecognized.  Just skip unknown opcodes */
 
 				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-					"Found unknown opcode %X at AML offset %X, ignoring\n",
-					walk_state->opcode, walk_state->aml_offset));
+					"Found unknown opcode %X at AML address %p offset %X, ignoring\n",
+					walk_state->opcode, parser_state->aml, walk_state->aml_offset));
 
 				ACPI_DUMP_BUFFER (parser_state->aml, 128);
 
@@ -552,10 +573,8 @@
 				parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);
 				walk_state->arg_types = walk_state->op_info->parse_args;
 				break;
-
 			}
 
-
 			/* Create Op structure and append to parent's argument list */
 
 			if (walk_state->op_info->flags & AML_NAMED) {
@@ -570,7 +589,6 @@
 					INCREMENT_ARG_LIST (walk_state->arg_types);
 				}
 
-
 				/* We know that this arg is a name, move to next arg */
 
 				INCREMENT_ARG_LIST (walk_state->arg_types);
@@ -624,7 +642,6 @@
 					((acpi_parse2_object * ) op)->length  = 0;
 				}
 			}
-
 			else {
 				/* Not a named opcode, just allocate Op and append to parent */
 
@@ -680,7 +697,7 @@
 		walk_state->arg_count = 0;
 
 		if (walk_state->arg_types) /* Are there any arguments that must be processed? */ {
-			/* get arguments */
+			/* Get arguments */
 
 			switch (op->opcode) {
 			case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
@@ -689,7 +706,7 @@
 			case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
 			case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */
 
-				/* fill in constant or string argument directly */
+				/* Fill in constant or string argument directly */
 
 				acpi_ps_get_next_simple_arg (parser_state,
 						 GET_CURRENT_ARG_TYPE (walk_state->arg_types), op);
@@ -719,9 +736,11 @@
 					INCREMENT_ARG_LIST (walk_state->arg_types);
 				}
 
-				/* For a method, save the length and address of the body */
+				switch (op->opcode) {
+				case AML_METHOD_OP:
+
+					/* For a method, save the length and address of the body */
 
-				if (op->opcode == AML_METHOD_OP) {
 					/*
 					 * Skip parsing of control method or opregion body,
 					 * because we don't have enough info in the first pass
@@ -730,7 +749,6 @@
 					((acpi_parse2_object * ) op)->data   = parser_state->aml;
 					((acpi_parse2_object * ) op)->length = (u32) (parser_state->pkg_end -
 							  parser_state->aml);
-
 					/*
 					 * Skip body of method.  For Op_regions, we must continue
 					 * parsing because the opregion is not a standalone
@@ -738,17 +756,42 @@
 					 */
 					parser_state->aml   = parser_state->pkg_end;
 					walk_state->arg_count = 0;
-				}
-				else if (op->opcode == AML_WHILE_OP) {
+					break;
+
+				case AML_BUFFER_OP:
+				case AML_PACKAGE_OP:
+				case AML_VAR_PACKAGE_OP:
+
+					if ((op->parent) &&
+						(op->parent->opcode == AML_NAME_OP) &&
+						(walk_state->descending_callback != acpi_ds_exec_begin_op)) {
+						/*
+						 * Skip parsing of
+						 * because we don't have enough info in the first pass
+						 * to parse them correctly.
+						 */
+						((acpi_parse2_object * ) op)->data   = aml_op_start;
+						((acpi_parse2_object * ) op)->length = (u32) (parser_state->pkg_end -
+								  aml_op_start);
+						/*
+						 * Skip body
+						 */
+						parser_state->aml   = parser_state->pkg_end;
+						walk_state->arg_count = 0;
+					}
+					break;
+
+				case AML_WHILE_OP:
+
 					if (walk_state->control_state) {
 						walk_state->control_state->control.package_end = parser_state->pkg_end;
 					}
+					break;
 				}
 				break;
 			}
 		}
 
-
 		/* Check for arguments that need to be processed */
 
 		if (walk_state->arg_count) {
@@ -758,7 +801,6 @@
 			op = NULL;
 			continue;
 		}
-
 
 		/* All arguments have been processed -- Op is complete, prepare for next */
 
diff -Nru a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
--- a/drivers/acpi/parser/psutils.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/parser/psutils.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: psutils - Parser miscellaneous utilities (Parser only)
- *              $Revision: 49 $
+ *              $Revision: 50 $
  *
  *****************************************************************************/
 
@@ -97,30 +97,25 @@
 		size = sizeof (acpi_parse2_object);
 		flags = ACPI_PARSEOP_DEFERRED;
 	}
-
 	else if (op_info->flags & AML_NAMED) {
 		size = sizeof (acpi_parse2_object);
 		flags = ACPI_PARSEOP_NAMED;
 	}
-
 	else if (opcode == AML_INT_BYTELIST_OP) {
 		size = sizeof (acpi_parse2_object);
 		flags = ACPI_PARSEOP_BYTELIST;
 	}
-
 	else {
 		size = sizeof (acpi_parse_object);
 		flags = ACPI_PARSEOP_GENERIC;
 	}
 
-
 	if (size == sizeof (acpi_parse_object)) {
 		/*
 		 * The generic op is by far the most common (16 to 1)
 		 */
 		op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE);
 	}
-
 	else {
 		op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT);
 	}
@@ -157,13 +152,12 @@
 
 
 	if (op->opcode == AML_INT_RETURN_VALUE_OP) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Free retval op: %p\n", op));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", op));
 	}
 
 	if (op->flags == ACPI_PARSEOP_GENERIC) {
 		acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op);
 	}
-
 	else {
 		acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE_EXT, op);
 	}
diff -Nru a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
--- a/drivers/acpi/parser/psxface.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/parser/psxface.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: psxface - Parser external interfaces
- *              $Revision: 59 $
+ *              $Revision: 61 $
  *
  *****************************************************************************/
 
@@ -102,7 +102,7 @@
 	 * 1) Perform the first pass parse of the method to enter any
 	 * named objects that it creates into the namespace
 	 */
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 		"**** Begin Method Parse **** Entry=%p obj=%p\n",
 		method_node, obj_desc));
 
@@ -144,7 +144,7 @@
 	/*
 	 * 2) Execute the method.  Performs second pass parse simultaneously
 	 */
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 		"**** Begin Method Execution **** Entry=%p obj=%p\n",
 		method_node, obj_desc));
 
@@ -157,7 +157,7 @@
 
 	/* Init new op with the method name and pointer back to the NS node */
 
-	acpi_ps_set_name (op, method_node->name);
+	acpi_ps_set_name (op, method_node->name.integer);
 	op->node = method_node;
 
 	/* Create and initialize a new walk state */
@@ -194,7 +194,7 @@
 	 * a control exception code
 	 */
 	if (*return_obj_desc) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Method returned Obj_desc=%p\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned Obj_desc=%p\n",
 			*return_obj_desc));
 		ACPI_DUMP_STACK_ENTRY (*return_obj_desc);
 
diff -Nru a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
--- a/drivers/acpi/tables/tbget.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/tables/tbget.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbget - ACPI Table get* routines
- *              $Revision: 63 $
+ *              $Revision: 67 $
  *
  *****************************************************************************/
 
@@ -125,8 +125,7 @@
 
 acpi_status
 acpi_tb_get_table (
-	ACPI_PHYSICAL_ADDRESS   physical_address,
-	acpi_table_header       *buffer_ptr,
+	ACPI_POINTER            *address,
 	acpi_table_desc         *table_info)
 {
 	acpi_table_header       *table_header = NULL;
@@ -139,21 +138,17 @@
 	ACPI_FUNCTION_TRACE ("Tb_get_table");
 
 
-	if (!table_info) {
+	if (!table_info || !address) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	if (buffer_ptr) {
+	switch (address->pointer_type) {
+	case ACPI_LOGICAL_POINTER:
+
 		/*
 		 * Getting data from a buffer, not BIOS tables
 		 */
-		table_header = buffer_ptr;
-		status = acpi_tb_validate_table_header (table_header);
-		if (ACPI_FAILURE (status)) {
-			/* Table failed verification, map all errors to BAD_DATA */
-
-			return_ACPI_STATUS (AE_BAD_DATA);
-		}
+		table_header = address->pointer.logical;
 
 		/* Allocate buffer for the entire table */
 
@@ -165,21 +160,23 @@
 		/* Copy the entire table (including header) to the local buffer */
 
 		size = table_header->length;
-		ACPI_MEMCPY (full_table, buffer_ptr, size);
+		ACPI_MEMCPY (full_table, table_header, size);
 
 		/* Save allocation type */
 
 		allocation = ACPI_MEM_ALLOCATED;
-	}
+		break;
 
-	/*
-	 * Not reading from a buffer, just map the table's physical memory
-	 * into our address space.
-	 */
-	else {
+
+	case ACPI_PHYSICAL_POINTER:
+
+		/*
+		 * Not reading from a buffer, just map the table's physical memory
+		 * into our address space.
+		 */
 		size = SIZE_IN_HEADER;
 
-		status = acpi_tb_map_acpi_table (physical_address, &size, &full_table);
+		status = acpi_tb_map_acpi_table (address->pointer.physical, &size, &full_table);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -187,6 +184,11 @@
 		/* Save allocation type */
 
 		allocation = ACPI_MEM_MAPPED;
+		break;
+
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
 	/* Return values */
@@ -196,6 +198,12 @@
 	table_info->allocation  = allocation;
 	table_info->base_pointer = full_table;
 
+	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+		"Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
+		full_table->signature,
+		ACPI_HIDWORD (address->pointer.physical),
+		ACPI_LODWORD (address->pointer.physical), full_table));
+
 	return_ACPI_STATUS (status);
 }
 
@@ -209,9 +217,15 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Load and validate all tables other than the RSDT.  The RSDT must
+ * DESCRIPTION: Load and validate tables other than the RSDT.  The RSDT must
  *              already be loaded and validated.
  *
+ *              Get the minimum set of ACPI tables, namely:
+ *
+ *              1) FADT (via RSDT in loop below)
+ *              2) FACS (via FADT)
+ *              3) DSDT (via FADT)
+ *
  ******************************************************************************/
 
 acpi_status
@@ -222,6 +236,7 @@
 	acpi_status             status = AE_OK;
 	u32                     index;
 	acpi_table_desc         table_info;
+	ACPI_POINTER            address;
 
 
 	ACPI_FUNCTION_TRACE ("Tb_get_all_tables");
@@ -232,7 +247,9 @@
 	/*
 	 * Loop through all table pointers found in RSDT.
 	 * This will NOT include the FACS and DSDT - we must get
-	 * them after the loop
+	 * them after the loop.
+	 *
+	 * The ONLY table we are interested in getting here is the FADT.
 	 */
 	for (index = 0; index < number_of_tables; index++) {
 		/* Clear the Table_info each time */
@@ -241,18 +258,10 @@
 
 		/* Get the table via the XSDT */
 
-		status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS)
-				 ACPI_GET_ADDRESS (acpi_gbl_XSDT->table_offset_entry[index]),
-				 table_ptr, &table_info);
-
-		/* Ignore a table that failed verification */
-
-		if (status == AE_BAD_DATA) {
-			continue;
-		}
-
-		/* However, abort on serious errors */
+		address.pointer_type  = acpi_gbl_table_flags;
+		address.pointer.value = ACPI_GET_ADDRESS (acpi_gbl_XSDT->table_offset_entry[index]);
 
+		status = acpi_tb_get_table (&address, &table_info);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -267,6 +276,7 @@
 			 * determine if there are enough tables to continue.
 			 */
 			acpi_tb_uninstall_table (&table_info);
+			status = AE_OK;
 		}
 	}
 
@@ -276,24 +286,20 @@
 	 */
 	status = acpi_tb_convert_table_fadt ();
 	if (ACPI_FAILURE (status)) {
+		ACPI_REPORT_ERROR (("Could not convert FADT to internal common format\n"));
 		return_ACPI_STATUS (status);
 	}
 
 	/*
-	 * Get the minimum set of ACPI tables, namely:
-	 *
-	 * 1) FADT (via RSDT in loop above)
-	 * 2) FACS
-	 * 3) DSDT
-	 *
-	 */
-
-	/*
 	 * Get the FACS (must have the FADT first, from loop above)
 	 * Acpi_tb_get_table_facs will fail if FADT pointer is not valid
 	 */
-	status = acpi_tb_get_table_facs (table_ptr, &table_info);
+	address.pointer_type  = acpi_gbl_table_flags;
+	address.pointer.value = ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl);
+
+	status = acpi_tb_get_table (&address, &table_info);
 	if (ACPI_FAILURE (status)) {
+		ACPI_REPORT_ERROR (("Could not get the FACS\n"));
 		return_ACPI_STATUS (status);
 	}
 
@@ -301,6 +307,7 @@
 
 	status = acpi_tb_install_table (table_ptr, &table_info);
 	if (ACPI_FAILURE (status)) {
+		ACPI_REPORT_ERROR (("Could not install the FACS\n"));
 		return_ACPI_STATUS (status);
 	}
 
@@ -310,15 +317,19 @@
 	 */
 	status = acpi_tb_build_common_facs (&table_info);
 	if (ACPI_FAILURE (status)) {
+		ACPI_REPORT_ERROR (("Could not convert FACS to common internal format\n"));
 		return_ACPI_STATUS (status);
 	}
 
 	/*
 	 * Get the DSDT (We know that the FADT is valid now)
 	 */
-	status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt),
-			  table_ptr, &table_info);
+	address.pointer_type  = acpi_gbl_table_flags;
+	address.pointer.value = ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt);
+
+	status = acpi_tb_get_table (&address, &table_info);
 	if (ACPI_FAILURE (status)) {
+		ACPI_REPORT_ERROR (("Could not get the DSDT\n"));
 		return_ACPI_STATUS (status);
 	}
 
@@ -326,20 +337,16 @@
 
 	status = acpi_tb_install_table (table_ptr, &table_info);
 	if (ACPI_FAILURE (status)) {
+		ACPI_REPORT_ERROR (("Could not install the DSDT\n"));
 		return_ACPI_STATUS (status);
 	}
 
-	/* Dump the DSDT Header */
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Hex dump of DSDT Header:\n"));
-	ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, sizeof (acpi_table_header));
-
 	/* Dump the entire DSDT */
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
-		"Hex dump of DSDT (After header), size %d (%x)\n",
+		"Hex dump of entire DSDT, size %d (0x%X)\n",
 		acpi_gbl_DSDT->length, acpi_gbl_DSDT->length));
-	ACPI_DUMP_BUFFER ((u8 *) (acpi_gbl_DSDT + 1), acpi_gbl_DSDT->length);
+	ACPI_DUMP_BUFFER ((u8 *) acpi_gbl_DSDT, acpi_gbl_DSDT->length);
 
 	/* Always delete the RSDP mapping, we are done with it */
 
@@ -362,7 +369,7 @@
 
 acpi_status
 acpi_tb_verify_rsdp (
-	ACPI_PHYSICAL_ADDRESS   rsdp_physical_address)
+	ACPI_POINTER            *address)
 {
 	acpi_table_desc         table_info;
 	acpi_status             status;
@@ -372,13 +379,25 @@
 	ACPI_FUNCTION_TRACE ("Tb_verify_rsdp");
 
 
-	/*
-	 * Obtain access to the RSDP structure
-	 */
-	status = acpi_os_map_memory (rsdp_physical_address, sizeof (RSDP_DESCRIPTOR),
-			  (void **) &rsdp);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+	switch (address->pointer_type) {
+	case ACPI_LOGICAL_POINTER:
+
+		rsdp = address->pointer.logical;
+		break;
+
+	case ACPI_PHYSICAL_POINTER:
+		/*
+		 * Obtain access to the RSDP structure
+		 */
+		status = acpi_os_map_memory (address->pointer.physical, sizeof (RSDP_DESCRIPTOR),
+				  (void **) &rsdp);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
 	/*
@@ -407,7 +426,6 @@
 		}
 	}
 
-
 	/* The RSDP supplied is OK */
 
 	table_info.pointer     = (acpi_table_header *) rsdp;
@@ -431,7 +449,9 @@
 	/* Error exit */
 cleanup:
 
-	acpi_os_unmap_memory (rsdp, sizeof (RSDP_DESCRIPTOR));
+	if (acpi_gbl_table_flags & ACPI_PHYSICAL_POINTER) {
+		acpi_os_unmap_memory (rsdp, sizeof (RSDP_DESCRIPTOR));
+	}
 	return_ACPI_STATUS (status);
 }
 
@@ -449,28 +469,26 @@
  *
  ******************************************************************************/
 
-ACPI_PHYSICAL_ADDRESS
-acpi_tb_get_rsdt_address (void)
+void
+acpi_tb_get_rsdt_address (
+	ACPI_POINTER            *out_address)
 {
-	ACPI_PHYSICAL_ADDRESS   physical_address;
-
 
 	ACPI_FUNCTION_ENTRY ();
 
 
+	out_address->pointer_type = acpi_gbl_table_flags;
+
 	/*
 	 * For RSDP revision 0 or 1, we use the RSDT.
 	 * For RSDP revision 2 (and above), we use the XSDT
 	 */
 	if (acpi_gbl_RSDP->revision < 2) {
-		physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->rsdt_physical_address;
+		out_address->pointer.value = acpi_gbl_RSDP->rsdt_physical_address;
 	}
 	else {
-		physical_address = (ACPI_PHYSICAL_ADDRESS)
-				   ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address);
+		out_address->pointer.value = ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address);
 	}
-
-	return (physical_address);
 }
 
 
@@ -543,25 +561,51 @@
 
 acpi_status
 acpi_tb_get_table_pointer (
-	ACPI_PHYSICAL_ADDRESS   physical_address,
+	ACPI_POINTER            *address,
 	u32                     flags,
 	u32                     *size,
 	acpi_table_header       **table_ptr)
 {
-	acpi_status             status;
+	acpi_status             status = AE_OK;
 
 
 	ACPI_FUNCTION_ENTRY ();
 
 
+	/*
+	 * What mode is the processor in? (Virtual or Physical addressing)
+	 */
 	if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
-		*size = SIZE_IN_HEADER;
-		status = acpi_tb_map_acpi_table (physical_address, size, table_ptr);
+		/* Incoming pointer can be either logical or physical */
+
+		switch (address->pointer_type) {
+		case ACPI_PHYSICAL_POINTER:
+
+			*size = SIZE_IN_HEADER;
+			status = acpi_tb_map_acpi_table (address->pointer.physical, size, table_ptr);
+			break;
+
+		case ACPI_LOGICAL_POINTER:
+
+			*table_ptr = address->pointer.logical;
+			*size = 0;
+			break;
+		}
 	}
 	else {
-		*size = 0;
-		*table_ptr = ACPI_PHYSADDR_TO_PTR (physical_address);
-		status = AE_OK;
+		/* In Physical addressing mode, all pointers must be physical */
+
+		switch (address->pointer_type) {
+		case ACPI_PHYSICAL_POINTER:
+			*size = 0;
+			*table_ptr = address->pointer.logical;
+			break;
+
+		case ACPI_LOGICAL_POINTER:
+
+			status = AE_BAD_PARAMETER;
+			break;
+		}
 	}
 
 	return (status);
@@ -586,7 +630,7 @@
 {
 	acpi_table_desc         table_info;
 	acpi_status             status;
-	ACPI_PHYSICAL_ADDRESS   physical_address;
+	ACPI_POINTER            address;
 
 
 	ACPI_FUNCTION_TRACE ("Tb_get_table_rsdt");
@@ -601,11 +645,11 @@
 		ACPI_HIDWORD (acpi_gbl_RSDP->rsdt_physical_address),
 		ACPI_LODWORD (acpi_gbl_RSDP->rsdt_physical_address)));
 
-	physical_address = acpi_tb_get_rsdt_address ();
 
 	/* Get the RSDT/XSDT */
 
-	status = acpi_tb_get_table (physical_address, NULL, &table_info);
+	acpi_tb_get_rsdt_address (&address);
+	status = acpi_tb_get_table (&address, &table_info);
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not get the RSDT, %s\n",
 			acpi_format_exception (status)));
@@ -645,82 +689,4 @@
 	return_ACPI_STATUS (status);
 }
 
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_tb_get_table_facs
- *
- * PARAMETERS:  *Buffer_ptr             - If Buffer_ptr is valid, read data from
- *                                        buffer rather than searching memory
- *              *Table_info             - Where the table info is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Returns a pointer to the FACS as defined in FADT.  This
- *              function assumes the global variable FADT has been
- *              correctly initialized.  The value of FADT->Firmware_ctrl
- *              into a far pointer which is returned.
- *
- *****************************************************************************/
-
-acpi_status
-acpi_tb_get_table_facs (
-	acpi_table_header       *buffer_ptr,
-	acpi_table_desc         *table_info)
-{
-	acpi_table_header       *table_ptr = NULL;
-	u32                     size;
-	u8                      allocation;
-	acpi_status             status = AE_OK;
-
-
-	ACPI_FUNCTION_TRACE ("Tb_get_table_facs");
-
-
-	/* Must have a valid FADT pointer */
-
-	if (!acpi_gbl_FADT) {
-		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
-	}
-
-	size = sizeof (FACS_DESCRIPTOR);
-	if (buffer_ptr) {
-		/*
-		 * Getting table from a file -- allocate a buffer and
-		 * read the table.
-		 */
-		table_ptr = ACPI_MEM_ALLOCATE (size);
-		if(!table_ptr) {
-			return_ACPI_STATUS (AE_NO_MEMORY);
-		}
-
-		ACPI_MEMCPY (table_ptr, buffer_ptr, size);
-
-		/* Save allocation type */
-
-		allocation = ACPI_MEM_ALLOCATED;
-	}
-	else {
-		/* Just map the physical memory to our address space */
-
-		status = acpi_tb_map_acpi_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl),
-				   &size, &table_ptr);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
-
-		/* Save allocation type */
-
-		allocation = ACPI_MEM_MAPPED;
-	}
-
-	/* Return values */
-
-	table_info->pointer     = table_ptr;
-	table_info->length      = size;
-	table_info->allocation  = allocation;
-	table_info->base_pointer = table_ptr;
-
-	return_ACPI_STATUS (status);
-}
 
diff -Nru a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
--- a/drivers/acpi/tables/tbinstal.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/tables/tbinstal.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbinstal - ACPI table installation and removal
- *              $Revision: 55 $
+ *              $Revision: 57 $
  *
  *****************************************************************************/
 
@@ -177,28 +177,35 @@
 	 * We only "recognize" a limited number of ACPI tables -- namely, the
 	 * ones that are used by the subsystem (DSDT, FADT, etc.)
 	 *
-	 * An AE_NOT_FOUND means that the table was not recognized.
+	 * An AE_TABLE_NOT_SUPPORTED means that the table was not recognized.
 	 * This can be any one of many valid ACPI tables, it just isn't one of
 	 * the tables that is consumed by the core subsystem
 	 */
 	status = acpi_tb_match_signature (table_header->signature, table_info);
-	if (ACPI_SUCCESS (status)) {
-		/* Return the table type and length via the info struct */
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
 
-		table_info->length  = table_header->length;
+	status = acpi_tb_validate_table_header (table_header);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
 
-		/*
-		 * Validate checksum for _most_ tables,
-		 * even the ones whose signature we don't recognize
-		 */
-		if (table_info->type != ACPI_TABLE_FACS) {
-			status = acpi_tb_verify_table_checksum (table_header);
-			if (ACPI_FAILURE (status) &&
-				(!ACPI_CHECKSUM_ABORT)) {
-				/* Ignore the error if configuration says so */
+	/* Return the table type and length via the info struct */
 
-				status = AE_OK;
-			}
+	table_info->length  = table_header->length;
+
+	/*
+	 * Validate checksum for _most_ tables,
+	 * even the ones whose signature we don't recognize
+	 */
+	if (table_info->type != ACPI_TABLE_FACS) {
+		status = acpi_tb_verify_table_checksum (table_header);
+		if (ACPI_FAILURE (status) &&
+			(!ACPI_CHECKSUM_ABORT)) {
+			/* Ignore the error if configuration says so */
+
+			status = AE_OK;
 		}
 	}
 
@@ -372,10 +379,6 @@
 		return;
 	}
 
-	/* Free the table */
-
-	acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]);
-
 	/* Clear the appropriate "typed" global table pointer */
 
 	switch (type) {
@@ -404,6 +407,10 @@
 	default:
 		break;
 	}
+
+	/* Free the table */
+
+	acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]);
 
 	(void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
 	return_VOID;
diff -Nru a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
--- a/drivers/acpi/tables/tbutils.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/acpi/tables/tbutils.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbutils - Table manipulation utilities
- *              $Revision: 49 $
+ *              $Revision: 51 $
  *
  *****************************************************************************/
 
@@ -71,7 +71,6 @@
 		} while (list_head != &acpi_gbl_acpi_tables[i]);
 	}
 
-
 	ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Table_id=%X does not exist\n", table_id));
 	return (AE_BAD_PARAMETER);
 }
@@ -115,7 +114,6 @@
 		return (AE_BAD_ADDRESS);
 	}
 
-
 	/* Ensure that the signature is 4 ASCII characters */
 
 	ACPI_MOVE_UNALIGNED32_TO_32 (&signature, &table_header->signature);
@@ -124,12 +122,11 @@
 			"Table signature at %p [%p] has invalid characters\n",
 			table_header, &signature));
 
-		ACPI_REPORT_WARNING (("Invalid table signature %4.4s found\n", (char *) &signature));
+		ACPI_REPORT_WARNING (("Invalid table signature found: [%4.4s]\n", (char *) &signature));
 		ACPI_DUMP_BUFFER (table_header, sizeof (acpi_table_header));
 		return (AE_BAD_SIGNATURE);
 	}
 
-
 	/* Validate the table length */
 
 	if (table_header->length < sizeof (acpi_table_header)) {
@@ -208,10 +205,10 @@
 		}
 	}
 
-
 	/* Map the physical memory for the correct length */
 
-	status = acpi_os_map_memory (physical_address, table_size, (void **) &table);
+	status = acpi_os_map_memory (physical_address, table_size,
+			  (void **) &table);
 	if (ACPI_FAILURE (status)) {
 		return (status);
 	}
@@ -222,7 +219,6 @@
 
 	*size = table_size;
 	*logical_address = table;
-
 	return (status);
 }
 
@@ -263,8 +259,6 @@
 
 		status = AE_BAD_CHECKSUM;
 	}
-
-
 	return_ACPI_STATUS (status);
 }
 
@@ -301,7 +295,6 @@
 			sum = (u8) (sum + *rover);
 		}
 	}
-
 	return (sum);
 }
 
diff -Nru a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
--- a/drivers/acpi/tables/tbxface.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/tables/tbxface.c	Sun Apr 14 12:16:59 2002
@@ -2,7 +2,7 @@
  *
  * Module Name: tbxface - Public interfaces to the ACPI subsystem
  *                         ACPI table oriented interfaces
- *              $Revision: 51 $
+ *              $Revision: 52 $
  *
  *****************************************************************************/
 
@@ -51,7 +51,7 @@
 acpi_status
 acpi_load_tables (void)
 {
-	ACPI_PHYSICAL_ADDRESS   rsdp_physical_address;
+	ACPI_POINTER            rsdp_address;
 	acpi_status             status;
 	u32                     number_of_tables = 0;
 
@@ -62,7 +62,7 @@
 	/* Get the RSDP */
 
 	status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
-			  &rsdp_physical_address);
+			  &rsdp_address);
 	if (ACPI_FAILURE (status)) {
 		ACPI_REPORT_ERROR (("Acpi_load_tables: Could not get RSDP, %s\n",
 				  acpi_format_exception (status)));
@@ -71,7 +71,9 @@
 
 	/* Map and validate the RSDP */
 
-	status = acpi_tb_verify_rsdp (rsdp_physical_address);
+	acpi_gbl_table_flags = rsdp_address.pointer_type;
+
+	status = acpi_tb_verify_rsdp (&rsdp_address);
 	if (ACPI_FAILURE (status)) {
 		ACPI_REPORT_ERROR (("Acpi_load_tables: RSDP Failed validation: %s\n",
 				  acpi_format_exception (status)));
@@ -141,6 +143,7 @@
 {
 	acpi_status             status;
 	acpi_table_desc         table_info;
+	ACPI_POINTER            address;
 
 
 	ACPI_FUNCTION_TRACE ("Acpi_load_table");
@@ -152,7 +155,10 @@
 
 	/* Copy the table to a local buffer */
 
-	status = acpi_tb_get_table (0, table_ptr, &table_info);
+	address.pointer_type    = ACPI_LOGICAL_POINTER;
+	address.pointer.logical = table_ptr;
+
+	status = acpi_tb_get_table (&address, &table_info);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
diff -Nru a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
--- a/drivers/acpi/tables/tbxfroot.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/tables/tbxfroot.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbxfroot - Find the root ACPI table (RSDT)
- *              $Revision: 58 $
+ *              $Revision: 61 $
  *
  *****************************************************************************/
 
@@ -118,7 +118,8 @@
 	u32                     flags,
 	acpi_table_header       **table_pointer)
 {
-	ACPI_PHYSICAL_ADDRESS   physical_address;
+	ACPI_POINTER            rsdp_address;
+	ACPI_POINTER            address;
 	acpi_table_header       *rsdt_ptr = NULL;
 	acpi_table_header       *table_ptr;
 	acpi_status             status;
@@ -149,7 +150,7 @@
 	if (!acpi_gbl_RSDP) {
 		/* Get the RSDP */
 
-		status = acpi_os_get_root_pointer (flags, &physical_address);
+		status = acpi_os_get_root_pointer (flags, &rsdp_address);
 		if (ACPI_FAILURE (status)) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not found\n"));
 			return_ACPI_STATUS (AE_NO_ACPI_TABLES);
@@ -158,14 +159,14 @@
 		/* Map and validate the RSDP */
 
 		if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
-			status = acpi_os_map_memory (physical_address, sizeof (RSDP_DESCRIPTOR),
+			status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (RSDP_DESCRIPTOR),
 					  (void **) &acpi_gbl_RSDP);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 		}
 		else {
-			acpi_gbl_RSDP = ACPI_PHYSADDR_TO_PTR (physical_address);
+			acpi_gbl_RSDP = rsdp_address.pointer.logical;
 		}
 
 		/*
@@ -194,8 +195,9 @@
 
 	/* Get the RSDT and validate it */
 
-	physical_address = acpi_tb_get_rsdt_address ();
-	status = acpi_tb_get_table_pointer (physical_address, flags, &rsdt_size, &rsdt_ptr);
+	acpi_tb_get_rsdt_address (&address);
+
+	status = acpi_tb_get_table_pointer (&address, flags, &rsdt_size, &rsdt_ptr);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -217,18 +219,18 @@
 	for (i = 0, j = 0; i < table_count; i++) {
 		/* Get the next table pointer */
 
+		address.pointer_type = acpi_gbl_table_flags;
 		if (acpi_gbl_RSDP->revision < 2) {
-			physical_address = (ACPI_PHYSICAL_ADDRESS)
-				((RSDT_DESCRIPTOR *) rsdt_ptr)->table_offset_entry[i];
+			address.pointer.value = ((RSDT_DESCRIPTOR *) rsdt_ptr)->table_offset_entry[i];
 		}
 		else {
-			physical_address = (ACPI_PHYSICAL_ADDRESS)
-				ACPI_GET_ADDRESS (((xsdt_descriptor *) rsdt_ptr)->table_offset_entry[i]);
+			address.pointer.value = ACPI_GET_ADDRESS (
+				((xsdt_descriptor *) rsdt_ptr)->table_offset_entry[i]);
 		}
 
 		/* Get addressibility if necessary */
 
-		status = acpi_tb_get_table_pointer (physical_address, flags, &table_size, &table_ptr);
+		status = acpi_tb_get_table_pointer (&address, flags, &table_size, &table_ptr);
 		if (ACPI_FAILURE (status)) {
 			goto cleanup;
 		}
@@ -276,8 +278,8 @@
  *
  * FUNCTION:    Acpi_find_root_pointer
  *
- * PARAMETERS:  **Rsdp_physical_address     - Where to place the RSDP address
- *              Flags                       - Logical/Physical addressing
+ * PARAMETERS:  **Rsdp_address          - Where to place the RSDP address
+ *              Flags                   - Logical/Physical addressing
  *
  * RETURN:      Status, Physical address of the RSDP
  *
@@ -288,7 +290,7 @@
 acpi_status
 acpi_find_root_pointer (
 	u32                     flags,
-	ACPI_PHYSICAL_ADDRESS   *rsdp_physical_address)
+	ACPI_POINTER            *rsdp_address)
 {
 	acpi_table_desc         table_info;
 	acpi_status             status;
@@ -305,7 +307,8 @@
 		return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 	}
 
-	*rsdp_physical_address = table_info.physical_address;
+	rsdp_address->pointer_type = ACPI_PHYSICAL_POINTER;
+	rsdp_address->pointer.physical = table_info.physical_address;
 	return_ACPI_STATUS (AE_OK);
 }
 
diff -Nru a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
--- a/drivers/acpi/utilities/utcopy.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/utilities/utcopy.c	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: utcopy - Internal to external object translation utilities
- *              $Revision: 94 $
+ *              $Revision: 95 $
  *
  *****************************************************************************/
 
@@ -654,6 +654,9 @@
 	case ACPI_TYPE_BUFFER:
 
 		dest_desc->buffer.node = NULL;
+		dest_desc->common.flags = source_desc->common.flags;
+
+		/* Fall through to common string/buffer case */
 
 	case ACPI_TYPE_STRING:
 
@@ -744,6 +747,7 @@
 		}
 
 		target_object->package.count = source_object->package.count;
+		target_object->common.flags = source_object->common.flags;
 
 		/*
 		 * Pass the new package object back to the package walk routine
@@ -792,6 +796,7 @@
 
 
 	dest_obj->common.type   = source_obj->common.type;
+	dest_obj->common.flags  = source_obj->common.flags;
 	dest_obj->package.count = source_obj->package.count;
 
 
@@ -805,10 +810,6 @@
 			("Aml_build_copy_internal_package_object: Package allocation failure\n"));
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
-
-	/* Init */
-
-	dest_obj->package.next_element = dest_obj->package.elements;
 
 	/*
 	 * Copy the package element-by-element by walking the package "tree".
diff -Nru a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
--- a/drivers/acpi/utilities/utdebug.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/acpi/utilities/utdebug.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: utdebug - Debug print routines
- *              $Revision: 96 $
+ *              $Revision: 97 $
  *
  *****************************************************************************/
 
@@ -508,6 +508,11 @@
 		return;
 	}
 
+	if ((count < 4) || (count & 0x01)) {
+		display = DB_BYTE_DISPLAY;
+	}
+
+	acpi_os_printf ("\n_offset Value\n");
 
 	/*
 	 * Nasty little dump buffer routine!
diff -Nru a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
--- a/drivers/acpi/utilities/utdelete.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/acpi/utilities/utdelete.c	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: utdelete - object deletion and reference count utilities
- *              $Revision: 87 $
+ *              $Revision: 88 $
  *
  ******************************************************************************/
 
@@ -68,10 +68,9 @@
 	 * actual ACPI objects (for example, a raw buffer pointer).
 	 */
 	switch (object->common.type) {
-
 	case ACPI_TYPE_STRING:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** String %p, ptr %p\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
 			object, object->string.pointer));
 
 		/* Free the actual string buffer */
@@ -84,7 +83,7 @@
 
 	case ACPI_TYPE_BUFFER:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Buffer %p, ptr %p\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
 			object, object->buffer.pointer));
 
 		/* Free the actual buffer */
@@ -95,7 +94,7 @@
 
 	case ACPI_TYPE_PACKAGE:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, " **** Package of count %X\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
 			object->package.count));
 
 		/*
@@ -111,7 +110,7 @@
 
 	case ACPI_TYPE_MUTEX:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "***** Mutex %p, Semaphore %p\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Mutex %p, Semaphore %p\n",
 			object, object->mutex.semaphore));
 
 		acpi_ex_unlink_mutex (object);
@@ -121,7 +120,7 @@
 
 	case ACPI_TYPE_EVENT:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "***** Event %p, Semaphore %p\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Event %p, Semaphore %p\n",
 			object, object->event.semaphore));
 
 		acpi_os_delete_semaphore (object->event.semaphore);
@@ -131,7 +130,7 @@
 
 	case ACPI_TYPE_METHOD:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "***** Method %p\n", object));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Method %p\n", object));
 
 		/* Delete the method semaphore if it exists */
 
@@ -144,7 +143,7 @@
 
 	case ACPI_TYPE_REGION:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "***** Region %p\n", object));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Region %p\n", object));
 
 		second_desc = acpi_ns_get_secondary_object (object);
 		if (second_desc) {
@@ -168,7 +167,7 @@
 
 	case ACPI_TYPE_BUFFER_FIELD:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "***** Buffer Field %p\n", object));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Buffer Field %p\n", object));
 
 		second_desc = acpi_ns_get_secondary_object (object);
 		if (second_desc) {
@@ -185,14 +184,14 @@
 	/* Free any allocated memory (pointer within the object) found above */
 
 	if (obj_pointer) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting Object Subptr %p\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
 				obj_pointer));
 		ACPI_MEM_FREE (obj_pointer);
 	}
 
 	/* Now the object can be safely deleted */
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Deleting Object %p [%s]\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
 			object, acpi_ut_get_type_name (object->common.type)));
 
 	acpi_ut_delete_object_desc (object);
@@ -232,7 +231,6 @@
 	/* Free the combined parameter pointer list and object array */
 
 	ACPI_MEM_FREE (obj_list);
-
 	return_ACPI_STATUS (AE_OK);
 }
 
@@ -261,11 +259,11 @@
 
 	ACPI_FUNCTION_NAME ("Ut_update_ref_count");
 
+
 	if (!object) {
 		return;
 	}
 
-
 	count = object->common.reference_count;
 	new_count = count;
 
@@ -279,7 +277,7 @@
 		new_count++;
 		object->common.reference_count = new_count;
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj %p Refs=%X, [Incremented]\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, [Incremented]\n",
 			object, new_count));
 		break;
 
@@ -287,21 +285,20 @@
 	case REF_DECREMENT:
 
 		if (count < 1) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
 				object, new_count));
 
 			new_count = 0;
 		}
-
 		else {
 			new_count--;
 
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj %p Refs=%X, [Decremented]\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, [Decremented]\n",
 				object, new_count));
 		}
 
 		if (object->common.type == ACPI_TYPE_METHOD) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Method Obj %p Refs=%X, [Decremented]\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Method Obj %p Refs=%X, [Decremented]\n",
 				object, new_count));
 		}
 
@@ -315,7 +312,7 @@
 
 	case REF_FORCE_DELETE:
 
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj %p Refs=%X, Force delete! (Set to 0)\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, Force delete! (Set to 0)\n",
 			object, count));
 
 		new_count = 0;
@@ -330,7 +327,6 @@
 		break;
 	}
 
-
 	/*
 	 * Sanity check the reference count, for debug purposes only.
 	 * (A deleted object will have a huge reference count)
@@ -394,7 +390,7 @@
 	 * Make sure that this isn't a namespace handle
 	 */
 	if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object %p is NS handle\n", object));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object));
 		return_ACPI_STATUS (AE_OK);
 	}
 
@@ -566,7 +562,6 @@
 	 * We have a valid ACPI internal object, now increment the reference count
 	 */
 	acpi_ut_update_object_reference (object, REF_INCREMENT);
-
 	return_VOID;
 }
 
@@ -607,7 +602,7 @@
 		return_VOID;
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Obj %p Refs=%X\n",
+	ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X\n",
 			object, object->common.reference_count));
 
 	/*
diff -Nru a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
--- a/drivers/acpi/utilities/uteval.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/utilities/uteval.c	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: uteval - Object evaluation
- *              $Revision: 37 $
+ *              $Revision: 38 $
  *
  *****************************************************************************/
 
@@ -68,7 +68,7 @@
 	status = acpi_ns_evaluate_relative (device_node, object_name, NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		if (status == AE_NOT_FOUND) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s on %4.4s was not found\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s on %4.4s was not found\n",
 				object_name, (char *) &device_node->name));
 		}
 		else {
@@ -147,7 +147,7 @@
 			 METHOD_NAME__HID, NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		if (status == AE_NOT_FOUND) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "_HID on %4.4s was not found\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_HID on %4.4s was not found\n",
 				(char *) &device_node->name));
 		}
 		else {
@@ -230,7 +230,7 @@
 			 METHOD_NAME__CID, NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		if (status == AE_NOT_FOUND) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "_CID on %4.4s was not found\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_CID on %4.4s was not found\n",
 				(char *)&device_node->name));
 		}
 		else {
@@ -324,7 +324,7 @@
 			 METHOD_NAME__UID, NULL, &obj_desc);
 	if (ACPI_FAILURE (status)) {
 		if (status == AE_NOT_FOUND) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "_UID on %4.4s was not found\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "_UID on %4.4s was not found\n",
 				(char *) &device_node->name));
 		}
 		else {
@@ -409,7 +409,7 @@
 	status = acpi_ns_evaluate_relative (device_node,
 			 METHOD_NAME__STA, NULL, &obj_desc);
 	if (AE_NOT_FOUND == status) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 			"_STA on %4.4s was not found, assuming present.\n",
 			(char *) &device_node->name));
 
diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
--- a/drivers/acpi/utilities/utglobal.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/acpi/utilities/utglobal.c	Sun Apr 14 12:16:55 2002
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: utglobal - Global variables for the ACPI subsystem
- *              $Revision: 153 $
+ *              $Revision: 155 $
  *
  *****************************************************************************/
 
@@ -56,51 +56,63 @@
 	acpi_status             sub_status;
 
 
-	sub_status = (status & ~AE_CODE_MASK);
+	ACPI_FUNCTION_NAME ("Format_exception");
+
 
+	sub_status = (status & ~AE_CODE_MASK);
 
 	switch (status & AE_CODE_MASK) {
 	case AE_CODE_ENVIRONMENTAL:
 
 		if (sub_status <= AE_CODE_ENV_MAX) {
 			exception = acpi_gbl_exception_names_env [sub_status];
+			break;
 		}
-		break;
+		goto unknown;
 
 	case AE_CODE_PROGRAMMER:
 
 		if (sub_status <= AE_CODE_PGM_MAX) {
 			exception = acpi_gbl_exception_names_pgm [sub_status -1];
+			break;
 		}
-		break;
+		goto unknown;
 
 	case AE_CODE_ACPI_TABLES:
 
 		if (sub_status <= AE_CODE_TBL_MAX) {
 			exception = acpi_gbl_exception_names_tbl [sub_status -1];
+			break;
 		}
-		break;
+		goto unknown;
 
 	case AE_CODE_AML:
 
 		if (sub_status <= AE_CODE_AML_MAX) {
 			exception = acpi_gbl_exception_names_aml [sub_status -1];
+			break;
 		}
-		break;
+		goto unknown;
 
 	case AE_CODE_CONTROL:
 
 		if (sub_status <= AE_CODE_CTRL_MAX) {
 			exception = acpi_gbl_exception_names_ctrl [sub_status -1];
+			break;
 		}
-		break;
+		goto unknown;
 
 	default:
-		break;
+		goto unknown;
 	}
 
 
 	return ((const char *) exception);
+
+unknown:
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown exception code: 0x%8.8X\n", status));
+	return ((const char *) exception);
 }
 
 
@@ -173,10 +185,10 @@
 	{"_SB_",    ACPI_TYPE_DEVICE},
 	{"_SI_",    INTERNAL_TYPE_DEF_ANY},
 	{"_TZ_",    INTERNAL_TYPE_DEF_ANY},
-	{"_REV",    ACPI_TYPE_INTEGER, "2"},
-	{"_OS_",    ACPI_TYPE_STRING, ACPI_OS_NAME},
-	{"_GL_",    ACPI_TYPE_MUTEX, "0"},
-	{NULL,      ACPI_TYPE_ANY}           /* Table terminator */
+	{"_REV",    ACPI_TYPE_INTEGER,          "2"},
+	{"_OS_",    ACPI_TYPE_STRING,           ACPI_OS_NAME},
+	{"_GL_",    ACPI_TYPE_MUTEX,            "0"},
+	{NULL,      ACPI_TYPE_ANY}              /* Table terminator */
 };
 
 
@@ -193,16 +205,16 @@
 	ACPI_NS_NORMAL,                     /* 01 Number           */
 	ACPI_NS_NORMAL,                     /* 02 String           */
 	ACPI_NS_NORMAL,                     /* 03 Buffer           */
-	ACPI_NS_LOCAL,                      /* 04 Package          */
+	ACPI_NS_NORMAL,                     /* 04 Package          */
 	ACPI_NS_NORMAL,                     /* 05 Field_unit       */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 06 Device           */
-	ACPI_NS_LOCAL,                      /* 07 Acpi_event       */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 08 Method           */
-	ACPI_NS_LOCAL,                      /* 09 Mutex            */
-	ACPI_NS_LOCAL,                      /* 10 Region           */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 11 Power            */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 12 Processor        */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,   /* 13 Thermal          */
+	ACPI_NS_NEWSCOPE,                   /* 06 Device           */
+	ACPI_NS_NORMAL,                     /* 07 Event            */
+	ACPI_NS_NEWSCOPE,                   /* 08 Method           */
+	ACPI_NS_NORMAL,                     /* 09 Mutex            */
+	ACPI_NS_NORMAL,                     /* 10 Region           */
+	ACPI_NS_NEWSCOPE,                   /* 11 Power            */
+	ACPI_NS_NEWSCOPE,                   /* 12 Processor        */
+	ACPI_NS_NEWSCOPE,                   /* 13 Thermal          */
 	ACPI_NS_NORMAL,                     /* 14 Buffer_field     */
 	ACPI_NS_NORMAL,                     /* 15 Ddb_handle       */
 	ACPI_NS_NORMAL,                     /* 16 Debug Object     */
@@ -758,6 +770,7 @@
 
 	/* Miscellaneous variables */
 
+	acpi_gbl_table_flags                = ACPI_PHYSICAL_POINTER;
 	acpi_gbl_rsdp_original_location     = 0;
 	acpi_gbl_cm_single_step             = FALSE;
 	acpi_gbl_db_terminate_threads       = FALSE;
@@ -779,7 +792,7 @@
 
 	acpi_gbl_root_node                  = NULL;
 
-	acpi_gbl_root_node_struct.name      = ACPI_ROOT_NAME;
+	acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
 	acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
 	acpi_gbl_root_node_struct.type      = ACPI_TYPE_ANY;
 	acpi_gbl_root_node_struct.child     = NULL;
diff -Nru a/drivers/atm/eni.c b/drivers/atm/eni.c
--- a/drivers/atm/eni.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/atm/eni.c	Sun Apr 14 12:16:56 2002
@@ -14,7 +14,6 @@
 #include <linux/sonet.h>
 #include <linux/skbuff.h>
 #include <linux/time.h>
-#include <linux/sched.h> /* for xtime */
 #include <linux/delay.h>
 #include <linux/uio.h>
 #include <linux/init.h>
diff -Nru a/drivers/base/Makefile b/drivers/base/Makefile
--- a/drivers/base/Makefile	Sun Apr 14 12:16:57 2002
+++ b/drivers/base/Makefile	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 O_TARGET	:= base.o
 
-obj-y		:= core.o interface.o fs.o
+obj-y		:= core.o sys.o interface.o fs.o power.o
 
-export-objs	:= core.o interface.o fs.o 
+export-objs	:= $(obj-y)
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/base/base.h b/drivers/base/base.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/base/base.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,14 @@
+#undef DEBUG
+
+#ifdef DEBUG
+# define DBG(x...) printk(x)
+#else
+# define DBG(x...)
+#endif
+
+extern struct device device_root;
+extern spinlock_t device_lock;
+
+extern int device_make_dir(struct device * dev);
+extern void device_remove_dir(struct device * dev);
+
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/base/core.c	Sun Apr 14 12:16:55 2002
@@ -10,16 +10,9 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include "base.h"
 
-#undef DEBUG
-
-#ifdef DEBUG
-# define DBG(x...) printk(x)
-#else
-# define DBG(x...)
-#endif
-
-static struct device device_root = {
+struct device device_root = {
 	bus_id:		"root",
 	name:		"System root",
 };
@@ -27,10 +20,7 @@
 int (*platform_notify)(struct device * dev) = NULL;
 int (*platform_notify_remove)(struct device * dev) = NULL;
 
-extern int device_make_dir(struct device * dev);
-extern void device_remove_dir(struct device * dev);
-
-static spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
 
 /**
  * device_register - register a device
@@ -39,10 +29,14 @@
  * First, make sure that the device has a parent, create
  * a directory for it, then add it to the parent's list of
  * children.
+ *
+ * Maintains a global list of all devices, in depth-first ordering.
+ * The head for that list is device_root.g_list.
  */
 int device_register(struct device *dev)
 {
 	int error;
+	struct device *prev_dev;
 
 	if (!dev || !strlen(dev->bus_id))
 		return -EINVAL;
@@ -50,6 +44,7 @@
 	spin_lock(&device_lock);
 	INIT_LIST_HEAD(&dev->node);
 	INIT_LIST_HEAD(&dev->children);
+	INIT_LIST_HEAD(&dev->g_list);
 	spin_lock_init(&dev->lock);
 	atomic_set(&dev->refcount,2);
 
@@ -57,6 +52,13 @@
 		if (!dev->parent)
 			dev->parent = &device_root;
 		get_device(dev->parent);
+
+		if (list_empty(&dev->parent->children))
+			prev_dev = dev->parent;
+		else
+			prev_dev = list_entry(dev->parent->children.prev, struct device, node);
+		list_add(&dev->g_list, &prev_dev->g_list);
+
 		list_add_tail(&dev->node,&dev->parent->children);
 	}
 	spin_unlock(&device_lock);
@@ -79,22 +81,15 @@
 }
 
 /**
- * put_device - clean up device
+ * put_device - decrement reference count, and clean up when it hits 0
  * @dev:	device in question
- *
- * Decrement reference count for device.
- * If it hits 0, we need to clean it up.
- * However, we may be here in interrupt context, and it may
- * take some time to do proper clean up (removing files, calling
- * back down to device to clean up everything it has).
- * So, we remove it from its parent's list and add it to the list of
- * devices to be cleaned up.
  */
 void put_device(struct device * dev)
 {
 	if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
 		return;
 	list_del_init(&dev->node);
+	list_del_init(&dev->g_list);
 	spin_unlock(&device_lock);
 
 	DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n",
diff -Nru a/drivers/base/power.c b/drivers/base/power.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/base/power.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,128 @@
+/*
+ * power.c - power management functions for the device tree.
+ * 
+ * Copyright (c) 2002 Patrick Mochel
+ *		 2002 Open Source Development Lab
+ * 
+ *  Kai Germaschewski contributed to the list walking routines.
+ *
+ * FIXME: The suspend and shutdown walks are identical. The resume walk
+ * is simply walking the list backward. Anyway we can combine these (cleanly)?
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include "base.h"
+
+/**
+ * device_suspend - suspend all devices on the device tree
+ * @state:	state we're entering
+ * @level:	what stage of the suspend process we're at 
+ * 
+ * The entries in the global device list are inserted such that they're in a 
+ * depth-first ordering. So, simply iterate over the list, and call the driver's
+ * suspend callback for each device.
+ */
+int device_suspend(u32 state, u32 level)
+{
+	struct device * dev;
+	struct device * prev = &device_root;
+	int error = 0;
+
+	printk(KERN_EMERG "Suspending Devices\n");
+
+	get_device(prev);
+
+	spin_lock(&device_lock);
+	dev = g_list_to_dev(prev->g_list.next);
+	while(dev != &device_root && !error) {
+		get_device(dev);
+		spin_unlock(&device_lock);
+		put_device(prev);
+
+		if (dev->driver && dev->driver->suspend)
+			error = dev->driver->suspend(dev,state,level);
+
+		spin_lock(&device_lock);
+		prev = dev;
+		dev = g_list_to_dev(prev->g_list.next);
+	}
+	spin_unlock(&device_lock);
+	put_device(prev);
+
+	return error;
+}
+
+/**
+ * device_resume - resume all the devices in the system
+ * @level:	stage of resume process we're at 
+ * 
+ * Similar to device_suspend above, though we want to do a breadth-first
+ * walk of the tree to make sure we wake up parents before children.
+ * So, we iterate over the list backward. 
+ */
+void device_resume(u32 level)
+{
+	struct device * dev;
+	struct device * prev = &device_root;
+
+	get_device(prev);
+
+	spin_lock(&device_lock);
+	dev = g_list_to_dev(prev->g_list.prev);
+	while(dev != &device_root) {
+		get_device(dev);
+		spin_unlock(&device_lock);
+		put_device(prev);
+
+		if (dev->driver && dev->driver->resume)
+			dev->driver->resume(dev,level);
+
+		spin_lock(&device_lock);
+		prev = dev;
+		dev = g_list_to_dev(prev->g_list.prev);
+	}
+	spin_unlock(&device_lock);
+	put_device(prev);
+
+	printk(KERN_EMERG "Devices Resumed\n");
+}
+
+/**
+ * device_shutdown - queisce all the devices before reboot/shutdown
+ *
+ * Do depth first iteration over device tree, calling ->remove() for each
+ * device. This should ensure the devices are put into a sane state before
+ * we reboot the system.
+ *
+ */
+void device_shutdown(void)
+{
+	struct device * dev;
+	struct device * prev = &device_root;
+
+	printk(KERN_EMERG "Shutting down devices\n");
+
+	get_device(prev);
+
+	spin_lock(&device_lock);
+	dev = g_list_to_dev(prev->g_list.next);
+	while(dev != &device_root) {
+		get_device(dev);
+		spin_unlock(&device_lock);
+		put_device(prev);
+
+		if (dev->driver && dev->driver->remove)
+			dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
+
+		spin_lock(&device_lock);
+		prev = dev;
+		dev = g_list_to_dev(prev->g_list.next);
+	}
+	spin_unlock(&device_lock);
+	put_device(prev);
+}
+
+EXPORT_SYMBOL(device_suspend);
+EXPORT_SYMBOL(device_resume);
+EXPORT_SYMBOL(device_shutdown);
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/base/sys.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,49 @@
+/*
+ * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc)
+ *
+ * Copyright (c) 2002 Patrick Mochel
+ *              2002 Open Source Development Lab
+ * 
+ * This exports a 'system' bus type. 
+ * By default, a 'sys' bus gets added to the root of the system. There will
+ * always be core system devices. Devices can use register_sys_device() to
+ * add themselves as children of the system bus.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+
+static struct device system_bus = {
+       name:           "System Bus",
+       bus_id:         "sys",
+};
+
+int register_sys_device(struct device * dev)
+{
+       int error = -EINVAL;
+
+       if (dev) {
+               if (!dev->parent)
+                       dev->parent = &system_bus;
+               error = device_register(dev);
+       }
+       return error;
+}
+
+void unregister_sys_device(struct device * dev)
+{
+       if (dev)
+               put_device(dev);
+}
+
+static int sys_bus_init(void)
+{
+       return device_register(&system_bus);
+}
+
+subsys_initcall(sys_bus_init);
+EXPORT_SYMBOL(register_sys_device);
+EXPORT_SYMBOL(unregister_sys_device);
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/block/DAC960.c	Sun Apr 14 12:16:59 2002
@@ -5295,7 +5295,7 @@
       DAC960_ComputeGenericDiskInfo(Controller);
       DAC960_RegisterDisk(Controller, LogicalDriveNumber);
     }
-  if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
+  if (Controller->GenericDiskInfo.sizes[minor(Inode->i_rdev)] == 0)
     return -ENXIO;
   /*
     Increment Controller and Logical Drive Usage Counts.
@@ -6902,3 +6902,5 @@
 
 module_init(DAC960_Initialize);
 module_exit(DAC960_Finalize);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/blkpg.c b/drivers/block/blkpg.c
--- a/drivers/block/blkpg.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/block/blkpg.c	Sun Apr 14 12:16:55 2002
@@ -113,6 +113,7 @@
 	g->part[minor].nr_sects = plength;
 	if (g->sizes)
 		g->sizes[minor] = (plength >> (BLOCK_SIZE_BITS - 9));
+	devfs_register_partitions (g, first_minor, 0);
 	return 0;
 }
 
@@ -172,6 +173,7 @@
 	g->part[minor].nr_sects = 0;
 	if (g->sizes)
 		g->sizes[minor] = 0;
+	devfs_register_partitions (g, first_minor, 0);
 	bd_release(bdevp);
 	bdput(bdevp);
 
@@ -213,7 +215,6 @@
 int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
 {
 	request_queue_t *q;
-	struct gendisk *g;
 	u64 ullval = 0;
 	int intval;
 	unsigned short usval;
@@ -236,6 +237,18 @@
 			intval = (is_read_only(dev) != 0);
 			return put_user(intval, (int *)(arg));
 
+		case BLKRASET:
+		case BLKFRASET:
+			if(!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			return blk_set_readahead(dev, arg);
+
+		case BLKRAGET:
+		case BLKFRAGET:
+			if (!arg)
+				return -EINVAL;
+			return put_user(blk_get_readahead(dev), (long *)arg);
+
 		case BLKSECTGET:
 			if ((q = blk_get_queue(dev)) == NULL)
 				return -EINVAL;
@@ -247,25 +260,23 @@
 		case BLKFLSBUF:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			fsync_dev(dev);
-			invalidate_buffers(dev);
+			fsync_bdev(bdev);
+			invalidate_bdev(bdev, 0);
 			return 0;
 
 		case BLKSSZGET:
-			/* get block device sector size as needed e.g. by fdisk */
+			/* get block device hardware sector size */
 			intval = get_hardsect_size(dev);
 			return put_user(intval, (int *) arg);
 
 		case BLKGETSIZE:
+			/* size in sectors, works up to 2 TB */
+			ullval = bdev->bd_inode->i_size;
+			return put_user((unsigned long)(ullval >> 9), (unsigned long *) arg);
 		case BLKGETSIZE64:
-			g = get_gendisk(dev);
-			if (g)
-				ullval = g->part[minor(dev)].nr_sects;
-
-			if (cmd == BLKGETSIZE)
-				return put_user((unsigned long)ullval, (unsigned long *)arg);
-			else
-				return put_user((u64)ullval << 9 , (u64 *)arg);
+			/* size in bytes */
+			ullval = bdev->bd_inode->i_size;
+			return put_user(ullval, (u64 *) arg);
 #if 0
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN)) 
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/block/cciss.c	Sun Apr 14 12:16:59 2002
@@ -42,6 +42,7 @@
 #include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
+#include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 #define DRIVER_NAME "Compaq CISS Driver (v 2.5.0)"
@@ -2033,13 +2034,6 @@
 	int cfg_base_addr_index;
 	int i;
 
-	vendor_id = pdev->vendor;
-	device_id = pdev->device;
-	irq = pdev->irq;
-
-	for(i=0; i<6; i++)
-		addr[i] = pdev->resource[i].start;
-
 	if (pci_enable_device(pdev))
 	{
 		printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
@@ -2050,6 +2044,13 @@
 		printk(KERN_ERR "cciss:  Unable to set DMA mask\n");
 		return(-1);
 	}
+
+	vendor_id = pdev->vendor;
+	device_id = pdev->device;
+	irq = pdev->irq;
+
+	for(i=0; i<6; i++)
+		addr[i] = pdev->resource[i].start;
 
 	(void) pci_read_config_word(pdev, PCI_COMMAND,&command);
 	(void) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
--- a/drivers/block/cciss_scsi.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/block/cciss_scsi.c	Sun Apr 14 12:16:56 2002
@@ -32,6 +32,7 @@
 #include "../scsi/hosts.h" 
 #include <asm/atomic.h>
 #include <linux/timer.h>
+#include <linux/completion.h>
 
 #include "cciss_scsi.h"
 
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/block/elevator.c	Sun Apr 14 12:16:59 2002
@@ -230,12 +230,6 @@
 	elevator_t *e = &q->elevator;
 	int lat = 0, *latency = e->elevator_data;
 
-	/*
-	 * it's a bug to let this rq preempt an already started request
-	 */
-	if (insert_here->next != &q->queue_head)
-		BUG_ON(list_entry_rq(insert_here->next)->flags & REQ_STARTED);
-
 	if (!(rq->flags & REQ_BARRIER))
 		lat = latency[rq_data_dir(rq)];
 
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/block/genhd.c	Sun Apr 14 12:16:58 2002
@@ -22,6 +22,7 @@
 #include <linux/blk.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/seq_file.h>
 
 
 static rwlock_t gendisk_lock;
@@ -142,39 +143,58 @@
 }
 
 #ifdef CONFIG_PROC_FS
-int
-get_partition_list(char *page, char **start, off_t offset, int count)
+/* iterator */
+static void *part_start(struct seq_file *part, loff_t *pos)
 {
-	struct gendisk *gp;
-	char buf[64];
-	int len, n;
+	loff_t k = *pos;
+	struct gendisk *sgp;
 
-	len = sprintf(page, "major minor  #blocks  name\n\n");
 	read_lock(&gendisk_lock);
-	for (gp = gendisk_head; gp; gp = gp->next) {
-		for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
-			if (gp->part[n].nr_sects == 0)
-				continue;
-
-			len += snprintf(page + len, 63,
-					"%4d  %4d %10d %s\n",
-					gp->major, n, gp->sizes[n],
-					disk_name(gp, n, buf));
-			if (len < offset)
-				offset -= len, len = 0;
-			else if (len >= offset + count)
-				goto out;
-		}
+	for (sgp = gendisk_head; sgp; sgp = sgp->next) {
+		if (!k--)
+			return sgp;
 	}
+	return NULL;
+}
 
-out:
+static void *part_next(struct seq_file *part, void *v, loff_t *pos)
+{
+	++*pos;
+	return ((struct gendisk *)v)->next;
+}
+
+static void part_stop(struct seq_file *part, void *v)
+{
 	read_unlock(&gendisk_lock);
-	*start = page + offset;
-	len -= offset;
-	if (len < 0)
-		len = 0;
-	return len > count ? count : len;
 }
+
+static int show_partition(struct seq_file *part, void *v)
+{
+	struct gendisk *sgp = v;
+	int n;
+	char buf[64];
+
+	if (sgp == gendisk_head)
+		seq_puts(part, "major minor  #blocks  name\n\n");
+
+	/* show all non-0 size partitions of this disk */
+	for (n = 0; n < (sgp->nr_real << sgp->minor_shift); n++) {
+		if (sgp->part[n].nr_sects == 0)
+			continue;
+		seq_printf(part, "%4d  %4d %10d %s\n",
+			sgp->major, n, sgp->sizes[n],
+			disk_name(sgp, n, buf));
+	}
+
+	return 0;
+}
+
+struct seq_operations partitions_op = {
+	start:	part_start,
+	next:	part_next,
+	stop:	part_stop,
+	show:	show_partition
+};
 #endif
 
 
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/block/ll_rw_blk.c	Sun Apr 14 12:16:55 2002
@@ -62,7 +62,7 @@
 
 /*
  * blk_size contains the size of all block-devices in units of 1024 byte
- * sectors:
+ * blocks:
  *
  * blk_size[MAJOR][MINOR]
  *
@@ -108,6 +108,47 @@
 		return &blk_dev[major(dev)].request_queue;
 }
 
+/**
+ * blk_set_readahead - set a queue's readahead tunable
+ * @dev:	device
+ * @sectors:	readahead, in 512 byte sectors
+ *
+ * Returns zero on success, else negative errno
+ */
+int blk_set_readahead(kdev_t dev, unsigned sectors)
+{
+	int ret = -EINVAL;
+	request_queue_t *q = blk_get_queue(dev);
+
+	if (q) {
+		q->ra_sectors = sectors;
+		ret = 0;
+	}
+	return ret;
+}
+
+/**
+ * blk_get_readahead - query a queue's readahead tunable
+ * @dev:	device
+ *
+ * Locates the passed device's request queue and returns its
+ * readahead setting.
+ *
+ * The returned value is in units of 512 byte sectors.
+ *
+ * Will return zero if the queue has never had its readahead
+ * setting altered.
+ */
+unsigned blk_get_readahead(kdev_t dev)
+{
+	unsigned ret = 0;
+	request_queue_t *q = blk_get_queue(dev);
+
+	if (q)
+		ret = q->ra_sectors;
+	return ret;
+}
+
 void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn)
 {
 	q->prep_rq_fn = pfn;
@@ -810,7 +851,8 @@
 	q->plug_tq.data		= q;
 	q->queue_flags		= (1 << QUEUE_FLAG_CLUSTER);
 	q->queue_lock		= lock;
-	
+	q->ra_sectors		= 0;		/* Use VM default */
+
 	blk_queue_segment_boundary(q, 0xffffffff);
 
 	blk_queue_make_request(q, __make_request);
@@ -1274,32 +1316,27 @@
  * */
 void generic_make_request(struct bio *bio)
 {
-	int major = major(bio->bi_dev);
-	int minor = minor(bio->bi_dev);
 	request_queue_t *q;
-	sector_t minorsize = 0;
+	sector_t maxsector;
 	int ret, nr_sectors = bio_sectors(bio);
 
 	/* Test device or partition size, when known. */
-	if (blk_size[major])
-		minorsize = blk_size[major][minor];
-	if (minorsize) {
-		unsigned long maxsector = (minorsize << 1) + 1;
-		unsigned long sector = bio->bi_sector;
-
-		if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
-			if (blk_size[major][minor]) {
-				
-				/* This may well happen - the kernel calls
-				 * bread() without checking the size of the
-				 * device, e.g., when mounting a device. */
-				printk(KERN_INFO
-				       "attempt to access beyond end of device\n");
-				printk(KERN_INFO "%s: rw=%ld, want=%ld, limit=%Lu\n",
-				       kdevname(bio->bi_dev), bio->bi_rw,
-				       (sector + nr_sectors)>>1,
-				       (long long) blk_size[major][minor]);
-			}
+	maxsector = (blkdev_size_in_bytes(bio->bi_dev) >> 9);
+	if (maxsector) {
+		sector_t sector = bio->bi_sector;
+
+		if (maxsector < nr_sectors ||
+		    maxsector - nr_sectors < sector) {
+			/* This may well happen - the kernel calls
+			 * bread() without checking the size of the
+			 * device, e.g., when mounting a device. */
+			printk(KERN_INFO
+			       "attempt to access beyond end of device\n");
+			printk(KERN_INFO "%s: rw=%ld, want=%ld, limit=%Lu\n",
+			       kdevname(bio->bi_dev), bio->bi_rw,
+			       sector + nr_sectors,
+			       (long long) maxsector);
+
 			set_bit(BIO_EOF, &bio->bi_flags);
 			goto end_io;
 		}
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/block/loop.c	Sun Apr 14 12:16:54 2002
@@ -36,6 +36,9 @@
  * Al Viro too.
  * Jens Axboe <axboe@suse.de>, Nov 2000
  *
+ * Support up to 256 loop devices
+ * Heinz Mauelshagen <mge@sistina.com>, Feb 2002
+ *
  * Still To Fix:
  * - Advisory locking is ignored here. 
  * - Should use an own CAP_* category instead of CAP_SYS_ADMIN 
@@ -151,14 +154,14 @@
 
 #define MAX_DISK_SIZE 1024*1024*1024
 
-static unsigned long compute_loop_size(struct loop_device *lo, struct dentry * lo_dentry, kdev_t lodev)
+static unsigned long
+compute_loop_size(struct loop_device *lo,
+		  struct dentry * lo_dentry, kdev_t lodev)
 {
-	if (S_ISREG(lo_dentry->d_inode->i_mode))
-		return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS;
-	if (blk_size[major(lodev)])
-		return blk_size[major(lodev)][minor(lodev)] -
-                                (lo->lo_offset >> BLOCK_SIZE_BITS);
-	return MAX_DISK_SIZE;
+	loff_t size = 0;
+
+	size = lo_dentry->d_inode->i_mapping->host->i_size;
+	return (size - lo->lo_offset) >> BLOCK_SIZE_BITS;
 }
 
 static void figure_loop_size(struct loop_device *lo)
@@ -927,7 +930,7 @@
  * And now the modules code and kernel interface.
  */
 MODULE_PARM(max_loop, "i");
-MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-255)");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)");
 MODULE_LICENSE("GPL");
 
 int loop_register_transfer(struct loop_func_table *funcs)
@@ -963,9 +966,9 @@
 {
 	int	i;
 
-	if ((max_loop < 1) || (max_loop > 255)) {
+	if ((max_loop < 1) || (max_loop > 256)) {
 		printk(KERN_WARNING "loop: invalid max_loop (must be between"
-				    " 1 and 255), using default (8)\n");
+				    " 1 and 256), using default (8)\n");
 		max_loop = 8;
 	}
 
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/block/nbd.c	Sun Apr 14 12:16:56 2002
@@ -327,7 +327,7 @@
 		req = CURRENT;
 #ifdef PARANOIA
 		if (!req)
-			FAIL("que not empty but no request?");
+			FAIL("queue not empty but no request?");
 #endif
 		dev = minor(req->rq_dev);
 #ifdef PARANOIA
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/block/rd.c	Sun Apr 14 12:16:55 2002
@@ -156,7 +156,6 @@
 
 	do {
 		int count;
-		struct page ** hash;
 		struct page * page;
 		char * src, * dst;
 		int unlock = 0;
@@ -166,8 +165,7 @@
 			count = size;
 		size -= count;
 
-		hash = page_hash(mapping, index);
-		page = __find_get_page(mapping, index, hash);
+		page = find_get_page(mapping, index);
 		if (!page) {
 			page = grab_cache_page(mapping, index);
 			err = -ENOMEM;
@@ -300,19 +298,13 @@
 			}
 			up(&inode->i_bdev->bd_sem);
 			break;
-         	case BLKGETSIZE:   /* Return device size */
-			if (!arg)
-				break;
-			error = put_user(rd_kbsize[minor] << 1, (unsigned long *) arg);
-			break;
+         	case BLKGETSIZE:
          	case BLKGETSIZE64:
-			error = put_user((u64)rd_kbsize[minor]<<10, (u64*)arg);
-			break;
 		case BLKROSET:
 		case BLKROGET:
 		case BLKSSZGET:
 			error = blk_ioctl(inode->i_bdev, cmd, arg);
-	};
+	}
 out:
 	return error;
 }
@@ -405,9 +397,10 @@
 	for (i = 0 ; i < NUM_RAMDISKS; i++) {
 		struct block_device *bdev = rd_bdev[i];
 		rd_bdev[i] = NULL;
-		if (bdev)
+		if (bdev) {
+			invalidate_bdev(bdev, 1);
 			blkdev_put(bdev, BDEV_FILE);
-		destroy_buffers(mk_kdev(MAJOR_NR, i));
+		}
 	}
 
 	devfs_unregister (devfs_handle);
@@ -418,11 +411,10 @@
 /* This is the registration and initialization section of the RAM disk driver */
 static int __init rd_init (void)
 {
-	int		i;
+	int i;
 
 	if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
-	    (rd_blocksize & (rd_blocksize-1)))
-	{
+	    (rd_blocksize & (rd_blocksize-1))) {
 		printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
 		       rd_blocksize);
 		rd_blocksize = BLOCK_SIZE;
@@ -449,7 +441,8 @@
 			       &rd_bd_op, NULL);
 
 	for (i = 0; i < NUM_RAMDISKS; i++)
-		register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
+		register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op,
+			      rd_size<<1);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* We ought to separate initrd operations here */
@@ -458,10 +451,10 @@
 			INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL);
 #endif
 
-	blksize_size[MAJOR_NR] = rd_blocksizes;		/* Avoid set_blocksize() check */
-	blk_size[MAJOR_NR] = rd_kbsize;			/* Size of the RAM disk in kB  */
+	blksize_size[MAJOR_NR] = rd_blocksizes;	/* Avoid set_blocksize() check */
+	blk_size[MAJOR_NR] = rd_kbsize;		/* Size of the RAM disk in kB  */
 
-		/* rd_size is given in kB */
+	/* rd_size is given in kB */
 	printk("RAMDISK driver initialized: "
 	       "%d RAM disks of %dK size %d blocksize\n",
 	       NUM_RAMDISKS, rd_size, rd_blocksize);
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/cdrom/cdrom.c	Sun Apr 14 12:16:56 2002
@@ -1107,6 +1107,7 @@
 
 	/* Misc */
 	case DVD_INVALIDATE_AGID:
+		cgc.quiet = 1;
 		cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
 		setup_report_key(&cgc, ai->lsa.agid, 0x3f);
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
diff -Nru a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
--- a/drivers/char/acquirewdt.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/char/acquirewdt.c	Sun Apr 14 12:16:55 2002
@@ -17,6 +17,9 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Can't add timeout - driver doesn't allow changing value
  */
 
 #include <linux/config.h>
@@ -50,8 +53,14 @@
 #define WDT_STOP 0x43
 #define WDT_START 0x443
 
-#define WD_TIMO (100*60)		/* 1 minute */
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
 
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 /*
  *	Kernel methods.
@@ -126,10 +135,13 @@
 				spin_unlock(&acq_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
-	 
+
 			acq_is_open=1;
 			inb_p(WDT_START);      
 			spin_unlock(&acq_lock);
@@ -144,9 +156,9 @@
 	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 		spin_lock(&acq_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_STOP);
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_STOP);
+		}
 		acq_is_open=0;
 		spin_unlock(&acq_lock);
 	}
diff -Nru a/drivers/char/advantechwdt.c b/drivers/char/advantechwdt.c
--- a/drivers/char/advantechwdt.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/char/advantechwdt.c	Sun Apr 14 12:16:57 2002
@@ -20,6 +20,9 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  */
 
 #include <linux/config.h>
@@ -56,8 +59,7 @@
  *	the manual says WDT_STOP is 0x43, not 0x443).
  *	(0x43 is also a write-only control register for the 8254 timer!)
  *
- *	TODO: module parameters to set the I/O port addresses and NOWAYOUT
- *	option at load time.
+ *	TODO: module parameters to set the I/O port addresses
  */
  
 #define WDT_STOP 0x443
@@ -65,6 +67,19 @@
 
 #define WD_TIMO 60		/* 1 minute */
 
+static int timeout = WD_TIMO;	/* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); 
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /*
  *	Kernel methods.
  */
@@ -73,7 +88,7 @@
 advwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(timeout, WDT_START);
 }
 
 static ssize_t
@@ -135,6 +150,9 @@
 				spin_unlock(&advwdt_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -153,9 +171,9 @@
 {
 	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&advwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_STOP);
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_STOP);
+		}
 		advwdt_is_open = 0;
 		spin_unlock(&advwdt_lock);
 	}
@@ -207,11 +225,21 @@
 	0
 };
 
+static void __init
+advwdt_validate_timeout(void)
+{
+	if (timeout < 1 || timeout > 63) {
+		timeout = WD_TIMO;
+		printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout);
+	}
+}
+
 static int __init
 advwdt_init(void)
 {
 	printk("WDT driver for Advantech single board computer initialising.\n");
 
+	advwdt_validate_timeout();
 	spin_lock_init(&advwdt_lock);
 	misc_register(&advwdt_miscdev);
 #if WDT_START != WDT_STOP
diff -Nru a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
--- a/drivers/char/agp/agpgart_be.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/agp/agpgart_be.c	Sun Apr 14 12:16:56 2002
@@ -397,7 +397,7 @@
 static void agp_generic_agp_enable(u32 mode)
 {
 	struct pci_dev *device = NULL;
-	u32 command, scratch, cap_id;
+	u32 command, scratch; 
 	u8 cap_ptr;
 
 	pci_read_config_dword(agp_bridge.dev,
@@ -410,34 +410,8 @@
 	 */
 
 
-	pci_for_each_dev(device)
-	{
-		/*
-		 *	Enable AGP devices. Most will be VGA display but
-		 *	some may be coprocessors on non VGA devices too
-		 */
-		 
-		if((((device->class >> 16) & 0xFF) != PCI_BASE_CLASS_DISPLAY) &&
-			(device->class != (PCI_CLASS_PROCESSOR_CO << 8)))
-			continue;
-
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
-		if (cap_ptr != 0x00) {
-			do {
-				pci_read_config_dword(device,
-						      cap_ptr, &cap_id);
-
-				if ((cap_id & 0xff) != 0x02)
-					cap_ptr = (cap_id >> 8) & 0xff;
-			}
-			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-		}
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00) {
 			/*
 			 * Ok, here we have a AGP device. Disable impossible 
@@ -506,25 +480,8 @@
 	 *        command registers.
 	 */
 
-	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
-					device)) != NULL) {
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
-		if (cap_ptr != 0x00) {
-			do {
-				pci_read_config_dword(device,
-						      cap_ptr, &cap_id);
-
-				if ((cap_id & 0xff) != 0x02)
-					cap_ptr = (cap_id >> 8) & 0xff;
-			}
-			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-		}
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00)
 			pci_write_config_dword(device, cap_ptr + 8, command);
 	}
@@ -809,9 +766,9 @@
 	struct page * page;
 	
 	page = alloc_page(GFP_KERNEL);
-	if (page == NULL) {
+	if (page == NULL)
 		return 0;
-	}
+
 	get_page(page);
 	LockPage(page);
 	atomic_inc(&agp_bridge.current_memory_agp);
@@ -823,10 +780,9 @@
 	void *pt = (void *) addr;
 	struct page *page;
 
-	if (pt == NULL) {
+	if (pt == NULL)
 		return;
-	}
-	
+
 	page = virt_to_page(pt);
 	put_page(page);
 	UnlockPage(page);
@@ -3318,24 +3274,8 @@
 	 */
 
 
-	pci_for_each_dev(device)
-	{
-		/*
-		 *	Enable AGP devices. Most will be VGA display but
-		 *	some may be coprocessors on non VGA devices too
-		 */
-		 
-		if((((device->class >> 16) & 0xFF) != PCI_BASE_CLASS_DISPLAY) &&
-			(device->class != (PCI_CLASS_PROCESSOR_CO << 8)))
-			continue;
-
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00) {
 			do {
 				pci_read_config_dword(device,
@@ -3413,25 +3353,8 @@
 	 *        command registers.
 	 */
 
-	while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8,
-					device)) != NULL) {
-		pci_read_config_dword(device, 0x04, &scratch);
-
-		if (!(scratch & 0x00100000))
-			continue;
-
-		pci_read_config_byte(device, 0x34, &cap_ptr);
-
-		if (cap_ptr != 0x00) {
-			do {
-				pci_read_config_dword(device,
-						      cap_ptr, &cap_id);
-
-				if ((cap_id & 0xff) != 0x02)
-					cap_ptr = (cap_id >> 8) & 0xff;
-			}
-			while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-		}
+	pci_for_each_dev(device) {
+		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
 		if (cap_ptr != 0x00)
 			pci_write_config_dword(device, cap_ptr + 8, command);
 	}
@@ -3881,7 +3804,6 @@
 {
 	struct pci_dev *dev = NULL;
 	u8 cap_ptr = 0x00;
-	u32 cap_id, scratch;
 
 	if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL)
 		return -ENODEV;
@@ -4022,20 +3944,7 @@
 #endif	/* CONFIG_AGP_SWORKS */
 
 	/* find capndx */
-	pci_read_config_dword(dev, 0x04, &scratch);
-	if (!(scratch & 0x00100000))
-		return -ENODEV;
-
-	pci_read_config_byte(dev, 0x34, &cap_ptr);
-	if (cap_ptr != 0x00) {
-		do {
-			pci_read_config_dword(dev, cap_ptr, &cap_id);
-
-			if ((cap_id & 0xff) != 0x02)
-				cap_ptr = (cap_id >> 8) & 0xff;
-		}
-		while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
-	}
+	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
 	if (cap_ptr == 0x00)
 		return -ENODEV;
 	agp_bridge.capndx = cap_ptr;
diff -Nru a/drivers/char/applicom.c b/drivers/char/applicom.c
--- a/drivers/char/applicom.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/char/applicom.c	Sun Apr 14 12:16:59 2002
@@ -36,7 +36,7 @@
 
 #if LINUX_VERSION_CODE < 0x20300 
 /* These probably want adding to <linux/compatmac.h> */
-#define init_waitqueue_head(x) do { *(x) = NULL; } while (0);
+#define init_waitqueue_head(x) do { *(x) = NULL; } while (0)
 #define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
 #define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x
 #define __setup(x,y) /* */
diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c
--- a/drivers/char/cyclades.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/cyclades.c	Sun Apr 14 12:16:56 2002
@@ -4965,6 +4965,8 @@
   uclong		Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
   uclong		Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
   unsigned char         Ze_irq[NR_CARDS];
+  struct resource *resource;
+  unsigned long res_start, res_len;
 
         for (i = 0; i < NR_CARDS; i++) {
                 /* look for a Cyclades card by vendor and device id */
@@ -5012,7 +5014,15 @@
 		/* Although we don't use this I/O region, we should
 		   request it from the kernel anyway, to avoid problems
 		   with other drivers accessing it. */
-		request_region(cy_pci_phys1, CyPCI_Yctl, "Cyclom-Y");
+		resource = request_region(cy_pci_phys1,
+					CyPCI_Yctl, "Cyclom-Y");
+		if (resource == NULL) {
+			printk(KERN_ERR "cyclades: failed to allocate IO "
+					"resource at 0x%lx\n", cy_pci_phys1);
+			continue;
+		}
+		res_start = cy_pci_phys1;
+		res_len = CyPCI_Yctl;
 
 #if defined(__alpha__)
                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
@@ -5083,7 +5093,11 @@
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
                 cy_card[j].num_chips = cy_pci_nchan/4;
-
+		cy_card[j].resource = resource;
+		cy_card[j].res_start = res_start;
+		cy_card[j].res_len = res_len;
+		resource = NULL;	/* For next card */
+	
                 /* enable interrupts in the PCI interface */
 		plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
 		switch (plx_ver) {
@@ -5162,8 +5176,16 @@
 		/* Although we don't use this I/O region, we should
 		   request it from the kernel anyway, to avoid problems
 		   with other drivers accessing it. */
-		request_region(cy_pci_phys1, CyPCI_Zctl, "Cyclades-Z");
-
+		resource = request_region(cy_pci_phys1,
+				CyPCI_Zctl, "Cyclades-Z");
+		if (resource == NULL) {
+			printk(KERN_ERR "cyclades: failed ot allocate IO resource "
+					"at 0x%lx\n", cy_pci_phys1);
+			continue;
+		}
+		res_start = cy_pci_phys1;
+		res_len = CyPCI_Zctl;
+	
 		if (mailbox == ZE_V1) {
 		    cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win);
 		    if (ZeIndex == NR_CARDS) {
@@ -5261,6 +5283,10 @@
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
                 cy_card[j].num_chips = -1;
+		cy_card[j].resource = resource;
+		cy_card[j].res_start = res_start;
+		cy_card[j].res_len = res_len;
+		resource = NULL;	/* For next card */
 
                 /* print message */
 #ifdef CONFIG_CYZ_INTR
@@ -5279,7 +5305,7 @@
                 printk("%d channels starting from port %d.\n",
 		    cy_pci_nchan,cy_next_channel);
                 cy_next_channel += cy_pci_nchan;
-    }
+	    }
         }
 
         for (; ZeIndex != 0 && i < NR_CARDS; i++) {
@@ -5787,6 +5813,8 @@
 #endif /* CONFIG_CYZ_INTR */
 	    )
 		free_irq(cy_card[i].irq, &cy_card[i]);
+		if (cy_card[i].resource)
+			release_region(cy_card[i].res_start, cy_card[i].res_len);
         }
     }
     if (tmp_buf) {
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/char/drm/i810_dma.c	Sun Apr 14 12:16:57 2002
@@ -73,7 +73,7 @@
 	*(volatile unsigned int *)(virt + outring) = n;			\
 	outring += 4;							\
 	outring &= ringmask;						\
-} while (0);
+} while (0)
 
 static inline void i810_print_status_page(drm_device_t *dev)
 {
diff -Nru a/drivers/char/ds1620.c b/drivers/char/ds1620.c
--- a/drivers/char/ds1620.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/char/ds1620.c	Sun Apr 14 12:16:55 2002
@@ -348,7 +348,7 @@
 	&ds1620_fops
 };
 
-int __init ds1620_init(void)
+static int __init ds1620_init(void)
 {
 	int ret;
 	struct therm th, th_start;
@@ -400,7 +400,7 @@
 	return 0;
 }
 
-void __exit ds1620_exit(void)
+static void __exit ds1620_exit(void)
 {
 #ifdef THERM_USE_PROC
 	remove_proc_entry("therm", NULL);
diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c
--- a/drivers/char/esp.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/char/esp.c	Sun Apr 14 12:16:54 2002
@@ -2161,7 +2161,7 @@
 		if (signal_pending(current))
 			break;
 
-		if (timeout && ((orig_jiffies + timeout) < jiffies))
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
 			break;
 
 		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
diff -Nru a/drivers/char/eurotechwdt.c b/drivers/char/eurotechwdt.c
--- a/drivers/char/eurotechwdt.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/eurotechwdt.c	Sun Apr 14 12:16:56 2002
@@ -20,6 +20,10 @@
  *      "AS-IS" and at no charge.
  *
  *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>*
+ *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  */
 
 #include <linux/config.h>
@@ -45,7 +49,6 @@
 #include <linux/smp_lock.h>
 
 static int eurwdt_is_open;
-static int eurwdt_timeout; 
 static spinlock_t eurwdt_lock;
  
 /*
@@ -58,6 +61,18 @@
 static char *ev = "int";
  
 #define WDT_TIMEOUT		60                /* 1 minute */
+static int timeout = WDT_TIMEOUT;
+
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)"); 
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 
 /*
@@ -116,6 +131,15 @@
  *      Programming support
  */
 
+static void __init eurwdt_validate_timeout(void)
+{
+	if (timeout < 0 || timeout > 255) {
+		timeout = WDT_TIMEOUT;
+		printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n",
+		       timeout);
+	}
+}
+
 static inline void eurwdt_write_reg(u8 index, u8 data)
 {
    outb(index, io);
@@ -189,7 +213,7 @@
 static void eurwdt_ping(void)
 {
    /* Write the watchdog default value */
-   eurwdt_set_timeout(eurwdt_timeout);
+   eurwdt_set_timeout(timeout);
 }
  
 /**
@@ -263,7 +287,7 @@
          if (time < 0 || time > 255)
             return -EINVAL;
 
-         eurwdt_timeout = time; 
+         timeout = time; 
          eurwdt_set_timeout(time); 
          return 0;
    }
@@ -287,9 +311,11 @@
             spin_unlock(&eurwdt_lock);
             return -EBUSY;
          }
+	 if (nowayout) {
+		 MOD_INC_USE_COUNT;
+	 }
 
          eurwdt_is_open = 1;
-         eurwdt_timeout = WDT_TIMEOUT;   /* initial timeout */
 
          /* Activate the WDT */
          eurwdt_activate_timer(); 
@@ -323,12 +349,12 @@
 static int eurwdt_release(struct inode *inode, struct file *file)
 {
    if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-      eurwdt_disable_timer();
-#endif
-      eurwdt_is_open = 0;
+	   if (!nowayout) {
+		   eurwdt_disable_timer();
+	   }
+	   eurwdt_is_open = 0;
 
-      MOD_DEC_USE_COUNT;
+	   MOD_DEC_USE_COUNT;
    }
 
    return 0;
@@ -422,7 +448,8 @@
 static int __init eurwdt_init(void)
 {
    int ret;
- 
+
+   eurwdt_validate_timeout();
    ret = misc_register(&eurwdt_miscdev);
    if (ret) {
       printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
diff -Nru a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c
--- a/drivers/char/i810-tco.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/char/i810-tco.c	Sun Apr 14 12:16:54 2002
@@ -1,5 +1,5 @@
 /*
- *	i810-tco 0.02:	TCO timer driver for i810 chipsets
+ *	i810-tco 0.03:	TCO timer driver for i810 chipsets
  *
  *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
  *				http://www.kernelconcepts.de
@@ -28,6 +28,9 @@
  *	Initial Version 0.01
  *  20000728 Nils Faerber
  *      0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
+ *  20011214 Matt Domsch <Matt_Domsch@dell.com>
+ *      0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Didn't add timeout option as i810_margin already exists.
  */
  
 #include <linux/module.h>
@@ -60,6 +63,18 @@
 static int i810_margin = TIMER_MARGIN;	/* steps of 0.6sec */
 
 MODULE_PARM (i810_margin, "i");
+MODULE_PARM_DESC(i810_margin, "Watchdog timeout in steps of 0.6sec, 2<n<64. Default = 50 (30 seconds)");
+
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 
 /*
  *	Timer active flag
@@ -167,6 +182,9 @@
 	if (timer_alive)
 		return -EBUSY;
 
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *      Reload and activate timer
 	 */
@@ -181,10 +199,10 @@
 	/*
 	 *      Shut off the timer.
 	 */
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-	tco_timer_stop ();
-	timer_alive = 0;
-#endif	
+	if (nowayout) {
+		tco_timer_stop ();
+		timer_alive = 0;
+	}
 	return 0;
 }
 
@@ -342,8 +360,8 @@
 	tco_timer_reload ();
 
 	printk (KERN_INFO
-		"i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
-		(int) (i810_margin * 6 / 10), TCOBASE);
+		"i810 TCO timer: V0.03, timer margin: %d sec (0x%04x), nowayout: %d\n",
+		(int) (i810_margin * 6 / 10), TCOBASE, nowayout);
 	return 0;
 }
 
diff -Nru a/drivers/char/i810_rng.c b/drivers/char/i810_rng.c
--- a/drivers/char/i810_rng.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/char/i810_rng.c	Sun Apr 14 12:16:58 2002
@@ -35,7 +35,7 @@
 /*
  * core module and version information
  */
-#define RNG_VERSION "0.9.6"
+#define RNG_VERSION "0.9.7"
 #define RNG_MODULE_NAME "i810_rng"
 #define RNG_DRIVER_NAME   RNG_MODULE_NAME " hardware driver " RNG_VERSION
 #define PFX RNG_MODULE_NAME ": "
@@ -334,7 +334,8 @@
 static struct pci_device_id rng_pci_tbl[] __initdata = {
 	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0x8086, 0x1130, PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
diff -Nru a/drivers/char/ib700wdt.c b/drivers/char/ib700wdt.c
--- a/drivers/char/ib700wdt.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/char/ib700wdt.c	Sun Apr 14 12:16:57 2002
@@ -25,6 +25,10 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Added timeout module option to override default
+ * 
  */
 
 #include <linux/config.h>
@@ -92,15 +96,36 @@
 
 #define WD_TIMO 0		/* 30 seconds +/- 20%, from table */
 
+static int timeout_val = WD_TIMO;	/* value in table */
+static int timeout = 30;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /*
  *	Kernel methods.
  */
 
+static void __init
+ibwdt_validate_timeout(void)
+{
+	timeout_val = (30 - timeout) / 2;
+	if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO;
+}
+
 static void
 ibwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(WD_TIMO, WDT_START);
+	outb_p(timeout_val, WDT_START);
 }
 
 static ssize_t
@@ -162,6 +187,9 @@
 				spin_unlock(&ibwdt_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate
 			 */
@@ -181,9 +209,9 @@
 	lock_kernel();
 	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&ibwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		outb_p(WD_TIMO, WDT_STOP);
-#endif
+		if (!nowayout) {
+			outb_p(timeout_val, WDT_STOP);
+		}
 		ibwdt_is_open = 0;
 		spin_unlock(&ibwdt_lock);
 	}
@@ -201,7 +229,7 @@
 {
 	if (code == SYS_DOWN || code == SYS_HALT) {
 		/* Turn the WDT off */
-		outb_p(WD_TIMO, WDT_STOP);
+		outb_p(timeout_val, WDT_STOP);
 	}
 	return NOTIFY_DONE;
 }
@@ -241,6 +269,7 @@
 {
 	printk("WDT driver for IB700 single board computer initialising.\n");
 
+	ibwdt_validate_timeout();
 	spin_lock_init(&ibwdt_lock);
 	misc_register(&ibwdt_miscdev);
 #if WDT_START != WDT_STOP
diff -Nru a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
--- a/drivers/char/ip2/i2lib.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/char/ip2/i2lib.c	Sun Apr 14 12:16:58 2002
@@ -1330,7 +1330,7 @@
 
 	// if expires == 0 then timer poped, then do not need to del_timer
 	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
-				(pCh->BookmarkTimer.expires > jiffies)) {
+	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
 		del_timer( &(pCh->BookmarkTimer) );
 		pCh->BookmarkTimer.expires = 0;
 
diff -Nru a/drivers/char/machzwd.c b/drivers/char/machzwd.c
--- a/drivers/char/machzwd.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/machzwd.c	Sun Apr 14 12:16:56 2002
@@ -24,6 +24,8 @@
  *  a system RESET and it starts wd#2 that unconditionaly will RESET 
  *  the system when the counter reaches zero.
  *
+ *  14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 
 #include <linux/config.h>
@@ -103,6 +105,15 @@
 MODULE_PARM(action, "i");
 MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
 
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 #define PFX "machzwd"
 
 static struct watchdog_info zf_info = {
@@ -307,23 +318,23 @@
  * no need to check for close confirmation
  * no way to disable watchdog ;)
  */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		size_t ofs;
-
-		/* 
-		 * note: just in case someone wrote the magic character
-		 * five months ago...
-		 */
-		zf_expect_close = 0;
-
-		/* now scan */
-		for(ofs = 0; ofs != count; ofs++){
-			if(buf[ofs] == 'V'){
-				zf_expect_close = 1;
-				dprintk("zf_expect_close 1\n");
+		if (!nowayout) {
+			size_t ofs;
+			
+			/* 
+			 * note: just in case someone wrote the magic character
+			 * five months ago...
+			 */
+			zf_expect_close = 0;
+			
+			/* now scan */
+			for(ofs = 0; ofs != count; ofs++){
+				if(buf[ofs] == 'V'){
+					zf_expect_close = 1;
+					dprintk("zf_expect_close 1\n");
+				}
 			}
 		}
-#endif
 		/*
 		 * Well, anyhow someone wrote to us,
 		 * we should return that favour
@@ -386,9 +397,9 @@
 				return -EBUSY;
 			}
 
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-			MOD_INC_USE_COUNT;
-#endif
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			zf_is_open = 1;
 
 			spin_unlock(&zf_lock);
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/char/mem.c	Sun Apr 14 12:16:59 2002
@@ -173,10 +173,10 @@
 	 * caching for the high addresses through the KEN pin, but
 	 * we maintain the tradition of paranoia in this code.
 	 */
- 	return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ||
-		  test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ||
-		  test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ||
-		  test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) )
+ 	return !( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) ||
+		  test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) ||
+		  test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) ||
+		  test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) )
 	  && addr >= __pa(high_memory);
 #else
 	return addr >= __pa(high_memory);
diff -Nru a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c
--- a/drivers/char/mixcomwd.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/mixcomwd.c	Sun Apr 14 12:16:56 2002
@@ -27,10 +27,13 @@
  *
  * Version 0.4 (99/11/15):
  *		- support for one more type board
+ *
+ * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
+ *              - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  *	
  */
 
-#define VERSION "0.4" 
+#define VERSION "0.5" 
   
 #include <linux/module.h>
 #include <linux/config.h>
@@ -57,26 +60,30 @@
 static long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
-
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
 static int mixcomwd_timer_alive;
 static struct timer_list mixcomwd_timer;
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
 #endif
 
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 static void mixcomwd_ping(void)
 {
 	outb_p(55,watchdog_port);
 	return;
 }
 
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
 static void mixcomwd_timerfun(unsigned long d)
 {
 	mixcomwd_ping();
 	
 	mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
 }
-#endif
 
 /*
  *	Allow only one person to hold it open
@@ -89,31 +96,32 @@
 	}
 	mixcomwd_ping();
 	
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		del_timer(&mixcomwd_timer);
-		mixcomwd_timer_alive=0;
-	} 
-#endif
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	} else {
+		if(mixcomwd_timer_alive) {
+			del_timer(&mixcomwd_timer);
+			mixcomwd_timer_alive=0;
+		}
+	}
 	return 0;
 }
 
 static int mixcomwd_release(struct inode *inode, struct file *file)
 {
 
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		printk(KERN_ERR "mixcomwd: release called while internal timer alive");
-		return -EBUSY;
+	if (!nowayout) {
+		if(mixcomwd_timer_alive) {
+			printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+			return -EBUSY;
+		}
+		init_timer(&mixcomwd_timer);
+		mixcomwd_timer.expires=jiffies + 5 * HZ;
+		mixcomwd_timer.function=mixcomwd_timerfun;
+		mixcomwd_timer.data=0;
+		mixcomwd_timer_alive=1;
+		add_timer(&mixcomwd_timer);
 	}
-	init_timer(&mixcomwd_timer);
-	mixcomwd_timer.expires=jiffies + 5 * HZ;
-	mixcomwd_timer.function=mixcomwd_timerfun;
-	mixcomwd_timer.data=0;
-	mixcomwd_timer_alive=1;
-	add_timer(&mixcomwd_timer);
-#endif
-
 	clear_bit(0,&mixcomwd_opened);
 	return 0;
 }
@@ -145,9 +153,9 @@
 	{
 		case WDIOC_GETSTATUS:
 			status=mixcomwd_opened;
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-			status|=mixcomwd_timer_alive;
-#endif
+			if (!nowayout) {
+				status|=mixcomwd_timer_alive;
+			}
 			if (copy_to_user((int *)arg, &status, sizeof(int))) {
 				return -EFAULT;
 			}
@@ -252,14 +260,14 @@
 
 static void __exit mixcomwd_exit(void)
 {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
-			" probably reboot!\n");
-		del_timer(&mixcomwd_timer);
-		mixcomwd_timer_alive=0;
+	if (!nowayout) {
+		if(mixcomwd_timer_alive) {
+			printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
+			       " probably reboot!\n");
+			del_timer(&mixcomwd_timer);
+			mixcomwd_timer_alive=0;
+		}
 	}
-#endif
 	release_region(watchdog_port,1);
 	misc_deregister(&mixcomwd_miscdev);
 }
diff -Nru a/drivers/char/mxser.c b/drivers/char/mxser.c
--- a/drivers/char/mxser.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/char/mxser.c	Sun Apr 14 12:16:59 2002
@@ -32,6 +32,9 @@
  *      version         : 1.2 
  *      
  *    Fixes for C104H/PCI by Tim Hockin <thockin@sun.com>
+ *    Added support for: C102, CI-132, CI-134, CP-132, CP-114, CT-114 cards
+ *                        by Damian Wrobel <dwrobel@ertel.com.pl>
+ *
  */
 
 #include <linux/config.h>
@@ -61,7 +64,7 @@
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
-#define		MXSER_VERSION			"1.2"
+#define		MXSER_VERSION			"1.2.1"
 
 #define		MXSERMAJOR	 	174
 #define		MXSERCUMAJOR		175
@@ -114,10 +117,22 @@
 #ifndef PCI_DEVICE_ID_C104
 #define PCI_DEVICE_ID_C104	0x1040
 #endif
+#ifndef PCI_DEVICE_ID_CP132
+#define PCI_DEVICE_ID_CP132	0x1320
+#endif
+#ifndef PCI_DEVICE_ID_CP114
+#define PCI_DEVICE_ID_CP114	0x1141
+#endif
+#ifndef PCI_DEVICE_ID_CT114
+#define PCI_DEVICE_ID_CT114	0x1140
+#endif
 
 #define C168_ASIC_ID    1
 #define C104_ASIC_ID    2
+#define CI134_ASIC_ID   3
+#define CI132_ASIC_ID   4
 #define CI104J_ASIC_ID  5
+#define C102_ASIC_ID	0xB
 
 enum {
 	MXSER_BOARD_C168_ISA = 0,
@@ -125,6 +140,12 @@
 	MXSER_BOARD_CI104J,
 	MXSER_BOARD_C168_PCI,
 	MXSER_BOARD_C104_PCI,
+	MXSER_BOARD_C102_ISA,
+	MXSER_BOARD_CI132,
+	MXSER_BOARD_CI134,
+	MXSER_BOARD_CP132_PCI,
+	MXSER_BOARD_CP114_PCI,
+	MXSER_BOARD_CT114_PCI
 };
 
 static char *mxser_brdname[] =
@@ -134,6 +155,12 @@
 	"CI-104J series",
 	"C168H/PCI series",
 	"C104H/PCI series",
+	"C102 series",
+	"CI-132 series",
+	"CI-134 series",
+	"CP-132 series",
+	"CP-114 series",
+	"CT-114 series"
 };
 
 static int mxser_numports[] =
@@ -143,6 +170,12 @@
 	4,
 	8,
 	4,
+	2,
+	2,
+	4,
+	2,
+	4,
+	4
 };
 
 /*
@@ -163,6 +196,12 @@
 	  MXSER_BOARD_C168_PCI },
 	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
 	  MXSER_BOARD_C104_PCI },
+	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  MXSER_BOARD_CP132_PCI },
+	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  MXSER_BOARD_CP114_PCI },
+	{ PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  MXSER_BOARD_CT114_PCI },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -613,38 +652,35 @@
 		n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
 		index = 0;
 		for (b = 0; b < n; b++) {
-			pdev = pci_find_device(mxser_pcibrds[b].vendor,
-					       mxser_pcibrds[b].device, pdev);
-			if (!pdev || pci_enable_device(pdev))
-				continue;
-			hwconf.pdev = pdev;
-			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
-				mxser_brdname[mxser_pcibrds[b].driver_data],
-				pdev->bus->number, PCI_SLOT(pdev->devfn));
-			if (m >= MXSER_BOARDS) {
-				printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
-			} else {
-				retval = mxser_get_PCI_conf(pdev,
-				   mxser_pcibrds[b].driver_data, &hwconf);
-				if (retval < 0) {
-					if (retval == MXSER_ERR_IRQ)
-						printk("Invalid interrupt number,board not configured\n");
-					else if (retval == MXSER_ERR_IRQ_CONFLIT)
-						printk("Invalid interrupt number,board not configured\n");
-					else if (retval == MXSER_ERR_VECTOR)
-						printk("Invalid interrupt vector,board not configured\n");
-					else if (retval == MXSER_ERR_IOADDR)
-						printk("Invalid I/O address,board not configured\n");
+			while (pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev)) 
+			{
+				if (pci_enable_device(pdev))
 					continue;
-
+				hwconf.pdev = pdev;
+				printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
+					mxser_brdname[mxser_pcibrds[b].driver_data],
+				pdev->bus->number, PCI_SLOT(pdev->devfn));
+				if (m >= MXSER_BOARDS) {
+					printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
+				} else {
+					retval = mxser_get_PCI_conf(pdev, mxser_pcibrds[b].driver_data, &hwconf);
+					if (retval < 0) {
+						if (retval == MXSER_ERR_IRQ)
+							printk("Invalid interrupt number,board not configured\n");
+						else if (retval == MXSER_ERR_IRQ_CONFLIT)
+							printk("Invalid interrupt number,board not configured\n");	
+						else if (retval == MXSER_ERR_VECTOR)
+							printk("Invalid interrupt vector,board not configured\n");
+						else if (retval == MXSER_ERR_IOADDR)
+							printk("Invalid I/O address,board not configured\n");
+						continue;
+					}
+					if (mxser_initbrd(m, &hwconf) < 0)
+						continue;
+					mxser_getcfg(m, &hwconf);
+					m++;
 				}
-				if (mxser_initbrd(m, &hwconf) < 0)
-					continue;
-				mxser_getcfg(m, &hwconf);
-				m++;
-
 			}
-
 		}
 	}
 #endif
@@ -2306,6 +2342,12 @@
 		hwconf->board_type = MXSER_BOARD_C168_ISA;
 	else if (id == C104_ASIC_ID)
 		hwconf->board_type = MXSER_BOARD_C104_ISA;
+	else if (id == C102_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_C102_ISA;
+	else if (id == CI132_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_CI132;
+	else if (id == CI134_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_CI134;
 	else if (id == CI104J_ASIC_ID)
 		hwconf->board_type = MXSER_BOARD_CI104J;
 	else
@@ -2417,7 +2459,8 @@
 	(void) inb(port);
 	restore_flags(flags);
 	id = inb(port + 1) & 0x1F;
-	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID))
+	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID) &&
+		(id != C102_ASIC_ID) &&	(id != CI132_ASIC_ID) && (id != CI134_ASIC_ID))
 		return (-1);
 	for (i = 0, j = 0; i < 4; i++) {
 		n = inb(port + 2);
diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c
--- a/drivers/char/n_tty.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/char/n_tty.c	Sun Apr 14 12:16:54 2002
@@ -538,7 +538,7 @@
 	 * handle specially, do shortcut processing to speed things
 	 * up.
 	 */
-	if (!test_bit(c, &tty->process_char_map) || tty->lnext) {
+	if (!test_bit(c, tty->process_char_map) || tty->lnext) {
 		finish_erasing(tty);
 		tty->lnext = 0;
 		if (L_ECHO(tty)) {
@@ -659,7 +659,7 @@
 
 		handle_newline:
 			spin_lock_irqsave(&tty->read_lock, flags);
-			set_bit(tty->read_head, &tty->read_flags);
+			set_bit(tty->read_head, tty->read_flags);
 			put_tty_queue_nolock(c, tty);
 			tty->canon_head = tty->read_head;
 			tty->canon_data++;
@@ -811,38 +811,38 @@
 		memset(tty->process_char_map, 0, 256/8);
 
 		if (I_IGNCR(tty) || I_ICRNL(tty))
-			set_bit('\r', &tty->process_char_map);
+			set_bit('\r', tty->process_char_map);
 		if (I_INLCR(tty))
-			set_bit('\n', &tty->process_char_map);
+			set_bit('\n', tty->process_char_map);
 
 		if (L_ICANON(tty)) {
-			set_bit(ERASE_CHAR(tty), &tty->process_char_map);
-			set_bit(KILL_CHAR(tty), &tty->process_char_map);
-			set_bit(EOF_CHAR(tty), &tty->process_char_map);
-			set_bit('\n', &tty->process_char_map);
-			set_bit(EOL_CHAR(tty), &tty->process_char_map);
+			set_bit(ERASE_CHAR(tty), tty->process_char_map);
+			set_bit(KILL_CHAR(tty), tty->process_char_map);
+			set_bit(EOF_CHAR(tty), tty->process_char_map);
+			set_bit('\n', tty->process_char_map);
+			set_bit(EOL_CHAR(tty), tty->process_char_map);
 			if (L_IEXTEN(tty)) {
 				set_bit(WERASE_CHAR(tty),
-					&tty->process_char_map);
+					tty->process_char_map);
 				set_bit(LNEXT_CHAR(tty),
-					&tty->process_char_map);
+					tty->process_char_map);
 				set_bit(EOL2_CHAR(tty),
-					&tty->process_char_map);
+					tty->process_char_map);
 				if (L_ECHO(tty))
 					set_bit(REPRINT_CHAR(tty),
-						&tty->process_char_map);
+						tty->process_char_map);
 			}
 		}
 		if (I_IXON(tty)) {
-			set_bit(START_CHAR(tty), &tty->process_char_map);
-			set_bit(STOP_CHAR(tty), &tty->process_char_map);
+			set_bit(START_CHAR(tty), tty->process_char_map);
+			set_bit(STOP_CHAR(tty), tty->process_char_map);
 		}
 		if (L_ISIG(tty)) {
-			set_bit(INTR_CHAR(tty), &tty->process_char_map);
-			set_bit(QUIT_CHAR(tty), &tty->process_char_map);
-			set_bit(SUSP_CHAR(tty), &tty->process_char_map);
+			set_bit(INTR_CHAR(tty), tty->process_char_map);
+			set_bit(QUIT_CHAR(tty), tty->process_char_map);
+			set_bit(SUSP_CHAR(tty), tty->process_char_map);
 		}
-		clear_bit(__DISABLED_CHAR, &tty->process_char_map);
+		clear_bit(__DISABLED_CHAR, tty->process_char_map);
 		sti();
 		tty->raw = 0;
 		tty->real_raw = 0;
@@ -1058,7 +1058,7 @@
  				int eol;
 
 				eol = test_and_clear_bit(tty->read_tail,
-						&tty->read_flags);
+						tty->read_flags);
 				c = tty->read_buf[tty->read_tail];
 				spin_lock_irqsave(&tty->read_lock, flags);
 				tty->read_tail = ((tty->read_tail+1) &
diff -Nru a/drivers/char/nwflash.c b/drivers/char/nwflash.c
--- a/drivers/char/nwflash.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/char/nwflash.c	Sun Apr 14 12:16:58 2002
@@ -672,7 +672,7 @@
 	if (machine_is_netwinder()) {
 		int id;
 
-		FLASH_BASE = __ioremap(DC21285_FLASH, KFLASH_SIZE4, 0);
+		FLASH_BASE = ioremap(DC21285_FLASH, KFLASH_SIZE4);
 		if (!FLASH_BASE)
 			goto out;
 
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/char/random.c	Sun Apr 14 12:16:55 2002
@@ -736,7 +736,7 @@
 	int		entropy = 0;
 
 #if defined (__i386__)
-	if ( test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability) ) {
+	if ( test_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability) ) {
 		__u32 high;
 		rdtsc(time, high);
 		num ^= high;
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/char/raw.c	Sun Apr 14 12:16:55 2002
@@ -266,6 +266,7 @@
 	unsigned long	limit;
 	int		sector_size, sector_bits, sector_mask;
 	sector_t	blocknr;
+	struct block_device *bdev;
 	
 	/*
 	 * First, a few checks on device size limits 
@@ -286,14 +287,14 @@
 		new_iobuf = 1;
 	}
 
-	dev = to_kdev_t(raw_devices[minor].binding->bd_dev);
+	bdev = raw_devices[minor].binding;
+	dev = to_kdev_t(bdev->bd_dev);
 	sector_size = raw_devices[minor].sector_size;
 	sector_bits = raw_devices[minor].sector_bits;
-	sector_mask = sector_size- 1;
-	
-	if (blk_size[major(dev)])
-		limit = (((loff_t) blk_size[major(dev)][minor(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
-	else
+	sector_mask = sector_size - 1;
+
+	limit = bdev->bd_inode->i_size >> sector_bits;
+	if (!limit)
 		limit = INT_MAX;
 	dprintk ("rw_raw_dev: dev %d:%d (+%d)\n",
 		 major(dev), minor(dev), limit);
@@ -322,7 +323,7 @@
 		if (err)
 			break;
 
-		err = brw_kiovec(rw, 1, &iobuf, dev, &blocknr, sector_size);
+		err = brw_kiovec(rw, 1, &iobuf, raw_devices[minor].binding, &blocknr, sector_size);
 
 		if (rw == READ && err > 0)
 			mark_dirty_kiobuf(iobuf, err);
diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c
--- a/drivers/char/rocket.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/rocket.c	Sun Apr 14 12:16:56 2002
@@ -42,10 +42,6 @@
 #include <linux/config.h>
 #include <linux/version.h>
 
-#ifdef CONFIG_PCI
-#define ENABLE_PCI
-#endif
-
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/major.h>
@@ -63,15 +59,8 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
-#ifdef ENABLE_PCI
 #include <linux/pci.h>
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-#include <linux/bios32.h>
-#endif
-#endif
-#if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
 #include <linux/init.h>
-#endif
 	
 #include "rocket_int.h"
 #ifdef LOCAL_ROCKET_H
@@ -154,7 +143,6 @@
 static unsigned long time_counter;
 #endif
 
-#if ((LINUX_VERSION_CODE > 0x020111) && defined(MODULE))
 MODULE_AUTHOR("Theodore Ts'o");
 MODULE_DESCRIPTION("Comtrol Rocketport driver");
 MODULE_LICENSE("GPL");
@@ -170,39 +158,8 @@
 MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
 MODULE_PARM(support_low_speed, "i");
 MODULE_PARM_DESC(support_low_speed, "0 means support 50 baud, 1 means support 460400 baud");	
-#endif
-
-#if (LINUX_VERSION_CODE < 131336)
-int copy_from_user(void *to, const void *from_user, unsigned long len)
-{
-	int	error;
-
-	error = verify_area(VERIFY_READ, from_user, len);
-	if (error)
-		return len;
-	memcpy_fromfs(to, from_user, len);
-	return 0;
-}
-
-int copy_to_user(void *to_user, const void *from, unsigned long len)
-{
-	int	error;
-	
-	error = verify_area(VERIFY_WRITE, to_user, len);
-	if (error)
-		return len;
-	memcpy_tofs(to_user, from, len);
-	return 0;
-}
-
-static inline int signal_pending(struct task_struct *p)
-{
-	return (p->signal & ~p->blocked) != 0;
-}
 
-#else
 #include <asm/uaccess.h>
-#endif
 
 /*
  * tmp_buf is used as a temporary buffer by rp_write.  We need to
@@ -497,7 +454,7 @@
 			continue;
 		ctlp= sCtlNumToCtlPtr(ctrl);
 
-#ifdef ENABLE_PCI
+#ifdef CONFIG_PCI
 		if(ctlp->BusType == isPCI)
 			CtlMask= sPCIGetControllerIntStatus(ctlp);
 		else
@@ -611,12 +568,6 @@
 	rp_table[line] = info;
 }
 
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300,
-	600, 1200, 1800, 2400, 4800, 9600, 19200,
-	38400, 57600, 115200, 230400, 460800, 0 };
-#endif
 
 /*
  * This routine configures a rocketport port so according to its
@@ -627,9 +578,6 @@
 	unsigned cflag;
 	unsigned long 	flags;
 	int	bits, baud;
-#if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
-	int i;
-#endif
 	CHANNEL_t	*cp;
 	
 	if (!info->tty || !info->tty->termios)
@@ -665,31 +613,9 @@
 	}
 	
 	/* baud rate */
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-	i = cflag & CBAUD;
-	if (i & CBAUDEX) {
-		i &= ~CBAUDEX;
-		if (i < 1 || i > 4) 
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			i += 15;
-	}
-	if (i == 15) {
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
-			i += 1;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
-			i += 2;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
-			i += 3;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
-			i += 4;
-	}
-	baud = baud_table[i] ? baud_table[i] : 9600;
-#else
 	baud = tty_get_baud_rate(info->tty);
 	if (!baud)
 		baud = 9600;
-#endif
 	info->cps = baud / bits;
 	sSetBaud(cp, (rp_baud_base/baud) - 1);
 	
@@ -990,7 +916,6 @@
 
 	info->flags |= ROCKET_INITIALIZED;
 
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	/*
 	 * Set up the tty->alt_speed kludge
 	 */
@@ -1002,7 +927,6 @@
 		info->tty->alt_speed = 230400;
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
 		info->tty->alt_speed = 460800;
-#endif
 
 	configure_r_port(info);
 	if (tty->termios->c_cflag & CBAUD) {
@@ -1094,10 +1018,8 @@
 	 * If transmission was throttled by the application request,
 	 * just flush the xmit buffer.
 	 */
-#if (LINUX_VERSION_CODE >= 131343)
 	if (tty->flow_stopped)
 		rp_flush_buffer(tty);
-#endif
 
 	/*
 	 * Wait for the transmit buffer to clear
@@ -1218,17 +1140,6 @@
 /*
  * Here are the routines used by rp_ioctl
  */
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-static void send_break(	struct r_port * info, int duration)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	cli();
-	sSendBreak(&info->channel);
-	schedule_timeout(duration);
-	sClrBreak(&info->channel);
-	sti();
-}
-#else
 static void rp_break(struct tty_struct *tty, int break_state)
 {
 	struct r_port * info = (struct r_port *)tty->driver_data;
@@ -1245,7 +1156,6 @@
 	}
 	restore_flags(flags);
 }
-#endif
 
 static int get_modem_info(struct r_port * info, unsigned int *value)
 {
@@ -1348,7 +1258,6 @@
 	info->close_delay = new_serial.close_delay;
 	info->closing_wait = new_serial.closing_wait;
 
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
 		info->tty->alt_speed = 57600;
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
@@ -1357,7 +1266,6 @@
 		info->tty->alt_speed = 230400;
 	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
 		info->tty->alt_speed = 460800;
-#endif
 	
 	configure_r_port(info);
 	return 0;
@@ -1389,54 +1297,13 @@
 		    unsigned int cmd, unsigned long arg)
 {
 	struct r_port * info = (struct r_port *)tty->driver_data;
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-	int retval, tmp;
-#endif
 
 	if (cmd != RCKP_GET_PORTS &&
 	    rocket_paranoia_check(info, tty->device, "rp_ioctl"))
 		return -ENODEV;
 
 	switch (cmd) {
-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
-		case TCSBRK:	/* SVID version: non-zero arg --> no break */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			if (!arg) {
-				send_break(info, HZ/4);	/* 1/4 second */
-				if (signal_pending(current))
-					return -EINTR;
-			}
-			return 0;
-		case TCSBRKP:	/* support for POSIX tcsendbreak() */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
-			if (signal_pending(current))
-				return -EINTR;
-			return 0;
-		case TIOCGSOFTCAR:
-			tmp = C_CLOCAL(tty) ? 1 : 0;
-			if (copy_to_user((void *)arg, &tmp, sizeof(int)))
-				return -EFAULT;
-			return 0;
-		case TIOCSSOFTCAR:
-			if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
-				return -EFAULT;
 
-			tty->termios->c_cflag =
-				((tty->termios->c_cflag & ~CLOCAL) |
-				 (tmp ? CLOCAL : 0));
-			return 0;
-#endif
 		case TIOCMGET:
 			return get_modem_info(info, (unsigned int *) arg);
 		case TIOCMBIS:
@@ -1877,36 +1744,7 @@
 	sFlushTxFIFO(cp);
 }
 
-#ifdef ENABLE_PCI
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-/* For compatibility */
-static struct pci_dev *pci_find_slot(unsigned char bus,
-				     unsigned char device_fn)
-{
-	unsigned short		vendor_id, device_id;
-	int			ret, error;
-	static struct pci_dev	ret_struct;
-	
-	error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,
-		&vendor_id);
-	ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,
-		&device_id);
-	if (error == 0)
-		error = ret;
-
-	if (error) {
-		printk("PCI RocketPort error: %s not initializing due to error"
-		       "reading configuration space\n",
-		       pcibios_strerror(error));
-		return(0);
-	}
-
-	memset(&ret_struct, 0, sizeof(ret_struct));
-	ret_struct.device = device_id;
-
-	return &ret_struct;
-}
-#endif
+#ifdef CONFIG_PCI
      
 int __init register_PCI(int i, unsigned int bus, unsigned int device_fn)
 {
@@ -1915,10 +1753,6 @@
 	char *str;
 	CONTROLLER_t	*ctlp;
 	struct pci_dev *dev = pci_find_slot(bus, device_fn);
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-	int	ret;
-	unsigned int port;
-#endif
 
 	if (!dev)
 		return 0;
@@ -2161,7 +1995,7 @@
 		if(init_ISA(i, &reserved_controller))
 			isa_boards_found++;
 	}
-#ifdef ENABLE_PCI
+#ifdef CONFIG_PCI
 	if (pcibios_present()) {
 		if(isa_boards_found < NUM_BOARDS)
 			pci_boards_found = init_PCI(isa_boards_found);
@@ -2219,13 +2053,9 @@
 	rocket_driver.stop = rp_stop;
 	rocket_driver.start = rp_start;
 	rocket_driver.hangup = rp_hangup;
-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	rocket_driver.break_ctl = rp_break;
-#endif
-#if (LINUX_VERSION_CODE >= 131343)
 	rocket_driver.send_xchar = rp_send_xchar;
 	rocket_driver.wait_until_sent = rp_wait_until_sent;
-#endif
 
 	/*
 	 * The callout device is just like normal device except for
diff -Nru a/drivers/char/sbc60xxwdt.c b/drivers/char/sbc60xxwdt.c
--- a/drivers/char/sbc60xxwdt.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/sbc60xxwdt.c	Sun Apr 14 12:16:56 2002
@@ -109,6 +109,15 @@
 static int wdt_is_open;
 static int wdt_expect_close;
 
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /*
  *	Whack the dog
  */
@@ -202,6 +211,9 @@
 			/* Just in case we're already talking to someone... */
 			if(wdt_is_open)
 				return -EBUSY;
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/* Good, fire up the show */
 			wdt_is_open = 1;
 			wdt_startup();
@@ -216,7 +228,7 @@
 {
 	if(minor(inode->i_rdev) == WATCHDOG_MINOR) 
 	{
-		if(wdt_expect_close)
+		if(wdt_expect_close && !nowayout)
 			wdt_turnoff();
 		else {
 			del_timer(&timer);
diff -Nru a/drivers/char/shwdt.c b/drivers/char/shwdt.c
--- a/drivers/char/shwdt.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/char/shwdt.c	Sun Apr 14 12:16:57 2002
@@ -9,6 +9,9 @@
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -88,6 +91,15 @@
 static struct timer_list timer;
 static unsigned long next_heartbeat;
 
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
 /**
  *	sh_wdt_write_cnt - Write to Counter
  *
@@ -175,6 +187,10 @@
 			if (test_and_set_bit(0, &sh_is_open))
 				return -EBUSY;
 
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
+
 			sh_wdt_start();
 
 			break;
@@ -196,9 +212,9 @@
 static int sh_wdt_close(struct inode *inode, struct file *file)
 {
 	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		sh_wdt_stop();
-#endif
+		if (!nowayout) {
+			sh_wdt_stop();
+		}
 		clear_bit(0, &sh_is_open);
 	}
 	
diff -Nru a/drivers/char/softdog.c b/drivers/char/softdog.c
--- a/drivers/char/softdog.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/char/softdog.c	Sun Apr 14 12:16:58 2002
@@ -1,5 +1,5 @@
 /*
- *	SoftDog	0.05:	A Software Watchdog Device
+ *	SoftDog	0.06:	A Software Watchdog Device
  *
  *	(c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
  *				http://www.redhat.com
@@ -26,6 +26,10 @@
  *
  *  19980911 Alan Cox
  *	Made SMP safe for 2.3.x
+ *
+ *  20011214 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *      Didn't add timeout option, as soft_margin option already exists.
  */
  
 #include <linux/module.h>
@@ -46,6 +50,15 @@
 static int soft_margin = TIMER_MARGIN;	/* in seconds */
 
 MODULE_PARM(soft_margin,"i");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 MODULE_LICENSE("GPL");
 
 /*
@@ -83,9 +96,9 @@
 {
 	if(timer_alive)
 		return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	 
-	MOD_INC_USE_COUNT;
-#endif	
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *	Activate timer
 	 */
@@ -98,11 +111,11 @@
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
+	 * 	Lock it in if it's a module and we set nowayout
 	 */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	 
-	del_timer(&watchdog_ticktock);
-#endif	
+	if(!nowayout) {
+		del_timer(&watchdog_ticktock);
+	}
 	timer_alive=0;
 	return 0;
 }
@@ -159,7 +172,7 @@
 	fops:		&softdog_fops,
 };
 
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n";
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n";
 
 static int __init watchdog_init(void)
 {
@@ -170,7 +183,7 @@
 	if (ret)
 		return ret;
 
-	printk(banner, soft_margin);
+	printk(banner, soft_margin, nowayout);
 
 	return 0;
 }
diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c
--- a/drivers/char/sonypi.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/sonypi.c	Sun Apr 14 12:16:56 2002
@@ -109,25 +109,29 @@
         return result;
 }
 
-static void sonypi_ecrset(u16 addr, u16 value) {
+static void sonypi_ecrset(u8 addr, u8 value) {
 
-	wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
-	outw_p(0x81, SONYPI_CST_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(value, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-}
-
-static u16 sonypi_ecrget(u16 addr) {
-
-	wait_on_command(1, inw_p(SONYPI_CST_IOPORT) & 3);
-	outw_p(0x80, SONYPI_CST_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	outw_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inw_p(SONYPI_CST_IOPORT) & 2);
-	return inw_p(SONYPI_DATA_IOPORT);
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
+	outb_p(0x81, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(value, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+}
+
+static u8 sonypi_ecrget(u8 addr) {
+
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
+	outb_p(0x80, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
+	return inb_p(SONYPI_DATA_IOPORT);
+}
+
+static u16 sonypi_ecrget16(u8 addr) {
+	return sonypi_ecrget(addr) | (sonypi_ecrget(addr + 1) << 8);
 }
 
 /* Initializes the device - this comes from the AML code in the ACPI bios */
@@ -286,19 +290,38 @@
 	sonypi_device.camera_power = 1;
 }
 
+/* sets the bluetooth subsystem power state */
+static void sonypi_setbluetoothpower(u8 state) {
+
+	state = (state != 0);
+	if (sonypi_device.bluetooth_power && state) 
+		return;
+	if (!sonypi_device.bluetooth_power && !state) 
+		return;
+	
+	sonypi_call2(0x96, state);
+	sonypi_call1(0x93);
+	sonypi_device.bluetooth_power = state;
+}
+
 /* Interrupt handler: some event is available */
 void sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) {
 	u8 v1, v2, event = 0;
 	int i;
 	u8 sonypi_jogger_ev, sonypi_fnkey_ev;
+	u8 sonypi_capture_ev, sonypi_bluetooth_ev;
 
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
 		sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV;
 		sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV;
+		sonypi_capture_ev = SONYPI_TYPE2_CAPTURE_EV;
+		sonypi_bluetooth_ev = SONYPI_TYPE2_BLUETOOTH_EV;
 	}
 	else {
 		sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV;
 		sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV;
+		sonypi_capture_ev = SONYPI_TYPE1_CAPTURE_EV;
+		sonypi_bluetooth_ev = SONYPI_TYPE1_BLUETOOTH_EV;
 	}
 
 	v1 = inb_p(sonypi_device.ioport1);
@@ -318,7 +341,7 @@
 				goto found;
 			}
 	}
-	if ((v2 & SONYPI_CAPTURE_EV) == SONYPI_CAPTURE_EV) {
+	if ((v2 & sonypi_capture_ev) == sonypi_capture_ev) {
 		for (i = 0; sonypi_captureev[i].event; i++)
 			if (sonypi_captureev[i].data == v1) {
 				event = sonypi_captureev[i].event;
@@ -332,7 +355,7 @@
 				goto found;
 			}
 	}
-	if ((v2 & SONYPI_BLUETOOTH_EV) == SONYPI_BLUETOOTH_EV) {
+	if ((v2 & sonypi_bluetooth_ev) == sonypi_bluetooth_ev) {
 		for (i = 0; sonypi_blueev[i].event; i++)
 			if (sonypi_blueev[i].data == v1) {
 				event = sonypi_blueev[i].event;
@@ -510,24 +533,74 @@
 static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 
 			     unsigned int cmd, unsigned long arg) {
 	int ret = 0;
-	u8 val;
+	u8 val8;
+	u16 val16;
 
 	down(&sonypi_device.lock);
 	switch (cmd) {
-		case SONYPI_IOCGBRT:
-			val = sonypi_ecrget(0x96) & 0xff;
-			if (copy_to_user((u8 *)arg, &val, sizeof(val))) {
-				ret = -EFAULT;
-				goto out;
-			}
-			break;
-		case SONYPI_IOCSBRT:
-			if (copy_from_user(&val, (u8 *)arg, sizeof(val))) {
-				ret = -EFAULT;
-				goto out;
-			}
-			sonypi_ecrset(0x96, val);
-			break;
+	case SONYPI_IOCGBRT:
+		val8 = sonypi_ecrget(0x96);
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCSBRT:
+		if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		sonypi_ecrset(0x96, val8);
+		break;
+	case SONYPI_IOCGBAT1CAP:
+		val16 = sonypi_ecrget16(0xb2);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT1REM:
+		val16 = sonypi_ecrget16(0xa2);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT2CAP:
+		val16 = sonypi_ecrget16(0xba);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBAT2REM:
+		val16 = sonypi_ecrget16(0xaa);
+		if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBATFLAGS:
+		val8 = sonypi_ecrget(0x81) & 0x07;
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCGBLUE:
+		val8 = sonypi_device.bluetooth_power;
+		if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		break;
+	case SONYPI_IOCSBLUE:
+		if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
+			ret = -EFAULT;
+			goto out;
+		}
+		sonypi_setbluetoothpower(val8);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -562,6 +635,7 @@
 		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
 	sonypi_initq();
 	init_MUTEX(&sonypi_device.lock);
+	sonypi_device.bluetooth_power = 0;
 	
 	if (pcidev && pci_enable_device(pcidev)) {
 		printk(KERN_ERR "sonypi: pci_enable_device failed\n");
diff -Nru a/drivers/char/sonypi.h b/drivers/char/sonypi.h
--- a/drivers/char/sonypi.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/char/sonypi.h	Sun Apr 14 12:16:55 2002
@@ -34,8 +34,8 @@
 
 #ifdef __KERNEL__
 
-#define SONYPI_DRIVER_MAJORVERSION	1
-#define SONYPI_DRIVER_MINORVERSION	8
+#define SONYPI_DRIVER_MAJORVERSION	 1
+#define SONYPI_DRIVER_MINORVERSION	10
 
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -132,15 +132,17 @@
 #define SONYPI_CAMERA_ROMVERSION 		9
 
 /* key press event data (ioport2) */
-#define SONYPI_TYPE1_JOGGER_EV	0x10
-#define SONYPI_TYPE2_JOGGER_EV	0x08
-#define SONYPI_CAPTURE_EV	0x60
-#define SONYPI_TYPE1_FNKEY_EV	0x20
-#define SONYPI_TYPE2_FNKEY_EV	0x08
-#define SONYPI_BLUETOOTH_EV	0x30
-#define SONYPI_TYPE1_PKEY_EV	0x40
-#define SONYPI_BACK_EV		0x08
-#define SONYPI_LID_EV		0x38
+#define SONYPI_TYPE1_JOGGER_EV		0x10
+#define SONYPI_TYPE2_JOGGER_EV		0x08
+#define SONYPI_TYPE1_CAPTURE_EV		0x60
+#define SONYPI_TYPE2_CAPTURE_EV		0x08
+#define SONYPI_TYPE1_FNKEY_EV		0x20
+#define SONYPI_TYPE2_FNKEY_EV		0x08
+#define SONYPI_TYPE1_BLUETOOTH_EV	0x30
+#define SONYPI_TYPE2_BLUETOOTH_EV	0x08
+#define SONYPI_TYPE1_PKEY_EV		0x40
+#define SONYPI_BACK_EV			0x08
+#define SONYPI_LID_EV			0x38
 
 struct sonypi_event {
 	u8	data;
@@ -203,6 +205,8 @@
 /* The set of possible bluetooth events */
 static struct sonypi_event sonypi_blueev[] = {
 	{ 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED },
+	{ 0x59, SONYPI_EVENT_BLUETOOTH_ON },
+	{ 0x5a, SONYPI_EVENT_BLUETOOTH_OFF },
 	{ 0x00, 0x00 }
 };
 
@@ -241,6 +245,7 @@
 	u16 ioport2;
 	u16 region_size;
 	int camera_power;
+	int bluetooth_power;
 	struct semaphore lock;
 	struct sonypi_queue queue;
 	int open_count;
diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c
--- a/drivers/char/stallion.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/stallion.c	Sun Apr 14 12:16:56 2002
@@ -2458,7 +2458,7 @@
 	}
 
 /*
- *	We have verfied that the board is actually present, so now we
+ *	We have verified that the board is actually present, so now we
  *	can complete the setup.
  */
 
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/char/synclink.c	Sun Apr 14 12:16:57 2002
@@ -925,9 +925,9 @@
 static char *driver_name = "SyncLink serial driver";
 static char *driver_version = "$Revision: 3.12 $";
 
-static int __init synclink_init_one (struct pci_dev *dev,
+static int synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
-static void __exit synclink_remove_one (struct pci_dev *dev);
+static void synclink_remove_one (struct pci_dev *dev);
 
 static struct pci_device_id synclink_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/char/tpqic02.c	Sun Apr 14 12:16:58 2002
@@ -2748,7 +2748,9 @@
 	 * the config parameters have been set using MTSETCONFIG.
 	 */
 
-	if (check_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE)) {
+	/* Grab the IO region. */
+	if (!request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE,
+			   TPQIC02_NAME)) {
 		printk(TPQIC02_NAME
 		       ": IO space at 0x%x [%d ports] already reserved\n",
 		       QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
@@ -2762,6 +2764,7 @@
 		printk(TPQIC02_NAME
 		       ": can't allocate IRQ%d for QIC-02 tape\n",
 		       QIC02_TAPE_IRQ);
+		release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
 		return -EBUSY;
 	}
 
@@ -2771,12 +2774,9 @@
 		       ": can't allocate DMA%d for QIC-02 tape\n",
 		       QIC02_TAPE_DMA);
 		free_irq(QIC02_TAPE_IRQ, NULL);
+		release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
 		return -EBUSY;
 	}
-
-	/* Grab the IO region. We already made sure it's available. */
-	request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE,
-		       TPQIC02_NAME);
 
 	/* Setup the page-address for the dma transfer. */
 	buffaddr =
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/char/tty_io.c	Sun Apr 14 12:16:59 2002
@@ -569,6 +569,8 @@
 	struct task_struct *p;
 	int tty_pgrp = -1;
 
+	lock_kernel();
+
 	if (tty) {
 		tty_pgrp = tty->pgrp;
 		if (on_exit && tty->driver.type != TTY_DRIVER_TYPE_PTY)
@@ -578,6 +580,7 @@
 			kill_pg(current->tty_old_pgrp, SIGHUP, on_exit);
 			kill_pg(current->tty_old_pgrp, SIGCONT, on_exit);
 		}
+		unlock_kernel();	
 		return;
 	}
 	if (tty_pgrp > 0) {
@@ -595,6 +598,7 @@
 	  	if (p->session == current->session)
 			p->tty = NULL;
 	read_unlock(&tasklist_lock);
+	unlock_kernel();
 }
 
 void stop_tty(struct tty_struct *tty)
diff -Nru a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
--- a/drivers/char/tty_ioctl.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/char/tty_ioctl.c	Sun Apr 14 12:16:58 2002
@@ -188,7 +188,7 @@
 	nr = (head - tail) & (N_TTY_BUF_SIZE-1);
 	/* Skip EOF-chars.. */
 	while (head != tail) {
-		if (test_bit(tail, &tty->read_flags) &&
+		if (test_bit(tail, tty->read_flags) &&
 		    tty->read_buf[tail] == __DISABLED_CHAR)
 			nr--;
 		tail = (tail+1) & (N_TTY_BUF_SIZE-1);
diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
--- a/drivers/char/vme_scc.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/char/vme_scc.c	Sun Apr 14 12:16:54 2002
@@ -214,7 +214,7 @@
 {
 	struct scc_port *port;
 
-	printk("SCC: MVME147 Serial Driver\n");
+	printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
 	/* Init channel A */
 	port = &scc_ports[0];
 	port->channel = CHANNEL_A;
@@ -284,7 +284,7 @@
 	if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
 		return (-ENODEV);
 
-	printk("SCC: MVME162 Serial Driver\n");
+	printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
 	/* Init channel A */
 	port = &scc_ports[0];
 	port->channel = CHANNEL_A;
@@ -352,7 +352,7 @@
 {
 	struct scc_port *port;
 
-	printk("SCC: BVME6000 Serial Driver\n");
+	printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
 	/* Init channel A */
 	port = &scc_ports[0];
 	port->channel = CHANNEL_A;
@@ -449,7 +449,7 @@
 
 	ch = SCCread_NB(RX_DATA_REG);
 	if (!tty) {
-		printk ("scc_rx_int with NULL tty!\n");
+		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 		return;
 	}
@@ -487,7 +487,7 @@
 	SCC_ACCESS_INIT(port);
 	
 	if (!tty) {
-		printk ("scc_spcond_int with NULL tty!\n");
+		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
 		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 		return;
@@ -533,7 +533,7 @@
 	SCC_ACCESS_INIT(port);
 
 	if (!port->gs.tty) {
-		printk ("scc_tx_int with NULL tty!\n");
+		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
 		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
 		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
 		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
@@ -719,7 +719,7 @@
 	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
 		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
 		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
-		printk("SCC: Bad speed requested, %d\n", baud);
+		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
 		return 0;
 	}
 
diff -Nru a/drivers/char/wdt.c b/drivers/char/wdt.c
--- a/drivers/char/wdt.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/char/wdt.c	Sun Apr 14 12:16:59 2002
@@ -15,7 +15,7 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
- *	Release 0.08.
+ *	Release 0.09.
  *
  *	Fixes
  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -27,6 +27,7 @@
  *		Tim Hockin	:	Added insmod parameters, comment cleanup
  *					Parameterized timeout
  *		Tigran Aivazian	:	Restructured wdt_init() to handle failures
+ *		Matt Domsch	:	added nowayout and timeout module options
  */
 
 #include <linux/config.h>
@@ -62,6 +63,26 @@
 
 #define WD_TIMO (100*60)		/* 1 minute */
 
+static int timeout_val = WD_TIMO;	/* value passed to card */
+static int timeout = 60;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+static void __init
+wdt_validate_timeout(void)
+{
+	timeout_val = timeout * 100;
+}
+
 #ifndef MODULE
 
 /**
@@ -216,7 +237,7 @@
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdt_ctr_mode(1,2);
-	wdt_ctr_load(1,WD_TIMO);		/* Timeout */
+	wdt_ctr_load(1,timeout_val);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -339,6 +360,9 @@
 		case WATCHDOG_MINOR:
 			if(test_and_set_bit(0, &wdt_is_open))
 				return -EBUSY;
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -348,7 +372,7 @@
 			wdt_ctr_mode(1,2);
 			wdt_ctr_mode(2,0);
 			wdt_ctr_load(0, 8948);		/* count at 100Hz */
-			wdt_ctr_load(1,WD_TIMO);	/* Timeout 120 seconds */
+			wdt_ctr_load(1,timeout_val);	/* Timeout */
 			wdt_ctr_load(2,65535);
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
@@ -375,10 +399,10 @@
 {
 	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_DC);		/* Disable counters */
-		wdt_ctr_load(2,0);	/* 0 length reset pulses now */
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_DC);		/* Disable counters */
+			wdt_ctr_load(2,0);	/* 0 length reset pulses now */
+		}
 		clear_bit(0, &wdt_is_open);
 	}
 	return 0;
@@ -484,6 +508,7 @@
 {
 	int ret;
 
+	wdt_validate_timeout();
 	ret = misc_register(&wdt_miscdev);
 	if (ret) {
 		printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR);
diff -Nru a/drivers/char/wdt977.c b/drivers/char/wdt977.c
--- a/drivers/char/wdt977.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/char/wdt977.c	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- *	Wdt977	0.01:	A Watchdog Device for Netwinder W83977AF chip
+ *	Wdt977	0.02:	A Watchdog Device for Netwinder W83977AF chip
  *
  *	(c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
  *
@@ -11,8 +11,13 @@
  *	2 of the License, or (at your option) any later version.
  *
  *			-----------------------
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *	19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
+ *	06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
+ *				    from minutes to seconds.
  */
- 
+
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -21,56 +26,123 @@
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/watchdog.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
+#include <asm/uaccess.h>
 
 #define WATCHDOG_MINOR	130
 
-static	int timeout = 3;
+#define	DEFAULT_TIMEOUT	1	/* default timeout = 1 minute */
+
+static	int timeout = DEFAULT_TIMEOUT*60;	/* TO in seconds from user */
+static	int timeoutM = DEFAULT_TIMEOUT;		/* timeout in minutes */
 static	int timer_alive;
 static	int testmode;
 
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=60");
+MODULE_PARM(testmode, "i");
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+
+/* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */
+int kick_wdog(void)
+{
+	/*
+	 *	Refresh the timer.
+	 */
+
+	/* unlock the SuperIO chip */
+	outb(0x87,0x370);
+	outb(0x87,0x370);
+
+	/* select device Aux2 (device=8) and kicks watchdog reg F2 */
+	/* F2 has the timeout in minutes */
+
+	outb(0x07,0x370);
+	outb(0x08,0x371);
+	outb(0xF2,0x370);
+	outb(timeoutM,0x371);
+
+	/* lock the SuperIO chip */
+	outb(0xAA,0x370);
+
+	return 0;
+}
+
+
 /*
  *	Allow only one person to hold it open
  */
- 
+
 static int wdt977_open(struct inode *inode, struct file *file)
 {
+
 	if(timer_alive)
 		return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-	MOD_INC_USE_COUNT;
-#endif
+
+	/* convert seconds to minutes, rounding up */
+	timeoutM = timeout + 59;
+	timeoutM /= 60;
+
+	if (nowayout)
+	{
+		MOD_INC_USE_COUNT;
+
+		/* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */
+		if (!timeoutM) timeoutM = DEFAULT_TIMEOUT;
+	}
 	timer_alive++;
 
-	//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
-	if (timeout>255)
-	    timeout = 255;
-
-	printk(KERN_INFO "Watchdog: active, current timeout %d min.\n",timeout);
-
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
-	//F2 has the timeout in minutes
-	//F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
-	//   at timeout, and to reset timer on kbd/mouse activity (not now)
-	//F4 is used to just clear the TIMEOUT'ed state (bit 0)
-	
+	if (machine_is_netwinder())
+	{
+		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+		 *  this limits the max timeout to half of device max of 255 minutes...
+		 */
+		timeoutM += timeoutM;
+	}
+
+	/* max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog. */
+	if (timeoutM > 255) timeoutM = 255;
+
+	/* convert seconds to minutes */
+	printk(KERN_INFO "Wdt977 Watchdog activated: timeout = %d sec, nowayout = %i, testmode = %i.\n",
+		machine_is_netwinder() ? (timeoutM>>1)*60 : timeoutM*60,
+		nowayout, testmode);
+
+	/* unlock the SuperIO chip */
+	outb(0x87,0x370);
+	outb(0x87,0x370);
+
+	/* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
+	 * F2 has the timeout in minutes
+	 * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
+	 *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
+	 * F4 is used to just clear the TIMEOUT'ed state (bit 0)
+	 */
 	outb(0x07,0x370);
 	outb(0x08,0x371);
 	outb(0xF2,0x370);
-	outb(timeout,0x371);
+	outb(timeoutM,0x371);
 	outb(0xF3,0x370);
-	outb(0x00,0x371);	//another setting is 0E for kbd/mouse/LED
+	outb(0x00,0x371);	/* another setting is 0E for kbd/mouse/LED */
 	outb(0xF4,0x370);
 	outb(0x00,0x371);
-	
-	//at last select device Aux1 (dev=7) and set GP16 as a watchdog output
+
+	/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+	/* in test mode watch the bit 1 on F4 to indicate "triggered" */
 	if (!testmode)
 	{
 		outb(0x07,0x370);
@@ -78,9 +150,9 @@
 		outb(0xE6,0x370);
 		outb(0x08,0x371);
 	}
-		
-	// lock the SuperIO chip
-	outb(0xAA,0x370); 
+
+	/* lock the SuperIO chip */
+	outb(0xAA,0x370);
 
 	return 0;
 }
@@ -89,84 +161,163 @@
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
+	 * 	Lock it in if it's a module and we set nowayout
 	 */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
+	if (!nowayout)
+	{
+		lock_kernel();
 
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
-	//F3 is reset to its default state
-	//F4 can clear the TIMEOUT'ed state (bit 0) - back to default
-	//We can not use GP17 as a PowerLed, as we use its usage as a RedLed
-	
-	outb(0x07,0x370);
-	outb(0x08,0x371);
-	outb(0xF2,0x370);
-	outb(0xFF,0x371);
-	outb(0xF3,0x370);
-	outb(0x00,0x371);
-	outb(0xF4,0x370);
-	outb(0x00,0x371);
-	outb(0xF2,0x370);
-	outb(0x00,0x371);
-	
-	//at last select device Aux1 (dev=7) and set GP16 as a watchdog output
-	outb(0x07,0x370);
-	outb(0x07,0x371);
-	outb(0xE6,0x370);
-	outb(0x08,0x371);
-	
-	// lock the SuperIO chip
-	outb(0xAA,0x370);
+		/* unlock the SuperIO chip */
+		outb(0x87,0x370);
+		outb(0x87,0x370);
+
+		/* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
+		* F3 is reset to its default state
+		* F4 can clear the TIMEOUT'ed state (bit 0) - back to default
+		* We can not use GP17 as a PowerLed, as we use its usage as a RedLed
+		*/
+		outb(0x07,0x370);
+		outb(0x08,0x371);
+		outb(0xF2,0x370);
+		outb(0xFF,0x371);
+		outb(0xF3,0x370);
+		outb(0x00,0x371);
+		outb(0xF4,0x370);
+		outb(0x00,0x371);
+		outb(0xF2,0x370);
+		outb(0x00,0x371);
 
-	timer_alive=0;
+		/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+		outb(0x07,0x370);
+		outb(0x07,0x371);
+		outb(0xE6,0x370);
+		outb(0x08,0x371);
 
-	printk(KERN_INFO "Watchdog: shutdown.\n");
-#endif
+		/* lock the SuperIO chip */
+		outb(0xAA,0x370);
+
+		timer_alive=0;
+		unlock_kernel();
+
+		printk(KERN_INFO "Wdt977 Watchdog: shutdown\n");
+	}
 	return 0;
 }
 
-static ssize_t wdt977_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+
+/*
+ *      wdt977_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt977_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
+	/*  Can't seek (pwrite) on this device  */
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
 
-	//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
-	if (timeout>255)
-	    timeout = 255;
+	if(count)
+	{
+		kick_wdog();
+		return 1;
+	}
+	return 0;
+}
 
-	/*
-	 *	Refresh the timer.
-	 */
-		
-	//we have a hw bug somewhere, so each 977 minute is actually only 30sec
-	//as such limit the max timeout to half of max of 255 minutes...
-//	if (timeout>126)
-//	    timeout = 126;
-	
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and kicks watchdog reg F2
-	//F2 has the timeout in minutes
-	
-	outb(0x07,0x370);
-	outb(0x08,0x371);
-	outb(0xF2,0x370);
-	outb(timeout,0x371);
-	
-	// lock the SuperIO chip
-	outb(0xAA,0x370); 
-	
-	return 1;
+/*
+ *      wdt977_ioctl:
+ *      @inode: inode of the device
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+
+static int wdt977_ioctl(struct inode *inode, struct file *file,
+         unsigned int cmd, unsigned long arg)
+{
+static struct watchdog_info ident = {
+	identity	: "Winbond 83977"
+};
+
+int temp;
+
+	switch(cmd)
+	{
+	default:
+		return -ENOTTY;
+
+	case WDIOC_GETSUPPORT:
+	    return copy_to_user((struct watchdog_info *)arg, &ident,
+			sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, (int *) arg);
+
+	case WDIOC_GETSTATUS:
+		/* unlock the SuperIO chip */
+		outb(0x87,0x370);
+		outb(0x87,0x370);
+
+		/* select device Aux2 (device=8) and read watchdog reg F4 */
+		outb(0x07,0x370);
+		outb(0x08,0x371);
+		outb(0xF4,0x370);
+		temp = inb(0x371);
+
+		/* lock the SuperIO chip */
+		outb(0xAA,0x370);
+
+		/* return info if "expired" in test mode */
+		return put_user(temp & 1, (int *) arg);
+
+	case WDIOC_KEEPALIVE:
+		kick_wdog();
+		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		if (copy_from_user(&temp, (int *) arg, sizeof(int)))
+			return -EFAULT;
+
+		/* convert seconds to minutes, rounding up */
+		temp += 59;
+		temp /= 60;
+
+		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+		*  this limits the max timeout to half of device max of 255 minutes...
+		*/
+		if (machine_is_netwinder())
+		{
+		    temp += temp;
+		}
+
+		/* Sanity check */
+		if (temp < 0 || temp > 255)
+			return -EINVAL;
+
+		if (!temp && nowayout)
+			return -EINVAL;
+
+		timeoutM = temp;
+		kick_wdog();
+		return 0;
+	}
 }
 
+
 static struct file_operations wdt977_fops=
 {
 	owner:		THIS_MODULE,
 	write:		wdt977_write,
+	ioctl:		wdt977_ioctl,
 	open:		wdt977_open,
 	release:	wdt977_release,
 };
@@ -184,9 +335,9 @@
 		return -ENODEV;
 
 	misc_register(&wdt977_miscdev);
-	printk(KERN_INFO "NetWinder Watchdog sleeping.\n");
+	printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
 	return 0;
-}	
+}
 
 static void __exit nwwatchdog_exit(void)
 {
diff -Nru a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c
--- a/drivers/char/wdt_pci.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/char/wdt_pci.c	Sun Apr 14 12:16:55 2002
@@ -15,7 +15,7 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
- *	Release 0.08.
+ *	Release 0.09.
  *
  *	Fixes
  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -30,6 +30,7 @@
  *		Alan Cox	:	Split ISA and PCI cards into two drivers
  *		Jeff Garzik	:	PCI cleanups
  *		Tigran Aivazian	:	Restructured wdtpci_init_one() to handle failures
+ *		Matt Domsch	:	added nowayout and timeout module options
  */
 
 #include <linux/config.h>
@@ -83,6 +84,26 @@
 
 #define WD_TIMO (100*60)		/* 1 minute */
 
+static int timeout_val = WD_TIMO;	/* value passed to card */
+static int timeout = 60;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+static void __init
+wdtpci_validate_timeout(void)
+{
+	timeout_val = timeout * 100;
+}
+
 #ifndef MODULE
 
 /**
@@ -232,7 +253,7 @@
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdtpci_ctr_mode(1,2);
-	wdtpci_ctr_load(1,WD_TIMO);		/* Timeout */
+	wdtpci_ctr_load(1,timeout_val);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -357,9 +378,9 @@
 			{
 				return -EBUSY;
 			}
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	
-			MOD_INC_USE_COUNT;
-#endif
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -385,7 +406,7 @@
 			wdtpci_ctr_mode(1,2);
 			wdtpci_ctr_mode(2,1);
 			wdtpci_ctr_load(0,20833);	/* count at 100Hz */
-			wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */
+			wdtpci_ctr_load(1,timeout_val); /* Timeout */
 			/* DO NOT LOAD CTR2 on PCI card! -- JPN */
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
@@ -412,10 +433,10 @@
 {
 	if(minor(inode->i_rdev)==WATCHDOG_MINOR)
 	{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_DC);		/* Disable counters */
-		wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_DC);		/* Disable counters */
+			wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
+		}
 		clear_bit(0, &wdt_is_open );
 	}
 	return 0;
@@ -617,6 +638,8 @@
 	
 	if (rc < 1)
 		return -ENODEV;
+
+	wdtpci_validate_timeout();
 	
 	return 0;
 }
diff -Nru a/drivers/fc4/soc.c b/drivers/fc4/soc.c
--- a/drivers/fc4/soc.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/fc4/soc.c	Sun Apr 14 12:16:55 2002
@@ -742,7 +742,6 @@
 	
 	for_each_soc(s) {
 		irq = s->port[0].fc.irq;
-		disable_irq (irq);
 		free_irq (irq, s);
 
 		fcp_release(&(s->port[0].fc), 2);
diff -Nru a/drivers/fc4/socal.c b/drivers/fc4/socal.c
--- a/drivers/fc4/socal.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/fc4/socal.c	Sun Apr 14 12:16:58 2002
@@ -881,7 +881,6 @@
 	
 	for_each_socal(s) {
 		irq = s->port[0].fc.irq;
-		disable_irq (irq);
 		free_irq (irq, s);
 
 		fcp_release(&(s->port[0].fc), 2);
diff -Nru a/drivers/hotplug/Config.in b/drivers/hotplug/Config.in
--- a/drivers/hotplug/Config.in	Sun Apr 14 12:16:56 2002
+++ b/drivers/hotplug/Config.in	Sun Apr 14 12:16:56 2002
@@ -8,6 +8,8 @@
 
 dep_tristate '  Compaq PCI Hotplug driver' CONFIG_HOTPLUG_PCI_COMPAQ $CONFIG_HOTPLUG_PCI $CONFIG_X86
 dep_mbool '    Save configuration into NVRAM on Compaq servers' CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM $CONFIG_HOTPLUG_PCI_COMPAQ
-dep_tristate '  IBM PCI Hotplug driver' CONFIG_HOTPLUG_PCI_IBM $CONFIG_HOTPLUG_PCI $CONFIG_X86_IO_APIC $CONFIG_X86
+if [ "$CONFIG_X86_IO_APIC" = "y" ]; then
+   dep_tristate '  IBM PCI Hotplug driver' CONFIG_HOTPLUG_PCI_IBM $CONFIG_HOTPLUG_PCI $CONFIG_X86_IO_APIC $CONFIG_X86
+fi
 
 endmenu
diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile	Sun Apr 14 12:16:56 2002
+++ b/drivers/hotplug/Makefile	Sun Apr 14 12:16:56 2002
@@ -4,8 +4,6 @@
 
 O_TARGET	:= vmlinux-obj.o
 
-list-multi	:= cpqphp.o pci_hotplug.o ibmphp.o
-
 export-objs	:= pci_hotplug_core.o pci_hotplug_util.o
 
 obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplug.o
@@ -32,13 +30,3 @@
 
 
 include $(TOPDIR)/Rules.make
-
-pci_hotplug.o: $(pci_hotplug-objs)
-	$(LD) -r -o $@ $(pci_hotplug-objs)
-
-cpqphp.o: $(cpqphp-objs)
-	$(LD) -r -o $@ $(cpqphp-objs)
-
-ibmphp.o: $(ibmphp-objs)
-	$(LD) -r -o $@ $(ibmphp-objs)
-
diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c
--- a/drivers/hotplug/ibmphp_core.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/hotplug/ibmphp_core.c	Sun Apr 14 12:16:59 2002
@@ -56,7 +56,7 @@
 MODULE_DESCRIPTION (DRIVER_DESC);
 
 static int *ops[MAX_OPS + 1];
-static struct pci_ops *ibmphp_pci_root_ops;
+struct pci_ops *ibmphp_pci_root_ops;
 static int max_slots;
 
 static int irqs[16];    /* PIC mode IRQ's we're using so far (in case MPS tables don't provide default info for empty slots */
diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
--- a/drivers/i2c/i2c-algo-bit.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/i2c/i2c-algo-bit.c	Sun Apr 14 12:16:54 2002
@@ -49,7 +49,7 @@
 /* respectively. This makes sure that the algorithm works. Some chips   */
 /* might not like this, as they have an internal timeout of some mils	*/
 /*
-#define SLO_IO      jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
+#define SLO_IO      jif=jiffies;while(time_before_eq(jiffies, jif+i2c_table[minor].veryslow))\
                         cond_resched();
 */
 
@@ -117,7 +117,7 @@
  		 * while they are processing data internally. 
  		 */
 		setscl(adap,1);
-		if (start+adap->timeout <= jiffies) {
+		if (time_after_eq(jiffies, start+adap->timeout)) {
 			return -ETIMEDOUT;
 		}
 		cond_resched();
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/i2c/i2c-dev.c	Sun Apr 14 12:16:59 2002
@@ -141,7 +141,7 @@
 #ifdef DEBUG
 	struct inode *inode = file->f_dentry->d_inode;
 	printk("i2c-dev.o: i2c-%d lseek to %ld bytes relative to %d.\n",
-	       MINOR(inode->i_rdev),(long) offset,origin);
+	       minor(inode->i_rdev),(long) offset,origin);
 #endif /* DEBUG */
 	return -ESPIPE;
 }
@@ -165,7 +165,7 @@
 		return -ENOMEM;
 
 #ifdef DEBUG
-	printk("i2c-dev.o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
+	printk("i2c-dev.o: i2c-%d reading %d bytes.\n",minor(inode->i_rdev),
 	       count);
 #endif
 
@@ -197,7 +197,7 @@
 	}
 
 #ifdef DEBUG
-	printk("i2c-dev.o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
+	printk("i2c-dev.o: i2c-%d writing %d bytes.\n",minor(inode->i_rdev),
 	       count);
 #endif
 	ret = i2c_master_send(client,tmp,count);
@@ -218,7 +218,7 @@
 
 #ifdef DEBUG
 	printk("i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", 
-	       MINOR(inode->i_rdev),cmd, arg);
+	       minor(inode->i_rdev),cmd, arg);
 #endif /* DEBUG */
 
 	switch ( cmd ) {
diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
--- a/drivers/i2c/i2c-proc.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/i2c/i2c-proc.c	Sun Apr 14 12:16:59 2002
@@ -119,6 +119,10 @@
 		sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
 	}
 	*name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
+	if (!*name) {
+		printk (KERN_WARNING "i2c_create_name: not enough memory\n");
+		return -ENOMEM;
+	}
 	strcpy(*name, name_buffer);
 	return 0;
 }
diff -Nru a/drivers/ide/Config.help b/drivers/ide/Config.help
--- a/drivers/ide/Config.help	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/Config.help	Sun Apr 14 12:16:59 2002
@@ -744,6 +744,28 @@
 
   Generally say N here.
 
+CONFIG_BLK_DEV_IDE_TCQ
+  Support for tagged command queueing on ATA disk drives. This enables
+  the IDE layer to have multiple in-flight requests on hardware that
+  supports it. For now this includes the IBM Deskstar series drives,
+  such as the GXP75, 40GV, GXP60, and GXP120 (ie any Deskstar made in
+  the last couple of years).
+
+  If you have such a drive, say Y here.
+
+CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
+  Enabled tagged command queueing unconditionally on drives that report
+  support for it.
+
+  Generally say Y here.
+
+CONFIG_BLK_DEV_IDE_TCQ_DEPTH
+  Maximum size of commands to enable per-drive. Any value between 1
+  and 32 is valid, with 32 being the maxium that the hardware supports.
+
+  You probably just want the default of 32 here. If you enter an invalid
+  number, the default value will be used.
+
 CONFIG_BLK_DEV_IT8172
   Say Y here to support the on-board IDE controller on the Integrated
   Technology Express, Inc. ITE8172 SBC.  Vendor page at
diff -Nru a/drivers/ide/Config.in b/drivers/ide/Config.in
--- a/drivers/ide/Config.in	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/Config.in	Sun Apr 14 12:16:59 2002
@@ -47,6 +47,11 @@
 	 dep_bool '      Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI
          dep_bool '    Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO
 	 define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI
+	 dep_bool '    ATA tagged command queueing' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI
+	   dep_bool '      TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ
+	   if [ $CONFIG_BLK_DEV_IDE_TCQ_DEFAULT != "n" ]; then
+		int '      Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32
+	   fi
 	 dep_bool '    ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
 	 dep_bool '    Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
 	 dep_bool '    AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile
--- a/drivers/ide/Makefile	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/Makefile	Sun Apr 14 12:16:55 2002
@@ -45,6 +45,7 @@
 ide-obj-$(CONFIG_BLK_DEV_HT6560B)	+= ht6560b.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI)	+= ide-dma.o
+ide-obj-$(CONFIG_BLK_DEV_IDE_TCQ)	+= ide-tcq.o
 ide-obj-$(CONFIG_BLK_DEV_IDEPCI)	+= ide-pci.o
 ide-obj-$(CONFIG_BLK_DEV_ISAPNP)	+= ide-pnp.o
 ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC)	+= ide-pmac.o
diff -Nru a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
--- a/drivers/ide/aec62xx.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/aec62xx.c	Sun Apr 14 12:16:57 2002
@@ -220,7 +220,7 @@
 
 static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	int err			= 0;
 	unsigned short d_conf	= 0x0000;
@@ -256,10 +256,10 @@
 
 static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
-	byte ultra_pci		= hwif->channel ? 0x45 : 0x44;
+	byte ultra_pci		= hwif->unit ? 0x45 : 0x44;
 	int err			= 0;
 	byte drive_conf		= 0x00;
 	byte ultra_conf		= 0x00;
@@ -293,7 +293,7 @@
 
 static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+	if (drive->channel->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
 		return ((int) aec6210_tune_chipset(drive, speed));
 	} else {
 		return ((int) aec6260_tune_chipset(drive, speed));
@@ -304,7 +304,7 @@
 static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte unit		= (drive->select.b.unit & 0x01);
 	unsigned long dma_base	= hwif->dma_base;
 	byte speed		= -1;
@@ -349,7 +349,7 @@
 static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte unit		= (drive->select.b.unit & 0x01);
 	unsigned long dma_base	= hwif->dma_base;
 	byte speed		= -1;
@@ -396,7 +396,7 @@
 
 static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
-	switch(HWIF(drive)->pci_dev->device) {	
+	switch(drive->channel->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 			return config_aec6210_chipset_for_dma(drive, ultra);
 		case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -418,7 +418,7 @@
 	else
 		speed = XFER_PIO_0 + min_t(byte, pio, 4);
 
-	switch(HWIF(drive)->pci_dev->device) {
+	switch(drive->channel->pci_dev->device) {
 		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 			(void) aec6210_tune_chipset(drive, speed);
 		case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -435,7 +435,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -476,7 +476,7 @@
 no_dma_set:
 		aec62xx_tune_drive(drive, 5);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -489,16 +489,16 @@
 			return config_drive_xfer_rate(drive);
 		case ide_dma_lostirq:
 		case ide_dma_timeout:
-			switch(HWIF(drive)->pci_dev->device) {
+			switch(drive->channel->pci_dev->device) {
 				case PCI_DEVICE_ID_ARTOP_ATP860:
 				case PCI_DEVICE_ID_ARTOP_ATP860R:
 //					{
 //						int i = 0;
 //						byte reg49h = 0;
-//						pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, &reg49h);
+//						pci_read_config_byte(drive->channel->pci_dev, 0x49, &reg49h);
 //						for (i=0;i<256;i++)
-//							pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10);
-//						pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10);
+//							pci_write_config_byte(drive->channel->pci_dev, 0x49, reg49h|0x10);
+//						pci_write_config_byte(drive->channel->pci_dev, 0x49, reg49h & ~0x10);
 //					}
 //					return 0;
 				default:
@@ -530,16 +530,16 @@
 	return dev->irq;
 }
 
-unsigned int __init ata66_aec62xx (ide_hwif_t *hwif)
+unsigned int __init ata66_aec62xx(struct ata_channel *hwif)
 {
-	byte mask	= hwif->channel ? 0x02 : 0x01;
+	byte mask	= hwif->unit ? 0x02 : 0x01;
 	byte ata66	= 0;
 
 	pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
 	return ((ata66 & mask) ? 0 : 1);
 }
 
-void __init ide_init_aec62xx (ide_hwif_t *hwif)
+void __init ide_init_aec62xx(struct ata_channel *hwif)
 {
 #ifdef CONFIG_AEC62XX_TUNING
 	hwif->tuneproc = &aec62xx_tune_drive;
@@ -555,7 +555,7 @@
 #endif /* CONFIG_AEC62XX_TUNING */
 }
 
-void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_aec62xx(struct ata_channel *hwif, unsigned long dmabase)
 {
 #ifdef CONFIG_AEC62XX_TUNING
 	unsigned long flags;
@@ -565,7 +565,7 @@
 	__cli();		/* local CPU only */
 
 	pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
-	pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+	pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->unit ? 0xF0 : 0x0F));
 
 	__restore_flags(flags);	/* local CPU only */
 #endif /* CONFIG_AEC62XX_TUNING */
diff -Nru a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
--- a/drivers/ide/ali14xx.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/ali14xx.c	Sun Apr 14 12:16:58 2002
@@ -134,7 +134,7 @@
 		drive->name, pio - XFER_PIO_0, time1, time2, param1, param2, param3, param4);
 
 	/* stuff timing parameters into controller registers */
-	driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
+	driveNum = (drive->channel->index << 1) + drive->select.b.unit;
 	save_flags(flags);	/* all CPUs */
 	cli();			/* all CPUs */
 	outb_p(regOn, basePort);
@@ -212,9 +212,8 @@
 	ide_hwifs[1].chipset = ide_ali14xx;
 	ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
 	ide_hwifs[1].tuneproc = &ali14xx_tune_drive;
-	ide_hwifs[0].mate = &ide_hwifs[1];
-	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
+	ide_hwifs[0].unit = ATA_PRIMARY;
+	ide_hwifs[1].unit = ATA_SECONDARY;
 
 	/* initialize controller registers */
 	if (!initRegisters()) {
diff -Nru a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
--- a/drivers/ide/alim15x3.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/alim15x3.c	Sun Apr 14 12:16:55 2002
@@ -242,13 +242,13 @@
 static void ali15x3_tune_drive (ide_drive_t *drive, byte pio)
 {
 	struct ata_timing *t;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	int s_time, a_time, c_time;
 	byte s_clc, a_clc, r_clc;
 	unsigned long flags;
-	int port = hwif->index ? 0x5c : 0x58;
-	int portFIFO = hwif->channel ? 0x55 : 0x54;
+	int port = hwif->unit ? 0x5c : 0x58;
+	int portFIFO = hwif->unit ? 0x55 : 0x54;
 	byte cd_dma_fifo = 0;
 
 	if (pio == 255)
@@ -305,11 +305,11 @@
 
 static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
 	byte tmpbyte		= 0x00;
-	int m5229_udma		= hwif->channel? 0x57 : 0x56;
+	int m5229_udma		= hwif->unit ? 0x57 : 0x56;
 	int err			= 0;
 
 	if (speed < XFER_UDMA_0) {
@@ -431,10 +431,10 @@
 
 static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
 {
-	struct hd_driveid *id		= drive->id;
-	ide_hwif_t *hwif		= HWIF(drive);
-	ide_dma_action_t dma_func	= ide_dma_on;
-	byte can_ultra_dma		= ali15x3_can_ultra(drive);
+	struct hd_driveid *id = drive->id;
+	struct ata_channel *hwif = drive->channel;
+	ide_dma_action_t dma_func = ide_dma_on;
+	byte can_ultra_dma = ali15x3_can_ultra(drive);
 
 	if ((m5229_revision<=0x20) && (drive->type != ATA_DISK))
 		return hwif->dmaproc(ide_dma_off_quietly, drive);
@@ -537,7 +537,7 @@
  * of UDMA66 transfers. It doesn't check the drives.
  * But see note 2 below!
  */
-unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif)
+unsigned int __init ata66_ali15x3(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned int ata66	= 0;
@@ -597,7 +597,7 @@
 		/*
 		 * Allow ata66 if cable of current channel has 80 pins
 		 */
-		ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+		ata66 = (hwif->unit)?cable_80_pin[1]:cable_80_pin[0];
 	} else {
 		/*
 		 * revision 0x20 (1543-E, 1543-F)
@@ -632,14 +632,14 @@
 	return(ata66);
 }
 
-void __init ide_init_ali15x3 (ide_hwif_t *hwif)
+void __init ide_init_ali15x3(struct ata_channel *hwif)
 {
 #ifndef CONFIG_SPARC64
 	byte ideic, inmir;
 	byte irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
 				      1, 11, 0, 12, 0, 14, 0, 15 };
 
-	hwif->irq = hwif->channel ? 15 : 14;
+	hwif->irq = hwif->unit ? 15 : 14;
 
 	if (isa_dev) {
 		/*
@@ -651,14 +651,14 @@
 		ideic = ideic & 0x03;
 
 		/* get IRQ for IDE Controller */
-		if ((hwif->channel && ideic == 0x03) || (!hwif->channel && !ideic)) {
+		if ((hwif->unit && ideic == 0x03) || (!hwif->unit && !ideic)) {
 			/*
 			 * get SIRQ1 routing table
 			 */
 			pci_read_config_byte(isa_dev, 0x44, &inmir);
 			inmir = inmir & 0x0f;
 			hwif->irq = irq_routing_table[inmir];
-		} else if (hwif->channel && !(ideic & 0x01)) {
+		} else if (hwif->unit && !(ideic & 0x01)) {
 			/*
 			 * get SIRQ2 routing table
 			 */
@@ -690,7 +690,7 @@
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
-void __init ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_ali15x3(struct ata_channel *hwif, unsigned long dmabase)
 {
 	if ((dmabase) && (m5229_revision < 0x20)) {
 		return;
diff -Nru a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
--- a/drivers/ide/amd74xx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/amd74xx.c	Sun Apr 14 12:16:59 2002
@@ -226,7 +226,7 @@
 
 static int amd_set_drive(ide_drive_t *drive, unsigned char speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_drive_t *peer = drive->channel->drives + (~drive->dn & 1);
 	struct ata_timing t, p;
 	int T, UT;
 
@@ -247,7 +247,7 @@
 
 	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
 
-	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+	amd_set_speed(drive->channel->pci_dev, drive->dn, &t);
 
 	if (!drive->init_speed)	
 		drive->init_speed = speed;
@@ -263,7 +263,7 @@
 
 static void amd74xx_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
-	if (!((amd_enabled >> HWIF(drive)->channel) & 1))
+	if (!((amd_enabled >> drive->channel->unit) & 1))
 		return;
 
 	if (pio == 255) {
@@ -287,7 +287,7 @@
 
 	if (func == ide_dma_check) {
 
-		short w80 = HWIF(drive)->udma_four;
+		short w80 = drive->channel->udma_four;
 
 		short speed = ata_timing_mode(drive,
 			XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
@@ -297,7 +297,7 @@
 
 		amd_set_drive(drive, speed);
 
-		func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+		func = (drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO)
 			? ide_dma_on : ide_dma_off_quietly;
 	}
 
@@ -409,12 +409,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_amd74xx(ide_hwif_t *hwif)
+unsigned int __init ata66_amd74xx(struct ata_channel *hwif)
 {
-	return ((amd_enabled & amd_80w) >> hwif->channel) & 1;
+	return ((amd_enabled & amd_80w) >> hwif->unit) & 1;
 }
 
-void __init ide_init_amd74xx(ide_hwif_t *hwif)
+void __init ide_init_amd74xx(struct ata_channel *hwif)
 {
 	int i;
 
@@ -426,7 +426,7 @@
 		hwif->drives[i].io_32bit = 1;
 		hwif->drives[i].unmask = 1;
 		hwif->drives[i].autotune = 1;
-		hwif->drives[i].dn = hwif->channel * 2 + i;
+		hwif->drives[i].dn = hwif->unit * 2 + i;
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -445,8 +445,8 @@
  * We allow the BM-DMA driver only work on enabled interfaces.
  */
 
-void __init ide_dmacapable_amd74xx(ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_amd74xx(struct ata_channel *hwif, unsigned long dmabase)
 {
-	if ((amd_enabled >> hwif->channel) & 1)
+	if ((amd_enabled >> hwif->unit) & 1)
 		ide_setup_dma(hwif, dmabase, 8);
 }
diff -Nru a/drivers/ide/buddha.c b/drivers/ide/buddha.c
--- a/drivers/ide/buddha.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/buddha.c	Sun Apr 14 12:16:58 2002
@@ -116,7 +116,7 @@
      *  Check and acknowledge the interrupt status
      */
 
-static int buddha_ack_intr(ide_hwif_t *hwif)
+static int buddha_ack_intr(struct ata_channel *hwif)
 {
     unsigned char ch;
 
@@ -126,7 +126,7 @@
     return 1;
 }
 
-static int xsurf_ack_intr(ide_hwif_t *hwif)
+static int xsurf_ack_intr(struct ata_channel *hwif)
 {
     unsigned char ch;
 
diff -Nru a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
--- a/drivers/ide/cmd640.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/cmd640.c	Sun Apr 14 12:16:58 2002
@@ -187,7 +187,7 @@
 /*
  * These are initialized to point at the devices we control
  */
-static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
+static struct ata_channel *cmd_hwif0, *cmd_hwif1;
 static ide_drive_t *cmd_drives[4];
 
 /*
@@ -429,7 +429,7 @@
 	cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */
 	cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */
 	for (i = 0; i < MAX_HWIFS; i++) {
-		ide_hwif_t *hwif = &ide_hwifs[i];
+		struct ata_channel *hwif = &ide_hwifs[i];
 		if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) {
 			if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0)
 				cmd_hwif0 = hwif;
@@ -689,7 +689,7 @@
 /*
  * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
  */
-int __init ide_probe_for_cmd640x (void)
+int __init ide_probe_for_cmd640x(void)
 {
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 	int second_port_toggled = 0;
@@ -793,9 +793,7 @@
 		cmd_hwif0->serialized = 1;
 		cmd_hwif1->serialized = 1;
 		cmd_hwif1->chipset = ide_cmd640;
-		cmd_hwif0->mate = cmd_hwif1;
-		cmd_hwif1->mate = cmd_hwif0;
-		cmd_hwif1->channel = 1;
+		cmd_hwif1->unit = ATA_SECONDARY;
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 		cmd_hwif1->tuneproc = &cmd640_tune_drive;
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
@@ -811,8 +809,8 @@
 		ide_drive_t *drive = cmd_drives[index];
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 		if (drive->autotune || ((index > 1) && second_port_toggled)) {
-	 		/*
-	 		 * Reset timing to the slowest speed and turn off prefetch.
+			/*
+			 * Reset timing to the slowest speed and turn off prefetch.
 			 * This way, the drive identify code has a better chance.
 			 */
 			setup_counts    [index] = 4;	/* max possible */
diff -Nru a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
--- a/drivers/ide/cmd64x.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/cmd64x.c	Sun Apr 14 12:16:57 2002
@@ -211,7 +211,7 @@
 static void program_drive_counts (ide_drive_t *drive, int setup_count, int active_count, int recovery_count)
 {
 	unsigned long flags;
-	ide_drive_t *drives = HWIF(drive)->drives;
+	ide_drive_t *drives = drive->channel->drives;
 	byte temp_b;
 	static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
 	static const byte recovery_counts[] =
@@ -224,7 +224,7 @@
 			{ DRWTIM0, DRWTIM1 },
 			{ DRWTIM2, DRWTIM3 }
 		};
-	int channel = (int) HWIF(drive)->channel;
+	int channel = drive->channel->unit;
 	int slave = (drives != drive);  /* Is this really the best way to determine this?? */
 
 	cmdprintk("program_drive_count parameters = s(%d),a(%d),r(%d),p(%d)\n", setup_count,
@@ -260,10 +260,10 @@
 	 * Program the address_setup clocks into ARTTIM reg,
 	 * and then the active/recovery counts into the DRWTIM reg
 	 */
-	(void) pci_read_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], &temp_b);
-	(void) pci_write_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave],
+	(void) pci_read_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], &temp_b);
+	(void) pci_write_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave],
 		((byte) setup_count) | (temp_b & 0x3f));
-	(void) pci_write_config_byte(HWIF(drive)->pci_dev, drwtim_regs[channel][slave],
+	(void) pci_write_config_byte(drive->channel->pci_dev, drwtim_regs[channel][slave],
 		(byte) ((active_count << 4) | recovery_count));
 	cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]);
 	cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]);
@@ -333,10 +333,10 @@
 		setup_count, active_count, recovery_count);
 }
 
-static byte cmd680_taskfile_timing (ide_hwif_t *hwif)
+static byte cmd680_taskfile_timing(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte addr_mask		= (hwif->channel) ? 0xB2 : 0xA2;
+	byte addr_mask		= (hwif->unit) ? 0xB2 : 0xA2;
 	unsigned short		timing;
 
 	pci_read_config_word(dev, addr_mask, &timing);
@@ -353,7 +353,7 @@
 
 static void cmd680_tuneproc (ide_drive_t *drive, byte mode_wanted)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte			drive_pci;
 	unsigned short		speedt;
@@ -394,10 +394,10 @@
 
 static void config_cmd680_chipset_for_pio (ide_drive_t *drive, byte set_speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	u8 unit			= (drive->select.b.unit & 0x01);
-	u8 addr_mask		= (hwif->channel) ? 0x84 : 0x80;
+	u8 addr_mask		= (hwif->unit) ? 0x84 : 0x80;
 	u8 speed		= 0x00;
 	u8 mode_pci		= 0x00;
 	u8 channel_timings	= cmd680_taskfile_timing(hwif);
@@ -420,7 +420,7 @@
 
 static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
 {
-        if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) {
+        if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680) {
 		config_cmd680_chipset_for_pio(drive, set_speed);
 	} else {
 		config_cmd64x_chipset_for_pio(drive, set_speed);
@@ -430,13 +430,13 @@
 static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed)
 {
 #ifdef CONFIG_BLK_DEV_IDEDMA
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	int err			= 0;
 
 	u8 unit			= (drive->select.b.unit & 0x01);
-	u8 pciU			= (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
-	u8 pciD			= (hwif->channel) ? BMIDESR1 : BMIDESR0;
+	u8 pciU			= (hwif->unit) ? UDIDETCR1 : UDIDETCR0;
+	u8 pciD			= (hwif->unit) ? BMIDESR1 : BMIDESR0;
 	u8 regU			= 0;
 	u8 regD			= 0;
 
@@ -498,9 +498,9 @@
 
 static int cmd680_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
-	u8 addr_mask		= (hwif->channel) ? 0x84 : 0x80;
+	u8 addr_mask		= (hwif->unit) ? 0x84 : 0x80;
 	u8 unit			= (drive->select.b.unit & 0x01);
 	u8 dma_pci		= 0;
 	u8 udma_pci		= 0;
@@ -615,7 +615,7 @@
 static int config_cmd64x_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte speed		= 0x00;
@@ -741,7 +741,7 @@
 
 static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
 {
-	if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680)
+	if (drive->channel->pci_dev->device == PCI_DEVICE_ID_CMD_680)
 		return (config_cmd680_chipset_for_dma(drive));
 	return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66));
 }
@@ -749,7 +749,7 @@
 static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned int class_rev	= 0;
 	byte can_ultra_33	= 0;
@@ -822,7 +822,7 @@
 no_dma_set:
 		config_chipset_for_pio(drive, 1);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 static int cmd680_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
@@ -841,9 +841,9 @@
 {
 	byte dma_stat		= 0;
 	byte dma_alt_stat	= 0;
-	byte mask		= (HWIF(drive)->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
-	unsigned long dma_base	= HWIF(drive)->dma_base;
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	byte mask		= (drive->channel->unit) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0;
+	unsigned long dma_base	= drive->channel->dma_base;
+	struct pci_dev *dev	= drive->channel->pci_dev;
 	byte jack_slap		= ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
 
 	switch (func) {
@@ -856,8 +856,8 @@
 			outb(dma_stat|6, dma_base+2);		/* clear the INTR & ERROR bits */
 			if (jack_slap) {
 				byte dma_intr	= 0;
-				byte dma_mask	= (HWIF(drive)->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
-				byte dma_reg	= (HWIF(drive)->channel) ? ARTTIM2 : CFR;
+				byte dma_mask	= (drive->channel->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0;
+				byte dma_reg	= (drive->channel->unit) ? ARTTIM2 : CFR;
 				(void) pci_read_config_byte(dev, dma_reg, &dma_intr);
 				/*
 				 * DAMN BMIDE is not connected to PCI space!
@@ -891,7 +891,7 @@
  */
 static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
 	byte dma_stat;
 
@@ -917,8 +917,8 @@
 static int cmd680_busproc (ide_drive_t * drive, int state)
 {
 #if 0
-	ide_hwif_t *hwif	= HWIF(drive);
-	u8 addr_mask		= (hwif->channel) ? 0xB0 : 0xA0;
+	struct ata_channel *hwif	= drive->channel;
+	u8 addr_mask		= (hwif->unit) ? 0xB0 : 0xA0;
 	u32 stat_config		= 0;
 
         pci_read_config_dword(hwif->pci_dev, addr_mask, &stat_config);
@@ -950,8 +950,8 @@
 static void cmd680_reset (ide_drive_t *drive)
 {
 #if 0
-	ide_hwif_t *hwif	= HWIF(drive);
-	u8 addr_mask		= (hwif->channel) ? 0xB0 : 0xA0;
+	struct ata_channel *hwif = drive->channel;
+	u8 addr_mask		= (hwif->unit) ? 0xB0 : 0xA0;
 	byte reset		= 0;
 
 	pci_read_config_byte(hwif->pci_dev, addr_mask, &reset);
@@ -1081,25 +1081,25 @@
 	return cmd64x_pci_init (dev);
 }
 
-unsigned int cmd680_ata66 (ide_hwif_t *hwif)
+unsigned int cmd680_ata66(struct ata_channel *hwif)
 {
 	byte ata66	= 0;
-	byte addr_mask	= (hwif->channel) ? 0xB0 : 0xA0;
+	byte addr_mask	= (hwif->unit) ? 0xB0 : 0xA0;
 
 	pci_read_config_byte(hwif->pci_dev, addr_mask, &ata66);
 	return (ata66 & 0x01) ? 1 : 0;
 }
 
-unsigned int cmd64x_ata66 (ide_hwif_t *hwif)
+unsigned int cmd64x_ata66(struct ata_channel *hwif)
 {
 	byte ata66 = 0;
-	byte mask = (hwif->channel) ? 0x02 : 0x01;
+	byte mask = (hwif->unit) ? 0x02 : 0x01;
 
 	pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
 	return (ata66 & mask) ? 1 : 0;
 }
 
-unsigned int __init ata66_cmd64x (ide_hwif_t *hwif)
+unsigned int __init ata66_cmd64x(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
 	if (dev->device == PCI_DEVICE_ID_CMD_680)
@@ -1107,7 +1107,7 @@
 	return cmd64x_ata66(hwif);
 }
 
-void __init ide_init_cmd64x (ide_hwif_t *hwif)
+void __init ide_init_cmd64x(struct ata_channel *hwif)
 {
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned int class_rev;
diff -Nru a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
--- a/drivers/ide/cs5530.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/cs5530.c	Sun Apr 14 12:16:59 2002
@@ -101,7 +101,7 @@
  * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
  */
 #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
-#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
+#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->unit ? 0x30 : 0x20))
 
 /*
  * cs5530_tuneproc() handles selection/setting of PIO modes
@@ -112,7 +112,7 @@
  */
 static void cs5530_tuneproc (ide_drive_t *drive, byte pio)	/* pio=255 means "autotune" */
 {
-	ide_hwif_t	*hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int	format, basereg = CS5530_BASEREG(hwif);
 
 	if (pio == 255)
@@ -134,7 +134,7 @@
 static int cs5530_config_dma (ide_drive_t *drive)
 {
 	int			udma_ok = 1, mode = 0;
-	ide_hwif_t		*hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	int			unit = drive->select.b.unit;
 	ide_drive_t		*mate = &hwif->drives[unit^1];
 	struct hd_driveid	*id = drive->id;
@@ -344,10 +344,9 @@
  * This gets invoked by the IDE driver once for each channel,
  * and performs channel-specific pre-initialization before drive probing.
  */
-void __init ide_init_cs5530 (ide_hwif_t *hwif)
+void __init ide_init_cs5530(struct ata_channel *hwif)
 {
-	if (hwif->mate)
-		hwif->serialized = hwif->mate->serialized = 1;
+	hwif->serialized = 1;
 	if (!hwif->dma_base) {
 		hwif->autodma = 0;
 	} else {
diff -Nru a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
--- a/drivers/ide/cy82c693.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/cy82c693.c	Sun Apr 14 12:16:56 2002
@@ -192,7 +192,7 @@
 	if (mode > drive->id->tDMA)  /* to be absolutly sure we have a valid mode */
 		mode = drive->id->tDMA;
 	
-        index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
+        index = (drive->channel->unit == 0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
 
 #if CY82C693_DEBUG_LOGS
        	/* for debug let's show the previous values */
@@ -200,7 +200,7 @@
 	OUT_BYTE(index, CY82_INDEX_PORT);
 	data = IN_BYTE(CY82_DATA_PORT);
 
-	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, (data&0x3), ((data>>2)&1));
+	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, (data&0x3), ((data>>2)&1));
 #endif /* CY82C693_DEBUG_LOGS */
 
 	data = (byte)mode|(byte)(single<<2);
@@ -209,7 +209,7 @@
 	OUT_BYTE(data, CY82_DATA_PORT);
 
 #if CY82C693_DEBUG_INFO
-	printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, mode, single);
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, mode, single);
 #endif /* CY82C693_DEBUG_INFO */
 
 	/* 
@@ -271,7 +271,7 @@
  */
 static void cy82c693_tune_drive (ide_drive_t *drive, byte pio)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	pio_clocks_t pclk;
 	unsigned int addrCtrl;
@@ -318,7 +318,7 @@
 		pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
 	}
 
-	printk (KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+	printk (KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->unit, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
 #endif /* CY82C693_DEBUG_LOGS */
 
         /* first let's calc the pio modes */
@@ -371,7 +371,7 @@
 	}	
 
 #if CY82C693_DEBUG_INFO
-	printk (KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->unit, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
 #endif /* CY82C693_DEBUG_INFO */
 }
 
@@ -431,7 +431,7 @@
 /*
  * the init function - called for each ide channel once
  */
-void __init ide_init_cy82c693(ide_hwif_t *hwif)
+void __init ide_init_cy82c693(struct ata_channel *hwif)
 {
 	hwif->chipset = ide_cy82c693;
 	hwif->tuneproc = cy82c693_tune_drive;
diff -Nru a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
--- a/drivers/ide/dtc2278.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/dtc2278.c	Sun Apr 14 12:16:58 2002
@@ -89,7 +89,7 @@
 	 * 32bit I/O has to be enabled for *both* drives at the same time.
 	 */
 	drive->io_32bit = 1;
-	HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
+	drive->channel->drives[!drive->select.b.unit].io_32bit = 1;
 }
 
 void __init init_dtc2278 (void)
@@ -124,7 +124,6 @@
 	ide_hwifs[0].drives[1].no_unmask = 1;
 	ide_hwifs[1].drives[0].no_unmask = 1;
 	ide_hwifs[1].drives[1].no_unmask = 1;
-	ide_hwifs[0].mate = &ide_hwifs[1];
-	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
+	ide_hwifs[0].unit = ATA_PRIMARY;
+	ide_hwifs[1].unit = ATA_SECONDARY;
 }
diff -Nru a/drivers/ide/gayle.c b/drivers/ide/gayle.c
--- a/drivers/ide/gayle.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/gayle.c	Sun Apr 14 12:16:56 2002
@@ -84,7 +84,7 @@
      *  Check and acknowledge the interrupt status
      */
 
-static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+static int gayle_ack_intr_a4000(struct ata_channel *hwif)
 {
     unsigned char ch;
 
@@ -94,7 +94,7 @@
     return 1;
 }
 
-static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+static int gayle_ack_intr_a1200(struct ata_channel *hwif)
 {
     unsigned char ch;
 
diff -Nru a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c
--- a/drivers/ide/hpt34x.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/hpt34x.c	Sun Apr 14 12:16:55 2002
@@ -98,12 +98,12 @@
 	unsigned int reg1	= 0, tmp1 = 0;
 	unsigned int reg2	= 0, tmp2 = 0;
 
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
-	tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
+	pci_read_config_dword(drive->channel->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(drive->channel->pci_dev, 0x48, &reg2);
+	tmp1 = ((0x00 << (3 * drive->dn)) | (reg1 & ~(7 << (3 * drive->dn))));
 	tmp2 = (reg2 & ~(0x11 << drive->dn));
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+	pci_write_config_dword(drive->channel->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(drive->channel->pci_dev, 0x48, tmp2);
 }
 
 static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed)
@@ -122,13 +122,13 @@
 		lo_speed >>= 5;
 	}
 
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
+	pci_read_config_dword(drive->channel->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(drive->channel->pci_dev, 0x48, &reg2);
 	tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
 	tmp2 = ((hi_speed << drive->dn) | reg2);
 	err = ide_config_drive_speed(drive, speed);
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
-	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+	pci_write_config_dword(drive->channel->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(drive->channel->pci_dev, 0x48, tmp2);
 
 	if (!drive->init_speed)
 		drive->init_speed = speed;
@@ -254,7 +254,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -301,7 +301,7 @@
 		dma_func = ide_dma_off;
 #endif /* CONFIG_HPT34X_AUTODMA */
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -314,7 +314,7 @@
 
 int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
 	unsigned int count, reading = 0;
 	byte dma_stat;
@@ -334,6 +334,7 @@
 			drive->waiting_for_dma = 1;
 			if (drive->type != ATA_DISK)
 				return 0;
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);	/* issue cmd to drive */
 			OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 			return 0;
@@ -408,7 +409,7 @@
 	return dev->irq;
 }
 
-void __init ide_init_hpt34x (ide_hwif_t *hwif)
+void __init ide_init_hpt34x(struct ata_channel *hwif)
 {
 	hwif->tuneproc = &hpt34x_tune_drive;
 	hwif->speedproc = &hpt34x_tune_chipset;
diff -Nru a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
--- a/drivers/ide/hpt366.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/hpt366.c	Sun Apr 14 12:16:56 2002
@@ -75,8 +75,6 @@
 #include <linux/proc_fs.h>
 #endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
 
-extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
-
 const char *quirk_drives[] = {
 	"QUANTUM FIREBALLlct08 08",
 	"QUANTUM FIREBALLP KA6.4",
@@ -485,7 +483,7 @@
 static void hpt366_tune_chipset (ide_drive_t *drive, byte speed)
 {
 	byte regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
-	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
+	byte regfast		= (drive->channel->unit) ? 0x55 : 0x51;
 			/*
 			 * since the channel is always 0 it does not matter.
 			 */
@@ -497,11 +495,11 @@
 	/*
 	 * Disable the "fast interrupt" prediction. 
 	 */
-	pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast);
+	pci_read_config_byte(drive->channel->pci_dev, regfast, &drive_fast);
 	if (drive_fast & 0x02)
-		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20);
+		pci_write_config_byte(drive->channel->pci_dev, regfast, drive_fast & ~0x20);
 
-	pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);
+	pci_read_config_dword(drive->channel->pci_dev, regtime, &reg1);
 	/* detect bus speed by looking at control reg timing: */
 	switch((reg1 >> 8) & 7) {
 		case 5:
@@ -531,18 +529,18 @@
 	}	
 	reg2 &= ~0x80000000;
 
-	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
+	pci_write_config_dword(drive->channel->pci_dev, regtime, reg2);
 }
 
 static void hpt370_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
+	byte regfast		= (drive->channel->unit) ? 0x55 : 0x51;
 	unsigned int list_conf	= 0;
 	unsigned int drive_conf = 0;
 	unsigned int conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
 	byte drive_pci		= 0x40 + (drive->dn * 4);
 	byte new_fast, drive_fast		= 0;
-	struct pci_dev *dev 	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= drive->channel->pci_dev;
 
 	/*
 	 * Disable the "fast interrupt" prediction.
@@ -561,7 +559,7 @@
 		new_fast |= 0x01;
 #endif
 	if (new_fast != drive_fast)
-		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, new_fast);
+		pci_write_config_byte(drive->channel->pci_dev, regfast, new_fast);
 
 	list_conf = pci_bus_clock_list(speed, 
 				       (struct chipset_bus_clock_list_entry *)
@@ -585,7 +583,7 @@
 	if (!drive->init_speed)
 		drive->init_speed = speed;
 
-	if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {
+	if (pci_rev_check_hpt3xx(drive->channel->pci_dev)) {
 		hpt370_tune_chipset(drive, speed);
         } else {
                 hpt366_tune_chipset(drive, speed);
@@ -670,7 +668,7 @@
 	if ((id->dma_ultra & 0x0020) &&
 	    (!check_in_drive_lists(drive, bad_ata100_5)) &&
 	    (HPT370_ALLOW_ATA100_5) &&
-	    (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) &&
+	    (pci_rev_check_hpt3xx(drive->channel->pci_dev)) &&
 	    (ultra66)) {
 		speed = XFER_UDMA_5;
 	} else if ((id->dma_ultra & 0x0010) &&
@@ -720,23 +718,23 @@
 	if (drive->quirk_list) {
 		/* drives in the quirk_list may not like intr setups/cleanups */
 	} else {
-		OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE((drive)->ctl|2, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
 	}
 }
 
 void hpt3xx_maskproc (ide_drive_t *drive, int mask)
 {
 	if (drive->quirk_list) {
-		if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) {
+		if (pci_rev_check_hpt3xx(drive->channel->pci_dev)) {
 			byte reg5a = 0;
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5a);
+			pci_read_config_byte(drive->channel->pci_dev, 0x5a, &reg5a);
 			if (((reg5a & 0x10) >> 4) != mask)
-				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
+				pci_write_config_byte(drive->channel->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
 		} else {
 			if (mask) {
-				disable_irq(HWIF(drive)->irq);
+				disable_irq(drive->channel->irq);
 			} else {
-				enable_irq(HWIF(drive)->irq);
+				enable_irq(drive->channel->irq);
 			}
 		}
 	} else {
@@ -750,7 +748,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -791,7 +789,7 @@
 
 		config_chipset_for_pio(drive);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -803,7 +801,7 @@
 int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
 	byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0;
-	unsigned long dma_base = HWIF(drive)->dma_base;
+	unsigned long dma_base = drive->channel->dma_base;
 
 	switch (func) {
 		case ide_dma_check:
@@ -812,21 +810,19 @@
 			dma_stat = inb(dma_base+2);
 			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 		case ide_dma_lostirq:
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5ah);
-			printk("%s: (%s)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
-				drive->name,
-				ide_dmafunc_verbose(func),
-				reg50h, reg52h, reg5ah);
+			pci_read_config_byte(drive->channel->pci_dev, 0x50, &reg50h);
+			pci_read_config_byte(drive->channel->pci_dev, 0x52, &reg52h);
+			pci_read_config_byte(drive->channel->pci_dev, 0x5a, &reg5ah);
+			printk("%s: (ide_dma_lostirq)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
+				drive->name, reg50h, reg52h, reg5ah);
 			if (reg5ah & 0x10)
-				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10);
+				pci_write_config_byte(drive->channel->pci_dev, 0x5a, reg5ah & ~0x10);
 			/* fall through to a reset */
 #if 0
 		case ide_dma_begin:
 		case ide_dma_end:
 			/* reset the chips state over and over.. */
-			pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13);
+			pci_write_config_byte(drive->channel->pci_dev, 0x51, 0x13);
 #endif
 			break;
 		case ide_dma_timeout:
@@ -838,10 +834,10 @@
 
 int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
-	byte regstate = hwif->channel ? 0x54 : 0x50;
-	byte reginfo = hwif->channel ? 0x56 : 0x52;
+	byte regstate = hwif->unit ? 0x54 : 0x50;
+	byte reginfo = hwif->unit ? 0x56 : 0x52;
 	byte dma_stat;
 
 	switch (func) {
@@ -899,23 +895,23 @@
 void hpt3xx_reset (ide_drive_t *drive)
 {
 #if 0
-	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
-	byte reset		= (HWIF(drive)->channel) ? 0x80 : 0x40;
+	unsigned long high_16	= pci_resource_start(drive->channel->pci_dev, 4);
+	byte reset		= (drive->channel->unit) ? 0x80 : 0x40;
 	byte reg59h		= 0;
 
-	pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, &reg59h);
-	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset);
-	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);
+	pci_read_config_byte(drive->channel->pci_dev, 0x59, &reg59h);
+	pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h|reset);
+	pci_write_config_byte(drive->channel->pci_dev, 0x59, reg59h);
 #endif
 }
 
 #if 0
 static int hpt3xx_tristate (ide_drive_t * drive, int state)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif	= drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte reset		= (hwif->channel) ? 0x80 : 0x40;
-	byte state_reg		= (hwif->channel) ? 0x57 : 0x53;
+	byte reset		= (hwif->unit) ? 0x80 : 0x40;
+	byte state_reg		= (hwif->unit) ? 0x57 : 0x53;
 	byte reg59h		= 0;
 	byte regXXh		= 0;
 
@@ -951,7 +947,7 @@
 #define TRISTATE_BIT  0x8000
 static int hpt370_busproc(ide_drive_t * drive, int state)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte tristate, resetmask, bus_reg;
 	u16 tri_reg;
 
@@ -960,7 +956,7 @@
 
 	hwif->bus_state = state;
 
-	if (hwif->channel) { 
+	if (hwif->unit) { 
 		/* secondary channel */
 		tristate = 0x56;
 		resetmask = 0x80; 
@@ -1125,32 +1121,32 @@
 
 	if (n_hpt_devs < HPT366_MAX_DEVS)
 		hpt_devs[n_hpt_devs++] = dev;
-	
+
 #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
 	if (!hpt366_proc) {
 		hpt366_proc = 1;
 		hpt366_display_info = &hpt366_get_info;
 	}
-#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
+#endif
 
 	return dev->irq;
 }
 
-unsigned int __init ata66_hpt366 (ide_hwif_t *hwif)
+unsigned int __init ata66_hpt366(struct ata_channel *hwif)
 {
 	byte ata66	= 0;
-	byte regmask	= (hwif->channel) ? 0x01 : 0x02;
+	byte regmask	= (hwif->unit) ? 0x01 : 0x02;
 
 	pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);
 #ifdef DEBUG
 	printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
 		ata66, (ata66 & regmask) ? "33" : "66",
 		PCI_FUNC(hwif->pci_dev->devfn));
-#endif /* DEBUG */
+#endif
 	return ((ata66 & regmask) ? 0 : 1);
 }
 
-void __init ide_init_hpt366 (ide_hwif_t *hwif)
+void __init ide_init_hpt366(struct ata_channel *hwif)
 {
 	int hpt_rev;
 
@@ -1210,12 +1206,12 @@
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
-void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_hpt366(struct ata_channel *hwif, unsigned long dmabase)
 {
 	byte masterdma = 0, slavedma = 0;
 	byte dma_new = 0, dma_old = inb(dmabase+2);
-	byte primary	= hwif->channel ? 0x4b : 0x43;
-	byte secondary	= hwif->channel ? 0x4f : 0x47;
+	byte primary	= hwif->unit ? 0x4b : 0x43;
+	byte secondary	= hwif->unit ? 0x4f : 0x47;
 	unsigned long flags;
 
 	__save_flags(flags);	/* local CPU only */
diff -Nru a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
--- a/drivers/ide/ht6560b.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/ht6560b.c	Sun Apr 14 12:16:56 2002
@@ -319,10 +319,9 @@
 			ide_hwifs[1].tuneproc = &tune_ht6560b;
 			ide_hwifs[0].serialized = 1;  /* is this needed? */
 			ide_hwifs[1].serialized = 1;  /* is this needed? */
-			ide_hwifs[0].mate = &ide_hwifs[1];
-			ide_hwifs[1].mate = &ide_hwifs[0];
-			ide_hwifs[1].channel = 1;
-			
+			ide_hwifs[0].unit = ATA_PRIMARY;
+			ide_hwifs[1].unit = ATA_SECONDARY;
+
 			/*
 			 * Setting default configurations for drives
 			 */
diff -Nru a/drivers/ide/icside.c b/drivers/ide/icside.c
--- a/drivers/ide/icside.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/icside.c	Sun Apr 14 12:16:55 2002
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 
 extern char *ide_xfer_verbose (byte xfer_rate);
-extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
 
 /*
  * Maximum number of interfaces per card
@@ -224,7 +223,7 @@
 #define NR_ENTRIES 256
 #define TABLE_SIZE (NR_ENTRIES * 8)
 
-static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
+static int ide_build_sglist(struct ata_channel *hwif, struct request *rq)
 {
 	request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
 	struct scatterlist *sg = hwif->sg_table;
@@ -245,16 +244,16 @@
 static int
 icside_build_dmatable(ide_drive_t *drive, int reading)
 {
-	return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+	return drive->channel->sg_nents = ide_build_sglist(drive->channel, HWGROUP(drive)->rq);
 }
 
 /* Teardown mappings after DMA has completed.  */
 static void icside_destroy_dmatable(ide_drive_t *drive)
 {
-	struct scatterlist *sg = HWIF(drive)->sg_table;
-	int nents = HWIF(drive)->sg_nents;
+	struct scatterlist *sg = drive->channel->sg_table;
+	int nents = drive->channel->sg_nents;
 
-	pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
+	pci_unmap_sg(NULL, sg, nents, drive->channel->sg_dma_direction);
 }
 
 /*
@@ -333,7 +332,7 @@
 	int i;
 	byte stat, dma_stat;
 
-	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -356,7 +355,7 @@
 icside_dma_check(ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	int autodma = hwif->autodma;
 	int xfer_mode = XFER_PIO_2;
 	int func = ide_dma_off_quietly;
@@ -397,7 +396,7 @@
 static int
 icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	int count, reading = 0;
 
 	switch (func) {
@@ -436,14 +435,15 @@
 		 */
 		set_dma_speed(hwif->hw.dma, drive->drive_data);
 
-		set_dma_sg(hwif->hw.dma, HWIF(drive)->sg_table, count);
+		set_dma_sg(hwif->hw.dma, drive->channel->sg_table, count);
 		set_dma_mode(hwif->hw.dma, reading ? DMA_MODE_READ
 			     : DMA_MODE_WRITE);
 
 		drive->waiting_for_dma = 1;
-		if (drive->media != ide_disk)
+		if (drive->type != ATA_DISK)
 			return 0;
 
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL);
 		OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA,
 			 IDE_COMMAND_REG);
@@ -466,14 +466,13 @@
 
 	case ide_dma_timeout:
 	default:
-		printk("icside_dmaproc: unsupported %s func: %d\n",
-			ide_dmafunc_verbose(func), func);
+		printk("icside_dmaproc: unsupported function: %d\n", func);
 	}
 	return 1;
 }
 
 static int
-icside_setup_dma(ide_hwif_t *hwif, int autodma)
+icside_setup_dma(struct ata_channel *hwif, int autodma)
 {
 	printk("    %s: SG-DMA", hwif->name);
 
@@ -498,7 +497,7 @@
 	return 0;
 }
 
-void ide_release_dma(ide_hwif_t *hwif)
+void ide_release_dma(struct ata_channel *hwif)
 {
 	if (hwif->sg_table) {
 		kfree(hwif->sg_table);
@@ -507,10 +506,10 @@
 }
 #endif
 
-static ide_hwif_t *
+static struct ata_channel *
 icside_find_hwif(unsigned long dataport)
 {
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	int index;
 
 	for (index = 0; index < MAX_HWIFS; ++index) {
@@ -530,11 +529,11 @@
 	return hwif;
 }
 
-static ide_hwif_t *
+static struct ata_channel *
 icside_setup(unsigned long base, struct cardinfo *info, int irq)
 {
 	unsigned long port = base + info->dataoffset;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	hwif = icside_find_hwif(base);
 	if (hwif) {
@@ -562,7 +561,7 @@
 static int __init icside_register_v5(struct expansion_card *ec, int autodma)
 {
 	unsigned long slot_port;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	slot_port = ecard_address(ec, ECARD_MEMC, 0);
 
@@ -584,7 +583,8 @@
 static int __init icside_register_v6(struct expansion_card *ec, int autodma)
 {
 	unsigned long slot_port, port;
-	ide_hwif_t *hwif, *mate;
+	struct ata_channel *hwif;
+	struct ata_channel *mate;
 	int sel = 0;
 
 	slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
@@ -620,7 +620,7 @@
 			hwif->hw.dma  = ec->dma;
 			hwif->hw.priv = (void *)
 					(port + ICS_ARCIN_V6_INTRSTAT_1);
-			hwif->channel = 0;
+			hwif->unit = 0;
 			icside_setup_dma(hwif, autodma);
 		}
 		if (mate) {
@@ -629,7 +629,7 @@
 			mate->hw.dma  = ec->dma;
 			mate->hw.priv = (void *)
 					(port + ICS_ARCIN_V6_INTRSTAT_2);
-			mate->channel = 1;
+			mate->unit = 1;
 			icside_setup_dma(mate, autodma);
 		}
 	}
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/ide-cd.c	Sun Apr 14 12:16:58 2002
@@ -512,7 +512,7 @@
 #endif /* not VERBOSE_IDE_CD_ERRORS */
 }
 
-static void cdrom_queue_request_sense(ide_drive_t *drive, 
+static void cdrom_queue_request_sense(ide_drive_t *drive,
 				      struct completion *wait,
 				      struct request_sense *sense,
 				      struct packet_command *failed_command)
@@ -536,7 +536,7 @@
 	rq->flags = REQ_SENSE;
 	rq->special = (char *) pc;
 	rq->waiting = wait;
-	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
+	ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
 
@@ -554,6 +554,7 @@
 	if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
 		uptodate = 1;
 
+	HWGROUP(drive)->rq->special = NULL;
 	ide_end_request(drive, uptodate);
 }
 
@@ -723,9 +724,9 @@
 
 	if (info->dma) {
 		if (info->cmd == READ) {
-			info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
+			info->dma = !drive->channel->dmaproc(ide_dma_read, drive);
 		} else if (info->cmd == WRITE) {
-			info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive);
+			info->dma = !drive->channel->dmaproc(ide_dma_write, drive);
 		} else {
 			printk("ide-cd: DMA set, but not allowed\n");
 		}
@@ -740,11 +741,12 @@
 	OUT_BYTE (xferlen >> 8  , IDE_HCYL_REG);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
- 
+
 	if (info->dma)
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 
 	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry);
 		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
 		return ide_started;
@@ -787,6 +789,7 @@
 	}
 
 	/* Arm the interrupt handler. */
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, handler, timeout, cdrom_timer_expiry);
 
 	/* Send the command to the device. */
@@ -899,8 +902,8 @@
 	/* Check for errors. */
 	if (dma) {
 		info->dma = 0;
-		if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive)))
-			HWIF(drive)->dmaproc(ide_dma_off, drive);
+		if ((dma_error = drive->channel->dmaproc(ide_dma_end, drive)))
+			drive->channel->dmaproc(ide_dma_off, drive);
 	}
 
 	if (cdrom_decode_status (&startstop, drive, 0, &stat))
@@ -1005,7 +1008,9 @@
 
 	/* Done moving data!
 	   Wait for another interrupt. */
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL);
+
 	return ide_started;
 }
 
@@ -1335,6 +1340,8 @@
 	}
 
 	/* Now we wait for another interrupt. */
+
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
 	return ide_started;
 }
@@ -1476,9 +1483,9 @@
 	/* Check for errors. */
 	if (dma) {
 		info->dma = 0;
-		if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) {
+		if ((dma_error = drive->channel->dmaproc(ide_dma_end, drive))) {
 			printk("ide-cd: write dma error\n");
-			HWIF(drive)->dmaproc(ide_dma_off, drive);
+			drive->channel->dmaproc(ide_dma_off, drive);
 		}
 	}
 
@@ -1559,6 +1566,7 @@
 	}
 
 	/* re-arm handler */
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);
 	return ide_started;
 }
@@ -2021,14 +2029,14 @@
 
 	/* Now try to get the total cdrom capacity. */
 	minor = (drive->select.b.unit) << PARTN_BITS;
-	dev = mk_kdev(HWIF(drive)->major, minor);
+	dev = mk_kdev(drive->channel->major, minor);
 	stat = cdrom_get_last_written(dev, &toc->capacity);
 	if (stat)
 		stat = cdrom_read_capacity(drive, &toc->capacity, sense);
 	if (stat)
 		toc->capacity = 0x1fffff;
 
-	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
+	drive->channel->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
 
 	/* Remember that we've read this stuff. */
@@ -2487,7 +2495,7 @@
 	struct cdrom_device_info *devinfo = &info->devinfo;
 	int minor = (drive->select.b.unit) << PARTN_BITS;
 
-	devinfo->dev = mk_kdev(HWIF(drive)->major, minor);
+	devinfo->dev = mk_kdev(drive->channel->major, minor);
 	devinfo->ops = &ide_cdrom_dops;
 	devinfo->mask = 0;
 	*(int *)&devinfo->speed = CDROM_STATE_FLAGS (drive)->current_speed;
@@ -2519,7 +2527,7 @@
 	 */
 
 	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
-				     HWIF(drive)->major, minor,
+				     drive->channel->major, minor,
 				     S_IFBLK | S_IRUGO | S_IWUGO,
 				     ide_fops, NULL);
 
@@ -2661,7 +2669,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
-		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
+		(void) drive->channel->dmaproc(ide_dma_verbose, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	printk("\n");
 
@@ -2684,8 +2692,8 @@
 	/*
 	 * default to read-only always and fix latter at the bottom
 	 */
-	set_device_ro(mk_kdev(HWIF(drive)->major, minor), 1);
-	set_blocksize(mk_kdev(HWIF(drive)->major, minor), CD_FRAMESIZE);
+	set_device_ro(mk_kdev(drive->channel->major, minor), 1);
+	set_blocksize(mk_kdev(drive->channel->major, minor), CD_FRAMESIZE);
 	blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE);
 
 	blk_queue_prep_rq(&drive->queue, ll_10byte_cmd_build);
@@ -2807,7 +2815,7 @@
 	nslots = ide_cdrom_probe_capabilities (drive);
 
 	if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
-		set_device_ro(mk_kdev(HWIF(drive)->major, minor), 0);
+		set_device_ro(mk_kdev(drive->channel->major, minor), 0);
 
 	if (ide_cdrom_register (drive, nslots)) {
 		printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
@@ -2854,7 +2862,7 @@
 static
 int ide_cdrom_check_media_change (ide_drive_t *drive)
 {
-	return cdrom_media_changed(mk_kdev (HWIF (drive)->major,
+	return cdrom_media_changed(mk_kdev (drive->channel->major,
 			(drive->select.b.unit) << PARTN_BITS));
 }
 
@@ -2875,14 +2883,14 @@
 
 	/* for general /dev/cdrom like mounting, one big disc */
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
-	HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
+	drive->channel->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
 
 	/*
 	 * reset block size, ide_revalidate_disk incorrectly sets it to
 	 * 1024 even for CDROM's
 	 */
-	blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
-	set_blocksize(mk_kdev(HWIF(drive)->major, minor), CD_FRAMESIZE);
+	blk_size[drive->channel->major] = drive->channel->gd->sizes;
+	set_blocksize(mk_kdev(drive->channel->major, minor), CD_FRAMESIZE);
 }
 
 static
@@ -2984,15 +2992,14 @@
 		memset (info, 0, sizeof (struct cdrom_info));
 		drive->driver_data = info;
 
-		/* ATA-PATTERN */
-		ata_ops(drive)->busy++;
+		MOD_INC_USE_COUNT;
 		if (ide_cdrom_setup (drive)) {
-			ata_ops(drive)->busy--;
+			MOD_DEC_USE_COUNT;
 			if (ide_cdrom_cleanup (drive))
 				printk ("%s: ide_cdrom_cleanup failed in ide_cdrom_init\n", drive->name);
 			continue;
 		}
-		ata_ops(drive)->busy--;
+		MOD_DEC_USE_COUNT;
 
 		failed--;
 	}
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/ide/ide-disk.c	Sun Apr 14 12:16:54 2002
@@ -1,34 +1,16 @@
 /*
- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 1994-1998  Linus Torvalds and authors:
  *
- *  Mostly written by Mark Lord <mlord@pobox.com>
- *                and Gadi Oxman <gadio@netvision.net.il>
- *                and Andre Hedrick <andre@linux-ide.org>
+ *	Mark Lord <mlord@pobox.com>
+ *	Gadi Oxman <gadio@netvision.net.il>
+ *	Andre Hedrick <andre@linux-ide.org>
+ *	Jens Axboe <axboe@suse.de>
+ *	Marcin Dalecki <dalecki@evision.ag>
  *
- * This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
- *
- * Version 1.00		move disk only code from ide.c to ide-disk.c
- *			support optional byte-swapping of all data
- * Version 1.01		fix previous byte-swapping code
- * Version 1.02		remove ", LBA" from drive identification msgs
- * Version 1.03		fix display of id->buf_size for big-endian
- * Version 1.04		add /proc configurable settings and S.M.A.R.T support
- * Version 1.05		add capacity support for ATA3 >= 8GB
- * Version 1.06		get boot-up messages to show full cyl count
- * Version 1.07		disable door-locking if it fails
- * Version 1.08		fixed CHS/LBA translations for ATA4 > 8GB,
- *			process of adding new ATA4 compliance.
- *			fixed problems in allowing fdisk to see
- *			the entire disk.
- * Version 1.09		added increment of rq->sector in ide_multwrite
- *			added UDMA 3/4 reporting
- * Version 1.10		request queue changes, Ultra DMA 100
- * Version 1.11		Highmem I/O support, Jens Axboe <axboe@suse.de>
- * Version 1.12		added 48-bit lba
- * Version 1.13		adding taskfile io access method
+ * This is the ATA disk device driver, as evolved from hd.c and ide.c.
  */
 
-#define IDEDISK_VERSION	"1.13"
+#define IDEDISK_VERSION	"1.14"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -51,13 +33,13 @@
 #include <asm/io.h>
 
 #ifdef CONFIG_BLK_DEV_PDC4030
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
+#define IS_PDC4030_DRIVE (drive->channel->chipset == ide_pdc4030)
 #else
 #define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
 #endif
 
 /*
- * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
+ * Perform a sanity check on the claimed "lba_capacity"
  * value for this drive (from its reported identification information).
  *
  * Returns:	1 if lba_capacity looks sensible
@@ -65,7 +47,7 @@
  *
  * It is called only once for each drive.
  */
-static int lba_capacity_is_ok (struct hd_driveid *id)
+static int lba_capacity_is_ok(struct hd_driveid *id)
 {
 	unsigned long lba_sects, chs_sects, head, tail;
 
@@ -106,165 +88,163 @@
 	return 0;	/* lba_capacity value may be bad */
 }
 
-static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block);
-static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block);
-
 /*
- * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS
- * otherwise, to address sectors.  It also takes care of issuing special
- * DRIVE_CMDs.
+ * Determine the apriopriate hardware command correspnding to the action in
+ * question, depending upon the device capabilities and setup.
  */
-static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
-{
-	/*
-	 * Wait until all request have bin finished.
-	 */
-
-	while (drive->blocked) {
-		yield();
-		// panic("ide: Request while drive blocked?");
-	}
-
-	if (!(rq->flags & REQ_CMD)) {
-		blk_dump_rq_flags(rq, "idedisk_do_request - bad command");
-		ide_end_request(drive, 0);
-		return ide_stopped;
-	}
-
-	if (IS_PDC4030_DRIVE) {
-		extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long);
-
-		return promise_rw_disk(drive, rq, block);
-	}
-
-	/* 48-bit LBA */
-	if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))
-		return lba48_do_request(drive, rq, block);
-
-	/* 28-bit LBA */
-	if (drive->select.b.lba)
-		return lba28_do_request(drive, rq, block);
-
-	/* 28-bit CHS */
-	return chs_do_request(drive, rq, block);
-}
-
-static task_ioreg_t get_command(ide_drive_t *drive, int cmd)
+static u8 get_command(ide_drive_t *drive, int cmd)
 {
 	int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
+	/* Well, calculating the command in this variable may be an
+	 * overoptimization. */
+	u8 command = WIN_NOP;
 
 #if 1
 	lba48bit = drive->addressing;
 #endif
 
-	if (cmd == READ) {
-		if (drive->using_dma)
-			return (lba48bit) ? WIN_READDMA_EXT : WIN_READDMA;
-		else if (drive->mult_count)
-			return (lba48bit) ? WIN_MULTREAD_EXT : WIN_MULTREAD;
-		else
-			return (lba48bit) ? WIN_READ_EXT : WIN_READ;
-	} else if (cmd == WRITE) {
-		if (drive->using_dma)
-			return (lba48bit) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
-		else if (drive->mult_count)
-			return (lba48bit) ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
+	/*
+	 * 48-bit commands are pretty sanely laid out
+	 */
+	if (lba48bit) {
+		if (cmd == READ)
+			command = WIN_READ_EXT;
 		else
-			return (lba48bit) ? WIN_WRITE_EXT : WIN_WRITE;
+			command = WIN_WRITE_EXT;
+
+		if (drive->using_dma) {
+			command++;		/* WIN_*DMA_EXT */
+			if (drive->using_tcq)
+				command++;	/* WIN_*DMA_QUEUED_EXT */
+		} else if (drive->mult_count)
+			command += 5;		/* WIN_MULT*_EXT */
+	} else {
+		/*
+		 * 28-bit commands seem not to be, though...
+		 */
+		if (cmd == READ) {
+			if (drive->using_dma) {
+				if (drive->using_tcq)
+					command = WIN_READDMA_QUEUED;
+				else
+					command = WIN_READDMA;
+			} else if (drive->mult_count)
+				command = WIN_MULTREAD;
+			else
+				command = WIN_READ;
+		} else {
+			if (drive->using_dma) {
+				if (drive->using_tcq)
+					command = WIN_WRITEDMA_QUEUED;
+				else
+					command = WIN_WRITEDMA;
+			} else if (drive->mult_count)
+				command = WIN_MULTWRITE;
+			else
+				command = WIN_WRITE;
+		}
 	}
-	return WIN_NOP;
+
+	return command;
 }
 
-static ide_startstop_t chs_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t chs_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block)
 {
-	struct hd_drive_task_hdr	taskfile;
-	struct hd_drive_hob_hdr		hobfile;
-	ide_task_t			args;
-	int				sectors;
-
-	task_ioreg_t command	= get_command(drive, rq_data_dir(rq));
+	struct ata_taskfile *args = &ar->ar_task;
+	struct request *rq = ar->ar_rq;
+	int sectors = rq->nr_sectors;
 
-	unsigned int track	= (block / drive->sect);
-	unsigned int sect	= (block % drive->sect) + 1;
-	unsigned int head	= (track % drive->head);
-	unsigned int cyl	= (track / drive->head);
+	unsigned int track = (block / drive->sect);
+	unsigned int sect = (block % drive->sect) + 1;
+	unsigned int head = (track % drive->head);
+	unsigned int cyl = (track / drive->head);
 
-	memset(&taskfile, 0, sizeof(task_struct_t));
-	memset(&hobfile, 0, sizeof(hob_struct_t));
+	memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr));
+	memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 
-	sectors = rq->nr_sectors;
 	if (sectors == 256)
 		sectors = 0;
 
-	taskfile.sector_count	= sectors;
-	taskfile.sector_number	= sect;
-	taskfile.low_cylinder	= cyl;
-	taskfile.high_cylinder	= (cyl>>8);
-	taskfile.device_head	= head;
-	taskfile.device_head	|= drive->select.all;
-	taskfile.command	= command;
+	if (ar->ar_flags & ATA_AR_QUEUED) {
+		unsigned long flags;
+
+		args->taskfile.feature = sectors;
+		args->taskfile.sector_count = ar->ar_tag << 3;
+
+		spin_lock_irqsave(DRIVE_LOCK(drive), flags);
+		blkdev_dequeue_request(rq);
+		spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
+	} else
+		args->taskfile.sector_count   = sectors;
+
+	args->taskfile.sector_number = sect;
+	args->taskfile.low_cylinder = cyl;
+	args->taskfile.high_cylinder = (cyl>>8);
+
+	args->taskfile.device_head = head;
+	args->taskfile.device_head |= drive->select.all;
+	args->taskfile.command = get_command(drive, rq_data_dir(rq));
 
 #ifdef DEBUG
 	printk("%s: %sing: ", drive->name,
 		(rq_data_dir(rq)==READ) ? "read" : "writ");
-	if (lba)	printk("LBAsect=%lld, ", block);
-	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
 	printk("sectors=%ld, ", rq->nr_sectors);
+	printk("CHS=%d/%d/%d, ", cyl, head, sect);
 	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
 #endif
 
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
-	ide_cmd_type_parser(&args);
-	args.rq	= rq;
-	args.block = block;
-	rq->special = &args;
+	ide_cmd_type_parser(args);
+	args->ar = ar;
+	rq->special = ar;
 
-	return do_rw_taskfile(drive, &args);
+	return ata_taskfile(drive, args, rq);
 }
 
-static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct request *rq, unsigned long block)
+static ide_startstop_t lba28_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block)
 {
-	struct hd_drive_task_hdr	taskfile;
-	struct hd_drive_hob_hdr		hobfile;
-	ide_task_t			args;
-	int				sectors;
+	struct ata_taskfile *args = &ar->ar_task;
+	struct request *rq = ar->ar_rq;
+	int sectors = rq->nr_sectors;
 
-	task_ioreg_t command	= get_command(drive, rq_data_dir(rq));
-
-	sectors = rq->nr_sectors;
 	if (sectors == 256)
 		sectors = 0;
 
-	memset(&taskfile, 0, sizeof(task_struct_t));
-	memset(&hobfile, 0, sizeof(hob_struct_t));
+	memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr));
+	memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
+	if (ar->ar_flags & ATA_AR_QUEUED) {
+		unsigned long flags;
+
+		args->taskfile.feature = sectors;
+		args->taskfile.sector_count = ar->ar_tag << 3;
 
-	taskfile.sector_count	= sectors;
-	taskfile.sector_number	= block;
-	taskfile.low_cylinder	= (block>>=8);
-	taskfile.high_cylinder	= (block>>=8);
-	taskfile.device_head	= ((block>>8)&0x0f);
-	taskfile.device_head	|= drive->select.all;
-	taskfile.command	= command;
+		spin_lock_irqsave(DRIVE_LOCK(drive), flags);
+		blkdev_dequeue_request(rq);
+		spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
+	} else
+		args->taskfile.sector_count = sectors;
+
+	args->taskfile.sector_number = block;
+	args->taskfile.low_cylinder = (block >>= 8);
+
+	args->taskfile.high_cylinder = (block >>= 8);
+
+	args->taskfile.device_head = ((block >> 8) & 0x0f);
+	args->taskfile.device_head |= drive->select.all;
+	args->taskfile.command = get_command(drive, rq_data_dir(rq));
 
 #ifdef DEBUG
 	printk("%s: %sing: ", drive->name,
 		(rq_data_dir(rq)==READ) ? "read" : "writ");
-	if (lba)	printk("LBAsect=%lld, ", block);
-	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
-	printk("sectors=%ld, ", rq->nr_sectors);
+	printk("sector=%lx, sectors=%ld, ", block, rq->nr_sectors);
 	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
 #endif
 
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
-	ide_cmd_type_parser(&args);
-	args.rq = rq;
-	args.block = block;
-	rq->special = &args;
+	ide_cmd_type_parser(args);
+	args->ar = ar;
+	rq->special = ar;
 
-	return do_rw_taskfile(drive, &args);
+	return ata_taskfile(drive, args, rq);
 }
 
 /*
@@ -272,78 +252,156 @@
  * 320173056  == 163929 MB or 48bit addressing
  * 1073741822 == 549756 MB or 48bit addressing fake drive
  */
-
-static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct request *rq, unsigned long long block)
+static ide_startstop_t lba48_do_request(ide_drive_t *drive, struct ata_request *ar, sector_t block)
 {
-	struct hd_drive_task_hdr	taskfile;
-	struct hd_drive_hob_hdr		hobfile;
-	ide_task_t			args;
-	int				sectors;
-
-	task_ioreg_t command	= get_command(drive, rq_data_dir(rq));
+	struct ata_taskfile *args = &ar->ar_task;
+	struct request *rq = ar->ar_rq;
+	int sectors = rq->nr_sectors;
 
-	memset(&taskfile, 0, sizeof(task_struct_t));
-	memset(&hobfile, 0, sizeof(hob_struct_t));
+	memset(&args->taskfile, 0, sizeof(struct hd_drive_task_hdr));
+	memset(&args->hobfile, 0, sizeof(struct hd_drive_hob_hdr));
 
-	sectors = rq->nr_sectors;
 	if (sectors == 65536)
 		sectors = 0;
 
-	taskfile.sector_count	= sectors;
-	hobfile.sector_count	= sectors >> 8;
+	if (ar->ar_flags & ATA_AR_QUEUED) {
+		unsigned long flags;
 
-	if (rq->nr_sectors == 65536) {
-		taskfile.sector_count	= 0x00;
-		hobfile.sector_count	= 0x00;
-	}
-
-	taskfile.sector_number	= block;	/* low lba */
-	taskfile.low_cylinder	= (block>>=8);	/* mid lba */
-	taskfile.high_cylinder	= (block>>=8);	/* hi  lba */
-	hobfile.sector_number	= (block>>=8);	/* low lba */
-	hobfile.low_cylinder	= (block>>=8);	/* mid lba */
-	hobfile.high_cylinder	= (block>>=8);	/* hi  lba */
-	taskfile.device_head	= drive->select.all;
-	hobfile.device_head	= taskfile.device_head;
-	hobfile.control		= (drive->ctl|0x80);
-	taskfile.command	= command;
+		args->taskfile.feature = sectors;
+		args->hobfile.feature = sectors >> 8;
+		args->taskfile.sector_count = ar->ar_tag << 3;
+
+		spin_lock_irqsave(DRIVE_LOCK(drive), flags);
+		blkdev_dequeue_request(rq);
+		spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
+	} else {
+		args->taskfile.sector_count = sectors;
+		args->hobfile.sector_count = sectors >> 8;
+	}
+
+	args->taskfile.sector_number = block;
+	args->taskfile.low_cylinder = (block >>= 8);
+	args->taskfile.high_cylinder = (block >>= 8);
+
+	args->hobfile.sector_number = (block >>= 8);
+	args->hobfile.low_cylinder = (block >>= 8);
+	args->hobfile.high_cylinder = (block >>= 8);
+
+	args->taskfile.device_head = drive->select.all;
+	args->hobfile.device_head = args->taskfile.device_head;
+	args->hobfile.control = (drive->ctl|0x80);
+	args->taskfile.command = get_command(drive, rq_data_dir(rq));
 
 #ifdef DEBUG
 	printk("%s: %sing: ", drive->name,
 		(rq_data_dir(rq)==READ) ? "read" : "writ");
-	if (lba)	printk("LBAsect=%lld, ", block);
-	else		printk("CHS=%d/%d/%d, ", cyl, head, sect);
-	printk("sectors=%ld, ", rq->nr_sectors);
+	printk("sector=%lx, sectors=%ld, ", block, rq->nr_sectors);
 	printk("buffer=0x%08lx\n", (unsigned long) rq->buffer);
 #endif
 
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr));
-	ide_cmd_type_parser(&args);
-	args.rq = rq;
-	args.block = block;
-	rq->special = &args;
+	ide_cmd_type_parser(args);
+	args->ar = ar;
+	rq->special = ar;
+
+	return ata_taskfile(drive, args, rq);
+}
+
+/*
+ * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS
+ * otherwise, to address sectors.  It also takes care of issuing special
+ * DRIVE_CMDs.
+ */
+static ide_startstop_t idedisk_do_request(ide_drive_t *drive, struct request *rq, sector_t block)
+{
+	unsigned long flags;
+	struct ata_request *ar;
+
+	/*
+	 * Wait until all request have bin finished.
+	 */
+
+	while (drive->blocked) {
+		yield();
+		printk("ide: Request while drive blocked?");
+	}
+
+	if (!(rq->flags & REQ_CMD)) {
+		blk_dump_rq_flags(rq, "idedisk_do_request - bad command");
+		ide_end_request(drive, 0);
+		return ide_stopped;
+	}
+
+	if (IS_PDC4030_DRIVE) {
+		extern ide_startstop_t promise_rw_disk(ide_drive_t *, struct request *, unsigned long);
+
+		return promise_rw_disk(drive, rq, block);
+	}
+
+	/*
+	 * get a new command (push ar further down to avoid grabbing lock here
+	 */
+	spin_lock_irqsave(DRIVE_LOCK(drive), flags);
+
+	ar = ata_ar_get(drive);
+
+	/*
+	 * we've reached maximum queue depth, bail
+	 */
+	if (!ar) {
+		spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
+		return ide_started;
+	}
+
+	ar->ar_rq = rq;
+
+	if (drive->using_tcq) {
+		int tag = ide_get_tag(drive);
 
-	return do_rw_taskfile(drive, &args);
+		BUG_ON(drive->tcq->active_tag != -1);
+
+		/* Set the tag: */
+		ar->ar_flags |= ATA_AR_QUEUED;
+		ar->ar_tag = tag;
+		drive->tcq->ar[tag] = ar;
+		drive->tcq->active_tag = tag;
+		ar->ar_time = jiffies;
+		drive->tcq->queued++;
+	}
+
+	spin_unlock_irqrestore(DRIVE_LOCK(drive), flags);
+
+	/* 48-bit LBA */
+	if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))
+		return lba48_do_request(drive, ar, block);
+
+	/* 28-bit LBA */
+	if (drive->select.b.lba)
+		return lba28_do_request(drive, ar, block);
+
+	/* 28-bit CHS */
+	return chs_do_request(drive, ar, block);
 }
 
 static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
 	MOD_INC_USE_COUNT;
 	if (drive->removable && drive->usage == 1) {
-		struct hd_drive_task_hdr taskfile;
-		struct hd_drive_hob_hdr hobfile;
-		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+		struct ata_taskfile args;
+
 		check_disk_change(inode->i_rdev);
-		taskfile.command = WIN_DOORLOCK;
+
+		memset(&args, 0, sizeof(args));
+
+		args.taskfile.command = WIN_DOORLOCK;
+		ide_cmd_type_parser(&args);
+
 		/*
-		 * Ignore the return code from door_lock,
-		 * since the open() has already succeeded,
-		 * and the door_lock is irrelevant at this point.
+		 * Ignore the return code from door_lock, since the open() has
+		 * already succeeded, and the door_lock is irrelevant at this
+		 * point.
 		 */
-		if (drive->doorlocking &&
-		    ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
+
+		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
 	}
 	return 0;
@@ -351,29 +409,33 @@
 
 static int idedisk_flushcache(ide_drive_t *drive)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	if (drive->id->cfs_enable_2 & 0x2400) {
-		taskfile.command	= WIN_FLUSH_CACHE_EXT;
-	} else {
-		taskfile.command	= WIN_FLUSH_CACHE;
-	}
-	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
+	struct ata_taskfile args;
+
+	memset(&args, 0, sizeof(args));
+
+	if (drive->id->cfs_enable_2 & 0x2400)
+		args.taskfile.command = WIN_FLUSH_CACHE_EXT;
+	else
+		args.taskfile.command = WIN_FLUSH_CACHE;
+
+	ide_cmd_type_parser(&args);
+
+	return ide_raw_taskfile(drive, &args, NULL);
 }
 
 static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
 	if (drive->removable && !drive->usage) {
-		struct hd_drive_task_hdr taskfile;
-		struct hd_drive_hob_hdr hobfile;
-		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+		struct ata_taskfile args;
+
 		invalidate_bdev(inode->i_bdev, 0);
-		taskfile.command = WIN_DOORUNLOCK;
+
+		memset(&args, 0, sizeof(args));
+		args.taskfile.command = WIN_DOORUNLOCK;
+		ide_cmd_type_parser(&args);
+
 		if (drive->doorlocking &&
-		    ide_wait_taskfile(drive, &taskfile, &hobfile, NULL))
+		    ide_raw_taskfile(drive, &args, NULL))
 			drive->doorlocking = 0;
 	}
 	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
@@ -395,7 +457,7 @@
  */
 static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
 {
-	ide_task_t args;
+	struct ata_taskfile args;
 	unsigned long addr = 0;
 
 	if (!(drive->id->command_set_1 & 0x0400) &&
@@ -403,51 +465,55 @@
 		return addr;
 
 	/* Create IDE/ATA command request structure */
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;
-	args.handler				= task_no_data_intr;
+	memset(&args, 0, sizeof(args));
+	args.taskfile.device_head = 0x40;
+	args.taskfile.command = WIN_READ_NATIVE_MAX;
+	args.handler = task_no_data_intr;
 
 	/* submit command request */
 	ide_raw_taskfile(drive, &args, NULL);
 
 	/* if OK, compute maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
-		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
-		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
-		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
+	if ((args.taskfile.command & 0x01) == 0) {
+		addr = ((args.taskfile.device_head & 0x0f) << 24)
+		     | (args.taskfile.high_cylinder << 16)
+		     | (args.taskfile.low_cylinder <<  8)
+		     | args.taskfile.sector_number;
 	}
+
 	addr++;	/* since the return value is (maxlba - 1), we add 1 */
+
 	return addr;
 }
 
 static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
 {
-	ide_task_t args;
+	struct ata_taskfile args;
 	unsigned long long addr = 0;
 
 	/* Create IDE/ATA command request structure */
-	memset(&args, 0, sizeof(ide_task_t));
+	memset(&args, 0, sizeof(args));
 
-	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;
-	args.handler				= task_no_data_intr;
+	args.taskfile.device_head = 0x40;
+	args.taskfile.command = WIN_READ_NATIVE_MAX_EXT;
+	args.handler = task_no_data_intr;
 
         /* submit command request */
         ide_raw_taskfile(drive, &args, NULL);
 
 	/* if OK, compute maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
-			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
-			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
-		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
-			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
-			    (args.tfRegister[IDE_SECTOR_OFFSET]);
+	if ((args.taskfile.command & 0x01) == 0) {
+		u32 high = (args.hobfile.high_cylinder << 16) |
+			   (args.hobfile.low_cylinder << 8) |
+			    args.hobfile.sector_number;
+		u32 low  = (args.taskfile.high_cylinder << 16) |
+			   (args.taskfile.low_cylinder << 8) |
+			    args.taskfile.sector_number;
 		addr = ((__u64)high << 24) | low;
 	}
+
 	addr++;	/* since the return value is (maxlba - 1), we add 1 */
+
 	return addr;
 }
 
@@ -458,26 +524,28 @@
  */
 static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
 {
-	ide_task_t args;
+	struct ata_taskfile args;
 	unsigned long addr_set = 0;
 
 	addr_req--;
 	/* Create IDE/ATA command request structure */
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
-	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);
-	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);
-	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;
-	args.handler				= task_no_data_intr;
+	memset(&args, 0, sizeof(args));
+
+	args.taskfile.sector_number = (addr_req >> 0);
+	args.taskfile.low_cylinder = (addr_req >> 8);
+	args.taskfile.high_cylinder = (addr_req >> 16);
+
+	args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40;
+	args.taskfile.command = WIN_SET_MAX;
+	args.handler = task_no_data_intr;
 	/* submit command request */
 	ide_raw_taskfile(drive, &args, NULL);
 	/* if OK, read new maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
-			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
-			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
-			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
+	if ((args.taskfile.command & 0x01) == 0) {
+		addr_set = ((args.taskfile.device_head & 0x0f) << 24)
+			 | (args.taskfile.high_cylinder << 16)
+			 | (args.taskfile.low_cylinder <<  8)
+			 | args.taskfile.sector_number;
 	}
 	addr_set++;
 	return addr_set;
@@ -485,33 +553,37 @@
 
 static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
 {
-	ide_task_t args;
+	struct ata_taskfile args;
 	unsigned long long addr_set = 0;
 
 	addr_req--;
 	/* Create IDE/ATA command request structure */
-	memset(&args, 0, sizeof(ide_task_t));
-	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
-	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
-	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
-	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;
-	args.hobRegister[IDE_SECTOR_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
-	args.hobRegister[IDE_LCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
-	args.hobRegister[IDE_HCYL_OFFSET_HOB]	= ((addr_req >>= 8) & 0xff);
-	args.hobRegister[IDE_SELECT_OFFSET_HOB]	= 0x40;
-	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
-        args.handler				= task_no_data_intr;
+	memset(&args, 0, sizeof(args));
+
+	args.taskfile.sector_number = (addr_req >>  0);
+	args.taskfile.low_cylinder = (addr_req >>= 8);
+	args.taskfile.high_cylinder = (addr_req >>= 8);
+	args.taskfile.device_head = 0x40;
+	args.taskfile.command = WIN_SET_MAX_EXT;
+
+	args.hobfile.sector_number = (addr_req >>= 8);
+	args.hobfile.low_cylinder = (addr_req >>= 8);
+	args.hobfile.high_cylinder = (addr_req >>= 8);
+
+	args.hobfile.device_head = 0x40;
+	args.hobfile.control = (drive->ctl | 0x80);
+
+        args.handler = task_no_data_intr;
 	/* submit command request */
 	ide_raw_taskfile(drive, &args, NULL);
 	/* if OK, compute maximum address value */
-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
-		u32 high = ((args.hobRegister[IDE_HCYL_OFFSET_HOB])<<16) |
-			   ((args.hobRegister[IDE_LCYL_OFFSET_HOB])<<8) |
-			    (args.hobRegister[IDE_SECTOR_OFFSET_HOB]);
-		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
-			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
-			    (args.tfRegister[IDE_SECTOR_OFFSET]);
+	if ((args.taskfile.command & 0x01) == 0) {
+		u32 high = (args.hobfile.high_cylinder << 16) |
+			   (args.hobfile.low_cylinder << 8) |
+			    args.hobfile.sector_number;
+		u32 low  = (args.taskfile.high_cylinder << 16) |
+			   (args.taskfile.low_cylinder << 8) |
+			    args.taskfile.sector_number;
 		addr_set = ((__u64)high << 24) | low;
 	}
 	return addr_set;
@@ -528,7 +600,7 @@
 	return flag;
 }
 
-#endif /* CONFIG_IDEDISK_STROKE */
+#endif
 
 /*
  * Compute drive->capacity, the full capacity of the drive
@@ -572,10 +644,10 @@
 				drive->select.b.lba = 1;
 				drive->id->lba_capacity_2 = capacity_2;
                         }
-#else /* !CONFIG_IDEDISK_STROKE */
+#else
 			printk("%s: setmax_ext LBA %llu, native  %llu\n",
 				drive->name, set_max_ext, capacity_2);
-#endif /* CONFIG_IDEDISK_STROKE */
+#endif
 		}
 		drive->bios_cyl		= drive->cyl;
 		drive->capacity48	= capacity_2;
@@ -598,10 +670,10 @@
 			drive->select.b.lba = 1;
 			drive->id->lba_capacity = capacity;
 		}
-#else /* !CONFIG_IDEDISK_STROKE */
+#else
 		printk("%s: setmax LBA %lu, native  %lu\n",
 			drive->name, set_max, capacity);
-#endif /* CONFIG_IDEDISK_STROKE */
+#endif
 	}
 
 	drive->capacity = capacity;
@@ -626,47 +698,45 @@
 	special_t *s = &drive->special;
 
 	if (s->b.set_geometry) {
-		struct hd_drive_task_hdr taskfile;
-		struct hd_drive_hob_hdr hobfile;
-		ide_handler_t *handler = NULL;
-
-		memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-		memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+		struct ata_taskfile args;
 
 		s->b.set_geometry	= 0;
-		taskfile.sector_number	= drive->sect;
-		taskfile.low_cylinder	= drive->cyl;
-		taskfile.high_cylinder	= drive->cyl>>8;
-		taskfile.device_head	= ((drive->head-1)|drive->select.all)&0xBF;
+
+		memset(&args, 0, sizeof(args));
+		args.taskfile.sector_number	= drive->sect;
+		args.taskfile.low_cylinder	= drive->cyl;
+		args.taskfile.high_cylinder	= drive->cyl>>8;
+		args.taskfile.device_head	= ((drive->head-1)|drive->select.all)&0xBF;
 		if (!IS_PDC4030_DRIVE) {
-			taskfile.sector_count = drive->sect;
-			taskfile.command = WIN_SPECIFY;
-			handler	= set_geometry_intr;;
+			args.taskfile.sector_count = drive->sect;
+			args.taskfile.command = WIN_SPECIFY;
+			args.handler = set_geometry_intr;;
 		}
-		do_taskfile(drive, &taskfile, &hobfile, handler);
+		ata_taskfile(drive, &args, NULL);
 	} else if (s->b.recalibrate) {
 		s->b.recalibrate = 0;
 		if (!IS_PDC4030_DRIVE) {
-			struct hd_drive_task_hdr taskfile;
-			struct hd_drive_hob_hdr hobfile;
-			memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-			taskfile.sector_count	= drive->sect;
-			taskfile.command	= WIN_RESTORE;
-			do_taskfile(drive, &taskfile, &hobfile, recal_intr);
+			struct ata_taskfile args;
+
+			memset(&args, 0, sizeof(args));
+			args.taskfile.sector_count = drive->sect;
+			args.taskfile.command = WIN_RESTORE;
+			args.handler = recal_intr;
+			ata_taskfile(drive, &args, NULL);
 		}
 	} else if (s->b.set_multmode) {
 		s->b.set_multmode = 0;
 		if (drive->id && drive->mult_req > drive->id->max_multsect)
 			drive->mult_req = drive->id->max_multsect;
 		if (!IS_PDC4030_DRIVE) {
-			struct hd_drive_task_hdr taskfile;
-			struct hd_drive_hob_hdr hobfile;
-			memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-			memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-			taskfile.sector_count	= drive->mult_req;
-			taskfile.command	= WIN_SETMULT;
-			do_taskfile(drive, &taskfile, &hobfile, &set_multmode_intr);
+			struct ata_taskfile args;
+
+			memset(&args, 0, sizeof(args));
+			args.taskfile.sector_count = drive->mult_req;
+			args.taskfile.command = WIN_SETMULT;
+			args.handler = set_multmode_intr;
+
+			ata_taskfile(drive, &args, NULL);
 		}
 	} else if (s->all) {
 		int special = s->all;
@@ -696,45 +766,50 @@
 
 static int smart_enable(ide_drive_t *drive)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	taskfile.feature	= SMART_ENABLE;
-	taskfile.low_cylinder	= SMART_LCYL_PASS;
-	taskfile.high_cylinder	= SMART_HCYL_PASS;
-	taskfile.command	= WIN_SMART;
-	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
-}
-
-static int get_smart_values(ide_drive_t *drive, byte *buf)
-{
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	taskfile.feature	= SMART_READ_VALUES;
-	taskfile.sector_count	= 0x01;
-	taskfile.low_cylinder	= SMART_LCYL_PASS;
-	taskfile.high_cylinder	= SMART_HCYL_PASS;
-	taskfile.command	= WIN_SMART;
+	struct ata_taskfile args;
+
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = SMART_ENABLE;
+	args.taskfile.low_cylinder = SMART_LCYL_PASS;
+	args.taskfile.high_cylinder = SMART_HCYL_PASS;
+	args.taskfile.command = WIN_SMART;
+	ide_cmd_type_parser(&args);
+
+	return ide_raw_taskfile(drive, &args, NULL);
+}
+
+static int get_smart_values(ide_drive_t *drive, u8 *buf)
+{
+	struct ata_taskfile args;
+
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = SMART_READ_VALUES;
+	args.taskfile.sector_count = 0x01;
+	args.taskfile.low_cylinder = SMART_LCYL_PASS;
+	args.taskfile.high_cylinder = SMART_HCYL_PASS;
+	args.taskfile.command = WIN_SMART;
+	ide_cmd_type_parser(&args);
+
 	smart_enable(drive);
-	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
+
+	return ide_raw_taskfile(drive, &args, buf);
 }
 
-static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
+static int get_smart_thresholds(ide_drive_t *drive, u8 *buf)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	taskfile.feature	= SMART_READ_THRESHOLDS;
-	taskfile.sector_count	= 0x01;
-	taskfile.low_cylinder	= SMART_LCYL_PASS;
-	taskfile.high_cylinder	= SMART_HCYL_PASS;
-	taskfile.command	= WIN_SMART;
+	struct ata_taskfile args;
+
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = SMART_READ_THRESHOLDS;
+	args.taskfile.sector_count = 0x01;
+	args.taskfile.low_cylinder = SMART_LCYL_PASS;
+	args.taskfile.high_cylinder = SMART_HCYL_PASS;
+	args.taskfile.command = WIN_SMART;
+	ide_cmd_type_parser(&args);
+
 	smart_enable(drive);
-	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
+
+	return ide_raw_taskfile(drive, &args, buf);
 }
 
 static int proc_idedisk_read_cache
@@ -789,11 +864,71 @@
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+static int proc_idedisk_read_tcq
+	(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	ide_drive_t	*drive = (ide_drive_t *) data;
+	char		*out = page;
+	int		len, cmds, i;
+	unsigned long tag_mask = 0, flags, cur_jif = jiffies, max_jif;
+
+	if (!drive->tcq) {
+		len = sprintf(out, "not configured\n");
+		PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+	}
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	len = sprintf(out, "TCQ currently on:\t%s\n", drive->using_tcq ? "yes" : "no");
+	len += sprintf(out+len, "Max queue depth:\t%d\n",drive->queue_depth);
+	len += sprintf(out+len, "Max achieved depth:\t%d\n",drive->tcq->max_depth);
+	len += sprintf(out+len, "Max depth since last:\t%d\n",drive->tcq->max_last_depth);
+	len += sprintf(out+len, "Current depth:\t\t%d\n", drive->tcq->queued);
+	max_jif = 0;
+	len += sprintf(out+len, "Active tags:\t\t[ ");
+	for (i = 0, cmds = 0; i < drive->queue_depth; i++) {
+		struct ata_request *ar = IDE_GET_AR(drive, i);
+
+		if (!ar)
+			continue;
+
+		__set_bit(i, &tag_mask);
+		len += sprintf(out+len, "%d, ", i);
+		if (ar->ar_time > max_jif)
+			max_jif = ar->ar_time;
+		cmds++;
+	}
+	len += sprintf(out+len, "]\n");
+
+	if (drive->tcq->queued != cmds)
+		len += sprintf(out+len, "pending request and queue count mismatch (%d)\n", cmds);
+
+	if (tag_mask != drive->tcq->tag_mask)
+		len += sprintf(out+len, "tag masks differ (counted %lx != %lx\n", tag_mask, drive->tcq->tag_mask);
+
+	len += sprintf(out+len, "DMA status:\t\t%srunning\n", test_bit(IDE_DMA, &HWGROUP(drive)->flags) ? "" : "not ");
+
+	if (max_jif)
+		len += sprintf(out+len, "Oldest command:\t\t%lu\n", cur_jif - max_jif);
+
+	len += sprintf(out+len, "immed rel %d, immed comp %d\n", drive->tcq->immed_rel, drive->tcq->immed_comp);
+
+	drive->tcq->max_last_depth = 0;
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+}
+#endif
+
 static ide_proc_entry_t idedisk_proc[] = {
 	{ "cache",		S_IFREG|S_IRUGO,	proc_idedisk_read_cache,		NULL },
 	{ "geometry",		S_IFREG|S_IRUGO,	proc_ide_read_geometry,			NULL },
 	{ "smart_values",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_values,		NULL },
 	{ "smart_thresholds",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_thresholds,	NULL },
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+	{ "tcq",		S_IFREG|S_IRUSR,	proc_idedisk_read_tcq,	NULL },
+#endif
 	{ NULL, 0, NULL, NULL }
 };
 
@@ -816,7 +951,7 @@
 	ide_init_drive_cmd (&rq);
 	drive->mult_req = arg;
 	drive->special.b.set_multmode = 1;
-	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
+	ide_do_drive_cmd (drive, &rq, ide_wait);
 	return (drive->mult_count == arg) ? 0 : -EIO;
 }
 
@@ -830,48 +965,66 @@
 	return 0;
 }
 
-static int write_cache (ide_drive_t *drive, int arg)
+static int write_cache(ide_drive_t *drive, int arg)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	taskfile.feature	= (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
-	taskfile.command	= WIN_SETFEATURES;
+	struct ata_taskfile args;
 
 	if (!(drive->id->cfs_enable_2 & 0x3000))
 		return 1;
 
-	ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature	= (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
+	args.taskfile.command	= WIN_SETFEATURES;
+	ide_cmd_type_parser(&args);
+	ide_raw_taskfile(drive, &args, NULL);
+
 	drive->wcache = arg;
+
 	return 0;
 }
 
-static int idedisk_standby (ide_drive_t *drive)
+static int idedisk_standby(ide_drive_t *drive)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
-	taskfile.command	= WIN_STANDBYNOW1;
-	return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
+	struct ata_taskfile args;
+
+	memset(&args, 0, sizeof(args));
+	args.taskfile.command = WIN_STANDBYNOW1;
+	ide_cmd_type_parser(&args);
+
+	return ide_raw_taskfile(drive, &args, NULL);
 }
 
-static int set_acoustic (ide_drive_t *drive, int arg)
+static int set_acoustic(ide_drive_t *drive, int arg)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+	struct ata_taskfile args;
 
-	taskfile.feature	= (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
-	taskfile.sector_count	= arg;
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
+	args.taskfile.sector_count = arg;
+	args.taskfile.command = WIN_SETFEATURES;
+	ide_cmd_type_parser(&args);
+	ide_raw_taskfile(drive, &args, NULL);
 
-	taskfile.command	= WIN_SETFEATURES;
-	ide_wait_taskfile(drive, &taskfile, &hobfile, NULL);
 	drive->acoustic = arg;
+
+	return 0;
+}
+
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+static int set_using_tcq(ide_drive_t *drive, int arg)
+{
+	if (!drive->driver)
+		return -EPERM;
+	if (!drive->channel->dmaproc)
+		return -EPERM;
+
+	drive->using_tcq = arg;
+	if (drive->channel->dmaproc(arg ? ide_dma_queued_on : ide_dma_queued_off, drive))
+		return -EIO;
+
 	return 0;
 }
+#endif
 
 static int probe_lba_addressing (ide_drive_t *drive, int arg)
 {
@@ -905,6 +1058,9 @@
 	ide_add_setting(drive,	"acoustic",		SETTING_RW,					HDIO_GET_ACOUSTIC,	HDIO_SET_ACOUSTIC,	TYPE_BYTE,	0,	254,				1,	1,	&drive->acoustic,		set_acoustic);
 	ide_add_setting(drive,	"failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->failures,		NULL);
 	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+	ide_add_setting(drive,	"using_tcq",		SETTING_RW,					HDIO_GET_QDMA,		HDIO_SET_QDMA,		TYPE_BYTE,	0,	IDE_MAX_TAG,			1,		1,		&drive->using_tcq,		set_using_tcq);
+#endif
 }
 
 static int idedisk_suspend(struct device *dev, u32 state, u32 level)
@@ -915,6 +1071,9 @@
 	 * already been done...
 	 */
 
+	if (level != SUSPEND_SAVE_STATE)
+		return 0;
+
 	/* wait until all commands are finished */
 	printk("ide_disk_suspend()\n");
 	while (HWGROUP(drive)->handler)
@@ -934,6 +1093,9 @@
 static int idedisk_resume(struct device *dev, u32 level)
 {
 	ide_drive_t *drive = dev->driver_data;
+
+	if (level != RESUME_RESTORE_STATE)
+		return 0;
 	if (!drive->blocked)
 		panic("ide: Resume but not suspended?\n");
 
@@ -979,7 +1141,7 @@
 		}
 	}
 	for (i = 0; i < MAX_DRIVES; ++i) {
-		ide_hwif_t *hwif = HWIF(drive);
+		struct ata_channel *hwif = drive->channel;
 
 		if (drive != &hwif->drives[i])
 		    continue;
@@ -994,12 +1156,12 @@
 	 */
 
 	if (drvid != -1) {
-	    sprintf(drive->device.bus_id, "%d", drvid);
-	    sprintf(drive->device.name, "ide-disk");
-	    drive->device.driver = &idedisk_devdrv;
-	    drive->device.parent = &HWIF(drive)->device;
-	    drive->device.driver_data = drive;
-	    device_register(&drive->device);
+		sprintf(drive->device.bus_id, "%d", drvid);
+		sprintf(drive->device.name, "ide-disk");
+		drive->device.driver = &idedisk_devdrv;
+		drive->device.parent = &drive->channel->dev;
+		drive->device.driver_data = drive;
+		device_register(&drive->device);
 	}
 
 	/* Extract geometry if we did not already have one for the drive */
@@ -1045,11 +1207,11 @@
 	if (id->buf_size)
 		printk (" w/%dKiB Cache", id->buf_size/2);
 
-	printk(", CHS=%d/%d/%d", 
+	printk(", CHS=%d/%d/%d",
 	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
-		(void) HWIF(drive)->dmaproc(ide_dma_verbose, drive);
+		(void) drive->channel->dmaproc(ide_dma_verbose, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	printk("\n");
 
@@ -1071,11 +1233,14 @@
 	drive->no_io_32bit = id->dword_io ? 1 : 0;
 	if (drive->id->cfs_enable_2 & 0x3000)
 		write_cache(drive, (id->cfs_enable_2 & 0x3000));
-	(void) probe_lba_addressing(drive, 1);
+	probe_lba_addressing(drive, 1);
 }
 
-static int idedisk_cleanup (ide_drive_t *drive)
+static int idedisk_cleanup(ide_drive_t *drive)
 {
+	if (!drive)
+	    return 0;
+
 	put_device(&drive->device);
 	if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
 		if (idedisk_flushcache(drive))
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/ide-dma.c	Sun Apr 14 12:16:56 2002
@@ -1,13 +1,10 @@
 /*
- *  Copyright (c) 1999-2000	Andre Hedrick <andre@linux-ide.org>
- *  May be copied or modified under the terms of the GNU General Public License
- */
-
-/*
- *  Special Thanks to Mark for his Six years of work.
- *
+ *  Copyright (c) 1999-2000  Andre Hedrick <andre@linux-ide.org>
  *  Copyright (c) 1995-1998  Mark Lord
+ *
  *  May be copied or modified under the terms of the GNU General Public License
+ *
+ *  Special Thanks to Mark for his Six years of work.
  */
 
 /*
@@ -82,6 +79,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ide.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -97,8 +95,6 @@
 #define DEFAULT_BMCRBA	0xcc00	/* VIA's default value */
 #define DEFAULT_BMALIBA	0xd400	/* ALI's default value */
 
-extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
-
 #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS
 
 struct drive_list_entry {
@@ -204,7 +200,7 @@
 {
 	byte stat, dma_stat;
 
-	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
 	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -213,54 +209,59 @@
 			__ide_end_request(drive, 1, rq->nr_sectors);
 			return ide_stopped;
 		}
-		printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
+		printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
 		       drive->name, dma_stat);
 	}
 	return ide_error(drive, "dma_intr", stat);
 }
 
-static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
+int ide_build_sglist(struct ata_channel *hwif, struct request *rq)
 {
 	request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
-	struct scatterlist *sg = hwif->sg_table;
-	int nents;
+	struct ata_request *ar = rq->special;
 
-	nents = blk_rq_map_sg(q, rq, hwif->sg_table);
+	if (!(ar->ar_flags & ATA_AR_SETUP)) {
+		ar->ar_flags |= ATA_AR_SETUP;
+		ar->ar_sg_nents = blk_rq_map_sg(q, rq, ar->ar_sg_table);
+	}
 
-	if (rq->q && nents > rq->nr_phys_segments)
-		printk("ide-dma: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
+	if (rq->q && ar->ar_sg_nents > rq->nr_phys_segments) {
+		printk("%s: received %d phys segments, build %d\n", __FILE__, rq->nr_phys_segments, ar->ar_sg_nents);
+		return 0;
+	} else if (!ar->ar_sg_nents) {
+		printk("%s: zero segments in request\n", __FILE__);
+		return 0;
+	}
 
 	if (rq_data_dir(rq) == READ)
-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+		ar->ar_sg_ddir = PCI_DMA_FROMDEVICE;
 	else
-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+		ar->ar_sg_ddir = PCI_DMA_TODEVICE;
 
-	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
+	return pci_map_sg(hwif->pci_dev, ar->ar_sg_table, ar->ar_sg_nents, ar->ar_sg_ddir);
 }
 
-static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
+/*
+ * FIXME: taskfiles should be a map of pages, not a long virt address... /jens
+ * FIXME: I agree with Jens --mdcki!
+ */
+static int raw_build_sglist(struct ata_channel *ch, struct request *rq)
 {
-	struct scatterlist *sg = hwif->sg_table;
-	int nents = 0;
-	ide_task_t *args = rq->special;
-#if 1
+	struct ata_request *ar = rq->special;
+	struct scatterlist *sg = ar->ar_sg_table;
+	struct ata_taskfile *args = &ar->ar_task;
 	unsigned char *virt_addr = rq->buffer;
 	int sector_count = rq->nr_sectors;
-#else
-        nents = blk_rq_map_sg(rq->q, rq, hwif->sg_table);
-
-	if (nents > rq->nr_segments)
-		printk("ide-dma: received %d segments, build %d\n", rq->nr_segments, nents);
-#endif
+	int nents = 0;
 
 	if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+		ar->ar_sg_ddir = PCI_DMA_TODEVICE;
 	else
-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+		ar->ar_sg_ddir = PCI_DMA_FROMDEVICE;
 
-#if 1	
 	if (sector_count > 128) {
 		memset(&sg[nents], 0, sizeof(*sg));
+
 		sg[nents].page = virt_to_page(virt_addr);
 		sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
 		sg[nents].length = 128  * SECTOR_SIZE;
@@ -273,20 +274,19 @@
 	sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
 	sg[nents].length =  sector_count  * SECTOR_SIZE;
 	nents++;
- #endif
 
-	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
+	return pci_map_sg(ch->pci_dev, sg, nents, ar->ar_sg_ddir);
 }
 
 /*
- * ide_build_dmatable() prepares a dma request.
+ * Prepare a dma request.
  * Returns 0 if all went okay, returns 1 otherwise.
- * May also be invoked from trm290.c
+ * This may also be invoked from trm290.c
  */
-int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
+int ide_build_dmatable(ide_drive_t *drive, struct request *rq,
+		       ide_dma_action_t func)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned int *table = hwif->dmatable_cpu;
+	struct ata_channel *hwif = drive->channel;
 #ifdef CONFIG_BLK_DEV_TRM290
 	unsigned int is_trm290_chipset = (hwif->chipset == ide_trm290);
 #else
@@ -295,16 +295,19 @@
 	unsigned int count = 0;
 	int i;
 	struct scatterlist *sg;
+	struct ata_request *ar = rq->special;
+	unsigned int *table = ar->ar_dmatable_cpu;
 
-	if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
-		hwif->sg_nents = i = ide_raw_build_sglist(hwif, HWGROUP(drive)->rq);
-	} else {
-		hwif->sg_nents = i = ide_build_sglist(hwif, HWGROUP(drive)->rq);
-	}
-	if (!i)
+	if (rq->flags & REQ_DRIVE_TASKFILE)
+		ar->ar_sg_nents = raw_build_sglist(hwif, rq);
+	else
+		ar->ar_sg_nents = ide_build_sglist(hwif, rq);
+
+	if (!ar->ar_sg_nents)
 		return 0;
 
-	sg = hwif->sg_table;
+	sg = ar->ar_sg_table;
+	i = ar->ar_sg_nents;
 	while (i) {
 		u32 cur_addr;
 		u32 cur_len;
@@ -323,7 +326,7 @@
 
 			if (count++ >= PRD_ENTRIES) {
 				printk("ide-dma: req %p\n", HWGROUP(drive)->rq);
-				printk("count %d, sg_nents %d, cur_len %d, cur_addr %u\n", count, hwif->sg_nents, cur_len, cur_addr);
+				printk("count %d, sg_nents %d, cur_len %d, cur_addr %u\n", count, ar->ar_sg_nents, cur_len, cur_addr);
 				BUG();
 			}
 
@@ -334,7 +337,7 @@
 			if (is_trm290_chipset)
 				xcount = ((xcount >> 2) - 1) << 16;
 			if (xcount == 0x0000) {
-		        /* 
+		        /*
 			 * Most chipsets correctly interpret a length of
 			 * 0x0000 as 64KB, but at least one (e.g. CS5530)
 			 * misinterprets it as zero (!). So here we break
@@ -342,8 +345,8 @@
 			 */
 				if (count++ >= PRD_ENTRIES) {
 					pci_unmap_sg(hwif->pci_dev, sg,
-						     hwif->sg_nents,
-						     hwif->sg_dma_direction);
+						     ar->ar_sg_nents,
+						     ar->ar_sg_ddir);
 					return 0;
 				}
 
@@ -371,11 +374,10 @@
 /* Teardown mappings after DMA has completed.  */
 void ide_destroy_dmatable (ide_drive_t *drive)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	struct scatterlist *sg = HWIF(drive)->sg_table;
-	int nents = HWIF(drive)->sg_nents;
+	struct pci_dev *dev = drive->channel->pci_dev;
+	struct ata_request *ar = IDE_CUR_AR(drive);
 
-	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
+	pci_unmap_sg(dev, ar->ar_sg_table, ar->ar_sg_nents, ar->ar_sg_ddir);
 }
 
 /*
@@ -421,7 +423,7 @@
 	return 0;
 }
 
-static int report_drive_dmaing (ide_drive_t *drive)
+int report_drive_dmaing (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
 
@@ -433,7 +435,7 @@
 			printk(", UDMA(133)");	/* UDMA BIOS-enabled! */
 		}
 	} else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
-	  	  (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
+		  (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
 		if ((id->dma_ultra >> 13) & 1) {
 			printk(", UDMA(100)");	/* UDMA BIOS-enabled! */
 		} else if ((id->dma_ultra >> 12) & 1) {
@@ -462,7 +464,7 @@
 {
 	int config_allows_dma = 1;
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 #ifdef CONFIG_IDEDMA_ONLYDISK
 	if (drive->type != ATA_DISK)
@@ -502,7 +504,7 @@
  */
 static int dma_timer_expiry(ide_drive_t *drive)
 {
-	byte dma_stat = inb(HWIF(drive)->dma_base+2);
+	byte dma_stat = inb(drive->channel->dma_base+2);
 
 #ifdef DEBUG
 	printk("%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat);
@@ -525,17 +527,49 @@
 {
 	u64 addr = BLK_BOUNCE_HIGH;
 
-	if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) {
+	if (on && drive->type == ATA_DISK && drive->channel->highmem) {
 		if (!PCI_DMA_BUS_IS_PHYS)
 			addr = BLK_BOUNCE_ANY;
 		else
-			addr = HWIF(drive)->pci_dev->dma_mask;
+			addr = drive->channel->pci_dev->dma_mask;
 	}
 
 	blk_queue_bounce_limit(&drive->queue, addr);
 }
 
 /*
+ * Start DMA engine.
+ */
+int ide_start_dma(struct ata_channel *hwif, ide_drive_t *drive, ide_dma_action_t func)
+{
+	unsigned int reading = 0, count;
+	unsigned long dma_base = hwif->dma_base;
+	struct ata_request *ar = IDE_CUR_AR(drive);
+
+	/* This can happen with drivers abusing the special request field.
+	 */
+
+	if (!ar)
+		return 1;
+
+	if (rq_data_dir(ar->ar_rq) == READ)
+		reading = 1 << 3;
+
+	if (hwif->rwproc)
+		hwif->rwproc(drive, func);
+
+	if (!(count = ide_build_dmatable(drive, ar->ar_rq, func)))
+		return 1;	/* try PIO instead of DMA */
+
+	ar->ar_flags |= ATA_AR_SETUP;
+	outl(ar->ar_dmatable, dma_base + 4);	/* PRD table */
+	outb(reading, dma_base);		/* specify r/w */
+	outb(inb(dma_base + 2) | 6, dma_base+2);/* clear INTR & ERROR flags */
+	drive->waiting_for_dma = 1;
+	return 0;
+}
+
+/*
  * ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
  *
  * The caller is assumed to have selected the drive and programmed the drive's
@@ -553,17 +587,19 @@
  */
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long dma_base = hwif->dma_base;
-	byte unit = (drive->select.b.unit & 0x01);
-	unsigned int count, reading = 0, set_high = 1;
-	byte dma_stat;
+	u8 unit = (drive->select.b.unit & 0x01);
+	unsigned int reading = 0, set_high = 1;
+	struct ata_request *ar;
+	u8 dma_stat;
 
 	switch (func) {
 		case ide_dma_off:
 			printk("%s: DMA disabled\n", drive->name);
-			set_high = 0;
 		case ide_dma_off_quietly:
+			set_high = 0;
+			drive->using_tcq = 0;
 			outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
 		case ide_dma_on:
 			ide_toggle_bounce(drive, set_high);
@@ -573,46 +609,66 @@
 			return 0;
 		case ide_dma_check:
 			return config_drive_for_dma (drive);
+		case ide_dma_begin:
+#ifdef DEBUG
+			printk("ide_dma_begin: from %p\n", __builtin_return_address(0));
+#endif
+			if (test_and_set_bit(IDE_DMA, &HWGROUP(drive)->flags))
+				BUG();
+			/* Note that this is done *after* the cmd has
+			 * been issued to the drive, as per the BM-IDE spec.
+			 * The Promise Ultra33 doesn't work correctly when
+			 * we do this part before issuing the drive cmd.
+			 */
+			outb(inb(dma_base)|1, dma_base);		/* start DMA */
+			return 0;
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+		case ide_dma_queued_on:
+		case ide_dma_queued_off:
+		case ide_dma_read_queued:
+		case ide_dma_write_queued:
+		case ide_dma_queued_start:
+			return ide_tcq_dmaproc(func, drive);
+#endif
+
 		case ide_dma_read:
 			reading = 1 << 3;
 		case ide_dma_write:
-			/* active tuning based on IO direction */
-			if (hwif->rwproc)
-				hwif->rwproc(drive, func);
-
-			if (!(count = ide_build_dmatable(drive, func)))
-				return 1;	/* try PIO instead of DMA */
-			outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */
-			outb(reading, dma_base);			/* specify r/w */
-			outb(inb(dma_base+2)|6, dma_base+2);		/* clear INTR & ERROR flags */
-			drive->waiting_for_dma = 1;
+			ar = HWGROUP(drive)->rq->special;
+
+			if (ide_start_dma(hwif, drive, func))
+				return 1;
+
 			if (drive->type != ATA_DISK)
 				return 0;
+
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry);	/* issue cmd to drive */
-			if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
+			if ((ar->ar_rq->flags & REQ_DRIVE_TASKFILE) &&
 			    (drive->addressing == 1)) {
-				ide_task_t *args = HWGROUP(drive)->rq->special;
-				OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG);
+				struct ata_taskfile *args = &ar->ar_task;
+				OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
 			} else if (drive->addressing) {
 				OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
 			} else {
 				OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 			}
-			return HWIF(drive)->dmaproc(ide_dma_begin, drive);
-		case ide_dma_begin:
-			/* Note that this is done *after* the cmd has
-			 * been issued to the drive, as per the BM-IDE spec.
-			 * The Promise Ultra33 doesn't work correctly when
-			 * we do this part before issuing the drive cmd.
-			 */
-			outb(inb(dma_base)|1, dma_base);		/* start DMA */
-			return 0;
+			return hwif->dmaproc(ide_dma_begin, drive);
 		case ide_dma_end: /* returns 1 on error, 0 otherwise */
+#ifdef DEBUG
+			printk("ide_dma_end: from %p\n", __builtin_return_address(0));
+#endif
+			if (!test_and_clear_bit(IDE_DMA, &HWGROUP(drive)->flags)) {
+				printk("ide_dma_end: dma not going? %p\n", __builtin_return_address(0));
+				return 1;
+			}
 			drive->waiting_for_dma = 0;
 			outb(inb(dma_base)&~1, dma_base);	/* stop DMA */
-			dma_stat = inb(dma_base+2);		/* get DMA status */
+			dma_stat = inb(dma_base+2);	/* get DMA status */
 			outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
 			ide_destroy_dmatable(drive);	/* purge DMA mappings */
+			if (drive->tcq)
+				IDE_SET_CUR_TAG(drive, -1);
 			return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;	/* verify good DMA status */
 		case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
 			dma_stat = inb(dma_base+2);
@@ -629,14 +685,14 @@
 		case ide_dma_verbose:
 			return report_drive_dmaing(drive);
 		case ide_dma_timeout:
-			printk("ide_dmaproc: DMA timeout occured!\n");
+			printk(KERN_ERR "%s: DMA timeout occured!\n", __FUNCTION__);
 			return 1;
 		case ide_dma_retune:
 		case ide_dma_lostirq:
-			printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);
+			printk(KERN_ERR "%s: chipset supported func only: %d\n", __FUNCTION__, func);
 			return 1;
 		default:
-			printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
+			printk(KERN_ERR "%s: unsupported func: %d\n", __FUNCTION__, func);
 			return 1;
 	}
 }
@@ -644,23 +700,12 @@
 /*
  * Needed for allowing full modular support of ide-driver
  */
-void ide_release_dma(ide_hwif_t *hwif)
+void ide_release_dma(struct ata_channel *hwif)
 {
 	if (!hwif->dma_base)
 		return;
 
-	if (hwif->dmatable_cpu) {
-		pci_free_consistent(hwif->pci_dev,
-				    PRD_ENTRIES * PRD_BYTES,
-				    hwif->dmatable_cpu,
-				    hwif->dmatable_dma);
-		hwif->dmatable_cpu = NULL;
-	}
-	if (hwif->sg_table) {
-		kfree(hwif->sg_table);
-		hwif->sg_table = NULL;
-	}
-	if ((hwif->dma_extra) && (hwif->channel == 0))
+	if ((hwif->dma_extra) && (hwif->unit == 0))
 		release_region((hwif->dma_base + 16), hwif->dma_extra);
 	release_region(hwif->dma_base, 8);
 	hwif->dma_base = 0;
@@ -669,7 +714,7 @@
 /*
  * This can be called for a dynamically installed interface. Don't __init it
  */
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
+void ide_setup_dma(struct ata_channel *hwif, unsigned long dma_base, unsigned int num_ports)
 {
 	printk("    %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, dma_base, dma_base + num_ports - 1);
 	if (check_region(dma_base, num_ports)) {
@@ -678,20 +723,6 @@
 	}
 	request_region(dma_base, num_ports, hwif->name);
 	hwif->dma_base = dma_base;
-	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
-						  PRD_ENTRIES * PRD_BYTES,
-						  &hwif->dmatable_dma);
-	if (hwif->dmatable_cpu == NULL)
-		goto dma_alloc_failure;
-
-	hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
-				 GFP_KERNEL);
-	if (hwif->sg_table == NULL) {
-		pci_free_consistent(hwif->pci_dev, PRD_ENTRIES * PRD_BYTES,
-				    hwif->dmatable_cpu, hwif->dmatable_dma);
-		goto dma_alloc_failure;
-	}
-
 	hwif->dmaproc = &ide_dmaproc;
 
 	if (hwif->chipset != ide_trm290) {
@@ -702,7 +733,4 @@
 	}
 	printk("\n");
 	return;
-
-dma_alloc_failure:
-	printk(" -- ERROR, UNABLE TO ALLOCATE DMA TABLES\n");
 }
diff -Nru a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c
--- a/drivers/ide/ide-features.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/ide-features.c	Sun Apr 14 12:16:59 2002
@@ -2,7 +2,7 @@
  * linux/drivers/block/ide-features.c	Version 0.04	June 9, 2000
  *
  *  Copyright (C) 1999-2000	Linus Torvalds & authors (see below)
- *  
+ *
  *  Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  *
  *  Extracts if ide.c to address the evolving transfer rate code for
@@ -69,34 +69,6 @@
 	}
 }
 
-/*
- * A Verbose noise maker for debugging on the attempted dmaing calls.
- */
-char *ide_dmafunc_verbose (ide_dma_action_t dmafunc)
-{
-	switch (dmafunc) {
-		case ide_dma_read:		return("ide_dma_read");
-		case ide_dma_write:		return("ide_dma_write");
-		case ide_dma_begin:		return("ide_dma_begin");
-		case ide_dma_end:		return("ide_dma_end:");
-		case ide_dma_check:		return("ide_dma_check");
-		case ide_dma_on:		return("ide_dma_on");
-		case ide_dma_off:		return("ide_dma_off");
-		case ide_dma_off_quietly:	return("ide_dma_off_quietly");
-		case ide_dma_test_irq:		return("ide_dma_test_irq");
-		case ide_dma_bad_drive:		return("ide_dma_bad_drive");
-		case ide_dma_good_drive:	return("ide_dma_good_drive");
-		case ide_dma_verbose:		return("ide_dma_verbose");
-		case ide_dma_retune:		return("ide_dma_retune");
-		case ide_dma_lostirq:		return("ide_dma_lostirq");
-		case ide_dma_timeout:		return("ide_dma_timeout");
-		default:			return("unknown");
-	}
-}
-
-/*
- *
- */
 byte ide_auto_reduce_xfer (ide_drive_t *drive)
 {
 	if (!drive->crc_count)
@@ -122,9 +94,6 @@
 	}
 }
 
-/*
- * Update the 
- */
 int ide_driveid_update (ide_drive_t *drive)
 {
 	/*
@@ -134,7 +103,7 @@
 	struct hd_driveid *id;
 	unsigned long timeout, flags;
 
-	SELECT_MASK(HWIF(drive), drive, 1);
+	SELECT_MASK(drive->channel, drive, 1);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	ide_delay_50ms();
@@ -142,20 +111,20 @@
 	timeout = jiffies + WAIT_WORSTCASE;
 	do {
 		if (0 < (signed long)(jiffies - timeout)) {
-			SELECT_MASK(HWIF(drive), drive, 0);
+			SELECT_MASK(drive->channel, drive, 0);
 			return 0;	/* drive timed-out */
 		}
 		ide_delay_50ms();	/* give drive a breather */
 	} while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
 	ide_delay_50ms();	/* wait for IRQ and DRQ_STAT */
 	if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
-		SELECT_MASK(HWIF(drive), drive, 0);
+		SELECT_MASK(drive->channel, drive, 0);
 		printk("%s: CHECK for good STATUS\n", drive->name);
 		return 0;
 	}
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only; some systems need this */
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_MASK(drive->channel, drive, 0);
 	id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
 	if (!id) {
 		__restore_flags(flags);	/* local CPU only */
@@ -184,21 +153,21 @@
  * in combination with the device (usually a disk) properly detect
  * and acknowledge each end of the ribbon.
  */
-int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
+int ide_ata66_check (ide_drive_t *drive, struct ata_taskfile *args)
 {
-	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
-	    (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
-	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
-		if (!HWIF(drive)->udma_four) {
-			printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name);
+	if ((args->taskfile.command == WIN_SETFEATURES) &&
+	    (args->taskfile.sector_number > XFER_UDMA_2) &&
+	    (args->taskfile.feature == SETFEATURES_XFER)) {
+		if (!drive->channel->udma_four) {
+			printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->channel->name);
 			return 1;
 		}
 #ifndef CONFIG_IDEDMA_IVB
 		if ((drive->id->hw_config & 0x6000) == 0) {
-#else /* !CONFIG_IDEDMA_IVB */
+#else
 		if (((drive->id->hw_config & 0x2000) == 0) ||
 		    ((drive->id->hw_config & 0x4000) == 0)) {
-#endif /* CONFIG_IDEDMA_IVB */
+#endif
 			printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name);
 			return 1;
 		}
@@ -211,11 +180,11 @@
  * 1 : Safe to update drive->id DMA registers.
  * 0 : OOPs not allowed.
  */
-int set_transfer (ide_drive_t *drive, ide_task_t *args)
+int set_transfer (ide_drive_t *drive, struct ata_taskfile *args)
 {
-	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
-	    (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
-	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
+	if ((args->taskfile.command == WIN_SETFEATURES) &&
+	    (args->taskfile.sector_number >= XFER_SW_DMA_0) &&
+	    (args->taskfile.feature == SETFEATURES_XFER) &&
 	    (drive->id->dma_ultra ||
 	     drive->id->dma_mword ||
 	     drive->id->dma_1word))
@@ -229,10 +198,10 @@
  */
 byte eighty_ninty_three (ide_drive_t *drive)
 {
-	return ((byte) ((HWIF(drive)->udma_four) &&
+	return ((byte) ((drive->channel->udma_four) &&
 #ifndef CONFIG_IDEDMA_IVB
 			(drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
+#endif
 			(drive->id->hw_config & 0x6000)) ? 1 : 0);
 }
 
@@ -249,8 +218,9 @@
  */
 int ide_config_drive_speed (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	int	i, error = 1;
+	struct ata_channel *hwif = drive->channel;
+	int i;
+	int error = 1;
 	byte stat;
 
 #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
@@ -269,8 +239,8 @@
          */
 	disable_irq(hwif->irq);	/* disable_irq_nosync ?? */
 	udelay(1);
-	SELECT_DRIVE(HWIF(drive), drive);
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_DRIVE(drive->channel, drive);
+	SELECT_MASK(drive->channel, drive, 0);
 	udelay(1);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
@@ -310,7 +280,7 @@
 		}
 	}
 
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_MASK(drive->channel, drive, 0);
 
 	enable_irq(hwif->irq);
 
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/ide-floppy.c	Sun Apr 14 12:16:56 2002
@@ -902,7 +902,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
-		if (HWIF(drive)->dmaproc(ide_dma_end, drive)) {
+		if (drive->channel->dmaproc(ide_dma_end, drive)) {
 			set_bit (PC_DMA_ERROR, &pc->flags);
 		} else {
 			pc->actually_transferred=pc->request_transfer;
@@ -945,7 +945,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk (KERN_ERR "ide-floppy: The floppy wants to issue more interrupts in DMA mode\n");
-		HWIF(drive)->dmaproc(ide_dma_off, drive);
+		drive->channel->dmaproc(ide_dma_off, drive);
 		return ide_stopped;
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -968,6 +968,7 @@
 			if (temp > pc->buffer_size) {
 				printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n");
 				idefloppy_discard_data (drive,bcount.all);
+				BUG_ON(HWGROUP(drive)->handler);
 				ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
 				return ide_started;
 			}
@@ -990,7 +991,9 @@
 	pc->actually_transferred+=bcount.all;				/* Update the current position */
 	pc->current_position+=bcount.all;
 
-	ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler(drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
+
 	return ide_started;
 }
 
@@ -1014,8 +1017,11 @@
 		printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
 		return ide_stopped;
 	}
+
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);	/* Set the interrupt routine */
 	atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */
+
 	return ide_started;
 }
 
@@ -1055,17 +1061,19 @@
 		printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
 		return ide_stopped;
 	}
-	/* 
+	/*
 	 * The following delay solves a problem with ATAPI Zip 100 drives where the
 	 * Busy flag was apparently being deasserted before the unit was ready to
 	 * receive data. This was happening on a 1200 MHz Athlon system. 10/26/01
-	 * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will 
+	 * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will
 	 * not be actually used until after the packet is moved in about 50 msec.
 	 */
-	ide_set_handler (drive, 
-	  &idefloppy_pc_intr, 		/* service routine for packet command */
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler (drive,
+	  &idefloppy_pc_intr,		/* service routine for packet command */
 	  floppy->ticks,			/* wait this long before "failing" */
 	  &idefloppy_transfer_pc2);	/* fail == transfer_pc2 */
+
 	return ide_started;
 }
 
@@ -1117,10 +1125,10 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
-		(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
+		(void) drive->channel->dmaproc(ide_dma_off, drive);
 	}
 	if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
-		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
+		dma_ok=!drive->channel->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (IDE_CONTROL_REG)
@@ -1133,7 +1141,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (dma_ok) {							/* Begin DMA, if necessary */
 		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
@@ -1143,8 +1151,9 @@
 	} else {
 		pkt_xfer_routine = &idefloppy_transfer_pc;	/* immediate */
 	}
-	
+
 	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL);
 		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		/* Issue the packet command */
 		return ide_started;
@@ -1156,7 +1165,7 @@
 
 static void idefloppy_rw_callback (ide_drive_t *drive)
 {
-#if IDEFLOPPY_DEBUG_LOG	
+#if IDEFLOPPY_DEBUG_LOG
 	printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
 #endif /* IDEFLOPPY_DEBUG_LOG */
 
@@ -2004,7 +2013,7 @@
 	(void) idefloppy_get_capacity (drive);
 	idefloppy_add_settings(drive);
 	for (i = 0; i < MAX_DRIVES; ++i) {
-		ide_hwif_t *hwif = HWIF(drive);
+		struct ata_channel *hwif = drive->channel;
 
 		if (drive != &hwif->drives[i]) continue;
 		hwif->gd->de_arr[i] = drive->de;
@@ -2109,10 +2118,9 @@
 			kfree (floppy);
 			continue;
 		}
-		/* ATA-PATTERN */
-		ata_ops(drive)->busy++;
+		MOD_INC_USE_COUNT;
 		idefloppy_setup (drive, floppy);
-		ata_ops(drive)->busy--;
+		MOD_DEC_USE_COUNT;
 
 		failed--;
 	}
diff -Nru a/drivers/ide/ide-geometry.c b/drivers/ide/ide-geometry.c
--- a/drivers/ide/ide-geometry.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/ide/ide-geometry.c	Sun Apr 14 12:16:54 2002
@@ -7,6 +7,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/ide.h>
 #include <linux/mc146818rtc.h>
 #include <asm/io.h>
diff -Nru a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
--- a/drivers/ide/ide-pci.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/ide-pci.c	Sun Apr 14 12:16:59 2002
@@ -39,45 +39,45 @@
 
 #ifdef CONFIG_BLK_DEV_AEC62XX
 extern unsigned int pci_init_aec62xx(struct pci_dev *);
-extern unsigned int ata66_aec62xx(ide_hwif_t *);
-extern void ide_init_aec62xx(ide_hwif_t *);
-extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_aec62xx(struct ata_channel *);
+extern void ide_init_aec62xx(struct ata_channel *);
+extern void ide_dmacapable_aec62xx(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_ALI15X3
 extern unsigned int pci_init_ali15x3(struct pci_dev *);
-extern unsigned int ata66_ali15x3(ide_hwif_t *);
-extern void ide_init_ali15x3(ide_hwif_t *);
-extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_ali15x3(struct ata_channel *);
+extern void ide_init_ali15x3(struct ata_channel *);
+extern void ide_dmacapable_ali15x3(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_AMD74XX
 extern unsigned int pci_init_amd74xx(struct pci_dev *);
-extern unsigned int ata66_amd74xx(ide_hwif_t *);
-extern void ide_init_amd74xx(ide_hwif_t *);
-extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_amd74xx(struct ata_channel *);
+extern void ide_init_amd74xx(struct ata_channel *);
+extern void ide_dmacapable_amd74xx(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_CMD64X
 extern unsigned int pci_init_cmd64x(struct pci_dev *);
-extern unsigned int ata66_cmd64x(ide_hwif_t *);
-extern void ide_init_cmd64x(ide_hwif_t *);
-extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_cmd64x(struct ata_channel *);
+extern void ide_init_cmd64x(struct ata_channel *);
+extern void ide_dmacapable_cmd64x(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_CY82C693
 extern unsigned int pci_init_cy82c693(struct pci_dev *);
-extern void ide_init_cy82c693(ide_hwif_t *);
+extern void ide_init_cy82c693(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_CS5530
 extern unsigned int pci_init_cs5530(struct pci_dev *);
-extern void ide_init_cs5530(ide_hwif_t *);
+extern void ide_init_cs5530(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_HPT34X
 extern unsigned int pci_init_hpt34x(struct pci_dev *);
-extern void ide_init_hpt34x(ide_hwif_t *);
+extern void ide_init_hpt34x(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_HPT366
@@ -85,9 +85,9 @@
 extern byte hpt363_shared_pin;
 
 extern unsigned int pci_init_hpt366(struct pci_dev *);
-extern unsigned int ata66_hpt366(ide_hwif_t *);
-extern void ide_init_hpt366(ide_hwif_t *);
-extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_hpt366(struct ata_channel *);
+extern void ide_init_hpt366(struct ata_channel *);
+extern void ide_dmacapable_hpt366(struct ata_channel *, unsigned long);
 #else
 /* FIXME: those have to be killed */
 static byte hpt363_shared_irq;
@@ -95,69 +95,69 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_NS87415
-extern void ide_init_ns87415(ide_hwif_t *);
+extern void ide_init_ns87415(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_OPTI621
-extern void ide_init_opti621(ide_hwif_t *);
+extern void ide_init_opti621(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_PDC_ADMA
 extern unsigned int pci_init_pdcadma(struct pci_dev *);
-extern unsigned int ata66_pdcadma(ide_hwif_t *);
-extern void ide_init_pdcadma(ide_hwif_t *);
-extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_pdcadma(struct ata_channel *);
+extern void ide_init_pdcadma(struct ata_channel *);
+extern void ide_dmacapable_pdcadma(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_PDC202XX
 extern unsigned int pci_init_pdc202xx(struct pci_dev *);
-extern unsigned int ata66_pdc202xx(ide_hwif_t *);
-extern void ide_init_pdc202xx(ide_hwif_t *);
+extern unsigned int ata66_pdc202xx(struct ata_channel *);
+extern void ide_init_pdc202xx(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_PIIX
 extern unsigned int pci_init_piix(struct pci_dev *);
-extern unsigned int ata66_piix(ide_hwif_t *);
-extern void ide_init_piix(ide_hwif_t *);
-extern void ide_dmacapable_piix(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_piix(struct ata_channel *);
+extern void ide_init_piix(struct ata_channel *);
+extern void ide_dmacapable_piix(struct ata_channel *, unsigned long);
 #endif
 
 #ifdef CONFIG_BLK_DEV_IT8172
 extern unsigned int pci_init_it8172(struct pci_dev *);
-extern void ide_init_it8172(ide_hwif_t *);
+extern void ide_init_it8172(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_RZ1000
-extern void ide_init_rz1000(ide_hwif_t *);
+extern void ide_init_rz1000(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_SVWKS
 extern unsigned int pci_init_svwks(struct pci_dev *);
-extern unsigned int ata66_svwks(ide_hwif_t *);
-extern void ide_init_svwks(ide_hwif_t *);
+extern unsigned int ata66_svwks(struct ata_channel *);
+extern void ide_init_svwks(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_SIS5513
 extern unsigned int pci_init_sis5513(struct pci_dev *);
-extern unsigned int ata66_sis5513(ide_hwif_t *);
-extern void ide_init_sis5513(ide_hwif_t *);
+extern unsigned int ata66_sis5513(struct ata_channel *);
+extern void ide_init_sis5513(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_SL82C105
 extern unsigned int pci_init_sl82c105(struct pci_dev *);
-extern void dma_init_sl82c105(ide_hwif_t *, unsigned long);
-extern void ide_init_sl82c105(ide_hwif_t *);
+extern void dma_init_sl82c105(struct ata_channel *, unsigned long);
+extern void ide_init_sl82c105(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_TRM290
-extern void ide_init_trm290(ide_hwif_t *);
+extern void ide_init_trm290(struct ata_channel *);
 #endif
 
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
 extern unsigned int pci_init_via82cxxx(struct pci_dev *);
-extern unsigned int ata66_via82cxxx(ide_hwif_t *);
-extern void ide_init_via82cxxx(ide_hwif_t *);
-extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
+extern unsigned int ata66_via82cxxx(struct ata_channel *);
+extern void ide_init_via82cxxx(struct ata_channel *);
+extern void ide_dmacapable_via82cxxx(struct ata_channel *, unsigned long);
 #endif
 
 typedef struct ide_pci_enablebit_s {
@@ -181,9 +181,9 @@
 	unsigned short		vendor;
 	unsigned short		device;
 	unsigned int		(*init_chipset)(struct pci_dev *dev);
-	unsigned int		(*ata66_check)(ide_hwif_t *hwif);
-	void			(*init_hwif)(ide_hwif_t *hwif);
-	void			(*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
+	unsigned int		(*ata66_check)(struct ata_channel *hwif);
+	void			(*init_channel)(struct ata_channel *hwif);
+	void			(*dma_init)(struct ata_channel *hwif, unsigned long dmabase);
 	ide_pci_enablebit_t	enablebits[2];
 	unsigned int		bootable;
 	unsigned int		extra;
@@ -229,6 +229,7 @@
 	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ  | ATA_F_DMA },
 	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, pci_init_pdc202xx, ata66_pdc202xx, ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
 	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, pci_init_pdc202xx, ata66_pdc202xx,	ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
+	{PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, pci_init_pdc202xx, ata66_pdc202xx,	ide_init_pdc202xx, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, ATA_F_IRQ | ATA_F_DMA },
 #endif
 #ifdef CONFIG_BLK_DEV_RZ1000
 	{PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, NULL, NULL,	ide_init_rz1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 },
@@ -328,10 +329,10 @@
  * Match a PCI IDE port against an entry in ide_hwifs[],
  * based on io_base port if possible.
  */
-static ide_hwif_t __init *lookup_hwif (unsigned long io_base, int bootable, const char *name)
+static struct ata_channel __init *lookup_hwif (unsigned long io_base, int bootable, const char *name)
 {
 	int h;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	/*
 	 * Look for a hwif with matching io_base specified using
@@ -430,29 +431,26 @@
 /*
  * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
  */
-static unsigned long __init get_dma_base(ide_hwif_t *hwif, int extra, const char *name)
+static unsigned long __init get_dma_base(struct ata_channel *hwif, int extra, const char *name)
 {
 	unsigned long	dma_base = 0;
 	struct pci_dev	*dev = hwif->pci_dev;
 
-	/*
-	 * If we are on the second channel, the dma base address will be one
-	 * entry away from the primary interface.
-	 */
-
-	if (hwif->mate && hwif->mate->dma_base)
-		dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
-	else
-		dma_base = pci_resource_start(dev, 4);
-
+	dma_base = pci_resource_start(dev, 4);
 	if (!dma_base)
 		return 0;
 
-	if (extra) /* PDC20246, PDC20262, HPT343, & HPT366 */
+	/* PDC20246, PDC20262, HPT343, & HPT366 */
+	if (extra) {
 		request_region(dma_base + 16, extra, name);
+		hwif->dma_extra = extra;
+	}
 
-	dma_base += hwif->channel ? 8 : 0;
-	hwif->dma_extra = extra;
+	/* If we are on the second channel, the dma base address will be one
+	 * entry away from the primary interface.
+	 */
+	if (hwif->unit == ATA_SECONDARY)
+		dma_base += 8;
 
 	if ((dev->vendor == PCI_VENDOR_ID_AL && dev->device == PCI_DEVICE_ID_AL_M5219) ||
 			(dev->vendor == PCI_VENDOR_ID_AMD && dev->device == PCI_DEVICE_ID_AMD_VIPER_7409) ||
@@ -462,8 +460,7 @@
 			printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
 	} else {
 
-		/*
-		 * If the device claims "simplex" DMA, this means only one of
+		/* If the device claims "simplex" DMA, this means only one of
 		 * the two interfaces can be trusted with DMA at any point in
 		 * time.  So we should enable DMA only on one of the two
 		 * interfaces.
@@ -471,7 +468,7 @@
 
 		if ((inb(dma_base + 2) & 0x80)) {
 			if ((!hwif->drives[0].present && !hwif->drives[1].present) ||
-					(hwif->mate && hwif->mate->dma_base)) {
+				hwif->unit == ATA_SECONDARY) {
 				printk("%s: simplex device:  DMA disabled\n", name);
 				dma_base = 0;
 			}
@@ -484,12 +481,13 @@
 /*
  * Setup DMA transfers on a channel.
  */
-static void __init setup_channel_dma(ide_hwif_t *hwif, struct pci_dev *dev,
+static void __init setup_channel_dma(struct ata_channel *hwif, struct pci_dev *dev,
 		ide_pci_device_t *d,
 		int port,
 		u8 class_rev,
-		int pciirq, ide_hwif_t **mate,
-		int autodma, unsigned short *pcicmd)
+		int pciirq,
+		int autodma,
+		unsigned short *pcicmd)
 {
 	unsigned long dma_base;
 
@@ -502,8 +500,13 @@
 	if (!((d->flags & ATA_F_DMA) || ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))))
 		return;
 
-	dma_base = get_dma_base(hwif, (!*mate && d->extra) ? d->extra : 0, dev->name);
-	if (dma_base && !(*pcicmd & PCI_COMMAND_MASTER)) {
+	dma_base = get_dma_base(hwif, ((port == ATA_PRIMARY) && d->extra) ? d->extra : 0, dev->name);
+	if (!dma_base) {
+		printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
+
+		return;
+	}
+	if (!(*pcicmd & PCI_COMMAND_MASTER)) {
 
 		/*
 		 * Set up BM-DMA capability (PnP BIOS should have done this already)
@@ -516,13 +519,10 @@
 			dma_base = 0;
 		}
 	}
-	if (dma_base) {
-		if (d->dma_init)
-			d->dma_init(hwif, dma_base);
-		else
-			ide_setup_dma(hwif, dma_base, 8);
-	} else
-		printk("%s: %s Bus-Master DMA was disabled by BIOS\n", hwif->name, dev->name);
+	if (d->dma_init)
+		d->dma_init(hwif, dma_base);
+	else
+		ide_setup_dma(hwif, dma_base, 8);
 }
 #endif
 
@@ -535,17 +535,17 @@
 		ide_pci_device_t *d,
 		int port,
 		u8 class_rev,
-		int pciirq, ide_hwif_t **mate,
+		int pciirq,
 		int autodma,
 		unsigned short *pcicmd)
 {
 	unsigned long base = 0;
 	unsigned long ctl = 0;
 	ide_pci_enablebit_t *e = &(d->enablebits[port]);
-	ide_hwif_t *hwif;
+	struct ata_channel *ch;
 
 	u8 tmp;
-	if (port == 1) {
+	if (port == ATA_SECONDARY) {
 
 		/* If this is a Promise FakeRaid controller, the 2nd controller
 		 * will be marked as disabled while it is actually there and
@@ -567,7 +567,7 @@
 
 	/* Nothing to be done for the second port.
 	 */
-	if (port == 1) {
+	if (port == ATA_SECONDARY) {
 		if ((d->flags & ATA_F_HPTHACK) && (class_rev < 0x03))
 			return 0;
 	}
@@ -597,57 +597,50 @@
 	if (!base)
 		base = port ? 0x170 : 0x1f0;
 
-	if ((hwif = lookup_hwif(base, d->bootable, dev->name)) == NULL)
+	if ((ch = lookup_hwif(base, d->bootable, dev->name)) == NULL)
 		return -ENOMEM;	/* no room in ide_hwifs[] */
 
-	if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
-		ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
-		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
-		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
-	}
-
-	hwif->chipset = ide_pci;
-	hwif->pci_dev = dev;
-	hwif->channel = port;
-	if (!hwif->irq)
-		hwif->irq = pciirq;
-
-	/* Setup the mate interface if we have two channels.
-	 */
-	if (*mate) {
-		hwif->mate = *mate;
-		(*mate)->mate = hwif;
-		if (d->flags & ATA_F_SER) {
-			hwif->serialized = 1;
-			(*mate)->serialized = 1;
-		}
-	}
+	if (ch->io_ports[IDE_DATA_OFFSET] != base) {
+		ide_init_hwif_ports(&ch->hw, base, (ctl | 2), NULL);
+		memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->io_ports));
+		ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
+	}
+
+	ch->chipset = ide_pci;
+	ch->pci_dev = dev;
+	ch->unit = port;
+	if (!ch->irq)
+		ch->irq = pciirq;
+
+	/* Serialize the interfaces if requested by configuration information.
+	 */
+	if (d->flags & ATA_F_SER)
+	    ch->serialized = 1;
 
 	/* Cross wired IRQ lines on UMC chips and no DMA transfers.*/
 	if (d->flags & ATA_F_FIXIRQ) {
-		hwif->irq = port ? 15 : 14;
+		ch->irq = port ? 15 : 14;
 		goto no_dma;
 	}
 	if (d->flags & ATA_F_NODMA)
 		goto no_dma;
 
 	/* Check whatever this interface is UDMA4 mode capable. */
-	if (hwif->udma_four) {
+	if (ch->udma_four) {
 		printk("%s: warning: ATA-66/100 forced bit set!\n", dev->name);
 	} else {
 		if (d->ata66_check)
-			hwif->udma_four = d->ata66_check(hwif);
+			ch->udma_four = d->ata66_check(ch);
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-	setup_channel_dma(hwif, dev, d, port, class_rev, pciirq,  mate, autodma, pcicmd);
+	setup_channel_dma(ch, dev, d, port, class_rev, pciirq, autodma, pcicmd);
 #endif
 
 no_dma:
-	if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
-		d->init_hwif(hwif);
-
-	*mate = hwif;
+	/* Call chipset-specific routine for each enabled channel. */
+	if (d->init_channel)
+		d->init_channel(ch);
 
 	return 0;
 }
@@ -669,7 +662,6 @@
 	int pciirq = 0;
 	unsigned short pcicmd = 0;
 	unsigned short tried_config = 0;
-	ide_hwif_t *mate = NULL;
 	unsigned int class_rev;
 
 #ifdef CONFIG_IDEDMA_AUTO
@@ -677,9 +669,9 @@
 		autodma = 1;
 #endif
 
-	if (d->init_hwif == IDE_NO_DRIVER) {
+	if (d->init_channel == IDE_NO_DRIVER) {
 		printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", dev->name);
-		d->init_hwif = NULL;
+		d->init_channel = NULL;
 	}
 
 	if (pci_enable_device(dev)) {
@@ -777,8 +769,8 @@
 	/*
 	 * Set up IDE chanells. First the primary, then the secondary.
 	 */
-	setup_host_channel(dev, d, 0, class_rev, pciirq, &mate, autodma, &pcicmd);
-	setup_host_channel(dev, d, 1, class_rev, pciirq, &mate, autodma, &pcicmd);
+	setup_host_channel(dev, d, ATA_PRIMARY, class_rev, pciirq, autodma, &pcicmd);
+	setup_host_channel(dev, d, ATA_SECONDARY, class_rev, pciirq, autodma, &pcicmd);
 }
 
 static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
@@ -854,12 +846,6 @@
 			if (hpt363_shared_pin && hpt363_shared_irq) {
 				d->bootable = ON_BOARD;
 				printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", dev->name, pin1, pin2);
-#if 0
-				/* I forgot why I did this once, but it fixed something. */
-				pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
-				printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
-				pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
-#endif
 			}
 			break;
 		}
@@ -892,7 +878,7 @@
 	while (d->vendor && !(d->vendor == vendor && d->device == device))
 		++d;
 
-	if (d->init_hwif == ATA_PCI_IGNORE)
+	if (d->init_channel == ATA_PCI_IGNORE)
 		printk("%s: has been ignored by PCI bus scan\n", dev->name);
 	else if ((d->vendor == PCI_VENDOR_ID_OPTI && d->device == PCI_DEVICE_ID_OPTI_82C558) && !(PCI_FUNC(dev->devfn) & 1))
 		return;
diff -Nru a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c
--- a/drivers/ide/ide-pmac.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/ide-pmac.c	Sun Apr 14 12:16:59 2002
@@ -15,6 +15,16 @@
  * Some code taken from drivers/ide/ide-dma.c:
  *
  *  Copyright (c) 1995-1998  Mark Lord
+ *  
+ * TODO:
+ * 
+ *  - Find a way to duplicate less code with ide-dma and use the
+ *    dma fileds in the hwif structure instead of our own
+ *  - Fix check_disk_change() call
+ *  - Make module-able (includes setting ppc_md. hooks from within
+ *    this file and not from arch code, and handling module deps with
+ *    mediabay (by having both modules do dynamic lookup of each other
+ *    symbols or by storing hooks at arch level).
  *
  */
 #include <linux/config.h>
@@ -24,26 +34,29 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
+#include <linux/pci.h>
 
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/ide.h>
 #include <asm/mediabay.h>
-#include <asm/feature.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/sections.h>
+#include <asm/irq.h>
 #ifdef CONFIG_PMAC_PBOOK
 #include <linux/adb.h>
 #include <linux/pmu.h>
-#include <asm/irq.h>
 #endif
 #include "ata-timing.h"
 
-extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
+extern spinlock_t ide_lock;
 
 #undef IDE_PMAC_DEBUG
 
-#define IDE_SYSCLK_NS		30
-#define IDE_SYSCLK_ULTRA_PS	0x1d4c /* (15 * 1000 / 2)*/
+#define DMA_WAIT_TIMEOUT	500
 
 struct pmac_ide_hwif {
 	ide_ioreg_t			regbase;
@@ -53,11 +66,20 @@
 	struct device_node*		node;
 	u32				timings[2];
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+	/* Those fields are duplicating what is in hwif. We currently
+	 * can't use the hwif ones because of some assumptions that are
+	 * beeing done by the generic code about the kind of dma controller
+	 * and format of the dma table. This will have to be fixed though.
+	 */
 	volatile struct dbdma_regs*	dma_regs;
-	struct dbdma_cmd*		dma_table;
-#endif
+	struct dbdma_cmd*		dma_table_cpu;
+	dma_addr_t			dma_table_dma;
+	struct scatterlist*		sg_table;
+	int				sg_nents;
+	int				sg_dma_direction;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 	
-} pmac_ide[MAX_HWIFS];
+} pmac_ide[MAX_HWIFS] __pmacdata;
 
 static int pmac_ide_count;
 
@@ -65,33 +87,160 @@
 	controller_ohare,	/* OHare based */
 	controller_heathrow,	/* Heathrow/Paddington */
 	controller_kl_ata3,	/* KeyLargo ATA-3 */
-	controller_kl_ata4	/* KeyLargo ATA-4 */
+	controller_kl_ata4,	/* KeyLargo ATA-4 */
+	controller_kl_ata4_80	/* KeyLargo ATA-4 with 80 conductor cable */
 };
 
+/*
+ * Extra registers, both 32-bit little-endian
+ */
+#define IDE_TIMING_CONFIG	0x200
+#define IDE_INTERRUPT		0x300
+
+/*
+ * Timing configuration register definitions
+ */
+
+/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
+#define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
+#define SYSCLK_TICKS_66(t)	(((t) + IDE_SYSCLK_66_NS - 1) / IDE_SYSCLK_66_NS)
+#define IDE_SYSCLK_NS		30	/* 33Mhz cell */
+#define IDE_SYSCLK_66_NS	15	/* 66Mhz cell */
+
+/* 66Mhz cell, found in KeyLargo. Can do ultra mode 0 to 2 on
+ * 40 connector cable and to 4 on 80 connector one.
+ * Clock unit is 15ns (66Mhz)
+ * 
+ * 3 Values can be programmed:
+ *  - Write data setup, which appears to match the cycle time. They
+ *    also call it DIOW setup.
+ *  - Ready to pause time (from spec)
+ *  - Address setup. That one is weird. I don't see where exactly
+ *    it fits in UDMA cycles, I got it's name from an obscure piece
+ *    of commented out code in Darwin. They leave it to 0, we do as
+ *    well, despite a comment that would lead to think it has a
+ *    min value of 45ns.
+ * Apple also add 60ns to the write data setup (or cycle time ?) on
+ * reads. I can't explain that, I tried it and it broke everything
+ * here.
+ */
+#define TR_66_UDMA_MASK			0xfff00000
+#define TR_66_UDMA_EN			0x00100000 /* Enable Ultra mode for DMA */
+#define TR_66_UDMA_ADDRSETUP_MASK	0xe0000000 /* Address setup */
+#define TR_66_UDMA_ADDRSETUP_SHIFT	29
+#define TR_66_UDMA_RDY2PAUS_MASK	0x1e000000 /* Ready 2 pause time */
+#define TR_66_UDMA_RDY2PAUS_SHIFT	25
+#define TR_66_UDMA_WRDATASETUP_MASK	0x01e00000 /* Write data setup time */
+#define TR_66_UDMA_WRDATASETUP_SHIFT	21
+#define TR_66_MDMA_MASK			0x000ffc00
+#define TR_66_MDMA_RECOVERY_MASK	0x000f8000
+#define TR_66_MDMA_RECOVERY_SHIFT	15
+#define TR_66_MDMA_ACCESS_MASK		0x00007c00
+#define TR_66_MDMA_ACCESS_SHIFT		10
+#define TR_66_PIO_MASK			0x000003ff
+#define TR_66_PIO_RECOVERY_MASK		0x000003e0
+#define TR_66_PIO_RECOVERY_SHIFT	5
+#define TR_66_PIO_ACCESS_MASK		0x0000001f
+#define TR_66_PIO_ACCESS_SHIFT		0
+
+/* 33Mhz cell, found in OHare, Heathrow (& Paddington) and KeyLargo
+ * Can do pio & mdma modes, clock unit is 30ns (33Mhz)
+ * 
+ * The access time and recovery time can be programmed. Some older
+ * Darwin code base limit OHare to 150ns cycle time. I decided to do
+ * the same here fore safety against broken old hardware ;)
+ * The HalfTick bit, when set, adds half a clock (15ns) to the access
+ * time and removes one from recovery. It's not supported on KeyLargo
+ * implementation afaik. The E bit appears to be set for PIO mode 0 and
+ * is used to reach long timings used in this mode.
+ */
+#define TR_33_MDMA_MASK			0x003ff800
+#define TR_33_MDMA_RECOVERY_MASK	0x001f0000
+#define TR_33_MDMA_RECOVERY_SHIFT	16
+#define TR_33_MDMA_ACCESS_MASK		0x0000f800
+#define TR_33_MDMA_ACCESS_SHIFT		11
+#define TR_33_MDMA_HALFTICK		0x00200000
+#define TR_33_PIO_MASK			0x000007ff
+#define TR_33_PIO_E			0x00000400
+#define TR_33_PIO_RECOVERY_MASK		0x000003e0
+#define TR_33_PIO_RECOVERY_SHIFT	5
+#define TR_33_PIO_ACCESS_MASK		0x0000001f
+#define TR_33_PIO_ACCESS_SHIFT		0
+
+/*
+ * Interrupt register definitions
+ */
+#define IDE_INTR_DMA			0x80000000
+#define IDE_INTR_DEVICE			0x40000000
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
-typedef struct {
+# define BAD_DMA_DRIVE		0
+# define GOOD_DMA_DRIVE		1
+
+/* Rounded Multiword DMA timings
+ * 
+ * I gave up finding a generic formula for all controller
+ * types and instead, built tables based on timing values
+ * used by Apple in Darwin's implementation.
+ */
+struct mdma_timings_t {
 	int	accessTime;
+	int	recoveryTime;
 	int	cycleTime;
-} pmac_ide_timing;
+};
 
-/* Multiword DMA timings */
-static pmac_ide_timing mdma_timings[] =
+struct mdma_timings_t mdma_timings_33[] __pmacdata =
 {
-    { 215,    480 },	/* Mode 0 */
-    {  80,    150 },	/*      1 */
-    {  70,    120 }	/*      2 */
+    { 240, 240, 480 },
+    { 180, 180, 360 },
+    { 135, 135, 270 },
+    { 120, 120, 240 },
+    { 105, 105, 210 },
+    {  90,  90, 180 },
+    {  75,  75, 150 },
+    {  75,  45, 120 },
+    {   0,   0,   0 }
 };
 
-/* Ultra DMA timings (for use when I know how to calculate them */
-static pmac_ide_timing udma_timings[] =
+struct mdma_timings_t mdma_timings_33k[] __pmacdata =
 {
-    {   0,    114 },	/* Mode 0 */
-    {   0,     75 },	/*      1 */
-    {   0,     55 },	/*      2 */
-    {   100,   45 },	/*      3 */
-    {   100,   25 }	/*      4 */
+    { 240, 240, 480 },
+    { 180, 180, 360 },
+    { 150, 150, 300 },
+    { 120, 120, 240 },
+    {  90, 120, 210 },
+    {  90,  90, 180 },
+    {  90,  60, 150 },
+    {  90,  30, 120 },
+    {   0,   0,   0 }
+};
+
+struct mdma_timings_t mdma_timings_66[] __pmacdata =
+{
+    { 240, 240, 480 },
+    { 180, 180, 360 },
+    { 135, 135, 270 },
+    { 120, 120, 240 },
+    { 105, 105, 210 },
+    {  90,  90, 180 },
+    {  90,  75, 165 },
+    {  75,  45, 120 },
+    {   0,   0,   0 }
+};
+
+/* Ultra DMA timings (rounded) */
+struct {
+	int	addrSetup; /* ??? */
+	int	rdy2pause;
+	int	wrDataSetup;
+} udma_timings[] __pmacdata =
+{
+    {   0, 180,  120 },	/* Mode 0 */
+    {   0, 150,  90 },	/*      1 */
+    {   0, 120,  60 },	/*      2 */
+    {   0, 90,   45 },	/*      3 */
+    {   0, 90,   30 }	/*      4 */
 };
 
 /* allow up to 256 DBDMA commands per xfer */
@@ -121,13 +270,13 @@
 };
 #endif /* CONFIG_PMAC_PBOOK */
 
-static int
+static int __pmac
 pmac_ide_find(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	ide_ioreg_t base;
 	int i;
-	
+
 	for (i=0; i<pmac_ide_count; i++) {
 		base = pmac_ide[i].regbase;
 		if (base && base == hwif->io_ports[0])
@@ -140,7 +289,8 @@
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
-void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+void __pmac
+pmac_ide_init_hwif_ports(hw_regs_t *hw,
 			      ide_ioreg_t data_port, ide_ioreg_t ctrl_port,
 			      int *irq)
 {
@@ -171,7 +321,7 @@
 	ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
 	ide_hwifs[ix].selectproc = pmac_ide_selectproc;
 	ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
-	if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
+	if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table_cpu) {
 		ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
 		if (!noautodma)
@@ -198,24 +348,33 @@
 /* Setup timings for the selected drive (master/slave). I still need to verify if this
  * is enough, I beleive selectproc will be called whenever an IDE command is started,
  * but... */
-static void
+static void __pmac
 pmac_ide_selectproc(ide_drive_t *drive)
 {
 	int i = pmac_ide_find(drive);
 	if (i < 0)
 		return;
-			
-	if (drive->select.all & 0x10)
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[1]);
+
+	if (drive->select.b.unit & 0x01)
+		out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
+			pmac_ide[i].timings[1]);
 	else
-		out_le32((unsigned *)(IDE_DATA_REG + 0x200 + _IO_BASE), pmac_ide[i].timings[0]);
+		out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
+			pmac_ide[i].timings[0]);
+	(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
 }
 
-/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
-#define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
-#define SYSCLK_TICKS_UDMA(t)	(((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
 
-static __inline__ int
+/* Note: We don't use the generic routine here because for some
+ * yet unexplained reasons, it cause some media-bay CD-ROMs to
+ * lockup the bus. Strangely, this new version of the code is
+ * almost identical to the generic one and works, I've not yet
+ * managed to figure out what bit is causing the lockup in the
+ * generic code, possibly a timing issue...
+ * 
+ * --BenH
+ */
+static int __pmac
 wait_for_ready(ide_drive_t *drive)
 {
 	/* Timeout bumped for some powerbooks */
@@ -241,57 +400,80 @@
 	return 0;
 }
 
-/* Note: We don't use the generic routine here because some of Apple's
- * controller seem to be very sensitive about how things are done.
- * We should probably set the NIEN bit, but that's an example of thing
- * that can cause the controller to hang under some circumstances when
- * done on the media-bay CD-ROM during boot. We do get occasional
- * spurrious interrupts because of that.
- * --BenH
- */
-static int
+static int __pmac
 pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
 {
-	unsigned long flags;
 	int result = 1;
-
-	save_flags(flags);
-	cli();
+	unsigned long flags;
+	struct ata_channel *hwif = HWIF(drive);
+	
+	disable_irq(hwif->irq);	/* disable_irq_nosync ?? */
 	udelay(1);
-	SELECT_DRIVE(HWIF(drive), drive);
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_DRIVE(drive->channel, drive);
+	SELECT_MASK(drive->channel, drive, 0);
 	udelay(1);
+	(void)GET_STAT(); /* Get rid of pending error state */
 	if(wait_for_ready(drive)) {
 		printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
 		goto out;
 	}
-	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+	udelay(10);
+	OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
 	OUT_BYTE(command, IDE_NSECTOR_REG);
+	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
 	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
 	udelay(1);
+	__save_flags(flags);	/* local CPU only */
+	ide__sti();		/* local CPU only -- for jiffies */
 	result = wait_for_ready(drive);
+	__restore_flags(flags); /* local CPU only */
+	OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
 	if (result)
 		printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
 out:
-	restore_flags(flags);
+	SELECT_MASK(HWIF(drive), drive, 0);
+	if (result == 0) {
+		drive->id->dma_ultra &= ~0xFF00;
+		drive->id->dma_mword &= ~0x0F00;
+		drive->id->dma_1word &= ~0x0F00;
+		switch(command) {
+			case XFER_UDMA_7:   drive->id->dma_ultra |= 0x8080; break;
+			case XFER_UDMA_6:   drive->id->dma_ultra |= 0x4040; break;
+			case XFER_UDMA_5:   drive->id->dma_ultra |= 0x2020; break;
+			case XFER_UDMA_4:   drive->id->dma_ultra |= 0x1010; break;
+			case XFER_UDMA_3:   drive->id->dma_ultra |= 0x0808; break;
+			case XFER_UDMA_2:   drive->id->dma_ultra |= 0x0404; break;
+			case XFER_UDMA_1:   drive->id->dma_ultra |= 0x0202; break;
+			case XFER_UDMA_0:   drive->id->dma_ultra |= 0x0101; break;
+			case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;
+			case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;
+			case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;
+			case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;
+			case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;
+			case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;
+			default: break;
+		}
+	}
+	enable_irq(hwif->irq);
 
 	return result;
 }
 
 /* Calculate PIO timings */
-static void
+static void __pmac
 pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
 {
 	struct ata_timing *t;
 	int i;
 	u32 *timings;
-	int accessTicks, recTicks;
+	unsigned accessTicks, recTicks;
+	unsigned accessTime, recTime;
 
 	i = pmac_ide_find(drive);
 	if (i < 0)
 		return;
 
-	if (pio = 255)
+	if (pio == 255)
 		pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
 	else
 		pio = XFER_PIO_0 + min_t(byte, pio, 4);
@@ -299,27 +481,40 @@
 	t = ata_timing_data(pio);
 
 	accessTicks = SYSCLK_TICKS(t->active);
-	if (drive->select.all & 0x10)
-		timings = &pmac_ide[i].timings[1];
-	else
-		timings = &pmac_ide[i].timings[0];
+	timings = &pmac_ide[i].timings[drive->select.b.unit & 0x01];
 
-	if (pmac_ide[i].kind == controller_kl_ata4) {
-		/* The "ata-4" IDE controller of Core99 machines */
-		accessTicks = SYSCLK_TICKS_UDMA(t->active * 1000);
-		recTicks = SYSCLK_TICKS_UDMA(t->cycle * 1000) - accessTicks;
-
-		*timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5);
+	recTime = t->cycle - t->active - t->setup;
+	recTime = max(recTime, 150U);
+	accessTime = t->active;
+	accessTime = max(accessTime, 150U);
+	if (pmac_ide[i].kind == controller_kl_ata4 ||
+		pmac_ide[i].kind == controller_kl_ata4_80) {
+		/* 66Mhz cell */
+		accessTicks = SYSCLK_TICKS_66(accessTime);
+		accessTicks = min(accessTicks, 0x1fU);
+		recTicks = SYSCLK_TICKS_66(recTime);
+		recTicks = min(recTicks, 0x1fU);
+		*timings = ((*timings) & ~TR_66_PIO_MASK) |
+				(accessTicks << TR_66_PIO_ACCESS_SHIFT) |
+				(recTicks << TR_66_PIO_RECOVERY_SHIFT);
 	} else {
-		/* The old "ata-3" IDE controller */
-		accessTicks = SYSCLK_TICKS(t->active);
-		if (accessTicks < 4)
-			accessTicks = 4;
-		recTicks = SYSCLK_TICKS(t->cycle) - accessTicks - 4;
-		if (recTicks < 1)
-			recTicks = 1;
-	
-		*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
+		/* 33Mhz cell */
+		int ebit = 0;
+		accessTicks = SYSCLK_TICKS(accessTime);
+		accessTicks = min(accessTicks, 0x1fU);
+		accessTicks = max(accessTicks, 4U);
+		recTicks = SYSCLK_TICKS(recTime);
+		recTicks = min(recTicks, 0x1fU);
+		recTicks = max(recTicks, 5U) - 4;
+		if (recTicks > 9) {
+			recTicks--; /* guess, but it's only for PIO0, so... */
+			ebit = 1;
+		}
+		*timings = ((*timings) & ~TR_33_PIO_MASK) |
+				(accessTicks << TR_33_PIO_ACCESS_SHIFT) |
+				(recTicks << TR_33_PIO_RECOVERY_SHIFT);
+		if (ebit)
+			*timings |= TR_33_PIO_E;
 	}
 
 #ifdef IDE_PMAC_DEBUG
@@ -332,70 +527,134 @@
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-static int
-set_timings_udma(int intf, u32 *timings, byte speed)
+static int __pmac
+set_timings_udma(u32 *timings, byte speed)
 {
-	int cycleTime, accessTime;
-	int rdyToPauseTicks, cycleTicks;
-
-	if (pmac_ide[intf].kind != controller_kl_ata4)
-		return 1;
-		
-	cycleTime = udma_timings[speed & 0xf].cycleTime;
-	accessTime = udma_timings[speed & 0xf].accessTime;
+	unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
 
-	rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-	cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
-
-	*timings = ((*timings) & 0xe00fffff) |
-			((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+	rdyToPauseTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].rdy2pause);
+	wrDataSetupTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].wrDataSetup);
+	addrTicks = SYSCLK_TICKS_66(udma_timings[speed & 0xf].addrSetup);
+
+	*timings = ((*timings) & ~(TR_66_UDMA_MASK | TR_66_MDMA_MASK)) |
+			(wrDataSetupTicks << TR_66_UDMA_WRDATASETUP_SHIFT) | 
+			(rdyToPauseTicks << TR_66_UDMA_RDY2PAUS_SHIFT) |
+			(addrTicks <<TR_66_UDMA_ADDRSETUP_SHIFT) |
+			TR_66_UDMA_EN;
+#ifdef IDE_PMAC_DEBUG
+	printk(KERN_ERR "ide_pmac: Set UDMA timing for mode %d, reg: 0x%08x\n",
+		speed & 0xf,  *timings);
+#endif	
 
 	return 0;
 }
 
-static int
-set_timings_mdma(int intf, u32 *timings, byte speed)
+static int __pmac
+set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time)
 {
-	int cycleTime, accessTime;
-	int accessTicks, recTicks;
+	int cycleTime, accessTime, recTime;
+	unsigned accessTicks, recTicks;
+	struct mdma_timings_t* tm;
+	int i;
 
-	/* Calculate accesstime and cycle time */
-	cycleTime = mdma_timings[speed & 0xf].cycleTime;
-	accessTime = mdma_timings[speed & 0xf].accessTime;
-	if ((pmac_ide[intf].kind == controller_ohare) && (cycleTime < 150))
+	/* Get default cycle time for mode */
+	switch(speed & 0xf) {
+		case 0: cycleTime = 480; break;
+		case 1: cycleTime = 150; break;
+		case 2: cycleTime = 120; break;
+		default:
+			return -1;
+	}
+	/* Adjust for drive */
+	if (drive_cycle_time && drive_cycle_time > cycleTime)
+		cycleTime = drive_cycle_time;
+	/* OHare limits according to some old Apple sources */	
+	if ((intf_type == controller_ohare) && (cycleTime < 150))
 		cycleTime = 150;
+	/* Get the proper timing array for this controller */
+	switch(intf_type) {
+		case controller_kl_ata4:
+		case controller_kl_ata4_80:
+			tm = mdma_timings_66;
+			break;
+		case controller_kl_ata3:
+			tm = mdma_timings_33k;
+			break;
+		default:
+			tm = mdma_timings_33;
+			break;
+	}
+	/* Lookup matching access & recovery times */
+	i = -1;
+	for (;;) {
+		if (tm[i+1].cycleTime < cycleTime)
+			break;
+		i++;
+	}
+	if (i < 0)
+		return -1;
+	cycleTime = tm[i].cycleTime;
+	accessTime = tm[i].accessTime;
+	recTime = tm[i].recoveryTime;
 
-	/* For ata-4 controller */
-	if (pmac_ide[intf].kind == controller_kl_ata4) {
-		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
-		*timings = ((*timings) & 0xffe003ff) |
-			(accessTicks | (recTicks << 5)) << 10;
+#ifdef IDE_PMAC_DEBUG
+	printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",
+		cycleTime, accessTime, recTime);
+#endif	
+	if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) {
+		/* 66Mhz cell */
+		accessTicks = SYSCLK_TICKS_66(accessTime);
+		accessTicks = min(accessTicks, 0x1fU);
+		accessTicks = max(accessTicks, 0x1U);
+		recTicks = SYSCLK_TICKS_66(recTime);
+		recTicks = min(recTicks, 0x1fU);
+		recTicks = max(recTicks, 0x3U);
+		/* Clear out mdma bits and disable udma */
+		*timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) |
+			(accessTicks << TR_66_MDMA_ACCESS_SHIFT) |
+			(recTicks << TR_66_MDMA_RECOVERY_SHIFT);
+	} else if (intf_type == controller_kl_ata3) {
+		/* 33Mhz cell on KeyLargo */
+		accessTicks = SYSCLK_TICKS(accessTime);
+		accessTicks = max(accessTicks, 1U);
+		accessTicks = min(accessTicks, 0x1fU);
+		accessTime = accessTicks * IDE_SYSCLK_NS;
+		recTicks = SYSCLK_TICKS(recTime);
+		recTicks = max(recTicks, 1U);
+		recTicks = min(recTicks, 0x1fU);
+		*timings = ((*timings) & ~TR_33_MDMA_MASK) |
+				(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
+				(recTicks << TR_33_MDMA_RECOVERY_SHIFT);
 	} else {
+		/* 33Mhz cell on others */
 		int halfTick = 0;
 		int origAccessTime = accessTime;
-		int origCycleTime = cycleTime;
+		int origRecTime = recTime;
 		
 		accessTicks = SYSCLK_TICKS(accessTime);
-		if (accessTicks < 1)
-			accessTicks = 1;
+		accessTicks = max(accessTicks, 1U);
+		accessTicks = min(accessTicks, 0x1fU);
 		accessTime = accessTicks * IDE_SYSCLK_NS;
-		recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
-		if (recTicks < 1)
-			recTicks = 1;
-		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
-
-		/* KeyLargo ata-3 don't support the half-tick stuff */
-		if ((pmac_ide[intf].kind != controller_kl_ata3) &&
-			(accessTicks > 1) &&
-			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
-			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
-            			halfTick    = 1;
-				accessTicks--;
+		recTicks = SYSCLK_TICKS(recTime);
+		recTicks = max(recTicks, 2U) - 1;
+		recTicks = min(recTicks, 0x1fU);
+		recTime = (recTicks + 1) * IDE_SYSCLK_NS;
+		if ((accessTicks > 1) &&
+		    ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
+		    ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) {
+            		halfTick = 1;
+			accessTicks--;
 		}
-		*timings = ((*timings) & 0x7FF) |
-			(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
+		*timings = ((*timings) & ~TR_33_MDMA_MASK) |
+				(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |
+				(recTicks << TR_33_MDMA_RECOVERY_SHIFT);
+		if (halfTick)
+			*timings |= TR_33_MDMA_HALFTICK;
 	}
+#ifdef IDE_PMAC_DEBUG
+	printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
+		speed & 0xf,  *timings);
+#endif	
 	return 0;
 }
 #endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
@@ -403,11 +662,11 @@
 /* You may notice we don't use this function on normal operation,
  * our, normal mdma function is supposed to be more precise
  */
-static int
+static int __pmac
 pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
 {
 	int intf		= pmac_ide_find(drive);
-	int unit		= (drive->select.all & 0x10) ? 1:0;
+	int unit		= (drive->select.b.unit & 0x01);
 	int ret			= 0;
 	u32 *timings;
 
@@ -420,19 +679,25 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 		case XFER_UDMA_4:
 		case XFER_UDMA_3:
+			if (pmac_ide[intf].kind != controller_kl_ata4_80)
+				return 1;		
 		case XFER_UDMA_2:
 		case XFER_UDMA_1:
 		case XFER_UDMA_0:
-			ret = set_timings_udma(intf, timings, speed);
+			if (pmac_ide[intf].kind != controller_kl_ata4 &&
+				pmac_ide[intf].kind != controller_kl_ata4_80)
+				return 1;		
+			ret = set_timings_udma(timings, speed);
 			break;
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_MW_DMA_0:
+			ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0);
+			break;
 		case XFER_SW_DMA_2:
 		case XFER_SW_DMA_1:
 		case XFER_SW_DMA_0:
-			ret = set_timings_mdma(intf, timings, speed);
-			break;
+			return 1;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 		case XFER_PIO_4:
 		case XFER_PIO_3:
@@ -457,13 +722,46 @@
 	return 0;
 }
 
-ide_ioreg_t
+static void __pmac
+sanitize_timings(int i)
+{
+	unsigned value;
+	
+	switch(pmac_ide[i].kind) {
+		case controller_kl_ata4:
+		case controller_kl_ata4_80:
+			value = 0x0008438c;
+			break;
+		case controller_kl_ata3:
+			value = 0x00084526;
+			break;
+		case controller_heathrow:
+		case controller_ohare:
+		default:
+			value = 0x00074526;
+			break;
+	}
+	pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value;
+}
+
+ide_ioreg_t __pmac
 pmac_ide_get_base(int index)
 {
 	return pmac_ide[index].regbase;
 }
 
-int
+int __pmac
+pmac_ide_check_base(ide_ioreg_t base)
+{
+	int ix;
+	
+ 	for (ix = 0; ix < MAX_HWIFS; ++ix)
+		if (base == pmac_ide[ix].regbase)
+			return ix;
+	return -1;
+}
+
+int __pmac
 pmac_ide_get_irq(ide_ioreg_t base)
 {
 	int ix;
@@ -474,7 +772,7 @@
 	return 0;
 }
 
-static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+static int ide_majors[]  __pmacdata = { 3, 22, 33, 34, 56, 57 };
 
 kdev_t __init
 pmac_find_ide_boot(char *bootdevice, int n)
@@ -491,11 +789,11 @@
 		name = pmac_ide[i].node->full_name;
 		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
 			/* XXX should cope with the 2nd drive as well... */
-			return MKDEV(ide_majors[i], 0);
+			return mk_kdev(ide_majors[i], 0);
 		}
 	}
 
-	return 0;
+	return NODEV;
 }
 
 void __init
@@ -507,7 +805,7 @@
 	struct device_node *p, **pp, *removables, **rp;
 	unsigned long base;
 	int irq, big_delay;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 
 	if (_machine != _MACH_Pmac)
 		return;
@@ -538,9 +836,12 @@
 
 	for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
 		struct device_node *tp;
+		struct pmac_ide_hwif *pmif;
 		int *bidp;
 		int in_bay = 0;
-
+		u8 pbus, pid;
+		struct pci_dev *pdev = NULL;
+		
 		/*
 		 * If this node is not under a mac-io or dbdma node,
 		 * leave it to the generic PCI driver.
@@ -558,6 +859,15 @@
 			continue;
 		}
 
+		/* We need to find the pci_dev of the mac-io holding the
+		 * IDE interface
+		 */
+		if (pci_device_from_OF_node(tp, &pbus, &pid) == 0)
+			pdev = pci_find_slot(pbus, pid);
+		if (pdev == NULL)
+			printk(KERN_WARNING "ide: no PCI host for device %s, DMA disabled\n",
+			       np->full_name);
+		
 		/*
 		 * If this slot is taken (e.g. by ide-pci.c) try the next one.
 		 */
@@ -566,8 +876,23 @@
 			++i;
 		if (i >= MAX_HWIFS)
 			break;
+		pmif = &pmac_ide[i];
 
-		base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _IO_BASE;
+		/*
+		 * Some older OFs have bogus sizes, causing request_OF_resource
+		 * to fail. We fix them up here
+		 */
+		if (np->addrs[0].size > 0x1000)
+			np->addrs[0].size = 0x1000;
+		if (np->n_addrs > 1 && np->addrs[1].size > 0x100)
+			np->addrs[1].size = 0x100;
+
+		if (request_OF_resource(np, 0, "  (mac-io IDE IO)") == NULL) {
+			printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name);
+			continue;
+		}
+
+		base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE;
 
 		/* XXX This is bogus. Should be fixed in the registry by checking
 		   the kind of host interrupt controller, a bit like gatwick
@@ -580,21 +905,30 @@
 		} else {
 			irq = np->intrs[0].line;
 		}
-		pmac_ide[i].regbase = base;
-		pmac_ide[i].irq = irq;
-		pmac_ide[i].node = np;
+		pmif->regbase = base;
+		pmif->irq = irq;
+		pmif->node = np;
 		if (device_is_compatible(np, "keylargo-ata")) {
 			if (strcmp(np->name, "ata-4") == 0)
-				pmac_ide[i].kind = controller_kl_ata4;
+				pmif->kind = controller_kl_ata4;
 			else
-				pmac_ide[i].kind = controller_kl_ata3;
+				pmif->kind = controller_kl_ata3;
 		} else if (device_is_compatible(np, "heathrow-ata"))
-			pmac_ide[i].kind = controller_heathrow;
+			pmif->kind = controller_heathrow;
 		else
-			pmac_ide[i].kind = controller_ohare;
+			pmif->kind = controller_ohare;
 
 		bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
-		pmac_ide[i].aapl_bus_id =  bidp ? *bidp : 0;
+		pmif->aapl_bus_id =  bidp ? *bidp : 0;
+
+		if (pmif->kind == controller_kl_ata4) {
+			char* cable = get_property(np, "cable-type", NULL);
+			if (cable && !strncmp(cable, "80-", 3))
+				pmif->kind = controller_kl_ata4_80;
+		}
+
+		/* Make sure we have sane timings */
+		sanitize_timings(i);
 
 		if (np->parent && np->parent->name
 		    && strcasecmp(np->parent->name, "media-bay") == 0) {
@@ -602,39 +936,22 @@
 			media_bay_set_ide_infos(np->parent,base,irq,i);
 #endif /* CONFIG_PMAC_PBOOK */
 			in_bay = 1;
-		} else if (pmac_ide[i].kind == controller_ohare) {
+			if (!bidp)
+				pmif->aapl_bus_id = 1;
+		} else if (pmif->kind == controller_ohare) {
 			/* The code below is having trouble on some ohare machines
 			 * (timing related ?). Until I can put my hand on one of these
 			 * units, I keep the old way
 			 */
-			 feature_set(np, FEATURE_IDE0_enable);
+			ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
 		} else {
  			/* This is necessary to enable IDE when net-booting */
 			printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",
-				pmac_ide[i].aapl_bus_id);
-			switch(pmac_ide[i].aapl_bus_id) {
-			    case 0:
-				feature_set(np, FEATURE_IDE0_reset);
-				mdelay(10);
- 				feature_set(np, FEATURE_IDE0_enable);
-				mdelay(10);
-				feature_clear(np, FEATURE_IDE0_reset);
-				break;
-			    case 1:
-				feature_set(np, FEATURE_IDE1_reset);
-				mdelay(10);
- 				feature_set(np, FEATURE_IDE1_enable);
-				mdelay(10);
-				feature_clear(np, FEATURE_IDE1_reset);
-				break;
-			    case 2:
-			    	/* This one exists only for KL, I don't know
-				   about any enable bit */
-				feature_set(np, FEATURE_IDE2_reset);
-				mdelay(10);
-				feature_clear(np, FEATURE_IDE2_reset);
-				break;
-			}
+				pmif->aapl_bus_id);
+			ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
+			ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
+			mdelay(10);
+			ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 0);
 			big_delay = 1;
 		}
 
@@ -643,13 +960,15 @@
 		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->chipset = ide_pmac;
 		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay;
+		hwif->udma_four = (pmif->kind == controller_kl_ata4_80);
+		hwif->pci_dev = pdev;
 #ifdef CONFIG_PMAC_PBOOK
 		if (in_bay && check_media_bay_by_base(base, MB_CD) == 0)
 			hwif->noprobe = 0;
 #endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-		if (np->n_addrs >= 2) {
+		if (pdev && np->n_addrs >= 2) {
 			/* has a DBDMA controller channel */
 			pmac_ide_setup_dma(np, i);
 		}
@@ -671,7 +990,15 @@
 static void __init 
 pmac_ide_setup_dma(struct device_node *np, int ix)
 {
-	pmac_ide[ix].dma_regs =
+	struct pmac_ide_hwif *pmif = &pmac_ide[ix];
+
+	if (request_OF_resource(np, 1, " (mac-io IDE DMA)") == NULL) {
+		printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n",
+			np->name);
+		return;
+	}
+
+	pmif->dma_regs =
 		(volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);
 
 	/*
@@ -679,14 +1006,24 @@
 	 * The +2 is +1 for the stop command and +1 to allow for
 	 * aligning the start address to a multiple of 16 bytes.
 	 */
-	pmac_ide[ix].dma_table = (struct dbdma_cmd*)
-	       kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);
-	if (pmac_ide[ix].dma_table == 0) {
+	pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
+		ide_hwifs[ix].pci_dev,
+		(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
+		&pmif->dma_table_dma);
+	if (pmif->dma_table_cpu == NULL) {
 		printk(KERN_ERR "%s: unable to allocate DMA command list\n",
 		       ide_hwifs[ix].name);
 		return;
 	}
 
+	pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS,
+				 GFP_KERNEL);
+	if (pmif->sg_table == NULL) {
+		pci_free_consistent(	ide_hwifs[ix].pci_dev,
+					(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
+				    	pmif->dma_table_cpu, pmif->dma_table_dma);
+		return;
+	}
 	ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
 	if (!noautodma)
@@ -694,6 +1031,62 @@
 #endif
 }
 
+static int
+pmac_ide_build_sglist (int ix, struct request *rq)
+{
+	struct ata_channel *hwif = &ide_hwifs[ix];
+	struct pmac_ide_hwif *pmif = &pmac_ide[ix];
+	request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
+	struct scatterlist *sg = pmif->sg_table;
+	int nents;
+
+	nents = blk_rq_map_sg(q, rq, pmif->sg_table);
+
+	if (rq->q && nents > rq->nr_phys_segments)
+		printk("ide-pmac: received %d phys segments, build %d\n", rq->nr_phys_segments, nents);
+
+	if (rq_data_dir(rq) == READ)
+		pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+	else
+		pmif->sg_dma_direction = PCI_DMA_TODEVICE;
+
+	return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
+}
+
+static int
+pmac_raw_build_sglist (int ix, struct request *rq)
+{
+	struct ata_channel *hwif = &ide_hwifs[ix];
+	struct pmac_ide_hwif *pmif = &pmac_ide[ix];
+	struct scatterlist *sg = pmif->sg_table;
+	int nents = 0;
+	struct ata_taskfile *args = rq->special;
+	unsigned char *virt_addr = rq->buffer;
+	int sector_count = rq->nr_sectors;
+
+	if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
+		pmif->sg_dma_direction = PCI_DMA_TODEVICE;
+	else
+		pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+
+	if (sector_count > 128) {
+		memset(&sg[nents], 0, sizeof(*sg));
+		sg[nents].page = virt_to_page(virt_addr);
+		sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
+		sg[nents].length = 128  * SECTOR_SIZE;
+		nents++;
+		virt_addr = virt_addr + (128 * SECTOR_SIZE);
+		sector_count -= 128;
+	}
+	memset(&sg[nents], 0, sizeof(*sg));
+	sg[nents].page = virt_to_page(virt_addr);
+	sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK;
+	sg[nents].length =  sector_count  * SECTOR_SIZE;
+	nents++;
+
+	return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
+}
+
 /*
  * pmac_ide_build_dmatable builds the DBDMA command list
  * for a transfer and sets the DBDMA channel to point to it.
@@ -701,47 +1094,40 @@
 static int
 pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr)
 {
-	struct dbdma_cmd *table, *tstart;
-	int count = 0;
+	struct dbdma_cmd *table;
+	int i, count = 0;
 	struct request *rq = HWGROUP(drive)->rq;
-	struct buffer_head *bh = rq->bh;
-	unsigned int size, addr;
 	volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;
+	struct scatterlist *sg;
 
-	table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table);
+	/* DMA table is already aligned */
+	table = (struct dbdma_cmd *) pmac_ide[ix].dma_table_cpu;
+
+	/* Make sure DMA controller is stopped (necessary ?) */
 	out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
 	while (in_le32(&dma->status) & RUN)
 		udelay(1);
 
-	do {
-		/*
-		 * Determine addr and size of next buffer area.  We assume that
-		 * individual virtual buffers are always composed linearly in
-		 * physical memory.  For example, we assume that any 8kB buffer
-		 * is always composed of two adjacent physical 4kB pages rather
-		 * than two possibly non-adjacent physical 4kB pages.
-		 */
-		if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
-			addr = virt_to_bus(rq->buffer);
-			size = rq->nr_sectors << 9;
-		} else {
-			/* group sequential buffers into one large buffer */
-			addr = virt_to_bus(bh->b_data);
-			size = bh->b_size;
-			while ((bh = bh->b_reqnext) != NULL) {
-				if ((addr + size) != virt_to_bus(bh->b_data))
-					break;
-				size += bh->b_size;
-			}
-		}
+	/* Build sglist */
+	if (rq->flags & REQ_DRIVE_TASKFILE) {
+		pmac_ide[ix].sg_nents = i = pmac_raw_build_sglist(ix, rq);
+	} else {
+		pmac_ide[ix].sg_nents = i = pmac_ide_build_sglist(ix, rq);
+	}
+	if (!i)
+		return 0;
 
-		/*
-		 * Fill in the next DBDMA command block.
-		 * Note that one DBDMA command can transfer
-		 * at most 65535 bytes.
-		 */
-		while (size) {
-			unsigned int tc = (size < 0xfe00)? size: 0xfe00;
+	/* Build DBDMA commands list */
+	sg = pmac_ide[ix].sg_table;
+	while (i) {
+		u32 cur_addr;
+		u32 cur_len;
+
+		cur_addr = sg_dma_address(sg);
+		cur_len = sg_dma_len(sg);
+
+		while (cur_len) {
+			unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00;
 
 			if (++count >= MAX_DCMDS) {
 				printk(KERN_WARNING "%s: DMA table too small\n",
@@ -750,15 +1136,17 @@
 			}
 			st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);
 			st_le16(&table->req_count, tc);
-			st_le32(&table->phy_addr, addr);
+			st_le32(&table->phy_addr, cur_addr);
 			table->cmd_dep = 0;
 			table->xfer_status = 0;
 			table->res_count = 0;
-			addr += tc;
-			size -= tc;
+			cur_addr += tc;
+			cur_len -= tc;
 			++table;
 		}
-	} while (bh != NULL);
+		sg++;
+		i--;
+	}
 
 	/* convert the last command to an input/output last command */
 	if (count)
@@ -770,10 +1158,24 @@
 	memset(table, 0, sizeof(struct dbdma_cmd));
 	out_le16(&table->command, DBDMA_STOP);
 
-	out_le32(&dma->cmdptr, virt_to_bus(tstart));
+	out_le32(&dma->cmdptr, pmac_ide[ix].dma_table_dma);
 	return 1;
 }
 
+/* Teardown mappings after DMA has completed.  */
+static void
+pmac_ide_destroy_dmatable (ide_drive_t *drive, int ix)
+{
+	struct pci_dev *dev = HWIF(drive)->pci_dev;
+	struct scatterlist *sg = pmac_ide[ix].sg_table;
+	int nents = pmac_ide[ix].sg_nents;
+
+	if (nents) {
+		pci_unmap_sg(dev, sg, nents, pmac_ide[ix].sg_dma_direction);
+		pmac_ide[ix].sg_nents = 0;
+	}
+}
+
 
 static __inline__ unsigned char
 dma_bits_to_command(unsigned char bits)
@@ -788,12 +1190,14 @@
 }
 
 static __inline__ unsigned char
-udma_bits_to_command(unsigned char bits)
+udma_bits_to_command(unsigned char bits, int high_speed)
 {
-	if(bits & 0x10)
-		return XFER_UDMA_4;
-	if(bits & 0x08)
-		return XFER_UDMA_3;
+	if (high_speed) {
+		if(bits & 0x10)
+			return XFER_UDMA_4;
+		if(bits & 0x08)
+			return XFER_UDMA_3;
+	}
 	if(bits & 0x04)
 		return XFER_UDMA_2;
 	if(bits & 0x02)
@@ -804,14 +1208,13 @@
 }
 
 /* Calculate MultiWord DMA timings */
-static int
+static int __pmac
 pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
 {
 	byte bits = drive->id->dma_mword & 0x07;
 	byte feature = dma_bits_to_command(bits);
 	u32 *timings;
-	int cycleTime, accessTime;
-	int accessTicks, recTicks;
+	int drive_cycle_time;
 	struct hd_driveid *id = drive->id;
 	int ret;
 
@@ -827,66 +1230,30 @@
 		drive->init_speed = feature;
 	
 	/* which drive is it ? */
-	if (drive->select.all & 0x10)
+	if (drive->select.b.unit & 0x01)
 		timings = &pmac_ide[idx].timings[1];
 	else
 		timings = &pmac_ide[idx].timings[0];
 
-	/* Calculate accesstime and cycle time */
-	cycleTime = mdma_timings[feature & 0xf].cycleTime;
-	accessTime = mdma_timings[feature & 0xf].accessTime;
+	/* Check if drive provide explicit cycle time */
 	if ((id->field_valid & 2) && (id->eide_dma_time))
-		cycleTime = id->eide_dma_time;
-	if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))
-		cycleTime = 150;
+		drive_cycle_time = id->eide_dma_time;
+	else
+		drive_cycle_time = 0;
+
+	/* Calculate controller timings */
+	set_timings_mdma(pmac_ide[idx].kind, timings, feature, drive_cycle_time);
 
-	/* For ata-4 controller */
-	if (pmac_ide[idx].kind == controller_kl_ata4) {
-		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
-		*timings = ((*timings) & 0xffe003ff) |
-			(accessTicks | (recTicks << 5)) << 10;
-	} else {
-		int halfTick = 0;
-		int origAccessTime = accessTime;
-		int origCycleTime = cycleTime;
-		
-		accessTicks = SYSCLK_TICKS(accessTime);
-		if (accessTicks < 1)
-			accessTicks = 1;
-		accessTime = accessTicks * IDE_SYSCLK_NS;
-		recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
-		if (recTicks < 1)
-			recTicks = 1;
-		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
-
-		/* KeyLargo ata-3 don't support the half-tick stuff */
-		if ((pmac_ide[idx].kind != controller_kl_ata3) &&
-			(accessTicks > 1) &&
-			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
-			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
-            			halfTick    = 1;
-				accessTicks--;
-		}
-		*timings = ((*timings) & 0x7FF) |
-			(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
-	}
-#ifdef IDE_PMAC_DEBUG
-	printk(KERN_INFO "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
-		feature & 0xf, *timings);
-#endif
 	drive->current_speed = feature;	
 	return 1;
 }
 
 /* Calculate Ultra DMA timings */
-static int
-pmac_ide_udma_enable(ide_drive_t *drive, int idx)
+static int __pmac
+pmac_ide_udma_enable(ide_drive_t *drive, int idx, int high_speed)
 {
 	byte bits = drive->id->dma_ultra & 0x1f;
-	byte feature = udma_bits_to_command(bits);
-	int cycleTime, accessTime;
-	int rdyToPauseTicks, cycleTicks;
+	byte feature = udma_bits_to_command(bits, high_speed);
 	u32 *timings;
 	int ret;
 
@@ -902,25 +1269,18 @@
 		drive->init_speed = feature;
 
 	/* which drive is it ? */
-	if (drive->select.all & 0x10)
+	if (drive->select.b.unit & 0x01)
 		timings = &pmac_ide[idx].timings[1];
 	else
 		timings = &pmac_ide[idx].timings[0];
 
-	cycleTime = udma_timings[feature & 0xf].cycleTime;
-	accessTime = udma_timings[feature & 0xf].accessTime;
-
-	rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
-	cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
-
-	*timings = ((*timings) & 0xe00fffff) |
-			((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+	set_timings_udma(timings, feature);
 
 	drive->current_speed = feature;	
 	return 1;
 }
 
-static int
+static int __pmac
 pmac_ide_check_dma(ide_drive_t *drive)
 {
 	int ata4, udma, idx;
@@ -928,12 +1288,12 @@
 	int enable = 1;
 
 	drive->using_dma = 0;
-	
+
 	idx = pmac_ide_find(drive);
 	if (idx < 0)
 		return 0;
-		
-	if (drive->media == ide_floppy)
+
+	if (drive->type == ATA_FLOPPY)
 		enable = 0;
 	if (((id->capability & 1) == 0) && !check_drive_lists(drive, GOOD_DMA_DRIVE))
 		enable = 0;
@@ -941,21 +1301,20 @@
 		enable = 0;
 
 	udma = 0;
-	ata4 = (pmac_ide[idx].kind == controller_kl_ata4);
-			
+	ata4 = (pmac_ide[idx].kind == controller_kl_ata4 ||
+		pmac_ide[idx].kind == controller_kl_ata4_80);
+
 	if(enable) {
-		if (ata4 && (drive->media == ide_disk) &&
-		    (id->field_valid & 0x0004) && (id->dma_ultra & 0x17)) {
+		if (ata4 && (drive->type == ATA_DISK) &&
+		    (id->field_valid & 0x0004) && (id->dma_ultra & 0x1f)) {
 			/* UltraDMA modes. */
-			drive->using_dma = pmac_ide_udma_enable(drive, idx);
+			drive->using_dma = pmac_ide_udma_enable(drive, idx,
+				pmac_ide[idx].kind == controller_kl_ata4_80);
 		}
 		if (!drive->using_dma && (id->dma_mword & 0x0007)) {
 			/* Normal MultiWord DMA modes. */
 			drive->using_dma = pmac_ide_mdma_enable(drive, idx);
 		}
-		/* Without this, strange things will happen on Keylargo-based
-		 * machines
-		 */
 		OUT_BYTE(0, IDE_CONTROL_REG);
 		/* Apply settings to controller */
 		pmac_ide_selectproc(drive);
@@ -963,11 +1322,26 @@
 	return 0;
 }
 
+static void ide_toggle_bounce(ide_drive_t *drive, int on)
+{
+	dma64_addr_t addr = BLK_BOUNCE_HIGH;
+
+	if (on && drive->type == ATA_DISK && HWIF(drive)->highmem) {
+		if (!PCI_DMA_BUS_IS_PHYS)
+			addr = BLK_BOUNCE_ANY;
+		else
+			addr = HWIF(drive)->pci_dev->dma_mask;
+	}
+
+	blk_queue_bounce_limit(&drive->queue, addr);
+}
+
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	int ix, dstat, i;
+	int ix, dstat, reading, ata4;
 	volatile struct dbdma_regs *dma;
-
+	byte unit = (drive->select.b.unit & 0x01);
+	
 	/* Can we stuff a pointer to our intf structure in config_data
 	 * or select_data in hwif ?
 	 */
@@ -975,58 +1349,106 @@
 	if (ix < 0)
 		return 0;		
 	dma = pmac_ide[ix].dma_regs;
-
+	ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
+		pmac_ide[ix].kind == controller_kl_ata4_80);
+	
 	switch (func) {
 	case ide_dma_off:
 		printk(KERN_INFO "%s: DMA disabled\n", drive->name);
 	case ide_dma_off_quietly:
 		drive->using_dma = 0;
+		ide_toggle_bounce(drive, 0);
 		break;
 	case ide_dma_on:
 	case ide_dma_check:
+		/* Change this to better match ide-dma.c */
 		pmac_ide_check_dma(drive);
+		ide_toggle_bounce(drive, drive->using_dma);
 		break;
 	case ide_dma_read:
 	case ide_dma_write:
-		if (!pmac_ide_build_dmatable(drive, ix, func==ide_dma_write))
+		/* this almost certainly isn't needed since we don't
+		   appear to have a rwproc */
+		if (HWIF(drive)->rwproc)
+			HWIF(drive)->rwproc(drive, func);
+		reading = (func == ide_dma_read);
+		if (!pmac_ide_build_dmatable(drive, ix, !reading))
 			return 1;
+		/* Apple adds 60ns to wrDataSetup on reads */
+		if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) {
+			out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
+				pmac_ide[ix].timings[unit] + 
+				((func == ide_dma_read) ? 0x00800000UL : 0));
+			(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
+		}
 		drive->waiting_for_dma = 1;
-		if (drive->media != ide_disk)
+		if (drive->type != ATA_DISK)
 			return 0;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
-		OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA,
-			 IDE_COMMAND_REG);
+		if ((HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) &&
+		    (drive->addressing == 1)) {
+			struct ata_taskfile *args = HWGROUP(drive)->rq->special;
+			OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
+		} else if (drive->addressing) {
+			OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
+		} else {
+			OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
+		}
+		/* fall through */
 	case ide_dma_begin:
 		out_le32(&dma->control, (RUN << 16) | RUN);
+		/* Make sure it gets to the controller right now */
+		(void)in_le32(&dma->control);
 		break;
-	case ide_dma_end:
+	case ide_dma_end: /* returns 1 on error, 0 otherwise */
 		drive->waiting_for_dma = 0;
 		dstat = in_le32(&dma->status);
 		out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
+		pmac_ide_destroy_dmatable(drive, ix);
 		/* verify good dma status */
 		return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
-	case ide_dma_test_irq:
-		if ((in_le32(&dma->status) & (RUN|ACTIVE)) == RUN)
-			return 1;
-		/* That's a bit ugly and dangerous, but works in our case
-		 * to workaround a problem with the channel status staying
-		 * active if the drive returns an error
+	case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+		/* We have to things to deal with here:
+		 * 
+		 * - The dbdma won't stop if the command was started
+		 * but completed with an error without transfering all
+		 * datas. This happens when bad blocks are met during
+		 * a multi-block transfer.
+		 * 
+		 * - The dbdma fifo hasn't yet finished flushing to
+		 * to system memory when the disk interrupt occurs.
+		 * 
+		 * The trick here is to increment drive->waiting_for_dma,
+		 * and return as if no interrupt occured. If the counter
+		 * reach a certain timeout value, we then return 1. If
+		 * we really got the interrupt, it will happen right away
+		 * again.
+		 * Apple's solution here may be more elegant. They issue
+		 * a DMA channel interrupt (a separate irq line) via a DBDMA
+		 * NOP command just before the STOP, and wait for both the
+		 * disk and DBDMA interrupts to have completed.
 		 */
-		if (IDE_CONTROL_REG) {
-			byte stat;
-			stat = GET_ALTSTAT();
-			if (stat & ERR_STAT)
-				return 1;
-		}
-		/* In some edge cases, some datas may still be in the dbdma
-		 * engine fifo, we wait a bit for dbdma to complete
+		 
+		/* If ACTIVE is cleared, the STOP command have passed and
+		 * transfer is complete.
 		 */
-		while ((in_le32(&dma->status) & (RUN|ACTIVE)) != RUN) {
-			if (++i > 100)
-				return 0;
-			udelay(1);
+		if (!(in_le32(&dma->status) & ACTIVE))
+			return 1;
+		if (!drive->waiting_for_dma)
+			printk(KERN_WARNING "ide%d, ide_dma_test_irq \
+				called while not waiting\n", ix);
+
+		/* If dbdma didn't execute the STOP command yet, the
+		 * active bit is still set */
+		drive->waiting_for_dma++;
+		if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
+			printk(KERN_WARNING "ide%d, timeout waiting \
+				for dbdma command stop\n", ix);
+			return 1;
 		}
-		return 1;
+		udelay(1);
+		return 0;
 
 		/* Let's implement tose just in case someone wants them */
 	case ide_dma_bad_drive:
@@ -1037,34 +1459,35 @@
 	case ide_dma_retune:
 	case ide_dma_lostirq:
 	case ide_dma_timeout:
-		printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);
+		printk(KERN_WARNING "ide_pmac_dmaproc: chipset supported func only: %d\n", func);
 		return 1;
 	default:
-		printk(KERN_WARNING "ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
+		printk(KERN_WARNING "ide_pmac_dmaproc: unsupported func: %d\n", func);
 		return 1;
 	}
 	return 0;
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
-#ifdef CONFIG_PMAC_PBOOK
 static void idepmac_sleep_device(ide_drive_t *drive, int i, unsigned base)
 {
 	int j;
-	
+
 	/* FIXME: We only handle the master IDE disk, we shoud
 	 *        try to fix CD-ROMs here
 	 */
-	switch (drive->media) {
-	case ide_disk:
+	switch (drive->type) {
+	case ATA_DISK:
 		/* Spin down the drive */
-		outb(0xa0, base+0x60);
+		outb(drive->select.all, base+0x60);
+		(void)inb(base+0x60);
+		udelay(100);
 		outb(0x0, base+0x30);
 		outb(0x0, base+0x20);
 		outb(0x0, base+0x40);
 		outb(0x0, base+0x50);
 		outb(0xe0, base+0x70);
-		outb(0x2, base+0x160);   
+		outb(0x2, base+0x160);
 		for (j = 0; j < 10; j++) {
 			int status;
 			mdelay(100);
@@ -1073,28 +1496,30 @@
 				break;
 		}
 		break;
-	case ide_cdrom:
+	case ATA_ROM:
 		// todo
 		break;
-	case ide_floppy:
+	case ATA_FLOPPY:
 		// todo
 		break;
 	}
 }
 
-static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
- {
+#ifdef CONFIG_PMAC_PBOOK
+static void __pmac
+idepmac_wake_device(ide_drive_t *drive, int used_dma)
+{
 	/* We force the IDE subdriver to check for a media change
 	 * This must be done first or we may lost the condition
 	 *
 	 * Problem: This can schedule. I moved the block device
 	 * wakeup almost late by priority because of that.
 	 */
-	if (DRIVER(drive) && DRIVER(drive)->media_change)
-		DRIVER(drive)->media_change(drive);
+	if (drive->driver != NULL && ata_ops(drive)->check_media_change)
+		ata_ops(drive)->check_media_change(drive);
 
 	/* We kick the VFS too (see fix in ide.c revalidate) */
-	check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS));
+	check_disk_change(mk_kdev(drive->channel->major, (drive->select.b.unit) << PARTN_BITS));
 	
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 	/* We re-enable DMA on the drive if it was active. */
@@ -1104,15 +1529,16 @@
 	 */
 	if (used_dma && !ide_spin_wait_hwgroup(drive)) {
 		/* Lock HW group */
-		HWGROUP(drive)->busy = 1;
+		set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
 		pmac_ide_check_dma(drive);
-		HWGROUP(drive)->busy = 0;
+		clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
 		spin_unlock_irq(&ide_lock);
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 }
 
-static void idepmac_sleep_interface(int i, unsigned base, int mediabay)
+static void __pmac
+idepmac_sleep_interface(int i, unsigned base, int mediabay)
 {
 	struct device_node* np = pmac_ide[i].node;
 
@@ -1124,73 +1550,81 @@
 	if (mediabay)
 		return;
 	
-	/* Disable and reset the bus */
-	feature_set(np, FEATURE_IDE0_reset);
-	feature_clear(np, FEATURE_IDE0_enable);
-	switch(pmac_ide[i].aapl_bus_id) {
-	    case 0:
-		feature_set(np, FEATURE_IDE0_reset);
-		feature_clear(np, FEATURE_IDE0_enable);
-		break;
-	    case 1:
-		feature_set(np, FEATURE_IDE1_reset);
-		feature_clear(np, FEATURE_IDE1_enable);
-		break;
-	    case 2:
-		feature_set(np, FEATURE_IDE2_reset);
-		break;
-	}
+	/* Disable the bus */
+	ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 0);
 }
 
-static void idepmac_wake_interface(int i, unsigned long base, int mediabay)
+static void __pmac
+idepmac_wake_interface(int i, unsigned long base, int mediabay)
 {
 	struct device_node* np = pmac_ide[i].node;
 
 	if (!mediabay) {
 		/* Revive IDE disk and controller */
-		switch(pmac_ide[i].aapl_bus_id) {
-		    case 0:
-			feature_set(np, FEATURE_IDE0_reset);
-			feature_set(np, FEATURE_IOBUS_enable);
-			mdelay(10);
-	 		feature_set(np, FEATURE_IDE0_enable);
-			mdelay(10);
-			feature_clear(np, FEATURE_IDE0_reset);
-			break;
-		    case 1:
-			feature_set(np, FEATURE_IDE1_reset);
-			feature_set(np, FEATURE_IOBUS_enable);
-			mdelay(10);
-	 		feature_set(np, FEATURE_IDE1_enable);
-			mdelay(10);
-			feature_clear(np, FEATURE_IDE1_reset);
-			break;
-		    case 2:
-		    	/* This one exists only for KL, I don't know
-			   about any enable bit */
-			feature_set(np, FEATURE_IDE2_reset);
-			mdelay(10);
-			feature_clear(np, FEATURE_IDE2_reset);
-			break;
-		}
+		ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 1);
+		ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmac_ide[i].aapl_bus_id, 1);
+		mdelay(10);
+		ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmac_ide[i].aapl_bus_id, 0);
 	}
+}
+
+static void
+idepmac_sleep_drive(ide_drive_t *drive, int idx, unsigned long base)
+{
+	/* Wait for HW group to complete operations */
+	if (ide_spin_wait_hwgroup(drive))
+		// What can we do here ? Wake drive we had already
+		// put to sleep and return an error ?
+		return;
+	else {
+		/* Lock HW group */
+		set_bit(IDE_BUSY, &HWGROUP(drive)->flags);
+		/* Stop the device */
+		idepmac_sleep_device(drive, idx, base);
+		spin_unlock_irq(&ide_lock);
+	}
+}
+
+static void
+idepmac_wake_drive(ide_drive_t *drive, unsigned long base)
+{
+	int j;
 	
 	/* Reset timings */
-	pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
+	pmac_ide_selectproc(drive);
 	mdelay(10);
+	
+	/* Wait up to 20 seconds for the drive to be ready */
+	for (j = 0; j < 200; j++) {
+		int status;
+		mdelay(100);
+		outb(drive->select.all, base + 0x60);
+		if (inb(base + 0x60) != drive->select.all)
+			continue;
+		status = inb(base + 0x70);
+		if (!(status & BUSY_STAT))
+			break;
+	}
+
+	/* We resume processing on the HW group */
+	spin_lock_irq(&ide_lock);
+	clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
+	if (!list_empty(&drive->queue.queue_head))
+		do_ide_request(&drive->queue);
+	spin_unlock_irq(&ide_lock);
 }
 
 /* Note: We support only master drives for now. This will have to be
  * improved if we want to handle sleep on the iMacDV where the CD-ROM
  * is a slave
  */
-static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
+static int __pmac
+idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	int i, ret;
 	unsigned long base;
-	unsigned long flags;
 	int big_delay;
-
+ 
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 		break;
@@ -1198,35 +1632,20 @@
 		break;
 	case PBOOK_SLEEP_NOW:
 		for (i = 0; i < pmac_ide_count; ++i) {
-			ide_hwif_t *hwif;
-			ide_drive_t *drive;
-			int unlock = 0;
+			struct ata_channel *hwif;
+			int dn;
 
 			if ((base = pmac_ide[i].regbase) == 0)
-				continue;	
+				continue;
 
 			hwif = &ide_hwifs[i];
-			drive = &hwif->drives[0];
-			
-			if (drive->present) {
-				/* Wait for HW group to complete operations */
-				if (ide_spin_wait_hwgroup(drive)) {
-					// What can we do here ? Wake drive we had already
-					// put to sleep and return an error ?
-				} else {
-					unlock = 1;
-					/* Lock HW group */
-					HWGROUP(drive)->busy = 1;
-
-					/* Stop the device */
-					idepmac_sleep_device(drive, i, base);
-				
-				}
+			for (dn=0; dn<MAX_DRIVES; dn++) {
+				if (!hwif->drives[dn].present)
+					continue;
+				idepmac_sleep_drive(&hwif->drives[dn], i, base);
 			}
 			/* Disable irq during sleep */
 			disable_irq(pmac_ide[i].irq);
-			if (unlock)
-				spin_unlock_irq(&ide_lock);
 			
 			/* Check if this is a media bay with an IDE device or not
 			 * a media bay.
@@ -1243,6 +1662,9 @@
 			if ((base = pmac_ide[i].regbase) == 0)
 				continue;
 				
+			/* Make sure we have sane timings */		
+			sanitize_timings(i);
+
 			/* Check if this is a media bay with an IDE device or not
 			 * a media bay
 			 */
@@ -1258,44 +1680,30 @@
 			mdelay(IDE_WAKEUP_DELAY_MS);
 	
 		for (i = 0; i < pmac_ide_count; ++i) {
-			ide_hwif_t *hwif;
-			ide_drive_t *drive;			
-			int j, used_dma;
+			struct ata_channel *hwif;
+			int used_dma, dn;
+			int irq_on = 0;
 			
 			if ((base = pmac_ide[i].regbase) == 0)
 				continue;
 				
 			hwif = &ide_hwifs[i];
-			drive = &hwif->drives[0];
-
-			/* Wait for the drive to come up and set it's DMA */
-			if (drive->present) {
-				/* Wait up to 20 seconds */
-				for (j = 0; j < 200; j++) {
-					int status;
-					mdelay(100);
-					status = inb(base + 0x70);
-					if (!(status & BUSY_STAT))
-						break;
+			for (dn=0; dn<MAX_DRIVES; dn++) {
+				ide_drive_t *drive = &hwif->drives[dn];
+				if (!drive->present)
+					continue;
+				/* We don't have re-configured DMA yet */
+				used_dma = drive->using_dma;
+				drive->using_dma = 0;
+				idepmac_wake_drive(drive, base);
+				if (!irq_on) {
+					enable_irq(pmac_ide[i].irq);
+					irq_on = 1;
 				}
-			}
-			
-			/* We don't have re-configured DMA yet */
-			used_dma = drive->using_dma;
-			drive->using_dma = 0;
-
-			/* We resume processing on the HW group */
-			spin_lock_irqsave(&ide_lock, flags);
-			enable_irq(pmac_ide[i].irq);
-			if (drive->present)
-				HWGROUP(drive)->busy = 0;
-			spin_unlock_irqrestore(&ide_lock, flags);
-			
-			/* Wake the device
-			 * We could handle the slave here
-			 */
-			if (drive->present)
 				idepmac_wake_device(drive, used_dma);
+			}
+			if (!irq_on)
+				enable_irq(pmac_ide[i].irq);
 		}
 		break;
 	}
diff -Nru a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
--- a/drivers/ide/ide-pnp.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/ide-pnp.c	Sun Apr 14 12:16:57 2002
@@ -13,9 +13,10 @@
  *
  * You should have received a copy of the GNU General Public License
  * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/types.h>
 #include <linux/ide.h>
 #include <linux/init.h>
 
@@ -57,7 +58,7 @@
 static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
 {
 	hw_regs_t hw;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	int index;
 
 	if (!enable)
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/ide/ide-probe.c	Sun Apr 14 12:16:54 2002
@@ -118,7 +118,7 @@
 		byte type = (id->config >> 8) & 0x1f;
 		printk("ATAPI ");
 #ifdef CONFIG_BLK_DEV_PDC4030
-		if (HWIF(drive)->channel == 1 && HWIF(drive)->chipset == ide_pdc4030) {
+		if (drive->channel->unit == 1 && drive->channel->chipset == ide_pdc4030) {
 			printk(" -- not supported on 2nd Promise port\n");
 			goto err_misc;
 		}
@@ -140,7 +140,7 @@
 				/* kludge for Apple PowerBook internal zip */
 				if (!strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) {
 					printk ("FLOPPY");
-					type = ide_floppy;
+					type = ATA_FLOPPY;
 					break;
 				}
 #endif
@@ -167,12 +167,16 @@
 	 */
 	if (id->config & (1<<7))
 		drive->removable = 1;
+
 	/*
-	 * Prevent long system lockup probing later for non-existant
-	 * slave drive if the hwif is actually a flash memory card of some variety:
+	 * FIXME: This is just plain ugly or plain unnecessary.
+	 *
+	 * Prevent long system lockup probing later for non-existant slave
+	 * drive if the hwif is actually a flash memory card of some variety:
 	 */
+
 	if (drive_is_flashcard(drive)) {
-		ide_drive_t *mate = &HWIF(drive)->drives[1^drive->select.b.unit];
+		ide_drive_t *mate = &drive->channel->drives[1 ^ drive->select.b.unit];
 		if (!mate->ata_flash) {
 			mate->present = 0;
 			mate->noprobe = 1;
@@ -182,8 +186,26 @@
 	printk("ATA DISK drive\n");
 
 	/* Initialize our quirk list. */
-	if (HWIF(drive)->quirkproc)
-		drive->quirk_list = HWIF(drive)->quirkproc(drive);
+	if (drive->channel->quirkproc)
+		drive->quirk_list = drive->channel->quirkproc(drive);
+
+	/*
+	 * it's an ata drive, build command list
+	 */
+#ifndef CONFIG_BLK_DEV_IDE_TCQ
+	drive->queue_depth = 1;
+#else
+# ifndef CONFIG_BLK_DEV_IDE_TCQ_DEPTH
+#  define CONFIG_BLK_DEV_IDE_TCQ_DEPTH 1
+# endif
+	drive->queue_depth = drive->id->queue_depth + 1;
+	if (drive->queue_depth > CONFIG_BLK_DEV_IDE_TCQ_DEPTH)
+		drive->queue_depth = CONFIG_BLK_DEV_IDE_TCQ_DEPTH;
+	if (drive->queue_depth < 1 || drive->queue_depth > IDE_MAX_TAG)
+		drive->queue_depth = IDE_MAX_TAG;
+#endif
+	if (ide_build_commandlist(drive))
+		goto err_misc;
 
 	return;
 
@@ -232,7 +254,7 @@
 		OUT_BYTE(0,IDE_FEATURE_REG);	/* disable dma & overlap */
 
 #if CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030) {
+	if (drive->channel->chipset == ide_pdc4030) {
 		/* DC4030 hosted drives need their own identify... */
 		extern int pdc4030_identify(ide_drive_t *);
 		if (pdc4030_identify(drive)) {
@@ -270,7 +292,7 @@
 	int autoprobe = 0;
 	unsigned long cookie = 0;
 
-	if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
+	if (IDE_CONTROL_REG && !drive->channel->irq) {
 		autoprobe = 1;
 		cookie = probe_irq_on();
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
@@ -284,9 +306,9 @@
 		GET_STAT();			/* clear drive IRQ */
 		udelay(5);
 		irq = probe_irq_off(cookie);
-		if (!HWIF(drive)->irq) {
+		if (!drive->channel->irq) {
 			if (irq > 0)
-				HWIF(drive)->irq = irq;
+				drive->channel->irq = irq;
 			else	/* Mmmm.. multiple IRQs.. don't know which was ours */
 				printk("%s: IRQ probe failed (0x%lx)\n", drive->name, cookie);
 		}
@@ -314,7 +336,7 @@
 static int do_probe (ide_drive_t *drive, byte cmd)
 {
 	int rc;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	if (drive->present) {	/* avoid waiting for inappropriate probes */
 		if ((drive->type != ATA_DISK) && (cmd == WIN_IDENTIFY))
 			return 4;
@@ -369,12 +391,12 @@
 /*
  *
  */
-static void enable_nest (ide_drive_t *drive)
+static void enable_nest(ide_drive_t *drive)
 {
 	unsigned long timeout;
 
-	printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model);
-	SELECT_DRIVE(HWIF(drive), drive);
+	printk("%s: enabling %s -- ", drive->channel->name, drive->id->model);
+	SELECT_DRIVE(drive->channel, drive);
 	ide_delay_50ms();
 	OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
 	timeout = jiffies + WAIT_WORSTCASE;
@@ -427,7 +449,7 @@
  * ordered sanely.  We deal with the CONTROL register
  * separately.
  */
-static int hwif_check_regions (ide_hwif_t *hwif)
+static int hwif_check_regions(struct ata_channel *hwif)
 {
 	int region_errors = 0;
 
@@ -453,20 +475,20 @@
 	return(region_errors);
 }
 
-static void hwif_register (ide_hwif_t *hwif)
+static void hwif_register(struct ata_channel *hwif)
 {
 	/* Register this hardware interface within the global device tree.
 	 */
-	sprintf(hwif->device.bus_id, "%04x", hwif->io_ports[IDE_DATA_OFFSET]);
-	sprintf(hwif->device.name, "ide");
-	hwif->device.driver_data = hwif;
+	sprintf(hwif->dev.bus_id, "%04x", hwif->io_ports[IDE_DATA_OFFSET]);
+	sprintf(hwif->dev.name, "ide");
+	hwif->dev.driver_data = hwif;
 #ifdef CONFIG_BLK_DEV_IDEPCI
 	if (hwif->pci_dev)
-		hwif->device.parent = &hwif->pci_dev->dev;
+		hwif->dev.parent = &hwif->pci_dev->dev;
 	else
 #endif
-		hwif->device.parent = NULL; /* Would like to do = &device_legacy */
-	device_register(&hwif->device);
+		hwif->dev.parent = NULL; /* Would like to do = &device_legacy */
+	device_register(&hwif->dev);
 
 	if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
 	    ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) {
@@ -503,7 +525,7 @@
  * This routine only knows how to look for drive units 0 and 1
  * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
  */
-static void probe_hwif (ide_hwif_t *hwif)
+static void probe_hwif(struct ata_channel *hwif)
 {
 	unsigned int unit;
 	unsigned long flags;
@@ -513,7 +535,7 @@
 
 	if (
 #if CONFIG_BLK_DEV_PDC4030
-	    (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
+	    (hwif->chipset != ide_pdc4030 || hwif->unit == 0) &&
 #endif
 	    hwif_check_regions(hwif)) {
 		int msgout = 0;
@@ -562,7 +584,7 @@
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t *drive = &hwif->drives[unit];
 		if (drive->present) {
-			ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
+			ide_tuneproc_t *tuneproc = drive->channel->tuneproc;
 			if (tuneproc != NULL && drive->autotune == 1)
 				tuneproc(drive, 255);	/* auto-tune PIO mode */
 		}
@@ -583,16 +605,16 @@
 
 	/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030)
+	if (drive->channel->chipset == ide_pdc4030)
 		max_sectors = 127;
 #endif
 	blk_queue_max_sectors(q, max_sectors);
 
 	/* IDE DMA can do PRD_ENTRIES number of segments. */
-	blk_queue_max_hw_segments(q, PRD_ENTRIES);
+	blk_queue_max_hw_segments(q, PRD_SEGMENTS);
 
 	/* This is a driver limit and could be eliminated. */
-	blk_queue_max_phys_segments(q, PRD_ENTRIES);
+	blk_queue_max_phys_segments(q, PRD_SEGMENTS);
 }
 
 #if MAX_HWIFS > 1
@@ -608,9 +630,10 @@
  *
  * This routine detects and reports such situations, but does not fix them.
  */
-static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
+static void save_match(struct ata_channel *hwif, struct ata_channel *new,
+		struct ata_channel **match)
 {
-	ide_hwif_t *m = *match;
+	struct ata_channel *m = *match;
 
 	if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
 		if (!new->hwgroup)
@@ -635,12 +658,12 @@
  * but anything else has led to problems on some machines.  We re-enable
  * interrupts as much as we can safely do in most places.
  */
-static int init_irq (ide_hwif_t *hwif)
+static int init_irq(struct ata_channel *hwif)
 {
 	unsigned long flags;
 	unsigned int index;
 	ide_hwgroup_t *hwgroup, *new_hwgroup;
-	ide_hwif_t *match = NULL;
+	struct ata_channel *match = NULL;
 
 
 	/* Allocate the buffer and potentially sleep first */
@@ -655,19 +678,18 @@
 	 * Group up with any other hwifs that share our irq(s).
 	 */
 	for (index = 0; index < MAX_HWIFS; index++) {
-		ide_hwif_t *h = &ide_hwifs[index];
+		struct ata_channel *h = &ide_hwifs[index];
 		if (h->hwgroup) {  /* scan only initialized hwif's */
 			if (hwif->irq == h->irq) {
 				hwif->sharing_irq = h->sharing_irq = 1;
 				if (hwif->chipset != ide_pci || h->chipset != ide_pci)
 					save_match(hwif, h, &match);
-			}
-			if (hwif->serialized) {
-				if (hwif->mate && hwif->mate->irq == h->irq)
-					save_match(hwif, h, &match);
-			}
-			if (h->serialized) {
-				if (h->mate && hwif->irq == h->mate->irq)
+
+				/* FIXME: This is still confusing. What would
+				 * happen if we match-ed two times?
+				 */
+
+				if (hwif->serialized || h->serialized)
 					save_match(hwif, h, &match);
 			}
 		}
@@ -736,7 +758,7 @@
 		ide_init_queue(drive);
 	}
 	if (!hwgroup->hwif) {
-		hwgroup->hwif = HWIF(hwgroup->drive);
+		hwgroup->hwif = hwgroup->drive->channel;
 #ifdef DEBUG
 		printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
 #endif
@@ -770,7 +792,7 @@
  * structures needed for the routines in genhd.c.  ide_geninit() gets called
  * somewhat later, during the partition check.
  */
-static void init_gendisk (ide_hwif_t *hwif)
+static void init_gendisk(struct ata_channel *hwif)
 {
 	struct gendisk *gd;
 	unsigned int unit, minors, i;
@@ -818,12 +840,11 @@
 
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		char name[80];
+
 		ide_add_generic_settings(hwif->drives + unit);
-		hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
+		hwif->drives[unit].dn = ((hwif->unit ? 2 : 0) + unit);
 		sprintf (name, "host%d/bus%d/target%d/lun%d",
-			(hwif->channel && hwif->mate) ?
-			hwif->mate->index : hwif->index,
-			hwif->channel, unit, hwif->drives[unit].lun);
+			hwif->index, hwif->unit, unit, hwif->drives[unit].lun);
 		if (hwif->drives[unit].present)
 			hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
 	}
@@ -840,7 +861,7 @@
 	return;
 }
 
-static int hwif_init (ide_hwif_t *hwif)
+static int hwif_init(struct ata_channel *hwif)
 {
 	if (!hwif->present)
 		return 0;
diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
--- a/drivers/ide/ide-proc.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/ide-proc.c	Sun Apr 14 12:16:55 2002
@@ -1,10 +1,6 @@
 /*
- *  linux/drivers/ide/ide-proc.c	Version 1.03	January  2, 1998
- *
  *  Copyright (C) 1997-1998	Mark Lord
- */
-
-/*
+ *
  * This is the /proc/ide/ filesystem implementation.
  *
  * The major reason this exists is to provide sufficient access
@@ -138,7 +134,7 @@
 static int proc_ide_read_imodel
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_hwif_t	*hwif = data;
+	struct ata_channel *hwif = data;
 	int		len;
 	const char	*name;
 
@@ -164,51 +160,38 @@
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
-static int proc_ide_read_mate
-	(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	ide_hwif_t	*hwif = data;
-	int		len;
-
-	if (hwif && hwif->mate && hwif->mate->present)
-		len = sprintf(page, "%s\n", hwif->mate->name);
-	else
-		len = sprintf(page, "(none)\n");
-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
 static int proc_ide_read_channel
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_hwif_t	*hwif = data;
+	struct ata_channel *hwif = data;
 	int		len;
 
-	page[0] = hwif->channel ? '1' : '0';
+	page[0] = hwif->unit ? '1' : '0';
 	page[1] = '\n';
 	len = 2;
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
-static int proc_ide_get_identify(ide_drive_t *drive, byte *buf)
+static int get_identify(ide_drive_t *drive, u8 *buf)
 {
-	struct hd_drive_task_hdr taskfile;
-	struct hd_drive_hob_hdr hobfile;
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-	memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+	struct ata_taskfile args;
 
-	taskfile.sector_count = 0x01;
-	taskfile.command = (drive->type == ATA_DISK) ? WIN_IDENTIFY : WIN_PIDENTIFY ;
+	memset(&args, 0, sizeof(args));
+	args.taskfile.sector_count = 0x01;
+	args.taskfile.command = (drive->type == ATA_DISK) ? WIN_IDENTIFY : WIN_PIDENTIFY ;
+	ide_cmd_type_parser(&args);
 
-	return ide_wait_taskfile(drive, &taskfile, &hobfile, buf);
+	return ide_raw_taskfile(drive, &args, buf);
 }
 
 static int proc_ide_read_identify
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_drive_t	*drive = data;
-	int		len = 0, i = 0;
+	ide_drive_t *drive = data;
+	int len = 0;
+	int i = 0;
 
-	if (drive && !proc_ide_get_identify(drive, page)) {
+	if (drive && !get_identify(drive, page)) {
 		unsigned short *val = (unsigned short *) page;
 		char *out = ((char *)val) + (SECTOR_WORDS * 4);
 		page = out;
@@ -217,8 +200,7 @@
 			val += 1;
 		} while (i < (SECTOR_WORDS * 2));
 		len = out - page;
-	}
-	else
+	} else
 		len = sprintf(page, "\n");
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
@@ -435,7 +417,9 @@
 	}
 }
 
-static void create_proc_ide_drives(ide_hwif_t *hwif)
+/* FIXME: we should iterate over the hwifs here as everywhere else.
+ */
+static void create_proc_ide_drives(struct ata_channel *hwif)
 {
 	int	d;
 	struct proc_dir_entry *ent;
@@ -460,12 +444,10 @@
 			}
 		}
 		sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
-		ent = proc_symlink(drive->name, proc_ide_root, name);
-		if (!ent) return;
 	}
 }
 
-static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
+static void destroy_proc_ide_device(struct ata_channel *hwif, ide_drive_t *drive)
 {
 	struct ata_operations *driver = drive->driver;
 
@@ -479,7 +461,7 @@
 	}
 }
 
-void destroy_proc_ide_drives(ide_hwif_t *hwif)
+void destroy_proc_ide_drives(struct ata_channel *hwif)
 {
 	int	d;
 
@@ -493,7 +475,6 @@
 
 static ide_proc_entry_t hwif_entries[] = {
 	{ "channel",	S_IFREG|S_IRUGO,	proc_ide_read_channel,	NULL },
-	{ "mate",	S_IFREG|S_IRUGO,	proc_ide_read_mate,	NULL },
 	{ "model",	S_IFREG|S_IRUGO,	proc_ide_read_imodel,	NULL },
 	{ NULL,	0, NULL, NULL }
 };
@@ -503,7 +484,7 @@
 	int	h;
 
 	for (h = 0; h < MAX_HWIFS; h++) {
-		ide_hwif_t *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 
 		if (!hwif->present)
 			continue;
@@ -522,7 +503,7 @@
 	int	h;
 
 	for (h = 0; h < MAX_HWIFS; h++) {
-		ide_hwif_t *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 		int exist = (hwif->proc != NULL);
 #if 0
 		if (!hwif->present)
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/ide-tape.c	Sun Apr 14 12:16:56 2002
@@ -2058,7 +2058,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
-		if (HWIF(drive)->dmaproc(ide_dma_end, drive)) {
+		if (drive->channel->dmaproc(ide_dma_end, drive)) {
 			/*
 			 * A DMA error is sometimes expected. For example,
 			 * if the tape is crossing a filemark during a
@@ -2132,7 +2132,7 @@
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n");
 		printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
-		HWIF(drive)->dmaproc(ide_dma_off, drive);
+		drive->channel->dmaproc(ide_dma_off, drive);
 		return ide_stopped;
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -2155,7 +2155,8 @@
 			if (temp > pc->buffer_size) {
 				printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
 				idetape_discard_data (drive, bcount.all);
-				ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
+				BUG_ON(HWGROUP(drive)->handler);
+				ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
 				return ide_started;
 			}
 #if IDETAPE_DEBUG_LOG
@@ -2181,7 +2182,8 @@
 	if (tape->debug_level >= 2)
 		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
 #endif
-	ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* And set the interrupt handler again */
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* And set the interrupt handler again */
 	return ide_started;
 }
 
@@ -2255,6 +2257,7 @@
 		return ide_stopped;
 	}
 	tape->cmd_start_time = jiffies;
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* Set the interrupt routine */
 	atapi_output_bytes (drive,pc->c,12);			/* Send the actual packet */
 	return ide_started;
@@ -2309,10 +2312,10 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
 		printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n");
-		(void) HWIF(drive)->dmaproc(ide_dma_off, drive);
+		(void) drive->channel->dmaproc(ide_dma_off, drive);
 	}
 	if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
-		dma_ok = !HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
+		dma_ok = !drive->channel->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	if (IDE_CONTROL_REG)
@@ -2324,10 +2327,11 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (dma_ok) {						/* Begin DMA, if necessary */
 		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
 		OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
@@ -3103,10 +3107,10 @@
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_read_position_result_t *result;
 	
-//#if IDETAPE_DEBUG_LOG
-//	if (tape->debug_level >= 4)
+#if IDETAPE_DEBUG_LOG
+	if (tape->debug_level >= 4)
 		printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
-//#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_DEBUG_LOG */
 
 	if (!tape->pc->error) {
 		result = (idetape_read_position_result_t *) tape->pc->buffer;
@@ -3280,10 +3284,10 @@
 	idetape_pc_t pc;
 	int position;
 
-//#if IDETAPE_DEBUG_LOG
-//        if (tape->debug_level >= 4)
-	printk (KERN_INFO "ide-tape: Reached idetape_read_position\n");
-//#endif /* IDETAPE_DEBUG_LOG */
+#if IDETAPE_DEBUG_LOG
+	if (tape->debug_level >= 4)
+	    printk (KERN_INFO "ide-tape: Reached idetape_read_position\n");
+#endif /* IDETAPE_DEBUG_LOG */
 
 #ifdef NO_LONGER_REQUIRED
 	idetape_flush_tape_buffers(drive);
@@ -5997,13 +6001,13 @@
 		tape->onstream = 1;
 	drive->dsc_overlap = 1;
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	if (!tape->onstream && HWIF(drive)->pci_dev != NULL) {
+	if (!tape->onstream && drive->channel->pci_dev != NULL) {
 		/*
 		 * These two ide-pci host adapters appear to need DSC overlap disabled.
 		 * This probably needs further analysis.
 		 */
-		if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
-		    (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
+		if ((drive->channel->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
+		    (drive->channel->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
 			printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name);
 		    	drive->dsc_overlap = 0;
 		}
@@ -6099,8 +6103,7 @@
 	idetape_chrdevs[minor].drive = NULL;
 	restore_flags (flags);	/* all CPUs (overkill?) */
 
-	/* FIXME: this appears to be totally wrong! */
-	ata_ops(drive)->busy = 0;
+	MOD_DEC_USE_COUNT;
 
 	ide_unregister_subdriver (drive);
 	drive->driver_data = NULL;
@@ -6255,12 +6258,12 @@
 		idetape_chrdevs[minor].drive = drive;
 		tape->de_r =
 		    devfs_register (drive->de, "mt", DEVFS_FL_DEFAULT,
-				    HWIF(drive)->major, minor,
+				    drive->channel->major, minor,
 				    S_IFCHR | S_IRUGO | S_IWUGO,
 				    &idetape_fops, NULL);
 		tape->de_n =
 		    devfs_register (drive->de, "mtn", DEVFS_FL_DEFAULT,
-				    HWIF(drive)->major, minor + 128,
+				    drive->channel->major, minor + 128,
 				    S_IFCHR | S_IRUGO | S_IWUGO,
 				    &idetape_fops, NULL);
 		devfs_register_tape (tape->de_r);
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/ide-taskfile.c	Sun Apr 14 12:16:59 2002
@@ -33,7 +33,7 @@
 #define DEBUG_TASKFILE	0	/* unset when fixed */
 
 #if DEBUG_TASKFILE
-#define DTF(x...) printk(##x)
+#define DTF(x...) printk(x)
 #else
 #define DTF(x...)
 #endif
@@ -48,14 +48,14 @@
 	if (rq->bio)
 		return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
 	else
-		return rq->buffer + task_rq_offset(rq);
+		return rq->buffer + ((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE;
 }
 
 static inline void ide_unmap_rq(struct request *rq, char *to,
 				unsigned long *flags)
 {
 	if (rq->bio)
-	    bio_kunmap_irq(to, flags);
+		bio_kunmap_irq(to, flags);
 }
 
 static void bswap_data (void *buffer, int wcount)
@@ -98,8 +98,8 @@
 	 * for handling polled ide transfers
 	 */
 
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_ide_input_data, drive, buffer, wcount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_ide_input_data, drive, buffer, wcount);
 		return;
 	}
 
@@ -138,8 +138,8 @@
 {
 	byte io_32bit;
 
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_ide_output_data, drive, buffer, wcount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_ide_output_data, drive, buffer, wcount);
 		return;
 	}
 
@@ -180,8 +180,8 @@
  */
 void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount);
 		return;
 	}
 
@@ -200,8 +200,8 @@
 
 void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
-	if (HWIF(drive)->ideproc) {
-		HWIF(drive)->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount);
+	if (drive->channel->ideproc) {
+		drive->channel->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount);
 		return;
 	}
 
@@ -243,7 +243,7 @@
 {
 	byte stat = 0;
 	if (drive->waiting_for_dma)
-		return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
+		return drive->channel->dmaproc(ide_dma_test_irq, drive);
 #if 0
 	/* need to guarantee 400ns since last command was issued */
 	udelay(1);
@@ -288,163 +288,186 @@
 			break;
 	}
 }
-static ide_startstop_t bio_mulout_intr(ide_drive_t *drive);
 
-/*
- * Handler for command write multiple
- * Called directly from execute_drive_cmd for the first bunch of sectors,
- * afterwards only by the ISR
- */
-static ide_startstop_t task_mulout_intr(ide_drive_t *drive)
+static ide_startstop_t pre_task_mulout_intr(ide_drive_t *drive, struct request *rq)
+{
+	struct ata_request *ar = rq->special;
+	struct ata_taskfile *args = &ar->ar_task;
+	ide_startstop_t startstop;
+
+	/*
+	 * assign private copy for multi-write
+	 */
+	memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
+
+	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
+		return startstop;
+
+	ata_poll_drive_ready(drive);
+
+	return args->handler(drive);
+}
+
+static ide_startstop_t task_mulout_intr (ide_drive_t *drive)
 {
-	unsigned int		msect, nsect;
 	byte stat		= GET_STAT();
+	/* FIXME: this should go possible as well */
 	byte io_32bit		= drive->io_32bit;
-	struct request *rq	= HWGROUP(drive)->rq;
+	struct request *rq	= &HWGROUP(drive)->wrq;
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
-	char *pBuf		= NULL;
-	unsigned long flags;
+	int mcount		= drive->mult_count;
+	ide_startstop_t startstop;
 
 	/*
 	 * (ks/hs): Handle last IRQ on multi-sector transfer,
 	 * occurs after all data was sent in this chunk
 	 */
-	if (rq->current_nr_sectors == 0) {
-		if (stat & (ERR_STAT|DRQ_STAT))
-			return ide_error(drive, "task_mulout_intr", stat);
+	if (!rq->nr_sectors) {
+		if (stat & (ERR_STAT|DRQ_STAT)) {
+			startstop = ide_error(drive, "task_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
+		}
 
-		/*
-		 * there may be more, ide_do_request will restart it if
-		 * necessary
-		 */
-		ide_end_request(drive, 1);
+		__ide_end_request(drive, 1, rq->hard_nr_sectors);
+		rq->bio = NULL;
 
 		return ide_stopped;
 	}
 
-	if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
-		if (stat & (ERR_STAT|DRQ_STAT)) {
-			return ide_error(drive, "task_mulout_intr", stat);
+	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
+		if (stat & (ERR_STAT | DRQ_STAT)) {
+			startstop = ide_error(drive, "task_mulout_intr", stat);
+			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
+			return startstop;
 		}
+
 		/* no data yet, so wait for another interrupt */
 		if (hwgroup->handler == NULL)
-			ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
+			ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
+
 		return ide_started;
 	}
 
-	/* (ks/hs): See task_mulin_intr */
-	msect = drive->mult_count;
-	nsect = rq->current_nr_sectors;
-	if (nsect > msect)
-		nsect = msect;
+	do {
+		char *buffer;
+		int nsect = rq->current_nr_sectors;
+		unsigned long flags;
+
+		if (nsect > mcount)
+			nsect = mcount;
+		mcount -= nsect;
+
+		buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
+		rq->sector += nsect;
+		rq->nr_sectors -= nsect;
+		rq->current_nr_sectors -= nsect;
+
+		/* Do we move to the next bio after this? */
+		if (!rq->current_nr_sectors) {
+			/* remember to fix this up /jens */
+			struct bio *bio = rq->bio->bi_next;
+
+			/* end early if we ran out of requests */
+			if (!bio) {
+				mcount = 0;
+			} else {
+				rq->bio = bio;
+				rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
+			}
+		}
+
+		/*
+		 * Ok, we're all setup for the interrupt
+		 * re-entering us on the last transfer.
+		 */
+		taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
+		bio_kunmap_irq(buffer, &flags);
+	} while (mcount);
 
-	pBuf = ide_map_rq(rq, &flags);
-	DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
-		pBuf, nsect, rq->current_nr_sectors);
-	drive->io_32bit = 0;
-	taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
-	ide_unmap_rq(rq, pBuf, &flags);
 	drive->io_32bit = io_32bit;
 	rq->errors = 0;
-	/* Are we sure that this as all been already transfered? */
-	rq->current_nr_sectors -= nsect;
 	if (hwgroup->handler == NULL)
-		ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL);
+		ide_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
+
 	return ide_started;
 }
 
-ide_startstop_t do_rw_taskfile(ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t ata_taskfile(ide_drive_t *drive,
+		struct ata_taskfile *args, struct request *rq)
 {
-	task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
-	hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
 	struct hd_driveid *id = drive->id;
-	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
+	u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (task->handler != task_mulout_intr && task->handler != bio_mulout_intr) {
+	if (args->handler != task_mulout_intr) {
 		if (IDE_CONTROL_REG)
 			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);	/* clear nIEN */
-		SELECT_MASK(HWIF(drive), drive, 0);
+		SELECT_MASK(drive->channel, drive, 0);
 	}
 
 	if ((id->command_set_2 & 0x0400) &&
 	    (id->cfs_enable_2 & 0x0400) &&
 	    (drive->addressing == 1)) {
-		OUT_BYTE(hobfile->feature, IDE_FEATURE_REG);
-		OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
-		OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
-		OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
-		OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
+		OUT_BYTE(args->hobfile.feature, IDE_FEATURE_REG);
+		OUT_BYTE(args->hobfile.sector_count, IDE_NSECTOR_REG);
+		OUT_BYTE(args->hobfile.sector_number, IDE_SECTOR_REG);
+		OUT_BYTE(args->hobfile.low_cylinder, IDE_LCYL_REG);
+		OUT_BYTE(args->hobfile.high_cylinder, IDE_HCYL_REG);
 	}
 
-	OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
-	OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
+	OUT_BYTE(args->taskfile.feature, IDE_FEATURE_REG);
+	OUT_BYTE(args->taskfile.sector_count, IDE_NSECTOR_REG);
 	/* refers to number of sectors to transfer */
-	OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
+	OUT_BYTE(args->taskfile.sector_number, IDE_SECTOR_REG);
 	/* refers to sector offset or start sector */
-	OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
-	OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
+	OUT_BYTE(args->taskfile.low_cylinder, IDE_LCYL_REG);
+	OUT_BYTE(args->taskfile.high_cylinder, IDE_HCYL_REG);
 
-	OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
-	if (task->handler != NULL) {
-		ide_set_handler (drive, task->handler, WAIT_CMD, NULL);
-		OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
+	OUT_BYTE((args->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
+	if (args->handler != NULL) {
+		ide_set_handler(drive, args->handler, WAIT_CMD, NULL);
+		OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
 		/*
 		 * Warning check for race between handler and prehandler for
 		 * writing first block of data.  however since we are well
 		 * inside the boundaries of the seek, we should be okay.
 		 */
-		if (task->prehandler != NULL) {
-			return task->prehandler(drive, task->rq);
-		}
+		if (args->prehandler != NULL)
+			return args->prehandler(drive, rq);
 	} else {
-		/* for dma commands we down set the handler */
-		if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
-	}
+		ide_dma_action_t dmaaction;
+		u8 command;
 
-	return ide_started;
-}
+		if (!drive->using_dma)
+			return ide_started;
 
-void do_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile,
-		struct hd_drive_hob_hdr *hobfile,
-		ide_handler_t *handler)
-{
-	struct hd_driveid *id = drive->id;
-	byte HIHI = (drive->addressing) ? 0xE0 : 0xEF;
+		command = args->taskfile.command;
 
-	/* (ks/hs): Moved to start, do not use for multiple out commands */
-	if (*handler != task_mulout_intr && handler != bio_mulout_intr) {
-		if (IDE_CONTROL_REG)
-			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);  /* clear nIEN */
-		SELECT_MASK(HWIF(drive), drive, 0);
-	}
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+		if (drive->using_tcq) {
+			if (command == WIN_READDMA_QUEUED
+			    || command == WIN_READDMA_QUEUED_EXT
+			    || command == WIN_WRITEDMA_QUEUED
+			    || command == WIN_READDMA_QUEUED_EXT)
+				return ide_start_tag(ide_dma_queued_start, drive, rq->special);
+		}
+#endif
 
-	if ((id->command_set_2 & 0x0400) &&
-	    (id->cfs_enable_2 & 0x0400) &&
-	    (drive->addressing == 1)) {
-		OUT_BYTE(hobfile->feature, IDE_FEATURE_REG);
-		OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG);
-		OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG);
-		OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG);
-		OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG);
-	}
+		if (command == WIN_WRITEDMA || command == WIN_WRITEDMA_EXT)
+			dmaaction = ide_dma_write;
+		else if (command == WIN_READDMA || command == WIN_READDMA_EXT)
+			dmaaction = ide_dma_read;
+		else
+			return ide_stopped;
 
-	OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
-	OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
-	/* refers to number of sectors to transfer */
-	OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
-	/* refers to sector offset or start sector */
-	OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
-	OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
+		if (!drive->channel->dmaproc(dmaaction, drive))
+			return ide_started;
 
-	OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
-	if (handler != NULL) {
-		ide_set_handler (drive, handler, WAIT_CMD, NULL);
-		OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
-	} else {
-		/* for dma commands we down set the handler */
-		if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive)));
+		return ide_stopped;
 	}
+
+	return ide_started;
 }
 
 /*
@@ -498,8 +521,9 @@
  */
 ide_startstop_t task_no_data_intr (ide_drive_t *drive)
 {
-	ide_task_t *args	= HWGROUP(drive)->rq->special;
-	byte stat		= GET_STAT();
+	struct ata_request *ar = HWGROUP(drive)->rq->special;
+	struct ata_taskfile *args = &ar->ar_task;
+	u8 stat = GET_STAT();
 
 	ide__sti();	/* local CPU only */
 
@@ -556,9 +580,10 @@
 	return ide_stopped;
 }
 
-static ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
 {
-	ide_task_t *args = rq->special;
+	struct ata_request *ar = rq->special;
+	struct ata_taskfile *args = &ar->ar_task;
 	ide_startstop_t startstop;
 
 	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
@@ -567,8 +592,8 @@
 	}
 
 	/* (ks/hs): Fixed Multi Write */
-	if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) &&
-	    (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) {
+	if ((args->taskfile.command != WIN_MULTWRITE) &&
+	    (args->taskfile.command != WIN_MULTWRITE_EXT)) {
 		unsigned long flags;
 		char *buf = ide_map_rq(rq, &flags);
 		/* For Write_sectors we need to stuff the first sector */
@@ -588,6 +613,7 @@
 static ide_startstop_t task_out_intr(ide_drive_t *drive)
 {
 	byte stat		= GET_STAT();
+	/* FIXME: this should go possible as well */
 	byte io_32bit		= drive->io_32bit;
 	struct request *rq	= HWGROUP(drive)->rq;
 	char *pBuf		= NULL;
@@ -604,7 +630,7 @@
 		rq = HWGROUP(drive)->rq;
 		pBuf = ide_map_rq(rq, &flags);
 		DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors);
-		drive->io_32bit = 0;
+
 		taskfile_output_data(drive, pBuf, SECTOR_WORDS);
 		ide_unmap_rq(rq, pBuf, &flags);
 		drive->io_32bit = io_32bit;
@@ -616,107 +642,6 @@
 	return ide_started;
 }
 
-static ide_startstop_t pre_bio_out_intr(ide_drive_t *drive, struct request *rq)
-{
-	ide_task_t *args = rq->special;
-	ide_startstop_t startstop;
-
-	/*
-	 * assign private copy for multi-write
-	 */
-	memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
-
-	if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ))
-		return startstop;
-
-	ata_poll_drive_ready(drive);
-	return args->handler(drive);
-}
-
-
-static ide_startstop_t bio_mulout_intr (ide_drive_t *drive)
-{
-	byte stat		= GET_STAT();
-	byte io_32bit		= drive->io_32bit;
-	struct request *rq	= &HWGROUP(drive)->wrq;
-	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
-	int mcount		= drive->mult_count;
-	ide_startstop_t startstop;
-
-	/*
-	 * (ks/hs): Handle last IRQ on multi-sector transfer,
-	 * occurs after all data was sent in this chunk
-	 */
-	if (!rq->nr_sectors) {
-		if (stat & (ERR_STAT|DRQ_STAT)) {
-			startstop = ide_error(drive, "bio_mulout_intr", stat);
-			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
-			return startstop;
-		}
-
-		__ide_end_request(drive, 1, rq->hard_nr_sectors);
-		HWGROUP(drive)->wrq.bio = NULL;
-		return ide_stopped;
-	}
-
-	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
-		if (stat & (ERR_STAT | DRQ_STAT)) {
-			startstop = ide_error(drive, "bio_mulout_intr", stat);
-			memcpy(rq, HWGROUP(drive)->rq, sizeof(struct request));
-			return startstop;
-		}
-
-		/* no data yet, so wait for another interrupt */
-		if (hwgroup->handler == NULL)
-			ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
-
-		return ide_started;
-	}
-
-	do {
-		char *buffer;
-		int nsect = rq->current_nr_sectors;
-		unsigned long flags;
-
-		if (nsect > mcount)
-			nsect = mcount;
-		mcount -= nsect;
-
-		buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
-		rq->sector += nsect;
-		rq->nr_sectors -= nsect;
-		rq->current_nr_sectors -= nsect;
-
-		/* Do we move to the next bio after this? */
-		if (!rq->current_nr_sectors) {
-			/* remember to fix this up /jens */
-			struct bio *bio = rq->bio->bi_next;
-
-			/* end early early we ran out of requests */
-			if (!bio) {
-				mcount = 0;
-			} else {
-				rq->bio = bio;
-				rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
-			}
-		}
-
-		/*
-		 * Ok, we're all setup for the interrupt
-		 * re-entering us on the last transfer.
-		 */
-		taskfile_output_data(drive, buffer, nsect * SECTOR_WORDS);
-		bio_kunmap_irq(buffer, &flags);
-	} while (mcount);
-
-	drive->io_32bit = io_32bit;
-	rq->errors = 0;
-	if (hwgroup->handler == NULL)
-		ide_set_handler(drive, bio_mulout_intr, WAIT_CMD, NULL);
-
-	return ide_started;
-}
-
 /*
  * Handler for command with Read Multiple
  */
@@ -724,6 +649,7 @@
 {
 	unsigned int		msect, nsect;
 	byte stat		= GET_STAT();
+	/* FIXME: this should go possible as well */
 	byte io_32bit		= drive->io_32bit;
 	struct request *rq	= HWGROUP(drive)->rq;
 	char *pBuf		= NULL;
@@ -748,7 +674,7 @@
 
 		pBuf = ide_map_rq(rq, &flags);
 
-		DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n",
+		DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %d\n",
 			pBuf, nsect, rq->current_nr_sectors);
 		drive->io_32bit = 0;
 		taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
@@ -772,14 +698,14 @@
 }
 
 /* Called by ioctl to feature out type of command being called */
-void ide_cmd_type_parser(ide_task_t *args)
+void ide_cmd_type_parser(struct ata_taskfile *args)
 {
-	struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister;
+	struct hd_drive_task_hdr *taskfile = &args->taskfile;
 
 	args->prehandler = NULL;
 	args->handler = NULL;
 
-	switch(args->tfRegister[IDE_COMMAND_OFFSET]) {
+	switch(args->taskfile.command) {
 		case WIN_IDENTIFY:
 		case WIN_PIDENTIFY:
 			args->handler = task_in_intr;
@@ -814,8 +740,8 @@
 		case CFA_WRITE_MULTI_WO_ERASE:
 		case WIN_MULTWRITE:
 		case WIN_MULTWRITE_EXT:
-			args->prehandler = pre_bio_out_intr;
-			args->handler = bio_mulout_intr;
+			args->prehandler = pre_task_mulout_intr;
+			args->handler = task_mulout_intr;
 			args->command_type = IDE_DRIVE_TASK_RAW_WRITE;
 			return;
 
@@ -830,9 +756,11 @@
 		case WIN_SMART:
 			if (taskfile->feature == SMART_WRITE_LOG_SECTOR)
 				args->prehandler = pre_task_out_intr;
-			args->tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS;
-			args->tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS;
-			switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
+
+			args->taskfile.low_cylinder = SMART_LCYL_PASS;
+			args->taskfile.high_cylinder = SMART_HCYL_PASS;
+
+			switch(args->taskfile.feature) {
 				case SMART_READ_VALUES:
 				case SMART_READ_THRESHOLDS:
 				case SMART_READ_LOG_SECTOR:
@@ -870,7 +798,7 @@
 #endif
 		case WIN_SETFEATURES:
 			args->handler = task_no_data_intr;
-			switch(args->tfRegister[IDE_FEATURE_OFFSET]) {
+			switch(args->taskfile.feature) {
 				case SETFEATURES_XFER:
 					args->command_type = IDE_DRIVE_TASK_SET_XFER;
 					return;
@@ -960,169 +888,109 @@
 /*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
  */
-static void ide_init_drive_taskfile (struct request *rq)
+void init_taskfile_request(struct request *rq)
 {
 	memset(rq, 0, sizeof(*rq));
 	rq->flags = REQ_DRIVE_TASKFILE;
 }
 
-/*
- * This is kept for internal use only !!!
- * This is an internal call and nobody in user-space has a damn
- * reason to call this taskfile.
- *
- * ide_raw_taskfile is the one that user-space executes.
- */
-int ide_wait_taskfile(ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf)
+int ide_raw_taskfile(ide_drive_t *drive, struct ata_taskfile *args, byte *buf)
 {
 	struct request rq;
-	ide_task_t args;
-
-	memset(&args, 0, sizeof(ide_task_t));
-
-	args.tfRegister[IDE_DATA_OFFSET]         = taskfile->data;
-	args.tfRegister[IDE_FEATURE_OFFSET]      = taskfile->feature;
-	args.tfRegister[IDE_NSECTOR_OFFSET]      = taskfile->sector_count;
-	args.tfRegister[IDE_SECTOR_OFFSET]       = taskfile->sector_number;
-	args.tfRegister[IDE_LCYL_OFFSET]         = taskfile->low_cylinder;
-	args.tfRegister[IDE_HCYL_OFFSET]         = taskfile->high_cylinder;
-	args.tfRegister[IDE_SELECT_OFFSET]       = taskfile->device_head;
-	args.tfRegister[IDE_COMMAND_OFFSET]      = taskfile->command;
-
-	args.hobRegister[IDE_DATA_OFFSET_HOB]    = hobfile->data;
-	args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature;
-	args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count;
-	args.hobRegister[IDE_SECTOR_OFFSET_HOB]  = hobfile->sector_number;
-	args.hobRegister[IDE_LCYL_OFFSET_HOB]    = hobfile->low_cylinder;
-	args.hobRegister[IDE_HCYL_OFFSET_HOB]    = hobfile->high_cylinder;
-	args.hobRegister[IDE_SELECT_OFFSET_HOB]  = hobfile->device_head;
-	args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control;
-
-	ide_init_drive_taskfile(&rq);
-	/* This is kept for internal use only !!! */
-	ide_cmd_type_parser(&args);
-	if (args.command_type != IDE_DRIVE_TASK_NO_DATA)
-		rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count;
+	struct ata_request ar;
 
+	ata_ar_init(drive, &ar);
+	init_taskfile_request(&rq);
 	rq.buffer = buf;
-	rq.special = &args;
-	return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
 
-int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *args, byte *buf)
-{
-	struct request rq;
-	ide_init_drive_taskfile(&rq);
-	rq.buffer = buf;
+	memcpy(&ar.ar_task, args, sizeof(*args));
 
 	if (args->command_type != IDE_DRIVE_TASK_NO_DATA)
-		rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
+		rq.current_nr_sectors = rq.nr_sectors
+			= (args->hobfile.sector_count << 8)
+			| args->taskfile.sector_count;
+
+	rq.special = &ar;
 
-	rq.special = args;
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
 /*
- *  The taskfile glue table
- *
- *  reqtask.data_phase	reqtask.req_cmd
- *			args.command_type		args.handler
- *
- *  TASKFILE_P_OUT_DMAQ	??				??
- *  TASKFILE_P_IN_DMAQ	??				??
- *  TASKFILE_P_OUT_DMA	??				??
- *  TASKFILE_P_IN_DMA	??				??
- *  TASKFILE_P_OUT	??				??
- *  TASKFILE_P_IN	??				??
- *
- *  TASKFILE_OUT_DMAQ	IDE_DRIVE_TASK_RAW_WRITE	NULL
- *  TASKFILE_IN_DMAQ	IDE_DRIVE_TASK_IN		NULL
- *
- *  TASKFILE_OUT_DMA	IDE_DRIVE_TASK_RAW_WRITE	NULL
- *  TASKFILE_IN_DMA	IDE_DRIVE_TASK_IN		NULL
- *
- *  TASKFILE_IN_OUT	??				??
- *
- *  TASKFILE_MULTI_OUT	IDE_DRIVE_TASK_RAW_WRITE	task_mulout_intr
- *  TASKFILE_MULTI_IN	IDE_DRIVE_TASK_IN		task_mulin_intr
- *
- *  TASKFILE_OUT	IDE_DRIVE_TASK_RAW_WRITE	task_out_intr
- *  TASKFILE_OUT	IDE_DRIVE_TASK_OUT		task_out_intr
+ * Implement generic ioctls invoked from userspace to imlpement specific
+ * functionality.
  *
- *  TASKFILE_IN		IDE_DRIVE_TASK_IN		task_in_intr
- *  TASKFILE_NO_DATA	IDE_DRIVE_TASK_NO_DATA		task_no_data_intr
+ * FIXME:
  *
- *			IDE_DRIVE_TASK_SET_XFER		task_no_data_intr
- *			IDE_DRIVE_TASK_INVALID
+ * 1. Rewrite hdparm to use the ide_task_ioctl function.
  *
- */
-
-/*
- * Issue ATA command and wait for completion. use for implementing commands in
- * kernel.
+ * 2. Publish it.
  *
- * The caller has to make sure buf is never NULL!
+ * 3. Kill this and HDIO_DRIVE_CMD alltogether.
  */
-static int ide_wait_cmd(ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *argbuf)
-{
-	struct request rq;
-
-	/* FIXME: Do we really have to zero out the buffer?
-	 */
-	memset(argbuf, 0, 4 + SECTOR_WORDS * 4 * sectors);
-	ide_init_drive_cmd(&rq);
-	rq.buffer = argbuf;
-	*argbuf++ = cmd;
-	*argbuf++ = nsect;
-	*argbuf++ = feature;
-	*argbuf++ = sectors;
-
-	return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
 
-int ide_cmd_ioctl(ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
 {
 	int err = 0;
-	byte args[4], *argbuf = args;
+	u8 vals[4];
+	u8 *argbuf = vals;
 	byte xfer_rate = 0;
 	int argsize = 4;
-	ide_task_t tfargs;
+	struct ata_taskfile args;
+	struct request rq;
 
+	/*
+	 * First phase.
+	 */
 	if (NULL == (void *) arg) {
 		struct request rq;
 		ide_init_drive_cmd(&rq);
 		return ide_do_drive_cmd(drive, &rq, ide_wait);
 	}
-	if (copy_from_user(args, (void *)arg, 4))
+
+	/*
+	 * Second phase.
+	 */
+	if (copy_from_user(vals, (void *)arg, 4))
 		return -EFAULT;
 
-	tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
-	tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
-	tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
-	tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
-	tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
-	tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
-	tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
+	args.taskfile.feature = vals[2];
+	args.taskfile.sector_count = vals[3];
+	args.taskfile.sector_number = vals[1];
+	args.taskfile.low_cylinder = 0x00;
+	args.taskfile.high_cylinder = 0x00;
+	args.taskfile.device_head = 0x00;
+	args.taskfile.command = vals[0];
 
-	if (args[3]) {
-		argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
+	if (vals[3]) {
+		argsize = 4 + (SECTOR_WORDS * 4 * vals[3]);
 		argbuf = kmalloc(argsize, GFP_KERNEL);
 		if (argbuf == NULL)
 			return -ENOMEM;
-		memcpy(argbuf, args, 4);
+		memcpy(argbuf, vals, 4);
 	}
-	if (set_transfer(drive, &tfargs)) {
-		xfer_rate = args[1];
-		if (ide_ata66_check(drive, &tfargs))
+
+	if (set_transfer(drive, &args)) {
+		xfer_rate = vals[1];
+		if (ide_ata66_check(drive, &args))
 			goto abort;
 	}
 
-	err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
+	/* Issue ATA command and wait for completion.
+	 */
+
+	/* FIXME: Do we really have to zero out the buffer?
+	 */
+	memset(argbuf, 0, 4 + SECTOR_WORDS * 4 * vals[3]);
+	ide_init_drive_cmd(&rq);
+	rq.buffer = argbuf;
+	memcpy(argbuf, vals, 4);
+
+	err = ide_do_drive_cmd(drive, &rq, ide_wait);
 
 	if (!err && xfer_rate) {
 		/* active-retuning-calls future */
-		if ((HWIF(drive)->speedproc) != NULL)
-			HWIF(drive)->speedproc(drive, xfer_rate);
+		if ((drive->channel->speedproc) != NULL)
+			drive->channel->speedproc(drive, xfer_rate);
 		ide_driveid_update(drive);
 	}
 abort:
@@ -1130,10 +998,11 @@
 		err = -EFAULT;
 	if (argsize > 4)
 		kfree(argbuf);
+
 	return err;
 }
 
-int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+int ide_task_ioctl(ide_drive_t *drive, unsigned long arg)
 {
 	int err = 0;
 	u8 args[7];
@@ -1162,16 +1031,14 @@
 EXPORT_SYMBOL(atapi_output_bytes);
 EXPORT_SYMBOL(taskfile_input_data);
 EXPORT_SYMBOL(taskfile_output_data);
-EXPORT_SYMBOL(do_rw_taskfile);
-EXPORT_SYMBOL(do_taskfile);
 
+EXPORT_SYMBOL(ata_taskfile);
 EXPORT_SYMBOL(recal_intr);
 EXPORT_SYMBOL(set_geometry_intr);
 EXPORT_SYMBOL(set_multmode_intr);
 EXPORT_SYMBOL(task_no_data_intr);
-
-EXPORT_SYMBOL(ide_wait_taskfile);
 EXPORT_SYMBOL(ide_raw_taskfile);
 EXPORT_SYMBOL(ide_cmd_type_parser);
+
 EXPORT_SYMBOL(ide_cmd_ioctl);
 EXPORT_SYMBOL(ide_task_ioctl);
diff -Nru a/drivers/ide/ide-tcq.c b/drivers/ide/ide-tcq.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/ide-tcq.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2001, 2002 Jens Axboe <axboe@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+/*
+ * Support for the DMA queued protocol, which enables ATA disk drives to
+ * use tagged command queueing.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ide.h>
+
+#include <asm/delay.h>
+
+/*
+ * warning: it will be _very_ verbose if set to 1
+ */
+#if 0
+#define TCQ_PRINTK printk
+#else
+#define TCQ_PRINTK(x...)
+#endif
+
+/*
+ * use nIEN or not
+ */
+#undef IDE_TCQ_NIEN
+
+/*
+ * we are leaving the SERVICE interrupt alone, IBM drives have it
+ * on per default and it can't be turned off. Doesn't matter, this
+ * is the sane config.
+ */
+#undef IDE_TCQ_FIDDLE_SI
+
+int ide_tcq_end(ide_drive_t *drive);
+ide_startstop_t ide_dmaq_intr(ide_drive_t *drive);
+
+static inline void drive_ctl_nien(ide_drive_t *drive, int clear)
+{
+#ifdef IDE_TCQ_NIEN
+	int mask = clear ? 0 : 2;
+
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl | mask, IDE_CONTROL_REG);
+#endif
+}
+
+/*
+ * if we encounter _any_ error doing I/O to one of the tags, we must
+ * invalidate the pending queue. clear the software busy queue and requeue
+ * on the request queue for restart. issue a WIN_NOP to clear hardware queue
+ */
+static void ide_tcq_invalidate_queue(ide_drive_t *drive)
+{
+	request_queue_t *q = &drive->queue;
+	unsigned long flags;
+	struct ata_request *ar;
+	int i;
+
+	printk("%s: invalidating pending queue\n", drive->name);
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	del_timer(&HWGROUP(drive)->timer);
+
+	/*
+	 * assume oldest commands have the higher tags... doesn't matter
+	 * much. shove requests back into request queue.
+	 */
+	for (i = drive->queue_depth - 1; i; i--) {
+		ar = drive->tcq->ar[i];
+		if (!ar)
+			continue;
+
+		ar->ar_rq->special = NULL;
+		ar->ar_rq->flags &= ~REQ_STARTED;
+		_elv_add_request(q, ar->ar_rq, 0, 0);
+		ata_ar_put(drive, ar);
+	}
+
+	drive->tcq->queued = 0;
+	drive->using_tcq = 0;
+	drive->queue_depth = 1;
+	clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
+	clear_bit(IDE_DMA, &HWGROUP(drive)->flags);
+	HWGROUP(drive)->handler = NULL;
+
+	/*
+	 * do some internal stuff -- we really need this command to be
+	 * executed before any new commands are started. issue a NOP
+	 * to clear internal queue on drive
+	 */
+	ar = ata_ar_get(drive);
+
+	memset(&ar->ar_task, 0, sizeof(ar->ar_task));
+	AR_TASK_CMD(ar) = WIN_NOP;
+	ide_cmd_type_parser(&ar->ar_task);
+	ar->ar_rq = &HWGROUP(drive)->wrq;
+	init_taskfile_request(ar->ar_rq);
+	ar->ar_rq->rq_dev = mk_kdev(drive->channel->major, (drive->select.b.unit)<<PARTN_BITS);
+	ar->ar_rq->special = ar;
+	ar->ar_flags |= ATA_AR_RETURN;
+	_elv_add_request(q, ar->ar_rq, 0, 0);
+
+	/*
+	 * make sure that nIEN is cleared
+	 */
+	drive_ctl_nien(drive, 0);
+
+	/*
+	 * start doing stuff again
+	 */
+	q->request_fn(q);
+	spin_unlock_irqrestore(&ide_lock, flags);
+	printk("ide_tcq_invalidate_queue: done\n");
+}
+
+void ide_tcq_intr_timeout(unsigned long data)
+{
+	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
+	unsigned long flags;
+	ide_drive_t *drive;
+
+	printk("ide_tcq_intr_timeout: timeout waiting for interrupt...\n");
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	if (test_bit(IDE_BUSY, &hwgroup->flags))
+		printk("ide_tcq_intr_timeout: hwgroup not busy\n");
+	if (hwgroup->handler == NULL)
+		printk("ide_tcq_intr_timeout: missing isr!\n");
+	if ((drive = hwgroup->drive) == NULL)
+		printk("ide_tcq_intr_timeout: missing drive!\n");
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	if (drive)
+		ide_tcq_invalidate_queue(drive);
+}
+
+void ide_tcq_set_intr(ide_hwgroup_t *hwgroup, ide_handler_t *handler)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	/*
+	 * always just bump the timer for now, the timeout handling will
+	 * have to be changed to be per-command
+	 */
+	hwgroup->timer.function = ide_tcq_intr_timeout;
+	hwgroup->timer.data = (unsigned long) hwgroup;
+	mod_timer(&hwgroup->timer, jiffies + 5 * HZ);
+
+	hwgroup->handler = handler;
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+/*
+ * wait 400ns, then poll for busy_mask to clear from alt status
+ */
+#define IDE_TCQ_WAIT	(10000)
+int ide_tcq_wait_altstat(ide_drive_t *drive, byte *stat, byte busy_mask)
+{
+	int i;
+
+	/*
+	 * one initial udelay(1) should be enough, reading alt stat should
+	 * provide the required delay...
+	 */
+	*stat = 0;
+	i = 0;
+	do {
+		udelay(1);
+
+		if (unlikely(i++ > IDE_TCQ_WAIT))
+			return 1;
+	} while ((*stat = GET_ALTSTAT()) & busy_mask);
+
+	return 0;
+}
+
+/*
+ * issue SERVICE command to drive -- drive must have been selected first,
+ * and it must have reported a need for service (status has SERVICE_STAT set)
+ *
+ * Also, nIEN must be set as not to need protection against ide_dmaq_intr
+ */
+ide_startstop_t ide_service(ide_drive_t *drive)
+{
+	struct ata_request *ar;
+	byte feat, tag, stat;
+
+	if (test_bit(IDE_DMA, &HWGROUP(drive)->flags))
+		printk("ide_service: DMA in progress\n");
+
+	/*
+	 * need to select the right drive first...
+	 */
+	if (drive != HWGROUP(drive)->drive) {
+		SELECT_DRIVE(drive->channel, drive);
+		udelay(10);
+	}
+
+	drive_ctl_nien(drive, 1);
+
+	/*
+	 * send SERVICE, wait 400ns, wait for BUSY_STAT to clear
+	 */
+	OUT_BYTE(WIN_QUEUED_SERVICE, IDE_COMMAND_REG);
+
+	if (ide_tcq_wait_altstat(drive, &stat, BUSY_STAT)) {
+		printk("ide_service: BUSY clear took too long\n");
+		ide_tcq_invalidate_queue(drive);
+		return ide_stopped;
+	}
+
+	drive_ctl_nien(drive, 0);
+
+	/*
+	 * FIXME, invalidate queue
+	 */
+	if (stat & ERR_STAT) {
+		printk("%s: error SERVICING drive (%x)\n", drive->name, stat);
+		ide_dump_status(drive, "ide_service", stat);
+		return ide_tcq_end(drive);
+	}
+
+	/*
+	 * should not happen, a buggy device could introduce loop
+	 */
+	if ((feat = GET_FEAT()) & NSEC_REL) {
+		printk("%s: release in service\n", drive->name);
+		IDE_SET_CUR_TAG(drive, -1);
+		return ide_stopped;
+	}
+
+	/*
+	 * start dma
+	 */
+	tag = feat >> 3;
+	IDE_SET_CUR_TAG(drive, tag);
+
+	TCQ_PRINTK("ide_service: stat %x, feat %x\n", stat, feat);
+
+	if ((ar = IDE_CUR_TAG(drive)) == NULL) {
+		printk("ide_service: missing request for tag %d\n", tag);
+		return ide_stopped;
+	}
+
+	/*
+	 * we'll start a dma read or write, device will trigger
+	 * interrupt to indicate end of transfer, release is not allowed
+	 */
+	if (rq_data_dir(ar->ar_rq) == READ) {
+		TCQ_PRINTK("ide_service: starting READ %x\n", stat);
+		drive->channel->dmaproc(ide_dma_read_queued, drive);
+	} else {
+		TCQ_PRINTK("ide_service: starting WRITE %x\n", stat);
+		drive->channel->dmaproc(ide_dma_write_queued, drive);
+	}
+
+	/*
+	 * dmaproc set intr handler
+	 */
+	return ide_started;
+}
+
+ide_startstop_t ide_check_service(ide_drive_t *drive)
+{
+	byte stat;
+
+	if (!ide_pending_commands(drive))
+		return ide_stopped;
+
+	if ((stat = GET_STAT()) & SERVICE_STAT)
+		return ide_service(drive);
+
+	/*
+	 * we have pending commands, wait for interrupt
+	 */
+	ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
+	return ide_started;
+}
+
+int ide_tcq_end(ide_drive_t *drive)
+{
+	byte stat = GET_STAT();
+
+	if (stat & ERR_STAT) {
+		ide_dump_status(drive, "ide_tcq_end", stat);
+		ide_tcq_invalidate_queue(drive);
+		return ide_stopped;
+	} else if (stat & SERVICE_STAT) {
+		TCQ_PRINTK("ide_tcq_end: serv stat=%x\n", stat);
+		return ide_service(drive);
+	}
+
+	TCQ_PRINTK("ide_tcq_end: stat=%x, feat=%x\n", stat, GET_FEAT());
+	return ide_stopped;
+}
+
+ide_startstop_t ide_dmaq_complete(ide_drive_t *drive, byte stat)
+{
+	struct ata_request *ar;
+	byte dma_stat;
+
+#if 0
+	byte feat = GET_FEAT();
+
+	if ((feat & (NSEC_CD | NSEC_IO)) != (NSEC_CD | NSEC_IO))
+		printk("%s: C/D | I/O not set\n", drive->name);
+#endif
+
+	/*
+	 * transfer was in progress, stop DMA engine
+	 */
+	ar = IDE_CUR_TAG(drive);
+
+	dma_stat = drive->channel->dmaproc(ide_dma_end, drive);
+
+	/*
+	 * must be end of I/O, check status and complete as necessary
+	 */
+	if (unlikely(!OK_STAT(stat, READY_STAT, drive->bad_wstat | DRQ_STAT))) {
+		printk("ide_dmaq_intr: %s: error status %x\n", drive->name, stat);
+		ide_dump_status(drive, "ide_dmaq_intr", stat);
+		ide_tcq_invalidate_queue(drive);
+		return ide_stopped;
+	}
+
+	if (dma_stat)
+		printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat);
+
+	TCQ_PRINTK("ide_dmaq_intr: ending %p, tag %d\n", ar, ar->ar_tag);
+	ide_end_queued_request(drive, !dma_stat, ar->ar_rq);
+
+	IDE_SET_CUR_TAG(drive, -1);
+	return ide_check_service(drive);
+}
+
+/*
+ * intr handler for queued dma operations. this can be entered for two
+ * reasons:
+ *
+ * 1) device has completed dma transfer
+ * 2) service request to start a command
+ *
+ * if the drive has an active tag, we first complete that request before
+ * processing any pending SERVICE.
+ */
+ide_startstop_t ide_dmaq_intr(ide_drive_t *drive)
+{
+	byte stat = GET_STAT();
+
+	TCQ_PRINTK("ide_dmaq_intr: stat=%x, tag %d\n", stat, drive->tcq->active_tag);
+
+	/*
+	 * if a command completion interrupt is pending, do that first and
+	 * check service afterwards
+	 */
+	if (drive->tcq->active_tag != -1)
+		return ide_dmaq_complete(drive, stat);
+
+	/*
+	 * service interrupt
+	 */
+	if (stat & SERVICE_STAT) {
+		TCQ_PRINTK("ide_dmaq_intr: SERV (stat=%x)\n", stat);
+		return ide_service(drive);
+	}
+
+	printk("ide_dmaq_intr: stat=%x, not expected\n", stat);
+	return ide_check_service(drive);
+}
+
+/*
+ * configure the drive for tcq
+ */
+static int ide_tcq_configure(ide_drive_t *drive)
+{
+	struct ata_taskfile args;
+	int tcq_supp = 1 << 1 | 1 << 14;
+
+	/*
+	 * bit 14 and 1 must be set in word 83 of the device id to indicate
+	 * support for dma queued protocol
+	 */
+	if ((drive->id->command_set_2 & tcq_supp) != tcq_supp) {
+		printk("%s: queued feature set not supported\n", drive->name);
+		return 1;
+	}
+
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = SETFEATURES_EN_WCACHE;
+	args.taskfile.command = WIN_SETFEATURES;
+	ide_cmd_type_parser(&args);
+
+	if (ide_raw_taskfile(drive, &args, NULL)) {
+		printk("%s: failed to enable write cache\n", drive->name);
+		return 1;
+	}
+
+	/*
+	 * disable RELease interrupt, it's quicker to poll this after
+	 * having sent the command opcode
+	 */
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = SETFEATURES_DIS_RI;
+	args.taskfile.command = WIN_SETFEATURES;
+	ide_cmd_type_parser(&args);
+
+	if (ide_raw_taskfile(drive, &args, NULL)) {
+		printk("%s: disabling release interrupt fail\n", drive->name);
+		return 1;
+	}
+
+#ifdef IDE_TCQ_FIDDLE_SI
+	/*
+	 * enable SERVICE interrupt
+	 */
+	memset(&args, 0, sizeof(args));
+	args.taskfile.feature = SETFEATURES_EN_SI;
+	args.taskfile.command = WIN_SETFEATURES;
+	ide_cmd_type_parser(&args);
+
+	if (ide_raw_taskfile(drive, &args, NULL)) {
+		printk("%s: enabling service interrupt fail\n", drive->name);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * for now assume that command list is always as big as we need and don't
+ * attempt to shrink it on tcq disable
+ */
+static int ide_enable_queued(ide_drive_t *drive, int on)
+{
+	/*
+	 * disable or adjust queue depth
+	 */
+	if (!on) {
+		printk("%s: TCQ disabled\n", drive->name);
+		drive->using_tcq = 0;
+
+		return 0;
+	} else if (drive->using_tcq) {
+		drive->queue_depth = drive->using_tcq;
+
+		goto out;
+	}
+
+	if (ide_tcq_configure(drive)) {
+		drive->using_tcq = 0;
+
+		return 1;
+	}
+
+out:
+	drive->tcq->max_depth = 0;
+
+	printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth);
+	drive->using_tcq = 1;
+
+	return 0;
+}
+
+int ide_tcq_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	struct ata_channel *hwif = drive->channel;
+	unsigned int reading = 0, enable_tcq = 1;
+	ide_startstop_t startstop;
+	struct ata_request *ar;
+	byte stat, feat;
+
+	switch (func) {
+		/*
+		 * invoked from a SERVICE interrupt, command etc already known.
+		 * just need to start the dma engine for this tag
+		 */
+		case ide_dma_read_queued:
+			reading = 1 << 3;
+		case ide_dma_write_queued:
+			TCQ_PRINTK("ide_dma: setting up queued %d\n", drive->tcq->active_tag);
+			BUG_ON(drive->tcq->active_tag == -1);
+
+			if (!test_bit(IDE_BUSY, &HWGROUP(drive)->flags))
+				printk("queued_rw: IDE_BUSY not set\n");
+
+			if (ide_wait_stat(&startstop, drive, READY_STAT | DRQ_STAT, BUSY_STAT, WAIT_READY)) {
+				printk("%s: timeout waiting for data phase\n", drive->name);
+				return startstop;
+			}
+
+			if (ide_start_dma(hwif, drive, func))
+				return 1;
+
+			ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
+			return hwif->dmaproc(ide_dma_begin, drive);
+
+			/*
+			 * start a queued command from scratch
+			 */
+		case ide_dma_queued_start:
+			BUG_ON(drive->tcq->active_tag == -1);
+			ar = IDE_CUR_TAG(drive);
+
+			/*
+			 * set nIEN, tag start operation will enable again when
+			 * it is safe
+			 */
+			drive_ctl_nien(drive, 1);
+
+			OUT_BYTE(AR_TASK_CMD(ar), IDE_COMMAND_REG);
+
+			if (ide_tcq_wait_altstat(drive, &stat, BUSY_STAT)) {
+				printk("ide_dma_queued_start: abort (stat=%x)\n", stat);
+				return ide_stopped;
+			}
+
+			drive_ctl_nien(drive, 0);
+
+			if (stat & ERR_STAT) {
+				printk("ide_dma_queued_start: abort (stat=%x)\n", stat);
+				return ide_stopped;
+			}
+
+			if ((feat = GET_FEAT()) & NSEC_REL) {
+				drive->tcq->immed_rel++;
+				TCQ_PRINTK("REL in queued_start\n");
+				IDE_SET_CUR_TAG(drive, -1);
+
+				if ((stat = GET_STAT()) & SERVICE_STAT)
+					return ide_service(drive);
+
+				ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
+				return ide_released;
+			}
+
+			drive->tcq->immed_comp++;
+
+			if (ide_wait_stat(&startstop, drive, READY_STAT | DRQ_STAT, BUSY_STAT, WAIT_READY)) {
+				printk("%s: timeout waiting for data phase\n", drive->name);
+				return startstop;
+			}
+
+			if (ide_start_dma(hwif, drive, func))
+				return ide_stopped;
+
+			if (hwif->dmaproc(ide_dma_begin, drive))
+				return ide_stopped;
+
+			/*
+			 * wait for SERVICE or completion interrupt
+			 */
+			ide_tcq_set_intr(HWGROUP(drive), ide_dmaq_intr);
+			return ide_started;
+
+		case ide_dma_queued_off:
+			enable_tcq = 0;
+		case ide_dma_queued_on:
+			return ide_enable_queued(drive, enable_tcq);
+		default:
+			break;
+	}
+
+	return 1;
+}
+
+int ide_build_sglist (struct ata_channel *hwif, struct request *rq);
+ide_startstop_t ide_start_tag(ide_dma_action_t func, ide_drive_t *drive,
+			      struct ata_request *ar)
+{
+	/*
+	 * do this now, no need to run that with interrupts disabled
+	 */
+	if (!ide_build_sglist(drive->channel, ar->ar_rq))
+		return ide_stopped;
+
+	IDE_SET_CUR_TAG(drive, ar->ar_tag);
+	return ide_tcq_dmaproc(func, drive);
+}
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/ide/ide.c	Sun Apr 14 12:16:58 2002
@@ -223,7 +223,7 @@
 /*
  * This is declared extern in ide.h, for access by other IDE modules:
  */
-ide_hwif_t ide_hwifs[MAX_HWIFS];	/* master data repository */
+struct ata_channel ide_hwifs[MAX_HWIFS];	/* master data repository */
 
 #if (DISK_RECOVERY_TIME > 0)
 /*
@@ -244,19 +244,19 @@
 	__restore_flags(flags);	/* local CPU only */
 	return (t - i);
 }
-#endif /* DISK_RECOVERY_TIME */
+#endif
 
-static inline void set_recovery_timer (ide_hwif_t *hwif)
+static inline void set_recovery_timer(struct ata_channel *channel)
 {
 #if (DISK_RECOVERY_TIME > 0)
-	hwif->last_time = read_timer();
-#endif /* DISK_RECOVERY_TIME */
+	channel->last_time = read_timer();
+#endif
 }
 
 /*
  * Do not even *think* about calling this!
  */
-static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
+static void init_hwif_data(struct ata_channel *hwif, unsigned int index)
 {
 	static const byte ide_major[] = {
 		IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR,
@@ -267,7 +267,7 @@
 	hw_regs_t hw;
 
 	/* bulk initialize hwif & drive info with zeros */
-	memset(hwif, 0, sizeof(ide_hwif_t));
+	memset(hwif, 0, sizeof(struct ata_channel));
 	memset(&hw, 0, sizeof(hw_regs_t));
 
 	/* fill in any non-zero initial values */
@@ -288,7 +288,7 @@
 
 		drive->type			= ATA_DISK;
 		drive->select.all		= (unit<<4)|0xa0;
-		drive->hwif			= hwif;
+		drive->channel			= hwif;
 		drive->ctl			= 0x08;
 		drive->ready_stat		= READY_STAT;
 		drive->bad_wstat		= BAD_W_STAT;
@@ -368,6 +368,25 @@
 	return 0;	/* no, it is not a flash memory card */
 }
 
+void ide_end_queued_request(ide_drive_t *drive, int uptodate, struct request *rq)
+{
+	unsigned long flags;
+
+	BUG_ON(!(rq->flags & REQ_STARTED));
+	BUG_ON(!rq->special);
+
+	if (!end_that_request_first(rq, uptodate, rq->hard_nr_sectors)) {
+		struct ata_request *ar = rq->special;
+
+		add_blkdev_randomness(major(rq->rq_dev));
+
+		spin_lock_irqsave(&ide_lock, flags);
+		ata_ar_put(drive, ar);
+		end_that_request_last(rq);
+		spin_unlock_irqrestore(&ide_lock, flags);
+	}
+}
+
 int __ide_end_request(ide_drive_t *drive, int uptodate, int nr_secs)
 {
 	struct request *rq;
@@ -396,9 +415,17 @@
 	}
 
 	if (!end_that_request_first(rq, uptodate, nr_secs)) {
+		struct ata_request *ar = rq->special;
+
 		add_blkdev_randomness(major(rq->rq_dev));
+		/*
+		 * request with ATA_AR_QUEUED set have already been
+		 * dequeued, but doing it twice is ok
+		 */
 		blkdev_dequeue_request(rq);
 		HWGROUP(drive)->rq = NULL;
+		if (ar)
+			ata_ar_put(drive, ar);
 		end_that_request_last(rq);
 		ret = 0;
 	}
@@ -422,8 +449,8 @@
 
 	spin_lock_irqsave(&ide_lock, flags);
 	if (hwgroup->handler != NULL) {
-		printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
-			drive->name, hwgroup->handler, handler);
+		printk("%s: ide_set_handler: handler not null; old=%p, new=%p, from %p\n",
+			drive->name, hwgroup->handler, handler, __builtin_return_address(0));
 	}
 	hwgroup->handler	= handler;
 	hwgroup->expiry		= expiry;
@@ -445,13 +472,13 @@
 	if (drive->using_dma) {
 		/* check the DMA crc count */
 		if (drive->crc_count) {
-			HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
-			if ((HWIF(drive)->speedproc) != NULL)
-				HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive));
+			drive->channel->dmaproc(ide_dma_off_quietly, drive);
+			if ((drive->channel->speedproc) != NULL)
+				drive->channel->speedproc(drive, ide_auto_reduce_xfer(drive));
 			if (drive->current_speed >= XFER_SW_DMA_0)
-				HWIF(drive)->dmaproc(ide_dma_on, drive);
+				drive->channel->dmaproc(ide_dma_on, drive);
 		} else
-			HWIF(drive)->dmaproc(ide_dma_off, drive);
+			drive->channel->dmaproc(ide_dma_off, drive);
 	}
 }
 
@@ -467,8 +494,11 @@
 	if (ata_ops(drive) && ata_ops(drive)->capacity)
 		return ata_ops(drive)->capacity(drive);
 
-	/* FIXME: This magic number seems to be bogous. */
-	return 0x7fffffff;
+	/* This used to be 0x7fffffff, but since now we use the maximal drive
+	 * capacity value used by other kernel subsystems as well.
+	 */
+
+	return ~0UL;
 }
 
 /*
@@ -483,7 +513,7 @@
 	printk("%s: ata_special: 0x%02x\n", drive->name, s->all);
 #endif
 	if (s->b.set_tune) {
-		ide_tuneproc_t *tuneproc = HWIF(drive)->tuneproc;
+		ide_tuneproc_t *tuneproc = drive->channel->tuneproc;
 		s->b.set_tune = 0;
 		if (tuneproc != NULL)
 			tuneproc(drive, drive->tune_req);
@@ -507,9 +537,9 @@
 extern struct block_device_operations ide_fops[];
 
 /*
- * ide_geninit() is called exactly *once* for each interface.
+ * This is called exactly *once* for each channel.
  */
-void ide_geninit (ide_hwif_t *hwif)
+void ide_geninit(struct ata_channel *hwif)
 {
 	unsigned int unit;
 	struct gendisk *gd = hwif->gd;
@@ -529,26 +559,26 @@
 	}
 }
 
-static ide_startstop_t do_reset1 (ide_drive_t *, int);		/* needed below */
+static ide_startstop_t do_reset1(ide_drive_t *, int);		/* needed below */
 
 /*
- * ATAPI_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an ATAPI drive reset operation. If the drive has not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
+ * Poll the interface for completion every 50ms during an ATAPI drive reset
+ * operation. If the drive has not yet responded, and we have not yet hit our
+ * maximum waiting time, then the timer is restarted for another 50ms.
  */
 static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	byte stat;
 
-	SELECT_DRIVE(HWIF(drive),drive);
+	SELECT_DRIVE(drive->channel,drive);
 	udelay (10);
 
 	if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
 		printk("%s: ATAPI reset complete\n", drive->name);
 	} else {
-		if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
+		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
 			return ide_started;	/* continue polling */
 		}
@@ -561,19 +591,19 @@
 }
 
 /*
- * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an ide reset operation. If the drives have not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
+ * Poll the interface for completion every 50ms during an ata reset operation.
+ * If the drives have not yet responded, and we have not yet hit our maximum
+ * waiting time, then the timer is restarted for another 50ms.
  */
 static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte tmp;
 
 	if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
-		if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
+		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
 			return ide_started;	/* continue polling */
 		}
@@ -632,7 +662,7 @@
 {
 	unsigned int unit;
 	unsigned long flags;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 
 	__save_flags(flags);	/* local CPU only */
@@ -645,6 +675,7 @@
 		udelay (20);
 		OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL);
 		__restore_flags (flags);	/* local CPU only */
 		return ide_started;
@@ -679,7 +710,8 @@
 	}
 	udelay(10);			/* more than enough time */
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-	ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL);
+	BUG_ON(HWGROUP(drive)->handler);
+	ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
 
 	/*
 	 * Some weird controller like resetting themselves to a strange
@@ -705,7 +737,7 @@
 /*
  * Clean up after success/failure of an explicit drive cmd
  */
-void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
+void ide_end_drive_cmd(ide_drive_t *drive, byte stat, byte err)
 {
 	unsigned long flags;
 	struct request *rq;
@@ -734,32 +766,36 @@
 			args[6] = IN_BYTE(IDE_SELECT_REG);
 		}
 	} else if (rq->flags & REQ_DRIVE_TASKFILE) {
-		ide_task_t *args = (ide_task_t *) rq->special;
-		rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+		struct ata_request *ar = rq->special;
+		struct ata_taskfile *args = &ar->ar_task;
+
+		rq->errors = !OK_STAT(stat, READY_STAT, BAD_STAT);
+		if (args && args->taskfile.command == WIN_NOP)
+			printk(KERN_INFO "%s: NOP completed\n", __FUNCTION__);
 		if (args) {
-			if (args->tf_in_flags.b.data) {
-				unsigned short data			= IN_WORD(IDE_DATA_REG);
-				args->tfRegister[IDE_DATA_OFFSET]	= (data) & 0xFF;
-				args->hobRegister[IDE_DATA_OFFSET_HOB]	= (data >> 8) & 0xFF;
-			}
-			args->tfRegister[IDE_ERROR_OFFSET]   = err;
-			args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG);
-			args->tfRegister[IDE_SECTOR_OFFSET]  = IN_BYTE(IDE_SECTOR_REG);
-			args->tfRegister[IDE_LCYL_OFFSET]    = IN_BYTE(IDE_LCYL_REG);
-			args->tfRegister[IDE_HCYL_OFFSET]    = IN_BYTE(IDE_HCYL_REG);
-			args->tfRegister[IDE_SELECT_OFFSET]  = IN_BYTE(IDE_SELECT_REG);
-			args->tfRegister[IDE_STATUS_OFFSET]  = stat;
+			args->taskfile.feature = err;
+			args->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
+			args->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
+			args->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
+			args->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
+			args->taskfile.device_head = IN_BYTE(IDE_SELECT_REG);
+			args->taskfile.command = stat;
 			if ((drive->id->command_set_2 & 0x0400) &&
 			    (drive->id->cfs_enable_2 & 0x0400) &&
 			    (drive->addressing == 1)) {
-				OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
-				args->hobRegister[IDE_FEATURE_OFFSET_HOB] = IN_BYTE(IDE_FEATURE_REG);
-				args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = IN_BYTE(IDE_NSECTOR_REG);
-				args->hobRegister[IDE_SECTOR_OFFSET_HOB]  = IN_BYTE(IDE_SECTOR_REG);
-				args->hobRegister[IDE_LCYL_OFFSET_HOB]    = IN_BYTE(IDE_LCYL_REG);
-				args->hobRegister[IDE_HCYL_OFFSET_HOB]    = IN_BYTE(IDE_HCYL_REG);
+				/* The following command goes to the hob file! */
+
+				OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG);
+				args->hobfile.feature = IN_BYTE(IDE_FEATURE_REG);
+				args->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
+
+				args->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
+				args->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
+				args->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
 			}
 		}
+		if (ar->ar_flags & ATA_AR_RETURN)
+			ata_ar_put(drive, ar);
 	}
 
 	blkdev_dequeue_request(rq);
@@ -870,13 +906,18 @@
 }
 
 /*
- * ide_error() takes action based on the error returned by the drive.
+ * Take action based on the error returned by the drive.
  */
-ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
+ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, byte stat)
 {
 	struct request *rq;
 	byte err;
 
+	/*
+	 * FIXME: remember to invalidate tcq queue when drive->using_tcq
+	 * and atomic_read(&drive->tcq->queued) /jens
+	 */
+
 	err = ide_dump_status(drive, msg, stat);
 	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
 		return ide_stopped;
@@ -928,21 +969,21 @@
 }
 
 /*
- * Issue a simple drive command
- * The drive must be selected beforehand.
+ * Issue a simple drive command.  The drive must be selected beforehand.
  */
-void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
+void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler (drive, handler, WAIT_CMD, NULL);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
-	SELECT_MASK(HWIF(drive),drive,0);
+	SELECT_MASK(drive->channel, drive, 0);
 	OUT_BYTE(nsect,IDE_NSECTOR_REG);
 	OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
 
 /*
- * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
+ * Invoked on completion of a special DRIVE_CMD.
  */
 static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
 {
@@ -968,17 +1009,17 @@
 }
 
 /*
- * This routine busy-waits for the drive status to be not "busy".
- * It then checks the status for all of the "good" bits and none
- * of the "bad" bits, and if all is okay it returns 0.  All other
- * cases return 1 after invoking ide_error() -- caller should just return.
+ * Busy-wait for the drive status to be not "busy".  Check then the status for
+ * all of the "good" bits and none of the "bad" bits, and if all is okay it
+ * returns 0.  All other cases return 1 after invoking ide_error() -- caller
+ * should just return.
  *
  * This routine should get fixed to not hog the cpu during extra long waits..
  * That could be done by busy-waiting for the first jiffy or two, and then
- * setting a timer to wake up at half second intervals thereafter,
- * until timeout is achieved, before timing out.
+ * setting a timer to wake up at half second intervals thereafter, until
+ * timeout is achieved, before timing out.
  */
-int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) {
+int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) {
 	byte stat;
 	int i;
 	unsigned long flags;
@@ -1020,98 +1061,14 @@
 }
 
 /*
- * execute_drive_cmd() issues a special drive command,
- * usually initiated by ioctl() from the external hdparm program.
- */
-static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
-{
-	if (rq->flags & REQ_DRIVE_TASKFILE) {
-		ide_task_t *args = rq->special;
-
-		if (!(args))
-			goto args_error;
-
-		do_taskfile(drive,
-				(struct hd_drive_task_hdr *)&args->tfRegister,
-				(struct hd_drive_hob_hdr *)&args->hobRegister,
-				args->handler);
-
-		if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
-		     (args->command_type == IDE_DRIVE_TASK_OUT)) &&
-		      args->prehandler && args->handler)
-			return args->prehandler(drive, rq);
-		return ide_started;
-
-	} else if (rq->flags & REQ_DRIVE_TASK) {
-		byte *args = rq->buffer;
-		byte sel;
-
-		if (!(args)) goto args_error;
-#ifdef DEBUG
-			printk("%s: DRIVE_TASK_CMD ", drive->name);
-			printk("cmd=0x%02x ", args[0]);
-			printk("fr=0x%02x ", args[1]);
-			printk("ns=0x%02x ", args[2]);
-			printk("sc=0x%02x ", args[3]);
-			printk("lcyl=0x%02x ", args[4]);
-			printk("hcyl=0x%02x ", args[5]);
-			printk("sel=0x%02x\n", args[6]);
-#endif
-		OUT_BYTE(args[1], IDE_FEATURE_REG);
-		OUT_BYTE(args[3], IDE_SECTOR_REG);
-		OUT_BYTE(args[4], IDE_LCYL_REG);
-		OUT_BYTE(args[5], IDE_HCYL_REG);
-		sel = (args[6] & ~0x10);
-		if (drive->select.b.unit)
-			sel |= 0x10;
-		OUT_BYTE(sel, IDE_SELECT_REG);
-		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
-		return ide_started;
-	} else if (rq->flags & REQ_DRIVE_CMD) {
-
-		byte *args = rq->buffer;
-		if (!(args)) goto args_error;
-#ifdef DEBUG
-		printk("%s: DRIVE_CMD ", drive->name);
-		printk("cmd=0x%02x ", args[0]);
-		printk("sc=0x%02x ", args[1]);
-		printk("fr=0x%02x ", args[2]);
-		printk("xx=0x%02x\n", args[3]);
-#endif
-		if (args[0] == WIN_SMART) {
-			OUT_BYTE(0x4f, IDE_LCYL_REG);
-			OUT_BYTE(0xc2, IDE_HCYL_REG);
-			OUT_BYTE(args[2],IDE_FEATURE_REG);
-			OUT_BYTE(args[1],IDE_SECTOR_REG);
-			ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
-			return ide_started;
-		}
-		OUT_BYTE(args[2],IDE_FEATURE_REG);
-		ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
-		return ide_started;
-	}
-
-args_error:
-	/*
-	 * NULL is actually a valid way of waiting for
-	 * all current requests to be flushed from the queue.
-	 */
-#ifdef DEBUG
-	printk("%s: DRIVE_CMD (null)\n", drive->name);
-#endif
-	ide_end_drive_cmd(drive, GET_STAT(), GET_ERR());
-	return ide_stopped;
-}
-
-/*
- * start_request() initiates handling of a new I/O request
+ * This initiates handling of a new I/O request.
  */
-static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t start_request(ide_drive_t *drive, struct request *rq)
 {
 	ide_startstop_t startstop;
 	unsigned long block;
 	unsigned int minor = minor(rq->rq_dev), unit = minor >> PARTN_BITS;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	BUG_ON(!(rq->flags & REQ_STARTED));
 
@@ -1144,15 +1101,110 @@
 	while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
 #endif
 
+	if (test_bit(IDE_DMA, &HWGROUP(drive)->flags))
+		printk("start_request: auch, DMA in progress 1\n");
 	SELECT_DRIVE(hwif, drive);
+	if (test_bit(IDE_DMA, &HWGROUP(drive)->flags))
+		printk("start_request: auch, DMA in progress 2\n");
 	if (ide_wait_stat(&startstop, drive, drive->ready_stat,
 			  BUSY_STAT|DRQ_STAT, WAIT_READY)) {
 		printk(KERN_WARNING "%s: drive not ready for command\n", drive->name);
 		return startstop;
 	}
+
+	/* FIXME: We can see nicely here that all commands should be submitted
+	 * through the request queue and that the special field in drive should
+	 * go as soon as possible!
+	 */
+
 	if (!drive->special.all) {
-		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE))
-			return execute_drive_cmd(drive, rq);
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
+			/* This issues a special drive command, usually
+			 * initiated by ioctl() from the external hdparm
+			 * program.
+			 */
+
+			if (rq->flags & REQ_DRIVE_TASKFILE) {
+				struct ata_request *ar = rq->special;
+				struct ata_taskfile *args;
+
+				if (!ar)
+					goto args_error;
+
+				args = &ar->ar_task;
+
+				ata_taskfile(drive, args, NULL);
+
+				if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
+					(args->command_type == IDE_DRIVE_TASK_OUT)) &&
+						args->prehandler && args->handler)
+					return args->prehandler(drive, rq);
+				return ide_started;
+
+			} else if (rq->flags & REQ_DRIVE_TASK) {
+				byte *args = rq->buffer;
+				byte sel;
+
+				if (!(args)) goto args_error;
+#ifdef DEBUG
+				printk("%s: DRIVE_TASK_CMD ", drive->name);
+				printk("cmd=0x%02x ", args[0]);
+				printk("fr=0x%02x ", args[1]);
+				printk("ns=0x%02x ", args[2]);
+				printk("sc=0x%02x ", args[3]);
+				printk("lcyl=0x%02x ", args[4]);
+				printk("hcyl=0x%02x ", args[5]);
+				printk("sel=0x%02x\n", args[6]);
+#endif
+				OUT_BYTE(args[1], IDE_FEATURE_REG);
+				OUT_BYTE(args[3], IDE_SECTOR_REG);
+				OUT_BYTE(args[4], IDE_LCYL_REG);
+				OUT_BYTE(args[5], IDE_HCYL_REG);
+				sel = (args[6] & ~0x10);
+				if (drive->select.b.unit)
+					sel |= 0x10;
+				OUT_BYTE(sel, IDE_SELECT_REG);
+				ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+				return ide_started;
+			} else if (rq->flags & REQ_DRIVE_CMD) {
+				byte *args = rq->buffer;
+				if (!(args)) goto args_error;
+#ifdef DEBUG
+				printk("%s: DRIVE_CMD ", drive->name);
+				printk("cmd=0x%02x ", args[0]);
+				printk("sc=0x%02x ", args[1]);
+				printk("fr=0x%02x ", args[2]);
+				printk("xx=0x%02x\n", args[3]);
+#endif
+				if (args[0] == WIN_SMART) {
+					OUT_BYTE(0x4f, IDE_LCYL_REG);
+					OUT_BYTE(0xc2, IDE_HCYL_REG);
+					OUT_BYTE(args[2],IDE_FEATURE_REG);
+					OUT_BYTE(args[1],IDE_SECTOR_REG);
+					ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
+
+					return ide_started;
+				}
+				OUT_BYTE(args[2],IDE_FEATURE_REG);
+				ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
+				return ide_started;
+			}
+
+args_error:
+			/*
+			 * NULL is actually a valid way of waiting for all
+			 * current requests to be flushed from the queue.
+			 */
+#ifdef DEBUG
+			printk("%s: DRIVE_CMD (null)\n", drive->name);
+#endif
+			ide_end_drive_cmd(drive, GET_STAT(), GET_ERR());
+			return ide_stopped;
+		}
+
+		/* The normal way of execution is to pass execute the request
+		 * handler.
+		 */
 
 		if (ata_ops(drive)) {
 			if (ata_ops(drive)->do_request)
@@ -1175,7 +1227,7 @@
 	return ide_stopped;
 }
 
-ide_startstop_t restart_request (ide_drive_t *drive)
+ide_startstop_t restart_request(ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	unsigned long flags;
@@ -1191,58 +1243,37 @@
 }
 
 /*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
+ * This is used by a drive to give excess bandwidth back to the hwgroup by
+ * sleeping for timeout jiffies.
  */
-void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
+void ide_stall_queue(ide_drive_t *drive, unsigned long timeout)
 {
 	if (timeout > WAIT_WORSTCASE)
 		timeout = WAIT_WORSTCASE;
-	drive->sleep = timeout + jiffies;
+	drive->PADAM_sleep = timeout + jiffies;
 }
 
-#define WAKEUP(drive)	((drive)->service_start + 2 * (drive)->service_time)
-
 /*
- * choose_drive() selects the next drive which will be serviced.
+ * Select the next drive which will be serviced.
  */
-static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
+static inline ide_drive_t *choose_drive(ide_hwgroup_t *hwgroup)
 {
 	ide_drive_t *drive, *best;
 
-repeat:
 	best = NULL;
 	drive = hwgroup->drive;
 	do {
-		if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
+		if (!list_empty(&drive->queue.queue_head)
+		&& (!drive->PADAM_sleep	|| time_after_eq(drive->PADAM_sleep, jiffies))) {
 			if (!best
-			 || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
-			 || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
+			 || (drive->PADAM_sleep && (!best->PADAM_sleep || time_after(best->PADAM_sleep, drive->PADAM_sleep)))
+			 || (!best->PADAM_sleep && time_after(best->PADAM_service_start + 2 * best->PADAM_service_time, drive->PADAM_service_start + 2 * drive->PADAM_service_time)))
 			{
 				if (!blk_queue_plugged(&drive->queue))
 					best = drive;
 			}
 		}
 	} while ((drive = drive->next) != hwgroup->drive);
-	if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
-		long t = (signed long)(WAKEUP(best) - jiffies);
-		if (t >= WAIT_MIN_SLEEP) {
-			/*
-			 * We *may* have some time to spare, but first let's see if
-			 * someone can potentially benefit from our nice mood today..
-			 */
-			drive = best->next;
-			do {
-				if (!drive->sleep
-				 && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
-				 && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
-				{
-					ide_stall_queue(best, min(t, 10L * WAIT_MIN_SLEEP));
-					goto repeat;
-				}
-			} while ((drive = drive->next) != best);
-		}
-	}
 	return best;
 }
 
@@ -1278,8 +1309,8 @@
  */
 static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
 {
-	ide_drive_t	*drive;
-	ide_hwif_t	*hwif;
+	ide_drive_t *drive;
+	struct ata_channel *hwif;
 	ide_startstop_t	startstop;
 	struct request	*rq;
 
@@ -1294,8 +1325,8 @@
 			hwgroup->rq = NULL;
 			drive = hwgroup->drive;
 			do {
-				if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
-					sleep = drive->sleep;
+				if (drive->PADAM_sleep && (!sleep || time_after(sleep, drive->PADAM_sleep)))
+					sleep = drive->PADAM_sleep;
 			} while ((drive = drive->next) != hwgroup->drive);
 			if (sleep) {
 				/*
@@ -1304,7 +1335,7 @@
 				 * play fairly with us, just in case there are big differences
 				 * in relative throughputs.. don't want to hog the cpu too much.
 				 */
-				if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) 
+				if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
 					sleep = jiffies + WAIT_MIN_SLEEP;
 #if 1
 				if (timer_pending(&hwgroup->timer))
@@ -1320,7 +1351,7 @@
 			}
 			return;		/* no more work for this hwgroup (for now) */
 		}
-		hwif = HWIF(drive);
+		hwif = drive->channel;
 		if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif && hwif->io_ports[IDE_CONTROL_OFFSET]) {
 			/* set nIEN for previous hwif */
 
@@ -1331,17 +1362,38 @@
 		}
 		hwgroup->hwif = hwif;
 		hwgroup->drive = drive;
-		drive->sleep = 0;
-		drive->service_start = jiffies;
+		drive->PADAM_sleep = 0;
+queue_next:
+		drive->PADAM_service_start = jiffies;
 
-		if (blk_queue_plugged(&drive->queue))
-			BUG();
+		if (test_bit(IDE_DMA, &hwgroup->flags)) {
+			printk("ide_do_request: DMA in progress...\n");
+			break;
+		}
+
+		/*
+		 * there's a small window between where the queue could be
+		 * replugged while we are in here when using tcq (in which
+		 * case the queue is probably empty anyways...), so check
+		 * and leave if appropriate. When not using tcq, this is
+		 * still a severe BUG!
+		 */
+		if (blk_queue_plugged(&drive->queue)) {
+			BUG_ON(!drive->using_tcq);
+			break;
+		}
 
 		/*
 		 * just continuing an interrupted request maybe
 		 */
 		rq = hwgroup->rq = elv_next_request(&drive->queue);
 
+		if (!rq) {
+			if (!ide_pending_commands(drive))
+				clear_bit(IDE_BUSY, &HWGROUP(drive)->flags);
+			break;
+		}
+
 		/*
 		 * Some systems have trouble with IDE IRQs arriving while
 		 * the driver is still setting things up.  So, here we disable
@@ -1352,25 +1404,34 @@
 		 */
 		if (masked_irq && hwif->irq != masked_irq)
 			disable_irq_nosync(hwif->irq);
+
 		spin_unlock(&ide_lock);
 		ide__sti();	/* allow other IRQs while we start this request */
 		startstop = start_request(drive, rq);
+
 		spin_lock_irq(&ide_lock);
 		if (masked_irq && hwif->irq != masked_irq)
 			enable_irq(hwif->irq);
-		if (startstop == ide_stopped)
+
+		if (startstop == ide_released)
+			goto queue_next;
+		else if (startstop == ide_stopped) {
+			if (test_bit(IDE_DMA, &hwgroup->flags))
+				printk("2nd illegal clear\n");
 			clear_bit(IDE_BUSY, &hwgroup->flags);
+		}
 	}
 }
 
 /*
  * Returns the queue which corresponds to a given device.
  */
-request_queue_t *ide_get_queue (kdev_t dev)
+request_queue_t *ide_get_queue(kdev_t dev)
 {
-	ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[major(dev)].data;
+	struct ata_channel *channel = (struct ata_channel *)blk_dev[major(dev)].data;
 
-	return &hwif->drives[DEVICE_NR(dev) & 1].queue;
+	/* FIXME: ALLERT: This discriminates between master and slave! */
+	return &channel->drives[DEVICE_NR(dev) & 1].queue;
 }
 
 /*
@@ -1385,25 +1446,43 @@
  * un-busy the hwgroup etc, and clear any pending DMA status. we want to
  * retry the current request in PIO mode instead of risking tossing it
  * all away
+ *
+ * FIXME: needs a bit of tcq work
  */
 void ide_dma_timeout_retry(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
-	struct request *rq;
+	struct ata_channel *hwif = drive->channel;
+	struct request *rq = NULL;
+	struct ata_request *ar = NULL;
+
+	if (drive->using_tcq) {
+		if (drive->tcq->active_tag != -1) {
+			ar = IDE_CUR_AR(drive);
+			rq = ar->ar_rq;
+		}
+	} else {
+		rq = HWGROUP(drive)->rq;
+		ar = rq->special;
+	}
 
 	/*
 	 * end current dma transaction
 	 */
-	hwif->dmaproc(ide_dma_end, drive);
+	if (rq)
+		hwif->dmaproc(ide_dma_end, drive);
 
 	/*
 	 * complain a little, later we might remove some of this verbosity
 	 */
-	printk("%s: timeout waiting for DMA\n", drive->name);
+	printk("%s: timeout waiting for DMA", drive->name);
+	if (drive->using_tcq)
+		printk(" queued, active tag %d", drive->tcq->active_tag);
+	printk("\n");
+
 	hwif->dmaproc(ide_dma_timeout, drive);
 
 	/*
-	 * disable dma for now, but remember that we did so because of
+	 * Disable dma for now, but remember that we did so because of
 	 * a timeout -- we'll reenable after we finish this next request
 	 * (or rather the first chunk of it) in pio.
 	 */
@@ -1415,21 +1494,31 @@
 	 * un-busy drive etc (hwgroup->busy is cleared on return) and
 	 * make sure request is sane
 	 */
-	rq = HWGROUP(drive)->rq;
 	HWGROUP(drive)->rq = NULL;
 
+	if (!rq)
+		return;
+
 	rq->errors = 0;
 	if (rq->bio) {
 		rq->sector = rq->bio->bi_sector;
 		rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
 		rq->buffer = NULL;
 	}
+
+	/*
+	 *  this request was not on the queue any more
+	 */
+	if (ar->ar_flags & ATA_AR_QUEUED) {
+		ata_ar_put(drive, ar);
+		_elv_add_request(&drive->queue, rq, 0, 0);
+	}
 }
 
 /*
- * ide_timer_expiry() is our timeout function for all drive operations.
- * But note that it can also be invoked as a result of a "sleep" operation
- * triggered by the mod_timer() call in ide_do_request.
+ * This is our timeout function for all drive operations.  But note that it can
+ * also be invoked as a result of a "sleep" operation triggered by the
+ * mod_timer() call in ide_do_request.
  */
 void ide_timer_expiry(unsigned long data)
 {
@@ -1461,7 +1550,7 @@
 			printk("ide_timer_expiry: hwgroup->drive was NULL\n");
 			hwgroup->handler = NULL;
 		} else {
-			ide_hwif_t *hwif;
+			struct ata_channel *hwif;
 			ide_startstop_t startstop;
 			/* paranoia */
 			if (!test_and_set_bit(IDE_BUSY, &hwgroup->flags))
@@ -1483,12 +1572,12 @@
 			 * mask the specific IRQ:
 			 */
 			spin_unlock(&ide_lock);
-			hwif  = HWIF(drive);
+			hwif  = drive->channel;
 #if DISABLE_IRQ_NOSYNC
 			disable_irq_nosync(hwif->irq);
 #else
 			disable_irq(hwif->irq);	/* disable_irq_nosync ?? */
-#endif /* DISABLE_IRQ_NOSYNC */
+#endif
 			__cli();	/* local CPU only, as if we were handling an interrupt */
 			if (hwgroup->poll_timeout != 0) {
 				startstop = handler(drive);
@@ -1506,7 +1595,7 @@
 					startstop = ide_error(drive, "irq timeout", GET_STAT());
 			}
 			set_recovery_timer(hwif);
-			drive->service_time = jiffies - drive->service_start;
+			drive->PADAM_service_time = jiffies - drive->PADAM_service_start;
 			enable_irq(hwif->irq);
 			spin_lock_irq(&ide_lock);
 			if (startstop == ide_stopped)
@@ -1540,10 +1629,10 @@
  * accidentally invoked as a result of any valid command completion interrupt.
  *
  */
-static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
+static void unexpected_intr(int irq, ide_hwgroup_t *hwgroup)
 {
-	byte stat;
-	ide_hwif_t *hwif = hwgroup->hwif;
+	u8 stat;
+	struct ata_channel *hwif = hwgroup->hwif;
 
 	/*
 	 * handle the unexpected interrupt
@@ -1568,11 +1657,11 @@
 /*
  * entry point for all interrupts, caller does __cli() for us
  */
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
+void ide_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	ide_handler_t *handler;
 	ide_startstop_t startstop;
@@ -1611,14 +1700,15 @@
 			 * Whack the status register, just in case we have a leftover pending IRQ.
 			 */
 			IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif
 		}
 		goto out_lock;
 	}
 	drive = hwgroup->drive;
 	if (!drive) {
 		/*
-		 * This should NEVER happen, and there isn't much we could do about it here.
+		 * This should NEVER happen, and there isn't much we could do
+		 * about it here.
 		 */
 		goto out_lock;
 	}
@@ -1650,11 +1740,13 @@
 	 * same irq as is currently being serviced here, and Linux
 	 * won't allow another of the same (on any CPU) until we return.
 	 */
-	set_recovery_timer(HWIF(drive));
-	drive->service_time = jiffies - drive->service_start;
+	set_recovery_timer(drive->channel);
+	drive->PADAM_service_time = jiffies - drive->PADAM_service_start;
 	if (startstop == ide_stopped) {
-		if (hwgroup->handler == NULL) {	/* paranoia */
+		if (hwgroup->handler == NULL) { /* paranoia */
 			clear_bit(IDE_BUSY, &hwgroup->flags);
+			if (test_bit(IDE_DMA, &hwgroup->flags))
+				printk("ide_intr: illegal clear\n");
 			ide_do_request(hwgroup, hwif->irq);
 		} else {
 			printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
@@ -1675,7 +1767,7 @@
 	int h;
 
 	for (h = 0; h < MAX_HWIFS; ++h) {
-		ide_hwif_t  *hwif = &ide_hwifs[h];
+		struct ata_channel *hwif = &ide_hwifs[h];
 		if (hwif->present && major == hwif->major) {
 			int unit = DEVICE_NR(i_rdev);
 			if (unit < MAX_DRIVES) {
@@ -1699,43 +1791,42 @@
 }
 
 /*
- * This function issues a special IDE device request
- * onto the request queue.
+ * This function issues a special IDE device request onto the request queue.
  *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed.  This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed.  As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
+ * If action is ide_wait, then the rq is queued at the end of the request
+ * queue, and the function sleeps until it has been processed.  This is for use
+ * when invoked from an ioctl handler.
+ *
+ * If action is ide_preempt, then the rq is queued at the head of the request
+ * queue, displacing the currently-being-processed request and this function
+ * returns immediately without waiting for the new rq to be completed.  This is
+ * VERY DANGEROUS, and is intended for careful use by the ATAPI tape/cdrom
+ * driver code.
+ *
+ * If action is ide_next, then the rq is queued immediately after the
+ * currently-being-processed-request (if any), and the function returns without
+ * waiting for the new rq to be completed.  As above, This is VERY DANGEROUS,
+ * and is intended for careful use by the ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the request queue,
+ * and the function returns immediately without waiting for the new rq to be
+ * completed. This is again intended for careful use by the ATAPI tape/cdrom
+ * driver code.
  */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action)
+int ide_do_drive_cmd(ide_drive_t *drive, struct request *rq, ide_action_t action)
 {
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	unsigned int major = HWIF(drive)->major;
+	unsigned int major = drive->channel->major;
 	request_queue_t *q = &drive->queue;
 	struct list_head *queue_head = &q->queue_head;
 	DECLARE_COMPLETION(wait);
 
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
+	if (drive->channel->chipset == ide_pdc4030 && rq->buffer != NULL)
 		return -ENOSYS;  /* special drive cmds not supported */
 #endif
+	rq->flags |= REQ_STARTED;
 	rq->errors = 0;
 	rq->rq_status = RQ_ACTIVE;
 	rq->rq_dev = mk_kdev(major,(drive->select.b.unit)<<PARTN_BITS);
@@ -1746,9 +1837,9 @@
 		if (action == ide_preempt)
 			hwgroup->rq = NULL;
 	} else {
-		if (action == ide_wait || action == ide_end) {
+		if (action == ide_wait || action == ide_end)
 			queue_head = queue_head->prev;
-		} else
+		else
 			queue_head = queue_head->next;
 	}
 	q->elevator.elevator_add_req_fn(q, rq, queue_head);
@@ -1812,7 +1903,7 @@
  */
 void revalidate_drives(void)
 {
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	int h;
 
@@ -1860,7 +1951,7 @@
 
 	/* Request a particular device type module.
 	 *
-	 * FIXME: The function which should rather requests the drivers is
+	 * FIXME: The function which should rather requests the drivers in
 	 * ide_driver_module(), since it seems illogical and even a bit
 	 * dangerous to delay this until open time!
 	 */
@@ -1935,29 +2026,28 @@
  * Note that we only release the standard ports, and do not even try to handle
  * any extra ports allocated for weird IDE interface chipsets.
  */
-static void hwif_unregister(ide_hwif_t *hwif)
+static void hwif_unregister(struct ata_channel *hwif)
 {
 	if (hwif->straight8) {
 		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-		goto jump_eight;
+	} else {
+		if (hwif->io_ports[IDE_DATA_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
+		if (hwif->io_ports[IDE_ERROR_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
+		if (hwif->io_ports[IDE_NSECTOR_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
+		if (hwif->io_ports[IDE_SECTOR_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
+		if (hwif->io_ports[IDE_LCYL_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
+		if (hwif->io_ports[IDE_HCYL_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
+		if (hwif->io_ports[IDE_SELECT_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
+		if (hwif->io_ports[IDE_STATUS_OFFSET])
+			ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
 	}
-	if (hwif->io_ports[IDE_DATA_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
-	if (hwif->io_ports[IDE_ERROR_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
-	if (hwif->io_ports[IDE_NSECTOR_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
-	if (hwif->io_ports[IDE_SECTOR_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_SECTOR_OFFSET], 1);
-	if (hwif->io_ports[IDE_LCYL_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_LCYL_OFFSET], 1);
-	if (hwif->io_ports[IDE_HCYL_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
-	if (hwif->io_ports[IDE_SELECT_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
-	if (hwif->io_ports[IDE_STATUS_OFFSET])
-		ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
-jump_eight:
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 #if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
@@ -1966,23 +2056,22 @@
 #endif
 }
 
-void ide_unregister(ide_hwif_t *hwif)
+void ide_unregister(struct ata_channel *channel)
 {
 	struct gendisk *gd;
 	ide_drive_t *drive, *d;
-	ide_hwif_t *g;
 	ide_hwgroup_t *hwgroup;
-	int irq_count = 0, unit, i;
+	int unit, i;
 	unsigned long flags;
 	unsigned int p, minor;
-	ide_hwif_t old_hwif;
+	struct ata_channel old_hwif;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	if (!hwif->present)
+	if (!channel->present)
 		goto abort;
-	put_device(&hwif->device);
+	put_device(&channel->dev);
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		drive = &hwif->drives[unit];
+		drive = &channel->drives[unit];
 		if (!drive->present)
 			continue;
 		if (drive->busy || drive->usage)
@@ -1995,43 +2084,47 @@
 				ide_unregister_subdriver(drive);
 		}
 	}
-	hwif->present = 0;
+	channel->present = 0;
 
 	/*
 	 * All clear?  Then blow away the buffer cache
 	 */
 	spin_unlock_irqrestore(&ide_lock, flags);
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		drive = &hwif->drives[unit];
+		drive = &channel->drives[unit];
 		if (!drive->present)
 			continue;
 		minor = drive->select.b.unit << PARTN_BITS;
 		for (p = 0; p < (1<<PARTN_BITS); ++p) {
 			if (drive->part[p].nr_sects > 0) {
-				kdev_t devp = mk_kdev(hwif->major, minor+p);
+				kdev_t devp = mk_kdev(channel->major, minor+p);
 				invalidate_device(devp, 0);
 			}
 		}
 	}
 #ifdef CONFIG_PROC_FS
-	destroy_proc_ide_drives(hwif);
+	destroy_proc_ide_drives(channel);
 #endif
 	spin_lock_irqsave(&ide_lock, flags);
-	hwgroup = hwif->hwgroup;
+	hwgroup = channel->hwgroup;
 
 	/*
 	 * free the irq if we were the only hwif using it
 	 */
-	g = hwgroup->hwif;
-	do {
-		if (g->irq == hwif->irq)
-			++irq_count;
-		g = g->next;
-	} while (g != hwgroup->hwif);
-	if (irq_count == 1)
-		free_irq(hwif->irq, hwgroup);
-
-	hwif_unregister(hwif);
+	{
+		struct ata_channel *g;
+		int irq_count = 0;
+
+		g = hwgroup->hwif;
+		do {
+			if (g->irq == channel->irq)
+				++irq_count;
+			g = g->next;
+		} while (g != hwgroup->hwif);
+		if (irq_count == 1)
+			free_irq(channel->irq, hwgroup);
+	}
+	hwif_unregister(channel);
 
 	/*
 	 * Remove us from the hwgroup, and free
@@ -2039,7 +2132,7 @@
 	 */
 	d = hwgroup->drive;
 	for (i = 0; i < MAX_DRIVES; ++i) {
-		drive = &hwif->drives[i];
+		drive = &channel->drives[i];
 		if (drive->de) {
 			devfs_unregister (drive->de);
 			drive->de = NULL;
@@ -2057,30 +2150,31 @@
 		}
 		drive->present = 0;
 		blk_cleanup_queue(&drive->queue);
+		ide_teardown_commandlist(drive);
 	}
 	if (d->present)
 		hwgroup->drive = d;
-	while (hwgroup->hwif->next != hwif)
+	while (hwgroup->hwif->next != channel)
 		hwgroup->hwif = hwgroup->hwif->next;
-	hwgroup->hwif->next = hwif->next;
-	if (hwgroup->hwif == hwif)
+	hwgroup->hwif->next = channel->next;
+	if (hwgroup->hwif == channel)
 		kfree(hwgroup);
 	else
-		hwgroup->hwif = HWIF(hwgroup->drive);
+		hwgroup->hwif = hwgroup->drive->channel;
 
 #if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI)
-	ide_release_dma(hwif);
+	ide_release_dma(channel);
 #endif
 
 	/*
-	 * Remove us from the kernel's knowledge
+	 * Remove us from the kernel's knowledge.
 	 */
-	unregister_blkdev(hwif->major, hwif->name);
-	kfree(blksize_size[hwif->major]);
-	blk_dev[hwif->major].data = NULL;
-	blk_dev[hwif->major].queue = NULL;
-	blk_clear(hwif->major);
-	gd = hwif->gd;
+	unregister_blkdev(channel->major, channel->name);
+	kfree(blksize_size[channel->major]);
+	blk_dev[channel->major].data = NULL;
+	blk_dev[channel->major].queue = NULL;
+	blk_clear(channel->major);
+	gd = channel->gd;
 	if (gd) {
 		del_gendisk(gd);
 		kfree(gd->sizes);
@@ -2090,45 +2184,45 @@
 		if (gd->flags)
 			kfree (gd->flags);
 		kfree(gd);
-		hwif->gd = NULL;
+		channel->gd = NULL;
 	}
 
 	/*
-	 * Reinitialize the hwif handler, but preserve any special methods for
+	 * Reinitialize the channel handler, but preserve any special methods for
 	 * it.
 	 */
 
-	old_hwif		= *hwif;
-	init_hwif_data(hwif, hwif->index);
-	hwif->hwgroup		= old_hwif.hwgroup;
-	hwif->tuneproc		= old_hwif.tuneproc;
-	hwif->speedproc		= old_hwif.speedproc;
-	hwif->selectproc	= old_hwif.selectproc;
-	hwif->resetproc		= old_hwif.resetproc;
-	hwif->intrproc		= old_hwif.intrproc;
-	hwif->maskproc		= old_hwif.maskproc;
-	hwif->quirkproc		= old_hwif.quirkproc;
-	hwif->rwproc		= old_hwif.rwproc;
-	hwif->ideproc		= old_hwif.ideproc;
-	hwif->dmaproc		= old_hwif.dmaproc;
-	hwif->busproc		= old_hwif.busproc;
-	hwif->bus_state		= old_hwif.bus_state;
-	hwif->dma_base		= old_hwif.dma_base;
-	hwif->dma_extra		= old_hwif.dma_extra;
-	hwif->config_data	= old_hwif.config_data;
-	hwif->select_data	= old_hwif.select_data;
-	hwif->proc		= old_hwif.proc;
+	old_hwif = *channel;
+	init_hwif_data(channel, channel->index);
+	channel->hwgroup = old_hwif.hwgroup;
+	channel->tuneproc = old_hwif.tuneproc;
+	channel->speedproc = old_hwif.speedproc;
+	channel->selectproc = old_hwif.selectproc;
+	channel->resetproc = old_hwif.resetproc;
+	channel->intrproc = old_hwif.intrproc;
+	channel->maskproc = old_hwif.maskproc;
+	channel->quirkproc = old_hwif.quirkproc;
+	channel->rwproc	= old_hwif.rwproc;
+	channel->ideproc = old_hwif.ideproc;
+	channel->dmaproc = old_hwif.dmaproc;
+	channel->busproc = old_hwif.busproc;
+	channel->bus_state = old_hwif.bus_state;
+	channel->dma_base = old_hwif.dma_base;
+	channel->dma_extra = old_hwif.dma_extra;
+	channel->config_data = old_hwif.config_data;
+	channel->select_data = old_hwif.select_data;
+	channel->proc = old_hwif.proc;
 #ifndef CONFIG_BLK_DEV_IDECS
-	hwif->irq		= old_hwif.irq;
+	channel->irq = old_hwif.irq;
 #endif
-	hwif->major		= old_hwif.major;
-	hwif->chipset		= old_hwif.chipset;
-	hwif->autodma		= old_hwif.autodma;
-	hwif->udma_four		= old_hwif.udma_four;
+	channel->major = old_hwif.major;
+	channel->chipset = old_hwif.chipset;
+	channel->autodma = old_hwif.autodma;
+	channel->udma_four = old_hwif.udma_four;
 #ifdef CONFIG_BLK_DEV_IDEPCI
-	hwif->pci_dev		= old_hwif.pci_dev;
+	channel->pci_dev = old_hwif.pci_dev;
 #endif
-	hwif->straight8		= old_hwif.straight8;
+	channel->straight8 = old_hwif.straight8;
 abort:
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
@@ -2155,7 +2249,7 @@
 				case IDE_IRQ_OFFSET:
 					hw->io_ports[i] = intr;
 					break;
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
+#endif
 				default:
 					hw->io_ports[i] = 0;
 					break;
@@ -2173,10 +2267,11 @@
  * Register an IDE interface, specifing exactly the registers etc
  * Set init=1 iff calling before probes have taken place.
  */
-int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp)
+int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp)
 {
-	int h, retry = 1;
-	ide_hwif_t *hwif;
+	int h;
+	int retry = 1;
+	struct ata_channel *hwif;
 
 	do {
 		for (h = 0; h < MAX_HWIFS; ++h) {
@@ -2186,14 +2281,16 @@
 		}
 		for (h = 0; h < MAX_HWIFS; ++h) {
 			hwif = &ide_hwifs[h];
-			if ((!hwif->present && !hwif->mate && !initializing) ||
+			if ((!hwif->present && (hwif->unit == ATA_PRIMARY) && !initializing) ||
 			    (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
 				goto found;
 		}
 		for (h = 0; h < MAX_HWIFS; ++h)
 			ide_unregister(&ide_hwifs[h]);
 	} while (retry--);
+
 	return -1;
+
 found:
 	ide_unregister(hwif);
 	if (hwif->present)
@@ -2219,7 +2316,7 @@
 }
 
 /*
- * Compatability function with existing drivers.  If you want
+ * Compatability function for existing drivers.  If you want
  * something different, use the function above.
  */
 int ide_register(int arg1, int arg2, int irq)
@@ -2230,7 +2327,7 @@
 	return ide_register_hw(&hw, NULL);
 }
 
-void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
 {
 	ide_settings_t **p = &drive->settings;
 	ide_settings_t *setting = NULL;
@@ -2375,8 +2472,8 @@
 {
 	drive->io_32bit = arg;
 #ifdef CONFIG_BLK_DEV_DTC2278
-	if (HWIF(drive)->chipset == ide_dtc2278)
-		HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
+	if (drive->channel->chipset == ide_dtc2278)
+		drive->channel->drives[!drive->select.b.unit].io_32bit = arg;
 #endif /* CONFIG_BLK_DEV_DTC2278 */
 	return 0;
 }
@@ -2385,9 +2482,9 @@
 {
 	if (!drive->driver)
 		return -EPERM;
-	if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
+	if (!drive->id || !(drive->id->capability & 1) || !drive->channel->dmaproc)
 		return -EPERM;
-	if (HWIF(drive)->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))
+	if (drive->channel->dmaproc(arg ? ide_dma_on : ide_dma_off, drive))
 		return -EIO;
 	return 0;
 }
@@ -2396,25 +2493,22 @@
 {
 	struct request rq;
 
-	if (!HWIF(drive)->tuneproc)
+	if (!drive->channel->tuneproc)
 		return -ENOSYS;
 	if (drive->special.b.set_tune)
 		return -EBUSY;
 	ide_init_drive_cmd(&rq);
 	drive->tune_req = (byte) arg;
 	drive->special.b.set_tune = 1;
-	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
+	ide_do_drive_cmd(drive, &rq, ide_wait);
 	return 0;
 }
 
 void ide_add_generic_settings (ide_drive_t *drive)
 {
-/*
- *			drive	setting name		read/write access				read ioctl		write ioctl		data type	min	max				mul_factor	div_factor	data pointer			set function
- */
+/*			drive	setting name		read/write access				read ioctl		write ioctl		data type	min	max				mul_factor	div_factor	data pointer			set function */
 	ide_add_setting(drive,	"io_32bit",		drive->no_io_32bit ? SETTING_READ : SETTING_RW,	HDIO_GET_32BIT,		HDIO_SET_32BIT,		TYPE_BYTE,	0,	1 + (SUPPORT_VLB_SYNC << 1),	1,		1,		&drive->io_32bit,		set_io_32bit);
 	ide_add_setting(drive,	"keepsettings",		SETTING_RW,					HDIO_GET_KEEPSETTINGS,	HDIO_SET_KEEPSETTINGS,	TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL);
-	ide_add_setting(drive,	"nice1",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL);
 	ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					-1,			HDIO_SET_PIO_MODE,	TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode);
 	ide_add_setting(drive,	"slow",			SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->slow,			NULL);
 	ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	HDIO_GET_UNMASKINTR,	HDIO_SET_UNMASKINTR,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL);
@@ -2540,25 +2634,22 @@
 
 		case HDIO_GET_NICE:
 			return put_user(drive->dsc_overlap	<<	IDE_NICE_DSC_OVERLAP	|
-					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP	|
-					drive->nice0		<< 	IDE_NICE_0		|
-					drive->nice1		<<	IDE_NICE_1		|
-					drive->nice2		<<	IDE_NICE_2,
+					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP,
 					(long *) arg);
 
 		case HDIO_DRIVE_CMD:
 			if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 				return -EACCES;
-			return ide_cmd_ioctl(drive, inode, file, cmd, arg);
+			return ide_cmd_ioctl(drive, arg);
 
 		case HDIO_DRIVE_TASK:
 			if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
 				return -EACCES;
-			return ide_task_ioctl(drive, inode, file, cmd, arg);
+			return ide_task_ioctl(drive, arg);
 
 		case HDIO_SET_NICE:
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+			if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP))))
 				return -EPERM;
 			drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
 			/* Only CD-ROM's and tapes support DSC overlap. */
@@ -2566,7 +2657,6 @@
 				drive->dsc_overlap = 0;
 				return -EPERM;
 			}
-			drive->nice1 = (arg >> IDE_NICE_1) & 1;
 			return 0;
 		case BLKGETSIZE:
 		case BLKGETSIZE64:
@@ -2591,15 +2681,15 @@
 		case HDIO_GET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			if (put_user(HWIF(drive)->bus_state, (long *)arg))
+			if (put_user(drive->channel->bus_state, (long *)arg))
 				return -EFAULT;
 			return 0;
 
 		case HDIO_SET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			if (HWIF(drive)->busproc)
-				HWIF(drive)->busproc(drive, (int)arg);
+			if (drive->channel->busproc)
+				drive->channel->busproc(drive, (int)arg);
 			return 0;
 
 		default:
@@ -2609,21 +2699,105 @@
 	}
 }
 
+void ide_teardown_commandlist(ide_drive_t *drive)
+{
+	struct pci_dev *pdev= drive->channel->pci_dev;
+	struct list_head *entry;
+
+	list_for_each(entry, &drive->free_req) {
+		struct ata_request *ar = list_ata_entry(entry);
+
+		list_del(&ar->ar_queue);
+		kfree(ar->ar_sg_table);
+		pci_free_consistent(pdev, PRD_SEGMENTS * PRD_BYTES, ar->ar_dmatable_cpu, ar->ar_dmatable);
+		kfree(ar);
+	}
+}
+
+int ide_build_commandlist(ide_drive_t *drive)
+{
+	struct pci_dev *pdev= drive->channel->pci_dev;
+	struct ata_request *ar;
+	ide_tag_info_t *tcq;
+	int i, err;
+
+	tcq = kmalloc(sizeof(ide_tag_info_t), GFP_ATOMIC);
+	if (!tcq)
+		return -ENOMEM;
+
+	drive->tcq = tcq;
+	memset(drive->tcq, 0, sizeof(ide_tag_info_t));
+
+	INIT_LIST_HEAD(&drive->free_req);
+	drive->using_tcq = 0;
+
+	err = -ENOMEM;
+	for (i = 0; i < drive->queue_depth; i++) {
+		/* Having kzmalloc would help reduce code size at quite
+		 * many places in kernel. */
+		ar = kmalloc(sizeof(*ar), GFP_ATOMIC);
+		if (!ar)
+			break;
+
+		memset(ar, 0, sizeof(*ar));
+		INIT_LIST_HEAD(&ar->ar_queue);
+
+		ar->ar_sg_table = kmalloc(PRD_SEGMENTS * sizeof(struct scatterlist), GFP_ATOMIC);
+		if (!ar->ar_sg_table) {
+			kfree(ar);
+			break;
+		}
+
+		ar->ar_dmatable_cpu = pci_alloc_consistent(pdev, PRD_SEGMENTS * PRD_BYTES, &ar->ar_dmatable);
+		if (!ar->ar_dmatable_cpu) {
+			kfree(ar->ar_sg_table);
+			kfree(ar);
+			break;
+		}
+
+		/*
+		 * pheew, all done, add to list
+		 */
+		list_add_tail(&ar->ar_queue, &drive->free_req);
+	}
+
+	if (i) {
+		drive->queue_depth = i;
+		if (i >= 1) {
+			drive->using_tcq = 1;
+			drive->tcq->queued = 0;
+			drive->tcq->active_tag = -1;
+			return 0;
+		}
+
+		kfree(drive->tcq);
+		drive->tcq = NULL;
+		err = 0;
+	}
+
+	kfree(drive->tcq);
+	drive->tcq = NULL;
+	return err;
+}
+
 static int ide_check_media_change (kdev_t i_rdev)
 {
 	ide_drive_t *drive;
+	int res = 0; /* not changed */
 
-	if ((drive = get_info_ptr(i_rdev)) == NULL)
+	drive = get_info_ptr(i_rdev);
+	if (!drive)
 		return -ENODEV;
+
 	if (ata_ops(drive)) {
 		ata_get(ata_ops(drive));
 		if (ata_ops(drive)->check_media_change)
-			return ata_ops(drive)->check_media_change(drive);
+			res = ata_ops(drive)->check_media_change(drive);
 		else
-			return 1; /* assume it was changed */
+			res = 1; /* assume it was changed */
 		ata_put(ata_ops(drive));
 	}
-	return 0;
+	return res;
 }
 
 void ide_fixstring (byte *s, const int bytecount, const int byteswap)
@@ -2653,6 +2827,10 @@
 		*p++ = '\0';
 }
 
+/****************************************************************************
+ * FIXME: rewrite the following crap:
+ */
+
 /*
  * stridx() returns the offset of c within s,
  * or -1 if c is '\0' or not found within s.
@@ -2660,11 +2838,12 @@
 static int __init stridx (const char *s, char c)
 {
 	char *i = strchr(s, c);
+
 	return (i && c) ? i - s : -1;
 }
 
 /*
- * match_parm() does parsing for ide_setup():
+ * Parsing for ide_setup():
  *
  * 1. the first char of s must be '='.
  * 2. if the remainder matches one of the supplied keywords,
@@ -2802,7 +2981,7 @@
 int __init ide_setup (char *s)
 {
 	int i, vals[3];
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	unsigned int hw, unit;
 	const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
@@ -2825,6 +3004,7 @@
 
 		printk(" : Enabled support for IDE doublers\n");
 		ide_doubler = 1;
+
 		return 1;
 	}
 #endif
@@ -2832,6 +3012,7 @@
 	if (!strcmp(s, "ide=nodma")) {
 		printk("IDE: Prevented DMA\n");
 		noautodma = 1;
+
 		return 1;
 	}
 
@@ -2839,14 +3020,15 @@
 	if (!strcmp(s, "ide=reverse")) {
 		ide_scan_direction = 1;
 		printk(" : Enabled support for IDE inverse scan order.\n");
+
 		return 1;
 	}
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif
 
 	/*
 	 * Look for drive options:  "hdx="
 	 */
-	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
+	if (!strncmp(s, "hd", 2) && s[2] >= 'a' && s[2] <= max_drive) {
 		const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
 				"serialize", "autotune", "noautotune",
 				"slow", "swapdata", "bswap", "flash",
@@ -2863,7 +3045,7 @@
 		/*
 		 * Look for last lun option:  "hdxlun="
 		 */
-		if (s[3] == 'l' && s[4] == 'u' && s[5] == 'n') {
+		if (!strncmp(&s[3], "lun", 3)) {
 			if (match_parm(&s[6], NULL, vals, 1) != 1)
 				goto bad_option;
 			if (vals[0] >= 0 && vals[0] <= 7) {
@@ -2920,7 +3102,7 @@
 #else
 				drive->scsi = 0;
 				goto bad_option;
-#endif /* defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI) */
+#endif
 			case 3: /* cyl,head,sect */
 				drive->type	= ATA_DISK;
 				drive->cyl	= drive->bios_cyl  = vals[0];
@@ -2935,12 +3117,10 @@
 		}
 	}
 
-	if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
-		goto bad_option;
 	/*
 	 * Look for bus speed option:  "idebus="
 	 */
-	if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
+	if (strncmp(s, "idebus", 6)) {
 		if (match_parm(&s[6], NULL, vals, 1) != 1)
 			goto bad_option;
 		if (vals[0] >= 20 && vals[0] <= 66) {
@@ -2949,13 +3129,14 @@
 			printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
 		goto done;
 	}
+
 	/*
 	 * Look for interface options:  "idex="
 	 */
-	if (s[3] >= '0' && s[3] <= max_hwif) {
+	if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_hwif) {
 		/*
 		 * Be VERY CAREFUL changing this: note hardcoded indexes below
-		 * -8,-9,-10 : are reserved for future idex calls to ease the hardcoding.
+		 * -8,-9,-10. -11 : are reserved for future idex calls to ease the hardcoding.
 		 */
 		const char *ide_words[] = {
 			"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66",
@@ -2963,6 +3144,7 @@
 			"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
 		hw = s[3] - '0';
 		hwif = &ide_hwifs[hw];
+
 		i = match_parm(&s[4], ide_words, vals, 3);
 
 		/*
@@ -2994,7 +3176,7 @@
 				init_ali14xx();
 				goto done;
 			}
-#endif /* CONFIG_BLK_DEV_ALI14XX */
+#endif
 #ifdef CONFIG_BLK_DEV_UMC8672
 			case -16: /* "umc8672" */
 			{
@@ -3002,7 +3184,7 @@
 				init_umc8672();
 				goto done;
 			}
-#endif /* CONFIG_BLK_DEV_UMC8672 */
+#endif
 #ifdef CONFIG_BLK_DEV_DTC2278
 			case -15: /* "dtc2278" */
 			{
@@ -3010,7 +3192,7 @@
 				init_dtc2278();
 				goto done;
 			}
-#endif /* CONFIG_BLK_DEV_DTC2278 */
+#endif
 #ifdef CONFIG_BLK_DEV_CMD640
 			case -14: /* "cmd640_vlb" */
 			{
@@ -3018,7 +3200,7 @@
 				cmd640_vlb = 1;
 				goto done;
 			}
-#endif /* CONFIG_BLK_DEV_CMD640 */
+#endif
 #ifdef CONFIG_BLK_DEV_HT6560B
 			case -13: /* "ht6560b" */
 			{
@@ -3026,7 +3208,7 @@
 				init_ht6560b();
 				goto done;
 			}
-#endif /* CONFIG_BLK_DEV_HT6560B */
+#endif
 #if CONFIG_BLK_DEV_QD65XX
 			case -12: /* "qd65xx" */
 			{
@@ -3034,7 +3216,7 @@
 				init_qd65xx();
 				goto done;
 			}
-#endif /* CONFIG_BLK_DEV_QD65XX */
+#endif
 			case -11: /* minus11 */
 			case -10: /* minus10 */
 			case -9: /* minus9 */
@@ -3044,10 +3226,10 @@
 #ifdef CONFIG_BLK_DEV_IDEPCI
 				hwif->udma_four = 1;
 				goto done;
-#else /* !CONFIG_BLK_DEV_IDEPCI */
+#else
 				hwif->udma_four = 0;
 				goto bad_hwif;
-#endif /* CONFIG_BLK_DEV_IDEPCI */
+#endif
 			case -6: /* dma */
 				hwif->autodma = 1;
 				goto done;
@@ -3064,9 +3246,13 @@
 				goto done;
 			case -2: /* "serialize" */
 			do_serialize:
-				hwif->mate = &ide_hwifs[hw^1];
-				hwif->mate->mate = hwif;
-				hwif->serialized = hwif->mate->serialized = 1;
+				{
+					struct ata_channel *mate;
+
+					mate = &ide_hwifs[hw ^ 1];
+					hwif->serialized = 1;
+					mate->serialized = 1;
+				}
 				goto done;
 
 			case -1: /* "noprobe" */
@@ -3092,16 +3278,22 @@
 				return 1;
 		}
 	}
+
 bad_option:
 	printk(" -- BAD OPTION\n");
 	return 1;
+
 bad_hwif:
 	printk("-- NOT SUPPORTED ON ide%d", hw);
+
 done:
 	printk("\n");
+
 	return 1;
 }
 
+/****************************************************************************/
+
 /* This is the default end request function as well */
 int ide_end_request(ide_drive_t *drive, int uptodate)
 {
@@ -3116,7 +3308,7 @@
 	unsigned int unit, index, i;
 
 	for (index = 0, i = 0; index < MAX_HWIFS; ++index) {
-		ide_hwif_t *hwif = &ide_hwifs[index];
+		struct ata_channel *hwif = &ide_hwifs[index];
 		if (!hwif->present)
 			continue;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
@@ -3146,7 +3338,7 @@
 	}
 
 	/* FIXME: This will be pushed to the drivers! Thus allowing us to
-	 * save one parameter here eparate this out.
+	 * save one parameter here separate this out.
 	 */
 
 	drive->driver = driver;
@@ -3154,7 +3346,7 @@
 	restore_flags(flags);		/* all CPUs */
 	/* FIXME: Check what this magic number is supposed to be about? */
 	if (drive->autotune != 2) {
-		if (HWIF(drive)->dmaproc != NULL) {
+		if (drive->channel->dmaproc != NULL) {
 
 			/*
 			 * Force DMAing for the beginning of the check.  Some
@@ -3164,13 +3356,15 @@
 			 *   PARANOIA!!!
 			 */
 
-			HWIF(drive)->dmaproc(ide_dma_off_quietly, drive);
-			HWIF(drive)->dmaproc(ide_dma_check, drive);
+			drive->channel->dmaproc(ide_dma_off_quietly, drive);
+			drive->channel->dmaproc(ide_dma_check, drive);
+#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
+			drive->channel->dmaproc(ide_dma_queued_on, drive);
+#endif /* CONFIG_BLK_DEV_IDE_TCQ_DEFAULT */
 		}
 		/* Only CD-ROMs and tape drives support DSC overlap. */
 		drive->dsc_overlap = (drive->next != drive
 				&& (drive->type == ATA_ROM || drive->type == ATA_TAPE));
-		drive->nice1 = 1;
 	}
 	drive->revalidate = 1;
 	drive->suspend_reset = 0;
@@ -3193,10 +3387,19 @@
 
 	save_flags(flags);		/* all CPUs */
 	cli();				/* all CPUs */
-	if (drive->usage || drive->busy || !ata_ops(drive) || ata_ops(drive)->busy) {
+
+#if 0
+	if (__MOD_IN_USE(ata_ops(drive)->owner)) {
+		restore_flags(flags);
+		return 1;
+	}
+#endif
+
+	if (drive->usage || drive->busy || !ata_ops(drive)) {
 		restore_flags(flags);	/* all CPUs */
 		return 1;
 	}
+
 #if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
 	pnpide_init(0);
 #endif
@@ -3207,7 +3410,10 @@
 #endif
 	auto_remove_settings(drive);
 	drive->driver = NULL;
+	drive->present = 0;
+
 	restore_flags(flags);		/* all CPUs */
+
 	return 0;
 }
 
@@ -3297,7 +3503,7 @@
 
 static int ide_notify_reboot (struct notifier_block *this, unsigned long event, void *x)
 {
-	ide_hwif_t *hwif;
+	struct ata_channel *hwif;
 	ide_drive_t *drive;
 	int i, unit;
 
@@ -3316,6 +3522,7 @@
 		hwif = &ide_hwifs[i];
 		if (!hwif->present)
 			continue;
+
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
 			drive = &hwif->drives[unit];
 			if (!drive->present)
@@ -3479,12 +3686,13 @@
 	initializing = 0;
 
 	for (h = 0; h < MAX_HWIFS; ++h) {
-		ide_hwif_t  *hwif = &ide_hwifs[h];
-		if (hwif->present)
-			ide_geninit(hwif);
+		struct ata_channel *channel = &ide_hwifs[h];
+		if (channel->present)
+			ide_geninit(channel);
 	}
 
 	register_reboot_notifier(&ide_notifier);
+
 	return 0;
 }
 
diff -Nru a/drivers/ide/it8172.c b/drivers/ide/it8172.c
--- a/drivers/ide/it8172.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/it8172.c	Sun Apr 14 12:16:55 2002
@@ -53,7 +53,7 @@
 static int it8172_config_drive_for_dma (ide_drive_t *drive);
 static int it8172_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
 #endif
-void __init ide_init_it8172 (ide_hwif_t *hwif);
+void __init ide_init_it8172(struct ata_channel *channel);
 
 
 static void it8172_tune_drive (ide_drive_t *drive, byte pio)
@@ -61,7 +61,7 @@
     unsigned long flags;
     u16 master_data;
     u32 slave_data;
-    int is_slave	= (&HWIF(drive)->drives[1] == drive);
+    int is_slave	= (&drive->channel->drives[1] == drive);
     int master_port	= 0x40;
     int slave_port      = 0x44;
 
@@ -70,8 +70,8 @@
     else
        pio = min_t(byte, pio, 4);
 
-    pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
-    pci_read_config_dword(HWIF(drive)->pci_dev, slave_port, &slave_data);
+    pci_read_config_word(drive->channel->pci_dev, master_port, &master_data);
+    pci_read_config_dword(drive->channel->pci_dev, slave_port, &slave_data);
 
     /*
      * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44
@@ -94,7 +94,7 @@
 
     save_flags(flags);
     cli();
-    pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
+    pci_write_config_word(drive->channel->pci_dev, master_port, master_data);
     restore_flags(flags);
 }
 
@@ -133,7 +133,7 @@
 
 static int it8172_tune_chipset (ide_drive_t *drive, byte speed)
 {
-    ide_hwif_t *hwif	= HWIF(drive);
+    struct ata_channel *hwif = drive->channel;
     struct pci_dev *dev	= hwif->pci_dev;
     int a_speed		= 3 << (drive->dn * 4);
     int u_flag		= 1 << drive->dn;
@@ -231,7 +231,7 @@
 }
 
 
-void __init ide_init_it8172 (ide_hwif_t *hwif)
+void __init ide_init_it8172(struct ata_channel *hwif)
 {
     struct pci_dev* dev = hwif->pci_dev;
     unsigned long cmdBase, ctrlBase;
diff -Nru a/drivers/ide/macide.c b/drivers/ide/macide.c
--- a/drivers/ide/macide.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/macide.c	Sun Apr 14 12:16:55 2002
@@ -69,7 +69,7 @@
     IDE_HCYL, IDE_SELECT, IDE_STATUS,  IDE_CONTROL
 };
 
-int macide_ack_intr(ide_hwif_t* hwif)
+int macide_ack_intr(struct ata_channel *hwif)
 {
 	if (*ide_ifr & 0x20) {
 		*ide_ifr &= ~0x20;
diff -Nru a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
--- a/drivers/ide/ns87415.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/ns87415.c	Sun Apr 14 12:16:57 2002
@@ -28,12 +28,12 @@
 
 /*
  * This routine either enables/disables (according to drive->present)
- * the IRQ associated with the port (HWIF(drive)),
+ * the IRQ associated with the port (drive->channel),
  * and selects either PIO or DMA handshaking for the next I/O operation.
  */
 static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned long flags;
@@ -43,12 +43,12 @@
 	new = *old;
 
 	/* Adjust IRQ enable bit */
-	bit = 1 << (8 + hwif->channel);
+	bit = 1 << (8 + hwif->unit);
 	new = drive->present ? (new & ~bit) : (new | bit);
 
 	/* Select PIO or DMA, DMA may only be selected for one drive/channel. */
-	bit   = 1 << (20 + drive->select.b.unit       + (hwif->channel << 1));
-	other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->channel << 1));
+	bit   = 1 << (20 + drive->select.b.unit       + (hwif->unit << 1));
+	other = 1 << (20 + (1 - drive->select.b.unit) + (hwif->unit << 1));
 	new = use_dma ? ((new & ~other) | bit) : (new & ~bit);
 
 	if (new != *old) {
@@ -84,7 +84,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t	*hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	byte		dma_stat;
 
 	switch (func) {
@@ -112,7 +112,7 @@
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-void __init ide_init_ns87415 (ide_hwif_t *hwif)
+void __init ide_init_ns87415(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned int ctrl, using_inta;
@@ -138,14 +138,24 @@
 	(void) pci_read_config_dword(dev, 0x40, &ctrl);
 	(void) pci_read_config_byte(dev, 0x09, &progif);
 	/* is irq in "native" mode? */
-	using_inta = progif & (1 << (hwif->channel << 1));
+	using_inta = progif & (1 << (hwif->unit << 1));
 	if (!using_inta)
-		using_inta = ctrl & (1 << (4 + hwif->channel));
-	if (hwif->mate) {
-		hwif->select_data = hwif->mate->select_data;
+		using_inta = ctrl & (1 << (4 + hwif->unit));
+	if (hwif->unit == ATA_SECONDARY) {
+
+		/* FIXME: If we are initializing the secondary channel, let us
+		 * assume that the primary channel got initialized just a tad
+		 * bit before now.  It would be much cleaner if the data in
+		 * ns87415_control just got duplicated.
+		 */
+
+		if (!hwif->select_data)
+		    hwif->select_data = (unsigned long)
+			&ns87415_control[ns87415_count - 1];
 	} else {
-		hwif->select_data = (unsigned long)
-					&ns87415_control[ns87415_count++];
+		if (!hwif->select_data)
+		    hwif->select_data = (unsigned long)
+			&ns87415_control[ns87415_count++];
 		ctrl |= (1 << 8) | (1 << 9);	/* mask both IRQs */
 		if (using_inta)
 			ctrl &= ~(1 << 6);	/* unmask INTA */
@@ -170,9 +180,9 @@
 		do {
 			udelay(50);
 			stat = inb(hwif->io_ports[IDE_STATUS_OFFSET]);
-                	if (stat == 0xff)
-                        	break;
-        	} while ((stat & BUSY_STAT) && --timeout);
+			if (stat == 0xff)
+				break;
+		} while ((stat & BUSY_STAT) && --timeout);
 #endif
 	}
 
@@ -180,14 +190,24 @@
 		outb(0x60, hwif->dma_base + 2);
 
 	if (!using_inta)
-		hwif->irq = hwif->channel ? 15 : 14;	/* legacy mode */
-	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-		hwif->irq = hwif->mate->irq;	/* share IRQ with mate */
+		hwif->irq = hwif->unit ? 15 : 14;	/* legacy mode */
+	else {
+		static int primary_irq = 0;
+
+		/* Ugly way to let the primary and secondary channel on the
+		 * chip use the same IRQ line.
+		 */
+
+		if (hwif->unit == ATA_PRIMARY)
+			primary_irq = hwif->irq;
+		else if (!hwif->irq)
+			hwif->irq = primary_irq;
+	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base)
 		hwif->dmaproc = &ns87415_dmaproc;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif
 
 	hwif->selectproc = &ns87415_selectproc;
 }
diff -Nru a/drivers/ide/opti621.c b/drivers/ide/opti621.c
--- a/drivers/ide/opti621.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/opti621.c	Sun Apr 14 12:16:56 2002
@@ -142,7 +142,7 @@
  */
 {
 	int d;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	if (pio == PIO_DONT_KNOW)
 		drive->drive_data = min(ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0, OPTI621_MAX_PIO);
@@ -252,7 +252,7 @@
 	pio_clocks_t first, second;
 	int ax, drdy;
 	byte cycle1, cycle2, misc;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	/* sets drive->drive_data for both drives */
 	compute_pios(drive, pio);
@@ -310,7 +310,7 @@
 /*
  * ide_init_opti621() is called once for each hwif found at boot.
  */
-void __init ide_init_opti621 (ide_hwif_t *hwif)
+void __init ide_init_opti621(struct ata_channel *hwif)
 {
 	hwif->drives[0].drive_data = PIO_DONT_KNOW;
 	hwif->drives[1].drive_data = PIO_DONT_KNOW;
diff -Nru a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c
--- a/drivers/ide/pdc202xx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/ide/pdc202xx.c	Sun Apr 14 12:16:59 2002
@@ -217,6 +217,9 @@
 		case PCI_DEVICE_ID_PROMISE_20275:
 			p += sprintf(p, "\n                                PDC20275 Chipset.\n");
 			break;
+		case PCI_DEVICE_ID_PROMISE_20276:
+			p += sprintf(p, "\n                                PDC20276 Chipset.\n");
+			break;
 		case PCI_DEVICE_ID_PROMISE_20269:
 			p += sprintf(p, "\n                                PDC20269 TX2 Chipset.\n");
 			break;
@@ -236,6 +239,7 @@
 	char *p = buffer;
 	switch(bmide_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_PROMISE_20268R:
@@ -395,8 +399,8 @@
 
 static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	struct pci_dev *dev	= hwif->pci_dev;
+	struct ata_channel *hwif = drive->channel;
+	struct pci_dev *dev = hwif->pci_dev;
 
 	unsigned int		drive_conf;
 	int			err;
@@ -519,14 +523,14 @@
 
 static int pdc202xx_new_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	unsigned long indexreg	= (hwif->dma_base + 1);
 	unsigned long datareg	= (hwif->dma_base + 3);
 #else
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16	= pci_resource_start(dev, 4);
-	unsigned long indexreg	= high_16 + (hwif->channel ? 0x09 : 0x01);
+	unsigned long indexreg	= high_16 + (hwif->unit ? 0x09 : 0x01);
 	unsigned long datareg	= (indexreg + 2);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 	byte thold		= 0x10;
@@ -660,6 +664,7 @@
 			OUT_BYTE(0xac, datareg);
 			break;
 		default:
+			;
 	}
 
 	if (!drive->init_speed)
@@ -698,7 +703,7 @@
 static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
 	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16   = pci_resource_start(dev, 4);
 	unsigned long dma_base  = hwif->dma_base;
@@ -720,8 +725,8 @@
 	byte udma_66		= ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0;
 	byte udma_100		= 0;
 	byte udma_133		= 0;
-	byte mask		= hwif->channel ? 0x08 : 0x02;
-	unsigned short c_mask	= hwif->channel ? (1<<11) : (1<<10);
+	byte mask		= hwif->unit ? 0x08 : 0x02;
+	unsigned short c_mask	= hwif->unit ? (1<<11) : (1<<10);
 
 	byte ultra_66		= ((id->dma_ultra & 0x0010) ||
 				   (id->dma_ultra & 0x0008)) ? 1 : 0;
@@ -732,6 +737,7 @@
 
 	switch(dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 			udma_133 = (udma_66) ? 1 : 0;
 			udma_100 = (udma_66) ? 1 : 0;
@@ -786,14 +792,14 @@
 
 	if (((ultra_66) || (ultra_100) || (ultra_133)) && (cable)) {
 #ifdef DEBUG
-		printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary" : "Primary");
+		printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->unit ? "Secondary" : "Primary");
 		printk("         Switching to Ultra33 mode.\n");
 #endif /* DEBUG */
 		/* Primary   : zero out second bit */
 		/* Secondary : zero out fourth bit */
 		if (!jumpbit)
 			OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11));
-		printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary");
+		printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->unit ? "Secondary":"Primary");
 		printk("%s reduced to Ultra33 mode.\n", drive->name);
 		udma_66 = 0; udma_100 = 0; udma_133 = 0;
 	} else {
@@ -918,7 +924,7 @@
 static int config_drive_xfer_rate (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	ide_dma_action_t dma_func = ide_dma_off_quietly;
 
 	if (id && (id->capability & 1) && hwif->autodma) {
@@ -963,7 +969,7 @@
 		(void) config_chipset_for_pio(drive, 5);
 	}
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 int pdc202xx_quirkproc (ide_drive_t *drive)
@@ -981,14 +987,15 @@
 	byte newchip		= 0;
 	byte clock		= 0;
 	byte hardware48hack	= 0;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16	= pci_resource_start(dev, 4);
-	unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x00);
+	unsigned long atapi_reg	= high_16 + (hwif->unit ? 0x24 : 0x00);
 	unsigned long dma_base	= hwif->dma_base;
 
 	switch (dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268R:
 		case PCI_DEVICE_ID_PROMISE_20268:
@@ -1016,7 +1023,7 @@
 				struct request *rq = HWGROUP(drive)->rq;
 				unsigned long word_count = 0;
 
-				outb(clock|(hwif->channel ? 0x08 : 0x02), high_16 + 0x11);
+				outb(clock|(hwif->unit ? 0x08 : 0x02), high_16 + 0x11);
 				word_count = (rq->nr_sectors << 8);
 				word_count = (rq_data_dir(rq) == READ) ? word_count | 0x05000000 : word_count | 0x06000000;
 				outl(word_count, atapi_reg);
@@ -1026,7 +1033,7 @@
 			if ((drive->addressing) && (hardware48hack)) {
 				outl(0, atapi_reg);	/* zero out extra */
 				clock = IN_BYTE(high_16 + 0x11);
-				OUT_BYTE(clock & ~(hwif->channel ? 0x08:0x02), high_16 + 0x11);
+				OUT_BYTE(clock & ~(hwif->unit ? 0x08:0x02), high_16 + 0x11);
 			}
 			break;
 		case ide_dma_test_irq:	/* returns 1 if dma irq issued, 0 otherwise */
@@ -1035,7 +1042,7 @@
 				return (dma_stat & 4) == 4;
 
 			sc1d = IN_BYTE(high_16 + 0x001d);
-			if (HWIF(drive)->channel) {
+			if (drive->channel->unit) {
 				if ((sc1d & 0x50) == 0x50) goto somebody_else;
 				else if ((sc1d & 0x40) == 0x40)
 					return (dma_stat & 4) == 4;
@@ -1048,8 +1055,14 @@
 			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
 		case ide_dma_lostirq:
 		case ide_dma_timeout:
-			if (HWIF(drive)->resetproc != NULL)
-				HWIF(drive)->resetproc(drive);
+			if (drive->channel->resetproc != NULL)
+				drive->channel->resetproc(drive);
+		/*
+		 * we cannot support queued operations on promise, so fail to
+		 * to enable it...
+		 */
+		case ide_dma_queued_on:
+			return 1;
 		default:
 			break;
 	}
@@ -1064,12 +1077,12 @@
 	OUT_BYTE(0x00,IDE_CONTROL_REG);
 	mdelay(1000);
 	printk("PDC202XX: %s channel reset.\n",
-		HWIF(drive)->channel ? "Secondary" : "Primary");
+		drive->channel->unit ? "Secondary" : "Primary");
 }
 
 void pdc202xx_reset (ide_drive_t *drive)
 {
-	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
+	unsigned long high_16	= pci_resource_start(drive->channel->pci_dev, 4);
 	byte udma_speed_flag	= IN_BYTE(high_16 + 0x001f);
 
 	OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
@@ -1077,7 +1090,7 @@
 	OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
 	mdelay(2000);		/* 2 seconds ?! */
 	printk("PDC202XX: %s channel reset.\n",
-		HWIF(drive)->channel ? "Secondary" : "Primary");
+		drive->channel->unit ? "Secondary" : "Primary");
 }
 
 /*
@@ -1088,7 +1101,7 @@
 static int pdc202xx_tristate (ide_drive_t * drive, int state)
 {
 #if 0
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
 	byte sc1f		= inb(high_16 + 0x001f);
 
@@ -1121,6 +1134,7 @@
 
 	switch (dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268R:
 		case PCI_DEVICE_ID_PROMISE_20268:
@@ -1208,13 +1222,14 @@
 	return dev->irq;
 }
 
-unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif)
+unsigned int __init ata66_pdc202xx(struct ata_channel *hwif)
 {
-	unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10);
+	unsigned short mask = (hwif->unit) ? (1<<11) : (1<<10);
 	unsigned short CIS;
 
         switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_PROMISE_20268R:
@@ -1226,13 +1241,14 @@
 	}
 }
 
-void __init ide_init_pdc202xx (ide_hwif_t *hwif)
+void __init ide_init_pdc202xx(struct ata_channel *hwif)
 {
 	hwif->tuneproc  = &pdc202xx_tune_drive;
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
         switch(hwif->pci_dev->device) {
 		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_PROMISE_20276:
 		case PCI_DEVICE_ID_PROMISE_20269:
 		case PCI_DEVICE_ID_PROMISE_20268:
 		case PCI_DEVICE_ID_PROMISE_20268R:
diff -Nru a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c
--- a/drivers/ide/pdc4030.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/pdc4030.c	Sun Apr 14 12:16:56 2002
@@ -99,7 +99,7 @@
 {
 	unsigned int number;
 
-	number = (HWIF(drive)->channel << 1) + drive->select.b.unit;
+	number = (drive->channel->unit << 1) + drive->select.b.unit;
 	OUT_BYTE(number,IDE_FEATURE_REG);
 }
 
@@ -155,14 +155,14 @@
  * setup_pdc4030()
  * Completes the setup of a Promise DC4030 controller card, once found.
  */
-int __init setup_pdc4030 (ide_hwif_t *hwif)
+int __init setup_pdc4030(struct ata_channel *hwif)
 {
         ide_drive_t *drive;
-	ide_hwif_t *hwif2;
+	struct ata_channel *hwif2;
 	struct dc_ident ident;
 	int i;
 	ide_startstop_t startstop;
-	
+
 	if (!hwif) return 0;
 
 	drive = &hwif->drives[0];
@@ -224,15 +224,14 @@
 	 */
 
 	hwif->chipset	= hwif2->chipset = ide_pdc4030;
-	hwif->mate	= hwif2;
-	hwif2->mate	= hwif;
-	hwif2->channel	= 1;
+	hwif->unit	= ATA_PRIMARY;
+	hwif2->unit	= ATA_SECONDARY;
 	hwif->selectproc = hwif2->selectproc = &promise_selectproc;
 	hwif->serialized = hwif2->serialized = 1;
 
 /* Shift the remaining interfaces down by one */
 	for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
-		ide_hwif_t *h = &ide_hwifs[i];
+		struct ata_channel *h = &ide_hwifs[i];
 
 #ifdef DEBUG
 		printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);
@@ -263,7 +262,7 @@
  * Tests for the presence of a DC4030 Promise card on this interface
  * Returns: 1 if found, 0 if not found
  */
-int __init detect_pdc4030(ide_hwif_t *hwif)
+int __init detect_pdc4030(struct ata_channel *hwif)
 {
 	ide_drive_t *drive = &hwif->drives[0];
 
@@ -288,7 +287,7 @@
 void __init ide_probe_for_pdc4030(void)
 {
 	unsigned int	index;
-	ide_hwif_t	*hwif;
+	struct ata_channel *hwif;
 
 	if (enable_promise_support == 0)
 		return;
@@ -394,6 +393,7 @@
 
 	if (GET_STAT() & BUSY_STAT) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
 			return ide_started; /* continue polling... */
 		}
@@ -476,6 +476,7 @@
 
 	if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
 			return ide_started; /* continue polling... */
 		}
@@ -489,6 +490,7 @@
 	 */
 	promise_multwrite(drive, 4);
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+	BUG_ON(HWGROUP(drive)->handler);
 	ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
@@ -523,6 +525,7 @@
 		if (promise_multwrite(drive, rq->nr_sectors - 4))
 			return ide_stopped;
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
 		return ide_started;
 	} else {
@@ -533,6 +536,7 @@
 		if (promise_multwrite(drive, rq->nr_sectors))
 			return ide_stopped;
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		BUG_ON(HWGROUP(drive)->handler);
 		ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
 #ifdef DEBUG_WRITE
 		printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
@@ -547,16 +551,23 @@
  * already set up. It issues a READ or WRITE command to the Promise
  * controller, assuming LBA has been used to set up the block number.
  */
-ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t do_pdc4030_io(ide_drive_t *drive, struct ata_taskfile *task)
 {
-	struct request *rq	= HWGROUP(drive)->rq;
-	task_struct_t *taskfile	= (task_struct_t *) task->tfRegister;
+	struct request *rq = HWGROUP(drive)->rq;
+	struct hd_drive_task_hdr *taskfile = &task->taskfile;
 	unsigned long timeout;
 	byte stat;
 
+	/* Check that it's a regular command. If not, bomb out early. */
+	if (!(rq->flags & REQ_CMD)) {
+		blk_dump_rq_flags(rq, "pdc4030 bad flags");
+		ide_end_request(drive, 0);
+		return ide_stopped;
+	}
+
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl, IDE_CONTROL_REG);  /* clear nIEN */
-	SELECT_MASK(HWIF(drive), drive, 0);
+	SELECT_MASK(drive->channel, drive, 0);
 
 	OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
 	OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
@@ -568,20 +579,12 @@
 	OUT_BYTE(taskfile->device_head, IDE_SELECT_REG);
 	OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
 
-/* Check that it's a regular command. If not, bomb out early. */
-	if (!(rq->flags & REQ_CMD)) {
-		blk_dump_rq_flags(rq, "pdc4030 bad flags");
-		ide_end_request(drive, 0);
-		return ide_stopped;
-	}
-
 	switch (rq_data_dir(rq)) {
 	case READ:
-		OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
 /*
  * The card's behaviour is odd at this point. If the data is
  * available, DRQ will be true, and no interrupt will be
- * generated by the card. If this is the case, we need to call the 
+ * generated by the card. If this is the case, we need to call the
  * "interrupt" handler (promise_read_intr) directly. Otherwise, if
  * an interrupt is going to occur, bit0 of the SELECT register will
  * be high, so we can set the handler the just return and be interrupted.
@@ -600,6 +603,7 @@
 				printk(KERN_DEBUG "%s: read: waiting for "
 				                  "interrupt\n", drive->name);
 #endif
+				BUG_ON(HWGROUP(drive)->handler);
 				ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
 				return ide_started;
 			}
@@ -612,7 +616,6 @@
 
 	case WRITE: {
 		ide_startstop_t startstop;
-		OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
 /*
  * Strategy on write is:
  *	look for the DRQ that should have been immediately asserted
@@ -624,7 +627,7 @@
 			printk(KERN_ERR "%s: no DRQ after issuing "
 			       "PROMISE_WRITE\n", drive->name);
 			return startstop;
-	    	}
+		}
 		if (!drive->unmask)
 			__cli();	/* local CPU only */
 		HWGROUP(drive)->wrq = *rq; /* scratchpad */
@@ -641,7 +644,7 @@
 ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
 	struct hd_drive_task_hdr taskfile;
-	ide_task_t		 args;
+	struct ata_taskfile args;
 
 	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
 
@@ -652,15 +655,13 @@
 	taskfile.device_head	= ((block>>8)&0x0f)|drive->select.all;
 	taskfile.command	= (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE;
 
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr));
+	args.taskfile = taskfile;
+	memset(&args.hobfile, 0, sizeof(struct hd_drive_hob_hdr));
+
 	ide_cmd_type_parser(&args);
 	/* We don't use the generic inerrupt handlers here? */
 	args.prehandler		= NULL;
 	args.handler		= NULL;
-	args.rq			= rq;
-	args.block		= block;
-	rq->special		= NULL;
 	rq->special		= &args;
 
 	return do_pdc4030_io(drive, &args);
diff -Nru a/drivers/ide/pdcadma.c b/drivers/ide/pdcadma.c
--- a/drivers/ide/pdcadma.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/pdcadma.c	Sun Apr 14 12:16:56 2002
@@ -82,12 +82,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_pdcadma (ide_hwif_t *hwif)
+unsigned int __init ata66_pdcadma(struct ata_channel *channel)
 {
 	return 1;
 }
 
-void __init ide_init_pdcadma (ide_hwif_t *hwif)
+void __init ide_init_pdcadma(struct ata_channel *hwif)
 {
 	hwif->autodma = 0;
 	hwif->dma_base = 0;
@@ -101,7 +101,7 @@
 //	}
 }
 
-void __init ide_dmacapable_pdcadma (ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_pdcadma(struct ata_channel *hwif, unsigned long dmabase)
 {
 //	ide_setup_dma(hwif, dmabase, 8);
 }
diff -Nru a/drivers/ide/piix.c b/drivers/ide/piix.c
--- a/drivers/ide/piix.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/piix.c	Sun Apr 14 12:16:57 2002
@@ -1,5 +1,5 @@
 /*
- * $Id: piix.c,v 1.2 2002/03/13 22:50:43 vojtech Exp $
+ * $Id: piix.c,v 1.3 2002/03/29 16:06:06 vojtech Exp $
  *
  *  Copyright (c) 2000-2002 Vojtech Pavlik
  *
@@ -128,7 +128,7 @@
 
 	piix_print("----------PIIX BusMastering IDE Configuration---------------");
 
-	piix_print("Driver Version:                     1.2");
+	piix_print("Driver Version:                     1.3");
 	piix_print("South Bridge:                       %s", bmide_dev->name);
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &t);
@@ -199,7 +199,7 @@
 
 		if (~piix_config->flags & PIIX_VICTORY) {
 			if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_66 && (u & (1 << i))) umul = 2;
-			if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100 && (u & ((1 << i) + 12))) umul = 1;
+			if ((piix_config->flags & PIIX_UDMA) >= PIIX_UDMA_100 && (u & (1 << (i + 12)))) umul = 1;
 			udma[i] = (4 - ((e >> (i << 2)) & 3)) * umul;
 		} else  udma[i] = (8 - ((e >> (i << 2)) & 7)) * 2;
 
@@ -316,7 +316,7 @@
 
 static int piix_set_drive(ide_drive_t *drive, unsigned char speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_drive_t *peer = drive->channel->drives + (~drive->dn & 1);
 	struct ata_timing t, p;
 	int err, T, UT, umul;
 
@@ -331,7 +331,7 @@
 		umul = 2;
 
 	T = 1000000000 / piix_clock;
-	UT = T / umul;
+	UT = umul ? (T / umul) : 0;
 
 	ata_timing_compute(drive, speed, &t, T, UT);
 
@@ -341,7 +341,7 @@
 				ata_timing_merge(&p, &t, &t, IDE_TIMING_ALL);
 	}
 
-	piix_set_speed(HWIF(drive)->pci_dev, drive->dn, &t, umul);
+	piix_set_speed(drive->channel->pci_dev, drive->dn, &t, umul);
 
 	if (!drive->init_speed)	
 		drive->init_speed = speed;
@@ -357,7 +357,7 @@
 
 static void piix_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
-	if (!((piix_enabled >> HWIF(drive)->channel) & 1))
+	if (!((piix_enabled >> drive->channel->unit) & 1))
 		return;
 
 	if (pio == 255) {
@@ -381,7 +381,7 @@
 
 	if (func == ide_dma_check) {
 
-		short w80 = HWIF(drive)->udma_four;
+		short w80 = drive->channel->udma_four;
 
 		short speed = ata_timing_mode(drive,
 			XFER_PIO | XFER_EPIO | 
@@ -392,7 +392,7 @@
 
 		piix_set_drive(drive, speed);
 
-		func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+		func = (drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO)
 			? ide_dma_on : ide_dma_off_quietly;
 
 	}
@@ -533,12 +533,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_piix(ide_hwif_t *hwif)
+unsigned int __init ata66_piix(struct ata_channel *hwif)
 {
-	return ((piix_enabled & piix_80w) >> hwif->channel) & 1;
+	return ((piix_enabled & piix_80w) >> hwif->unit) & 1;
 }
 
-void __init ide_init_piix(ide_hwif_t *hwif)
+void __init ide_init_piix(struct ata_channel *hwif)
 {
 	int i;
 
@@ -550,7 +550,7 @@
 		hwif->drives[i].io_32bit = 1;
 		hwif->drives[i].unmask = 1;
 		hwif->drives[i].autotune = 1;
-		hwif->drives[i].dn = hwif->channel * 2 + i;
+		hwif->drives[i].dn = hwif->unit * 2 + i;
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -570,9 +570,9 @@
  * and only if DMA is safe with the chip and bridge.
  */
 
-void __init ide_dmacapable_piix(ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_piix(struct ata_channel *hwif, unsigned long dmabase)
 {
-	if (((piix_enabled >> hwif->channel) & 1)
+	if (((piix_enabled >> hwif->unit) & 1)
 		&& !(piix_config->flags & PIIX_NODMA))
 			ide_setup_dma(hwif, dmabase, 8);
 }
diff -Nru a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
--- a/drivers/ide/qd65xx.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/qd65xx.c	Sun Apr 14 12:16:57 2002
@@ -125,11 +125,11 @@
  * qd6500_compute_timing
  *
  * computes the timing value where
- * 	lower nibble represents active time,   in count of VLB clocks
- * 	upper nibble represents recovery time, in count of VLB clocks
+ *	lower nibble represents active time,   in count of VLB clocks
+ *	upper nibble represents recovery time, in count of VLB clocks
  */
 
-static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
+static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time)
 {
 	byte active_cycle,recovery_cycle;
 
@@ -208,7 +208,7 @@
 
 static void qd_set_timing (ide_drive_t *drive, byte timing)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 
 	drive->drive_data &= 0xff00;
 	drive->drive_data |= timing;
@@ -240,7 +240,7 @@
 		recovery_time = drive->id->eide_pio - 120;
 	}
 
-	qd_set_timing(drive,qd6500_compute_timing(HWIF(drive),active_time,recovery_time));
+	qd_set_timing(drive,qd6500_compute_timing(drive->channel, active_time,recovery_time));
 }
 
 /*
@@ -250,7 +250,7 @@
 static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
 {
 	struct ata_timing *t;
-	int base = HWIF(drive)->select_data;
+	int base = drive->channel->select_data;
 	int active_time   = 175;
 	int recovery_time = 415; /* worst case values from the dos driver */
 
@@ -291,9 +291,9 @@
 		printk(KERN_INFO "%s: PIO mode%d\n", drive->name, pio - XFER_PIO_0);
 	}
 
-	if (!HWIF(drive)->channel && drive->type != ATA_DISK) {
+	if (!drive->channel->unit && drive->type != ATA_DISK) {
 		qd_write_reg(0x5f,QD_CONTROL_PORT);
-		printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name,HWIF(drive)->name);
+		printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name, drive->channel->name);
 	}
 
 	qd_set_timing(drive,qd6580_compute_timing(active_time,recovery_time));
@@ -348,7 +348,7 @@
 	index = ! (config & QD_CONFIG_IDE_BASEPORT);
 
 	if ((config & 0xf0) == QD_CONFIG_QD6500) {
-		ide_hwif_t *hwif = &ide_hwifs[index];
+		struct ata_channel *hwif = &ide_hwifs[index];
 
 		if (qd_testreg(base)) return 1;		/* bad register */
 
@@ -392,7 +392,7 @@
 			config, control, QD_ID3);
 
 		if (control & QD_CONTR_SEC_DISABLED) {
-			ide_hwif_t *hwif = &ide_hwifs[index];
+			struct ata_channel *hwif = &ide_hwifs[index];
 
 			/* secondary disabled */
 			printk(KERN_INFO "%s: qd6580: single IDE board\n",
@@ -411,22 +411,23 @@
 
 			return 1;
 		} else {
-			int i,j;
+			int i;
+
 			/* secondary enabled */
 			printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
 					ide_hwifs[0].name,ide_hwifs[1].name);
 
-			for (i=0;i<2;i++) {
+			for (i = 0; i < 2; i++) {
+				int j;
 
 				ide_hwifs[i].chipset = ide_qd65xx;
-				ide_hwifs[i].mate = &ide_hwifs[i^1];
-				ide_hwifs[i].channel = i;
+				ide_hwifs[i].unit = i;
 
 				ide_hwifs[i].select_data = base;
 				ide_hwifs[i].config_data = config | (control <<8);
 				ide_hwifs[i].tuneproc = &qd6580_tune_drive;
 
-				for (j=0;j<2;j++) {
+				for (j = 0; j < 2; j++) {
 					ide_hwifs[i].drives[j].drive_data =
 					       i?QD6580_DEF_DATA2:QD6580_DEF_DATA;
 					ide_hwifs[i].drives[j].io_32bit = 1;
diff -Nru a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c
--- a/drivers/ide/rz1000.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ide/rz1000.c	Sun Apr 14 12:16:55 2002
@@ -28,7 +28,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 
-void __init ide_init_rz1000 (ide_hwif_t *hwif)	/* called from ide-pci.c */
+void __init ide_init_rz1000(struct ata_channel *hwif)	/* called from ide-pci.c */
 {
 	unsigned short reg;
 	struct pci_dev *dev = hwif->pci_dev;
@@ -62,7 +62,7 @@
 		printk("IDE: disabled chipset read-ahead (buggy %s)\n", name);
 	} else {
 		for (h = 0; h < MAX_HWIFS; ++h) {
-			ide_hwif_t *hwif = &ide_hwifs[h];
+			struct ata_channel *hwif = &ide_hwifs[h];
 			if ((hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0 || hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
 			 && (hwif->chipset == ide_unknown || hwif->chipset == ide_generic))
 			{
@@ -71,7 +71,7 @@
 				hwif->drives[0].no_unmask = 1;
 				hwif->drives[1].no_unmask = 1;
 				if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
-					hwif->channel = 1;
+					hwif->unit = 1;
 				printk("%s: serialized, disabled unmasking (buggy %s)\n", hwif->name, name);
 			}
 		}
diff -Nru a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
--- a/drivers/ide/serverworks.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/ide/serverworks.c	Sun Apr 14 12:16:54 2002
@@ -243,7 +243,7 @@
 	byte dma_modes[]	= { 0x77, 0x21, 0x20 };
 	byte pio_modes[]	= { 0x5d, 0x47, 0x34, 0x22, 0x20 };
 
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
 	byte csb5		= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
@@ -255,7 +255,7 @@
 
 	byte drive_pci		= 0x00;
 	byte drive_pci2		= 0x00;
-	byte drive_pci3		= hwif->channel ? 0x57 : 0x56;
+	byte drive_pci3		= hwif->unit ? 0x57 : 0x56;
 
 	byte ultra_enable	= 0x00;
 	byte ultra_timing	= 0x00;
@@ -413,7 +413,7 @@
 static int config_chipset_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	struct pci_dev *dev	= drive->channel->pci_dev;
 	byte udma_66	= eighty_ninty_three(drive);
 	int ultra66	= (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0;
 	int ultra100	= (ultra66 && svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 1 : 0;
@@ -436,7 +436,7 @@
 	struct hd_driveid *id = drive->id;
 	ide_dma_action_t dma_func = ide_dma_on;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -477,7 +477,7 @@
 no_dma_set:
 		config_chipset_for_pio(drive);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 static int svwks_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
@@ -487,7 +487,7 @@
 			return config_drive_xfer_rate(drive);
 		case ide_dma_end:
 		{
-			ide_hwif_t *hwif		= HWIF(drive);
+			struct ata_channel *hwif = drive->channel;
 			unsigned long dma_base		= hwif->dma_base;
 	
 			if(inb(dma_base+0x02)&1)
@@ -584,13 +584,13 @@
  * Bit 14 clear = primary IDE channel does not have 80-pin cable.
  * Bit 14 set   = primary IDE channel has 80-pin cable.
  */
-static unsigned int __init ata66_svwks_dell (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_dell(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-		return ((1 << (hwif->channel + 14)) &
+		return ((1 << (hwif->unit + 14)) &
 			dev->subsystem_device) ? 1 : 0;
 	return 0;
 }
@@ -601,18 +601,18 @@
  *
  * WARNING: this only works on Alpine hardware!
  */
-static unsigned int __init ata66_svwks_cobalt (ide_hwif_t *hwif)
+static unsigned int __init ata66_svwks_cobalt(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-		return ((1 << (hwif->channel + 14)) &
+		return ((1 << (hwif->unit + 14)) &
 			dev->subsystem_device) ? 1 : 0;
 	return 0;
 }
 
-unsigned int __init ata66_svwks (ide_hwif_t *hwif)
+unsigned int __init ata66_svwks(struct ata_channel *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
 
@@ -627,10 +627,10 @@
 	return 0;
 }
 
-void __init ide_init_svwks (ide_hwif_t *hwif)
+void __init ide_init_svwks(struct ata_channel *hwif)
 {
 	if (!hwif->irq)
-		hwif->irq = hwif->channel ? 15 : 14;
+		hwif->irq = hwif->unit ? 15 : 14;
 
 	hwif->tuneproc = &svwks_tune_drive;
 	hwif->speedproc = &svwks_tune_chipset;
diff -Nru a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
--- a/drivers/ide/sis5513.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/sis5513.c	Sun Apr 14 12:16:57 2002
@@ -1,17 +1,17 @@
 /*
- * linux/drivers/ide/sis5513.c		Version 0.13	March 4, 2002
+ * linux/drivers/ide/sis5513.c		Version 0.13	March 6, 2002
  *
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
  * May be copied or modified under the terms of the GNU General Public License
  *
-*/
-
-/* Thanks :
- * For direct support and hardware : SiS Taiwan.
- * For ATA100 support advice       : Daniela Engert.
- * For checking code correctness, providing patches :
- * John Fremlin, Manfred Spraul
+ *
+ * Thanks :
+ *
+ * SiS Taiwan		: for direct support and hardware.
+ * Daniela Engert	: for initial ATA100 advices and numerous others.
+ * John Fremlin, Manfred Spraul :
+ *			  for checking code correctness, providing patches.
  */
 
 /*
@@ -52,59 +52,40 @@
 
 #include "ata-timing.h"
 
+/* When DEBUG is defined it outputs initial PCI config register
+   values and changes made to them by the driver */
 // #define DEBUG
-/* if BROKEN_LEVEL is defined it limits the DMA mode
+/* When BROKEN_LEVEL is defined it limits the DMA mode
    at boot time to its value */
 // #define BROKEN_LEVEL XFER_SW_DMA_0
 #define DISPLAY_SIS_TIMINGS
 
 /* Miscellaneaous flags */
 #define SIS5513_LATENCY		0x01
-/* ATA transfer mode capabilities */
+
+/* registers layout and init values are chipset family dependant */
+/* 1/ define families */
 #define ATA_00		0x00
 #define ATA_16		0x01
 #define ATA_33		0x02
 #define ATA_66		0x03
-#define ATA_100a	0x04
+#define ATA_100a	0x04	// SiS730 is ATA100 with ATA66 layout
 #define ATA_100		0x05
 #define ATA_133		0x06
 
-static unsigned char dma_capability = 0x00;
-
+/* 2/ variable holding the controller chipset family value */
+static unsigned char chipset_family;
 
 /*
  * Debug code: following IDE config registers' changes
  */
 #ifdef DEBUG
-/* Copy of IDE Config registers 0x00 -> 0x58
+/* Copy of IDE Config registers 0x00 -> 0x57
    Fewer might be used depending on the actual chipset */
-static unsigned char ide_regs_copy[] = {
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0,
-	0x0, 0x0, 0x0, 0x0
-};
+static unsigned char ide_regs_copy[0x58];
 
 static byte sis5513_max_config_register(void) {
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00:
 		case ATA_16:	return 0x4f;
 		case ATA_33:	return 0x52;
@@ -185,7 +166,7 @@
 static const struct {
 	const char *name;
 	unsigned short host_id;
-	unsigned char dma_capability;
+	unsigned char chipset_family;
 	unsigned char flags;
 } SiSHostChipInfo[] = {
 	{ "SiS750",	PCI_DEVICE_ID_SI_750,	ATA_100,	SIS5513_LATENCY },
@@ -211,7 +192,7 @@
 
 /* Cycle time bits and values vary accross chip dma capabilities
    These three arrays hold the register layout and the values to set.
-   Indexed by dma_capability and (dma_mode - XFER_UDMA_0) */
+   Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */
 static byte cycle_time_offset[] = {0,0,5,4,4,0,0};
 static byte cycle_time_range[] = {0,0,2,3,3,4,4};
 static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = {
@@ -293,13 +274,13 @@
 	pci_read_config_byte(bmide_dev, 0x45+2*pos, &reg11);
 
 /* UDMA */
-	if (dma_capability >= ATA_33) {
+	if (chipset_family >= ATA_33) {
 		p += sprintf(p, "                UDMA %s \t \t \t UDMA %s\n",
 			     (reg01 & 0x80)  ? "Enabled" : "Disabled",
 			     (reg11 & 0x80) ? "Enabled" : "Disabled");
 
 		p += sprintf(p, "                UDMA Cycle Time    ");
-		switch(dma_capability) {
+		switch(chipset_family) {
 			case ATA_33:	p += sprintf(p, cycle_time[(reg01 & 0x60) >> 5]); break;
 			case ATA_66:
 			case ATA_100a:	p += sprintf(p, cycle_time[(reg01 & 0x70) >> 4]); break;
@@ -308,7 +289,7 @@
 			default:	p += sprintf(p, "133+ ?"); break;
 		}
 		p += sprintf(p, " \t UDMA Cycle Time    ");
-		switch(dma_capability) {
+		switch(chipset_family) {
 			case ATA_33:	p += sprintf(p, cycle_time[(reg11 & 0x60) >> 5]); break;
 			case ATA_66:
 			case ATA_100a:	p += sprintf(p, cycle_time[(reg11 & 0x70) >> 4]); break;
@@ -321,7 +302,7 @@
 
 /* Data Active */
 	p += sprintf(p, "                Data Active Time   ");
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00:
 		case ATA_16: /* confirmed */
 		case ATA_33:
@@ -332,7 +313,7 @@
 		default: p += sprintf(p, "133+ ?"); break;
 	}
 	p += sprintf(p, " \t Data Active Time   ");
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00:
 		case ATA_16:
 		case ATA_33:
@@ -370,7 +351,7 @@
 	u16 reg2, reg3;
 
 	p += sprintf(p, "\nSiS 5513 ");
-	switch(dma_capability) {
+	switch(chipset_family) {
 		case ATA_00: p += sprintf(p, "Unknown???"); break;
 		case ATA_16: p += sprintf(p, "DMA 16"); break;
 		case ATA_33: p += sprintf(p, "Ultra 33"); break;
@@ -386,7 +367,7 @@
 /* Status */
 	pci_read_config_byte(bmide_dev, 0x4a, &reg);
 	p += sprintf(p, "Channel Status: ");
-	if (dma_capability < ATA_66) {
+	if (chipset_family < ATA_66) {
 		p += sprintf(p, "%s \t \t \t \t %s\n",
 			     (reg & 0x04) ? "On" : "Off",
 			     (reg & 0x02) ? "On" : "Off");
@@ -403,7 +384,7 @@
 		     (reg & 0x04) ? "Native" : "Compatible");
 
 /* 80-pin cable ? */
-	if (dma_capability > ATA_33) {
+	if (chipset_family > ATA_33) {
 		pci_read_config_byte(bmide_dev, 0x48, &reg);
 		p += sprintf(p, "Cable Type:     %s \t \t \t %s\n",
 			     (reg & 0x10) ? cable_type[1] : cable_type[0],
@@ -434,7 +415,7 @@
 /* Enables per-drive prefetch and postwrite */
 static void config_drive_art_rwp (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte reg4bh		= 0;
@@ -460,7 +441,7 @@
 /* Set per-drive active and recovery time */
 static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte			timing, drive_pci, test1, test2;
@@ -507,7 +488,7 @@
 	}
 
 	/* register layout changed with newer ATA100 chips */
-	if (dma_capability < ATA_100) {
+	if (chipset_family < ATA_100) {
 		pci_read_config_byte(dev, drive_pci, &test1);
 		pci_read_config_byte(dev, drive_pci+1, &test2);
 
@@ -560,7 +541,7 @@
 
 static int sis5513_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev	= hwif->pci_dev;
 
 	byte			drive_pci, reg;
@@ -587,7 +568,7 @@
 
 	pci_read_config_byte(dev, drive_pci+1, &reg);
 	/* Disable UDMA bit for non UDMA modes on UDMA chips */
-	if ((speed < XFER_UDMA_0) && (dma_capability > ATA_16)) {
+	if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) {
 		reg &= 0x7F;
 		pci_write_config_byte(dev, drive_pci+1, reg);
 	}
@@ -604,11 +585,11 @@
 			/* Force the UDMA bit on if we want to use UDMA */
 			reg |= 0x80;
 			/* clean reg cycle time bits */
-			reg &= ~((0xFF >> (8 - cycle_time_range[dma_capability]))
-				 << cycle_time_offset[dma_capability]);
+			reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
+				 << cycle_time_offset[chipset_family]);
 			/* set reg cycle time bits */
-			reg |= cycle_time_value[dma_capability-ATA_00][speed-XFER_UDMA_0]
-				<< cycle_time_offset[dma_capability];
+			reg |= cycle_time_value[chipset_family-ATA_00][speed-XFER_UDMA_0]
+				<< cycle_time_offset[chipset_family];
 			pci_write_config_byte(dev, drive_pci+1, reg);
 			break;
 		case XFER_MW_DMA_2:
@@ -624,7 +605,7 @@
 		case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2));
 		case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1));
 		case XFER_PIO_0:
-		default:	 return((int) config_chipset_for_pio(drive, 0));	
+		default:	 return((int) config_chipset_for_pio(drive, 0));
 	}
 	drive->current_speed = speed;
 #ifdef DEBUG
@@ -640,12 +621,12 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 /*
- * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four))
+ * ((id->hw_config & 0x4000|0x2000) && (drive->channel->udma_four))
  */
 static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
-	struct hd_driveid *id	= drive->id;
-	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id = drive->id;
+	struct ata_channel *hwif = drive->channel;
 
 	byte			speed = 0;
 
@@ -657,17 +638,17 @@
 	       drive->dn, ultra);
 #endif
 
-	if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (dma_capability >= ATA_100a))
+	if ((id->dma_ultra & 0x0020) && ultra && udma_66 && (chipset_family >= ATA_100a))
 		speed = XFER_UDMA_5;
-	else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (dma_capability >= ATA_66))
+	else if ((id->dma_ultra & 0x0010) && ultra && udma_66 && (chipset_family >= ATA_66))
 		speed = XFER_UDMA_4;
-	else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (dma_capability >= ATA_66))
+	else if ((id->dma_ultra & 0x0008) && ultra && udma_66 && (chipset_family >= ATA_66))
 		speed = XFER_UDMA_3;
-	else if ((id->dma_ultra & 0x0004) && ultra && (dma_capability >= ATA_33))
+	else if ((id->dma_ultra & 0x0004) && ultra && (chipset_family >= ATA_33))
 		speed = XFER_UDMA_2;
-	else if ((id->dma_ultra & 0x0002) && ultra && (dma_capability >= ATA_33))
+	else if ((id->dma_ultra & 0x0002) && ultra && (chipset_family >= ATA_33))
 		speed = XFER_UDMA_1;
-	else if ((id->dma_ultra & 0x0001) && ultra && (dma_capability >= ATA_33))
+	else if ((id->dma_ultra & 0x0001) && ultra && (chipset_family >= ATA_33))
 		speed = XFER_UDMA_0;
 	else if (id->dma_mword & 0x0004)
 		speed = XFER_MW_DMA_2;
@@ -700,7 +681,9 @@
 	struct hd_driveid *id		= drive->id;
 	ide_dma_action_t dma_func	= ide_dma_off_quietly;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+	config_chipset_for_pio(drive, 5);
+
+	if (id && (id->capability & 1) && drive->channel->autodma) {
 		/* Consult the list of known "bad" drives */
 		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
 			dma_func = ide_dma_off;
@@ -740,7 +723,7 @@
 		(void) config_chipset_for_pio(drive, 5);
 	}
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /* initiates/aborts (U)DMA read/write operations on a drive. */
@@ -764,10 +747,6 @@
 	struct pci_dev *host;
 	int i = 0;
 
-#ifdef DEBUG
-	sis5513_print_registers(dev, "pci_init_sis5513 start");
-#endif
-
 	/* Find the chip */
 	for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !host_dev; i++) {
 		host = pci_find_device (PCI_VENDOR_ID_SI,
@@ -777,12 +756,16 @@
 			continue;
 
 		host_dev = host;
-		dma_capability = SiSHostChipInfo[i].dma_capability;
+		chipset_family = SiSHostChipInfo[i].chipset_family;
 		printk(SiSHostChipInfo[i].name);
 		printk("\n");
 
+#ifdef DEBUG
+		sis5513_print_registers(dev, "pci_init_sis5513 start");
+#endif
+
 		if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) {
-			byte latency = (dma_capability == ATA_100)? 0x80 : 0x10; /* Lacking specs */
+			byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */
 			pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency);
 		}
 	}
@@ -792,7 +775,7 @@
 	   2/ tell old chips to allow per drive IDE timings */
 	if (host_dev) {
 		byte reg;
-		switch(dma_capability) {
+		switch(chipset_family) {
 			case ATA_133:
 			case ATA_100:
 				/* Set compatibility bit */
@@ -841,22 +824,22 @@
 	return 0;
 }
 
-unsigned int __init ata66_sis5513 (ide_hwif_t *hwif)
+unsigned int __init ata66_sis5513(struct ata_channel *hwif)
 {
 	byte reg48h = 0, ata66 = 0;
-	byte mask = hwif->channel ? 0x20 : 0x10;
+	byte mask = hwif->unit ? 0x20 : 0x10;
 	pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
 
-	if (dma_capability >= ATA_66) {
+	if (chipset_family >= ATA_66) {
 		ata66 = (reg48h & mask) ? 0 : 1;
 	}
         return ata66;
 }
 
-void __init ide_init_sis5513 (ide_hwif_t *hwif)
+void __init ide_init_sis5513(struct ata_channel *hwif)
 {
 
-	hwif->irq = hwif->channel ? 15 : 14;
+	hwif->irq = hwif->unit ? 15 : 14;
 
 	hwif->tuneproc = &sis5513_tune_drive;
 	hwif->speedproc = &sis5513_tune_chipset;
@@ -866,7 +849,7 @@
 
 	if (host_dev) {
 #ifdef CONFIG_BLK_DEV_IDEDMA
-		if (dma_capability > ATA_16) {
+		if (chipset_family > ATA_16) {
 			hwif->autodma = noautodma ? 0 : 1;
 			hwif->highmem = 1;
 			hwif->dmaproc = &sis5513_dmaproc;
diff -Nru a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
--- a/drivers/ide/sl82c105.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/sl82c105.c	Sun Apr 14 12:16:57 2002
@@ -57,13 +57,13 @@
  */
 static void config_for_pio(ide_drive_t *drive, int pio, int report)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	struct ata_timing *t;
 	unsigned short drv_ctrl = 0x909;
 	unsigned int xfer_mode, reg;
 
-	reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
+	reg = (hwif->unit ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
 
 	if (pio == 255)
 		xfer_mode = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
@@ -95,12 +95,12 @@
  */
 static int config_for_dma(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned short drv_ctrl = 0x909;
 	unsigned int reg;
 
-	reg = (hwif->channel ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
+	reg = (hwif->unit ? 0x4c : 0x44) + (drive->select.b.unit ? 4 : 0);
 
 	if (ide_config_drive_speed(drive, XFER_MW_DMA_2) == 0)
 		drv_ctrl = 0x0240;
@@ -120,7 +120,7 @@
 
 	do {
 		struct hd_driveid *id = drive->id;
-		ide_hwif_t *hwif = HWIF(drive);
+		struct ata_channel *hwif = drive->channel;
 
 		if (!hwif->autodma)
 			break;
@@ -146,7 +146,7 @@
 		}
 	} while (0);
 
-	return HWIF(drive)->dmaproc(dma_func, drive);
+	return drive->channel->dmaproc(dma_func, drive);
 }
 
 /*
@@ -232,7 +232,7 @@
 	return dev->irq;
 }
 
-void __init dma_init_sl82c105(ide_hwif_t *hwif, unsigned long dma_base)
+void __init dma_init_sl82c105(struct ata_channel *hwif, unsigned long dma_base)
 {
 	unsigned int rev;
 	byte dma_state;
@@ -261,7 +261,7 @@
 /*
  * Initialise the chip
  */
-void __init ide_init_sl82c105(ide_hwif_t *hwif)
+void __init ide_init_sl82c105(struct ata_channel *hwif)
 {
 	hwif->tuneproc = tune_sl82c105;
 }
diff -Nru a/drivers/ide/trm290.c b/drivers/ide/trm290.c
--- a/drivers/ide/trm290.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ide/trm290.c	Sun Apr 14 12:16:56 2002
@@ -141,7 +141,7 @@
 
 static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int reg;
 	unsigned long flags;
 
@@ -153,14 +153,14 @@
 
 	if (reg != hwif->select_data) {
 		hwif->select_data = reg;
-		outb(0x51|(hwif->channel<<3), hwif->config_data+1);	/* set PIO/DMA */
+		outb(0x51|(hwif->unit<<3), hwif->config_data+1);	/* set PIO/DMA */
 		outw(reg & 0xff, hwif->config_data);
 	}
 
 	/* enable IRQ if not probing */
 	if (drive->present) {
 		reg = inw(hwif->config_data+3) & 0x13;
-		reg &= ~(1 << hwif->channel);
+		reg &= ~(1 << hwif->unit);
 		outw(reg, hwif->config_data+3);
 	}
 
@@ -175,7 +175,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
+	struct ata_channel *hwif = drive->channel;
 	unsigned int count, reading = 2, writing = 0;
 
 	switch (func) {
@@ -194,6 +194,7 @@
 			outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
 			if (drive->type != ATA_DISK)
 				return 0;
+			BUG_ON(HWGROUP(drive)->handler);
 			ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
 			OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
 			return 0;
@@ -216,7 +217,7 @@
 /*
  * Invoked from ide-dma.c at boot time.
  */
-void __init ide_init_trm290 (ide_hwif_t *hwif)
+void __init ide_init_trm290(struct ata_channel *hwif)
 {
 	unsigned int cfgbase = 0;
 	unsigned long flags;
@@ -237,7 +238,7 @@
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
 	/* put config reg into first byte of hwif->select_data */
-	outb(0x51|(hwif->channel<<3), hwif->config_data+1);
+	outb(0x51|(hwif->unit<<3), hwif->config_data+1);
 	hwif->select_data = 0x21;			/* select PIO as default */
 	outb(hwif->select_data, hwif->config_data);
 	reg = inb(hwif->config_data+3);			/* get IRQ info */
@@ -246,10 +247,21 @@
 	__restore_flags(flags);	/* local CPU only */
 
 	if ((reg & 0x10))
-		hwif->irq = hwif->channel ? 15 : 14;	/* legacy mode */
-	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
-		hwif->irq = hwif->mate->irq;		/* sharing IRQ with mate */
-	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
+		hwif->irq = hwif->unit ? 15 : 14;	/* legacy mode */
+	else {
+		static int primary_irq = 0;
+
+		/* Ugly way to let the primary and secondary channel on the
+		 * chip use the same IRQ line.
+		 */
+
+		if (hwif->unit == ATA_PRIMARY)
+			primary_irq = hwif->irq;
+		else if (!hwif->irq)
+			hwif->irq = primary_irq;
+	}
+
+	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->unit ? 0x0080 : 0x0000), 3);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	hwif->dmaproc = &trm290_dmaproc;
@@ -264,10 +276,10 @@
 		 * for the control basereg, so this kludge ensures that we use only
 		 * values that are known to work.  Ugh.		-ml
 		 */
-		unsigned short old, compat = hwif->channel ? 0x374 : 0x3f4;
+		unsigned short old, compat = hwif->unit ? 0x374 : 0x3f4;
 		static unsigned short next_offset = 0;
 
-		outb(0x54|(hwif->channel<<3), hwif->config_data+1);
+		outb(0x54|(hwif->unit<<3), hwif->config_data+1);
 		old = inw(hwif->config_data) & ~1;
 		if (old != compat && inb(old+2) == 0xff) {
 			compat += (next_offset += 0x400);	/* leave lower 10 bits untouched */
diff -Nru a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
--- a/drivers/ide/umc8672.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/umc8672.c	Sun Apr 14 12:16:57 2002
@@ -111,7 +111,7 @@
 static void tune_umc (ide_drive_t *drive, byte pio)
 {
 	unsigned long flags;
-	ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
+	ide_hwgroup_t *hwgroup = ide_hwifs[drive->channel->index ^ 1].hwgroup;
 
 	if (pio == 255)
 		pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
@@ -146,7 +146,7 @@
 	{
 		__restore_flags(flags);	/* local CPU only */
 		printk ("umc8672: not found\n");
-		return;  
+		return;
 	}
 	outb_p (0xa5,0x108); /* disable umc */
 
@@ -158,7 +158,6 @@
 	ide_hwifs[1].chipset = ide_umc8672;
 	ide_hwifs[0].tuneproc = &tune_umc;
 	ide_hwifs[1].tuneproc = &tune_umc;
-	ide_hwifs[0].mate = &ide_hwifs[1];
-	ide_hwifs[1].mate = &ide_hwifs[0];
-	ide_hwifs[1].channel = 1;
+	ide_hwifs[0].unit = ATA_PRIMARY;
+	ide_hwifs[1].unit = ATA_SECONDARY;
 }
diff -Nru a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
--- a/drivers/ide/via82cxxx.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ide/via82cxxx.c	Sun Apr 14 12:16:57 2002
@@ -302,7 +302,7 @@
 
 static int via_set_drive(ide_drive_t *drive, unsigned char speed)
 {
-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	ide_drive_t *peer = drive->channel->drives + (~drive->dn & 1);
 	struct ata_timing t, p;
 	unsigned int T, UT;
 
@@ -328,7 +328,7 @@
 		ata_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
 	}
 
-	via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
+	via_set_speed(drive->channel->pci_dev, drive->dn, &t);
 
 	if (!drive->init_speed)
 		drive->init_speed = speed;
@@ -344,7 +344,7 @@
 
 static void via82cxxx_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
-	if (!((via_enabled >> HWIF(drive)->channel) & 1))
+	if (!((via_enabled >> drive->channel->unit) & 1))
 		return;
 
 	if (pio == 255) {
@@ -368,7 +368,7 @@
 
 	if (func == ide_dma_check) {
 
-		short w80 = HWIF(drive)->udma_four;
+		short w80 = drive->channel->udma_four;
 
 		short speed = ata_timing_mode(drive,
 			XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
@@ -379,7 +379,7 @@
 
 		via_set_drive(drive, speed);
 
-		func = (HWIF(drive)->autodma && (speed & XFER_MODE) != XFER_PIO)
+		func = (drive->channel->autodma && (speed & XFER_MODE) != XFER_PIO)
 			? ide_dma_on : ide_dma_off_quietly;
 	}
 
@@ -523,12 +523,12 @@
 	return 0;
 }
 
-unsigned int __init ata66_via82cxxx(ide_hwif_t *hwif)
+unsigned int __init ata66_via82cxxx(struct ata_channel *hwif)
 {
-	return ((via_enabled & via_80w) >> hwif->channel) & 1;
+	return ((via_enabled & via_80w) >> hwif->unit) & 1;
 }
 
-void __init ide_init_via82cxxx(ide_hwif_t *hwif)
+void __init ide_init_via82cxxx(struct ata_channel *hwif)
 {
 	int i;
 
@@ -540,7 +540,7 @@
 		hwif->drives[i].io_32bit = 1;
 		hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1;
 		hwif->drives[i].autotune = 1;
-		hwif->drives[i].dn = hwif->channel * 2 + i;
+		hwif->drives[i].dn = hwif->unit * 2 + i;
 	}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -559,8 +559,8 @@
  * We allow the BM-DMA driver to only work on enabled interfaces.
  */
 
-void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase)
+void __init ide_dmacapable_via82cxxx(struct ata_channel *hwif, unsigned long dmabase)
 {
-	if ((via_enabled >> hwif->channel) & 1)
+	if ((via_enabled >> hwif->unit) & 1)
 		ide_setup_dma(hwif, dmabase, 8);
 }
diff -Nru a/drivers/ieee1394/Config.help b/drivers/ieee1394/Config.help
--- a/drivers/ieee1394/Config.help	Sun Apr 14 12:16:57 2002
+++ b/drivers/ieee1394/Config.help	Sun Apr 14 12:16:57 2002
@@ -90,6 +90,31 @@
   say M here and read <file:Documentation/modules.txt>.  The module
   will be called raw1394.o.
 
+CONFIG_IEEE1394_ETH1394
+  Extremely Experimental! This driver is a Linux specific way to use your
+  IEEE1394 Host as an Ethernet type device. This is _NOT_ IP1394.
+
+CONFIG_IEEE1394_AMDTP
+  This option enables the Audio & Music Data Transmission Protocol
+  (IEC61883-6) driver, which implements audio transmission over
+  IEEE1394.
+
+  The userspace interface is documented in amdtp.h.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read <file:Documentation/modules.txt>.  The module
+  will be called amdtp.o.
+
+CONFIG_IEEE1394_CMP
+  This option enables the Connection Management Procedures
+  (IEC61883-1) driver, which implements input and output plugs.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read <file:Documentation/modules.txt>.  The module
+  will be called amdtp.o.
+
 CONFIG_IEEE1394_VERBOSEDEBUG
   If you say Y here, you will get very verbose debugging logs from the
   subsystem which includes a dump of the header of every sent and
@@ -99,4 +124,3 @@
 
   Say Y if you really want or need the debugging output, everyone else
   says N.
-
diff -Nru a/drivers/ieee1394/Config.in b/drivers/ieee1394/Config.in
--- a/drivers/ieee1394/Config.in	Sun Apr 14 12:16:59 2002
+++ b/drivers/ieee1394/Config.in	Sun Apr 14 12:16:59 2002
@@ -19,8 +19,14 @@
 	comment "Protocol Drivers"
 	dep_tristate '  OHCI-1394 Video support' CONFIG_IEEE1394_VIDEO1394 $CONFIG_IEEE1394_OHCI1394
 	dep_tristate '  SBP-2 support (Harddisks etc.)' CONFIG_IEEE1394_SBP2 $CONFIG_SCSI $CONFIG_IEEE1394
+	dep_tristate '  Ethernet over 1394' CONFIG_IEEE1394_ETH1394 $CONFIG_IEEE1394
 	dep_tristate '  OHCI-DV I/O support' CONFIG_IEEE1394_DV1394 $CONFIG_IEEE1394_OHCI1394
 	dep_tristate '  Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394
+	dep_tristate '  IEC61883-1 Plug support' CONFIG_IEEE1394_CMP $CONFIG_IEEE1394
+
+	if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then
+	    dep_tristate '    IEC61883-6 (Audio transmission) support' CONFIG_IEEE1394_AMDTP $CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394_CMP
+	fi
 
 	bool 'Excessive debugging output' CONFIG_IEEE1394_VERBOSEDEBUG
     fi
diff -Nru a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
--- a/drivers/ieee1394/Makefile	Sun Apr 14 12:17:00 2002
+++ b/drivers/ieee1394/Makefile	Sun Apr 14 12:17:00 2002
@@ -4,7 +4,7 @@
 
 O_TARGET := ieee1394drv.o
 
-export-objs := ieee1394_core.o ohci1394.o
+export-objs := ieee1394_core.o ohci1394.o cmp.o
 
 list-multi := ieee1394.o
 ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
@@ -17,6 +17,9 @@
 obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
 obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
 obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
+obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
+obj-$(CONFIG_IEEE1394_AMDTP) += amdtp.o
+obj-$(CONFIG_IEEE1394_CMP) += cmp.o
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/amdtp.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,1141 @@
+/* -*- c-basic-offset: 8 -*-
+ *
+ * amdtp.c - Audio and Music Data Transmission Protocol Driver
+ * Copyright (C) 2001 Kristian Høgsberg
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+/* OVERVIEW
+ * --------
+ *
+ * The AMDTP driver is designed to expose the IEEE1394 bus as a
+ * regular OSS soundcard, i.e. you can link /dev/dsp to /dev/amdtp and
+ * then your favourite MP3 player, game or whatever sound program will
+ * output to an IEEE1394 isochronous channel.  The signal destination
+ * could be a set of IEEE1394 loudspeakers (if and when such things
+ * become available) or an amplifier with IEEE1394 input (like the
+ * Sony STR-LSA1).  The driver only handles the actual streaming, some
+ * connection management is also required for this to actually work.
+ * That is outside the scope of this driver, and furthermore it is not
+ * really standardized yet.
+ *
+ * The Audio and Music Data Tranmission Protocol is avaiable at
+ *
+ *     http://www.1394ta.org/Download/Technology/Specifications/2001/AM20Final-jf2.pdf
+ *
+ *
+ * TODO
+ * ----
+ *
+ * - We should be able to change input sample format between LE/BE, as
+ *   we already shift the bytes around when we construct the iso
+ *   packets.
+ *
+ * - Fix DMA stop after bus reset!
+ *
+ * - Implement poll.
+ *
+ * - Clean up iso context handling in ohci1394.
+ *
+ *
+ * MAYBE TODO
+ * ----------
+ *
+ * - Receive data for local playback or recording.  Playback requires
+ *   soft syncing with the sound card.
+ *
+ * - Signal processing, i.e. receive packets, do some processing, and
+ *   transmit them again using the same packet structure and timestamps
+ *   offset by processing time.
+ *
+ * - Maybe make an ALSA interface, that is, create a file_ops
+ *   implementation that recognizes ALSA ioctls and uses defaults for
+ *   things that can't be controlled through ALSA (iso channel).
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+
+#include "hosts.h"
+#include "highlevel.h"
+#include "ieee1394.h"
+#include "ieee1394_core.h"
+#include "ohci1394.h"
+
+#include "amdtp.h"
+#include "cmp.h"
+
+#define FMT_AMDTP 0x10
+#define FDF_AM824 0x00
+#define FDF_SFC_32KHZ  0x00 /* 32kHz */
+#define FDF_SFC_44K1HZ 0x01 /* 44.1kHz */
+#define FDF_SFC_48KHZ  0x02 /* 44.1kHz */
+
+struct descriptor_block {
+	struct output_more_immediate {
+		u32 control;
+		u32 pad0;
+		u32 skip;
+		u32 pad1;
+		u32 header[4];
+	} header_desc;
+
+	struct output_last {
+		u32 control;
+		u32 data_address;
+		u32 branch;
+		u32 status;
+	} payload_desc;
+};
+
+struct packet {
+	struct descriptor_block *db;
+	dma_addr_t db_bus;
+	quadlet_t *payload;
+	dma_addr_t payload_bus;
+};
+
+struct fraction {
+	int integer;
+	int numerator;
+	int denominator;
+	int counter;
+};
+
+#define PACKET_LIST_SIZE 256
+#define MAX_PACKET_LISTS 4
+
+struct packet_list {
+	struct list_head link;
+	int last_cycle_count;
+	struct packet packets[PACKET_LIST_SIZE];
+};
+
+#define BUFFER_SIZE 128
+
+/* This implements a circular buffer for incoming samples. */
+
+struct buffer {
+	int head, tail, length, size;
+	unsigned char data[0];
+};
+
+struct stream {
+	int iso_channel;
+	int format;
+	int rate;
+	int dimension;
+	int fdf;
+	struct cmp_pcr *opcr;
+
+	/* Input samples are copied here. */
+	struct buffer *input;
+
+	/* ISO Packer state */
+	unsigned char dbc;
+	struct packet_list *current_packet_list;
+	int current_packet;
+	struct fraction packet_size_fraction;
+
+	/* We use these to generate control bits when we are packing
+	 * iec958 data.
+	 */
+	int iec958_frame_count;
+	int iec958_rate_code;
+
+	/* The cycle_count and cycle_offset fields are used for the
+	 * synchronization timestamps (syt) in the cip header.  They
+	 * are incremented by at least a cycle every time we put a
+	 * time stamp in a packet.  As we dont time stamp all
+	 * packages, cycle_count isn't updated in every cycle, and
+	 * sometimes it's incremented by 2.  Thus, we have
+	 * cycle_count2, which is simply incremented by one with each
+	 * packet, so we can compare it to the transmission time
+	 * written back in the dma programs.
+	 */
+	atomic_t cycle_count, cycle_count2;
+	int cycle_offset;
+	struct fraction syt_fraction;
+	int syt_interval;
+	int stale_count;
+
+	/* Theses fields control the sample output to the DMA engine.
+	 * The dma_packet_lists list holds packet lists currently
+	 * queued for dma; the head of the list is currently being
+	 * processed.  The last program in a packet list generates an
+	 * interrupt, which removes the head from dma_packet_lists and
+	 * puts it back on the free list.
+	 */
+	struct list_head dma_packet_lists;
+	struct list_head free_packet_lists;
+        wait_queue_head_t packet_list_wait;
+	spinlock_t packet_list_lock;
+	int iso_context;
+	struct pci_pool *descriptor_pool, *packet_pool;
+
+	/* Streams at a host controller are chained through this field. */
+	struct list_head link;
+	struct amdtp_host *host;
+};
+
+struct amdtp_host {
+	struct hpsb_host *host;
+	struct ti_ohci *ohci;
+	struct list_head stream_list;
+	spinlock_t stream_list_lock;
+	struct list_head link;
+};
+
+static struct hpsb_highlevel *amdtp_highlevel;
+static LIST_HEAD(host_list);
+static spinlock_t host_list_lock = SPIN_LOCK_UNLOCKED;
+
+/* FIXME: This doesn't belong here... */
+
+#define OHCI1394_CONTEXT_CYCLE_MATCH 0x80000000
+#define OHCI1394_CONTEXT_RUN         0x00008000
+#define OHCI1394_CONTEXT_WAKE        0x00001000
+#define OHCI1394_CONTEXT_DEAD        0x00000800
+#define OHCI1394_CONTEXT_ACTIVE      0x00000400
+
+static inline int ohci1394_alloc_it_ctx(struct ti_ohci *ohci)
+{
+	int i;
+
+	for (i = 0; i < ohci->nb_iso_xmit_ctx; i++)
+		if (!test_and_set_bit(i, &ohci->it_ctx_usage))
+			return i;
+
+	return -EBUSY;
+}
+	
+static inline void ohci1394_free_it_ctx(struct ti_ohci *ohci, int ctx)
+{
+	clear_bit(ctx, &ohci->it_ctx_usage);
+}
+
+
+void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
+			   dma_addr_t first_cmd, int z, int cycle_match)
+{
+	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx);
+	reg_write(ohci, OHCI1394_IsoXmitCommandPtr + ctx * 16, first_cmd | z);
+	reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16, ~0);
+	wmb();
+	reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
+		  OHCI1394_CONTEXT_CYCLE_MATCH | (cycle_match << 16) |
+		  OHCI1394_CONTEXT_RUN);
+}
+
+void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
+{
+	reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
+		  OHCI1394_CONTEXT_WAKE);
+}
+
+void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx)
+{
+	u32 control;
+	int wait;
+
+	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << ctx);
+	reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16,
+		  OHCI1394_CONTEXT_RUN);
+	wmb();
+
+	for (wait = 0; wait < 5; wait++) {
+		control = reg_read(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16);
+		if ((control & OHCI1394_CONTEXT_ACTIVE) == 0)
+			break;
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+}
+
+/* Note: we can test if free_packet_lists is empty without aquiring
+ * the packet_list_lock.  The interrupt handler only adds to the free
+ * list, there is no race condition between testing the list non-empty
+ * and acquiring the lock.
+ */
+
+static struct packet_list *stream_get_free_packet_list(struct stream *s)
+{
+	struct packet_list *pl;
+	unsigned long flags;
+
+	if (list_empty(&s->free_packet_lists))
+		return NULL;
+
+	spin_lock_irqsave(&s->packet_list_lock, flags);
+	pl = list_entry(s->free_packet_lists.next, struct packet_list, link);
+	list_del(&pl->link);
+	spin_unlock_irqrestore(&s->packet_list_lock, flags);
+
+	return pl;
+}
+
+static void stream_put_dma_packet_list(struct stream *s,
+				       struct packet_list *pl)
+{
+	unsigned long flags;
+	struct packet_list *prev;
+
+	/* Remember the cycle_count used for timestamping the last packet. */
+	pl->last_cycle_count = atomic_read(&s->cycle_count2) - 1;
+	pl->packets[PACKET_LIST_SIZE - 1].db->payload_desc.branch = 0;
+
+	spin_lock_irqsave(&s->packet_list_lock, flags);
+	list_add_tail(&pl->link, &s->dma_packet_lists);
+	spin_unlock_irqrestore(&s->packet_list_lock, flags);
+
+	prev = list_entry(pl->link.prev, struct packet_list, link);
+	if (pl->link.prev != &s->dma_packet_lists) {
+		struct packet *last = &prev->packets[PACKET_LIST_SIZE - 1];
+		last->db->payload_desc.branch = pl->packets[0].db_bus | 3;
+		ohci1394_wake_it_ctx(s->host->ohci, s->iso_context);
+	}
+	else {
+		u32 syt, cycle_count;
+
+		cycle_count = reg_read(s->host->host->hostdata,
+				       OHCI1394_IsochronousCycleTimer) >> 12;
+		syt = (pl->packets[0].payload[1] >> 12) & 0x0f;
+		cycle_count = (cycle_count & ~0x0f) + 32 + syt;
+		if ((cycle_count & 0x1fff) >= 8000)
+			cycle_count = cycle_count - 8000 + 0x2000;
+
+		ohci1394_start_it_ctx(s->host->ohci, s->iso_context,
+				      pl->packets[0].db_bus, 3,
+				      cycle_count & 0x7fff);
+	}
+}
+
+static void stream_shift_packet_lists(struct stream *s)
+{
+	struct packet_list *pl;
+	struct packet *last;
+	int diff;
+
+	if (list_empty(&s->dma_packet_lists)) {
+		HPSB_ERR("empty dma_packet_lists in %s", __FUNCTION__);
+		return;
+	}
+
+	/* Now that we know the list is non-empty, we can get the head
+	 * of the list without locking, because the process context
+	 * only adds to the tail.  
+	 */
+	pl = list_entry(s->dma_packet_lists.next, struct packet_list, link);
+	last = &pl->packets[PACKET_LIST_SIZE - 1];
+
+	/* This is weird... if we stop dma processing in the middle of
+	 * a packet list, the dma context immediately generates an
+	 * interrupt if we enable it again later.  This only happens
+	 * when amdtp_release is interrupted while waiting for dma to
+	 * complete, though.  Anyway, we detect this by seeing that
+	 * the status of the dma descriptor that we expected an
+	 * interrupt from is still 0.
+	 */
+	if (last->db->payload_desc.status == 0) {
+		HPSB_INFO("weird interrupt...");
+		return;
+	}		
+
+	/* If the last descriptor block does not specify a branch
+	 * address, we have a sample underflow.
+	 */
+	if (last->db->payload_desc.branch == 0)
+		HPSB_INFO("FIXME: sample underflow...");
+
+	/* Here we check when (which cycle) the last packet was sent
+	 * and compare it to what the iso packer was using at the
+	 * time.  If there is a mismatch, we adjust the cycle count in
+	 * the iso packer.  However, there are still up to
+	 * MAX_PACKET_LISTS packet lists queued with bad time stamps,
+	 * so we disable time stamp monitoring for the next
+	 * MAX_PACKET_LISTS packet lists.
+	 */
+	diff = (last->db->payload_desc.status - pl->last_cycle_count) & 0xf;
+	if (diff > 0 && s->stale_count == 0) {
+		atomic_add(diff, &s->cycle_count);
+		atomic_add(diff, &s->cycle_count2);
+		s->stale_count = MAX_PACKET_LISTS;
+	}
+
+	if (s->stale_count > 0)
+		s->stale_count--;
+
+	/* Finally, we move the packet list that was just processed
+	 * back to the free list, and notify any waiters.
+	 */
+	spin_lock(&s->packet_list_lock);
+	list_del(&pl->link);
+	list_add_tail(&pl->link, &s->free_packet_lists);
+	spin_unlock(&s->packet_list_lock);
+
+	wake_up_interruptible(&s->packet_list_wait);
+}
+
+static struct packet *stream_current_packet(struct stream *s)
+{
+	if (s->current_packet_list == NULL &&
+	    (s->current_packet_list = stream_get_free_packet_list(s)) == NULL)
+		return NULL;
+
+	return &s->current_packet_list->packets[s->current_packet];
+}
+	
+static void stream_queue_packet(struct stream *s)
+{
+	s->current_packet++;
+	if (s->current_packet == PACKET_LIST_SIZE) {
+		stream_put_dma_packet_list(s, s->current_packet_list);
+		s->current_packet_list = NULL;
+		s->current_packet = 0;
+	}
+}
+
+/* Integer fractional math.  When we transmit a 44k1Hz signal we must
+ * send 5 41/80 samples per isochronous cycle, as these occur 8000
+ * times a second.  Of course, we must send an integral number of
+ * samples in a packet, so we use the integer math to alternate
+ * between sending 5 and 6 samples per packet.
+ */
+
+static void fraction_init(struct fraction *f, int numerator, int denominator)
+{
+	f->integer = numerator / denominator;
+	f->numerator = numerator % denominator;
+	f->denominator = denominator;
+	f->counter = 0;
+}
+
+static int fraction_next_size(struct fraction *f)
+{
+	return f->integer + ((f->counter + f->numerator) / f->denominator);
+}
+
+static void fraction_inc(struct fraction *f)
+{
+	f->counter = (f->counter + f->numerator) % f->denominator;
+}
+
+static void amdtp_irq_handler(int card, quadlet_t isoRecvIntEvent,
+			      quadlet_t isoXmitIntEvent, void *data)
+{
+	struct amdtp_host *host = data;
+	struct list_head *lh;
+	struct stream *s = NULL;
+
+	spin_lock(&host->stream_list_lock);
+	list_for_each(lh, &host->stream_list) {
+		s = list_entry(lh, struct stream, link);
+		if (isoXmitIntEvent & (1 << s->iso_context))
+			break;
+	}
+	spin_unlock(&host->stream_list_lock);
+
+	if (s != NULL)
+		stream_shift_packet_lists(s);
+}
+
+void packet_initialize(struct packet *p, struct packet *next)
+{
+	/* Here we initialize the dma descriptor block for
+	 * transferring one iso packet.  We use two descriptors per
+	 * packet: an OUTPUT_MORE_IMMMEDIATE descriptor for the
+	 * IEEE1394 iso packet header and an OUTPUT_LAST descriptor
+	 * for the payload.
+	 */
+
+	p->db->header_desc.control =
+		DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 8;
+	p->db->header_desc.skip = 0;
+
+	if (next) {
+		p->db->payload_desc.control = 
+			DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
+		p->db->payload_desc.branch = next->db_bus | 3;
+	}
+	else {
+		p->db->payload_desc.control = 
+			DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH |
+			DMA_CTL_UPDATE | DMA_CTL_IRQ;
+		p->db->payload_desc.branch = 0;
+	}
+	p->db->payload_desc.data_address = p->payload_bus;
+	p->db->payload_desc.status = 0;
+}
+
+struct packet_list *packet_list_alloc(struct stream *s)
+{
+	int i;
+	struct packet_list *pl;
+	struct packet *next;
+
+	pl = kmalloc(sizeof *pl, SLAB_KERNEL);
+	if (pl == NULL)
+		return NULL;
+
+	for (i = 0; i < PACKET_LIST_SIZE; i++) {
+		struct packet *p = &pl->packets[i];
+		p->db = pci_pool_alloc(s->descriptor_pool, SLAB_KERNEL,
+				       &p->db_bus);
+		p->payload = pci_pool_alloc(s->packet_pool, SLAB_KERNEL,
+					    &p->payload_bus);
+	}
+
+	for (i = 0; i < PACKET_LIST_SIZE; i++) {
+		if (i < PACKET_LIST_SIZE - 1)
+			next = &pl->packets[i + 1];
+		else 
+			next = NULL;
+		packet_initialize(&pl->packets[i], next);
+	}
+
+	return pl;
+}
+
+void packet_list_free(struct packet_list *pl, struct stream *s)
+{
+	int i;
+
+	for (i = 0; i < PACKET_LIST_SIZE; i++) {
+		struct packet *p = &pl->packets[i];
+		pci_pool_free(s->descriptor_pool, p->db, p->db_bus);
+		pci_pool_free(s->packet_pool, p->payload, p->payload_bus);
+	}
+	kfree(pl);
+}
+
+static struct buffer *buffer_alloc(int size)
+{
+	struct buffer *b;
+
+	b = kmalloc(sizeof *b + size, SLAB_KERNEL);
+	b->head = 0;
+	b->tail = 0;
+	b->length = 0;
+	b->size = size;
+
+	return b;
+}
+
+static unsigned char *buffer_get_bytes(struct buffer *buffer, int size)
+{
+	unsigned char *p;
+
+	if (buffer->head + size > buffer->size)
+		BUG();
+
+	p = &buffer->data[buffer->head];
+	buffer->head += size;
+	if (buffer->head == buffer->size)
+		buffer->head = 0;
+	buffer->length -= size;
+
+	return p;
+}
+
+static unsigned char *buffer_put_bytes(struct buffer *buffer,
+				       int max, int *actual)
+{
+	int length;
+	unsigned char *p;
+
+	p = &buffer->data[buffer->tail];
+	length = min(buffer->size - buffer->length, max);
+	if (buffer->tail + length < buffer->size) {
+		*actual = length;
+		buffer->tail += length;
+	}
+	else {
+		*actual = buffer->size - buffer->tail;
+		 buffer->tail = 0;
+	}
+
+	buffer->length += *actual;
+	return p;
+}
+
+static u32 get_iec958_header_bits(struct stream *s, int sub_frame, u32 sample)
+{
+	int csi, parity, shift;
+	int block_start;
+	u32 bits;
+
+	switch (s->iec958_frame_count) {
+	case 1:
+		csi = s->format == AMDTP_FORMAT_IEC958_AC3;
+		break;
+	case 2:
+	case 9:
+		csi = 1;
+		break;
+	case 24 ... 27:
+		csi = (s->iec958_rate_code >> (27 - s->iec958_frame_count)) & 0x01;
+		break;
+	default:
+		csi = 0;
+		break;
+	}
+
+	block_start = (s->iec958_frame_count == 0 && sub_frame == 0);
+
+	/* The parity bit is the xor of the sample bits and the
+	 * channel status info bit. */
+	for (shift = 16, parity = sample ^ csi; shift > 0; shift >>= 1)
+		parity ^= (parity >> shift);
+
+	bits =  (block_start << 5) |		/* Block start bit */
+		((sub_frame == 0) << 4) |	/* Subframe bit */
+		((parity & 1) << 3) |		/* Parity bit */
+		(csi << 2);			/* Channel status info bit */
+
+	return bits;
+}
+
+static u32 get_header_bits(struct stream *s, int sub_frame, u32 sample)
+{
+	switch (s->format) {
+	case AMDTP_FORMAT_IEC958_PCM:
+	case AMDTP_FORMAT_IEC958_AC3:
+		return get_iec958_header_bits(s, sub_frame, sample);
+		
+	case AMDTP_FORMAT_RAW:
+		return 0x40000000;
+
+	default:
+		return 0;
+	}
+}
+
+
+static void fill_packet(struct stream *s, struct packet *packet, int nevents)
+{
+	int size, node_id, i, j;
+	quadlet_t *event;
+	unsigned char *p;
+	u32 control, sample, bits;
+	int syt_index, syt, next;
+
+	size = (nevents * s->dimension + 2) * sizeof(quadlet_t);
+	node_id = s->host->host->node_id & 0x3f;
+
+	/* Update DMA descriptors */
+	packet->db->payload_desc.status = 0;
+	control = packet->db->payload_desc.control & 0xffff0000;
+	packet->db->payload_desc.control = control | size;
+
+	/* Fill IEEE1394 headers */
+	packet->db->header_desc.header[0] =
+		(SPEED_100 << 16) | (0x01 << 14) | 
+		(s->iso_channel << 8) | (TCODE_ISO_DATA << 4);
+	packet->db->header_desc.header[1] = size << 16;
+	
+	/* Fill cip header */
+	syt_index = s->dbc & (s->syt_interval - 1);
+	if (syt_index == 0 || syt_index + nevents > s->syt_interval) {
+		syt = ((atomic_read(&s->cycle_count) << 12) | 
+		       s->cycle_offset) & 0xffff;
+		next = fraction_next_size(&s->syt_fraction) + s->cycle_offset;
+		/* This next addition should be modulo 8000 (0x1f40),
+		 * but we only use the lower 4 bits of cycle_count, so
+		 * we dont need the modulo. */
+		atomic_add(next / 3072, &s->cycle_count);
+		s->cycle_offset = next % 3072;
+		fraction_inc(&s->syt_fraction);
+	}
+	else {
+		syt = 0xffff;
+		next = 0;
+	}
+	atomic_inc(&s->cycle_count2);
+
+	packet->payload[0] = cpu_to_be32((node_id << 24) | (s->dimension << 16) | s->dbc);
+	packet->payload[1] = cpu_to_be32((1 << 31) | (FMT_AMDTP << 24) | (s->fdf << 16) | syt);
+
+	/* Fill payload */
+	for (i = 0, event = &packet->payload[2]; i < nevents; i++) {
+
+		for (j = 0; j < s->dimension; j++) {
+			p = buffer_get_bytes(s->input, 2);
+			sample = (p[1] << 16) | (p[0] << 8);
+			bits = get_header_bits(s, j, sample);
+			event[j] = cpu_to_be32((bits << 24) | sample);
+		}
+
+		event += s->dimension;
+		if (++s->iec958_frame_count == 192)
+			s->iec958_frame_count = 0;
+	}
+
+	s->dbc += nevents;
+}
+
+static void stream_flush(struct stream *s)
+{
+	struct packet *p;
+	int nevents;
+
+	while (nevents = fraction_next_size(&s->packet_size_fraction),
+	       p = stream_current_packet(s),
+	       nevents * s->dimension * 2 <= s->input->length && p != NULL) {
+		fill_packet(s, p, nevents);
+		fraction_inc(&s->packet_size_fraction);
+		stream_queue_packet(s);
+	}
+}
+
+static int stream_alloc_packet_lists(struct stream *s)
+{
+	int max_nevents, max_packet_size, i;
+
+	max_nevents = s->packet_size_fraction.integer;
+	if (s->packet_size_fraction.numerator > 0)
+		max_nevents++;
+
+	max_packet_size = max_nevents * s->dimension * 4 + 8;
+	s->packet_pool = pci_pool_create("packet pool", s->host->ohci->dev,
+					 max_packet_size, 0, 0, SLAB_KERNEL);
+	if (s->packet_pool == NULL)
+		return -1;
+
+	INIT_LIST_HEAD(&s->free_packet_lists);
+	INIT_LIST_HEAD(&s->dma_packet_lists);
+	for (i = 0; i < MAX_PACKET_LISTS; i++) {
+		struct packet_list *pl = packet_list_alloc(s);
+		if (pl == NULL)
+			break;
+		list_add_tail(&pl->link, &s->free_packet_lists);
+	}
+
+	return i < MAX_PACKET_LISTS ? -1 : 0;
+}
+
+static void stream_free_packet_lists(struct stream *s)
+{
+	struct list_head *lh, *next;
+
+	if (s->current_packet_list != NULL)
+		packet_list_free(s->current_packet_list, s);
+	list_for_each_safe(lh, next, &s->dma_packet_lists)
+		packet_list_free(list_entry(lh, struct packet_list, link), s);
+	list_for_each_safe(lh, next, &s->free_packet_lists)
+		packet_list_free(list_entry(lh, struct packet_list, link), s);
+	if (s->packet_pool != NULL)
+		pci_pool_destroy(s->packet_pool);
+
+	s->current_packet_list = NULL;
+	INIT_LIST_HEAD(&s->free_packet_lists);
+	INIT_LIST_HEAD(&s->dma_packet_lists);
+	s->packet_pool = NULL;
+}
+
+static void plug_update(struct cmp_pcr *plug, void *data)
+{
+	struct stream *s = data;
+
+	HPSB_INFO("plug update: p2p_count=%d, channel=%d",
+		  plug->p2p_count, plug->channel);
+	s->iso_channel = plug->channel;
+	if (plug->p2p_count > 0) {
+		/* start streaming */
+	}
+	else {
+		/* stop streaming */
+	}
+}
+
+static int stream_configure(struct stream *s, int cmd, struct amdtp_ioctl *cfg)
+{
+	if (cfg->format <= AMDTP_FORMAT_IEC958_AC3)
+		s->format = cfg->format;
+	else
+		return -EINVAL;
+
+	switch (cfg->rate) {
+	case 32000:
+		s->syt_interval = 8;
+		s->fdf = FDF_SFC_32KHZ;
+		s->iec958_rate_code = 0x0c;
+		s->rate = cfg->rate;
+		break;
+	case 44100:
+		s->syt_interval = 8;
+		s->fdf = FDF_SFC_44K1HZ;
+		s->iec958_rate_code = 0x00;
+		s->rate = cfg->rate;
+		break;
+	case 48000:
+		s->syt_interval = 8;
+		s->fdf = FDF_SFC_48KHZ;
+		s->iec958_rate_code = 0x04;
+		s->rate = cfg->rate;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	fraction_init(&s->packet_size_fraction, s->rate, 8000);
+
+	/* The syt_fraction is initialized to the number of ticks
+	 * between syt_interval events.  The number of ticks per
+	 * second is 24.576e6, so the number of ticks between
+	 * syt_interval events is 24.576e6 * syt_interval / rate.
+	 */
+	fraction_init(&s->syt_fraction, 24576000 * s->syt_interval, s->rate);
+
+	/* When using the AM824 raw subformat we can stream signals of
+	 * any dimension.  The IEC958 subformat, however, only
+	 * supports 2 channels.
+	 */
+	if (s->format == AMDTP_FORMAT_RAW || cfg->dimension == 2)
+		s->dimension = cfg->dimension;
+	else
+		return -EINVAL;
+
+	if (s->opcr != NULL) {
+		cmp_unregister_opcr(s->host->host, s->opcr);
+		s->opcr = NULL;
+	}
+
+	switch(cmd) {
+	case AMDTP_IOC_PLUG:
+		s->opcr = cmp_register_opcr(s->host->host, cfg->u.plug,
+					   /*payload*/ 12, plug_update, s);
+		if (s->opcr == NULL)
+			return -EINVAL;
+		s->iso_channel = s->opcr->channel;
+		break;
+
+	case AMDTP_IOC_CHANNEL:
+		if (cfg->u.channel >= 0 && cfg->u.channel < 64)
+			s->iso_channel = cfg->u.channel;
+		else
+			return -EINVAL;
+		break;
+	}
+
+	/* The ioctl settings were all valid, so we realloc the packet
+	 * lists to make sure the packet size is big enough.
+	 */
+	if (s->packet_pool != NULL)
+		stream_free_packet_lists(s);
+
+	if (stream_alloc_packet_lists(s) < 0) {
+		stream_free_packet_lists(s);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+struct stream *stream_alloc(struct amdtp_host *host)
+{
+	struct stream *s;
+	unsigned long flags;
+	const int transfer_delay = 8651; /* approx 352 us */
+
+        s = kmalloc(sizeof(struct stream), SLAB_KERNEL);
+        if (s == NULL)
+                return NULL;
+
+        memset(s, 0, sizeof(struct stream));
+	s->host = host;
+
+	s->input = buffer_alloc(BUFFER_SIZE);
+	if (s->input == NULL) {
+		kfree(s);
+		return NULL;
+	}
+
+	s->cycle_offset = transfer_delay % 3072;
+	atomic_set(&s->cycle_count, transfer_delay / 3072);
+	atomic_set(&s->cycle_count2, 0);
+
+	s->descriptor_pool = pci_pool_create("descriptor pool", host->ohci->dev,
+					     sizeof(struct descriptor_block),
+					     16, 0, SLAB_KERNEL);
+	if (s->descriptor_pool == NULL) {
+		kfree(s->input);
+		kfree(s);
+		return NULL;
+	}
+
+	INIT_LIST_HEAD(&s->free_packet_lists);
+	INIT_LIST_HEAD(&s->dma_packet_lists);
+
+        init_waitqueue_head(&s->packet_list_wait);
+        spin_lock_init(&s->packet_list_lock);
+
+	s->iso_context = ohci1394_alloc_it_ctx(host->ohci);
+	if (s->iso_context < 0) {
+		pci_pool_destroy(s->descriptor_pool);
+		kfree(s->input);
+		kfree(s);
+		return NULL;
+	}
+
+	spin_lock_irqsave(&host->stream_list_lock, flags);
+	list_add_tail(&s->link, &host->stream_list);
+	spin_unlock_irqrestore(&host->stream_list_lock, flags);
+
+	return s;
+}
+
+void stream_free(struct stream *s)
+{
+	unsigned long flags;
+
+	/* Stop the DMA.  We wait for the dma packet list to become
+	 * empty and let the dma controller run out of programs.  This
+	 * seems to be more reliable than stopping it directly, since
+	 * that sometimes generates an it transmit interrupt if we
+	 * later re-enable the context.
+	 */
+	wait_event_interruptible(s->packet_list_wait, 
+				 list_empty(&s->dma_packet_lists));
+
+	ohci1394_stop_it_ctx(s->host->ohci, s->iso_context);
+	ohci1394_free_it_ctx(s->host->ohci, s->iso_context);
+
+	if (s->opcr != NULL)
+		cmp_unregister_opcr(s->host->host, s->opcr);
+
+	spin_lock_irqsave(&s->host->stream_list_lock, flags);
+	list_del(&s->link);
+	spin_unlock_irqrestore(&s->host->stream_list_lock, flags);
+
+	kfree(s->input);
+
+	stream_free_packet_lists(s);
+	pci_pool_destroy(s->descriptor_pool);
+
+	kfree(s);
+}
+
+/* File operations */
+
+static ssize_t amdtp_write(struct file *file, const char *buffer, size_t count,
+			   loff_t *offset_is_ignored)
+{
+	struct stream *s = file->private_data;
+	unsigned char *p;
+	int i, length;
+	
+	if (s->packet_pool == NULL)
+		return -EBADFD;
+
+	/* Fill the circular buffer from the input buffer and call the
+	 * iso packer when the buffer is full.  The iso packer may
+	 * leave bytes in the buffer for two reasons: either the
+	 * remaining bytes wasn't enough to build a new packet, or
+	 * there were no free packet lists.  In the first case we
+	 * re-fill the buffer and call the iso packer again or return
+	 * if we used all the data from userspace.  In the second
+	 * case, the wait_event_interruptible will block until the irq
+	 * handler frees a packet list.
+	 */
+
+	for (i = 0; i < count; i += length) {
+		p = buffer_put_bytes(s->input, count, &length);
+		copy_from_user(p, buffer + i, length);
+		if (s->input->length < s->input->size)
+			continue;
+		
+		stream_flush(s);
+		
+		if (s->current_packet_list == NULL &&
+		    wait_event_interruptible(s->packet_list_wait, 
+					     !list_empty(&s->free_packet_lists)))
+			return -EINTR;
+	}
+
+	return count;
+}
+
+static int amdtp_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	struct stream *s = file->private_data;
+	struct amdtp_ioctl cfg;
+	int new;
+
+	switch(cmd)
+	{
+	case AMDTP_IOC_PLUG:
+	case AMDTP_IOC_CHANNEL:
+		if (copy_from_user(&cfg, (struct amdtp_ioctl *) arg, sizeof cfg))
+			return -EFAULT;
+		else 
+			return stream_configure(s, cmd, &cfg);
+
+	case AMDTP_IOC_PING:
+		HPSB_INFO("ping: offsetting timpestamps %ld ticks", arg);
+		new = s->cycle_offset + arg;
+		s->cycle_offset = new % 3072;
+		atomic_add(new / 3072, &s->cycle_count);
+		return 0;
+
+	case AMDTP_IOC_ZAP:
+		while (MOD_IN_USE)
+			MOD_DEC_USE_COUNT;
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int amdtp_open(struct inode *inode, struct file *file)
+{
+	struct amdtp_host *host;
+
+	/* FIXME: We just grab the first registered host */
+	spin_lock(&host_list_lock);
+	if (!list_empty(&host_list))
+		host = list_entry(host_list.next, struct amdtp_host, link);
+	else
+		host = NULL;
+	spin_unlock(&host_list_lock);
+
+	if (host == NULL)
+		return -ENODEV;
+
+	file->private_data = stream_alloc(host);
+	if (file->private_data == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int amdtp_release(struct inode *inode, struct file *file)
+{
+	struct stream *s = file->private_data;
+
+	stream_free(s);
+
+	return 0;
+}
+
+static struct file_operations amdtp_fops =
+{
+	owner:		THIS_MODULE,
+	write:		amdtp_write,
+	ioctl:		amdtp_ioctl,
+	open:		amdtp_open,
+	release:	amdtp_release
+};
+
+/* IEEE1394 Subsystem functions */
+
+static void amdtp_add_host(struct hpsb_host *host)
+{
+	struct amdtp_host *ah;
+
+	/* FIXME: check it's an ohci host. */
+
+	ah = kmalloc(sizeof *ah, SLAB_KERNEL);
+	ah->host = host;
+	ah->ohci = host->hostdata;
+	INIT_LIST_HEAD(&ah->stream_list);
+	spin_lock_init(&ah->stream_list_lock);
+
+	spin_lock_irq(&host_list_lock);
+	list_add_tail(&ah->link, &host_list);
+	spin_unlock_irq(&host_list_lock);
+
+	ohci1394_hook_irq(ah->ohci, amdtp_irq_handler, ah);
+}
+
+static void amdtp_remove_host(struct hpsb_host *host)
+{
+	struct list_head *lh;
+	struct amdtp_host *ah;
+
+	spin_lock_irq(&host_list_lock);
+	list_for_each(lh, &host_list) {
+		if (list_entry(lh, struct amdtp_host, link)->host == host) {
+			list_del(lh);
+			break;
+		}
+	}
+	spin_unlock_irq(&host_list_lock);
+	
+	if (lh != &host_list) {
+		ah = list_entry(lh, struct amdtp_host, link);
+		ohci1394_unhook_irq(ah->ohci, amdtp_irq_handler, ah);
+		kfree(ah);
+	}
+	else
+		HPSB_ERR("remove_host: bogus ohci host: %p", host);
+}
+
+static struct hpsb_highlevel_ops amdtp_highlevel_ops = {
+	add_host:	amdtp_add_host,
+	remove_host:	amdtp_remove_host,
+};
+
+/* Module interface */
+
+MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
+MODULE_DESCRIPTION("Driver for Audio & Music Data Transmission Protocol "
+		   "on OHCI boards.");
+MODULE_SUPPORTED_DEVICE("amdtp");
+MODULE_LICENSE("GPL");
+
+static int __init amdtp_init_module (void)
+{
+	if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_EXPERIMENTAL,
+				      THIS_MODULE, &amdtp_fops)) {
+		HPSB_ERR("amdtp: unable to get minor device block");
+ 		return -EIO;
+ 	}
+
+	amdtp_highlevel = hpsb_register_highlevel ("amdtp",
+						   &amdtp_highlevel_ops);
+	if (amdtp_highlevel == NULL) {
+		HPSB_ERR("amdtp: unable to register highlevel ops");
+		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_EXPERIMENTAL);
+		return -EIO;
+	}
+
+	HPSB_INFO("Loaded AMDTP driver");
+
+	return 0;
+}
+
+static void __exit amdtp_exit_module (void)
+{
+        hpsb_unregister_highlevel(amdtp_highlevel);
+        ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_EXPERIMENTAL);
+
+	HPSB_INFO("Unloaded AMDTP driver");
+}
+
+module_init(amdtp_init_module);
+module_exit(amdtp_exit_module);
diff -Nru a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/amdtp.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,75 @@
+/* -*- c-basic-offset: 8 -*- */
+
+#ifndef __AMDTP_H
+#define __AMDTP_H
+
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+/* The userspace interface for the Audio & Music Data Transmission
+ * Protocol driver is really simple. First, open /dev/amdtp, use the
+ * ioctl to configure format, rate, dimension and either plug or
+ * channel, then start writing samples.
+ *
+ * The formats supported by the driver are listed below.
+ * AMDTP_FORMAT_RAW corresponds to the AM824 raw format, which can
+ * carry any number of channels, so use this if you're streaming
+ * multichannel audio.  The AMDTP_FORMAT_IEC958_PCM corresponds to the
+ * AM824 IEC958 encapsulation without the IEC958 data bit set, using
+ * AMDTP_FORMAT_IEC958_AC3 will transmit the samples with the data bit
+ * set, suitable for transmitting compressed AC-3 audio.
+ *
+ * The rate field specifies the transmission rate; supported values are
+ * AMDTP_RATE_32KHZ, AMDTP_RATE_44K1HZ and AMDTP_RATE_48KHZ.
+ *
+ * The dimension field specifies the dimension of the signal, that is,
+ * the number of audio channels.  Only AMDTP_FORMAT_RAW supports
+ * settings greater than 2.  
+ *
+ * The last thing to specify is either the isochronous channel to use
+ * or the output plug to connect to.  If you know what channel the
+ * destination device will listen on, you can specify the channel
+ * directly and use the AMDTP_IOC_CHANNEL ioctl.  However, if the
+ * destination device chooses the channel and uses the IEC61883-1 plug
+ * mechanism, you can specify an output plug to connect to.  The
+ * driver will pick up the channel number from the plug once the
+ * destination device locks the output plug control register.  In this
+ * case set the plug field and use the AMDTP_IOC_PLUG ioctl.
+ *
+ * Having configured the interface, the driver now accepts writes of
+ * regular 16 bit signed little endian samples, with the channels
+ * interleaved.  For example, 4 channels would look like:
+ *
+ *   | sample 0                                      | sample 1    ...
+ *   | ch. 0     | ch. 1     | ch. 2     | ch. 3     | ch. 0     | ...
+ *   | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ...
+ *
+ */
+
+/* We use '#' for our ioctl magic number because it's cool. */
+
+#define AMDTP_IOC_CHANNEL _IOW('#', 0, sizeof (struct amdtp_ioctl))
+#define AMDTP_IOC_PLUG    _IOW('#', 1, sizeof (struct amdtp_ioctl))
+#define AMDTP_IOC_PING    _IOW('#', 2, sizeof (struct amdtp_ioctl))
+#define AMDTP_IOC_ZAP     _IO('#', 3)
+
+enum {
+	AMDTP_FORMAT_RAW,
+	AMDTP_FORMAT_IEC958_PCM,
+	AMDTP_FORMAT_IEC958_AC3
+};
+
+enum {
+	AMDTP_RATE_32KHZ,
+	AMDTP_RATE_44K1HZ,
+	AMDTP_RATE_48KHZ,
+};
+
+struct amdtp_ioctl {
+	__u32 format;
+	__u32 rate;
+	__u32 dimension;
+	union { __u32 channel; __u32 plug; } u;
+};
+
+#endif /* __AMDTP_H */
diff -Nru a/drivers/ieee1394/cmp.c b/drivers/ieee1394/cmp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/cmp.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,348 @@
+/* -*- c-basic-offset: 8 -*-
+ *
+ * cmp.c - Connection Management Procedures
+ * Copyright (C) 2001 Kristian Høgsberg
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+/* TODO
+ * ----
+ *
+ * - Implement IEC61883-1 output plugs and connection management.
+ *   This should probably be part of the general subsystem, as it could
+ *   be shared with dv1394.
+ *
+ * - Add IEC61883 unit directory when loading this module.  This
+ *   requires a run-time changeable config rom.
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+
+#include "hosts.h"
+#include "highlevel.h"
+#include "ieee1394.h"
+#include "ieee1394_core.h"
+#include "cmp.h"
+
+struct plug {
+	union {
+		struct cmp_pcr pcr;
+		quadlet_t quadlet;
+	} u;
+	void (*update)(struct cmp_pcr *plug, void *data);
+	void *data;
+};
+
+struct cmp_host {
+	struct hpsb_host *host;
+
+	union {
+		struct cmp_mpr ompr;
+		quadlet_t ompr_quadlet;
+	} u;
+	struct plug opcr[2];
+
+	union {
+		struct cmp_mpr impr;
+		quadlet_t impr_quadlet;
+	} v;
+	struct plug ipcr[2];
+
+	struct list_head link;
+};
+
+enum {
+	CMP_P2P_CONNECTION,
+	CMP_BC_CONNECTION
+};
+
+#define CSR_PCR_MAP      0x900
+#define CSR_PCR_MAP_END  0x9fc
+
+static struct hpsb_highlevel *cmp_highlevel;
+
+static LIST_HEAD(host_list);
+static spinlock_t host_list_lock = SPIN_LOCK_UNLOCKED;
+
+static struct cmp_host *
+lookup_cmp_host(struct hpsb_host *host)
+{
+	struct cmp_host *ch;
+	struct list_head *lh;
+	unsigned long flags;
+
+	ch = NULL;
+	spin_lock_irqsave(&host_list_lock, flags);
+	list_for_each(lh, &host_list) {
+		ch = list_entry(lh, struct cmp_host, link);
+		if (ch->host == host)
+			break;
+	}
+	spin_unlock_irqrestore(&host_list_lock, flags);
+
+	if (lh == &host_list)
+		return NULL;
+	else
+		return ch;
+}
+
+struct cmp_pcr *
+cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
+		  void (*update)(struct cmp_pcr *pcr, void *data),
+		  void *data)
+{
+	struct cmp_host *ch;
+	struct plug *plug;
+
+	ch = lookup_cmp_host(host);
+
+	if (opcr_number >= ch->u.ompr.nplugs ||
+	    ch->opcr[opcr_number].update != NULL)
+		return NULL;
+
+	plug = &ch->opcr[opcr_number];
+	plug->u.pcr.online = 1;
+	plug->u.pcr.bcast_count = 0;
+	plug->u.pcr.p2p_count = 0;
+	plug->u.pcr.overhead = 0;
+	plug->u.pcr.payload = payload;
+	plug->update = update;
+	plug->data = data;
+
+	return &plug->u.pcr;
+}
+
+void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr)
+{
+	struct cmp_host *ch;
+	struct plug *plug;
+
+	ch = lookup_cmp_host(host);
+	plug = (struct plug *)opcr;
+	if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG();
+
+	plug->u.pcr.online = 0;
+	plug->update = NULL;
+}
+
+static void reset_plugs(struct cmp_host *ch)
+{
+	int i;
+
+	ch->u.ompr.non_persistent_ext = 0xff;
+	for (i = 0; i < ch->u.ompr.nplugs; i++) {
+		ch->opcr[i].u.pcr.bcast_count = 0;
+		ch->opcr[i].u.pcr.p2p_count = 0;
+		ch->opcr[i].u.pcr.overhead = 0;
+	}
+}
+
+static void cmp_add_host(struct hpsb_host *host)
+{
+	struct cmp_host *ch;
+
+	ch = kmalloc(sizeof *ch, SLAB_KERNEL);
+	if (ch == NULL) {
+		HPSB_ERR("Failed to allocate cmp_host");
+		return;
+	}
+	memset(ch, 0, sizeof *ch);
+	ch->host = host;
+	ch->u.ompr.rate = SPEED_100;
+	ch->u.ompr.bcast_channel_base = 63;
+	ch->u.ompr.nplugs = 2;
+	reset_plugs(ch);
+
+	spin_lock_irq(&host_list_lock);
+	list_add_tail(&ch->link, &host_list);
+	spin_unlock_irq(&host_list_lock);
+}
+
+static void cmp_host_reset(struct hpsb_host *host)
+{
+	struct cmp_host *ch;
+
+	ch = lookup_cmp_host(host);
+	if (ch == NULL) BUG();
+	reset_plugs(ch);
+}
+
+static void cmp_remove_host(struct hpsb_host *host)
+{
+	struct cmp_host *ch;
+
+	ch = lookup_cmp_host(host);
+	if (ch == NULL) BUG();
+
+	spin_lock_irq(&host_list_lock);
+	list_del(&ch->link);
+	spin_unlock_irq(&host_list_lock);
+
+	kfree(ch);
+}
+
+static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
+		    u64 addr, unsigned int length)
+{
+	int csraddr = addr - CSR_REGISTER_BASE;
+	int plug;
+	struct cmp_host *ch;
+	
+	if (length != 4)
+		return RCODE_TYPE_ERROR;
+
+	ch = lookup_cmp_host(host);
+	if (csraddr == 0x900) {
+		*buf = cpu_to_be32(ch->u.ompr_quadlet);
+		return RCODE_COMPLETE;   
+	}
+	else if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
+		plug = (csraddr - 0x904) / 4;
+		*buf = cpu_to_be32(ch->opcr[plug].u.quadlet);
+		return RCODE_COMPLETE;
+	}
+	else if (csraddr < 0x980) {
+		return RCODE_ADDRESS_ERROR;
+	}
+	else if (csraddr == 0x980) {
+		*buf = cpu_to_be32(ch->v.impr_quadlet);
+		return RCODE_COMPLETE;   
+	}
+	else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
+		plug = (csraddr - 0x984) / 4;
+		*buf = cpu_to_be32(ch->ipcr[plug].u.quadlet);
+		return RCODE_COMPLETE;
+	}
+	else
+		return RCODE_ADDRESS_ERROR;
+}
+
+static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
+		    u64 addr, quadlet_t data, quadlet_t arg, int extcode)
+{
+	int csraddr = addr - CSR_REGISTER_BASE;
+	int plug;
+	struct cmp_host *ch;
+
+	ch = lookup_cmp_host(host);
+	
+	if (extcode != EXTCODE_COMPARE_SWAP) 
+		return RCODE_TYPE_ERROR;
+	
+	if (csraddr == 0x900) {
+		/* FIXME: Ignore writes to bits 30-31 and 0-7 */
+		*store = cpu_to_be32(ch->u.ompr_quadlet);
+		if (arg == cpu_to_be32(ch->u.ompr_quadlet))
+			ch->u.ompr_quadlet = be32_to_cpu(data);
+
+		return RCODE_COMPLETE;
+	}
+	if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
+		plug = (csraddr - 0x904) / 4;
+		*store = cpu_to_be32(ch->opcr[plug].u.quadlet);
+
+		if (arg == *store)
+			ch->opcr[plug].u.quadlet = be32_to_cpu(data);
+
+		if (be32_to_cpu(*store) != ch->opcr[plug].u.quadlet &&
+		    ch->opcr[plug].update != NULL)
+			ch->opcr[plug].update(&ch->opcr[plug].u.pcr,
+					      ch->opcr[plug].data);
+
+		return RCODE_COMPLETE;
+	}
+	else if (csraddr < 0x980) {
+		return RCODE_ADDRESS_ERROR;
+	}
+	else if (csraddr == 0x980) {
+		/* FIXME: Ignore writes to bits 24-31 and 0-7 */
+		*store = cpu_to_be32(ch->u.ompr_quadlet);
+		if (arg == cpu_to_be32(ch->u.ompr_quadlet))
+			ch->u.ompr_quadlet = be32_to_cpu(data);
+
+		return RCODE_COMPLETE;
+	}
+	else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
+		plug = (csraddr - 0x984) / 4;
+		*store = cpu_to_be32(ch->ipcr[plug].u.quadlet);
+
+		if (arg == *store)
+			ch->ipcr[plug].u.quadlet = be32_to_cpu(data);
+
+		if (be32_to_cpu(*store) != ch->ipcr[plug].u.quadlet &&
+		    ch->ipcr[plug].update != NULL)
+			ch->ipcr[plug].update(&ch->ipcr[plug].u.pcr,
+					      ch->ipcr[plug].data);
+
+		return RCODE_COMPLETE;
+	}
+	else
+		return RCODE_ADDRESS_ERROR;
+}
+
+
+static struct hpsb_highlevel_ops cmp_highlevel_ops = {
+	add_host:	cmp_add_host,
+	remove_host:	cmp_remove_host,
+        host_reset:	cmp_host_reset,
+};
+
+static struct hpsb_address_ops pcr_ops = {
+        read: pcr_read,
+        lock: pcr_lock,
+};
+
+/* Module interface */
+
+MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
+MODULE_DESCRIPTION("Connection Management Procedures (CMP)");
+MODULE_SUPPORTED_DEVICE("cmp");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cmp_register_opcr);
+EXPORT_SYMBOL(cmp_unregister_opcr);
+
+static int __init cmp_init_module (void)
+{
+	cmp_highlevel = hpsb_register_highlevel ("cmp",
+						 &cmp_highlevel_ops);
+	if (cmp_highlevel == NULL) {
+		HPSB_ERR("cmp: unable to register highlevel ops");
+		return -EIO;
+	}
+
+	hpsb_register_addrspace(cmp_highlevel, &pcr_ops,
+				CSR_REGISTER_BASE + CSR_PCR_MAP,
+				CSR_REGISTER_BASE + CSR_PCR_MAP_END);
+
+	HPSB_INFO("Loaded CMP driver");
+
+	return 0;
+}
+
+static void __exit cmp_exit_module (void)
+{
+        hpsb_unregister_highlevel(cmp_highlevel);
+
+	HPSB_INFO("Unloaded CMP driver");
+}
+
+module_init(cmp_init_module);
+module_exit(cmp_exit_module);
diff -Nru a/drivers/ieee1394/cmp.h b/drivers/ieee1394/cmp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/cmp.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,31 @@
+#ifndef __CMP_H
+#define __CMP_H
+
+struct cmp_mpr {
+	u32 nplugs:5;
+	u32 reserved:3;
+	u32 persistent_ext:8;
+	u32 non_persistent_ext:8;
+	u32 bcast_channel_base:6;
+	u32 rate:2;
+} __attribute__((packed));
+
+struct cmp_pcr {
+	u32 payload:10;
+	u32 overhead:4;
+	u32 speed:2;
+	u32 channel:6;
+	u32 reserved:2;
+	u32 p2p_count:6;
+	u32 bcast_count:1;
+	u32 online:1;
+} __attribute__((packed));
+
+struct cmp_pcr *cmp_register_opcr(struct hpsb_host *host, int plug,
+				  int payload,
+				  void (*update)(struct cmp_pcr *plug,
+						 void *data),
+				  void *data);
+void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *plug);
+
+#endif /* __CMP_H */
diff -Nru a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h
--- a/drivers/ieee1394/dv1394-private.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/ieee1394/dv1394-private.h	Sun Apr 14 12:16:55 2002
@@ -412,6 +412,10 @@
 /* struct video_card contains all data associated with one instance
    of the dv1394 driver 
 */
+enum modes {
+	MODE_RECEIVE,
+	MODE_TRANSMIT
+};
 
 struct video_card {
 
@@ -574,6 +578,7 @@
 	
 	unsigned int current_packet;
 	int first_frame; 	/* received first start frame marker? */
+	enum modes mode;
 };
 
 /* 
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ieee1394/dv1394.c	Sun Apr 14 12:16:56 2002
@@ -46,8 +46,6 @@
 /*
   TODO:
 
-  - expose xmit and recv as separate devices
-
   - tunable frame-drop behavior: either loop last frame, or halt transmission
   
   - use a scatter/gather buffer for DMA programs (f->descriptor_pool)
@@ -73,6 +71,9 @@
   - keep all video_cards in a list (for open() via chardev), set file->private_data = video
   - dv1394_poll should indicate POLLIN when receiving buffers are available
   - add proc fs interface to set cip_n, cip_d, syt_offset, and video signal
+  - expose xmit and recv as separate devices (not exclusive)
+  - expose NTSC and PAL as separate devices (can be overridden)
+  - read/edit channel in procfs
 
 */
      
@@ -100,7 +101,6 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <linux/sched.h>
-#include <asm/segment.h>
 #include <linux/types.h>
 #include <linux/wrapper.h>
 #include <linux/vmalloc.h>
@@ -170,7 +170,14 @@
 
 static struct hpsb_highlevel *hl_handle; /* = NULL; */
 
-static devfs_handle_t dv1394_devfs_handle;
+static LIST_HEAD(dv1394_devfs);
+struct dv1394_devfs_entry {
+	struct list_head list;
+    devfs_handle_t devfs;
+	char name[32];
+	struct dv1394_devfs_entry *parent;
+};
+static spinlock_t dv1394_devfs_lock = SPIN_LOCK_UNLOCKED;
 
 /* translate from a struct file* to the corresponding struct video_card* */
 
@@ -185,19 +192,71 @@
 /* Memory management functions */
 /*******************************/
 
+#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ *    out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed.  We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline struct page *uvirt_to_page(pgd_t *pgd, unsigned long adr)
+{
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+	struct page *ret = NULL;
+	
+	if (!pgd_none(*pgd)) {
+                pmd = pmd_offset(pgd, adr);
+                if (!pmd_none(*pmd)) {
+                        ptep = pte_offset_kernel(pmd, adr);
+                        pte = *ptep;
+                        if(pte_present(pte))
+				ret = pte_page(pte);
+                }
+        }
+	return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved, and for
+ * handling page faults on the rvmalloc()ed buffer
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
+{
+        unsigned long va, kva, ret;
+
+        va = VMALLOC_VMADDR(adr);
+	kva = (unsigned long) page_address(uvirt_to_page(pgd_offset_k(va), va));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+        MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
+        return ret;
+}
+
 static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
+	unsigned long adr, page;
+        
 	mem=vmalloc_32(size);
 	if (mem) {
 		memset(mem, 0, size); /* Clear the ram out, 
 					 no junk to the user */
 	        adr=(unsigned long) mem;
 		while (size > 0) {
-			mem_map_reserve(vmalloc_to_page((void *)adr));
+	                page = kvirt_to_pa(adr);
+			mem_map_reserve(virt_to_page(__va(page)));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -207,12 +266,13 @@
 
 static void rvfree(void * mem, unsigned long size)
 {
-        unsigned long adr;
-
+        unsigned long adr, page;
+        
 	if (mem) {
 	        adr=(unsigned long) mem;
-		while ((long) size > 0) {
-			mem_map_unreserve(vmalloc_to_page((void *)adr));
+		while (size > 0) {
+	                page = kvirt_to_pa(adr);
+			mem_map_unreserve(virt_to_page(__va(page)));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -1106,9 +1166,9 @@
 		
 		/* fill the sglist with the kernel addresses of pages in the non-contiguous buffer */
 		for(i = 0; i < video->user_dma.n_pages; i++) {
-			unsigned long va = (unsigned long) video->user_buf + i * PAGE_SIZE;
+			unsigned long va = VMALLOC_VMADDR( (unsigned long) video->user_buf + i * PAGE_SIZE );
 			
-			video->user_dma.sglist[i].page = vmalloc_to_page((void *)va);
+			video->user_dma.sglist[i].page = uvirt_to_page(pgd_offset_k(va), va);
 			video->user_dma.sglist[i].length = PAGE_SIZE;
 		}
 		
@@ -1239,9 +1299,9 @@
 	struct dv1394_init init;
 
 	init.api_version = DV1394_API_VERSION;
-	init.channel = 63;
 	init.n_frames = 2;
-	/* the following are now set via proc_fs */
+	/* the following are now set via proc_fs or devfs */
+	init.channel = video->channel;
 	init.format = video->pal_or_ntsc;
 	init.cip_n = video->cip_n; 
 	init.cip_d = video->cip_d;
@@ -1432,7 +1492,7 @@
 static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long address, int write_access)
 {
 	unsigned long offset;
-	unsigned long kernel_virt_addr;
+	unsigned long page, kernel_virt_addr;
 	struct page *ret = NOPAGE_SIGBUS;
 
 	struct video_card *video = (struct video_card*) area->vm_private_data;
@@ -1450,7 +1510,10 @@
 
 	offset = address - area->vm_start;
 	kernel_virt_addr = (unsigned long) video->user_buf + offset;
-	ret = vmalloc_to_page((void *)kernel_virt_addr);
+
+	page = kvirt_to_pa(kernel_virt_addr);
+	
+	ret = virt_to_page(__va(page));
 	get_page(ret);
 
  out:
@@ -2022,7 +2085,7 @@
 			struct video_card *p;
 			list_for_each(lh, &dv1394_cards) {
 				p = list_entry(lh, struct video_card, list);
-				if(p->id == ieee1394_file_to_instance(file)) {
+				if((p->id >> 2) == ieee1394_file_to_instance(file)) {
 					video = p;
 					break;
 				}
@@ -2047,7 +2110,6 @@
 
 #endif
 
-	V22_COMPAT_MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -2065,36 +2127,38 @@
 	/* give someone else a turn */
 	clear_bit(0, &video->open);
 
-	V22_COMPAT_MOD_DEC_USE_COUNT;
 	return 0;
 }
 
 
 /*** PROC_FS INTERFACE ******************************************************/
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *dv1394_procfs_entry;
+static LIST_HEAD(dv1394_procfs);
+struct dv1394_procfs_entry {
+	struct list_head list;
+    struct proc_dir_entry *procfs;
+	char name[32];
+	struct dv1394_procfs_entry *parent;
+};
+static spinlock_t dv1394_procfs_lock = SPIN_LOCK_UNLOCKED;
 
 static int dv1394_procfs_read( char *page, char **start, off_t off,
 			int count, int *eof, void *data)
 {
 	struct video_card *video = (struct video_card*) data;
 
-	V22_COMPAT_MOD_INC_USE_COUNT;
 	snprintf( page, count, 
 		"\
-dv1394 settings for host %d:\n\
-----------------------------\n\
 format=%s\n\
+channel=%d\n\
 cip_n=%lu\n\
 cip_d=%lu\n\
 syt_offset=%u\n",
-		video->id,
 		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
+		video->channel,
 		video->cip_n, video->cip_d, video->syt_offset );
-	V22_COMPAT_MOD_DEC_USE_COUNT;
 	return strlen(page);
 }
-#endif /* CONFIG_PROC_FS */
 
 /* lifted from the stallion.c driver */
 #undef  TOLOWER
@@ -2129,7 +2193,6 @@
 	return(val);
 }
 
-#ifdef CONFIG_PROC_FS
 static int dv1394_procfs_write( struct file *file,
 			const char *buffer, unsigned long count, void *data)
 {
@@ -2138,17 +2201,13 @@
 	char *pos;
 	struct video_card *video = (struct video_card*) data;
 	
-	V22_COMPAT_MOD_INC_USE_COUNT;
-	
 	if (count > 64)
 		len = 64;
 	else
 		len = count;
 				
-	if (copy_from_user( new_value, buffer, len)) {
-		V22_COMPAT_MOD_DEC_USE_COUNT;
+	if (copy_from_user( new_value, buffer, len))
 		return -EFAULT;
-	}
 	
 	pos = strchr(new_value, '=');
 	if (pos != NULL) {
@@ -2170,31 +2229,142 @@
 			video->cip_d = atol(buf);
 		} else if (strnicmp( new_value, "syt_offset", (pos-new_value)) == 0) {
 			video->syt_offset = atol(buf);
+		} else if (strnicmp( new_value, "channel", (pos-new_value)) == 0) {
+			video->channel = atol(buf);
 		}
 	}
 	
-	V22_COMPAT_MOD_DEC_USE_COUNT;
 	return len;
 }
 
+struct dv1394_procfs_entry *
+dv1394_procfs_find( char *name)
+{
+	struct list_head *lh;
+	struct dv1394_procfs_entry *p;
+		
+	spin_lock( &dv1394_procfs_lock);
+	if(!list_empty(&dv1394_procfs)) {
+		list_for_each(lh, &dv1394_procfs) {
+			p = list_entry(lh, struct dv1394_procfs_entry, list);
+			if(!strncmp(p->name, name, sizeof(p->name))) {
+				spin_unlock( &dv1394_procfs_lock);
+				return p;
+			}
+		}
+	}
+	spin_unlock( &dv1394_procfs_lock);
+	return NULL;
+}
+
 static int dv1394_procfs_add_entry(struct video_card *video)
 {
-	struct proc_dir_entry *procfs_entry = NULL;
-	char buf[16];
+	char buf[32];
+	struct dv1394_procfs_entry *p;
+	struct dv1394_procfs_entry *parent;
+
+	p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL);
+	if(!p) {
+		printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n");
+		goto err;
+	}
+	memset(p, 0, sizeof(struct dv1394_procfs_entry));
+	
+	snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2),
+						(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"));
+		
+	parent = dv1394_procfs_find(buf);
+	if (parent == NULL) {
+		printk(KERN_ERR "dv1394: unable to locate parent procfs of %s\n", buf);
+		goto err_free;
+	}
 	
-	snprintf(buf, sizeof(buf), "%d", video->id);
+	p->procfs = create_proc_entry( 
+						(video->mode == MODE_RECEIVE ? "in" : "out"),
+						0666, parent->procfs);
+
+	if (p->procfs == NULL) {
+		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s/%s\n",
+			parent->name,
+			(video->mode == MODE_RECEIVE ? "in" : "out"));
+		goto err_free;
+	}
+	
+	p->procfs->owner = THIS_MODULE;
+	p->procfs->data = video;
+	p->procfs->read_proc = dv1394_procfs_read;
+	p->procfs->write_proc = dv1394_procfs_write;
+
+	spin_lock( &dv1394_procfs_lock);
+	INIT_LIST_HEAD(&p->list);
+	list_add_tail(&p->list, &dv1394_procfs);
+	spin_unlock( &dv1394_procfs_lock);
+	
+	return 0;
+	
+ err_free:
+	kfree(p);
+ err:
+	return -ENOMEM;
+}
 
-	procfs_entry = create_proc_entry( buf, 0666, dv1394_procfs_entry);
-	if (procfs_entry == NULL) {
-		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv/X\n");
-		return -ENOMEM;
+static int
+dv1394_procfs_add_dir( char *name,
+					struct dv1394_procfs_entry *parent, 
+					struct dv1394_procfs_entry **out)
+{
+	struct dv1394_procfs_entry *p;
+
+	p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL);
+	if(!p) {
+		printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n");
+		goto err;
 	}
-	procfs_entry->owner = THIS_MODULE;
-	procfs_entry->data = video;
-	procfs_entry->read_proc = dv1394_procfs_read;
-	procfs_entry->write_proc = dv1394_procfs_write;
+	memset(p, 0, sizeof(struct dv1394_procfs_entry));
 	
+	if (parent == NULL) {
+		snprintf(p->name, sizeof(p->name), "%s", name);
+		p->procfs = proc_mkdir( name, ieee1394_procfs_entry);
+	} else {
+		snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name);
+		p->procfs = proc_mkdir( name, parent->procfs);
+	}
+	if (p->procfs == NULL) {
+		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s\n", p->name);
+		goto err_free;
+	}
+
+	p->procfs->owner = THIS_MODULE;
+	p->parent = parent;
+	if (out != NULL) *out = p;
+
+	spin_lock( &dv1394_procfs_lock);
+	INIT_LIST_HEAD(&p->list);
+	list_add_tail(&p->list, &dv1394_procfs);
+	spin_unlock( &dv1394_procfs_lock);
+
 	return 0;
+	
+ err_free:
+	kfree(p);
+ err:
+	return -ENOMEM;
+}
+
+void dv1394_procfs_del( char *name)
+{
+	struct dv1394_procfs_entry *p = dv1394_procfs_find(name);
+	if (p != NULL) {
+		if (p->parent == NULL)
+			remove_proc_entry(p->name, ieee1394_procfs_entry);
+		else
+			remove_proc_entry(p->name, p->parent->procfs);
+		
+		spin_lock( &dv1394_procfs_lock);
+		list_del(&p->list);
+		spin_unlock( &dv1394_procfs_lock);
+		kfree(p);
+	}
 }
 #endif /* CONFIG_PROC_FS */
 
@@ -2432,7 +2602,7 @@
 
 static struct file_operations dv1394_fops=
 {
-        OWNER_THIS_MODULE
+	owner:		THIS_MODULE,
 	poll:           dv1394_poll,
 	ioctl:		dv1394_ioctl,
 	mmap:		dv1394_mmap,
@@ -2444,11 +2614,141 @@
 };
 
 
-static int dv1394_init(struct ti_ohci *ohci)
+/*** DEVFS HELPERS *********************************************************/
+
+struct dv1394_devfs_entry *
+dv1394_devfs_find( char *name)
+{
+	struct list_head *lh;
+	struct dv1394_devfs_entry *p;
+
+	spin_lock( &dv1394_devfs_lock);
+	if(!list_empty(&dv1394_devfs)) {
+		list_for_each(lh, &dv1394_devfs) {
+			p = list_entry(lh, struct dv1394_devfs_entry, list);
+			if(!strncmp(p->name, name, sizeof(p->name))) {
+				spin_unlock( &dv1394_devfs_lock);
+				return p;
+			}
+		}
+	}
+	return NULL;
+}
+
+static int dv1394_devfs_add_entry(struct video_card *video)
+{
+	char buf[32];
+	struct dv1394_devfs_entry *p;
+	struct dv1394_devfs_entry *parent;
+
+	p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL);
+	if(!p) {
+		printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n");
+		goto err;
+	}
+	memset(p, 0, sizeof(struct dv1394_devfs_entry));
+	
+	snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2),
+						(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"));
+		
+	parent = dv1394_devfs_find(buf);
+	if (parent == NULL) {
+		printk(KERN_ERR "dv1394: unable to locate parent devfs of %s\n", buf);
+		goto err_free;
+	}
+	
+	video->devfs_handle = devfs_register(
+						 parent->devfs,
+					     (video->mode == MODE_RECEIVE ? "in" : "out"),
+						 DEVFS_FL_NONE,
+					     IEEE1394_MAJOR,
+					     IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
+					     S_IFCHR | S_IRUGO | S_IWUGO,
+					     &dv1394_fops,
+					     (void*) video);
+	p->devfs = video->devfs_handle;
+
+	if (p->devfs == NULL) {
+		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s/%s\n",
+			parent->name,
+			(video->mode == MODE_RECEIVE ? "in" : "out"));
+		goto err_free;
+	}
+	
+	spin_lock( &dv1394_devfs_lock);
+	INIT_LIST_HEAD(&p->list);
+	list_add_tail(&p->list, &dv1394_devfs);
+	spin_unlock( &dv1394_devfs_lock);
+	
+	return 0;
+	
+ err_free:
+	kfree(p);
+ err:
+	return -ENOMEM;
+}
+
+static int
+dv1394_devfs_add_dir( char *name,
+					struct dv1394_devfs_entry *parent, 
+					struct dv1394_devfs_entry **out)
+{
+	struct dv1394_devfs_entry *p;
+
+	p = kmalloc(sizeof(struct dv1394_devfs_entry), GFP_KERNEL);
+	if(!p) {
+		printk(KERN_ERR "dv1394: cannot allocate dv1394_devfs_entry\n");
+		goto err;
+	}
+	memset(p, 0, sizeof(struct dv1394_devfs_entry));
+	
+	if (parent == NULL) {
+		snprintf(p->name, sizeof(p->name), "%s", name);
+		p->devfs = devfs_mk_dir(ieee1394_devfs_handle, name, NULL);
+	} else {
+		snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name);
+		p->devfs = devfs_mk_dir(parent->devfs, name, NULL);
+	}
+	if (p->devfs == NULL) {
+		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/%s\n", p->name);
+		goto err_free;
+	}
+
+	p->parent = parent;
+	if (out != NULL) *out = p;
+
+	spin_lock( &dv1394_devfs_lock);
+	INIT_LIST_HEAD(&p->list);
+	list_add_tail(&p->list, &dv1394_devfs);
+	spin_unlock( &dv1394_devfs_lock);
+
+	return 0;
+	
+ err_free:
+	kfree(p);
+ err:
+	return -ENOMEM;
+}
+
+void dv1394_devfs_del( char *name)
+{
+	struct dv1394_devfs_entry *p = dv1394_devfs_find(name);
+	if (p != NULL) {
+		devfs_unregister(p->devfs);
+		
+		spin_lock( &dv1394_devfs_lock);
+		list_del(&p->list);
+		spin_unlock( &dv1394_devfs_lock);
+		kfree(p);
+	}
+}
+
+/*** IEEE1394 HPSB CALLBACKS ***********************************************/
+
+static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes mode)
 {
 	struct video_card *video;
 	unsigned long flags;
-	char buf[16];
 	int i;
 
 	video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
@@ -2466,10 +2766,9 @@
 
 	
 	video->ohci = ohci;
-	video->id = ohci->id;
-
-	if ( dv1394_procfs_add_entry(video) < 0 )
-		goto err_free;
+	/* lower 2 bits of id indicate which of four "plugs"
+	   per host */
+	video->id = ohci->id << 2; 
 
 	video->ohci_it_ctx = -1;
 	video->ohci_ir_ctx = -1;
@@ -2484,14 +2783,20 @@
 	video->ohci_IsoRcvContextMatch = 0;
 		
 	video->n_frames = 0; /* flag that video is not initialized */
-	video->channel = -1;
+	video->channel = 63; /* default to broadcast channel */
 	video->active_frame = -1;
 	
 	/* initialize the following for proc_fs */
-	video->pal_or_ntsc = DV1394_NTSC;
+	video->pal_or_ntsc = format;
 	video->cip_n = 0; /* 0 = use builtin default */
 	video->cip_d = 0;
 	video->syt_offset = 0;
+	video->mode = mode;
+
+#ifdef CONFIG_PROC_FS
+	if ( dv1394_procfs_add_entry(video) < 0 )
+		goto err_free;
+#endif
 
 	for(i = 0; i < DV1394_MAX_FRAMES; i++)
 		video->frames[i] = NULL;
@@ -2510,17 +2815,14 @@
 	list_add_tail(&video->list, &dv1394_cards);
 	spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 	
-	snprintf(buf, sizeof(buf), "%d", video->id);
+	if (format == DV1394_NTSC)
+		video->id |= mode;
+	else video->id |= 2 + mode;
 	
-	video->devfs_handle = devfs_register(dv1394_devfs_handle,
-					     buf, DEVFS_FL_NONE,
-					     IEEE1394_MAJOR,
-					     IEEE1394_MINOR_BLOCK_DV1394*16 + video->id,
-					     S_IFCHR | S_IRUGO | S_IWUGO,
-					     &dv1394_fops,
-					     (void*) video);
+	if (dv1394_devfs_add_entry(video) < 0)
+			goto err_free;
 
-	debug_printk("dv1394: dv1394_init() OK on ID %d\n", ohci->id);
+	debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
 	
 	return 0;
 
@@ -2532,18 +2834,20 @@
 
 static void dv1394_un_init(struct video_card *video)
 {
-	unsigned long flags;
+	char buf[32];
 	
 	/* obviously nobody has the driver open at this point */
 	do_dv1394_shutdown(video, 1);
 	ohci1394_unhook_irq(video->ohci, irq_handler, (void*) video);
-	if(video->devfs_handle)
-		devfs_unregister(video->devfs_handle);
-
-	spin_lock_irqsave(&dv1394_cards_lock, flags);
+	snprintf(buf, sizeof(buf), "dv/host%d/%s/%s", (video->id >> 2),
+		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),
+		(video->mode == MODE_RECEIVE ? "in" : "out")
+		);
+	dv1394_devfs_del(buf);
+#ifdef CONFIG_PROC_FS
+	dv1394_procfs_del(buf);
+#endif
 	list_del(&video->list);
-	spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-	
 	kfree(video);
 }
 
@@ -2554,6 +2858,8 @@
 	struct video_card *video = NULL;
 	unsigned long flags;
 	struct list_head *lh;
+	char buf[32];
+	int	n;
 	
 	/* We only work with the OHCI-1394 driver */
 	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
@@ -2562,33 +2868,40 @@
 	ohci = (struct ti_ohci *)host->hostdata;
 
 
-	/* find the corresponding video_card */
+	/* find the corresponding video_cards */
 	spin_lock_irqsave(&dv1394_cards_lock, flags);
 	if(!list_empty(&dv1394_cards)) {
-		struct video_card *p;
 		list_for_each(lh, &dv1394_cards) {
-			p = list_entry(lh, struct video_card, list);
-			if(p->id == ohci->id) {
-				video = p;
-				break;
-			}
+			video = list_entry(lh, struct video_card, list);
+			if((video->id >> 2) == ohci->id)
+				dv1394_un_init(video);
 		}
 	}
 	spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 
-	if(video) {
-		char buf[16];
-		dv1394_un_init(video);
-		snprintf( buf, sizeof(buf), "%i", video->id);
+	n = (video->id >> 2);
+	snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n);
+	dv1394_devfs_del(buf);
+	snprintf(buf, sizeof(buf), "dv/host%d/PAL", n);
+	dv1394_devfs_del(buf);
+	snprintf(buf, sizeof(buf), "dv/host%d", n);
+	dv1394_devfs_del(buf);
+
 #ifdef CONFIG_PROC_FS
-		remove_proc_entry( buf, dv1394_procfs_entry);
-#endif
-	}
+	snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n);
+	dv1394_procfs_del(buf);
+	snprintf(buf, sizeof(buf), "dv/host%d/PAL", n);
+	dv1394_procfs_del(buf);
+	snprintf(buf, sizeof(buf), "dv/host%d", n);
+	dv1394_procfs_del(buf);
+#endif	
 }
 
 static void dv1394_add_host (struct hpsb_host *host)
 {
 	struct ti_ohci *ohci;
+	char buf[16];
+	struct dv1394_devfs_entry *devfs_entry;
 
 	/* We only work with the OHCI-1394 driver */
 	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
@@ -2596,7 +2909,31 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	dv1394_init(ohci);
+#ifdef CONFIG_PROC_FS
+{
+	struct dv1394_procfs_entry *p;
+	p = dv1394_procfs_find("dv");
+	if (p != NULL) {
+		snprintf(buf, sizeof(buf), "host%d", ohci->id);
+		dv1394_procfs_add_dir(buf, p, &p);
+		dv1394_procfs_add_dir("NTSC", p, NULL);
+		dv1394_procfs_add_dir("PAL", p, NULL);
+	}
+}
+#endif
+
+	devfs_entry = dv1394_devfs_find("dv");
+	if (devfs_entry != NULL) {
+		snprintf(buf, sizeof(buf), "host%d", ohci->id);
+		dv1394_devfs_add_dir(buf, devfs_entry, &devfs_entry);
+		dv1394_devfs_add_dir("NTSC", devfs_entry, NULL);
+		dv1394_devfs_add_dir("PAL", devfs_entry, NULL);
+	}
+	
+	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
+	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
+	dv1394_init(ohci, DV1394_PAL, MODE_RECEIVE);
+	dv1394_init(ohci, DV1394_PAL, MODE_TRANSMIT);
 }
 
 static struct hpsb_highlevel_ops hl_ops = {
@@ -2616,9 +2953,9 @@
 {
 	hpsb_unregister_highlevel (hl_handle);
 	ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-	devfs_unregister(dv1394_devfs_handle);
+	dv1394_devfs_del("dv");
 #ifdef CONFIG_PROC_FS
-	remove_proc_entry( "dv", ieee1394_procfs_entry);
+	dv1394_procfs_del("dv");
 #endif
 }
 
@@ -2630,26 +2967,28 @@
 		return -EIO;
 	}
 
-	dv1394_devfs_handle = devfs_mk_dir(ieee1394_devfs_handle, "dv", NULL);
+	if (dv1394_devfs_add_dir("dv", NULL, NULL) < 0) {
+		printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
+		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
+		return -ENOMEM;
+	}
 
 #ifdef CONFIG_PROC_FS
-	dv1394_procfs_entry = proc_mkdir( "dv", ieee1394_procfs_entry);
-	if (dv1394_procfs_entry == NULL) {
-		printk(KERN_ERR "dv1394: unable to create /proc/ieee1394/dv\n");
+	if (dv1394_procfs_add_dir("dv",NULL,NULL) < 0) {
+		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-		devfs_unregister(dv1394_devfs_handle);
+		dv1394_devfs_del("dv");
 		return -ENOMEM;
 	}
-	dv1394_procfs_entry->owner = THIS_MODULE;
 #endif
 
 	hl_handle = hpsb_register_highlevel ("dv1394", &hl_ops);
 	if (hl_handle == NULL) {
 		printk(KERN_ERR "dv1394: hpsb_register_highlevel failed\n");
 		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
-		devfs_unregister(dv1394_devfs_handle);
+		dv1394_devfs_del("dv");
 #ifdef CONFIG_PROC_FS
-		remove_proc_entry( "dv", ieee1394_procfs_entry);
+		dv1394_procfs_del("dv");
 #endif
 		return -ENOMEM;
 	}
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/eth1394.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,741 @@
+/*
+ * eth1394.c -- Ethernet driver for Linux IEEE-1394 Subsystem
+ * 
+ * Copyright (C) 2001 Ben Collins <bcollins@debian.org>
+ *               2000 Bonin Franck <boninf@free.fr>
+ *
+ * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
+ *
+ * This program is free software; you can redistribute it and/or 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.
+ */
+
+/* State of this driver:
+ *
+ * This driver intends to support RFC 2734, which describes a method for
+ * transporting IPv4 datagrams over IEEE-1394 serial busses. This driver
+ * will ultimately support that method, but currently falls short in
+ * several areas. A few issues are:
+ *
+ *   - Does not support send/recv over Async streams using GASP
+ *     packet formats, as per the RFC for ARP requests.
+ *   - Does not yet support fragmented packets.
+ *   - Relies on hardware address being equal to the nodeid for some things.
+ *   - Does not support multicast
+ *   - Hardcoded address for sending packets, instead of using discovery
+ *     (ARP, see first item)
+ */
+
+#include <linux/module.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <asm/delay.h>
+#include <asm/semaphore.h>
+#include <asm/bitops.h>
+#include <net/arp.h>
+
+#include "ieee1394_types.h"
+#include "ieee1394_core.h"
+#include "ieee1394_transactions.h"
+#include "ieee1394.h"
+#include "highlevel.h"
+#include "eth1394.h"
+
+#define ETH1394_PRINT_G(level, fmt, args...) \
+	printk(level ETHER1394_DRIVER_NAME": "fmt, ## args)
+
+#define ETH1394_PRINT(level, dev_name, fmt, args...) \
+	printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## args)
+
+#define DEBUG(fmt, args...) \
+	printk(KERN_ERR fmt, ## args)
+
+static char version[] __devinitdata =
+	"eth1394.c:v0.50 15/Jul/01 Ben Collins <bcollins@debian.org>";
+
+/* Our ieee1394 highlevel driver */
+#define ETHER1394_DRIVER_NAME "ether1394"
+
+static kmem_cache_t *packet_task_cache;
+static struct hpsb_highlevel *hl_handle = NULL;
+
+/* Card handling */
+static LIST_HEAD (host_info_list);
+static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
+
+/* Use common.lf to determine header len */
+static int hdr_type_len[] = {
+	sizeof (struct eth1394_uf_hdr),
+	sizeof (struct eth1394_ff_hdr),
+	sizeof (struct eth1394_sf_hdr),
+	sizeof (struct eth1394_sf_hdr)
+};
+
+MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");
+MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
+
+/* Find our host_info struct for a given host pointer. Must be called
+ * under spinlock.  */
+static inline struct host_info *find_host_info (struct hpsb_host *host)
+{
+	struct list_head *lh;
+	struct host_info *hi;
+
+	lh = host_info_list.next;
+	while (lh != &host_info_list) {
+		hi = list_entry (lh, struct host_info, list);
+
+		if (hi->host == host)
+			return hi;
+
+		lh = lh->next;
+	}
+	return NULL;
+}
+
+/* Find the network device for our host */
+static inline struct net_device *ether1394_find_dev (struct hpsb_host *host)
+{
+	struct host_info *hi;
+
+	spin_lock_irq (&host_info_lock);
+	hi = find_host_info (host);
+	spin_unlock_irq (&host_info_lock);
+
+	if (hi == NULL)
+		return NULL;
+
+	return hi->dev;
+}
+
+/* This is called after an "ifup" */
+static int ether1394_open (struct net_device *dev)
+{
+	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
+
+	/* Set the spinlock before grabbing IRQ! */
+	priv->lock = SPIN_LOCK_UNLOCKED;
+
+	netif_start_queue (dev);
+	return 0;
+}
+
+/* This is called after an "ifdown" */
+static int ether1394_stop (struct net_device *dev)
+{
+	netif_stop_queue (dev);
+	return 0;
+}
+
+/* Return statistics to the caller */
+static struct net_device_stats *ether1394_stats (struct net_device *dev)
+{
+	return &(((struct eth1394_priv *)dev->priv)->stats);
+}
+
+/* What to do if we timeout. I think a host reset is probably in order, so
+ * that's what we do. Should we increment the stat counters too?  */
+static void ether1394_tx_timeout (struct net_device *dev)
+{
+	ETH1394_PRINT (KERN_ERR, dev->name, "Timeout, resetting host %s\n",
+		       ((struct eth1394_priv *)(dev->priv))->host->driver->name);
+
+	highlevel_host_reset (((struct eth1394_priv *)(dev->priv))->host);
+
+	netif_wake_queue (dev);
+}
+
+/* We need to encapsulate the standard header with our own. We use the
+ * ethernet header's proto for our own.
+ *
+ * XXX: This is where we need to create a list of skb's for fragmented
+ * packets.  */
+static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev,
+			    int proto)
+{
+	union eth1394_hdr *hdr =
+		(union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]);
+
+	hdr->common.lf = ETH1394_HDR_LF_UF;
+	hdr->words.word1 = htons(hdr->words.word1);
+	hdr->uf.ether_type = proto;
+
+	return;
+}
+
+/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the
+ * entire arphdr) is the same format as the ip1394 header, so they
+ * overlap. The rest needs to be munged a bit. The remainder of the
+ * arphdr is formatted based on hwaddr len and ipaddr len. We know what
+ * they'll be, so it's easy to judge.  */
+static inline void ether1394_arp_to_1394arp (struct sk_buff *skb, struct net_device *dev)
+{
+	struct eth1394_priv *priv =
+		(struct eth1394_priv *)(dev->priv);
+	u16 phy_id = priv->host->node_id & NODE_MASK;
+
+	unsigned char *arp_ptr = (unsigned char *)skb->data;
+	struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
+	unsigned char arp_data[2*(dev->addr_len+4)];
+
+	/* Copy the main data that we need */
+	arp_ptr = memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data));
+
+	/* Extend the buffer enough for our new header */
+	skb_put (skb, sizeof (struct eth1394_arp) -
+		 (sizeof (arp_data) + sizeof (struct arphdr)));
+
+#define PROCESS_MEMBER(ptr,val,len) \
+  memcpy (val, ptr, len); ptr += len
+	arp_ptr += arp1394->hw_addr_len;
+	PROCESS_MEMBER (arp_ptr, &arp1394->sip, arp1394->ip_addr_len);
+	arp_ptr += arp1394->hw_addr_len;
+	PROCESS_MEMBER (arp_ptr, &arp1394->tip, arp1394->ip_addr_len);
+#undef PROCESS_MEMBER
+
+	/* Now add our own flavor of arp header fields to the orig one */
+	arp1394->hw_addr_len	= IP1394_HW_ADDR_LEN;
+	arp1394->hw_type	= __constant_htons (ARPHRD_IEEE1394);
+	arp1394->s_uniq_id	= cpu_to_le64 (priv->eui[phy_id]);
+	arp1394->max_rec	= priv->max_rec[phy_id];
+	arp1394->sspd		= priv->sspd[phy_id];
+	arp1394->fifo_hi	= htons (priv->fifo_hi[phy_id]);
+	arp1394->fifo_lo	= htonl (priv->fifo_lo[phy_id]);
+
+	return;
+}
+
+static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if ((new_mtu < 68) || (new_mtu > ETHER1394_REGION_ADDR_LEN))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,
+				       unsigned char sspd, u64 eui, u16 fifo_hi,
+				       u32 fifo_lo, struct eth1394_priv *priv)
+{
+	int i;
+
+	if (nodeid < 0 || nodeid >= ALL_NODES) {
+		ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid);
+		return;
+	}
+
+	priv->max_rec[nodeid]	= max_rec;
+	priv->sspd[nodeid]	= sspd;
+	priv->fifo_hi[nodeid]	= fifo_hi;
+	priv->fifo_lo[nodeid]	= fifo_lo;
+	priv->eui[nodeid]	= eui;
+
+	/* 63 is used for broadcasts to all hosts. It is equal to the
+	 * minimum of all registered nodes. A registered node is one with
+	 * a nonzero offset. Set the values rediculously high to start. We
+	 * know we have atleast one to change the default to.  */
+	sspd = 0xff;
+	max_rec = 0xff;
+	for (i = 0; i < ALL_NODES; i++) {
+		if (!priv->fifo_hi && !priv->fifo_lo) continue; /* Unregistered */
+		if (priv->max_rec[i] < max_rec) max_rec = priv->max_rec[i];
+		if (priv->sspd[i] < sspd) sspd = priv->sspd[i];
+	}
+
+	priv->max_rec[ALL_NODES] = max_rec;
+	priv->sspd[ALL_NODES] = sspd;
+
+	return;
+}
+
+static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
+{
+	int flags;
+	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
+	int phy_id = priv->host->node_id & NODE_MASK;
+
+	spin_lock_irqsave (&priv->lock, flags);
+
+	/* Clear the speed/payload/offset tables */
+	memset (priv->max_rec, 0, sizeof (priv->max_rec));
+	memset (priv->sspd, 0, sizeof (priv->sspd));
+	memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi));
+	memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo));
+
+	/* Register our limits now */
+	ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf,
+				   priv->host->speed_map[(phy_id << 6) + phy_id],
+				   (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) |
+				   be32_to_cpu(priv->host->csr.rom[4])),
+				   ETHER1394_REGION_ADDR >> 32,
+				   ETHER1394_REGION_ADDR & 0xffffffff, priv);
+
+	/* We'll use our max_rec as the default mtu */
+	if (set_mtu)
+		dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr);
+
+	/* Set our hardware address while we're at it */
+	*(nodeid_t *)dev->dev_addr = htons (priv->host->node_id);
+
+	spin_unlock_irqrestore (&priv->lock, flags);
+}
+
+static int ether1394_tx (struct sk_buff *skb, struct net_device *dev);
+
+/* This function is called by register_netdev */
+static int ether1394_init_dev (struct net_device *dev)
+{
+	/* Our functions */
+	dev->open		= ether1394_open;
+	dev->stop		= ether1394_stop;
+	dev->hard_start_xmit	= ether1394_tx;
+	dev->get_stats		= ether1394_stats;
+	dev->tx_timeout		= ether1394_tx_timeout;
+	dev->change_mtu		= ether1394_change_mtu;
+
+	/* Some constants */
+	dev->watchdog_timeo	= ETHER1394_TIMEOUT;
+	dev->flags		= IFF_BROADCAST; /* TODO: Support MCAP */
+	dev->features		= NETIF_F_NO_CSUM|NETIF_F_SG|NETIF_F_HIGHDMA|NETIF_F_FRAGLIST;
+	dev->addr_len		= 2;
+
+	ether1394_reset_priv (dev, 1);
+
+	return 0;
+}
+
+/*
+ * This function is called every time a card is found. It is generally called
+ * when the module is installed. This is where we add all of our ethernet
+ * devices. One for each host.
+ */
+static void ether1394_add_host (struct hpsb_host *host)
+{
+	struct host_info *hi = NULL;
+	struct net_device *dev = NULL;
+	struct eth1394_priv *priv;
+	static int version_printed = 0;
+
+	if (version_printed++ == 0)
+		ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
+
+	dev = alloc_etherdev(sizeof (struct eth1394_priv));
+
+	if (dev == NULL)
+		goto out;
+
+	SET_MODULE_OWNER(dev);
+
+	dev->init = ether1394_init_dev;
+
+	priv = (struct eth1394_priv *)dev->priv;
+
+	priv->host = host;
+
+	hi = (struct host_info *)kmalloc (sizeof (struct host_info),
+					  GFP_KERNEL);
+
+	if (hi == NULL)
+		goto out;
+
+	if (register_netdev (dev)) {
+		ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");
+		kfree (dev);
+		return;
+	}
+
+	ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n",
+		       host->driver->name);
+
+	INIT_LIST_HEAD (&hi->list);
+	hi->host = host;
+	hi->dev = dev;
+
+	spin_lock_irq (&host_info_lock);
+	list_add_tail (&hi->list, &host_info_list);
+	spin_unlock_irq (&host_info_lock);
+
+	return;
+
+out:
+	if (dev != NULL)
+		kfree (dev);
+	ETH1394_PRINT_G (KERN_ERR, "Out of memory\n");
+
+	return;
+}
+
+/* Remove a card from our list */
+static void ether1394_remove_host (struct hpsb_host *host)
+{
+	struct host_info *hi;
+
+	spin_lock_irq (&host_info_lock);
+	hi = find_host_info (host);
+	if (hi != NULL) {
+		unregister_netdev (hi->dev);
+		kfree (hi->dev);
+		list_del (&hi->list);
+		kfree (hi);
+	}
+	spin_unlock_irq (&host_info_lock);
+
+	return;
+}
+
+/* A reset has just arisen */
+static void ether1394_host_reset (struct hpsb_host *host)
+{
+	struct net_device *dev = ether1394_find_dev(host);
+
+	/* This can happen for hosts that we don't use */
+	if (dev == NULL)
+		return;
+
+	/* Reset our private host data, but not our mtu */
+	netif_stop_queue (dev);
+	ether1394_reset_priv (dev, 0);
+	netif_wake_queue (dev);
+}
+
+/* Copied from net/ethernet/eth.c */
+static inline unsigned short ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+	struct ethhdr *eth;
+	unsigned char *rawp;
+
+	skb->mac.raw = skb->data;
+	skb_pull (skb, ETH_HLEN);
+	eth = skb->mac.ethernet;
+#if 0
+	if(*eth->h_dest & 1) {
+		if(memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	} else {
+		if(memcmp(eth->h_dest, dev->dev_addr, dev->addr_len))
+			skb->pkt_type = PACKET_OTHERHOST;
+        }
+#endif
+	if (ntohs (eth->h_proto) >= 1536)
+		return eth->h_proto;
+
+	rawp = skb->data;
+
+        if (*(unsigned short *)rawp == 0xFFFF)
+		return htons (ETH_P_802_3);
+
+        return htons (ETH_P_802_2);
+}
+
+/* Parse an encapsulated IP1394 header into an ethernet frame packet.
+ * We also perform ARP translation here, if need be.  */
+static inline unsigned short ether1394_parse_encap (struct sk_buff *skb, struct net_device *dev,
+					     nodeid_t srcid, nodeid_t destid)
+{
+	union eth1394_hdr *hdr = (union eth1394_hdr *)skb->data;
+	unsigned char src_hw[ETH_ALEN], dest_hw[ETH_ALEN];
+	unsigned short ret = 0;
+
+	/* Setup our hw addresses. We use these to build the
+	 * ethernet header.  */
+	*(u16 *)dest_hw = htons(destid);
+	*(u16 *)src_hw = htons(srcid);
+
+	/* Remove the encapsulation header */
+	hdr->words.word1 = ntohs(hdr->words.word1);
+	skb_pull (skb, hdr_type_len[hdr->common.lf]);
+
+	/* If this is an ARP packet, convert it. First, we want to make
+	 * use of some of the fields, since they tell us a little bit
+	 * about the sending machine.  */
+	if (hdr->uf.ether_type == __constant_htons (ETH_P_ARP)) {
+		int flags;
+		u16 phy_id = srcid & NODE_MASK;
+		struct eth1394_priv *priv =
+			(struct eth1394_priv *)dev->priv;
+		struct eth1394_arp arp1394;
+		struct arphdr *arp = (struct arphdr *)skb->data;
+		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
+
+		memcpy (&arp1394, arp, sizeof (struct eth1394_arp));
+
+		/* Update our speed/payload/fifo_offset table */
+		spin_lock_irqsave (&priv->lock, flags);
+		ether1394_register_limits (phy_id, arp1394.max_rec, arp1394.sspd,
+					   le64_to_cpu (arp1394.s_uniq_id),
+					   ntohs (arp1394.fifo_hi),
+					   ntohl (arp1394.fifo_lo), priv);
+		spin_unlock_irqrestore (&priv->lock, flags);
+
+#define PROCESS_MEMBER(ptr,val,len) \
+  ptr = memcpy (ptr, val, len) + len
+                PROCESS_MEMBER (arp_ptr, src_hw, dev->addr_len);
+                PROCESS_MEMBER (arp_ptr, &arp1394.sip, 4);
+                PROCESS_MEMBER (arp_ptr, dest_hw, dev->addr_len);
+                PROCESS_MEMBER (arp_ptr, &arp1394.tip, 4);
+#undef PROCESS_MEMBER
+
+		arp->ar_hln = dev->addr_len;
+		arp->ar_hrd = __constant_htons (ARPHRD_ETHER);
+
+		skb_trim (skb, sizeof (struct arphdr) + 2*(dev->addr_len+4));
+	}
+
+	/* Now add the ethernet header. */
+	if (dev->hard_header (skb, dev, __constant_ntohs (hdr->uf.ether_type),
+			      dest_hw, src_hw, skb->len) >= 0)
+		ret = ether1394_type_trans(skb, dev);
+
+	return ret;
+}
+
+/* Packet reception. We convert the IP1394 encapsulation header to an
+ * ethernet header, and fill it with some of our other fields. This is
+ * an incoming packet from the 1394 bus.  */
+static int ether1394_write (struct hpsb_host *host, int srcid, int destid,
+			    quadlet_t *data, u64 addr, unsigned int len)
+{
+	struct sk_buff *skb;
+	char *buf = (char *)data;
+	int flags;
+	struct net_device *dev = ether1394_find_dev (host);
+	struct eth1394_priv *priv;
+
+	if (dev == NULL) {
+		ETH1394_PRINT_G (KERN_ERR, "Could not find net device for host %p\n",
+				 host);
+		return RCODE_ADDRESS_ERROR;
+	}
+
+	priv = (struct eth1394_priv *)dev->priv;
+
+	/* A packet has been received by the ieee1394 bus. Build an skbuff
+	 * around it so we can pass it to the high level network layer. */
+
+	skb = dev_alloc_skb (len + dev->hard_header_len + 15);
+	if (!skb) {
+		HPSB_PRINT (KERN_ERR, "ether1394 rx: low on mem\n");
+		priv->stats.rx_dropped++;
+		return RCODE_ADDRESS_ERROR;
+	}
+
+	skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
+
+	memcpy (skb_put (skb, len), buf, len);
+
+	/* Write metadata, and then pass to the receive level */
+	skb->dev = dev;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;	/* don't check it */
+
+	/* Parse the encapsulation header. This actually does the job of
+	 * converting to an ethernet frame header, aswell as arp
+	 * conversion if needed. ARP conversion is easier in this
+	 * direction, since we are using ethernet as our backend.  */
+	skb->protocol = ether1394_parse_encap (skb, dev, srcid, destid);
+
+	spin_lock_irqsave (&priv->lock, flags);
+	if (!skb->protocol) {
+		priv->stats.rx_errors++;
+		priv->stats.rx_dropped++;
+		dev_kfree_skb_any(skb);
+		goto bad_proto;
+	}
+
+	netif_stop_queue(dev);
+	if (netif_rx (skb) == NET_RX_DROP) {
+		priv->stats.rx_errors++;
+		priv->stats.rx_dropped++;
+		goto bad_proto;
+	}
+
+	/* Statistics */
+	priv->stats.rx_packets++;
+	priv->stats.rx_bytes += skb->len;
+
+bad_proto:
+	netif_start_queue(dev);
+	spin_unlock_irqrestore (&priv->lock, flags);
+
+	dev->last_rx = jiffies;
+
+	return RCODE_COMPLETE;
+}
+
+/* This function is our scheduled write */
+static void hpsb_write_sched (void *__ptask)
+{
+	struct packet_task *ptask = (struct packet_task *)__ptask;
+	struct sk_buff *skb = ptask->skb;
+	struct net_device *dev = ptask->skb->dev;
+	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
+	int flags;
+
+	/* Statistics */
+	spin_lock_irqsave (&priv->lock, flags);
+	if (!hpsb_write(priv->host, ptask->dest_node,
+			get_hpsb_generation(priv->host),
+			ptask->addr, (quadlet_t *)skb->data, skb->len)) {
+		priv->stats.tx_bytes += skb->len;
+		priv->stats.tx_packets++;
+	} else {
+		//printk("Failed in hpsb_write_sched\n");
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+		if (netif_queue_stopped (dev))
+			netif_wake_queue (dev);
+	}
+	spin_unlock_irqrestore (&priv->lock, flags);
+
+	dev->trans_start = jiffies;
+	dev_kfree_skb(skb);
+	kmem_cache_free(packet_task_cache, ptask);
+
+	return;
+}
+
+/* Transmit a packet (called by kernel) */
+static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
+{
+	int kmflags = in_interrupt () ? GFP_ATOMIC : GFP_KERNEL;
+	struct ethhdr *eth;
+	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;
+	int proto, flags;
+	nodeid_t dest_node;
+	u64 addr;
+	struct packet_task *ptask = NULL;
+	int ret = 0;
+
+	if ((skb = skb_share_check (skb, kmflags)) == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* Get rid of the ethernet header, but save a pointer */
+	eth = (struct ethhdr *)skb->data;
+	skb_pull (skb, ETH_HLEN);
+
+	/* Save the destination id, and proto for our encapsulation, then
+	 * toss the ethernet header aside like the cheap whore it is.  */
+	dest_node = ntohs (*(nodeid_t *)(eth->h_dest));
+	proto = eth->h_proto;
+
+	/* If this is an ARP packet, convert it */
+	if (proto == __constant_htons (ETH_P_ARP))
+		ether1394_arp_to_1394arp (skb, dev);
+
+	/* Now add our encapsulation header */
+	ether1394_encapsulate (skb, dev, proto);
+
+	/* TODO: The above encapsulate function needs to recognize when a
+	 * packet needs to be split for a specified node. It should create
+	 * a list of skb's that we could then iterate over for the below
+	 * call to schedule our writes.  */
+
+	/* XXX: Right now we accept that we don't exactly follow RFC. When
+	 * we do, we will send ARP requests via GASP format, and so we wont
+	 * need this hack.  */
+
+	spin_lock_irqsave (&priv->lock, flags);
+	addr = (u64)priv->fifo_hi[dest_node & NODE_MASK] << 32 |
+		priv->fifo_lo[dest_node & NODE_MASK];
+	spin_unlock_irqrestore (&priv->lock, flags);
+
+	if (!addr)
+		addr = ETHER1394_REGION_ADDR;
+
+	ptask = kmem_cache_alloc(packet_task_cache, kmflags);
+	if (ptask == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	ptask->skb = skb;
+	ptask->addr = addr;
+	ptask->dest_node = dest_node;
+	INIT_TQUEUE(&ptask->tq, hpsb_write_sched, ptask);
+	schedule_task(&ptask->tq);
+
+	return 0;
+fail:
+	printk("Failed in ether1394_tx\n");
+
+	if (skb != NULL)
+		dev_kfree_skb (skb);
+
+	spin_lock_irqsave (&priv->lock, flags);
+	priv->stats.tx_dropped++;
+	priv->stats.tx_errors++;
+	if (netif_queue_stopped (dev))
+		netif_wake_queue (dev);
+	spin_unlock_irqrestore (&priv->lock, flags);
+
+	return ret;
+}
+
+/* Function for incoming 1394 packets */
+static struct hpsb_address_ops addr_ops = {
+	write:		ether1394_write,
+};
+
+/* Ieee1394 highlevel driver functions */
+static struct hpsb_highlevel_ops hl_ops = {
+	add_host:	ether1394_add_host,
+	remove_host:	ether1394_remove_host,
+	host_reset:	ether1394_host_reset,
+};
+
+static int __init ether1394_init_module (void)
+{
+	packet_task_cache = kmem_cache_create("packet_task", sizeof(struct packet_task),
+					      0, 0, NULL, NULL);
+
+	/* Register ourselves as a highlevel driver */
+	hl_handle = hpsb_register_highlevel (ETHER1394_DRIVER_NAME, &hl_ops);
+
+	if (hl_handle == NULL) {
+		ETH1394_PRINT_G (KERN_ERR, "No more memory for driver\n");
+		return -ENOMEM;
+	}
+
+	hpsb_register_addrspace (hl_handle, &addr_ops, ETHER1394_REGION_ADDR,
+				 ETHER1394_REGION_ADDR_END);
+
+	return 0;
+}
+
+static void __exit ether1394_exit_module (void)
+{
+	hpsb_unregister_highlevel (hl_handle);
+	kmem_cache_destroy(packet_task_cache);
+}
+
+module_init(ether1394_init_module);
+module_exit(ether1394_exit_module);
diff -Nru a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/eth1394.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,190 @@
+/*
+ * eth1394.h -- Ethernet driver for Linux IEEE-1394 Subsystem
+ *
+ * Copyright (C) 2000 Bonin Franck <boninf@free.fr>
+ *           (C) 2001 Ben Collins <bcollins@debian.org>
+ *
+ * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ETH1394_H
+#define __ETH1394_H
+
+/* Register for incoming packets. This is 8192 bytes, which supports up to
+ * 1600mbs. We'll need to change this if that ever becomes "small" :)  */
+#define ETHER1394_REGION_ADDR_LEN	8192
+#define ETHER1394_REGION_ADDR		0xfffff0200000ULL
+#define ETHER1394_REGION_ADDR_END	(ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN)
+
+/* Node set == 64 */
+#define NODE_SET			(ALL_NODES + 1)
+
+/* Private structure for our ethernet driver */
+struct eth1394_priv {
+	struct net_device_stats stats;	/* Device stats			 */
+	struct hpsb_host *host;		/* The card for this dev	 */
+	unsigned char max_rec[NODE_SET];/* Max payload per node		 */
+	unsigned char sspd[NODE_SET];	/* Max speed per node		 */
+	u16 fifo_hi[ALL_NODES];		/* 16bit hi fifo offset per node */
+	u32 fifo_lo[ALL_NODES];		/* 32bit lo fifo offset per node */
+	u64 eui[ALL_NODES];		/* EUI-64 per node		 */
+	spinlock_t lock;		/* Private lock			 */
+};
+
+struct host_info {
+	struct list_head list;
+	struct hpsb_host *host;
+	struct net_device *dev;
+};
+
+/* This is our task struct. It's used for the complete_tq callback.  */
+struct packet_task {
+	struct sk_buff *skb;	/* Socket buffer we are sending */
+	nodeid_t dest_node;	/* Destination of the packet */
+	u64 addr;		/* Address */
+	struct tq_struct tq;	/* The task */
+};
+
+/* IP1394 headers */
+#include <asm/byteorder.h>
+
+/* Unfragmented */
+#if defined __BIG_ENDIAN_BITFIELD
+struct eth1394_uf_hdr {
+	u8 lf:2;
+	u16 res:14;
+	u16 ether_type;		/* Ethernet packet type */
+} __attribute__((packed));
+#elif defined __LITTLE_ENDIAN_BITFIELD
+struct eth1394_uf_hdr {
+	u16 res:14;
+	u8 lf:2;
+	u16 ether_type;
+} __attribute__((packed));
+#else
+#error Unknown bit field type
+#endif
+
+/* First fragment */
+#if defined __BIG_ENDIAN_BITFIELD
+struct eth1394_ff_hdr {
+	u8 lf:2;
+	u8 res1:2;
+	u16 dg_size:12;		/* Datagram size */
+	u16 ether_type;		/* Ethernet packet type */
+	u16 dgl;		/* Datagram label */
+	u16 res2;
+} __attribute__((packed));
+#elif defined __LITTLE_ENDIAN_BITFIELD
+struct eth1394_ff_hdr {
+	u16 dg_size:12;
+	u8 res1:2;
+	u8 lf:2;
+	u16 ether_type;
+	u16 dgl;
+	u16 res2;
+} __attribute__((packed));
+#else
+#error Unknown bit field type
+#endif
+
+/* XXX: Subsequent fragments, including last */
+#if defined __BIG_ENDIAN_BITFIELD
+struct eth1394_sf_hdr {
+	u8 lf:2;
+	u8 res1:2;
+	u16 dg_size:12;		/* Datagram size */
+	u8 res2:6;
+	u16 fg_off:10;		/* Fragment offset */
+	u16 dgl;		/* Datagram label */
+	u16 res3;
+} __attribute__((packed));
+#elif defined __LITTLE_ENDIAN_BITFIELD
+struct eth1394_sf_hdr {
+	u16 dg_size:12;
+	u8 res1:2;
+	u8 lf:2;
+	u16 fg_off:10;
+	u8 res2:6;
+	u16 dgl;
+	u16 res3;
+} __attribute__((packed));
+#else
+#error Unknown bit field type
+#endif
+
+#if defined __BIG_ENDIAN_BITFIELD
+struct eth1394_common_hdr {
+	u8 lf:2;
+	u16 pad1:14;
+} __attribute__((packed));
+#elif defined __LITTLE_ENDIAN_BITFIELD
+struct eth1394_common_hdr {
+	u16 pad1:14;
+	u8 lf:2;
+} __attribute__((packed));
+#else
+#error Unknown bit field type
+#endif
+
+struct eth1394_hdr_words {
+	u16 word1;
+	u16 word2;
+	u16 word3;
+	u16 word4;
+};
+
+union eth1394_hdr {
+	struct eth1394_common_hdr common;
+	struct eth1394_uf_hdr uf;
+	struct eth1394_ff_hdr ff;
+	struct eth1394_sf_hdr sf;
+	struct eth1394_hdr_words words;
+};
+
+/* End of IP1394 headers */
+
+/* Fragment types */
+#define ETH1394_HDR_LF_UF	0	/* unfragmented		*/
+#define ETH1394_HDR_LF_FF	1	/* first fragment	*/
+#define ETH1394_HDR_LF_LF	2	/* last fragment	*/
+#define ETH1394_HDR_LF_IF	3	/* interior fragment	*/
+
+#define IP1394_HW_ADDR_LEN	16	/* As per RFC		*/
+
+/* Our arp packet (ARPHRD_IEEE1394) */
+struct eth1394_arp {
+	u16 hw_type;		/* 0x0018	*/
+	u16 proto_type;		/* 0x0806	*/
+	u8 hw_addr_len;		/* 16 		*/
+	u8 ip_addr_len;		/* 4		*/
+	u16 opcode;		/* ARP Opcode	*/
+	/* Above is exactly the same format as struct arphdr */
+
+	u64 s_uniq_id;		/* Sender's 64bit EUI			*/
+	u8 max_rec;		/* Sender's max packet size		*/
+	u8 sspd;		/* Sender's max speed			*/
+	u16 fifo_hi;		/* hi 16bits of sender's FIFO addr	*/
+	u32 fifo_lo;		/* lo 32bits of sender's FIFO addr	*/
+	u32 sip;		/* Sender's IP Address			*/
+	u32 tip;		/* IP Address of requested hw addr	*/
+};
+
+/* Network timeout */
+#define ETHER1394_TIMEOUT	100000
+
+#endif /* __ETH1394_H */
diff -Nru a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
--- a/drivers/ieee1394/hosts.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ieee1394/hosts.c	Sun Apr 14 12:16:57 2002
@@ -43,6 +43,16 @@
         devctl:           dummy_devctl
 };
 
+/**
+ * hpsb_ref_host - increase reference count for host controller.
+ * @host: the host controller
+ *
+ * Increase the reference count for the specified host controller.
+ * When holding a reference to a host, the memory allocated for the
+ * host struct will not be freed and the host is guaranteed to be in a
+ * consistent state.  The driver may be unloaded or the controller may
+ * be removed (PCMCIA), but the host struct will remain valid.
+ */
 
 int hpsb_ref_host(struct hpsb_host *host)
 {
@@ -53,18 +63,26 @@
         spin_lock_irqsave(&hosts_lock, flags);
         list_for_each(lh, &hosts) {
                 if (host == list_entry(lh, struct hpsb_host, host_list)) {
-                        if (host->ops->devctl(host, MODIFY_USAGE, 1)) {
-				host->refcount++;
-                                retval = 1;
-                }
+                        host->ops->devctl(host, MODIFY_USAGE, 1);
+			host->refcount++;
+                        retval = 1;
 			break;
-        }
+        	}
         }
         spin_unlock_irqrestore(&hosts_lock, flags);
 
         return retval;
 }
 
+/**
+ * hpsb_unref_host - decrease reference count for host controller.
+ * @host: the host controller
+ *
+ * Decrease the reference count for the specified host controller.
+ * When the reference count reaches zero, the memory allocated for the
+ * &hpsb_host will be freed.
+ */
+
 void hpsb_unref_host(struct hpsb_host *host)
 {
         unsigned long flags;
@@ -74,23 +92,44 @@
         spin_lock_irqsave(&hosts_lock, flags);
         host->refcount--;
 
-        if (!host->refcount && !host->is_shutdown)
+        if (!host->refcount && host->is_shutdown)
                 kfree(host);
         spin_unlock_irqrestore(&hosts_lock, flags);
 }
 
+/**
+ * hpsb_alloc_host - allocate a new host controller.
+ * @drv: the driver that will manage the host controller
+ * @extra: number of extra bytes to allocate for the driver
+ *
+ * Allocate a &hpsb_host and initialize the general subsystem specific
+ * fields.  If the driver needs to store per host data, as drivers
+ * usually do, the amount of memory required can be specified by the
+ * @extra parameter.  Once allocated, the driver should initialize the
+ * driver specific parts, enable the controller and make it available
+ * to the general subsystem using hpsb_add_host().
+ *
+ * The &hpsb_host is allocated with an single initial reference
+ * belonging to the driver.  Once the driver is done with the struct,
+ * for example, when the driver is unloaded, it should release this
+ * reference using hpsb_unref_host().
+ *
+ * Return Value: a pointer to the &hpsb_host if succesful, %NULL if
+ * no memory was available.
+ */
+
 struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra)
 {
         struct hpsb_host *h;
 
         h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
         if (!h) return NULL;
+        memset(h, 0, sizeof(struct hpsb_host));
 
-        memset(h, 0, sizeof(struct hpsb_host) + extra);
-
+	h->hostdata = h + 1;
         h->driver = drv;
         h->ops = drv->ops;
-	h->hostdata = h + 1;
+	h->refcount = 1;
 
         INIT_LIST_HEAD(&h->pending_packets);
         spin_lock_init(&h->pending_pkt_lock);
@@ -134,9 +173,7 @@
         spin_lock_irqsave(&hosts_lock, flags);
         list_del(&host->driver_list);
         list_del(&host->host_list);
-
         drv->number_of_hosts--;
-        if (!host->refcount) kfree(host);
         spin_unlock_irqrestore(&hosts_lock, flags);
 }
 
diff -Nru a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
--- a/drivers/ieee1394/hosts.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/ieee1394/hosts.h	Sun Apr 14 12:16:56 2002
@@ -36,6 +36,7 @@
 
         int node_count; /* number of identified nodes on this bus */
         int selfid_count; /* total number of SelfIDs received */
+	int nodes_active; /* number of nodes that are actually active */
 
         nodeid_t node_id; /* node ID of this host */
         nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
--- a/drivers/ieee1394/ieee1394_core.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ieee1394/ieee1394_core.c	Sun Apr 14 12:16:56 2002
@@ -41,6 +41,10 @@
 MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
 static int disable_nodemgr = 0;
 
+MODULE_PARM(disable_hotplug, "i");
+MODULE_PARM_DESC(disable_hotplug, "Disable hotplug for detected nodes.");
+static int disable_hotplug = 0;
+
 /* We are GPL, so treat us special */
 MODULE_LICENSE("GPL");
 
@@ -108,7 +112,7 @@
                 packet->data_size = data_size;
         }
 
-        INIT_TQ_HEAD(packet->complete_tq);
+        INIT_LIST_HEAD(&packet->complete_tq);
         INIT_LIST_HEAD(&packet->list);
         sema_init(&packet->state_change, 0);
         packet->state = hpsb_unused;
@@ -177,6 +181,8 @@
         struct ext_selfid *esid;
         int esid_seq = 23;
 
+	host->nodes_active = 0;
+
         while (rest_of_selfids--) {
                 if (!sid->extended) {
                         nodeid++;
@@ -188,9 +194,11 @@
                                 return 0;
                         }
                         
-                        if (sid->contender && sid->link_active) {
-                                host->irm_id = LOCAL_BUS | sid->phy_id;
-                        }
+			if (sid->link_active) {
+				host->nodes_active++;
+				if (sid->contender)
+					host->irm_id = LOCAL_BUS | sid->phy_id;
+			}
                 } else {
                         esid = (struct ext_selfid *)sid;
 
@@ -224,7 +232,8 @@
                         return 0;
         }
 
-        return nodeid + 1;
+	host->node_count = nodeid + 1;
+        return 1;
 }
 
 static void build_speed_map(struct hpsb_host *host, int nodecount)
@@ -322,8 +331,7 @@
         host->node_id = LOCAL_BUS | phyid;
         host->is_root = isroot;
 
-        host->node_count = check_selfids(host);
-        if (!host->node_count) {
+        if (!check_selfids(host)) {
                 if (host->reset_retries++ < 20) {
                         /* selfid stage did not complete without error */
                         HPSB_NOTICE("Error in SelfID stage, resetting");
@@ -803,8 +811,8 @@
 static int ieee1394_dispatch_open(struct inode *inode, struct file *file);
 
 static struct file_operations ieee1394_chardev_ops = {
-	OWNER_THIS_MODULE
-	open: ieee1394_dispatch_open,
+	owner:	THIS_MODULE,
+	open:	ieee1394_dispatch_open,
 };
 
 devfs_handle_t ieee1394_devfs_handle;
@@ -828,8 +836,6 @@
 		ieee1394_chardevs[blocknum].module = module;
 		
 		retval = 0;
-
-		V22_COMPAT_MOD_INC_USE_COUNT;
 	} else {
 		/* block already taken */
 		retval = -EBUSY;
@@ -851,7 +857,6 @@
 	if(ieee1394_chardevs[blocknum].file_ops) {
 		ieee1394_chardevs[blocknum].file_ops = NULL;
 		ieee1394_chardevs[blocknum].module = NULL;
-		V22_COMPAT_MOD_DEC_USE_COUNT;
 	}
 	
 	write_unlock(&ieee1394_chardevs_lock);
@@ -868,12 +873,6 @@
 	/*
 	  Maintaining correct module reference counts is tricky here!
 
-	  For Linux v2.2:
-
-	  The task-specific driver is expected to maintain its own
-	  reference count via V22_COMPAT_MOD_[INC,DEC]_USE_COUNT.
-	  We don't need to do anything special.
-	  
 	  For Linux v2.4 and later:
 	  
 	  The key thing to remember is that the VFS increments the
@@ -894,17 +893,10 @@
 	  
 	*/
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-	/* 2.2 */
-#define INCREF(mod) do {} while (0)
-#define DECREF(mod) do {} while (0)
-#else
-	/* 2.4 */
 #define INCREF(mod_) do { struct module *mod = (struct module*) mod_; \
                           if(mod != NULL) __MOD_INC_USE_COUNT(mod); } while(0)
 #define DECREF(mod_) do { struct module *mod = (struct module*) mod_; \
                           if(mod != NULL) __MOD_DEC_USE_COUNT(mod); } while(0)
-#endif
 	
         /* shift away lower four bits of the minor
 	   to get the index of the ieee1394_driver
@@ -1013,7 +1005,7 @@
 	init_hpsb_highlevel();
 	init_csr();
 	if (!disable_nodemgr)
-		init_ieee1394_nodemgr();
+		init_ieee1394_nodemgr(disable_hotplug);
 	else
 		HPSB_INFO("nodemgr functionality disabled");
 
@@ -1099,8 +1091,10 @@
 
 EXPORT_SYMBOL(hpsb_guid_get_entry);
 EXPORT_SYMBOL(hpsb_nodeid_get_entry);
-EXPORT_SYMBOL(hpsb_get_host_by_ne);
-EXPORT_SYMBOL(hpsb_guid_fill_packet);
+EXPORT_SYMBOL(hpsb_node_fill_packet);
+EXPORT_SYMBOL(hpsb_node_read);
+EXPORT_SYMBOL(hpsb_node_write);
+EXPORT_SYMBOL(hpsb_node_lock);
 EXPORT_SYMBOL(hpsb_register_protocol);
 EXPORT_SYMBOL(hpsb_unregister_protocol);
 EXPORT_SYMBOL(hpsb_release_unit_directory);
diff -Nru a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
--- a/drivers/ieee1394/ieee1394_transactions.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ieee1394/ieee1394_transactions.c	Sun Apr 14 12:16:57 2002
@@ -415,8 +415,8 @@
  * avoid in kernel buffers for user space callers
  */
 
-int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr,
-              quadlet_t *buffer, size_t length)
+int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	      u64 addr, quadlet_t *buffer, size_t length)
 {
         struct hpsb_packet *packet;
         int retval = 0;
@@ -447,7 +447,7 @@
                 return -ENOMEM;
         }
 
-	packet->generation = get_hpsb_generation(host);
+	packet->generation = generation;
         if (!hpsb_send_packet(packet)) {
 		retval = -EINVAL;
 		goto hpsb_read_fail;
@@ -496,8 +496,8 @@
 	return packet;
 }
 
-int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr,
-	       quadlet_t *buffer, size_t length)
+int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	       u64 addr, quadlet_t *buffer, size_t length)
 {
 	struct hpsb_packet *packet;
 	int retval;
@@ -522,7 +522,7 @@
 	if (!packet)
 		return -ENOMEM;
 
-	packet->generation = get_hpsb_generation(host);
+	packet->generation = generation;
         if (!hpsb_send_packet(packet)) {
 		retval = -EINVAL;
 		goto hpsb_write_fail;
@@ -541,8 +541,8 @@
 
 
 /* We need a hpsb_lock64 function for the 64 bit equivalent.  Probably. */
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, u64 addr, int extcode,
-              quadlet_t *data, quadlet_t arg)
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
 {
         struct hpsb_packet *packet;
         int retval = 0, length;
@@ -588,7 +588,7 @@
         }
         fill_async_lock(packet, addr, extcode, length);
 
-	packet->generation = get_hpsb_generation(host);
+	packet->generation = generation;
         if (!hpsb_send_packet(packet)) {
 		retval = -EINVAL;
 		goto hpsb_lock_fail;
diff -Nru a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
--- a/drivers/ieee1394/ieee1394_transactions.h	Sun Apr 14 12:16:57 2002
+++ b/drivers/ieee1394/ieee1394_transactions.h	Sun Apr 14 12:16:57 2002
@@ -63,14 +63,16 @@
  * The generic read, write and lock functions.  All recognize the local node ID
  * and act accordingly.  Read and write automatically use quadlet commands if
  * length == 4 and and block commands otherwise (however, they do not yet
- * support lengths that are not a multiple of 4).
+ * support lengths that are not a multiple of 4).  You must explicitly specifiy
+ * the generation for which the node ID is valid, to avoid sending packets to
+ * the wrong nodes when we race with a bus reset.
  */
-int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr,
-              quadlet_t *buffer, size_t length);
-int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr,
-               quadlet_t *buffer, size_t length);
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, u64 addr, int extcode,
-              quadlet_t *data, quadlet_t arg);
+int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	      u64 addr, quadlet_t *buffer, size_t length);
+int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	       u64 addr, quadlet_t *buffer, size_t length);
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
 
 /* Generic packet creation. Used by hpsb_write. Also useful for protocol
  * drivers that want to implement their own hpsb_write replacement.  */
diff -Nru a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
--- a/drivers/ieee1394/ieee1394_types.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/ieee1394/ieee1394_types.h	Sun Apr 14 12:16:59 2002
@@ -10,17 +10,6 @@
 #include <asm/byteorder.h>
 
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-#include "linux22compat.h"
-#else
-#define V22_COMPAT_MOD_INC_USE_COUNT do {} while (0)
-#define V22_COMPAT_MOD_DEC_USE_COUNT do {} while (0)
-#define OWNER_THIS_MODULE owner: THIS_MODULE,
-
-#define INIT_TQ_LINK(tq) INIT_LIST_HEAD(&(tq).list)
-#define INIT_TQ_HEAD(tq) INIT_LIST_HEAD(&(tq))
-#endif
-
 /* The great kdev_t changeover in 2.5.x */
 #include <linux/kdev_t.h>
 #ifndef minor
@@ -48,11 +37,7 @@
 
 #endif /* Linux version < 2.4.12 */
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
-#include <asm/spinlock.h>
-#else
 #include <linux/spinlock.h>
-#endif
 
 #ifndef list_for_each_safe
 #define list_for_each_safe(pos, n, head) \
@@ -61,6 +46,10 @@
 
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,5)
+#define pte_offset_kernel pte_offset
+#endif
+
 #ifndef MIN
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
@@ -78,7 +67,8 @@
 #define LOCAL_BUS 0xffc0
 #define ALL_NODES 0x003f
 
-#define NODE_BUS_FMT    "%d:%d"
+/* Can be used to consistently print a node/bus ID. */
+#define NODE_BUS_FMT    "%02d:%04d"
 #define NODE_BUS_ARGS(nodeid) \
 	(nodeid & NODE_MASK), ((nodeid & BUS_MASK) >> 6)
 
diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
--- a/drivers/ieee1394/nodemgr.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ieee1394/nodemgr.c	Sun Apr 14 12:16:55 2002
@@ -12,11 +12,11 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
-#include <asm/atomic.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
 #include <linux/completion.h>
+#include <linux/delay.h>
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #endif
@@ -61,70 +61,122 @@
 static LIST_HEAD(host_info_list);
 static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
 
+/* Disables use of the hotplug calls.  */
+static int nodemgr_disable_hotplug = 0;
+
 struct host_info {
 	struct hpsb_host *host;
 	struct list_head list;
-	struct completion started;
 	struct completion exited;
-	wait_queue_head_t wait;
+	struct semaphore reset_sem;
 	int pid;
 };
 
 #ifdef CONFIG_PROC_FS
 
-static int raw1394_read_proc(char *buffer, char **start, off_t offset,
-			     int size, int *eof, void *data )
+#define PUTF(fmt, args...) out += sprintf(out, fmt, ## args)
+
+static int raw1394_read_proc(char *page, char **start, off_t off,
+			     int count, int *eof, void *data)
 {
 	struct list_head *lh;
 	struct node_entry *ne;
-	int disp_size = 0;
-	char display_str[1024];
+	int len;
+	char *out = page;
 
-#define PUTF(fmt, args...) disp_size += sprintf(display_str, fmt, ## args); strcat(buffer,display_str)
-	buffer[0] = '\0';
 	list_for_each(lh, &node_list) {
+		struct list_head *l;
+		int ud_count = 0;
+
 		ne = list_entry(lh, struct node_entry, list);
 		if (!ne)
 			continue;
+
 		PUTF("Node[" NODE_BUS_FMT "]  GUID[%016Lx]:\n",
 		     NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid);
-		if (ne->host != NULL && ne->host->node_id == ne->nodeid) {
-			PUTF("\tNodes connected : %d\n", ne->host->node_count);
-			PUTF("\tSelfIDs received: %d\n", ne->host->selfid_count);
-			PUTF("\tOwn ID          : 0x%08x\n",ne->host->node_id);
-			PUTF("\tIrm ID          : 0x%08x\n",ne->host->irm_id);
-			PUTF("\tBusMgr ID       : 0x%08x\n",ne->host->busmgr_id);
-			PUTF("\tBR IR IC II IB\n");
-			PUTF("\t%02d %02d %02d %02d %02d\n",
-			     ne->host->in_bus_reset, ne->host->is_root,
-			     ne->host->is_cycmst, ne->host->is_irm,
-			     ne->host->is_busmgr);
-		}
-		PUTF("\tVendor ID: %s [0x%06x]\n",
+
+		/* Generic Node information */
+		PUTF("  Vendor ID: `%s' [0x%06x]\n",
 		     ne->vendor_name ?: "Unknown", ne->vendor_id);
-		PUTF("\tCapabilities: 0x%06x\n", ne->capabilities);
-		PUTF("\tirmc=%d cmc=%d isc=%d bmc=%d pmc=%d cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d\n",
+		PUTF("  Capabilities: 0x%06x\n", ne->capabilities);
+		PUTF("  Bus Options:\n");
+		PUTF("    IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d)\n"
+		     "    LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n",
 		     ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
-		     ne->busopt.pmc, ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
-		     ne->busopt.generation, ne->busopt.lnkspd);
+		     ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd,
+		     ne->busopt.max_rec, ne->busopt.cyc_clk_acc);
+
+		/* If this is the host entry, output some info about it aswell */
+		if (ne->host != NULL && ne->host->node_id == ne->nodeid) {
+			PUTF("  Host Node Status:\n");
+			PUTF("    Host Driver     : %s\n", ne->host->driver->name);
+			PUTF("    Nodes connected : %d\n", ne->host->node_count);
+			PUTF("    Nodes active    : %d\n", ne->host->nodes_active);
+			PUTF("    SelfIDs received: %d\n", ne->host->selfid_count);
+			PUTF("    Irm ID          : [" NODE_BUS_FMT "]\n",
+			     NODE_BUS_ARGS(ne->host->irm_id));
+			PUTF("    BusMgr ID       : [" NODE_BUS_FMT "]\n",
+			     NODE_BUS_ARGS(ne->host->busmgr_id));
+			PUTF("    In Bus Reset    : %s\n", ne->host->in_bus_reset ? "yes" : "no");
+			PUTF("    Root            : %s\n", ne->host->is_root ? "yes" : "no");
+			PUTF("    Cycle Master    : %s\n", ne->host->is_cycmst ? "yes" : "no");
+			PUTF("    IRM             : %s\n", ne->host->is_irm ? "yes" : "no");
+			PUTF("    Bus Manager     : %s\n", ne->host->is_busmgr ? "yes" : "no");
+		}
+
+		/* Now the unit directories */
+		list_for_each (l, &ne->unit_directories) {
+			struct unit_directory *ud = list_entry (l, struct unit_directory, node_list);
+			PUTF("  Unit Directory %d:\n", ud_count++);
+			if (ud->flags & UNIT_DIRECTORY_VENDOR_ID)
+				PUTF("    Vendor/Model ID: %s [%06x]",
+				     ud->vendor_name ?: "Unknown", ud->vendor_id);
+			else if (ud->flags & UNIT_DIRECTORY_MODEL_ID) /* Have to put something */
+				PUTF("    Vendor/Model ID: %s [%06x]",
+				      ne->vendor_name ?: "Unknown", ne->vendor_id);
+			if (ud->flags & UNIT_DIRECTORY_MODEL_ID)
+				PUTF(" / %s [%06x]", ud->model_name ?: "Unknown", ud->model_id);
+			PUTF("\n");
+			if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
+				PUTF("    Software Specifier ID: %06x\n", ud->specifier_id);
+			if (ud->flags & UNIT_DIRECTORY_VERSION)
+				PUTF("    Software Version: %06x\n", ud->version);
+			if (ud->driver)
+				PUTF("    Driver: %s\n", ud->driver->name);
+			PUTF("    Length (in quads): %d\n", ud->count);
+		}
+
 	}
-#undef PUTF
-    return disp_size;
+
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else
+		len = count;
+
+        *start = page + off;
+
+	return len;
 }
+
+#undef PUTF
 #endif /* CONFIG_PROC_FS */
 
 static void nodemgr_process_config_rom(struct node_entry *ne, 
 				       quadlet_t busoptions);
 
 static int nodemgr_read_quadlet(struct hpsb_host *host,
-				nodeid_t nodeid, octlet_t address,
-				quadlet_t *quad)
+				nodeid_t nodeid, unsigned int generation,
+				octlet_t address, quadlet_t *quad)
 {
 	int i;
 	int ret = 0;
 
 	for (i = 0; i < 3; i++) {
-		ret = hpsb_read(host, nodeid, address, quad, 4);
+		ret = hpsb_read(host, nodeid, generation, address, quad, 4);
 		if (ret != -EAGAIN)
 			break;
 	}
@@ -134,17 +186,17 @@
 }
 
 static int nodemgr_size_text_leaf(struct hpsb_host *host,
-				  nodeid_t nodeid,
+				  nodeid_t nodeid, unsigned int generation,
 				  octlet_t address)
 {
 	quadlet_t quad;
 	int size = 0;
-	if (nodemgr_read_quadlet(host, nodeid, address, &quad))
+	if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
 		return -1;
 	if (CONFIG_ROM_KEY(quad) == CONFIG_ROM_DESCRIPTOR_LEAF) {
 		/* This is the offset.  */
 		address += 4 * CONFIG_ROM_VALUE(quad); 
-		if (nodemgr_read_quadlet(host, nodeid, address, &quad))
+		if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
 			return -1;
 		/* Now we got the size of the text descriptor leaf. */
 		size = CONFIG_ROM_LEAF_LENGTH(quad);
@@ -152,21 +204,20 @@
 	return size;
 }
 
-static int nodemgr_read_text_leaf(struct hpsb_host *host,
-				  nodeid_t nodeid,
+static int nodemgr_read_text_leaf(struct node_entry *ne,
 				  octlet_t address,
 				  quadlet_t *quadp)
 {
 	quadlet_t quad;
 	int i, size, ret;
 
-	if (nodemgr_read_quadlet(host, nodeid, address, &quad)
+	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)
 	    && CONFIG_ROM_KEY(quad) != CONFIG_ROM_DESCRIPTOR_LEAF)
 		return -1;
 
 	/* This is the offset.  */
 	address += 4 * CONFIG_ROM_VALUE(quad);
-	if (nodemgr_read_quadlet(host, nodeid, address, &quad))
+	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
 		return -1;
 
 	/* Now we got the size of the text descriptor leaf. */
@@ -176,7 +227,7 @@
 
 	address += 4;
 	for (i = 0; i < 2; i++, address += 4, quadp++) {
-		if (nodemgr_read_quadlet(host, nodeid, address, quadp))
+		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, quadp))
 			return -1;
 	}
 
@@ -184,7 +235,7 @@
 	ret = -ENXIO;
 	for (; size > 0; size--, address += 4, quadp++) {
 		for (i = 0; i < 3; i++) {
-			ret = hpsb_read(host, nodeid, address, quadp, 4);
+			ret = hpsb_read(ne->host, ne->nodeid, ne->generation, address, quadp, 4);
 			if (ret != -EAGAIN)
 				break;
 		}
@@ -196,7 +247,7 @@
 }
 
 static struct node_entry *nodemgr_scan_root_directory
-	(struct hpsb_host *host, nodeid_t nodeid)
+	(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation)
 {
 	octlet_t address;
 	quadlet_t quad;
@@ -206,11 +257,11 @@
 
 	address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
 	
-	if (nodemgr_read_quadlet(host, nodeid, address, &quad))
+	if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
 		return NULL;
 	address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
 
-	if (nodemgr_read_quadlet(host, nodeid, address, &quad))
+	if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
 		return NULL;
 	length = CONFIG_ROM_ROOT_LENGTH(quad);
 	address += 4;
@@ -218,30 +269,22 @@
 	size = 0;
 	total_size = sizeof(struct node_entry);
 	for (; length > 0; length--, address += 4) {
-		if (nodemgr_read_quadlet(host, nodeid, address, &quad))
+		if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad))
 			return NULL;
 		code = CONFIG_ROM_KEY(quad);
 
-		if (code == CONFIG_ROM_VENDOR_ID) {
+		if (code == CONFIG_ROM_VENDOR_ID && length > 0) {
 			/* Check if there is a text descriptor leaf
 			   immediately after this.  */
-			length--;
-			if (length <= 0)
-				break;	
-			address += 4;
-			size = nodemgr_size_text_leaf(host, nodeid,
-						      address);
-			switch (size) {
-			case -1:
-				return NULL;
-				break;
-			case 0:
-				break;
-			default:
+			size = nodemgr_size_text_leaf(host, nodeid, generation,
+						      address + 4);
+			if (size > 0) {
+				address += 4;
+				length--;
 				total_size += (size + 1) * sizeof (quadlet_t);
-				break;
 			}
-			break;
+			else if (size < 0)
+				return NULL;
 		}
 	}
 	ne = kmalloc(total_size, SLAB_ATOMIC);
@@ -259,12 +302,13 @@
 }
 
 static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions,
-					      struct hpsb_host *host, nodeid_t nodeid)
+					      struct hpsb_host *host,
+					      nodeid_t nodeid, unsigned int generation)
 {
         struct node_entry *ne;
         unsigned long flags;
 
-	ne = nodemgr_scan_root_directory (host, nodeid);
+	ne = nodemgr_scan_root_directory (host, nodeid, generation);
         if (!ne) return NULL;
 
         INIT_LIST_HEAD(&ne->list);
@@ -272,7 +316,7 @@
         ne->host = host;
         ne->nodeid = nodeid;
         ne->guid = guid;
-	atomic_set(&ne->generation, get_hpsb_generation(ne->host));
+	ne->generation = generation;
 
         write_lock_irqsave(&node_lock, flags);
         list_add_tail(&ne->list, &node_list);
@@ -281,7 +325,7 @@
 	nodemgr_process_config_rom (ne, busoptions);
 
 	HPSB_DEBUG("%s added: Node[" NODE_BUS_FMT "]  GUID[%016Lx]  [%s]",
-		   (host->node_id == nodeid) ? "Local host" : "Device",
+		   (host->node_id == nodeid) ? "Host" : "Device",
 		   NODE_BUS_ARGS(nodeid), (unsigned long long)guid,
 		   ne->vendor_name ?: "Unknown");
 
@@ -323,7 +367,7 @@
 	int length, size, total_size, count;
 	int vendor_name_size, model_name_size;
 
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
 		return NULL;
 	length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
 	address += 4;
@@ -338,8 +382,8 @@
 		int code;
 		quadlet_t value;
 
-retry:
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
+					 address, &quad))
 			return NULL;
 		code = CONFIG_ROM_KEY(quad);
 		value = CONFIG_ROM_VALUE(quad);
@@ -373,32 +417,27 @@
 			break;
 		}
 
-		if (todo) {
+		if (todo && length > 0) {
 			/* Check if there is a text descriptor leaf
 			   immediately after this.  */
-			length--;
-			if (length <= 0)
-				break;
-			address += 4;
 			size = nodemgr_size_text_leaf(ne->host,
 						      ne->nodeid,
-						      address);
-			if (todo | UNIT_DIRECTORY_VENDOR_TEXT)
+						      ne->generation,
+						      address + 4);
+
+			if (todo == UNIT_DIRECTORY_VENDOR_TEXT)
 				vendor_name_size = size;
 			else
 				model_name_size = size;
-			switch (size) {
-			case -1:
-				return NULL;
-				break;
-			case 0:
-				goto retry;
-				break;
-			default:
+
+			if (size > 0) {
+				address += 4;
+				length--;
 				flags |= todo;
 				total_size += (size + 1) * sizeof (quadlet_t);
-				break;
 			}
+			else if (size < 0)
+				return NULL;
 		}
 	}
 	total_size += count * sizeof (quadlet_t);
@@ -435,7 +474,8 @@
 	ud->ne = ne;
 	ud->address = address;
 
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
+				 address, &quad))
 		goto unit_directory_error;
 	length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
 	address += 4;
@@ -446,7 +486,8 @@
 		quadlet_t value;
 		quadlet_t *quadp;
 
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
+					 address, &quad))
 			goto unit_directory_error;
 		code = CONFIG_ROM_KEY(quad) ;
 		value = CONFIG_ROM_VALUE(quad);
@@ -459,9 +500,7 @@
 				length--;
 				address += 4;
 				quadp = &(ud->quadlets[ud->count]);
-				if (nodemgr_read_text_leaf(ne->host,
-							   ne->nodeid,
-							   address,
+				if (nodemgr_read_text_leaf(ne, address,
 							   quadp) == 0
 				    && quadp[0] == 0
 				    && quadp[1] == 0) {
@@ -481,9 +520,7 @@
 				length--;
 				address += 4;
 				quadp = &(ud->quadlets[ud->count + ud->vendor_name_size + 1]);
-				if (nodemgr_read_text_leaf(ne->host,
-							   ne->nodeid,
-							   address,
+				if (nodemgr_read_text_leaf(ne, address,
 							   quadp) == 0
 				    && quadp[0] == 0
 				    && quadp[1] == 0) {
@@ -568,11 +605,13 @@
 
 	address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
 	
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
+				 address, &quad))
 		return;
 	address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;
 
-	if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
+				 address, &quad))
 		return;
 	length = CONFIG_ROM_ROOT_LENGTH(quad);
 	address += 4;
@@ -580,7 +619,8 @@
 	for (; length > 0; length--, address += 4) {
 		int code, value;
 
-		if (nodemgr_read_quadlet(ne->host, ne->nodeid, address, &quad))
+		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
+					 address, &quad))
 			return;
 		code = CONFIG_ROM_KEY(quad);
 		value = CONFIG_ROM_VALUE(quad);
@@ -593,9 +633,7 @@
 			if (ne->vendor_name != NULL) {
 				length--;
 				address += 4;
-				if (nodemgr_read_text_leaf(ne->host,
-							   ne->nodeid,
-							   address,
+				if (nodemgr_read_text_leaf(ne, address,
 							   ne->quadlets)
 				    != 0
 				    || ne->quadlets [0] != 0
@@ -631,6 +669,10 @@
 	char *argv [3], **envp, *buf, *scratch;
 	int i = 0, value;
 
+	/* User requested to disable hotplug when module was loaded. */
+	if (nodemgr_disable_hotplug)
+		return;
+
 	if (!hotplug_path [0])
 		return;
 	if (!current->fs->root)
@@ -902,7 +944,8 @@
  * the to take whatever actions required.
  */
 static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
-                               struct hpsb_host *host, nodeid_t nodeid)
+                               struct hpsb_host *host,
+				nodeid_t nodeid, unsigned int generation)
 {
 	struct list_head *lh;
 	struct unit_directory *ud;
@@ -917,7 +960,7 @@
 		nodemgr_process_config_rom (ne, busoptions);
 
 	/* Since that's done, we can declare this record current */
-	atomic_set(&ne->generation, get_hpsb_generation(ne->host));
+	ne->generation = generation;
 
 	list_for_each (lh, &ne->unit_directories) {
 		ud = list_entry (lh, struct unit_directory, node_list);
@@ -926,73 +969,59 @@
 	}
 }
 
-static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid,
+static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation,
 			      quadlet_t *buffer, int buffer_length)
 {
-	octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
-	int retries = 3;
-	int header_count;
+	octlet_t addr = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
 	unsigned header_size;
-	quadlet_t quad;
-	int ret;
-
-retry_configrom:
-
-	if (!retries--) {
-		HPSB_ERR("Giving up on node " NODE_BUS_FMT
-			 " for ConfigROM probe, too many errors",
-			 NODE_BUS_ARGS(nodeid));
-		return -1;
-	}
+	int i;
 
-	header_count = 0;
-	header_size = 0;
+	/* IEEE P1212 says that devices should support 64byte block
+	 * reads, aligned on 64byte boundaries. That doesn't seem to
+	 * work though, and we are forced to doing quadlet sized
+	 * reads.  */
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 	HPSB_INFO("Initiating ConfigROM request for node " NODE_BUS_FMT,
 		  NODE_BUS_ARGS(nodeid));
 #endif
 
-	/* Now, P1212 says that devices should support 64byte block
-	 * reads, aligned on 64byte boundaries. That doesn't seem
-	 * to work though, and we are forced to doing quadlet
-	 * sized reads.  */
-
-	ret = hpsb_read(host, nodeid, base, &quad, 4);
-	if (ret) {
-		HPSB_ERR("ConfigROM quadlet transaction error (%d) for node " NODE_BUS_FMT,
-			 ret, NODE_BUS_ARGS(nodeid));
-		goto retry_configrom;
+	if (nodemgr_read_quadlet(host, nodeid, generation,
+				 addr, &buffer[0]) < 0) {
+		HPSB_ERR("ConfigROM quadlet transaction error for node "
+			 NODE_BUS_FMT, NODE_BUS_ARGS(nodeid));
+		return -1;
 	}
-	buffer[header_count++] = be32_to_cpu(quad);
 
 	header_size = buffer[0] >> 24;
+	addr += 4;
 
 	if (header_size < 4) {
-		HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM format (%d quads), "
-			  "cannot parse", NODE_BUS_ARGS(nodeid), header_size);
+		HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM "
+			  "format (%d quads), cannot parse",
+			  NODE_BUS_ARGS(nodeid), header_size);
 		return -1;
 	}
 
-	while (header_count <= header_size && header_count < buffer_length) {
-		ret = hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4);
-		if (ret) {
-			HPSB_ERR("ConfigROM quadlet transaction error (%d) for " NODE_BUS_FMT,
-				 ret, NODE_BUS_ARGS(nodeid));
-			goto retry_configrom;
+	for (i = 1; i < buffer_length; i++, addr += 4) {
+		if (nodemgr_read_quadlet(host, nodeid, generation,
+					 addr, &buffer[i]) < 0) {
+			HPSB_ERR("ConfigROM quadlet transaction "
+				 "error for node " NODE_BUS_FMT,
+				 NODE_BUS_ARGS(nodeid));
+			return -1;
 		}
-		buffer[header_count++] = be32_to_cpu(quad);
 	}
 
 	return 0;
-}
+}		
 
 static void nodemgr_remove_node(struct node_entry *ne)
 {
 	unsigned long flags;
 
 	HPSB_DEBUG("%s removed: Node[" NODE_BUS_FMT "]  GUID[%016Lx]  [%s]",
-		   (ne->host->node_id == ne->nodeid) ? "Local host" : "Device",
+		   (ne->host->node_id == ne->nodeid) ? "Host" : "Device",
 		   NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid,
 		   ne->vendor_name ?: "Unknown");
 
@@ -1007,7 +1036,8 @@
 
 /* This is where we probe the nodes for their information and provided
  * features.  */
-static void nodemgr_node_probe_one(struct hpsb_host *host, nodeid_t nodeid)
+static void nodemgr_node_probe_one(struct hpsb_host *host,
+				   nodeid_t nodeid, int generation)
 {
 	struct node_entry *ne;
 	quadlet_t buffer[5];
@@ -1016,7 +1046,8 @@
 	/* We need to detect when the ConfigROM's generation has changed,
 	 * so we only update the node's info when it needs to be.  */
 
-	if (read_businfo_block (host, nodeid, buffer, sizeof(buffer) >> 2))
+	if (read_businfo_block (host, nodeid, generation,
+				buffer, sizeof(buffer) >> 2))
 		return;
 
 	if (buffer[1] != IEEE1394_BUSID_MAGIC) {
@@ -1030,14 +1061,14 @@
 	ne = hpsb_guid_get_entry(guid);
 
 	if (!ne)
-		nodemgr_create_node(guid, buffer[2], host, nodeid);
+		nodemgr_create_node(guid, buffer[2], host, nodeid, generation);
 	else
-		nodemgr_update_node(ne, buffer[2], host, nodeid);
+		nodemgr_update_node(ne, buffer[2], host, nodeid, generation);
 
 	return;
 }
 
-static void nodemgr_node_probe_cleanup(struct hpsb_host *host)
+static void nodemgr_node_probe_cleanup(struct hpsb_host *host, unsigned int generation)
 {
 	unsigned long flags;
 	struct list_head *lh, *next;
@@ -1057,7 +1088,7 @@
 		 * node was removed, or it failed the above probe. Either
 		 * way, we remove references to it, since they are
 		 * invalid.  */
-		if (!hpsb_node_entry_valid(ne))
+		if (ne->generation != generation)
 			nodemgr_remove_node(ne);
 	}
 	write_unlock_irqrestore(&node_lock, flags);
@@ -1067,22 +1098,46 @@
 
 static void nodemgr_node_probe(struct hpsb_host *host)
 {
-	int nodecount = host->node_count;
+	int count;
 	struct selfid *sid = (struct selfid *)host->topology_map;
 	nodeid_t nodeid = LOCAL_BUS;
+	unsigned int generation;
+
+	/* Pause for 1 second, to make sure things settle down. If
+	 * schedule_timeout returns non-zero, it means we caught a signal
+	 * and need to return. */
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (schedule_timeout (HZ))
+		return;
+
+	/* Now get the generation in which the node ID's we collect
+	 * are valid.  During the bus scan we will use this generation
+	 * for the read transactions, so that if another reset occurs
+	 * during the scan the transactions will fail instead of
+	 * returning bogus data. */
+	generation = get_hpsb_generation(host);
 
 	/* Scan each node on the bus */
-	for (; nodecount; nodecount--, nodeid++, sid++) {
-		while (sid->extended)
-			sid++;
-		if (!sid->link_active)
+	for (count = host->selfid_count; count; count--, sid++) {
+		if (sid->extended)
 			continue;
 
-		nodemgr_node_probe_one(host, nodeid);
+		if (!sid->link_active) {
+			nodeid++;
+			continue;
+		}
+
+		nodemgr_node_probe_one(host, nodeid++, generation);
 	}
 
-	/* Cleanup if needed */
-	nodemgr_node_probe_cleanup(host);
+	/* If we had a bus reset while we were scanning the bus, it is
+	 * possible that we did not probe all nodes.  In that case, we
+	 * skip the clean up for now, since we could remove nodes that
+	 * were still on the bus.  The bus reset increased
+	 * hi->reset_sem, so there's a bus scan pending which will do
+	 * the clean up eventually. */
+	if (generation == get_hpsb_generation(host))
+		nodemgr_node_probe_cleanup(host, generation);
 
 	return;
 }
@@ -1090,29 +1145,21 @@
 static int nodemgr_host_thread(void *__hi)
 {
 	struct host_info *hi = (struct host_info *)__hi;
-	lock_kernel();
 
 	/* No userlevel access needed */
 	daemonize();
 
-	strcpy(current->comm, "NodeMgr");
-
-	complete(&hi->started);
+	strcpy(current->comm, "knodemgrd");
 
 	/* Sit and wait for a signal to probe the nodes on the bus. This
-	 * happens when we get a bus reset.  */
-	do {
-		interruptible_sleep_on(&hi->wait);
-		if (!signal_pending(current))
-			nodemgr_node_probe(hi->host);
-	} while (!signal_pending(current));
+	 * happens when we get a bus reset. */
+	while (!down_interruptible(&hi->reset_sem))
+		nodemgr_node_probe(hi->host);
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 	HPSB_DEBUG ("NodeMgr: Exiting thread for %s", hi->host->driver->name);
 #endif
 
-	unlock_kernel();
-
 	complete_and_exit(&hi->exited, 0);
 }
 
@@ -1140,23 +1187,57 @@
 	return ne;
 }
 
-struct hpsb_host *hpsb_get_host_by_ne(struct node_entry *ne)
+/* The following four convenience functions use a struct node_entry
+ * for addressing a node on the bus.  They are intended for use by any
+ * process context, not just the nodemgr thread, so we need to be a
+ * little careful when reading out the node ID and generation.  The
+ * thing that can go wrong is that we get the node ID, then a bus
+ * reset occurs, and then we read the generation.  The node ID is
+ * possibly invalid, but the generation is current, and we end up
+ * sending a packet to a the wrong node.
+ *
+ * The solution is to make sure we read the generation first, so that
+ * if a reset occurs in the process, we end up with a stale generation
+ * and the transactions will fail instead of silently using wrong node
+ * ID's.
+ */
+
+void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
 {
-        if (atomic_read(&ne->generation) != get_hpsb_generation(ne->host))
-		return NULL;
-        if (ne->nodeid == ne->host->node_id) return ne->host;
-        return NULL;
+        pkt->host = ne->host;
+        pkt->generation = ne->generation;
+	barrier();
+        pkt->node_id = ne->nodeid;
 }
 
-int hpsb_guid_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
+int hpsb_node_read(struct node_entry *ne, u64 addr,
+		   quadlet_t *buffer, size_t length)
 {
-        if (atomic_read(&ne->generation) != get_hpsb_generation(ne->host))
-		return 0;
+	unsigned int generation = ne->generation;
 
-        pkt->host = ne->host;
-        pkt->node_id = ne->nodeid;
-        pkt->generation = atomic_read(&ne->generation);
-        return 1;
+	barrier();
+	return hpsb_read(ne->host, ne->nodeid, generation,
+			 addr, buffer, length);
+}
+
+int hpsb_node_write(struct node_entry *ne, u64 addr, 
+		    quadlet_t *buffer, size_t length)
+{
+	unsigned int generation = ne->generation;
+
+	barrier();
+	return hpsb_write(ne->host, ne->nodeid, generation,
+			  addr, buffer, length);
+}
+
+int hpsb_node_lock(struct node_entry *ne, u64 addr, 
+		   int extcode, quadlet_t *data, quadlet_t arg)
+{
+	unsigned int generation = ne->generation;
+
+	barrier();
+	return hpsb_lock(ne->host, ne->nodeid, generation,
+			 addr, extcode, data, arg);
 }
 
 static void nodemgr_add_host(struct hpsb_host *host)
@@ -1169,23 +1250,24 @@
 		return;
 	}
 
-	/* We simply initialize the struct here. We don't start the thread
-	 * until the first bus reset.  */
+	/* Initialize the hostinfo here and start the thread.  The
+	 * thread blocks on the reset semaphore until a bus reset
+	 * happens. */
 	hi->host = host;
 	INIT_LIST_HEAD(&hi->list);
-	init_completion(&hi->started);
 	init_completion(&hi->exited);
-	init_waitqueue_head(&hi->wait);
-
-	hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+        sema_init(&hi->reset_sem, 0);
 
+	hi->pid = kernel_thread(nodemgr_host_thread, hi,
+				CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+	
 	if (hi->pid < 0) {
-		HPSB_ERR ("NodeMgr: failed to start NodeMgr thread for %s", host->driver->name);
+		HPSB_ERR ("NodeMgr: failed to start NodeMgr thread for %s",
+			  host->driver->name);
+		kfree(hi);
 		return;
 	}
 
-	wait_for_completion(&hi->started);
-
 	spin_lock_irqsave (&host_info_lock, flags);
 	list_add_tail (&hi->list, &host_info_list);
 	spin_unlock_irqrestore (&host_info_lock, flags);
@@ -1216,8 +1298,7 @@
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 	HPSB_DEBUG ("NodeMgr: Processing host reset for %s", host->driver->name);
 #endif
-
-	wake_up(&hi->wait);
+	up(&hi->reset_sem);
 
 done_reset_host:
 	spin_unlock_irqrestore (&host_info_lock, flags);
@@ -1254,7 +1335,7 @@
 		ne = list_entry(lh, struct node_entry, list);
 
 		if (ne->host == host)
-		nodemgr_remove_node(ne);
+			nodemgr_remove_node(ne);
 	}
 	write_unlock_irqrestore(&node_lock, flags);
 
@@ -1279,8 +1360,9 @@
 
 #define PROC_ENTRY "devices"
 
-void init_ieee1394_nodemgr(void)
+void init_ieee1394_nodemgr(int disable_hotplug)
 {
+	nodemgr_disable_hotplug = disable_hotplug;
 #ifdef CONFIG_PROC_FS
 	if (!create_proc_read_entry(PROC_ENTRY, 0444, ieee1394_procfs_entry, raw1394_read_proc, NULL))
 		HPSB_ERR("Can't create devices procfs entry");
diff -Nru a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
--- a/drivers/ieee1394/nodemgr.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/ieee1394/nodemgr.h	Sun Apr 14 12:16:54 2002
@@ -125,7 +125,7 @@
 	struct hpsb_host *host;		/* Host this node is attached to */
 	nodeid_t nodeid;		/* NodeID */
 	struct bus_options busopt;	/* Bus Options */
-	atomic_t generation;		/* Synced with hpsb generation */
+	unsigned int generation;	/* Synced with hpsb generation */
 
 	/* The following is read from the config rom */
 	u32 vendor_id;
@@ -138,7 +138,7 @@
 
 static inline int hpsb_node_entry_valid(struct node_entry *ne)
 {
-	return atomic_read(&ne->generation) == get_hpsb_generation(ne->host);
+	return ne->generation == get_hpsb_generation(ne->host);
 }
 
 /*
@@ -170,10 +170,17 @@
  * number).  It will at least reliably fail so that you don't accidentally and
  * unknowingly send your packet to the wrong node.
  */
-int hpsb_guid_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt);
+void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt);
 
+int hpsb_node_read(struct node_entry *ne, u64 addr,
+		   quadlet_t *buffer, size_t length);
+int hpsb_node_write(struct node_entry *ne, u64 addr, 
+		    quadlet_t *buffer, size_t length);
+int hpsb_node_lock(struct node_entry *ne, u64 addr, 
+		   int extcode, quadlet_t *data, quadlet_t arg);
 
-void init_ieee1394_nodemgr(void);
+
+void init_ieee1394_nodemgr(int disable_hotplug);
 void cleanup_ieee1394_nodemgr(void);
 
 #endif /* _IEEE1394_NODEMGR_H */
diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
--- a/drivers/ieee1394/ohci1394.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ieee1394/ohci1394.c	Sun Apr 14 12:16:57 2002
@@ -96,7 +96,6 @@
 #include <linux/poll.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/tqueue.h>
 #include <linux/delay.h>
@@ -161,7 +160,7 @@
 printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-	"$Revision: 1.91 $ Ben Collins <bcollins@debian.org>";
+	"$Revision: 1.101 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 MODULE_PARM(attempt_root,"i");
@@ -487,7 +486,6 @@
 /* Global initialization */
 static void ohci_initialize(struct ti_ohci *ohci)
 {
-	int i;
 	quadlet_t buf;
 
 	spin_lock_init(&ohci->phy_reg_lock);
@@ -535,14 +533,6 @@
 	/* Don't accept phy packets into AR request context */ 
 	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
 
-	/* Initialize IR dma */
-	for (i=0;i<ohci->nb_iso_rcv_ctx;i++) {
-		reg_write(ohci, OHCI1394_IsoRcvContextControlClear+32*i,
-			  0xffffffff);
-		reg_write(ohci, OHCI1394_IsoRcvContextMatch+32*i, 0);
-		reg_write(ohci, OHCI1394_IsoRcvCommandPtr+32*i, 0);
-	}
-
 	/* Set bufferFill, isochHeader, multichannel for IR context */
 	reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000);
 			
@@ -553,13 +543,6 @@
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
 	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
 
-	/* Initialize IT dma */
-	for (i=0;i<ohci->nb_iso_xmit_ctx;i++) {
-		reg_write(ohci, OHCI1394_IsoXmitContextControlClear+32*i,
-			  0xffffffff);
-		reg_write(ohci, OHCI1394_IsoXmitCommandPtr+32*i, 0);
-	}
-	
 	/* Clear the interrupt mask */
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
 	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
@@ -615,7 +598,8 @@
 		  OHCI1394_respTxComplete |
 		  OHCI1394_reqTxComplete |
 		  OHCI1394_isochRx |
-		  OHCI1394_isochTx);
+		  OHCI1394_isochTx |
+		  OHCI1394_cycleInconsistent);
 
 	/* Enable link */
 	reg_write(ohci, OHCI1394_HCControlSet, 0x00020000);
@@ -936,6 +920,7 @@
                 } else {
                         MOD_DEC_USE_COUNT;
                 }
+		retval = 1;
                 break;
 
 	case ISO_LISTEN_CHANNEL:
@@ -1098,6 +1083,14 @@
 		return;
 	}
 
+	if (event & OHCI1394_cycleInconsistent) {
+		/* We subscribe to the cycleInconsistent event only to
+		 * clear the corresponding event bit... otherwise,
+		 * isochronous cycleMatch DMA wont work. */
+		DBGMSG(ohci->id, "OHCI1394_cycleInconsistent");
+		event &= ~OHCI1394_cycleInconsistent;
+	}
+
 	if (event & OHCI1394_busReset) {
 		/* The busReset event bit can't be cleared during the
 		 * selfID phase, so we disable busReset interrupts, to
@@ -1265,8 +1258,8 @@
 		/* Finally, we clear the busReset event and reenable
 		 * the busReset interrupt. */
 		spin_lock_irqsave(&ohci->event_lock, flags);
-		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); 
 		reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); 
 		spin_unlock_irqrestore(&ohci->event_lock, flags);
 		event &= ~OHCI1394_selfIDComplete;	
 	}
@@ -1509,6 +1502,15 @@
 			/* this packet hasn't been sent yet*/
 			break;
 
+		if (!(ack & 0x10)) {
+			/* XXX: This is an OHCI evt_* code. We need to handle
+			 * this specially! For right now, we just fake an
+			 * ackx_send_error. */
+			PRINT(KERN_DEBUG, ohci->id, "Received OHCI evt_* error 0x%x",
+			       ack & 0xf);
+			ack = (ack & 0xffe0) | ACK_BUSY_A;
+		}
+
 #ifdef OHCI1394_DEBUG
 		if (datasize)
 			DBGMSG(ohci->id,
@@ -1942,7 +1944,8 @@
 
 	/* Root directory */
 	cf_unit_begin(&cr, 1);
-	cf_put_keyval(&cr, 0x03, 0x00005e);	/* Vendor ID */
+	/* Vendor ID */
+	cf_put_keyval(&cr, 0x03, reg_read(ohci,OHCI1394_VendorID) & 0xFFFFFF);
 	cf_put_refer(&cr, 0x81, 2);		/* Textual description unit */
 	cf_put_keyval(&cr, 0x0c, 0x0083c0);	/* Node capabilities */
 	/* NOTE: Add other unit referers here, and append at bottom */
@@ -2287,7 +2290,7 @@
 #endif /* CONFIG_ALL_PPC */
 
 	pci_set_drvdata(ohci->dev, NULL);
-	kfree(ohci);
+	hpsb_unref_host(ohci->host);
 }
 
 #define PCI_CLASS_FIREWIRE_OHCI     ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10)
diff -Nru a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
--- a/drivers/ieee1394/ohci1394.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/ieee1394/ohci1394.h	Sun Apr 14 12:16:55 2002
@@ -22,6 +22,7 @@
 #define _OHCI1394_H
 
 #include "ieee1394_types.h"
+#include <asm/io.h>
 
 #define OHCI1394_DRIVER_NAME      "ohci1394"
 
@@ -192,7 +193,7 @@
 
 	/* IRQ hooks, for video1394 and dv1394 */
 	
-#define OHCI1394_MAX_IRQ_HOOKS 4
+#define OHCI1394_MAX_IRQ_HOOKS 16
 	
 	struct ohci1394_irq_hook {
 		void (*irq_handler) (int card, quadlet_t isoRecvEvent, 
@@ -314,7 +315,7 @@
 #define OHCI1394_AsRspRcvCommandPtr           0x1EC
 
 /* Isochronous transmit registers */
-/* Add (32 * n) for context n */
+/* Add (16 * n) for context n */
 #define OHCI1394_IsoXmitContextBase           0x200
 #define OHCI1394_IsoXmitContextControlSet     0x200
 #define OHCI1394_IsoXmitContextControlClear   0x204
@@ -362,6 +363,28 @@
 #define DMA_CTL_IRQ                      0x00300000
 #define DMA_CTL_BRANCH                   0x000c0000
 #define DMA_CTL_WAIT                     0x00030000
+
+/* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */
+#define EVT_NO_STATUS		0x0	/* No event status */
+#define EVT_RESERVED		0x1	/* Reserved, not used !!! */
+#define EVT_LONG_PACKET		0x2	/* The revc data was longer than the buf */
+#define EVT_MISSING_ACK		0x3	/* A subaction gap was detected before an ack
+					   arrived, or recv'd ack had a parity error */
+#define EVT_UNDERRUN		0x4	/* Underrun on corresponding FIFO, packet
+					   truncated */
+#define EVT_OVERRUN		0x5	/* A recv FIFO overflowed on reception of ISO
+					   packet */
+#define EVT_DESCRIPTOR_READ	0x6	/* An unrecoverable error occured while host was
+					   reading a descriptor block */
+#define EVT_DATA_READ		0x7	/* An error occured while host controller was
+					   attempting to read from host memory in the data
+					   stage of descriptor processing */
+#define EVT_DATA_WRITE		0x8	/* An error occured while host controller was
+					   attempting to write either during the data stage
+					   of descriptor processing, or when processing a single
+					   16-bit host memory write */
+#define EVT_BUS_RESET		0x9	/* Identifies a PHY packet in the recv buffer as
+					   being a synthesized bus reset packet */
 
 #define OHCI1394_TCODE_PHY               0xE
 
diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
--- a/drivers/ieee1394/pcilynx.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/ieee1394/pcilynx.c	Sun Apr 14 12:16:57 2002
@@ -29,7 +29,6 @@
 #include <linux/pci.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -615,7 +614,7 @@
 
 
 static struct file_operations aux_ops = {
-        OWNER_THIS_MODULE
+	owner:		THIS_MODULE,
         read:           mem_read,
         write:          mem_write,
         poll:           aux_poll,
@@ -636,46 +635,35 @@
 
 static int mem_open(struct inode *inode, struct file *file)
 {
-        int cid = MINOR(inode->i_rdev);
+        int cid = minor(inode->i_rdev);
         enum { t_rom, t_aux, t_ram } type;
         struct memdata *md;
         
-        V22_COMPAT_MOD_INC_USE_COUNT;
-
         if (cid < PCILYNX_MINOR_AUX_START) {
                 /* just for completeness */
-                V22_COMPAT_MOD_DEC_USE_COUNT;
                 return -ENXIO;
         } else if (cid < PCILYNX_MINOR_ROM_START) {
                 cid -= PCILYNX_MINOR_AUX_START;
-                if (cid >= num_of_cards || !cards[cid].aux_port) {
-                        V22_COMPAT_MOD_DEC_USE_COUNT;
+                if (cid >= num_of_cards || !cards[cid].aux_port)
                         return -ENXIO;
-                }
                 type = t_aux;
         } else if (cid < PCILYNX_MINOR_RAM_START) {
                 cid -= PCILYNX_MINOR_ROM_START;
-                if (cid >= num_of_cards || !cards[cid].local_rom) {
-                        V22_COMPAT_MOD_DEC_USE_COUNT;
+                if (cid >= num_of_cards || !cards[cid].local_rom)
                         return -ENXIO;
-                }
                 type = t_rom;
         } else {
                 /* WARNING: Know what you are doing when opening RAM.
                  * It is currently used inside the driver! */
                 cid -= PCILYNX_MINOR_RAM_START;
-                if (cid >= num_of_cards || !cards[cid].local_ram) {
-                        V22_COMPAT_MOD_DEC_USE_COUNT;
+                if (cid >= num_of_cards || !cards[cid].local_ram)
                         return -ENXIO;
-                }
                 type = t_ram;
         }
 
         md = (struct memdata *)kmalloc(sizeof(struct memdata), SLAB_KERNEL);
-        if (md == NULL) {
-                V22_COMPAT_MOD_DEC_USE_COUNT;
+        if (md == NULL)
                 return -ENOMEM;
-        }
 
         md->lynx = &cards[cid];
         md->cid = cid;
@@ -701,11 +689,7 @@
 
 static int mem_release(struct inode *inode, struct file *file)
 {
-        struct memdata *md = (struct memdata *)file->private_data;
-
-        kfree(md);
-
-        V22_COMPAT_MOD_DEC_USE_COUNT;
+        kfree(file->private_data);
         return 0;
 }
 
@@ -733,9 +717,8 @@
 
 loff_t mem_llseek(struct file *file, loff_t offs, int orig)
 {
-        loff_t newoffs = -1;
+        loff_t newoffs;
 
-        lock_kernel();
         switch (orig) {
         case 0:
                 newoffs = offs;
@@ -745,14 +728,13 @@
                 break;
         case 2:
                 newoffs = PCILYNX_MAX_MEMORY + 1 + offs;
-        }
-
-        if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) {
-                unlock_kernel();
+                break;
+        default:
                 return -EINVAL;
         }
 
-        unlock_kernel();
+        if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) return -EINVAL;
+
         file->f_pos = newoffs;
         return newoffs;
 }
@@ -1230,7 +1212,7 @@
         }
 
 	tasklet_kill(&lynx->iso_rcv.tq);
-        kfree(lynx);
+	hpsb_unref_host(lynx->host);
 }
 
 
diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
--- a/drivers/ieee1394/raw1394.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/ieee1394/raw1394.c	Sun Apr 14 12:16:54 2002
@@ -21,10 +21,7 @@
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
 #include <linux/devfs_fs_kernel.h>
-#endif
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
@@ -919,13 +916,9 @@
                 return -ENXIO;
         }
 
-        V22_COMPAT_MOD_INC_USE_COUNT;
-
         fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
-        if (fi == NULL) {
-                V22_COMPAT_MOD_DEC_USE_COUNT;
+        if (fi == NULL)
                 return -ENOMEM;
-        }
         
         memset(fi, 0, sizeof(struct file_info));
 
@@ -988,7 +981,6 @@
 
         kfree(fi);
 
-        V22_COMPAT_MOD_DEC_USE_COUNT;
         return 0;
 }
 
@@ -1001,12 +993,12 @@
 };
 
 static struct file_operations file_ops = {
-        OWNER_THIS_MODULE
-        read:     raw1394_read, 
-        write:    raw1394_write, 
-        poll:     raw1394_poll, 
-        open:     raw1394_open, 
-        release:  raw1394_release, 
+	owner:		THIS_MODULE,
+        read:		raw1394_read, 
+        write:		raw1394_write, 
+        poll:		raw1394_poll, 
+        open:		raw1394_open, 
+        release:	raw1394_release, 
 };
 
 static int __init init_raw1394(void)
diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
--- a/drivers/ieee1394/sbp2.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/ieee1394/sbp2.c	Sun Apr 14 12:16:55 2002
@@ -27,6 +27,7 @@
  * driver. It also registers as a SCSI lower-level driver in order to accept
  * SCSI commands for transport using SBP-2.
  *
+ *
  * Driver Loading:
  *
  * Currently, the SBP-2 driver is supported only as a module. Because the 
@@ -45,7 +46,7 @@
  *
  * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the
  * initial scsi bus scan (when the driver is first loaded). To add or remove
- * SBP-2 devices after this initial scan (i.e. if you plug-in or un-plug a 
+ * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a 
  * device after the SBP-2 driver is loaded), you must either use the scsi procfs
  * add-single-device, remove-single-device, or a shell script such as 
  * rescan-scsi-bus.sh.
@@ -76,6 +77,19 @@
  * fdisk, mkfs, etc.).
  *
  *
+ * Module Load Options:
+ *
+ * sbp2_max_speed 		- Force max speed allowed 
+ *				  (2 = 400mb, 1 = 200mb, 0 = 100mb. default = 2)
+ * sbp2_serialize_io		- Serialize all I/O coming down from the scsi drivers 
+ *				  (0 = deserialized, 1 = serialized, default = 0)
+ * sbp2_max_sectors, 		- Change max sectors per I/O supported (default = 255)
+ * sbp2_max_outstanding_cmds	- Change max outstanding concurrent commands (default = 8)
+ * sbp2_max_cmds_per_lun	- Change max concurrent commands per sbp2 device (default = 1)
+ *
+ * (e.g. insmod sbp2 sbp2_serialize_io = 1)
+ *
+ *
  * Current Support:
  *
  * The SBP-2 driver is still in an early state, but supports a variety of devices.
@@ -83,7 +97,8 @@
  * performance of more than 25 MBytes/s on individual drives (limit of the media 
  * transfer rate).
  *
- * Following are the devices that have been tested successfully:
+ *
+ * Following are a sampling of devices that have been tested successfully:
  *
  *	- Western Digital IEEE-1394 hard drives
  *	- Maxtor IEEE-1394 hard drives
@@ -102,7 +117,7 @@
  *	- APDrives IEEE-1394 hard drives
  *	- Fujitsu IEEE-1394 MO drives
  *	- Sony IEEE-1394 CD-RW drives
- *	- Epson IEEE-1394 scanner
+ *	- Epson IEEE-1394 scanners
  *	- ADS IEEE-1394 memory stick and compact flash readers 
  *	- SBP-2 bridge-based devices (LSI, Oxford Semiconductor, Indigita bridges)
  *	- Various other standard IEEE-1394 hard drives and enclosures
@@ -117,10 +132,6 @@
  *
  * Current Issues:
  *
- *	- Currently, all I/O from the scsi stack is serialized by default, as there
- *	  are some stress issues under investigation with deserialized I/O. To enable
- *	  deserialized I/O for testing, do "insmod sbp2 serialize_io=0"
- *
  *	- Error Handling: SCSI aborts and bus reset requests are handled somewhat
  *	  but the code needs additional debugging.
  *
@@ -246,6 +257,28 @@
  *		   1394 devices (Peerless, Jazz). Also a bit of clean-up of the 
  *		   driver, thanks to H.J.Lu (hjl@lucon.org). Removed mode_sense_hack
  *		   module load option, as it's been fixed in the 2.4 scsi stack.
+ *	02/10/02 - Added support for max_sectors, minor fix for inquiry command, make
+ *		   up sbp2 device type from inquiry response data if not part of 
+ *		   device's 1394 unit directory. (JSG)
+ *	02/18/02 - Code clean-up and enhancements: (JSG)
+ *		   * Finish cleaning out hacked code for dealing with broken sbp2 devices
+ *		     which do not support requests of 128KB or greater. Now use 
+ *		     max_sectors scsi host entry to limit transfer sizes.
+ *		   * Change status fifo address from a single address to a set of addresses,
+ *		     with each sbp2 device having it's own status fifo address. This makes
+ *		     it easier to match the status write to the sbp2 device instance.
+ *		   * Minor change to use lun when logging into sbp2 devices. First step in
+ *		     supporting multi-lun devices such as CD/DVD changer devices.
+ *		   * Added a new module load option for setting max sectors. For use by folk
+ *		     who'd like to bump up the max scsi transfer size supported.
+ *		   * Enabled deserialized operation by default, allowing for better performance,
+ *		     particularily when running with multiple sbp2 devices. For debugging,
+ *		     you may enable serialization through use of the sbp2_serialize_io module
+ *		     load option (e.g. insmod sbp2 sbp2_serialize_io=1).
+ *	02/20/02 - Added a couple additional module load options. 
+ *		   Needed to bump down max commands per lun because of the !%@&*^# QPS CDRW 
+ *		   drive I have, which doesn't seem to get along with other sbp2 devices 
+ *		   (or handle linked commands well).  
  */
 
 
@@ -301,7 +334,7 @@
  */
 
 /*
- * Change max_speed on module load if you have a bad IEEE-1394 controller
+ * Change sbp2_max_speed on module load if you have a bad IEEE-1394 controller
  * that has trouble running 2KB packets at 400mb.
  *
  * NOTE: On certain OHCI parts I have seen short packets on async transmit
@@ -309,31 +342,51 @@
  * bump down the speed if you are running into problems.
  *
  * Valid values:
- * max_speed = 2 (default: max speed 400mb)
- * max_speed = 1 (max speed 200mb)
- * max_speed = 0 (max speed 100mb)
+ * sbp2_max_speed = 2 (default: max speed 400mb)
+ * sbp2_max_speed = 1 (max speed 200mb)
+ * sbp2_max_speed = 0 (max speed 100mb)
  */
-MODULE_PARM(max_speed,"i");
-MODULE_PARM_DESC(max_speed, "Force down max speed (2 = 400mb default, 1 = 200mb, 0 = 100mb)");
-static int max_speed = SPEED_400;
+MODULE_PARM(sbp2_max_speed,"i");
+MODULE_PARM_DESC(sbp2_max_speed, "Force max speed (2 = 400mb default, 1 = 200mb, 0 = 100mb)");
+static int sbp2_max_speed = SPEED_400;
 
 /*
- * Set serialize_io to 1 if you'd like only one scsi command sent down to
- * us at a time (debugging).
+ * Set sbp2_serialize_io to 1 if you'd like only one scsi command sent down to
+ * us at a time (debugging). This might be necessary for very badly behaved sbp2 devices.
  */
-MODULE_PARM(serialize_io,"i");
-MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (debugging)");
-static int serialize_io = 1;	/* serialize I/O until stress issues are resolved */
+MODULE_PARM(sbp2_serialize_io,"i");
+MODULE_PARM_DESC(sbp2_serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)");
+static int sbp2_serialize_io = 0;	/* serialize I/O - available for debugging purposes */
 
 /*
- * Set no_large_packets to 1 if you'd like to limit the size of requests
- * sent down to us (normally the sbp2 driver will break up any requests to
- * any individual devices with 128KB transfer size limits).  Sets max s/g
- * list elements to 0x1f in size and disables s/g clustering.
+ * Bump up sbp2_max_sectors if you'd like to support very large sized transfers. Please note 
+ * that some older sbp2 bridge chips are broken for transfers greater or equal to 128KB.
+ * Default is a value of 255 sectors, or just under 128KB (at 512 byte sector size). I can note
+ * that the Oxsemi sbp2 chipsets have no problems supporting very large transfer sizes.
  */
-MODULE_PARM(no_large_packets,"i");
-MODULE_PARM_DESC(no_large_packets, "Do not allow large transfers from scsi drivers (debugging)");
-static int no_large_packets = 0;
+MODULE_PARM(sbp2_max_sectors,"i");
+MODULE_PARM_DESC(sbp2_max_sectors, "Change max sectors per I/O supported (default = 255)");
+static int sbp2_max_sectors = SBP2_MAX_SECTORS;
+
+/*
+ * Adjust sbp2_max_outstanding_cmds to tune performance if you have many sbp2 devices attached
+ * (or if you need to do some debugging).
+ */
+MODULE_PARM(sbp2_max_outstanding_cmds,"i");
+MODULE_PARM_DESC(sbp2_max_outstanding_cmds, "Change max outstanding concurrent commands (default = 8)");
+static int sbp2_max_outstanding_cmds = SBP2SCSI_MAX_OUTSTANDING_CMDS;
+
+/*
+ * Adjust sbp2_max_cmds_per_lun to tune performance. Enabling more than one concurrent/linked 
+ * command per sbp2 device may allow some performance gains, but some older sbp2 devices have 
+ * firmware bugs resulting in problems when linking commands... so, enable this with care. 
+ * I can note that the Oxsemi OXFW911 sbp2 chipset works very well with large numbers of 
+ * concurrent/linked commands.  =)
+ */
+MODULE_PARM(sbp2_max_cmds_per_lun,"i");
+MODULE_PARM_DESC(sbp2_max_cmds_per_lun, "Change max concurrent commands per sbp2 device (default = 1)");
+static int sbp2_max_cmds_per_lun = SBP2SCSI_MAX_CMDS_PER_LUN;
+
 
 /*
  * Export information about protocols/devices supported by this driver.
@@ -351,9 +404,14 @@
 MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
 
 /*
- * Debug levels, configured via kernel config.
+ * Debug levels, configured via kernel config, or enable here.
  */
 
+/* #define CONFIG_IEEE1394_SBP2_DEBUG_ORBS */
+/* #define CONFIG_IEEE1394_SBP2_DEBUG_DMA */
+/* #define CONFIG_IEEE1394_SBP2_DEBUG 1 */
+/* #define CONFIG_IEEE1394_SBP2_DEBUG 2 */
+
 #ifdef CONFIG_IEEE1394_SBP2_DEBUG_ORBS
 #define SBP2_ORB_DEBUG(fmt, args...)	HPSB_ERR("sbp2(%s): "fmt, __FUNCTION__, ## args)
 static u32 global_outstanding_command_orbs = 0;
@@ -390,9 +448,9 @@
 #define SBP2_WARN(fmt, args...)		HPSB_WARN("sbp2: "fmt, ## args)
 #else 
 #define SBP2_DEBUG(fmt, args...)
-#define SBP2_INFO(fmt, args...)
-#define SBP2_NOTICE(fmt, args...)
-#define SBP2_WARN(fmt, args...)
+#define SBP2_INFO(fmt, args...)		HPSB_INFO("sbp2: "fmt, ## args)
+#define SBP2_NOTICE(fmt, args...)       HPSB_NOTICE("sbp2: "fmt, ## args)
+#define SBP2_WARN(fmt, args...)         HPSB_WARN("sbp2: "fmt, ## args)
 #endif
 
 #define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)
@@ -490,7 +548,19 @@
 	struct hpsb_packet *packet;
 	int i;
 
-	/* Create SBP2_MAX_REQUEST_PACKETS number of request packets. */
+	hi->request_packet = kmalloc(sizeof(struct sbp2_request_packet) * SBP2_MAX_REQUEST_PACKETS, 
+				     GFP_KERNEL);
+
+	if (!hi->request_packet) {
+		SBP2_ERR("sbp2util_create_request_packet_pool - packet allocation failed!");
+		return(-ENOMEM);
+	}
+	memset(hi->request_packet, 0, sizeof(struct sbp2_request_packet) * SBP2_MAX_REQUEST_PACKETS);
+
+	/* 
+	 * Create a pool of request packets. Just take the max supported 
+	 * concurrent commands and multiply by two to be safe... 
+	 */
 	for (i=0; i<SBP2_MAX_REQUEST_PACKETS; i++) {
 
 		/*
@@ -547,6 +617,7 @@
 		}
 
 	}
+	kfree(hi->request_packet);
 	sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);
 
 	return;
@@ -561,7 +632,7 @@
  */
 static struct sbp2_request_packet *
 sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
-				       nodeid_t node, u64 addr,
+				       struct node_entry *ne, u64 addr,
 				       size_t data_size,
 				       quadlet_t data) {
 	struct list_head *lh;
@@ -590,12 +661,11 @@
 		INIT_LIST_HEAD(&packet->list);
 		sema_init(&packet->state_change, 0);
 		packet->state = hpsb_unused;
-		packet->generation = get_hpsb_generation(hi->host);
 		packet->data_be = 1;
+		
+		hpsb_node_fill_packet(ne, packet);
 
-		packet->host = hi->host;
-		packet->tlabel = get_tlabel(hi->host, node, 1);
-		packet->node_id = node;
+		packet->tlabel = get_tlabel(hi->host, packet->node_id, 1);
 
 		if (!data_size) {
 			fill_async_writequad(packet, addr, data);
@@ -717,8 +787,8 @@
 }
 
 /* 
- * This functions finds the sbp2_command for a given outstanding command
- * orb. Only looks at the inuse list.
+ * This function finds the sbp2_command for a given outstanding command
+ * orb.Only looks at the inuse list.
  */
 static struct sbp2_command_info *sbp2util_find_command_for_orb(
 		struct scsi_id_instance_data *scsi_id, dma_addr_t orb)
@@ -745,7 +815,7 @@
 }
 
 /* 
- * This functions finds the sbp2_command for a given outstanding SCpnt.
+ * This function finds the sbp2_command for a given outstanding SCpnt.
  * Only looks at the inuse list.
  */
 static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt)
@@ -788,7 +858,6 @@
 		command = list_entry(lh, struct sbp2_command_info, list);
 		command->Current_done = Current_done;
 		command->Current_SCpnt = Current_SCpnt;
-		command->linked = 0;
 		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse);
 	} else {
 		SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
@@ -878,7 +947,8 @@
 	 * Register our sbp2 status address space...
 	 */
 	hpsb_register_addrspace(sbp2_hl_handle, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,
-				SBP2_STATUS_FIFO_ADDRESS + sizeof(struct sbp2_status_block));
+				SBP2_STATUS_FIFO_ADDRESS + 
+				SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));
 
 	hpsb_register_protocol(&sbp2_driver);
 
@@ -936,7 +1006,8 @@
 
 	if (sbp2_reconnect_device(hi, scsi_id)) {
 		
-		/* Ok, reconnect has failed.  Perhaps we didn't
+		/* 
+		 * Ok, reconnect has failed. Perhaps we didn't
 		 * reconnect fast enough. Try doing a regular login.
 		 */
 		if (sbp2_login_device(hi, scsi_id)) {
@@ -1008,8 +1079,10 @@
 
 	/* Register our host with the SCSI stack. */
 	hi->scsi_host = scsi_register (&scsi_driver_template, sizeof(void *));
-	if (hi->scsi_host)
+	if (hi->scsi_host) {
 		hi->scsi_host->hostdata[0] = (unsigned long)hi;
+		hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS;
+	}
 	scsi_driver_template.present++;
 
 	return;
@@ -1190,19 +1263,11 @@
 	/* 
 	 * Knock the total command orbs down if we are serializing I/O
 	 */
-	if (serialize_io) {
+	if (sbp2_serialize_io) {
 		scsi_id->sbp2_total_command_orbs = 2;	/* one extra for good measure */
 	}
 
 	/*
-	 * Allocate some extra command orb structures for devices with
-	 * 128KB limit.
-	 */
-	if (scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) {
-		scsi_id->sbp2_total_command_orbs *= 4;
-	} 
-
-	/*
 	 * Find an empty spot to stick our scsi id instance data. 
 	 */
 	for (i = 0; i < SBP2SCSI_MAX_SCSI_IDS; i++) {
@@ -1348,14 +1413,19 @@
 	scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(LOGIN_REQUEST);
 	scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);	/* One second reconnect time */
 	scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(1);	/* Exclusive access to device */
-	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);		/* Notify us of login complete */
+	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);	/* Notify us of login complete */
+	/* Set the lun if we were able to pull it from the device's unit directory */
+	if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
+		scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+	}
 	SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
 
 	scsi_id->login_orb->passwd_resp_lengths =
 		ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
 	SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized");
 
-	scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
+	scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 
+					     SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
 	scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
 					      SBP2_STATUS_FIFO_ADDRESS_HI);
 	SBP2_DEBUG("sbp2_login_device: status FIFO initialized");
@@ -1383,7 +1453,7 @@
 	sbp2util_cpu_to_be32_buffer(data, 8);
 
 	SBP2_DEBUG("sbp2_login_device: prepared to write");
-	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
+	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 	SBP2_DEBUG("sbp2_login_device: written");
 
 	/*
@@ -1472,7 +1542,8 @@
 	scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
 
 	scsi_id->logout_orb->reserved5 = 0x0;
-	scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
+	scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 
+					      SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
 	scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) |
 					       SBP2_STATUS_FIFO_ADDRESS_HI);
 
@@ -1488,7 +1559,7 @@
 	data[1] = scsi_id->logout_orb_dma;
 	sbp2util_cpu_to_be32_buffer(data, 8);
 
-	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
+	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 
 	/* Wait for device to logout...1 second. */
 	sleep_on_timeout(&scsi_id->sbp2_login_wait, HZ);
@@ -1526,7 +1597,8 @@
 	scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
 
 	scsi_id->reconnect_orb->reserved5 = 0x0;
-	scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO;
+	scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + 
+						 SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id);
 	scsi_id->reconnect_orb->status_FIFO_hi =
 		(ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI);
 
@@ -1547,7 +1619,7 @@
 	data[1] = scsi_id->reconnect_orb_dma;
 	sbp2util_cpu_to_be32_buffer(data, 8);
 
-	hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, scsi_id->sbp2_management_agent_addr, data, 8);
+	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8);
 
 	/*
 	 * Wait for reconnect status... but, only if the device has not
@@ -1601,7 +1673,7 @@
 	 */
 	data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
 
-	if (hpsb_write(hi->host, LOCAL_BUS | scsi_id->ne->nodeid, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
+	if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) {
 		SBP2_ERR("sbp2_set_busy_timeout error");
 	}
 
@@ -1620,6 +1692,14 @@
 
 	SBP2_DEBUG("sbp2_parse_unit_directory");
 
+	/* Initialize some fields, in case an entry does not exist */
+	scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
+	scsi_id->sbp2_management_agent_addr = 0x0;
+	scsi_id->sbp2_command_set_spec_id = 0x0;
+	scsi_id->sbp2_command_set = 0x0;
+	scsi_id->sbp2_unit_characteristics = 0x0;
+	scsi_id->sbp2_firmware_revision = 0x0;
+
 	ud = scsi_id->ud;
 
 	/* Handle different fields in the unit directory, based on keys */
@@ -1683,7 +1763,9 @@
 			 */
 			scsi_id->sbp2_firmware_revision
 				= CONFIG_ROM_VALUE(ud->quadlets[i]);
-			if (scsi_id->sbp2_firmware_revision ==
+			SBP2_DEBUG("sbp2_firmware_revision = %x",
+				   (unsigned int) scsi_id->sbp2_firmware_revision);
+			if ((scsi_id->sbp2_firmware_revision & 0xffff00) ==
 			    SBP2_128KB_BROKEN_FIRMWARE) {
 				SBP2_WARN("warning: Bridge chipset supports 128KB max transfer size");
 			}
@@ -1713,8 +1795,8 @@
 						  + (scsi_id->ne->nodeid & NODE_MASK)];
 
 	/* Bump down our speed if the user requested it */
-	if (scsi_id->speed_code > max_speed) {
-		scsi_id->speed_code = max_speed;
+	if (scsi_id->speed_code > sbp2_max_speed) {
+		scsi_id->speed_code = sbp2_max_speed;
 		SBP2_ERR("Forcing SBP-2 max speed down to %s",
 			 hpsb_speedto_str[scsi_id->speed_code]);
 	}
@@ -1744,7 +1826,7 @@
 	 * Ok, let's write to the target's management agent register
 	 */
 	agent_reset_request_packet =
-		sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->ne->nodeid,
+		sbp2util_allocate_write_request_packet(hi, scsi_id->ne,
 						       scsi_id->sbp2_command_block_agent_addr +
 						       SBP2_AGENT_RESET_OFFSET,
 						       0, ntohl(SBP2_AGENT_RESET_DATA));
@@ -2034,8 +2116,8 @@
 	struct sbp2_command_orb *command_orb = &command->command_orb;
 
 	outstanding_orb_incr;
-	SBP2_ORB_DEBUG("sending command orb %p, linked = %x, total orbs = %x",
-			command_orb, command->linked, global_outstanding_command_orbs);
+	SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
+			command_orb, global_outstanding_command_orbs);
 
 	pci_dma_sync_single(hi->host->pdev, command->command_orb_dma,
 			    sizeof(struct sbp2_command_orb),
@@ -2054,7 +2136,7 @@
 		if (hpsb_node_entry_valid(scsi_id->ne)) {
 
 			command_request_packet =
-				sbp2util_allocate_write_request_packet(hi, LOCAL_BUS | scsi_id->ne->nodeid,
+				sbp2util_allocate_write_request_packet(hi, scsi_id->ne,
 								scsi_id->sbp2_command_block_agent_addr +
 								SBP2_ORB_POINTER_OFFSET, 8, 0);
 		
@@ -2099,13 +2181,12 @@
 				    PCI_DMA_BIDIRECTIONAL);
 
 		/*
-		 * Only ring the doorbell if we need to (first parts of
-		 * linked orbs don't need this).
+		 * Ring the doorbell
 		 */
-		if (!command->linked && hpsb_node_entry_valid(scsi_id->ne)) {
+		if (hpsb_node_entry_valid(scsi_id->ne)) {
 
 			command_request_packet = sbp2util_allocate_write_request_packet(hi,
-				LOCAL_BUS | scsi_id->ne->nodeid,
+				scsi_id->ne,
 				scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET,
 				0, cpu_to_be32(command->command_orb_dma));
 	
@@ -2151,24 +2232,6 @@
 	SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
 
 	/*
-	 * Check for broken devices that can't handle greater than 128K
-	 * transfers, and deal with them in a hacked ugly way.
-	 */
-	if ((scsi_id->sbp2_firmware_revision == SBP2_128KB_BROKEN_FIRMWARE) && 
-	    (SCpnt->request_bufflen > SBP2_BROKEN_FIRMWARE_MAX_TRANSFER) && 
-	    (device_type == TYPE_DISK) &&
-	    (SCpnt->use_sg) &&
-	    (*cmd == READ_6 || *cmd == READ_10 || *cmd == WRITE_6 || *cmd == WRITE_10)) {
-
-		/*
-		 * Darn, a broken device. We'll need to split up the
-		 * transfer ourselves.
-		 */
-		sbp2_send_split_command(hi, scsi_id, SCpnt, done);
-		return(0);
-	}
-
-	/*
 	 * Allocate a command orb and s/g structure
 	 */
 	command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done, hi);
@@ -2179,11 +2242,11 @@
 	/*
 	 * The scsi stack sends down a request_bufflen which does not match the
 	 * length field in the scsi cdb. This causes some sbp2 devices to 
-	 * reject this inquiry command. Fix is to fix request_bufflen to match
-	 * the value in the cdb.
+	 * reject this inquiry command. Hack fix is to set both buff length and
+	 * length field in cdb to 36. This gives best compatibility.
 	 */
 	if (*cmd == INQUIRY) {
-		request_bufflen = cmd[4];
+		request_bufflen = cmd[4] = 0x24;
 	}
 
 	/*
@@ -2215,120 +2278,6 @@
 	return(0);
 }
 
-/*
- * This function is called for broken sbp2 device, where we have to break
- * up large transfers.
- */
-static int sbp2_send_split_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
-				   Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
-{
-	unchar *cmd = (unchar *) SCpnt->cmnd;
-	struct scatterlist *sgpnt = (struct scatterlist *) SCpnt->request_buffer;
-	struct sbp2_command_info *command;
-	unsigned int i, block_count, block_address, block_size;
-	unsigned int current_sg = 0;
-	unsigned int total_transfer = 0;
-	unsigned int total_sg = 0;
-	unchar new_cmd[12];
-
-	memset(new_cmd, 0, 12);
-	memcpy(new_cmd, cmd, COMMAND_SIZE(*cmd));
-
-	/*
-	 * Turns command into 10 byte version
-	 */
-	sbp2_check_sbp2_command(new_cmd);
-        
-	/*
-	 * Pull block size, block address, block count from command sent down
-	 */
-	block_count = (cmd[7] << 8) | cmd[8];
-	block_address = (cmd[2] << 24) | (cmd[3] << 16) | (cmd[4] << 8) | cmd[5]; 
-	block_size = SCpnt->request_bufflen/block_count;
-
-	/*
-	 * Walk the scsi s/g list to determine how much we can transfer in one pop
-	 */
-	for (i=0; i<SCpnt->use_sg; i++) {
-
-		total_transfer+=sgpnt[i].length;
-		total_sg++;
-
-		if (total_transfer > SBP2_BROKEN_FIRMWARE_MAX_TRANSFER) {
-
-			/*
-			 * Back everything up one, so that we're less than 128KB
-			 */
-			total_transfer-=sgpnt[i].length;
-			total_sg--;
-			i--;
-
-			command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done, hi);
-			if (!command) {
-				return(-EIO);
-			}
-
-			/*
-			 * This is not the final piece, so mark it as linked
-			 */
-			command->linked = 1;
-
-			block_count = total_transfer/block_size;
-			new_cmd[2] = (unchar) (block_address >> 24) & 0xff;
-			new_cmd[3] = (unchar) (block_address >> 16) & 0xff;
-			new_cmd[4] = (unchar) (block_address >> 8) & 0xff;
-			new_cmd[5] = (unchar) block_address & 0xff;
-			new_cmd[7] = (unchar) (block_count >> 8) & 0xff;
-			new_cmd[8] = (unchar) block_count & 0xff;
-			block_address+=block_count;
-
-			sbp2_create_command_orb(hi, scsi_id, command, new_cmd, total_sg, 
-						total_transfer, &sgpnt[current_sg],
-						SCpnt->sc_data_direction);
-
-			/*
-			 * Link up the orb, and ring the doorbell if needed
-			 */
-			memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
-			sbp2_link_orb_command(hi, scsi_id, command);
-
-			current_sg += total_sg;
-			total_sg = 0;
-			total_transfer = 0;
-
-		}
-
-	}
-
-	/*
-	 * Get the last piece...
-	 */
-	command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done, hi);
-	if (!command) {
-		return(-EIO);
-	}
-
-	block_count = total_transfer/block_size;
-	new_cmd[2] = (unchar) (block_address >> 24) & 0xff;
-	new_cmd[3] = (unchar) (block_address >> 16) & 0xff;
-	new_cmd[4] = (unchar) (block_address >> 8) & 0xff;
-	new_cmd[5] = (unchar) block_address & 0xff;
-	new_cmd[7] = (unchar) (block_count >> 8) & 0xff;
-	new_cmd[8] = (unchar) block_count & 0xff;
-
-	sbp2_create_command_orb(hi, scsi_id, command, new_cmd, total_sg, 
-				total_transfer, &sgpnt[current_sg],
-				SCpnt->sc_data_direction);
-
-	/*
-	 * Link up the orb, and ring the doorbell if needed
-	 */
-	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block));
-	sbp2_link_orb_command(hi, scsi_id, command);
-
-
-	return(0);
-}
 
 /*
  * This function deals with command set differences between Linux scsi
@@ -2469,6 +2418,15 @@
 		case INQUIRY:
 
 			/*
+			 * If scsi_id->sbp2_device_type_and_lun is uninitialized, then fill 
+			 * this information in from the inquiry response data. Lun is set to zero.
+			 */
+			if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
+				SBP2_DEBUG("Creating sbp2_device_type_and_lun from scsi inquiry data");
+				scsi_id->sbp2_device_type_and_lun = (scsi_buf[0] & 0x1f) << 16;
+			}
+
+			/*
 			 * Make sure data length is ok. Minimum length is 36 bytes
 			 */
 			if (scsi_buf[4] == 0) {
@@ -2529,7 +2487,7 @@
 {
 	struct sbp2scsi_host_info *hi = NULL;
 	struct scsi_id_instance_data *scsi_id = NULL;
-	int i;
+	u32 id;
 	unsigned long flags;
 	Scsi_Cmnd *SCpnt = NULL;
 	u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
@@ -2554,17 +2512,11 @@
 	sbp2_spin_lock(&hi->sbp2_command_lock, flags);
 
 	/*
-	 * Find our scsi_id structure
+	 * Find our scsi_id structure by looking at the status fifo address written to by
+	 * the sbp2 device.
 	 */
-	for (i=0; i<SBP2SCSI_MAX_SCSI_IDS; i++) {
-		if (hi->scsi_id[i]) {
-			if ((hi->scsi_id[i]->ne->nodeid & NODE_MASK) == (nodeid & NODE_MASK)) {
-				scsi_id = hi->scsi_id[i];
-				SBP2_DEBUG("SBP-2 status write from node %x", scsi_id->ne->nodeid);
-				break;
-			}
-		}
-	}
+	id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); 
+	scsi_id = hi->scsi_id[id];
 
 	if (!scsi_id) {
 		SBP2_ERR("scsi_id is NULL - device is gone?");
@@ -2605,12 +2557,12 @@
 		SCpnt = command->Current_SCpnt;
 		sbp2util_mark_command_completed(scsi_id, command);
 
-		if (SCpnt && !command->linked) {
+		if (SCpnt) {
 
 			/*
 			 * See if the target stored any scsi status information
 			 */
-			if (length > 8) {
+			if (STATUS_GET_LENGTH(scsi_id->status_block.ORB_offset_hi_misc) > 1) {
 				/*
 				 * Translate SBP-2 status to SCSI sense data
 				 */
@@ -2657,7 +2609,6 @@
 	return(RCODE_COMPLETE);
 }
 
-
 
 /**************************************
  * SCSI interface related section
@@ -2722,8 +2673,7 @@
 	}
 
 	/*
-	 * Check to see if there is a command in progress and just return
-	 * busy (to be queued later)
+	 * Check to see if we are in the middle of a bus reset.
 	 */
 	if (!hpsb_node_entry_valid(scsi_id->ne)) {
 		SBP2_ERR("Bus reset in progress - rejecting command");
@@ -2769,7 +2719,7 @@
 				    sizeof(command->scatter_gather_element),
 				    PCI_DMA_BIDIRECTIONAL);
 		sbp2util_mark_command_completed(scsi_id, command);
-		if (command->Current_SCpnt && !command->linked) {
+		if (command->Current_SCpnt) {
 			void (*done)(Scsi_Cmnd *) = command->Current_done;
 			command->Current_SCpnt->result = status << 16;
 			done (command->Current_SCpnt);
@@ -2873,14 +2823,22 @@
 	 * or hot-plug...
 	 */
 	if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) {
-		SBP2_INFO("UNIT ATTENTION - return busy");
+		SBP2_DEBUG("UNIT ATTENTION - return busy");
 		SCpnt->result = DID_BUS_BUSY << 16;
 	}
 
 	/*
 	 * Tell scsi stack that we're done with this command
 	 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	spin_lock_irq(&io_request_lock);
+	done (SCpnt);
+	spin_unlock_irq(&io_request_lock);
+#else
+	spin_lock_irq(&hi->scsi_host->host_lock);
 	done (SCpnt);
+	spin_unlock_irq(&hi->scsi_host->host_lock);
+#endif
 
 	return;
 }
@@ -2903,30 +2861,27 @@
 
 		/*
 		 * Right now, just return any matching command structures
-		 * to the free pool (there may be more than one because of
-		 * broken up/linked commands).
+		 * to the free pool.
 		 */
 		sbp2_spin_lock(&hi->sbp2_command_lock, flags);
-		do {
-			command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
-			if (command) {
-				SBP2_DEBUG("Found command to abort");
-				pci_dma_sync_single(hi->host->pdev,
-						    command->command_orb_dma,
-						    sizeof(struct sbp2_command_orb),
-						    PCI_DMA_BIDIRECTIONAL);
-				pci_dma_sync_single(hi->host->pdev,
-						    command->sge_dma,
-						    sizeof(command->scatter_gather_element),
-						    PCI_DMA_BIDIRECTIONAL);
-				sbp2util_mark_command_completed(scsi_id, command);
-				if (command->Current_SCpnt && !command->linked) {
-					void (*done)(Scsi_Cmnd *) = command->Current_done;
-					command->Current_SCpnt->result = DID_ABORT << 16;
-					done (command->Current_SCpnt);
-				}
+		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt);
+		if (command) {
+			SBP2_DEBUG("Found command to abort");
+			pci_dma_sync_single(hi->host->pdev,
+					    command->command_orb_dma,
+					    sizeof(struct sbp2_command_orb),
+					    PCI_DMA_BIDIRECTIONAL);
+			pci_dma_sync_single(hi->host->pdev,
+					    command->sge_dma,
+					    sizeof(command->scatter_gather_element),
+					    PCI_DMA_BIDIRECTIONAL);
+			sbp2util_mark_command_completed(scsi_id, command);
+			if (command->Current_SCpnt) {
+				void (*done)(Scsi_Cmnd *) = command->Current_done;
+				command->Current_SCpnt->result = DID_ABORT << 16;
+				done (command->Current_SCpnt);
 			}
-		} while (command);
+		}
 
 		/*
 		 * Initiate a fetch agent reset. 
@@ -2945,12 +2900,13 @@
 static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) 
 {
 	struct sbp2scsi_host_info *hi = (struct sbp2scsi_host_info *) SCpnt->host->hostdata[0];
+	struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->target];
 
 	SBP2_ERR("reset requested");
 
-	if (hi) {
+	if (scsi_id) {
 		SBP2_ERR("Generating IEEE-1394 bus reset");
-		hpsb_reset_bus(hi->host, LONG_RESET);
+		sbp2_agent_reset(hi, scsi_id, SBP2_SEND_NO_WAIT);
 	}
 
 	return(SUCCESS);
@@ -2990,7 +2946,7 @@
 	SBP2_DEBUG("sbp2scsi_detect");
 
 	/*
-	 * Call sbp2_init to register with the ieee1394 stack.  This
+	 * Call sbp2_init to register with the ieee1394 stack. This
 	 * results in a callback to sbp2_add_host for each ieee1394
 	 * host controller currently registered, and for each of those
 	 * we register a scsi host with the scsi stack.
@@ -3013,8 +2969,19 @@
 	if (!hi) /* shouldn't happen, but... */
         	return "IEEE-1394 SBP-2 protocol driver";
 
-	sprintf(info, "IEEE-1394 SBP-2 protocol driver\nHost Driver: %s\nSerial I/O: %s",
-		hi->host->driver->name, serialize_io ? "yes" : "no");
+	sprintf(info, "IEEE-1394 SBP-2 protocol driver (host: %s)\n"
+		"SBP-2 module load options:\n"
+		"- Max speed supported: %s\n"
+		"- Max sectors per I/O supported: %d\n"
+		"- Max outstanding commands supported: %d\n"
+		"- Max outstanding commands per lun supported: %d\n"
+                "- Serialized I/O (debug): %s",
+		hi->host->driver->name, 
+		hpsb_speedto_str[sbp2_max_speed],
+		sbp2_max_sectors,
+		sbp2_max_outstanding_cmds,
+		sbp2_max_cmds_per_lun,
+		sbp2_serialize_io ? "yes" : "no");
 
 	return info;
 }
@@ -3025,17 +2992,6 @@
 MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
 MODULE_LICENSE("GPL");
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,26)
-#define PROC_SCSI_SBP2 PROC_SCSI_NOT_PRESENT /* What should I use? */
-static struct proc_dir_entry proc_scsi_sbp2scsi = {
-	low_ino:	PROC_SCSI_SBP2,
-	namelen:	SBP2_DEVICE_NAME_SIZE,
-	name:		SBP2_DEVICE_NAME,
-	mode:		S_IFDIR | S_IRUGO | S_IXUGO,
-	nlink:		2
-};
-#endif
-
 /* SCSI host template */
 static Scsi_Host_Template scsi_driver_template = {
 	name:			"IEEE-1394 SBP-2 protocol driver",
@@ -3047,20 +3003,14 @@
 	eh_bus_reset_handler:	sbp2scsi_reset,
 	eh_host_reset_handler:	sbp2scsi_reset,
 	bios_param:		sbp2scsi_biosparam,
-	can_queue:		SBP2SCSI_MAX_OUTSTANDING_CMDS,
 	this_id:		-1,
 	sg_tablesize:		SBP2_MAX_SG_ELEMENTS,
-	cmd_per_lun:		SBP2SCSI_MAX_CMDS_PER_LUN,
 	use_clustering:		SBP2_CLUSTERING,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	use_new_eh_code:	TRUE,
 #endif
 	emulated:		1,
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,26)
 	proc_name:	SBP2_DEVICE_NAME,
-#else
-	proc_dir:	&proc_scsi_sbp2scsi,
-#endif
 };
 
 static int sbp2_module_init(void)
@@ -3068,29 +3018,26 @@
 	SBP2_DEBUG("sbp2_module_init");
 
 	/*
-	 * Module load option for force one command at a time
+	 * Module load debug option to force one command at a time (serializing I/O)
 	 */
-	if (serialize_io) {
+	if (sbp2_serialize_io) {
 		SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
 		scsi_driver_template.can_queue = 1;
 		scsi_driver_template.cmd_per_lun = 1;
+	} else {
+		scsi_driver_template.can_queue = sbp2_max_outstanding_cmds;
+		scsi_driver_template.cmd_per_lun = sbp2_max_cmds_per_lun;
 	}
 
-	/*
-	 * Module load option to limit max size of requests from the
-	 * scsi drivers
+	/* 
+	 * Set max sectors (module load option). Default is 255 sectors. 
 	 */
-	if (no_large_packets) {
-		SBP2_ERR("Driver forced to limit max transfer size "
-			 "(no_large_packets = 1)");
-		scsi_driver_template.sg_tablesize = 0x1f;
-		scsi_driver_template.use_clustering = DISABLE_CLUSTERING;
-	}
+	scsi_driver_template.max_sectors = sbp2_max_sectors;
 
 	/*
 	 * Ideally we would register our scsi_driver_template with the
 	 * scsi stack and after that register with the ieee1394 stack
-	 * and process the add_host callbacks.  However, the detect
+	 * and process the add_host callbacks. However, the detect
 	 * function in the scsi host template requires that we find at
 	 * least one host, so we "nest" the registrations by calling
 	 * sbp2_init from the detect function.
diff -Nru a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
--- a/drivers/ieee1394/sbp2.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/ieee1394/sbp2.h	Sun Apr 14 12:16:56 2002
@@ -195,10 +195,28 @@
  * Miscellaneous SBP2 related config rom defines
  */
 
-#define SBP2_STATUS_FIFO_ADDRESS				0xfffe00000000ULL     /* for write posting! */
+/* 
+ * The status fifo address definition below is used as a status base, with a chunk
+ * separately assigned for each sbp2 device detected. For example, 0xfffe00000000ULL 
+ * is used for the first sbp2 device detected, 0xfffe00000020ULL for the next sbp2 
+ * device, and so on.
+ *
+ * Note: We could use a single status fifo address for all sbp2 devices, and figure 
+ * out which sbp2 device the status belongs to by looking at the source node id of
+ * the status write... but, using separate addresses for each sbp2 device allows for
+ * better code and the ability to support multiple luns within a single 1394 node.
+ *
+ * Also note that we choose the address range below as it is a region specified for
+ * write posting, where the ohci controller will automatically send an ack_complete
+ * when the status is written by the sbp2 device... saving a split transaction.   =)
+ */ 
+#define SBP2_STATUS_FIFO_ADDRESS				0xfffe00000000ULL
 #define SBP2_STATUS_FIFO_ADDRESS_HI                             0xfffe
 #define SBP2_STATUS_FIFO_ADDRESS_LO                             0x0
 
+#define SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(entry)			((entry) << 5)
+#define SBP2_STATUS_FIFO_OFFSET_TO_ENTRY(offset)		((offset) >> 5)
+
 #define SBP2_UNIT_DIRECTORY_OFFSET_KEY				0xd1
 #define SBP2_CSR_OFFSET_KEY					0x54
 #define SBP2_UNIT_SPEC_ID_KEY					0x12
@@ -209,8 +227,8 @@
 #define SBP2_DEVICE_TYPE_AND_LUN_KEY				0x14
 #define SBP2_FIRMWARE_REVISION_KEY				0x3c
 
-#define SBP2_DEVICE_TYPE(q)			(((q) >> 16) & 0x1f)
-#define SBP2_DEVICE_LUN(q)			((q) & 0xffff)
+#define SBP2_DEVICE_TYPE(q)					(((q) >> 16) & 0x1f)
+#define SBP2_DEVICE_LUN(q)					((q) & 0xffff)
 
 #define SBP2_AGENT_STATE_OFFSET					0x00ULL
 #define SBP2_AGENT_RESET_OFFSET					0x04ULL
@@ -231,10 +249,14 @@
 #define SBP2_UNIT_SPEC_ID_ENTRY					0x0000609e
 #define SBP2_SW_VERSION_ENTRY					0x00010483
 
-
+/*
+ * Other misc defines
+ */
 #define SBP2_128KB_BROKEN_FIRMWARE				0xa0b800
 #define SBP2_BROKEN_FIRMWARE_MAX_TRANSFER			0x20000
 
+#define SBP2_DEVICE_TYPE_LUN_UNINITIALIZED			0xffffffff
+
 /*
  * Flags for SBP-2 functions
  */
@@ -247,9 +269,10 @@
 #define SBP2_MAX_SG_ELEMENTS		SG_ALL
 #define SBP2_CLUSTERING			ENABLE_CLUSTERING
 #define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
-#define SBP2SCSI_MAX_SCSI_IDS		8
+#define SBP2SCSI_MAX_SCSI_IDS		16	/* Max sbp2 device instances supported */
 #define SBP2SCSI_MAX_OUTSTANDING_CMDS	8	/* Max total outstanding sbp2 commands allowed at a time! */
-#define SBP2SCSI_MAX_CMDS_PER_LUN	4 	/* Max outstanding sbp2 commands per device - tune as needed */
+#define SBP2SCSI_MAX_CMDS_PER_LUN	1 	/* Max outstanding sbp2 commands per device - tune as needed */
+#define SBP2_MAX_SECTORS		255	/* Max sectors supported */
 
 #ifndef TYPE_SDAD
 #define TYPE_SDAD			0x0e	/* simplified direct access device */
@@ -291,13 +314,8 @@
 	DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
 };
 
-
-/*
- * Number of request packets available for actual sbp2 I/O requests (these are used
- * for sending command and agent reset packets).
- */
-#define SBP2_MAX_REQUEST_PACKETS	SBP2SCSI_MAX_OUTSTANDING_CMDS	/* Per host adapter instance */
-#define SBP2_MAX_COMMAND_ORBS		SBP2SCSI_MAX_CMDS_PER_LUN * 2	/* Per sbp2 device instance */
+#define SBP2_MAX_REQUEST_PACKETS	(sbp2_max_outstanding_cmds * 2)
+#define SBP2_MAX_COMMAND_ORBS		(sbp2_max_cmds_per_lun * 2)
 
 /*
  * Request packets structure (used for sending command and agent reset packets)
@@ -327,7 +345,6 @@
 	dma_addr_t command_orb_dma ____cacheline_aligned;
 	Scsi_Cmnd *Current_SCpnt;
 	void (*Current_done)(Scsi_Cmnd *);
-	unsigned int linked;
 
 	/* Also need s/g structure for each sbp2 command */
 	struct sbp2_unrestricted_page_table scatter_gather_element[SBP2_MAX_SG_ELEMENTS] ____cacheline_aligned;
@@ -434,7 +451,7 @@
 	 * Here is the pool of request packets. All the hpsb packets (for 1394 bus transactions)
 	 * are allocated at init and simply re-initialized when needed.
 	 */
-	struct sbp2_request_packet request_packet[SBP2_MAX_REQUEST_PACKETS];
+	struct sbp2_request_packet *request_packet;
 
 	/*
 	 * SCSI ID instance data (one for each sbp2 device instance possible)
@@ -453,7 +470,7 @@
 static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi);
 static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi);
 static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
-									  nodeid_t node, u64 addr,
+									  struct node_entry *ne, u64 addr,
 									  size_t data_size,
 									  quadlet_t data);
 static void sbp2util_free_request_packet(struct sbp2_request_packet *request_packet);
@@ -505,8 +522,6 @@
 				 struct sbp2_command_info *command);
 static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
 			     Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-static int sbp2_send_split_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
-				   Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
 static void sbp2_check_sbp2_command(unchar *cmd);
 static void sbp2_check_sbp2_response(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, 
diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
--- a/drivers/ieee1394/video1394.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/ieee1394/video1394.c	Sun Apr 14 12:16:56 2002
@@ -18,6 +18,9 @@
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+/* jds -- add private data to file to keep track of iso contexts associated
+   with each open -- so release won't kill all iso transfers */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -31,19 +34,12 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 #include <linux/proc_fs.h>
 #include <linux/tqueue.h>
 #include <linux/delay.h>
 #include <linux/devfs_fs_kernel.h>
 
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
-#include <asm/segment.h>
+#include <asm/bitops.h>
 #include <linux/types.h>
 #include <linux/wrapper.h>
 #include <linux/vmalloc.h>
@@ -71,6 +67,14 @@
 #define vmalloc_32(x) vmalloc(x)
 #endif
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3))
+#define remap_page_range_1394(vma, start, addr, size, prot) \
+	remap_page_range(start, addr, size, prot)
+#else
+#define remap_page_range_1394(vma, start, addr, size, prot) \
+	remap_page_range(vma, start, addr, size, prot)
+#endif
+
 struct it_dma_prg {
 	struct dma_cmd begin;
 	quadlet_t data[4];
@@ -108,6 +112,8 @@
 	spinlock_t lock;
 	unsigned int syt_offset;
 	int flags;
+
+	struct list_head link;
 };
 
 struct video_card {
@@ -115,9 +121,12 @@
 	struct list_head list;
 	int id;
 	devfs_handle_t devfs;
+};
+
 
-	struct dma_iso_ctx **ir_context;
-	struct dma_iso_ctx **it_context;
+struct file_ctx {
+	struct video_card *video;
+	struct list_head context_list;
 	struct dma_iso_ctx *current_ctx;
 };
 
@@ -159,35 +168,86 @@
 /* Memory management functions */
 /*******************************/
 
-static inline unsigned long kvirt_to_bus(unsigned long adr) 
+#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ *    out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guaranteed.  We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+        unsigned long ret = 0UL;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+  
+	if (!pgd_none(*pgd)) {
+                pmd = pmd_offset(pgd, adr);
+                if (!pmd_none(*pmd)) {
+                        ptep = pte_offset_kernel(pmd, adr);
+                        pte = *ptep;
+                        if(pte_present(pte)) {
+				ret = (unsigned long) 
+					page_address(pte_page(pte));
+                                ret |= (adr & (PAGE_SIZE - 1));
+			}
+                }
+        }
+        MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
+	return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr) 
 {
         unsigned long kva, ret;
 
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+        kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
 	ret = virt_to_bus((void *)kva);
+        MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
+        return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr) 
+{
+        unsigned long va, kva, ret;
+
+        va = VMALLOC_VMADDR(adr);
+        kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = virt_to_bus((void *)kva);
+        MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
         return ret;
 }
 
 /* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
  */
 static inline unsigned long kvirt_to_pa(unsigned long adr) 
 {
-        unsigned long kva, ret;
+        unsigned long va, kva, ret;
 
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+        va = VMALLOC_VMADDR(adr);
+        kva = uvirt_to_kva(pgd_offset_k(va), va);
 	ret = __pa(kva);
+        MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
         return ret;
 }
 
 static void * rvmalloc(unsigned long size)
 {
 	void * mem;
-	unsigned long adr;
- 
-	size=PAGE_ALIGN(size);
+	unsigned long adr, page;
+        
 	mem=vmalloc_32(size);
 	if (mem) 
 	{
@@ -196,7 +256,8 @@
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
-			mem_map_reserve(vmalloc_to_page((void *)adr));
+	                page = kvirt_to_pa(adr);
+			mem_map_reserve(virt_to_page(__va(page)));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -206,14 +267,15 @@
 
 static void rvfree(void * mem, unsigned long size)
 {
-        unsigned long adr;
-
+        unsigned long adr, page;
+        
 	if (mem) 
 	{
 	        adr=(unsigned long) mem;
-		while ((long) size > 0) 
+		while (size > 0) 
                 {
-			mem_map_unreserve(vmalloc_to_page((void *)adr));
+	                page = kvirt_to_pa(adr);
+			mem_map_unreserve(virt_to_page(__va(page)));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -222,52 +284,48 @@
 }
 /* End of code taken from bttv.c */
 
-static int free_dma_iso_ctx(struct dma_iso_ctx **d)
+static int free_dma_iso_ctx(struct dma_iso_ctx *d)
 {
 	int i;
-	struct ti_ohci *ohci;
 	unsigned long *usage;
 	
-	if ((*d)==NULL) return -1;
+	DBGMSG(d->ohci->id, "Freeing dma_iso_ctx %d", d->ctx);
 
-	ohci = (struct ti_ohci *)(*d)->ohci;
+	ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
+	ohci1394_unhook_irq(d->ohci, irq_handler, d);
 
-	DBGMSG(ohci->id, "Freeing dma_iso_ctx %d", (*d)->ctx);
+	if (d->buf)
+		rvfree((void *)d->buf, d->num_desc * d->buf_size);
 
-	ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL);
-
-	if ((*d)->buf) rvfree((void *)(*d)->buf, 
-			      (*d)->num_desc * (*d)->buf_size);
-
-	if ((*d)->ir_prg) {
-		for (i=0;i<(*d)->num_desc;i++) 
-			if ((*d)->ir_prg[i]) kfree((*d)->ir_prg[i]);
-		kfree((*d)->ir_prg);
+	if (d->ir_prg) {
+		for (i=0;i<d->num_desc;i++) 
+			if (d->ir_prg[i]) kfree(d->ir_prg[i]);
+		kfree(d->ir_prg);
 	}
 
-	if ((*d)->it_prg) {
-		for (i=0;i<(*d)->num_desc;i++) 
-			if ((*d)->it_prg[i]) kfree((*d)->it_prg[i]);
-		kfree((*d)->it_prg);
+	if (d->it_prg) {
+		for (i=0;i<d->num_desc;i++) 
+			if (d->it_prg[i]) kfree(d->it_prg[i]);
+		kfree(d->it_prg);
 	}
 
-	if ((*d)->buffer_status)
-		kfree((*d)->buffer_status);
-	if ((*d)->buffer_time)
-		kfree((*d)->buffer_time);
-	if ((*d)->last_used_cmd)
-		kfree((*d)->last_used_cmd);
-	if ((*d)->next_buffer)
-		kfree((*d)->next_buffer);
+	if (d->buffer_status)
+		kfree(d->buffer_status);
+	if (d->buffer_time)
+		kfree(d->buffer_time);
+	if (d->last_used_cmd)
+		kfree(d->last_used_cmd);
+	if (d->next_buffer)
+		kfree(d->next_buffer);
 
-	usage = ((*d)->type == ISO_RECEIVE) ? &ohci->ir_ctx_usage :
-		&ohci->it_ctx_usage;
+	usage = (d->type == ISO_RECEIVE) ? &d->ohci->ir_ctx_usage :
+		&d->ohci->it_ctx_usage;
        
 	/* clear the ISO context usage bit */
-	clear_bit((*d)->ctx, usage);
-	
-	kfree(*d);
-	*d = NULL;
+	clear_bit(d->ctx, usage);
+	list_del(&d->link);
+
+	kfree(d);
 
 	return 0;
 }
@@ -319,11 +377,17 @@
 	d->ir_prg = NULL;
 	init_waitqueue_head(&d->waitq);
 
+	if (ohci1394_hook_irq(ohci, irq_handler, d) != 0) {
+		PRINT(KERN_ERR, ohci->id, "ohci1394_hook_irq() failed");
+		free_dma_iso_ctx(d);
+		return NULL;
+	}
+
 	d->buf = rvmalloc(d->num_desc * d->buf_size);
 
 	if (d->buf == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer");
-		free_dma_iso_ctx(&d);
+		free_dma_iso_ctx(d);
 		return NULL;
 	}
 	memset(d->buf, 0, d->num_desc * d->buf_size);
@@ -340,7 +404,7 @@
 		if (d->ir_prg == NULL) {
 			PRINT(KERN_ERR, ohci->id, 
 			      "Failed to allocate dma ir prg");
-			free_dma_iso_ctx(&d);
+			free_dma_iso_ctx(d);
 			return NULL;
 		}
 		memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *));
@@ -356,7 +420,7 @@
 			if (d->ir_prg[i] == NULL) {
 				PRINT(KERN_ERR, ohci->id, 
 				      "Failed to allocate dma ir prg");
-				free_dma_iso_ctx(&d);
+				free_dma_iso_ctx(d);
 				return NULL;
 			}
 		}
@@ -372,7 +436,7 @@
 		if (d->it_prg == NULL) {
 			PRINT(KERN_ERR, ohci->id, 
 			      "Failed to allocate dma it prg");
-			free_dma_iso_ctx(&d);
+			free_dma_iso_ctx(d);
 			return NULL;
 		}
 		memset(d->it_prg, 0, d->num_desc*sizeof(struct it_dma_prg *));
@@ -384,7 +448,7 @@
 			      "Packet size %d (page_size: %ld) "
 			      "not yet supported\n",
 			      packet_size, PAGE_SIZE);
-			free_dma_iso_ctx(&d);
+			free_dma_iso_ctx(d);
 			return NULL;
 		}
 
@@ -403,7 +467,7 @@
 			if (d->it_prg[i] == NULL) {
 				PRINT(KERN_ERR, ohci->id, 
 				      "Failed to allocate dma it prg");
-				free_dma_iso_ctx(&d);
+				free_dma_iso_ctx(d);
 				return NULL;
 			}
 		}
@@ -420,22 +484,22 @@
 
 	if (d->buffer_status == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_status");
-		free_dma_iso_ctx(&d);
+		free_dma_iso_ctx(d);
 		return NULL;
 	}
 	if (d->buffer_time == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_time");
-		free_dma_iso_ctx(&d);
+		free_dma_iso_ctx(d);
 		return NULL;
 	}
 	if (d->last_used_cmd == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Failed to allocate last_used_cmd");
-		free_dma_iso_ctx(&d);
+		free_dma_iso_ctx(d);
 		return NULL;
 	}
 	if (d->next_buffer == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Failed to allocate next_buffer");
-		free_dma_iso_ctx(&d);
+		free_dma_iso_ctx(d);
 		return NULL;
 	}
 	memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
@@ -537,36 +601,17 @@
 }
 
 /* find which context is listening to this channel */
-static struct dma_iso_ctx **
-ir_ctx_listening(struct video_card *video, int channel)
-{
-	int i;
-	struct ti_ohci *ohci = video->ohci;
-
-	for (i = 0; i < ohci->nb_iso_rcv_ctx-1; i++) 
-		if (video->ir_context[i] &&
-		    video->ir_context[i]->channel == channel)
-			return &video->ir_context[i];
-		
-	PRINT(KERN_ERR, ohci->id, "No iso context is listening to channel %d",
-	      channel);
-
-	return NULL;
-}
-
-static struct dma_iso_ctx **
-it_ctx_talking(struct video_card *video, int channel)
+static struct dma_iso_ctx *
+find_ctx(struct list_head *list, int type, int channel)
 {
-	int i;
-	struct ti_ohci *ohci = video->ohci;
+	struct list_head *lh;
 
-	for (i = 0; i < ohci->nb_iso_xmit_ctx; i++) 
-		if (video->it_context[i] &&
-		    video->it_context[i]->channel==channel)
-			return &video->ir_context[i];
-		
-	PRINT(KERN_ERR, ohci->id, "No iso context is talking to channel %d",
-	      channel);
+	list_for_each(lh, list) {
+		struct dma_iso_ctx *ctx;
+		ctx = list_entry(lh, struct dma_iso_ctx, link);
+		if (ctx->type == type && ctx->channel == channel)
+			return ctx;
+	}
 
 	return NULL;
 }
@@ -586,7 +631,11 @@
 		if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) {
 			reset_ir_status(d, i);
 			d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
+			get_fast_time(&d->buffer_time[i]);
+#else
 			do_gettimeofday(&d->buffer_time[i]);
+#endif
 		}
 	}
 	spin_unlock(&d->lock);
@@ -791,13 +840,14 @@
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
 }
 
-static int do_iso_mmap(struct vm_area_struct *vma, struct ti_ohci *ohci, struct dma_iso_ctx *d, 
-		       const char *adr, unsigned long size)
+static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d,
+		       struct vm_area_struct *vma)
 {
-        unsigned long start=(unsigned long) adr;
-        unsigned long page,pos;
+        unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+        unsigned long page, pos;
 
-        if (size>d->num_desc * d->buf_size) {
+        if (size > d->num_desc * d->buf_size) {
 		PRINT(KERN_ERR, ohci->id, 
 		      "iso context %d buf size is different from mmap size", 
 		      d->ctx);
@@ -809,14 +859,14 @@
 		return -EINVAL;
 	}
 
-        pos=(unsigned long) d->buf;
+	pos = (unsigned long) d->buf;
         while (size > 0) {
                 page = kvirt_to_pa(pos);
-                if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+                if (remap_page_range_1394(vma, start, page, PAGE_SIZE, PAGE_SHARED))
                         return -EAGAIN;
-                start+=PAGE_SIZE;
-                pos+=PAGE_SIZE;
-                size-=PAGE_SIZE;
+                start += PAGE_SIZE;
+                pos += PAGE_SIZE;
+                size -= PAGE_SIZE;
         }
         return 0;
 }
@@ -824,30 +874,10 @@
 static int video1394_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, unsigned long arg)
 {
-	struct video_card *video = NULL;
-	struct ti_ohci *ohci = NULL;
+	struct file_ctx *ctx = (struct file_ctx *)file->private_data;
+	struct video_card *video = ctx->video;
+	struct ti_ohci *ohci = video->ohci;
 	unsigned long flags;
-	struct list_head *lh;
-
-	spin_lock_irqsave(&video1394_cards_lock, flags);
-	if (!list_empty(&video1394_cards)) {
-		struct video_card *p;
-		list_for_each(lh, &video1394_cards) {
-			p = list_entry(lh, struct video_card, list);
-			if (p->id == ieee1394_file_to_instance(file)) {
-				video = p;
-				ohci = video->ohci;
-				break;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&video1394_cards_lock, flags);
-
-	if (video == NULL) {
-		PRINT_G(KERN_ERR, "%s: Unknown video card for minor %d",
-			__FUNCTION__, ieee1394_file_to_instance(file));
-		return -EFAULT;
-	}
 
 	switch(cmd)
 	{
@@ -856,6 +886,7 @@
 	{
 		struct video1394_mmap v;
 		u64 mask;
+		struct dma_iso_ctx *d;
 		int i;
 
 		if(copy_from_user(&v, (void *)arg, sizeof(v)))
@@ -890,7 +921,7 @@
 			return -EFAULT;
 		}
 		ohci->ISO_channel_usage |= mask;
-		
+
 		if (v.buf_size<=0) {
 			PRINT(KERN_ERR, ohci->id,
 			      "Invalid %d length buffer requested",v.buf_size);
@@ -911,67 +942,47 @@
 		}
 
 		if (cmd == VIDEO1394_LISTEN_CHANNEL) {
-			/* find a free iso receive context */
-			for (i=0;i<ohci->nb_iso_rcv_ctx-1;i++) 
-				if (video->ir_context[i]==NULL) break;
-			    
-			if (i==(ohci->nb_iso_rcv_ctx-1)) {
-				PRINT(KERN_ERR, ohci->id, 
-				      "No iso context available");
-				return -EFAULT;
-			}
+			d = alloc_dma_iso_ctx(ohci, ISO_RECEIVE,
+					      v.nb_buffers, v.buf_size, 
+					      v.channel, 0);
 
-			video->ir_context[i] = 
-				alloc_dma_iso_ctx(ohci, ISO_RECEIVE,
-						  v.nb_buffers, v.buf_size, 
-						  v.channel, 0);
-
-			if (video->ir_context[i] == NULL) {
+			if (d == NULL) {
 				PRINT(KERN_ERR, ohci->id, 
 				      "Couldn't allocate ir context");
 				return -EFAULT;
 			}
-			initialize_dma_ir_ctx(video->ir_context[i], 
-					      v.sync_tag, v.flags);
+			initialize_dma_ir_ctx(d, v.sync_tag, v.flags);
 
-			video->current_ctx = video->ir_context[i];
+			ctx->current_ctx = d;
 
-			v.buf_size = video->ir_context[i]->buf_size;
+			v.buf_size = d->buf_size;
+			list_add_tail(&d->link, &ctx->context_list);
 
 			PRINT(KERN_INFO, ohci->id, 
 			      "iso context %d listen on channel %d",
-			      video->current_ctx->ctx, v.channel);
+			      d->ctx, v.channel);
 		}
 		else {
-			/* find a free iso transmit context */
-			for (i=0;i<ohci->nb_iso_xmit_ctx;i++) 
-				if (video->it_context[i]==NULL) break;
-			    
-			if (i==ohci->nb_iso_xmit_ctx) {
-				PRINT(KERN_ERR, ohci->id, 
-				      "No iso context available");
-				return -EFAULT;
-			}
-			
-			video->it_context[i] = 
-				alloc_dma_iso_ctx(ohci, ISO_TRANSMIT,
-						  v.nb_buffers, v.buf_size, 
-						  v.channel, v.packet_size);
+			d = alloc_dma_iso_ctx(ohci, ISO_TRANSMIT,
+					      v.nb_buffers, v.buf_size, 
+					      v.channel, v.packet_size);
 
-			if (video->it_context[i] == NULL) {
+			if (d == NULL) {
 				PRINT(KERN_ERR, ohci->id, 
 				      "Couldn't allocate it context");
 				return -EFAULT;
 			}
-			initialize_dma_it_ctx(video->it_context[i], 
-					      v.sync_tag, v.syt_offset, v.flags);
+			initialize_dma_it_ctx(d, v.sync_tag, 
+					      v.syt_offset, v.flags);
 
-			video->current_ctx = video->it_context[i];
+			ctx->current_ctx = d;
 
-			v.buf_size = video->it_context[i]->buf_size;
+			v.buf_size = d->buf_size;
+
+			list_add_tail(&d->link, &ctx->context_list);
 
 			PRINT(KERN_INFO, ohci->id, 
-			      "Iso context %d talk on channel %d", i, 
+			      "Iso context %d talk on channel %d", d->ctx,
 			      v.channel);
 		}
 
@@ -985,6 +996,7 @@
 	{
 		int channel;
 		u64 mask;
+		struct dma_iso_ctx *d;
 
 		if(copy_from_user(&channel, (void *)arg, sizeof(int)))
 			return -EFAULT;
@@ -1000,41 +1012,31 @@
 			      "Channel %d is not being used", channel);
 			return -EFAULT;
 		}
+
+		/* Mark this channel as unused */
 		ohci->ISO_channel_usage &= ~mask;
 
-		if (cmd == VIDEO1394_UNLISTEN_CHANNEL) {
-			struct dma_iso_ctx **d;
-			d = ir_ctx_listening(video, channel);
-			if (d == NULL) return -EFAULT;
-			PRINT(KERN_INFO, ohci->id, 
-			      "Iso context %d stop listening on channel %d", 
-			      (*d)->ctx, channel);
-			free_dma_iso_ctx(d);
-		}
-		else {
-			struct dma_iso_ctx **d;
-			d = it_ctx_talking(video, channel);
-			if (d == NULL) return -EFAULT;
-			PRINT(KERN_INFO, ohci->id, 
-			      "Iso context %d stop talking on channel %d", 
-			      (*d)->ctx, channel);
-			free_dma_iso_ctx(d);
+		if (cmd == VIDEO1394_UNLISTEN_CHANNEL)
+			d = find_ctx(&ctx->context_list, ISO_RECEIVE, channel);
+		else
+			d = find_ctx(&ctx->context_list, ISO_TRANSMIT, channel);
 
-		}
+		if (d == NULL) return -EFAULT;
+		PRINT(KERN_INFO, ohci->id, "Iso context %d "
+		      "stop talking on channel %d", d->ctx, channel);
+		free_dma_iso_ctx(d);
 		
 		return 0;
 	}
 	case VIDEO1394_LISTEN_QUEUE_BUFFER:
 	{
 		struct video1394_wait v;
-		struct dma_iso_ctx *d, **dd;
+		struct dma_iso_ctx *d;
 
 		if(copy_from_user(&v, (void *)arg, sizeof(v)))
 			return -EFAULT;
 
-		dd = ir_ctx_listening(video, v.channel);
-		if (dd == NULL) return -EFAULT;
-		d = *dd;
+		d = find_ctx(&ctx->context_list, ISO_RECEIVE, v.channel);
 
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->id, 
@@ -1090,15 +1092,13 @@
 	case VIDEO1394_LISTEN_POLL_BUFFER:
 	{
 		struct video1394_wait v;
-		struct dma_iso_ctx *d, **dd;
+		struct dma_iso_ctx *d;
 		int i;
 
 		if(copy_from_user(&v, (void *)arg, sizeof(v)))
 			return -EFAULT;
 
-		dd = ir_ctx_listening(video, v.channel);
-		if (dd==NULL) return -EFAULT;
-		d = *dd;
+		d = find_ctx(&ctx->context_list, ISO_RECEIVE, v.channel);
 
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->id, 
@@ -1174,14 +1174,12 @@
 	{
 		struct video1394_wait v;
 		struct video1394_queue_variable qv;
-		struct dma_iso_ctx *d, **dd;
+		struct dma_iso_ctx *d;
 
 		if(copy_from_user(&v, (void *)arg, sizeof(v)))
 			return -EFAULT;
 
-		dd = it_ctx_talking(video, v.channel);
-		if (dd == NULL) return -EFAULT;
-		d = *dd;
+		d = find_ctx(&ctx->context_list, ISO_TRANSMIT, v.channel);
 
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->id, 
@@ -1265,14 +1263,12 @@
 	case VIDEO1394_TALK_WAIT_BUFFER:
 	{
 		struct video1394_wait v;
-		struct dma_iso_ctx *d, **dd;
+		struct dma_iso_ctx *d;
 
 		if(copy_from_user(&v, (void *)arg, sizeof(v)))
 			return -EFAULT;
 
-		dd = it_ctx_talking(video, v.channel);
-		if (dd == NULL) return -EFAULT;
-		d = *dd;
+		d = find_ctx(&ctx->context_list, ISO_TRANSMIT, v.channel);
 
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->id, 
@@ -1322,40 +1318,18 @@
 
 int video1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct video_card *video = NULL;
-	struct ti_ohci *ohci;
+	struct file_ctx *ctx = (struct file_ctx *)file->private_data;
+	struct video_card *video = ctx->video;
+	struct ti_ohci *ohci = video->ohci;
 	int res = -EINVAL;
-	unsigned long flags;
-	struct list_head *lh;
-
-        spin_lock_irqsave(&video1394_cards_lock, flags);
-        if (!list_empty(&video1394_cards)) {
-		struct video_card *p;
-		list_for_each(lh, &video1394_cards) {
-			p = list_entry(lh, struct video_card, list);
-			if (p->id == ieee1394_file_to_instance(file)) {
-				video = p;
-				break;
-			}
-                }
-        }
-        spin_unlock_irqrestore(&video1394_cards_lock, flags);
-
-	if (video == NULL) {
-		PRINT_G(KERN_ERR, "%s: Unknown video card for minor %d",
-			__FUNCTION__, ieee1394_file_to_instance(file));
-		return -EFAULT;
-	}
 
 	lock_kernel();
 	ohci = video->ohci;
 
-	if (video->current_ctx == NULL) {
+	if (ctx->current_ctx == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Current iso context not set");
 	} else
-		res = do_iso_mmap(vma, ohci, video->current_ctx, 
-			   (char *)vma->vm_start, 
-			   (unsigned long)(vma->vm_end-vma->vm_start));
+		res = do_iso_mmap(ohci, ctx->current_ctx, vma);
 	unlock_kernel();
 	return res;
 }
@@ -1366,16 +1340,14 @@
 	unsigned long flags;
 	struct video_card *video = NULL;
 	struct list_head *lh;
+	struct file_ctx *ctx;
 
 	spin_lock_irqsave(&video1394_cards_lock, flags);
-	if (!list_empty(&video1394_cards)) {
-		struct video_card *p;
-		list_for_each(lh, &video1394_cards) {
-			p = list_entry(lh, struct video_card, list);
-			if (p->id == i) {
-				video = p;
-				break;
-			}
+	list_for_each(lh, &video1394_cards) {
+		struct video_card *p = list_entry(lh, struct video_card, list);
+		if (p->id == i) {
+			video = p;
+			break;
 		}
 	}
 	spin_unlock_irqrestore(&video1394_cards_lock, flags);
@@ -1383,76 +1355,50 @@
         if (video == NULL)
                 return -EIO;
 
-	V22_COMPAT_MOD_INC_USE_COUNT;
+	ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL);
+	if (ctx == NULL)  {
+		PRINT(KERN_ERR, video->ohci->id, "Cannot malloc file_ctx");
+		return -ENOMEM;
+	}
+
+	memset(ctx, 0, sizeof(struct file_ctx));
+	ctx->video = video;
+	INIT_LIST_HEAD(&ctx->context_list);
+	ctx->current_ctx = NULL;
+	file->private_data = ctx;
 
 	return 0;
 }
 
 static int video1394_release(struct inode *inode, struct file *file)
 {
-	struct video_card *video = NULL;
-	struct ti_ohci *ohci;
+	struct file_ctx *ctx = (struct file_ctx *)file->private_data;
+	struct video_card *video = ctx->video;
+	struct ti_ohci *ohci = video->ohci;
+	struct list_head *lh, *next;
 	u64 mask;
-	int i;
-	unsigned long flags;
-	struct list_head *lh;
-
-        spin_lock_irqsave(&video1394_cards_lock, flags);
-        if (!list_empty(&video1394_cards)) {
-		struct video_card *p;
-		list_for_each(lh, &video1394_cards) {
-			p = list_entry(lh, struct video_card, list);
-			if (p->id == ieee1394_file_to_instance(file)) {
-				video = p;
-				break;
-			}
-		}
-	}
-        spin_unlock_irqrestore(&video1394_cards_lock, flags);
 
-	if (video == NULL) {
-		PRINT_G(KERN_ERR, "%s: Unknown device for minor %d",
-			__FUNCTION__, ieee1394_file_to_instance(file));
-		return 1;
+	lock_kernel();
+	list_for_each_safe(lh, next, &ctx->context_list) {
+		struct dma_iso_ctx *d;
+		d = list_entry(lh, struct dma_iso_ctx, link);
+		mask = (u64) 1 << d->channel;
+		
+		if (!(ohci->ISO_channel_usage & mask))
+			PRINT(KERN_ERR, ohci->id, "On release: Channel %d "
+			      "is not being used", d->channel);
+		else
+			ohci->ISO_channel_usage &= ~mask;
+		PRINT(KERN_INFO, ohci->id, "On release: Iso %s context "
+		      "%d stop listening on channel %d",
+		      d->type == ISO_RECEIVE ? "receive" : "transmit",
+		      d->ctx, d->channel);
+		free_dma_iso_ctx(d);
 	}
 
-	ohci = video->ohci;
-
-	lock_kernel();
-	for (i=0;i<ohci->nb_iso_rcv_ctx-1;i++) 
-		if (video->ir_context[i]) {
-			mask = (u64)0x1<<video->ir_context[i]->channel;
-			if (!(ohci->ISO_channel_usage & mask))
-				PRINT(KERN_ERR, ohci->id, 
-				      "On release: Channel %d is not being used", 
-				      video->ir_context[i]->channel);
-			else
-				ohci->ISO_channel_usage &= ~mask;
-			PRINT(KERN_INFO, ohci->id, 
-			      "Iso receive context %d stop listening "
-			      "on channel %d", video->ir_context[i]->ctx,
-			      video->ir_context[i]->channel);
-			free_dma_iso_ctx(&video->ir_context[i]);
-		}
+	kfree(ctx);
+	file->private_data = NULL;
 	
-	for (i=0;i<ohci->nb_iso_xmit_ctx;i++) 
-		if (video->it_context[i]) {
-			mask = (u64)0x1<<video->it_context[i]->channel;
-			if (!(ohci->ISO_channel_usage & mask))
-				PRINT(KERN_ERR, ohci->id, 
-				      "Channel %d is not being used", 
-				      video->it_context[i]->channel);
-			else
-				ohci->ISO_channel_usage &= ~mask;
-			PRINT(KERN_INFO, ohci->id, 
-			      "Iso transmit context %d stop talking "
-			      "on channel %d", video->it_context[i]->ctx,
-			      video->it_context[i]->channel);
-			free_dma_iso_ctx(&video->it_context[i]);
-		}
-
-	V22_COMPAT_MOD_DEC_USE_COUNT;
-
 	unlock_kernel();
 	return 0;
 }
@@ -1460,32 +1406,20 @@
 static void irq_handler(int card, quadlet_t isoRecvIntEvent, 
 			quadlet_t isoXmitIntEvent, void *data)
 {
-	int i;
-	struct video_card *video = (struct video_card*) data;
+	struct dma_iso_ctx *d = (struct dma_iso_ctx *) data;
 
-	if (video == NULL) {
-		PRINT_G(KERN_ERR, "%s: Unknown card number %d",
-			__FUNCTION__, card);
-		return;
-	}
-	
 	DBGMSG(card, "Iso event Recv: %08x Xmit: %08x",
 	       isoRecvIntEvent, isoXmitIntEvent);
 
-	for (i = 0; i < video->ohci->nb_iso_rcv_ctx-1; i++)
-		if (video->ir_context[i] != NULL &&
-		    isoRecvIntEvent & (1<<(video->ir_context[i]->ctx)))
-			wakeup_dma_ir_ctx(video->ohci, video->ir_context[i]);
-
-	for (i = 0; i < video->ohci->nb_iso_xmit_ctx; i++)
-		if (video->it_context[i] != NULL &&
-		    isoXmitIntEvent & (1<<(video->it_context[i]->ctx)))
-			wakeup_dma_it_ctx(video->ohci, video->it_context[i]);
+	if (d->type == ISO_RECEIVE && isoRecvIntEvent & (1 << d->ctx))
+		wakeup_dma_ir_ctx(d->ohci, d);
+	if (d->type == ISO_TRANSMIT && isoXmitIntEvent & (1 << d->ctx))
+		wakeup_dma_it_ctx(d->ohci, d);
 }
 
 static struct file_operations video1394_fops=
 {
-        OWNER_THIS_MODULE
+	owner:		THIS_MODULE,
 	ioctl:		video1394_ioctl,
 	mmap:		video1394_mmap,
 	open:		video1394_open,
@@ -1494,10 +1428,12 @@
 
 static int video1394_init(struct ti_ohci *ohci)
 {
-	struct video_card *video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
+	struct video_card *video;
 	unsigned long flags;
 	char name[16];
+	int minor;
 
+	video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
 	if (video == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Cannot allocate video_card");
 		return -1;
@@ -1510,43 +1446,14 @@
 	list_add_tail(&video->list, &video1394_cards);
 	spin_unlock_irqrestore(&video1394_cards_lock, flags);
 
-	if (ohci1394_hook_irq(ohci, irq_handler, (void*) video) != 0) {
-		PRINT(KERN_ERR, ohci->id, "ohci1394_hook_irq() failed");
-		return -1;
-	}
-
 	video->id = ohci->id;
 	video->ohci = ohci;
 
-	/* Iso receive dma contexts */
-	video->ir_context = (struct dma_iso_ctx **)
-		kmalloc((ohci->nb_iso_rcv_ctx-1)*
-			sizeof(struct dma_iso_ctx *), GFP_KERNEL);
-	if (video->ir_context) 
-		memset(video->ir_context, 0,
-		       (ohci->nb_iso_rcv_ctx-1)*sizeof(struct dma_iso_ctx *));
-	else {
-		PRINT(KERN_ERR, ohci->id, "Cannot allocate ir_context");
-		return -1;
-	}
-
-	/* Iso transmit dma contexts */
-	video->it_context = (struct dma_iso_ctx **)
-		kmalloc(ohci->nb_iso_xmit_ctx *
-			sizeof(struct dma_iso_ctx *), GFP_KERNEL);
-	if (video->it_context) 
-		memset(video->it_context, 0,
-		       ohci->nb_iso_xmit_ctx * sizeof(struct dma_iso_ctx *));
-	else {
-		PRINT(KERN_ERR, ohci->id, "Cannot allocate it_context");
-		return -1;
-	}
-
 	sprintf(name, "%d", video->id);
+	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + video->id;
 	video->devfs = devfs_register(devfs_handle, name,
 				      DEVFS_FL_AUTO_OWNER,
-				      IEEE1394_MAJOR,
-				      IEEE1394_MINOR_BLOCK_VIDEO1394*16+video->id,
+				      IEEE1394_MAJOR, minor,
 				      S_IFCHR | S_IRUSR | S_IWUSR,
 				      &video1394_fops, NULL);
 
@@ -1556,27 +1463,7 @@
 /* Must be called under spinlock */
 static void remove_card(struct video_card *video)
 {
-	int i;
-
-	ohci1394_unhook_irq(video->ohci, irq_handler, (void*) video);
-
 	devfs_unregister(video->devfs);
-
-	/* Free the iso receive contexts */
-	if (video->ir_context) {
-		for (i=0;i<video->ohci->nb_iso_rcv_ctx-1;i++) {
-			free_dma_iso_ctx(&video->ir_context[i]);
-		}
-		kfree(video->ir_context);
-	}
-
-	/* Free the iso transmit contexts */
-	if (video->it_context) {
-		for (i=0;i<video->ohci->nb_iso_xmit_ctx;i++) {
-			free_dma_iso_ctx(&video->it_context[i]);
-		}
-		kfree(video->it_context);
-	}
 	list_del(&video->list);
 
 	kfree(video);
diff -Nru a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c
--- a/drivers/isdn/avmb1/capifs.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/isdn/avmb1/capifs.c	Sun Apr 14 12:16:56 2002
@@ -235,10 +235,9 @@
 	unsigned int maxncci = 512;
 	char *this_char, *value;
 
-	this_char = NULL;
-	if ( options )
-		this_char = strtok(options,",");
-	for ( ; this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
 		if (!strcmp(this_char,"uid")) {
diff -Nru a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c
--- a/drivers/isdn/avmb1/kcapi.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/isdn/avmb1/kcapi.c	Sun Apr 14 12:16:59 2002
@@ -102,8 +102,8 @@
 #define APPL(a)		   (&applications[(a)-1])
 #define	VALID_APPLID(a)	   ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
 #define APPL_IS_FREE(a)    (APPL(a)->applid == 0)
-#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
-#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
+#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0)
+#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0)
 
 #define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
 
diff -Nru a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c
--- a/drivers/isdn/eicon/eicon_mod.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/isdn/eicon/eicon_mod.c	Sun Apr 14 12:16:55 2002
@@ -665,8 +665,11 @@
 			else
 				cnt = skb->len;
 
-			if (user)
+			if (user) {
+				spin_unlock_irqrestore(&eicon_lock, flags);
 				copy_to_user(p, skb->data, cnt);
+				spin_lock_irqsave(&eicon_lock, flags);
+			}
 			else
 				memcpy(p, skb->data, cnt);
 
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	Sun Apr 14 12:16:56 2002
@@ -65,6 +65,7 @@
 
 static int protocol = 2;       /* EURO-ISDN Default */
 MODULE_PARM(protocol, "i");
+MODULE_LICENSE("GPL");
 
 // ----------------------------------------------------------------------
 
diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c
--- a/drivers/isdn/hisax/hisax_isac.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/isdn/hisax/hisax_isac.c	Sun Apr 14 12:16:55 2002
@@ -44,6 +44,7 @@
 
 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
 MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
+MODULE_LICENSE("GPL");
 
 #define DBG_WARN      0x0001
 #define DBG_IRQ       0x0002
diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
--- a/drivers/macintosh/adb.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/macintosh/adb.c	Sun Apr 14 12:16:58 2002
@@ -77,7 +77,7 @@
 static int adb_got_sleep = 0;
 static int adb_inited = 0;
 static pid_t adb_probe_task_pid;
-static int adb_probe_task_flag;
+static unsigned long adb_probe_task_flag;
 static wait_queue_head_t adb_probe_task_wq;
 static int sleepy_trackpad;
 int __adb_probe_sync;
@@ -439,7 +439,7 @@
 }
 
 static struct adb_request adb_sreq;
-static int adb_sreq_lock; // Use semaphore ! */ 
+static unsigned long adb_sreq_lock; // Use semaphore ! */ 
 
 int
 adb_request(struct adb_request *req, void (*done)(struct adb_request *),
diff -Nru a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c
--- a/drivers/md/lvm-snap.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/md/lvm-snap.c	Sun Apr 14 12:16:59 2002
@@ -302,6 +302,7 @@
 {
 	const char * reason;
 	kdev_t snap_phys_dev;
+	struct block_device *org_bdev, *snap_bdev;
 	unsigned long org_start, snap_start, virt_start, pe_off;
 	int idx = lv_snap->u.lv_remap_ptr, chunk_size = lv_snap->u.lv_chunk_size;
 	struct kiobuf * iobuf;
@@ -321,6 +322,15 @@
 	snap_phys_dev = lv_snap->u.lv_block_exception[idx].rdev_new;
 	snap_start = lv_snap->u.lv_block_exception[idx].rsector_new;
 
+	org_bdev = bdget(kdev_t_to_nr(org_phys_dev));
+	if (!org_bdev)
+		goto fail_enomem;
+	snap_bdev = bdget(kdev_t_to_nr(snap_phys_dev));
+	if (!snap_bdev) {
+		bdput(org_bdev);
+		goto fail_enomem;
+	}
+
 #ifdef DEBUG_SNAPSHOT
 	printk(KERN_INFO
 	       "%s -- COW: "
@@ -356,7 +366,7 @@
 						nr_sectors, blksize_org))
 			goto fail_prepare;
 
-		if (brw_kiovec(READ, 1, &iobuf, org_phys_dev,
+		if (brw_kiovec(READ, 1, &iobuf, org_bdev,
 			       lv_snap->blocks, blksize_org) != (nr_sectors<<9))
 			goto fail_raw_read;
 
@@ -364,7 +374,7 @@
 						nr_sectors, blksize_snap))
 			goto fail_prepare;
 
-		if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
+		if (brw_kiovec(WRITE, 1, &iobuf, snap_bdev,
 			       lv_snap->blocks, blksize_snap) !=(nr_sectors<<9))
 			goto fail_raw_write;
 	}
@@ -387,16 +397,21 @@
 		if (lv_snap->u.lv_remap_ptr * 100 / lv_snap->u.lv_remap_end >= lv_snap->lv_snapshot_use_rate)
 			wake_up_interruptible(&lv_snap->lv_snapshot_wait);
 	}
+	bdput(snap_bdev);
+	bdput(org_bdev);
 	return 0;
 
 	/* slow path */
  out:
+	bdput(snap_bdev);
+	bdput(org_bdev);
+ out1:
 	lvm_drop_snapshot(vg, lv_snap, reason);
 	return 1;
 
  fail_out_of_space:
 	reason = "out of space";
-	goto out;
+	goto out1;
  fail_raw_read:
 	reason = "read error";
 	goto out;
@@ -405,7 +420,9 @@
 	goto out;
  fail_blksize:
 	reason = "blocksize error";
-	goto out;
+ fail_enomem:
+	reason = "out of memory";
+	goto out1;
 
  fail_prepare:
 	reason = "couldn't prepare kiovec blocks "
@@ -569,6 +586,7 @@
 		COW_entries_per_pe, COW_chunks_per_pe, COW_entries_per_block;
 	ulong blocks[1];
 	kdev_t snap_phys_dev;
+	struct block_device *bdev;
 	lv_block_exception_t *be;
 	struct kiobuf * COW_table_iobuf = lv_snap->lv_COW_table_iobuf;
 	lv_COW_table_disk_t * lv_COW_table =
@@ -581,6 +599,8 @@
 	snap_phys_dev = lv_snap->u.lv_block_exception[idx].rdev_new;
 	snap_pe_start = lv_snap->u.lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->u.lv_chunk_size;
 
+	bdev = bdget(kdev_t_to_nr(snap_phys_dev));
+
 	blksize_snap = block_size(snap_phys_dev);
 
         COW_entries_per_block = blksize_snap / sizeof(lv_COW_table_disk_t);
@@ -611,7 +631,7 @@
 
 	COW_table_iobuf->length = blksize_snap;
 
-	if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
+	if (brw_kiovec(WRITE, 1, &COW_table_iobuf, bdev,
 		       blocks, blksize_snap) != blksize_snap)
 		goto fail_raw_write;
 
@@ -629,25 +649,30 @@
 			idx++;
 			snap_phys_dev = lv_snap->u.lv_block_exception[idx].rdev_new;
 			snap_pe_start = lv_snap->u.lv_block_exception[idx - (idx % COW_entries_per_pe)].rsector_new - lv_snap->u.lv_chunk_size;
+			bdput(bdev);
+			bdev = bdget(kdev_t_to_nr(snap_phys_dev));
 			blksize_snap = block_size(snap_phys_dev);
 			blocks[0] = snap_pe_start >> (blksize_snap >> 10);
 		} else blocks[0]++;
 
-               if (brw_kiovec(WRITE, 1, &COW_table_iobuf, snap_phys_dev,
+               if (brw_kiovec(WRITE, 1, &COW_table_iobuf, bdev,
                                  blocks, blksize_snap) !=
                     blksize_snap)
 			goto fail_raw_write;
 	}
 
  out:
+	bdput(bdev);
 	return 0;
 
  fail_raw_write:
 	*reason = "write error";
+	bdput(bdev);
 	return 1;
 
  fail_pv_get_number:
 	*reason = "_pv_get_number failed";
+	bdput(bdev);
 	return 1;
 }
 
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/md/md.c	Sun Apr 14 12:16:57 2002
@@ -283,10 +283,7 @@
 static unsigned int calc_dev_sboffset(kdev_t dev, mddev_t *mddev,
 						int persistent)
 {
-	unsigned int size = 0;
-
-	if (blk_size[major(dev)])
-		size = blk_size[major(dev)][minor(dev)];
+	unsigned int size = (blkdev_size_in_bytes(dev) >> BLOCK_SIZE_BITS);
 	if (persistent)
 		size = MD_NEW_SIZE_BLOCKS(size);
 	return size;
@@ -1106,12 +1103,11 @@
 	rdev->desc_nr = -1;
 	rdev->faulty = 0;
 
-	size = 0;
-	if (blk_size[major(newdev)])
-		size = blk_size[major(newdev)][minor(newdev)];
+	size = (blkdev_size_in_bytes(newdev) >> BLOCK_SIZE_BITS);
 	if (!size) {
-		printk(KERN_WARNING "md: %s has zero size, marking faulty!\n",
-				partition_name(newdev));
+		printk(KERN_WARNING
+		       "md: %s has zero or unknown size, marking faulty!\n",
+		       partition_name(newdev));
 		err = -EINVAL;
 		goto abort_free;
 	}
@@ -1581,7 +1577,7 @@
 	if (!md_size[mdidx(mddev)])
 		md_size[mdidx(mddev)] = sb->size * data_disks;
 
-	readahead = MD_READAHEAD;
+	readahead = (blk_get_readahead(rdev->dev) * 512) / PAGE_SIZE;
 	if (!sb->level || (sb->level == 4) || (sb->level == 5)) {
 		readahead = (mddev->sb->chunk_size>>PAGE_SHIFT) * 4 * data_disks;
 		if (readahead < data_disks * (MAX_SECTORS>>(PAGE_SHIFT-9))*2)
@@ -3391,7 +3387,7 @@
 	/*
 	 * Tune reconstruction:
 	 */
-	window = MAX_READAHEAD*(PAGE_SIZE/512);
+	window = 32*(PAGE_SIZE/512);
 	printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",
 	       window/2,max_sectors/2);
 
@@ -3609,7 +3605,7 @@
 	for(i = 0; i < MAX_MD_DEVS; i++) {
 		md_blocksizes[i] = 1024;
 		md_size[i] = 0;
-		md_maxreadahead[i] = MD_READAHEAD;
+		md_maxreadahead[i] = 32;
 	}
 	blksize_size[MAJOR_NR] = md_blocksizes;
 	blk_size[MAJOR_NR] = md_size;
@@ -3768,7 +3764,7 @@
 		printk(KERN_WARNING "md: md=%d, Minor device number too high.\n", minor);
 		return 0;
 	} else if (md_setup_args.device_names[minor]) {
-		printk(KERN_WARNING "md: md=%d, Specified more then once. "
+		printk(KERN_WARNING "md: md=%d, Specified more than once. "
 		       "Replacing previous definition.\n", minor);
 	}
 	switch (get_option(&str, &level)) {	/* RAID Personality */
diff -Nru a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
--- a/drivers/media/radio/miropcm20-radio.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/media/radio/miropcm20-radio.c	Sun Apr 14 12:16:56 2002
@@ -121,8 +121,8 @@
 	return 0;
 }
 
-static int pcm20_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+static int pcm20_do_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct pcm20_device *pcm20 = dev->priv;
@@ -210,6 +210,12 @@
 	}
 }
 
+static int pcm20_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, pcm20_do_ioctl);
+}
+
 static struct pcm20_device pcm20_unit = {
 	freq:   87*16000,
 	muted:  1,
@@ -220,7 +226,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		pcm20_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -230,7 +236,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_RTRACK,
 	fops:           &pcm20_fops,
-	kernel_ioctl:	pcm20_ioctl,
 	priv:		&pcm20_unit
 };
 
diff -Nru a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
--- a/drivers/media/radio/radio-aimslab.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/media/radio/radio-aimslab.c	Sun Apr 14 12:16:56 2002
@@ -213,8 +213,8 @@
 	return 1;		/* signal present		*/
 }
 
-static int rt_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, void *arg)
+static int rt_do_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct rt_device *rt=dev->priv;
@@ -291,13 +291,19 @@
 	}
 }
 
+static int rt_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, rt_do_ioctl);
+}
+
 static struct rt_device rtrack_unit;
 
 static struct file_operations rtrack_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:	        rt_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -308,7 +314,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_RTRACK,
 	fops:           &rtrack_fops,
-	kernel_ioctl:	rt_ioctl,
 };
 
 static int __init rtrack_init(void)
diff -Nru a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
--- a/drivers/media/radio/radio-aztech.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/media/radio/radio-aztech.c	Sun Apr 14 12:16:59 2002
@@ -157,8 +157,8 @@
 	return 0;
 }
 
-static int az_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, void *arg)
+static int az_do_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct az_device *az = dev->priv;
@@ -243,13 +243,19 @@
 	}
 }
 
+static int az_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, az_do_ioctl);
+}
+
 static struct az_device aztech_unit;
 
 static struct file_operations aztech_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		az_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -260,7 +266,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_AZTECH,
 	fops:           &aztech_fops,
-	kernel_ioctl:   az_ioctl,
 };
 
 static int __init aztech_init(void)
diff -Nru a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
--- a/drivers/media/radio/radio-cadet.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/media/radio/radio-cadet.c	Sun Apr 14 12:16:58 2002
@@ -384,8 +384,8 @@
 
 
 
-static int cadet_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+static int cadet_do_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, void *arg)
 {
 	switch(cmd)
 	{
@@ -497,6 +497,11 @@
 	}
 }
 
+static int cadet_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl);
+}
 
 static int cadet_open(struct inode *inode, struct file *file)
 {
@@ -523,7 +528,7 @@
 	open:		cadet_open,
 	release:       	cadet_release,
 	read:		cadet_read,
-	ioctl:		video_generic_ioctl,
+	ioctl:		cadet_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -534,7 +539,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_CADET,
 	fops:           &cadet_fops,
-	kernel_ioctl:	cadet_ioctl,
 };
 
 static int isapnp_cadet_probe(void)
diff -Nru a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
--- a/drivers/media/radio/radio-gemtek-pci.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/media/radio/radio-gemtek-pci.c	Sun Apr 14 12:16:55 2002
@@ -177,8 +177,8 @@
 	return ( inb( card->iobase ) & 0x08 ) ? 0 : 1;
 }
 
-static int gemtek_pci_ioctl(struct inode *inode, struct file *file,
-			    unsigned int cmd, void *arg)
+static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
+			       unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct gemtek_pci_card *card = dev->priv;
@@ -272,6 +272,12 @@
 	}
 }
 
+static int gemtek_pci_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, gemtek_pci_do_ioctl);
+}
+
 enum {
 	GEMTEK_PR103
 };
@@ -295,7 +301,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		gemtek_pci_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -305,7 +311,6 @@
 	type:          VID_TYPE_TUNER,
 	hardware:      VID_HARDWARE_GEMTEK,
 	fops:          &gemtek_pci_fops,
-	kernel_ioctl:  gemtek_pci_ioctl,
 };
 
 static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
@@ -385,7 +390,7 @@
     name:	"gemtek_pci",
 id_table:	gemtek_pci_id,
    probe:	gemtek_pci_probe,
-  remove:	__devexit_p(gemtek_pci_remove)
+  remove:	__devexit_p(gemtek_pci_remove),
 };
 
 static int __init gemtek_pci_init_module( void )
diff -Nru a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
--- a/drivers/media/radio/radio-gemtek.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/media/radio/radio-gemtek.c	Sun Apr 14 12:16:54 2002
@@ -138,8 +138,8 @@
 	return 1;		/* signal present */
 }
 
-static int gemtek_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, void *arg)
+static int gemtek_do_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct gemtek_device *rt=dev->priv;
@@ -220,13 +220,19 @@
 	}
 }
 
+static int gemtek_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, gemtek_do_ioctl);
+}
+
 static struct gemtek_device gemtek_unit;
 
 static struct file_operations gemtek_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		gemtek_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -237,7 +243,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_GEMTEK,
 	fops:           &gemtek_fops,
-	kernel_ioctl:	gemtek_ioctl,
 };
 
 static int __init gemtek_init(void)
diff -Nru a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
--- a/drivers/media/radio/radio-maestro.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/media/radio/radio-maestro.c	Sun Apr 14 12:16:59 2002
@@ -65,13 +65,13 @@
 MODULE_PARM(radio_nr, "i");
 
 static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg);
+		       unsigned int cmd, unsigned long arg);
 
 static struct file_operations maestro_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		radio_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -82,7 +82,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_SF16MI,
 	fops:           &maestro_fops,
-	kernel_ioctl:	radio_ioctl,
 };
 
 static struct radio_device
@@ -175,10 +174,12 @@
 	sleep_125ms();
 }
 
-inline static int radio_function(struct video_device *dev, 
+inline static int radio_function(struct inode *inode, struct file *file,
 				 unsigned int cmd, void *arg)
 {
+	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
+	
 	switch(cmd) {
 		case VIDIOCGCAP: {
 			struct video_capability *v = arg;
@@ -257,13 +258,14 @@
 }
 
 static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+		       unsigned int cmd, unsigned long arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
 	int ret;
+
 	down(&card->lock);
-	ret = radio_function(dev, cmd, arg);
+	ret = video_usercopy(inode, file, cmd, arg, radio_function);
 	up(&card->lock);
 	return ret;
 }
diff -Nru a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
--- a/drivers/media/radio/radio-maxiradio.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/media/radio/radio-maxiradio.c	Sun Apr 14 12:16:57 2002
@@ -73,13 +73,13 @@
 
 
 static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg);
+		       unsigned int cmd, unsigned long arg);
 
 static struct file_operations maxiradio_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:	        radio_ioctl,
 	llseek:         no_llseek,
 };
 static struct video_device maxiradio_radio =
@@ -89,7 +89,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_SF16MI,
 	fops:           &maxiradio_fops,
-	kernel_ioctl:	radio_ioctl,
 };
 
 static struct radio_device
@@ -174,9 +173,10 @@
 }
 
 
-inline static int radio_function(struct video_device *dev,
+inline static int radio_function(struct inode *inode, struct file *file,
 				 unsigned int cmd, void *arg)
 {
+	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
 
 	switch(cmd) {
@@ -267,14 +267,14 @@
 }
 
 static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+		       unsigned int cmd, unsigned long arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
 	int ret;
 	
 	down(&card->lock);
-	ret = radio_function(dev, cmd, arg);
+	ret = video_usercopy(inode, file, cmd, arg, radio_function);
 	up(&card->lock);
 	return ret;
 }
diff -Nru a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
--- a/drivers/media/radio/radio-rtrack2.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/media/radio/radio-rtrack2.c	Sun Apr 14 12:16:55 2002
@@ -106,8 +106,8 @@
 	return 1;		/* signal present		*/
 }
 
-static int rt_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, void *arg)
+static int rt_do_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct rt_device *rt=dev->priv;
@@ -186,13 +186,19 @@
 	}
 }
 
+static int rt_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, rt_do_ioctl);
+}
+
 static struct rt_device rtrack2_unit;
 
 static struct file_operations rtrack2_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		rt_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -203,7 +209,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_RTRACK2,
 	fops:           &rtrack2_fops,
-	kernel_ioctl:   rt_ioctl,
 };
 
 static int __init rtrack2_init(void)
diff -Nru a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
--- a/drivers/media/radio/radio-sf16fmi.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/media/radio/radio-sf16fmi.c	Sun Apr 14 12:16:57 2002
@@ -132,8 +132,8 @@
 	return (res & 2) ? 0 : 0xFFFF;
 }
 
-static int fmi_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, void *arg)
+static int fmi_do_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct fmi_device *fmi=dev->priv;
@@ -230,13 +230,19 @@
 	}
 }
 
+static int fmi_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, fmi_do_ioctl);
+}
+
 static struct fmi_device fmi_unit;
 
 static struct file_operations fmi_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		fmi_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -247,7 +253,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_SF16MI,
 	fops:           &fmi_fops,
-	kernel_ioctl:   fmi_ioctl,
 };
 
 /* ladis: this is my card. does any other types exist? */
diff -Nru a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
--- a/drivers/media/radio/radio-terratec.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/media/radio/radio-terratec.c	Sun Apr 14 12:16:58 2002
@@ -185,8 +185,8 @@
 
 /* implement the video4linux api */
 
-static int tt_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, void *arg)
+static int tt_do_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct tt_device *tt=dev->priv;
@@ -263,13 +263,19 @@
 	}
 }
 
+static int tt_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, tt_do_ioctl);
+}
+
 static struct tt_device terratec_unit;
 
 static struct file_operations terratec_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		tt_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -280,7 +286,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_TERRATEC,
 	fops:           &terratec_fops,
-	kernel_ioctl:	tt_ioctl,
 };
 
 static int __init terratec_init(void)
diff -Nru a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
--- a/drivers/media/radio/radio-trust.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/media/radio/radio-trust.c	Sun Apr 14 12:16:58 2002
@@ -154,8 +154,8 @@
 	write_i2c(5, TSA6060T_ADDR, (f << 1) | 1, f >> 7, 0x60 | ((f >> 15) & 1), 0);
 }
 
-static int tr_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, void *arg)
+static int tr_do_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, void *arg)
 {
 	switch(cmd)
 	{
@@ -244,11 +244,17 @@
 	}
 }
 
+static int tr_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, tr_do_ioctl);
+}
+
 static struct file_operations trust_fops = {
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		tr_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -259,7 +265,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_TRUST,
 	fops:           &trust_fops,
-	kernel_ioctl:	tr_ioctl,
 };
 
 static int __init trust_init(void)
diff -Nru a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
--- a/drivers/media/radio/radio-typhoon.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/media/radio/radio-typhoon.c	Sun Apr 14 12:16:57 2002
@@ -70,7 +70,7 @@
 static void typhoon_unmute(struct typhoon_device *dev);
 static int typhoon_setvol(struct typhoon_device *dev, int vol);
 static int typhoon_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg);
+			 unsigned int cmd, unsigned long arg);
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
 #endif
@@ -163,8 +163,8 @@
 }
 
 
-static int typhoon_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg)
+static int typhoon_do_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct typhoon_device *typhoon = dev->priv;
@@ -243,6 +243,12 @@
 	}
 }
 
+static int typhoon_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, typhoon_do_ioctl);
+}
+
 static struct typhoon_device typhoon_unit =
 {
 	iobase:		CONFIG_RADIO_TYPHOON_PORT,
@@ -254,7 +260,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:		video_generic_ioctl,
+	ioctl:		typhoon_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -265,7 +271,6 @@
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_TYPHOON,
 	fops:           &typhoon_fops,
-	kernel_ioctl:	typhoon_ioctl,
 };
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
diff -Nru a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
--- a/drivers/media/radio/radio-zoltrix.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/media/radio/radio-zoltrix.c	Sun Apr 14 12:16:58 2002
@@ -40,7 +40,6 @@
 
 static int io = CONFIG_RADIO_ZOLTRIX_PORT;
 static int radio_nr = -1;
-static int users = 0;
 
 struct zol_device {
 	int port;
@@ -216,106 +215,93 @@
 	return 0;
 }
 
-static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+static int zol_do_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, void *arg)
 {
+	struct video_device *dev = video_devdata(file);
 	struct zol_device *zol = dev->priv;
 
 	switch (cmd) {
 	case VIDIOCGCAP:
 		{
-			struct video_capability v;
-			v.type = VID_TYPE_TUNER;
-			v.channels = 1 + zol->stereo;
-			v.audios = 1;
-			/* No we don't do pictures */
-			v.maxwidth = 0;
-			v.maxheight = 0;
-			v.minwidth = 0;
-			v.minheight = 0;
-			strcpy(v.name, "Zoltrix Radio");
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
+			struct video_capability *v = arg;
+
+			memset(v,0,sizeof(*v));
+			v->type = VID_TYPE_TUNER;
+			v->channels = 1 + zol->stereo;
+			v->audios = 1;
+			strcpy(v->name, "Zoltrix Radio");
 			return 0;
 		}
 	case VIDIOCGTUNER:
 		{
-			struct video_tuner v;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if (v.tuner)	
+			struct video_tuner *v = arg;
+			if (v->tuner)	
 				return -EINVAL;
-			strcpy(v.name, "FM");
-			v.rangelow = (int) (88.0 * 16000);
-			v.rangehigh = (int) (108.0 * 16000);
-			v.flags = zol_is_stereo(zol)
+			strcpy(v->name, "FM");
+			v->rangelow = (int) (88.0 * 16000);
+			v->rangehigh = (int) (108.0 * 16000);
+			v->flags = zol_is_stereo(zol)
 					? VIDEO_TUNER_STEREO_ON : 0;
-			v.flags |= VIDEO_TUNER_LOW;
-			v.mode = VIDEO_MODE_AUTO;
-			v.signal = 0xFFFF * zol_getsigstr(zol);
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
+			v->flags |= VIDEO_TUNER_LOW;
+			v->mode = VIDEO_MODE_AUTO;
+			v->signal = 0xFFFF * zol_getsigstr(zol);
 			return 0;
 		}
 	case VIDIOCSTUNER:
 		{
-			struct video_tuner v;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if (v.tuner != 0)
+			struct video_tuner *v = arg;
+			if (v->tuner != 0)
 				return -EINVAL;
 			/* Only 1 tuner so no setting needed ! */
 			return 0;
 		}
 	case VIDIOCGFREQ:
-		if (copy_to_user(arg, &zol->curfreq, sizeof(zol->curfreq)))
-			return -EFAULT;
+	{
+		unsigned long *freq = arg;
+		*freq = zol->curfreq;
 		return 0;
+	}
 	case VIDIOCSFREQ:
-		if (copy_from_user(&zol->curfreq, arg, sizeof(zol->curfreq)))
-			return -EFAULT;
+	{
+		unsigned long *freq = arg;
+		zol->curfreq = *freq;
 		zol_setfreq(zol, zol->curfreq);
 		return 0;
+	}
 	case VIDIOCGAUDIO:
 		{
-			struct video_audio v;
-			memset(&v, 0, sizeof(v));
-			v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
-			v.mode != zol_is_stereo(zol)
+			struct video_audio *v = arg;
+			memset(&v, 0, sizeof(*v));
+			v->flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
+			v->mode != zol_is_stereo(zol)
 				? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
-			v.volume = zol->curvol * 4096;
-			v.step = 4096;
-			strcpy(v.name, "Zoltrix Radio");
-			if (copy_to_user(arg, &v, sizeof(v)))
-				return -EFAULT;
+			v->volume = zol->curvol * 4096;
+			v->step = 4096;
+			strcpy(v->name, "Zoltrix Radio");
 			return 0;
 		}
 	case VIDIOCSAUDIO:
 		{
-			struct video_audio v;
-			if (copy_from_user(&v, arg, sizeof(v)))
-				return -EFAULT;
-			if (v.audio)
+			struct video_audio *v = arg;
+			if (v->audio)
 				return -EINVAL;
 
-			if (v.flags & VIDEO_AUDIO_MUTE)
+			if (v->flags & VIDEO_AUDIO_MUTE)
 				zol_mute(zol);
-			else
-			{
+			else {
 				zol_unmute(zol);
-				zol_setvol(zol, v.volume / 4096);
+				zol_setvol(zol, v->volume / 4096);
 			}
 
-			if (v.mode & VIDEO_SOUND_STEREO)
-			{
+			if (v->mode & VIDEO_SOUND_STEREO) {
 				zol->stereo = 1;
 				zol_setfreq(zol, zol->curfreq);
 			}
-			if (v.mode & VIDEO_SOUND_MONO)
-			{
+			if (v->mode & VIDEO_SOUND_MONO) {
 				zol->stereo = 0;
 				zol_setfreq(zol, zol->curfreq);
 			}
-
 			return 0;
 		}
 	default:
@@ -323,30 +309,30 @@
 	}
 }
 
-static int zol_open(struct video_device *dev, int flags)
-{
-	if (users)
-		return -EBUSY;
-	users++;
-	return 0;
-}
-
-static void zol_close(struct video_device *dev)
+static int zol_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
 {
-	users--;
+	return video_usercopy(inode, file, cmd, arg, zol_do_ioctl);
 }
 
 static struct zol_device zoltrix_unit;
 
+static struct file_operations zoltrix_fops =
+{
+	owner:		THIS_MODULE,
+	open:           video_exclusive_open,
+	release:        video_exclusive_release,
+	ioctl:		zol_ioctl,
+	llseek:         no_llseek,
+};
+
 static struct video_device zoltrix_radio =
 {
 	owner:		THIS_MODULE,
 	name:		"Zoltrix Radio Plus",
 	type:		VID_TYPE_TUNER,
 	hardware:	VID_HARDWARE_ZOLTRIX,
-	open:		zol_open,
-	close:		zol_close,
-	ioctl:		zol_ioctl,
+	fops:           &zoltrix_fops,
 };
 
 static int __init zoltrix_init(void)
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/media/video/bttv-driver.c	Sun Apr 14 12:16:56 2002
@@ -1650,8 +1650,8 @@
 	bttv_dma_free(fh->btv,buf);
 }
 
-static int bttv_ioctl(struct inode *inode, struct file *file,
-		      unsigned int cmd, void *arg)
+static int bttv_do_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, void *arg)
 {
 	struct bttv_fh *fh  = file->private_data;
 	struct bttv    *btv = fh->btv;
@@ -2432,6 +2432,12 @@
 	return retval;
 }
 
+static int bttv_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
+}
+
 /* start capture to a kernel bounce buffer */
 static int bttv_read_capture(struct bttv_fh *fh)
 {
@@ -2647,7 +2653,7 @@
 	owner:	  THIS_MODULE,
 	open:	  bttv_open,
 	release:  bttv_release,
-	ioctl:	  video_generic_ioctl,
+	ioctl:	  bttv_ioctl,
 	llseek:	  no_llseek,
 	read:	  bttv_read,
 	mmap:	  bttv_mmap,
@@ -2661,7 +2667,6 @@
 	          VID_TYPE_CLIPPING|VID_TYPE_SCALES,
 	hardware: VID_HARDWARE_BT848,
 	fops:     &bttv_fops,
-	kernel_ioctl: bttv_ioctl,
 	minor:    -1,
 };
 
@@ -2712,8 +2717,8 @@
 	return 0;
 }
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+static int radio_do_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, void *arg)
 {
 	struct bttv    *btv = file->private_data;
 
@@ -2763,12 +2768,18 @@
 	return 0;
 }
 
+static int radio_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
+}
+
 static struct file_operations radio_fops =
 {
 	owner:	  THIS_MODULE,
 	open:	  radio_open,
 	release:  radio_release,
-	ioctl:	  video_generic_ioctl,
+	ioctl:	  radio_ioctl,
 	llseek:	  no_llseek,
 };
 
@@ -2778,7 +2789,6 @@
 	type:     VID_TYPE_TUNER|VID_TYPE_TELETEXT,
 	hardware: VID_HARDWARE_BT848,
 	fops:     &radio_fops,
-	kernel_ioctl: radio_ioctl,
 	minor:    -1,
 };
 
diff -Nru a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
--- a/drivers/media/video/bttv-vbi.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/media/video/bttv-vbi.c	Sun Apr 14 12:16:59 2002
@@ -276,8 +276,8 @@
 	return 0;
 }
 
-static int vbi_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, void *arg)
+static int vbi_do_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, void *arg)
 {
 	struct bttv *btv = file->private_data;
 #ifdef HAVE_V4L2
@@ -507,6 +507,12 @@
 #endif
 }
 
+static int vbi_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, vbi_do_ioctl);
+}
+
 static ssize_t vbi_read(struct file *file, char *data,
 			size_t count, loff_t *ppos)
 {
@@ -634,7 +640,7 @@
 	owner:	  THIS_MODULE,
 	open:	  vbi_open,
 	release:  vbi_release,
-	ioctl:	  video_generic_ioctl,
+	ioctl:	  vbi_ioctl,
 	llseek:	  no_llseek,
 	read:	  vbi_read,
 	poll:	  vbi_poll,
@@ -647,7 +653,6 @@
 	type:     VID_TYPE_TUNER|VID_TYPE_TELETEXT,
 	hardware: VID_HARDWARE_BT848,
 	fops:     &vbi_fops,
-	kernel_ioctl: vbi_ioctl,
 	minor:    -1,
 };
 
diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
--- a/drivers/media/video/bw-qcam.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/media/video/bw-qcam.c	Sun Apr 14 12:16:56 2002
@@ -694,8 +694,8 @@
  *	Video4linux interfacing
  */
 
-static int qcam_ioctl(struct inode *inode, struct file *file,
-		      unsigned int cmd, void *arg)
+static int qcam_do_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -854,6 +854,12 @@
 	return 0;
 }
 
+static int qcam_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+}
+
 static int qcam_read(struct file *file, char *buf,
 		     size_t count, loff_t *ppos)
 {
@@ -882,7 +888,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:          video_generic_ioctl,
+	ioctl:          qcam_ioctl,
 	read:		qcam_read,
 	llseek:         no_llseek,
 };
@@ -893,7 +899,6 @@
 	type:		VID_TYPE_CAPTURE,
 	hardware:	VID_HARDWARE_QCAM_BW,
 	fops:           &qcam_fops,
-	kernel_ioctl:	qcam_ioctl,
 };
 
 #define MAX_CAMS 4
diff -Nru a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
--- a/drivers/media/video/c-qcam.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/media/video/c-qcam.c	Sun Apr 14 12:16:58 2002
@@ -496,8 +496,8 @@
  *	Video4linux interfacing
  */
 
-static int qcam_ioctl(struct inode *inode, struct file *file,
-		      unsigned int cmd, void *arg)
+static int qcam_do_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -662,6 +662,12 @@
 	return 0;
 }
 
+static int qcam_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+}
+
 static int qcam_read(struct file *file, char *buf,
 		     size_t count, loff_t *ppos)
 {
@@ -683,7 +689,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:          video_generic_ioctl,
+	ioctl:          qcam_ioctl,
 	read:		qcam_read,
 	llseek:         no_llseek,
 };
@@ -695,7 +701,6 @@
 	type:		VID_TYPE_CAPTURE,
 	hardware:	VID_HARDWARE_QCAM_C,
 	fops:           &qcam_fops,
-	kernel_ioctl:	qcam_ioctl,
 };
 
 /* Initialize the QuickCam driver control structure. */
diff -Nru a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
--- a/drivers/media/video/cpia.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/media/video/cpia.c	Sun Apr 14 12:16:59 2002
@@ -2572,8 +2572,8 @@
 	return cam->decompressed_frame.count;
 }
 
-static int cpia_ioctl(struct inode *inode, struct file *file,
-		      unsigned int ioctlnr, void *arg)
+static int cpia_do_ioctl(struct inode *inode, struct file *file,
+			 unsigned int ioctlnr, void *arg)
 {
 	struct video_device *dev = file->private_data;
 	struct cam_data *cam = dev->priv;
@@ -2874,6 +2874,12 @@
 	return retval;
 } 
 
+static int cpia_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
+}
+
 /* FIXME */
 static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
 {
@@ -2933,7 +2939,7 @@
 	release:       	cpia_close,
 	read:		cpia_read,
 	mmap:		cpia_mmap,
-	ioctl:          video_generic_ioctl,
+	ioctl:          cpia_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -2943,7 +2949,6 @@
 	type:		VID_TYPE_CAPTURE,
 	hardware:	VID_HARDWARE_CPIA,      /* FIXME */
 	fops:           &cpia_fops,
-	kernel_ioctl:	cpia_ioctl,
 };
 
 /* initialise cam_data structure  */
diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/media/video/meye.c	Sun Apr 14 12:16:55 2002
@@ -893,8 +893,8 @@
 	return 0;
 }
 
-static int meye_ioctl(struct inode *inode, struct file *file,
-		      unsigned int cmd, void *arg) {
+static int meye_do_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, void *arg) {
 
 	switch (cmd) {
 
@@ -1169,6 +1169,12 @@
 	return 0;
 }
 
+static int meye_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);
+}
+
 static int meye_mmap(struct file *file, struct vm_area_struct *vma) {
 	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end - vma->vm_start;
@@ -1209,7 +1215,7 @@
 	open:		meye_open,
 	release:	meye_release,
 	mmap:		meye_mmap,
-	ioctl:		video_generic_ioctl,
+	ioctl:		meye_ioctl,
 	llseek:		no_llseek,
 };
 
@@ -1219,7 +1225,6 @@
 	type:		VID_TYPE_CAPTURE,
 	hardware:	VID_HARDWARE_MEYE,
 	fops:		&meye_fops,
-	kernel_ioctl:	meye_ioctl,
 };
 
 static int __devinit meye_probe(struct pci_dev *pcidev, 
diff -Nru a/drivers/media/video/pms.c b/drivers/media/video/pms.c
--- a/drivers/media/video/pms.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/media/video/pms.c	Sun Apr 14 12:16:57 2002
@@ -672,8 +672,8 @@
  *	Video4linux interfacing
  */
 
-static int pms_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, void *arg)
+static int pms_do_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct pms_device *pd=(struct pms_device *)dev;
@@ -855,6 +855,12 @@
 	return 0;
 }
 
+static int pms_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, pms_do_ioctl);
+}
+
 static int pms_read(struct file *file, char *buf,
 		    size_t count, loff_t *ppos)
 {
@@ -872,7 +878,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:          video_generic_ioctl,
+	ioctl:          pms_ioctl,
 	read:           pms_read,
 	llseek:         no_llseek,
 };
@@ -884,7 +890,6 @@
 	type:		VID_TYPE_CAPTURE,
 	hardware:	VID_HARDWARE_PMS,
 	fops:           &pms_fops,
-	kernel_ioctl:	pms_ioctl,
 };
 
 struct pms_device pms_device;
diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
--- a/drivers/media/video/saa5249.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/media/video/saa5249.c	Sun Apr 14 12:16:56 2002
@@ -341,9 +341,12 @@
  *	Standard character-device-driver functions
  */
 
-static int do_saa5249_ioctl(struct saa5249_device *t, unsigned int cmd, void *arg) 
+static int do_saa5249_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, void *arg)
 {
 	static int virtual_mode = FALSE;
+	struct video_device *vd = video_devdata(file);
+	struct saa5249_device *t=vd->priv;
 
 	switch(cmd) 
 	{
@@ -591,16 +594,15 @@
  */
  
 static int saa5249_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg) 
+			 unsigned int cmd, unsigned long arg) 
 {
 	struct video_device *vd = video_devdata(file);
 	struct saa5249_device *t=vd->priv;
 	int err;
 	
 	down(&t->lock);
-	err = do_saa5249_ioctl(t, cmd, arg);
+	err = video_usercopy(inode,file,cmd,arg,do_saa5249_ioctl);
 	up(&t->lock);
-
 	return err;
 }
 
@@ -679,7 +681,7 @@
 	owner:		THIS_MODULE,
 	open:		saa5249_open,
 	release:       	saa5249_release,
-	ioctl:          video_generic_ioctl,
+	ioctl:          saa5249_ioctl,
 	llseek:         no_llseek,
 };
 
@@ -690,7 +692,6 @@
 	type:		VID_TYPE_TELETEXT,	/*| VID_TYPE_TUNER ?? */
 	hardware:	VID_HARDWARE_SAA5249,
 	fops:           &saa_fops,
-	kernel_ioctl:  	saa5249_ioctl,
 };
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
--- a/drivers/media/video/videodev.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/media/video/videodev.c	Sun Apr 14 12:16:55 2002
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/semaphore.h>
@@ -107,20 +108,18 @@
 }
 
 /*
- * ioctl helper function -- handles userspace copying
+ * helper function -- handles userspace copying for ioctl arguments
  */
 int
-video_generic_ioctl(struct inode *inode, struct file *file,
-		    unsigned int cmd, unsigned long arg)
+video_usercopy(struct inode *inode, struct file *file,
+	       unsigned int cmd, unsigned long arg,
+	       int (*func)(struct inode *inode, struct file *file,
+			   unsigned int cmd, void *arg))
 {
-	struct  video_device *vfl = video_devdata(file);
 	char	sbuf[128];
 	void    *mbuf = NULL;
 	void	*parg = NULL;
 	int	err  = -EINVAL;
-	
-	if (vfl->kernel_ioctl == NULL)
-		return -EINVAL;
 
 	/*  Copy arguments into temp kernel buffer  */
 	switch (_IOC_DIR(cmd)) {
@@ -147,7 +146,7 @@
 	}
 
 	/* call driver */
-	err = vfl->kernel_ioctl(inode, file, cmd, parg);
+	err = func(inode, file, cmd, parg);
 	if (err == -ENOIOCTLCMD)
 		err = -EINVAL;
 	if (err < 0)
@@ -512,7 +511,7 @@
 EXPORT_SYMBOL(video_register_device);
 EXPORT_SYMBOL(video_unregister_device);
 EXPORT_SYMBOL(video_devdata);
-EXPORT_SYMBOL(video_generic_ioctl);
+EXPORT_SYMBOL(video_usercopy);
 EXPORT_SYMBOL(video_exclusive_open);
 EXPORT_SYMBOL(video_exclusive_release);
 
diff -Nru a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
--- a/drivers/media/video/w9966.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/media/video/w9966.c	Sun Apr 14 12:16:56 2002
@@ -174,7 +174,7 @@
 static int w9966_i2c_rbyte(struct w9966_dev* cam);
 
 static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
-			   unsigned int cmd, void *arg);
+			   unsigned int cmd, unsigned long arg);
 static int w9966_v4l_read(struct file *file, char *buf,
 			  size_t count, loff_t *ppos);
 
@@ -182,7 +182,7 @@
 	owner:		THIS_MODULE,
 	open:           video_exclusive_open,
 	release:        video_exclusive_release,
-	ioctl:          video_generic_ioctl,
+	ioctl:          w9966_v4l_ioctl,
 	read:           w9966_v4l_read,
 	llseek:         no_llseek,
 };
@@ -192,7 +192,6 @@
 	type:           VID_TYPE_CAPTURE | VID_TYPE_SCALES,
 	hardware:       VID_HARDWARE_W9966,
 	fops:           &w9966_fops,
-	kernel_ioctl:   w9966_v4l_ioctl,
 };
 
 /*
@@ -700,8 +699,8 @@
  *	Video4linux interfacing
  */
 
-static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
-			   unsigned int cmd, void *arg)
+static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg)
 {
 	struct video_device *vdev = video_devdata(file);
 	struct w9966_dev *cam = (struct w9966_dev*)vdev->priv;
@@ -851,6 +850,12 @@
 		return -ENOIOCTLCMD;
 	}
 	return 0;
+}
+
+static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, w9966_v4l_do_ioctl);
 }
 
 // Capture data
diff -Nru a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
--- a/drivers/mtd/chips/sharp.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/mtd/chips/sharp.c	Sun Apr 14 12:16:59 2002
@@ -440,7 +440,7 @@
 
 	timeo = jiffies + HZ;
 
-	while(jiffies<timeo){
+	while(time_before(jiffies, timeo)){
 		map->write32(map,CMD_READ_STATUS,adr);
 		status = map->read32(map,adr);
 		if((status & SR_READY)==SR_READY){
diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
--- a/drivers/mtd/devices/blkmtd.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/mtd/devices/blkmtd.c	Sun Apr 14 12:16:55 2002
@@ -67,7 +67,6 @@
 /* Default erase size in K, always make it a multiple of PAGE_SIZE */
 #define CONFIG_MTD_BLKDEV_ERASESIZE 128
 #define VERSION "1.7"
-extern int *blk_size[];
 
 /* Info for the block device */
 typedef struct mtd_raw_dev_data_s {
@@ -264,7 +263,7 @@
 
 
   DEBUG(3, "bklmtd: readpage: starting brw_kiovec\n");
-  err = brw_kiovec(READ, 1, &iobuf, dev, blocks, rawdevice->sector_size);
+  err = brw_kiovec(READ, 1, &iobuf, rawdevice->binding, blocks, rawdevice->sector_size);
   DEBUG(3, "blkmtd: readpage: finished, err = %d\n", err);
   iobuf->locked = 0;
   free_kiovec(1, &iobuf);
@@ -401,7 +400,7 @@
 	iobuf->nr_pages = cpagecnt;
 	iobuf->length = cursectors << item->rawdevice->sector_bits;
 	DEBUG(3, "blkmtd: write_task: about to kiovec\n");
-	err = brw_kiovec(WRITE, 1, &iobuf, dev, blocks, item->rawdevice->sector_size);
+	err = brw_kiovec(WRITE, 1, &iobuf, item->rawdevice->binding, blocks, item->rawdevice->sector_size);
 	DEBUG(3, "bklmtd: write_task: done, err = %d\n", err);
 	if(err != (cursectors << item->rawdevice->sector_bits)) {
 	  /* if an error occured - set this to exit the loop */
@@ -1062,7 +1061,7 @@
 
   int maj, min;
   int i, blocksize, blocksize_bits;
-  loff_t size = 0;
+  loff_t size;
   int readonly = 0;
   int erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
   kdev_t rdev;
@@ -1143,14 +1142,8 @@
     i >>= 1;
   }
 
-  if(count) {
-    size = count;
-  } else {
-    if (blk_size[maj]) {
-      size = ((loff_t) blk_size[maj][min] << BLOCK_SIZE_BITS) >> blocksize_bits;
-    }
-  }
-  size *= blocksize;
+  size = (count ? count*blocksize : blkdev_size_in_bytes(rdev));
+
   DEBUG(1, "blkmtd: size = %ld\n", (long int)size);
 
   if(size == 0) {
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/mtd/ftl.c	Sun Apr 14 12:16:57 2002
@@ -195,7 +195,7 @@
 		     u_int cmd, u_long arg);
 static int ftl_open(struct inode *inode, struct file *file);
 static release_t ftl_close(struct inode *inode, struct file *file);
-static int ftl_reread_partitions(int minor);
+static int ftl_reread_partitions(kdev_t dev);
 
 static void ftl_erase_callback(struct erase_info *done);
 
@@ -842,7 +842,7 @@
 
 static int ftl_open(struct inode *inode, struct file *file)
 {
-    int minor = MINOR(inode->i_rdev);
+    int minor = minor(inode->i_rdev);
     partition_t *partition;
 
     if (minor>>4 >= MAX_MTD_DEVICES)
@@ -878,7 +878,7 @@
 
 static release_t ftl_close(struct inode *inode, struct file *file)
 {
-    int minor = MINOR(inode->i_rdev);
+    int minor = minor(inode->i_rdev);
     partition_t *part = myparts[minor >> 4];
     int i;
     
@@ -1114,7 +1114,7 @@
 		     u_int cmd, u_long arg)
 {
     struct hd_geometry *geo = (struct hd_geometry *)arg;
-    int ret = 0, minor = MINOR(inode->i_rdev);
+    int ret = 0, minor = minor(inode->i_rdev);
     partition_t *part= myparts[minor >> 4];
     u_long sect;
 
@@ -1139,7 +1139,7 @@
 	ret = put_user((u64)ftl_hd[minor].nr_sects << 9, (u64 *)arg);
 	break;
     case BLKRRPART:
-	ret = ftl_reread_partitions(minor);
+	ret = ftl_reread_partitions(inode->i_rdev);
 	break;
     case BLKROSET:
     case BLKROGET:
@@ -1161,7 +1161,7 @@
 
 static int ftl_reread_partitions(kdev_t dev)
 {
-    int minor = MINOR(dev);
+    int minor = minor(dev);
     partition_t *part = myparts[minor >> 4];
     int res;
 
@@ -1197,7 +1197,7 @@
       //	    sti();
 	INIT_REQUEST;
 
-	minor = MINOR(CURRENT->rq_dev);
+	minor = minor(CURRENT->rq_dev);
 	
 	part = myparts[minor >> 4];
 	if (part) {
@@ -1369,7 +1369,7 @@
 
     unregister_blkdev(FTL_MAJOR, "ftl");
     blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR));
-    bklk_clear(FTL_MAJOR);
+    blk_clear(FTL_MAJOR);
 
     del_gendisk(&ftl_gendisk);
 }
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/mtd/mtdblock.c	Sun Apr 14 12:16:57 2002
@@ -413,7 +413,7 @@
 	for (;;) {
 		INIT_REQUEST;
 		req = CURRENT;
-		spin_unlock_irq(&QUEUE->queue_lock);
+		spin_unlock_irq(QUEUE->queue_lock);
 		mtdblk = mtdblks[minor(req->rq_dev)];
 		res = 0;
 
@@ -457,7 +457,7 @@
 		}
 
 end_req:
-		spin_lock_irq(&QUEUE->queue_lock);
+		spin_lock_irq(QUEUE->queue_lock);
 		if (!end_that_request_first(req, res, req->hard_cur_sectors)) {
 			blkdev_dequeue_request(req);
 			end_that_request_last(req);
@@ -487,16 +487,16 @@
 	while (!leaving) {
 		add_wait_queue(&thr_wq, &wait);
 		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irq(&QUEUE->queue_lock);
+		spin_lock_irq(QUEUE->queue_lock);
 		if (QUEUE_EMPTY || QUEUE_PLUGGED) {
-			spin_unlock_irq(&QUEUE->queue_lock);
+			spin_unlock_irq(QUEUE->queue_lock);
 			schedule();
 			remove_wait_queue(&thr_wq, &wait); 
 		} else {
 			remove_wait_queue(&thr_wq, &wait); 
 			set_current_state(TASK_RUNNING);
 			handle_mtdblock_request();
-			spin_unlock_irq(&QUEUE->queue_lock);
+			spin_unlock_irq(QUEUE->queue_lock);
 		}
 	}
 
@@ -541,7 +541,7 @@
 			return -EACCES;
 #endif
 		fsync_bdev(inode->i_bdev);
-		invalidate_buffers(inode->i_rdev);
+		invalidate_bdev(inode->i_bdev, 0);
 		down(&mtdblk->cache_sem);
 		write_cached_data(mtdblk);
 		up(&mtdblk->cache_sem);
diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
--- a/drivers/mtd/mtdblock_ro.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/mtd/mtdblock_ro.c	Sun Apr 14 12:16:58 2002
@@ -222,7 +222,7 @@
 		if(!capable(CAP_SYS_ADMIN))  return -EACCES;
 #endif
 		fsync_bdev(inode->i_bdev);
-		invalidate_buffers(inode->i_rdev);
+		invalidate_bdev(inode->i_bdev, 0);
 		if (mtd->sync)
 			mtd->sync(mtd);
 		return 0;
diff -Nru a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
--- a/drivers/mtd/nand/nand_ecc.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/mtd/nand/nand_ecc.c	Sun Apr 14 12:16:57 2002
@@ -207,3 +207,5 @@
 
 EXPORT_SYMBOL(nand_calculate_ecc);
 EXPORT_SYMBOL(nand_correct_data);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/mtd/nftlcore.c	Sun Apr 14 12:16:54 2002
@@ -796,7 +796,7 @@
 	case BLKFLSBUF:
 		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 		fsync_bdev(inode->i_bdev);
-		invalidate_buffers(inode->i_rdev);
+		invalidate_bdev(inode->i_bdev, 0);
 		if (nftl->mtd->sync)
 			nftl->mtd->sync(nftl->mtd);
 		return 0;
diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c
--- a/drivers/net/3c503.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/3c503.c	Sun Apr 14 12:16:59 2002
@@ -263,13 +263,13 @@
 #endif  /* EL2MEMTEST */
 
 	if (dev->mem_start)
-		dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE;
+		dev->mem_end = ei_status.rmem_end = dev->mem_start + EL2_MEMSIZE;
 
 	if (wordlength) {	/* No Tx pages to skip over to get to Rx */
-		dev->rmem_start = dev->mem_start;
+		ei_status.rmem_start = dev->mem_start;
 		ei_status.name = "3c503/16";
 	} else {
-		dev->rmem_start = TX_PAGES*256 + dev->mem_start;
+		ei_status.rmem_start = TX_PAGES*256 + dev->mem_start;
 		ei_status.name = "3c503";
 	}
     }
@@ -549,7 +549,7 @@
     unsigned short int *buf;
     unsigned short word;
 
-    int end_of_ring = dev->rmem_end;
+    int end_of_ring = ei_status.rmem_end;
 
     /* Maybe enable shared memory just be to be safe... nahh.*/
     if (dev->mem_start) {	/* Use the shared memory. */
@@ -559,7 +559,7 @@
 	    int semi_count = end_of_ring - (dev->mem_start + ring_offset);
 	    isa_memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
 	    count -= semi_count;
-	    isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+	    isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
 		isa_eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c
--- a/drivers/net/3c505.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/3c505.c	Sun Apr 14 12:16:58 2002
@@ -1383,7 +1383,7 @@
 	/*
 	 * memory information
 	 */
-	dev->mem_start = dev->mem_end = dev->rmem_end = dev->rmem_start = 0;
+	dev->mem_start = dev->mem_end = 0;
 }
 
 /************************************************************
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/3c59x.c	Sun Apr 14 12:16:54 2002
@@ -166,7 +166,15 @@
     - Rename wait_for_completion() to issue_and_wait() to avoid completion.h
       clash.
 
-    - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
+   LK1.1.17 18Dec01 akpm
+    - PCI ID 9805 is a Python-T, not a dual-port Cyclone.  Apparently.
+      And it has NWAY.
+    - Mask our advertised modes (vp->advertising) with our capabilities
+	  (MII reg5) when deciding which duplex mode to use.
+    - Add `global_options' as default for options[].  Ditto global_enable_wol,
+      global_full_duplex.
+
+    - See http://www.zip.com.au/~akpm/linux/#3c59x-2.3 for more details.
     - Also see Documentation/networking/vortex.txt
 */
 
@@ -181,8 +189,8 @@
 
 
 #define DRV_NAME	"3c59x"
-#define DRV_VERSION	"LK1.1.16"
-#define DRV_RELDATE	"19 July 2001"
+#define DRV_VERSION	"LK1.1.17"
+#define DRV_RELDATE	"18 Dec 2001"
 
 
 
@@ -270,10 +278,13 @@
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(debug, "i");
+MODULE_PARM(global_options, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(global_full_duplex, "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(hw_checksums, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(flow_ctrl, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(global_enable_wol, "i");
 MODULE_PARM(enable_wol, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
@@ -283,10 +294,13 @@
 MODULE_PARM(watchdog, "i");
 MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
 MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
+MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)");
+MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)");
 MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)");
 MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)");
+MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if options is unset");
 MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt");
 MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)");
@@ -473,7 +487,7 @@
 	{"3c900 Boomerang 10Mbps Combo",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
 	{"3c900 Cyclone 10Mbps TPO",						/* AKPM: from Don's 0.99M */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 	{"3c900 Cyclone 10Mbps Combo",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 
@@ -496,8 +510,8 @@
 	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c980 Cyclone",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
-	{"3c982 Dual Port Server Cyclone",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	{"3c980C Python-T",
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 
 	{"3cSOHO100-TX Hurricane",
 	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
@@ -853,6 +867,9 @@
 static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int global_options = -1;
+static int global_full_duplex = -1;
+static int global_enable_wol = -1;
 
 /* #define dev_alloc_skb dev_alloc_skb_debug */
 
@@ -995,6 +1012,8 @@
 	SET_MODULE_OWNER(dev);
 	vp = dev->priv;
 
+	option = global_options;
+
 	/* The lower four bits are the media type. */
 	if (dev->mem_start) {
 		/*
@@ -1003,10 +1022,10 @@
 		 */
 		option = dev->mem_start;
 	}
-	else if (card_idx < MAX_UNITS)
-		option = options[card_idx];
-	else
-		option = -1;
+	else if (card_idx < MAX_UNITS) {
+		if (options[card_idx] >= 0)
+			option = options[card_idx];
+	}
 
 	if (option > 0) {
 		if (option & 0x8000)
@@ -1099,6 +1118,11 @@
 		vp->bus_master = (option & 16) ? 1 : 0;
 	}
 
+	if (global_full_duplex > 0)
+		vp->full_duplex = 1;
+	if (global_enable_wol > 0)
+		vp->enable_wol = 1;
+
 	if (card_idx < MAX_UNITS) {
 		if (full_duplex[card_idx] > 0)
 			vp->full_duplex = 1;
@@ -1244,11 +1268,12 @@
 	} else
 		dev->if_port = vp->default_media;
 
-	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
+	if ((vp->available_media & 0x4b) || (vci->drv_flags & HAS_NWAY) ||
+		dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
 		int phy, phy_idx = 0;
 		EL3WINDOW(4);
 		mii_preamble_required++;
-		mii_preamble_required++;
+		mdio_sync(ioaddr, 32);
 		mdio_read(dev, 24, 1);
 		for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
 			int mii_status, phyx;
@@ -1264,6 +1289,8 @@
 			else
 				phyx = phy;
 			mii_status = mdio_read(dev, phyx, 1);
+		printk("phy=%d, phyx=%d, mii_status=0x%04x\n",
+			phy, phyx, mii_status);
 			if (mii_status  &&  mii_status != 0xffff) {
 				vp->phys[phy_idx++] = phyx;
 				if (print_info) {
@@ -1444,11 +1471,14 @@
 		/* Read BMSR (reg1) only to clear old status. */
 		mii_reg1 = mdio_read(dev, vp->phys[0], 1);
 		mii_reg5 = mdio_read(dev, vp->phys[0], 5);
-		if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000)
+		if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000) {
 			;					/* No MII device or no link partner report */
-		else if ((mii_reg5 & 0x0100) != 0	/* 100baseTx-FD */
+		} else {
+			mii_reg5 &= vp->advertising;
+			if ((mii_reg5 & 0x0100) != 0	/* 100baseTx-FD */
 				 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
 			vp->full_duplex = 1;
+		}
 		vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
 		if (vortex_debug > 1)
 			printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"
@@ -1669,8 +1699,10 @@
 			if (mii_status & 0x0004) {
 				int mii_reg5 = mdio_read(dev, vp->phys[0], 5);
 				if (! vp->force_fd  &&  mii_reg5 != 0xffff) {
-					int duplex = (mii_reg5&0x0100) ||
-						(mii_reg5 & 0x01C0) == 0x0040;
+					int duplex;
+
+					mii_reg5 &= vp->advertising;
+					duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
 					if (vp->full_duplex != duplex) {
 						vp->full_duplex = duplex;
 						printk(KERN_INFO "%s: Setting %s-duplex based on MII "
@@ -1753,9 +1785,11 @@
 		   dev->name, inb(ioaddr + TxStatus),
 		   inw(ioaddr + EL3_STATUS));
 	EL3WINDOW(4);
-	printk(KERN_ERR "  diagnostics: net %04x media %04x dma %8.8x.\n",
-		   inw(ioaddr + Wn4_NetDiag), inw(ioaddr + Wn4_Media),
-		   inl(ioaddr + PktStatus));
+	printk(KERN_ERR "  diagnostics: net %04x media %04x dma %08x fifo %04x\n",
+			inw(ioaddr + Wn4_NetDiag),
+			inw(ioaddr + Wn4_Media),
+			inl(ioaddr + PktStatus),
+			inw(ioaddr + Wn4_FIFODiag));
 	/* Slight code bloat to be user friendly. */
 	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
 		printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
@@ -2538,7 +2572,6 @@
 			((vp->drv_flags & HAS_HWCKSM) == 0) &&
 			(hw_checksums[vp->card_idx] == -1)) {
 		printk(KERN_WARNING "%s supports hardware checksums, and we're not using them!\n", dev->name);
-		printk(KERN_WARNING "Please see http://www.uow.edu.au/~andrewm/zerocopy.html\n");
 	}
 #endif
 		
diff -Nru a/drivers/net/7990.c b/drivers/net/7990.c
--- a/drivers/net/7990.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/7990.c	Sun Apr 14 12:16:59 2002
@@ -630,3 +630,4 @@
 		netif_start_queue (dev);
 }
 
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/8390.h b/drivers/net/8390.h
--- a/drivers/net/8390.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/8390.h	Sun Apr 14 12:16:59 2002
@@ -51,8 +51,6 @@
 extern int ei_close(struct net_device *dev);
 extern void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
-/* Most of these entries should be in 'struct net_device' (or most of the
-   things in there should be here!) */
 /* You have one of these per-board */
 struct ei_device {
 	const char *name;
@@ -60,6 +58,8 @@
 	void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
 	void (*block_output)(struct net_device *, int, const unsigned char *, int);
 	void (*block_input)(struct net_device *, int, struct sk_buff *, int);
+	unsigned long rmem_start;
+	unsigned long rmem_end;
 	unsigned char mcfilter[8];
 	unsigned open:1;
 	unsigned word16:1;  		/* We have the 16-bit (vs 8-bit) version of the card. */
diff -Nru a/drivers/net/Config.in b/drivers/net/Config.in
--- a/drivers/net/Config.in	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/Config.in	Sun Apr 14 12:16:55 2002
@@ -57,6 +57,9 @@
    if [ "$CONFIG_MIPS_AU1000" = "y" ]; then
       bool '  MIPS AU1000 Ethernet support' CONFIG_MIPS_AU1000_ENET
    fi
+   if [ "$CONFIG_SIBYTE_SB1250" = "y" ]; then
+      tristate '  SB1250 Ethernet support' CONFIG_NET_SB1250_MAC
+   fi
    if [ "$CONFIG_SGI_IP27" = "y" ]; then
       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/Makefile	Sun Apr 14 12:16:57 2002
@@ -82,6 +82,7 @@
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
 obj-$(CONFIG_FEALNX) += fealnx.o mii.o
 obj-$(CONFIG_TIGON3) += tg3.o
+obj-$(CONFIG_TC35815) += tc35815.o
 
 ifeq ($(CONFIG_SK98LIN),y)
 obj-y += sk98lin/sk98lin.o
@@ -133,6 +134,7 @@
 obj-$(CONFIG_ES3210) += es3210.o 8390.o
 obj-$(CONFIG_LNE390) += lne390.o 8390.o
 obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o
 
 obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
@@ -153,6 +155,7 @@
 obj-$(CONFIG_DE620) += de620.o
 obj-$(CONFIG_AT1500) += lance.o
 obj-$(CONFIG_LANCE) += lance.o
+obj-$(CONFIG_SUN3_82586) += sun3_82586.o
 obj-$(CONFIG_SUN3LANCE) += sun3lance.o
 obj-$(CONFIG_DEFXX) += defxx.o
 obj-$(CONFIG_SGISEEQ) += sgiseeq.o
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/Space.c	Sun Apr 14 12:16:55 2002
@@ -12,6 +12,8 @@
  *		Donald J. Becker, <becker@scyld.com>
  *
  * Changelog:
+ *		Paul Gortmaker (03/2002)
+		- struct init cleanup, enable multiple ISA autoprobes.
  *		Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 09/1999
  *		- fix sbni: s/device/net_device/
  *		Paul Gortmaker (06/98): 
@@ -86,6 +88,7 @@
 extern int sgiseeq_probe(struct net_device *);
 extern int atarilance_probe(struct net_device *);
 extern int sun3lance_probe(struct net_device *);
+extern int sun3_82586_probe(struct net_device *);
 extern int apne_probe(struct net_device *);
 extern int bionet_probe(struct net_device *);
 extern int pamsnet_probe(struct net_device *);
@@ -332,6 +335,9 @@
 #ifdef CONFIG_SUN3LANCE         /* sun3 onboard Lance chip */
 	{sun3lance_probe, 0},
 #endif
+#ifdef CONFIG_SUN3_82586        /* sun3 onboard Intel 82586 chip */
+	{sun3_82586_probe, 0},
+#endif
 #ifdef CONFIG_APNE		/* A1200 PCMCIA NE2000 */
 	{apne_probe, 0},
 #endif
@@ -410,14 +416,7 @@
 		return 0;
 	if (probe_list(dev, mca_probes) == 0)
 		return 0;
-        /*
-         * Backwards compatibility - an I/O of 0xffe0 was used to indicate
-         * that we shouldn't do a bunch of potentially risky ISA probes
-         * for ethN (N>1).  Since the widespread use of modules, *nobody*
-         * compiles a kernel with all the ISA drivers built in anymore,
-         * and so we should delete this check in linux 2.3 - Paul G.
-         */
-	if (base_addr != 0xffe0 && probe_list(dev, isa_probes) == 0) 
+	if (probe_list(dev, isa_probes) == 0) 
 		return 0;
 	if (probe_list(dev, parport_probes) == 0)
 		return 0;
@@ -466,74 +465,102 @@
 
 
 #ifdef CONFIG_ETHERTAP
-    static struct net_device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, };
-#   undef NEXT_DEV
-#   define NEXT_DEV	(&tap0_dev)
+static struct net_device tap0_dev = {
+	name:		"tap0",
+	base_addr:	NETLINK_TAPBASE,
+	next:		NEXT_DEV,
+	init:		ethertap_probe,
+};
+#undef NEXT_DEV
+#define NEXT_DEV	(&tap0_dev)
 #endif
 
 #ifdef CONFIG_SDLA
-    extern int sdla_init(struct net_device *);
-    static struct net_device sdla0_dev = { "sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, sdla_init, };
-
-#   undef NEXT_DEV
-#   define NEXT_DEV	(&sdla0_dev)
+extern int sdla_init(struct net_device *);
+static struct net_device sdla0_dev = {
+	name:		 "sdla0",
+	next:		 NEXT_DEV,
+	init:		 sdla_init,
+};
+#undef NEXT_DEV
+#define NEXT_DEV	(&sdla0_dev)
 #endif
 
 #if defined(CONFIG_LTPC)
-    extern int ltpc_probe(struct net_device *);
-    static struct net_device dev_ltpc = {
-        "lt0",
-                0, 0, 0, 0,
-                0x0, 0,
-                0, 0, 0, NEXT_DEV, ltpc_probe };
-#   undef NEXT_DEV
-#   define NEXT_DEV	(&dev_ltpc)
+extern int ltpc_probe(struct net_device *);
+static struct net_device dev_ltpc = {
+	name:		"lt0",
+	next:		NEXT_DEV,
+	init:		ltpc_probe
+};
+#undef NEXT_DEV
+#define NEXT_DEV	(&dev_ltpc)
 #endif  /* LTPC */
 
 #if defined(CONFIG_COPS)
-    extern int cops_probe(struct net_device *);
-    static struct net_device cops2_dev = { "lt2", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NEXT_DEV, cops_probe };
-    static struct net_device cops1_dev = { "lt1", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops2_dev, cops_probe };
-    static struct net_device cops0_dev = { "lt0", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops1_dev, cops_probe };
-#   undef NEXT_DEV
-#   define NEXT_DEV     (&cops0_dev)
+extern int cops_probe(struct net_device *);
+static struct net_device cops2_dev = {
+	name:		"lt2",
+	next:		NEXT_DEV,
+	init:		cops_probe,
+};
+static struct net_device cops1_dev = {
+	name:		"lt1",
+	next:		&cops2_dev,
+	init:		cops_probe,
+};
+static struct net_device cops0_dev = {
+	name:		"lt0",
+	next:		&cops1_dev,
+	init:		cops_probe,
+};
+#undef NEXT_DEV
+#define NEXT_DEV     (&cops0_dev)
 #endif  /* COPS */
 
-
-/* The first device defaults to I/O base '0', which means autoprobe. */
-#ifndef ETH0_ADDR
-# define ETH0_ADDR 0
-#endif
-#ifndef ETH0_IRQ
-# define ETH0_IRQ 0
-#endif
-
-/* "eth0" defaults to autoprobe (== 0), other use a base of 0xffe0 (== -0x20),
-   which means "don't do ISA probes".  Distributions don't ship kernels with
-   all ISA drivers compiled in anymore, so its probably no longer an issue. */
-
-#define ETH_NOPROBE_ADDR 0xffe0
-
 static struct net_device eth7_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
+	name:		"eth%d",
+	next:		NEXT_DEV,
+	init:		ethif_probe,
+};
 static struct net_device eth6_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth7_dev, ethif_probe };
+	name:		"eth%d",
+	next:		&eth7_dev,
+	init:		ethif_probe,
+};
 static struct net_device eth5_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth6_dev, ethif_probe };
+	name:		"eth%d",
+	next:		&eth6_dev,
+	init:		ethif_probe,
+};
 static struct net_device eth4_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth5_dev, ethif_probe };
+	name:		"eth%d",
+	next:		&eth5_dev,
+	init:		ethif_probe,
+};
 static struct net_device eth3_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth4_dev, ethif_probe };
+	name:		"eth%d",
+	next:		&eth4_dev,
+	init:		ethif_probe,
+};
 static struct net_device eth2_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth3_dev, ethif_probe };
+	name:		"eth%d",
+	next:		&eth3_dev,
+	init:		ethif_probe,
+};
 static struct net_device eth1_dev = {
-    "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth2_dev, ethif_probe };
-
+	name:		"eth%d",
+	next:		&eth2_dev,
+	init:		ethif_probe,
+};
 static struct net_device eth0_dev = {
-    "eth%d", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, &eth1_dev, ethif_probe };
+	name:		"eth%d",
+	next:		&eth1_dev,
+	init:		ethif_probe,
+};
 
-#   undef NEXT_DEV
-#   define NEXT_DEV	(&eth0_dev)
+#undef NEXT_DEV
+#define NEXT_DEV	(&eth0_dev)
 
 
 
@@ -558,75 +585,153 @@
     return 0;
 }
 static struct net_device tr7_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, NEXT_DEV, trif_probe };
+	name:		"tr%d",
+	next:		NEXT_DEV,
+	init:		trif_probe,
+};
 static struct net_device tr6_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr7_dev, trif_probe };
+	name:		"tr%d",
+	next:		&tr7_dev,
+	init:		trif_probe,
+};
 static struct net_device tr5_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr6_dev, trif_probe };
+	name:		"tr%d",
+	next:		&tr6_dev,
+	init:		trif_probe,
+};
 static struct net_device tr4_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr5_dev, trif_probe };
+	name:		"tr%d",
+	next:		&tr5_dev,
+	init:		trif_probe,
+};
 static struct net_device tr3_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr4_dev, trif_probe };
+	name:		"tr%d",
+	next:		&tr4_dev,
+	init:		trif_probe,
+};
 static struct net_device tr2_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr3_dev, trif_probe };
+	name:		"tr%d",
+	next:		&tr3_dev,
+	init:		trif_probe,
+};
 static struct net_device tr1_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr2_dev, trif_probe };
+	name:		"tr%d",
+	next:		&tr2_dev,
+	init:		trif_probe,
+};
 static struct net_device tr0_dev = {
-    "tr%d",0,0,0,0,0,0,0,0,0, &tr1_dev, trif_probe };
-#   undef       NEXT_DEV
-#   define      NEXT_DEV        (&tr0_dev)
+	name:		"tr%d",
+	next:		&tr1_dev,
+	init:		trif_probe,
+};
+#undef       NEXT_DEV
+#define      NEXT_DEV        (&tr0_dev)
 
 #endif 
 
 #ifdef CONFIG_FDDI
-	static struct net_device fddi7_dev =
-		{"fddi7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, fddiif_probe};
-	static struct net_device fddi6_dev =
-		{"fddi6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi7_dev, fddiif_probe};
-	static struct net_device fddi5_dev =
-		{"fddi5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi6_dev, fddiif_probe};
-	static struct net_device fddi4_dev =
-		{"fddi4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi5_dev, fddiif_probe};
-	static struct net_device fddi3_dev =
-		{"fddi3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi4_dev, fddiif_probe};
-	static struct net_device fddi2_dev =
-		{"fddi2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi3_dev, fddiif_probe};
-	static struct net_device fddi1_dev =
-		{"fddi1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi2_dev, fddiif_probe};
-	static struct net_device fddi0_dev =
-		{"fddi0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi1_dev, fddiif_probe};
+static struct net_device fddi7_dev = {
+	name:		"fddi7",
+	next:		 NEXT_DEV,
+	init:		fddiif_probe
+};
+static struct net_device fddi6_dev = {
+	name:		"fddi6",
+	next:		&fddi7_dev,
+	init:		fddiif_probe
+};
+static struct net_device fddi5_dev = {
+	name:		"fddi5",
+	next:		&fddi6_dev,
+	init:		fddiif_probe
+};
+static struct net_device fddi4_dev = {
+	name:		"fddi4",
+	next:		&fddi5_dev,
+	init:		fddiif_probe
+};
+static struct net_device fddi3_dev = {
+	name:		"fddi3",
+	next:		&fddi4_dev,
+	init:		fddiif_probe
+};
+static struct net_device fddi2_dev = {
+	name:		"fddi2",
+	next:		&fddi3_dev,
+	init:		fddiif_probe
+};
+static struct net_device fddi1_dev = {
+	name:		"fddi1",
+	next:		&fddi2_dev,
+	init:		fddiif_probe
+};
+static struct net_device fddi0_dev = {
+	name:		"fddi0",
+	next:		&fddi1_dev,
+	init:		fddiif_probe
+};
 #undef	NEXT_DEV
 #define	NEXT_DEV	(&fddi0_dev)
 #endif 
 
 
 #ifdef CONFIG_NET_FC
-    static struct net_device fc1_dev = {
-        "fc1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, fcif_probe};
-	static struct net_device fc0_dev = {
-		"fc0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fc1_dev, fcif_probe};
-#   undef       NEXT_DEV
-#   define      NEXT_DEV        (&fc0_dev)
+static struct net_device fc1_dev = {
+	name:		"fc1",
+	next:		NEXT_DEV,
+	init:		fcif_probe
+};
+static struct net_device fc0_dev = {
+	name:		"fc0",
+	next:		 &fc1_dev,
+	init:		fcif_probe
+};
+#undef       NEXT_DEV
+#define      NEXT_DEV        (&fc0_dev)
 #endif
 
 
 #ifdef CONFIG_SBNI
-	static struct net_device sbni7_dev =
-		{"sbni7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, sbni_probe};
-	static struct net_device sbni6_dev =
-		{"sbni6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni7_dev, sbni_probe};
-	static struct net_device sbni5_dev =
-		{"sbni5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni6_dev, sbni_probe};
-	static struct net_device sbni4_dev =
-		{"sbni4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni5_dev, sbni_probe};
-	static struct net_device sbni3_dev =
-		{"sbni3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni4_dev, sbni_probe};
-	static struct net_device sbni2_dev =
-		{"sbni2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni3_dev, sbni_probe};
-	static struct net_device sbni1_dev =
-		{"sbni1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni2_dev, sbni_probe};
-	static struct net_device sbni0_dev =
-		{"sbni0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &sbni1_dev, sbni_probe};
+static struct net_device sbni7_dev = {
+	name:		"sbni7",
+	next:		NEXT_DEV,
+	init:		sbni_probe,
+};
+static struct net_device sbni6_dev =
+	name:		"sbni6",
+	next:		&sbni7_dev,
+	init:		sbni_probe,
+};
+static struct net_device sbni5_dev =
+	name:		"sbni5",
+	next:		&sbni6_dev,
+	init:		sbni_probe,
+};
+static struct net_device sbni4_dev =
+	name:		"sbni4",
+	next:		&sbni5_dev,
+	init:		sbni_probe,
+};
+static struct net_device sbni3_dev =
+	name:		"sbni3",
+	next:		&sbni4_dev,
+	init:		sbni_probe,
+};
+static struct net_device sbni2_dev =
+	name:		"sbni2",
+	next:		&sbni3_dev,
+	init:		sbni_probe,
+};
+static struct net_device sbni1_dev =
+	name:		"sbni1",
+	next:		&sbni2_dev,
+	init:		sbni_probe,
+};
+static struct net_device sbni0_dev =
+	name:		"sbni0",
+	next:		&sbni1_dev,
+	init:		sbni_probe,
+};
 
 #undef	NEXT_DEV
 #define	NEXT_DEV	(&sbni0_dev)
@@ -638,8 +743,11 @@
  */
 
 extern int loopback_init(struct net_device *dev);
-struct net_device loopback_dev = 
-	{"lo", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, loopback_init};
+struct net_device loopback_dev = {
+	name:		"lo",
+	next:		NEXT_DEV,
+	init:		loopback_init
+};
 
 /*
  * The @dev_base list is protected by @dev_base_lock and the rtln
diff -Nru a/drivers/net/a2065.c b/drivers/net/a2065.c
--- a/drivers/net/a2065.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/a2065.c	Sun Apr 14 12:16:59 2002
@@ -51,7 +51,6 @@
 #include <linux/crc32.h>
 
 #include <asm/bitops.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <linux/errno.h>
 
@@ -496,14 +495,14 @@
 
 	last_dev = dev;
 
+	/* Stop the Lance */
+	ll->rap = LE_CSR0;
+	ll->rdp = LE_C0_STOP;
+
 	/* Install the Interrupt handler */
 	ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, SA_SHIRQ,
 			  dev->name, dev);
 	if (ret) return ret;
-
-	/* Stop the Lance */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
 
 	load_csrs (lp);
 	lance_init_ring (dev);
diff -Nru a/drivers/net/ac3200.c b/drivers/net/ac3200.c
--- a/drivers/net/ac3200.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/ac3200.c	Sun Apr 14 12:16:55 2002
@@ -226,8 +226,8 @@
 				AC_STOP_PG/4, dev->mem_start);
 	}
 
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = dev->rmem_end = dev->mem_start
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+	dev->mem_end = ei_status.rmem_end = dev->mem_start
 		+ (AC_STOP_PG - AC_START_PG)*256;
 
 	ei_status.name = "AC3200";
@@ -302,12 +302,12 @@
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (AC_START_PG<<8);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
 		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/acenic.c	Sun Apr 14 12:16:58 2002
@@ -65,7 +65,10 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/sockios.h>
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #include <linux/if_vlan.h>
+#endif
 
 #ifdef SIOCETHTOOL
 #include <linux/ethtool.h>
@@ -320,9 +323,11 @@
 
 #if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \
 	defined(NETIF_F_HW_VLAN_RX)
-#define ACENIC_DO_VLAN	1
+#define ACENIC_DO_VLAN		1
+#define ACE_RCB_VLAN_FLAG	RCB_FLG_VLAN_ASSIST
 #else
-#define ACENIC_DO_VLAN	0
+#define ACENIC_DO_VLAN		0
+#define ACE_RCB_VLAN_FLAG	0
 #endif
 
 #include "acenic.h"
@@ -563,7 +568,7 @@
 static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 
 static char version[] __initdata = 
-  "acenic.c: v0.88 03/14/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
+  "acenic.c: v0.89 03/15/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
 static struct net_device *root_dev;
@@ -1461,10 +1466,8 @@
 
 	set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
 	info->rx_std_ctrl.max_len = ACE_STD_MTU + ETH_HLEN + 4;
-	info->rx_std_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
-#if ACENIC_DO_VLAN
-	info->rx_std_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
-#endif
+	info->rx_std_ctrl.flags =
+	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
 
 	memset(ap->rx_std_ring, 0,
 	       RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1479,10 +1482,8 @@
 		    (ap->rx_ring_base_dma +
 		     (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
 	info->rx_jumbo_ctrl.max_len = 0;
-	info->rx_jumbo_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
-#if ACENIC_DO_VLAN
-	info->rx_jumbo_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
-#endif
+	info->rx_jumbo_ctrl.flags =
+	  RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
 
 	memset(ap->rx_jumbo_ring, 0,
 	       RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1504,10 +1505,7 @@
 			       RX_JUMBO_RING_ENTRIES))));
 		info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
 		info->rx_mini_ctrl.flags = 
-			RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
-#if ACENIC_DO_VLAN
-		info->rx_mini_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
-#endif
+		  RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|ACE_RCB_VLAN_FLAG;
 
 		for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
 			ap->rx_mini_ring[i].flags =
@@ -1554,7 +1552,7 @@
 	}
 
 	info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
-	tmp = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
+	tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
 
 	/*
 	 * The Tigon I does not like having the TX ring in host memory ;-(
@@ -1564,9 +1562,6 @@
 #if TX_COAL_INTS_ONLY
 	tmp |= RCB_FLG_COAL_INT_ONLY;
 #endif
-#if ACENIC_DO_VLAN
-	tmp |= RCB_FLG_VLAN_ASSIST;
-#endif
 	info->tx_ctrl.flags = tmp;
 
 	set_aceaddr(&info->tx_csm_ptr, ap->tx_csm_dma);
@@ -1592,7 +1587,7 @@
 	ace_set_rxtx_parms(dev, 0);
 
 	if (board_idx == BOARD_IDX_OVERFLOW) {
-		printk(KERN_WARNING "%s: more then %i NICs detected, "
+		printk(KERN_WARNING "%s: more than %i NICs detected, "
 		       "ignoring module parameters!\n",
 		       dev->name, ACE_MAX_MOD_PARMS);
 	} else if (board_idx >= 0) {
@@ -2181,14 +2176,6 @@
 }
 
 
-#if ACENIC_DO_VLAN
-static int ace_vlan_rx(struct ace_private *ap, struct sk_buff *skb, u16 vlan_tag)
-{
-	return vlan_hwaccel_rx(skb, ap->vlgrp, vlan_tag);
-}
-#endif
-
-
 static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 {
 	struct ace_private *ap = dev->priv;
@@ -2274,11 +2261,9 @@
 		}
 
 		/* send it up */
-
 #if ACENIC_DO_VLAN
-		if (ap->vlgrp != NULL &&
-		    (bd_flags & BD_FLG_VLAN_TAG)) {
-			ace_vlan_rx(ap, skb, retdesc->vlan);
+		if (ap->vlgrp && (bd_flags & BD_FLG_VLAN_TAG)) {
+			vlan_hwaccel_rx(skb, ap->vlgrp, retdesc->vlan);
 		} else
 #endif
 			netif_rx(skb);
diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h
--- a/drivers/net/acenic.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/acenic.h	Sun Apr 14 12:16:58 2002
@@ -642,10 +642,6 @@
 	struct ace_skb		*skb;
 	dma_addr_t		info_dma;	/* 32/64 bit */
 
-#if ACENIC_DO_VLAN
-	struct vlan_group	*vlgrp;
-#endif
-
 	int			version, link;
 	int			promisc, mcast_all;
 
@@ -655,7 +651,6 @@
 	struct tx_desc		*tx_ring;
 	u32			tx_prd;
 	volatile u32		tx_ret_csm;
-	struct timer_list	timer;
 	int			tx_ring_entries;
 
 	/*
@@ -674,6 +669,10 @@
 	struct rx_desc		*rx_jumbo_ring;
 	struct rx_desc		*rx_mini_ring;
 	struct rx_desc		*rx_return_ring;
+
+#if ACENIC_DO_VLAN
+	struct vlan_group	*vlgrp;
+#endif
 
 	int			tasklet_pending, jumbo;
 	struct tasklet_struct	ace_tasklet;
diff -Nru a/drivers/net/aironet4500.h b/drivers/net/aironet4500.h
--- a/drivers/net/aironet4500.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/aironet4500.h	Sun Apr 14 12:16:54 2002
@@ -450,7 +450,7 @@
 };
 
 
-extern  __inline__ void
+static  __inline__ void
 awc_fid_queue_init(struct awc_fid_queue * queue){
 
 	unsigned long flags;
@@ -463,7 +463,7 @@
 	spin_unlock_irqrestore(&queue->spinlock,flags);	
 };
 
-extern inline void
+static inline void
 awc_fid_queue_push_tail(	struct awc_fid_queue * 	queue,
 				struct awc_fid *	fid){
 
@@ -488,7 +488,7 @@
 };
 
 
-extern inline void
+static inline void
 awc_fid_queue_push_head(	struct awc_fid_queue * 	queue,
 				struct awc_fid *	fid){
 
@@ -513,7 +513,7 @@
 
 
 
-extern inline void
+static inline void
 awc_fid_queue_rm(		struct awc_fid_queue * 	queue,
 				struct awc_fid *	fid){
 
@@ -541,7 +541,7 @@
 	}		
 };
 
-extern inline void
+static inline void
 awc_fid_queue_remove(		struct awc_fid_queue * 	queue,
 				struct awc_fid *	fid){
 	unsigned long flags;
@@ -555,7 +555,7 @@
 
 
 
-extern inline struct awc_fid * 
+static inline struct awc_fid * 
 awc_fid_queue_pop_head(		struct awc_fid_queue * 	queue){
 
 	unsigned long flags;
@@ -575,7 +575,7 @@
 
 
 
-extern inline struct awc_fid * 
+static inline struct awc_fid * 
 awc_fid_queue_pop_tail(		struct awc_fid_queue * 	queue){
 
 	unsigned long flags;
diff -Nru a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
--- a/drivers/net/arcnet/arc-rawmode.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/arcnet/arc-rawmode.c	Sun Apr 14 12:16:59 2002
@@ -83,6 +83,7 @@
 	arcnet_unregister_proto(&rawmode_proto);
 }
 
+MODULE_LICENSE("GPL");
 #endif				/* MODULE */
 
 
diff -Nru a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
--- a/drivers/net/arcnet/arc-rimi.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/arcnet/arc-rimi.c	Sun Apr 14 12:16:55 2002
@@ -153,8 +153,6 @@
 
 	dev->mem_start = first_mirror;
 	dev->mem_end = last_mirror + MIRROR_SIZE - 1;
-	dev->rmem_start = dev->mem_start + BUFFER_SIZE * 0;
-	dev->rmem_end = dev->mem_start + BUFFER_SIZE * 2 - 1;
 
 	/* initialize the rest of the device structure. */
 
@@ -297,6 +295,7 @@
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM(device, "s");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -Nru a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
--- a/drivers/net/arcnet/arcnet.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/arcnet/arcnet.c	Sun Apr 14 12:16:59 2002
@@ -163,6 +163,7 @@
 
 static int debug = ARCNET_DEBUG;
 MODULE_PARM(debug, "i");
+MODULE_LICENSE("GPL");
 
 int __init init_module(void)
 {
diff -Nru a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
--- a/drivers/net/arcnet/com20020-isa.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/arcnet/com20020-isa.c	Sun Apr 14 12:16:56 2002
@@ -133,6 +133,7 @@
 MODULE_PARM(backplane, "i");
 MODULE_PARM(clockp, "i");
 MODULE_PARM(clockm, "i");
+MODULE_LICENSE("GPL");
 
 static void com20020isa_open_close(struct net_device *dev, bool open)
 {
diff -Nru a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
--- a/drivers/net/arcnet/com20020-pci.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/arcnet/com20020-pci.c	Sun Apr 14 12:16:56 2002
@@ -57,6 +57,7 @@
 MODULE_PARM(backplane, "i");
 MODULE_PARM(clockp, "i");
 MODULE_PARM(clockm, "i");
+MODULE_LICENSE("GPL");
 
 static void com20020pci_open_close(struct net_device *dev, bool open)
 {
@@ -160,7 +161,7 @@
 	name:		"com20020",
 	id_table:	com20020pci_id_table,
 	probe:		com20020pci_probe,
-	remove:		__devexit_p(com20020pci_remove)
+	remove:		__devexit_p(com20020pci_remove),
 };
 
 static int __init com20020pci_init(void)
diff -Nru a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
--- a/drivers/net/arcnet/com20020.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/arcnet/com20020.c	Sun Apr 14 12:16:57 2002
@@ -356,6 +356,8 @@
 EXPORT_SYMBOL(com20020_found);
 EXPORT_SYMBOL(com20020_remove);
 
+MODULE_LICENSE("GPL");
+
 int init_module(void)
 {
 	BUGLVL(D_NORMAL) printk(VERSION);
diff -Nru a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
--- a/drivers/net/arcnet/com90io.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/arcnet/com90io.c	Sun Apr 14 12:16:57 2002
@@ -383,6 +383,7 @@
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM(device, "s");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -Nru a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
--- a/drivers/net/arcnet/com90xx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/arcnet/com90xx.c	Sun Apr 14 12:16:59 2002
@@ -447,8 +447,6 @@
 
 	dev->mem_start = first_mirror;
 	dev->mem_end = last_mirror + MIRROR_SIZE - 1;
-	dev->rmem_start = dev->mem_start + BUFFER_SIZE * 0;
-	dev->rmem_end = dev->mem_start + BUFFER_SIZE * 2 - 1;
 
 	/* Initialize the rest of the device structure. */
 	memset(lp, 0, sizeof(struct arcnet_local));
@@ -619,6 +617,7 @@
 MODULE_PARM(irq, "i");
 MODULE_PARM(shmem, "i");
 MODULE_PARM(device, "s");
+MODULE_LICENSE("GPL");
 
 int init_module(void)
 {
diff -Nru a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c
--- a/drivers/net/arcnet/rfc1051.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/arcnet/rfc1051.c	Sun Apr 14 12:16:55 2002
@@ -68,6 +68,8 @@
 
 #ifdef MODULE
 
+MODULE_LICENSE("GPL");
+
 int __init init_module(void)
 {
 	printk(VERSION);
diff -Nru a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
--- a/drivers/net/arcnet/rfc1201.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/arcnet/rfc1201.c	Sun Apr 14 12:16:58 2002
@@ -70,6 +70,8 @@
 
 #ifdef MODULE
 
+MODULE_LICENSE("GPL");
+
 int __init init_module(void)
 {
 	printk(VERSION);
diff -Nru a/drivers/net/ariadne.c b/drivers/net/ariadne.c
--- a/drivers/net/ariadne.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/ariadne.c	Sun Apr 14 12:16:59 2002
@@ -847,3 +847,5 @@
 
 module_init(ariadne_probe);
 module_exit(ariadne_cleanup);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c
--- a/drivers/net/ariadne2.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/ariadne2.c	Sun Apr 14 12:16:55 2002
@@ -30,7 +30,7 @@
 #include <linux/zorro.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
+
 #include <asm/irq.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
@@ -142,15 +142,15 @@
     {
 	unsigned long reset_start_time = jiffies;
 
-	writeb(readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+	z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
-	while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+	while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
 	    if (jiffies - reset_start_time > 2*HZ/100) {
 		printk(" not found (no reset ack).\n");
 		return -ENODEV;
 	    }
 
-	writeb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
+	z_writeb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
     }
 
     /* Read the 16 bytes of station address PROM.
@@ -177,16 +177,16 @@
 	    {E8390_RREAD+E8390_START, NE_CMD},
 	};
 	for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) {
-	    writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
+	    z_writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
 	}
     }
     for (i = 0; i < 16; i++) {
-	SA_prom[i] = readb(ioaddr + NE_DATAPORT);
-	(void)readb(ioaddr + NE_DATAPORT);
+	SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
+	(void)z_readb(ioaddr + NE_DATAPORT);
     }
 
     /* We must set the 8390 for word mode. */
-    writeb(0x49, ioaddr + NE_EN0_DCFG);
+    z_writeb(0x49, ioaddr + NE_EN0_DCFG);
     start_page = NESM_START_PG;
     stop_page = NESM_STOP_PG;
 
@@ -260,18 +260,18 @@
     if (ei_debug > 1)
 	printk("resetting the 8390 t=%ld...", jiffies);
 
-    writeb(readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+    z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 
     ei_status.txing = 0;
     ei_status.dmaing = 0;
 
     /* This check _should_not_ be necessary, omit eventually. */
-    while ((readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
+    while ((z_readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
 	if (jiffies - reset_start_time > 2*HZ/100) {
 	    printk("%s: ne_reset_8390() did not complete.\n", dev->name);
 	    break;
 	}
-    writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr. */
+    z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr. */
 }
 
 /* Grab the 8390 specific header. Similar to the block_input routine, but
@@ -294,19 +294,19 @@
     }
 
     ei_status.dmaing |= 0x01;
-    writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
-    writeb(0, nic_base + NE_EN0_RCNTHI);
-    writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
-    writeb(ring_page, nic_base + NE_EN0_RSARHI);
-    writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+    z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+    z_writeb(0, nic_base + NE_EN0_RCNTHI);
+    z_writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
+    z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
+    z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
     ptrs = (short*)hdr;
     for (cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
-	*ptrs++ = readw(NE_BASE + NE_DATAPORT);
+	*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
 
-    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
 
     hdr->count = WORDSWAP(hdr->count);
 
@@ -316,7 +316,7 @@
 /* Block input and output, similar to the Crynwr packet driver.  If you
    are porting to a new ethercard, look at the packet driver source for hints.
    The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using writeb. */
+   the packet out through the "remote DMA" dataport using z_writeb. */
 
 static void ariadne2_block_input(struct net_device *dev, int count,
 				 struct sk_buff *skb, int ring_offset)
@@ -334,20 +334,20 @@
 	return;
     }
     ei_status.dmaing |= 0x01;
-    writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
-    writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
-    writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
-    writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+    z_writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+    z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+    z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+    z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
     ptrs = (short*)buf;
     for (cnt = 0; cnt < (count>>1); cnt++)
-	*ptrs++ = readw(NE_BASE + NE_DATAPORT);
+	*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
     if (count & 0x01)
-	buf[count-1] = readb(NE_BASE + NE_DATAPORT);
+	buf[count-1] = z_readb(NE_BASE + NE_DATAPORT);
 
-    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
     ei_status.dmaing &= ~0x01;
 }
 
@@ -375,24 +375,24 @@
     }
     ei_status.dmaing |= 0x01;
     /* We should already be in page 0, but to be safe... */
-    writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+    z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
 
-    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
 
    /* Now the normal output. */
-    writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
-    writeb(0x00, nic_base + NE_EN0_RSARLO);
-    writeb(start_page, nic_base + NE_EN0_RSARHI);
+    z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    z_writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+    z_writeb(0x00, nic_base + NE_EN0_RSARLO);
+    z_writeb(start_page, nic_base + NE_EN0_RSARHI);
 
-    writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+    z_writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
     ptrs = (short*)buf;
     for (cnt = 0; cnt < count>>1; cnt++)
-	writew(*ptrs++, NE_BASE+NE_DATAPORT);
+	z_writew(*ptrs++, NE_BASE+NE_DATAPORT);
 
     dma_start = jiffies;
 
-    while ((readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+    while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
 	if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
 		printk("%s: timeout waiting for Tx RDC.\n", dev->name);
 		ariadne2_reset_8390(dev);
@@ -400,7 +400,7 @@
 		break;
 	}
 
-    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
     ei_status.dmaing &= ~0x01;
     return;
 }
@@ -423,3 +423,5 @@
 
 module_init(ariadne2_probe);
 module_exit(ariadne2_cleanup);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/arlan.c b/drivers/net/arlan.c
--- a/drivers/net/arlan.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/arlan.c	Sun Apr 14 12:16:55 2002
@@ -128,7 +128,7 @@
 
 EXPORT_SYMBOL(arlan_command);
 
-extern inline long long arlan_time(void)
+static inline long long arlan_time(void)
 {
 	struct timeval timev;
 	do_gettimeofday(&timev);
@@ -186,7 +186,7 @@
 
 
 
-extern inline int arlan_drop_tx(struct net_device *dev)
+static inline int arlan_drop_tx(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -554,7 +554,7 @@
 
 };
 
-extern inline void arlan_command_process(struct net_device *dev)
+static inline void arlan_command_process(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -575,7 +575,7 @@
 }
 
 
-extern inline void arlan_retransmit_now(struct net_device *dev)
+static inline void arlan_retransmit_now(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -677,7 +677,7 @@
 		arlan_retransmit_now(dev);
 	}
 	if (!registrationBad(dev) &&
-		priv->tx_done_delayed < jiffies &&
+		time_after(jiffies, priv->tx_done_delayed) &&
 		priv->tx_done_delayed != 0)
 	{
 		TXLAST(dev).offset = 0;
@@ -1405,7 +1405,7 @@
 }
 
 
-extern inline int DoNotReTransmitCrap(struct net_device *dev)
+static inline int DoNotReTransmitCrap(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1415,7 +1415,7 @@
 
 }
 
-extern inline int DoNotWaitReTransmitCrap(struct net_device *dev)
+static inline int DoNotWaitReTransmitCrap(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
@@ -1424,7 +1424,7 @@
 	return 0;
 }
 
-extern inline void arlan_queue_retransmit(struct net_device *dev)
+static inline void arlan_queue_retransmit(struct net_device *dev)
 {
 	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
 
diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c
--- a/drivers/net/at1700.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/at1700.c	Sun Apr 14 12:16:57 2002
@@ -465,7 +465,7 @@
 #define EE_DATA_READ	0x80	/* EEPROM chip data out, in reg. 17. */
 
 /* Delay between EEPROM clock transitions. */
-#define eeprom_delay()	do {} while (0);
+#define eeprom_delay()	do { } while (0)
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
diff -Nru a/drivers/net/atp.c b/drivers/net/atp.c
--- a/drivers/net/atp.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/atp.c	Sun Apr 14 12:16:58 2002
@@ -667,7 +667,7 @@
 			}
 			num_tx_since_rx++;
 		} else if (num_tx_since_rx > 8
-				   && jiffies > dev->last_rx + HZ) {
+				   && time_after(jiffies, dev->last_rx + HZ)) {
 			if (net_debug > 2)
 				printk(KERN_DEBUG "%s: Missed packet? No Rx after %d Tx and "
 					   "%ld jiffies status %02x  CMR1 %02x.\n", dev->name,
diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
--- a/drivers/net/au1000_eth.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/au1000_eth.c	Sun Apr 14 12:16:54 2002
@@ -48,6 +48,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/crc32.h>
+#include <asm/mipsregs.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -65,6 +66,7 @@
 static void *dma_alloc(size_t, dma_addr_t *);
 static void dma_free(void *, size_t);
 static void hard_stop(struct net_device *);
+static void enable_rx_tx(struct net_device *dev);
 static int __init au1000_probe1(struct net_device *, long, int, int);
 static int au1000_init(struct net_device *);
 static int au1000_open(struct net_device *);
@@ -79,15 +81,17 @@
 static inline void update_tx_stats(struct net_device *, u32, u32);
 static inline void update_rx_stats(struct net_device *, u32);
 static void au1000_timer(unsigned long);
-static void cleanup_buffers(struct net_device *);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *, int, int);
 static void mdio_write(struct net_device *, int, int, u16);
-static inline void sync(void);
+static void dump_mii(struct net_device *dev, int phy_id);
 
+// externs
 extern  void ack_rise_edge_irq(unsigned int);
-
-static int next_dev;
+extern int get_ethernet_addr(char *ethernet_addr);
+extern inline void str2eaddr(unsigned char *ea, unsigned char *str);
+extern inline unsigned char str2hexnum(unsigned char c);
+extern char * __init prom_getcmdline(void);
 
 /*
  * Theory of operation
@@ -106,24 +110,30 @@
 
 
 /*
- * Base address and interupt of the Au1000 ethernet macs
+ * Base address and interupt of the Au1xxx ethernet macs
  */
 static struct {
 	unsigned int port;
 	int irq;
 } au1000_iflist[NUM_INTERFACES] = {
-	{AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, 
-	{AU1000_ETH1_BASE, AU1000_ETH1_IRQ}
-};
+		{AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, 
+		{AU1000_ETH1_BASE, AU1000_ETH1_IRQ}
+	},
+  au1500_iflist[NUM_INTERFACES] = {
+		{AU1500_ETH0_BASE, AU1000_ETH0_IRQ}, 
+		{AU1500_ETH1_BASE, AU1000_ETH1_IRQ}
+	};
 
 
 static char version[] __devinitdata =
-    "au1000eth.c:0.1 ppopov@mvista.com\n";
+    "au1000eth.c:1.0 ppopov@mvista.com\n";
 
-// FIX! Need real Ethernet addresses
-static unsigned char au1000_mac_addr[2][6] __devinitdata = { 
-	{0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00},
-	{0x00, 0x50, 0xc2, 0x0c, 0x40, 0x00}
+/* These addresses are only used if yamon doesn't tell us what
+ * the mac address is, and the mac address is not passed on the
+ * command line.
+ */
+static unsigned char au1000_mac_addr[6] __devinitdata = { 
+	0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
 };
 
 #define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
@@ -133,11 +143,6 @@
 #define cpu_to_dma32 cpu_to_be32
 #define dma32_to_cpu be32_to_cpu
 
-/* CPU pipeline flush */
-static inline void sync(void)
-{
-	asm volatile ("sync");
-}
 
 /* FIXME 
  * All of the PHY code really should be detached from the MAC 
@@ -148,7 +153,8 @@
 	{"unknown", 
 	"10Base2", "10BaseT", 
 	"AUI",
-	"100BaseT", "100BaseTX", "100BaseFX"};
+	"100BaseT", "100BaseTX", "100BaseFX"
+	};
 
 int bcm_5201_init(struct net_device *dev, int phy_addr)
 {
@@ -169,7 +175,8 @@
 	data = mdio_read(dev, phy_addr, MII_CONTROL);
 	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
 	mdio_write(dev, phy_addr, MII_CONTROL, data);
-	//dump_mii(dev, phy_addr);
+
+	if (au1000_debug > 4) dump_mii(dev, phy_addr);
 	return 0;
 }
 
@@ -229,10 +236,91 @@
 	else {
 		*link = 0;
 		*speed = 0;
+		dev->if_port = IF_PORT_UNKNOWN;
+	}
+	return 0;
+}
+
+int lsi_80227_init(struct net_device *dev, int phy_addr)
+{
+	if (au1000_debug > 4)
+		printk("lsi_80227_init\n");
+
+	/* restart auto-negotiation */
+	mdio_write(dev, phy_addr, 0, 0x3200);
+
+	/* set up LEDs to correct display */
+	mdio_write(dev, phy_addr, 17, 0xffc0);
+
+	if (au1000_debug > 4)
+		dump_mii(dev, phy_addr);
+	return 0;
+}
+
+int lsi_80227_reset(struct net_device *dev, int phy_addr)
+{
+	s16 mii_control, timeout;
+	
+	if (au1000_debug > 4) {
+		printk("lsi_80227_reset\n");
+		dump_mii(dev, phy_addr);
+	}
+
+	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+	mdelay(1);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+		if ((mii_control & MII_CNTL_RESET) == 0)
+			break;
+		mdelay(1);
+	}
+	if (mii_control & MII_CNTL_RESET) {
+		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+		return -1;
 	}
 	return 0;
 }
 
+int
+lsi_80227_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+	u16 mii_data;
+	struct au1000_private *aup;
+
+	if (!dev) {
+		printk(KERN_ERR "lsi_80227_status error: NULL dev\n");
+		return -1;
+	}
+	aup = (struct au1000_private *) dev->priv;
+
+	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+	if (mii_data & MII_STAT_LINK) {
+		*link = 1;
+		mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_STAT);
+		if (mii_data & MII_LSI_STAT_SPD) {
+			if (mii_data & MII_LSI_STAT_FDX) {
+				*speed = IF_PORT_100BASEFX;
+				dev->if_port = IF_PORT_100BASEFX;
+			}
+			else {
+				*speed = IF_PORT_100BASETX;
+				dev->if_port = IF_PORT_100BASETX;
+			}
+		}
+		else  {
+			*speed = IF_PORT_10BASET;
+			dev->if_port = IF_PORT_10BASET;
+		}
+
+	}
+	else {
+		*link = 0;
+		*speed = 0;
+		dev->if_port = IF_PORT_UNKNOWN;
+	}
+	return 0;
+}
 
 int am79c901_init(struct net_device *dev, int phy_addr)
 {
@@ -264,6 +352,12 @@
 	am79c901_status,
 };
 
+struct phy_ops lsi_80227_ops = { 
+	lsi_80227_init,
+	lsi_80227_reset,
+	lsi_80227_status,
+};
+
 static struct mii_chip_info {
 	const char * name;
 	u16 phy_id0;
@@ -272,6 +366,7 @@
 } mii_chip_table[] = {
 	{"Broadcom BCM5201 10/100 BaseT PHY",  0x0040, 0x6212, &bcm_5201_ops },
 	{"AMD 79C901 HomePNA PHY",  0x0000, 0x35c8, &am79c901_ops },
+	{"LSI 80227 10/100 BaseT PHY", 0x0016, 0xf840, &lsi_80227_ops },
 	{0,},
 };
 
@@ -284,7 +379,8 @@
 	while (aup->mac->mii_control & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: read_MII busy timeout!!\n", dev->name);
+			printk(KERN_ERR "%s: read_MII busy timeout!!\n", 
+					dev->name);
 			return -1;
 		}
 	}
@@ -298,7 +394,8 @@
 	while (aup->mac->mii_control & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: mdio_read busy timeout!!\n", dev->name);
+			printk(KERN_ERR "%s: mdio_read busy timeout!!\n", 
+					dev->name);
 			return -1;
 		}
 	}
@@ -314,7 +411,8 @@
 	while (aup->mac->mii_control & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: mdio_write busy timeout!!\n", dev->name);
+			printk(KERN_ERR "%s: mdio_write busy timeout!!\n", 
+					dev->name);
 			return;
 		}
 	}
@@ -363,25 +461,34 @@
 		phy_id1 = mdio_read(dev, phy_addr, MII_PHY_ID1);
 
 		/* search our mii table for the current mii */ 
-		for (i = 0; mii_chip_table[i].phy_id1; i++)
+		for (i = 0; mii_chip_table[i].phy_id1; i++) {
 			if (phy_id0 == mii_chip_table[i].phy_id0 &&
 			    phy_id1 == mii_chip_table[i].phy_id1) {
 				struct mii_phy * mii_phy;
 
-				printk(KERN_INFO "%s: %s found at phy address %d\n",
-				       dev->name, mii_chip_table[i].name, phy_addr);
-				if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) != NULL) {
+				printk(KERN_INFO "%s: %s at phy address %d\n",
+				       dev->name, mii_chip_table[i].name, 
+				       phy_addr);
+				mii_phy = kmalloc(sizeof(struct mii_phy), 
+						GFP_KERNEL);
+				if (mii_phy) {
 					mii_phy->chip_info = mii_chip_table+i;
 					mii_phy->phy_addr = phy_addr;
-					//mii_phy->status = mdio_read(dev, phy_addr, MII_STATUS);
 					mii_phy->next = aup->mii;
-					aup->phy_ops = mii_chip_table[i].phy_ops;
+					aup->phy_ops = 
+						mii_chip_table[i].phy_ops;
 					aup->mii = mii_phy;
+					aup->phy_ops->phy_init(dev,phy_addr);
+				} else {
+					printk(KERN_ERR "%s: out of memory\n",
+							dev->name);
+					return -1;
 				}
 				/* the current mii is on our mii_info_table,
 				   try next address */
 				break;
 			}
+		}
 	}
 
 	if (aup->mii == NULL) {
@@ -391,7 +498,8 @@
 
 	/* use last PHY */
 	aup->phy_addr = aup->mii->phy_addr;
-	printk(KERN_INFO "%s: Using %s as default\n", dev->name, aup->mii->chip_info->name);
+	printk(KERN_INFO "%s: Using %s as default\n", 
+			dev->name, aup->mii->chip_info->name);
 
 	return 0;
 }
@@ -438,7 +546,7 @@
 	if (ret != NULL) {
 		memset(ret, 0, size);
 		*dma_handle = virt_to_bus(ret);
-		ret = KSEG0ADDR(ret);
+		ret = (void *)KSEG0ADDR(ret);
 	}
 	return ret;
 }
@@ -446,11 +554,22 @@
 
 static void dma_free(void *vaddr, size_t size)
 {
-	vaddr = KSEG0ADDR(vaddr);
+	vaddr = (void *)KSEG0ADDR(vaddr);
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
 
+static void enable_rx_tx(struct net_device *dev)
+{
+	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+
+	if (au1000_debug > 4)
+		printk(KERN_INFO "%s: enable_rx_tx\n", dev->name);
+
+	aup->mac->control |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
+	au_sync_delay(10);
+}
+
 static void hard_stop(struct net_device *dev)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
@@ -459,8 +578,7 @@
 		printk(KERN_INFO "%s: hard stop\n", dev->name);
 
 	aup->mac->control &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
-	sync();
-	mdelay(10);
+	au_sync_delay(10);
 }
 
 
@@ -469,39 +587,21 @@
 	u32 flags;
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 
-	if (au1000_debug > 4)
-		printk(KERN_INFO "%s: reset mac, aup %x\n", dev->name, (unsigned)aup);
+	if (au1000_debug > 4) 
+		printk(KERN_INFO "%s: reset mac, aup %x\n", 
+				dev->name, (unsigned)aup);
 
 	spin_lock_irqsave(&aup->lock, flags);
 	del_timer(&aup->timer);
 	hard_stop(dev);
-	*aup->enable |= MAC_DMA_RESET;
-	sync();
-	mdelay(10);
+	*aup->enable = MAC_EN_CLOCK_ENABLE;
+	au_sync_delay(2);
+       	*aup->enable = 0;
+	au_sync_delay(2);
 	aup->tx_full = 0;
 	spin_unlock_irqrestore(&aup->lock, flags);
 }
 
-static void cleanup_buffers(struct net_device *dev)
-{
-	int i;
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-
-	for (i=0; i<NUM_RX_DMA; i++) {
-		if (aup->rx_db_inuse[i]) {
-			ReleaseDB(aup, aup->rx_db_inuse[i]);
-			aup->rx_db_inuse[i] = 0;
-		}
-	}
-
-	for (i=0; i<NUM_TX_DMA; i++) {
-		if (aup->tx_db_inuse[i]) {
-			ReleaseDB(aup, aup->tx_db_inuse[i]);
-			aup->tx_db_inuse[i] = 0;
-		}
-	}
-}
-
 
 /* 
  * Setup the receive and transmit "rings".  These pointers are the addresses
@@ -514,44 +614,40 @@
 	int i;
 
 	for (i=0; i<NUM_RX_DMA; i++) {
-		aup->rx_dma_ring[i] = (volatile rx_dma_t *) ioremap_nocache((unsigned long)
-					(rx_base + sizeof(rx_dma_t)*i), sizeof(rx_dma_t));
+		aup->rx_dma_ring[i] = 
+			(volatile rx_dma_t *) (rx_base + sizeof(rx_dma_t)*i);
 	}
 	for (i=0; i<NUM_TX_DMA; i++) {
-		aup->tx_dma_ring[i] = (volatile tx_dma_t *)ioremap_nocache((unsigned long)
-				(tx_base + sizeof(tx_dma_t)*i), sizeof(tx_dma_t));
+		aup->tx_dma_ring[i] = 
+			(volatile tx_dma_t *) (tx_base + sizeof(tx_dma_t)*i);
 	}
 }
 
-/*
- * Probe for a AU1000 ethernet controller.
- */
-int __init au1000_probe(struct net_device *dev)
+static int __init au1000_init_module(void)
 {
-	int base_addr = au1000_iflist[next_dev].port;
-	int irq = au1000_iflist[next_dev].irq;
-
-#ifndef CONFIG_MIPS_AU1000_ENET
-	return -ENODEV;
-#endif
-
-	if (au1000_debug > 4)
-		printk(KERN_INFO "%s: au1000_probe base_addr %x\n", 
-				dev->name, base_addr);
+	int i;
+	int prid;
+	int base_addr, irq;
 
-	if (next_dev >= NUM_INTERFACES) {
-		return -ENODEV;
-	}
-	if (au1000_probe1(dev, base_addr, irq, next_dev) == 0) {
-		next_dev++;
-		return 0;
+	prid = read_32bit_cp0_register(CP0_PRID);
+	for (i=0; i<NUM_INTERFACES; i++) {
+		if ( (prid & 0xffff0000) == 0x00030000 ) {
+			base_addr = au1000_iflist[i].port;
+			irq = au1000_iflist[i].irq;
+		} else if ( (prid & 0xffff0000) == 0x01030000 ) {
+			base_addr = au1500_iflist[i].port;
+			irq = au1500_iflist[i].irq;
+		} else {
+			printk(KERN_ERR "au1000 eth: unknown Processor ID\n");
+			return -ENODEV;
+		}
+		if (au1000_probe1(NULL, base_addr, irq, i) != 0) {
+			return -ENODEV;
+		}
 	}
-	next_dev++;
-	return -ENODEV;
+	return 0;
 }
 
-
-
 static int __init
 au1000_probe1(struct net_device *dev, long ioaddr, int irq, int port_num)
 {
@@ -559,11 +655,8 @@
 	struct au1000_private *aup = NULL;
 	int i, retval = 0;
 	db_dest_t *pDB, *pDBfree;
-	u16 link, speed;
-
-	if ((ioaddr != AU1000_ETH0_BASE) && (ioaddr != AU1000_ETH1_BASE))  {
-		return -ENODEV;
-	}
+	char *pmac, *argptr;
+	char ethaddr[6];
 
 	if (!request_region(ioaddr, MAC_IOSIZE, "Au1000 ENET")) {
 		 return -ENODEV;
@@ -579,13 +672,13 @@
 		 return -ENODEV;
 	}
 
-	printk("%s: Au1000 ethernet found at 0x%lx, irq %d\n",
-	       dev->name, ioaddr, irq);
-
+	printk("%s: Au1xxx ethernet found at 0x%lx, irq %d\n", 
+			dev->name, ioaddr, irq);
 
 	/* Initialize our private structure */
 	if (dev->priv == NULL) {
-		aup = (struct au1000_private *) kmalloc(sizeof(*aup), GFP_KERNEL);
+		aup = (struct au1000_private *) 
+			kmalloc(sizeof(*aup), GFP_KERNEL);
 		if (aup == NULL) {
 			retval = -ENOMEM;
 			goto free_region;
@@ -598,52 +691,75 @@
 
 
 	/* Allocate the data buffers */
-	aup->vaddr = (u32)dma_alloc(MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS), &aup->dma_addr);
+	aup->vaddr = (u32)dma_alloc(MAX_BUF_SIZE * 
+			(NUM_TX_BUFFS+NUM_RX_BUFFS), &aup->dma_addr);
 	if (!aup->vaddr) {
 		retval = -ENOMEM;
 		goto free_region;
 	}
 
 	/* aup->mac is the base address of the MAC's registers */
-	aup->mac = (volatile mac_reg_t *)ioremap_nocache((unsigned long)ioaddr, sizeof(*aup->mac));
+	aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
 	/* Setup some variables for quick register address access */
-	if (ioaddr == AU1000_ETH0_BASE) {
-		aup->enable = (volatile u32 *)
-			ioremap_nocache((unsigned long)MAC0_ENABLE, sizeof(*aup->enable)); 
-		memcpy(dev->dev_addr, au1000_mac_addr[0], sizeof(dev->dev_addr));
+	switch (ioaddr) {
+	case AU1000_ETH0_BASE:
+	case AU1500_ETH0_BASE:
+		/* check env variables first */
+		if (!get_ethernet_addr(ethaddr)) { 
+			memcpy(au1000_mac_addr, ethaddr, sizeof(dev->dev_addr));
+		} else {
+			/* Check command line */
+			argptr = prom_getcmdline();
+			if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
+				printk(KERN_INFO "%s: No mac address found\n", 
+						dev->name);
+				/* use the hard coded mac addresses */
+			} else {
+				str2eaddr(ethaddr, pmac + strlen("ethaddr="));
+				memcpy(au1000_mac_addr, ethaddr, 
+						sizeof(dev->dev_addr));
+			}
+		}
+		if (ioaddr == AU1000_ETH0_BASE)
+			aup->enable = (volatile u32 *) 
+				((unsigned long)AU1000_MAC0_ENABLE);
+		else
+			aup->enable = (volatile u32 *) 
+				((unsigned long)AU1500_MAC0_ENABLE);
+		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(dev->dev_addr));
 		setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-	}
-	else if (ioaddr == AU1000_ETH1_BASE) {
-		aup->enable = (volatile u32 *)
-			ioremap_nocache((unsigned long)MAC1_ENABLE, sizeof(*aup->enable)); 
-		memcpy(dev->dev_addr, au1000_mac_addr[1], sizeof(dev->dev_addr));
+			break;
+	case AU1000_ETH1_BASE:
+	case AU1500_ETH1_BASE:
+		if (ioaddr == AU1000_ETH1_BASE)
+			aup->enable = (volatile u32 *) 
+				((unsigned long)AU1000_MAC1_ENABLE);
+		else
+			aup->enable = (volatile u32 *) 
+				((unsigned long)AU1500_MAC1_ENABLE);
+		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(dev->dev_addr));
+		dev->dev_addr[4] += 0x10;
 		setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-	}
-	else { /* should never happen */
-		 printk (KERN_ERR "au1000 eth: bad ioaddr %x\n", (unsigned)ioaddr);  
-		 retval = -ENODEV;
-		 goto free_region;
+			break;
+	default:
+		printk(KERN_ERR "%s: bad ioaddr\n", dev->name);
+		break;
+
 	}
 
 	aup->phy_addr = PHY_ADDRESS;
+
 	/* bring the device out of reset, otherwise probing the mii
 	 * will hang */
-	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 |
-		MAC_EN_CLOCK_ENABLE | MAC_EN_TOSS;
-	sync();
-	mdelay(2);
+	*aup->enable = MAC_EN_CLOCK_ENABLE;
+	au_sync_delay(2);
+	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
+		MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
+	au_sync_delay(2);
+
 	if (mii_probe(dev) != 0) {
 		 goto free_region;
 	}
-	aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
-	if (!link) {
-		printk(KERN_INFO "%s: link down resetting...\n", dev->name);
-		aup->phy_ops->phy_reset(dev, aup->phy_addr);
-		aup->phy_ops->phy_init(dev, aup->phy_addr);
-	}
-	else {
-		printk(KERN_INFO "%s: link up (%s)\n", dev->name, phy_link[speed]);
-	}
 
 	pDBfree = NULL;
 	/* setup the data buffer descriptors and attach a buffer to each one */
@@ -689,18 +805,18 @@
 	ether_setup(dev);
 
 	/* 
-	 * The boot code uses the ethernet controller, so reset it to start fresh.
-	 * au1000_init() expects that the device is in reset state.
+	 * The boot code uses the ethernet controller, so reset it to start 
+	 * fresh.  au1000_init() expects that the device is in reset state.
 	 */
 	reset_mac(dev);
-
 	return 0;
 
 free_region:
 	release_region(ioaddr, MAC_IOSIZE);
 	unregister_netdev(dev);
-	if (aup->vaddr)
-		dma_free((void *)aup->vaddr, MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS));
+	if (aup->vaddr) 
+		dma_free((void *)aup->vaddr, 
+				MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS));
 	if (dev->priv != NULL)
 		kfree(dev->priv);
 	kfree(dev);
@@ -724,18 +840,19 @@
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 	u32 flags;
 	int i;
-	u32 value, control;
+	u32 control;
+	u16 link, speed;
 
-	if (au1000_debug > 4) printk("%s: au1000_init", dev->name);
+	if (au1000_debug > 4) printk("%s: au1000_init\n", dev->name);
 
 	spin_lock_irqsave(&aup->lock, flags);
 
 	/* bring the device out of reset */
-	value = MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2 |
-		MAC_EN_CLOCK_ENABLE | MAC_EN_TOSS;
-	*aup->enable = value;
-	sync();
-	mdelay(200);
+	*aup->enable = MAC_EN_CLOCK_ENABLE;
+        au_sync_delay(2);
+	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
+		MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
+	au_sync_delay(20);
 
 	aup->mac->control = 0;
 	aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
@@ -749,13 +866,18 @@
 	for (i=0; i<NUM_RX_DMA; i++) {
 		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
 	}
+	au_sync();
 
-	sync();
+	aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
 	control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
 	control |= MAC_BIG_ENDIAN;
 #endif
+	if (link && (dev->if_port == IF_PORT_100BASEFX)) {
+		control |= MAC_FULL_DUPLEX;
+	}
 	aup->mac->control = control;
+	au_sync();
 
 	spin_unlock_irqrestore(&aup->lock, flags);
 	return 0;
@@ -765,23 +887,22 @@
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-	u16 mii_data, link, speed;
+	unsigned char if_port;
+	u16 link, speed;
 
 	if (!dev) {
 		/* fatal error, don't restart the timer */
 		printk(KERN_ERR "au1000_timer error: NULL dev\n");
 		return;
 	}
-	if (!(dev->flags & IFF_UP)) {
-		goto set_timer;
-	}
 
+	if_port = dev->if_port;
 	if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) {
 		if (link) {
 			if (!(dev->flags & IFF_RUNNING)) {
 				netif_carrier_on(dev);
 				dev->flags |= IFF_RUNNING;
-				printk(KERN_DEBUG "%s: link up\n", dev->name);
+				printk(KERN_INFO "%s: link up\n", dev->name);
 			}
 		}
 		else {
@@ -789,12 +910,27 @@
 				netif_carrier_off(dev);
 				dev->flags &= ~IFF_RUNNING;
 				dev->if_port = 0;
-				printk(KERN_DEBUG "%s: link down\n", dev->name);
+				printk(KERN_INFO "%s: link down\n", dev->name);
 			}
 		}
 	}
 
-set_timer:
+	if (link && (dev->if_port != if_port) && 
+			(dev->if_port != IF_PORT_UNKNOWN)) {
+		hard_stop(dev);
+		if (dev->if_port == IF_PORT_100BASEFX) {
+			printk(KERN_INFO "%s: going to full duplex\n", 
+					dev->name);
+			aup->mac->control |= MAC_FULL_DUPLEX;
+			au_sync_delay(1);
+		}
+		else {
+			aup->mac->control &= ~MAC_FULL_DUPLEX;
+			au_sync_delay(1);
+		}
+		enable_rx_tx(dev);
+	}
+
 	aup->timer.expires = RUN_AT((1*HZ)); 
 	aup->timer.data = (unsigned long)dev;
 	aup->timer.function = &au1000_timer; /* timer handler */
@@ -820,8 +956,10 @@
 	}
 	netif_start_queue(dev);
 
-	if ((retval = request_irq(dev->irq, &au1000_interrupt, 0, dev->name, dev))) {
-		printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq);
+	if ((retval = request_irq(dev->irq, &au1000_interrupt, 0, 
+					dev->name, dev))) {
+		printk(KERN_ERR "%s: unable to get IRQ %d\n", 
+				dev->name, dev->irq);
 		MOD_DEC_USE_COUNT;
 		return retval;
 	}
@@ -861,8 +999,13 @@
 	return 0;
 }
 
+static void __exit au1000_cleanup_module(void)
+{
+}
 
-static inline void update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
+
+static inline void 
+update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 	struct net_device_stats *ps = &aup->stats;
@@ -871,10 +1014,20 @@
 	ps->tx_bytes += pkt_len;
 
 	if (status & TX_FRAME_ABORTED) {
-		ps->tx_errors++;
-		ps->tx_aborted_errors++;
-		if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
-			ps->tx_carrier_errors++;
+		if (dev->if_port == IF_PORT_100BASEFX) {
+			if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
+				/* any other tx errors are only valid
+				 * in half duplex mode */
+				ps->tx_errors++;
+				ps->tx_aborted_errors++;
+			}
+		}
+		else {
+			ps->tx_errors++;
+			ps->tx_aborted_errors++;
+			if (status & (TX_NO_CARRIER | TX_LOSS_CARRIER))
+				ps->tx_carrier_errors++;
+		}
 	}
 }
 
@@ -895,7 +1048,7 @@
 		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
 		ptxd->buff_stat &= ~TX_T_DONE;
 		ptxd->len = 0;
-		sync();
+		au_sync();
 
 		aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
 		ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -914,26 +1067,22 @@
 static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-	//unsigned long flags;
 	volatile tx_dma_t *ptxd;
 	u32 buff_stat;
 	db_dest_t *pDB;
 	int i;
 
 	if (au1000_debug > 4)
-		printk("%s: tx: aup %x len=%d, data=%p, head %d\n",
-		       dev->name, (unsigned)aup, skb->len, skb->data, aup->tx_head);
+		printk("%s: tx: aup %x len=%d, data=%p, head %d\n", 
+				dev->name, (unsigned)aup, skb->len, 
+				skb->data, aup->tx_head);
 
-	/* Prevent interrupts from changing the Tx ring */
-	//spin_lock_irqsave(&aup->lock, flags);
-	
 	ptxd = aup->tx_dma_ring[aup->tx_head];
 	buff_stat = ptxd->buff_stat;
 	if (buff_stat & TX_DMA_ENABLE) {
 		/* We've wrapped around and the transmitter is still busy */
 		netif_stop_queue(dev);
 		aup->tx_full = 1;
-		//spin_unlock_irqrestore(&aup->lock, flags);
 		return 1;
 	}
 	else if (buff_stat & TX_T_DONE) {
@@ -958,11 +1107,10 @@
 		ptxd->len = skb->len;
 
 	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
-	sync();
+	au_sync();
 	dev_kfree_skb(skb);
 	aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
 	dev->trans_start = jiffies;
-	//spin_unlock_irqrestore(&aup->lock, flags);
 	return 0;
 }
 
@@ -1027,7 +1175,7 @@
 			skb_reserve(skb, 2);	/* 16 byte IP header align */
 			eth_copy_and_sum(skb, (unsigned char *)pDB->vaddr, 
 					status & RX_FRAME_LEN_MASK, 0);
-			skb_put(skb, status & RX_FRAME_LEN_MASK); /* Make room */
+			skb_put(skb, status & RX_FRAME_LEN_MASK);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);	/* pass the packet to upper layers */
 		}
@@ -1057,7 +1205,7 @@
 		}
 		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
 		aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
-		sync();
+		au_sync();
 
 		/* next descriptor */
 		prxd = aup->rx_dma_ring[aup->rx_head];
@@ -1079,8 +1227,8 @@
 		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
 		return;
 	}
-	au1000_rx(dev);
 	au1000_tx_ack(dev);
+	au1000_rx(dev);
 }
 
 
@@ -1099,9 +1247,8 @@
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 
-	/* fixme */
 	if (au1000_debug > 4) 
-		printk("%s: set_multicast: flags=%x\n", dev->name, dev->flags);
+		printk("%s: set_rx_mode: flags=%x\n", dev->name, dev->flags);
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
 		aup->mac->control |= MAC_PROMISCUOUS;
@@ -1123,6 +1270,7 @@
 		}
 		aup->mac->multi_hash_high = mc_filter[1];
 		aup->mac->multi_hash_low = mc_filter[0];
+		aup->mac->control &= ~MAC_PROMISCUOUS;
 		aup->mac->control |= MAC_HASH_MODE;
 	}
 }
@@ -1130,24 +1278,23 @@
 
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	//struct au1000_private *aup = (struct au1000_private *) dev->priv;
 	u16 *data = (u16 *)&rq->ifr_data;
 
 	/* fixme */
 	switch(cmd) { 
-		case SIOCGMIIPHY:		/* Get the address of the PHY in use. */
+	case SIOCGMIIPHY:		/* Get the address of the PHY in use. */
 		data[0] = PHY_ADDRESS;
 
-		case SIOCGMIIREG:		/* Read the specified MII register. */
+	case SIOCGMIIREG:		/* Read the specified MII register. */
 		//data[3] = mdio_read(ioaddr, data[0], data[1]); 
 		return 0;
 
-		case SIOCSMIIREG:		/* Write the specified MII register */
+	case SIOCSMIIREG:		/* Write the specified MII register */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		//mdio_write(ioaddr, data[0], data[1], data[2]);
 		return 0;
-		default:
+	default:
 		return -EOPNOTSUPP;
 	}
 }
@@ -1165,7 +1312,8 @@
 
 	switch(map->port){
 		case IF_PORT_UNKNOWN: /* use auto here */   
-			printk("auto\\n");
+			printk(KERN_INFO "%s: config phy for aneg\n", 
+					dev->name);
 			dev->if_port = map->port;
 			/* Link Down: the timer will bring it up */
 			netif_carrier_off(dev);
@@ -1175,13 +1323,15 @@
 			control &= ~(MII_CNTL_FDX | MII_CNTL_F100);
 
 			/* enable auto negotiation and reset the negotiation */
-			mdio_write(dev, aup->phy_addr,
-				   MII_CONTROL, control | MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
+			mdio_write(dev, aup->phy_addr, MII_CONTROL, 
+					control | MII_CNTL_AUTO | 
+					MII_CNTL_RST_AUTO);
 
 			break;
     
 		case IF_PORT_10BASET: /* 10BaseT */         
-			printk("10baseT\n");
+			printk(KERN_INFO "%s: config phy for 10BaseT\n", 
+					dev->name);
 			dev->if_port = map->port;
 	
 			/* Link Down: the timer will bring it up */
@@ -1189,8 +1339,8 @@
 
 			/* set Speed to 10Mbps, Half Duplex */
 			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-			printk("read control %x\n", control);
-			control &= ~(MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_FDX);
+			control &= ~(MII_CNTL_F100 | MII_CNTL_AUTO | 
+					MII_CNTL_FDX);
 	
 			/* disable auto negotiation and force 10M/HD mode*/
 			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
@@ -1198,7 +1348,8 @@
     
 		case IF_PORT_100BASET: /* 100BaseT */
 		case IF_PORT_100BASETX: /* 100BaseTx */ 
-			printk("100 base T/TX\n");
+			printk(KERN_INFO "%s: config phy for 100BaseTX\n", 
+					dev->name);
 			dev->if_port = map->port;
 	
 			/* Link Down: the timer will bring it up */
@@ -1214,7 +1365,8 @@
 			break;
     
 		case IF_PORT_100BASEFX: /* 100BaseFx */
-			printk("100 Base FX\n");
+			printk(KERN_INFO "%s: config phy for 100BaseFX\n", 
+					dev->name);
 			dev->if_port = map->port;
 	
 			/* Link Down: the timer will bring it up */
@@ -1230,12 +1382,14 @@
 		case IF_PORT_10BASE2: /* 10Base2 */
 		case IF_PORT_AUI: /* AUI */
 		/* These Modes are not supported (are they?)*/
-			printk(KERN_INFO "Not supported");
+			printk(KERN_ERR "%s: 10Base2/AUI not supported", 
+					dev->name);
 			return -EOPNOTSUPP;
 			break;
     
 		default:
-			printk("Invalid");
+			printk(KERN_ERR "%s: Invalid media selected", 
+					dev->name);
 			return -EINVAL;
 	}
 	return 0;
@@ -1253,3 +1407,6 @@
 	}
 	return 0;
 }
+
+module_init(au1000_init_module);
+module_exit(au1000_cleanup_module);
diff -Nru a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
--- a/drivers/net/au1000_eth.h	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/au1000_eth.h	Sun Apr 14 12:16:57 2002
@@ -39,7 +39,7 @@
 #define ETH_TX_TIMEOUT HZ/4
 #define MAC_MIN_PKT_SIZE 64
 
-#ifdef CONFIG_MIPS_PB1000
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1500)
 #define PHY_ADDRESS              0
 #define PHY_CONTROL_DEFAULT 0x3000
 #define PHY_CONTROL_REG_ADDR     0
@@ -60,7 +60,9 @@
 #define MII_ANLPAR  0x0005
 #define MII_AEXP    0x0006
 #define MII_ANEXT   0x0007
-#define MII_AUX_CNTRL 0x18
+#define MII_LSI_CONFIG 0x0011
+#define MII_LSI_STAT   0x0012
+#define MII_AUX_CNTRL  0x0018
 
 /* mii registers specific to AMD 79C901 */
 #define	MII_STATUS_SUMMARY = 0x0018
@@ -123,6 +125,11 @@
 #define MII_STSSUM_DPLX  0x0004
 #define	MII_STSSUM_AUTO  0x0002
 #define MII_STSSUM_SPD   0x0001
+
+/* lsi status register */
+
+#define MII_LSI_STAT_FDX	0x0008
+#define MII_LSI_STAT_SPD	0x0010
 
 /* Auxilliary Control/Status Register */
 #define MII_AUX_FDX      0x0001
diff -Nru a/drivers/net/daynaport.c b/drivers/net/daynaport.c
--- a/drivers/net/daynaport.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/daynaport.c	Sun Apr 14 12:16:54 2002
@@ -513,14 +513,14 @@
                ei_status.tx_start_page = CABLETRON_TX_START_PG;
                ei_status.rx_start_page = CABLETRON_RX_START_PG;
                ei_status.stop_page = CABLETRON_RX_STOP_PG;
-               dev->rmem_start = dev->mem_start;
-               dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
+               ei_status.rmem_start = dev->mem_start;
+               ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
        } else {
                ei_status.tx_start_page = WD_START_PG;
                ei_status.rx_start_page = WD_START_PG + TX_PAGES;
                ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
-               dev->rmem_start = dev->mem_start + TX_PAGES*256;
-               dev->rmem_end = dev->mem_end;
+               ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+               ei_status.rmem_end = dev->mem_end;
        }
 	
 	if(promoff==-1)		/* Use nubus resources ? */
@@ -779,14 +779,14 @@
 	 *	is word per long onto our space.
 	 */
 	 
-	if (xfer_start + count > dev->rmem_end) 
+	if (xfer_start + count > ei_status.rmem_end) 
 	{
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
 		count -= semi_count;
 		dayna_memcpy_fromcard(dev, skb->data + semi_count, 
-			dev->rmem_start - dev->mem_start, count);
+			ei_status.rmem_start - dev->mem_start, count);
 	}
 	else
 	{
@@ -820,14 +820,14 @@
 	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
 	unsigned long xfer_start = xfer_base+dev->mem_start;
 
-	if (xfer_start + count > dev->rmem_end) 
+	if (xfer_start + count > ei_status.rmem_end) 
 	{
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		memcpy(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
 		count -= semi_count;
 		memcpy(skb->data + semi_count, 
-			(char *)dev->rmem_start, count);
+			(char *)ei_status.rmem_start, count);
 	}
 	else
 	{
@@ -881,14 +881,14 @@
 	unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
 	unsigned long xfer_start = xfer_base+dev->mem_start;
 
-	if (xfer_start + count > dev->rmem_end) 
+	if (xfer_start + count > ei_status.rmem_end) 
 	{
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
 		count -= semi_count;
 		word_memcpy_fromcard(skb->data + semi_count, 
-			(char *)dev->rmem_start, count);
+			(char *)ei_status.rmem_start, count);
 	}
 	else
 	{
@@ -919,12 +919,4 @@
 #endif	
 }
 
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c"
- *  version-control: t
- *  c-basic-offset: 4
- *  tab-width: 4
- *  kept-new-versions: 5
- * End:
- */
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/de620.c b/drivers/net/de620.c
--- a/drivers/net/de620.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/de620.c	Sun Apr 14 12:16:54 2002
@@ -449,11 +449,17 @@
 		return ret;
 	}
 
-	if (adapter_init(dev))
-		return -EIO;
+	if (adapter_init(dev)) {
+		ret = -EIO;
+		goto out_free_irq;
+	}
 
 	netif_start_queue(dev);
 	return 0;
+
+out_free_irq:
+	free_irq(dev->irq, dev);
+	return ret;
 }
 
 /************************************************
@@ -850,7 +856,10 @@
 		return -EBUSY;
 	}
 #endif
-	request_region(dev->base_addr, 3, "de620");
+	if (!request_region(dev->base_addr, 3, "de620")) {
+		printk(KERN_ERR "io 0x%3lX, which is busy.\n", dev->base_addr);
+		return -EBUSY;
+	}
 
 	/* else, got it! */
 	printk(", Ethernet Address: %2.2X",
diff -Nru a/drivers/net/dl2k.c b/drivers/net/dl2k.c
--- a/drivers/net/dl2k.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/dl2k.c	Sun Apr 14 12:16:58 2002
@@ -1,6 +1,6 @@
 /*  D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
 /*
-    Copyright (c) 2001 by D-Link Corporation
+    Copyright (c) 2001,2002 by D-Link Corporation
     Written by Edward Peng.<edward_peng@dlink.com.tw>
     Created 03-May-2001, base on Linux' sundance.c.
 
@@ -27,12 +27,14 @@
 				Added tx_coalesce paramter.
     1.07	2002/01/03	Fixed miscount of RX frame error.
     1.08	2002/01/17	Fixed the multicast bug.
+    1.09	2002/03/07	Move rx-poll-now to re-fill loop.	
+    				Added rio_timer() to watch rx buffers. 
  */
 
 #include "dl2k.h"
 
 static char version[] __devinitdata =
-    KERN_INFO "D-Link DL2000-based linux driver v1.08 2002/01/17\n";
+    KERN_INFO "D-Link DL2000-based linux driver v1.09 2002/03/07\n";
 
 #define MAX_UNITS 8
 static int mtu[MAX_UNITS];
@@ -42,9 +44,10 @@
 static int tx_flow[MAX_UNITS];
 static int rx_flow[MAX_UNITS];
 static int copy_thresh;
-static int rx_coalesce = DEFAULT_RXC;
-static int rx_timeout = DEFAULT_RXT;	
-static int tx_coalesce = DEFAULT_TXC;	
+static int rx_coalesce;			/* Rx frame count each interrupt */
+static int rx_timeout; 			/* Rx DMA wait time in 64ns increments */
+static int tx_coalesce = DEFAULT_TXC; 	/* HW xmit count each TxComplete [1-8] */
+
 
 MODULE_AUTHOR ("Edward Peng");
 MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
@@ -71,6 +74,7 @@
 static int multicast_filter_limit = 0x40;
 
 static int rio_open (struct net_device *dev);
+static void rio_timer (unsigned long data);
 static void tx_timeout (struct net_device *dev);
 static void alloc_list (struct net_device *dev);
 static int start_xmit (struct sk_buff *skb, struct net_device *dev);
@@ -146,6 +150,7 @@
 	np->chip_id = chip_idx;
 	np->pdev = pdev;
 	spin_lock_init (&np->lock);
+	spin_lock_init (&np->rx_lock);
 
 	/* Parse manual configuration */
 	np->an_enable = 1;
@@ -260,6 +265,7 @@
 			np->an_enable = 1;
 		mii_set_media (dev);
 	}
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
 
 	/* Reset all logic functions */
 	writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
@@ -340,7 +346,7 @@
 	}
 
 	/* Check CRC */
-	crc = ~ether_crc_le(256 - 4, sromdata);
+ 	crc = ~ether_crc_le(256 - 4, sromdata);
 	if (psrom->crc != crc) {
 		printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
 		return -1;
@@ -421,8 +427,10 @@
 			ioaddr + RxDMAIntCtrl);
 	}
 	/* Set RIO to poll every N*320nsec. */
-	writeb (0xff, ioaddr + RxDMAPollPeriod);
+	writeb (0x20, ioaddr + RxDMAPollPeriod);
 	writeb (0xff, ioaddr + TxDMAPollPeriod);
+	writeb (0x30, ioaddr + RxDMABurstThresh);
+	writeb (0x30, ioaddr + RxDMAUrgentThresh);
 	netif_start_queue (dev);
 	writel (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl);
 	/* VLAN supported */
@@ -445,9 +453,59 @@
 
 	/* clear statistics */
 	get_stats (dev);
+	init_timer (&np->timer);
+	np->timer.expires = jiffies + 1*HZ;
+	np->timer.data = (unsigned long) dev;
+	np->timer.function = &rio_timer;
+	add_timer (&np->timer);
 	return 0;
 }
+static void 
+rio_timer (unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct netdev_private *np = dev->priv;
+	unsigned int entry;
+	int next_tick = 1*HZ;
+	unsigned long flags;
 
+	/* Recover rx ring exhausted error */
+	if (np->cur_rx - np->old_rx >= RX_RING_SIZE) {
+		printk(KERN_INFO "Try to recover rx ring exhausted...\n");
+		spin_lock_irqsave(&np->rx_lock, flags);
+		/* Re-allocate skbuffs to fill the descriptor ring */
+		for (; np->cur_rx - np->old_rx > 0; np->old_rx++) {
+			struct sk_buff *skb;
+			entry = np->old_rx % RX_RING_SIZE;
+			/* Dropped packets don't need to re-allocate */
+			if (np->rx_skbuff[entry] == NULL) {
+				skb = dev_alloc_skb (np->rx_buf_sz);
+				if (skb == NULL) {
+					np->rx_ring[entry].fraginfo = 0;
+					printk (KERN_INFO
+						"%s: Still unable to re-allocate Rx skbuff.#%d\n",
+						dev->name, entry);
+					break;
+				}
+				np->rx_skbuff[entry] = skb;
+				skb->dev = dev;
+				/* 16 byte align the IP header */
+				skb_reserve (skb, 2);
+				np->rx_ring[entry].fraginfo =
+				    cpu_to_le64 (pci_map_single
+					 (np->pdev, skb->tail, np->rx_buf_sz,
+					  PCI_DMA_FROMDEVICE));
+			}
+			np->rx_ring[entry].fraginfo |=
+			    cpu_to_le64 (np->rx_buf_sz) << 48;
+			np->rx_ring[entry].status = 0;
+		} /* end for */
+		spin_unlock_irqrestore (&np->rx_lock, flags);
+	} /* end if */
+	np->timer.expires = jiffies + next_tick;
+	add_timer(&np->timer);
+}
+	
 static void
 tx_timeout (struct net_device *dev)
 {
@@ -499,16 +557,14 @@
 		np->tx_ring[i].status = cpu_to_le64 (TFDDone);
 		np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma +
 					      ((i+1)%TX_RING_SIZE) *
-					      sizeof (struct
-					      netdev_desc));
+					      sizeof (struct netdev_desc));
 	}
 
 	/* Initialize Rx descriptors */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma +
 						((i + 1) % RX_RING_SIZE) *
-						sizeof (struct
-						netdev_desc));
+						sizeof (struct netdev_desc));
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].fraginfo = 0;
 		np->rx_skbuff[i] = 0;
@@ -529,8 +585,8 @@
 		skb_reserve (skb, 2);	/* 16 byte align the IP header. */
 		/* Rubicon now supports 40 bits of addressing space. */
 		np->rx_ring[i].fraginfo =
-		    cpu_to_le64 (pci_map_single
-				 (np->pdev, skb->tail, np->rx_buf_sz,
+		    cpu_to_le64 ( pci_map_single (
+			 	  np->pdev, skb->tail, np->rx_buf_sz,
 				  PCI_DMA_FROMDEVICE));
 		np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48;
 	}
@@ -773,6 +829,8 @@
 	int entry = np->cur_rx % RX_RING_SIZE;
 	int cnt = np->old_rx + RX_RING_SIZE - np->cur_rx;
 	int rx_shift;
+
+	spin_lock (&np->rx_lock);
 	if (np->old_rx > RX_RING_SIZE) {
 		rx_shift = RX_RING_SIZE;
 		np->old_rx -= rx_shift;
@@ -828,12 +886,14 @@
 				skb_put (skb, pkt_len);
 			}
 			skb->protocol = eth_type_trans (skb, dev);
-#if 0
+#if 0			
 			/* Checksum done by hw, but csum value unavailable. */
-			if (!(frame_status & (TCPError | UDPError | IPError))) {
+			if (np->pci_rev_id >= 0x0c && 
+				!(frame_status & (TCPError | UDPError | IPError))) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
-			}
+			} 
 #endif
+					
 			netif_rx (skb);
 			dev->last_rx = jiffies;
 		}
@@ -849,9 +909,10 @@
 			skb = dev_alloc_skb (np->rx_buf_sz);
 			if (skb == NULL) {
 				np->rx_ring[entry].fraginfo = 0;
-				printk (KERN_ERR
-					"%s: Allocate Rx buffer error!",
-					dev->name);
+				printk (KERN_INFO
+					"%s: receive_packet: "
+					"Unable to re-allocate Rx skbuff.#%d\n",
+					dev->name, entry);
 				break;
 			}
 			np->rx_skbuff[entry] = skb;
@@ -866,13 +927,12 @@
 		np->rx_ring[entry].fraginfo |=
 		    cpu_to_le64 (np->rx_buf_sz) << 48;
 		np->rx_ring[entry].status = 0;
+		/* RxDMAPollNow */
+		writel (readl (dev->base_addr + DMACtrl) | 0x00000010,
+			dev->base_addr + DMACtrl);
 	}
-
-	/* RxDMAPollNow */
-	writel (readl (dev->base_addr + DMACtrl) | 0x00000010,
-		dev->base_addr + DMACtrl);
-
 	DEBUG_RFD_DUMP (np, 2);
+	spin_unlock(&np->rx_lock);
 	return 0;
 }
 
@@ -1006,7 +1066,7 @@
 	
 	hash_table[0] = hash_table[1] = 0;
 	/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
-	hash_table[1] |= 0x02000000;
+	hash_table[1] |= cpu_to_le32(0x02000000);
 	if (dev->flags & IFF_PROMISC) {
 		/* Receive all frames promiscuously. */
 		rx_mode = ReceiveAllFrames;
@@ -1020,11 +1080,16 @@
 		rx_mode =
 		    ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
 		for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; 
-				i++, mclist=mclist->next) {
+			i++, mclist=mclist->next) {
+
 			crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
-			for (index=0, bit=0; bit<6; bit++, crc<<=1) {
-				if (crc & 0x80000000) index |= 1 << bit;
-			}
+
+			/* The inverted high significant 6 bits of CRC are
+			   used as an index to hashtable */
+			for (index = 0, bit = 0; bit < 6; bit++)
+				if (test_bit(31 - bit, &crc))
+					set_bit(bit, &index);
+
 			hash_table[index / 32] |= (1 << (index % 32));
 		}
 	} else {
@@ -1094,6 +1159,7 @@
 		     np->old_rx);
 		break;
 	case SIOCDEVPRIVATE + 8:
+		printk("TX ring:\n");
 		for (i = 0; i < TX_RING_SIZE; i++) {
 			desc = &np->tx_ring[i];
 			printk
@@ -1629,7 +1695,8 @@
 	writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl);
 	synchronize_irq ();
 	free_irq (dev->irq, dev);
-
+	del_timer_sync (&np->timer);
+	
 	/* Free all the skbuffs in the queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].status = 0;
@@ -1679,10 +1746,10 @@
 }
 
 static struct pci_driver rio_driver = {
-	name:"dl2k",
-	id_table:rio_pci_tbl,
-	probe:rio_probe1,
-	remove: __devexit_p(rio_remove1),
+	name:		"dl2k",
+	id_table:	rio_pci_tbl,
+	probe:		rio_probe1,
+	remove:		__devexit_p(rio_remove1),
 };
 
 static int __init
diff -Nru a/drivers/net/dl2k.h b/drivers/net/dl2k.h
--- a/drivers/net/dl2k.h	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/dl2k.h	Sun Apr 14 12:16:57 2002
@@ -1,6 +1,6 @@
 /*  D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
 /*  
-    Copyright (c) 2001 by D-Link Corporation
+    Copyright (c) 2001, 2002 by D-Link Corporation
     Written by Edward Peng.<edward_peng@dlink.com.tw>
     Created 03-May-2001, base on Linux' sundance.c.
 
@@ -649,6 +649,7 @@
 	dma_addr_t rx_ring_dma;
 	struct pci_dev *pdev;
 	spinlock_t lock;
+	spinlock_t rx_lock;
 	struct net_device_stats stats;
 	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
 	unsigned int speed;		/* Operating speed */
@@ -664,9 +665,11 @@
 	unsigned int tx_flow:1;		/* Tx flow control enable */
 	unsigned int rx_flow:1;		/* Rx flow control enable */
 	unsigned int phy_media:1;	/* 1: fiber, 0: copper */
+	unsigned char pci_rev_id;	/* PCI revision ID */
 	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
 	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
 	unsigned long cur_tx, old_tx;
+	struct timer_list timer;
 	int wake_polarity;
 	char name[256];		/* net device description */
 	u8 duplex_polarity;
diff -Nru a/drivers/net/e100/Makefile b/drivers/net/e100/Makefile
--- a/drivers/net/e100/Makefile	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/e100/Makefile	Sun Apr 14 12:16:59 2002
@@ -10,7 +10,7 @@
 O_TARGET := e100.o
 
 obj-y   := e100_main.o e100_config.o e100_proc.o e100_phy.o \
-	   e100_eeprom.o
+	   e100_eeprom.o e100_test.o
 obj-m   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h
--- a/drivers/net/e100/e100.h	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/e100/e100.h	Sun Apr 14 12:16:57 2002
@@ -144,7 +144,8 @@
 
 #define E100_MAX_NIC 16
 
-#define E100_MAX_BUSY_WAIT 50	/*Max udelays in wait_scb and wait_cus_idle */
+#define E100_MAX_SCB_WAIT	100	/* Max udelays in wait_scb */
+#define E100_MAX_CU_IDLE_WAIT	50	/* Max udelays in wait_cus_idle */
 
 /* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled.
  * In some situations, such as the TCP windowing algorithm, it may be
@@ -899,6 +900,15 @@
 	int PollingMaxWork;
 	u32 b_params;
 };
+#ifdef ETHTOOL_TEST 
+struct ethtool_lpbk_data{
+        dma_addr_t dma_handle;
+        tcb_t *tcb;
+        rfd_t *rfd;
+
+};
+#endif
+
 
 struct e100_private {
 	u32 flags;		/* board management flags */
@@ -988,6 +998,9 @@
 	u32 wolopts;
 	u16 ip_lbytes;
 #endif
+#ifdef ETHTOOL_TEST
+struct ethtool_lpbk_data loopback;
+#endif
 
 #ifdef CONFIG_PM
 	u32 pci_state[16];
@@ -1027,5 +1040,24 @@
 				  u8 recover, u8 full_reset);
 extern unsigned char e100_hw_reset_recover(struct e100_private *bdp,
 					   u32 reset_cmd);
+
+#ifdef ETHTOOL_TEST
+
+#define ROM_TEST_FAIL		0x01
+#define REGISTER_TEST_FAIL	0x02
+#define SELF_TEST_FAIL		0x04
+#define TEST_TIMEOUT		0x08
+
+enum test_offsets {
+	E100_EEPROM_TEST_FAIL = 0,
+	E100_CHIP_TIMEOUT,
+	E100_ROM_TEST_FAIL,
+	E100_REG_TEST_FAIL,
+	E100_MAC_TEST_FAIL,
+	E100_LPBK_MAC_FAIL,
+	E100_LPBK_PHY_FAIL,
+	E100_MAX_TEST_RES
+};
+#endif
 
 #endif
diff -Nru a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c
--- a/drivers/net/e100/e100_config.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/e100/e100_config.c	Sun Apr 14 12:16:57 2002
@@ -593,3 +593,102 @@
 }
 #endif
 
+#ifdef ETHTOOL_TEST
+/**
+ * e100_config_loopback_mode
+ * @bdp: atapter's private data struct
+ * @mode: loopback mode(phy/mac/none)
+ *
+ */
+unsigned char
+e100_config_loopback_mode(struct e100_private *bdp, u8 mode)
+{
+	unsigned char bc_changed = false;
+	u8 config_byte;
+
+	spin_lock_bh(&(bdp->config_lock));
+
+	switch (mode) {
+	case NO_LOOPBACK:
+		config_byte = CB_CFIG_LOOPBACK_NORMAL;
+		break;
+	case MAC_LOOPBACK:
+		config_byte = CB_CFIG_LOOPBACK_INTERNAL;
+		break;
+	case PHY_LOOPBACK:
+		config_byte = CB_CFIG_LOOPBACK_EXTERNAL;
+		break;
+	default:
+		printk(KERN_NOTICE "e100_config_loopback_mode: "
+		       "Invalid argument 'mode': %d\n", mode);
+		goto exit;
+	}
+
+	if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) {
+
+		bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE);
+		bdp->config[10] |= config_byte;
+		E100_CONFIG(bdp, 10);
+		bc_changed = true;
+	}
+
+exit:
+	spin_unlock_bh(&(bdp->config_lock));
+	return bc_changed;
+}
+unsigned char
+e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable)
+{
+        unsigned char bc_changed = false;
+ 
+        spin_lock_bh(&(bdp->config_lock));
+ 
+        if (enable) {
+                if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) {
+ 
+                        bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS);
+                        E100_CONFIG(bdp, 6);
+                        bc_changed = true;
+                }
+ 
+        } else {
+                if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) {
+ 
+                        bdp->config[6] |= CB_CFIG_EXT_TCB_DIS;
+                        E100_CONFIG(bdp, 6);
+                        bc_changed = true;
+                }
+        }
+        spin_unlock_bh(&(bdp->config_lock));
+ 
+        return bc_changed;
+}
+unsigned char
+e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
+{
+        unsigned char bc_changed = false;
+ 
+        spin_lock_bh(&(bdp->config_lock));
+ 
+        if (enable) {
+                if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) {
+ 
+                        bdp->config[7] |= CB_CFIG_DYNTBD_EN;
+                        E100_CONFIG(bdp, 7);
+                        bc_changed = true;
+                }
+ 
+        } else {
+                if (bdp->config[7] & CB_CFIG_DYNTBD_EN) {
+ 
+                        bdp->config[7] &= (~CB_CFIG_DYNTBD_EN);
+                        E100_CONFIG(bdp, 7);
+                        bc_changed = true;
+                }
+        }
+        spin_unlock_bh(&(bdp->config_lock));
+ 
+        return bc_changed;
+}
+#endif
+
diff -Nru a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h
--- a/drivers/net/e100/e100_config.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/e100/e100_config.h	Sun Apr 14 12:16:56 2002
@@ -190,6 +190,10 @@
 
 #define CB_CFIG_LONG_RX_OK	    BIT_3
 
+#define NO_LOOPBACK	0	
+#define MAC_LOOPBACK	0x01
+#define PHY_LOOPBACK	0x02
+
 /* function prototypes */
 extern void e100_config_init(struct e100_private *bdp);
 extern unsigned char e100_force_config(struct e100_private *bdp);
@@ -201,5 +205,8 @@
 				     unsigned char enable);
 extern void e100_config_ifs(struct e100_private *bdp);
 extern void e100_config_force_dplx(struct e100_private *bdp);
+extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode);
+extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable);
+extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable);
 
 #endif /* _E100_CONFIG_INC_ */
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/e100/e100_main.c	Sun Apr 14 12:16:58 2002
@@ -147,6 +147,23 @@
 static u16 e100_get_ip_lbytes(struct net_device *dev);
 extern void e100_config_wol(struct e100_private *bdp);
 #endif
+#ifdef ETHTOOL_TEST
+extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags);
+static int e100_ethtool_test(struct net_device *, struct ifreq *);
+#endif
+#ifdef ETHTOOL_GSTRINGS
+static int e100_ethtool_gstrings(struct net_device *, struct ifreq *);
+static char *test_strings[] = {
+	"E100_EEPROM_TEST_FAIL",
+	"E100_CHIP_TIMEOUT",
+	"E100_ROM_TEST_FAIL",
+	"E100_REG_TEST_FAIL",
+	"E100_MAC_TEST_FAIL",
+	"E100_LPBK_MAC_FAIL",
+	"E100_LPBK_PHY_FAIL"
+};
+
+#endif
 #endif /*E100_ETHTOOL_IOCTL */
 
 #ifdef SIOCGMIIPHY
@@ -165,7 +182,7 @@
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation";
 
-#define E100_VERSION  "2.0.24-pre1"
+#define E100_VERSION  "2.0.27-pre3"
 
 #define E100_FULL_DRIVER_NAME 	"Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver "
 
@@ -382,6 +399,7 @@
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION(E100_FULL_DRIVER_NAME E100_VERSION);
 MODULE_LICENSE("Dual BSD/GPL");
+EXPORT_NO_SYMBOLS;
 
 E100_PARAM(TxDescriptors, "Number of transmit descriptors");
 E100_PARAM(RxDescriptors, "Number of receive descriptors");
@@ -409,6 +427,7 @@
 e100_exec_cmd(struct e100_private *bdp, u8 cmd_low)
 {
 	writeb(cmd_low, &(bdp->scb->scb_cmd_low));
+	readw(&(bdp->scb->scb_status));	/* flashes last write, read-safe */
 }
 
 /**
@@ -437,7 +456,7 @@
 	}
 
 	/* it didn't work. do it the slow way using udelay()s */
-	for (i = 0; i < E100_MAX_BUSY_WAIT; i++) {
+	for (i = 0; i < E100_MAX_SCB_WAIT; i++) {
 		if (!readb(&bdp->scb->scb_cmd_low))
 			return true;
 		cpu_relax();
@@ -463,7 +482,7 @@
 e100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low)
 {
 	if (!e100_wait_scb(bdp)) {
-		printk(KERN_ERR "%s e100_wait_exec_simple: Wait failed\n",
+		printk(KERN_DEBUG "%s e100_wait_exec_simple: Wait failed\n",
 		       bdp->device->name);
 		return false;
 	}
@@ -503,7 +522,7 @@
 		cpu_relax();
 	}
 
-	for (i = 0; i < E100_MAX_BUSY_WAIT; i++) {
+	for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) {
 		if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) !=
 		     SCB_CUS_ACTIVE)) {
 			return true;
@@ -2354,11 +2373,13 @@
 	case START_WAIT:
 		// The last command was a non_tx CU command
 		if (!e100_wait_cus_idle(bdp))
-			printk("%s cu_start: timeout waiting for cu\n",
+			printk(KERN_DEBUG
+			       "%s cu_start: timeout waiting for cu\n",
 			       bdp->device->name);
 		if (!e100_wait_exec_cmplx(bdp, (u32) (tcb->tcb_phys),
 					  SCB_CUC_START)) {
-			printk("%s cu_start: timeout waiting for scb\n",
+			printk(KERN_DEBUG
+			       "%s cu_start: timeout waiting for scb\n",
 			       bdp->device->name);
 			e100_exec_cmplx(bdp, (u32) (tcb->tcb_phys),
 					SCB_CUC_START);
@@ -2519,7 +2540,8 @@
 	spin_lock(&bdp->bd_lock);
 
 	if (!e100_wait_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START)) {
-		printk("%s start_ru: wait_scb failed\n", bdp->device->name);
+		printk(KERN_DEBUG
+		       "%s start_ru: wait_scb failed\n", bdp->device->name);
 		e100_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START);
 	}
 	if (bdp->next_cu_cmd == RESUME_NO_WAIT) {
@@ -2715,8 +2737,10 @@
 	ntcb_hdr->cb_lnk_ptr = 0;
 
 	wmb();
+	if (in_interrupt())
+		return e100_delayed_exec_non_cu_cmd(bdp, command);
 
-	if (in_interrupt() || netif_running(bdp->device))
+	if (netif_running(bdp->device) && (!bdp->driver_isolated))
 		return e100_delayed_exec_non_cu_cmd(bdp, command);
 
 	spin_lock_bh(&(bdp->bd_non_tx_lock));
@@ -3302,6 +3326,16 @@
 		rc = e100_ethtool_wol(dev, ifr);
 		break;
 #endif
+#ifdef ETHTOOL_TEST
+	case ETHTOOL_TEST:
+		rc = e100_ethtool_test(dev, ifr);
+		break;
+#endif
+#ifdef ETHTOOL_GSTRINGS
+	case ETHTOOL_GSTRINGS:
+		rc = e100_ethtool_gstrings(dev,ifr);
+		break;
+#endif
 	default:
 		break;
 	}			//switch
@@ -3464,6 +3498,36 @@
 }
 #endif
 
+#ifdef ETHTOOL_TEST
+static int
+e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
+{
+	struct ethtool_test *info;
+	int rc = -EFAULT;
+
+	info = kmalloc(sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64),
+		       GFP_ATOMIC);
+
+	if (!info)
+		return -EFAULT;
+
+	memset((void *) info, 0, sizeof(*info) +
+				 E100_MAX_TEST_RES * sizeof(u64));
+
+	if (copy_from_user(info, ifr->ifr_data, sizeof(*info)))
+		goto exit;
+
+	info->flags = e100_run_diag(dev, info->data, info->flags);
+
+	if (!copy_to_user(ifr->ifr_data, info,
+			 sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64)))
+		rc = 0;
+exit:
+	kfree(info);
+	return rc;
+}
+#endif
+
 #ifdef ETHTOOL_NWAY_RST
 static int
 e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr)
@@ -3505,7 +3569,9 @@
 #ifdef ETHTOOL_GEEPROM
 	info.eedump_len = (bdp->eeprom_size << 1);	
 #endif
-
+#ifdef ETHTOOL_TEST
+	info.testinfo_len = E100_MAX_TEST_RES;
+#endif
 	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
 		return -EFAULT;
 
@@ -3737,6 +3803,51 @@
 	return res;
 }
 
+#endif
+
+#ifdef ETHTOOL_GSTRINGS
+static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
+{
+	struct ethtool_gstrings info;
+	char *strings = NULL;
+	char *usr_strings;
+	int i;
+
+	memset((void *) &info, 0, sizeof(info));
+
+	usr_strings = (u8 *) (ifr->ifr_data + 
+			      offsetof(struct ethtool_gstrings, data));
+
+	if (copy_from_user(&info, ifr->ifr_data, sizeof (info)))
+		return -EFAULT;
+
+	switch (info.string_set) {
+	case ETH_SS_TEST:
+		if (info.len > E100_MAX_TEST_RES)
+			info.len = E100_MAX_TEST_RES;
+		strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
+		if (!strings)
+			return -EFAULT;
+		memset(strings, 0, info.len * ETH_GSTRING_LEN);
+
+		for (i = 0; i < info.len; i++) {
+			sprintf(strings + i * ETH_GSTRING_LEN, "%-31s",
+				test_strings[i]);
+		}
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
+		return -EFAULT;
+
+	if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN))
+		return -EFAULT;
+
+	kfree(strings);
+	return 0;
+}
 #endif
 #endif /*E100_ETHTOOL_IOCTL */
 
diff -Nru a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e100/e100_test.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,467 @@
+/*******************************************************************************
+
+This software program is available to you under a choice of one of two 
+licenses. You may choose to be licensed under either the GNU General Public 
+License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html, 
+or the Intel BSD + Patent License, the text of which follows:
+
+Recipient has requested a license and Intel Corporation ("Intel") is willing
+to grant a license for the software entitled Linux Base Driver for the 
+Intel(R) PRO/100 Family of Adapters (e100) (the "Software") being provided 
+by Intel Corporation. The following definitions apply to this license:
+
+"Licensed Patents" means patent claims licensable by Intel Corporation which 
+are necessarily infringed by the use of sale of the Software alone or when 
+combined with the operating system referred to below.
+
+"Recipient" means the party to whom Intel delivers this Software.
+
+"Licensee" means Recipient and those third parties that receive a license to 
+any operating system available under the GNU General Public License 2.0 or 
+later.
+
+Copyright (c) 1999 - 2002 Intel Corporation.
+All rights reserved.
+
+The license is provided to Recipient and Recipient's Licensees under the 
+following terms.
+
+Redistribution and use in source and binary forms of the Software, with or 
+without modification, are permitted provided that the following conditions 
+are met:
+
+Redistributions of source code of the Software may retain the above 
+copyright notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form of the Software may reproduce the above 
+copyright notice, this list of conditions and the following disclaimer in 
+the documentation and/or materials provided with the distribution.
+
+Neither the name of Intel Corporation nor the names of its contributors 
+shall be used to endorse or promote products derived from this Software 
+without specific prior written permission.
+
+Intel hereby grants Recipient and Licensees a non-exclusive, worldwide, 
+royalty-free patent license under Licensed Patents to make, use, sell, offer 
+to sell, import and otherwise transfer the Software, if any, in source code 
+and object code form. This license shall include changes to the Software 
+that are error corrections or other minor changes to the Software that do 
+not add functionality or features when the Software is incorporated in any 
+version of an operating system that has been distributed under the GNU 
+General Public License 2.0 or later. This patent license shall apply to the 
+combination of the Software and any operating system licensed under the GNU 
+General Public License 2.0 or later if, at the time Intel provides the 
+Software to Recipient, such addition of the Software to the then publicly 
+available versions of such operating systems available under the GNU General 
+Public License 2.0 or later (whether in gold, beta or alpha form) causes 
+such combination to be covered by the Licensed Patents. The patent license 
+shall not apply to any other combinations which include the Software. NO 
+hardware per se is licensed hereunder.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED 
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR 
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+#include "e100.h"
+#include "e100_config.h"
+#ifdef ETHTOOL_TEST
+
+extern u16 e100_eeprom_read(struct e100_private *, u16);
+extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8);
+extern void e100_phy_reset(struct e100_private *bdp);
+
+static u8 e100_diag_selftest(struct net_device *);
+static u8 e100_diag_eeprom(struct net_device *);
+static u8 e100_diag_loopback(struct net_device *);
+
+static u8 e100_diag_one_loopback (struct net_device *, u8);
+static u8 e100_diag_rcv_loopback_pkt(struct e100_private *);
+static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *);
+static u8 e100_diag_loopback_alloc(struct e100_private *);
+static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
+static u8 e100_diag_check_pkt(u8 *);
+static void e100_diag_loopback_free(struct e100_private *);
+
+#define LB_PACKET_SIZE 1500
+
+/**
+ * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines  
+ * @dev: atapter's net device data struct
+ * @test_info: array with test request mask also used to store test results
+ *
+ * RETURNS: updated flags field of struct ethtool_test
+ */
+u32
+e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
+{
+	struct e100_private* bdp = dev->priv;
+	u8 test_result = true;
+
+	e100_isolate_driver(bdp);
+
+	if (flags & ETH_TEST_FL_OFFLINE) {
+		u8 fail_mask;
+		
+		fail_mask = e100_diag_selftest(dev);
+		if (fail_mask) {
+			test_result = false;
+			if (fail_mask & REGISTER_TEST_FAIL)
+				test_info [E100_REG_TEST_FAIL] = true;
+			if (fail_mask & ROM_TEST_FAIL)
+				test_info [E100_ROM_TEST_FAIL] = true;
+			if (fail_mask & SELF_TEST_FAIL)
+				test_info [E100_MAC_TEST_FAIL] = true;
+			if (fail_mask & TEST_TIMEOUT)
+				test_info [E100_CHIP_TIMEOUT] = true;
+		}
+
+		fail_mask = e100_diag_loopback(dev);
+		if (fail_mask) {
+			test_result = false;
+			if (fail_mask & PHY_LOOPBACK)
+				test_info [E100_LPBK_PHY_FAIL] = true;
+			if (fail_mask & MAC_LOOPBACK)
+				test_info [E100_LPBK_MAC_FAIL] = true;
+		}
+	}
+
+	if (!e100_diag_eeprom(dev)) {
+		test_result = false;
+		test_info [E100_EEPROM_TEST_FAIL] = true;
+	}
+
+	/* fully recover only if the device is open*/
+	if (netif_running(dev))  {
+		e100_deisolate_driver(bdp, true, false);
+	} else {
+    		e100_deisolate_driver(bdp, false, false);
+	}
+	/*Let card recover from the test*/
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ * 2);
+
+	return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
+}
+
+/**
+ * e100_diag_selftest - run hardware selftest 
+ * @dev: atapter's net device data struct
+ */
+static u8
+e100_diag_selftest(struct net_device *dev)
+{
+	struct e100_private *bdp = dev->priv;
+	u32 st_timeout, st_result;
+	u8 retval = 0;
+
+	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
+		if (!st_timeout) {
+			if (st_result & CB_SELFTEST_REGISTER_BIT)
+				retval |= REGISTER_TEST_FAIL;
+			if (st_result & CB_SELFTEST_DIAG_BIT)
+				retval |= SELF_TEST_FAIL;
+			if (st_result & CB_SELFTEST_ROM_BIT)
+				retval |= ROM_TEST_FAIL;
+		} else {
+            		retval = TEST_TIMEOUT;
+		}
+	}
+
+	e100_hw_reset_recover(bdp,PORT_SOFTWARE_RESET);
+
+	return retval;
+}
+
+/**
+ * e100_diag_eeprom - validate eeprom checksum correctness
+ * @dev: atapter's net device data struct
+ *
+ */
+static u8
+e100_diag_eeprom (struct net_device *dev)
+{
+	struct e100_private *bdp = dev->priv;
+	u16 i, eeprom_sum, eeprom_actual_csm;
+
+	for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) {
+		eeprom_sum += e100_eeprom_read(bdp, i);
+	}
+
+	eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1);
+
+	if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) {
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * e100_diag_loopback - performs loopback test  
+ * @dev: atapter's net device data struct
+ */
+static u8
+e100_diag_loopback (struct net_device *dev)
+{
+	u8 rc = 0;
+
+	if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
+		rc |= PHY_LOOPBACK;
+	}
+
+	if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
+		rc |= MAC_LOOPBACK;
+	}
+
+	return rc;
+}
+
+/**
+ * e100_diag_loopback - performs loopback test  
+ * @dev: atapter's net device data struct
+ * @mode: lopback test type
+ */
+static u8
+e100_diag_one_loopback (struct net_device *dev, u8 mode)
+{
+        struct e100_private *bdp = dev->priv;
+        u8 res = false;
+   	u8 saved_dynamic_tbd = false;
+   	u8 saved_extended_tcb = false;
+
+	if (!e100_diag_loopback_alloc(bdp))
+		return false;
+
+	/* change the config block to standard tcb and the correct loopback */
+        e100_diag_config_loopback(bdp, true, mode,
+				  &saved_extended_tcb, &saved_dynamic_tbd);
+
+	e100_diag_loopback_cu_ru_exec(bdp);
+
+        if (e100_diag_rcv_loopback_pkt(bdp)) {
+		res = true;
+	}
+
+        e100_diag_loopback_free(bdp);
+
+        /* change the config block to previous tcb mode and the no loopback */
+        e100_diag_config_loopback(bdp, false, mode,
+				  &saved_extended_tcb, &saved_dynamic_tbd);
+	return res;
+}
+
+/**
+ * e100_diag_config_loopback - setup/clear loopback before/after lpbk test
+ * @bdp: atapter's private data struct
+ * @set_loopback: true if the function is called to set lb
+ * @loopback_mode: the loopback mode(MAC or PHY)
+ * @tcb_extended: true if need to set extended tcb mode after clean loopback
+ * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback
+ *
+ */
+void
+e100_diag_config_loopback(struct e100_private* bdp,
+			  u8 set_loopback,
+			  u8 loopback_mode,
+			  u8* tcb_extended,
+			  u8* dynamic_tbd)
+{
+	/* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd.
+	 * the previous values are saved in the params tcb_extended/dynamic_tbd
+	 * if set_loopback == false - we want to restore previous value.
+	 */
+	if (set_loopback || (*tcb_extended))
+		  *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended);
+
+	if (set_loopback || (*dynamic_tbd))
+		 *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
+
+	if (set_loopback) {
+		e100_config_loopback_mode(bdp,loopback_mode);
+	} else {
+		e100_config_loopback_mode(bdp,NO_LOOPBACK);
+	}
+
+	e100_config(bdp);
+
+	if (loopback_mode == PHY_LOOPBACK) {
+		unsigned long expires = jiffies + HZ * 5;
+
+		if (set_loopback)
+			e100_phy_reset(bdp);
+
+		/* wait up to 5 secs for PHY loopback ON/OFF to take effect */
+		while ((e100_get_link_state(bdp) != set_loopback) &&
+		       time_before(jiffies, expires)) {
+			yield();
+		}
+	} else { /* For MAC loopback wait 500 msec to take effect */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ / 2);
+	}
+}
+  
+/**
+ * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback
+ * @bdp: atapter's private data struct
+ *
+ */
+static u8
+e100_diag_loopback_alloc(struct e100_private *bdp)
+{
+	dma_addr_t dma_handle;
+	tcb_t *tcb;
+	rfd_t *rfd;
+	tbd_t *tbd;
+
+	tcb = pci_alloc_consistent(bdp->pdev,
+				   (sizeof (tcb_t) + sizeof (tbd_t) +
+				    LB_PACKET_SIZE),
+				   &dma_handle);
+        if (tcb == NULL)
+		return false;
+
+	memset(tcb, 0x00, sizeof (tcb_t) + LB_PACKET_SIZE);
+	tcb->tcb_phys = dma_handle;
+	tcb->tcb_hdr.cb_status = 0;
+	tcb->tcb_hdr.cb_cmd =
+		cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT);
+	tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(tcb->tcb_phys);
+	tcb->tcb_tbd_ptr = cpu_to_le32(0xffffffff);
+	tcb->tcb_cnt = 0;
+	tcb->tcb_thrshld = bdp->tx_thld;
+	tcb->tcb_tbd_num = 1;
+	tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t));
+	tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t));
+	tbd->tbd_buf_addr =
+		cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t));
+	tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024);
+	memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 1024);
+	memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512);
+	wmb();
+	rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle);
+
+	if (rfd == NULL) {
+		pci_free_consistent(bdp->pdev,
+				    sizeof (tcb_t) + sizeof (tbd_t) +
+				    LB_PACKET_SIZE, tcb, tcb->tcb_phys);
+		return false;
+	}
+
+	memset(rfd, 0x00, sizeof (rfd_t));
+
+	/* init all fields in rfd */
+	rfd->rfd_header.cb_status = 0;
+	rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT);
+	rfd->rfd_act_cnt = 0;
+	rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE);
+	bdp->loopback.dma_handle = dma_handle;
+	bdp->loopback.tcb = tcb;
+	bdp->loopback.rfd = rfd;
+	wmb();
+	return true;
+}
+
+/**
+ * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt
+ * @bdp: atapter's private data struct
+ *
+ */
+static void
+e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
+{
+	/*load CU & RU base */ 
+	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE))
+		printk("@@@ SCB_CUC_LOAD_BASE failed\n");
+	if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE))
+		printk("@@@ SCB_RUC_LOAD_BASE failed!\n");
+	if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START))
+		printk("@@@ SCB_RUC_START failed!\n");
+
+	bdp->next_cu_cmd = START_WAIT;
+	e100_start_cu(bdp, bdp->loopback.tcb);
+	bdp->last_tcb = NULL;
+	rmb();
+}
+/**
+ * e100_diag_check_pkt - checks if a given packet is a loopback packet
+ * @bdp: atapter's private data struct
+ *
+ * Returns true if OK false otherwise.
+ */
+static u8
+e100_diag_check_pkt(u8 *datap)
+{
+        if( (*datap)==0xFF) {
+                if(*(datap + 600) == 0xBA) {
+                        return true;
+                }
+        }
+        return false;
+}
+
+/**
+ * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet
+ * @bdp: atapter's private data struct
+ *
+ * Returns true if OK false otherwise.
+ */
+static u8
+e100_diag_rcv_loopback_pkt(struct e100_private* bdp) 
+{    
+	rfd_t *rfdp;
+	u16 rfd_status;
+	unsigned long expires = jiffies + HZ * 2;
+
+        rfdp =bdp->loopback.rfd;
+
+        rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
+
+        while (!(rfd_status & RFD_STATUS_COMPLETE)) { 
+		if (time_before(jiffies, expires)) {
+			yield();
+			rmb();
+			rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
+		} else {
+			break;
+		}
+        }
+
+        if (rfd_status & RFD_STATUS_COMPLETE)
+                return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size));
+	else
+		return false;
+}
+
+/**
+ * e100_diag_loopback_free - free data allocated for loopback pkt send/receive
+ * @bdp: atapter's private data struct
+ *
+ */
+static void
+e100_diag_loopback_free (struct e100_private *bdp)
+{
+        pci_free_consistent(bdp->pdev,
+			    sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE,
+			    bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys);
+
+        pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd,
+			    bdp->loopback.dma_handle);
+}
+
+#endif
+
+
+
+
+
+
+
+
diff -Nru a/drivers/net/e1000/LICENSE b/drivers/net/e1000/LICENSE
--- a/drivers/net/e1000/LICENSE	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/e1000/LICENSE	Sun Apr 14 12:16:58 2002
@@ -1,8 +1,7 @@
 This software program is available to you under a choice of one of two
 licenses. You may choose to be licensed under either the GNU General Public
-License (GPL) Version 2, June 1991, available at
-http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-text of which follows:
+License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+or the Intel BSD + Patent License, the text of which follows:
 
 Recipient has requested a license and Intel Corporation ("Intel") is willing
 to grant a license for the software entitled Linux Base Driver for the
@@ -16,7 +15,7 @@
 "Recipient" means the party to whom Intel delivers this Software.
 
 "Licensee" means Recipient and those third parties that receive a license to
-any operating system available under the GNU Public License version 2.0 or
+any operating system available under the GNU General Public License 2.0 or
 later.
 
 Copyright (c) 1999 - 2002 Intel Corporation.
@@ -49,10 +48,10 @@
 version of an operating system that has been distributed under the GNU
 General Public License 2.0 or later. This patent license shall apply to the
 combination of the Software and any operating system licensed under the GNU
-Public License version 2.0 or later if, at the time Intel provides the
+General Public License 2.0 or later if, at the time Intel provides the
 Software to Recipient, such addition of the Software to the then publicly
-available versions of such operating systems available under the GNU Public
-License version 2.0 or later (whether in gold, beta or alpha form) causes
+available versions of such operating systems available under the GNU General
+Public License 2.0 or later (whether in gold, beta or alpha form) causes
 such combination to be covered by the Licensed Patents. The patent license
 shall not apply to any other combinations which include the Software. NO
 hardware per se is licensed hereunder.
diff -Nru a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile
--- a/drivers/net/e1000/Makefile	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/e1000/Makefile	Sun Apr 14 12:16:55 2002
@@ -9,8 +9,7 @@
 
 O_TARGET := e1000.o
 
-obj-y   := e1000_main.o e1000_mac.o e1000_phy.o \
-           e1000_ethtool.o e1000_param.o e1000_proc.o
+obj-y   := e1000_main.o e1000_hw.o e1000_ethtool.o e1000_param.o e1000_proc.o
 obj-m   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/e1000/e1000.h	Sun Apr 14 12:16:54 2002
@@ -2,9 +2,8 @@
 
   This software program is available to you under a choice of one of two
   licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
   
   Recipient has requested a license and Intel Corporation ("Intel") is willing
   to grant a license for the software entitled Linux Base Driver for the
@@ -18,7 +17,7 @@
   "Recipient" means the party to whom Intel delivers this Software.
   
   "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
+  any operating system available under the GNU General Public License 2.0 or
   later.
   
   Copyright (c) 1999 - 2002 Intel Corporation.
@@ -51,10 +50,10 @@
   version of an operating system that has been distributed under the GNU
   General Public License 2.0 or later. This patent license shall apply to the
   combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
+  General Public License 2.0 or later if, at the time Intel provides the
   Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
   such combination to be covered by the Licensed Patents. The patent license
   shall not apply to any other combinations which include the Software. NO
   hardware per se is licensed hereunder.
@@ -109,11 +108,14 @@
 #include <net/pkt_sched.h>
 #include <linux/list.h>
 #include <asm/uaccess.h>
+#include <linux/ethtool.h>
+#ifdef NETIF_F_HW_VLAN_TX
+#include <linux/if_vlan.h>
+#endif
 
 struct e1000_adapter;
 
-#include "e1000_mac.h"
-#include "e1000_phy.h"
+#include "e1000_hw.h"
 
 #define BAR_0 0
 
@@ -138,7 +140,9 @@
 #define E1000_RXBUFFER_16384 16384
 
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
-#define E1000_TX_QUEUE_WAKE 16
+#define E1000_TX_QUEUE_WAKE	16
+/* How many Rx Buffers do we bundle into one write to the hardware ? */
+#define E1000_RX_BUFFER_WRITE	16
 
 #define E1000_JUMBO_PBA      0x00000028
 #define E1000_DEFAULT_PBA    0x00000030
@@ -163,10 +167,6 @@
 	unsigned int size;
 	/* number of descriptors in the ring */
 	unsigned int count;
-	/* (atomic) number of desc with no buffer */
-	atomic_t unused;
-	/* number of desc with no buffer */
-	unsigned int unused_count;
 	/* next descriptor to associate a buffer with */
 	unsigned int next_to_use;
 	/* next descriptor to check for DD status bit */
@@ -175,14 +175,13 @@
 	struct e1000_buffer *buffer_info;
 };
 
-#define E1000_RX_DESC(ring, i) \
-	(&(((struct e1000_rx_desc *)((ring).desc))[i]))
-
-#define E1000_TX_DESC(ring, i) \
-	(&(((struct e1000_tx_desc *)((ring).desc))[i]))
+#define E1000_DESC_UNUSED(R) \
+((((R)->next_to_clean + (R)->count) - ((R)->next_to_use + 1)) % ((R)->count))
 
-#define E1000_CONTEXT_DESC(ring, i) \
-	(&(((struct e1000_context_desc *)((ring).desc))[i]))
+#define E1000_GET_DESC(R, i, type)	(&(((struct type *)((R).desc))[i]))
+#define E1000_RX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_rx_desc)
+#define E1000_TX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_tx_desc)
+#define E1000_CONTEXT_DESC(R, i)	E1000_GET_DESC(R, i, e1000_context_desc)
 
 /* board specific private data structure */
 
@@ -192,6 +191,9 @@
 #ifdef CONFIG_PROC_FS
 	struct list_head proc_list_head;
 #endif
+#ifdef NETIF_F_HW_VLAN_TX
+	struct vlan_group *vlgrp;
+#endif
 	char *id_string;
 	uint32_t bd_number;
 	uint32_t rx_buffer_len;
@@ -201,28 +203,29 @@
 	uint16_t link_duplex;
 	spinlock_t stats_lock;
 	atomic_t irq_sem;
-	boolean_t rx_csum;
 
 	/* TX */
 	struct e1000_desc_ring tx_ring;
 	unsigned long trans_finish;
-	uint32_t tx_int_delay;
+	spinlock_t tx_lock;
 	uint32_t txd_cmd;
+	int max_data_per_txd;
 
 	/* RX */
 	struct e1000_desc_ring rx_ring;
 	uint64_t hw_csum_err;
 	uint64_t hw_csum_good;
 	uint32_t rx_int_delay;
+	boolean_t rx_csum;
 
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
 	struct net_device_stats net_stats;
 
-	/* structs defined in e1000_mac.h or e1000_phy.h */
-	struct e1000_shared_adapter shared;
-	struct e1000_shared_stats stats;
+	/* structs defined in e1000_hw.h */
+	struct e1000_hw hw;
+	struct e1000_hw_stats stats;
 	struct e1000_phy_info phy_info;
 	struct e1000_phy_stats phy_stats;
 };
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/e1000/e1000_ethtool.c	Sun Apr 14 12:16:58 2002
@@ -2,9 +2,8 @@
 
   This software program is available to you under a choice of one of two
   licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
   
   Recipient has requested a license and Intel Corporation ("Intel") is willing
   to grant a license for the software entitled Linux Base Driver for the
@@ -18,7 +17,7 @@
   "Recipient" means the party to whom Intel delivers this Software.
   
   "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
+  any operating system available under the GNU General Public License 2.0 or
   later.
   
   Copyright (c) 1999 - 2002 Intel Corporation.
@@ -51,10 +50,10 @@
   version of an operating system that has been distributed under the GNU
   General Public License 2.0 or later. This patent license shall apply to the
   combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
+  General Public License 2.0 or later if, at the time Intel provides the
   Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
   such combination to be covered by the Licensed Patents. The patent license
   shall not apply to any other combinations which include the Software. NO
   hardware per se is licensed hereunder.
@@ -89,9 +88,9 @@
 static void
 e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 
-	if(shared->media_type == e1000_media_type_copper) {
+	if(hw->media_type == e1000_media_type_copper) {
 
 		ecmd->supported = (SUPPORTED_10baseT_Half |
 		                   SUPPORTED_10baseT_Full |
@@ -103,18 +102,18 @@
 
 		ecmd->advertising = ADVERTISED_TP;
 
-		if(shared->autoneg == 1) {
+		if(hw->autoneg == 1) {
 			ecmd->advertising |= ADVERTISED_Autoneg;
 
 			/* the e1000 autoneg seems to match ethtool nicely */
 
-			ecmd->advertising |= shared->autoneg_advertised;
+			ecmd->advertising |= hw->autoneg_advertised;
 		}
 
 		ecmd->port = PORT_TP;
-		ecmd->phy_address = shared->phy_addr;
+		ecmd->phy_address = hw->phy_addr;
 
-		if(shared->mac_type == e1000_82543)
+		if(hw->mac_type == e1000_82543)
 			ecmd->transceiver = XCVR_EXTERNAL;
 		else
 			ecmd->transceiver = XCVR_INTERNAL;
@@ -129,13 +128,12 @@
 				     SUPPORTED_Autoneg);
 
 		ecmd->port = PORT_FIBRE;
-
 		ecmd->transceiver = XCVR_EXTERNAL;
 	}
 
 	if(netif_carrier_ok(adapter->netdev)) {
 
-		e1000_get_speed_and_duplex(shared, &adapter->link_speed,
+		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
 		                                   &adapter->link_duplex);
 		ecmd->speed = adapter->link_speed;
 
@@ -151,37 +149,35 @@
 		ecmd->duplex = -1;
 	}
 
-	ecmd->autoneg = (shared->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-
-	return;
+	ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
 }
 
 static int
 e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 
 	if(ecmd->autoneg == AUTONEG_ENABLE) {
-		shared->autoneg = 1;
-		shared->autoneg_advertised = (ecmd->advertising & 0x002F);
+		hw->autoneg = 1;
+		hw->autoneg_advertised = (ecmd->advertising & 0x002F);
 	} else {
-		shared->autoneg = 0;
+		hw->autoneg = 0;
 		switch(ecmd->speed + ecmd->duplex) {
 		case SPEED_10 + DUPLEX_HALF:
-			shared->forced_speed_duplex = e1000_10_half;
+			hw->forced_speed_duplex = e1000_10_half;
 			break;
 		case SPEED_10 + DUPLEX_FULL:
-			shared->forced_speed_duplex = e1000_10_full;
+			hw->forced_speed_duplex = e1000_10_full;
 			break;
 		case SPEED_100 + DUPLEX_HALF:
-			shared->forced_speed_duplex = e1000_100_half;
+			hw->forced_speed_duplex = e1000_100_half;
 			break;
 		case SPEED_100 + DUPLEX_FULL:
-			shared->forced_speed_duplex = e1000_100_full;
+			hw->forced_speed_duplex = e1000_100_full;
 			break;
 		case SPEED_1000 + DUPLEX_FULL:
-			shared->autoneg = 1;
-			shared->autoneg_advertised = ADVERTISE_1000_FULL;
+			hw->autoneg = 1;
+			hw->autoneg_advertised = ADVERTISE_1000_FULL;
 			break;
 		case SPEED_1000 + DUPLEX_HALF: /* not supported */
 		default:
@@ -198,9 +194,13 @@
 }
 
 static inline int
-e1000_eeprom_size(struct e1000_shared_adapter *shared)
+e1000_eeprom_size(struct e1000_hw *hw)
 {
-	return 128;
+	if((hw->mac_type > e1000_82544) &&
+	   (E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE))
+		return 512;
+	else
+		return 128;
 }
 
 static void
@@ -211,36 +211,33 @@
 	strncpy(drvinfo->version, e1000_driver_version, 32);
 	strncpy(drvinfo->fw_version, "", 32);
 	strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
-	drvinfo->eedump_len  = e1000_eeprom_size(&adapter->shared);
-	return;
+	drvinfo->eedump_len  = e1000_eeprom_size(&adapter->hw);
 }
 
 static void
 e1000_ethtool_geeprom(struct e1000_adapter *adapter,
                       struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 	int i, max_len;
 
-	eeprom->magic = shared->vendor_id | (shared->device_id << 16);
+	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 
-	max_len = e1000_eeprom_size(shared);
+	max_len = e1000_eeprom_size(hw);
 
 	if ((eeprom->offset + eeprom->len) > max_len)
 		eeprom->len = (max_len - eeprom->offset);
 
 	for(i = 0; i < max_len; i++)
-		eeprom_buff[i] = e1000_read_eeprom(&adapter->shared, i);
-
-	return;
+		e1000_read_eeprom(&adapter->hw, i, &eeprom_buff[i]);
 }
 
 static void
 e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 	
-	if(shared->mac_type < e1000_82544) {
+	if(hw->mac_type < e1000_82544) {
 		wol->supported = 0;
 		wol->wolopts   = 0;
 		return;
@@ -260,17 +257,15 @@
 		wol->wolopts |= WAKE_BCAST;
 	if(adapter->wol & E1000_WUFC_MAG)
 		wol->wolopts |= WAKE_MAGIC;
-
-	return;
 }
 
 static int
 e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 
-	if(shared->mac_type < e1000_82544)
-		return wol->wolopts == 0 ? 0 : -EOPNOTSUPP;
+	if(hw->mac_type < e1000_82544)
+		return wol->wolopts ? -EOPNOTSUPP : 0;
 
 	adapter->wol = 0;
 
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_hw.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,3228 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU General Public License 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  General Public License 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* e1000_hw.c
+ * Shared functions for accessing and configuring the MAC
+ */
+
+#include "e1000_hw.h"
+
+static int32_t e1000_setup_fiber_link(struct e1000_hw *hw);
+static int32_t e1000_setup_copper_link(struct e1000_hw *hw);
+static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw);
+static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw);
+static int32_t e1000_force_mac_fc(struct e1000_hw *hw);
+static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl);
+static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count);
+static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw);
+static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw);
+static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd);
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count);
+static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw);
+static void e1000_setup_eeprom(struct e1000_hw *hw);
+static void e1000_standby_eeprom(struct e1000_hw *hw);
+
+/******************************************************************************
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_reset_hw(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint32_t ctrl_ext;
+    uint32_t icr;
+    uint32_t manc;
+    uint16_t pci_cmd_word;
+
+    DEBUGFUNC("e1000_reset_hw");
+    
+    /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
+    if(hw->mac_type == e1000_82542_rev2_0) {
+        if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
+            DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+            pci_cmd_word = hw->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
+            e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &pci_cmd_word);
+        }
+    }
+
+    /* Clear interrupt mask to stop board from generating interrupts */
+    DEBUGOUT("Masking off all interrupts\n");
+    E1000_WRITE_REG(hw, IMC, 0xffffffff);
+
+    /* Disable the Transmit and Receive units.  Then delay to allow
+     * any pending transactions to complete before we hit the MAC with
+     * the global reset.
+     */
+    E1000_WRITE_REG(hw, RCTL, 0);
+    E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
+
+    /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
+    hw->tbi_compatibility_on = FALSE;
+
+    /* Delay to allow any outstanding PCI transactions to complete before
+     * resetting the device
+     */ 
+    msec_delay(10);
+
+    /* Issue a global reset to the MAC.  This will reset the chip's
+     * transmit, receive, DMA, and link units.  It will not effect
+     * the current PCI configuration.  The global reset bit is self-
+     * clearing, and should clear within a microsecond.
+     */
+    DEBUGOUT("Issuing a global reset to MAC\n");
+    ctrl = E1000_READ_REG(hw, CTRL);
+    E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+
+    /* Force a reload from the EEPROM if necessary */
+    if(hw->mac_type < e1000_82540) {
+        /* Wait for reset to complete */
+        usec_delay(10);
+        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+        /* Wait for EEPROM reload */
+        msec_delay(2);
+    } else {
+        /* Wait for EEPROM reload (it happens automatically) */
+        msec_delay(4);
+        /* Dissable HW ARPs on ASF enabled adapters */
+        manc = E1000_READ_REG(hw, MANC);
+        manc &= ~(E1000_MANC_ARP_EN);
+        E1000_WRITE_REG(hw, MANC, manc);
+    }
+    
+    /* Clear interrupt mask to stop board from generating interrupts */
+    DEBUGOUT("Masking off all interrupts\n");
+    E1000_WRITE_REG(hw, IMC, 0xffffffff);
+
+    /* Clear any pending interrupt events. */
+    icr = E1000_READ_REG(hw, ICR);
+
+    /* If MWI was previously enabled, reenable it. */
+    if(hw->mac_type == e1000_82542_rev2_0) {
+        if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+            e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &hw->pci_cmd_word);
+    }
+}
+
+/******************************************************************************
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * 
+ * Assumes that the controller has previously been reset and is in a 
+ * post-reset uninitialized state. Initializes the receive address registers,
+ * multicast table, and VLAN filter table. Calls routines to setup link
+ * configuration and flow control settings. Clears all on-chip counters. Leaves
+ * the transmit and receive units disabled and uninitialized.
+ *****************************************************************************/
+int32_t
+e1000_init_hw(struct e1000_hw *hw)
+{
+    uint32_t ctrl, status;
+    uint32_t i;
+    int32_t ret_val;
+    uint16_t pci_cmd_word;
+
+    DEBUGFUNC("e1000_init_hw");
+
+    /* Set the Media Type and exit with error if it is not valid. */
+    if(hw->mac_type != e1000_82543) {
+        /* tbi_compatibility is only valid on 82543 */
+        hw->tbi_compatibility_en = FALSE;
+    }
+
+    if(hw->mac_type >= e1000_82543) {
+        status = E1000_READ_REG(hw, STATUS);
+        if(status & E1000_STATUS_TBIMODE) {
+            hw->media_type = e1000_media_type_fiber;
+            /* tbi_compatibility not valid on fiber */
+            hw->tbi_compatibility_en = FALSE;
+        } else {
+            hw->media_type = e1000_media_type_copper;
+        }
+    } else {
+        /* This is an 82542 (fiber only) */
+        hw->media_type = e1000_media_type_fiber;
+    }
+
+    /* Disabling VLAN filtering. */
+    DEBUGOUT("Initializing the IEEE VLAN\n");
+    E1000_WRITE_REG(hw, VET, 0);
+
+    e1000_clear_vfta(hw);
+
+    /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
+    if(hw->mac_type == e1000_82542_rev2_0) {
+        if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
+            DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+            pci_cmd_word = hw->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
+            e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &pci_cmd_word);
+        }
+        E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
+        msec_delay(5);
+    }
+
+    /* Setup the receive address. This involves initializing all of the Receive
+     * Address Registers (RARs 0 - 15).
+     */
+    e1000_init_rx_addrs(hw);
+
+    /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
+    if(hw->mac_type == e1000_82542_rev2_0) {
+        E1000_WRITE_REG(hw, RCTL, 0);
+        msec_delay(1);
+        if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+            e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &hw->pci_cmd_word);
+    }
+
+    /* Zero out the Multicast HASH table */
+    DEBUGOUT("Zeroing the MTA\n");
+    for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+        E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+
+    /* Set the PCI priority bit correctly in the CTRL register.  This
+     * determines if the adapter gives priority to receives, or if it
+     * gives equal priority to transmits and receives.
+     */
+    if(hw->dma_fairness) {
+        ctrl = E1000_READ_REG(hw, CTRL);
+        E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
+    }
+
+    /* Call a subroutine to configure the link and setup flow control. */
+    ret_val = e1000_setup_link(hw);
+
+    /* Clear all of the statistics registers (clear on read).  It is
+     * important that we do this after we have tried to establish link
+     * because the symbol error count will increment wildly if there
+     * is no link.
+     */
+    e1000_clear_hw_cntrs(hw);
+
+    return ret_val;
+}
+
+/******************************************************************************
+ * Configures flow control and link settings.
+ * 
+ * hw - Struct containing variables accessed by shared code
+ * 
+ * Determines which flow control settings to use. Calls the apropriate media-
+ * specific link configuration function. Configures the flow control settings.
+ * Assuming the adapter has a valid link partner, a valid link should be
+ * established. Assumes the hardware has previously been reset and the 
+ * transmitter and receiver are not enabled.
+ *****************************************************************************/
+int32_t
+e1000_setup_link(struct e1000_hw *hw)
+{
+    uint32_t ctrl_ext;
+    int32_t ret_val;
+    uint16_t eeprom_data;
+
+    DEBUGFUNC("e1000_setup_link");
+
+    /* Read and store word 0x0F of the EEPROM. This word contains bits
+     * that determine the hardware's default PAUSE (flow control) mode,
+     * a bit that determines whether the HW defaults to enabling or
+     * disabling auto-negotiation, and the direction of the
+     * SW defined pins. If there is no SW over-ride of the flow
+     * control setting, then the variable hw->fc will
+     * be initialized based on a value in the EEPROM.
+     */
+    if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data) < 0) {
+        DEBUGOUT("EEPROM Read Error\n");
+        return -E1000_ERR_EEPROM;
+    }
+
+    if(hw->fc == e1000_fc_default) {
+        if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
+            hw->fc = e1000_fc_none;
+        else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 
+                EEPROM_WORD0F_ASM_DIR)
+            hw->fc = e1000_fc_tx_pause;
+        else
+            hw->fc = e1000_fc_full;
+    }
+
+    /* We want to save off the original Flow Control configuration just
+     * in case we get disconnected and then reconnected into a different
+     * hub or switch with different Flow Control capabilities.
+     */
+    if(hw->mac_type == e1000_82542_rev2_0)
+        hw->fc &= (~e1000_fc_tx_pause);
+
+    if((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
+        hw->fc &= (~e1000_fc_rx_pause);
+
+    hw->original_fc = hw->fc;
+
+    DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc);
+
+    /* Take the 4 bits from EEPROM word 0x0F that determine the initial
+     * polarity value for the SW controlled pins, and setup the
+     * Extended Device Control reg with that info.
+     * This is needed because one of the SW controlled pins is used for
+     * signal detection.  So this should be done before e1000_setup_pcs_link()
+     * or e1000_phy_setup() is called.
+     */
+    if(hw->mac_type == e1000_82543) {
+        ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << 
+                    SWDPIO__EXT_SHIFT);
+        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+    }
+
+    /* Call the necessary subroutine to configure the link. */
+    ret_val = (hw->media_type == e1000_media_type_fiber) ?
+              e1000_setup_fiber_link(hw) :
+              e1000_setup_copper_link(hw);
+
+    /* Initialize the flow control address, type, and PAUSE timer
+     * registers to their default values.  This is done even if flow
+     * control is disabled, because it does not hurt anything to
+     * initialize these registers.
+     */
+    DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
+
+    E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
+    E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+    E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
+    E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
+
+    /* Set the flow control receive threshold registers.  Normally,
+     * these registers will be set to a default threshold that may be
+     * adjusted later by the driver's runtime code.  However, if the
+     * ability to transmit pause frames in not enabled, then these
+     * registers will be set to 0. 
+     */
+    if(!(hw->fc & e1000_fc_tx_pause)) {
+        E1000_WRITE_REG(hw, FCRTL, 0);
+        E1000_WRITE_REG(hw, FCRTH, 0);
+    } else {
+        /* We need to set up the Receive Threshold high and low water marks
+         * as well as (optionally) enabling the transmission of XON frames.
+         */
+        if(hw->fc_send_xon) {
+            E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
+            E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+        } else {
+            E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water);
+            E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+        }
+    }
+    return ret_val;
+}
+
+/******************************************************************************
+ * Sets up link for a fiber based adapter
+ *
+ * hw - Struct containing variables accessed by shared code
+ * ctrl - Current value of the device control register
+ *
+ * Manipulates Physical Coding Sublayer functions in order to configure
+ * link. Assumes the hardware has been previously reset and the transmitter
+ * and receiver are not enabled.
+ *****************************************************************************/
+static int32_t 
+e1000_setup_fiber_link(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint32_t status;
+    uint32_t txcw = 0;
+    uint32_t i;
+    uint32_t signal;
+    int32_t ret_val;
+
+    DEBUGFUNC("e1000_setup_fiber_link");
+
+    /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be 
+     * set when the optics detect a signal. On older adapters, it will be 
+     * cleared when there is a signal
+     */
+    ctrl = E1000_READ_REG(hw, CTRL);
+    if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1;
+    else signal = 0;
+   
+    /* Take the link out of reset */
+    ctrl &= ~(E1000_CTRL_LRST);
+    
+    e1000_config_collision_dist(hw);
+
+    /* Check for a software override of the flow control settings, and setup
+     * the device accordingly.  If auto-negotiation is enabled, then software
+     * will have to set the "PAUSE" bits to the correct value in the Tranmsit
+     * Config Word Register (TXCW) and re-start auto-negotiation.  However, if
+     * auto-negotiation is disabled, then software will have to manually 
+     * configure the two flow control enable bits in the CTRL register.
+     *
+     * The possible values of the "fc" parameter are:
+     *      0:  Flow control is completely disabled
+     *      1:  Rx flow control is enabled (we can receive pause frames, but 
+     *          not send pause frames).
+     *      2:  Tx flow control is enabled (we can send pause frames but we do
+     *          not support receiving pause frames).
+     *      3:  Both Rx and TX flow control (symmetric) are enabled.
+     */
+    switch (hw->fc) {
+    case e1000_fc_none:
+        /* Flow control is completely disabled by a software over-ride. */
+        txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+        break;
+    case e1000_fc_rx_pause:
+        /* RX Flow control is enabled and TX Flow control is disabled by a 
+         * software over-ride. Since there really isn't a way to advertise 
+         * that we are capable of RX Pause ONLY, we will advertise that we
+         * support both symmetric and asymmetric RX PAUSE. Later, we will
+         *  disable the adapter's ability to send PAUSE frames.
+         */
+        txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+        break;
+    case e1000_fc_tx_pause:
+        /* TX Flow control is enabled, and RX Flow control is disabled, by a 
+         * software over-ride.
+         */
+        txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+        break;
+    case e1000_fc_full:
+        /* Flow control (both RX and TX) is enabled by a software over-ride. */
+        txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+        break;
+    default:
+        DEBUGOUT("Flow control param set incorrectly\n");
+        return -E1000_ERR_CONFIG;
+        break;
+    }
+
+    /* Since auto-negotiation is enabled, take the link out of reset (the link
+     * will be in reset, because we previously reset the chip). This will
+     * restart auto-negotiation.  If auto-neogtiation is successful then the
+     * link-up status bit will be set and the flow control enable bits (RFCE
+     * and TFCE) will be set according to their negotiated value.
+     */
+    DEBUGOUT("Auto-negotiation enabled\n");
+
+    E1000_WRITE_REG(hw, TXCW, txcw);
+    E1000_WRITE_REG(hw, CTRL, ctrl);
+
+    hw->txcw = txcw;
+    msec_delay(1);
+
+    /* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
+     * indication in the Device Status Register.  Time-out if a link isn't 
+     * seen in 500 milliseconds seconds (Auto-negotiation should complete in 
+     * less than 500 milliseconds even if the other end is doing it in SW).
+     */
+    if((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
+        DEBUGOUT("Looking for Link\n");
+        for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
+            msec_delay(10);
+            status = E1000_READ_REG(hw, STATUS);
+            if(status & E1000_STATUS_LU) break;
+        }
+        if(i == (LINK_UP_TIMEOUT / 10)) {
+            /* AutoNeg failed to achieve a link, so we'll call 
+             * e1000_check_for_link. This routine will force the link up if we
+             * detect a signal. This will allow us to communicate with
+             * non-autonegotiating link partners.
+             */
+            DEBUGOUT("Never got a valid link from auto-neg!!!\n");
+            hw->autoneg_failed = 1;
+            ret_val = e1000_check_for_link(hw);
+            if(ret_val < 0) {
+                DEBUGOUT("Error while checking for link\n");
+                return ret_val;
+            }
+            hw->autoneg_failed = 0;
+        } else {
+            hw->autoneg_failed = 0;
+            DEBUGOUT("Valid Link Found\n");
+        }
+    } else {
+        DEBUGOUT("No Signal Detected\n");
+    }
+    return 0;
+}
+
+/******************************************************************************
+* Detects which PHY is present and the speed and duplex
+*
+* hw - Struct containing variables accessed by shared code
+* ctrl - current value of the device control register
+******************************************************************************/
+static int32_t 
+e1000_setup_copper_link(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    int32_t ret_val;
+    uint16_t i;
+    uint16_t phy_data;
+
+    DEBUGFUNC("e1000_setup_copper_link");
+
+    ctrl = E1000_READ_REG(hw, CTRL);
+    /* With 82543, we need to force speed and duplex on the MAC equal to what
+     * the PHY speed and duplex configuration is. In addition, we need to
+     * perform a hardware reset on the PHY to take it out of reset.
+     */
+    if(hw->mac_type > e1000_82543) {
+        ctrl |= E1000_CTRL_SLU;
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+    } else {
+        ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+        e1000_phy_hw_reset(hw);
+    }
+
+    /* Make sure we have a valid PHY */
+    ret_val = e1000_detect_gig_phy(hw);
+    if(ret_val < 0) {
+        DEBUGOUT("Error, did not detect valid phy.\n");
+        return ret_val;
+    }
+    DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
+
+    /* Enable CRS on TX. This must be set for half-duplex operation. */
+    if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+    /* Options:
+     *   MDI/MDI-X = 0 (default)
+     *   0 - Auto for all speeds
+     *   1 - MDI mode
+     *   2 - MDI-X mode
+     *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+     */
+    phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+    switch (hw->mdix) {
+    case 1:
+        phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+        break;
+    case 2:
+        phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+        break;
+    case 3:
+        phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+        break;
+    case 0:
+    default:
+        phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+        break;
+    }
+
+    /* Options:
+     *   disable_polarity_correction = 0 (default)
+     *       Automatic Correction for Reversed Cable Polarity
+     *   0 - Disabled
+     *   1 - Enabled
+     */
+    phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+    if(hw->disable_polarity_correction == 1)
+        phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+    if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* Force TX_CLK in the Extended PHY Specific Control Register
+     * to 25MHz clock.
+     */
+    if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    phy_data |= M88E1000_EPSCR_TX_CLK_25;
+    /* Configure Master and Slave downshift values */
+    phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
+                  M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
+    phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+                 M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+    if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* SW Reset the PHY so all changes take effect */
+    ret_val = e1000_phy_reset(hw);
+    if(ret_val < 0) {
+        DEBUGOUT("Error Resetting the PHY\n");
+        return ret_val;
+    }
+    
+    /* Options:
+     *   autoneg = 1 (default)
+     *      PHY will advertise value(s) parsed from
+     *      autoneg_advertised and fc
+     *   autoneg = 0
+     *      PHY will be set to 10H, 10F, 100H, or 100F
+     *      depending on value parsed from forced_speed_duplex.
+     */
+
+    /* Is autoneg enabled?  This is enabled by default or by software override.
+     * If so, call e1000_phy_setup_autoneg routine to parse the
+     * autoneg_advertised and fc options. If autoneg is NOT enabled, then the
+     * user should have provided a speed/duplex override.  If so, then call
+     * e1000_phy_force_speed_duplex to parse and set this up.
+     */
+    if(hw->autoneg) {
+        /* Perform some bounds checking on the hw->autoneg_advertised
+         * parameter.  If this variable is zero, then set it to the default.
+         */
+        hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+        /* If autoneg_advertised is zero, we assume it was not defaulted
+         * by the calling code so we set to advertise full capability.
+         */
+        if(hw->autoneg_advertised == 0)
+            hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+        DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+        ret_val = e1000_phy_setup_autoneg(hw);
+        if(ret_val < 0) {
+            DEBUGOUT("Error Setting up Auto-Negotiation\n");
+            return ret_val;
+        }
+        DEBUGOUT("Restarting Auto-Neg\n");
+
+        /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+         * the Auto Neg Restart bit in the PHY control register.
+         */
+        if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+        phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+        if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) {
+            DEBUGOUT("PHY Write Error\n");
+            return -E1000_ERR_PHY;
+        }
+
+        /* Does the user want to wait for Auto-Neg to complete here, or
+         * check at a later time (for example, callback routine).
+         */
+        if(hw->wait_autoneg_complete) {
+            ret_val = e1000_wait_autoneg(hw);
+            if(ret_val < 0) {
+                DEBUGOUT("Error while waiting for autoneg to complete\n");
+                return ret_val;
+            }
+        }
+    } else {
+        DEBUGOUT("Forcing speed and duplex\n");
+        ret_val = e1000_phy_force_speed_duplex(hw);
+        if(ret_val < 0) {
+            DEBUGOUT("Error Forcing Speed and Duplex\n");
+            return ret_val;
+        }
+    }
+
+    /* Check link status. Wait up to 100 microseconds for link to become
+     * valid.
+     */
+    for(i = 0; i < 10; i++) {
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+        if(phy_data & MII_SR_LINK_STATUS) {
+            /* We have link, so we need to finish the config process:
+             *   1) Set up the MAC to the current PHY speed/duplex
+             *      if we are on 82543.  If we
+             *      are on newer silicon, we only need to configure
+             *      collision distance in the Transmit Control Register.
+             *   2) Set up flow control on the MAC to that established with
+             *      the link partner.
+             */
+            if(hw->mac_type >= e1000_82544) {
+                e1000_config_collision_dist(hw);
+            } else {
+                ret_val = e1000_config_mac_to_phy(hw);
+                if(ret_val < 0) {
+                    DEBUGOUT("Error configuring MAC to PHY settings\n");
+                    return ret_val;
+                  }
+            }
+            ret_val = e1000_config_fc_after_link_up(hw);
+            if(ret_val < 0) {
+                DEBUGOUT("Error Configuring Flow Control\n");
+                return ret_val;
+            }
+            DEBUGOUT("Valid link established!!!\n");
+            return 0;
+        }
+        usec_delay(10);
+    }
+
+    DEBUGOUT("Unable to establish link!!!\n");
+    return 0;
+}
+
+/******************************************************************************
+* Configures PHY autoneg and flow control advertisement settings
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+int32_t
+e1000_phy_setup_autoneg(struct e1000_hw *hw)
+{
+    uint16_t mii_autoneg_adv_reg;
+    uint16_t mii_1000t_ctrl_reg;
+
+    DEBUGFUNC("e1000_phy_setup_autoneg");
+
+    /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+    if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* Read the MII 1000Base-T Control Register (Address 9). */
+    if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* Need to parse both autoneg_advertised and fc and set up
+     * the appropriate PHY registers.  First we will parse for
+     * autoneg_advertised software override.  Since we can advertise
+     * a plethora of combinations, we need to check each bit
+     * individually.
+     */
+
+    /* First we clear all the 10/100 mb speed bits in the Auto-Neg
+     * Advertisement Register (Address 4) and the 1000 mb speed bits in
+     * the  1000Base-T Control Register (Address 9).
+     */
+    mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
+    mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
+
+    DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);
+
+    /* Do we want to advertise 10 Mb Half Duplex? */
+    if(hw->autoneg_advertised & ADVERTISE_10_HALF) {
+        DEBUGOUT("Advertise 10mb Half duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
+    }
+
+    /* Do we want to advertise 10 Mb Full Duplex? */
+    if(hw->autoneg_advertised & ADVERTISE_10_FULL) {
+        DEBUGOUT("Advertise 10mb Full duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
+    }
+
+    /* Do we want to advertise 100 Mb Half Duplex? */
+    if(hw->autoneg_advertised & ADVERTISE_100_HALF) {
+        DEBUGOUT("Advertise 100mb Half duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
+    }
+
+    /* Do we want to advertise 100 Mb Full Duplex? */
+    if(hw->autoneg_advertised & ADVERTISE_100_FULL) {
+        DEBUGOUT("Advertise 100mb Full duplex\n");
+        mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
+    }
+
+    /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
+    if(hw->autoneg_advertised & ADVERTISE_1000_HALF) {
+        DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
+    }
+
+    /* Do we want to advertise 1000 Mb Full Duplex? */
+    if(hw->autoneg_advertised & ADVERTISE_1000_FULL) {
+        DEBUGOUT("Advertise 1000mb Full duplex\n");
+        mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+    }
+
+    /* Check for a software override of the flow control settings, and
+     * setup the PHY advertisement registers accordingly.  If
+     * auto-negotiation is enabled, then software will have to set the
+     * "PAUSE" bits to the correct value in the Auto-Negotiation
+     * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
+     *
+     * The possible values of the "fc" parameter are:
+     *      0:  Flow control is completely disabled
+     *      1:  Rx flow control is enabled (we can receive pause frames
+     *          but not send pause frames).
+     *      2:  Tx flow control is enabled (we can send pause frames
+     *          but we do not support receiving pause frames).
+     *      3:  Both Rx and TX flow control (symmetric) are enabled.
+     *  other:  No software override.  The flow control configuration
+     *          in the EEPROM is used.
+     */
+    switch (hw->fc) {
+    case e1000_fc_none: /* 0 */
+        /* Flow control (RX & TX) is completely disabled by a
+         * software over-ride.
+         */
+        mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+        break;
+    case e1000_fc_rx_pause: /* 1 */
+        /* RX Flow control is enabled, and TX Flow control is
+         * disabled, by a software over-ride.
+         */
+        /* Since there really isn't a way to advertise that we are
+         * capable of RX Pause ONLY, we will advertise that we
+         * support both symmetric and asymmetric RX PAUSE.  Later
+         * (in e1000_config_fc_after_link_up) we will disable the
+         *hw's ability to send PAUSE frames.
+         */
+        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+        break;
+    case e1000_fc_tx_pause: /* 2 */
+        /* TX Flow control is enabled, and RX Flow control is
+         * disabled, by a software over-ride.
+         */
+        mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
+        mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
+        break;
+    case e1000_fc_full: /* 3 */
+        /* Flow control (both RX and TX) is enabled by a software
+         * over-ride.
+         */
+        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+        break;
+    default:
+        DEBUGOUT("Flow control param set incorrectly\n");
+        return -E1000_ERR_CONFIG;
+    }
+
+    if(e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
+
+    if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+    return 0;
+}
+
+/******************************************************************************
+* Force PHY speed and duplex settings to hw->forced_speed_duplex
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    int32_t ret_val;
+    uint16_t mii_ctrl_reg;
+    uint16_t mii_status_reg;
+    uint16_t phy_data;
+    uint16_t i;
+
+    DEBUGFUNC("e1000_phy_force_speed_duplex");
+
+    /* Turn off Flow control if we are forcing speed and duplex. */
+    hw->fc = e1000_fc_none;
+
+    DEBUGOUT1("hw->fc = %d\n", hw->fc);
+
+    /* Read the Device Control Register. */
+    ctrl = E1000_READ_REG(hw, CTRL);
+
+    /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
+    ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+    ctrl &= ~(DEVICE_SPEED_MASK);
+
+    /* Clear the Auto Speed Detect Enable bit. */
+    ctrl &= ~E1000_CTRL_ASDE;
+
+    /* Read the MII Control Register. */
+    if(e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* We need to disable autoneg in order to force link and duplex. */
+
+    mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
+
+    /* Are we forcing Full or Half Duplex? */
+    if(hw->forced_speed_duplex == e1000_100_full ||
+       hw->forced_speed_duplex == e1000_10_full) {
+        /* We want to force full duplex so we SET the full duplex bits in the
+         * Device and MII Control Registers.
+         */
+        ctrl |= E1000_CTRL_FD;
+        mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
+        DEBUGOUT("Full Duplex\n");
+    } else {
+        /* We want to force half duplex so we CLEAR the full duplex bits in
+         * the Device and MII Control Registers.
+         */
+        ctrl &= ~E1000_CTRL_FD;
+        mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
+        DEBUGOUT("Half Duplex\n");
+    }
+
+    /* Are we forcing 100Mbps??? */
+    if(hw->forced_speed_duplex == e1000_100_full ||
+       hw->forced_speed_duplex == e1000_100_half) {
+        /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
+        ctrl |= E1000_CTRL_SPD_100;
+        mii_ctrl_reg |= MII_CR_SPEED_100;
+        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
+        DEBUGOUT("Forcing 100mb ");
+    } else {
+        /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
+        ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+        mii_ctrl_reg |= MII_CR_SPEED_10;
+        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
+        DEBUGOUT("Forcing 10mb ");
+    }
+
+    e1000_config_collision_dist(hw);
+
+    /* Write the configured values back to the Device Control Reg. */
+    E1000_WRITE_REG(hw, CTRL, ctrl);
+
+    /* Write the MII Control Register with the new PHY configuration. */
+    if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
+     * forced whenever speed are duplex are forced.
+     */
+    phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+    if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+    DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
+    
+    /* Need to reset the PHY or these changes will be ignored */
+    mii_ctrl_reg |= MII_CR_RESET;
+    if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+    usec_delay(1);
+
+    /* The wait_autoneg_complete flag may be a little misleading here.
+     * Since we are forcing speed and duplex, Auto-Neg is not enabled.
+     * But we do want to delay for a period while forcing only so we
+     * don't generate false No Link messages.  So we will wait here
+     * only if the user has set wait_autoneg_complete to 1, which is
+     * the default.
+     */
+    if(hw->wait_autoneg_complete) {
+        /* We will wait for autoneg to complete. */
+        DEBUGOUT("Waiting for forced speed/duplex link.\n");
+        mii_status_reg = 0;
+
+        /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+        for(i = PHY_FORCE_TIME; i > 0; i--) {
+            /* Read the MII Status Register and wait for Auto-Neg Complete bit
+             * to be set.
+             */
+            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+            if(mii_status_reg & MII_SR_LINK_STATUS) break;
+            msec_delay(100);
+        }
+        if(i == 0) { /* We didn't get link */
+            /* Reset the DSP and wait again for link. */
+            
+            ret_val = e1000_phy_reset_dsp(hw);
+            if(ret_val < 0) {
+                DEBUGOUT("Error Resetting PHY DSP\n");
+                return ret_val;
+            }
+        }
+        /* This loop will early-out if the link condition has been met.  */
+        for(i = PHY_FORCE_TIME; i > 0; i--) {
+            if(mii_status_reg & MII_SR_LINK_STATUS) break;
+            msec_delay(100);
+            /* Read the MII Status Register and wait for Auto-Neg Complete bit
+             * to be set.
+             */
+            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+            if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+        }
+    }
+    
+    /* Because we reset the PHY above, we need to re-force TX_CLK in the
+     * Extended PHY Specific Control Register to 25MHz clock.  This value
+     * defaults back to a 2.5MHz clock when the PHY is reset.
+     */
+    if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    phy_data |= M88E1000_EPSCR_TX_CLK_25;
+    if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+
+    /* In addition, because of the s/w reset above, we need to enable CRS on
+     * TX.  This must be set for both full and half duplex operation.
+     */
+    if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+    if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+    return 0;
+}
+
+/******************************************************************************
+* Sets the collision distance in the Transmit Control register
+*
+* hw - Struct containing variables accessed by shared code
+*
+* Link should have been established previously. Reads the speed and duplex
+* information from the Device Status register.
+******************************************************************************/
+void
+e1000_config_collision_dist(struct e1000_hw *hw)
+{
+    uint32_t tctl;
+
+    tctl = E1000_READ_REG(hw, TCTL);
+
+    tctl &= ~E1000_TCTL_COLD;
+    tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+
+    E1000_WRITE_REG(hw, TCTL, tctl);
+}
+
+/******************************************************************************
+* Sets MAC speed and duplex settings to reflect the those in the PHY
+*
+* hw - Struct containing variables accessed by shared code
+* mii_reg - data to write to the MII control register
+*
+* The contents of the PHY register containing the needed information need to
+* be passed in.
+******************************************************************************/
+static int32_t
+e1000_config_mac_to_phy(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint16_t phy_data;
+
+    DEBUGFUNC("e1000_config_mac_to_phy");
+
+    /* Read the Device Control Register and set the bits to Force Speed
+     * and Duplex.
+     */
+    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+    ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
+
+    /* Set up duplex in the Device Control and Transmit Control
+     * registers depending on negotiated values.
+     */
+    if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;
+    else ctrl &= ~E1000_CTRL_FD;
+
+    e1000_config_collision_dist(hw);
+
+    /* Set up speed in the Device Control register depending on
+     * negotiated values.
+     */
+    if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+        ctrl |= E1000_CTRL_SPD_1000;
+    else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+        ctrl |= E1000_CTRL_SPD_100;
+    /* Write the configured values back to the Device Control Reg. */
+    E1000_WRITE_REG(hw, CTRL, ctrl);
+    return 0;
+}
+
+/******************************************************************************
+ * Forces the MAC's flow control settings.
+ * 
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets the TFCE and RFCE bits in the device control register to reflect
+ * the adapter settings. TFCE and RFCE need to be explicitly set by
+ * software when a Copper PHY is used because autonegotiation is managed
+ * by the PHY rather than the MAC. Software must also configure these
+ * bits when link is forced on a fiber connection.
+ *****************************************************************************/
+static int32_t
+e1000_force_mac_fc(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+
+    DEBUGFUNC("e1000_force_mac_fc");
+
+    /* Get the current configuration of the Device Control Register */
+    ctrl = E1000_READ_REG(hw, CTRL);
+
+    /* Because we didn't get link via the internal auto-negotiation
+     * mechanism (we either forced link or we got link via PHY
+     * auto-neg), we have to manually enable/disable transmit an
+     * receive flow control.
+     *
+     * The "Case" statement below enables/disable flow control
+     * according to the "hw->fc" parameter.
+     *
+     * The possible values of the "fc" parameter are:
+     *      0:  Flow control is completely disabled
+     *      1:  Rx flow control is enabled (we can receive pause
+     *          frames but not send pause frames).
+     *      2:  Tx flow control is enabled (we can send pause frames
+     *          frames but we do not receive pause frames).
+     *      3:  Both Rx and TX flow control (symmetric) is enabled.
+     *  other:  No other values should be possible at this point.
+     */
+
+    switch (hw->fc) {
+    case e1000_fc_none:
+        ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+        break;
+    case e1000_fc_rx_pause:
+        ctrl &= (~E1000_CTRL_TFCE);
+        ctrl |= E1000_CTRL_RFCE;
+        break;
+    case e1000_fc_tx_pause:
+        ctrl &= (~E1000_CTRL_RFCE);
+        ctrl |= E1000_CTRL_TFCE;
+        break;
+    case e1000_fc_full:
+        ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
+        break;
+    default:
+        DEBUGOUT("Flow control param set incorrectly\n");
+        return -E1000_ERR_CONFIG;
+    }
+
+    /* Disable TX Flow Control for 82542 (rev 2.0) */
+    if(hw->mac_type == e1000_82542_rev2_0)
+        ctrl &= (~E1000_CTRL_TFCE);
+
+    E1000_WRITE_REG(hw, CTRL, ctrl);
+    return 0;
+}
+
+/******************************************************************************
+ * Configures flow control settings after link is established
+ * 
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Should be called immediately after a valid link has been established.
+ * Forces MAC flow control settings if link was forced. When in MII/GMII mode
+ * and autonegotiation is enabled, the MAC flow control settings will be set
+ * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
+ * and RFCE bits will be automaticaly set to the negotiated flow control mode.
+ *****************************************************************************/
+int32_t
+e1000_config_fc_after_link_up(struct e1000_hw *hw)
+{
+    int32_t ret_val;
+    uint16_t mii_status_reg;
+    uint16_t mii_nway_adv_reg;
+    uint16_t mii_nway_lp_ability_reg;
+    uint16_t speed;
+    uint16_t duplex;
+
+    DEBUGFUNC("e1000_config_fc_after_link_up");
+
+    /* Check for the case where we have fiber media and auto-neg failed
+     * so we had to force link.  In this case, we need to force the
+     * configuration of the MAC to match the "fc" parameter.
+     */
+    if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
+       ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) {
+        ret_val = e1000_force_mac_fc(hw);
+        if(ret_val < 0) {
+            DEBUGOUT("Error forcing flow control settings\n");
+            return ret_val;
+        }
+    }
+
+    /* Check for the case where we have copper media and auto-neg is
+     * enabled.  In this case, we need to check and see if Auto-Neg
+     * has completed, and if so, how the PHY and link partner has
+     * flow control configured.
+     */
+    if((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
+        /* Read the MII Status Register and check to see if AutoNeg
+         * has completed.  We read this twice because this reg has
+         * some "sticky" (latched) bits.
+         */
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
+            DEBUGOUT("PHY Read Error \n");
+            return -E1000_ERR_PHY;
+        }
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) {
+            DEBUGOUT("PHY Read Error \n");
+            return -E1000_ERR_PHY;
+        }
+
+        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
+            /* The AutoNeg process has completed, so we now need to
+             * read both the Auto Negotiation Advertisement Register
+             * (Address 4) and the Auto_Negotiation Base Page Ability
+             * Register (Address 5) to determine how flow control was
+             * negotiated.
+             */
+            if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+            if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+
+            /* Two bits in the Auto Negotiation Advertisement Register
+             * (Address 4) and two bits in the Auto Negotiation Base
+             * Page Ability Register (Address 5) determine flow control
+             * for both the PHY and the link partner.  The following
+             * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+             * 1999, describes these PAUSE resolution bits and how flow
+             * control is determined based upon these settings.
+             * NOTE:  DC = Don't Care
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+             *-------|---------|-------|---------|--------------------
+             *   0   |    0    |  DC   |   DC    | e1000_fc_none
+             *   0   |    1    |   0   |   DC    | e1000_fc_none
+             *   0   |    1    |   1   |    0    | e1000_fc_none
+             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+             *   1   |    0    |   0   |   DC    | e1000_fc_none
+             *   1   |   DC    |   1   |   DC    | e1000_fc_full
+             *   1   |    1    |   0   |    0    | e1000_fc_none
+             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+             *
+             */
+            /* Are both PAUSE bits set to 1?  If so, this implies
+             * Symmetric Flow Control is enabled at both ends.  The
+             * ASM_DIR bits are irrelevant per the spec.
+             *
+             * For Symmetric Flow Control:
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+             *-------|---------|-------|---------|--------------------
+             *   1   |   DC    |   1   |   DC    | e1000_fc_full
+             *
+             */
+            if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+               (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+                /* Now we need to check if the user selected RX ONLY
+                 * of pause frames.  In this case, we had to advertise
+                 * FULL flow control because we could not advertise RX
+                 * ONLY. Hence, we must now check to see if we need to
+                 * turn OFF  the TRANSMISSION of PAUSE frames.
+                 */
+                if(hw->original_fc == e1000_fc_full) {
+                    hw->fc = e1000_fc_full;
+                    DEBUGOUT("Flow Control = FULL.\r\n");
+                } else {
+                    hw->fc = e1000_fc_rx_pause;
+                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                }
+            }
+            /* For receiving PAUSE frames ONLY.
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+             *-------|---------|-------|---------|--------------------
+             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+             *
+             */
+            else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+                hw->fc = e1000_fc_tx_pause;
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
+            }
+            /* For transmitting PAUSE frames ONLY.
+             *
+             *   LOCAL DEVICE  |   LINK PARTNER
+             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+             *-------|---------|-------|---------|--------------------
+             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+             *
+             */
+            else if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                    !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+                hw->fc = e1000_fc_rx_pause;
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+            }
+            /* Per the IEEE spec, at this point flow control should be
+             * disabled.  However, we want to consider that we could
+             * be connected to a legacy switch that doesn't advertise
+             * desired flow control, but can be forced on the link
+             * partner.  So if we advertised no flow control, that is
+             * what we will resolve to.  If we advertised some kind of
+             * receive capability (Rx Pause Only or Full Flow Control)
+             * and the link partner advertised none, we will configure
+             * ourselves to enable Rx Flow Control only.  We can do
+             * this safely for two reasons:  If the link partner really
+             * didn't want flow control enabled, and we enable Rx, no
+             * harm done since we won't be receiving any PAUSE frames
+             * anyway.  If the intent on the link partner was to have
+             * flow control enabled, then by us enabling RX only, we
+             * can at least receive pause frames and process them.
+             * This is a good idea because in most cases, since we are
+             * predominantly a server NIC, more times than not we will
+             * be asked to delay transmission of packets than asking
+             * our link partner to pause transmission of frames.
+             */
+            else if(hw->original_fc == e1000_fc_none ||
+                    hw->original_fc == e1000_fc_tx_pause) {
+                hw->fc = e1000_fc_none;
+                DEBUGOUT("Flow Control = NONE.\r\n");
+            } else {
+                hw->fc = e1000_fc_rx_pause;
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+            }
+
+            /* Now we need to do one last check...  If we auto-
+             * negotiated to HALF DUPLEX, flow control should not be
+             * enabled per IEEE 802.3 spec.
+             */
+            e1000_get_speed_and_duplex(hw, &speed, &duplex);
+
+            if(duplex == HALF_DUPLEX)
+                hw->fc = e1000_fc_none;
+
+            /* Now we call a subroutine to actually force the MAC
+             * controller to use the correct flow control settings.
+             */
+            ret_val = e1000_force_mac_fc(hw);
+            if(ret_val < 0) {
+                DEBUGOUT("Error forcing flow control settings\n");
+                return ret_val;
+             }
+        } else {
+            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
+        }
+    }
+    return 0;
+}
+
+/******************************************************************************
+ * Checks to see if the link status of the hardware has changed.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Called by any function that needs to check the link status of the adapter.
+ *****************************************************************************/
+int32_t
+e1000_check_for_link(struct e1000_hw *hw)
+{
+    uint32_t rxcw;
+    uint32_t ctrl;
+    uint32_t status;
+    uint32_t rctl;
+    uint32_t signal;
+    int32_t ret_val;
+    uint16_t phy_data;
+    uint16_t lp_capability;
+
+    DEBUGFUNC("e1000_check_for_link");
+    
+    /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be 
+     * set when the optics detect a signal. On older adapters, it will be 
+     * cleared when there is a signal
+     */
+    if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1;
+    else signal = 0;
+
+    ctrl = E1000_READ_REG(hw, CTRL);
+    status = E1000_READ_REG(hw, STATUS);
+    rxcw = E1000_READ_REG(hw, RXCW);
+
+    /* If we have a copper PHY then we only want to go out to the PHY
+     * registers to see if Auto-Neg has completed and/or if our link
+     * status has changed.  The get_link_status flag will be set if we
+     * receive a Link Status Change interrupt or we have Rx Sequence
+     * Errors.
+     */
+    if((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
+        /* First we want to see if the MII Status Register reports
+         * link.  If so, then we want to get the current speed/duplex
+         * of the PHY.
+         * Read the register twice since the link bit is sticky.
+         */
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+
+        if(phy_data & MII_SR_LINK_STATUS) {
+            hw->get_link_status = FALSE;
+        } else {
+            /* No link detected */
+            return 0;
+        }
+
+        /* If we are forcing speed/duplex, then we simply return since
+         * we have already determined whether we have link or not.
+         */
+        if(!hw->autoneg) return -E1000_ERR_CONFIG;
+
+        /* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
+         * have Si on board that is 82544 or newer, Auto
+         * Speed Detection takes care of MAC speed/duplex
+         * configuration.  So we only need to configure Collision
+         * Distance in the MAC.  Otherwise, we need to force
+         * speed/duplex on the MAC to the current PHY speed/duplex
+         * settings.
+         */
+        if(hw->mac_type >= e1000_82544)
+            e1000_config_collision_dist(hw);
+        else {
+            ret_val = e1000_config_mac_to_phy(hw);
+            if(ret_val < 0) {
+                DEBUGOUT("Error configuring MAC to PHY settings\n");
+                return ret_val;
+            }
+        }
+
+        /* Configure Flow Control now that Auto-Neg has completed. First, we 
+         * need to restore the desired flow control settings because we may
+         * have had to re-autoneg with a different link partner.
+         */
+        ret_val = e1000_config_fc_after_link_up(hw);
+        if(ret_val < 0) {
+            DEBUGOUT("Error configuring flow control\n");
+            return ret_val;
+        }
+
+        /* At this point we know that we are on copper and we have
+         * auto-negotiated link.  These are conditions for checking the link
+         * parter capability register.  We use the link partner capability to
+         * determine if TBI Compatibility needs to be turned on or off.  If
+         * the link partner advertises any speed in addition to Gigabit, then
+         * we assume that they are GMII-based, and TBI compatibility is not
+         * needed. If no other speeds are advertised, we assume the link
+         * partner is TBI-based, and we turn on TBI Compatibility.
+         */
+        if(hw->tbi_compatibility_en) {
+            if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &lp_capability) < 0) {
+                DEBUGOUT("PHY Read Error\n");
+                return -E1000_ERR_PHY;
+            }
+            if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
+                                NWAY_LPAR_10T_FD_CAPS |
+                                NWAY_LPAR_100TX_HD_CAPS |
+                                NWAY_LPAR_100TX_FD_CAPS |
+                                NWAY_LPAR_100T4_CAPS)) {
+                /* If our link partner advertises anything in addition to 
+                 * gigabit, we do not need to enable TBI compatibility.
+                 */
+                if(hw->tbi_compatibility_on) {
+                    /* If we previously were in the mode, turn it off. */
+                    rctl = E1000_READ_REG(hw, RCTL);
+                    rctl &= ~E1000_RCTL_SBP;
+                    E1000_WRITE_REG(hw, RCTL, rctl);
+                    hw->tbi_compatibility_on = FALSE;
+                }
+            } else {
+                /* If TBI compatibility is was previously off, turn it on. For
+                 * compatibility with a TBI link partner, we will store bad
+                 * packets. Some frames have an additional byte on the end and
+                 * will look like CRC errors to to the hardware.
+                 */
+                if(!hw->tbi_compatibility_on) {
+                    hw->tbi_compatibility_on = TRUE;
+                    rctl = E1000_READ_REG(hw, RCTL);
+                    rctl |= E1000_RCTL_SBP;
+                    E1000_WRITE_REG(hw, RCTL, rctl);
+                }
+            }
+        }
+    }
+    /* If we don't have link (auto-negotiation failed or link partner cannot
+     * auto-negotiate), the cable is plugged in (we have signal), and our
+     * link partner is not trying to auto-negotiate with us (we are receiving
+     * idles or data), we need to force link up. We also need to give
+     * auto-negotiation time to complete, in case the cable was just plugged
+     * in. The autoneg_failed flag does this.
+     */
+    else if((hw->media_type == e1000_media_type_fiber) &&
+            (!(status & E1000_STATUS_LU)) &&
+            ((ctrl & E1000_CTRL_SWDPIN1) == signal) &&
+            (!(rxcw & E1000_RXCW_C))) {
+        if(hw->autoneg_failed == 0) {
+            hw->autoneg_failed = 1;
+            return 0;
+        }
+        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+
+        /* Disable auto-negotiation in the TXCW register */
+        E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
+
+        /* Force link-up and also force full-duplex. */
+        ctrl = E1000_READ_REG(hw, CTRL);
+        ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+
+        /* Configure Flow Control after forcing link up. */
+        ret_val = e1000_config_fc_after_link_up(hw);
+        if(ret_val < 0) {
+            DEBUGOUT("Error configuring flow control\n");
+            return ret_val;
+        }
+    }
+    /* If we are forcing link and we are receiving /C/ ordered sets, re-enable
+     * auto-negotiation in the TXCW register and disable forced link in the
+     * Device Control register in an attempt to auto-negotiate with our link
+     * partner.
+     */
+    else if((hw->media_type == e1000_media_type_fiber) &&
+              (ctrl & E1000_CTRL_SLU) &&
+              (rxcw & E1000_RXCW_C)) {
+        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
+        E1000_WRITE_REG(hw, TXCW, hw->txcw);
+        E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+    }
+    return 0;
+}
+
+/******************************************************************************
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ *****************************************************************************/
+void
+e1000_get_speed_and_duplex(struct e1000_hw *hw,
+                           uint16_t *speed,
+                           uint16_t *duplex)
+{
+    uint32_t status;
+
+    DEBUGFUNC("e1000_get_speed_and_duplex");
+
+    if(hw->mac_type >= e1000_82543) {
+        status = E1000_READ_REG(hw, STATUS);
+        if(status & E1000_STATUS_SPEED_1000) {
+            *speed = SPEED_1000;
+            DEBUGOUT("1000 Mbs, ");
+        } else if(status & E1000_STATUS_SPEED_100) {
+            *speed = SPEED_100;
+            DEBUGOUT("100 Mbs, ");
+        } else {
+            *speed = SPEED_10;
+            DEBUGOUT("10 Mbs, ");
+        }
+
+        if(status & E1000_STATUS_FD) {
+            *duplex = FULL_DUPLEX;
+            DEBUGOUT("Full Duplex\r\n");
+        } else {
+            *duplex = HALF_DUPLEX;
+            DEBUGOUT(" Half Duplex\r\n");
+        }
+    } else {
+        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
+        *speed = SPEED_1000;
+        *duplex = FULL_DUPLEX;
+    }
+}
+
+/******************************************************************************
+* Blocks until autoneg completes or times out (~4.5 seconds)
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+int32_t
+e1000_wait_autoneg(struct e1000_hw *hw)
+{
+    uint16_t i;
+    uint16_t phy_data;
+
+    DEBUGFUNC("e1000_wait_autoneg");
+    DEBUGOUT("Waiting for Auto-Neg to complete.\n");
+
+    /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+    for(i = PHY_AUTO_NEG_TIME; i > 0; i--) {
+        /* Read the MII Status Register and wait for Auto-Neg
+         * Complete bit to be set.
+         */
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {
+            DEBUGOUT("PHY Read Error\n");
+            return -E1000_ERR_PHY;
+        }
+        if(phy_data & MII_SR_AUTONEG_COMPLETE) {
+            return 0;
+        }
+        msec_delay(100);
+    }
+    return 0;
+}
+
+/******************************************************************************
+* Raises the Management Data Clock
+*
+* hw - Struct containing variables accessed by shared code
+* ctrl - Device control register's current value
+******************************************************************************/
+static void
+e1000_raise_mdi_clk(struct e1000_hw *hw,
+                    uint32_t *ctrl)
+{
+    /* Raise the clock input to the Management Data Clock (by setting the MDC
+     * bit), and then delay 2 microseconds.
+     */
+    E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC));
+    usec_delay(2);
+}
+
+/******************************************************************************
+* Lowers the Management Data Clock
+*
+* hw - Struct containing variables accessed by shared code
+* ctrl - Device control register's current value
+******************************************************************************/
+static void
+e1000_lower_mdi_clk(struct e1000_hw *hw,
+                    uint32_t *ctrl)
+{
+    /* Lower the clock input to the Management Data Clock (by clearing the MDC
+     * bit), and then delay 2 microseconds.
+     */
+    E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC));
+    usec_delay(2);
+}
+
+/******************************************************************************
+* Shifts data bits out to the PHY
+*
+* hw - Struct containing variables accessed by shared code
+* data - Data to send out to the PHY
+* count - Number of bits to shift out
+*
+* Bits are shifted out in MSB to LSB order.
+******************************************************************************/
+static void
+e1000_shift_out_mdi_bits(struct e1000_hw *hw,
+                         uint32_t data,
+                         uint16_t count)
+{
+    uint32_t ctrl;
+    uint32_t mask;
+
+    /* We need to shift "count" number of bits out to the PHY. So, the value
+     * in the "data" parameter will be shifted out to the PHY one bit at a 
+     * time. In order to do this, "data" must be broken down into bits.
+     */
+    mask = 0x01;
+    mask <<= (count - 1);
+
+    ctrl = E1000_READ_REG(hw, CTRL);
+
+    /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
+    ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
+
+    while(mask) {
+        /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
+         * then raising and lowering the Management Data Clock. A "0" is
+         * shifted out to the PHY by setting the MDIO bit to "0" and then
+         * raising and lowering the clock.
+         */
+        if(data & mask) ctrl |= E1000_CTRL_MDIO;
+        else ctrl &= ~E1000_CTRL_MDIO;
+
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+
+        usec_delay(2);
+
+        e1000_raise_mdi_clk(hw, &ctrl);
+        e1000_lower_mdi_clk(hw, &ctrl);
+
+        mask = mask >> 1;
+    }
+
+    /* Clear the data bit just before leaving this routine. */
+    ctrl &= ~E1000_CTRL_MDIO;
+}
+
+/******************************************************************************
+* Shifts data bits in from the PHY
+*
+* hw - Struct containing variables accessed by shared code
+*
+* Bits are shifted in in MSB to LSB order. 
+******************************************************************************/
+static uint16_t
+e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint16_t data = 0;
+    uint8_t i;
+
+    /* In order to read a register from the PHY, we need to shift in a total
+     * of 18 bits from the PHY. The first two bit (turnaround) times are used
+     * to avoid contention on the MDIO pin when a read operation is performed.
+     * These two bits are ignored by us and thrown away. Bits are "shifted in"
+     * by raising the input to the Management Data Clock (setting the MDC bit),
+     * and then reading the value of the MDIO bit.
+     */ 
+    ctrl = E1000_READ_REG(hw, CTRL);
+
+    /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
+    ctrl &= ~E1000_CTRL_MDIO_DIR;
+    ctrl &= ~E1000_CTRL_MDIO;
+
+    E1000_WRITE_REG(hw, CTRL, ctrl);
+
+    /* Raise and Lower the clock before reading in the data. This accounts for
+     * the turnaround bits. The first clock occurred when we clocked out the
+     * last bit of the Register Address.
+     */
+    e1000_raise_mdi_clk(hw, &ctrl);
+    e1000_lower_mdi_clk(hw, &ctrl);
+
+    for(data = 0, i = 0; i < 16; i++) {
+        data = data << 1;
+        e1000_raise_mdi_clk(hw, &ctrl);
+        ctrl = E1000_READ_REG(hw, CTRL);
+        /* Check to see if we shifted in a "1". */
+        if(ctrl & E1000_CTRL_MDIO) data |= 1;
+        e1000_lower_mdi_clk(hw, &ctrl);
+    }
+
+    e1000_raise_mdi_clk(hw, &ctrl);
+    e1000_lower_mdi_clk(hw, &ctrl);
+
+    /* Clear the MDIO bit just before leaving this routine. */
+    ctrl &= ~E1000_CTRL_MDIO;
+
+    return data;
+}
+
+/*****************************************************************************
+* Reads the value from a PHY register
+*
+* hw - Struct containing variables accessed by shared code
+* reg_addr - address of the PHY register to read
+******************************************************************************/
+int32_t
+e1000_read_phy_reg(struct e1000_hw *hw,
+                   uint32_t reg_addr,
+                   uint16_t *phy_data)
+{
+    uint32_t i;
+    uint32_t mdic = 0;
+    const uint32_t phy_addr = 1;
+
+    DEBUGFUNC("e1000_read_phy_reg");
+
+    if(reg_addr > MAX_PHY_REG_ADDRESS) {
+        DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
+        return -E1000_ERR_PARAM;
+    }
+
+    if(hw->mac_type > e1000_82543) {
+        /* Set up Op-code, Phy Address, and register address in the MDI
+         * Control register.  The MAC will take care of interfacing with the
+         * PHY to retrieve the desired data.
+         */
+        mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
+                (phy_addr << E1000_MDIC_PHY_SHIFT) | 
+                (E1000_MDIC_OP_READ));
+
+        E1000_WRITE_REG(hw, MDIC, mdic);
+
+        /* Poll the ready bit to see if the MDI read completed */
+        for(i = 0; i < 64; i++) {
+            usec_delay(10);
+            mdic = E1000_READ_REG(hw, MDIC);
+            if(mdic & E1000_MDIC_READY) break;
+        }
+        if(!(mdic & E1000_MDIC_READY)) {
+            DEBUGOUT("MDI Read did not complete\n");
+            return -E1000_ERR_PHY;
+        }
+        if(mdic & E1000_MDIC_ERROR) {
+            DEBUGOUT("MDI Error\n");
+            return -E1000_ERR_PHY;
+        }
+        *phy_data = (uint16_t) mdic;
+    } else {
+        /* We must first send a preamble through the MDIO pin to signal the
+         * beginning of an MII instruction.  This is done by sending 32
+         * consecutive "1" bits.
+         */
+        e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+        /* Now combine the next few fields that are required for a read
+         * operation.  We use this method instead of calling the
+         * e1000_shift_out_mdi_bits routine five different times. The format of
+         * a MII read instruction consists of a shift out of 14 bits and is
+         * defined as follows:
+         *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
+         * followed by a shift in of 18 bits.  This first two bits shifted in
+         * are TurnAround bits used to avoid contention on the MDIO pin when a
+         * READ operation is performed.  These two bits are thrown away
+         * followed by a shift in of 16 bits which contains the desired data.
+         */
+        mdic = ((reg_addr) | (phy_addr << 5) | 
+                (PHY_OP_READ << 10) | (PHY_SOF << 12));
+
+        e1000_shift_out_mdi_bits(hw, mdic, 14);
+
+        /* Now that we've shifted out the read command to the MII, we need to
+         * "shift in" the 16-bit value (18 total bits) of the requested PHY
+         * register address.
+         */
+        *phy_data = e1000_shift_in_mdi_bits(hw);
+    }
+    return 0;
+}
+
+/******************************************************************************
+* Writes a value to a PHY register
+*
+* hw - Struct containing variables accessed by shared code
+* reg_addr - address of the PHY register to write
+* data - data to write to the PHY
+******************************************************************************/
+int32_t
+e1000_write_phy_reg(struct e1000_hw *hw,
+                    uint32_t reg_addr,
+                    uint16_t phy_data)
+{
+    uint32_t i;
+    uint32_t mdic = 0;
+    const uint32_t phy_addr = 1;
+
+    DEBUGFUNC("e1000_write_phy_reg");
+
+    if(reg_addr > MAX_PHY_REG_ADDRESS) {
+        DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
+        return -E1000_ERR_PARAM;
+    }
+
+    if(hw->mac_type > e1000_82543) {
+        /* Set up Op-code, Phy Address, register address, and data intended
+         * for the PHY register in the MDI Control register.  The MAC will take
+         * care of interfacing with the PHY to send the desired data.
+         */
+        mdic = (((uint32_t) phy_data) |
+                (reg_addr << E1000_MDIC_REG_SHIFT) |
+                (phy_addr << E1000_MDIC_PHY_SHIFT) | 
+                (E1000_MDIC_OP_WRITE));
+
+        E1000_WRITE_REG(hw, MDIC, mdic);
+
+        /* Poll the ready bit to see if the MDI read completed */
+        for(i = 0; i < 64; i++) {
+            usec_delay(10);
+            mdic = E1000_READ_REG(hw, MDIC);
+            if(mdic & E1000_MDIC_READY) break;
+        }
+        if(!(mdic & E1000_MDIC_READY)) {
+            DEBUGOUT("MDI Write did not complete\n");
+            return -E1000_ERR_PHY;
+        }
+    } else {
+        /* We'll need to use the SW defined pins to shift the write command
+         * out to the PHY. We first send a preamble to the PHY to signal the
+         * beginning of the MII instruction.  This is done by sending 32 
+         * consecutive "1" bits.
+         */
+        e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+        /* Now combine the remaining required fields that will indicate a 
+         * write operation. We use this method instead of calling the
+         * e1000_shift_out_mdi_bits routine for each field in the command. The
+         * format of a MII write instruction is as follows:
+         * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
+         */
+        mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
+                (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+        mdic <<= 16;
+        mdic |= (uint32_t) phy_data;
+
+        e1000_shift_out_mdi_bits(hw, mdic, 32);
+    }
+    return 0;
+}
+
+/******************************************************************************
+* Returns the PHY to the power-on reset state
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+void
+e1000_phy_hw_reset(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint32_t ctrl_ext;
+
+    DEBUGFUNC("e1000_phy_hw_reset");
+
+    DEBUGOUT("Resetting Phy...\n");
+
+    if(hw->mac_type > e1000_82543) {
+        /* Read the device control register and assert the E1000_CTRL_PHY_RST
+         * bit. Then, take it out of reset.
+         */
+        ctrl = E1000_READ_REG(hw, CTRL);
+        E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
+        msec_delay(10);
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+    } else {
+        /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
+         * bit to put the PHY into reset. Then, take it out of reset.
+         */
+        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
+        ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
+        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+        msec_delay(10);
+        ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
+        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+    }
+    usec_delay(150);
+}
+
+/******************************************************************************
+* Resets the PHY
+*
+* hw - Struct containing variables accessed by shared code
+*
+* Sets bit 15 of the MII Control regiser
+******************************************************************************/
+int32_t
+e1000_phy_reset(struct e1000_hw *hw)
+{
+    uint16_t phy_data;
+
+    DEBUGFUNC("e1000_phy_reset");
+
+    if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    phy_data |= MII_CR_RESET;
+    if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) {
+        DEBUGOUT("PHY Write Error\n");
+        return -E1000_ERR_PHY;
+    }
+    usec_delay(1);
+    return 0;
+}
+
+/******************************************************************************
+* Probes the expected PHY address for known PHY IDs
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+int32_t
+e1000_detect_gig_phy(struct e1000_hw *hw)
+{
+    uint16_t phy_id_high, phy_id_low;
+    boolean_t match = FALSE;
+
+    DEBUGFUNC("e1000_detect_gig_phy");
+
+    /* Read the PHY ID Registers to identify which PHY is onboard. */
+    if(e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    hw->phy_id = (uint32_t) (phy_id_high << 16);
+    usec_delay(2);
+    if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) {
+        DEBUGOUT("PHY Read Error\n");
+        return -E1000_ERR_PHY;
+    }
+    hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
+    
+    switch(hw->mac_type) {
+    case e1000_82543:
+        if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
+        break;
+    case e1000_82544:
+        if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
+        break;
+    case e1000_82540:
+        if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
+        break;
+    default:
+        DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
+        return -E1000_ERR_CONFIG;
+    }
+    if(match) {
+        DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
+        return 0;
+    }
+    DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id);
+    return -E1000_ERR_PHY;
+}
+
+/******************************************************************************
+* Resets the PHY's DSP
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_phy_reset_dsp(struct e1000_hw *hw)
+{
+    int32_t ret_val = -E1000_ERR_PHY;
+    DEBUGFUNC("e1000_phy_reset_dsp");
+    
+    do {
+        if(e1000_write_phy_reg(hw, 29, 0x1d) < 0) break;
+        if(e1000_write_phy_reg(hw, 30, 0xc1) < 0) break;
+        if(e1000_write_phy_reg(hw, 30, 0x00) < 0) break;
+        ret_val = 0;
+    } while(0);
+
+    if(ret_val < 0) DEBUGOUT("PHY Write Error\n");
+    return ret_val;
+}
+
+/******************************************************************************
+* Get PHY information from various PHY registers
+*
+* hw - Struct containing variables accessed by shared code
+* phy_info - PHY information structure
+******************************************************************************/
+int32_t
+e1000_phy_get_info(struct e1000_hw *hw,
+                   struct e1000_phy_info *phy_info)
+{
+    int32_t ret_val = -E1000_ERR_PHY;
+    uint16_t phy_data;
+
+    DEBUGFUNC("e1000_phy_get_info");
+
+    phy_info->cable_length = e1000_cable_length_undefined;
+    phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
+    phy_info->cable_polarity = e1000_rev_polarity_undefined;
+    phy_info->polarity_correction = e1000_polarity_reversal_undefined;
+    phy_info->mdix_mode = e1000_auto_x_mode_undefined;
+    phy_info->local_rx = e1000_1000t_rx_status_undefined;
+    phy_info->remote_rx = e1000_1000t_rx_status_undefined;
+
+    if(hw->media_type != e1000_media_type_copper) {
+        DEBUGOUT("PHY info is only valid for copper media\n");
+        return -E1000_ERR_CONFIG;
+    }
+
+    do {
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) break;
+        if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) break;
+        if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
+            DEBUGOUT("PHY info is only valid if link is up\n");
+            return -E1000_ERR_CONFIG;
+        }
+
+        if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0)
+            break;
+        phy_info->extended_10bt_distance =
+            (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
+            M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT;
+        phy_info->polarity_correction =
+            (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
+            M88E1000_PSCR_POLARITY_REVERSAL_SHIFT;
+
+        if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0)
+            break;
+        phy_info->cable_polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
+            M88E1000_PSSR_REV_POLARITY_SHIFT;
+        phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
+            M88E1000_PSSR_MDIX_SHIFT;
+        if(phy_data & M88E1000_PSSR_1000MBS) {
+            /* Cable Length Estimation and Local/Remote Receiver Informatoion
+	     * are only valid at 1000 Mbps
+	     */
+            phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+                                      M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+            if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) 
+                break;
+            phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
+                SR_1000T_LOCAL_RX_STATUS_SHIFT;
+            phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >>
+                SR_1000T_REMOTE_RX_STATUS_SHIFT;
+        }
+        ret_val = 0;
+    } while(0);
+
+    if(ret_val < 0) DEBUGOUT("PHY Read Error\n");
+    return ret_val;
+}
+
+int32_t
+e1000_validate_mdi_setting(struct e1000_hw *hw)
+{
+    DEBUGFUNC("e1000_validate_mdi_settings");
+
+    if(!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
+        DEBUGOUT("Invalid MDI setting detected\n");
+        hw->mdix = 1;
+        return -E1000_ERR_CONFIG;
+    }
+    return 0;
+}
+
+/******************************************************************************
+ * Raises the EEPROM's clock input.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * eecd - EECD's current value
+ *****************************************************************************/
+static void
+e1000_raise_ee_clk(struct e1000_hw *hw,
+                   uint32_t *eecd)
+{
+    /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+     * wait 50 microseconds.
+     */
+    *eecd = *eecd | E1000_EECD_SK;
+    E1000_WRITE_REG(hw, EECD, *eecd);
+    usec_delay(50);
+}
+
+/******************************************************************************
+ * Lowers the EEPROM's clock input.
+ *
+ * hw - Struct containing variables accessed by shared code 
+ * eecd - EECD's current value
+ *****************************************************************************/
+static void
+e1000_lower_ee_clk(struct e1000_hw *hw,
+                   uint32_t *eecd)
+{
+    /* Lower the clock input to the EEPROM (by clearing the SK bit), and then 
+     * wait 50 microseconds. 
+     */
+    *eecd = *eecd & ~E1000_EECD_SK;
+    E1000_WRITE_REG(hw, EECD, *eecd);
+    usec_delay(50);
+}
+
+/******************************************************************************
+ * Shift data bits out to the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * data - data to send to the EEPROM
+ * count - number of bits to shift out
+ *****************************************************************************/
+static void
+e1000_shift_out_ee_bits(struct e1000_hw *hw,
+                        uint16_t data,
+                        uint16_t count)
+{
+    uint32_t eecd;
+    uint32_t mask;
+
+    /* We need to shift "count" bits out to the EEPROM. So, value in the
+     * "data" parameter will be shifted out to the EEPROM one bit at a time.
+     * In order to do this, "data" must be broken down into bits. 
+     */
+    mask = 0x01 << (count - 1);
+    eecd = E1000_READ_REG(hw, EECD);
+    eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
+    do {
+        /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
+         * and then raising and then lowering the clock (the SK bit controls
+         * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
+         * by setting "DI" to "0" and then raising and then lowering the clock.
+         */
+        eecd &= ~E1000_EECD_DI;
+
+        if(data & mask)
+            eecd |= E1000_EECD_DI;
+
+        E1000_WRITE_REG(hw, EECD, eecd);
+
+        usec_delay(50);
+
+        e1000_raise_ee_clk(hw, &eecd);
+        e1000_lower_ee_clk(hw, &eecd);
+
+        mask = mask >> 1;
+
+    } while(mask);
+
+    /* We leave the "DI" bit set to "0" when we leave this routine. */
+    eecd &= ~E1000_EECD_DI;
+    E1000_WRITE_REG(hw, EECD, eecd);
+}
+
+/******************************************************************************
+ * Shift data bits in from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static uint16_t
+e1000_shift_in_ee_bits(struct e1000_hw *hw)
+{
+    uint32_t eecd;
+    uint32_t i;
+    uint16_t data;
+
+    /* In order to read a register from the EEPROM, we need to shift 16 bits 
+     * in from the EEPROM. Bits are "shifted in" by raising the clock input to
+     * the EEPROM (setting the SK bit), and then reading the value of the "DO"
+     * bit.  During this "shifting in" process the "DI" bit should always be 
+     * clear..
+     */
+
+    eecd = E1000_READ_REG(hw, EECD);
+
+    eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
+    data = 0;
+
+    for(i = 0; i < 16; i++) {
+        data = data << 1;
+        e1000_raise_ee_clk(hw, &eecd);
+
+        eecd = E1000_READ_REG(hw, EECD);
+
+        eecd &= ~(E1000_EECD_DI);
+        if(eecd & E1000_EECD_DO)
+            data |= 1;
+
+        e1000_lower_ee_clk(hw, &eecd);
+    }
+
+    return data;
+}
+
+/******************************************************************************
+ * Prepares EEPROM for access
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This 
+ * function should be called before issuing a command to the EEPROM.
+ *****************************************************************************/
+static void
+e1000_setup_eeprom(struct e1000_hw *hw)
+{
+    uint32_t eecd;
+
+    eecd = E1000_READ_REG(hw, EECD);
+
+    /* Clear SK and DI */
+    eecd &= ~(E1000_EECD_SK | E1000_EECD_DI);
+    E1000_WRITE_REG(hw, EECD, eecd);
+
+    /* Set CS */
+    eecd |= E1000_EECD_CS;
+    E1000_WRITE_REG(hw, EECD, eecd);
+}
+
+/******************************************************************************
+ * Returns EEPROM to a "standby" state
+ * 
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+static void
+e1000_standby_eeprom(struct e1000_hw *hw)
+{
+    uint32_t eecd;
+
+    eecd = E1000_READ_REG(hw, EECD);
+
+    /* Deselct EEPROM */
+    eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
+    E1000_WRITE_REG(hw, EECD, eecd);
+    usec_delay(50);
+
+    /* Clock high */
+    eecd |= E1000_EECD_SK;
+    E1000_WRITE_REG(hw, EECD, eecd);
+    usec_delay(50);
+
+    /* Select EEPROM */
+    eecd |= E1000_EECD_CS;
+    E1000_WRITE_REG(hw, EECD, eecd);
+    usec_delay(50);
+
+    /* Clock low */
+    eecd &= ~E1000_EECD_SK;
+    E1000_WRITE_REG(hw, EECD, eecd);
+    usec_delay(50);
+}
+
+
+/******************************************************************************
+ * Reads a 16 bit word from the EEPROM.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of  word in the EEPROM to read
+ * data - word read from the EEPROM 
+ *****************************************************************************/
+int32_t
+e1000_read_eeprom(struct e1000_hw *hw,
+                  uint16_t offset,
+                  uint16_t *data)
+{
+    uint32_t eecd;
+    uint32_t i = 0;
+    boolean_t large_eeprom = FALSE;
+
+    DEBUGFUNC("e1000_read_eeprom");
+
+    /* Request EEPROM Access */
+    if(hw->mac_type > e1000_82544) {
+        eecd = E1000_READ_REG(hw, EECD);
+        if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE;
+        eecd |= E1000_EECD_REQ;
+        E1000_WRITE_REG(hw, EECD, eecd);
+        eecd = E1000_READ_REG(hw, EECD);
+        while((!(eecd & E1000_EECD_GNT)) && (i < 100)) {
+            i++;
+            usec_delay(5);
+            eecd = E1000_READ_REG(hw, EECD);
+        }
+        if(!(eecd & E1000_EECD_GNT)) {
+            eecd &= ~E1000_EECD_REQ;
+            E1000_WRITE_REG(hw, EECD, eecd);
+            DEBUGOUT("Could not acquire EEPROM grant\n");
+            return -E1000_ERR_EEPROM;
+        }
+    }
+
+    /*  Prepare the EEPROM for reading  */
+    e1000_setup_eeprom(hw);
+
+    /*  Send the READ command (opcode + addr)  */
+    e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE, 3);
+    if(large_eeprom) {
+        /* If we have a 256 word EEPROM, there are 8 address bits */
+        e1000_shift_out_ee_bits(hw, offset, 8);
+    } else {
+        /* If we have a 64 word EEPROM, there are 6 address bits */
+        e1000_shift_out_ee_bits(hw, offset, 6);
+    }
+
+    /* Read the data */
+    *data = e1000_shift_in_ee_bits(hw);
+
+    /* End this read operation */
+    e1000_standby_eeprom(hw);
+
+    /* Stop requesting EEPROM access */
+    if(hw->mac_type > e1000_82544) {
+        eecd = E1000_READ_REG(hw, EECD);
+        eecd &= ~E1000_EECD_REQ;
+        E1000_WRITE_REG(hw, EECD, eecd);
+    }
+
+    return 0;
+}
+
+/******************************************************************************
+ * Verifies that the EEPROM has a valid checksum
+ * 
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Reads the first 64 16 bit words of the EEPROM and sums the values read.
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ *****************************************************************************/
+int32_t
+e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+{
+    uint16_t checksum = 0;
+    uint16_t i, eeprom_data;
+
+    DEBUGFUNC("e1000_validate_eeprom_checksum");
+
+    for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+        if(e1000_read_eeprom(hw, i, &eeprom_data) < 0) {
+            DEBUGOUT("EEPROM Read Error\n");
+            return -E1000_ERR_EEPROM;
+        }
+        checksum += eeprom_data;
+    }
+
+    if(checksum == (uint16_t) EEPROM_SUM) {
+        return 0;
+    } else {
+        DEBUGOUT("EEPROM Checksum Invalid\n");    
+        return -E1000_ERR_EEPROM;
+    }
+}
+
+/******************************************************************************
+ * Reads the adapter's part number from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ * part_num - Adapter's part number
+ *****************************************************************************/
+int32_t
+e1000_read_part_num(struct e1000_hw *hw,
+                    uint32_t *part_num)
+{
+    uint16_t offset = EEPROM_PBA_BYTE_1;
+    uint16_t eeprom_data;
+
+    DEBUGFUNC("e1000_read_part_num");
+
+    /* Get word 0 from EEPROM */
+    if(e1000_read_eeprom(hw, offset, &eeprom_data) < 0) {
+        DEBUGOUT("EEPROM Read Error\n");
+        return -E1000_ERR_EEPROM;
+    }
+    /* Save word 0 in upper half of part_num */
+    *part_num = (uint32_t) (eeprom_data << 16);
+
+    /* Get word 1 from EEPROM */
+    if(e1000_read_eeprom(hw, ++offset, &eeprom_data) < 0) {
+        DEBUGOUT("EEPROM Read Error\n");
+        return -E1000_ERR_EEPROM;
+    }
+    /* Save word 1 in lower half of part_num */
+    *part_num |= eeprom_data;
+
+    return 0;
+}
+
+/******************************************************************************
+ * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
+ * second function of dual function devices
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_read_mac_addr(struct e1000_hw * hw)
+{
+    uint16_t offset;
+    uint16_t eeprom_data, i;
+
+    DEBUGFUNC("e1000_read_mac_addr");
+
+    for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
+        offset = i >> 1;
+        if(e1000_read_eeprom(hw, offset, &eeprom_data) < 0) {
+            DEBUGOUT("EEPROM Read Error\n");
+            return -E1000_ERR_EEPROM;
+        }
+        hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
+        hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
+    }
+    for(i = 0; i < NODE_ADDRESS_SIZE; i++)
+        hw->mac_addr[i] = hw->perm_mac_addr[i];
+    return 0;
+}
+
+/******************************************************************************
+ * Initializes receive address filters.
+ *
+ * hw - Struct containing variables accessed by shared code 
+ *
+ * Places the MAC address in receive address register 0 and clears the rest
+ * of the receive addresss registers. Clears the multicast table. Assumes
+ * the receiver is in reset when the routine is called.
+ *****************************************************************************/
+void
+e1000_init_rx_addrs(struct e1000_hw *hw)
+{
+    uint32_t i;
+    uint32_t addr_low;
+    uint32_t addr_high;
+
+    DEBUGFUNC("e1000_init_rx_addrs");
+
+    /* Setup the receive address. */
+    DEBUGOUT("Programming MAC Address into RAR[0]\n");
+    addr_low = (hw->mac_addr[0] |
+                (hw->mac_addr[1] << 8) |
+                (hw->mac_addr[2] << 16) | (hw->mac_addr[3] << 24));
+
+    addr_high = (hw->mac_addr[4] |
+                 (hw->mac_addr[5] << 8) | E1000_RAH_AV);
+
+    E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low);
+    E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high);
+
+    /* Zero out the other 15 receive addresses. */
+    DEBUGOUT("Clearing RAR[1-15]\n");
+    for(i = 1; i < E1000_RAR_ENTRIES; i++) {
+        E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+        E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+    }
+}
+
+/******************************************************************************
+ * Updates the MAC's list of multicast addresses.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr_list - the list of new multicast addresses
+ * mc_addr_count - number of addresses
+ * pad - number of bytes between addresses in the list
+ *
+ * The given list replaces any existing list. Clears the last 15 receive
+ * address registers and the multicast table. Uses receive address registers
+ * for the first 15 multicast addresses, and hashes the rest into the 
+ * multicast table.
+ *****************************************************************************/
+void
+e1000_mc_addr_list_update(struct e1000_hw *hw,
+                          uint8_t *mc_addr_list,
+                          uint32_t mc_addr_count,
+                          uint32_t pad)
+{
+    uint32_t hash_value;
+    uint32_t i;
+    uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */
+
+    DEBUGFUNC("e1000_mc_addr_list_update");
+
+    /* Set the new number of MC addresses that we are being requested to use. */
+    hw->num_mc_addrs = mc_addr_count;
+
+    /* Clear RAR[1-15] */
+    DEBUGOUT(" Clearing RAR[1-15]\n");
+    for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) {
+        E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+        E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+    }
+
+    /* Clear the MTA */
+    DEBUGOUT(" Clearing MTA\n");
+    for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) {
+        E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+    }
+
+    /* Add the new addresses */
+    for(i = 0; i < mc_addr_count; i++) {
+        DEBUGOUT(" Adding the multicast addresses:\n");
+        DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad)],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 1],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 2],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 3],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 4],
+                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 5]);
+
+        hash_value = e1000_hash_mc_addr(hw,
+                                        mc_addr_list +
+                                        (i * (ETH_LENGTH_OF_ADDRESS + pad)));
+
+        DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
+
+        /* Place this multicast address in the RAR if there is room, *
+         * else put it in the MTA            
+         */
+        if(rar_used_count < E1000_RAR_ENTRIES) {
+            e1000_rar_set(hw,
+                          mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)),
+                          rar_used_count);
+            rar_used_count++;
+        } else {
+            e1000_mta_set(hw, hash_value);
+        }
+    }
+    DEBUGOUT("MC Update Complete\n");
+}
+
+/******************************************************************************
+ * Hashes an address to determine its location in the multicast table
+ *
+ * hw - Struct containing variables accessed by shared code
+ * mc_addr - the multicast address to hash 
+ *****************************************************************************/
+uint32_t
+e1000_hash_mc_addr(struct e1000_hw *hw,
+                   uint8_t *mc_addr)
+{
+    uint32_t hash_value = 0;
+
+    /* The portion of the address that is used for the hash table is
+     * determined by the mc_filter_type setting.  
+     */
+    switch (hw->mc_filter_type) {
+    /* [0] [1] [2] [3] [4] [5]
+     * 01  AA  00  12  34  56
+     * LSB                 MSB
+     */
+    case 0:
+        /* [47:36] i.e. 0x563 for above example address */
+        hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
+        break;
+    case 1:
+        /* [46:35] i.e. 0xAC6 for above example address */
+        hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
+        break;
+    case 2:
+        /* [45:34] i.e. 0x5D8 for above example address */
+        hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
+        break;
+    case 3:
+        /* [43:32] i.e. 0x634 for above example address */
+        hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
+        break;
+    }
+
+    hash_value &= 0xFFF;
+    return hash_value;
+}
+
+/******************************************************************************
+ * Sets the bit in the multicast table corresponding to the hash value.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ *****************************************************************************/
+void
+e1000_mta_set(struct e1000_hw *hw,
+              uint32_t hash_value)
+{
+    uint32_t hash_bit, hash_reg;
+    uint32_t mta;
+    uint32_t temp;
+
+    /* The MTA is a register array of 128 32-bit registers.  
+     * It is treated like an array of 4096 bits.  We want to set 
+     * bit BitArray[hash_value]. So we figure out what register
+     * the bit is in, read it, OR in the new bit, then write
+     * back the new value.  The register is determined by the 
+     * upper 7 bits of the hash value and the bit within that 
+     * register are determined by the lower 5 bits of the value.
+     */
+    hash_reg = (hash_value >> 5) & 0x7F;
+    hash_bit = hash_value & 0x1F;
+
+    mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg);
+
+    mta |= (1 << hash_bit);
+
+    /* If we are on an 82544 and we are trying to write an odd offset
+     * in the MTA, save off the previous entry before writing and
+     * restore the old value after writing.
+     */
+    if((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
+        temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1));
+        E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
+        E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp);
+    } else {
+        E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
+    }
+}
+
+/******************************************************************************
+ * Puts an ethernet address into a receive address register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * addr - Address to put into receive address register
+ * index - Receive address register to write
+ *****************************************************************************/
+void
+e1000_rar_set(struct e1000_hw *hw,
+              uint8_t *addr,
+              uint32_t index)
+{
+    uint32_t rar_low, rar_high;
+
+    /* HW expects these in little endian so we reverse the byte order
+     * from network order (big endian) to little endian              
+     */
+    rar_low = ((uint32_t) addr[0] |
+               ((uint32_t) addr[1] << 8) |
+               ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
+
+    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV);
+
+    E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+    E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
+}
+
+/******************************************************************************
+ * Writes a value to the specified offset in the VLAN filter table.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - Offset in VLAN filer table to write
+ * value - Value to write into VLAN filter table
+ *****************************************************************************/
+void
+e1000_write_vfta(struct e1000_hw *hw,
+                 uint32_t offset,
+                 uint32_t value)
+{
+    uint32_t temp;
+
+    if((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
+        temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
+        E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+        E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
+    } else {
+        E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+    }
+}
+
+/******************************************************************************
+ * Clears the VLAN filer table
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_clear_vfta(struct e1000_hw *hw)
+{
+    uint32_t offset;
+
+    for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
+        E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+}
+
+/******************************************************************************
+ * Prepares SW controlable LED for use and saves the current state of the LED.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_setup_led(struct e1000_hw *hw)
+{
+    uint32_t ledctl;
+ 
+    DEBUGFUNC("e1000_setup_led");
+   
+    switch(hw->device_id) {
+    case E1000_DEV_ID_82542:
+    case E1000_DEV_ID_82543GC_FIBER:
+    case E1000_DEV_ID_82543GC_COPPER:
+    case E1000_DEV_ID_82544EI_COPPER:
+    case E1000_DEV_ID_82544EI_FIBER:
+    case E1000_DEV_ID_82544GC_COPPER:
+    case E1000_DEV_ID_82544GC_LOM:
+        /* No setup necessary */
+        break;
+    case E1000_DEV_ID_82540EM:
+    case E1000_DEV_ID_82540EM_LOM:
+        ledctl = E1000_READ_REG(hw, LEDCTL);
+        /* Save current LEDCTL settings */
+        hw->ledctl = ledctl;
+        /* Turn off LED2 and LED3 */
+        ledctl &= ~(E1000_LEDCTL_LED2_IVRT |
+                    E1000_LEDCTL_LED2_BLINK | 
+                    E1000_LEDCTL_LED2_MODE_MASK);
+        ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED2_MODE_SHIFT);
+        ledctl &= ~(E1000_LEDCTL_LED3_IVRT |
+                    E1000_LEDCTL_LED3_BLINK | 
+                    E1000_LEDCTL_LED3_MODE_MASK);
+        ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED3_MODE_SHIFT);
+        E1000_WRITE_REG(hw, LEDCTL, ledctl);
+        break;
+    default:
+        DEBUGOUT("Invalid device ID\n");
+        return -E1000_ERR_CONFIG;
+    }
+    return 0;
+}
+
+/******************************************************************************
+ * Restores the saved state of the SW controlable LED.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_cleanup_led(struct e1000_hw *hw)
+{
+    DEBUGFUNC("e1000_cleanup_led");
+
+    switch(hw->device_id) {
+    case E1000_DEV_ID_82542:
+    case E1000_DEV_ID_82543GC_FIBER:
+    case E1000_DEV_ID_82543GC_COPPER:
+    case E1000_DEV_ID_82544EI_COPPER:
+    case E1000_DEV_ID_82544EI_FIBER:
+    case E1000_DEV_ID_82544GC_COPPER:
+    case E1000_DEV_ID_82544GC_LOM:
+        /* No cleanup necessary */
+        break;
+    case E1000_DEV_ID_82540EM:
+    case E1000_DEV_ID_82540EM_LOM:
+        /* Restore LEDCTL settings */
+        E1000_WRITE_REG(hw, LEDCTL, hw->ledctl);
+        break;
+    default:
+        DEBUGOUT("Invalid device ID\n");
+        return -E1000_ERR_CONFIG;
+    }
+    return 0;
+}
+    
+/******************************************************************************
+ * Turns on the software controllable LED
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_led_on(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint32_t ledctl;
+
+    DEBUGFUNC("e1000_led_on");
+
+    switch(hw->device_id) {
+    case E1000_DEV_ID_82542:
+    case E1000_DEV_ID_82543GC_FIBER:
+    case E1000_DEV_ID_82543GC_COPPER:
+    case E1000_DEV_ID_82544EI_FIBER:
+        ctrl = E1000_READ_REG(hw, CTRL);
+        /* Set SW Defineable Pin 0 to turn on the LED */
+        ctrl |= E1000_CTRL_SWDPIN0;
+        ctrl |= E1000_CTRL_SWDPIO0;
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+        break;
+    case E1000_DEV_ID_82544EI_COPPER:
+    case E1000_DEV_ID_82544GC_COPPER:
+    case E1000_DEV_ID_82544GC_LOM:
+        ctrl = E1000_READ_REG(hw, CTRL);
+        /* Clear SW Defineable Pin 0 to turn on the LED */
+        ctrl &= ~E1000_CTRL_SWDPIN0;
+        ctrl |= E1000_CTRL_SWDPIO0;
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+        break;
+    case E1000_DEV_ID_82540EM:
+    case E1000_DEV_ID_82540EM_LOM:
+        ledctl = E1000_READ_REG(hw, LEDCTL);
+        /* Set LED 3 mode to on */
+        ledctl &= ~E1000_LEDCTL_LED3_MODE_MASK;
+        ledctl |= (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED3_MODE_SHIFT);
+        E1000_WRITE_REG(hw, LEDCTL, ledctl);
+        break;
+    default:
+        DEBUGOUT("Invalid device ID\n");
+        return -E1000_ERR_CONFIG;
+    }
+    return 0;
+}
+
+/******************************************************************************
+ * Turns off the software controllable LED
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_led_off(struct e1000_hw *hw)
+{
+    uint32_t ctrl;
+    uint32_t ledctl;
+
+    DEBUGFUNC("e1000_led_off");
+
+    switch(hw->device_id) {
+    case E1000_DEV_ID_82542:
+    case E1000_DEV_ID_82543GC_FIBER:
+    case E1000_DEV_ID_82543GC_COPPER:
+    case E1000_DEV_ID_82544EI_FIBER:
+        ctrl = E1000_READ_REG(hw, CTRL);
+        /* Clear SW Defineable Pin 0 to turn off the LED */
+        ctrl &= ~E1000_CTRL_SWDPIN0;
+        ctrl |= E1000_CTRL_SWDPIO0;
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+        break;
+    case E1000_DEV_ID_82544EI_COPPER:
+    case E1000_DEV_ID_82544GC_COPPER:
+    case E1000_DEV_ID_82544GC_LOM:
+        ctrl = E1000_READ_REG(hw, CTRL);
+        /* Set SW Defineable Pin 0 to turn off the LED */
+        ctrl |= E1000_CTRL_SWDPIN0;
+        ctrl |= E1000_CTRL_SWDPIO0;
+        E1000_WRITE_REG(hw, CTRL, ctrl);
+        break;
+    case E1000_DEV_ID_82540EM:
+    case E1000_DEV_ID_82540EM_LOM:
+        ledctl = E1000_READ_REG(hw, LEDCTL);
+        /* Set LED 3 mode to off */
+        ledctl &= ~E1000_LEDCTL_LED3_MODE_MASK;
+        ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED3_MODE_SHIFT);
+        E1000_WRITE_REG(hw, LEDCTL, ledctl);
+        break;
+    default:
+        DEBUGOUT("Invalid device ID\n");
+        return -E1000_ERR_CONFIG;
+    }
+    return 0;
+}
+
+/******************************************************************************
+ * Clears all hardware statistics counters. 
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_clear_hw_cntrs(struct e1000_hw *hw)
+{
+    volatile uint32_t temp;
+
+    temp = E1000_READ_REG(hw, CRCERRS);
+    temp = E1000_READ_REG(hw, SYMERRS);
+    temp = E1000_READ_REG(hw, MPC);
+    temp = E1000_READ_REG(hw, SCC);
+    temp = E1000_READ_REG(hw, ECOL);
+    temp = E1000_READ_REG(hw, MCC);
+    temp = E1000_READ_REG(hw, LATECOL);
+    temp = E1000_READ_REG(hw, COLC);
+    temp = E1000_READ_REG(hw, DC);
+    temp = E1000_READ_REG(hw, SEC);
+    temp = E1000_READ_REG(hw, RLEC);
+    temp = E1000_READ_REG(hw, XONRXC);
+    temp = E1000_READ_REG(hw, XONTXC);
+    temp = E1000_READ_REG(hw, XOFFRXC);
+    temp = E1000_READ_REG(hw, XOFFTXC);
+    temp = E1000_READ_REG(hw, FCRUC);
+    temp = E1000_READ_REG(hw, PRC64);
+    temp = E1000_READ_REG(hw, PRC127);
+    temp = E1000_READ_REG(hw, PRC255);
+    temp = E1000_READ_REG(hw, PRC511);
+    temp = E1000_READ_REG(hw, PRC1023);
+    temp = E1000_READ_REG(hw, PRC1522);
+    temp = E1000_READ_REG(hw, GPRC);
+    temp = E1000_READ_REG(hw, BPRC);
+    temp = E1000_READ_REG(hw, MPRC);
+    temp = E1000_READ_REG(hw, GPTC);
+    temp = E1000_READ_REG(hw, GORCL);
+    temp = E1000_READ_REG(hw, GORCH);
+    temp = E1000_READ_REG(hw, GOTCL);
+    temp = E1000_READ_REG(hw, GOTCH);
+    temp = E1000_READ_REG(hw, RNBC);
+    temp = E1000_READ_REG(hw, RUC);
+    temp = E1000_READ_REG(hw, RFC);
+    temp = E1000_READ_REG(hw, ROC);
+    temp = E1000_READ_REG(hw, RJC);
+    temp = E1000_READ_REG(hw, TORL);
+    temp = E1000_READ_REG(hw, TORH);
+    temp = E1000_READ_REG(hw, TOTL);
+    temp = E1000_READ_REG(hw, TOTH);
+    temp = E1000_READ_REG(hw, TPR);
+    temp = E1000_READ_REG(hw, TPT);
+    temp = E1000_READ_REG(hw, PTC64);
+    temp = E1000_READ_REG(hw, PTC127);
+    temp = E1000_READ_REG(hw, PTC255);
+    temp = E1000_READ_REG(hw, PTC511);
+    temp = E1000_READ_REG(hw, PTC1023);
+    temp = E1000_READ_REG(hw, PTC1522);
+    temp = E1000_READ_REG(hw, MPTC);
+    temp = E1000_READ_REG(hw, BPTC);
+
+    if(hw->mac_type < e1000_82543) return;
+
+    temp = E1000_READ_REG(hw, ALGNERRC);
+    temp = E1000_READ_REG(hw, RXERRC);
+    temp = E1000_READ_REG(hw, TNCRS);
+    temp = E1000_READ_REG(hw, CEXTERR);
+    temp = E1000_READ_REG(hw, TSCTC);
+    temp = E1000_READ_REG(hw, TSCTFC);
+
+    if(hw->mac_type <= e1000_82544) return;
+
+    temp = E1000_READ_REG(hw, MGTPRC);
+    temp = E1000_READ_REG(hw, MGTPDC);
+    temp = E1000_READ_REG(hw, MGTPTC);
+}
+
+/******************************************************************************
+ * Resets Adaptive IFS to its default state.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Call this after e1000_init_hw. You may override the IFS defaults by setting
+ * hw->ifs_params_forced to TRUE. However, you must initialize hw->
+ * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
+ * before calling this function.
+ *****************************************************************************/
+void
+e1000_reset_adaptive(struct e1000_hw *hw)
+{
+    DEBUGFUNC("e1000_reset_adaptive");
+
+    if(hw->adaptive_ifs) {
+        if(!hw->ifs_params_forced) {
+            hw->current_ifs_val = 0;
+            hw->ifs_min_val = IFS_MIN;
+            hw->ifs_max_val = IFS_MAX;
+            hw->ifs_step_size = IFS_STEP;
+            hw->ifs_ratio = IFS_RATIO;
+        }
+        hw->in_ifs_mode = FALSE;
+        E1000_WRITE_REG(hw, AIT, 0);
+    } else {
+        DEBUGOUT("Not in Adaptive IFS mode!\n");
+    }
+}
+
+/******************************************************************************
+ * Called during the callback/watchdog routine to update IFS value based on
+ * the ratio of transmits to collisions.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * tx_packets - Number of transmits since last callback
+ * total_collisions - Number of collisions since last callback
+ *****************************************************************************/
+void
+e1000_update_adaptive(struct e1000_hw *hw)
+{
+    DEBUGFUNC("e1000_update_adaptive");
+
+    if(hw->adaptive_ifs) {
+        if((hw->collision_delta * hw->ifs_ratio) > 
+           hw->tx_packet_delta) {
+            if(hw->tx_packet_delta > MIN_NUM_XMITS) {
+                hw->in_ifs_mode = TRUE;
+                if(hw->current_ifs_val < hw->ifs_max_val) {
+                    if(hw->current_ifs_val == 0)
+                        hw->current_ifs_val = hw->ifs_min_val;
+                    else
+                        hw->current_ifs_val += hw->ifs_step_size;
+                    E1000_WRITE_REG(hw, AIT, hw->current_ifs_val);
+                }
+            }
+        } else {
+            if((hw->in_ifs_mode == TRUE) && 
+               (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
+                hw->current_ifs_val = 0;
+                hw->in_ifs_mode = FALSE;
+                E1000_WRITE_REG(hw, AIT, 0);
+            }
+        }
+    } else {
+        DEBUGOUT("Not in Adaptive IFS mode!\n");
+    }
+}
+
+/******************************************************************************
+ * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
+ * 
+ * hw - Struct containing variables accessed by shared code
+ * frame_len - The length of the frame in question
+ * mac_addr - The Ethernet destination address of the frame in question
+ *****************************************************************************/
+void
+e1000_tbi_adjust_stats(struct e1000_hw *hw,
+                       struct e1000_hw_stats *stats,
+                       uint32_t frame_len,
+                       uint8_t *mac_addr)
+{
+    uint64_t carry_bit;
+
+    /* First adjust the frame length. */
+    frame_len--;
+    /* We need to adjust the statistics counters, since the hardware
+     * counters overcount this packet as a CRC error and undercount
+     * the packet as a good packet
+     */
+    /* This packet should not be counted as a CRC error.    */
+    stats->crcerrs--;
+    /* This packet does count as a Good Packet Received.    */
+    stats->gprc++;
+
+    /* Adjust the Good Octets received counters             */
+    carry_bit = 0x80000000 & stats->gorcl;
+    stats->gorcl += frame_len;
+    /* If the high bit of Gorcl (the low 32 bits of the Good Octets
+     * Received Count) was one before the addition, 
+     * AND it is zero after, then we lost the carry out, 
+     * need to add one to Gorch (Good Octets Received Count High).
+     * This could be simplified if all environments supported 
+     * 64-bit integers.
+     */
+    if(carry_bit && ((stats->gorcl & 0x80000000) == 0))
+        stats->gorch++;
+    /* Is this a broadcast or multicast?  Check broadcast first,
+     * since the test for a multicast frame will test positive on 
+     * a broadcast frame.
+     */
+    if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
+        /* Broadcast packet */
+        stats->bprc++;
+    else if(*mac_addr & 0x01)
+        /* Multicast packet */
+        stats->mprc++;
+
+    if(frame_len == hw->max_frame_size) {
+        /* In this case, the hardware has overcounted the number of
+         * oversize frames.
+         */
+        if(stats->roc > 0)
+            stats->roc--;
+    }
+
+    /* Adjust the bin counters when the extra byte put the frame in the
+     * wrong bin. Remember that the frame_len was adjusted above.
+     */
+    if(frame_len == 64) {
+        stats->prc64++;
+        stats->prc127--;
+    } else if(frame_len == 127) {
+        stats->prc127++;
+        stats->prc255--;
+    } else if(frame_len == 255) {
+        stats->prc255++;
+        stats->prc511--;
+    } else if(frame_len == 511) {
+        stats->prc511++;
+        stats->prc1023--;
+    } else if(frame_len == 1023) {
+        stats->prc1023++;
+        stats->prc1522--;
+    } else if(frame_len == 1522) {
+        stats->prc1522++;
+    }
+}
+
+/******************************************************************************
+ * Gets the current PCI bus type, speed, and width of the hardware
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+void
+e1000_get_bus_info(struct e1000_hw *hw)
+{
+    uint32_t status;
+
+    if(hw->mac_type < e1000_82543) {
+        hw->bus_type = e1000_bus_type_unknown;
+        hw->bus_speed = e1000_bus_speed_unknown;
+        hw->bus_width = e1000_bus_width_unknown;
+        return;
+    }
+
+    status = E1000_READ_REG(hw, STATUS);
+    hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
+                   e1000_bus_type_pcix : e1000_bus_type_pci;
+    if(hw->bus_type == e1000_bus_type_pci) {
+        hw->bus_speed = (status & E1000_STATUS_PCI66) ?
+                        e1000_bus_speed_66 : e1000_bus_speed_33;
+    } else {
+        switch (status & E1000_STATUS_PCIX_SPEED) {
+        case E1000_STATUS_PCIX_SPEED_66:
+            hw->bus_speed = e1000_bus_speed_66;
+            break;
+        case E1000_STATUS_PCIX_SPEED_100:
+            hw->bus_speed = e1000_bus_speed_100;
+            break;
+        case E1000_STATUS_PCIX_SPEED_133:
+            hw->bus_speed = e1000_bus_speed_133;
+            break;
+        default:
+            hw->bus_speed = e1000_bus_speed_reserved;
+            break;
+        }
+    }
+    hw->bus_width = (status & E1000_STATUS_BUS64) ?
+                    e1000_bus_width_64 : e1000_bus_width_32;
+}
+
diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/e1000/e1000_hw.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,1767 @@
+/*******************************************************************************
+
+  This software program is available to you under a choice of one of two
+  licenses. You may choose to be licensed under either the GNU General Public
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
+  
+  Recipient has requested a license and Intel Corporation ("Intel") is willing
+  to grant a license for the software entitled Linux Base Driver for the
+  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
+  by Intel Corporation. The following definitions apply to this license:
+  
+  "Licensed Patents" means patent claims licensable by Intel Corporation which
+  are necessarily infringed by the use of sale of the Software alone or when
+  combined with the operating system referred to below.
+  
+  "Recipient" means the party to whom Intel delivers this Software.
+  
+  "Licensee" means Recipient and those third parties that receive a license to
+  any operating system available under the GNU General Public License 2.0 or
+  later.
+  
+  Copyright (c) 1999 - 2002 Intel Corporation.
+  All rights reserved.
+  
+  The license is provided to Recipient and Recipient's Licensees under the
+  following terms.
+  
+  Redistribution and use in source and binary forms of the Software, with or
+  without modification, are permitted provided that the following conditions
+  are met:
+  
+  Redistributions of source code of the Software may retain the above
+  copyright notice, this list of conditions and the following disclaimer.
+  
+  Redistributions in binary form of the Software may reproduce the above
+  copyright notice, this list of conditions and the following disclaimer in
+  the documentation and/or materials provided with the distribution.
+  
+  Neither the name of Intel Corporation nor the names of its contributors
+  shall be used to endorse or promote products derived from this Software
+  without specific prior written permission.
+  
+  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+  royalty-free patent license under Licensed Patents to make, use, sell, offer
+  to sell, import and otherwise transfer the Software, if any, in source code
+  and object code form. This license shall include changes to the Software
+  that are error corrections or other minor changes to the Software that do
+  not add functionality or features when the Software is incorporated in any
+  version of an operating system that has been distributed under the GNU
+  General Public License 2.0 or later. This patent license shall apply to the
+  combination of the Software and any operating system licensed under the GNU
+  General Public License 2.0 or later if, at the time Intel provides the
+  Software to Recipient, such addition of the Software to the then publicly
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
+  such combination to be covered by the Licensed Patents. The patent license
+  shall not apply to any other combinations which include the Software. NO
+  hardware per se is licensed hereunder.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
+  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
+  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/* e1000_hw.h
+ * Structures, enums, and macros for the MAC
+ */
+
+#ifndef _E1000_HW_H_
+#define _E1000_HW_H_
+
+#include "e1000_osdep.h"
+
+/* Forward declarations of structures used by the shared code */
+struct e1000_hw;
+struct e1000_hw_stats;
+
+/* Enumerated types specific to the e1000 hardware */
+/* Media Access Controlers */
+typedef enum {
+    e1000_82542_rev2_0 = 0,
+    e1000_82542_rev2_1,
+    e1000_82543,
+    e1000_82544,
+    e1000_82540,
+    e1000_num_macs
+} e1000_mac_type;
+
+/* Media Types */
+typedef enum {
+    e1000_media_type_copper = 0,
+    e1000_media_type_fiber = 1,
+    e1000_num_media_types
+} e1000_media_type;
+
+typedef enum {
+    e1000_10_half = 0,
+    e1000_10_full = 1,
+    e1000_100_half = 2,
+    e1000_100_full = 3
+} e1000_speed_duplex_type;
+
+/* Flow Control Settings */
+typedef enum {
+    e1000_fc_none = 0,
+    e1000_fc_rx_pause = 1,
+    e1000_fc_tx_pause = 2,
+    e1000_fc_full = 3,
+    e1000_fc_default = 0xFF
+} e1000_fc_type;
+
+/* PCI bus types */
+typedef enum {
+    e1000_bus_type_unknown = 0,
+    e1000_bus_type_pci,
+    e1000_bus_type_pcix
+} e1000_bus_type;
+
+/* PCI bus speeds */
+typedef enum {
+    e1000_bus_speed_unknown = 0,
+    e1000_bus_speed_33,
+    e1000_bus_speed_66,
+    e1000_bus_speed_100,
+    e1000_bus_speed_133,
+    e1000_bus_speed_reserved
+} e1000_bus_speed;
+
+/* PCI bus widths */
+typedef enum {
+    e1000_bus_width_unknown = 0,
+    e1000_bus_width_32,
+    e1000_bus_width_64
+} e1000_bus_width;
+
+/* PHY status info structure and supporting enums */
+typedef enum {
+    e1000_cable_length_50 = 0,
+    e1000_cable_length_50_80,
+    e1000_cable_length_80_110,
+    e1000_cable_length_110_140,
+    e1000_cable_length_140,
+    e1000_cable_length_undefined = 0xFF
+} e1000_cable_length;
+
+typedef enum {
+    e1000_10bt_ext_dist_enable_normal = 0,
+    e1000_10bt_ext_dist_enable_lower,
+    e1000_10bt_ext_dist_enable_undefined = 0xFF
+} e1000_10bt_ext_dist_enable;
+
+typedef enum {
+    e1000_rev_polarity_normal = 0,
+    e1000_rev_polarity_reversed,
+    e1000_rev_polarity_undefined = 0xFF
+} e1000_rev_polarity;
+
+typedef enum {
+    e1000_polarity_reversal_enabled = 0,
+    e1000_polarity_reversal_disabled,
+    e1000_polarity_reversal_undefined = 0xFF
+} e1000_polarity_reversal;
+
+typedef enum {
+    e1000_auto_x_mode_manual_mdi = 0,
+    e1000_auto_x_mode_manual_mdix,
+    e1000_auto_x_mode_auto1,
+    e1000_auto_x_mode_auto2,
+    e1000_auto_x_mode_undefined = 0xFF
+} e1000_auto_x_mode;
+
+typedef enum {
+    e1000_1000t_rx_status_not_ok = 0,
+    e1000_1000t_rx_status_ok,
+    e1000_1000t_rx_status_undefined = 0xFF
+} e1000_1000t_rx_status;
+
+struct e1000_phy_info {
+    e1000_cable_length cable_length;
+    e1000_10bt_ext_dist_enable extended_10bt_distance;
+    e1000_rev_polarity cable_polarity;
+    e1000_polarity_reversal polarity_correction;
+    e1000_auto_x_mode mdix_mode;
+    e1000_1000t_rx_status local_rx;
+    e1000_1000t_rx_status remote_rx;
+};
+
+struct e1000_phy_stats {
+    uint32_t idle_errors;
+    uint32_t receive_errors;
+};
+
+
+
+/* Error Codes */
+#define E1000_SUCCESS    0
+#define E1000_ERR_EEPROM 1
+#define E1000_ERR_PHY    2
+#define E1000_ERR_CONFIG 3
+#define E1000_ERR_PARAM  4
+
+/* Function prototypes */
+/* Initialization */
+void e1000_reset_hw(struct e1000_hw *hw);
+int32_t e1000_init_hw(struct e1000_hw *hw);
+
+/* Link Configuration */
+int32_t e1000_setup_link(struct e1000_hw *hw);
+int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw);
+void e1000_config_collision_dist(struct e1000_hw *hw);
+int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw);
+int32_t e1000_check_for_link(struct e1000_hw *hw);
+void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex);
+int32_t e1000_wait_autoneg(struct e1000_hw *hw);
+
+/* PHY */
+int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
+int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
+void e1000_phy_hw_reset(struct e1000_hw *hw);
+int32_t e1000_phy_reset(struct e1000_hw *hw);
+int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
+int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
+
+/* EEPROM Functions */
+int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t *data);
+int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
+int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
+int32_t e1000_read_mac_addr(struct e1000_hw * hw);
+
+/* Filters (multicast, vlan, receive) */
+void e1000_init_rx_addrs(struct e1000_hw *hw);
+void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad);
+uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
+void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
+void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
+void e1000_write_vfta(struct e1000_hw *hw, uint32_t offset, uint32_t value);
+void e1000_clear_vfta(struct e1000_hw *hw);
+
+/* LED functions */
+int32_t e1000_setup_led(struct e1000_hw *hw);
+int32_t e1000_cleanup_led(struct e1000_hw *hw);
+int32_t e1000_led_on(struct e1000_hw *hw);
+int32_t e1000_led_off(struct e1000_hw *hw);
+
+/* Adaptive IFS Functions */
+
+/* Everything else */
+void e1000_clear_hw_cntrs(struct e1000_hw *hw);
+void e1000_reset_adaptive(struct e1000_hw *hw);
+void e1000_update_adaptive(struct e1000_hw *hw);
+void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
+void e1000_get_bus_info(struct e1000_hw *hw);
+void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
+
+/* PCI Device IDs */
+#define E1000_DEV_ID_82542          0x1000
+#define E1000_DEV_ID_82543GC_FIBER  0x1001
+#define E1000_DEV_ID_82543GC_COPPER 0x1004
+#define E1000_DEV_ID_82544EI_COPPER 0x1008
+#define E1000_DEV_ID_82544EI_FIBER  0x1009
+#define E1000_DEV_ID_82544GC_COPPER 0x100C
+#define E1000_DEV_ID_82544GC_LOM    0x100D
+#define E1000_DEV_ID_82540EM        0x100E
+#define E1000_DEV_ID_82540EM_LOM    0x1015
+#define NUM_DEV_IDS 9
+
+#define NODE_ADDRESS_SIZE 6
+#define ETH_LENGTH_OF_ADDRESS 6
+
+/* MAC decode size is 128K - This is the size of BAR0 */
+#define MAC_DECODE_SIZE (128 * 1024)
+
+#define E1000_82542_2_0_REV_ID 2
+#define E1000_82542_2_1_REV_ID 3
+
+#define SPEED_10    10
+#define SPEED_100   100
+#define SPEED_1000  1000
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+/* The sizes (in bytes) of a ethernet packet */
+#define ENET_HEADER_SIZE             14
+#define MAXIMUM_ETHERNET_FRAME_SIZE  1518 /* With FCS */
+#define MINIMUM_ETHERNET_FRAME_SIZE  64   /* With FCS */
+#define ETHERNET_FCS_SIZE            4
+#define MAXIMUM_ETHERNET_PACKET_SIZE \
+    (MAXIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
+#define MINIMUM_ETHERNET_PACKET_SIZE \
+    (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
+#define CRC_LENGTH                   ETHERNET_FCS_SIZE
+#define MAX_JUMBO_FRAME_SIZE         0x3F00
+
+
+/* 802.1q VLAN Packet Sizes */
+#define VLAN_TAG_SIZE                     4     /* 802.3ac tag (not DMAed) */
+
+/* Ethertype field values */
+#define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
+#define ETHERNET_IP_TYPE        0x0800  /* IP packets */
+#define ETHERNET_ARP_TYPE       0x0806  /* Address Resolution Protocol (ARP) */
+
+/* Packet Header defines */
+#define IP_PROTOCOL_TCP    6
+#define IP_PROTOCOL_UDP    0x11
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error 
+ */
+#define POLL_IMS_ENABLE_MASK ( \
+    E1000_IMS_RXDMT0 |         \
+    E1000_IMS_RXSEQ)
+
+/* This defines the bits that are set in the Interrupt Mask
+ * Set/Read Register.  Each bit is documented below:
+ *   o RXT0   = Receiver Timer Interrupt (ring 0)
+ *   o TXDW   = Transmit Descriptor Written Back
+ *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
+ *   o RXSEQ  = Receive Sequence Error
+ *   o LSC    = Link Status Change
+ */
+#define IMS_ENABLE_MASK ( \
+    E1000_IMS_RXT0   |    \
+    E1000_IMS_TXDW   |    \
+    E1000_IMS_RXDMT0 |    \
+    E1000_IMS_RXSEQ  |    \
+    E1000_IMS_LSC)
+
+/* The number of high/low register pairs in the RAR. The RAR (Receive Address
+ * Registers) holds the directed and multicast addresses that we monitor. We
+ * reserve one of these spots for our directed address, allowing us room for
+ * E1000_RAR_ENTRIES - 1 multicast addresses. 
+ */
+#define E1000_RAR_ENTRIES 16
+
+#define MIN_NUMBER_OF_DESCRIPTORS 8
+#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8
+
+/* Receive Descriptor */
+struct e1000_rx_desc {
+    uint64_t buffer_addr; /* Address of the descriptor's data buffer */
+    uint16_t length;     /* Length of data DMAed into data buffer */
+    uint16_t csum;       /* Packet checksum */
+    uint8_t status;      /* Descriptor status */
+    uint8_t errors;      /* Descriptor Errors */
+    uint16_t special;
+};
+
+/* Receive Decriptor bit definitions */
+#define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
+#define E1000_RXD_STAT_EOP      0x02    /* End of Packet */
+#define E1000_RXD_STAT_IXSM     0x04    /* Ignore checksum */
+#define E1000_RXD_STAT_VP       0x08    /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_TCPCS    0x20    /* TCP xsum calculated */
+#define E1000_RXD_STAT_IPCS     0x40    /* IP xsum calculated */
+#define E1000_RXD_STAT_PIF      0x80    /* passed in-exact filter */
+#define E1000_RXD_ERR_CE        0x01    /* CRC Error */
+#define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
+#define E1000_RXD_ERR_SEQ       0x04    /* Sequence Error */
+#define E1000_RXD_ERR_CXE       0x10    /* Carrier Extension Error */
+#define E1000_RXD_ERR_TCPE      0x20    /* TCP/UDP Checksum Error */
+#define E1000_RXD_ERR_IPE       0x40    /* IP Checksum Error */
+#define E1000_RXD_ERR_RXE       0x80    /* Rx Data Error */
+#define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
+#define E1000_RXD_SPC_PRI_MASK  0xE000  /* Priority is in upper 3 bits */
+#define E1000_RXD_SPC_PRI_SHIFT 0x000D  /* Priority is in upper 3 of 16 */
+#define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_SHIFT 0x000C  /* CFI is bit 12 */
+
+/* mask to determine if packets should be dropped due to frame errors */
+#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
+    E1000_RXD_ERR_CE  |                \
+    E1000_RXD_ERR_SE  |                \
+    E1000_RXD_ERR_SEQ |                \
+    E1000_RXD_ERR_CXE |                \
+    E1000_RXD_ERR_RXE)
+
+/* Transmit Descriptor */
+struct e1000_tx_desc {
+    uint64_t buffer_addr;       /* Address of the descriptor's data buffer */
+    union {
+        uint32_t data;
+        struct {
+            uint16_t length;    /* Data buffer length */
+            uint8_t cso;        /* Checksum offset */
+            uint8_t cmd;        /* Descriptor control */
+        } flags;
+    } lower;
+    union {
+        uint32_t data;
+        struct {
+            uint8_t status;     /* Descriptor status */
+            uint8_t css;        /* Checksum start */
+            uint16_t special;
+        } fields;
+    } upper;
+};
+
+/* Transmit Descriptor bit definitions */
+#define E1000_TXD_DTYP_D     0x00100000 /* Data Descriptor */
+#define E1000_TXD_DTYP_C     0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
+#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
+#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
+#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
+#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
+#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
+#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
+#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
+#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
+#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
+#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
+#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
+#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
+#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
+#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
+#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
+#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
+
+/* Offload Context Descriptor */
+struct e1000_context_desc {
+    union {
+        uint32_t ip_config;
+        struct {
+            uint8_t ipcss;      /* IP checksum start */
+            uint8_t ipcso;      /* IP checksum offset */
+            uint16_t ipcse;     /* IP checksum end */
+        } ip_fields;
+    } lower_setup;
+    union {
+        uint32_t tcp_config;
+        struct {
+            uint8_t tucss;      /* TCP checksum start */
+            uint8_t tucso;      /* TCP checksum offset */
+            uint16_t tucse;     /* TCP checksum end */
+        } tcp_fields;
+    } upper_setup;
+    uint32_t cmd_and_length;    /* */
+    union {
+        uint32_t data;
+        struct {
+            uint8_t status;     /* Descriptor status */
+            uint8_t hdr_len;    /* Header length */
+            uint16_t mss;       /* Maximum segment size */
+        } fields;
+    } tcp_seg_setup;
+};
+
+/* Offload data descriptor */
+struct e1000_data_desc {
+    uint64_t buffer_addr;       /* Address of the descriptor's buffer address */
+    union {
+        uint32_t data;
+        struct {
+            uint16_t length;    /* Data buffer length */
+            uint8_t typ_len_ext;        /* */
+            uint8_t cmd;        /* */
+        } flags;
+    } lower;
+    union {
+        uint32_t data;
+        struct {
+            uint8_t status;     /* Descriptor status */
+            uint8_t popts;      /* Packet Options */
+            uint16_t special;   /* */
+        } fields;
+    } upper;
+};
+
+/* Filters */
+#define E1000_NUM_UNICAST          16   /* Unicast filter entries */
+#define E1000_MC_TBL_SIZE          128  /* Multicast Filter Table (4096 bits) */
+#define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
+
+
+/* Receive Address Register */
+struct e1000_rar {
+    volatile uint32_t low;      /* receive address low */
+    volatile uint32_t high;     /* receive address high */
+};
+
+/* The number of entries in the Multicast Table Array (MTA). */
+#define E1000_NUM_MTA_REGISTERS 128
+
+/* IPv4 Address Table Entry */
+struct e1000_ipv4_at_entry {
+    volatile uint32_t ipv4_addr;        /* IP Address (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Four wakeup IP addresses are supported */
+#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4
+#define E1000_IP4AT_SIZE                  E1000_WAKEUP_IP_ADDRESS_COUNT_MAX
+#define E1000_IP6AT_SIZE                  1
+
+/* IPv6 Address Table Entry */
+struct e1000_ipv6_at_entry {
+    volatile uint8_t ipv6_addr[16];
+};
+
+/* Flexible Filter Length Table Entry */
+struct e1000_fflt_entry {
+    volatile uint32_t length;   /* Flexible Filter Length (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Flexible Filter Mask Table Entry */
+struct e1000_ffmt_entry {
+    volatile uint32_t mask;     /* Flexible Filter Mask (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Flexible Filter Value Table Entry */
+struct e1000_ffvt_entry {
+    volatile uint32_t value;    /* Flexible Filter Value (RW) */
+    volatile uint32_t reserved;
+};
+
+/* Four Flexible Filters are supported */
+#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
+
+/* Each Flexible Filter is at most 128 (0x80) bytes in length */
+#define E1000_FLEXIBLE_FILTER_SIZE_MAX  128
+
+#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
+#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
+
+/* Register Set. (82543, 82544)
+ *
+ * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
+ * These registers are physically located on the NIC, but are mapped into the 
+ * host memory address space.
+ *
+ * RW - register is both readable and writable
+ * RO - register is read only
+ * WO - register is write only
+ * R/clr - register is read only and is cleared when read
+ * A - register array
+ */
+#define E1000_CTRL     0x00000  /* Device Control - RW */
+#define E1000_STATUS   0x00008  /* Device Status - RO */
+#define E1000_EECD     0x00010  /* EEPROM/Flash Control - RW */
+#define E1000_EERD     0x00014  /* EEPROM Read - RW */
+#define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
+#define E1000_MDIC     0x00020  /* MDI Control - RW */
+#define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
+#define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
+#define E1000_FCT      0x00030  /* Flow Control Type - RW */
+#define E1000_VET      0x00038  /* VLAN Ether Type - RW */
+#define E1000_ICR      0x000C0  /* Interrupt Cause Read - R/clr */
+#define E1000_ITR      0x000C4  /* Interrupt Throttling Rate - RW */
+#define E1000_ICS      0x000C8  /* Interrupt Cause Set - WO */
+#define E1000_IMS      0x000D0  /* Interrupt Mask Set - RW */
+#define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
+#define E1000_RCTL     0x00100  /* RX Control - RW */
+#define E1000_FCTTV    0x00170  /* Flow Control Transmit Timer Value - RW */
+#define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
+#define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
+#define E1000_TCTL     0x00400  /* TX Control - RW */
+#define E1000_TIPG     0x00410  /* TX Inter-packet gap -RW */
+#define E1000_TBT      0x00448  /* TX Burst Timer - RW */
+#define E1000_AIT      0x00458  /* Adaptive Interframe Spacing Throttle - RW */
+#define E1000_LEDCTL   0x00E00  /* LED Control - RW */
+#define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
+#define E1000_FCRTL    0x02160  /* Flow Control Receive Threshold Low - RW */
+#define E1000_FCRTH    0x02168  /* Flow Control Receive Threshold High - RW */
+#define E1000_RDBAL    0x02800  /* RX Descriptor Base Address Low - RW */
+#define E1000_RDBAH    0x02804  /* RX Descriptor Base Address High - RW */
+#define E1000_RDLEN    0x02808  /* RX Descriptor Length - RW */
+#define E1000_RDH      0x02810  /* RX Descriptor Head - RW */
+#define E1000_RDT      0x02818  /* RX Descriptor Tail - RW */
+#define E1000_RDTR     0x02820  /* RX Delay Timer - RW */
+#define E1000_RXDCTL   0x02828  /* RX Descriptor Control - RW */
+#define E1000_RADV     0x0282C  /* RX Interrupt Absolute Delay Timer - RW */
+#define E1000_RSRPD    0x02C00  /* RX Small Packet Detect - RW */
+#define E1000_TXDMAC   0x03000  /* TX DMA Control - RW */
+#define E1000_TDBAL    0x03800  /* TX Descriptor Base Address Low - RW */
+#define E1000_TDBAH    0x03804  /* TX Descriptor Base Address High - RW */
+#define E1000_TDLEN    0x03808  /* TX Descriptor Length - RW */
+#define E1000_TDH      0x03810  /* TX Descriptor Head - RW */
+#define E1000_TDT      0x03818  /* TX Descripotr Tail - RW */
+#define E1000_TIDV     0x03820  /* TX Interrupt Delay Value - RW */
+#define E1000_TXDCTL   0x03828  /* TX Descriptor Control - RW */
+#define E1000_TADV     0x0382C  /* TX Interrupt Absolute Delay Val - RW */
+#define E1000_TSPMT    0x03830  /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_CRCERRS  0x04000  /* CRC Error Count - R/clr */
+#define E1000_ALGNERRC 0x04004  /* Alignment Error Count - R/clr */
+#define E1000_SYMERRS  0x04008  /* Symbol Error Count - R/clr */
+#define E1000_RXERRC   0x0400C  /* Receive Error Count - R/clr */
+#define E1000_MPC      0x04010  /* Missed Packet Count - R/clr */
+#define E1000_SCC      0x04014  /* Single Collision Count - R/clr */
+#define E1000_ECOL     0x04018  /* Excessive Collision Count - R/clr */
+#define E1000_MCC      0x0401C  /* Multiple Collision Count - R/clr */
+#define E1000_LATECOL  0x04020  /* Late Collision Count - R/clr */
+#define E1000_COLC     0x04028  /* Collision Count - R/clr */
+#define E1000_DC       0x04030  /* Defer Count - R/clr */
+#define E1000_TNCRS    0x04034  /* TX-No CRS - R/clr */
+#define E1000_SEC      0x04038  /* Sequence Error Count - R/clr */
+#define E1000_CEXTERR  0x0403C  /* Carrier Extension Error Count - R/clr */
+#define E1000_RLEC     0x04040  /* Receive Length Error Count - R/clr */
+#define E1000_XONRXC   0x04048  /* XON RX Count - R/clr */
+#define E1000_XONTXC   0x0404C  /* XON TX Count - R/clr */
+#define E1000_XOFFRXC  0x04050  /* XOFF RX Count - R/clr */
+#define E1000_XOFFTXC  0x04054  /* XOFF TX Count - R/clr */
+#define E1000_FCRUC    0x04058  /* Flow Control RX Unsupported Count- R/clr */
+#define E1000_PRC64    0x0405C  /* Packets RX (64 bytes) - R/clr */
+#define E1000_PRC127   0x04060  /* Packets RX (65-127 bytes) - R/clr */
+#define E1000_PRC255   0x04064  /* Packets RX (128-255 bytes) - R/clr */
+#define E1000_PRC511   0x04068  /* Packets RX (255-511 bytes) - R/clr */
+#define E1000_PRC1023  0x0406C  /* Packets RX (512-1023 bytes) - R/clr */
+#define E1000_PRC1522  0x04070  /* Packets RX (1024-1522 bytes) - R/clr */
+#define E1000_GPRC     0x04074  /* Good Packets RX Count - R/clr */
+#define E1000_BPRC     0x04078  /* Broadcast Packets RX Count - R/clr */
+#define E1000_MPRC     0x0407C  /* Multicast Packets RX Count - R/clr */
+#define E1000_GPTC     0x04080  /* Good Packets TX Count - R/clr */
+#define E1000_GORCL    0x04088  /* Good Octets RX Count Low - R/clr */
+#define E1000_GORCH    0x0408C  /* Good Octets RX Count High - R/clr */
+#define E1000_GOTCL    0x04090  /* Good Octets TX Count Low - R/clr */
+#define E1000_GOTCH    0x04094  /* Good Octets TX Count High - R/clr */
+#define E1000_RNBC     0x040A0  /* RX No Buffers Count - R/clr */
+#define E1000_RUC      0x040A4  /* RX Undersize Count - R/clr */
+#define E1000_RFC      0x040A8  /* RX Fragment Count - R/clr */
+#define E1000_ROC      0x040AC  /* RX Oversize Count - R/clr */
+#define E1000_RJC      0x040B0  /* RX Jabber Count - R/clr */
+#define E1000_MGTPRC   0x040B4  /* Management Packets RX Count - R/clr */
+#define E1000_MGTPDC   0x040B8  /* Management Packets Dropped Count - R/clr */
+#define E1000_MGTPTC   0x040BC  /* Management Packets TX Count - R/clr */
+#define E1000_TORL     0x040C0  /* Total Octets RX Low - R/clr */
+#define E1000_TORH     0x040C4  /* Total Octets RX High - R/clr */
+#define E1000_TOTL     0x040C8  /* Total Octets TX Low - R/clr */
+#define E1000_TOTH     0x040CC  /* Total Octets TX High - R/clr */
+#define E1000_TPR      0x040D0  /* Total Packets RX - R/clr */
+#define E1000_TPT      0x040D4  /* Total Packets TX - R/clr */
+#define E1000_PTC64    0x040D8  /* Packets TX (64 bytes) - R/clr */
+#define E1000_PTC127   0x040DC  /* Packets TX (65-127 bytes) - R/clr */
+#define E1000_PTC255   0x040E0  /* Packets TX (128-255 bytes) - R/clr */
+#define E1000_PTC511   0x040E4  /* Packets TX (256-511 bytes) - R/clr */
+#define E1000_PTC1023  0x040E8  /* Packets TX (512-1023 bytes) - R/clr */
+#define E1000_PTC1522  0x040EC  /* Packets TX (1024-1522 Bytes) - R/clr */
+#define E1000_MPTC     0x040F0  /* Multicast Packets TX Count - R/clr */
+#define E1000_BPTC     0x040F4  /* Broadcast Packets TX Count - R/clr */
+#define E1000_TSCTC    0x040F8  /* TCP Segmentation Context TX - R/clr */
+#define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context TX Fail - R/clr */
+#define E1000_RXCSUM   0x05000  /* RX Checksum Control - RW */
+#define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
+#define E1000_RA       0x05400  /* Receive Address - RW Array */
+#define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
+#define E1000_WUC      0x05800  /* Wakeup Control - RW */
+#define E1000_WUFC     0x05808  /* Wakeup Filter Control - RW */
+#define E1000_WUS      0x05810  /* Wakeup Status - RO */
+#define E1000_MANC     0x05820  /* Management Control - RW */
+#define E1000_IPAV     0x05838  /* IP Address Valid - RW */
+#define E1000_IP4AT    0x05840  /* IPv4 Address Table - RW Array */
+#define E1000_IP6AT    0x05880  /* IPv6 Address Table - RW Array */
+#define E1000_WUPL     0x05900  /* Wakeup Packet Length - RW */
+#define E1000_WUPM     0x05A00  /* Wakeup Packet Memory - RO A */
+#define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - RW Array */
+#define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
+#define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
+
+/* Register Set (82542)
+ *
+ * Some of the 82542 registers are located at different offsets than they are
+ * in more current versions of the 8254x. Despite the difference in location,
+ * the registers function in the same manner.
+ */
+#define E1000_82542_CTRL     E1000_CTRL
+#define E1000_82542_STATUS   E1000_STATUS
+#define E1000_82542_EECD     E1000_EECD
+#define E1000_82542_EERD     E1000_EERD
+#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
+#define E1000_82542_MDIC     E1000_MDIC
+#define E1000_82542_FCAL     E1000_FCAL
+#define E1000_82542_FCAH     E1000_FCAH
+#define E1000_82542_FCT      E1000_FCT
+#define E1000_82542_VET      E1000_VET
+#define E1000_82542_RA       0x00040
+#define E1000_82542_ICR      E1000_ICR
+#define E1000_82542_ITR      E1000_ITR
+#define E1000_82542_ICS      E1000_ICS
+#define E1000_82542_IMS      E1000_IMS
+#define E1000_82542_IMC      E1000_IMC
+#define E1000_82542_RCTL     E1000_RCTL
+#define E1000_82542_RDTR     0x00108
+#define E1000_82542_RDBAL    0x00110
+#define E1000_82542_RDBAH    0x00114
+#define E1000_82542_RDLEN    0x00118
+#define E1000_82542_RDH      0x00120
+#define E1000_82542_RDT      0x00128
+#define E1000_82542_FCRTH    0x00160
+#define E1000_82542_FCRTL    0x00168
+#define E1000_82542_FCTTV    E1000_FCTTV
+#define E1000_82542_TXCW     E1000_TXCW
+#define E1000_82542_RXCW     E1000_RXCW
+#define E1000_82542_MTA      0x00200
+#define E1000_82542_TCTL     E1000_TCTL
+#define E1000_82542_TIPG     E1000_TIPG
+#define E1000_82542_TDBAL    0x00420
+#define E1000_82542_TDBAH    0x00424
+#define E1000_82542_TDLEN    0x00428
+#define E1000_82542_TDH      0x00430
+#define E1000_82542_TDT      0x00438
+#define E1000_82542_TIDV     0x00440
+#define E1000_82542_TBT      E1000_TBT
+#define E1000_82542_AIT      E1000_AIT
+#define E1000_82542_VFTA     0x00600
+#define E1000_82542_LEDCTL   E1000_LEDCTL
+#define E1000_82542_PBA      E1000_PBA
+#define E1000_82542_RXDCTL   E1000_RXDCTL
+#define E1000_82542_RADV     E1000_RADV
+#define E1000_82542_RSRPD    E1000_RSRPD
+#define E1000_82542_TXDMAC   E1000_TXDMAC
+#define E1000_82542_TXDCTL   E1000_TXDCTL
+#define E1000_82542_TADV     E1000_TADV
+#define E1000_82542_TSPMT    E1000_TSPMT
+#define E1000_82542_CRCERRS  E1000_CRCERRS
+#define E1000_82542_ALGNERRC E1000_ALGNERRC
+#define E1000_82542_SYMERRS  E1000_SYMERRS
+#define E1000_82542_RXERRC   E1000_RXERRC
+#define E1000_82542_MPC      E1000_MPC
+#define E1000_82542_SCC      E1000_SCC
+#define E1000_82542_ECOL     E1000_ECOL
+#define E1000_82542_MCC      E1000_MCC
+#define E1000_82542_LATECOL  E1000_LATECOL
+#define E1000_82542_COLC     E1000_COLC
+#define E1000_82542_DC       E1000_DC
+#define E1000_82542_TNCRS    E1000_TNCRS
+#define E1000_82542_SEC      E1000_SEC
+#define E1000_82542_CEXTERR  E1000_CEXTERR
+#define E1000_82542_RLEC     E1000_RLEC
+#define E1000_82542_XONRXC   E1000_XONRXC
+#define E1000_82542_XONTXC   E1000_XONTXC
+#define E1000_82542_XOFFRXC  E1000_XOFFRXC
+#define E1000_82542_XOFFTXC  E1000_XOFFTXC
+#define E1000_82542_FCRUC    E1000_FCRUC
+#define E1000_82542_PRC64    E1000_PRC64
+#define E1000_82542_PRC127   E1000_PRC127
+#define E1000_82542_PRC255   E1000_PRC255
+#define E1000_82542_PRC511   E1000_PRC511
+#define E1000_82542_PRC1023  E1000_PRC1023
+#define E1000_82542_PRC1522  E1000_PRC1522
+#define E1000_82542_GPRC     E1000_GPRC
+#define E1000_82542_BPRC     E1000_BPRC
+#define E1000_82542_MPRC     E1000_MPRC
+#define E1000_82542_GPTC     E1000_GPTC
+#define E1000_82542_GORCL    E1000_GORCL
+#define E1000_82542_GORCH    E1000_GORCH
+#define E1000_82542_GOTCL    E1000_GOTCL
+#define E1000_82542_GOTCH    E1000_GOTCH
+#define E1000_82542_RNBC     E1000_RNBC
+#define E1000_82542_RUC      E1000_RUC
+#define E1000_82542_RFC      E1000_RFC
+#define E1000_82542_ROC      E1000_ROC
+#define E1000_82542_RJC      E1000_RJC
+#define E1000_82542_MGTPRC   E1000_MGTPRC
+#define E1000_82542_MGTPDC   E1000_MGTPDC
+#define E1000_82542_MGTPTC   E1000_MGTPTC
+#define E1000_82542_TORL     E1000_TORL
+#define E1000_82542_TORH     E1000_TORH
+#define E1000_82542_TOTL     E1000_TOTL
+#define E1000_82542_TOTH     E1000_TOTH
+#define E1000_82542_TPR      E1000_TPR
+#define E1000_82542_TPT      E1000_TPT
+#define E1000_82542_PTC64    E1000_PTC64
+#define E1000_82542_PTC127   E1000_PTC127
+#define E1000_82542_PTC255   E1000_PTC255
+#define E1000_82542_PTC511   E1000_PTC511
+#define E1000_82542_PTC1023  E1000_PTC1023
+#define E1000_82542_PTC1522  E1000_PTC1522
+#define E1000_82542_MPTC     E1000_MPTC
+#define E1000_82542_BPTC     E1000_BPTC
+#define E1000_82542_TSCTC    E1000_TSCTC
+#define E1000_82542_TSCTFC   E1000_TSCTFC
+#define E1000_82542_RXCSUM   E1000_RXCSUM
+#define E1000_82542_WUC      E1000_WUC
+#define E1000_82542_WUFC     E1000_WUFC
+#define E1000_82542_WUS      E1000_WUS
+#define E1000_82542_MANC     E1000_MANC
+#define E1000_82542_IPAV     E1000_IPAV
+#define E1000_82542_IP4AT    E1000_IP4AT
+#define E1000_82542_IP6AT    E1000_IP6AT
+#define E1000_82542_WUPL     E1000_WUPL
+#define E1000_82542_WUPM     E1000_WUPM
+#define E1000_82542_FFLT     E1000_FFLT
+#define E1000_82542_FFMT     E1000_FFMT
+#define E1000_82542_FFVT     E1000_FFVT
+
+/* Statistics counters collected by the MAC */
+struct e1000_hw_stats {
+    uint64_t crcerrs;
+    uint64_t algnerrc;
+    uint64_t symerrs;
+    uint64_t rxerrc;
+    uint64_t mpc;
+    uint64_t scc;
+    uint64_t ecol;
+    uint64_t mcc;
+    uint64_t latecol;
+    uint64_t colc;
+    uint64_t dc;
+    uint64_t tncrs;
+    uint64_t sec;
+    uint64_t cexterr;
+    uint64_t rlec;
+    uint64_t xonrxc;
+    uint64_t xontxc;
+    uint64_t xoffrxc;
+    uint64_t xofftxc;
+    uint64_t fcruc;
+    uint64_t prc64;
+    uint64_t prc127;
+    uint64_t prc255;
+    uint64_t prc511;
+    uint64_t prc1023;
+    uint64_t prc1522;
+    uint64_t gprc;
+    uint64_t bprc;
+    uint64_t mprc;
+    uint64_t gptc;
+    uint64_t gorcl;
+    uint64_t gorch;
+    uint64_t gotcl;
+    uint64_t gotch;
+    uint64_t rnbc;
+    uint64_t ruc;
+    uint64_t rfc;
+    uint64_t roc;
+    uint64_t rjc;
+    uint64_t mgprc;
+    uint64_t mgpdc;
+    uint64_t mgptc;
+    uint64_t torl;
+    uint64_t torh;
+    uint64_t totl;
+    uint64_t toth;
+    uint64_t tpr;
+    uint64_t tpt;
+    uint64_t ptc64;
+    uint64_t ptc127;
+    uint64_t ptc255;
+    uint64_t ptc511;
+    uint64_t ptc1023;
+    uint64_t ptc1522;
+    uint64_t mptc;
+    uint64_t bptc;
+    uint64_t tsctc;
+    uint64_t tsctfc;
+};
+
+/* Structure containing variables used by the shared code (e1000_hw.c) */
+struct e1000_hw {
+    uint8_t *hw_addr;
+    e1000_mac_type mac_type;
+    e1000_media_type media_type;
+    void *back;
+    e1000_fc_type fc;
+    e1000_bus_speed bus_speed;
+    e1000_bus_width bus_width;
+    e1000_bus_type bus_type;
+    uint32_t phy_id;
+    uint32_t phy_addr;
+    uint32_t original_fc;
+    uint32_t txcw;
+    uint32_t autoneg_failed;
+    uint32_t max_frame_size;
+    uint32_t min_frame_size;
+    uint32_t mc_filter_type;
+    uint32_t num_mc_addrs;
+    uint32_t collision_delta;
+    uint32_t tx_packet_delta;
+    uint32_t ledctl;
+    uint16_t autoneg_advertised;
+    uint16_t pci_cmd_word;
+    uint16_t fc_high_water;
+    uint16_t fc_low_water;
+    uint16_t fc_pause_time;
+    uint16_t current_ifs_val;
+    uint16_t ifs_min_val;
+    uint16_t ifs_max_val;
+    uint16_t ifs_step_size;
+    uint16_t ifs_ratio;
+    uint16_t device_id;
+    uint16_t vendor_id;
+    uint16_t subsystem_id;
+    uint16_t subsystem_vendor_id;
+    uint8_t revision_id;
+    uint8_t autoneg;
+    uint8_t mdix;
+    uint8_t forced_speed_duplex;
+    uint8_t wait_autoneg_complete;
+    uint8_t dma_fairness;
+    uint8_t mac_addr[NODE_ADDRESS_SIZE];
+    uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
+    boolean_t disable_polarity_correction;
+    boolean_t get_link_status;
+    boolean_t tbi_compatibility_en;
+    boolean_t tbi_compatibility_on;
+    boolean_t fc_send_xon;
+    boolean_t report_tx_early;
+    boolean_t adaptive_ifs;
+    boolean_t ifs_params_forced;
+    boolean_t in_ifs_mode;
+};
+
+
+#define E1000_EEPROM_SWDPIN0   0x0001   /* SWDPIN 0 EEPROM Value */
+#define E1000_EEPROM_LED_LOGIC 0x0020   /* Led Logic Word */
+
+/* Register Bit Masks */
+/* Device Control */
+#define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
+#define E1000_CTRL_BEM      0x00000002  /* Endian Mode.0=little,1=big */
+#define E1000_CTRL_PRIOR    0x00000004  /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_LRST     0x00000008  /* Link reset. 0=normal,1=reset */
+#define E1000_CTRL_TME      0x00000010  /* Test mode. 0=normal,1=test */
+#define E1000_CTRL_SLE      0x00000020  /* Serial Link on 0=dis,1=en */
+#define E1000_CTRL_ASDE     0x00000020  /* Auto-speed detect enable */
+#define E1000_CTRL_SLU      0x00000040  /* Set link up (Force Link) */
+#define E1000_CTRL_ILOS     0x00000080  /* Invert Loss-Of Signal */
+#define E1000_CTRL_SPD_SEL  0x00000300  /* Speed Select Mask */
+#define E1000_CTRL_SPD_10   0x00000000  /* Force 10Mb */
+#define E1000_CTRL_SPD_100  0x00000100  /* Force 100Mb */
+#define E1000_CTRL_SPD_1000 0x00000200  /* Force 1Gb */
+#define E1000_CTRL_BEM32    0x00000400  /* Big Endian 32 mode */
+#define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
+#define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
+#define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
+#define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
+#define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
+#define E1000_CTRL_SWDPIN3  0x00200000  /* SWDPIN 3 value */
+#define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
+#define E1000_CTRL_SWDPIO1  0x00800000  /* SWDPIN 1 input or output */
+#define E1000_CTRL_SWDPIO2  0x01000000  /* SWDPIN 2 input or output */
+#define E1000_CTRL_SWDPIO3  0x02000000  /* SWDPIN 3 input or output */
+#define E1000_CTRL_RST      0x04000000  /* Global reset */
+#define E1000_CTRL_RFCE     0x08000000  /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE     0x10000000  /* Transmit flow control enable */
+#define E1000_CTRL_RTE      0x20000000  /* Routing tag enable */
+#define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
+#define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
+
+/* Device Status */
+#define E1000_STATUS_FD         0x00000001      /* Full duplex.0=half,1=full */
+#define E1000_STATUS_LU         0x00000002      /* Link up.0=no,1=link */
+#define E1000_STATUS_FUNC_MASK  0x0000000C      /* PCI Function Mask */
+#define E1000_STATUS_FUNC_0     0x00000000      /* Function 0 */
+#define E1000_STATUS_FUNC_1     0x00000004      /* Function 1 */
+#define E1000_STATUS_TXOFF      0x00000010      /* transmission paused */
+#define E1000_STATUS_TBIMODE    0x00000020      /* TBI mode */
+#define E1000_STATUS_SPEED_MASK 0x000000C0
+#define E1000_STATUS_SPEED_10   0x00000000      /* Speed 10Mb/s */
+#define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
+#define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
+#define E1000_STATUS_ASDV       0x00000300      /* Auto speed detect value */
+#define E1000_STATUS_MTXCKOK    0x00000400      /* MTX clock running OK */
+#define E1000_STATUS_PCI66      0x00000800      /* In 66Mhz slot */
+#define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
+#define E1000_STATUS_PCIX_MODE  0x00002000      /* PCI-X mode */
+#define E1000_STATUS_PCIX_SPEED 0x0000C000      /* PCI-X bus speed */
+
+/* Constants used to intrepret the masked PCI-X bus speed. */
+#define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed  50-66 MHz */
+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed  66-100 MHz */
+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */
+
+/* EEPROM/Flash Control */
+#define E1000_EECD_SK        0x00000001 /* EEPROM Clock */
+#define E1000_EECD_CS        0x00000002 /* EEPROM Chip Select */
+#define E1000_EECD_DI        0x00000004 /* EEPROM Data In */
+#define E1000_EECD_DO        0x00000008 /* EEPROM Data Out */
+#define E1000_EECD_FWE_MASK  0x00000030 
+#define E1000_EECD_FWE_DIS   0x00000010 /* Disable FLASH writes */
+#define E1000_EECD_FWE_EN    0x00000020 /* Enable FLASH writes */
+#define E1000_EECD_FWE_SHIFT 4
+#define E1000_EECD_SIZE      0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
+#define E1000_EECD_REQ       0x00000040 /* EEPROM Access Request */
+#define E1000_EECD_GNT       0x00000080 /* EEPROM Access Grant */
+#define E1000_EECD_PRES      0x00000100 /* EEPROM Present */
+
+/* EEPROM Read */
+#define E1000_EERD_START      0x00000001 /* Start Read */
+#define E1000_EERD_DONE       0x00000010 /* Read Done */
+#define E1000_EERD_ADDR_SHIFT 8
+#define E1000_EERD_ADDR_MASK  0x0000FF00 /* Read Address */
+#define E1000_EERD_DATA_SHIFT 16
+#define E1000_EERD_DATA_MASK  0xFFFF0000 /* Read Data */
+
+/* Extended Device Control */
+#define E1000_CTRL_EXT_GPI0_EN   0x00000001 /* Maps SDP4 to GPI0 */ 
+#define E1000_CTRL_EXT_GPI1_EN   0x00000002 /* Maps SDP5 to GPI1 */
+#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
+#define E1000_CTRL_EXT_GPI2_EN   0x00000004 /* Maps SDP6 to GPI2 */
+#define E1000_CTRL_EXT_GPI3_EN   0x00000008 /* Maps SDP7 to GPI3 */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
+#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
+#define E1000_CTRL_EXT_PHY_INT   E1000_CTRL_EXT_SDP5_DATA
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */
+#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
+#define E1000_CTRL_EXT_SDP4_DIR  0x00000100 /* Direction of SDP4 0=in 1=out */
+#define E1000_CTRL_EXT_SDP5_DIR  0x00000200 /* Direction of SDP5 0=in 1=out */
+#define E1000_CTRL_EXT_SDP6_DIR  0x00000400 /* Direction of SDP6 0=in 1=out */
+#define E1000_CTRL_EXT_SDP7_DIR  0x00000800 /* Direction of SDP7 0=in 1=out */
+#define E1000_CTRL_EXT_ASDCHK    0x00001000 /* Initiate an ASD sequence */
+#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
+#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
+#define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
+#define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
+#define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
+#define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
+#define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
+#define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
+
+/* MDI Control */
+#define E1000_MDIC_DATA_MASK 0x0000FFFF
+#define E1000_MDIC_REG_MASK  0x001F0000
+#define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK  0x03E00000
+#define E1000_MDIC_PHY_SHIFT 21
+#define E1000_MDIC_OP_WRITE  0x04000000
+#define E1000_MDIC_OP_READ   0x08000000
+#define E1000_MDIC_READY     0x10000000
+#define E1000_MDIC_INT_EN    0x20000000
+#define E1000_MDIC_ERROR     0x40000000
+
+/* LED Control */
+#define E1000_LEDCTL_LED0_MODE_MASK  0x0000000F
+#define E1000_LEDCTL_LED0_MODE_SHIFT 0
+#define E1000_LEDCTL_LED0_IVRT       0x00000040
+#define E1000_LEDCTL_LED0_BLINK      0x00000080
+#define E1000_LEDCTL_LED1_MODE_MASK  0x00000F00
+#define E1000_LEDCTL_LED1_MODE_SHIFT 8
+#define E1000_LEDCTL_LED1_IVRT       0x00004000
+#define E1000_LEDCTL_LED1_BLINK      0x00008000
+#define E1000_LEDCTL_LED2_MODE_MASK  0x000F0000
+#define E1000_LEDCTL_LED2_MODE_SHIFT 16
+#define E1000_LEDCTL_LED2_IVRT       0x00400000
+#define E1000_LEDCTL_LED2_BLINK      0x00800000
+#define E1000_LEDCTL_LED3_MODE_MASK  0x0F000000
+#define E1000_LEDCTL_LED3_MODE_SHIFT 24
+#define E1000_LEDCTL_LED3_IVRT       0x40000000
+#define E1000_LEDCTL_LED3_BLINK      0x80000000
+
+#define E1000_LEDCTL_MODE_LINK_10_1000  0x0
+#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
+#define E1000_LEDCTL_MODE_LINK_UP       0x2
+#define E1000_LEDCTL_MODE_ACTIVITY      0x3
+#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
+#define E1000_LEDCTL_MODE_LINK_10       0x5
+#define E1000_LEDCTL_MODE_LINK_100      0x6
+#define E1000_LEDCTL_MODE_LINK_1000     0x7
+#define E1000_LEDCTL_MODE_PCIX_MODE     0x8
+#define E1000_LEDCTL_MODE_FULL_DUPLEX   0x9
+#define E1000_LEDCTL_MODE_COLLISION     0xA
+#define E1000_LEDCTL_MODE_BUS_SPEED     0xB
+#define E1000_LEDCTL_MODE_BUS_SIZE      0xC
+#define E1000_LEDCTL_MODE_PAUSED        0xD
+#define E1000_LEDCTL_MODE_LED_ON        0xE
+#define E1000_LEDCTL_MODE_LED_OFF       0xF
+
+/* Receive Address */
+#define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
+
+/* Interrupt Cause Read */
+#define E1000_ICR_TXDW    0x00000001    /* Transmit desc written back */
+#define E1000_ICR_TXQE    0x00000002    /* Transmit Queue empty */
+#define E1000_ICR_LSC     0x00000004    /* Link Status Change */
+#define E1000_ICR_RXSEQ   0x00000008    /* rx sequence error */
+#define E1000_ICR_RXDMT0  0x00000010    /* rx desc min. threshold (0) */
+#define E1000_ICR_RXO     0x00000040    /* rx overrun */
+#define E1000_ICR_RXT0    0x00000080    /* rx timer intr (ring 0) */
+#define E1000_ICR_MDAC    0x00000200    /* MDIO access complete */
+#define E1000_ICR_RXCFG   0x00000400    /* RX /c/ ordered set */
+#define E1000_ICR_GPI_EN0 0x00000800    /* GP Int 0 */
+#define E1000_ICR_GPI_EN1 0x00001000    /* GP Int 1 */
+#define E1000_ICR_GPI_EN2 0x00002000    /* GP Int 2 */
+#define E1000_ICR_GPI_EN3 0x00004000    /* GP Int 3 */
+#define E1000_ICR_TXD_LOW 0x00008000
+#define E1000_ICR_SRPD    0x00010000
+
+/* Interrupt Cause Set */
+#define E1000_ICS_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
+#define E1000_ICS_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
+#define E1000_ICS_LSC     E1000_ICR_LSC         /* Link Status Change */
+#define E1000_ICS_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
+#define E1000_ICS_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
+#define E1000_ICS_RXO     E1000_ICR_RXO         /* rx overrun */
+#define E1000_ICS_RXT0    E1000_ICR_RXT0        /* rx timer intr */
+#define E1000_ICS_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
+#define E1000_ICS_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
+#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
+#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
+#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
+#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
+#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_ICS_SRPD    E1000_ICR_SRPD
+
+/* Interrupt Mask Set */
+#define E1000_IMS_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
+#define E1000_IMS_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
+#define E1000_IMS_LSC     E1000_ICR_LSC         /* Link Status Change */
+#define E1000_IMS_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
+#define E1000_IMS_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
+#define E1000_IMS_RXO     E1000_ICR_RXO         /* rx overrun */
+#define E1000_IMS_RXT0    E1000_ICR_RXT0        /* rx timer intr */
+#define E1000_IMS_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
+#define E1000_IMS_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
+#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
+#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
+#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
+#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
+#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_IMS_SRPD    E1000_ICR_SRPD
+
+/* Interrupt Mask Clear */
+#define E1000_IMC_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
+#define E1000_IMC_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
+#define E1000_IMC_LSC     E1000_ICR_LSC         /* Link Status Change */
+#define E1000_IMC_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
+#define E1000_IMC_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
+#define E1000_IMC_RXO     E1000_ICR_RXO         /* rx overrun */
+#define E1000_IMC_RXT0    E1000_ICR_RXT0        /* rx timer intr */
+#define E1000_IMC_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
+#define E1000_IMC_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
+#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
+#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
+#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
+#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
+#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW
+#define E1000_IMC_SRPD    E1000_ICR_SRPD
+
+/* Receive Control */
+#define E1000_RCTL_RST          0x00000001      /* Software reset */
+#define E1000_RCTL_EN           0x00000002      /* enable */
+#define E1000_RCTL_SBP          0x00000004      /* store bad packet */
+#define E1000_RCTL_UPE          0x00000008      /* unicast promiscuous enable */
+#define E1000_RCTL_MPE          0x00000010      /* multicast promiscuous enab */
+#define E1000_RCTL_LPE          0x00000020      /* long packet enable */
+#define E1000_RCTL_LBM_NO       0x00000000      /* no loopback mode */
+#define E1000_RCTL_LBM_MAC      0x00000040      /* MAC loopback mode */
+#define E1000_RCTL_LBM_SLP      0x00000080      /* serial link loopback mode */
+#define E1000_RCTL_LBM_TCVR     0x000000C0      /* tcvr loopback mode */
+#define E1000_RCTL_RDMTS_HALF   0x00000000      /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_QUAT   0x00000100      /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_EIGTH  0x00000200      /* rx desc min threshold size */
+#define E1000_RCTL_MO_SHIFT     12              /* multicast offset shift */
+#define E1000_RCTL_MO_0         0x00000000      /* multicast offset 11:0 */
+#define E1000_RCTL_MO_1         0x00001000      /* multicast offset 12:1 */
+#define E1000_RCTL_MO_2         0x00002000      /* multicast offset 13:2 */
+#define E1000_RCTL_MO_3         0x00003000      /* multicast offset 15:4 */
+#define E1000_RCTL_MDR          0x00004000      /* multicast desc ring 0 */
+#define E1000_RCTL_BAM          0x00008000      /* broadcast enable */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+#define E1000_RCTL_SZ_2048      0x00000000      /* rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024      0x00010000      /* rx buffer size 1024 */
+#define E1000_RCTL_SZ_512       0x00020000      /* rx buffer size 512 */
+#define E1000_RCTL_SZ_256       0x00030000      /* rx buffer size 256 */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+#define E1000_RCTL_SZ_16384     0x00010000      /* rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192      0x00020000      /* rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096      0x00030000      /* rx buffer size 4096 */
+#define E1000_RCTL_VFE          0x00040000      /* vlan filter enable */
+#define E1000_RCTL_CFIEN        0x00080000      /* canonical form enable */
+#define E1000_RCTL_CFI          0x00100000      /* canonical form indicator */
+#define E1000_RCTL_DPF          0x00400000      /* discard pause frames */
+#define E1000_RCTL_PMCF         0x00800000      /* pass MAC control frames */
+#define E1000_RCTL_BSEX         0x02000000      /* Buffer size extension */
+
+/* Receive Descriptor */
+#define E1000_RDT_DELAY 0x0000ffff      /* Delay timer (1=1024us) */
+#define E1000_RDT_FPDB  0x80000000      /* Flush descriptor block */
+#define E1000_RDLEN_LEN 0x0007ff80      /* descriptor length */
+#define E1000_RDH_RDH   0x0000ffff      /* receive descriptor head */
+#define E1000_RDT_RDT   0x0000ffff      /* receive descriptor tail */
+
+/* Flow Control */
+#define E1000_FCRTH_RTH  0x0000FFF8     /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTH_XFCE 0x80000000     /* External Flow Control Enable */
+#define E1000_FCRTL_RTL  0x0000FFF8     /* Mask Bits[15:3] for RTL */
+#define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
+
+/* Receive Descriptor Control */
+#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
+#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
+#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */
+#define E1000_RXDCTL_GRAN    0x01000000 /* RXDCTL Granularity */
+
+/* Transmit Descriptor Control */
+#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+
+/* Transmit Configuration Word */
+#define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
+#define E1000_TXCW_HD         0x00000040        /* TXCW half duplex */
+#define E1000_TXCW_PAUSE      0x00000080        /* TXCW sym pause request */
+#define E1000_TXCW_ASM_DIR    0x00000100        /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE_MASK 0x00000180        /* TXCW pause request mask */
+#define E1000_TXCW_RF         0x00003000        /* TXCW remote fault */
+#define E1000_TXCW_NP         0x00008000        /* TXCW next page */
+#define E1000_TXCW_CW         0x0000ffff        /* TxConfigWord mask */
+#define E1000_TXCW_TXC        0x40000000        /* Transmit Config control */
+#define E1000_TXCW_ANE        0x80000000        /* Auto-neg enable */
+
+/* Receive Configuration Word */
+#define E1000_RXCW_CW    0x0000ffff     /* RxConfigWord mask */
+#define E1000_RXCW_NC    0x04000000     /* Receive config no carrier */
+#define E1000_RXCW_IV    0x08000000     /* Receive config invalid */
+#define E1000_RXCW_CC    0x10000000     /* Receive config change */
+#define E1000_RXCW_C     0x20000000     /* Receive config */
+#define E1000_RXCW_SYNCH 0x40000000     /* Receive config synch */
+#define E1000_RXCW_ANC   0x80000000     /* Auto-neg complete */
+
+/* Transmit Control */
+#define E1000_TCTL_RST    0x00000001    /* software reset */
+#define E1000_TCTL_EN     0x00000002    /* enable tx */
+#define E1000_TCTL_BCE    0x00000004    /* busy check enable */
+#define E1000_TCTL_PSP    0x00000008    /* pad short packets */
+#define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
+#define E1000_TCTL_COLD   0x003ff000    /* collision distance */
+#define E1000_TCTL_SWXOFF 0x00400000    /* SW Xoff transmission */
+#define E1000_TCTL_PBE    0x00800000    /* Packet Burst Enable */
+#define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
+#define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
+
+/* Receive Checksum Control */
+#define E1000_RXCSUM_PCSS_MASK 0x000000FF   /* Packet Checksum Start */
+#define E1000_RXCSUM_IPOFL     0x00000100   /* IPv4 checksum offload */
+#define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
+#define E1000_RXCSUM_IPV6OFL   0x00000400   /* IPv6 checksum offload */
+
+/* Definitions for power management and wakeup registers */
+/* Wake Up Control */
+#define E1000_WUC_APME       0x00000001 /* APM Enable */
+#define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
+#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
+#define E1000_WUC_APMPME     0x00000008 /* Assert PME on APM Wakeup */
+
+/* Wake Up Filter Control */
+#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define E1000_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define E1000_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define E1000_WUFC_MC   0x00000008 /* Directed Multicast Wakeup Enable */
+#define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+#define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
+#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
+#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
+#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
+#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
+#define E1000_WUFC_FLX_OFFSET 16       /* Offset to the Flexible Filters bits */
+#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+
+/* Wake Up Status */
+#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */
+#define E1000_WUS_MAG  0x00000002 /* Magic Packet Received */
+#define E1000_WUS_EX   0x00000004 /* Directed Exact Received */
+#define E1000_WUS_MC   0x00000008 /* Directed Multicast Received */
+#define E1000_WUS_BC   0x00000010 /* Broadcast Received */
+#define E1000_WUS_ARP  0x00000020 /* ARP Request Packet Received */
+#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */
+#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */
+#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */
+#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */
+#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */
+#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */
+#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+
+/* Management Control */
+#define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
+#define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_R_ON_FORCE    0x00000004 /* Reset on Force TCO - RO */
+#define E1000_MANC_RMCP_EN       0x00000100 /* Enable RCMP 026Fh Filtering */
+#define E1000_MANC_0298_EN       0x00000200 /* Enable RCMP 0298h Filtering */
+#define E1000_MANC_IPV4_EN       0x00000400 /* Enable IPv4 */
+#define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
+#define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
+#define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
+#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery 
+                                             * Filtering */
+#define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
+#define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
+#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
+#define E1000_MANC_SMB_GNT       0x02000000 /* SMBus Grant */
+#define E1000_MANC_SMB_CLK_IN    0x04000000 /* SMBus Clock In */
+#define E1000_MANC_SMB_DATA_IN   0x08000000 /* SMBus Data In */
+#define E1000_MANC_SMB_DATA_OUT  0x10000000 /* SMBus Data Out */
+#define E1000_MANC_SMB_CLK_OUT   0x20000000 /* SMBus Clock Out */
+
+#define E1000_MANC_SMB_DATA_OUT_SHIFT  28 /* SMBus Data Out Shift */
+#define E1000_MANC_SMB_CLK_OUT_SHIFT   29 /* SMBus Clock Out Shift */
+
+/* Wake Up Packet Length */
+#define E1000_WUPL_LENGTH_MASK 0x0FFF   /* Only the lower 12 bits are valid */
+
+#define E1000_MDALIGN          4096
+
+/* EEPROM Commands */
+#define EEPROM_READ_OPCODE  0x6  /* EERPOM read opcode */
+#define EEPROM_WRITE_OPCODE 0x5  /* EERPOM write opcode */
+#define EEPROM_ERASE_OPCODE 0x7  /* EERPOM erase opcode */
+#define EEPROM_EWEN_OPCODE  0x13 /* EERPOM erase/write enable */
+#define EEPROM_EWDS_OPCODE  0x10 /* EERPOM erast/write disable */
+
+/* EEPROM Word Offsets */
+#define EEPROM_INIT_CONTROL1_REG 0x000A
+#define EEPROM_INIT_CONTROL2_REG 0x000F
+#define EEPROM_FLASH_VERSION     0x0032
+#define EEPROM_CHECKSUM_REG      0x003F
+
+/* Mask bits for fields in Word 0x0a of the EEPROM */
+#define EEPROM_WORD0A_ILOS   0x0010
+#define EEPROM_WORD0A_SWDPIO 0x01E0
+#define EEPROM_WORD0A_LRST   0x0200
+#define EEPROM_WORD0A_FD     0x0400
+#define EEPROM_WORD0A_66MHZ  0x0800
+
+/* Mask bits for fields in Word 0x0f of the EEPROM */
+#define EEPROM_WORD0F_PAUSE_MASK 0x3000
+#define EEPROM_WORD0F_PAUSE      0x1000
+#define EEPROM_WORD0F_ASM_DIR    0x2000
+#define EEPROM_WORD0F_ANE        0x0800
+#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
+
+/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
+#define EEPROM_SUM 0xBABA
+
+/* EEPROM Map defines (WORD OFFSETS)*/
+#define EEPROM_NODE_ADDRESS_BYTE_0 0
+#define EEPROM_PBA_BYTE_1          8
+
+/* EEPROM Map Sizes (Byte Counts) */
+#define PBA_SIZE 4
+
+/* Collision related configuration parameters */
+#define E1000_COLLISION_THRESHOLD       16
+#define E1000_CT_SHIFT                  4
+#define E1000_COLLISION_DISTANCE        64
+#define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
+#define E1000_HDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
+#define E1000_GB_HDX_COLLISION_DISTANCE 512
+#define E1000_COLD_SHIFT                12
+
+/* The number of Transmit and Receive Descriptors must be a multiple of 8 */
+#define REQ_TX_DESCRIPTOR_MULTIPLE  8
+#define REQ_RX_DESCRIPTOR_MULTIPLE  8
+
+/* Default values for the transmit IPG register */
+#define DEFAULT_82542_TIPG_IPGT        10
+#define DEFAULT_82543_TIPG_IPGT_FIBER  9
+#define DEFAULT_82543_TIPG_IPGT_COPPER 8
+
+#define E1000_TIPG_IPGT_MASK  0x000003FF
+#define E1000_TIPG_IPGR1_MASK 0x000FFC00
+#define E1000_TIPG_IPGR2_MASK 0x3FF00000
+
+#define DEFAULT_82542_TIPG_IPGR1 2
+#define DEFAULT_82543_TIPG_IPGR1 8
+#define E1000_TIPG_IPGR1_SHIFT  10
+
+#define DEFAULT_82542_TIPG_IPGR2 10
+#define DEFAULT_82543_TIPG_IPGR2 6
+#define E1000_TIPG_IPGR2_SHIFT  20
+
+#define E1000_TXDMAC_DPP 0x00000001
+
+/* Adaptive IFS defines */
+#define TX_THRESHOLD_START     8
+#define TX_THRESHOLD_INCREMENT 10
+#define TX_THRESHOLD_DECREMENT 1
+#define TX_THRESHOLD_STOP      190
+#define TX_THRESHOLD_DISABLE   0
+#define TX_THRESHOLD_TIMER_MS  10000
+#define MIN_NUM_XMITS          1000
+#define IFS_MAX                80
+#define IFS_STEP               10
+#define IFS_MIN                40
+#define IFS_RATIO              4
+
+/* PBA constants */
+#define E1000_PBA_16K 0x0010    /* 16KB, default TX allocation */
+#define E1000_PBA_24K 0x0018
+#define E1000_PBA_40K 0x0028
+#define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
+
+/* Flow Control Constants */
+#define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
+#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
+#define FLOW_CONTROL_TYPE         0x8808
+
+/* The historical defaults for the flow control values are given below. */
+#define FC_DEFAULT_HI_THRESH        (0x8000)    /* 32KB */
+#define FC_DEFAULT_LO_THRESH        (0x4000)    /* 16KB */
+#define FC_DEFAULT_TX_TIMER         (0x100)     /* ~130 us */
+
+
+/* The number of bits that we need to shift right to move the "pause"
+ * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field
+ * in the TXCW register 
+ */
+#define PAUSE_SHIFT 5
+
+/* The number of bits that we need to shift left to move the "SWDPIO"
+ * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field
+ * in the CTRL register 
+ */
+#define SWDPIO_SHIFT 17
+
+/* The number of bits that we need to shift left to move the "SWDPIO_EXT"
+ * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The
+ * Extended CTRL register.
+ * in the CTRL register 
+ */
+#define SWDPIO__EXT_SHIFT 4
+
+/* The number of bits that we need to shift left to move the "ILOS"
+ * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field
+ * in the CTRL register 
+ */
+#define ILOS_SHIFT  3
+
+
+#define RECEIVE_BUFFER_ALIGN_SIZE  (256)
+
+/* The number of milliseconds we wait for auto-negotiation to complete */
+#define LINK_UP_TIMEOUT             500
+
+#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
+
+/* The carrier extension symbol, as received by the NIC. */
+#define CARRIER_EXTENSION   0x0F
+
+/* TBI_ACCEPT macro definition:
+ *
+ * This macro requires:
+ *      adapter = a pointer to struct e1000_hw 
+ *      status = the 8 bit status field of the RX descriptor with EOP set
+ *      error = the 8 bit error field of the RX descriptor with EOP set
+ *      length = the sum of all the length fields of the RX descriptors that
+ *               make up the current frame
+ *      last_byte = the last byte of the frame DMAed by the hardware
+ *      max_frame_length = the maximum frame length we want to accept.
+ *      min_frame_length = the minimum frame length we want to accept.
+ *
+ * This macro is a conditional that should be used in the interrupt 
+ * handler's Rx processing routine when RxErrors have been detected.
+ *
+ * Typical use:
+ *  ...
+ *  if (TBI_ACCEPT) {
+ *      accept_frame = TRUE;
+ *      e1000_tbi_adjust_stats(adapter, MacAddress);
+ *      frame_length--;
+ *  } else {
+ *      accept_frame = FALSE;
+ *  }
+ *  ...
+ */
+
+#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \
+    ((adapter)->tbi_compatibility_on && \
+     (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
+     ((last_byte) == CARRIER_EXTENSION) && \
+     (((status) & E1000_RXD_STAT_VP) ? \
+          (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \
+           ((length) <= ((adapter)->max_frame_size + 1))) : \
+          (((length) > (adapter)->min_frame_size) && \
+           ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1)))))
+
+
+/* Structures, enums, and macros for the PHY */
+
+/* Bit definitions for the Management Data IO (MDIO) and Management Data
+ * Clock (MDC) pins in the Device Control Register.
+ */
+#define E1000_CTRL_PHY_RESET_DIR  E1000_CTRL_SWDPIO0
+#define E1000_CTRL_PHY_RESET      E1000_CTRL_SWDPIN0
+#define E1000_CTRL_MDIO_DIR       E1000_CTRL_SWDPIO2
+#define E1000_CTRL_MDIO           E1000_CTRL_SWDPIN2
+#define E1000_CTRL_MDC_DIR        E1000_CTRL_SWDPIO3
+#define E1000_CTRL_MDC            E1000_CTRL_SWDPIN3
+#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
+#define E1000_CTRL_PHY_RESET4     E1000_CTRL_EXT_SDP4_DATA
+
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CTRL         0x00 /* Control Register */
+#define PHY_STATUS       0x01 /* Status Regiser */
+#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
+
+/* M88E1000 Specific Registers */
+#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
+#define M88E1000_PHY_SPEC_STATUS   0x11  /* PHY Specific Status Register */
+#define M88E1000_INT_ENABLE        0x12  /* Interrupt Enable Register */
+#define M88E1000_INT_STATUS        0x13  /* Interrupt Status Register */
+#define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
+#define M88E1000_RX_ERR_CNTR       0x15  /* Receive Error Counter */
+
+#define MAX_PHY_REG_ADDRESS 0x1F        /* 5 bit address bus (0-0x1F) */
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
+#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
+#define MII_CR_ISOLATE          0x0400  /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN       0x0800  /* Power down */
+#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS     0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT     0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS      0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT      0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS   0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS     0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS     0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS       0x0800 /* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS       0x1000 /* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS      0x2000 /* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS      0x4000 /* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS        0x8000 /* 100T4 Capable */
+
+/* Autoneg Advertisement Register */
+#define NWAY_AR_SELECTOR_FIELD 0x0001   /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS    0x0020   /* 10T   Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS    0x0040   /* 10T   Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS  0x0080   /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS  0x0100   /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS     0x0200   /* 100T4 Capable */
+#define NWAY_AR_PAUSE          0x0400   /* Pause operation desired */
+#define NWAY_AR_ASM_DIR        0x0800   /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT   0x2000   /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE      0x8000   /* Next Page ability supported */
+
+/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS    0x0020 /* LP is 10T   Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS    0x0040 /* LP is 10T   Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS  0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS  0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS     0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT   0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE    0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE      0x8000 /* Next Page ability supported */
+
+/* Autoneg Expansion Register */
+#define NWAY_ER_LP_NWAY_CAPS      0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD          0x0002 /* LP is 10T   Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS    0x0004 /* LP is 10T   Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT  0x0100 /* LP is 100TX Full Duplex Capable */
+
+/* Next Page TX Register */
+#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define NPTX_TOGGLE         0x0800 /* Toggles between exchanges
+                                    * of different NP
+                                    */
+#define NPTX_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
+                                    * 0 = cannot comply with msg
+                                    */
+#define NPTX_MSG_PAGE       0x2000 /* formatted(1)/unformatted(0) pg */
+#define NPTX_NEXT_PAGE      0x8000 /* 1 = addition NP will follow 
+                                    * 0 = sending last NP
+                                    */
+
+/* Link Partner Next Page Register */
+#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define LP_RNPR_TOGGLE         0x0800 /* Toggles between exchanges
+                                       * of different NP
+                                       */
+#define LP_RNPR_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg 
+                                       * 0 = cannot comply with msg
+                                       */
+#define LP_RNPR_MSG_PAGE       0x2000  /* formatted(1)/unformatted(0) pg */
+#define LP_RNPR_ACKNOWLDGE     0x4000  /* 1 = ACK / 0 = NO ACK */
+#define LP_RNPR_NEXT_PAGE      0x8000  /* 1 = addition NP will follow
+                                        * 0 = sending last NP 
+                                        */
+
+/* 1000BASE-T Control Register */
+#define CR_1000T_ASYM_PAUSE      0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
+#define CR_1000T_REPEATER_DTE    0x0400 /* 1=Repeater/switch device port */
+                                        /* 0=DTE device */
+#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
+                                        /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE       0x1000 /* 1=Master/Slave manual config value */
+                                        /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1     0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2     0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3     0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4     0x8000 /* Transmitter Distortion test */
+
+/* 1000BASE-T Status Register */
+#define SR_1000T_IDLE_ERROR_CNT   0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR   0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS       0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local TX is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
+#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12
+#define SR_1000T_LOCAL_RX_STATUS_SHIFT  13
+
+/* Extended Status Register */
+#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+
+#define PHY_TX_POLARITY_MASK   0x0100 /* register 10h bit 8 (polarity bit) */
+#define PHY_TX_NORMAL_POLARITY 0      /* register 10h bit 8 (normal polarity) */
+
+#define AUTO_POLARITY_DISABLE  0x0010 /* register 11h bit 4 */
+                                      /* (0=enable, 1=disable) */
+
+/* M88E1000 PHY Specific Control Register */
+#define M88E1000_PSCR_JABBER_DISABLE    0x0001 /* 1=Jabber Function disabled */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define M88E1000_PSCR_SQE_TEST          0x0004 /* 1=SQE Test enabled */
+#define M88E1000_PSCR_CLK125_DISABLE    0x0010 /* 1=CLK125 low, 
+                                                * 0=CLK125 toggling
+                                                */
+#define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000  /* MDI Crossover Mode bits 6:5 */
+                                               /* Manual MDI configuration */
+#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
+#define M88E1000_PSCR_AUTO_X_1000T     0x0040  /* 1000BASE-T: Auto crossover,
+                                                *  100BASE-TX/10BASE-T: 
+                                                *  MDI Mode
+                                                */
+#define M88E1000_PSCR_AUTO_X_MODE      0x0060  /* Auto crossover enabled 
+                                                * all speeds. 
+                                                */
+#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 
+                                        /* 1=Enable Extended 10BASE-T distance
+                                         * (Lower 10BASE-T RX Threshold)
+                                         * 0=Normal 10BASE-T RX Threshold */
+#define M88E1000_PSCR_MII_5BIT_ENABLE      0x0100
+                                        /* 1=5-Bit interface in 100BASE-TX
+                                         * 0=MII interface in 100BASE-TX */
+#define M88E1000_PSCR_SCRAMBLER_DISABLE    0x0200 /* 1=Scrambler disable */
+#define M88E1000_PSCR_FORCE_LINK_GOOD      0x0400 /* 1=Force link good */
+#define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800 /* 1=Assert CRS on Transmit */
+
+#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT    1
+#define M88E1000_PSCR_AUTO_X_MODE_SHIFT          5
+#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+
+/* M88E1000 PHY Specific Status Register */
+#define M88E1000_PSSR_JABBER             0x0001 /* 1=Jabber */
+#define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
+#define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
+#define M88E1000_PSSR_CABLE_LENGTH       0x0380 /* 0=<50M;1=50-80M;2=80-110M;
+                                            * 3=110-140M;4=>140M */
+#define M88E1000_PSSR_LINK               0x0400 /* 1=Link up, 0=Link down */
+#define M88E1000_PSSR_SPD_DPLX_RESOLVED  0x0800 /* 1=Speed & Duplex resolved */
+#define M88E1000_PSSR_PAGE_RCVD          0x1000 /* 1=Page received */
+#define M88E1000_PSSR_DPLX               0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88E1000_PSSR_SPEED              0xC000 /* Speed, bits 14:15 */
+#define M88E1000_PSSR_10MBS              0x0000 /* 00=10Mbs */
+#define M88E1000_PSSR_100MBS             0x4000 /* 01=100Mbs */
+#define M88E1000_PSSR_1000MBS            0x8000 /* 10=1000Mbs */
+
+#define M88E1000_PSSR_REV_POLARITY_SHIFT 1
+#define M88E1000_PSSR_MDIX_SHIFT         6
+#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
+
+/* M88E1000 Extended PHY Specific Control Register */
+#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
+#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000 /* 1=Lost lock detect enabled.
+                                              * Will assert lost lock and bring
+                                              * link down if idle not seen
+                                              * within 1ms in 1000BASE-T 
+                                              */
+/* Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master */
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000    
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X   0x0400
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X   0x0800
+#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X   0x0C00
+/* Number of times we will attempt to autonegotiate before downshifting if we
+ * are the slave */
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS   0x0000
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X    0x0200
+#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X    0x0300
+#define M88E1000_EPSCR_TX_CLK_2_5     0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0       0x0000 /* NO  TX_CLK */
+
+/* Bit definitions for valid PHY IDs. */
+#define M88E1000_E_PHY_ID  0x01410C50
+#define M88E1000_I_PHY_ID  0x01410C30
+#define M88E1011_I_PHY_ID  0x01410C20
+#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
+#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
+
+/* Miscellaneous PHY bit definitions. */
+#define PHY_PREAMBLE        0xFFFFFFFF
+#define PHY_SOF             0x01
+#define PHY_OP_READ         0x02
+#define PHY_OP_WRITE        0x01
+#define PHY_TURNAROUND      0x02
+#define PHY_PREAMBLE_SIZE   32
+#define MII_CR_SPEED_1000   0x0040
+#define MII_CR_SPEED_100    0x2000
+#define MII_CR_SPEED_10     0x0000
+#define E1000_PHY_ADDRESS   0x01
+#define PHY_AUTO_NEG_TIME   45  /* 4.5 Seconds */
+#define PHY_FORCE_TIME      20  /* 2.0 Seconds */
+#define PHY_REVISION_MASK   0xFFFFFFF0
+#define DEVICE_SPEED_MASK   0x00000300  /* Device Ctrl Reg Speed Mask */
+#define REG4_SPEED_MASK     0x01E0
+#define REG9_SPEED_MASK     0x0300
+#define ADVERTISE_10_HALF   0x0001
+#define ADVERTISE_10_FULL   0x0002
+#define ADVERTISE_100_HALF  0x0004
+#define ADVERTISE_100_FULL  0x0008
+#define ADVERTISE_1000_HALF 0x0010
+#define ADVERTISE_1000_FULL 0x0020
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F  /* Everything but 1000-Half */
+
+#endif /* _E1000_HW_H_ */
diff -Nru a/drivers/net/e1000/e1000_mac.c b/drivers/net/e1000/e1000_mac.c
--- a/drivers/net/e1000/e1000_mac.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1821 +0,0 @@
-/*******************************************************************************
-
-  This software program is available to you under a choice of one of two
-  licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
-  
-  Recipient has requested a license and Intel Corporation ("Intel") is willing
-  to grant a license for the software entitled Linux Base Driver for the
-  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
-  by Intel Corporation. The following definitions apply to this license:
-  
-  "Licensed Patents" means patent claims licensable by Intel Corporation which
-  are necessarily infringed by the use of sale of the Software alone or when
-  combined with the operating system referred to below.
-  
-  "Recipient" means the party to whom Intel delivers this Software.
-  
-  "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
-  later.
-  
-  Copyright (c) 1999 - 2002 Intel Corporation.
-  All rights reserved.
-  
-  The license is provided to Recipient and Recipient's Licensees under the
-  following terms.
-  
-  Redistribution and use in source and binary forms of the Software, with or
-  without modification, are permitted provided that the following conditions
-  are met:
-  
-  Redistributions of source code of the Software may retain the above
-  copyright notice, this list of conditions and the following disclaimer.
-  
-  Redistributions in binary form of the Software may reproduce the above
-  copyright notice, this list of conditions and the following disclaimer in
-  the documentation and/or materials provided with the distribution.
-  
-  Neither the name of Intel Corporation nor the names of its contributors
-  shall be used to endorse or promote products derived from this Software
-  without specific prior written permission.
-  
-  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
-  royalty-free patent license under Licensed Patents to make, use, sell, offer
-  to sell, import and otherwise transfer the Software, if any, in source code
-  and object code form. This license shall include changes to the Software
-  that are error corrections or other minor changes to the Software that do
-  not add functionality or features when the Software is incorporated in any
-  version of an operating system that has been distributed under the GNU
-  General Public License 2.0 or later. This patent license shall apply to the
-  combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
-  Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
-  such combination to be covered by the Licensed Patents. The patent license
-  shall not apply to any other combinations which include the Software. NO
-  hardware per se is licensed hereunder.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
-  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
-  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
-
-/* e1000_mac.c
- * Shared functions for accessing and configuring the MAC
- */
-
-#include "e1000_mac.h"
-#include "e1000_phy.h"
-
-/******************************************************************************
- * Raises the EEPROM's clock input.
- *
- * shared - Struct containing variables accessed by shared code
- * eecd_reg - EECD's current value
- *****************************************************************************/
-static void
-e1000_raise_clock(struct e1000_shared_adapter *shared,
-                  uint32_t *eecd_reg)
-{
-    /* Raise the clock input to the EEPROM (by setting the SK bit), and then
-     * wait 50 microseconds.
-     */
-    *eecd_reg = *eecd_reg | E1000_EECD_SK;
-    E1000_WRITE_REG(shared, EECD, *eecd_reg);
-    usec_delay(50);
-    return;
-}
-
-/******************************************************************************
- * Lowers the EEPROM's clock input.
- *
- * shared - Struct containing variables accessed by shared code 
- * eecd_reg - EECD's current value
- *****************************************************************************/
-static void
-e1000_lower_clock(struct e1000_shared_adapter *shared,
-                  uint32_t *eecd_reg)
-{
-    /* Lower the clock input to the EEPROM (by clearing the SK bit), and then 
-     * wait 50 microseconds. 
-     */
-    *eecd_reg = *eecd_reg & ~E1000_EECD_SK;
-    E1000_WRITE_REG(shared, EECD, *eecd_reg);
-    usec_delay(50);
-    return;
-}
-
-/******************************************************************************
- * Shift data bits out to the EEPROM.
- *
- * shared - Struct containing variables accessed by shared code
- * data - data to send to the EEPROM
- * count - number of bits to shift out
- *****************************************************************************/
-static void
-e1000_shift_out_bits(struct e1000_shared_adapter *shared,
-                     uint16_t data,
-                     uint16_t count)
-{
-    uint32_t eecd_reg;
-    uint32_t mask;
-
-    /* We need to shift "count" bits out to the EEPROM. So, value in the
-     * "data" parameter will be shifted out to the EEPROM one bit at a time.
-     * In order to do this, "data" must be broken down into bits. 
-     */
-    mask = 0x01 << (count - 1);
-    eecd_reg = E1000_READ_REG(shared, EECD);
-    eecd_reg &= ~(E1000_EECD_DO | E1000_EECD_DI);
-    do {
-        /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
-         * and then raising and then lowering the clock (the SK bit controls
-         * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
-         * by setting "DI" to "0" and then raising and then lowering the clock.
-         */
-        eecd_reg &= ~E1000_EECD_DI;
-
-        if(data & mask)
-            eecd_reg |= E1000_EECD_DI;
-
-        E1000_WRITE_REG(shared, EECD, eecd_reg);
-
-        usec_delay(50);
-
-        e1000_raise_clock(shared, &eecd_reg);
-        e1000_lower_clock(shared, &eecd_reg);
-
-        mask = mask >> 1;
-
-    } while(mask);
-
-    /* We leave the "DI" bit set to "0" when we leave this routine. */
-    eecd_reg &= ~E1000_EECD_DI;
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-    return;
-}
-
-/******************************************************************************
- * Shift data bits in from the EEPROM
- *
- * shared - Struct containing variables accessed by shared code
- *****************************************************************************/
-static uint16_t
-e1000_shift_in_bits(struct e1000_shared_adapter *shared)
-{
-    uint32_t eecd_reg;
-    uint32_t i;
-    uint16_t data;
-
-    /* In order to read a register from the EEPROM, we need to shift 16 bits 
-     * in from the EEPROM. Bits are "shifted in" by raising the clock input to
-     * the EEPROM (setting the SK bit), and then reading the value of the "DO"
-     * bit.  During this "shifting in" process the "DI" bit should always be 
-     * clear..
-     */
-
-    eecd_reg = E1000_READ_REG(shared, EECD);
-
-    eecd_reg &= ~(E1000_EECD_DO | E1000_EECD_DI);
-    data = 0;
-
-    for(i = 0; i < 16; i++) {
-        data = data << 1;
-        e1000_raise_clock(shared, &eecd_reg);
-
-        eecd_reg = E1000_READ_REG(shared, EECD);
-
-        eecd_reg &= ~(E1000_EECD_DI);
-        if(eecd_reg & E1000_EECD_DO)
-            data |= 1;
-
-        e1000_lower_clock(shared, &eecd_reg);
-    }
-
-    return data;
-}
-
-/******************************************************************************
- * Prepares EEPROM for access
- *
- * shared - Struct containing variables accessed by shared code
- *
- * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This 
- * function should be called before issuing a command to the EEPROM.
- *****************************************************************************/
-static void
-e1000_setup_eeprom(struct e1000_shared_adapter *shared)
-{
-    uint32_t eecd_reg;
-
-    eecd_reg = E1000_READ_REG(shared, EECD);
-
-    /* Clear SK and DI */
-    eecd_reg &= ~(E1000_EECD_SK | E1000_EECD_DI);
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-
-    /* Set CS */
-    eecd_reg |= E1000_EECD_CS;
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-    return;
-}
-
-/******************************************************************************
- * Returns EEPROM to a "standby" state
- * 
- * shared - Struct containing variables accessed by shared code
- *****************************************************************************/
-static void
-e1000_standby_eeprom(struct e1000_shared_adapter *shared)
-{
-    uint32_t eecd_reg;
-
-    eecd_reg = E1000_READ_REG(shared, EECD);
-
-    /* Deselct EEPROM */
-    eecd_reg &= ~(E1000_EECD_CS | E1000_EECD_SK);
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-    usec_delay(50);
-
-    /* Clock high */
-    eecd_reg |= E1000_EECD_SK;
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-    usec_delay(50);
-
-    /* Select EEPROM */
-    eecd_reg |= E1000_EECD_CS;
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-    usec_delay(50);
-
-    /* Clock low */
-    eecd_reg &= ~E1000_EECD_SK;
-    E1000_WRITE_REG(shared, EECD, eecd_reg);
-    usec_delay(50);
-    return;
-}
-
-
-/******************************************************************************
- * Forces the MAC's flow control settings.
- * 
- * shared - Struct containing variables accessed by shared code
- *
- * Sets the TFCE and RFCE bits in the device control register to reflect
- * the adapter settings. TFCE and RFCE need to be explicitly set by
- * software when a Copper PHY is used because autonegotiation is managed
- * by the PHY rather than the MAC. Software must also configure these
- * bits when link is forced on a fiber connection.
- *****************************************************************************/
-static void
-e1000_force_mac_fc(struct e1000_shared_adapter *shared)
-{
-    uint32_t ctrl_reg;
-
-    DEBUGFUNC("e1000_force_mac_fc");
-
-    /* Get the current configuration of the Device Control Register */
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-    /* Because we didn't get link via the internal auto-negotiation
-     * mechanism (we either forced link or we got link via PHY
-     * auto-neg), we have to manually enable/disable transmit an
-     * receive flow control.
-     *
-     * The "Case" statement below enables/disable flow control
-     * according to the "shared->fc" parameter.
-     *
-     * The possible values of the "fc" parameter are:
-     *      0:  Flow control is completely disabled
-     *      1:  Rx flow control is enabled (we can receive pause
-     *          frames but not send pause frames).
-     *      2:  Tx flow control is enabled (we can send pause frames
-     *          frames but we do not receive pause frames).
-     *      3:  Both Rx and TX flow control (symmetric) is enabled.
-     *  other:  No other values should be possible at this point.
-     */
-
-    switch (shared->fc) {
-    case e1000_fc_none:
-        ctrl_reg &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
-        break;
-    case e1000_fc_rx_pause:
-        ctrl_reg &= (~E1000_CTRL_TFCE);
-        ctrl_reg |= E1000_CTRL_RFCE;
-        break;
-    case e1000_fc_tx_pause:
-        ctrl_reg &= (~E1000_CTRL_RFCE);
-        ctrl_reg |= E1000_CTRL_TFCE;
-        break;
-    case e1000_fc_full:
-        ctrl_reg |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
-        break;
-    default:
-        DEBUGOUT("Flow control param set incorrectly\n");
-        ASSERT(0);
-        break;
-    }
-
-    /* Disable TX Flow Control for 82542 (rev 2.0) */
-    if(shared->mac_type == e1000_82542_rev2_0)
-        ctrl_reg &= (~E1000_CTRL_TFCE);
-
-
-    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-    return;
-}
-
-/******************************************************************************
- * Reset the transmit and receive units; mask and clear all interrupts.
- *
- * shared - Struct containing variables accessed by shared code
- *****************************************************************************/
-void
-e1000_adapter_stop(struct e1000_shared_adapter *shared)
-{
-    uint32_t ctrl_reg;
-    uint32_t ctrl_ext_reg;
-    uint32_t icr_reg;
-    uint16_t pci_cmd_word;
-
-    DEBUGFUNC("e1000_shared_adapter_stop");
-
-    /* If we are stopped or resetting exit gracefully and wait to be
-     * started again before accessing the hardware.
-     */
-    if(shared->adapter_stopped) {
-        DEBUGOUT("Exiting because the adapter is already stopped!!!\n");
-        return;
-    }
-
-    /* Set the Adapter Stopped flag so other driver functions stop
-     * touching the Hardware.
-     */
-    shared->adapter_stopped = TRUE;
-
-    /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
-    if(shared->mac_type == e1000_82542_rev2_0) {
-        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
-            DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
-
-            pci_cmd_word = shared->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
-
-            e1000_write_pci_cfg(shared, PCI_COMMAND_REGISTER, &pci_cmd_word);
-        }
-    }
-
-    /* Clear interrupt mask to stop board from generating interrupts */
-    DEBUGOUT("Masking off all interrupts\n");
-    E1000_WRITE_REG(shared, IMC, 0xffffffff);
-
-    /* Disable the Transmit and Receive units.  Then delay to allow
-     * any pending transactions to complete before we hit the MAC with
-     * the global reset.
-     */
-    E1000_WRITE_REG(shared, RCTL, 0);
-    E1000_WRITE_REG(shared, TCTL, E1000_TCTL_PSP);
-
-    /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
-    shared->tbi_compatibility_on = FALSE;
-
-    msec_delay(10);
-
-    /* Issue a global reset to the MAC.  This will reset the chip's
-     * transmit, receive, DMA, and link units.  It will not effect
-     * the current PCI configuration.  The global reset bit is self-
-     * clearing, and should clear within a microsecond.
-     */
-    DEBUGOUT("Issuing a global reset to MAC\n");
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-    E1000_WRITE_REG(shared, CTRL, (ctrl_reg | E1000_CTRL_RST));
-
-    /* Delay a few ms just to allow the reset to complete */
-    msec_delay(10);
-
-#if DBG
-    /* Make sure the self-clearing global reset bit did self clear */
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-    ASSERT(!(ctrl_reg & E1000_CTRL_RST));
-#endif
-
-    /* Force a reload from the EEPROM */
-    ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
-    ctrl_ext_reg |= E1000_CTRL_EXT_EE_RST;
-    E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
-    msec_delay(2);
-    
-    /* Clear interrupt mask to stop board from generating interrupts */
-    DEBUGOUT("Masking off all interrupts\n");
-    E1000_WRITE_REG(shared, IMC, 0xffffffff);
-
-    /* Clear any pending interrupt events. */
-    icr_reg = E1000_READ_REG(shared, ICR);
-
-    /* If MWI was previously enabled, reenable it. */
-    if(shared->mac_type == e1000_82542_rev2_0) {
-        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
-            e1000_write_pci_cfg(shared,
-                                PCI_COMMAND_REGISTER, &shared->pci_cmd_word);
-        }
-    }
-    return;
-}
-
-/******************************************************************************
- * Performs basic configuration of the adapter.
- *
- * shared - Struct containing variables accessed by shared code
- * 
- * Assumes that the controller has previously been reset and is in a 
- * post-reset uninitialized state. Initializes the receive address registers,
- * multicast table, and VLAN filter table. Calls routines to setup link
- * configuration and flow control settings. Clears all on-chip counters. Leaves
- * the transmit and receive units disabled and uninitialized.
- *****************************************************************************/
-boolean_t
-e1000_init_hw(struct e1000_shared_adapter *shared)
-{
-    uint32_t status_reg;
-    uint32_t i;
-    uint16_t pci_cmd_word;
-    boolean_t status;
-
-    DEBUGFUNC("e1000_init_hw");
-
-    /* Set the Media Type and exit with error if it is not valid. */
-    if(shared->mac_type != e1000_82543) {
-        /* tbi_compatibility is only valid on 82543 */
-        shared->tbi_compatibility_en = FALSE;
-    }
-
-    if(shared->mac_type >= e1000_82543) {
-        status_reg = E1000_READ_REG(shared, STATUS);
-        if(status_reg & E1000_STATUS_TBIMODE) {
-            shared->media_type = e1000_media_type_fiber;
-            /* tbi_compatibility not valid on fiber */
-            shared->tbi_compatibility_en = FALSE;
-        } else {
-            shared->media_type = e1000_media_type_copper;
-        }
-    } else {
-        /* This is an 82542 (fiber only) */
-        shared->media_type = e1000_media_type_fiber;
-    }
-
-    /* Disabling VLAN filtering. */
-    DEBUGOUT("Initializing the IEEE VLAN\n");
-    E1000_WRITE_REG(shared, VET, 0);
-
-    e1000_clear_vfta(shared);
-
-    /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
-    if(shared->mac_type == e1000_82542_rev2_0) {
-        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
-            DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
-            pci_cmd_word = shared->pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
-            e1000_write_pci_cfg(shared, PCI_COMMAND_REGISTER, &pci_cmd_word);
-        }
-        E1000_WRITE_REG(shared, RCTL, E1000_RCTL_RST);
-
-        msec_delay(5);
-    }
-
-    /* Setup the receive address. This involves initializing all of the Receive
-     * Address Registers (RARs 0 - 15).
-     */
-    e1000_init_rx_addrs(shared);
-
-    /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
-    if(shared->mac_type == e1000_82542_rev2_0) {
-        E1000_WRITE_REG(shared, RCTL, 0);
-
-        msec_delay(1);
-
-        if(shared->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) {
-            e1000_write_pci_cfg(shared,
-                                PCI_COMMAND_REGISTER, &shared->pci_cmd_word);
-        }
-    }
-
-    /* Zero out the Multicast HASH table */
-    DEBUGOUT("Zeroing the MTA\n");
-    for(i = 0; i < E1000_MC_TBL_SIZE; i++)
-        E1000_WRITE_REG_ARRAY(shared, MTA, i, 0);
-
-    /* Call a subroutine to configure the link and setup flow control. */
-    status = e1000_setup_fc_and_link(shared);
-
-    /* Clear all of the statistics registers (clear on read).  It is
-     * important that we do this after we have tried to establish link
-     * because the symbol error count will increment wildly if there
-     * is no link.
-     */
-    e1000_clear_hw_cntrs(shared);
-
-    return (status);
-}
-
-/******************************************************************************
- * Initializes receive address filters.
- *
- * shared - Struct containing variables accessed by shared code 
- *
- * Places the MAC address in receive address register 0 and clears the rest
- * of the receive addresss registers. Clears the multicast table. Assumes
- * the receiver is in reset when the routine is called.
- *****************************************************************************/
-void
-e1000_init_rx_addrs(struct e1000_shared_adapter *shared)
-{
-    uint32_t i;
-    uint32_t addr_low;
-    uint32_t addr_high;
-
-    DEBUGFUNC("e1000_init_rx_addrs");
-
-    /* Setup the receive address. */
-    DEBUGOUT("Programming MAC Address into RAR[0]\n");
-    addr_low = (shared->mac_addr[0] |
-                (shared->mac_addr[1] << 8) |
-                (shared->mac_addr[2] << 16) | (shared->mac_addr[3] << 24));
-
-    addr_high = (shared->mac_addr[4] |
-                 (shared->mac_addr[5] << 8) | E1000_RAH_AV);
-
-    E1000_WRITE_REG_ARRAY(shared, RA, 0, addr_low);
-    E1000_WRITE_REG_ARRAY(shared, RA, 1, addr_high);
-
-    /* Zero out the other 15 receive addresses. */
-    DEBUGOUT("Clearing RAR[1-15]\n");
-    for(i = 1; i < E1000_RAR_ENTRIES; i++) {
-        E1000_WRITE_REG_ARRAY(shared, RA, (i << 1), 0);
-        E1000_WRITE_REG_ARRAY(shared, RA, ((i << 1) + 1), 0);
-    }
-
-    return;
-}
-
-/******************************************************************************
- * Updates the MAC's list of multicast addresses.
- *
- * shared - Struct containing variables accessed by shared code
- * mc_addr_list - the list of new multicast addresses
- * mc_addr_count - number of addresses
- * pad - number of bytes between addresses in the list
- *
- * The given list replaces any existing list. Clears the last 15 receive
- * address registers and the multicast table. Uses receive address registers
- * for the first 15 multicast addresses, and hashes the rest into the 
- * multicast table.
- *****************************************************************************/
-void
-e1000_mc_addr_list_update(struct e1000_shared_adapter *shared,
-                          uint8_t *mc_addr_list,
-                          uint32_t mc_addr_count,
-                          uint32_t pad)
-{
-    uint32_t hash_value;
-    uint32_t i;
-    uint32_t rar_used_count = 1;        /* RAR[0] is used for our MAC address */
-
-    DEBUGFUNC("e1000_mc_addr_list_update");
-
-    /* Set the new number of MC addresses that we are being requested to use. */
-    shared->num_mc_addrs = mc_addr_count;
-
-    /* Clear RAR[1-15] */
-    DEBUGOUT(" Clearing RAR[1-15]\n");
-    for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) {
-        E1000_WRITE_REG_ARRAY(shared, RA, (i << 1), 0);
-        E1000_WRITE_REG_ARRAY(shared, RA, ((i << 1) + 1), 0);
-    }
-
-    /* Clear the MTA */
-    DEBUGOUT(" Clearing MTA\n");
-    for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) {
-        E1000_WRITE_REG_ARRAY(shared, MTA, i, 0);
-    }
-
-    /* Add the new addresses */
-    for(i = 0; i < mc_addr_count; i++) {
-        DEBUGOUT(" Adding the multicast addresses:\n");
-        DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
-                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad)],
-                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 1],
-                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 2],
-                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 3],
-                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 4],
-                  mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad) + 5]);
-
-        hash_value = e1000_hash_mc_addr(shared,
-                                        mc_addr_list +
-                                        (i * (ETH_LENGTH_OF_ADDRESS + pad)));
-
-        DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
-
-        /* Place this multicast address in the RAR if there is room, *
-         * else put it in the MTA            
-         */
-        if(rar_used_count < E1000_RAR_ENTRIES) {
-            e1000_rar_set(shared,
-                          mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)),
-                          rar_used_count);
-            rar_used_count++;
-        } else {
-            e1000_mta_set(shared, hash_value);
-        }
-    }
-
-    DEBUGOUT("MC Update Complete\n");
-    return;
-}
-
-/******************************************************************************
- * Hashes an address to determine its location in the multicast table
- *
- * shared - Struct containing variables accessed by shared code
- * mc_addr - the multicast address to hash 
- *****************************************************************************/
-uint32_t
-e1000_hash_mc_addr(struct e1000_shared_adapter *shared,
-                   uint8_t *mc_addr)
-{
-    uint32_t hash_value = 0;
-
-    /* The portion of the address that is used for the hash table is
-     * determined by the mc_filter_type setting.  
-     */
-    switch (shared->mc_filter_type) {
-        /* [0] [1] [2] [3] [4] [5]
-            * 01  AA  00  12  34  56
-            * LSB                 MSB - According to H/W docs */
-    case 0:
-        /* [47:36] i.e. 0x563 for above example address */
-        hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4));
-        break;
-    case 1:                   /* [46:35] i.e. 0xAC6 for above example address */
-        hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5));
-        break;
-    case 2:                   /* [45:34] i.e. 0x5D8 for above example address */
-        hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6));
-        break;
-    case 3:                   /* [43:32] i.e. 0x634 for above example address */
-        hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8));
-        break;
-    }
-
-    hash_value &= 0xFFF;
-    return (hash_value);
-}
-
-/******************************************************************************
- * Sets the bit in the multicast table corresponding to the hash value.
- *
- * shared - Struct containing variables accessed by shared code
- * hash_value - Multicast address hash value
- *****************************************************************************/
-void
-e1000_mta_set(struct e1000_shared_adapter *shared,
-              uint32_t hash_value)
-{
-    uint32_t hash_bit, hash_reg;
-    uint32_t mta_reg;
-    uint32_t temp;
-
-    /* The MTA is a register array of 128 32-bit registers.  
-     * It is treated like an array of 4096 bits.  We want to set 
-     * bit BitArray[hash_value]. So we figure out what register
-     * the bit is in, read it, OR in the new bit, then write
-     * back the new value.  The register is determined by the 
-     * upper 7 bits of the hash value and the bit within that 
-     * register are determined by the lower 5 bits of the value.
-     */
-    hash_reg = (hash_value >> 5) & 0x7F;
-    hash_bit = hash_value & 0x1F;
-
-    mta_reg = E1000_READ_REG_ARRAY(shared, MTA, hash_reg);
-
-    mta_reg |= (1 << hash_bit);
-
-    /* If we are on an 82544 and we are trying to write an odd offset
-     * in the MTA, save off the previous entry before writing and
-     * restore the old value after writing.
-     */
-    if((shared->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
-        temp = E1000_READ_REG_ARRAY(shared, MTA, (hash_reg - 1));
-        E1000_WRITE_REG_ARRAY(shared, MTA, hash_reg, mta_reg);
-        E1000_WRITE_REG_ARRAY(shared, MTA, (hash_reg - 1), temp);
-    } else {
-        E1000_WRITE_REG_ARRAY(shared, MTA, hash_reg, mta_reg);
-    }
-    return;
-}
-
-/******************************************************************************
- * Puts an ethernet address into a receive address register.
- *
- * shared - Struct containing variables accessed by shared code
- * addr - Address to put into receive address register
- * index - Receive address register to write
- *****************************************************************************/
-void
-e1000_rar_set(struct e1000_shared_adapter *shared,
-              uint8_t *addr,
-              uint32_t index)
-{
-    uint32_t rar_low, rar_high;
-
-    /* HW expects these in little endian so we reverse the byte order
-     * from network order (big endian) to little endian              
-     */
-    rar_low = ((uint32_t) addr[0] |
-               ((uint32_t) addr[1] << 8) |
-               ((uint32_t) addr[2] << 16) | ((uint32_t) addr[3] << 24));
-
-    rar_high = ((uint32_t) addr[4] | ((uint32_t) addr[5] << 8) | E1000_RAH_AV);
-
-    E1000_WRITE_REG_ARRAY(shared, RA, (index << 1), rar_low);
-    E1000_WRITE_REG_ARRAY(shared, RA, ((index << 1) + 1), rar_high);
-    return;
-}
-
-/******************************************************************************
- * Writes a value to the specified offset in the VLAN filter table.
- *
- * shared - Struct containing variables accessed by shared code
- * offset - Offset in VLAN filer table to write
- * value - Value to write into VLAN filter table
- *****************************************************************************/
-void
-e1000_write_vfta(struct e1000_shared_adapter *shared,
-                 uint32_t offset,
-                 uint32_t value)
-{
-    uint32_t temp;
-
-    if((shared->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
-        temp = E1000_READ_REG_ARRAY(shared, VFTA, (offset - 1));
-        E1000_WRITE_REG_ARRAY(shared, VFTA, offset, value);
-        E1000_WRITE_REG_ARRAY(shared, VFTA, (offset - 1), temp);
-    } else {
-        E1000_WRITE_REG_ARRAY(shared, VFTA, offset, value);
-    }
-    return;
-}
-
-/******************************************************************************
- * Clears the VLAN filer table
- *
- * shared - Struct containing variables accessed by shared code
- *****************************************************************************/
-void
-e1000_clear_vfta(struct e1000_shared_adapter *shared)
-{
-    uint32_t offset;
-
-    for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
-        E1000_WRITE_REG_ARRAY(shared, VFTA, offset, 0);
-    return;
-}
-
-/******************************************************************************
- * Configures flow control and link settings.
- * 
- * shared - Struct containing variables accessed by shared code
- * 
- * Determines which flow control settings to use. Calls the apropriate media-
- * specific link configuration function. Configures the flow control settings.
- * Assuming the adapter has a valid link partner, a valid link should be
- * established. Assumes the hardware has previously been reset and the 
- * transmitter and receiver are not enabled.
- *****************************************************************************/
-boolean_t
-e1000_setup_fc_and_link(struct e1000_shared_adapter *shared)
-{
-    uint32_t ctrl_reg;
-    uint32_t eecd_reg;
-    uint32_t ctrl_ext_reg;
-    boolean_t status = TRUE;
-
-    DEBUGFUNC("e1000_setup_fc_and_link");
-
-    /* Read the SWDPIO bits and the ILOS bit out of word 0x0A in the
-     * EEPROM.  Store these bits in a variable that we will later write
-     * to the Device Control Register (CTRL).
-     */
-    eecd_reg = e1000_read_eeprom(shared, EEPROM_INIT_CONTROL1_REG);
-
-    ctrl_reg =
-        (((eecd_reg & EEPROM_WORD0A_SWDPIO) << SWDPIO_SHIFT) |
-         ((eecd_reg & EEPROM_WORD0A_ILOS) << ILOS_SHIFT));
-
-    /* Set the PCI priority bit correctly in the CTRL register.  This
-     * determines if the adapter gives priority to receives, or if it
-     * gives equal priority to transmits and receives.
-     */
-    if(shared->dma_fairness)
-        ctrl_reg |= E1000_CTRL_PRIOR;
-
-    /* Read and store word 0x0F of the EEPROM. This word contains bits
-     * that determine the hardware's default PAUSE (flow control) mode,
-     * a bit that determines whether the HW defaults to enabling or
-     * disabling auto-negotiation, and the direction of the
-     * SW defined pins. If there is no SW over-ride of the flow
-     * control setting, then the variable shared->fc will
-     * be initialized based on a value in the EEPROM.
-     */
-    eecd_reg = e1000_read_eeprom(shared, EEPROM_INIT_CONTROL2_REG);
-
-    if(shared->fc > e1000_fc_full) {
-        if((eecd_reg & EEPROM_WORD0F_PAUSE_MASK) == 0)
-            shared->fc = e1000_fc_none;
-        else if((eecd_reg & EEPROM_WORD0F_PAUSE_MASK) == EEPROM_WORD0F_ASM_DIR)
-            shared->fc = e1000_fc_tx_pause;
-        else
-            shared->fc = e1000_fc_full;
-    }
-
-    /* We want to save off the original Flow Control configuration just
-     * in case we get disconnected and then reconnected into a different
-     * hub or switch with different Flow Control capabilities.
-     */
-    shared->original_fc = shared->fc;
-
-    if(shared->mac_type == e1000_82542_rev2_0)
-        shared->fc &= (~e1000_fc_tx_pause);
-
-    if((shared->mac_type < e1000_82543) && (shared->report_tx_early == 1))
-        shared->fc &= (~e1000_fc_rx_pause);
-
-    DEBUGOUT1("After fix-ups FlowControl is now = %x\n", shared->fc);
-
-    /* Take the 4 bits from EEPROM word 0x0F that determine the initial
-     * polarity value for the SW controlled pins, and setup the
-     * Extended Device Control reg with that info.
-     * This is needed because one of the SW controlled pins is used for
-     * signal detection.  So this should be done before e1000_setup_pcs_link()
-     * or e1000_phy_setup() is called.
-     */
-    if(shared->mac_type == e1000_82543) {
-        ctrl_ext_reg = ((eecd_reg & EEPROM_WORD0F_SWPDIO_EXT)
-                        << SWDPIO__EXT_SHIFT);
-        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
-    }
-
-    /* Call the necessary subroutine to configure the link. */
-    if(shared->media_type == e1000_media_type_fiber)
-        status = e1000_setup_pcs_link(shared, ctrl_reg);
-    else
-        status = e1000_phy_setup(shared, ctrl_reg);
-
-    /* Initialize the flow control address, type, and PAUSE timer
-     * registers to their default values.  This is done even if flow
-     * control is disabled, because it does not hurt anything to
-     * initialize these registers.
-     */
-    DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
-
-    E1000_WRITE_REG(shared, FCAL, FLOW_CONTROL_ADDRESS_LOW);
-    E1000_WRITE_REG(shared, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
-    E1000_WRITE_REG(shared, FCT, FLOW_CONTROL_TYPE);
-    E1000_WRITE_REG(shared, FCTTV, shared->fc_pause_time);
-
-    /* Set the flow control receive threshold registers.  Normally,
-     * these registers will be set to a default threshold that may be
-     * adjusted later by the driver's runtime code.  However, if the
-     * ability to transmit pause frames in not enabled, then these
-     * registers will be set to 0. 
-     */
-    if(!(shared->fc & e1000_fc_tx_pause)) {
-        E1000_WRITE_REG(shared, FCRTL, 0);
-        E1000_WRITE_REG(shared, FCRTH, 0);
-    } else {
-        /* We need to set up the Receive Threshold high and low water marks
-         * as well as (optionally) enabling the transmission of XON frames.
-         */
-        if(shared->fc_send_xon) {
-            E1000_WRITE_REG(shared, FCRTL,
-                            (shared->fc_low_water | E1000_FCRTL_XONE));
-            E1000_WRITE_REG(shared, FCRTH, shared->fc_high_water);
-        } else {
-            E1000_WRITE_REG(shared, FCRTL, shared->fc_low_water);
-            E1000_WRITE_REG(shared, FCRTH, shared->fc_high_water);
-        }
-    }
-    return (status);
-}
-
-/******************************************************************************
- * Sets up link for a fiber based adapter
- *
- * shared - Struct containing variables accessed by shared code
- * ctrl_reg - Current value of the device control register
- *
- * Manipulates Physical Coding Sublayer functions in order to configure
- * link. Assumes the hardware has been previously reset and the transmitter
- * and receiver are not enabled.
- *****************************************************************************/
-boolean_t
-e1000_setup_pcs_link(struct e1000_shared_adapter *shared,
-                     uint32_t ctrl_reg)
-{
-    uint32_t status_reg;
-    uint32_t tctl_reg;
-    uint32_t txcw_reg = 0;
-    uint32_t i;
-
-    DEBUGFUNC("e1000_setup_pcs_link");
-
-    /* Setup the collsion distance.  Since this is configuring the
-     * TBI it is assumed that we are in Full Duplex.
-     */
-    tctl_reg = E1000_READ_REG(shared, TCTL);
-    i = E1000_FDX_COLLISION_DISTANCE;
-    i <<= E1000_COLD_SHIFT;
-    tctl_reg |= i;
-    E1000_WRITE_REG(shared, TCTL, tctl_reg);
-
-    /* Check for a software override of the flow control settings, and
-     * setup the device accordingly.  If auto-negotiation is enabled,
-     * then software will have to set the "PAUSE" bits to the correct
-     * value in the Tranmsit Config Word Register (TXCW) and re-start
-     * auto-negotiation.  However, if auto-negotiation is disabled,
-     * then software will have to manually configure the two flow
-     * control enable bits in the CTRL register.
-     *
-     * The possible values of the "fc" parameter are:
-     *      0:  Flow control is completely disabled
-     *      1:  Rx flow control is enabled (we can receive pause frames
-     *          but not send pause frames).
-     *      2:  Tx flow control is enabled (we can send pause frames
-     *          but we do not support receiving pause frames).
-     *      3:  Both Rx and TX flow control (symmetric) are enabled.
-     *  other:  No software override.  The flow control configuration
-     *          in the EEPROM is used.
-     */
-    switch (shared->fc) {
-    case e1000_fc_none:        /* 0 */
-        /* Flow control (RX & TX) is completely disabled by a
-         * software over-ride.
-         */
-        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD);
-        break;
-    case e1000_fc_rx_pause:    /* 1 */
-        /* RX Flow control is enabled, and TX Flow control is
-         * disabled, by a software over-ride.
-         */
-        /* Since there really isn't a way to advertise that we are
-         * capable of RX Pause ONLY, we will advertise that we
-         * support both symmetric and asymmetric RX PAUSE.  Later
-         * we will disable the adapter's ability to send PAUSE
-         * frames.
-         */
-        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-        break;
-    case e1000_fc_tx_pause:    /* 2 */
-        /* TX Flow control is enabled, and RX Flow control is
-         * disabled, by a software over-ride.
-         */
-        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
-        break;
-    case e1000_fc_full:        /* 3 */
-        /* Flow control (both RX and TX) is enabled by a software
-         * over-ride.
-         */
-        txcw_reg = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
-        break;
-    default:
-        /* We should never get here.  The value should be 0-3. */
-        DEBUGOUT("Flow control param set incorrectly\n");
-        ASSERT(0);
-        break;
-    }
-
-    /* Since auto-negotiation is enabled, take the link out of reset.
-     * (the link will be in reset, because we previously reset the
-     * chip). This will restart auto-negotiation.  If auto-neogtiation
-     * is successful then the link-up status bit will be set and the
-     * flow control enable bits (RFCE and TFCE) will be set according
-     * to their negotiated value.
-     */
-    DEBUGOUT("Auto-negotiation enabled\n");
-
-    E1000_WRITE_REG(shared, TXCW, txcw_reg);
-    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-    shared->txcw_reg = txcw_reg;
-    msec_delay(1);
-
-    /* If we have a signal then poll for a "Link-Up" indication in the
-     * Device Status Register.   Time-out if a link isn't seen in 500
-     * milliseconds seconds (Auto-negotiation should complete in less
-     * than 500 milliseconds even if the other end is doing it in SW).
-     */
-    if(!(E1000_READ_REG(shared, CTRL) & E1000_CTRL_SWDPIN1)) {
-
-        DEBUGOUT("Looking for Link\n");
-        for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
-            msec_delay(10);
-            status_reg = E1000_READ_REG(shared, STATUS);
-            if(status_reg & E1000_STATUS_LU)
-                break;
-        }
-
-        if(i == (LINK_UP_TIMEOUT / 10)) {
-            /* AutoNeg failed to achieve a link, so we'll call the
-             * "CheckForLink" routine.  This routine will force the link
-             * up if we have "signal-detect".  This will allow us to
-             * communicate with non-autonegotiating link partners.
-             */
-            DEBUGOUT("Never got a valid link from auto-neg!!!\n");
-
-            shared->autoneg_failed = 1;
-            e1000_check_for_link(shared);
-            shared->autoneg_failed = 0;
-        } else {
-            shared->autoneg_failed = 0;
-            DEBUGOUT("Valid Link Found\n");
-        }
-    } else {
-        DEBUGOUT("No Signal Detected\n");
-    }
-
-    return (TRUE);
-}
-
-/******************************************************************************
- * Configures flow control settings after link is established
- * 
- * shared - Struct containing variables accessed by shared code
- *
- * Should be called immediately after a valid link has been established.
- * Forces MAC flow control settings if link was forced. When in MII/GMII mode
- * and autonegotiation is enabled, the MAC flow control settings will be set
- * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
- * and RFCE bits will be automaticaly set to the negotiated flow control mode.
- *****************************************************************************/
-void
-e1000_config_fc_after_link_up(struct e1000_shared_adapter *shared)
-{
-    uint16_t mii_status_reg;
-    uint16_t mii_nway_adv_reg;
-    uint16_t mii_nway_lp_ability_reg;
-    uint16_t speed;
-    uint16_t duplex;
-
-    DEBUGFUNC("e1000_config_fc_after_link_up");
-
-    /* Check for the case where we have fiber media and auto-neg failed
-     * so we had to force link.  In this case, we need to force the
-     * configuration of the MAC to match the "fc" parameter.
-     */
-    if(((shared->media_type == e1000_media_type_fiber)
-        && (shared->autoneg_failed))
-       || ((shared->media_type == e1000_media_type_copper)
-           && (!shared->autoneg))) {
-        e1000_force_mac_fc(shared);
-    }
-
-    /* Check for the case where we have copper media and auto-neg is
-     * enabled.  In this case, we need to check and see if Auto-Neg
-     * has completed, and if so, how the PHY and link partner has
-     * flow control configured.
-     */
-    if((shared->media_type == e1000_media_type_copper) && shared->autoneg) {
-        /* Read the MII Status Register and check to see if AutoNeg
-         * has completed.  We read this twice because this reg has
-         * some "sticky" (latched) bits.
-         */
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-
-        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
-            /* The AutoNeg process has completed, so we now need to
-             * read both the Auto Negotiation Advertisement Register
-             * (Address 4) and the Auto_Negotiation Base Page Ability
-             * Register (Address 5) to determine how flow control was
-             * negotiated.
-             */
-            mii_nway_adv_reg = e1000_read_phy_reg(shared,
-                                                  PHY_AUTONEG_ADV);
-            mii_nway_lp_ability_reg = e1000_read_phy_reg(shared,
-                                                         PHY_LP_ABILITY);
-
-            /* Two bits in the Auto Negotiation Advertisement Register
-             * (Address 4) and two bits in the Auto Negotiation Base
-             * Page Ability Register (Address 5) determine flow control
-             * for both the PHY and the link partner.  The following
-             * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
-             * 1999, describes these PAUSE resolution bits and how flow
-             * control is determined based upon these settings.
-             * NOTE:  DC = Don't Care
-             *
-             *   LOCAL DEVICE  |   LINK PARTNER
-             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
-             *-------|---------|-------|---------|--------------------
-             *   0   |    0    |  DC   |   DC    | e1000_fc_none
-             *   0   |    1    |   0   |   DC    | e1000_fc_none
-             *   0   |    1    |   1   |    0    | e1000_fc_none
-             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
-             *   1   |    0    |   0   |   DC    | e1000_fc_none
-             *   1   |   DC    |   1   |   DC    | e1000_fc_full
-             *   1   |    1    |   0   |    0    | e1000_fc_none
-             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
-             *
-             */
-            /* Are both PAUSE bits set to 1?  If so, this implies
-             * Symmetric Flow Control is enabled at both ends.  The
-             * ASM_DIR bits are irrelevant per the spec.
-             *
-             * For Symmetric Flow Control:
-             *
-             *   LOCAL DEVICE  |   LINK PARTNER
-             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-             *-------|---------|-------|---------|--------------------
-             *   1   |   DC    |   1   |   DC    | e1000_fc_full
-             *
-             */
-            if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-               (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
-                /* Now we need to check if the user selected RX ONLY
-                 * of pause frames.  In this case, we had to advertise
-                 * FULL flow control because we could not advertise RX
-                 * ONLY. Hence, we must now check to see if we need to
-                 * turn OFF  the TRANSMISSION of PAUSE frames.
-                 */
-                if(shared->original_fc == e1000_fc_full) {
-                    shared->fc = e1000_fc_full;
-                    DEBUGOUT("Flow Control = FULL.\r\n");
-                } else {
-                    shared->fc = e1000_fc_rx_pause;
-                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
-                }
-            }
-            /* For receiving PAUSE frames ONLY.
-             *
-             *   LOCAL DEVICE  |   LINK PARTNER
-             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-             *-------|---------|-------|---------|--------------------
-             *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
-             *
-             */
-            else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-                    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
-                shared->fc = e1000_fc_tx_pause;
-                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
-            }
-            /* For transmitting PAUSE frames ONLY.
-             *
-             *   LOCAL DEVICE  |   LINK PARTNER
-             * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
-             *-------|---------|-------|---------|--------------------
-             *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
-             *
-             */
-            else if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-                    !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
-                shared->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
-            }
-            /* Per the IEEE spec, at this point flow control should be
-             * disabled.  However, we want to consider that we could
-             * be connected to a legacy switch that doesn't advertise
-             * desired flow control, but can be forced on the link
-             * partner.  So if we advertised no flow control, that is
-             * what we will resolve to.  If we advertised some kind of
-             * receive capability (Rx Pause Only or Full Flow Control)
-             * and the link partner advertised none, we will configure
-             * ourselves to enable Rx Flow Control only.  We can do
-             * this safely for two reasons:  If the link partner really
-             * didn't want flow control enabled, and we enable Rx, no
-             * harm done since we won't be receiving any PAUSE frames
-             * anyway.  If the intent on the link partner was to have
-             * flow control enabled, then by us enabling RX only, we
-             * can at least receive pause frames and process them.
-             * This is a good idea because in most cases, since we are
-             * predominantly a server NIC, more times than not we will
-             * be asked to delay transmission of packets than asking
-             * our link partner to pause transmission of frames.
-             */
-            else if(shared->original_fc == e1000_fc_none ||
-                    shared->original_fc == e1000_fc_tx_pause) {
-                shared->fc = e1000_fc_none;
-                DEBUGOUT("Flow Control = NONE.\r\n");
-            } else {
-                shared->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
-            }
-
-            /* Now we need to do one last check...  If we auto-
-             * negotiated to HALF DUPLEX, flow control should not be
-             * enabled per IEEE 802.3 spec.
-             */
-            e1000_get_speed_and_duplex(shared, &speed, &duplex);
-
-            if(duplex == HALF_DUPLEX)
-                shared->fc = e1000_fc_none;
-
-            /* Now we call a subroutine to actually force the MAC
-             * controller to use the correct flow control settings.
-             */
-            e1000_force_mac_fc(shared);
-        } else {
-            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
-        }
-    }
-    return;  
-}
-
-/******************************************************************************
- * Checks to see if the link status of the hardware has changed.
- *
- * shared - Struct containing variables accessed by shared code
- *
- * Called by any function that needs to check the link status of the adapter.
- *****************************************************************************/
-void
-e1000_check_for_link(struct e1000_shared_adapter *shared)
-{
-    uint32_t rxcw_reg;
-    uint32_t ctrl_reg;
-    uint32_t status_reg;
-    uint32_t rctl_reg;
-    uint16_t phy_data;
-    uint16_t lp_capability;
-
-    DEBUGFUNC("e1000_check_for_link");
-
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-    status_reg = E1000_READ_REG(shared, STATUS);
-    rxcw_reg = E1000_READ_REG(shared, RXCW);
-
-    /* If we have a copper PHY then we only want to go out to the PHY
-     * registers to see if Auto-Neg has completed and/or if our link
-     * status has changed.  The get_link_status flag will be set if we
-     * receive a Link Status Change interrupt or we have Rx Sequence
-     * Errors.
-     */
-    if(shared->media_type == e1000_media_type_copper
-       && shared->get_link_status) {
-        /* First we want to see if the MII Status Register reports
-         * link.  If so, then we want to get the current speed/duplex
-         * of the PHY.
-         * Read the register twice since the link bit is sticky.
-         */
-        phy_data = e1000_read_phy_reg(shared, PHY_STATUS);
-        phy_data = e1000_read_phy_reg(shared, PHY_STATUS);
-
-        if(phy_data & MII_SR_LINK_STATUS) {
-            shared->get_link_status = FALSE;
-        } else {
-            DEBUGOUT("**** CFL - No link detected. ****\r\n");
-            return;
-        }
-
-        /* If we are forcing speed/duplex, then we simply return since
-         * we have already determined whether we have link or not.
-         */
-        if(!shared->autoneg) {
-            return;
-        }
-
-        switch (shared->phy_id) {
-        case M88E1000_12_PHY_ID:
-        case M88E1000_14_PHY_ID:
-        case M88E1000_I_PHY_ID:
-            /* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
-             * have Si on board that is 82544 or newer, Auto
-             * Speed Detection takes care of MAC speed/duplex
-             * configuration.  So we only need to configure Collision
-             * Distance in the MAC.  Otherwise, we need to force
-             * speed/duplex on the MAC to the current PHY speed/duplex
-             * settings.
-             */
-            if(shared->mac_type >= e1000_82544) {
-                DEBUGOUT("CFL - Auto-Neg complete.");
-                DEBUGOUT("Configuring Collision Distance.");
-                e1000_config_collision_dist(shared);
-            } else {
-                /* Read the Phy Specific Status register to get the
-                 * resolved speed/duplex settings.  Then call
-                 * e1000_config_mac_to_phy which will retrieve
-                 * PHY register information and configure the MAC to
-                 * equal the negotiated speed/duplex.
-                 */
-                phy_data = e1000_read_phy_reg(shared, 
-                                              M88E1000_PHY_SPEC_STATUS);
-
-                DEBUGOUT1("CFL - Auto-Neg complete.  phy_data = %x\r\n",
-                          phy_data);
-                e1000_config_mac_to_phy(shared, phy_data);
-            }
-
-            /* Configure Flow Control now that Auto-Neg has completed.
-             * We need to first restore the users desired Flow
-             * Control setting since we may have had to re-autoneg
-             * with a different link partner.
-             */
-            e1000_config_fc_after_link_up(shared);
-            break;
-
-        default:
-            DEBUGOUT("CFL - Invalid PHY detected.\r\n");
-
-        } /* end switch statement */
-
-        /* At this point we know that we are on copper, link is up, 
-         * and we are auto-neg'd.  These are pre-conditions for checking
-         * the link parter capabilities register.  We use the link partner
-         * capabilities to determine if TBI Compatibility needs to be turned on
-         * or turned off.  If the link partner advertises any speed in addition
-         * to Gigabit, then we assume that they are GMII-based and TBI 
-         * compatibility is not needed.
-         * If no other speeds are advertised, then we assume the link partner
-         * is TBI-based and we turn on TBI Compatibility.
-         */
-        if(shared->tbi_compatibility_en) {
-            lp_capability = e1000_read_phy_reg(shared, PHY_LP_ABILITY);
-            if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
-                                NWAY_LPAR_10T_FD_CAPS |
-                                NWAY_LPAR_100TX_HD_CAPS |
-                                NWAY_LPAR_100TX_FD_CAPS |
-                                NWAY_LPAR_100T4_CAPS)) {
-                /* If our link partner advertises below Gig, then they do not
-                 * need the special Tbi Compatibility mode. 
-                 */
-                if(shared->tbi_compatibility_on) {
-                    /* If we previously were in the mode, turn it off, now. */
-                    rctl_reg = E1000_READ_REG(shared, RCTL);
-                    rctl_reg &= ~E1000_RCTL_SBP;
-                    E1000_WRITE_REG(shared, RCTL, rctl_reg);
-                    shared->tbi_compatibility_on = FALSE;
-                }
-            } else {
-                /* If the mode is was previously off, turn it on. 
-                 * For compatibility with a suspected Tbi link partners, 
-                 * we will store bad packets.
-                 * (Certain frames have an additional byte on the end and will 
-                 * look like CRC errors to to the hardware).
-                 */
-                if(!shared->tbi_compatibility_on) {
-                    shared->tbi_compatibility_on = TRUE;
-                    rctl_reg = E1000_READ_REG(shared, RCTL);
-                    rctl_reg |= E1000_RCTL_SBP;
-                    E1000_WRITE_REG(shared, RCTL, rctl_reg);
-                }
-            }
-        }
-    } /* end if e1000_media_type_copper statement */
-    /* If we don't have link (auto-negotiation failed or link partner
-     * cannot auto-negotiate) and the cable is plugged in since we don't
-     * have Loss-Of-Signal (we HAVE a signal) and our link partner is
-     * not trying to AutoNeg with us (we are receiving idles/data
-     * then we need to force our link to connect to a non
-     * auto-negotiating link partner.  We also need to give
-     * auto-negotiation time to complete in case the cable was just
-     * plugged in.  The autoneg_failed flag does this.
-     */
-    else if((shared->media_type == e1000_media_type_fiber) &&  /* Fiber PHY */
-            (!(status_reg & E1000_STATUS_LU)) &&        /* no link and    */
-            (!(ctrl_reg & E1000_CTRL_SWDPIN1)) &&       /* we have signal */
-            (!(rxcw_reg & E1000_RXCW_C))) {     /* and rxing idle/data */
-        if(shared->autoneg_failed == 0) {      /* given AutoNeg time */
-            shared->autoneg_failed = 1;
-            return;
-        }
-
-        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
-
-        /* Disable auto-negotiation in the TXCW register */
-        E1000_WRITE_REG(shared, TXCW, (shared->txcw_reg & ~E1000_TXCW_ANE));
-
-        /* Force link-up and also force full-duplex. */
-        ctrl_reg = E1000_READ_REG(shared, CTRL);
-        ctrl_reg |= (E1000_CTRL_SLU | E1000_CTRL_FD);
-        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-        /* Configure Flow Control after forcing link up. */
-        e1000_config_fc_after_link_up(shared);
-
-    } else if((shared->media_type == e1000_media_type_fiber) && /* Fiber */
-              (ctrl_reg & E1000_CTRL_SLU) &&    /* we have forced link */
-              (rxcw_reg & E1000_RXCW_C)) {      /* and Rxing /C/ ordered sets */
-        /* If we are forcing link and we are receiving /C/ ordered sets,
-         * then re-enable auto-negotiation in the RXCW register and
-         * disable forced link in the Device Control register in an attempt
-         * to AutoNeg with our link partner.
-         */
-        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
-
-        /* Enable auto-negotiation in the TXCW register and stop
-         * forcing link.
-         */
-        E1000_WRITE_REG(shared, TXCW, shared->txcw_reg);
-
-        E1000_WRITE_REG(shared, CTRL, (ctrl_reg & ~E1000_CTRL_SLU));
-    }
-
-    return;
-}
-
-/******************************************************************************
- * Clears all hardware statistics counters. 
- *
- * shared - Struct containing variables accessed by shared code
- *****************************************************************************/
-void
-e1000_clear_hw_cntrs(struct e1000_shared_adapter *shared)
-{
-    volatile uint32_t temp_reg;
-
-    DEBUGFUNC("e1000_clear_hw_cntrs");
-
-    /* if we are stopped or resetting exit gracefully */
-    if(shared->adapter_stopped) {
-        DEBUGOUT("Exiting because the adapter is stopped!!!\n");
-        return;
-    }
-
-    temp_reg = E1000_READ_REG(shared, CRCERRS);
-    temp_reg = E1000_READ_REG(shared, SYMERRS);
-    temp_reg = E1000_READ_REG(shared, MPC);
-    temp_reg = E1000_READ_REG(shared, SCC);
-    temp_reg = E1000_READ_REG(shared, ECOL);
-    temp_reg = E1000_READ_REG(shared, MCC);
-    temp_reg = E1000_READ_REG(shared, LATECOL);
-    temp_reg = E1000_READ_REG(shared, COLC);
-    temp_reg = E1000_READ_REG(shared, DC);
-    temp_reg = E1000_READ_REG(shared, SEC);
-    temp_reg = E1000_READ_REG(shared, RLEC);
-    temp_reg = E1000_READ_REG(shared, XONRXC);
-    temp_reg = E1000_READ_REG(shared, XONTXC);
-    temp_reg = E1000_READ_REG(shared, XOFFRXC);
-    temp_reg = E1000_READ_REG(shared, XOFFTXC);
-    temp_reg = E1000_READ_REG(shared, FCRUC);
-    temp_reg = E1000_READ_REG(shared, PRC64);
-    temp_reg = E1000_READ_REG(shared, PRC127);
-    temp_reg = E1000_READ_REG(shared, PRC255);
-    temp_reg = E1000_READ_REG(shared, PRC511);
-    temp_reg = E1000_READ_REG(shared, PRC1023);
-    temp_reg = E1000_READ_REG(shared, PRC1522);
-    temp_reg = E1000_READ_REG(shared, GPRC);
-    temp_reg = E1000_READ_REG(shared, BPRC);
-    temp_reg = E1000_READ_REG(shared, MPRC);
-    temp_reg = E1000_READ_REG(shared, GPTC);
-    temp_reg = E1000_READ_REG(shared, GORCL);
-    temp_reg = E1000_READ_REG(shared, GORCH);
-    temp_reg = E1000_READ_REG(shared, GOTCL);
-    temp_reg = E1000_READ_REG(shared, GOTCH);
-    temp_reg = E1000_READ_REG(shared, RNBC);
-    temp_reg = E1000_READ_REG(shared, RUC);
-    temp_reg = E1000_READ_REG(shared, RFC);
-    temp_reg = E1000_READ_REG(shared, ROC);
-    temp_reg = E1000_READ_REG(shared, RJC);
-    temp_reg = E1000_READ_REG(shared, TORL);
-    temp_reg = E1000_READ_REG(shared, TORH);
-    temp_reg = E1000_READ_REG(shared, TOTL);
-    temp_reg = E1000_READ_REG(shared, TOTH);
-    temp_reg = E1000_READ_REG(shared, TPR);
-    temp_reg = E1000_READ_REG(shared, TPT);
-    temp_reg = E1000_READ_REG(shared, PTC64);
-    temp_reg = E1000_READ_REG(shared, PTC127);
-    temp_reg = E1000_READ_REG(shared, PTC255);
-    temp_reg = E1000_READ_REG(shared, PTC511);
-    temp_reg = E1000_READ_REG(shared, PTC1023);
-    temp_reg = E1000_READ_REG(shared, PTC1522);
-    temp_reg = E1000_READ_REG(shared, MPTC);
-    temp_reg = E1000_READ_REG(shared, BPTC);
-
-    if(shared->mac_type < e1000_82543)
-        return;
-
-    temp_reg = E1000_READ_REG(shared, ALGNERRC);
-    temp_reg = E1000_READ_REG(shared, RXERRC);
-    temp_reg = E1000_READ_REG(shared, TNCRS);
-    temp_reg = E1000_READ_REG(shared, CEXTERR);
-    temp_reg = E1000_READ_REG(shared, TSCTC);
-    temp_reg = E1000_READ_REG(shared, TSCTFC);
-    return;
-}
-
-/******************************************************************************
- * Detects the current speed and duplex settings of the hardware.
- *
- * shared - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- *****************************************************************************/
-void
-e1000_get_speed_and_duplex(struct e1000_shared_adapter *shared,
-                           uint16_t *speed,
-                           uint16_t *duplex)
-{
-    uint32_t status_reg;
-#if DBG
-    uint16_t phy_data;
-#endif
-
-    DEBUGFUNC("e1000_get_speed_and_duplex");
-
-    /* If the adapter is stopped we don't have a speed or duplex */
-    if(shared->adapter_stopped) {
-        *speed = 0;
-        *duplex = 0;
-        return;
-    }
-
-    if(shared->mac_type >= e1000_82543) {
-        status_reg = E1000_READ_REG(shared, STATUS);
-        if(status_reg & E1000_STATUS_SPEED_1000) {
-            *speed = SPEED_1000;
-            DEBUGOUT("1000 Mbs, ");
-        } else if(status_reg & E1000_STATUS_SPEED_100) {
-            *speed = SPEED_100;
-            DEBUGOUT("100 Mbs, ");
-        } else {
-            *speed = SPEED_10;
-            DEBUGOUT("10 Mbs, ");
-        }
-
-        if(status_reg & E1000_STATUS_FD) {
-            *duplex = FULL_DUPLEX;
-            DEBUGOUT("Full Duplex\r\n");
-        } else {
-            *duplex = HALF_DUPLEX;
-            DEBUGOUT(" Half Duplex\r\n");
-        }
-    } else {
-        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
-        *speed = SPEED_1000;
-        *duplex = FULL_DUPLEX;
-    }
-
-#if DBG
-    if(shared->phy_id == M88E1000_12_PHY_ID ||
-       shared->phy_id == M88E1000_14_PHY_ID ||
-       shared->phy_id == M88E1000_I_PHY_ID) {
-        /* read the phy specific status register */
-        phy_data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
-        DEBUGOUT1("M88E1000 Phy Specific Status Reg contents = %x\n", phy_data);
-        phy_data = e1000_read_phy_reg(shared, PHY_STATUS);
-        DEBUGOUT1("Phy MII Status Reg contents = %x\n", phy_data);
-        DEBUGOUT1("Device Status Reg contents = %x\n", 
-                  E1000_READ_REG(shared, STATUS));
-    }
-#endif
-    return;
-}
-
-/******************************************************************************
- * Reads a 16 bit word from the EEPROM.
- *
- * shared - Struct containing variables accessed by shared code
- * offset - offset of 16 bit word in the EEPROM to read
- *****************************************************************************/
-uint16_t
-e1000_read_eeprom(struct e1000_shared_adapter *shared,
-                  uint16_t offset)
-{
-    uint16_t data;
-
-    /*  Prepare the EEPROM for reading  */
-    e1000_setup_eeprom(shared);
-
-    /*  Send the READ command (opcode + addr)  */
-    e1000_shift_out_bits(shared, EEPROM_READ_OPCODE, 3);
-    e1000_shift_out_bits(shared, offset, 6);
-
-    /* Read the data */
-    data = e1000_shift_in_bits(shared);
-
-    /* End this read operation */
-    e1000_standby_eeprom(shared);
-
-    return (data);
-}
-
-/******************************************************************************
- * Verifies that the EEPROM has a valid checksum
- * 
- * shared - Struct containing variables accessed by shared code
- *
- * Reads the first 64 16 bit words of the EEPROM and sums the values read.
- * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
- * valid.
- *****************************************************************************/
-boolean_t
-e1000_validate_eeprom_checksum(struct e1000_shared_adapter *shared)
-{
-    uint16_t checksum = 0;
-    uint16_t i;
-
-    for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++)
-        checksum += e1000_read_eeprom(shared, i);
-
-    if(checksum == (uint16_t) EEPROM_SUM)
-        return (TRUE);
-    else
-        return (FALSE);
-}
-/******************************************************************************
- * Reads the adapter's part number from the EEPROM
- *
- * shared - Struct containing variables accessed by shared code
- * part_num - Adapter's part number
- *****************************************************************************/
-boolean_t
-e1000_read_part_num(struct e1000_shared_adapter *shared,
-                    uint32_t *part_num)
-{
-    uint16_t eeprom_word;
-
-    DEBUGFUNC("e1000_read_part_num");
-
-    /* Don't read the EEPROM if we are stopped */
-    if(shared->adapter_stopped) {
-        *part_num = 0;
-        return (FALSE);
-    }
-
-    /* Get word 0 from EEPROM */
-    eeprom_word = e1000_read_eeprom(shared, (uint16_t) (EEPROM_PBA_BYTE_1));
-
-    DEBUGOUT("Read first part number word\n");
-
-    /* Save word 0 in upper half is PartNumber */
-    *part_num = (uint32_t) eeprom_word;
-    *part_num = *part_num << 16;
-
-    /* Get word 1 from EEPROM */
-    eeprom_word =
-        e1000_read_eeprom(shared, (uint16_t) (EEPROM_PBA_BYTE_1 + 1));
-
-    DEBUGOUT("Read second part number word\n");
-
-    /* Save word 1 in lower half of PartNumber */
-    *part_num |= eeprom_word;
-
-    /* read a valid part number */
-    return (TRUE);
-}
-
-void
-e1000_read_mac_addr(struct e1000_shared_adapter * shared)
-{
-    uint16_t temp, x;
-
-    for(x = 0; x < NODE_ADDRESS_SIZE; x += 2) {
-        temp = e1000_read_eeprom(shared, (uint16_t) 
-                                         (EEPROM_NODE_ADDRESS_BYTE_0 + (x/2)));
-        shared->perm_mac_addr[x] = (uint8_t) (temp & 0x00FF);
-        shared->perm_mac_addr[x+1] = (uint8_t) (temp >> 8);
-    }
-    
-    for(x = 0; x < NODE_ADDRESS_SIZE; x++)
-        shared->mac_addr[x] = shared->perm_mac_addr[x];
-}
-
-/******************************************************************************
- * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
- * 
- * shared - Struct containing variables accessed by shared code
- * frame_len - The length of the frame in question
- * mac_addr - The Ethernet destination address of the frame in question
- *****************************************************************************/
-uint32_t
-e1000_tbi_adjust_stats(struct e1000_shared_adapter *shared,
-                       struct e1000_shared_stats *stats,
-                       uint32_t frame_len,
-                       uint8_t *mac_addr)
-{
-    uint64_t carry_bit;
-
-    /* First adjust the frame length. */
-    frame_len--;
-    /* We need to adjust the statistics counters, since the hardware
-     * counters overcount this packet as a CRC error and undercount
-     * the packet as a good packet
-     */
-    /* This packet should not be counted as a CRC error.    */
-    stats->crcerrs--;
-    /* This packet does count as a Good Packet Received.    */
-    stats->gprc++;
-
-    /* Adjust the Good Octets received counters             */
-    carry_bit = 0x80000000 & stats->gorcl;
-    stats->gorcl += frame_len;
-    /* If the high bit of Gorcl (the low 32 bits of the Good Octets
-     * Received Count) was one before the addition, 
-     * AND it is zero after, then we lost the carry out, 
-     * need to add one to Gorch (Good Octets Received Count High).
-     * This could be simplified if all environments supported 
-     * 64-bit integers.
-     */
-    if(carry_bit && ((stats->gorcl & 0x80000000) == 0))
-        stats->gorch++;
-    /* Is this a broadcast or multicast?  Check broadcast first,
-     * since the test for a multicast frame will test positive on 
-     * a broadcast frame.
-     */
-    if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
-        /* Broadcast packet */
-        stats->bprc++;
-    else if(*mac_addr & 0x01)
-        /* Multicast packet */
-        stats->mprc++;
-
-    if(frame_len == shared->max_frame_size) {
-        /* In this case, the hardware has overcounted the number of
-         * oversize frames.
-         */
-        if(stats->roc > 0)
-            stats->roc--;
-    }
-
-    /* Adjust the bin counters when the extra byte put the frame in the
-     * wrong bin. Remember that the frame_len was adjusted above.
-     */
-    if(frame_len == 64) {
-        stats->prc64++;
-        stats->prc127--;
-    } else if(frame_len == 127) {
-        stats->prc127++;
-        stats->prc255--;
-    } else if(frame_len == 255) {
-        stats->prc255++;
-        stats->prc511--;
-    } else if(frame_len == 511) {
-        stats->prc511++;
-        stats->prc1023--;
-    } else if(frame_len == 1023) {
-        stats->prc1023++;
-        stats->prc1522--;
-    } else if(frame_len == 1522) {
-        stats->prc1522++;
-    }
-    return frame_len;
-}
-
-/******************************************************************************
- * Gets the current PCI bus type, speed, and width of the hardware
- *
- * shared - Struct containing variables accessed by shared code
- *****************************************************************************/
-void
-e1000_get_bus_info(struct e1000_shared_adapter *shared)
-{
-    uint32_t status_reg;
-
-    if(shared->mac_type < e1000_82543) {
-        shared->bus_type = e1000_bus_type_unknown;
-        shared->bus_speed = e1000_bus_speed_unknown;
-        shared->bus_width = e1000_bus_width_unknown;
-        return;
-    }
-
-    status_reg = E1000_READ_REG(shared, STATUS);
-
-    shared->bus_type = (status_reg & E1000_STATUS_PCIX_MODE) ?
-        e1000_bus_type_pcix : e1000_bus_type_pci;
-
-    if(shared->bus_type == e1000_bus_type_pci) {
-        shared->bus_speed = (status_reg & E1000_STATUS_PCI66) ?
-            e1000_bus_speed_66 : e1000_bus_speed_33;
-    } else {
-        switch (status_reg & E1000_STATUS_PCIX_SPEED) {
-        case E1000_STATUS_PCIX_SPEED_66:
-            shared->bus_speed = e1000_bus_speed_66;
-            break;
-        case E1000_STATUS_PCIX_SPEED_100:
-            shared->bus_speed = e1000_bus_speed_100;
-            break;
-        case E1000_STATUS_PCIX_SPEED_133:
-            shared->bus_speed = e1000_bus_speed_133;
-            break;
-        default:
-            shared->bus_speed = e1000_bus_speed_reserved;
-            break;
-        }
-    }
-
-    shared->bus_width = (status_reg & E1000_STATUS_BUS64) ?
-        e1000_bus_width_64 : e1000_bus_width_32;
-
-    return;
-}
diff -Nru a/drivers/net/e1000/e1000_mac.h b/drivers/net/e1000/e1000_mac.h
--- a/drivers/net/e1000/e1000_mac.h	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1383 +0,0 @@
-/*******************************************************************************
-
-  This software program is available to you under a choice of one of two
-  licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
-  
-  Recipient has requested a license and Intel Corporation ("Intel") is willing
-  to grant a license for the software entitled Linux Base Driver for the
-  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
-  by Intel Corporation. The following definitions apply to this license:
-  
-  "Licensed Patents" means patent claims licensable by Intel Corporation which
-  are necessarily infringed by the use of sale of the Software alone or when
-  combined with the operating system referred to below.
-  
-  "Recipient" means the party to whom Intel delivers this Software.
-  
-  "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
-  later.
-  
-  Copyright (c) 1999 - 2002 Intel Corporation.
-  All rights reserved.
-  
-  The license is provided to Recipient and Recipient's Licensees under the
-  following terms.
-  
-  Redistribution and use in source and binary forms of the Software, with or
-  without modification, are permitted provided that the following conditions
-  are met:
-  
-  Redistributions of source code of the Software may retain the above
-  copyright notice, this list of conditions and the following disclaimer.
-  
-  Redistributions in binary form of the Software may reproduce the above
-  copyright notice, this list of conditions and the following disclaimer in
-  the documentation and/or materials provided with the distribution.
-  
-  Neither the name of Intel Corporation nor the names of its contributors
-  shall be used to endorse or promote products derived from this Software
-  without specific prior written permission.
-  
-  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
-  royalty-free patent license under Licensed Patents to make, use, sell, offer
-  to sell, import and otherwise transfer the Software, if any, in source code
-  and object code form. This license shall include changes to the Software
-  that are error corrections or other minor changes to the Software that do
-  not add functionality or features when the Software is incorporated in any
-  version of an operating system that has been distributed under the GNU
-  General Public License 2.0 or later. This patent license shall apply to the
-  combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
-  Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
-  such combination to be covered by the Licensed Patents. The patent license
-  shall not apply to any other combinations which include the Software. NO
-  hardware per se is licensed hereunder.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
-  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
-  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
-
-/* e1000_mac.h
- * Structures, enums, and macros for the MAC
- */
-
-#ifndef _E1000_MAC_H_
-#define _E1000_MAC_H_
-
-#include "e1000_osdep.h"
-
-/* Forward declarations of structures used by the shared code */
-struct e1000_shared_adapter;
-struct e1000_shared_stats;
-
-/* Enumerated types specific to the e1000 hardware */
-/* Media Access Controlers */
-typedef enum {
-    e1000_82542_rev2_0 = 0,
-    e1000_82542_rev2_1,
-    e1000_82543,
-    e1000_82544,
-    e1000_num_macs
-} e1000_mac_type;
-
-/* Media Types */
-typedef enum {
-    e1000_media_type_copper = 0,
-    e1000_media_type_fiber = 1,
-    e1000_num_media_types
-} e1000_media_type;
-
-typedef enum {
-    e1000_10_half = 0,
-    e1000_10_full = 1,
-    e1000_100_half = 2,
-    e1000_100_full = 3
-} e1000_speed_duplex_type;
-
-/* Flow Control Settings */
-typedef enum {
-    e1000_fc_none = 0,
-    e1000_fc_rx_pause = 1,
-    e1000_fc_tx_pause = 2,
-    e1000_fc_full = 3,
-    e1000_fc_default = 0xFF
-} e1000_fc_type;
-
-/* PCI bus types */
-typedef enum {
-    e1000_bus_type_unknown = 0,
-    e1000_bus_type_pci,
-    e1000_bus_type_pcix
-} e1000_bus_type;
-
-/* PCI bus speeds */
-typedef enum {
-    e1000_bus_speed_unknown = 0,
-    e1000_bus_speed_33,
-    e1000_bus_speed_66,
-    e1000_bus_speed_100,
-    e1000_bus_speed_133,
-    e1000_bus_speed_reserved
-} e1000_bus_speed;
-
-/* PCI bus widths */
-typedef enum {
-    e1000_bus_width_unknown = 0,
-    e1000_bus_width_32,
-    e1000_bus_width_64
-} e1000_bus_width;
-
-
-
-/* Function prototypes */
-/* Setup */
-void e1000_adapter_stop(struct e1000_shared_adapter *shared);
-boolean_t e1000_init_hw(struct e1000_shared_adapter *shared);
-void e1000_init_rx_addrs(struct e1000_shared_adapter *shared);
-
-/* Filters (multicast, vlan, receive) */
-void e1000_mc_addr_list_update(struct e1000_shared_adapter *shared, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad);
-uint32_t e1000_hash_mc_addr(struct e1000_shared_adapter *shared, uint8_t * mc_addr);
-void e1000_mta_set(struct e1000_shared_adapter *shared, uint32_t hash_value);
-void e1000_rar_set(struct e1000_shared_adapter *shared, uint8_t * mc_addr, uint32_t rar_index);
-void e1000_write_vfta(struct e1000_shared_adapter *shared, uint32_t offset, uint32_t value);
-void e1000_clear_vfta(struct e1000_shared_adapter *shared);
-
-/* Link layer setup functions */
-boolean_t e1000_setup_fc_and_link(struct e1000_shared_adapter *shared);
-boolean_t e1000_setup_pcs_link(struct e1000_shared_adapter *shared, uint32_t dev_ctrl_reg);
-void e1000_config_fc_after_link_up(struct e1000_shared_adapter *shared);
-void e1000_check_for_link(struct e1000_shared_adapter *shared);
-void e1000_get_speed_and_duplex(struct e1000_shared_adapter *shared, uint16_t * speed, uint16_t * duplex);
-
-/* EEPROM Functions */
-uint16_t e1000_read_eeprom(struct e1000_shared_adapter *shared, uint16_t reg);
-boolean_t e1000_validate_eeprom_checksum(struct e1000_shared_adapter *shared);
-
-/* Everything else */
-void e1000_clear_hw_cntrs(struct e1000_shared_adapter *shared);
-boolean_t e1000_read_part_num(struct e1000_shared_adapter *shared, uint32_t * part_num);
-void e1000_read_mac_addr(struct e1000_shared_adapter * shared);
-void e1000_get_bus_info(struct e1000_shared_adapter *shared);
-uint32_t e1000_tbi_adjust_stats(struct e1000_shared_adapter *shared, struct e1000_shared_stats *stats, uint32_t frame_len, uint8_t * mac_addr);
-void e1000_write_pci_cfg(struct e1000_shared_adapter *shared, uint32_t reg, uint16_t * value);
-
-/* PCI Device IDs */
-#define E1000_DEV_ID_82542          0x1000
-#define E1000_DEV_ID_82543GC_FIBER  0x1001
-#define E1000_DEV_ID_82543GC_COPPER 0x1004
-#define E1000_DEV_ID_82544EI_COPPER 0x1008
-#define E1000_DEV_ID_82544EI_FIBER  0x1009
-#define E1000_DEV_ID_82544GC_COPPER 0x100C
-#define E1000_DEV_ID_82544GC_LOM    0x100D
-#define NUM_DEV_IDS 7
-
-#define NODE_ADDRESS_SIZE 6
-#define ETH_LENGTH_OF_ADDRESS 6
-
-/* MAC decode size is 128K - This is the size of BAR0 */
-#define MAC_DECODE_SIZE (128 * 1024)
-
-#define E1000_82542_2_0_REV_ID 2
-#define E1000_82542_2_1_REV_ID 3
-
-#define SPEED_10    10
-#define SPEED_100   100
-#define SPEED_1000  1000
-#define HALF_DUPLEX 1
-#define FULL_DUPLEX 2
-
-/* The sizes (in bytes) of a ethernet packet */
-#define ENET_HEADER_SIZE             14
-#define MAXIMUM_ETHERNET_PACKET_SIZE 1514 /* Without FCS */
-#define MINIMUM_ETHERNET_PACKET_SIZE 60   /* Without FCS */
-#define CRC_LENGTH                   4
-#define MAX_JUMBO_FRAME_SIZE         0x3F00
-
-
-/* 802.1q VLAN Packet Sizes */
-#define VLAN_TAG_SIZE                     4     /* 802.3ac tag (not DMAed) */
-
-/* Ethertype field values */
-#define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
-#define ETHERNET_IP_TYPE        0x0800  /* IP packets */
-#define ETHERNET_ARP_TYPE       0x0806  /* Address Resolution Protocol (ARP) */
-
-/* Packet Header defines */
-#define IP_PROTOCOL_TCP    6
-#define IP_PROTOCOL_UDP    0x11
-
-/* This defines the bits that are set in the Interrupt Mask
- * Set/Read Register.  Each bit is documented below:
- *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
- *   o RXSEQ  = Receive Sequence Error 
- */
-#define POLL_IMS_ENABLE_MASK ( \
-    E1000_IMS_RXDMT0 |         \
-    E1000_IMS_RXSEQ)
-
-/* This defines the bits that are set in the Interrupt Mask
- * Set/Read Register.  Each bit is documented below:
- *   o RXT0   = Receiver Timer Interrupt (ring 0)
- *   o TXDW   = Transmit Descriptor Written Back
- *   o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0)
- *   o RXSEQ  = Receive Sequence Error
- *   o LSC    = Link Status Change
- */
-#define IMS_ENABLE_MASK ( \
-    E1000_IMS_RXT0   |    \
-    E1000_IMS_TXDW   |    \
-    E1000_IMS_RXDMT0 |    \
-    E1000_IMS_RXSEQ  |    \
-    E1000_IMS_LSC)
-
-/* The number of high/low register pairs in the RAR. The RAR (Receive Address
- * Registers) holds the directed and multicast addresses that we monitor. We
- * reserve one of these spots for our directed address, allowing us room for
- * E1000_RAR_ENTRIES - 1 multicast addresses. 
- */
-#define E1000_RAR_ENTRIES 16
-
-#define MIN_NUMBER_OF_DESCRIPTORS 8
-#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8
-
-/* Receive Descriptor */
-struct e1000_rx_desc {
-    uint64_t buffer_addr; /* Address of the descriptor's data buffer */
-    uint16_t length;     /* Length of data DMAed into data buffer */
-    uint16_t csum;       /* Packet checksum */
-    uint8_t status;      /* Descriptor status */
-    uint8_t errors;      /* Descriptor Errors */
-    uint16_t special;
-};
-
-/* Receive Decriptor bit definitions */
-#define E1000_RXD_STAT_DD       0x01    /* Descriptor Done */
-#define E1000_RXD_STAT_EOP      0x02    /* End of Packet */
-#define E1000_RXD_STAT_IXSM     0x04    /* Ignore checksum */
-#define E1000_RXD_STAT_VP       0x08    /* IEEE VLAN Packet */
-#define E1000_RXD_STAT_TCPCS    0x20    /* TCP xsum calculated */
-#define E1000_RXD_STAT_IPCS     0x40    /* IP xsum calculated */
-#define E1000_RXD_STAT_PIF      0x80    /* passed in-exact filter */
-#define E1000_RXD_ERR_CE        0x01    /* CRC Error */
-#define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
-#define E1000_RXD_ERR_SEQ       0x04    /* Sequence Error */
-#define E1000_RXD_ERR_CXE       0x10    /* Carrier Extension Error */
-#define E1000_RXD_ERR_TCPE      0x20    /* TCP/UDP Checksum Error */
-#define E1000_RXD_ERR_IPE       0x40    /* IP Checksum Error */
-#define E1000_RXD_ERR_RXE       0x80    /* Rx Data Error */
-#define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
-#define E1000_RXD_SPC_PRI_MASK  0xE000  /* Priority is in upper 3 bits */
-#define E1000_RXD_SPC_PRI_SHIFT 0x000D  /* Priority is in upper 3 of 16 */
-#define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
-#define E1000_RXD_SPC_CFI_SHIFT 0x000C  /* CFI is bit 12 */
-
-/* mask to determine if packets should be dropped due to frame errors */
-#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
-    E1000_RXD_ERR_CE  |                \
-    E1000_RXD_ERR_SE  |                \
-    E1000_RXD_ERR_SEQ |                \
-    E1000_RXD_ERR_CXE |                \
-    E1000_RXD_ERR_RXE)
-
-/* Transmit Descriptor */
-struct e1000_tx_desc {
-    uint64_t buffer_addr;       /* Address of the descriptor's data buffer */
-    union {
-        uint32_t data;
-        struct {
-            uint16_t length;    /* Data buffer length */
-            uint8_t cso;        /* Checksum offset */
-            uint8_t cmd;        /* Descriptor control */
-        } flags;
-    } lower;
-    union {
-        uint32_t data;
-        struct {
-            uint8_t status;     /* Descriptor status */
-            uint8_t css;        /* Checksum start */
-            uint16_t special;
-        } fields;
-    } upper;
-};
-
-/* Transmit Descriptor bit definitions */
-#define E1000_TXD_DTYP_D     0x00100000 /* Data Descriptor */
-#define E1000_TXD_DTYP_C     0x00000000 /* Context Descriptor */
-#define E1000_TXD_POPTS_IXSM 0x01       /* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02       /* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP    0x01000000 /* End of Packet */
-#define E1000_TXD_CMD_IFCS   0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC     0x04000000 /* Insert Checksum */
-#define E1000_TXD_CMD_RS     0x08000000 /* Report Status */
-#define E1000_TXD_CMD_RPS    0x10000000 /* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT   0x20000000 /* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE    0x40000000 /* Add VLAN tag */
-#define E1000_TXD_CMD_IDE    0x80000000 /* Enable Tidv register */
-#define E1000_TXD_STAT_DD    0x00000001 /* Descriptor Done */
-#define E1000_TXD_STAT_EC    0x00000002 /* Excess Collisions */
-#define E1000_TXD_STAT_LC    0x00000004 /* Late Collisions */
-#define E1000_TXD_STAT_TU    0x00000008 /* Transmit underrun */
-#define E1000_TXD_CMD_TCP    0x01000000 /* TCP packet */
-#define E1000_TXD_CMD_IP     0x02000000 /* IP packet */
-#define E1000_TXD_CMD_TSE    0x04000000 /* TCP Seg enable */
-#define E1000_TXD_STAT_TC    0x00000004 /* Tx Underrun */
-
-/* Offload Context Descriptor */
-struct e1000_context_desc {
-    union {
-        uint32_t ip_config;
-        struct {
-            uint8_t ipcss;      /* IP checksum start */
-            uint8_t ipcso;      /* IP checksum offset */
-            uint16_t ipcse;     /* IP checksum end */
-        } ip_fields;
-    } lower_setup;
-    union {
-        uint32_t tcp_config;
-        struct {
-            uint8_t tucss;      /* TCP checksum start */
-            uint8_t tucso;      /* TCP checksum offset */
-            uint16_t tucse;     /* TCP checksum end */
-        } tcp_fields;
-    } upper_setup;
-    uint32_t cmd_and_length;    /* */
-    union {
-        uint32_t data;
-        struct {
-            uint8_t status;     /* Descriptor status */
-            uint8_t hdr_len;    /* Header length */
-            uint16_t mss;       /* Maximum segment size */
-        } fields;
-    } tcp_seg_setup;
-};
-
-/* Offload data descriptor */
-struct e1000_data_desc {
-    uint64_t buffer_addr;       /* Address of the descriptor's buffer address */
-    union {
-        uint32_t data;
-        struct {
-            uint16_t length;    /* Data buffer length */
-            uint8_t typ_len_ext;        /* */
-            uint8_t cmd;        /* */
-        } flags;
-    } lower;
-    union {
-        uint32_t data;
-        struct {
-            uint8_t status;     /* Descriptor status */
-            uint8_t popts;      /* Packet Options */
-            uint16_t special;   /* */
-        } fields;
-    } upper;
-};
-
-/* Filters */
-#define E1000_NUM_UNICAST          16   /* Unicast filter entries */
-#define E1000_MC_TBL_SIZE          128  /* Multicast Filter Table (4096 bits) */
-#define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
-
-
-/* Receive Address Register */
-struct e1000_rar {
-    volatile uint32_t low;      /* receive address low */
-    volatile uint32_t high;     /* receive address high */
-};
-
-/* The number of entries in the Multicast Table Array (MTA). */
-#define E1000_NUM_MTA_REGISTERS 128
-
-/* IPv4 Address Table Entry */
-struct e1000_ipv4_at_entry {
-    volatile uint32_t ipv4_addr;        /* IP Address (RW) */
-    volatile uint32_t reserved;
-};
-
-/* Four wakeup IP addresses are supported */
-#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4
-#define E1000_IP4AT_SIZE                  E1000_WAKEUP_IP_ADDRESS_COUNT_MAX
-#define E1000_IP6AT_SIZE                  1
-
-/* IPv6 Address Table Entry */
-struct e1000_ipv6_at_entry {
-    volatile uint8_t ipv6_addr[16];
-};
-
-/* Flexible Filter Length Table Entry */
-struct e1000_fflt_entry {
-    volatile uint32_t length;   /* Flexible Filter Length (RW) */
-    volatile uint32_t reserved;
-};
-
-/* Flexible Filter Mask Table Entry */
-struct e1000_ffmt_entry {
-    volatile uint32_t mask;     /* Flexible Filter Mask (RW) */
-    volatile uint32_t reserved;
-};
-
-/* Flexible Filter Value Table Entry */
-struct e1000_ffvt_entry {
-    volatile uint32_t value;    /* Flexible Filter Value (RW) */
-    volatile uint32_t reserved;
-};
-
-/* Four Flexible Filters are supported */
-#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4
-
-/* Each Flexible Filter is at most 128 (0x80) bytes in length */
-#define E1000_FLEXIBLE_FILTER_SIZE_MAX  128
-
-#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX
-#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX
-
-/* Register Set. (82543, 82544)
- *
- * Registers are defined to be 32 bits and  should be accessed as 32 bit values.
- * These registers are physically located on the NIC, but are mapped into the 
- * host memory address space.
- *
- * RW - register is both readable and writable
- * RO - register is read only
- * WO - register is write only
- * R/clr - register is read only and is cleared when read
- * A - register array
- */
-#define E1000_CTRL     0x00000  /* Device Control - RW */
-#define E1000_STATUS   0x00008  /* Device Status - RO */
-#define E1000_EECD     0x00010  /* EEPROM/Flash Control - RW */
-#define E1000_EERD     0x00014  /* EEPROM Read - RW */
-#define E1000_CTRL_EXT 0x00018  /* Extended Device Control - RW */
-#define E1000_MDIC     0x00020  /* MDI Control - RW */
-#define E1000_FCAL     0x00028  /* Flow Control Address Low - RW */
-#define E1000_FCAH     0x0002C  /* Flow Control Address High -RW */
-#define E1000_FCT      0x00030  /* Flow Control Type - RW */
-#define E1000_VET      0x00038  /* VLAN Ether Type - RW */
-#define E1000_ICR      0x000C0  /* Interrupt Cause Read - R/clr */
-#define E1000_ITR      0x000C4  /* Interrupt Throttling Rate - RW */
-#define E1000_ICS      0x000C8  /* Interrupt Cause Set - WO */
-#define E1000_IMS      0x000D0  /* Interrupt Mask Set - RW */
-#define E1000_IMC      0x000D8  /* Interrupt Mask Clear - WO */
-#define E1000_RCTL     0x00100  /* RX Control - RW */
-#define E1000_FCTTV    0x00170  /* Flow Control Transmit Timer Value - RW */
-#define E1000_TXCW     0x00178  /* TX Configuration Word - RW */
-#define E1000_RXCW     0x00180  /* RX Configuration Word - RO */
-#define E1000_TCTL     0x00400  /* TX Control - RW */
-#define E1000_TIPG     0x00410  /* TX Inter-packet gap -RW */
-#define E1000_TBT      0x00448  /* TX Burst Timer - RW */
-#define E1000_LEDCTL   0x00E00  /* LED Control - RW */
-#define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
-#define E1000_FCRTL    0x02160  /* Flow Control Receive Threshold Low - RW */
-#define E1000_FCRTH    0x02168  /* Flow Control Receive Threshold High - RW */
-#define E1000_RDBAL    0x02800  /* RX Descriptor Base Address Low - RW */
-#define E1000_RDBAH    0x02804  /* RX Descriptor Base Address High - RW */
-#define E1000_RDLEN    0x02808  /* RX Descriptor Length - RW */
-#define E1000_RDH      0x02810  /* RX Descriptor Head - RW */
-#define E1000_RDT      0x02818  /* RX Descriptor Tail - RW */
-#define E1000_RDTR     0x02820  /* RX Delay Timer - RW */
-#define E1000_RXDCTL   0x02828  /* RX Descriptor Control - RW */
-#define E1000_RADV     0x0282C  /* RX Interrupt Absolute Delay Timer - RW */
-#define E1000_RSRPD    0x02C00  /* RX Small Packet Detect - RW */
-#define E1000_TXDMAC   0x03000  /* TX DMA Control - RW */
-#define E1000_TDBAL    0x03800  /* TX Descriptor Base Address Low - RW */
-#define E1000_TDBAH    0x03804  /* TX Descriptor Base Address High - RW */
-#define E1000_TDLEN    0x03808  /* TX Descriptor Length - RW */
-#define E1000_TDH      0x03810  /* TX Descriptor Head - RW */
-#define E1000_TDT      0x03818  /* TX Descripotr Tail - RW */
-#define E1000_TIDV     0x03820  /* TX Interrupt Delay Value - RW */
-#define E1000_TXDCTL   0x03828  /* TX Descriptor Control - RW */
-#define E1000_TADV     0x0382C  /* TX Interrupt Absolute Delay Val - RW */
-#define E1000_TSPMT    0x03830  /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_CRCERRS  0x04000  /* CRC Error Count - R/clr */
-#define E1000_ALGNERRC 0x04004  /* Alignment Error Count - R/clr */
-#define E1000_SYMERRS  0x04008  /* Symbol Error Count - R/clr */
-#define E1000_RXERRC   0x0400C  /* Receive Error Count - R/clr */
-#define E1000_MPC      0x04010  /* Missed Packet Count - R/clr */
-#define E1000_SCC      0x04014  /* Single Collision Count - R/clr */
-#define E1000_ECOL     0x04018  /* Excessive Collision Count - R/clr */
-#define E1000_MCC      0x0401C  /* Multiple Collision Count - R/clr */
-#define E1000_LATECOL  0x04020  /* Late Collision Count - R/clr */
-#define E1000_COLC     0x04028  /* Collision Count - R/clr */
-#define E1000_DC       0x04030  /* Defer Count - R/clr */
-#define E1000_TNCRS    0x04034  /* TX-No CRS - R/clr */
-#define E1000_SEC      0x04038  /* Sequence Error Count - R/clr */
-#define E1000_CEXTERR  0x0403C  /* Carrier Extension Error Count - R/clr */
-#define E1000_RLEC     0x04040  /* Receive Length Error Count - R/clr */
-#define E1000_XONRXC   0x04048  /* XON RX Count - R/clr */
-#define E1000_XONTXC   0x0404C  /* XON TX Count - R/clr */
-#define E1000_XOFFRXC  0x04050  /* XOFF RX Count - R/clr */
-#define E1000_XOFFTXC  0x04054  /* XOFF TX Count - R/clr */
-#define E1000_FCRUC    0x04058  /* Flow Control RX Unsupported Count- R/clr */
-#define E1000_PRC64    0x0405C  /* Packets RX (64 bytes) - R/clr */
-#define E1000_PRC127   0x04060  /* Packets RX (65-127 bytes) - R/clr */
-#define E1000_PRC255   0x04064  /* Packets RX (128-255 bytes) - R/clr */
-#define E1000_PRC511   0x04068  /* Packets RX (255-511 bytes) - R/clr */
-#define E1000_PRC1023  0x0406C  /* Packets RX (512-1023 bytes) - R/clr */
-#define E1000_PRC1522  0x04070  /* Packets RX (1024-1522 bytes) - R/clr */
-#define E1000_GPRC     0x04074  /* Good Packets RX Count - R/clr */
-#define E1000_BPRC     0x04078  /* Broadcast Packets RX Count - R/clr */
-#define E1000_MPRC     0x0407C  /* Multicast Packets RX Count - R/clr */
-#define E1000_GPTC     0x04080  /* Good Packets TX Count - R/clr */
-#define E1000_GORCL    0x04088  /* Good Octets RX Count Low - R/clr */
-#define E1000_GORCH    0x0408C  /* Good Octets RX Count High - R/clr */
-#define E1000_GOTCL    0x04090  /* Good Octets TX Count Low - R/clr */
-#define E1000_GOTCH    0x04094  /* Good Octets TX Count High - R/clr */
-#define E1000_RNBC     0x040A0  /* RX No Buffers Count - R/clr */
-#define E1000_RUC      0x040A4  /* RX Undersize Count - R/clr */
-#define E1000_RFC      0x040A8  /* RX Fragment Count - R/clr */
-#define E1000_ROC      0x040AC  /* RX Oversize Count - R/clr */
-#define E1000_RJC      0x040B0  /* RX Jabber Count - R/clr */
-#define E1000_MGTPRC   0x040B4  /* Management Packets RX Count - R/clr */
-#define E1000_MGTPDC   0x040B8  /* Management Packets Dropped Count - R/clr */
-#define E1000_MGTPTC   0x040BC  /* Management Packets TX Count - R/clr */
-#define E1000_TORL     0x040C0  /* Total Octets RX Low - R/clr */
-#define E1000_TORH     0x040C4  /* Total Octets RX High - R/clr */
-#define E1000_TOTL     0x040C8  /* Total Octets TX Low - R/clr */
-#define E1000_TOTH     0x040CC  /* Total Octets TX High - R/clr */
-#define E1000_TPR      0x040D0  /* Total Packets RX - R/clr */
-#define E1000_TPT      0x040D4  /* Total Packets TX - R/clr */
-#define E1000_PTC64    0x040D8  /* Packets TX (64 bytes) - R/clr */
-#define E1000_PTC127   0x040DC  /* Packets TX (65-127 bytes) - R/clr */
-#define E1000_PTC255   0x040E0  /* Packets TX (128-255 bytes) - R/clr */
-#define E1000_PTC511   0x040E4  /* Packets TX (256-511 bytes) - R/clr */
-#define E1000_PTC1023  0x040E8  /* Packets TX (512-1023 bytes) - R/clr */
-#define E1000_PTC1522  0x040EC  /* Packets TX (1024-1522 Bytes) - R/clr */
-#define E1000_MPTC     0x040F0  /* Multicast Packets TX Count - R/clr */
-#define E1000_BPTC     0x040F4  /* Broadcast Packets TX Count - R/clr */
-#define E1000_TSCTC    0x040F8  /* TCP Segmentation Context TX - R/clr */
-#define E1000_TSCTFC   0x040FC  /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_RXCSUM   0x05000  /* RX Checksum Control - RW */
-#define E1000_MTA      0x05200  /* Multicast Table Array - RW Array */
-#define E1000_RA       0x05400  /* Receive Address - RW Array */
-#define E1000_VFTA     0x05600  /* VLAN Filter Table Array - RW Array */
-#define E1000_WUC      0x05800  /* Wakeup Control - RW */
-#define E1000_WUFC     0x05808  /* Wakeup Filter Control - RW */
-#define E1000_WUS      0x05810  /* Wakeup Status - RO */
-#define E1000_MANC     0x05820  /* Management Control - RW */
-#define E1000_IPAV     0x05838  /* IP Address Valid - RW */
-#define E1000_IP4AT    0x05840  /* IPv4 Address Table - RW Array */
-#define E1000_IP6AT    0x05880  /* IPv6 Address Table - RW Array */
-#define E1000_WUPL     0x05900  /* Wakeup Packet Length - RW */
-#define E1000_WUPM     0x05A00  /* Wakeup Packet Memory - RO A */
-#define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - RW Array */
-#define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
-#define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
-
-/* Register Set (82542)
- *
- * Some of the 82542 registers are located at different offsets than they are
- * in more current versions of the 8254x. Despite the difference in location,
- * the registers function in the same manner.
- */
-#define E1000_82542_CTRL     E1000_CTRL
-#define E1000_82542_STATUS   E1000_STATUS
-#define E1000_82542_EECD     E1000_EECD
-#define E1000_82542_EERD     E1000_EERD
-#define E1000_82542_CTRL_EXT E1000_CTRL_EXT
-#define E1000_82542_MDIC     E1000_MDIC
-#define E1000_82542_FCAL     E1000_FCAL
-#define E1000_82542_FCAH     E1000_FCAH
-#define E1000_82542_FCT      E1000_FCT
-#define E1000_82542_VET      E1000_VET
-#define E1000_82542_RA       0x00040
-#define E1000_82542_ICR      E1000_ICR
-#define E1000_82542_ITR      E1000_ITR
-#define E1000_82542_ICS      E1000_ICS
-#define E1000_82542_IMS      E1000_IMS
-#define E1000_82542_IMC      E1000_IMC
-#define E1000_82542_RCTL     E1000_RCTL
-#define E1000_82542_RDTR     0x00108
-#define E1000_82542_RDBAL    0x00110
-#define E1000_82542_RDBAH    0x00114
-#define E1000_82542_RDLEN    0x00118
-#define E1000_82542_RDH      0x00120
-#define E1000_82542_RDT      0x00128
-#define E1000_82542_FCRTH    0x00160
-#define E1000_82542_FCRTL    0x00168
-#define E1000_82542_FCTTV    E1000_FCTTV
-#define E1000_82542_TXCW     E1000_TXCW
-#define E1000_82542_RXCW     E1000_RXCW
-#define E1000_82542_MTA      0x00200
-#define E1000_82542_TCTL     E1000_TCTL
-#define E1000_82542_TIPG     E1000_TIPG
-#define E1000_82542_TDBAL    0x00420
-#define E1000_82542_TDBAH    0x00424
-#define E1000_82542_TDLEN    0x00428
-#define E1000_82542_TDH      0x00430
-#define E1000_82542_TDT      0x00438
-#define E1000_82542_TIDV     0x00440
-#define E1000_82542_TBT      E1000_TBT
-#define E1000_82542_VFTA     0x00600
-#define E1000_82542_LEDCTL   E1000_LEDCTL
-#define E1000_82542_PBA      E1000_PBA
-#define E1000_82542_RXDCTL   E1000_RXDCTL
-#define E1000_82542_RADV     E1000_RADV
-#define E1000_82542_RSRPD    E1000_RSRPD
-#define E1000_82542_TXDMAC   E1000_TXDMAC
-#define E1000_82542_TXDCTL   E1000_TXDCTL
-#define E1000_82542_TADV     E1000_TADV
-#define E1000_82542_TSPMT    E1000_TSPMT
-#define E1000_82542_CRCERRS  E1000_CRCERRS
-#define E1000_82542_ALGNERRC E1000_ALGNERRC
-#define E1000_82542_SYMERRS  E1000_SYMERRS
-#define E1000_82542_RXERRC   E1000_RXERRC
-#define E1000_82542_MPC      E1000_MPC
-#define E1000_82542_SCC      E1000_SCC
-#define E1000_82542_ECOL     E1000_ECOL
-#define E1000_82542_MCC      E1000_MCC
-#define E1000_82542_LATECOL  E1000_LATECOL
-#define E1000_82542_COLC     E1000_COLC
-#define E1000_82542_DC       E1000_DC
-#define E1000_82542_TNCRS    E1000_TNCRS
-#define E1000_82542_SEC      E1000_SEC
-#define E1000_82542_CEXTERR  E1000_CEXTERR
-#define E1000_82542_RLEC     E1000_RLEC
-#define E1000_82542_XONRXC   E1000_XONRXC
-#define E1000_82542_XONTXC   E1000_XONTXC
-#define E1000_82542_XOFFRXC  E1000_XOFFRXC
-#define E1000_82542_XOFFTXC  E1000_XOFFTXC
-#define E1000_82542_FCRUC    E1000_FCRUC
-#define E1000_82542_PRC64    E1000_PRC64
-#define E1000_82542_PRC127   E1000_PRC127
-#define E1000_82542_PRC255   E1000_PRC255
-#define E1000_82542_PRC511   E1000_PRC511
-#define E1000_82542_PRC1023  E1000_PRC1023
-#define E1000_82542_PRC1522  E1000_PRC1522
-#define E1000_82542_GPRC     E1000_GPRC
-#define E1000_82542_BPRC     E1000_BPRC
-#define E1000_82542_MPRC     E1000_MPRC
-#define E1000_82542_GPTC     E1000_GPTC
-#define E1000_82542_GORCL    E1000_GORCL
-#define E1000_82542_GORCH    E1000_GORCH
-#define E1000_82542_GOTCL    E1000_GOTCL
-#define E1000_82542_GOTCH    E1000_GOTCH
-#define E1000_82542_RNBC     E1000_RNBC
-#define E1000_82542_RUC      E1000_RUC
-#define E1000_82542_RFC      E1000_RFC
-#define E1000_82542_ROC      E1000_ROC
-#define E1000_82542_RJC      E1000_RJC
-#define E1000_82542_MGTPRC   E1000_MGTPRC
-#define E1000_82542_MGTPDC   E1000_MGTPDC
-#define E1000_82542_MGTPTC   E1000_MGTPTC
-#define E1000_82542_TORL     E1000_TORL
-#define E1000_82542_TORH     E1000_TORH
-#define E1000_82542_TOTL     E1000_TOTL
-#define E1000_82542_TOTH     E1000_TOTH
-#define E1000_82542_TPR      E1000_TPR
-#define E1000_82542_TPT      E1000_TPT
-#define E1000_82542_PTC64    E1000_PTC64
-#define E1000_82542_PTC127   E1000_PTC127
-#define E1000_82542_PTC255   E1000_PTC255
-#define E1000_82542_PTC511   E1000_PTC511
-#define E1000_82542_PTC1023  E1000_PTC1023
-#define E1000_82542_PTC1522  E1000_PTC1522
-#define E1000_82542_MPTC     E1000_MPTC
-#define E1000_82542_BPTC     E1000_BPTC
-#define E1000_82542_TSCTC    E1000_TSCTC
-#define E1000_82542_TSCTFC   E1000_TSCTFC
-#define E1000_82542_RXCSUM   E1000_RXCSUM
-#define E1000_82542_WUC      E1000_WUC
-#define E1000_82542_WUFC     E1000_WUFC
-#define E1000_82542_WUS      E1000_WUS
-#define E1000_82542_MANC     E1000_MANC
-#define E1000_82542_IPAV     E1000_IPAV
-#define E1000_82542_IP4AT    E1000_IP4AT
-#define E1000_82542_IP6AT    E1000_IP6AT
-#define E1000_82542_WUPL     E1000_WUPL
-#define E1000_82542_WUPM     E1000_WUPM
-#define E1000_82542_FFLT     E1000_FFLT
-#define E1000_82542_FFMT     E1000_FFMT
-#define E1000_82542_FFVT     E1000_FFVT
-
-/* Statistics counters collected by the MAC */
-struct e1000_shared_stats {
-    uint64_t crcerrs;
-    uint64_t algnerrc;
-    uint64_t symerrs;
-    uint64_t rxerrc;
-    uint64_t mpc;
-    uint64_t scc;
-    uint64_t ecol;
-    uint64_t mcc;
-    uint64_t latecol;
-    uint64_t colc;
-    uint64_t dc;
-    uint64_t tncrs;
-    uint64_t sec;
-    uint64_t cexterr;
-    uint64_t rlec;
-    uint64_t xonrxc;
-    uint64_t xontxc;
-    uint64_t xoffrxc;
-    uint64_t xofftxc;
-    uint64_t fcruc;
-    uint64_t prc64;
-    uint64_t prc127;
-    uint64_t prc255;
-    uint64_t prc511;
-    uint64_t prc1023;
-    uint64_t prc1522;
-    uint64_t gprc;
-    uint64_t bprc;
-    uint64_t mprc;
-    uint64_t gptc;
-    uint64_t gorcl;
-    uint64_t gorch;
-    uint64_t gotcl;
-    uint64_t gotch;
-    uint64_t rnbc;
-    uint64_t ruc;
-    uint64_t rfc;
-    uint64_t roc;
-    uint64_t rjc;
-    uint64_t mgprc;
-    uint64_t mgpdc;
-    uint64_t mgptc;
-    uint64_t torl;
-    uint64_t torh;
-    uint64_t totl;
-    uint64_t toth;
-    uint64_t tpr;
-    uint64_t tpt;
-    uint64_t ptc64;
-    uint64_t ptc127;
-    uint64_t ptc255;
-    uint64_t ptc511;
-    uint64_t ptc1023;
-    uint64_t ptc1522;
-    uint64_t mptc;
-    uint64_t bptc;
-    uint64_t tsctc;
-    uint64_t tsctfc;
-};
-
-/* Structure containing variables used by the shared code (e1000_mac.c and 
- * e1000_phy.c)
- */
-struct e1000_shared_adapter {
-    uint8_t *hw_addr;
-    e1000_mac_type mac_type;
-    e1000_media_type media_type;
-    void *back;
-    e1000_fc_type fc;
-    e1000_bus_speed bus_speed;
-    e1000_bus_width bus_width;
-    e1000_bus_type bus_type;
-    uint32_t phy_id;
-    uint32_t phy_addr;
-    uint32_t original_fc;
-    uint32_t txcw_reg;
-    uint32_t autoneg_failed;
-    uint32_t max_frame_size;
-    uint32_t min_frame_size;
-    uint32_t mc_filter_type;
-    uint32_t num_mc_addrs;
-    uint16_t autoneg_advertised;
-    uint16_t pci_cmd_word;
-    uint16_t fc_high_water;
-    uint16_t fc_low_water;
-    uint16_t fc_pause_time;
-    uint16_t device_id;
-    uint16_t vendor_id;
-    uint16_t subsystem_id;
-    uint16_t subsystem_vendor_id;
-    uint8_t revision_id;
-    boolean_t disable_polarity_correction;
-    boolean_t get_link_status;
-    boolean_t tbi_compatibility_en;
-    boolean_t tbi_compatibility_on;
-    boolean_t adapter_stopped;
-    boolean_t fc_send_xon;
-    boolean_t report_tx_early;
-    uint8_t autoneg;
-    uint8_t mdix;
-    uint8_t forced_speed_duplex;
-    uint8_t wait_autoneg_complete;
-    uint8_t dma_fairness;
-    uint8_t mac_addr[NODE_ADDRESS_SIZE];
-    uint8_t perm_mac_addr[NODE_ADDRESS_SIZE];
-};
-
-
-#define E1000_EEPROM_SWDPIN0   0x0001   /* SWDPIN 0 EEPROM Value */
-#define E1000_EEPROM_LED_LOGIC 0x0020   /* Led Logic Word */
-
-/* Register Bit Masks */
-/* Device Control */
-#define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
-#define E1000_CTRL_BEM      0x00000002  /* Endian Mode.0=little,1=big */
-#define E1000_CTRL_PRIOR    0x00000004  /* Priority on PCI. 0=rx,1=fair */
-#define E1000_CTRL_LRST     0x00000008  /* Link reset. 0=normal,1=reset */
-#define E1000_CTRL_TME      0x00000010  /* Test mode. 0=normal,1=test */
-#define E1000_CTRL_SLE      0x00000020  /* Serial Link on 0=dis,1=en */
-#define E1000_CTRL_ASDE     0x00000020  /* Auto-speed detect enable */
-#define E1000_CTRL_SLU      0x00000040  /* Set link up (Force Link) */
-#define E1000_CTRL_ILOS     0x00000080  /* Invert Loss-Of Signal */
-#define E1000_CTRL_SPD_SEL  0x00000300  /* Speed Select Mask */
-#define E1000_CTRL_SPD_10   0x00000000  /* Force 10Mb */
-#define E1000_CTRL_SPD_100  0x00000100  /* Force 100Mb */
-#define E1000_CTRL_SPD_1000 0x00000200  /* Force 1Gb */
-#define E1000_CTRL_BEM32    0x00000400  /* Big Endian 32 mode */
-#define E1000_CTRL_FRCSPD   0x00000800  /* Force Speed */
-#define E1000_CTRL_FRCDPX   0x00001000  /* Force Duplex */
-#define E1000_CTRL_SWDPIN0  0x00040000  /* SWDPIN 0 value */
-#define E1000_CTRL_SWDPIN1  0x00080000  /* SWDPIN 1 value */
-#define E1000_CTRL_SWDPIN2  0x00100000  /* SWDPIN 2 value */
-#define E1000_CTRL_SWDPIN3  0x00200000  /* SWDPIN 3 value */
-#define E1000_CTRL_SWDPIO0  0x00400000  /* SWDPIN 0 Input or output */
-#define E1000_CTRL_SWDPIO1  0x00800000  /* SWDPIN 1 input or output */
-#define E1000_CTRL_SWDPIO2  0x01000000  /* SWDPIN 2 input or output */
-#define E1000_CTRL_SWDPIO3  0x02000000  /* SWDPIN 3 input or output */
-#define E1000_CTRL_RST      0x04000000  /* Global reset */
-#define E1000_CTRL_RFCE     0x08000000  /* Receive Flow Control enable */
-#define E1000_CTRL_TFCE     0x10000000  /* Transmit flow control enable */
-#define E1000_CTRL_RTE      0x20000000  /* Routing tag enable */
-#define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
-#define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
-
-/* Device Status */
-#define E1000_STATUS_FD         0x00000001      /* Full duplex.0=half,1=full */
-#define E1000_STATUS_LU         0x00000002      /* Link up.0=no,1=link */
-#define E1000_STATUS_FUNC_MASK  0x0000000C      /* PCI Function Mask */
-#define E1000_STATUS_FUNC_0     0x00000000      /* Function 0 */
-#define E1000_STATUS_FUNC_1     0x00000004      /* Function 1 */
-#define E1000_STATUS_TXOFF      0x00000010      /* transmission paused */
-#define E1000_STATUS_TBIMODE    0x00000020      /* TBI mode */
-#define E1000_STATUS_SPEED_MASK 0x000000C0
-#define E1000_STATUS_SPEED_10   0x00000000      /* Speed 10Mb/s */
-#define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
-#define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
-#define E1000_STATUS_ASDV       0x00000300      /* Auto speed detect value */
-#define E1000_STATUS_MTXCKOK    0x00000400      /* MTX clock running OK */
-#define E1000_STATUS_PCI66      0x00000800      /* In 66Mhz slot */
-#define E1000_STATUS_BUS64      0x00001000      /* In 64 bit slot */
-#define E1000_STATUS_PCIX_MODE  0x00002000      /* PCI-X mode */
-#define E1000_STATUS_PCIX_SPEED 0x0000C000      /* PCI-X bus speed */
-
-/* Constants used to intrepret the masked PCI-X bus speed. */
-#define E1000_STATUS_PCIX_SPEED_66  0x00000000 /* PCI-X bus speed  50-66 MHz */
-#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed  66-100 MHz */
-#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */
-
-/* EEPROM/Flash Control */
-#define E1000_EECD_SK        0x00000001 /* EEPROM Clock */
-#define E1000_EECD_CS        0x00000002 /* EEPROM Chip Select */
-#define E1000_EECD_DI        0x00000004 /* EEPROM Data In */
-#define E1000_EECD_DO        0x00000008 /* EEPROM Data Out */
-#define E1000_EECD_FWE_MASK  0x00000030 
-#define E1000_EECD_FWE_DIS   0x00000010 /* Disable FLASH writes */
-#define E1000_EECD_FWE_EN    0x00000020 /* Enable FLASH writes */
-#define E1000_EECD_FWE_SHIFT 4
-#define E1000_EECD_SIZE      0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
-#define E1000_EECD_REQ       0x00000040 /* EEPROM Access Request */
-#define E1000_EECD_GNT       0x00000080 /* EEPROM Access Grant */
-#define E1000_EECD_PRES      0x00000100 /* EEPROM Present */
-
-/* EEPROM Read */
-#define E1000_EERD_START      0x00000001 /* Start Read */
-#define E1000_EERD_DONE       0x00000010 /* Read Done */
-#define E1000_EERD_ADDR_SHIFT 8
-#define E1000_EERD_ADDR_MASK  0x0000FF00 /* Read Address */
-#define E1000_EERD_DATA_SHIFT 16
-#define E1000_EERD_DATA_MASK  0xFFFF0000 /* Read Data */
-
-/* Extended Device Control */
-#define E1000_CTRL_EXT_GPI0_EN   0x00000001 /* Maps SDP4 to GPI0 */ 
-#define E1000_CTRL_EXT_GPI1_EN   0x00000002 /* Maps SDP5 to GPI1 */
-#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
-#define E1000_CTRL_EXT_GPI2_EN   0x00000004 /* Maps SDP6 to GPI2 */
-#define E1000_CTRL_EXT_GPI3_EN   0x00000008 /* Maps SDP7 to GPI3 */
-#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
-#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
-#define E1000_CTRL_EXT_PHY_INT   E1000_CTRL_EXT_SDP5_DATA
-#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */
-#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
-#define E1000_CTRL_EXT_SDP4_DIR  0x00000100 /* Direction of SDP4 0=in 1=out */
-#define E1000_CTRL_EXT_SDP5_DIR  0x00000200 /* Direction of SDP5 0=in 1=out */
-#define E1000_CTRL_EXT_SDP6_DIR  0x00000400 /* Direction of SDP6 0=in 1=out */
-#define E1000_CTRL_EXT_SDP7_DIR  0x00000800 /* Direction of SDP7 0=in 1=out */
-#define E1000_CTRL_EXT_ASDCHK    0x00001000 /* Initiate an ASD sequence */
-#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
-#define E1000_CTRL_EXT_IPS       0x00004000 /* Invert Power State */
-#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
-#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
-#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
-#define E1000_CTRL_EXT_LINK_MODE_TBI  0x00C00000
-#define E1000_CTRL_EXT_WR_WMARK_MASK  0x03000000
-#define E1000_CTRL_EXT_WR_WMARK_256   0x00000000
-#define E1000_CTRL_EXT_WR_WMARK_320   0x01000000
-#define E1000_CTRL_EXT_WR_WMARK_384   0x02000000
-#define E1000_CTRL_EXT_WR_WMARK_448   0x03000000
-
-/* MDI Control */
-#define E1000_MDIC_DATA_MASK 0x0000FFFF
-#define E1000_MDIC_REG_MASK  0x001F0000
-#define E1000_MDIC_REG_SHIFT 16
-#define E1000_MDIC_PHY_MASK  0x03E00000
-#define E1000_MDIC_PHY_SHIFT 21
-#define E1000_MDIC_OP_WRITE  0x04000000
-#define E1000_MDIC_OP_READ   0x08000000
-#define E1000_MDIC_READY     0x10000000
-#define E1000_MDIC_INT_EN    0x20000000
-#define E1000_MDIC_ERROR     0x40000000
-
-/* LED Control */
-#define E1000_LEDCTL_LED0_MODE_MASK  0x0000000F
-#define E1000_LEDCTL_LED0_MODE_SHIFT 0
-#define E1000_LEDCTL_LED0_IVRT       0x00000040
-#define E1000_LEDCTL_LED0_BLINK      0x00000080
-#define E1000_LEDCTL_LED1_MODE_MASK  0x00000F00
-#define E1000_LEDCTL_LED1_MODE_SHIFT 8
-#define E1000_LEDCTL_LED1_IVRT       0x00004000
-#define E1000_LEDCTL_LED1_BLINK      0x00008000
-#define E1000_LEDCTL_LED2_MODE_MASK  0x000F0000
-#define E1000_LEDCTL_LED2_MODE_SHIFT 16
-#define E1000_LEDCTL_LED2_IVRT       0x00400000
-#define E1000_LEDCTL_LED2_BLINK      0x00800000
-#define E1000_LEDCTL_LED3_MODE_MASK  0x0F000000
-#define E1000_LEDCTL_LED3_MODE_SHIFT 24
-#define E1000_LEDCTL_LED3_IVRT       0x40000000
-#define E1000_LEDCTL_LED3_BLINK      0x80000000
-
-#define E1000_LEDCTL_MODE_LINK_10_1000  0x0
-#define E1000_LEDCTL_MODE_LINK_100_1000 0x1
-#define E1000_LEDCTL_MODE_LINK_UP       0x2
-#define E1000_LEDCTL_MODE_ACTIVITY      0x3
-#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4
-#define E1000_LEDCTL_MODE_LINK_10       0x5
-#define E1000_LEDCTL_MODE_LINK_100      0x6
-#define E1000_LEDCTL_MODE_LINK_1000     0x7
-#define E1000_LEDCTL_MODE_PCIX_MODE     0x8
-#define E1000_LEDCTL_MODE_FULL_DUPLEX   0x9
-#define E1000_LEDCTL_MODE_COLLISION     0xA
-#define E1000_LEDCTL_MODE_BUS_SPEED     0xB
-#define E1000_LEDCTL_MODE_BUS_SIZE      0xC
-#define E1000_LEDCTL_MODE_PAUSED        0xD
-#define E1000_LEDCTL_MODE_LED_ON        0xE
-#define E1000_LEDCTL_MODE_LED_OFF       0xF
-
-/* Receive Address */
-#define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
-
-/* Interrupt Cause Read */
-#define E1000_ICR_TXDW    0x00000001    /* Transmit desc written back */
-#define E1000_ICR_TXQE    0x00000002    /* Transmit Queue empty */
-#define E1000_ICR_LSC     0x00000004    /* Link Status Change */
-#define E1000_ICR_RXSEQ   0x00000008    /* rx sequence error */
-#define E1000_ICR_RXDMT0  0x00000010    /* rx desc min. threshold (0) */
-#define E1000_ICR_RXO     0x00000040    /* rx overrun */
-#define E1000_ICR_RXT0    0x00000080    /* rx timer intr (ring 0) */
-#define E1000_ICR_MDAC    0x00000200    /* MDIO access complete */
-#define E1000_ICR_RXCFG   0x00000400    /* RX /c/ ordered set */
-#define E1000_ICR_GPI_EN0 0x00000800    /* GP Int 0 */
-#define E1000_ICR_GPI_EN1 0x00001000    /* GP Int 1 */
-#define E1000_ICR_GPI_EN2 0x00002000    /* GP Int 2 */
-#define E1000_ICR_GPI_EN3 0x00004000    /* GP Int 3 */
-#define E1000_ICR_TXD_LOW 0x00008000
-#define E1000_ICR_SRPD    0x00010000
-
-/* Interrupt Cause Set */
-#define E1000_ICS_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
-#define E1000_ICS_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
-#define E1000_ICS_LSC     E1000_ICR_LSC         /* Link Status Change */
-#define E1000_ICS_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
-#define E1000_ICS_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
-#define E1000_ICS_RXO     E1000_ICR_RXO         /* rx overrun */
-#define E1000_ICS_RXT0    E1000_ICR_RXT0        /* rx timer intr */
-#define E1000_ICS_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
-#define E1000_ICS_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
-#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
-#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
-#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
-#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
-#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
-#define E1000_ICS_SRPD    E1000_ICR_SRPD
-
-/* Interrupt Mask Set */
-#define E1000_IMS_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
-#define E1000_IMS_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
-#define E1000_IMS_LSC     E1000_ICR_LSC         /* Link Status Change */
-#define E1000_IMS_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
-#define E1000_IMS_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
-#define E1000_IMS_RXO     E1000_ICR_RXO         /* rx overrun */
-#define E1000_IMS_RXT0    E1000_ICR_RXT0        /* rx timer intr */
-#define E1000_IMS_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
-#define E1000_IMS_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
-#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
-#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
-#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
-#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
-#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
-#define E1000_IMS_SRPD    E1000_ICR_SRPD
-
-/* Interrupt Mask Clear */
-#define E1000_IMC_TXDW    E1000_ICR_TXDW        /* Transmit desc written back */
-#define E1000_IMC_TXQE    E1000_ICR_TXQE        /* Transmit Queue empty */
-#define E1000_IMC_LSC     E1000_ICR_LSC         /* Link Status Change */
-#define E1000_IMC_RXSEQ   E1000_ICR_RXSEQ       /* rx sequence error */
-#define E1000_IMC_RXDMT0  E1000_ICR_RXDMT0      /* rx desc min. threshold */
-#define E1000_IMC_RXO     E1000_ICR_RXO         /* rx overrun */
-#define E1000_IMC_RXT0    E1000_ICR_RXT0        /* rx timer intr */
-#define E1000_IMC_MDAC    E1000_ICR_MDAC        /* MDIO access complete */
-#define E1000_IMC_RXCFG   E1000_ICR_RXCFG       /* RX /c/ ordered set */
-#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0     /* GP Int 0 */
-#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1     /* GP Int 1 */
-#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2     /* GP Int 2 */
-#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3     /* GP Int 3 */
-#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW
-#define E1000_IMC_SRPD    E1000_ICR_SRPD
-
-/* Receive Control */
-#define E1000_RCTL_RST          0x00000001      /* Software reset */
-#define E1000_RCTL_EN           0x00000002      /* enable */
-#define E1000_RCTL_SBP          0x00000004      /* store bad packet */
-#define E1000_RCTL_UPE          0x00000008      /* unicast promiscuous enable */
-#define E1000_RCTL_MPE          0x00000010      /* multicast promiscuous enab */
-#define E1000_RCTL_LPE          0x00000020      /* long packet enable */
-#define E1000_RCTL_LBM_NO       0x00000000      /* no loopback mode */
-#define E1000_RCTL_LBM_MAC      0x00000040      /* MAC loopback mode */
-#define E1000_RCTL_LBM_SLP      0x00000080      /* serial link loopback mode */
-#define E1000_RCTL_LBM_TCVR     0x000000C0      /* tcvr loopback mode */
-#define E1000_RCTL_RDMTS_HALF   0x00000000      /* rx desc min threshold size */
-#define E1000_RCTL_RDMTS_QUAT   0x00000100      /* rx desc min threshold size */
-#define E1000_RCTL_RDMTS_EIGTH  0x00000200      /* rx desc min threshold size */
-#define E1000_RCTL_MO_SHIFT     12              /* multicast offset shift */
-#define E1000_RCTL_MO_0         0x00000000      /* multicast offset 11:0 */
-#define E1000_RCTL_MO_1         0x00001000      /* multicast offset 12:1 */
-#define E1000_RCTL_MO_2         0x00002000      /* multicast offset 13:2 */
-#define E1000_RCTL_MO_3         0x00003000      /* multicast offset 15:4 */
-#define E1000_RCTL_MDR          0x00004000      /* multicast desc ring 0 */
-#define E1000_RCTL_BAM          0x00008000      /* broadcast enable */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048      0x00000000      /* rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024      0x00010000      /* rx buffer size 1024 */
-#define E1000_RCTL_SZ_512       0x00020000      /* rx buffer size 512 */
-#define E1000_RCTL_SZ_256       0x00030000      /* rx buffer size 256 */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384     0x00010000      /* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192      0x00020000      /* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096      0x00030000      /* rx buffer size 4096 */
-#define E1000_RCTL_VFE          0x00040000      /* vlan filter enable */
-#define E1000_RCTL_CFIEN        0x00080000      /* canonical form enable */
-#define E1000_RCTL_CFI          0x00100000      /* canonical form indicator */
-#define E1000_RCTL_DPF          0x00400000      /* discard pause frames */
-#define E1000_RCTL_PMCF         0x00800000      /* pass MAC control frames */
-#define E1000_RCTL_BSEX         0x02000000      /* Buffer size extension */
-
-/* Receive Descriptor */
-#define E1000_RDT_DELAY 0x0000ffff      /* Delay timer (1=1024us) */
-#define E1000_RDT_FPDB  0x80000000      /* Flush descriptor block */
-#define E1000_RDLEN_LEN 0x0007ff80      /* descriptor length */
-#define E1000_RDH_RDH   0x0000ffff      /* receive descriptor head */
-#define E1000_RDT_RDT   0x0000ffff      /* receive descriptor tail */
-
-/* Flow Control */
-#define E1000_FCRTH_RTH  0x0000FFF8     /* Mask Bits[15:3] for RTH */
-#define E1000_FCRTH_XFCE 0x80000000     /* External Flow Control Enable */
-#define E1000_FCRTL_RTL  0x0000FFF8     /* Mask Bits[15:3] for RTL */
-#define E1000_FCRTL_XONE 0x80000000     /* Enable XON frame transmission */
-
-/* Receive Descriptor Control */
-#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
-#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
-#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */
-#define E1000_RXDCTL_GRAN    0x01000000 /* RXDCTL Granularity */
-
-/* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
-#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
-
-/* Transmit Configuration Word */
-#define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
-#define E1000_TXCW_HD         0x00000040        /* TXCW half duplex */
-#define E1000_TXCW_PAUSE      0x00000080        /* TXCW sym pause request */
-#define E1000_TXCW_ASM_DIR    0x00000100        /* TXCW astm pause direction */
-#define E1000_TXCW_PAUSE_MASK 0x00000180        /* TXCW pause request mask */
-#define E1000_TXCW_RF         0x00003000        /* TXCW remote fault */
-#define E1000_TXCW_NP         0x00008000        /* TXCW next page */
-#define E1000_TXCW_CW         0x0000ffff        /* TxConfigWord mask */
-#define E1000_TXCW_TXC        0x40000000        /* Transmit Config control */
-#define E1000_TXCW_ANE        0x80000000        /* Auto-neg enable */
-
-/* Receive Configuration Word */
-#define E1000_RXCW_CW    0x0000ffff     /* RxConfigWord mask */
-#define E1000_RXCW_NC    0x04000000     /* Receive config no carrier */
-#define E1000_RXCW_IV    0x08000000     /* Receive config invalid */
-#define E1000_RXCW_CC    0x10000000     /* Receive config change */
-#define E1000_RXCW_C     0x20000000     /* Receive config */
-#define E1000_RXCW_SYNCH 0x40000000     /* Receive config synch */
-#define E1000_RXCW_ANC   0x80000000     /* Auto-neg complete */
-
-/* Transmit Control */
-#define E1000_TCTL_RST    0x00000001    /* software reset */
-#define E1000_TCTL_EN     0x00000002    /* enable tx */
-#define E1000_TCTL_BCE    0x00000004    /* busy check enable */
-#define E1000_TCTL_PSP    0x00000008    /* pad short packets */
-#define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
-#define E1000_TCTL_COLD   0x003ff000    /* collision distance */
-#define E1000_TCTL_SWXOFF 0x00400000    /* SW Xoff transmission */
-#define E1000_TCTL_PBE    0x00800000    /* Packet Burst Enable */
-#define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
-#define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
-
-/* Receive Checksum Control */
-#define E1000_RXCSUM_PCSS_MASK 0x000000FF   /* Packet Checksum Start */
-#define E1000_RXCSUM_IPOFL     0x00000100   /* IPv4 checksum offload */
-#define E1000_RXCSUM_TUOFL     0x00000200   /* TCP / UDP checksum offload */
-#define E1000_RXCSUM_IPV6OFL   0x00000400   /* IPv6 checksum offload */
-
-/* Definitions for power management and wakeup registers */
-/* Wake Up Control */
-#define E1000_WUC_APME       0x00000001 /* APM Enable */
-#define E1000_WUC_PME_EN     0x00000002 /* PME Enable */
-#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
-#define E1000_WUC_APMPME     0x00000008 /* Assert PME on APM Wakeup */
-
-/* Wake Up Filter Control */
-#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-#define E1000_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
-#define E1000_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
-#define E1000_WUFC_MC   0x00000008 /* Directed Multicast Wakeup Enable */
-#define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
-#define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
-#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
-#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
-#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
-#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
-#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
-#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
-#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
-#define E1000_WUFC_FLX_OFFSET 16       /* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
-
-/* Wake Up Status */
-#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */
-#define E1000_WUS_MAG  0x00000002 /* Magic Packet Received */
-#define E1000_WUS_EX   0x00000004 /* Directed Exact Received */
-#define E1000_WUS_MC   0x00000008 /* Directed Multicast Received */
-#define E1000_WUS_BC   0x00000010 /* Broadcast Received */
-#define E1000_WUS_ARP  0x00000020 /* ARP Request Packet Received */
-#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */
-#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */
-#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */
-#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */
-#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */
-#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */
-#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
-
-/* Management Control */
-#define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
-#define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
-#define E1000_MANC_R_ON_FORCE    0x00000004 /* Reset on Force TCO - RO */
-#define E1000_MANC_RMCP_EN       0x00000100 /* Enable RCMP 026Fh Filtering */
-#define E1000_MANC_0298_EN       0x00000200 /* Enable RCMP 0298h Filtering */
-#define E1000_MANC_IPV4_EN       0x00000400 /* Enable IPv4 */
-#define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
-#define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
-#define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
-#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery 
-                                             * Filtering */
-#define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
-#define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
-#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
-#define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
-#define E1000_MANC_SMB_GNT       0x02000000 /* SMBus Grant */
-#define E1000_MANC_SMB_CLK_IN    0x04000000 /* SMBus Clock In */
-#define E1000_MANC_SMB_DATA_IN   0x08000000 /* SMBus Data In */
-#define E1000_MANC_SMB_DATA_OUT  0x10000000 /* SMBus Data Out */
-#define E1000_MANC_SMB_CLK_OUT   0x20000000 /* SMBus Clock Out */
-
-#define E1000_MANC_SMB_DATA_OUT_SHIFT  28 /* SMBus Data Out Shift */
-#define E1000_MANC_SMB_CLK_OUT_SHIFT   29 /* SMBus Clock Out Shift */
-
-/* Wake Up Packet Length */
-#define E1000_WUPL_LENGTH_MASK 0x0FFF   /* Only the lower 12 bits are valid */
-
-#define E1000_MDALIGN          4096
-
-/* EEPROM Commands */
-#define EEPROM_READ_OPCODE  0x6  /* EERPOM read opcode */
-#define EEPROM_WRITE_OPCODE 0x5  /* EERPOM write opcode */
-#define EEPROM_ERASE_OPCODE 0x7  /* EERPOM erase opcode */
-#define EEPROM_EWEN_OPCODE  0x13 /* EERPOM erase/write enable */
-#define EEPROM_EWDS_OPCODE  0x10 /* EERPOM erast/write disable */
-
-/* EEPROM Word Offsets */
-#define EEPROM_INIT_CONTROL1_REG 0x000A
-#define EEPROM_INIT_CONTROL2_REG 0x000F
-#define EEPROM_FLASH_VERSION     0x0032
-#define EEPROM_CHECKSUM_REG      0x003F
-
-/* Mask bits for fields in Word 0x0a of the EEPROM */
-#define EEPROM_WORD0A_ILOS   0x0010
-#define EEPROM_WORD0A_SWDPIO 0x01E0
-#define EEPROM_WORD0A_LRST   0x0200
-#define EEPROM_WORD0A_FD     0x0400
-#define EEPROM_WORD0A_66MHZ  0x0800
-
-/* Mask bits for fields in Word 0x0f of the EEPROM */
-#define EEPROM_WORD0F_PAUSE_MASK 0x3000
-#define EEPROM_WORD0F_PAUSE      0x1000
-#define EEPROM_WORD0F_ASM_DIR    0x2000
-#define EEPROM_WORD0F_ANE        0x0800
-#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0
-
-/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
-#define EEPROM_SUM 0xBABA
-
-/* EEPROM Map defines (WORD OFFSETS)*/
-#define EEPROM_NODE_ADDRESS_BYTE_0 0
-#define EEPROM_PBA_BYTE_1          8
-
-/* EEPROM Map Sizes (Byte Counts) */
-#define PBA_SIZE 4
-
-/* Collision related configuration parameters */
-#define E1000_COLLISION_THRESHOLD       16
-#define E1000_CT_SHIFT                  4
-#define E1000_FDX_COLLISION_DISTANCE    64
-#define E1000_HDX_COLLISION_DISTANCE    64
-#define E1000_GB_HDX_COLLISION_DISTANCE 512
-#define E1000_COLD_SHIFT                12
-
-/* The number of Transmit and Receive Descriptors must be a multiple of 8 */
-#define REQ_TX_DESCRIPTOR_MULTIPLE  8
-#define REQ_RX_DESCRIPTOR_MULTIPLE  8
-
-/* Default values for the transmit IPG register */
-#define DEFAULT_82542_TIPG_IPGT        10
-#define DEFAULT_82543_TIPG_IPGT_FIBER  9
-#define DEFAULT_82543_TIPG_IPGT_COPPER 8
-
-#define E1000_TIPG_IPGT_MASK  0x000003FF
-#define E1000_TIPG_IPGR1_MASK 0x000FFC00
-#define E1000_TIPG_IPGR2_MASK 0x3FF00000
-
-#define DEFAULT_82542_TIPG_IPGR1 2
-#define DEFAULT_82543_TIPG_IPGR1 8
-#define E1000_TIPG_IPGR1_SHIFT  10
-
-#define DEFAULT_82542_TIPG_IPGR2 10
-#define DEFAULT_82543_TIPG_IPGR2 6
-#define E1000_TIPG_IPGR2_SHIFT  20
-
-#define E1000_TXDMAC_DPP 0x00000001
-
-/* PBA constants */
-#define E1000_PBA_16K 0x0010    /* 16KB, default TX allocation */
-#define E1000_PBA_24K 0x0018
-#define E1000_PBA_40K 0x0028
-#define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
-
-/* Flow Control Constants */
-#define FLOW_CONTROL_ADDRESS_LOW  0x00C28001
-#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
-#define FLOW_CONTROL_TYPE         0x8808
-
-/* The historical defaults for the flow control values are given below. */
-#define FC_DEFAULT_HI_THRESH        (0x8000)    /* 32KB */
-#define FC_DEFAULT_LO_THRESH        (0x4000)    /* 16KB */
-#define FC_DEFAULT_TX_TIMER         (0x100)     /* ~130 us */
-
-
-/* The number of bits that we need to shift right to move the "pause"
- * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field
- * in the TXCW register 
- */
-#define PAUSE_SHIFT 5
-
-/* The number of bits that we need to shift left to move the "SWDPIO"
- * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field
- * in the CTRL register 
- */
-#define SWDPIO_SHIFT 17
-
-/* The number of bits that we need to shift left to move the "SWDPIO_EXT"
- * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The
- * Extended CTRL register.
- * in the CTRL register 
- */
-#define SWDPIO__EXT_SHIFT 4
-
-/* The number of bits that we need to shift left to move the "ILOS"
- * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field
- * in the CTRL register 
- */
-#define ILOS_SHIFT  3
-
-
-#define RECEIVE_BUFFER_ALIGN_SIZE  (256)
-
-/* The number of milliseconds we wait for auto-negotiation to complete */
-#define LINK_UP_TIMEOUT             500
-
-#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
-
-/* The carrier extension symbol, as received by the NIC. */
-#define CARRIER_EXTENSION   0x0F
-
-/* TBI_ACCEPT macro definition:
- *
- * If Tbi Compatibility mode is turned-on, then we should accept frames with
- * receive errors if and only if:
- *      1) errors is equal to the CRC error bit.
- *      2) The last byte is a Carrier extension (0x0F).
- *      3) The frame length (as reported by Hardware) is greater than 64 (60
- *         if a VLAN tag was stripped from the frame.
- *      4) "    "     "      "   "       "   "        <= max_frame_size+1.
- *
- * This macro requires:
- *      adapter = a pointer to struct e1000_shared_adapter 
- *      special = the 16 bit special field of the RX descriptor with EOP set
- *      error = the 8 bit error field of the RX descriptor with EOP set
- *      length = the sum of all the length fields of the RX descriptors that
- *               make up the current frame
- *      last_byte = the last byte of the frame DMAed by the hardware
- *      max_frame_length = the maximum frame length we want to accept.
- *      min_frame_length = the minimum frame length we want to accept.
- *
- * This macro is a conditional that should be used in the interrupt 
- * handler's Rx processing routine when RxErrors have been detected.
- *
- * Typical use:
- *  ...
- *  if (TBI_ACCEPT) {
- *      accept_frame = TRUE;
- *      e1000_tbi_adjust_stats(adapter, MacAddress);
- *      frame_length--;
- *  } else {
- *      accept_frame = FALSE;
- *  }
- *  ...
- */
-
-#define TBI_ACCEPT(adapter, special, errors, length, last_byte) \
-    ((adapter)->tbi_compatibility_on && \
-     (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
-     ((last_byte) == CARRIER_EXTENSION) && \
-     ((length) <= ((adapter)->max_frame_size + 1)) && \
-     ((length) > ((special == 0x0000) ? \
-		  ((adapter)->min_frame_size) : \
-		  ((adapter)->min_frame_size - VLAN_TAG_SIZE))))
-
-
-#endif /* _E1000_MAC_H_ */
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/e1000/e1000_main.c	Sun Apr 14 12:16:57 2002
@@ -2,9 +2,8 @@
 
   This software program is available to you under a choice of one of two
   licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
   
   Recipient has requested a license and Intel Corporation ("Intel") is willing
   to grant a license for the software entitled Linux Base Driver for the
@@ -18,7 +17,7 @@
   "Recipient" means the party to whom Intel delivers this Software.
   
   "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
+  any operating system available under the GNU General Public License 2.0 or
   later.
   
   Copyright (c) 1999 - 2002 Intel Corporation.
@@ -51,10 +50,10 @@
   version of an operating system that has been distributed under the GNU
   General Public License 2.0 or later. This patent license shall apply to the
   combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
+  General Public License 2.0 or later if, at the time Intel provides the
   Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
   such combination to be covered by the Licensed Patents. The patent license
   shall not apply to any other combinations which include the Software. NO
   hardware per se is licensed hereunder.
@@ -76,11 +75,8 @@
 #include "e1000.h"
 
 char e1000_driver_name[] = "e1000";
-
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-
-char e1000_driver_version[] = "4.2.4-k2";
-
+char e1000_driver_version[] = "4.2.8";
 char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -100,6 +96,7 @@
 	{0x8086, 0x1008, 0x8086, 0x1107, 0, 0, 0},
 	{0x8086, 0x1009, 0x8086, 0x1109, 0, 0, 0},
 	{0x8086, 0x100C, 0x8086, 0x1112, 0, 0, 0},
+	{0x8086, 0x100E, 0x8086, 0x001E, 0, 0, 0},
 	/* Compaq Gigabit Ethernet Server Adapter */
 	{0x8086, 0x1000, 0x0E11, PCI_ANY_ID, 0, 0, 1},
 	{0x8086, 0x1001, 0x0E11, PCI_ANY_ID, 0, 0, 1},
@@ -116,6 +113,7 @@
 	{0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	/* required last entry */
 	{0,}
 };
@@ -132,6 +130,8 @@
 
 int e1000_up(struct e1000_adapter *adapter);
 void e1000_down(struct e1000_adapter *adapter);
+void e1000_reset(struct e1000_adapter *adapter);
+
 static int e1000_init_module(void);
 static void e1000_exit_module(void);
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -164,13 +164,17 @@
 static void e1000_clean_rx_irq(struct e1000_adapter *adapter);
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
-static void e1000_reset(struct e1000_adapter *adapter);
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
 static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
                                      struct e1000_rx_desc *rx_desc,
                                      struct sk_buff *skb);
 void e1000_enable_WOL(struct e1000_adapter *adapter);
+#ifdef NETIF_F_HW_VLAN_TX
+static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
+static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
+static void e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+#endif
 
 /* Exported from other modules */
 
@@ -192,6 +196,7 @@
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
 MODULE_LICENSE("Dual BSD/GPL");
+EXPORT_NO_SYMBOLS;
 
 /**
  * e1000_init_module - Driver Registration Routine
@@ -224,8 +229,6 @@
 e1000_exit_module(void)
 {
 	pci_unregister_driver(&e1000_driver);
-
-	return;
 }
 
 module_exit(e1000_exit_module);
@@ -249,8 +252,6 @@
 	e1000_configure_rx(adapter);
 	e1000_alloc_rx_buffers(adapter);
 
-	e1000_clear_hw_cntrs(&adapter->shared);
-
 	mod_timer(&adapter->watchdog_timer, jiffies);
 	e1000_irq_enable(adapter);
 
@@ -260,74 +261,41 @@
 void
 e1000_down(struct e1000_adapter *adapter)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
 	struct net_device *netdev = adapter->netdev;
 
 	e1000_irq_disable(adapter);
 	free_irq(netdev->irq, netdev);
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
+	adapter->link_speed = 0;
+	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	/* disable the transmit and receive units */
-
-	E1000_WRITE_REG(shared, RCTL, 0);
-	E1000_WRITE_REG(shared, TCTL, E1000_TCTL_PSP);
-
-	/* delay to allow PCI transactions to complete */
-
-	msec_delay(10);
-
+	e1000_reset(adapter);
 	e1000_clean_tx_ring(adapter);
 	e1000_clean_rx_ring(adapter);
-
-	e1000_reset(adapter);
 }
 
-static void
+void
 e1000_reset(struct e1000_adapter *adapter)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
-	uint32_t ctrl_ext;
-
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
 	 */
 
 	if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
-		E1000_WRITE_REG(shared, PBA, E1000_JUMBO_PBA);
+		E1000_WRITE_REG(&adapter->hw, PBA, E1000_JUMBO_PBA);
 	else
-		E1000_WRITE_REG(shared, PBA, E1000_DEFAULT_PBA);
-
-	/* 82542 2.0 needs MWI disabled while issuing a reset */
-
-	if(shared->mac_type == e1000_82542_rev2_0)
-		e1000_enter_82542_rst(adapter);
-
-	/* global reset */
-
-	E1000_WRITE_REG(shared, CTRL, E1000_CTRL_RST);
-	msec_delay(10);
-
-	/* EEPROM reload */
-
-	ctrl_ext = E1000_READ_REG(shared, CTRL_EXT);
-	ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-	E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext);
-	msec_delay(5);
-
-	if(shared->mac_type == e1000_82542_rev2_0)
-		e1000_leave_82542_rst(adapter);
+		E1000_WRITE_REG(&adapter->hw, PBA, E1000_DEFAULT_PBA);
 
-	shared->tbi_compatibility_on = FALSE;
-	shared->fc = shared->original_fc;
-
-	e1000_init_hw(shared);
+	adapter->hw.fc = adapter->hw.original_fc;
+	e1000_reset_hw(&adapter->hw);
+	e1000_init_hw(&adapter->hw);
+	e1000_reset_adaptive(&adapter->hw);
+	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
 
 	e1000_enable_WOL(adapter);
-
-	return;
 }
 
 /**
@@ -382,13 +350,13 @@
 	adapter = netdev->priv;
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
-	adapter->shared.back = adapter;
+	adapter->hw.back = adapter;
 
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
 
-	adapter->shared.hw_addr = ioremap(mmio_start, mmio_len);
-	if(!adapter->shared.hw_addr)
+	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
+	if(!adapter->hw.hw_addr)
 		goto err_ioremap;
 
 	netdev->open = &e1000_open;
@@ -401,6 +369,11 @@
 	netdev->do_ioctl = &e1000_ioctl;
 	netdev->tx_timeout = &e1000_tx_timeout;
 	netdev->watchdog_timeo = HZ;
+#ifdef NETIF_F_HW_VLAN_TX
+	netdev->vlan_rx_register = e1000_vlan_rx_register;
+	netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
+	netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
+#endif
 
 	netdev->irq = pdev->irq;
 	netdev->base_addr = mmio_start;
@@ -412,8 +385,16 @@
 
 	e1000_sw_init(adapter);
 
-	if(adapter->shared.mac_type >= e1000_82543) {
+	if(adapter->hw.mac_type >= e1000_82543) {
+#ifdef NETIF_F_HW_VLAN_TX
+		netdev->features = NETIF_F_SG |
+			           NETIF_F_HW_CSUM |
+		       	           NETIF_F_HW_VLAN_TX |
+		                   NETIF_F_HW_VLAN_RX |
+				   NETIF_F_HW_VLAN_FILTER;
+#else
 		netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM;
+#endif
 	} else {
 		netdev->features = NETIF_F_SG;
 	}
@@ -423,19 +404,28 @@
 
 	/* make sure the EEPROM is good */
 
-	if(!e1000_validate_eeprom_checksum(&adapter->shared))
+	if(e1000_validate_eeprom_checksum(&adapter->hw) < 0)
 		goto err_eeprom;
 
 	/* copy the MAC address out of the EEPROM */
 
-	e1000_read_mac_addr(&adapter->shared);
-	memcpy(netdev->dev_addr, adapter->shared.mac_addr, netdev->addr_len);
+	e1000_read_mac_addr(&adapter->hw);
+	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
 
 	if(!is_valid_ether_addr(netdev->dev_addr))
 		goto err_eeprom;
 
-	e1000_read_part_num(&adapter->shared, &(adapter->part_num));
-	e1000_get_bus_info(&adapter->shared);
+	e1000_read_part_num(&adapter->hw, &(adapter->part_num));
+
+	e1000_get_bus_info(&adapter->hw);
+
+	if((adapter->hw.mac_type == e1000_82544) &&
+	   (adapter->hw.bus_type == e1000_bus_type_pcix))
+
+		adapter->max_data_per_txd = 4096;
+	else
+		adapter->max_data_per_txd = MAX_JUMBO_FRAME_SIZE;
+
 
 	init_timer(&adapter->watchdog_timer);
 	adapter->watchdog_timer.function = &e1000_watchdog;
@@ -464,7 +454,7 @@
 	return 0;
 
 err_eeprom:
-	iounmap(adapter->shared.hw_addr);
+	iounmap(adapter->hw.hw_addr);
 err_ioremap:
 	pci_release_regions(pdev);
 	kfree(netdev);
@@ -480,10 +470,6 @@
  * that it should release a PCI device.  The could be caused by a
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
- *
- * This routine is also called to clean up from a failure in
- * e1000_probe.  The Adapter struct and netdev will always exist,
- * all other pointers must be checked for NULL before freeing.
  **/
 
 static void __devexit
@@ -494,15 +480,14 @@
 
 	unregister_netdev(netdev);
 
-	e1000_phy_hw_reset(&adapter->shared);
+	e1000_phy_hw_reset(&adapter->hw);
 
 	e1000_proc_dev_free(adapter);
 
-	iounmap(adapter->shared.hw_addr);
+	iounmap(adapter->hw.hw_addr);
 	pci_release_regions(pdev);
 
 	kfree(netdev);
-	return;
 }
 
 /**
@@ -517,17 +502,17 @@
 static void __devinit
 e1000_sw_init(struct e1000_adapter *adapter)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 
 	/* PCI config space info */
 
-	uint16_t *vendor = &shared->vendor_id;
-	uint16_t *device = &shared->device_id;
-	uint16_t *subvendor = &shared->subsystem_vendor_id;
-	uint16_t *subsystem = &shared->subsystem_id;
-	uint8_t  *revision  = &shared->revision_id;
+	uint16_t *vendor = &hw->vendor_id;
+	uint16_t *device = &hw->device_id;
+	uint16_t *subvendor = &hw->subsystem_vendor_id;
+	uint16_t *subsystem = &hw->subsystem_id;
+	uint8_t  *revision  = &hw->revision_id;
 
 	pci_read_config_word(pdev, PCI_VENDOR_ID, vendor);
 	pci_read_config_word(pdev, PCI_DEVICE_ID, device);
@@ -535,11 +520,12 @@
 	pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, subvendor);
 	pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, subsystem);
 
-	pci_read_config_word(pdev, PCI_COMMAND, &shared->pci_cmd_word);
+	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
 	adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-	shared->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + CRC_LENGTH;
-	shared->min_frame_size = MINIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH;
+	hw->max_frame_size = netdev->mtu +
+	                         ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
+	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
 
 	/* identify the MAC */
 
@@ -547,25 +533,28 @@
 	case E1000_DEV_ID_82542:
 		switch (*revision) {
 		case E1000_82542_2_0_REV_ID:
-			shared->mac_type = e1000_82542_rev2_0;
+			hw->mac_type = e1000_82542_rev2_0;
 			break;
 		case E1000_82542_2_1_REV_ID:
-			shared->mac_type = e1000_82542_rev2_1;
+			hw->mac_type = e1000_82542_rev2_1;
 			break;
 		default:
-			shared->mac_type = e1000_82542_rev2_0;
+			hw->mac_type = e1000_82542_rev2_0;
 			E1000_ERR("Could not identify 82542 revision\n");
 		}
 		break;
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
-		shared->mac_type = e1000_82543;
+		hw->mac_type = e1000_82543;
 		break;
 	case E1000_DEV_ID_82544EI_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
 	case E1000_DEV_ID_82544GC_COPPER:
 	case E1000_DEV_ID_82544GC_LOM:
-		shared->mac_type = e1000_82544;
+		hw->mac_type = e1000_82544;
+		break;
+	case E1000_DEV_ID_82540EM:
+		hw->mac_type = e1000_82540;
 		break;
 	default:
 		/* should never have loaded on this device */
@@ -574,33 +563,35 @@
 
 	/* flow control settings */
 
-	shared->fc_high_water = FC_DEFAULT_HI_THRESH;
-	shared->fc_low_water = FC_DEFAULT_LO_THRESH;
-	shared->fc_pause_time = FC_DEFAULT_TX_TIMER;
-	shared->fc_send_xon = 1;
+	hw->fc_high_water = FC_DEFAULT_HI_THRESH;
+	hw->fc_low_water = FC_DEFAULT_LO_THRESH;
+	hw->fc_pause_time = FC_DEFAULT_TX_TIMER;
+	hw->fc_send_xon = 1;
 
 	/* Media type - copper or fiber */
 
-	if(shared->mac_type >= e1000_82543) {
-		uint32_t status = E1000_READ_REG(shared, STATUS);
+	if(hw->mac_type >= e1000_82543) {
+		uint32_t status = E1000_READ_REG(hw, STATUS);
 
 		if(status & E1000_STATUS_TBIMODE)
-			shared->media_type = e1000_media_type_fiber;
+			hw->media_type = e1000_media_type_fiber;
 		else
-			shared->media_type = e1000_media_type_copper;
+			hw->media_type = e1000_media_type_copper;
 	} else {
-		shared->media_type = e1000_media_type_fiber;
+		hw->media_type = e1000_media_type_fiber;
 	}
 
-	if(shared->mac_type < e1000_82543)
-		shared->report_tx_early = 0;
+	if(hw->mac_type < e1000_82543)
+		hw->report_tx_early = 0;
 	else
-		shared->report_tx_early = 1;
+		hw->report_tx_early = 1;
 
-	shared->wait_autoneg_complete = FALSE;
-	shared->tbi_compatibility_en = TRUE;
+	hw->wait_autoneg_complete = FALSE;
+	hw->tbi_compatibility_en = TRUE;
+	hw->adaptive_ifs = TRUE;
 
 	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->tx_lock);
 	spin_lock_init(&adapter->stats_lock);
 }
 
@@ -677,9 +668,6 @@
  * @adapter: board private structure
  *
  * Return 0 on success, negative on failure
- *
- * e1000_setup_tx_resources allocates all software transmit resources
- * and enabled the Tx unit of the MAC.
  **/
 
 static int
@@ -708,7 +696,6 @@
 	}
 	memset(txdr->desc, 0, txdr->size);
 
-	atomic_set(&txdr->unused, txdr->count);
 	txdr->next_to_use = 0;
 	txdr->next_to_clean = 0;
 
@@ -729,19 +716,19 @@
 	uint32_t tdlen = adapter->tx_ring.count * sizeof(struct e1000_tx_desc);
 	uint32_t tctl, tipg;
 
-	E1000_WRITE_REG(&adapter->shared, TDBAL, (tdba & 0x00000000FFFFFFFF));
-	E1000_WRITE_REG(&adapter->shared, TDBAH, (tdba >> 32));
+	E1000_WRITE_REG(&adapter->hw, TDBAL, (tdba & 0x00000000FFFFFFFF));
+	E1000_WRITE_REG(&adapter->hw, TDBAH, (tdba >> 32));
 
-	E1000_WRITE_REG(&adapter->shared, TDLEN, tdlen);
+	E1000_WRITE_REG(&adapter->hw, TDLEN, tdlen);
 
 	/* Setup the HW Tx Head and Tail descriptor pointers */
 
-	E1000_WRITE_REG(&adapter->shared, TDH, 0);
-	E1000_WRITE_REG(&adapter->shared, TDT, 0);
+	E1000_WRITE_REG(&adapter->hw, TDH, 0);
+	E1000_WRITE_REG(&adapter->hw, TDT, 0);
 
 	/* Set the default values for the Tx Inter Packet Gap timer */
 
-	switch (adapter->shared.mac_type) {
+	switch (adapter->hw.mac_type) {
 	case e1000_82542_rev2_0:
 	case e1000_82542_rev2_1:
 		tipg = DEFAULT_82542_TIPG_IPGT;
@@ -749,53 +736,45 @@
 		tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
 		break;
 	default:
-		if(adapter->shared.media_type == e1000_media_type_fiber)
+		if(adapter->hw.media_type == e1000_media_type_fiber)
 			tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
 		else
 			tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
 		tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
 		tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
 	}
-	E1000_WRITE_REG(&adapter->shared, TIPG, tipg);
+	E1000_WRITE_REG(&adapter->hw, TIPG, tipg);
 
 	/* Set the Tx Interrupt Delay register */
 
-	E1000_WRITE_REG(&adapter->shared, TIDV, adapter->tx_int_delay);
+	E1000_WRITE_REG(&adapter->hw, TIDV, 64);
 
 	/* Program the Transmit Control Register */
 
-	tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
+	tctl = E1000_READ_REG(&adapter->hw, TCTL);
+
+	tctl &= ~E1000_TCTL_CT;	
+	tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
 	       (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
 
-	if(adapter->link_duplex == FULL_DUPLEX) {
-		tctl |= E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
-	} else {
-		tctl |= E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT;
-	}
+	E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
 
-	E1000_WRITE_REG(&adapter->shared, TCTL, tctl);
+	e1000_config_collision_dist(&adapter->hw);
 
 	/* Setup Transmit Descriptor Settings for this adapter */
-	adapter->txd_cmd = E1000_TXD_CMD_IFCS;
+	adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE;
 
-	if(adapter->tx_int_delay > 0)
-		adapter->txd_cmd |= E1000_TXD_CMD_IDE;
-	if(adapter->shared.report_tx_early == 1)
+	if(adapter->hw.report_tx_early == 1)
 		adapter->txd_cmd |= E1000_TXD_CMD_RS;
 	else
 		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
-
-	return;
 }
 
 /**
- * e1000_setup_rx_resources - allocate Rx resources (Descriptors, receive SKBs)
+ * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
  * @adapter: board private structure
  *
  * Returns 0 on success, negative on failure
- *
- * e1000_setup_rx_resources allocates all software receive resources
- * and network buffers, and enables the Rx unit of the MAC.
  **/
 
 static int
@@ -826,7 +805,6 @@
 	memset(rxdr->desc, 0, rxdr->size);
 
 	rxdr->next_to_clean = 0;
-	rxdr->unused_count = rxdr->count;
 	rxdr->next_to_use = 0;
 
 	return 0;
@@ -842,18 +820,25 @@
 {
 	uint32_t rctl;
 
-	/* Setup the Receive Control Register */
-	rctl = E1000_RCTL_EN | E1000_RCTL_BAM |
-	       E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-	       (adapter->shared.mc_filter_type << E1000_RCTL_MO_SHIFT);
+	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+
+	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
 
-	if(adapter->shared.tbi_compatibility_on == 1)
+	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
+	        E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+	        (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+
+	if(adapter->hw.tbi_compatibility_on == 1)
 		rctl |= E1000_RCTL_SBP;
+	else
+		rctl &= ~E1000_RCTL_SBP;
 
+	rctl &= ~(E1000_RCTL_SZ_4096);
 	switch (adapter->rx_buffer_len) {
 	case E1000_RXBUFFER_2048:
 	default:
 		rctl |= E1000_RCTL_SZ_2048;
+		rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE);
 		break;
 	case E1000_RXBUFFER_4096:
 		rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
@@ -866,7 +851,7 @@
 		break;
 	}
 
-	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
 
 /**
@@ -886,38 +871,47 @@
 
 	/* make sure receives are disabled while setting up the descriptors */
 
-	rctl = E1000_READ_REG(&adapter->shared, RCTL);
-	E1000_WRITE_REG(&adapter->shared, RCTL, rctl & ~E1000_RCTL_EN);
+	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
 
 	/* set the Receive Delay Timer Register */
 
-	E1000_WRITE_REG(&adapter->shared, RDTR,
-	                adapter->rx_int_delay | E1000_RDT_FPDB);
+	if(adapter->hw.mac_type == e1000_82540) {
+		E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_int_delay);
+		E1000_WRITE_REG(&adapter->hw, RDTR, 64);
+
+		/* Set the interrupt throttling rate.  Value is calculated
+		 * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */
+#define MAX_INTS_PER_SEC        8000
+#define DEFAULT_ITR             1000000000/(MAX_INTS_PER_SEC * 256)
+		E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR);
+
+	} else {
+		E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
+	}
 
 	/* Setup the Base and Length of the Rx Descriptor Ring */
 
-	E1000_WRITE_REG(&adapter->shared, RDBAL, (rdba & 0x00000000FFFFFFFF));
-	E1000_WRITE_REG(&adapter->shared, RDBAH, (rdba >> 32));
+	E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000FFFFFFFF));
+	E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
 
-	E1000_WRITE_REG(&adapter->shared, RDLEN, rdlen);
+	E1000_WRITE_REG(&adapter->hw, RDLEN, rdlen);
 
 	/* Setup the HW Rx Head and Tail Descriptor Pointers */
-	E1000_WRITE_REG(&adapter->shared, RDH, 0);
-	E1000_WRITE_REG(&adapter->shared, RDT, 0);
+	E1000_WRITE_REG(&adapter->hw, RDH, 0);
+	E1000_WRITE_REG(&adapter->hw, RDT, 0);
 
 	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
-	if((adapter->shared.mac_type >= e1000_82543) &&
+	if((adapter->hw.mac_type >= e1000_82543) &&
 	   (adapter->rx_csum == TRUE)) {
-		rxcsum = E1000_READ_REG(&adapter->shared, RXCSUM);
+		rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
 		rxcsum |= E1000_RXCSUM_TUOFL;
-		E1000_WRITE_REG(&adapter->shared, RXCSUM, rxcsum);
+		E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
 	}
 
 	/* Enable Receives */
 
-	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
-
-	return;
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
 
 /**
@@ -941,8 +935,6 @@
 	                    adapter->tx_ring.desc, adapter->tx_ring.dma);
 
 	adapter->tx_ring.desc = NULL;
-
-	return;
 }
 
 /**
@@ -980,14 +972,11 @@
 
 	memset(adapter->tx_ring.desc, 0, adapter->tx_ring.size);
 
-	atomic_set(&adapter->tx_ring.unused, adapter->tx_ring.count);
 	adapter->tx_ring.next_to_use = 0;
 	adapter->tx_ring.next_to_clean = 0;
 
-	E1000_WRITE_REG(&adapter->shared, TDH, 0);
-	E1000_WRITE_REG(&adapter->shared, TDT, 0);
-
-	return;
+	E1000_WRITE_REG(&adapter->hw, TDH, 0);
+	E1000_WRITE_REG(&adapter->hw, TDT, 0);
 }
 
 /**
@@ -1011,8 +1000,6 @@
 	                    adapter->rx_ring.desc, adapter->rx_ring.dma);
 
 	adapter->rx_ring.desc = NULL;
-
-	return;
 }
 
 /**
@@ -1050,14 +1037,11 @@
 
 	memset(adapter->rx_ring.desc, 0, adapter->rx_ring.size);
 
-	adapter->rx_ring.unused_count = adapter->rx_ring.count;
 	adapter->rx_ring.next_to_clean = 0;
 	adapter->rx_ring.next_to_use = 0;
 
-	E1000_WRITE_REG(&adapter->shared, RDH, 0);
-	E1000_WRITE_REG(&adapter->shared, RDT, 0);
-
-	return;
+	E1000_WRITE_REG(&adapter->hw, RDH, 0);
+	E1000_WRITE_REG(&adapter->hw, RDT, 0);
 }
 
 /* The 82542 2.0 (revision 2) needs to have the receive unit in reset
@@ -1068,7 +1052,7 @@
 {
 	struct pci_dev *pdev = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
-	uint16_t pci_command_word = adapter->shared.pci_cmd_word;
+	uint16_t pci_command_word = adapter->hw.pci_cmd_word;
 	uint32_t rctl;
 
 	if(pci_command_word & PCI_COMMAND_INVALIDATE) {
@@ -1076,14 +1060,13 @@
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command_word);
 	}
 
-	rctl = E1000_READ_REG(&adapter->shared, RCTL);
+	rctl = E1000_READ_REG(&adapter->hw, RCTL);
 	rctl |= E1000_RCTL_RST;
-	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 	msec_delay(5);
 
 	if(netif_running(netdev))
 		e1000_clean_rx_ring(adapter);
-	return;
 }
 
 static void
@@ -1091,12 +1074,12 @@
 {
 	struct pci_dev *pdev = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
-	uint16_t pci_command_word = adapter->shared.pci_cmd_word;
+	uint16_t pci_command_word = adapter->hw.pci_cmd_word;
 	uint32_t rctl;
 
-	rctl = E1000_READ_REG(&adapter->shared, RCTL);
+	rctl = E1000_READ_REG(&adapter->hw, RCTL);
 	rctl &= ~E1000_RCTL_RST;
-	E1000_WRITE_REG(&adapter->shared, RCTL, rctl);
+	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 	msec_delay(5);
 
 	if(pci_command_word & PCI_COMMAND_INVALIDATE)
@@ -1106,7 +1089,6 @@
 		e1000_configure_rx(adapter);
 		e1000_alloc_rx_buffers(adapter);
 	}
-	return;
 }
 
 /**
@@ -1125,15 +1107,15 @@
 
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
-	if(adapter->shared.mac_type == e1000_82542_rev2_0)
+	if(adapter->hw.mac_type == e1000_82542_rev2_0)
 		e1000_enter_82542_rst(adapter);
 
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->shared.mac_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
 
-	e1000_rar_set(&adapter->shared, adapter->shared.mac_addr, 0);
+	e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
 
-	if(adapter->shared.mac_type == e1000_82542_rev2_0)
+	if(adapter->hw.mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
 
 	return 0;
@@ -1153,7 +1135,7 @@
 e1000_set_multi(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev->priv;
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 	struct dev_mc_list *mc_ptr;
 	uint32_t rctl;
 	uint32_t hash_value;
@@ -1161,7 +1143,7 @@
 
 	/* Check for Promiscuous and All Multicast modes */
 
-	rctl = E1000_READ_REG(shared, RCTL);
+	rctl = E1000_READ_REG(hw, RCTL);
 
 	if(netdev->flags & IFF_PROMISC) {
 		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
@@ -1172,11 +1154,11 @@
 		rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
 	}
 
-	E1000_WRITE_REG(shared, RCTL, rctl);
+	E1000_WRITE_REG(hw, RCTL, rctl);
 
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
-	if(shared->mac_type == e1000_82542_rev2_0)
+	if(hw->mac_type == e1000_82542_rev2_0)
 		e1000_enter_82542_rst(adapter);
 
 	/* load the first 15 multicast address into the exact filters 1-15
@@ -1187,29 +1169,28 @@
 
 	for(i = 1; i < E1000_RAR_ENTRIES; i++) {
 		if(mc_ptr) {
-			e1000_rar_set(shared, mc_ptr->dmi_addr, i);
+			e1000_rar_set(hw, mc_ptr->dmi_addr, i);
 			mc_ptr = mc_ptr->next;
 		} else {
-			E1000_WRITE_REG_ARRAY(shared, RA, i << 1, 0);
-			E1000_WRITE_REG_ARRAY(shared, RA, (i << 1) + 1, 0);
+			E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
+			E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
 		}
 	}
 
 	/* clear the old settings from the multicast hash table */
 
 	for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
-		E1000_WRITE_REG_ARRAY(shared, MTA, i, 0);
+		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
 
 	/* load any remaining addresses into the hash table */
 
 	for(; mc_ptr; mc_ptr = mc_ptr->next) {
-		hash_value = e1000_hash_mc_addr(shared, mc_ptr->dmi_addr);
-		e1000_mta_set(shared, hash_value);
+		hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		e1000_mta_set(hw, hash_value);
 	}
 
-	if(shared->mac_type == e1000_82542_rev2_0)
+	if(hw->mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
-	return;
 }
 
 
@@ -1219,8 +1200,7 @@
 e1000_update_phy_info(unsigned long data)
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-	e1000_phy_get_info(&adapter->shared, &adapter->phy_info);
-	return;
+	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
 }
 
 /**
@@ -1234,11 +1214,11 @@
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
 	struct net_device *netdev = adapter->netdev;
 
-	e1000_check_for_link(&adapter->shared);
+	e1000_check_for_link(&adapter->hw);
 
-	if(E1000_READ_REG(&adapter->shared, STATUS) & E1000_STATUS_LU) {
+	if(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
 		if(!netif_carrier_ok(netdev)) {
-			e1000_get_speed_and_duplex(&adapter->shared,
+			e1000_get_speed_and_duplex(&adapter->hw,
 			                           &adapter->link_speed,
 			                           &adapter->link_duplex);
 
@@ -1262,171 +1242,203 @@
 			       netdev->name);
 			netif_carrier_off(netdev);
 			netif_stop_queue(netdev);
+			mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
 		}
 	}
 
 	e1000_update_stats(adapter);
+	e1000_update_adaptive(&adapter->hw);
 
 	/* Reset the timer */
 	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-
-	return;
 }
 
-/**
- * e1000_xmit_frame - Transmit entry point
- * @skb: buffer with frame data to transmit
- * @netdev: network interface device structure
- *
- * Returns 0 on success, 1 on error
- *
- * e1000_xmit_frame is called by the stack to initiate a transmit.
- * The out of resource condition is checked after each successful Tx
- * so that the stack can be notified, preventing the driver from
- * ever needing to drop a frame.  The atomic operations on
- * tx_ring.unused are used to syncronize with the transmit
- * interrupt processing code without the need for a spinlock.
- **/
-
-#define TXD_USE_COUNT(x) (((x) >> 12) + ((x) & 0x0fff ? 1 : 0))
-
-#define SETUP_TXD_PAGE(L, P, O) do { \
-	tx_ring->buffer_info[i].length = (L); \
-	tx_ring->buffer_info[i].dma = \
-		pci_map_page(pdev, (P), (O), (L), PCI_DMA_TODEVICE); \
-	tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); \
-	tx_desc->lower.data = cpu_to_le32(txd_lower | (L)); \
-	tx_desc->upper.data = cpu_to_le32(txd_upper); \
-} while (0)
+#define E1000_TX_FLAGS_CSUM		0x00000001
+#define E1000_TX_FLAGS_VLAN		0x00000002
+#define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
+#define E1000_TX_FLAGS_VLAN_SHIFT	16
 
-#define SETUP_TXD_PTR(L, P) \
-	SETUP_TXD_PAGE((L), virt_to_page(P), (unsigned long)(P) & ~PAGE_MASK)
+static inline boolean_t
+e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
+{
+	struct e1000_context_desc *context_desc;
+	int i;
+	uint8_t css, cso;
 
-#define QUEUE_TXD() do { i = (i + 1) % tx_ring->count; \
-                         atomic_dec(&tx_ring->unused); } while (0)
+	if(skb->ip_summed == CHECKSUM_HW) {
+		css = skb->h.raw - skb->data;
+		cso = (skb->h.raw + skb->csum) - skb->data;
 
+		i = adapter->tx_ring.next_to_use;
+		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
 
-static int
-e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+		context_desc->upper_setup.tcp_fields.tucss = css;
+		context_desc->upper_setup.tcp_fields.tucso = cso;
+		context_desc->upper_setup.tcp_fields.tucse = 0;
+		context_desc->tcp_seg_setup.data = 0;
+		context_desc->cmd_and_length =
+			cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT);
+
+		i = (i + 1) % adapter->tx_ring.count;
+		adapter->tx_ring.next_to_use = i;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static inline int
+e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
-	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
-	struct pci_dev *pdev = adapter->pdev;
-	struct e1000_tx_desc *tx_desc;
-	int f, len, offset, txd_needed;
-	skb_frag_t *frag;
+	int len, offset, size, count, i;
 
-	int i = tx_ring->next_to_use;
-	uint32_t txd_upper = 0;
-	uint32_t txd_lower = adapter->txd_cmd;
+	int f;
+	len = skb->len - skb->data_len;
 
+	i = (tx_ring->next_to_use + tx_ring->count - 1) % tx_ring->count;
+	count = 0;
 
-	/* If controller appears hung, force transmit timeout */
+	offset = 0;
 
-	if (time_after(netdev->trans_start, adapter->trans_finish + HZ) &&
-	    /* If transmitting XOFFs, we're not really hung */
-	    !(E1000_READ_REG(&adapter->shared, STATUS) & E1000_STATUS_TXOFF)) {
-		adapter->trans_finish = jiffies;
-		netif_stop_queue(netdev);
-		return 1;
+	while(len) {
+		i = (i + 1) % tx_ring->count;
+		size = min(len, adapter->max_data_per_txd);
+		tx_ring->buffer_info[i].length = size;
+		tx_ring->buffer_info[i].dma =
+			pci_map_single(adapter->pdev,
+				skb->data + offset,
+				size,
+				PCI_DMA_TODEVICE);
+
+		len -= size;
+		offset += size;
+		count++;
 	}
 
-	txd_needed = TXD_USE_COUNT(skb->len - skb->data_len);
-
 	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
-		frag = &skb_shinfo(skb)->frags[f];
-		txd_needed += TXD_USE_COUNT(frag->size);
-	}
+		struct skb_frag_struct *frag;
 
-	if(skb->ip_summed == CHECKSUM_HW)
-		txd_needed += 1;
-
-	/* make sure there are enough Tx descriptors available in the ring */
+		frag = &skb_shinfo(skb)->frags[f];
+		len = frag->size;
+		offset = 0;
 
-	if(atomic_read(&tx_ring->unused) <= (txd_needed + 1)) {
-		adapter->net_stats.tx_dropped++;
-		netif_stop_queue(netdev);
-		return 1;
+		while(len) {
+			i = (i + 1) % tx_ring->count;
+			size = min(len, adapter->max_data_per_txd);
+			tx_ring->buffer_info[i].length = size;
+			tx_ring->buffer_info[i].dma =
+				pci_map_page(adapter->pdev,
+					frag->page,
+					frag->page_offset + offset,
+					size,
+					PCI_DMA_TODEVICE);
+
+			len -= size;
+			offset += size;
+			count++;
+		}
 	}
+	tx_ring->buffer_info[i].skb = skb;
 
-	if(skb->ip_summed == CHECKSUM_HW) {
-		struct e1000_context_desc *context_desc;
-		uint8_t css = skb->h.raw - skb->data;
-		uint8_t cso = (skb->h.raw + skb->csum) - skb->data;
-
-		context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+	return count;
+}
 
-		context_desc->upper_setup.tcp_fields.tucss = css;
-		context_desc->upper_setup.tcp_fields.tucso = cso;
-		context_desc->upper_setup.tcp_fields.tucse = 0;
-		context_desc->tcp_seg_setup.data = 0;
-		context_desc->cmd_and_length =
-			cpu_to_le32(txd_lower | E1000_TXD_CMD_DEXT);
+static inline void
+e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
+{
+	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
+	struct e1000_tx_desc *tx_desc = NULL;
+	uint32_t txd_upper, txd_lower;
+	int i;
 
-		QUEUE_TXD();
+	txd_upper = 0;
+	txd_lower = adapter->txd_cmd;
 
-		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+	if(tx_flags & E1000_TX_FLAGS_CSUM) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
+		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
 	}
 
-	tx_desc = E1000_TX_DESC(*tx_ring, i);
-	len = skb->len - skb->data_len;
-	offset = 0;
+	if(tx_flags & E1000_TX_FLAGS_VLAN) {
+		txd_lower |= E1000_TXD_CMD_VLE;
+		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
+	}
 
-	while(len > 4096) {
-		SETUP_TXD_PTR(4096, skb->data + offset);
-		QUEUE_TXD();
+	i = tx_ring->next_to_use;
 
+	while(count--) {
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
-		len -= 4096;
-		offset += 4096;
+		tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma);
+		tx_desc->lower.data =
+			cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length);
+		tx_desc->upper.data = cpu_to_le32(txd_upper);
+		i = (i + 1) % tx_ring->count;
 	}
 
-	SETUP_TXD_PTR(len, skb->data + offset);
+	tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
 
-	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
-		frag = &skb_shinfo(skb)->frags[f];
+	tx_ring->next_to_use = i;
+	E1000_WRITE_REG(&adapter->hw, TDT, i);
+}
 
-		QUEUE_TXD();
+#define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0))
 
-		tx_desc = E1000_TX_DESC(*tx_ring, i);
-		len = frag->size;
-		offset = 0;
+static int
+e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	unsigned long flags;
+	int tx_flags = 0, count;
 
-		while(len > 4096) {
-			SETUP_TXD_PAGE(4096, frag->page,
-			               frag->page_offset + offset);
-			QUEUE_TXD();
-
-			tx_desc = E1000_TX_DESC(*tx_ring, i);
-			len -= 4096;
-			offset += 4096;
-		}
-		SETUP_TXD_PAGE(len, frag->page, frag->page_offset + offset);
-	}
+	int f;
 
-	/* EOP and SKB pointer go with the last fragment */
 
-	tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP);
-	tx_ring->buffer_info[i].skb = skb;
+	if(time_after(netdev->trans_start, adapter->trans_finish + HZ) &&
+	   !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) {
 
-	QUEUE_TXD();
+		adapter->trans_finish = jiffies;
+		netif_stop_queue(netdev);
+		return 1;
+	}
 
-	tx_ring->next_to_use = i;
+	count = TXD_USE_COUNT(skb->len - skb->data_len,
+	                      adapter->max_data_per_txd);
+	for(f = 0; f < skb_shinfo(skb)->nr_frags; f++)
+		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
+		                       adapter->max_data_per_txd);
+	if(skb->ip_summed == CHECKSUM_HW)
+		count++;
 
-	/* Move the HW Tx Tail Pointer */
+	spin_lock_irqsave(&adapter->tx_lock, flags);
+	e1000_clean_tx_irq(adapter);
+	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) {
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		return 1;
+	}
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 
-	E1000_WRITE_REG(&adapter->shared, TDT, i);
+	if(e1000_tx_csum(adapter, skb))
+		tx_flags |= E1000_TX_FLAGS_CSUM;
+
+#ifdef NETIF_F_HW_VLAN_TX
+	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
+		tx_flags |= E1000_TX_FLAGS_VLAN;
+		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
+	}
+#endif
+	
+	count = e1000_tx_map(adapter, skb);
+
+	e1000_tx_queue(adapter, count, tx_flags);
 
 	netdev->trans_start = jiffies;
 
 	return 0;
 }
 
-#undef TXD_USE_COUNT
-#undef SETUP_TXD
-#undef QUEUE_TXD
-
 /**
  * e1000_tx_timeout - Respond to a Tx Hang
  * @netdev: network interface device structure
@@ -1470,24 +1482,21 @@
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	int old_mtu = adapter->rx_buffer_len;
-	int max_frame = new_mtu + ENET_HEADER_SIZE + CRC_LENGTH;
+	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
 
-	if((max_frame < MINIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH) ||
-	   (max_frame > MAX_JUMBO_FRAME_SIZE + CRC_LENGTH)) {
+	if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+	   (max_frame > MAX_JUMBO_FRAME_SIZE)) {
 		E1000_ERR("Invalid MTU setting\n");
 		return -EINVAL;
 	}
 
-	if(max_frame <= MAXIMUM_ETHERNET_PACKET_SIZE + CRC_LENGTH) {
+	if(max_frame <= E1000_RXBUFFER_2048) {
 		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
 
-	} else if(adapter->shared.mac_type < e1000_82543) {
+	} else if(adapter->hw.mac_type < e1000_82543) {
 		E1000_ERR("Jumbo Frames not supported on 82542\n");
 		return -EINVAL;
 
-	} else if(max_frame <= E1000_RXBUFFER_2048) {
-		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-
 	} else if(max_frame <= E1000_RXBUFFER_4096) {
 		adapter->rx_buffer_len = E1000_RXBUFFER_4096;
 
@@ -1501,13 +1510,11 @@
 	if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
 
 		e1000_down(adapter);
-		e1000_clean_rx_ring(adapter);
-		e1000_clean_tx_ring(adapter);
 		e1000_up(adapter);
 	}
 
 	netdev->mtu = new_mtu;
-	adapter->shared.max_frame_size = max_frame;
+	adapter->hw.max_frame_size = max_frame;
 
 	return 0;
 }
@@ -1520,8 +1527,9 @@
 static void
 e1000_update_stats(struct e1000_adapter *adapter)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 	unsigned long flags;
+	uint16_t phy_tmp;
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
@@ -1532,68 +1540,73 @@
 	 * be written while holding adapter->stats_lock
 	 */
 
-	adapter->stats.crcerrs += E1000_READ_REG(shared, CRCERRS);
-	adapter->stats.gprc += E1000_READ_REG(shared, GPRC);
-	adapter->stats.gorcl += E1000_READ_REG(shared, GORCL);
-	adapter->stats.gorch += E1000_READ_REG(shared, GORCH);
-	adapter->stats.bprc += E1000_READ_REG(shared, BPRC);
-	adapter->stats.mprc += E1000_READ_REG(shared, MPRC);
-	adapter->stats.roc += E1000_READ_REG(shared, ROC);
-	adapter->stats.prc64 += E1000_READ_REG(shared, PRC64);
-	adapter->stats.prc127 += E1000_READ_REG(shared, PRC127);
-	adapter->stats.prc255 += E1000_READ_REG(shared, PRC255);
-	adapter->stats.prc511 += E1000_READ_REG(shared, PRC511);
-	adapter->stats.prc1023 += E1000_READ_REG(shared, PRC1023);
-	adapter->stats.prc1522 += E1000_READ_REG(shared, PRC1522);
+	adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
+	adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
+	adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
+	adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
+	adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
+	adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
+	adapter->stats.roc += E1000_READ_REG(hw, ROC);
+	adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
+	adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
+	adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
+	adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
+	adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
+	adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
 
 	spin_unlock_irqrestore(&adapter->stats_lock, flags);
 
 	/* the rest of the counters are only modified here */
 
-	adapter->stats.symerrs += E1000_READ_REG(shared, SYMERRS);
-	adapter->stats.mpc += E1000_READ_REG(shared, MPC);
-	adapter->stats.scc += E1000_READ_REG(shared, SCC);
-	adapter->stats.ecol += E1000_READ_REG(shared, ECOL);
-	adapter->stats.mcc += E1000_READ_REG(shared, MCC);
-	adapter->stats.latecol += E1000_READ_REG(shared, LATECOL);
-	adapter->stats.colc += E1000_READ_REG(shared, COLC);
-	adapter->stats.dc += E1000_READ_REG(shared, DC);
-	adapter->stats.sec += E1000_READ_REG(shared, SEC);
-	adapter->stats.rlec += E1000_READ_REG(shared, RLEC);
-	adapter->stats.xonrxc += E1000_READ_REG(shared, XONRXC);
-	adapter->stats.xontxc += E1000_READ_REG(shared, XONTXC);
-	adapter->stats.xoffrxc += E1000_READ_REG(shared, XOFFRXC);
-	adapter->stats.xofftxc += E1000_READ_REG(shared, XOFFTXC);
-	adapter->stats.fcruc += E1000_READ_REG(shared, FCRUC);
-	adapter->stats.gptc += E1000_READ_REG(shared, GPTC);
-	adapter->stats.gotcl += E1000_READ_REG(shared, GOTCL);
-	adapter->stats.gotch += E1000_READ_REG(shared, GOTCH);
-	adapter->stats.rnbc += E1000_READ_REG(shared, RNBC);
-	adapter->stats.ruc += E1000_READ_REG(shared, RUC);
-	adapter->stats.rfc += E1000_READ_REG(shared, RFC);
-	adapter->stats.rjc += E1000_READ_REG(shared, RJC);
-	adapter->stats.torl += E1000_READ_REG(shared, TORL);
-	adapter->stats.torh += E1000_READ_REG(shared, TORH);
-	adapter->stats.totl += E1000_READ_REG(shared, TOTL);
-	adapter->stats.toth += E1000_READ_REG(shared, TOTH);
-	adapter->stats.tpr += E1000_READ_REG(shared, TPR);
-	adapter->stats.tpt += E1000_READ_REG(shared, TPT);
-	adapter->stats.ptc64 += E1000_READ_REG(shared, PTC64);
-	adapter->stats.ptc127 += E1000_READ_REG(shared, PTC127);
-	adapter->stats.ptc255 += E1000_READ_REG(shared, PTC255);
-	adapter->stats.ptc511 += E1000_READ_REG(shared, PTC511);
-	adapter->stats.ptc1023 += E1000_READ_REG(shared, PTC1023);
-	adapter->stats.ptc1522 += E1000_READ_REG(shared, PTC1522);
-	adapter->stats.mptc += E1000_READ_REG(shared, MPTC);
-	adapter->stats.bptc += E1000_READ_REG(shared, BPTC);
-
-	if(adapter->shared.mac_type >= e1000_82543) {
-		adapter->stats.algnerrc += E1000_READ_REG(shared, ALGNERRC);
-		adapter->stats.rxerrc += E1000_READ_REG(shared, RXERRC);
-		adapter->stats.tncrs += E1000_READ_REG(shared, TNCRS);
-		adapter->stats.cexterr += E1000_READ_REG(shared, CEXTERR);
-		adapter->stats.tsctc += E1000_READ_REG(shared, TSCTC);
-		adapter->stats.tsctfc += E1000_READ_REG(shared, TSCTFC);
+	adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
+	adapter->stats.mpc += E1000_READ_REG(hw, MPC);
+	adapter->stats.scc += E1000_READ_REG(hw, SCC);
+	adapter->stats.ecol += E1000_READ_REG(hw, ECOL);
+	adapter->stats.mcc += E1000_READ_REG(hw, MCC);
+	adapter->stats.latecol += E1000_READ_REG(hw, LATECOL);
+	adapter->stats.dc += E1000_READ_REG(hw, DC);
+	adapter->stats.sec += E1000_READ_REG(hw, SEC);
+	adapter->stats.rlec += E1000_READ_REG(hw, RLEC);
+	adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC);
+	adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC);
+	adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC);
+	adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
+	adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
+	adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
+	adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
+	adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
+	adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
+	adapter->stats.ruc += E1000_READ_REG(hw, RUC);
+	adapter->stats.rfc += E1000_READ_REG(hw, RFC);
+	adapter->stats.rjc += E1000_READ_REG(hw, RJC);
+	adapter->stats.torl += E1000_READ_REG(hw, TORL);
+	adapter->stats.torh += E1000_READ_REG(hw, TORH);
+	adapter->stats.totl += E1000_READ_REG(hw, TOTL);
+	adapter->stats.toth += E1000_READ_REG(hw, TOTH);
+	adapter->stats.tpr += E1000_READ_REG(hw, TPR);
+	adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
+	adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
+	adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
+	adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
+	adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
+	adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
+	adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
+	adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
+
+	/* used for adaptive IFS */
+
+	hw->tx_packet_delta = E1000_READ_REG(hw, TPT);
+	adapter->stats.tpt += hw->tx_packet_delta;
+	hw->collision_delta = E1000_READ_REG(hw, COLC);
+	adapter->stats.colc += hw->collision_delta;
+
+	if(hw->mac_type >= e1000_82543) {
+		adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
+		adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
+		adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
+		adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR);
+		adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
+		adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
 	}
 
 	/* Fill out the OS statistics structure */
@@ -1627,14 +1640,18 @@
 
 	/* Tx Dropped needs to be maintained elsewhere */
 
-	if(adapter->shared.media_type == e1000_media_type_copper) {
-		adapter->phy_stats.idle_errors +=
-			(e1000_read_phy_reg(shared, PHY_1000T_STATUS)
-			 & PHY_IDLE_ERROR_COUNT_MASK);
-		adapter->phy_stats.receive_errors +=
-			e1000_read_phy_reg(shared, M88E1000_RX_ERR_CNTR);
+	/* Phy Stats */
+
+	if(hw->media_type == e1000_media_type_copper) {
+		if((adapter->link_speed == SPEED_1000) &&
+		   (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
+			phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
+			adapter->phy_stats.idle_errors += phy_tmp;
+		}
+
+		if(!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
+			adapter->phy_stats.receive_errors += phy_tmp;
 	}
-	return;
 }
 
 /**
@@ -1646,9 +1663,8 @@
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
 	atomic_inc(&adapter->irq_sem);
-	E1000_WRITE_REG(&adapter->shared, IMC, ~0);
+	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
 	synchronize_irq();
-	return;
 }
 
 /**
@@ -1660,8 +1676,7 @@
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
 	if(atomic_dec_and_test(&adapter->irq_sem))
-		E1000_WRITE_REG(&adapter->shared, IMS, IMS_ENABLE_MASK);
-	return;
+		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
 }
 
 /**
@@ -1679,20 +1694,23 @@
 	uint32_t icr;
 	int i = E1000_MAX_INTR;
 
-	while(i && (icr = E1000_READ_REG(&adapter->shared, ICR))) {
+	while(i && (icr = E1000_READ_REG(&adapter->hw, ICR))) {
 
 		if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
-			/* run the watchdog ASAP */
-			adapter->shared.get_link_status = 1;
+			adapter->hw.get_link_status = 1;
 			mod_timer(&adapter->watchdog_timer, jiffies);
 		}
 
 		e1000_clean_rx_irq(adapter);
-		e1000_clean_tx_irq(adapter);
+
+		if((icr & E1000_ICR_TXDW) && spin_trylock(&adapter->tx_lock)) {
+			e1000_clean_tx_irq(adapter);
+			spin_unlock(&adapter->tx_lock);
+		}
+
 		i--;
-	}
 
-	return;
+	}
 }
 
 /**
@@ -1726,7 +1744,7 @@
 
 		if(tx_ring->buffer_info[i].skb) {
 
-			dev_kfree_skb_irq(tx_ring->buffer_info[i].skb);
+			dev_kfree_skb_any(tx_ring->buffer_info[i].skb);
 
 			tx_ring->buffer_info[i].skb = NULL;
 		}
@@ -1734,7 +1752,6 @@
 		memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
 		mb();
 
-		atomic_inc(&tx_ring->unused);
 		i = (i + 1) % tx_ring->count;
 		tx_desc = E1000_TX_DESC(*tx_ring, i);
 
@@ -1744,11 +1761,10 @@
 	tx_ring->next_to_clean = i;
 
 	if(netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
-	   (atomic_read(&tx_ring->unused) > E1000_TX_QUEUE_WAKE)) {
+	   (E1000_DESC_UNUSED(tx_ring) > E1000_TX_QUEUE_WAKE)) {
 
 		netif_wake_queue(netdev);
 	}
-	return;
 }
 
 /**
@@ -1789,12 +1805,10 @@
 			E1000_DBG("Receive packet consumed multiple buffers\n");
 
 			dev_kfree_skb_irq(skb);
-			memset(rx_desc, 0, 16);
+			memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
 			mb();
 			rx_ring->buffer_info[i].skb = NULL;
 
-			rx_ring->unused_count++;
-
 			i = (i + 1) % rx_ring->count;
 
 			rx_desc = E1000_RX_DESC(*rx_ring, i);
@@ -1805,12 +1819,12 @@
 
 			last_byte = *(skb->data + length - 1);
 
-			if(TBI_ACCEPT(&adapter->shared, rx_desc->special,
+			if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
 			              rx_desc->errors, length, last_byte)) {
 
 				spin_lock_irqsave(&adapter->stats_lock, flags);
 
-				e1000_tbi_adjust_stats(&adapter->shared,
+				e1000_tbi_adjust_stats(&adapter->hw,
 				                       &adapter->stats,
 				                       length, skb->data);
 
@@ -1820,11 +1834,10 @@
 			} else {
 
 				dev_kfree_skb_irq(skb);
-				memset(rx_desc, 0, 16);
+				memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
 				mb();
 				rx_ring->buffer_info[i].skb = NULL;
 
-				rx_ring->unused_count++;
 				i = (i + 1) % rx_ring->count;
 
 				rx_desc = E1000_RX_DESC(*rx_ring, i);
@@ -1833,20 +1846,28 @@
 		}
 
 		/* Good Receive */
-		skb_put(skb, length - CRC_LENGTH);
+		skb_put(skb, length - ETHERNET_FCS_SIZE);
 
 		/* Receive Checksum Offload */
 		e1000_rx_checksum(adapter, rx_desc, skb);
 
 		skb->protocol = eth_type_trans(skb, netdev);
+#ifdef NETIF_F_HW_VLAN_TX
+		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
+			vlan_hwaccel_rx(skb, adapter->vlgrp,
+				(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
+		} else {
+			netif_rx(skb);
+		}
+#else
 		netif_rx(skb);
+#endif
+		netdev->last_rx = jiffies;
 
 		memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
 		mb();
 		rx_ring->buffer_info[i].skb = NULL;
 
-		rx_ring->unused_count++;
-
 		i = (i + 1) % rx_ring->count;
 
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
@@ -1855,8 +1876,6 @@
 	rx_ring->next_to_clean = i;
 
 	e1000_alloc_rx_buffers(adapter);
-
-	return;
 }
 
 /**
@@ -1911,16 +1930,13 @@
 
 		rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma);
 
-		/* move tail */
-		E1000_WRITE_REG(&adapter->shared, RDT, i);
-
-		atomic_dec(&rx_ring->unused);
+		if(!(i % E1000_RX_BUFFER_WRITE))
+			E1000_WRITE_REG(&adapter->hw, RDT, i);
 
 		i = (i + 1) % rx_ring->count;
 	}
 
 	rx_ring->next_to_use = i;
-	return;
 }
 
 /**
@@ -1954,7 +1970,7 @@
                   struct sk_buff *skb)
 {
 	/* 82543 or newer only */
-	if((adapter->shared.mac_type < e1000_82543) ||
+	if((adapter->hw.mac_type < e1000_82543) ||
 	/* Ignore Checksum bit is set */
 	(rx_desc->status & E1000_RXD_STAT_IXSM) ||
 	/* TCP Checksum has not been calculated */
@@ -1974,10 +1990,8 @@
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		adapter->hw_csum_good++;
 	}
-	return;
 }
 
-
 /**
  * e1000_enable_WOL - Wake On Lan Support (Magic Pkt)
  * @adapter: Adapter structure
@@ -1988,29 +2002,104 @@
 {
 	uint32_t wuc;
 
-	if(adapter->shared.mac_type < e1000_82544)
+	if(adapter->hw.mac_type < e1000_82544)
 		return;
 
 	if(adapter->wol) {
 		wuc = E1000_WUC_APME | E1000_WUC_PME_EN |
 		      E1000_WUC_PME_STATUS | E1000_WUC_APMPME;
 
-		E1000_WRITE_REG(&adapter->shared, WUC, wuc);
+		E1000_WRITE_REG(&adapter->hw, WUC, wuc);
 
-		E1000_WRITE_REG(&adapter->shared, WUFC, adapter->wol);
+		E1000_WRITE_REG(&adapter->hw, WUFC, adapter->wol);
 	}
-
-	return;
 }
 
 void
-e1000_write_pci_cfg(struct e1000_shared_adapter *shared,
+e1000_write_pci_cfg(struct e1000_hw *hw,
                     uint32_t reg, uint16_t *value)
 {
-	struct e1000_adapter *adapter = shared->back;
+	struct e1000_adapter *adapter = hw->back;
 
 	pci_write_config_word(adapter->pdev, reg, *value);
-	return;
 }
+
+#ifdef NETIF_F_HW_VLAN_TX
+static void
+e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	uint32_t ctrl, rctl;
+
+	e1000_irq_disable(adapter);
+	adapter->vlgrp = grp;
+
+	if(grp) {
+		/* enable VLAN tag insert/strip */
+
+		E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
+
+		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+		ctrl |= E1000_CTRL_VME;
+		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+
+		/* enable VLAN receive filtering */
+
+		rctl = E1000_READ_REG(&adapter->hw, RCTL);
+		rctl |= E1000_RCTL_VFE;
+		rctl &= ~E1000_RCTL_CFIEN;
+		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+	} else {
+		/* disable VLAN tag insert/strip */
+
+		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+		ctrl &= ~E1000_CTRL_VME;
+		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+
+		/* disable VLAN filtering */
+
+		rctl = E1000_READ_REG(&adapter->hw, RCTL);
+		rctl &= ~E1000_RCTL_VFE;
+		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+	}
+
+	e1000_irq_enable(adapter);
+}
+
+static void
+e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	uint32_t vfta, index;
+
+	/* add VID to filter table */
+
+	index = (vid >> 5) & 0x7F;
+	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta |= (1 << (vid & 0x1F));
+	e1000_write_vfta(&adapter->hw, index, vfta);
+}
+
+static void
+e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	uint32_t vfta, index;
+
+	e1000_irq_disable(adapter);
+	
+	if(adapter->vlgrp)
+		adapter->vlgrp->vlan_devices[vid] = NULL;
+	
+	e1000_irq_enable(adapter);
+
+	/* remove VID from filter table*/
+
+	index = (vid >> 5) & 0x7F;
+	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta &= ~(1 << (vid & 0x1F));
+	e1000_write_vfta(&adapter->hw, index, vfta);
+}
+#endif
 
 /* e1000_main.c */
diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
--- a/drivers/net/e1000/e1000_osdep.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/e1000/e1000_osdep.h	Sun Apr 14 12:16:56 2002
@@ -2,9 +2,8 @@
 
   This software program is available to you under a choice of one of two
   licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
   
   Recipient has requested a license and Intel Corporation ("Intel") is willing
   to grant a license for the software entitled Linux Base Driver for the
@@ -18,7 +17,7 @@
   "Recipient" means the party to whom Intel delivers this Software.
   
   "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
+  any operating system available under the GNU General Public License 2.0 or
   later.
   
   Copyright (c) 1999 - 2002 Intel Corporation.
@@ -51,10 +50,10 @@
   version of an operating system that has been distributed under the GNU
   General Public License 2.0 or later. This patent license shall apply to the
   combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
+  General Public License 2.0 or later if, at the time Intel provides the
   Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
   such combination to be covered by the Licensed Patents. The patent license
   shall not apply to any other combinations which include the Software. NO
   hardware per se is licensed hereunder.
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- a/drivers/net/e1000/e1000_param.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/e1000/e1000_param.c	Sun Apr 14 12:16:56 2002
@@ -2,9 +2,8 @@
 
   This software program is available to you under a choice of one of two
   licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
   
   Recipient has requested a license and Intel Corporation ("Intel") is willing
   to grant a license for the software entitled Linux Base Driver for the
@@ -18,7 +17,7 @@
   "Recipient" means the party to whom Intel delivers this Software.
   
   "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
+  any operating system available under the GNU General Public License 2.0 or
   later.
   
   Copyright (c) 1999 - 2002 Intel Corporation.
@@ -51,10 +50,10 @@
   version of an operating system that has been distributed under the GNU
   General Public License 2.0 or later. This patent license shall apply to the
   combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
+  General Public License 2.0 or later if, at the time Intel provides the
   Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
   such combination to be covered by the Licensed Patents. The patent license
   shall not apply to any other combinations which include the Software. NO
   hardware per se is licensed hereunder.
@@ -153,7 +152,7 @@
 
 /* Auto-negotiation Advertisement Override
  *
- * Valid Range: 0x00-0x0F, 0x20-0x2F
+ * Valid Range: 0x01-0x0F, 0x20-0x2F
  *
  * The AutoNeg value is a bit mask describing which speed and duplex
  * combinations should be advertised during auto-negotiation.
@@ -193,20 +192,11 @@
 
 E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
 
-/* Transmit Interrupt Delay in units of 1.024 microseconds
- *
- * Valid Range: 0-65535
- *
- * Default Value: 64
- */
-
-E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
-
 /* Receive Interrupt Delay in units of 1.024 microseconds
  *
  * Valid Range: 0-65535
  *
- * Default Value: 64
+ * Default Value: 64/128
  */
 
 E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
@@ -252,13 +242,10 @@
 #define MIN_RXD                       80
 #define MAX_82544_RXD               4096
 
-#define DEFAULT_TIDV                  64
-#define MAX_TIDV                  0xFFFF
-#define MIN_TIDV                       0
-
-#define DEFAULT_RIDV                  64
-#define MAX_RIDV                  0xFFFF
-#define MIN_RIDV                       0
+#define DEFAULT_RDTR                  64
+#define DEFAULT_RADV                 128
+#define MAX_RXDELAY               0xFFFF
+#define MIN_RXDELAY                    0
 
 #define DEFAULT_MDIX                   0
 #define MAX_MDIX                       3
@@ -332,8 +319,6 @@
 	return -1;
 }
 
-#define LIST_LEN(l) (sizeof(l) / sizeof(l[0]))
-
 static void e1000_check_fiber_options(struct e1000_adapter *adapter);
 static void e1000_check_copper_options(struct e1000_adapter *adapter);
 
@@ -367,7 +352,7 @@
 			arg: { r: { min: MIN_TXD }}
 		};
 		struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
-		e1000_mac_type mac_type = adapter->shared.mac_type;
+		e1000_mac_type mac_type = adapter->hw.mac_type;
 		opt.arg.r.max = mac_type < e1000_82544 ? MAX_TXD : MAX_82544_TXD;
 
 		tx_ring->count = TxDescriptors[bd];
@@ -383,7 +368,7 @@
 			arg: { r: { min: MIN_RXD }}
 		};
 		struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
-		e1000_mac_type mac_type = adapter->shared.mac_type;
+		e1000_mac_type mac_type = adapter->hw.mac_type;
 		opt.arg.r.max = mac_type < e1000_82544 ? MAX_RXD : MAX_82544_RXD;
 
 		rx_ring->count = RxDescriptors[bd];
@@ -416,39 +401,30 @@
 			name: "Flow Control",
 			err:  "reading default settings from EEPROM",
 			def:  e1000_fc_default,
-			arg: { l: { nr: LIST_LEN(fc_list), p: fc_list }}
+			arg: { l: { nr: ARRAY_SIZE(fc_list), p: fc_list }}
 		};
 
 		int fc = FlowControl[bd];
 		e1000_validate_option(&fc, &opt);
-		adapter->shared.fc = adapter->shared.original_fc = fc;
-	}
-	{ /* Transmit Interrupt Delay */
-		struct e1000_option opt = {
-			type: range_option,
-			name: "Transmit Interrupt Delay",
-			err:  "using default of " __MODULE_STRING(DEFAULT_TIDV),
-			def:  DEFAULT_TIDV,
-			arg: { r: { min: MIN_TIDV, max: MAX_TIDV }}
-		};
-
-		adapter->tx_int_delay = TxIntDelay[bd];
-		e1000_validate_option(&adapter->tx_int_delay, &opt);
+		adapter->hw.fc = adapter->hw.original_fc = fc;
 	}
 	{ /* Receive Interrupt Delay */
+		char *rdtr = "using default of " __MODULE_STRING(DEFAULT_RDTR);
+		char *radv = "using default of " __MODULE_STRING(DEFAULT_RADV);
 		struct e1000_option opt = {
 			type: range_option,
 			name: "Receive Interrupt Delay",
-			err:  "using default of " __MODULE_STRING(DEFAULT_RIDV),
-			def:  DEFAULT_RIDV,
-			arg: { r: { min: MIN_RIDV, max: MAX_RIDV }}
+			arg: { r: { min: MIN_RXDELAY, max: MAX_RXDELAY }}
 		};
+		e1000_mac_type mac_type = adapter->hw.mac_type;
+		opt.def = mac_type < e1000_82540 ? DEFAULT_RDTR : DEFAULT_RADV;
+		opt.err = mac_type < e1000_82540 ? rdtr : radv;
 
 		adapter->rx_int_delay = RxIntDelay[bd];
 		e1000_validate_option(&adapter->rx_int_delay, &opt);
 	}
 	
-	switch(adapter->shared.media_type) {
+	switch(adapter->hw.media_type) {
 	case e1000_media_type_fiber:
 		e1000_check_fiber_options(adapter);
 		break;
@@ -511,7 +487,7 @@
 			name: "Speed",
 			err:  "parameter ignored",
 			def:  0,
-			arg: { l: { nr: LIST_LEN(speed_list), p: speed_list }}
+			arg: { l: { nr: ARRAY_SIZE(speed_list), p: speed_list }}
 		};
 
 		speed = Speed[bd];
@@ -526,7 +502,7 @@
 			name: "Duplex",
 			err:  "parameter ignored",
 			def:  0,
-			arg: { l: { nr: LIST_LEN(dplx_list), p: dplx_list }}
+			arg: { l: { nr: ARRAY_SIZE(dplx_list), p: dplx_list }}
 		};
 
 		dplx = Duplex[bd];
@@ -537,10 +513,10 @@
 		printk(KERN_INFO
 		       "AutoNeg specified along with Speed or Duplex, "
 		       "parameter ignored\n");
-		adapter->shared.autoneg_advertised = AUTONEG_ADV_DEFAULT;
+		adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
 	} else { /* Autoneg */
 		struct e1000_opt_list an_list[] =
-			#define AA "Autoneg advertising "
+			#define AA "AutoNeg advertising "
 			{{ 0x01, AA "10/HD" },
 			 { 0x02, AA "10/FD" },
 			 { 0x03, AA "10/FD, 10/HD" },
@@ -575,20 +551,20 @@
 
 		struct e1000_option opt = {
 			type: list_option,
-			name: "Autoneg",
+			name: "AutoNeg",
 			err:  "parameter ignored",
 			def:  AUTONEG_ADV_DEFAULT,
-			arg: { l: { nr: LIST_LEN(an_list), p: an_list }}
+			arg: { l: { nr: ARRAY_SIZE(an_list), p: an_list }}
 		};
 
 		int an = AutoNeg[bd];
 		e1000_validate_option(&an, &opt);
-		adapter->shared.autoneg_advertised = an;
+		adapter->hw.autoneg_advertised = an;
 	}
 
 	switch (speed + dplx) {
 	case 0:
-		adapter->shared.autoneg = 1;
+		adapter->hw.autoneg = 1;
 		if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
 			printk(KERN_INFO
 			       "Speed and duplex autonegotiation enabled\n");
@@ -596,75 +572,75 @@
 	case HALF_DUPLEX:
 		printk(KERN_INFO "Half Duplex specified without Speed\n");
 		printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_10_HALF | 
-		                                     ADVERTISE_100_HALF;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | 
+		                                 ADVERTISE_100_HALF;
 		break;
 	case FULL_DUPLEX:
 		printk(KERN_INFO "Full Duplex specified without Speed\n");
 		printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_10_FULL |
-		                                     ADVERTISE_100_FULL |
-		                                     ADVERTISE_1000_FULL;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
+		                                 ADVERTISE_100_FULL |
+		                                 ADVERTISE_1000_FULL;
 		break;
 	case SPEED_10:
 		printk(KERN_INFO "10 Mbps Speed specified without Duplex\n");
 		printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_10_HALF |
-		                                     ADVERTISE_10_FULL;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
+		                                 ADVERTISE_10_FULL;
 		break;
 	case SPEED_10 + HALF_DUPLEX:
 		printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n");
-		adapter->shared.autoneg = 0;
-		adapter->shared.forced_speed_duplex = e1000_10_half;
-		adapter->shared.autoneg_advertised = 0;
+		adapter->hw.autoneg = 0;
+		adapter->hw.forced_speed_duplex = e1000_10_half;
+		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_10 + FULL_DUPLEX:
 		printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n");
-		adapter->shared.autoneg = 0;
-		adapter->shared.forced_speed_duplex = e1000_10_full;
-		adapter->shared.autoneg_advertised = 0;
+		adapter->hw.autoneg = 0;
+		adapter->hw.forced_speed_duplex = e1000_10_full;
+		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_100:
 		printk(KERN_INFO "100 Mbps Speed specified without Duplex\n");
 		printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_100_HALF |
-		                                     ADVERTISE_100_FULL;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
+		                                 ADVERTISE_100_FULL;
 		break;
 	case SPEED_100 + HALF_DUPLEX:
 		printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n");
-		adapter->shared.autoneg = 0;
-		adapter->shared.forced_speed_duplex = e1000_100_half;
-		adapter->shared.autoneg_advertised = 0;
+		adapter->hw.autoneg = 0;
+		adapter->hw.forced_speed_duplex = e1000_100_half;
+		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_100 + FULL_DUPLEX:
 		printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n");
-		adapter->shared.autoneg = 0;
-		adapter->shared.forced_speed_duplex = e1000_100_full;
-		adapter->shared.autoneg_advertised = 0;
+		adapter->hw.autoneg = 0;
+		adapter->hw.forced_speed_duplex = e1000_100_full;
+		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_1000:
 		printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n");
 		printk(KERN_INFO
 		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_1000_FULL;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
 	case SPEED_1000 + HALF_DUPLEX:
 		printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n");
 		printk(KERN_INFO
 		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_1000_FULL;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
 	case SPEED_1000 + FULL_DUPLEX:
 		printk(KERN_INFO
 		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
-		adapter->shared.autoneg = 1;
-		adapter->shared.autoneg_advertised = ADVERTISE_1000_FULL;
+		adapter->hw.autoneg = 1;
+		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
 	default:
 		BUG();
@@ -683,7 +659,7 @@
 
 		int mdix = MdiX[bd];
 		e1000_validate_option(&mdix, &opt);
-		adapter->shared.mdix = mdix;
+		adapter->hw.mdix = mdix;
 	}
 	{ /* Automatic Correction for Reverse Cable Polarity */
 	  /* option is actually to disable polarity correction,
@@ -697,11 +673,11 @@
 
 		int dpc = DisablePolarityCorrection[bd];
 		e1000_validate_option(&dpc, &opt);
-		adapter->shared.disable_polarity_correction = dpc;
+		adapter->hw.disable_polarity_correction = dpc;
 	}
 	
 	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
-	if (!e1000_validate_mdi_setting(&(adapter->shared))) {
+	if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
 		printk(KERN_INFO "Speed, AutoNeg and MDI-X specifications are "
 		       "incompatible. Setting MDI-X to a compatible value.\n");
 	}
diff -Nru a/drivers/net/e1000/e1000_phy.c b/drivers/net/e1000/e1000_phy.c
--- a/drivers/net/e1000/e1000_phy.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1485 +0,0 @@
-/*******************************************************************************
-
-  This software program is available to you under a choice of one of two
-  licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
-  
-  Recipient has requested a license and Intel Corporation ("Intel") is willing
-  to grant a license for the software entitled Linux Base Driver for the
-  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
-  by Intel Corporation. The following definitions apply to this license:
-  
-  "Licensed Patents" means patent claims licensable by Intel Corporation which
-  are necessarily infringed by the use of sale of the Software alone or when
-  combined with the operating system referred to below.
-  
-  "Recipient" means the party to whom Intel delivers this Software.
-  
-  "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
-  later.
-  
-  Copyright (c) 1999 - 2002 Intel Corporation.
-  All rights reserved.
-  
-  The license is provided to Recipient and Recipient's Licensees under the
-  following terms.
-  
-  Redistribution and use in source and binary forms of the Software, with or
-  without modification, are permitted provided that the following conditions
-  are met:
-  
-  Redistributions of source code of the Software may retain the above
-  copyright notice, this list of conditions and the following disclaimer.
-  
-  Redistributions in binary form of the Software may reproduce the above
-  copyright notice, this list of conditions and the following disclaimer in
-  the documentation and/or materials provided with the distribution.
-  
-  Neither the name of Intel Corporation nor the names of its contributors
-  shall be used to endorse or promote products derived from this Software
-  without specific prior written permission.
-  
-  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
-  royalty-free patent license under Licensed Patents to make, use, sell, offer
-  to sell, import and otherwise transfer the Software, if any, in source code
-  and object code form. This license shall include changes to the Software
-  that are error corrections or other minor changes to the Software that do
-  not add functionality or features when the Software is incorporated in any
-  version of an operating system that has been distributed under the GNU
-  General Public License 2.0 or later. This patent license shall apply to the
-  combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
-  Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
-  such combination to be covered by the Licensed Patents. The patent license
-  shall not apply to any other combinations which include the Software. NO
-  hardware per se is licensed hereunder.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
-  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
-  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
-
-/* e1000_phy.c
- * Shared functions for accessing and configuring the PHY
- */
-
-#include "e1000_mac.h"
-#include "e1000_phy.h"
-
-/******************************************************************************
-* Raises the Management Data Clock
-*
-* shared - Struct containing variables accessed by shared code
-* ctrl_reg - Device control register's current value
-******************************************************************************/
-static void
-e1000_raise_mdc(struct e1000_shared_adapter *shared,
-                uint32_t *ctrl_reg)
-{
-    /* Raise the clock input to the Management Data Clock (by setting
-     * the MDC bit), and then delay 2 microseconds.
-     */
-    E1000_WRITE_REG(shared, CTRL, (*ctrl_reg | E1000_CTRL_MDC));
-    usec_delay(2);
-    return;
-}
-
-/******************************************************************************
-* Lowers the Management Data Clock
-*
-* shared - Struct containing variables accessed by shared code
-* ctrl_reg - Device control register's current value
-******************************************************************************/
-static void
-e1000_lower_mdc(struct e1000_shared_adapter *shared,
-                uint32_t *ctrl_reg)
-{
-    /* Lower the clock input to the Management Data Clock (by clearing
-     * the MDC bit), and then delay 2 microseconds.
-     */
-    E1000_WRITE_REG(shared, CTRL, (*ctrl_reg & ~E1000_CTRL_MDC));
-    usec_delay(2);
-    return;
-}
-
-/******************************************************************************
-* Shifts data bits out to the PHY
-*
-* shared - Struct containing variables accessed by shared code
-* data - Data to send out to the PHY
-* count - Number of bits to shift out
-*
-* Bits are shifted out in MSB to LSB order.
-******************************************************************************/
-static void
-e1000_phy_shift_out(struct e1000_shared_adapter *shared,
-                    uint32_t data,
-                    uint16_t count)
-{
-    uint32_t ctrl_reg;
-    uint32_t mask;
-
-    ASSERT(count <= 32);
-
-    /* We need to shift "count" number of bits out to the PHY.  So, the
-     * value in the "Data" parameter will be shifted out to the PHY
-     * one bit at a time.  In order to do this, "Data" must be broken
-     * down into bits, which is what the "while" logic does below.
-     */
-    mask = 0x01;
-    mask <<= (count - 1);
-
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-    /* Set MDIO_DIR (SWDPIO1) and MDC_DIR (SWDPIO2) direction bits to
-     * be used as output pins.
-     */
-    ctrl_reg |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
-
-    while(mask) {
-        /* A "1" is shifted out to the PHY by setting the MDIO bit to
-         * "1" and then raising and lowering the Management Data Clock
-         * (MDC).  A "0" is shifted out to the PHY by setting the MDIO
-         * bit to "0" and then raising and lowering the clock.
-         */
-        if(data & mask)
-            ctrl_reg |= E1000_CTRL_MDIO;
-        else
-            ctrl_reg &= ~E1000_CTRL_MDIO;
-
-        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-        usec_delay(2);
-
-        e1000_raise_mdc(shared, &ctrl_reg);
-        e1000_lower_mdc(shared, &ctrl_reg);
-
-        mask = mask >> 1;
-    }
-
-    /* Clear the data bit just before leaving this routine. */
-    ctrl_reg &= ~E1000_CTRL_MDIO;
-    return;
-}
-
-/******************************************************************************
-* Shifts data bits in from the PHY
-*
-* shared - Struct containing variables accessed by shared code
-*
-* Bits are shifted in in MSB to LSB order. 
-******************************************************************************/
-static uint16_t
-e1000_phy_shift_in(struct e1000_shared_adapter *shared)
-{
-    uint32_t ctrl_reg;
-    uint16_t data = 0;
-    uint8_t i;
-
-    /* In order to read a register from the PHY, we need to shift in a
-     * total of 18 bits from the PHY.  The first two bit (TurnAround)
-     * times are used to avoid contention on the MDIO pin when a read
-     * operation is performed.  These two bits are ignored by us and
-     * thrown away.  Bits are "shifted in" by raising the clock input
-     * to the Management Data Clock (setting the MDC bit), and then
-     * reading the value of the MDIO bit.
-     */ 
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-    /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as
-     * input.
-     */ 
-    ctrl_reg &= ~E1000_CTRL_MDIO_DIR;
-    ctrl_reg &= ~E1000_CTRL_MDIO;
-
-    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-    /* Raise and Lower the clock before reading in the data.  This
-     * accounts for the TurnAround bits.  The first clock occurred
-     * when we clocked out the last bit of the Register Address.
-     */
-    e1000_raise_mdc(shared, &ctrl_reg);
-    e1000_lower_mdc(shared, &ctrl_reg);
-
-    for(data = 0, i = 0; i < 16; i++) {
-        data = data << 1;
-        e1000_raise_mdc(shared, &ctrl_reg);
-
-        ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-        /* Check to see if we shifted in a "1". */
-        if(ctrl_reg & E1000_CTRL_MDIO)
-            data |= 1;
-
-        e1000_lower_mdc(shared, &ctrl_reg);
-    }
-
-    e1000_raise_mdc(shared, &ctrl_reg);
-    e1000_lower_mdc(shared, &ctrl_reg);
-
-    /* Clear the MDIO bit just before leaving this routine. */
-    ctrl_reg &= ~E1000_CTRL_MDIO;
-
-    return (data);
-}
-
-/******************************************************************************
-* Force PHY speed and duplex settings to shared->forced_speed_duplex
-*
-* shared - Struct containing variables accessed by shared code
-******************************************************************************/
-static void
-e1000_phy_force_speed_duplex(struct e1000_shared_adapter *shared)
-{
-    uint32_t tctl_reg;
-    uint32_t ctrl_reg;
-    uint32_t shift;
-    uint16_t mii_ctrl_reg;
-    uint16_t mii_status_reg;
-    uint16_t phy_data;
-    uint16_t i;
-
-    DEBUGFUNC("e1000_phy_force_speed_duplex");
-
-    /* Turn off Flow control if we are forcing speed and duplex. */
-    shared->fc = e1000_fc_none;
-
-    DEBUGOUT1("shared->fc = %d\n", shared->fc);
-
-    /* Read the Device Control Register. */
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-    /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
-    ctrl_reg |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-    ctrl_reg &= ~(DEVICE_SPEED_MASK);
-
-    /* Clear the Auto Speed Detect Enable bit. */
-    ctrl_reg &= ~E1000_CTRL_ASDE;
-
-    /* Read the MII Control Register. */
-    mii_ctrl_reg = e1000_read_phy_reg(shared, PHY_CTRL);
-
-    /* We need to disable autoneg in order to force link and duplex. */
-
-    mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
-
-    /* Are we forcing Full or Half Duplex? */
-    if(shared->forced_speed_duplex == e1000_100_full ||
-       shared->forced_speed_duplex == e1000_10_full) {
-
-        /* We want to force full duplex so we SET the full duplex bits
-         * in the Device and MII Control Registers.
-         */
-        ctrl_reg |= E1000_CTRL_FD;
-        mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
-
-        DEBUGOUT("Full Duplex\n");
-    } else {
-
-        /* We want to force half duplex so we CLEAR the full duplex
-         * bits in the Device and MII Control Registers.
-         */
-        ctrl_reg &= ~E1000_CTRL_FD;
-        mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;    /* Do this implies HALF */
-
-        DEBUGOUT("Half Duplex\n");
-    }
-
-    /* Are we forcing 100Mbps??? */
-    if(shared->forced_speed_duplex == e1000_100_full ||
-       shared->forced_speed_duplex == e1000_100_half) {
-
-        /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
-        ctrl_reg |= E1000_CTRL_SPD_100;
-        mii_ctrl_reg |= MII_CR_SPEED_100;
-        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
-
-        DEBUGOUT("Forcing 100mb ");
-    } else {                    /* Force 10MB Full or Half */
-
-        /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
-        ctrl_reg &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-        mii_ctrl_reg |= MII_CR_SPEED_10;
-        mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
-
-        DEBUGOUT("Forcing 10mb ");
-    }
-
-    /* Now we need to configure the Collision Distance.  We need to read
-     * the Transmit Control Register to do this.
-     * Note: This must be done for both Half or Full Duplex.
-     */
-    tctl_reg = E1000_READ_REG(shared, TCTL);
-    DEBUGOUT1("tctl_reg = %x\n", tctl_reg);
-
-    if(!(mii_ctrl_reg & MII_CR_FULL_DUPLEX)) {
-
-       /* We are in Half Duplex mode so we need to set up our collision
-        * distance for 10/100.
-        */
-        tctl_reg &= ~E1000_TCTL_COLD;
-        shift = E1000_HDX_COLLISION_DISTANCE;
-        shift <<= E1000_COLD_SHIFT;
-        tctl_reg |= shift;
-    } else {
-        /* We are in Full Duplex mode.  We have the same collision
-         * distance regardless of speed.
-         */
-        tctl_reg &= ~E1000_TCTL_COLD;
-        shift = E1000_FDX_COLLISION_DISTANCE;
-        shift <<= E1000_COLD_SHIFT;
-        tctl_reg |= shift;
-    }
-
-    /* Write the configured values back to the Transmit Control Reg. */
-    E1000_WRITE_REG(shared, TCTL, tctl_reg);
-
-    /* Write the configured values back to the Device Control Reg. */
-    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-    /* Write the MII Control Register with the new PHY configuration. */
-    phy_data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
-
-    /* Clear Auto-Crossover to force MDI manually.
-     * M88E1000 requires MDI forced whenever speed/duplex is forced
-     */
-    phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-
-    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_data);
-
-    DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
-
-    /* Need to reset the PHY or these bits will get ignored. */
-    mii_ctrl_reg |= MII_CR_RESET;
-
-    e1000_write_phy_reg(shared, PHY_CTRL, mii_ctrl_reg);
-
-    /* The wait_autoneg_complete flag may be a little misleading here.
-     * Since we are forcing speed and duplex, Auto-Neg is not enabled.
-     * But we do want to delay for a period while forcing only so we
-     * don't generate false No Link messages.  So we will wait here
-     * only if the user has set wait_autoneg_complete to 1, which is
-     * the default.
-     */
-    if(shared->wait_autoneg_complete) {
-        /* We will wait for autoneg to complete. */
-        DEBUGOUT("Waiting for forced speed/duplex link.\n");
-        mii_status_reg = 0;
-
-        /* We will wait for autoneg to complete or 4.5 seconds to expire. */
-        for(i = PHY_FORCE_TIME; i > 0; i--) {
-            /* Read the MII Status Register and wait for Auto-Neg
-             * Complete bit to be set.
-             */
-            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-
-            if(mii_status_reg & MII_SR_LINK_STATUS)
-                break;
-
-            msec_delay(100);
-        }                       /* end for loop */
-
-        if(i == 0) {            /* We didn't get link   */
-
-            /* Reset the DSP and wait again for link.   */
-            e1000_phy_reset_dsp(shared);
-        }
-
-        /* This loop will early-out if the link condition has been met.  */
-        for(i = PHY_FORCE_TIME; i > 0; i--) {
-            if(mii_status_reg & MII_SR_LINK_STATUS)
-                break;
-
-            msec_delay(100);
-            /* Read the MII Status Register and wait for Auto-Neg
-             * Complete bit to be set.
-             */
-            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-            mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-
-        }                       /* end for loop */
-    }    /* end if wait_autoneg_complete */
-    /*
-     * Because we reset the PHY above, we need to re-force TX_CLK in the
-     * Extended PHY Specific Control Register to 25MHz clock.  This
-     * value defaults back to a 2.5MHz clock when the PHY is reset.
-     */
-    phy_data = e1000_read_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL);
-
-    phy_data |= M88E1000_EPSCR_TX_CLK_25;
-
-    e1000_write_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
-
-    /* In addition, because of the s/w reset above, we need to enable
-     * CRS on TX.  This must be set for both full and half duplex
-     * operation.
-     */
-    phy_data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
-
-    phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-
-    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_data);
-    DEBUGOUT1("M88E1000 Phy Specific Ctrl Reg = %4x\r\n", phy_data);
-
-    return;
-}
-
-/*****************************************************************************
-* Reads the value from a PHY register
-*
-* shared - Struct containing variables accessed by shared code
-* reg_addr - address of the PHY register to read
-******************************************************************************/
-uint16_t
-e1000_read_phy_reg(struct e1000_shared_adapter *shared,
-                   uint32_t reg_addr)
-{
-    uint32_t i;
-    uint32_t data = 0;
-    uint32_t command = 0;
-
-    ASSERT(reg_addr <= MAX_PHY_REG_ADDRESS);
-
-    if(shared->mac_type > e1000_82543) {
-        /* Set up Op-code, Phy Address, and
-         * register address in the MDI Control register.  The MAC will
-         * take care of interfacing with the PHY to retrieve the
-         * desired data.
-         */
-        command = ((reg_addr << E1000_MDIC_REG_SHIFT) |
-                   (shared->phy_addr << E1000_MDIC_PHY_SHIFT) | 
-                   (E1000_MDIC_OP_READ));
-
-        E1000_WRITE_REG(shared, MDIC, command);
-
-        /* Check every 10 usec to see if the read completed.  The read
-         * may take as long as 64 usecs (we'll wait 100 usecs max)
-         * from the CPU Write to the Ready bit assertion.
-         */
-        for(i = 0; i < 64; i++) {
-            usec_delay(10);
-
-            data = E1000_READ_REG(shared, MDIC);
-
-            if(data & E1000_MDIC_READY)
-                break;
-        }
-    } else {
-        /* We must first send a preamble through the MDIO pin to signal the
-         * beginning of an MII instruction.  This is done by sending 32
-         * consecutive "1" bits.
-         */
-        e1000_phy_shift_out(shared, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
-
-        /* Now combine the next few fields that are required for a read
-         * operation.  We use this method instead of calling the
-         * e1000_phy_shift_out routine five different times.  The format of
-         * a MII read instruction consists of a shift out of 14 bits and is
-         * defined as follows:
-         *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
-         * followed by a shift in of 18 bits.  This first two bits shifted
-         * in are TurnAround bits used to avoid contention on the MDIO pin
-         * when a READ operation is performed.  These two bits are thrown
-         * away followed by a shift in of 16 bits which contains the
-         * desired data.
-         */
-        command = ((reg_addr) |
-                   (shared->phy_addr << 5) |
-                   (PHY_OP_READ << 10) | (PHY_SOF << 12));
-
-        e1000_phy_shift_out(shared, command, 14);
-
-        /* Now that we've shifted out the read command to the MII, we need
-         * to "shift in" the 16-bit value (18 total bits) of the requested
-         * PHY register address.
-         */
-        data = (uint32_t) e1000_phy_shift_in(shared);
-    }
-
-    ASSERT(!(data & E1000_MDIC_ERROR));
-
-    return ((uint16_t) data);
-}
-
-/******************************************************************************
-* Writes a value to a PHY register
-*
-* shared - Struct containing variables accessed by shared code
-* reg_addr - address of the PHY register to write
-* data - data to write to the PHY
-******************************************************************************/
-void
-e1000_write_phy_reg(struct e1000_shared_adapter *shared,
-                    uint32_t reg_addr,
-                    uint16_t data)
-{
-    uint32_t i;
-    uint32_t command = 0;
-    uint32_t mdic_reg;
-
-    ASSERT(reg_addr <= MAX_PHY_REG_ADDRESS);
-
-    if(shared->mac_type > e1000_82543) {
-        /* Set up Op-code, Phy Address, register
-         * address, and data intended for the PHY register in the MDI
-         * Control register.  The MAC will take care of interfacing
-         * with the PHY to send the desired data.
-         */
-        command = (((uint32_t) data) |
-                   (reg_addr << E1000_MDIC_REG_SHIFT) |
-                   (shared->phy_addr << E1000_MDIC_PHY_SHIFT) | 
-                   (E1000_MDIC_OP_WRITE));
-
-        E1000_WRITE_REG(shared, MDIC, command);
-
-        /* Check every 10 usec to see if the read completed.  The read
-         * may take as long as 64 usecs (we'll wait 100 usecs max)
-         * from the CPU Write to the Ready bit assertion.
-         */
-        for(i = 0; i < 10; i++) {
-            usec_delay(10);
-
-            mdic_reg = E1000_READ_REG(shared, MDIC);
-
-            if(mdic_reg & E1000_MDIC_READY)
-                break;
-        }
-    } else {
-        /* We'll need to use the SW defined pins to shift the write command
-         *  out to the PHY. We first send a preamble to the PHY to signal the
-         * beginning of the MII instruction.  This is done by sending 32 
-         * consecutive "1" bits.
-         */
-        e1000_phy_shift_out(shared, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
-
-        /* Now combine the remaining required fields that will indicate
-         * a write operation.  We use this method instead of calling the
-         * e1000_phy_shift_out routine for each field in the command.  The
-         * format of a MII write instruction is as follows:
-         * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
-         */
-        command = ((PHY_TURNAROUND) |
-                   (reg_addr << 2) |
-                   (shared->phy_addr << 7) |
-                   (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
-        command <<= 16;
-        command |= ((uint32_t) data);
-
-        e1000_phy_shift_out(shared, command, 32);
-    }
-    return;
-}
-
-/******************************************************************************
-* Returns the PHY to the power-on reset state
-*
-* shared - Struct containing variables accessed by shared code
-******************************************************************************/
-void
-e1000_phy_hw_reset(struct e1000_shared_adapter *shared)
-{
-    uint32_t ctrl_reg;
-    uint32_t ctrl_ext_reg;
-
-    DEBUGFUNC("e1000_phy_hw_reset");
-
-    DEBUGOUT("Resetting Phy...\n");
-
-    if(shared->mac_type > e1000_82543) {
-        /* Read the device control register and assert the
-         * E1000_CTRL_PHY_RST bit.  Hold for 20ms and then take it out
-         * of reset.
-         */
-        ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-        ctrl_reg |= E1000_CTRL_PHY_RST;
-
-        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-        msec_delay(20);
-
-        ctrl_reg &= ~E1000_CTRL_PHY_RST;
-
-        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-        msec_delay(20);
-    } else {
-        /* Read the Extended Device Control Register, assert the
-         * PHY_RESET_DIR bit.  Then clock it out to the PHY.
-         */
-        ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
-
-        ctrl_ext_reg |= E1000_CTRL_PHY_RESET_DIR4;
-
-        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
-
-        msec_delay(20);
-
-        /* Set the reset bit in the device control register and clock
-         * it out to the PHY.
-         */
-        ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
-
-        ctrl_ext_reg &= ~E1000_CTRL_PHY_RESET4;
-
-        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
-
-        msec_delay(20);
-
-        ctrl_ext_reg = E1000_READ_REG(shared, CTRL_EXT);
-
-        ctrl_ext_reg |= E1000_CTRL_PHY_RESET4;
-
-        E1000_WRITE_REG(shared, CTRL_EXT, ctrl_ext_reg);
-
-        msec_delay(20);
-    }
-    return;
-}
-
-/******************************************************************************
-* Resets the PHY
-*
-* shared - Struct containing variables accessed by shared code
-*
-* Sets bit 15 of the MII Control regiser
-******************************************************************************/
-boolean_t
-e1000_phy_reset(struct e1000_shared_adapter *shared)
-{
-    uint16_t reg_data;
-    uint16_t i;
-
-    DEBUGFUNC("e1000_phy_reset");
-
-    /* Read the MII control register, set the reset bit and write the
-     * value back by clocking it out to the PHY.
-     */
-    reg_data = e1000_read_phy_reg(shared, PHY_CTRL);
-
-    reg_data |= MII_CR_RESET;
-
-    e1000_write_phy_reg(shared, PHY_CTRL, reg_data);
-
-    /* Wait for bit 15 of the MII Control Register to be cleared
-     * indicating the PHY has been reset.
-     */
-    i = 0;
-    while((reg_data & MII_CR_RESET) && i++ < 500) {
-        reg_data = e1000_read_phy_reg(shared, PHY_CTRL);
-        usec_delay(1);
-    }
-
-    if(i >= 500) {
-        DEBUGOUT("Timeout waiting for PHY to reset.\n");
-        return FALSE;
-    }
-    return TRUE;
-}
-
-/******************************************************************************
-* Detects which PHY is present and the speed and duplex
-*
-* shared - Struct containing variables accessed by shared code
-* ctrl_reg - current value of the device control register
-******************************************************************************/
-boolean_t
-e1000_phy_setup(struct e1000_shared_adapter *shared,
-                uint32_t ctrl_reg)
-{
-    uint16_t mii_ctrl_reg;
-    uint16_t mii_status_reg;
-    uint16_t phy_specific_ctrl_reg;
-    uint16_t mii_autoneg_adv_reg;
-    uint16_t mii_1000t_ctrl_reg;
-    uint16_t i;
-    uint16_t data;
-    uint16_t autoneg_hw_setting;
-    uint16_t autoneg_fc_setting;
-    boolean_t restart_autoneg = FALSE;
-    boolean_t force_autoneg_restart = FALSE;
-
-    DEBUGFUNC("e1000_phy_setup");
-
-    /* We want to enable the Auto-Speed Detection bit in the Device
-     * Control Register.  When set to 1, the MAC automatically detects
-     * the resolved speed of the link and self-configures appropriately.
-     * The Set Link Up bit must also be set for this behavior work
-     * properly.
-     */
-    /* Nothing but 82543 and newer */
-    ASSERT(shared->mac_type >= e1000_82543);
-
-    /* With 82543, we need to force speed/duplex
-     * on the MAC equal to what the PHY speed/duplex configuration is.
-     * In addition, on 82543, we need to perform a hardware reset
-     * on the PHY to take it out of reset.
-     */
-    if(shared->mac_type >= e1000_82544) {
-        ctrl_reg |= E1000_CTRL_SLU;
-        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-    } else {
-        ctrl_reg |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
-        E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-        if(shared->mac_type == e1000_82543)
-            e1000_phy_hw_reset(shared);
-    }
-
-    if(!e1000_detect_gig_phy(shared)) {
-        /* No PHY detected, return FALSE */
-        DEBUGOUT("PhySetup failure, did not detect valid phy.\n");
-        return (FALSE);
-    }
-
-    DEBUGOUT1("Phy ID = %x \n", shared->phy_id);
-
-    /* Read the MII Control Register. */
-    mii_ctrl_reg = e1000_read_phy_reg(shared, PHY_CTRL);
-
-    DEBUGOUT1("MII Ctrl Reg contents = %x\n", mii_ctrl_reg);
-
-    /* Check to see if the Auto Neg Enable bit is set in the MII Control
-     * Register.  If not, we could be in a situation where a driver was
-     * loaded previously and was forcing speed and duplex.  Then the
-     * driver was unloaded but a e1000_phy_hw_reset was not performed, so
-     * link was still being forced and link was still achieved.  Then
-     * the driver was reloaded with the intention to auto-negotiate, but
-     * since link is already established we end up not restarting
-     * auto-neg.  So if the auto-neg bit is not enabled and the driver
-     * is being loaded with the desire to auto-neg, we set this flag to
-     * to ensure the restart of the auto-neg engine later in the logic.
-     */
-    if(!(mii_ctrl_reg & MII_CR_AUTO_NEG_EN))
-        force_autoneg_restart = TRUE;
-
-    /* Clear the isolate bit for normal operation and write it back to
-     * the MII Control Reg.  Although the spec says this doesn't need
-     * to be done when the PHY address is not equal to zero, we do it
-     * anyway just to be safe.
-     */
-    mii_ctrl_reg &= ~(MII_CR_ISOLATE);
-
-    e1000_write_phy_reg(shared, PHY_CTRL, mii_ctrl_reg);
-
-    data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
-
-    /* Enable CRS on TX.  This must be set for half-duplex operation. */
-    data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-
-    DEBUGOUT1("M88E1000 PSCR: %x \n", data);
-
-    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, data);
-
-    data = e1000_read_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL);
-
-    /* Force TX_CLK in the Extended PHY Specific Control Register
-     * to 25MHz clock.
-     */
-    data |= M88E1000_EPSCR_TX_CLK_25;
-
-    e1000_write_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL, data);
-
-    /* Certain PHYs will set the default of MII register 4 differently.
-     * We need to check this against our fc value.  If it is
-     * different, we need to setup up register 4 correctly and restart
-     * autonegotiation.
-     */
-    /* Read the MII Auto-Neg Advertisement Register (Address 4). */
-    mii_autoneg_adv_reg = e1000_read_phy_reg(shared, PHY_AUTONEG_ADV);
-
-    /* Shift right to put 10T-Half bit in bit 0
-     * Isolate the four bits for 100/10 Full/Half.
-     */ 
-    autoneg_hw_setting = (mii_autoneg_adv_reg >> 5) & 0xF;
-
-    /* Get the 1000T settings. */
-    mii_1000t_ctrl_reg = e1000_read_phy_reg(shared, PHY_1000T_CTRL);
-
-    /* Isolate and OR in the 1000T settings. */
-    autoneg_hw_setting |= ((mii_1000t_ctrl_reg & 0x0300) >> 4);
-
-    /* mask all bits in the MII Auto-Neg Advertisement Register
-     * except for ASM_DIR and PAUSE and shift.  This value
-     * will be used later to see if we need to restart Auto-Negotiation.
-     */
-    autoneg_fc_setting = ((mii_autoneg_adv_reg & 0x0C00) >> 10);
-
-    /* Perform some bounds checking on the shared->autoneg_advertised
-     * parameter.  If this variable is zero, then set it to the default.
-     */
-    shared->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
-    /* If autoneg_advertised is zero, we assume it was not defaulted
-     * by the calling code so we set to advertise full capability.
-     */
-    if(shared->autoneg_advertised == 0)
-        shared->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
-    /* We could be in the situation where Auto-Neg has already completed
-     * and the user has not indicated any overrides.  In this case we
-     * simply need to call e1000_get_speed_and_duplex to obtain the Auto-
-     * Negotiated speed and duplex, then return.
-     */
-    if(!force_autoneg_restart && shared->autoneg &&
-       (shared->autoneg_advertised == autoneg_hw_setting) &&
-       (shared->fc == autoneg_fc_setting)) {
-
-        DEBUGOUT("No overrides - Reading MII Status Reg..\n");
-
-        /* Read the MII Status Register.  We read this twice because
-         * certain bits are "sticky" and need to be read twice.
-         */
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-
-        DEBUGOUT1("MII Status Reg contents = %x\n", mii_status_reg);
-
-        /* Do we have link now? (if so, auto-neg has completed) */
-        if(mii_status_reg & MII_SR_LINK_STATUS) {
-            data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
-            DEBUGOUT1("M88E1000 Phy Specific Status Reg contents = %x\n", data);
-
-            /* We have link, so we need to finish the config process:
-             *   1) Set up the MAC to the current PHY speed/duplex
-             *      if we are on 82543.  If we
-             *      are on newer silicon, we only need to configure
-             *      collision distance in the Transmit Control Register.
-             *   2) Set up flow control on the MAC to that established
-             *      with the link partner.
-             */
-            if(shared->mac_type >= e1000_82544)
-                e1000_config_collision_dist(shared);
-            else
-                e1000_config_mac_to_phy(shared, data);
-
-            e1000_config_fc_after_link_up(shared);
-
-            return (TRUE);
-        }
-    }
-
-    /* Options:
-     *   MDI/MDI-X = 0 (default)
-     *   0 - Auto for all speeds
-     *   1 - MDI mode
-     *   2 - MDI-X mode
-     *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
-     */
-    phy_specific_ctrl_reg = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
-
-    phy_specific_ctrl_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
-
-    switch (shared->mdix) {
-    case 1:
-        phy_specific_ctrl_reg |= M88E1000_PSCR_MDI_MANUAL_MODE;
-        break;
-    case 2:
-        phy_specific_ctrl_reg |= M88E1000_PSCR_MDIX_MANUAL_MODE;
-        break;
-    case 3:
-        phy_specific_ctrl_reg |= M88E1000_PSCR_AUTO_X_1000T;
-        break;
-    case 0:
-    default:
-        phy_specific_ctrl_reg |= M88E1000_PSCR_AUTO_X_MODE;
-        break;
-    }
-
-    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_specific_ctrl_reg);
-
-    /* Options:
-     *   disable_polarity_correction = 0 (default)
-     *       Automatic Correction for Reversed Cable Polarity
-     *   0 - Disabled
-     *   1 - Enabled
-     */
-    phy_specific_ctrl_reg = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
-
-    phy_specific_ctrl_reg &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-
-    if(shared->disable_polarity_correction == 1)
-        phy_specific_ctrl_reg |= M88E1000_PSCR_POLARITY_REVERSAL;
-
-    e1000_write_phy_reg(shared, M88E1000_PHY_SPEC_CTRL, phy_specific_ctrl_reg);
-
-    /* Options:
-     *   autoneg = 1 (default)
-     *      PHY will advertise value(s) parsed from
-     *      autoneg_advertised and fc
-     *   autoneg = 0
-     *      PHY will be set to 10H, 10F, 100H, or 100F
-     *      depending on value parsed from forced_speed_duplex.
-     */
-
-    /* Is autoneg enabled?  This is enabled by default or by software override.
-     * If so, call e1000_phy_setup_autoneg routine to parse the
-     * autoneg_advertised and fc options. If autoneg is NOT enabled, then the
-     * user should have provided a speed/duplex override.  If so, then call
-     * e1000_phy_force_speed_duplex to parse and set this up.  Otherwise,
-     * we are in an error situation and need to bail.
-     */
-    if(shared->autoneg) {
-        DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
-        restart_autoneg = e1000_phy_setup_autoneg(shared);
-    } else {
-        DEBUGOUT("Forcing speed and duplex\n");
-        e1000_phy_force_speed_duplex(shared);
-    }
-
-    /* Based on information parsed above, check the flag to indicate
-     * whether we need to restart Auto-Neg.
-     */
-    if(restart_autoneg) {
-        DEBUGOUT("Restarting Auto-Neg\n");
-
-        /* Read the MII Control Register. */
-        mii_ctrl_reg = e1000_read_phy_reg(shared, PHY_CTRL);
-
-        /* Restart auto-negotiation by setting the Auto Neg Enable bit and
-         * the Auto Neg Restart bit.
-         */
-        mii_ctrl_reg |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
-
-        e1000_write_phy_reg(shared, PHY_CTRL, mii_ctrl_reg);
-
-        /* Does the user want to wait for Auto-Neg to complete here, or
-         * check at a later time (for example, callback routine).
-         */
-        if(shared->wait_autoneg_complete)
-            e1000_wait_autoneg(shared);
-    } /* end if restart_autoneg */
-
-    /* Read the MII Status Register. */
-    mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-    mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-
-    DEBUGOUT1("Checking for link status - MII Status Reg contents = %x\n",
-              mii_status_reg);
-
-    /* Check link status.  Wait up to 100 microseconds for link to
-     * become valid.
-     */
-    for(i = 0; i < 10; i++) {
-        if(mii_status_reg & MII_SR_LINK_STATUS)
-            break;
-        usec_delay(10);
-        DEBUGOUT(". ");
-
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-    }
-
-    if(mii_status_reg & MII_SR_LINK_STATUS) {
-        /* Yes, so configure MAC to PHY settings as well as flow control
-         * registers.
-         */
-        data = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
-
-        DEBUGOUT1("M88E1000 Phy Specific Status Reg contents = %x\n", data);
-
-        /* We have link, so we need to finish the config process:
-         *   1) Set up the MAC to the current PHY speed/duplex
-         *      if we are on 82543.  If we
-         *      are on newer silicon, we only need to configure
-         *      collision distance in the Transmit Control Register.
-         *   2) Set up flow control on the MAC to that established with
-         *      the link partner.
-         */
-        if(shared->mac_type >= e1000_82544)
-            e1000_config_collision_dist(shared);
-        else
-            e1000_config_mac_to_phy(shared, data);
-
-        e1000_config_fc_after_link_up(shared);
-
-        DEBUGOUT("Valid link established!!!\n");
-    } else {
-        DEBUGOUT("Unable to establish link!!!\n");
-    }
-
-    return (TRUE);
-}
-
-/******************************************************************************
-* Configures PHY autoneg and flow control advertisement settings
-*
-* shared - Struct containing variables accessed by shared code
-******************************************************************************/
-boolean_t
-e1000_phy_setup_autoneg(struct e1000_shared_adapter *shared)
-{
-    uint16_t mii_autoneg_adv_reg;
-    uint16_t mii_1000t_ctrl_reg;
-
-    DEBUGFUNC("e1000_phy_setup_autoneg");
-
-    /* Read the MII Auto-Neg Advertisement Register (Address 4). */
-    mii_autoneg_adv_reg = e1000_read_phy_reg(shared, PHY_AUTONEG_ADV);
-
-    /* Read the MII 1000Base-T Control Register (Address 9). */
-    mii_1000t_ctrl_reg = e1000_read_phy_reg(shared, PHY_1000T_CTRL);
-
-    /* Need to parse both autoneg_advertised and fc and set up
-     * the appropriate PHY registers.  First we will parse for
-     * autoneg_advertised software override.  Since we can advertise
-     * a plethora of combinations, we need to check each bit
-     * individually.
-     */
-
-    /* First we clear all the 10/100 mb speed bits in the Auto-Neg
-     * Advertisement Register (Address 4) and the 1000 mb speed bits in
-     * the  1000Base-T Control Register (Address 9).
-     */
-    mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
-    mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
-
-    DEBUGOUT1("autoneg_advertised %x\n", shared->autoneg_advertised);
-
-    /* Do we want to advertise 10 Mb Half Duplex? */
-    if(shared->autoneg_advertised & ADVERTISE_10_HALF) {
-        DEBUGOUT("Advertise 10mb Half duplex\n");
-        mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
-    }
-
-    /* Do we want to advertise 10 Mb Full Duplex? */
-    if(shared->autoneg_advertised & ADVERTISE_10_FULL) {
-        DEBUGOUT("Advertise 10mb Full duplex\n");
-        mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
-    }
-
-    /* Do we want to advertise 100 Mb Half Duplex? */
-    if(shared->autoneg_advertised & ADVERTISE_100_HALF) {
-        DEBUGOUT("Advertise 100mb Half duplex\n");
-        mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
-    }
-
-    /* Do we want to advertise 100 Mb Full Duplex? */
-    if(shared->autoneg_advertised & ADVERTISE_100_FULL) {
-        DEBUGOUT("Advertise 100mb Full duplex\n");
-        mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
-    }
-
-    /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
-    if(shared->autoneg_advertised & ADVERTISE_1000_HALF) {
-        DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
-    }
-
-    /* Do we want to advertise 1000 Mb Full Duplex? */
-    if(shared->autoneg_advertised & ADVERTISE_1000_FULL) {
-        DEBUGOUT("Advertise 1000mb Full duplex\n");
-        mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
-    }
-
-    /* Check for a software override of the flow control settings, and
-     * setup the PHY advertisement registers accordingly.  If
-     * auto-negotiation is enabled, then software will have to set the
-     * "PAUSE" bits to the correct value in the Auto-Negotiation
-     * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
-     *
-     * The possible values of the "fc" parameter are:
-     *      0:  Flow control is completely disabled
-     *      1:  Rx flow control is enabled (we can receive pause frames
-     *          but not send pause frames).
-     *      2:  Tx flow control is enabled (we can send pause frames
-     *          but we do not support receiving pause frames).
-     *      3:  Both Rx and TX flow control (symmetric) are enabled.
-     *  other:  No software override.  The flow control configuration
-     *          in the EEPROM is used.
-     */
-    switch (shared->fc) {
-    case e1000_fc_none:        /* 0 */
-            /* Flow control (RX & TX) is completely disabled by a
-             * software over-ride.
-             */
-        mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-        break;
-    case e1000_fc_rx_pause:    /* 1 */
-            /* RX Flow control is enabled, and TX Flow control is
-             * disabled, by a software over-ride.
-             */
-
-            /* Since there really isn't a way to advertise that we are
-             * capable of RX Pause ONLY, we will advertise that we
-             * support both symmetric and asymmetric RX PAUSE.  Later
-             * (in e1000_config_fc_after_link_up) we will disable the
-             *shared's ability to send PAUSE frames.
-             */
-        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-        break;
-    case e1000_fc_tx_pause:    /* 2 */
-            /* TX Flow control is enabled, and RX Flow control is
-             * disabled, by a software over-ride.
-             */
-        mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
-        mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
-        break;
-    case e1000_fc_full:        /* 3 */
-            /* Flow control (both RX and TX) is enabled by a software
-             * over-ride.
-             */
-        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
-        break;
-    default:
-            /* We should never get here.  The value should be 0-3. */
-        DEBUGOUT("Flow control param set incorrectly\n");
-        ASSERT(0);
-        break;
-    }
-
-    /* Write the MII Auto-Neg Advertisement Register (Address 4). */
-    e1000_write_phy_reg(shared, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
-
-    DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
-
-    /* Write the MII 1000Base-T Control Register (Address 9). */
-    e1000_write_phy_reg(shared, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
-    return (TRUE);
-}
-
-/******************************************************************************
-* Sets MAC speed and duplex settings to reflect the those in the PHY
-*
-* shared - Struct containing variables accessed by shared code
-* mii_reg - data to write to the MII control register
-*
-* The contents of the PHY register containing the needed information need to
-* be passed in.
-******************************************************************************/
-void
-e1000_config_mac_to_phy(struct e1000_shared_adapter *shared,
-                        uint16_t mii_reg)
-{
-    uint32_t ctrl_reg;
-    uint32_t tctl_reg;
-    uint32_t shift;
-
-    DEBUGFUNC("e1000_config_mac_to_phy");
-
-    /* We need to read the Transmit Control register to configure the
-     * collision distance.
-     * Note: This must be done for both Half or Full Duplex.
-     */
-    tctl_reg = E1000_READ_REG(shared, TCTL);
-    DEBUGOUT1("tctl_reg = %x\n", tctl_reg);
-
-    /* Read the Device Control Register and set the bits to Force Speed
-     * and Duplex.
-     */
-    ctrl_reg = E1000_READ_REG(shared, CTRL);
-
-    ctrl_reg |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-    ctrl_reg &= ~(DEVICE_SPEED_MASK);
-
-    DEBUGOUT1("MII Register Data = %x\r\n", mii_reg);
-
-    /* Clear the ILOS bit. */
-    ctrl_reg &= ~E1000_CTRL_ILOS;
-
-    /* Set up duplex in the Device Control and Transmit Control
-     * registers depending on negotiated values.
-     */
-    if(mii_reg & M88E1000_PSSR_DPLX) {
-        ctrl_reg |= E1000_CTRL_FD;
-
-        /* We are in Full Duplex mode.  We have the same collision
-         * distance regardless of speed.
-         */
-        tctl_reg &= ~E1000_TCTL_COLD;
-        shift = E1000_FDX_COLLISION_DISTANCE;
-        shift <<= E1000_COLD_SHIFT;
-        tctl_reg |= shift;
-    } else {
-        ctrl_reg &= ~E1000_CTRL_FD;
-
-        /* We are in Half Duplex mode.  Our Half Duplex collision
-         * distance is different for Gigabit than for 10/100 so we will
-         * set accordingly.
-         */
-        if((mii_reg & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { 
-            /* 1000Mbs HDX */
-            tctl_reg &= ~E1000_TCTL_COLD;
-            shift = E1000_GB_HDX_COLLISION_DISTANCE;
-            shift <<= E1000_COLD_SHIFT;
-            tctl_reg |= shift;
-            tctl_reg |= E1000_TCTL_PBE; /* Enable Packet Bursting */
-        } else {
-            /* 10/100Mbs HDX */
-            tctl_reg &= ~E1000_TCTL_COLD;
-            shift = E1000_HDX_COLLISION_DISTANCE;
-            shift <<= E1000_COLD_SHIFT;
-            tctl_reg |= shift;
-        }
-    }
-
-    /* Set up speed in the Device Control register depending on
-     * negotiated values.
-     */
-    if((mii_reg & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
-        ctrl_reg |= E1000_CTRL_SPD_1000;
-    else if((mii_reg & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
-        ctrl_reg |= E1000_CTRL_SPD_100;
-    else
-        ctrl_reg &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
-
-    /* Write the configured values back to the Transmit Control Reg. */
-    E1000_WRITE_REG(shared, TCTL, tctl_reg);
-
-    /* Write the configured values back to the Device Control Reg. */
-    E1000_WRITE_REG(shared, CTRL, ctrl_reg);
-
-    return;
-}
-
-/******************************************************************************
-* Sets the collision distance in the Transmit Control register
-*
-* shared - Struct containing variables accessed by shared code
-*
-* Link should have been established previously. Reads the speed and duplex
-* information from the Device Status register.
-******************************************************************************/
-void
-e1000_config_collision_dist(struct e1000_shared_adapter *shared)
-{
-    uint32_t tctl_reg;
-    uint16_t speed;
-    uint16_t duplex;
-    uint32_t shift;
-
-    DEBUGFUNC("e1000_config_collision_dist");
-
-    /* Get our current speed and duplex from the Device Status Register. */
-    e1000_get_speed_and_duplex(shared, &speed, &duplex);
-
-    /* We need to configure the Collision Distance for both Full or
-     * Half Duplex.
-     */
-    tctl_reg = E1000_READ_REG(shared, TCTL);
-    DEBUGOUT1("tctl_reg = %x\n", tctl_reg);
-
-    /* mask the Collision Distance bits in the Transmit Control Reg. */
-    tctl_reg &= ~E1000_TCTL_COLD;
-
-    if(duplex == FULL_DUPLEX) {
-        /* We are in Full Duplex mode.  Therefore, the collision distance
-         * is the same regardless of speed.
-         */
-        shift = E1000_FDX_COLLISION_DISTANCE;
-        shift <<= E1000_COLD_SHIFT;
-        tctl_reg |= shift;
-    } else {
-        /* We are in Half Duplex mode.  Half Duplex collision distance is
-         * different for Gigabit vs. 10/100, so we will set accordingly.
-         */
-        if(speed == SPEED_1000) {       /* 1000Mbs HDX */
-            shift = E1000_GB_HDX_COLLISION_DISTANCE;
-            shift <<= E1000_COLD_SHIFT;
-            tctl_reg |= shift;
-            tctl_reg |= E1000_TCTL_PBE; /* Enable Packet Bursting */
-        } else {                /* 10/100Mbs HDX */
-            shift = E1000_HDX_COLLISION_DISTANCE;
-            shift <<= E1000_COLD_SHIFT;
-            tctl_reg |= shift;
-        }
-    }
-
-    /* Write the configured values back to the Transmit Control Reg. */
-    E1000_WRITE_REG(shared, TCTL, tctl_reg);
-
-    return;
-}
-
-/******************************************************************************
-* Probes the expected PHY address for known PHY IDs
-*
-* shared - Struct containing variables accessed by shared code
-******************************************************************************/
-boolean_t
-e1000_detect_gig_phy(struct e1000_shared_adapter *shared)
-{
-    uint32_t phy_id_high;
-    uint16_t phy_id_low;
-
-    DEBUGFUNC("e1000_detect_gig_phy");
-
-    /* Read the PHY ID Registers to identify which PHY is onboard. */
-    shared->phy_addr = 1;
-
-    phy_id_high = e1000_read_phy_reg(shared, PHY_ID1);
-
-    usec_delay(2);
-
-    phy_id_low = e1000_read_phy_reg(shared, PHY_ID2);
-
-    shared->phy_id = (phy_id_low | (phy_id_high << 16)) & PHY_REVISION_MASK;
-
-    if(shared->phy_id == M88E1000_12_PHY_ID ||
-       shared->phy_id == M88E1000_14_PHY_ID ||
-       shared->phy_id == M88E1000_I_PHY_ID) {
-
-        DEBUGOUT2("phy_id 0x%x detected at address 0x%x\n",
-                  shared->phy_id, shared->phy_addr);
-        return (TRUE);
-    } else {
-        DEBUGOUT("Could not auto-detect Phy!\n");
-        return (FALSE);
-    }
-}
-
-/******************************************************************************
-* Resets the PHY's DSP
-*
-* shared - Struct containing variables accessed by shared code
-******************************************************************************/
-void
-e1000_phy_reset_dsp(struct e1000_shared_adapter *shared)
-{
-    e1000_write_phy_reg(shared, 29, 0x1d);
-    e1000_write_phy_reg(shared, 30, 0xc1);
-    e1000_write_phy_reg(shared, 30, 0x00);
-    return;
-}
-
-/******************************************************************************
-* Blocks until autoneg completes or times out (~4.5 seconds)
-*
-* shared - Struct containing variables accessed by shared code
-******************************************************************************/
-boolean_t
-e1000_wait_autoneg(struct e1000_shared_adapter *shared)
-{
-    uint16_t i;
-    uint16_t mii_status_reg;
-    boolean_t autoneg_complete = FALSE;
-
-    DEBUGFUNC("e1000_wait_autoneg");
-
-    /* We will wait for autoneg to complete. */
-    DEBUGOUT("Waiting for Auto-Neg to complete.\n");
-    mii_status_reg = 0;
-
-    /* We will wait for autoneg to complete or 4.5 seconds to expire. */
-
-    for(i = PHY_AUTO_NEG_TIME; i > 0; i--) {
-        /* Read the MII Status Register and wait for Auto-Neg
-         * Complete bit to be set.
-         */
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-        mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-
-        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
-            autoneg_complete = TRUE;
-            break;
-        }
-
-        msec_delay(100);
-    }
-
-    return (autoneg_complete);
-}
-
-/******************************************************************************
-* Get PHY information from various PHY registers
-*
-* shared - Struct containing variables accessed by shared code
-* phy_status_info - PHY information structure
-******************************************************************************/
-boolean_t
-e1000_phy_get_info(struct e1000_shared_adapter *shared,
-                   struct e1000_phy_info *phy_status_info)
-{
-    uint16_t phy_mii_status_reg;
-    uint16_t phy_specific_ctrl_reg;
-    uint16_t phy_specific_status_reg;
-    uint16_t phy_specific_ext_ctrl_reg;
-    uint16_t phy_1000t_stat_reg;
-
-    phy_status_info->cable_length = e1000_cable_length_undefined;
-    phy_status_info->extended_10bt_distance =
-        e1000_10bt_ext_dist_enable_undefined;
-    phy_status_info->cable_polarity = e1000_rev_polarity_undefined;
-    phy_status_info->polarity_correction = e1000_polarity_reversal_undefined;
-    phy_status_info->link_reset = e1000_down_no_idle_undefined;
-    phy_status_info->mdix_mode = e1000_auto_x_mode_undefined;
-    phy_status_info->local_rx = e1000_1000t_rx_status_undefined;
-    phy_status_info->remote_rx = e1000_1000t_rx_status_undefined;
-
-    /* PHY info only valid for copper media. */
-    if(shared == NULL || shared->media_type != e1000_media_type_copper)
-        return FALSE;
-
-    /* PHY info only valid for LINK UP.  Read MII status reg 
-     * back-to-back to get link status.
-     */
-    phy_mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-    phy_mii_status_reg = e1000_read_phy_reg(shared, PHY_STATUS);
-    if((phy_mii_status_reg & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS)
-        return FALSE;
-
-    /* Read various PHY registers to get the PHY info. */
-    phy_specific_ctrl_reg = e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_CTRL);
-    phy_specific_status_reg =
-        e1000_read_phy_reg(shared, M88E1000_PHY_SPEC_STATUS);
-    phy_specific_ext_ctrl_reg =
-        e1000_read_phy_reg(shared, M88E1000_EXT_PHY_SPEC_CTRL);
-    phy_1000t_stat_reg = e1000_read_phy_reg(shared, PHY_1000T_STATUS);
-
-    phy_status_info->cable_length =
-        ((phy_specific_status_reg & M88E1000_PSSR_CABLE_LENGTH) >>
-         M88E1000_PSSR_CABLE_LENGTH_SHIFT);
-
-    phy_status_info->extended_10bt_distance =
-        (phy_specific_ctrl_reg & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
-        M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT;
-
-    phy_status_info->cable_polarity =
-        (phy_specific_status_reg & M88E1000_PSSR_REV_POLARITY) >>
-        M88E1000_PSSR_REV_POLARITY_SHIFT;
-
-    phy_status_info->polarity_correction =
-        (phy_specific_ctrl_reg & M88E1000_PSCR_POLARITY_REVERSAL) >>
-        M88E1000_PSCR_POLARITY_REVERSAL_SHIFT;
-
-    phy_status_info->link_reset =
-        (phy_specific_ext_ctrl_reg & M88E1000_EPSCR_DOWN_NO_IDLE) >>
-        M88E1000_EPSCR_DOWN_NO_IDLE_SHIFT;
-
-    phy_status_info->mdix_mode =
-        (phy_specific_status_reg & M88E1000_PSSR_MDIX) >>
-        M88E1000_PSSR_MDIX_SHIFT;
-
-    phy_status_info->local_rx =
-        (phy_1000t_stat_reg & SR_1000T_LOCAL_RX_STATUS) >>
-        SR_1000T_LOCAL_RX_STATUS_SHIFT;
-
-    phy_status_info->remote_rx =
-        (phy_1000t_stat_reg & SR_1000T_REMOTE_RX_STATUS) >>
-        SR_1000T_REMOTE_RX_STATUS_SHIFT;
-
-    return TRUE;
-}
-
-boolean_t
-e1000_validate_mdi_setting(struct e1000_shared_adapter *shared)
-{
-    if(!shared->autoneg && (shared->mdix == 0 || shared->mdix == 3)) {
-        shared->mdix = 1;
-        return FALSE;
-    }
-    return TRUE;
-}
diff -Nru a/drivers/net/e1000/e1000_phy.h b/drivers/net/e1000/e1000_phy.h
--- a/drivers/net/e1000/e1000_phy.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,422 +0,0 @@
-/*******************************************************************************
-
-  This software program is available to you under a choice of one of two
-  licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
-  
-  Recipient has requested a license and Intel Corporation ("Intel") is willing
-  to grant a license for the software entitled Linux Base Driver for the
-  Intel(R) PRO/1000 Family of Adapters (e1000) (the "Software") being provided
-  by Intel Corporation. The following definitions apply to this license:
-  
-  "Licensed Patents" means patent claims licensable by Intel Corporation which
-  are necessarily infringed by the use of sale of the Software alone or when
-  combined with the operating system referred to below.
-  
-  "Recipient" means the party to whom Intel delivers this Software.
-  
-  "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
-  later.
-  
-  Copyright (c) 1999 - 2002 Intel Corporation.
-  All rights reserved.
-  
-  The license is provided to Recipient and Recipient's Licensees under the
-  following terms.
-  
-  Redistribution and use in source and binary forms of the Software, with or
-  without modification, are permitted provided that the following conditions
-  are met:
-  
-  Redistributions of source code of the Software may retain the above
-  copyright notice, this list of conditions and the following disclaimer.
-  
-  Redistributions in binary form of the Software may reproduce the above
-  copyright notice, this list of conditions and the following disclaimer in
-  the documentation and/or materials provided with the distribution.
-  
-  Neither the name of Intel Corporation nor the names of its contributors
-  shall be used to endorse or promote products derived from this Software
-  without specific prior written permission.
-  
-  Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
-  royalty-free patent license under Licensed Patents to make, use, sell, offer
-  to sell, import and otherwise transfer the Software, if any, in source code
-  and object code form. This license shall include changes to the Software
-  that are error corrections or other minor changes to the Software that do
-  not add functionality or features when the Software is incorporated in any
-  version of an operating system that has been distributed under the GNU
-  General Public License 2.0 or later. This patent license shall apply to the
-  combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
-  Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
-  such combination to be covered by the Licensed Patents. The patent license
-  shall not apply to any other combinations which include the Software. NO
-  hardware per se is licensed hereunder.
-  
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-  IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-  (INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-  ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
-  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
-  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
-
-/* e1000_phy.h
- * Structures, enums, and macros for the PHY
- */
-
-#ifndef _E1000_PHY_H_
-#define _E1000_PHY_H_
-
-#include "e1000_osdep.h"
-
-/* PHY status info structure and supporting enums */
-typedef enum {
-    e1000_cable_length_50 = 0,
-    e1000_cable_length_50_80,
-    e1000_cable_length_80_110,
-    e1000_cable_length_110_140,
-    e1000_cable_length_140,
-    e1000_cable_length_undefined = 0xFF
-} e1000_cable_length;
-
-typedef enum {
-    e1000_10bt_ext_dist_enable_normal = 0,
-    e1000_10bt_ext_dist_enable_lower,
-    e1000_10bt_ext_dist_enable_undefined = 0xFF
-} e1000_10bt_ext_dist_enable;
-
-typedef enum {
-    e1000_rev_polarity_normal = 0,
-    e1000_rev_polarity_reversed,
-    e1000_rev_polarity_undefined = 0xFF
-} e1000_rev_polarity;
-
-typedef enum {
-    e1000_polarity_reversal_enabled = 0,
-    e1000_polarity_reversal_disabled,
-    e1000_polarity_reversal_undefined = 0xFF
-} e1000_polarity_reversal;
-
-typedef enum {
-    e1000_down_no_idle_no_detect = 0,
-    e1000_down_no_idle_detect,
-    e1000_down_no_idle_undefined = 0xFF
-} e1000_down_no_idle;
-
-typedef enum {
-    e1000_auto_x_mode_manual_mdi = 0,
-    e1000_auto_x_mode_manual_mdix,
-    e1000_auto_x_mode_auto1,
-    e1000_auto_x_mode_auto2,
-    e1000_auto_x_mode_undefined = 0xFF
-} e1000_auto_x_mode;
-
-typedef enum {
-    e1000_1000t_rx_status_not_ok = 0,
-    e1000_1000t_rx_status_ok,
-    e1000_1000t_rx_status_undefined = 0xFF
-} e1000_1000t_rx_status;
-
-struct e1000_phy_info {
-    e1000_cable_length cable_length;
-    e1000_10bt_ext_dist_enable extended_10bt_distance;
-    e1000_rev_polarity cable_polarity;
-    e1000_polarity_reversal polarity_correction;
-    e1000_down_no_idle link_reset;
-    e1000_auto_x_mode mdix_mode;
-    e1000_1000t_rx_status local_rx;
-    e1000_1000t_rx_status remote_rx;
-};
-
-struct e1000_phy_stats {
-    uint32_t idle_errors;
-    uint32_t receive_errors;
-};
-
-/* Function Prototypes */
-uint16_t e1000_read_phy_reg(struct e1000_shared_adapter *shared, uint32_t reg_addr);
-void e1000_write_phy_reg(struct e1000_shared_adapter *shared, uint32_t reg_addr, uint16_t data);
-void e1000_phy_hw_reset(struct e1000_shared_adapter *shared);
-boolean_t e1000_phy_reset(struct e1000_shared_adapter *shared);
-boolean_t e1000_phy_setup(struct e1000_shared_adapter *shared, uint32_t ctrl_reg);
-boolean_t e1000_phy_setup_autoneg(struct e1000_shared_adapter *shared);
-void e1000_config_mac_to_phy(struct e1000_shared_adapter *shared, uint16_t mii_reg);
-void e1000_config_collision_dist(struct e1000_shared_adapter *shared);
-boolean_t e1000_detect_gig_phy(struct e1000_shared_adapter *shared);
-void e1000_phy_reset_dsp(struct e1000_shared_adapter *shared);
-boolean_t e1000_wait_autoneg(struct e1000_shared_adapter *shared);
-boolean_t e1000_phy_get_info(struct e1000_shared_adapter *shared, struct e1000_phy_info *phy_status_info);
-boolean_t e1000_validate_mdi_setting(struct e1000_shared_adapter *shared);
-
-/* Bit definitions for the Management Data IO (MDIO) and Management Data
- * Clock (MDC) pins in the Device Control Register.
- */
-#define E1000_CTRL_PHY_RESET_DIR  E1000_CTRL_SWDPIO0
-#define E1000_CTRL_PHY_RESET      E1000_CTRL_SWDPIN0
-#define E1000_CTRL_MDIO_DIR       E1000_CTRL_SWDPIO2
-#define E1000_CTRL_MDIO           E1000_CTRL_SWDPIN2
-#define E1000_CTRL_MDC_DIR        E1000_CTRL_SWDPIO3
-#define E1000_CTRL_MDC            E1000_CTRL_SWDPIN3
-#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR
-#define E1000_CTRL_PHY_RESET4     E1000_CTRL_EXT_SDP4_DATA
-
-/* PHY 1000 MII Register/Bit Definitions */
-/* PHY Registers defined by IEEE */
-#define PHY_CTRL         0x00 /* Control Register */
-#define PHY_STATUS       0x01 /* Status Regiser */
-#define PHY_ID1          0x02 /* Phy Id Reg (word 1) */
-#define PHY_ID2          0x03 /* Phy Id Reg (word 2) */
-#define PHY_AUTONEG_ADV  0x04 /* Autoneg Advertisement */
-#define PHY_LP_ABILITY   0x05 /* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP  0x06 /* Autoneg Expansion Reg */
-#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
-#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
-#define PHY_1000T_CTRL   0x09 /* 1000Base-T Control Reg */
-#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
-#define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
-
-/* M88E1000 Specific Registers */
-#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
-#define M88E1000_PHY_SPEC_STATUS   0x11  /* PHY Specific Status Register */
-#define M88E1000_INT_ENABLE        0x12  /* Interrupt Enable Register */
-#define M88E1000_INT_STATUS        0x13  /* Interrupt Status Register */
-#define M88E1000_EXT_PHY_SPEC_CTRL 0x14  /* Extended PHY Specific Control */
-#define M88E1000_RX_ERR_CNTR       0x15  /* Receive Error Counter */
-
-#define MAX_PHY_REG_ADDRESS 0x1F        /* 5 bit address bus (0-0x1F) */
-
-/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
-#define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
-#define MII_CR_ISOLATE          0x0400  /* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN       0x0800  /* Power down */
-#define MII_CR_AUTO_NEG_EN      0x1000  /* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB 0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK         0x4000  /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET            0x8000  /* 0 = normal, 1 = PHY reset */
-
-/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS     0x0001 /* Extended register capabilities */
-#define MII_SR_JABBER_DETECT     0x0002 /* Jabber Detected */
-#define MII_SR_LINK_STATUS       0x0004 /* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS      0x0008 /* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT      0x0010 /* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE  0x0020 /* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS   0x0100 /* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS     0x0200 /* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS     0x0400 /* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS       0x0800 /* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS       0x1000 /* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS      0x2000 /* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS      0x4000 /* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS        0x8000 /* 100T4 Capable */
-
-/* Autoneg Advertisement Register */
-#define NWAY_AR_SELECTOR_FIELD 0x0001   /* indicates IEEE 802.3 CSMA/CD */
-#define NWAY_AR_10T_HD_CAPS    0x0020   /* 10T   Half Duplex Capable */
-#define NWAY_AR_10T_FD_CAPS    0x0040   /* 10T   Full Duplex Capable */
-#define NWAY_AR_100TX_HD_CAPS  0x0080   /* 100TX Half Duplex Capable */
-#define NWAY_AR_100TX_FD_CAPS  0x0100   /* 100TX Full Duplex Capable */
-#define NWAY_AR_100T4_CAPS     0x0200   /* 100T4 Capable */
-#define NWAY_AR_PAUSE          0x0400   /* Pause operation desired */
-#define NWAY_AR_ASM_DIR        0x0800   /* Asymmetric Pause Direction bit */
-#define NWAY_AR_REMOTE_FAULT   0x2000   /* Remote Fault detected */
-#define NWAY_AR_NEXT_PAGE      0x8000   /* Next Page ability supported */
-
-/* Link Partner Ability Register (Base Page) */
-#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
-#define NWAY_LPAR_10T_HD_CAPS    0x0020 /* LP is 10T   Half Duplex Capable */
-#define NWAY_LPAR_10T_FD_CAPS    0x0040 /* LP is 10T   Full Duplex Capable */
-#define NWAY_LPAR_100TX_HD_CAPS  0x0080 /* LP is 100TX Half Duplex Capable */
-#define NWAY_LPAR_100TX_FD_CAPS  0x0100 /* LP is 100TX Full Duplex Capable */
-#define NWAY_LPAR_100T4_CAPS     0x0200 /* LP is 100T4 Capable */
-#define NWAY_LPAR_PAUSE          0x0400 /* LP Pause operation desired */
-#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */
-#define NWAY_LPAR_REMOTE_FAULT   0x2000 /* LP has detected Remote Fault */
-#define NWAY_LPAR_ACKNOWLEDGE    0x4000 /* LP has rx'd link code word */
-#define NWAY_LPAR_NEXT_PAGE      0x8000 /* Next Page ability supported */
-
-/* Autoneg Expansion Register */
-#define NWAY_ER_LP_NWAY_CAPS      0x0001 /* LP has Auto Neg Capability */
-#define NWAY_ER_PAGE_RXD          0x0002 /* LP is 10T   Half Duplex Capable */
-#define NWAY_ER_NEXT_PAGE_CAPS    0x0004 /* LP is 10T   Full Duplex Capable */
-#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
-#define NWAY_ER_PAR_DETECT_FAULT  0x0100 /* LP is 100TX Full Duplex Capable */
-
-/* Next Page TX Register */
-#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
-#define NPTX_TOGGLE         0x0800 /* Toggles between exchanges
-                                    * of different NP
-                                    */
-#define NPTX_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg
-                                    * 0 = cannot comply with msg
-                                    */
-#define NPTX_MSG_PAGE       0x2000 /* formatted(1)/unformatted(0) pg */
-#define NPTX_NEXT_PAGE      0x8000 /* 1 = addition NP will follow 
-                                    * 0 = sending last NP
-                                    */
-
-/* Link Partner Next Page Register */
-#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
-#define LP_RNPR_TOGGLE         0x0800 /* Toggles between exchanges
-                                       * of different NP
-                                       */
-#define LP_RNPR_ACKNOWLDGE2    0x1000 /* 1 = will comply with msg 
-                                       * 0 = cannot comply with msg
-                                       */
-#define LP_RNPR_MSG_PAGE       0x2000  /* formatted(1)/unformatted(0) pg */
-#define LP_RNPR_ACKNOWLDGE     0x4000  /* 1 = ACK / 0 = NO ACK */
-#define LP_RNPR_NEXT_PAGE      0x8000  /* 1 = addition NP will follow
-                                        * 0 = sending last NP 
-                                        */
-
-/* 1000BASE-T Control Register */
-#define CR_1000T_ASYM_PAUSE      0x0080 /* Advertise asymmetric pause bit */
-#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
-#define CR_1000T_FD_CAPS         0x0200 /* Advertise 1000T FD capability  */
-#define CR_1000T_REPEATER_DTE    0x0400 /* 1=Repeater/switch device port */
-                                        /* 0=DTE device */
-#define CR_1000T_MS_VALUE        0x0800 /* 1=Configure PHY as Master */
-                                        /* 0=Configure PHY as Slave */
-#define CR_1000T_MS_ENABLE       0x1000 /* 1=Master/Slave manual config value */
-                                        /* 0=Automatic Master/Slave config */
-#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
-#define CR_1000T_TEST_MODE_1     0x2000 /* Transmit Waveform test */
-#define CR_1000T_TEST_MODE_2     0x4000 /* Master Transmit Jitter test */
-#define CR_1000T_TEST_MODE_3     0x6000 /* Slave Transmit Jitter test */
-#define CR_1000T_TEST_MODE_4     0x8000 /* Transmitter Distortion test */
-
-/* 1000BASE-T Status Register */
-#define SR_1000T_IDLE_ERROR_CNT   0x00FF /* Num idle errors since last read */
-#define SR_1000T_ASYM_PAUSE_DIR   0x0100 /* LP asymmetric pause direction bit */
-#define SR_1000T_LP_HD_CAPS       0x0400 /* LP is 1000T HD capable */
-#define SR_1000T_LP_FD_CAPS       0x0800 /* LP is 1000T FD capable */
-#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
-#define SR_1000T_LOCAL_RX_STATUS  0x2000 /* Local receiver OK */
-#define SR_1000T_MS_CONFIG_RES    0x4000 /* 1=Local TX is Master, 0=Slave */
-#define SR_1000T_MS_CONFIG_FAULT  0x8000 /* Master/Slave config fault */
-#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12
-#define SR_1000T_LOCAL_RX_STATUS_SHIFT  13
-
-/* Extended Status Register */
-#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
-#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
-#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
-#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
-
-#define PHY_TX_POLARITY_MASK   0x0100 /* register 10h bit 8 (polarity bit) */
-#define PHY_TX_NORMAL_POLARITY 0      /* register 10h bit 8 (normal polarity) */
-
-#define AUTO_POLARITY_DISABLE  0x0010 /* register 11h bit 4 */
-                                      /* (0=enable, 1=disable) */
-
-/* M88E1000 PHY Specific Control Register */
-#define M88E1000_PSCR_JABBER_DISABLE    0x0001 /* 1=Jabber Function disabled */
-#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
-#define M88E1000_PSCR_SQE_TEST          0x0004 /* 1=SQE Test enabled */
-#define M88E1000_PSCR_CLK125_DISABLE    0x0010 /* 1=CLK125 low, 
-                                                * 0=CLK125 toggling
-                                                */
-#define M88E1000_PSCR_MDI_MANUAL_MODE  0x0000  /* MDI Crossover Mode bits 6:5 */
-                                               /* Manual MDI configuration */
-#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020  /* Manual MDIX configuration */
-#define M88E1000_PSCR_AUTO_X_1000T     0x0040  /* 1000BASE-T: Auto crossover,
-                                                *  100BASE-TX/10BASE-T: 
-                                                *  MDI Mode
-                                                */
-#define M88E1000_PSCR_AUTO_X_MODE      0x0060  /* Auto crossover enabled 
-                                                * all speeds. 
-                                                */
-#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 
-                                        /* 1=Enable Extended 10BASE-T distance
-                                         * (Lower 10BASE-T RX Threshold)
-                                         * 0=Normal 10BASE-T RX Threshold */
-#define M88E1000_PSCR_MII_5BIT_ENABLE      0x0100
-                                        /* 1=5-Bit interface in 100BASE-TX
-                                         * 0=MII interface in 100BASE-TX */
-#define M88E1000_PSCR_SCRAMBLER_DISABLE    0x0200 /* 1=Scrambler disable */
-#define M88E1000_PSCR_FORCE_LINK_GOOD      0x0400 /* 1=Force link good */
-#define M88E1000_PSCR_ASSERT_CRS_ON_TX     0x0800 /* 1=Assert CRS on Transmit */
-
-#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT    1
-#define M88E1000_PSCR_AUTO_X_MODE_SHIFT          5
-#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
-
-/* M88E1000 PHY Specific Status Register */
-#define M88E1000_PSSR_JABBER             0x0001 /* 1=Jabber */
-#define M88E1000_PSSR_REV_POLARITY       0x0002 /* 1=Polarity reversed */
-#define M88E1000_PSSR_MDIX               0x0040 /* 1=MDIX; 0=MDI */
-#define M88E1000_PSSR_CABLE_LENGTH       0x0380 /* 0=<50M;1=50-80M;2=80-110M;
-                                            * 3=110-140M;4=>140M */
-#define M88E1000_PSSR_LINK               0x0400 /* 1=Link up, 0=Link down */
-#define M88E1000_PSSR_SPD_DPLX_RESOLVED  0x0800 /* 1=Speed & Duplex resolved */
-#define M88E1000_PSSR_PAGE_RCVD          0x1000 /* 1=Page received */
-#define M88E1000_PSSR_DPLX               0x2000 /* 1=Duplex 0=Half Duplex */
-#define M88E1000_PSSR_SPEED              0xC000 /* Speed, bits 14:15 */
-#define M88E1000_PSSR_10MBS              0x0000 /* 00=10Mbs */
-#define M88E1000_PSSR_100MBS             0x4000 /* 01=100Mbs */
-#define M88E1000_PSSR_1000MBS            0x8000 /* 10=1000Mbs */
-
-#define M88E1000_PSSR_REV_POLARITY_SHIFT 1
-#define M88E1000_PSSR_MDIX_SHIFT         6
-#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
-
-/* M88E1000 Extended PHY Specific Control Register */
-#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
-#define M88E1000_EPSCR_DOWN_NO_IDLE   0x8000 /* 1=Lost lock detect enabled.
-                                              * Will assert lost lock and bring
-                                              * link down if idle not seen
-                                              * within 1ms in 1000BASE-T 
-                                              */
-#define M88E1000_EPSCR_TX_CLK_2_5     0x0060 /* 2.5 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_0       0x0000 /* NO  TX_CLK */
-
-#define M88E1000_EPSCR_DOWN_NO_IDLE_SHIFT 15
-
-/* Bit definitions for valid PHY IDs. */
-#define M88E1000_12_PHY_ID 0x01410C50
-#define M88E1000_14_PHY_ID 0x01410C40
-#define M88E1000_I_PHY_ID  0x01410C30
-
-/* Miscellaneous PHY bit definitions. */
-#define PHY_PREAMBLE        0xFFFFFFFF
-#define PHY_SOF             0x01
-#define PHY_OP_READ         0x02
-#define PHY_OP_WRITE        0x01
-#define PHY_TURNAROUND      0x02
-#define PHY_PREAMBLE_SIZE   32
-#define MII_CR_SPEED_1000   0x0040
-#define MII_CR_SPEED_100    0x2000
-#define MII_CR_SPEED_10     0x0000
-#define E1000_PHY_ADDRESS   0x01
-#define PHY_AUTO_NEG_TIME   45  /* 4.5 Seconds */
-#define PHY_FORCE_TIME      20  /* 2.0 Seconds */
-#define PHY_REVISION_MASK   0xFFFFFFF0
-#define DEVICE_SPEED_MASK   0x00000300  /* Device Ctrl Reg Speed Mask */
-#define REG4_SPEED_MASK     0x01E0
-#define REG9_SPEED_MASK     0x0300
-#define ADVERTISE_10_HALF   0x0001
-#define ADVERTISE_10_FULL   0x0002
-#define ADVERTISE_100_HALF  0x0004
-#define ADVERTISE_100_FULL  0x0008
-#define ADVERTISE_1000_HALF 0x0010
-#define ADVERTISE_1000_FULL 0x0020
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F  /* Everything but 1000-Half */
-
-#endif /* _E1000_PHY_H_ */
diff -Nru a/drivers/net/e1000/e1000_proc.c b/drivers/net/e1000/e1000_proc.c
--- a/drivers/net/e1000/e1000_proc.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/e1000/e1000_proc.c	Sun Apr 14 12:16:56 2002
@@ -2,9 +2,8 @@
 
   This software program is available to you under a choice of one of two
   licenses. You may choose to be licensed under either the GNU General Public
-  License (GPL) Version 2, June 1991, available at
-  http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License, the
-  text of which follows:
+  License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
+  or the Intel BSD + Patent License, the text of which follows:
   
   Recipient has requested a license and Intel Corporation ("Intel") is willing
   to grant a license for the software entitled Linux Base Driver for the
@@ -18,7 +17,7 @@
   "Recipient" means the party to whom Intel delivers this Software.
   
   "Licensee" means Recipient and those third parties that receive a license to
-  any operating system available under the GNU Public License version 2.0 or
+  any operating system available under the GNU General Public License 2.0 or
   later.
   
   Copyright (c) 1999 - 2002 Intel Corporation.
@@ -51,10 +50,10 @@
   version of an operating system that has been distributed under the GNU
   General Public License 2.0 or later. This patent license shall apply to the
   combination of the Software and any operating system licensed under the GNU
-  Public License version 2.0 or later if, at the time Intel provides the
+  General Public License 2.0 or later if, at the time Intel provides the
   Software to Recipient, such addition of the Software to the then publicly
-  available versions of such operating systems available under the GNU Public
-  License version 2.0 or later (whether in gold, beta or alpha form) causes
+  available versions of such operating systems available under the GNU General
+  Public License 2.0 or later (whether in gold, beta or alpha form) causes
   such combination to be covered by the Licensed Patents. The patent license
   shall not apply to any other combinations which include the Software. NO
   hardware per se is licensed hereunder.
@@ -96,7 +95,9 @@
 #include <linux/proc_fs.h>
 
 #define ADAPTERS_PROC_DIR           "PRO_LAN_Adapters"
-#define TAG_MAX_LENGTH              36
+#define TAG_MAX_LENGTH              32
+#define LINE_MAX_LENGTH             80
+#define FIELD_MAX_LENGTH            LINE_MAX_LENGTH - TAG_MAX_LENGTH - 3
 
 extern char e1000_driver_name[];
 extern char e1000_driver_version[];
@@ -110,7 +111,7 @@
 
 struct proc_list {
 	struct list_head list;                  /* link list */
-	char tag[TAG_MAX_LENGTH];               /* attribute name */
+	char tag[TAG_MAX_LENGTH + 1];           /* attribute name */
 	void *data;                             /* attribute data */
 	size_t len;				/* sizeof data */
 	char *(*func)(void *, size_t, char *);  /* format data func */
@@ -142,15 +143,20 @@
 	struct list_head *proc_list_head = data, *curr;
 	struct proc_list *elem;
 	char *p = page;
-	char buf[64];
+	char buf[FIELD_MAX_LENGTH + 1];
 
 	list_for_each(curr, proc_list_head) {
 		elem = list_entry(curr, struct proc_list, list);
 
-		if(strlen(elem->tag) == 0)
+		if (p - page + LINE_MAX_LENGTH >= PAGE_SIZE)
+			break;
+
+		if(!strlen(elem->tag))
 			p += sprintf(p, "\n");
 		else
-			p += sprintf(p, "%-32s %s\n", elem->tag,
+			p += sprintf(p, "%-*.*s %.*s\n", 
+				TAG_MAX_LENGTH, TAG_MAX_LENGTH,
+				elem->tag, FIELD_MAX_LENGTH,
 				elem->func(elem->data, elem->len, buf));
 	}
 
@@ -165,7 +171,8 @@
 {
 	struct proc_list *elem = data;
 
-	sprintf(page, "%s", elem->func(elem->data, elem->len, page));
+	sprintf(page, "%.*s", FIELD_MAX_LENGTH, elem->func(elem->data, 
+	        elem->len, page));
 
 	return e1000_proc_read(page, start, off, count, eof);
 }
@@ -179,8 +186,7 @@
 	for(intel_proc_dir = proc_net->subdir; intel_proc_dir;
 		intel_proc_dir = intel_proc_dir->next) {
 		if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&
-			(memcmp(intel_proc_dir->name,
-			ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)) == 0))
+		   !memcmp(intel_proc_dir->name, ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)))
 			break;
 	}
 
@@ -224,8 +230,6 @@
 
 	if(!proc_dir)
 		remove_proc_entry(ADAPTERS_PROC_DIR, proc_net);
-
-	return;
 }
 
 
@@ -241,7 +245,7 @@
 
 		elem = list_entry(curr, struct proc_list, list);
 
-		if(strlen(elem->tag) == 0)
+		if(!strlen(elem->tag))
 			continue;
 
 		if(!(proc_entry =
@@ -256,8 +260,9 @@
 	return 1;
 }
 
-static int __devinit
-e1000_proc_dirs_create(char *name, struct list_head *proc_list_head)
+static void __devinit
+e1000_proc_dirs_create(void *data, char *name, 
+                       struct list_head *proc_list_head)
 {
 	struct proc_dir_entry *intel_proc_dir, *proc_dir, *info_entry;
 	char info_name[strlen(name) + strlen(".info")];
@@ -265,8 +270,7 @@
 	for(intel_proc_dir = proc_net->subdir; intel_proc_dir;
 		intel_proc_dir = intel_proc_dir->next) {
 		if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&
-			(memcmp(intel_proc_dir->name,
-			ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)) == 0))
+		   !memcmp(intel_proc_dir->name, ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)))
 			break;
 	}
 
@@ -274,28 +278,26 @@
 		if(!(intel_proc_dir =
 			create_proc_entry(ADAPTERS_PROC_DIR,
 				S_IFDIR, proc_net)))
-			return 0;
+			return;
 
 	if(!(proc_dir =
 		create_proc_entry(name, S_IFDIR, intel_proc_dir)))
-		return 0;
+		return;
 	SET_MODULE_OWNER(proc_dir);
 
 	if(!e1000_proc_singles_create(proc_dir, proc_list_head))
-		return 0;
+		return;
 
 	strcpy(info_name, name);
 	strcat(info_name, ".info");
 
 	if(!(info_entry =
 		create_proc_entry(info_name, S_IFREG, intel_proc_dir)))
-		return 0;
+		return;
 	SET_MODULE_OWNER(info_entry);
 
 	info_entry->read_proc = e1000_proc_info_read;
 	info_entry->data = proc_list_head;
-
-	return 1;
 }
 
 static void __devinit
@@ -315,8 +317,6 @@
 	new->func = func;
 
 	list_add_tail(&new->list, proc_list_head);
-
-	return;
 }
 
 static void __devexit
@@ -329,8 +329,6 @@
 		list_del(&elem->list);
 		kfree(elem);
 	}
-
-	return;
 }
 
 /*
@@ -491,7 +489,7 @@
 {
 	struct e1000_adapter *adapter = data;
 	sprintf(buf,
-		adapter->shared.media_type == e1000_media_type_copper ?
+		adapter->hw.media_type == e1000_media_type_copper ?
 		"Copper" : "Fiber");
 	return buf;
 }
@@ -547,18 +545,6 @@
 	sprintf(buf,
 		correction == e1000_polarity_reversal_enabled  ? "Disabled" :
 		correction == e1000_polarity_reversal_disabled ? "Enabled"  :
-		"Undefined");
-	return buf;
-}
-
-static char *
-e1000_proc_link_reset_enabled(void *data, size_t len, char *buf)
-{
-	struct e1000_adapter *adapter = data;
-	e1000_down_no_idle link_reset = adapter->phy_info.link_reset;
-	sprintf(buf,
-		link_reset == e1000_down_no_idle_no_detect ? "Disabled" :
-		link_reset == e1000_down_no_idle_detect    ? "Enabled"  :
 		"Unknown");
 	return buf;
 }
@@ -568,7 +554,10 @@
 {
 	struct e1000_adapter *adapter = data;
 	e1000_auto_x_mode mdix_mode = adapter->phy_info.mdix_mode;
-	sprintf(buf, mdix_mode == 0 ? "MDI" : "MDI-X");
+	sprintf(buf, 
+		mdix_mode == e1000_auto_x_mode_manual_mdi  ? "MDI"   : 
+		mdix_mode == e1000_auto_x_mode_manual_mdix ? "MDI-X" :
+		"Unknown");
 	return buf;
 }
 
@@ -601,7 +590,7 @@
 static void __devinit
 e1000_proc_list_setup(struct e1000_adapter *adapter)
 {
-	struct e1000_shared_adapter *shared = &adapter->shared;
+	struct e1000_hw *hw = &adapter->hw;
 	struct list_head *proc_list_head = &adapter->proc_list_head;
 
 	INIT_LIST_HEAD(proc_list_head);
@@ -610,21 +599,21 @@
 	LIST_ADD_F("Part_Number", &adapter->part_num, e1000_proc_part_number);
 	LIST_ADD_S("Driver_Name", e1000_driver_name);
 	LIST_ADD_S("Driver_Version", e1000_driver_version);
-	LIST_ADD_H("PCI_Vendor", &shared->vendor_id);
-	LIST_ADD_H("PCI_Device_ID", &shared->device_id);
-	LIST_ADD_H("PCI_Subsystem_Vendor", &shared->subsystem_vendor_id);
-	LIST_ADD_H("PCI_Subsystem_ID", &shared->subsystem_id);
-	LIST_ADD_H("PCI_Revision_ID", &shared->revision_id);
+	LIST_ADD_H("PCI_Vendor", &hw->vendor_id);
+	LIST_ADD_H("PCI_Device_ID", &hw->device_id);
+	LIST_ADD_H("PCI_Subsystem_Vendor", &hw->subsystem_vendor_id);
+	LIST_ADD_H("PCI_Subsystem_ID", &hw->subsystem_id);
+	LIST_ADD_H("PCI_Revision_ID", &hw->revision_id);
 	LIST_ADD_U("PCI_Bus", &adapter->pdev->bus->number);
 	LIST_ADD_F("PCI_Slot", adapter, e1000_proc_slot);
 
-	if(adapter->shared.mac_type >= e1000_82543) {
+	if(adapter->hw.mac_type >= e1000_82543) {
 		LIST_ADD_F("PCI_Bus_Type",
-		           &shared->bus_type, e1000_proc_bus_type);
+		           &hw->bus_type, e1000_proc_bus_type);
 		LIST_ADD_F("PCI_Bus_Speed",
-		           &shared->bus_speed, e1000_proc_bus_speed);
+		           &hw->bus_speed, e1000_proc_bus_speed);
 		LIST_ADD_F("PCI_Bus_Width",
-		           &shared->bus_width, e1000_proc_bus_width);
+		           &hw->bus_width, e1000_proc_bus_width);
 	}
 
 	LIST_ADD_U("IRQ", &adapter->pdev->irq);
@@ -632,7 +621,7 @@
 	LIST_ADD_F("Current_HWaddr",
 	            adapter->netdev->dev_addr, e1000_proc_hwaddr);
 	LIST_ADD_F("Permanent_HWaddr",
-	            adapter->shared.perm_mac_addr, e1000_proc_hwaddr);
+	            adapter->hw.perm_mac_addr, e1000_proc_hwaddr);
 
 	LIST_ADD_BLANK();
 
@@ -679,7 +668,7 @@
 	LIST_ADD_U("Rx_Short_Length_Errors", &adapter->stats.ruc);
 	
 	/* The 82542 does not have an alignment error count register */
-	if(adapter->shared.mac_type >= e1000_82543)
+	if(adapter->hw.mac_type >= e1000_82543)
 		LIST_ADD_U("Rx_Align_Errors", &adapter->stats.algnerrc);
 	
 	LIST_ADD_U("Rx_Flow_Control_XON", &adapter->stats.xonrxc);
@@ -693,7 +682,7 @@
 
 	/* Cable diags */
 	LIST_ADD_F("PHY_Media_Type", adapter, e1000_proc_media_type);
-	if(adapter->shared.media_type == e1000_media_type_copper) {
+	if(adapter->hw.media_type == e1000_media_type_copper) {
 		LIST_ADD_F("PHY_Cable_Length",
 		           adapter, e1000_proc_cable_length);
 		LIST_ADD_F("PHY_Extended_10Base_T_Distance",
@@ -704,8 +693,6 @@
 		           adapter, e1000_proc_polarity_correction);
 		LIST_ADD_U("PHY_Idle_Errors", 
 		           &adapter->phy_stats.idle_errors);
-		LIST_ADD_F("PHY_Link_Reset_Enabled",
-		           adapter, e1000_proc_link_reset_enabled);
 		LIST_ADD_U("PHY_Receive_Errors",
 		           &adapter->phy_stats.receive_errors);
 		LIST_ADD_F("PHY_MDI_X_Enabled",
@@ -718,7 +705,6 @@
 			   e1000_proc_rx_status);
 	}
 
-	return;
 }
 
 /*
@@ -731,9 +717,9 @@
 {
 	e1000_proc_list_setup(adapter);
 
-	e1000_proc_dirs_create(adapter->netdev->name,&adapter->proc_list_head);
-
-	return;
+	e1000_proc_dirs_create(adapter, 
+	                       adapter->netdev->name,
+	                       &adapter->proc_list_head);
 }
 
 /*
@@ -747,8 +733,6 @@
 	e1000_proc_dirs_free(adapter->netdev->name, &adapter->proc_list_head);
 
 	e1000_proc_list_free(&adapter->proc_list_head);
-
-	return;
 }
 
 #else /* CONFIG_PROC_FS */
diff -Nru a/drivers/net/e2100.c b/drivers/net/e2100.c
--- a/drivers/net/e2100.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/e2100.c	Sun Apr 14 12:16:59 2002
@@ -72,7 +72,7 @@
 #define E21_SAPROM		0x10	/* Offset to station address data. */
 #define E21_IO_EXTENT	 0x20
 
-extern inline void mem_on(short port, volatile char *mem_base,
+static inline void mem_on(short port, volatile char *mem_base,
 						  unsigned char start_page )
 {
 	/* This is a little weird: set the shared memory window by doing a
@@ -82,7 +82,7 @@
 	outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
 }
 
-extern inline void mem_off(short port)
+static inline void mem_off(short port)
 {
 	inb(port + E21_MEM_ENABLE);
 	outb(0x00, port + E21_MEM_ENABLE);
@@ -234,8 +234,8 @@
 #ifdef notdef
 	/* These values are unused.  The E2100 has a 2K window into the packet
 	   buffer.  The window can be set to start on any page boundary. */
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = dev->rmem_end = dev->mem_start + 2*1024;
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+	dev->mem_end = ei_status.rmem_end = dev->mem_start + 2*1024;
 #endif
 
 	printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/eepro100.c	Sun Apr 14 12:16:59 2002
@@ -826,8 +826,9 @@
 	sp->phy[0] = eeprom[6];
 	sp->phy[1] = eeprom[7];
 	sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;
-	if (((pdev->device > 0x1030 && (pdev->device < 0x1039))) 
-	    || (pdev->device == 0x2449)) {
+	if (((pdev->device > 0x1030 && (pdev->device < 0x103F))) 
+	    || (pdev->device == 0x2449) || (pdev->device == 0x2459) 
+            || (pdev->device == 0x245D)) {
 	    	sp->chip_id = 1;
 	}
 
@@ -1795,6 +1796,7 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			sp->stats.rx_packets++;
 			sp->stats.rx_bytes += pkt_len;
 		}
@@ -2284,8 +2286,17 @@
 	{ PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1228, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0,}
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/epic100.c	Sun Apr 14 12:16:58 2002
@@ -60,11 +60,14 @@
 	LK1.1.12:
 	* fix power-up sequence
 
+	LK1.1.13:
+	* revert version 1.1.12, power-up sequence "fix"
+
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.12"
-#define DRV_RELDATE	"Jan 18, 2002"
+#define DRV_VERSION	"1.11+LK1.1.13"
+#define DRV_RELDATE	"Mar 20, 2002"
 
 
 /* The user-configurable values.
@@ -678,8 +681,9 @@
 	   required by the details of which bits are reset and the transceiver
 	   wiring on the Ositech CardBus card.
 	*/
-
-	outl(0x12, ioaddr + MIICfg);
+#if 0
+	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+#endif
 	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c
--- a/drivers/net/es3210.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/es3210.c	Sun Apr 14 12:16:56 2002
@@ -233,9 +233,9 @@
 		printk(" assigning ");
 	}
 
-	dev->mem_end = dev->rmem_end = dev->mem_start
+	dev->mem_end = ei_status.rmem_end = dev->mem_start
 		+ (ES_STOP_PG - ES_START_PG)*256;
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
 
 	printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
 
@@ -335,12 +335,12 @@
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (ES_START_PG<<8);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* Packet wraps over end of ring buffer. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
 		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
diff -Nru a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c
--- a/drivers/net/gt96100eth.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/gt96100eth.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000 MontaVista Software Inc.
+ * Copyright 2000, 2001 MontaVista Software Inc.
  * Author: MontaVista Software, Inc.
  *         	stevel@mvista.com or source@mvista.com
  *
@@ -22,8 +22,23 @@
  *
  * Ethernet driver for the MIPS GT96100 Advanced Communication Controller.
  * 
+ *  Revision history
+ *    
+ *    11.11.2001  Moved to 2.4.14, ppopov@mvista.com.  Modified driver to add
+ *                proper gt96100A support.
+ *    12.05.2001  Moved eth port 0 to irq 3 (mapped to GT_SERINT0 on EV96100A)
+ *                in order for both ports to work. Also cleaned up boot
+ *                option support (mac address string parsing), fleshed out
+ *                gt96100_cleanup_module(), and other general code cleanups
+ *                <stevel@mvista.com>.
  */
 
+#ifndef __OPTIMIZE__
+#error You must compile this file with the correct options!
+#error See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
 #ifndef __mips__
 #error This driver only works with MIPS architectures!
 #endif
@@ -45,34 +60,49 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
+#include <linux/ctype.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
-#include "gt96100eth.h"
+#define DESC_BE 1
+#define DESC_DATA_BE 1
 
-#ifdef GT96100_DEBUG
-static int gt96100_debug = GT96100_DEBUG;
-#else
-static int gt96100_debug = 3;
-#endif
+#define GT96100_DEBUG 2
+
+#include "gt96100eth.h"
 
 // prototypes
-static void *dmaalloc(size_t size, dma_addr_t * dma_handle);
+static void* dmaalloc(size_t size, dma_addr_t *dma_handle);
 static void dmafree(size_t size, void *vaddr);
+static void gt96100_delay(int msec);
 static int gt96100_add_hash_entry(struct net_device *dev,
-				  unsigned char *addr);
+				  unsigned char* addr);
 static void read_mib_counters(struct gt96100_private *gp);
-static int read_MII(struct net_device *dev, u32 reg);
-static int write_MII(struct net_device *dev, u32 reg, u16 data);
-static void dump_MII(struct net_device *dev);
+static int read_MII(int phy_addr, u32 reg);
+static int write_MII(int phy_addr, u32 reg, u16 data);
+#if 0
+static void dump_tx_ring(struct net_device *dev);
+static void dump_rx_ring(struct net_device *dev);
+#endif
+static int gt96100_init_module(void);
+static void gt96100_cleanup_module(void);
+static void dump_MII(int dbg_lvl, struct net_device *dev);
+static void dump_tx_desc(int dbg_lvl, struct net_device *dev, int i);
+static void dump_rx_desc(int dbg_lvl, struct net_device *dev, int i);
+static void dump_skb(int dbg_lvl, struct net_device *dev,
+		     struct sk_buff *skb);
+static void dump_hw_addr(int dbg_lvl, struct net_device *dev,
+			 const char* pfx, unsigned char* addr_str);
 static void update_stats(struct gt96100_private *gp);
 static void abort(struct net_device *dev, u32 abort_bits);
 static void hard_stop(struct net_device *dev);
 static void enable_ether_irq(struct net_device *dev);
 static void disable_ether_irq(struct net_device *dev);
-static int __init gt96100_probe1(struct net_device *dev, long ioaddr,
-				 int irq, int port_num);
+static int gt96100_probe1(int port_num);
+static void reset_tx(struct net_device *dev);
+static void reset_rx(struct net_device *dev);
+static int gt96100_check_tx_consistent(struct gt96100_private *gp);
 static int gt96100_init(struct net_device *dev);
 static int gt96100_open(struct net_device *dev);
 static int gt96100_close(struct net_device *dev);
@@ -81,134 +111,229 @@
 static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void gt96100_tx_timeout(struct net_device *dev);
 static void gt96100_set_rx_mode(struct net_device *dev);
-static struct net_device_stats *gt96100_get_stats(struct net_device *dev);
+static struct net_device_stats* gt96100_get_stats(struct net_device *dev);
 
-static char version[] __devinitdata =
-    "gt96100eth.c:0.1 stevel@mvista.com\n";
+extern char * __init prom_getcmdline(void);
 
-// FIX! Need real Ethernet addresses
-static unsigned char gt96100_station_addr[2][6] __devinitdata =
-    { {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
-{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}
-};
+static int max_interrupt_work = 32;
 
 #define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
 
 #define RUN_AT(x) (jiffies + (x))
 
-// For reading/writing 32-bit words from/to DMA memory
+// For reading/writing 32-bit words and half-words from/to DMA memory
+#ifdef DESC_BE
 #define cpu_to_dma32 cpu_to_be32
 #define dma32_to_cpu be32_to_cpu
+#define cpu_to_dma16 cpu_to_be16
+#define dma16_to_cpu be16_to_cpu
+#else
+#define cpu_to_dma32 cpu_to_le32
+#define dma32_to_cpu le32_to_cpu
+#define cpu_to_dma16 cpu_to_le16
+#define dma16_to_cpu le16_to_cpu
+#endif
+
+static char mac0[18] = "00.02.03.04.05.06";
+static char mac1[18] = "00.01.02.03.04.05";
+MODULE_PARM(mac0, "c18");
+MODULE_PARM(mac1, "c18");
+MODULE_PARM_DESC(mac0, "MAC address for GT96100 ethernet port 0");
+MODULE_PARM_DESC(mac1, "MAC address for GT96100 ethernet port 1");
 
 /*
- * Base address and interupt of the GT96100 ethernet controllers
+ * Info for the GT96100 ethernet controller's ports.
  */
-static struct {
-	unsigned int port;
-	int irq;
+static struct gt96100_if_t {
+	struct net_device *dev;
+	unsigned int  iobase;   // IO Base address of this port
+	int           irq;      // IRQ number of this port
+	char         *mac_str;
 } gt96100_iflist[NUM_INTERFACES] = {
 	{
-	GT96100_ETH0_BASE, GT96100_ETHER0_IRQ}, {
-	GT96100_ETH1_BASE, GT96100_ETHER1_IRQ}
+		NULL,
+		GT96100_ETH0_BASE, GT96100_ETHER0_IRQ,
+		mac0
+	},
+	{
+		NULL,
+		GT96100_ETH1_BASE, GT96100_ETHER1_IRQ,
+		mac1
+	}
 };
 
+static inline const char*
+chip_name(int chip_rev)
+{
+	switch (chip_rev) {
+	case REV_GT96100:
+		return "GT96100";
+	case REV_GT96100A_1:
+	case REV_GT96100A:
+		return "GT96100A";
+	default:
+		return "Unknown GT96100";
+	}
+}
+
 /*
   DMA memory allocation, derived from pci_alloc_consistent.
 */
-static void *dmaalloc(size_t size, dma_addr_t * dma_handle)
+static void *
+dmaalloc(size_t size, dma_addr_t *dma_handle)
 {
 	void *ret;
-
-	ret =
-	    (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
-				      get_order(size));
-
+	
+	ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA,
+				       get_order(size));
+	
 	if (ret != NULL) {
-		dma_cache_inv((unsigned long) ret, size);
+		dma_cache_inv((unsigned long)ret, size);
 		if (dma_handle != NULL)
 			*dma_handle = virt_to_phys(ret);
 
 		/* bump virtual address up to non-cached area */
-		ret = KSEG1ADDR(ret);
+		ret = (void*)KSEG1ADDR(ret);
 	}
 
 	return ret;
 }
 
-static void dmafree(size_t size, void *vaddr)
+static void
+dmafree(size_t size, void *vaddr)
 {
-	vaddr = KSEG0ADDR(vaddr);
-	free_pages((unsigned long) vaddr, get_order(size));
+	vaddr = (void*)KSEG0ADDR(vaddr);
+	free_pages((unsigned long)vaddr, get_order(size));
 }
 
 
-static int read_MII(struct net_device *dev, u32 reg)
+
+static void
+gt96100_delay(int ms)
+{
+	if (in_interrupt())
+		return;
+	else {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(ms*HZ/1000);
+	}
+}
+
+static int
+parse_mac_addr(struct net_device *dev, char* macstr)
+{
+	int i, j;
+	unsigned char result, value;
+	
+	for (i=0; i<6; i++) {
+		result = 0;
+		if (i != 5 && *(macstr+2) != '.') {
+			err(__FILE__ "invalid mac address format: %d %c\n",
+			    i, *(macstr+2));
+			return -EINVAL;
+		}
+		
+		for (j=0; j<2; j++) {
+			if (isxdigit(*macstr) &&
+			    (value = isdigit(*macstr) ? *macstr-'0' : 
+			     toupper(*macstr)-'A'+10) < 16) {
+				result = result*16 + value;
+				macstr++;
+			} else {
+				err(__FILE__ "invalid mac address "
+				    "character: %c\n", *macstr);
+				return -EINVAL;
+			}
+		}
+
+		macstr++; // step over '.'
+		dev->dev_addr[i] = result;
+	}
+
+	return 0;
+}
+
+
+static int
+read_MII(int phy_addr, u32 reg)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
 	int timedout = 20;
-	u32 smir = smirOpCode | (gp->phy_addr << smirPhyAdBit) |
-	    (reg << smirRegAdBit);
+	u32 smir = smirOpCode | (phy_addr << smirPhyAdBit) |
+		(reg << smirRegAdBit);
 
 	// wait for last operation to complete
 	while (GT96100_READ(GT96100_ETH_SMI_REG) & smirBusy) {
 		// snooze for 1 msec and check again
-#if 0
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(10 * HZ / 10000);
-#else
-		mdelay(1);
-#endif
+		gt96100_delay(1);
 
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: read_MII busy timeout!!\n",
-			       dev->name);
-			return -1;
+			printk(KERN_ERR __FUNCTION__ ": busy timeout!!\n");
+			return -ENODEV;
 		}
 	}
-
+    
 	GT96100_WRITE(GT96100_ETH_SMI_REG, smir);
 
 	timedout = 20;
 	// wait for read to complete
-	while (!(smir = GT96100_READ(GT96100_ETH_SMI_REG) & smirReadValid)) {
+	while (!((smir = GT96100_READ(GT96100_ETH_SMI_REG)) & smirReadValid)) {
 		// snooze for 1 msec and check again
-#if 0
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(10 * HZ / 10000);
-#else
-		mdelay(1);
-#endif
-
+		gt96100_delay(1);
+	
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: read_MII timeout!!\n",
-			       dev->name);
-			return -1;
+			printk(KERN_ERR __FUNCTION__ ": timeout!!\n");
+			return -ENODEV;
 		}
 	}
 
-	return (int) (smir & smirDataMask);
+	return (int)(smir & smirDataMask);
+}
+
+static void
+dump_tx_desc(int dbg_lvl, struct net_device *dev, int i)
+{
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	gt96100_td_t *td = &gp->tx_ring[i];
+
+	dbg(dbg_lvl, "Tx descriptor at 0x%08lx:\n", virt_to_phys(td));
+	dbg(dbg_lvl,
+	    "    cmdstat=%04x, byte_cnt=%04x, buff_ptr=%04x, next=%04x\n",
+	    dma32_to_cpu(td->cmdstat),
+	    dma16_to_cpu(td->byte_cnt),
+	    dma32_to_cpu(td->buff_ptr),
+	    dma32_to_cpu(td->next));
+}
+
+static void
+dump_rx_desc(int dbg_lvl, struct net_device *dev, int i)
+{
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	gt96100_rd_t *rd = &gp->rx_ring[i];
+
+	dbg(dbg_lvl, "Rx descriptor at 0x%08lx:\n", virt_to_phys(rd));
+	dbg(dbg_lvl, "    cmdstat=%04x, buff_sz=%04x, byte_cnt=%04x, "
+	    "buff_ptr=%04x, next=%04x\n",
+	    dma32_to_cpu(rd->cmdstat),
+	    dma16_to_cpu(rd->buff_sz),
+	    dma16_to_cpu(rd->byte_cnt),
+	    dma32_to_cpu(rd->buff_ptr),
+	    dma32_to_cpu(rd->next));
 }
 
-static int write_MII(struct net_device *dev, u32 reg, u16 data)
+static int
+write_MII(int phy_addr, u32 reg, u16 data)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
 	int timedout = 20;
-	u32 smir =
-	    (gp->phy_addr << smirPhyAdBit) | (reg << smirRegAdBit) | data;
+	u32 smir = (phy_addr << smirPhyAdBit) |
+		(reg << smirRegAdBit) | data;
 
 	// wait for last operation to complete
 	while (GT96100_READ(GT96100_ETH_SMI_REG) & smirBusy) {
 		// snooze for 1 msec and check again
-#if 0
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(10 * HZ / 10000);
-#else
-		mdelay(1);
-#endif
-
+		gt96100_delay(1);
+	
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: write_MII busy timeout!!\n",
-			       dev->name);
+			printk(KERN_ERR __FUNCTION__ ": busy timeout!!\n");
 			return -1;
 		}
 	}
@@ -217,109 +342,203 @@
 	return 0;
 }
 
+#if 0
+// These routines work, just disabled to avoid compile warnings
+static void
+dump_tx_ring(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	int i;
+
+	dbg(0, __FUNCTION__ ": txno/txni/cnt=%d/%d/%d\n",
+	    gp->tx_next_out, gp->tx_next_in, gp->tx_count);
 
-static void dump_MII(struct net_device *dev)
+	for (i=0; i<TX_RING_SIZE; i++)
+		dump_tx_desc(0, dev, i);
+}
+
+static void
+dump_rx_ring(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	int i;
+
+	dbg(0, __FUNCTION__ ": rxno=%d\n", gp->rx_next_out);
+
+	for (i=0; i<RX_RING_SIZE; i++)
+		dump_rx_desc(0, dev, i);
+}
+#endif
+
+static void
+dump_MII(int dbg_lvl, struct net_device *dev)
 {
 	int i, val;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+    
+	if (dbg_lvl <= GT96100_DEBUG) {
+		for (i=0; i<7; i++) {
+			if ((val = read_MII(gp->phy_addr, i)) >= 0)
+				printk("MII Reg %d=%x\n", i, val);
+		}
+		for (i=16; i<21; i++) {
+			if ((val = read_MII(gp->phy_addr, i)) >= 0)
+				printk("MII Reg %d=%x\n", i, val);
+		}
+	}
+}
 
-	for (i = 0; i < 7; i++) {
-		if ((val = read_MII(dev, i)) >= 0)
-			printk("%s: MII Reg %d=%x\n", dev->name, i, val);
-	}
-	for (i = 16; i < 21; i++) {
-		if ((val = read_MII(dev, i)) >= 0)
-			printk("%s: MII Reg %d=%x\n", dev->name, i, val);
+static void
+dump_hw_addr(int dbg_lvl, struct net_device *dev, const char* pfx,
+	     unsigned char* addr_str)
+{
+	int i;
+	char buf[100], octet[5];
+    
+	if (dbg_lvl <= GT96100_DEBUG) {
+		strcpy(buf, pfx);
+		for (i = 0; i < 6; i++) {
+			sprintf(octet, "%2.2x%s",
+				addr_str[i], i<5 ? ":" : "\n");
+			strcat(buf, octet);
+		}
+		info("%s", buf);
+	}
+}
+
+
+static void
+dump_skb(int dbg_lvl, struct net_device *dev, struct sk_buff *skb)
+{
+	int i;
+	unsigned char* skbdata;
+    
+	if (dbg_lvl <= GT96100_DEBUG) {
+		dbg(dbg_lvl, __FUNCTION__
+		    ": skb=%p, skb->data=%p, skb->len=%d\n",
+		    skb, skb->data, skb->len);
+
+		skbdata = (unsigned char*)KSEG1ADDR(skb->data);
+    
+		for (i=0; i<skb->len; i++) {
+			if (!(i % 16))
+				printk(KERN_DEBUG "\n   %3.3x: %2.2x,",
+				       i, skbdata[i]);
+			else
+				printk(KERN_DEBUG "%2.2x,", skbdata[i]);
+		}
+		printk(KERN_DEBUG "\n");
 	}
 }
 
 
 static int
-gt96100_add_hash_entry(struct net_device *dev, unsigned char *addr)
+gt96100_add_hash_entry(struct net_device *dev, unsigned char* addr)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
-	u16 hashResult, stmp;
-	unsigned char ctmp, hash_ea[6];
-	u32 tblEntry, *tblEntryAddr;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	//u16 hashResult, stmp;
+	//unsigned char ctmp, hash_ea[6];
+	u32 tblEntry1, tblEntry0, *tblEntryAddr;
 	int i;
 
-	for (i = 0; i < 6; i++) {
+	tblEntry1 = hteValid | hteRD;
+	tblEntry1 |= (u32)addr[5] << 3;
+	tblEntry1 |= (u32)addr[4] << 11;
+	tblEntry1 |= (u32)addr[3] << 19;
+	tblEntry1 |= ((u32)addr[2] & 0x1f) << 27;
+	dbg(3, __FUNCTION__ ": tblEntry1=%x\n", tblEntry1);
+	tblEntry0 = ((u32)addr[2] >> 5) & 0x07;
+	tblEntry0 |= (u32)addr[1] << 3;
+	tblEntry0 |= (u32)addr[0] << 11;
+	dbg(3, __FUNCTION__ ": tblEntry0=%x\n", tblEntry0);
+
+#if 0
+
+	for (i=0; i<6; i++) {
 		// nibble swap
 		ctmp = nibswap(addr[i]);
 		// invert every nibble
-		hash_ea[i] = ((ctmp & 1) << 3) | ((ctmp & 8) >> 3) |
-		    ((ctmp & 2) << 1) | ((ctmp & 4) >> 1);
-		hash_ea[i] |= ((ctmp & 0x10) << 3) | ((ctmp & 0x80) >> 3) |
-		    ((ctmp & 0x20) << 1) | ((ctmp & 0x40) >> 1);
+		hash_ea[i] = ((ctmp&1)<<3) | ((ctmp&8)>>3) |
+			((ctmp&2)<<1) | ((ctmp&4)>>1);
+		hash_ea[i] |= ((ctmp&0x10)<<3) | ((ctmp&0x80)>>3) |
+			((ctmp&0x20)<<1) | ((ctmp&0x40)>>1);
 	}
 
+	dump_hw_addr(3, dev, __FUNCTION__ ": nib swap/invt addr=", hash_ea);
+    
 	if (gp->hash_mode == 0) {
-		hashResult = ((u16) hash_ea[0] & 0xfc) << 7;
-		stmp =
-		    ((u16) hash_ea[0] & 0x03) | (((u16) hash_ea[1] & 0x7f)
-						 << 2);
-		stmp ^=
-		    (((u16) hash_ea[1] >> 7) & 0x01) | ((u16) hash_ea[2] <<
-							1);
-		stmp ^= (u16) hash_ea[3] | (((u16) hash_ea[4] & 1) << 8);
+		hashResult = ((u16)hash_ea[0] & 0xfc) << 7;
+		stmp = ((u16)hash_ea[0] & 0x03) |
+			(((u16)hash_ea[1] & 0x7f) << 2);
+		stmp ^= (((u16)hash_ea[1] >> 7) & 0x01) |
+			((u16)hash_ea[2] << 1);
+		stmp ^= (u16)hash_ea[3] | (((u16)hash_ea[4] & 1) << 8);
 		hashResult |= stmp;
 	} else {
-		return -1;	// don't support hash mode 1
+		return -1; // don't support hash mode 1
 	}
 
-	tblEntryAddr =
-	    (u32 *) (&gp->hash_table[((u32) hashResult & 0x7ff) << 3]);
+	dbg(3, __FUNCTION__ ": hashResult=%x\n", hashResult);
 
-	for (i = 0; i < HASH_HOP_NUMBER; i++) {
-		if ((*tblEntryAddr & hteValid)
-		    && !(*tblEntryAddr & hteSkip)) {
+	tblEntryAddr =
+		(u32 *)(&gp->hash_table[((u32)hashResult & 0x7ff) << 3]);
+    
+	dbg(3, __FUNCTION__ ": tblEntryAddr=%p\n", tblEntryAddr);
+
+	for (i=0; i<HASH_HOP_NUMBER; i++) {
+		if ((*tblEntryAddr & hteValid) &&
+		    !(*tblEntryAddr & hteSkip)) {
 			// This entry is already occupied, go to next entry
 			tblEntryAddr += 2;
+			dbg(3, __FUNCTION__ ": skipping to %p\n",
+			    tblEntryAddr);
 		} else {
 			memset(tblEntryAddr, 0, 8);
-			tblEntry = hteValid | hteRD;
-			tblEntry |= (u32) addr[5] << 3;
-			tblEntry |= (u32) addr[4] << 11;
-			tblEntry |= (u32) addr[3] << 19;
-			tblEntry |= ((u32) addr[2] & 0x1f) << 27;
-			*(tblEntryAddr + 1) = cpu_to_dma32(tblEntry);
-			tblEntry = ((u32) addr[2] >> 5) & 0x07;
-			tblEntry |= (u32) addr[1] << 3;
-			tblEntry |= (u32) addr[0] << 11;
-			*tblEntryAddr = cpu_to_dma32(tblEntry);
+			tblEntryAddr[1] = cpu_to_dma32(tblEntry1);
+			tblEntryAddr[0] = cpu_to_dma32(tblEntry0);
 			break;
 		}
 	}
 
 	if (i >= HASH_HOP_NUMBER) {
-		printk(KERN_ERR "%s: gt96100_add_hash_entry expired!\n",
-		       dev->name);
-		return -1;	// Couldn't find an unused entry
+		err(__FUNCTION__ ": expired!\n");
+		return -1; // Couldn't find an unused entry
+	}
+
+#else
+
+	tblEntryAddr = (u32 *)gp->hash_table;
+	for (i=0; i<RX_HASH_TABLE_SIZE/4; i+=2) {
+		tblEntryAddr[i+1] = cpu_to_dma32(tblEntry1);
+		tblEntryAddr[i] = cpu_to_dma32(tblEntry0);
 	}
 
+#endif
+    
 	return 0;
 }
 
 
-static void read_mib_counters(struct gt96100_private *gp)
+static void
+read_mib_counters(struct gt96100_private *gp)
 {
-	u32 *mib_regs = (u32 *) & gp->mib;
+	u32* mib_regs = (u32*)&gp->mib;
 	int i;
-
-	for (i = 0; i < sizeof(mib_counters_t) / sizeof(u32); i++)
-		mib_regs[i] =
-		    GT96100ETH_READ(gp,
-				    GT96100_ETH_MIB_COUNT_BASE +
-				    i * sizeof(u32));
+    
+	for (i=0; i<sizeof(mib_counters_t)/sizeof(u32); i++)
+		mib_regs[i] = GT96100ETH_READ(gp, GT96100_ETH_MIB_COUNT_BASE +
+					      i*sizeof(u32));
 }
 
 
-static void update_stats(struct gt96100_private *gp)
+static void
+update_stats(struct gt96100_private *gp)
 {
 	mib_counters_t *mib = &gp->mib;
 	struct net_device_stats *stats = &gp->stats;
-
+    
 	read_mib_counters(gp);
-
+    
 	stats->rx_packets = mib->totalFramesReceived;
 	stats->tx_packets = mib->framesSent;
 	stats->rx_bytes = mib->totalByteReceived;
@@ -329,8 +548,7 @@
 	//rx_dropped incremented by gt96100_rx
 	//tx_dropped incremented by gt96100_tx
 	stats->multicast = mib->multicastFramesReceived;
-	// Tx collisions incremented by ISR, so add in MIB Rx collisions
-	stats->collisions += mib->collision + mib->lateCollision;
+	// collisions incremented by gt96100_tx_complete
 	stats->rx_length_errors = mib->oversizeFrames + mib->fragments;
 	// The RxError condition means the Rx DMA encountered a
 	// CPU owned descriptor, which, if things are working as
@@ -339,13 +557,13 @@
 	stats->rx_crc_errors = mib->cRCError;
 }
 
-static void abort(struct net_device *dev, u32 abort_bits)
+static void
+abort(struct net_device *dev, u32 abort_bits)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
-	int timedout = 100;	// wait up to 100 msec for hard stop to complete
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	int timedout = 100; // wait up to 100 msec for hard stop to complete
 
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: abort\n", dev->name);
+	dbg(3, __FUNCTION__ "\n");
 
 	// Return if neither Rx or Tx abort bits are set
 	if (!(abort_bits & (sdcmrAR | sdcmrAT)))
@@ -353,48 +571,36 @@
 
 	// make sure only the Rx/Tx abort bits are set
 	abort_bits &= (sdcmrAR | sdcmrAT);
-
+    
 	spin_lock(&gp->lock);
 
 	// abort any Rx/Tx DMA immediately
 	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, abort_bits);
 
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: abort: SDMA comm = %x\n",
-		       dev->name, GT96100ETH_READ(gp,
-						  GT96100_ETH_SDMA_COMM));
+	dbg(3, __FUNCTION__ ": SDMA comm = %x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM));
 
 	// wait for abort to complete
 	while (GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM) & abort_bits) {
 		// snooze for 20 msec and check again
-#if 0
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(10 * HZ / 10000);
-#else
-		mdelay(1);
-#endif
-
+		gt96100_delay(1);
+	
 		if (--timedout == 0) {
-			printk(KERN_ERR "%s: abort timeout!!\n",
-			       dev->name);
+			err(__FUNCTION__ ": timeout!!\n");
 			break;
 		}
 	}
 
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: abort: timedout=%d\n", dev->name,
-		       timedout);
-
 	spin_unlock(&gp->lock);
 }
 
 
-static void hard_stop(struct net_device *dev)
+static void
+hard_stop(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: hard stop\n", dev->name);
+	dbg(3, __FUNCTION__ "\n");
 
 	disable_ether_irq(dev);
 
@@ -405,207 +611,236 @@
 }
 
 
-static void enable_ether_irq(struct net_device *dev)
+static void
+enable_ether_irq(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	u32 intMask;
-
+	/*
+	 * route ethernet interrupt to GT_SERINT0 for port 0,
+	 * GT_INT0 for port 1.
+	 */
+	int intr_mask_reg = (gp->port_num == 0) ?
+		GT96100_SERINT0_MASK : GT96100_INT0_HIGH_MASK;
+	
+	if (gp->chip_rev >= REV_GT96100A_1) {
+		intMask = icrTxBufferLow | icrTxEndLow |
+			icrTxErrorLow  | icrRxOVR | icrTxUdr |
+			icrRxBufferQ0 | icrRxErrorQ0 |
+			icrMIIPhySTC | icrEtherIntSum;
+	}
+	else {
+		intMask = icrTxBufferLow | icrTxEndLow |
+			icrTxErrorLow  | icrRxOVR | icrTxUdr |
+			icrRxBuffer | icrRxError |
+			icrMIIPhySTC | icrEtherIntSum;
+	}
+	
 	// unmask interrupts
-	GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK,
-			 icrRxBuffer | icrTxBufferLow | icrTxEndLow |
-			 icrRxError | icrTxErrorLow | icrRxOVR |
-			 icrTxUdr | icrRxBufferQ0 | icrRxErrorQ0 |
-			 icrMIIPhySTC);
-
-	// now route ethernet interrupts to GT Int0 (eth0 and eth1 will be
-	// sharing it).
-	// FIX! The kernel's irq code should do this
-	intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);
-	intMask |= 1 << gp->port_num;
-	GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);
+	GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK, intMask);
+    
+	intMask = GT96100_READ(intr_mask_reg);
+	intMask |= 1<<gp->port_num;
+	GT96100_WRITE(intr_mask_reg, intMask);
 }
 
-static void disable_ether_irq(struct net_device *dev)
+static void
+disable_ether_irq(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	u32 intMask;
+	int intr_mask_reg = (gp->port_num == 0) ?
+		GT96100_SERINT0_MASK : GT96100_INT0_HIGH_MASK;
 
-	// FIX! The kernel's irq code should do this
-	intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);
-	intMask &= ~(1 << gp->port_num);
-	GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);
-
+	intMask = GT96100_READ(intr_mask_reg);
+	intMask &= ~(1<<gp->port_num);
+	GT96100_WRITE(intr_mask_reg, intMask);
+    
 	GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK, 0);
 }
 
 
 /*
- * Probe for a GT96100 ethernet controller.
+ * Init GT96100 ethernet controller driver
  */
-int __init gt96100_probe(struct net_device *dev)
+int gt96100_init_module(void)
 {
-	unsigned int base_addr = dev ? dev->base_addr : 0;
-	int i;
+	int i, retval=0;
+	u16 vendor_id, device_id;
+	u32 cpuConfig;
 
 #ifndef CONFIG_MIPS_GT96100ETH
 	return -ENODEV;
 #endif
 
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: gt96100_probe\n", dev->name);
+	// probe for GT96100 by reading PCI0 vendor/device ID register
+	pcibios_read_config_word(0, 0, PCI_VENDOR_ID, &vendor_id);
+	pcibios_read_config_word(0, 0, PCI_DEVICE_ID, &device_id);
+    
+	if (vendor_id != PCI_VENDOR_ID_GALILEO ||
+	    (device_id != PCI_DEVICE_ID_GALILEO_GT96100 &&
+	     device_id != PCI_DEVICE_ID_GALILEO_GT96100A)) {
+		printk(KERN_ERR __FILE__ ": GT96100 not found!\n");
+		return -ENODEV;
+	}
 
-	if (base_addr >= KSEG0)	/* Check a single specified location. */
-		return gt96100_probe1(dev, base_addr, dev->irq, 0);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-//	for (i = 0; i<NUM_INTERFACES; i++) {
-	for (i = NUM_INTERFACES - 1; i >= 0; i--) {
-		int base_addr = gt96100_iflist[i].port;
-#if 0
-		if (check_region(base_addr, GT96100_ETH_IO_SIZE)) {
-			printk(KERN_ERR
-			       "%s: gt96100_probe: ioaddr 0x%lx taken?\n",
-			       dev->name, base_addr);
-			continue;
-		}
-#endif
-		if (gt96100_probe1
-		    (dev, base_addr, gt96100_iflist[i].irq, i) == 0)
-			return 0;
+	cpuConfig = GT96100_READ(GT96100_CPU_INTERF_CONFIG);
+	if (cpuConfig & (1<<12)) {
+		printk(KERN_ERR __FILE__
+		       ": must be in Big Endian mode!\n");
+		return -ENODEV;
 	}
-	return -ENODEV;
+
+	for (i=0; i < NUM_INTERFACES; i++) {
+		retval |= gt96100_probe1(i);
+	}
+
+	return retval;
 }
 
 
 
 static int __init
-gt96100_probe1(struct net_device *dev, long ioaddr, int irq, int port_num)
+gt96100_probe1(int port_num)
 {
-	static unsigned version_printed = 0;
 	struct gt96100_private *gp = NULL;
-	int i, retval;
-	u32 cpuConfig;
-
-	// FIX! probe for GT96100 by reading a suitable register
-
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "gt96100_probe1: ioaddr 0x%lx, irq %d\n",
-		       ioaddr, irq);
-
-	request_region(ioaddr, GT96100_ETH_IO_SIZE, "GT96100ETH");
-
-	cpuConfig = GT96100_READ(GT96100_CPU_INTERF_CONFIG);
-	if (cpuConfig & (1 << 12)) {
-		printk(KERN_ERR
-		       "gt96100_probe1: must be in Big Endian mode!\n");
-		retval = -ENODEV;
-		goto free_region;
-	}
-
-	if (gt96100_debug > 2)
-		printk(KERN_INFO
-		       "gt96100_probe1: chip in Big Endian mode - cool\n");
-
-	/* Allocate a new 'dev' if needed. */
-	if (dev == NULL)
-		dev = init_etherdev(0, sizeof(struct gt96100_private));
-
-	if (gt96100_debug && version_printed++ == 0)
-		printk(version);
-
-	if (irq < 0) {
-		printk(KERN_ERR
-		       "gt96100_probe1: irq unknown - probing not supported\n");
-		retval = -ENODEV;
-		goto free_region;
-	}
-
-	printk(KERN_INFO "%s: GT-96100 ethernet found at 0x%lx, irq %d\n",
-	       dev->name, ioaddr, irq);
-
+	struct gt96100_if_t *gtif = &gt96100_iflist[port_num];
+	int phy_addr, phy_id1, phy_id2;
+	u32 phyAD;
+	int retval;
+	unsigned char chip_rev;
+	struct net_device *dev = NULL;
+    
+	if (gtif->irq < 0) {
+		printk(KERN_ERR __FUNCTION__
+		       ": irq unknown - probing not supported\n");
+		return -ENODEV;
+	}
+    
+	pcibios_read_config_byte(0, 0, PCI_REVISION_ID, &chip_rev);
+
+	if (chip_rev >= REV_GT96100A_1) {
+		phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
+		phy_addr = (phyAD >> (5*port_num)) & 0x1f;
+	} else {
+		/*
+		 * not sure what's this about -- probably 
+		 * a gt bug
+		 */
+		phy_addr = port_num;
+		phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
+		phyAD &= ~(0x1f << (port_num*5));
+		phyAD |= phy_addr << (port_num*5);
+		GT96100_WRITE(GT96100_ETH_PHY_ADDR_REG, phyAD);
+	}
+	
+	// probe for the external PHY
+	if ((phy_id1 = read_MII(phy_addr, 2)) <= 0 ||
+	    (phy_id2 = read_MII(phy_addr, 3)) <= 0) {
+		printk(KERN_ERR __FUNCTION__
+		       ": no PHY found on MII%d\n", port_num);
+		return -ENODEV;
+	}
+	
+	if (!request_region(gtif->iobase, GT96100_ETH_IO_SIZE, "GT96100ETH")) {
+		printk(KERN_ERR __FUNCTION__ ": request_region failed\n");
+		return -EBUSY;
+	}
+
+	dev = init_etherdev(0, sizeof(struct gt96100_private));
+	gtif->dev = dev;
+	
 	/* private struct aligned and zeroed by init_etherdev */
 	/* Fill in the 'dev' fields. */
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	memcpy(dev->dev_addr, gt96100_station_addr[port_num],
-	       sizeof(dev->dev_addr));
-
-	printk(KERN_INFO "%s: HW Address ", dev->name);
-	for (i = 0; i < sizeof(dev->dev_addr); i++) {
-		printk("%2.2x", dev->dev_addr[i]);
-		printk(i < 5 ? ":" : "\n");
+	dev->base_addr = gtif->iobase;
+	dev->irq = gtif->irq;
+
+	if ((retval = parse_mac_addr(dev, gtif->mac_str))) {
+		err(__FUNCTION__ ": MAC address parse failed\n");
+		retval = -EINVAL;
+		goto free_region;
 	}
 
 	/* Initialize our private structure. */
 	if (dev->priv == NULL) {
 
-		gp =
-		    (struct gt96100_private *) kmalloc(sizeof(*gp),
+		gp = (struct gt96100_private *)kmalloc(sizeof(*gp),
 						       GFP_KERNEL);
 		if (gp == NULL) {
 			retval = -ENOMEM;
 			goto free_region;
 		}
-
+	
 		dev->priv = gp;
 	}
 
 	gp = dev->priv;
 
-	memset(gp, 0, sizeof(*gp));	// clear it
+	memset(gp, 0, sizeof(*gp)); // clear it
 
 	gp->port_num = port_num;
 	gp->io_size = GT96100_ETH_IO_SIZE;
 	gp->port_offset = port_num * GT96100_ETH_IO_SIZE;
-	gp->phy_addr = port_num + 1;
+	gp->phy_addr = phy_addr;
+	gp->chip_rev = chip_rev;
 
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: gt96100_probe1, port %d\n",
-		       dev->name, gp->port_num);
+	info("%s found at 0x%x, irq %d\n",
+	     chip_name(gp->chip_rev), gtif->iobase, gtif->irq);
+	dump_hw_addr(0, dev, "HW Address ", dev->dev_addr);
+	info("%s chip revision=%d\n", chip_name(gp->chip_rev), gp->chip_rev);
+	info("%s ethernet port %d\n", chip_name(gp->chip_rev), gp->port_num);
+	info("external PHY ID1=0x%04x, ID2=0x%04x\n", phy_id1, phy_id2);
 
 	// Allocate Rx and Tx descriptor rings
 	if (gp->rx_ring == NULL) {
 		// All descriptors in ring must be 16-byte aligned
 		gp->rx_ring = dmaalloc(sizeof(gt96100_rd_t) * RX_RING_SIZE
-				       +
-				       sizeof(gt96100_td_t) * TX_RING_SIZE,
+				       + sizeof(gt96100_td_t) * TX_RING_SIZE,
 				       &gp->rx_ring_dma);
 		if (gp->rx_ring == NULL) {
 			retval = -ENOMEM;
 			goto free_region;
 		}
-
-		gp->tx_ring =
-		    (gt96100_td_t *) (gp->rx_ring + RX_RING_SIZE);
+	
+		gp->tx_ring = (gt96100_td_t *)(gp->rx_ring + RX_RING_SIZE);
 		gp->tx_ring_dma =
-		    gp->rx_ring_dma + sizeof(gt96100_rd_t) * RX_RING_SIZE;
+			gp->rx_ring_dma + sizeof(gt96100_rd_t) * RX_RING_SIZE;
 	}
-
-	if (gt96100_debug > 2)
-		printk(KERN_INFO
-		       "%s: gt96100_probe1, rx_ring=%p, tx_ring=%p\n",
-		       dev->name, gp->rx_ring, gp->tx_ring);
+    
+	// Allocate the Rx Data Buffers
+	if (gp->rx_buff == NULL) {
+		gp->rx_buff = dmaalloc(PKT_BUF_SZ*RX_RING_SIZE,
+				       &gp->rx_buff_dma);
+		if (gp->rx_buff == NULL) {
+			dmafree(sizeof(gt96100_rd_t) * RX_RING_SIZE
+				+ sizeof(gt96100_td_t) * TX_RING_SIZE,
+				gp->rx_ring);
+			retval = -ENOMEM;
+			goto free_region;
+		}
+	}
+    
+	dbg(3, __FUNCTION__ ": rx_ring=%p, tx_ring=%p\n",
+	    gp->rx_ring, gp->tx_ring);
 
 	// Allocate Rx Hash Table
 	if (gp->hash_table == NULL) {
-		gp->hash_table = (char *) dmaalloc(RX_HASH_TABLE_SIZE,
-						   &gp->hash_table_dma);
+		gp->hash_table = (char*)dmaalloc(RX_HASH_TABLE_SIZE,
+						 &gp->hash_table_dma);
 		if (gp->hash_table == NULL) {
 			dmafree(sizeof(gt96100_rd_t) * RX_RING_SIZE
 				+ sizeof(gt96100_td_t) * TX_RING_SIZE,
 				gp->rx_ring);
+			dmafree(PKT_BUF_SZ*RX_RING_SIZE, gp->rx_buff);
 			retval = -ENOMEM;
 			goto free_region;
 		}
 	}
-
-	if (gt96100_debug > 2)
-		printk(KERN_INFO "%s: gt96100_probe1, hash=%p\n",
-		       dev->name, gp->hash_table);
+    
+	dbg(3, __FUNCTION__ ": hash=%p\n", gp->hash_table);
 
 	spin_lock_init(&gp->lock);
-
+    
 	dev->open = gt96100_open;
 	dev->hard_start_xmit = gt96100_tx;
 	dev->stop = gt96100_close;
@@ -619,317 +854,358 @@
 	ether_setup(dev);
 	return 0;
 
-      free_region:
-	release_region(ioaddr, gp->io_size);
+ free_region:
+	release_region(gtif->iobase, GT96100_ETH_IO_SIZE);
 	unregister_netdev(dev);
 	if (dev->priv != NULL)
-		kfree(dev->priv);
-	kfree(dev);
-	printk(KERN_ERR "%s: gt96100_probe1 failed.  Returns %d\n",
-	       dev->name, retval);
+		kfree (dev->priv);
+	kfree (dev);
+	err(__FUNCTION__ " failed.  Returns %d\n", retval);
 	return retval;
 }
 
 
-static int gt96100_init(struct net_device *dev)
+static void
+reset_tx(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
-	unsigned long flags;
-	u32 phyAD, ciu;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	int i;
 
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: dev=%p\n", dev->name, dev);
+	abort(dev, sdcmrAT);
 
-	// Stop and disable Port
-	hard_stop(dev);
-
-	spin_lock_irqsave(&gp->lock, flags);
+	for (i=0; i<TX_RING_SIZE; i++) {
+		if (gp->tx_skbuff[i]) {
+			if (in_interrupt())
+				dev_kfree_skb_irq(gp->tx_skbuff[i]);
+			else
+				dev_kfree_skb(gp->tx_skbuff[i]);
+			gp->tx_skbuff[i] = NULL;
+		}
 
-	// First things first, set-up hash table
-	memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);	// clear it
-	gp->hash_mode = 0;
-	// Add a single entry to hash table - our ethernet address
-	gt96100_add_hash_entry(dev, dev->dev_addr);
-	// Set-up DMA ptr to hash table
-	GT96100ETH_WRITE(gp, GT96100_ETH_HASH_TBL_PTR, gp->hash_table_dma);
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: Hash Tbl Ptr=%x\n", dev->name,
-		       GT96100ETH_READ(gp, GT96100_ETH_HASH_TBL_PTR));
-
-	// Setup Tx descriptor ring
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		gp->tx_ring[i].cmdstat = 0;	// CPU owns
+		gp->tx_ring[i].cmdstat = 0; // CPU owns
 		gp->tx_ring[i].byte_cnt = 0;
 		gp->tx_ring[i].buff_ptr = 0;
 		gp->tx_ring[i].next =
-		    cpu_to_dma32(gp->tx_ring_dma +
-				 sizeof(gt96100_td_t) * (i + 1));
+			cpu_to_dma32(gp->tx_ring_dma +
+				     sizeof(gt96100_td_t) * (i+1));
+		dump_tx_desc(4, dev, i);
 	}
 	/* Wrap the ring. */
-	gp->tx_ring[i - 1].next = cpu_to_dma32(gp->tx_ring_dma);
-
+	gp->tx_ring[i-1].next = cpu_to_dma32(gp->tx_ring_dma);
+    
 	// setup only the lowest priority TxCDP reg
-	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR0,
-			 gp->tx_ring_dma);
+	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR0, gp->tx_ring_dma);
 	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR1, 0);
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: Curr Tx Desc Ptr0=%x\n",
-		       dev->name, GT96100ETH_READ(gp,
-						  GT96100_ETH_CURR_TX_DESC_PTR0));
-
-	// Setup Rx descriptor ring 
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		dma_addr_t rx_buff_dma;
+
+	// init Tx indeces and pkt counter
+	gp->tx_next_in = gp->tx_next_out = 0;
+	gp->tx_count = 0;
+
+}
+
+static void
+reset_rx(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	int i;
+
+	abort(dev, sdcmrAR);
+    
+	for (i=0; i<RX_RING_SIZE; i++) {
 		gp->rx_ring[i].next =
-		    cpu_to_dma32(gp->rx_ring_dma +
-				 sizeof(gt96100_rd_t) * (i + 1));
-		if (gp->rx_buff[i] == NULL)
-			gp->rx_buff[i] =
-			    dmaalloc(PKT_BUF_SZ, &rx_buff_dma);
-		else
-			rx_buff_dma = virt_to_phys(gp->rx_buff[i]);
-		if (gp->rx_buff[i] == NULL)
-			break;
-		gp->rx_ring[i].buff_ptr = cpu_to_dma32(rx_buff_dma);
-		gp->rx_ring[i].buff_cnt_sz =
-		    cpu_to_dma32(PKT_BUF_SZ << rdBuffSzBit);
-		// Give ownership to device, enable interrupt
+			cpu_to_dma32(gp->rx_ring_dma +
+				     sizeof(gt96100_rd_t) * (i+1));
+		gp->rx_ring[i].buff_ptr =
+			cpu_to_dma32(gp->rx_buff_dma + i*PKT_BUF_SZ);
+		gp->rx_ring[i].buff_sz = cpu_to_dma16(PKT_BUF_SZ);
+		// Give ownership to device, set first and last, enable intr
 		gp->rx_ring[i].cmdstat =
-		    cpu_to_dma32((u32) (rxOwn | rxEI));
+			cpu_to_dma32((u32)(rxFirst | rxLast | rxOwn | rxEI));
+		dump_rx_desc(4, dev, i);
 	}
+	/* Wrap the ring. */
+	gp->rx_ring[i-1].next = cpu_to_dma32(gp->rx_ring_dma);
 
-	if (i != RX_RING_SIZE) {
-		int j;
-		for (j = 0; j < RX_RING_SIZE; j++) {
-			if (gp->rx_buff[j]) {
-				dmafree(PKT_BUF_SZ, gp->rx_buff[j]);
-				gp->rx_buff[j] = NULL;
-			}
+	// Setup only the lowest priority RxFDP and RxCDP regs
+	for (i=0; i<4; i++) {
+		if (i == 0) {
+			GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0,
+					 gp->rx_ring_dma);
+			GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0,
+					 gp->rx_ring_dma);
+		} else {
+			GT96100ETH_WRITE(gp,
+					 GT96100_ETH_1ST_RX_DESC_PTR0 + i*4,
+					 0);
+			GT96100ETH_WRITE(gp,
+					 GT96100_ETH_CURR_RX_DESC_PTR0 + i*4,
+					 0);
 		}
-		printk(KERN_ERR "%s: Rx ring allocation failed.\n",
-		       dev->name);
-		spin_unlock_irqrestore(&gp->lock, flags);
-		return -ENOMEM;
 	}
 
-	/* Wrap the ring. */
-	gp->rx_ring[i - 1].next = cpu_to_dma32(gp->rx_ring_dma);
+	// init Rx NextOut index
+	gp->rx_next_out = 0;
+}
 
-	// Set our MII PHY device address
-	phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
-	phyAD &= ~(0x1f << (gp->port_num * 5));
-	phyAD |= gp->phy_addr << (gp->port_num * 5);
-	GT96100_WRITE(GT96100_ETH_PHY_ADDR_REG, phyAD);
-
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: PhyAD=%x\n", dev->name,
-		       GT96100_READ(GT96100_ETH_PHY_ADDR_REG));
-
-	// Clear all the RxFDP and RXCDP regs...
-	for (i = 0; i < 4; i++) {
-		GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0 + i * 4,
-				 0);
-		GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0 + i * 4,
-				 0);
-	}
-	// and setup only the lowest priority RxFDP and RxCDP regs
-	GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0,
-			 gp->rx_ring_dma);
-	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0,
-			 gp->rx_ring_dma);
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: 1st/Curr Rx Desc Ptr0=%x/%x\n",
-		       dev->name, GT96100ETH_READ(gp,
-						  GT96100_ETH_1ST_RX_DESC_PTR0),
-		       GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0));
 
-	// init Rx/Tx indeces and pkt counters
-	gp->rx_next_out = gp->tx_next_in = gp->tx_next_out = 0;
-	gp->tx_count = 0;
+// Returns 1 if the Tx counter and indeces don't gel
+static int
+gt96100_check_tx_consistent(struct gt96100_private *gp)
+{
+	int diff = gp->tx_next_in - gp->tx_next_out;
 
-	// setup DMA
+	diff = diff<0 ? TX_RING_SIZE + diff : diff;
+	diff = gp->tx_count == TX_RING_SIZE ? diff + TX_RING_SIZE : diff;
+    
+	return (diff != gp->tx_count);
+}
+
+static int
+gt96100_init(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	u32 tmp;
+	u16 mii_reg;
+    
+	dbg(3, __FUNCTION__ ": dev=%p\n", dev);
+	dbg(3, __FUNCTION__ ": scs10_lo=%4x, scs10_hi=%4x\n",
+	    GT96100_READ(0x8), GT96100_READ(0x10));
+	dbg(3, __FUNCTION__ ": scs32_lo=%4x, scs32_hi=%4x\n",
+	    GT96100_READ(0x18), GT96100_READ(0x20));
+    
+	// Stop and disable Port
+	hard_stop(dev);
+    
+	// Setup CIU Arbiter
+	tmp = GT96100_READ(GT96100_CIU_ARBITER_CONFIG);
+	tmp |= (0x0c << (gp->port_num*2)); // set Ether DMA req priority to hi
+#ifndef DESC_BE
+	tmp &= ~(1<<31);                   // set desc endianess to little
+#else
+	tmp |= (1<<31);
+#endif
+	GT96100_WRITE(GT96100_CIU_ARBITER_CONFIG, tmp);
+	dbg(3, __FUNCTION__ ": CIU Config=%x/%x\n",
+	    tmp, GT96100_READ(GT96100_CIU_ARBITER_CONFIG));
+
+	// Set routing.
+	tmp = GT96100_READ(GT96100_ROUTE_MAIN) & (0x3f << 18);
+	tmp |= (0x07 << (18 + gp->port_num*3));
+	GT96100_WRITE(GT96100_ROUTE_MAIN, tmp);
+
+	/* set MII as peripheral func */
+	tmp = GT96100_READ(GT96100_GPP_CONFIG2);
+	tmp |= 0x7fff << (gp->port_num*16);
+	GT96100_WRITE(GT96100_GPP_CONFIG2, tmp);
+	
+	/* Set up MII port pin directions */
+	tmp = GT96100_READ(GT96100_GPP_IO2);
+	tmp |= 0x003d << (gp->port_num*16);
+	GT96100_WRITE(GT96100_GPP_IO2, tmp);
+
+	// Set-up hash table
+	memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE); // clear it
+	gp->hash_mode = 0;
+	// Add a single entry to hash table - our ethernet address
+	gt96100_add_hash_entry(dev, dev->dev_addr);
+	// Set-up DMA ptr to hash table
+	GT96100ETH_WRITE(gp, GT96100_ETH_HASH_TBL_PTR, gp->hash_table_dma);
+	dbg(3, __FUNCTION__ ": Hash Tbl Ptr=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_HASH_TBL_PTR));
+
+	// Setup Tx
+	reset_tx(dev);
 
-	// FIX! this should be done by Kernel setup code
-	ciu = GT96100_READ(GT96100_CIU_ARBITER_CONFIG);
-	ciu |= (0x0c << (gp->port_num * 2));	// set Ether DMA req priority to high
-	// FIX! setting the following bit causes the EV96100 board to hang!!!
-	//ciu |= (1 << (24+gp->port_num));   // pull Ethernet port out of Reset???
-	// FIX! endian mode???
-	ciu &= ~(1 << 31);	// set desc endianess to Big
-	GT96100_WRITE(GT96100_CIU_ARBITER_CONFIG, ciu);
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: CIU Config=%x/%x\n", dev->name,
-		       ciu, GT96100_READ(GT96100_CIU_ARBITER_CONFIG));
+	dbg(3, __FUNCTION__ ": Curr Tx Desc Ptr0=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_CURR_TX_DESC_PTR0));
+
+	// Setup Rx
+	reset_rx(dev);
+
+	dbg(3, __FUNCTION__ ": 1st/Curr Rx Desc Ptr0=%x/%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_1ST_RX_DESC_PTR0),
+	    GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0));
+
+	// eth port config register
+	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
+			 pcxrFCTL | pcxrFCTLen | pcxrFLP | pcxrDPLXen);
+
+	mii_reg = read_MII(gp->phy_addr, 0x11); /* int enable register */
+	mii_reg |= 2;  /* enable mii interrupt */
+	write_MII(gp->phy_addr, 0x11, mii_reg);
+	
+	dbg(3, __FUNCTION__ ": PhyAD=%x\n",
+	    GT96100_READ(GT96100_ETH_PHY_ADDR_REG));
+
+	// setup DMA
 
 	// We want the Rx/Tx DMA to write/read data to/from memory in
 	// Big Endian mode. Also set DMA Burst Size to 8 64Bit words.
-	// FIX! endian mode???
+#ifdef DESC_DATA_BE
+	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_CONFIG,
+			 (0xf<<sdcrRCBit) | sdcrRIFB | (3<<sdcrBSZBit));
+#else
 	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_CONFIG,
-			 //sdcrBLMR | sdcrBLMT |
-			 (0xf << sdcrRCBit) | sdcrRIFB | (3 << sdcrBSZBit));
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: SDMA Config=%x\n", dev->name,
-		       GT96100ETH_READ(gp, GT96100_ETH_SDMA_CONFIG));
+			 sdcrBLMR | sdcrBLMT |
+			 (0xf<<sdcrRCBit) | sdcrRIFB | (3<<sdcrBSZBit));
+#endif
+	dbg(3, __FUNCTION__ ": SDMA Config=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_SDMA_CONFIG));
 
 	// start Rx DMA
 	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: SDMA Comm=%x\n", dev->name,
-		       GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM));
-
-	// enable interrupts
-	enable_ether_irq(dev);
-
+	dbg(3, __FUNCTION__ ": SDMA Comm=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM));
+    
+	// enable this port (set hash size to 1/2K)
+	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, pcrEN | pcrHS);
+	dbg(3, __FUNCTION__ ": Port Config=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG));
+    
 	/*
 	 * Disable all Type-of-Service queueing. All Rx packets will be
 	 * treated normally and will be sent to the lowest priority
 	 * queue.
 	 *
-	 * Disable flow-control for now. FIX! support flow control?
+	 * Disable flow-control for now. FIXME: support flow control?
 	 */
+
 	// clear all the MIB ctr regs
-	// Enable reg clear on read. FIX! desc of this bit is inconsistent
-	// in the GT-96100A datasheet.
 	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
-			 pcxrFCTL | pcxrFCTLen | pcxrFLP);
+			 pcxrFCTL | pcxrFCTLen | pcxrFLP |
+			 pcxrPRIOrxOverride);
 	read_mib_counters(gp);
 	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
-			 pcxrFCTL | pcxrFCTLen | pcxrFLP | pcxrMIBclrMode);
+			 pcxrFCTL | pcxrFCTLen | pcxrFLP |
+			 pcxrPRIOrxOverride | pcxrMIBclrMode);
+    
+	dbg(3, __FUNCTION__ ": Port Config Ext=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG_EXT));
 
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: Port Config Ext=%x\n", dev->name,
-		       GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG_EXT));
+	netif_start_queue(dev);
 
-	// enable this port (set hash size to 1/2K)
-	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, pcrEN | pcrHS);
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_init: Port Config=%x\n", dev->name,
-		       GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG));
+	dump_MII(4, dev);
 
-	// we should now be receiving frames
-	if (gt96100_debug > 2)
-		dump_MII(dev);
+	// enable interrupts
+	enable_ether_irq(dev);
 
-	spin_unlock_irqrestore(&gp->lock, flags);
+	// we should now be receiving frames
 	return 0;
 }
 
 
-static int gt96100_open(struct net_device *dev)
+static int
+gt96100_open(struct net_device *dev)
 {
 	int retval;
-
+    
 	MOD_INC_USE_COUNT;
 
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_open: dev=%p\n", dev->name, dev);
+	dbg(2, __FUNCTION__ ": dev=%p\n", dev);
 
-	if ((retval = request_irq(dev->irq, &gt96100_interrupt,
-				  SA_SHIRQ, dev->name, dev))) {
-		printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
-		       dev->irq);
-		MOD_DEC_USE_COUNT;
-		return retval;
-	}
 	// Initialize and startup the GT-96100 ethernet port
 	if ((retval = gt96100_init(dev))) {
-		printk(KERN_ERR "%s: error in gt96100_init\n", dev->name);
+		err("error in gt96100_init\n");
 		free_irq(dev->irq, dev);
 		MOD_DEC_USE_COUNT;
 		return retval;
 	}
 
-	netif_start_queue(dev);
-
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_open: Initialization done.\n",
-		       dev->name);
+	if ((retval = request_irq(dev->irq, &gt96100_interrupt,
+				  SA_SHIRQ, dev->name, dev))) {
+		err("unable to get IRQ %d\n", dev->irq);
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+	
+	dbg(2, __FUNCTION__ ": Initialization done.\n");
 
 	return 0;
 }
 
-static int gt96100_close(struct net_device *dev)
+static int
+gt96100_close(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
-	int i;
-
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_close: dev=%p\n", dev->name, dev);
+	dbg(3, __FUNCTION__ ": dev=%p\n", dev);
 
 	// stop the device
 	if (netif_device_present(dev)) {
 		netif_stop_queue(dev);
 		hard_stop(dev);
 	}
-	// free the Rx DMA buffers
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		if (gp->rx_buff[i]) {
-			dmafree(PKT_BUF_SZ, gp->rx_buff[i]);
-			gp->rx_buff[i] = NULL;
-		}
-	}
 
 	free_irq(dev->irq, dev);
-
+    
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
 
-static int gt96100_tx(struct sk_buff *skb, struct net_device *dev)
+static int
+gt96100_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	unsigned long flags;
 	int nextIn;
 
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_tx: skb->len=%d, skb->data=%p\n",
-		       dev->name, skb->len, skb->data);
-
 	spin_lock_irqsave(&gp->lock, flags);
 
+	nextIn = gp->tx_next_in;
+
+	dbg(3, __FUNCTION__ ": nextIn=%d\n", nextIn);
+    
 	if (gp->tx_count >= TX_RING_SIZE) {
-		printk(KERN_WARNING
-		       "%s: Tx Ring full, refusing to send buffer.\n",
-		       dev->name);
+		warn("Tx Ring full, pkt dropped.\n");
 		gp->stats.tx_dropped++;
 		spin_unlock_irqrestore(&gp->lock, flags);
 		return 1;
 	}
-	// Prepare the Descriptor at tx_next_in
-	nextIn = gp->tx_next_in;
-
+    
+	if (!(gp->last_psr & psrLink)) {
+		err(__FUNCTION__ ": Link down, pkt dropped.\n");
+		gp->stats.tx_dropped++;
+		spin_unlock_irqrestore(&gp->lock, flags);
+		return 1;
+	}
+    
 	if (dma32_to_cpu(gp->tx_ring[nextIn].cmdstat) & txOwn) {
-		printk(KERN_ERR "%s: gt96100_tx: TxOwn bit wrong!!\n",
-		       dev->name);
+		err(__FUNCTION__ ": device owns descriptor, pkt dropped.\n");
+		gp->stats.tx_dropped++;
+		// stop the queue, so Tx timeout can fix it
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&gp->lock, flags);
+		return 1;
 	}
-
+    
+	// Prepare the Descriptor at tx_next_in
 	gp->tx_skbuff[nextIn] = skb;
-	gp->tx_ring[nextIn].byte_cnt =
-	    cpu_to_dma32(skb->len << tdByteCntBit);
-	gp->tx_ring[nextIn].buff_ptr =
-	    cpu_to_dma32(virt_to_phys(skb->data));
+	gp->tx_ring[nextIn].byte_cnt = cpu_to_dma16(skb->len);
+	gp->tx_ring[nextIn].buff_ptr = cpu_to_dma32(virt_to_phys(skb->data));
+	// make sure packet gets written back to memory
+	dma_cache_wback_inv((unsigned long)(skb->data), skb->len);
 	// Give ownership to device, set first and last desc, enable interrupt
 	// Setting of ownership bit must be *last*!
 	gp->tx_ring[nextIn].cmdstat =
-	    cpu_to_dma32((u32) (txOwn | txEI | txFirst | txLast));
+		cpu_to_dma32((u32)(txOwn | txGenCRC | txEI |
+				   txPad | txFirst | txLast));
+    
+	dump_tx_desc(4, dev, nextIn);
+	dump_skb(4, dev, skb);
 
 	// increment tx_next_in with wrap
 	gp->tx_next_in = (nextIn + 1) % TX_RING_SIZE;
-	// If count is zero, DMA should be stopped, so restart
-	if (gp->tx_count == 0) {
-		if (GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS) &
-		    psrTxLow) printk(KERN_WARNING
-				     "%s: Tx count zero but Tx queue running!\n",
-				     dev->name);
+	// If DMA is stopped, restart
+	if (!(GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS) & psrTxLow))
 		GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
 				 sdcmrERD | sdcmrTXDL);
-	}
+
 	// increment count and stop queue if full
-	if (++gp->tx_count == TX_RING_SIZE)
+	if (++gp->tx_count == TX_RING_SIZE) {
+		gp->tx_full = 1;
 		netif_stop_queue(dev);
-
+		dbg(2, "Tx Ring now full, queue stopped.\n");
+	}
+    
 	dev->trans_start = jiffies;
 	spin_unlock_irqrestore(&gp->lock, flags);
 
@@ -937,317 +1213,438 @@
 }
 
 
-static int gt96100_rx(struct net_device *dev, u32 status)
+static int
+gt96100_rx(struct net_device *dev, u32 status)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	struct sk_buff *skb;
-	int pkt_len, nextOut;
+	int pkt_len, nextOut, cdp;
 	gt96100_rd_t *rd;
 	u32 cmdstat;
+    
+	dbg(3, __FUNCTION__ ": dev=%p, status=%x\n", dev, status);
 
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_rx: dev=%p, status = %x\n",
-		       dev->name, dev, status);
+	cdp = (GT96100ETH_READ(gp, GT96100_ETH_1ST_RX_DESC_PTR0)
+	       - gp->rx_ring_dma) / sizeof(gt96100_rd_t);
 
-	// Continue until we reach the current descriptor pointer
-	for (nextOut = gp->rx_next_out;
-	     nextOut !=
-	     (GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0) -
-	      gp->rx_ring_dma) / sizeof(gt96100_rd_t);
+	// Continue until we reach 1st descriptor pointer
+	for (nextOut = gp->rx_next_out; nextOut != cdp;
 	     nextOut = (nextOut + 1) % RX_RING_SIZE) {
+	
+		if (--gp->intr_work_done == 0)
+			break;
 
 		rd = &gp->rx_ring[nextOut];
 		cmdstat = dma32_to_cpu(rd->cmdstat);
+	
+		dbg(4, __FUNCTION__ ": Rx desc cmdstat=%x, nextOut=%d\n",
+		    cmdstat, nextOut);
+
+		if (cmdstat & (u32)rxOwn) {
+			//err(__FUNCTION__ ": device owns descriptor!\n");
+			// DMA is not finished updating descriptor???
+			// Leave and come back later to pick-up where
+			// we left off.
+			break;
+		}
 
-		if (cmdstat & (u32) rxOwn) {
-			cmdstat &= ~((u32) rxOwn);
+		// Drop this received pkt if there were any errors
+		if (((cmdstat & (u32)(rxErrorSummary)) &&
+		     (cmdstat & (u32)(rxFirst))) || (status & icrRxError)) {
+			// update the detailed rx error counters that
+			// are not covered by the MIB counters.
+			if (cmdstat & (u32)rxOverrun)
+				gp->stats.rx_fifo_errors++;
+			cmdstat |= (u32)rxOwn;
 			rd->cmdstat = cpu_to_dma32(cmdstat);
-			printk(KERN_ERR
-			       "%s: gt96100_rx: ownership bit wrong!\n",
-			       dev->name);
-		}
-		// must be first and last (ie only) buffer of packet
-		if (!(cmdstat & (u32) rxFirst)
-		    || !(cmdstat & (u32) rxLast)) {
-			printk(KERN_ERR
-			       "%s: gt96100_rx: desc not first and last!\n",
-			       dev->name);
 			continue;
 		}
-		// drop this received pkt if there were any errors
-		if ((cmdstat & (u32) rxErrorSummary)
-		    || (status & icrRxErrorQ0)) {
-			// update the detailed rx error counters that are not covered
-			// by the MIB counters.
-			if (cmdstat & (u32) rxOverrun)
-				gp->stats.rx_fifo_errors++;
+
+		/*
+		 * Must be first and last (ie only) descriptor of packet. We
+		 * ignore (drop) any packets that do not fit in one descriptor.
+		 * Every descriptor's receive buffer is large enough to hold
+		 * the maximum 802.3 frame size, so a multi-descriptor packet
+		 * indicates an error. Most if not all corrupted packets will
+		 * have already been dropped by the above check for the
+		 * rxErrorSummary status bit.
+		 */
+		if (!(cmdstat & (u32)rxFirst) || !(cmdstat & (u32)rxLast)) {
+			if (cmdstat & (u32)rxFirst) {
+				/*
+				 * This is the first descriptor of a
+				 * multi-descriptor packet. It isn't corrupted
+				 * because the above check for rxErrorSummary
+				 * would have dropped it already, so what's
+				 * the deal with this packet? Good question,
+				 * let's dump it out.
+				 */
+				err(__FUNCTION__
+				    ": desc not first and last!\n");
+				dump_rx_desc(0, dev, nextOut);
+			}
+			cmdstat |= (u32)rxOwn;
+			rd->cmdstat = cpu_to_dma32(cmdstat);
+			// continue to drop every descriptor of this packet
 			continue;
 		}
-
-		pkt_len = dma32_to_cpu(rd->buff_cnt_sz) & rdByteCntMask;
-
+	
+		pkt_len = dma16_to_cpu(rd->byte_cnt);
+	
 		/* Create new skb. */
-		skb = dev_alloc_skb(pkt_len + 2);
+		skb = dev_alloc_skb(pkt_len+2);
 		if (skb == NULL) {
-			printk(KERN_ERR
-			       "%s: Memory squeeze, dropping packet.\n",
-			       dev->name);
+			err(__FUNCTION__
+			    ": Memory squeeze, dropping packet.\n");
 			gp->stats.rx_dropped++;
+			cmdstat |= (u32)rxOwn;
+			rd->cmdstat = cpu_to_dma32(cmdstat);
 			continue;
 		}
 		skb->dev = dev;
-		skb_reserve(skb, 2);	/* 16 byte IP header align */
-		skb_put(skb, pkt_len);	/* Make room */
-		eth_copy_and_sum(skb, gp->rx_buff[nextOut], pkt_len, 0);
+		skb_reserve(skb, 2);   /* 16 byte IP header align */
+		memcpy(skb_put(skb, pkt_len),
+		       &gp->rx_buff[nextOut*PKT_BUF_SZ], pkt_len);
 		skb->protocol = eth_type_trans(skb, dev);
-		netif_rx(skb);	/* pass the packet to upper layers */
+		dump_skb(4, dev, skb);
+	
+		netif_rx(skb);        /* pass the packet to upper layers */
+		dev->last_rx = jiffies;
 
 		// now we can release ownership of this desc back to device
-		cmdstat |= (u32) rxOwn;
+		cmdstat |= (u32)rxOwn;
 		rd->cmdstat = cpu_to_dma32(cmdstat);
-
-		dev->last_rx = jiffies;
 	}
+    
+	if (nextOut == gp->rx_next_out)
+		dbg(3, __FUNCTION__ ": RxCDP did not increment?\n");
 
 	gp->rx_next_out = nextOut;
 	return 0;
 }
 
 
-static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void
+gt96100_tx_complete(struct net_device *dev, u32 status)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
-	u32 status;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	int nextOut, cdp;
+	gt96100_td_t *td;
+	u32 cmdstat;
 
-	if (dev == NULL) {
-		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
-		return;
+	cdp = (GT96100ETH_READ(gp, GT96100_ETH_CURR_TX_DESC_PTR0)
+	       - gp->tx_ring_dma) / sizeof(gt96100_td_t);
+    
+	// Continue until we reach the current descriptor pointer
+	for (nextOut = gp->tx_next_out; nextOut != cdp;
+	     nextOut = (nextOut + 1) % TX_RING_SIZE) {
+	
+		if (--gp->intr_work_done == 0)
+			break;
+
+		td = &gp->tx_ring[nextOut];
+		cmdstat = dma32_to_cpu(td->cmdstat);
+	
+		dbg(3, __FUNCTION__ ": Tx desc cmdstat=%x, nextOut=%d\n",
+		    cmdstat, nextOut);
+	
+		if (cmdstat & (u32)txOwn) {
+			//dump_tx_ring(dev);
+			// DMA is not finished writing descriptor???
+			// Leave and come back later to pick-up where
+			// we left off.
+			break;
+		}
+	
+		// increment Tx error stats
+		if (cmdstat & (u32)txErrorSummary) {
+			dbg(2, __FUNCTION__ ": Tx error, cmdstat = %x\n",
+			    cmdstat);
+			gp->stats.tx_errors++;
+			if (cmdstat & (u32)txReTxLimit)
+				gp->stats.tx_aborted_errors++;
+			if (cmdstat & (u32)txUnderrun)
+				gp->stats.tx_fifo_errors++;
+			if (cmdstat & (u32)txLateCollision)
+				gp->stats.tx_window_errors++;
+		}
+	
+		if (cmdstat & (u32)txCollision)
+			gp->stats.collisions +=
+				(u32)((cmdstat & txReTxCntMask) >>
+				      txReTxCntBit);
+
+		// Wake the queue if the ring was full
+		if (gp->tx_full) {
+			gp->tx_full = 0;
+			if (gp->last_psr & psrLink) {
+				netif_wake_queue(dev);
+				dbg(2, __FUNCTION__
+				    ": Tx Ring was full, queue waked\n");
+			}
+		}
+	
+		// decrement tx ring buffer count
+		if (gp->tx_count) gp->tx_count--;
+	
+		// free the skb
+		if (gp->tx_skbuff[nextOut]) {
+			dbg(3, __FUNCTION__ ": good Tx, skb=%p\n",
+			    gp->tx_skbuff[nextOut]);
+			dev_kfree_skb_irq(gp->tx_skbuff[nextOut]);
+			gp->tx_skbuff[nextOut] = NULL;
+		} else {
+			err(__FUNCTION__ ": no skb!\n");
+		}
 	}
 
-	status = GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE);
-	// ACK interrupts
-#if 0
-	GT96100ETH_CLRBIT(gp, GT96100_ETH_INT_CAUSE,
-			  icrEtherIntSum | icrRxBufferQ1 | icrRxBufferQ2 |
-			  icrRxBufferQ3 | icrRxBufferQ0 | icrTxBufferHigh |
-			  icrTxEndHigh | icrTxBufferLow | icrTxEndLow |
-			  icrTxErrorHigh | icrTxErrorLow | icrTxUdr);
-#else
-	GT96100ETH_WRITE(gp, GT96100_ETH_INT_CAUSE, 0);
-#endif
+	gp->tx_next_out = nextOut;
+
+	if (gt96100_check_tx_consistent(gp)) {
+		err(__FUNCTION__ ": Tx queue inconsistent!\n");
+	}
+    
+	if ((status & icrTxEndLow) && gp->tx_count != 0) {
+		// we must restart the DMA
+		dbg(3, __FUNCTION__ ": Restarting Tx DMA\n");
+		GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
+				 sdcmrERD | sdcmrTXDL);
+	}
+}
+
 
-	if ((status & icrEtherIntSum) == 0) {
-		// not our interrupt
-		//printk("%s: isr: no ints? icr=%x,cp0_cause=%x\n",
-		//       dev->name, status, read_32bit_cp0_register(CP0_CAUSE));
+static void
+gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	u32 status;
+    
+	if (dev == NULL) {
+		err(__FUNCTION__ ": null dev ptr\n");
 		return;
 	}
 
-	if (gt96100_debug > 3)
-		printk("%s: isr: entry, icr=%x\n", dev->name, status);
+	dbg(3, __FUNCTION__ ": entry, icr=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE));
 
-	if (status & (icrRxBufferQ1 | icrRxBufferQ2 | icrRxBufferQ3)) {
-		printk(KERN_ERR "%s: isr: Rx intr in unused queues!?\n",
-		       dev->name);
-	}
-
-	if (status & icrRxBufferQ0) {
-		gt96100_rx(dev, status);
-	}
-
-	if (status & (icrTxBufferHigh | icrTxEndHigh)) {
-		printk(KERN_ERR "%s: isr: Tx intr in unused queue!?\n",
-		       dev->name);
-	}
-
-	if (status & icrMIIPhySTC) {
-		u32 psr = GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS);
-		printk("%s: port status:\n", dev->name);
-		printk
-		    ("%s:     %s MBit/s, %s-duplex, flow-control %s, link is %s,\n",
-		     dev->name, psr & psrSpeed ? "100" : "10",
-		     psr & psrDuplex ? "full" : "half",
-		     psr & psrFctl ? "disabled" : "enabled",
-		     psr & psrLink ? "up" : "down");
-		printk
-		    ("%s:     TxLowQ is %s, TxHighQ is %s, Transmitter is %s\n",
-		     dev->name, psr & psrTxLow ? "running" : "stopped",
-		     psr & psrTxHigh ? "running" : "stopped",
-		     psr & psrTxInProg ? "on" : "off");
-		gp->last_psr = psr;
-	}
-
-	if (status & (icrTxBufferLow | icrTxEndLow)) {
-		int nextOut;
-		gt96100_td_t *td;
-		u32 cmdstat;
-
-		// Continue until we reach the current descriptor pointer
-		for (nextOut = gp->tx_next_out;
-		     nextOut !=
-		     (GT96100ETH_READ(gp, GT96100_ETH_CURR_TX_DESC_PTR0) -
-		      gp->tx_ring_dma) / sizeof(gt96100_td_t);
-		     nextOut = (nextOut + 1) % TX_RING_SIZE) {
-
-			td = &gp->tx_ring[nextOut];
-			cmdstat = dma32_to_cpu(td->cmdstat);
-
-			if (gt96100_debug > 2)
-				printk("%s: isr: Tx desc cmdstat=%x\n",
-				       dev->name, cmdstat);
-
-			if (cmdstat & (u32) txOwn) {
-				cmdstat &= ~((u32) txOwn);
-				td->cmdstat = cpu_to_dma32(cmdstat);
-				printk(KERN_ERR
-				       "%s: isr: Tx ownership bit wrong!\n",
-				       dev->name);
-			}
-			// increment Tx error stats
-			if (cmdstat & (u32) txErrorSummary) {
-				if (gt96100_debug > 2)
-					printk
-					    ("%s: gt96100_interrupt: Tx error, cmdstat = %x\n",
-					     dev->name, cmdstat);
-				gp->stats.tx_errors++;
-				if (cmdstat & (u32) txReTxLimit)
-					gp->stats.collisions++;
-				if (cmdstat & (u32) txUnderrun)
-					gp->stats.tx_fifo_errors++;
-				if (cmdstat & (u32) txLateCollision)
-					gp->stats.tx_window_errors++;
-			}
-			// Wake the queue if the ring was full
-			if (gp->tx_count == TX_RING_SIZE)
-				netif_wake_queue(dev);
+	spin_lock(&gp->lock);
 
-			// decrement tx ring buffer count
-			if (gp->tx_count)
-				gp->tx_count--;
-
-			// free the skb
-			if (gp->tx_skbuff[nextOut]) {
-				if (gt96100_debug > 2)
-					printk
-					    ("%s: isr: good Tx, skb=%p\n",
-					     dev->name,
-					     gp->tx_skbuff[nextOut]);
-				dev_kfree_skb_irq(gp->tx_skbuff[nextOut]);
-				gp->tx_skbuff[nextOut] = NULL;
-			} else {
-				printk(KERN_ERR "%s: isr: no skb!\n",
-				       dev->name);
-			}
-		}
+	gp->intr_work_done = max_interrupt_work;
 
-		if (gp->tx_count == 0 && nextOut != gp->tx_next_in) {
-			// FIX! this should probably be a panic
-			printk(KERN_ERR
-			       "%s: isr: warning! Tx queue inconsistent\n",
-			       dev->name);
-		}
+	while (gp->intr_work_done > 0) {
 
-		gp->tx_next_out = nextOut;
+		status = GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE);
+		// ACK interrupts
+		GT96100ETH_WRITE(gp, GT96100_ETH_INT_CAUSE, ~status);
 
-		if ((status & icrTxEndLow) && gp->tx_count != 0) {
-			// we must restart the DMA
-			if (gt96100_debug > 2)
-				printk("%s: isr: Restarting Tx DMA\n",
-				       dev->name);
-			GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
-					 sdcmrERD | sdcmrTXDL);
-		}
-	}
-	// Now check TX errors (RX errors were handled in gt96100_rx)
+		if ((status & icrEtherIntSum) == 0 &&
+		    !(status & (icrTxBufferLow|icrTxBufferHigh|icrRxBuffer)))
+			break;
+	
+		if (status & icrMIIPhySTC) {
+			u32 psr = GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS);
+			if (gp->last_psr != psr) {
+				dbg(0, "port status:\n");
+				dbg(0, "    %s MBit/s, %s-duplex, "
+				    "flow-control %s, link is %s,\n",
+				    psr & psrSpeed ? "100":"10",
+				    psr & psrDuplex ? "full":"half",
+				    psr & psrFctl ? "disabled":"enabled",
+				    psr & psrLink ? "up":"down");
+				dbg(0, "    TxLowQ is %s, TxHighQ is %s, "
+				    "Transmitter is %s\n",
+				    psr & psrTxLow ? "running":"stopped",
+				    psr & psrTxHigh ? "running":"stopped",
+				    psr & psrTxInProg ? "on":"off");
+		
+				if ((psr & psrLink) && !gp->tx_full &&
+				    netif_queue_stopped(dev)) {
+					dbg(0, __FUNCTION__
+					    ": Link up, waking queue.\n");
+					netif_wake_queue(dev);
+				} else if (!(psr & psrLink) &&
+					   !netif_queue_stopped(dev)) {
+					dbg(0, __FUNCTION__
+					    "Link down, stopping queue.\n");
+					netif_stop_queue(dev);
+				}
 
-	if (status & icrTxErrorHigh) {
-		printk(KERN_ERR
-		       "%s: isr: Tx resource error in unused queue!?\n",
-		       dev->name);
-	}
+				gp->last_psr = psr;
+			}
 
-	if (status & icrTxErrorLow) {
-		printk(KERN_ERR "%s: isr: Tx resource error\n", dev->name);
-	}
+			if (--gp->intr_work_done == 0)
+				break;
+		}
+	
+		if (status & (icrTxBufferLow | icrTxEndLow))
+			gt96100_tx_complete(dev, status);
 
-	if (status & icrTxUdr) {
-		printk(KERN_ERR "%s: isr: Tx underrun error\n", dev->name);
+		if (status & (icrRxBuffer | icrRxError)) {
+			gt96100_rx(dev, status);
+		}
+	
+		// Now check TX errors (RX errors were handled in gt96100_rx)
+		if (status & icrTxErrorLow) {
+			err(__FUNCTION__ ": Tx resource error\n");
+			if (--gp->intr_work_done == 0)
+				break;
+		}
+	
+		if (status & icrTxUdr) {
+			err(__FUNCTION__ ": Tx underrun error\n");
+			if (--gp->intr_work_done == 0)
+				break;
+		}
 	}
 
-	if (gt96100_debug > 3)
-		printk("%s: isr: exit, icr=%x\n",
-		       dev->name, GT96100ETH_READ(gp,
-						  GT96100_ETH_INT_CAUSE));
+	if (gp->intr_work_done == 0) {
+		// ACK any remaining pending interrupts
+		GT96100ETH_WRITE(gp, GT96100_ETH_INT_CAUSE, 0);
+		dbg(3, __FUNCTION__ ": hit max work\n");
+	}
+    
+	dbg(3, __FUNCTION__ ": exit, icr=%x\n",
+	    GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE));
+
+	spin_unlock(&gp->lock);
 }
 
 
-/*
- * The Tx ring has been full longer than the watchdog timeout
- * value, meaning that the interrupt routine has not been freeing
- * up space in the Tx ring buffer.
- */
-static void gt96100_tx_timeout(struct net_device *dev)
+static void
+gt96100_tx_timeout(struct net_device *dev)
 {
-//    struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
-
-	printk(KERN_ERR "%s: gt96100_tx_timeout: dev=%p\n", dev->name,
-	       dev);
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+	unsigned long flags;
+    
+	spin_lock_irqsave(&gp->lock, flags);
+    
+	if (!(gp->last_psr & psrLink)) {
+		err("tx_timeout: link down.\n");
+		spin_unlock_irqrestore(&gp->lock, flags);
+	} else {
+		if (gt96100_check_tx_consistent(gp))
+			err("tx_timeout: Tx ring error.\n");
 
-	// FIX! do something, like reset the device
+		disable_ether_irq(dev);
+		spin_unlock_irqrestore(&gp->lock, flags);
+		reset_tx(dev);
+		enable_ether_irq(dev);
+	
+		netif_wake_queue(dev);
+	}
 }
 
 
-static void gt96100_set_rx_mode(struct net_device *dev)
+static void
+gt96100_set_rx_mode(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	unsigned long flags;
-	struct dev_mc_list *mcptr;
-
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_set_rx_mode: dev=%p, flags=%x\n",
-		       dev->name, dev, dev->flags);
+	//struct dev_mc_list *mcptr;
+    
+	dbg(3, __FUNCTION__ ": dev=%p, flags=%x\n", dev, dev->flags);
 
 	// stop the Receiver DMA
 	abort(dev, sdcmrAR);
 
 	spin_lock_irqsave(&gp->lock, flags);
 
-	if (dev->flags & IFF_PROMISC)
+	if (dev->flags & IFF_PROMISC) {
 		GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG,
 				 pcrEN | pcrHS | pcrPM);
+	}
 
-	memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);	// clear hash table
-	// Add our ethernet address
-	gt96100_add_hash_entry(dev, dev->dev_addr);
-
+#if 0
+	/*
+	  FIXME: currently multicast doesn't work - need to get hash table
+	  working first.
+	*/
 	if (dev->mc_count) {
+		// clear hash table
+		memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);
+		// Add our ethernet address
+		gt96100_add_hash_entry(dev, dev->dev_addr);
+
 		for (mcptr = dev->mc_list; mcptr; mcptr = mcptr->next) {
+			dump_hw_addr(2, dev, __FUNCTION__ ": addr=",
+				     mcptr->dmi_addr);
 			gt96100_add_hash_entry(dev, mcptr->dmi_addr);
 		}
 	}
+#endif
+    
 	// restart Rx DMA
 	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);
 
 	spin_unlock_irqrestore(&gp->lock, flags);
 }
 
-static struct net_device_stats *gt96100_get_stats(struct net_device *dev)
+static struct net_device_stats *
+gt96100_get_stats(struct net_device *dev)
 {
-	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
 	unsigned long flags;
 
-	if (gt96100_debug > 2)
-		printk("%s: gt96100_get_stats: dev=%p\n", dev->name, dev);
+	dbg(3, __FUNCTION__ ": dev=%p\n", dev);
 
 	if (netif_device_present(dev)) {
-		spin_lock_irqsave(&gp->lock, flags);
+		spin_lock_irqsave (&gp->lock, flags);
 		update_stats(gp);
-		spin_unlock_irqrestore(&gp->lock, flags);
+		spin_unlock_irqrestore (&gp->lock, flags);
 	}
 
 	return &gp->stats;
 }
 
-module_init(gt96100_probe);
-MODULE_LICENSE("GPL");
+static void gt96100_cleanup_module(void)
+{
+	int i;
+	for (i=0; i<NUM_INTERFACES; i++) {
+		struct gt96100_if_t *gtif = &gt96100_iflist[i];
+		if (gtif->dev != NULL) {
+			struct gt96100_private *gp =
+				(struct gt96100_private *)gtif->dev->priv;
+			release_region(gtif->iobase, gp->io_size);
+			unregister_netdev(gtif->dev);
+			if (gtif->dev->priv != NULL)
+				kfree (gtif->dev->priv);
+			kfree (gtif->dev);
+		}
+	}
+}
+
+
+#ifndef MODULE
+
+static int __init gt96100_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+        for(this_opt=strtok(options, ",");
+	    this_opt; this_opt=strtok(NULL, ",")) {
+		if (!strncmp(this_opt, "mac0:", 5)) {
+			memcpy(mac0, this_opt+5, 17);
+			mac0[17]= '\0';
+		} else if (!strncmp(this_opt, "mac1:", 5)) {
+			memcpy(mac1, this_opt+5, 17);
+			mac1[17]= '\0';
+		}
+	}
+
+	return 1;
+}
+
+__setup("gt96100eth=", gt96100_setup);
+
+#endif /* !MODULE */
+
+
+module_init(gt96100_init_module);
+module_exit(gt96100_cleanup_module);
+
+MODULE_AUTHOR("Steve Longerbeam <stevel@mvista.com>");
+MODULE_DESCRIPTION("GT96100 Ethernet driver");
diff -Nru a/drivers/net/gt96100eth.h b/drivers/net/gt96100eth.h
--- a/drivers/net/gt96100eth.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/gt96100eth.h	Sun Apr 14 12:16:56 2002
@@ -29,29 +29,43 @@
 
 #include <asm/galileo-boards/gt96100.h>
 
+#define dbg(lvl, format, arg...) \
+    if (lvl <= GT96100_DEBUG) \
+        printk(KERN_DEBUG "%s: " format, dev->name , ## arg)
+#define err(format, arg...) \
+    printk(KERN_ERR "%s: " format, dev->name , ## arg)
+#define info(format, arg...) \
+    printk(KERN_INFO "%s: " format, dev->name , ## arg)
+#define warn(format, arg...) \
+    printk(KERN_WARNING "%s: " format, dev->name , ## arg)
+
 /* Keep the ring sizes a power of two for efficiency. */
 #define TX_RING_SIZE	16
 #define RX_RING_SIZE	32
-#define PKT_BUF_SZ	1536	/* Size of each temporary Rx buffer. */
+#define PKT_BUF_SZ	1536	/* Size of each temporary Rx buffer.*/
 
 #define RX_HASH_TABLE_SIZE 16384
 #define HASH_HOP_NUMBER 12
 
 #define NUM_INTERFACES 2
 
-#define GT96100ETH_TX_TIMEOUT HZ
+#define GT96100ETH_TX_TIMEOUT HZ/4
 
 #define GT96100_ETH0_BASE (MIPS_GT96100_BASE + GT96100_ETH_PORT_CONFIG)
 #define GT96100_ETH1_BASE (GT96100_ETH0_BASE + GT96100_ETH_IO_SIZE)
 
 #ifdef CONFIG_MIPS_EV96100
-#define GT96100_ETHER0_IRQ 4
+#define GT96100_ETHER0_IRQ 3
 #define GT96100_ETHER1_IRQ 4
 #else
 #define GT96100_ETHER0_IRQ -1
 #define GT96100_ETHER1_IRQ -1
 #endif
 
+#define REV_GT96100  1
+#define REV_GT96100A_1 2
+#define REV_GT96100A 3
+
 #define GT96100ETH_READ(gp, offset) \
     GT96100_READ((gp->port_offset + offset))
 
@@ -70,13 +84,13 @@
 /* Bit definitions of the SMI Reg */
 enum {
 	smirDataMask = 0xffff,
-	smirPhyAdMask = 0x1f << 16,
+	smirPhyAdMask = 0x1f<<16,
 	smirPhyAdBit = 16,
-	smirRegAdMask = 0x1f << 21,
+	smirRegAdMask = 0x1f<<21,
 	smirRegAdBit = 21,
-	smirOpCode = 1 << 26,
-	smirReadValid = 1 << 27,
-	smirBusy = 1 << 28
+	smirOpCode = 1<<26,
+	smirReadValid = 1<<27,
+	smirBusy = 1<<28
 };
 
 /* Bit definitions of the Port Config Reg */
@@ -84,17 +98,17 @@
 	pcrPM = 1,
 	pcrRBM = 2,
 	pcrPBF = 4,
-	pcrEN = 1 << 7,
-	pcrLPBKMask = 0x3 << 8,
+	pcrEN = 1<<7,
+	pcrLPBKMask = 0x3<<8,
 	pcrLPBKBit = 8,
-	pcrFC = 1 << 10,
-	pcrHS = 1 << 12,
-	pcrHM = 1 << 13,
-	pcrHDM = 1 << 14,
-	pcrHD = 1 << 15,
-	pcrISLMask = 0x7 << 28,
+	pcrFC = 1<<10,
+	pcrHS = 1<<12,
+	pcrHM = 1<<13,
+	pcrHDM = 1<<14,
+	pcrHD = 1<<15,
+	pcrISLMask = 0x7<<28,
 	pcrISLBit = 28,
-	pcrACCS = 1 << 31
+	pcrACCS = 1<<31
 };
 
 /* Bit definitions of the Port Config Extend Reg */
@@ -102,27 +116,27 @@
 	pcxrIGMP = 1,
 	pcxrSPAN = 2,
 	pcxrPAR = 4,
-	pcxrPRIOtxMask = 0x7 << 3,
+	pcxrPRIOtxMask = 0x7<<3,
 	pcxrPRIOtxBit = 3,
-	pcxrPRIOrxMask = 0x3 << 6,
+	pcxrPRIOrxMask = 0x3<<6,
 	pcxrPRIOrxBit = 6,
-	pcxrPRIOrxOverride = 1 << 8,
-	pcxrDPLXen = 1 << 9,
-	pcxrFCTLen = 1 << 10,
-	pcxrFLP = 1 << 11,
-	pcxrFCTL = 1 << 12,
-	pcxrMFLMask = 0x3 << 14,
+	pcxrPRIOrxOverride = 1<<8,
+	pcxrDPLXen = 1<<9,
+	pcxrFCTLen = 1<<10,
+	pcxrFLP = 1<<11,
+	pcxrFCTL = 1<<12,
+	pcxrMFLMask = 0x3<<14,
 	pcxrMFLBit = 14,
-	pcxrMIBclrMode = 1 << 16,
-	pcxrSpeed = 1 << 18,
-	pcxrSpeeden = 1 << 19,
-	pcxrRMIIen = 1 << 20,
-	pcxrDSCPen = 1 << 21
+	pcxrMIBclrMode = 1<<16,
+	pcxrSpeed = 1<<18,
+	pcxrSpeeden = 1<<19,
+	pcxrRMIIen = 1<<20,
+	pcxrDSCPen = 1<<21
 };
 
 /* Bit definitions of the Port Command Reg */
 enum pcmr_bits {
-	pcmrFJ = 1 << 15
+	pcmrFJ = 1<<15
 };
 
 
@@ -132,119 +146,124 @@
 	psrDuplex = 2,
 	psrFctl = 4,
 	psrLink = 8,
-	psrPause = 1 << 4,
-	psrTxLow = 1 << 5,
-	psrTxHigh = 1 << 6,
-	psrTxInProg = 1 << 7
+	psrPause = 1<<4,
+	psrTxLow = 1<<5,
+	psrTxHigh = 1<<6,
+	psrTxInProg = 1<<7
 };
 
 /* Bit definitions of the SDMA Config Reg */
 enum sdcr_bits {
-	sdcrRCMask = 0xf << 2,
+	sdcrRCMask = 0xf<<2,
 	sdcrRCBit = 2,
-	sdcrBLMR = 1 << 6,
-	sdcrBLMT = 1 << 7,
-	sdcrPOVR = 1 << 8,
-	sdcrRIFB = 1 << 9,
-	sdcrBSZMask = 0x3 << 12,
+	sdcrBLMR = 1<<6,
+	sdcrBLMT = 1<<7,
+	sdcrPOVR = 1<<8,
+	sdcrRIFB = 1<<9,
+	sdcrBSZMask = 0x3<<12,
 	sdcrBSZBit = 12
 };
 
 /* Bit definitions of the SDMA Command Reg */
 enum sdcmr_bits {
-	sdcmrERD = 1 << 7,
-	sdcmrAR = 1 << 15,
-	sdcmrSTDH = 1 << 16,
-	sdcmrSTDL = 1 << 17,
-	sdcmrTXDH = 1 << 23,
-	sdcmrTXDL = 1 << 24,
-	sdcmrAT = 1 << 31
+	sdcmrERD = 1<<7,
+	sdcmrAR = 1<<15,
+	sdcmrSTDH = 1<<16,
+	sdcmrSTDL = 1<<17,
+	sdcmrTXDH = 1<<23,
+	sdcmrTXDL = 1<<24,
+	sdcmrAT = 1<<31
 };
 
 /* Bit definitions of the Interrupt Cause Reg */
 enum icr_bits {
 	icrRxBuffer = 1,
-	icrTxBufferHigh = 1 << 2,
-	icrTxBufferLow = 1 << 3,
-	icrTxEndHigh = 1 << 6,
-	icrTxEndLow = 1 << 7,
-	icrRxError = 1 << 8,
-	icrTxErrorHigh = 1 << 10,
-	icrTxErrorLow = 1 << 11,
-	icrRxOVR = 1 << 12,
-	icrTxUdr = 1 << 13,
-	icrRxBufferQ0 = 1 << 16,
-	icrRxBufferQ1 = 1 << 17,
-	icrRxBufferQ2 = 1 << 18,
-	icrRxBufferQ3 = 1 << 19,
-	icrRxErrorQ0 = 1 << 20,
-	icrRxErrorQ1 = 1 << 21,
-	icrRxErrorQ2 = 1 << 22,
-	icrRxErrorQ3 = 1 << 23,
-	icrMIIPhySTC = 1 << 28,
-	icrSMIdone = 1 << 29,
-	icrEtherIntSum = 1 << 31
+	icrTxBufferHigh = 1<<2,
+	icrTxBufferLow = 1<<3,
+	icrTxEndHigh = 1<<6,
+	icrTxEndLow = 1<<7,
+	icrRxError = 1<<8,
+	icrTxErrorHigh = 1<<10,
+	icrTxErrorLow = 1<<11,
+	icrRxOVR = 1<<12,
+	icrTxUdr = 1<<13,
+	icrRxBufferQ0 = 1<<16,
+	icrRxBufferQ1 = 1<<17,
+	icrRxBufferQ2 = 1<<18,
+	icrRxBufferQ3 = 1<<19,
+	icrRxErrorQ0 = 1<<20,
+	icrRxErrorQ1 = 1<<21,
+	icrRxErrorQ2 = 1<<22,
+	icrRxErrorQ3 = 1<<23,
+	icrMIIPhySTC = 1<<28,
+	icrSMIdone = 1<<29,
+	icrEtherIntSum = 1<<31
 };
 
 
 /* The Rx and Tx descriptor lists. */
-
 typedef struct {
+#ifdef DESC_BE
+	u16 byte_cnt;
+	u16 reserved;
+#else
+	u16 reserved;
+	u16 byte_cnt;
+#endif
 	u32 cmdstat;
-	u32 byte_cnt;
-	u32 buff_ptr;
 	u32 next;
-} gt96100_td_t;
-
-#define tdByteCntBit 16
+	u32 buff_ptr;
+} gt96100_td_t __attribute__ ((packed));
 
 typedef struct {
+#ifdef DESC_BE
+	u16 buff_sz;
+	u16 byte_cnt;
+#else
+	u16 byte_cnt;
+	u16 buff_sz;
+#endif
 	u32 cmdstat;
-	u32 buff_cnt_sz;
-	u32 buff_ptr;
 	u32 next;
-} gt96100_rd_t;
-
-#define rdBuffSzBit 16
-#define rdByteCntMask 0xffff
+	u32 buff_ptr;
+} gt96100_rd_t __attribute__ ((packed));
 
 
 /* Values for the Tx command-status descriptor entry. */
 enum td_cmdstat {
-	txOwn = 1 << 31,
-	txAutoMode = 1 << 30,
-	txEI = 1 << 23,
-	txGenCRC = 1 << 22,
-	txPad = 1 << 18,
-	txFirst = 1 << 17,
-	txLast = 1 << 16,
-	txErrorSummary = 1 << 15,
-	txReTxCntMask = 0x0f << 10,
+	txOwn = 1<<31,
+	txAutoMode = 1<<30,
+	txEI = 1<<23,
+	txGenCRC = 1<<22,
+	txPad = 1<<18,
+	txFirst = 1<<17,
+	txLast = 1<<16,
+	txErrorSummary = 1<<15,
+	txReTxCntMask = 0x0f<<10,
 	txReTxCntBit = 10,
-	txCollision = 1 << 9,
-	txReTxLimit = 1 << 8,
-	txUnderrun = 1 << 6,
-	txLateCollision = 1 << 5
+	txCollision = 1<<9,
+	txReTxLimit = 1<<8,
+	txUnderrun = 1<<6,
+	txLateCollision = 1<<5
 };
 
-#define TxReTxCntBit 10
 
 /* Values for the Rx command-status descriptor entry. */
 enum rd_cmdstat {
-	rxOwn = 1 << 31,
-	rxAutoMode = 1 << 30,
-	rxEI = 1 << 23,
-	rxFirst = 1 << 17,
-	rxLast = 1 << 16,
-	rxErrorSummary = 1 << 15,
-	rxIGMP = 1 << 14,
-	rxHashExpired = 1 << 13,
-	rxMissedFrame = 1 << 12,
-	rxFrameType = 1 << 11,
-	rxShortFrame = 1 << 8,
-	rxMaxFrameLen = 1 << 7,
-	rxOverrun = 1 << 6,
-	rxCollision = 1 << 4,
+	rxOwn = 1<<31,
+	rxAutoMode = 1<<30,
+	rxEI = 1<<23,
+	rxFirst = 1<<17,
+	rxLast = 1<<16,
+	rxErrorSummary = 1<<15,
+	rxIGMP = 1<<14,
+	rxHashExpired = 1<<13,
+	rxMissedFrame = 1<<12,
+	rxFrameType = 1<<11,
+	rxShortFrame = 1<<8,
+	rxMaxFrameLen = 1<<7,
+	rxOverrun = 1<<6,
+	rxCollision = 1<<4,
 	rxCRCError = 1
 };
 
@@ -286,40 +305,44 @@
 
 
 struct gt96100_private {
-	gt96100_rd_t *rx_ring;
-	gt96100_td_t *tx_ring;
+	gt96100_rd_t* rx_ring;
+	gt96100_td_t* tx_ring;
 	// The Rx and Tx rings must be 16-byte aligned
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
-	char *hash_table;
+	char* hash_table;
 	// The Hash Table must be 8-byte aligned
 	dma_addr_t hash_table_dma;
 	int hash_mode;
-
+    
 	// The Rx buffers must be 8-byte aligned
-	char *rx_buff[RX_RING_SIZE];
+	char* rx_buff;
+	dma_addr_t rx_buff_dma;
 	// Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
 	// of payload must be 8-byte aligned
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	int rx_next_out;	/* The next free ring entry to receive */
-	int tx_next_in;		/* The next free ring entry to send */
-	int tx_next_out;	/* The last ring entry the ISR processed */
-	int tx_count;		/* current # of pkts waiting to be sent in Tx ring */
-
+	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	int rx_next_out; /* The next free ring entry to receive */
+	int tx_next_in;	 /* The next free ring entry to send */
+	int tx_next_out; /* The last ring entry the ISR processed */
+	int tx_count;    /* current # of pkts waiting to be sent in Tx ring */
+	int intr_work_done; /* number of Rx and Tx pkts processed in the isr */
+	int tx_full;        /* Tx ring is full */
+    
 	mib_counters_t mib;
 	struct net_device_stats stats;
 
 	int io_size;
-	int port_num;		// 0 or 1
+	int port_num;  // 0 or 1
+	int chip_rev;
 	u32 port_offset;
+    
+	int phy_addr; // PHY address
+	u32 last_psr; // last value of the port status register
 
-	int phy_addr;		// PHY address
-	u32 last_psr;		// last value of the port status register
-
-	int options;		/* User-settable misc. driver options. */
+	int options;     /* User-settable misc. driver options. */
 	int drv_flags;
-	unsigned char phys[2];	/* MII device addresses. */
-	spinlock_t lock;	/* Serialise access to device */
+	struct timer_list timer;
+	spinlock_t lock; /* Serialise access to device */
 };
 
 #endif
diff -Nru a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
--- a/drivers/net/hamradio/6pack.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/hamradio/6pack.c	Sun Apr 14 12:16:56 2002
@@ -256,7 +256,7 @@
 	skb->mac.raw = skb->data;
 	skb->protocol = htons(ETH_P_AX25);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
+	sp->dev->last_rx = jiffies;
 	sp->stats.rx_packets++;
 }
 
@@ -701,7 +701,6 @@
 /* Initialize 6pack control device -- register 6pack line discipline */
 
 static char msg_banner[]  __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n";
-static char msg_invparm[] __initdata = KERN_ERR  "6pack: sixpack_maxdev parameter too large.\n";
 static char msg_nomem[]   __initdata = KERN_ERR  "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n";
 static char msg_regfail[] __initdata = KERN_ERR  "6pack: can't register line discipline (err = %d)\n";
 
@@ -1064,6 +1063,7 @@
 
 MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>");
 MODULE_DESCRIPTION("6pack driver for AX.25");
+MODULE_LICENSE("GPL");
 
 module_init(sixpack_init_driver);
 module_exit(sixpack_exit_driver);
diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
--- a/drivers/net/hamradio/baycom_epp.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hamradio/baycom_epp.c	Sun Apr 14 12:16:58 2002
@@ -302,7 +302,7 @@
 /*---------------------------------------------------------------------------*/
 
 #if 0
-extern inline void append_crc_ccitt(unsigned char *buffer, int len)
+static inline void append_crc_ccitt(unsigned char *buffer, int len)
 {
  	unsigned int crc = 0xffff;
 
@@ -316,7 +316,7 @@
 
 /*---------------------------------------------------------------------------*/
 
-extern inline int check_crc_ccitt(const unsigned char *buf, int cnt)
+static inline int check_crc_ccitt(const unsigned char *buf, int cnt)
 {
 	unsigned int crc = 0xffff;
 
@@ -327,7 +327,7 @@
 
 /*---------------------------------------------------------------------------*/
 
-extern inline int calc_crc_ccitt(const unsigned char *buf, int cnt)
+static inline int calc_crc_ccitt(const unsigned char *buf, int cnt)
 {
 	unsigned int crc = 0xffff;
 
@@ -1416,6 +1416,7 @@
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("Baycom epp amateur radio modem driver");
+MODULE_LICENSE("GPL");
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
--- a/drivers/net/hamradio/baycom_par.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/hamradio/baycom_par.c	Sun Apr 14 12:16:59 2002
@@ -493,6 +493,7 @@
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("Baycom par96 and picpar amateur radio modem driver");
+MODULE_LICENSE("GPL");
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
--- a/drivers/net/hamradio/baycom_ser_fdx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/hamradio/baycom_ser_fdx.c	Sun Apr 14 12:16:59 2002
@@ -201,12 +201,12 @@
 /* --------------------------------------------------------------------- */
 
 #if 0
-extern inline unsigned int hweight16(unsigned int w)
+static inline unsigned int hweight16(unsigned int w)
         __attribute__ ((unused));
-extern inline unsigned int hweight8(unsigned int w)
+static inline unsigned int hweight8(unsigned int w)
         __attribute__ ((unused));
 
-extern inline unsigned int hweight16(unsigned int w)
+static inline unsigned int hweight16(unsigned int w)
 {
         unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
         res = (res & 0x3333) + ((res >> 2) & 0x3333);
@@ -214,7 +214,7 @@
         return (res & 0x00FF) + ((res >> 8) & 0x00FF);
 }
 
-extern inline unsigned int hweight8(unsigned int w)
+static inline unsigned int hweight8(unsigned int w)
 {
         unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
         res = (res & 0x33) + ((res >> 2) & 0x33);
@@ -609,6 +609,7 @@
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("Baycom ser12 full duplex amateur radio modem driver");
+MODULE_LICENSE("GPL");
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
--- a/drivers/net/hamradio/baycom_ser_hdx.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/hamradio/baycom_ser_hdx.c	Sun Apr 14 12:16:55 2002
@@ -649,6 +649,7 @@
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("Baycom ser12 half duplex amateur radio modem driver");
+MODULE_LICENSE("GPL");
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
--- a/drivers/net/hamradio/bpqether.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hamradio/bpqether.c	Sun Apr 14 12:16:58 2002
@@ -645,5 +645,6 @@
 
 MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@yaina.de>");
 MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet");
+MODULE_LICENSE("GPL");
 module_init(bpq_init_driver);
 module_exit(bpq_cleanup_driver);
diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
--- a/drivers/net/hamradio/dmascc.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hamradio/dmascc.c	Sun Apr 14 12:16:58 2002
@@ -305,6 +305,7 @@
 MODULE_AUTHOR("Klaus Kudielka");
 MODULE_DESCRIPTION("Driver for high-speed SCC boards");
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
+MODULE_LICENSE("GPL");
 
 
 int init_module(void) {
@@ -1121,6 +1122,7 @@
       skb->protocol = ntohs(ETH_P_AX25);
       skb->mac.raw = skb->data;
       netif_rx(skb);
+      priv->dev->last_rx = jiffies;
       priv->stats.rx_packets++;
       priv->stats.rx_bytes += cb;
     }
diff -Nru a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
--- a/drivers/net/hamradio/hdlcdrv.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/hamradio/hdlcdrv.c	Sun Apr 14 12:16:56 2002
@@ -902,6 +902,7 @@
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
+MODULE_LICENSE("GPL");
 module_init(hdlcdrv_init_driver);
 module_exit(hdlcdrv_cleanup_driver);
 
diff -Nru a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hamradio/mkiss.c	Sun Apr 14 12:16:58 2002
@@ -345,7 +345,7 @@
 	skb->mac.raw  = skb->data;
 	skb->protocol = htons(ETH_P_AX25);
 	netif_rx(skb);
-	dev->last_rx = jiffies;
+	tmp_ax->dev->last_rx = jiffies;
 	tmp_ax->rx_packets++;
 }
 
@@ -1008,6 +1008,7 @@
 MODULE_DESCRIPTION("KISS driver for AX.25 over TTYs");
 MODULE_PARM(ax25_maxdev, "i");
 MODULE_PARM_DESC(ax25_maxdev, "number of MKISS devices");
+MODULE_LICENSE("GPL");
 
 module_init(mkiss_init_driver);
 module_exit(mkiss_exit_driver);
diff -Nru a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
--- a/drivers/net/hamradio/scc.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/hamradio/scc.c	Sun Apr 14 12:16:57 2002
@@ -1661,7 +1661,7 @@
 	skb->pkt_type = PACKET_HOST;
 	
 	netif_rx(skb);
-	dev->last_rx = jiffies;
+	scc->dev->last_rx = jiffies;
 	return;
 }
 
@@ -2180,5 +2180,6 @@
 MODULE_AUTHOR("Joerg Reuter <jreuter@yaina.de>");
 MODULE_DESCRIPTION("AX.25 Device Driver for Z8530 based HDLC cards");
 MODULE_SUPPORTED_DEVICE("Z8530 based SCC cards for Amateur Radio");
+MODULE_LICENSE("GPL");
 module_init(scc_init_driver);
 module_exit(scc_cleanup_driver);
diff -Nru a/drivers/net/hamradio/soundmodem/sm.h b/drivers/net/hamradio/soundmodem/sm.h
--- a/drivers/net/hamradio/soundmodem/sm.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/hamradio/soundmodem/sm.h	Sun Apr 14 12:16:54 2002
@@ -158,7 +158,7 @@
  * ===================== diagnostics stuff ===============================
  */
 
-extern inline void diag_trigger(struct sm_state *sm)
+static inline void diag_trigger(struct sm_state *sm)
 {
 	if (sm->diag.ptr < 0)
 		if (!(sm->diag.flags & SM_DIAGFLAG_DCDGATE) || sm->hdrv.hdlcrx.dcd)
@@ -170,7 +170,7 @@
 #define SHRT_MAX ((short)(((unsigned short)(~0U))>>1))
 #define SHRT_MIN (-SHRT_MAX-1)
 
-extern inline void diag_add(struct sm_state *sm, int valinp, int valdemod)
+static inline void diag_add(struct sm_state *sm, int valinp, int valdemod)
 {
 	int val;
 
@@ -189,7 +189,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern inline void diag_add_one(struct sm_state *sm, int val)
+static inline void diag_add_one(struct sm_state *sm, int val)
 {
 	if ((sm->diag.mode != SM_DIAGMODE_INPUT &&
 	     sm->diag.mode != SM_DIAGMODE_DEMOD) ||
@@ -229,14 +229,14 @@
  */
 
 #if 0
-extern inline unsigned int hweight32(unsigned int w)
+static inline unsigned int hweight32(unsigned int w)
 	__attribute__ ((unused));
-extern inline unsigned int hweight16(unsigned short w)
+static inline unsigned int hweight16(unsigned short w)
 	__attribute__ ((unused));
-extern inline unsigned int hweight8(unsigned char w)
+static inline unsigned int hweight8(unsigned char w)
         __attribute__ ((unused));
 
-extern inline unsigned int hweight32(unsigned int w)
+static inline unsigned int hweight32(unsigned int w)
 {
         unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
         res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
@@ -245,7 +245,7 @@
         return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
 }
 
-extern inline unsigned int hweight16(unsigned short w)
+static inline unsigned int hweight16(unsigned short w)
 {
         unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
         res = (res & 0x3333) + ((res >> 2) & 0x3333);
@@ -253,7 +253,7 @@
         return (res & 0x00FF) + ((res >> 8) & 0x00FF);
 }
 
-extern inline unsigned int hweight8(unsigned char w)
+static inline unsigned int hweight8(unsigned char w)
 {
         unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
         res = (res & 0x33) + ((res >> 2) & 0x33);
@@ -262,12 +262,12 @@
 
 #endif
 
-extern inline unsigned int gcd(unsigned int x, unsigned int y)
+static inline unsigned int gcd(unsigned int x, unsigned int y)
 	__attribute__ ((unused));
-extern inline unsigned int lcm(unsigned int x, unsigned int y)
+static inline unsigned int lcm(unsigned int x, unsigned int y)
 	__attribute__ ((unused));
 
-extern inline unsigned int gcd(unsigned int x, unsigned int y)
+static inline unsigned int gcd(unsigned int x, unsigned int y)
 {
 	for (;;) {
 		if (!x)
@@ -281,7 +281,7 @@
 	}
 }
 
-extern inline unsigned int lcm(unsigned int x, unsigned int y)
+static inline unsigned int lcm(unsigned int x, unsigned int y)
 {
 	return x * y / gcd(x, y);
 }
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk1200.c b/drivers/net/hamradio/soundmodem/sm_afsk1200.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk1200.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hamradio/soundmodem/sm_afsk1200.c	Sun Apr 14 12:16:58 2002
@@ -94,7 +94,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum)
+static __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum)
 {
 	int sum = -0x80 * csum;
 	
@@ -111,7 +111,7 @@
 	return sum * sum;
 }
 
-extern __inline__ int convolution8_s16(const short *st, const int *coeff, int csum)
+static __inline__ int convolution8_s16(const short *st, const int *coeff, int csum)
 {
 	int sum = 0;
 	
@@ -128,7 +128,7 @@
 	return sum * sum;
 }
 
-extern __inline__ int do_filter_1200_u8(const unsigned char *buf)
+static __inline__ int do_filter_1200_u8(const unsigned char *buf)
 {
 	int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
 	sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
@@ -137,7 +137,7 @@
 	return sum;
 }
 
-extern __inline__ int do_filter_1200_s16(const short *buf)
+static __inline__ int do_filter_1200_s16(const short *buf)
 {
 	int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I);
 	sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q);
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c b/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c	Sun Apr 14 12:16:56 2002
@@ -104,7 +104,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
+static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
 {
 	int sum = -0x80 * csum;
 	
@@ -127,7 +127,7 @@
 	return sum * sum;
 }
 
-extern __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
+static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
 {
 	int sum = 0;
 	
@@ -150,7 +150,7 @@
 	return sum * sum;
 }
 
-extern __inline__ int do_filter_2400_u8(const unsigned char *buf)
+static __inline__ int do_filter_2400_u8(const unsigned char *buf)
 {
 	int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
 	sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
@@ -159,7 +159,7 @@
 	return sum;
 }
 
-extern __inline__ int do_filter_2400_s16(const short *buf)
+static __inline__ int do_filter_2400_s16(const short *buf)
 {
 	int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
 	sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c b/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c	Sun Apr 14 12:16:56 2002
@@ -104,7 +104,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
+static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum)
 {
 	int sum = -0x80 * csum;
 	
@@ -127,7 +127,7 @@
 	return sum * sum;
 }
 
-extern __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
+static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum)
 {
 	int sum = 0;
 	
@@ -150,7 +150,7 @@
 	return sum * sum;
 }
 
-extern __inline__ int do_filter_2400_u8(const unsigned char *buf)
+static __inline__ int do_filter_2400_u8(const unsigned char *buf)
 {
 	int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
 	sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
@@ -159,7 +159,7 @@
 	return sum;
 }
 
-extern __inline__ int do_filter_2400_s16(const short *buf)
+static __inline__ int do_filter_2400_s16(const short *buf)
 {
 	int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I);
 	sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q);
diff -Nru a/drivers/net/hamradio/soundmodem/sm_afsk2666.c b/drivers/net/hamradio/soundmodem/sm_afsk2666.c
--- a/drivers/net/hamradio/soundmodem/sm_afsk2666.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/hamradio/soundmodem/sm_afsk2666.c	Sun Apr 14 12:16:59 2002
@@ -114,7 +114,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ int convolution12_u8(const unsigned char *st, const int *coeff, int csum)
+static __inline__ int convolution12_u8(const unsigned char *st, const int *coeff, int csum)
 {
 	int sum = -0x80 * csum;
 	
@@ -134,7 +134,7 @@
 	return sum;
 }
 
-extern __inline__ int convolution12_s16(const short *st, const int *coeff, int csum)
+static __inline__ int convolution12_s16(const short *st, const int *coeff, int csum)
 {
 	int sum = 0;
 	
diff -Nru a/drivers/net/hamradio/soundmodem/sm_sbc.c b/drivers/net/hamradio/soundmodem/sm_sbc.c
--- a/drivers/net/hamradio/soundmodem/sm_sbc.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/hamradio/soundmodem/sm_sbc.c	Sun Apr 14 12:16:56 2002
@@ -59,7 +59,7 @@
 #define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
 #define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
 
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
+static inline int copy_from_user(void *to, const void *from, unsigned long n)
 {
         int i = verify_area(VERIFY_READ, from, n);
         if (i)
@@ -68,7 +68,7 @@
         return 0;
 }
 
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
+static inline int copy_to_user(void *to, const void *from, unsigned long n)
 {
         int i = verify_area(VERIFY_WRITE, to, n);
         if (i)
diff -Nru a/drivers/net/hamradio/soundmodem/sm_wss.c b/drivers/net/hamradio/soundmodem/sm_wss.c
--- a/drivers/net/hamradio/soundmodem/sm_wss.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hamradio/soundmodem/sm_wss.c	Sun Apr 14 12:16:58 2002
@@ -58,7 +58,7 @@
 #define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
 #define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
 
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
+static inline int copy_from_user(void *to, const void *from, unsigned long n)
 {
         int i = verify_area(VERIFY_READ, from, n);
         if (i)
@@ -67,7 +67,7 @@
         return 0;
 }
 
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
+static inline int copy_to_user(void *to, const void *from, unsigned long n)
 {
         int i = verify_area(VERIFY_WRITE, to, n);
         if (i)
diff -Nru a/drivers/net/hamradio/soundmodem/smdma.h b/drivers/net/hamradio/soundmodem/smdma.h
--- a/drivers/net/hamradio/soundmodem/smdma.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/hamradio/soundmodem/smdma.h	Sun Apr 14 12:16:55 2002
@@ -52,7 +52,7 @@
 /*
  * returns the number of samples per fragment
  */
-extern __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr)
+static __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr)
 {
 	if (send) {
 		disable_dma(dmanr);
@@ -79,7 +79,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr,
+static __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr,
 				       unsigned int *curfrag)
 {
 	unsigned int dmaptr, sz, frg, offs;
@@ -120,7 +120,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag)
+static __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag)
 {
 	unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS;
 
@@ -137,7 +137,7 @@
 	return 0;
 }
 
-extern __inline__ void dma_transmit(struct sm_state *sm)
+static __inline__ void dma_transmit(struct sm_state *sm)
 {
 	void *p;
 
@@ -155,13 +155,13 @@
 	}
 }
 
-extern __inline__ void dma_init_transmit(struct sm_state *sm)
+static __inline__ void dma_init_transmit(struct sm_state *sm)
 {
 	sm->dma.ofragptr = 0;
 	sm->dma.ptt_cnt = 0;
 }
 
-extern __inline__ void dma_start_transmit(struct sm_state *sm)
+static __inline__ void dma_start_transmit(struct sm_state *sm)
 {
 	sm->dma.ofragptr = 0;
 	if (sm->dma.o16bit) {
@@ -174,7 +174,7 @@
 	sm->dma.ptt_cnt = 1;
 }
 
-extern __inline__ void dma_clear_transmit(struct sm_state *sm)
+static __inline__ void dma_clear_transmit(struct sm_state *sm)
 {
 	sm->dma.ptt_cnt = 0;
 	memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS);
@@ -182,7 +182,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag)
+static __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag)
 {
 	void *p;
 
@@ -205,7 +205,7 @@
 	}
 }
 
-extern __inline__ void dma_init_receive(struct sm_state *sm)
+static __inline__ void dma_init_receive(struct sm_state *sm)
 {
 	sm->dma.ifragptr = 0;
 }
diff -Nru a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
--- a/drivers/net/hamradio/yam.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/hamradio/yam.c	Sun Apr 14 12:16:59 2002
@@ -308,7 +308,8 @@
 static void delay(int ms)
 {
 	unsigned long timeout = jiffies + ((ms * HZ) / 1000);
-	while (jiffies < timeout);
+	while (time_before(jiffies, timeout))
+		cpu_relax();
 }
 
 /*
@@ -1178,6 +1179,7 @@
 
 MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");
 MODULE_DESCRIPTION("Yam amateur radio modem driver");
+MODULE_LICENSE("GPL");
 
 module_init(yam_init_driver);
 module_exit(yam_cleanup_driver);
diff -Nru a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
--- a/drivers/net/hp-plus.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/hp-plus.c	Sun Apr 14 12:16:55 2002
@@ -230,8 +230,8 @@
 		ei_status.block_output = &hpp_mem_block_output;
 		ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
 		dev->mem_start = mem_start;
-		dev->rmem_start = dev->mem_start + TX_2X_PAGES*256;
-		dev->mem_end = dev->rmem_end
+		ei_status.rmem_start = dev->mem_start + TX_2X_PAGES*256;
+		dev->mem_end = ei_status.rmem_end
 			= dev->mem_start + (HP_STOP_PG - HP_START_PG)*256;
 	}
 
diff -Nru a/drivers/net/hydra.c b/drivers/net/hydra.c
--- a/drivers/net/hydra.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/hydra.c	Sun Apr 14 12:16:58 2002
@@ -121,7 +121,7 @@
 	dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
 
     /* We must set the 8390 for word mode. */
-    writeb(0x4b, ioaddr + NE_EN0_DCFG);
+    z_writeb(0x4b, ioaddr + NE_EN0_DCFG);
     start_page = NESM_START_PG;
     stop_page = NESM_STOP_PG;
 
@@ -196,10 +196,10 @@
 			     ((ring_page - NESM_START_PG)<<8);
     ptrs = (short *)hdr;
 
-    *(ptrs++) = readw(hdr_start);
+    *(ptrs++) = z_readw(hdr_start);
     *((short *)hdr) = WORDSWAP(*((short *)hdr));
     hdr_start += 2;
-    *(ptrs++) = readw(hdr_start);
+    *(ptrs++) = z_readw(hdr_start);
     *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
 }
 
@@ -216,11 +216,11 @@
     if (xfer_start+count >  mem_base + (NESM_STOP_PG<<8)) {
 	int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
 
-	memcpy_fromio(skb->data,xfer_start,semi_count);
+	z_memcpy_fromio(skb->data,xfer_start,semi_count);
 	count -= semi_count;
-	memcpy_fromio(skb->data+semi_count, mem_base, count);
+	z_memcpy_fromio(skb->data+semi_count, mem_base, count);
     } else
-	memcpy_fromio(skb->data, xfer_start,count);
+	z_memcpy_fromio(skb->data, xfer_start,count);
 
 }
 
@@ -233,7 +233,7 @@
     if (count&1)
 	count++;
 
-    memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
+    z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
 }
 
 static void __exit hydra_cleanup(void)
diff -Nru a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
--- a/drivers/net/ioc3-eth.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/ioc3-eth.c	Sun Apr 14 12:16:55 2002
@@ -341,14 +341,15 @@
 }
 
 /*
- * Read the NIC (Number-In-a-Can) device.
+ * Read the NIC (Number-In-a-Can) device used to store the MAC address on
+ * SN0 / SN00 nodeboards and PCI cards.
  */
-static void ioc3_get_eaddr(struct ioc3_private *ip)
+static void ioc3_get_eaddr_nic(struct ioc3_private *ip)
 {
 	struct ioc3 *ioc3 = ip->regs;
 	u8 nic[14];
-	int i;
 	int tries = 2; /* There may be some problem with the battery?  */
+	int i;
 
 	ioc3_w(gpcr_s, (1 << 21));
 
@@ -371,16 +372,123 @@
 	for (i = 13; i >= 0; i--)
 		nic[i] = nic_read_byte(ioc3);
 
-	printk("Ethernet address is ");
-	for (i = 2; i < 8; i++) {
+	for (i = 2; i < 8; i++)
 		ip->dev->dev_addr[i - 2] = nic[i];
-		printk("%02x", nic[i]);
+}
+
+#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
+/*
+ * Get the ether-address on SN1 nodes
+ */
+static void ioc3_get_eaddr_sn(struct ioc3_private *ip)
+{
+	int ibrick_mac_addr_get(nasid_t, char *);
+	struct ioc3 *ioc3 = ip->regs;
+	nasid_t nasid_of_ioc3;
+	char io7eaddr[20];
+	long mac;
+	int err_val;
+
+	/*
+	 * err_val = ibrick_mac_addr_get(get_nasid(), io7eaddr );
+	 * 
+	 * BAD!!  The above call uses get_nasid() and assumes that
+	 * the ioc3 pointed to by struct ioc3 is hooked up to the
+	 * cbrick that we're running on.  The proper way to make this call
+	 * is to figure out which nasid the ioc3 is connected to
+	 * and use that to call ibrick_mac_addr_get.  Below is
+	 * a hack to do just that.
+	 */
+
+	/*
+	 * Get the nasid of the ioc3 from the ioc3's base addr.
+	 * FIXME: the 8 at the end assumes we're in memory mode, 
+	 * not node mode (for that, we'd change it to a 9).
+	 * Is there a call to extract this info from a physical
+	 * addr somewhere in an sn header file already?  If so,
+	 * we should probably use that, or restructure this routine
+	 * to use pci_dev and generic numa nodeid getting stuff.
+	 */
+	nasid_of_ioc3 = (((unsigned long)ioc3 >> 33) & ~(-1 << 8));
+	err_val = ibrick_mac_addr_get(nasid_of_ioc3, io7eaddr );
+
+
+	if (err_val) {
+		/* Couldn't read the eeprom; try OSLoadOptions. */
+		printk("WARNING: ibrick_mac_addr_get failed: %d\n", err_val);
+
+		/* this is where we hardwire the mac address
+ 		 * 1st ibrick had 08:00:69:11:34:75
+ 		 * 2nd ibrick had 08:00:69:11:35:35
+ 		 *
+ 		 * Eagan Machines:
+ 		 *      mankato1 08:00:69:11:BE:95
+ 		 *      warroad  08:00:69:11:bd:60
+ 		 *      duron    08:00:69:11:34:60
+ 		 *
+ 		 * an easy way to get the mac address is to hook
+ 		 * up an ip35, then from L1 do 'cti serial'
+ 		 * and then look for MAC line XXX THIS DOESN"T QUITE WORK!!
+ 		 */
+		printk("ioc3_get_eaddr: setting ethernet address to:\n -----> ");
+		ip->dev->dev_addr[0] = 0x8;
+		ip->dev->dev_addr[1] = 0x0;
+		ip->dev->dev_addr[2] = 0x69;
+		ip->dev->dev_addr[3] = 0x11;
+		ip->dev->dev_addr[4] = 0x34;
+		ip->dev->dev_addr[5] = 0x60;
+	}
+	else {
+		long simple_strtol(const char *,char **,unsigned int);
+
+		mac = simple_strtol(io7eaddr, (char **)0, 16);
+		ip->dev->dev_addr[0] = (mac >> 40) & 0xff;
+		ip->dev->dev_addr[1] = (mac >> 32) & 0xff;
+		ip->dev->dev_addr[2] = (mac >> 24) & 0xff;
+		ip->dev->dev_addr[3] = (mac >> 16) & 0xff;
+		ip->dev->dev_addr[4] = (mac >> 8) & 0xff;
+		ip->dev->dev_addr[5] = mac & 0xff;
+	}
+}
+#endif
+
+/*
+ * Ok, this is hosed by design.  It's necessary to know what machine the
+ * NIC is in in order to know how to read the NIC address.  We also have
+ * to know if it's a PCI card or a NIC in on the node board ...
+ */
+static void ioc3_get_eaddr(struct ioc3_private *ip)
+{
+	void (*do_get_eaddr)(struct ioc3_private *ip) = NULL;
+	int i;
+
+	/*
+	 * We should also use this code for PCI cards, no matter what host
+	 * machine but how to know that we're a PCI card?
+	 */
+#ifdef CONFIG_SGI_IP27
+	do_get_eaddr = ioc3_get_eaddr_nic;
+#endif
+#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
+	do_get_eaddr = ioc3_get_eaddr_sn;
+#endif
+
+	if (!do_get_eaddr) {
+		printk(KERN_ERR "Don't know how to read MAC address of this "
+		       "IOC3 NIC\n");
+		return;
+	}
+
+	printk("Ethernet address is ");
+	for (i = 0; i < 6; i++) {
+		printk("%02x", ip->dev->dev_addr[i]);
 		if (i < 7)
 			printk(":");
 	}
 	printk(".\n");
 }
 
+
 /*
  * Caller must hold the ioc3_lock ever for MII readers.  This is also
  * used to protect the transmitter side but it's low contention.
@@ -435,10 +543,10 @@
 
 	skb = ip->rx_skbs[rx_entry];
 	rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
-	w0 = rxb->w0;
+	w0 = be32_to_cpu(rxb->w0);
 
 	while (w0 & ERXBUF_V) {
-		err = rxb->err;				/* It's valid ...  */
+		err = be32_to_cpu(rxb->err);		/* It's valid ...  */
 		if (err & ERXBUF_GOODPKT) {
 			len = ((w0 >> ERXBUF_BYTECNT_SHIFT) & 0x7ff) - 4;
 			skb_trim(skb, len);
@@ -479,8 +587,8 @@
 			ip->stats.rx_frame_errors++;
 next:
 		ip->rx_skbs[n_entry] = new_skb;
-		rxr[n_entry] = (0xa5UL << 56) |
-		                ((unsigned long) rxb & TO_PHYS_MASK);
+		rxr[n_entry] = cpu_to_be32((0xa5UL << 56) |
+		                         ((unsigned long) rxb & TO_PHYS_MASK));
 		rxb->w0 = 0;				/* Clear valid flag */
 		n_entry = (n_entry + 1) & 511;		/* Update erpir */
 
@@ -488,7 +596,7 @@
 		rx_entry = (rx_entry + 1) & 511;
 		skb = ip->rx_skbs[rx_entry];
 		rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
-		w0 = rxb->w0;
+		w0 = be32_to_cpu(rxb->w0);
 	}
 	ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
 	ip->rx_pi = n_entry;
@@ -1190,8 +1298,8 @@
 			/* Because we reserve afterwards. */
 			skb_put(skb, (1664 + RX_OFFSET));
 			rxb = (struct ioc3_erxbuf *) skb->data;
-			rxr[i] = (0xa5UL << 56)
-				| ((unsigned long) rxb & TO_PHYS_MASK);
+			rxr[i] = cpu_to_be64((0xa5UL << 56) |
+			                ((unsigned long) rxb & TO_PHYS_MASK));
 			skb_reserve(skb, RX_OFFSET);
 		}
 		ip->rx_ci = 0;
@@ -1555,8 +1663,8 @@
 			memset(desc->data + len, 0, ETH_ZLEN - len);
 			len = ETH_ZLEN;
 		}
-		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_D0V;
-		desc->bufcnt = len;
+		desc->cmd    = cpu_to_be32(len | ETXD_INTWHENDONE | ETXD_D0V);
+		desc->bufcnt = cpu_to_be32(len);
 	} else if ((data ^ (data + len)) & 0x4000) {
 		unsigned long b2, s1, s2;
 
@@ -1564,16 +1672,20 @@
 		s1 = b2 - data;
 		s2 = data + len - b2;
 
-		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_B1V | ETXD_B2V;
-		desc->bufcnt = (s1 << ETXD_B1CNT_SHIFT) |
-		               (s2 << ETXD_B2CNT_SHIFT);
-		desc->p1     = (0xa5UL << 56) | (data & TO_PHYS_MASK);
-		desc->p2     = (0xa5UL << 56) | (data & TO_PHYS_MASK);
+		desc->cmd    = cpu_to_be32(len | ETXD_INTWHENDONE |
+		                           ETXD_B1V | ETXD_B2V);
+		desc->bufcnt = cpu_to_be32((s1 << ETXD_B1CNT_SHIFT)
+		                           | (s2 << ETXD_B2CNT_SHIFT));
+		desc->p1     = cpu_to_be64((0xa5UL << 56) |
+                                           (data & TO_PHYS_MASK));
+		desc->p2     = cpu_to_be64((0xa5UL << 56) |
+		                           (data & TO_PHYS_MASK));
 	} else {
 		/* Normal sized packet that doesn't cross a page boundary. */
-		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_B1V;
-		desc->bufcnt = len << ETXD_B1CNT_SHIFT;
-		desc->p1     = (0xa5UL << 56) | (data & TO_PHYS_MASK);
+		desc->cmd    = cpu_to_be32(len | ETXD_INTWHENDONE | ETXD_B1V);
+		desc->bufcnt = cpu_to_be32(len << ETXD_B1CNT_SHIFT);
+		desc->p1     = cpu_to_be64((0xa5UL << 56) |
+		                           (data & TO_PHYS_MASK));
 	}
 
 	BARRIER();
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/irda/irda-usb.c	Sun Apr 14 12:16:59 2002
@@ -45,6 +45,8 @@
  * Amongst the reasons :
  *	o uhci doesn't implement USB_ZERO_PACKET
  *	o uhci non-compliant use of urb->timeout
+ * The final fix for USB_ZERO_PACKET in uhci is likely to be in 2.4.19 and
+ * 2.5.8. With this fix, the driver will work properly. More on that later.
  *
  * Jean II
  */
@@ -243,10 +245,10 @@
 /*------------------------------------------------------------------*/
 /*
  * Send a command to change the speed of the dongle
+ * Need to be called with spinlock on.
  */
 static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
 {
-	unsigned long flags;
 	__u8 *frame;
 	struct urb *urb;
 	int ret;
@@ -261,8 +263,6 @@
 		return;
 	}
 
-	spin_lock_irqsave(&self->lock, flags);
-
 	/* Allocate the fake frame */
 	frame = self->speed_buff;
 
@@ -278,10 +278,10 @@
 	urb->transfer_flags = USB_QUEUE_BULK | USB_ASYNC_UNLINK;
 	urb->timeout = MSECS_TO_JIFFIES(100);
 
-	if ((ret = usb_submit_urb(urb, GFP_KERNEL))) {
+	/* Irq disabled -> GFP_ATOMIC */
+	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
 		WARNING(__FUNCTION__ "(), failed Speed URB\n");
 	}
-	spin_unlock_irqrestore(&self->lock, flags);
 }
 
 /*------------------------------------------------------------------*/
@@ -335,14 +335,20 @@
 	s16 xbofs;
 	int res, mtt;
 
-	/* Check if the device is still there */
+	netif_stop_queue(netdev);
+
+	/* Protect us from USB callbacks, net watchdog and else. */
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Check if the device is still there.
+	 * We need to check self->present under the spinlock because
+	 * of irda_usb_disconnect() is synchronous - Jean II */
 	if ((!self) || (!self->present)) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), Device is gone...\n");
+		spin_unlock_irqrestore(&self->lock, flags);
 		return 1;	/* Failed */
 	}
 
-	netif_stop_queue(netdev);
-
 	/* Check if we need to change the number of xbofs */
         xbofs = irda_get_next_xbofs(skb);
         if ((xbofs != self->xbofs) && (xbofs != -1)) {
@@ -366,16 +372,14 @@
 			 * Jean II */
 			irda_usb_change_speed_xbofs(self);
 			netdev->trans_start = jiffies;
-			dev_kfree_skb(skb);
 			/* Will netif_wake_queue() in callback */
-			return 0;
+			goto drop;
 		}
 	}
 
 	if (urb->status != 0) {
 		WARNING(__FUNCTION__ "(), URB still in use!\n");
-		dev_kfree_skb(skb);
-		return 0;
+		goto drop;
 	}
 
 	/* Make sure there is room for IrDA-USB header. The actual
@@ -386,13 +390,10 @@
 		IRDA_DEBUG(0, __FUNCTION__ "(), Insuficient skb headroom.\n");
 		if (skb_cow(skb, USB_IRDA_HEADER)) {
 			WARNING(__FUNCTION__ "(), failed skb_cow() !!!\n");
-			dev_kfree_skb(skb);
-			return 0;
+			goto drop;
 		}
 	}
 
-	spin_lock_irqsave(&self->lock, flags);
-
 	/* Change setting for next frame */
 	irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0);
 
@@ -457,8 +458,8 @@
 		}
 	}
 	
-	/* Ask USB to send the packet */
-	if ((res = usb_submit_urb(urb, GFP_KERNEL))) {
+	/* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */
+	if ((res = usb_submit_urb(urb, GFP_ATOMIC))) {
 		WARNING(__FUNCTION__ "(), failed Tx URB\n");
 		self->stats.tx_errors++;
 		/* Let USB recover : We will catch that in the watchdog */
@@ -473,6 +474,12 @@
 	spin_unlock_irqrestore(&self->lock, flags);
 	
 	return 0;
+
+drop:
+	/* Drop silently the skb and exit */
+	dev_kfree_skb(skb);
+	spin_unlock_irqrestore(&self->lock, flags);
+	return 0;
 }
 
 /*------------------------------------------------------------------*/
@@ -481,6 +488,7 @@
  */
 static void write_bulk_callback(struct urb *urb)
 {
+	unsigned long flags;
 	struct sk_buff *skb = urb->context;
 	struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context;
 	
@@ -511,11 +519,15 @@
 	}
 
 	/* urb is now available */
-	urb->status = 0;
+	//urb->status = 0; -> tested above
+
+	/* Make sure we read self->present properly */
+	spin_lock_irqsave(&self->lock, flags);
 
 	/* If the network is closed, stop everything */
 	if ((!self->netopen) || (!self->present)) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), Network is gone...\n");
+		spin_unlock_irqrestore(&self->lock, flags);
 		return;
 	}
 
@@ -527,6 +539,7 @@
 		/* Otherwise, allow the stack to send more packets */
 		netif_wake_queue(self->netdev);
 	}
+	spin_unlock_irqrestore(&self->lock, flags);
 }
 
 /*------------------------------------------------------------------*/
@@ -540,15 +553,20 @@
  */
 static void irda_usb_net_timeout(struct net_device *netdev)
 {
+	unsigned long flags;
 	struct irda_usb_cb *self = netdev->priv;
 	struct urb *urb;
 	int	done = 0;	/* If we have made any progress */
 
 	IRDA_DEBUG(0, __FUNCTION__ "(), Network layer thinks we timed out!\n");
 
+	/* Protect us from USB callbacks, net Tx and else. */
+	spin_lock_irqsave(&self->lock, flags);
+
 	if ((!self) || (!self->present)) {
 		WARNING(__FUNCTION__ "(), device not present!\n");
 		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&self->lock, flags);
 		return;
 	}
 
@@ -623,6 +641,7 @@
 			break;
 		}
 	}
+	spin_unlock_irqrestore(&self->lock, flags);
 
 	/* Maybe we need a reset */
 	/* Note : Some drivers seem to use a usb_set_interface() when they
@@ -736,8 +755,9 @@
 	 * irda_usb_net_close() -> free the skb - Jean II */
 	urb->status = 0;
 	urb->next = NULL;	/* Don't auto resubmit URBs */
-	
-	ret = usb_submit_urb(urb, GFP_KERNEL);
+
+	/* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		/* If this ever happen, we are in deep s***.
 		 * Basically, the Rx path will stop... */
@@ -1014,8 +1034,10 @@
 			urb->context = NULL;
 		}
 	}
-	/* Cancel Tx and speed URB */
+	/* Cancel Tx and speed URB - need to be synchronous to avoid races */
+	self->tx_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
 	usb_unlink_urb(self->tx_urb);
+	self->speed_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
 	usb_unlink_urb(self->speed_urb);
 
 	/* Stop and remove instance of IrLAP */
@@ -1034,6 +1056,7 @@
  */
 static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
+	unsigned long flags;
 	struct if_irda_req *irq = (struct if_irda_req *) rq;
 	struct irda_usb_cb *self;
 	int ret = 0;
@@ -1044,23 +1067,26 @@
 
 	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
 
-	/* Check if the device is still there */
-	if(!self->present)
-		return -EFAULT;
-
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		/* Set the desired speed */
-		self->new_speed = irq->ifr_baudrate;
-		irda_usb_change_speed_xbofs(self);
-		/* Note : will spinlock in above function */
+		/* Protect us from USB callbacks, net watchdog and else. */
+		spin_lock_irqsave(&self->lock, flags);
+		/* Check if the device is still there */
+		if(self->present) {
+			/* Set the desired speed */
+			self->new_speed = irq->ifr_baudrate;
+			irda_usb_change_speed_xbofs(self);
+		}
+		spin_unlock_irqrestore(&self->lock, flags);
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		irda_device_set_media_busy(self->netdev, TRUE);
+		/* Check if the IrDA stack is still there */
+		if(self->netopen)
+			irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
 		irq->ifr_receiving = irda_usb_is_receiving(self);
@@ -1410,8 +1436,7 @@
 		dev->descriptor.idProduct);
 
 	/* Try to cleanup all instance that have a pending disconnect
-	 * Instance will be in this state is the disconnect() occurs
-	 * before the net_close().
+	 * In theory, it can't happen any longer.
 	 * Jean II */
 	for (i = 0; i < NIRUSB; i++) {
 		struct irda_usb_cb *irda = &irda_instance[i];
@@ -1519,33 +1544,47 @@
 /*
  * The current irda-usb device is removed, the USB layer tell us
  * to shut it down...
+ * One of the constraints is that when we exit this function,
+ * we cannot use the usb_device no more. Gone. Destroyed. kfree().
+ * Most other subsystem allow you to destroy the instance at a time
+ * when it's convenient to you, to postpone it to a later date, but
+ * not the USB subsystem.
+ * So, we must make bloody sure that everything gets deactivated.
+ * Jean II
  */
 static void irda_usb_disconnect(struct usb_device *dev, void *ptr)
 {
+	unsigned long flags;
 	struct irda_usb_cb *self = (struct irda_usb_cb *) ptr;
 	int i;
 
 	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
-	/* Oups ! We are not there any more */
+	/* Make sure that the Tx path is not executing. - Jean II */
+	spin_lock_irqsave(&self->lock, flags);
+
+	/* Oups ! We are not there any more.
+	 * This will stop/desactivate the Tx path. - Jean II */
 	self->present = 0;
 
-	/* Hum... Check if networking is still active */
-	if (self->netopen) {
+	/* We need to have irq enabled to unlink the URBs. That's OK,
+	 * at this point the Tx path is gone - Jean II */
+	spin_unlock_irqrestore(&self->lock, flags);
+
+	/* Hum... Check if networking is still active (avoid races) */
+	if((self->netopen) || (self->irlap)) {
 		/* Accept no more transmissions */
 		/*netif_device_detach(self->netdev);*/
 		netif_stop_queue(self->netdev);
 		/* Stop all the receive URBs */
 		for (i = 0; i < IU_MAX_RX_URBS; i++)
 			usb_unlink_urb(self->rx_urb[i]);
-		/* Cancel Tx and speed URB */
+		/* Cancel Tx and speed URB.
+		 * Toggle flags to make sure it's synchronous. */
+		self->tx_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
 		usb_unlink_urb(self->tx_urb);
+		self->speed_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
 		usb_unlink_urb(self->speed_urb);
-
-		IRDA_DEBUG(0, __FUNCTION__ "(), postponing disconnect, network is still active...\n");
-		/* better not do anything just yet, usb_irda_cleanup()
-		 * will do whats needed */
-		return;
 	}
 
 	/* Cleanup the device stuff */
@@ -1556,7 +1595,7 @@
 	/* Clean up our urbs */
 	for (i = 0; i < IU_MAX_RX_URBS; i++)
 		usb_free_urb(self->rx_urb[i]);
-	/* Cancel Tx and speed URB */
+	/* Clean up Tx and speed URB */
 	usb_free_urb(self->tx_urb);
 	usb_free_urb(self->speed_urb);
 
@@ -1603,7 +1642,8 @@
 	struct irda_usb_cb *irda = NULL;
 	int	i;
 
-	/* Find zombie instances and kill them... */
+	/* Find zombie instances and kill them...
+	 * In theory, it can't happen any longer. Jean II */
 	for (i = 0; i < NIRUSB; i++) {
 		irda = &irda_instance[i];
 		/* If the Device is zombie */
@@ -1626,3 +1666,4 @@
 MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
 MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>");
 MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); 
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
--- a/drivers/net/irda/irtty.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/irda/irtty.c	Sun Apr 14 12:16:56 2002
@@ -713,8 +713,6 @@
 
 		self->tx_buff.data += actual;
 		self->tx_buff.len  -= actual;
-
-		self->stats.tx_packets++;		      
 	} else {		
 		/* 
 		 *  Now serial buffer is almost free & we can start 
@@ -722,6 +720,8 @@
 		 */
 		IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
 		
+		self->stats.tx_packets++;		      
+
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
 		if (self->new_speed) {
diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/irda/nsc-ircc.c	Sun Apr 14 12:16:54 2002
@@ -88,10 +88,14 @@
 
 /* These are the known NSC chips */
 static nsc_chip_t chips[] = {
+/*  Name, {cfg registers}, chip id index reg, chip id expected value, revision mask */
 	{ "PC87108", { 0x150, 0x398, 0xea }, 0x05, 0x10, 0xf0, 
 	  nsc_ircc_probe_108, nsc_ircc_init_108 },
 	{ "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, 
 	  nsc_ircc_probe_338, nsc_ircc_init_338 },
+	/* Contributed by Kevin Thayer - OmniBook 6100 */
+	{ "PC87338?", { 0x2e, 0x15c, 0x398 }, 0x08, 0x00, 0xf8, 
+	  nsc_ircc_probe_338, nsc_ircc_init_338 },
 	{ NULL }
 };
 
@@ -697,6 +701,9 @@
 	/* Read the Module ID */
 	switch_bank(iobase, BANK3);
 	version = inb(iobase+MID);
+
+	IRDA_DEBUG(2, __FUNCTION__  "() Driver %s Found chip version %02x\n",
+		   driver_name, version);
 
 	/* Should be 0x2? */
 	if (0x20 != (version & 0xf0)) {
diff -Nru a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
--- a/drivers/net/irda/sa1100_ir.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/irda/sa1100_ir.c	Sun Apr 14 12:16:57 2002
@@ -12,6 +12,12 @@
  *  Note that we don't have to worry about the SA1111's DMA bugs in here,
  *  so we use the straight forward pci_map_* functions with a null pointer.
  *  IMHO we should really be using our own machine specific set.
+ *
+ *  This driver takes one kernel command line parameter, sa1100ir=, with
+ *  the following options:
+ *	max_rate:baudrate	- set the maximum baud rate
+ *	power_leve:level	- set the transmitter power level
+ *	tx_lpm:0|1		- set transmit low power mode
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -38,11 +44,6 @@
 
 #include <asm/arch/assabet.h>
 
-#ifndef CONFIG_SA1100_H3600
-#define clr_h3600_egpio(x)	do { } while (0)
-#define set_h3600_egpio(x)	do { } while (0)
-#endif
-
 #ifndef GPIO_IRDA_FIR
 #define GPIO_IRDA_FIR		(0)
 #endif
@@ -52,7 +53,8 @@
 #endif
 
 static int power_level = 3;
-static int tx_lpm = 0;
+static int tx_lpm;
+static int max_rate = 4000000;
 
 /*
  * Our netdevice.  There is only ever one of these.
@@ -72,8 +74,8 @@
 	struct sk_buff		*rxskb;
 	dma_addr_t		txbuf_dma;
 	dma_addr_t		rxbuf_dma;
-	int			txdma;
-	int			rxdma;
+	dma_regs_t		*txdma;
+	dma_regs_t		*rxdma;
 
 	struct net_device_stats	stats;
 	struct irlap_cb		*irlap;
@@ -134,8 +136,8 @@
 	/*
 	 * Enable the DMA, receiver and receive interrupt.
 	 */
-	sa1100_dma_flush_all(si->rxdma);
-	sa1100_dma_queue_buffer(si->rxdma, NULL, si->rxbuf_dma, HPSIR_MAX_RXLEN);
+	sa1100_clear_dma(si->rxdma);
+	sa1100_start_dma(si->rxdma, si->rxbuf_dma, HPSIR_MAX_RXLEN);
 	Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_RXE;
 }
 
@@ -156,7 +158,7 @@
 		 * Stop the receive DMA.
 		 */
 		if (IS_FIR(si))
-			sa1100_dma_stop(si->rxdma);
+			sa1100_stop_dma(si->rxdma);
 
 		local_irq_save(flags);
 
@@ -174,8 +176,8 @@
 
 		if (machine_is_assabet())
 			ASSABET_BCR_clear(ASSABET_BCR_IRDA_FSEL);
-		if (machine_is_h3600())
-			clr_h3600_egpio(EGPIO_H3600_IR_FSEL);
+		if (machine_is_h3xxx())
+			clr_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
 		if (machine_is_yopy())
 			PPSR &= ~GPIO_IRDA_FIR;
 
@@ -199,8 +201,8 @@
 
 		if (machine_is_assabet())
 			ASSABET_BCR_set(ASSABET_BCR_IRDA_FSEL);
-		if (machine_is_h3600())
-			set_h3600_egpio(EGPIO_H3600_IR_FSEL);
+		if (machine_is_h3xxx())
+			set_h3600_egpio(IPAQ_EGPIO_IR_FSEL);
 		if (machine_is_yopy())
 			PPSR |= GPIO_IRDA_FIR;
 
@@ -246,10 +248,7 @@
 static inline int
 sa1100_irda_set_power_h3600(struct sa1100_irda *si, unsigned int state)
 {
-	if (state)
-		set_h3600_egpio(EGPIO_H3600_IR_ON);
-	else
-		clr_h3600_egpio(EGPIO_H3600_IR_ON);
+	assign_h3600_egpio( IPAQ_EGPIO_IR_ON, state );
 	return 0;
 }
 
@@ -283,7 +282,7 @@
 
 	if (machine_is_assabet())
 		ret = sa1100_irda_set_power_assabet(si, state);
-	if (machine_is_h3600())
+	if (machine_is_h3xxx())
 		ret = sa1100_irda_set_power_h3600(si, state);
 	if (machine_is_yopy())
 		ret = sa1100_irda_set_power_yopy(si, state);
@@ -350,8 +349,8 @@
 	/*
 	 * Stop all DMA activity.
 	 */
-	sa1100_dma_stop(si->rxdma);
-	sa1100_dma_stop(si->txdma);
+	sa1100_stop_dma(si->rxdma);
+	sa1100_stop_dma(si->txdma);
 
 	/* Disable the port. */
 	Ser2UTCR3 = 0;
@@ -552,8 +551,10 @@
 	/*
 	 * Get the current data position.
 	 */
-	sa1100_dma_get_current(si->rxdma, NULL, &dma_addr);
+	dma_addr = sa1100_get_dma_pos(si->rxdma);
 	len = dma_addr - si->rxbuf_dma;
+	if (len > HPSIR_MAX_RXLEN)
+		len = HPSIR_MAX_RXLEN;
 	pci_unmap_single(NULL, si->rxbuf_dma, len, PCI_DMA_FROMDEVICE);
 
 	do {
@@ -597,6 +598,7 @@
 		sa1100_irda_rx_alloc(si);
 
 		netif_rx(skb);
+		dev->last_rx = jiffies;
 	} else {
 		/*
 		 * Remap the buffer.
@@ -620,7 +622,7 @@
 	/*
 	 * Stop RX DMA
 	 */
-	sa1100_dma_stop(si->rxdma);
+	sa1100_stop_dma(si->rxdma);
 
 	/*
 	 * Framing error - we throw away the packet completely.
@@ -672,7 +674,7 @@
 /*
  * TX DMA completion handler.
  */
-static void sa1100_irda_txdma_irq(void *id, int len)
+static void sa1100_irda_txdma_irq(void *id)
 {
 	struct net_device *dev = id;
 	struct sa1100_irda *si = dev->priv;
@@ -714,9 +716,9 @@
 	 * Account and free the packet.
 	 */
 	if (skb) {
-		pci_unmap_single(NULL, si->txbuf_dma, len, PCI_DMA_TODEVICE);
+		pci_unmap_single(NULL, si->txbuf_dma, skb->len, PCI_DMA_TODEVICE);
 		si->stats.tx_packets ++;
-		si->stats.tx_bytes += len;
+		si->stats.tx_bytes += skb->len;
 		dev_kfree_skb_irq(skb);
 	}
 
@@ -727,11 +729,6 @@
 	netif_wake_queue(dev);
 }
 
-/*
- * Note that we will never build up a backlog of frames; the protocol is a
- * half duplex protocol which basically means we transmit a frame, we
- * receive a frame, we transmit the next frame etc.
- */
 static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sa1100_irda *si = dev->priv;
@@ -758,6 +755,8 @@
 	}
 
 	if (!IS_FIR(si)) {
+		netif_stop_queue(dev);
+
 		si->tx_buff.data = si->tx_buff.head;
 		si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data,
 						  si->tx_buff.truesize);
@@ -786,8 +785,7 @@
 		si->txbuf_dma = pci_map_single(NULL, skb->data,
 					 skb->len, PCI_DMA_TODEVICE);
 
-		sa1100_dma_queue_buffer(si->txdma, dev, si->txbuf_dma,
-					skb->len);
+		sa1100_start_dma(si->txdma, si->txbuf_dma, skb->len);
 
 		/*
 		 * If we have a mean turn-around time, impose the specified
@@ -868,11 +866,13 @@
 	if (err)
 		goto err_irq;
 
-	err = sa1100_request_dma(&si->rxdma, "IrDA receive", DMA_Ser2HSSPRd);
+	err = sa1100_request_dma(DMA_Ser2HSSPRd, "IrDA receive",
+				 NULL, NULL, &si->rxdma);
 	if (err)
 		goto err_rx_dma;
 
-	err = sa1100_request_dma(&si->txdma, "IrDA transmit", DMA_Ser2HSSPWr);
+	err = sa1100_request_dma(DMA_Ser2HSSPWr, "IrDA transmit",
+				 sa1100_irda_txdma_irq, dev, &si->txdma);
 	if (err)
 		goto err_tx_dma;
 
@@ -896,8 +896,6 @@
 	if (!si->irlap)
 		goto err_irlap;
 
-	sa1100_dma_set_callback(si->txdma, sa1100_irda_txdma_irq);
-
 	/*
 	 * Now enable the interrupt and start the queue
 	 */
@@ -1010,8 +1008,16 @@
 	 * We support original IRDA up to 115k2. (we don't currently
 	 * support 4Mbps).  Min Turn Time set to 1ms or greater.
 	 */
-	baudrate_mask = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	baudrate_mask |= IR_4000000 << 8;
+	baudrate_mask = IR_9600;
+
+	switch (max_rate) {
+	case 4000000:		baudrate_mask |= IR_4000000 << 8;
+	case 115200:		baudrate_mask |= IR_115200;
+	case 57600:		baudrate_mask |= IR_57600;
+	case 38400:		baudrate_mask |= IR_38400;
+	case 19200:		baudrate_mask |= IR_19200;
+	}
+		
 	si->qos.baud_rate.bits &= baudrate_mask;
 	si->qos.min_turn_time.bits = 7;
 
@@ -1148,6 +1154,33 @@
 	 */
 }
 
+static int __init sa1100ir_setup(char *line)
+{
+	char *opt;
+
+	if (!line)
+		return 0;
+
+	while ((opt = strsep(&line, ",")) != NULL) {
+		if (!strncmp(opt, "max_rate:", 9)) {
+			max_rate = simple_strtoul(opt + 9, NULL, 0);
+			continue;
+		}
+		if (!strncmp(opt, "power_level:", 12)) {
+			power_level = simple_strtoul(opt + 12, NULL, 0);
+			continue;
+		}
+		if (!strncmp(opt, "tx_lpm:", 7)) {
+			tx_lpm = simple_strtoul(opt + 7, NULL, 0);
+			continue;
+		}
+	}
+
+	return 1;
+}
+
+__setup("sa1100ir=", sa1100ir_setup);
+
 #ifdef MODULE
 module_init(sa1100_irda_init);
 module_exit(sa1100_irda_exit);
@@ -1160,4 +1193,6 @@
 MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)");
 MODULE_PARM(tx_lpm, "i");
 MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode");
+MODULE_PARM(max_rate, "i");
+MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)");
 EXPORT_NO_SYMBOLS;
diff -Nru a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
--- a/drivers/net/irda/w83977af_ir.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/irda/w83977af_ir.c	Sun Apr 14 12:16:57 2002
@@ -612,7 +612,7 @@
 	disable_dma(self->io.dma);
 	clear_dma_ff(self->io.dma);
 	set_dma_mode(self->io.dma, DMA_MODE_READ);
-	set_dma_addr(self->io.dma, virt_to_bus(self->tx_buff.data));
+	set_dma_addr(self->io.dma, isa_virt_to_bus(self->tx_buff.data));
 	set_dma_count(self->io.dma, self->tx_buff.len);
 #else
 	setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, 
@@ -770,7 +770,7 @@
 	disable_dma(self->io.dma);
 	clear_dma_ff(self->io.dma);
 	set_dma_mode(self->io.dma, DMA_MODE_READ);
-	set_dma_addr(self->io.dma, virt_to_bus(self->rx_buff.data));
+	set_dma_addr(self->io.dma, isa_virt_to_bus(self->rx_buff.data));
 	set_dma_count(self->io.dma, self->rx_buff.truesize);
 #else
 	setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, 
diff -Nru a/drivers/net/lance.c b/drivers/net/lance.c
--- a/drivers/net/lance.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/lance.c	Sun Apr 14 12:16:55 2002
@@ -383,7 +383,7 @@
 					return 0;
 				}
 			}
-			release_resource(r);
+			release_region(ioaddr, LANCE_TOTAL_SIZE);
 		}
 	}
 	return -ENODEV;
diff -Nru a/drivers/net/lne390.c b/drivers/net/lne390.c
--- a/drivers/net/lne390.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/lne390.c	Sun Apr 14 12:16:59 2002
@@ -247,9 +247,9 @@
 				LNE390_STOP_PG/4, dev->mem_start);
 	}
 
-	dev->mem_end = dev->rmem_end = dev->mem_start
+	dev->mem_end = ei_status.rmem_end = dev->mem_start
 		+ (LNE390_STOP_PG - LNE390_START_PG)*256;
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
 
 	/* The 8390 offset is zero for the LNE390 */
 	dev->base_addr = ioaddr;
@@ -334,12 +334,12 @@
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (LNE390_START_PG<<8);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* Packet wraps over end of ring buffer. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
 		isa_memcpy_fromio(skb->data, xfer_start, count);
diff -Nru a/drivers/net/ne3210.c b/drivers/net/ne3210.c
--- a/drivers/net/ne3210.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/ne3210.c	Sun Apr 14 12:16:58 2002
@@ -234,9 +234,9 @@
 				NE3210_STOP_PG/4, dev->mem_start);
 	}
 
-	dev->mem_end = dev->rmem_end = dev->mem_start
+	dev->mem_end = ei_status.rmem_end = dev->mem_start
 		+ (NE3210_STOP_PG - NE3210_START_PG)*256;
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
 
 	/* The 8390 offset is zero for the NE3210 */
 	dev->base_addr = ioaddr;
@@ -323,12 +323,12 @@
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (NE3210_START_PG<<8);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* Packet wraps over end of ring buffer. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
 		isa_memcpy_fromio(skb->data, xfer_start, count);
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/ns83820.c	Sun Apr 14 12:16:59 2002
@@ -797,23 +797,6 @@
 	}
 }
 
-/* I hate the network stack sometimes */
-#ifdef __i386__
-#define skb_mangle_for_davem(skb,len)	(skb)
-#else
-static inline struct sk_buff *skb_mangle_for_davem(struct sk_buff *skb, int len)
-{
-	tmp = __dev_alloc_skb(len+2, GFP_ATOMIC);
-	if (!tmp)
-		goto done;
-	tmp->dev = &dev->net_dev;
-	skb_reserve(tmp, 2);
-	memcpy(skb_put(tmp, len), skb->data, len);
-	kfree_skb(skb);
-	return tmp;
-}
-#endif
-
 static void FASTCALL(ns83820_rx_kick(struct ns83820 *dev));
 static void ns83820_rx_kick(struct ns83820 *dev)
 {
@@ -883,7 +866,6 @@
 		if (likely(CMDSTS_OK & cmdsts)) {
 			int len = cmdsts & 0xffff;
 			skb_put(skb, len);
-			skb = skb_mangle_for_davem(skb, len);
 			if (unlikely(!skb))
 				goto netdev_mangle_me_harder_failed;
 			if (cmdsts & CMDSTS_DEST_MULTI)
diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
--- a/drivers/net/pcmcia/pcnet_cs.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/pcmcia/pcnet_cs.c	Sun Apr 14 12:16:57 2002
@@ -1460,7 +1460,7 @@
 			       struct e8390_pkt_hdr *hdr,
 			       int ring_page)
 {
-    void *xfer_start = (void *)(dev->rmem_start + (ring_page << 8)
+    void *xfer_start = (void *)(ei_status.rmem_start + (ring_page << 8)
 				- (ei_status.rx_start_page << 8));
     
     copyin((void *)hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
@@ -1473,17 +1473,17 @@
 static void shmem_block_input(struct net_device *dev, int count,
 			      struct sk_buff *skb, int ring_offset)
 {
-    void *xfer_start = (void *)(dev->rmem_start + ring_offset
+    void *xfer_start = (void *)(ei_status.rmem_start + ring_offset
 				- (ei_status.rx_start_page << 8));
     char *buf = skb->data;
     
-    if (xfer_start + count > (void *)dev->rmem_end) {
+    if (xfer_start + count > (void *)ei_status.rmem_end) {
 	/* We must wrap the input move. */
-	int semi_count = (void*)dev->rmem_end - xfer_start;
+	int semi_count = (void*)ei_status.rmem_end - xfer_start;
 	copyin(buf, xfer_start, semi_count);
 	buf += semi_count;
 	ring_offset = ei_status.rx_start_page << 8;
-	xfer_start = (void *)dev->rmem_start;
+	xfer_start = (void *)ei_status.rmem_start;
 	count -= semi_count;
     }
     copyin(buf, xfer_start, count);
@@ -1548,8 +1548,8 @@
     }
     
     dev->mem_start = (u_long)info->base + offset;
-    dev->rmem_start = dev->mem_start + (TX_PAGES<<8);
-    dev->mem_end = dev->rmem_end = (u_long)info->base + req.Size;
+    ei_status.rmem_start = dev->mem_start + (TX_PAGES<<8);
+    dev->mem_end = ei_status.rmem_end = (u_long)info->base + req.Size;
 
     ei_status.tx_start_page = start_pg;
     ei_status.rx_start_page = start_pg + TX_PAGES;
diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
--- a/drivers/net/pcnet32.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/pcnet32.c	Sun Apr 14 12:16:57 2002
@@ -511,7 +511,6 @@
 		struct pci_dev *pdev)
 {
     struct pcnet32_private *lp;
-    struct resource *res;
     dma_addr_t lp_dma_addr;
     int i, media;
     int fdx, mii, fset, dxsuflo, ltint;
@@ -689,13 +688,12 @@
     }
 
     dev->base_addr = ioaddr;
-    res = request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname);
-    if (!res)
+    if (request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname) == NULL)
 	return -EBUSY;
     
     /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
     if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {
-	release_resource(res);
+	release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	return -ENOMEM;
     }
 
@@ -727,7 +725,7 @@
     if (!a) {
       printk(KERN_ERR PFX "No access methods\n");
       pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
-      release_resource(res);
+      release_region(ioaddr, PCNET32_TOTAL_SIZE);
       return -ENODEV;
     }
     lp->a = *a;
@@ -775,7 +773,7 @@
 	else {
 	    printk(", failed to detect IRQ line.\n");
 	    pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
-	    release_resource(res);
+	    release_region(ioaddr, PCNET32_TOTAL_SIZE);
 	    return -ENODEV;
 	}
     }
diff -Nru a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
--- a/drivers/net/ppp_async.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/ppp_async.c	Sun Apr 14 12:16:59 2002
@@ -17,7 +17,7 @@
  * PPP driver, written by Michael Callahan and Al Longyear, and
  * subsequently hacked by Paul Mackerras.
  *
- * ==FILEVERSION 20000227==
+ * ==FILEVERSION 20020125==
  */
 
 #include <linux/module.h>
@@ -33,7 +33,7 @@
 #include <linux/init.h>
 #include <asm/uaccess.h>
 
-#define PPP_VERSION	"2.4.1"
+#define PPP_VERSION	"2.4.2"
 
 #define OBUFSIZE	256
 
@@ -62,6 +62,8 @@
 	struct sk_buff	*rpkt;
 	int		lcp_fcs;
 
+	atomic_t	refcnt;
+	struct semaphore dead_sem;
 	struct ppp_channel chan;	/* interface to generic ppp layer */
 	unsigned char	obuf[OBUFSIZE];
 };
@@ -108,6 +110,35 @@
  */
 
 /*
+ * We have a potential race on dereferencing tty->disc_data,
+ * because the tty layer provides no locking at all - thus one
+ * cpu could be running ppp_asynctty_receive while another
+ * calls ppp_asynctty_close, which zeroes tty->disc_data and
+ * frees the memory that ppp_asynctty_receive is using.  The best
+ * way to fix this is to use a rwlock in the tty struct, but for now
+ * we use a single global rwlock for all ttys in ppp line discipline.
+ */
+static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+
+static struct asyncppp *ap_get(struct tty_struct *tty)
+{
+	struct asyncppp *ap;
+
+	read_lock(&disc_data_lock);
+	ap = tty->disc_data;
+	if (ap != NULL)
+		atomic_inc(&ap->refcnt);
+	read_unlock(&disc_data_lock);
+	return ap;
+}
+
+static void ap_put(struct asyncppp *ap)
+{
+	if (atomic_dec_and_test(&ap->refcnt))
+		up(&ap->dead_sem);
+}
+
+/*
  * Called when a tty is put into PPP line discipline.
  */
 static int
@@ -135,6 +166,9 @@
 	ap->olim = ap->obuf;
 	ap->lcp_fcs = -1;
 
+	atomic_set(&ap->refcnt, 1);
+	init_MUTEX_LOCKED(&ap->dead_sem);
+
 	ap->chan.private = ap;
 	ap->chan.ops = &async_ops;
 	ap->chan.mtu = PPP_MRU;
@@ -155,19 +189,34 @@
 
 /*
  * Called when the tty is put into another line discipline
- * or it hangs up.
- * We assume that while we are in this routine, the tty layer
- * won't call any of the other line discipline entries for the
- * same tty.
+ * or it hangs up.  We have to wait for any cpu currently
+ * executing in any of the other ppp_asynctty_* routines to
+ * finish before we can call ppp_unregister_channel and free
+ * the asyncppp struct.  This routine must be called from
+ * process context, not interrupt or softirq context.
  */
 static void
 ppp_asynctty_close(struct tty_struct *tty)
 {
-	struct asyncppp *ap = tty->disc_data;
+	struct asyncppp *ap;
 
+	write_lock(&disc_data_lock);
+	ap = tty->disc_data;
+	tty->disc_data = 0;
+	write_unlock(&disc_data_lock);
 	if (ap == 0)
 		return;
-	tty->disc_data = 0;
+
+	/*
+	 * We have now ensured that nobody can start using ap from now
+	 * on, but we have to wait for all existing users to finish.
+	 * Note that ppp_unregister_channel ensures that no calls to
+	 * our channel ops (i.e. ppp_async_send/ioctl) are in progress
+	 * by the time it returns.
+	 */
+	if (!atomic_dec_and_test(&ap->refcnt))
+		down(&ap->dead_sem);
+
 	ppp_unregister_channel(&ap->chan);
 	if (ap->rpkt != 0)
 		kfree_skb(ap->rpkt);
@@ -203,9 +252,11 @@
 ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
 		   unsigned int cmd, unsigned long arg)
 {
-	struct asyncppp *ap = tty->disc_data;
+	struct asyncppp *ap = ap_get(tty);
 	int err, val;
 
+	if (ap == 0)
+		return -ENXIO;
 	err = -EFAULT;
 	switch (cmd) {
 	case PPPIOCGCHAN:
@@ -251,6 +302,7 @@
 		err = -ENOIOCTLCMD;
 	}
 
+	ap_put(ap);
 	return err;
 }
 
@@ -271,13 +323,14 @@
 ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
 		  char *flags, int count)
 {
-	struct asyncppp *ap = tty->disc_data;
+	struct asyncppp *ap = ap_get(tty);
 
 	if (ap == 0)
 		return;
 	spin_lock_bh(&ap->recv_lock);
 	ppp_async_input(ap, buf, flags, count);
 	spin_unlock_bh(&ap->recv_lock);
+	ap_put(ap);
 	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
 	    && tty->driver.unthrottle)
 		tty->driver.unthrottle(tty);
@@ -286,13 +339,14 @@
 static void
 ppp_asynctty_wakeup(struct tty_struct *tty)
 {
-	struct asyncppp *ap = tty->disc_data;
+	struct asyncppp *ap = ap_get(tty);
 
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	if (ap == 0)
 		return;
 	if (ppp_async_push(ap))
 		ppp_output_wakeup(&ap->chan);
+	ap_put(ap);
 }
 
 
diff -Nru a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
--- a/drivers/net/ppp_deflate.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/ppp_deflate.c	Sun Apr 14 12:16:57 2002
@@ -35,16 +35,12 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 
 #include <linux/ppp_defs.h>
 #include <linux/ppp-comp.h>
 
 #include <linux/zlib.h>
 
-static spinlock_t comp_free_list_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(comp_free_list);
-
 /*
  * State for a Deflate (de)compressor.
  */
@@ -56,7 +52,6 @@
     int		debug;
     z_stream	strm;
     struct compstat stats;
-    struct list_head list;
 };
 
 #define DEFLATE_OVHD	2		/* Deflate overhead/packet */
@@ -81,27 +76,6 @@
 static void	z_decomp_reset __P((void *state));
 static void	z_comp_stats __P((void *state, struct compstat *stats));
 
-static void z_comp_delayedfree(void *arg)
-{
-	struct ppp_deflate_state *state;
-
-	spin_lock_bh(&comp_free_list_lock);
-	while(!list_empty(&comp_free_list)) {
-		state = list_entry(comp_free_list.next, struct ppp_deflate_state, list);
-		list_del(&state->list);
-		spin_unlock_bh(&comp_free_list_lock);
-		if (state->strm.workspace)
-			vfree(state->strm.workspace);
-		kfree(state);
-		spin_lock_bh(&comp_free_list_lock);
-	}
-	spin_unlock_bh(&comp_free_list_lock);
-}
-
-static struct tq_struct z_comp_task = {
-	routine: z_comp_delayedfree
-};
-
 static void
 z_comp_free(arg)
     void *arg;
@@ -110,12 +84,9 @@
 
 	if (state) {
 		zlib_deflateEnd(&state->strm);
-
-		spin_lock_bh(&comp_free_list_lock);
-		list_add(&state->list, &comp_free_list);
-		spin_unlock_bh(&comp_free_list_lock);
-
-		schedule_task(&z_comp_task);
+		if (state->strm.workspace)
+			vfree(state->strm.workspace);
+		kfree(state);
 		MOD_DEC_USE_COUNT;
 	}
 }
@@ -616,8 +587,6 @@
 {
 	ppp_unregister_compressor(&ppp_deflate);
 	ppp_unregister_compressor(&ppp_deflate_draft);
-	/* Ensure that any deflate state pending free is actually freed */
-	flush_scheduled_tasks();
 }
 
 module_init(deflate_init);
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/ppp_generic.c	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,7 @@
 /*
  * Generic PPP layer for Linux.
  *
- * Copyright 1999-2000 Paul Mackerras.
+ * Copyright 1999-2002 Paul Mackerras.
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -19,7 +19,7 @@
  * PPP driver, written by Michael Callahan and Al Longyear, and
  * subsequently hacked by Paul Mackerras.
  *
- * ==FILEVERSION 20000902==
+ * ==FILEVERSION 20020217==
  */
 
 #include <linux/config.h>
@@ -43,10 +43,12 @@
 #include <linux/tcp.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
+#include <linux/rwsem.h>
+#include <linux/stddef.h>
 #include <net/slhc_vj.h>
 #include <asm/atomic.h>
 
-#define PPP_VERSION	"2.4.1"
+#define PPP_VERSION	"2.4.2"
 
 /*
  * Network protocols we support.
@@ -75,11 +77,11 @@
 	wait_queue_head_t rwait;	/* for poll on reading /dev/ppp */
 	atomic_t	refcnt;		/* # refs (incl /dev/ppp attached) */
 	int		hdrlen;		/* space to leave for headers */
-	struct list_head list;		/* link in all_* list */
 	int		index;		/* interface unit / channel number */
+	int		dead;		/* unit/channel has been shut down */
 };
 
-#define PF_TO_X(pf, X)	((X *)((char *)(pf)-(unsigned long)(&((X *)0)->file)))
+#define PF_TO_X(pf, X)		((X *)((char *)(pf) - offsetof(X, file)))
 
 #define PF_TO_PPP(pf)		PF_TO_X(pf, struct ppp)
 #define PF_TO_CHANNEL(pf)	PF_TO_X(pf, struct channel)
@@ -93,26 +95,27 @@
  * It can have 0 or more ppp channels connected to it.
  */
 struct ppp {
-	struct ppp_file	file;		/* stuff for read/write/poll */
-	struct list_head channels;	/* list of attached channels */
-	int		n_channels;	/* how many channels are attached */
-	spinlock_t	rlock;		/* lock for receive side */
-	spinlock_t	wlock;		/* lock for transmit side */
-	int		mru;		/* max receive unit */
-	unsigned int	flags;		/* control bits */
-	unsigned int	xstate;		/* transmit state bits */
-	unsigned int	rstate;		/* receive state bits */
-	int		debug;		/* debug flags */
+	struct ppp_file	file;		/* stuff for read/write/poll 0 */
+	struct file	*owner;		/* file that owns this unit 48 */
+	struct list_head channels;	/* list of attached channels 4c */
+	int		n_channels;	/* how many channels are attached 54 */
+	spinlock_t	rlock;		/* lock for receive side 58 */
+	spinlock_t	wlock;		/* lock for transmit side 5c */
+	int		mru;		/* max receive unit 60 */
+	unsigned int	flags;		/* control bits 64 */
+	unsigned int	xstate;		/* transmit state bits 68 */
+	unsigned int	rstate;		/* receive state bits 6c */
+	int		debug;		/* debug flags 70 */
 	struct slcompress *vj;		/* state for VJ header compression */
-	enum NPmode	npmode[NUM_NP];	/* what to do with each net proto */
-	struct sk_buff	*xmit_pending;	/* a packet ready to go out */
-	struct compressor *xcomp;	/* transmit packet compressor */
-	void		*xc_state;	/* its internal state */
-	struct compressor *rcomp;	/* receive decompressor */
-	void		*rc_state;	/* its internal state */
-	unsigned long	last_xmit;	/* jiffies when last pkt sent */
-	unsigned long	last_recv;	/* jiffies when last pkt rcvd */
-	struct net_device *dev;		/* network interface device */
+	enum NPmode	npmode[NUM_NP];	/* what to do with each net proto 78 */
+	struct sk_buff	*xmit_pending;	/* a packet ready to go out 88 */
+	struct compressor *xcomp;	/* transmit packet compressor 8c */
+	void		*xc_state;	/* its internal state 90 */
+	struct compressor *rcomp;	/* receive decompressor 94 */
+	void		*rc_state;	/* its internal state 98 */
+	unsigned long	last_xmit;	/* jiffies when last pkt sent 9c */
+	unsigned long	last_recv;	/* jiffies when last pkt rcvd a0 */
+	struct net_device *dev;		/* network interface device a4 */
 #ifdef CONFIG_PPP_MULTILINK
 	int		nxchan;		/* next channel to send something on */
 	u32		nxseq;		/* next sequence number to send */
@@ -144,11 +147,13 @@
  */
 struct channel {
 	struct ppp_file	file;		/* stuff for read/write/poll */
+	struct list_head list;		/* link in all/new_channels list */
 	struct ppp_channel *chan;	/* public channel data structure */
+	struct rw_semaphore chan_sem;	/* protects `chan' during chan ioctl */
 	spinlock_t	downl;		/* protects `chan', file.xq dequeue */
 	struct ppp	*ppp;		/* ppp unit we're connected to */
 	struct list_head clist;		/* link in list of channels per unit */
-	rwlock_t	upl;		/* protects `ppp' and `ulist' */
+	rwlock_t	upl;		/* protects `ppp' */
 #ifdef CONFIG_PPP_MULTILINK
 	u8		avail;		/* flag used in multilink stuff */
 	u8		had_frag;	/* >= 1 fragments have been sent */
@@ -166,12 +171,35 @@
  */
 
 /*
- * all_ppp_lock protects the all_ppp_units.
- * It also ensures that finding a ppp unit in the all_ppp_units list
+ * A cardmap represents a mapping from unsigned integers to pointers,
+ * and provides a fast "find lowest unused number" operation.
+ * It uses a broad (32-way) tree with a bitmap at each level.
+ * It is designed to be space-efficient for small numbers of entries
+ * and time-efficient for large numbers of entries.
+ */
+#define CARDMAP_ORDER	5
+#define CARDMAP_WIDTH	(1U << CARDMAP_ORDER)
+#define CARDMAP_MASK	(CARDMAP_WIDTH - 1)
+
+struct cardmap {
+	int shift;
+	unsigned long inuse;
+	struct cardmap *parent;
+	void *ptr[CARDMAP_WIDTH];
+};
+static void *cardmap_get(struct cardmap *map, unsigned int nr);
+static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
+static unsigned int cardmap_find_first_free(struct cardmap *map);
+static void cardmap_destroy(struct cardmap **map);
+
+/*
+ * all_ppp_sem protects the all_ppp_units mapping.
+ * It also ensures that finding a ppp unit in the all_ppp_units map
  * and updating its file.refcnt field is atomic.
  */
-static spinlock_t all_ppp_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(all_ppp_units);
+static DECLARE_MUTEX(all_ppp_sem);
+static struct cardmap *all_ppp_units;
+static atomic_t ppp_unit_count = ATOMIC_INIT(0);
 
 /*
  * all_channels_lock protects all_channels and last_channel_index,
@@ -180,7 +208,9 @@
  */
 static spinlock_t all_channels_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(all_channels);
+static LIST_HEAD(new_channels);
 static int last_channel_index;
+static atomic_t channel_count = ATOMIC_INIT(0);
 
 /* Get the PPP protocol number from a skb */
 #define PPP_PROTO(skb)	(((skb)->data[0] << 8) + (skb)->data[1])
@@ -205,10 +235,6 @@
 #define seq_after(a, b)		((s32)((a) - (b)) > 0)
 
 /* Prototypes. */
-static ssize_t ppp_file_read(struct ppp_file *pf, struct file *file,
-			     char *buf, size_t count);
-static ssize_t ppp_file_write(struct ppp_file *pf, const char *buf,
-			      size_t count);
 static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
 				unsigned int cmd, unsigned long arg);
 static void ppp_xmit_process(struct ppp *ppp);
@@ -235,6 +261,7 @@
 static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
 static struct ppp *ppp_create_interface(int unit, int *retp);
 static void init_ppp_file(struct ppp_file *pf, int kind);
+static void ppp_shutdown_interface(struct ppp *ppp);
 static void ppp_destroy_interface(struct ppp *ppp);
 static struct ppp *ppp_find_unit(int unit);
 static struct channel *ppp_find_channel(int unit);
@@ -303,7 +330,6 @@
 #define ppp_unlock(ppp)		do { ppp_recv_unlock(ppp); \
 				     ppp_xmit_unlock(ppp); } while (0)
 
-
 /*
  * /dev/ppp device routines.
  * The /dev/ppp device is used by pppd to control the ppp unit.
@@ -323,10 +349,16 @@
 
 static int ppp_release(struct inode *inode, struct file *file)
 {
-	struct ppp_file *pf = (struct ppp_file *) file->private_data;
+	struct ppp_file *pf = file->private_data;
+	struct ppp *ppp;
 
 	if (pf != 0) {
 		file->private_data = 0;
+		if (pf->kind == INTERFACE) {
+			ppp = PF_TO_PPP(pf);
+			if (file == ppp->owner)
+				ppp_shutdown_interface(ppp);
+		}
 		if (atomic_dec_and_test(&pf->refcnt)) {
 			switch (pf->kind) {
 			case INTERFACE:
@@ -344,30 +376,21 @@
 static ssize_t ppp_read(struct file *file, char *buf,
 			size_t count, loff_t *ppos)
 {
-	struct ppp_file *pf = (struct ppp_file *) file->private_data;
-
-	return ppp_file_read(pf, file, buf, count);
-}
-
-static ssize_t ppp_file_read(struct ppp_file *pf, struct file *file,
-			     char *buf, size_t count)
-{
+	struct ppp_file *pf = file->private_data;
 	DECLARE_WAITQUEUE(wait, current);
 	ssize_t ret;
 	struct sk_buff *skb = 0;
 
-	ret = -ENXIO;
 	if (pf == 0)
-		goto out;		/* not currently attached */
-
+		return -ENXIO;
 	add_wait_queue(&pf->rwait, &wait);
-	current->state = TASK_INTERRUPTIBLE;
 	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		skb = skb_dequeue(&pf->rq);
 		if (skb)
 			break;
 		ret = 0;
-		if (pf->kind == CHANNEL && PF_TO_CHANNEL(pf)->chan == 0)
+		if (pf->dead)
 			break;
 		ret = -EAGAIN;
 		if (file->f_flags & O_NONBLOCK)
@@ -377,7 +400,7 @@
 			break;
 		schedule();
 	}
-	current->state = TASK_RUNNING;
+	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&pf->rwait, &wait);
 
 	if (skb == 0)
@@ -400,21 +423,12 @@
 static ssize_t ppp_write(struct file *file, const char *buf,
 			 size_t count, loff_t *ppos)
 {
-	struct ppp_file *pf = (struct ppp_file *) file->private_data;
-
-	return ppp_file_write(pf, buf, count);
-}
-
-static ssize_t ppp_file_write(struct ppp_file *pf, const char *buf,
-			      size_t count)
-{
+	struct ppp_file *pf = file->private_data;
 	struct sk_buff *skb;
 	ssize_t ret;
 
-	ret = -ENXIO;
 	if (pf == 0)
-		goto out;
-
+		return -ENXIO;
 	ret = -ENOMEM;
 	skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
 	if (skb == 0)
@@ -446,7 +460,7 @@
 /* No kernel lock - fine */
 static unsigned int ppp_poll(struct file *file, poll_table *wait)
 {
-	struct ppp_file *pf = (struct ppp_file *) file->private_data;
+	struct ppp_file *pf = file->private_data;
 	unsigned int mask;
 
 	if (pf == 0)
@@ -455,28 +469,52 @@
 	mask = POLLOUT | POLLWRNORM;
 	if (skb_peek(&pf->rq) != 0)
 		mask |= POLLIN | POLLRDNORM;
-	if (pf->kind == CHANNEL) {
-		struct channel *pch = PF_TO_CHANNEL(pf);
-		if (pch->chan == 0)
-			mask |= POLLHUP;
-	}
+	if (pf->dead)
+		mask |= POLLHUP;
 	return mask;
 }
 
 static int ppp_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	struct ppp_file *pf = (struct ppp_file *) file->private_data;
+	struct ppp_file *pf = file->private_data;
 	struct ppp *ppp;
 	int err = -EFAULT, val, val2, i;
 	struct ppp_idle idle;
 	struct npioctl npi;
-	int unit;
+	int unit, cflags;
 	struct slcompress *vj;
 
 	if (pf == 0)
 		return ppp_unattached_ioctl(pf, file, cmd, arg);
 
+	if (cmd == PPPIOCDETACH) {
+		/*
+		 * We have to be careful here... if the file descriptor
+		 * has been dup'd, we could have another process in the
+		 * middle of a poll using the same file *, so we had
+		 * better not free the interface data structures -
+		 * instead we fail the ioctl.  Even in this case, we
+		 * shut down the interface if we are the owner of it.
+		 * Actually, we should get rid of PPPIOCDETACH, userland
+		 * (i.e. pppd) could achieve the same effect by closing
+		 * this fd and reopening /dev/ppp.
+		 */
+		err = -EINVAL;
+		if (pf->kind == INTERFACE) {
+			ppp = PF_TO_PPP(pf);
+			if (file == ppp->owner)
+				ppp_shutdown_interface(ppp);
+		}
+		if (atomic_read(&file->f_count) <= 2) {
+			ppp_release(inode, file);
+			err = 0;
+		} else
+			printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%d\n",
+			       atomic_read(&file->f_count));
+		return err;
+	}
+
 	if (pf->kind == CHANNEL) {
 		struct channel *pch = PF_TO_CHANNEL(pf);
 		struct ppp_channel *chan;
@@ -492,20 +530,13 @@
 			err = ppp_disconnect_channel(pch);
 			break;
 
-		case PPPIOCDETACH:
-			file->private_data = 0;
-			if (atomic_dec_and_test(&pf->refcnt))
-				ppp_destroy_channel(pch);
-			err = 0;
-			break;
-
 		default:
-			spin_lock_bh(&pch->downl);
+			down_read(&pch->chan_sem);
 			chan = pch->chan;
 			err = -ENOTTY;
 			if (chan && chan->ops->ioctl)
 				err = chan->ops->ioctl(chan, cmd, arg);
-			spin_unlock_bh(&pch->downl);
+			up_read(&pch->chan_sem);
 		}
 		return err;
 	}
@@ -518,13 +549,6 @@
 
 	ppp = PF_TO_PPP(pf);
 	switch (cmd) {
-	case PPPIOCDETACH:
-		file->private_data = 0;
-		if (atomic_dec_and_test(&pf->refcnt))
-			ppp_destroy_interface(ppp);
-		err = 0;
-		break;
-
 	case PPPIOCSMRU:
 		if (get_user(val, (int *) arg))
 			break;
@@ -536,10 +560,11 @@
 		if (get_user(val, (int *) arg))
 			break;
 		ppp_lock(ppp);
-		if (ppp->flags & ~val & SC_CCP_OPEN)
-			ppp_ccp_closed(ppp);
+		cflags = ppp->flags & ~val;
 		ppp->flags = val & SC_FLAG_BITS;
 		ppp_unlock(ppp);
+		if (cflags & SC_CCP_OPEN)
+			ppp_ccp_closed(ppp);
 		err = 0;
 		break;
 
@@ -675,6 +700,7 @@
 	default:
 		err = -ENOTTY;
 	}
+
 	return err;
 }
 
@@ -694,6 +720,7 @@
 		if (ppp == 0)
 			break;
 		file->private_data = &ppp->file;
+		ppp->owner = file;
 		err = -EFAULT;
 		if (put_user(ppp->file.index, (int *) arg))
 			break;
@@ -704,31 +731,29 @@
 		/* Attach to an existing ppp unit */
 		if (get_user(unit, (int *) arg))
 			break;
-		spin_lock(&all_ppp_lock);
+		down(&all_ppp_sem);
+		err = -ENXIO;
 		ppp = ppp_find_unit(unit);
-		if (ppp != 0)
+		if (ppp != 0) {
 			atomic_inc(&ppp->file.refcnt);
-		spin_unlock(&all_ppp_lock);
-		err = -ENXIO;
-		if (ppp == 0)
-			break;
-		file->private_data = &ppp->file;
-		err = 0;
+			file->private_data = &ppp->file;
+			err = 0;
+		}
+		up(&all_ppp_sem);
 		break;
 
 	case PPPIOCATTCHAN:
 		if (get_user(unit, (int *) arg))
 			break;
 		spin_lock_bh(&all_channels_lock);
+		err = -ENXIO;
 		chan = ppp_find_channel(unit);
-		if (chan != 0)
+		if (chan != 0) {
 			atomic_inc(&chan->file.refcnt);
+			file->private_data = &chan->file;
+			err = 0;
+		}
 		spin_unlock_bh(&all_channels_lock);
-		err = -ENXIO;
-		if (chan == 0)
-			break;
-		file->private_data = &chan->file;
-		err = 0;
 		break;
 
 	default:
@@ -905,15 +930,16 @@
 	struct sk_buff *skb;
 
 	ppp_xmit_lock(ppp);
-	ppp_push(ppp);
-	while (ppp->xmit_pending == 0
-	       && (skb = skb_dequeue(&ppp->file.xq)) != 0)
-		ppp_send_frame(ppp, skb);
-	/* If there's no work left to do, tell the core net
-	   code that we can accept some more. */
-	if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0
-	    && ppp->dev != 0)
-		netif_wake_queue(ppp->dev);
+	if (ppp->dev != 0) {
+		ppp_push(ppp);
+		while (ppp->xmit_pending == 0
+		       && (skb = skb_dequeue(&ppp->file.xq)) != 0)
+			ppp_send_frame(ppp, skb);
+		/* If there's no work left to do, tell the core net
+		   code that we can accept some more. */
+		if (ppp->xmit_pending == 0 && skb_peek(&ppp->file.xq) == 0)
+			netif_wake_queue(ppp->dev);
+	}
 	ppp_xmit_unlock(ppp);
 }
 
@@ -1526,6 +1552,7 @@
 			   error indication. */
 			if (len == DECOMP_FATALERROR)
 				ppp->rstate |= SC_DC_FERROR;
+			kfree_skb(ns);
 			goto err;
 		}
 
@@ -1797,7 +1824,7 @@
 {
 	struct channel *pch;
 
-	pch = kmalloc(sizeof(struct channel), GFP_ATOMIC);
+	pch = kmalloc(sizeof(struct channel), GFP_KERNEL);
 	if (pch == 0)
 		return -ENOMEM;
 	memset(pch, 0, sizeof(struct channel));
@@ -1809,11 +1836,13 @@
 #ifdef CONFIG_PPP_MULTILINK
 	pch->lastseq = -1;
 #endif /* CONFIG_PPP_MULTILINK */
+	init_rwsem(&pch->chan_sem);
 	spin_lock_init(&pch->downl);
 	pch->upl = RW_LOCK_UNLOCKED;
 	spin_lock_bh(&all_channels_lock);
 	pch->file.index = ++last_channel_index;
-	list_add(&pch->file.list, &all_channels);
+	list_add(&pch->list, &new_channels);
+	atomic_inc(&channel_count);
 	spin_unlock_bh(&all_channels_lock);
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -1826,7 +1855,9 @@
 {
 	struct channel *pch = chan->ppp;
 
-	return pch->file.index;
+	if (pch != 0)
+		return pch->file.index;
+	return -1;
 }
 
 /*
@@ -1848,7 +1879,7 @@
 
 /*
  * Disconnect a channel from the generic layer.
- * This can be called from mainline or BH/softirq level.
+ * This must be called in process context.
  */
 void
 ppp_unregister_channel(struct ppp_channel *chan)
@@ -1863,14 +1894,17 @@
 	 * This ensures that we have returned from any calls into the
 	 * the channel's start_xmit or ioctl routine before we proceed.
 	 */
+	down_write(&pch->chan_sem);
 	spin_lock_bh(&pch->downl);
 	pch->chan = 0;
 	spin_unlock_bh(&pch->downl);
+	up_write(&pch->chan_sem);
 	ppp_disconnect_channel(pch);
-	wake_up_interruptible(&pch->file.rwait);
 	spin_lock_bh(&all_channels_lock);
-	list_del(&pch->file.list);
+	list_del(&pch->list);
 	spin_unlock_bh(&all_channels_lock);
+	pch->file.dead = 1;
+	wake_up_interruptible(&pch->file.rwait);
 	if (atomic_dec_and_test(&pch->file.refcnt))
 		ppp_destroy_channel(pch);
 	MOD_DEC_USE_COUNT;
@@ -1899,9 +1933,9 @@
 ppp_set_compress(struct ppp *ppp, unsigned long arg)
 {
 	int err;
-	struct compressor *cp;
+	struct compressor *cp, *ocomp;
 	struct ppp_option_data data;
-	void *state;
+	void *state, *ostate;
 	unsigned char ccp_option[CCP_MAX_OPTION_LENGTH];
 #ifdef CONFIG_KMOD
 	char modname[32];
@@ -1927,41 +1961,39 @@
 #endif /* CONFIG_KMOD */
 	if (cp == 0)
 		goto out;
+	/*
+	 * XXX race: the compressor module could get unloaded between
+	 * here and when we do the comp_alloc or decomp_alloc call below.
+	 */
 
 	err = -ENOBUFS;
 	if (data.transmit) {
-		ppp_xmit_lock(ppp);
-		ppp->xstate &= ~SC_COMP_RUN;
-		if (ppp->xc_state != 0) {
-			ppp->xcomp->comp_free(ppp->xc_state);
-			ppp->xc_state = 0;
-		}
-		ppp_xmit_unlock(ppp);
-
 		state = cp->comp_alloc(ccp_option, data.length);
 		if (state != 0) {
 			ppp_xmit_lock(ppp);
+			ppp->xstate &= ~SC_COMP_RUN;
+			ocomp = ppp->xcomp;
+			ostate = ppp->xc_state;
 			ppp->xcomp = cp;
 			ppp->xc_state = state;
 			ppp_xmit_unlock(ppp);
+			if (ostate != 0)
+				ocomp->comp_free(ostate);
 			err = 0;
 		}
 
 	} else {
-		ppp_recv_lock(ppp);
-		ppp->rstate &= ~SC_DECOMP_RUN;
-		if (ppp->rc_state != 0) {
-			ppp->rcomp->decomp_free(ppp->rc_state);
-			ppp->rc_state = 0;
-		}
-		ppp_recv_unlock(ppp);
-
 		state = cp->decomp_alloc(ccp_option, data.length);
 		if (state != 0) {
 			ppp_recv_lock(ppp);
+			ppp->rstate &= ~SC_DECOMP_RUN;
+			ocomp = ppp->rcomp;
+			ostate = ppp->rc_state;
 			ppp->rcomp = cp;
 			ppp->rc_state = state;
 			ppp_recv_unlock(ppp);
+			if (ostate != 0)
+				ocomp->decomp_free(ostate);
 			err = 0;
 		}
 	}
@@ -2059,19 +2091,25 @@
 static void
 ppp_ccp_closed(struct ppp *ppp)
 {
-	ppp->flags &= ~(SC_CCP_OPEN | SC_CCP_UP);
+	void *xstate, *rstate;
+	struct compressor *xcomp, *rcomp;
 
-	ppp->xstate &= ~SC_COMP_RUN;
-	if (ppp->xc_state) {
-		ppp->xcomp->comp_free(ppp->xc_state);
-		ppp->xc_state = 0;
-	}
+	ppp_lock(ppp);
+	ppp->flags &= ~(SC_CCP_OPEN | SC_CCP_UP);
+	ppp->xstate = 0;
+	xcomp = ppp->xcomp;
+	xstate = ppp->xc_state;
+	ppp->xc_state = 0;
+	ppp->rstate = 0;
+	rcomp = ppp->rcomp;
+	rstate = ppp->rc_state;
+	ppp->rc_state = 0;
+	ppp_unlock(ppp);
 
-	ppp->xstate &= ~SC_DECOMP_RUN;
-	if (ppp->rc_state) {
-		ppp->rcomp->decomp_free(ppp->rc_state);
-		ppp->rc_state = 0;
-	}
+	if (xstate)
+		xcomp->comp_free(xstate);
+	if (rstate)
+		rcomp->decomp_free(rstate);
 }
 
 /* List of compressors. */
@@ -2191,39 +2229,27 @@
 ppp_create_interface(int unit, int *retp)
 {
 	struct ppp *ppp;
-	struct net_device *dev;
-	struct list_head *list;
-	int last_unit = -1;
-	int ret = -EEXIST;
+	struct net_device *dev = NULL;
+	int ret = -ENOMEM;
 	int i;
 
-	spin_lock(&all_ppp_lock);
-	list = &all_ppp_units;
-	while ((list = list->next) != &all_ppp_units) {
-		ppp = list_entry(list, struct ppp, file.list);
-		if ((unit < 0 && ppp->file.index > last_unit + 1)
-		    || (unit >= 0 && unit < ppp->file.index))
-			break;
-		if (unit == ppp->file.index)
-			goto out;	/* unit already exists */
-		last_unit = ppp->file.index;
-	}
-	if (unit < 0)
-		unit = last_unit + 1;
-
-	/* Create a new ppp structure and link it before `list'. */
-	ret = -ENOMEM;
-	ppp = kmalloc(sizeof(struct ppp), GFP_ATOMIC);
+	ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL);
 	if (ppp == 0)
-		goto out;
+		goto err;
+	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	if (dev == 0)
+		goto err;
 	memset(ppp, 0, sizeof(struct ppp));
-	dev = kmalloc(sizeof(struct net_device), GFP_ATOMIC);
-	if (dev == 0) {
-		kfree(ppp);
-		goto out;
-	}
 	memset(dev, 0, sizeof(struct net_device));
 
+	ret = -EEXIST;
+	down(&all_ppp_sem);
+	if (unit < 0)
+		unit = cardmap_find_first_free(all_ppp_units);
+	else if (cardmap_get(all_ppp_units, unit) != NULL)
+		goto err_unlock;	/* unit already exists */
+
+	/* Initialize the new ppp unit */
 	ppp->file.index = unit;
 	ppp->mru = PPP_MRU;
 	init_ppp_file(&ppp->file, INTERFACE);
@@ -2248,19 +2274,26 @@
 	ret = register_netdevice(dev);
 	rtnl_unlock();
 	if (ret != 0) {
-		printk(KERN_ERR "PPP: couldn't register device (%d)\n", ret);
-		kfree(dev);
-		kfree(ppp);
-		goto out;
+		printk(KERN_ERR "PPP: couldn't register device %s (%d)\n",
+		       dev->name, ret);
+		goto err_unlock;
 	}
 
-	list_add(&ppp->file.list, list->prev);
- out:
-	spin_unlock(&all_ppp_lock);
-	*retp = ret;
-	if (ret != 0)
-		ppp = 0;
+	atomic_inc(&ppp_unit_count);
+	cardmap_set(&all_ppp_units, unit, ppp);
+	up(&all_ppp_sem);
+	*retp = 0;
 	return ppp;
+
+ err_unlock:
+	up(&all_ppp_sem);
+ err:
+	*retp = ret;
+	if (ppp)
+		kfree(ppp);
+	if (dev)
+		kfree(dev);
+	return NULL;
 }
 
 /*
@@ -2277,19 +2310,48 @@
 }
 
 /*
- * Free up all the resources used by a ppp interface unit.
+ * Take down a ppp interface unit - called when the owning file
+ * (the one that created the unit) is closed or detached.
  */
-static void ppp_destroy_interface(struct ppp *ppp)
+static void ppp_shutdown_interface(struct ppp *ppp)
 {
 	struct net_device *dev;
-	int n_channels ;
-
-	spin_lock(&all_ppp_lock);
-	list_del(&ppp->file.list);
 
-	/* Last fd open to this ppp unit is being closed or detached:
-	   mark the interface down, free the ppp unit */
+	down(&all_ppp_sem);
 	ppp_lock(ppp);
+	dev = ppp->dev;
+	ppp->dev = 0;
+	ppp_unlock(ppp);
+	if (dev) {
+		rtnl_lock();
+		dev_close(dev);
+		unregister_netdevice(dev);
+		rtnl_unlock();
+	}
+	cardmap_set(&all_ppp_units, ppp->file.index, NULL);
+	ppp->file.dead = 1;
+	ppp->owner = NULL;
+	wake_up_interruptible(&ppp->file.rwait);
+	up(&all_ppp_sem);
+}
+
+/*
+ * Free the memory used by a ppp unit.  This is only called once
+ * there are no channels connected to the unit and no file structs
+ * that reference the unit.
+ */
+static void ppp_destroy_interface(struct ppp *ppp)
+{
+	atomic_dec(&ppp_unit_count);
+
+	if (!ppp->file.dead || ppp->n_channels) {
+		/* "can't happen" */
+		printk(KERN_ERR "ppp: destroying ppp struct %p but dead=%d "
+		       "n_channels=%d !\n", ppp, ppp->file.dead,
+		       ppp->n_channels);
+		return;
+	}
+
 	ppp_ccp_closed(ppp);
 	if (ppp->vj) {
 		slhc_free(ppp->vj);
@@ -2310,52 +2372,27 @@
 		ppp->active_filter.filter = 0;
 	}
 #endif /* CONFIG_PPP_FILTER */
-	dev = ppp->dev;
-	ppp->dev = 0;
-	n_channels = ppp->n_channels ;
-	ppp_unlock(ppp);
-
-	if (dev) {
-		rtnl_lock();
-		dev_close(dev);
-		unregister_netdevice(dev);
-		rtnl_unlock();
-	}
-
-	/*
-	 * We can't acquire any new channels (since we have the
-	 * all_ppp_lock) so if n_channels is 0, we can free the
-	 * ppp structure.  Otherwise we leave it around until the
-	 * last channel disconnects from it.
-	 */
-	if (n_channels == 0) 
-		kfree(ppp);
 
-	spin_unlock(&all_ppp_lock);
+	kfree(ppp);
 }
 
 /*
  * Locate an existing ppp unit.
- * The caller should have locked the all_ppp_lock.
+ * The caller should have locked the all_ppp_sem.
  */
 static struct ppp *
 ppp_find_unit(int unit)
 {
-	struct ppp *ppp;
-	struct list_head *list;
-
-	list = &all_ppp_units;
-	while ((list = list->next) != &all_ppp_units) {
-		ppp = list_entry(list, struct ppp, file.list);
-		if (ppp->file.index == unit)
-			return ppp;
-	}
-	return 0;
+	return cardmap_get(all_ppp_units, unit);
 }
 
 /*
  * Locate an existing ppp channel.
  * The caller should have locked the all_channels_lock.
+ * First we look in the new_channels list, then in the
+ * all_channels list.  If found in the new_channels list,
+ * we move it to the all_channels list.  This is for speed
+ * when we have a lot of channels in use.
  */
 static struct channel *
 ppp_find_channel(int unit)
@@ -2363,9 +2400,18 @@
 	struct channel *pch;
 	struct list_head *list;
 
+	list = &new_channels;
+	while ((list = list->next) != &new_channels) {
+		pch = list_entry(list, struct channel, list);
+		if (pch->file.index == unit) {
+			list_del(&pch->list);
+			list_add(&pch->list, &all_channels);
+			return pch;
+		}
+	}
 	list = &all_channels;
 	while ((list = list->next) != &all_channels) {
-		pch = list_entry(list, struct channel, file.list);
+		pch = list_entry(list, struct channel, list);
 		if (pch->file.index == unit)
 			return pch;
 	}
@@ -2382,19 +2428,16 @@
 	int ret = -ENXIO;
 	int hdrlen;
 
-	spin_lock(&all_ppp_lock);
+	down(&all_ppp_sem);
 	ppp = ppp_find_unit(unit);
 	if (ppp == 0)
 		goto out;
 	write_lock_bh(&pch->upl);
 	ret = -EINVAL;
 	if (pch->ppp != 0)
-		goto outwl;
-	ppp_lock(ppp);
-	spin_lock_bh(&pch->downl);
-	if (pch->chan == 0)		/* need to check this?? */
-		goto outr;
+		goto outl;
 
+	ppp_lock(ppp);
 	if (pch->file.hdrlen > ppp->file.hdrlen)
 		ppp->file.hdrlen = pch->file.hdrlen;
 	hdrlen = pch->file.hdrlen + 2;	/* for protocol bytes */
@@ -2403,15 +2446,14 @@
 	list_add_tail(&pch->clist, &ppp->channels);
 	++ppp->n_channels;
 	pch->ppp = ppp;
+	atomic_inc(&ppp->file.refcnt);
+	ppp_unlock(ppp);
 	ret = 0;
 
- outr:
-	spin_unlock_bh(&pch->downl);
-	ppp_unlock(ppp);
- outwl:
+ outl:
 	write_unlock_bh(&pch->upl);
  out:
-	spin_unlock(&all_ppp_lock);
+	up(&all_ppp_sem);
 	return ret;
 }
 
@@ -2423,25 +2465,21 @@
 {
 	struct ppp *ppp;
 	int err = -EINVAL;
-	int dead;
 
 	write_lock_bh(&pch->upl);
 	ppp = pch->ppp;
+	pch->ppp = NULL;
+	write_unlock_bh(&pch->upl);
 	if (ppp != 0) {
 		/* remove it from the ppp unit's list */
-		pch->ppp = NULL;
 		ppp_lock(ppp);
 		list_del(&pch->clist);
 		--ppp->n_channels;
-		dead = ppp->dev == 0 && ppp->n_channels == 0;
 		ppp_unlock(ppp);
-		if (dead)
-			/* Last disconnect from a ppp unit
-			   that is already dead: free it. */
-			kfree(ppp);
+		if (atomic_dec_and_test(&ppp->file.refcnt))
+			ppp_destroy_interface(ppp);
 		err = 0;
 	}
-	write_unlock_bh(&pch->upl);
 	return err;
 }
 
@@ -2450,6 +2488,14 @@
  */
 static void ppp_destroy_channel(struct channel *pch)
 {
+	atomic_dec(&channel_count);
+
+	if (!pch->file.dead) {
+		/* "can't happen" */
+		printk(KERN_ERR "ppp: destroying undead channel %p !\n",
+		       pch);
+		return;
+	}
 	skb_queue_purge(&pch->file.xq);
 	skb_queue_purge(&pch->file.rq);
 	kfree(pch);
@@ -2458,12 +2504,123 @@
 static void __exit ppp_cleanup(void)
 {
 	/* should never happen */
-	if (!list_empty(&all_ppp_units) || !list_empty(&all_channels))
+	if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
 		printk(KERN_ERR "PPP: removing module but units remain!\n");
+	cardmap_destroy(&all_ppp_units);
 	if (devfs_unregister_chrdev(PPP_MAJOR, "ppp") != 0)
 		printk(KERN_ERR "PPP: failed to unregister PPP device\n");
 	devfs_unregister(devfs_handle);
 }
+
+/*
+ * Cardmap implementation.
+ */
+static void *cardmap_get(struct cardmap *map, unsigned int nr)
+{
+	struct cardmap *p;
+	int i;
+
+	for (p = map; p != NULL; ) {
+		if ((i = nr >> p->shift) >= CARDMAP_WIDTH)
+			return NULL;
+		if (p->shift == 0)
+			return p->ptr[i];
+		nr &= ~(CARDMAP_MASK << p->shift);
+		p = p->ptr[i];
+	}
+	return NULL;
+}
+
+static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
+{
+	struct cardmap *p;
+	int i;
+
+	p = *pmap;
+	if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) {
+		do {
+			/* need a new top level */
+			struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
+			memset(np, 0, sizeof(*np));
+			np->ptr[0] = p;
+			if (p != NULL) {
+				np->shift = p->shift + CARDMAP_ORDER;
+				p->parent = np;
+			} else
+				np->shift = 0;
+			p = np;
+		} while ((nr >> p->shift) >= CARDMAP_WIDTH);
+		*pmap = p;
+	}
+	while (p->shift > 0) {
+		i = (nr >> p->shift) & CARDMAP_MASK;
+		if (p->ptr[i] == NULL) {
+			struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
+			memset(np, 0, sizeof(*np));
+			np->shift = p->shift - CARDMAP_ORDER;
+			np->parent = p;
+			p->ptr[i] = np;
+		}
+		if (ptr == NULL)
+			clear_bit(i, &p->inuse);
+		p = p->ptr[i];
+	}
+	i = nr & CARDMAP_MASK;
+	p->ptr[i] = ptr;
+	if (ptr != NULL)
+		set_bit(i, &p->inuse);
+	else
+		clear_bit(i, &p->inuse);
+}
+
+static unsigned int cardmap_find_first_free(struct cardmap *map)
+{
+	struct cardmap *p;
+	unsigned int nr = 0;
+	int i;
+
+	if ((p = map) == NULL)
+		return 0;
+	for (;;) {
+		i = find_first_zero_bit(&p->inuse, CARDMAP_WIDTH);
+		if (i >= CARDMAP_WIDTH) {
+			if (p->parent == NULL)
+				return CARDMAP_WIDTH << p->shift;
+			p = p->parent;
+			i = (nr >> p->shift) & CARDMAP_MASK;
+			set_bit(i, &p->inuse);
+			continue;
+		}
+		nr = (nr & (~CARDMAP_MASK << p->shift)) | (i << p->shift);
+		if (p->shift == 0 || p->ptr[i] == NULL)
+			return nr;
+		p = p->ptr[i];
+	}
+}
+
+static void cardmap_destroy(struct cardmap **pmap)
+{
+	struct cardmap *p, *np;
+	int i;
+
+	for (p = *pmap; p != NULL; p = np) {
+		if (p->shift != 0) {
+			for (i = 0; i < CARDMAP_WIDTH; ++i)
+				if (p->ptr[i] != NULL)
+					break;
+			if (i < CARDMAP_WIDTH) {
+				np = p->ptr[i];
+				p->ptr[i] = NULL;
+				continue;
+			}
+		}
+		np = p->parent;
+		kfree(p);
+	}
+	*pmap = NULL;
+}
+
+/* Module/initialization stuff */
 
 module_init(ppp_init);
 module_exit(ppp_cleanup);
diff -Nru a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
--- a/drivers/net/ppp_synctty.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/ppp_synctty.c	Sun Apr 14 12:16:58 2002
@@ -25,11 +25,11 @@
  * the generic PPP layer to give it frames to send and to process
  * received frames.  It implements the PPP line discipline.
  *
- * Part of the code in this driver was inspired by the old sync-only
+ * Part of the code in this driver was inspired by the old async-only
  * PPP driver, written by Michael Callahan and Al Longyear, and
  * subsequently hacked by Paul Mackerras.
  *
- * ==FILEVERSION 20000322==
+ * ==FILEVERSION 20020125==
  */
 
 #include <linux/module.h>
@@ -41,10 +41,12 @@
 #include <linux/ppp_defs.h>
 #include <linux/if_ppp.h>
 #include <linux/ppp_channel.h>
+#include <linux/spinlock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
+#include <asm/semaphore.h>
 
-#define PPP_VERSION	"2.4.1"
+#define PPP_VERSION	"2.4.2"
 
 /* Structure for storing local state. */
 struct syncppp {
@@ -65,6 +67,8 @@
 
 	struct sk_buff	*rpkt;
 
+	atomic_t	refcnt;
+	struct semaphore dead_sem;
 	struct ppp_channel chan;	/* interface to generic ppp layer */
 };
 
@@ -161,7 +165,36 @@
  */
 
 /*
- * Called when a tty is put into line discipline.
+ * We have a potential race on dereferencing tty->disc_data,
+ * because the tty layer provides no locking at all - thus one
+ * cpu could be running ppp_synctty_receive while another
+ * calls ppp_synctty_close, which zeroes tty->disc_data and
+ * frees the memory that ppp_synctty_receive is using.  The best
+ * way to fix this is to use a rwlock in the tty struct, but for now
+ * we use a single global rwlock for all ttys in ppp line discipline.
+ */
+static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+
+static struct syncppp *sp_get(struct tty_struct *tty)
+{
+	struct syncppp *ap;
+
+	read_lock(&disc_data_lock);
+	ap = tty->disc_data;
+	if (ap != NULL)
+		atomic_inc(&ap->refcnt);
+	read_unlock(&disc_data_lock);
+	return ap;
+}
+
+static void sp_put(struct syncppp *ap)
+{
+	if (atomic_dec_and_test(&ap->refcnt))
+		up(&ap->dead_sem);
+}
+
+/*
+ * Called when a tty is put into sync-PPP line discipline.
  */
 static int
 ppp_sync_open(struct tty_struct *tty)
@@ -185,6 +218,9 @@
 	ap->xaccm[3] = 0x60000000U;
 	ap->raccm = ~0U;
 
+	atomic_set(&ap->refcnt, 1);
+	init_MUTEX_LOCKED(&ap->dead_sem);
+
 	ap->chan.private = ap;
 	ap->chan.ops = &sync_ops;
 	ap->chan.mtu = PPP_MRU;
@@ -206,16 +242,34 @@
 
 /*
  * Called when the tty is put into another line discipline
- * (or it hangs up).
+ * or it hangs up.  We have to wait for any cpu currently
+ * executing in any of the other ppp_synctty_* routines to
+ * finish before we can call ppp_unregister_channel and free
+ * the syncppp struct.  This routine must be called from
+ * process context, not interrupt or softirq context.
  */
 static void
 ppp_sync_close(struct tty_struct *tty)
 {
-	struct syncppp *ap = tty->disc_data;
+	struct syncppp *ap;
 
+	write_lock(&disc_data_lock);
+	ap = tty->disc_data;
+	tty->disc_data = 0;
+	write_unlock(&disc_data_lock);
 	if (ap == 0)
 		return;
-	tty->disc_data = 0;
+
+	/*
+	 * We have now ensured that nobody can start using ap from now
+	 * on, but we have to wait for all existing users to finish.
+	 * Note that ppp_unregister_channel ensures that no calls to
+	 * our channel ops (i.e. ppp_sync_send/ioctl) are in progress
+	 * by the time it returns.
+	 */
+	if (!atomic_dec_and_test(&ap->refcnt))
+		down(&ap->dead_sem);
+
 	ppp_unregister_channel(&ap->chan);
 	if (ap->rpkt != 0)
 		kfree_skb(ap->rpkt);
@@ -251,9 +305,11 @@
 ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
 		  unsigned int cmd, unsigned long arg)
 {
-	struct syncppp *ap = tty->disc_data;
+	struct syncppp *ap = sp_get(tty);
 	int err, val;
 
+	if (ap == 0)
+		return -ENXIO;
 	err = -EFAULT;
 	switch (cmd) {
 	case PPPIOCGCHAN:
@@ -299,6 +355,7 @@
 		err = -ENOIOCTLCMD;
 	}
 
+	sp_put(ap);
 	return err;
 }
 
@@ -319,13 +376,14 @@
 ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
 		  char *flags, int count)
 {
-	struct syncppp *ap = tty->disc_data;
+	struct syncppp *ap = sp_get(tty);
 
 	if (ap == 0)
 		return;
 	spin_lock_bh(&ap->recv_lock);
 	ppp_sync_input(ap, buf, flags, count);
 	spin_unlock_bh(&ap->recv_lock);
+	sp_put(ap);
 	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
 	    && tty->driver.unthrottle)
 		tty->driver.unthrottle(tty);
@@ -334,13 +392,14 @@
 static void
 ppp_sync_wakeup(struct tty_struct *tty)
 {
-	struct syncppp *ap = tty->disc_data;
+	struct syncppp *ap = sp_get(tty);
 
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	if (ap == 0)
 		return;
 	if (ppp_sync_push(ap))
 		ppp_output_wakeup(&ap->chan);
+	sp_put(ap);
 }
 
 
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/pppoe.c	Sun Apr 14 12:16:55 2002
@@ -5,7 +5,7 @@
  * PPPoE --- PPP over Ethernet (RFC 2516)
  *
  *
- * Version:    0.6.9
+ * Version:    0.6.10
  *
  * 220102 :	Fix module use count on failure in pppoe_create, pppox_sk -acme
  * 030700 :     Fixed connect logic to allow for disconnect.
@@ -32,6 +32,9 @@
  *		a memory leak.
  * 081001 :     Misc. cleanup (licence string, non-blocking, prevent
  *              reference of device on close).
+ * 121301 :     New ppp channels interface; cannot unregister a channel
+ *              from interrupts.  Thus, we mark the socket as a ZOMBIE
+ *              and do the unregistration later.
  *
  * Author:	Michal Ostrowski <mostrows@speakeasy.net>
  * Contributors:
@@ -87,11 +90,11 @@
 
 
 #if 0
-#define CHECKPTR(x,y) { if (!(x) && pppoe_debug &7 ){ printk(KERN_CRIT "PPPoE Invalid pointer : %s , %p\n",#x,(x)); error=-EINVAL; goto y; }}
-#define DEBUG(s,args...) if( pppoe_debug & (s) ) printk(KERN_CRIT args );
+#define CHECKPTR(x,y) do { if (!(x) && pppoe_debug &7 ){ printk(KERN_CRIT "PPPoE Invalid pointer : %s , %p\n",#x,(x)); error=-EINVAL; goto y; }} while (0)
+#define DEBUG(s,args...) do { if( pppoe_debug & (s) ) printk(KERN_CRIT args ); } while (0)
 #else
-#define CHECKPTR(x,y) do {} while (0);
-#define DEBUG(s,args...) do { } while (0);
+#define CHECKPTR(x,y) do { } while (0)
+#define DEBUG(s,args...) do { } while (0)
 #endif
 
 
@@ -275,10 +278,10 @@
 
 				lock_sock(sk);
 
-				if (sk->state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+				if (sk->state & (PPPOX_CONNECTED|PPPOX_BOUND)){
 					pppox_unbind_sock(sk);
 					dev_put(dev);
-					sk->state = PPPOX_DEAD;
+					sk->state = PPPOX_ZOMBIE;
 					sk->state_change(sk);
 				}
 
@@ -441,8 +444,10 @@
 		 * one socket family type, we cannot (easily) distinguish
 		 * what kind of SKB it is during backlog rcv.
 		 */
-		if (sk->lock.users == 0)
+		if (sk->lock.users == 0) {
+			sk->state = PPPOX_ZOMBIE;
 			pppox_unbind_sock(sk);
+		}
 
 		bh_unlock_sock(sk);
 		sock_put(sk);
@@ -719,7 +724,7 @@
 		struct pppox_opt *relay_po;
 
 		err = -EBUSY;
-		if (sk->state & PPPOX_BOUND)
+		if (sk->state & (PPPOX_BOUND|PPPOX_ZOMBIE|PPPOX_DEAD))
 			break;
 
 		err = -ENOTCONN;
diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c
--- a/drivers/net/rrunner.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/rrunner.c	Sun Apr 14 12:16:56 2002
@@ -271,6 +271,7 @@
 #if LINUX_VERSION_CODE > 0x20118
 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
 MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
+MODULE_LICENSE("GPL");
 #endif
 
 int init_module(void)
diff -Nru a/drivers/net/sb1000.c b/drivers/net/sb1000.c
--- a/drivers/net/sb1000.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/sb1000.c	Sun Apr 14 12:16:55 2002
@@ -196,7 +196,7 @@
 		/* check I/O base and IRQ */
 		if (dev->base_addr != 0 && dev->base_addr != ioaddr[0])
 			continue;
-		if (dev->rmem_end != 0 && dev->rmem_end != ioaddr[1])
+		if (dev->mem_start != 0 && dev->mem_start != ioaddr[1])
 			continue;
 		if (dev->irq != 0 && dev->irq != irq)
 			continue;
@@ -212,14 +212,14 @@
 		}
 		 
 		dev->base_addr = ioaddr[0];
-		/* rmem_end holds the second I/O address - fv */
-		dev->rmem_end = ioaddr[1];
+		/* mem_start holds the second I/O address */
+		dev->mem_start = ioaddr[1];
 		dev->irq = irq;
 
 		if (sb1000_debug > 0)
 			printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), "
 				"S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
-				dev->rmem_end, serial_number, dev->irq);
+				dev->mem_start, serial_number, dev->irq);
 
 		dev = init_etherdev(dev, 0);
 		if (!dev)
@@ -405,7 +405,7 @@
 	}
 	timeout = jiffies + Sb1000TimeOutJiffies;
 	while (!(inb(ioaddr[1] + 6) & 0x40)) {
-		if (jiffies >= timeout) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk(KERN_WARNING "%s: sb1000_wait_for_ready timeout\n",
 				name);
 			return -ETIME;
@@ -423,7 +423,7 @@
 
 	timeout = jiffies + Sb1000TimeOutJiffies;
 	while (inb(ioaddr[1] + 6) & 0x80) {
-		if (jiffies >= timeout) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n",
 				name);
 			return -ETIME;
@@ -431,7 +431,7 @@
 	}
 	timeout = jiffies + Sb1000TimeOutJiffies;
 	while (inb(ioaddr[1] + 6) & 0x40) {
-		if (jiffies >= timeout) {
+		if (time_after_eq(jiffies, timeout)) {
 			printk(KERN_WARNING "%s: sb1000_wait_for_ready_clear timeout\n",
 				name);
 			return -ETIME;
@@ -935,8 +935,8 @@
 	const int ErrorDpcCounterInitialize = 200;
 
 	ioaddr[0] = dev->base_addr;
-	/* rmem_end holds the second I/O address - fv */
-	ioaddr[1] = dev->rmem_end;
+	/* mem_start holds the second I/O address */
+	ioaddr[1] = dev->mem_start;
 	name = dev->name;
 
 	sb1000_wait_for_ready_clear(ioaddr, name);
@@ -961,8 +961,8 @@
 	const unsigned short FirmwareVersion[] = {0x01, 0x01};
 
 	ioaddr[0] = dev->base_addr;
-	/* rmem_end holds the second I/O address - fv */
-	ioaddr[1] = dev->rmem_end;
+	/* mem_start holds the second I/O address */
+	ioaddr[1] = dev->mem_start;
 	name = dev->name;
 
 	/* initialize sb1000 */
@@ -1029,8 +1029,8 @@
 		return -ENODEV;
 
 	ioaddr[0] = dev->base_addr;
-	/* rmem_end holds the second I/O address - fv */
-	ioaddr[1] = dev->rmem_end;
+	/* mem_start holds the second I/O address */
+	ioaddr[1] = dev->mem_start;
 	name = dev->name;
 
 	switch (cmd) {
@@ -1130,8 +1130,8 @@
 	}
 
 	ioaddr[0] = dev->base_addr;
-	/* rmem_end holds the second I/O address - fv */
-	ioaddr[1] = dev->rmem_end;
+	/* mem_start holds the second I/O address */
+	ioaddr[1] = dev->mem_start;
 	name = dev->name;
 
 	/* is it a good interrupt? */
@@ -1189,8 +1189,8 @@
 	netif_stop_queue(dev);
 	
 	ioaddr[0] = dev->base_addr;
-	/* rmem_end holds the second I/O address - fv */
-	ioaddr[1] = dev->rmem_end;
+	/* mem_start holds the second I/O address */
+	ioaddr[1] = dev->mem_start;
 
 	free_irq(dev->irq, dev);
 	/* If we don't do this, we can't re-insmod it later. */
@@ -1234,8 +1234,8 @@
 	}
 	dev_sb1000.init = sb1000_probe;
 	dev_sb1000.base_addr = io[0];
-	/* rmem_end holds the second I/O address - fv */
-	dev_sb1000.rmem_end = io[1];
+	/* mem_start holds the second I/O address */
+	dev_sb1000.mem_start = io[1];
 	dev_sb1000.irq = irq;
 	if (register_netdev(&dev_sb1000) != 0) {
 		printk(KERN_ERR "sb1000: failed to register device (io: %03x,%03x   "
@@ -1249,7 +1249,7 @@
 {
 	unregister_netdev(&dev_sb1000);
 	release_region(dev_sb1000.base_addr, 16);
-	release_region(dev_sb1000.rmem_end, 16);
+	release_region(dev_sb1000.mem_start, 16);
 	kfree(dev_sb1000.priv);
 	dev_sb1000.priv = NULL;
 }
diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/sb1250-mac.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,2673 @@
+/*
+ * Copyright (C) 2001 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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+  This driver is designed for the Broadcom BCM12500 SOC chip's built-in
+  Ethernet controllers.
+  
+  The author may be reached as mpl@broadcom.com
+*/
+
+
+/* A few user-configurable values.
+   These may be modified when a driver module is loaded. */
+
+static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
+
+/* Used to pass the media type, etc.
+   Both 'options[]' and 'full_duplex[]' should exist for driver
+   interoperability.
+   The media type is usually passed in 'options[]'.
+*/
+
+#define MAX_UNITS 3		/* More are supported, limit only on options */
+#ifdef MODULE
+static int options[MAX_UNITS] = {-1, -1, -1};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1};
+#endif
+
+
+/* Operational parameters that usually are not changed. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+
+#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error  You must compile this driver with "-O".
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/64bit.h>
+
+/* This is only here until the firmware is ready.  In that case,
+   the firmware leaves the ethernet address in the register for us. */
+#ifdef CONFIG_SWARM_STANDALONE
+#define SBMAC_ETH0_HWADDR "40:00:00:00:01:00"
+#define SBMAC_ETH1_HWADDR "40:00:00:00:01:01"
+#define SBMAC_ETH2_HWADDR "40:00:00:00:01:02"
+#endif
+
+
+/* These identify the driver base version and may not be removed. */
+#if 0
+static char version1[] __devinitdata =
+"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg (mpl@broadcom.com)\n";
+#endif
+
+
+
+MODULE_AUTHOR("Mitch Lichtenberg (mpl@broadcom.com)");
+MODULE_DESCRIPTION("Broadcom BCM12500 SOC GB Ethernet driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+
+
+#include <asm/sibyte/sb1250_defs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_mac.h>
+#include <asm/sibyte/sb1250_dma.h>
+#include <asm/sibyte/sb1250_int.h>
+
+
+/**********************************************************************
+ *  Simple types
+ ********************************************************************* */
+
+
+typedef unsigned long sbmac_port_t;
+typedef uint64_t sbmac_physaddr_t;
+typedef uint64_t sbmac_enetaddr_t;
+
+typedef enum { sbmac_speed_auto, sbmac_speed_10,
+	       sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
+
+typedef enum { sbmac_duplex_auto, sbmac_duplex_half,
+	       sbmac_duplex_full } sbmac_duplex_t;
+
+typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame,
+	       sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t;
+
+typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on, 
+	       sbmac_state_broken } sbmac_state_t;
+
+
+/**********************************************************************
+ *  Macros
+ ********************************************************************* */
+
+
+#define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \
+			  (d)->sbdma_dscrtable : (d)->f+1)
+
+
+#define CACHELINESIZE 32
+#define NUMCACHEBLKS(x) (((x)+CACHELINESIZE-1)/CACHELINESIZE)
+#define KMALLOC(x) kmalloc((x),GFP_KERNEL)
+#define KFREE(x) kfree(x)
+#define KVTOPHYS(x) virt_to_bus((void *)(x))
+
+ 
+#define SBMAC_READCSR(t)    (in64((unsigned long)(t)))
+#define SBMAC_WRITECSR(t,v) (out64(v, (unsigned long)(t)))
+
+#define PKSEG1(x) ((sbmac_port_t) KSEG1ADDR(x))
+
+#define SBMAC_MAX_TXDESCR	32
+#define SBMAC_MAX_RXDESCR	32
+
+#define ETHER_ALIGN	2
+#define ETHER_ADDR_LEN	6
+#define ENET_PACKET_SIZE	1518
+
+/**********************************************************************
+ *  DMA Descriptor structure
+ ********************************************************************* */
+
+typedef struct sbdmadscr_s {
+	uint64_t  dscr_a;
+	uint64_t  dscr_b;
+} sbdmadscr_t;
+
+typedef unsigned long paddr_t;
+typedef unsigned long vaddr_t;
+
+/**********************************************************************
+ *  DMA Controller structure
+ ********************************************************************* */
+
+typedef struct sbmacdma_s {
+	
+	/* 
+	 * This stuff is used to identify the channel and the registers
+	 * associated with it.
+	 */
+	
+	struct sbmac_softc *sbdma_eth;	        /* back pointer to associated MAC */
+	int              sbdma_channel;	/* channel number */
+	int		     sbdma_txdir;       /* direction (1=transmit) */
+	int		     sbdma_maxdescr;	/* total # of descriptors in ring */
+	sbmac_port_t     sbdma_config0;	/* DMA config register 0 */
+	sbmac_port_t     sbdma_config1;	/* DMA config register 1 */
+	sbmac_port_t     sbdma_dscrbase;	/* Descriptor base address */
+	sbmac_port_t     sbdma_dscrcnt;     /* Descriptor count register */
+	sbmac_port_t     sbdma_curdscr;	/* current descriptor address */
+	
+	/*
+	 * This stuff is for maintenance of the ring
+	 */
+	
+	sbdmadscr_t     *sbdma_dscrtable;	/* base of descriptor table */
+	sbdmadscr_t     *sbdma_dscrtable_end; /* end of descriptor table */
+	
+	struct sk_buff **sbdma_ctxtable;    /* context table, one per descr */
+	
+	paddr_t          sbdma_dscrtable_phys; /* and also the phys addr */
+	sbdmadscr_t     *sbdma_addptr;	/* next dscr for sw to add */
+	sbdmadscr_t     *sbdma_remptr;	/* next dscr for sw to remove */
+	
+} sbmacdma_t;
+
+
+/**********************************************************************
+ *  Ethernet softc structure
+ ********************************************************************* */
+
+struct sbmac_softc {
+	
+	/*
+	 * Linux-specific things
+	 */
+	
+	struct net_device *sbm_dev;		/* pointer to linux device */
+	spinlock_t sbm_lock;		/* spin lock */
+	struct timer_list sbm_timer;     	/* for monitoring MII */
+	struct net_device_stats sbm_stats; 
+	int sbm_devflags;			/* current device flags */
+
+        int	     sbm_phy_oldbmsr;
+        int	     sbm_phy_oldanlpar;
+        int	     sbm_phy_oldk1stsr;
+        int          sbm_phy_oldlinkstat;
+	int sbm_buffersize;
+	
+	unsigned char sbm_phys[2];
+	
+	/*
+	 * Controller-specific things
+	 */
+	
+	sbmac_port_t     sbm_base;          /* MAC's base address */
+	sbmac_state_t    sbm_state;         /* current state */
+	
+	sbmac_port_t     sbm_macenable;	/* MAC Enable Register */
+	sbmac_port_t     sbm_maccfg;	/* MAC Configuration Register */
+	sbmac_port_t     sbm_fifocfg;	/* FIFO configuration register */
+	sbmac_port_t     sbm_framecfg;	/* Frame configuration register */
+	sbmac_port_t     sbm_rxfilter;	/* receive filter register */
+	sbmac_port_t     sbm_isr;		/* Interrupt status register */
+	sbmac_port_t     sbm_imr;		/* Interrupt mask register */
+	sbmac_port_t     sbm_mdio;		/* MDIO register */
+	
+	sbmac_speed_t    sbm_speed;		/* current speed */
+	sbmac_duplex_t   sbm_duplex;	/* current duplex */
+	sbmac_fc_t       sbm_fc;		/* current flow control setting */
+	
+	u_char           sbm_hwaddr[ETHER_ADDR_LEN];
+	
+	sbmacdma_t       sbm_txdma;		/* for now, only use channel 0 */
+	sbmacdma_t       sbm_rxdma;
+	
+};
+
+
+/**********************************************************************
+ *  Externs
+ ********************************************************************* */
+
+/**********************************************************************
+ *  Prototypes
+ ********************************************************************* */
+
+static void sbdma_initctx(sbmacdma_t *d,
+			  struct sbmac_softc *s,
+			  int chan,
+			  int txrx,
+			  int maxdescr);
+static void sbdma_channel_start(sbmacdma_t *d);
+static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *m);
+static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m);
+static void sbdma_emptyring(sbmacdma_t *d);
+static void sbdma_fillring(sbmacdma_t *d);
+static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d);
+static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d);
+static int sbmac_initctx(struct sbmac_softc *s);
+static void sbmac_channel_start(struct sbmac_softc *s);
+static void sbmac_channel_stop(struct sbmac_softc *s);
+static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t);
+static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff);
+/*static void sbmac_init_and_start(struct sbmac_softc *sc);*/
+static uint64_t sbmac_addr2reg(unsigned char *ptr);
+static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
+static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
+static void sbmac_setmulti(struct sbmac_softc *sc);
+static int sbmac_init(struct net_device *dev);
+static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed);
+static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc);
+
+static int sbmac_open(struct net_device *dev);
+static void sbmac_timer(unsigned long data);
+static void sbmac_tx_timeout (struct net_device *dev);
+static struct net_device_stats *sbmac_get_stats(struct net_device *dev);
+static void sbmac_set_rx_mode(struct net_device *dev);
+static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int sbmac_close(struct net_device *dev);
+static int sbmac_mii_poll(struct sbmac_softc *s,int noisy);
+
+static void sbmac_mii_sync(struct sbmac_softc *s);
+static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt);
+static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx);
+static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
+			    unsigned int regval);
+
+
+/**********************************************************************
+ *  Globals
+ ********************************************************************* */
+
+
+/**********************************************************************
+ *  MDIO constants
+ ********************************************************************* */
+
+#define	MII_COMMAND_START	0x01
+#define	MII_COMMAND_READ	0x02
+#define	MII_COMMAND_WRITE	0x01
+#define	MII_COMMAND_ACK		0x02
+
+#define BMCR_RESET     0x8000
+#define BMCR_LOOPBACK  0x4000
+#define BMCR_SPEED0    0x2000
+#define BMCR_ANENABLE  0x1000
+#define BMCR_POWERDOWN 0x0800
+#define BMCR_ISOLATE   0x0400
+#define BMCR_RESTARTAN 0x0200
+#define BMCR_DUPLEX    0x0100
+#define BMCR_COLTEST   0x0080
+#define BMCR_SPEED1    0x0040
+#define BMCR_SPEED1000 (BMCR_SPEED1|BMCR_SPEED0)
+#define BMCR_SPEED100  (BMCR_SPEED0)
+#define BMCR_SPEED10 	0
+
+#define BMSR_100BT4	0x8000
+#define BMSR_100BT_FDX	0x4000
+#define BMSR_100BT_HDX  0x2000
+#define BMSR_10BT_FDX   0x1000
+#define BMSR_10BT_HDX   0x0800
+#define BMSR_100BT2_FDX 0x0400
+#define BMSR_100BT2_HDX 0x0200
+#define BMSR_1000BT_XSR	0x0100
+#define BMSR_PRESUP	0x0040
+#define BMSR_ANCOMPLT	0x0020
+#define BMSR_REMFAULT	0x0010
+#define BMSR_AUTONEG	0x0008
+#define BMSR_LINKSTAT	0x0004
+#define BMSR_JABDETECT	0x0002
+#define BMSR_EXTCAPAB	0x0001
+
+#define PHYIDR1 	0x2000
+#define PHYIDR2		0x5C60
+
+#define ANAR_NP		0x8000
+#define ANAR_RF		0x2000
+#define ANAR_ASYPAUSE	0x0800
+#define ANAR_PAUSE	0x0400
+#define ANAR_T4		0x0200
+#define ANAR_TXFD	0x0100
+#define ANAR_TXHD	0x0080
+#define ANAR_10FD	0x0040
+#define ANAR_10HD	0x0020
+#define ANAR_PSB	0x0001
+
+#define ANLPAR_NP	0x8000
+#define ANLPAR_ACK	0x4000
+#define ANLPAR_RF	0x2000
+#define ANLPAR_ASYPAUSE	0x0800
+#define ANLPAR_PAUSE	0x0400
+#define ANLPAR_T4	0x0200
+#define ANLPAR_TXFD	0x0100
+#define ANLPAR_TXHD	0x0080
+#define ANLPAR_10FD	0x0040
+#define ANLPAR_10HD	0x0020
+#define ANLPAR_PSB	0x0001	/* 802.3 */
+
+#define ANER_PDF	0x0010
+#define ANER_LPNPABLE	0x0008
+#define ANER_NPABLE	0x0004
+#define ANER_PAGERX	0x0002
+#define ANER_LPANABLE	0x0001
+
+#define ANNPTR_NP	0x8000
+#define ANNPTR_MP	0x2000
+#define ANNPTR_ACK2	0x1000
+#define ANNPTR_TOGTX	0x0800
+#define ANNPTR_CODE	0x0008
+
+#define ANNPRR_NP	0x8000
+#define ANNPRR_MP	0x2000
+#define ANNPRR_ACK3	0x1000
+#define ANNPRR_TOGTX	0x0800
+#define ANNPRR_CODE	0x0008
+
+#define K1TCR_TESTMODE	0x0000
+#define K1TCR_MSMCE	0x1000
+#define K1TCR_MSCV	0x0800
+#define K1TCR_RPTR	0x0400
+#define K1TCR_1000BT_FDX 0x200
+#define K1TCR_1000BT_HDX 0x100
+
+#define K1STSR_MSMCFLT	0x8000
+#define K1STSR_MSCFGRES	0x4000
+#define K1STSR_LRSTAT	0x2000
+#define K1STSR_RRSTAT	0x1000
+#define K1STSR_LP1KFD	0x0800
+#define K1STSR_LP1KHD   0x0400
+#define K1STSR_LPASMDIR	0x0200
+
+#define K1SCR_1KX_FDX	0x8000
+#define K1SCR_1KX_HDX	0x4000
+#define K1SCR_1KT_FDX	0x2000
+#define K1SCR_1KT_HDX	0x1000
+
+#define STRAP_PHY1	0x0800
+#define STRAP_NCMODE	0x0400
+#define STRAP_MANMSCFG	0x0200
+#define STRAP_ANENABLE	0x0100
+#define STRAP_MSVAL	0x0080
+#define STRAP_1KHDXADV	0x0010
+#define STRAP_1KFDXADV	0x0008
+#define STRAP_100ADV	0x0004
+#define STRAP_SPEEDSEL	0x0000
+#define STRAP_SPEED100	0x0001
+
+#define PHYSUP_SPEED1000 0x10
+#define PHYSUP_SPEED100  0x08
+#define PHYSUP_SPEED10   0x00
+#define PHYSUP_LINKUP	 0x04
+#define PHYSUP_FDX       0x02
+
+#define	MII_BMCR	0x00 	/* Basic mode control register (rw) */
+#define	MII_BMSR	0x01	/* Basic mode status register (ro) */
+#define MII_K1STSR	0x0A	/* 1K Status Register (ro) */
+#define	MII_ANLPAR	0x05	/* Autonegotiation lnk partner abilities (rw) */
+
+
+#define M_MAC_MDIO_DIR_OUTPUT	0		/* for clarity */
+
+
+/**********************************************************************
+ *  SBMAC_MII_SYNC(s)
+ *  
+ *  Synchronize with the MII - send a pattern of bits to the MII
+ *  that will guarantee that it is ready to accept a command.
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbmac_mii_sync(struct sbmac_softc *s)
+{
+	int cnt;
+	uint64_t bits;
+	
+	bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
+	
+	SBMAC_WRITECSR(s->sbm_mdio,bits);
+	
+	for (cnt = 0; cnt < 32; cnt++) {
+		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC);
+		SBMAC_WRITECSR(s->sbm_mdio,bits);
+	}
+}
+
+/**********************************************************************
+ *  SBMAC_MII_SENDDATA(s,data,bitcnt)
+ *  
+ *  Send some bits to the MII.  The bits to be sent are right-
+ *  justified in the 'data' parameter.
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   data - data to send
+ *  	   bitcnt - number of bits to send
+ ********************************************************************* */
+
+static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt)
+{
+	int i;
+	uint64_t bits;
+	unsigned int curmask;
+	
+	bits = M_MAC_MDIO_DIR_OUTPUT;
+	SBMAC_WRITECSR(s->sbm_mdio,bits);
+	
+	curmask = 1 << (bitcnt - 1);
+	
+	for (i = 0; i < bitcnt; i++) {
+		if (data & curmask) bits |= M_MAC_MDIO_OUT;
+		else bits &= ~M_MAC_MDIO_OUT;
+		SBMAC_WRITECSR(s->sbm_mdio,bits);
+		SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC);
+		SBMAC_WRITECSR(s->sbm_mdio,bits);
+		curmask >>= 1;
+	}
+}
+
+
+
+/**********************************************************************
+ *  SBMAC_MII_READ(s,phyaddr,regidx)
+ *  
+ *  Read a PHY register.
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   phyaddr - PHY's address
+ *  	   regidx = index of register to read
+ *  	   
+ *  Return value:
+ *  	   value read, or 0 if an error occured.
+ ********************************************************************* */
+
+static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
+{
+	int idx;
+	int error;
+	int regval;
+	
+	/*
+	 * Synchronize ourselves so that the PHY knows the next
+	 * thing coming down is a command
+	 */
+	
+	sbmac_mii_sync(s);
+	
+	/*
+	 * Send the data to the PHY.  The sequence is
+	 * a "start" command (2 bits)
+	 * a "read" command (2 bits)
+	 * the PHY addr (5 bits)
+	 * the register index (5 bits)
+	 */
+	
+	sbmac_mii_senddata(s,MII_COMMAND_START, 2);
+	sbmac_mii_senddata(s,MII_COMMAND_READ, 2);
+	sbmac_mii_senddata(s,phyaddr, 5);
+	sbmac_mii_senddata(s,regidx, 5);
+	
+	/* 
+	 * Switch the port around without a clock transition.
+	 */
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT);
+	
+	/*
+	 * Send out a clock pulse to signal we want the status
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT);
+	
+	/* 
+	 * If an error occured, the PHY will signal '1' back
+	 */
+	error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN;
+	
+	/* 
+	 * Issue an 'idle' clock pulse, but keep the direction
+	 * the same.
+	 */
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT);
+	
+	regval = 0;
+	
+	for (idx = 0; idx < 16; idx++) {
+		regval <<= 1;
+		
+		if (error == 0) {
+			if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN) regval |= 1;
+		}
+		
+		SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
+		SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT);
+	}
+	
+	/* Switch back to output */
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT);
+	
+	if (error == 0) return regval;
+	return 0;
+}
+
+
+/**********************************************************************
+ *  SBMAC_MII_WRITE(s,phyaddr,regidx,regval)
+ *  
+ *  Write a value to a PHY register.
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   phyaddr - PHY to use
+ *  	   regidx - register within the PHY
+ *  	   regval - data to write to register
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
+			    unsigned int regval)
+{
+	
+	sbmac_mii_sync(s);
+	
+	sbmac_mii_senddata(s,MII_COMMAND_START,2);
+	sbmac_mii_senddata(s,MII_COMMAND_WRITE,2);
+	sbmac_mii_senddata(s,phyaddr, 5);
+	sbmac_mii_senddata(s,regidx, 5);
+	sbmac_mii_senddata(s,MII_COMMAND_ACK,2);
+	sbmac_mii_senddata(s,regval,16);
+	
+	SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT);
+}
+
+
+
+/**********************************************************************
+ *  SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
+ *  
+ *  Initialize a DMA channel context.  Since there are potentially
+ *  eight DMA channels per MAC, it's nice to do this in a standard
+ *  way.  
+ *  
+ *  Input parameters: 
+ *  	   d - sbmacdma_t structure (DMA channel context)
+ *  	   s - sbmac_softc structure (pointer to a MAC)
+ *  	   chan - channel number (0..1 right now)
+ *  	   txrx - Identifies DMA_TX or DMA_RX for channel direction
+ *      maxdescr - number of descriptors
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_initctx(sbmacdma_t *d,
+			  struct sbmac_softc *s,
+			  int chan,
+			  int txrx,
+			  int maxdescr)
+{
+	/* 
+	 * Save away interesting stuff in the structure 
+	 */
+	
+	d->sbdma_eth       = s;
+	d->sbdma_channel   = chan;
+	d->sbdma_txdir     = txrx;
+	
+	/* 
+	 * initialize register pointers 
+	 */
+	
+	d->sbdma_config0 = 
+		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
+	d->sbdma_config1 = 
+		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
+	d->sbdma_dscrbase = 
+		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE));
+	d->sbdma_dscrcnt = 
+		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT));
+	d->sbdma_curdscr = 	
+		PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR));
+	
+	/*
+	 * Allocate memory for the ring
+	 */
+	
+	d->sbdma_maxdescr = maxdescr;
+	
+	d->sbdma_dscrtable = (sbdmadscr_t *) 
+		KMALLOC(d->sbdma_maxdescr*sizeof(sbdmadscr_t));
+	
+	memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
+	
+	d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
+	
+	d->sbdma_dscrtable_phys = KVTOPHYS(d->sbdma_dscrtable);
+	
+	/*
+	 * And context table
+	 */
+	
+	d->sbdma_ctxtable = (struct sk_buff **) 
+		KMALLOC(d->sbdma_maxdescr*sizeof(struct sk_buff *));
+	
+	memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
+	
+}
+
+/**********************************************************************
+ *  SBDMA_CHANNEL_START(d)
+ *  
+ *  Initialize the hardware registers for a DMA channel.
+ *  
+ *  Input parameters: 
+ *  	   d - DMA channel to init (context must be previously init'd
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_channel_start(sbmacdma_t *d)
+{
+	/*
+	 * Turn on the DMA channel
+	 */
+	
+	SBMAC_WRITECSR(d->sbdma_config1,0);
+	
+	SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
+	
+	SBMAC_WRITECSR(d->sbdma_config0,
+		       V_DMA_RINGSZ(d->sbdma_maxdescr) |
+		       0);
+	
+	/*
+	 * Initialize ring pointers
+	 */
+	
+	d->sbdma_addptr = d->sbdma_dscrtable;
+	d->sbdma_remptr = d->sbdma_dscrtable;
+}
+
+
+static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
+{
+	unsigned long addr;
+	unsigned long newaddr;
+	
+	addr = (unsigned long) skb->data;
+	
+	newaddr = (addr + power2 - 1) & ~(power2 - 1);
+	
+	skb_reserve(skb,newaddr-addr+offset);
+}
+
+
+/**********************************************************************
+ *  SBDMA_ADD_RCVBUFFER(d,sb)
+ *  
+ *  Add a buffer to the specified DMA channel.   For receive channels,
+ *  this queues a buffer for inbound packets.
+ *  
+ *  Input parameters: 
+ *  	   d - DMA channel descriptor
+ * 	   sb - sk_buff to add, or NULL if we should allocate one
+ *  	   
+ *  Return value:
+ *  	   0 if buffer could not be added (ring is full)
+ *  	   1 if buffer added successfully
+ ********************************************************************* */
+
+
+static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
+{
+	sbdmadscr_t *dsc;
+	sbdmadscr_t *nextdsc;
+	struct sk_buff *sb_new = NULL;
+	int pktsize = ENET_PACKET_SIZE;
+	
+	/* get pointer to our current place in the ring */
+	
+	dsc = d->sbdma_addptr;
+	nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
+	
+	/*
+	 * figure out if the ring is full - if the next descriptor
+	 * is the same as the one that we're going to remove from
+	 * the ring, the ring is full
+	 */
+	
+	if (nextdsc == d->sbdma_remptr) {
+		return -ENOSPC;
+	}
+	
+	/* 
+	 * Allocate a sk_buff if we don't already have one.  
+	 * If we do have an sk_buff, reset it so that it's empty.
+	 *
+	 * Note: sk_buffs don't seem to be guaranteed to have any sort
+	 * of alignment when they are allocated.  Therefore, allocate enough
+	 * extra space to make sure that:
+	 *
+	 *    1. the data does not start in the middle of a cache line.
+	 *    2. The data does not end in the middle of a cache line
+	 * 	  3. The buffer can be aligned such that the IP addresses are 
+	 *       naturally aligned.
+	 *
+	 *  Remember, the SB1250's MAC writes whole cache lines at a time,
+	 *  without reading the old contents first.  So, if the sk_buff's
+	 *  data portion starts in the middle of a cache line, the SB1250
+	 *  DMA will trash the beginning (and ending) portions.
+	 */
+	
+	if (sb == NULL) {
+		sb_new = dev_alloc_skb(ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN);
+		if (sb_new == NULL) {
+			printk(KERN_INFO "%s: sk_buff allocation failed\n",
+			       d->sbdma_eth->sbm_dev->name);
+			return -ENOBUFS;
+		}
+		
+		sbdma_align_skb(sb_new,CACHELINESIZE,ETHER_ALIGN);
+		
+		/* mark skbuff owned by our device */
+		sb_new->dev = d->sbdma_eth->sbm_dev;
+	}
+	else {
+		sb_new = sb;
+		/* 
+		 * nothing special to reinit buffer, it's already aligned
+		 * and sb->tail already points to a good place.
+		 */
+	}
+	
+	/*
+	 * fill in the descriptor 
+	 */
+	
+	dsc->dscr_a = KVTOPHYS(sb_new->tail) |
+		V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
+		M_DMA_DSCRA_INTERRUPT;
+	
+	/* receiving: no options */
+	dsc->dscr_b = 0;
+	
+	/*
+	 * fill in the context 
+	 */
+	
+	d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
+	
+	/* 
+	 * point at next packet 
+	 */
+	
+	d->sbdma_addptr = nextdsc;
+	
+	/* 
+	 * Give the buffer to the DMA engine.
+	 */
+	
+	SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
+	
+	return 0;					/* we did it */
+}
+
+/**********************************************************************
+ *  SBDMA_ADD_TXBUFFER(d,sb)
+ *  
+ *  Add a transmit buffer to the specified DMA channel, causing a
+ *  transmit to start.
+ *  
+ *  Input parameters: 
+ *  	   d - DMA channel descriptor
+ * 	   sb - sk_buff to add
+ *  	   
+ *  Return value:
+ *  	   0 transmit queued successfully
+ *  	   otherwise error code
+ ********************************************************************* */
+
+
+static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
+{
+	sbdmadscr_t *dsc;
+	sbdmadscr_t *nextdsc;
+	uint64_t phys;
+	uint64_t ncb;
+	int length;
+	
+	/* get pointer to our current place in the ring */
+	
+	dsc = d->sbdma_addptr;
+	nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
+	
+	/*
+	 * figure out if the ring is full - if the next descriptor
+	 * is the same as the one that we're going to remove from
+	 * the ring, the ring is full
+	 */
+	
+	if (nextdsc == d->sbdma_remptr) {
+		return -ENOSPC;
+	}
+	
+	/*
+	 * Under Linux, it's not necessary to copy/coalesce buffers
+	 * like it is on NetBSD.  We think they're all contiguous,
+	 * but that may not be true for GBE.
+	 */
+	
+	length = sb->len;
+	
+	/*
+	 * fill in the descriptor.  Note that the number of cache
+	 * blocks in the descriptor is the number of blocks
+	 * *spanned*, so we need to add in the offset (if any)
+	 * while doing the calculation.
+	 */
+	
+	phys = KVTOPHYS(sb->data);
+	ncb = NUMCACHEBLKS(length+(phys & (CACHELINESIZE-1)));
+	
+	dsc->dscr_a = phys | 
+		V_DMA_DSCRA_A_SIZE(ncb) |
+		M_DMA_DSCRA_INTERRUPT |
+		M_DMA_ETHTX_SOP;
+	
+	/* transmitting: set outbound options and length */
+
+	dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
+		V_DMA_DSCRB_PKT_SIZE(length);
+	
+	/*
+	 * fill in the context 
+	 */
+	
+	d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
+	
+	/* 
+	 * point at next packet 
+	 */
+	
+	d->sbdma_addptr = nextdsc;
+	
+	/* 
+	 * Give the buffer to the DMA engine.
+	 */
+	
+	SBMAC_WRITECSR(d->sbdma_dscrcnt,1);
+	
+	return 0;					/* we did it */
+}
+
+
+
+
+/**********************************************************************
+ *  SBDMA_EMPTYRING(d)
+ *  
+ *  Free all allocated sk_buffs on the specified DMA channel;
+ *  
+ *  Input parameters: 
+ *  	   d  - DMA channel
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_emptyring(sbmacdma_t *d)
+{
+	int idx;
+	struct sk_buff *sb;
+	
+	for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
+		sb = d->sbdma_ctxtable[idx];
+		if (sb) {
+			dev_kfree_skb(sb);
+			d->sbdma_ctxtable[idx] = NULL;
+		}
+	}
+}
+
+
+/**********************************************************************
+ *  SBDMA_FILLRING(d)
+ *  
+ *  Fill the specified DMA channel (must be receive channel)
+ *  with sk_buffs
+ *  
+ *  Input parameters: 
+ *  	   d - DMA channel
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_fillring(sbmacdma_t *d)
+{
+	int idx;
+	
+	for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
+		if (sbdma_add_rcvbuffer(d,NULL) != 0) break;
+	}
+}
+
+
+/**********************************************************************
+ *  SBDMA_RX_PROCESS(sc,d)
+ *  
+ *  Process "completed" receive buffers on the specified DMA channel.  
+ *  Note that this isn't really ideal for priority channels, since
+ *  it processes all of the packets on a given channel before 
+ *  returning. 
+ *
+ *  Input parameters: 
+ *	   sc - softc structure
+ *  	   d - DMA channel context
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
+{
+	int curidx;
+	int hwidx;
+	sbdmadscr_t *dsc;
+	struct sk_buff *sb;
+	int len;
+	
+	for (;;) {
+		/* 
+		 * figure out where we are (as an index) and where
+		 * the hardware is (also as an index)
+		 *
+		 * This could be done faster if (for example) the 
+		 * descriptor table was page-aligned and contiguous in
+		 * both virtual and physical memory -- you could then
+		 * just compare the low-order bits of the virtual address
+		 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
+		 */
+		
+		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
+		hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+				d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
+		
+		/*
+		 * If they're the same, that means we've processed all
+		 * of the descriptors up to (but not including) the one that
+		 * the hardware is working on right now.
+		 */
+		
+		if (curidx == hwidx) break;
+		
+		/*
+		 * Otherwise, get the packet's sk_buff ptr back
+		 */
+		
+		dsc = &(d->sbdma_dscrtable[curidx]);
+		sb = d->sbdma_ctxtable[curidx];
+		d->sbdma_ctxtable[curidx] = NULL;
+		
+		len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
+		
+		/*
+		 * Check packet status.  If good, process it.
+		 * If not, silently drop it and put it back on the
+		 * receive ring.
+		 */
+		
+		if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
+			
+			/*
+			 * Set length into the packet
+			 */
+			skb_put(sb,len);
+			
+       			/*
+			 * Add a new buffer to replace the old one.  If we fail
+			 * to allocate a buffer, we're going to drop this
+			 * packet and put it right back on the receive ring.
+			 */
+			
+			if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
+			    sbdma_add_rcvbuffer(d,sb);	/* re-add old buffer */
+			    }
+			else {
+			    /*
+			     * Buffer has been replaced on the receive ring.
+			     * Pass the buffer to the kernel
+			     */
+			    sc->sbm_stats.rx_bytes += len;
+			    sc->sbm_stats.rx_packets++;
+			    sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
+			    netif_rx(sb);
+			    }
+		}
+		else {
+			/*
+			 * Packet was mangled somehow.  Just drop it and
+			 * put it back on the receive ring.
+			 */
+			sbdma_add_rcvbuffer(d,sb);
+		}
+		
+		
+		/* 
+		 * .. and advance to the next buffer.
+		 */
+		
+		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
+		
+	}
+}
+
+
+
+/**********************************************************************
+ *  SBDMA_TX_PROCESS(sc,d)
+ *  
+ *  Process "completed" transmit buffers on the specified DMA channel.  
+ *  This is normally called within the interrupt service routine.
+ *  Note that this isn't really ideal for priority channels, since
+ *  it processes all of the packets on a given channel before 
+ *  returning. 
+ *
+ *  Input parameters: 
+ *      sc - softc structure
+ *  	   d - DMA channel context
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
+{
+	int curidx;
+	int hwidx;
+	sbdmadscr_t *dsc;
+	struct sk_buff *sb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&(sc->sbm_lock), flags);
+	
+	for (;;) {
+		/* 
+		 * figure out where we are (as an index) and where
+		 * the hardware is (also as an index)
+		 *
+		 * This could be done faster if (for example) the 
+		 * descriptor table was page-aligned and contiguous in
+		 * both virtual and physical memory -- you could then
+		 * just compare the low-order bits of the virtual address
+		 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
+		 */
+		
+		curidx = d->sbdma_remptr - d->sbdma_dscrtable;
+		{
+			/* XXX This is gross, ugly, and only here because justin hacked it
+			   in to fix a problem without really understanding it. 
+			   
+			   It seems that, for whatever reason, this routine is invoked immediately upon the enabling of interrupts.
+			   So then the Read below returns zero, making hwidx a negative number, and anti-hilarity
+			   ensues.
+			   
+			   I'm guessing there's a proper fix involving clearing out interrupt state from old packets
+			   before enabling interrupts, but I'm not sure.  
+
+			   Anyways, this hack seems to work, and is Good Enough for 11 PM.  :)
+			   
+			   -Justin
+			*/
+			  
+			uint64_t tmp = SBMAC_READCSR(d->sbdma_curdscr);
+			if (!tmp) {
+				break;
+			}
+			hwidx = (int) (((tmp & M_DMA_CURDSCR_ADDR) -
+					d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
+		}
+		/*
+		 * If they're the same, that means we've processed all
+		 * of the descriptors up to (but not including) the one that
+		 * the hardware is working on right now.
+		 */
+		
+		if (curidx == hwidx) break;
+		
+		/*
+		 * Otherwise, get the packet's sk_buff ptr back
+		 */
+		
+		dsc = &(d->sbdma_dscrtable[curidx]);
+		sb = d->sbdma_ctxtable[curidx];
+		d->sbdma_ctxtable[curidx] = NULL;
+		
+		/*
+		 * Stats
+		 */
+		
+		sc->sbm_stats.tx_bytes += sb->len;
+		sc->sbm_stats.tx_packets++;
+		
+		/*
+		 * for transmits, we just free buffers.
+		 */
+		
+		dev_kfree_skb_irq(sb);
+		
+		/* 
+		 * .. and advance to the next buffer.
+		 */
+
+		d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
+		
+	}
+	
+	/*
+	 * Decide if we should wake up the protocol or not.
+	 * Other drivers seem to do this when we reach a low
+	 * watermark on the transmit queue.
+	 */
+	
+	netif_wake_queue(d->sbdma_eth->sbm_dev);
+	
+	spin_unlock_irqrestore(&(sc->sbm_lock), flags);
+	
+}
+
+
+
+/**********************************************************************
+ *  SBMAC_INITCTX(s)
+ *  
+ *  Initialize an Ethernet context structure - this is called
+ *  once per MAC on the 1250.  Memory is allocated here, so don't
+ *  call it again from inside the ioctl routines that bring the
+ *  interface up/down
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac context structure
+ *  	   
+ *  Return value:
+ *  	   0
+ ********************************************************************* */
+
+static int sbmac_initctx(struct sbmac_softc *s)
+{
+	
+	/* 
+	 * figure out the addresses of some ports 
+	 */
+	
+	s->sbm_macenable = PKSEG1(s->sbm_base + R_MAC_ENABLE);
+	s->sbm_maccfg    = PKSEG1(s->sbm_base + R_MAC_CFG);
+	s->sbm_fifocfg   = PKSEG1(s->sbm_base + R_MAC_THRSH_CFG);
+	s->sbm_framecfg  = PKSEG1(s->sbm_base + R_MAC_FRAMECFG);
+	s->sbm_rxfilter  = PKSEG1(s->sbm_base + R_MAC_ADFILTER_CFG);
+	s->sbm_isr       = PKSEG1(s->sbm_base + R_MAC_STATUS);
+	s->sbm_imr       = PKSEG1(s->sbm_base + R_MAC_INT_MASK);
+	s->sbm_mdio      = PKSEG1(s->sbm_base + R_MAC_MDIO);
+
+	s->sbm_phys[0]   = 1;
+	s->sbm_phys[1]   = 0;
+
+	s->sbm_phy_oldbmsr = 0;
+	s->sbm_phy_oldanlpar = 0;
+	s->sbm_phy_oldk1stsr = 0;
+	s->sbm_phy_oldlinkstat = 0;
+	
+	/*
+	 * Initialize the DMA channels.  Right now, only one per MAC is used
+	 * Note: Only do this _once_, as it allocates memory from the kernel!
+	 */
+	
+	sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
+	sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
+	
+	/*
+	 * initial state is OFF
+	 */
+	
+	s->sbm_state = sbmac_state_off;
+	
+	/*
+	 * Initial speed is (XXX TEMP) 10MBit/s HDX no FC
+	 */
+	
+	s->sbm_speed = sbmac_speed_10;
+	s->sbm_duplex = sbmac_duplex_half;
+	s->sbm_fc = sbmac_fc_disabled;
+	
+	return 0;
+}
+
+
+static void sbdma_uninitctx(struct sbmacdma_s *d)
+{
+	if (d->sbdma_dscrtable) {
+		KFREE(d->sbdma_dscrtable);
+		d->sbdma_dscrtable = NULL;
+	}
+	
+	if (d->sbdma_ctxtable) {
+		KFREE(d->sbdma_ctxtable);
+		d->sbdma_ctxtable = NULL;
+	}
+}
+
+
+static void sbmac_uninitctx(struct sbmac_softc *sc)
+{
+	sbdma_uninitctx(&(sc->sbm_txdma));
+	sbdma_uninitctx(&(sc->sbm_rxdma));
+}
+
+
+/**********************************************************************
+ *  SBMAC_CHANNEL_START(s)
+ *  
+ *  Start packet processing on this MAC.
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbmac_channel_start(struct sbmac_softc *s)
+{
+	uint64_t reg;
+	sbmac_port_t port;
+	uint64_t cfg,fifo,framecfg;
+	int idx;
+	
+	/*
+	 * Don't do this if running
+	 */
+
+	if (s->sbm_state == sbmac_state_on) return;
+	
+	/*
+	 * Bring the controller out of reset, but leave it off.
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_macenable,0);
+	
+	/*
+	 * Ignore all received packets
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_rxfilter,0);
+	
+	/* 
+	 * Calculate values for various control registers.
+	 */
+	
+	cfg = M_MAC_RETRY_EN |
+		M_MAC_TX_HOLD_SOP_EN | 
+		V_MAC_TX_PAUSE_CNT_16K |
+		M_MAC_AP_STAT_EN |
+		M_MAC_FAST_SYNC |
+		M_MAC_SS_EN |
+		0;
+	
+	fifo = V_MAC_TX_WR_THRSH(4) |	/* Must be '4' or '8' */
+		V_MAC_TX_RD_THRSH(4) |
+		V_MAC_TX_RL_THRSH(4) |
+		V_MAC_RX_PL_THRSH(4) |
+		V_MAC_RX_RD_THRSH(4) |	/* Must be '4' */
+		V_MAC_RX_PL_THRSH(4) |
+		V_MAC_RX_RL_THRSH(8) |
+		0;
+	
+	framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
+		V_MAC_MAX_FRAMESZ_DEFAULT |
+		V_MAC_BACKOFF_SEL(1);
+	
+	
+	/*
+	 * Clear out the hash address map 
+	 */
+	
+	port = PKSEG1(s->sbm_base + R_MAC_HASH_BASE);
+        for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
+		SBMAC_WRITECSR(port,0);
+		port += sizeof(uint64_t);
+	}
+	
+	/*
+	 * Clear out the exact-match table
+	 */
+	
+	port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
+	for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
+		SBMAC_WRITECSR(port,0);
+		port += sizeof(uint64_t);
+	}
+	
+	/*
+	 * Clear out the DMA Channel mapping table registers
+	 */
+	
+	port = PKSEG1(s->sbm_base + R_MAC_CHUP0_BASE);
+	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
+		SBMAC_WRITECSR(port,0);
+		port += sizeof(uint64_t);
+	}
+
+
+	port = PKSEG1(s->sbm_base + R_MAC_CHLO0_BASE);
+	for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
+		SBMAC_WRITECSR(port,0);
+		port += sizeof(uint64_t);
+	}
+	
+	/*
+	 * Program the hardware address.  It goes into the hardware-address
+	 * register as well as the first filter register.
+	 */
+	
+	reg = sbmac_addr2reg(s->sbm_hwaddr);
+	
+	port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
+	SBMAC_WRITECSR(port,reg);
+	port = PKSEG1(s->sbm_base + R_MAC_ETHERNET_ADDR);
+
+#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
+	/*
+	 * Pass1 SB1250s do not receive packets addressed to the
+	 * destination address in the R_MAC_ETHERNET_ADDR register.
+	 * Set the value to zero.
+	 */
+	SBMAC_WRITECSR(port,0);
+#else
+	SBMAC_WRITECSR(port,reg);
+#endif
+	
+	/*
+	 * Set the receive filter for no packets, and write values
+	 * to the various config registers
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_rxfilter,0);
+	SBMAC_WRITECSR(s->sbm_imr,0);
+	SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
+	SBMAC_WRITECSR(s->sbm_fifocfg,fifo);
+	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
+	
+	/*
+	 * Initialize DMA channels (rings should be ok now)
+	 */
+	
+	sbdma_channel_start(&(s->sbm_rxdma));
+	sbdma_channel_start(&(s->sbm_txdma));
+	
+	/*
+	 * Configure the speed, duplex, and flow control
+	 */
+
+	sbmac_set_speed(s,s->sbm_speed);
+	sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
+	
+	/*
+	 * Fill the receive ring
+	 */
+	
+	sbdma_fillring(&(s->sbm_rxdma));
+	
+	/* 
+	 * Turn on the rest of the bits in the enable register
+	 */      
+	
+	SBMAC_WRITECSR(s->sbm_macenable,
+		       M_MAC_RXDMA_EN0 |
+		       M_MAC_TXDMA_EN0 |
+		       M_MAC_RX_ENABLE |
+		       M_MAC_TX_ENABLE);
+	
+	
+
+	/*
+	 * Accept any kind of interrupt on TX and RX DMA channel 0
+	 */
+	SBMAC_WRITECSR(s->sbm_imr,
+		       (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
+		       (M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
+	
+	/* 
+	 * Enable receiving unicasts and broadcasts 
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN);
+	
+	/*
+	 * we're running now. 
+	 */
+	
+	s->sbm_state = sbmac_state_on;
+	
+	/* 
+	 * Program multicast addresses 
+	 */
+	
+	sbmac_setmulti(s);
+	
+	/* 
+	 * If channel was in promiscuous mode before, turn that on 
+	 */
+	
+	if (s->sbm_devflags & IFF_PROMISC) {
+		sbmac_promiscuous_mode(s,1);
+	}
+	
+}
+
+
+/**********************************************************************
+ *  SBMAC_CHANNEL_STOP(s)
+ *  
+ *  Stop packet processing on this MAC.
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbmac_channel_stop(struct sbmac_softc *s)
+{
+	uint64_t ctl;
+	
+	/* don't do this if already stopped */
+	
+	if (s->sbm_state == sbmac_state_off) return;
+	
+	/* don't accept any packets, disable all interrupts */
+	
+	SBMAC_WRITECSR(s->sbm_rxfilter,0);
+	SBMAC_WRITECSR(s->sbm_imr,0);
+	
+	/* Turn off ticker */
+	
+	/* XXX */
+	
+	/* turn off receiver and transmitter */
+	
+	ctl = SBMAC_READCSR(s->sbm_macenable);
+	ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0);
+	SBMAC_WRITECSR(s->sbm_macenable,ctl);
+	
+	/* We're stopped now. */
+	
+	s->sbm_state = sbmac_state_off;
+	
+	
+	/* Empty the receive and transmit rings */
+	
+	sbdma_emptyring(&(s->sbm_rxdma));
+	sbdma_emptyring(&(s->sbm_txdma));
+	
+}
+
+/**********************************************************************
+ *  SBMAC_SET_CHANNEL_STATE(state)
+ *  
+ *  Set the channel's state ON or OFF
+ *  
+ *  Input parameters: 
+ *  	   state - new state
+ *  	   
+ *  Return value:
+ *  	   old state
+ ********************************************************************* */
+static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc,
+					     sbmac_state_t state)
+{
+	sbmac_state_t oldstate = sc->sbm_state;
+	
+	/*
+	 * If same as previous state, return
+	 */
+	
+	if (state == oldstate) {
+		return oldstate;
+	}
+	
+	/*
+	 * If new state is ON, turn channel on 
+	 */
+	
+	if (state == sbmac_state_on) {
+		sbmac_channel_start(sc);
+	}
+	else {
+		sbmac_channel_stop(sc);
+	}
+	
+	/*
+	 * Return previous state
+	 */
+	
+	return oldstate;
+}
+
+
+/**********************************************************************
+ *  SBMAC_PROMISCUOUS_MODE(sc,onoff)
+ *  
+ *  Turn on or off promiscuous mode
+ *  
+ *  Input parameters: 
+ *  	   sc - softc
+ *      onoff - 1 to turn on, 0 to turn off
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
+{
+	uint64_t reg;
+	
+	if (sc->sbm_state != sbmac_state_on) return;
+	
+	if (onoff) {
+		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg |= M_MAC_ALLPKT_EN;
+		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+	}	
+	else {
+		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg &= ~M_MAC_ALLPKT_EN;
+		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+	}
+}
+
+
+
+#if 0
+/**********************************************************************
+ *  SBMAC_INIT_AND_START(sc)
+ *  
+ *  Stop the channel and restart it.  This is generally used
+ *  when we have to do something to the channel that requires
+ *  a swift kick.
+ *  
+ *  Input parameters: 
+ *  	   sc - softc
+ ********************************************************************* */
+
+static void sbmac_init_and_start(struct sbmac_softc *sc)
+{
+	unsigned long flags;
+	
+	spin_lock_irqsave(&(sc->sbm_lock),flags);
+	
+	sbmac_set_channel_state(sc,sbmac_state_on);
+	
+	spin_unlock_irqrestore(&(sc->sbm_lock),flags);
+}
+#endif
+
+
+/**********************************************************************
+ *  SBMAC_ADDR2REG(ptr)
+ *  
+ *  Convert six bytes into the 64-bit register value that
+ *  we typically write into the SBMAC's address/mcast registers
+ *  
+ *  Input parameters: 
+ *  	   ptr - pointer to 6 bytes
+ *  	   
+ *  Return value:
+ *  	   register value
+ ********************************************************************* */
+
+static uint64_t sbmac_addr2reg(unsigned char *ptr)
+{
+	uint64_t reg = 0;
+	
+	ptr += 6;
+	
+	reg |= (uint64_t) *(--ptr); 
+	reg <<= 8;
+	reg |= (uint64_t) *(--ptr); 
+	reg <<= 8;
+	reg |= (uint64_t) *(--ptr); 
+	reg <<= 8;
+	reg |= (uint64_t) *(--ptr); 
+	reg <<= 8;
+	reg |= (uint64_t) *(--ptr); 
+	reg <<= 8;
+	reg |= (uint64_t) *(--ptr); 
+	
+	return reg;
+}
+
+
+/**********************************************************************
+ *  SBMAC_SET_SPEED(s,speed)
+ *  
+ *  Configure LAN speed for the specified MAC.
+ *  Warning: must be called when MAC is off!
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   speed - speed to set MAC to (see sbmac_speed_t enum)
+ *  	   
+ *  Return value:
+ *  	   1 if successful
+ *      0 indicates invalid parameters
+ ********************************************************************* */
+
+static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
+{
+	uint64_t cfg;
+	uint64_t framecfg;
+
+	/*
+	 * Save new current values
+	 */
+	
+	s->sbm_speed = speed;
+	
+	if (s->sbm_state == sbmac_state_on) return 0;	/* save for next restart */
+
+	/*
+	 * Read current register values 
+	 */
+	
+	cfg = SBMAC_READCSR(s->sbm_maccfg);
+	framecfg = SBMAC_READCSR(s->sbm_framecfg);
+	
+	/*
+	 * Mask out the stuff we want to change
+	 */
+	
+	cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
+	framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
+		      M_MAC_SLOT_SIZE);
+	
+	/*
+	 * Now add in the new bits
+	 */
+	
+	switch (speed) {
+	case sbmac_speed_10:
+		framecfg |= V_MAC_IFG_RX_10 |
+			V_MAC_IFG_TX_10 |
+			K_MAC_IFG_THRSH_10 |
+			V_MAC_SLOT_SIZE_10;
+		cfg |= V_MAC_SPEED_SEL_10MBPS;
+		break;
+		
+	case sbmac_speed_100:
+		framecfg |= V_MAC_IFG_RX_100 |
+			V_MAC_IFG_TX_100 |
+			V_MAC_IFG_THRSH_100 |
+			V_MAC_SLOT_SIZE_100;
+		cfg |= V_MAC_SPEED_SEL_100MBPS ;
+		break;
+		
+	case sbmac_speed_1000:
+		framecfg |= V_MAC_IFG_RX_1000 |
+			V_MAC_IFG_TX_1000 |
+			V_MAC_IFG_THRSH_1000 |
+			V_MAC_SLOT_SIZE_1000;
+		cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
+		break;
+		
+	case sbmac_speed_auto:		/* XXX not implemented */
+		/* fall through */
+	default:
+		return 0;
+	}
+	
+	/*
+	 * Send the bits back to the hardware 
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_framecfg,framecfg);
+	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
+	
+	return 1;
+	
+}
+
+/**********************************************************************
+ *  SBMAC_SET_DUPLEX(s,duplex,fc)
+ *  
+ *  Set Ethernet duplex and flow control options for this MAC
+ *  Warning: must be called when MAC is off!
+ *  
+ *  Input parameters: 
+ *  	   s - sbmac structure
+ *  	   duplex - duplex setting (see sbmac_duplex_t)
+ *  	   fc - flow control setting (see sbmac_fc_t)
+ *  	   
+ *  Return value:
+ *  	   1 if ok
+ *  	   0 if an invalid parameter combination was specified
+ ********************************************************************* */
+
+static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc)
+{
+	uint64_t cfg;
+	
+	/*
+	 * Save new current values
+	 */
+	
+	s->sbm_duplex = duplex;
+	s->sbm_fc = fc;
+	
+	if (s->sbm_state == sbmac_state_on) return 0;	/* save for next restart */
+	
+	/*
+	 * Read current register values 
+	 */
+	
+	cfg = SBMAC_READCSR(s->sbm_maccfg);
+	
+	/*
+	 * Mask off the stuff we're about to change
+	 */
+	
+	cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
+	
+	
+	switch (duplex) {
+	case sbmac_duplex_half:
+		switch (fc) {
+		case sbmac_fc_disabled:
+			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
+			break;
+			
+		case sbmac_fc_collision:
+			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
+			break;
+			
+		case sbmac_fc_carrier:
+			cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
+			break;
+			
+		case sbmac_fc_auto:		/* XXX not implemented */
+			/* fall through */					   
+		case sbmac_fc_frame:		/* not valid in half duplex */
+		default:			/* invalid selection */
+			return 0;
+		}
+		break;
+		
+	case sbmac_duplex_full:
+		switch (fc) {
+		case sbmac_fc_disabled:
+			cfg |= V_MAC_FC_CMD_DISABLED;
+			break;
+			
+		case sbmac_fc_frame:
+			cfg |= V_MAC_FC_CMD_ENABLED;
+			break;
+			
+		case sbmac_fc_collision:	/* not valid in full duplex */
+		case sbmac_fc_carrier:		/* not valid in full duplex */
+		case sbmac_fc_auto:		/* XXX not implemented */
+			/* fall through */					   
+		default:
+			return 0;
+		}
+		break;
+	case sbmac_duplex_auto:
+		/* XXX not implemented */
+		break;
+	}
+	
+	/*
+	 * Send the bits back to the hardware 
+	 */
+	
+	SBMAC_WRITECSR(s->sbm_maccfg,cfg);
+	
+	return 1;
+}
+
+
+
+
+/**********************************************************************
+ *  SBMAC_INTR()
+ *  
+ *  Interrupt handler for MAC interrupts
+ *  
+ *  Input parameters: 
+ *  	   MAC structure
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
+{
+	struct net_device *dev = (struct net_device *) dev_instance;
+	struct sbmac_softc *sc = (struct sbmac_softc *) (dev->priv);
+	uint64_t isr;
+	
+	for (;;) {
+		
+		/*
+		 * Read the ISR (this clears the bits in the real register)
+		 */
+		
+		isr = SBMAC_READCSR(sc->sbm_isr);
+		
+		if (isr == 0) break;
+		
+		/*
+		 * Transmits on channel 0
+		 */
+		
+		if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
+			sbdma_tx_process(sc,&(sc->sbm_txdma));
+		}
+		
+		/*
+		 * Receives on channel 0
+		 */
+		
+		if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
+			sbdma_rx_process(sc,&(sc->sbm_rxdma));
+		}
+	}
+	
+}
+
+
+/**********************************************************************
+ *  SBMAC_START_TX(skb,dev)
+ *  
+ *  Start output on the specified interface.  Basically, we 
+ *  queue as many buffers as we can until the ring fills up, or
+ *  we run off the end of the queue, whichever comes first.
+ *  
+ *  Input parameters: 
+ *  	   
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+	
+	/* lock eth irq */
+	spin_lock_irq (&sc->sbm_lock);
+	
+	/*
+	 * Put the buffer on the transmit ring.  If we 
+	 * don't have room, stop the queue.
+	 */
+	
+	if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
+		/* XXX save skb that we could not send */
+		netif_stop_queue(dev);
+	}
+	
+	dev->trans_start = jiffies;
+	
+	spin_unlock_irq (&sc->sbm_lock);
+	
+	return 0;
+}
+
+/**********************************************************************
+ *  SBMAC_SETMULTI(sc)
+ *  
+ *  Reprogram the multicast table into the hardware, given
+ *  the list of multicasts associated with the interface
+ *  structure.
+ *  
+ *  Input parameters: 
+ *  	   sc - softc
+ *  	   
+ *  Return value:
+ *  	   nothing
+ ********************************************************************* */
+
+static void sbmac_setmulti(struct sbmac_softc *sc)
+{
+	uint64_t reg;
+	sbmac_port_t port;
+	int idx;
+	struct dev_mc_list *mclist;
+	struct net_device *dev = sc->sbm_dev;
+	
+	/* 
+	 * Clear out entire multicast table.  We do this by nuking
+	 * the entire hash table and all the direct matches except
+	 * the first one, which is used for our station address 
+	 */
+	
+	for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
+		port = PKSEG1(sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)));
+		SBMAC_WRITECSR(port,0);	
+	}
+	
+	for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
+		port = PKSEG1(sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)));
+		SBMAC_WRITECSR(port,0);	
+	}
+	
+	/*
+	 * Clear the filter to say we don't want any multicasts.
+	 */
+	
+	reg = SBMAC_READCSR(sc->sbm_rxfilter);
+	reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
+	SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+	
+	if (dev->flags & IFF_ALLMULTI) {
+		/* 
+		 * Enable ALL multicasts.  Do this by inverting the 
+		 * multicast enable bit. 
+		 */
+		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
+		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+		return;
+	}
+	
+
+	/* 
+	 * Progam new multicast entries.  For now, only use the
+	 * perfect filter.  In the future we'll need to use the
+	 * hash filter if the perfect filter overflows
+	 */
+	
+	/* XXX only using perfect filter for now, need to use hash
+	 * XXX if the table overflows */
+	
+	idx = 1;		/* skip station address */
+	mclist = dev->mc_list;
+	while (mclist && (idx < MAC_ADDR_COUNT)) {
+		reg = sbmac_addr2reg(mclist->dmi_addr);
+		port = PKSEG1(sc->sbm_base + 
+			      R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)));
+		SBMAC_WRITECSR(port,reg);
+		idx++;
+		mclist = mclist->next;
+	}
+	
+	/*	
+	 * Enable the "accept multicast bits" if we programmed at least one
+	 * multicast. 
+	 */
+	
+	if (idx > 1) {
+		reg = SBMAC_READCSR(sc->sbm_rxfilter);
+		reg |= M_MAC_MCAST_EN;
+		SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
+	}
+}
+
+
+
+#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
+/**********************************************************************
+ *  SBMAC_PARSE_XDIGIT(str)
+ *  
+ *  Parse a hex digit, returning its value
+ *  
+ *  Input parameters: 
+ *  	   str - character
+ *  	   
+ *  Return value:
+ *  	   hex value, or -1 if invalid
+ ********************************************************************* */
+
+static int sbmac_parse_xdigit(char str)
+{
+	int digit;
+	
+	if ((str >= '0') && (str <= '9')) digit = str - '0';
+	else if ((str >= 'a') && (str <= 'f')) digit = str - 'a' + 10;
+	else if ((str >= 'A') && (str <= 'F')) digit = str - 'A' + 10;
+	else return -1;
+	
+	return digit;
+}
+
+/**********************************************************************
+ *  SBMAC_PARSE_HWADDR(str,hwaddr)
+ *  
+ *  Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
+ *  Ethernet address.
+ *  
+ *  Input parameters: 
+ *  	   str - string
+ *  	   hwaddr - pointer to hardware address
+ *  	   
+ *  Return value:
+ *  	   0 if ok, else -1
+ ********************************************************************* */
+
+static int sbmac_parse_hwaddr(char *str,u_char *hwaddr)
+{
+	int digit1,digit2;
+	int idx = 6;
+	
+	while (*str && (idx > 0)) {
+		digit1 = sbmac_parse_xdigit(*str);
+		if (digit1 < 0) return -1;
+		str++;
+		if (!*str) return -1;
+		
+		if ((*str == ':') || (*str == '-')) {
+			digit2 = digit1;
+			digit1 = 0;
+		}
+		else {
+			digit2 = sbmac_parse_xdigit(*str);
+			if (digit2 < 0) return -1;
+			str++;
+		}
+		
+		*hwaddr++ = (digit1 << 4) | digit2;
+		idx--;
+		
+		if (*str == '-') str++;
+		if (*str == ':') str++;
+	}
+	return 0;
+}
+#endif
+
+/**********************************************************************
+ *  SBMAC_INIT(dev)
+ *  
+ *  Attach routine - init hardware and hook ourselves into linux
+ *  
+ *  Input parameters: 
+ *  	   dev - net_device structure
+ *  	   
+ *  Return value:
+ *  	   status
+ ********************************************************************* */
+
+static int sbmac_init(struct net_device *dev)
+{
+	struct sbmac_softc *sc;
+	u_char *eaddr;
+	uint64_t ea_reg;
+	int idx;
+	
+	sc = (struct sbmac_softc *)dev->priv;
+	
+	/* Determine controller base address */
+	
+	sc->sbm_base = (sbmac_port_t) dev->base_addr;
+	sc->sbm_dev = dev;
+	
+	eaddr = sc->sbm_hwaddr;
+	
+	/* 
+	 * Read the ethernet address.  The firwmare left this programmed
+	 * for us in the ethernet address register for each mac.
+	 */
+	
+	ea_reg = SBMAC_READCSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR));
+	SBMAC_WRITECSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR), 0);
+	for (idx = 0; idx < 6; idx++) {
+		eaddr[idx] = (uint8_t) (ea_reg & 0xFF);
+		ea_reg >>= 8;
+	}
+	
+	
+	for (idx = 0; idx < 6; idx++) {
+		dev->dev_addr[idx] = eaddr[idx];
+	}
+	
+	
+	/*
+	 * Init packet size 
+	 */
+	
+	sc->sbm_buffersize = ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN;
+	
+	/* 
+	 * Initialize context (get pointers to registers and stuff), then
+	 * allocate the memory for the descriptor tables.
+	 */
+	
+	sbmac_initctx(sc);
+	
+	
+	/*
+	 * Display Ethernet address (this is called during the config process
+	 * so we need to finish off the config message that was being displayed)
+	 */
+	printk(KERN_INFO
+	       "%s: SB1250 Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n", 
+	       dev->name,
+	       (unsigned long) sc->sbm_base,
+	       eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
+	
+	/*
+	 * Set up Linux device callins
+	 */
+	
+	spin_lock_init(&(sc->sbm_lock));
+	
+	ether_setup(dev);
+	dev->open               = sbmac_open;
+	dev->hard_start_xmit    = sbmac_start_tx;
+	dev->stop               = sbmac_close;
+	dev->get_stats          = sbmac_get_stats;
+	dev->set_multicast_list = sbmac_set_rx_mode;
+	dev->do_ioctl           = sbmac_mii_ioctl;
+	dev->tx_timeout         = sbmac_tx_timeout;
+	dev->watchdog_timeo     = TX_TIMEOUT;
+	
+	return 0;
+	
+}
+
+
+static int sbmac_open(struct net_device *dev)
+{
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+	
+	MOD_INC_USE_COUNT;
+
+	if (debug > 1) {
+		printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
+	}
+	
+	/* 
+	 * map/route interrupt 
+	 */
+	
+	if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev)) {
+		MOD_DEC_USE_COUNT;
+		return -EBUSY;
+	}
+	
+	/*
+	 * Configure default speed 
+	 */
+
+	sbmac_mii_poll(sc,1);
+	
+	/*
+	 * Turn on the channel
+	 */
+
+	sbmac_set_channel_state(sc,sbmac_state_on);
+	
+	/*
+	 * XXX Station address is in dev->dev_addr
+	 */
+	
+	if (dev->if_port == 0)
+		dev->if_port = 0; 
+	
+	netif_start_queue(dev);
+	
+	sbmac_set_rx_mode(dev);
+	
+	/* Set the timer to check for link beat. */
+	init_timer(&sc->sbm_timer);
+	sc->sbm_timer.expires = jiffies + 2;
+	sc->sbm_timer.data = (unsigned long)dev;
+	sc->sbm_timer.function = &sbmac_timer;
+	add_timer(&sc->sbm_timer);
+	
+	return 0;
+}
+
+
+
+static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
+{
+    int bmsr,bmcr,k1stsr,anlpar;
+    int chg;
+    char buffer[100];
+    char *p = buffer;
+
+    /* Read the mode status and mode control registers. */
+    bmsr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMSR);
+    bmcr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMCR);
+
+    /* get the link partner status */
+    anlpar = sbmac_mii_read(s,s->sbm_phys[0],MII_ANLPAR);
+
+    /* if supported, read the 1000baseT register */
+    if (bmsr & BMSR_1000BT_XSR) {
+	k1stsr = sbmac_mii_read(s,s->sbm_phys[0],MII_K1STSR);
+	}
+    else {
+	k1stsr = 0;
+	}
+
+    chg = 0;
+
+    if ((bmsr & BMSR_LINKSTAT) == 0) {
+	/*
+	 * If link status is down, clear out old info so that when
+	 * it comes back up it will force us to reconfigure speed
+	 */
+	s->sbm_phy_oldbmsr = 0;
+	s->sbm_phy_oldanlpar = 0;
+	s->sbm_phy_oldk1stsr = 0;
+	return 0;
+	}
+
+    if ((s->sbm_phy_oldbmsr != bmsr) ||
+	(s->sbm_phy_oldanlpar != anlpar) ||
+	(s->sbm_phy_oldk1stsr != k1stsr)) {
+	if (debug > 1) {
+	    printk(KERN_DEBUG "%s: bmsr:%x/%x anlpar:%x/%x  k1stsr:%x/%x\n",
+	       s->sbm_dev->name,
+	       s->sbm_phy_oldbmsr,bmsr,
+	       s->sbm_phy_oldanlpar,anlpar,
+	       s->sbm_phy_oldk1stsr,k1stsr);
+	    }
+	s->sbm_phy_oldbmsr = bmsr;
+	s->sbm_phy_oldanlpar = anlpar;
+	s->sbm_phy_oldk1stsr = k1stsr;
+	chg = 1;
+	}
+
+    if (chg == 0) return 0;
+
+    p += sprintf(p,"Link speed: ");
+
+    if (k1stsr & K1STSR_LP1KFD) {
+	s->sbm_speed = sbmac_speed_1000;
+	s->sbm_duplex = sbmac_duplex_full;
+	s->sbm_fc = sbmac_fc_frame;
+	p += sprintf(p,"1000BaseT FDX");
+	}
+    else if (k1stsr & K1STSR_LP1KHD) {
+	s->sbm_speed = sbmac_speed_1000;
+	s->sbm_duplex = sbmac_duplex_half;
+	s->sbm_fc = sbmac_fc_disabled;
+	p += sprintf(p,"1000BaseT HDX");
+	}
+    else if (anlpar & ANLPAR_TXFD) {
+	s->sbm_speed = sbmac_speed_100;
+	s->sbm_duplex = sbmac_duplex_full;
+	s->sbm_fc = (anlpar & ANLPAR_PAUSE) ? sbmac_fc_frame : sbmac_fc_disabled;
+	p += sprintf(p,"100BaseT FDX");
+	}
+    else if (anlpar & ANLPAR_TXHD) {
+	s->sbm_speed = sbmac_speed_100;
+	s->sbm_duplex = sbmac_duplex_half;
+	s->sbm_fc = sbmac_fc_disabled;
+	p += sprintf(p,"100BaseT HDX");
+	}
+    else if (anlpar & ANLPAR_10FD) {
+	s->sbm_speed = sbmac_speed_10;
+	s->sbm_duplex = sbmac_duplex_full;
+	s->sbm_fc = sbmac_fc_frame;
+	p += sprintf(p,"10BaseT FDX");
+	}
+    else if (anlpar & ANLPAR_10HD) {
+	s->sbm_speed = sbmac_speed_10;
+	s->sbm_duplex = sbmac_duplex_half;
+	s->sbm_fc = sbmac_fc_collision;
+	p += sprintf(p,"10BaseT HDX");
+	}
+    else {
+	p += sprintf(p,"Unknown");
+	}
+
+    if (noisy) {
+	    printk(KERN_INFO "%s: %s\n",s->sbm_dev->name,buffer);
+	    }
+
+    return 1;
+}
+
+
+
+
+static void sbmac_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+	int next_tick = HZ;
+	int mii_status;
+
+	spin_lock_irq (&sc->sbm_lock);
+	
+	/* make IFF_RUNNING follow the MII status bit "Link established" */
+	mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
+	
+	if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) {
+    	        sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT;
+		if (mii_status & BMSR_LINKSTAT) {
+			netif_carrier_on(dev);
+		}
+		else {
+			netif_carrier_off(dev);	
+		}
+	}
+	
+	/*
+	 * Poll the PHY to see what speed we should be running at
+	 */
+
+	if (sbmac_mii_poll(sc,1)) {
+	    if (sc->sbm_state != sbmac_state_off) {
+		/*
+		 * something changed, restart the channel
+		 */
+		if (debug > 1) {
+		    printk("%s: restarting channel because speed changed\n",
+			   sc->sbm_dev->name);
+		    }
+		sbmac_channel_stop(sc);
+		sbmac_channel_start(sc);
+		}
+	    }
+	
+	spin_unlock_irq (&sc->sbm_lock);
+	
+	sc->sbm_timer.expires = jiffies + next_tick;
+	add_timer(&sc->sbm_timer);
+}
+
+
+static void sbmac_tx_timeout (struct net_device *dev)
+{
+	struct sbmac_softc *sc = (struct sbmac_softc *) dev->priv;
+	
+	spin_lock_irq (&sc->sbm_lock);
+	
+	
+	dev->trans_start = jiffies;
+	sc->sbm_stats.tx_errors++;
+	
+	spin_unlock_irq (&sc->sbm_lock);
+
+	printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
+}
+
+
+
+
+static struct net_device_stats *sbmac_get_stats(struct net_device *dev)
+{
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&sc->sbm_lock, flags);
+	
+	/* XXX update other stats here */
+	
+	spin_unlock_irqrestore(&sc->sbm_lock, flags);
+	
+	return &sc->sbm_stats;
+}
+
+
+
+static void sbmac_set_rx_mode(struct net_device *dev)
+{
+	unsigned long flags;
+	int msg_flag = 0;
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+
+	spin_lock_irqsave(&sc->sbm_lock, flags);
+	if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) {
+		/*
+		 * Promiscuous changed.
+		 */
+		
+		if (dev->flags & IFF_PROMISC) {	
+			/* Unconditionally log net taps. */
+			msg_flag = 1;
+			sbmac_promiscuous_mode(sc,1);
+		}
+		else {
+			msg_flag = 2;
+			sbmac_promiscuous_mode(sc,0);
+		}
+	}
+	spin_unlock_irqrestore(&sc->sbm_lock, flags);
+	
+	if (msg_flag) {
+		printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n", dev->name,(msg_flag==1)?"en":"dis");
+	}
+	
+	/*
+	 * Program the multicasts.  Do this every time.
+	 */
+	
+	sbmac_setmulti(sc);
+	
+}
+
+static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+	u16 *data = (u16 *)&rq->ifr_data;
+	unsigned long flags;
+	int retval;
+	
+	spin_lock_irqsave(&sc->sbm_lock, flags);
+	retval = 0;
+	
+	switch(cmd) {
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = sc->sbm_phys[0] & 0x1f;
+		/* Fall Through */
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		data[3] = sbmac_mii_read(sc, data[0] & 0x1f, data[1] & 0x1f);
+		break;
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!capable(CAP_NET_ADMIN)) {
+			retval = -EPERM;
+			break;
+		}
+		if (debug > 1) {
+		    printk(KERN_DEBUG "%s: sbmac_mii_ioctl: write %02X %02X %02X\n",dev->name,
+		       data[0],data[1],data[2]);
+		    }
+		sbmac_mii_write(sc, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		break;
+	default:
+		retval = -EOPNOTSUPP;
+	}
+	
+	spin_unlock_irqrestore(&sc->sbm_lock, flags);
+	return retval;
+}
+
+static int sbmac_close(struct net_device *dev)
+{
+	struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+	unsigned long flags;
+	
+	sbmac_set_channel_state(sc,sbmac_state_off);
+	
+	del_timer_sync(&sc->sbm_timer);
+	
+	spin_lock_irqsave(&sc->sbm_lock, flags);
+	
+	netif_stop_queue(dev);
+	
+	if (debug > 1) {
+		printk(KERN_DEBUG "%s: Shutting down ethercard\n",dev->name);
+	}
+	
+	spin_unlock_irqrestore(&sc->sbm_lock, flags);
+	
+	/* Make sure there is no irq-handler running on a different CPU. */
+	synchronize_irq();
+	
+	free_irq(dev->irq, dev);
+	
+	sbdma_emptyring(&(sc->sbm_txdma));
+	sbdma_emptyring(&(sc->sbm_rxdma));
+	
+	MOD_DEC_USE_COUNT;
+	
+	return 0;
+}
+
+
+
+#if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR)
+static void
+sbmac_setup_hwaddr(int chan,char *addr)
+{
+	uint8_t eaddr[6];
+	uint64_t val;
+	sbmac_port_t port;
+
+	port = A_MAC_CHANNEL_BASE(chan);
+	sbmac_parse_hwaddr(addr,eaddr);
+	val = sbmac_addr2reg(eaddr);
+	SBMAC_WRITECSR(PKSEG1(port+R_MAC_ETHERNET_ADDR),val);
+	val = SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR));
+}
+#endif
+
+static struct net_device *dev_sbmac[MAX_UNITS] = {0,0,0};
+
+static int __init
+sbmac_init_module(void)
+{
+	int idx;
+	int macidx = 0;
+	struct net_device *dev;
+	sbmac_port_t port;
+	
+	/*
+	 * For bringup when not using the firmware, we can pre-fill
+	 * the MAC addresses using the environment variables
+	 * specified in this file (or maybe from the config file?)
+	 */
+#ifdef SBMAC_ETH0_HWADDR
+	sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR);
+#endif
+#ifdef SBMAC_ETH1_HWADDR
+	sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR);
+#endif
+#ifdef SBMAC_ETH2_HWADDR
+	sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR);
+#endif
+
+	/*
+	 * Walk through the Ethernet controllers and find
+	 * those who have their MAC addresses set.
+	 */
+	
+	for (idx = 0; idx < MAX_UNITS; idx++) {
+
+	        /*
+	         * This is the base address of the MAC.
+		 */
+
+	        port = A_MAC_CHANNEL_BASE(idx);
+
+		/*	
+		 * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
+		 * value for us by the firmware if we're going to use this MAC.
+		 * If we find a zero, skip this MAC.
+		 */
+
+		if (SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR)) == 0) {
+		    continue;
+		    }
+
+		/*
+		 * Okay, cool.  Initialize this MAC.
+		 */
+
+		dev = init_etherdev(NULL,sizeof(struct sbmac_softc));
+		if (!dev) break;			/* problems, get out now. */
+		dev->irq = K_INT_MAC_0 + idx;
+		dev->base_addr = port;
+		dev->mem_end = 0;
+		/*dev->init = sbmac_init;*/
+		sbmac_init(dev);
+
+		dev_sbmac[macidx] = dev;
+		macidx++;
+
+	}
+
+	/*
+	 * Should we care, 'macidx' is the total number of enabled MACs.
+	 */
+	
+	return 0;
+}
+
+
+static void __exit
+sbmac_cleanup_module(void)
+{
+	int idx;
+	struct net_device *dev;
+	for (idx = 0; idx < MAX_UNITS; idx++) {
+		dev = dev_sbmac[idx];
+		if (dev == NULL) continue;
+		if (dev->priv != NULL) {
+			struct sbmac_softc *sc = (struct sbmac_softc *) dev->priv;
+			
+			unregister_netdev(dev);
+			
+			sbmac_uninitctx(sc);
+			
+			KFREE(sc);
+		}
+		KFREE(dev);
+		dev_sbmac[idx] = NULL;
+	}
+}
+
+module_init(sbmac_init_module);
+module_exit(sbmac_cleanup_module);
diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
--- a/drivers/net/sgiseeq.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/sgiseeq.c	Sun Apr 14 12:16:59 2002
@@ -720,3 +720,5 @@
 			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
 			    &hpc3c0->ethregs, SGI_ENET_IRQ);
 }
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
--- a/drivers/net/skfp/skfddi.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/skfp/skfddi.c	Sun Apr 14 12:16:55 2002
@@ -520,8 +520,6 @@
 {
 	/* Initialize new device structure */
 
-	dev->rmem_end = 0;	/* shared memory isn't used */
-	dev->rmem_start = 0;	/* shared memory isn't used */
 	dev->mem_end = 0;	/* shared memory isn't used */
 	dev->mem_start = 0;	/* shared memory isn't used */
 	dev->base_addr = iobase;	/* save port (I/O) base address */
diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
--- a/drivers/net/smc-mca.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/smc-mca.c	Sun Apr 14 12:16:55 2002
@@ -299,8 +299,8 @@
 	ei_status.rx_start_page = START_PG + TX_PAGES;
 	ei_status.stop_page = num_pages;
 
-	dev->rmem_start = dev->mem_start + TX_PAGES * 256;
-	dev->mem_end = dev->rmem_end =
+	ei_status.rmem_start = dev->mem_start + TX_PAGES * 256;
+	dev->mem_end = ei_status.rmem_end =
 	dev->mem_start + (ei_status.stop_page - START_PG) * 256;
 
 	printk(KERN_INFO ", IRQ %d memory %#lx-%#lx.\n",
@@ -387,12 +387,12 @@
 {
 	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG << 8);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
 		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
--- a/drivers/net/smc-ultra.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/smc-ultra.c	Sun Apr 14 12:16:56 2002
@@ -251,8 +251,8 @@
 	ei_status.rx_start_page = START_PG + TX_PAGES;
 	ei_status.stop_page = num_pages;
 
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = dev->rmem_end
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+	dev->mem_end = ei_status.rmem_end
 		= dev->mem_start + (ei_status.stop_page - START_PG)*256;
 
 	if (piomode) {
@@ -403,12 +403,12 @@
 	/* Enable shared memory. */
 	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
 		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
--- a/drivers/net/smc-ultra32.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/smc-ultra32.c	Sun Apr 14 12:16:57 2002
@@ -231,8 +231,8 @@
 	/* All Ultra32 cards have 32KB memory with an 8KB window. */
 	ei_status.stop_page = 128;
 
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = dev->rmem_end = dev->mem_start + 0x1fff;
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+	dev->mem_end = ei_status.rmem_end = dev->mem_start + 0x1fff;
 
 	printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n",
 	       dev->irq, dev->mem_start, dev->mem_end);
@@ -353,7 +353,7 @@
 		} else {
 			/* Select first 8KB Window. */
 			outb(ei_status.reg0, RamReg);
-			isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+			isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 		}
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
diff -Nru a/drivers/net/sonic.c b/drivers/net/sonic.c
--- a/drivers/net/sonic.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/sonic.c	Sun Apr 14 12:16:59 2002
@@ -620,3 +620,5 @@
 
 	return 0;
 }
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/strip.c b/drivers/net/strip.c
--- a/drivers/net/strip.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/strip.c	Sun Apr 14 12:16:56 2002
@@ -2080,6 +2080,7 @@
 #ifdef EXT_COUNTERS
         strip_info->rx_bytes += packetlen;
 #endif
+        skb->dev->last_rx = jiffies;
         netif_rx(skb);
     }
 }
diff -Nru a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/sun3_82586.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,1206 @@
+/*
+ * Sun3 i82586 Ethernet driver
+ *
+ * Cloned from ni52.c for the Sun3 by Sam Creasey (sammy@sammy.net)
+ *
+ * Original copyright follows:
+ * --------------------------
+ *
+ * net-3-driver for the NI5210 card (i82586 Ethernet chip)
+ *
+ * This is an extension to the Linux operating system, and is covered by the
+ * same Gnu Public License that covers that work.
+ *
+ * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later)
+ * Copyrights (c) 1994,1995,1996 by M.Hipp (hippm@informatik.uni-tuebingen.de)
+ * --------------------------
+ * 
+ * Consult ni52.c for further notes from the original driver.
+ *
+ * This incarnation currently supports the OBIO version of the i82586 chip 
+ * used in certain sun3 models.  It should be fairly doable to expand this
+ * to support VME if I should every acquire such a board.
+ *
+ */
+
+static int debuglevel = 0; /* debug-printk 0: off 1: a few 2: more */
+static int automatic_resume = 0; /* experimental .. better should be zero */
+static int rfdadd = 0; /* rfdadd=1 may be better for 8K MEM cards */
+static int fifo=0x8;	/* don't change */
+
+/* #define REALLY_SLOW_IO */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+#include <asm/sun3mmu.h>
+#include <asm/dvma.h>
+#include <asm/byteorder.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include "sun3_82586.h"
+
+#define DEBUG       /* debug on */
+#define SYSBUSVAL 0 /* 16 Bit */
+
+#define sun3_attn586()  {*(volatile unsigned char *)(dev->base_addr) |= IEOB_ATTEN; *(volatile unsigned char *)(dev->base_addr) &= ~IEOB_ATTEN;}
+#define sun3_reset586() {*(volatile unsigned char *)(dev->base_addr) = 0; udelay(100); *(volatile unsigned char *)(dev->base_addr) = IEOB_NORSET;}
+#define sun3_disint()   {*(volatile unsigned char *)(dev->base_addr) &= ~IEOB_IENAB;}
+#define sun3_enaint()   {*(volatile unsigned char *)(dev->base_addr) |= IEOB_IENAB;}
+#define sun3_active()   {*(volatile unsigned char *)(dev->base_addr) |= (IEOB_IENAB|IEOB_ONAIR|IEOB_NORSET);}
+
+#define make32(ptr16) (p->memtop + (swab16((unsigned short) (ptr16))) )
+#define make24(ptr32) (char *)swab32(( ((unsigned long) (ptr32)) - p->base))
+#define make16(ptr32) (swab16((unsigned short) ((unsigned long)(ptr32) - (unsigned long) p->memtop )))
+
+/******************* how to calculate the buffers *****************************
+
+  * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works
+  * --------------- in a different (more stable?) mode. Only in this mode it's
+  *                 possible to configure the driver with 'NO_NOPCOMMANDS'
+
+sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8;
+sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT
+sizeof(rfd) = 24; sizeof(rbd) = 12;
+sizeof(tbd) = 8; sizeof(transmit_cmd) = 16;
+sizeof(nop_cmd) = 8;
+
+  * if you don't know the driver, better do not change these values: */
+
+#define RECV_BUFF_SIZE 1536 /* slightly oversized */
+#define XMIT_BUFF_SIZE 1536 /* slightly oversized */
+#define NUM_XMIT_BUFFS 1    /* config for 32K shmem */
+#define NUM_RECV_BUFFS_8 4 /* config for 32K shared mem */
+#define NUM_RECV_BUFFS_16 9 /* config for 32K shared mem */
+#define NUM_RECV_BUFFS_32 16 /* config for 32K shared mem */
+#define NO_NOPCOMMANDS      /* only possible with NUM_XMIT_BUFFS=1 */
+
+/**************************************************************************/
+
+/* different DELAYs */
+#define DELAY(x) mdelay(32 * x);
+#define DELAY_16(); { udelay(16); }
+#define DELAY_18(); { udelay(4); }
+
+/* wait for command with timeout: */
+#define WAIT_4_SCB_CMD() \
+{ int i; \
+  for(i=0;i<16384;i++) { \
+    if(!p->scb->cmd_cuc) break; \
+    DELAY_18(); \
+    if(i == 16383) { \
+      printk("%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_cuc,p->scb->cus); \
+       if(!p->reseted) { p->reseted = 1; sun3_reset586(); } } } }
+
+#define WAIT_4_SCB_CMD_RUC() { int i; \
+  for(i=0;i<16384;i++) { \
+    if(!p->scb->cmd_ruc) break; \
+    DELAY_18(); \
+    if(i == 16383) { \
+      printk("%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_ruc,p->scb->rus); \
+       if(!p->reseted) { p->reseted = 1; sun3_reset586(); } } } }
+
+#define WAIT_4_STAT_COMPL(addr) { int i; \
+   for(i=0;i<32767;i++) { \
+     if(swab16((addr)->cmd_status) & STAT_COMPL) break; \
+     DELAY_16(); DELAY_16(); } }
+
+static int     sun3_82586_probe1(struct net_device *dev,int ioaddr);
+static void    sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr);
+static int     sun3_82586_open(struct net_device *dev);
+static int     sun3_82586_close(struct net_device *dev);
+static int     sun3_82586_send_packet(struct sk_buff *,struct net_device *);
+static struct  net_device_stats *sun3_82586_get_stats(struct net_device *dev);
+static void    set_multicast_list(struct net_device *dev);
+static void    sun3_82586_timeout(struct net_device *dev);
+#if 0
+static void    sun3_82586_dump(struct net_device *,void *);
+#endif
+
+/* helper-functions */
+static int     init586(struct net_device *dev);
+static int     check586(struct net_device *dev,char *where,unsigned size);
+static void    alloc586(struct net_device *dev);
+static void    startrecv586(struct net_device *dev);
+static void   *alloc_rfa(struct net_device *dev,void *ptr);
+static void    sun3_82586_rcv_int(struct net_device *dev);
+static void    sun3_82586_xmt_int(struct net_device *dev);
+static void    sun3_82586_rnr_int(struct net_device *dev);
+
+struct priv
+{
+	struct net_device_stats stats;
+	unsigned long base;
+	char *memtop;
+	long int lock;
+	int reseted;
+	volatile struct rfd_struct	*rfd_last,*rfd_top,*rfd_first;
+	volatile struct scp_struct	*scp;	/* volatile is important */
+	volatile struct iscp_struct	*iscp;	/* volatile is important */
+	volatile struct scb_struct	*scb;	/* volatile is important */
+	volatile struct tbd_struct	*xmit_buffs[NUM_XMIT_BUFFS];
+	volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS];
+#if (NUM_XMIT_BUFFS == 1)
+	volatile struct nop_cmd_struct *nop_cmds[2];
+#else
+	volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS];
+#endif
+	volatile int		nop_point,num_recv_buffs;
+	volatile char		*xmit_cbuffs[NUM_XMIT_BUFFS];
+	volatile int		xmit_count,xmit_last;
+};
+
+/**********************************************
+ * close device
+ */
+static int sun3_82586_close(struct net_device *dev)
+{
+	free_irq(dev->irq, dev);
+
+	sun3_reset586(); /* the hard way to stop the receiver */
+
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+/**********************************************
+ * open device
+ */
+static int sun3_82586_open(struct net_device *dev)
+{
+	int ret;
+
+	sun3_disint();
+	alloc586(dev);
+	init586(dev);
+	startrecv586(dev);
+	sun3_enaint();
+
+	ret = request_irq(dev->irq, &sun3_82586_interrupt,0,dev->name,dev);
+	if (ret)
+	{
+		sun3_reset586();
+		return ret;
+	}
+
+	netif_start_queue(dev);
+
+	return 0; /* most done by init */
+}
+
+/**********************************************
+ * Check to see if there's an 82586 out there.
+ */
+static int check586(struct net_device *dev,char *where,unsigned size)
+{
+	struct priv pb;
+	struct priv *p = /* (struct priv *) dev->priv*/ &pb;
+	char *iscp_addr;
+	int i;
+
+	p->base = (unsigned long) dvma_btov(0);
+	p->memtop = (char *)dvma_btov((unsigned long)where);
+	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
+	memset((char *)p->scp,0, sizeof(struct scp_struct));
+	for(i=0;i<sizeof(struct scp_struct);i++) /* memory was writeable? */
+		if(((char *)p->scp)[i])
+			return 0;
+	p->scp->sysbus = SYSBUSVAL;				/* 1 = 8Bit-Bus, 0 = 16 Bit */
+	if(p->scp->sysbus != SYSBUSVAL)
+		return 0;
+
+	iscp_addr = (char *)dvma_btov((unsigned long)where);
+	
+	p->iscp = (struct iscp_struct *) iscp_addr;
+	memset((char *)p->iscp,0, sizeof(struct iscp_struct));
+
+	p->scp->iscp = make24(p->iscp);
+	p->iscp->busy = 1;
+
+	sun3_reset586();
+	sun3_attn586();
+	DELAY(1);	/* wait a while... */
+	
+	if(p->iscp->busy) /* i82586 clears 'busy' after successful init */
+		return 0;
+
+	return 1;
+}
+
+/******************************************************************
+ * set iscp at the right place, called by sun3_82586_probe1 and open586.
+ */
+static void alloc586(struct net_device *dev)
+{
+	struct priv *p =	(struct priv *) dev->priv;
+
+	sun3_reset586();
+	DELAY(1);
+
+	p->scp	= (struct scp_struct *)	(p->base + SCP_DEFAULT_ADDRESS);
+	p->iscp	= (struct iscp_struct *) dvma_btov(dev->mem_start);
+	p->scb  = (struct scb_struct *)  ((char *)p->iscp + sizeof(struct iscp_struct));
+
+	memset((char *) p->iscp,0,sizeof(struct iscp_struct));
+	memset((char *) p->scp ,0,sizeof(struct scp_struct));
+
+	p->scp->iscp = make24(p->iscp);
+	p->scp->sysbus = SYSBUSVAL;
+	p->iscp->scb_offset = make16(p->scb);
+	p->iscp->scb_base = make24(dvma_btov(dev->mem_start));
+
+	p->iscp->busy = 1;
+	sun3_reset586();
+	sun3_attn586();
+
+	DELAY(1);
+
+	if(p->iscp->busy)
+		printk("%s: Init-Problems (alloc).\n",dev->name);
+
+	p->reseted = 0;
+
+	memset((char *)p->scb,0,sizeof(struct scb_struct));
+}
+
+int __init sun3_82586_probe(struct net_device *dev)
+{
+	unsigned long ioaddr, iopte;
+	static int found = 0;
+	
+	/* check that this machine has an onboard lance */
+	switch(idprom->id_machtype) {
+	case SM_SUN3|SM_3_160:
+	case SM_SUN3|SM_3_260:
+		/* these machines have lance */
+		break;
+
+	default:
+		return(-ENODEV);
+	}
+
+	if(found)
+		return -ENODEV;
+	
+	for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 +
+	    SUN3_PMEG_SIZE); ioaddr += SUN3_PTE_SIZE) {
+
+		iopte = sun3_get_pte(ioaddr);
+		if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
+			continue;
+
+		if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
+		   IE_OBIO) {
+			found = 1;
+			break;
+		}
+	}
+	
+	if(!found)
+		return 0;
+	
+	SET_MODULE_OWNER(dev);
+
+	dev->irq = IE_IRQ;
+	dev->base_addr = ioaddr;
+	if(sun3_82586_probe1(dev, ioaddr) == 0)
+		return 0;
+
+	return -ENODEV;
+}
+
+static int __init sun3_82586_probe1(struct net_device *dev,int ioaddr)
+{
+	int i, size, retval;
+
+//	if (!request_region(ioaddr, SUN3_82586_TOTAL_SIZE, dev->name))
+//		return -EBUSY;
+
+	/* copy in the ethernet address from the prom */
+	for(i = 0; i < 6 ; i++)
+	     dev->dev_addr[i] = idprom->id_ethaddr[i];
+
+	printk("%s: SUN3 Intel 82586 found at %lx, ",dev->name,dev->base_addr);
+
+	/*
+	 * check (or search) IO-Memory, 32K
+	 */
+	size = 0x8000;
+
+	dev->mem_start = (unsigned long)dvma_malloc_align(0x8000, 0x1000);
+	dev->mem_end = dev->mem_start + size;
+
+	if(size != 0x2000 && size != 0x4000 && size != 0x8000) {
+		printk("\n%s: Illegal memory size %d. Allowed is 0x2000 or 0x4000 or 0x8000 bytes.\n",dev->name,size);
+		retval = -ENODEV;
+		goto out;
+	}
+	if(!check586(dev,(char *) dev->mem_start,size)) {
+		printk("?memcheck, Can't find memory at 0x%lx with size %d!\n",dev->mem_start,size);
+		retval = -ENODEV;
+		goto out;
+	}
+
+	dev->priv = (void *) kmalloc(sizeof(struct priv),GFP_KERNEL);
+	if(dev->priv == NULL) {
+		printk("%s: Ooops .. can't allocate private driver memory.\n",dev->name);
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	/* warning: we don't free it on errors */
+	memset((char *) dev->priv,0,sizeof(struct priv));
+
+	((struct priv *) (dev->priv))->memtop = (char *)dvma_btov(dev->mem_start);
+	((struct priv *) (dev->priv))->base = (unsigned long) dvma_btov(0);
+	alloc586(dev);
+
+	/* set number of receive-buffs according to memsize */
+	if(size == 0x2000)
+		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
+	else if(size == 0x4000)
+		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
+	else
+		((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_32;
+
+	printk("Memaddr: 0x%lx, Memsize: %d, IRQ %d\n",dev->mem_start,size, dev->irq);
+	
+	dev->open		= sun3_82586_open;
+	dev->stop		= sun3_82586_close;
+	dev->get_stats		= sun3_82586_get_stats;
+	dev->tx_timeout 	= sun3_82586_timeout;
+	dev->watchdog_timeo	= HZ/20;
+	dev->hard_start_xmit 	= sun3_82586_send_packet;
+	dev->set_multicast_list = set_multicast_list;
+
+	dev->if_port 		= 0;
+
+	ether_setup(dev);
+
+	return 0;
+out:
+	return retval;
+}
+
+
+static int init586(struct net_device *dev)
+{
+	void *ptr;
+	int i,result=0;
+	struct priv *p = (struct priv *) dev->priv;
+	volatile struct configure_cmd_struct	*cfg_cmd;
+	volatile struct iasetup_cmd_struct *ias_cmd;
+	volatile struct tdr_cmd_struct *tdr_cmd;
+	volatile struct mcsetup_cmd_struct *mc_cmd;
+	struct dev_mc_list *dmi=dev->mc_list;
+	int num_addrs=dev->mc_count;
+
+	ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
+
+	cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */
+	cfg_cmd->cmd_status	= 0;
+	cfg_cmd->cmd_cmd	= swab16(CMD_CONFIGURE | CMD_LAST);
+	cfg_cmd->cmd_link	= 0xffff;
+
+	cfg_cmd->byte_cnt	= 0x0a; /* number of cfg bytes */
+	cfg_cmd->fifo		= fifo; /* fifo-limit (8=tx:32/rx:64) */
+	cfg_cmd->sav_bf		= 0x40; /* hold or discard bad recv frames (bit 7) */
+	cfg_cmd->adr_len	= 0x2e; /* addr_len |!src_insert |pre-len |loopback */
+	cfg_cmd->priority	= 0x00;
+	cfg_cmd->ifs		= 0x60;
+	cfg_cmd->time_low	= 0x00;
+	cfg_cmd->time_high	= 0xf2;
+	cfg_cmd->promisc	= 0;
+	if(dev->flags & IFF_ALLMULTI) {
+		int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
+		if(num_addrs > len)	{
+			printk("%s: switching to promisc. mode\n",dev->name);
+			dev->flags|=IFF_PROMISC;
+		}
+	}
+	if(dev->flags&IFF_PROMISC)
+	{
+			 cfg_cmd->promisc=1;
+			 dev->flags|=IFF_PROMISC;
+	}
+	cfg_cmd->carr_coll	= 0x00;
+
+	p->scb->cbl_offset	= make16(cfg_cmd);
+	p->scb->cmd_ruc		= 0;
+
+	p->scb->cmd_cuc		= CUC_START; /* cmd.-unit start */
+	sun3_attn586();
+
+	WAIT_4_STAT_COMPL(cfg_cmd);
+
+	if((swab16(cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK))
+	{
+		printk("%s: configure command failed: %x\n",dev->name,swab16(cfg_cmd->cmd_status));
+		return 1;
+	}
+
+	/*
+	 * individual address setup
+	 */
+
+	ias_cmd = (struct iasetup_cmd_struct *)ptr;
+
+	ias_cmd->cmd_status	= 0;
+	ias_cmd->cmd_cmd	= swab16(CMD_IASETUP | CMD_LAST);
+	ias_cmd->cmd_link	= 0xffff;
+
+	memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN);
+
+	p->scb->cbl_offset = make16(ias_cmd);
+
+	p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */
+	sun3_attn586();
+
+	WAIT_4_STAT_COMPL(ias_cmd);
+
+	if((swab16(ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) {
+		printk("%s (82586): individual address setup command failed: %04x\n",dev->name,swab16(ias_cmd->cmd_status));
+		return 1;
+	}
+
+	/*
+	 * TDR, wire check .. e.g. no resistor e.t.c
+	 */
+	 
+	tdr_cmd = (struct tdr_cmd_struct *)ptr;
+
+	tdr_cmd->cmd_status	= 0;
+	tdr_cmd->cmd_cmd	= swab16(CMD_TDR | CMD_LAST);
+	tdr_cmd->cmd_link	= 0xffff;
+	tdr_cmd->status		= 0;
+
+	p->scb->cbl_offset = make16(tdr_cmd);
+	p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */
+	sun3_attn586();
+
+	WAIT_4_STAT_COMPL(tdr_cmd);
+
+	if(!(swab16(tdr_cmd->cmd_status) & STAT_COMPL))
+	{
+		printk("%s: Problems while running the TDR.\n",dev->name);
+	}
+	else
+	{
+		DELAY_16(); /* wait for result */
+		result = swab16(tdr_cmd->status);
+
+		p->scb->cmd_cuc = p->scb->cus & STAT_MASK;
+		sun3_attn586(); /* ack the interrupts */
+
+		if(result & TDR_LNK_OK)
+			;
+		else if(result & TDR_XCVR_PRB)
+			printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name);
+		else if(result & TDR_ET_OPN)
+			printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
+		else if(result & TDR_ET_SRT)
+		{
+			if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */
+				printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK);
+		}
+		else
+			printk("%s: TDR: Unknown status %04x\n",dev->name,result);
+	}
+
+	/*
+	 * Multicast setup
+	 */
+	if(num_addrs && !(dev->flags & IFF_PROMISC) )
+	{
+		mc_cmd = (struct mcsetup_cmd_struct *) ptr;
+		mc_cmd->cmd_status = 0;
+		mc_cmd->cmd_cmd = swab16(CMD_MCSETUP | CMD_LAST);
+		mc_cmd->cmd_link = 0xffff;
+		mc_cmd->mc_cnt = swab16(num_addrs * 6);
+
+		for(i=0;i<num_addrs;i++,dmi=dmi->next)
+			memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6);
+
+		p->scb->cbl_offset = make16(mc_cmd);
+		p->scb->cmd_cuc = CUC_START;
+		sun3_attn586();
+
+		WAIT_4_STAT_COMPL(mc_cmd);
+
+		if( (swab16(mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) )
+			printk("%s: Can't apply multicast-address-list.\n",dev->name);
+	}
+
+	/*
+	 * alloc nop/xmit-cmds
+	 */
+#if (NUM_XMIT_BUFFS == 1)
+	for(i=0;i<2;i++)
+	{
+		p->nop_cmds[i] 			= (struct nop_cmd_struct *)ptr;
+		p->nop_cmds[i]->cmd_cmd		= swab16(CMD_NOP);
+		p->nop_cmds[i]->cmd_status 	= 0;
+		p->nop_cmds[i]->cmd_link	= make16((p->nop_cmds[i]));
+		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
+	}
+#else
+	for(i=0;i<NUM_XMIT_BUFFS;i++)
+	{
+		p->nop_cmds[i]			= (struct nop_cmd_struct *)ptr;
+		p->nop_cmds[i]->cmd_cmd		= swab16(CMD_NOP);
+		p->nop_cmds[i]->cmd_status	= 0;
+		p->nop_cmds[i]->cmd_link	= make16((p->nop_cmds[i]));
+		ptr = (char *) ptr + sizeof(struct nop_cmd_struct);
+	}
+#endif
+
+	ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */
+
+	/*
+	 * alloc xmit-buffs / init xmit_cmds
+	 */
+	for(i=0;i<NUM_XMIT_BUFFS;i++)
+	{
+		p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/
+		ptr = (char *) ptr + sizeof(struct transmit_cmd_struct);
+		p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */
+		ptr = (char *) ptr + XMIT_BUFF_SIZE;
+		p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */
+		ptr = (char *) ptr + sizeof(struct tbd_struct);
+		if((void *)ptr > (void *)dev->mem_end)
+		{
+			printk("%s: not enough shared-mem for your configuration!\n",dev->name);
+			return 1;
+		}
+		memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct));
+		memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct));
+		p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]);
+		p->xmit_cmds[i]->cmd_status = swab16(STAT_COMPL);
+		p->xmit_cmds[i]->cmd_cmd = swab16(CMD_XMIT | CMD_INT);
+		p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i]));
+		p->xmit_buffs[i]->next = 0xffff;
+		p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i]));
+	}
+
+	p->xmit_count = 0;
+	p->xmit_last	= 0;
+#ifndef NO_NOPCOMMANDS
+	p->nop_point	= 0;
+#endif
+
+	 /*
+		* 'start transmitter'
+		*/
+#ifndef NO_NOPCOMMANDS
+	p->scb->cbl_offset = make16(p->nop_cmds[0]);
+	p->scb->cmd_cuc = CUC_START;
+	sun3_attn586();
+	WAIT_4_SCB_CMD();
+#else
+	p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]);
+	p->xmit_cmds[0]->cmd_cmd	= swab16(CMD_XMIT | CMD_SUSPEND | CMD_INT);
+#endif
+
+	/*
+	 * ack. interrupts
+	 */
+	p->scb->cmd_cuc = p->scb->cus & STAT_MASK;
+	sun3_attn586();
+	DELAY_16();
+
+	sun3_enaint();
+	sun3_active();
+
+	return 0;
+}
+
+/******************************************************
+ * This is a helper routine for sun3_82586_rnr_int() and init586().
+ * It sets up the Receive Frame Area (RFA).
+ */
+
+static void *alloc_rfa(struct net_device *dev,void *ptr)
+{
+	volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr;
+	volatile struct rbd_struct *rbd;
+	int i;
+	struct priv *p = (struct priv *) dev->priv;
+
+	memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd));
+	p->rfd_first = rfd;
+
+	for(i = 0; i < (p->num_recv_buffs+rfdadd); i++) {
+		rfd[i].next = make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd) );
+		rfd[i].rbd_offset = 0xffff;
+	}
+	rfd[p->num_recv_buffs-1+rfdadd].last = RFD_SUSP;	 /* RU suspend */
+
+	ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd) );
+
+	rbd = (struct rbd_struct *) ptr;
+	ptr = (void *) (rbd + p->num_recv_buffs);
+
+	 /* clr descriptors */
+	memset((char *) rbd,0,sizeof(struct rbd_struct)*(p->num_recv_buffs));
+
+	for(i=0;i<p->num_recv_buffs;i++)
+	{
+		rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs));
+		rbd[i].size = swab16(RECV_BUFF_SIZE);
+		rbd[i].buffer = make24(ptr);
+		ptr = (char *) ptr + RECV_BUFF_SIZE;
+	}
+
+	p->rfd_top	= p->rfd_first;
+	p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd);
+
+	p->scb->rfa_offset		= make16(p->rfd_first);
+	p->rfd_first->rbd_offset	= make16(rbd);
+
+	return ptr;
+}
+
+
+/**************************************************
+ * Interrupt Handler ...
+ */
+
+static void sun3_82586_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
+{
+	struct net_device *dev = dev_id;
+	unsigned short stat;
+	int cnt=0;
+	struct priv *p;
+
+	if (!dev) {
+		printk ("sun3_82586-interrupt: irq %d for unknown device.\n",irq);
+		return;
+	}
+	p = (struct priv *) dev->priv;
+
+	if(debuglevel > 1)
+		printk("I");
+
+	WAIT_4_SCB_CMD(); /* wait for last command	*/
+
+	while((stat=p->scb->cus & STAT_MASK))
+	{
+		p->scb->cmd_cuc = stat;
+		sun3_attn586();
+
+		if(stat & STAT_FR)	 /* received a frame */
+			sun3_82586_rcv_int(dev);
+
+		if(stat & STAT_RNR) /* RU went 'not ready' */
+		{
+			printk("(R)");
+			if(p->scb->rus & RU_SUSPEND) /* special case: RU_SUSPEND */
+			{
+				WAIT_4_SCB_CMD();
+				p->scb->cmd_ruc = RUC_RESUME;
+				sun3_attn586();
+				WAIT_4_SCB_CMD_RUC();
+			}
+			else
+			{
+				printk("%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->rus);
+				sun3_82586_rnr_int(dev);
+			}
+		}
+
+		if(stat & STAT_CX)		/* command with I-bit set complete */
+			 sun3_82586_xmt_int(dev);
+
+#ifndef NO_NOPCOMMANDS
+		if(stat & STAT_CNA)	/* CU went 'not ready' */
+		{
+			if(netif_running(dev))
+				printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus);
+		}
+#endif
+
+		if(debuglevel > 1)
+			printk("%d",cnt++);
+
+		WAIT_4_SCB_CMD(); /* wait for ack. (sun3_82586_xmt_int can be faster than ack!!) */
+		if(p->scb->cmd_cuc)	 /* timed out? */
+		{
+			printk("%s: Acknowledge timed out.\n",dev->name);
+			sun3_disint();
+			break;
+		}
+	}
+
+	if(debuglevel > 1)
+		printk("i");
+}
+
+/*******************************************************
+ * receive-interrupt
+ */
+
+static void sun3_82586_rcv_int(struct net_device *dev)
+{
+	int status,cnt=0;
+	unsigned short totlen;
+	struct sk_buff *skb;
+	struct rbd_struct *rbd;
+	struct priv *p = (struct priv *) dev->priv;
+
+	if(debuglevel > 0)
+		printk("R");
+
+	for(;(status = p->rfd_top->stat_high) & RFD_COMPL;)
+	{
+			rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
+
+			if(status & RFD_OK) /* frame received without error? */
+			{
+				if( (totlen = swab16(rbd->status)) & RBD_LAST) /* the first and the last buffer? */
+				{
+					totlen &= RBD_MASK; /* length of this frame */
+					rbd->status = 0;
+					skb = (struct sk_buff *) dev_alloc_skb(totlen+2);
+					if(skb != NULL)
+					{
+						skb->dev = dev;
+						skb_reserve(skb,2);
+						skb_put(skb,totlen);
+						eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0);
+						skb->protocol=eth_type_trans(skb,dev);
+						netif_rx(skb);
+						p->stats.rx_packets++;
+					}
+					else
+						p->stats.rx_dropped++;
+				}
+				else
+				{
+					int rstat;
+						 /* free all RBD's until RBD_LAST is set */
+					totlen = 0;
+					while(!((rstat=swab16(rbd->status)) & RBD_LAST))
+					{
+						totlen += rstat & RBD_MASK;
+						if(!rstat)
+						{
+							printk("%s: Whoops .. no end mark in RBD list\n",dev->name);
+							break;
+						}
+						rbd->status = 0;
+						rbd = (struct rbd_struct *) make32(rbd->next);
+					}
+					totlen += rstat & RBD_MASK;
+					rbd->status = 0;
+					printk("%s: received oversized frame! length: %d\n",dev->name,totlen);
+					p->stats.rx_dropped++;
+			 }
+		}
+		else /* frame !(ok), only with 'save-bad-frames' */
+		{
+			printk("%s: oops! rfd-error-status: %04x\n",dev->name,status);
+			p->stats.rx_errors++;
+		}
+		p->rfd_top->stat_high = 0;
+		p->rfd_top->last = RFD_SUSP; /* maybe exchange by RFD_LAST */
+		p->rfd_top->rbd_offset = 0xffff;
+		p->rfd_last->last = 0;				/* delete RFD_SUSP	*/
+		p->rfd_last = p->rfd_top;
+		p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */
+		p->scb->rfa_offset = make16(p->rfd_top);
+
+		if(debuglevel > 0)
+			printk("%d",cnt++);
+	}
+
+	if(automatic_resume)
+	{
+		WAIT_4_SCB_CMD();
+		p->scb->cmd_ruc = RUC_RESUME;
+		sun3_attn586();
+		WAIT_4_SCB_CMD_RUC();
+	}
+
+#ifdef WAIT_4_BUSY
+	{
+		int i;
+		for(i=0;i<1024;i++)
+		{
+			if(p->rfd_top->status)
+				break;
+			DELAY_16();
+			if(i == 1023)
+				printk("%s: RU hasn't fetched next RFD (not busy/complete)\n",dev->name);
+		}
+	}
+#endif
+
+#if 0
+	if(!at_least_one)
+	{
+		int i;
+		volatile struct rfd_struct *rfds=p->rfd_top;
+		volatile struct rbd_struct *rbds;
+		printk("%s: received a FC intr. without having a frame: %04x %d\n",dev->name,status,old_at_least);
+		for(i=0;i< (p->num_recv_buffs+4);i++)
+		{
+			rbds = (struct rbd_struct *) make32(rfds->rbd_offset);
+			printk("%04x:%04x ",rfds->status,rbds->status);
+			rfds = (struct rfd_struct *) make32(rfds->next);
+		}
+		printk("\nerrs: %04x %04x stat: %04x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->status);
+		printk("\nerrs: %04x %04x rus: %02x, cus: %02x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->rus,(int)p->scb->cus);
+	}
+	old_at_least = at_least_one;
+#endif
+
+	if(debuglevel > 0)
+		printk("r");
+}
+
+/**********************************************************
+ * handle 'Receiver went not ready'.
+ */
+
+static void sun3_82586_rnr_int(struct net_device *dev)
+{
+	struct priv *p = (struct priv *) dev->priv;
+
+	p->stats.rx_errors++;
+
+	WAIT_4_SCB_CMD();		/* wait for the last cmd, WAIT_4_FULLSTAT?? */
+	p->scb->cmd_ruc = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */
+	sun3_attn586();
+	WAIT_4_SCB_CMD_RUC();		/* wait for accept cmd. */
+
+	alloc_rfa(dev,(char *)p->rfd_first);
+/* maybe add a check here, before restarting the RU */
+	startrecv586(dev); /* restart RU */
+
+	printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->rus);
+
+}
+
+/**********************************************************
+ * handle xmit - interrupt
+ */
+
+static void sun3_82586_xmt_int(struct net_device *dev)
+{
+	int status;
+	struct priv *p = (struct priv *) dev->priv;
+
+	if(debuglevel > 0)
+		printk("X");
+
+	status = swab16(p->xmit_cmds[p->xmit_last]->cmd_status);
+	if(!(status & STAT_COMPL))
+		printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name);
+
+	if(status & STAT_OK)
+	{
+		p->stats.tx_packets++;
+		p->stats.collisions += (status & TCMD_MAXCOLLMASK);
+	}
+	else
+	{
+		p->stats.tx_errors++;
+		if(status & TCMD_LATECOLL) {
+			printk("%s: late collision detected.\n",dev->name);
+			p->stats.collisions++;
+		}
+		else if(status & TCMD_NOCARRIER) {
+			p->stats.tx_carrier_errors++;
+			printk("%s: no carrier detected.\n",dev->name);
+		}
+		else if(status & TCMD_LOSTCTS)
+			printk("%s: loss of CTS detected.\n",dev->name);
+		else if(status & TCMD_UNDERRUN) {
+			p->stats.tx_fifo_errors++;
+			printk("%s: DMA underrun detected.\n",dev->name);
+		}
+		else if(status & TCMD_MAXCOLL) {
+			printk("%s: Max. collisions exceeded.\n",dev->name);
+			p->stats.collisions += 16;
+		}
+	}
+
+#if (NUM_XMIT_BUFFS > 1)
+	if( (++p->xmit_last) == NUM_XMIT_BUFFS)
+		p->xmit_last = 0;
+#endif
+	netif_wake_queue(dev);
+}
+
+/***********************************************************
+ * (re)start the receiver
+ */
+
+static void startrecv586(struct net_device *dev)
+{
+	struct priv *p = (struct priv *) dev->priv;
+
+	WAIT_4_SCB_CMD();
+	WAIT_4_SCB_CMD_RUC();
+	p->scb->rfa_offset = make16(p->rfd_first);
+	p->scb->cmd_ruc = RUC_START;
+	sun3_attn586();		/* start cmd. */
+	WAIT_4_SCB_CMD_RUC();	/* wait for accept cmd. (no timeout!!) */
+}
+
+static void sun3_82586_timeout(struct net_device *dev)
+{
+	struct priv *p = (struct priv *) dev->priv;
+#ifndef NO_NOPCOMMANDS
+	if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */
+	{
+		netif_wake_queue(dev);
+#ifdef DEBUG
+		printk("%s: strange ... timeout with CU active?!?\n",dev->name);
+		printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)swab16(p->xmit_cmds[0]->cmd_status),(int)swab16(p->nop_cmds[0]->cmd_status),(int)swab16(p->nop_cmds[1]->cmd_status),(int)p->nop_point);
+#endif
+		p->scb->cmd_cuc = CUC_ABORT;
+		sun3_attn586();
+		WAIT_4_SCB_CMD();
+		p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
+		p->scb->cmd_cuc = CUC_START;
+		sun3_attn586();
+		WAIT_4_SCB_CMD();
+		dev->trans_start = jiffies;
+		return 0;
+	}
+#endif
+	{
+#ifdef DEBUG
+		printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
+		printk("%s: command-stats: %04x %04x\n",dev->name,swab16(p->xmit_cmds[0]->cmd_status),swab16(p->xmit_cmds[1]->cmd_status));
+		printk("%s: check, whether you set the right interrupt number!\n",dev->name);
+#endif
+		sun3_82586_close(dev);
+		sun3_82586_open(dev);
+	}
+	dev->trans_start = jiffies;
+}
+
+/******************************************************
+ * send frame
+ */
+
+static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	int len,i;
+#ifndef NO_NOPCOMMANDS
+	int next_nop;
+#endif
+	struct priv *p = (struct priv *) dev->priv;
+
+	if(skb->len > XMIT_BUFF_SIZE)
+	{
+		printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
+		return 0;
+	}
+
+	netif_stop_queue(dev);
+
+#if(NUM_XMIT_BUFFS > 1)
+	if(test_and_set_bit(0,(void *) &p->lock)) {
+		printk("%s: Queue was locked\n",dev->name);
+		return 1;
+	}
+	else
+#endif
+	{
+		memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
+		len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+
+#if (NUM_XMIT_BUFFS == 1)
+#	ifdef NO_NOPCOMMANDS
+
+#ifdef DEBUG
+		if(p->scb->cus & CU_ACTIVE)
+		{
+			printk("%s: Hmmm .. CU is still running and we wanna send a new packet.\n",dev->name);
+			printk("%s: stat: %04x %04x\n",dev->name,p->scb->cus,swab16(p->xmit_cmds[0]->cmd_status));
+		}
+#endif
+
+		p->xmit_buffs[0]->size = swab16(TBD_LAST | len);
+		for(i=0;i<16;i++)
+		{
+			p->xmit_cmds[0]->cmd_status = 0;
+			WAIT_4_SCB_CMD();
+			if( (p->scb->cus & CU_STATUS) == CU_SUSPEND)
+				p->scb->cmd_cuc = CUC_RESUME;
+			else
+			{
+				p->scb->cbl_offset = make16(p->xmit_cmds[0]);
+				p->scb->cmd_cuc = CUC_START;
+			}
+
+			sun3_attn586();
+			dev->trans_start = jiffies;
+			if(!i)
+				dev_kfree_skb(skb);
+			WAIT_4_SCB_CMD();
+			if( (p->scb->cus & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */
+				break;
+			if(p->xmit_cmds[0]->cmd_status)
+				break;
+			if(i==15)
+				printk("%s: Can't start transmit-command.\n",dev->name);
+		}
+#	else
+		next_nop = (p->nop_point + 1) & 0x1;
+		p->xmit_buffs[0]->size = swab16(TBD_LAST | len);
+
+		p->xmit_cmds[0]->cmd_link	 = p->nop_cmds[next_nop]->cmd_link
+			= make16((p->nop_cmds[next_nop]));
+		p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
+
+		p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
+		dev->trans_start = jiffies;
+		p->nop_point = next_nop;
+		dev_kfree_skb(skb);
+#	endif
+#else
+		p->xmit_buffs[p->xmit_count]->size = swab16(TBD_LAST | len);
+		if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS )
+			next_nop = 0;
+
+		p->xmit_cmds[p->xmit_count]->cmd_status	= 0;
+		/* linkpointer of xmit-command already points to next nop cmd */
+		p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop]));
+		p->nop_cmds[next_nop]->cmd_status = 0;
+
+		p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
+		dev->trans_start = jiffies;
+		p->xmit_count = next_nop;
+
+		{
+			unsigned long flags;
+			save_flags(flags);
+			cli();
+			if(p->xmit_count != p->xmit_last)
+				netif_wake_queue(dev);
+			p->lock = 0;
+			restore_flags(flags);
+		}
+		dev_kfree_skb(skb);
+#endif
+	}
+	return 0;
+}
+
+/*******************************************
+ * Someone wanna have the statistics
+ */
+
+static struct net_device_stats *sun3_82586_get_stats(struct net_device *dev)
+{
+	struct priv *p = (struct priv *) dev->priv;
+	unsigned short crc,aln,rsc,ovrn;
+
+	crc = swab16(p->scb->crc_errs); /* get error-statistic from the ni82586 */
+	p->scb->crc_errs = 0;
+	aln = swab16(p->scb->aln_errs);
+	p->scb->aln_errs = 0;
+	rsc = swab16(p->scb->rsc_errs);
+	p->scb->rsc_errs = 0;
+	ovrn = swab16(p->scb->ovrn_errs);
+	p->scb->ovrn_errs = 0;
+
+	p->stats.rx_crc_errors += crc;
+	p->stats.rx_fifo_errors += ovrn;
+	p->stats.rx_frame_errors += aln;
+	p->stats.rx_dropped += rsc;
+
+	return &p->stats;
+}
+
+/********************************************************
+ * Set MC list ..
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	sun3_disint();
+	alloc586(dev);
+	init586(dev);
+	startrecv586(dev);
+	sun3_enaint();
+	netif_wake_queue(dev);
+}
+
+#ifdef MODULE
+#error This code is not currently supported as a module
+static struct net_device dev_sun3_82586;
+
+int init_module(void)
+{
+	dev_sun3_82586.init = sun3_82586_probe;
+	if (register_netdev(&dev_sun3_82586) != 0)
+		return -EIO;
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	unregister_netdev(&dev_sun3_82586);
+	kfree(dev_sun3_82586.priv);
+	dev_sun3_82586.priv = NULL;
+}
+#endif /* MODULE */
+
+#if 0
+/*
+ * DUMP .. we expect a not running CMD unit and enough space
+ */
+void sun3_82586_dump(struct net_device *dev,void *ptr)
+{
+	struct priv *p = (struct priv *) dev->priv;
+	struct dump_cmd_struct *dump_cmd = (struct dump_cmd_struct *) ptr;
+	int i;
+
+	p->scb->cmd_cuc = CUC_ABORT;
+	sun3_attn586();
+	WAIT_4_SCB_CMD();
+	WAIT_4_SCB_CMD_RUC();
+
+	dump_cmd->cmd_status = 0;
+	dump_cmd->cmd_cmd = CMD_DUMP | CMD_LAST;
+	dump_cmd->dump_offset = make16((dump_cmd + 1));
+	dump_cmd->cmd_link = 0xffff;
+
+	p->scb->cbl_offset = make16(dump_cmd);
+	p->scb->cmd_cuc = CUC_START;
+	sun3_attn586();
+	WAIT_4_STAT_COMPL(dump_cmd);
+
+	if( (dump_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) )
+				printk("%s: Can't get dump information.\n",dev->name);
+
+	for(i=0;i<170;i++) {
+		printk("%02x ",(int) ((unsigned char *) (dump_cmd + 1))[i]);
+		if(i % 24 == 23)
+			printk("\n");
+	}
+	printk("\n");
+}
+#endif
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/net/sun3_82586.h b/drivers/net/sun3_82586.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/sun3_82586.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,318 @@
+/*
+ * Intel i82586 Ethernet definitions
+ *
+ * This is an extension to the Linux operating system, and is covered by the
+ * same Gnu Public License that covers that work.
+ *
+ * copyrights (c) 1994 by Michael Hipp (hippm@informatik.uni-tuebingen.de)
+ *
+ * I have done a look in the following sources:
+ *   crynwr-packet-driver by Russ Nelson
+ *   Garret A. Wollman's i82586-driver for BSD
+ */
+
+/*
+ * Cloned from ni52.h, copyright as above.  
+ *
+ * Modified for Sun3 OBIO i82586 by Sam Creasey (sammy@sammy.net)
+ */
+
+
+/* defines for the obio chip (not vme) */ 
+#define IEOB_NORSET 0x80        /* don't reset the board */
+#define IEOB_ONAIR  0x40        /* put us on the air */
+#define IEOB_ATTEN  0x20        /* attention! */
+#define IEOB_IENAB  0x10        /* interrupt enable */
+#define IEOB_XXXXX  0x08        /* free bit */
+#define IEOB_XCVRL2 0x04        /* level 2 transceiver? */
+#define IEOB_BUSERR 0x02        /* bus error */
+#define IEOB_INT    0x01        /* interrupt */
+
+/* where the obio one lives */
+#define IE_OBIO 0xc0000
+#define IE_IRQ 3
+
+/*
+ * where to find the System Configuration Pointer (SCP)
+ */
+#define SCP_DEFAULT_ADDRESS 0xfffff4
+
+
+/*
+ * System Configuration Pointer Struct
+ */
+
+struct scp_struct
+{
+  unsigned short zero_dum0;	/* has to be zero */
+  unsigned char  sysbus;	/* 0=16Bit,1=8Bit */
+  unsigned char  zero_dum1;	/* has to be zero for 586 */
+  unsigned short zero_dum2;
+  unsigned short zero_dum3;
+  char          *iscp;		/* pointer to the iscp-block */
+};
+
+
+/*
+ * Intermediate System Configuration Pointer (ISCP)
+ */
+struct iscp_struct
+{
+  unsigned char  busy;          /* 586 clears after successful init */
+  unsigned char  zero_dummy;    /* has to be zero */
+  unsigned short scb_offset;    /* pointeroffset to the scb_base */
+  char          *scb_base;      /* base-address of all 16-bit offsets */
+};
+
+/*
+ * System Control Block (SCB)
+ */
+struct scb_struct
+{
+  unsigned char rus;
+  unsigned char cus;
+  unsigned char cmd_ruc;           /* command word: RU part */
+  unsigned char cmd_cuc;           /* command word: CU part & ACK */
+  unsigned short cbl_offset;    /* pointeroffset, command block list */
+  unsigned short rfa_offset;    /* pointeroffset, receive frame area */
+  unsigned short crc_errs;      /* CRC-Error counter */
+  unsigned short aln_errs;      /* allignmenterror counter */
+  unsigned short rsc_errs;      /* Resourceerror counter */
+  unsigned short ovrn_errs;     /* OVerrunerror counter */
+};
+
+/*
+ * possible command values for the command word
+ */
+#define RUC_MASK	0x0070	/* mask for RU commands */
+#define RUC_NOP		0x0000	/* NOP-command */
+#define RUC_START	0x0010	/* start RU */
+#define RUC_RESUME	0x0020	/* resume RU after suspend */
+#define RUC_SUSPEND	0x0030	/* suspend RU */
+#define RUC_ABORT	0x0040	/* abort receiver operation immediately */
+
+#define CUC_MASK        0x07  /* mask for CU command */
+#define CUC_NOP         0x00  /* NOP-command */
+#define CUC_START       0x01  /* start execution of 1. cmd on the CBL */
+#define CUC_RESUME      0x02  /* resume after suspend */
+#define CUC_SUSPEND     0x03  /* Suspend CU */
+#define CUC_ABORT       0x04  /* abort command operation immediately */
+
+#define ACK_MASK        0xf0  /* mask for ACK command */
+#define ACK_CX          0x80  /* acknowledges STAT_CX */
+#define ACK_FR          0x40  /* ack. STAT_FR */
+#define ACK_CNA         0x20  /* ack. STAT_CNA */
+#define ACK_RNR         0x10  /* ack. STAT_RNR */
+
+/*
+ * possible status values for the status word
+ */
+#define STAT_MASK       0xf0  /* mask for cause of interrupt */
+#define STAT_CX         0x80  /* CU finished cmd with its I bit set */
+#define STAT_FR         0x40  /* RU finished receiving a frame */
+#define STAT_CNA        0x20  /* CU left active state */
+#define STAT_RNR        0x10  /* RU left ready state */
+
+#define CU_STATUS       0x7   /* CU status, 0=idle */
+#define CU_SUSPEND      0x1   /* CU is suspended */
+#define CU_ACTIVE       0x2   /* CU is active */
+
+#define RU_STATUS	0x70	/* RU status, 0=idle */
+#define RU_SUSPEND	0x10	/* RU suspended */
+#define RU_NOSPACE	0x20	/* RU no resources */
+#define RU_READY	0x40	/* RU is ready */
+
+/*
+ * Receive Frame Descriptor (RFD)
+ */
+struct rfd_struct
+{
+  unsigned char  stat_low;	/* status word */
+  unsigned char  stat_high;	/* status word */
+  unsigned char  rfd_sf;	/* 82596 mode only */
+  unsigned char  last;		/* Bit15,Last Frame on List / Bit14,suspend */
+  unsigned short next;		/* linkoffset to next RFD */
+  unsigned short rbd_offset;	/* pointeroffset to RBD-buffer */
+  unsigned char  dest[6];	/* ethernet-address, destination */
+  unsigned char  source[6];	/* ethernet-address, source */
+  unsigned short length;	/* 802.3 frame-length */
+  unsigned short zero_dummy;	/* dummy */
+};
+
+#define RFD_LAST     0x80	/* last: last rfd in the list */
+#define RFD_SUSP     0x40	/* last: suspend RU after  */
+#define RFD_COMPL    0x80
+#define RFD_OK       0x20
+#define RFD_BUSY     0x40
+#define RFD_ERR_LEN  0x10     /* Length error (if enabled length-checking */
+#define RFD_ERR_CRC  0x08     /* CRC error */
+#define RFD_ERR_ALGN 0x04     /* Alignment error */
+#define RFD_ERR_RNR  0x02     /* status: receiver out of resources */
+#define RFD_ERR_OVR  0x01     /* DMA Overrun! */
+
+#define RFD_ERR_FTS  0x0080	/* Frame to short */
+#define RFD_ERR_NEOP 0x0040	/* No EOP flag (for bitstuffing only) */
+#define RFD_ERR_TRUN 0x0020	/* (82596 only/SF mode) indicates truncated frame */
+#define RFD_MATCHADD 0x0002     /* status: Destinationaddress !matches IA (only 82596) */
+#define RFD_COLLDET  0x0001	/* Detected collision during reception */
+
+/*
+ * Receive Buffer Descriptor (RBD)
+ */
+struct rbd_struct 
+{
+  unsigned short status;	/* status word,number of used bytes in buff */
+  unsigned short next;		/* pointeroffset to next RBD */
+  char          *buffer;	/* receive buffer address pointer */
+  unsigned short size;		/* size of this buffer */
+  unsigned short zero_dummy;    /* dummy */
+};
+
+#define RBD_LAST	0x8000	/* last buffer */
+#define RBD_USED	0x4000	/* this buffer has data */
+#define RBD_MASK	0x3fff	/* size-mask for length */
+
+/*
+ * Statusvalues for Commands/RFD
+ */
+#define STAT_COMPL   0x8000	/* status: frame/command is complete */
+#define STAT_BUSY    0x4000	/* status: frame/command is busy */
+#define STAT_OK      0x2000	/* status: frame/command is ok */
+
+/*
+ * Action-Commands
+ */
+#define CMD_NOP		0x0000	/* NOP */
+#define CMD_IASETUP	0x0001	/* initial address setup command */
+#define CMD_CONFIGURE	0x0002	/* configure command */
+#define CMD_MCSETUP	0x0003	/* MC setup command */
+#define CMD_XMIT	0x0004	/* transmit command */
+#define CMD_TDR		0x0005	/* time domain reflectometer (TDR) command */
+#define CMD_DUMP	0x0006	/* dump command */
+#define CMD_DIAGNOSE	0x0007	/* diagnose command */
+
+/*
+ * Action command bits
+ */
+#define CMD_LAST	0x8000	/* indicates last command in the CBL */
+#define CMD_SUSPEND	0x4000	/* suspend CU after this CB */
+#define CMD_INT		0x2000	/* generate interrupt after execution */
+
+/*
+ * NOP - command
+ */
+struct nop_cmd_struct
+{
+  unsigned short cmd_status;	/* status of this command */
+  unsigned short cmd_cmd;       /* the command itself (+bits) */
+  unsigned short cmd_link;      /* offsetpointer to next command */
+};
+
+/*
+ * IA Setup command
+ */
+struct iasetup_cmd_struct 
+{
+  unsigned short cmd_status;
+  unsigned short cmd_cmd;
+  unsigned short cmd_link;
+  unsigned char  iaddr[6];
+};
+
+/*
+ * Configure command 
+ */
+struct configure_cmd_struct
+{
+  unsigned short cmd_status;
+  unsigned short cmd_cmd;
+  unsigned short cmd_link;
+  unsigned char  byte_cnt;   /* size of the config-cmd */
+  unsigned char  fifo;       /* fifo/recv monitor */
+  unsigned char  sav_bf;     /* save bad frames (bit7=1)*/
+  unsigned char  adr_len;    /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/
+  unsigned char  priority;   /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */
+  unsigned char  ifs;        /* inter frame spacing */
+  unsigned char  time_low;   /* slot time low */
+  unsigned char  time_high;  /* slot time high(0-2) and max. retries(4-7) */
+  unsigned char  promisc;    /* promisc-mode(0) , et al (1-7) */
+  unsigned char  carr_coll;  /* carrier(0-3)/collision(4-7) stuff */
+  unsigned char  fram_len;   /* minimal frame len */
+  unsigned char  dummy;	     /* dummy */
+};
+
+/*
+ * Multicast Setup command 
+ */
+struct mcsetup_cmd_struct 
+{
+  unsigned short cmd_status;
+  unsigned short cmd_cmd;
+  unsigned short cmd_link;
+  unsigned short mc_cnt;		/* number of bytes in the MC-List */
+  unsigned char  mc_list[0][6];  	/* pointer to 6 bytes entries */
+};
+
+/*
+ * DUMP command
+ */
+struct dump_cmd_struct
+{
+  unsigned short cmd_status;
+  unsigned short cmd_cmd;
+  unsigned short cmd_link;
+  unsigned short dump_offset;    /* pointeroffset to DUMP space */
+};
+
+/*
+ * transmit command 
+ */
+struct transmit_cmd_struct 
+{
+  unsigned short cmd_status;
+  unsigned short cmd_cmd;
+  unsigned short cmd_link;
+  unsigned short tbd_offset;	/* pointeroffset to TBD */
+  unsigned char  dest[6];       /* destination address of the frame */
+  unsigned short length;	/* user defined: 802.3 length / Ether type */
+};
+
+#define TCMD_ERRMASK     0x0fa0
+#define TCMD_MAXCOLLMASK 0x000f
+#define TCMD_MAXCOLL     0x0020
+#define TCMD_HEARTBEAT   0x0040
+#define TCMD_DEFERRED    0x0080
+#define TCMD_UNDERRUN    0x0100
+#define TCMD_LOSTCTS     0x0200
+#define TCMD_NOCARRIER   0x0400
+#define TCMD_LATECOLL    0x0800
+
+struct tdr_cmd_struct
+{
+  unsigned short cmd_status;
+  unsigned short cmd_cmd;
+  unsigned short cmd_link;
+  unsigned short status;
+};
+
+#define TDR_LNK_OK	0x8000	/* No link problem identified */
+#define TDR_XCVR_PRB	0x4000	/* indicates a transceiver problem */
+#define TDR_ET_OPN	0x2000	/* open, no correct termination */
+#define TDR_ET_SRT	0x1000	/* TDR detected a short circuit */
+#define TDR_TIMEMASK	0x07ff	/* mask for the time field */
+
+/*
+ * Transmit Buffer Descriptor (TBD)
+ */
+struct tbd_struct
+{
+  unsigned short size;		/* size + EOF-Flag(15) */
+  unsigned short next;          /* pointeroffset to next TBD */
+  char          *buffer;        /* pointer to buffer */
+};
+
+#define TBD_LAST 0x8000         /* EOF-Flag, indicates last buffer in list */
+
+
+
+
diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c
--- a/drivers/net/sungem.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/sungem.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /* $Id: sungem.c,v 1.49 2002/01/23 15:40:45 davem Exp $
  * sungem.c: Sun GEM ethernet driver.
  *
- * Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2000, 2001, 2002 David S. Miller (davem@redhat.com)
  * 
  * Support for Apple GMAC and assorted PHYs by
  * Benjamin Herrenscmidt (benh@kernel.crashing.org)
@@ -16,6 +16,8 @@
  *    I can at least detect gigabit with autoneg.
  */
 
+#include <linux/config.h>
+
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -35,9 +37,10 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/random.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -67,8 +70,8 @@
 			 NETIF_MSG_LINK)
 
 #define DRV_NAME	"sungem"
-#define DRV_VERSION	"0.96"
-#define DRV_RELDATE	"11/17/01"
+#define DRV_VERSION	"0.97"
+#define DRV_RELDATE	"3/20/02"
 #define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
 
 static char version[] __devinitdata =
@@ -293,19 +296,119 @@
 	return 0;
 }
 
+/* When we get a RX fifo overflow, the RX unit in GEM is probably hung
+ * so we do the following.
+ *
+ * If any part of the reset goes wrong, we return 1 and that causes the
+ * whole chip to be reset.
+ */
+static int gem_rxmac_reset(struct gem *gp)
+{
+	struct net_device *dev = gp->dev;
+	int limit, i;
+	u64 desc_dma;
+	u32 val;
+
+	/* First, reset MAC RX. */
+	writel(gp->mac_rx_cfg & ~MAC_RXCFG_ENAB,
+	       gp->regs + MAC_RXCFG);
+	for (limit = 0; limit < 5000; limit++) {
+		if (!(readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB))
+			break;
+		udelay(10);
+	}
+	if (limit == 5000) {
+		printk(KERN_ERR "%s: RX MAC will not disable, resetting whole "
+		       "chip.\n", dev->name);
+		return 1;
+	}
+
+	/* Second, disable RX DMA. */
+	writel(0, gp->regs + RXDMA_CFG);
+	for (limit = 0; limit < 5000; limit++) {
+		if (!(readl(gp->regs + RXDMA_CFG) & RXDMA_CFG_ENABLE))
+			break;
+		udelay(10);
+	}
+	if (limit == 5000) {
+		printk(KERN_ERR "%s: RX DMA will not disable, resetting whole "
+		       "chip.\n", dev->name);
+		return 1;
+	}
+
+	udelay(5000);
+
+	/* Execute RX reset command. */
+	writel(gp->swrst_base | GREG_SWRST_RXRST,
+	       gp->regs + GREG_SWRST);
+	for (limit = 0; limit < 5000; limit++) {
+		if (!(readl(gp->regs + GREG_SWRST) & GREG_SWRST_RXRST))
+			break;
+		udelay(10);
+	}
+	if (limit == 5000) {
+		printk(KERN_ERR "%s: RX reset command will not execute, resetting "
+		       "whole chip.\n", dev->name);
+		return 1;
+	}
+
+	/* Refresh the RX ring. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct gem_rxd *rxd = &gp->init_block->rxd[i];
+
+		if (gp->rx_skbs[i] == NULL) {
+			printk(KERN_ERR "%s: Parts of RX ring empty, resetting "
+			       "whole chip.\n", dev->name);
+			return 1;
+		}
+
+		rxd->status_word = cpu_to_le64(RXDCTRL_FRESH(gp));
+	}
+	gp->rx_new = gp->rx_old = 0;
+
+	/* Now we must reprogram the rest of RX unit. */
+	desc_dma = (u64) gp->gblock_dvma;
+	desc_dma += (INIT_BLOCK_TX_RING_SIZE * sizeof(struct gem_txd));
+	writel(desc_dma >> 32, gp->regs + RXDMA_DBHI);
+	writel(desc_dma & 0xffffffff, gp->regs + RXDMA_DBLOW);
+	writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
+	val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) |
+	       ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128);
+	writel(val, gp->regs + RXDMA_CFG);
+	if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN)
+		writel(((5 & RXDMA_BLANK_IPKTS) |
+			((8 << 12) & RXDMA_BLANK_ITIME)),
+		       gp->regs + RXDMA_BLANK);
+	else
+		writel(((5 & RXDMA_BLANK_IPKTS) |
+			((4 << 12) & RXDMA_BLANK_ITIME)),
+		       gp->regs + RXDMA_BLANK);
+	val  = (((gp->rx_pause_off / 64) << 0) & RXDMA_PTHRESH_OFF);
+	val |= (((gp->rx_pause_on / 64) << 12) & RXDMA_PTHRESH_ON);
+	writel(val, gp->regs + RXDMA_PTHRESH);
+	val = readl(gp->regs + RXDMA_CFG);
+	writel(val | RXDMA_CFG_ENABLE, gp->regs + RXDMA_CFG);
+	writel(MAC_RXSTAT_RCV, gp->regs + MAC_RXMASK);
+	val = readl(gp->regs + MAC_RXCFG);
+	writel(val | MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
+
+	return 0;
+}
+
 static int gem_rxmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_status)
 {
 	u32 rxmac_stat = readl(gp->regs + MAC_RXSTAT);
+	int ret = 0;
 
 	if (netif_msg_intr(gp))
 		printk(KERN_DEBUG "%s: rxmac interrupt, rxmac_stat: 0x%x\n",
 			gp->dev->name, rxmac_stat);
 
 	if (rxmac_stat & MAC_RXSTAT_OFLW) {
-		printk(KERN_ERR "%s: RX MAC fifo overflow.\n",
-		       dev->name);
 		gp->net_stats.rx_over_errors++;
 		gp->net_stats.rx_fifo_errors++;
+
+		ret = gem_rxmac_reset(gp);
 	}
 
 	if (rxmac_stat & MAC_RXSTAT_ACE)
@@ -320,7 +423,7 @@
 	/* We do not track MAC_RXSTAT_FCE and MAC_RXSTAT_VCE
 	 * events.
 	 */
-	return 0;
+	return ret;
 }
 
 static int gem_mac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_status)
@@ -480,7 +583,7 @@
 	return 0;
 
 do_reset:
-	gp->reset_task_pending = 1;
+	gp->reset_task_pending = 2;
 	schedule_task(&gp->reset_task);
 
 	return 1;
@@ -542,7 +645,7 @@
 	gp->tx_old = entry;
 
 	if (netif_queue_stopped(dev) &&
-	    TX_BUFFS_AVAIL(gp) > 0)
+	    TX_BUFFS_AVAIL(gp) > (MAX_SKB_FRAGS + 1))
 		netif_wake_queue(dev);
 }
 
@@ -717,7 +820,7 @@
 
 	spin_lock_irq(&gp->lock);
 
-	gp->reset_task_pending = 1;
+	gp->reset_task_pending = 2;
 	schedule_task(&gp->reset_task);
 
 	spin_unlock_irq(&gp->lock);
@@ -752,9 +855,12 @@
 
 	spin_lock_irq(&gp->lock);
 
+	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
 		spin_unlock_irq(&gp->lock);
+		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
+		       dev->name);
 		return 1;
 	}
 
@@ -829,7 +935,7 @@
 	}
 
 	gp->tx_new = entry;
-	if (TX_BUFFS_AVAIL(gp) <= 0)
+	if (TX_BUFFS_AVAIL(gp) <= (MAX_SKB_FRAGS + 1))
 		netif_stop_queue(dev);
 
 	if (netif_msg_tx_queued(gp))
@@ -844,19 +950,28 @@
 }
 
 /* Jumbo-grams don't seem to work :-( */
+#define GEM_MIN_MTU	68
 #if 1
-#define MAX_MTU		1500
+#define GEM_MAX_MTU	1500
 #else
-#define MAX_MTU		9000
+#define GEM_MAX_MTU	9000
 #endif
 
 static int gem_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct gem *gp = dev->priv;
 
-	if (new_mtu < 0 || new_mtu > MAX_MTU)
+	if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
 		return -EINVAL;
 
+	if (!netif_running(dev) || !netif_device_present(dev)) {
+		/* We'll just catch it later when the
+		 * device is up'd or resumed.
+		 */
+		dev->mtu = new_mtu;
+		return 0;
+	}
+
 	spin_lock_irq(&gp->lock);
 	dev->mtu = new_mtu;
 	gp->reset_task_pending = 1;
@@ -870,6 +985,7 @@
 
 #define STOP_TRIES 32
 
+/* Must be invoked under gp->lock. */
 static void gem_stop(struct gem *gp)
 {
 	int limit;
@@ -879,7 +995,8 @@
 	writel(0xffffffff, gp->regs + GREG_IMASK);
 
 	/* Reset the chip */
-	writel(GREG_SWRST_TXRST | GREG_SWRST_RXRST, gp->regs + GREG_SWRST);
+	writel(gp->swrst_base | GREG_SWRST_TXRST | GREG_SWRST_RXRST,
+	       gp->regs + GREG_SWRST);
 
 	limit = STOP_TRIES;
 
@@ -894,6 +1011,7 @@
 		printk(KERN_ERR "gem: SW reset is ghetto.\n");
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_start_dma(struct gem *gp)
 {
 	unsigned long val;
@@ -929,6 +1047,7 @@
 	{ 1, 0, 1 },	/* 1000BT */
 };
 
+/* Must be invoked under gp->lock. */
 static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
 {
 	u16 ctl;
@@ -954,11 +1073,8 @@
 	}
 
 start_aneg:
-	spin_lock_irq(&gp->lock);
-	if (!gp->hw_running) {
-		spin_unlock_irq(&gp->lock);
+	if (!gp->hw_running)
 		return;
-	}
 
 	/* Configure PHY & start aneg */
 	ctl = phy_read(gp, MII_BMCR);
@@ -973,11 +1089,10 @@
 	phy_write(gp, MII_BMCR, ctl);
 
 	gp->timer_ticks = 0;
-	gp->link_timer.expires = jiffies + ((12 * HZ) / 10);
-	add_timer(&gp->link_timer);
-	spin_unlock_irq(&gp->lock);
+	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_read_mii_link_mode(struct gem *gp, int *fd, int *spd, int *pause)
 {
 	u32 val;
@@ -1021,6 +1136,8 @@
 
 /* A link-up condition has occurred, initialize and enable the
  * rest of the chip.
+ *
+ * Must be invoked under gp->lock.
  */
 static void gem_set_link_modes(struct gem *gp)
 {
@@ -1101,6 +1218,20 @@
 			pause = 1;
 	}
 
+	if (netif_msg_link(gp)) {
+		if (pause) {
+			printk(KERN_INFO "%s: Pause is enabled "
+			       "(rxfifo: %d off: %d on: %d)\n",
+			       gp->dev->name,
+			       gp->rx_fifo_sz,
+			       gp->rx_pause_off,
+			       gp->rx_pause_on);
+		} else {
+			printk(KERN_INFO "%s: Pause is disabled\n",
+			       gp->dev->name);
+		}
+	}
+
 	if (!full_duplex)
 		writel(512, gp->regs + MAC_STIME);
 	else
@@ -1115,6 +1246,7 @@
 	gem_start_dma(gp);
 }
 
+/* Must be invoked under gp->lock. */
 static int gem_mdio_link_not_up(struct gem *gp)
 {
 	u16 val;
@@ -1158,7 +1290,7 @@
 	return 0;
 }
 
-static void gem_init_rings(struct gem *, int);
+static void gem_init_rings(struct gem *);
 static void gem_init_hw(struct gem *, int);
 
 static void gem_reset_task(void *data)
@@ -1169,24 +1301,27 @@
 	 * DMA stopped. Todo: Use this function for reset
 	 * on error as well.
 	 */
+
+	spin_lock_irq(&gp->lock);
+
 	if (gp->hw_running && gp->opened) {
 		/* Make sure we don't get interrupts or tx packets */
-		spin_lock_irq(&gp->lock);
-
 		netif_stop_queue(gp->dev);
 
 		writel(0xffffffff, gp->regs + GREG_IMASK);
 
-		spin_unlock_irq(&gp->lock);
-
 		/* Reset the chip & rings */
 		gem_stop(gp);
-		gem_init_rings(gp, 0);
-		gem_init_hw(gp, 0);
+		gem_init_rings(gp);
+
+		gem_init_hw(gp,
+			    (gp->reset_task_pending == 2));
 
 		netif_wake_queue(gp->dev);
 	}
 	gp->reset_task_pending = 0;
+
+	spin_unlock_irq(&gp->lock);
 }
 
 static void gem_link_timer(unsigned long data)
@@ -1196,13 +1331,14 @@
 	if (!gp->hw_running)
 		return;
 
+	spin_lock_irq(&gp->lock);
+
 	/* If the link of task is still pending, we just
 	 * reschedule the link timer
 	 */
 	if (gp->reset_task_pending)
 		goto restart;
 	    	
-	spin_lock_irq(&gp->lock);
 	if (gp->phy_type == phy_mii_mdio0 ||
 	    gp->phy_type == phy_mii_mdio1) {
 		u16 val = phy_read(gp, MII_BMSR);
@@ -1247,16 +1383,15 @@
 				if (netif_msg_link(gp))
 					printk(KERN_INFO "%s: Link down\n",
 						gp->dev->name);
-				gp->reset_task_pending = 1;
+				gp->reset_task_pending = 2;
 				schedule_task(&gp->reset_task);
 				restart = 1;
 			} else if (++gp->timer_ticks > 10)
 				restart = gem_mdio_link_not_up(gp);
 
 			if (restart) {
-				spin_unlock_irq(&gp->lock);
 				gem_begin_auto_negotiation(gp, NULL);
-				return;
+				goto out_unlock;
 			}
 		}
 	} else {
@@ -1273,11 +1408,12 @@
 	}
 
 restart:
-	gp->link_timer.expires = jiffies + ((12 * HZ) / 10);
-	add_timer(&gp->link_timer);
+	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
+out_unlock:
 	spin_unlock_irq(&gp->lock);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_clean_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1311,7 +1447,9 @@
 			gp->tx_skbs[i] = NULL;
 
 			for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
-				txd = &gb->txd[i];
+				int ent = i & (TX_RING_SIZE - 1);
+
+				txd = &gb->txd[ent];
 				dma_addr = le64_to_cpu(txd->buffer);
 				pci_unmap_page(gp->pdev, dma_addr,
 					       le64_to_cpu(txd->control_word) &
@@ -1325,16 +1463,14 @@
 	}
 }
 
-static void gem_init_rings(struct gem *gp, int from_irq)
+/* Must be invoked under gp->lock. */
+static void gem_init_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
 	struct net_device *dev = gp->dev;
-	int i, gfp_flags = GFP_KERNEL;
+	int i;
 	dma_addr_t dma_addr;
 
-	if (from_irq)
-		gfp_flags = GFP_ATOMIC;
-
 	gp->rx_new = gp->rx_old = gp->tx_new = gp->tx_old = 0;
 
 	gem_clean_rings(gp);
@@ -1343,7 +1479,7 @@
 		struct sk_buff *skb;
 		struct gem_rxd *rxd = &gb->rxd[i];
 
-		skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), gfp_flags);
+		skb = gem_alloc_skb(RX_BUF_ALLOC_SIZE(gp), GFP_ATOMIC);
 		if (!skb) {
 			rxd->buffer = 0;
 			rxd->status_word = 0;
@@ -1372,6 +1508,7 @@
 	}
 }
 
+/* Must be invoked under gp->lock. */
 static int gem_reset_one_mii_phy(struct gem *gp, int phy_addr)
 {
 	u16 val;
@@ -1396,6 +1533,7 @@
 	return (limit <= 0);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_bcm5201_phy(struct gem *gp)
 {
 	u16 data;
@@ -1405,6 +1543,7 @@
 	phy_write(gp, MII_BCM5201_MULTIPHY, data);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_bcm5400_phy(struct gem *gp)
 {
 	u16 data;
@@ -1432,6 +1571,7 @@
 	phy_write(gp, MII_BCM5400_AUXCONTROL, data);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_bcm5401_phy(struct gem *gp)
 {
 	u16 data;
@@ -1446,6 +1586,9 @@
 		 * WARNING ! OF and Darwin don't agree on the
 		 * register addresses. OF seem to interpret the
 		 * register numbers below as decimal
+		 *
+		 * Note: This should (and does) match tg3_init_5401phy_dsp
+		 *       in the tg3.c driver. -DaveM
 		 */
 		phy_write(gp, 0x18, 0x0c20);
 		phy_write(gp, 0x17, 0x0012);
@@ -1475,6 +1618,7 @@
 	__phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_bcm5411_phy(struct gem *gp)
 {
 	u16 data;
@@ -1501,6 +1645,7 @@
 	phy_write(gp, MII_BCM5400_GB_CONTROL, data);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_phy(struct gem *gp)
 {
 	u32 mifcfg;
@@ -1649,7 +1794,9 @@
 		val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
 		writel(val, gp->regs + PCS_CFG);
 
-		/* Advertise all capabilities. */
+		/* Advertise all capabilities except assymetric
+		 * pause.
+		 */
 		val = readl(gp->regs + PCS_MIIADV);
 		val |= (PCS_MIIADV_FD | PCS_MIIADV_HD |
 			PCS_MIIADV_SP | PCS_MIIADV_AP);
@@ -1684,9 +1831,9 @@
 	if (gp->phy_mod != phymod_bcm5400 && gp->phy_mod != phymod_bcm5401 &&
 	    gp->phy_mod != phymod_bcm5411)
 	    	gp->link_cntl &= ~BMCR_SPD2;
-	    
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_dma(struct gem *gp)
 {
 	u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1702,7 +1849,7 @@
 	writel(0, gp->regs + TXDMA_KICK);
 
 	val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) |
-	       ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_512);
+	       ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128);
 	writel(val, gp->regs + RXDMA_CFG);
 
 	writel(desc_dma >> 32, gp->regs + RXDMA_DBHI);
@@ -1724,6 +1871,7 @@
 		       gp->regs + RXDMA_BLANK);
 }
 
+/* Must be invoked under gp->lock. */
 static u32
 gem_setup_multicast(struct gem *gp)
 {
@@ -1766,10 +1914,10 @@
 	return rxcfg;
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_mac(struct gem *gp)
 {
 	unsigned char *e = &gp->dev->dev_addr[0];
-	u32 rxcfg;
 
 	if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    gp->pdev->device == PCI_DEVICE_ID_SUN_GEM)
@@ -1780,7 +1928,10 @@
 	writel(0x04, gp->regs + MAC_IPG2);
 	writel(0x40, gp->regs + MAC_STIME);
 	writel(0x40, gp->regs + MAC_MINFSZ);
-	writel(0x20000000 | (gp->dev->mtu + 18), gp->regs + MAC_MAXFSZ);
+
+	/* Ethernet payload + header + FCS + optional VLAN tag. */
+	writel(0x20000000 | (gp->dev->mtu + ETH_HLEN + 4 + 4), gp->regs + MAC_MAXFSZ);
+
 	writel(0x07, gp->regs + MAC_PASIZE);
 	writel(0x04, gp->regs + MAC_JAMSIZE);
 	writel(0x10, gp->regs + MAC_ATTLIM);
@@ -1806,7 +1957,7 @@
 	writel(0, gp->regs + MAC_AF21MSK);
 	writel(0, gp->regs + MAC_AF0MSK);
 
-	rxcfg = gem_setup_multicast(gp);
+	gp->mac_rx_cfg = gem_setup_multicast(gp);
 
 	writel(0, gp->regs + MAC_NCOLL);
 	writel(0, gp->regs + MAC_FASUCC);
@@ -1824,7 +1975,7 @@
 	 * them once a link is established.
 	 */
 	writel(0, gp->regs + MAC_TXCFG);
-	writel(rxcfg, gp->regs + MAC_RXCFG);
+	writel(gp->mac_rx_cfg, gp->regs + MAC_RXCFG);
 	writel(0, gp->regs + MAC_MCCFG);
 	writel(0, gp->regs + MAC_XIFCFG);
 
@@ -1841,6 +1992,7 @@
 	writel(0xffffffff, gp->regs + MAC_MCMASK);
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_pause_thresholds(struct gem *gp)
 {
 	/* Calculate pause thresholds.  Setting the OFF threshold to the
@@ -1851,8 +2003,9 @@
 	if (gp->rx_fifo_sz <= (2 * 1024)) {
 		gp->rx_pause_off = gp->rx_pause_on = gp->rx_fifo_sz;
 	} else {
-		int off = (gp->rx_fifo_sz - (5 * 1024));
-		int on = off - 1024;
+		int max_frame = (gp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63;
+		int off = (gp->rx_fifo_sz - (max_frame * 2));
+		int on = off - max_frame;
 
 		gp->rx_pause_off = off;
 		gp->rx_pause_on = on;
@@ -1861,7 +2014,10 @@
 	{
 		u32 cfg;
 
-		cfg  = GREG_CFG_IBURST;
+		cfg  = 0;
+#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
+		cfg |= GREG_CFG_IBURST;
+#endif
 		cfg |= ((31 << 1) & GREG_CFG_TXDMALIM);
 		cfg |= ((31 << 6) & GREG_CFG_RXDMALIM);
 		writel(cfg, gp->regs + GREG_CFG);
@@ -1881,6 +2037,7 @@
 		gp->phy_type = phy_mii_mdio0;
 		gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64;
 		gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64;
+		gp->swrst_base = 0;
 		return 0;
 	}
 
@@ -1943,6 +2100,7 @@
 				       gp->tx_fifo_sz, gp->rx_fifo_sz);
 				return -1;
 			}
+			gp->swrst_base = 0;
 		} else {
 			if (gp->tx_fifo_sz != (2 * 1024) ||
 			    gp->rx_fifo_sz != (2 * 1024)) {
@@ -1950,12 +2108,14 @@
 				       gp->tx_fifo_sz, gp->rx_fifo_sz);
 				return -1;
 			}
+			gp->swrst_base = (64 / 4) << GREG_SWRST_CACHE_SHIFT;
 		}
 	}
 
 	return 0;
 }
 
+/* Must be invoked under gp->lock. */
 static void gem_init_hw(struct gem *gp, int restart_link)
 {
 	/* On Apple's gmac, I initialize the PHY only after
@@ -1970,21 +2130,16 @@
 	gem_init_mac(gp);
 	gem_init_pause_thresholds(gp);
 
-	spin_lock_irq(&gp->lock);
 	if (restart_link) {
 		/* Default aneg parameters */
 		gp->timer_ticks = 0;
 		gp->lstate = link_down;
 
-		spin_unlock_irq(&gp->lock);
-
 		/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
 		gem_begin_auto_negotiation(gp, NULL);
 	} else {
 		if (gp->lstate == link_up)
 			gem_set_link_modes(gp);
-
-		spin_unlock_irq(&gp->lock);
 	}
 }
 
@@ -2029,6 +2184,7 @@
 
 #endif /* CONFIG_ALL_PPC */
 
+/* Must be invoked under gp->lock. */
 static void gem_stop_phy(struct gem *gp)
 {
 	u32 mifcfg;
@@ -2100,14 +2256,21 @@
 		schedule();
 	
 	/* Actually stop the chip */
+	spin_lock_irq(&gp->lock);
 	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
 		gem_stop_phy(gp);
+
+		spin_unlock_irq(&gp->lock);
+
 #ifdef CONFIG_ALL_PPC
 		/* Power down the chip */
 		gem_apple_powerdown(gp);
 #endif /* CONFIG_ALL_PPC */
-	} else
+	} else {
 		gem_stop(gp);
+
+		spin_unlock_irq(&gp->lock);
+	}
 }
 
 static void gem_pm_task(void *data)
@@ -2142,14 +2305,19 @@
 static int gem_open(struct net_device *dev)
 {
 	struct gem *gp = dev->priv;
-	int hw_was_up = gp->hw_running;
+	int hw_was_up;
 
 	down(&gp->pm_sem);
 
+	hw_was_up = gp->hw_running;
+
 	/* Stop the PM timer/task */
 	del_timer(&gp->pm_timer);
 	flush_scheduled_tasks();
 
+	/* The power-management semaphore protects the hw_running
+	 * etc. state so it is safe to do this bit without gp->lock
+	 */
 	if (!gp->hw_running) {
 #ifdef CONFIG_ALL_PPC
 		/* First, we need to bring up the chip */
@@ -2158,18 +2326,26 @@
 			gem_check_invariants(gp);
 		}
 #endif /* CONFIG_ALL_PPC */
+
 		/* Reset the chip */
+		spin_lock_irq(&gp->lock);
 		gem_stop(gp);
+		spin_unlock_irq(&gp->lock);
 
 		gp->hw_running = 1;
 	}
 
+	spin_lock_irq(&gp->lock);
+
 	/* We can now request the interrupt as we know it's masked
 	 * on the controller
 	 */
 	if (request_irq(gp->pdev->irq, gem_interrupt,
 			SA_SHIRQ, dev->name, (void *)dev)) {
+		spin_unlock_irq(&gp->lock);
+
 		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
+
 #ifdef CONFIG_ALL_PPC
 		if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
 			gem_apple_powerdown(gp);
@@ -2183,13 +2359,15 @@
 	}
 
 	/* Allocate & setup ring buffers */
-	gem_init_rings(gp, 0);
+	gem_init_rings(gp);
 
 	/* Init & setup chip hardware */
 	gem_init_hw(gp, !hw_was_up);
 
 	gp->opened = 1;
 
+	spin_unlock_irq(&gp->lock);
+
 	up(&gp->pm_sem);
 
 	return 0;
@@ -2209,8 +2387,6 @@
 	writel(0xffffffff, gp->regs + GREG_IMASK);
 	netif_stop_queue(dev);
 
-	spin_unlock_irq(&gp->lock);
-
 	/* Stop chip */
 	gem_stop(gp);
 
@@ -2220,6 +2396,8 @@
 	/* Bye, the pm timer will finish the job */
 	free_irq(gp->pdev->irq, (void *) dev);
 
+	spin_unlock_irq(&gp->lock);
+
 	/* Fire the PM timer that will shut us down in about 10 seconds */
 	gp->pm_timer.expires = jiffies + 10*HZ;
 	add_timer(&gp->pm_timer);
@@ -2245,21 +2423,21 @@
 	
 	/* If the driver is opened, we stop the DMA */
 	if (gp->opened) {
+		spin_lock_irq(&gp->lock);
+
 		/* Stop traffic, mark us closed */
 		netif_device_detach(dev);
 
-		spin_lock_irq(&gp->lock);
-
 		writel(0xffffffff, gp->regs + GREG_IMASK);
 
-		spin_unlock_irq(&gp->lock);
-
 		/* Stop chip */
 		gem_stop(gp);
 
 		/* Get rid of ring buffers */
 		gem_clean_rings(gp);
 
+		spin_unlock_irq(&gp->lock);
+
 		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
 			disable_irq(gp->pdev->irq);
 	}
@@ -2290,10 +2468,15 @@
 			gem_check_invariants(gp);
 		}
 #endif /* CONFIG_ALL_PPC */
+		spin_lock_irq(&gp->lock);
+
 		gem_stop(gp);
 		gp->hw_running = 1;
-		gem_init_rings(gp, 0);
+		gem_init_rings(gp);
 		gem_init_hw(gp, 1);
+
+		spin_unlock_irq(&gp->lock);
+
 		netif_device_attach(dev);
 		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
 			enable_irq(gp->pdev->irq);
@@ -2309,6 +2492,8 @@
 	struct gem *gp = dev->priv;
 	struct net_device_stats *stats = &gp->net_stats;
 
+	spin_lock_irq(&gp->lock);
+
 	if (gp->hw_running) {
 		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
 		writel(0, gp->regs + MAC_FCSERR);
@@ -2326,6 +2511,9 @@
 		writel(0, gp->regs + MAC_ECOLL);
 		writel(0, gp->regs + MAC_LCOLL);
 	}
+
+	spin_unlock_irq(&gp->lock);
+
 	return &gp->net_stats;
 }
 
@@ -2338,10 +2526,12 @@
 	if (!gp->hw_running)
 		return;
 		
+	spin_lock_irq(&gp->lock);
+
 	netif_stop_queue(dev);
 
 	rxcfg = readl(gp->regs + MAC_RXCFG);
-	rxcfg_new = gem_setup_multicast(gp);
+	gp->mac_rx_cfg = rxcfg_new = gem_setup_multicast(gp);
 	
 	writel(rxcfg & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
 	while (readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB) {
@@ -2355,8 +2545,9 @@
 
 	writel(rxcfg, gp->regs + MAC_RXCFG);
 
-	/* Hrm... we may walk on the reset task here... */
 	netif_wake_queue(dev);
+
+	spin_unlock_irq(&gp->lock);
 }
 
 /* Eventually add support for changing the advertisement
@@ -2405,11 +2596,13 @@
 		ecmd.phy_address = 0; /* XXX fixed PHYAD */
 
 		/* Record PHY settings if HW is on. */
+		spin_lock_irq(&gp->lock);
 		if (gp->hw_running) {
 			bmcr = phy_read(gp, MII_BMCR);
 			gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause);
 		} else
 			bmcr = 0;
+		spin_unlock_irq(&gp->lock);
 		if (bmcr & BMCR_ANENABLE) {
 			ecmd.autoneg = AUTONEG_ENABLE;
 			ecmd.speed = speed == 10 ? SPEED_10 : (speed == 1000 ? SPEED_1000 : SPEED_100);
@@ -2443,18 +2636,22 @@
 		      ecmd.duplex != DUPLEX_FULL)))
 			return -EINVAL;
 
-		/* Apply settings and restart link process */
-		if (gp->hw_running)
-			del_timer(&gp->link_timer);
+		/* Apply settings and restart link process. */
+		spin_lock_irq(&gp->lock);
 		gem_begin_auto_negotiation(gp, &ecmd);
+		spin_unlock_irq(&gp->lock);
+
 		return 0;
 
 	case ETHTOOL_NWAY_RST:
 		if ((gp->link_cntl & BMCR_ANENABLE) == 0)
 			return -EINVAL;
-		if (gp->hw_running)
-			del_timer(&gp->link_timer);
+
+		/* Restart link process. */
+		spin_lock_irq(&gp->lock);
 		gem_begin_auto_negotiation(gp, NULL);
+		spin_unlock_irq(&gp->lock);
+
 		return 0;
 
 	case ETHTOOL_GWOL:
@@ -2570,13 +2767,74 @@
 	return rc;
 }
 
+#if (!defined(__sparc__) && !defined(CONFIG_ALL_PPC))
+/* Fetch MAC address from vital product data of PCI ROM. */
+static void find_eth_addr_in_vpd(void *rom_base, int len, unsigned char *dev_addr)
+{
+	int this_offset;
+
+	for (this_offset = 0x20; this_offset < len; this_offset++) {
+		void *p = rom_base + this_offset;
+		int i;
+
+		if (readb(p + 0) != 0x90 ||
+		    readb(p + 1) != 0x00 ||
+		    readb(p + 2) != 0x09 ||
+		    readb(p + 3) != 0x4e ||
+		    readb(p + 4) != 0x41 ||
+		    readb(p + 5) != 0x06)
+			continue;
+
+		this_offset += 6;
+		p += 6;
+
+		for (i = 0; i < 6; i++)
+			dev_addr[i] = readb(p + i);
+		break;
+	}
+}
+
+static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
+{
+	u32 rom_reg_orig;
+	void *p;
+
+	if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
+		if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
+			goto use_random;
+	}
+
+	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
+	pci_write_config_dword(pdev, pdev->rom_base_reg,
+			       rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+
+	p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
+	if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
+		find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
+
+	if (p != NULL)
+		iounmap(p);
+
+	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
+	return;
+
+use_random:
+	/* Sun MAC prefix then 3 random bytes. */
+	dev_addr[0] = 0x08;
+	dev_addr[1] = 0x00;
+	dev_addr[2] = 0x20;
+	get_random_bytes(dev_addr, 3);
+	return;
+}
+#endif /* not Sparc and not PPC */
+
 static int __devinit gem_get_device_address(struct gem *gp)
 {
 #if defined(__sparc__) || defined(CONFIG_ALL_PPC)
 	struct net_device *dev = gp->dev;
 #endif
 
-#ifdef __sparc__
+#if defined(__sparc__)
 	struct pci_dev *pdev = gp->pdev;
 	struct pcidev_cookie *pcp = pdev->sysdata;
 	int node = -1;
@@ -2591,8 +2849,7 @@
 	}
 	if (node == -1)
 		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
-#endif
-#ifdef CONFIG_ALL_PPC
+#elif defined(CONFIG_ALL_PPC)
 	unsigned char *addr;
 
 	addr = get_property(gp->of_node, "local-mac-address", NULL);
@@ -2602,6 +2859,8 @@
 		return -1;
 	}
 	memcpy(dev->dev_addr, addr, MAX_ADDR_LEN);
+#else
+	get_gem_mac_nonobp(gp->pdev, gp->dev->dev_addr);
 #endif
 	return 0;
 }
@@ -2664,21 +2923,21 @@
 		return -ENODEV;
 	}
 
-	dev = init_etherdev(NULL, sizeof(*gp));
+	dev = alloc_etherdev(sizeof(*gp));
 	if (!dev) {
-		printk(KERN_ERR PFX "Etherdev init failed, aborting.\n");
+		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
 		return -ENOMEM;
 	}
 	SET_MODULE_OWNER(dev);
 
-	if (!request_mem_region(gemreg_base, gemreg_len, dev->name)) {
-		printk(KERN_ERR PFX "MMIO resource (0x%lx@0x%lx) unavailable, "
-		       "aborting.\n", gemreg_base, gemreg_len);
+	gp = dev->priv;
+
+	if (pci_request_regions(pdev, dev->name)) {
+		printk(KERN_ERR PFX "Cannot obtain PCI resources, "
+		       "aborting.\n");
 		goto err_out_free_netdev;
 	}
 
-	gp = dev->priv;
-
 	gp->pdev = pdev;
 	dev->base_addr = (long) pdev;
 	gp->dev = dev;
@@ -2711,7 +2970,7 @@
 	if (gp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
-		goto err_out_free_mmio_res;
+		goto err_out_free_res;
 	}
 
 	/* On Apple, we power the chip up now in order for check
@@ -2722,12 +2981,18 @@
 	if (pdev->vendor == PCI_VENDOR_ID_APPLE)
 		gem_apple_powerup(gp);
 #endif
+	spin_lock_irq(&gp->lock);
 	gem_stop(gp);
+	spin_unlock_irq(&gp->lock);
+
 	if (gem_check_invariants(gp))
 		goto err_out_iounmap;
+
+	spin_lock_irq(&gp->lock);
 	gp->hw_running = 1;
 	gem_init_phy(gp);
 	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock_irq(&gp->lock);
 
 	/* It is guarenteed that the returned buffer will be at least
 	 * PAGE_SIZE aligned.
@@ -2741,22 +3006,28 @@
 		goto err_out_iounmap;
 	}
 
-	pci_set_drvdata(pdev, dev);
-
-	printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet ",
-	       dev->name);
-
 #ifdef CONFIG_ALL_PPC
 	gp->of_node = pci_device_to_OF_node(pdev);
 #endif	
 	if (gem_get_device_address(gp))
-		goto err_out_iounmap;
+		goto err_out_free_consistent;
+
+	if (register_netdev(dev)) {
+		printk(KERN_ERR PFX "Cannot register net device, "
+		       "aborting.\n");
+		goto err_out_free_consistent;
+	}
+
+	printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet ",
+	       dev->name);
 
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? ' ' : ':');
 	printk("\n");
 
+	pci_set_drvdata(pdev, dev);
+
 	dev->open = gem_open;
 	dev->stop = gem_close;
 	dev->hard_start_xmit = gem_start_xmit;
@@ -2780,6 +3051,12 @@
 
 	return 0;
 
+err_out_free_consistent:
+	pci_free_consistent(pdev,
+			    sizeof(struct gem_init_block),
+			    gp->init_block,
+			    gp->gblock_dvma);
+
 err_out_iounmap:
 	down(&gp->pm_sem);
 	/* Stop the PM timer & task */
@@ -2788,13 +3065,13 @@
 	if (gp->hw_running)
 		gem_shutdown(gp);
 	up(&gp->pm_sem);
+
 	iounmap((void *) gp->regs);
 
-err_out_free_mmio_res:
-	release_mem_region(gemreg_base, gemreg_len);
+err_out_free_res:
+	pci_release_regions(pdev);
 
 err_out_free_netdev:
-	unregister_netdev(dev);
 	kfree(dev);
 
 	return -ENODEV;
@@ -2823,8 +3100,7 @@
 				    gp->init_block,
 				    gp->gblock_dvma);
 		iounmap((void *) gp->regs);
-		release_mem_region(pci_resource_start(pdev, 0),
-				   pci_resource_len(pdev, 0));
+		pci_release_regions(pdev);
 		kfree(dev);
 
 		pci_set_drvdata(pdev, NULL);
diff -Nru a/drivers/net/sungem.h b/drivers/net/sungem.h
--- a/drivers/net/sungem.h	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/sungem.h	Sun Apr 14 12:16:54 2002
@@ -94,6 +94,8 @@
 #define GREG_SWRST_TXRST	0x00000001	/* TX Software Reset		*/
 #define GREG_SWRST_RXRST	0x00000002	/* RX Software Reset		*/
 #define GREG_SWRST_RSTOUT	0x00000004	/* Force RST# pin active	*/
+#define GREG_SWRST_CACHESIZE	0x00ff0000	/* RIO only: cache line size	*/
+#define GREG_SWRST_CACHE_SHIFT	16
 
 /* TX DMA Registers */
 #define TXDMA_KICK	0x2000UL	/* TX Kick Register		*/
@@ -985,6 +987,9 @@
 	int			rx_pause_on;
 	int			mii_phy_addr;
 	int			gigabit_capable;
+
+	u32			mac_rx_cfg;
+	u32			swrst_base;
 
 	/* Autoneg & PHY control */
 	int			link_cntl;
diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c
--- a/drivers/net/sunhme.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/net/sunhme.c	Sun Apr 14 12:16:57 2002
@@ -3,7 +3,7 @@
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
  *
- * Copyright (C) 1996, 1998, 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1998, 1999, 2002 David S. Miller (davem@redhat.com)
  *
  * Changes :
  * 2000/11/11 Willy Tarreau <willy AT meta-x.org>
@@ -14,7 +14,7 @@
  */
 
 static char version[] =
-        "sunhme.c:v1.99 12/Sep/99 David S. Miller (davem@redhat.com)\n";
+        "sunhme.c:v2.01 26/Mar/2002 David S. Miller (davem@redhat.com)\n";
 
 #include <linux/module.h>
 
@@ -34,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/crc32.h>
+#include <linux/random.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -696,7 +697,7 @@
 	return 1;
 }
 
-static int happy_meal_init(struct happy_meal *hp, int from_irq);
+static int happy_meal_init(struct happy_meal *hp);
 
 static int is_lucent_phy(struct happy_meal *hp)
 {
@@ -707,12 +708,8 @@
 	mr2 = happy_meal_tcvr_read(hp, tregs, 2);
 	mr3 = happy_meal_tcvr_read(hp, tregs, 3);
 	if ((mr2 & 0xffff) == 0x0180 &&
-	    ((mr3 & 0xffff) >> 10) == 0x1d) {
-#if 0
-		printk("HMEDEBUG: Lucent PHY detected.\n");
-#endif
+	    ((mr3 & 0xffff) >> 10) == 0x1d)
 		ret = 1;
-	}
 
 	return ret;
 }
@@ -723,6 +720,8 @@
 	unsigned long tregs = hp->tcvregs;
 	int restart_timer = 0;
 
+	spin_lock_irq(&hp->happy_lock);
+
 	hp->timer_ticks++;
 	switch(hp->timer_state) {
 	case arbwait:
@@ -852,13 +851,13 @@
 					printk(KERN_NOTICE "%s: Link down, cable problem?\n",
 					       hp->dev->name);
 
-					ret = happy_meal_init(hp, 0);
+					ret = happy_meal_init(hp);
 					if (ret) {
 						/* ho hum... */
 						printk(KERN_ERR "%s: Error, cannot re-init the "
 						       "Happy Meal.\n", hp->dev->name);
 					}
-					return;
+					goto out;
 				}
 				if (!is_lucent_phy(hp)) {
 					hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs,
@@ -890,11 +889,15 @@
 		hp->happy_timer.expires = jiffies + ((12 * HZ)/10); /* 1.2 sec. */
 		add_timer(&hp->happy_timer);
 	}
+
+out:
+	spin_unlock_irq(&hp->happy_lock);
 }
 
 #define TX_RESET_TRIES     32
 #define RX_RESET_TRIES     32
 
+/* hp->happy_lock must be held */
 static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs)
 {
 	int tries = TX_RESET_TRIES;
@@ -914,6 +917,7 @@
 	HMD(("done\n"));
 }
 
+/* hp->happy_lock must be held */
 static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs)
 {
 	int tries = RX_RESET_TRIES;
@@ -935,6 +939,7 @@
 
 #define STOP_TRIES         16
 
+/* hp->happy_lock must be held */
 static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs)
 {
 	int tries = STOP_TRIES;
@@ -954,6 +959,7 @@
 	HMD(("done\n"));
 }
 
+/* hp->happy_lock must be held */
 static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs)
 {
 	struct net_device_stats *stats = &hp->net_stats;
@@ -976,53 +982,7 @@
 	hme_write32(hp, bregs + BMAC_LTCTR, 0);
 }
 
-#if 0
-static void happy_meal_poll_start(struct happy_meal *hp, unsigned long tregs)
-{
-	u32 tmp;
-	int speed;
-
-	ASD(("happy_meal_poll_start: "));
-	if (!(hp->happy_flags & HFLAG_POLLENABLE)) {
-		HMD(("polling disabled, return\n"));
-		return;
-	}
-
-	/* Start the MIF polling on the external transceiver. */
-	ASD(("polling on, "));
-	tmp = hme_read32(hp, tregs + TCVR_CFG);
-	tmp &= ~(TCV_CFG_PDADDR | TCV_CFG_PREGADDR);
-	tmp |= ((hp->paddr & 0x1f) << 10);
-	tmp |= (TCV_PADDR_ETX << 3);
-	tmp |= TCV_CFG_PENABLE;
-	hme_write32(hp, tregs + TCVR_CFG, tmp);
-
-	/* Let the bits set. */
-	udelay(200);
-
-	/* We are polling now. */
-	ASD(("now polling, "));
-	hp->happy_flags |= HFLAG_POLL;
-
-	/* Clear the poll flags, get the basic status as of now. */
-	hp->poll_flag = 0;
-	hp->poll_data = hme_read32(hp, tregs + TCVR_STATUS) >> 16;
-
-	if (hp->happy_flags & HFLAG_AUTO)
-		speed = hp->auto_speed;
-	else
-		speed = hp->forced_speed;
-
-	/* Listen only for the MIF interrupts we want to hear. */
-	ASD(("mif ints on, "));
-	if (speed == 100)
-		hme_write32(hp, tregs + TCVR_IMASK, 0xfffb);
-	else
-		hme_write32(hp, tregs + TCVR_IMASK, 0xfff9);
-	ASD(("done\n"));
-}
-#endif
-
+/* hp->happy_lock must be held */
 static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs)
 {
 	ASD(("happy_meal_poll_stop: "));
@@ -1057,6 +1017,7 @@
 #define TCVR_RESET_TRIES       16 /* It should reset quickly        */
 #define TCVR_UNISOLATE_TRIES   32 /* Dis-isolation can take longer. */
 
+/* hp->happy_lock must be held */
 static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs)
 {
 	u32 tconfig;
@@ -1151,7 +1112,10 @@
 	return 0;
 }
 
-/* Figure out whether we have an internal or external transceiver. */
+/* Figure out whether we have an internal or external transceiver.
+ *
+ * hp->happy_lock must be held
+ */
 static void happy_meal_transceiver_check(struct happy_meal *hp, unsigned long tregs)
 {
 	unsigned long tconfig = hme_read32(hp, tregs + TCVR_CFG);
@@ -1303,14 +1267,12 @@
 	}
 }
 
-static void happy_meal_init_rings(struct happy_meal *hp, int from_irq)
+/* hp->happy_lock must be held */
+static void happy_meal_init_rings(struct happy_meal *hp)
 {
 	struct hmeal_init_block *hb = hp->happy_block;
 	struct net_device *dev = hp->dev;
-	int i, gfp_flags = GFP_KERNEL;
-
-	if (from_irq || in_interrupt())
-		gfp_flags = GFP_ATOMIC;
+	int i;
 
 	HMD(("happy_meal_init_rings: counters to zero, "));
 	hp->rx_new = hp->rx_old = hp->tx_new = hp->tx_old = 0;
@@ -1324,7 +1286,7 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
 
-		skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags);
+		skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC);
 		if (!skb) {
 			hme_write_rxd(hp, &hb->happy_meal_rxd[i], 0, 0);
 			continue;
@@ -1347,6 +1309,7 @@
 	HMD(("done\n"));
 }
 
+/* hp->happy_lock must be held */
 static void happy_meal_begin_auto_negotiation(struct happy_meal *hp,
 					      unsigned long tregs,
 					      struct ethtool_cmd *ep)
@@ -1470,7 +1433,8 @@
 	add_timer(&hp->happy_timer);
 }
 
-static int happy_meal_init(struct happy_meal *hp, int from_irq)
+/* hp->happy_lock must be held */
+static int happy_meal_init(struct happy_meal *hp)
 {
 	unsigned long gregs        = hp->gregs;
 	unsigned long etxregs      = hp->etxregs;
@@ -1501,7 +1465,7 @@
 
 	/* Alloc and reset the tx/rx descriptor chains. */
 	HMD(("happy_meal_init: to happy_meal_init_rings\n"));
-	happy_meal_init_rings(hp, from_irq);
+	happy_meal_init_rings(hp);
 
 	/* Shut up the MIF. */
 	HMD(("happy_meal_init: Disable all MIF irqs (old[%08x]), ",
@@ -1618,6 +1582,17 @@
 	hme_write32(hp, etxregs + ETX_RING,
 		    ((__u32)hp->hblock_dvma + hblock_offset(happy_meal_txd, 0)));
 
+	/* Parity issues in the ERX unit of some HME revisions can cause some
+	 * registers to not be written unless their parity is even.  Detect such
+	 * lost writes and simply rewrite with a low bit set (which will be ignored
+	 * since the rxring needs to be 2K aligned).
+	 */
+	if (hme_read32(hp, erxregs + ERX_RING) !=
+	    ((__u32)hp->hblock_dvma + hblock_offset(happy_meal_rxd, 0)))
+		hme_write32(hp, erxregs + ERX_RING,
+			    ((__u32)hp->hblock_dvma + hblock_offset(happy_meal_rxd, 0))
+			    | 0x4);
+
 	/* Set the supported burst sizes. */
 	HMD(("happy_meal_init: old[%08x] bursts<",
 	     hme_read32(hp, gregs + GREG_CFG)));
@@ -1698,7 +1673,7 @@
 	/* Enable Big Mac hash table filter. */
 	HMD(("happy_meal_init: enable hash rx_cfg_old[%08x], ",
 	     hme_read32(hp, bregs + BMAC_RXCFG)));
-	rxcfg = BIGMAC_RXCFG_HENABLE;
+	rxcfg = BIGMAC_RXCFG_HENABLE | BIGMAC_RXCFG_REJME;
 	if (hp->dev->flags & IFF_PROMISC)
 		rxcfg |= BIGMAC_RXCFG_PMISC;
 	hme_write32(hp, bregs + BMAC_RXCFG, rxcfg);
@@ -1711,7 +1686,14 @@
 	regtmp = 0;
 	if (hp->happy_flags & HFLAG_FULL)
 		regtmp |= BIGMAC_TXCFG_FULLDPLX;
-	hme_write32(hp, bregs + BMAC_TXCFG, regtmp | BIGMAC_TXCFG_DGIVEUP);
+
+	/* Don't turn on the "don't give up" bit for now.  It could cause hme
+	 * to deadlock with the PHY if a Jabber occurs.
+	 */
+	hme_write32(hp, bregs + BMAC_TXCFG, regtmp /*| BIGMAC_TXCFG_DGIVEUP*/);
+
+	/* Give up after 16 TX attempts. */
+	hme_write32(hp, bregs + BMAC_ALIMIT, 16);
 
 	/* Enable the output drivers no matter what. */
 	regtmp = BIGMAC_XCFG_ODENABLE;
@@ -1744,6 +1726,7 @@
 	return 0;
 }
 
+/* hp->happy_lock must be held */
 static void happy_meal_set_initial_advertisement(struct happy_meal *hp)
 {
 	unsigned long tregs	= hp->tcvregs;
@@ -1801,6 +1784,8 @@
 
 /* Once status is latched (by happy_meal_interrupt) it is cleared by
  * the hardware, so we cannot re-read it and get a correct value.
+ *
+ * hp->happy_lock must be held
  */
 static int happy_meal_is_not_so_happy(struct happy_meal *hp, u32 status)
 {
@@ -1909,12 +1894,13 @@
 
 	if (reset) {
 		printk(KERN_NOTICE "%s: Resetting...\n", hp->dev->name);
-		happy_meal_init(hp, 1);
+		happy_meal_init(hp);
 		return 1;
 	}
 	return 0;
 }
 
+/* hp->happy_lock must be held */
 static void happy_meal_mif_interrupt(struct happy_meal *hp)
 {
 	unsigned long tregs = hp->tcvregs;
@@ -1948,6 +1934,7 @@
 #define TXD(x)
 #endif
 
+/* hp->happy_lock must be held */
 static void happy_meal_tx(struct happy_meal *hp)
 {
 	struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
@@ -1955,8 +1942,6 @@
 	struct net_device *dev = hp->dev;
 	int elem;
 
-	spin_lock(&hp->happy_lock);
-
 	elem = hp->tx_old;
 	TXD(("TX<"));
 	while (elem != hp->tx_new) {
@@ -2000,10 +1985,8 @@
 	TXD((">"));
 
 	if (netif_queue_stopped(dev) &&
-	    TX_BUFFS_AVAIL(hp) > 0)
+	    TX_BUFFS_AVAIL(hp) > (MAX_SKB_FRAGS + 1))
 		netif_wake_queue(dev);
-
-	spin_unlock(&hp->happy_lock);
 }
 
 #ifdef RXDEBUG
@@ -2018,6 +2001,8 @@
  * with all of the packets it has DMA'd in.  So now I just drop the entire
  * ring when we cannot get a new skb and give them all back to the happy meal,
  * maybe things will be "happier" now.
+ *
+ * hp->happy_lock must be held
  */
 static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
 {
@@ -2127,10 +2112,12 @@
 
 	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
+	spin_lock(&hp->happy_lock);
+
 	if (happy_status & GREG_STAT_ERRORS) {
 		HMD(("ERRORS "));
 		if (happy_meal_is_not_so_happy(hp, /* un- */ happy_status))
-			return;
+			goto out;
 	}
 
 	if (happy_status & GREG_STAT_MIFIRQ) {
@@ -2149,6 +2136,8 @@
 	}
 
 	HMD(("done\n"));
+out:
+	spin_unlock(&hp->happy_lock);
 }
 
 #ifdef CONFIG_SBUS
@@ -2170,10 +2159,12 @@
 				      GREG_STAT_RXTOHOST)))
 			continue;
 
+		spin_lock(&hp->happy_lock);
+
 		if (happy_status & GREG_STAT_ERRORS) {
 			HMD(("ERRORS "));
 			if (happy_meal_is_not_so_happy(hp, happy_status))
-				break;
+				goto next;
 		}
 
 		if (happy_status & GREG_STAT_MIFIRQ) {
@@ -2190,6 +2181,9 @@
 			HMD(("RXTOHOST "));
 			happy_meal_rx(hp, dev);
 		}
+
+	next:
+		spin_unlock(&hp->happy_lock);
 	}
 	HMD(("done\n"));
 }
@@ -2222,7 +2216,11 @@
 	}
 
 	HMD(("to happy_meal_init\n"));
-	res = happy_meal_init(hp, 0);
+
+	spin_lock_irq(&hp->happy_lock);
+	res = happy_meal_init(hp);
+	spin_unlock_irq(&hp->happy_lock);
+
 	if (res && ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO))
 		free_irq(dev->irq, dev);
 	return res;
@@ -2232,12 +2230,15 @@
 {
 	struct happy_meal *hp = dev->priv;
 
+	spin_lock_irq(&hp->happy_lock);
 	happy_meal_stop(hp, hp->gregs);
 	happy_meal_clean_rings(hp);
 
 	/* If auto-negotiation timer is running, kill it. */
 	del_timer(&hp->happy_timer);
 
+	spin_unlock_irq(&hp->happy_lock);
+
 	/* On Quattro QFE cards, all hme interrupts are concentrated
 	 * into a single source which we register handling at probe
 	 * time and never unregister.
@@ -2254,7 +2255,6 @@
 #define SXD(x)
 #endif
 
-#ifdef CONFIG_SBUS
 static void happy_meal_tx_timeout(struct net_device *dev)
 {
 	struct happy_meal *hp = dev->priv;
@@ -2265,10 +2265,13 @@
 		hme_read32(hp, hp->gregs + GREG_STAT),
 		hme_read32(hp, hp->etxregs + ETX_CFG),
 		hme_read32(hp, hp->bigmacregs + BMAC_TXCFG));
-	happy_meal_init(hp, 0);
+
+	spin_lock_irq(&hp->happy_lock);
+	happy_meal_init(hp);
+	spin_unlock_irq(&hp->happy_lock);
+
 	netif_wake_queue(dev);
 }
-#endif
 
 static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -2293,6 +2296,8 @@
  	if (TX_BUFFS_AVAIL(hp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
 		spin_unlock_irq(&hp->happy_lock);
+		printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n",
+		       dev->name);
 		return 1;
 	}
 
@@ -2345,7 +2350,7 @@
 
 	hp->tx_new = entry;
 
-	if (TX_BUFFS_AVAIL(hp) <= 0)
+	if (TX_BUFFS_AVAIL(hp) <= (MAX_SKB_FRAGS + 1))
 		netif_stop_queue(dev);
 
 	/* Get it going. */
@@ -2363,7 +2368,10 @@
 {
 	struct happy_meal *hp = dev->priv;
 
+	spin_lock_irq(&hp->happy_lock);
 	happy_meal_get_counters(hp, hp->bigmacregs);
+	spin_unlock_irq(&hp->happy_lock);
+
 	return &hp->net_stats;
 }
 
@@ -2376,7 +2384,8 @@
 	int i;
 	u32 crc;
 
-	/* Lock out others. */
+	spin_lock_irq(&hp->happy_lock);
+
 	netif_stop_queue(dev);
 
 	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
@@ -2410,8 +2419,9 @@
 		hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
 	}
 
-	/* Let us get going again. */
 	netif_wake_queue(dev);
+
+	spin_unlock_irq(&hp->happy_lock);
 }
 
 /* Ethtool support... */
@@ -2439,8 +2449,11 @@
 		ecmd.phy_address = 0; /* XXX fixed PHYAD */
 
 		/* Record PHY settings. */
+		spin_lock_irq(&hp->happy_lock);
 		hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, MII_BMCR);
 		hp->sw_lpa = happy_meal_tcvr_read(hp, hp->tcvregs, MII_LPA);
+		spin_unlock_irq(&hp->happy_lock);
+
 		if (hp->sw_bmcr & BMCR_ANENABLE) {
 			ecmd.autoneg = AUTONEG_ENABLE;
 			ecmd.speed =
@@ -2482,10 +2495,12 @@
 			return -EINVAL;
 
 		/* Ok, do it to it. */
+		spin_lock_irq(&hp->happy_lock);
 		del_timer(&hp->happy_timer);
 		happy_meal_begin_auto_negotiation(hp,
 						  hp->tcvregs,
 						  &ecmd);
+		spin_unlock_irq(&hp->happy_lock);
 
 		return 0;
 	} else
@@ -2657,7 +2672,7 @@
 	}
 
 	err = -ENOMEM;
-	dev = init_etherdev(NULL, sizeof(struct happy_meal));
+	dev = alloc_etherdev(sizeof(struct happy_meal));
 	if (!dev)
 		goto err_out;
 	SET_MODULE_OWNER(dev);
@@ -2665,13 +2680,6 @@
 	if (hme_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
 
-	if (qfe_slot != -1)
-		printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ",
-		       dev->name, qfe_slot);
-	else
-		printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ",
-		       dev->name);
-
 	/* If user did not specify a MAC address specifically, use
 	 * the Quattro local-mac-address property...
 	 */
@@ -2682,6 +2690,7 @@
 	if (i < 6) { /* a mac address was given */
 		for (i = 0; i < 6; i++)
 			dev->dev_addr[i] = macaddr[i];
+		macaddr[5]++;
 	} else if (qfe_slot != -1 &&
 		   prom_getproplen(sdev->prom_node,
 				   "local-mac-address") == 6) {
@@ -2691,11 +2700,6 @@
 		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 	}
 
-	for (i = 0; i < 6; i++)
-		printk("%2.2x%c",
-		       dev->dev_addr[i], i == 5 ? ' ' : ':');
-	printk("\n");
-
 	hp = dev->priv;
 	memset(hp, 0, sizeof(*hp));
 
@@ -2818,19 +2822,42 @@
 	/* Grrr, Happy Meal comes up by default not advertising
 	 * full duplex 100baseT capabilities, fix this.
 	 */
+	spin_lock_irq(&hp->happy_lock);
 	happy_meal_set_initial_advertisement(hp);
+	spin_unlock_irq(&hp->happy_lock);
 
-	ether_setup(dev);
+	if (register_netdev(hp->dev)) {
+		printk(KERN_ERR "happymeal: Cannot register net device, "
+		       "aborting.\n");
+		goto err_out_free_consistent;
+	}
+
+	if (qfe_slot != -1)
+		printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ",
+		       dev->name, qfe_slot);
+	else
+		printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ",
+		       dev->name);
+
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c",
+		       dev->dev_addr[i], i == 5 ? ' ' : ':');
+	printk("\n");
 
 	/* We are home free at this point, link us in to the happy
 	 * device list.
 	 */
-	dev->ifindex = dev_new_index();
 	hp->next_module = root_happy_dev;
 	root_happy_dev = hp;
 
 	return 0;
 
+err_out_free_consistent:
+	sbus_free_consistent(hp->happy_dev,
+			     PAGE_SIZE,
+			     hp->happy_block,
+			     hp->hblock_dvma);
+
 err_out_iounmap:
 	if (hp->gregs)
 		sbus_iounmap(hp->gregs, GREG_REG_SIZE);
@@ -2844,7 +2871,6 @@
 		sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
 
 err_out_free_netdev:
-	unregister_netdev(dev);
 	kfree(dev);
 
 err_out:
@@ -2853,6 +2879,104 @@
 #endif
 
 #ifdef CONFIG_PCI
+#ifndef __sparc__
+static int is_quattro_p(struct pci_dev *pdev)
+{
+	struct pci_dev *busdev = pdev->bus->self;
+	struct list_head *tmp;
+	int n_hmes;
+
+	if (busdev->vendor != PCI_VENDOR_ID_DEC ||
+	    busdev->device != PCI_DEVICE_ID_DEC_21153)
+		return 0;
+
+	n_hmes = 0;
+	tmp = pdev->bus->devices.next;
+	while (tmp != &pdev->bus->devices) {
+		struct pci_dev *this_pdev = pci_dev_b(tmp);
+
+		if (this_pdev->vendor == PCI_VENDOR_ID_SUN &&
+		    this_pdev->device == PCI_DEVICE_ID_SUN_HAPPYMEAL)
+			n_hmes++;
+
+		tmp = tmp->next;
+	}
+
+	if (n_hmes != 4)
+		return 0;
+
+	return 1;
+}
+
+/* Fetch MAC address from vital product data of PCI ROM. */
+static void find_eth_addr_in_vpd(void *rom_base, int len, int index, unsigned char *dev_addr)
+{
+	int this_offset;
+
+	for (this_offset = 0x20; this_offset < len; this_offset++) {
+		void *p = rom_base + this_offset;
+
+		if (readb(p + 0) != 0x90 ||
+		    readb(p + 1) != 0x00 ||
+		    readb(p + 2) != 0x09 ||
+		    readb(p + 3) != 0x4e ||
+		    readb(p + 4) != 0x41 ||
+		    readb(p + 5) != 0x06)
+			continue;
+
+		this_offset += 6;
+		p += 6;
+
+		if (index == 0) {
+			int i;
+
+			for (i = 0; i < 6; i++)
+				dev_addr[i] = readb(p + i);
+			break;
+		}
+		index--;
+	}
+}
+
+static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
+{
+	u32 rom_reg_orig;
+	void *p;
+	int index;
+
+	index = 0;
+	if (is_quattro_p(pdev))
+		index = PCI_SLOT(pdev->devfn);
+
+	if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
+		if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
+			goto use_random;
+	}
+
+	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
+	pci_write_config_dword(pdev, pdev->rom_base_reg,
+			       rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+
+	p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
+	if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
+		find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
+
+	if (p != NULL)
+		iounmap(p);
+
+	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
+	return;
+
+use_random:
+	/* Sun MAC prefix then 3 random bytes. */
+	dev_addr[0] = 0x08;
+	dev_addr[1] = 0x00;
+	dev_addr[2] = 0x20;
+	get_random_bytes(dev_addr, 3);
+	return;
+}
+#endif /* !(__sparc__) */
+
 static int __init happy_meal_pci_init(struct pci_dev *pdev)
 {
 	struct quattro *qp = NULL;
@@ -2878,8 +3002,10 @@
 	
 	prom_getstring(node, "name", prom_name, sizeof(prom_name));
 #else
-/* This needs to be corrected... -DaveM */
-	strcpy(prom_name, "qfe");
+	if (is_quattro_p(pdev))
+		strcpy(prom_name, "SUNW,qfe");
+	else
+		strcpy(prom_name, "SUNW,hme");
 #endif
 
 	err = -ENODEV;
@@ -2894,7 +3020,7 @@
 			goto err_out;
 	}
 
-	dev = init_etherdev(NULL, sizeof(struct happy_meal));
+	dev = alloc_etherdev(sizeof(struct happy_meal));
 	err = -ENOMEM;
 	if (!dev)
 		goto err_out;
@@ -2903,29 +3029,6 @@
 	if (hme_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
 
-	if (!qfe_slot) {
-		struct pci_dev *qpdev = qp->quattro_dev;
-
-		prom_name[0] = 0;
-		if (!strncmp(dev->name, "eth", 3)) {
-			int i = simple_strtoul(dev->name + 3, NULL, 10);
-			sprintf(prom_name, "-%d", i + 3);
-		}
-		printk(KERN_INFO "%s%s: Quattro HME (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, prom_name);
-		if (qpdev->vendor == PCI_VENDOR_ID_DEC &&
-		    qpdev->device == PCI_DEVICE_ID_DEC_21153)
-			printk("DEC 21153 PCI Bridge\n");
-		else
-			printk("unknown bridge %04x.%04x\n", 
-				qpdev->vendor, qpdev->device);
-	}
-	if (qfe_slot != -1)
-		printk(KERN_INFO "%s: Quattro HME slot %d (PCI/CheerIO) 10/100baseT Ethernet ",
-		       dev->name, qfe_slot);
-	else
-		printk(KERN_INFO "%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ",
-		       dev->name);
-
 	dev->base_addr = (long) pdev;
 
 	hp = (struct happy_meal *)dev->priv;
@@ -2947,9 +3050,15 @@
 		printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n");
 		goto err_out_clear_quattro;
 	}
+	if (pci_request_regions(pdev, dev->name)) {
+		printk(KERN_ERR "happymeal(PCI): Cannot obtain PCI resources, "
+		       "aborting.\n");
+		goto err_out_clear_quattro;
+	}
+
 	if ((hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000)) == 0) {
 		printk(KERN_ERR "happymeal(PCI): Unable to remap card memory.\n");
-		return -ENODEV;
+		goto err_out_free_res;
 	}
 
 	for (i = 0; i < 6; i++) {
@@ -2959,6 +3068,7 @@
 	if (i < 6) { /* a mac address was given */
 		for (i = 0; i < 6; i++)
 			dev->dev_addr[i] = macaddr[i];
+		macaddr[5]++;
 	} else {
 #ifdef __sparc__
 		if (qfe_slot != -1 &&
@@ -2969,15 +3079,10 @@
 			memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 		}
 #else
-		memset(dev->dev_addr, 0, 6);
+		get_hme_mac_nonsparc(pdev, &dev->dev_addr[0]);
 #endif
 	}
 	
-	for (i = 0; i < 6; i++)
-		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':');
-
-	printk("\n");
-
 	/* Layout registers. */
 	hp->gregs      = (hpreg_base + 0x0000UL);
 	hp->etxregs    = (hpreg_base + 0x2000UL);
@@ -3032,6 +3137,8 @@
 	dev->hard_start_xmit = &happy_meal_start_xmit;
 	dev->get_stats = &happy_meal_get_stats;
 	dev->set_multicast_list = &happy_meal_set_multicast;
+	dev->tx_timeout = &happy_meal_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
 	dev->do_ioctl = &happy_meal_ioctl;
 	dev->irq = pdev->irq;
 	dev->dma = 0;
@@ -3054,14 +3161,48 @@
 	/* Grrr, Happy Meal comes up by default not advertising
 	 * full duplex 100baseT capabilities, fix this.
 	 */
+	spin_lock_irq(&hp->happy_lock);
 	happy_meal_set_initial_advertisement(hp);
+	spin_unlock_irq(&hp->happy_lock);
+
+	if (register_netdev(hp->dev)) {
+		printk(KERN_ERR "happymeal(PCI): Cannot register net device, "
+		       "aborting.\n");
+		goto err_out_iounmap;
+	}
+
+	if (!qfe_slot) {
+		struct pci_dev *qpdev = qp->quattro_dev;
 
-	ether_setup(dev);
+		prom_name[0] = 0;
+		if (!strncmp(dev->name, "eth", 3)) {
+			int i = simple_strtoul(dev->name + 3, NULL, 10);
+			sprintf(prom_name, "-%d", i + 3);
+		}
+		printk(KERN_INFO "%s%s: Quattro HME (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, prom_name);
+		if (qpdev->vendor == PCI_VENDOR_ID_DEC &&
+		    qpdev->device == PCI_DEVICE_ID_DEC_21153)
+			printk("DEC 21153 PCI Bridge\n");
+		else
+			printk("unknown bridge %04x.%04x\n", 
+				qpdev->vendor, qpdev->device);
+	}
+
+	if (qfe_slot != -1)
+		printk(KERN_INFO "%s: Quattro HME slot %d (PCI/CheerIO) 10/100baseT Ethernet ",
+		       dev->name, qfe_slot);
+	else
+		printk(KERN_INFO "%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ",
+		       dev->name);
+
+	for (i = 0; i < 6; i++)
+		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':');
+
+	printk("\n");
 
 	/* We are home free at this point, link us in to the happy
 	 * device list.
 	 */
-	dev->ifindex = dev_new_index();
 	hp->next_module = root_happy_dev;
 	root_happy_dev = hp;
 
@@ -3070,11 +3211,13 @@
 err_out_iounmap:
 	iounmap((void *)hp->gregs);
 
+err_out_free_res:
+	pci_release_regions(pdev);
+
 err_out_clear_quattro:
 	if (qp != NULL)
 		qp->happy_meals[qfe_slot] = NULL;
 
-	unregister_netdev(dev);
 	kfree(dev);
 
 err_out:
@@ -3125,6 +3268,7 @@
 				       PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) {
 		if (pci_enable_device(pdev))
 			continue;
+		pci_set_master(pdev);
 		cards++;
 		happy_meal_pci_init(pdev);
 	}
@@ -3165,12 +3309,18 @@
 	while (root_happy_dev) {
 		struct happy_meal *hp = root_happy_dev;
 		struct happy_meal *next = root_happy_dev->next_module;
+		struct net_device *dev = hp->dev;
+
+		/* Unregister netdev before unmapping registers as this
+		 * call can end up trying to access those registers.
+		 */
+		unregister_netdev(dev);
 
 #ifdef CONFIG_SBUS
 		if (!(hp->happy_flags & HFLAG_PCI)) {
 			if (hp->happy_flags & HFLAG_QUATTRO) {
 				if (hp->qfe_parent != last_seen_qfe) {
-					free_irq(hp->dev->irq, hp->qfe_parent);
+					free_irq(dev->irq, hp->qfe_parent);
 					last_seen_qfe = hp->qfe_parent;
 				}
 			}
@@ -3193,12 +3343,35 @@
 					    hp->happy_block,
 					    hp->hblock_dvma);
 			iounmap((void *)hp->gregs);
+			pci_release_regions(hp->happy_dev);
 		}
 #endif
-		unregister_netdev(hp->dev);
-		kfree(hp->dev);
+		kfree(dev);
+
 		root_happy_dev = next;
 	}
+
+	/* Now cleanup the quattro lists. */
+#ifdef CONFIG_SBUS
+	while (qfe_sbus_list) {
+		struct quattro *qfe = qfe_sbus_list;
+		struct quattro *next = qfe->next;
+
+		kfree(qfe);
+
+		qfe_sbus_list = next;
+	}
+#endif
+#ifdef CONFIG_PCI
+	while (qfe_pci_list) {
+		struct quattro *qfe = qfe_pci_list;
+		struct quattro *next = qfe->next;
+
+		kfree(qfe);
+
+		qfe_pci_list = next;
+	}
+#endif
 }
 
 module_init(happy_meal_probe);
diff -Nru a/drivers/net/sunhme.h b/drivers/net/sunhme.h
--- a/drivers/net/sunhme.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/sunhme.h	Sun Apr 14 12:16:58 2002
@@ -227,7 +227,7 @@
 #define BIGMAC_RXCFG_PMISC    0x00000040 /* Enable promiscous mode          */
 #define BIGMAC_RXCFG_DERR     0x00000080 /* Disable error checking          */
 #define BIGMAC_RXCFG_DCRCS    0x00000100 /* Disable CRC stripping           */
-#define BIGMAC_RXCFG_ME       0x00000200 /* Receive packets addressed to me */
+#define BIGMAC_RXCFG_REJME    0x00000200 /* Reject packets addressed to me  */
 #define BIGMAC_RXCFG_PGRP     0x00000400 /* Enable promisc group mode       */
 #define BIGMAC_RXCFG_HENABLE  0x00000800 /* Enable the hash filter          */
 #define BIGMAC_RXCFG_AENABLE  0x00001000 /* Enable the address filter       */
diff -Nru a/drivers/net/tc35815.c b/drivers/net/tc35815.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/net/tc35815.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,1779 @@
+/* tc35815.c: A TOSHIBA TC35815CF PCI 10/100Mbps ethernet driver for linux.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc. 
+ *                ahennessy@mvista.com
+ *
+ * Based on skelton.c by Donald Becker.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.
+ */
+
+static const char *version =
+	"tc35815.c:v0.00 26/07/2000 by Toshiba Corporation\n";
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <asm/byteorder.h>
+
+
+/*
+ * The name of the card. Is used for messages and in the requests for
+ * io regions, irqs and dma channels
+ */
+static const char* cardname = "TC35815CF";
+#define TC35815_PROC_ENTRY "net/tc35815"
+
+#define TC35815_MODULE_NAME "TC35815CF"
+#define TX_TIMEOUT (4*HZ)
+
+/* First, a few definitions that the brave might change. */
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef TC35815_DEBUG
+#define TC35815_DEBUG 1
+#endif
+static unsigned int tc35815_debug = TC35815_DEBUG;
+
+#define GATHER_TXINT	/* On-Demand Tx Interrupt */
+
+#define vtonocache(p)	KSEG1ADDR(virt_to_phys(p))
+
+/*
+ * Registers
+ */
+struct tc35815_regs {
+	volatile __u32 DMA_Ctl;		/* 0x00 */
+	volatile __u32 TxFrmPtr;
+	volatile __u32 TxThrsh;
+	volatile __u32 TxPollCtr;
+	volatile __u32 BLFrmPtr;
+	volatile __u32 RxFragSize;
+	volatile __u32 Int_En;
+	volatile __u32 FDA_Bas;
+	volatile __u32 FDA_Lim;		/* 0x20 */
+	volatile __u32 Int_Src;
+	volatile __u32 unused0[2];
+	volatile __u32 PauseCnt;
+	volatile __u32 RemPauCnt;
+	volatile __u32 TxCtlFrmStat;
+	volatile __u32 unused1;
+	volatile __u32 MAC_Ctl;		/* 0x40 */
+	volatile __u32 CAM_Ctl;
+	volatile __u32 Tx_Ctl;
+	volatile __u32 Tx_Stat;
+	volatile __u32 Rx_Ctl;
+	volatile __u32 Rx_Stat;
+	volatile __u32 MD_Data;
+	volatile __u32 MD_CA;
+	volatile __u32 CAM_Adr;		/* 0x60 */
+	volatile __u32 CAM_Data;
+	volatile __u32 CAM_Ena;
+	volatile __u32 PROM_Ctl;
+	volatile __u32 PROM_Data;
+	volatile __u32 Algn_Cnt;
+	volatile __u32 CRC_Cnt;
+	volatile __u32 Miss_Cnt;
+};
+
+/*
+ * Bit assignments
+ */
+/* DMA_Ctl bit asign ------------------------------------------------------- */
+#define DMA_IntMask            0x00040000 /* 1:Interupt mask                 */
+#define DMA_SWIntReq           0x00020000 /* 1:Software Interrupt request    */
+#define DMA_TxWakeUp           0x00010000 /* 1:Transmit Wake Up              */
+#define DMA_RxBigE             0x00008000 /* 1:Receive Big Endian            */
+#define DMA_TxBigE             0x00004000 /* 1:Transmit Big Endian           */
+#define DMA_TestMode           0x00002000 /* 1:Test Mode                     */
+#define DMA_PowrMgmnt          0x00001000 /* 1:Power Management              */
+#define DMA_DmBurst_Mask       0x000001fc /* DMA Burst size                  */
+
+/* RxFragSize bit asign ---------------------------------------------------- */
+#define RxFrag_EnPack          0x00008000 /* 1:Enable Packing                */
+#define RxFrag_MinFragMask     0x00000ffc /* Minimum Fragment                */
+
+/* MAC_Ctl bit asign ------------------------------------------------------- */
+#define MAC_Link10             0x00008000 /* 1:Link Status 10Mbits           */
+#define MAC_EnMissRoll         0x00002000 /* 1:Enable Missed Roll            */
+#define MAC_MissRoll           0x00000400 /* 1:Missed Roll                   */
+#define MAC_Loop10             0x00000080 /* 1:Loop 10 Mbps                  */
+#define MAC_Conn_Auto          0x00000000 /*00:Connection mode (Automatic)   */
+#define MAC_Conn_10M           0x00000020 /*01:                (10Mbps endec)*/
+#define MAC_Conn_Mll           0x00000040 /*10:                (Mll clock)   */
+#define MAC_MacLoop            0x00000010 /* 1:MAC Loopback                  */
+#define MAC_FullDup            0x00000008 /* 1:Full Duplex 0:Half Duplex     */
+#define MAC_Reset              0x00000004 /* 1:Software Reset                */
+#define MAC_HaltImm            0x00000002 /* 1:Halt Immediate                */
+#define MAC_HaltReq            0x00000001 /* 1:Halt request                  */
+
+/* PROM_Ctl bit asign ------------------------------------------------------ */
+#define PROM_Busy              0x00008000 /* 1:Busy (Start Operation)        */
+#define PROM_Read              0x00004000 /*10:Read operation                */
+#define PROM_Write             0x00002000 /*01:Write operation               */
+#define PROM_Erase             0x00006000 /*11:Erase operation               */
+                                          /*00:Enable or Disable Writting,   */
+                                          /*      as specified in PROM_Addr. */
+#define PROM_Addr_Ena          0x00000030 /*11xxxx:PROM Write enable         */
+                                          /*00xxxx:           disable        */
+
+/* CAM_Ctl bit asign ------------------------------------------------------- */
+#define CAM_CompEn             0x00000010 /* 1:CAM Compare Enable            */
+#define CAM_NegCAM             0x00000008 /* 1:Reject packets CAM recognizes,*/
+                                          /*                    accept other */
+#define CAM_BroadAcc           0x00000004 /* 1:Broadcast assept              */
+#define CAM_GroupAcc           0x00000002 /* 1:Multicast assept              */
+#define CAM_StationAcc         0x00000001 /* 1:unicast accept                */
+
+/* CAM_Ena bit asign ------------------------------------------------------- */
+#define CAM_ENTRY_MAX                  21   /* CAM Data entry max count      */
+#define CAM_Ena_Mask ((1<<CAM_ENTRY_MAX)-1) /* CAM Enable bits (Max 21bits)  */
+#define CAM_Ena_Bit(index)         (1<<(index))
+#define CAM_ENTRY_DESTINATION	0
+#define CAM_ENTRY_SOURCE	1
+#define CAM_ENTRY_MACCTL	20
+
+/* Tx_Ctl bit asign -------------------------------------------------------- */
+#define Tx_En                  0x00000001 /* 1:Transmit enable               */
+#define Tx_TxHalt              0x00000002 /* 1:Transmit Halt Request         */
+#define Tx_NoPad               0x00000004 /* 1:Suppress Padding              */
+#define Tx_NoCRC               0x00000008 /* 1:Suppress Padding              */
+#define Tx_FBack               0x00000010 /* 1:Fast Back-off                 */
+#define Tx_EnUnder             0x00000100 /* 1:Enable Underrun               */
+#define Tx_EnExDefer           0x00000200 /* 1:Enable Excessive Deferral     */
+#define Tx_EnLCarr             0x00000400 /* 1:Enable Lost Carrier           */
+#define Tx_EnExColl            0x00000800 /* 1:Enable Excessive Collision    */
+#define Tx_EnLateColl          0x00001000 /* 1:Enable Late Collision         */
+#define Tx_EnTxPar             0x00002000 /* 1:Enable Transmit Parity        */
+#define Tx_EnComp              0x00004000 /* 1:Enable Completion             */
+
+/* Tx_Stat bit asign ------------------------------------------------------- */
+#define Tx_TxColl_MASK         0x0000000F /* Tx Collision Count              */
+#define Tx_ExColl              0x00000010 /* Excessive Collision             */
+#define Tx_TXDefer             0x00000020 /* Transmit Defered                */
+#define Tx_Paused              0x00000040 /* Transmit Paused                 */
+#define Tx_IntTx               0x00000080 /* Interrupt on Tx                 */
+#define Tx_Under               0x00000100 /* Underrun                        */
+#define Tx_Defer               0x00000200 /* Deferral                        */
+#define Tx_NCarr               0x00000400 /* No Carrier                      */
+#define Tx_10Stat              0x00000800 /* 10Mbps Status                   */
+#define Tx_LateColl            0x00001000 /* Late Collision                  */
+#define Tx_TxPar               0x00002000 /* Tx Parity Error                 */
+#define Tx_Comp                0x00004000 /* Completion                      */
+#define Tx_Halted              0x00008000 /* Tx Halted                       */
+#define Tx_SQErr               0x00010000 /* Signal Quality Error(SQE)       */
+
+/* Rx_Ctl bit asign -------------------------------------------------------- */
+#define Rx_EnGood              0x00004000 /* 1:Enable Good                   */
+#define Rx_EnRxPar             0x00002000 /* 1:Enable Receive Parity         */
+#define Rx_EnLongErr           0x00000800 /* 1:Enable Long Error             */
+#define Rx_EnOver              0x00000400 /* 1:Enable OverFlow               */
+#define Rx_EnCRCErr            0x00000200 /* 1:Enable CRC Error              */
+#define Rx_EnAlign             0x00000100 /* 1:Enable Alignment              */
+#define Rx_IgnoreCRC           0x00000040 /* 1:Ignore CRC Value              */
+#define Rx_StripCRC            0x00000010 /* 1:Strip CRC Value               */
+#define Rx_ShortEn             0x00000008 /* 1:Short Enable                  */
+#define Rx_LongEn              0x00000004 /* 1:Long Enable                   */
+#define Rx_RxHalt              0x00000002 /* 1:Receive Halt Request          */
+#define Rx_RxEn                0x00000001 /* 1:Receive Intrrupt Enable       */
+
+/* Rx_Stat bit asign ------------------------------------------------------- */
+#define Rx_Halted              0x00008000 /* Rx Halted                       */
+#define Rx_Good                0x00004000 /* Rx Good                         */
+#define Rx_RxPar               0x00002000 /* Rx Parity Error                 */
+                            /* 0x00001000    not use                         */
+#define Rx_LongErr             0x00000800 /* Rx Long Error                   */
+#define Rx_Over                0x00000400 /* Rx Overflow                     */
+#define Rx_CRCErr              0x00000200 /* Rx CRC Error                    */
+#define Rx_Align               0x00000100 /* Rx Alignment Error              */
+#define Rx_10Stat              0x00000080 /* Rx 10Mbps Status                */
+#define Rx_IntRx               0x00000040 /* Rx Interrupt                    */
+#define Rx_CtlRecd             0x00000020 /* Rx Control Receive              */
+
+#define Rx_Stat_Mask           0x0000EFC0 /* Rx All Status Mask              */
+
+/* Int_En bit asign -------------------------------------------------------- */
+#define Int_NRAbtEn            0x00000800 /* 1:Non-recoverable Abort Enable  */
+#define Int_TxCtlCmpEn         0x00000400 /* 1:Transmit Control Complete Enable */
+#define Int_DmParErrEn         0x00000200 /* 1:DMA Parity Error Enable       */
+#define Int_DParDEn            0x00000100 /* 1:Data Parity Error Enable      */
+#define Int_EarNotEn           0x00000080 /* 1:Early Notify Enable           */
+#define Int_DParErrEn          0x00000040 /* 1:Detected Parity Error Enable  */
+#define Int_SSysErrEn          0x00000020 /* 1:Signalled System Error Enable */
+#define Int_RMasAbtEn          0x00000010 /* 1:Received Master Abort Enable  */
+#define Int_RTargAbtEn         0x00000008 /* 1:Received Target Abort Enable  */
+#define Int_STargAbtEn         0x00000004 /* 1:Signalled Target Abort Enable */
+#define Int_BLExEn             0x00000002 /* 1:Buffer List Exhausted Enable  */
+#define Int_FDAExEn            0x00000001 /* 1:Free Descriptor Area          */
+                                          /*               Exhausted Enable  */
+
+/* Int_Src bit asign ------------------------------------------------------- */
+#define Int_NRabt              0x00004000 /* 1:Non Recoverable error         */
+#define Int_DmParErrStat       0x00002000 /* 1:DMA Parity Error & Clear      */
+#define Int_BLEx               0x00001000 /* 1:Buffer List Empty & Clear     */
+#define Int_FDAEx              0x00000800 /* 1:FDA Empty & Clear             */
+#define Int_IntNRAbt           0x00000400 /* 1:Non Recoverable Abort         */
+#define	Int_IntCmp             0x00000200 /* 1:MAC control packet complete   */
+#define Int_IntExBD            0x00000100 /* 1:Interrupt Extra BD & Clear    */
+#define Int_DmParErr           0x00000080 /* 1:DMA Parity Error & Clear      */
+#define Int_IntEarNot          0x00000040 /* 1:Receive Data write & Clear    */
+#define Int_SWInt              0x00000020 /* 1:Software request & Clear      */
+#define Int_IntBLEx            0x00000010 /* 1:Buffer List Empty & Clear     */
+#define Int_IntFDAEx           0x00000008 /* 1:FDA Empty & Clear             */
+#define Int_IntPCI             0x00000004 /* 1:PCI controller & Clear        */
+#define Int_IntMacRx           0x00000002 /* 1:Rx controller & Clear         */
+#define Int_IntMacTx           0x00000001 /* 1:Tx controller & Clear         */
+
+/* MD_CA bit asign --------------------------------------------------------- */
+#define MD_CA_PreSup           0x00001000 /* 1:Preamble Supress              */
+#define MD_CA_Busy             0x00000800 /* 1:Busy (Start Operation)        */
+#define MD_CA_Wr               0x00000400 /* 1:Write 0:Read                  */
+
+
+/* MII register offsets */
+#define MII_CONTROL             0x0000
+#define MII_STATUS              0x0001
+#define MII_PHY_ID0             0x0002
+#define MII_PHY_ID1             0x0003
+#define MII_ANAR                0x0004
+#define MII_ANLPAR              0x0005
+#define MII_ANER                0x0006
+/* MII Control register bit definitions. */
+#define MIICNTL_FDX             0x0100
+#define MIICNTL_RST_AUTO        0x0200
+#define MIICNTL_ISOLATE         0x0400
+#define MIICNTL_PWRDWN          0x0800
+#define MIICNTL_AUTO            0x1000
+#define MIICNTL_SPEED           0x2000
+#define MIICNTL_LPBK            0x4000
+#define MIICNTL_RESET           0x8000
+/* MII Status register bit significance. */
+#define MIISTAT_EXT             0x0001
+#define MIISTAT_JAB             0x0002
+#define MIISTAT_LINK            0x0004
+#define MIISTAT_CAN_AUTO        0x0008
+#define MIISTAT_FAULT           0x0010
+#define MIISTAT_AUTO_DONE       0x0020
+#define MIISTAT_CAN_T           0x0800
+#define MIISTAT_CAN_T_FDX       0x1000
+#define MIISTAT_CAN_TX          0x2000
+#define MIISTAT_CAN_TX_FDX      0x4000
+#define MIISTAT_CAN_T4          0x8000
+/* MII Auto-Negotiation Expansion/RemoteEnd Register Bits */
+#define MII_AN_TX_FDX           0x0100
+#define MII_AN_TX_HDX           0x0080
+#define MII_AN_10_FDX           0x0040
+#define MII_AN_10_HDX           0x0020
+
+
+/*
+ * Descriptors
+ */
+
+/* Frame descripter */
+struct FDesc {
+	volatile __u32 FDNext;
+	volatile __u32 FDSystem;
+	volatile __u32 FDStat;
+	volatile __u32 FDCtl;
+};
+
+/* Buffer descripter */
+struct BDesc {
+	volatile __u32 BuffData;
+	volatile __u32 BDCtl;
+};
+
+#define FD_ALIGN	16
+
+/* Frame Descripter bit asign ---------------------------------------------- */
+#define FD_FDLength_MASK       0x0000FFFF /* Length MASK                     */
+#define FD_BDCnt_MASK          0x001F0000 /* BD count MASK in FD             */
+#define FD_FrmOpt_MASK         0x7C000000 /* Frame option MASK               */
+#define FD_FrmOpt_BigEndian    0x40000000 /* Tx/Rx */
+#define FD_FrmOpt_IntTx        0x20000000 /* Tx only */
+#define FD_FrmOpt_NoCRC        0x10000000 /* Tx only */
+#define FD_FrmOpt_NoPadding    0x08000000 /* Tx only */
+#define FD_FrmOpt_Packing      0x04000000 /* Rx only */
+#define FD_CownsFD             0x80000000 /* FD Controller owner bit         */
+#define FD_Next_EOL            0x00000001 /* FD EOL indicator                */
+#define FD_BDCnt_SHIFT         16
+
+/* Buffer Descripter bit asign --------------------------------------------- */
+#define BD_BuffLength_MASK     0x0000FFFF /* Recieve Data Size               */
+#define BD_RxBDID_MASK         0x00FF0000 /* BD ID Number MASK               */
+#define BD_RxBDSeqN_MASK       0x7F000000 /* Rx BD Sequence Number           */
+#define BD_CownsBD             0x80000000 /* BD Controller owner bit         */
+#define BD_RxBDID_SHIFT        16
+#define BD_RxBDSeqN_SHIFT      24
+
+
+/* Some useful constants. */
+#undef NO_CHECK_CARRIER	/* Does not check No-Carrier with TP */
+
+#ifdef NO_CHECK_CARRIER
+#define TX_CTL_CMD	(Tx_EnComp | Tx_EnTxPar | Tx_EnLateColl | \
+	Tx_EnExColl | Tx_EnLCarr | Tx_EnExDefer | Tx_EnUnder | \
+	Tx_En)	/* maybe  0x7d01 */
+#else
+#define TX_CTL_CMD	(Tx_EnComp | Tx_EnTxPar | Tx_EnLateColl | \
+	Tx_EnExColl | Tx_EnExDefer | Tx_EnUnder | \
+	Tx_En)	/* maybe  0x7f01 */
+#endif
+#define RX_CTL_CMD	(Rx_EnGood | Rx_EnRxPar | Rx_EnLongErr | Rx_EnOver \
+	| Rx_EnCRCErr | Rx_EnAlign | Rx_RxEn)	/* maybe 0x6f01 */
+
+#define INT_EN_CMD  (Int_NRAbtEn | \
+	 Int_DParDEn | Int_DParErrEn | \
+	Int_SSysErrEn  | Int_RMasAbtEn | Int_RTargAbtEn | \
+	Int_STargAbtEn | \
+	Int_BLExEn  | Int_FDAExEn) /* maybe 0xb7f*/
+
+/* Tuning parameters */
+#define DMA_BURST_SIZE	32
+#define TX_THRESHOLD	1024
+
+#define FD_PAGE_NUM 2
+#define FD_PAGE_ORDER 1
+/* 16 + RX_BUF_PAGES * 8 + RX_FD_NUM * 16 + TX_FD_NUM * 32 <= PAGE_SIZE*2 */
+#define RX_BUF_PAGES	8	/* >= 2 */
+#define RX_FD_NUM	250	/* >= 32 */
+#define TX_FD_NUM	128
+
+struct TxFD {
+	struct FDesc fd;
+	struct BDesc bd;
+	struct BDesc unused;
+};
+
+struct RxFD {
+	struct FDesc fd;
+	struct BDesc bd[0];	/* variable length */
+};
+
+struct FrFD {
+	struct FDesc fd;
+	struct BDesc bd[RX_BUF_PAGES];
+};
+
+
+extern unsigned long tc_readl(volatile __u32 *addr);
+extern void tc_writel(unsigned long data, volatile __u32 *addr);
+
+dma_addr_t priv_dma_handle;
+
+/* Information that need to be kept for each board. */
+struct tc35815_local {
+	struct net_device *next_module;
+
+	/* statistics */
+	struct net_device_stats stats;
+	struct {
+		int max_tx_qlen;
+		int tx_ints;
+		int rx_ints;
+	} lstats;
+
+	int tbusy;
+	int option;
+#define TC35815_OPT_AUTO	0x00
+#define TC35815_OPT_10M	0x01
+#define TC35815_OPT_100M	0x02
+#define TC35815_OPT_FULLDUP	0x04
+	int linkspeed;	/* 10 or 100 */
+	int fullduplex;
+
+	/*
+	 * Transmitting: Batch Mode.
+	 *	1 BD in 1 TxFD.
+	 * Receiving: Packing Mode.
+	 *	1 circular FD for Free Buffer List.
+	 *	RX_BUG_PAGES BD in Free Buffer FD.
+	 *	One Free Buffer BD has PAGE_SIZE data buffer.
+	 */
+        struct pci_dev *pdev;
+	dma_addr_t fd_buf_dma_handle;
+	void * fd_buf;	/* for TxFD, TxFD, FrFD */
+	struct TxFD *tfd_base;
+	int tfd_start;
+	int tfd_end;
+	struct RxFD *rfd_base;
+	struct RxFD *rfd_limit;
+	struct RxFD *rfd_cur;
+	struct FrFD *fbl_ptr;
+	unsigned char fbl_curid;
+	dma_addr_t data_buf_dma_handle[RX_BUF_PAGES];
+	void * data_buf[RX_BUF_PAGES];		/* packing */
+};
+
+/* Index to functions, as function prototypes. */
+
+static int __init tc35815_probe1(struct pci_dev *pdev, unsigned int base_addr, unsigned int irq);
+
+static int	tc35815_open(struct net_device *dev);
+static int	tc35815_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void     tc35815_tx_timeout(struct net_device *dev);
+static void	tc35815_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void	tc35815_rx(struct net_device *dev);
+static void	tc35815_txdone(struct net_device *dev);
+static int	tc35815_close(struct net_device *dev);
+static struct	net_device_stats *tc35815_get_stats(struct net_device *dev);
+static void	tc35815_set_multicast_list(struct net_device *dev);
+
+static void 	tc35815_chip_reset(struct net_device *dev);
+static void 	tc35815_chip_init(struct net_device *dev);
+static void 	tc35815_phy_chip_init(struct net_device *dev);
+static int 	tc35815_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+
+/* A list of all installed tc35815 devices. */
+static struct net_device *root_tc35815_dev = NULL;
+
+/*
+ * PCI device identifiers for "new style" Linux PCI Device Drivers
+ */
+static struct pci_device_id tc35815_pci_tbl[] __devinitdata = {
+    { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+    { 0, }
+};
+
+MODULE_DEVICE_TABLE (pci, tc35815_pci_tbl);
+
+int
+tc35815_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	static int called = 0;
+	int err = 0;
+	int ret;
+
+	if (called)
+		return -ENODEV;
+	called++;
+
+	if (!pci_present())
+		return -ENODEV;
+
+	if (pdev) {
+		unsigned int pci_memaddr;
+		unsigned int pci_irq_line;
+
+		printk(KERN_INFO "tc35815_probe: found device %#08x.%#08x\n", ent->vendor, ent->device);
+
+	        pci_memaddr = pci_resource_start (pdev, 1);
+
+	        printk(KERN_INFO "    pci_memaddr=%#08lx  resource_flags=%#08lx\n", pci_memaddr, pci_resource_flags (pdev, 0));
+
+		if (!pci_memaddr) {
+			printk(KERN_WARNING "no PCI MEM resources, aborting\n");
+			return -ENODEV;
+		}
+		pci_irq_line = pdev->irq;
+		/* irq disabled. */
+		if (pci_irq_line == 0) {
+			printk(KERN_WARNING "no PCI irq, aborting\n");
+			return -ENODEV;
+		}
+
+		ret =  tc35815_probe1(pdev, pci_memaddr, pci_irq_line);
+
+		if (!ret) {
+			if ((err = pci_enable_device(pdev)) < 0) {
+			    printk(KERN_ERR "tc35815_probe: failed to enable device -- err=%d\n", err);
+			    return err;
+			}
+			pci_set_master(pdev);
+		}
+
+		return ret;
+	}
+	return -ENODEV;
+}
+
+static int __init tc35815_probe1(struct pci_dev *pdev, unsigned int base_addr, unsigned int irq)
+{
+	static unsigned version_printed = 0;
+	int i;
+	struct tc35815_local *lp;
+	struct tc35815_regs *tr;
+	struct net_device *dev;
+
+	/* Allocate a new 'dev' if needed. */
+	dev = init_etherdev(NULL, 0);
+	if (dev == NULL)
+		return -ENOMEM;
+
+	if (tc35815_debug  &&  version_printed++ == 0)
+		printk(KERN_DEBUG "%s", version);
+
+	printk(KERN_INFO "%s: %s found at %#x, irq %d\n",
+	       dev->name, cardname, base_addr, irq);
+
+	/* Fill in the 'dev' fields. */
+	dev->irq = irq;
+	dev->base_addr = (unsigned long)ioremap(base_addr,
+						sizeof(struct tc35815_regs));
+	tr = (struct tc35815_regs*)dev->base_addr;
+
+	tc35815_chip_reset(dev);
+
+	/* Retrieve and print the ethernet address. */
+	while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
+		;
+	for (i = 0; i < 6; i += 2) {
+		unsigned short data;
+		tc_writel(PROM_Busy | PROM_Read | (i / 2 + 2), &tr->PROM_Ctl);
+		while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
+			;
+		data = tc_readl(&tr->PROM_Data);
+		dev->dev_addr[i] = data & 0xff;
+		dev->dev_addr[i+1] = data >> 8;
+	}
+	for (i = 0; i < 6; i++)
+		printk(" %2.2x", dev->dev_addr[i]);
+	printk("\n");
+
+	/* Initialize the device structure. */
+	if (dev->priv == NULL) {
+		dev->priv = kmalloc(sizeof(struct tc35815_local), GFP_KERNEL);
+		if (dev->priv == NULL)
+			return -ENODEV;
+	}
+	lp = dev->priv;
+
+	lp->pdev = pdev;
+
+	memset(lp, 0, sizeof(struct tc35815_local));
+
+	lp->next_module = root_tc35815_dev;
+	root_tc35815_dev = dev;
+
+	if (dev->mem_start > 0) {
+		lp->option = dev->mem_start;
+		if ((lp->option & TC35815_OPT_10M) &&
+		    (lp->option & TC35815_OPT_100M)) {
+			/* if both speed speficied, auto select. */
+			lp->option &= ~(TC35815_OPT_10M | TC35815_OPT_100M);
+		}
+	}
+	//XXX fixme
+        lp->option |= TC35815_OPT_10M;
+
+	/* do auto negotiation */
+	tc35815_phy_chip_init(dev);
+	printk(KERN_INFO "%s: linkspeed %dMbps, %s Duplex\n",
+	       dev->name, lp->linkspeed, lp->fullduplex ? "Full" : "Half");
+
+	dev->open		= tc35815_open;
+	dev->stop		= tc35815_close;
+	dev->tx_timeout         = tc35815_tx_timeout;
+	dev->watchdog_timeo     = TX_TIMEOUT;
+	dev->hard_start_xmit	= tc35815_send_packet;
+	dev->get_stats		= tc35815_get_stats;
+	dev->set_multicast_list = tc35815_set_multicast_list;
+
+#if 0	/* XXX called in init_etherdev */
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(dev);
+#endif
+
+	return 0;
+}
+
+
+static int
+tc35815_init_queues(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	int i;
+	unsigned long fd_addr;
+
+	if (!lp->fd_buf) {
+		if (sizeof(struct FDesc) +
+		    sizeof(struct BDesc) * RX_BUF_PAGES +
+		    sizeof(struct FDesc) * RX_FD_NUM +
+		    sizeof(struct TxFD) * TX_FD_NUM > PAGE_SIZE * FD_PAGE_NUM) {
+			printk(KERN_WARNING "%s: Invalid Queue Size.\n", dev->name);
+			return -ENOMEM;
+		}
+
+		if ((lp->fd_buf = (void *)__get_free_pages(GFP_KERNEL, FD_PAGE_ORDER)) == 0)
+			return -ENOMEM;
+		for (i = 0; i < RX_BUF_PAGES; i++) {
+			if ((lp->data_buf[i] = (void *)get_free_page(GFP_KERNEL)) == 0) {
+				while (--i >= 0) {
+					free_page((unsigned long)lp->data_buf[i]);
+					lp->data_buf[i] = 0;
+				}
+				free_page((unsigned long)lp->fd_buf);
+				lp->fd_buf = 0;
+				return -ENOMEM;
+			}
+#ifdef __mips__
+			dma_cache_wback_inv((unsigned long)lp->data_buf[i], PAGE_SIZE * FD_PAGE_NUM);
+#endif
+		}
+#ifdef __mips__
+		dma_cache_wback_inv((unsigned long)lp->fd_buf, PAGE_SIZE * FD_PAGE_NUM);
+#endif
+	} else {
+		clear_page(lp->fd_buf);
+#ifdef __mips__
+		dma_cache_wback_inv((unsigned long)lp->fd_buf, PAGE_SIZE * FD_PAGE_NUM);
+#endif
+	}
+#ifdef __mips__
+	fd_addr = (unsigned long)vtonocache(lp->fd_buf);  
+#else
+	fd_addr = (unsigned long)lp->fd_buf;
+#endif
+
+	/* Free Descriptors (for Receive) */
+	lp->rfd_base = (struct RxFD *)fd_addr;
+	fd_addr += sizeof(struct RxFD) * RX_FD_NUM;
+	for (i = 0; i < RX_FD_NUM; i++) {
+		lp->rfd_base[i].fd.FDCtl = cpu_to_le32(FD_CownsFD);
+	}
+	lp->rfd_cur = lp->rfd_base;
+	lp->rfd_limit = (struct RxFD *)(fd_addr -
+					sizeof(struct FDesc) -
+					sizeof(struct BDesc) * 30);
+
+	/* Transmit Descriptors */
+	lp->tfd_base = (struct TxFD *)fd_addr;
+	fd_addr += sizeof(struct TxFD) * TX_FD_NUM;
+	for (i = 0; i < TX_FD_NUM; i++) {
+		lp->tfd_base[i].fd.FDNext = cpu_to_le32(virt_to_bus(&lp->tfd_base[i+1]));
+		lp->tfd_base[i].fd.FDSystem = cpu_to_le32(0);
+		lp->tfd_base[i].fd.FDCtl = cpu_to_le32(0);
+	}
+	lp->tfd_base[TX_FD_NUM-1].fd.FDNext = cpu_to_le32(virt_to_bus(&lp->tfd_base[0]));
+	lp->tfd_start = 0;
+	lp->tfd_end = 0;
+
+	/* Buffer List (for Receive) */
+	lp->fbl_ptr = (struct FrFD *)fd_addr;
+	lp->fbl_ptr->fd.FDNext = cpu_to_le32(virt_to_bus(lp->fbl_ptr));
+	lp->fbl_ptr->fd.FDCtl = cpu_to_le32(RX_BUF_PAGES | FD_CownsFD);
+	for (i = 0; i < RX_BUF_PAGES; i++) {
+		lp->fbl_ptr->bd[i].BuffData = cpu_to_le32(virt_to_bus(lp->data_buf[i]));
+		/* BDID is index of FrFD.bd[] */
+		lp->fbl_ptr->bd[i].BDCtl =
+			cpu_to_le32(BD_CownsBD | (i << BD_RxBDID_SHIFT) | PAGE_SIZE);
+	}
+	lp->fbl_curid = 0;
+
+	return 0;
+}
+
+static void
+tc35815_clear_queues(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	int i;
+
+	for (i = 0; i < TX_FD_NUM; i++) {
+		struct sk_buff *skb = (struct sk_buff *)
+			le32_to_cpu(lp->tfd_base[i].fd.FDSystem);
+		if (skb)
+			dev_kfree_skb_any(skb);
+		lp->tfd_base[i].fd.FDSystem = cpu_to_le32(0);
+	}
+
+	tc35815_init_queues(dev);
+}
+
+static void
+tc35815_free_queues(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	int i;
+
+	if (lp->tfd_base) {
+		for (i = 0; i < TX_FD_NUM; i++) {
+			struct sk_buff *skb = (struct sk_buff *)
+				le32_to_cpu(lp->tfd_base[i].fd.FDSystem);
+			if (skb)
+				dev_kfree_skb_any(skb);
+			lp->tfd_base[i].fd.FDSystem = cpu_to_le32(0);
+		}
+	}
+
+	lp->rfd_base = NULL;
+	lp->rfd_base = NULL;
+	lp->rfd_limit = NULL;
+	lp->rfd_cur = NULL;
+	lp->fbl_ptr = NULL;
+
+	for (i = 0; i < RX_BUF_PAGES; i++) {
+		if (lp->data_buf[i])
+			free_page((unsigned long)lp->data_buf[i]);
+		lp->data_buf[i] = 0;
+	}
+	if (lp->fd_buf)
+		__free_pages(lp->fd_buf, FD_PAGE_ORDER);
+	lp->fd_buf = NULL;
+}
+
+static void
+dump_txfd(struct TxFD *fd)
+{
+	printk("TxFD(%p): %08x %08x %08x %08x\n", fd,
+	       le32_to_cpu(fd->fd.FDNext),
+	       le32_to_cpu(fd->fd.FDSystem),
+	       le32_to_cpu(fd->fd.FDStat),
+	       le32_to_cpu(fd->fd.FDCtl));
+	printk("BD: ");
+	printk(" %08x %08x",
+	       le32_to_cpu(fd->bd.BuffData),
+	       le32_to_cpu(fd->bd.BDCtl));
+	printk("\n");
+}
+
+static int
+dump_rxfd(struct RxFD *fd)
+{
+	int i, bd_count = (le32_to_cpu(fd->fd.FDCtl) & FD_BDCnt_MASK) >> FD_BDCnt_SHIFT;
+	if (bd_count > 8)
+		bd_count = 8;
+	printk("RxFD(%p): %08x %08x %08x %08x\n", fd,
+	       le32_to_cpu(fd->fd.FDNext),
+	       le32_to_cpu(fd->fd.FDSystem),
+	       le32_to_cpu(fd->fd.FDStat),
+	       le32_to_cpu(fd->fd.FDCtl));
+	if (le32_to_cpu(fd->fd.FDCtl) & FD_CownsFD)
+	    return 0;
+	printk("BD: ");
+	for (i = 0; i < bd_count; i++)
+		printk(" %08x %08x",
+		       le32_to_cpu(fd->bd[i].BuffData),
+		       le32_to_cpu(fd->bd[i].BDCtl));
+	printk("\n");
+	return bd_count;
+}
+
+static void
+dump_frfd(struct FrFD *fd)
+{
+	int i;
+	printk("FrFD(%p): %08x %08x %08x %08x\n", fd,
+	       le32_to_cpu(fd->fd.FDNext),
+	       le32_to_cpu(fd->fd.FDSystem),
+	       le32_to_cpu(fd->fd.FDStat),
+	       le32_to_cpu(fd->fd.FDCtl));
+	printk("BD: ");
+	for (i = 0; i < RX_BUF_PAGES; i++)
+		printk(" %08x %08x",
+		       le32_to_cpu(fd->bd[i].BuffData),
+		       le32_to_cpu(fd->bd[i].BDCtl));
+	printk("\n");
+}
+
+static void
+panic_queues(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	int i;
+
+	printk("TxFD base %p, start %d, end %d\n",
+	       lp->tfd_base, lp->tfd_start, lp->tfd_end);
+	printk("RxFD base %p limit %p cur %p\n",
+	       lp->rfd_base, lp->rfd_limit, lp->rfd_cur);
+	printk("FrFD %p\n", lp->fbl_ptr);
+	for (i = 0; i < TX_FD_NUM; i++)
+		dump_txfd(&lp->tfd_base[i]);
+	for (i = 0; i < RX_FD_NUM; i++) {
+		int bd_count = dump_rxfd(&lp->rfd_base[i]);
+		i += (bd_count + 1) / 2;	/* skip BDs */
+	}
+	dump_frfd(lp->fbl_ptr);
+	panic("%s: Illegal queue state.", dev->name);
+}
+
+static void print_buf(char *add, int length)
+{
+	int i;
+	int len = length;
+
+	printk("print_buf(%08x)(%x)\n", (unsigned int) add,length);
+
+	if (len > 100)
+		len = 100;
+	for (i = 0; i < len; i++) {
+		printk(" %2.2X", (unsigned char) add[i]);
+		if (!(i % 16))
+			printk("\n");
+	}
+	printk("\n");
+}
+
+static void print_eth(char *add)
+{
+	int i;
+
+	printk("print_eth(%08x)\n", (unsigned int) add);
+	for (i = 0; i < 6; i++)
+		printk(" %2.2X", (unsigned char) add[i + 6]);
+	printk(" =>");
+	for (i = 0; i < 6; i++)
+		printk(" %2.2X", (unsigned char) add[i]);
+	printk(" : %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
+}
+
+/*
+ * Open/initialize the board. This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
+static int
+tc35815_open(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	/*
+	 * This is used if the interrupt line can turned off (shared).
+	 * See 3c503.c for an example of selecting the IRQ at config-time.
+	 */
+
+	if (dev->irq == 0  ||
+	    request_irq(dev->irq, &tc35815_interrupt, SA_SHIRQ, cardname, dev)) {
+		return -EAGAIN;
+	}
+
+	tc35815_chip_reset(dev);
+
+	if (tc35815_init_queues(dev) != 0) {
+		free_irq(dev->irq, dev);
+		return -EAGAIN;
+	}
+
+	/* Reset the hardware here. Don't forget to set the station address. */
+	tc35815_chip_init(dev);
+
+	lp->tbusy = 0;
+	netif_start_queue(dev);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static void tc35815_tx_timeout(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs *)dev->base_addr;
+	int flags;
+
+	save_and_cli(flags);
+	printk(KERN_WARNING "%s: transmit timed out, status %#x\n",
+	       dev->name, tc_readl(&tr->Tx_Stat));
+	/* Try to restart the adaptor. */
+	tc35815_chip_reset(dev);
+	tc35815_clear_queues(dev);
+	tc35815_chip_init(dev);
+	lp->tbusy=0;
+	restore_flags(flags);
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+}
+
+static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs *)dev->base_addr;
+
+	if (netif_queue_stopped(dev)) {
+		/*
+		 * 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;
+		printk(KERN_WARNING "%s: transmit timed out, status %#x\n",
+		       dev->name, tc_readl(&tr->Tx_Stat));
+		/* Try to restart the adaptor. */
+		tc35815_chip_reset(dev);
+		tc35815_clear_queues(dev);
+		tc35815_chip_init(dev);
+		lp->tbusy=0;
+		dev->trans_start = jiffies;
+		netif_wake_queue(dev);
+	}
+
+	/*
+	 * Block a timer-based transmit from overlapping. This could better be
+	 * done with atomic_swap(1, lp->tbusy), but set_bit() works as well.
+	 */
+	if (test_and_set_bit(0, (void*)&lp->tbusy) != 0) {
+		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+		dev_kfree_skb_any(skb);
+	} else {
+		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		unsigned char *buf = skb->data;
+		struct TxFD *txfd = &lp->tfd_base[lp->tfd_start];
+		int flags;
+		lp->stats.tx_bytes += skb->len;
+
+
+#ifdef __mips__
+		dma_cache_wback_inv((unsigned long)buf, length);
+#endif
+
+		save_and_cli(flags);
+
+		/* failsafe... */
+		if (lp->tfd_start != lp->tfd_end)
+			tc35815_txdone(dev);
+
+
+		txfd->bd.BuffData = cpu_to_le32(virt_to_bus(buf));
+
+		txfd->bd.BDCtl = cpu_to_le32(length);
+		txfd->fd.FDSystem = cpu_to_le32((__u32)skb);
+		txfd->fd.FDCtl = cpu_to_le32(FD_CownsFD | (1 << FD_BDCnt_SHIFT));
+
+		if (lp->tfd_start == lp->tfd_end) {
+			/* Start DMA Transmitter. */
+			txfd->fd.FDNext |= cpu_to_le32(FD_Next_EOL);
+#ifdef GATHER_TXINT
+			txfd->fd.FDCtl |= cpu_to_le32(FD_FrmOpt_IntTx);
+#endif
+			if (tc35815_debug > 2) {
+				printk("%s: starting TxFD.\n", dev->name);
+				dump_txfd(txfd);
+				if (tc35815_debug > 3)
+					print_eth(buf);
+			}
+			tc_writel(virt_to_bus(txfd), &tr->TxFrmPtr);
+		} else {
+			txfd->fd.FDNext &= cpu_to_le32(~FD_Next_EOL);
+			if (tc35815_debug > 2) {
+				printk("%s: queueing TxFD.\n", dev->name);
+				dump_txfd(txfd);
+				if (tc35815_debug > 3)
+					print_eth(buf);
+			}
+		}
+		lp->tfd_start = (lp->tfd_start + 1) % TX_FD_NUM;
+
+		dev->trans_start = jiffies;
+
+		if ((lp->tfd_start + 1) % TX_FD_NUM != lp->tfd_end) {
+			/* we can send another packet */
+			lp->tbusy = 0;
+			netif_start_queue(dev);
+		} else {
+			netif_stop_queue(dev);
+			if (tc35815_debug > 1)
+				printk(KERN_WARNING "%s: TxFD Exhausted.\n", dev->name);
+		}
+		restore_flags(flags);
+	}
+
+	return 0;
+}
+
+#define FATAL_ERROR_INT \
+	(Int_IntPCI | Int_DmParErr | Int_IntNRAbt)
+static void tc35815_fatal_error_interrupt(struct net_device *dev, int status)
+{
+	static int count;
+	printk(KERN_WARNING "%s: Fatal Error Intterrupt (%#x):",
+	       dev->name, status);
+
+	if (status & Int_IntPCI)
+		printk(" IntPCI");
+	if (status & Int_DmParErr)
+		printk(" DmParErr");
+	if (status & Int_IntNRAbt)
+		printk(" IntNRAbt");
+	printk("\n");
+	if (count++ > 100)
+		panic("%s: Too many fatal errors.", dev->name);
+	printk(KERN_WARNING "%s: Resetting %s...\n", dev->name, cardname);
+	/* Try to restart the adaptor. */
+	tc35815_chip_reset(dev);
+	tc35815_clear_queues(dev);
+	tc35815_chip_init(dev);
+}
+
+/*
+ * The typical workload of the driver:
+ *   Handle the network interface interrupts.
+ */
+static void tc35815_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct net_device *dev = dev_id;
+	struct tc35815_regs *tr;
+	struct tc35815_local *lp;
+	int status, boguscount = 0;
+
+	if (dev == NULL) {
+		printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
+		return;
+	}
+
+	tr = (struct tc35815_regs*)dev->base_addr;
+	lp = (struct tc35815_local *)dev->priv;
+
+	do {
+		status = tc_readl(&tr->Int_Src);
+		if (status == 0)
+			break;
+		tc_writel(status, &tr->Int_Src);	/* write to clear */
+
+		/* Fatal errors... */
+		if (status & FATAL_ERROR_INT) {
+			tc35815_fatal_error_interrupt(dev, status);
+			break;
+		}
+		/* recoverable errors */
+		if (status & Int_IntFDAEx) {
+			/* disable FDAEx int. (until we make rooms...) */
+			tc_writel(tc_readl(&tr->Int_En) & ~Int_FDAExEn, &tr->Int_En);
+			printk(KERN_WARNING
+			       "%s: Free Descriptor Area Exhausted (%#x).\n",
+			       dev->name, status);
+			lp->stats.rx_dropped++;
+		}
+		if (status & Int_IntBLEx) {
+			/* disable BLEx int. (until we make rooms...) */
+			tc_writel(tc_readl(&tr->Int_En) & ~Int_BLExEn, &tr->Int_En);
+			printk(KERN_WARNING
+			       "%s: Buffer List Exhausted (%#x).\n",
+			       dev->name, status);
+			lp->stats.rx_dropped++;
+		}
+		if (status & Int_IntExBD) {
+			printk(KERN_WARNING
+			       "%s: Excessive Buffer Descriptiors (%#x).\n",
+			       dev->name, status);
+			lp->stats.rx_length_errors++;
+		}
+		/* normal notification */
+		if (status & Int_IntMacRx) {
+			/* Got a packet(s). */
+			lp->lstats.rx_ints++;
+			tc35815_rx(dev);
+		}
+		if (status & Int_IntMacTx) {
+			lp->lstats.tx_ints++;
+			tc35815_txdone(dev);
+		}
+	} while (++boguscount < 20) ;
+
+	return;
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+tc35815_rx(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+	unsigned int fdctl;
+	int i;
+	int buf_free_count = 0;
+	int fd_free_count = 0;
+
+	while (!((fdctl = le32_to_cpu(lp->rfd_cur->fd.FDCtl)) & FD_CownsFD)) {
+		int status = le32_to_cpu(lp->rfd_cur->fd.FDStat);
+		int pkt_len = fdctl & FD_FDLength_MASK;
+		struct RxFD *next_rfd;
+		int bd_count = (fdctl & FD_BDCnt_MASK) >> FD_BDCnt_SHIFT;
+
+		if (tc35815_debug > 2)
+			dump_rxfd(lp->rfd_cur);
+		if (status & Rx_Good) {
+			/* Malloc up new buffer. */
+			struct sk_buff *skb;
+			unsigned char *data;
+			int cur_bd, offset;
+
+			lp->stats.rx_bytes += pkt_len;
+			
+			skb = dev_alloc_skb(pkt_len + 2); /* +2: for reserve */
+			if (skb == NULL) {
+				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+				       dev->name);
+				lp->stats.rx_dropped++;
+				break;
+			}
+			skb_reserve(skb, 2);   /* 16 bit alignment */
+			skb->dev = dev;
+
+			data = skb_put(skb, pkt_len);
+
+			/* copy from receive buffer */
+			cur_bd = 0;
+			offset = 0;
+			while (offset < pkt_len && cur_bd < bd_count) {
+				int len = le32_to_cpu(lp->rfd_cur->bd[cur_bd].BDCtl) &
+					BD_BuffLength_MASK;
+				void *rxbuf =
+					bus_to_virt(le32_to_cpu(lp->rfd_cur->bd[cur_bd].BuffData));
+#ifdef __mips__
+				dma_cache_inv((unsigned long)rxbuf, len);
+#endif
+				memcpy(data + offset, rxbuf, len);
+				offset += len;
+				cur_bd++;
+			}
+	//		print_buf(data,pkt_len);
+			if (tc35815_debug > 3)
+				print_eth(data);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			lp->stats.rx_packets++;
+		} else {
+			lp->stats.rx_errors++;
+			/* WORKAROUND: LongErr and CRCErr means Overflow. */
+			if ((status & Rx_LongErr) && (status & Rx_CRCErr)) {
+				status &= ~(Rx_LongErr|Rx_CRCErr);
+				status |= Rx_Over;
+			}
+			if (status & Rx_LongErr) lp->stats.rx_length_errors++;
+			if (status & Rx_Over) lp->stats.rx_fifo_errors++;
+			if (status & Rx_CRCErr) lp->stats.rx_crc_errors++;
+			if (status & Rx_Align) lp->stats.rx_frame_errors++;
+		}
+
+		if (bd_count > 0) {
+			/* put Free Buffer back to controller */
+			int bdctl = le32_to_cpu(lp->rfd_cur->bd[bd_count - 1].BDCtl);
+			unsigned char id =
+				(bdctl & BD_RxBDID_MASK) >> BD_RxBDID_SHIFT;
+			if (id >= RX_BUF_PAGES) {
+				printk("%s: invalid BDID.\n", dev->name);
+				panic_queues(dev);
+			}
+			/* free old buffers */
+			while (lp->fbl_curid != id) {
+				bdctl = le32_to_cpu(lp->fbl_ptr->bd[lp->fbl_curid].BDCtl);
+				if (bdctl & BD_CownsBD) {
+					printk("%s: Freeing invalid BD.\n",
+					       dev->name);
+					panic_queues(dev);
+				}
+				/* pass BD to controler */
+				/* Note: BDLength was modified by chip. */
+				lp->fbl_ptr->bd[lp->fbl_curid].BDCtl =
+					cpu_to_le32(BD_CownsBD |
+						    (lp->fbl_curid << BD_RxBDID_SHIFT) |
+						    PAGE_SIZE);
+				lp->fbl_curid =
+					(lp->fbl_curid + 1) % RX_BUF_PAGES;
+				if (tc35815_debug > 2) {
+					printk("%s: Entering new FBD %d\n",
+					       dev->name, lp->fbl_curid);
+					dump_frfd(lp->fbl_ptr);
+				}
+				buf_free_count++;
+			}
+		}
+
+		/* put RxFD back to controller */
+		next_rfd = bus_to_virt(le32_to_cpu(lp->rfd_cur->fd.FDNext));
+#ifdef __mips__
+		next_rfd = (struct RxFD *)vtonocache(next_rfd);
+#endif
+		if (next_rfd < lp->rfd_base || next_rfd > lp->rfd_limit) {
+			printk("%s: RxFD FDNext invalid.\n", dev->name);
+			panic_queues(dev);
+		}
+		for (i = 0; i < (bd_count + 1) / 2 + 1; i++) {
+			/* pass FD to controler */
+			lp->rfd_cur->fd.FDNext = cpu_to_le32(0xdeaddead);	/* for debug */
+			lp->rfd_cur->fd.FDCtl = cpu_to_le32(FD_CownsFD);
+			lp->rfd_cur++;
+			fd_free_count++;
+		}
+
+		lp->rfd_cur = next_rfd;
+	}
+
+	/* re-enable BL/FDA Exhaust interupts. */
+	if (fd_free_count) {
+		tc_writel(tc_readl(&tr->Int_En) | Int_FDAExEn, &tr->Int_En);
+		if (buf_free_count)
+			tc_writel(tc_readl(&tr->Int_En) | Int_BLExEn, &tr->Int_En);
+	}
+}
+
+#ifdef NO_CHECK_CARRIER
+#define TX_STA_ERR	(Tx_ExColl|Tx_Under|Tx_Defer|Tx_LateColl|Tx_TxPar|Tx_SQErr)
+#else
+#define TX_STA_ERR	(Tx_ExColl|Tx_Under|Tx_Defer|Tx_NCarr|Tx_LateColl|Tx_TxPar|Tx_SQErr)
+#endif
+
+static void
+tc35815_check_tx_stat(struct net_device *dev, int status)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	const char *msg = NULL;
+
+	/* count collisions */
+	if (status & Tx_ExColl)
+		lp->stats.collisions += 16;
+	if (status & Tx_TxColl_MASK)
+		lp->stats.collisions += status & Tx_TxColl_MASK;
+
+	/* WORKAROUND: ignore LostCrS in full duplex operation */
+	if (lp->fullduplex)
+		status &= ~Tx_NCarr;
+
+	if (!(status & TX_STA_ERR)) {
+		/* no error. */
+		lp->stats.tx_packets++;
+		return;
+	}
+
+	lp->stats.tx_errors++;
+	if (status & Tx_ExColl) {
+		lp->stats.tx_aborted_errors++;
+		msg = "Excessive Collision.";
+	}
+	if (status & Tx_Under) {
+		lp->stats.tx_fifo_errors++;
+		msg = "Tx FIFO Underrun.";
+	}
+	if (status & Tx_Defer) {
+		lp->stats.tx_fifo_errors++;
+		msg = "Excessive Deferral.";
+	}
+#ifndef NO_CHECK_CARRIER
+	if (status & Tx_NCarr) {
+		lp->stats.tx_carrier_errors++;
+		msg = "Lost Carrier Sense.";
+	}
+#endif
+	if (status & Tx_LateColl) {
+		lp->stats.tx_aborted_errors++;
+		msg = "Late Collision.";
+	}
+	if (status & Tx_TxPar) {
+		lp->stats.tx_fifo_errors++;
+		msg = "Transmit Parity Error.";
+	}
+	if (status & Tx_SQErr) {
+		lp->stats.tx_heartbeat_errors++;
+		msg = "Signal Quality Error.";
+	}
+	if (msg)
+		printk(KERN_WARNING "%s: %s (%#x)\n", dev->name, msg, status);
+}
+
+static void
+tc35815_txdone(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+	struct TxFD *txfd;
+	unsigned int fdctl;
+	int num_done = 0;
+
+	txfd = &lp->tfd_base[lp->tfd_end];
+	while (lp->tfd_start != lp->tfd_end &&
+	       !((fdctl = le32_to_cpu(txfd->fd.FDCtl)) & FD_CownsFD)) {
+		int status = le32_to_cpu(txfd->fd.FDStat);
+		struct sk_buff *skb;
+		unsigned long fdnext = le32_to_cpu(txfd->fd.FDNext);
+
+		if (tc35815_debug > 2) {
+			printk("%s: complete TxFD.\n", dev->name);
+			dump_txfd(txfd);
+		}
+		tc35815_check_tx_stat(dev, status);
+
+		skb = (struct sk_buff *)le32_to_cpu(txfd->fd.FDSystem);
+		if (skb) {
+			dev_kfree_skb_any(skb);
+		}
+		txfd->fd.FDSystem = cpu_to_le32(0);
+
+		num_done++;
+		lp->tfd_end = (lp->tfd_end + 1) % TX_FD_NUM;
+		txfd = &lp->tfd_base[lp->tfd_end];
+		if ((fdnext & ~FD_Next_EOL) != virt_to_bus(txfd)) {
+			printk("%s: TxFD FDNext invalid.\n", dev->name);
+			panic_queues(dev);
+		}
+		if (fdnext & FD_Next_EOL) {
+			/* DMA Transmitter has been stopping... */
+			if (lp->tfd_end != lp->tfd_start) {
+				int head = (lp->tfd_start + TX_FD_NUM - 1) % TX_FD_NUM;
+				struct TxFD* txhead = &lp->tfd_base[head];
+				int qlen = (lp->tfd_start + TX_FD_NUM
+					    - lp->tfd_end) % TX_FD_NUM;
+
+				if (!(le32_to_cpu(txfd->fd.FDCtl) & FD_CownsFD)) {
+					printk("%s: TxFD FDCtl invalid.\n", dev->name);
+					panic_queues(dev);
+				}
+				/* log max queue length */
+				if (lp->lstats.max_tx_qlen < qlen)
+					lp->lstats.max_tx_qlen = qlen;
+
+
+				/* start DMA Transmitter again */
+				txhead->fd.FDNext |= cpu_to_le32(FD_Next_EOL);
+#ifdef GATHER_TXINT
+				txhead->fd.FDCtl |= cpu_to_le32(FD_FrmOpt_IntTx);
+#endif
+				if (tc35815_debug > 2) {
+					printk("%s: start TxFD on queue.\n",
+					       dev->name);
+					dump_txfd(txfd);
+				}
+				tc_writel(virt_to_bus(txfd), &tr->TxFrmPtr);
+			}
+			break;
+		}
+	}
+
+	if (num_done > 0 && lp->tbusy) {
+		lp->tbusy = 0;
+		netif_start_queue(dev);
+	}
+}
+
+/* The inverse routine to tc35815_open(). */
+static int
+tc35815_close(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+
+	lp->tbusy = 1;
+	netif_stop_queue(dev);
+
+	/* Flush the Tx and disable Rx here. */
+
+	tc35815_chip_reset(dev);
+	free_irq(dev->irq, dev);
+
+	tc35815_free_queues(dev);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *tc35815_get_stats(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+	unsigned long flags;
+
+	if (netif_running(dev)) {
+		save_and_cli(flags);
+		/* Update the statistics from the device registers. */
+		lp->stats.rx_missed_errors = tc_readl(&tr->Miss_Cnt);
+		restore_flags(flags);
+	}
+
+	return &lp->stats;
+}
+
+static void tc35815_set_cam_entry(struct tc35815_regs *tr, int index, unsigned char *addr)
+{
+	int cam_index = index * 6;
+	unsigned long cam_data;
+	unsigned long saved_addr;
+	saved_addr = tc_readl(&tr->CAM_Adr);
+
+	if (tc35815_debug > 1) {
+		int i;
+		printk(KERN_DEBUG "%s: CAM %d:", cardname, index);
+		for (i = 0; i < 6; i++)
+			printk(" %02x", addr[i]);
+		printk("\n");
+	}
+	if (index & 1) {
+		/* read modify write */
+		tc_writel(cam_index - 2, &tr->CAM_Adr);
+		cam_data = tc_readl(&tr->CAM_Data) & 0xffff0000;
+		cam_data |= addr[0] << 8 | addr[1];
+		tc_writel(cam_data, &tr->CAM_Data);
+		/* write whole word */
+		tc_writel(cam_index + 2, &tr->CAM_Adr);
+		cam_data = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
+		tc_writel(cam_data, &tr->CAM_Data);
+	} else {
+		/* write whole word */
+		tc_writel(cam_index, &tr->CAM_Adr);
+		cam_data = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
+		tc_writel(cam_data, &tr->CAM_Data);
+		/* read modify write */
+		tc_writel(cam_index + 4, &tr->CAM_Adr);
+		cam_data = tc_readl(&tr->CAM_Data) & 0x0000ffff;
+		cam_data |= addr[4] << 24 | (addr[5] << 16);
+		tc_writel(cam_data, &tr->CAM_Data);
+	}
+
+	if (tc35815_debug > 2) {
+		int i;
+		for (i = cam_index / 4; i < cam_index / 4 + 2; i++) {
+			tc_writel(i * 4, &tr->CAM_Adr);
+			printk("CAM 0x%x: %08x",
+			       i * 4, tc_readl(&tr->CAM_Data));
+		}
+	}
+	tc_writel(saved_addr, &tr->CAM_Adr);
+}
+
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ * num_addrs == -1	Promiscuous mode, receive all packets
+ * num_addrs == 0	Normal mode, clear multicast list
+ * num_addrs > 0	Multicast mode, receive normal and MC packets,
+ *			and do best-effort filtering.
+ */
+static void
+tc35815_set_multicast_list(struct net_device *dev)
+{
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+
+	if (dev->flags&IFF_PROMISC)
+	{
+		/* Enable promiscuous mode */
+		tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc | CAM_StationAcc, &tr->CAM_Ctl);
+	}
+	else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > CAM_ENTRY_MAX - 3)
+	{
+		/* CAM 0, 1, 20 are reserved. */
+		/* Disable promiscuous mode, use normal mode. */
+		tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc, &tr->CAM_Ctl);
+	}
+	else if(dev->mc_count)
+	{
+		struct dev_mc_list* cur_addr = dev->mc_list;
+		int i;
+		int ena_bits = CAM_Ena_Bit(CAM_ENTRY_SOURCE);
+
+		tc_writel(0, &tr->CAM_Ctl);
+		/* Walk the address list, and load the filter */
+		for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
+			if (!cur_addr)
+				break;
+			/* entry 0,1 is reserved. */
+			tc35815_set_cam_entry(tr, i + 2, cur_addr->dmi_addr);
+			ena_bits |= CAM_Ena_Bit(i + 2);
+		}
+		tc_writel(ena_bits, &tr->CAM_Ena);
+		tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+	}
+	else {
+		tc_writel(CAM_Ena_Bit(CAM_ENTRY_SOURCE), &tr->CAM_Ena);
+		tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+	}
+}
+
+static unsigned long tc_phy_read(struct tc35815_regs *tr, int phy, int phy_reg)
+{
+	unsigned long data;
+	int flags;
+	save_and_cli(flags);
+	tc_writel(MD_CA_Busy | (phy << 5) | phy_reg, &tr->MD_CA);
+	while (tc_readl(&tr->MD_CA) & MD_CA_Busy)
+		;
+	data = tc_readl(&tr->MD_Data);
+	restore_flags(flags);
+	return data;
+}
+
+static void tc_phy_write(unsigned long d, struct tc35815_regs *tr, int phy, int phy_reg)
+{
+	int flags;
+	save_and_cli(flags);
+	tc_writel(d, &tr->MD_Data);
+	tc_writel(MD_CA_Busy | MD_CA_Wr | (phy << 5) | phy_reg, &tr->MD_CA);
+	while (tc_readl(&tr->MD_CA) & MD_CA_Busy)
+		;
+	restore_flags(flags);
+}
+
+static void tc35815_phy_chip_init(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+	static int first = 1;
+	unsigned short ctl;
+
+	if (first) {
+		unsigned short id0, id1;
+		int count;
+		first = 0;
+
+		/* first data written to the PHY will be an ID number */
+		tc_phy_write(0, tr, 0, MII_CONTROL);	/* ID:0 */
+#if 0
+		tc_phy_write(MIICNTL_RESET, tr, 0, MII_CONTROL);
+		printk(KERN_INFO "%s: Resetting PHY...", dev->name);
+		while (tc_phy_read(tr, 0, MII_CONTROL) & MIICNTL_RESET)
+			;
+		printk("\n");
+		tc_phy_write(MIICNTL_AUTO|MIICNTL_SPEED|MIICNTL_FDX, tr, 0,
+			     MII_CONTROL);
+#endif
+		id0 = tc_phy_read(tr, 0, MII_PHY_ID0);
+		id1 = tc_phy_read(tr, 0, MII_PHY_ID1);
+		printk(KERN_DEBUG "%s: PHY ID %04x %04x\n", dev->name,
+		       id0, id1);
+		if (lp->option & TC35815_OPT_10M) {
+			lp->linkspeed = 10;
+			lp->fullduplex = (lp->option & TC35815_OPT_FULLDUP) != 0;
+		} else if (lp->option & TC35815_OPT_100M) {
+			lp->linkspeed = 100;
+			lp->fullduplex = (lp->option & TC35815_OPT_FULLDUP) != 0;
+		} else {
+			/* auto negotiation */
+			unsigned long neg_result;
+			tc_phy_write(MIICNTL_AUTO | MIICNTL_RST_AUTO, tr, 0, MII_CONTROL);
+			printk(KERN_INFO "%s: Auto Negotiation...", dev->name);
+			count = 0;
+			while (!(tc_phy_read(tr, 0, MII_STATUS) & MIISTAT_AUTO_DONE)) {
+				if (count++ > 5000) {
+					printk(" failed. Assume 10Mbps\n");
+					lp->linkspeed = 10;
+					lp->fullduplex = 0;
+					goto done;
+				}
+				if (count % 512 == 0)
+					printk(".");
+				mdelay(1);
+			}
+			printk(" done.\n");
+			neg_result = tc_phy_read(tr, 0, MII_ANLPAR);
+			if (neg_result & (MII_AN_TX_FDX | MII_AN_TX_HDX))
+				lp->linkspeed = 100;
+			else
+				lp->linkspeed = 10;
+			if (neg_result & (MII_AN_TX_FDX | MII_AN_10_FDX))
+				lp->fullduplex = 1;
+			else
+				lp->fullduplex = 0;
+		done:
+			;
+		}
+	}
+
+	ctl = 0;
+	if (lp->linkspeed == 100)
+		ctl |= MIICNTL_SPEED;
+	if (lp->fullduplex)
+		ctl |= MIICNTL_FDX;
+	tc_phy_write(ctl, tr, 0, MII_CONTROL);
+
+	if (lp->fullduplex) {
+		tc_writel(tc_readl(&tr->MAC_Ctl) | MAC_FullDup, &tr->MAC_Ctl);
+	}
+}
+
+static void tc35815_chip_reset(struct net_device *dev)
+{
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+
+	/* reset the controller */
+	tc_writel(MAC_Reset, &tr->MAC_Ctl);
+	while (tc_readl(&tr->MAC_Ctl) & MAC_Reset)
+		;
+
+	tc_writel(0, &tr->MAC_Ctl);
+
+	/* initialize registers to default value */
+	tc_writel(0, &tr->DMA_Ctl);
+	tc_writel(0, &tr->TxThrsh);
+	tc_writel(0, &tr->TxPollCtr);
+	tc_writel(0, &tr->RxFragSize);
+	tc_writel(0, &tr->Int_En);
+	tc_writel(0, &tr->FDA_Bas);
+	tc_writel(0, &tr->FDA_Lim);
+	tc_writel(0xffffffff, &tr->Int_Src);	/* Write 1 to clear */
+	tc_writel(0, &tr->CAM_Ctl);
+	tc_writel(0, &tr->Tx_Ctl);
+	tc_writel(0, &tr->Rx_Ctl);
+	tc_writel(0, &tr->CAM_Ena);
+	(void)tc_readl(&tr->Miss_Cnt);	/* Read to clear */
+
+}
+
+static void tc35815_chip_init(struct net_device *dev)
+{
+	struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+	struct tc35815_regs *tr = (struct tc35815_regs*)dev->base_addr;
+	int flags;
+	unsigned long txctl = TX_CTL_CMD;
+
+	tc35815_phy_chip_init(dev);
+
+	/* load station address to CAM */
+	tc35815_set_cam_entry(tr, CAM_ENTRY_SOURCE, dev->dev_addr);
+
+	/* Enable CAM (broadcast and unicast) */
+	tc_writel(CAM_Ena_Bit(CAM_ENTRY_SOURCE), &tr->CAM_Ena);
+	tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl);
+
+	save_and_cli(flags);
+
+	tc_writel(DMA_BURST_SIZE, &tr->DMA_Ctl);
+
+	tc_writel(RxFrag_EnPack | ETH_ZLEN, &tr->RxFragSize);	/* Packing */
+	tc_writel(0, &tr->TxPollCtr);	/* Batch mode */
+	tc_writel(TX_THRESHOLD, &tr->TxThrsh);
+	tc_writel(INT_EN_CMD, &tr->Int_En);
+
+	/* set queues */
+	tc_writel(virt_to_bus(lp->rfd_base), &tr->FDA_Bas);
+	tc_writel((unsigned long)lp->rfd_limit - (unsigned long)lp->rfd_base,
+		  &tr->FDA_Lim);
+	/*
+	 * Activation method:
+	 * First, enable eht MAC Transmitter and the DMA Receive circuits.
+	 * Then enable the DMA Transmitter and the MAC Receive circuits.
+	 */
+	tc_writel(virt_to_bus(lp->fbl_ptr), &tr->BLFrmPtr);	/* start DMA receiver */
+	tc_writel(RX_CTL_CMD, &tr->Rx_Ctl);	/* start MAC receiver */
+	/* start MAC transmitter */
+	/* WORKAROUND: ignore LostCrS in full duplex operation */
+	if (lp->fullduplex)
+		txctl = TX_CTL_CMD & ~Tx_EnLCarr;
+#ifdef GATHER_TXINT
+	txctl &= ~Tx_EnComp;	/* disable global tx completion int. */
+#endif
+	tc_writel(txctl, &tr->Tx_Ctl);
+#if 0	/* No need to polling */
+	tc_writel(virt_to_bus(lp->tfd_base), &tr->TxFrmPtr);	/* start DMA transmitter */
+#endif
+	restore_flags(flags);
+}
+
+static int tc35815_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+	int len = 0;
+	off_t pos = 0;
+	off_t begin = 0;
+	struct net_device *dev;
+
+	len += sprintf(buffer, "TC35815 statistics:\n");
+	for (dev = root_tc35815_dev; dev; dev = ((struct tc35815_local *)dev->priv)->next_module) {
+		struct tc35815_local *lp = (struct tc35815_local *)dev->priv;
+		len += sprintf(buffer + len,
+			       "%s: tx_ints %d, rx_ints %d, max_tx_qlen %d\n",
+			       dev->name,
+			       lp->lstats.tx_ints,
+			       lp->lstats.rx_ints,
+			       lp->lstats.max_tx_qlen);
+		pos = begin + len;
+
+		if (pos < offset) {
+			len = 0;
+			begin = pos;
+		}
+    
+		if (pos > offset+length) break;
+	}
+
+	*start = buffer + (offset - begin);
+	len -= (offset - begin);
+  
+	if (len > length) len = length;
+  
+	return len;
+}
+
+/* XXX */
+void
+tc35815_killall(void)
+{
+	struct net_device *dev;
+
+	for (dev = root_tc35815_dev; dev; dev = ((struct tc35815_local *)dev->priv)->next_module) {
+		if (dev->flags&IFF_UP){
+			dev->stop(dev);
+		}
+	}
+}
+
+static struct pci_driver tc35815_driver = {
+	name:  TC35815_MODULE_NAME,
+	probe: tc35815_probe,
+	remove: NULL,
+	id_table: tc35815_pci_tbl,
+};
+
+static int __init tc35815_init_module(void)
+{
+	int err;
+
+	if ((err = pci_module_init(&tc35815_driver)) < 0 )
+		       return err;      
+	else
+		return 0;
+}
+
+static void __exit tc35815_cleanup_module(void)
+{
+	struct net_device *next_dev;
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_tc35815_dev) {
+		struct net_device *dev = root_tc35815_dev;
+		next_dev = ((struct tc35815_local *)dev->priv)->next_module;
+		kfree(dev->priv);
+		iounmap((void *)(dev->base_addr));
+		unregister_netdev(dev);
+		kfree(dev);
+		root_tc35815_dev = next_dev;
+	}
+}
+module_init(tc35815_init_module);
+module_exit(tc35815_cleanup_module);
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/tg3.c	Sun Apr 14 12:16:54 2002
@@ -1509,7 +1509,8 @@
 		if (unlikely(skb == NULL))
 			BUG();
 
-		pci_unmap_single(tp->pdev, ri->mapping,
+		pci_unmap_single(tp->pdev,
+				 pci_unmap_addr(ri, mapping),
 				 (skb->len - skb->data_len),
 				 PCI_DMA_TODEVICE);
 
@@ -1526,7 +1527,7 @@
 				BUG();
 
 			pci_unmap_page(tp->pdev,
-				       ri->mapping,
+				       pci_unmap_addr(ri, mapping),
 				       skb_shinfo(skb)->frags[i].size,
 				       PCI_DMA_TODEVICE);
 
@@ -1614,7 +1615,7 @@
 				 PCI_DMA_FROMDEVICE);
 
 	map->skb = skb;
-	map->mapping = mapping;
+	pci_unmap_addr_set(map, mapping, mapping);
 
 	if (src_map != NULL)
 		src_map->skb = NULL;
@@ -1666,7 +1667,8 @@
 	};
 
 	dest_map->skb = src_map->skb;
-	dest_map->mapping = src_map->mapping;
+	pci_unmap_addr_set(dest_map, mapping,
+			   pci_unmap_addr(src_map, mapping));
 	dest_desc->addr_hi = src_desc->addr_hi;
 	dest_desc->addr_lo = src_desc->addr_lo;
 
@@ -1723,17 +1725,20 @@
 		desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
 		opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
 		if (opaque_key == RXD_OPAQUE_RING_STD) {
-			dma_addr = tp->rx_std_buffers[desc_idx].mapping;
+			dma_addr = pci_unmap_addr(&tp->rx_std_buffers[desc_idx],
+						  mapping);
 			skb = tp->rx_std_buffers[desc_idx].skb;
 			post_ptr = &tp->rx_std_ptr;
 		} else if (opaque_key == RXD_OPAQUE_RING_JUMBO) {
-			dma_addr = tp->rx_jumbo_buffers[desc_idx].mapping;
+			dma_addr = pci_unmap_addr(&tp->rx_jumbo_buffers[desc_idx],
+						  mapping);
 			skb = tp->rx_jumbo_buffers[desc_idx].skb;
 			post_ptr = &tp->rx_jumbo_ptr;
 		}
 #if TG3_MINI_RING_WORKS
 		else if (opaque_key == RXD_OPAQUE_RING_MINI) {
-			dma_addr = tp->rx_mini_buffers[desc_idx].mapping;
+			dma_addr = pci_unmap_addr(&tp->rx_mini_buffers[desc_idx],
+						  mapping);
 			skb = tp->rx_mini_buffers[desc_idx].skb;
 			post_ptr = &tp->rx_mini_ptr;
 		}
@@ -2072,8 +2077,9 @@
 		       NIC_SRAM_TX_BUFFER_DESC);
 		txd += (entry * TXD_SIZE);
 
-		writel(((u64) mapping >> 32),
-		       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
+		if (sizeof(dma_addr_t) != sizeof(u32))
+			writel(((u64) mapping >> 32),
+			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
 
 		writel(((u64) mapping & 0xffffffff),
 		       txd + TXD_ADDR + TG3_64BIT_REG_LOW);
@@ -2111,10 +2117,12 @@
 					frag->page, frag->page_offset,
 					guilty_len, PCI_DMA_TODEVICE);
 	}
-	pci_unmap_single(tp->pdev, tp->tx_buffers[guilty_entry].mapping,
+	pci_unmap_single(tp->pdev, pci_unmap_addr(&tp->tx_buffers[guilty_entry],
+						  mapping),
 			 guilty_len, PCI_DMA_TODEVICE);
 	tg3_set_txd_addr(tp, guilty_entry, new_addr);
-	tp->tx_buffers[guilty_entry].mapping = new_addr;
+	pci_unmap_addr_set(&tp->tx_buffers[guilty_entry], mapping,
+			   new_addr);
 	*start = last_plus_one;
 #else
 	/* Oh well, no IOMMU, have to allocate a whole new SKB. */
@@ -2148,11 +2156,12 @@
 			len = skb->len - skb->data_len;
 		else
 			len = skb_shinfo(skb)->frags[i-1].size;
-		pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
+		pci_unmap_single(tp->pdev,
+				 pci_unmap_addr(&tp->tx_buffers[entry], mapping),
 				 len, PCI_DMA_TODEVICE);
 		if (i == 0) {
 			tp->tx_buffers[entry].skb = new_skb;
-			tp->tx_buffers[entry].mapping = new_addr;
+			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, new_addr);
 		} else {
 			tp->tx_buffers[entry].skb = NULL;
 		}
@@ -2199,8 +2208,7 @@
 		txd += (entry * TXD_SIZE);
 
 		/* Save some PIOs */
-		if (((u64) tp->tx_buffers[entry].mapping >> 32) !=
-		    ((u64) mapping >> 32))
+		if (sizeof(dma_addr_t) != sizeof(u32))
 			writel(((u64) mapping >> 32),
 			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
 
@@ -2257,9 +2265,12 @@
 	mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
 	tp->tx_buffers[entry].skb = skb;
-	tp->tx_buffers[entry].mapping = mapping;
+	pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
+
+	would_hit_hwbug = 0;
 
-	would_hit_hwbug = tg3_4g_overflow_test(mapping, len);
+	if (tg3_4g_overflow_test(mapping, len))
+		would_hit_hwbug = entry + 1;
 
 	tg3_set_txd(tp, entry, mapping, len, base_flags,
 		    (skb_shinfo(skb)->nr_frags == 0));
@@ -2281,10 +2292,14 @@
 					       len, PCI_DMA_TODEVICE);
 
 			tp->tx_buffers[entry].skb = NULL;
-			tp->tx_buffers[entry].mapping = mapping;
+			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
-			would_hit_hwbug |=
-				tg3_4g_overflow_test(mapping, len);
+			if (tg3_4g_overflow_test(mapping, len)) {
+				/* Only one should match. */
+				if (would_hit_hwbug)
+					BUG();
+				would_hit_hwbug = entry + 1;
+			}
 
 			tg3_set_txd(tp, entry, mapping, len,
 				    base_flags, (i == last));
@@ -2298,19 +2313,18 @@
 		u32 start;
 		unsigned int len = 0;
 
+		would_hit_hwbug -= 1;
 		entry = entry - 1 - skb_shinfo(skb)->nr_frags;
 		entry &= (TG3_TX_RING_SIZE - 1);
 		start = entry;
 		i = 0;
 		while (entry != last_plus_one) {
-			dma_addr_t mapping = tp->tx_buffers[entry].mapping;
-
 			if (i == 0)
 				len = skb->len - skb->data_len;
 			else
 				len = skb_shinfo(skb)->frags[i-1].size;
 
-			if (tg3_4g_overflow_test(mapping, len))
+			if (entry == would_hit_hwbug)
 				break;
 
 			i++;
@@ -2390,7 +2404,7 @@
 	mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
 
 	tp->tx_buffers[entry].skb = skb;
-	tp->tx_buffers[entry].mapping = mapping;
+	pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
 	tg3_set_txd(tp, entry, mapping, len, base_flags,
 		    (skb_shinfo(skb)->nr_frags == 0));
@@ -2413,7 +2427,7 @@
 					       len, PCI_DMA_TODEVICE);
 
 			tp->tx_buffers[entry].skb = NULL;
-			tp->tx_buffers[entry].mapping = mapping;
+			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
 			tg3_set_txd(tp, entry, mapping, len,
 				    base_flags, (i == last));
@@ -2497,7 +2511,8 @@
 
 		if (rxp->skb == NULL)
 			continue;
-		pci_unmap_single(tp->pdev, rxp->mapping,
+		pci_unmap_single(tp->pdev,
+				 pci_unmap_addr(rxp, mapping),
 				 RX_PKT_BUF_SZ - tp->rx_offset,
 				 PCI_DMA_FROMDEVICE);
 		dev_kfree_skb(rxp->skb);
@@ -2509,7 +2524,8 @@
 
 		if (rxp->skb == NULL)
 			continue;
-		pci_unmap_single(tp->pdev, rxp->mapping,
+		pci_unmap_single(tp->pdev,
+				 pci_unmap_addr(rxp, mapping),
 				 RX_MINI_PKT_BUF_SZ - tp->rx_offset,
 				 PCI_DMA_FROMDEVICE);
 		dev_kfree_skb(rxp->skb);
@@ -2521,7 +2537,8 @@
 
 		if (rxp->skb == NULL)
 			continue;
-		pci_unmap_single(tp->pdev, rxp->mapping,
+		pci_unmap_single(tp->pdev,
+				 pci_unmap_addr(rxp, mapping),
 				 RX_JUMBO_PKT_BUF_SZ - tp->rx_offset,
 				 PCI_DMA_FROMDEVICE);
 		dev_kfree_skb(rxp->skb);
@@ -2541,7 +2558,8 @@
 			continue;
 		}
 
-		pci_unmap_single(tp->pdev, txp->mapping,
+		pci_unmap_single(tp->pdev,
+				 pci_unmap_addr(txp, mapping),
 				 (skb->len - skb->data_len),
 				 PCI_DMA_TODEVICE);
 		txp->skb = NULL;
@@ -2550,7 +2568,8 @@
 
 		for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
 			txp = &tp->tx_buffers[i & (TG3_TX_RING_SIZE - 1)];
-			pci_unmap_page(tp->pdev, txp->mapping,
+			pci_unmap_page(tp->pdev,
+				       pci_unmap_addr(txp, mapping),
 				       skb_shinfo(skb)->frags[j].size,
 				       PCI_DMA_TODEVICE);
 			i++;
@@ -4770,6 +4789,7 @@
 		edata.data = netif_carrier_ok(tp->dev) ? 1 : 0;
 		if (copy_to_user(useraddr, &edata, sizeof(edata)))
 			return -EFAULT;
+		return 0;
 	}
 	case ETHTOOL_GCOALESCE: {
 		struct ethtool_coalesce ecoal = { ETHTOOL_GCOALESCE };
@@ -5441,10 +5461,23 @@
 	pci_read_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
 			      &cacheline_sz_reg);
 
-	tp->pci_cacheline_sz = (cacheline_sz_reg >> 24) & 0xff;
-	tp->pci_lat_timer    = (cacheline_sz_reg >> 16) & 0xff;
-	tp->pci_hdr_type     = (cacheline_sz_reg >>  8) & 0xff;
-	tp->pci_bist         = (cacheline_sz_reg >>  0) & 0xff;
+	tp->pci_cacheline_sz = (cacheline_sz_reg >>  0) & 0xff;
+	tp->pci_lat_timer    = (cacheline_sz_reg >>  8) & 0xff;
+	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_5703 &&
+	    tp->pci_lat_timer < 64) {
+		tp->pci_lat_timer = 64;
+
+		cacheline_sz_reg  = ((tp->pci_cacheline_sz & 0xff) <<  0);
+		cacheline_sz_reg |= ((tp->pci_lat_timer    & 0xff) <<  8);
+		cacheline_sz_reg |= ((tp->pci_hdr_type     & 0xff) << 16);
+		cacheline_sz_reg |= ((tp->pci_bist         & 0xff) << 24);
+
+		pci_write_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
+				       cacheline_sz_reg);
+	}
 
 	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
 			      &pci_state_reg);
@@ -5923,6 +5956,10 @@
 	tp->dma_rwctrl |= DMA_RWCTRL_USE_MEM_READ_MULT;
 
 	tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
+		return 0;
 
 	ret = 0;
 	while (1) {
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/tg3.h	Sun Apr 14 12:16:56 2002
@@ -1654,7 +1654,7 @@
  */
 struct ring_info {
 	struct sk_buff			*skb;
-	dma_addr_t			mapping;
+	DECLARE_PCI_UNMAP_ADDR(mapping)
 };
 
 struct tg3_config_info {
diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
--- a/drivers/net/tokenring/olympic.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/tokenring/olympic.c	Sun Apr 14 12:16:59 2002
@@ -1757,7 +1757,7 @@
 	name:		"olympic",
 	id_table:	olympic_pci_tbl,
 	probe:		olympic_probe,
-	remove:		__devexit_p(olympic_remove_one)
+	remove:		__devexit_p(olympic_remove_one),
 };
 
 static int __init olympic_pci_init(void) 
diff -Nru a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
--- a/drivers/net/tokenring/smctr.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/tokenring/smctr.c	Sun Apr 14 12:16:58 2002
@@ -3718,8 +3718,8 @@
         }
 
         tp = (struct net_local *)dev->priv;
-        dev->rmem_start = dev->mem_start = tp->ram_base;
-        dev->rmem_end = dev->mem_end = dev->mem_start + 0x10000;
+        dev->mem_start = tp->ram_base;
+        dev->mem_end = dev->mem_start + 0x10000;
         ram = (__u32 *)phys_to_virt(dev->mem_start);
         tp->ram_access = *(__u32 *)&ram;
 	tp->status = NOT_INITIALIZED;
diff -Nru a/drivers/net/wan/comx-hw-locomx.c b/drivers/net/wan/comx-hw-locomx.c
--- a/drivers/net/wan/comx-hw-locomx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/wan/comx-hw-locomx.c	Sun Apr 14 12:16:59 2002
@@ -154,11 +154,9 @@
 		return -ENODEV;
 	}
 
-	if (check_region(dev->base_addr, hw->io_extent)) {
+	if (!request_region(dev->base_addr, hw->io_extent, dev->name)) {
 		return -EAGAIN;
 	}
-
-	request_region(dev->base_addr, hw->io_extent, dev->name);
 
 	hw->board.chanA.ctrlio=dev->base_addr + 5;
 	hw->board.chanA.dataio=dev->base_addr + 7;
diff -Nru a/drivers/net/wan/comx-hw-mixcom.c b/drivers/net/wan/comx-hw-mixcom.c
--- a/drivers/net/wan/comx-hw-mixcom.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/net/wan/comx-hw-mixcom.c	Sun Apr 14 12:16:58 2002
@@ -566,8 +566,6 @@
 
 	return 0;
 	
-err_restore_flags:
-	restore_flags(flags);
 err_release_region:
 	release_region(dev->base_addr, MIXCOM_IO_EXTENT);
 err_ret:
diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c
--- a/drivers/net/wan/comx-hw-munich.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/wan/comx-hw-munich.c	Sun Apr 14 12:16:56 2002
@@ -1397,15 +1397,6 @@
     return;
 }
 
-void free_stuff(munich_board_t *board, struct comx_channel *ch)
-{
-/* Free CCB and the interrupt queues */
-    if (board->ccb) kfree((void *)board->ccb);
-    if (board->tiq) kfree((void *)board->tiq);
-    if (board->riq) kfree((void *)board->riq);
-    if (board->piq) kfree((void *)board->piq);
-}
-
 /* 
  * Hardware open routine.
  * Called by comx (upper) layer when the user wants to bring up the interface
@@ -1488,7 +1479,6 @@
 	if (board->tiq == NULL)
 	{
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -ENOMEM;
 	}
 	memset((void *)board->tiq, 0, MUNICH_INTQSIZE);
@@ -1497,7 +1487,6 @@
 	if (board->riq == NULL)
 	{
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -ENOMEM;
 	}
 	memset((void *)board->riq, 0, MUNICH_INTQSIZE);
@@ -1506,7 +1495,6 @@
 	if (board->piq == NULL)
 	{
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -ENOMEM;
 	}
 	memset((void *)board->piq, 0, MUNICH_PIQSIZE);
@@ -1527,7 +1515,6 @@
 		   board->pci->irq);
 	    /* TOD: free other resources (a sok malloc feljebb)                     */
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -EAGAIN;
 	}
 	board->irq = board->pci->irq;	/* csak akkor legyen != 0, ha tenyleg le van foglalva nekunk */
@@ -1597,7 +1584,6 @@
 	    free_irq(board->irq, (void *)board);	/* TOD: free other resources too *//* maybe shut down hw? */
 	    board->irq = 0;
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -EAGAIN;
 	}
 	else if (!(stat & STAT_PCMA))
@@ -1608,7 +1594,6 @@
 	    free_irq(board->irq, (void *)board);	/* TOD: free other resources too *//* maybe shut off the hw? */
 	    board->irq = 0;
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -EIO;
 	}
 
@@ -1670,7 +1655,7 @@
     spin_unlock_irqrestore(&mister_lock, flags);
 
     dev->irq = board->irq;	/* hogy szep legyen az ifconfig outputja */
-    ccb = board->ccb;		/* TOD: ez igy csunya egy kicsit hogy benn is meg kinn is beletoltom :( */
+    ccb = board->ccb;		/* TODO: ez igy csunya egy kicsit hogy benn is meg kinn is beletoltom :( */
 
     spin_lock_irqsave(&mister_lock, flags);
 
@@ -1680,13 +1665,12 @@
     /* Check if the selected timeslots aren't used already */
 
     for (i = 0; i < 32; i++)
-	if (((1 << i) & timeslots) && ccb->timeslot_spec[i].tti == 0)
+	if (((1 << i) & timeslots) && !ccb->timeslot_spec[i].tti)
 	{
 	    printk("MUNICH_open: %s: timeslot %d already used by %s\n",
 		   dev->name, i, board->twins[ccb->timeslot_spec[i].txchannel]->name);
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
-	    return -EBUSY;	/* TOD: lehet hogy valami mas errno kellene? */
+	    return -EBUSY;	/* TODO: lehet hogy valami mas errno kellene? */
 	}
 
     /* find a free channel: */
@@ -1700,7 +1684,6 @@
 		("MUNICH_open: %s: FATAL: can not find a free channel - this should not happen!\n",
 		 dev->name);
 	    spin_unlock_irqrestore(&mister_lock, flags);
-	    free_stuff(board, ch);
 	    return -ENODEV;
 	}
 	if (board->twins[channel] == NULL)
@@ -1998,7 +1981,7 @@
 
     spin_lock_irqsave(&mister_lock, flags);
 
-    board->use_count--;
+    if (board->use_count) board->use_count--;
 
     if (!board->use_count)	/* we were the last user of the board */
     {
@@ -2020,7 +2003,12 @@
 	    free_irq(board->irq, (void *)board);	/* Ha nem inicializalta magat, akkor meg nincs irq */
 	board->irq = 0;
 
-	free_stuff(board, ch);
+	/* Free CCB and the interrupt queues */
+	if (board->ccb) kfree((void *)board->ccb);
+	if (board->tiq) kfree((void *)board->tiq);
+	if (board->riq) kfree((void *)board->riq);
+	if (board->piq) kfree((void *)board->piq);
+	board->ccb = board->tiq = board->riq = board->piq = NULL;
     }
 
     /* Enable setting of hw parameters */
diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
--- a/drivers/net/wan/cosa.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/net/wan/cosa.c	Sun Apr 14 12:16:54 2002
@@ -105,13 +105,6 @@
 #include <net/syncppp.h>
 #include "cosa.h"
 
-/* Linux version stuff */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-typedef struct wait_queue *wait_queue_head_t;
-#define DECLARE_WAITQUEUE(wait, current) \
-	struct wait_queue wait = { current, NULL }
-#endif
-
 /* Maximum length of the identification string. */
 #define COSA_MAX_ID_STRING	128
 
diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
--- a/drivers/net/wan/dscc4.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/wan/dscc4.c	Sun Apr 14 12:16:56 2002
@@ -515,8 +515,9 @@
 		stats->rx_bytes += pkt_len;
 		skb->tail += pkt_len;
 		skb->len = pkt_len;
-       		if (netif_running(dev))
+       	if (netif_running(dev))
 			skb->protocol = htons(ETH_P_HDLC);
+		skb->dev->last_rx = jiffies;
 		netif_rx(skb);
 		try_get_rx_skb(dpriv, cur, dev);
 	} else {
diff -Nru a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
--- a/drivers/net/wan/hd6457x.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/wan/hd6457x.c	Sun Apr 14 12:16:56 2002
@@ -291,6 +291,7 @@
 #endif
 	port->hdlc.stats.rx_packets++;
 	port->hdlc.stats.rx_bytes += skb->len;
+	skb->dev->last_rx = jiffies;
 	skb->mac.raw = skb->data;
 	skb->dev = hdlc_to_dev(&port->hdlc);
 	skb->protocol = htons(ETH_P_HDLC);
diff -Nru a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
--- a/drivers/net/wan/sdla_ppp.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/net/wan/sdla_ppp.c	Sun Apr 14 12:16:56 2002
@@ -1463,11 +1463,11 @@
 {
         int cnt = 0;
 
-        tokens[0] = strtok(str, "/");
+        tokens[0] = strsep(&str, "/");
         while (tokens[cnt] && (cnt < 32 - 1))
         {
                 tokens[cnt] = strstrip(tokens[cnt], " \t");
-                tokens[++cnt] = strtok(NULL, "/");
+                tokens[++cnt] = strsep(&str, "/");
         }
 	return cnt;
 }
diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c
--- a/drivers/net/wd.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/net/wd.c	Sun Apr 14 12:16:55 2002
@@ -97,7 +97,7 @@
 			return -EBUSY;
 		i = wd_probe1(dev, base_addr);
 		if (i != 0)  
-			release_resource(r);
+			release_region(base_addr, WD_IO_EXTENT);
 		else
 			r->name = dev->name;
 		return i;
@@ -114,7 +114,7 @@
 			r->name = dev->name;
 			return 0;
 		}
-		release_resource(r);
+		release_region(ioaddr, WD_IO_EXTENT);
 	}
 
 	return -ENODEV;
@@ -281,7 +281,7 @@
 	ei_status.rx_start_page = WD_START_PG + TX_PAGES;
 
 	/* Don't map in the shared memory until the board is actually opened. */
-	dev->rmem_start = dev->mem_start + TX_PAGES*256;
+	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
 
 	/* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
 	if (dev->mem_end != 0) {
@@ -290,7 +290,7 @@
 		ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
 		dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
 	}
-	dev->rmem_end = dev->mem_end;
+	ei_status.rmem_end = dev->mem_end;
 
 	printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
 		   model_name, dev->irq, dev->mem_start, dev->mem_end-1);
@@ -384,12 +384,12 @@
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 	unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
 
-	if (xfer_start + count > dev->rmem_end) {
+	if (xfer_start + count > ei_status.rmem_end) {
 		/* We must wrap the input move. */
-		int semi_count = dev->rmem_end - xfer_start;
+		int semi_count = ei_status.rmem_end - xfer_start;
 		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
 		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
diff -Nru a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
--- a/drivers/net/wireless/orinoco_plx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/wireless/orinoco_plx.c	Sun Apr 14 12:16:59 2002
@@ -267,21 +267,28 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
-
 static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = {
-	{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},
+	{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,},	/* Netgear MA301 */
+#if 0
+	{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},	/* Correga */
+#endif
+	{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* SMC EZConnect SMC2602W,
+							   Eumitcom PCI WL11000,
+							   Addtron AWA-100*/
+	{0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* Global Sun Tech GL24110P */
+	{0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,},	/* Reported working, but unknown */
+	{0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,},	/* Linksys WDT11 */
+	{0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,},	/* USR 2415 */
+	{0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, 	/* Belkin F5D6000 */
 	{0,},
 };
-
 MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table);
 
 static struct pci_driver orinoco_plx_driver = {
-	name:"orinoco_plx",
-	id_table:orinoco_plx_pci_id_table,
-	probe:orinoco_plx_init_one,
-	remove:__devexit_p(orinoco_plx_remove_one),
-	suspend:0,
-	resume:0
+	name:		"orinoco_plx",
+	id_table:	orinoco_plx_pci_id_table,
+	probe:		orinoco_plx_init_one,
+	remove:		__devexit_p(orinoco_plx_remove_one),
 };
 
 static int __init orinoco_plx_init(void)
diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
--- a/drivers/net/wireless/wavelan_cs.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/net/wireless/wavelan_cs.c	Sun Apr 14 12:16:59 2002
@@ -4477,9 +4477,8 @@
 	  break;
 	}
 
-      dev->rmem_start = dev->mem_start =
-	  (u_long)ioremap(req.Base, req.Size);
-      dev->rmem_end = dev->mem_end = dev->mem_start + req.Size;
+      dev->mem_start = (u_long)ioremap(req.Base, req.Size);
+      dev->mem_end = dev->mem_start + req.Size;
 
       mem.CardOffset = 0; mem.Page = 0;
       i = CardServices(MapMemPage, link->win, &mem);
diff -Nru a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
--- a/drivers/parport/parport_mfc3.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/parport/parport_mfc3.c	Sun Apr 14 12:16:57 2002
@@ -408,6 +408,7 @@
 MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
 MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port");
 MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port");
+MODULE_LICENSE("GPL");
 
 module_init(parport_mfc3_init)
 module_exit(parport_mfc3_exit)
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/pci/pci.c	Sun Apr 14 12:16:57 2002
@@ -893,7 +893,7 @@
 #endif /* !HAVE_ARCH_PCI_MWI */
 
 /**
- * pci_set_mwi - enables memory-write-validate PCI transaction
+ * pci_set_mwi - enables memory-write-invalidate PCI transaction
  * @dev: the PCI device for which MWI is enabled
  *
  * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	Sun Apr 14 12:16:54 2002
+++ b/drivers/pci/pci.ids	Sun Apr 14 12:16:54 2002
@@ -824,6 +824,7 @@
 	0074  56k Voice Modem
 		1033 8014  RCV56ACF 56k Voice Modem
 	009b  Vrc5476
+	00a6  VRC5477 AC97
 	00e0  USB 2.0
 1034  Framatome Connectors USA Inc.
 1035  Comp. & Comm. Research Lab
@@ -1108,12 +1109,14 @@
 1059  Teknor Industrial Computers Inc
 105a  Promise Technology, Inc.
 	0d30  20265
+	1275  20275
 	4d30  20267
 	4d33  20246
 	4d38  20262
 	4d68  20268
 	6268  20268R
 	4d69  20269
+	5275  20276
 	5300  DC5300
 105b  Foxconn International, Inc.
 105c  Wipro Infotech Limited
@@ -1192,11 +1195,21 @@
 	0017  Paddington Mac I/O
 	0018  UniNorth FireWire
 	0019  KeyLargo USB
-	001e  UniNorth PCI
+	001e  UniNorth Internal PCI
 	001f  UniNorth PCI
 	0020  UniNorth AGP
-	0021  UniNorth GMAC
+	0021  UniNorth GMAC (Sun GEM)
 	0022  KeyLargo Mac I/O
+	0024  UniNorth/Pangea GMAC (Sun GEM)
+	0025  KeyLargo/Pangea Mac I/O
+	0026  KeyLargo/Pangea USB
+	0027  UniNorth/Pangea AGP
+	0028  UniNorth/Pangea PCI
+	0029  UniNorth/Pangea Internal PCI
+	002d  UniNorth 1.5 AGP
+	002e  UniNorth 1.5 PCI
+	002f  UniNorth 1.5 Internal PCI
+	0030  UniNorth/Pangea FireWire
 106c  Hyundai Electronics America
 	8801  Dual Pentium ISA/PCI Motherboard
 	8802  PowerPC ISA/PCI Motherboard
@@ -2620,6 +2633,8 @@
 	0005  ATP850UF
 	0006  ATP860 NO-BIOS
 	0007  ATP860
+	0008  ATP865 NO-ROM
+	0009  ATP865
 	8002  AEC6710 SCSI-2 Host Adapter
 	8010  AEC6712UW SCSI
 	8020  AEC6712U SCSI
@@ -3965,7 +3980,7 @@
 	9511  16PCI954 Function 1
 		15ed 2000  Macrolink MCCR Serial p4-7 of 8
 		15ed 2001  Macrolink MCCR Serial p4-15 of 16
-	9521  Oxford Semi OX16PCI952 PCI/dual 16950 UART
+	9521  16PCI952 PCI/dual 16950 UART
 1416  Multiwave Innovation pte Ltd
 1417  Convergenet Technologies Inc
 1418  Kyushu electronics systems Inc
diff -Nru a/drivers/pcmcia/Config.in b/drivers/pcmcia/Config.in
--- a/drivers/pcmcia/Config.in	Sun Apr 14 12:16:58 2002
+++ b/drivers/pcmcia/Config.in	Sun Apr 14 12:16:58 2002
@@ -24,6 +24,8 @@
       dep_tristate '  HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
    fi
 fi
-dep_tristate '  SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
+if [ "$CONFIG_ARM" = "y" ]; then
+   dep_tristate '  SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
+fi
 
 endmenu
diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
--- a/drivers/pcmcia/i82092.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/pcmcia/i82092.c	Sun Apr 14 12:16:58 2002
@@ -43,7 +43,7 @@
 	name:           "i82092aa",
 	id_table:       i82092aa_pci_ids,
 	probe:          i82092aa_pci_probe,
-	remove:         i82092aa_pci_remove,
+	remove:         __devexit_p(i82092aa_pci_remove),
 	suspend:        NULL,
 	resume:         NULL 
 };
@@ -168,7 +168,7 @@
 	return ret;			
 }
 
-static void __exit i82092aa_pci_remove(struct pci_dev *dev)
+static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
 {
 	enter("i82092aa_pci_remove");
 	
diff -Nru a/drivers/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c
--- a/drivers/pnp/pnpbios_core.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/pnp/pnpbios_core.c	Sun Apr 14 12:16:55 2002
@@ -4,7 +4,7 @@
  * Originally (C) 1998 Christian Schmidt <schmidt@digadd.de>
  * Modifications (c) 1998 Tom Lees <tom@lpsg.demon.co.uk>
  * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
- * Modifications (c) 2001 by Thomas Hood <jdthood@mail.com>
+ * Modifications (c) 2001,2002 by Thomas Hood <jdthood@mail.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
@@ -190,8 +190,8 @@
 	/* If we get here and this is set then the PnP BIOS faulted on us. */
 	if(pnp_bios_is_utter_crap)
 	{
-		printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue.\n");
-		printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably.\n");
+		printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
+		printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably\n");
 		printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
 	}
 
@@ -205,11 +205,16 @@
  *
  */
 
+static void pnpbios_warn_unexpected_status(const char * module, u16 status)
+{
+	printk(KERN_ERR "PnPBIOS: %s: Unexpected status 0x%x\n", module, status);
+}
+
 void *pnpbios_kmalloc(size_t size, int f)
 {
 	void *p = kmalloc( size, f );
 	if ( p == NULL )
-		printk(KERN_ERR "PnPBIOS: kmalloc() failed.\n");
+		printk(KERN_ERR "PnPBIOS: kmalloc() failed\n");
 	return p;
 }
 
@@ -251,7 +256,7 @@
 static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_dev_node_info));
 	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
@@ -263,7 +268,7 @@
 {
 	int status = __pnp_bios_dev_node_info( data );
 	if ( status )
-		printk(KERN_WARNING "PnPBIOS: dev_node_info: Unexpected status 0x%x\n", status);
+		pnpbios_warn_unexpected_status( "dev_node_info", status );
 	return status;
 }
 
@@ -284,7 +289,7 @@
 static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	if ( !boot & pnpbios_dont_use_current_config )
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -299,7 +304,7 @@
 	int status;
 	status =  __pnp_bios_get_dev_node( nodenum, boot, data );
 	if ( status )
-		printk(KERN_WARNING "PnPBIOS: get_dev_node: Unexpected 0x%x\n", status);
+		pnpbios_warn_unexpected_status( "get_dev_node", status );
 	return status;
 }
 
@@ -313,7 +318,7 @@
 static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	if ( !boot & pnpbios_dont_use_current_config )
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -327,17 +332,14 @@
 	int status;
 	status =  __pnp_bios_set_dev_node( nodenum, boot, data );
 	if ( status ) {
-		printk(KERN_WARNING "PnPBIOS: set_dev_node: Unexpected set_dev_node status 0x%x\n", status);
+		pnpbios_warn_unexpected_status( "set_dev_node", status );
 		return status;
 	}
-	if ( !boot ) {
-		/* Update devlist */
+	if ( !boot ) { /* Update devlist */
 		u8 thisnodenum = nodenum;
-		status =  __pnp_bios_get_dev_node( &nodenum, boot, data );
-		if ( status ) {
-			printk(KERN_WARNING "PnPBIOS: set_dev_node: Unexpected get_dev_node status 0x%x\n", status);
+		status =  pnp_bios_get_dev_node( &nodenum, boot, data );
+		if ( status )
 			return status;
-		}
 		update_devlist( thisnodenum, data );
 	}
 	return status;
@@ -350,7 +352,7 @@
 static int pnp_bios_get_event(u16 *event)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, event, sizeof(u16));
 	status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
@@ -365,7 +367,7 @@
 static int pnp_bios_send_message(u16 message)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0);
 	return status;
@@ -379,7 +381,7 @@
 static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_docking_station_info));
 	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
@@ -395,7 +397,7 @@
 static int pnp_bios_set_stat_res(char *info)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, info, *((u16 *) info));
 	status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
@@ -403,21 +405,28 @@
 }
 #endif
 
-#if needed
 /*
  * Call PnP BIOS with function 0x0a, "get statically allocated resource
  * information"
  */
-static int pnp_bios_get_stat_res(char *info)
+static int __pnp_bios_get_stat_res(char *info)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, info, 64 * 1024);
 	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
 	return status;
 }
-#endif
+
+int pnp_bios_get_stat_res(char *info)
+{
+	int status;
+	status = __pnp_bios_get_stat_res( info );
+	if ( status )
+		pnpbios_warn_unexpected_status( "get_stat_res", status );
+	return status;
+}
 
 #if needed
 /*
@@ -426,7 +435,7 @@
 static int pnp_bios_apm_id_table(char *table, u16 *size)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, table, *size);
 	Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
@@ -435,45 +444,58 @@
 }
 #endif
 
-#if needed
 /*
  * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
  */
-static int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
+static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_isa_config_struc));
 	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
 	return status;
 }
-#endif
 
-#if needed
+int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
+{
+	int status;
+	status = __pnp_bios_isapnp_config( data );
+	if ( status )
+		pnpbios_warn_unexpected_status( "isapnp_config", status );
+	return status;
+}
+
 /*
  * Call PnP BIOS with function 0x41, "get ESCD info"
  */
-static int pnp_bios_escd_info(struct escd_info_struc *data)
+static int __pnp_bios_escd_info(struct escd_info_struc *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, sizeof(struct escd_info_struc));
 	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
 	return status;
 }
-#endif
 
-#if needed
+int pnp_bios_escd_info(struct escd_info_struc *data)
+{
+	int status;
+	status = __pnp_bios_escd_info( data );
+	if ( status )
+		pnpbios_warn_unexpected_status( "escd_info", status );
+	return status;
+}
+
 /*
  * Call PnP BIOS function 0x42, "read ESCD"
  * nvram_base is determined by calling escd_info
  */
-static int pnp_bios_read_escd(char *data, u32 nvram_base)
+static int __pnp_bios_read_escd(char *data, u32 nvram_base)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
 	set_base(gdt[PNP_TS2 >> 3], nvram_base);
@@ -481,7 +503,15 @@
 	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
 	return status;
 }
-#endif
+
+int pnp_bios_read_escd(char *data, u32 nvram_base)
+{
+	int status;
+	status = __pnp_bios_read_escd( data, nvram_base );
+	if ( status )
+		pnpbios_warn_unexpected_status( "read_escd", status );
+	return status;
+}
 
 #if needed
 /*
@@ -490,7 +520,7 @@
 static int pnp_bios_write_escd(char *data, u32 nvram_base)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
 	set_base(gdt[PNP_TS2 >> 3], nvram_base);
@@ -574,13 +604,13 @@
 static int pnp_dock_thread(void * unused)
 {
 	static struct pnp_docking_station_info now;
-	int docked = -1, d;
+	int docked = -1, d = 0;
 	daemonize();
 	reparent_to_init();
-	strcpy(current->comm, "kpnpbios");
+	strcpy(current->comm, "kpnpbiosd");
 	while(!unloading && !signal_pending(current))
 	{
-		int err;
+		int status;
 		
 		/*
 		 * Poll every 2 seconds
@@ -590,9 +620,9 @@
 		if(signal_pending(current))
 			break;
 
-		err = pnp_bios_dock_station_info(&now);
+		status = pnp_bios_dock_station_info(&now);
 
-		switch(err)
+		switch(status)
 		{
 			/*
 			 * No dock to manage
@@ -606,7 +636,7 @@
 				d = 1;
 				break;
 			default:
-				printk(KERN_WARNING "PnPBIOS: pnp_dock_thread: Unexpected status 0x%x returned by BIOS.\n", err);
+				pnpbios_warn_unexpected_status( "pnp_dock_thread", status );
 				continue;
 		}
 		if(d != docked)
@@ -615,7 +645,7 @@
 			{
 				docked = d;
 #if 0
-				printk(KERN_INFO "PnPBIOS: Docking station %stached.\n", docked?"at":"de");
+				printk(KERN_INFO "PnPBIOS: Docking station %stached\n", docked?"at":"de");
 #endif
 			}
 		}
@@ -848,15 +878,14 @@
  */
 static void __init build_devlist(void)
 {
-	int i;
-	int nodenum;
-	int nodes_got = 0;
-	int devs = 0;
+	u8 nodenum;
+	unsigned int nodes_got = 0;
+	unsigned int devs = 0;
 	struct pnp_bios_node *node;
 	struct pnp_dev_node_info node_info;
 	struct pci_dev *dev;
 	
-	if (!pnp_bios_present ())
+	if (!pnp_bios_present())
 		return;
 
 	if (pnp_bios_dev_node_info(&node_info) != 0)
@@ -866,26 +895,20 @@
 	if (!node)
 		return;
 
-	for(i=0,nodenum=0; i<0xff && nodenum!=0xff; i++) {
-		int thisnodenum = nodenum;
-		/* For now we build the list from the "boot" config
-		 * because asking for the "current" config causes
-		 * some BIOSes to crash.                          */
-		if (pnp_bios_get_dev_node((u8 *)&nodenum, (char )1 , node)) {
-			printk(KERN_WARNING "PnPBIOS: PnP BIOS reported error on attempt to get dev node.\n");
-			break;
-		}
-		/* The BIOS returns with nodenum = the next node number */
-		if (nodenum < thisnodenum) {
-			printk(KERN_WARNING "PnPBIOS: Node number is out of sequence. Naughty BIOS!\n");
+	for(nodenum=0; nodenum<0xff; ) {
+		u8 thisnodenum = nodenum;
+		/* We build the list from the "boot" config because
+		 * asking for the "current" config causes some
+		 * BIOSes to crash.
+		 */
+		if (pnp_bios_get_dev_node(&nodenum, (char )1 , node))
 			break;
-		}
 		nodes_got++;
 		dev =  pnpbios_kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
 		if (!dev)
 			break;
 		memset(dev,0,sizeof(struct pci_dev));
-		dev->devfn=thisnodenum;
+		dev->devfn = thisnodenum;
 		memcpy(dev->name,"PNPBIOS",8);
 		pnpid32_to_pnpid(node->eisa_id,dev->slot_name);
 		node_resource_data_to_dev(node,dev);
@@ -893,10 +916,14 @@
 			kfree(dev);
 		else
 			devs++;
+		if (nodenum <= thisnodenum) {
+			printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
+			break;
+		}
 	}
 	kfree(node);
 
-	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver.\n",
+	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver\n",
 		nodes_got, nodes_got != 1 ? "s" : "", devs);
 }
 
@@ -1062,7 +1089,7 @@
 	regionid = pnpbios_kmalloc(16, GFP_KERNEL);
 	if ( regionid == NULL )
 		return;
-	sprintf(regionid, "PnPBIOS %s", pnpid);
+	snprintf(regionid, 16, "PnPBIOS %s", pnpid);
 	res = request_region(start,end-start+1,regionid);
 	if ( res == NULL )
 		kfree( regionid );
@@ -1074,7 +1101,7 @@
 	 * have double reservations.
 	 */
 	printk(KERN_INFO
-		"PnPBIOS: %s: ioport range 0x%x-0x%x %s reserved.\n",
+		"PnPBIOS: %s: ioport range 0x%x-0x%x %s reserved\n",
 		pnpid, start, end,
 		NULL != res ? "has been" : "could not be"
 	);
@@ -1193,14 +1220,14 @@
 {
 	union pnp_bios_expansion_header *check;
 	u8 sum;
-	int i, length;
+	int i, length, r;
 
 	spin_lock_init(&pnp_bios_lock);
 	spin_lock_init(&pnpbios_devices_lock);
 
 	if(pnpbios_disabled) {
-		printk(KERN_INFO "PnPBIOS: Disabled.\n");
-		return 0;
+		printk(KERN_INFO "PnPBIOS: Disabled\n");
+		return -ENODEV;
 	}
 
 	if ( is_sony_vaio_laptop )
@@ -1224,13 +1251,13 @@
 		if (sum)
 			continue;
 		if (check->fields.version < 0x10) {
-			printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported.\n",
+			printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported\n",
 			       check->fields.version >> 4,
 			       check->fields.version & 15);
 			continue;
 		}
-		printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p.\n", check);
-		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x.\n",
+		printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check);
+		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n",
                        check->fields.version >> 4, check->fields.version & 15,
 		       check->fields.pm16cseg, check->fields.pm16offset,
 		       check->fields.pm16dseg);
@@ -1242,12 +1269,21 @@
 		pnp_bios_hdr = check;
 		break;
 	}
+	if (!pnp_bios_present())
+		return -ENODEV;
 	build_devlist();
 	if ( ! dont_reserve_resources )
 		reserve_resources();
 #ifdef CONFIG_PROC_FS
-	pnpbios_proc_init();
+	r = pnpbios_proc_init();
+	if (r)
+		return r;
 #endif
+	return 0;
+}
+
+static int __init pnpbios_thread_init(void)
+{
 #ifdef CONFIG_HOTPLUG	
 	init_completion(&unload_sem);
 	if(kernel_thread(pnp_dock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL)>0)
@@ -1256,23 +1292,46 @@
 	return 0;
 }
 
-#ifdef MODULE
+#ifndef MODULE
+
+/* init/main.c calls pnpbios_init early */
+
+/* Start the kernel thread later: */
+module_init(pnpbios_thread_init);
+
+#else
+
+/*
+ * N.B.: Building pnpbios as a module hasn't been fully implemented
+ */
 
 MODULE_LICENSE("GPL");
 
-/* We have to run it early and not as a module. */
-module_init(pnpbios_init);
+static int __init pnpbios_init_all(void)
+{
+	int r;
+
+	r = pnpbios_init();
+	if (r)
+		return r;
+	r = pnpbios_thread_init();
+	if (r)
+		return r;
+	return 0;
+}
 
-#ifdef CONFIG_HOTPLUG
-static void pnpbios_exit(void)
+static void __exit pnpbios_exit(void)
 {
-	/* free_resources() ought to go here */
-	/* pnpbios_proc_done() */
+#ifdef CONFIG_HOTPLUG
 	unloading = 1;
 	wait_for_completion(&unload_sem);
+#endif
+	pnpbios_proc_exit();
+	/* We ought to free resources here */
+	return;
 }
 
+module_init(pnpbios_init_all);
 module_exit(pnpbios_exit);
 
-#endif
 #endif
diff -Nru a/drivers/pnp/pnpbios_proc.c b/drivers/pnp/pnpbios_proc.c
--- a/drivers/pnp/pnpbios_proc.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/pnp/pnpbios_proc.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,21 @@
 /*
- * pnp_proc.c: /proc/bus/pnp interface for Plug and Play devices
+ * /proc/bus/pnp interface for Plug and Play devices
  *
  * Written by David Hinds, dahinds@users.sourceforge.net
+ * Modified by Thomas Hood, jdthood@mail.com
+ *
+ * The .../devices and .../<node> and .../boot/<node> files are
+ * utilized by the lspnp and setpnp utilities, supplied with the
+ * pcmcia-cs package.
+ *     http://pcmcia-cs.sourceforge.net
+ *
+ * The .../escd file is utilized by the lsescd utility written by
+ * Gunther Mayer.
+ *     http://home.t-online.de/home/gunther.mayer/lsescd
+ *
+ * The .../legacy_device_resources file is not used yet.
+ *
+ * The other files are human-readable.
  */
 
 //#include <pcmcia/config.h>
@@ -19,30 +33,118 @@
 static struct proc_dir_entry *proc_pnp_boot = NULL;
 static struct pnp_dev_node_info node_info;
 
+static int proc_read_pnpconfig(char *buf, char **start, off_t pos,
+                               int count, int *eof, void *data)
+{
+	struct pnp_isa_config_struc pnps;
+
+	if (pnp_bios_isapnp_config(&pnps))
+		return -EIO;
+	return snprintf(buf, count,
+		"structure_revision %d\n"
+		"number_of_CSNs %d\n"
+		"ISA_read_data_port 0x%x\n",
+		pnps.revision,
+		pnps.no_csns,
+		pnps.isa_rd_data_port
+	);
+}
+
+static int proc_read_escdinfo(char *buf, char **start, off_t pos,
+                              int count, int *eof, void *data)
+{
+	struct escd_info_struc escd;
+
+	if (pnp_bios_escd_info(&escd))
+		return -EIO;
+	return snprintf(buf, count,
+		"min_ESCD_write_size %d\n"
+		"ESCD_size %d\n"
+		"NVRAM_base 0x%x\n",
+		escd.min_escd_write_size,
+		escd.escd_size,
+		escd.nv_storage_base
+	);
+}
+
+static int proc_read_escd(char *buf, char **start, off_t pos,
+                          int count, int *eof, void *data)
+{
+	struct escd_info_struc escd;
+	char *tmpbuf;
+	int escd_size, escd_left_to_read, n;
+
+	if (pnp_bios_escd_info(&escd))
+		return -EIO;
+
+	/* sanity check */
+	if (escd.escd_size > (32*1024)) {
+		printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size is too great\n");
+		return -EFBIG;
+	}
+
+	tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
+	if (!tmpbuf) return -ENOMEM;
+
+	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base))
+		return -EIO;
+
+	escd_size = (unsigned char)(buf[0]) + (unsigned char)(buf[1])*256;
+	escd_left_to_read = escd_size - pos;
+	if (escd_left_to_read < 0) escd_left_to_read = 0;
+	if (escd_left_to_read == 0) *eof = 1;
+	n = min(count,escd_left_to_read);
+	memcpy(buf, tmpbuf + pos, n);
+	kfree(tmpbuf);
+	*start = buf;
+	return n;
+}
+
+static int proc_read_legacyres(char *buf, char **start, off_t pos,
+                               int count, int *eof, void *data)
+{
+	/* Assume that the following won't overflow the buffer */
+	if (pnp_bios_get_stat_res(buf)) 
+		return -EIO;
+
+	return count;  // FIXME: Return actual length
+}
+
 static int proc_read_devices(char *buf, char **start, off_t pos,
                              int count, int *eof, void *data)
 {
 	struct pnp_bios_node *node;
-	int i;
 	u8 nodenum;
 	char *p = buf;
 
-	if (pos != 0) {
-	    *eof = 1;
-	    return 0;
-	}
+	if (pos >= 0xff)
+		return 0;
+
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	for (i=0,nodenum=0;i<0xff && nodenum!=0xff; i++) {
-		if ( pnp_bios_get_dev_node(&nodenum, 1, node) )
+
+	for (nodenum=pos; nodenum<0xff; ) {
+		u8 thisnodenum = nodenum;
+		/* 26 = the number of characters per line sprintf'ed */
+		if ((p - buf + 26) > count)
+			break;
+		if (pnp_bios_get_dev_node(&nodenum, 1, node))
 			break;
 		p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
 			     node->handle, node->eisa_id,
 			     node->type_code[0], node->type_code[1],
 			     node->type_code[2], node->flags);
+		if (nodenum <= thisnodenum) {
+			printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum);
+			*eof = 1;
+			break;
+		}
 	}
 	kfree(node);
-	return (p-buf);
+	if (nodenum == 0xff)
+		*eof = 1;
+	*start = (char *)((off_t)nodenum - pos);
+	return p - buf;
 }
 
 static int proc_read_node(char *buf, char **start, off_t pos,
@@ -53,13 +155,9 @@
 	u8 nodenum = (long)data;
 	int len;
 
-	if (pos != 0) {
-	    *eof = 1;
-	    return 0;
-	}
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
+	if (pnp_bios_get_dev_node(&nodenum, boot, node))
 		return -EIO;
 	len = node->size - sizeof(struct pnp_bios_node);
 	memcpy(buf, node->data, len);
@@ -92,25 +190,34 @@
  * work and the pnpbios_dont_use_current_config flag
  * should already have been set to the appropriate value
  */
-void pnpbios_proc_init( void )
+int __init pnpbios_proc_init( void )
 {
 	struct pnp_bios_node *node;
 	struct proc_dir_entry *ent;
 	char name[3];
-	int i;
 	u8 nodenum;
 
-	if (pnp_bios_dev_node_info(&node_info) != 0) return;
+	if (pnp_bios_dev_node_info(&node_info))
+		return -EIO;
 	
 	proc_pnp = proc_mkdir("pnp", proc_bus);
-	if (!proc_pnp) return;
+	if (!proc_pnp)
+		return -EIO;
 	proc_pnp_boot = proc_mkdir("boot", proc_pnp);
-	if (!proc_pnp_boot) return;
+	if (!proc_pnp_boot)
+		return -EIO;
 	create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
+	create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL);
+	create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, NULL);
+	create_proc_read_entry("escd", 0, proc_pnp, proc_read_escd, NULL);
+	create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL);
 	
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
-	if (!node) return;
-	for (i=0,nodenum = 0; i<0xff && nodenum != 0xff; i++) {
+	if (!node)
+		return -ENOMEM;
+
+	for (nodenum=0; nodenum<0xff; ) {
+		u8 thisnodenum = nodenum;
 		if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
 			break;
 		sprintf(name, "%02x", node->handle);
@@ -128,11 +235,17 @@
 			ent->write_proc = proc_write_node;
 			ent->data = (void *)(long)(node->handle+0x100);
 		}
+		if (nodenum <= thisnodenum) {
+			printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_init:", (unsigned int)nodenum, (unsigned int)thisnodenum);
+			break;
+		}
 	}
 	kfree(node);
+
+	return 0;
 }
 
-void pnpbios_proc_done(void)
+void __exit pnpbios_proc_exit(void)
 {
 	int i;
 	char name[3];
@@ -145,7 +258,13 @@
 			remove_proc_entry(name, proc_pnp);
 		remove_proc_entry(name, proc_pnp_boot);
 	}
-	remove_proc_entry("boot", proc_pnp);
+	remove_proc_entry("legacy_device_resources", proc_pnp);
+	remove_proc_entry("escd", proc_pnp);
+	remove_proc_entry("escd_info", proc_pnp);
+	remove_proc_entry("configuration_info", proc_pnp);
 	remove_proc_entry("devices", proc_pnp);
+	remove_proc_entry("boot", proc_pnp);
 	remove_proc_entry("pnp", proc_bus);
+
+	return;
 }
diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/s390/block/dasd.c	Sun Apr 14 12:16:58 2002
@@ -2618,7 +2618,7 @@
 	}
         count = atomic_dec_return (&device->open_count);
         if ( count == 0) {
-                invalidate_buffers (inp->i_rdev);
+                invalidate_bdev (inp->i_bdev, 0);
                 if ( device->discipline->owner )
                         __MOD_DEC_USE_COUNT(device->discipline->owner);
                 MOD_DEC_USE_COUNT;
diff -Nru a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
--- a/drivers/s390/block/dasd_int.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/s390/block/dasd_int.h	Sun Apr 14 12:16:59 2002
@@ -201,14 +201,14 @@
         debug_sprintf_event(d_device->debug_area,d_level,\
                     DASD_DEVICE_FORMAT_STRING d_str "\n",\
                     d_device, d_data);\
-} while(0);
+} while(0)
 #define DASD_DEVICE_DEBUG_EXCEPTION(d_level, d_device, d_str, d_data...)\
 do {\
         if ( d_device->debug_area != NULL )\
         debug_sprintf_exception(d_device->debug_area,d_level,\
                         DASD_DEVICE_FORMAT_STRING d_str "\n",\
                         d_device, d_data);\
-} while(0);
+} while(0)
 
 #define DASD_DRIVER_FORMAT_STRING "Driver: <[%p]>"
 #define DASD_DRIVER_DEBUG_EVENT(d_level, d_fn, d_str, d_data...)\
@@ -217,14 +217,14 @@
         debug_sprintf_event(dasd_debug_area, d_level,\
                     DASD_DRIVER_FORMAT_STRING #d_fn ":" d_str "\n",\
                     d_fn, d_data);\
-} while(0);
+} while(0)
 #define DASD_DRIVER_DEBUG_EXCEPTION(d_level, d_fn, d_str, d_data...)\
 do {\
         if ( dasd_debug_area != NULL )\
         debug_sprintf_exception(dasd_debug_area, d_level,\
                         DASD_DRIVER_FORMAT_STRING #d_fn ":" d_str "\n",\
                         d_fn, d_data);\
-} while(0);
+} while(0)
 
 struct dasd_device_t;
 struct request;
diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/s390/block/xpram.c	Sun Apr 14 12:16:59 2002
@@ -655,7 +655,7 @@
 
 	case BLKFLSBUF: /* flush, 0x1261 */
 		fsync_bdev(inode->i_bdev);
-		if ( capable(CAP_SYS_ADMIN) )invalidate_buffers(inode->i_rdev);
+		if ( capable(CAP_SYS_ADMIN) )invalidate_bdev(inode->i_bdev, 0);
 		return 0;
 
 	case BLKRRPART: /* re-read partition table: can't do it, 0x1259 */
@@ -1045,7 +1045,7 @@
 		for (i=0; i < xpram_devs; i++) 
 			if (xpram_sizes[i] == 0) xpram_sizes[i] = mem_auto;
 	}
-	blk_size[major]=xpram_sizes;
+	blk_size[major] = xpram_sizes;
 
 	xpram_offsets = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
 	if (!xpram_offsets) {
diff -Nru a/drivers/s390/char/tapeblock.c b/drivers/s390/char/tapeblock.c
--- a/drivers/s390/char/tapeblock.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/s390/char/tapeblock.c	Sun Apr 14 12:16:58 2002
@@ -217,7 +217,7 @@
 	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
 	tapestate_set (ti, TS_UNUSED);
 	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
-	invalidate_buffers(inode->i_rdev);
+	invalidate_bdev(inode->i_bdev, 0);
 	return 0;
 }
 
diff -Nru a/drivers/sbus/audio/amd7930.c b/drivers/sbus/audio/amd7930.c
--- a/drivers/sbus/audio/amd7930.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/sbus/audio/amd7930.c	Sun Apr 14 12:16:59 2002
@@ -1619,7 +1619,6 @@
 	info->irq = irq.pri;
 	request_irq(info->irq, amd7930_interrupt,
 		    SA_INTERRUPT, "amd7930", drv);
-	enable_irq(info->irq);
 	amd7930_enable_ints(info);
 
 	/* Initalize the local copy of the MAP registers. */
@@ -1644,7 +1643,6 @@
 	err = register_sparcaudio_driver(drv, 1);
 	if (err < 0) {
 		printk(KERN_ERR "amd7930: unable to register\n");
-		disable_irq(info->irq);
 		free_irq(info->irq, drv);
 		sbus_iounmap(info->regs, info->regs_size);
 		kfree(drv->private);
@@ -1666,7 +1664,6 @@
 
 	unregister_sparcaudio_driver(drv, 1);
 	amd7930_idle(info);
-	disable_irq(info->irq);
 	free_irq(info->irq, drv);
 	sbus_iounmap(info->regs, info->regs_size);
 	kfree(drv->private);
diff -Nru a/drivers/sbus/audio/cs4231.c b/drivers/sbus/audio/cs4231.c
--- a/drivers/sbus/audio/cs4231.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/sbus/audio/cs4231.c	Sun Apr 14 12:16:59 2002
@@ -2210,7 +2210,6 @@
         /* Attach the interrupt handler to the audio interrupt. */
         cs4231_chip->irq = sdev->irqs[0];
         request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv);
-        enable_irq(cs4231_chip->irq);
 
         cs4231_chip->nirqs = 1;
         cs4231_enable_interrupts(drv);
@@ -2224,7 +2223,6 @@
         if (err < 0) {
                 printk(KERN_ERR "cs4231: unable to register\n");
                 cs4231_disable_interrupts(drv);
-                disable_irq(cs4231_chip->irq);
                 free_irq(cs4231_chip->irq, drv);
                 sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size);
                 kfree(drv->private);
@@ -2312,9 +2310,7 @@
         bail:
                 printk(KERN_ERR "cs4231: unable to register\n");
                 cs4231_disable_interrupts(drv);
-                disable_irq(cs4231_chip->irq);
                 free_irq(cs4231_chip->irq, drv);
-                disable_irq(cs4231_chip->irq2);
                 free_irq(cs4231_chip->irq2, drv);
                 kfree(drv->private);
                 return -EIO;
@@ -2371,7 +2367,6 @@
 
 	cs4231_disable_interrupts(drv);
 	unregister_sparcaudio_driver(drv, 1);
-	disable_irq(cs4231_chip->irq);
 	free_irq(cs4231_chip->irq, drv);
 	if (!(cs4231_chip->status & CS_STATUS_IS_EBUS)) {
 		sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size);
@@ -2380,7 +2375,6 @@
 		iounmap(cs4231_chip->regs);
 		iounmap(cs4231_chip->eb2p);
 		iounmap(cs4231_chip->eb2c);
-		disable_irq(cs4231_chip->irq2);
 		free_irq(cs4231_chip->irq2, drv);
 #endif
 	}
diff -Nru a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
--- a/drivers/sbus/char/aurora.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/sbus/char/aurora.c	Sun Apr 14 12:16:56 2002
@@ -179,7 +179,7 @@
 #ifdef AURORA_DEBUG
 	printk("aurora_long_delay: start\n");
 #endif
-	for (i = jiffies + delay; i > jiffies; ) ;
+	for (i = jiffies + delay; time_before(jiffies, i); ) ;
 #ifdef AURORA_DEBUG
 	printk("aurora_long_delay: end\n");
 #endif
diff -Nru a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
--- a/drivers/sbus/char/uctrl.c	Sun Apr 14 12:17:00 2002
+++ b/drivers/sbus/char/uctrl.c	Sun Apr 14 12:17:00 2002
@@ -389,15 +389,11 @@
 	if(!driver->irq) 
 		driver->irq = tmp_irq[0].pri;
 
-	request_irq(driver->irq, uctrl_interrupt, 0, 
-		    "uctrl", driver);
-
-	enable_irq(driver->irq);
+	request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
 
 	if (misc_register(&uctrl_dev)) {
 		printk("%s: unable to get misc minor %d\n",
 		       __FUNCTION__, uctrl_dev.minor);
-		disable_irq(driver->irq);
 		free_irq(driver->irq, driver);
 		return -ENODEV;
 	}
@@ -414,10 +410,8 @@
 	struct uctrl_driver *driver = &drv;
 
 	misc_deregister(&uctrl_dev);
-	if (driver->irq) {
-		disable_irq(driver->irq);
+	if (driver->irq)
 		free_irq(driver->irq, driver);
-	}
 	if (driver->regs)
 		driver->regs = 0;
 }
diff -Nru a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
--- a/drivers/sbus/sbus.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/sbus/sbus.c	Sun Apr 14 12:16:58 2002
@@ -392,6 +392,10 @@
 		sbus_bus_ranges_init(iommund, sbus);
 
 		sbus_devs = prom_getchild(this_sbus);
+		if (!sbus_devs) {
+			sbus->devices = NULL;
+			goto next_bus;
+		}
 
 		sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
 
@@ -455,7 +459,7 @@
 		sbus_fixup_all_regs(sbus->devices);
 
 		dvma_init(sbus);
-
+	next_bus:
 		num_sbus++;
 		if(sparc_cpu_model == sun4u) {
 			this_sbus = prom_getsibling(this_sbus);
diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/scsi/3w-xxxx.c	Sun Apr 14 12:16:59 2002
@@ -133,6 +133,14 @@
                  some SMP systems.
    1.02.00.020 - Add pci_set_dma_mask(), rewrite kmalloc()/virt_to_bus() to
                  pci_alloc/free_consistent().
+                 Better alignment checking in tw_allocate_memory().
+                 Cleanup tw_initialize_device_extension().
+   1.02.00.021 - Bump cmd_per_lun in SHT to 255 for better jbod performance.
+                 Improve handling of errors in tw_interrupt().
+                 Add handling/clearing of controller queue error.
+                 Empty stale responses before draining aen queue.
+                 Fix tw_scsi_eh_abort() to not reset on every io abort.
+                 Set can_queue in SHT to 255 to prevent hang from AEN.
 */
 
 #include <linux/module.h>
@@ -182,7 +190,7 @@
 };
 
 /* Globals */
-char *tw_driver_version="1.02.00.020";
+char *tw_driver_version="1.02.00.021";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -284,6 +292,9 @@
 	}
 	tw_clear_attention_interrupt(tw_dev);
 
+	/* Empty response queue */
+	tw_empty_response_que(tw_dev);
+
 	/* Initialize command packet */
 	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
 		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
@@ -337,7 +348,7 @@
 			status_reg_value = inl(status_reg_addr);
 			if (tw_check_bits(status_reg_value)) {
 				dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
-				tw_decode_bits(tw_dev, status_reg_value);
+				tw_decode_bits(tw_dev, status_reg_value, 0);
 				return 1;
 			}
 			if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
@@ -451,7 +462,7 @@
 	status_reg_value = inl(status_reg_addr);
 	if (tw_check_bits(status_reg_value)) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
-		tw_decode_bits(tw_dev, status_reg_value);
+		tw_decode_bits(tw_dev, status_reg_value, 1);
 		return 1;
 	}
 	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
@@ -571,13 +582,23 @@
 	status_reg_value = inl(status_reg_addr);
 
 	if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
-		tw_decode_bits(tw_dev, status_reg_value);
+		tw_decode_bits(tw_dev, status_reg_value, 0);
 		return 1;
 	}
 
 	return 0;
 } /* End tw_check_errors() */
 
+/* This function will clear all interrupts on the controller */
+void tw_clear_all_interrupts(TW_Device_Extension *tw_dev)
+{
+	u32 control_reg_addr, control_reg_value;
+
+	control_reg_addr = tw_dev->registers.control_reg_addr;
+	control_reg_value = TW_STATUS_VALID_INTERRUPT;
+	outl(control_reg_value, control_reg_addr);
+} /* End tw_clear_all_interrupts() */
+
 /* This function will clear the attention interrupt */
 void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -632,30 +653,51 @@
 	}
 } /* End tw_copy_mem_info() */
 
-/* This function will print readable messages from statsu register errors */
-void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value)
+/* This function will print readable messages from status register errors */
+int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host)
 {
+	char host[16];
+
 	dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");
+
+	if (print_host)
+		sprintf(host, " scsi%d:", tw_dev->host->host_no);
+	else
+		host[0] = '\0';
+
 	switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) {
 	case TW_STATUS_PCI_PARITY_ERROR:
-		printk(KERN_WARNING "3w-xxxx: PCI Parity Error: clearing.\n");
+		printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host);
 		outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr);
 		break;
 	case TW_STATUS_MICROCONTROLLER_ERROR:
-		printk(KERN_WARNING "3w-xxxx: Microcontroller Error.\n");
-		break;
+		if (tw_dev->reset_print == 0) {
+			printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host);
+			tw_dev->reset_print = 1;
+		}
+		return 1;
 	case TW_STATUS_PCI_ABORT:
-		printk(KERN_WARNING "3w-xxxx: PCI Abort: clearing.\n");
+		printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host);
 		outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr);
 		pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
 		break;
-  }
+	case TW_STATUS_QUEUE_ERROR:
+		printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host);
+		outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr);
+		break;
+	case TW_STATUS_SBUF_WRITE_ERROR:
+		printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host);
+		outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr);
+		break;
+	}
+	
+	return 0;
 } /* End tw_decode_bits() */
 
 /* This function will return valid sense buffer information for failed cmds */
-void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
+int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
 {
-	int i, found=0;
+	int i;
 	TW_Command *command;
 
         dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n");
@@ -668,7 +710,6 @@
 		if ((command->status == 0xc7) || (command->status == 0xcb)) {
 			for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) {
 				if (command->flags == tw_sense_table[i][0]) {
-					found=1;
 
 					/* Valid bit and 'current errors' */
 					tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70);
@@ -686,13 +727,16 @@
 					tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3];
 
 					tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+					return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */
 				}
 			}
 		}
+
 		/* If no table match, error so we get a reset */
-		if (found == 0)
-			tw_dev->srb[request_id]->result = (DID_RESET << 16);
+		return 1;
 	}
+
+	return 0;
 } /* End tw_decode_sense() */
 
 /* This function will disable interrupts on the controller */  
@@ -706,7 +750,7 @@
 } /* End tw_disable_interrupts() */
 
 /* This function will empty the response que */
-int tw_empty_response_que(TW_Device_Extension *tw_dev) 
+void tw_empty_response_que(TW_Device_Extension *tw_dev) 
 {
 	u32 status_reg_addr, status_reg_value;
 	u32 response_que_addr, response_que_value;
@@ -716,22 +760,10 @@
   
 	status_reg_value = inl(status_reg_addr);
 
-	if (tw_check_bits(status_reg_value)) {
-		dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
-		tw_decode_bits(tw_dev, status_reg_value);
-		return 1;
-	}
-  
 	while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
 		response_que_value = inl(response_que_addr);
 		status_reg_value = inl(status_reg_addr);
-		if (tw_check_bits(status_reg_value)) {
-			dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
-			tw_decode_bits(tw_dev, status_reg_value);
-			return 1;
-		}
 	}
-	return 0;
 } /* End tw_empty_response_que() */
 
 /* This function will enable interrupts on the controller */
@@ -811,8 +843,8 @@
 
 			/* Check for errors and clear them */
 			status_reg_value = inl(tw_dev->registers.status_reg_addr);
-			if (TW_STATUS_ERRORS(status_reg_value)) 
-			  tw_decode_bits(tw_dev, status_reg_value);
+			if (TW_STATUS_ERRORS(status_reg_value))
+				tw_decode_bits(tw_dev, status_reg_value, 0);
 			
 			/* Poll status register for 60 secs for 'Controller Ready' flag */
 			if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) {
@@ -843,14 +875,6 @@
 					continue;
 				}
 
-				/* Empty the response queue */
-				error = tw_empty_response_que(tw_dev);
-				if (error) {
-					printk(KERN_WARNING "3w-xxxx: Couldn't empty response queue, retrying for card %d.\n", numcards);
-					tries++;
-					continue;
-				}
-
 				/* Now the controller is in a good state */
 				break;
 			}
@@ -877,7 +901,7 @@
 			request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME);
 			error = tw_initialize_units(tw_dev);
 			if (error) {
-				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize units for card %d.\n", numcards);
+				printk(KERN_WARNING "3w-xxxx: No valid units for for card %d.\n", numcards);
 				release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
 				tw_free_device_extension(tw_dev);
 				kfree(tw_dev);
@@ -895,7 +919,7 @@
 
 			/* Calculate max cmds per lun, and setup queues */
 			if (tw_dev->num_units > 0) {
-				tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units;
+				/* Use SHT cmd_per_lun here */
 				tw_dev->free_head = TW_Q_START;
 				tw_dev->free_tail = TW_Q_LENGTH - 1;
 				tw_dev->free_wrap = TW_Q_LENGTH - 1;
@@ -1064,7 +1088,7 @@
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
 			dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
-			tw_decode_bits(tw_dev, status_reg_value);
+			tw_decode_bits(tw_dev, status_reg_value, 0);
 			return 1;
 		}
 		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
@@ -1191,7 +1215,7 @@
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
 			dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
-			tw_decode_bits(tw_dev, status_reg_value);
+			tw_decode_bits(tw_dev, status_reg_value, 0);
 			return 1;
 		}
 		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
@@ -1251,51 +1275,52 @@
 	u32 response_que_addr;
 	TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
 	TW_Response_Queue response_que;
-	int error = 0;
-	int do_response_interrupt=0;
-	int do_attention_interrupt=0;
-	int do_host_interrupt=0;
-	int do_command_interrupt=0;
+	int error = 0, retval = 0;
 	unsigned long flags = 0;
 	TW_Command *command_packet;
+
+	dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
+
+	/* See if we are already running on another processor */
 	if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags))
 		return;
+
+	/* Get the host lock for io completions */
 	spin_lock_irqsave(tw_dev->host->host_lock, flags);
 
+	/* See if the interrupt matches this instance */
 	if (tw_dev->tw_pci_dev->irq == irq) {
+
+		/* Make sure io isn't queueing */
 		spin_lock(&tw_dev->tw_lock);
-		dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
 
 		/* Read the registers */
 		status_reg_addr = tw_dev->registers.status_reg_addr;
 		response_que_addr = tw_dev->registers.response_que_addr;
 		status_reg_value = inl(status_reg_addr);
 
+		/* Check if this is our interrupt, otherwise bail */
+		if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+			goto tw_interrupt_bail;
+
+		/* Check controller for errors */
 		if (tw_check_bits(status_reg_value)) {
 			dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
-			tw_decode_bits(tw_dev, status_reg_value);
+			if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
+				tw_clear_all_interrupts(tw_dev);
+				goto tw_interrupt_bail;
+			}
 		}
 
-		/* Check which interrupt */
-		if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
-			do_host_interrupt=1;
-		if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT)
-			do_attention_interrupt=1;
-		if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT)
-			do_command_interrupt=1;
-		if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT)
-			do_response_interrupt=1;
-
 		/* Handle host interrupt */
-		if (do_host_interrupt) {
+		if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
 			dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
 			tw_clear_host_interrupt(tw_dev);
 		}
 
 		/* Handle attention interrupt */
-		if (do_attention_interrupt) {
+		if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
 			dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
-			dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Clearing attention interrupt.\n");
 			tw_clear_attention_interrupt(tw_dev);
 			tw_state_request_start(tw_dev, &request_id);
 			error = tw_aen_read_queue(tw_dev, request_id);
@@ -1307,7 +1332,7 @@
 		}
 
 		/* Handle command interrupt */
-		if (do_command_interrupt) {
+		if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
 			/* Drain as many pending commands as we can */
 			while (tw_dev->pending_request_count > 0) {
 				request_id = tw_dev->pending_queue[tw_dev->pending_head];
@@ -1323,6 +1348,7 @@
 					}
 					tw_dev->pending_request_count--;
 				} else {
+					printk(KERN_WARNING "3w-xxxx: scsi%d: Error posting pending commands.\n", tw_dev->host->host_no);
 					break;
 				}
 			}
@@ -1332,40 +1358,40 @@
 		}
 
 		/* Handle response interrupt */
-		if (do_response_interrupt) {
+		if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
 			/* Drain the response queue from the board */
 			while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+				/* Read response queue register */
 				response_que.value = inl(response_que_addr);
 				request_id = response_que.u.response_id;
 				command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
 				error = 0;
+
+				/* Check for bad response */
 				if (command_packet->status != 0) {
-					/* Bad response */
-					if (tw_dev->srb[request_id] != 0)
-						tw_decode_sense(tw_dev, request_id, 1);
-					error = 3;
+					/* If internal command, don't error, don't fill sense */
+					if (tw_dev->srb[request_id] == 0) {
+						tw_decode_sense(tw_dev, request_id, 0);
+					} else {
+						error = tw_decode_sense(tw_dev, request_id, 1);
+					}
 				}
+
+				/* Check for correct state */
 				if (tw_dev->state[request_id] != TW_S_POSTED) {
 					printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode);
 					error = 1;
 				}
-				if (TW_STATUS_ERRORS(status_reg_value)) {
-					tw_decode_bits(tw_dev, status_reg_value);
-					error = 1;
-				}
+
 				dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
-				/* Check for internal command */
+
+				/* Check for internal command completion */
 				if (tw_dev->srb[request_id] == 0) {
 					dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
-					error = tw_aen_complete(tw_dev, request_id);
-					if (error) {
+					retval = tw_aen_complete(tw_dev, request_id);
+					if (retval) {
 						printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
 					}
-					status_reg_value = inl(status_reg_addr);
-					if (tw_check_bits(status_reg_value)) {
-						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
-						tw_decode_bits(tw_dev, status_reg_value);
-					}
 				} else {
 				switch (tw_dev->srb[request_id]->cmnd[0]) {
 					case READ_10:
@@ -1389,20 +1415,22 @@
 						error = tw_ioctl_complete(tw_dev, request_id);
 						break;
 					default:
-						printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]);
-						tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
-						tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-					}
-					if (error == 1) {
-						/* Tell scsi layer there was an error */
-						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Scsi Error.\n");
-						tw_dev->srb[request_id]->result = (DID_RESET << 16);
+						printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
+						error = 1;
 					}
+
+					/* If no error command was a success */
 					if (error == 0) {
-						/* Tell scsi layer command was a success */
 						tw_dev->srb[request_id]->result = (DID_OK << 16);
 					}
-					if (error != 2) {
+
+					/* If error, command failed */
+					if (error == 1) {
+						tw_dev->srb[request_id]->result = (DID_RESET << 16);
+					}
+
+					/* Now complete the io */
+					if ((error != TW_ISR_DONT_COMPLETE)) {
 						tw_dev->state[request_id] = TW_S_COMPLETED;
 						tw_state_request_finish(tw_dev, request_id);
 						tw_dev->posted_request_count--;
@@ -1410,16 +1438,24 @@
 
 						tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
 					}
-					status_reg_value = inl(status_reg_addr);
-					if (tw_check_bits(status_reg_value)) {
-						dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
-						tw_decode_bits(tw_dev, status_reg_value);
+				}
+				
+				/* Check for valid status after each drain */
+				status_reg_value = inl(status_reg_addr);
+				if (tw_check_bits(status_reg_value)) {
+					dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+					if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
+						tw_clear_all_interrupts(tw_dev);
+						goto tw_interrupt_bail;
 					}
 				}
 			}
 		}
+tw_interrupt_bail:
 		spin_unlock(&tw_dev->tw_lock);
-	}
+	} else
+		dprintk(KERN_WARNING "3w-xxxx: tw_interrupt() called for wrong instance.\n");
+
 	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
 	clear_bit(TW_IN_INTR, &tw_dev->flags);
 } /* End tw_interrupt() */
@@ -1782,7 +1818,7 @@
 			break;
 		case TW_CMD_PACKET_WITH_DATA:
 			dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n");
-			return 2; /* Special case for isr to not complete io */
+			return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */
 		default:
 			memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
 			param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
@@ -1852,7 +1888,7 @@
 
 	if (tw_check_bits(status_reg_value)) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
-		tw_decode_bits(tw_dev, status_reg_value);
+		tw_decode_bits(tw_dev, status_reg_value, 0);
 	}
 		
 	while ((status_reg_value & flag) != flag) {
@@ -1860,7 +1896,7 @@
 
 		if (tw_check_bits(status_reg_value)) {
 			dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
-			tw_decode_bits(tw_dev, status_reg_value);
+			tw_decode_bits(tw_dev, status_reg_value, 0);
 		}
 
 		do_gettimeofday(&timeout);
@@ -1887,7 +1923,7 @@
 
 	if (tw_check_bits(status_reg_value)) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
-		tw_decode_bits(tw_dev, status_reg_value);
+		tw_decode_bits(tw_dev, status_reg_value, 1);
 	}
 
 	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
@@ -1941,7 +1977,6 @@
 		    (tw_dev->state[i] != TW_S_COMPLETED)) {
 			srb = tw_dev->srb[i];
 			if (srb != NULL) {
-				srb = tw_dev->srb[i];
 				srb->result = (DID_RESET << 16);
 				tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
 				tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
@@ -1960,6 +1995,7 @@
 	tw_dev->pending_request_count = 0;
 	tw_dev->pending_head = TW_Q_START;
 	tw_dev->pending_tail = TW_Q_START;
+	tw_dev->reset_print = 0;
 
 	return 0;
 } /* End tw_reset_device_extension() */
@@ -1991,14 +2027,6 @@
 			continue;
 		}
 
-		/* Empty the response queue again */
-		error = tw_empty_response_que(tw_dev);
-		if (error) {
-			printk(KERN_WARNING "3w-xxxx: scsi%d: Couldn't empty response queue, retrying.\n", tw_dev->host->host_no);
-			tries++;
-			continue;
-		}
-
 		/* Now the controller is in a good state */
 		break;
 	}
@@ -2086,11 +2114,6 @@
 		return (FAILED);
 	}
 
-	/* We have to let AEN requests through before the reset */
-	spin_unlock_irq(tw_dev->host->host_lock);
-	mdelay(TW_AEN_WAIT_TIME);
-	spin_lock_irq(tw_dev->host->host_lock);
-
 	spin_lock(&tw_dev->tw_lock);
 	tw_dev->num_aborts++;
 
@@ -2117,18 +2140,26 @@
 				spin_unlock(&tw_dev->tw_lock);
 				return (SUCCESS);
 			}
+			if (tw_dev->state[i] == TW_S_POSTED) {
+				/* If the command has already been posted, we have to reset the card */
+				printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt);
+				/* We have to let AEN requests through before the reset */
+				spin_unlock(&tw_dev->tw_lock);
+				spin_unlock_irq(tw_dev->host->host_lock);
+				mdelay(TW_AEN_WAIT_TIME);
+				spin_lock_irq(tw_dev->host->host_lock);
+				spin_lock(&tw_dev->tw_lock);
+
+				if (tw_reset_device_extension(tw_dev)) {
+					dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
+					spin_unlock(&tw_dev->tw_lock);
+					return (FAILED);
+				}
+			}
 		}
 	}
 
-	/* If the command has already been posted, we have to reset the card */
-	printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt);
-	if (tw_reset_device_extension(tw_dev)) {
-		dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
-		spin_unlock(&tw_dev->tw_lock);
-		return (FAILED);
-	}
 	spin_unlock(&tw_dev->tw_lock);
-
 	return (SUCCESS);
 } /* End tw_scsi_eh_abort() */
 
@@ -2593,7 +2624,7 @@
 	}
 
 	command_packet->byte0.sgl_offset = 3;
-	command_packet->size = 5;
+	command_packet->size = 3;
 	command_packet->request_id = request_id;
 	command_packet->byte3.unit = srb->target;
 	command_packet->byte3.host_id = 0;
@@ -2628,6 +2659,7 @@
 		buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
 		command_packet->byte8.io.sgl[0].address = buffaddr;
 		command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
+		command_packet->size+=2;
 	}
 
 	/* Do this if we have multiple sg list entries */
@@ -2638,8 +2670,6 @@
 			command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
 			command_packet->size+=2;
 		}
-		if (tw_dev->srb[request_id]->use_sg >= 1)
-			command_packet->size-=2;
 	}
 
 	/* Update SG statistics */
@@ -2754,7 +2784,7 @@
 		status_reg_value = inl(status_reg_addr);
 		if (tw_check_bits(status_reg_value)) {
 			dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
-			tw_decode_bits(tw_dev, status_reg_value);
+			tw_decode_bits(tw_dev, status_reg_value, 1);
 			return 1;
 		}
 		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
diff -Nru a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
--- a/drivers/scsi/3w-xxxx.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/scsi/3w-xxxx.h	Sun Apr 14 12:16:56 2002
@@ -92,10 +92,11 @@
 	"Verify failed: Port #",                // 0x02A
 	"Verify complete: Unit #",              // 0x02B
 	"Overwrote bad sector during rebuild: Port #",  //0x2C
-	"Encountered bad sector during rebuild: Port #" //0x2D
+	"Encountered bad sector during rebuild: Port #", //0x2D
+	"Replacement drive is too small: Port #" //0x2E
 };
 
-#define TW_AEN_STRING_MAX                      0x02E
+#define TW_AEN_STRING_MAX                      0x02F
 
 /*
    Sense key lookup table
@@ -134,7 +135,9 @@
 #define TW_CONTROL_DISABLE_INTERRUPTS	       0x00000040
 #define TW_CONTROL_ISSUE_HOST_INTERRUPT	       0x00000020
 #define TW_CONTROL_CLEAR_PARITY_ERROR          0x00800000
+#define TW_CONTROL_CLEAR_QUEUE_ERROR           0x00400000
 #define TW_CONTROL_CLEAR_PCI_ABORT             0x00100000
+#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR      0x00000008
 
 /* Status register bit definitions */
 #define TW_STATUS_MAJOR_VERSION_MASK	       0xF0000000
@@ -154,7 +157,9 @@
 #define TW_STATUS_ALL_INTERRUPTS	       0x000F0000
 #define TW_STATUS_CLEARABLE_BITS	       0x00D00000
 #define TW_STATUS_EXPECTED_BITS		       0x00002000
-#define TW_STATUS_UNEXPECTED_BITS	       0x00F80000
+#define TW_STATUS_UNEXPECTED_BITS	       0x00F00008
+#define TW_STATUS_SBUF_WRITE_ERROR             0x00000008
+#define TW_STATUS_VALID_INTERRUPT              0x00DF0008
 
 /* RESPONSE QUEUE BIT DEFINITIONS */
 #define TW_RESPONSE_ID_MASK		       0x00000FF0
@@ -214,7 +219,7 @@
 #define TW_MAX_PCI_BUSES		      255
 #define TW_MAX_RESET_TRIES		      3
 #define TW_UNIT_INFORMATION_TABLE_BASE	      0x300
-#define TW_MAX_CMDS_PER_LUN		      (TW_Q_LENGTH-2)/TW_MAX_UNITS
+#define TW_MAX_CMDS_PER_LUN		      255
 #define TW_BLOCK_SIZE			      0x200 /* 512-byte blocks */
 #define TW_IOCTL                              0x80
 #define TW_MAX_AEN_TRIES                      100
@@ -223,6 +228,8 @@
 #define TW_MAX_SECTORS                        256
 #define TW_AEN_WAIT_TIME                      1000
 #define TW_IOCTL_WAIT_TIME                    (1 * HZ) /* 1 second */
+#define TW_ISR_DONT_COMPLETE                  2
+#define TW_ISR_DONT_RESULT                    3
 
 /* Macros */
 #define TW_STATUS_ERRORS(x) \
@@ -235,7 +242,7 @@
 #ifdef TW_DEBUG
 #define dprintk(msg...) printk(msg)
 #else
-#define dprintk(msg...) do { } while(0);
+#define dprintk(msg...) do { } while(0)
 #endif
 
 /* Scatter Gather List Entry */
@@ -402,8 +409,9 @@
 	unsigned short		aen_queue[TW_Q_LENGTH];
 	unsigned char		aen_head;
 	unsigned char		aen_tail;
-	long			flags; /* long req'd for set_bit --RR */
+	volatile long		flags; /* long req'd for set_bit --RR */
 	char			*ioctl_data[TW_Q_LENGTH];
+	int			reset_print;
 } TW_Device_Extension;
 
 /* Function prototypes */
@@ -413,12 +421,13 @@
 int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which);
 int tw_check_bits(u32 status_reg_value);
 int tw_check_errors(TW_Device_Extension *tw_dev);
+void tw_clear_all_interrupts(TW_Device_Extension *tw_dev);
 void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev);
 void tw_clear_host_interrupt(TW_Device_Extension *tw_dev);
-void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value);
-void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense);
+int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host);
+int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense);
 void tw_disable_interrupts(TW_Device_Extension *tw_dev);
-int tw_empty_response_que(TW_Device_Extension *tw_dev);
+void tw_empty_response_que(TW_Device_Extension *tw_dev);
 void tw_enable_interrupts(TW_Device_Extension *tw_dev);
 void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev);
 int tw_findcards(Scsi_Host_Template *tw_host);
@@ -478,7 +487,7 @@
 	reset : NULL,					\
 	slave_attach : NULL,				\
 	bios_param : tw_scsi_biosparam,			\
-	can_queue : TW_Q_LENGTH,			\
+	can_queue : TW_Q_LENGTH-1,			\
 	this_id: -1,					\
 	sg_tablesize : TW_MAX_SGL_LENGTH,		\
 	cmd_per_lun: TW_MAX_CMDS_PER_LUN,		\
diff -Nru a/drivers/scsi/53c7,8xx.c b/drivers/scsi/53c7,8xx.c
--- a/drivers/scsi/53c7,8xx.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/scsi/53c7,8xx.c	Sun Apr 14 12:16:55 2002
@@ -1869,7 +1869,7 @@
 	 */
 
 	timeout = jiffies + 5 * HZ / 10;
-	while ((hostdata->test_completed == -1) && jiffies < timeout) {
+	while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) {
 		barrier();
 		cpu_relax();
 	}
@@ -1955,7 +1955,7 @@
 	    restore_flags(flags);
 
 	    timeout = jiffies + 5 * HZ;	/* arbitrary */
-	    while ((hostdata->test_completed == -1) && jiffies < timeout) {
+	    while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) {
 	    	barrier();
 		cpu_relax();
 	    }
diff -Nru a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
--- a/drivers/scsi/53c7xx.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/scsi/53c7xx.c	Sun Apr 14 12:16:59 2002
@@ -1627,7 +1627,7 @@
 	 */
 
 	timeout = jiffies + 5 * HZ / 10;
-	while ((hostdata->test_completed == -1) && jiffies < timeout)
+	while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
 		barrier();
 
 	failed = 1;
@@ -1713,7 +1713,7 @@
 	    restore_flags(flags);
 
 	    timeout = jiffies + 5 * HZ;	/* arbitrary */
-	    while ((hostdata->test_completed == -1) && jiffies < timeout)
+	    while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
 	    	barrier();
 
 	    NCR53c7x0_write32 (DSA_REG, 0);
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/scsi/NCR53C9x.c	Sun Apr 14 12:16:56 2002
@@ -3615,3 +3615,5 @@
 	esps_running = esps_in_use;
 }
 #endif
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
--- a/drivers/scsi/a2091.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/scsi/a2091.c	Sun Apr 14 12:16:54 2002
@@ -248,3 +248,5 @@
 #endif
 	return 1;
 }
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_linux.c b/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- a/drivers/scsi/aic7xxx/aic7xxx_linux.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/scsi/aic7xxx/aic7xxx_linux.c	Sun Apr 14 12:16:58 2002
@@ -445,7 +445,7 @@
 						      struct ahc_linux_device*);
 static void ahc_linux_run_device_queue(struct ahc_softc*,
 				       struct ahc_linux_device*);
-static void ahc_linux_setup_tag_info(char *p, char *end);
+static void ahc_linux_setup_tag_info(char *p, char *end, char *s);
 static int ahc_linux_next_unit(void);
 static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf);
 
@@ -906,7 +906,7 @@
 }
 
 static void
-ahc_linux_setup_tag_info(char *p, char *end)
+ahc_linux_setup_tag_info(char *p, char *end, char *s)
 {
 	char	*base;
 	char	*tok;
@@ -986,7 +986,7 @@
 		}
 	}
 	while ((p != base) && (p != NULL))
-		p = strtok(NULL, ",.");
+		p = strsep(&s, ",.");
 }
 
 /*
@@ -1018,7 +1018,8 @@
 
 	end = strchr(s, '\0');
 
-	for (p = strtok(s, ",."); p; p = strtok(NULL, ",.")) {
+	while ((p = strsep(&s, ",.")) != NULL) {
+		if (!*p) continue;
 		for (i = 0; i < NUM_ELEMENTS(options); i++) {
 			n = strlen(options[i].name);
 
@@ -1026,7 +1027,7 @@
 				continue;
 
 			if (strncmp(p, "tag_info", n) == 0) {
-				ahc_linux_setup_tag_info(p + n, end);
+				ahc_linux_setup_tag_info(p + n, end, s);
 			} else if (p[n] == ':') {
 				*(options[i].flag) =
 				    simple_strtoul(p + n + 1, NULL, 0);
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/scsi/aic7xxx_old.c	Sun Apr 14 12:16:58 2002
@@ -1443,7 +1443,7 @@
 
   end = strchr(s, '\0');
 
-  for (p = strtok(s, ",."); p; p = strtok(NULL, ",."))
+  while ((p = strsep(&s, ",.")) != NULL)
   {
     for (i = 0; i < NUMBER(options); i++)
     {
@@ -1525,7 +1525,7 @@
               }
             }
             while((p != base) && (p != NULL))
-              p = strtok(NULL, ",.");
+              p = strsep(&s, ",.");
           }
         }
         else if (p[n] == ':')
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/scsi/cpqfcTSinit.c	Sun Apr 14 12:16:55 2002
@@ -261,10 +261,22 @@
 /* "Entry" point to discover if any supported PCI 
    bus adapter can be found
 */
-// We're supporting:
-// Compaq 64-bit, 66MHz HBA with Tachyon TS
-// Agilent XL2 
-#define HBA_TYPES 2
+/* We're supporting:
+ * Compaq 64-bit, 66MHz HBA with Tachyon TS
+ * Agilent XL2 
+ * HP Tachyon
+ */
+#define HBA_TYPES 3
+
+#ifndef PCI_DEVICE_ID_COMPAQ_
+#define PCI_DEVICE_ID_COMPAQ_TACHYON	0xa0fc
+#endif
+
+static struct SupportedPCIcards cpqfc_boards[] __initdata = {
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TACHYON},
+	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_TACHLITE},
+	{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_TACHYON},
+};
 
 
 int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
@@ -274,35 +286,28 @@
   struct Scsi_Host *HostAdapter = NULL;
   CPQFCHBA *cpqfcHBAdata = NULL; 
   struct timer_list *cpqfcTStimer = NULL;
-  SupportedPCIcards PCIids[HBA_TYPES];
   int i;
-  
+
   ENTER("cpqfcTS_detect");
-  
+
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
   ScsiHostTemplate->proc_dir = &proc_scsi_cpqfcTS;
 #else
   ScsiHostTemplate->proc_name = "cpqfcTS";
 #endif
-  
+
   if( pci_present() == 0) // no PCI busses?
   {
     printk( "  no PCI bus?@#!\n");
     return NumberOfAdapters;
   }
 
-  // what HBA adapters are we supporting?
-  PCIids[0].vendor_id = PCI_VENDOR_ID_COMPAQ;
-  PCIids[0].device_id = CPQ_DEVICE_ID;
-  PCIids[1].vendor_id = PCI_VENDOR_ID_HP; // i.e. 103Ch (Agilent == HP for now)
-  PCIids[1].device_id = AGILENT_XL2_ID;   // i.e. 1029h
-
   for( i=0; i < HBA_TYPES; i++)
   {
     // look for all HBAs of each type
 
-    while( (PciDev =
-      pci_find_device( PCIids[i].vendor_id, PCIids[i].device_id, PciDev) ))
+    while((PciDev = pci_find_device(cpqfc_boards[i].vendor_id,
+				    cpqfc_boards[i].device_id, PciDev)))
     {
 
       if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
diff -Nru a/drivers/scsi/cpqfcTSstructs.h b/drivers/scsi/cpqfcTSstructs.h
--- a/drivers/scsi/cpqfcTSstructs.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/scsi/cpqfcTSstructs.h	Sun Apr 14 12:16:58 2002
@@ -95,14 +95,11 @@
 
 #define DEV_NAME "cpqfcTS"
 
-#define CPQ_DEVICE_ID     0xA0FC
-#define AGILENT_XL2_ID    0x1029
-
-typedef struct
+struct SupportedPCIcards
 {
   __u16 vendor_id;
   __u16 device_id;
-} SupportedPCIcards;
+};
 			 
 // nn:nn denotes bit field
                             // TachyonHeader struct def.
diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c
--- a/drivers/scsi/eata.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/scsi/eata.c	Sun Apr 14 12:16:57 2002
@@ -311,7 +311,7 @@
  *  include in the list of i/o ports to be probed all the PCI SCSI controllers.
  *
  *  Due to a DPT BIOS "feature", it might not be possible to force an EISA
- *  address on more then a single DPT PCI board, so in this case you have to
+ *  address on more than a single DPT PCI board, so in this case you have to
  *  let the PCI BIOS assign the addresses.
  *
  *  The sequence of detection probes is:
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/scsi/fdomain.c	Sun Apr 14 12:16:56 2002
@@ -78,7 +78,7 @@
  Please note that the drive ordering that Future Domain implemented in BIOS
  versions 3.4 and 3.5 is the opposite of the order (currently) used by the
  rest of the SCSI industry.  If you have BIOS version 3.4 or 3.5, and have
- more then one drive, then the drive ordering will be the reverse of that
+ more than one drive, then the drive ordering will be the reverse of that
  which you see under DOS.  For example, under DOS SCSI ID 0 will be D: and
  SCSI ID 1 will be C: (the boot device).  Under Linux, SCSI ID 0 will be
  /dev/sda and SCSI ID 1 will be /dev/sdb.  The Linux ordering is consistent
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/scsi/ide-scsi.c	Sun Apr 14 12:16:55 2002
@@ -331,7 +331,7 @@
 		printk ("ide-scsi: %s: DMA complete\n", drive->name);
 #endif /* IDESCSI_DEBUG_LOG */
 		pc->actually_transferred=pc->request_transfer;
-		(void) (HWIF(drive)->dmaproc(ide_dma_end, drive));
+		(void) drive->channel->dmaproc(ide_dma_end, drive);
 	}
 
 	status = GET_STAT();						/* Clear the interrupt */
@@ -434,9 +434,9 @@
 	bcount = min(pc->request_transfer, 63 * 1024);		/* Request to transfer the entire buffer at once */
 
 	if (drive->using_dma && rq->bio)
-		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
+		dma_ok = !drive->channel->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 
-	SELECT_DRIVE(HWIF(drive), drive);
+	SELECT_DRIVE(drive->channel, drive);
 	if (IDE_CONTROL_REG)
 		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok,IDE_FEATURE_REG);
@@ -444,8 +444,8 @@
 	OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG);
 
 	if (dma_ok) {
-		set_bit (PC_DMA_IN_PROGRESS, &pc->flags);
-		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
+		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+		(void) drive->channel->dmaproc(ide_dma_begin, drive);
 	}
 	if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
 		ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL);
@@ -508,7 +508,7 @@
  */
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id)
 {
-	ata_ops(drive)->busy++;
+	MOD_INC_USE_COUNT;
 
 	idescsi_drives[id] = drive;
 	drive->driver_data = scsi;
@@ -629,8 +629,9 @@
 
 	for (id = 0; id < MAX_HWIFS * MAX_DRIVES; id++) {
 		drive = idescsi_drives[id];
-		if (drive)
-			ata_ops(drive)->busy--;
+		if (drive) {
+			MOD_DEC_USE_COUNT;
+		}
 	}
 	return 0;
 }
diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
--- a/drivers/scsi/ppa.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/scsi/ppa.c	Sun Apr 14 12:16:55 2002
@@ -702,7 +702,7 @@
 	 * change things for "normal" hardware since generally 
 	 * the 6th bit is always high.
 	 * This makes the CPU load higher on some hardware 
-	 * but otherwise we can not get more then 50K/secs 
+	 * but otherwise we can not get more than 50K/secs 
 	 * on this problem hardware.
 	 */
 	if ((r & 0xc0) != 0xc0) {
diff -Nru a/drivers/scsi/ql12160_fw.h b/drivers/scsi/ql12160_fw.h
--- a/drivers/scsi/ql12160_fw.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/scsi/ql12160_fw.h	Sun Apr 14 12:16:58 2002
@@ -1,1704 +1,1787 @@
-/*
- ************************************************************************
- *									*
- * 	           --- ISP12160 Initiator Firmware ---               	*
- *			      32 LUN Support				*
- *									*
- ************************************************************************
- *									*
- * Copyright (C) 1999,2000 Qlogic, Corporation
- * All rights reserved.
+/*****************************************************************************
+ *                  QLOGIC LINUX SOFTWARE
  *
- * Redistribution and use in source and binary forms are permitted provided
- * that the following conditions are met:
- * 1. Redistribution of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
+ * QLogic ISP12160 device driver for Linux 2.2.x and 2.4.x
+ * Copyright (C) 2002 Qlogic Corporation (www.qlogic.com)
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *									*
- ************************************************************************
- */
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ *****************************************************************************/
 
+/************************************************************************
+ * 	           --- ISP12160A Initiator Firmware ---                 *
+ *			      32 LUN Support                            *
+ ************************************************************************/
 
 /*
- *	Firmware Version 10.01.19 (12:38 Oct 12, 1999)
+ *	Firmware Version 10.04.32 (12:03 May 09, 2001)
  */
 
 #ifdef UNIQUE_FW_NAME
-unsigned short fw12160i_version = 10*1024+1;
+unsigned short fw12160i_version = 10*1024+4;
 #else
-unsigned short risc_code_version = 10*1024+1;
+unsigned short risc_code_version = 10*1024+4;
 #endif
 
 #ifdef UNIQUE_FW_NAME
-unsigned char fw12160i_version_str[] = {10,1,19};
+unsigned char fw12160i_version_str[] = {10,4,32};
 #else
-unsigned char firmware_version[] = {10,1,19};
+unsigned char firmware_version[] = {10,4,32};
 #endif
 
 #ifdef UNIQUE_FW_NAME
-#define fw12160i_VERSION_STRING "10.1.19"
+#define fw12160i_VERSION_STRING "10.04.32"
 #else
-#define FW_VERSION_STRING "10.1.19"
+#define FW_VERSION_STRING "10.04.32"
 #endif
 
 #ifdef UNIQUE_FW_NAME
-unsigned short fw12160i_addr01 = 0x1000 ;
+unsigned short fw12160i_addr01 = 0x1000;
 #else
-unsigned short risc_code_addr01 = 0x1000 ;
+unsigned short risc_code_addr01 = 0x1000;
 #endif
 
 #ifdef UNIQUE_FW_NAME
-unsigned short fw12160i_code01[] = { 
+unsigned short fw12160i_code01[] = {
 #else
-unsigned short risc_code01[] = { 
+unsigned short risc_code01[] = {
 #endif
-	0x0804, 0x1041, 0x0000, 0x32f8, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x0804, 0x1041, 0x0000, 0x35e6, 0x0000, 0x2043, 0x4f50, 0x5952,
 	0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
 	0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
 	0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
 	0x3132, 0x3136, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
-	0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3031, 0x2020, 0x2043,
+	0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3034, 0x2020, 0x2043,
 	0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
 	0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
-	0x2400, 0x20c9, 0x8cff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
+	0x2400, 0x20c9, 0x8fff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
 	0x01ff, 0x2004, 0xd0fc, 0x1120, 0x2071, 0x0100, 0x70a0, 0x70a2,
-	0x20c1, 0x0020, 0x2089, 0x1223, 0x2071, 0x0010, 0x70c3, 0x0004,
+	0x20c1, 0x0020, 0x2089, 0x1221, 0x2071, 0x0010, 0x70c3, 0x0004,
 	0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x000a,
 	0x2001, 0x04fd, 0x2004, 0x70d6, 0x2009, 0xfeff, 0x2130, 0x2128,
-	0xa1a2, 0x4300, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
-	0xa192, 0x8d00, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1d83,
-	0x2218, 0x2079, 0x4300, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+	0xa1a2, 0x4600, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+	0xa192, 0x9000, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1de8,
+	0x2218, 0x2079, 0x4600, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
 	0x0040, 0x42a4, 0x8109, 0x1dd8, 0x2009, 0xff00, 0x3400, 0xa102,
 	0x0218, 0x0110, 0x20a8, 0x42a4, 0x781b, 0x0064, 0x7814, 0xc0cd,
-	0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4340, 0x080c,
-	0x42d8, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4380,
-	0x2071, 0x0100, 0x080c, 0x42d8, 0x7814, 0xc0d4, 0x7816, 0x00de,
+	0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4640, 0x080c,
+	0x459a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4680,
+	0x2071, 0x0100, 0x080c, 0x459a, 0x7814, 0xc0d4, 0x7816, 0x00de,
 	0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
 	0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
-	0x2009, 0x0002, 0x2069, 0x4340, 0x681b, 0x0003, 0x6823, 0x0007,
-	0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0000,
-	0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, 0x8109, 0x0500,
-	0x68d3, 0x000a, 0x68c3, 0x43c0, 0x2079, 0x4300, 0x68d7, 0x762d,
-	0x68c7, 0x48c0, 0x68cb, 0x47c0, 0x68cf, 0x88c0, 0x68ab, 0x8b44,
-	0x68af, 0x8b49, 0x68b3, 0x8b44, 0x68b7, 0x8b44, 0x68a7, 0x0001,
-	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4380, 0x0860,
-	0x68d3, 0x000a, 0x68c3, 0x45c0, 0x68d7, 0x7839, 0x68c7, 0x68c0,
-	0x68cb, 0x4840, 0x68cf, 0x89d0, 0x68ab, 0x8b49, 0x68af, 0x8b4e,
-	0x68b3, 0x8b49, 0x68b7, 0x8b49, 0x68a7, 0x0001, 0x00e6, 0x2069,
-	0x47c0, 0x2071, 0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021,
-	0x0009, 0x1120, 0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1cf3,
-	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4840, 0x2071,
-	0x0100, 0x70ec, 0xd0e4, 0x2019, 0x1c09, 0x2021, 0x0009, 0x1120,
-	0x2019, 0x1c0c, 0x2021, 0x000c, 0x080c, 0x1cf3, 0x00ee, 0x2011,
-	0x0002, 0x2069, 0x48c0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837,
-	0x0000, 0x680b, 0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817,
-	0x0100, 0x681f, 0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002,
-	0xade8, 0x0010, 0x1f04, 0x1137, 0x8109, 0x1d38, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x1128, 0x8211, 0x0118, 0x2069, 0x68c0, 0x08d8,
-	0x080c, 0x2254, 0x080c, 0x3e39, 0x080c, 0x1b0f, 0x080c, 0x42a0,
-	0x2091, 0x2200, 0x2079, 0x4300, 0x2071, 0x0050, 0x2091, 0x2400,
-	0x2079, 0x4300, 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200,
-	0x2071, 0x4340, 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4380,
-	0x2091, 0x2000, 0x2079, 0x4300, 0x2071, 0x0010, 0x3200, 0xa085,
-	0x303d, 0x2090, 0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118e,
-	0x70c0, 0xa086, 0x0002, 0x1110, 0x080c, 0x13a3, 0x2039, 0x0000,
-	0x080c, 0x129c, 0x78ac, 0xa005, 0x1180, 0x0e04, 0x119c, 0x786c,
-	0xa065, 0x0110, 0x080c, 0x1ffe, 0x080c, 0x1da4, 0x0e04, 0x11b1,
-	0x786c, 0xa065, 0x0110, 0x080c, 0x1ffe, 0x0e04, 0x11b1, 0x2009,
-	0x4347, 0x2011, 0x4387, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c,
-	0x1c21, 0x2071, 0x4340, 0x70a4, 0xa005, 0x01e8, 0x7450, 0xa485,
-	0x0000, 0x01c8, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, 0xa28c,
-	0x303d, 0x2190, 0x080c, 0x260d, 0x2091, 0x8000, 0x2091, 0x303d,
-	0x0e04, 0x11d3, 0x2079, 0x4300, 0x786c, 0xa065, 0x0120, 0x2071,
-	0x0010, 0x080c, 0x1ffe, 0x1d04, 0x11db, 0x2079, 0x4300, 0x2071,
-	0x0010, 0x080c, 0x40ed, 0x2071, 0x4380, 0x70a4, 0xa005, 0x0188,
-	0x7050, 0xa025, 0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d4,
-	0xa28c, 0x303d, 0x2190, 0x080c, 0x260d, 0x2091, 0x8000, 0x2091,
-	0x303d, 0x2079, 0x4300, 0x2071, 0x0010, 0x0e04, 0x11fc, 0x786c,
-	0xa065, 0x0110, 0x080c, 0x1ffe, 0x1d04, 0x1190, 0x080c, 0x40ed,
-	0x0804, 0x1190, 0x3c00, 0xa084, 0x0007, 0x0002, 0x120e, 0x120e,
-	0x1210, 0x1210, 0x1215, 0x1215, 0x121a, 0x121a, 0x080c, 0x243b,
-	0x2091, 0x2400, 0x080c, 0x3e9c, 0x0005, 0x2091, 0x2200, 0x080c,
-	0x3e9c, 0x0005, 0x2091, 0x2200, 0x080c, 0x3e9c, 0x2091, 0x2400,
-	0x080c, 0x3e9c, 0x0005, 0x1243, 0x1243, 0x1244, 0x1244, 0x124f,
-	0x124f, 0x124f, 0x124f, 0x1258, 0x1258, 0x1263, 0x1263, 0x124f,
-	0x124f, 0x124f, 0x124f, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272,
-	0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272, 0x1272,
-	0x1272, 0x1272, 0x1272, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091,
-	0x2800, 0x080c, 0x2458, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006,
-	0x0106, 0x0126, 0x080c, 0x1202, 0x012e, 0x010e, 0x000e, 0x000d,
-	0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2458, 0x012e,
-	0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600,
-	0x080c, 0x2458, 0x2091, 0x2800, 0x080c, 0x2458, 0x012e, 0x010e,
-	0x000e, 0x000d, 0x0006, 0x0106, 0x0126, 0x00e6, 0x00f6, 0x2079,
-	0x4300, 0x2071, 0x0200, 0x2069, 0x4340, 0x3d00, 0xd08c, 0x1120,
-	0x2069, 0x4380, 0x2071, 0x0100, 0x080c, 0x42d8, 0x00fe, 0x00ee,
-	0x012e, 0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007,
-	0x0002, 0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897,
-	0x70c3, 0x4002, 0x0804, 0x13a6, 0x0e04, 0x1308, 0x2061, 0x0000,
-	0x6018, 0xd084, 0x1904, 0x1308, 0x7828, 0xa005, 0x1120, 0x0004,
-	0x1309, 0x0804, 0x1308, 0xd0fc, 0x0148, 0x0006, 0x080c, 0x1aa9,
-	0x000e, 0x0168, 0x2001, 0x4007, 0x0804, 0x13a5, 0x0006, 0x080c,
-	0x1a9b, 0x000e, 0x0120, 0x2001, 0x4007, 0x0804, 0x13a5, 0x7910,
-	0xd0fc, 0x1128, 0x2061, 0x4340, 0xc19c, 0xc7fc, 0x0020, 0x2061,
-	0x4380, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x15d0, 0x7912, 0x6083,
-	0x0000, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x1120, 0x00c6, 0x080c,
-	0x18c9, 0x00ce, 0x782b, 0x0000, 0x607c, 0xa065, 0x0190, 0x00c6,
-	0x609c, 0x080c, 0x1b76, 0x00ce, 0x609f, 0x0000, 0x080c, 0x19db,
-	0x2009, 0x0018, 0x6087, 0x0103, 0x080c, 0x1ab7, 0x1198, 0x080c,
-	0x1b02, 0x7810, 0xd09c, 0x1118, 0x2061, 0x4340, 0x0020, 0x2061,
-	0x4380, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0c4, 0x0130,
-	0xc0c4, 0x60d6, 0x2001, 0x4005, 0x0804, 0x13a5, 0x0804, 0x13a3,
-	0x0005, 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0,
-	0xa08a, 0x0040, 0x1a04, 0x1355, 0x0002, 0x13a3, 0x13f1, 0x13bf,
-	0x1425, 0x1459, 0x1459, 0x13b7, 0x19f3, 0x1463, 0x13b1, 0x13c3,
-	0x13c4, 0x13c5, 0x13c6, 0x19f7, 0x13b1, 0x1470, 0x14c5, 0x18e4,
-	0x19ed, 0x13c7, 0x1795, 0x17cb, 0x17fa, 0x183d, 0x1752, 0x175f,
-	0x1772, 0x1784, 0x159a, 0x13b1, 0x14f7, 0x1502, 0x1510, 0x151e,
-	0x1535, 0x1543, 0x1546, 0x1554, 0x1562, 0x156c, 0x1580, 0x158c,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x15a7, 0x15b8, 0x15d2, 0x1606,
-	0x162f, 0x1641, 0x1644, 0x1677, 0x16aa, 0x16bc, 0x1720, 0x1730,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x1742, 0x2100, 0xa08a, 0x0040,
-	0x1a04, 0x13b1, 0x0002, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
-	0x1a19, 0x1a1f, 0x13b1, 0x13b1, 0x13b1, 0x1a23, 0x1a63, 0x13b1,
-	0x13b1, 0x13b1, 0x13b1, 0x13ec, 0x1454, 0x146b, 0x14c0, 0x18df,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x1a67, 0x1a0b, 0x1a15, 0x13b1,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
-	0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1, 0x13b1,
-	0x13b1, 0x13b1, 0x13b1, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0028,
-	0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0e04, 0x13a6,
-	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
-	0x0005, 0x70c3, 0x4001, 0x0c90, 0x70c3, 0x4006, 0x0c78, 0x2099,
-	0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0c20, 0x70c4,
-	0x70c3, 0x0004, 0x0807, 0x08f8, 0x08f0, 0x08e8, 0x08e0, 0x2091,
-	0x8000, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf,
-	0x2020, 0x70d3, 0x000a, 0x2001, 0x0001, 0x70d6, 0x2079, 0x0000,
-	0x781b, 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a,
-	0x2051, 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000,
-	0x2091, 0x4080, 0x0804, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de,
-	0x0018, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4,
-	0x20a0, 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a,
-	0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0904, 0x13a3,
-	0xa182, 0x0040, 0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012,
-	0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0x7007,
-	0x0002, 0xa084, 0x01e0, 0x0120, 0x70c3, 0x4002, 0x0804, 0x13a6,
-	0x24a8, 0x53a5, 0x0c10, 0x0804, 0x13a3, 0x2029, 0x0000, 0x2520,
-	0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003,
-	0x0000, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021,
-	0x0040, 0x7007, 0x0006, 0x81ff, 0x0904, 0x13a3, 0xa182, 0x0040,
-	0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6,
-	0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48,
-	0x70c3, 0x4002, 0x0804, 0x13a6, 0x75d8, 0x74dc, 0x75da, 0x74de,
-	0x0878, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a,
-	0x72ca, 0x0804, 0x13a2, 0x70c7, 0x000a, 0x70cb, 0x0001, 0x70cf,
-	0x0013, 0x0804, 0x13a3, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018,
-	0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
-	0x72ca, 0x73ce, 0x74d2, 0xa005, 0x05f0, 0xa40a, 0x0110, 0x1a04,
-	0x13a5, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc085,
-	0x78ae, 0x2001, 0x4005, 0x0804, 0x13a5, 0x7b7e, 0x7a7a, 0x7e86,
-	0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0170, 0x8407, 0x8004, 0x8004,
-	0x810c, 0x810c, 0x810f, 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000,
-	0xa581, 0x0000, 0x0050, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291,
-	0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622,
-	0x7026, 0xa605, 0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084,
-	0xfffc, 0x78ae, 0x0018, 0x78ac, 0xc085, 0x78ae, 0x0804, 0x13a3,
-	0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029, 0x0000, 0x2530,
-	0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
-	0xa005, 0x0500, 0xa40a, 0x0110, 0x1a04, 0x13a5, 0x8001, 0x7892,
-	0xa084, 0xfc00, 0x0138, 0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005,
-	0x0804, 0x13a5, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505,
-	0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff,
-	0x78ae, 0x0018, 0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13a3, 0x2009,
-	0x0000, 0x786c, 0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4,
-	0x0804, 0x13a1, 0x2009, 0x4348, 0x210c, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1904, 0x13a2, 0x2011, 0x4388, 0x2214, 0x0804, 0x13a1,
-	0x2009, 0x4349, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
-	0x13a2, 0x2011, 0x4389, 0x2214, 0x0804, 0x13a1, 0x2061, 0x4340,
-	0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1148, 0x2061, 0x4380, 0x6328, 0x73da, 0x632c, 0x831c,
-	0x831c, 0x831c, 0x73de, 0x0804, 0x13a1, 0x2009, 0x434c, 0x210c,
-	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x438c,
-	0x2214, 0x0804, 0x13a1, 0x7918, 0x0804, 0x13a2, 0x2009, 0x434d,
-	0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011,
-	0x438d, 0x2214, 0x0804, 0x13a1, 0x2009, 0x434e, 0x210c, 0x2001,
-	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2011, 0x438e, 0x2214,
-	0x0804, 0x13a1, 0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
-	0x13a2, 0x7a24, 0x0804, 0x13a1, 0x2011, 0x4840, 0x71c4, 0xd1fc,
-	0x1110, 0x2011, 0x47c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13a0,
-	0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091,
-	0x8001, 0x2708, 0x0804, 0x13a0, 0x2061, 0x4340, 0x6118, 0x2001,
-	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13a2, 0x2061, 0x4380, 0x6218,
-	0x0804, 0x13a1, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6908,
-	0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0804, 0x13a0, 0x71c4,
-	0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x1a04, 0x139c, 0x080c,
-	0x230e, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13a0,
-	0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x1a04, 0x139c, 0xd1bc,
-	0x1120, 0x2011, 0x4348, 0x2204, 0x0020, 0x2011, 0x4388, 0x2204,
-	0xc0bd, 0x0006, 0x2100, 0xc0bc, 0x2012, 0x080c, 0x22b4, 0x001e,
-	0x0804, 0x13a2, 0x71c4, 0x2021, 0x4349, 0x2404, 0x70c6, 0x2019,
-	0x0000, 0x0030, 0x71c8, 0x2021, 0x4389, 0x2404, 0x70ca, 0xc3fd,
-	0x2011, 0x15fe, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210,
-	0x1f04, 0x15e4, 0x71c4, 0x72c8, 0x0804, 0x139b, 0xa292, 0x15fe,
-	0x0026, 0x2122, 0x001e, 0x080c, 0x22c6, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1110, 0xd3fc, 0x09f0, 0x0804, 0x13a3, 0x03e8, 0x00fa,
-	0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4340,
-	0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8,
-	0x8003, 0x8003, 0x8003, 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc,
-	0x11a0, 0x0026, 0x0016, 0x2061, 0x4380, 0x6128, 0x622c, 0x8214,
-	0x8214, 0x8214, 0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003,
-	0x602e, 0x71da, 0x72de, 0x001e, 0x002e, 0x0804, 0x13a1, 0x2061,
-	0x4340, 0x6130, 0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc,
-	0x1904, 0x13a2, 0x2061, 0x4380, 0x6230, 0x70c8, 0x6032, 0x0804,
-	0x13a1, 0x7918, 0x0804, 0x13a2, 0x71c4, 0xa184, 0xffcf, 0x0148,
-	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x139c, 0x72c8, 0x0804,
-	0x139b, 0x2011, 0x434d, 0x2204, 0x2112, 0x0006, 0x2019, 0x0000,
-	0x080c, 0x2302, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x001e,
-	0x0804, 0x13a2, 0x71c8, 0xa184, 0xffcf, 0x0128, 0x0006, 0x2110,
-	0x71c4, 0x0804, 0x139b, 0x2011, 0x438d, 0x2204, 0x2112, 0x0006,
-	0xc3fd, 0x080c, 0x2302, 0x002e, 0x001e, 0x0804, 0x13a1, 0x71c4,
-	0xa182, 0x0010, 0x0248, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
-	0x139c, 0x72c8, 0x0804, 0x139b, 0x2011, 0x434e, 0x2204, 0x0006,
-	0x2112, 0x2019, 0x0000, 0x080c, 0x22ef, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x0118, 0x001e, 0x0804, 0x13a2, 0x71c8, 0xa182, 0x0010,
-	0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, 0x139b, 0x2011, 0x438e,
-	0x2204, 0x0006, 0x2112, 0xc3fd, 0x080c, 0x22ef, 0x002e, 0x001e,
-	0x0804, 0x13a1, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x1904, 0x139b,
-	0xa284, 0xfffd, 0x1904, 0x139b, 0x2100, 0x7920, 0x7822, 0x2200,
-	0x7a24, 0x7826, 0x0804, 0x13a1, 0x2011, 0x4840, 0x71c4, 0xd1fc,
-	0x1110, 0x2011, 0x47c0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa268, 0x72c8, 0x73cc, 0x74d8, 0x71c6, 0x6800, 0x70ca,
-	0x73ce, 0x74da, 0x2091, 0x8000, 0x6a02, 0xd2ac, 0x1118, 0x2021,
-	0x0000, 0x0078, 0xa484, 0x00ff, 0xa082, 0x0002, 0x16e8, 0x843f,
-	0xa7bc, 0x00ff, 0x0130, 0xa786, 0x0002, 0x15b0, 0xa484, 0x00ff,
-	0x0598, 0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029,
-	0x0009, 0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307,
-	0xa084, 0x00ff, 0x1110, 0xa73d, 0x11f8, 0x2041, 0x001d, 0x8307,
-	0xa084, 0x00ff, 0x0150, 0xa842, 0x02b8, 0xa3bc, 0x00ff, 0x2500,
-	0xa702, 0x0290, 0x2600, 0xa702, 0x1278, 0x2039, 0x003a, 0x6804,
-	0xa705, 0x6806, 0x6b0a, 0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e,
-	0x2091, 0x8001, 0x0804, 0x13a3, 0x2091, 0x8001, 0x0804, 0x139d,
-	0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091,
-	0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0804, 0x13a0,
-	0x70c4, 0x2061, 0x4340, 0x6118, 0x601a, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1904, 0x13a2, 0x70c8, 0x2061, 0x4380, 0x6218, 0x601a,
-	0x0804, 0x13a1, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04,
-	0x139c, 0x080c, 0x2332, 0xa384, 0x4000, 0x0110, 0xa295, 0x0020,
-	0x0804, 0x13a0, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08,
-	0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0804, 0x13a1, 0x77c4,
-	0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a,
-	0x6804, 0xa005, 0x0110, 0x080c, 0x2233, 0x2091, 0x8001, 0x2708,
-	0x0804, 0x13a1, 0x77c4, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6a08,
-	0xc295, 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x2233, 0x2091,
-	0x8001, 0x2708, 0x0804, 0x13a1, 0x77c4, 0x2041, 0x0001, 0x2049,
-	0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b35, 0x2091,
-	0x8001, 0x2708, 0x6a08, 0x0804, 0x13a1, 0x77c4, 0xd7fc, 0x0128,
-	0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110,
-	0x0804, 0x13a5, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c,
-	0x1bad, 0x11e8, 0x6818, 0xa005, 0x01a0, 0x2708, 0x0076, 0x080c,
-	0x2351, 0x007e, 0x1170, 0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061,
-	0x4340, 0x0018, 0xc0fd, 0x2061, 0x4380, 0x782a, 0x2091, 0x8001,
-	0x0005, 0x2091, 0x8001, 0x2001, 0x4005, 0x0804, 0x13a5, 0x2091,
-	0x8001, 0x0804, 0x13a3, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1aa9,
-	0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110, 0x0804, 0x13a5,
-	0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
-	0x8000, 0x080c, 0x1b35, 0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061,
-	0x4340, 0x0018, 0x2061, 0x4380, 0xc1fd, 0x6067, 0x0003, 0x607f,
-	0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x080c, 0x2233, 0x2091,
+	0x2009, 0x0002, 0x2069, 0x4640, 0x681b, 0x0003, 0x6823, 0x0007,
+	0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0006,
+	0x6833, 0x0008, 0x683b, 0x0000, 0x8109, 0x0500, 0x68cf, 0x000a,
+	0x68bf, 0x46c0, 0x2079, 0x4600, 0x68d3, 0x762d, 0x68c3, 0x4bc0,
+	0x68c7, 0x4ac0, 0x68cb, 0x8bc0, 0x68a7, 0x8e44, 0x68ab, 0x8e49,
+	0x68af, 0x8e44, 0x68b3, 0x8e44, 0x68a3, 0x0001, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4680, 0x0870, 0x68cf, 0x000a,
+	0x68bf, 0x48c0, 0x68d3, 0x7839, 0x68c3, 0x6bc0, 0x68c7, 0x4b40,
+	0x68cb, 0x8cd0, 0x68a7, 0x8e49, 0x68ab, 0x8e4e, 0x68af, 0x8e49,
+	0x68b3, 0x8e49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x4ac0, 0x2071,
+	0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120,
+	0x2019, 0x180c, 0x2021, 0x000c, 0x080c, 0x1d58, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x1188, 0x2069, 0x4b40, 0x2071, 0x0100, 0x70ec,
+	0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120, 0x2019, 0x180c,
+	0x2021, 0x000c, 0x080c, 0x1d58, 0x00ee, 0x2011, 0x0002, 0x2069,
+	0x4bc0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b,
+	0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817, 0x0100, 0x681f,
+	0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
+	0x1f04, 0x1135, 0x8109, 0x1d38, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+	0x1128, 0x8211, 0x0118, 0x2069, 0x6bc0, 0x08d8, 0x080c, 0x22cf,
+	0x080c, 0x4015, 0x080c, 0x1b6d, 0x080c, 0x4553, 0x2091, 0x2200,
+	0x2079, 0x4600, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4600,
+	0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4640,
+	0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4680, 0x2091, 0x2000,
+	0x2079, 0x4600, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
+	0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118c, 0x70c0, 0xa086,
+	0x0002, 0x1110, 0x080c, 0x13ba, 0x2039, 0x0000, 0x080c, 0x12ab,
+	0x78ac, 0xa005, 0x1180, 0x0e04, 0x119a, 0x786c, 0xa065, 0x0110,
+	0x080c, 0x207a, 0x080c, 0x1e09, 0x0e04, 0x11af, 0x786c, 0xa065,
+	0x0110, 0x080c, 0x207a, 0x0e04, 0x11af, 0x2009, 0x4647, 0x2011,
+	0x4687, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c7c, 0x2071,
+	0x4640, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8,
+	0x2079, 0x0200, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d, 0x2190,
+	0x080c, 0x2720, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1,
+	0x2079, 0x4600, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c,
+	0x207a, 0x1d04, 0x11d9, 0x2079, 0x4600, 0x2071, 0x0010, 0x080c,
+	0x4370, 0x2071, 0x4680, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025,
+	0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d,
+	0x2190, 0x080c, 0x2720, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079,
+	0x4600, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110,
+	0x080c, 0x207a, 0x1d04, 0x118e, 0x080c, 0x4370, 0x0804, 0x118e,
+	0x3c00, 0xa084, 0x0007, 0x0002, 0x120c, 0x120c, 0x120e, 0x120e,
+	0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x254c, 0x2091, 0x2400,
+	0x080c, 0x40ad, 0x0005, 0x2091, 0x2200, 0x080c, 0x40ad, 0x0005,
+	0x2091, 0x2200, 0x080c, 0x40ad, 0x2091, 0x2400, 0x080c, 0x40ad,
+	0x0005, 0x1241, 0x1241, 0x1242, 0x1242, 0x124d, 0x124d, 0x124d,
+	0x124d, 0x1256, 0x1256, 0x1261, 0x1261, 0x124d, 0x124d, 0x124d,
+	0x124d, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
+	0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
+	0x1270, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091, 0x2800, 0x080c,
+	0x2569, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126,
+	0x080c, 0x1200, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106,
+	0x0126, 0x2091, 0x2600, 0x080c, 0x2569, 0x012e, 0x010e, 0x000e,
+	0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2569,
+	0x2091, 0x2800, 0x080c, 0x2569, 0x012e, 0x010e, 0x000e, 0x000d,
+	0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4600,
+	0x2071, 0x0200, 0x2069, 0x4640, 0x3d00, 0xd08c, 0x0130, 0x70ec,
+	0xa084, 0x1c00, 0x78e2, 0x080c, 0x459a, 0x3d00, 0xd084, 0x0150,
+	0x2069, 0x4680, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6,
+	0x080c, 0x459a, 0x080c, 0x24fd, 0x00fe, 0x00ee, 0x00de, 0x012e,
+	0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007, 0x0002,
+	0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897, 0x70c3,
+	0x4002, 0x0804, 0x13bd, 0x0e04, 0x131e, 0x2061, 0x0000, 0x6018,
+	0xd084, 0x1904, 0x131e, 0x7828, 0xa005, 0x1120, 0x0004, 0x131f,
+	0x0804, 0x131e, 0xd0fc, 0x0130, 0x0006, 0x080c, 0x1b0a, 0x000e,
+	0x0150, 0x0028, 0x0006, 0x080c, 0x1aff, 0x000e, 0x0120, 0x2001,
+	0x4007, 0x0804, 0x13bc, 0x7910, 0xd0fc, 0x1128, 0x2061, 0x4640,
+	0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4680, 0xc19d, 0xc7fd, 0x6060,
+	0xa005, 0x1904, 0x131e, 0x7912, 0x607e, 0x7828, 0xc0fc, 0xa086,
+	0x0018, 0x1120, 0x00c6, 0x080c, 0x1916, 0x00ce, 0x782b, 0x0000,
+	0x6078, 0xa065, 0x01e0, 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce,
+	0x609f, 0x0000, 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087, 0x0103,
+	0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
+	0x080c, 0x1b15, 0x000e, 0x7812, 0x1198, 0x080c, 0x1b60, 0x7810,
+	0xd09c, 0x1118, 0x2061, 0x4640, 0x0020, 0x2061, 0x4680, 0xc09c,
+	0x7812, 0x607b, 0x0000, 0x60d0, 0xd0c4, 0x0130, 0xc0c4, 0x60d2,
+	0x2001, 0x4005, 0x0804, 0x13bc, 0x0804, 0x13ba, 0x0005, 0xa006,
+	0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a,
+	0x0040, 0x1a04, 0x136c, 0x0002, 0x13ba, 0x1408, 0x13d6, 0x143c,
+	0x1470, 0x1470, 0x13ce, 0x1a59, 0x147a, 0x13c8, 0x13da, 0x13db,
+	0x13dc, 0x13dd, 0x1a5d, 0x13c8, 0x1487, 0x14db, 0x1931, 0x1a53,
+	0x13de, 0x17ba, 0x17f0, 0x1822, 0x1868, 0x1777, 0x1784, 0x1797,
+	0x17a9, 0x15b0, 0x13c8, 0x150d, 0x1518, 0x1526, 0x1534, 0x154b,
+	0x1559, 0x155c, 0x156a, 0x1578, 0x1582, 0x1596, 0x15a2, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x15bd, 0x15ce, 0x15e8, 0x161c, 0x1645,
+	0x1657, 0x165a, 0x1685, 0x16be, 0x16d0, 0x1745, 0x1755, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x1767, 0x2100, 0xa08a, 0x0040, 0x1a04,
+	0x13c8, 0x0002, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x1a7f,
+	0x1a85, 0x13c8, 0x13c8, 0x13c8, 0x1a89, 0x1ac9, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x1403, 0x146b, 0x1482, 0x14d6, 0x192c, 0x13c8,
+	0x13c8, 0x18fb, 0x13c8, 0x1acd, 0x1a71, 0x1a7b, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0028, 0x73ce,
+	0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0e04, 0x13bd, 0x2061,
+	0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x0005,
+	0x70c3, 0x4001, 0x0c90, 0x70c3, 0x4006, 0x0c78, 0x2099, 0x0041,
+	0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0c20, 0x70c4, 0x70c3,
+	0x0004, 0x0807, 0x08f8, 0x08f0, 0x08e8, 0x08e0, 0x2091, 0x8000,
+	0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020,
+	0x70d3, 0x000a, 0x2001, 0x0004, 0x70d6, 0x2079, 0x0000, 0x781b,
+	0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051,
+	0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091,
+	0x4080, 0x0804, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0018,
+	0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0,
+	0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e,
+	0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0904, 0x13ba, 0xa182,
+	0x0040, 0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x7007,
+	0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002,
+	0xa084, 0x01e0, 0x0120, 0x70c3, 0x4002, 0x0804, 0x13bd, 0x24a8,
+	0x53a5, 0x0c10, 0x0804, 0x13ba, 0x2029, 0x0000, 0x2520, 0x71d0,
+	0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003, 0x0000,
+	0x7007, 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040,
+	0x7007, 0x0006, 0x81ff, 0x0904, 0x13ba, 0xa182, 0x0040, 0x1210,
+	0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007,
+	0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48, 0x70c3,
+	0x4002, 0x0804, 0x13bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0878,
+	0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a, 0x72ca,
+	0x0804, 0x13b9, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, 0x0020,
+	0x0804, 0x13ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029,
+	0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca,
+	0x73ce, 0x74d2, 0xa005, 0x05e8, 0xa40a, 0x0108, 0x1240, 0x8001,
+	0x7872, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc085, 0x78ae, 0x2001,
+	0x4005, 0x0804, 0x13bc, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76,
+	0xa48c, 0xff00, 0x0170, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c,
+	0x810f, 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000,
+	0x0050, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1,
+	0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605,
+	0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae,
+	0x0018, 0x78ac, 0xc085, 0x78ae, 0x0804, 0x13ba, 0x75d8, 0x76dc,
+	0x75da, 0x76de, 0x0018, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8,
+	0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0500,
+	0xa40a, 0x0110, 0x1a04, 0x13bc, 0x8001, 0x7892, 0xa084, 0xfc00,
+	0x0138, 0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0804, 0x13bc,
+	0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0118, 0x7a10,
+	0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0018,
+	0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13ba, 0x2009, 0x0000, 0x786c,
+	0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4, 0x0804, 0x13b8,
+	0x2009, 0x4648, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+	0x13b9, 0x2011, 0x4688, 0x2214, 0x0804, 0x13b8, 0x2009, 0x4649,
+	0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
+	0x4689, 0x2214, 0x0804, 0x13b8, 0x2061, 0x4640, 0x6128, 0x622c,
+	0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1148,
+	0x2061, 0x4680, 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c,
+	0x73de, 0x0804, 0x13b8, 0x2009, 0x464c, 0x210c, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x468c, 0x2214, 0x0804,
+	0x13b8, 0x7918, 0x0804, 0x13b9, 0x2009, 0x0202, 0x210c, 0x2001,
+	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x0102, 0x2214,
+	0x0804, 0x13b8, 0x2009, 0x464d, 0x210c, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1904, 0x13b9, 0x2011, 0x468d, 0x2214, 0x0804, 0x13b8,
+	0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x7a24,
+	0x0804, 0x13b8, 0x2011, 0x4b40, 0x71c4, 0xd1fc, 0x1110, 0x2011,
+	0x4ac0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268,
+	0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13b7, 0x77c4, 0x080c,
+	0x1b7b, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708,
+	0x0804, 0x13b7, 0x2061, 0x4640, 0x6118, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1904, 0x13b9, 0x2061, 0x4680, 0x6218, 0x0804, 0x13b8,
+	0x77c4, 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10,
+	0x77da, 0x2091, 0x8001, 0x0804, 0x13b7, 0x71c4, 0x2110, 0xa294,
+	0x000f, 0xa282, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x238b, 0xa384,
+	0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x71c4, 0x2100,
+	0xc0bc, 0xa082, 0x0010, 0x1a04, 0x13b3, 0xd1bc, 0x1120, 0x2011,
+	0x4648, 0x2204, 0x0020, 0x2011, 0x4688, 0x2204, 0xc0bd, 0x0006,
+	0x2100, 0xc0bc, 0x2012, 0x080c, 0x2331, 0x001e, 0x0804, 0x13b9,
+	0x71c4, 0x2021, 0x4649, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0030,
+	0x71c8, 0x2021, 0x4689, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1614,
+	0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, 0x1f04, 0x15fa,
+	0x71c4, 0x72c8, 0x0804, 0x13b2, 0xa292, 0x1614, 0x0026, 0x2122,
+	0x001e, 0x080c, 0x2343, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1110,
+	0xd3fc, 0x09f0, 0x0804, 0x13ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
+	0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4640, 0x6128, 0x622c,
+	0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
+	0x8003, 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11a0, 0x0026,
+	0x0016, 0x2061, 0x4680, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
+	0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da,
+	0x72de, 0x001e, 0x002e, 0x0804, 0x13b8, 0x2061, 0x4640, 0x6130,
+	0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9,
+	0x2061, 0x4680, 0x6230, 0x70c8, 0x6032, 0x0804, 0x13b8, 0x7918,
+	0x0804, 0x13b9, 0x71c4, 0xa184, 0xf0cf, 0x0148, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2, 0x0006,
+	0x2019, 0x0000, 0x080c, 0x237f, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+	0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa184, 0xf0cf, 0x0128,
+	0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x0006, 0xc3fd, 0x080c,
+	0x237f, 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0xa182, 0x0010,
+	0x0248, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8,
+	0x0804, 0x13b2, 0x2011, 0x464d, 0x2204, 0x0006, 0x8104, 0x1208,
+	0x8108, 0x2112, 0x2019, 0x0000, 0x080c, 0x236c, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa182,
+	0x0010, 0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x2011,
+	0x468d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, 0x2112, 0xc3fd,
+	0x080c, 0x236c, 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0x72c8,
+	0xa184, 0xfffd, 0x1904, 0x13b2, 0xa284, 0xfffd, 0x1904, 0x13b2,
+	0x2100, 0x7920, 0x7822, 0x2200, 0x7a24, 0x7826, 0x0804, 0x13b8,
+	0x2011, 0x4b40, 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4ac0, 0x8107,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x72c8, 0x73cc,
+	0x74d8, 0x71c6, 0x6800, 0x70ca, 0x73ce, 0x74da, 0x2091, 0x8000,
+	0x6a02, 0xd2ac, 0x1118, 0x2021, 0x0000, 0x0090, 0xa484, 0x00ff,
+	0xa082, 0x0002, 0x1a04, 0x1741, 0x843f, 0xa7bc, 0x00ff, 0x0140,
+	0xa786, 0x0002, 0x1904, 0x1741, 0xa484, 0x00ff, 0x0904, 0x1741,
+	0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, 0x0009,
+	0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, 0xa084,
+	0x00ff, 0x1110, 0xa73d, 0x1138, 0x2041, 0x0019, 0xa384, 0x00ff,
+	0xa082, 0x001a, 0x0210, 0xa4a4, 0x00ff, 0x8307, 0xa084, 0x00ff,
+	0x0188, 0xa842, 0x02f0, 0xa086, 0x0010, 0x1120, 0xa39c, 0x00ff,
+	0xa39d, 0x0f00, 0xa3bc, 0x00ff, 0x2500, 0xa702, 0x0290, 0x2600,
+	0xa702, 0x1278, 0x2039, 0x003a, 0x6804, 0xa705, 0x6806, 0x6b0a,
+	0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e, 0x2091, 0x8001, 0x0804,
+	0x13ba, 0x2091, 0x8001, 0x0804, 0x13b4, 0x77c4, 0x080c, 0x1b7b,
+	0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816,
+	0x70cc, 0x681e, 0x2708, 0x0804, 0x13b7, 0x70c4, 0x2061, 0x4640,
+	0x6118, 0x601a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9,
+	0x70c8, 0x2061, 0x4680, 0x6218, 0x601a, 0x0804, 0x13b8, 0x71c4,
+	0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23af,
+	0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x77c4,
+	0x080c, 0x1b7b, 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091,
+	0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b7b, 0x2091,
+	0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0110,
+	0x080c, 0x22ae, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4,
+	0x080c, 0x1b7b, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804,
+	0xa005, 0x0110, 0x080c, 0x22ae, 0x2091, 0x8001, 0x2708, 0x0804,
+	0x13b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020,
+	0x2091, 0x8000, 0x080c, 0x1b93, 0x2091, 0x8001, 0x2708, 0x6a08,
+	0x0804, 0x13b8, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b0a, 0x0138,
+	0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x73c8,
+	0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c, 0x1c0b, 0x11e8, 0x6818,
+	0xa005, 0x01a0, 0x2708, 0x0076, 0x080c, 0x23ce, 0x007e, 0x1170,
+	0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0xc0fd,
+	0x2061, 0x4680, 0x782a, 0x2091, 0x8001, 0x0005, 0x2091, 0x8001,
+	0x2001, 0x4005, 0x0804, 0x13bc, 0x2091, 0x8001, 0x0804, 0x13ba,
+	0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b0a, 0x0138, 0x0804, 0x13bc,
+	0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x77c6, 0x2041, 0x0021,
+	0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b93,
+	0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061,
+	0x4680, 0xc1fd, 0x6063, 0x0003, 0x607b, 0x0000, 0x6772, 0x607f,
+	0x000f, 0x792a, 0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22ae, 0x2091,
 	0x8001, 0x0005, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128,
-	0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110,
-	0x0804, 0x13a5, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017,
-	0xd7fc, 0x1118, 0x2061, 0x4340, 0x0018, 0x2061, 0x4380, 0xc1fd,
-	0x607f, 0x0000, 0x6067, 0x0002, 0x6776, 0x6083, 0x000f, 0x792a,
-	0x080c, 0x2233, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005,
-	0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118, 0x60d4,
-	0xc0fd, 0x60d6, 0x080c, 0x1b35, 0x70c8, 0x6836, 0x8738, 0xa784,
-	0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005, 0x72c8, 0xd284, 0x0128,
-	0x080c, 0x1aa9, 0x0138, 0x0804, 0x13a5, 0x080c, 0x1a9b, 0x0110,
-	0x0804, 0x13a5, 0x72c8, 0x72ca, 0x78ac, 0xa084, 0x0003, 0x1508,
-	0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049,
-	0x0004, 0x2051, 0x0008, 0x080c, 0x1b1d, 0x2091, 0x8000, 0x6808,
-	0xc0d4, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f,
-	0x1d90, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
-	0x1d50, 0x2091, 0x8000, 0x72c8, 0x2069, 0x0100, 0xd284, 0x1110,
-	0x2069, 0x0200, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4,
-	0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110,
-	0x1f04, 0x1885, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084,
-	0x0110, 0x1f04, 0x188e, 0x20a9, 0x00fa, 0x1f04, 0x1895, 0x2079,
-	0x4300, 0x2009, 0x0018, 0x72c8, 0xd284, 0x1118, 0x2061, 0x4340,
-	0x0018, 0x2061, 0x4380, 0xc1fd, 0x792a, 0x6067, 0x0001, 0x6083,
-	0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4,
-	0x0160, 0xc0b4, 0x60d6, 0x00c6, 0x60b8, 0xa065, 0x6008, 0xc0d4,
-	0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x60d4, 0xa084, 0x7eff,
-	0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x681b, 0x0054, 0x2091, 0x8001,
-	0x0005, 0xd7fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, 0x4380,
-	0x71c4, 0x71c6, 0x6916, 0x81ff, 0x1110, 0x68a7, 0x0001, 0x78ac,
-	0xc08c, 0x78ae, 0xd084, 0x1110, 0x080c, 0x1c00, 0x0005, 0x75d8,
-	0x74dc, 0x75da, 0x74de, 0x0018, 0x2029, 0x0000, 0x2520, 0x71c4,
-	0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4300, 0x7dde,
-	0x7cda, 0x7bd6, 0x7ad2, 0x080c, 0x1afa, 0x0904, 0x19d7, 0x20a9,
-	0x0005, 0x20a1, 0x4314, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001,
-	0x2009, 0x0040, 0x080c, 0x1cbf, 0x0120, 0x080c, 0x1b02, 0x0804,
-	0x19d7, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x1120, 0x0006,
-	0x080c, 0x1fe3, 0x000e, 0xa084, 0xff00, 0x8007, 0x8009, 0x0904,
-	0x1981, 0x00c6, 0x2c68, 0x080c, 0x1afa, 0x05a8, 0x2c00, 0x689e,
-	0x8109, 0x1dc0, 0x609f, 0x0000, 0x00ce, 0x00c6, 0x7ddc, 0x7cd8,
-	0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000,
-	0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x2c68, 0x689c,
-	0xa065, 0x0904, 0x1980, 0x2009, 0x0040, 0x080c, 0x1cbf, 0x1550,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x1168, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x000a, 0x1120, 0x0016, 0x080c, 0x1fe0, 0x001e,
-	0x2d00, 0x6002, 0x0898, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1b76,
-	0x00ce, 0x609f, 0x0000, 0x080c, 0x19db, 0x2009, 0x0018, 0x6008,
-	0xc0cd, 0x600a, 0x6004, 0x6086, 0x080c, 0x1ab7, 0x080c, 0x1b02,
-	0x0804, 0x19d7, 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1b76, 0x00ce,
-	0x609f, 0x0000, 0x080c, 0x19db, 0x2009, 0x0018, 0x6087, 0x0103,
-	0x601b, 0x0003, 0x080c, 0x1ab7, 0x080c, 0x1b02, 0x0804, 0x19d7,
-	0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1aa9, 0x01b8, 0x0018,
-	0x080c, 0x1a9b, 0x0198, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018,
-	0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x080c, 0x1ab7,
-	0x080c, 0x1b02, 0x2001, 0x4007, 0x0804, 0x13a5, 0x74c4, 0x73c8,
-	0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc,
-	0x1118, 0x2071, 0x4340, 0x0018, 0x2071, 0x4380, 0xc1fd, 0x792a,
-	0x7067, 0x0005, 0x71d4, 0xa18c, 0xfe7f, 0x71d6, 0x736a, 0x726e,
-	0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, 0x2530,
-	0x611c, 0xa184, 0x0060, 0x0110, 0x080c, 0x3de5, 0x00ee, 0x6596,
-	0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714,
-	0x6023, 0x0000, 0x080c, 0x2233, 0x2091, 0x8001, 0x0005, 0x70c3,
-	0x4005, 0x0804, 0x13a6, 0x20a9, 0x0005, 0x2099, 0x4314, 0x2091,
-	0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, 0xa399, 0x0000,
-	0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000,
-	0x791e, 0x0804, 0x13a3, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069,
-	0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8,
-	0xa285, 0x0000, 0x1118, 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003,
-	0x70ca, 0x0804, 0x13a6, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003,
-	0x1a04, 0x139c, 0x7966, 0x0804, 0x13a3, 0x7964, 0x71c6, 0x0804,
-	0x13a3, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0804, 0x13a3, 0x7900,
-	0x71c6, 0x0804, 0x13a3, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d,
-	0x0160, 0x810c, 0x0230, 0x8210, 0x810c, 0x810c, 0x0210, 0x8210,
-	0x810c, 0x81ff, 0x1904, 0x139d, 0x8210, 0x7a0e, 0xd28c, 0x0538,
-	0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, 0x0003, 0xd284,
-	0x01c0, 0x8108, 0x2019, 0x0041, 0x2011, 0x8b4e, 0x2312, 0x2019,
-	0x0042, 0x8210, 0x2312, 0x2019, 0x0043, 0x8210, 0x2312, 0x2019,
-	0x0046, 0x8210, 0x2312, 0x2019, 0x0047, 0x8210, 0x2312, 0x2019,
-	0x0006, 0x2011, 0x8b53, 0x2112, 0x2011, 0x8b73, 0x2312, 0x7904,
-	0x7806, 0x0804, 0x13a2, 0x7804, 0x70c6, 0x0804, 0x13a3, 0x71c4,
-	0xd1fc, 0x1118, 0x2011, 0x47c0, 0x0010, 0x2011, 0x4840, 0x8107,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x2011, 0x0000,
-	0x6814, 0xd0fc, 0x0110, 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295,
-	0x0001, 0x6b0c, 0x0804, 0x13a0, 0x0016, 0x7814, 0xd0f4, 0x0138,
-	0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0050, 0xd0fc,
-	0x0138, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0008,
-	0xa006, 0x001e, 0x0005, 0x0016, 0x7814, 0xd0f4, 0x0138, 0x2001,
-	0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e,
-	0x0005, 0x0016, 0x7814, 0xd0fc, 0x0138, 0x2001, 0x4007, 0x70db,
-	0x0001, 0xa18d, 0x0001, 0x0008, 0xa006, 0x001e, 0x0005, 0x7112,
-	0x721a, 0x731e, 0x7810, 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80,
-	0x0001, 0x8108, 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003,
-	0x0000, 0x6084, 0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184,
-	0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
-	0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
-	0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80,
-	0xa421, 0x7008, 0xd0fc, 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006,
-	0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084,
-	0x01e0, 0x0005, 0x7848, 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063,
-	0x0000, 0x0005, 0x00f6, 0x2079, 0x4300, 0x7848, 0x2062, 0x2c00,
-	0xa005, 0x1110, 0x080c, 0x243b, 0x784a, 0x00fe, 0x0005, 0x2011,
-	0x8d00, 0x7a4a, 0x7bc4, 0x8319, 0x0128, 0xa280, 0x0032, 0x2012,
-	0x2010, 0x0cc8, 0x2013, 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc,
-	0x1118, 0x2011, 0x48c0, 0x0010, 0x2011, 0x68c0, 0xa784, 0x0f00,
-	0x800b, 0xa784, 0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003,
-	0xa105, 0xa268, 0x002e, 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a,
-	0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6,
-	0xd7fc, 0x1128, 0x2009, 0x4353, 0x2071, 0x4340, 0x0020, 0x2009,
-	0x4393, 0x2071, 0x4380, 0x210c, 0x6804, 0xa005, 0x0148, 0xa116,
-	0x1138, 0x2060, 0x6000, 0x6806, 0x0016, 0x200b, 0x0000, 0x0018,
-	0x2009, 0x0000, 0x0016, 0x6804, 0xa065, 0x0178, 0x6000, 0x6806,
-	0x0421, 0x080c, 0x1d30, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001,
-	0x6812, 0x1d88, 0x7910, 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906,
-	0x2d00, 0x2060, 0x080c, 0x2580, 0x00ee, 0x0005, 0xa065, 0x0160,
-	0x2008, 0x609c, 0xa005, 0x0128, 0x2062, 0x609f, 0x0000, 0xa065,
-	0x0cc0, 0x7848, 0x794a, 0x2062, 0x0005, 0x6007, 0x0103, 0x608f,
-	0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000,
-	0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc,
-	0x1128, 0x2071, 0x4340, 0x2031, 0x43c0, 0x0020, 0x2071, 0x4380,
-	0x2031, 0x45c0, 0x7050, 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a,
-	0x8000, 0x7052, 0xa006, 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118,
-	0x2079, 0x4340, 0x0010, 0x2079, 0x4380, 0x080c, 0x1b1d, 0x2091,
-	0x8000, 0x6804, 0x780a, 0xa065, 0x0904, 0x1bfe, 0x0030, 0x2c00,
-	0x780a, 0x2060, 0x6000, 0xa065, 0x05c8, 0x6010, 0xa306, 0x1db8,
-	0x600c, 0xa206, 0x1da0, 0x2c28, 0x784c, 0xac06, 0x1108, 0x0458,
-	0x6804, 0xac06, 0x1140, 0x6000, 0x2060, 0x6806, 0xa005, 0x1118,
-	0x6803, 0x0000, 0x0048, 0x6400, 0x7808, 0x2060, 0x6402, 0xa486,
-	0x0000, 0x1110, 0x2c00, 0x6802, 0x2560, 0x00fe, 0x080c, 0x1b85,
-	0x00f6, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe, 0x080c, 0x1d30,
-	0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, 0x6812, 0x1118,
-	0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005, 0x00fe, 0x0005,
-	0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108, 0xc7fd, 0x2041,
-	0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x080c,
-	0x1b35, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc, 0xff00, 0x873f,
-	0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091, 0x8001, 0x007e,
-	0x0005, 0x786c, 0x2009, 0x8b74, 0x210c, 0xa10d, 0x0118, 0xa065,
-	0x0804, 0x1ffe, 0x2061, 0x0000, 0x6018, 0xd084, 0x11b8, 0x7810,
-	0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069, 0x4340, 0x0028,
-	0xc08d, 0x7812, 0x2069, 0x4380, 0xc7fd, 0x2091, 0x8000, 0x681c,
-	0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108, 0x0005, 0xa08c,
-	0xfff0, 0x0110, 0x080c, 0x243b, 0x0002, 0x1c5d, 0x1c60, 0x1c66,
-	0x1c6a, 0x1c5e, 0x1c6e, 0x1c5e, 0x1c5e, 0x1c5e, 0x1c73, 0x1c9f,
-	0x1ca2, 0x1ca7, 0x1c5e, 0x1c5e, 0x1c5e, 0x0005, 0x080c, 0x243b,
-	0x080c, 0x1c00, 0x2001, 0x8001, 0x0804, 0x1cb0, 0x2001, 0x8003,
-	0x0804, 0x1cb0, 0x2001, 0x8004, 0x0804, 0x1cb0, 0x080c, 0x1c00,
-	0x2001, 0x8006, 0x04e8, 0x2091, 0x8000, 0x0076, 0xd7fc, 0x1128,
-	0x2069, 0x4340, 0x2039, 0x0009, 0x0020, 0x2069, 0x4380, 0x2039,
-	0x0009, 0x6800, 0xa086, 0x0000, 0x0128, 0x000e, 0x6f1e, 0x2091,
-	0x8001, 0x0005, 0x6874, 0x007e, 0xa0bc, 0xff00, 0x2041, 0x0021,
-	0x2049, 0x0004, 0x2051, 0x0010, 0x080c, 0x1b35, 0x8738, 0xa784,
-	0x001f, 0x1dd0, 0x2091, 0x8001, 0x2001, 0x800a, 0x0088, 0x2001,
-	0x800c, 0x0070, 0x080c, 0x1c00, 0x2001, 0x800d, 0x0048, 0xd7fc,
-	0x0110, 0x78ec, 0x0008, 0x78e4, 0x70c6, 0x2001, 0x800e, 0x0000,
-	0x70c2, 0xd7fc, 0x1118, 0x70db, 0x0000, 0x0010, 0x70db, 0x0001,
-	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x0005, 0xac80,
-	0x0001, 0x81ff, 0x0518, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084,
-	0x07ff, 0x0100, 0x7018, 0x0006, 0x701c, 0x0006, 0x7020, 0x0006,
-	0x7024, 0x0006, 0x7112, 0x81ac, 0x721a, 0x731e, 0x7422, 0x7526,
-	0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b, 0x1ee8, 0x7007,
-	0x0002, 0xa08c, 0x01e0, 0x1110, 0x53a5, 0xa006, 0x7003, 0x0000,
-	0x7007, 0x0004, 0x000e, 0x7026, 0x000e, 0x7022, 0x000e, 0x701e,
-	0x000e, 0x701a, 0x0005, 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a,
-	0x6c0e, 0x681f, 0x0201, 0x6803, 0xfd20, 0x6807, 0x0038, 0x6a1a,
-	0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109, 0x1d80, 0x0005,
-	0x70ec, 0xd0dc, 0x1520, 0x2029, 0x0001, 0x7814, 0xd0cc, 0x1160,
-	0x70ec, 0xd0e4, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1120, 0x2019,
-	0x0c0c, 0x2021, 0x000c, 0x0070, 0x70ec, 0xd0e4, 0x1128, 0x2019,
-	0x1c0c, 0x2021, 0x000c, 0x0030, 0x2019, 0x1c09, 0x2021, 0x0009,
-	0xa5ad, 0x0200, 0x6b0a, 0x6c0e, 0x6d1e, 0x6807, 0x0038, 0x0005,
-	0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, 0x7868, 0xa005, 0x796a,
-	0x0110, 0x2c02, 0x0008, 0x796e, 0x0005, 0x00c6, 0x2061, 0x4300,
-	0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a,
-	0x0110, 0x2d02, 0x0008, 0x616e, 0x00ce, 0x0005, 0x2091, 0x8000,
-	0x2c04, 0x786e, 0xa005, 0x1108, 0x786a, 0x2091, 0x8001, 0x609c,
-	0xa005, 0x0188, 0x00c6, 0x2060, 0x2008, 0x609c, 0xa005, 0x0138,
-	0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005, 0x1dc8, 0x7848,
-	0x794a, 0x2062, 0x00ce, 0x7848, 0x2062, 0x609f, 0x0000, 0xac85,
-	0x0000, 0x1110, 0x080c, 0x243b, 0x784a, 0x0005, 0x20a9, 0x0010,
-	0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x1d7a,
-	0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8,
-	0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04,
-	0x1d8a, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x1d8a, 0x0006,
-	0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006,
-	0x3200, 0xa085, 0x1000, 0x0cb8, 0x7d74, 0x70d0, 0xa506, 0x0904,
-	0x1e5b, 0x7810, 0x2050, 0x7800, 0xd08c, 0x0100, 0x080c, 0x1afa,
-	0x0904, 0x1e5b, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, 0x2009,
-	0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, 0x2009,
-	0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9,
-	0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0110,
-	0x080c, 0x1afa, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, 0x2091,
-	0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, 0x88ff,
-	0x0904, 0x1e48, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80,
-	0x0001, 0x20a0, 0x53a5, 0x0804, 0x1e48, 0xa046, 0x7218, 0x731c,
-	0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000,
-	0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0118,
-	0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1e48, 0x8cff,
-	0x0110, 0x080c, 0x1b02, 0x00ce, 0x080c, 0x1b02, 0xa046, 0x7888,
-	0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, 0xdac4,
-	0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210,
-	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e,
-	0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, 0x1118,
-	0x2069, 0x4340, 0x0010, 0x2069, 0x4380, 0x2091, 0x8000, 0x681f,
-	0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, 0x788b,
-	0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0098,
-	0x00ce, 0x788b, 0x0000, 0x080c, 0x1fb9, 0x6004, 0xa084, 0x000f,
-	0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, 0x000f,
-	0x0019, 0x0804, 0x1da4, 0x0005, 0x0002, 0x1e6d, 0x1e88, 0x1ea1,
-	0x1e6d, 0x1eae, 0x1e7e, 0x1e6d, 0x1e6d, 0x1e6d, 0x1e86, 0x1e9f,
-	0x1e6d, 0x1e6d, 0x1e6d, 0x1e6d, 0x1e6d, 0x2039, 0x0400, 0x78bc,
-	0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1eea, 0x609c,
-	0x78ba, 0x609f, 0x0000, 0x080c, 0x1fa5, 0x0005, 0x78bc, 0xd0c4,
-	0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, 0x1fe3,
-	0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, 0x8007,
-	0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1eea, 0x0120,
-	0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f05, 0x0005, 0x080c,
-	0x1fe0, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, 0x0828,
-	0x080c, 0x1eea, 0x1110, 0x0804, 0x1f05, 0x0005, 0x78bc, 0xd0c4,
-	0x0110, 0x0804, 0x1e6d, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001,
-	0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, 0xff00,
-	0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, 0x2011,
-	0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, 0x080c,
-	0x1b1d, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000,
-	0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001,
-	0x1f04, 0x1ed2, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, 0x080c,
-	0x1b02, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6,
-	0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06,
-	0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, 0xc0c4,
-	0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, 0x2530,
-	0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, 0xa984,
-	0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c, 0x3de5, 0x6596,
-	0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4380, 0xd7fc, 0x1110,
-	0x2071, 0x4340, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0120,
-	0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700,
-	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100,
-	0x60c2, 0x2091, 0x8000, 0x6e08, 0xd684, 0x0170, 0xd9fc, 0x1160,
-	0x2091, 0x8001, 0x080c, 0x1b85, 0x2091, 0x8000, 0x080c, 0x1d30,
-	0x2091, 0x8001, 0x0804, 0x1fa3, 0x6024, 0xa096, 0x0001, 0x1110,
-	0x8000, 0x6026, 0x6a10, 0x6814, 0xa202, 0x0268, 0x0160, 0x2091,
-	0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c,
-	0x1fa5, 0x0804, 0x1fa3, 0x2c08, 0xd9fc, 0x01f0, 0x6800, 0xa065,
-	0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0168, 0x704c, 0xa206,
-	0x1150, 0x6b04, 0x2160, 0x2304, 0x6002, 0xa005, 0x1108, 0x6902,
-	0x2260, 0x6102, 0x0098, 0x2d00, 0x2060, 0x080c, 0x2580, 0x6e08,
-	0x2160, 0x6202, 0x6906, 0x0050, 0x6800, 0x6902, 0xa065, 0x0110,
-	0x6102, 0x0008, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0xd9fc,
-	0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08, 0x8528, 0x7d0a,
-	0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0128, 0xa6b6, 0x0040,
-	0x6e0a, 0x080c, 0x1b96, 0x00ee, 0x0005, 0x6008, 0xa705, 0x600a,
-	0x2091, 0x8000, 0x080c, 0x1d30, 0x2091, 0x8001, 0x78b8, 0xa065,
-	0x0128, 0x609c, 0x78ba, 0x609f, 0x0000, 0x0c78, 0x78b6, 0x78ba,
-	0x0005, 0x7970, 0x7874, 0x2818, 0xd384, 0x0118, 0x8000, 0xa112,
-	0x0220, 0x8000, 0xa112, 0x1278, 0xc384, 0x7a7c, 0x721a, 0x7a78,
-	0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222, 0x7a80, 0x7226, 0xa006,
-	0xd384, 0x0108, 0x8000, 0x7876, 0x70d2, 0x781c, 0xa005, 0x0138,
-	0x8001, 0x781e, 0x1120, 0x0e04, 0x1fdf, 0x2091, 0x4080, 0x0005,
-	0x2039, 0x1ff5, 0x0010, 0x2039, 0x1ffb, 0x2704, 0xa005, 0x0160,
-	0xac00, 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814,
-	0x6916, 0x680e, 0x8738, 0x0c88, 0x0005, 0x0003, 0x0009, 0x000f,
-	0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000,
-	0x780c, 0x0002, 0x21a7, 0x2182, 0x2006, 0x2076, 0x2039, 0x8b74,
-	0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086, 0x0103, 0x1904, 0x2060,
-	0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, 0x11d8, 0x0804, 0x2060,
-	0x8603, 0xa080, 0x8b55, 0x620c, 0x2202, 0x8000, 0x6210, 0x2202,
-	0x080c, 0x1d4e, 0x8630, 0xa68e, 0x000f, 0x0904, 0x20e1, 0x786c,
-	0xa065, 0x1d08, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a,
-	0x0005, 0xa682, 0x0003, 0x1a04, 0x20e1, 0x2091, 0x8000, 0x2069,
-	0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, 0x8b55, 0x2204, 0x70c6,
-	0x8210, 0x2204, 0x70ca, 0xd684, 0x1130, 0x8210, 0x2204, 0x70da,
-	0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001,
-	0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001,
-	0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x0804, 0x20e1,
-	0x263a, 0x080c, 0x21ad, 0x1904, 0x21c9, 0x786c, 0xa065, 0x1904,
-	0x200b, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108,
-	0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804, 0x21c9, 0x2039, 0x8b74,
-	0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086, 0x0103, 0x1904, 0x20cb,
-	0x6114, 0x6018, 0xa105, 0x0120, 0x86ff, 0x11b8, 0x0804, 0x20cb,
-	0xa680, 0x8b55, 0x620c, 0x2202, 0x080c, 0x1d4e, 0x8630, 0xa68e,
-	0x001e, 0x0904, 0x20e1, 0x786c, 0xa065, 0x1d28, 0x7808, 0xa602,
-	0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0006, 0x1a04,
-	0x20e1, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8,
-	0x2011, 0x8b55, 0x2009, 0x8b4e, 0x26a8, 0x211c, 0x2204, 0x201a,
-	0x8108, 0x8210, 0x1f04, 0x20ad, 0xa685, 0x8030, 0x70c2, 0x681b,
-	0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091,
-	0x8001, 0xa006, 0x2009, 0x8b75, 0x200a, 0x203a, 0x0005, 0x7810,
-	0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c, 0x21ad, 0x1904, 0x21c9,
-	0x786c, 0xa065, 0x1904, 0x207b, 0x2091, 0x8000, 0x7810, 0xa084,
-	0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804,
-	0x21c9, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994, 0x70d4, 0xa102,
-	0x0228, 0x0168, 0x7b90, 0xa302, 0x1150, 0x0010, 0x8002, 0x1138,
-	0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0005, 0xa184,
-	0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
-	0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a,
-	0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0130, 0x7aa4, 0xa211,
-	0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030, 0x7003, 0x0000,
-	0x2009, 0x8b54, 0x260a, 0x8109, 0x2198, 0x2104, 0xd084, 0x0108,
-	0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603, 0x7012, 0x7007,
-	0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, 0x1208, 0xa006, 0x2028,
-	0x7974, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004,
-	0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x797c,
-	0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0120, 0x7b84, 0xa319,
-	0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x01d0,
-	0x7d10, 0x2031, 0x8b54, 0x2634, 0x78a8, 0x8000, 0x78aa, 0xd08c,
-	0x1138, 0x7007, 0x0006, 0x7004, 0xd094, 0x1de8, 0x0804, 0x20e3,
-	0x2069, 0x4347, 0x206b, 0x0003, 0x78ac, 0xa085, 0x0300, 0x78ae,
-	0xa006, 0x0048, 0x2030, 0x75d6, 0x2091, 0x4080, 0x7d96, 0x7d10,
-	0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001, 0x78aa, 0x7007, 0x0006,
-	0x263a, 0x7003, 0x0001, 0x711a, 0x721e, 0xd5c4, 0x0110, 0x7322,
-	0x7426, 0x0005, 0x6084, 0xa086, 0x0103, 0x11d8, 0x6114, 0x6018,
-	0xa105, 0x11b8, 0x2069, 0x0000, 0x6818, 0xd084, 0x1190, 0x600c,
-	0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091,
-	0x4080, 0x080c, 0x1d4e, 0x0e04, 0x21a0, 0x786c, 0xa065, 0x1d10,
-	0x0005, 0x0059, 0x1530, 0x786c, 0xa065, 0x19e0, 0x0410, 0x0029,
-	0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0, 0x6084, 0xa086, 0x0103,
-	0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004, 0x1138, 0x7804,
-	0xd0a4, 0x0120, 0x080c, 0x1d4e, 0xa006, 0x0005, 0x0079, 0x1118,
-	0xa085, 0x0001, 0x0005, 0x00b9, 0x1110, 0x2041, 0x0001, 0x7d10,
-	0x0005, 0x88ff, 0x0110, 0x2091, 0x4080, 0x0005, 0x7b90, 0x7994,
-	0x70d4, 0xa102, 0x1118, 0xa385, 0x0000, 0x0005, 0x0210, 0xa302,
-	0x0005, 0x8002, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c,
+	0x080c, 0x1b0a, 0x0138, 0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110,
+	0x0804, 0x13bc, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017,
+	0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061, 0x4680, 0xc1fd,
+	0x607b, 0x0000, 0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a,
+	0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22ae, 0x2091, 0x8001, 0x2041,
+	0x0021, 0x2049, 0x0005, 0x2051, 0x0030, 0x2091, 0x8000, 0x70c8,
+	0xa005, 0x0118, 0x60d0, 0xc0fd, 0x60d2, 0x080c, 0x1b93, 0x70c8,
+	0x6836, 0x8738, 0xa784, 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005,
+	0x2019, 0x0000, 0x72c8, 0xd284, 0x0128, 0x080c, 0x1b0a, 0x0138,
+	0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x72c8,
+	0x72ca, 0x78ac, 0xa084, 0x0003, 0x1508, 0x2039, 0x0000, 0xd284,
+	0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
+	0x080c, 0x1b7b, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a,
+	0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x1d90, 0xa7bc, 0xff00,
+	0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d50, 0x2091, 0x8000,
+	0x72c8, 0x2069, 0x0100, 0xd284, 0x1110, 0x2069, 0x0200, 0x6808,
+	0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004,
+	0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x18b2, 0x684b,
+	0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x18bb,
+	0x20a9, 0x00fa, 0x1f04, 0x18c2, 0x2079, 0x4600, 0x2009, 0x0018,
+	0x72c8, 0xd284, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061, 0x4680,
+	0xc1fd, 0x607b, 0x0000, 0x792a, 0x6063, 0x0001, 0x607f, 0x000f,
+	0x60a3, 0x0000, 0x60a4, 0x60ae, 0x60b2, 0x60d0, 0xd0b4, 0x0160,
+	0xc0b4, 0x60d2, 0x00c6, 0x60b4, 0xa065, 0x6008, 0xc0d4, 0x600a,
+	0x6018, 0x8001, 0x601a, 0x00ce, 0x60d0, 0xa084, 0x7eff, 0x60d2,
+	0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0108, 0x0005, 0x681b, 0x0054,
+	0x2091, 0x8001, 0x0005, 0x73cc, 0x080c, 0x186a, 0x69ec, 0x6a48,
+	0xa185, 0x1800, 0x684a, 0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021,
+	0x0004, 0x20a9, 0x09ff, 0x1f04, 0x190b, 0x8421, 0x1dd0, 0x8319,
+	0x1db0, 0x69ee, 0x6a4a, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118,
+	0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x71c4, 0x71c6, 0x6916,
+	0x81ff, 0x1110, 0x68a3, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
+	0x1110, 0x080c, 0x1c5b, 0x0005, 0x75d8, 0x74dc, 0x75da, 0x74de,
+	0x0010, 0xa02e, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
+	0x72ce, 0x2079, 0x4600, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c,
+	0x1b58, 0x0904, 0x1a3d, 0x20a9, 0x0005, 0x20a1, 0x4614, 0x2091,
+	0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0040, 0x080c, 0x1d24,
+	0x0120, 0x080c, 0x1b60, 0x0804, 0x1a3d, 0x6004, 0xa08c, 0x00ff,
+	0xa18e, 0x0009, 0x1120, 0x0006, 0x080c, 0x205f, 0x000e, 0xa084,
+	0xff00, 0x8007, 0x8009, 0x0904, 0x19e1, 0x00c6, 0x2c68, 0x080c,
+	0x1b58, 0x05a8, 0x2c00, 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000,
+	0x00ce, 0x00c6, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
+	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
+	0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0904, 0x19e0, 0x2009,
+	0x0040, 0x080c, 0x1d24, 0x15a0, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x0002, 0x1168, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a, 0x1120,
+	0x0016, 0x080c, 0x205c, 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce,
+	0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce, 0x609f, 0x0000, 0x080c,
+	0x1a41, 0x2009, 0x0018, 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086,
+	0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
+	0x080c, 0x1b15, 0x000e, 0x7812, 0x080c, 0x1b60, 0x0804, 0x1a3d,
+	0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce, 0x609f, 0x0000,
+	0x080c, 0x1a41, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003,
+	0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
+	0x080c, 0x1b15, 0x000e, 0x7812, 0x080c, 0x1b60, 0x0804, 0x1a3d,
+	0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1b0a, 0x01f0, 0x0018,
+	0x080c, 0x1aff, 0x01d0, 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087,
+	0x0103, 0x601b, 0x0021, 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff,
+	0x0110, 0xc0c5, 0x7812, 0x080c, 0x1b15, 0x000e, 0x7812, 0x080c,
+	0x1b60, 0x2001, 0x4007, 0x0804, 0x13bc, 0x74c4, 0x73c8, 0x72cc,
+	0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc, 0x1118,
+	0x2071, 0x4640, 0x0018, 0x2071, 0x4680, 0xc1fd, 0x792a, 0x7063,
+	0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, 0x746e, 0x7072,
+	0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, 0x611c, 0xa184,
+	0x0060, 0x0110, 0x080c, 0x3fc1, 0x00ee, 0x6596, 0x65a6, 0x669a,
+	0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000,
+	0x080c, 0x22ae, 0x2091, 0x8001, 0x0005, 0x70c3, 0x4005, 0x0804,
+	0x13bd, 0x20a9, 0x0005, 0x2099, 0x4614, 0x2091, 0x8000, 0x530a,
+	0x2091, 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000,
+	0xa5a9, 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0804,
+	0x13ba, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c,
+	0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000,
+	0x1118, 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, 0x70ca, 0x0804,
+	0x13bd, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x1a04, 0x13b3,
+	0x7966, 0x0804, 0x13ba, 0x7964, 0x71c6, 0x0804, 0x13ba, 0x7900,
+	0x71c6, 0x71c4, 0x7902, 0x0804, 0x13ba, 0x7900, 0x71c6, 0x0804,
+	0x13ba, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c,
+	0x0230, 0x8210, 0x810c, 0x810c, 0x0210, 0x8210, 0x810c, 0x81ff,
+	0x1904, 0x13b4, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd,
+	0x7912, 0x2009, 0x0021, 0x2019, 0x0003, 0xd284, 0x01c0, 0x8108,
+	0x2019, 0x0041, 0x2011, 0x8e4e, 0x2312, 0x2019, 0x0042, 0x8210,
+	0x2312, 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210,
+	0x2312, 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011,
+	0x8e53, 0x2112, 0x2011, 0x8e73, 0x2312, 0x7904, 0x7806, 0x0804,
+	0x13b9, 0x7804, 0x70c6, 0x0804, 0x13ba, 0x71c4, 0xd1fc, 0x1118,
+	0x2011, 0x4ac0, 0x0010, 0x2011, 0x4b40, 0x8107, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc,
+	0x0110, 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, 0x0001, 0x6b0c,
+	0x6800, 0x70da, 0x0804, 0x13b7, 0x7814, 0xd0f4, 0x0130, 0x2001,
+	0x4007, 0x70db, 0x0000, 0xa005, 0x0048, 0xd0fc, 0x0130, 0x2001,
+	0x4007, 0x70db, 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7814,
+	0xd0f4, 0x0130, 0x2001, 0x4007, 0x70db, 0x0000, 0xa005, 0x0008,
+	0xa006, 0x0005, 0x7814, 0xd0fc, 0x0130, 0x2001, 0x4007, 0x70db,
+	0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7112, 0x721a, 0x731e,
+	0x7810, 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108,
+	0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084,
+	0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140,
+	0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018,
+	0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
+	0x7d10, 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008,
+	0xd0fc, 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, 0x711a, 0x721e,
+	0x7d10, 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, 0x01e0, 0x0005,
+	0x7848, 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, 0x0000, 0x0005,
+	0x00f6, 0x2079, 0x4600, 0x7848, 0x2062, 0x2c00, 0xa005, 0x1110,
+	0x080c, 0x254c, 0x784a, 0x00fe, 0x0005, 0x2011, 0x9000, 0x7a4a,
+	0x7bc4, 0x8319, 0x0128, 0xa280, 0x0032, 0x2012, 0x2010, 0x0cc8,
+	0x2013, 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, 0x1118, 0x2011,
+	0x4bc0, 0x0010, 0x2011, 0x6bc0, 0xa784, 0x0f00, 0x800b, 0xa784,
+	0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa268,
+	0x002e, 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, 0x2a00, 0x682e,
+	0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, 0xd7fc, 0x1128,
+	0x2009, 0x4652, 0x2071, 0x4640, 0x0020, 0x2009, 0x4692, 0x2071,
+	0x4680, 0x210c, 0x6804, 0xa005, 0x0148, 0xa116, 0x1138, 0x2060,
+	0x6000, 0x6806, 0x0016, 0x200b, 0x0000, 0x0018, 0x2009, 0x0000,
+	0x0016, 0x6804, 0xa065, 0x0178, 0x6000, 0x6806, 0x0421, 0x080c,
+	0x1d95, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x6812, 0x1d88,
+	0x7910, 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, 0x2d00, 0x2060,
+	0x080c, 0x2693, 0x00ee, 0x0005, 0xa065, 0x0160, 0x2008, 0x609c,
+	0xa005, 0x0128, 0x2062, 0x609f, 0x0000, 0xa065, 0x0cc0, 0x7848,
+	0x794a, 0x2062, 0x0005, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
+	0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
+	0x601a, 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, 0x1128, 0x2071,
+	0x4640, 0x2031, 0x46c0, 0x0020, 0x2071, 0x4680, 0x2031, 0x48c0,
+	0x704c, 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, 0x8000, 0x704e,
+	0xa006, 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x4640,
+	0x0010, 0x2079, 0x4680, 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6804,
+	0x780a, 0xa065, 0x05f0, 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000,
+	0xa065, 0x05b8, 0x6010, 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0,
+	0x2c28, 0x7848, 0xac06, 0x1108, 0x0448, 0x6804, 0xac06, 0x1140,
+	0x6000, 0x2060, 0x6806, 0xa005, 0x1118, 0x6803, 0x0000, 0x0048,
+	0x6400, 0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00,
+	0x6802, 0x2560, 0x080c, 0x1be3, 0x601b, 0x0005, 0x6023, 0x0020,
+	0x00fe, 0x080c, 0x1d95, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810,
+	0x8001, 0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff,
+	0xa005, 0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc,
+	0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
+	0x2091, 0x8000, 0x080c, 0x1b93, 0x8738, 0xa784, 0x001f, 0x1dd0,
+	0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90,
+	0x2091, 0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8e74, 0x210c,
+	0xa10d, 0x0118, 0xa065, 0x0804, 0x207a, 0x2061, 0x0000, 0x6018,
+	0xd084, 0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc,
+	0x2069, 0x4640, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4680, 0xc7fd,
+	0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005,
+	0x1108, 0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x254c, 0x0002,
+	0x1cb8, 0x1cbb, 0x1cc1, 0x1cc5, 0x1cb9, 0x1cc9, 0x1cb9, 0x1cb9,
+	0x1cb9, 0x1ccf, 0x1cfb, 0x1cfe, 0x1d03, 0x1d0c, 0x1cb9, 0x1cb9,
+	0x0005, 0x080c, 0x254c, 0x080c, 0x1c5b, 0x2001, 0x8001, 0x0804,
+	0x1d15, 0x2001, 0x8003, 0x0804, 0x1d15, 0x2001, 0x8004, 0x0804,
+	0x1d15, 0x080c, 0x1c5b, 0x2001, 0x8006, 0x0804, 0x1d15, 0x2091,
+	0x8000, 0x0076, 0xd7fc, 0x1128, 0x2069, 0x4640, 0x2039, 0x0009,
+	0x0020, 0x2069, 0x4680, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000,
+	0x0128, 0x000e, 0x6f1e, 0x2091, 0x8001, 0x0005, 0x6870, 0x007e,
+	0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
+	0x080c, 0x1b93, 0x8738, 0xa784, 0x001f, 0x1dd0, 0x2091, 0x8001,
+	0x2001, 0x800a, 0x00d0, 0x2001, 0x800c, 0x00b8, 0x080c, 0x1c5b,
+	0x2001, 0x800d, 0x0090, 0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0,
+	0x70c6, 0x2001, 0x800e, 0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008,
+	0x78e8, 0x70c6, 0x2001, 0x800f, 0x0000, 0x70c2, 0xd7fc, 0x1118,
+	0x70db, 0x0000, 0x0010, 0x70db, 0x0001, 0x2061, 0x0000, 0x601b,
+	0x0001, 0x2091, 0x4080, 0x0005, 0xac80, 0x0001, 0x81ff, 0x0518,
+	0x2099, 0x0030, 0x20a0, 0x700c, 0xa084, 0x07ff, 0x0100, 0x7018,
+	0x0006, 0x701c, 0x0006, 0x7020, 0x0006, 0x7024, 0x0006, 0x7112,
+	0x81ac, 0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007,
+	0x0001, 0x7008, 0x800b, 0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0,
+	0x1110, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x000e,
+	0x7026, 0x000e, 0x7022, 0x000e, 0x701e, 0x000e, 0x701a, 0x0005,
+	0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201,
+	0x6803, 0xfd20, 0x6807, 0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008,
+	0xa290, 0x0004, 0x8109, 0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520,
+	0x2029, 0x0001, 0x7814, 0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019,
+	0x0c0a, 0x2021, 0x000a, 0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c,
+	0x0070, 0x70ec, 0xd0e4, 0x1128, 0x2019, 0x180c, 0x2021, 0x000c,
+	0x0030, 0x2019, 0x1809, 0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a,
+	0x6c0e, 0x6d1e, 0x6807, 0x0038, 0x0005, 0x6004, 0x6086, 0x2c08,
+	0x2063, 0x0000, 0x7868, 0xa005, 0x796a, 0x0110, 0x2c02, 0x0008,
+	0x796e, 0x0005, 0x00c6, 0x2061, 0x4600, 0x6887, 0x0103, 0x2d08,
+	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008,
+	0x616e, 0x00ce, 0x0005, 0x2091, 0x8000, 0x2c04, 0x786e, 0xa005,
+	0x1108, 0x786a, 0x2091, 0x8001, 0x609c, 0xa005, 0x0188, 0x00c6,
+	0x2060, 0x2008, 0x609c, 0xa005, 0x0138, 0x2062, 0x609f, 0x0000,
+	0xa065, 0x609c, 0xa005, 0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce,
+	0x7848, 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x1110, 0x080c,
+	0x254c, 0x784a, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
+	0x818e, 0x1208, 0xa200, 0x1f04, 0x1ddf, 0x8086, 0x818e, 0x0005,
+	0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213,
+	0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x1def, 0x0028, 0xa11a,
+	0x2308, 0x8210, 0x1f04, 0x1def, 0x0006, 0x3200, 0xa084, 0xefff,
+	0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000,
+	0x0cb8, 0x7d74, 0x70d0, 0xa506, 0x0904, 0x1ebd, 0x7810, 0x2050,
+	0x080c, 0x1b58, 0x0904, 0x1ebd, 0xa046, 0x7970, 0x2500, 0x8000,
+	0xa112, 0x2009, 0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118,
+	0x8840, 0x2009, 0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099,
+	0x0030, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000,
+	0x88ff, 0x0110, 0x080c, 0x1b58, 0x7008, 0xd0fc, 0x0de8, 0x7007,
+	0x0002, 0x2091, 0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff,
+	0x1120, 0x88ff, 0x0904, 0x1eaa, 0x0050, 0x2c00, 0x788e, 0x20a9,
+	0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0804, 0x1eaa, 0xa046,
+	0x7218, 0x731c, 0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040,
+	0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e,
+	0xdac4, 0x0118, 0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904,
+	0x1eaa, 0x8cff, 0x0110, 0x080c, 0x1b60, 0x00ce, 0x080c, 0x1b60,
+	0xa046, 0x7888, 0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c,
+	0x7b78, 0xdac4, 0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004,
+	0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
+	0x721a, 0x731e, 0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014,
+	0xd0fc, 0x1118, 0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x2091,
+	0x8000, 0x681f, 0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060,
+	0x0c70, 0x788b, 0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091,
+	0x8001, 0x0098, 0x00ce, 0x788b, 0x0000, 0x080c, 0x2035, 0x6004,
+	0xa084, 0x000f, 0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004,
+	0xa084, 0x000f, 0x0019, 0x0804, 0x1e09, 0x0005, 0x0002, 0x1ecf,
+	0x1eea, 0x1f03, 0x1ecf, 0x1f10, 0x1ee0, 0x1ecf, 0x1ecf, 0x1ecf,
+	0x1ee8, 0x1f01, 0x1ecf, 0x1ecf, 0x1ecf, 0x1ecf, 0x1ecf, 0x2039,
+	0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c,
+	0x1f4c, 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c, 0x2021, 0x0005,
+	0x78bc, 0xd0c4, 0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030,
+	0x080c, 0x205f, 0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000,
+	0x6004, 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c,
+	0x1f4c, 0x0120, 0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f67,
+	0x0005, 0x080c, 0x205c, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4,
+	0x1108, 0x0828, 0x080c, 0x1f4c, 0x1110, 0x0804, 0x1f67, 0x0005,
+	0x78bc, 0xd0c4, 0x0110, 0x0804, 0x1ecf, 0x78bf, 0x0000, 0x6714,
+	0x2011, 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188,
+	0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc,
+	0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108,
+	0x00c0, 0x080c, 0x1b7b, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000,
+	0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010,
+	0x2091, 0x8001, 0x1f04, 0x1f34, 0x8211, 0x0118, 0x20a9, 0x0100,
+	0x0c58, 0x080c, 0x1b60, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d,
+	0x2c00, 0x78b6, 0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002,
+	0x78b8, 0xad06, 0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130,
+	0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6,
+	0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2,
+	0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c,
+	0x3fc1, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4680,
+	0xd7fc, 0x1110, 0x2071, 0x4640, 0xa784, 0x0f00, 0x800b, 0xa784,
+	0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0,
+	0xa168, 0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0x71c4, 0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138,
+	0xd7fc, 0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08,
+	0xd684, 0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1be3,
+	0x2091, 0x8000, 0x080c, 0x1d95, 0x2091, 0x8001, 0x7814, 0xd0c4,
+	0x0904, 0x201f, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x201f,
+	0xd0fc, 0x1110, 0x0804, 0x201f, 0x601b, 0x0021, 0x0804, 0x201f,
+	0x6024, 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814,
+	0xa202, 0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c,
+	0x78ba, 0x609f, 0x0000, 0x080c, 0x2021, 0x0804, 0x201f, 0x2c08,
+	0xd9fc, 0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084,
+	0x0002, 0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304,
+	0x6002, 0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00,
+	0x2060, 0x080c, 0x2693, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050,
+	0x6800, 0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160,
+	0x6003, 0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a,
+	0x6810, 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001,
+	0xd6b4, 0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1bf4, 0x00ee,
+	0x0005, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1d95,
+	0x2091, 0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f,
+	0x0000, 0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818,
+	0xd384, 0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278,
+	0xc384, 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84,
+	0x7222, 0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876,
+	0x70d2, 0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04,
+	0x205b, 0x2091, 0x4080, 0x0005, 0x2039, 0x2071, 0x0010, 0x2039,
+	0x2077, 0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810,
+	0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88,
+	0x0005, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015,
+	0x001b, 0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x2223, 0x21fe,
+	0x2082, 0x20f2, 0x2039, 0x8e74, 0x2734, 0x7d10, 0x00c0, 0x6084,
+	0xa086, 0x0103, 0x1904, 0x20dc, 0x6114, 0x6018, 0xa105, 0x0120,
+	0x86ff, 0x11d8, 0x0804, 0x20dc, 0x8603, 0xa080, 0x8e55, 0x620c,
+	0x2202, 0x8000, 0x6210, 0x2202, 0x080c, 0x1db3, 0x8630, 0xa68e,
+	0x000f, 0x0904, 0x215d, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602,
+	0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04,
+	0x215d, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8,
+	0x2011, 0x8e55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684,
+	0x1130, 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685,
+	0x8020, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084,
+	0xffcf, 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810,
+	0xc0ad, 0x7812, 0x0804, 0x215d, 0x263a, 0x080c, 0x2229, 0x1904,
+	0x2245, 0x786c, 0xa065, 0x1904, 0x2087, 0x2091, 0x8000, 0x7810,
+	0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001,
+	0x0804, 0x2245, 0x2039, 0x8e74, 0x2734, 0x7d10, 0x00a0, 0x6084,
+	0xa086, 0x0103, 0x1904, 0x2147, 0x6114, 0x6018, 0xa105, 0x0120,
+	0x86ff, 0x11b8, 0x0804, 0x2147, 0xa680, 0x8e55, 0x620c, 0x2202,
+	0x080c, 0x1db3, 0x8630, 0xa68e, 0x001e, 0x0904, 0x215d, 0x786c,
+	0xa065, 0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a,
+	0x0005, 0xa682, 0x0006, 0x1a04, 0x215d, 0x2091, 0x8000, 0x2069,
+	0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, 0x8e55, 0x2009, 0x8e4e,
+	0x26a8, 0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2129,
+	0xa685, 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810,
+	0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8e75,
+	0x200a, 0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a,
+	0x080c, 0x2229, 0x1904, 0x2245, 0x786c, 0xa065, 0x1904, 0x20f7,
+	0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad,
+	0x7812, 0x2091, 0x8001, 0x0804, 0x2245, 0x2091, 0x8000, 0x7007,
+	0x0004, 0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302,
+	0x1150, 0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812,
+	0x2091, 0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c,
 	0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004,
-	0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319,
-	0xa421, 0xa529, 0x2009, 0x0018, 0x6028, 0xa005, 0x0110, 0x2009,
-	0x0040, 0x080c, 0x1ab7, 0x01d0, 0x78a8, 0x8000, 0x78aa, 0xd08c,
-	0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069,
-	0x4380, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000, 0x78ac,
-	0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0068, 0x78ab, 0x0000,
-	0x080c, 0x1d4e, 0x7990, 0x7894, 0x8000, 0xa10a, 0x1208, 0xa006,
-	0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, 0x8001, 0x0005,
-	0x2138, 0xd7fc, 0x1118, 0x2009, 0x4359, 0x0010, 0x2009, 0x4399,
-	0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, 0x4380, 0x2079, 0x0100,
-	0xd7fc, 0x1120, 0x2009, 0x4340, 0x2079, 0x0200, 0x2104, 0xa086,
-	0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, 0x4345, 0x0010, 0x2009,
-	0x4385, 0x2104, 0xa005, 0x1130, 0x7830, 0xa084, 0x00c0, 0x1110,
-	0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, 0x0002, 0x2069, 0x4300,
-	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x22a9, 0x2071, 0x4380,
-	0x2079, 0x0100, 0x2021, 0x45bf, 0x784b, 0x000f, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x0118, 0x2019, 0x3c3b, 0x0030, 0x20a1, 0x012b,
-	0x2019, 0x3c3b, 0xd184, 0x0110, 0x20a1, 0x022b, 0x2304, 0xa005,
-	0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
-	0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af,
-	0x0000, 0x78af, 0x2020, 0x1f04, 0x2287, 0x7003, 0x0000, 0x0016,
-	0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, 0x080c, 0x23bd, 0x001e,
-	0x7020, 0xa084, 0x000f, 0xa085, 0x6300, 0x7806, 0x780f, 0x9000,
-	0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, 0x0308, 0x7456, 0x7053,
-	0x0000, 0x8109, 0x0140, 0x2071, 0x4340, 0x2079, 0x0200, 0x2021,
-	0x43bf, 0x0804, 0x2264, 0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc,
-	0x1110, 0x2011, 0x0201, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0,
-	0xa105, 0x2012, 0x001e, 0x080c, 0x23bd, 0x0005, 0x2011, 0x0101,
-	0xd3fc, 0x1110, 0x2011, 0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04,
-	0x22ce, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012,
-	0x0005, 0x2019, 0x0002, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213,
-	0x1f04, 0x22df, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
-	0x200a, 0x8319, 0x0118, 0x2009, 0x0201, 0x0c78, 0x0005, 0x2011,
-	0x0101, 0xd3fc, 0x1110, 0x2011, 0x0201, 0x20a9, 0x000c, 0x810b,
-	0x1f04, 0x22f7, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105,
-	0x2012, 0x0005, 0x2011, 0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202,
-	0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061,
-	0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003,
-	0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6,
+	0x8004, 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e,
+	0xd4c4, 0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226,
+	0x20a1, 0x0030, 0x7003, 0x0000, 0x2009, 0x8e54, 0x260a, 0x8109,
+	0x2198, 0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8,
+	0x53a6, 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000,
+	0xa10a, 0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140,
+	0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018,
+	0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
+	0xd4c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc,
+	0x0de8, 0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8e54, 0x2634,
+	0x78a8, 0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004,
+	0xd094, 0x1de8, 0x0804, 0x215f, 0x2069, 0x4647, 0x206b, 0x0003,
+	0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6,
+	0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091,
+	0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a,
+	0x721e, 0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086,
+	0x0103, 0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000,
+	0x6818, 0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3,
+	0x8020, 0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1db3, 0x0e04,
+	0x221c, 0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c,
+	0xa065, 0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8,
+	0x00e0, 0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a,
+	0xa086, 0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1db3,
+	0xa006, 0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9,
+	0x1110, 0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091,
+	0x4080, 0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385,
+	0x0000, 0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184,
+	0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
+	0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4,
+	0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018,
+	0x6028, 0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1b15, 0x01d0,
+	0x78a8, 0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118,
+	0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x2091, 0x8000, 0x681f,
+	0x0003, 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091,
+	0x8001, 0x0068, 0x78ab, 0x0000, 0x080c, 0x1db3, 0x7990, 0x7894,
+	0x8000, 0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071,
+	0x0010, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2009, 0x4658,
+	0x0010, 0x2009, 0x4698, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009,
+	0x4680, 0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4640, 0x2079,
+	0x0200, 0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009,
+	0x4645, 0x0010, 0x2009, 0x4685, 0x2104, 0xa005, 0x1130, 0x7830,
+	0xa084, 0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009,
+	0x0002, 0x2069, 0x4600, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+	0x2324, 0x2071, 0x4680, 0x2079, 0x0100, 0x2021, 0x48bf, 0x784b,
+	0x000f, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3e0f,
+	0x0030, 0x20a1, 0x012b, 0x2019, 0x3e0f, 0xd184, 0x0110, 0x20a1,
+	0x022b, 0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318,
+	0x2398, 0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020,
+	0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x2302,
+	0x7003, 0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd,
+	0x080c, 0x2443, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300,
+	0x7806, 0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b,
+	0x2f08, 0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4640,
+	0x2079, 0x0200, 0x2021, 0x46bf, 0x0804, 0x22df, 0x080c, 0x24fd,
+	0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201,
+	0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e,
+	0x080c, 0x2443, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011,
+	0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04, 0x234b, 0xa18c, 0x0e00,
+	0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002,
+	0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x235c, 0xa294,
+	0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118,
+	0x2009, 0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110,
+	0x2011, 0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x2374, 0xa18c,
+	0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011,
+	0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa084, 0xf0cf,
+	0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110,
+	0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a,
+	0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc,
+	0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022,
+	0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005, 0x00c6,
 	0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103,
-	0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae,
-	0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061,
-	0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4,
-	0xa28c, 0x0020, 0x0118, 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4,
-	0x1108, 0xc3ed, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce,
-	0x0005, 0x2091, 0x8000, 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904,
-	0x23a1, 0xd1fc, 0x0118, 0x2061, 0x8ad0, 0x0010, 0x2061, 0x89c0,
-	0x080c, 0x23a9, 0x0538, 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061,
-	0x89d0, 0x0010, 0x2061, 0x88c0, 0x00c6, 0x04d9, 0x0128, 0x00ce,
-	0x8c60, 0x1f04, 0x236c, 0x0468, 0x000e, 0xd1fc, 0x0128, 0xa082,
-	0x89d0, 0x2071, 0x4380, 0x0020, 0xa082, 0x88c0, 0x2071, 0x4340,
-	0x707a, 0x7176, 0x2001, 0x0004, 0x7066, 0x7083, 0x000f, 0x080c,
-	0x2228, 0x00a0, 0xd1fc, 0x1118, 0x2071, 0x4340, 0x0010, 0x2071,
-	0x4380, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2c00, 0x707e, 0x2001,
-	0x0006, 0x7066, 0x7083, 0x000f, 0x080c, 0x2228, 0x2001, 0x0000,
-	0x0010, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce,
-	0x0005, 0x2c04, 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140,
-	0x600c, 0xa206, 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020,
-	0x6000, 0x0c80, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016,
-	0x2079, 0x4380, 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4340,
-	0x2071, 0x0200, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110,
-	0x001e, 0x0060, 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d,
-	0x0800, 0xd0bc, 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe,
-	0x0005, 0x00e6, 0x2001, 0x4301, 0x2004, 0xd0ac, 0x1904, 0x2439,
-	0x68e4, 0xd0ac, 0x0904, 0x2439, 0xa084, 0x0006, 0x1904, 0x2439,
-	0x6014, 0xd0fc, 0x1118, 0x2071, 0x47c0, 0x0010, 0x2071, 0x4840,
-	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004,
-	0xa084, 0x000a, 0x15b0, 0x7108, 0xa194, 0xff00, 0x0590, 0xa18c,
-	0x00ff, 0x2001, 0x000a, 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106,
-	0x01a0, 0x2001, 0x0012, 0xa106, 0x0198, 0x2001, 0x0014, 0xa106,
-	0x0190, 0x2001, 0x0019, 0xa106, 0x0188, 0x2001, 0x0032, 0xa106,
-	0x0180, 0x0090, 0x2009, 0x000c, 0x0088, 0x2009, 0x0012, 0x0070,
-	0x2009, 0x0014, 0x0058, 0x2009, 0x0019, 0x0040, 0x2009, 0x0020,
-	0x0028, 0x2009, 0x003f, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205,
-	0x700a, 0x00ee, 0x0005, 0x0e04, 0x243b, 0x2091, 0x8000, 0x2071,
-	0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e, 0x2071, 0x0010,
-	0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a01, 0x70df,
-	0x0013, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0cf8,
-	0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592, 0x7496,
-	0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc, 0x1128,
-	0xa784, 0x007d, 0x1904, 0x3ace, 0x0871, 0xa49c, 0x000f, 0xa382,
-	0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418, 0x8507, 0xa084,
-	0x000f, 0x0002, 0x2a4f, 0x2b10, 0x2b38, 0x2d71, 0x30cc, 0x3112,
-	0x31a7, 0x3220, 0x32db, 0x33a6, 0x248d, 0x248a, 0x285b, 0x295c,
-	0x30a0, 0x248a, 0x080c, 0x243b, 0x0005, 0xa006, 0x0038, 0x7808,
-	0xc08d, 0x780a, 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060,
-	0xa005, 0x1904, 0x25d9, 0x7064, 0xa084, 0x0007, 0x0002, 0x24a7,
-	0x2513, 0x251b, 0x2524, 0x252d, 0x25bf, 0x2536, 0x2513, 0x7830,
-	0xd0bc, 0x1d10, 0x71d4, 0xd1b4, 0x1904, 0x24f0, 0x70a4, 0xa086,
-	0x0001, 0x09d0, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b,
-	0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d,
-	0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0,
-	0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804, 0x270a, 0x7060, 0xa005,
-	0x1904, 0x248c, 0x00c6, 0x00d6, 0x70b4, 0xa06d, 0x6800, 0xa065,
-	0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10,
-	0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa,
-	0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0804, 0x270a,
-	0x080c, 0x3a8d, 0x1904, 0x248c, 0x781b, 0x0068, 0x70bc, 0xa06d,
-	0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
-	0x7808, 0xc08d, 0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8,
-	0xa065, 0x68c0, 0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80,
-	0x0009, 0x7046, 0x0005, 0x080c, 0x3a8d, 0x1120, 0x781b, 0x0054,
-	0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, 0x2011, 0x000c,
-	0x0419, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128, 0x2011,
-	0x0006, 0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d, 0x1128,
-	0x2011, 0x000d, 0x0089, 0x7003, 0x0004, 0x0005, 0x080c, 0x3a8d,
-	0x1150, 0x2011, 0x0006, 0x0041, 0x707c, 0x707f, 0x0000, 0x2068,
-	0x704e, 0x7003, 0x0001, 0x0005, 0x7174, 0xc1fc, 0x8107, 0x7882,
-	0x789b, 0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, 0x2001, 0x0001,
-	0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d,
-	0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, 0x0020, 0x7178,
-	0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, 0x785b,
-	0x0004, 0x781b, 0x0113, 0x080c, 0x3aa0, 0x7083, 0x000f, 0x70d4,
-	0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, 0x70b8, 0xa065, 0x6008,
-	0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005,
-	0x7014, 0xa005, 0x1138, 0x70d4, 0xd0b4, 0x0128, 0x70b8, 0xac06,
-	0x1110, 0x0c29, 0x0005, 0x0016, 0x71a4, 0xa186, 0x0001, 0x0528,
-	0x00d6, 0x0026, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068,
-	0x6800, 0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, 0x0cc8, 0x00c6,
-	0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068, 0x6800, 0x2060,
-	0x6008, 0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, 0x0041, 0x0cb0,
-	0x70a7, 0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, 0x0005, 0xade8,
-	0x0005, 0x70ac, 0xad06, 0x1110, 0x70a8, 0x2068, 0x0005, 0x080c,
-	0x3a8d, 0x1904, 0x248c, 0x707c, 0x2068, 0x7774, 0x080c, 0x396d,
-	0x2c50, 0x080c, 0x3b28, 0x789b, 0x0080, 0x6814, 0xa084, 0x001f,
-	0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0804,
-	0x270f, 0x080c, 0x3a8d, 0x1904, 0x248c, 0x789b, 0x0080, 0x7060,
-	0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6,
-	0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
-	0x601a, 0x00ce, 0x080c, 0x396d, 0x2c50, 0x080c, 0x3b28, 0x6824,
-	0xa005, 0x0130, 0xa082, 0x0006, 0x0208, 0x0010, 0x6827, 0x0005,
-	0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041,
-	0x0001, 0x2001, 0x0003, 0x0804, 0x270f, 0xc28d, 0x72d6, 0x72c0,
-	0xa200, 0xa015, 0x7154, 0x8108, 0xa12a, 0x0208, 0x71c0, 0x2164,
-	0x6504, 0x85ff, 0x1170, 0x7156, 0x8421, 0x1da8, 0x70d4, 0xd08c,
-	0x0128, 0x70d0, 0xa005, 0x1110, 0x70d3, 0x000a, 0x0005, 0x2200,
-	0x0c90, 0x70d4, 0xc08c, 0x70d6, 0x70d3, 0x0000, 0x6034, 0xa005,
-	0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, 0x1d80, 0xa784,
-	0x0021, 0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, 0x0004, 0x0d38,
-	0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, 0xa784, 0x0100,
-	0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, 0x670a, 0x2568,
-	0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0128, 0x601c,
-	0xa302, 0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, 0x2d58, 0x2c50,
-	0x7156, 0xd7bc, 0x1110, 0x7028, 0x6022, 0xc7bc, 0x670a, 0x68c0,
-	0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, 0x6b14, 0xa39c,
-	0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, 0x0110, 0xa39c,
-	0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, 0x000e, 0x1904,
-	0x26c1, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001,
-	0x1178, 0x70d4, 0xd0b4, 0x1160, 0x7000, 0xa082, 0x0002, 0x1240,
-	0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, 0x0804, 0x2708,
-	0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, 0x70ac, 0xa606,
-	0x1108, 0x76a8, 0x76b2, 0x2c3a, 0x8738, 0x2d3a, 0x8738, 0x283a,
-	0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, 0x0150, 0x2091,
-	0x8000, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000,
-	0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, 0x1904, 0x2612,
-	0x0005, 0xd1dc, 0x0904, 0x35d5, 0x2029, 0x0020, 0xd69c, 0x1120,
-	0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108,
-	0xa18c, 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0188, 0x6014,
-	0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, 0x2a60, 0x6008,
-	0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, 0x2612, 0x0005,
-	0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008, 0xc0d5,
-	0x600a, 0x77a4, 0xa786, 0x0001, 0x1904, 0x2698, 0x70d4, 0xd0b4,
-	0x1904, 0x2698, 0x7000, 0xa082, 0x0002, 0x1a04, 0x2698, 0x7830,
-	0xd0bc, 0x1904, 0x2698, 0x789b, 0x0080, 0x7baa, 0x7daa, 0x79aa,
-	0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, 0x0008, 0x0006,
-	0x2960, 0x6104, 0x2a60, 0x080c, 0x3b3b, 0x1590, 0xa184, 0x0018,
-	0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x3776, 0x1548, 0xa184,
-	0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, 0x080c, 0x3696,
-	0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, 0x0800, 0x0178,
-	0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d,
-	0x0010, 0x6106, 0x00ce, 0x080c, 0x3776, 0x1150, 0x69a0, 0xa184,
-	0x0200, 0x0118, 0x080c, 0x36d9, 0x0018, 0xa184, 0x0400, 0x19f0,
-	0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, 0xff00, 0x810f,
-	0x080c, 0x231f, 0x002e, 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0128,
-	0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6,
-	0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc,
-	0x0168, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0328, 0xa08a,
-	0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, 0x3518,
-	0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b,
-	0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0,
-	0xa286, 0x0020, 0x1508, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba,
-	0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286, 0x0002,
-	0x0904, 0x27e0, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa498, 0x0005,
-	0x70ac, 0xa306, 0x1108, 0x73a8, 0x73b6, 0xa286, 0x0010, 0x0904,
-	0x248c, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, 0x19e0, 0xa286,
-	0x0002, 0x1904, 0x27f7, 0x080c, 0x3a8d, 0x19a8, 0x6814, 0xc0fc,
-	0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4, 0x785a,
-	0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001,
-	0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, 0x70d4, 0xa084,
-	0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, 0x705a, 0x68bc,
-	0x7042, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
-	0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d,
-	0x2091, 0x8000, 0x2090, 0x70a4, 0xa005, 0x1108, 0x0005, 0x8421,
-	0x0de8, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0804, 0x2612, 0xa286,
-	0x0010, 0x1560, 0x080c, 0x3a8d, 0x1904, 0x278b, 0x6814, 0xc0fc,
-	0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6,
-	0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a4,
-	0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, 0x1108,
-	0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002,
-	0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, 0x6bb4, 0xa39d,
-	0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94, 0x7bd6,
-	0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, 0x2900, 0x705a,
-	0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0170, 0x70d4,
-	0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, 0x0000, 0x0010,
-	0x2009, 0x0001, 0xa284, 0x000f, 0x0023, 0xad80, 0x0009, 0x7046,
-	0x0005, 0x2859, 0x3fb8, 0x3fb8, 0x3fa6, 0x3fb8, 0x2859, 0x2859,
-	0x2859, 0x080c, 0x243b, 0x7808, 0xa084, 0xfffd, 0x780a, 0x00f6,
-	0x2079, 0x4300, 0x78ac, 0x00fe, 0xd084, 0x01c0, 0x7064, 0xa086,
-	0x0001, 0x1118, 0x7066, 0x0804, 0x293a, 0x7064, 0xa086, 0x0005,
-	0x1158, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817, 0x0000, 0x6820,
-	0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, 0x0000,
-	0x70a8, 0x70b2, 0x70b6, 0x080c, 0x256f, 0x0156, 0x2011, 0x0004,
-	0x7164, 0xa186, 0x0001, 0x0170, 0xa186, 0x0007, 0x1118, 0x701f,
-	0x0005, 0x0040, 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0c5,
-	0x70d6, 0x0010, 0x7067, 0x0000, 0x2001, 0x430a, 0x2004, 0xa084,
-	0x00ff, 0xa086, 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110,
-	0x70a7, 0x0001, 0x0066, 0x080c, 0x3d52, 0x20a9, 0x0010, 0x2039,
-	0x0000, 0x080c, 0x3861, 0xa7b8, 0x0100, 0x1f04, 0x28b1, 0x006e,
-	0x7000, 0x0002, 0x28ee, 0x28cc, 0x28cc, 0x28c4, 0x28ee, 0x28ee,
-	0x28ee, 0x28c2, 0x080c, 0x243b, 0x7060, 0xa005, 0x0538, 0xad06,
-	0x1118, 0x6800, 0x7062, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14,
-	0x080c, 0x396d, 0x6008, 0xc0d4, 0x600a, 0x080c, 0x35ab, 0x0020,
-	0x705c, 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818,
-	0xd0fc, 0x0108, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820,
-	0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d3d, 0xb284, 0x0800,
-	0x0118, 0x2021, 0x8ad0, 0x0010, 0x2021, 0x89c0, 0x080c, 0x293f,
-	0xb284, 0x0800, 0x0118, 0x2021, 0x4398, 0x0010, 0x2021, 0x4358,
-	0x04f1, 0x20a9, 0x0101, 0xb284, 0x0800, 0x0118, 0x2021, 0x89d0,
-	0x0010, 0x2021, 0x88c0, 0x0499, 0x8420, 0x1f04, 0x290b, 0xb284,
-	0x0600, 0x0118, 0x2061, 0x48c0, 0x0010, 0x2061, 0x68c0, 0x2021,
+	0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020, 0x0118,
+	0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed, 0x62ae,
+	0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091, 0x8000,
+	0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2427, 0xd1fc, 0x0118,
+	0x2061, 0x8dd0, 0x0010, 0x2061, 0x8cc0, 0x080c, 0x242f, 0x0560,
+	0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8cd0, 0x0010, 0x2061,
+	0x8bc0, 0x00c6, 0x080c, 0x242f, 0x0128, 0x00ce, 0x8c60, 0x1f04,
+	0x23e9, 0x04a8, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8cd0, 0x2071,
+	0x4680, 0x0020, 0xa082, 0x8bc0, 0x2071, 0x4640, 0x7076, 0x7172,
+	0x2138, 0x2001, 0x0004, 0x7062, 0x707f, 0x000f, 0x71d0, 0xc1c4,
+	0x71d2, 0x080c, 0x22a4, 0x00c0, 0xd1fc, 0x1118, 0x2071, 0x4640,
+	0x0010, 0x2071, 0x4680, 0x6020, 0xc0dd, 0x6022, 0x7172, 0x2138,
+	0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, 0x000f, 0x71d0,
+	0xc1c4, 0x71d2, 0x080c, 0x22a4, 0x2001, 0x0000, 0x0010, 0x2001,
+	0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005, 0x2c04,
+	0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c, 0xa206,
+	0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000, 0x0c80,
+	0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079, 0x4680,
+	0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4640, 0x2071, 0x0200,
+	0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e, 0x0060,
+	0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800, 0xd0bc,
+	0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005, 0x2001,
+	0x4601, 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120, 0xa084,
+	0x0006, 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036, 0x2018,
+	0x2071, 0x4b40, 0xd0fc, 0x1110, 0x2071, 0x4ac0, 0x8007, 0xa084,
+	0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084, 0x000a,
+	0x1904, 0x24fa, 0x7108, 0xa194, 0xff00, 0x0904, 0x24fa, 0xa18c,
+	0x00ff, 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085, 0x003a,
+	0x7006, 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a, 0xa102,
+	0x16d0, 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084, 0x00ff,
+	0x701e, 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a, 0xa106,
+	0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012, 0xa106,
+	0x0198, 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019, 0xa106,
+	0x0188, 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009, 0x000c,
+	0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0, 0x2009,
+	0x0019, 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f, 0x0058,
+	0x2009, 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009, 0x0019,
+	0x0010, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004, 0xa085,
+	0x000a, 0x7006, 0x2071, 0x4600, 0x7004, 0xd0bc, 0x0158, 0xd3fc,
+	0x1120, 0x73ea, 0x2071, 0x4640, 0x0018, 0x73ee, 0x2071, 0x4680,
+	0x701f, 0x000d, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x12a0,
+	0x2071, 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c, 0x810c,
+	0x2079, 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004, 0x8004,
+	0xa105, 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x254b, 0x2532,
+	0x254b, 0x2532, 0x2525, 0x253f, 0x2525, 0x7008, 0xa084, 0xc3ff,
+	0xa085, 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x3000,
+	0x780a, 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x700a,
+	0x7808, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005, 0x7008,
+	0xa084, 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084, 0xc3ff,
+	0xa085, 0x0c00, 0x780a, 0x0005, 0x0e04, 0x254c, 0x2091, 0x8000,
+	0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e, 0x2071,
+	0x0010, 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a04,
+	0x70df, 0x0020, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
+	0x0cf8, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a, 0x758e,
+	0x7492, 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc,
+	0x1128, 0xa784, 0x007d, 0x1904, 0x3c74, 0x0871, 0xa49c, 0x000f,
+	0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418, 0x8507,
+	0xa084, 0x000f, 0x0002, 0x2b49, 0x2c34, 0x2c72, 0x2ed8, 0x3256,
+	0x32ad, 0x3353, 0x33e2, 0x34b6, 0x3588, 0x259e, 0x259b, 0x2970,
+	0x2a56, 0x322a, 0x259b, 0x080c, 0x254c, 0x0005, 0xa006, 0x0038,
+	0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042, 0x70ce,
+	0x705c, 0xa005, 0x1904, 0x26ec, 0x7060, 0xa084, 0x0007, 0x0002,
+	0x25b8, 0x2626, 0x262e, 0x2637, 0x2640, 0x26d2, 0x2649, 0x2626,
+	0x7830, 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4, 0x1904,
+	0x2603, 0x70a0, 0xa086, 0x0001, 0x09c0, 0x70b0, 0xa06d, 0x6800,
+	0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045,
+	0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc,
+	0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804,
+	0x281f, 0x705c, 0xa005, 0x1904, 0x259d, 0x00c6, 0x00d6, 0x70b0,
+	0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa,
+	0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001,
+	0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001,
+	0x0020, 0x0804, 0x281f, 0x080c, 0x3c33, 0x1904, 0x259d, 0x781b,
+	0x0068, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
+	0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc, 0x703e,
+	0xc1b4, 0x71d2, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x7003, 0x0002,
+	0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x080c, 0x3c33,
+	0x1120, 0x781b, 0x0054, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c33,
+	0x1128, 0x2011, 0x000c, 0x0419, 0x7003, 0x0004, 0x0005, 0x080c,
+	0x3c33, 0x1128, 0x2011, 0x0006, 0x00d1, 0x7003, 0x0004, 0x0005,
+	0x080c, 0x3c33, 0x1128, 0x2011, 0x000d, 0x0089, 0x7003, 0x0004,
+	0x0005, 0x080c, 0x3c33, 0x1150, 0x2011, 0x0006, 0x0041, 0x7078,
+	0x707b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0004, 0x0005, 0x7170,
+	0xc1fc, 0x8107, 0x7882, 0x789b, 0x0080, 0xa286, 0x000c, 0x1120,
+	0x7aaa, 0x2001, 0x0001, 0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0,
+	0x79aa, 0xa286, 0x000d, 0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038,
+	0x78ab, 0x0020, 0x7174, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b,
+	0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0113, 0x080c, 0x3c46,
+	0x707f, 0x000f, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6,
+	0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+	0x601a, 0x00ce, 0x0005, 0x7014, 0xa005, 0x1138, 0x70d0, 0xd0b4,
+	0x0128, 0x70b4, 0xac06, 0x1110, 0x0c29, 0x0005, 0x0016, 0x71a0,
+	0xa186, 0x0001, 0x0528, 0x00d6, 0x0026, 0x2100, 0x2011, 0x0001,
+	0xa212, 0x70b0, 0x2068, 0x6800, 0xac06, 0x0120, 0x8211, 0x01b0,
+	0x00c9, 0x0cc8, 0x00c6, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0,
+	0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a, 0x8211,
+	0x0110, 0x0041, 0x0cb0, 0x70a3, 0x0001, 0x00ce, 0x002e, 0x00de,
+	0x001e, 0x0005, 0xade8, 0x0005, 0x70a8, 0xad06, 0x1110, 0x70a4,
+	0x2068, 0x0005, 0x080c, 0x3c33, 0x1904, 0x259d, 0x7078, 0x2068,
+	0x7770, 0x080c, 0x3b6f, 0x2c50, 0x080c, 0x3cce, 0x789b, 0x0080,
+	0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001,
+	0x2001, 0x0004, 0x0804, 0x2824, 0x080c, 0x3c33, 0x1904, 0x259d,
+	0x789b, 0x0080, 0x705c, 0x2068, 0x6f14, 0x70d0, 0xd0b4, 0x0168,
+	0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x080c, 0x3b6f, 0x2c50,
+	0x080c, 0x3cce, 0x6824, 0xa005, 0x0130, 0xa082, 0x0006, 0x0208,
+	0x0010, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa,
+	0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0804, 0x2824,
+	0xc28d, 0x72d2, 0x72bc, 0xa200, 0xa015, 0x7150, 0x8108, 0xa12a,
+	0x0208, 0x71bc, 0x2164, 0x6504, 0x85ff, 0x1170, 0x7152, 0x8421,
+	0x1da8, 0x70d0, 0xd08c, 0x0128, 0x70cc, 0xa005, 0x1110, 0x70cf,
+	0x000a, 0x0005, 0x2200, 0x0c90, 0x70d0, 0xc08c, 0x70d2, 0x70cf,
+	0x0000, 0x6034, 0xa005, 0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0,
+	0xd7d4, 0x1d80, 0xa784, 0x0021, 0x1d68, 0xa784, 0x0002, 0x0130,
+	0xa784, 0x0004, 0x0d38, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218,
+	0x1d08, 0xa784, 0x0100, 0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc,
+	0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e,
+	0x6318, 0x0128, 0x601c, 0xa302, 0x0220, 0x0118, 0x0858, 0x83ff,
+	0x1948, 0x2d58, 0x2c50, 0x7152, 0xd7bc, 0x1120, 0x7028, 0x6022,
+	0x603a, 0x0010, 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100,
+	0x2a60, 0x2041, 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0,
+	0xd1fc, 0x0110, 0xd684, 0x0110, 0xa39c, 0xffbf, 0xd6a4, 0x0110,
+	0xa39d, 0x0020, 0xa684, 0x000e, 0x1904, 0x27d6, 0xc7a5, 0x670a,
+	0x2c00, 0x68c6, 0x77a0, 0xa786, 0x0001, 0x1178, 0x70d0, 0xd0b4,
+	0x1160, 0x7000, 0xa082, 0x0002, 0x1240, 0x7830, 0xd0bc, 0x1128,
+	0x789b, 0x0080, 0x7baa, 0x0804, 0x281d, 0x8739, 0x77a2, 0x2750,
+	0x77ac, 0xa7b0, 0x0005, 0x70a8, 0xa606, 0x1108, 0x76a4, 0x76ae,
+	0x2c3a, 0x8738, 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738,
+	0x253a, 0x7830, 0xd0bc, 0x0150, 0x2091, 0x8000, 0x2091, 0x303d,
+	0x70d0, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000,
+	0x0120, 0x8421, 0x2200, 0x1904, 0x2725, 0x0005, 0xd1dc, 0x0904,
+	0x37ce, 0x2029, 0x0020, 0xd69c, 0x1120, 0x8528, 0xd68c, 0x1108,
+	0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, 0x00ff, 0x70c8,
+	0xa160, 0x2c64, 0x8cff, 0x0188, 0x6014, 0xa706, 0x1dd0, 0x60b8,
+	0x8001, 0x60ba, 0x1d88, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a,
+	0x2200, 0x8421, 0x1904, 0x2725, 0x0005, 0x2a60, 0x610e, 0x69be,
+	0x2c00, 0x68c6, 0x8840, 0x6008, 0xc0d5, 0x600a, 0x77a0, 0xa786,
+	0x0001, 0x1904, 0x27ad, 0x70d0, 0xd0b4, 0x1904, 0x27ad, 0x7000,
+	0xa082, 0x0002, 0x1a04, 0x27ad, 0x7830, 0xd0bc, 0x1904, 0x27ad,
+	0x789b, 0x0080, 0x7baa, 0x7daa, 0x79aa, 0x2001, 0x0002, 0x0006,
+	0x6018, 0x8000, 0x601a, 0x0008, 0x0006, 0x2960, 0x6104, 0x2a60,
+	0x080c, 0x3ce1, 0x1590, 0xa184, 0x0018, 0x0180, 0xa184, 0x0010,
+	0x0118, 0x080c, 0x3977, 0x1548, 0xa184, 0x0008, 0x0138, 0x69a0,
+	0xa184, 0x0600, 0x1118, 0x080c, 0x3895, 0x00f8, 0x69a0, 0xa184,
+	0x1e00, 0x0528, 0xa184, 0x0800, 0x0178, 0x00c6, 0x2960, 0x6000,
+	0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x00ce,
+	0x080c, 0x3977, 0x1150, 0x69a0, 0xa184, 0x0200, 0x0118, 0x080c,
+	0x38da, 0x0018, 0xa184, 0x0400, 0x19f0, 0x69a0, 0xa184, 0x1000,
+	0x0130, 0x6914, 0xa18c, 0xff00, 0x810f, 0x080c, 0x239c, 0x002e,
+	0xa68c, 0x00e0, 0xa684, 0x0060, 0x0128, 0xa086, 0x0060, 0x1110,
+	0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, 0x0060, 0x2800,
+	0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0168, 0xc0fc, 0x7083,
+	0x0000, 0xa08a, 0x000d, 0x0328, 0xa08a, 0x000c, 0x7182, 0x2001,
+	0x000c, 0x800c, 0x7186, 0x78aa, 0x3518, 0x3340, 0x3428, 0x8000,
+	0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b, 0x0000, 0xad80, 0x000b,
+	0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0, 0xa286, 0x0020, 0x1508,
+	0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x6814,
+	0xc0fc, 0x8007, 0x7882, 0xa286, 0x0002, 0x0904, 0x28f5, 0x70a0,
+	0x8000, 0x70a2, 0x74b0, 0xa498, 0x0005, 0x70a8, 0xa306, 0x1108,
+	0x73a4, 0x73b2, 0xa286, 0x0010, 0x0904, 0x259d, 0x00de, 0x00ce,
+	0x0005, 0x7000, 0xa005, 0x19e0, 0xa286, 0x0002, 0x1904, 0x290c,
+	0x080c, 0x3c33, 0x19a8, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091,
+	0x8000, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
+	0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a,
+	0x0126, 0x00d6, 0x00c6, 0x70d0, 0xa084, 0x2e00, 0x2090, 0x00ce,
+	0x00de, 0x012e, 0x2900, 0x7056, 0x68bc, 0x703e, 0x7003, 0x0002,
+	0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x7830, 0xd0bc, 0x0140,
+	0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090,
+	0x70a0, 0xa005, 0x1108, 0x0005, 0x8421, 0x0de8, 0x724c, 0x70bc,
+	0xa200, 0xa015, 0x0804, 0x2725, 0xa286, 0x0010, 0x1560, 0x080c,
+	0x3c33, 0x1904, 0x28a0, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b,
+	0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+	0x78da, 0x7808, 0xc08d, 0x780a, 0x70a0, 0x8000, 0x70a2, 0x74b0,
+	0xa490, 0x0005, 0x70a8, 0xa206, 0x1108, 0x72a4, 0x72b2, 0x2900,
+	0x7056, 0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80,
+	0x0009, 0x7042, 0x0005, 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814,
+	0xc0fc, 0x8007, 0x7882, 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2,
+	0x7eda, 0x781b, 0x0068, 0x2900, 0x7056, 0x7202, 0x7808, 0xc08d,
+	0x780a, 0x2300, 0xa605, 0x0170, 0x70d0, 0xa084, 0x2e00, 0xa086,
+	0x2600, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, 0x0001, 0xa284,
+	0x000f, 0x0023, 0xad80, 0x0009, 0x7042, 0x0005, 0x296e, 0x41d9,
+	0x41d9, 0x41c7, 0x41d9, 0x296e, 0x296e, 0x296e, 0x080c, 0x254c,
+	0x7808, 0xa084, 0xfffd, 0x780a, 0x00f6, 0x2079, 0x4600, 0x78ac,
+	0x00fe, 0xd084, 0x01b0, 0x7060, 0xa086, 0x0001, 0x0904, 0x2a32,
+	0x7060, 0xa086, 0x0005, 0x1158, 0x7078, 0x2068, 0x681b, 0x0004,
+	0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7063,
+	0x0000, 0x70a3, 0x0000, 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x2682,
+	0x0156, 0x2011, 0x0004, 0x7160, 0xa186, 0x0001, 0x0160, 0xa186,
+	0x0007, 0x1118, 0x701f, 0x0005, 0x0030, 0x701f, 0x0001, 0x70d0,
+	0xc0c5, 0x70d2, 0x0000, 0x2001, 0x460a, 0x2004, 0xa084, 0x00ff,
+	0xa086, 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3,
+	0x0001, 0x0066, 0x080c, 0x3f26, 0x20a9, 0x0010, 0x2039, 0x0000,
+	0x080c, 0x3a66, 0xa7b8, 0x0100, 0x1f04, 0x29c0, 0x006e, 0x7000,
+	0x0002, 0x29fd, 0x29db, 0x29db, 0x29d3, 0x29fd, 0x29fd, 0x29fd,
+	0x29d1, 0x080c, 0x254c, 0x705c, 0xa005, 0x0538, 0xad06, 0x1118,
+	0x6800, 0x705e, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c,
+	0x3b6f, 0x6008, 0xc0d4, 0x600a, 0x080c, 0x37a4, 0x0020, 0x7058,
+	0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc,
+	0x0108, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084,
+	0x00ff, 0xc09d, 0x6822, 0x080c, 0x1da2, 0x2011, 0x0004, 0x74c8,
+	0xa4a0, 0x0100, 0x04b1, 0xaea0, 0x0017, 0x0499, 0x20a9, 0x0101,
+	0x74c8, 0x0479, 0x8420, 0x1f04, 0x2a09, 0x70c0, 0x2060, 0x2021,
 	0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016,
-	0x0006, 0x2011, 0x4302, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e,
-	0xa102, 0x0338, 0x6012, 0x1128, 0x2011, 0x4304, 0x2204, 0xc0a5,
-	0x2012, 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x291b, 0x8421,
-	0x1d00, 0x015e, 0x7003, 0x0000, 0x704f, 0x0000, 0x0005, 0x0046,
-	0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a, 0x6817,
-	0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820,
-	0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1d3d, 0x000e, 0x0c48,
-	0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310, 0x080c,
-	0x243b, 0x2300, 0x0002, 0x2966, 0x29e3, 0x29fd, 0xa282, 0x0002,
-	0x0110, 0x080c, 0x243b, 0x7064, 0x7067, 0x0000, 0x7083, 0x0000,
-	0x0022, 0x77d4, 0xc7c5, 0x77d6, 0x0002, 0x297d, 0x297d, 0x297f,
-	0x29b7, 0x35df, 0x297d, 0x29b7, 0x297d, 0x080c, 0x243b, 0x7774,
-	0x080c, 0x3861, 0x7774, 0xa7bc, 0x8f00, 0x080c, 0x396d, 0x6018,
-	0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x89c0, 0x0010, 0x2021,
-	0x8ad0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2a17, 0x01b8,
-	0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x88c0, 0x0010,
-	0x2021, 0x89d0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c,
-	0x2a17, 0x004e, 0x0118, 0x8420, 0x1f04, 0x29a2, 0x015e, 0x8738,
-	0xa784, 0x001f, 0x1990, 0x0804, 0x248f, 0x0804, 0x248f, 0x7774,
-	0x080c, 0x396d, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118, 0x2021,
-	0x89c0, 0x0010, 0x2021, 0x8ad0, 0x2009, 0x0005, 0x2011, 0x0020,
-	0x080c, 0x2a17, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118,
-	0x2021, 0x88c0, 0x0010, 0x2021, 0x89d0, 0x0046, 0x2009, 0x0005,
-	0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420, 0x1f04, 0x29d5,
-	0x015e, 0x0804, 0x248f, 0x2200, 0x0002, 0x29e8, 0x29ea, 0x29ea,
-	0x080c, 0x243b, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0110,
-	0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a, 0x7067, 0x0000,
-	0x70d4, 0xc0c5, 0x70d6, 0x0804, 0x3a3f, 0x2200, 0x0002, 0x2a04,
-	0x29ea, 0x2a02, 0x080c, 0x243b, 0x080c, 0x3d52, 0x7000, 0xa086,
-	0x0002, 0x1904, 0x356d, 0x080c, 0x35c5, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x080c, 0x355f, 0x0904, 0x356d, 0x0804, 0x248f, 0x2404,
-	0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814, 0xa706, 0x0118,
-	0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a, 0x6817, 0x0000,
-	0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084,
-	0x00ff, 0xa205, 0x6822, 0x080c, 0x1d3d, 0x2021, 0x4302, 0x241c,
-	0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128, 0x2021, 0x4304,
-	0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x080c,
-	0x258b, 0x080c, 0x35c5, 0x0005, 0xa085, 0x0001, 0x0ce0, 0x2300,
-	0x0002, 0x2a56, 0x2a54, 0x2abc, 0x080c, 0x243b, 0x78e4, 0xa005,
-	0x1708, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x248c, 0x0010,
-	0x0304, 0x248c, 0x2008, 0xa084, 0x0030, 0x1110, 0x0804, 0x30a0,
-	0x78ec, 0xa084, 0x0003, 0x0dd0, 0x2100, 0xa084, 0x0007, 0x0002,
-	0x2a9f, 0x2aa8, 0x2a95, 0x2a78, 0x3a83, 0x3a83, 0x2a78, 0x2ab2,
-	0x080c, 0x243b, 0x7000, 0xa086, 0x0004, 0x1190, 0x7064, 0xa086,
-	0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x295c,
-	0x7064, 0xa086, 0x0006, 0x0db0, 0x7064, 0xa086, 0x0004, 0x0d90,
-	0x79e4, 0x2001, 0x0003, 0x0804, 0x2daa, 0x6818, 0xd0fc, 0x0110,
-	0x681b, 0x001d, 0x080c, 0x3837, 0x781b, 0x006e, 0x0005, 0x6818,
-	0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3837, 0x0804, 0x3a61,
-	0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3837, 0x781b,
-	0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c,
-	0x3837, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, 0x7000,
-	0x0002, 0x248f, 0x2ac9, 0x2acb, 0x356d, 0x356d, 0x356d, 0x2ac9,
-	0x2ac9, 0x080c, 0x243b, 0x080c, 0x35c5, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x080c, 0x355f, 0x0904, 0x356d, 0x0804, 0x248f, 0x78e4,
-	0xa005, 0x1b04, 0x2a7a, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104,
-	0x2a7a, 0x0010, 0x0304, 0x2a7a, 0x2008, 0xa084, 0x0030, 0x1118,
-	0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, 0x2100,
-	0xa184, 0x0007, 0x0002, 0x2b02, 0x2b06, 0x2afd, 0x2afb, 0x3a83,
-	0x3a83, 0x2afb, 0x3a7d, 0x080c, 0x243b, 0x080c, 0x383d, 0x781b,
-	0x006e, 0x0005, 0x080c, 0x383d, 0x0804, 0x3a61, 0x080c, 0x383d,
-	0x781b, 0x00fa, 0x0005, 0x080c, 0x383d, 0x781b, 0x00cb, 0x0005,
-	0x2300, 0x0002, 0x2b17, 0x2b15, 0x2b19, 0x080c, 0x243b, 0x0804,
-	0x3220, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030,
-	0x0904, 0x3220, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3220, 0xa184,
-	0x0100, 0x0d98, 0xa184, 0x0007, 0x0002, 0x2b35, 0x2b06, 0x2a95,
-	0x3a3f, 0x3a83, 0x3a83, 0x3a3f, 0x3a7d, 0x080c, 0x3a4b, 0x0005,
-	0xa282, 0x0005, 0x0310, 0x080c, 0x243b, 0x7898, 0x2040, 0x2300,
-	0x0002, 0x2b44, 0x2d41, 0x2d4b, 0x2200, 0x0002, 0x2b60, 0x2b4d,
-	0x2b60, 0x2b4b, 0x2d25, 0x080c, 0x243b, 0x789b, 0x0018, 0x78a8,
-	0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04, 0x3809, 0xa08a,
-	0x0004, 0x1a04, 0x3809, 0x0002, 0x3809, 0x3809, 0x3809, 0x37bf,
-	0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148, 0x0804, 0x3809,
-	0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804, 0x33b2, 0xa184,
-	0x00ff, 0xa08a, 0x0010, 0x1a04, 0x3809, 0x0002, 0x2b88, 0x2b86,
-	0x2b9a, 0x2b9e, 0x2c3c, 0x3809, 0x3809, 0x2c3e, 0x3809, 0x3809,
-	0x2d21, 0x2d21, 0x3809, 0x3809, 0x3809, 0x2d23, 0x080c, 0x243b,
-	0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b,
-	0x00c6, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b, 0x001d, 0x0c90,
-	0x0804, 0x3a3f, 0x681b, 0x001d, 0x0804, 0x3831, 0x6920, 0x6922,
-	0xa684, 0x1800, 0x15e0, 0x6820, 0xd084, 0x1904, 0x2be7, 0x6818,
-	0xa086, 0x0008, 0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, 0xd6bc,
-	0x0558, 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d,
-	0x0718, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
-	0x789b, 0x0061, 0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, 0x3208,
-	0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b,
-	0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098,
-	0x53a6, 0x014e, 0x013e, 0x015e, 0x781b, 0x0071, 0x0005, 0xd6e4,
-	0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083, 0x0005, 0xa684,
-	0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, 0x7e5a,
-	0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084, 0x007f, 0xa108,
-	0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
-	0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000,
-	0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3d52, 0x080c, 0x3fb8,
-	0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c, 0x4083, 0x6ab0,
-	0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120, 0x2200, 0xa422,
-	0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde,
-	0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0080,
-	0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118, 0x080c, 0x3fb8,
-	0x0005, 0x080c, 0x3fe5, 0x0005, 0x080c, 0x243b, 0x0804, 0x2cbd,
-	0x00c6, 0x7058, 0x2060, 0x7aa8, 0xa294, 0x00ff, 0xa286, 0x0004,
-	0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, 0x0000,
-	0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x36f6, 0x080c, 0x379a,
-	0x0804, 0x2cb1, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, 0xffdd,
-	0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, 0x6104,
-	0xa18c, 0x0010, 0x0548, 0x080c, 0x3969, 0x080c, 0x3776, 0x88ff,
-	0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695,
-	0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082,
-	0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, 0x6000,
-	0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, 0x0000,
-	0xa006, 0x2010, 0x080c, 0x379a, 0xa286, 0x0001, 0x0158, 0x6104,
-	0xa18c, 0x0008, 0x01b0, 0x080c, 0x3969, 0x080c, 0x3696, 0x88ff,
-	0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, 0x6922,
-	0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c,
-	0x36f6, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005,
-	0x781b, 0x0083, 0x0005, 0x0804, 0x382d, 0x2808, 0x789b, 0x0080,
-	0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x1188,
-	0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, 0xa102,
-	0x0a04, 0x2c40, 0x0904, 0x2c40, 0x24a8, 0x7aa8, 0x1f04, 0x2cd5,
-	0x0c48, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082,
-	0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, 0x0ad0,
-	0xa286, 0x0023, 0x0980, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
-	0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
-	0x78a0, 0x8001, 0x0904, 0x2cb1, 0x20a8, 0x7998, 0x789b, 0x0060,
-	0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa,
-	0x7a98, 0x1f04, 0x2d03, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
-	0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, 0xa302,
-	0x0a04, 0x2cc2, 0xa284, 0x0080, 0x1904, 0x3831, 0x78a0, 0xa005,
-	0x08c8, 0x0804, 0x3831, 0x0804, 0x3809, 0x7058, 0xa04d, 0x789b,
-	0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c,
-	0x243b, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
-	0x0005, 0x1a04, 0x3809, 0x0002, 0x3809, 0x3615, 0x3809, 0x3726,
-	0x3b83, 0xa282, 0x0000, 0x1110, 0x080c, 0x243b, 0x080c, 0x3837,
-	0x781b, 0x0082, 0x0005, 0xa282, 0x0003, 0x1110, 0x080c, 0x243b,
-	0xd4fc, 0x11d0, 0x7064, 0xa005, 0x0110, 0x080c, 0x243b, 0x6f14,
-	0x7776, 0xa7bc, 0x8f00, 0x080c, 0x396d, 0x6008, 0xa085, 0x0021,
-	0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c, 0x383a, 0x7067,
-	0x0002, 0x701f, 0x0009, 0x0010, 0x080c, 0x3846, 0x781b, 0x0082,
-	0x0005, 0xa282, 0x0004, 0x0310, 0x080c, 0x243b, 0x2300, 0x0002,
-	0x2d7b, 0x2eff, 0x2f3b, 0xa286, 0x0003, 0x0560, 0x7200, 0x7cd8,
-	0x7ddc, 0x7fd0, 0x71d4, 0xd1b4, 0x00f0, 0x7868, 0xa084, 0x00ff,
-	0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300, 0x781b,
-	0x0059, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
-	0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x00de,
-	0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, 0x0057, 0x2001,
-	0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a, 0x68a0,
-	0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f, 0x0002,
-	0x2ee0, 0x2dc5, 0x2dc2, 0x3012, 0x3085, 0x248f, 0x2dc0, 0x2dc0,
-	0x080c, 0x243b, 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120, 0x7048,
-	0xa086, 0x0014, 0x11e8, 0x080c, 0x3d52, 0x2009, 0x0000, 0x6818,
-	0xd0fc, 0x0108, 0x7048, 0xa086, 0x0014, 0x0168, 0x6818, 0xa086,
-	0x0008, 0x1904, 0x2ea2, 0x7858, 0xd09c, 0x0904, 0x2ea2, 0x6820,
-	0xd0ac, 0x0904, 0x2ea2, 0x681b, 0x0014, 0x2009, 0x0002, 0x04a8,
-	0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158, 0x6008,
-	0xc0a4, 0x600a, 0x080c, 0x355f, 0x0540, 0x080c, 0x35c5, 0x080c,
-	0x3d52, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, 0xa005, 0x0d78,
-	0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820, 0xd084,
-	0x0904, 0x248f, 0xc084, 0x6822, 0x080c, 0x2580, 0x705c, 0x00c6,
-	0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005, 0x2d00,
-	0x1108, 0x6002, 0x6006, 0x0804, 0x248f, 0x0016, 0x81ff, 0x15e0,
-	0x7000, 0xa086, 0x0030, 0x05c0, 0x71d4, 0xd1b4, 0x11e8, 0x7060,
-	0xa005, 0x1590, 0x70a4, 0xa086, 0x0001, 0x0570, 0x7003, 0x0000,
-	0x0046, 0x0056, 0x0076, 0x0066, 0x00c6, 0x00d6, 0x080c, 0x24b2,
-	0x00de, 0x00ce, 0x006e, 0x007e, 0x005e, 0x004e, 0x71d4, 0xd1b4,
-	0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c, 0x3a8d, 0x11a8, 0x781b,
-	0x0068, 0x00d6, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
-	0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030,
-	0x7808, 0xc08d, 0x780a, 0x00de, 0x080c, 0x2f63, 0x001e, 0x81ff,
-	0x0904, 0x2ea2, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14,
-	0xa186, 0x0002, 0x15c0, 0x6818, 0xa086, 0x0014, 0x1130, 0x2008,
-	0xd6e4, 0x0118, 0x7868, 0xa08c, 0x00ff, 0x080c, 0x3850, 0x080c,
-	0x258b, 0x6820, 0xd0dc, 0x1538, 0x8717, 0xa294, 0x000f, 0x8213,
-	0x8213, 0x8213, 0xb284, 0x0600, 0x0118, 0xa290, 0x47c0, 0x0010,
-	0xa290, 0x4840, 0xa290, 0x0000, 0x221c, 0xd3c4, 0x0130, 0x8210,
-	0x2204, 0xa085, 0x0038, 0x2012, 0x8211, 0xd3d4, 0x0138, 0x68a0,
-	0xd0c4, 0x1120, 0x080c, 0x2fcb, 0x0804, 0x248f, 0x6008, 0xc08d,
-	0x600a, 0x0008, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7048,
-	0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0168, 0x2009,
-	0x4302, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021,
-	0x4304, 0x2404, 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0118, 0x8001,
-	0x601a, 0x1118, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x1130,
-	0x6800, 0xa005, 0x1108, 0x6002, 0x6006, 0x0020, 0x705c, 0x2060,
-	0x6800, 0x6002, 0x2061, 0x4300, 0x6887, 0x0103, 0x2d08, 0x206b,
-	0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e,
-	0x7200, 0xa286, 0x0030, 0x0158, 0xa286, 0x0040, 0x1904, 0x248f,
-	0x7003, 0x0002, 0x704c, 0x2068, 0x68c4, 0x2060, 0x0005, 0x7003,
-	0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0,
-	0x705a, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005, 0xa282,
-	0x0004, 0x0210, 0x080c, 0x243b, 0x2200, 0x0002, 0x2f0a, 0x2f19,
-	0x2f25, 0x2f19, 0xa586, 0x1300, 0x0160, 0xa586, 0x8300, 0x1d90,
-	0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x7000, 0xa086, 0x0005, 0x0128, 0x080c, 0x3837, 0x781b,
-	0x0082, 0x0005, 0x781b, 0x0083, 0x0005, 0x7890, 0x8007, 0x8001,
-	0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
-	0xa186, 0x0003, 0x0128, 0xa186, 0x0000, 0x0110, 0x0804, 0x3809,
-	0x781b, 0x0083, 0x0005, 0x6820, 0xc095, 0x6822, 0x82ff, 0x1118,
-	0x080c, 0x3837, 0x0030, 0x8211, 0x0110, 0x080c, 0x243b, 0x080c,
-	0x3846, 0x781b, 0x0082, 0x0005, 0x080c, 0x3aa0, 0x7830, 0xa084,
-	0x00c0, 0x1170, 0x0016, 0x3208, 0xa18c, 0x0800, 0x001e, 0x0118,
-	0x0104, 0x2f60, 0x0010, 0x0304, 0x2f60, 0x791a, 0xa006, 0x0005,
-	0xa085, 0x0001, 0x0005, 0xa684, 0x0060, 0x1130, 0x682f, 0x0000,
-	0x6833, 0x0000, 0x0804, 0x2fca, 0xd6dc, 0x1198, 0x68b4, 0xd0dc,
-	0x1180, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x1130,
-	0x2200, 0xa105, 0x0904, 0x3d52, 0x704b, 0x0015, 0x0804, 0x3d52,
-	0x0005, 0xd6ac, 0x01f0, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833,
-	0x0000, 0x0804, 0x3d52, 0x68b4, 0xa084, 0x4000, 0xa635, 0xd6f4,
-	0x1da0, 0x7048, 0xa005, 0x1110, 0x704b, 0x0015, 0xd6dc, 0x1128,
-	0x68b4, 0xd0dc, 0x0110, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0804,
-	0x3d52, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804,
-	0x3d52, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x1da0, 0x7048,
-	0xa005, 0x1110, 0x704b, 0x0015, 0x2408, 0x2510, 0x2700, 0x8007,
-	0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100,
-	0xa205, 0x1110, 0x0804, 0x3d52, 0x7000, 0xa086, 0x0006, 0x0110,
-	0x0804, 0x3d52, 0x0005, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0108,
-	0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000,
-	0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
-	0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020,
-	0x7000, 0x0002, 0x248f, 0x2ffa, 0x2ff4, 0x2ff2, 0x2ff2, 0x2ff2,
-	0x2ff2, 0x2ff2, 0x080c, 0x243b, 0x6820, 0xd084, 0x1118, 0x080c,
-	0x35ab, 0x0030, 0x705c, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
-	0x3208, 0xa18c, 0x0600, 0x0118, 0x2021, 0x4358, 0x0010, 0x2021,
-	0x4398, 0x2404, 0xa005, 0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b,
-	0x0000, 0x0005, 0x080c, 0x35b1, 0x080c, 0x35c5, 0x6008, 0xc0cc,
-	0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a,
-	0x6944, 0x6916, 0x3208, 0xa18c, 0x0600, 0x0118, 0x2009, 0x0000,
-	0x0010, 0x2009, 0x0001, 0x080c, 0x40b1, 0xd6dc, 0x0118, 0x691c,
-	0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0148, 0x7868, 0xa08c, 0x00ff,
-	0x0118, 0x681b, 0x001e, 0x0010, 0x681b, 0x0000, 0xb284, 0x0600,
-	0x1118, 0x2021, 0x4398, 0x0010, 0x2021, 0x4358, 0x6800, 0x2022,
-	0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4,
-	0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x00d6,
-	0x00f6, 0x0156, 0x0146, 0x2079, 0x4300, 0x080c, 0x1b35, 0x014e,
-	0x015e, 0x00fe, 0x70cc, 0x2010, 0x2009, 0x0101, 0x0026, 0x2204,
-	0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800, 0x0cc8, 0x6820,
-	0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, 0x00de, 0x7067,
-	0x0003, 0x707f, 0x0000, 0x7776, 0x7083, 0x000f, 0x71d4, 0xc1c4,
-	0x71d6, 0x080c, 0x1d3d, 0x0804, 0x248f, 0x7cd8, 0x7ddc, 0x7fd0,
-	0x080c, 0x2f63, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x080c,
-	0x3aa4, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7048,
-	0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0804, 0x248f,
-	0x7000, 0xa005, 0x1110, 0x0804, 0x248f, 0xa006, 0x080c, 0x3d52,
-	0x6920, 0xd1ac, 0x1110, 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e,
-	0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822, 0x7000, 0x0002,
-	0x248f, 0x30c2, 0x30c2, 0x30c5, 0x30c5, 0x30c5, 0x30c0, 0x30c0,
-	0x080c, 0x243b, 0x6818, 0x0804, 0x2daa, 0x6008, 0xc0a4, 0x600a,
-	0x6817, 0x0000, 0x0804, 0x357a, 0x2300, 0x0002, 0x30d1, 0x30d3,
-	0x3110, 0x080c, 0x243b, 0xd6fc, 0x1904, 0x2bee, 0x7000, 0xa00d,
-	0x0002, 0x248f, 0x30e3, 0x30e3, 0x3104, 0x30e3, 0x310d, 0x30e1,
-	0x30e1, 0x080c, 0x243b, 0xa684, 0x0060, 0xa086, 0x0060, 0x11d0,
-	0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, 0xc0ac, 0x681e, 0xa186,
-	0x0002, 0x0110, 0x080c, 0x3d52, 0x080c, 0x3fb8, 0x781b, 0x0083,
-	0x71d4, 0xd1b4, 0x1904, 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904,
-	0x24ce, 0x0005, 0xd6ec, 0x0d30, 0x6818, 0xd0fc, 0x0130, 0x681b,
-	0x0015, 0xd6f4, 0x0110, 0x681b, 0x0007, 0x080c, 0x3a4b, 0x0005,
-	0x080c, 0x243b, 0x2300, 0x0002, 0x3119, 0x3134, 0x3182, 0x080c,
-	0x243b, 0x7000, 0x0002, 0x3123, 0x3125, 0x3125, 0x3123, 0x3123,
-	0x3123, 0x3123, 0x3123, 0x080c, 0x243b, 0x080c, 0x3fb8, 0x681c,
-	0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x1904, 0x248c, 0x70a4, 0xa086,
-	0x0001, 0x1904, 0x24ce, 0x0005, 0xd6fc, 0x15e0, 0x7000, 0xa00d,
-	0x0002, 0x248f, 0x3149, 0x3143, 0x316a, 0x3149, 0x316f, 0x3141,
-	0x3141, 0x080c, 0x243b, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
-	0x78da, 0xa684, 0x0060, 0xa086, 0x0060, 0x11d0, 0xa6b4, 0xbfbf,
-	0xc6ed, 0x7e5a, 0xa186, 0x0002, 0x0110, 0x080c, 0x3d52, 0x080c,
-	0x3fb8, 0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4,
-	0x1904, 0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, 0x24ce, 0x0005,
-	0xd6ec, 0x0d30, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, 0x781b,
-	0x00fb, 0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100,
-	0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b,
-	0x0083, 0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, 0x0083,
-	0x0804, 0x248c, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008,
-	0x1150, 0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b,
-	0x0083, 0x0804, 0x248c, 0x6820, 0xc095, 0x6822, 0x080c, 0x39ca,
-	0xc6dd, 0x080c, 0x3837, 0x781b, 0x0082, 0x0804, 0x248c, 0x2300,
-	0x0002, 0x31ac, 0x31ae, 0x31b0, 0x080c, 0x243b, 0x0804, 0x3831,
-	0x7d98, 0xd6d4, 0x11f8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, 0xa084,
-	0x0003, 0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000,
-	0xa684, 0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, 0x78ec,
-	0xa084, 0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2daa, 0xa184,
-	0x0007, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8,
-	0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384, 0x0001, 0x11d0,
-	0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009, 0xffdf, 0x0058,
-	0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028, 0xa386, 0x0003,
-	0x1148, 0x2009, 0xffef, 0x00c6, 0x7058, 0x2060, 0x6004, 0xa104,
-	0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
-	0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff, 0x6922, 0x7d9a,
-	0x0804, 0x3a3f, 0x2a9f, 0x2aa8, 0x3214, 0x321a, 0x3212, 0x3212,
-	0x3a3f, 0x3a3f, 0x080c, 0x243b, 0x6920, 0xa18c, 0xfcff, 0x6922,
-	0x0804, 0x3a45, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3a3f,
-	0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084, 0x0003, 0x1558,
-	0x7000, 0xa086, 0x0004, 0x1190, 0x7064, 0xa086, 0x0002, 0x1130,
-	0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x295c, 0x7064, 0xa086,
-	0x0006, 0x0db0, 0x7064, 0xa086, 0x0004, 0x0d90, 0x7000, 0xa086,
-	0x0000, 0x0904, 0x248c, 0x6920, 0xa184, 0x0420, 0x0128, 0xc1d4,
-	0x6922, 0x6818, 0x0804, 0x2daa, 0x6818, 0xc0fd, 0x681a, 0x2001,
-	0x0014, 0x0804, 0x2daa, 0xa184, 0x0007, 0x0002, 0x3a3f, 0x3a3f,
-	0x325e, 0x3a3f, 0x3a83, 0x3a83, 0x3a3f, 0x3a3f, 0xd6bc, 0x0570,
-	0x7184, 0x81ff, 0x0558, 0xa182, 0x000d, 0x1318, 0x7087, 0x0000,
-	0x0028, 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061,
-	0x79aa, 0x0156, 0x0136, 0x0146, 0x7088, 0x8114, 0xa210, 0x728a,
-	0xa080, 0x000b, 0xad00, 0x2098, 0xb284, 0x0600, 0x0118, 0x20a1,
-	0x022b, 0x0010, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac,
-	0x53a6, 0x014e, 0x013e, 0x015e, 0x0804, 0x3a45, 0xd6d4, 0x1904,
-	0x32d1, 0x6820, 0xd084, 0x0904, 0x3a45, 0xa68c, 0x0060, 0xa684,
-	0x0060, 0x0120, 0xa086, 0x0060, 0x1108, 0xc1f5, 0xc194, 0x795a,
-	0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818,
-	0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0904, 0x35da, 0xa18c,
-	0x00f8, 0x1904, 0x35da, 0x0156, 0x0136, 0x0146, 0x0016, 0x20a1,
-	0x012b, 0x3208, 0xa18c, 0x0600, 0x0110, 0x20a1, 0x022b, 0x001e,
-	0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
-	0x014e, 0x013e, 0x015e, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0804,
-	0x3a45, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0008, 0x080c, 0x3837,
-	0x781b, 0x00ed, 0x0005, 0x2300, 0x0002, 0x32e2, 0x3398, 0x32e0,
-	0x080c, 0x243b, 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x11f0, 0x7200,
-	0xa286, 0x0003, 0x0904, 0x2d7f, 0x71d4, 0xd1b4, 0x00c0, 0x00d6,
-	0x783b, 0x8800, 0x781b, 0x0059, 0x70bc, 0xa06d, 0x68b4, 0xc0a5,
-	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
-	0x71d6, 0x7003, 0x0030, 0x00de, 0x0030, 0x7200, 0x0020, 0x783b,
-	0x1800, 0x781b, 0x0057, 0xa284, 0x000f, 0x0002, 0x3383, 0x3344,
-	0x3318, 0x2da7, 0x3316, 0x3383, 0x3316, 0x3316, 0x080c, 0x243b,
-	0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185,
-	0x6922, 0x6800, 0x6006, 0xa005, 0x1108, 0x6002, 0x6008, 0xc0d4,
-	0x600a, 0x681c, 0xa084, 0x000e, 0x1148, 0xb284, 0x0600, 0x0118,
-	0x2009, 0x89c0, 0x0040, 0x2009, 0x8ad0, 0x0028, 0x7030, 0x68ba,
-	0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e, 0xd6dc,
-	0x1118, 0xc6fc, 0x6eb6, 0x04f8, 0x6eb6, 0xa684, 0x0060, 0x05d8,
-	0xd6dc, 0x1150, 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898,
-	0x68aa, 0x080c, 0x3d52, 0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c,
-	0x3d52, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510,
-	0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x69aa,
-	0x6aa6, 0x080c, 0x3d52, 0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6,
-	0x2510, 0x2408, 0xd6ac, 0x1138, 0x2700, 0x8007, 0xa084, 0x007f,
-	0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
-	0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030, 0x1904, 0x248f,
-	0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065,
-	0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x0005,
-	0xa586, 0x8800, 0x1148, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a,
-	0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x3831, 0x7047, 0x0000,
-	0xa282, 0x0006, 0x0310, 0x080c, 0x243b, 0x2300, 0x0002, 0x33b2,
-	0x33e4, 0x340f, 0x2200, 0x0002, 0x33ba, 0x3831, 0x33bc, 0x33ba,
-	0x343f, 0x349d, 0x080c, 0x243b, 0x7003, 0x0005, 0xb284, 0x0600,
-	0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12, 0x2068, 0x704e,
-	0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x33cb,
-	0x015e, 0xb284, 0x0600, 0x0118, 0x6817, 0x0000, 0x0010, 0x6817,
-	0x8000, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
-	0x6827, 0x0003, 0x0804, 0x3809, 0x7000, 0xa086, 0x0002, 0x1150,
-	0x080c, 0x35c5, 0x0010, 0x080c, 0x3d52, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x0020, 0x7000, 0xa086, 0x0003, 0x0da8, 0x7003, 0x0005,
-	0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12,
-	0x2068, 0x704e, 0xad80, 0x0009, 0x7046, 0x2200, 0x0002, 0x3831,
-	0x340d, 0x340d, 0x343f, 0x340d, 0x3831, 0x080c, 0x243b, 0x7000,
-	0xa086, 0x0002, 0x1150, 0x080c, 0x35c5, 0x0010, 0x080c, 0x3d52,
-	0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003,
-	0x0da8, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0,
-	0x0010, 0x2001, 0x8b12, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
-	0x2200, 0x0002, 0x343a, 0x3438, 0x3438, 0x343a, 0x3438, 0x343a,
-	0x080c, 0x243b, 0x080c, 0x3846, 0x781b, 0x0082, 0x0005, 0x7000,
-	0xa086, 0x0002, 0x1158, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba,
-	0x2d00, 0x70be, 0x0038, 0x080c, 0x3d52, 0x0020, 0x7000, 0xa086,
-	0x0003, 0x0dc8, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b,
-	0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x89c0, 0xb284,
-	0x0600, 0x1118, 0xc2fd, 0x2069, 0x8ad0, 0x2d04, 0x2d08, 0x715e,
-	0xa06d, 0x0128, 0x6814, 0xa206, 0x0500, 0x6800, 0x0cb8, 0x7003,
-	0x0005, 0xd2fc, 0x1118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12,
-	0x2068, 0x704e, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000,
-	0x1f04, 0x347d, 0x015e, 0xad80, 0x0009, 0x7046, 0x6a16, 0x68b7,
-	0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6920,
-	0xa184, 0x0c00, 0x0904, 0x3507, 0x681b, 0x0005, 0xc1ad, 0xc1d4,
-	0x6922, 0x080c, 0x383d, 0x0804, 0x3507, 0x7200, 0xa286, 0x0002,
-	0x1158, 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be,
-	0x0030, 0x080c, 0x3d52, 0x0018, 0xa286, 0x0003, 0x0dd0, 0x7003,
-	0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484,
-	0x001f, 0xa215, 0xb284, 0x0600, 0x1108, 0xc2fd, 0x79a8, 0x79a8,
-	0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e, 0xa06d,
-	0x0128, 0x6814, 0xa206, 0x0538, 0x6800, 0x0cb8, 0x7003, 0x0005,
-	0xb284, 0x0600, 0x0118, 0x2001, 0x8ae0, 0x0010, 0x2001, 0x8b12,
-	0x2068, 0x704e, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000,
-	0x1f04, 0x34dd, 0x015e, 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008,
-	0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
-	0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0178,
-	0xd0dc, 0x0118, 0x080c, 0x3843, 0x0050, 0x681b, 0x0005, 0xc1ad,
-	0xc1d4, 0x6922, 0x080c, 0x383d, 0x707f, 0x0000, 0x0000, 0xa6ac,
-	0x0060, 0x05c8, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x11c0,
-	0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0xa586, 0x0060,
-	0x0550, 0xc6ed, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009,
-	0x0082, 0x2019, 0x0000, 0x2320, 0x791a, 0x080c, 0x3fb8, 0x0418,
-	0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01a0, 0x7bd2,
-	0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xc6f4, 0x7e5a, 0x2011, 0x0083,
-	0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000, 0x2320, 0x7a1a,
-	0x080c, 0x3fe5, 0x0040, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0110,
-	0x2009, 0x0082, 0x791a, 0x68c0, 0x705a, 0x2d00, 0x704e, 0x68c4,
-	0x2060, 0x71d4, 0xd1b4, 0x1904, 0x248c, 0x2300, 0xa405, 0x0904,
-	0x248c, 0x70a4, 0xa086, 0x0001, 0x1904, 0x24ce, 0x0005, 0x6020,
+	0x0006, 0x2011, 0x4602, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e,
+	0xa102, 0x0338, 0x6012, 0x1128, 0x2011, 0x4604, 0x2204, 0xc0a5,
+	0x2012, 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a13, 0x8421,
+	0x1d00, 0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000,
+	0x0005, 0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006,
+	0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00,
+	0x681e, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1da2,
+	0x000e, 0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003,
+	0x0310, 0x080c, 0x254c, 0x2300, 0x0002, 0x2a60, 0x2add, 0x2af7,
+	0xa282, 0x0002, 0x0110, 0x080c, 0x254c, 0x7060, 0x7063, 0x0000,
+	0x707f, 0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2a77,
+	0x2a77, 0x2a79, 0x2ab1, 0x37d8, 0x2a77, 0x2ab1, 0x2a77, 0x080c,
+	0x254c, 0x7770, 0x080c, 0x3a66, 0x7770, 0xa7bc, 0x8f00, 0x080c,
+	0x3b6f, 0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8cc0,
+	0x0010, 0x2021, 0x8dd0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c,
+	0x2b11, 0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021,
+	0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x0046, 0x2009, 0x0005, 0x2011,
+	0x0010, 0x080c, 0x2b11, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2a9c,
+	0x015e, 0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x25a0, 0x0804,
+	0x25a0, 0x7770, 0x080c, 0x3b6f, 0x6018, 0xa005, 0x0520, 0xd7fc,
+	0x1118, 0x2021, 0x8cc0, 0x0010, 0x2021, 0x8dd0, 0x2009, 0x0005,
+	0x2011, 0x0020, 0x080c, 0x2b11, 0x01b0, 0x0156, 0x20a9, 0x0101,
+	0xd7fc, 0x1118, 0x2021, 0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x0046,
+	0x2009, 0x0005, 0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420,
+	0x1f04, 0x2acf, 0x015e, 0x0804, 0x25a0, 0x2200, 0x0002, 0x2ae2,
+	0x2ae4, 0x2ae4, 0x080c, 0x254c, 0x2009, 0x0012, 0x7060, 0xa086,
+	0x0002, 0x0110, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a,
+	0x7063, 0x0000, 0x70d0, 0xc0c5, 0x70d2, 0x0804, 0x3be5, 0x2200,
+	0x0002, 0x2afe, 0x2ae4, 0x2afc, 0x080c, 0x254c, 0x080c, 0x3f26,
+	0x7000, 0xa086, 0x0002, 0x1904, 0x375d, 0x080c, 0x37be, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x080c, 0x374f, 0x0904, 0x375d, 0x0804,
+	0x25a0, 0x2404, 0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814,
+	0xa706, 0x0118, 0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a,
+	0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e,
+	0x6820, 0xa084, 0x00ff, 0xa205, 0x6822, 0x080c, 0x1da2, 0x2021,
+	0x4602, 0x241c, 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128,
+	0x2021, 0x4604, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef,
+	0x600a, 0x080c, 0x269e, 0x080c, 0x37be, 0x0005, 0xa085, 0x0001,
+	0x0ce0, 0x2300, 0x0002, 0x2b50, 0x2b4e, 0x2bcb, 0x080c, 0x254c,
+	0x78e4, 0xa005, 0x17b0, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104,
+	0x259d, 0x0010, 0x0304, 0x259d, 0x2008, 0xa084, 0x0030, 0x1110,
+	0x0804, 0x322a, 0x78ec, 0xa084, 0x0003, 0x0dd0, 0x7884, 0xd0fc,
+	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
+	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
+	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2bae,
+	0x2bb7, 0x2ba4, 0x2b87, 0x3c29, 0x3c29, 0x2b87, 0x2bc1, 0x080c,
+	0x254c, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086, 0x0002,
+	0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a56, 0x7060,
+	0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90, 0x79e4,
+	0x2001, 0x0003, 0x0804, 0x2f18, 0x6818, 0xd0fc, 0x0110, 0x681b,
+	0x001d, 0x080c, 0x3a3c, 0x781b, 0x006e, 0x0005, 0x6818, 0xd0fc,
+	0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c, 0x0804, 0x3c07, 0x6818,
+	0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c, 0x781b, 0x00fa,
+	0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c,
+	0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, 0x7000, 0x0002,
+	0x25a0, 0x2bd8, 0x2bda, 0x375d, 0x375d, 0x375d, 0x2bd8, 0x2bd8,
+	0x080c, 0x254c, 0x080c, 0x37be, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x080c, 0x374f, 0x0904, 0x375d, 0x0804, 0x25a0, 0x78e4, 0xa005,
+	0x1b04, 0x2b89, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x2b89,
+	0x0010, 0x0304, 0x2b89, 0x2008, 0xa084, 0x0030, 0x1118, 0x781b,
+	0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, 0x7884, 0xd0fc,
+	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
+	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
+	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2c26,
+	0x2c2a, 0x2c21, 0x2c1f, 0x3c29, 0x3c29, 0x2c1f, 0x3c23, 0x080c,
+	0x254c, 0x080c, 0x3a42, 0x781b, 0x006e, 0x0005, 0x080c, 0x3a42,
+	0x0804, 0x3c07, 0x080c, 0x3a42, 0x781b, 0x00fa, 0x0005, 0x080c,
+	0x3a42, 0x781b, 0x00cb, 0x0005, 0x2300, 0x0002, 0x2c3b, 0x2c39,
+	0x2c3d, 0x080c, 0x254c, 0x0804, 0x33e2, 0x681b, 0x0016, 0x78a3,
+	0x0000, 0x79e4, 0xa184, 0x0030, 0x0904, 0x33e2, 0x78ec, 0xa084,
+	0x0003, 0x0904, 0x33e2, 0xa184, 0x0100, 0x0d98, 0x7884, 0xd0fc,
+	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
+	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
+	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2c6f,
+	0x2c2a, 0x2ba4, 0x3be5, 0x3c29, 0x3c29, 0x3be5, 0x3c23, 0x080c,
+	0x3bf1, 0x0005, 0xa282, 0x0005, 0x0310, 0x080c, 0x254c, 0x7898,
+	0x2040, 0x2300, 0x0002, 0x2c7e, 0x2ea8, 0x2eb2, 0x2200, 0x0002,
+	0x2c9a, 0x2c87, 0x2c9a, 0x2c85, 0x2e8a, 0x080c, 0x254c, 0x789b,
+	0x0018, 0x78a8, 0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04,
+	0x3a0b, 0xa08a, 0x0004, 0x1a04, 0x3a0b, 0x0002, 0x3a0b, 0x3a0b,
+	0x3a0b, 0x39c1, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148,
+	0x0804, 0x3a0b, 0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804,
+	0x3594, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x1a04, 0x3a0b, 0x0002,
+	0x2cc2, 0x2cc0, 0x2cd4, 0x2cd8, 0x2d86, 0x3a0b, 0x3a0b, 0x2d88,
+	0x3a0b, 0x3a0b, 0x2e86, 0x2e86, 0x3a0b, 0x3a0b, 0x3a0b, 0x2e88,
+	0x080c, 0x254c, 0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000,
+	0x783a, 0x781b, 0x00c7, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b,
+	0x001d, 0x0c90, 0x0804, 0x3be5, 0x681b, 0x001d, 0x0804, 0x3a36,
+	0x6920, 0x6922, 0xa684, 0x1800, 0x1904, 0x2d29, 0x6820, 0xd084,
+	0x1904, 0x2d31, 0x6818, 0xa086, 0x0008, 0x1110, 0x681b, 0x0000,
+	0xd6d4, 0x0568, 0xd6bc, 0x0558, 0x7083, 0x0000, 0x6818, 0xa084,
+	0x003f, 0xa08a, 0x000d, 0x0718, 0xa08a, 0x000c, 0x7182, 0x2001,
+	0x000c, 0x800c, 0x7186, 0x789b, 0x0061, 0x78aa, 0x0156, 0x0136,
+	0x0146, 0x0016, 0x3208, 0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b,
+	0x0010, 0x20a1, 0x012b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac,
+	0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6038,
+	0xa005, 0x1150, 0x681c, 0xa084, 0x000e, 0x0904, 0x3a36, 0x080c,
+	0x3a48, 0x782b, 0x3008, 0x0010, 0x8001, 0x603a, 0x781b, 0x0071,
+	0x0005, 0xd6e4, 0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083,
+	0x0005, 0xa684, 0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0,
+	0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084,
+	0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
+	0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a,
+	0x6eb6, 0x7000, 0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3f26,
+	0x080c, 0x41d9, 0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c,
+	0x42b5, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120,
+	0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6,
+	0x7bd6, 0x7bde, 0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6,
+	0x781b, 0x0080, 0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118,
+	0x080c, 0x41d9, 0x0005, 0x080c, 0x4206, 0x0005, 0x080c, 0x254c,
+	0x0804, 0x2e1c, 0x00c6, 0x7054, 0x2060, 0x6920, 0xa18c, 0xecff,
+	0x6922, 0x6000, 0xa084, 0xcfdf, 0x6002, 0x080c, 0x38f4, 0xa006,
+	0x2040, 0x2038, 0x080c, 0x399c, 0x0804, 0x2e10, 0x00c6, 0x7054,
+	0x2060, 0x2c48, 0x7aa8, 0xa294, 0x00ff, 0xa286, 0x0004, 0x11d8,
+	0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031,
+	0x0000, 0xa006, 0x2010, 0x080c, 0x38f7, 0x080c, 0x399c, 0x0804,
+	0x2e10, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, 0xffdd, 0x6106,
+	0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, 0x6104, 0xa184,
+	0x0010, 0x0548, 0x080c, 0x3b6b, 0x080c, 0x3977, 0x88ff, 0x0518,
+	0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
+	0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005,
+	0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, 0x6000, 0xc0ec,
+	0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, 0x0000, 0xa006,
+	0x2010, 0x080c, 0x399c, 0xa286, 0x0001, 0x0158, 0x6104, 0xa184,
+	0x0008, 0x01b0, 0x080c, 0x3b6b, 0x080c, 0x3895, 0x88ff, 0x1980,
+	0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, 0x6922, 0x6000,
+	0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7,
+	0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b,
+	0x0083, 0x0005, 0x0804, 0x3a32, 0x2808, 0x789b, 0x0080, 0x2019,
+	0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x11b8, 0x2300,
+	0xa102, 0xa086, 0x0001, 0x0904, 0x2d8a, 0x7ca8, 0xa4a4, 0x00ff,
+	0xa480, 0x0002, 0xa300, 0x2018, 0xa102, 0x0a04, 0x2d9e, 0x0904,
+	0x2d9e, 0x24a8, 0x7aa8, 0x1f04, 0x2e3a, 0x0c18, 0xa284, 0x00f0,
+	0xa082, 0x0020, 0x06b8, 0x2200, 0xa082, 0x0021, 0x1698, 0x7aa8,
+	0x8318, 0x8318, 0x2100, 0xa302, 0x0aa0, 0xa286, 0x0023, 0x0950,
+	0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5,
+	0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x78a0, 0x8001, 0x0904,
+	0x2e10, 0x20a8, 0x7998, 0x789b, 0x0060, 0x78aa, 0x2011, 0x0080,
+	0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa, 0x7a98, 0x1f04, 0x2e68,
+	0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b,
+	0x0082, 0x0005, 0x8318, 0x2100, 0xa302, 0x0a04, 0x2e21, 0xa284,
+	0x0080, 0x1904, 0x3a36, 0x78a0, 0xa005, 0x08c8, 0x0804, 0x3a36,
+	0x0804, 0x3a0b, 0x7054, 0xa04d, 0x789b, 0x0018, 0x78a8, 0xa084,
+	0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c, 0x254c, 0x7aa8, 0xa294,
+	0x00ff, 0x784b, 0x0008, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0005,
+	0x1a04, 0x3a0b, 0x0002, 0x3a0b, 0x380c, 0x3a0b, 0x3927, 0x3d31,
+	0xa282, 0x0000, 0x1110, 0x080c, 0x254c, 0x080c, 0x3a3c, 0x781b,
+	0x0082, 0x0005, 0xa282, 0x0003, 0x1110, 0x080c, 0x254c, 0xd4fc,
+	0x11d0, 0x7060, 0xa005, 0x0110, 0x080c, 0x254c, 0x6f14, 0x7772,
+	0xa7bc, 0x8f00, 0x080c, 0x3b6f, 0x6008, 0xa085, 0x0021, 0x600a,
+	0x8738, 0xa784, 0x001f, 0x1db0, 0x080c, 0x3a3f, 0x7063, 0x0002,
+	0x701f, 0x0009, 0x0010, 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005,
+	0xa282, 0x0004, 0x0310, 0x080c, 0x254c, 0x2300, 0x0002, 0x2ee2,
+	0x3078, 0x30b4, 0xa286, 0x0003, 0x0598, 0x7200, 0x7cd8, 0x7ddc,
+	0x7fd0, 0x71d0, 0xd1b4, 0x0528, 0xd1bc, 0x1518, 0x2001, 0x4601,
+	0x2004, 0xd0c4, 0x11f0, 0x7868, 0xa084, 0x00ff, 0x11d0, 0xa282,
+	0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300, 0x781b, 0x0059, 0x70b8,
+	0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+	0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x2001, 0x0000,
+	0x0058, 0x783b, 0x1300, 0x781b, 0x0057, 0x2001, 0x0000, 0x0020,
+	0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x7046, 0x68a0, 0xd0ec, 0x0118,
+	0x6008, 0xc08d, 0x600a, 0xa284, 0x000f, 0x0002, 0x3059, 0x2f33,
+	0x2f30, 0x3184, 0x320f, 0x25a0, 0x2f2e, 0x2f2e, 0x080c, 0x254c,
+	0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120, 0x7044, 0xa086, 0x0014,
+	0x11e8, 0x080c, 0x3f26, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0108,
+	0x7044, 0xa086, 0x0014, 0x0168, 0x6818, 0xa086, 0x0008, 0x1904,
+	0x301b, 0x7858, 0xd09c, 0x0904, 0x301b, 0x6820, 0xd0ac, 0x0904,
+	0x301b, 0x681b, 0x0014, 0x2009, 0x0002, 0x04a8, 0x7868, 0xa08c,
+	0x00ff, 0x0588, 0xa186, 0x0008, 0x1158, 0x6008, 0xc0a4, 0x600a,
+	0x080c, 0x374f, 0x0540, 0x080c, 0x37be, 0x080c, 0x3f26, 0x0060,
+	0xa186, 0x0028, 0x1500, 0x6018, 0xa005, 0x0d78, 0x8001, 0x0d68,
+	0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820, 0xd084, 0x0904, 0x25a0,
+	0xc084, 0x6822, 0x080c, 0x2693, 0x7058, 0x00c6, 0x2060, 0x6800,
+	0x6002, 0x00ce, 0x6004, 0x6802, 0xa005, 0x2d00, 0x1108, 0x6002,
+	0x6006, 0x0804, 0x25a0, 0x0016, 0x81ff, 0x15f0, 0x7000, 0xa086,
+	0x0030, 0x05d0, 0x71d0, 0xd1bc, 0x15b8, 0xd1b4, 0x11e8, 0x705c,
+	0xa005, 0x1590, 0x70a0, 0xa086, 0x0001, 0x0570, 0x7003, 0x0000,
+	0x0046, 0x0056, 0x0076, 0x0066, 0x00c6, 0x00d6, 0x080c, 0x25c5,
+	0x00de, 0x00ce, 0x006e, 0x007e, 0x005e, 0x004e, 0x71d0, 0xd1b4,
+	0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c, 0x3c33, 0x11a8, 0x781b,
+	0x0068, 0x00d6, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
+	0x7808, 0xc08d, 0x780a, 0x00de, 0x080c, 0x30dc, 0x001e, 0x81ff,
+	0x0904, 0x301b, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14,
+	0xa186, 0x0002, 0x1904, 0x301c, 0x6818, 0xa086, 0x0014, 0x1130,
+	0x2008, 0xd6e4, 0x0118, 0x7868, 0xa08c, 0x00ff, 0x080c, 0x3a55,
+	0x080c, 0x269e, 0x6820, 0xd0dc, 0x1578, 0x8717, 0xa294, 0x000f,
+	0x8213, 0x8213, 0x8213, 0xb284, 0x0600, 0x0118, 0xa290, 0x4ac0,
+	0x0010, 0xa290, 0x4b40, 0xa290, 0x0000, 0x221c, 0xd3c4, 0x0170,
+	0x6820, 0xd0e4, 0x0128, 0xa084, 0xefff, 0x6822, 0xc3ac, 0x2312,
+	0x8210, 0x2204, 0xa085, 0x0038, 0x2012, 0x8211, 0xd3d4, 0x0138,
+	0x68a0, 0xd0c4, 0x1120, 0x080c, 0x3144, 0x0804, 0x25a0, 0x6008,
+	0xc08d, 0x600a, 0x0008, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0110,
+	0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0168,
+	0x2009, 0x4602, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128,
+	0x2021, 0x4604, 0x2404, 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0118,
+	0x8001, 0x601a, 0x1118, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084,
+	0x1130, 0x6800, 0xa005, 0x1108, 0x6002, 0x6006, 0x0020, 0x7058,
+	0x2060, 0x6800, 0x6002, 0x2061, 0x4600, 0x6887, 0x0103, 0x2d08,
+	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008,
+	0x616e, 0x7200, 0xa286, 0x0030, 0x0158, 0xa286, 0x0040, 0x1904,
+	0x25a0, 0x7003, 0x0002, 0x7048, 0x2068, 0x68c4, 0x2060, 0x0005,
+	0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065,
+	0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005,
+	0xa282, 0x0004, 0x0210, 0x080c, 0x254c, 0x2200, 0x0002, 0x3083,
+	0x3092, 0x309e, 0x3092, 0xa586, 0x1300, 0x0160, 0xa586, 0x8300,
+	0x1d90, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x7000, 0xa086, 0x0005, 0x0128, 0x080c, 0x3a3c,
+	0x781b, 0x0082, 0x0005, 0x781b, 0x0083, 0x0005, 0x7890, 0x8007,
+	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
+	0x00ff, 0xa186, 0x0003, 0x0128, 0xa186, 0x0000, 0x0110, 0x0804,
+	0x3a0b, 0x781b, 0x0083, 0x0005, 0x6820, 0xc095, 0x6822, 0x82ff,
+	0x1118, 0x080c, 0x3a3c, 0x0030, 0x8211, 0x0110, 0x080c, 0x254c,
+	0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005, 0x080c, 0x3c46, 0x7830,
+	0xa084, 0x00c0, 0x1170, 0x0016, 0x3208, 0xa18c, 0x0800, 0x001e,
+	0x0118, 0x0104, 0x30d9, 0x0010, 0x0304, 0x30d9, 0x791a, 0xa006,
+	0x0005, 0xa085, 0x0001, 0x0005, 0xa684, 0x0060, 0x1130, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x0804, 0x3143, 0xd6dc, 0x1198, 0x68b4,
+	0xd0dc, 0x1180, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7044, 0xa005,
+	0x1130, 0x2200, 0xa105, 0x0904, 0x3f26, 0x7047, 0x0015, 0x0804,
+	0x3f26, 0x0005, 0xd6ac, 0x01f0, 0xd6f4, 0x0130, 0x682f, 0x0000,
+	0x6833, 0x0000, 0x0804, 0x3f26, 0x68b4, 0xa084, 0x4000, 0xa635,
+	0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, 0x0015, 0xd6dc,
+	0x1128, 0x68b4, 0xd0dc, 0x0110, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32,
+	0x0804, 0x3f26, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000,
+	0x0804, 0x3f26, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x1da0,
+	0x7044, 0xa005, 0x1110, 0x7047, 0x0015, 0x2408, 0x2510, 0x2700,
+	0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32,
+	0x2100, 0xa205, 0x1110, 0x0804, 0x3f26, 0x7000, 0xa086, 0x0006,
+	0x0110, 0x0804, 0x3f26, 0x0005, 0x6946, 0x6008, 0xc0cd, 0xd3cc,
+	0x0108, 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f,
+	0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f,
+	0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b,
+	0x0020, 0x7000, 0x0002, 0x25a0, 0x3173, 0x316d, 0x316b, 0x316b,
+	0x316b, 0x316b, 0x316b, 0x080c, 0x254c, 0x6820, 0xd084, 0x1118,
+	0x080c, 0x37a4, 0x0030, 0x7058, 0x2c50, 0x2060, 0x6800, 0x6002,
+	0x2a60, 0xaea0, 0x0017, 0x2404, 0xa005, 0x0110, 0x2020, 0x0cd8,
+	0x2d22, 0x206b, 0x0000, 0x0005, 0x080c, 0x37aa, 0x080c, 0x37be,
+	0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14,
+	0x6938, 0x691a, 0x6944, 0x6916, 0x2009, 0x0000, 0xae86, 0x4640,
+	0x0110, 0x2009, 0x0001, 0x080c, 0x42ec, 0xd6dc, 0x01c8, 0x691c,
+	0xc1ed, 0x691e, 0x6828, 0xa082, 0x000e, 0x0290, 0x6848, 0xa084,
+	0x000f, 0xa086, 0x000b, 0x1160, 0x685c, 0xa086, 0x0047, 0x1140,
+	0x2001, 0x4601, 0x2004, 0xd0ac, 0x1118, 0x2700, 0x080c, 0x2475,
+	0x6818, 0xd0fc, 0x0140, 0x681b, 0x0000, 0x7868, 0xa08c, 0x00ff,
+	0x0110, 0x681b, 0x001e, 0xaea0, 0x0017, 0x6800, 0x2022, 0x6a3c,
+	0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0580,
+	0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x00d6, 0x00f6,
+	0x0156, 0x0146, 0x2079, 0x4600, 0x080c, 0x1b93, 0x014e, 0x015e,
+	0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101, 0x0026, 0x2204, 0xa06d,
+	0x0140, 0x6814, 0xa706, 0x0110, 0x6800, 0x0cc8, 0x6820, 0xc0d5,
+	0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, 0x00de, 0x7063, 0x0003,
+	0x707b, 0x0000, 0x7772, 0x707f, 0x000f, 0x71d0, 0xc1c4, 0x71d2,
+	0x6818, 0xa086, 0x0002, 0x1138, 0x6817, 0x0000, 0x682b, 0x0000,
+	0x681c, 0xc0ec, 0x681e, 0x080c, 0x1da2, 0x0804, 0x25a0, 0x7cd8,
+	0x7ddc, 0x7fd0, 0x080c, 0x30dc, 0x682b, 0x0000, 0x789b, 0x000e,
+	0x6f14, 0x080c, 0x3c4a, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc,
+	0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7063, 0x0000,
+	0x0804, 0x25a0, 0x7000, 0xa005, 0x1110, 0x0804, 0x25a0, 0xa006,
+	0x080c, 0x3f26, 0x6920, 0xd1ac, 0x1110, 0x681b, 0x0014, 0xa68c,
+	0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822,
+	0x7000, 0x0002, 0x25a0, 0x324c, 0x324c, 0x324f, 0x324f, 0x324f,
+	0x324a, 0x324a, 0x080c, 0x254c, 0x6818, 0x0804, 0x2f18, 0x6008,
+	0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804, 0x3772, 0x2300, 0x0002,
+	0x325b, 0x325d, 0x32ab, 0x080c, 0x254c, 0xd6fc, 0x1904, 0x2d38,
+	0x7000, 0xa00d, 0x0002, 0x25a0, 0x326d, 0x326d, 0x3297, 0x326d,
+	0x32a8, 0x326b, 0x326b, 0x080c, 0x254c, 0xa684, 0x0060, 0x0538,
+	0xa086, 0x0060, 0x1510, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6,
+	0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002, 0x0148, 0x080c, 0x3f26,
+	0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x4206, 0x0010, 0x080c,
+	0x41d9, 0x781b, 0x0083, 0x71d0, 0xd1b4, 0x1904, 0x259d, 0x70a0,
+	0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6ec, 0x09f0, 0x6818,
+	0xd0fc, 0x0170, 0xd6f4, 0x1130, 0x681b, 0x0015, 0x781b, 0x0083,
+	0x0804, 0x259d, 0x681b, 0x0007, 0x682f, 0x0000, 0x6833, 0x0000,
+	0x080c, 0x3bf1, 0x0005, 0x080c, 0x254c, 0x2300, 0x0002, 0x32b4,
+	0x32d6, 0x332e, 0x080c, 0x254c, 0x7000, 0x0002, 0x32be, 0x32c0,
+	0x32c7, 0x32be, 0x32be, 0x32be, 0x32be, 0x32be, 0x080c, 0x254c,
+	0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x4206, 0x0010, 0x080c,
+	0x41d9, 0x681c, 0xc0b4, 0x681e, 0x70d0, 0xd0b4, 0x1904, 0x259d,
+	0x70a0, 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6fc, 0x1904,
+	0x331e, 0x7000, 0xa00d, 0x0002, 0x25a0, 0x32ec, 0x32e6, 0x3316,
+	0x32ec, 0x331b, 0x32e4, 0x32e4, 0x080c, 0x254c, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0538, 0xa086,
+	0x0060, 0x1510, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0x6eb6, 0xa186,
+	0x0002, 0x0148, 0x080c, 0x3f26, 0x69ac, 0x68b0, 0xa115, 0x0118,
+	0x080c, 0x4206, 0x0010, 0x080c, 0x41d9, 0x781b, 0x0083, 0x681c,
+	0xc0b4, 0x681e, 0x71d0, 0xd1b4, 0x1904, 0x259d, 0x70a0, 0xa086,
+	0x0001, 0x1904, 0x25e1, 0x0005, 0xd6ec, 0x09f0, 0x6818, 0xd0fc,
+	0x0110, 0x681b, 0x0007, 0x781b, 0x00fb, 0x0005, 0xc6fc, 0x7e5a,
+	0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
+	0xa303, 0x68ae, 0x79d2, 0x781b, 0x0083, 0x0005, 0xd6dc, 0x0130,
+	0x782b, 0x3009, 0x781b, 0x0083, 0x0804, 0x259d, 0x7884, 0xc0ac,
+	0x7886, 0x78e4, 0xa084, 0x0008, 0x1150, 0xa484, 0x0200, 0x0108,
+	0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0083, 0x0804, 0x259d, 0x6820,
+	0xc095, 0x6822, 0x080c, 0x3bdc, 0xc6dd, 0x080c, 0x3a3c, 0x781b,
+	0x0082, 0x0804, 0x259d, 0x2300, 0x0002, 0x3358, 0x335a, 0x335c,
+	0x080c, 0x254c, 0x0804, 0x3a36, 0x7d98, 0xd6d4, 0x15a8, 0x79e4,
+	0xd1ac, 0x0130, 0x78ec, 0xa084, 0x0003, 0x0110, 0x782b, 0x3009,
+	0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x7d9a,
+	0x79e4, 0xd1ac, 0x0120, 0x78ec, 0xa084, 0x0003, 0x1120, 0x2001,
+	0x0014, 0x0804, 0x2f18, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007,
+	0x0090, 0xa184, 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000,
+	0x0050, 0xa184, 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007,
+	0x0010, 0x2001, 0x0001, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b,
+	0x0060, 0x79a8, 0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384,
+	0x0001, 0x11d0, 0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009,
+	0xffdf, 0x0058, 0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028,
+	0xa386, 0x0003, 0x1148, 0x2009, 0xffef, 0x00c6, 0x7054, 0x2060,
+	0x6004, 0xa104, 0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000,
+	0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff,
+	0x6922, 0x7d9a, 0x0804, 0x3be5, 0x2bae, 0x2bb7, 0x33d6, 0x33dc,
+	0x33d4, 0x33d4, 0x3be5, 0x3be5, 0x080c, 0x254c, 0x6920, 0xa18c,
+	0xfcff, 0x6922, 0x0804, 0x3beb, 0x6920, 0xa18c, 0xfcff, 0x6922,
+	0x0804, 0x3be5, 0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084,
+	0x0003, 0x1570, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086,
+	0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a56,
+	0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90,
+	0x7000, 0xa086, 0x0000, 0x0904, 0x259d, 0x6920, 0xa184, 0x0420,
+	0x0128, 0xc1d4, 0x6922, 0x6818, 0x0804, 0x2f18, 0x6818, 0xa08e,
+	0x0002, 0x0120, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0804, 0x2f18,
+	0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007,
+	0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007,
+	0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001,
+	0x0002, 0x3be5, 0x3be5, 0x3439, 0x3be5, 0x3c29, 0x3c29, 0x3be5,
+	0x3be5, 0xd6bc, 0x0570, 0x7180, 0x81ff, 0x0558, 0xa182, 0x000d,
+	0x1318, 0x7083, 0x0000, 0x0028, 0xa182, 0x000c, 0x7082, 0x2009,
+	0x000c, 0x789b, 0x0061, 0x79aa, 0x0156, 0x0136, 0x0146, 0x7084,
+	0x8114, 0xa210, 0x7286, 0xa080, 0x000b, 0xad00, 0x2098, 0xb284,
+	0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, 0x789b,
+	0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e, 0x013e, 0x015e, 0x0804,
+	0x3beb, 0xd6d4, 0x1904, 0x34ac, 0x6820, 0xd084, 0x0904, 0x3beb,
+	0xa68c, 0x0060, 0xa684, 0x0060, 0x0120, 0xa086, 0x0060, 0x1108,
+	0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000,
+	0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c,
+	0x0904, 0x37d3, 0xa18c, 0x00f8, 0x1904, 0x37d3, 0x0156, 0x0136,
+	0x0146, 0x0016, 0x20a1, 0x012b, 0x3208, 0xa18c, 0x0600, 0x0110,
+	0x20a1, 0x022b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
+	0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6814, 0xc0fc,
+	0x8007, 0x7882, 0x0804, 0x3beb, 0x6818, 0xd0fc, 0x0110, 0x681b,
+	0x0008, 0x080c, 0x3a3c, 0x781b, 0x00ed, 0x0005, 0x2300, 0x0002,
+	0x34bd, 0x357a, 0x34bb, 0x080c, 0x254c, 0x7cd8, 0x7ddc, 0x7fd0,
+	0x82ff, 0x1528, 0x7200, 0xa286, 0x0003, 0x0904, 0x2ee6, 0x71d0,
+	0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001, 0x4601, 0x2004, 0xd0c4,
+	0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b, 0x0059, 0x70b8, 0xa06d,
+	0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+	0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x0030, 0x7200,
+	0x0020, 0x783b, 0x1800, 0x781b, 0x0057, 0xa284, 0x000f, 0x0002,
+	0x3565, 0x3522, 0x34fa, 0x2f15, 0x34f8, 0x3565, 0x34f8, 0x34f8,
+	0x080c, 0x254c, 0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a,
+	0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005, 0x1108, 0x6002,
+	0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084, 0x000e, 0x1120, 0x71c8,
+	0xa188, 0x0100, 0x0028, 0x7030, 0x68ba, 0x713c, 0x70c8, 0xa108,
+	0x2104, 0x6802, 0x2d0a, 0x715a, 0xd6dc, 0x1120, 0xc6fc, 0x6eb6,
+	0x0804, 0x3565, 0x6eb6, 0xa684, 0x0060, 0x1120, 0xa684, 0x7fff,
+	0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684, 0x7fff, 0x68b6, 0x6894,
+	0x68a6, 0x6898, 0x68aa, 0x080c, 0x3f26, 0x0478, 0xd6ac, 0x0140,
+	0xa006, 0x080c, 0x3f26, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068,
+	0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291,
+	0x0000, 0x69aa, 0x6aa6, 0x080c, 0x3f26, 0xd6fc, 0x01b0, 0xa684,
+	0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x1138, 0x2700, 0x8007,
+	0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
+	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030,
+	0x1904, 0x25a0, 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e,
+	0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009,
+	0x7042, 0x0005, 0xa586, 0x8800, 0x1148, 0x7003, 0x0000, 0x6018,
+	0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x3a36,
+	0x7043, 0x0000, 0xa282, 0x0006, 0x0310, 0x080c, 0x254c, 0x2300,
+	0x0002, 0x3594, 0x35a5, 0x35af, 0x2200, 0x0002, 0x359c, 0x3a36,
+	0x359e, 0x359c, 0x35e0, 0x362e, 0x080c, 0x254c, 0x7a80, 0xa294,
+	0x0f00, 0x080c, 0x3682, 0x0804, 0x3a0b, 0x00c1, 0x0002, 0x3a36,
+	0x35ad, 0x35ad, 0x35e0, 0x35ad, 0x3a36, 0x080c, 0x254c, 0x0071,
+	0x0002, 0x35b9, 0x35b7, 0x35b7, 0x35b9, 0x35b7, 0x35b9, 0x080c,
+	0x254c, 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005, 0x7000, 0xa086,
+	0x0002, 0x1150, 0x080c, 0x37be, 0x0010, 0x080c, 0x3f26, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003, 0x0da8,
+	0x7003, 0x0005, 0x2001, 0x8de0, 0xae8e, 0x4640, 0x0110, 0x2001,
+	0x8e12, 0x2068, 0x704a, 0xad80, 0x0009, 0x7042, 0x2200, 0x0005,
+	0x7000, 0xa086, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00,
+	0x70b6, 0x2d00, 0x70ba, 0x0038, 0x080c, 0x3f26, 0x0020, 0x7000,
+	0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00,
+	0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x8cc0,
+	0xb284, 0x0600, 0x1118, 0xc2fd, 0x2069, 0x8dd0, 0x2d04, 0x2d08,
+	0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0120, 0x6800, 0x0cb8,
+	0x080c, 0x3682, 0x6eb4, 0x7e5a, 0x6920, 0xa184, 0x0c00, 0x0904,
+	0x36a8, 0x7060, 0xa086, 0x0006, 0x1128, 0x7070, 0xa206, 0x1110,
+	0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad, 0x681b, 0x0005, 0xc1ad,
+	0xc1d4, 0x6922, 0x080c, 0x3a42, 0x0804, 0x36a8, 0x7200, 0xa286,
+	0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00,
+	0x70ba, 0x0030, 0x080c, 0x3f26, 0x0018, 0xa286, 0x0003, 0x0dd0,
+	0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8,
+	0xa484, 0x001f, 0xa215, 0xae86, 0x4640, 0x0108, 0xc2fd, 0x79a8,
+	0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8, 0xa168, 0x2d04, 0x2d08,
+	0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0118, 0x6800, 0x0cb8,
+	0x0409, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0904, 0x36a8, 0xd0dc,
+	0x0178, 0x7060, 0xa086, 0x0004, 0x1140, 0x7070, 0xa206, 0x1128,
+	0x7074, 0xa306, 0x1110, 0x7062, 0x707a, 0x080c, 0x3a48, 0x0480,
+	0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a42, 0x707b,
+	0x0000, 0x0430, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001,
+	0x8de0, 0x0010, 0x2001, 0x8e12, 0x2068, 0x704a, 0x0156, 0x20a9,
+	0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x3691, 0x015e, 0xb284,
+	0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd, 0x6a16, 0xad80, 0x0009,
+	0x7042, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0005,
+	0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x36ef, 0x6b98, 0x6c94, 0x69ac,
+	0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586,
+	0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a,
+	0x2009, 0x0083, 0xd69c, 0x0128, 0x2009, 0x0082, 0x2019, 0x0000,
+	0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c, 0x41d9, 0x0470, 0x68b0,
+	0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01f8, 0x7bd2, 0x7bda,
+	0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108, 0xc6ed, 0xc6f4, 0x7e5a,
+	0x2011, 0x0083, 0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000,
+	0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c, 0x4206, 0x0070, 0x2019,
+	0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083,
+	0xd69c, 0x0110, 0x2009, 0x0082, 0x791a, 0x68c0, 0x7056, 0x2d00,
+	0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001, 0x4601, 0x2004, 0xd0c4,
+	0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc, 0x0548, 0x7a80, 0xa294,
+	0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0, 0xa504, 0x1558, 0x70d6,
+	0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001, 0x852c, 0x0218, 0x8633,
+	0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594, 0xff00, 0x0130, 0x2011,
+	0x0008, 0x852f, 0x0c81, 0x8637, 0x0008, 0x0c69, 0x8217, 0x7880,
+	0xa084, 0x0f00, 0xa206, 0x0170, 0x72da, 0x76d6, 0x0058, 0x7a80,
+	0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0, 0x78e0, 0xa534, 0x0da8,
+	0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x259d, 0x2300, 0xa405, 0x0904,
+	0x259d, 0x70a0, 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0x6020,
 	0xa005, 0x0150, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a,
-	0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3d52,
+	0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3f26,
+	0x7000, 0xa086, 0x0002, 0x0120, 0x7060, 0xa086, 0x0005, 0x1150,
 	0x682b, 0x0000, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
-	0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x248f, 0x358b,
-	0x3588, 0x35a7, 0x3594, 0x248f, 0x3586, 0x3586, 0x080c, 0x243b,
-	0x0441, 0x0409, 0x0028, 0x0429, 0x705c, 0x2060, 0x6800, 0x6002,
-	0x080c, 0x1d3d, 0x0804, 0x248f, 0x7064, 0x7067, 0x0000, 0x7083,
-	0x0000, 0x0002, 0x35a3, 0x35a3, 0x35a2, 0x35a2, 0x35a2, 0x35a3,
-	0x35a2, 0x35a3, 0x2971, 0x7067, 0x0000, 0x0804, 0x248f, 0x681b,
-	0x0000, 0x0804, 0x3012, 0x6800, 0xa005, 0x1108, 0x6002, 0x6006,
-	0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4302, 0x2104, 0x8001,
-	0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4304, 0x2404, 0xc0a5,
-	0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005, 0x0110,
-	0x8001, 0x601a, 0x0005, 0x080c, 0x3aa0, 0x681b, 0x0018, 0x04a0,
-	0x080c, 0x3aa0, 0x681b, 0x0019, 0x0478, 0x080c, 0x3aa0, 0x681b,
-	0x001a, 0x0450, 0x080c, 0x3aa0, 0x681b, 0x0003, 0x0428, 0x7774,
-	0x080c, 0x396d, 0x7178, 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0600,
-	0x0118, 0xa1e8, 0x88c0, 0x0010, 0xa1e8, 0x89d0, 0x2d04, 0x2d08,
-	0x2068, 0xa005, 0x1118, 0x707e, 0x0804, 0x248f, 0x6814, 0xc0fc,
-	0x7274, 0xc2fc, 0xa206, 0x0110, 0x6800, 0x0c88, 0x6800, 0x200a,
-	0x681b, 0x0005, 0x707f, 0x0000, 0x080c, 0x35b1, 0x6820, 0xd084,
-	0x1110, 0x080c, 0x35ab, 0x080c, 0x35c5, 0x681f, 0x0000, 0x6823,
-	0x0020, 0x080c, 0x1d3d, 0x0804, 0x248f, 0xa282, 0x0003, 0x1904,
-	0x380d, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920,
-	0xc1bd, 0x6922, 0xd1c4, 0x0590, 0xc1c4, 0x6922, 0xa6b4, 0x00ff,
-	0x0510, 0xa682, 0x001c, 0x0218, 0x0110, 0x2031, 0x001c, 0x852b,
-	0x852b, 0x2041, 0x0000, 0x080c, 0x38c6, 0x0118, 0x080c, 0x36f6,
-	0x00a0, 0x080c, 0x3892, 0x080c, 0x36f3, 0x6920, 0xc1c5, 0x6922,
-	0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005,
-	0x781b, 0x0082, 0x0005, 0x080c, 0x36f3, 0x7e58, 0xd6d4, 0x1118,
-	0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x00c6, 0x7058,
-	0x2060, 0x6100, 0xd1e4, 0x0578, 0x6208, 0x8217, 0xa294, 0x00ff,
-	0xa282, 0x001c, 0x0218, 0x0110, 0x2011, 0x001c, 0x2600, 0xa202,
-	0x1208, 0x2230, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130,
-	0xa282, 0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c,
-	0x1210, 0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c,
-	0x3896, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x38c6, 0x0118,
-	0x080c, 0x36f6, 0x0020, 0x080c, 0x3892, 0x080c, 0x36f3, 0x7858,
-	0xc095, 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960,
-	0x6000, 0xd0e4, 0x1178, 0x6010, 0xa084, 0x000f, 0x1130, 0x6104,
-	0xa18c, 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032, 0x2019,
-	0x0000, 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294, 0x00ff,
-	0x78ec, 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011, 0x000a,
-	0x0028, 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308, 0x831f,
-	0xa39c, 0x00ff, 0xa382, 0x001c, 0x0218, 0x0110, 0x2019, 0x001c,
-	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
-	0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3850, 0x00ce,
-	0x0005, 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011,
-	0x0032, 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0003,
-	0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
-	0x6822, 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6, 0x7158,
-	0x2160, 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86, 0x6018,
-	0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c, 0x000f,
-	0xa105, 0x2029, 0x4305, 0x252c, 0xd5cc, 0x0140, 0xd3a4, 0x0110,
-	0xa085, 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6, 0x6016,
-	0x788a, 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605, 0x600e,
-	0x6004, 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282, 0x0002,
-	0x1904, 0x3816, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0568,
-	0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04, 0x3809,
-	0x080c, 0x379c, 0x080c, 0x36f3, 0xa980, 0x0001, 0x200c, 0x080c,
-	0x3969, 0x080c, 0x3696, 0x88ff, 0x0178, 0x789b, 0x0060, 0x2800,
-	0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e,
-	0x0005, 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118, 0x781b,
-	0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002, 0x1218,
-	0xa284, 0x0001, 0x0140, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec,
-	0x1110, 0x2011, 0x0000, 0x080c, 0x3883, 0x0471, 0x080c, 0x36f3,
-	0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6, 0x0026,
-	0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1150, 0x6014, 0xa084,
-	0x0040, 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088, 0x2011, 0x0000,
-	0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0,
-	0x0004, 0x080c, 0x3850, 0x6820, 0xa085, 0x0200, 0x6822, 0x002e,
-	0x00ce, 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009, 0x0000, 0x7058,
-	0x2060, 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018, 0xa080, 0x0002,
-	0x789a, 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108,
-	0xc0ed, 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020, 0x78a6, 0x6016,
-	0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce, 0x0005, 0x0006,
-	0x7000, 0xa086, 0x0003, 0x0110, 0x000e, 0x0010, 0x000e, 0x0488,
-	0xd6ac, 0x0578, 0x7888, 0xa084, 0x0040, 0x0558, 0x7bb8, 0x8307,
-	0xa084, 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff, 0xa09e, 0x0001,
-	0x1904, 0x382d, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291,
-	0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x4083, 0x781b,
-	0x0080, 0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001,
-	0x0001, 0x080c, 0x3f50, 0x0005, 0x080c, 0x243b, 0x781b, 0x0080,
-	0x0005, 0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000,
-	0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x36f6, 0x080c, 0x379a,
-	0x7e58, 0x04f9, 0x781b, 0x0082, 0x0005, 0x0cd9, 0x6820, 0xc0c4,
-	0x6822, 0x00c6, 0x7058, 0x2060, 0x0804, 0x3720, 0x0c91, 0x6820,
-	0xc0cc, 0x6822, 0x00c6, 0x7058, 0x2060, 0x0804, 0x37b9, 0x0c49,
-	0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7058, 0x2060, 0x6004,
-	0xa084, 0xffc5, 0x6006, 0x00ce, 0x0005, 0x0049, 0x781b, 0x0082,
-	0x0005, 0x6827, 0x0002, 0x0049, 0x781b, 0x0082, 0x0005, 0x2001,
-	0x0005, 0x0088, 0x2001, 0x000c, 0x0070, 0x6820, 0xc0d5, 0x6822,
-	0x2001, 0x0006, 0x0040, 0x2001, 0x000d, 0x0028, 0x2001, 0x0009,
-	0x0010, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a,
-	0x70d4, 0xd0b4, 0x0168, 0xc0b4, 0x70d6, 0x00c6, 0x70b8, 0xa065,
-	0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce,
-	0x0005, 0x0076, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703,
-	0xb28c, 0x0600, 0x0118, 0xa0e0, 0x47c0, 0x0010, 0xa0e0, 0x4840,
-	0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x7fe0, 0x78ae, 0x6012,
-	0x79a4, 0xa184, 0x773f, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0038,
-	0x6006, 0x007e, 0x0005, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab,
-	0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004,
-	0x0804, 0x3850, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080,
-	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
-	0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3850, 0x0156, 0x8007,
-	0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
-	0xa18c, 0xffe0, 0x2021, 0x3952, 0x2019, 0x0011, 0x20a9, 0x000e,
-	0x2011, 0x0032, 0x2404, 0xa084, 0xffe0, 0xa106, 0x0128, 0x8420,
-	0x2300, 0xa210, 0x1f04, 0x38ba, 0x015e, 0x0005, 0x0156, 0x0804,
-	0x3908, 0x2021, 0x3960, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582,
-	0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033, 0xa582, 0x0033,
-	0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0065, 0x2200,
-	0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x38df, 0x015e,
-	0x0088, 0x2021, 0x3952, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
-	0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300, 0xa210, 0x1f04,
-	0x38f1, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064,
-	0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x0005,
-	0xa886, 0x0002, 0x01e8, 0x2021, 0x393e, 0x20a9, 0x000d, 0x2011,
-	0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019, 0x0019, 0x2011,
-	0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300, 0xa210, 0x1f04,
-	0x3919, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890,
-	0x2021, 0x394d, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024,
-	0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028, 0x0930, 0x8420,
-	0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x38f1, 0x1021, 0x2202,
-	0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610, 0x4612, 0x5812,
-	0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021, 0xb002, 0xe204,
-	0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
-	0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
-	0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07, 0x7e07,
-	0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784, 0x0f00, 0x800b,
-	0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xd7fc,
-	0x0118, 0xa0e0, 0x68c0, 0x0010, 0xa0e0, 0x48c0, 0x0005, 0x00e6,
-	0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4380, 0x2071,
-	0x4380, 0x0030, 0x2009, 0x4340, 0x2079, 0x0200, 0x2071, 0x4340,
-	0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x39c5, 0x39a0,
-	0x39a0, 0x39a0, 0x39a0, 0x39a0, 0x399e, 0x399e, 0x080c, 0x243b,
-	0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b, 0x0008,
-	0x7848, 0xa084, 0x0008, 0x1de0, 0x68b4, 0xc0f5, 0x68b6, 0x7858,
-	0xc0f5, 0x785a, 0x7830, 0xd0bc, 0x1180, 0xb284, 0x0800, 0x0118,
-	0x0104, 0x39c5, 0x0010, 0x0304, 0x39c5, 0x681c, 0xd0ac, 0x1118,
-	0x080c, 0x3a4b, 0x0010, 0x781b, 0x00fb, 0x2091, 0x8001, 0x00fe,
-	0x00ee, 0x0005, 0x00c6, 0x2001, 0x4301, 0x2004, 0xd0ac, 0x1904,
-	0x3a3d, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xb28c, 0x0600, 0x0118, 0xa0e0, 0x47c0, 0x0010, 0xa0e0, 0x4840,
-	0x6004, 0xa084, 0x000a, 0x1904, 0x3a3d, 0x6108, 0xa194, 0xff00,
-	0x0904, 0x3a3d, 0xa18c, 0x00ff, 0x601c, 0xa084, 0xff00, 0x0180,
-	0x2001, 0x0009, 0xa102, 0x16b8, 0x2001, 0x000a, 0xa102, 0x16b0,
-	0x2001, 0x000c, 0xa102, 0x16a8, 0x601c, 0xa084, 0x00ff, 0x601e,
-	0x2001, 0x000a, 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0,
-	0x2001, 0x0012, 0xa106, 0x0198, 0x2001, 0x0014, 0xa106, 0x0190,
-	0x2001, 0x0019, 0xa106, 0x0188, 0x2001, 0x0032, 0xa106, 0x0180,
-	0x00d8, 0x2009, 0x000c, 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009,
-	0x0014, 0x00a0, 0x2009, 0x0019, 0x0088, 0x2009, 0x0020, 0x0070,
-	0x2009, 0x003f, 0x0058, 0x2009, 0x000a, 0x0040, 0x2009, 0x000c,
-	0x0028, 0x2009, 0x0019, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205,
-	0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x00ce, 0x0005, 0x781b,
-	0x0083, 0x0005, 0x781b, 0x0082, 0x0005, 0x781b, 0x0071, 0x0005,
-	0x781b, 0x006e, 0x0005, 0x2009, 0x4319, 0x210c, 0xa186, 0x0000,
-	0x0150, 0xa186, 0x0001, 0x0150, 0x701f, 0x000b, 0x7067, 0x0001,
-	0x781b, 0x0054, 0x0005, 0x781b, 0x00f3, 0x0005, 0x701f, 0x000a,
-	0x0005, 0x2009, 0x4319, 0x210c, 0xa186, 0x0000, 0x0168, 0xa186,
-	0x0001, 0x0138, 0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0054,
-	0x0005, 0x701f, 0x000a, 0x0005, 0x781b, 0x00f2, 0x0005, 0x781b,
-	0x00fb, 0x0005, 0x781b, 0x00fa, 0x0005, 0x781b, 0x00cc, 0x0005,
-	0x781b, 0x00cb, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d,
-	0x7067, 0x0001, 0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0,
-	0x1170, 0x7808, 0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000,
-	0x78ec, 0xa084, 0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005,
-	0x7808, 0xc08d, 0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0,
-	0xb284, 0x0800, 0x0118, 0x1104, 0x3ab2, 0x0010, 0x1304, 0x3ab2,
-	0x78ac, 0x0005, 0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000,
-	0xe000, 0xe000, 0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800,
-	0x0118, 0x1104, 0x3ac1, 0x0010, 0x1304, 0x3ac4, 0x78ac, 0x0006,
-	0x7808, 0xa085, 0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001,
-	0x1904, 0x30a0, 0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68,
-	0x080c, 0x23e1, 0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148,
-	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x248f, 0x0804,
-	0x3a3f, 0xa784, 0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8,
-	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x248f, 0x78e4,
-	0xa084, 0x0007, 0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800,
-	0x2030, 0x7e5a, 0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140,
-	0x7884, 0xd0fc, 0x0128, 0x080c, 0x382d, 0x681b, 0x0022, 0x0005,
-	0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000,
-	0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904,
-	0x2a7a, 0xb284, 0x0800, 0x0110, 0x0104, 0x248c, 0x0304, 0x248c,
-	0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc,
-	0x0118, 0xa080, 0x4840, 0x0010, 0xa080, 0x47c0, 0x2060, 0x2048,
-	0x705a, 0x2a60, 0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904,
-	0x3b81, 0xd1ac, 0x05e0, 0x6108, 0x8117, 0xa18c, 0x00ff, 0x631c,
-	0x832f, 0x68a0, 0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec,
-	0xd0e4, 0x0110, 0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c,
-	0x1290, 0x78ec, 0xd0e4, 0x1118, 0x2009, 0x000c, 0x0060, 0xa182,
-	0x000b, 0x1248, 0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011,
-	0x0000, 0x2029, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
-	0x0004, 0x79aa, 0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0,
-	0x0008, 0x6820, 0xa085, 0x1000, 0x6822, 0x080c, 0x3850, 0xa085,
-	0x0001, 0x00ce, 0x0005, 0xa282, 0x0006, 0x1904, 0x381f, 0x7da8,
-	0x7eac, 0x8637, 0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747,
-	0xa7bc, 0x00ff, 0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4,
-	0x05c8, 0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x37fc,
-	0xa6b4, 0x00ff, 0x0560, 0xa682, 0x0039, 0x1a04, 0x37fc, 0xa582,
-	0x0009, 0x0a04, 0x37fc, 0xa882, 0x0003, 0x1a04, 0x37fc, 0xa886,
-	0x0002, 0x0128, 0xa886, 0x0000, 0x0138, 0x0804, 0x37fc, 0xa786,
-	0x0000, 0x0904, 0x37fc, 0x8634, 0x852b, 0x852b, 0x080c, 0x38c6,
-	0x0904, 0x37fc, 0x080c, 0x36f6, 0x080c, 0x379a, 0x7e58, 0xd6d4,
-	0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x080c,
-	0x36f3, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7158, 0xa188,
-	0x0000, 0x210c, 0xd1ac, 0x0904, 0x37fc, 0xd1ec, 0x1120, 0x2039,
-	0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000, 0x2041,
-	0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff, 0xa706,
-	0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f, 0xa39c,
-	0x00ff, 0x0168, 0xa302, 0x1208, 0x2330, 0x8807, 0xa705, 0xa086,
-	0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000, 0x2041,
-	0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284, 0xff00,
-	0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128, 0x852b,
-	0x852b, 0x080c, 0x38c6, 0x0d58, 0x080c, 0x36f6, 0x080c, 0x379a,
-	0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004,
-	0x78ab, 0x0000, 0x7daa, 0x7eaa, 0x7faa, 0x2800, 0x78aa, 0x789b,
-	0x0060, 0x78ab, 0x0005, 0x080c, 0x3850, 0x7858, 0xc095, 0x785a,
-	0x781b, 0x0082, 0x0005, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x25a0, 0x3783,
+	0x3780, 0x37a0, 0x378c, 0x25a0, 0x377e, 0x377e, 0x080c, 0x254c,
+	0x0449, 0x0411, 0x0028, 0x0431, 0x7058, 0x2060, 0x6800, 0x6002,
+	0x080c, 0x1da2, 0x0804, 0x25a0, 0x7060, 0x7063, 0x0000, 0x707f,
+	0x0000, 0x0002, 0x379c, 0x379c, 0x379a, 0x379a, 0x379a, 0x379c,
+	0x379a, 0x379c, 0x0804, 0x2a6b, 0x7063, 0x0000, 0x0804, 0x25a0,
+	0x681b, 0x0000, 0x0804, 0x3184, 0x6800, 0xa005, 0x1108, 0x6002,
+	0x6006, 0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4602, 0x2104,
+	0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4604, 0x2404,
+	0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005,
+	0x0110, 0x8001, 0x601a, 0x0005, 0x080c, 0x3c46, 0x681b, 0x0018,
+	0x0490, 0x080c, 0x3c46, 0x681b, 0x0019, 0x0468, 0x080c, 0x3c46,
+	0x681b, 0x001a, 0x0440, 0x080c, 0x3c46, 0x681b, 0x0003, 0x0418,
+	0x7770, 0x080c, 0x3b6f, 0x7174, 0xa18c, 0x00ff, 0x3210, 0xa294,
+	0x0600, 0x0118, 0xa1e8, 0x8bc0, 0x0010, 0xa1e8, 0x8cd0, 0x2d04,
+	0x2d08, 0x2068, 0xa005, 0x1118, 0x707a, 0x0804, 0x25a0, 0x6814,
+	0x7270, 0xa206, 0x0110, 0x6800, 0x0c98, 0x6800, 0x200a, 0x681b,
+	0x0005, 0x707b, 0x0000, 0x080c, 0x37aa, 0x6820, 0xd084, 0x1110,
+	0x080c, 0x37a4, 0x080c, 0x37be, 0x681f, 0x0000, 0x6823, 0x0020,
+	0x080c, 0x1da2, 0x0804, 0x25a0, 0xa282, 0x0003, 0x1904, 0x3a10,
+	0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd,
+	0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0530,
+	0xa682, 0x0018, 0x0218, 0x0110, 0x2031, 0x0018, 0xa686, 0x0010,
+	0x1108, 0x8630, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3ac9,
+	0x0118, 0x080c, 0x38f7, 0x00a0, 0x080c, 0x3a95, 0x080c, 0x38f4,
+	0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118,
+	0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x080c, 0x38f4,
+	0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083,
+	0x0005, 0x00c6, 0x7054, 0x2060, 0x6100, 0xd1e4, 0x0598, 0x6208,
+	0x8217, 0xa294, 0x00ff, 0xa282, 0x0018, 0x0218, 0x0110, 0x2011,
+	0x0018, 0x2600, 0xa202, 0x1208, 0x2230, 0xa686, 0x0010, 0x1108,
+	0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282,
+	0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210,
+	0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c, 0x3a99,
+	0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3ac9, 0x0118, 0x080c,
+	0x38f7, 0x0020, 0x080c, 0x3a95, 0x080c, 0x38f4, 0x7858, 0xc095,
+	0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960, 0x6000,
+	0xd0e4, 0x1188, 0xd0b4, 0x1150, 0x6010, 0xa084, 0x000f, 0x1130,
+	0x6104, 0xa18c, 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032,
+	0x2019, 0x0000, 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294,
+	0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011,
+	0x000a, 0x0028, 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308,
+	0x831f, 0xa39c, 0x00ff, 0xa382, 0x0018, 0x0218, 0x0110, 0x2019,
+	0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa,
+	0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3a55,
+	0x00ce, 0x0005, 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106,
+	0x2011, 0x0032, 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab,
+	0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820,
+	0xc0c5, 0x6822, 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6,
+	0x7154, 0x2160, 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86,
+	0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c,
+	0x000f, 0xa105, 0x2029, 0x4605, 0x252c, 0xd5cc, 0x0140, 0xd3a4,
+	0x0110, 0xa085, 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6,
+	0x6016, 0x788a, 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605,
+	0x600e, 0x6004, 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282,
+	0x0002, 0x1904, 0x3a1a, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc,
+	0x0568, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04,
+	0x3a0b, 0x080c, 0x399e, 0x080c, 0x38f4, 0xa980, 0x0001, 0x200c,
+	0x080c, 0x3b6b, 0x080c, 0x3895, 0x88ff, 0x0178, 0x789b, 0x0060,
+	0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
+	0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118,
+	0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002,
+	0x1218, 0xa284, 0x0001, 0x0140, 0x7154, 0xa188, 0x0000, 0x210c,
+	0xd1ec, 0x1110, 0x2011, 0x0000, 0x080c, 0x3a87, 0x0479, 0x080c,
+	0x38f4, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6,
+	0x0026, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1158, 0xd0bc,
+	0x1138, 0x6014, 0xd0b4, 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088,
+	0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
+	0x7aaa, 0xa8c0, 0x0004, 0x080c, 0x3a55, 0x6820, 0xa085, 0x0200,
+	0x6822, 0x002e, 0x00ce, 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009,
+	0x0000, 0x7054, 0x2060, 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018,
+	0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec,
+	0xd0b4, 0x1108, 0xc0ed, 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020,
+	0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce,
+	0x0005, 0x0006, 0x7000, 0xa086, 0x0003, 0x0110, 0x000e, 0x0010,
+	0x000e, 0x0488, 0xd6ac, 0x0578, 0x7888, 0xa084, 0x0040, 0x0558,
+	0x7bb8, 0x8307, 0xa084, 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff,
+	0xa09e, 0x0001, 0x1904, 0x3a32, 0xd6f4, 0x11d0, 0x79d8, 0x7adc,
+	0xa108, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c,
+	0x42b5, 0x781b, 0x0080, 0xb284, 0x0600, 0x0118, 0x2001, 0x0000,
+	0x0010, 0x2001, 0x0001, 0x080c, 0x4172, 0x0005, 0x080c, 0x254c,
+	0x781b, 0x0080, 0x0005, 0x781b, 0x0083, 0x0005, 0x2039, 0x0000,
+	0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7,
+	0x080c, 0x399c, 0x7e58, 0x080c, 0x3a4e, 0x781b, 0x0082, 0x0005,
+	0x0cd1, 0x6820, 0xc0c4, 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c,
+	0x3921, 0x00b0, 0x0c81, 0x6820, 0xc0cc, 0x6822, 0x00c6, 0x7054,
+	0x2060, 0x080c, 0x39bb, 0x0060, 0x0c31, 0x6820, 0xa084, 0xecff,
+	0x6822, 0x00c6, 0x7054, 0x2060, 0x6004, 0xa084, 0xffc5, 0x6006,
+	0x00ce, 0x0005, 0x0049, 0x781b, 0x0082, 0x0005, 0x6827, 0x0002,
+	0x0049, 0x781b, 0x0082, 0x0005, 0x2001, 0x0005, 0x0088, 0x2001,
+	0x000c, 0x0070, 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040,
+	0x2001, 0x000d, 0x0028, 0x2001, 0x0009, 0x0010, 0x2001, 0x0007,
+	0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d0, 0xd0b4, 0x0168,
+	0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x0076, 0x873f,
+	0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, 0x4ac0, 0xae8e,
+	0x4640, 0x0110, 0xa0e0, 0x4b40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4,
+	0xa184, 0x7fe0, 0x78ae, 0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6,
+	0x6016, 0x6004, 0xa085, 0x0038, 0x6006, 0x007e, 0x0005, 0x789b,
+	0x0080, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
+	0x789b, 0x0060, 0x78ab, 0x0004, 0x0800, 0x2031, 0x0000, 0x2029,
+	0x0032, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
+	0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804,
+	0x3a55, 0x0156, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080,
+	0x0020, 0x789a, 0x79a4, 0xa18c, 0xffe0, 0x2021, 0x3b54, 0x2019,
+	0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xffe0,
+	0xa106, 0x0128, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3abd, 0x015e,
+	0x0005, 0x0156, 0x04f8, 0x2021, 0x3b62, 0x20a9, 0x0009, 0x2011,
+	0x0029, 0xa582, 0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033,
+	0xa582, 0x0033, 0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011,
+	0x0065, 0x2200, 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04,
+	0x3ae1, 0x015e, 0x0088, 0x2021, 0x3b54, 0x2019, 0x0011, 0x20a9,
+	0x000e, 0x2011, 0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300,
+	0xa210, 0x1f04, 0x3af3, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e,
+	0xa582, 0x0064, 0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404,
+	0xa005, 0x0005, 0xa886, 0x0002, 0x01e8, 0x2021, 0x3b40, 0x20a9,
+	0x000d, 0x2011, 0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019,
+	0x0019, 0x2011, 0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300,
+	0xa210, 0x1f04, 0x3b1b, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185,
+	0x0ab0, 0x0890, 0x2021, 0x3b4f, 0x20a9, 0x0003, 0x2011, 0x0024,
+	0xa586, 0x0024, 0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028,
+	0x0930, 0x8420, 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3af3,
+	0x1021, 0x2202, 0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610,
+	0x4612, 0x5812, 0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021,
+	0xb002, 0xe204, 0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203,
+	0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07,
+	0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06,
+	0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784,
+	0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003,
+	0xa105, 0xd7fc, 0x0118, 0xa0e0, 0x6bc0, 0x0010, 0xa0e0, 0x4bc0,
+	0x0005, 0x00e6, 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009,
+	0x4680, 0x2071, 0x4680, 0x0030, 0x2009, 0x4640, 0x2079, 0x0200,
+	0x2071, 0x4640, 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002,
+	0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba0, 0x3ba0,
+	0x080c, 0x254c, 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005,
+	0x0580, 0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828,
+	0xa086, 0x1814, 0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+	0x1de0, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830,
+	0xd0bc, 0x11b8, 0xb284, 0x0800, 0x0118, 0x0104, 0x3bd9, 0x0010,
+	0x0304, 0x3bd9, 0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084,
+	0x0003, 0x0138, 0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b,
+	0x00fb, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x4601, 0x2004, 0xd0ac,
+	0x1118, 0x6814, 0x080c, 0x2475, 0x0005, 0x781b, 0x0083, 0x0005,
+	0x781b, 0x0082, 0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e,
+	0x0005, 0x2009, 0x4619, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186,
+	0x0001, 0x0150, 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054,
+	0x0005, 0x781b, 0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009,
+	0x4619, 0x210c, 0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138,
+	0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f,
+	0x000a, 0x0005, 0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005,
+	0x781b, 0x00fa, 0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb,
+	0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x7063, 0x0001,
+	0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0, 0x1170, 0x7808,
+	0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000, 0x78ec, 0xa084,
+	0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005, 0x7808, 0xc08d,
+	0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0, 0xb284, 0x0800,
+	0x0118, 0x1104, 0x3c58, 0x0010, 0x1304, 0x3c58, 0x78ac, 0x0005,
+	0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000,
+	0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800, 0x0118, 0x1104,
+	0x3c67, 0x0010, 0x1304, 0x3c6a, 0x78ac, 0x0006, 0x7808, 0xa085,
+	0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x322a,
+	0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2467,
+	0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148, 0x784b, 0x0008,
+	0x78ec, 0xa084, 0x0003, 0x0904, 0x322a, 0x0804, 0x3be5, 0xa784,
+	0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8, 0x784b, 0x0008,
+	0x78ec, 0xa084, 0x0003, 0x0904, 0x322a, 0x78e4, 0xa084, 0x0007,
+	0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a,
+	0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140, 0x7884, 0xd0fc,
+	0x0128, 0x080c, 0x3a32, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003,
+	0x7858, 0xa084, 0x5f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000,
+	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x2b89, 0xb284,
+	0x0800, 0x0110, 0x0104, 0x259d, 0x0304, 0x259d, 0x6b14, 0x8307,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, 0x0118, 0xa080,
+	0x4b40, 0x0010, 0xa080, 0x4ac0, 0x2060, 0x2048, 0x7056, 0x2a60,
+	0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3d2f, 0x68a0,
+	0xd1ac, 0x1120, 0xa084, 0x0e00, 0x0904, 0x3d2d, 0x6108, 0x8117,
+	0xa18c, 0x00ff, 0x631c, 0x832f, 0xd0dc, 0x0110, 0xa39d, 0x0001,
+	0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec, 0xd0e4, 0x0110,
+	0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c, 0x1290, 0x78ec,
+	0xd0e4, 0x1118, 0x2009, 0x000c, 0x0060, 0xa182, 0x000b, 0x1248,
+	0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011, 0x0000, 0x2029,
+	0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, 0x79aa,
+	0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0, 0x0008, 0x6820,
+	0xa085, 0x1000, 0x6822, 0x080c, 0x3a55, 0xa085, 0x0001, 0x00ce,
+	0x0005, 0xa282, 0x0006, 0x1904, 0x3a24, 0x7da8, 0x7eac, 0x8637,
+	0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747, 0xa7bc, 0x00ff,
+	0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3da3,
+	0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x39fe, 0xa6b4,
+	0x00ff, 0x0904, 0x3da0, 0xa682, 0x0031, 0x1a04, 0x39fe, 0xa582,
+	0x0009, 0x0a04, 0x39fe, 0xa882, 0x0003, 0x1a04, 0x39fe, 0xa886,
+	0x0002, 0x01d0, 0xa886, 0x0000, 0x1904, 0x39fe, 0x2001, 0x000c,
+	0x79ec, 0xd1e4, 0x0110, 0x2001, 0x000a, 0xa502, 0x1290, 0x080c,
+	0x39fe, 0x00c6, 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000,
+	0xc0ac, 0x6002, 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x39fe,
+	0x8634, 0xa682, 0x0018, 0x0228, 0x0120, 0x2031, 0x0018, 0x0804,
+	0x3df1, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c,
+	0x3ac9, 0x0904, 0x39fe, 0x080c, 0x38f7, 0x080c, 0x399c, 0x7e58,
+	0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005,
+	0x080c, 0x38f4, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154,
+	0xa188, 0x0000, 0x210c, 0xd1ac, 0x0904, 0x39fe, 0xd1ec, 0x1120,
+	0x2039, 0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000,
+	0x2041, 0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff,
+	0xa706, 0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f,
+	0xa39c, 0x00ff, 0x0168, 0xa302, 0x1208, 0x2330, 0x8807, 0xa705,
+	0xa086, 0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000,
+	0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284,
+	0xff00, 0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128,
+	0x852b, 0x852b, 0x080c, 0x3ac9, 0x0d58, 0x080c, 0x38f7, 0x080c,
+	0x399c, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
+	0x0004, 0x7daa, 0x78ab, 0x0000, 0x7eaa, 0x7faa, 0x2800, 0x78aa,
+	0x789b, 0x0060, 0x78ab, 0x0008, 0x6820, 0xc0e5, 0x6822, 0x080c,
+	0x3a55, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x0020,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014,
-	0x0014, 0x9855, 0x984d, 0x0014, 0x9911, 0x98ff, 0x0014, 0x0014,
-	0x0090, 0x00e7, 0x0100, 0x0402, 0x2008, 0xf880, 0x0018, 0x0017,
-	0x840f, 0xd8c1, 0x0014, 0x0016, 0xa20a, 0x0014, 0x300b, 0xa20c,
-	0x0014, 0x2500, 0x0013, 0x2500, 0x0010, 0x0010, 0x0010, 0x0010,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
+	0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9855, 0x984d, 0x0014,
+	0x9911, 0x98ff, 0x0014, 0x0014, 0x0090, 0x00e7, 0x0100, 0x0402,
+	0x2008, 0xf880, 0x0018, 0x0017, 0x840f, 0xd8c1, 0x0014, 0x0016,
+	0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0x2500, 0x0013, 0x2500,
 	0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
-	0x0010, 0x0010, 0xa200, 0x3806, 0x8839, 0x20c4, 0x0864, 0xa84f,
-	0x3008, 0x28c1, 0x9d18, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a,
-	0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9cce, 0xa8f3,
-	0x0864, 0xa83d, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9cce, 0x2021,
-	0xa818, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x67a4,
-	0x6c80, 0x0212, 0xa205, 0x883d, 0x882b, 0x1814, 0x883b, 0x7027,
-	0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa814, 0x883e,
-	0xa812, 0x280a, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x1814,
-	0x883b, 0x7027, 0x8576, 0x8677, 0xa806, 0x796d, 0xa8da, 0x796b,
-	0xa8f1, 0x7861, 0x883e, 0x206b, 0x28c1, 0x9d18, 0x2044, 0x2103,
-	0x20b4, 0x2095, 0xa8ca, 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203,
-	0x8000, 0x85a4, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208,
-	0x856e, 0x866f, 0x7121, 0x0014, 0x0704, 0x3008, 0x9cce, 0x0014,
-	0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e,
-	0x883f, 0x08e6, 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, 0xf881,
-	0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532,
-	0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008,
-	0x8000, 0x2849, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2081,
-	0x2802, 0x1011, 0xa8fc, 0xa889, 0x3008, 0x20a1, 0x283c, 0x1011,
-	0xa8fc, 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1,
-	0x0014, 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2,
-	0x26e0, 0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210,
-	0x9d22, 0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823,
-	0x0016, 0x6042, 0x8008, 0xa8fa, 0x8160, 0x842a, 0x8180, 0xf021,
-	0x3008, 0x84a8, 0x11d7, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822,
-	0x0016, 0x0000, 0x0126, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090,
-	0x7204, 0x7008, 0xc09c, 0xa205, 0x1178, 0x720c, 0x82ff, 0x0128,
-	0x8aff, 0x1150, 0x7200, 0xd284, 0x1138, 0x7007, 0x0004, 0x7003,
-	0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003, 0x7002,
-	0xc69c, 0xd084, 0x05b8, 0x2001, 0x4301, 0x2004, 0xd0b4, 0x0904,
-	0x3dcf, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184, 0x0003,
-	0x0904, 0x3dcf, 0xa184, 0x01e0, 0x1904, 0x3dcf, 0xd1f4, 0x1d88,
-	0xa184, 0x3000, 0xa086, 0x1000, 0x0d60, 0x2011, 0x0180, 0x710c,
-	0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20, 0x700c, 0xa106, 0x0dc0,
-	0x7007, 0x0012, 0x7108, 0xe000, 0x7008, 0xa106, 0x1dd8, 0xa184,
-	0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4, 0x0548, 0x7007, 0x0002,
-	0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130, 0x080c, 0x3e9e, 0x8aff,
-	0x0904, 0x3d58, 0x0cb8, 0x700c, 0xa08c, 0x07ff, 0x01e8, 0x7004,
-	0xd084, 0x0178, 0x7014, 0xa005, 0x1148, 0x7010, 0x7310, 0xa306,
-	0x1de0, 0x2300, 0xa005, 0x0128, 0xa102, 0x1e20, 0x7007, 0x0010,
-	0x0030, 0x8aff, 0x0148, 0x080c, 0x4046, 0x1de8, 0x09d8, 0x080c,
-	0x3e58, 0x012e, 0x2000, 0x0005, 0x7204, 0x7108, 0xc19c, 0x8103,
-	0x1218, 0x080c, 0x3e9e, 0x0cc0, 0xa205, 0x1d88, 0x7007, 0x0004,
-	0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x6428, 0x84ff, 0x0508,
-	0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb,
-	0x1148, 0x0210, 0x080c, 0x243b, 0x609c, 0xa075, 0x0190, 0x0c88,
-	0x2039, 0x3e0e, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529,
-	0x8421, 0x0138, 0x8738, 0x2704, 0xa005, 0x1da8, 0x709c, 0xa075,
-	0x1d00, 0x0005, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011, 0x0015,
-	0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b,
-	0x0000, 0x0000, 0x3e0e, 0x3e0b, 0x0000, 0x0000, 0x8000, 0x0000,
-	0x3e0e, 0x0000, 0x3e16, 0x3e13, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x3e16, 0x0000, 0x3e11, 0x3e11, 0x0000, 0x0000, 0x8000, 0x0000,
-	0x3e11, 0x0000, 0x3e17, 0x3e17, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x3e17, 0x2079, 0x4300, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007,
-	0x0002, 0x7003, 0x0001, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007,
-	0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1128, 0x8109, 0x0118, 0x2071, 0x0020, 0x0c80, 0x0005,
-	0x7004, 0x8004, 0x1690, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
-	0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110, 0x080c, 0x243b,
-	0xa19c, 0x300c, 0xa386, 0x2004, 0x0130, 0xa386, 0x0008, 0x0160,
-	0xa386, 0x200c, 0x1d60, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384,
-	0x07ff, 0x0110, 0x080c, 0x243b, 0x7007, 0x0012, 0x7000, 0xd084,
-	0x1160, 0x7008, 0xa084, 0x01e0, 0x1140, 0x7310, 0x7014, 0xa305,
-	0x0120, 0x710c, 0xa184, 0x07ff, 0x1958, 0x7007, 0x0012, 0x7007,
-	0x0008, 0x7004, 0xd09c, 0x1de8, 0x7007, 0x0012, 0x7108, 0x8103,
-	0x0ed8, 0x7003, 0x0008, 0x0005, 0x7108, 0x0000, 0xa184, 0x01e0,
-	0x1550, 0x7108, 0xa184, 0x01e0, 0x1530, 0xa184, 0x0007, 0x0002,
-	0x3eb2, 0x3ec0, 0x3eb0, 0x3ec0, 0x3eb0, 0x3f06, 0x3eb0, 0x3f05,
-	0x080c, 0x243b, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
-	0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x4046, 0x1de8, 0x0005,
-	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x0118, 0x080c,
-	0x4046, 0x1de8, 0x0005, 0x7007, 0x0012, 0x7108, 0x1d04, 0x3ece,
-	0x2091, 0x6000, 0x1d04, 0x3ed2, 0x2091, 0x6000, 0x7007, 0x0012,
-	0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8, 0x7007, 0x0012, 0x7108,
-	0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000, 0xa005, 0x1130, 0x7004,
-	0xa005, 0x1118, 0x700c, 0xa005, 0x0108, 0x0c40, 0x2049, 0x0000,
-	0xb284, 0x0200, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001,
-	0x080c, 0x397f, 0x6818, 0xa084, 0x8000, 0x0110, 0x681b, 0x0002,
-	0x0005, 0x080c, 0x243b, 0x080c, 0x243b, 0x04b9, 0x7210, 0x7114,
-	0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
-	0x0461, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c,
-	0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238, 0x8412, 0x8210,
-	0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60, 0x8a07, 0x0006,
-	0x6004, 0xa084, 0x0008, 0x0118, 0xa7ba, 0x3e13, 0x0010, 0xa7ba,
-	0x3e0b, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e,
-	0x7007, 0x0012, 0x080c, 0x3e58, 0x0005, 0x8a50, 0x8739, 0x2704,
-	0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60, 0x6004, 0xa084,
-	0x000f, 0xa080, 0x3e29, 0x203c, 0x87fb, 0x090c, 0x243b, 0x0005,
-	0x0126, 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
-	0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff,
-	0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008, 0x000e, 0x0118,
-	0xa0b8, 0x3e13, 0x0010, 0xa0b8, 0x3e0b, 0xb284, 0x0200, 0x0110,
-	0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0108,
-	0xc685, 0x2400, 0xa305, 0x0520, 0x2c58, 0x2704, 0x6104, 0xac60,
-	0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, 0x0008,
-	0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000,
-	0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203,
-	0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x4067, 0x0010,
-	0x080c, 0x4046, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6,
-	0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004,
-	0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005,
-	0x0126, 0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
-	0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c, 0x681c,
-	0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050, 0x2d60,
-	0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, 0x1138,
-	0x0210, 0x080c, 0x243b, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c,
-	0x4046, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016,
-	0x00d6, 0x70d4, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284,
-	0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5, 0x000c,
-	0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
-	0x2049, 0x3fe5, 0x6828, 0xa055, 0x05f0, 0x2d70, 0x2e60, 0x7004,
-	0xa0bc, 0x000f, 0xa7b8, 0x3e19, 0x273c, 0x87fb, 0x1140, 0x0210,
-	0x080c, 0x243b, 0x709c, 0xa075, 0x2060, 0x0568, 0x0c80, 0x2704,
-	0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268, 0x8a51, 0x1110,
-	0x080c, 0x243b, 0x8738, 0x2704, 0xa005, 0x1d90, 0x709c, 0xa075,
-	0x2060, 0x01c8, 0x08e0, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000,
-	0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1210, 0x080c,
-	0x243b, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050, 0x0010, 0x2071,
-	0x0020, 0x0804, 0x3f79, 0x012e, 0x2000, 0x0005, 0x7008, 0xa084,
-	0x0003, 0xa086, 0x0003, 0x1108, 0x0005, 0x2704, 0xac78, 0x7800,
-	0x701a, 0x7804, 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004,
-	0xa084, 0x0008, 0x0120, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602,
-	0x7004, 0xa084, 0x0010, 0xc085, 0x7006, 0x2079, 0x4300, 0x8a51,
-	0x01b0, 0x8738, 0x2704, 0xa005, 0x1168, 0x609c, 0xa005, 0x0180,
-	0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x3e19, 0x203c, 0x87fb,
-	0x090c, 0x243b, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x0005,
-	0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6, 0x70d4, 0xa084,
-	0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108, 0xa184, 0x0003,
-	0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3d6c, 0x7108, 0xd1fc,
-	0x0118, 0x080c, 0x3e9e, 0x0c88, 0x7007, 0x0010, 0x7108, 0xd1fc,
-	0x0de8, 0x080c, 0x3e9e, 0x7008, 0xa086, 0x0008, 0x1d30, 0x7000,
-	0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000, 0x012e, 0x2000,
-	0x0005, 0x0126, 0x0146, 0x0136, 0x0156, 0x00c6, 0x00d6, 0x70d4,
-	0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x2049, 0x40b1, 0xad80,
-	0x0011, 0x20a0, 0xb284, 0x0200, 0x0118, 0x2099, 0x0032, 0x0010,
-	0x2099, 0x0031, 0x700c, 0xa084, 0x07ff, 0x682a, 0x7007, 0x0008,
-	0x7007, 0x0002, 0x7003, 0x0001, 0x0118, 0x8000, 0x80ac, 0x53a5,
-	0x700c, 0xa084, 0x07ff, 0x0130, 0x7007, 0x0004, 0x7004, 0xa084,
-	0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000, 0x7003, 0x0000, 0x015e,
-	0x013e, 0x014e, 0x012e, 0x2000, 0x0005, 0x2091, 0x8000, 0x2091,
-	0x6000, 0x78ac, 0xa005, 0x1168, 0x7974, 0x70d0, 0xa106, 0x1148,
-	0x781c, 0xa005, 0x0130, 0x781f, 0x0000, 0x0e04, 0x4101, 0x2091,
-	0x4080, 0x7830, 0x8001, 0x7832, 0x1904, 0x416b, 0x7834, 0x7832,
-	0x2061, 0x68c0, 0x2069, 0x4380, 0xc7fd, 0x68d0, 0xa005, 0x0128,
-	0x8001, 0x68d2, 0x1110, 0x080c, 0x42c4, 0x6800, 0xa084, 0x000f,
-	0x0168, 0xa086, 0x0001, 0x0150, 0x6844, 0xa00d, 0x0138, 0x2104,
-	0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x425f, 0x6814, 0xa005,
-	0x01a8, 0x8001, 0x6816, 0x1190, 0x68a7, 0x0001, 0x00f6, 0xd7fc,
-	0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, 0x080c, 0x3aa0,
-	0x00fe, 0x6864, 0xa005, 0x0110, 0x080c, 0x2233, 0x6880, 0xa005,
-	0x0140, 0x8001, 0x6882, 0x1128, 0x6867, 0x0000, 0x68d4, 0xc0c5,
-	0x68d6, 0x68d4, 0xd0fc, 0x01b0, 0xc0fc, 0x68d6, 0x20a9, 0x0200,
-	0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d4, 0xc0fd, 0x68d6,
-	0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x2233, 0xace0, 0x0010,
-	0x1f04, 0x4150, 0xd7fc, 0x0138, 0x2061, 0x48c0, 0x2069, 0x4340,
-	0xc7fc, 0x0804, 0x410d, 0x0459, 0x7838, 0x8001, 0x783a, 0x11a0,
-	0x783c, 0x783a, 0x2061, 0x48c0, 0x2069, 0x4340, 0xc7fc, 0x680c,
-	0xa005, 0x0110, 0x080c, 0x41c9, 0xd7fc, 0x1130, 0x2061, 0x68c0,
-	0x2069, 0x4380, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, 0x0168, 0xd0ac,
+	0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0xa200, 0x3806,
+	0x8839, 0x20c4, 0x0864, 0xa850, 0x3008, 0x28c1, 0x9d18, 0xa201,
+	0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a,
+	0xa808, 0x28e2, 0x9cce, 0xa8f3, 0x0864, 0xa83e, 0x300c, 0xa801,
+	0x3008, 0x28e1, 0x9cce, 0x28a2, 0x7163, 0xa831, 0x2021, 0xa818,
+	0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x67a4, 0x6c80,
+	0x0212, 0xa205, 0x883d, 0x882b, 0x1814, 0x883b, 0x7027, 0x85f2,
+	0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa813, 0x883e, 0xa811,
+	0x2882, 0x7162, 0xa814, 0x280a, 0xa204, 0x64c0, 0x6de0, 0x67a0,
+	0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa802, 0x7861,
+	0x883e, 0x206a, 0x28c1, 0x9d18, 0x2042, 0x2101, 0xa8ca, 0x2902,
+	0xa20e, 0xa80b, 0xa207, 0x0014, 0xa203, 0x8000, 0x85a4, 0x1872,
+	0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x7121, 0x0014,
+	0x0704, 0x3008, 0x9cce, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009,
+	0x84a8, 0x19e2, 0xf844, 0x856e, 0x883f, 0x08e6, 0xa8f5, 0xf861,
+	0xa8eb, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532,
+	0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8,
+	0xd6e0, 0x1fe6, 0x0014, 0x3008, 0x8000, 0x2849, 0x1011, 0xa8fc,
+	0x3008, 0x8000, 0xa000, 0x2081, 0x2802, 0x1011, 0xa8fc, 0xa889,
+	0x3008, 0x20a1, 0x283c, 0x1011, 0xa8fc, 0xa209, 0x0017, 0x300c,
+	0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x0210, 0xa801, 0x0014,
+	0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0, 0x18f2, 0x0014, 0xa20b,
+	0x0014, 0xa20d, 0x3806, 0x0210, 0x9d22, 0x0704, 0xa206, 0x6865,
+	0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa,
+	0x8160, 0x842a, 0x8180, 0xf021, 0x3008, 0x84a8, 0x11d7, 0x7042,
+	0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x0000, 0x0126, 0x70d0,
+	0xa084, 0x4c00, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
+	0x11a0, 0x720c, 0x82ff, 0x0128, 0x8aff, 0x1178, 0x7200, 0xd284,
+	0x1160, 0x7804, 0xd0cc, 0x0110, 0x080c, 0x4328, 0x7007, 0x0008,
+	0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003,
+	0x7002, 0xc69c, 0xd084, 0x0588, 0x7108, 0xe000, 0x7008, 0xa106,
+	0x1dd8, 0xa184, 0x0003, 0x0904, 0x3fa2, 0xa184, 0x01e0, 0x1904,
+	0x3fa2, 0xd1f4, 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60,
+	0x2011, 0x0180, 0x710c, 0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20,
+	0x700c, 0xa106, 0x0dc0, 0x7007, 0x0012, 0x7108, 0xe000, 0x7008,
+	0xa106, 0x1dd8, 0xa184, 0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4,
+	0x0548, 0x7007, 0x0002, 0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130,
+	0x080c, 0x40ae, 0x8aff, 0x0904, 0x3f2c, 0x0cb8, 0x700c, 0xa08c,
+	0x07ff, 0x01e8, 0x7004, 0xd084, 0x0178, 0x7014, 0xa005, 0x1148,
+	0x7010, 0x7310, 0xa306, 0x1de0, 0x2300, 0xa005, 0x0128, 0xa102,
+	0x1e20, 0x7007, 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x426b,
+	0x1de8, 0x09d8, 0x080c, 0x4034, 0x012e, 0x2000, 0x0005, 0x7204,
+	0x7108, 0xc19c, 0x8103, 0x1218, 0x7007, 0x0002, 0x0cc0, 0xa205,
+	0x1d88, 0x7007, 0x0008, 0x7003, 0x0008, 0x0006, 0x2001, 0x4601,
+	0x2004, 0xd0cc, 0x0110, 0x080c, 0x4328, 0x000e, 0x012e, 0x2000,
+	0x0005, 0x6428, 0x84ff, 0x0508, 0x2c70, 0x7004, 0xa0bc, 0x000f,
+	0xa7b8, 0x3ff5, 0x273c, 0x87fb, 0x1148, 0x0210, 0x080c, 0x254c,
+	0x609c, 0xa075, 0x0190, 0x0c88, 0x2039, 0x3fea, 0x2704, 0xae68,
+	0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0138, 0x8738, 0x2704,
+	0xa005, 0x1da8, 0x709c, 0xa075, 0x1d00, 0x0005, 0x0000, 0x0005,
+	0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
+	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x3fea, 0x3fe7,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x3fea, 0x0000, 0x3ff2, 0x3fef,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x3ff2, 0x0000, 0x3fed, 0x3fed,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x3fed, 0x0000, 0x3ff3, 0x3ff3,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x3ff3, 0x2079, 0x4600, 0x2071,
+	0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x2009,
+	0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
+	0x0000, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1128, 0x8109, 0x0118,
+	0x2071, 0x0020, 0x0c80, 0x0005, 0x7004, 0x8004, 0x1a04, 0x408a,
+	0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c,
+	0x40e6, 0x0804, 0x40aa, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
+	0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x40e6,
+	0x0804, 0x40aa, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0190, 0xa386,
+	0x0008, 0x01c0, 0x7004, 0xd084, 0x1148, 0x7108, 0x7008, 0xa106,
+	0x1de0, 0xa184, 0x0003, 0x0110, 0x0804, 0x40e6, 0xa386, 0x200c,
+	0x19f0, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384, 0x07ff, 0x0110,
+	0x080c, 0x254c, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
+	0x0118, 0x080c, 0x40e6, 0x0470, 0x7007, 0x0012, 0x7000, 0xd084,
+	0x1148, 0x7310, 0x7014, 0xa305, 0x0128, 0x710c, 0xa184, 0x07ff,
+	0x1904, 0x4034, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
+	0x0118, 0x080c, 0x40e6, 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008,
+	0x7004, 0xd09c, 0x1de8, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184,
+	0x01e0, 0x0118, 0x080c, 0x40e6, 0x0028, 0x7007, 0x0012, 0x7108,
+	0x8103, 0x0e88, 0x7003, 0x0008, 0x0005, 0x7108, 0xa184, 0x01e0,
+	0x15a8, 0x7108, 0xa184, 0x01e0, 0x1588, 0xa184, 0x0007, 0x0002,
+	0x40c2, 0x40d0, 0x40c0, 0x40d0, 0x40c0, 0x4120, 0x40c0, 0x411e,
+	0x080c, 0x254c, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
+	0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x426b, 0x1de8, 0x0005,
+	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x1140,
+	0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x0003, 0x0108, 0x0030,
+	0x8aff, 0x0118, 0x080c, 0x426b, 0x1de8, 0x0005, 0x7007, 0x0012,
+	0x7108, 0x1d04, 0x40e9, 0x2091, 0x6000, 0x1d04, 0x40ed, 0x2091,
+	0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8,
+	0x7007, 0x0012, 0x7108, 0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000,
+	0xa005, 0x1130, 0x7004, 0xa005, 0x1118, 0x700c, 0xa005, 0x0108,
+	0x0c40, 0x2049, 0x0000, 0xb284, 0x0200, 0x0118, 0x2001, 0x0000,
+	0x0010, 0x2001, 0x0001, 0x080c, 0x3b81, 0x681b, 0x0002, 0x2051,
+	0x0000, 0x0005, 0x080c, 0x254c, 0x080c, 0x254c, 0x080c, 0x415f,
+	0x7210, 0x7114, 0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211,
+	0xa189, 0x0000, 0x04a1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200,
+	0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238,
+	0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60,
+	0x8a07, 0x0006, 0x6004, 0xd09c, 0x0118, 0xa7ba, 0x3fef, 0x0010,
+	0xa7ba, 0x3fe7, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
+	0x6b8e, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110,
+	0x080c, 0x40e6, 0x7007, 0x0012, 0x080c, 0x4034, 0x0005, 0x8a50,
+	0x8739, 0x2704, 0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60,
+	0x6004, 0xa084, 0x000f, 0xa080, 0x4005, 0x203c, 0x87fb, 0x090c,
+	0x254c, 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004,
+	0x2090, 0x00de, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057,
+	0xaad4, 0x00ff, 0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008,
+	0x000e, 0x0118, 0xa0b8, 0x3fef, 0x0010, 0xa0b8, 0x3fe7, 0xb284,
+	0x0200, 0x0110, 0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+	0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0518, 0x2c58, 0x2704,
+	0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e,
+	0xd19c, 0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081,
+	0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300,
+	0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x4292,
+	0x0010, 0x080c, 0x426b, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126,
+	0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007,
+	0x0004, 0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000,
+	0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090,
+	0x00de, 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c,
+	0x681c, 0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050,
+	0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3ff5, 0x273c, 0x87fb,
+	0x1138, 0x0210, 0x080c, 0x254c, 0x689c, 0xa065, 0x0120, 0x0c88,
+	0x080c, 0x426b, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006,
+	0x0016, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20,
+	0xb284, 0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5,
+	0x000c, 0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007,
+	0x0004, 0x2049, 0x4206, 0x6828, 0xa055, 0x00d6, 0x0904, 0x4267,
+	0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3ff5, 0x273c,
+	0x87fb, 0x1140, 0x0210, 0x080c, 0x254c, 0x709c, 0xa075, 0x2060,
+	0x0570, 0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b,
+	0x0268, 0x8a51, 0x1110, 0x080c, 0x254c, 0x8738, 0x2704, 0xa005,
+	0x1d90, 0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420,
+	0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
+	0xa11b, 0x1210, 0x080c, 0x254c, 0xb284, 0x0200, 0x0118, 0x2071,
+	0x0050, 0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x419b, 0x00de,
+	0x012e, 0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e,
+	0x0110, 0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108,
+	0x0005, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808,
+	0x7012, 0x780c, 0x7016, 0x6004, 0xd09c, 0x0120, 0x7810, 0x7022,
+	0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006,
+	0x2079, 0x4600, 0x8a51, 0x01e8, 0x8738, 0x2704, 0xa005, 0x1168,
+	0x609c, 0xa005, 0x01b8, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
+	0x3ff5, 0x203c, 0x87fb, 0x090c, 0x254c, 0x7008, 0x0006, 0xa084,
+	0x01e0, 0x000e, 0x0110, 0xa006, 0x0028, 0xa084, 0x0003, 0xa086,
+	0x0003, 0x0005, 0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6,
+	0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108,
+	0xa184, 0x0003, 0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3f45,
+	0x7108, 0xd1fc, 0x0118, 0x080c, 0x40ae, 0x0c88, 0x7007, 0x0010,
+	0x7108, 0xd1fc, 0x0de8, 0x080c, 0x40ae, 0x7008, 0xa086, 0x0008,
+	0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000,
+	0x0006, 0x2001, 0x4601, 0x2004, 0xd0cc, 0x0110, 0x080c, 0x4328,
+	0x000e, 0x012e, 0x2000, 0x0005, 0x0126, 0x0146, 0x0136, 0x0156,
+	0x00c6, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
+	0x2049, 0x42ec, 0xad80, 0x0011, 0x20a0, 0xb284, 0x0200, 0x0118,
+	0x2099, 0x0032, 0x0010, 0x2099, 0x0031, 0x700c, 0xa084, 0x07ff,
+	0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0118,
+	0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x07ff, 0x0130, 0x7007,
+	0x0004, 0x7004, 0xa084, 0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000,
+	0x7003, 0x0000, 0x015e, 0x013e, 0x014e, 0x012e, 0x2000, 0x0005,
+	0x6814, 0xd0fc, 0x0904, 0x436b, 0x7000, 0xd084, 0x05e0, 0x7e24,
+	0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0,
+	0x7118, 0x0016, 0x711c, 0x0016, 0x7120, 0x0016, 0x7124, 0x0016,
+	0x701b, 0x0000, 0x701f, 0x3fff, 0x7023, 0x0000, 0x7027, 0x0000,
+	0x7013, 0x0004, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x2001,
+	0xffff, 0x2009, 0x0031, 0x200a, 0x200a, 0x7108, 0x7008, 0xa106,
+	0x1de0, 0xd1fc, 0x0dd0, 0x002e, 0x7226, 0x002e, 0x7222, 0x002e,
+	0x721e, 0x002e, 0x721a, 0x7007, 0x0002, 0x7008, 0xa086, 0x0008,
+	0x0110, 0x0804, 0x40e6, 0x7007, 0x0004, 0x7003, 0x0000, 0x0005,
+	0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168, 0x7974,
+	0x70d0, 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f, 0x0000,
+	0x0e04, 0x4384, 0x2091, 0x4080, 0x2069, 0x4680, 0xd7fc, 0x1110,
+	0x2069, 0x4640, 0x6800, 0xa084, 0x000f, 0x1198, 0x68d0, 0xd0b4,
+	0x0180, 0xd0bc, 0x1170, 0x00f6, 0x2079, 0x0100, 0xd7fc, 0x1110,
+	0x2079, 0x0200, 0x7830, 0xa084, 0x00c0, 0x1110, 0x080c, 0x22ae,
+	0x00fe, 0x7830, 0x8001, 0x7832, 0x1904, 0x440b, 0x7834, 0x7832,
+	0x2061, 0x6bc0, 0x2069, 0x4680, 0xc7fd, 0x68cc, 0xa005, 0x0128,
+	0x8001, 0x68ce, 0x1110, 0x080c, 0x4577, 0x6800, 0xa084, 0x000f,
+	0x0168, 0xa086, 0x0001, 0x0150, 0x6840, 0xa00d, 0x0138, 0x2104,
+	0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x4514, 0x6814, 0xa005,
+	0x01a8, 0x8001, 0x6816, 0x1190, 0x68a3, 0x0001, 0x00f6, 0xd7fc,
+	0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, 0x080c, 0x3c46,
+	0x00fe, 0x6860, 0xa005, 0x0110, 0x080c, 0x22ae, 0x687c, 0xa005,
+	0x0140, 0x8001, 0x687e, 0x1128, 0x6863, 0x0000, 0x68d0, 0xc0c5,
+	0x68d2, 0x68d0, 0xd0fc, 0x01b0, 0xc0fc, 0x68d2, 0x20a9, 0x0200,
+	0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d0, 0xc0fd, 0x68d2,
+	0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x22ae, 0xace0, 0x0010,
+	0x1f04, 0x43f0, 0xd7fc, 0x0138, 0x2061, 0x4bc0, 0x2069, 0x4640,
+	0xc7fc, 0x0804, 0x43ad, 0x0459, 0x7838, 0x8001, 0x783a, 0x11a0,
+	0x783c, 0x783a, 0x2061, 0x4bc0, 0x2069, 0x4640, 0xc7fc, 0x680c,
+	0xa005, 0x0110, 0x080c, 0x4487, 0xd7fc, 0x1130, 0x2061, 0x6bc0,
+	0x2069, 0x4680, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, 0x0168, 0xd0ac,
 	0x1120, 0xd0a4, 0x0148, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0e04,
-	0x4193, 0x080c, 0x1ffe, 0x0005, 0x2091, 0x8001, 0x0005, 0x7840,
-	0x8001, 0x7842, 0x1568, 0x7844, 0x7842, 0x2091, 0x8000, 0x2061,
-	0x48c0, 0x2069, 0x4340, 0xc7fc, 0x6810, 0xa005, 0x1110, 0x2001,
-	0x0101, 0x8001, 0x6812, 0xd7fc, 0x0118, 0xa080, 0x89d0, 0x0010,
-	0xa080, 0x88c0, 0x2040, 0x2004, 0xa065, 0x0150, 0x6024, 0xa005,
-	0x0120, 0x8001, 0x6026, 0x0904, 0x4207, 0x6000, 0x2c40, 0x0ca0,
-	0xd7fc, 0x1130, 0x2061, 0x68c0, 0x2069, 0x4380, 0xc7fd, 0x08e0,
-	0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0540,
-	0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0400, 0x6008, 0xc09c,
-	0xd084, 0x1110, 0xd0ac, 0x01a8, 0x600a, 0x6004, 0xa06d, 0x01c0,
-	0x00c6, 0x0016, 0x6010, 0x8001, 0x6012, 0x080c, 0x35ab, 0x2d00,
-	0x2c68, 0x2060, 0x080c, 0x1b85, 0x080c, 0x1d30, 0x001e, 0x00ce,
-	0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0010, 0xa18d, 0x0100,
-	0xace0, 0x0010, 0x1f04, 0x41cd, 0xa184, 0x0001, 0x0130, 0xa18c,
-	0xfffe, 0x690e, 0x080c, 0x2233, 0x0008, 0x690e, 0x0005, 0x6800,
-	0xa005, 0x0120, 0x684c, 0xac06, 0x0904, 0x425f, 0x6864, 0xa005,
-	0x0120, 0x6027, 0x0001, 0x0804, 0x425c, 0x2c00, 0x687e, 0x6714,
-	0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4,
-	0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060,
-	0x6022, 0x6000, 0x2042, 0x080c, 0x1b1d, 0x6818, 0xa005, 0x0110,
+	0x4433, 0x080c, 0x207a, 0x0005, 0x2091, 0x8001, 0x0005, 0x7840,
+	0x8001, 0x7842, 0x1904, 0x4486, 0x7844, 0x7842, 0x2069, 0x4640,
+	0xc7fc, 0x2079, 0x0200, 0x68d4, 0xa005, 0x0138, 0x7de0, 0xa504,
+	0x1120, 0x68d6, 0x68d0, 0xc0bc, 0x68d2, 0x2079, 0x4600, 0x6810,
+	0xa005, 0x1110, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0118,
+	0xa080, 0x8cd0, 0x0010, 0xa080, 0x8bc0, 0x2040, 0x2004, 0xa065,
+	0x01e0, 0x6024, 0xa005, 0x01b0, 0x8001, 0x6026, 0x1198, 0x6800,
+	0xa005, 0x0130, 0x6848, 0xac06, 0x1118, 0x080c, 0x4514, 0x0068,
+	0x6860, 0xa005, 0x0118, 0x6027, 0x0001, 0x0020, 0x080c, 0x44c8,
+	0x2804, 0x0c28, 0x6000, 0x2c40, 0x0c10, 0xd7fc, 0x1138, 0x2069,
+	0x4680, 0xc7fd, 0x2079, 0x0100, 0x0804, 0x4443, 0x0005, 0x2009,
+	0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0558, 0x6024, 0xa005,
+	0x0118, 0x8001, 0x6026, 0x0418, 0x6008, 0xc09c, 0xd084, 0x1110,
+	0xd0ac, 0x01c0, 0x600a, 0x6004, 0xa005, 0x01d8, 0x00d6, 0x00c6,
+	0x0016, 0x2068, 0x6010, 0x8001, 0x6012, 0x080c, 0x37a4, 0x2d00,
+	0x2c68, 0x2060, 0x080c, 0x1be3, 0x080c, 0x1d95, 0x001e, 0x00ce,
+	0x00de, 0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0010, 0xa18d,
+	0x0100, 0xace0, 0x0010, 0x1f04, 0x448b, 0xa184, 0x0001, 0x0130,
+	0xa18c, 0xfffe, 0x690e, 0x080c, 0x22ae, 0x0008, 0x690e, 0x0005,
+	0x2c00, 0x687a, 0x6714, 0x6f72, 0x6017, 0x0000, 0x602b, 0x0000,
+	0x601b, 0x0006, 0x60b4, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084,
+	0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6858, 0xac06,
+	0x1110, 0x2800, 0x685a, 0x080c, 0x1b7b, 0x6818, 0xa005, 0x0110,
 	0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109,
-	0x790a, 0x8001, 0x1310, 0x080c, 0x243b, 0x6812, 0x1118, 0x7910,
+	0x790a, 0x8001, 0x1310, 0x080c, 0x254c, 0x6812, 0x1118, 0x7910,
 	0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x080c,
-	0x1d3d, 0xd7fc, 0x1118, 0x2069, 0x4340, 0x0010, 0x2069, 0x4380,
-	0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118, 0x697a, 0x2001,
-	0x0004, 0x2708, 0x080c, 0x2228, 0x2091, 0x8001, 0x0005, 0x00d6,
-	0x694c, 0x2160, 0xd7fc, 0x1118, 0x2069, 0x0200, 0x0010, 0x2069,
-	0x0100, 0x080c, 0x23e1, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00,
-	0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f,
-	0x0000, 0x6033, 0x0000, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004,
-	0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x4282, 0x684b,
-	0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x428b,
-	0x20a9, 0x00fa, 0x1f04, 0x4292, 0x6808, 0xa084, 0xfffd, 0x680a,
-	0x681b, 0x0054, 0x00de, 0x6867, 0x0007, 0x2091, 0x8001, 0x0005,
-	0x2079, 0x4300, 0x00e1, 0x0089, 0x00a9, 0x2009, 0x0002, 0x2069,
-	0x4380, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817, 0x0000, 0x8109,
-	0x0118, 0x2069, 0x4340, 0x0ca8, 0x0005, 0x2019, 0x00a3, 0x7b3a,
-	0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42, 0x7b46, 0x0005, 0x2019,
-	0x32dd, 0x7b32, 0x7b36, 0x0005, 0x6950, 0xa185, 0x0000, 0x0178,
-	0x00c6, 0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008,
-	0xc0b5, 0x600a, 0x8210, 0x8109, 0x1da8, 0x6952, 0x00ce, 0x0005,
-	0x70ec, 0xd0dc, 0x1118, 0xd0d4, 0x0180, 0x0088, 0xae8e, 0x0100,
-	0x0130, 0x7814, 0xc0f5, 0x7816, 0xd0d4, 0x1170, 0x0050, 0x7814,
-	0xc0fd, 0x7816, 0xd0d4, 0x1140, 0x0020, 0xd0e4, 0x0138, 0x70a0,
-	0x70a2, 0x7804, 0xd08c, 0x0110, 0x681f, 0x000c, 0x0005, 0xaf67
+	0x1da2, 0xd7fc, 0x1118, 0x2069, 0x4640, 0x0010, 0x2069, 0x4680,
+	0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118, 0x6976, 0x2001,
+	0x0004, 0x080c, 0x22a4, 0x0005, 0x00d6, 0x6948, 0x2160, 0xd7fc,
+	0x1118, 0x2069, 0x0200, 0x0010, 0x2069, 0x0100, 0x080c, 0x2467,
+	0x601b, 0x0006, 0x6858, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084,
+	0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000,
+	0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b,
+	0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x453b,
+	0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04,
+	0x4544, 0x20a9, 0x00fa, 0x1f04, 0x454b, 0x681b, 0x0054, 0x00de,
+	0x6863, 0x0007, 0x0005, 0x2079, 0x4600, 0x00e1, 0x0089, 0x00a9,
+	0x2009, 0x0002, 0x2069, 0x4680, 0x680f, 0x0000, 0x6813, 0x0000,
+	0x6817, 0x0000, 0x8109, 0x0118, 0x2069, 0x4640, 0x0ca8, 0x0005,
+	0x2019, 0x00a3, 0x7b3a, 0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42,
+	0x7b46, 0x0005, 0x2019, 0x32dd, 0x7b32, 0x7b36, 0x0005, 0x6a4c,
+	0xa285, 0x0000, 0x01f0, 0x6950, 0x6bbc, 0xa300, 0x00c6, 0x2164,
+	0x6304, 0x83ff, 0x1138, 0x8211, 0x0148, 0x8108, 0xa11a, 0x0eb8,
+	0x69bc, 0x0ca8, 0x68cf, 0x000a, 0x00ce, 0x0005, 0x694c, 0x6abc,
+	0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109, 0x1dc8, 0x694e,
+	0x00ce, 0x0005, 0x1d04, 0x459a, 0x2091, 0x6000, 0x1d04, 0x459e,
+	0x2091, 0x6000, 0x70ec, 0xd0dc, 0x1118, 0xd0d4, 0x0190, 0x0098,
+	0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5, 0xc0c5, 0x7816, 0xd0d4,
+	0x1578, 0x0458, 0x7814, 0xc0fd, 0xc0c5, 0x7816, 0xd0d4, 0x1540,
+	0x0420, 0xd0e4, 0x0538, 0x1d04, 0x45bb, 0x2091, 0x6000, 0x2009,
+	0x000c, 0x1d04, 0x45c1, 0x2091, 0x6000, 0x8109, 0x1dd0, 0x70e4,
+	0xa084, 0x01ff, 0xa086, 0x01ff, 0x1110, 0x70ec, 0x08c8, 0xae8e,
+	0x0100, 0x0128, 0x7814, 0xc0f4, 0xd0fc, 0x1130, 0x0020, 0x7814,
+	0xc0fc, 0xd0f4, 0x1108, 0xc0c4, 0x7816, 0x7804, 0xd08c, 0x0110,
+	0x681f, 0x000c, 0x70a0, 0x70a2, 0x0005, 0x7c12
 };
 #ifdef UNIQUE_FW_NAME
-unsigned short   fw12160i_length01 = 0x32f8;
+unsigned short   fw12160i_length01 = 0x35e6;
 #else
-unsigned short   risc_code_length01 = 0x32f8;
+unsigned short   risc_code_length01 = 0x35e6;
 #endif
-
diff -Nru a/drivers/scsi/ql1280_fw.h b/drivers/scsi/ql1280_fw.h
--- a/drivers/scsi/ql1280_fw.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/scsi/ql1280_fw.h	Sun Apr 14 12:16:59 2002
@@ -1,59 +1,74 @@
+/*****************************************************************************
+ *                  QLOGIC LINUX SOFTWARE
+ *
+ * QLogic ISP1280/ device driver for Linux 2.2.x and 2.4.x
+ * Copyright (C) 2001 Qlogic Corporation (www.qlogic.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ *****************************************************************************/
+
 /************************************************************************
- *									*
  * 	         --- ISP1240/1080/1280 Initiator Firmware ---           *
  *			      32 LUN Support				*
- *									*
- ************************************************************************
- * Copyright (C) 1999,2000 Qlogic, Corporation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted provided
- * that the following conditions are met:
- * 1. Redistribution of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *									*
- ************************************************************************
- */
+ ************************************************************************/
 
 
 /*
- *	Firmware Version 8.09.00 (18:29 Apr 16, 1999)
+ *	Firmware Version 8.15.00 (14:35 Aug 22, 2000)
  */
 
-unsigned short fw1280ei_version = 8*1024+9;
+#ifdef UNIQUE_FW_NAME
+unsigned short fw1280ei_version = 8*1024+15;
+#else
+unsigned short risc_code_version = 8*1024+15;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+unsigned char fw1280ei_version_str[] = {8,15,0};
+#else
+unsigned char firmware_version[] = {8,15,0};
+#endif
 
-unsigned char fw1280ei_version_str[] = {8,9,0};
+#ifdef UNIQUE_FW_NAME
+#define fw1280ei_VERSION_STRING "8.15.00"
+#else
+#define FW_VERSION_STRING "8.15.00"
+#endif
 
-unsigned short fw1280ei_addr01 = 0x1000 ;
+#ifdef UNIQUE_FW_NAME
+unsigned short fw1280ei_addr01 = 0x1000;
+#else
+unsigned short risc_code_addr01 = 0x1000;
+#endif
 
-unsigned short fw1280ei_code01[] = { 
-	0x0078, 0x1041, 0x0000, 0x39e3, 0x0000, 0x2043, 0x4f50, 0x5952,
+#ifdef UNIQUE_FW_NAME
+unsigned short fw1280ei_code01[] = {
+#else
+unsigned short risc_code01[] = {
+#endif
+	0x0078, 0x1041, 0x0000, 0x3d3b, 0x0000, 0x2043, 0x4f50, 0x5952,
 	0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
 	0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
 	0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
 	0x3132, 0x3430, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
-	0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3039, 0x2020, 0x2043,
+	0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3135, 0x2020, 0x2043,
 	0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
 	0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
-	0x2400, 0x20c9, 0x93ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
+	0x2400, 0x20c9, 0x97ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
 	0x00c0, 0x1054, 0x2071, 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010,
-	0x2089, 0x136a, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086,
+	0x2089, 0x1374, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086,
 	0x1280, 0x00c0, 0x1069, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2071,
-	0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, 0x2089, 0x13ea, 0x0078,
-	0x106d, 0x20c1, 0x0020, 0x2089, 0x1312, 0x2071, 0x0010, 0x70c3,
+	0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, 0x2089, 0x13f8, 0x0078,
+	0x106d, 0x20c1, 0x0020, 0x2089, 0x131c, 0x2071, 0x0010, 0x70c3,
 	0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
 	0x0008, 0x2001, 0x04fe, 0x70d6, 0x20c1, 0x0021, 0x2019, 0x0000,
 	0x2009, 0xfeff, 0x2100, 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64,
@@ -61,1838 +76,1948 @@
 	0xa286, 0xa5a5, 0x0040, 0x10a4, 0xa386, 0x000f, 0x0040, 0x10a0,
 	0x2c6a, 0x2a5a, 0x20c1, 0x0020, 0x2019, 0x000f, 0x0078, 0x1080,
 	0x2c6a, 0x2a5a, 0x0078, 0x10a2, 0x2c6a, 0x2a5a, 0x2130, 0x2128,
-	0xa1a2, 0x4a00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
-	0xa192, 0x9400, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x2078,
-	0x2218, 0x2079, 0x4a00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
-	0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2001, 0x04fc, 0x2004,
-	0xa086, 0x1080, 0x00c0, 0x10db, 0x2071, 0x0100, 0x0d7e, 0x2069,
-	0x4a40, 0x1078, 0x49ae, 0x0d7f, 0x7810, 0xc0ed, 0x7812, 0x781b,
-	0x0064, 0x0078, 0x1100, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1280,
-	0x00c0, 0x10fb, 0x7814, 0xc0ed, 0xc0d5, 0x7816, 0x781b, 0x0064,
-	0x2071, 0x0200, 0x0d7e, 0x2069, 0x4a40, 0x1078, 0x49ae, 0x2069,
-	0x4a80, 0x2071, 0x0100, 0x1078, 0x49ae, 0x7814, 0xc0d4, 0x7816,
-	0x0d7f, 0x0078, 0x1100, 0x7814, 0xc0e5, 0x7816, 0x781b, 0x003c,
-	0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
-	0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
-	0x2009, 0x0002, 0x2069, 0x4a40, 0x681b, 0x0003, 0x6823, 0x0007,
-	0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0000,
-	0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000, 0x8109, 0x0040,
-	0x1154, 0x68d3, 0x000a, 0x68c3, 0x4ac0, 0x2079, 0x4a00, 0x7814,
-	0xd0e4, 0x00c0, 0x113a, 0xd0ec, 0x00c0, 0x113e, 0x68d7, 0x7329,
-	0x0078, 0x1140, 0x68d7, 0x730d, 0x0078, 0x1140, 0x68d7, 0x7329,
-	0x68c7, 0x4fc0, 0x68cb, 0x4ec0, 0x68cf, 0x8fc0, 0x68ab, 0x9244,
-	0x68af, 0x9249, 0x68b3, 0x9244, 0x68b7, 0x9244, 0x68a7, 0x0001,
-	0x2069, 0x4a80, 0x0078, 0x1114, 0x68d3, 0x000a, 0x68c3, 0x4cc0,
-	0x7814, 0xd0e4, 0x00c0, 0x1160, 0x68d7, 0x7439, 0x0078, 0x1162,
-	0x68d7, 0x7419, 0x68c7, 0x6fc0, 0x68cb, 0x4f40, 0x68cf, 0x90d0,
-	0x68ab, 0x9249, 0x68af, 0x924e, 0x68b3, 0x9249, 0x68b7, 0x9249,
-	0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11b8, 0x7814, 0xd0e4,
-	0x00c0, 0x11aa, 0x0e7e, 0x2069, 0x4ec0, 0x2071, 0x0200, 0x70ec,
-	0xd0e4, 0x00c0, 0x118b, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
-	0x2007, 0x0078, 0x1191, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
-	0x2007, 0x2069, 0x4f40, 0x2071, 0x0100, 0x70ec, 0xd0e4, 0x00c0,
-	0x11a1, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, 0x2007, 0x0078,
-	0x11a7, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, 0x2007, 0x0e7f,
-	0x0078, 0x11d1, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x2069, 0x4ec0,
-	0x1078, 0x2007, 0x2069, 0x4f40, 0x1078, 0x2007, 0x0078, 0x11d1,
-	0x2069, 0x4ec0, 0x0e7e, 0x2071, 0x0100, 0x70ec, 0xd0e4, 0x00c0,
-	0x11ca, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078, 0x2007, 0x0e7f,
-	0x0078, 0x11d1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078, 0x2007,
-	0x0e7f, 0x2011, 0x0002, 0x2069, 0x4fc0, 0x2009, 0x0002, 0x20a9,
-	0x0100, 0x683f, 0x0000, 0x680b, 0x0040, 0x7bc8, 0xa386, 0xfeff,
-	0x00c0, 0x11e8, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x11ec,
-	0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x00f0, 0x11d9,
-	0x8109, 0x00c0, 0x11d7, 0x8211, 0x0040, 0x11fa, 0x2069, 0x6fc0,
-	0x0078, 0x11d5, 0x1078, 0x2611, 0x1078, 0x441d, 0x1078, 0x1df2,
-	0x1078, 0x4957, 0x2091, 0x2100, 0x2079, 0x4a00, 0x7810, 0xd0ec,
-	0x0040, 0x120e, 0x2071, 0x0020, 0x0078, 0x1210, 0x2071, 0x0050,
-	0x2091, 0x2200, 0x2079, 0x4a00, 0x2071, 0x0020, 0x2091, 0x2300,
-	0x2079, 0x4a00, 0x7810, 0xd0ec, 0x0040, 0x1222, 0x2079, 0x0100,
-	0x0078, 0x1224, 0x2079, 0x0200, 0x2071, 0x4a40, 0x2091, 0x2400,
-	0x2079, 0x0100, 0x2071, 0x4a80, 0x2091, 0x2000, 0x2079, 0x4a00,
-	0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090, 0x2071, 0x0010,
-	0x70c3, 0x0000, 0x0090, 0x1243, 0x70c0, 0xa086, 0x0002, 0x00c0,
-	0x1243, 0x1078, 0x159d, 0x2039, 0x0000, 0x7810, 0xd0ec, 0x00c0,
-	0x12c5, 0x1078, 0x1472, 0x78ac, 0xa005, 0x00c0, 0x1261, 0x0068,
-	0x1257, 0x786c, 0xa065, 0x0040, 0x1257, 0x1078, 0x2368, 0x1078,
-	0x209f, 0x0068, 0x126e, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078,
-	0x2368, 0x0068, 0x126e, 0x2009, 0x4a47, 0x2011, 0x4a87, 0x2104,
-	0x220c, 0xa105, 0x0040, 0x126e, 0x1078, 0x1f1e, 0x2071, 0x4a40,
-	0x70a4, 0xa005, 0x0040, 0x1293, 0x7450, 0xa485, 0x0000, 0x0040,
-	0x1293, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d,
-	0x2190, 0x1078, 0x2a9c, 0x2091, 0x8000, 0x2091, 0x303d, 0x0068,
-	0x1293, 0x2079, 0x4a00, 0x786c, 0xa065, 0x0040, 0x1293, 0x2071,
-	0x0010, 0x1078, 0x2368, 0x00e0, 0x129b, 0x2079, 0x4a00, 0x2071,
-	0x0010, 0x1078, 0x4765, 0x2071, 0x4a80, 0x70a4, 0xa005, 0x0040,
-	0x12b3, 0x7050, 0xa025, 0x0040, 0x12b3, 0x2079, 0x0100, 0x2091,
-	0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2a9c, 0x2091,
-	0x8000, 0x2091, 0x303d, 0x2079, 0x4a00, 0x2071, 0x0010, 0x0068,
-	0x12bf, 0x786c, 0xa065, 0x0040, 0x12bf, 0x1078, 0x2368, 0x00e0,
-	0x1249, 0x1078, 0x4765, 0x0078, 0x1249, 0x1078, 0x1472, 0x78ac,
-	0xa005, 0x00c0, 0x12dd, 0x0068, 0x12d3, 0x786c, 0xa065, 0x0040,
-	0x12d3, 0x1078, 0x2368, 0x1078, 0x209f, 0x0068, 0x12e7, 0x786c,
-	0xa065, 0x0040, 0x12dd, 0x1078, 0x2368, 0x0068, 0x12e7, 0x2009,
-	0x4a47, 0x2104, 0xa005, 0x0040, 0x12e7, 0x1078, 0x1f1e, 0x2071,
-	0x4a40, 0x70a4, 0xa005, 0x0040, 0x1302, 0x7450, 0xa485, 0x0000,
-	0x0040, 0x1302, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c,
-	0x303d, 0x2190, 0x1078, 0x2a9c, 0x2091, 0x8000, 0x2091, 0x303d,
-	0x2079, 0x4a00, 0x2071, 0x0010, 0x0068, 0x130c, 0x786c, 0xa065,
-	0x0040, 0x130c, 0x1078, 0x2368, 0x00e0, 0x12c5, 0x1078, 0x4765,
-	0x0078, 0x12c5, 0x1332, 0x1332, 0x1334, 0x1334, 0x1341, 0x1341,
-	0x1341, 0x1341, 0x134c, 0x134c, 0x1359, 0x1359, 0x1341, 0x1341,
-	0x1341, 0x1341, 0x1332, 0x1332, 0x1334, 0x1334, 0x1341, 0x1341,
-	0x1341, 0x1341, 0x134c, 0x134c, 0x1359, 0x1359, 0x1341, 0x1341,
-	0x1341, 0x1341, 0x0078, 0x1332, 0x007e, 0x107e, 0x127e, 0x2091,
-	0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
-	0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13ba, 0x127f, 0x107f,
-	0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091,
-	0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
-	0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x290b,
-	0x2091, 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091,
-	0x8001, 0x007c, 0x138a, 0x138a, 0x138c, 0x138c, 0x1399, 0x1399,
-	0x1399, 0x1399, 0x13a4, 0x13a4, 0x138c, 0x138c, 0x1399, 0x1399,
-	0x1399, 0x1399, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5,
-	0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5, 0x13a5,
-	0x13a5, 0x13a5, 0x0078, 0x138a, 0x007e, 0x107e, 0x127e, 0x2091,
-	0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
-	0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c7, 0x127f, 0x107f,
-	0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e, 0x127e, 0x0d7e,
-	0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069, 0x4a40, 0x2079,
-	0x4a00, 0x1078, 0x49ae, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
-	0x107f, 0x007c, 0x3c00, 0xa084, 0x0007, 0x0079, 0x13bf, 0x13d0,
-	0x13d0, 0x13d2, 0x13d2, 0x13d7, 0x13d7, 0x13dc, 0x13dc, 0x3c00,
-	0xa084, 0x0003, 0x0079, 0x13cc, 0x13d0, 0x13d0, 0x13e5, 0x13e5,
-	0x1078, 0x28ec, 0x2091, 0x2200, 0x1078, 0x44b7, 0x007c, 0x2091,
-	0x2100, 0x1078, 0x44b7, 0x007c, 0x2091, 0x2100, 0x1078, 0x44b7,
-	0x2091, 0x2200, 0x1078, 0x44b7, 0x007c, 0x2091, 0x2100, 0x1078,
-	0x44b7, 0x007c, 0x140a, 0x140a, 0x140c, 0x140c, 0x1419, 0x1419,
-	0x1419, 0x1419, 0x1424, 0x1424, 0x1431, 0x1431, 0x1419, 0x1419,
-	0x1419, 0x1419, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442,
-	0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442, 0x1442,
-	0x1442, 0x1442, 0x0078, 0x140a, 0x007e, 0x107e, 0x127e, 0x2091,
-	0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
-	0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13ba, 0x127f, 0x107f,
-	0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091,
-	0x2300, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001,
-	0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x290b,
-	0x2091, 0x2400, 0x1078, 0x290b, 0x127f, 0x107f, 0x007f, 0x2091,
-	0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e,
-	0x2079, 0x4a00, 0x2071, 0x0200, 0x2069, 0x4a40, 0x3d00, 0xd08c,
-	0x00c0, 0x1456, 0x2069, 0x4a80, 0x2071, 0x0100, 0x1078, 0x49ae,
-	0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007f, 0x007c, 0x7008,
-	0x800b, 0x00c8, 0x146d, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
-	0x146e, 0xd09c, 0x0040, 0x146d, 0x087a, 0x097a, 0x70c3, 0x4002,
-	0x0078, 0x15a0, 0x0068, 0x14f7, 0x2061, 0x0000, 0x6018, 0xd084,
-	0x00c0, 0x14f7, 0x7828, 0xa005, 0x00c0, 0x1482, 0x0010, 0x14f8,
-	0x0078, 0x14f7, 0x7910, 0xd1f4, 0x0040, 0x148a, 0x2001, 0x4007,
-	0x0078, 0x159f, 0x7914, 0xd1ec, 0x0040, 0x14a5, 0xd0fc, 0x0040,
-	0x149b, 0x007e, 0x1078, 0x1d82, 0x007f, 0x0040, 0x14a5, 0x2001,
-	0x4007, 0x0078, 0x159f, 0x007e, 0x1078, 0x1d72, 0x007f, 0x0040,
-	0x14a5, 0x2001, 0x4007, 0x0078, 0x159f, 0x7910, 0xd0fc, 0x00c0,
-	0x14af, 0x2061, 0x4a40, 0xc19c, 0xc7fc, 0x0078, 0x14b3, 0x2061,
-	0x4a80, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x00c0, 0x14f7, 0x7912,
-	0x6083, 0x0000, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x00c0, 0x14c4,
-	0x0c7e, 0x1078, 0x1b13, 0x0c7f, 0x782b, 0x0000, 0x607c, 0xa065,
-	0x0040, 0x14dd, 0x0c7e, 0x609c, 0x1078, 0x1e5d, 0x0c7f, 0x609f,
-	0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, 0x6087, 0x0103, 0x1078,
-	0x1d92, 0x00c0, 0x14f1, 0x1078, 0x1de4, 0x7810, 0xd09c, 0x00c0,
-	0x14e5, 0x2061, 0x4a40, 0x0078, 0x14e9, 0x2061, 0x4a80, 0xc09c,
-	0x7812, 0x607f, 0x0000, 0x60d4, 0xd0dc, 0x0040, 0x14f5, 0xc0dc,
-	0x60d6, 0x2001, 0x4005, 0x0078, 0x159f, 0x0078, 0x159d, 0x007c,
-	0x7810, 0xd0f4, 0x0040, 0x1500, 0x2001, 0x4007, 0x0078, 0x159f,
-	0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa08a,
-	0x0040, 0x00c8, 0x150d, 0x0079, 0x1514, 0x2100, 0xa08a, 0x0040,
-	0x00c8, 0x15ab, 0x0079, 0x1554, 0x159d, 0x15f3, 0x15bc, 0x162b,
-	0x1663, 0x1663, 0x15b3, 0x1c57, 0x166e, 0x15ab, 0x15c0, 0x15c2,
-	0x15c4, 0x15c6, 0x1c5c, 0x15ab, 0x167c, 0x16d4, 0x1b35, 0x1c51,
-	0x15c8, 0x19a7, 0x19e9, 0x1a1f, 0x1a6b, 0x1962, 0x196f, 0x1983,
-	0x1996, 0x17a4, 0x1cdc, 0x1706, 0x1713, 0x171f, 0x172b, 0x1741,
-	0x174d, 0x1750, 0x175c, 0x1768, 0x1770, 0x178c, 0x1798, 0x15ab,
-	0x15ab, 0x15ab, 0x15ab, 0x17b1, 0x17c3, 0x17df, 0x1815, 0x183d,
-	0x184d, 0x1850, 0x1881, 0x18b2, 0x18c4, 0x1931, 0x1941, 0x1d32,
-	0x15ab, 0x15ab, 0x15ab, 0x1951, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
-	0x15ab, 0x1c81, 0x1c87, 0x15ab, 0x15ab, 0x15ab, 0x1c8b, 0x1cd8,
-	0x15ab, 0x15ab, 0x1ce8, 0x1cf7, 0x15ed, 0x165d, 0x1676, 0x16ce,
-	0x1b2f, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x1d39, 0x1c73, 0x1c7d,
-	0x15ab, 0x15ab, 0x1d02, 0x1d1b, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
-	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
-	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
-	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x15ab,
-	0x15ab, 0x15ab, 0x15ab, 0x15ab, 0x72ca, 0x71c6, 0x2001, 0x4006,
-	0x0078, 0x159f, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2,
-	0x0068, 0x15a0, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000,
-	0x2091, 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x15a0, 0x70c3,
-	0x4006, 0x0078, 0x15a0, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9,
-	0x0005, 0x53a3, 0x0078, 0x159d, 0x70c4, 0x70c3, 0x0004, 0x007a,
-	0x0078, 0x159d, 0x0078, 0x159d, 0x0078, 0x159d, 0x0078, 0x159d,
-	0x2091, 0x8000, 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020,
-	0x70cf, 0x2020, 0x70d3, 0x0008, 0x2001, 0x0009, 0x70d6, 0x2079,
-	0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029,
-	0x041a, 0x2051, 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091,
-	0x5000, 0x2091, 0x4080, 0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da,
-	0x74de, 0x0078, 0x15f6, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8,
-	0x73cc, 0x70c4, 0x20a0, 0x2099, 0x0030, 0x7003, 0x0001, 0x7007,
-	0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff,
-	0x0040, 0x159d, 0xa182, 0x0040, 0x00c8, 0x1610, 0x2120, 0xa006,
-	0x2008, 0x8403, 0x7012, 0x7007, 0x0004, 0x7007, 0x0001, 0x7008,
-	0xd0fc, 0x0040, 0x1617, 0x7007, 0x0002, 0xa084, 0x01e0, 0x0040,
-	0x1625, 0x70c3, 0x4002, 0x0078, 0x15a0, 0x24a8, 0x53a5, 0x0078,
-	0x1607, 0x0078, 0x159d, 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8,
-	0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x7007,
-	0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040, 0x7007,
-	0x0006, 0x81ff, 0x0040, 0x159d, 0xa182, 0x0040, 0x00c8, 0x164a,
-	0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007,
-	0x0001, 0x7008, 0xd0fc, 0x0040, 0x1651, 0xa084, 0x01e0, 0x0040,
-	0x163f, 0x70c3, 0x4002, 0x0078, 0x15a0, 0x75d8, 0x74dc, 0x75da,
-	0x74de, 0x0078, 0x162e, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004,
-	0x00c0, 0x166b, 0x200a, 0x72ca, 0x0078, 0x159c, 0x70c7, 0x0008,
-	0x70cb, 0x0009, 0x70cf, 0x0000, 0x0078, 0x159d, 0x75d8, 0x76dc,
-	0x75da, 0x76de, 0x0078, 0x167f, 0x2029, 0x0000, 0x2530, 0x70c4,
-	0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005,
-	0x0040, 0x16c9, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0040, 0x1697,
-	0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, 0x159f, 0x7b7e,
-	0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0040, 0x16af,
-	0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118, 0xa291,
-	0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, 0x16b9, 0x8407,
-	0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581,
-	0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0040, 0x16c3,
-	0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae, 0x0078,
-	0x16cc, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x159d, 0x75d8, 0x76dc,
-	0x75da, 0x76de, 0x0078, 0x16d7, 0x2029, 0x0000, 0x2530, 0x70c4,
-	0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005,
-	0x0040, 0x1701, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x16ef,
-	0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x159f, 0x7a9a,
-	0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x16fa, 0x7a10,
-	0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078,
-	0x1704, 0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x159d, 0x2009, 0x0000,
-	0x786c, 0xa065, 0x0040, 0x1710, 0x8108, 0x6000, 0x0078, 0x1709,
-	0x7ac4, 0x0078, 0x159b, 0x2009, 0x4a48, 0x210c, 0x7810, 0xd0ec,
-	0x00c0, 0x159c, 0x2011, 0x4a88, 0x2214, 0x0078, 0x159b, 0x2009,
-	0x4a49, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2011, 0x4a89,
-	0x2214, 0x0078, 0x159b, 0x2061, 0x4a40, 0x6128, 0x622c, 0x8214,
-	0x8214, 0x8214, 0x7810, 0xd0ec, 0x00c0, 0x173f, 0x2061, 0x4a80,
-	0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078,
-	0x159b, 0x2009, 0x4a4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c,
-	0x2011, 0x4a8c, 0x2214, 0x0078, 0x159b, 0x7918, 0x0078, 0x159c,
-	0x2009, 0x4a4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2011,
-	0x4a8d, 0x2214, 0x0078, 0x159b, 0x2009, 0x4a4e, 0x210c, 0x7810,
-	0xd0ec, 0x00c0, 0x159c, 0x2011, 0x4a8e, 0x2214, 0x0078, 0x159b,
-	0x7920, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x7a24, 0x0078, 0x159b,
-	0x71c4, 0xd1fc, 0x00c0, 0x1778, 0x2011, 0x4ec0, 0x0078, 0x177a,
-	0x2011, 0x4f40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xa268, 0x6a00, 0x6804, 0xd09c, 0x0040, 0x1789, 0x6b08, 0x0078,
-	0x178a, 0x6b0c, 0x0078, 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091,
-	0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x159a,
-	0x2061, 0x4a40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2061,
-	0x4a80, 0x6218, 0x0078, 0x159b, 0x77c4, 0x1078, 0x1e02, 0x2091,
-	0x8000, 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078,
-	0x159a, 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8,
-	0x1595, 0x1078, 0x2729, 0xa384, 0x4000, 0x0040, 0x17c1, 0xa295,
-	0x0020, 0x0078, 0x159a, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010,
-	0x00c8, 0x1595, 0xd1bc, 0x00c0, 0x17d2, 0x2011, 0x4a48, 0x2204,
-	0x0078, 0x17d6, 0x2011, 0x4a88, 0x2204, 0xc0bd, 0x007e, 0x2100,
-	0xc0bc, 0x2012, 0x1078, 0x2686, 0x017f, 0x0078, 0x159c, 0x71c4,
-	0x2021, 0x4a49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x17ee,
-	0x71c8, 0x2021, 0x4a89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x180d,
-	0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x17fd, 0x8210, 0x00f0,
-	0x17f2, 0x71c4, 0x72c8, 0x0078, 0x1594, 0xa292, 0x180d, 0x027e,
-	0x2122, 0x017f, 0x1078, 0x26a7, 0x7810, 0xd0ec, 0x00c0, 0x180b,
-	0xd3fc, 0x0040, 0x17e8, 0x0078, 0x159d, 0x03e8, 0x00fa, 0x01f4,
-	0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x4a40, 0x6128,
-	0x622c, 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003,
-	0x8003, 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x183b, 0x027e,
-	0x017e, 0x2061, 0x4a80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
-	0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da,
-	0x72de, 0x017f, 0x027f, 0x0078, 0x159b, 0x2061, 0x4a40, 0x6130,
-	0x70c4, 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x159c, 0x2061, 0x4a80,
-	0x6230, 0x70c8, 0x6032, 0x0078, 0x159b, 0x7918, 0x0078, 0x159c,
-	0x71c4, 0xa184, 0xffcf, 0x0040, 0x185c, 0x7810, 0xd0ec, 0x00c0,
-	0x1595, 0x72c8, 0x0078, 0x1594, 0x2011, 0x4a4d, 0x2204, 0x2112,
-	0x007e, 0x2019, 0x0000, 0x1078, 0x270e, 0x7810, 0xd0ec, 0x0040,
-	0x186c, 0x017f, 0x0078, 0x159c, 0x71c8, 0xa184, 0xffcf, 0x0040,
-	0x1875, 0x2110, 0x71c4, 0x0078, 0x1594, 0x2011, 0x4a8d, 0x2204,
-	0x2112, 0x007e, 0xc3fd, 0x1078, 0x270e, 0x027f, 0x017f, 0x0078,
-	0x159b, 0x71c4, 0xa182, 0x0010, 0x0048, 0x188d, 0x7810, 0xd0ec,
-	0x00c0, 0x1595, 0x72c8, 0x0078, 0x1594, 0x2011, 0x4a4e, 0x2204,
-	0x007e, 0x2112, 0x2019, 0x0000, 0x1078, 0x26ec, 0x7810, 0xd0ec,
-	0x0040, 0x189d, 0x017f, 0x0078, 0x159c, 0x71c8, 0xa182, 0x0010,
-	0x0048, 0x18a6, 0x2110, 0x71c4, 0x0078, 0x1594, 0x2011, 0x4a8e,
-	0x2204, 0x007e, 0x2112, 0xc3fd, 0x1078, 0x26ec, 0x027f, 0x017f,
-	0x0078, 0x159b, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x1594,
-	0xa284, 0xfffd, 0x00c0, 0x1594, 0x2100, 0x7920, 0x7822, 0x2200,
-	0x7a24, 0x7826, 0x0078, 0x159b, 0x71c4, 0xd1fc, 0x00c0, 0x18cc,
-	0x2011, 0x4ec0, 0x0078, 0x18ce, 0x2011, 0x4f40, 0x8107, 0xa084,
-	0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8,
-	0xa284, 0x0080, 0x0040, 0x18e2, 0x6c14, 0x84ff, 0x00c0, 0x18e2,
-	0x6817, 0x0040, 0xa284, 0x0040, 0x0040, 0x18ec, 0x6c10, 0x84ff,
-	0x00c0, 0x18ec, 0x6813, 0x0001, 0x6800, 0x007e, 0xa226, 0x0040,
-	0x1909, 0x6a02, 0xd4ec, 0x0040, 0x18f6, 0xc3a5, 0xd4e4, 0x0040,
-	0x18fa, 0xc39d, 0xd4f4, 0x0040, 0x1909, 0x810f, 0xd2f4, 0x0040,
-	0x1905, 0x1078, 0x276b, 0x0078, 0x1909, 0x1078, 0x2749, 0x0078,
-	0x1909, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1929, 0xa2a4, 0x00ff,
-	0x7814, 0xd0e4, 0x00c0, 0x191c, 0xa482, 0x0028, 0x0048, 0x1926,
-	0x0040, 0x1926, 0x0078, 0x1920, 0xa482, 0x0043, 0x0048, 0x1926,
-	0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x1596, 0x6a0a, 0xa39d,
-	0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078,
-	0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a14, 0x6b1c,
-	0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078,
-	0x159a, 0x70c4, 0x2061, 0x4a40, 0x6118, 0x601a, 0x7810, 0xd0ec,
-	0x00c0, 0x159c, 0x70c8, 0x2061, 0x4a80, 0x6218, 0x601a, 0x0078,
-	0x159b, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x1595,
-	0x1078, 0x278d, 0xa384, 0x4000, 0x0040, 0x1960, 0xa295, 0x0020,
-	0x0078, 0x159a, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6a08,
-	0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4,
-	0x1078, 0x1e02, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a,
-	0x6804, 0xa005, 0x0040, 0x197e, 0x1078, 0x25de, 0x2091, 0x8001,
-	0x2708, 0x0078, 0x159b, 0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000,
-	0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1991, 0x1078,
-	0x25de, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4, 0x2041,
-	0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
-	0x1e1d, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x159b, 0x77c4,
-	0x7814, 0xd0e4, 0x00c0, 0x19bb, 0xd7fc, 0x0040, 0x19b5, 0x1078,
-	0x1d82, 0x0040, 0x19bb, 0x0078, 0x159f, 0x1078, 0x1d72, 0x0040,
-	0x19bb, 0x0078, 0x159f, 0x73c8, 0x72cc, 0x77c6, 0x73ca, 0x72ce,
-	0x1078, 0x1e9a, 0x00c0, 0x19e5, 0x6818, 0xa005, 0x0040, 0x19df,
-	0x2708, 0x077e, 0x1078, 0x27bd, 0x077f, 0x00c0, 0x19df, 0x2001,
-	0x0015, 0xd7fc, 0x00c0, 0x19d8, 0x2061, 0x4a40, 0x0078, 0x19db,
-	0xc0fd, 0x2061, 0x4a80, 0x782a, 0x2091, 0x8001, 0x007c, 0x2091,
-	0x8001, 0x2001, 0x4005, 0x0078, 0x159f, 0x2091, 0x8001, 0x0078,
-	0x159d, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19fd, 0xd7fc, 0x0040,
-	0x19f7, 0x1078, 0x1d82, 0x0040, 0x19fd, 0x0078, 0x159f, 0x1078,
-	0x1d72, 0x0040, 0x19fd, 0x0078, 0x159f, 0x77c6, 0x2041, 0x0021,
-	0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x1e1d,
-	0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a11, 0x2061, 0x4a40, 0x0078,
-	0x1a14, 0x2061, 0x4a80, 0xc1fd, 0x6067, 0x0003, 0x6776, 0x6083,
-	0x000f, 0x792a, 0x1078, 0x25de, 0x2091, 0x8001, 0x007c, 0x77c8,
-	0x77ca, 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a36, 0xd7fc,
-	0x0040, 0x1a30, 0x1078, 0x1d82, 0x0040, 0x1a36, 0x0078, 0x159f,
-	0x1078, 0x1d72, 0x0040, 0x1a36, 0x0078, 0x159f, 0xa7bc, 0xff00,
-	0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a43, 0x2061,
-	0x4a40, 0x0078, 0x1a46, 0x2061, 0x4a80, 0xc1fd, 0x6067, 0x0002,
-	0x6776, 0x6083, 0x000f, 0x792a, 0x1078, 0x25de, 0x2091, 0x8001,
-	0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0010, 0x2091, 0x8000,
-	0x70c8, 0xa005, 0x0040, 0x1a5f, 0x60d4, 0xc0fd, 0x60d6, 0x1078,
-	0x1e1d, 0x70c8, 0x683e, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1a5f,
-	0x2091, 0x8001, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x1a7f, 0x72c8,
-	0xd284, 0x0040, 0x1a79, 0x1078, 0x1d82, 0x0040, 0x1a7f, 0x0078,
-	0x159f, 0x1078, 0x1d72, 0x0040, 0x1a7f, 0x0078, 0x159f, 0x72c8,
-	0x72ca, 0x78ac, 0xa084, 0x0003, 0x00c0, 0x1aaa, 0x2039, 0x0000,
-	0xd284, 0x0040, 0x1a8c, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004,
-	0x2051, 0x0008, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6808, 0xc0d4,
-	0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0,
-	0x1a92, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
-	0x00c0, 0x1a92, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1abc,
-	0x7810, 0xd0ec, 0x0040, 0x1ab8, 0x2069, 0x0100, 0x0078, 0x1abe,
-	0x2069, 0x0200, 0x0078, 0x1abe, 0x2069, 0x0100, 0x6830, 0xd0b4,
-	0x0040, 0x1ada, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094,
-	0x0040, 0x1acc, 0x00f0, 0x1ac6, 0x684b, 0x0009, 0x20a9, 0x0014,
-	0x6848, 0xd084, 0x0040, 0x1ad6, 0x00f0, 0x1ad0, 0x20a9, 0x00fa,
-	0x00f0, 0x1ad8, 0x2079, 0x4a00, 0x2009, 0x0018, 0x72c8, 0xd284,
-	0x00c0, 0x1ae6, 0x2061, 0x4a40, 0x0078, 0x1ae9, 0x2061, 0x4a80,
-	0xc1fd, 0x792a, 0x6067, 0x0001, 0x6083, 0x000f, 0x60a7, 0x0000,
-	0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4, 0x0040, 0x1b03, 0xc0b4,
-	0x60d6, 0x0c7e, 0x60b8, 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018,
-	0x8001, 0x601a, 0x0c7f, 0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac,
-	0xc08d, 0x78ae, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0047,
-	0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b1a, 0x2069, 0x4a40,
-	0x0078, 0x1b1c, 0x2069, 0x4a80, 0x78ac, 0xc08c, 0x78ae, 0xd084,
-	0x00c0, 0x1b26, 0x0d7e, 0x1078, 0x1efa, 0x0d7f, 0x71c4, 0x71c6,
-	0x6916, 0x81ff, 0x00c0, 0x1b2e, 0x68a7, 0x0001, 0x007c, 0x75d8,
-	0x74dc, 0x75da, 0x74de, 0x0078, 0x1b38, 0x2029, 0x0000, 0x2520,
-	0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4a00,
-	0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1ddb, 0x0040, 0x1c3b,
-	0x20a9, 0x0005, 0x20a1, 0x4a14, 0x2091, 0x8000, 0x41a1, 0x2091,
-	0x8001, 0x2009, 0x0040, 0x1078, 0x1fcf, 0x0040, 0x1b5b, 0x1078,
-	0x1de4, 0x0078, 0x1c3b, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009,
-	0x00c0, 0x1b66, 0x007e, 0x1078, 0x234b, 0x007f, 0xa084, 0xff00,
-	0x8007, 0x8009, 0x0040, 0x1bda, 0x0c7e, 0x2c68, 0x1078, 0x1ddb,
-	0x0040, 0x1bac, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1b6d, 0x609f,
-	0x0000, 0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290,
-	0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde,
-	0x7cda, 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1bd9,
-	0x2009, 0x0040, 0x1078, 0x1fcf, 0x00c0, 0x1bc3, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0002, 0x00c0, 0x1bac, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x000a, 0x00c0, 0x1ba8, 0x017e, 0x1078, 0x2347, 0x017f,
-	0x2d00, 0x6002, 0x0078, 0x1b7b, 0x0c7f, 0x0c7e, 0x609c, 0x1078,
-	0x1e5d, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018,
-	0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086, 0x1078, 0x1d92, 0x1078,
-	0x1de4, 0x0078, 0x1c3b, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e5d,
-	0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c3f, 0x2009, 0x0018, 0x6087,
-	0x0103, 0x601b, 0x0003, 0x1078, 0x1d92, 0x1078, 0x1de4, 0x0078,
-	0x1c3b, 0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1bff, 0x6114, 0xd1fc,
-	0x0040, 0x1be8, 0x1078, 0x1d82, 0x0040, 0x1bff, 0x0078, 0x1bec,
-	0x1078, 0x1d72, 0x0040, 0x1bff, 0x2029, 0x0000, 0x2520, 0x2009,
-	0x0018, 0x73c8, 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078,
-	0x1d92, 0x1078, 0x1de4, 0x2001, 0x4007, 0x0078, 0x159f, 0x74c4,
-	0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012,
-	0xd0fc, 0x00c0, 0x1c0f, 0x2071, 0x4a40, 0x0078, 0x1c12, 0x2071,
-	0x4a80, 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xa18c, 0xf77f,
-	0x71d6, 0x736a, 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00,
-	0x707e, 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1c2a,
-	0x1078, 0x43c1, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af,
-	0x0000, 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000, 0x1078, 0x25de,
-	0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x15a0, 0x20a9,
-	0x0005, 0x2099, 0x4a14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001,
-	0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
-	0x007c, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0078, 0x159d, 0x71c4,
-	0x71c6, 0x2168, 0x0078, 0x1c5e, 0x2069, 0x1000, 0x690c, 0xa016,
-	0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1c60, 0xa285, 0x0000,
-	0x00c0, 0x1c6e, 0x70c3, 0x4000, 0x0078, 0x1c70, 0x70c3, 0x4003,
-	0x70ca, 0x0078, 0x15a0, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003,
-	0x00c8, 0x1595, 0x7966, 0x0078, 0x159d, 0x7964, 0x71c6, 0x0078,
-	0x159d, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x0078, 0x159d, 0x7900,
-	0x71c6, 0x0078, 0x159d, 0x70c4, 0xd08c, 0x0040, 0x1c94, 0x7a10,
-	0xd2ec, 0x00c0, 0x1c94, 0xc08c, 0x2011, 0x0000, 0xa08c, 0x000d,
-	0x0040, 0x1ca8, 0x810c, 0x0048, 0x1ca4, 0x8210, 0x810c, 0x810c,
-	0x0048, 0x1ca4, 0x8210, 0x810c, 0x81ff, 0x00c0, 0x1596, 0x8210,
-	0x7a0e, 0xd28c, 0x0040, 0x1cd4, 0x7910, 0xc1cd, 0x7912, 0x2009,
-	0x0021, 0x2019, 0x0003, 0xd284, 0x0040, 0x1cce, 0x8108, 0x2019,
-	0x0041, 0x2011, 0x924e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312,
-	0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312,
-	0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9253,
-	0x2112, 0x2011, 0x9273, 0x2312, 0x7904, 0x7806, 0x0078, 0x159c,
-	0x7804, 0x70c6, 0x0078, 0x159d, 0x2091, 0x8000, 0x2019, 0x0000,
-	0x2011, 0x0000, 0x2009, 0x0000, 0x2091, 0x8001, 0x0078, 0x159a,
-	0x77c4, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6830, 0xa084, 0xff00,
-	0x8007, 0x2010, 0x2091, 0x8001, 0x2708, 0x0078, 0x159b, 0x77c4,
-	0x1078, 0x1e02, 0x2091, 0x8000, 0x6a34, 0x2091, 0x8001, 0x2708,
-	0x0078, 0x159b, 0x77c4, 0x077e, 0xa7bc, 0xff00, 0x20a9, 0x0008,
-	0x72c8, 0x8217, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6c30, 0x6a32,
-	0x2091, 0x8001, 0x8738, 0x00f0, 0x1d0a, 0x077f, 0x2708, 0x8427,
-	0x2410, 0x0078, 0x159b, 0x77c4, 0x077e, 0xa7bc, 0xff00, 0x20a9,
-	0x0008, 0x72c8, 0x1078, 0x1e02, 0x2091, 0x8000, 0x6c34, 0x6a36,
-	0x2091, 0x8001, 0x8738, 0x00f0, 0x1d22, 0x077f, 0x2708, 0x2410,
-	0x0078, 0x159b, 0x2011, 0x4a3c, 0x220c, 0x70c4, 0x2012, 0x0078,
-	0x159c, 0x71c4, 0xd1fc, 0x00c0, 0x1d41, 0x2011, 0x4ec0, 0x0078,
-	0x1d43, 0x2011, 0x4f40, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d52, 0x2011, 0x0001,
-	0x0078, 0x1d54, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x159a, 0x017e,
-	0x7814, 0xd0f4, 0x0040, 0x1d64, 0x2001, 0x4007, 0x70db, 0x0000,
-	0xa18d, 0x0001, 0x0078, 0x1d70, 0xd0fc, 0x0040, 0x1d6f, 0x2001,
-	0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d70, 0xa006,
-	0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d7f, 0x2001,
-	0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d80, 0xa006,
-	0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040, 0x1d8f, 0x2001,
-	0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078, 0x1d90, 0xa006,
-	0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4, 0x0040,
-	0x1d9b, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c, 0x81a9,
-	0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2, 0x53a6,
-	0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1db8, 0x810f,
-	0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, 0x1dbb,
-	0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
-	0x7d10, 0xd5c4, 0x0040, 0x1dc8, 0x7b84, 0xa319, 0x7c80, 0xa421,
-	0x7008, 0xd0fc, 0x0040, 0x1dc8, 0x7003, 0x0001, 0x7007, 0x0006,
-	0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1dd8, 0x7322, 0x7426,
-	0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1de3, 0x2c04,
-	0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4a00, 0x7848,
-	0x2062, 0x2c00, 0xa005, 0x00c0, 0x1def, 0x1078, 0x28ec, 0x784a,
-	0x0f7f, 0x007c, 0x2011, 0x9400, 0x7a4a, 0x7bc4, 0x8319, 0x0040,
-	0x1dff, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1df6, 0x2013,
-	0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1e0b, 0x2011,
-	0x4fc0, 0x0078, 0x1e0d, 0x2011, 0x6fc0, 0xa784, 0x0f00, 0x800b,
-	0xa784, 0x001f, 0x0040, 0x1e18, 0x8003, 0x8003, 0x8003, 0x8003,
-	0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1e02, 0x2900,
-	0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a,
-	0xd7fc, 0x00c0, 0x1e2f, 0x2009, 0x4a53, 0x0078, 0x1e31, 0x2009,
-	0x4a93, 0x210c, 0x6804, 0xa005, 0x0040, 0x1e41, 0xa116, 0x00c0,
-	0x1e41, 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078,
-	0x1e44, 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e59,
-	0x6000, 0x6806, 0x1078, 0x1e6f, 0x1078, 0x201b, 0x6810, 0x7908,
-	0x8109, 0x790a, 0x8001, 0x6812, 0x00c0, 0x1e44, 0x7910, 0xc1a5,
-	0x7912, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x1e6e,
-	0x2008, 0x609c, 0xa005, 0x0040, 0x1e6b, 0x2062, 0x609f, 0x0000,
-	0xa065, 0x0078, 0x1e61, 0x7848, 0x794a, 0x2062, 0x007c, 0x6007,
-	0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005, 0x20a0,
-	0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022, 0x007c,
-	0x0e7e, 0xd7fc, 0x00c0, 0x1e8a, 0x2071, 0x4a40, 0x2031, 0x4ac0,
-	0x0078, 0x1e8e, 0x2071, 0x4a80, 0x2031, 0x4cc0, 0x7050, 0xa08c,
-	0x0200, 0x00c0, 0x1e98, 0xa608, 0x2d0a, 0x8000, 0x7052, 0xa006,
-	0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0, 0x1ea2, 0x2079, 0x4a40,
-	0x0078, 0x1ea4, 0x2079, 0x4a80, 0x1078, 0x1e02, 0x2091, 0x8000,
-	0x6804, 0x780a, 0xa065, 0x0040, 0x1ef8, 0x0078, 0x1eb6, 0x2c00,
-	0x780a, 0x2060, 0x6000, 0xa065, 0x0040, 0x1ef8, 0x6010, 0xa306,
-	0x00c0, 0x1eaf, 0x600c, 0xa206, 0x00c0, 0x1eaf, 0x2c28, 0x784c,
-	0xac06, 0x00c0, 0x1ec5, 0x0078, 0x1ef5, 0x6804, 0xac06, 0x00c0,
-	0x1ed3, 0x6000, 0x2060, 0x6806, 0xa005, 0x00c0, 0x1ed3, 0x6803,
-	0x0000, 0x0078, 0x1edd, 0x6400, 0x7808, 0x2060, 0x6402, 0xa486,
-	0x0000, 0x00c0, 0x1edd, 0x2c00, 0x6802, 0x2560, 0x0f7f, 0x1078,
-	0x1e6f, 0x0f7e, 0x601b, 0x0005, 0x6023, 0x0020, 0x0f7f, 0x1078,
-	0x201b, 0x0f7e, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001, 0x6812,
-	0x00c0, 0x1ef5, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005,
-	0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0040,
-	0x1f02, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
-	0x2091, 0x8000, 0x1078, 0x1e1d, 0x8738, 0xa784, 0x001f, 0x00c0,
-	0x1f0a, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
-	0x00c0, 0x1f0a, 0x2091, 0x8001, 0x077f, 0x007c, 0x2061, 0x0000,
-	0x6018, 0xd084, 0x00c0, 0x1f3e, 0x7810, 0xd08c, 0x0040, 0x1f2f,
-	0xc08c, 0x7812, 0xc7fc, 0x2069, 0x4a40, 0x0078, 0x1f34, 0xc08d,
-	0x7812, 0x2069, 0x4a80, 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f,
-	0x0000, 0x2091, 0x8001, 0xa005, 0x00c0, 0x1f3f, 0x007c, 0xa08c,
-	0xfff0, 0x0040, 0x1f45, 0x1078, 0x28ec, 0x0079, 0x1f47, 0x1f57,
-	0x1f5a, 0x1f60, 0x1f64, 0x1f58, 0x1f68, 0x1f58, 0x1f58, 0x1f58,
-	0x1f6e, 0x1f9f, 0x1fa3, 0x1fa9, 0x1f58, 0x1f58, 0x1f58, 0x007c,
-	0x1078, 0x28ec, 0x1078, 0x1efa, 0x2001, 0x8001, 0x0078, 0x1fbe,
-	0x2001, 0x8003, 0x0078, 0x1fbe, 0x2001, 0x8004, 0x0078, 0x1fbe,
-	0x1078, 0x1efa, 0x2001, 0x8006, 0x0078, 0x1fbe, 0x2091, 0x8000,
-	0x077e, 0xd7fc, 0x00c0, 0x1f7a, 0x2069, 0x4a40, 0x2039, 0x0009,
-	0x0078, 0x1f7e, 0x2069, 0x4a80, 0x2039, 0x0009, 0x6800, 0xa086,
-	0x0000, 0x0040, 0x1f88, 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c,
-	0x6874, 0x077f, 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004,
-	0x2051, 0x0010, 0x1078, 0x1e1d, 0x8738, 0xa784, 0x001f, 0x00c0,
-	0x1f92, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078, 0x1fbe, 0x2001,
-	0x800c, 0x0078, 0x1fbe, 0x1078, 0x1efa, 0x2001, 0x800d, 0x0078,
-	0x1fbe, 0x7814, 0xd0e4, 0x00c0, 0x1fbc, 0xd0ec, 0x0040, 0x1fb6,
-	0xd7fc, 0x0040, 0x1fb6, 0x78ec, 0x0078, 0x1fb7, 0x78e4, 0x70c6,
-	0x2001, 0x800e, 0x0078, 0x1fbe, 0x0078, 0x1f58, 0x70c2, 0xd7fc,
-	0x00c0, 0x1fc6, 0x70db, 0x0000, 0x0078, 0x1fc8, 0x70db, 0x0001,
-	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0xac80,
-	0x0001, 0x81ff, 0x0040, 0x1ffa, 0x2099, 0x0030, 0x20a0, 0x700c,
-	0xa084, 0x03ff, 0x0040, 0x1fdc, 0x7018, 0x007e, 0x701c, 0x007e,
-	0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a, 0x731e,
-	0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b,
-	0x00c8, 0x1fee, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x1ffa,
-	0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f, 0x7026,
-	0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c, 0x2011,
-	0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00, 0x6807,
-	0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109,
-	0x00c0, 0x200b, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000,
-	0x7868, 0xa005, 0x796a, 0x0040, 0x2028, 0x2c02, 0x0078, 0x2029,
-	0x796e, 0x007c, 0x0c7e, 0x2061, 0x4a00, 0x6887, 0x0103, 0x2d08,
-	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x203a, 0x2d02,
-	0x0078, 0x203b, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04,
-	0x786e, 0xa005, 0x00c0, 0x2045, 0x786a, 0x2091, 0x8001, 0x609c,
-	0xa005, 0x0040, 0x205e, 0x0c7e, 0x2060, 0x2008, 0x609c, 0xa005,
-	0x0040, 0x205a, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005,
-	0x00c0, 0x2052, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848, 0x2062,
-	0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x2068, 0x1078, 0x28ec,
-	0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
-	0x00c8, 0x2073, 0xa200, 0x00f0, 0x206e, 0x8086, 0x818e, 0x007c,
-	0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x2099, 0xa11a, 0x00c8,
-	0x2099, 0x8213, 0x818d, 0x0048, 0x208c, 0xa11a, 0x00c8, 0x208d,
-	0x00f0, 0x2081, 0x0078, 0x2091, 0xa11a, 0x2308, 0x8210, 0x00f0,
-	0x2081, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
-	0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x2095, 0x7d74,
-	0x70d0, 0xa506, 0x0040, 0x2185, 0x7810, 0x2050, 0x7800, 0xd08c,
-	0x0040, 0x20c1, 0xdaec, 0x0040, 0x20c1, 0x0e7e, 0x2091, 0x8000,
-	0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20be, 0x7008, 0x0e7f,
-	0xa086, 0x0008, 0x0040, 0x20c1, 0x0078, 0x2185, 0x0e7f, 0x0078,
-	0x2185, 0x1078, 0x1ddb, 0x0040, 0x2185, 0xa046, 0x7970, 0x2500,
-	0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20d0, 0x0078, 0x20d7,
-	0x72d0, 0xa206, 0x0040, 0x20d7, 0x8840, 0x2009, 0x0080, 0x0c7e,
-	0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020, 0xac80,
-	0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x20e9, 0x1078,
-	0x1ddb, 0x7008, 0xd0fc, 0x0040, 0x20e9, 0x7007, 0x0002, 0x2091,
-	0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2120, 0x53a5, 0x8cff, 0x00c0,
-	0x20fe, 0x88ff, 0x0040, 0x216f, 0x0078, 0x2108, 0x2c00, 0x788e,
-	0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078, 0x216f,
-	0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2110, 0x7420, 0x7524,
-	0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000,
-	0x721a, 0x731e, 0xdac4, 0x0040, 0x2120, 0x7422, 0x7526, 0xa006,
-	0x7007, 0x0004, 0x0040, 0x216f, 0x8cff, 0x0040, 0x2129, 0x1078,
-	0x1de4, 0x0c7f, 0x1078, 0x1de4, 0xa046, 0x7888, 0x8000, 0x788a,
-	0xa086, 0x0002, 0x0040, 0x214f, 0x7a7c, 0x7b78, 0xdac4, 0x0040,
-	0x213b, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210,
-	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e,
-	0xdac4, 0x0040, 0x2185, 0x7422, 0x7526, 0x0078, 0x2185, 0x6014,
-	0xd0fc, 0x00c0, 0x2157, 0x2069, 0x4a40, 0x0078, 0x2159, 0x2069,
-	0x4a80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040, 0x2165,
-	0xa046, 0x788c, 0x2060, 0x0078, 0x214f, 0x788b, 0x0000, 0x78ac,
-	0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x2185, 0x0c7f,
-	0x788b, 0x0000, 0x1078, 0x2319, 0x6004, 0xa084, 0x000f, 0x1078,
-	0x2186, 0x88ff, 0x0040, 0x2183, 0x788c, 0x2060, 0x6004, 0xa084,
-	0x000f, 0x1078, 0x2186, 0x0078, 0x209f, 0x007c, 0x0079, 0x2188,
-	0x2198, 0x21b6, 0x21d4, 0x2198, 0x21e5, 0x21a9, 0x2198, 0x2198,
-	0x2198, 0x21b4, 0x21d2, 0x2198, 0x2198, 0x2198, 0x2198, 0x2198,
-	0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a,
-	0x1078, 0x2228, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, 0x2303,
-	0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21af, 0x0078, 0x2198, 0x601c,
-	0xc0bd, 0x601e, 0x0078, 0x21bc, 0x1078, 0x234b, 0x78bc, 0xd0c4,
-	0x0040, 0x21bc, 0x0078, 0x2198, 0x78bf, 0x0000, 0x6004, 0x8007,
-	0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21cf, 0x1078, 0x2228,
-	0x0040, 0x21cf, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x21d1, 0x0078,
-	0x2247, 0x007c, 0x1078, 0x2347, 0x78bc, 0xa08c, 0x0e00, 0x00c0,
-	0x21dc, 0xd0c4, 0x00c0, 0x21de, 0x0078, 0x2198, 0x1078, 0x2228,
-	0x00c0, 0x21e4, 0x0078, 0x2247, 0x007c, 0x78bc, 0xd0c4, 0x0040,
-	0x21eb, 0x0078, 0x2198, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001,
-	0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x220b, 0xa7bc,
-	0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x220b, 0xa7bc,
-	0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040,
-	0x220b, 0x0078, 0x2225, 0x1078, 0x1e02, 0x2d00, 0x2091, 0x8000,
-	0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a,
-	0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x220e, 0x8211, 0x0040,
-	0x2225, 0x20a9, 0x0100, 0x0078, 0x220e, 0x1078, 0x1de4, 0x007c,
-	0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0, 0x2233,
-	0x78ba, 0x0078, 0x223b, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06,
-	0x00c0, 0x223b, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0, 0x2246,
-	0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c, 0x0e7e,
-	0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2,
-	0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040, 0x225a,
-	0x1078, 0x43c1, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071,
-	0x4a80, 0xd7fc, 0x00c0, 0x2266, 0x2071, 0x4a40, 0xa784, 0x0f00,
-	0x800b, 0xa784, 0x001f, 0x0040, 0x2271, 0x8003, 0x8003, 0x8003,
-	0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091, 0x8000,
-	0x7810, 0xd0f4, 0x00c0, 0x228b, 0x6e08, 0xd684, 0x0040, 0x22a1,
-	0xd9fc, 0x00c0, 0x22a1, 0x2091, 0x8001, 0x1078, 0x1e6f, 0x2091,
-	0x8000, 0x1078, 0x201b, 0x2091, 0x8001, 0x7814, 0xd0e4, 0x00c0,
-	0x2301, 0x7810, 0xd0f4, 0x0040, 0x2301, 0x601b, 0x0021, 0x0078,
-	0x2301, 0x6024, 0xa096, 0x0001, 0x00c0, 0x22a8, 0x8000, 0x6026,
-	0x6a10, 0x6814, 0xa202, 0x0048, 0x22bb, 0x0040, 0x22bb, 0x2091,
+	0xa1a2, 0x4e00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+	0xa192, 0x9800, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x207a,
+	0x2218, 0x2079, 0x4e00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+	0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2009, 0xff00, 0x3400,
+	0xa102, 0x0048, 0x10cf, 0x0040, 0x10cf, 0x20a8, 0x42a4, 0x2001,
+	0x04fc, 0x2004, 0xa086, 0x1080, 0x00c0, 0x10e5, 0x2071, 0x0100,
+	0x0d7e, 0x2069, 0x4e40, 0x1078, 0x4cdd, 0x0d7f, 0x7810, 0xc0ed,
+	0x7812, 0x781b, 0x0064, 0x0078, 0x110a, 0x2001, 0x04fc, 0x2004,
+	0xa086, 0x1280, 0x00c0, 0x1105, 0x7814, 0xc0ed, 0xc0d5, 0x7816,
+	0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4e40, 0x1078,
+	0x4cdd, 0x2069, 0x4e80, 0x2071, 0x0100, 0x1078, 0x4cdd, 0x7814,
+	0xc0d4, 0x7816, 0x0d7f, 0x0078, 0x110a, 0x7814, 0xc0e5, 0x7816,
+	0x781b, 0x003c, 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800,
+	0xc08d, 0x7802, 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002,
+	0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4e40, 0x681b, 0x0003,
+	0x6823, 0x0007, 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028,
+	0x6837, 0x0000, 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000,
+	0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4ec0, 0x2079,
+	0x4e00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148,
+	0x68d7, 0x7329, 0x0078, 0x114a, 0x68d7, 0x730d, 0x0078, 0x114a,
+	0x68d7, 0x732d, 0x68c7, 0x53c0, 0x68cb, 0x52c0, 0x68cf, 0x93c0,
+	0x68ab, 0x9644, 0x68af, 0x9649, 0x68b3, 0x9644, 0x68b7, 0x9644,
+	0x68a7, 0x0001, 0x2069, 0x4e80, 0x0078, 0x111e, 0x68d3, 0x000a,
+	0x68c3, 0x50c0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439,
+	0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x73c0, 0x68cb, 0x5340,
+	0x68cf, 0x94d0, 0x68ab, 0x9649, 0x68af, 0x964e, 0x68b3, 0x9649,
+	0x68b7, 0x9649, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2,
+	0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x52c0, 0x2071,
+	0x0200, 0x70ec, 0xd0e4, 0x00c0, 0x1195, 0x2019, 0x0c0c, 0x2021,
+	0x000c, 0x1078, 0x2009, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021,
+	0x000a, 0x1078, 0x2009, 0x2069, 0x5340, 0x2071, 0x0100, 0x70ec,
+	0xd0e4, 0x00c0, 0x11ab, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
+	0x2009, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
+	0x2009, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c,
+	0x2069, 0x52c0, 0x1078, 0x2009, 0x2069, 0x5340, 0x1078, 0x2009,
+	0x0078, 0x11db, 0x2069, 0x52c0, 0x0e7e, 0x2071, 0x0100, 0x70ec,
+	0xd0e4, 0x00c0, 0x11d4, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
+	0x2009, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a,
+	0x1078, 0x2009, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x53c0, 0x2009,
+	0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bc8,
+	0xa386, 0xfeff, 0x00c0, 0x11f2, 0x6817, 0x0100, 0x681f, 0x0064,
+	0x0078, 0x11f6, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
+	0x00f0, 0x11e3, 0x8109, 0x00c0, 0x11e1, 0x8211, 0x0040, 0x1204,
+	0x2069, 0x73c0, 0x0078, 0x11df, 0x1078, 0x265b, 0x1078, 0x468e,
+	0x1078, 0x1dd4, 0x1078, 0x4c6f, 0x2091, 0x2100, 0x2079, 0x4e00,
+	0x7810, 0xd0ec, 0x0040, 0x1218, 0x2071, 0x0020, 0x0078, 0x121a,
+	0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4e00, 0x2071, 0x0020,
+	0x2091, 0x2300, 0x2079, 0x4e00, 0x7810, 0xd0ec, 0x0040, 0x122c,
+	0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4e40,
+	0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4e80, 0x2091, 0x2000,
+	0x2079, 0x4e00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
+	0x2071, 0x0010, 0x70c3, 0x0000, 0x0090, 0x124d, 0x70c0, 0xa086,
+	0x0002, 0x00c0, 0x124d, 0x1078, 0x15ba, 0x2039, 0x0000, 0x7810,
+	0xd0ec, 0x00c0, 0x12cf, 0x1078, 0x148e, 0x78ac, 0xa005, 0x00c0,
+	0x126b, 0x0068, 0x1261, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078,
+	0x2395, 0x1078, 0x20a1, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040,
+	0x126b, 0x1078, 0x2395, 0x0068, 0x1278, 0x2009, 0x4e47, 0x2011,
+	0x4e87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1f0a,
+	0x2071, 0x4e40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485,
+	0x0000, 0x0040, 0x129d, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4,
+	0xa28c, 0x303d, 0x2190, 0x1078, 0x2b6a, 0x2091, 0x8000, 0x2091,
+	0x303d, 0x0068, 0x129d, 0x2079, 0x4e00, 0x786c, 0xa065, 0x0040,
+	0x129d, 0x2071, 0x0010, 0x1078, 0x2395, 0x00e0, 0x12a5, 0x2079,
+	0x4e00, 0x2071, 0x0010, 0x1078, 0x4a43, 0x2071, 0x4e80, 0x70a4,
+	0xa005, 0x0040, 0x12bd, 0x7050, 0xa025, 0x0040, 0x12bd, 0x2079,
+	0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078,
+	0x2b6a, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4e00, 0x2071,
+	0x0010, 0x0068, 0x12c9, 0x786c, 0xa065, 0x0040, 0x12c9, 0x1078,
+	0x2395, 0x00e0, 0x1253, 0x1078, 0x4a43, 0x0078, 0x1253, 0x1078,
+	0x148e, 0x78ac, 0xa005, 0x00c0, 0x12e7, 0x0068, 0x12dd, 0x786c,
+	0xa065, 0x0040, 0x12dd, 0x1078, 0x2395, 0x1078, 0x20a1, 0x0068,
+	0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x2395, 0x0068,
+	0x12f1, 0x2009, 0x4e47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078,
+	0x1f0a, 0x2071, 0x4e40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450,
+	0xa485, 0x0000, 0x0040, 0x130c, 0x2079, 0x0100, 0x2091, 0x8000,
+	0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2b6a, 0x2091, 0x8000,
+	0x2091, 0x303d, 0x2079, 0x4e00, 0x2071, 0x0010, 0x0068, 0x1316,
+	0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x2395, 0x00e0, 0x12cf,
+	0x1078, 0x4a43, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e,
+	0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
+	0x134b, 0x134b, 0x134b, 0x134b, 0x133c, 0x133c, 0x133e, 0x133e,
+	0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
+	0x134b, 0x134b, 0x134b, 0x134b, 0x0078, 0x133c, 0x007e, 0x107e,
+	0x127e, 0x2091, 0x2400, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+	0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c8,
+	0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e,
+	0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+	0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300,
+	0x1078, 0x298a, 0x2091, 0x2400, 0x1078, 0x298a, 0x127f, 0x107f,
+	0x007f, 0x2091, 0x8001, 0x007c, 0x1394, 0x1394, 0x1396, 0x1396,
+	0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13ae, 0x13ae, 0x1396, 0x1396,
+	0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13af, 0x13af, 0x13af, 0x13af,
+	0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af,
+	0x13af, 0x13af, 0x13af, 0x13af, 0x0078, 0x1394, 0x007e, 0x107e,
+	0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+	0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13d5,
+	0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e,
+	0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069,
+	0x4e40, 0x2079, 0x4e00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078,
+	0x4cdd, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c,
+	0x3c00, 0xa084, 0x0007, 0x0079, 0x13cd, 0x13de, 0x13de, 0x13e0,
+	0x13e0, 0x13e5, 0x13e5, 0x13ea, 0x13ea, 0x3c00, 0xa084, 0x0003,
+	0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x296b,
+	0x2091, 0x2200, 0x1078, 0x4768, 0x007c, 0x2091, 0x2100, 0x1078,
+	0x4768, 0x007c, 0x2091, 0x2100, 0x1078, 0x4768, 0x2091, 0x2200,
+	0x1078, 0x4768, 0x007c, 0x2091, 0x2100, 0x1078, 0x4768, 0x007c,
+	0x1418, 0x1418, 0x141a, 0x141a, 0x1427, 0x1427, 0x1427, 0x1427,
+	0x1432, 0x1432, 0x143f, 0x143f, 0x1427, 0x1427, 0x1427, 0x1427,
+	0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
+	0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
+	0x0078, 0x1418, 0x007e, 0x107e, 0x127e, 0x2091, 0x2400, 0x1078,
+	0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
+	0x107e, 0x127e, 0x1078, 0x13c8, 0x127f, 0x107f, 0x007f, 0x2091,
+	0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078,
+	0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
+	0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x2091, 0x2400,
+	0x1078, 0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c,
+	0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4e00,
+	0x2071, 0x0200, 0x2069, 0x4e40, 0x3d00, 0xd08c, 0x0040, 0x1466,
+	0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4cdd, 0x3d00, 0xd084,
+	0x0040, 0x1474, 0x2069, 0x4e80, 0x2071, 0x0100, 0x70ec, 0xa084,
+	0x1c00, 0x78e6, 0x1078, 0x4cdd, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
+	0x107f, 0x007f, 0x007c, 0x7008, 0x800b, 0x00c8, 0x1489, 0x7007,
+	0x0002, 0xa08c, 0x01e0, 0x00c0, 0x148a, 0xd09c, 0x0040, 0x1489,
+	0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15bd, 0x0068, 0x1513,
+	0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x1513, 0x7828, 0xa005,
+	0x00c0, 0x149e, 0x0010, 0x1514, 0x0078, 0x1513, 0x7910, 0xd1f4,
+	0x0040, 0x14a6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x7914, 0xd1ec,
+	0x0040, 0x14c1, 0xd0fc, 0x0040, 0x14b7, 0x007e, 0x1078, 0x1d64,
+	0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078, 0x15bc, 0x007e,
+	0x1078, 0x1d54, 0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078,
+	0x15bc, 0x7910, 0xd0fc, 0x00c0, 0x14cb, 0x2061, 0x4e40, 0xc19c,
+	0xc7fc, 0x0078, 0x14cf, 0x2061, 0x4e80, 0xc19d, 0xc7fd, 0x6064,
+	0xa005, 0x00c0, 0x1513, 0x7912, 0x6083, 0x0000, 0x7828, 0xc0fc,
+	0xa086, 0x0018, 0x00c0, 0x14e0, 0x0c7e, 0x1078, 0x1b5b, 0x0c7f,
+	0x782b, 0x0000, 0x607c, 0xa065, 0x0040, 0x14f9, 0x0c7e, 0x609c,
+	0x1078, 0x1e49, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c84, 0x2009,
+	0x0018, 0x6087, 0x0103, 0x1078, 0x1d74, 0x00c0, 0x150d, 0x1078,
+	0x1dc6, 0x7810, 0xd09c, 0x00c0, 0x1501, 0x2061, 0x4e40, 0x0078,
+	0x1505, 0x2061, 0x4e80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4,
+	0xd0dc, 0x0040, 0x1511, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078,
+	0x15bc, 0x0078, 0x15ba, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x151c,
+	0x2001, 0x4007, 0x0078, 0x15bc, 0xa006, 0x70c2, 0x70c6, 0x70ca,
+	0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x152a,
+	0x0079, 0x1531, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15c8, 0x0079,
+	0x1571, 0x15ba, 0x1610, 0x15d9, 0x1648, 0x1680, 0x1680, 0x15d0,
+	0x1c9c, 0x168b, 0x15c8, 0x15dd, 0x15df, 0x15e1, 0x15e3, 0x1ca1,
+	0x15c8, 0x1699, 0x16f6, 0x1b7b, 0x1c96, 0x15e5, 0x19c0, 0x1a02,
+	0x1a3d, 0x1a8e, 0x197b, 0x1988, 0x199c, 0x19af, 0x17cb, 0x15c8,
+	0x172d, 0x173a, 0x1746, 0x1752, 0x1768, 0x1774, 0x1777, 0x1783,
+	0x178f, 0x1797, 0x17b3, 0x17bf, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
+	0x17d8, 0x17ea, 0x1806, 0x183c, 0x1864, 0x1874, 0x1877, 0x18a8,
+	0x18d9, 0x18eb, 0x194a, 0x195a, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
+	0x196a, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x1cc6, 0x1ccc,
+	0x15c8, 0x15c8, 0x15c8, 0x1cd0, 0x1d15, 0x15c8, 0x15c8, 0x15c8,
+	0x15c8, 0x160a, 0x167a, 0x1693, 0x16f0, 0x1b75, 0x15c8, 0x15c8,
+	0x1b3e, 0x15c8, 0x1d19, 0x1cb8, 0x1cc2, 0x15c8, 0x15c8, 0x15c8,
+	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
+	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
+	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
+	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
+	0x15c8, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15bc, 0x73ce,
+	0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15bd, 0x2061,
+	0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c,
+	0x70c3, 0x4001, 0x0078, 0x15bd, 0x70c3, 0x4006, 0x0078, 0x15bd,
+	0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078,
+	0x15ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15ba, 0x0078,
+	0x15ba, 0x0078, 0x15ba, 0x0078, 0x15ba, 0x2091, 0x8000, 0x70c3,
+	0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
+	0x0008, 0x2001, 0x000f, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001,
+	0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445,
+	0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080,
+	0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1613,
+	0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0,
+	0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e,
+	0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15ba, 0xa182,
+	0x0040, 0x00c8, 0x162d, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012,
+	0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x1634,
+	0x7007, 0x0002, 0xa084, 0x01e0, 0x0040, 0x1642, 0x70c3, 0x4002,
+	0x0078, 0x15bd, 0x24a8, 0x53a5, 0x0078, 0x1624, 0x0078, 0x15ba,
+	0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098,
+	0x20a1, 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e,
+	0x7422, 0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040,
+	0x15ba, 0xa182, 0x0040, 0x00c8, 0x1667, 0x2120, 0xa006, 0x2008,
+	0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc,
+	0x0040, 0x166e, 0xa084, 0x01e0, 0x0040, 0x165c, 0x70c3, 0x4002,
+	0x0078, 0x15bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x164b,
+	0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x1688, 0x200a,
+	0x72ca, 0x0078, 0x15b9, 0x70c7, 0x0008, 0x70cb, 0x000f, 0x70cf,
+	0x0000, 0x0078, 0x15ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
+	0x169c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
+	0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16eb, 0xa40a,
+	0x0040, 0x16ac, 0x00c8, 0x16b5, 0x8001, 0x7872, 0xa084, 0xfc00,
+	0x0040, 0x16b9, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078,
+	0x15bc, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00,
+	0x0040, 0x16d1, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f,
+	0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078,
+	0x16db, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1,
+	0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605,
+	0x0040, 0x16e5, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc,
+	0x78ae, 0x0078, 0x16ee, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15ba,
+	0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16f9, 0x2029, 0x0000,
+	0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce,
+	0x74d6, 0xa005, 0x0040, 0x1728, 0xa40a, 0x0040, 0x1709, 0x00c8,
+	0x15bc, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x1716, 0x78ac,
+	0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15bc, 0x7a9a, 0x7b9e,
+	0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x1721, 0x7a10, 0xc2c5,
+	0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x172b,
+	0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x15ba, 0x2009, 0x0000, 0x786c,
+	0xa065, 0x0040, 0x1737, 0x8108, 0x6000, 0x0078, 0x1730, 0x7ac4,
+	0x0078, 0x15b8, 0x2009, 0x4e48, 0x210c, 0x7810, 0xd0ec, 0x00c0,
+	0x15b9, 0x2011, 0x4e88, 0x2214, 0x0078, 0x15b8, 0x2009, 0x4e49,
+	0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4e89, 0x2214,
+	0x0078, 0x15b8, 0x2061, 0x4e40, 0x6128, 0x622c, 0x8214, 0x8214,
+	0x8214, 0x7810, 0xd0ec, 0x00c0, 0x1766, 0x2061, 0x4e80, 0x6328,
+	0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15b8,
+	0x2009, 0x4e4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011,
+	0x4e8c, 0x2214, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x2009,
+	0x4e4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4e8d,
+	0x2214, 0x0078, 0x15b8, 0x2009, 0x4e4e, 0x210c, 0x7810, 0xd0ec,
+	0x00c0, 0x15b9, 0x2011, 0x4e8e, 0x2214, 0x0078, 0x15b8, 0x7920,
+	0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x7a24, 0x0078, 0x15b8, 0x71c4,
+	0xd1fc, 0x00c0, 0x179f, 0x2011, 0x52c0, 0x0078, 0x17a1, 0x2011,
+	0x5340, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268,
+	0x6a00, 0x6804, 0xd09c, 0x0040, 0x17b0, 0x6b08, 0x0078, 0x17b1,
+	0x6b0c, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
+	0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b7, 0x2061,
+	0x4e40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4e80,
+	0x6218, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
+	0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15b7,
+	0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b2,
+	0x1078, 0x277f, 0xa384, 0x4000, 0x0040, 0x17e8, 0xa295, 0x0020,
+	0x0078, 0x15b7, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8,
+	0x15b2, 0xd1bc, 0x00c0, 0x17f9, 0x2011, 0x4e48, 0x2204, 0x0078,
+	0x17fd, 0x2011, 0x4e88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc,
+	0x2012, 0x1078, 0x26dc, 0x017f, 0x0078, 0x15b9, 0x71c4, 0x2021,
+	0x4e49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1815, 0x71c8,
+	0x2021, 0x4e89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1834, 0x20a9,
+	0x0008, 0x2204, 0xa106, 0x0040, 0x1824, 0x8210, 0x00f0, 0x1819,
+	0x71c4, 0x72c8, 0x0078, 0x15b1, 0xa292, 0x1834, 0x027e, 0x2122,
+	0x017f, 0x1078, 0x26fd, 0x7810, 0xd0ec, 0x00c0, 0x1832, 0xd3fc,
+	0x0040, 0x180f, 0x0078, 0x15ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
+	0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4e40, 0x6128, 0x622c,
+	0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
+	0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1862, 0x027e, 0x017e,
+	0x2061, 0x4e80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
+	0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
+	0x017f, 0x027f, 0x0078, 0x15b8, 0x2061, 0x4e40, 0x6130, 0x70c4,
+	0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4e80, 0x6230,
+	0x70c8, 0x6032, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x71c4,
+	0xa184, 0xffcf, 0x0040, 0x1883, 0x7810, 0xd0ec, 0x00c0, 0x15b2,
+	0x72c8, 0x0078, 0x15b1, 0x2011, 0x4e4d, 0x2204, 0x2112, 0x007e,
+	0x2019, 0x0000, 0x1078, 0x2764, 0x7810, 0xd0ec, 0x0040, 0x1893,
+	0x017f, 0x0078, 0x15b9, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x189c,
+	0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4e8d, 0x2204, 0x2112,
+	0x007e, 0xc3fd, 0x1078, 0x2764, 0x027f, 0x017f, 0x0078, 0x15b8,
+	0x71c4, 0xa182, 0x0010, 0x0048, 0x18b4, 0x7810, 0xd0ec, 0x00c0,
+	0x15b2, 0x72c8, 0x0078, 0x15b1, 0x2011, 0x4e4e, 0x2204, 0x007e,
+	0x2112, 0x2019, 0x0000, 0x1078, 0x2742, 0x7810, 0xd0ec, 0x0040,
+	0x18c4, 0x017f, 0x0078, 0x15b9, 0x71c8, 0xa182, 0x0010, 0x0048,
+	0x18cd, 0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4e8e, 0x2204,
+	0x007e, 0x2112, 0xc3fd, 0x1078, 0x2742, 0x027f, 0x017f, 0x0078,
+	0x15b8, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b1, 0xa284,
+	0xfffd, 0x00c0, 0x15b1, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24,
+	0x7826, 0x0078, 0x15b8, 0x71c4, 0xd1fc, 0x00c0, 0x18f3, 0x2011,
+	0x52c0, 0x0078, 0x18f5, 0x2011, 0x5340, 0x8107, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0x2091,
+	0x8000, 0x6800, 0x007e, 0xa226, 0x0040, 0x191e, 0x6a02, 0xd4ec,
+	0x0040, 0x190b, 0xc3a5, 0xd4e4, 0x0040, 0x190f, 0xc39d, 0xd4f4,
+	0x0040, 0x191e, 0x810f, 0xd2f4, 0x0040, 0x191a, 0x1078, 0x27c1,
+	0x0078, 0x191e, 0x1078, 0x279f, 0x0078, 0x191e, 0x72cc, 0x6808,
+	0xa206, 0x0040, 0x1940, 0xa2a4, 0x00ff, 0x7814, 0xd0e4, 0x00c0,
+	0x1931, 0xa482, 0x0028, 0x0048, 0x193d, 0x0040, 0x193d, 0x0078,
+	0x1935, 0xa482, 0x0043, 0x0048, 0x193d, 0x71c4, 0x71c6, 0x027f,
+	0x72ca, 0x2091, 0x8001, 0x0078, 0x15b3, 0x6a0a, 0xa39d, 0x000a,
+	0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x2091, 0x8001,
+	0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000, 0x6a14,
+	0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708,
+	0x0078, 0x15b7, 0x70c4, 0x2061, 0x4e40, 0x6118, 0x601a, 0x7810,
+	0xd0ec, 0x00c0, 0x15b9, 0x70c8, 0x2061, 0x4e80, 0x6218, 0x601a,
+	0x0078, 0x15b8, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8,
+	0x15b2, 0x1078, 0x27e3, 0xa384, 0x4000, 0x0040, 0x1979, 0xa295,
+	0x0020, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
+	0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8,
+	0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9,
+	0x6a0a, 0x6804, 0xa005, 0x0040, 0x1997, 0x1078, 0x2628, 0x2091,
+	0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1de4, 0x2091,
+	0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x19aa,
+	0x1078, 0x2628, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4,
+	0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
+	0x1078, 0x1dff, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x15b8,
+	0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19d4, 0xd7fc, 0x0040, 0x19ce,
+	0x1078, 0x1d64, 0x0040, 0x19d4, 0x0078, 0x15bc, 0x1078, 0x1d54,
+	0x0040, 0x19d4, 0x0078, 0x15bc, 0x73c8, 0x72cc, 0x77c6, 0x73ca,
+	0x72ce, 0x1078, 0x1e86, 0x00c0, 0x19fe, 0x6818, 0xa005, 0x0040,
+	0x19f8, 0x2708, 0x077e, 0x1078, 0x2813, 0x077f, 0x00c0, 0x19f8,
+	0x2001, 0x0015, 0xd7fc, 0x00c0, 0x19f1, 0x2061, 0x4e40, 0x0078,
+	0x19f4, 0xc0fd, 0x2061, 0x4e80, 0x782a, 0x2091, 0x8001, 0x007c,
+	0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x15bc, 0x2091, 0x8001,
+	0x0078, 0x15ba, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x1a16, 0xd7fc,
+	0x0040, 0x1a10, 0x1078, 0x1d64, 0x0040, 0x1a16, 0x0078, 0x15bc,
+	0x1078, 0x1d54, 0x0040, 0x1a16, 0x0078, 0x15bc, 0x77c6, 0x2041,
+	0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
+	0x1dff, 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a2a, 0x2061, 0x4e40,
+	0x0078, 0x1a2d, 0x2061, 0x4e80, 0xc1fd, 0x6067, 0x0003, 0x607f,
+	0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc, 0x61d6,
+	0x1078, 0x2628, 0x2091, 0x8001, 0x007c, 0x77c8, 0x77ca, 0x77c4,
+	0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a54, 0xd7fc, 0x0040, 0x1a4e,
+	0x1078, 0x1d64, 0x0040, 0x1a54, 0x0078, 0x15bc, 0x1078, 0x1d54,
+	0x0040, 0x1a54, 0x0078, 0x15bc, 0xa7bc, 0xff00, 0x2091, 0x8000,
+	0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a61, 0x2061, 0x4e40, 0x0078,
+	0x1a64, 0x2061, 0x4e80, 0xc1fd, 0x607f, 0x0000, 0x6067, 0x0002,
+	0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc, 0x61d6, 0x1078,
+	0x2628, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051,
+	0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0040, 0x1a82, 0x60d4,
+	0xc0fd, 0x60d6, 0x1078, 0x1dff, 0x70c8, 0x6836, 0x8738, 0xa784,
+	0x001f, 0x00c0, 0x1a82, 0x2091, 0x8001, 0x007c, 0x2019, 0x0000,
+	0x7814, 0xd0e4, 0x00c0, 0x1aa4, 0x72c8, 0xd284, 0x0040, 0x1a9e,
+	0x1078, 0x1d64, 0x0040, 0x1aa4, 0x0078, 0x15bc, 0x1078, 0x1d54,
+	0x0040, 0x1aa4, 0x0078, 0x15bc, 0x72c8, 0x72ca, 0x78ac, 0xa084,
+	0x0003, 0x00c0, 0x1acf, 0x2039, 0x0000, 0xd284, 0x0040, 0x1ab1,
+	0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
+	0x1de4, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x2091,
+	0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ab7, 0xa7bc, 0xff00,
+	0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1ab7, 0x2091,
+	0x8000, 0x72c8, 0xd284, 0x00c0, 0x1ae1, 0x7810, 0xd0ec, 0x0040,
+	0x1add, 0x2069, 0x0100, 0x0078, 0x1ae3, 0x2069, 0x0200, 0x0078,
+	0x1ae3, 0x2069, 0x0100, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830,
+	0xd0b4, 0x0040, 0x1b03, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
+	0xd094, 0x0040, 0x1af5, 0x00f0, 0x1aef, 0x684b, 0x0009, 0x20a9,
+	0x0014, 0x6848, 0xd084, 0x0040, 0x1aff, 0x00f0, 0x1af9, 0x20a9,
+	0x00fa, 0x00f0, 0x1b01, 0x2079, 0x4e00, 0x2009, 0x0018, 0x72c8,
+	0xd284, 0x00c0, 0x1b0f, 0x2061, 0x4e40, 0x0078, 0x1b12, 0x2061,
+	0x4e80, 0xc1fd, 0x607f, 0x0000, 0x792a, 0x6067, 0x0001, 0x6083,
+	0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4,
+	0x0040, 0x1b2e, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8, 0xa065, 0x6008,
+	0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x60d4, 0xa084,
+	0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0040, 0x1b39,
+	0x007c, 0x681b, 0x0047, 0x2091, 0x8001, 0x007c, 0x73cc, 0x1078,
+	0x1a90, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a, 0xa185, 0x0040,
+	0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff, 0x00f0, 0x1b4e,
+	0x8421, 0x00c0, 0x1b4c, 0x8319, 0x00c0, 0x1b4a, 0x69ee, 0x6a4a,
+	0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b62, 0x2069, 0x4e40,
+	0x0078, 0x1b64, 0x2069, 0x4e80, 0x71c4, 0x71c6, 0x6916, 0x81ff,
+	0x00c0, 0x1b6c, 0x68a7, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
+	0x00c0, 0x1b74, 0x1078, 0x1ee6, 0x007c, 0x75d8, 0x74dc, 0x75da,
+	0x74de, 0x0078, 0x1b7e, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8,
+	0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4e00, 0x7dde, 0x7cda,
+	0x7bd6, 0x7ad2, 0x1078, 0x1dbd, 0x0040, 0x1c80, 0x20a9, 0x0005,
+	0x20a1, 0x4e14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009,
+	0x0040, 0x1078, 0x1fd1, 0x0040, 0x1ba1, 0x1078, 0x1dc6, 0x0078,
+	0x1c80, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0, 0x1bac,
+	0x007e, 0x1078, 0x2378, 0x007f, 0xa084, 0xff00, 0x8007, 0x8009,
+	0x0040, 0x1c20, 0x0c7e, 0x2c68, 0x1078, 0x1dbd, 0x0040, 0x1bf2,
+	0x2c00, 0x689e, 0x8109, 0x00c0, 0x1bb3, 0x609f, 0x0000, 0x0c7f,
+	0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6,
+	0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c1f, 0x2009, 0x0040,
+	0x1078, 0x1fd1, 0x00c0, 0x1c09, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x0002, 0x00c0, 0x1bf2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a,
+	0x00c0, 0x1bee, 0x017e, 0x1078, 0x2374, 0x017f, 0x2d00, 0x6002,
+	0x0078, 0x1bc1, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e49, 0x0c7f,
+	0x609f, 0x0000, 0x1078, 0x1c84, 0x2009, 0x0018, 0x6008, 0xc0cd,
+	0x600a, 0x6004, 0x6086, 0x1078, 0x1d74, 0x1078, 0x1dc6, 0x0078,
+	0x1c80, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e49, 0x0c7f, 0x609f,
+	0x0000, 0x1078, 0x1c84, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b,
+	0x0003, 0x1078, 0x1d74, 0x1078, 0x1dc6, 0x0078, 0x1c80, 0x0c7f,
+	0x7814, 0xd0e4, 0x00c0, 0x1c45, 0x6114, 0xd1fc, 0x0040, 0x1c2e,
+	0x1078, 0x1d64, 0x0040, 0x1c45, 0x0078, 0x1c32, 0x1078, 0x1d54,
+	0x0040, 0x1c45, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018, 0x73c8,
+	0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078, 0x1d74, 0x1078,
+	0x1dc6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x74c4, 0x73c8, 0x72cc,
+	0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012, 0xd0fc, 0x00c0,
+	0x1c55, 0x2071, 0x4e40, 0x0078, 0x1c58, 0x2071, 0x4e80, 0xc1fd,
+	0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6, 0x736a, 0x726e,
+	0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, 0x2530,
+	0x611c, 0xa184, 0x0060, 0x0040, 0x1c6f, 0x1078, 0x4632, 0x0e7f,
+	0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000,
+	0x6714, 0x6023, 0x0000, 0x1078, 0x2628, 0x2091, 0x8001, 0x007c,
+	0x70c3, 0x4005, 0x0078, 0x15bd, 0x20a9, 0x0005, 0x2099, 0x4e14,
+	0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4, 0x70c7,
+	0x0000, 0x791e, 0x0078, 0x15ba, 0x71c4, 0x71c6, 0x2168, 0x0078,
+	0x1ca3, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68,
+	0x8109, 0x00c0, 0x1ca5, 0xa285, 0x0000, 0x00c0, 0x1cb3, 0x70c3,
+	0x4000, 0x0078, 0x1cb5, 0x70c3, 0x4003, 0x70ca, 0x0078, 0x15bd,
+	0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b2, 0x7966,
+	0x0078, 0x15ba, 0x7964, 0x71c6, 0x0078, 0x15ba, 0x7900, 0x71c6,
+	0x71c4, 0x7902, 0x0078, 0x15ba, 0x7900, 0x71c6, 0x0078, 0x15ba,
+	0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1ce5, 0x810c,
+	0x0048, 0x1ce1, 0x8210, 0x810c, 0x810c, 0x0048, 0x1ce1, 0x8210,
+	0x810c, 0x81ff, 0x00c0, 0x15b3, 0x8210, 0x7a0e, 0xd28c, 0x0040,
+	0x1d11, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, 0x0003,
+	0xd284, 0x0040, 0x1d0b, 0x8108, 0x2019, 0x0041, 0x2011, 0x964e,
+	0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043, 0x8210,
+	0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047, 0x8210,
+	0x2312, 0x2019, 0x0006, 0x2011, 0x9653, 0x2112, 0x2011, 0x9673,
+	0x2312, 0x7904, 0x7806, 0x0078, 0x15b9, 0x7804, 0x70c6, 0x0078,
+	0x15ba, 0x71c4, 0xd1fc, 0x00c0, 0x1d21, 0x2011, 0x52c0, 0x0078,
+	0x1d23, 0x2011, 0x5340, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d32, 0x2011, 0x0001,
+	0x0078, 0x1d34, 0x2011, 0x0000, 0x6b0c, 0x6800, 0x70da, 0x0078,
+	0x15b7, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d46, 0x2001, 0x4007,
+	0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d52, 0xd0fc, 0x0040,
+	0x1d51, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078,
+	0x1d52, 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040,
+	0x1d61, 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078,
+	0x1d62, 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040,
+	0x1d71, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078,
+	0x1d72, 0xa006, 0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810,
+	0xd0c4, 0x0040, 0x1d7d, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108,
+	0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084,
+	0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040,
+	0x1d9a, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+	0x0078, 0x1d9d, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
+	0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1daa, 0x7b84, 0xa319,
+	0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x1daa, 0x7003, 0x0001,
+	0x7007, 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1dba,
+	0x7322, 0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040,
+	0x1dc5, 0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079,
+	0x4e00, 0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1dd1, 0x1078,
+	0x296b, 0x784a, 0x0f7f, 0x007c, 0x2011, 0x9800, 0x7a4a, 0x7bc4,
+	0x8319, 0x0040, 0x1de1, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078,
+	0x1dd8, 0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0,
+	0x1ded, 0x2011, 0x53c0, 0x0078, 0x1def, 0x2011, 0x73c0, 0xa784,
+	0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x1dfa, 0x8003, 0x8003,
+	0x8003, 0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078,
+	0x1de4, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef,
+	0xa80d, 0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1e14, 0x2009, 0x4e53,
+	0x2071, 0x4e40, 0x0078, 0x1e18, 0x2009, 0x4e93, 0x2071, 0x4e80,
+	0x210c, 0x6804, 0xa005, 0x0040, 0x1e28, 0xa116, 0x00c0, 0x1e28,
+	0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e2b,
+	0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e40, 0x6000,
+	0x6806, 0x1078, 0x1e5b, 0x1078, 0x201d, 0x6810, 0x7908, 0x8109,
+	0x790a, 0x8001, 0x6812, 0x00c0, 0x1e2b, 0x7910, 0xc1a5, 0x7912,
+	0x017f, 0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2acc, 0x0e7f,
+	0x007c, 0xa065, 0x0040, 0x1e5a, 0x2008, 0x609c, 0xa005, 0x0040,
+	0x1e57, 0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e4d, 0x7848,
+	0x794a, 0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
+	0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
+	0x601a, 0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1e76,
+	0x2071, 0x4e40, 0x2031, 0x4ec0, 0x0078, 0x1e7a, 0x2071, 0x4e80,
+	0x2031, 0x50c0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1e84, 0xa608,
+	0x2d0a, 0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc,
+	0x00c0, 0x1e8e, 0x2079, 0x4e40, 0x0078, 0x1e90, 0x2079, 0x4e80,
+	0x1078, 0x1de4, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040,
+	0x1ee4, 0x0078, 0x1ea2, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065,
+	0x0040, 0x1ee4, 0x6010, 0xa306, 0x00c0, 0x1e9b, 0x600c, 0xa206,
+	0x00c0, 0x1e9b, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1eb1, 0x0078,
+	0x1ee1, 0x6804, 0xac06, 0x00c0, 0x1ebf, 0x6000, 0x2060, 0x6806,
+	0xa005, 0x00c0, 0x1ebf, 0x6803, 0x0000, 0x0078, 0x1ec9, 0x6400,
+	0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1ec9, 0x2c00,
+	0x6802, 0x2560, 0x0f7f, 0x1078, 0x1e5b, 0x0f7e, 0x601b, 0x0005,
+	0x6023, 0x0020, 0x0f7f, 0x1078, 0x201d, 0x0f7e, 0x7908, 0x8109,
+	0x790a, 0x6810, 0x8001, 0x6812, 0x00c0, 0x1ee1, 0x7810, 0xc0a5,
+	0x7812, 0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700,
+	0x2039, 0x0000, 0xd0fc, 0x0040, 0x1eee, 0xc7fd, 0x2041, 0x0021,
+	0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1dff,
+	0x8738, 0xa784, 0x001f, 0x00c0, 0x1ef6, 0xa7bc, 0xff00, 0x873f,
+	0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1ef6, 0x2091, 0x8001,
+	0x077f, 0x007c, 0x786c, 0x2009, 0x9674, 0x210c, 0xa10d, 0x0040,
+	0x1f14, 0xa065, 0x0078, 0x2395, 0x2061, 0x0000, 0x6018, 0xd084,
+	0x00c0, 0x1f34, 0x7810, 0xd08c, 0x0040, 0x1f25, 0xc08c, 0x7812,
+	0xc7fc, 0x2069, 0x4e40, 0x0078, 0x1f2a, 0xc08d, 0x7812, 0x2069,
+	0x4e80, 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091,
+	0x8001, 0xa005, 0x00c0, 0x1f35, 0x007c, 0xa08c, 0xfff0, 0x0040,
+	0x1f3b, 0x1078, 0x296b, 0x0079, 0x1f3d, 0x1f4d, 0x1f50, 0x1f56,
+	0x1f5a, 0x1f4e, 0x1f5e, 0x1f4e, 0x1f4e, 0x1f4e, 0x1f64, 0x1f95,
+	0x1f99, 0x1f9f, 0x1fb4, 0x1f4e, 0x1f4e, 0x007c, 0x1078, 0x296b,
+	0x1078, 0x1ee6, 0x2001, 0x8001, 0x0078, 0x1fc0, 0x2001, 0x8003,
+	0x0078, 0x1fc0, 0x2001, 0x8004, 0x0078, 0x1fc0, 0x1078, 0x1ee6,
+	0x2001, 0x8006, 0x0078, 0x1fc0, 0x2091, 0x8000, 0x077e, 0xd7fc,
+	0x00c0, 0x1f70, 0x2069, 0x4e40, 0x2039, 0x0009, 0x0078, 0x1f74,
+	0x2069, 0x4e80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040,
+	0x1f7e, 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f,
+	0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
+	0x1078, 0x1dff, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1f88, 0x2091,
+	0x8001, 0x2001, 0x800a, 0x0078, 0x1fc0, 0x2001, 0x800c, 0x0078,
+	0x1fc0, 0x1078, 0x1ee6, 0x2001, 0x800d, 0x0078, 0x1fc0, 0x7814,
+	0xd0e4, 0x00c0, 0x1fb2, 0xd0ec, 0x0040, 0x1fac, 0xd7fc, 0x0040,
+	0x1fac, 0x78e4, 0x0078, 0x1fad, 0x78e0, 0x70c6, 0x2001, 0x800e,
+	0x0078, 0x1fc0, 0x0078, 0x1f4e, 0xd7fc, 0x0040, 0x1fba, 0x78ec,
+	0x0078, 0x1fbb, 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0078, 0x1fc0,
+	0x70c2, 0xd7fc, 0x00c0, 0x1fc8, 0x70db, 0x0000, 0x0078, 0x1fca,
+	0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080,
+	0x007c, 0xac80, 0x0001, 0x81ff, 0x0040, 0x1ffc, 0x2099, 0x0030,
+	0x20a0, 0x700c, 0xa084, 0x03ff, 0x0040, 0x1fde, 0x7018, 0x007e,
+	0x701c, 0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac,
+	0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001,
+	0x7008, 0x800b, 0x00c8, 0x1ff0, 0x7007, 0x0002, 0xa08c, 0x01e0,
+	0x00c0, 0x1ffc, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004,
+	0x007f, 0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a,
+	0x007c, 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803,
+	0xfd00, 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290,
+	0x0004, 0x8109, 0x00c0, 0x200d, 0x007c, 0x6004, 0x6086, 0x2c08,
+	0x2063, 0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x202a, 0x2c02,
+	0x0078, 0x202b, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4e00, 0x6887,
+	0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040,
+	0x203c, 0x2d02, 0x0078, 0x203d, 0x616e, 0x0c7f, 0x007c, 0x2091,
+	0x8000, 0x2c04, 0x786e, 0xa005, 0x00c0, 0x2047, 0x786a, 0x2091,
+	0x8001, 0x609c, 0xa005, 0x0040, 0x2060, 0x0c7e, 0x2060, 0x2008,
+	0x609c, 0xa005, 0x0040, 0x205c, 0x2062, 0x609f, 0x0000, 0xa065,
+	0x609c, 0xa005, 0x00c0, 0x2054, 0x7848, 0x794a, 0x2062, 0x0c7f,
+	0x7848, 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x206a,
+	0x1078, 0x296b, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004,
+	0x8086, 0x818e, 0x00c8, 0x2075, 0xa200, 0x00f0, 0x2070, 0x8086,
+	0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x209b,
+	0xa11a, 0x00c8, 0x209b, 0x8213, 0x818d, 0x0048, 0x208e, 0xa11a,
+	0x00c8, 0x208f, 0x00f0, 0x2083, 0x0078, 0x2093, 0xa11a, 0x2308,
+	0x8210, 0x00f0, 0x2083, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080,
+	0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078,
+	0x2097, 0x7d74, 0x70d0, 0xa506, 0x0040, 0x2187, 0x7810, 0x2050,
+	0x7800, 0xd08c, 0x0040, 0x20c3, 0xdaec, 0x0040, 0x20c3, 0x0e7e,
+	0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20c0,
+	0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x20c3, 0x0078, 0x2187,
+	0x0e7f, 0x0078, 0x2187, 0x1078, 0x1dbd, 0x0040, 0x2187, 0xa046,
+	0x7970, 0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20d2,
+	0x0078, 0x20d9, 0x72d0, 0xa206, 0x0040, 0x20d9, 0x8840, 0x2009,
+	0x0080, 0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9,
+	0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040,
+	0x20eb, 0x1078, 0x1dbd, 0x7008, 0xd0fc, 0x0040, 0x20eb, 0x7007,
+	0x0002, 0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2122, 0x53a5,
+	0x8cff, 0x00c0, 0x2100, 0x88ff, 0x0040, 0x2171, 0x0078, 0x210a,
+	0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5,
+	0x0078, 0x2171, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2112,
+	0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000,
+	0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2122, 0x7422,
+	0x7526, 0xa006, 0x7007, 0x0004, 0x0040, 0x2171, 0x8cff, 0x0040,
+	0x212b, 0x1078, 0x1dc6, 0x0c7f, 0x1078, 0x1dc6, 0xa046, 0x7888,
+	0x8000, 0x788a, 0xa086, 0x0002, 0x0040, 0x2151, 0x7a7c, 0x7b78,
+	0xdac4, 0x0040, 0x213d, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004,
+	0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
+	0x721a, 0x731e, 0xdac4, 0x0040, 0x2187, 0x7422, 0x7526, 0x0078,
+	0x2187, 0x6014, 0xd0fc, 0x00c0, 0x2159, 0x2069, 0x4e40, 0x0078,
+	0x215b, 0x2069, 0x4e80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff,
+	0x0040, 0x2167, 0xa046, 0x788c, 0x2060, 0x0078, 0x2151, 0x788b,
+	0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078,
+	0x2187, 0x0c7f, 0x788b, 0x0000, 0x1078, 0x2346, 0x6004, 0xa084,
+	0x000f, 0x1078, 0x2188, 0x88ff, 0x0040, 0x2185, 0x788c, 0x2060,
+	0x6004, 0xa084, 0x000f, 0x1078, 0x2188, 0x0078, 0x20a1, 0x007c,
+	0x0079, 0x218a, 0x219a, 0x21b8, 0x21d6, 0x219a, 0x21e7, 0x21ab,
+	0x219a, 0x219a, 0x219a, 0x21b6, 0x21d4, 0x219a, 0x219a, 0x219a,
+	0x219a, 0x219a, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008,
+	0xa705, 0x600a, 0x1078, 0x222a, 0x609c, 0x78ba, 0x609f, 0x0000,
+	0x1078, 0x2330, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21b1, 0x0078,
+	0x219a, 0x601c, 0xc0bd, 0x601e, 0x0078, 0x21be, 0x1078, 0x2378,
+	0x78bc, 0xd0c4, 0x0040, 0x21be, 0x0078, 0x219a, 0x78bf, 0x0000,
+	0x6004, 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21d1,
+	0x1078, 0x222a, 0x0040, 0x21d1, 0x78bc, 0xc0c5, 0x78be, 0x0078,
+	0x21d3, 0x0078, 0x2249, 0x007c, 0x1078, 0x2374, 0x78bc, 0xa08c,
+	0x0e00, 0x00c0, 0x21de, 0xd0c4, 0x00c0, 0x21e0, 0x0078, 0x219a,
+	0x1078, 0x222a, 0x00c0, 0x21e6, 0x0078, 0x2249, 0x007c, 0x78bc,
+	0xd0c4, 0x0040, 0x21ed, 0x0078, 0x219a, 0x78bf, 0x0000, 0x6714,
+	0x2011, 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040,
+	0x220d, 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040,
+	0x220d, 0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e,
+	0x0002, 0x0040, 0x220d, 0x0078, 0x2227, 0x1078, 0x1de4, 0x2d00,
+	0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084,
+	0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x2210,
+	0x8211, 0x0040, 0x2227, 0x20a9, 0x0100, 0x0078, 0x2210, 0x1078,
+	0x1dc6, 0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6,
+	0x00c0, 0x2235, 0x78ba, 0x0078, 0x223d, 0x689e, 0x2d00, 0x6002,
+	0x78b8, 0xad06, 0x00c0, 0x223d, 0x6002, 0x78b0, 0x8001, 0x78b2,
+	0x00c0, 0x2248, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006,
+	0x007c, 0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2,
+	0x601c, 0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060,
+	0x0040, 0x225c, 0x1078, 0x4632, 0x6596, 0x65a6, 0x669a, 0x66aa,
+	0x6714, 0x2071, 0x4e80, 0xd7fc, 0x00c0, 0x2268, 0x2071, 0x4e40,
+	0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x2273, 0x8003,
+	0x8003, 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2,
+	0x2091, 0x8000, 0x7814, 0xd0c4, 0x0040, 0x2298, 0xd0ec, 0x0040,
+	0x2294, 0xd7fc, 0x00c0, 0x2291, 0xd0f4, 0x00c0, 0x229f, 0x0078,
+	0x2298, 0xd0fc, 0x00c0, 0x229f, 0x7810, 0xd0f4, 0x00c0, 0x229f,
+	0x6e08, 0xd684, 0x0040, 0x22c9, 0xd9fc, 0x00c0, 0x22c9, 0x2091,
+	0x8001, 0x1078, 0x1e5b, 0x2091, 0x8000, 0x1078, 0x201d, 0x2091,
+	0x8001, 0x7814, 0xd0e4, 0x00c0, 0x232e, 0x7814, 0xd0c4, 0x0040,
+	0x232e, 0xd0ec, 0x0040, 0x22c1, 0xd7fc, 0x00c0, 0x22bc, 0xd0f4,
+	0x00c0, 0x22c5, 0x0078, 0x232e, 0xd0fc, 0x00c0, 0x22c5, 0x0078,
+	0x232e, 0x7810, 0xd0f4, 0x0040, 0x232e, 0x601b, 0x0021, 0x0078,
+	0x232e, 0x6024, 0xa096, 0x0001, 0x00c0, 0x22d0, 0x8000, 0x6026,
+	0x6a10, 0x6814, 0xa202, 0x0048, 0x22e3, 0x0040, 0x22e3, 0x2091,
 	0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
-	0x2303, 0x0078, 0x2301, 0x2c08, 0xd9fc, 0x0040, 0x22de, 0x6800,
-	0xa065, 0x0040, 0x22de, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040,
-	0x22d9, 0x704c, 0xa206, 0x00c0, 0x22d9, 0x6b04, 0x2160, 0x2304,
-	0x6002, 0xa005, 0x00c0, 0x22d5, 0x6902, 0x2260, 0x6102, 0x0078,
-	0x22ea, 0x2160, 0x6202, 0x6906, 0x0078, 0x22ea, 0x6800, 0x6902,
-	0xa065, 0x0040, 0x22e6, 0x6102, 0x0078, 0x22e7, 0x6906, 0x2160,
-	0x6003, 0x0000, 0x2160, 0xd9fc, 0x0040, 0x22f1, 0xa6b4, 0xfffc,
-	0x6e0a, 0x6810, 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091,
-	0x8001, 0xd6b4, 0x0040, 0x2301, 0xa6b6, 0x0040, 0x6e0a, 0x1078,
-	0x1e80, 0x0e7f, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000,
-	0x1078, 0x201b, 0x2091, 0x8001, 0x78b8, 0xa065, 0x0040, 0x2316,
-	0x609c, 0x78ba, 0x609f, 0x0000, 0x0078, 0x2303, 0x78b6, 0x78ba,
-	0x007c, 0x7970, 0x7874, 0x2818, 0xd384, 0x0040, 0x2323, 0x8000,
-	0xa112, 0x0048, 0x2328, 0x8000, 0xa112, 0x00c8, 0x2338, 0xc384,
-	0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0040, 0x2333, 0x7a84,
-	0x7222, 0x7a80, 0x7226, 0xa006, 0xd384, 0x0040, 0x2338, 0x8000,
-	0x7876, 0x70d2, 0x781c, 0xa005, 0x0040, 0x2346, 0x8001, 0x781e,
-	0x00c0, 0x2346, 0x0068, 0x2346, 0x2091, 0x4080, 0x007c, 0x2039,
-	0x235f, 0x0078, 0x234d, 0x2039, 0x2365, 0x2704, 0xa005, 0x0040,
-	0x235e, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912, 0x680a, 0x690c,
-	0x6814, 0x6916, 0x680e, 0x8738, 0x0078, 0x234d, 0x007c, 0x0003,
-	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000,
-	0x2041, 0x0000, 0x780c, 0x0079, 0x236d, 0x2535, 0x2508, 0x2371,
-	0x23e5, 0x2039, 0x9274, 0x2734, 0x7d10, 0x0078, 0x238c, 0x6084,
-	0xa086, 0x0103, 0x00c0, 0x23ce, 0x6114, 0x6018, 0xa105, 0x00c0,
-	0x23ce, 0x8603, 0xa080, 0x9255, 0x620c, 0x2202, 0x8000, 0x6210,
-	0x2202, 0x1078, 0x203d, 0x8630, 0xa68e, 0x000f, 0x0040, 0x2454,
-	0x786c, 0xa065, 0x00c0, 0x2377, 0x7808, 0xa602, 0x00c8, 0x239d,
-	0xd5ac, 0x00c0, 0x239d, 0x263a, 0x007c, 0xa682, 0x0003, 0x00c8,
-	0x2454, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
-	0x23c9, 0x2011, 0x9255, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca,
-	0xd684, 0x00c0, 0x23b9, 0x8210, 0x2204, 0x70da, 0x8210, 0x2204,
-	0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080,
-	0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b, 0x0000,
-	0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x2454, 0x263a, 0x1078,
-	0x253f, 0x00c0, 0x254e, 0x786c, 0xa065, 0x00c0, 0x2377, 0x2091,
-	0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x23e0, 0xc0ad,
-	0x7812, 0x2091, 0x8001, 0x0078, 0x254e, 0x2039, 0x9274, 0x2734,
-	0x7d10, 0x0078, 0x23fc, 0x6084, 0xa086, 0x0103, 0x00c0, 0x243d,
-	0x6114, 0x6018, 0xa105, 0x00c0, 0x243d, 0xa680, 0x9255, 0x620c,
-	0x2202, 0x1078, 0x203d, 0x8630, 0xa68e, 0x001e, 0x0040, 0x2454,
-	0x786c, 0xa065, 0x00c0, 0x23eb, 0x7808, 0xa602, 0x00c8, 0x240d,
-	0xd5ac, 0x00c0, 0x240d, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8,
-	0x2454, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0,
-	0x2438, 0x2011, 0x9255, 0x2009, 0x924e, 0x26a8, 0x211c, 0x2204,
-	0x201a, 0x8108, 0x8210, 0x00f0, 0x241e, 0xa685, 0x8030, 0x70c2,
-	0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812,
-	0x2091, 0x8001, 0xa006, 0x2009, 0x9275, 0x200a, 0x203a, 0x007c,
-	0x7810, 0xc0ad, 0x7812, 0x0078, 0x2454, 0x263a, 0x1078, 0x253f,
-	0x00c0, 0x254e, 0x786c, 0xa065, 0x00c0, 0x23eb, 0x2091, 0x8000,
-	0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x244f, 0xc0ad, 0x7812,
-	0x2091, 0x8001, 0x0078, 0x254e, 0x2091, 0x8000, 0x7007, 0x0004,
-	0x7994, 0x70d4, 0xa102, 0x0048, 0x2465, 0x0040, 0x246f, 0x7b90,
-	0xa302, 0x00c0, 0x246f, 0x0078, 0x2468, 0x8002, 0x00c0, 0x246f,
-	0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184,
-	0xff00, 0x0040, 0x247c, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004,
-	0x8007, 0xa100, 0x0078, 0x247f, 0x8107, 0x8004, 0x8004, 0x7a9c,
-	0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040,
-	0x248f, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1,
-	0x0030, 0x7003, 0x0000, 0x2009, 0x9254, 0x260a, 0x8109, 0x2198,
-	0x2104, 0xd084, 0x0040, 0x249d, 0x8633, 0xa6b0, 0x0002, 0x26a8,
-	0x53a6, 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000,
-	0xa10a, 0x00c8, 0x24ac, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00,
-	0x0040, 0x24bb, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
-	0xa100, 0x0078, 0x24be, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108,
-	0x7a78, 0xa006, 0xa211, 0xd4c4, 0x0040, 0x24ca, 0x7b84, 0xa319,
-	0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x24ca, 0xa084, 0x01e0,
-	0x0040, 0x24ef, 0x7d10, 0x2031, 0x9254, 0x2634, 0x78a8, 0x8000,
-	0x78aa, 0xd08c, 0x00c0, 0x24e4, 0x7007, 0x0006, 0x7004, 0xd094,
-	0x00c0, 0x24de, 0x0078, 0x2456, 0x2069, 0x4a47, 0x206b, 0x0003,
-	0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x24f8, 0x2030,
-	0x75d6, 0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12,
-	0x2091, 0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001,
-	0x711a, 0x721e, 0xd5c4, 0x0040, 0x2507, 0x7322, 0x7426, 0x007c,
-	0x6084, 0xa086, 0x0103, 0x00c0, 0x252b, 0x6114, 0x6018, 0xa105,
-	0x00c0, 0x252b, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x252b,
-	0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001,
-	0x2091, 0x4080, 0x1078, 0x203d, 0x0068, 0x252a, 0x786c, 0xa065,
-	0x00c0, 0x2508, 0x007c, 0x1078, 0x253f, 0x00c0, 0x254e, 0x786c,
-	0xa065, 0x00c0, 0x2508, 0x0078, 0x254e, 0x1078, 0x253f, 0x00c0,
-	0x254e, 0x786c, 0xa065, 0x00c0, 0x2535, 0x0078, 0x254e, 0x1078,
-	0x2554, 0x00c0, 0x2546, 0xa085, 0x0001, 0x007c, 0x1078, 0x2563,
-	0x00c0, 0x254c, 0x2041, 0x0001, 0x7d10, 0x007c, 0x88ff, 0x0040,
-	0x2553, 0x2091, 0x4080, 0x007c, 0x7b90, 0x7994, 0x70d4, 0xa102,
-	0x00c0, 0x255d, 0xa385, 0x0000, 0x007c, 0x0048, 0x2561, 0xa302,
-	0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x257b, 0x0e7e,
-	0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2578,
-	0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x257b, 0x0078, 0x25cc,
-	0x0e7f, 0x0078, 0x25cc, 0xa184, 0xff00, 0x0040, 0x2588, 0x810f,
-	0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078, 0x258b,
-	0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa210,
-	0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028, 0xa005,
-	0x0040, 0x259c, 0x2009, 0x0040, 0x1078, 0x1d92, 0x0040, 0x25be,
-	0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0, 0x25cc, 0x6014, 0xd0fc,
-	0x00c0, 0x25ae, 0x2069, 0x4a40, 0x0078, 0x25b0, 0x2069, 0x4a80,
-	0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000, 0x78ac, 0xa085,
-	0x0300, 0x78ae, 0x2091, 0x8001, 0x0078, 0x25cc, 0x78ab, 0x0000,
-	0x1078, 0x203d, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, 0x25c9,
-	0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010, 0x2091, 0x8001,
-	0x007c, 0x2138, 0xd7fc, 0x00c0, 0x25d9, 0x2009, 0x4a59, 0x0078,
-	0x25db, 0x2009, 0x4a99, 0x2091, 0x8000, 0x200a, 0x0f7e, 0xd7fc,
-	0x00c0, 0x25f2, 0x2009, 0x4a40, 0x2001, 0x4a04, 0x2004, 0xd0ec,
-	0x0040, 0x25ee, 0x2079, 0x0100, 0x0078, 0x25f6, 0x2079, 0x0200,
-	0x0078, 0x25f6, 0x2009, 0x4a80, 0x2079, 0x0100, 0x2104, 0xa086,
-	0x0000, 0x00c0, 0x260f, 0xd7fc, 0x00c0, 0x2602, 0x2009, 0x4a45,
-	0x0078, 0x2604, 0x2009, 0x4a85, 0x2104, 0xa005, 0x00c0, 0x260f,
-	0x7830, 0xa084, 0x00c0, 0x00c0, 0x260f, 0x781b, 0x0045, 0x0f7f,
-	0x007c, 0x2009, 0x0002, 0x2069, 0x4a00, 0x6810, 0xd0ec, 0x00c0,
-	0x2672, 0x2071, 0x4a80, 0x2079, 0x0100, 0x2021, 0x4cbf, 0x784b,
-	0x000f, 0x2019, 0x4205, 0xd184, 0x0040, 0x2632, 0x6810, 0xd0ec,
-	0x0040, 0x262e, 0x20a1, 0x012b, 0x0078, 0x2634, 0x20a1, 0x022b,
-	0x0078, 0x2634, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x2641,
-	0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078,
-	0x2634, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af,
-	0x8020, 0x00f0, 0x2645, 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009,
-	0x0000, 0x0040, 0x2654, 0xc1bd, 0x1078, 0x283d, 0x017f, 0x7020,
-	0xa084, 0x000f, 0x007e, 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x2664,
-	0xa085, 0x6340, 0x0078, 0x2666, 0xa085, 0x62c0, 0x7806, 0x780f,
-	0x9200, 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7456,
-	0x7053, 0x0000, 0x8109, 0x0040, 0x2685, 0x2071, 0x4a40, 0x6810,
-	0xd0ec, 0x0040, 0x267f, 0x2079, 0x0100, 0x0078, 0x2681, 0x2079,
-	0x0200, 0x2021, 0x4abf, 0x0078, 0x261f, 0x007c, 0x017e, 0xd1bc,
-	0x00c0, 0x269a, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f,
-	0x0040, 0x2696, 0x2011, 0x0101, 0x0078, 0x269c, 0x2011, 0x0201,
-	0x0078, 0x269c, 0x2011, 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084,
-	0xfff0, 0xa105, 0x2012, 0x017f, 0x1078, 0x283d, 0x007c, 0xd3fc,
-	0x00c0, 0x26ba, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f,
-	0x0040, 0x26b6, 0x2011, 0x0101, 0x0078, 0x26bc, 0x2011, 0x0201,
-	0x0078, 0x26bc, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0,
-	0x26be, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012,
-	0x007c, 0x2019, 0x0002, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x0040,
-	0x26d6, 0x8319, 0x2009, 0x0101, 0x0078, 0x26d8, 0x2009, 0x0101,
-	0x20a9, 0x0005, 0x8213, 0x00f0, 0x26da, 0xa294, 0x00e0, 0x2104,
-	0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0040, 0x26eb, 0x2009,
-	0x0201, 0x0078, 0x26d8, 0x007c, 0xd3fc, 0x00c0, 0x26ff, 0x007e,
-	0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26fb, 0x2011,
-	0x0101, 0x0078, 0x2701, 0x2011, 0x0201, 0x0078, 0x2701, 0x2011,
-	0x0101, 0x20a9, 0x000c, 0x810b, 0x00f0, 0x2703, 0xa18c, 0xf000,
-	0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0,
-	0x2721, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040,
-	0x271d, 0x2011, 0x0102, 0x0078, 0x2723, 0x2011, 0x0202, 0x0078,
-	0x2723, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012,
-	0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x273d, 0x007e, 0x2001, 0x4a04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2739, 0x2061, 0x0100, 0x0078,
-	0x273f, 0x2061, 0x0200, 0x0078, 0x273f, 0x2061, 0x0100, 0xc1bc,
-	0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f,
-	0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x275d, 0x007e, 0x2001, 0x4a04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2759, 0x2061, 0x0100, 0x0078,
-	0x275f, 0x2061, 0x0200, 0x0078, 0x275f, 0x2061, 0x0100, 0xc1bc,
-	0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf,
-	0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x277f, 0x007e,
-	0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x277b, 0x2061,
-	0x0100, 0x0078, 0x2781, 0x2061, 0x0200, 0x0078, 0x2781, 0x2061,
-	0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4,
-	0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0,
-	0x27a1, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040,
-	0x279d, 0x2061, 0x0100, 0x0078, 0x27a3, 0x2061, 0x0200, 0x0078,
-	0x27a3, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020,
-	0x609a, 0x60a4, 0xa28c, 0x0020, 0x0040, 0x27b1, 0xc2ac, 0xa39d,
-	0x4000, 0xc3fc, 0xd3b4, 0x00c0, 0x27b6, 0xc3fd, 0x62ae, 0x2010,
-	0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e,
-	0x0e7e, 0x6818, 0xa005, 0x0040, 0x281b, 0xd1fc, 0x0040, 0x27cc,
-	0x2061, 0x91d0, 0x0078, 0x27ce, 0x2061, 0x90c0, 0x1078, 0x2823,
-	0x0040, 0x2801, 0x20a9, 0x0101, 0xd1fc, 0x0040, 0x27db, 0x2061,
-	0x90d0, 0x0078, 0x27dd, 0x2061, 0x8fc0, 0x0c7e, 0x1078, 0x2823,
-	0x0040, 0x27e8, 0x0c7f, 0x8c60, 0x00f0, 0x27dd, 0x0078, 0x281b,
-	0x007f, 0xd1fc, 0x0040, 0x27f2, 0xa082, 0x90d0, 0x2071, 0x4a80,
-	0x0078, 0x27f6, 0xa082, 0x8fc0, 0x2071, 0x4a40, 0x707a, 0x7176,
-	0x2001, 0x0004, 0x7066, 0x7083, 0x000f, 0x1078, 0x25d1, 0x0078,
-	0x2817, 0xd1fc, 0x00c0, 0x2808, 0x2071, 0x4a40, 0x0078, 0x280a,
-	0x2071, 0x4a80, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2c00, 0x707e,
-	0x2001, 0x0006, 0x7066, 0x7083, 0x000f, 0x1078, 0x25d1, 0x2001,
-	0x0000, 0x0078, 0x281d, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005,
-	0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x283a, 0x2060,
-	0x6010, 0xa306, 0x00c0, 0x2837, 0x600c, 0xa206, 0x00c0, 0x2837,
-	0x6014, 0xa106, 0x00c0, 0x2837, 0xa006, 0x0078, 0x283c, 0x6000,
-	0x0078, 0x2824, 0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e,
-	0xd1bc, 0x00c0, 0x2855, 0x2079, 0x4a40, 0x007e, 0x2001, 0x4a04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2851, 0x2071, 0x0100, 0x0078,
-	0x2859, 0x2071, 0x0200, 0x0078, 0x2859, 0x2079, 0x4a80, 0x2071,
-	0x0100, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x2863,
-	0x017f, 0x0078, 0x287e, 0x810b, 0x810b, 0x810b, 0x810b, 0x007f,
-	0xd0bc, 0x00c0, 0x287b, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x2877, 0xa18d, 0x0f00, 0x0078, 0x287d, 0xa18d,
-	0x0f00, 0x0078, 0x287d, 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f,
-	0x007c, 0x0e7e, 0x2001, 0x4a01, 0x2004, 0xd0ac, 0x00c0, 0x28ea,
-	0x68e4, 0xd0ac, 0x0040, 0x28ea, 0xa084, 0x0006, 0x00c0, 0x28ea,
-	0x6014, 0xd0fc, 0x00c0, 0x2898, 0x2071, 0x4ec0, 0x0078, 0x289a,
-	0x2071, 0x4f40, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xae70, 0x7004, 0xa084, 0x000a, 0x00c0, 0x28ea, 0x7108, 0xa194,
-	0xff00, 0x0040, 0x28ea, 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106,
-	0x0040, 0x28cd, 0x2001, 0x000c, 0xa106, 0x0040, 0x28d1, 0x2001,
-	0x0012, 0xa106, 0x0040, 0x28d5, 0x2001, 0x0014, 0xa106, 0x0040,
-	0x28d9, 0x2001, 0x0019, 0xa106, 0x0040, 0x28dd, 0x2001, 0x0032,
-	0xa106, 0x0040, 0x28e1, 0x0078, 0x28e5, 0x2009, 0x000c, 0x0078,
-	0x28e7, 0x2009, 0x0012, 0x0078, 0x28e7, 0x2009, 0x0014, 0x0078,
-	0x28e7, 0x2009, 0x0019, 0x0078, 0x28e7, 0x2009, 0x0020, 0x0078,
-	0x28e7, 0x2009, 0x003f, 0x0078, 0x28e7, 0x2011, 0x0000, 0x2100,
-	0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x28ec, 0x2091, 0x8000,
-	0x2071, 0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x28f3, 0x007f,
-	0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db,
-	0x0809, 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
-	0x4080, 0x0078, 0x2909, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0,
-	0x708e, 0x7592, 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4,
-	0x0040, 0x2920, 0xa784, 0x007d, 0x00c0, 0x417b, 0x1078, 0x28ec,
-	0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x292b, 0xa3a6, 0x0007,
-	0x00c0, 0x28ec, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x2930,
-	0x2f45, 0x3035, 0x3060, 0x32c1, 0x363b, 0x36a1, 0x3741, 0x37bd,
-	0x38a1, 0x398a, 0x2943, 0x2940, 0x2d2a, 0x2e43, 0x360e, 0x2940,
-	0x1078, 0x28ec, 0x007c, 0xa006, 0x0078, 0x294d, 0x7808, 0xc08d,
-	0x780a, 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005,
-	0x00c0, 0x2a64, 0x7064, 0xa084, 0x0007, 0x0079, 0x2957, 0x295f,
-	0x29cf, 0x29d8, 0x29e3, 0x29ee, 0x2a4a, 0x29f9, 0x29cf, 0x7830,
-	0xd0bc, 0x00c0, 0x2942, 0x71d4, 0xd1b4, 0x00c0, 0x29ac, 0x70a4,
-	0xa086, 0x0001, 0x0040, 0x2942, 0x70b4, 0xa06d, 0x6800, 0xa065,
-	0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10,
-	0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x2982, 0x69bc,
-	0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0078,
-	0x2bbd, 0x7060, 0xa005, 0x00c0, 0x2942, 0x0c7e, 0x0d7e, 0x70b4,
-	0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa,
-	0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001,
-	0x0040, 0x29a5, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c,
-	0x2001, 0x0020, 0x0078, 0x2bbd, 0x1078, 0x411c, 0x00c0, 0x2942,
-	0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
-	0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc,
-	0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x7003,
-	0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0x1078,
-	0x411c, 0x00c0, 0x29d7, 0x781b, 0x0047, 0x7003, 0x0004, 0x007c,
-	0x1078, 0x411c, 0x00c0, 0x29e2, 0x2011, 0x000c, 0x1078, 0x2a09,
-	0x7003, 0x0004, 0x007c, 0x1078, 0x411c, 0x00c0, 0x29ed, 0x2011,
-	0x0006, 0x1078, 0x2a09, 0x7003, 0x0004, 0x007c, 0x1078, 0x411c,
-	0x00c0, 0x29f8, 0x2011, 0x000d, 0x1078, 0x2a09, 0x7003, 0x0004,
-	0x007c, 0x1078, 0x411c, 0x00c0, 0x2a08, 0x2011, 0x0006, 0x1078,
-	0x2a09, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e, 0x7003, 0x0001,
-	0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0010, 0xa286,
-	0x000c, 0x00c0, 0x2a18, 0x7aaa, 0x2001, 0x0001, 0x0078, 0x2a2d,
-	0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, 0x0040,
-	0x2a26, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2a2d, 0x78ab, 0x0020,
-	0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa,
-	0x785b, 0x0004, 0x781b, 0x0108, 0x1078, 0x4131, 0x7083, 0x000f,
-	0x70d4, 0xd0b4, 0x0040, 0x2a49, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8,
-	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
-	0x0c7f, 0x007c, 0x1078, 0x411c, 0x00c0, 0x2942, 0x707c, 0x2068,
-	0x7774, 0x1078, 0x3fe1, 0x2c50, 0x1078, 0x41f0, 0x789b, 0x0010,
-	0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001,
-	0x2001, 0x0004, 0x0078, 0x2bc3, 0x1078, 0x411c, 0x00c0, 0x2942,
-	0x789b, 0x0010, 0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040,
-	0x2a7e, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
-	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x3fe1,
-	0x2c50, 0x1078, 0x41f0, 0x6824, 0xa005, 0x0040, 0x2a8f, 0xa082,
-	0x0006, 0x0048, 0x2a8d, 0x0078, 0x2a8f, 0x6827, 0x0005, 0x6814,
-	0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
-	0x2001, 0x0003, 0x0078, 0x2bc3, 0xc28d, 0x72d6, 0x72c0, 0xa200,
-	0xa015, 0x7154, 0x8108, 0xa12a, 0x0048, 0x2aa7, 0x71c0, 0x2164,
-	0x6504, 0x85ff, 0x00c0, 0x2abe, 0x7156, 0x8421, 0x00c0, 0x2aa2,
-	0x70d4, 0xd08c, 0x0040, 0x2aba, 0x70d0, 0xa005, 0x00c0, 0x2aba,
-	0x70d3, 0x000a, 0x007c, 0x2200, 0x0078, 0x2aac, 0x70d4, 0xc08c,
-	0x70d6, 0x70d3, 0x0000, 0x603c, 0xa005, 0x00c0, 0x2abb, 0x6708,
-	0xa784, 0x073f, 0x0040, 0x2aed, 0xd7d4, 0x00c0, 0x2abb, 0xa784,
-	0x0021, 0x00c0, 0x2abb, 0xa784, 0x0002, 0x0040, 0x2ade, 0xa784,
-	0x0004, 0x0040, 0x2abb, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218,
-	0x00c0, 0x2abb, 0xa784, 0x0100, 0x0040, 0x2aed, 0x6018, 0xa005,
-	0x00c0, 0x2abb, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000,
-	0x6e1c, 0xa684, 0x000e, 0x6318, 0x0040, 0x2afe, 0x601c, 0xa302,
-	0x0048, 0x2b01, 0x0040, 0x2b01, 0x0078, 0x2abb, 0x83ff, 0x00c0,
-	0x2abb, 0x2d58, 0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2b09, 0x7028,
-	0x6022, 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60,
-	0x2041, 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc,
-	0x0040, 0x2b1d, 0xd684, 0x0040, 0x2b1f, 0xa39c, 0xffbf, 0xd6a4,
-	0x0040, 0x2b24, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2b6f,
-	0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0,
-	0x2b43, 0x70d4, 0xd0b4, 0x00c0, 0x2b43, 0x7000, 0xa082, 0x0002,
-	0x00c8, 0x2b43, 0x7830, 0xd0bc, 0x00c0, 0x2b43, 0x789b, 0x0010,
-	0x7baa, 0x0078, 0x2bbb, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0,
-	0x0005, 0x70ac, 0xa606, 0x00c0, 0x2b4e, 0x76a8, 0x76b2, 0x2c3a,
-	0x8738, 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a,
-	0x7830, 0xd0bc, 0x0040, 0x2b66, 0x2091, 0x8000, 0x2091, 0x303d,
-	0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000,
-	0x0040, 0x2b6e, 0x8421, 0x2200, 0x00c0, 0x2aa1, 0x007c, 0xd1dc,
-	0x0040, 0x3be5, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2b7c, 0x8528,
-	0xd68c, 0x00c0, 0x2b7c, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108,
-	0xa18c, 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2b9b,
-	0x6014, 0xa706, 0x00c0, 0x2b84, 0x60b8, 0x8001, 0x60ba, 0x00c0,
-	0x2b7f, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421,
-	0x00c0, 0x2aa1, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6,
-	0x8840, 0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0,
-	0x2b43, 0x70d4, 0xd0b4, 0x00c0, 0x2b43, 0x7000, 0xa082, 0x0002,
-	0x00c8, 0x2b43, 0x7830, 0xd0bc, 0x00c0, 0x2b43, 0x789b, 0x0010,
-	0x7baa, 0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000,
-	0x601a, 0x0078, 0x2bc4, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184,
-	0x0018, 0x0040, 0x2be0, 0xa184, 0x0010, 0x0040, 0x2bd3, 0x1078,
-	0x3df6, 0x00c0, 0x2c05, 0xa184, 0x0008, 0x0040, 0x2be0, 0x69a0,
-	0xa184, 0x0600, 0x00c0, 0x2be0, 0x1078, 0x3cda, 0x0078, 0x2c05,
-	0x69a0, 0xa184, 0x1e00, 0x0040, 0x2c10, 0xa184, 0x0800, 0x0040,
-	0x2bf9, 0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104,
-	0xa18d, 0x0010, 0x6106, 0x0c7f, 0x1078, 0x3df6, 0x00c0, 0x2c05,
-	0x69a0, 0xa184, 0x0200, 0x0040, 0x2c01, 0x1078, 0x3d3a, 0x0078,
-	0x2c05, 0xa184, 0x0400, 0x00c0, 0x2bdc, 0x69a0, 0xa184, 0x1000,
-	0x0040, 0x2c10, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x2749,
-	0x027f, 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2c1d, 0xa086,
-	0x0060, 0x00c0, 0x2c1d, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6,
-	0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc,
-	0x0040, 0x2c38, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050,
-	0x2c36, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
-	0x78aa, 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b,
-	0x20a0, 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8,
-	0x2898, 0x25a0, 0xa286, 0x0020, 0x00c0, 0x2c70, 0x70d4, 0xc0b5,
-	0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007,
-	0x7882, 0xa286, 0x0002, 0x0040, 0x2ca6, 0x70a4, 0x8000, 0x70a6,
-	0x74b4, 0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2c68, 0x73a8,
-	0x73b6, 0xa286, 0x0010, 0x0040, 0x2942, 0x0d7f, 0x0c7f, 0x007c,
-	0x7000, 0xa005, 0x00c0, 0x2c4e, 0xa286, 0x0002, 0x00c0, 0x2cc0,
-	0x1078, 0x411c, 0x00c0, 0x2c4e, 0x6814, 0xc0fc, 0x8007, 0x7882,
-	0x2091, 0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6,
-	0x78de, 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d,
-	0x780a, 0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090,
-	0x0c7f, 0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003,
-	0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc,
-	0x0040, 0x2cb2, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091,
-	0x8000, 0x2090, 0x70a4, 0xa005, 0x00c0, 0x2cb7, 0x007c, 0x8421,
-	0x0040, 0x2cb6, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2aa1,
-	0xa286, 0x0010, 0x00c0, 0x2cf1, 0x1078, 0x411c, 0x00c0, 0x2c4e,
-	0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a,
+	0x2330, 0x0078, 0x232e, 0x2c08, 0xd9fc, 0x0040, 0x230b, 0x6800,
+	0xa065, 0x0040, 0x230b, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040,
+	0x2301, 0x704c, 0xa206, 0x00c0, 0x2301, 0x6b04, 0x2160, 0x2304,
+	0x6002, 0xa005, 0x00c0, 0x22fd, 0x6902, 0x2260, 0x6102, 0x0078,
+	0x2317, 0x2d00, 0x2060, 0x1078, 0x2acc, 0x6e08, 0x2160, 0x6202,
+	0x6906, 0x0078, 0x2317, 0x6800, 0x6902, 0xa065, 0x0040, 0x2313,
+	0x6102, 0x0078, 0x2314, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160,
+	0xd9fc, 0x0040, 0x231e, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08,
+	0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0040,
+	0x232e, 0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1e6c, 0x0e7f, 0x007c,
+	0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x201d, 0x2091,
+	0x8001, 0x78b8, 0xa065, 0x0040, 0x2343, 0x609c, 0x78ba, 0x609f,
+	0x0000, 0x0078, 0x2330, 0x78b6, 0x78ba, 0x007c, 0x7970, 0x7874,
+	0x2818, 0xd384, 0x0040, 0x2350, 0x8000, 0xa112, 0x0048, 0x2355,
+	0x8000, 0xa112, 0x00c8, 0x2365, 0xc384, 0x7a7c, 0x721a, 0x7a78,
+	0x721e, 0xdac4, 0x0040, 0x2360, 0x7a84, 0x7222, 0x7a80, 0x7226,
+	0xa006, 0xd384, 0x0040, 0x2365, 0x8000, 0x7876, 0x70d2, 0x781c,
+	0xa005, 0x0040, 0x2373, 0x8001, 0x781e, 0x00c0, 0x2373, 0x0068,
+	0x2373, 0x2091, 0x4080, 0x007c, 0x2039, 0x238c, 0x0078, 0x237a,
+	0x2039, 0x2392, 0x2704, 0xa005, 0x0040, 0x238b, 0xac00, 0x2068,
+	0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e,
+	0x8738, 0x0078, 0x237a, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015,
+	0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, 0x780c,
+	0x0079, 0x239a, 0x256c, 0x253f, 0x239e, 0x2417, 0x2039, 0x9674,
+	0x2734, 0x7d10, 0x0078, 0x23be, 0x6084, 0xa086, 0x0103, 0x00c0,
+	0x2400, 0x6114, 0x6018, 0xa105, 0x0040, 0x23b3, 0x86ff, 0x00c0,
+	0x23cf, 0x0078, 0x2400, 0x8603, 0xa080, 0x9655, 0x620c, 0x2202,
+	0x8000, 0x6210, 0x2202, 0x1078, 0x203f, 0x8630, 0xa68e, 0x000f,
+	0x0040, 0x248b, 0x786c, 0xa065, 0x00c0, 0x23a4, 0x7808, 0xa602,
+	0x00c8, 0x23cf, 0xd5ac, 0x00c0, 0x23cf, 0x263a, 0x007c, 0xa682,
+	0x0003, 0x00c8, 0x248b, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818,
+	0xd084, 0x00c0, 0x23fb, 0x2011, 0x9655, 0x2204, 0x70c6, 0x8210,
+	0x2204, 0x70ca, 0xd684, 0x00c0, 0x23eb, 0x8210, 0x2204, 0x70da,
+	0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001,
+	0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001,
+	0x203b, 0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x248b,
+	0x263a, 0x1078, 0x2576, 0x00c0, 0x2599, 0x786c, 0xa065, 0x00c0,
+	0x23a4, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040,
+	0x2412, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x2599, 0x2039,
+	0x9674, 0x2734, 0x7d10, 0x0078, 0x2433, 0x6084, 0xa086, 0x0103,
+	0x00c0, 0x2474, 0x6114, 0x6018, 0xa105, 0x0040, 0x242c, 0x86ff,
+	0x00c0, 0x2444, 0x0078, 0x2474, 0xa680, 0x9655, 0x620c, 0x2202,
+	0x1078, 0x203f, 0x8630, 0xa68e, 0x001e, 0x0040, 0x248b, 0x786c,
+	0xa065, 0x00c0, 0x241d, 0x7808, 0xa602, 0x00c8, 0x2444, 0xd5ac,
+	0x00c0, 0x2444, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, 0x248b,
+	0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x246f,
+	0x2011, 0x9655, 0x2009, 0x964e, 0x26a8, 0x211c, 0x2204, 0x201a,
+	0x8108, 0x8210, 0x00f0, 0x2455, 0xa685, 0x8030, 0x70c2, 0x681b,
+	0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091,
+	0x8001, 0xa006, 0x2009, 0x9675, 0x200a, 0x203a, 0x007c, 0x7810,
+	0xc0ad, 0x7812, 0x0078, 0x248b, 0x263a, 0x1078, 0x2576, 0x00c0,
+	0x2599, 0x786c, 0xa065, 0x00c0, 0x241d, 0x2091, 0x8000, 0x7810,
+	0xa084, 0xffcf, 0x86ff, 0x0040, 0x2486, 0xc0ad, 0x7812, 0x2091,
+	0x8001, 0x0078, 0x2599, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994,
+	0x70d4, 0xa102, 0x0048, 0x249c, 0x0040, 0x24a6, 0x7b90, 0xa302,
+	0x00c0, 0x24a6, 0x0078, 0x249f, 0x8002, 0x00c0, 0x24a6, 0x263a,
+	0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, 0xff00,
+	0x0040, 0x24b3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
+	0xa100, 0x0078, 0x24b6, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210,
+	0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, 0x24c6,
+	0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030,
+	0x7003, 0x0000, 0x2009, 0x9654, 0x260a, 0x8109, 0x2198, 0x2104,
+	0xd084, 0x0040, 0x24d4, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6,
+	0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a,
+	0x00c8, 0x24e3, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0040,
+	0x24f2, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+	0x0078, 0x24f5, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
+	0xa006, 0xa211, 0xd4c4, 0x0040, 0x2501, 0x7b84, 0xa319, 0x7c80,
+	0xa421, 0x7008, 0xd0fc, 0x0040, 0x2501, 0xa084, 0x01e0, 0x0040,
+	0x2526, 0x7d10, 0x2031, 0x9654, 0x2634, 0x78a8, 0x8000, 0x78aa,
+	0xd08c, 0x00c0, 0x251b, 0x7007, 0x0006, 0x7004, 0xd094, 0x00c0,
+	0x2515, 0x0078, 0x248d, 0x2069, 0x4e47, 0x206b, 0x0003, 0x78ac,
+	0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x252f, 0x2030, 0x75d6,
+	0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091,
+	0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a,
+	0x721e, 0xd5c4, 0x0040, 0x253e, 0x7322, 0x7426, 0x007c, 0x6084,
+	0xa086, 0x0103, 0x00c0, 0x2562, 0x6114, 0x6018, 0xa105, 0x00c0,
+	0x2562, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x2562, 0x600c,
+	0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091,
+	0x4080, 0x1078, 0x203f, 0x0068, 0x2561, 0x786c, 0xa065, 0x00c0,
+	0x253f, 0x007c, 0x1078, 0x2576, 0x00c0, 0x2599, 0x786c, 0xa065,
+	0x00c0, 0x253f, 0x0078, 0x2599, 0x1078, 0x2576, 0x00c0, 0x2599,
+	0x786c, 0xa065, 0x00c0, 0x256c, 0x0078, 0x2599, 0x6084, 0xa086,
+	0x0103, 0x00c0, 0x258a, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004,
+	0x00c0, 0x258a, 0x7804, 0xd0a4, 0x0040, 0x258a, 0x1078, 0x203f,
+	0xa006, 0x007c, 0x1078, 0x259f, 0x00c0, 0x2591, 0xa085, 0x0001,
+	0x007c, 0x1078, 0x25ae, 0x00c0, 0x2597, 0x2041, 0x0001, 0x7d10,
+	0x007c, 0x88ff, 0x0040, 0x259e, 0x2091, 0x4080, 0x007c, 0x7b90,
+	0x7994, 0x70d4, 0xa102, 0x00c0, 0x25a8, 0xa385, 0x0000, 0x007c,
+	0x0048, 0x25ac, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec,
+	0x0040, 0x25c6, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004,
+	0xa005, 0x00c0, 0x25c3, 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040,
+	0x25c6, 0x0078, 0x2617, 0x0e7f, 0x0078, 0x2617, 0xa184, 0xff00,
+	0x0040, 0x25d3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
+	0xa100, 0x0078, 0x25d6, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98,
+	0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009,
+	0x0018, 0x6028, 0xa005, 0x0040, 0x25e7, 0x2009, 0x0040, 0x1078,
+	0x1d74, 0x0040, 0x2609, 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0,
+	0x2617, 0x6014, 0xd0fc, 0x00c0, 0x25f9, 0x2069, 0x4e40, 0x0078,
+	0x25fb, 0x2069, 0x4e80, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab,
+	0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078,
+	0x2617, 0x78ab, 0x0000, 0x1078, 0x203f, 0x7990, 0x7894, 0x8000,
+	0xa10a, 0x00c8, 0x2614, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071,
+	0x0010, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x2623, 0x2009,
+	0x4e59, 0x0078, 0x2625, 0x2009, 0x4e99, 0x2091, 0x8000, 0x200a,
+	0x0f7e, 0xd7fc, 0x00c0, 0x263c, 0x2009, 0x4e40, 0x2001, 0x4e04,
+	0x2004, 0xd0ec, 0x0040, 0x2638, 0x2079, 0x0100, 0x0078, 0x2640,
+	0x2079, 0x0200, 0x0078, 0x2640, 0x2009, 0x4e80, 0x2079, 0x0100,
+	0x2104, 0xa086, 0x0000, 0x00c0, 0x2659, 0xd7fc, 0x00c0, 0x264c,
+	0x2009, 0x4e45, 0x0078, 0x264e, 0x2009, 0x4e85, 0x2104, 0xa005,
+	0x00c0, 0x2659, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2659, 0x781b,
+	0x0045, 0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, 0x4e00, 0x6810,
+	0xd0ec, 0x00c0, 0x26c8, 0x2071, 0x4e80, 0x2079, 0x0100, 0x2021,
+	0x50bf, 0x784b, 0x000f, 0x2019, 0x4457, 0xd184, 0x0040, 0x267c,
+	0x6810, 0xd0ec, 0x0040, 0x2678, 0x20a1, 0x012b, 0x0078, 0x267e,
+	0x20a1, 0x022b, 0x0078, 0x267e, 0x20a1, 0x012b, 0x2304, 0xa005,
+	0x0040, 0x268b, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6,
+	0x3318, 0x0078, 0x267e, 0x789b, 0x0020, 0x20a9, 0x0010, 0x6814,
+	0xd0e4, 0x0040, 0x269b, 0x78af, 0x0000, 0x78af, 0x9020, 0x00f0,
+	0x2693, 0x0078, 0x26a1, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0,
+	0x269b, 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040,
+	0x26aa, 0xc1bd, 0x1078, 0x289b, 0x017f, 0x7020, 0xa084, 0x000f,
+	0x007e, 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x26ba, 0xa085, 0x6340,
+	0x0078, 0x26bc, 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843,
+	0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000,
+	0x8109, 0x0040, 0x26db, 0x2071, 0x4e40, 0x6810, 0xd0ec, 0x0040,
+	0x26d5, 0x2079, 0x0100, 0x0078, 0x26d7, 0x2079, 0x0200, 0x2021,
+	0x4ebf, 0x0078, 0x2669, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x26f0,
+	0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26ec,
+	0x2011, 0x0101, 0x0078, 0x26f2, 0x2011, 0x0201, 0x0078, 0x26f2,
+	0x2011, 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105,
+	0x2012, 0x017f, 0x1078, 0x289b, 0x007c, 0xd3fc, 0x00c0, 0x2710,
+	0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x270c,
+	0x2011, 0x0101, 0x0078, 0x2712, 0x2011, 0x0201, 0x0078, 0x2712,
+	0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, 0x2714, 0xa18c,
+	0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019,
+	0x0002, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x0040, 0x272c, 0x8319,
+	0x2009, 0x0101, 0x0078, 0x272e, 0x2009, 0x0101, 0x20a9, 0x0005,
+	0x8213, 0x00f0, 0x2730, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f,
+	0xa205, 0x200a, 0x8319, 0x0040, 0x2741, 0x2009, 0x0201, 0x0078,
+	0x272e, 0x007c, 0xd3fc, 0x00c0, 0x2755, 0x007e, 0x2001, 0x4e04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2751, 0x2011, 0x0101, 0x0078,
+	0x2757, 0x2011, 0x0201, 0x0078, 0x2757, 0x2011, 0x0101, 0x20a9,
+	0x000c, 0x810b, 0x00f0, 0x2759, 0xa18c, 0xf000, 0x2204, 0xa084,
+	0x0fff, 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x2777, 0x007e,
+	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2773, 0x2011,
+	0x0102, 0x0078, 0x2779, 0x2011, 0x0202, 0x0078, 0x2779, 0x2011,
+	0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e,
+	0xd1bc, 0x00c0, 0x2793, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x278f, 0x2061, 0x0100, 0x0078, 0x2795, 0x2061,
+	0x0200, 0x0078, 0x2795, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003,
+	0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e,
+	0xd1bc, 0x00c0, 0x27b3, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x27af, 0x2061, 0x0100, 0x0078, 0x27b5, 0x2061,
+	0x0200, 0x0078, 0x27b5, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003,
+	0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f,
+	0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27d5, 0x007e, 0x2001, 0x4e04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x27d1, 0x2061, 0x0100, 0x0078,
+	0x27d7, 0x2061, 0x0200, 0x0078, 0x27d7, 0x2061, 0x0100, 0xc1bc,
+	0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020,
+	0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27f7, 0x007e,
+	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27f3, 0x2061,
+	0x0100, 0x0078, 0x27f9, 0x2061, 0x0200, 0x0078, 0x27f9, 0x2061,
+	0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4,
+	0xa28c, 0x0020, 0x0040, 0x2807, 0xc2ac, 0xa39d, 0x4000, 0xc3fc,
+	0xd3b4, 0x00c0, 0x280c, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae,
+	0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818,
+	0xa005, 0x0040, 0x2879, 0xd1fc, 0x0040, 0x2822, 0x2061, 0x95d0,
+	0x0078, 0x2824, 0x2061, 0x94c0, 0x1078, 0x2881, 0x0040, 0x285b,
+	0x20a9, 0x0101, 0xd1fc, 0x0040, 0x2831, 0x2061, 0x94d0, 0x0078,
+	0x2833, 0x2061, 0x93c0, 0x0c7e, 0x1078, 0x2881, 0x0040, 0x283e,
+	0x0c7f, 0x8c60, 0x00f0, 0x2833, 0x0078, 0x2879, 0x007f, 0xd1fc,
+	0x0040, 0x2848, 0xa082, 0x94d0, 0x2071, 0x4e80, 0x0078, 0x284c,
+	0xa082, 0x93c0, 0x2071, 0x4e40, 0x707a, 0x7176, 0x2138, 0x2001,
+	0x0004, 0x7066, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x1078,
+	0x261c, 0x0078, 0x2875, 0xd1fc, 0x00c0, 0x2862, 0x2071, 0x4e40,
+	0x0078, 0x2864, 0x2071, 0x4e80, 0x6020, 0xc0dd, 0x6022, 0x7176,
+	0x2138, 0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, 0x000f,
+	0x71d4, 0xc1dc, 0x71d6, 0x1078, 0x261c, 0x2001, 0x0000, 0x0078,
+	0x287b, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f,
+	0x007c, 0x2c04, 0xa005, 0x0040, 0x2898, 0x2060, 0x6010, 0xa306,
+	0x00c0, 0x2895, 0x600c, 0xa206, 0x00c0, 0x2895, 0x6014, 0xa106,
+	0x00c0, 0x2895, 0xa006, 0x0078, 0x289a, 0x6000, 0x0078, 0x2882,
+	0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0,
+	0x28b3, 0x2079, 0x4e40, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x28af, 0x2071, 0x0100, 0x0078, 0x28b7, 0x2071,
+	0x0200, 0x0078, 0x28b7, 0x2079, 0x4e80, 0x2071, 0x0100, 0x7920,
+	0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x28c1, 0x017f, 0x0078,
+	0x28dc, 0x810b, 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0,
+	0x28d9, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040,
+	0x28d5, 0xa18d, 0x0f00, 0x0078, 0x28db, 0xa18d, 0x0f00, 0x0078,
+	0x28db, 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e,
+	0x2001, 0x4e01, 0x2004, 0xd0ac, 0x00c0, 0x295c, 0x68e4, 0xd0ac,
+	0x0040, 0x295c, 0xa084, 0x0006, 0x00c0, 0x295c, 0x6014, 0xd0fc,
+	0x00c0, 0x28f6, 0x2071, 0x52c0, 0x0078, 0x28f8, 0x2071, 0x5340,
+	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004,
+	0xa084, 0x000a, 0x00c0, 0x295c, 0x7108, 0xa194, 0xff00, 0x0040,
+	0x295c, 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x292b,
+	0x2001, 0x000c, 0xa106, 0x0040, 0x292f, 0x2001, 0x0012, 0xa106,
+	0x0040, 0x2933, 0x2001, 0x0014, 0xa106, 0x0040, 0x2937, 0x2001,
+	0x0019, 0xa106, 0x0040, 0x293b, 0x2001, 0x0032, 0xa106, 0x0040,
+	0x293f, 0x0078, 0x2943, 0x2009, 0x000c, 0x0078, 0x2945, 0x2009,
+	0x0012, 0x0078, 0x2945, 0x2009, 0x0014, 0x0078, 0x2945, 0x2009,
+	0x0019, 0x0078, 0x2945, 0x2009, 0x0020, 0x0078, 0x2945, 0x2009,
+	0x003f, 0x0078, 0x2945, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a,
+	0x2071, 0x4e00, 0x7004, 0xd0bc, 0x0040, 0x295c, 0x6014, 0xd0fc,
+	0x00c0, 0x2957, 0x70ea, 0x2071, 0x4e40, 0x0078, 0x295a, 0x70ee,
+	0x2071, 0x4e80, 0x701f, 0x000d, 0x0e7f, 0x007c, 0x2001, 0x4e05,
+	0x2004, 0xd0e4, 0x00c0, 0x296a, 0x7804, 0xa084, 0xff1f, 0xa085,
+	0x6340, 0x7806, 0x007c, 0x0068, 0x296b, 0x2091, 0x8000, 0x2071,
+	0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x2972, 0x007f, 0x2071,
+	0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x080f,
+	0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
+	0x0078, 0x2988, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e,
+	0x7592, 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0040,
+	0x299f, 0xa784, 0x007d, 0x00c0, 0x43cd, 0x1078, 0x296b, 0xa49c,
+	0x000f, 0xa382, 0x0004, 0x0050, 0x29aa, 0xa3a6, 0x0007, 0x00c0,
+	0x296b, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x29af, 0x3028,
+	0x3119, 0x3144, 0x33b6, 0x379f, 0x3819, 0x38ce, 0x395f, 0x3a4d,
+	0x3b3c, 0x29c2, 0x29bf, 0x2df9, 0x2f1c, 0x3770, 0x29bf, 0x1078,
+	0x296b, 0x007c, 0xa006, 0x0078, 0x29cc, 0x7808, 0xc08d, 0x780a,
+	0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, 0x00c0,
+	0x2b32, 0x7064, 0xa084, 0x0007, 0x0079, 0x29d6, 0x29de, 0x2a51,
+	0x2a5a, 0x2a65, 0x2a70, 0x2b18, 0x2a7b, 0x2a51, 0x7830, 0xd0bc,
+	0x00c0, 0x29c1, 0x71d4, 0xd1bc, 0x00c0, 0x29c1, 0xd1b4, 0x00c0,
+	0x2a2e, 0x70a4, 0xa086, 0x0001, 0x0040, 0x29c1, 0x70b4, 0xa06d,
+	0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808,
+	0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040,
+	0x2a04, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001,
+	0x0010, 0x0078, 0x2c8c, 0x7060, 0xa005, 0x00c0, 0x29c1, 0x0c7e,
+	0x0d7e, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010,
+	0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d,
+	0xa886, 0x0001, 0x0040, 0x2a27, 0x69bc, 0x7daa, 0x79aa, 0x68c0,
+	0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0078, 0x2c8c, 0x1078, 0x4360,
+	0x00c0, 0x29c1, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a,
 	0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d,
-	0x780a, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac,
-	0xa206, 0x00c0, 0x2ce4, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc,
-	0x7042, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
-	0x007c, 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007,
-	0x7882, 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b,
-	0x005b, 0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300,
-	0xa605, 0x0040, 0x2d1c, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300,
-	0x00c0, 0x2d16, 0x2009, 0x0000, 0x0078, 0x2d18, 0x2009, 0x0001,
-	0xa284, 0x000f, 0x1079, 0x2d20, 0xad80, 0x0009, 0x7046, 0x007c,
-	0x2d28, 0x45f7, 0x45f7, 0x45e4, 0x45f7, 0x2d28, 0x2d28, 0x2d28,
-	0x1078, 0x28ec, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e, 0x2079,
-	0x4a00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2d4e, 0x7064, 0xa086,
-	0x0001, 0x00c0, 0x2d3e, 0x7066, 0x0078, 0x2e27, 0x7064, 0xa086,
-	0x0005, 0x00c0, 0x2d4c, 0x707c, 0x2068, 0x681b, 0x0004, 0x6817,
-	0x0000, 0x6820, 0xc09d, 0x6822, 0x7067, 0x0000, 0x70a7, 0x0000,
-	0x70a8, 0x70b2, 0x70b6, 0x70d4, 0xd0b4, 0x0040, 0x2d64, 0xc0b4,
+	0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0,
+	0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
+	0x007c, 0x1078, 0x4360, 0x00c0, 0x2a59, 0x781b, 0x0047, 0x7003,
+	0x0004, 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a64, 0x2011, 0x000c,
+	0x1078, 0x2a8b, 0x7003, 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0,
+	0x2a6f, 0x2011, 0x0006, 0x1078, 0x2a8b, 0x7003, 0x0004, 0x007c,
+	0x1078, 0x4360, 0x00c0, 0x2a7a, 0x2011, 0x000d, 0x1078, 0x2a8b,
+	0x7003, 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a8a, 0x2011,
+	0x0006, 0x1078, 0x2a8b, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e,
+	0x7003, 0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b,
+	0x0010, 0xa286, 0x000c, 0x00c0, 0x2a9a, 0x7aaa, 0x2001, 0x0001,
+	0x0078, 0x2aaf, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286,
+	0x000d, 0x0040, 0x2aa8, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2aaf,
+	0x78ab, 0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b,
+	0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0116, 0x1078, 0x4383,
+	0x7083, 0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2acb, 0xc0b4, 0x70d6,
+	0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
+	0x8001, 0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, 0x2ada,
+	0x70d4, 0xd0b4, 0x0040, 0x2adb, 0x70b8, 0xac06, 0x00c0, 0x2adb,
+	0x1078, 0x2aba, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, 0x0040,
+	0x2b0d, 0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4,
+	0x2068, 0x6800, 0xac06, 0x0040, 0x2af4, 0x8211, 0x0040, 0x2b0b,
+	0x1078, 0x2b0f, 0x0078, 0x2ae9, 0x0c7e, 0x2100, 0x2011, 0x0001,
+	0xa212, 0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x8211, 0x0040, 0x2b08, 0x1078, 0x2b0f, 0x0078, 0x2afb,
+	0x70a7, 0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, 0xade8,
+	0x0005, 0x70ac, 0xad06, 0x00c0, 0x2b17, 0x70a8, 0x2068, 0x007c,
+	0x1078, 0x4360, 0x00c0, 0x29c1, 0x707c, 0x2068, 0x7774, 0x1078,
+	0x41fe, 0x2c50, 0x1078, 0x4442, 0x789b, 0x0010, 0x6814, 0xa084,
+	0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004,
+	0x0078, 0x2c92, 0x1078, 0x4360, 0x00c0, 0x29c1, 0x789b, 0x0010,
+	0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2b4c, 0xc0b4,
 	0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x6018, 0x8001, 0x601a, 0x0c7f, 0x157e, 0x2011, 0x0004, 0x7164,
-	0xa186, 0x0001, 0x0040, 0x2d7d, 0xa186, 0x0007, 0x00c0, 0x2d74,
-	0x701f, 0x0005, 0x0078, 0x2d7d, 0x701f, 0x0001, 0x7067, 0x0000,
-	0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x2d7f, 0x7067, 0x0000, 0x2001,
-	0x4a0a, 0x2004, 0xa084, 0x00ff, 0xa086, 0x0018, 0x0040, 0x2d8f,
-	0x7018, 0x7016, 0xa005, 0x00c0, 0x2d8f, 0x70a7, 0x0001, 0x1078,
-	0x4326, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, 0x3edb, 0xa7b8,
-	0x0100, 0x00f0, 0x2d95, 0x7000, 0x0079, 0x2d9e, 0x2dcd, 0x2db3,
-	0x2db3, 0x2da8, 0x2dcd, 0x2dcd, 0x2dcd, 0x2da6, 0x1078, 0x28ec,
-	0x7060, 0xa005, 0x0040, 0x2dcd, 0xad06, 0x00c0, 0x2db3, 0x6800,
-	0x7062, 0x0078, 0x2dc5, 0x6820, 0xd084, 0x00c0, 0x2dc1, 0x6f14,
-	0x1078, 0x3fe1, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3bb5, 0x0078,
-	0x2dc5, 0x705c, 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000,
-	0x6820, 0xc09d, 0x6822, 0x1078, 0x202a, 0xb284, 0x0400, 0x0040,
-	0x2dd5, 0x2021, 0x91d0, 0x0078, 0x2dd7, 0x2021, 0x90c0, 0x1078,
-	0x2e2c, 0xb284, 0x0400, 0x0040, 0x2de1, 0x2021, 0x4a98, 0x0078,
-	0x2de3, 0x2021, 0x4a58, 0x1078, 0x2e2c, 0x20a9, 0x0101, 0xb284,
-	0x0400, 0x0040, 0x2def, 0x2021, 0x90d0, 0x0078, 0x2df1, 0x2021,
-	0x8fc0, 0x1078, 0x2e2c, 0x8420, 0x00f0, 0x2df1, 0xb284, 0x0300,
-	0x0040, 0x2dfe, 0x2061, 0x4fc0, 0x0078, 0x2e00, 0x2061, 0x6fc0,
-	0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040, 0x2e1d,
-	0x6018, 0x017e, 0x007e, 0x2011, 0x4a02, 0x220c, 0xa102, 0x2012,
-	0x007f, 0x017f, 0xa102, 0x0050, 0x2e1d, 0x6012, 0x00c0, 0x2e1d,
-	0x2011, 0x4a04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000, 0xace0,
-	0x0010, 0x00f0, 0x2e04, 0x8421, 0x00c0, 0x2e02, 0x157f, 0x7003,
-	0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005, 0x0040,
-	0x2e3f, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000, 0x6820,
-	0xc09d, 0x6822, 0x1078, 0x202a, 0x007f, 0x0078, 0x2e2e, 0x047f,
-	0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2e49, 0x1078,
-	0x28ec, 0x2300, 0x0079, 0x2e4c, 0x2e4f, 0x2eda, 0x2ef7, 0xa282,
-	0x0002, 0x0040, 0x2e55, 0x1078, 0x28ec, 0x7064, 0x7067, 0x0000,
-	0x7083, 0x0000, 0x0079, 0x2e5c, 0x2e64, 0x2e64, 0x2e66, 0x2ea6,
-	0x3bf1, 0x2e64, 0x2ea6, 0x2e64, 0x1078, 0x28ec, 0x7774, 0x1078,
-	0x3edb, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x3fe1, 0x6018, 0xa005,
-	0x0040, 0x2e9d, 0xd7fc, 0x00c0, 0x2e79, 0x2021, 0x90c0, 0x0078,
-	0x2e7b, 0x2021, 0x91d0, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078,
-	0x2f12, 0x0040, 0x2e9d, 0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0,
-	0x2e8d, 0x2021, 0x8fc0, 0x0078, 0x2e8f, 0x2021, 0x90d0, 0x047e,
-	0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2f12, 0x047f, 0x0040,
-	0x2e9c, 0x8420, 0x00f0, 0x2e8f, 0x157f, 0x8738, 0xa784, 0x001f,
-	0x00c0, 0x2e6c, 0x0078, 0x2946, 0x0078, 0x2946, 0x7774, 0x1078,
-	0x3fe1, 0x6018, 0xa005, 0x0040, 0x2ed8, 0xd7fc, 0x00c0, 0x2eb4,
-	0x2021, 0x90c0, 0x0078, 0x2eb6, 0x2021, 0x91d0, 0x2009, 0x0005,
-	0x2011, 0x0020, 0x1078, 0x2f12, 0x0040, 0x2ed8, 0x157e, 0x20a9,
-	0x0101, 0xd7fc, 0x00c0, 0x2ec8, 0x2021, 0x8fc0, 0x0078, 0x2eca,
-	0x2021, 0x90d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078,
-	0x2f12, 0x047f, 0x0040, 0x2ed7, 0x8420, 0x00f0, 0x2eca, 0x157f,
-	0x0078, 0x2946, 0x2200, 0x0079, 0x2edd, 0x2ee0, 0x2ee2, 0x2ee2,
-	0x1078, 0x28ec, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002, 0x0040,
-	0x2eeb, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2ef0, 0x691a,
-	0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x40c9, 0x2200,
-	0x0079, 0x2efa, 0x2eff, 0x2ee2, 0x2efd, 0x1078, 0x28ec, 0x1078,
-	0x4326, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b7a, 0x1078, 0x3bd2,
-	0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3b6b, 0x0040, 0x3b7a,
-	0x0078, 0x2946, 0x2404, 0xa005, 0x0040, 0x2f41, 0x2068, 0x2d04,
-	0x007e, 0x6814, 0xa706, 0x0040, 0x2f21, 0x2d20, 0x007f, 0x0078,
-	0x2f13, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x6820, 0xa205,
-	0x6822, 0x1078, 0x202a, 0x2021, 0x4a02, 0x241c, 0x8319, 0x2322,
-	0x6010, 0x8001, 0x6012, 0x00c0, 0x2f3a, 0x2021, 0x4a04, 0x2404,
-	0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078, 0x3bd2,
-	0x007c, 0xa085, 0x0001, 0x0078, 0x2f40, 0x2300, 0x0079, 0x2f48,
-	0x2f4d, 0x2f4b, 0x2fce, 0x1078, 0x28ec, 0x78e4, 0xa005, 0x00d0,
-	0x2f84, 0x3208, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f,
-	0x0040, 0x2f5e, 0xa18c, 0x0300, 0x0078, 0x2f60, 0xa18c, 0x0400,
-	0x0040, 0x2f66, 0x0018, 0x2942, 0x0078, 0x2f68, 0x0028, 0x2942,
-	0x2008, 0xa084, 0x0030, 0x00c0, 0x2f70, 0x781b, 0x005b, 0x007c,
-	0x78ec, 0xa084, 0x0003, 0x0040, 0x2f6d, 0x2100, 0xa084, 0x0007,
-	0x0079, 0x2f7a, 0x2fae, 0x2fb8, 0x2fa3, 0x2f82, 0x4111, 0x4111,
-	0x2f82, 0x2fc3, 0x1078, 0x28ec, 0x7000, 0xa086, 0x0004, 0x00c0,
-	0x2f9e, 0x7064, 0xa086, 0x0002, 0x00c0, 0x2f94, 0x2011, 0x0002,
-	0x2019, 0x0000, 0x0078, 0x2e43, 0x7064, 0xa086, 0x0006, 0x0040,
-	0x2f8e, 0x7064, 0xa086, 0x0004, 0x0040, 0x2f8e, 0x79e4, 0x2001,
-	0x0003, 0x0078, 0x3304, 0x6818, 0xd0fc, 0x0040, 0x2fa9, 0x681b,
-	0x001d, 0x1078, 0x3eae, 0x781b, 0x0061, 0x007c, 0x6818, 0xd0fc,
-	0x0040, 0x2fb4, 0x681b, 0x001d, 0x1078, 0x3eae, 0x0078, 0x40ed,
-	0x6818, 0xd0fc, 0x0040, 0x2fbe, 0x681b, 0x001d, 0x1078, 0x3eae,
-	0x781b, 0x00ef, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x2fc9, 0x681b,
-	0x001d, 0x1078, 0x3eae, 0x781b, 0x00bf, 0x007c, 0xa584, 0x000f,
-	0x00c0, 0x2feb, 0x7000, 0x0079, 0x2fd5, 0x2946, 0x2fdd, 0x2fdf,
-	0x3b7a, 0x3b7a, 0x3b7a, 0x2fdd, 0x2fdd, 0x1078, 0x28ec, 0x1078,
-	0x3bd2, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3b6b, 0x0040,
-	0x3b7a, 0x0078, 0x2946, 0x78e4, 0xa005, 0x00d0, 0x2f84, 0x3208,
-	0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2ffc,
-	0xa18c, 0x0300, 0x0078, 0x2ffe, 0xa18c, 0x0400, 0x0040, 0x3004,
-	0x0018, 0x2f84, 0x0078, 0x3006, 0x0028, 0x2f84, 0x2008, 0xa084,
-	0x0030, 0x00c0, 0x300e, 0x781b, 0x005b, 0x007c, 0x78ec, 0xa084,
-	0x0003, 0x0040, 0x300b, 0x2100, 0xa184, 0x0007, 0x0079, 0x3018,
-	0x3027, 0x302b, 0x3022, 0x3020, 0x4111, 0x4111, 0x3020, 0x410b,
-	0x1078, 0x28ec, 0x1078, 0x3eb6, 0x781b, 0x0061, 0x007c, 0x1078,
-	0x3eb6, 0x0078, 0x40ed, 0x1078, 0x3eb6, 0x781b, 0x00ef, 0x007c,
-	0x1078, 0x3eb6, 0x781b, 0x00bf, 0x007c, 0x2300, 0x0079, 0x3038,
-	0x303d, 0x303b, 0x303f, 0x1078, 0x28ec, 0x0078, 0x37bd, 0x681b,
-	0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x37bd,
-	0x78ec, 0xa084, 0x0003, 0x0040, 0x37bd, 0xa184, 0x0100, 0x0040,
-	0x3043, 0xa184, 0x0007, 0x0079, 0x3055, 0x305d, 0x302b, 0x2fa3,
-	0x40c9, 0x4111, 0x4111, 0x40c9, 0x410b, 0x1078, 0x40d5, 0x007c,
-	0xa282, 0x0005, 0x0050, 0x3066, 0x1078, 0x28ec, 0x2300, 0x0079,
-	0x3069, 0x306c, 0x328b, 0x3296, 0x2200, 0x0079, 0x306f, 0x3089,
-	0x3076, 0x3089, 0x3074, 0x326e, 0x1078, 0x28ec, 0x789b, 0x0018,
-	0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x3e9d, 0xa08a,
-	0x0004, 0x00c8, 0x3e9d, 0x0079, 0x3085, 0x3e9d, 0x3e9d, 0x3e9d,
-	0x3e47, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x309a,
-	0x0078, 0x3e9d, 0x7000, 0xa005, 0x00c0, 0x3090, 0x2011, 0x0004,
-	0x0078, 0x3998, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x3e9d,
-	0x0079, 0x30a2, 0x30b4, 0x30b2, 0x30c9, 0x30cd, 0x318f, 0x3e9d,
-	0x3e9d, 0x3191, 0x3e9d, 0x3e9d, 0x326a, 0x326a, 0x3e9d, 0x3e9d,
-	0x3e9d, 0x326c, 0x1078, 0x28ec, 0xd6e4, 0x0040, 0x30bf, 0x2001,
-	0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00ba, 0x007c, 0x6818,
-	0xd0fc, 0x0040, 0x30c7, 0x681b, 0x001d, 0x0078, 0x30b7, 0x0078,
-	0x40c9, 0x681b, 0x001d, 0x0078, 0x3ea7, 0x6920, 0x6922, 0xa684,
-	0x1800, 0x00c0, 0x3121, 0x6820, 0xd084, 0x00c0, 0x3127, 0x6818,
-	0xa086, 0x0008, 0x00c0, 0x30de, 0x681b, 0x0000, 0xd6d4, 0x0040,
-	0x318c, 0xd6bc, 0x0040, 0x311e, 0x7087, 0x0000, 0x6818, 0xa084,
-	0x003f, 0xa08a, 0x000d, 0x0050, 0x311e, 0xa08a, 0x000c, 0x7186,
-	0x2001, 0x000c, 0x800c, 0x718a, 0x789b, 0x0061, 0x78aa, 0x157e,
-	0x137e, 0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3110,
-	0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x310c,
-	0x20a1, 0x012b, 0x0078, 0x3112, 0x20a1, 0x022b, 0x0078, 0x3112,
-	0x20a1, 0x012b, 0x017f, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
-	0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x781b, 0x0064,
-	0x007c, 0xd6e4, 0x0040, 0x3127, 0x781b, 0x0076, 0x007c, 0xa684,
-	0x0060, 0x0040, 0x3189, 0xd6dc, 0x0040, 0x3189, 0xd6fc, 0x00c0,
-	0x3133, 0x0078, 0x314a, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8,
-	0x78d0, 0x801b, 0x00c8, 0x313d, 0x8000, 0xa084, 0x003f, 0xa108,
-	0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
-	0xa303, 0x68ae, 0xd6f4, 0x0040, 0x3150, 0xc6f4, 0x7e5a, 0x6eb6,
-	0x7000, 0xa086, 0x0003, 0x00c0, 0x315e, 0x007e, 0x1078, 0x4326,
-	0x1078, 0x45f7, 0x007f, 0x781b, 0x0073, 0x007c, 0xa006, 0x1078,
-	0x46e5, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040,
-	0x316d, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda,
-	0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0, 0x317d, 0xc6f5,
-	0x7e5a, 0x6eb6, 0x781b, 0x0073, 0x007c, 0x781b, 0x0073, 0x2200,
-	0xa115, 0x00c0, 0x3186, 0x1078, 0x45f7, 0x007c, 0x1078, 0x462d,
-	0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0064, 0x007c, 0x1078,
-	0x28ec, 0x0078, 0x31dd, 0x6920, 0xd1c4, 0x0040, 0x31a6, 0xc1c4,
-	0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004,
-	0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x31d1, 0xd1cc, 0x0040,
-	0x31d1, 0xc1cc, 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec,
-	0x6002, 0x6004, 0xc0a4, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c,
-	0x0040, 0x31d1, 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040,
-	0x31d1, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
-	0xd6d4, 0x00c0, 0x31ce, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075,
-	0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x31d8, 0x781b, 0x0064, 0x007c,
-	0x781b, 0x0076, 0x007c, 0x0078, 0x3ea2, 0x2019, 0x0000, 0x7990,
-	0xa18c, 0x0007, 0x00c0, 0x31eb, 0x6820, 0xa084, 0x0100, 0x0040,
-	0x31db, 0x2009, 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff,
-	0xa286, 0x0001, 0x00c0, 0x3207, 0x2300, 0x7ca8, 0xa400, 0x2018,
-	0xa102, 0x0040, 0x31ff, 0x0048, 0x31ff, 0x0078, 0x3201, 0x0078,
-	0x3193, 0x24a8, 0x7aa8, 0x00f0, 0x3201, 0x0078, 0x31ed, 0xa284,
-	0x00f0, 0xa086, 0x0020, 0x00c0, 0x325b, 0x8318, 0x8318, 0x2300,
-	0xa102, 0x0040, 0x3217, 0x0048, 0x3217, 0x0078, 0x3258, 0xa286,
-	0x0023, 0x0040, 0x31db, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
-	0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
-	0x0c7e, 0x7058, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4,
-	0x0040, 0x3238, 0x1078, 0x3fdd, 0x1078, 0x3df6, 0x0078, 0x3246,
-	0x0c7e, 0x7058, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c,
-	0x0040, 0x31d1, 0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040,
-	0x31d1, 0x789b, 0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4,
-	0x00c0, 0x3255, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c,
-	0x7aa8, 0x0078, 0x31ed, 0x8318, 0x2300, 0xa102, 0x0040, 0x3264,
-	0x0048, 0x3264, 0x0078, 0x31ed, 0xa284, 0x0080, 0x00c0, 0x3ea7,
-	0x0078, 0x3ea2, 0x0078, 0x3ea7, 0x0078, 0x3e9d, 0x7058, 0xa04d,
-	0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040,
-	0x327b, 0x1078, 0x28ec, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084,
-	0x00ff, 0xa08a, 0x0004, 0x00c8, 0x3e9d, 0x0079, 0x3287, 0x3e9d,
-	0x3c2c, 0x3e9d, 0x3d9e, 0xa282, 0x0000, 0x00c0, 0x3291, 0x1078,
-	0x28ec, 0x1078, 0x3eae, 0x781b, 0x0075, 0x007c, 0xa282, 0x0003,
-	0x00c0, 0x329c, 0x1078, 0x28ec, 0xd4fc, 0x00c0, 0x32bc, 0x7064,
-	0xa005, 0x0040, 0x32a5, 0x1078, 0x28ec, 0x6f14, 0x7776, 0xa7bc,
-	0x8f00, 0x1078, 0x3fe1, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738,
-	0xa784, 0x001f, 0x00c0, 0x32a9, 0x1078, 0x3eb2, 0x7067, 0x0002,
-	0x701f, 0x0009, 0x0078, 0x32be, 0x1078, 0x3ebe, 0x781b, 0x0075,
-	0x007c, 0xa282, 0x0004, 0x0050, 0x32c7, 0x1078, 0x28ec, 0x2300,
-	0x0079, 0x32ca, 0x32cd, 0x346b, 0x34ae, 0xa286, 0x0003, 0x0040,
-	0x3304, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1b4, 0x0078,
-	0x32fc, 0x0040, 0x32fc, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x32fc,
-	0xa282, 0x0002, 0x00c8, 0x32fc, 0x0d7e, 0x783b, 0x8300, 0x781b,
-	0x004c, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
-	0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f,
-	0x2001, 0x0000, 0x0078, 0x3308, 0x783b, 0x1300, 0x781b, 0x004a,
-	0x2001, 0x0000, 0x0078, 0x3308, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0,
-	0x704a, 0x68a0, 0xd0ec, 0x0040, 0x3310, 0x6008, 0xc08d, 0x600a,
-	0xa284, 0x000f, 0x0079, 0x3314, 0x344b, 0x3321, 0x331e, 0x35ae,
-	0x35f2, 0x2946, 0x331c, 0x331c, 0x1078, 0x28ec, 0x6008, 0xc0d4,
-	0x600a, 0xd6e4, 0x00c0, 0x3328, 0x1078, 0x4326, 0x0040, 0x3404,
-	0x7868, 0xa08c, 0x00ff, 0x0040, 0x3369, 0xa186, 0x0008, 0x00c0,
-	0x333e, 0x1078, 0x3bd2, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3b6b,
-	0x0040, 0x3369, 0x1078, 0x4326, 0x0078, 0x3353, 0xa186, 0x0028,
-	0x00c0, 0x3369, 0x1078, 0x4326, 0x6008, 0xc0a4, 0x600a, 0x6018,
-	0xa005, 0x0040, 0x3353, 0x8001, 0x601a, 0x0040, 0x3353, 0x8001,
-	0x0040, 0x3353, 0x601e, 0x6820, 0xd084, 0x0040, 0x2946, 0xc084,
-	0x6822, 0x705c, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004,
-	0x6802, 0xa005, 0x2d00, 0x00c0, 0x3366, 0x6002, 0x6006, 0x0078,
-	0x2946, 0x017e, 0x81ff, 0x00c0, 0x33b0, 0x7000, 0xa086, 0x0030,
-	0x0040, 0x33b0, 0x71d4, 0xd1b4, 0x00c0, 0x3397, 0x7060, 0xa005,
-	0x00c0, 0x33b0, 0x70a4, 0xa086, 0x0001, 0x0040, 0x33b0, 0x7003,
+	0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x41fe, 0x2c50, 0x1078,
+	0x4442, 0x6824, 0xa005, 0x0040, 0x2b5d, 0xa082, 0x0006, 0x0048,
+	0x2b5b, 0x0078, 0x2b5d, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f,
+	0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003,
+	0x0078, 0x2c92, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, 0x7154,
+	0x8108, 0xa12a, 0x0048, 0x2b75, 0x71c0, 0x2164, 0x6504, 0x85ff,
+	0x00c0, 0x2b8c, 0x7156, 0x8421, 0x00c0, 0x2b70, 0x70d4, 0xd08c,
+	0x0040, 0x2b88, 0x70d0, 0xa005, 0x00c0, 0x2b88, 0x70d3, 0x000a,
+	0x007c, 0x2200, 0x0078, 0x2b7a, 0x70d4, 0xc08c, 0x70d6, 0x70d3,
+	0x0000, 0x6034, 0xa005, 0x00c0, 0x2b89, 0x6708, 0xa784, 0x073f,
+	0x0040, 0x2bbb, 0xd7d4, 0x00c0, 0x2b89, 0xa784, 0x0021, 0x00c0,
+	0x2b89, 0xa784, 0x0002, 0x0040, 0x2bac, 0xa784, 0x0004, 0x0040,
+	0x2b89, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, 0x2b89,
+	0xa784, 0x0100, 0x0040, 0x2bbb, 0x6018, 0xa005, 0x00c0, 0x2b89,
+	0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684,
+	0x000e, 0x6318, 0x0040, 0x2bcc, 0x601c, 0xa302, 0x0048, 0x2bcf,
+	0x0040, 0x2bcf, 0x0078, 0x2b89, 0x83ff, 0x00c0, 0x2b89, 0x2d58,
+	0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2bd8, 0x7028, 0x6022, 0x603a,
+	0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041,
+	0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040,
+	0x2bec, 0xd684, 0x0040, 0x2bee, 0xa39c, 0xffbf, 0xd6a4, 0x0040,
+	0x2bf3, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2c3e, 0xc7a5,
+	0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c12,
+	0x70d4, 0xd0b4, 0x00c0, 0x2c12, 0x7000, 0xa082, 0x0002, 0x00c8,
+	0x2c12, 0x7830, 0xd0bc, 0x00c0, 0x2c12, 0x789b, 0x0010, 0x7baa,
+	0x0078, 0x2c8a, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005,
+	0x70ac, 0xa606, 0x00c0, 0x2c1d, 0x76a8, 0x76b2, 0x2c3a, 0x8738,
+	0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830,
+	0xd0bc, 0x0040, 0x2c35, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4,
+	0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040,
+	0x2c3d, 0x8421, 0x2200, 0x00c0, 0x2b6f, 0x007c, 0xd1dc, 0x0040,
+	0x3e00, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2c4b, 0x8528, 0xd68c,
+	0x00c0, 0x2c4b, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c,
+	0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2c6a, 0x6014,
+	0xa706, 0x00c0, 0x2c53, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2c4e,
+	0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0,
+	0x2b6f, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840,
+	0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c12,
+	0x70d4, 0xd0b4, 0x00c0, 0x2c12, 0x7000, 0xa082, 0x0002, 0x00c8,
+	0x2c12, 0x7830, 0xd0bc, 0x00c0, 0x2c12, 0x789b, 0x0010, 0x7baa,
+	0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a,
+	0x0078, 0x2c93, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018,
+	0x0040, 0x2caf, 0xa184, 0x0010, 0x0040, 0x2ca2, 0x1078, 0x4011,
+	0x00c0, 0x2cd4, 0xa184, 0x0008, 0x0040, 0x2caf, 0x69a0, 0xa184,
+	0x0600, 0x00c0, 0x2caf, 0x1078, 0x3ef5, 0x0078, 0x2cd4, 0x69a0,
+	0xa184, 0x1e00, 0x0040, 0x2cdf, 0xa184, 0x0800, 0x0040, 0x2cc8,
+	0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d,
+	0x0010, 0x6106, 0x0c7f, 0x1078, 0x4011, 0x00c0, 0x2cd4, 0x69a0,
+	0xa184, 0x0200, 0x0040, 0x2cd0, 0x1078, 0x3f54, 0x0078, 0x2cd4,
+	0xa184, 0x0400, 0x00c0, 0x2cab, 0x69a0, 0xa184, 0x1000, 0x0040,
+	0x2cdf, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x279f, 0x027f,
+	0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2cec, 0xa086, 0x0060,
+	0x00c0, 0x2cec, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b,
+	0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040,
+	0x2d07, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2d05,
+	0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa,
+	0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0,
+	0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898,
+	0x25a0, 0xa286, 0x0020, 0x00c0, 0x2d3f, 0x70d4, 0xc0b5, 0x70d6,
+	0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882,
+	0xa286, 0x0002, 0x0040, 0x2d75, 0x70a4, 0x8000, 0x70a6, 0x74b4,
+	0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2d37, 0x73a8, 0x73b6,
+	0xa286, 0x0010, 0x0040, 0x29c1, 0x0d7f, 0x0c7f, 0x007c, 0x7000,
+	0xa005, 0x00c0, 0x2d1d, 0xa286, 0x0002, 0x00c0, 0x2d8f, 0x1078,
+	0x4360, 0x00c0, 0x2d1d, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091,
+	0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
+	0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a,
+	0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f,
+	0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002,
+	0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040,
+	0x2d81, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000,
+	0x2090, 0x70a4, 0xa005, 0x00c0, 0x2d86, 0x007c, 0x8421, 0x0040,
+	0x2d85, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2b6f, 0xa286,
+	0x0010, 0x00c0, 0x2dc0, 0x1078, 0x4360, 0x00c0, 0x2d1d, 0x6814,
+	0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894,
+	0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
+	0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206,
+	0x00c0, 0x2db3, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042,
+	0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c,
+	0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882,
+	0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b,
+	0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605,
+	0x0040, 0x2deb, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0,
+	0x2de5, 0x2009, 0x0000, 0x0078, 0x2de7, 0x2009, 0x0001, 0xa284,
+	0x000f, 0x1079, 0x2def, 0xad80, 0x0009, 0x7046, 0x007c, 0x2df7,
+	0x48bd, 0x48bd, 0x48aa, 0x48bd, 0x2df7, 0x2df7, 0x2df7, 0x1078,
+	0x296b, 0x7808, 0xa084, 0xfffd, 0x780a, 0x1078, 0x295e, 0x0f7e,
+	0x2079, 0x4e00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2e21, 0x7064,
+	0xa086, 0x0001, 0x00c0, 0x2e0f, 0x7066, 0x0078, 0x2ef8, 0x7064,
+	0xa086, 0x0005, 0x00c0, 0x2e1f, 0x707c, 0x2068, 0x681b, 0x0004,
+	0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067,
+	0x0000, 0x70a7, 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078, 0x2aba,
+	0x157e, 0x2011, 0x0004, 0x7164, 0xa186, 0x0001, 0x0040, 0x2e41,
+	0xa186, 0x0007, 0x00c0, 0x2e38, 0x701f, 0x0005, 0x0078, 0x2e41,
+	0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078,
+	0x2e43, 0x7067, 0x0000, 0x2001, 0x4e0a, 0x2004, 0xa084, 0x00ff,
+	0xa086, 0x0018, 0x0040, 0x2e53, 0x7018, 0x7016, 0xa005, 0x00c0,
+	0x2e53, 0x70a7, 0x0001, 0x067e, 0x1078, 0x4586, 0x20a9, 0x0010,
+	0x2039, 0x0000, 0x1078, 0x40f8, 0xa7b8, 0x0100, 0x00f0, 0x2e5a,
+	0x067f, 0x7000, 0x0079, 0x2e64, 0x2e9e, 0x2e79, 0x2e79, 0x2e6e,
+	0x2e9e, 0x2e9e, 0x2e9e, 0x2e6c, 0x1078, 0x296b, 0x7060, 0xa005,
+	0x0040, 0x2e9e, 0xad06, 0x00c0, 0x2e79, 0x6800, 0x7062, 0x0078,
+	0x2e8b, 0x6820, 0xd084, 0x00c0, 0x2e87, 0x6f14, 0x1078, 0x41fe,
+	0x6008, 0xc0d4, 0x600a, 0x1078, 0x3dd0, 0x0078, 0x2e8b, 0x705c,
+	0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc,
+	0x0040, 0x2e93, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820,
+	0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x202c, 0xb284, 0x0400,
+	0x0040, 0x2ea6, 0x2021, 0x95d0, 0x0078, 0x2ea8, 0x2021, 0x94c0,
+	0x1078, 0x2efd, 0xb284, 0x0400, 0x0040, 0x2eb2, 0x2021, 0x4e98,
+	0x0078, 0x2eb4, 0x2021, 0x4e58, 0x1078, 0x2efd, 0x20a9, 0x0101,
+	0xb284, 0x0400, 0x0040, 0x2ec0, 0x2021, 0x94d0, 0x0078, 0x2ec2,
+	0x2021, 0x93c0, 0x1078, 0x2efd, 0x8420, 0x00f0, 0x2ec2, 0xb284,
+	0x0300, 0x0040, 0x2ecf, 0x2061, 0x53c0, 0x0078, 0x2ed1, 0x2061,
+	0x73c0, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040,
+	0x2eee, 0x6018, 0x017e, 0x007e, 0x2011, 0x4e02, 0x220c, 0xa102,
+	0x2012, 0x007f, 0x017f, 0xa102, 0x0050, 0x2eee, 0x6012, 0x00c0,
+	0x2eee, 0x2011, 0x4e04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000,
+	0xace0, 0x0010, 0x00f0, 0x2ed5, 0x8421, 0x00c0, 0x2ed3, 0x157f,
+	0x7003, 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005,
+	0x0040, 0x2f18, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000,
+	0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084,
+	0x00ff, 0xc09d, 0x6822, 0x1078, 0x202c, 0x007f, 0x0078, 0x2eff,
+	0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2f22,
+	0x1078, 0x296b, 0x2300, 0x0079, 0x2f25, 0x2f28, 0x2fb3, 0x2fd0,
+	0xa282, 0x0002, 0x0040, 0x2f2e, 0x1078, 0x296b, 0x7064, 0x7067,
+	0x0000, 0x7083, 0x0000, 0x0079, 0x2f35, 0x2f3d, 0x2f3d, 0x2f3f,
+	0x2f7f, 0x3e0c, 0x2f3d, 0x2f7f, 0x2f3d, 0x1078, 0x296b, 0x7774,
+	0x1078, 0x40f8, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x41fe, 0x6018,
+	0xa005, 0x0040, 0x2f76, 0xd7fc, 0x00c0, 0x2f52, 0x2021, 0x94c0,
+	0x0078, 0x2f54, 0x2021, 0x95d0, 0x2009, 0x0005, 0x2011, 0x0010,
+	0x1078, 0x2feb, 0x0040, 0x2f76, 0x157e, 0x20a9, 0x0101, 0xd7fc,
+	0x00c0, 0x2f66, 0x2021, 0x93c0, 0x0078, 0x2f68, 0x2021, 0x94d0,
+	0x047e, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2feb, 0x047f,
+	0x0040, 0x2f75, 0x8420, 0x00f0, 0x2f68, 0x157f, 0x8738, 0xa784,
+	0x001f, 0x00c0, 0x2f45, 0x0078, 0x29c5, 0x0078, 0x29c5, 0x7774,
+	0x1078, 0x41fe, 0x6018, 0xa005, 0x0040, 0x2fb1, 0xd7fc, 0x00c0,
+	0x2f8d, 0x2021, 0x94c0, 0x0078, 0x2f8f, 0x2021, 0x95d0, 0x2009,
+	0x0005, 0x2011, 0x0020, 0x1078, 0x2feb, 0x0040, 0x2fb1, 0x157e,
+	0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2fa1, 0x2021, 0x93c0, 0x0078,
+	0x2fa3, 0x2021, 0x94d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020,
+	0x1078, 0x2feb, 0x047f, 0x0040, 0x2fb0, 0x8420, 0x00f0, 0x2fa3,
+	0x157f, 0x0078, 0x29c5, 0x2200, 0x0079, 0x2fb6, 0x2fb9, 0x2fbb,
+	0x2fbb, 0x1078, 0x296b, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002,
+	0x0040, 0x2fc4, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2fc9,
+	0x691a, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x430d,
+	0x2200, 0x0079, 0x2fd3, 0x2fd8, 0x2fbb, 0x2fd6, 0x1078, 0x296b,
+	0x1078, 0x4586, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3d7e, 0x1078,
+	0x3ded, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3d6f, 0x0040,
+	0x3d7e, 0x0078, 0x29c5, 0x2404, 0xa005, 0x0040, 0x3024, 0x2068,
+	0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, 0x2ffa, 0x2d20, 0x007f,
+	0x0078, 0x2fec, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b,
+	0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff,
+	0xa205, 0x6822, 0x1078, 0x202c, 0x2021, 0x4e02, 0x241c, 0x8319,
+	0x2322, 0x6010, 0x8001, 0x6012, 0x00c0, 0x301b, 0x2021, 0x4e04,
+	0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078,
+	0x2adb, 0x1078, 0x3ded, 0x007c, 0xa085, 0x0001, 0x0078, 0x3023,
+	0x2300, 0x0079, 0x302b, 0x3030, 0x302e, 0x30b0, 0x1078, 0x296b,
+	0x78e4, 0xa005, 0x00d0, 0x3066, 0x3208, 0x007e, 0x2001, 0x4e04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x3041, 0xa18c, 0x0300, 0x0078,
+	0x3043, 0xa18c, 0x0400, 0x0040, 0x3049, 0x0018, 0x29c1, 0x0078,
+	0x304b, 0x0028, 0x29c1, 0x2008, 0xa084, 0x0030, 0x00c0, 0x3052,
+	0x0078, 0x3770, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3050, 0x2100,
+	0xa084, 0x0007, 0x0079, 0x305c, 0x3090, 0x309a, 0x3085, 0x3064,
+	0x4355, 0x4355, 0x3064, 0x30a5, 0x1078, 0x296b, 0x7000, 0xa086,
+	0x0004, 0x00c0, 0x3080, 0x7064, 0xa086, 0x0002, 0x00c0, 0x3076,
+	0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2f1c, 0x7064, 0xa086,
+	0x0006, 0x0040, 0x3070, 0x7064, 0xa086, 0x0004, 0x0040, 0x3070,
+	0x79e4, 0x2001, 0x0003, 0x0078, 0x33fa, 0x6818, 0xd0fc, 0x0040,
+	0x308b, 0x681b, 0x001d, 0x1078, 0x40c8, 0x781b, 0x0064, 0x007c,
+	0x6818, 0xd0fc, 0x0040, 0x3096, 0x681b, 0x001d, 0x1078, 0x40c8,
+	0x0078, 0x4331, 0x6818, 0xd0fc, 0x0040, 0x30a0, 0x681b, 0x001d,
+	0x1078, 0x40c8, 0x781b, 0x00f8, 0x007c, 0x6818, 0xd0fc, 0x0040,
+	0x30ab, 0x681b, 0x001d, 0x1078, 0x40c8, 0x781b, 0x00c8, 0x007c,
+	0xa584, 0x000f, 0x00c0, 0x30cf, 0x1078, 0x295e, 0x7000, 0x0079,
+	0x30b9, 0x29c5, 0x30c1, 0x30c3, 0x3d7e, 0x3d7e, 0x3d7e, 0x30c1,
+	0x30c1, 0x1078, 0x296b, 0x1078, 0x3ded, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x1078, 0x3d6f, 0x0040, 0x3d7e, 0x0078, 0x29c5, 0x78e4,
+	0xa005, 0x00d0, 0x3066, 0x3208, 0x007e, 0x2001, 0x4e04, 0x2004,
+	0xd0ec, 0x007f, 0x0040, 0x30e0, 0xa18c, 0x0300, 0x0078, 0x30e2,
+	0xa18c, 0x0400, 0x0040, 0x30e8, 0x0018, 0x3066, 0x0078, 0x30ea,
+	0x0028, 0x3066, 0x2008, 0xa084, 0x0030, 0x00c0, 0x30f2, 0x781b,
+	0x005b, 0x007c, 0x78ec, 0xa084, 0x0003, 0x0040, 0x30ef, 0x2100,
+	0xa184, 0x0007, 0x0079, 0x30fc, 0x310b, 0x310f, 0x3106, 0x3104,
+	0x4355, 0x4355, 0x3104, 0x434f, 0x1078, 0x296b, 0x1078, 0x40d0,
+	0x781b, 0x0064, 0x007c, 0x1078, 0x40d0, 0x0078, 0x4331, 0x1078,
+	0x40d0, 0x781b, 0x00f8, 0x007c, 0x1078, 0x40d0, 0x781b, 0x00c8,
+	0x007c, 0x2300, 0x0079, 0x311c, 0x3121, 0x311f, 0x3123, 0x1078,
+	0x296b, 0x0078, 0x395f, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4,
+	0xa184, 0x0030, 0x0040, 0x395f, 0x78ec, 0xa084, 0x0003, 0x0040,
+	0x395f, 0xa184, 0x0100, 0x0040, 0x3127, 0xa184, 0x0007, 0x0079,
+	0x3139, 0x3141, 0x310f, 0x3085, 0x430d, 0x4355, 0x4355, 0x430d,
+	0x434f, 0x1078, 0x4319, 0x007c, 0xa282, 0x0005, 0x0050, 0x314a,
+	0x1078, 0x296b, 0x2300, 0x0079, 0x314d, 0x3150, 0x3380, 0x338b,
+	0x2200, 0x0079, 0x3153, 0x316d, 0x315a, 0x316d, 0x3158, 0x3363,
+	0x1078, 0x296b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082,
+	0x0020, 0x0048, 0x40b7, 0xa08a, 0x0004, 0x00c8, 0x40b7, 0x0079,
+	0x3169, 0x40b7, 0x40b7, 0x40b7, 0x4061, 0x789b, 0x0018, 0x79a8,
+	0xa184, 0x0080, 0x0040, 0x317e, 0x0078, 0x40b7, 0x7000, 0xa005,
+	0x00c0, 0x3174, 0x2011, 0x0004, 0x0078, 0x3b4a, 0xa184, 0x00ff,
+	0xa08a, 0x0010, 0x00c8, 0x40b7, 0x0079, 0x3186, 0x3198, 0x3196,
+	0x31ad, 0x31b1, 0x3284, 0x40b7, 0x40b7, 0x3286, 0x40b7, 0x40b7,
+	0x335f, 0x335f, 0x40b7, 0x40b7, 0x40b7, 0x3361, 0x1078, 0x296b,
+	0xd6e4, 0x0040, 0x31a3, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a,
+	0x781b, 0x00c3, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x31ab, 0x681b,
+	0x001d, 0x0078, 0x319b, 0x0078, 0x430d, 0x681b, 0x001d, 0x0078,
+	0x40c1, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x3216, 0x6820,
+	0xd084, 0x00c0, 0x321c, 0x6818, 0xa086, 0x0008, 0x00c0, 0x31c2,
+	0x681b, 0x0000, 0xd6d4, 0x0040, 0x3281, 0xd6bc, 0x0040, 0x3202,
+	0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050,
+	0x3202, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
+	0x789b, 0x0061, 0x78aa, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208,
+	0xa18c, 0x0300, 0x0040, 0x31f4, 0x007e, 0x2001, 0x4e04, 0x2004,
+	0xd0ec, 0x007f, 0x0040, 0x31f0, 0x20a1, 0x012b, 0x0078, 0x31f6,
+	0x20a1, 0x022b, 0x0078, 0x31f6, 0x20a1, 0x012b, 0x017f, 0x789b,
+	0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f,
+	0x137f, 0x157f, 0x6038, 0xa005, 0x00c0, 0x3211, 0x681c, 0xa084,
+	0x000e, 0x0040, 0x40c1, 0x1078, 0x40d7, 0x782b, 0x3008, 0x0078,
+	0x3213, 0x8001, 0x603a, 0x781b, 0x0067, 0x007c, 0xd6e4, 0x0040,
+	0x321c, 0x781b, 0x0079, 0x007c, 0xa684, 0x0060, 0x0040, 0x327e,
+	0xd6dc, 0x0040, 0x327e, 0xd6fc, 0x00c0, 0x3228, 0x0078, 0x323f,
+	0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8,
+	0x3232, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98,
+	0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4,
+	0x0040, 0x3245, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003,
+	0x00c0, 0x3253, 0x007e, 0x1078, 0x4586, 0x1078, 0x48bd, 0x007f,
+	0x781b, 0x0076, 0x007c, 0xa006, 0x1078, 0x49c3, 0x6ab0, 0x69ac,
+	0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x3262, 0x2200, 0xa422,
+	0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde,
+	0x2300, 0xa405, 0x00c0, 0x3272, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b,
+	0x0076, 0x007c, 0x781b, 0x0076, 0x2200, 0xa115, 0x00c0, 0x327b,
+	0x1078, 0x48bd, 0x007c, 0x1078, 0x48f5, 0x007c, 0x781b, 0x0079,
+	0x007c, 0x781b, 0x0067, 0x007c, 0x1078, 0x296b, 0x0078, 0x32d2,
+	0x6920, 0xd1c4, 0x0040, 0x329b, 0xc1c4, 0x6922, 0x0c7e, 0x7058,
+	0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006,
+	0x0c7f, 0x0078, 0x32c6, 0xd1cc, 0x0040, 0x32c6, 0xc1cc, 0x6922,
+	0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004, 0xc0a4,
+	0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x32c6, 0x1078,
+	0x41fa, 0x1078, 0x3ef5, 0x88ff, 0x0040, 0x32c6, 0x789b, 0x0060,
+	0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x32c3,
+	0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58, 0xd6d4,
+	0x00c0, 0x32cd, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079, 0x007c,
+	0x0078, 0x40bc, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x00c0,
+	0x32e0, 0x6820, 0xa084, 0x0100, 0x0040, 0x32d0, 0x2009, 0x0008,
+	0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
+	0x32fc, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x32f4,
+	0x0048, 0x32f4, 0x0078, 0x32f6, 0x0078, 0x3288, 0x24a8, 0x7aa8,
+	0x00f0, 0x32f6, 0x0078, 0x32e2, 0xa284, 0x00f0, 0xa086, 0x0020,
+	0x00c0, 0x3350, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x330c,
+	0x0048, 0x330c, 0x0078, 0x334d, 0xa286, 0x0023, 0x0040, 0x32d0,
+	0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5,
+	0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058, 0x2060,
+	0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, 0x0040, 0x332d, 0x1078,
+	0x41fa, 0x1078, 0x4011, 0x0078, 0x333b, 0x0c7e, 0x7058, 0x2060,
+	0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x32c6, 0x1078,
+	0x41fa, 0x1078, 0x3ef5, 0x88ff, 0x0040, 0x32c6, 0x789b, 0x0060,
+	0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x334a, 0x781b,
+	0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7aa8, 0x0078, 0x32e2,
+	0x8318, 0x2300, 0xa102, 0x0040, 0x3359, 0x0048, 0x3359, 0x0078,
+	0x32e2, 0xa284, 0x0080, 0x00c0, 0x40c1, 0x0078, 0x40bc, 0x0078,
+	0x40c1, 0x0078, 0x40b7, 0x7058, 0xa04d, 0x789b, 0x0018, 0x78a8,
+	0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x3370, 0x1078, 0x296b,
+	0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004,
+	0x00c8, 0x40b7, 0x0079, 0x337c, 0x40b7, 0x3e46, 0x40b7, 0x3fb9,
+	0xa282, 0x0000, 0x00c0, 0x3386, 0x1078, 0x296b, 0x1078, 0x40c8,
+	0x781b, 0x0078, 0x007c, 0xa282, 0x0003, 0x00c0, 0x3391, 0x1078,
+	0x296b, 0xd4fc, 0x00c0, 0x33b1, 0x7064, 0xa005, 0x0040, 0x339a,
+	0x1078, 0x296b, 0x6f14, 0x7776, 0xa7bc, 0x8f00, 0x1078, 0x41fe,
+	0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x00c0,
+	0x339e, 0x1078, 0x40cc, 0x7067, 0x0002, 0x701f, 0x0009, 0x0078,
+	0x33b3, 0x1078, 0x40db, 0x781b, 0x0078, 0x007c, 0xa282, 0x0004,
+	0x0050, 0x33bc, 0x1078, 0x296b, 0x2300, 0x0079, 0x33bf, 0x33c2,
+	0x3582, 0x35c5, 0xa286, 0x0003, 0x0040, 0x33fa, 0x7200, 0x7cd8,
+	0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, 0x33f2, 0xd1b4, 0x0040,
+	0x33f2, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x33f2, 0xa282, 0x0002,
+	0x00c8, 0x33f2, 0x0d7e, 0x783b, 0x8300, 0x781b, 0x004c, 0x70bc,
+	0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+	0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x2001, 0x0000,
+	0x0078, 0x33fe, 0x783b, 0x1300, 0x781b, 0x004a, 0x2001, 0x0000,
+	0x0078, 0x33fe, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a, 0x68a0,
+	0xd0ec, 0x0040, 0x3406, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f,
+	0x0079, 0x340a, 0x3562, 0x3417, 0x3414, 0x36c8, 0x3754, 0x29c5,
+	0x3412, 0x3412, 0x1078, 0x296b, 0x6008, 0xc0d4, 0x600a, 0xd6e4,
+	0x0040, 0x341f, 0x7048, 0xa086, 0x0014, 0x00c0, 0x343f, 0x1078,
+	0x4586, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0040, 0x3428, 0x7048,
+	0xa086, 0x0014, 0x0040, 0x3439, 0x6818, 0xa086, 0x0008, 0x00c0,
+	0x351a, 0x7858, 0xd09c, 0x0040, 0x351a, 0x6820, 0xd0ac, 0x0040,
+	0x351a, 0x681b, 0x0014, 0x2009, 0x0002, 0x0078, 0x347e, 0x7868,
+	0xa08c, 0x00ff, 0x0040, 0x347e, 0xa186, 0x0008, 0x00c0, 0x3455,
+	0x6008, 0xc0a4, 0x600a, 0x1078, 0x3d6f, 0x0040, 0x347e, 0x1078,
+	0x3ded, 0x1078, 0x4586, 0x0078, 0x3466, 0xa186, 0x0028, 0x00c0,
+	0x347e, 0x6018, 0xa005, 0x0040, 0x3448, 0x8001, 0x0040, 0x3448,
+	0x8001, 0x0040, 0x3448, 0x601e, 0x0078, 0x3448, 0x6820, 0xd084,
+	0x0040, 0x29c5, 0xc084, 0x6822, 0x1078, 0x2acc, 0x705c, 0x0c7e,
+	0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00,
+	0x00c0, 0x347b, 0x6002, 0x6006, 0x0078, 0x29c5, 0x017e, 0x81ff,
+	0x00c0, 0x34c8, 0x7000, 0xa086, 0x0030, 0x0040, 0x34c8, 0x71d4,
+	0xd1bc, 0x00c0, 0x34c8, 0xd1b4, 0x00c0, 0x34af, 0x7060, 0xa005,
+	0x00c0, 0x34c8, 0x70a4, 0xa086, 0x0001, 0x0040, 0x34c8, 0x7003,
 	0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e, 0x1078,
-	0x296c, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f, 0x71d4,
-	0xd1b4, 0x00c0, 0x33b0, 0x7003, 0x0040, 0x0078, 0x33b0, 0x1078,
-	0x411c, 0x00c0, 0x33b0, 0x781b, 0x005b, 0x0d7e, 0x70bc, 0xa06d,
+	0x29ee, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f, 0x71d4,
+	0xd1b4, 0x00c0, 0x34c8, 0x7003, 0x0040, 0x0078, 0x34c8, 0x1078,
+	0x4360, 0x00c0, 0x34c8, 0x781b, 0x005b, 0x0d7e, 0x70bc, 0xa06d,
 	0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
 	0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x0d7f,
-	0x1078, 0x34e8, 0x017f, 0x81ff, 0x0040, 0x3403, 0xa684, 0xdf00,
-	0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0, 0x3404,
-	0x70d4, 0xd0b4, 0x0040, 0x33d1, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8,
-	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
-	0x0c7f, 0x6820, 0xd0dc, 0x00c0, 0x3404, 0x8717, 0xa294, 0x000f,
-	0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x33e3, 0xa290,
-	0x4ec0, 0x0078, 0x33e5, 0xa290, 0x4f40, 0xa290, 0x0000, 0x221c,
-	0xd3c4, 0x00c0, 0x33ed, 0x0078, 0x33f3, 0x8210, 0x2204, 0xa085,
-	0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x33fe, 0x68a0, 0xd0c4,
-	0x00c0, 0x33fe, 0x1078, 0x3562, 0x0078, 0x2946, 0x6008, 0xc08d,
-	0x600a, 0x0078, 0x3404, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040,
-	0x340b, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff,
-	0x0040, 0x3420, 0x2009, 0x4a02, 0x2104, 0x8001, 0x200a, 0x8421,
-	0x6412, 0x00c0, 0x3420, 0x2021, 0x4a04, 0x2404, 0xc0a5, 0x2022,
-	0x6018, 0xa005, 0x0040, 0x3428, 0x8001, 0x601a, 0x00c0, 0x342b,
-	0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x3437, 0x6800,
-	0xa005, 0x00c0, 0x3434, 0x6002, 0x6006, 0x0078, 0x343b, 0x705c,
-	0x2060, 0x6800, 0x6002, 0x2061, 0x4a00, 0x6887, 0x0103, 0x2d08,
-	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x344a, 0x2d02,
-	0x0078, 0x344b, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x345b,
-	0xa286, 0x0040, 0x00c0, 0x2946, 0x7003, 0x0002, 0x704c, 0x2068,
-	0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
-	0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
-	0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x3471, 0x1078,
-	0x28ec, 0x2200, 0x0079, 0x3474, 0x3478, 0x3489, 0x3496, 0x3489,
-	0xa586, 0x1300, 0x0040, 0x3489, 0xa586, 0x8300, 0x00c0, 0x346f,
-	0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x3493, 0x1078, 0x3eae,
-	0x781b, 0x0075, 0x007c, 0x781b, 0x0076, 0x007c, 0x7890, 0x8007,
-	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
-	0x00ff, 0xa186, 0x0003, 0x0040, 0x34ab, 0xa186, 0x0000, 0x0040,
-	0x34ab, 0x0078, 0x3e9d, 0x781b, 0x0076, 0x007c, 0x6820, 0xc095,
-	0x6822, 0x82ff, 0x00c0, 0x34b8, 0x1078, 0x3eae, 0x0078, 0x34bf,
-	0x8211, 0x0040, 0x34bd, 0x1078, 0x28ec, 0x1078, 0x3ebe, 0x781b,
-	0x0075, 0x007c, 0x1078, 0x4131, 0x7830, 0xa084, 0x00c0, 0x00c0,
-	0x34e5, 0x017e, 0x3208, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x34d7, 0xa18c, 0x0300, 0x0078, 0x34d9, 0xa18c,
-	0x0400, 0x017f, 0x0040, 0x34e0, 0x0018, 0x34e5, 0x0078, 0x34e2,
-	0x0028, 0x34e5, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
-	0xa684, 0x0060, 0x00c0, 0x34f2, 0x682f, 0x0000, 0x6833, 0x0000,
-	0x0078, 0x3561, 0xd6dc, 0x00c0, 0x350a, 0x68b4, 0xd0dc, 0x00c0,
-	0x350a, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0,
-	0x3507, 0x2200, 0xa105, 0x0040, 0x4326, 0x704b, 0x0015, 0x0078,
-	0x4326, 0x007c, 0xd6ac, 0x0040, 0x3530, 0xd6f4, 0x0040, 0x3516,
-	0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x4326, 0x68b4, 0xa084,
-	0x4000, 0xa635, 0xd6f4, 0x00c0, 0x3510, 0x7048, 0xa005, 0x00c0,
-	0x3523, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x352c, 0x68b4, 0xd0dc,
-	0x0040, 0x352c, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x4326,
-	0xd6f4, 0x0040, 0x3539, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
-	0x4326, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x3533,
-	0x7048, 0xa005, 0x00c0, 0x3546, 0x704b, 0x0015, 0x2408, 0x2510,
-	0x2700, 0x80fb, 0x00c8, 0x354d, 0x8000, 0xa084, 0x003f, 0xa108,
-	0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x355a,
-	0x0078, 0x4326, 0x7000, 0xa086, 0x0006, 0x0040, 0x3561, 0x0078,
-	0x4326, 0x007c, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x3568, 0xc08d,
-	0x600a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30,
-	0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837,
-	0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0079, 0x3580,
-	0x2946, 0x3592, 0x358a, 0x3588, 0x3588, 0x3588, 0x3588, 0x3588,
-	0x1078, 0x28ec, 0x6820, 0xd084, 0x00c0, 0x3592, 0x1078, 0x3bb5,
-	0x0078, 0x3598, 0x705c, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
-	0x3208, 0xa18c, 0x0300, 0x0040, 0x35a1, 0x2021, 0x4a58, 0x0078,
-	0x35a3, 0x2021, 0x4a98, 0x2404, 0xa005, 0x0040, 0x35aa, 0x2020,
-	0x0078, 0x35a3, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x3bbc,
-	0x1078, 0x3bd2, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b,
-	0x000e, 0x6f14, 0x6817, 0x0002, 0x3208, 0xa18c, 0x0300, 0x0040,
-	0x35c5, 0x2009, 0x0000, 0x0078, 0x35c7, 0x2009, 0x0001, 0x1078,
-	0x471a, 0xd6dc, 0x0040, 0x35cf, 0x691c, 0xc1ed, 0x691e, 0x6818,
-	0xd0fc, 0x0040, 0x35de, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x35dc,
-	0x681b, 0x001e, 0x0078, 0x35de, 0x681b, 0x0000, 0xb284, 0x0300,
-	0x00c0, 0x35e6, 0x2021, 0x4a98, 0x0078, 0x35e8, 0x2021, 0x4a58,
-	0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x202a,
-	0x0078, 0x2946, 0x7cd8, 0x7ddc, 0x7fd0, 0x1078, 0x34e8, 0x682b,
-	0x0000, 0x789b, 0x000e, 0x6f14, 0x1078, 0x4135, 0xa08c, 0x00ff,
-	0x6916, 0x6818, 0xd0fc, 0x0040, 0x3607, 0x7048, 0x681a, 0xa68c,
-	0xdf00, 0x691e, 0x7067, 0x0000, 0x0078, 0x2946, 0x7000, 0xa005,
-	0x00c0, 0x3614, 0x0078, 0x2946, 0xa006, 0x1078, 0x4326, 0x6817,
-	0x0000, 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000,
-	0x6820, 0xa084, 0x00ff, 0x6822, 0x7000, 0x0079, 0x3627, 0x2946,
-	0x3634, 0x3631, 0x3636, 0x3636, 0x3636, 0x362f, 0x362f, 0x1078,
-	0x28ec, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3bd2, 0x6008, 0xc0a4,
-	0x600a, 0x0078, 0x3b85, 0x2300, 0x0079, 0x363e, 0x3641, 0x3643,
-	0x369f, 0x1078, 0x28ec, 0xd6fc, 0x00c0, 0x3686, 0x7000, 0xa00d,
-	0x0079, 0x364a, 0x2946, 0x3654, 0x3654, 0x3678, 0x3654, 0x3683,
-	0x3652, 0x3652, 0x1078, 0x28ec, 0xa684, 0x0060, 0xa086, 0x0060,
-	0x00c0, 0x3675, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x681c, 0xc0ac,
-	0x681e, 0xa186, 0x0002, 0x0040, 0x3667, 0x1078, 0x4326, 0x1078,
-	0x45f7, 0x781b, 0x0076, 0x71d4, 0xd1b4, 0x00c0, 0x2942, 0x70a4,
-	0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6ec, 0x0040, 0x365c,
-	0x6818, 0xd0fc, 0x0040, 0x3683, 0x681b, 0x0015, 0xd6f4, 0x0040,
-	0x3683, 0x681b, 0x0007, 0x1078, 0x40d5, 0x007c, 0xc6fc, 0x7e5a,
-	0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x368f, 0x8000, 0xa084,
-	0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
-	0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0076, 0x007c, 0x1078,
-	0x28ec, 0x2300, 0x0079, 0x36a4, 0x36a9, 0x36c5, 0x3719, 0x1078,
-	0x28ec, 0x7000, 0x0079, 0x36ac, 0x36b4, 0x36b6, 0x36b6, 0x36b4,
-	0x36b4, 0x36b4, 0x36b4, 0x36b4, 0x1078, 0x28ec, 0x1078, 0x45f7,
-	0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x2942, 0x70a4,
-	0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6fc, 0x00c0, 0x3709,
-	0x7000, 0xa00d, 0x0079, 0x36cc, 0x2946, 0x36dc, 0x36d6, 0x3700,
-	0x36dc, 0x3706, 0x36d4, 0x36d4, 0x1078, 0x28ec, 0x6894, 0x78d6,
-	0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0xa086, 0x0060,
-	0x00c0, 0x36fd, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0xa186, 0x0002,
-	0x0040, 0x36ec, 0x1078, 0x4326, 0x1078, 0x45f7, 0x781b, 0x0076,
-	0x681c, 0xc0b4, 0x681e, 0x71d4, 0xd1b4, 0x00c0, 0x2942, 0x70a4,
-	0xa086, 0x0001, 0x00c0, 0x2989, 0x007c, 0xd6ec, 0x0040, 0x36e4,
-	0x6818, 0xd0fc, 0x0040, 0x3706, 0x681b, 0x0007, 0x781b, 0x00f0,
-	0x007c, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302,
-	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0076,
-	0x007c, 0xd6dc, 0x0040, 0x3722, 0x782b, 0x3009, 0x781b, 0x0076,
-	0x0078, 0x2942, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008,
-	0x00c0, 0x3735, 0xa484, 0x0200, 0x0040, 0x372f, 0xc6f5, 0xc6dd,
-	0x7e5a, 0x781b, 0x0076, 0x0078, 0x2942, 0x6820, 0xc095, 0x6822,
-	0x1078, 0x4062, 0xc6dd, 0x1078, 0x3eae, 0x781b, 0x0075, 0x0078,
-	0x2942, 0x2300, 0x0079, 0x3744, 0x3747, 0x3749, 0x374b, 0x1078,
-	0x28ec, 0x0078, 0x3ea7, 0xd6d4, 0x00c0, 0x3771, 0x79e4, 0xd1ac,
-	0x0040, 0x3759, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3759, 0x782b,
-	0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a,
-	0x79e4, 0xd1ac, 0x0040, 0x3769, 0x78ec, 0xa084, 0x0003, 0x00c0,
-	0x376d, 0x2001, 0x0014, 0x0078, 0x3304, 0xa184, 0x0007, 0x0079,
-	0x37a7, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff,
-	0x0040, 0x37a5, 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0,
-	0x3798, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x378b, 0x2009,
-	0xfff7, 0x0078, 0x3791, 0xa386, 0x0003, 0x00c0, 0x3798, 0x2009,
-	0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f,
-	0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b,
-	0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40c9, 0x2fae,
-	0x2fb8, 0x37b1, 0x37b7, 0x37af, 0x37af, 0x40c9, 0x40c9, 0x1078,
-	0x28ec, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x40cf, 0x6920,
-	0xa18c, 0xfcff, 0x6922, 0x0078, 0x40c9, 0x79e4, 0xa184, 0x0030,
-	0x0040, 0x37c7, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x37f1, 0x7000,
-	0xa086, 0x0004, 0x00c0, 0x37e1, 0x7064, 0xa086, 0x0002, 0x00c0,
-	0x37d7, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2e43, 0x7064,
-	0xa086, 0x0006, 0x0040, 0x37d1, 0x7064, 0xa086, 0x0004, 0x0040,
-	0x37d1, 0x7000, 0xa086, 0x0000, 0x0040, 0x2942, 0x6820, 0xd0ac,
-	0x00c0, 0x37ed, 0x6818, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0078,
-	0x3304, 0xa184, 0x0007, 0x0079, 0x37f5, 0x40c9, 0x40c9, 0x37fd,
-	0x40c9, 0x4111, 0x4111, 0x40c9, 0x40c9, 0xd6bc, 0x0040, 0x383f,
-	0x7184, 0x81ff, 0x0040, 0x383f, 0xa182, 0x000d, 0x00d0, 0x380c,
-	0x7087, 0x0000, 0x0078, 0x3811, 0xa182, 0x000c, 0x7086, 0x2009,
-	0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e, 0x7088,
-	0x8114, 0xa210, 0x728a, 0xa080, 0x000b, 0xad00, 0x2098, 0xb284,
-	0x0300, 0x0040, 0x3833, 0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x382f, 0x20a1, 0x012b, 0x0078, 0x3835, 0x20a1,
-	0x022b, 0x0078, 0x3835, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108,
-	0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078, 0x40cf, 0xd6d4,
-	0x00c0, 0x3893, 0x6820, 0xd084, 0x0040, 0x40cf, 0xa68c, 0x0060,
-	0xa684, 0x0060, 0x0040, 0x3851, 0xa086, 0x0060, 0x00c0, 0x3851,
-	0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000,
-	0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c,
-	0x0040, 0x3beb, 0xa18c, 0x00f8, 0x00c0, 0x3beb, 0x157e, 0x137e,
-	0x147e, 0x017e, 0x3208, 0xa18c, 0x0300, 0x0040, 0x387f, 0x007e,
-	0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x387b, 0x20a1,
-	0x012b, 0x0078, 0x3881, 0x20a1, 0x022b, 0x0078, 0x3881, 0x20a1,
-	0x012b, 0x017f, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b,
-	0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6814, 0xc0fc, 0x8007,
-	0x7882, 0x0078, 0x40cf, 0x6818, 0xd0fc, 0x0040, 0x3899, 0x681b,
-	0x0008, 0x6820, 0xc0ad, 0x6822, 0x1078, 0x3eb6, 0x781b, 0x00e1,
-	0x007c, 0x2300, 0x0079, 0x38a4, 0x38a9, 0x397b, 0x38a7, 0x1078,
-	0x28ec, 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x00c0, 0x38d1, 0x7200,
-	0xa286, 0x0003, 0x0040, 0x32d2, 0x71d4, 0xd1b4, 0x0078, 0x38d4,
-	0x0040, 0x38d4, 0x0d7e, 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc,
-	0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
-	0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078,
-	0x38d8, 0x7200, 0x0078, 0x38d8, 0x783b, 0x1800, 0x781b, 0x004a,
-	0xa284, 0x000f, 0x0079, 0x38dc, 0x3966, 0x391a, 0x38e6, 0x3300,
-	0x38e4, 0x3966, 0x38e4, 0x38e4, 0x1078, 0x28ec, 0x681c, 0xd0ec,
-	0x0040, 0x38ed, 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922,
-	0x6800, 0x6006, 0xa005, 0x00c0, 0x38f6, 0x6002, 0x6008, 0xc0d4,
-	0x600a, 0x681c, 0xa084, 0x000e, 0x00c0, 0x390a, 0xb284, 0x0300,
-	0x0040, 0x3906, 0x2009, 0x90c0, 0x0078, 0x390f, 0x2009, 0x91d0,
-	0x0078, 0x390f, 0x7030, 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104,
-	0x6802, 0x2d0a, 0x715e, 0xd6dc, 0x00c0, 0x391a, 0xc6fc, 0x6eb6,
-	0x0078, 0x3966, 0x6eb6, 0xa684, 0x0060, 0x0040, 0x3966, 0xd6dc,
-	0x00c0, 0x392d, 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898,
-	0x68aa, 0x1078, 0x4326, 0x0078, 0x3966, 0xd6ac, 0x0040, 0x3939,
-	0xa006, 0x1078, 0x4326, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0078,
-	0x3949, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8, 0x3940, 0x8000,
-	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa, 0x6aa6, 0x1078,
-	0x4326, 0xd6fc, 0x0040, 0x3966, 0xa684, 0x7fff, 0x68b6, 0x2510,
-	0x2408, 0xd6ac, 0x00c0, 0x395e, 0x2700, 0x801b, 0x00c8, 0x3959,
-	0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100,
-	0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086,
-	0x0030, 0x00c0, 0x2946, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
-	0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
-	0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0, 0x3988, 0x7003,
+	0x1078, 0x35ff, 0x017f, 0x81ff, 0x0040, 0x351a, 0xa684, 0xdf00,
+	0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0, 0x351b,
+	0x6818, 0xa086, 0x0014, 0x00c0, 0x34e4, 0x2008, 0xd6e4, 0x0040,
+	0x34e4, 0x7868, 0xa08c, 0x00ff, 0x1078, 0x2aba, 0x1078, 0x2adb,
+	0x6820, 0xd0dc, 0x00c0, 0x351b, 0x8717, 0xa294, 0x000f, 0x8213,
+	0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x34fa, 0xa290, 0x52c0,
+	0x0078, 0x34fc, 0xa290, 0x5340, 0xa290, 0x0000, 0x221c, 0xd3c4,
+	0x00c0, 0x3504, 0x0078, 0x350a, 0x8210, 0x2204, 0xa085, 0x0018,
+	0x2012, 0x8211, 0xd3d4, 0x0040, 0x3515, 0x68a0, 0xd0c4, 0x00c0,
+	0x3515, 0x1078, 0x3679, 0x0078, 0x29c5, 0x6008, 0xc08d, 0x600a,
+	0x0078, 0x351b, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3522,
+	0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0040,
+	0x3537, 0x2009, 0x4e02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412,
+	0x00c0, 0x3537, 0x2021, 0x4e04, 0x2404, 0xc0a5, 0x2022, 0x6018,
+	0xa005, 0x0040, 0x353f, 0x8001, 0x601a, 0x00c0, 0x3542, 0x6008,
+	0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x354e, 0x6800, 0xa005,
+	0x00c0, 0x354b, 0x6002, 0x6006, 0x0078, 0x3552, 0x705c, 0x2060,
+	0x6800, 0x6002, 0x2061, 0x4e00, 0x6887, 0x0103, 0x2d08, 0x206b,
+	0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x3561, 0x2d02, 0x0078,
+	0x3562, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x3572, 0xa286,
+	0x0040, 0x00c0, 0x29c5, 0x7003, 0x0002, 0x704c, 0x2068, 0x68c4,
+	0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042,
+	0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009,
+	0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x3588, 0x1078, 0x296b,
+	0x2200, 0x0079, 0x358b, 0x358f, 0x35a0, 0x35ad, 0x35a0, 0xa586,
+	0x1300, 0x0040, 0x35a0, 0xa586, 0x8300, 0x00c0, 0x3586, 0x7003,
 	0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x0078, 0x3ea7, 0x7047, 0x0000, 0xa282, 0x0006, 0x0050, 0x3992,
-	0x1078, 0x28ec, 0x2300, 0x0079, 0x3995, 0x3998, 0x39cf, 0x3a01,
-	0x2200, 0x0079, 0x399b, 0x39a1, 0x3ea7, 0x39a3, 0x39a1, 0x3a38,
-	0x3a9b, 0x1078, 0x28ec, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040,
-	0x39ad, 0x2001, 0x91e0, 0x0078, 0x39af, 0x2001, 0x9212, 0x2068,
-	0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0,
-	0x39b4, 0x157f, 0xb284, 0x0300, 0x0040, 0x39c2, 0x6817, 0x0000,
-	0x0078, 0x39c4, 0x6817, 0x8000, 0xad80, 0x0009, 0x7046, 0x68b7,
-	0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x3e9d, 0x7000,
-	0xa086, 0x0002, 0x00c0, 0x39e0, 0x1078, 0x3bd2, 0x0078, 0x39da,
-	0x1078, 0x4326, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0078, 0x39e5,
-	0x7000, 0xa086, 0x0003, 0x0040, 0x39d8, 0x7003, 0x0005, 0xb284,
-	0x0300, 0x0040, 0x39ef, 0x2001, 0x91e0, 0x0078, 0x39f1, 0x2001,
-	0x9212, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046, 0x2200, 0x0079,
-	0x39f9, 0x3ea7, 0x39ff, 0x39ff, 0x3a38, 0x39ff, 0x3ea7, 0x1078,
-	0x28ec, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3a12, 0x1078, 0x3bd2,
-	0x0078, 0x3a0c, 0x1078, 0x4326, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x0078, 0x3a17, 0x7000, 0xa086, 0x0003, 0x0040, 0x3a0a, 0x7003,
-	0x0005, 0xb284, 0x0300, 0x0040, 0x3a21, 0x2001, 0x91e0, 0x0078,
-	0x3a23, 0x2001, 0x9212, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
-	0x2200, 0x0079, 0x3a2b, 0x3a33, 0x3a31, 0x3a31, 0x3a33, 0x3a31,
-	0x3a33, 0x1078, 0x28ec, 0x1078, 0x3ebe, 0x781b, 0x0075, 0x007c,
-	0x7000, 0xa086, 0x0002, 0x00c0, 0x3a4a, 0x70d4, 0xc0b5, 0x70d6,
-	0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3a4f, 0x1078, 0x4326,
-	0x0078, 0x3a4f, 0x7000, 0xa086, 0x0003, 0x0040, 0x3a46, 0x7003,
-	0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484,
-	0x001f, 0xa215, 0x2069, 0x90c0, 0xb284, 0x0300, 0x00c0, 0x3a63,
-	0xc2fd, 0x2069, 0x91d0, 0x2d04, 0x2d08, 0x715e, 0xa06d, 0x0040,
-	0x3a70, 0x6814, 0xa206, 0x0040, 0x3a90, 0x6800, 0x0078, 0x3a64,
-	0x7003, 0x0005, 0xd2fc, 0x00c0, 0x3a79, 0x2001, 0x91e0, 0x0078,
-	0x3a7b, 0x2001, 0x9212, 0x2068, 0x704e, 0x157e, 0x20a9, 0x0032,
-	0x2003, 0x0000, 0x8000, 0x00f0, 0x3a80, 0x157f, 0xad80, 0x0009,
-	0x7046, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003,
-	0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x3b10, 0x1078,
-	0x3eb6, 0x0078, 0x3b10, 0x7200, 0xa286, 0x0002, 0x00c0, 0x3aad,
-	0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078,
-	0x3ab1, 0x1078, 0x4326, 0x0078, 0x3ab1, 0xa286, 0x0003, 0x0040,
-	0x3aa9, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018,
-	0x7ca8, 0xa484, 0x001f, 0xa215, 0xb284, 0x0300, 0x00c0, 0x3ac1,
-	0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x70cc, 0xa168, 0x2d04,
-	0x2d08, 0x715e, 0xa06d, 0x0040, 0x3ad4, 0x6814, 0xa206, 0x0040,
-	0x3afd, 0x6800, 0x0078, 0x3ac8, 0x7003, 0x0005, 0xb284, 0x0300,
-	0x0040, 0x3ade, 0x2001, 0x91e0, 0x0078, 0x3ae0, 0x2001, 0x9212,
-	0x2068, 0x704e, 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000,
-	0x00f0, 0x3ae5, 0x157f, 0xb284, 0x0300, 0x0040, 0x3af2, 0xc2fc,
-	0x0078, 0x3af3, 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7,
-	0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6820, 0xa084,
-	0x0c00, 0x0040, 0x3b10, 0xd0dc, 0x0040, 0x3b0a, 0x1078, 0x3eba,
-	0x0078, 0x3b10, 0x1078, 0x3eb6, 0x707f, 0x0000, 0x0078, 0x3b10,
-	0xa6ac, 0x0060, 0x0040, 0x3b4e, 0x6b98, 0x6c94, 0x69ac, 0x68b0,
-	0xa105, 0x00c0, 0x3b33, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4,
-	0xb7ff, 0xa586, 0x0060, 0x0040, 0x3b4e, 0xc6ed, 0x7e5a, 0x2009,
-	0x0076, 0xd69c, 0x0040, 0x3b2e, 0x2009, 0x0075, 0x791a, 0x1078,
-	0x45f7, 0x0078, 0x3b57, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400,
-	0xa305, 0x0040, 0x3b4e, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0,
-	0xc6f4, 0x7e5a, 0x2011, 0x0076, 0xd69c, 0x0040, 0x3b49, 0x2011,
-	0x0075, 0x7a1a, 0x1078, 0x462d, 0x0078, 0x3b57, 0x7e5a, 0x2009,
-	0x0076, 0xd69c, 0x0040, 0x3b56, 0x2009, 0x0075, 0x791a, 0x68c0,
-	0x705a, 0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, 0xd1b4, 0x00c0,
-	0x2942, 0x2300, 0xa405, 0x0040, 0x2942, 0x70a4, 0xa086, 0x0001,
-	0x00c0, 0x2989, 0x007c, 0x6020, 0xa005, 0x0040, 0x3b79, 0x8001,
-	0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x700f, 0x0100, 0x702c,
-	0x6026, 0x007c, 0xa006, 0x1078, 0x4326, 0x6817, 0x0000, 0x681b,
+	0x7000, 0xa086, 0x0005, 0x0040, 0x35aa, 0x1078, 0x40c8, 0x781b,
+	0x0078, 0x007c, 0x781b, 0x0079, 0x007c, 0x7890, 0x8007, 0x8001,
+	0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
+	0xa186, 0x0003, 0x0040, 0x35c2, 0xa186, 0x0000, 0x0040, 0x35c2,
+	0x0078, 0x40b7, 0x781b, 0x0079, 0x007c, 0x6820, 0xc095, 0x6822,
+	0x82ff, 0x00c0, 0x35cf, 0x1078, 0x40c8, 0x0078, 0x35d6, 0x8211,
+	0x0040, 0x35d4, 0x1078, 0x296b, 0x1078, 0x40db, 0x781b, 0x0078,
+	0x007c, 0x1078, 0x4383, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x35fc,
+	0x017e, 0x3208, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x35ee, 0xa18c, 0x0300, 0x0078, 0x35f0, 0xa18c, 0x0400,
+	0x017f, 0x0040, 0x35f7, 0x0018, 0x35fc, 0x0078, 0x35f9, 0x0028,
+	0x35fc, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684,
+	0x0060, 0x00c0, 0x3609, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
+	0x3678, 0xd6dc, 0x00c0, 0x3621, 0x68b4, 0xd0dc, 0x00c0, 0x3621,
+	0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0, 0x361e,
+	0x2200, 0xa105, 0x0040, 0x4586, 0x704b, 0x0015, 0x0078, 0x4586,
+	0x007c, 0xd6ac, 0x0040, 0x3647, 0xd6f4, 0x0040, 0x362d, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x0078, 0x4586, 0x68b4, 0xa084, 0x4000,
+	0xa635, 0xd6f4, 0x00c0, 0x3627, 0x7048, 0xa005, 0x00c0, 0x363a,
+	0x704b, 0x0015, 0xd6dc, 0x00c0, 0x3643, 0x68b4, 0xd0dc, 0x0040,
+	0x3643, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x4586, 0xd6f4,
+	0x0040, 0x3650, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x4586,
+	0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x364a, 0x7048,
+	0xa005, 0x00c0, 0x365d, 0x704b, 0x0015, 0x2408, 0x2510, 0x2700,
+	0x80fb, 0x00c8, 0x3664, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
+	0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x3671, 0x0078,
+	0x4586, 0x7000, 0xa086, 0x0006, 0x0040, 0x3678, 0x0078, 0x4586,
+	0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x3680, 0xc08d,
+	0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893,
+	0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833,
+	0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000,
+	0x0079, 0x369a, 0x29c5, 0x36ac, 0x36a4, 0x36a2, 0x36a2, 0x36a2,
+	0x36a2, 0x36a2, 0x1078, 0x296b, 0x6820, 0xd084, 0x00c0, 0x36ac,
+	0x1078, 0x3dd0, 0x0078, 0x36b2, 0x705c, 0x2c50, 0x2060, 0x6800,
+	0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, 0x0040, 0x36bb, 0x2021,
+	0x4e58, 0x0078, 0x36bd, 0x2021, 0x4e98, 0x2404, 0xa005, 0x0040,
+	0x36c4, 0x2020, 0x0078, 0x36bd, 0x2d22, 0x206b, 0x0000, 0x007c,
+	0x1078, 0x3dd7, 0x1078, 0x3ded, 0x6008, 0xc0cc, 0x600a, 0x682b,
+	0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916,
+	0x3208, 0xa18c, 0x0300, 0x0040, 0x36e1, 0x2009, 0x0000, 0x0078,
+	0x36e3, 0x2009, 0x0001, 0x1078, 0x49f8, 0xd6dc, 0x0040, 0x36eb,
+	0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0040, 0x36fa, 0x7868,
+	0xa08c, 0x00ff, 0x0040, 0x36f8, 0x681b, 0x001e, 0x0078, 0x36fa,
+	0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, 0x3702, 0x2021, 0x4e98,
+	0x0078, 0x3704, 0x2021, 0x4e58, 0x6800, 0x2022, 0x6a3c, 0x6940,
+	0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0040, 0x3744,
+	0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x0d7e, 0x0f7e,
+	0x157e, 0x147e, 0x2079, 0x4e00, 0x1078, 0x1dff, 0x147f, 0x157f,
+	0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, 0x027e, 0x2204, 0xa06d,
+	0x0040, 0x3734, 0x6814, 0xa706, 0x0040, 0x3731, 0x6800, 0x0078,
+	0x3727, 0x6820, 0xc0d5, 0x6822, 0x027f, 0x8210, 0x8109, 0x00c0,
+	0x3725, 0x0d7f, 0x7067, 0x0003, 0x707f, 0x0000, 0x7776, 0x7083,
+	0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, 0xa086, 0x0002, 0x00c0,
+	0x3750, 0x6817, 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e,
+	0x1078, 0x202c, 0x0078, 0x29c5, 0x7cd8, 0x7ddc, 0x7fd0, 0x1078,
+	0x35ff, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078, 0x4387,
+	0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3769, 0x7048,
+	0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078, 0x29c5,
+	0x7000, 0xa005, 0x00c0, 0x3776, 0x0078, 0x29c5, 0xa006, 0x1078,
+	0x4586, 0x6920, 0xd1ac, 0x00c0, 0x377f, 0x681b, 0x0014, 0xa68c,
+	0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822,
+	0x7000, 0x0079, 0x378b, 0x29c5, 0x3795, 0x3795, 0x3798, 0x3798,
+	0x3798, 0x3793, 0x3793, 0x1078, 0x296b, 0x6818, 0x0078, 0x33fa,
+	0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0078, 0x3d95, 0x2300,
+	0x0079, 0x37a2, 0x37a5, 0x37a7, 0x3817, 0x1078, 0x296b, 0xd6fc,
+	0x00c0, 0x37fe, 0x7000, 0xa00d, 0x0079, 0x37ae, 0x29c5, 0x37b8,
+	0x37b8, 0x37e8, 0x37b8, 0x37fb, 0x37b6, 0x37b6, 0x1078, 0x296b,
+	0xa684, 0x0060, 0x0040, 0x37e8, 0xa086, 0x0060, 0x00c0, 0x37e5,
+	0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac, 0x681e,
+	0xa186, 0x0002, 0x0040, 0x37d7, 0x1078, 0x4586, 0x69ac, 0x68b0,
+	0xa115, 0x0040, 0x37d7, 0x1078, 0x48f5, 0x0078, 0x37d9, 0x1078,
+	0x48bd, 0x781b, 0x0079, 0x71d4, 0xd1b4, 0x00c0, 0x29c1, 0x70a4,
+	0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0xd6ec, 0x0040, 0x37c2,
+	0x6818, 0xd0fc, 0x0040, 0x37fb, 0xd6f4, 0x00c0, 0x37f5, 0x681b,
+	0x0015, 0x781b, 0x0079, 0x0078, 0x29c1, 0x681b, 0x0007, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x1078, 0x4319, 0x007c, 0xc6fc, 0x7e5a,
+	0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x3807, 0x8000, 0xa084,
+	0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
+	0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0079, 0x007c, 0x1078,
+	0x296b, 0x2300, 0x0079, 0x381c, 0x3821, 0x3846, 0x38a6, 0x1078,
+	0x296b, 0x7000, 0x0079, 0x3824, 0x382c, 0x382e, 0x3837, 0x382c,
+	0x382c, 0x382c, 0x382c, 0x382c, 0x1078, 0x296b, 0x69ac, 0x68b0,
+	0xa115, 0x0040, 0x3837, 0x1078, 0x48f5, 0x0078, 0x3839, 0x1078,
+	0x48bd, 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x29c1,
+	0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0xd6fc, 0x00c0,
+	0x3896, 0x7000, 0xa00d, 0x0079, 0x384d, 0x29c5, 0x385d, 0x3857,
+	0x388d, 0x385d, 0x3893, 0x3855, 0x3855, 0x1078, 0x296b, 0x6894,
+	0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0040,
+	0x388d, 0xa086, 0x0060, 0x00c0, 0x388a, 0xa6b4, 0xbfbf, 0xc6ed,
+	0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0040, 0x3879, 0x1078, 0x4586,
+	0x69ac, 0x68b0, 0xa115, 0x0040, 0x3879, 0x1078, 0x48f5, 0x0078,
+	0x387b, 0x1078, 0x48bd, 0x781b, 0x0079, 0x681c, 0xc0b4, 0x681e,
+	0x71d4, 0xd1b4, 0x00c0, 0x29c1, 0x70a4, 0xa086, 0x0001, 0x00c0,
+	0x2a0b, 0x007c, 0xd6ec, 0x0040, 0x3867, 0x6818, 0xd0fc, 0x0040,
+	0x3893, 0x681b, 0x0007, 0x781b, 0x00f9, 0x007c, 0xc6fc, 0x7e5a,
+	0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
+	0xa303, 0x68ae, 0x79d2, 0x781b, 0x0079, 0x007c, 0xd6dc, 0x0040,
+	0x38af, 0x782b, 0x3009, 0x781b, 0x0079, 0x0078, 0x29c1, 0x7884,
+	0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x00c0, 0x38c2, 0xa484,
+	0x0200, 0x0040, 0x38bc, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0079,
+	0x0078, 0x29c1, 0x6820, 0xc095, 0x6822, 0x1078, 0x4292, 0xc6dd,
+	0x1078, 0x40c8, 0x781b, 0x0078, 0x0078, 0x29c1, 0x2300, 0x0079,
+	0x38d1, 0x38d4, 0x38d6, 0x38d8, 0x1078, 0x296b, 0x0078, 0x40c1,
+	0xd6d4, 0x00c0, 0x3913, 0x79e4, 0xd1ac, 0x0040, 0x38e6, 0x78ec,
+	0xa084, 0x0003, 0x0040, 0x38e6, 0x782b, 0x3009, 0x789b, 0x0060,
+	0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xd1ac, 0x0040,
+	0x38f6, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x390f, 0x2001, 0x4e04,
+	0x2004, 0xd0e4, 0x00c0, 0x390b, 0x6820, 0xd0c4, 0x0040, 0x390b,
+	0x0c7e, 0x7058, 0x2060, 0x6004, 0xc09d, 0x6006, 0x6008, 0xa084,
+	0x00ff, 0x600a, 0x0c7f, 0x2001, 0x0014, 0x0078, 0x33fa, 0xa184,
+	0x0007, 0x0079, 0x3949, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060,
+	0x79a8, 0x81ff, 0x0040, 0x3947, 0x789b, 0x0010, 0x7ba8, 0xa384,
+	0x0001, 0x00c0, 0x393a, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0,
+	0x392d, 0x2009, 0xfff7, 0x0078, 0x3933, 0xa386, 0x0003, 0x00c0,
+	0x393a, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104,
+	0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
+	0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078,
+	0x430d, 0x3090, 0x309a, 0x3953, 0x3959, 0x3951, 0x3951, 0x430d,
+	0x430d, 0x1078, 0x296b, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078,
+	0x4313, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x430d, 0x79e4,
+	0xa184, 0x0030, 0x0040, 0x3969, 0x78ec, 0xa084, 0x0003, 0x00c0,
+	0x399d, 0x7000, 0xa086, 0x0004, 0x00c0, 0x3983, 0x7064, 0xa086,
+	0x0002, 0x00c0, 0x3979, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078,
+	0x2f1c, 0x7064, 0xa086, 0x0006, 0x0040, 0x3973, 0x7064, 0xa086,
+	0x0004, 0x0040, 0x3973, 0x7000, 0xa086, 0x0000, 0x0040, 0x29c1,
+	0x6920, 0xa184, 0x0420, 0x0040, 0x3992, 0xc1d4, 0x6922, 0x6818,
+	0x0078, 0x33fa, 0x6818, 0xa08e, 0x0002, 0x0040, 0x399b, 0xc0fd,
+	0x681a, 0x2001, 0x0014, 0x0078, 0x33fa, 0xa184, 0x0007, 0x0079,
+	0x39a1, 0x430d, 0x430d, 0x39a9, 0x430d, 0x4355, 0x4355, 0x430d,
+	0x430d, 0xd6bc, 0x0040, 0x39eb, 0x7184, 0x81ff, 0x0040, 0x39eb,
+	0xa182, 0x000d, 0x00d0, 0x39b8, 0x7087, 0x0000, 0x0078, 0x39bd,
+	0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa,
+	0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a, 0xa080,
+	0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x39df, 0x007e,
+	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x39db, 0x20a1,
+	0x012b, 0x0078, 0x39e1, 0x20a1, 0x022b, 0x0078, 0x39e1, 0x20a1,
+	0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f, 0x137f,
+	0x157f, 0x0078, 0x4313, 0xd6d4, 0x00c0, 0x3a3f, 0x6820, 0xd084,
+	0x0040, 0x4313, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x39fd,
+	0xa086, 0x0060, 0x00c0, 0x39fd, 0xc1f5, 0xc194, 0x795a, 0x69b6,
+	0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd,
+	0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3e06, 0xa18c, 0x00f8,
+	0x00c0, 0x3e06, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208, 0xa18c,
+	0x0300, 0x0040, 0x3a2b, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x3a27, 0x20a1, 0x012b, 0x0078, 0x3a2d, 0x20a1,
+	0x022b, 0x0078, 0x3a2d, 0x20a1, 0x012b, 0x017f, 0x789b, 0x0000,
+	0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
+	0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x4313, 0x6818,
+	0xd0fc, 0x0040, 0x3a45, 0x681b, 0x0008, 0x6820, 0xc0ad, 0x6822,
+	0x1078, 0x40d0, 0x781b, 0x00ea, 0x007c, 0x2300, 0x0079, 0x3a50,
+	0x3a55, 0x3b2d, 0x3a53, 0x1078, 0x296b, 0x7cd8, 0x7ddc, 0x7fd0,
+	0x82ff, 0x00c0, 0x3a7e, 0x7200, 0xa286, 0x0003, 0x0040, 0x33c7,
+	0x71d4, 0xd1bc, 0x00c0, 0x3a81, 0xd1b4, 0x0040, 0x3a81, 0x0d7e,
+	0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4, 0xc0a5,
+	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
+	0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x3a85, 0x7200, 0x0078,
+	0x3a85, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f, 0x0079,
+	0x3a89, 0x3b18, 0x3ac7, 0x3a93, 0x33f6, 0x3a91, 0x3b18, 0x3a91,
+	0x3a91, 0x1078, 0x296b, 0x681c, 0xd0ec, 0x0040, 0x3a9a, 0x6008,
+	0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005,
+	0x00c0, 0x3aa3, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084,
+	0x000e, 0x00c0, 0x3ab7, 0xb284, 0x0300, 0x0040, 0x3ab3, 0x2009,
+	0x94c0, 0x0078, 0x3abc, 0x2009, 0x95d0, 0x0078, 0x3abc, 0x7030,
+	0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e,
+	0xd6dc, 0x00c0, 0x3ac7, 0xc6fc, 0x6eb6, 0x0078, 0x3b18, 0x6eb6,
+	0xa684, 0x0060, 0x00c0, 0x3ad1, 0xa684, 0x7fff, 0x68b6, 0x0078,
+	0x3b18, 0xd6dc, 0x00c0, 0x3adf, 0xa684, 0x7fff, 0x68b6, 0x6894,
+	0x68a6, 0x6898, 0x68aa, 0x1078, 0x4586, 0x0078, 0x3b18, 0xd6ac,
+	0x0040, 0x3aeb, 0xa006, 0x1078, 0x4586, 0x2408, 0x2510, 0x69aa,
+	0x6aa6, 0x0078, 0x3afb, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8,
+	0x3af2, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa,
+	0x6aa6, 0x1078, 0x4586, 0xd6fc, 0x0040, 0x3b18, 0xa684, 0x7fff,
+	0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3b10, 0x2700, 0x801b,
+	0x00c8, 0x3b0b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
+	0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
+	0x7000, 0xa086, 0x0030, 0x00c0, 0x29c5, 0x7003, 0x0002, 0x70bc,
+	0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00,
+	0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0,
+	0x3b3a, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x0078, 0x40c1, 0x7047, 0x0000, 0xa282, 0x0006,
+	0x0050, 0x3b44, 0x1078, 0x296b, 0x2300, 0x0079, 0x3b47, 0x3b4a,
+	0x3b5c, 0x3b68, 0x2200, 0x0079, 0x3b4d, 0x3b53, 0x40c1, 0x3b55,
+	0x3b53, 0x3ba2, 0x3bf7, 0x1078, 0x296b, 0x7a80, 0xa294, 0x0f00,
+	0x1078, 0x3c81, 0x0078, 0x40b7, 0x1078, 0x3b79, 0x0079, 0x3b60,
+	0x40c1, 0x3b66, 0x3b66, 0x3ba2, 0x3b66, 0x40c1, 0x1078, 0x296b,
+	0x1078, 0x3b79, 0x0079, 0x3b6c, 0x3b74, 0x3b72, 0x3b72, 0x3b74,
+	0x3b72, 0x3b74, 0x1078, 0x296b, 0x1078, 0x40db, 0x781b, 0x0078,
+	0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b8a, 0x1078, 0x3ded,
+	0x0078, 0x3b84, 0x1078, 0x4586, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x0078, 0x3b8f, 0x7000, 0xa086, 0x0003, 0x0040, 0x3b82, 0x7003,
+	0x0005, 0xb284, 0x0300, 0x0040, 0x3b99, 0x2001, 0x95e0, 0x0078,
+	0x3b9b, 0x2001, 0x9612, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
+	0x2200, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bb4, 0x70d4,
+	0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3bb9,
+	0x1078, 0x4586, 0x0078, 0x3bb9, 0x7000, 0xa086, 0x0003, 0x0040,
+	0x3bb0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018,
+	0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x94c0, 0xb284, 0x0300,
+	0x00c0, 0x3bcd, 0xc2fd, 0x2069, 0x95d0, 0x2d04, 0x2d08, 0x715e,
+	0xa06d, 0x0040, 0x3bda, 0x6814, 0xa206, 0x0040, 0x3bdc, 0x6800,
+	0x0078, 0x3bce, 0x1078, 0x3c81, 0x6eb4, 0x7e5a, 0x6920, 0xa184,
+	0x0c00, 0x0040, 0x3cab, 0x7064, 0xa086, 0x0006, 0x00c0, 0x3bee,
+	0x7074, 0xa206, 0x00c0, 0x3bee, 0x7066, 0x707e, 0x681b, 0x0005,
+	0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x40d0, 0x0078, 0x3cab, 0x7200,
+	0xa286, 0x0002, 0x00c0, 0x3c09, 0x70d4, 0xc0b5, 0x70d6, 0x2c00,
+	0x70ba, 0x2d00, 0x70be, 0x0078, 0x3c0d, 0x1078, 0x4586, 0x0078,
+	0x3c0d, 0xa286, 0x0003, 0x0040, 0x3c05, 0x7003, 0x0001, 0x7a80,
+	0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215,
+	0xb284, 0x0300, 0x00c0, 0x3c1d, 0xc2fd, 0x79a8, 0x79a8, 0xa18c,
+	0x00ff, 0x2118, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e, 0xa06d,
+	0x0040, 0x3c31, 0x6814, 0xa206, 0x0040, 0x3c5a, 0x6800, 0x0078,
+	0x3c25, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c3b, 0x2001,
+	0x95e0, 0x0078, 0x3c3d, 0x2001, 0x9612, 0x2068, 0x704e, 0x157e,
+	0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c42, 0x157f,
+	0xb284, 0x0300, 0x0040, 0x3c4f, 0xc2fc, 0x0078, 0x3c50, 0xc2fd,
+	0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
+	0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0040, 0x3cab,
+	0xd0dc, 0x0040, 0x3c76, 0x7064, 0xa086, 0x0004, 0x00c0, 0x3c72,
+	0x7074, 0xa206, 0x00c0, 0x3c72, 0x7078, 0xa306, 0x00c0, 0x3c72,
+	0x7066, 0x707e, 0x1078, 0x40d7, 0x0078, 0x3cab, 0x681b, 0x0005,
+	0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x40d0, 0x707f, 0x0000, 0x0078,
+	0x3cab, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c8b, 0x2001,
+	0x95e0, 0x0078, 0x3c8d, 0x2001, 0x9612, 0x2068, 0x704e, 0x157e,
+	0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c92, 0x157f,
+	0xb284, 0x0300, 0x0040, 0x3c9f, 0xc2fc, 0x0078, 0x3ca0, 0xc2fd,
+	0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
+	0x6827, 0x0003, 0x007c, 0xc6ec, 0xa6ac, 0x0060, 0x0040, 0x3cfd,
+	0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3cd8, 0x7bd2,
+	0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3d02, 0xd6f4,
+	0x00c0, 0x3cc3, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079,
+	0xd69c, 0x0040, 0x3cd0, 0x2009, 0x0078, 0x2019, 0x0000, 0x2320,
+	0x791a, 0xd6ec, 0x0040, 0x3d0d, 0x1078, 0x48bd, 0x0078, 0x3d0d,
+	0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, 0x3d04,
+	0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0, 0x3ce9,
+	0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0079, 0xd69c, 0x0040, 0x3cf5,
+	0x2011, 0x0078, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, 0x0040,
+	0x3d0d, 0x1078, 0x48f5, 0x0078, 0x3d0d, 0x2019, 0x0000, 0x2320,
+	0x0078, 0x3d04, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079, 0xd69c,
+	0x0040, 0x3d0c, 0x2009, 0x0078, 0x791a, 0x68c0, 0x705a, 0x2d00,
+	0x704e, 0x68c4, 0x2060, 0x71d4, 0x2001, 0x4e01, 0x2004, 0xd0c4,
+	0x00c0, 0x3d62, 0x70d8, 0xa02d, 0x0040, 0x3d3b, 0xd1bc, 0x0040,
+	0x3d55, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040, 0x3d2c,
+	0x78e0, 0xa504, 0x00c0, 0x3d62, 0x70da, 0xc1bc, 0x71d6, 0x0078,
+	0x3d62, 0x2031, 0x0001, 0x852c, 0x0048, 0x3d3a, 0x8633, 0x8210,
+	0x0078, 0x3d33, 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040, 0x3d48,
+	0x2011, 0x0008, 0x852f, 0x1078, 0x3d31, 0x8637, 0x0078, 0x3d4a,
+	0x1078, 0x3d31, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0040,
+	0x3d62, 0x72de, 0x76da, 0x0078, 0x3d62, 0x7a80, 0xa294, 0x0f00,
+	0x70dc, 0xa236, 0x0040, 0x3d52, 0x78e0, 0xa534, 0x0040, 0x3d52,
+	0xc1bd, 0x71d6, 0xd1b4, 0x00c0, 0x29c1, 0x2300, 0xa405, 0x0040,
+	0x29c1, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0x6020,
+	0xa005, 0x0040, 0x3d7d, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008,
+	0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x007c, 0xa006, 0x1078,
+	0x4586, 0x7000, 0xa086, 0x0002, 0x0040, 0x3d8b, 0x7064, 0xa086,
+	0x0005, 0x00c0, 0x3d95, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b,
 	0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
-	0x0079, 0x3b8a, 0x2946, 0x3b94, 0x3b94, 0x3bb1, 0x3b9c, 0x2946,
-	0x3b92, 0x3b92, 0x1078, 0x28ec, 0x1078, 0x3bbc, 0x1078, 0x3bb5,
-	0x1078, 0x202a, 0x0078, 0x2946, 0x7064, 0x7067, 0x0000, 0x7083,
-	0x0000, 0x0079, 0x3ba3, 0x3bad, 0x3bad, 0x3bab, 0x3bab, 0x3bab,
-	0x3bad, 0x3bab, 0x3bad, 0x0079, 0x2e5c, 0x7067, 0x0000, 0x0078,
-	0x2946, 0x681b, 0x0000, 0x0078, 0x35ae, 0x6800, 0xa005, 0x00c0,
-	0x3bba, 0x6002, 0x6006, 0x007c, 0x6410, 0x84ff, 0x0040, 0x3bce,
-	0x2009, 0x4a02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x00c0,
-	0x3bce, 0x2021, 0x4a04, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xc0a4,
-	0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x3bd8, 0x8001, 0x601a,
-	0x007c, 0x1078, 0x4131, 0x681b, 0x0018, 0x0078, 0x3c1a, 0x1078,
-	0x4131, 0x681b, 0x0019, 0x0078, 0x3c1a, 0x1078, 0x4131, 0x681b,
-	0x001a, 0x0078, 0x3c1a, 0x1078, 0x4131, 0x681b, 0x0003, 0x0078,
-	0x3c1a, 0x7774, 0x1078, 0x3fe1, 0x7178, 0xa18c, 0x00ff, 0x3210,
-	0xa294, 0x0300, 0x0040, 0x3c00, 0xa1e8, 0x8fc0, 0x0078, 0x3c02,
-	0xa1e8, 0x90d0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x3c0a,
-	0x0078, 0x2946, 0x6814, 0xc0fc, 0x7274, 0xc2fc, 0xa206, 0x0040,
-	0x3c14, 0x6800, 0x0078, 0x3c03, 0x6800, 0x200a, 0x681b, 0x0005,
-	0x707f, 0x0000, 0x1078, 0x3bbc, 0x6820, 0xd084, 0x00c0, 0x3c22,
-	0x1078, 0x3bb5, 0x1078, 0x3bd2, 0x681f, 0x0000, 0x6823, 0x0020,
-	0x1078, 0x202a, 0x0078, 0x2946, 0xa282, 0x0003, 0x00c0, 0x3e9d,
-	0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd,
-	0x6922, 0xd1c4, 0x0040, 0x3c86, 0xc1c4, 0x6922, 0xa6b4, 0x00ff,
-	0x0040, 0x3c73, 0xa682, 0x000c, 0x0048, 0x3c4a, 0x0040, 0x3c4a,
-	0x2031, 0x000c, 0x2500, 0xa086, 0x000a, 0x0040, 0x3c51, 0x852b,
-	0x852b, 0x1078, 0x3f73, 0x0040, 0x3c59, 0x1078, 0x3d55, 0x0078,
-	0x3c7c, 0x1078, 0x3f2e, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
-	0x6006, 0x1078, 0x3d8a, 0x0c7f, 0x6920, 0xc1c5, 0x6922, 0x7e58,
-	0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3c70, 0x781b, 0x0061, 0x007c,
-	0x781b, 0x0075, 0x007c, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
-	0x6006, 0x1078, 0x3d8a, 0x0c7f, 0x7e58, 0xd6d4, 0x00c0, 0x3c83,
-	0x781b, 0x0064, 0x007c, 0x781b, 0x0076, 0x007c, 0x0c7e, 0x7058,
-	0x2060, 0x6100, 0xd1e4, 0x0040, 0x3ccf, 0x6208, 0x8217, 0xa294,
-	0x00ff, 0xa282, 0x000c, 0x0048, 0x3c99, 0x0040, 0x3c99, 0x2011,
-	0x000c, 0x2600, 0xa202, 0x00c8, 0x3c9e, 0x2230, 0x6208, 0xa294,
-	0x00ff, 0x2001, 0x4a05, 0x2004, 0xd0e4, 0x00c0, 0x3cb3, 0x78ec,
-	0xd0e4, 0x0040, 0x3cb3, 0xa282, 0x000a, 0x00c8, 0x3cb9, 0x2011,
-	0x000a, 0x0078, 0x3cb9, 0xa282, 0x000c, 0x00c8, 0x3cb9, 0x2011,
-	0x000c, 0x2200, 0xa502, 0x00c8, 0x3cbe, 0x2228, 0x1078, 0x3f32,
-	0x2500, 0xa086, 0x000a, 0x0040, 0x3cc7, 0x852b, 0x852b, 0x1078,
-	0x3f73, 0x0040, 0x3ccf, 0x1078, 0x3d55, 0x0078, 0x3cd3, 0x1078,
-	0x3f2e, 0x1078, 0x3d8a, 0x7858, 0xc095, 0x785a, 0x0c7f, 0x781b,
-	0x0075, 0x007c, 0x0c7e, 0x2960, 0x6000, 0xd0e4, 0x00c0, 0x3cf1,
-	0x6010, 0xa084, 0x000f, 0x00c0, 0x3ceb, 0x6104, 0xa18c, 0xfff5,
-	0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
-	0x3d1c, 0x68a0, 0xd0cc, 0x00c0, 0x3ceb, 0x6208, 0xa294, 0x00ff,
-	0x2001, 0x4a05, 0x2004, 0xd0e4, 0x00c0, 0x3d0a, 0x78ec, 0xd0e4,
-	0x0040, 0x3d0a, 0xa282, 0x000a, 0x00c0, 0x3d0a, 0x2011, 0x000a,
-	0x0078, 0x3d10, 0xa282, 0x000c, 0x00c8, 0x3d10, 0x2011, 0x000c,
-	0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x3d1c,
-	0x0040, 0x3d1c, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003,
-	0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
-	0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3d38, 0xc0b4, 0x70d6, 0x70b8,
-	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
-	0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106,
-	0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3d46, 0x78ab, 0x0001,
+	0x0079, 0x3d9a, 0x29c5, 0x3daa, 0x3da4, 0x3dcc, 0x3db4, 0x29c5,
+	0x3da2, 0x3da2, 0x1078, 0x296b, 0x1078, 0x3dd7, 0x1078, 0x3dd0,
+	0x0078, 0x3db0, 0x1078, 0x3dd7, 0x705c, 0x2060, 0x6800, 0x6002,
+	0x1078, 0x202c, 0x0078, 0x29c5, 0x7064, 0x7067, 0x0000, 0x7083,
+	0x0000, 0x0079, 0x3dbb, 0x3dc8, 0x3dc8, 0x3dc3, 0x3dc3, 0x3dc3,
+	0x3dc8, 0x3dc3, 0x3dc8, 0x77d4, 0xc7dd, 0x77d6, 0x0079, 0x2f35,
+	0x7067, 0x0000, 0x0078, 0x29c5, 0x681b, 0x0000, 0x0078, 0x36c8,
+	0x6800, 0xa005, 0x00c0, 0x3dd5, 0x6002, 0x6006, 0x007c, 0x6410,
+	0x84ff, 0x0040, 0x3de9, 0x2009, 0x4e02, 0x2104, 0x8001, 0x200a,
+	0x8421, 0x6412, 0x00c0, 0x3de9, 0x2021, 0x4e04, 0x2404, 0xc0a5,
+	0x2022, 0x6008, 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040,
+	0x3df3, 0x8001, 0x601a, 0x007c, 0x1078, 0x4383, 0x681b, 0x0018,
+	0x0078, 0x3e34, 0x1078, 0x4383, 0x681b, 0x0019, 0x0078, 0x3e34,
+	0x1078, 0x4383, 0x681b, 0x001a, 0x0078, 0x3e34, 0x1078, 0x4383,
+	0x681b, 0x0003, 0x0078, 0x3e34, 0x7774, 0x1078, 0x41fe, 0x7178,
+	0xa18c, 0x00ff, 0x3210, 0xa294, 0x0300, 0x0040, 0x3e1b, 0xa1e8,
+	0x93c0, 0x0078, 0x3e1d, 0xa1e8, 0x94d0, 0x2d04, 0x2d08, 0x2068,
+	0xa005, 0x00c0, 0x3e26, 0x707e, 0x0078, 0x29c5, 0x6814, 0x7274,
+	0xa206, 0x0040, 0x3e2e, 0x6800, 0x0078, 0x3e1e, 0x6800, 0x200a,
+	0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3dd7, 0x6820, 0xd084,
+	0x00c0, 0x3e3c, 0x1078, 0x3dd0, 0x1078, 0x3ded, 0x681f, 0x0000,
+	0x6823, 0x0020, 0x1078, 0x202c, 0x0078, 0x29c5, 0xa282, 0x0003,
+	0x00c0, 0x40b7, 0x7da8, 0xa5ac, 0x00ff, 0x7e5a, 0x7ea8, 0xa6b4,
+	0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3ea1, 0xc1c4,
+	0x6922, 0xa6b4, 0x00ff, 0x0040, 0x3e8e, 0xa682, 0x000c, 0x0048,
+	0x3e65, 0x0040, 0x3e65, 0x2031, 0x000c, 0x2500, 0xa086, 0x000a,
+	0x0040, 0x3e6c, 0x852b, 0x852b, 0x1078, 0x4190, 0x0040, 0x3e74,
+	0x1078, 0x3f6f, 0x0078, 0x3e97, 0x1078, 0x414b, 0x0c7e, 0x2960,
+	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3fa5, 0x0c7f, 0x6920,
+	0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3e8b,
+	0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960,
+	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3fa5, 0x0c7f, 0x7e58,
+	0xd6d4, 0x00c0, 0x3e9e, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
+	0x007c, 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040, 0x3eea,
+	0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x3eb4,
+	0x0040, 0x3eb4, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8, 0x3eb9,
+	0x2230, 0x6208, 0xa294, 0x00ff, 0x2001, 0x4e05, 0x2004, 0xd0e4,
+	0x00c0, 0x3ece, 0x78ec, 0xd0e4, 0x0040, 0x3ece, 0xa282, 0x000a,
+	0x00c8, 0x3ed4, 0x2011, 0x000a, 0x0078, 0x3ed4, 0xa282, 0x000c,
+	0x00c8, 0x3ed4, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x3ed9,
+	0x2228, 0x1078, 0x414f, 0x2500, 0xa086, 0x000a, 0x0040, 0x3ee2,
+	0x852b, 0x852b, 0x1078, 0x4190, 0x0040, 0x3eea, 0x1078, 0x3f6f,
+	0x0078, 0x3eee, 0x1078, 0x414b, 0x1078, 0x3fa5, 0x7858, 0xc095,
+	0x785a, 0x0c7f, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960, 0x6000,
+	0xd0e4, 0x00c0, 0x3f0b, 0xa084, 0x0040, 0x00c0, 0x3f05, 0x6104,
+	0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019,
+	0x0000, 0x0078, 0x3f36, 0x68a0, 0xd0cc, 0x00c0, 0x3f05, 0x6208,
+	0xa294, 0x00ff, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x3f24,
+	0x78ec, 0xd0e4, 0x0040, 0x3f24, 0xa282, 0x000b, 0x00c8, 0x3f24,
+	0x2011, 0x000a, 0x0078, 0x3f2a, 0xa282, 0x000c, 0x00c8, 0x3f2a,
+	0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c,
+	0x0048, 0x3f36, 0x0040, 0x3f36, 0x2019, 0x000c, 0x78ab, 0x0001,
 	0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
-	0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7158, 0x2160,
-	0x2018, 0xa08c, 0x0020, 0x0040, 0x3d5e, 0xc0ac, 0x2008, 0xa084,
-	0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
-	0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xa39c, 0x0020, 0x0040,
-	0x3d73, 0xa085, 0x4000, 0xc0fc, 0xd0b4, 0x00c0, 0x3d78, 0xc0fd,
-	0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
-	0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
-	0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6018, 0x789a, 0x78a4,
-	0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
-	0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, 0x007c, 0xa282, 0x0002,
-	0x00c0, 0x3e9d, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0040,
-	0x3dd9, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8,
-	0x3e9d, 0x1078, 0x3e2a, 0x1078, 0x3d8a, 0xa980, 0x0001, 0x200c,
-	0x1078, 0x3fdd, 0x1078, 0x3cda, 0x88ff, 0x0040, 0x3dcf, 0x789b,
-	0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
-	0x3dcc, 0x781b, 0x0061, 0x007c, 0x781b, 0x0075, 0x007c, 0x7e58,
-	0xd6d4, 0x00c0, 0x3dd6, 0x781b, 0x0064, 0x007c, 0x781b, 0x0076,
-	0x007c, 0xa282, 0x0002, 0x00c8, 0x3de1, 0xa284, 0x0001, 0x0040,
-	0x3dea, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x00c0, 0x3dea,
-	0x2011, 0x0000, 0x1078, 0x3f0f, 0x1078, 0x3e2a, 0x1078, 0x3d8a,
-	0x7858, 0xc095, 0x785a, 0x781b, 0x0075, 0x007c, 0x0c7e, 0x027e,
-	0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0, 0x3e0b, 0x6014,
-	0xa084, 0x0040, 0x00c0, 0x3e09, 0xc1a4, 0x6106, 0xa006, 0x0078,
-	0x3e27, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
-	0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x3e23,
-	0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f,
-	0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff, 0x0040, 0x3e32,
-	0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
-	0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x3e3f, 0xc0fd, 0x78a6,
-	0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f, 0x007c, 0x007e,
-	0x7000, 0xa086, 0x0003, 0x0040, 0x3e50, 0x007f, 0x0078, 0x3e53,
-	0x007f, 0x0078, 0x3e9a, 0xd6ac, 0x0040, 0x3e9a, 0x7888, 0xa084,
-	0x0040, 0x0040, 0x3e9a, 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8,
-	0x3e62, 0x8000, 0xa005, 0x0040, 0x3e77, 0x831b, 0x00c8, 0x3e6b,
-	0x8001, 0x0040, 0x3e97, 0xd6f4, 0x0040, 0x3e77, 0x78b8, 0x801b,
-	0x00c8, 0x3e73, 0x8000, 0xa084, 0x003f, 0x00c0, 0x3e97, 0xc6f4,
-	0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x3e82,
-	0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x46e5,
-	0x781b, 0x0073, 0xb284, 0x0300, 0x0040, 0x3e92, 0x2001, 0x0000,
-	0x0078, 0x3e94, 0x2001, 0x0001, 0x1078, 0x4585, 0x007c, 0x781b,
-	0x0073, 0x007c, 0x781b, 0x0076, 0x007c, 0x1078, 0x3ec2, 0x781b,
-	0x0075, 0x007c, 0x1078, 0x3eae, 0x781b, 0x0075, 0x007c, 0x6827,
-	0x0002, 0x1078, 0x3eb6, 0x781b, 0x0075, 0x007c, 0x2001, 0x0005,
-	0x0078, 0x3ec4, 0x2001, 0x000c, 0x0078, 0x3ec4, 0x2001, 0x0006,
-	0x0078, 0x3ec4, 0x2001, 0x000d, 0x0078, 0x3ec4, 0x2001, 0x0009,
-	0x0078, 0x3ec4, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d,
-	0x7e5a, 0x70d4, 0xd0b4, 0x0040, 0x3eda, 0xc0b4, 0x70d6, 0x0c7e,
+	0x6820, 0xc0c5, 0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3f52, 0xc0b4,
+	0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
+	0x8001, 0x601a, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c,
+	0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3f60,
+	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
+	0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e,
+	0x7158, 0x2160, 0x2018, 0xa08c, 0x0020, 0x0040, 0x3f78, 0xc0ac,
+	0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae,
+	0x6612, 0x78a4, 0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4,
+	0xa39c, 0x0020, 0x0040, 0x3f8e, 0xa085, 0x4000, 0xc0fc, 0xd0b4,
+	0x00c0, 0x3f93, 0xc0fd, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f,
+	0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004,
+	0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060,
+	0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884,
+	0xa084, 0xfff0, 0x7886, 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f,
+	0x007c, 0xa282, 0x0002, 0x00c0, 0x40b7, 0x7aa8, 0x6920, 0xc1bd,
+	0x6922, 0xd1cc, 0x0040, 0x3ff4, 0xc1cc, 0x6922, 0xa294, 0x00ff,
+	0xa282, 0x0002, 0x00c8, 0x40b7, 0x1078, 0x4044, 0x1078, 0x3fa5,
+	0xa980, 0x0001, 0x200c, 0x1078, 0x41fa, 0x1078, 0x3ef5, 0x88ff,
+	0x0040, 0x3fea, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695,
+	0x7e5a, 0xd6d4, 0x00c0, 0x3fe7, 0x781b, 0x0064, 0x007c, 0x781b,
+	0x0078, 0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x3ff1, 0x781b, 0x0067,
+	0x007c, 0x781b, 0x0079, 0x007c, 0xa282, 0x0002, 0x00c8, 0x3ffc,
+	0xa284, 0x0001, 0x0040, 0x4005, 0x7158, 0xa188, 0x0000, 0x210c,
+	0xd1ec, 0x00c0, 0x4005, 0x2011, 0x0000, 0x1078, 0x412c, 0x1078,
+	0x4044, 0x1078, 0x3fa5, 0x7858, 0xc095, 0x785a, 0x781b, 0x0078,
+	0x007c, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec,
+	0x00c0, 0x4025, 0xa084, 0x0080, 0x00c0, 0x4023, 0xc1a4, 0x6106,
+	0xa006, 0x0078, 0x4041, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+	0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4,
+	0x0040, 0x403d, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200,
+	0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff,
+	0x0040, 0x404c, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a,
+	0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x4059,
+	0xc0fd, 0x78a6, 0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f,
+	0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x406a, 0x007f,
+	0x0078, 0x406d, 0x007f, 0x0078, 0x40b4, 0xd6ac, 0x0040, 0x40b4,
+	0x7888, 0xa084, 0x0040, 0x0040, 0x40b4, 0x7bb8, 0xa384, 0x003f,
+	0x831b, 0x00c8, 0x407c, 0x8000, 0xa005, 0x0040, 0x4091, 0x831b,
+	0x00c8, 0x4085, 0x8001, 0x0040, 0x40b1, 0xd6f4, 0x0040, 0x4091,
+	0x78b8, 0x801b, 0x00c8, 0x408d, 0x8000, 0xa084, 0x003f, 0x00c0,
+	0x40b1, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108,
+	0x00c8, 0x409c, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade,
+	0x1078, 0x49c3, 0x781b, 0x0076, 0xb284, 0x0300, 0x0040, 0x40ac,
+	0x2001, 0x0000, 0x0078, 0x40ae, 0x2001, 0x0001, 0x1078, 0x484b,
+	0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0079, 0x007c, 0x1078,
+	0x40df, 0x781b, 0x0078, 0x007c, 0x1078, 0x40c8, 0x781b, 0x0078,
+	0x007c, 0x6827, 0x0002, 0x1078, 0x40d0, 0x781b, 0x0078, 0x007c,
+	0x2001, 0x0005, 0x0078, 0x40e1, 0x2001, 0x000c, 0x0078, 0x40e1,
+	0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x40e1, 0x2001,
+	0x000d, 0x0078, 0x40e1, 0x2001, 0x0009, 0x0078, 0x40e1, 0x2001,
+	0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d4, 0xd0b4,
+	0x0040, 0x40f7, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c,
+	0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0x017e,
+	0xb28c, 0x0300, 0x0040, 0x4108, 0xa0e0, 0x52c0, 0x0078, 0x410a,
+	0xa0e0, 0x5340, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
+	0x000f, 0x0040, 0x411a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
+	0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
+	0x0040, 0x412a, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, 0x6004,
+	0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
+	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
+	0x0004, 0x70d4, 0xd0b4, 0x0040, 0x414a, 0xc0b4, 0x70d6, 0x0c7e,
 	0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
-	0x601a, 0x0c7f, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b,
-	0x873b, 0x8703, 0x017e, 0xb28c, 0x0300, 0x0040, 0x3eeb, 0xa0e0,
-	0x4ec0, 0x0078, 0x3eed, 0xa0e0, 0x4f40, 0x017f, 0xa7b8, 0x0020,
-	0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, 0x3efd, 0xa184, 0xfff0,
-	0x78a6, 0x6012, 0x6004, 0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a,
-	0x79a4, 0xa184, 0x0040, 0x0040, 0x3f0d, 0xa184, 0xffbf, 0xc0fd,
-	0x78a6, 0x6016, 0x6004, 0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b,
-	0x0010, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
-	0x789b, 0x0060, 0x78ab, 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x3f2d,
-	0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000,
-	0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003,
-	0x78ab, 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005,
-	0x70d4, 0xd0b4, 0x0040, 0x3f51, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8,
-	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
-	0x0c7f, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003,
-	0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x3fc6,
-	0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084,
-	0xfff0, 0xa106, 0x0040, 0x3f71, 0x8420, 0x2300, 0xa210, 0x00f0,
-	0x3f66, 0x157f, 0x007c, 0x157e, 0x2001, 0x4a05, 0x2004, 0xd0e4,
-	0x00c0, 0x3fa4, 0x2021, 0x3fd4, 0x20a9, 0x0009, 0x2011, 0x0028,
-	0xa582, 0x0019, 0x0040, 0x3fba, 0x0048, 0x3fba, 0x8420, 0x95a9,
-	0x2011, 0x0032, 0xa582, 0x0032, 0x0040, 0x3fba, 0x0048, 0x3fba,
-	0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0064, 0x2200, 0xa502,
-	0x0040, 0x3fba, 0x0048, 0x3fba, 0x8420, 0x2300, 0xa210, 0x00f0,
-	0x3f96, 0x157f, 0x0078, 0x3fb8, 0x2021, 0x3fc6, 0x2019, 0x0011,
-	0x20a9, 0x000e, 0x2011, 0x0032, 0x2200, 0xa502, 0x0040, 0x3fba,
-	0x0048, 0x3fba, 0x8420, 0x2300, 0xa210, 0x00f0, 0x3fac, 0x157f,
-	0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8, 0x3fc3, 0x7808,
-	0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x007c, 0x1209, 0x3002,
-	0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806,
-	0x7a06, 0x0c07, 0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05,
-	0x6a06, 0x6c06, 0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046,
-	0x007c, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003,
-	0x8003, 0x8003, 0xa105, 0xd7fc, 0x0040, 0x3ff2, 0xa0e0, 0x6fc0,
-	0x0078, 0x3ff4, 0xa0e0, 0x4fc0, 0x007c, 0x0e7e, 0x0f7e, 0xd084,
-	0x0040, 0x4002, 0x2079, 0x0100, 0x2009, 0x4a80, 0x2071, 0x4a80,
-	0x0078, 0x4014, 0x2009, 0x4a40, 0x007e, 0x2001, 0x4a04, 0x2004,
-	0xd0ec, 0x007f, 0x0040, 0x4010, 0x2079, 0x0100, 0x0078, 0x4014,
-	0x2079, 0x0200, 0x2071, 0x4a40, 0x2091, 0x8000, 0x2104, 0xa084,
-	0x000f, 0x0079, 0x401b, 0x405d, 0x4025, 0x4025, 0x4025, 0x4025,
-	0x4025, 0x4023, 0x4023, 0x1078, 0x28ec, 0x784b, 0x0004, 0x7848,
-	0xa084, 0x0004, 0x00c0, 0x4027, 0x784b, 0x0008, 0x7848, 0xa084,
-	0x0008, 0x00c0, 0x402e, 0x68b4, 0xc0f5, 0x68b6, 0x7858, 0xc0f5,
-	0x785a, 0x7830, 0xd0bc, 0x00c0, 0x405d, 0x007e, 0x2001, 0x4a04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x4049, 0xb284, 0x0300, 0x0078,
-	0x404b, 0xb284, 0x0400, 0x0040, 0x4051, 0x0018, 0x405d, 0x0078,
-	0x4053, 0x0028, 0x405d, 0x681c, 0xd0ac, 0x00c0, 0x405b, 0x1078,
-	0x40d5, 0x0078, 0x405d, 0x781b, 0x00f0, 0x2091, 0x8001, 0x0f7f,
-	0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4a01, 0x2004, 0xd0ac, 0x00c0,
-	0x40c7, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xb28c, 0x0300, 0x0040, 0x4078, 0xa0e0, 0x4ec0, 0x0078, 0x407a,
-	0xa0e0, 0x4f40, 0x6004, 0xa084, 0x000a, 0x00c0, 0x40c7, 0x6108,
-	0xa194, 0xff00, 0x0040, 0x40c7, 0xa18c, 0x00ff, 0x2001, 0x000a,
-	0xa106, 0x0040, 0x40a6, 0x2001, 0x000c, 0xa106, 0x0040, 0x40aa,
-	0x2001, 0x0012, 0xa106, 0x0040, 0x40ae, 0x2001, 0x0014, 0xa106,
-	0x0040, 0x40b2, 0x2001, 0x0019, 0xa106, 0x0040, 0x40b6, 0x2001,
-	0x0032, 0xa106, 0x0040, 0x40ba, 0x0078, 0x40be, 0x2009, 0x000c,
-	0x0078, 0x40c0, 0x2009, 0x0012, 0x0078, 0x40c0, 0x2009, 0x0014,
-	0x0078, 0x40c0, 0x2009, 0x0019, 0x0078, 0x40c0, 0x2009, 0x0020,
-	0x0078, 0x40c0, 0x2009, 0x003f, 0x0078, 0x40c0, 0x2011, 0x0000,
-	0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f,
-	0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0075, 0x007c, 0x781b,
-	0x0064, 0x007c, 0x781b, 0x0061, 0x007c, 0x2009, 0x4a19, 0x210c,
-	0xa186, 0x0000, 0x0040, 0x40e7, 0xa186, 0x0001, 0x0040, 0x40ea,
-	0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c, 0x781b,
-	0x00e7, 0x007c, 0x701f, 0x000a, 0x007c, 0x2009, 0x4a19, 0x210c,
-	0xa186, 0x0000, 0x0040, 0x4102, 0xa186, 0x0001, 0x0040, 0x40ff,
-	0x701f, 0x000b, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c, 0x701f,
-	0x000a, 0x007c, 0x781b, 0x00e6, 0x007c, 0x781b, 0x00f0, 0x007c,
-	0x781b, 0x00ef, 0x007c, 0x781b, 0x00c0, 0x007c, 0x781b, 0x00bf,
-	0x007c, 0x6818, 0xd0fc, 0x0040, 0x4117, 0x681b, 0x001d, 0x7067,
-	0x0001, 0x781b, 0x0047, 0x007c, 0x7830, 0xa084, 0x00c0, 0x00c0,
-	0x4130, 0x7808, 0xc08c, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
-	0x78ec, 0xa084, 0x0021, 0x0040, 0x4130, 0x7808, 0xc08d, 0x780a,
-	0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040,
-	0x00c0, 0x4135, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x0040, 0x4144,
-	0xb284, 0x0300, 0x0078, 0x4146, 0xb284, 0x0400, 0x0040, 0x414c,
-	0x0098, 0x4150, 0x0078, 0x414e, 0x00a8, 0x4150, 0x78ac, 0x007c,
-	0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
-	0x78ec, 0xa084, 0x0021, 0x0040, 0x4173, 0x007e, 0x2001, 0x4a04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x4169, 0xb284, 0x0300, 0x0078,
-	0x416b, 0xb284, 0x0400, 0x0040, 0x4171, 0x0098, 0x416d, 0x0078,
-	0x4173, 0x00a8, 0x4171, 0x78ac, 0x007e, 0x7808, 0xa085, 0x0002,
-	0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0, 0x360e, 0xa784,
-	0x0070, 0x0040, 0x418b, 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x2881,
-	0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040, 0x4198, 0x784b,
-	0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2946, 0x0078, 0x40c9,
-	0xa784, 0x0004, 0x0040, 0x41c7, 0x78b8, 0xa084, 0x4001, 0x0040,
-	0x41c7, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2946,
-	0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0, 0x41c7, 0x78c0,
-	0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f0, 0x007c, 0x784b,
-	0x0008, 0x6818, 0xd0fc, 0x0040, 0x41c4, 0x681b, 0x0015, 0xd6f4,
-	0x0040, 0x41c4, 0x681b, 0x0007, 0x1078, 0x40d5, 0x007c, 0x681b,
-	0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833,
-	0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2f84,
-	0x007e, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x41e4,
-	0xb284, 0x0300, 0x0078, 0x41e6, 0xb284, 0x0400, 0x0040, 0x41ec,
-	0x0018, 0x2942, 0x0078, 0x41ee, 0x0028, 0x2942, 0x0078, 0x3ea2,
-	0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc,
-	0x0040, 0x41fe, 0xa080, 0x4f40, 0x0078, 0x4200, 0xa080, 0x4ec0,
-	0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020, 0x0020, 0x0000,
+	0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b,
+	0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
+	0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x70d4, 0xd0b4, 0x0040,
+	0x416e, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x157e,
+	0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a,
+	0x79a4, 0xa18c, 0xfff0, 0x2021, 0x41e3, 0x2019, 0x0011, 0x20a9,
+	0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040,
+	0x418e, 0x8420, 0x2300, 0xa210, 0x00f0, 0x4183, 0x157f, 0x007c,
+	0x157e, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x41c1, 0x2021,
+	0x41f1, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, 0x0040,
+	0x41d7, 0x0048, 0x41d7, 0x8420, 0x95a9, 0x2011, 0x0032, 0xa582,
+	0x0032, 0x0040, 0x41d7, 0x0048, 0x41d7, 0x8420, 0x95a9, 0x2019,
+	0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x41d7, 0x0048,
+	0x41d7, 0x8420, 0x2300, 0xa210, 0x00f0, 0x41b3, 0x157f, 0x0078,
+	0x41d5, 0x2021, 0x41e3, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+	0x0032, 0x2200, 0xa502, 0x0040, 0x41d7, 0x0048, 0x41d7, 0x8420,
+	0x2300, 0xa210, 0x00f0, 0x41c9, 0x157f, 0xa006, 0x007c, 0x157f,
+	0xa582, 0x0064, 0x00c8, 0x41e0, 0x7808, 0xa085, 0x0070, 0x780a,
+	0x2404, 0xa005, 0x007c, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403,
+	0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07,
+	0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07,
+	0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00,
+	0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105,
+	0xd7fc, 0x0040, 0x420f, 0xa0e0, 0x73c0, 0x0078, 0x4211, 0xa0e0,
+	0x53c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x421f, 0x2079,
+	0x0100, 0x2009, 0x4e80, 0x2071, 0x4e80, 0x0078, 0x422f, 0x2009,
+	0x4e40, 0x2071, 0x4e40, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x0040,
+	0x422d, 0x2079, 0x0100, 0x0078, 0x422f, 0x2079, 0x0200, 0x2091,
+	0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x4236, 0x4240, 0x4240,
+	0x4240, 0x4240, 0x4240, 0x4240, 0x423e, 0x423e, 0x1078, 0x296b,
+	0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, 0x428f,
+	0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086,
+	0x1814, 0x00c0, 0x428f, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+	0x00c0, 0x4255, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
+	0x425c, 0x7830, 0xd0bc, 0x00c0, 0x428f, 0x007e, 0x2001, 0x4e04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x4271, 0xb284, 0x0300, 0x0078,
+	0x4273, 0xb284, 0x0400, 0x0040, 0x4279, 0x0018, 0x428f, 0x0078,
+	0x427b, 0x0028, 0x428f, 0x79e4, 0xa184, 0x0030, 0x0040, 0x428f,
+	0x78ec, 0xa084, 0x0003, 0x0040, 0x428f, 0x681c, 0xd0ac, 0x00c0,
+	0x428d, 0x1078, 0x4319, 0x0078, 0x428f, 0x781b, 0x00f9, 0x0f7f,
+	0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4e01, 0x2004, 0xd0ac, 0x00c0,
+	0x430b, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xb28c, 0x0300, 0x0040, 0x42a8, 0xa0e0, 0x52c0, 0x0078, 0x42aa,
+	0xa0e0, 0x5340, 0x6004, 0xa084, 0x000a, 0x00c0, 0x430b, 0x6108,
+	0xa194, 0xff00, 0x0040, 0x430b, 0xa18c, 0x00ff, 0x2001, 0x000a,
+	0xa106, 0x0040, 0x42d6, 0x2001, 0x000c, 0xa106, 0x0040, 0x42da,
+	0x2001, 0x0012, 0xa106, 0x0040, 0x42de, 0x2001, 0x0014, 0xa106,
+	0x0040, 0x42e2, 0x2001, 0x0019, 0xa106, 0x0040, 0x42e6, 0x2001,
+	0x0032, 0xa106, 0x0040, 0x42ea, 0x0078, 0x42ee, 0x2009, 0x000c,
+	0x0078, 0x42f0, 0x2009, 0x0012, 0x0078, 0x42f0, 0x2009, 0x0014,
+	0x0078, 0x42f0, 0x2009, 0x0019, 0x0078, 0x42f0, 0x2009, 0x0020,
+	0x0078, 0x42f0, 0x2009, 0x003f, 0x0078, 0x42f0, 0x2011, 0x0000,
+	0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x2061,
+	0x4e00, 0x6004, 0xd0bc, 0x0040, 0x430b, 0x6814, 0xd0fc, 0x00c0,
+	0x4306, 0x60ea, 0x2061, 0x4e40, 0x0078, 0x4309, 0x60ee, 0x2061,
+	0x4e80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0079, 0x007c,
+	0x781b, 0x0078, 0x007c, 0x781b, 0x0067, 0x007c, 0x781b, 0x0064,
+	0x007c, 0x2009, 0x4e19, 0x210c, 0xa186, 0x0000, 0x0040, 0x432b,
+	0xa186, 0x0001, 0x0040, 0x432e, 0x701f, 0x000b, 0x7067, 0x0001,
+	0x781b, 0x0047, 0x007c, 0x781b, 0x00f0, 0x007c, 0x701f, 0x000a,
+	0x007c, 0x2009, 0x4e19, 0x210c, 0xa186, 0x0000, 0x0040, 0x4346,
+	0xa186, 0x0001, 0x0040, 0x4343, 0x701f, 0x000b, 0x7067, 0x0001,
+	0x781b, 0x0047, 0x007c, 0x701f, 0x000a, 0x007c, 0x781b, 0x00ef,
+	0x007c, 0x781b, 0x00f9, 0x007c, 0x781b, 0x00f8, 0x007c, 0x781b,
+	0x00c9, 0x007c, 0x781b, 0x00c8, 0x007c, 0x6818, 0xd0fc, 0x0040,
+	0x435b, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c,
+	0x7830, 0xa084, 0x00c0, 0x00c0, 0x4382, 0x7808, 0xc08c, 0x780a,
+	0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x00c0,
+	0x437f, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x437d, 0x7804,
+	0xa084, 0xff1f, 0xa085, 0x00e0, 0x7806, 0xa006, 0x007c, 0x7808,
+	0xc08d, 0x780a, 0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830,
+	0xa084, 0x0040, 0x00c0, 0x4387, 0x2001, 0x4e04, 0x2004, 0xd0ec,
+	0x0040, 0x4396, 0xb284, 0x0300, 0x0078, 0x4398, 0xb284, 0x0400,
+	0x0040, 0x439e, 0x0098, 0x43a2, 0x0078, 0x43a0, 0x00a8, 0x43a2,
+	0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
+	0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x43c5, 0x007e,
+	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x43bb, 0xb284,
+	0x0300, 0x0078, 0x43bd, 0xb284, 0x0400, 0x0040, 0x43c3, 0x0098,
+	0x43bf, 0x0078, 0x43c5, 0x00a8, 0x43c3, 0x78ac, 0x007e, 0x7808,
+	0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0,
+	0x3770, 0xa784, 0x0070, 0x0040, 0x43dd, 0x0c7e, 0x2d60, 0x2f68,
+	0x1078, 0x28df, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
+	0x43ea, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3770,
+	0x0078, 0x430d, 0xa784, 0x0004, 0x0040, 0x4419, 0x78b8, 0xa084,
+	0x4001, 0x0040, 0x4419, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
+	0x0040, 0x3770, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
+	0x4419, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f9,
+	0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, 0x0040, 0x4416, 0x681b,
+	0x0015, 0xd6f4, 0x0040, 0x4416, 0x681b, 0x0007, 0x1078, 0x4319,
+	0x007c, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
+	0x0040, 0x3066, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x4436, 0xb284, 0x0300, 0x0078, 0x4438, 0xb284, 0x0400,
+	0x0040, 0x443e, 0x0018, 0x29c1, 0x0078, 0x4440, 0x0028, 0x29c1,
+	0x0078, 0x40bc, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xd3fc, 0x0040, 0x4450, 0xa080, 0x5340, 0x0078, 0x4452,
+	0xa080, 0x52c0, 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020,
+	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062,
-	0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014, 0x9906, 0x98f4,
-	0x0014, 0x0014, 0x0080, 0x00f1, 0x0100, 0x0402, 0x2008, 0xf880,
-	0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0x2500, 0x0013,
-	0x2500, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
-	0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0xa200,
-	0x3806, 0x8839, 0x20c4, 0x0864, 0xa850, 0x3008, 0x28c1, 0x9d0d,
-	0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856,
-	0x883a, 0xa808, 0x28e2, 0x9cc2, 0xa8f3, 0x0864, 0xa83e, 0x300c,
-	0xa801, 0x3008, 0x28e1, 0x9cc2, 0x2021, 0xa81b, 0xa205, 0x870c,
-	0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x63a4, 0x6c80, 0x0212, 0xa205,
-	0x883d, 0x9d25, 0x882b, 0x1814, 0x883b, 0x9d2b, 0x883b, 0x7027,
-	0x85f2, 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa812, 0x883e,
-	0xa810, 0x280c, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x9d25,
-	0x1814, 0x9d2b, 0x883b, 0x7023, 0x8576, 0x8677, 0xa802, 0x7861,
-	0x883e, 0x206b, 0x28c1, 0x9d0d, 0x2044, 0x2103, 0x20a2, 0x2081,
-	0xa8c9, 0xa207, 0x2901, 0xa80a, 0x0014, 0xa203, 0x8000, 0x85a4,
-	0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f,
-	0x7161, 0x0014, 0x0704, 0x3008, 0x9cc2, 0x0014, 0xa202, 0x8000,
-	0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844, 0x856e, 0x883f, 0x08e6,
-	0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2,
-	0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014,
-	0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0x3008, 0x8000, 0x284a,
-	0x1011, 0xa8fc, 0x3008, 0x9d25, 0x8000, 0xa000, 0x2802, 0x1011,
-	0xa8fd, 0x9d2b, 0xa887, 0x3008, 0x9d25, 0x283b, 0x1011, 0xa8fd,
-	0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014,
+	0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014,
+	0x9914, 0x98fd, 0x0014, 0x0014, 0x0080, 0x00ff, 0x0100, 0x0402,
+	0x2008, 0xf880, 0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014,
+	0x2500, 0x0013, 0x2500, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
+	0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
+	0x0010, 0xa200, 0x3806, 0x7102, 0x805f, 0x9481, 0x8839, 0x20c4,
+	0x0864, 0xa856, 0x3008, 0x28c1, 0x9d1b, 0xa201, 0x300c, 0x2847,
+	0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2,
+	0x9ccb, 0xa8f3, 0x0864, 0xa844, 0x300c, 0xa801, 0x3008, 0x28e1,
+	0x9ccb, 0x2021, 0xa81d, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0,
+	0x6fc0, 0x63a4, 0x6c80, 0x0212, 0xa205, 0x883d, 0x7942, 0x8020,
+	0xa4a1, 0x882b, 0x1814, 0x883b, 0x80df, 0x94a1, 0x7027, 0x85f2,
+	0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa816, 0x883e, 0xa814,
+	0x2001, 0xa812, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x7942,
+	0x8020, 0xa4a1, 0x1814, 0x80df, 0x94a1, 0x883b, 0x7023, 0x8576,
+	0x8677, 0xa802, 0x7861, 0x883e, 0x206b, 0x28c1, 0x9d1b, 0x2044,
+	0x2103, 0x20a2, 0x2081, 0xa8c3, 0xa207, 0x0904, 0xa20e, 0xa809,
+	0xa203, 0x8000, 0x85a4, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601,
+	0xa208, 0x856e, 0x866f, 0x7161, 0x0014, 0x0704, 0x3008, 0x9ccb,
+	0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844,
+	0x856e, 0x883f, 0x08e6, 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014,
+	0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014,
+	0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014,
+	0x3008, 0x8000, 0x284a, 0x1011, 0xa8fc, 0x3008, 0x9d33, 0x8000,
+	0xa000, 0x2802, 0x1011, 0xa8fd, 0x9d39, 0xa8bd, 0x3008, 0x9d33,
+	0x283b, 0x1011, 0xa8fd, 0xa209, 0x7102, 0x805f, 0x9481, 0x0017,
+	0x300c, 0xa209, 0x8000, 0x85a4, 0x1de2, 0xa209, 0xdac1, 0x0014,
 	0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0,
-	0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d17,
+	0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d25,
 	0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016,
 	0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021,
 	0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822,
 	0x0016, 0x7944, 0x8421, 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944,
 	0x8421, 0xa0df, 0x9532, 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4,
 	0xa084, 0x4600, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
-	0x00c0, 0x4342, 0x720c, 0x82ff, 0x0040, 0x433d, 0x8aff, 0x00c0,
-	0x4342, 0x7200, 0xd284, 0x00c0, 0x4342, 0x7003, 0x0008, 0x127f,
+	0x00c0, 0x45a2, 0x720c, 0x82ff, 0x0040, 0x459d, 0x8aff, 0x00c0,
+	0x45a2, 0x7200, 0xd284, 0x00c0, 0x45a2, 0x7003, 0x0008, 0x127f,
 	0x2000, 0x007c, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084,
-	0x0040, 0x4374, 0x2001, 0x4a05, 0x2004, 0xd0ec, 0x00c0, 0x43a5,
-	0xd0e4, 0x00c0, 0x435a, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003,
-	0x0040, 0x43a5, 0x0e7e, 0x2071, 0x0010, 0x2009, 0x0007, 0x7008,
-	0xa084, 0x3000, 0x00c0, 0x435d, 0x8109, 0x00c0, 0x435f, 0x0e7f,
-	0x2009, 0x0007, 0x7008, 0xa084, 0x3000, 0x00c0, 0x435a, 0x8109,
-	0x00c0, 0x436a, 0x0078, 0x43a5, 0x7108, 0xd1fc, 0x0040, 0x437f,
-	0x1078, 0x44ba, 0x8aff, 0x0040, 0x432c, 0x0078, 0x4374, 0x700c,
-	0xa08c, 0x03ff, 0x0040, 0x43aa, 0x7004, 0xd084, 0x0040, 0x439c,
-	0x7014, 0xa005, 0x00c0, 0x4398, 0x7010, 0x7310, 0xa306, 0x00c0,
-	0x438c, 0x2300, 0xa005, 0x0040, 0x439c, 0xa102, 0x00c8, 0x4374,
-	0x7007, 0x0010, 0x0078, 0x43a5, 0x8aff, 0x0040, 0x43aa, 0x1078,
-	0x46a3, 0x00c0, 0x439f, 0x0040, 0x4374, 0x1078, 0x4443, 0x127f,
-	0x2000, 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x43b9,
-	0x1078, 0x44ba, 0x0078, 0x43aa, 0x7003, 0x0008, 0x127f, 0x2000,
-	0x007c, 0xa205, 0x00c0, 0x43a5, 0x7003, 0x0008, 0x127f, 0x2000,
-	0x007c, 0x6428, 0x84ff, 0x0040, 0x43ed, 0x2c70, 0x7004, 0xa0bc,
-	0x000f, 0xa7b8, 0x43fd, 0x273c, 0x87fb, 0x00c0, 0x43db, 0x0048,
-	0x43d3, 0x1078, 0x28ec, 0x609c, 0xa075, 0x0040, 0x43ed, 0x0078,
-	0x43c6, 0x2039, 0x43f2, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c,
-	0xa529, 0x8421, 0x0040, 0x43ed, 0x8738, 0x2704, 0xa005, 0x00c0,
-	0x43dc, 0x709c, 0xa075, 0x00c0, 0x43c6, 0x007c, 0x0000, 0x0005,
-	0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
-	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x43f2, 0x43ef,
-	0x0000, 0x0000, 0x8000, 0x0000, 0x43f2, 0x0000, 0x43fa, 0x43f7,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x43fa, 0x0000, 0x43f5, 0x43f5,
-	0x0000, 0x0000, 0x8000, 0x0000, 0x43f5, 0x0000, 0x43fb, 0x43fb,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x43fb, 0x2079, 0x4a00, 0x2071,
-	0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x7810,
-	0xd0ec, 0x0040, 0x4431, 0x2009, 0x0001, 0x2071, 0x0020, 0x0078,
-	0x4435, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007,
-	0x0002, 0x7003, 0x0000, 0x8109, 0x0040, 0x4442, 0x2071, 0x0020,
-	0x0078, 0x4435, 0x007c, 0x7004, 0x8004, 0x00c8, 0x44a6, 0x7007,
-	0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106, 0x00c0, 0x444b,
-	0xa184, 0x01e0, 0x0040, 0x4456, 0x1078, 0x28ec, 0x7810, 0xd0ec,
-	0x0040, 0x4470, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x4474, 0xa184, 0x4000, 0x0040, 0x4478, 0xa382, 0x0003, 0x00c8,
-	0x4478, 0xa184, 0x0004, 0x0040, 0x444b, 0x8318, 0x0078, 0x444b,
-	0x7814, 0xd0ec, 0x00c0, 0x4478, 0xa184, 0x4000, 0x00c0, 0x444b,
-	0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x4486, 0xa386, 0x0008,
-	0x0040, 0x4491, 0xa386, 0x200c, 0x00c0, 0x444b, 0x7200, 0x8204,
-	0x0048, 0x4491, 0x730c, 0xa384, 0x03ff, 0x0040, 0x4491, 0x1078,
-	0x28ec, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x44a6, 0x7008,
-	0xa084, 0x01e0, 0x00c0, 0x44a6, 0x7310, 0x7014, 0xa305, 0x0040,
-	0x44a6, 0x710c, 0xa184, 0x03ff, 0x00c0, 0x4443, 0x7007, 0x0012,
-	0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x44aa, 0x7007, 0x0012,
-	0x7108, 0x8103, 0x0048, 0x44ae, 0x7003, 0x0008, 0x007c, 0x7108,
-	0x0078, 0x44ba, 0xa184, 0x01e0, 0x00c0, 0x44ee, 0x7108, 0xa184,
-	0x01e0, 0x00c0, 0x44ee, 0xa184, 0x0007, 0x0079, 0x44c7, 0x44d1,
-	0x44e1, 0x44cf, 0x44e1, 0x44cf, 0x4533, 0x44cf, 0x4531, 0x1078,
-	0x28ec, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0,
-	0x44dc, 0x2049, 0x0000, 0x007c, 0x1078, 0x46a3, 0x00c0, 0x44dc,
-	0x007c, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x0040,
-	0x44ed, 0x1078, 0x46a3, 0x00c0, 0x44e9, 0x007c, 0x7007, 0x0012,
-	0x7108, 0x00e0, 0x44f1, 0x2091, 0x6000, 0x00e0, 0x44f5, 0x2091,
-	0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0,
-	0x44fd, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x00c0, 0x4501, 0x7003,
-	0x0000, 0x7000, 0xa005, 0x00c0, 0x4515, 0x7004, 0xa005, 0x00c0,
-	0x4515, 0x700c, 0xa005, 0x0040, 0x4517, 0x0078, 0x44f9, 0x2049,
-	0x0000, 0xb284, 0x0100, 0x0040, 0x4521, 0x2001, 0x0000, 0x0078,
-	0x4523, 0x2001, 0x0001, 0x1078, 0x3ff5, 0x6818, 0xa084, 0x8000,
-	0x0040, 0x452c, 0x681b, 0x0002, 0x007c, 0x1078, 0x28ec, 0x1078,
-	0x28ec, 0x1078, 0x4570, 0x7210, 0x7114, 0x700c, 0xa09c, 0x03ff,
-	0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x4570, 0x2704,
-	0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b,
-	0x2400, 0xa305, 0x0040, 0x4556, 0x00c8, 0x4556, 0x8412, 0x8210,
-	0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x453d, 0x2b60, 0x8a07,
-	0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4562, 0xa7ba, 0x43f7,
-	0x0078, 0x4564, 0xa7ba, 0x43ef, 0x007f, 0xa73d, 0x2c00, 0x6886,
-	0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4443, 0x007c,
-	0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x4584, 0x6000, 0xa064,
-	0x00c0, 0x457b, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x440d,
-	0x203c, 0x87fb, 0x1040, 0x28ec, 0x007c, 0x127e, 0x0d7e, 0x70d4,
-	0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888,
-	0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e,
-	0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x45a2, 0xa0b8, 0x43f7,
-	0x0078, 0x45a4, 0xa0b8, 0x43ef, 0xb284, 0x0100, 0x0040, 0x45ab,
-	0x7e20, 0x0078, 0x45ac, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4,
-	0x0040, 0x45b3, 0xc685, 0x2400, 0xa305, 0x0040, 0x45dd, 0x2c58,
-	0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301,
-	0x701e, 0xa184, 0x0008, 0x0040, 0x45cd, 0x6010, 0xa081, 0x0000,
-	0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202,
-	0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001,
-	0x2b60, 0x1078, 0x46c6, 0x0078, 0x45df, 0x1078, 0x46a3, 0x00c0,
-	0x45dd, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084,
-	0x4600, 0x8004, 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094,
-	0x00c0, 0x45ee, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e,
-	0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x7e20,
-	0xb284, 0x0100, 0x00c0, 0x4605, 0x7e24, 0xa6b5, 0x000c, 0x681c,
-	0xd0ac, 0x00c0, 0x4610, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
-	0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x43fd,
-	0x273c, 0x87fb, 0x00c0, 0x4626, 0x0048, 0x4620, 0x1078, 0x28ec,
-	0x689c, 0xa065, 0x0040, 0x462a, 0x0078, 0x4613, 0x1078, 0x46a3,
-	0x00c0, 0x4626, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
-	0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x7e20, 0xb284,
-	0x0100, 0x00c0, 0x463c, 0x7e24, 0x0d7f, 0x037f, 0x047f, 0xa6b5,
-	0x000c, 0x681c, 0xd0b4, 0x0040, 0x464a, 0xc685, 0x7003, 0x0000,
-	0x7007, 0x0004, 0x2049, 0x462d, 0x6828, 0xa055, 0x0040, 0x46a0,
-	0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x43fd, 0x273c,
-	0x87fb, 0x00c0, 0x4666, 0x0048, 0x465f, 0x1078, 0x28ec, 0x709c,
-	0xa075, 0x2060, 0x0040, 0x46a0, 0x0078, 0x4652, 0x2704, 0xae68,
-	0x6808, 0xa422, 0x680c, 0xa31b, 0x0048, 0x467f, 0x8a51, 0x00c0,
-	0x4673, 0x1078, 0x28ec, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4667,
-	0x709c, 0xa075, 0x2060, 0x0040, 0x46a0, 0x0078, 0x4652, 0x8422,
-	0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c,
-	0x2300, 0xa11b, 0x00c8, 0x468e, 0x1078, 0x28ec, 0xb284, 0x0100,
-	0x0040, 0x469c, 0x2001, 0x4a04, 0x2004, 0xd0ec, 0x00c0, 0x469c,
-	0x2071, 0x0050, 0x0078, 0x469e, 0x2071, 0x0020, 0x0078, 0x45b3,
-	0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x0003, 0xa086, 0x0003,
-	0x00c0, 0x46ab, 0x007c, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804,
-	0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xa084, 0x0008,
-	0x0040, 0x46be, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004,
-	0xa084, 0x0010, 0xc085, 0x7006, 0x2079, 0x4a00, 0x8a51, 0x0040,
-	0x46e1, 0x8738, 0x2704, 0xa005, 0x00c0, 0x46dc, 0x609c, 0xa005,
-	0x0040, 0x46e2, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x43fd,
-	0x203c, 0x87fb, 0x1040, 0x28ec, 0x7008, 0xa084, 0x0003, 0xa086,
-	0x0003, 0x007c, 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e,
-	0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108,
-	0xa184, 0x0003, 0x00c0, 0x46fa, 0x6828, 0xa005, 0x0040, 0x470a,
-	0x0078, 0x4342, 0x7108, 0xd1fc, 0x0040, 0x4702, 0x1078, 0x44ba,
-	0x0078, 0x46ef, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4704,
-	0x1078, 0x44ba, 0x7008, 0xa086, 0x0008, 0x00c0, 0x46ef, 0x7000,
-	0xa005, 0x00c0, 0x46ef, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f,
-	0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e,
-	0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x471a,
-	0xad80, 0x0011, 0x20a0, 0xb284, 0x0100, 0x0040, 0x473d, 0x2001,
-	0x4a04, 0x2004, 0xd0ec, 0x0040, 0x4739, 0x2099, 0x0031, 0x0078,
-	0x473f, 0x2099, 0x0032, 0x0078, 0x473f, 0x2099, 0x0031, 0x700c,
-	0xa084, 0x03ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003,
-	0x0001, 0x0040, 0x474e, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084,
-	0x03ff, 0x0040, 0x475a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
-	0x00c0, 0x4755, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f,
-	0x137f, 0x147f, 0x127f, 0x2000, 0x007c, 0x2091, 0x8000, 0x2091,
-	0x6000, 0x78ac, 0xa005, 0x00c0, 0x477c, 0x7974, 0x70d0, 0xa106,
-	0x00c0, 0x477c, 0x781c, 0xa005, 0x0040, 0x477c, 0x781f, 0x0000,
-	0x0068, 0x477c, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0,
-	0x4804, 0x7834, 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x47fd, 0x2061,
-	0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x4796,
-	0x8001, 0x68d2, 0x00c0, 0x4796, 0x1078, 0x4998, 0x6800, 0xa084,
-	0x000f, 0x0040, 0x47ab, 0xa086, 0x0001, 0x0040, 0x47ab, 0x6844,
-	0xa00d, 0x0040, 0x47ab, 0x2104, 0xa005, 0x0040, 0x47ab, 0x8001,
-	0x200a, 0x0040, 0x4909, 0x6814, 0xa005, 0x0040, 0x47d0, 0x8001,
-	0x6816, 0x00c0, 0x47d0, 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0,
-	0x47c5, 0x7810, 0xd0ec, 0x0040, 0x47c1, 0x2079, 0x0100, 0x0078,
-	0x47c7, 0x2079, 0x0200, 0x0078, 0x47c7, 0x2079, 0x0100, 0x1078,
-	0x4131, 0x0f7f, 0x6864, 0xa005, 0x0040, 0x47d0, 0x1078, 0x25de,
-	0x6880, 0xa005, 0x0040, 0x47dd, 0x8001, 0x6882, 0x00c0, 0x47dd,
-	0x6867, 0x0000, 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040,
-	0x47fa, 0xc0fc, 0x68d6, 0x20a9, 0x0200, 0x603c, 0xa005, 0x0040,
-	0x47f6, 0x8001, 0x603e, 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x47f6,
-	0x6010, 0xa005, 0x0040, 0x47f6, 0x1078, 0x25de, 0xace0, 0x0010,
-	0x00f0, 0x47e5, 0xd7fc, 0x0040, 0x4804, 0x2061, 0x4fc0, 0x2069,
-	0x4a40, 0xc7fc, 0x0078, 0x478c, 0x1078, 0x4840, 0x7838, 0x8001,
-	0x783a, 0x00c0, 0x4826, 0x783c, 0x783a, 0x2061, 0x4fc0, 0x2069,
-	0x4a40, 0xc7fc, 0x680c, 0xa005, 0x0040, 0x4818, 0x1078, 0x487f,
-	0xd7fc, 0x00c0, 0x4826, 0x7810, 0xd0ec, 0x00c0, 0x4826, 0x2061,
-	0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x0078, 0x4812, 0x7814, 0xd0e4,
-	0x00c0, 0x482a, 0x7810, 0xd0cc, 0x0040, 0x483d, 0xd0ac, 0x00c0,
-	0x4836, 0xd0a4, 0x0040, 0x483d, 0xc0ad, 0x7812, 0x2091, 0x8001,
-	0x0068, 0x483c, 0x1078, 0x2368, 0x007c, 0x2091, 0x8001, 0x007c,
-	0x7840, 0x8001, 0x7842, 0x00c0, 0x487e, 0x7844, 0x7842, 0x2091,
-	0x8000, 0x2061, 0x4fc0, 0x2069, 0x4a40, 0xc7fc, 0x6810, 0xa005,
-	0x00c0, 0x4854, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0040,
-	0x485d, 0xa080, 0x90d0, 0x0078, 0x485f, 0xa080, 0x8fc0, 0x2040,
-	0x2004, 0xa065, 0x0040, 0x4870, 0x6024, 0xa005, 0x0040, 0x486c,
-	0x8001, 0x6026, 0x0040, 0x48ad, 0x6000, 0x2c40, 0x0078, 0x4861,
-	0xd7fc, 0x00c0, 0x487e, 0x7810, 0xd0ec, 0x00c0, 0x487e, 0x2061,
-	0x6fc0, 0x2069, 0x4a80, 0xc7fd, 0x0078, 0x484e, 0x007c, 0x2009,
-	0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0040, 0x4899, 0x6024,
-	0xa005, 0x0040, 0x488f, 0x8001, 0x6026, 0x0078, 0x4897, 0x6008,
-	0xc09c, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, 0x4899, 0xa18d,
-	0x0100, 0xace0, 0x0010, 0x00f0, 0x4883, 0xa184, 0x0001, 0x0040,
-	0x48a8, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x25de, 0x0078, 0x48a9,
-	0x690e, 0x007c, 0x00c0, 0x48a9, 0x786c, 0x6800, 0xa005, 0x0040,
-	0x48b5, 0x684c, 0xac06, 0x0040, 0x4909, 0x6864, 0xa005, 0x0040,
-	0x48bd, 0x6027, 0x0001, 0x0078, 0x4906, 0x2c00, 0x687e, 0x601b,
-	0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
-	0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f76, 0x1078,
-	0x1e02, 0x6818, 0xa005, 0x0040, 0x48d7, 0x8001, 0x681a, 0x6808,
-	0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0,
-	0x48e3, 0x1078, 0x28ec, 0x6812, 0x00c0, 0x48e9, 0x7910, 0xc1a5,
-	0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x202a,
-	0xd7fc, 0x00c0, 0x48f7, 0x2069, 0x4a40, 0x0078, 0x48f9, 0x2069,
-	0x4a80, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4903,
-	0x697a, 0x2001, 0x0004, 0x2708, 0x1078, 0x25d1, 0x2091, 0x8001,
-	0x007c, 0x0d7e, 0x694c, 0x2160, 0xd7fc, 0x00c0, 0x491b, 0x7810,
-	0xd0ec, 0x0040, 0x4917, 0x2069, 0x0100, 0x0078, 0x491d, 0x2069,
-	0x0200, 0x0078, 0x491d, 0x2069, 0x0100, 0x1078, 0x2881, 0x601b,
-	0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
-	0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830,
-	0xd0b4, 0x0040, 0x494b, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
-	0xd094, 0x0040, 0x493d, 0x00f0, 0x4937, 0x684b, 0x0009, 0x20a9,
-	0x0014, 0x6848, 0xd084, 0x0040, 0x4947, 0x00f0, 0x4941, 0x20a9,
-	0x00fa, 0x00f0, 0x4949, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b,
-	0x0047, 0x0d7f, 0x6867, 0x0007, 0x2091, 0x8001, 0x007c, 0x2079,
-	0x4a00, 0x1078, 0x498b, 0x1078, 0x4971, 0x1078, 0x497e, 0x2009,
-	0x0002, 0x2069, 0x4a80, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817,
-	0x0000, 0x8109, 0x0040, 0x4970, 0x2069, 0x4a40, 0x0078, 0x4963,
-	0x007c, 0x7810, 0xd0ec, 0x0040, 0x4979, 0x2019, 0x00cc, 0x0078,
-	0x497b, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, 0x7814, 0xd0e4,
-	0x00c0, 0x4986, 0x2019, 0x0040, 0x0078, 0x4988, 0x2019, 0x0026,
-	0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4993, 0x2019,
-	0x3f94, 0x0078, 0x4995, 0x2019, 0x2624, 0x7b32, 0x7b36, 0x007c,
-	0x6950, 0xa185, 0x0000, 0x0040, 0x49ad, 0x0c7e, 0x6ac0, 0x2264,
-	0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, 0x600a, 0x8210,
-	0x8109, 0x00c0, 0x499f, 0x6952, 0x0c7f, 0x007c, 0x70ec, 0xd0dc,
-	0x00c0, 0x49b7, 0xd0d4, 0x0040, 0x49d6, 0x0078, 0x49d9, 0x7810,
-	0xd0ec, 0x0040, 0x49c2, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x49dd,
-	0x0078, 0x49d9, 0xae8e, 0x0100, 0x0040, 0x49ce, 0x7814, 0xc0f5,
-	0x7816, 0xd0d4, 0x00c0, 0x49dd, 0x0078, 0x49d9, 0x7814, 0xc0fd,
-	0x7816, 0xd0d4, 0x00c0, 0x49dd, 0x0078, 0x49d9, 0xd0e4, 0x0040,
-	0x49df, 0x7804, 0xd08c, 0x0040, 0x49df, 0x681f, 0x000c, 0x70a0,
-	0x70a2, 0x007c, 0x699a
+	0x0040, 0x45e5, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x45aa,
+	0xa184, 0x0003, 0x0040, 0x4616, 0xa184, 0x01e0, 0x00c0, 0x4616,
+	0xd1f4, 0x00c0, 0x45aa, 0xa184, 0x3000, 0xa086, 0x1000, 0x0040,
+	0x45aa, 0x2011, 0x0180, 0x710c, 0x8211, 0x0040, 0x45cf, 0x7008,
+	0xd0f4, 0x00c0, 0x45aa, 0x700c, 0xa106, 0x0040, 0x45c4, 0x7007,
+	0x0012, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x45d1, 0xa184,
+	0x0003, 0x0040, 0x4616, 0xd194, 0x0040, 0x45d1, 0xd1f4, 0x0040,
+	0x4616, 0x7007, 0x0002, 0x0078, 0x45aa, 0x7108, 0xd1fc, 0x0040,
+	0x45f0, 0x1078, 0x4769, 0x8aff, 0x0040, 0x458c, 0x0078, 0x45e5,
+	0x700c, 0xa08c, 0x03ff, 0x0040, 0x461b, 0x7004, 0xd084, 0x0040,
+	0x460d, 0x7014, 0xa005, 0x00c0, 0x4609, 0x7010, 0x7310, 0xa306,
+	0x00c0, 0x45fd, 0x2300, 0xa005, 0x0040, 0x460d, 0xa102, 0x00c8,
+	0x45e5, 0x7007, 0x0010, 0x0078, 0x4616, 0x8aff, 0x0040, 0x461b,
+	0x1078, 0x4970, 0x00c0, 0x4610, 0x0040, 0x45e5, 0x1078, 0x46b4,
+	0x127f, 0x2000, 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8,
+	0x462a, 0x7007, 0x0002, 0x0078, 0x461b, 0x7003, 0x0008, 0x127f,
+	0x2000, 0x007c, 0xa205, 0x00c0, 0x4616, 0x7003, 0x0008, 0x127f,
+	0x2000, 0x007c, 0x6428, 0x84ff, 0x0040, 0x465e, 0x2c70, 0x7004,
+	0xa0bc, 0x000f, 0xa7b8, 0x466e, 0x273c, 0x87fb, 0x00c0, 0x464c,
+	0x0048, 0x4644, 0x1078, 0x296b, 0x609c, 0xa075, 0x0040, 0x465e,
+	0x0078, 0x4637, 0x2039, 0x4663, 0x2704, 0xae68, 0x6808, 0xa630,
+	0x680c, 0xa529, 0x8421, 0x0040, 0x465e, 0x8738, 0x2704, 0xa005,
+	0x00c0, 0x464d, 0x709c, 0xa075, 0x00c0, 0x4637, 0x007c, 0x0000,
+	0x0005, 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000,
+	0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4663,
+	0x4660, 0x0000, 0x0000, 0x8000, 0x0000, 0x4663, 0x0000, 0x466b,
+	0x4668, 0x0000, 0x0000, 0x0000, 0x0000, 0x466b, 0x0000, 0x4666,
+	0x4666, 0x0000, 0x0000, 0x8000, 0x0000, 0x4666, 0x0000, 0x466c,
+	0x466c, 0x0000, 0x0000, 0x0000, 0x0000, 0x466c, 0x2079, 0x4e00,
+	0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001,
+	0x7810, 0xd0ec, 0x0040, 0x46a2, 0x2009, 0x0001, 0x2071, 0x0020,
+	0x0078, 0x46a6, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, 0x000a,
+	0x7007, 0x0002, 0x7003, 0x0000, 0x8109, 0x0040, 0x46b3, 0x2071,
+	0x0020, 0x0078, 0x46a6, 0x007c, 0x7004, 0x8004, 0x00c8, 0x473d,
+	0x7108, 0x7008, 0xa106, 0x00c0, 0x46b8, 0xa184, 0x01e0, 0x0040,
+	0x46c5, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007, 0x0012, 0x2019,
+	0x0000, 0x7108, 0x7008, 0xa106, 0x00c0, 0x46c9, 0xa184, 0x01e0,
+	0x0040, 0x46d6, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7810, 0xd0ec,
+	0x0040, 0x46f0, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0,
+	0x46f4, 0xa184, 0x4000, 0x0040, 0x46f8, 0xa382, 0x0003, 0x00c8,
+	0x46f8, 0xa184, 0x0004, 0x0040, 0x46c9, 0x8318, 0x0078, 0x46c9,
+	0x7814, 0xd0ec, 0x00c0, 0x46f8, 0xa184, 0x4000, 0x00c0, 0x46c9,
+	0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x4715, 0xa386, 0x0008,
+	0x0040, 0x4720, 0x7004, 0xd084, 0x00c0, 0x4711, 0x7108, 0x7008,
+	0xa106, 0x00c0, 0x4706, 0xa184, 0x0003, 0x0040, 0x4711, 0x0078,
+	0x47ac, 0xa386, 0x200c, 0x00c0, 0x46c9, 0x7200, 0x8204, 0x0048,
+	0x4720, 0x730c, 0xa384, 0x03ff, 0x0040, 0x4720, 0x1078, 0x296b,
+	0x7108, 0x7008, 0xa106, 0x00c0, 0x4720, 0xa184, 0x01e0, 0x0040,
+	0x472d, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007, 0x0012, 0x7000,
+	0xd084, 0x00c0, 0x473d, 0x7310, 0x7014, 0xa305, 0x0040, 0x473d,
+	0x710c, 0xa184, 0x03ff, 0x00c0, 0x46b4, 0x7108, 0x7008, 0xa106,
+	0x00c0, 0x473d, 0xa184, 0x01e0, 0x0040, 0x474a, 0x1078, 0x47ac,
+	0x0078, 0x4765, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c,
+	0x00c0, 0x474e, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4752, 0xa184,
+	0x01e0, 0x0040, 0x475f, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007,
+	0x0012, 0x7108, 0x8103, 0x0048, 0x4752, 0x7003, 0x0008, 0x007c,
+	0x7108, 0xa184, 0x01e0, 0x00c0, 0x47ac, 0x7108, 0xa184, 0x01e0,
+	0x00c0, 0x47ac, 0xa184, 0x0007, 0x0079, 0x4776, 0x4780, 0x4790,
+	0x477e, 0x4790, 0x477e, 0x47ee, 0x477e, 0x47ec, 0x1078, 0x296b,
+	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0, 0x478b,
+	0x2049, 0x0000, 0x007c, 0x1078, 0x4970, 0x00c0, 0x478b, 0x007c,
+	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x00c0,
+	0x47a4, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4799, 0xa184, 0x0003,
+	0x0040, 0x47a4, 0x0078, 0x47ac, 0x8aff, 0x0040, 0x47ab, 0x1078,
+	0x4970, 0x00c0, 0x47a7, 0x007c, 0x7007, 0x0012, 0x7108, 0x00e0,
+	0x47af, 0x2091, 0x6000, 0x00e0, 0x47b3, 0x2091, 0x6000, 0x7007,
+	0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x47bb, 0x7007,
+	0x0012, 0x7108, 0xd1fc, 0x00c0, 0x47bf, 0x7003, 0x0000, 0x7000,
+	0xa005, 0x00c0, 0x47d3, 0x7004, 0xa005, 0x00c0, 0x47d3, 0x700c,
+	0xa005, 0x0040, 0x47d5, 0x0078, 0x47b7, 0x2049, 0x0000, 0xb284,
+	0x0100, 0x0040, 0x47df, 0x2001, 0x0000, 0x0078, 0x47e1, 0x2001,
+	0x0001, 0x1078, 0x4212, 0x681b, 0x0002, 0x2051, 0x0000, 0x007c,
+	0x1078, 0x296b, 0x1078, 0x296b, 0x1078, 0x4836, 0x7210, 0x7114,
+	0x700c, 0xa09c, 0x03ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
+	0x1078, 0x4836, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322,
+	0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4811, 0x00c8,
+	0x4811, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078,
+	0x47f8, 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040,
+	0x481d, 0xa7ba, 0x4668, 0x0078, 0x481f, 0xa7ba, 0x4660, 0x007f,
+	0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7108, 0x7008,
+	0xa106, 0x00c0, 0x4826, 0xa184, 0x01e0, 0x0040, 0x4831, 0x1078,
+	0x47ac, 0x7007, 0x0012, 0x1078, 0x46b4, 0x007c, 0x8a50, 0x8739,
+	0x2704, 0xa004, 0x00c0, 0x484a, 0x6000, 0xa064, 0x00c0, 0x4841,
+	0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x467e, 0x203c, 0x87fb,
+	0x1040, 0x296b, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600,
+	0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90,
+	0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084,
+	0x0008, 0x007f, 0x0040, 0x4868, 0xa0b8, 0x4668, 0x0078, 0x486a,
+	0xa0b8, 0x4660, 0xb284, 0x0100, 0x0040, 0x4871, 0x7e20, 0x0078,
+	0x4872, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x4879,
+	0xc685, 0x2400, 0xa305, 0x0040, 0x48a3, 0x2c58, 0x2704, 0x6104,
+	0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
+	0x0008, 0x0040, 0x4893, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014,
+	0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c,
+	0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
+	0x499b, 0x0078, 0x48a5, 0x1078, 0x4970, 0x00c0, 0x48a3, 0x127f,
+	0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004,
+	0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094, 0x00c0, 0x48b4,
+	0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4,
+	0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f, 0x0d7f, 0x7e20,
+	0xb284, 0x0100, 0x00c0, 0x48cd, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+	0xd0ac, 0x00c0, 0x48d8, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
+	0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x466e,
+	0x273c, 0x87fb, 0x00c0, 0x48ee, 0x0048, 0x48e8, 0x1078, 0x296b,
+	0x689c, 0xa065, 0x0040, 0x48f2, 0x0078, 0x48db, 0x1078, 0x4970,
+	0x00c0, 0x48ee, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
+	0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f,
+	0x7e20, 0xb284, 0x0100, 0x00c0, 0x4906, 0x7e24, 0x0d7f, 0x037f,
+	0x047f, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x4914, 0xc685,
+	0x7003, 0x0000, 0x7007, 0x0004, 0x2049, 0x48f5, 0x6828, 0xa055,
+	0x0d7e, 0x0040, 0x496c, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f,
+	0xa7b8, 0x466e, 0x273c, 0x87fb, 0x00c0, 0x4931, 0x0048, 0x492a,
+	0x1078, 0x296b, 0x709c, 0xa075, 0x2060, 0x0040, 0x496c, 0x0078,
+	0x491d, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048,
+	0x494a, 0x8a51, 0x00c0, 0x493e, 0x1078, 0x296b, 0x8738, 0x2704,
+	0xa005, 0x00c0, 0x4932, 0x709c, 0xa075, 0x2060, 0x0040, 0x496c,
+	0x0078, 0x491d, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908,
+	0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4959, 0x1078,
+	0x296b, 0xb284, 0x0100, 0x0040, 0x4967, 0x2001, 0x4e04, 0x2004,
+	0xd0ec, 0x00c0, 0x4967, 0x2071, 0x0050, 0x0078, 0x4969, 0x2071,
+	0x0020, 0x0d7f, 0x0078, 0x4879, 0x0d7f, 0x127f, 0x2000, 0x007c,
+	0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x4979, 0xa006,
+	0x007c, 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0, 0x4980, 0x007c,
+	0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808, 0x7012,
+	0x780c, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040, 0x4993, 0x7810,
+	0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085,
+	0x7006, 0x2079, 0x4e00, 0x8a51, 0x0040, 0x49bf, 0x8738, 0x2704,
+	0xa005, 0x00c0, 0x49b1, 0x609c, 0xa005, 0x0040, 0x49c0, 0x2060,
+	0x6004, 0xa084, 0x000f, 0xa080, 0x466e, 0x203c, 0x87fb, 0x1040,
+	0x296b, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x49bb,
+	0xa006, 0x0078, 0x49c0, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c,
+	0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4, 0xa084,
+	0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003,
+	0x00c0, 0x49d8, 0x6828, 0xa005, 0x0040, 0x49e8, 0x0078, 0x45a2,
+	0x7108, 0xd1fc, 0x0040, 0x49e0, 0x1078, 0x4769, 0x0078, 0x49cd,
+	0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x49e2, 0x1078, 0x4769,
+	0x7008, 0xa086, 0x0008, 0x00c0, 0x49cd, 0x7000, 0xa005, 0x00c0,
+	0x49cd, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c,
+	0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4, 0xa084,
+	0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x49f8, 0xad80, 0x0011,
+	0x20a0, 0xb284, 0x0100, 0x0040, 0x4a1b, 0x2001, 0x4e04, 0x2004,
+	0xd0ec, 0x0040, 0x4a17, 0x2099, 0x0031, 0x0078, 0x4a1d, 0x2099,
+	0x0032, 0x0078, 0x4a1d, 0x2099, 0x0031, 0x700c, 0xa084, 0x03ff,
+	0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040,
+	0x4a2c, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff, 0x0040,
+	0x4a38, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4a33,
+	0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f,
+	0x127f, 0x2000, 0x007c, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac,
+	0xa005, 0x00c0, 0x4a5a, 0x7974, 0x70d0, 0xa106, 0x00c0, 0x4a5a,
+	0x781c, 0xa005, 0x0040, 0x4a5a, 0x781f, 0x0000, 0x0068, 0x4a5a,
+	0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0, 0x4ae2, 0x7834,
+	0x7832, 0x7810, 0xd0ec, 0x00c0, 0x4adb, 0x2061, 0x73c0, 0x2069,
+	0x4e80, 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x4a74, 0x8001, 0x68d2,
+	0x00c0, 0x4a74, 0x1078, 0x4cb0, 0x6800, 0xa084, 0x000f, 0x0040,
+	0x4a89, 0xa086, 0x0001, 0x0040, 0x4a89, 0x6844, 0xa00d, 0x0040,
+	0x4a89, 0x2104, 0xa005, 0x0040, 0x4a89, 0x8001, 0x200a, 0x0040,
+	0x4c23, 0x6814, 0xa005, 0x0040, 0x4aae, 0x8001, 0x6816, 0x00c0,
+	0x4aae, 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0, 0x4aa3, 0x7810,
+	0xd0ec, 0x0040, 0x4a9f, 0x2079, 0x0100, 0x0078, 0x4aa5, 0x2079,
+	0x0200, 0x0078, 0x4aa5, 0x2079, 0x0100, 0x1078, 0x4383, 0x0f7f,
+	0x6864, 0xa005, 0x0040, 0x4aae, 0x1078, 0x2628, 0x6880, 0xa005,
+	0x0040, 0x4abb, 0x8001, 0x6882, 0x00c0, 0x4abb, 0x6867, 0x0000,
+	0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040, 0x4ad8, 0xc0fc,
+	0x68d6, 0x20a9, 0x0200, 0x6034, 0xa005, 0x0040, 0x4ad4, 0x8001,
+	0x6036, 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x4ad4, 0x6010, 0xa005,
+	0x0040, 0x4ad4, 0x1078, 0x2628, 0xace0, 0x0010, 0x00f0, 0x4ac3,
+	0xd7fc, 0x0040, 0x4ae2, 0x2061, 0x53c0, 0x2069, 0x4e40, 0xc7fc,
+	0x0078, 0x4a6a, 0x1078, 0x4b1e, 0x7838, 0x8001, 0x783a, 0x00c0,
+	0x4b04, 0x783c, 0x783a, 0x2061, 0x53c0, 0x2069, 0x4e40, 0xc7fc,
+	0x680c, 0xa005, 0x0040, 0x4af6, 0x1078, 0x4b88, 0xd7fc, 0x00c0,
+	0x4b04, 0x7810, 0xd0ec, 0x00c0, 0x4b04, 0x2061, 0x73c0, 0x2069,
+	0x4e80, 0xc7fd, 0x0078, 0x4af0, 0x7814, 0xd0e4, 0x00c0, 0x4b08,
+	0x7810, 0xd0cc, 0x0040, 0x4b1b, 0xd0ac, 0x00c0, 0x4b14, 0xd0a4,
+	0x0040, 0x4b1b, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0068, 0x4b1a,
+	0x1078, 0x2395, 0x007c, 0x2091, 0x8001, 0x007c, 0x7840, 0x8001,
+	0x7842, 0x00c0, 0x4b87, 0x7844, 0x7842, 0x2069, 0x4e40, 0xc7fc,
+	0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040, 0x4b30, 0x2079, 0x0100,
+	0x68d8, 0xa005, 0x0040, 0x4b3c, 0x7de0, 0xa504, 0x00c0, 0x4b3c,
+	0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079, 0x4e00, 0x6810, 0xa005,
+	0x00c0, 0x4b44, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0040,
+	0x4b4d, 0xa080, 0x94d0, 0x0078, 0x4b4f, 0xa080, 0x93c0, 0x2040,
+	0x2004, 0xa065, 0x0040, 0x4b79, 0x6024, 0xa005, 0x0040, 0x4b75,
+	0x8001, 0x6026, 0x00c0, 0x4b75, 0x6800, 0xa005, 0x0040, 0x4b68,
+	0x684c, 0xac06, 0x00c0, 0x4b68, 0x1078, 0x4c23, 0x0078, 0x4b79,
+	0x6864, 0xa005, 0x0040, 0x4b70, 0x6027, 0x0001, 0x0078, 0x4b75,
+	0x1078, 0x4bd6, 0x2804, 0x0078, 0x4b51, 0x6000, 0x2c40, 0x0078,
+	0x4b51, 0xd7fc, 0x00c0, 0x4b87, 0x7810, 0xd0ec, 0x00c0, 0x4b87,
+	0x2069, 0x4e80, 0xc7fd, 0x2079, 0x0100, 0x0078, 0x4b30, 0x007c,
+	0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0040, 0x4bc2,
+	0x6024, 0xa005, 0x0040, 0x4b98, 0x8001, 0x6026, 0x0078, 0x4bc0,
+	0x6008, 0xc09c, 0xd084, 0x00c0, 0x4ba0, 0xd0ac, 0x0040, 0x4bba,
+	0x600a, 0x6004, 0xa005, 0x0040, 0x4bc2, 0x0d7e, 0x0c7e, 0x017e,
+	0x2068, 0x6010, 0x8001, 0x6012, 0x1078, 0x3dd0, 0x2d00, 0x2c68,
+	0x2060, 0x1078, 0x1e5b, 0x1078, 0x201d, 0x017f, 0x0c7f, 0x0d7f,
+	0x0078, 0x4bc2, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, 0x4bc2,
+	0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0, 0x4b8c, 0xa184, 0x0001,
+	0x0040, 0x4bd1, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x2628, 0x0078,
+	0x4bd2, 0x690e, 0x007c, 0x00c0, 0x4bd2, 0x786c, 0x2c00, 0x687e,
+	0x6714, 0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006,
+	0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
+	0x0060, 0x6022, 0x6000, 0x2042, 0x1078, 0x1de4, 0x6818, 0xa005,
+	0x0040, 0x4bf4, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810,
+	0x7908, 0x8109, 0x790a, 0x8001, 0x00d0, 0x4c00, 0x1078, 0x296b,
+	0x6812, 0x00c0, 0x4c06, 0x7910, 0xc1a5, 0x7912, 0x602f, 0x0000,
+	0x6033, 0x0000, 0x2c68, 0x1078, 0x202c, 0xd7fc, 0x00c0, 0x4c14,
+	0x2069, 0x4e40, 0x0078, 0x4c16, 0x2069, 0x4e80, 0x6910, 0xa184,
+	0x0100, 0x2001, 0x0006, 0x00c0, 0x4c20, 0x697a, 0x2001, 0x0004,
+	0x1078, 0x261c, 0x007c, 0x0d7e, 0x694c, 0x2160, 0xd7fc, 0x00c0,
+	0x4c35, 0x7810, 0xd0ec, 0x0040, 0x4c31, 0x2069, 0x0100, 0x0078,
+	0x4c37, 0x2069, 0x0200, 0x0078, 0x4c37, 0x2069, 0x0100, 0x1078,
+	0x28df, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020,
+	0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033,
+	0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x0040,
+	0x4c69, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0040,
+	0x4c5b, 0x00f0, 0x4c55, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848,
+	0xd084, 0x0040, 0x4c65, 0x00f0, 0x4c5f, 0x20a9, 0x00fa, 0x00f0,
+	0x4c67, 0x681b, 0x0047, 0x0d7f, 0x6867, 0x0007, 0x007c, 0x2079,
+	0x4e00, 0x1078, 0x4ca3, 0x1078, 0x4c89, 0x1078, 0x4c96, 0x2009,
+	0x0002, 0x2069, 0x4e80, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817,
+	0x0000, 0x8109, 0x0040, 0x4c88, 0x2069, 0x4e40, 0x0078, 0x4c7b,
+	0x007c, 0x7810, 0xd0ec, 0x0040, 0x4c91, 0x2019, 0x00cc, 0x0078,
+	0x4c93, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, 0x7814, 0xd0e4,
+	0x00c0, 0x4c9e, 0x2019, 0x0040, 0x0078, 0x4ca0, 0x2019, 0x0026,
+	0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4cab, 0x2019,
+	0x3f94, 0x0078, 0x4cad, 0x2019, 0x2624, 0x7b32, 0x7b36, 0x007c,
+	0x6a50, 0xa285, 0x0000, 0x0040, 0x4cdc, 0x6954, 0x6bc0, 0xa300,
+	0x0c7e, 0x2164, 0x6304, 0x83ff, 0x00c0, 0x4cc8, 0x8211, 0x0040,
+	0x4ccc, 0x8108, 0xa11a, 0x0048, 0x4cb9, 0x69c0, 0x0078, 0x4cb9,
+	0x68d3, 0x000a, 0x0c7f, 0x007c, 0x6950, 0x6ac0, 0x2264, 0x602b,
+	0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109,
+	0x00c0, 0x4cce, 0x6952, 0x0c7f, 0x007c, 0x00e0, 0x4cdd, 0x2091,
+	0x6000, 0x00e0, 0x4ce1, 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x00c0,
+	0x4cee, 0xd0d4, 0x0040, 0x4d17, 0x0078, 0x4d1a, 0x2008, 0x7810,
+	0xd0ec, 0x0040, 0x4d01, 0xd1c4, 0x00c0, 0x4d39, 0x7814, 0xc0c5,
+	0x7816, 0x7810, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x4d35, 0x0078,
+	0x4d31, 0xae8e, 0x0100, 0x0040, 0x4d0e, 0x7814, 0xc0f5, 0xc0c5,
+	0x7816, 0xd0d4, 0x00c0, 0x4d35, 0x0078, 0x4d31, 0x7814, 0xc0fd,
+	0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4d35, 0x0078, 0x4d31, 0xd0e4,
+	0x0040, 0x4d37, 0x00e0, 0x4d1a, 0x2091, 0x6000, 0x2009, 0x000c,
+	0x00e0, 0x4d20, 0x2091, 0x6000, 0x8109, 0x00c0, 0x4d20, 0x70e4,
+	0xa084, 0x01ff, 0xa086, 0x01ff, 0x00c0, 0x4d31, 0x70ec, 0x0078,
+	0x4cee, 0x7804, 0xd08c, 0x0040, 0x4d37, 0x681f, 0x000c, 0x70a0,
+	0x70a2, 0x007c, 0x205b
 };
-unsigned short   fw1280ei_length01 = 0x39e3;
-
+#ifdef UNIQUE_FW_NAME
+unsigned short   fw1280ei_length01 = 0x3d3b;
+#else
+unsigned short   risc_code_length01 = 0x3d3b;
+#endif
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	Sun Apr 14 12:17:00 2002
+++ b/drivers/scsi/qla1280.c	Sun Apr 14 12:17:00 2002
@@ -1,165 +1,221 @@
-/********************************************************************************
- *                  QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.X).
- *
- * COPYRIGHT (C) 1999-2000 QLOGIC CORPORATION    
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Qlogic's Linux Software License. See below.
- *
- * This program is WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistribution's or source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- ********************************************************************************/
- 
-/*****************************************************************************************
-			QLOGIC CORPORATION SOFTWARE
-           "GNU" GENERAL PUBLIC LICENSE
-    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
-                 AND MODIFICATION
-
-This GNU General Public License ("License") applies solely to QLogic Linux 
-Software ("Software") and may be distributed under the terms of this License.  
- 
-1. You may copy and distribute verbatim copies of the Software's source code as 
-you receive it, in any medium, provided that you conspicuously and appropriately 
-publish on each copy an appropriate copyright notice and disclaimer of warranty;
-keep intact all the notices that refer to this License and to the absence of any
-warranty; and give any other recipients of the Software a copy of this License along
-with the Software. 
-
-You may charge a fee for the physical act of transferring a copy, and you may at your
-option offer warranty protection in exchange for a fee.
- 
-2. You may modify your copy or copies of the Software or any portion of it, thus forming
-a work based on the Software, and copy and distribute such modifications or work under
-the terms of Section 1 above, provided that you also meet all of these conditions:
- 
-* a) You must cause the modified files to carry prominent notices stating that you
-changed the files and the date of any change. 
-
-* b) You must cause any work that you distribute or publish that in whole or in part
-contains or is derived from the Software or any part thereof, to be licensed as a
-whole at no charge to all third parties under the terms of this License. 
-
-* c) If the modified Software normally reads commands interactively when run, you
-must cause it, when started running for such interactive use in the most ordinary way,
-to print or display an announcement including an appropriate copyright notice and a 
-notice that there is no warranty (or else, saying that you provide a warranty) and that
-users may redistribute the Software under these conditions, and telling the user how to
-view a copy of this License. (Exception:if the Software itself is interactive but does 
-not normally print such an announcement, your work based on the Software is not required
-to print an announcement.) 
-
-These requirements apply to the modified work as a whole. If identifiable sections of
-that work are not derived from the Software, and can be reasonably considered independent
-and separate works in themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you distribute the same
-sections as part of a whole which is a work based on the Software, the distribution of the
-whole must be on the terms of this License, whose permissions for other licensees extend
-to the entire whole, and thus to each and every part regardless of who wrote it. 
-
-3. You may copy and distribute the Software (or a work based on it, under Section 2) in 
-object code or executable form under the terms of Sections 1 and 2 above provided that
-you also do one of the following: 
-
-* a) Accompany it with the complete corresponding machine-readable source code, which must
-be distributed under the terms of Sections 1 and 2 above on a medium customarily used for
-software interchange; or, 
-
-* b) Accompany it with a written offer, valid for at least three years, to give any third
-party, for a charge no more than your cost of physically performing source distribution,
-a complete machine-readable copy of the corresponding source code, to be distributed under
-the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
-or,
-
-* c) Accompany it with the information you received as to the offer to distribute 
-corresponding source code. (This alternative is allowed only for noncommercial distribution
-and only if you received the Software in object code or executable form with such an offer,
-in accord with Subsection b above.) 
-
-The source code for a work means the preferred form of the work for making modifications
-to it. For an executable work, complete source code means all the source code for all 
-modules it contains, plus any associated interface definition files, plus the scripts used
-to control compilation and installation of the executable.     
-
-If distribution of executable or object code is made by offering access to copy from a 
-designated place, then offering equivalent access to copy the source code from the same
-place counts as distribution of the source code, even though third parties are not 
-compelled to copy the source along with the object code. 
-
-4. You may not copy, modify, sublicense, or distribute the Software except as expressly 
-provided under this License. Any attempt otherwise to copy, modify, sublicense or 
-distribute the Software is void, and will automatically terminate your rights under this
-License. However, parties who have received copies, or rights, from you under this License
-will not have their licenses terminated so long as such parties remain in full compliance. 
-
-5. This license grants you world wide, royalty free non-exclusive rights to modify or 
-distribute the Software or its derivative works. These actions are prohibited by law 
-if you do not accept this License. Therefore, by modifying or distributing the Software
-(or any work based on the Software), you indicate your acceptance of this License to do
-so, and all its terms and conditions for copying, distributing or modifying the Software
-or works based on it.
- 
-6. Each time you redistribute the Software (or any work based on the Software), the 
-recipient automatically receives a license from the original licensor to copy, distribute
-or modify the Software subject to these terms and conditions. You may not impose any 
-further restrictions on the recipients' exercise of the rights granted herein. You are
-not responsible for enforcing compliance by third parties to this License.
- 
-7. If, as a consequence of a court judgment or allegation of patent infringement or for
-any other reason (not limited to patent issues), conditions are imposed on you 
-(whether by court order, agreement or otherwise) that contradict the conditions of this
-License, they do not excuse you from the conditions of this License. If you cannot 
-distribute so as to satisfy simultaneously your obligations under this License 
-and any other pertinent obligations, then as a consequence you may not distribute the
-Software at all.    
-
-If any portion of this section is held invalid or unenforceable under any particular 
-circumstance, the balance of the section is intended to apply and the section as a whole
-is intended to apply in other circumstances. 
-NO WARRANTY
-
-11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO 
-WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
-OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, 
-EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
-ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. 
-SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
-NECESSARY SERVICING, REPAIR OR CORRECTION.
- 
-12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
-REDISTRIBUTE THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
-DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
-DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING 
-BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 
-LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO 
-OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 
-BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
-END OF TERMS AND CONDITIONS 
-
-*******************************************************************************************/ 
-
-/****************************************************************************
+/******************************************************************************
+*                  QLOGIC LINUX SOFTWARE
+*
+* QLogic  QLA1280 (Ultra2)  and  QLA12160 (Ultra3) SCSI driver
+* Copyright (C) 2000 Qlogic Corporation (www.qlogic.com)
+* Copyright (C) 2001-2002 Jes Sorensen, Wild Open Source Inc.
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2, or (at your option) 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.
+*
+******************************************************************************/
+#define QLA1280_VERSION      "3.23.19 Beta"
+/******************************************************************************
     Revision History:
-    Rev. 3.00       Jan 17, 1999    DG  Qlogic
+    Rev  3.23.19 Beta April 11, 2002, Linus Torvalds
+	- Do qla1280_pci_config() before calling request_irq() and
+	  request_region()
+	- Use pci_dma_hi32() to handle upper word of DMA addresses instead
+	  of large shifts
+	- Hand correct arguments to free_irq() in case of failure
+    Rev  3.23.18 Beta April 11, 2002, Jes Sorensen
+	- Run source through Lindent and clean up the output
+    Rev  3.23.17 Beta April 11, 2002, Jes Sorensen
+	- Update SCSI firmware to qla1280 v8.15.00 and qla12160 v10.04.32
+    Rev  3.23.16 Beta March 19, 2002, Jes Sorensen
+	- Rely on mailbox commands generating interrupts - do not
+	  run qla1280_isr() from ql1280_mailbox_command()
+	- Remove device_reg_t
+	- Integrate ql12160_set_target_parameters() with 1280 version
+	- Make qla1280_setup() non static
+	- Do not call qla1280_check_for_dead_scsi_bus() on every I/O request
+	  sent to the card - this command pauses the firmare!!!
+    Rev  3.23.15 Beta March 19, 2002, Jes Sorensen
+	- Clean up qla1280.h - remove obsolete QL_DEBUG_LEVEL_x definitions
+	- Remove a pile of pointless and confusing (srb_t **) and
+	  (scsi_lu_t *) typecasts
+	- Explicit mark that we do not use the new error handling (for now)
+	- Remove scsi_qla_host_t and use 'struct' instead
+	- Remove in_abort, watchdog_enabled, dpc, dpc_sched, bios_enabled,
+	  pci_64bit_slot flags which weren't used for anything anyway
+	- Grab host->host_lock while calling qla1280_isr() from abort()
+	- Use spin_lock()/spin_unlock() in qla1280_intr_handler() - we
+	  do not need to save/restore flags in the interrupt handler
+	- Enable interrupts early (before any mailbox access) in preparation
+	  for cleaning up the mailbox handling
+    Rev  3.23.14 Beta March 14, 2002, Jes Sorensen
+	- Further cleanups. Remove all trace of QL_DEBUG_LEVEL_x and replace
+	  it with proper use of dprintk().
+	- Make qla1280_print_scsi_cmd() and qla1280_dump_buffer() both take
+	  a debug level argument to determine if data is to be printed
+	- Add KERN_* info to printk()
+    Rev  3.23.13 Beta March 14, 2002, Jes Sorensen
+	- Significant cosmetic cleanups
+	- Change debug code to use dprintk() and remove #if mess
+    Rev  3.23.12 Beta March 13, 2002, Jes Sorensen
+	- More cosmetic cleanups, fix places treating return as function
+	- use cpu_relax() in qla1280_debounce_register()
+    Rev  3.23.11 Beta March 13, 2002, Jes Sorensen
+	- Make it compile under 2.5.5
+    Rev  3.23.10 Beta October 1, 2001, Jes Sorensen
+	- Do no typecast short * to long * in QL1280BoardTbl, this
+	  broke miserably on big endian boxes
+    Rev  3.23.9 Beta September 30, 2001, Jes Sorensen
+	- Remove pre 2.2 hack for checking for reentrance in interrupt handler
+	- Make data types used to receive from SCSI_{BUS,TCN,LUN}_32
+	  unsigned int to match the types from struct scsi_cmnd
+    Rev  3.23.8 Beta September 29, 2001, Jes Sorensen
+	- Remove bogus timer_t typedef from qla1280.h
+	- Remove obsolete pre 2.2 PCI setup code, use proper #define's
+	  for PCI_ values, call pci_set_master()
+	- Fix memleak of qla1280_buffer on module unload
+	- Only compile module parsing code #ifdef MODULE - should be
+	  changed to use individual MODULE_PARM's later
+	- Remove dummy_buffer that was never modified nor printed
+	- ENTER()/LEAVE() are noops unless QL_DEBUG_LEVEL_3, hence remove
+	  #ifdef QL_DEBUG_LEVEL_3/#endif around ENTER()/LEAVE() calls
+	- Remove \r from print statements, this is Linux, not DOS
+	- Remove obsolete QLA1280_{SCSILU,INTR,RING}_{LOCK,UNLOCK}
+	  dummy macros
+	- Remove C++ compile hack in header file as Linux driver are not
+	  supposed to be compiled as C++
+	- Kill MS_64BITS macro as it makes the code more readable
+	- Remove unnecessary flags.in_interrupts bit
+    Rev  3.23.7 Beta August 20, 2001, Jes Sorensen
+	- Dont' check for set flags on q->q_flag one by one in qla1280_next()
+        - Check whether the interrupt was generated by the QLA1280 before
+          doing any processing
+	- qla1280_status_entry(): Only zero out part of sense_buffer that
+	  is not being copied into
+	- Remove more superflouous typecasts
+	- qla1280_32bit_start_scsi() replace home-brew memcpy() with memcpy()
+    Rev  3.23.6 Beta August 20, 2001, Tony Luck, Intel
+        - Don't walk the entire list in qla1280_putq_t() just to directly
+	  grab the pointer to the last element afterwards
+    Rev  3.23.5 Beta August 9, 2001, Jes Sorensen
+	- Don't use SA_INTERRUPT, it's use is deprecated for this kinda driver
+    Rev  3.23.4 Beta August 8, 2001, Jes Sorensen
+	- Set dev->max_sectors to 1024
+    Rev  3.23.3 Beta August 6, 2001, Jes Sorensen
+	- Provide compat macros for pci_enable_device(), pci_find_subsys()
+	  and scsi_set_pci_device()
+	- Call scsi_set_pci_device() for all devices
+	- Reduce size of kernel version dependant device probe code
+	- Move duplicate probe/init code to seperate function
+	- Handle error if qla1280_mem_alloc() fails
+	- Kill OFFSET() macro and use Linux's PCI definitions instead
+        - Kill private structure defining PCI config space (struct config_reg)
+	- Only allocate I/O port region if not in MMIO mode
+	- Remove duplicate (unused) sanity check of sife of srb_t
+    Rev  3.23.2 Beta August 6, 2001, Jes Sorensen
+	- Change home-brew memset() implementations to use memset()
+        - Remove all references to COMTRACE() - accessing a PC's COM2 serial
+          port directly is not legal under Linux.
+    Rev  3.23.1 Beta April 24, 2001, Jes Sorensen
+        - Remove pre 2.2 kernel support
+        - clean up 64 bit DMA setting to use 2.4 API (provide backwards compat)
+        - Fix MMIO access to use readl/writel instead of directly
+          dereferencing pointers
+        - Nuke MSDOS debugging code
+        - Change true/false data types to int from uint8_t
+        - Use int for counters instead of uint8_t etc.
+        - Clean up size & byte order conversion macro usage
+    Rev  3.23 Beta January 11, 2001 BN Qlogic
+        - Added check of device_id when handling non
+          QLA12160s during detect().
+    Rev  3.22 Beta January 5, 2001 BN Qlogic
+        - Changed queue_task() to schedule_task()
+          for kernels 2.4.0 and higher.
+          Note: 2.4.0-testxx kernels released prior to
+                the actual 2.4.0 kernel release on January 2001
+                will get compile/link errors with schedule_task().
+                Please update your kernel to released 2.4.0 level,
+                or comment lines in this file flagged with  3.22
+                to resolve compile/link error of schedule_task().
+        - Added -DCONFIG_SMP in addition to -D__SMP__
+          in Makefile for 2.4.0 builds of driver as module.
+    Rev  3.21 Beta January 4, 2001 BN Qlogic
+        - Changed criteria of 64/32 Bit mode of HBA
+          operation according to BITS_PER_LONG rather
+          than HBA's NVRAM setting of >4Gig memory bit;
+          so that the HBA auto-configures without the need
+          to setup each system individually.
+    Rev  3.20 Beta December 5, 2000 BN Qlogic
+        - Added priority handling to IA-64  onboard SCSI
+          ISP12160 chip for kernels greater than 2.3.18.
+        - Added irqrestore for qla1280_intr_handler.
+        - Enabled /proc/scsi/qla1280 interface.
+        - Clear /proc/scsi/qla1280 counters in detect().
+    Rev  3.19 Beta October 13, 2000 BN Qlogic
+        - Declare driver_template for new kernel
+          (2.4.0 and greater) scsi initialization scheme.
+        - Update /proc/scsi entry for 2.3.18 kernels and
+          above as qla1280
+    Rev  3.18 Beta October 10, 2000 BN Qlogic
+        - Changed scan order of adapters to map
+          the QLA12160 followed by the QLA1280.
+    Rev  3.17 Beta September 18, 2000 BN Qlogic
+        - Removed warnings for 32 bit 2.4.x compiles
+        - Corrected declared size for request and response
+          DMA addresses that are kept in each ha
+    Rev. 3.16 Beta  August 25, 2000   BN  Qlogic
+        - Corrected 64 bit addressing issue on IA-64
+          where the upper 32 bits were not properly
+          passed to the RISC engine.
+    Rev. 3.15 Beta  August 22, 2000   BN  Qlogic
+        - Modified qla1280_setup_chip to properly load
+          ISP firmware for greater that 4 Gig memory on IA-64
+    Rev. 3.14 Beta  August 16, 2000   BN  Qlogic
+        - Added setting of dma_mask to full 64 bit
+          if flags.enable_64bit_addressing is set in NVRAM
+    Rev. 3.13 Beta  August 16, 2000   BN  Qlogic
+        - Use new PCI DMA mapping APIs for 2.4.x kernel
+    Rev. 3.12       July 18, 2000    Redhat & BN Qlogic
+        - Added check of pci_enable_device to detect() for 2.3.x
+        - Use pci_resource_start() instead of
+          pdev->resource[0].start in detect() for 2.3.x
+        - Updated driver version
+    Rev. 3.11       July 14, 2000    BN  Qlogic
+	- Updated SCSI Firmware to following versions:
+	  qla1x80:   8.13.08
+	  qla1x160:  10.04.08
+	- Updated driver version to 3.11
+    Rev. 3.10    June 23, 2000   BN Qlogic
+        - Added filtering of AMI SubSys Vendor ID devices
+    Rev. 3.9
+        - DEBUG_QLA1280 undefined and  new version  BN Qlogic
+    Rev. 3.08b      May 9, 2000    MD Dell
+        - Added logic to check against AMI subsystem vendor ID
+	Rev. 3.08       May 4, 2000    DG  Qlogic
+        - Added logic to check for PCI subsystem ID.
+	Rev. 3.07       Apr 24, 2000    DG & BN  Qlogic
+	   - Updated SCSI Firmware to following versions:
+	     qla12160:   10.01.19
+		 qla1280:     8.09.00
+	Rev. 3.06       Apr 12, 2000    DG & BN  Qlogic
+	   - Internal revision; not released
+    Rev. 3.05       Mar 28, 2000    DG & BN  Qlogic
+       - Edit correction for virt_to_bus and PROC.
+    Rev. 3.04       Mar 28, 2000    DG & BN  Qlogic
+       - Merge changes from ia64 port.
+    Rev. 3.03       Mar 28, 2000    BN  Qlogic
+       - Increase version to reflect new code drop with compile fix
+         of issue with inclusion of linux/spinlock for 2.3 kernels
+    Rev. 3.02       Mar 15, 2000    BN  Qlogic
+       - Merge qla1280_proc_info from 2.10 code base
+    Rev. 3.01       Feb 10, 2000    BN  Qlogic
+       - Corrected code to compile on a 2.2.x kernel.
+    Rev. 3.00       Jan 17, 2000    DG  Qlogic
 	   - Added 64-bit support.
     Rev. 2.07       Nov 9, 1999     DG  Qlogic
-	   - Added new routine to set target parameters for ISP12160. 
+	   - Added new routine to set target parameters for ISP12160.
     Rev. 2.06       Sept 10, 1999     DG  Qlogic
        - Added support for ISP12160 Ultra 3 chip.
     Rev. 2.03       August 3, 1999    Fred Lewis, Intel DuPont
@@ -173,27 +229,18 @@
         - Added l modifiers to sprintf and printk format specifiers for longs.
         - Removed unused local variables.
     Rev. 1.20       June 8, 1999      DG,  Qlogic
-         Changes to support RedHat release 6.0 (kernel 2.2.5).  
-       - Added SCSI exclusive access lock (io_request_lock) when accessing 
+         Changes to support RedHat release 6.0 (kernel 2.2.5).
+       - Added SCSI exclusive access lock (io_request_lock) when accessing
          the adapter.
        - Added changes for the new LINUX interface template. Some new error
          handling routines have been added to the template, but for now we
          will use the old ones.
-    -   Initial Beta Release.  
+    -   Initial Beta Release.
 *****************************************************************************/
 
-#error Please convert me to Documentation/DMA-mapping.txt
-
-#ifdef MODULE
+#include <linux/config.h>
 #include <linux/module.h>
-#endif
-
-#define QLA1280_VERSION      " 3.00-Beta"
 
-#include <stdarg.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/byteorder.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -207,204 +254,224 @@
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include <linux/tqueue.h>
-/* MRS #include <linux/tasks.h> */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-# include <linux/bios32.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <asm/processor.h>
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18)
+#include <linux/pci_ids.h>
 #endif
+
 #include "sd.h"
 #include "scsi.h"
 #include "hosts.h"
 #define UNIQUE_FW_NAME
 #include "qla1280.h"
-#include "ql12160_fw.h"                     /* ISP RISC code */
+#include "ql12160_fw.h"		/* ISP RISC codes */
 #include "ql1280_fw.h"
 
-#include <linux/stat.h>
-#include <linux/slab.h>        /* for kmalloc() */
-
-
-#ifndef KERNEL_VERSION
-#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
-#endif
-
-
 /*
- * Compile time Options: 
- *            0 - Disable and 1 - Enable 
+ * Compile time Options:
+ *            0 - Disable and 1 - Enable
  */
-#define  QLA1280_64BIT_SUPPORT         1   /* 64-bit Support */
-#define  QL1280_TARGET_MODE_SUPPORT    0   /* Target mode support */
+#define  QL1280_TARGET_MODE_SUPPORT    0	/* Target mode support */
+#define  QL1280_LUN_SUPPORT            0
 #define  WATCHDOGTIMER                 0
 #define  MEMORY_MAPPED_IO              0
 #define  DEBUG_QLA1280_INTR            0
 #define  USE_NVRAM_DEFAULTS	       0
 #define  DEBUG_PRINT_NVRAM             0
 #define  LOADING_RISC_ACTIVITY         0
-#define  AUTO_ESCALATE_RESET           0   /* Automatically escalate resets */
-#define  AUTO_ESCALATE_ABORT           0   /* Automatically escalate aborts */
-#define  STOP_ON_ERROR                 0   /* Stop on aborts and resets  */
-#define  STOP_ON_RESET                 0 
-#define  STOP_ON_ABORT                 0 
-#undef   DYNAMIC_MEM_ALLOC
-
-#define  DEBUG_QLA1280                 0    /* Debugging  */
-/* #define CHECKSRBSIZE */
-
-/*
- * These macros to assist programming
- */
-
-#define	BZERO(ptr, amt)		memset(ptr, 0, amt)
-#define	BCOPY(src, dst, amt)	memcpy(dst, src, amt)
-#define	KMALLOC(siz)	kmalloc((siz), GFP_ATOMIC)
-#define	KMFREE(ip,siz)	kfree((ip))
-#define	SYS_DELAY(x)		udelay(x);barrier()
-#define QLA1280_DELAY(sec)  mdelay(sec * 1000)
-#define VIRT_TO_BUS(a) virt_to_bus((a))
-#if  QLA1280_64BIT_SUPPORT
-#if  BITS_PER_LONG <= 32
-#define  VIRT_TO_BUS_LOW(a) (uint32_t)virt_to_bus((a))
-#define  VIRT_TO_BUS_HIGH(a) (uint32_t)(0x0)
+#define  AUTO_ESCALATE_RESET           0	/* Automatically escalate resets */
+#define  AUTO_ESCALATE_ABORT           0	/* Automatically escalate aborts */
+#define  STOP_ON_ERROR                 0	/* Stop on aborts and resets  */
+#define  STOP_ON_RESET                 0
+#define  STOP_ON_ABORT                 0
+#define  QLA1280_PROFILE               1	/* 3.20 */
+#define  DEBUG_QLA1280                 0
+
+/*
+ * Missing PCI ID's
+ */
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP1080
+#define PCI_DEVICE_ID_QLOGIC_ISP1080	0x1080
+#endif
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP1240
+#define PCI_DEVICE_ID_QLOGIC_ISP1240	0x1240
+#endif
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP1280
+#define PCI_DEVICE_ID_QLOGIC_ISP1280	0x1280
+#endif
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP10160
+#define PCI_DEVICE_ID_QLOGIC_ISP10160	0x1016
+#endif
+#ifndef PCI_DEVICE_ID_QLOGIC_ISP12160
+#define PCI_DEVICE_ID_QLOGIC_ISP12160	0x1216
+#endif
+
+#ifndef PCI_VENDOR_ID_AMI
+#define PCI_VENDOR_ID_AMI               0x101e
+#endif
+
+#if (BITS_PER_LONG == 64) || defined CONFIG_HIGHMEM
+#define QLA_64BIT_PTR	1
+#endif
+
+/* 3.16 */
+#ifdef QLA_64BIT_PTR
+#define pci_dma_lo32(a)		(a & 0xffffffff)
+#define pci_dma_hi32(a)		(a >> 32)
 #else
-#define  VIRT_TO_BUS_LOW(a) (uint32_t)(0xffffffff & virt_to_bus((a)))
-#define  VIRT_TO_BUS_HIGH(a) (uint32_t)(0xffffffff & (virt_to_bus((a))>>32))
+#define pci_dma_lo32(a)		(a & 0xffffffff)
+#define pci_dma_hi32(a)		0
 #endif
-#endif  /* QLA1280_64BIT_SUPPORT */
 
-#define STATIC     
+#define NVRAM_DELAY()		udelay(500)	/* 2 microsecond delay */
 
-#define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */
-void qla1280_device_queue_depth(scsi_qla_host_t *, Scsi_Device *);
+#define CACHE_FLUSH(a)		RD_REG_WORD(a)
+#define INVALID_HANDLE		(MAX_OUTSTANDING_COMMANDS + 1)
 
-#define  CACHE_FLUSH(a) (RD_REG_WORD(a))
-#define  INVALID_HANDLE    (MAX_OUTSTANDING_COMMANDS+1)
+/*
+ * Compat macros
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#define pci_set_dma_mask(dev, mask)		dev->dma_mask = mask;
+#define pci_present()				pcibios_present()
+#define pci_enable_device(pdev)			0
+#define pci_find_subsys(id, dev, sid, sdev, pdev) pci_find_device(id,dev,pdev)
+#define scsi_set_pci_device(host, pdev)
+#endif
 
-#define  MSW(x)          (uint16_t)((uint32_t)(x) >> 16)
-#define  LSW(x)          (uint16_t)(x)
-#define  MSB(x)          (uint8_t)((uint16_t)(x) >> 8)
-#define  LSB(x)          (uint8_t)(x)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+typedef unsigned long dma_addr_t;
 
-#if  BITS_PER_LONG <= 32
-#define  LS_64BITS(x) (uint32_t)(x)
-#define  MS_64BITS(x) (uint32_t)(0x0)
-#else
-#define  LS_64BITS(x) (uint32_t)(0xffffffff & (x))
-#define  MS_64BITS(x) (uint32_t)(0xffffffff & ((x)>>32) )
+static inline void *
+pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+		     dma_addr_t * dma_handle)
+{
+	void *virt_ptr;
+
+	virt_ptr = kmalloc(size, GFP_KERNEL);
+	if (!virt_ptr)
+		return NULL;
+	*dma_handle = virt_to_bus(virt_ptr);
+	return virt_ptr;
+}
+
+#define pci_free_consistent(cookie, size, ptr, dma_ptr)	kfree(ptr)
+#define pci_map_single(cookie, address, size, dir)	virt_to_bus(address)
+#define pci_map_sg(cookie, scatter, ents, dir)		ents
+#define pci_unmap_single(cookie, address, size, dir)
+#define pci_unmap_sg(cookie, scatter, ents, dir)
+
+#define pci_resource_start(dev, i)			dev->base_address[i]
 #endif
 
 /*
  *  QLogic Driver Support Function Prototypes.
  */
-STATIC void   qla1280_done(scsi_qla_host_t *, srb_t **, srb_t **);
-STATIC void   qla1280_next(scsi_qla_host_t *, scsi_lu_t *, uint8_t);
-STATIC void   qla1280_putq_t(scsi_lu_t *, srb_t *);
-STATIC void   qla1280_done_q_put(srb_t *, srb_t **, srb_t **);
-STATIC void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
-#ifdef  QLA1280_UNUSED 
-static void qla1280_dump_regs(struct Scsi_Host *host);
-#endif
-#if  STOP_ON_ERROR 
+static void qla1280_done(struct scsi_qla_host *, srb_t **, srb_t **);
+static void qla1280_next(struct scsi_qla_host *, scsi_lu_t *, int);
+static void qla1280_putq_t(scsi_lu_t *, srb_t *);
+static void qla1280_done_q_put(srb_t *, srb_t **, srb_t **);
+static void qla1280_device_queue_depth(struct scsi_qla_host *, Scsi_Device *);
+static void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
+#if STOP_ON_ERROR
 static void qla1280_panic(char *, struct Scsi_Host *host);
 #endif
-void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd);
-STATIC void qla1280_abort_queue_single(scsi_qla_host_t *,uint32_t,uint32_t,uint32_t,uint32_t);
+static void qla1280_abort_queue_single(struct scsi_qla_host *, int, int,
+				       int, uint32_t);
 
-STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd       *cp);
-STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp);
-STATIC void qla1280_mem_free(scsi_qla_host_t *ha);
-static void qla1280_do_dpc(void *p);
-#ifdef  QLA1280_UNUSED 
-static void qla1280_set_flags(char * s);
-#endif
-static char	*qla1280_get_token(char *, char *);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-STATIC inline void mdelay(int);
+static int qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp);
+static void qla1280_removeq(scsi_lu_t * q, srb_t * sp);
+static void qla1280_mem_free(struct scsi_qla_host *ha);
+void qla1280_do_dpc(void *p);
+#ifdef MODULE
+static char *qla1280_get_token(char *, char *);
 #endif
-static inline void qla1280_enable_intrs(scsi_qla_host_t *);
-static inline void qla1280_disable_intrs(scsi_qla_host_t *);
+static inline void qla1280_enable_intrs(struct scsi_qla_host *);
+static inline void qla1280_disable_intrs(struct scsi_qla_host *);
 
 /*
  *  QLogic ISP1280 Hardware Support Function Prototypes.
  */
-STATIC uint8_t   qla1280_initialize_adapter(struct scsi_qla_host   *ha);
-STATIC uint8_t   qla1280_enable_tgt(scsi_qla_host_t *, uint8_t);
-STATIC uint8_t   qla1280_isp_firmware(scsi_qla_host_t *);
-STATIC uint8_t   qla1280_pci_config(scsi_qla_host_t *);
-STATIC uint8_t   qla1280_chip_diag(scsi_qla_host_t *);
-STATIC uint8_t   qla1280_setup_chip(scsi_qla_host_t *);
-STATIC uint8_t   qla1280_init_rings(scsi_qla_host_t *);
-STATIC uint8_t   qla1280_nvram_config(scsi_qla_host_t *);
-STATIC uint8_t   qla1280_mailbox_command(scsi_qla_host_t *, uint8_t, uint16_t *);
-STATIC uint8_t   qla1280_bus_reset(scsi_qla_host_t *, uint8_t);
-STATIC uint8_t   qla1280_device_reset(scsi_qla_host_t *, uint8_t, uint32_t);
-STATIC uint8_t   qla1280_abort_device(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t);
-STATIC uint8_t   qla1280_abort_command(scsi_qla_host_t *, srb_t *),
-#if  QLA1280_64BIT_SUPPORT
-                 qla1280_64bit_start_scsi(scsi_qla_host_t *, srb_t *),
-#endif
-                 qla1280_32bit_start_scsi(scsi_qla_host_t *, srb_t *),
-                 qla1280_abort_isp(scsi_qla_host_t *);
-STATIC void      qla1280_nv_write(scsi_qla_host_t *, uint16_t),
-                 qla1280_nv_delay(scsi_qla_host_t *),
-                 qla1280_poll(scsi_qla_host_t *),
-                 qla1280_reset_adapter(scsi_qla_host_t *),
-                 qla1280_marker(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t, uint8_t),
-                 qla1280_isp_cmd(scsi_qla_host_t *),
-                 qla1280_isr(scsi_qla_host_t *, srb_t **, srb_t **),
-                 qla1280_rst_aen(scsi_qla_host_t *),
-                 qla1280_status_entry(scsi_qla_host_t *, sts_entry_t *, srb_t **,
-                                      srb_t **),
-                 qla1280_error_entry(scsi_qla_host_t *, response_t *, srb_t **,
-                                     srb_t **),
-                 qla1280_restart_queues(scsi_qla_host_t *),
-                 qla1280_abort_queues(scsi_qla_host_t *);
-STATIC uint16_t  qla1280_get_nvram_word(scsi_qla_host_t *, uint32_t),
-                 qla1280_nvram_request(scsi_qla_host_t *, uint32_t),
-                 qla1280_debounce_register(volatile uint16_t *);
-STATIC request_t *qla1280_req_pkt(scsi_qla_host_t *);
-int  qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp);
-STATIC uint8_t qla1280_mem_alloc(scsi_qla_host_t *ha);
-STATIC uint8_t  qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels);
+static int qla1280_initialize_adapter(struct scsi_qla_host *ha);
+static int qla1280_enable_tgt(struct scsi_qla_host *, int);
+static int qla1280_isp_firmware(struct scsi_qla_host *);
+static int qla1280_pci_config(struct scsi_qla_host *);
+static int qla1280_chip_diag(struct scsi_qla_host *);
+static int qla1280_setup_chip(struct scsi_qla_host *);
+static int qla1280_init_rings(struct scsi_qla_host *);
+static int qla1280_nvram_config(struct scsi_qla_host *);
+static int qla1280_mailbox_command(struct scsi_qla_host *,
+				   uint8_t, uint16_t *);
+static int qla1280_bus_reset(struct scsi_qla_host *, int);
+static int qla1280_device_reset(struct scsi_qla_host *, int, int);
+static int qla1280_abort_device(struct scsi_qla_host *, int, int, int);
+static int qla1280_abort_command(struct scsi_qla_host *, srb_t *);
+static int qla1280_abort_isp(struct scsi_qla_host *);
+static int qla1280_64bit_start_scsi(struct scsi_qla_host *, srb_t *);
+static int qla1280_32bit_start_scsi(struct scsi_qla_host *, srb_t *);
+static void qla1280_nv_write(struct scsi_qla_host *, uint16_t);
+static void qla1280_poll(struct scsi_qla_host *);
+static void qla1280_reset_adapter(struct scsi_qla_host *);
+static void qla1280_marker(struct scsi_qla_host *, int, int, int, u8);
+static void qla1280_isp_cmd(struct scsi_qla_host *);
+static void qla1280_isr(struct scsi_qla_host *, srb_t **, srb_t **);
+static void qla1280_rst_aen(struct scsi_qla_host *);
+static void qla1280_status_entry(struct scsi_qla_host *, sts_entry_t *,
+				 srb_t **, srb_t **);
+static void qla1280_error_entry(struct scsi_qla_host *, response_t *,
+				srb_t **, srb_t **);
+static void qla1280_restart_queues(struct scsi_qla_host *);
+static void qla1280_abort_queues(struct scsi_qla_host *);
+static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t);
+static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t);
+static uint16_t qla1280_debounce_register(volatile uint16_t *);
+static request_t *qla1280_req_pkt(struct scsi_qla_host *);
+static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *,
+					   unsigned int);
+static int qla1280_mem_alloc(struct scsi_qla_host *ha);
 
-STATIC uint8_t qla12160_set_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t, nvram160_t *);
-STATIC void qla12160_get_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t);
+static void qla12160_get_target_parameters(struct scsi_qla_host *,
+					   uint32_t, uint32_t, uint32_t);
+
+#if QL1280_LUN_SUPPORT
+static void qla1280_enable_lun(struct scsi_qla_host *, int, int);
+#endif
 
 #if QL1280_TARGET_MODE_SUPPORT
-STATIC void      qla1280_enable_lun(scsi_qla_host_t *, uint8_t, uint32_t),
-                 qla1280_notify_ack(scsi_qla_host_t *, notify_entry_t *),
-                 qla1280_immed_notify(scsi_qla_host_t *, notify_entry_t *),
-                 qla1280_accept_io(scsi_qla_host_t *, ctio_ret_entry_t *),
-#if  QLA1280_64BIT_SUPPORT
-                 qla1280_64bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t,
-                                     paddr32_t *),
-#endif
-                 qla1280_32bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t,
-                                     paddr32_t *),
-                 qla1280_atio_entry(scsi_qla_host_t *, atio_entry_t *),
-                 qla1280_notify_entry(scsi_qla_host_t *, notify_entry_t *);
-#endif  /* QLA1280_TARGET_MODE_SUPPORT */
+static void qla1280_notify_ack(struct scsi_qla_host *, notify_entry_t *);
+static void qla1280_immed_notify(struct scsi_qla_host *, notify_entry_t *);
+static void qla1280_accept_io(struct scsi_qla_host *, ctio_ret_entry_t *);
+static void qla1280_64bit_continue_io(struct scsi_qla_host *, atio_entry_t *,
+				      uint32_t, paddr32_t *);
+static void qla1280_32bit_continue_io(struct scsi_qla_host *, atio_entry_t *,
+				      uint32_t, paddr32_t *);
+static void qla1280_atio_entry(struct scsi_qla_host *, atio_entry_t *);
+static void qla1280_notify_entry(struct scsi_qla_host *, notify_entry_t *);
+#endif				/* QLA1280_TARGET_MODE_SUPPORT */
 
 #ifdef QL_DEBUG_ROUTINES
 /*
  *  Driver Debug Function Prototypes.
  */
-STATIC uint8_t  qla1280_getbyte(uint8_t *);
-STATIC uint16_t qla1280_getword(uint16_t *);
-STATIC uint32_t qla1280_getdword(uint32_t *);
-STATIC void     qla1280_putbyte(uint8_t *, uint8_t),
-                qla1280_putword(uint16_t *, uint16_t),
-                qla1280_putdword(uint32_t *, uint32_t),
-                qla1280_print(caddr_t),
-                qla1280_output_number(uint32_t, uint8_t),
-                qla1280_putc(uint8_t),
-                qla1280_dump_buffer(caddr_t, uint32_t);
-
-char          debug_buff[80];
-#if DEBUG_QLA1280 
-STATIC uint8_t ql_debug_print = 1;
-#else
-STATIC uint8_t ql_debug_print = 0;
-#endif
+static u8 qla1280_getbyte(u8 *);
+static u16 qla1280_getword(u16 *);
+static u32 qla1280_getdword(u32 *);
+static void qla1280_putbyte(u8 *, u8);
+static void qla1280_putword(u16 *, u8);
+static void qla1280_putdword(u32 *, u32);
+static void __qla1280_print_scsi_cmd(Scsi_Cmnd * cmd);
+static void __qla1280_dump_buffer(char *, u32);
 #endif
 
 /*
@@ -412,18 +479,26 @@
  */
 #ifdef MODULE
 static char *options = NULL;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18)
 
 /* insmod qla1280 options=verbose" */
-MODULE_PARM(options, "s");  
+MODULE_PARM(options, "s");
 #endif
+
+MODULE_LICENSE("GPL");
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
 /*
- * Just in case someone uses commas to separate items on the insmod
- * command line, we define a dummy buffer here to avoid having insmod
- * write wild stuff into our code segment
+ * Our directory Entry in /proc/scsi for the user to
+ * access the driver.
  */
-static char dummy_buffer[60] = "Please don't add commas in your insmod command!!\n";
+/* Need to add in proc_fs.h     PROC_SCSI_QL1280 */
+#define PROC_SCSI_QL1280  PROC_SCSI_QLOGICISP
 
+struct proc_dir_entry proc_scsi_qla1280 = {
+	PROC_SCSI_QL1280, 7, "qla1280",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2,
+	0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
 #endif
 
 /* We use the Scsi_Pointer structure that's included with each command
@@ -440,109 +515,89 @@
  *  - SCp.phase --> not used
  */
 
-#define	CMD_SP(Cmnd)		(&(Cmnd)->SCp)
-#define	CMD_XFRLEN(Cmnd)	(Cmnd)->request_bufflen
-#define	CMD_CDBLEN(Cmnd)	(Cmnd)->cmd_len
-#define	CMD_CDBP(Cmnd)		(Cmnd)->cmnd
-#define	CMD_SNSP(Cmnd)		(Cmnd)->sense_buffer
-#define	CMD_SNSLEN(Cmnd)	(sizeof (Cmnd)->sense_buffer)
-#define	CMD_RESULT(Cmnd)	((Cmnd)->result)
-#define	CMD_HANDLE(Cmnd)	((Cmnd)->host_scribble)
+#define	CMD_SP(Cmnd)		&Cmnd->SCp
+#define	CMD_CDBLEN(Cmnd)	Cmnd->cmd_len
+#define	CMD_CDBP(Cmnd)		Cmnd->cmnd
+#define	CMD_SNSP(Cmnd)		Cmnd->sense_buffer
+#define	CMD_SNSLEN(Cmnd)	sizeof(Cmnd->sense_buffer)
+#define	CMD_RESULT(Cmnd)	Cmnd->result
+#define	CMD_HANDLE(Cmnd)	Cmnd->host_scribble
 
 /*****************************************/
 /*   ISP Boards supported by this driver */
 /*****************************************/
-#define QLA1280_VENDOR_ID   0x1077
-#define QLA1080_DEVICE_ID   0x1080
-#define QLA1240_DEVICE_ID   0x1240
-#define QLA1280_DEVICE_ID   0x1280
-#define QLA12160_DEVICE_ID  0x1216
-#define QLA10160_DEVICE_ID  0x1016
-#define NUM_OF_ISP_DEVICES        6
-
-typedef struct _qlaboards 
-{
-   unsigned char   bdName[9];       /* Board ID String */
-   unsigned long   device_id;       /* Device PCI ID   */
-   int   numPorts;                  /* Number of SCSI ports */
-   unsigned short   *fwcode;        /* pointer to FW array         */
-   unsigned long    *fwlen;         /* number of words in array    */
-   unsigned short   *fwstart;       /* start address for F/W       */
-   unsigned char   *fwver;          /* Ptr to F/W version array    */
-} qla_boards_t;
-
-struct _qlaboards   QLBoardTbl[NUM_OF_ISP_DEVICES] = 
-{
-   /* Name ,  Board PCI Device ID,         Number of ports */
-  {"QLA1080 ", QLA1080_DEVICE_ID,           1,        
-               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
-  {"QLA1240 ", QLA1240_DEVICE_ID,           2,       
-               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
-  {"QLA1280 ", QLA1280_DEVICE_ID,           2,      
-               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
-  {"QLA12160 ", QLA12160_DEVICE_ID,          2,      
-               &fw12160i_code01[0],  (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },       
-  {"QLA10160 ", QLA10160_DEVICE_ID,          1,      
-               &fw12160i_code01[0],  (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },       
-  {"        ",                 0,           0}
+
+#define NUM_OF_ISP_DEVICES	6
+
+struct qla_boards {
+	unsigned char bdName[9];	/* Board ID String */
+	unsigned long device_id;	/* Device PCI ID   */
+	int numPorts;		/* Number of SCSI ports */
+	unsigned short *fwcode;	/* pointer to FW array         */
+	unsigned short *fwlen;	/* number of words in array    */
+	unsigned short *fwstart;	/* start address for F/W       */
+	unsigned char *fwver;	/* Ptr to F/W version array    */
+};
+
+struct qla_boards ql1280_board_tbl[NUM_OF_ISP_DEVICES] = {
+	/* Name ,  Board PCI Device ID,         Number of ports */
+	{"QLA12160 ", PCI_DEVICE_ID_QLOGIC_ISP12160, 2,
+	 &fw12160i_code01[0], &fw12160i_length01,
+	 &fw12160i_addr01, &fw12160i_version_str[0]},
+	{"QLA1080 ", PCI_DEVICE_ID_QLOGIC_ISP1080, 1,
+	 &fw1280ei_code01[0], &fw1280ei_length01,
+	 &fw1280ei_addr01, &fw1280ei_version_str[0]},
+	{"QLA1240 ", PCI_DEVICE_ID_QLOGIC_ISP1240, 2,
+	 &fw1280ei_code01[0], &fw1280ei_length01,
+	 &fw1280ei_addr01, &fw1280ei_version_str[0]},
+	{"QLA1280 ", PCI_DEVICE_ID_QLOGIC_ISP1280, 2,
+	 &fw1280ei_code01[0], &fw1280ei_length01,
+	 &fw1280ei_addr01, &fw1280ei_version_str[0]},
+	{"QLA10160 ", PCI_DEVICE_ID_QLOGIC_ISP10160, 1,
+	 &fw12160i_code01[0], &fw12160i_length01,
+	 &fw12160i_addr01, &fw12160i_version_str[0]},
+	{"        ", 0, 0}
 };
 
-static unsigned long qla1280_verbose = 1L;
-static scsi_qla_host_t *qla1280_hostlist = NULL;
-#ifdef QLA1280_PROFILE
+static int qla1280_verbose = 1;
+static struct scsi_qla_host *qla1280_hostlist = NULL;
+#if QLA1280_PROFILE
 static int qla1280_buffer_size = 0;
 static char *qla1280_buffer = NULL;
 #endif
 
-#ifdef QL_DEBUG_LEVEL_3 
-#define ENTER(x)	sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \
-                        qla1280_print(debug_buff);
-#define LEAVE(x)	sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \
-                        qla1280_print(debug_buff);
-#define ENTER_INTR(x)	sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \
-                        qla1280_print(debug_buff);
-#define LEAVE_INTR(x)	sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \
-                        qla1280_print(debug_buff);
-#define DEBUG3(x)	x
-#else
-#define ENTER(x)
-#define LEAVE(x)
-#define ENTER_INTR(x)
-#define LEAVE_INTR(x)
-#define DEBUG3(x)
-#endif
-
-#if  DEBUG_QLA1280  
-#define COMTRACE(x)
-/* #define COMTRACE(x)     qla1280_putc(x); */
+#if DEBUG_QLA1280
+static int ql_debug_print = 1;
+char debug_buff[80];
 #define DEBUG(x)	x
+static int ql_debug_level = 0;
+#define dprintk(level, format, a...)	\
+	if ((ql_debug_level >= level) && ql_debug_print) printk(KERN_DEBUG format, ##a)
+#define qla1280_dump_buffer(level, buf, size)	\
+	if (ql_debug_level >= level) __qla1280_dump_buffer(buf, size)
+#define qla1280_dump_print_cmd(level, cmd)	\
+	if (ql_debug_level >= level) __qla1280_print_scsi_cmd(cmd)
 #else
 #define DEBUG(x)
-#define COMTRACE(x)
+#define ql_debug_level			0
+#define dprintk(level, format, a...)	do{}while(0)
+#define qla1280_dump_buffer(a, b, c)	do{}while(0)
+#define qla1280_print_scsi_cmd(a, b)	do{}while(0)
 #endif
 
-#ifdef QL_DEBUG_LEVEL_2 
-#define DEBUG2(x)	x
-#else
-#define DEBUG2(x)
-#endif
-#define DEBUG5(x)
-
-#if (BITS_PER_LONG==64)
-#   define OFFSET(w)   (((uint64_t) &w) & 0xFF)   /* 256 byte offsets */
-#else
-#   define OFFSET(w)   (((uint32_t) &w) & 0xFF)   /* 256 byte offsets */
-#endif
-
-#define SCSI_BUS_32(scp)   ((scp)->channel)
-#define SCSI_TCN_32(scp)    ((scp)->target)
-#define SCSI_LUN_32(scp)    ((scp)->lun)
+#define ENTER(x)		dprintk(3, "qla1280 : Entering %s()\n", x);
+#define LEAVE(x)		dprintk(3, "qla1280 : Leaving %s()\n", x);
+#define ENTER_INTR(x)		dprintk(3, "qla1280 : Entering %s()\n", x);
+#define LEAVE_INTR(x)		dprintk(3, "qla1280 : Leaving %s()\n", x);
+
+#define SCSI_BUS_32(scp)	scp->channel
+#define SCSI_TCN_32(scp)	scp->target
+#define SCSI_LUN_32(scp)	scp->lun
 
 /****************************************************************************/
 /*  LINUX -  Loadable Module Functions.                                     */
 /****************************************************************************/
 
-
 /*************************************************************************
  *   qla1280_set_info
  *
@@ -554,7 +609,7 @@
 int
 qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
 {
-  return (-ENOSYS);  /* Currently this is a no-op */
+	return -ENOSYS;		/* Currently this is a no-op */
 }
 
 /*************************************************************************
@@ -567,157 +622,296 @@
  *
  * Returns:
  *************************************************************************/
-#ifdef QLA1280_PROFILE
-#define	PROC_BUF	(&qla1280_buffer[size])
-#define LUN_ID       (targ_lun>>(MAX_T_BITS+MAX_L_BITS)),((targ_lun>>MAX_L_BITS)&0xf), targ_lun&0x7 
-#endif
+#define	PROC_BUF	&qla1280_buffer[len]
+
 int
-qla1280_proc_info ( char *buffer, char **start, off_t offset, int length, 
-                    int hostno, int inout)
+qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
+		  int hostno, int inout)
 {
-#ifdef QLA1280_PROFILE
-  struct Scsi_Host *host;
-  scsi_qla_host_t *ha;
-  int    size = 0;
-  int  targ_lun;
-  scsi_lu_t  *up;
-  int   no_devices;
-
-  printk("Entering proc_info 0x%p,0x%lx,0x%x,0x%x\n",buffer,offset,length,hostno);
-  host = NULL;
-  /* find the host they want to look at */
-  for(ha=qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno; ha=ha->next)
-    ;
-
-  if (!ha)
-  {
-    size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
-    if (size > length)
-    {
-      return (size);
-    }
-    else
-    {
-      return (length);
-    }
-  }
-
-  host = ha->host;
-  if (inout == TRUE) /* Has data been written to the file? */ 
-  {
-    return (qla1280_set_info(buffer, length, host));
-  }
-
-  /* compute number of active devices */
-  no_devices = 0;
-  for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++)
-  {
-          if( (up = ha->dev[targ_lun]) == NULL )
-              continue;
-          no_devices++;
-  }
-  /* size = 112 * no_devices; */
-  size = 4096;
-  /* round up to the next page */
-  
-  /* 
-   * if our old buffer is the right size use it otherwise 
-   * allocate a new one.
-   */
-  if (qla1280_buffer_size != size)
-  {
-    /* deallocate this buffer and get a new one */
-    if (qla1280_buffer != NULL) 
-    {
-      kfree(qla1280_buffer);
-      qla1280_buffer_size = 0;
-    }
-    qla1280_buffer = kmalloc(size, GFP_KERNEL);
-  }
-  if (qla1280_buffer == NULL)
-  {
-    size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
-        __LINE__);
-    return size;
-  }
-  qla1280_buffer_size = size;
-
-  size = 0;
-  size += sprintf(PROC_BUF, "Qlogic 1280/1080 SCSI driver version: ");   /* 43 bytes */
-  size += sprintf(PROC_BUF, "%5s, ", QLA1280_VERSION);                         /* 5        */
-  size += sprintf(PROC_BUF, "Qlogic Firmware version: ");                     /* 25       */
-  size += sprintf(PROC_BUF, "%2d.%2d.%2d",_firmware_version[0],           /* 8        */
-                                          ql12_firmware_version[1],
-                                          ql12_firmware_version[2]);
-  size += sprintf(PROC_BUF, "\n");                                             /* 1       */
-                           
-  size += sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", QLBoardTbl[ha->devnum].bdName);
-  size += sprintf(PROC_BUF, "Request Queue = 0x%lx, Response Queue = 0x%lx\n",
-                        ha->request_dma,
-                        ha->response_dma);
-  size += sprintf(PROC_BUF, "Request Queue count= 0x%x, Response Queue count= 0x%x\n",
-                        REQUEST_ENTRY_CNT,
-                        RESPONSE_ENTRY_CNT);
-  size += sprintf(PROC_BUF,"Number of pending commands = 0x%lx\n", ha->actthreads);
-  size += sprintf(PROC_BUF,"Number of queued commands = 0x%lx\n", ha->qthreads);
-  size += sprintf(PROC_BUF,"Number of free request entries = %d\n",ha->req_q_cnt);
-  size += sprintf(PROC_BUF, "\n");                                             /* 1       */
-                        
-  size += sprintf(PROC_BUF, "Attached devices:\n");
-  /* scan for all equipment stats */ 
-  for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++)
-  {
-      if( (up = ha->dev[targ_lun]) == NULL )
-           continue;
-      if( up->io_cnt == 0 )
-      {
-          size += sprintf(PROC_BUF,"(%2d:%2d:%2d) No stats\n",LUN_ID);
-           continue;
-      }
-      /* total reads since boot */
-      /* total writes since boot */
-      /* total requests since boot  */
-      size += sprintf(PROC_BUF, "Total requests %ld,",up->io_cnt);
-      /* current number of pending requests */
-      size += sprintf(PROC_BUF, "(%2d:%2d:%2d) pending requests %d,",LUN_ID,up->q_outcnt);
-      /* avg response time */
-      size += sprintf(PROC_BUF, "Avg response time %ld%%,",(up->resp_time/up->io_cnt)*100);
-      
-      /* avg active time */
-      size += sprintf(PROC_BUF, "Avg active time %ld%%\n",(up->act_time/up->io_cnt)*100);
-  }
-
-  if (size >= qla1280_buffer_size)
-  {
-    printk(KERN_WARNING "qla1280: Overflow buffer in qla1280_proc.c\n");
-  }
-
-  if (offset > size - 1)
-  {
-    kfree(qla1280_buffer);
-    qla1280_buffer = NULL;
-    qla1280_buffer_size = length = 0;
-    *start = NULL;
-  }
-  else
-  {
-    *start = &qla1280_buffer[offset];   /* Start of wanted data */
-    if (size - offset < length)
-    {
-      length = size - offset;
-    }
-  }
+#if QLA1280_PROFILE
+	struct Scsi_Host *host;
+	struct scsi_qla_host *ha;
+	int size = 0;
+	scsi_lu_t *up;
+	int len = 0;
+	struct qla_boards *bdp;
+	uint32_t b, t, l;
+	host = NULL;
+
+	/* Find the host that was specified */
+	for (ha = qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno;
+	     ha = ha->next) ;
+
+	/* if host wasn't found then exit */
+	if (!ha) {
+		size =  sprintf(buffer, "Can't find adapter for host "
+				"number %d\n", hostno);
+		if (size > length) {
+			return size;
+		} else {
+			return 0;
+		}
+	}
+
+	host = ha->host;
+
+	if (inout == TRUE) {	/* Has data been written to the file? */
+		printk(KERN_INFO
+		       "qla1280_proc: has data been written to the file.\n");
+		return qla1280_set_info(buffer, length, host);
+	}
+
+	/*
+	 * if our old buffer is the right size use it otherwise
+	 * allocate a new one.
+	 */
+	if (qla1280_buffer_size != PAGE_SIZE) {
+		/* deallocate this buffer and get a new one */
+		if (qla1280_buffer != NULL) {
+			free_page((unsigned long)qla1280_buffer);
+			qla1280_buffer_size = 0;
+		}
+		qla1280_buffer = (char *)get_free_page(GFP_KERNEL);
+	}
+	if (qla1280_buffer == NULL) {
+		size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
+			       __LINE__);
+		return size;
+	}
+	/* save the size of our buffer */
+	qla1280_buffer_size = PAGE_SIZE;
+
+	/* 3.20 clear the buffer we use for proc display */
+	memset(qla1280_buffer, 0, PAGE_SIZE);
+
+	/* start building the print buffer */
+	bdp = &ql1280_board_tbl[ha->devnum];
+	size = sprintf(PROC_BUF,
+		       "QLogic PCI to SCSI Adapter for ISP 1280/12160:\n"
+		       "        Firmware version: %2d.%02d.%02d, Driver version %s\n",
+		       bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
+		       QLA1280_VERSION);
+
+	len += size;
+
+	size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n",
+		       bdp->bdName);
+	len += size;
+	size = sprintf(PROC_BUF, "Request Queue = 0x%p, Response Queue = 0x%p\n",
+		       (void *)ha->request_dma, (void *)ha->response_dma);
+	len += size;
+	size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response "
+		       "Queue count= 0x%x\n",
+		       REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT);
+	len += size;
+	size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n",
+		       ha->actthreads);
+	len += size;
+	size = sprintf(PROC_BUF, "Number of queued commands = 0x%lx\n",
+		       ha->qthreads);
+	len += size;
+	size = sprintf(PROC_BUF, "Number of free request entries = %d\n",
+		       ha->req_q_cnt);
+	len += size;
+	size = sprintf(PROC_BUF, "\n");	/* 1       */
+	len += size;
+
+	size = sprintf(PROC_BUF, "SCSI device Information:\n");
+	len += size;
+	/* scan for all equipment stats */
+	for (b = 0; b < MAX_BUSES; b++)
+		for (t = 0; t < MAX_TARGETS; t++) {
+			for (l = 0; l < MAX_LUNS; l++) {
+				up = LU_Q(ha, b, t, l);
+				if (up == NULL)
+					continue;
+				/* unused device/lun */
+				if (up->io_cnt == 0 || up->io_cnt < 2)
+					continue;
+				/* total reads since boot */
+				/* total writes since boot */
+				/* total requests since boot  */
+				size = sprintf (PROC_BUF,
+						"(%2d:%2d:%2d): Total reqs %ld,",
+						b, t, l, up->io_cnt);
+				len += size;
+				/* current number of pending requests */
+				size =	sprintf(PROC_BUF, " Pend reqs %d,",
+						up->q_outcnt);
+				len += size;
+#if 0
+				/* avg response time */
+				size = sprintf(PROC_BUF, " Avg resp time %ld%%,",
+					       (up->resp_time / up->io_cnt) *
+					       100);
+				len += size;
+
+				/* avg active time */
+				size = sprintf(PROC_BUF,
+					       " Avg active time %ld%%\n",
+					       (up->act_time / up->io_cnt) * 100);
+#else
+				size = sprintf(PROC_BUF, "\n");
 #endif
+				len += size;
+			}
+			if (len >= qla1280_buffer_size)
+				break;
+		}
+
+	if (len >= qla1280_buffer_size) {
+		printk(KERN_WARNING
+		       "qla1280: Overflow buffer in qla1280_proc.c\n");
+	}
 
-  return (length);
+	if (offset > len - 1) {
+		free_page((unsigned long) qla1280_buffer);
+		qla1280_buffer = NULL;
+		qla1280_buffer_size = length = 0;
+		*start = NULL;
+	} else {
+		*start = &qla1280_buffer[offset];	/* Start of wanted data */
+		if (len - offset < length) {
+			length = len - offset;
+		}
+	}
+	return length;
+#else
+	return 0;
+#endif
 }
 
+/**************************************************************************
+ * qla1280_do_device_init
+ *    This routine will register the device with the SCSI subsystem,
+ *    initialize the host adapter structure and call the device init
+ *    routines.
+ *
+ * Input:
+ *     pdev      - pointer to struct pci_dev for adapter
+ *     template  - pointer to SCSI template
+ *     devnum    - the device number
+ *     bdp       - pointer to struct _qlaboards
+ *     num_hosts - the host number
+ *
+ * Returns:
+ *  host - pointer to SCSI host structure
+ **************************************************************************/
+struct Scsi_Host *
+qla1280_do_device_init(struct pci_dev *pdev,
+		       Scsi_Host_Template * template,
+		       int devnum, struct qla_boards *bdp, int num_hosts)
+{
+	struct Scsi_Host *host;
+	struct scsi_qla_host *ha;
+	struct device_reg *reg;
+
+	printk("qla1x160: Initializing ISP12160 on PCI bus %i, dev %i\n",
+	       pdev->bus->number, PCI_SLOT(pdev->devfn));
+
+	host = scsi_register(template, sizeof(struct scsi_qla_host));
+	if (!host) {
+		printk(KERN_WARNING
+		       "qla1280: Failed to register host, aborting.\n");
+		goto error;
+	}
+
+	scsi_set_pci_device(host, pdev);
+	ha = (struct scsi_qla_host *)host->hostdata;
+	/* Clear our data area */
+	memset(ha, 0, sizeof(struct scsi_qla_host));
+	/* Sanitize the information from PCI BIOS.  */
+	host->irq = pdev->irq;
+	ha->pci_bus = pdev->bus->number;
+	ha->pci_device_fn = pdev->devfn;
+	ha->pdev = pdev;
+	ha->device_id = bdp->device_id;
+	ha->devnum = devnum;	/* specifies microcode load address */
+
+	if (qla1280_mem_alloc(ha)) {
+		printk(KERN_INFO "qla1x160: Failed to get memory\n");
+		goto error;
+	}
+
+	ha->ports = bdp->numPorts;
+	/* following needed for all cases of OS versions */
+	ha->host = host;
+	ha->host_no = host->host_no;
+
+	host->can_queue = 0xfffff;	/* unlimited  */
+	host->cmd_per_lun = 1;
+	host->select_queue_depths = qla1280_select_queue_depth;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+	host->base = (unsigned char *)ha->mmpbase;
+#else
+	host->base = (unsigned long)ha->mmpbase;
+#endif
+	host->max_channel = bdp->numPorts - 1;
+	host->max_lun = MAX_LUNS - 1;
+	host->max_id = MAX_TARGETS;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
+	host->max_sectors = 1024;
+#endif
+
+	ha->instance = num_hosts;
+	host->unique_id = ha->instance;
+
+	if (qla1280_pci_config(ha)) {
+		printk(KERN_INFO "qla1x160: Unable to configure PCI\n");
+		goto error_mem_alloced;
+	}
+
+	/* Disable ISP interrupts. */
+	qla1280_disable_intrs(ha);
+
+	/* Register the IRQ with Linux (sharable) */
+	if (request_irq(host->irq, qla1280_intr_handler, SA_SHIRQ,
+			"qla1280", ha)) {
+		printk("qla1280 : Failed to reserve interrupt %d already "
+		       "in use\n", host->irq);
+		goto error_mem_alloced;
+	}
+#if !MEMORY_MAPPED_IO
+	/* Register the I/O space with Linux */
+	if (check_region(host->io_port, 0xff)) {
+		printk("qla1280 : Failed to reserve i/o region 0x%04lx-0x%04lx"
+		       " already in use\n",
+		       host->io_port, host->io_port + 0xff);
+		free_irq(host->irq, ha);
+		goto error_mem_alloced;
+	}
+
+	request_region(host->io_port, 0xff, "qla1280");
+#endif
+
+	reg = ha->iobase;
+
+	/* load the F/W, read paramaters, and init the H/W */
+	if (qla1280_initialize_adapter(ha)) {
+		printk(KERN_INFO "qla1x160:Failed to initialize adapter\n");
+		goto error_mem_alloced;
+	}
+
+	/* set our host ID  (need to do something about our two IDs) */
+	host->this_id = ha->bus_settings[0].id;
+
+	return host;
+
+ error_mem_alloced:
+	qla1280_mem_free(ha);
+
+ error:
+	if (host) {
+		scsi_unregister(host);
+	}
+	return NULL;
+}
 
 /**************************************************************************
  * qla1280_detect
  *    This routine will probe for Qlogic 1280 SCSI host adapters.
  *    It returns the number of host adapters of a particular
- *    type that were found.	 It also initialize all data necessary for 
+ *    type that were found.	 It also initialize all data necessary for
  *    the driver.  It is passed-in the host number, so that it
  *    knows where its first entry is in the scsi_hosts[] array.
  *
@@ -725,241 +919,162 @@
  *     template - pointer to SCSI template
  *
  * Returns:
- *  num - number of host adapters found.  
+ *  num - number of host adapters found.
  **************************************************************************/
 int
-qla1280_detect(Scsi_Host_Template *template)
+qla1280_detect(Scsi_Host_Template * template)
 {
-    int num_hosts = 0;
-    struct Scsi_Host *host;
-    scsi_qla_host_t *ha, *cur_ha;
-    struct _qlaboards  *bdp;
-    int i, j;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,95)
-    unsigned int piobase;
-    unsigned char pci_bus, pci_devfn, pci_irq;
-    config_reg_t   *cfgp = 0;
-#endif
-    device_reg_t   *reg;
-    char   *cp;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-    struct pci_dev *pdev = NULL;
-#else
-    int index;
-#endif
-
-    ENTER("qla1280_detect");
-
-#ifdef CHECKSRBSIZE
-    if (sizeof(srb_t) > sizeof(Scsi_Pointer) )
-    {
-      printk("Redefine SRB - its too big");
-      return 0;
-    }
+	struct pci_dev *pdev = NULL;
+	struct Scsi_Host *host;
+	struct scsi_qla_host *ha, *cur_ha;
+	struct qla_boards *bdp;
+	uint16_t subsys_vendor, subsys_device;
+	int num_hosts = 0;
+	int devnum = 0;
+
+	ENTER("qla1280_detect");
+
+	if (sizeof(srb_t) > sizeof(Scsi_Pointer)) {
+		printk(KERN_WARNING
+		       "qla1280_detect: [WARNING] srb_t too big\n");
+		return 0;
+	}
+#ifdef MODULE
+	dprintk(1, "DEBUG: qla1280_detect starts at address = %p\n",
+		qla1280_detect);
+	/*
+	 * If we are called as a module, the qla1280 pointer may not be null
+	 * and it would point to our bootup string, just like on the lilo
+	 * command line.  IF not NULL, then process this config string with
+	 * qla1280_setup
+	 *
+	 * Boot time Options
+	 * To add options at boot time add a line to your lilo.conf file like:
+	 * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
+	 * which will result in the first four devices on the first two
+	 * controllers being set to a tagged queue depth of 32.
+	 */
+	if (options)
+		qla1280_setup(options, NULL);
+
+	printk(KERN_WARNING
+	       "qla1280: Please read the file /usr/src/linux/drivers"
+	       "/scsi/README.qla1280\n"
+	       "qla1280: to see the proper way to specify options to the qla1280 "
+	       "module\n"
+	       "qla1280: Specifically, don't use any commas when passing "
+	       "arguments to\n"
+	       "qla1280: insmod or else it might trash certain memory areas.\n");
 #endif
 
-#ifdef MODULE
-	DEBUG(sprintf(debug_buff,"DEBUG: qla1280_detect starts at address = %p\n",qla1280_detect);)
-	DEBUG(qla1280_print(debug_buff);)
-    /*
-    * If we are called as a module, the qla1280 pointer may not be null
-    * and it would point to our bootup string, just like on the lilo
-    * command line.  IF not NULL, then process this config string with
-    * qla1280_setup
-    *
-    * Boot time Options
-    * To add options at boot time add a line to your lilo.conf file like:
-    * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
-    * which will result in the first four devices on the first two
-    * controllers being set to a tagged queue depth of 32.
-    */
-    if(options)
-        qla1280_setup(options, NULL);
-    if(dummy_buffer[0] != 'P')
-        printk(KERN_WARNING "qla1280: Please read the file /usr/src/linux/drivers"
-                "/scsi/README.qla1280\n"
-                "qla1280: to see the proper way to specify options to the qla1280 "
-                "module\n"
-                "qla1280: Specifically, don't use any commas when passing arguments to\n"
-                "qla1280: insmod or else it might trash certain memory areas.\n");
-#endif
-
-    if ((int) !pcibios_present())
-    {
-		printk("scsi: PCI not present\n");
+	if (!pci_present()) {
+		printk(KERN_INFO "scsi: PCI not present\n");
 		return 0;
-    } /* end of IF */
-    bdp = &QLBoardTbl[0];
-    qla1280_hostlist = NULL;
-#if 0
-    template->proc_dir = &proc_scsi_qla1280;
+	}
+
+	bdp = &ql1280_board_tbl[0];
+	qla1280_hostlist = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+	template->proc_dir = &proc_scsi_qla1280;
 #else
-    template->proc_name = "qla1280";
+	template->proc_name = "qla1280";
 #endif
-    
-	/* Try and find each different type of adapter we support */
-	for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-		while ((pdev = pci_find_device(QLA1280_VENDOR_ID,
-			bdp->device_id, pdev ) ))  {
-		if (pci_enable_device(pdev)) continue;
-#else
-		while (!(pcibios_find_device(QLA1280_VENDOR_ID,
-			bdp->device_id,
-			index++, &pci_bus, &pci_devfn)) )  {
-#endif
-                /* found a adapter */
-		host = scsi_register(template, sizeof(scsi_qla_host_t));
-                if (!host) { 
-			printk(KERN_WARNING "qla1280: Failed to register host, aborting.\n");
-                        return 0;
-                }
-		scsi_set_pci_device(host, pdev);
-		ha = (scsi_qla_host_t *) host->hostdata;
-		/* Clear our data area */
-		for( j =0, cp = (char *)ha;  j < sizeof(scsi_qla_host_t); j++)
-			*cp = 0;
-		/* Sanitize the information from PCI BIOS.  */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-		host->irq = pdev->irq;
-		host->io_port = pci_resource_start(pdev, 0);
-		ha->pci_bus = pdev->bus->number;
-		ha->pci_device_fn = pdev->devfn;
-		ha->pdev = pdev;
-#else
-		pcibios_read_config_byte(pci_bus, pci_devfn, OFFSET(cfgp->interrupt_line), &pci_irq);
-		pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase);
-		host->irq = pci_irq;
-		host->io_port = (unsigned int) piobase;
-		host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
-		ha->pci_bus = pci_bus;
-		ha->pci_device_fn = pci_devfn;
-#endif
-		ha->device_id = bdp->device_id;
-    
-                ha->devnum = i;
-		if( qla1280_mem_alloc(ha) ) {
-			printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n");
-		}
-                
-                ha->ports = bdp->numPorts; 
-                ha->iobase = (device_reg_t *) host->io_port;
-                ha->host = host;
-                ha->host_no = host->host_no;
-
-                /* load the F/W, read paramaters, and init the H/W */
-                if (qla1280_initialize_adapter(ha))
-                {
-
-                    printk(KERN_INFO "qla1280: Failed to initialized adapter\n");
-                    qla1280_mem_free(ha);
-                    scsi_unregister(host);
-                    continue;
-                }
-                
-                host->max_channel = bdp->numPorts-1; 
-                ha->instance = num_hosts;
-		/* Register our resources with Linux */
-		if( qla1280_register_with_Linux(ha, bdp->numPorts-1) ) {
-			printk(KERN_INFO "qla1280: Failed to register our resources\n");
-			qla1280_mem_free(ha);
-			scsi_unregister(host);
-			continue;
-		}
 
+	/* 3.20 */
+	/* First Initialize QLA12160 on PCI Bus 1 Dev 2 */
+	while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, bdp->device_id,
+				       PCI_ANY_ID, PCI_ANY_ID, pdev))) {
 
-                reg = ha->iobase;
-                /* Disable ISP interrupts. */
-		qla1280_disable_intrs(ha);
+		/* find QLA12160 device on PCI bus=1 slot=2 */
+		if ((pdev->bus->number != 1) || (PCI_SLOT(pdev->devfn) != 2))
+			continue;
 
-                /* Insure mailbox registers are free. */
-                WRT_REG_WORD(&reg->semaphore, 0);
-                WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
-                WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
-
-                /* Enable chip interrupts. */
-		qla1280_enable_intrs(ha);
-               
-                /* Insert new entry into the list of adapters */
-                ha->next = NULL;
-                if( qla1280_hostlist == NULL )
-                {
-                    cur_ha = qla1280_hostlist = ha;
-                }
-                else
-                {
-                    cur_ha = qla1280_hostlist;
-                    while( cur_ha->next != NULL )
-                        cur_ha = cur_ha->next;
-                    cur_ha->next = ha;
-                }
-                num_hosts++;
-            }  /* end of WHILE */
-        } /* end of FOR */
+		/* Bypass all AMI SUBSYS VENDOR IDs */
+		if (pdev->subsystem_vendor == PCI_VENDOR_ID_AMI) {
+			printk(KERN_INFO
+			       "qla1x160: Skip AMI SubSys Vendor ID Chip\n");
+			continue;
+		}
 
-    LEAVE("qla1280_detect");
-    return num_hosts; 
-}
+		if (pci_enable_device(pdev))
+			goto find_devices;
 
-/**************************************************************************
-*   qla1280_register_with_Linux
-*
-* Description:
-*   Free the passed in Scsi_Host memory structures prior to unloading the
-*   module.
-*
-* Input:
-*     ha - pointer to host adapter structure
-*     maxchannels - MAX number of channels.
-*
-* Returns:
-*  0 - Sucessfully reserved resources.
-*  1 - Failed to reserved a resource.
-**************************************************************************/
-STATIC uint8_t  qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels)
-{
-
-	struct Scsi_Host *host = ha->host;
+		host = qla1280_do_device_init(pdev, template, devnum,
+					      bdp, num_hosts);
+		if (!host)
+			continue;
+		ha = (struct scsi_qla_host *)host->hostdata;
 
-	host->can_queue = 0xfffff;  /* unlimited  */
-	host->cmd_per_lun = 1;
-       host->select_queue_depths = qla1280_select_queue_depth;
-	host->n_io_port = 0xFF;
-	host->base = (unsigned long) ha->mmpbase;
-	host->max_channel = maxchannels; 
-       host->max_lun = MAX_LUNS-1; 
-	host->unique_id = ha->instance;
-       host->max_id = MAX_TARGETS; 
-       host->unique_id = ha->instance;
+		/* this preferred device will always be the first one found */
+		cur_ha = qla1280_hostlist = ha;
+		num_hosts++;
+	}
 
-	/* set our host ID  (need to do something about our two IDs) */
-       host->this_id = ha->bus_settings[0].id;
-       /* Register the IRQ with Linux (sharable) */
-       if ( request_irq(host->irq, qla1280_intr_handler, SA_INTERRUPT| SA_SHIRQ, "qla1280", ha))
-       {
-          printk("qla1280 : Failed to reserved interrupt %d already in use\n", host->irq);
-          qla1280_mem_free(ha);
-          scsi_unregister(host);
-	     return 1;
-       }
-
-       /* Register the I/O space with Linux */
-       if (check_region(host->io_port, 0xff))
-       {
-           printk("qla1280 : Failed to reserved i/o region 0x%04lx-0x%04lx already in use\n",
-              host->io_port, host->io_port + 0xff);
-           free_irq(host->irq, NULL);
-           qla1280_mem_free(ha);
-           scsi_unregister(host);
-	     return 1;
-       }
+ find_devices:
 
-       request_region(host->io_port, 0xff, "qla1280");
+	pdev = NULL;
+	/* Try and find each different type of adapter we support */
+	for (devnum = 0; bdp->device_id != 0 && devnum < NUM_OF_ISP_DEVICES;
+	     devnum++, bdp++) {
+		/* PCI_SUBSYSTEM_IDS supported */
+		while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC,
+					       bdp->device_id, PCI_ANY_ID,
+					       PCI_ANY_ID, pdev))) {
+			if (pci_enable_device(pdev))
+				continue;
+			/* found an adapter */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18)
+			subsys_vendor = pdev->subsystem_vendor;
+			subsys_device = pdev->subsystem_device;
+#else
+			pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID,
+					     &subsys_vendor);
+			pci_read_config_word(pdev, PCI_SUBSYSTEM_ID,
+					     &subsys_device);
+#endif
+			/*
+			 * skip QLA12160 already initialized on
+			 * PCI Bus 1 Dev 2 since we already initialized
+			 * and presented it
+			 */
+			if ((bdp->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160)&&
+			    (pdev->bus->number == 1) &&
+			    (PCI_SLOT(pdev->devfn) == 2))
+				continue;
+
+			/* Bypass all AMI SUBSYS VENDOR IDs */
+			if (subsys_vendor == PCI_VENDOR_ID_AMI) {
+				printk(KERN_INFO
+				       "qla1x160: Skip AMI SubSys Vendor ID Chip\n");
+				continue;
+			}
+			printk(KERN_INFO
+			       "qla1x160: Supported Device Found VID=%x "
+			       "DID=%x SSVID=%x SSDID=%x\n", pdev->vendor,
+			       pdev->device, subsys_vendor, subsys_device);
+
+			host = qla1280_do_device_init(pdev, template,
+						      devnum, bdp, num_hosts);
+			if (!host)
+				continue;
+			ha = (struct scsi_qla_host *)host->hostdata;
+
+			if (qla1280_hostlist == NULL) {
+				cur_ha = qla1280_hostlist = ha;
+			} else {
+				cur_ha = qla1280_hostlist;
+				while (cur_ha->next != NULL)
+					cur_ha = cur_ha->next;
+				cur_ha->next = ha;
+			}
+			num_hosts++;
+		}		/* end of WHILE */
+	}			/* end of FOR */
 
-	return 0;
+	LEAVE("qla1280_detect");
+	return num_hosts;
 }
 
-
 /**************************************************************************
  *   qla1280_release
  *   Free the passed in Scsi_Host memory structures prior to unloading the
@@ -968,38 +1083,33 @@
 int
 qla1280_release(struct Scsi_Host *host)
 {
-    scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata;
+	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
 
-    ENTER("qla1280_release");
+	ENTER("qla1280_release");
 
-    if( !ha->flags.online )
-        return(0);
-
-    /* turn-off interrupts on the card */
-    WRT_REG_WORD(&ha->iobase->ictrl, 0);
+	if (!ha->flags.online)
+		return 0;
 
-    /* Detach interrupts */
-    if(host->irq)
-        free_irq(host->irq, ha);
+	/* turn-off interrupts on the card */
+	WRT_REG_WORD(&ha->iobase->ictrl, 0);
 
-    /* release io space registers  */
-    if( host->io_port )
-        release_region(host->io_port, 0xff);
+	/* Detach interrupts */
+	if (host->irq)
+		free_irq(host->irq, ha);
 
 #if MEMORY_MAPPED_IO
-    if(ha->mmpbase)
-    {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-        vfree((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));
+	if (ha->mmpbase)
+		iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK));
 #else
-        iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));
-#endif
-    }
-#endif /* MEMORY_MAPPED_IO */
-    qla1280_mem_free(ha);
+	/* release io space registers  */
+	if (host->io_port)
+		release_region(host->io_port, 0xff);
+#endif				/* MEMORY_MAPPED_IO */
 
-    ENTER("qla1280_release");
-    return(0);
+	qla1280_mem_free(ha);
+
+	ENTER("qla1280_release");
+	return 0;
 }
 
 /**************************************************************************
@@ -1009,22 +1119,22 @@
 const char *
 qla1280_info(struct Scsi_Host *host)
 {
-    static char qla1280_buffer[125];
-    char *bp;
-    scsi_qla_host_t *ha;
-    qla_boards_t   *bdp; 
-
-    bp = &qla1280_buffer[0];
-    ha = (scsi_qla_host_t *)host->hostdata;
-    bdp = &QLBoardTbl[ha->devnum];
-    memset(bp, 0, sizeof(qla1280_buffer));
-    sprintf(bp,
-            "QLogic %sPCI to SCSI Host Adapter: bus %d device %d irq %d\n"
-            "       Firmware version: %2d.%02d.%02d, Driver version %s",
-            (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq,
-            bdp->fwver[0],bdp->fwver[1],bdp->fwver[2],
-            QLA1280_VERSION);
-    return(bp);
+	static char qla1280_scsi_name_buffer[125];
+	char *bp;
+	struct scsi_qla_host *ha;
+	struct qla_boards *bdp;
+
+	bp = &qla1280_scsi_name_buffer[0];
+	ha = (struct scsi_qla_host *)host->hostdata;
+	bdp = &ql1280_board_tbl[ha->devnum];
+	memset(bp, 0, sizeof(qla1280_scsi_name_buffer));
+	sprintf (bp,
+		 "QLogic %s PCI to SCSI Host Adapter: bus %d device %d irq %d\n"
+		 "       Firmware version: %2d.%02d.%02d, Driver version %s",
+		 &bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3,
+		 host->irq, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
+		 QLA1280_VERSION);
+	return bp;
 }
 
 /**************************************************************************
@@ -1039,86 +1149,71 @@
  * context which is a big NO! NO!.
  **************************************************************************/
 int
-qla1280_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
+qla1280_queuecommand(Scsi_Cmnd * cmd, void (*fn) (Scsi_Cmnd *))
 {
-    scsi_qla_host_t *ha;
-    srb_t  *sp;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-    struct Scsi_Host *host;
-    uint32_t        b, t, l;
-    scsi_lu_t       *q;
-    u_long          handle;
-
-    ENTER("qla1280_queuecommand");
-    COMTRACE('C') 
-
-    host = cmd->host;
-    ha = (scsi_qla_host_t *) host->hostdata;
-
-    /* send command to adapter */
-    sp = (srb_t *) CMD_SP(cmd);
-    sp->cmd =  cmd;
-    cmd->scsi_done = fn;
-    if (cmd->flags == 0)  /* new command */
-    {
-        sp->flags = 0;
-    }
-
-    DEBUG5(qla1280_print_scsi_cmd(cmd));
-
-    /* Generate LU queue on bus, target, LUN */
-    b = SCSI_BUS_32(cmd);
-    t = SCSI_TCN_32(cmd);
-    l = SCSI_LUN_32(cmd);
-    if((q = LU_Q(ha, b, t, l)) == NULL )
-    {
-        DRIVER_LOCK
-        if( (q = (scsi_lu_t *)KMALLOC(sizeof(struct scsi_lu))) )
-        {
-           LU_Q(ha, b, t, l) = q;
-           BZERO(q,sizeof(struct scsi_lu));
-           DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q));
-           DEBUG(qla1280_print(debug_buff));
-           DRIVER_UNLOCK
-        }
-        else
-        {
-            CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
-            qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
-
-            schedule_task(&ha->run_qla_bh);
-            ha->flags.dpc_sched = TRUE;
-            DRIVER_UNLOCK
-            return(0);
-        }
-    }
-    /* Set an invalid handle until we issue the command to ISP */
-    /* then we will set the real handle value.                 */
-    handle = INVALID_HANDLE;  
-    CMD_HANDLE(cmd) = (unsigned char *)handle;
-
-    /* Bookkeeping information */
-    sp->r_start = jiffies;       /* time the request was received */
-    sp->u_start = 0;              
-
-    /* add the command to our queue */
-    ha->qthreads++;
-    qla1280_putq_t(q,sp);
-    
-    DEBUG(sprintf(debug_buff,"qla1280_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle));
-    DEBUG(qla1280_print(debug_buff));
-
-    /* send command to adapter */
-    DRIVER_LOCK
-        if (q->q_outcnt == 0)
-            qla1280_restart_queues(ha);
-    DRIVER_UNLOCK
-    
-    
-    LEAVE("qla1280_queuecommand");
-    return (0);
+	struct scsi_qla_host *ha;
+	srb_t *sp;
+	struct Scsi_Host *host;
+	int bus, target, lun;
+	scsi_lu_t *q;
+
+	/*ENTER("qla1280_queuecommand");
+	 */
+
+	host = cmd->host;
+	ha = (struct scsi_qla_host *)host->hostdata;
+
+	/* send command to adapter */
+	sp = (srb_t *)CMD_SP(cmd);
+	sp->cmd = cmd;
+	cmd->scsi_done = fn;
+	if (cmd->flags == 0) {	/* new command */
+		sp->flags = 0;
+	}
+
+	qla1280_print_scsi_cmd(5, cmd);
+
+	/* Generate LU queue on bus, target, LUN */
+	bus = SCSI_BUS_32(cmd);
+	target = SCSI_TCN_32(cmd);
+	lun = SCSI_LUN_32(cmd);
+	if ((q = LU_Q(ha, bus, target, lun)) == NULL) {
+		if ((q = (scsi_lu_t *)kmalloc(sizeof(struct scsi_lu),
+					  GFP_ATOMIC))) {
+			LU_Q(ha, bus, target, lun) = q;
+			memset(q, 0, sizeof(struct scsi_lu));
+			dprintk(1, "Allocate new device queue 0x%p\n",
+				(void *)q);
+		} else {
+			CMD_RESULT(cmd) = DID_BUS_BUSY << 16;
+			qla1280_done_q_put(sp, &ha->done_q_first,
+					   &ha->done_q_last);
+/* 3.22 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 3.22 */
+			queue_task(&ha->run_qla_bh, &tq_scheduler);
+#else				/* 3.22 */
+			schedule_task(&ha->run_qla_bh);	/* 3.22 */
+#endif				/* 3.22 */
+			return 0;
+		}
+	}
+	/* Set an invalid handle until we issue the command to ISP */
+	/* then we will set the real handle value.                 */
+	CMD_HANDLE(cmd) = (unsigned char *)INVALID_HANDLE;
+
+	/* add the command to our queue */
+	ha->qthreads++;
+	qla1280_putq_t(q, sp);
+
+	dprintk(1, "qla1280_QC: t=%x CDB=%x I/OSize=0x%x haQueueCount=0x%lx\n",
+		target, cmd->cmnd[0], cmd->request_bufflen, ha->qthreads);
+
+	/* send command to adapter */
+	if (q->q_outcnt == 0)
+		qla1280_restart_queues(ha);
+
+	/*LEAVE("qla1280_queuecommand"); */
+	return 0;
 }
 
 /**************************************************************************
@@ -1126,150 +1221,267 @@
  *     Abort the speciifed SCSI command(s).
  **************************************************************************/
 int
-qla1280_abort(Scsi_Cmnd *cmd)
+qla1280_abort(Scsi_Cmnd * cmd)
 {
-    scsi_qla_host_t *ha;
-    srb_t  *sp;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-    struct Scsi_Host *host;
-    uint32_t        b, t, l;
-    scsi_lu_t       *q;
-    int return_status = SCSI_ABORT_SUCCESS;
-    int found = 0;
-    int i;
-    u_long     handle;
-    u_short    data;
-
-    ENTER("qla1280_abort");
-    COMTRACE('A')
-    ha = (scsi_qla_host_t *) cmd->host->hostdata;
-    host = cmd->host;
-    DRIVER_LOCK
-
-    /* Get the SCSI request ptr */
-    sp = (srb_t *) CMD_SP(cmd);
-    handle = (u_long) CMD_HANDLE(cmd);
-    if (qla1280_verbose)
-        printk("scsi(%d): ABORT Command=0x%lx, handle=0x%lx\n",(int)ha->host_no,(long)cmd,handle);
-
-    /* Check for pending interrupts. */
-    if( handle == 0L )
-    {
-    COMTRACE('a')
-        /* we never got this command */
-        printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
-        DRIVER_UNLOCK
-                return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */
-    }
-    data = qla1280_debounce_register(&ha->iobase->istatus);
-    if( !(ha->flags.in_isr) && (data & RISC_INT) )
-    {
-        /* put any pending command in done queue */
-        qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-    }
-
-    handle = (u_long) CMD_HANDLE(cmd);
-
-    /* Generate LU queue on bus, target, LUN */
-    b = SCSI_BUS_32(cmd);
-    t = SCSI_TCN_32(cmd);
-    l = SCSI_LUN_32(cmd);
-    if((q = LU_Q(ha, b, t, l)) == NULL )
-    {
-    COMTRACE('a')
-        /* No lun queue -- command must not be active */
-        DRIVER_UNLOCK
-        printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the specified device\n",(int)b,(int)t,(int)l);
-        return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */
-    }
+	struct scsi_qla_host *ha;
+	srb_t *sp;
+	struct Scsi_Host *host;
+	unsigned int bus, target, lun;
+	scsi_lu_t *q;
+	int return_status = SCSI_ABORT_SUCCESS;
+	int found = 0;
+	int i;
+	unsigned char *handle;
+	u16 data;
+
+	ENTER("qla1280_abort");
+	ha = (struct scsi_qla_host *)cmd->host->hostdata;
+	host = cmd->host;
+
+	/* Get the SCSI request ptr */
+	sp = (srb_t *)CMD_SP(cmd);
+	handle = CMD_HANDLE(cmd);
+	if (qla1280_verbose)
+		printk(KERN_ERR "scsi(%li): ABORT Command=0x%p, handle=0x%p\n",
+		       ha->host_no, (void *) cmd, (void *) handle);
+
+	/* Check for pending interrupts. */
+	if (handle == NULL) {
+		/* we never got this command */
+		printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
+		return SCSI_ABORT_NOT_RUNNING;	/* no action - we don't have command */
+	}
+	data = qla1280_debounce_register(&ha->iobase->istatus);
+	/*
+	 * The io_request_lock is held when the reset handler is called, hence
+	 * the interrupt handler cannot be running in parallel as it also
+	 * grabs the lock. No reason to play funny games with set_bit() in
+	 * order to test for interrupt handler entry as the driver used to
+	 * do here.
+	 * /Jes
+	 */
+	if (data & RISC_INT) {
+		/* put any pending command in done queue */
+		qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
+	}
 
+	/*
+	 * This seems unnecessary, it's not used below! / Jes
+	 */
+#ifdef UNUSED
+	handle = CMD_HANDLE(cmd);
+#endif
+
+	/* Generate LU queue on bus, target, LUN */
+	bus = SCSI_BUS_32(cmd);
+	target = SCSI_TCN_32(cmd);
+	lun = SCSI_LUN_32(cmd);
+	if ((q = LU_Q(ha, bus, target, lun)) == NULL) {
+		/* No lun queue -- command must not be active */
+		printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the "
+		       "specified device\n", bus, target, lun);
+		return SCSI_ABORT_NOT_RUNNING;	/* no action - we don't have command */
+	}
 #if AUTO_ESCALATE_ABORT
-    if ( (sp->flags & SRB_ABORTED) )
-    {
-        DRIVER_UNLOCK
-        DEBUG(qla1280_print("qla1280_abort: Abort escalayted - returning SCSI_ABORT_SNOOZE.\n\r"));
-        return(SCSI_ABORT_SNOOZE);
-    }
-#endif
-
-    if ( (sp->flags & SRB_ABORT_PENDING) )
-    {
-    COMTRACE('a')
-        DRIVER_UNLOCK
-        if( qla1280_verbose  )
-            printk("scsi(): Command has a pending abort message - ABORT_PENDING.\n");
-        DEBUG(qla1280_print("qla1280: Command has a pending abort message - ABORT_PENDING.\n\r"));
-        return(SCSI_ABORT_PENDING);
-    }
-
-#if  STOP_ON_ABORT 
-    printk("Scsi layer issued a ABORT command= 0x%x\n",(int)cmd);
-    DEBUG2(qla1280_print_scsi_cmd(cmd));
-#endif
-
-    ha->flags.in_abort = TRUE;
-    /*
-    * Normally, would would need to search our queue for the specified command
-    * but; since our sp contains the cmd ptr, we can just remove it from our
-    * LUN queue.
-    */
-    if( !(sp->flags&SRB_SENT) )
-    { 
-        found++;
-        if( qla1280_verbose  )
-            printk("scsi(): Command returned from queue aborted.\n");
-        DEBUG(qla1280_print("qla1280: Command returned from queue aborted.\n\r"));
-        /* Remove srb from SCSI LU queue. */
-        qla1280_removeq(q, sp);
-        sp->flags |=  SRB_ABORTED;
-        CMD_RESULT(cmd) = DID_ABORT << 16; 
-        qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
-        return_status = SCSI_ABORT_SUCCESS;
-    }
-    else
-    {  /* find the command in our active list */
-        for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++)
-        {
-            if( sp == ha->outstanding_cmds[i] )
-            {
-                found++;
-                DEBUG(qla1280_print("qla1280: RISC aborting command.\n\r"));
-                qla1280_abort_command(ha,sp);
-                return_status = SCSI_ABORT_PENDING;
-                break;
-            }
-        }
-    }
-
-#if  STOP_ON_ABORT 
-    qla1280_panic("qla1280_abort",ha->host);
-#endif
-    if ( found == 0 )
-        return_status = SCSI_ABORT_NOT_RUNNING;  /* no action - we don't have command */
-
-    DEBUG(sprintf(debug_buff, "qla1280_abort: Aborted status returned = 0x%x.\n\r",return_status));
-    DEBUG(qla1280_print(debug_buff));
-
-    if( ha->done_q_first )
-       qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-    if ( found )
-    {
-        qla1280_restart_queues(ha);
-    }
-    ha->flags.in_abort = FALSE;
-    DRIVER_UNLOCK
-
-    LEAVE("qla1280_abort");
-    COMTRACE('a')
-    return(return_status);
+	if ((sp->flags & SRB_ABORTED)) {
+		dprintk(1, "qla1280_abort: Abort escalayted - returning "
+			"SCSI_ABORT_SNOOZE.\n");
+		return SCSI_ABORT_SNOOZE;
+	}
+#endif
+
+	if ((sp->flags & SRB_ABORT_PENDING)) {
+		if (qla1280_verbose)
+			printk(KERN_WARNING
+			       "scsi(): Command has a pending abort "
+			       "message - ABORT_PENDING.\n");
+
+		return SCSI_ABORT_PENDING;
+	}
+#if STOP_ON_ABORT
+	printk(KERN_WARNING "Scsi layer issued a ABORT command= 0x%p\n", cmd);
+	qla1280_print_scsi_cmd(2, cmd);
+#endif
+
+	/*
+	 * Normally, would would need to search our queue for the specified command
+	 * but; since our sp contains the cmd ptr, we can just remove it from our
+	 * LUN queue.
+	 */
+	if (!(sp->flags & SRB_SENT)) {
+		found++;
+		if (qla1280_verbose)
+			printk(KERN_WARNING
+			       "scsi(): Command returned from queue "
+			       "aborted.\n");
+
+		/* Remove srb from SCSI LU queue. */
+		qla1280_removeq(q, sp);
+		sp->flags |= SRB_ABORTED;
+		CMD_RESULT(cmd) = DID_ABORT << 16;
+		qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
+		return_status = SCSI_ABORT_SUCCESS;
+	} else {		/* find the command in our active list */
+		for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
+			if (sp == ha->outstanding_cmds[i]) {
+				found++;
+				dprintk(1,
+					"qla1280: RISC aborting command.\n");
+				qla1280_abort_command(ha, sp);
+				return_status = SCSI_ABORT_PENDING;
+				break;
+			}
+		}
+	}
+
+#if STOP_ON_ABORT
+	qla1280_panic("qla1280_abort", ha->host);
+#endif
+	if (found == 0)
+		return_status = SCSI_ABORT_NOT_RUNNING;	/* no action - we don't have command */
+
+	dprintk(1, "qla1280_abort: Aborted status returned = 0x%x.\n",
+		return_status);
+
+	if (ha->done_q_first)
+		qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
+	if (found)
+		qla1280_restart_queues(ha);
+
+	LEAVE("qla1280_abort");
+	return return_status;
+}
+
+int
+qla1280_new_abort(Scsi_Cmnd * cmd)
+{
+	struct scsi_qla_host *ha;
+	srb_t *sp;
+	struct Scsi_Host *host;
+	int bus, target, lun;
+	scsi_lu_t *q;
+	unsigned long cpu_flags;
+	int return_status = SCSI_ABORT_SUCCESS;
+	int found = 0;
+	int i;
+	unsigned char *handle;
+	u16 data;
+
+	ENTER("qla1280_abort");
+	host = cmd->host;
+	ha = (struct scsi_qla_host *)host->hostdata;
+
+	/* Get the SCSI request ptr */
+	sp = (srb_t *) CMD_SP(cmd);
+	handle = CMD_HANDLE(cmd);
+	if (qla1280_verbose)
+		printk(KERN_ERR "scsi(%li): ABORT Command=0x%p, handle=0x%p\n",
+		       ha->host_no, cmd, handle);
+
+	/* Check for pending interrupts. */
+	if (handle == NULL) {
+		/* we never got this command */
+		printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
+		return SUCCESS;	/* no action - we don't have command */
+	}
+
+	spin_lock_irqsave (ha->host->host_lock, cpu_flags);
+	data = qla1280_debounce_register(&ha->iobase->istatus);
+	/*
+	 * We grab the host lock in the interrupt handler to
+	 * prevent racing here.
+	 *
+	 * Then again, running the interrupt handler from here is somewhat
+	 * questionable.
+	 * /Jes
+	 */
+	if (data & RISC_INT) {
+		/* put any pending command in done queue */
+		qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
+	}
+
+	/* Generate LU queue on bus, target, LUN */
+	bus = SCSI_BUS_32(cmd);
+	target = SCSI_TCN_32(cmd);
+	lun = SCSI_LUN_32(cmd);
+	if ((q = LU_Q(ha, bus, target, lun)) == NULL) {
+		/* No lun queue -- command must not be active */
+		printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the "
+		       "specified device\n", bus, target, lun);
+		return_status = SUCCESS;	/* no action - we don't have command */
+		goto out;
+	}
+
+	if ((sp->flags & SRB_ABORT_PENDING)) {
+		if (qla1280_verbose)
+			printk(KERN_WARNING
+			       "scsi(): Command has a pending abort "
+			       "message - ABORT_PENDING.\n");
+
+		return_status = SCSI_ABORT_PENDING;
+		goto out;
+	}
+#if STOP_ON_ABORT
+	printk(KERN_WARNING "Scsi layer issued a ABORT command= 0x%p\n", cmd);
+	qla1280_print_scsi_cmd(2, cmd);
+#endif
+
+	/*
+	 * Normally, would would need to search our queue for the specified command
+	 * but; since our sp contains the cmd ptr, we can just remove it from our
+	 * LUN queue.
+	 */
+	if (!(sp->flags & SRB_SENT)) {
+		found++;
+		if (qla1280_verbose)
+			printk(KERN_WARNING
+			       "scsi(): Command returned from queue "
+			       "aborted.\n");
+
+		/* Remove srb from SCSI LU queue. */
+		qla1280_removeq(q, sp);
+		sp->flags |= SRB_ABORTED;
+		CMD_RESULT(cmd) = DID_ABORT << 16;
+		qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
+		return_status = SUCCESS;
+	} else {		/* find the command in our active list */
+		for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
+			if (sp == ha->outstanding_cmds[i]) {
+				found++;
+				dprintk(1,
+					"qla1280: RISC aborting command.\n");
+				qla1280_abort_command(ha, sp);
+				return_status = SCSI_ABORT_PENDING;
+				break;
+			}
+		}
+	}
+
+#if STOP_ON_ABORT
+	qla1280_panic("qla1280_abort", ha->host);
+#endif
+	if (found == 0)
+		return_status = SUCCESS;	/* no action - we don't have the command */
+
+	dprintk(1, "qla1280_abort: Aborted status returned = 0x%x.\n",
+		return_status);
+
+	if (ha->done_q_first)
+		qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
+	if (found)
+		qla1280_restart_queues(ha);
+
+ out:
+	spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
+
+	LEAVE("qla1280_abort");
+	return return_status;
 }
 
 /**************************************************************************
  * qla1200_reset
  *    The reset function will reset the SCSI bus and abort any executing
- *    commands. 
+ *    commands.
  *
  * Input:
  *      cmd = Linux SCSI command packet of the command that cause the
@@ -1277,7 +1489,7 @@
  *      flags = SCSI bus reset option flags (see scsi.h)
  *
  * Returns:
- *      DID_RESET in cmd.host_byte of aborted command(s) 
+ *      DID_RESET in cmd.host_byte of aborted command(s)
  *
  * Note:
  *      Resetting the bus always succeeds - is has to, otherwise the
@@ -1286,354 +1498,301 @@
  *      the SCSI bus reset line.
  **************************************************************************/
 int
-qla1280_reset(Scsi_Cmnd *cmd, unsigned int flags)
+qla1280_reset(Scsi_Cmnd * cmd, unsigned int flags)
 {
-    scsi_qla_host_t *ha;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-    uint32_t        b, t, l;
-    srb_t  *sp;
-    typedef enum
-    {
-        ABORT_DEVICE = 1, 
-                DEVICE_RESET = 2, 
-                BUS_RESET    = 3, 
-                ADAPTER_RESET= 4,
-                RESET_DELAYED= 5,
-                FAIL         = 6
-    } action_t;
-    action_t     action = ADAPTER_RESET;
-    u_short    data;
-    scsi_lu_t       *q;
-    int result;
-
-
-    ENTER("qla1280_reset");
-    COMTRACE('R')
-    if (qla1280_verbose)
-        printk("scsi(): Resetting Cmnd=0x%lx, Handle=0x%lx, flags=0x%x\n",(long)cmd,(long)CMD_HANDLE(cmd),flags);
-    if ( cmd == NULL )
-    {
-        printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd "
-                "pointer, failing.\n");
-        return(SCSI_RESET_SNOOZE);
-    }
-    ha = (scsi_qla_host_t *) cmd->host->hostdata;
-    sp = (srb_t *) CMD_SP(cmd);
-
-#if  STOP_ON_RESET 
-    qla1280_panic("qla1280_reset",ha->host);
-#endif 
-
-    DRIVER_LOCK
-    /* Check for pending interrupts. */
-    data = qla1280_debounce_register(&ha->iobase->istatus);
-    if( !(ha->flags.in_isr) && (data & RISC_INT) )
-    {
-        qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-    }
-    DRIVER_UNLOCK
-
-    /*
-    * Determine the suggested action that the mid-level driver wants
-    * us to perform.
-    */
-    if( CMD_HANDLE(cmd) == (unsigned char *) 0  )
-    {
-        /* 
-        * if mid-level driver called reset with a orphan SCSI_Cmnd 
-        * (i.e. a command that's not pending ), so perform the 
-        * function specified.
-        */
-        if( (flags & SCSI_RESET_SUGGEST_HOST_RESET) )
-            action = ADAPTER_RESET;
-        else 
-            action = BUS_RESET;
-    }
-    else
-    { /* 
-        * Mid-level driver has called reset with this SCSI_Cmnd and 
-        * its pending.
-        */
-        if( flags & SCSI_RESET_SUGGEST_HOST_RESET )
-            action = ADAPTER_RESET;
-        else if( flags & SCSI_RESET_SUGGEST_BUS_RESET )
-            action = BUS_RESET;
-        else 
-            action = DEVICE_RESET;
-    }
-
-    b = SCSI_BUS_32(cmd);
-    t = SCSI_TCN_32(cmd);
-    l = SCSI_LUN_32(cmd);
-    q = LU_Q(ha, b, t, l);
+	struct scsi_qla_host *ha;
+	int bus, target, lun;
+	srb_t *sp;
+	typedef enum {
+		ABORT_DEVICE = 1,
+		DEVICE_RESET = 2,
+		BUS_RESET = 3,
+		ADAPTER_RESET = 4,
+		RESET_DELAYED = 5,
+		FAIL = 6
+	} action_t;
+	action_t action = ADAPTER_RESET;
+	u16 data;
+	scsi_lu_t *q;
+	int result;
+
+	ENTER("qla1280_reset");
+	if (qla1280_verbose)
+		printk(KERN_INFO "scsi(): Resetting Cmnd=0x%p, Handle=0x%p, "
+		       "flags=0x%x\n", cmd, CMD_HANDLE(cmd), flags);
+	if (cmd == NULL) {
+		printk(KERN_WARNING
+		       "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd "
+		       "pointer, failing.\n");
+		return SCSI_RESET_SNOOZE;
+	}
+	ha = (struct scsi_qla_host *)cmd->host->hostdata;
+	sp = (srb_t *)CMD_SP(cmd);
+
+#if STOP_ON_RESET
+	qla1280_panic("qla1280_reset", ha->host);
+#endif
+
+	/* Check for pending interrupts. */
+	data = qla1280_debounce_register(&ha->iobase->istatus);
+	/*
+	 * The io_request_lock is held when the reset handler is called, hence
+	 * the interrupt handler cannot be running in parallel as it also
+	 * grabs the lock. /Jes
+	 */
+	if (data & RISC_INT)
+		qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
+
+	/*
+	 * Determine the suggested action that the mid-level driver wants
+	 * us to perform.
+	 */
+	if (CMD_HANDLE(cmd) == NULL) {
+		/*
+		 * if mid-level driver called reset with a orphan SCSI_Cmnd
+		 * (i.e. a command that's not pending), so perform the
+		 * function specified.
+		 */
+		if (flags & SCSI_RESET_SUGGEST_HOST_RESET)
+			action = ADAPTER_RESET;
+		else
+			action = BUS_RESET;
+	} else {
+		/*
+		 * Mid-level driver has called reset with this SCSI_Cmnd and
+		 * its pending.
+		 */
+		if (flags & SCSI_RESET_SUGGEST_HOST_RESET)
+			action = ADAPTER_RESET;
+		else if (flags & SCSI_RESET_SUGGEST_BUS_RESET)
+			action = BUS_RESET;
+		else
+			action = DEVICE_RESET;
+	}
+
+	bus = SCSI_BUS_32(cmd);
+	target = SCSI_TCN_32(cmd);
+	lun = SCSI_LUN_32(cmd);
+	q = LU_Q(ha, bus, target, lun);
 
 #if AUTO_ESCALATE_RESET
-    if ( (action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET) )
-    {
-        printk(KERN_INFO "qla1280(%d): Bus device reset already sent to " "device, escalating.\n", (int)ha->host_no);
-        action = BUS_RESET;
-    }
-    if ( (action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING) )
-    {
-        printk(KERN_INFO "qla1280(%d):Have already attempted to reach " "device with abort device\n", (int)ha->host_no);
-        printk(KERN_INFO "qla1280(%d):message, will escalate to BUS " "RESET.\n",(int) ha->host_no);
-        action = BUS_RESET;
-    }
-#endif
-
-    /*
-    *  By this point, we want to already know what we are going to do,
-    *  so we only need to perform the course of action.
-    */
-    DRIVER_LOCK
-    result = SCSI_RESET_ERROR;
-    switch (action)
-    {
-        case FAIL:
-            break;
-
-        case RESET_DELAYED:
-            result = SCSI_RESET_PENDING;
-            break;
-
-        case ABORT_DEVICE:
-            ha->flags.in_reset = TRUE;
-            if (qla1280_verbose)
-                printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing abort device command.\n", (int)ha->host_no,(int)b,(int)t,(int)l); 
-            qla1280_abort_queue_single(ha,b,t,l,DID_ABORT);
-            if( qla1280_abort_device(ha, b, t, l) == 0)
-                result = SCSI_RESET_PENDING;
-            break;
-
-        case DEVICE_RESET:
-            if (qla1280_verbose)
-                printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing device reset command.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
-            ha->flags.in_reset = TRUE;
-            for (l = 0; l < MAX_LUNS; l++)
-                qla1280_abort_queue_single(ha,b,t,l,DID_ABORT);
-            if( qla1280_device_reset(ha, b, t) == 0 ) 
-                result = SCSI_RESET_PENDING;
-            q->q_flag |= QLA1280_QRESET;
-            break;
-
-        case BUS_RESET:
-                if (qla1280_verbose)
-                    printk(KERN_INFO "qla1280(%d:%d:%d:%d): Issuing BUS DEVICE RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
-            ha->flags.in_reset = TRUE;
-            for (t = 0; t < MAX_TARGETS; t++)
-                for (l = 0; l < MAX_LUNS; l++)
-                    qla1280_abort_queue_single(ha,b,t,l,DID_RESET);
-                qla1280_bus_reset(ha, b);
-                /*
-                * The bus reset routine returns all the outstanding commands back
-                * with "DID_RESET" in the status field after a short delay
-                * by the firmware. If the mid-level time out the SCSI reset before
-                * our delay we may need to ignore it.
-                */
-                /* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */
-                result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
-                mdelay(4 * 1000); barrier();
-                if( flags & SCSI_RESET_SYNCHRONOUS )
-                {
-                  CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
-                  (*(cmd)->scsi_done)(cmd); 
-                }
-                /* ha->reset_start = jiffies; */
-                break;
-
-            case ADAPTER_RESET:
-            default:
-                if (qla1280_verbose)
-                {
-                    printk(KERN_INFO "scsi(%d:%d:%d:%d): Issued an ADAPTER RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
-                    printk(KERN_INFO "scsi(%d:%d:%d:%d): I/O processing will continue automatically.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
-                }
-                ha->flags.reset_active = TRUE;
-                /* 
-                * We restarted all of the commands automatically, so the mid-level code can expect 
-                * completions momentitarily.
-                */
-                if( qla1280_abort_isp(ha) == 0 )
-                    result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
-
-                        ha->flags.reset_active = FALSE;
-    }
-
-    if( ha->done_q_first ) 
-        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-    qla1280_restart_queues(ha);
-    ha->flags.in_reset = FALSE;
-    
-DRIVER_UNLOCK
-    DEBUG(printk("RESET returning %d\n", result)); 
-
-    COMTRACE('r')
-    LEAVE("qla1280_reset");
-    return( result );
+	if ((action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET)) {
+		printk(KERN_INFO
+		       "qla1280(%ld): Bus device reset already sent to "
+		       "device, escalating.\n", ha->host_no);
+		action = BUS_RESET;
+	}
+	if ((action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING)) {
+		printk(KERN_INFO
+		       "qla1280(%ld):Have already attempted to reach "
+		       "device with abort device\n", ha->host_no);
+		printk(KERN_INFO "qla1280(%ld):message, will escalate to BUS "
+		       "RESET.\n", ha->host_no);
+		action = BUS_RESET;
+	}
+#endif
+
+	/*
+	 *  By this point, we want to already know what we are going to do,
+	 *  so we only need to perform the course of action.
+	 */
+	result = SCSI_RESET_ERROR;
+	switch (action) {
+	case FAIL:
+		break;
+
+	case RESET_DELAYED:
+		result = SCSI_RESET_PENDING;
+		break;
+
+	case ABORT_DEVICE:
+		ha->flags.in_reset = TRUE;
+		if (qla1280_verbose)
+			printk(KERN_INFO
+			       "scsi(%ld:%d:%d:%d): Queueing abort device "
+			       "command.\n", ha->host_no, bus, target, lun);
+		qla1280_abort_queue_single(ha, bus, target, lun, DID_ABORT);
+		if (qla1280_abort_device(ha, bus, target, lun) == 0)
+			result = SCSI_RESET_PENDING;
+		break;
+
+	case DEVICE_RESET:
+		if (qla1280_verbose)
+			printk(KERN_INFO
+			       "scsi(%ld:%d:%d:%d): Queueing device reset "
+			       "command.\n", ha->host_no, bus, target, lun);
+		ha->flags.in_reset = TRUE;
+		for (lun = 0; lun < MAX_LUNS; lun++)
+			qla1280_abort_queue_single(ha, bus, target, lun,
+						   DID_ABORT);
+		if (qla1280_device_reset(ha, bus, target) == 0)
+			result = SCSI_RESET_PENDING;
+		q->q_flag |= QLA1280_QRESET;
+		break;
+
+	case BUS_RESET:
+		if (qla1280_verbose)
+			printk(KERN_INFO "qla1280(%ld:%d:%d:%d): Issuing BUS "
+			       "DEVICE RESET.\n", ha->host_no, bus, target,
+			       lun);
+		ha->flags.in_reset = TRUE;
+		for (target = 0; target < MAX_TARGETS; target++)
+			for (lun = 0; lun < MAX_LUNS; lun++)
+				qla1280_abort_queue_single(ha, bus, target,
+							   lun, DID_RESET);
+		qla1280_bus_reset(ha, bus);
+		/*
+		 * The bus reset routine returns all the outstanding commands
+		 * back with "DID_RESET" in the status field after a short
+		 * delay by the firmware. If the mid-level time out the SCSI
+		 * reset before our delay we may need to ignore it.
+		 */
+		/* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */
+		result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+		/*
+		 * Wheeeee!!!
+		 */
+		mdelay(4 * 1000);
+		barrier();
+		if (flags & SCSI_RESET_SYNCHRONOUS) {
+			CMD_RESULT(cmd) = DID_BUS_BUSY << 16;
+			(*(cmd)->scsi_done)(cmd);
+		}
+		/* ha->reset_start = jiffies; */
+		break;
+
+	case ADAPTER_RESET:
+	default:
+		if (qla1280_verbose) {
+			printk(KERN_INFO
+			       "scsi(%ld:%d:%d:%d): Issued an ADAPTER "
+			       "RESET.\n", ha->host_no, bus, target, lun);
+			printk(KERN_INFO
+			       "scsi(%ld:%d:%d:%d): I/O processing will "
+			       "continue automatically.\n", ha->host_no, bus,
+			       target, lun);
+		}
+		ha->flags.reset_active = TRUE;
+		/*
+		 * We restarted all of the commands automatically, so the
+		 * mid-level code can expect completions momentitarily.
+		 */
+		if (qla1280_abort_isp(ha) == 0)
+			result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
+
+		ha->flags.reset_active = FALSE;
+	}
+
+	if (ha->done_q_first)
+		qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
+	qla1280_restart_queues(ha);
+	ha->flags.in_reset = FALSE;
+
+	dprintk(1, "RESET returning %d\n", result);
+
+	LEAVE("qla1280_reset");
+	return result;
 }
 
 /**************************************************************************
- * qla1200_biosparam
+ * qla1280_biosparam
  *   Return the disk geometry for the given SCSI device.
  **************************************************************************/
 int
-qla1280_biosparam(Disk *disk, kdev_t dev, int geom[])
+qla1280_biosparam(Disk * disk, kdev_t dev, int geom[])
 {
-    int heads, sectors, cylinders;
+	int heads, sectors, cylinders;
 
-            heads = 64;
-    sectors = 32;
-    cylinders = disk->capacity / (heads * sectors);
-    if (cylinders > 1024)
-    {
-        heads = 255;
-        sectors = 63;
-        cylinders = disk->capacity / (heads * sectors);
-        /* if (cylinders > 1023)
-        cylinders = 1023; */
-    }
-
-    geom[0] = heads;
-    geom[1] = sectors;
-    geom[2] = cylinders;
+	heads = 64;
+	sectors = 32;
+	cylinders = disk->capacity / (heads * sectors);
+	if (cylinders > 1024) {
+		heads = 255;
+		sectors = 63;
+		cylinders = disk->capacity / (heads * sectors);
+		/* if (cylinders > 1023)
+		   cylinders = 1023; */
+	}
+
+	geom[0] = heads;
+	geom[1] = sectors;
+	geom[2] = cylinders;
 
-    return (0);
+	return 0;
 }
+
 /**************************************************************************
  * qla1280_intr_handler
  *   Handles the H/W interrupt
  **************************************************************************/
-void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+void
+qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-    scsi_qla_host_t *ha;
-    u_short    data;
-    device_reg_t *reg;
-
-    ENTER_INTR("qla1280_intr_handler");
-    COMTRACE('I')
-    ha = (scsi_qla_host_t *) dev_id;
-    if(!ha)
-    {
-        printk(KERN_INFO "scsi(): Interrupt with NULL host ptr\n");
-        COMTRACE('X')
-        return;
-    }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
-    spin_lock_irqsave(ha->host->host_lock, cpu_flags);
-    if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags))
-    {
-        COMTRACE('X')
-        spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
-        return;
-    }
-    ha->isr_count++;
-    reg = ha->iobase;
-     /* disable our interrupt. */
-    WRT_REG_WORD(&reg->ictrl, 0); 
-    data = qla1280_debounce_register(&reg->istatus);
-    /* Check for pending interrupts. */
-    if ( !(data & RISC_INT) )
-    {
-        /* spurious interrupts can happen legally */
-        DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no));
-        COMTRACE('X')
-    }
-    else
-      qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-    if (ha->done_q_first)
-        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-
-    clear_bit(QLA1280_IN_ISR_BIT, &ha->flags);
-    spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
-#else  /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) */
-
-    if( test_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags) )
-    {
-          COMTRACE('X')
-          printk(KERN_INFO "scsi(%d): Already in interrupt - returning \n", (int)ha->host_no);
-          return;
-    }
-    set_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
-    ha->isr_count++;
-    reg = ha->iobase;
-     /* disable our interrupt. */
-    WRT_REG_WORD(&reg->ictrl, 0); 
-
-    data = qla1280_debounce_register(&reg->istatus);
-    /* Check for pending interrupts. */
-    if ( !(data & RISC_INT) )
-    {
-        /* spurious interrupts can happen legally */
-        DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no));
-        COMTRACE('X')
-    }
-    else
-     qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-
-    /* if no work to do then call the SCSI mid-level right away */
-    if( ha->done_q_first )
-        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-
-    /* Schedule the DPC routine */
-    if (ha->flags.isp_abort_needed || ha->flags.reset_marker ||
-            ha->done_q_first        )
-        {
-            ha->run_qla_bh.data = (void *) ha;
-            ha->run_qla_bh.routine = qla1280_do_dpc; 
-
-             COMTRACE('P') 
-            schedule_task(&ha->run_qla_bh);
-            ha->flags.dpc_sched = TRUE;
-        }
-        clear_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
-#endif
-     /* enable our interrupt. */
-        WRT_REG_WORD(&reg->ictrl, ISP_EN_INT + ISP_EN_RISC);
+	struct scsi_qla_host *ha;
+	struct device_reg *reg;
+	u16 data;
+
+	ENTER_INTR ("qla1280_intr_handler");
+	ha = (struct scsi_qla_host *)dev_id;
+
+	spin_lock(ha->host->host_lock);
+
+	ha->isr_count++;
+	reg = ha->iobase;
+
+	WRT_REG_WORD(&reg->ictrl, 0);	/* disable our interrupt. */
+
+	data = qla1280_debounce_register(&reg->istatus);
+	/* Check for pending interrupts. */
+	if (data & RISC_INT) {
+		qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
+	} else {
+		/* spurious interrupts can happen legally */
+		dprintk(1, "scsi(%ld): Spurious interrupt - ignoring\n",
+			ha->host_no);
+	}
 
-        COMTRACE('i')  
-        LEAVE_INTR("qla1280_intr_handler");
+	if (ha->done_q_first)
+		qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
+
+	spin_unlock(ha->host->host_lock);
+
+	/* enable our interrupt. */
+	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+
+	LEAVE_INTR("qla1280_intr_handler");
 }
 
 /**************************************************************************
  *   qla1280_do_dpc
  *
  * Description:
- * This routine is a task that is schedule by the interrupt handler 
- * to perform the background processing for interrupts.  We put it 
+ * This routine is a task that is schedule by the interrupt handler
+ * to perform the background processing for interrupts.  We put it
  * on a task queue that is consumed whenever the scheduler runs; that's
- * so you can do anything (i.e. put the process to sleep etc).  In fact, the 
- * mid-level tries to sleep when it reaches the driver threshold 
+ * so you can do anything (i.e. put the process to sleep etc).  In fact, the
+ * mid-level tries to sleep when it reaches the driver threshold
  * "host->can_queue". This can cause a panic if we were in our interrupt
  * code .
  **************************************************************************/
-static void qla1280_do_dpc(void *p)
+void
+qla1280_do_dpc(void *p)
 {
-    scsi_qla_host_t *ha = (scsi_qla_host_t *) p;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
+	struct scsi_qla_host *ha = (struct scsi_qla_host *) p;
+	unsigned long cpu_flags;
 
-    COMTRACE('p')  
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-    spin_lock_irqsave(ha->host->host_lock, cpu_flags);
-#endif
-    if (ha->flags.isp_abort_needed)
-        qla1280_abort_isp(ha);
+	spin_lock_irqsave(ha->host->host_lock, cpu_flags);
 
-    if (ha->flags.reset_marker)
-        qla1280_rst_aen(ha);
+	if (ha->flags.isp_abort_needed)
+		qla1280_abort_isp(ha);
 
-    if (ha->done_q_first)
-        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-    ha->flags.dpc_sched = FALSE;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-    spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
-#endif
+	if (ha->flags.reset_marker)
+		qla1280_rst_aen(ha);
+
+	if (ha->done_q_first)
+		qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
+
+	spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
 }
 
 /**************************************************************************
@@ -1647,27 +1806,26 @@
  *   as the default queue depth.  Otherwise, we use either 4 or 8 as the
  *   default queue depth (dependent on the number of hardware SCBs).
  **************************************************************************/
-STATIC void qla1280_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device)
+static void
+qla1280_device_queue_depth(struct scsi_qla_host *p, Scsi_Device * device)
 {
-    int default_depth = 3;
-    int bus = device->channel;
-    int target = device->id;
-
-    device->queue_depth = default_depth;
-
-    if (device->tagged_supported &&
-        (p->bus_settings[bus].qtag_enables & (BIT_0 << target)) )
-    {
-        device->tagged_queue = 1;
-        device->current_tag = 0;
-        device->queue_depth = p->bus_settings[bus].hiwat; 
-        /* device->queue_depth = 20; */
-        printk(KERN_INFO "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue depth %d.\n",
-                (int)p->host_no, device->channel, device->id,
-                device->lun, device->queue_depth);
-    }
-    qla12160_get_target_parameters(p, bus, target, device->lun);
-
+	int default_depth = 3;
+	int bus = device->channel;
+	int target = device->id;
+
+	device->queue_depth = default_depth;
+
+	if (device->tagged_supported &&
+	    (p->bus_settings[bus].qtag_enables & (BIT_0 << target))) {
+		device->tagged_queue = 1;
+		device->current_tag = 0;
+		device->queue_depth = p->bus_settings[bus].hiwat;
+		/* device->queue_depth = 20; */
+		printk(KERN_INFO "scsi(%li:%d:%d:%d): Enabled tagged queuing, "
+		       "queue depth %d.\n", p->host_no, device->channel,
+		       device->id, device->lun, device->queue_depth);
+	}
+	qla12160_get_target_parameters(p, bus, target, device->lun);
 }
 
 /**************************************************************************
@@ -1677,41 +1835,27 @@
  *   host adapter.  We use a queue depth of 2 for devices that do not
  *   support tagged queueing.
  **************************************************************************/
-STATIC void
-qla1280_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs)
+static void
+qla1280_select_queue_depth(struct Scsi_Host *host, Scsi_Device * scsi_devs)
 {
-    Scsi_Device *device;
-    scsi_qla_host_t  *p = (scsi_qla_host_t *) host->hostdata;
+	Scsi_Device *device;
+	struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
 
-    ENTER("qla1280_select_queue_depth");
-    for (device = scsi_devs; device != NULL; device = device->next)
-    {
-        if (device->host == host)
-            qla1280_device_queue_depth(p, device);
-    }
-    LEAVE("qla1280_select_queue_depth");
-}
+	ENTER("qla1280_select_queue_depth");
+	for (device = scsi_devs; device != NULL; device = device->next) {
+		if (device->host == host)
+			qla1280_device_queue_depth (ha, device);
+	}
 
-/*--------------------------**
-** Driver Support Routines  **
-**--------------------------*/
+	if (scsi_devs)
+		qla1280_check_for_dead_scsi_bus(ha, scsi_devs->channel);
+
+	LEAVE("qla1280_select_queue_depth");
+}
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
 /*
- * mdelay
- *      Delay in milliseconds 
- *
- * Input:
- *      milliseconds  = delay 
+ * Driver Support Routines
  */
-STATIC inline void mdelay(int milliseconds)
-{
-    int i;
-
-    for(i=0; i<milliseconds; i++)
-        udelay(1000);
-}
-#endif
 
 /*
  * qla1280_done
@@ -1722,176 +1866,181 @@
  *      done_q_first = done queue first pointer.
  *      done_q_last  = done queue last pointer.
  */
-STATIC void
-qla1280_done(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last)
-{
-    srb_t           *sp;
-    scsi_lu_t       *q;
-    uint32_t        b, t, l;
-    Scsi_Cmnd  *cmd;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-
-    ENTER("qla1280_done");
-    COMTRACE('D') 
-
-    DRIVER_LOCK 
-    while (*done_q_first !=  NULL)
-    {
-        /* remove command from done list */
-                sp = *done_q_first;
-        if (!(*done_q_first = sp->s_next))
-            *done_q_last = NULL;
-        else
-            (*done_q_first)->s_prev = NULL;
-                cmd = sp->cmd;
-        b = SCSI_BUS_32(cmd);
-        t = SCSI_TCN_32(cmd);
-        l = SCSI_LUN_32(cmd);
-        q = LU_Q(ha, b, t, l);
-
-        /* Decrement outstanding commands on device. */
-        if (q->q_outcnt)
-            q->q_outcnt--;
-        if (q->q_outcnt < ha->bus_settings[b].hiwat)
-        {
-            q->q_flag &= ~QLA1280_QBUSY;
-        }
-        
-        q->resp_time += jiffies - sp->r_start;                /* Lun bookkeeping information */
-        q->act_time += jiffies - sp->u_start;
-        q->io_cnt++;
-        if( sp->dir & BIT_5 )
-         q->r_cnt++;
-        else
-         q->w_cnt++;
-
-        switch ( (CMD_RESULT(cmd)>>16))
-        {
-            case DID_RESET:
-                q->q_flag &= ~QLA1280_QRESET;
-                /* Issue marker command. */
-                qla1280_marker(ha, b, t, 0, MK_SYNC_ID); 
-                break;
-            case DID_ABORT:
-                sp->flags &= ~SRB_ABORT_PENDING;
-                sp->flags |= SRB_ABORTED;
-                if (sp->flags & SRB_TIMEOUT)
-                    CMD_RESULT(sp->cmd)= DID_TIME_OUT << 16;
-                break;
-            default:
-                break;
-        }
-
-        /* Call the mid-level driver interrupt handler */
-        CMD_HANDLE(sp->cmd) = (unsigned char *) 0;
-        ha->actthreads--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-        sti(); 
-        (*(cmd)->scsi_done)(cmd);
-        cli(); 
-#else
-        (*(cmd)->scsi_done)(cmd);
-#endif
-        qla1280_next(ha, q, b);
-    }
-    DRIVER_UNLOCK 
+static void
+qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first,
+	     srb_t ** done_q_last)
+{
+	srb_t *sp;
+	scsi_lu_t *q;
+	int bus, target, lun;
+	Scsi_Cmnd *cmd;
+
+	ENTER("qla1280_done");
+
+	while (*done_q_first != NULL) {
+		/* remove command from done list */
+		sp = *done_q_first;
+		if (!(*done_q_first = sp->s_next))
+			*done_q_last = NULL;
+		else
+			(*done_q_first)->s_prev = NULL;
+
+		cmd = sp->cmd;
+		bus = SCSI_BUS_32(cmd);
+		target = SCSI_TCN_32(cmd);
+		lun = SCSI_LUN_32(cmd);
+		q = LU_Q(ha, bus, target, lun);
+
+		/* Decrement outstanding commands on device. */
+		if (q->q_outcnt)
+			q->q_outcnt--;
+		if (q->q_outcnt < ha->bus_settings[bus].hiwat) {
+			q->q_flag &= ~QLA1280_QBUSY;
+		}
 
+		q->io_cnt++;
+		if (sp->dir & BIT_5)
+			q->r_cnt++;
+		else
+			q->w_cnt++;
+
+		switch ((CMD_RESULT(cmd) >> 16)) {
+		case DID_RESET:
+			q->q_flag &= ~QLA1280_QRESET;
+			/* Issue marker command. */
+			qla1280_marker(ha, bus, target, 0, MK_SYNC_ID);
+			break;
+		case DID_ABORT:
+			sp->flags &= ~SRB_ABORT_PENDING;
+			sp->flags |= SRB_ABORTED;
+			if (sp->flags & SRB_TIMEOUT)
+				CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16;
+			break;
+		default:
+			break;
+		}
 
-    COMTRACE('d') 
-    LEAVE("qla1280_done");
+		/* 3.13   64 and 32 bit */
+		/* Release memory used for this I/O */
+		if (cmd->use_sg) {
+			dprintk(1, "S/G unmap_sg cmd=%p\n", cmd);
+
+			pci_unmap_sg(ha->pdev, cmd->request_buffer,
+				     cmd->use_sg,
+				     scsi_to_pci_dma_dir(cmd->sc_data_direction));
+		} else if (cmd->request_bufflen) {
+			/*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n",
+			  cmd, sp->saved_dma_handle); */
+
+			pci_unmap_single(ha->pdev, sp->saved_dma_handle,
+					 cmd->request_bufflen,
+					 scsi_to_pci_dma_dir(cmd->sc_data_direction));
+		}
+
+		/* Call the mid-level driver interrupt handler */
+		CMD_HANDLE(sp->cmd) = NULL;
+		ha->actthreads--;
+
+		(*(cmd)->scsi_done)(cmd);
+
+		qla1280_next(ha, q, bus);
+	}
+	LEAVE("qla1280_done");
 }
 
 /*
  * Translates a ISP error to a Linux SCSI error
  */
-STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd       *cp)
+static int
+qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp)
 {
-    int host_status = DID_ERROR;
+	int host_status = DID_ERROR;
 #if DEBUG_QLA1280_INTR
-    STATIC char *reason[] =
-    {
-        "DID_OK",
-                "DID_NO_CONNECT",
-                "DID_BUS_BUSY",
-                "DID_TIME_OUT",
-                "DID_BAD_TARGET",
-                "DID_ABORT",
-                "DID_PARITY",
-                "DID_ERROR",
-                "DID_RESET",
-                "DID_BAD_INTR"
-    };
-#endif /* DEBUG_QLA1280_INTR */
+	static char *reason[] = {
+		"DID_OK",
+		"DID_NO_CONNECT",
+		"DID_BUS_BUSY",
+		"DID_TIME_OUT",
+		"DID_BAD_TARGET",
+		"DID_ABORT",
+		"DID_PARITY",
+		"DID_ERROR",
+		"DID_RESET",
+		"DID_BAD_INTR"
+	};
+#endif				/* DEBUG_QLA1280_INTR */
 
-    ENTER("qla1280_return_status");
+	ENTER("qla1280_return_status");
 
 #if DEBUG_QLA1280_INTR
-    /*
-    DEBUG(printk("qla1280_return_status: compl status = 0x%04x\n", sts->comp_status));
-    */
-#endif
-    switch(sts->comp_status)
-    {
-        case CS_COMPLETE:
-            host_status = DID_OK;
-            break;
-        case CS_INCOMPLETE:
-            if (!(sts->state_flags & SF_GOT_BUS))
-                host_status = DID_NO_CONNECT;
-            else if (!(sts->state_flags & SF_GOT_TARGET))
-                host_status = DID_BAD_TARGET;
-            else if (!(sts->state_flags & SF_SENT_CDB))
-                host_status = DID_ERROR;
-            else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
-                host_status = DID_ERROR;
-            else if (!(sts->state_flags & SF_GOT_STATUS))
-                host_status = DID_ERROR;
-            else if (!(sts->state_flags & SF_GOT_SENSE))
-                host_status = DID_ERROR;
-            break;
-        case CS_RESET:
-            host_status = DID_RESET;
-            break;
-        case CS_ABORTED:
-            host_status = DID_ABORT;
-            break;
-        case CS_TIMEOUT:
-            host_status = DID_TIME_OUT;
-            break;
-        case CS_DATA_OVERRUN:
-#ifdef QL_DEBUG_LEVEL_2 
-            printk("Data overrun 0x%x\n",(int)sts->residual_length);
-            qla1280_print(
-                        "\n\rqla1280_isr: response packet data\n\r");
-                        qla1280_dump_buffer((caddr_t)sts,
-                        RESPONSE_ENTRY_SIZE); 
-#endif
-            host_status = DID_ERROR;
-            break;
-        case CS_DATA_UNDERRUN:
-            if ( (CMD_XFRLEN(cp) - sts->residual_length) < cp->underflow)    
-            { 
-              printk("scsi: Underflow detected - retrying command.\n");
-              host_status = DID_ERROR;
-            }
-            else
-                host_status = DID_OK;
-            break;
-        default:
-            host_status = DID_ERROR;
-            break;
-    }
+	/*
+	  dprintk(1, "qla1280_return_status: compl status = 0x%04x\n",
+	  sts->comp_status);
+	*/
+#endif
+	switch (sts->comp_status) {
+	case CS_COMPLETE:
+		host_status = DID_OK;
+		break;
+
+	case CS_INCOMPLETE:
+		if (!(sts->state_flags & SF_GOT_BUS))
+			host_status = DID_NO_CONNECT;
+		else if (!(sts->state_flags & SF_GOT_TARGET))
+			host_status = DID_BAD_TARGET;
+		else if (!(sts->state_flags & SF_SENT_CDB))
+			host_status = DID_ERROR;
+		else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
+			host_status = DID_ERROR;
+		else if (!(sts->state_flags & SF_GOT_STATUS))
+			host_status = DID_ERROR;
+		else if (!(sts->state_flags & SF_GOT_SENSE))
+			host_status = DID_ERROR;
+		break;
+
+	case CS_RESET:
+		host_status = DID_RESET;
+		break;
+
+	case CS_ABORTED:
+		host_status = DID_ABORT;
+		break;
+
+	case CS_TIMEOUT:
+		host_status = DID_TIME_OUT;
+		break;
+
+	case CS_DATA_OVERRUN:
+		dprintk(2, "Data overrun 0x%x\n", sts->residual_length);
+		dprintk(2, "qla1280_isr: response packet data\n");
+		qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
+		host_status = DID_ERROR;
+		break;
+
+	case CS_DATA_UNDERRUN:
+		if ((cp->request_bufflen - sts->residual_length) <
+		    cp->underflow) {
+			printk(KERN_WARNING
+			       "scsi: Underflow detected - retrying "
+			       "command.\n");
+			host_status = DID_ERROR;
+		} else
+			host_status = DID_OK;
+		break;
+
+	default:
+		host_status = DID_ERROR;
+		break;
+	}
 
 #if DEBUG_QLA1280_INTR
-    sprintf(debug_buff, "qla1280 ISP status: host status (%s) scsi status %x\n\r", reason[host_status], sts->scsi_status);
-    qla1280_print(debug_buff);
+	dprintk(1, "qla1280 ISP status: host status (%s) scsi status %x\n",
+		reason[host_status], sts->scsi_status);
 #endif
 
-    LEAVE("qla1280_return_status");
+	LEAVE("qla1280_return_status");
 
-    return (sts->scsi_status & 0xff) | (host_status << 16);
+	return (sts->scsi_status & 0xff) | (host_status << 16);
 }
 
 /*
@@ -1903,29 +2052,21 @@
  *      done_q_first = done queue first pointer.
  *      done_q_last  = done queue last pointer.
  */
-STATIC void
-qla1280_done_q_put(srb_t *sp, srb_t **done_q_first, srb_t **done_q_last)
+static void
+qla1280_done_q_put(srb_t * sp, srb_t ** done_q_first, srb_t ** done_q_last)
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_put_done_q");
-#endif
-    /* Place block on done queue */
-    DRIVER_LOCK
-            sp->s_next = NULL;
-    sp->s_prev = *done_q_last;
-    if (!*done_q_first)
-        *done_q_first = sp;
-    else
-        (*done_q_last)->s_next = sp;
-    *done_q_last = sp;
-
-    DRIVER_UNLOCK
-#ifdef QL_DEBUG_LEVEL_3
-            LEAVE("qla1280_put_done_q");
-#endif
+	ENTER("qla1280_put_done_q");
+
+	/* Place block on done queue */
+	sp->s_next = NULL;
+	sp->s_prev = *done_q_last;
+	if (!*done_q_first)
+		*done_q_first = sp;
+	else
+		(*done_q_last)->s_next = sp;
+	*done_q_last = sp;
+
+	LEAVE("qla1280_put_done_q");
 }
 
 /*
@@ -1933,128 +2074,97 @@
  *      Retrieve and process next job in the queue.
  *
  * Input:
- *      ha = adapter block pointer.
- *      q  = SCSI LU pointer.
- *      b  = SCSI bus number.
- *      SCSI_LU_Q lock must be already obtained and no other locks.
+ *      ha   = adapter block pointer.
+ *      q    = SCSI LU pointer.
+ *      bus  = SCSI bus number.
+ *      SCSI_LU_Qlock must be already obtained and no other locks.
  *
  * Output:
- *      Releases SCSI_LU_Q upon exit.
+ *      Releases SCSI_LU_Qupon exit.
  */
-STATIC void
-qla1280_next(scsi_qla_host_t *ha, scsi_lu_t *q, uint8_t b)
+static void
+qla1280_next(struct scsi_qla_host *ha, scsi_lu_t * q, int bus)
 {
-    srb_t   *sp;
-    uint32_t cnt;
-    uint8_t status;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-
-    ENTER("qla1280_next");
-
-    DRIVER_LOCK
-    while ( ((sp = q->q_first) != NULL) &&     /* we have a queue pending */
-        !(q->q_flag &  QLA1280_QBUSY) &&      /* device not busy */
-        !ha->flags.abort_isp_active &&      /* not resetting the adapter */
-        !(q->q_flag & QLA1280_QSUSP) )      /* device not suspended */
-    {
-        /* Remove srb from SCSI LU queue. */
-        qla1280_removeq(q, sp);
-
-        DEBUG(sprintf(debug_buff,"starting request 0x%p<-(0x%p)\n\r",q,sp));
-        DEBUG(qla1280_print(debug_buff));
-        {
-            /* Set busy flag if reached high water mark. */
-            q->q_outcnt++;
-            if (q->q_outcnt >= ha->bus_settings[b].hiwat)
-                q->q_flag |= QLA1280_QBUSY;
-
-#if  QLA1280_64BIT_SUPPORT
-            if (ha->flags.enable_64bit_addressing)
-                status = qla1280_64bit_start_scsi(ha, sp);
-            else
-#endif
-                status = qla1280_32bit_start_scsi(ha, sp);
-
-            if (status)  /* if couldn't start the request */
-            {
-                if (q->q_outcnt == 1)
-                {
-                    /* Release SCSI LU queue specific lock */
-                    QLA1280_SCSILU_UNLOCK(q);
-
-                    /* Wait for 30 sec for command to be accepted. */
-                    for (cnt = 6000000; cnt; cnt--)
-                    {
-#if  QLA1280_64BIT_SUPPORT
-                        if (ha->flags.enable_64bit_addressing)
-                            status = qla1280_64bit_start_scsi(ha, sp);
-                        else
-#endif
-                            status = qla1280_32bit_start_scsi(ha, sp);
-
-                        if (!status)
-                        {
-                            break;
-                        }
-
-                        /* Go check for pending interrupts. */
-                        qla1280_poll(ha);
-
-                        SYS_DELAY(5);  /* 10 */
-                    }
-                    if (!cnt)
-                    {
-                        /* Set timeout status */
-                        CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16;
+	srb_t *sp;
+	int cnt, status;
 
-#if WATCHDOGTIMER
-                        /* Remove command from watchdog queue. */
-                        if (sp->flags & SRB_WATCHDOG)
-                            qla1280_timeout_remove(ha, sp);
-#endif
-                        COMTRACE('M') 
-                        CMD_HANDLE(sp->cmd) = (unsigned char *) 0;
-
-                        /* Call the mid-level driver interrupt handler */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-                        sti(); 
-                        (*(sp->cmd)->scsi_done)(sp->cmd);
-                        cli(); 
-#else
-                        (*(sp->cmd)->scsi_done)(sp->cmd);
+	ENTER("qla1280_next");
+
+	while (((sp = q->q_first) != NULL) &&	/* we have a queue pending */
+	       /* device not busy/suspended */
+	       !(q->q_flag & (QLA1280_QBUSY | QLA1280_QSUSP)) && !ha->flags.abort_isp_active) {	/* not resetting the adapter */
+		/* Remove srb from SCSI LU queue. */
+		qla1280_removeq(q, sp);
+
+		dprintk(1, "starting request 0x%p<-(0x%p)\n", q, sp);
+		{
+			/* Set busy flag if reached high water mark. */
+			q->q_outcnt++;
+			if (q->q_outcnt >= ha->bus_settings[bus].hiwat)
+				q->q_flag |= QLA1280_QBUSY;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
+			if (ha->flags.enable_64bit_addressing)
+				status = qla1280_64bit_start_scsi(ha, sp);
+			else
 #endif
+				status = qla1280_32bit_start_scsi(ha, sp);
 
-                        /* Acquire LU queue specific lock */
-                        QLA1280_SCSILU_LOCK(q);
-
-                        if (q->q_outcnt)
-                            q->q_outcnt--;
-                    }
-                    else
-                        /* Acquire LU queue specific lock */
-                        QLA1280_SCSILU_LOCK(q);
-                }
-                else
-                {   /* Place request back on top of device queue. */
-                    qla1280_putq_t(q, sp);
-
-                    if (q->q_outcnt)
-                        q->q_outcnt--;
-                    if (q->q_outcnt < ha->bus_settings[b].hiwat)
-                        q->q_flag &= ~QLA1280_QBUSY;
-                    break;
-                }
-            }
-        }
-    }
-   DRIVER_UNLOCK
+			if (status) {	/* if couldn't start the request */
+				if (q->q_outcnt == 1) {
+					/* Wait for 30 sec for command to be accepted. */
+					for (cnt = 6000000; cnt; cnt--) {
+#if QLA_64BIT_PTR
+						if (ha->flags.enable_64bit_addressing)
+							status =
+								qla1280_64bit_start_scsi(ha, sp);
+						else
+#endif
+							status =
+								qla1280_32bit_start_scsi(ha, sp);
+
+						if (!status)
+							break;
+
+						/* Go check for pending interrupts. */
+						qla1280_poll(ha);
+
+						udelay(5);	/* 10 */
+					}
+					if (!cnt) {
+						/* Set timeout status */
+						CMD_RESULT(sp->cmd) =
+							DID_TIME_OUT << 16;
 
-    /* Release SCSI LU queue specific lock */
-    QLA1280_SCSILU_UNLOCK(q);
+#if WATCHDOGTIMER
+						/* Remove command from watchdog queue. */
+						if (sp->flags & SRB_WATCHDOG)
+							qla1280_timeout_remove
+								(ha, sp);
+#endif
+						CMD_HANDLE(sp->cmd) = NULL;
+
+						/* Call the mid-level driver interrupt handler */
+						(*(sp->cmd)->scsi_done)(sp->cmd);
+
+						if (q->q_outcnt)
+							q->q_outcnt--;
+					}
+				} else {	/* Place request back on top of device queue. */
+					qla1280_putq_t(q, sp);
+
+					if (q->q_outcnt)
+						q->q_outcnt--;
+					if (q->q_outcnt <
+					    ha->bus_settings[bus].hiwat)
+						q->q_flag &= ~QLA1280_QBUSY;
+					break;
+				}
+			}
+		}
+	}
 
-    LEAVE("qla1280_next");
+	LEAVE("qla1280_next");
 }
 
 /*
@@ -2064,57 +2174,28 @@
  * Input:
  *      q  = SCSI LU pointer.
  *      sp = srb pointer.
- *      SCSI_LU_Q lock must be already obtained.
+ *      SCSI_LU_Qlock must be already obtained.
  */
-STATIC void
-qla1280_putq_t(scsi_lu_t *q, srb_t *sp)
+static void
+qla1280_putq_t(scsi_lu_t * q, srb_t * sp)
 {
-    srb_t *srb_p;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_putq_t");
-#endif
-    DRIVER_LOCK
-    DEBUG(sprintf(debug_buff,"Adding to device 0x%p<-(0x%p)\n\r",q,sp));
-    DEBUG(qla1280_print(debug_buff));
-    sp->s_next = NULL;
-    if (!q->q_first)                  /* If queue empty */
-    {
-        sp->s_prev = NULL;
-        q->q_first = sp;
-        q->q_last = sp;
-    }
-    else
-    {      
-        srb_p = q->q_first;
-        while (srb_p )
-            srb_p = srb_p->s_next;
-
-        if (srb_p)
-        {
-            sp->s_prev = srb_p->s_prev;
-            if (srb_p->s_prev)
-                srb_p->s_prev->s_next = sp;
-            else
-                q->q_first = sp;
-            srb_p->s_prev = sp;
-            sp->s_next = srb_p;
-        }
-        else
-        {
-            sp->s_prev = q->q_last;
-            q->q_last->s_next = sp;
-            q->q_last = sp;
-        }
-    }
-
-    DRIVER_UNLOCK
-#ifdef QL_DEBUG_LEVEL_3
-            LEAVE("qla1280_putq_t");
-#endif
+	ENTER("qla1280_putq_t");
+
+	dprintk(1, "Adding to device q=0x%p<-(0x%p)sp\n", (void *) q,
+		(void *) sp);
+
+	sp->s_next = NULL;
+	if (!q->q_first) {	/* If queue empty */
+		sp->s_prev = NULL;
+		q->q_first = sp;
+		q->q_last = sp;
+	} else {
+		sp->s_prev = q->q_last;
+		q->q_last->s_next = sp;
+		q->q_last = sp;
+	}
+
+	LEAVE("qla1280_putq_t");
 }
 
 /*
@@ -2125,29 +2206,22 @@
  * Input:
  *      q  = SCSI LU pointer.
  *      sp = srb pointer.
- *      SCSI_LU_Q lock must be already obtained.
+ *      SCSI_LU_Qlock must be already obtained.
  */
-STATIC void
-qla1280_removeq(scsi_lu_t *q, srb_t *sp)
+static void
+qla1280_removeq(scsi_lu_t * q, srb_t * sp)
 {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-    DEBUG(sprintf(debug_buff,"Removing from device_q (0x%p)->(0x%p)\n\r",q,sp));
-    DEBUG(qla1280_print(debug_buff));
-    DRIVER_LOCK
-            if (sp->s_prev)
-    {
-        if ((sp->s_prev->s_next = sp->s_next) != NULL)
-            sp->s_next->s_prev = sp->s_prev;
-        else
-            q->q_last = sp->s_prev;
-    }
-    else if (!(q->q_first = sp->s_next))
-        q->q_last = NULL;
-    else
-        q->q_first->s_prev = NULL;
-    DRIVER_UNLOCK
+	dprintk(1, "Removing from device_q (0x%p)->(0x%p)\n", q, sp);
+
+	if (sp->s_prev) {
+		if ((sp->s_prev->s_next = sp->s_next) != NULL)
+			sp->s_next->s_prev = sp->s_prev;
+		else
+			q->q_last = sp->s_prev;
+	} else if (!(q->q_first = sp->s_next))
+		q->q_last = NULL;
+	else
+		q->q_first->s_prev = NULL;
 }
 
 /*
@@ -2158,44 +2232,38 @@
 *      0  = success.
 *      1  = failure.
 */
-STATIC uint8_t
-qla1280_mem_alloc(scsi_qla_host_t *ha)
+static int
+qla1280_mem_alloc(struct scsi_qla_host *ha)
 {
+	int status = 1;
+	dma_addr_t dma_handle;
 
-	uint8_t   status = 1;
-
-#ifdef QL_DEBUG_LEVEL_3
 	ENTER("qla1280_mem_alloc");
-#endif
 
-#ifdef DYNAMIC_MEM_ALLOC
-	ha->request_ring = qla1280_alloc_phys(REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT,
-	&ha->request_dma);
-	if(ha->request_ring) {
-		ha->response_ring = qla1280_alloc_phys(RESPONSE_ENTRY_SIZE * RESPONSE_ENTRY_CNT,
-		&ha->response_dma);
-		if(ha->response_ring) {
-			status = 0;
-		}
-	}
-#else
-	ha->request_ring = &ha->req[0];
-	ha->request_dma = VIRT_TO_BUS(&ha->req[0]);
-	ha->response_ring = &ha->res[0];
-	ha->response_dma = VIRT_TO_BUS(&ha->res[0]);
+	/* 3.13 */
+	/* get consistent memory allocated for request and response rings */
+	ha->request_ring = pci_alloc_consistent(ha->pdev,
+						((REQUEST_ENTRY_CNT + 1) *
+						 (sizeof(request_t))),
+						&dma_handle);
+	if (!ha->request_ring)
+		goto error;
+	ha->request_dma = dma_handle;
+	ha->response_ring = pci_alloc_consistent(ha->pdev,
+						 ((RESPONSE_ENTRY_CNT + 1) *
+						  (sizeof(response_t))),
+						 &dma_handle);
+	if (!ha->request_ring)
+		goto error;
+	ha->response_dma = dma_handle;
 	status = 0;
-#endif
 
-	if(status) {
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-		qla1280_print("qla1280_mem_alloc: **** FAILED ****\n");
-#endif
-	}
-#ifdef QL_DEBUG_LEVEL_3
-	else
-		LEAVE("qla1280_mem_alloc");
-#endif
-	return(status);
+ error:
+	if (status)
+		dprintk(2, "qla1280_mem_alloc: **** FAILED ****\n");
+
+	LEAVE("qla1280_mem_alloc");
+	return status;
 }
 
 /*
@@ -2205,66 +2273,91 @@
  * Input:
  *      ha = adapter block pointer.
  */
-STATIC void
-qla1280_mem_free(scsi_qla_host_t *ha)
+static void
+qla1280_mem_free(struct scsi_qla_host *ha)
 {
-    scsi_lu_t *q;
-    uint32_t  b, t, l;
-
-    ENTER("qlc1280_mem_free");
-    if (ha)
-    {
-        /* Free device queues. */
-        for (b = 0; b < MAX_BUSES; b++)
-        {
-            q = LU_Q(ha, b, ha->bus_settings[b].id, 0);
-            for (t = 0; t < MAX_TARGETS; t++)
-                for (l = 0; l < MAX_LUNS; l++)
-                    if (LU_Q(ha, b, t, l) != NULL && LU_Q(ha, b, t, l) != q)
-                        KMFREE(LU_Q(ha, b, t, l),sizeof(struct scsi_lu));
-                    KMFREE(q, sizeof(struct scsi_lu));
-        }
-        for( b =0; b < MAX_EQ; b++ )
-            ha->dev[b] =  (scsi_lu_t  *)NULL;
-    }
-
-    LEAVE("qlc1280_mem_free");
-}
+	scsi_lu_t *q;
+	int bus, target, lun;
 
+	ENTER("qlc1280_mem_free");
+	if (ha) {
+		/* Free device queues. */
+		for (bus = 0; bus < MAX_BUSES; bus++) {
+			q = LU_Q(ha, bus, ha->bus_settings[bus].id, 0);
+			for (target = 0; target < MAX_TARGETS; target++)
+				for (lun = 0; lun < MAX_LUNS; lun++)
+					if (LU_Q(ha, bus, target, lun) != NULL
+					    && LU_Q(ha, bus, target, lun) != q)
+						kfree(LU_Q(ha, bus, target, lun));
+			kfree(q);
+		}
+		for (bus = 0; bus < MAX_EQ; bus++)
+			ha->dev[bus] = NULL;
+	}
 
+	/* 3.13 */
+	/* free consistent memory allocated for request and response rings */
+	if (ha->request_ring)
+		pci_free_consistent(ha->pdev,
+				    ((REQUEST_ENTRY_CNT + 1) *
+				     (sizeof(request_t))),
+				    ha->request_ring, ha->request_dma);
+
+	if (ha->response_ring)
+		pci_free_consistent(ha->pdev,
+				    ((RESPONSE_ENTRY_CNT + 1) *
+				     (sizeof(response_t))),
+				    ha->response_ring, ha->response_dma);
+
+	if (qla1280_buffer) {
+		free_page((unsigned long) qla1280_buffer);
+		qla1280_buffer = NULL;
+	}
 
+	LEAVE("qlc1280_mem_free");
+}
 
 /****************************************************************************/
 /*                QLogic ISP1280 Hardware Support Functions.                */
 /****************************************************************************/
 
  /*
- * qla2100_enable_intrs
- * qla2100_disable_intrs
- *
- * Input:
- *      ha = adapter block pointer.
- *
- * Returns:
- *      None      
- */
-    static inline void qla1280_enable_intrs(scsi_qla_host_t *ha) {
-        device_reg_t *reg;
+    * qla2100_enable_intrs
+    * qla2100_disable_intrs
+    *
+    * Input:
+    *      ha = adapter block pointer.
+    *
+    * Returns:
+    *      None
+  */
+static inline void
+qla1280_enable_intrs(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg;
+
+	reg = ha->iobase;
+	/* enable risc and host interrupts */
+	WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
+	ha->flags.ints_enabled = 1;
+#if 0
+	printk("Enabling ints\n");
+#endif
+}
 
-        reg = ha->iobase;
-        ha->flags.interrupts_on = 1;
-        /* enable risc and host interrupts */
-        WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT+ ISP_EN_RISC));
-    }
-
-    static inline void qla1280_disable_intrs(scsi_qla_host_t *ha) {
-        device_reg_t *reg;
-
-        reg = ha->iobase;
-        ha->flags.interrupts_on = 0;
-        /* disable risc and host interrupts */
-        WRT_REG_WORD(&reg->ictrl, 0);
-    }
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg;
+
+	reg = ha->iobase;
+	/* disable risc and host interrupts */
+	WRT_REG_WORD(&reg->ictrl, 0);
+	ha->flags.ints_enabled = 0;
+#if 0
+	printk("Disabling ints\n");
+#endif
+}
 
 /*
  * qla1280_initialize_adapter
@@ -2276,118 +2369,110 @@
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_initialize_adapter(scsi_qla_host_t *ha)
+static int
+qla1280_initialize_adapter(struct scsi_qla_host *ha)
 {
-    device_reg_t *reg;
-    uint8_t      status;
-    /* uint8_t      cnt; */
-    uint8_t      b;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_initialize_adapter");
-#endif
-
-    /* Clear adapter flags. */
-    ha->flags.online = FALSE;
-    ha->flags.isp_abort_needed = FALSE;
-    ha->flags.disable_host_adapter = FALSE;
-    ha->flags.reset_active = FALSE;
-    ha->flags.abort_isp_active = FALSE;
-    ha->flags.watchdog_enabled = FALSE;
-
-    DEBUG(printk("Configure PCI space for adapter...\n"));
-    if (!(status = qla1280_pci_config(ha)))
-    {
-        reg = ha->iobase;
-
-        /* Disable ISP interrupts. */
-        WRT_REG_WORD(&reg->ictrl, 0);
-
-        /* Insure mailbox registers are free. */
-        WRT_REG_WORD(&reg->semaphore, 0);
-        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
-        WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
-
-        /* If firmware needs to be loaded */
-        if (qla1280_verbose)
-         printk("scsi(%d): Determining if RISC is loaded...\n",(int)ha->host_no);
-        if (qla1280_isp_firmware(ha))
-        {
-            if (qla1280_verbose)
-              printk("scsi(%d): Verifying chip...\n",(int)ha->host_no);
-            if (!(status = qla1280_chip_diag(ha)))
-            {
-                if (qla1280_verbose)
-                  printk("scsi(%d): Setup chip...\n",(int)ha->host_no);
-                status = qla1280_setup_chip(ha); 
-            }
-        }
-
-        if (!status)
-        {
-            /* Setup adapter based on NVRAM parameters. */
-            if (qla1280_verbose)
-              printk("scsi(%d): Configure NVRAM parameters...\n",(int)ha->host_no);
-            qla1280_nvram_config(ha);
-
-            if (!ha->flags.disable_host_adapter &&
-                !qla1280_init_rings(ha))
-            {
-                /* Issue SCSI reset. */
-                for (b = 0; b < ha->ports; b++)
-                    if (!ha->bus_settings[b].disable_scsi_reset)
-                    {
-                      /* dg 03/13 if we can't reset twice then bus is dead */
-                        if( qla1280_bus_reset(ha, b) )
-                           if( qla1280_bus_reset(ha, b) )
-                           {
-                               ha->bus_settings[b].scsi_bus_dead = TRUE;
-                            }
-                    }
-
-                    do
-                    {
-                        /* Issue marker command. */
-                        ha->flags.reset_marker = FALSE;
-                        for (b = 0; b < ha->ports; b++)
-                        {
-                            ha->bus_settings[b].reset_marker = FALSE;
-                            qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
-                        }
-                    }while (ha->flags.reset_marker);
-
-                    ha->flags.online = TRUE;
-
-                    /* Enable host adapter target mode. */
-                    for (b = 0; b < ha->ports; b++)
-                    {
-                        if (!(status = qla1280_enable_tgt(ha, b)))
-                        {
-                            /* for (cnt = 0; cnt < MAX_LUNS; cnt++)
-                            {
-                                qla1280_enable_lun(ha, b, cnt);
-                                 qla1280_poll(ha);
-                            }*/
-                        }
-                        else
-                            break;
-                    }
-            }
-            else
-                status = 1;
-        }
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_initialize_adapter: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_initialize_adapter");
-#endif
-    return(status);
+	struct device_reg *reg;
+	int status;
+	int bus;
+
+	ENTER("qla1280_initialize_adapter");
+
+	/* Clear adapter flags. */
+	ha->flags.online = FALSE;
+	ha->flags.isp_abort_needed = FALSE;
+	ha->flags.disable_host_adapter = FALSE;
+	ha->flags.reset_active = FALSE;
+	ha->flags.abort_isp_active = FALSE;
+
+	ha->flags.ints_enabled = FALSE;
+
+	dprintk(1, "Configure PCI space for adapter...\n");
+
+	reg = ha->iobase;
+
+	/* Insure mailbox registers are free. */
+	WRT_REG_WORD(&reg->semaphore, 0);
+	WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+	WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
+
+	/* If firmware needs to be loaded */
+	if (qla1280_verbose)
+		printk(KERN_INFO "scsi(%li): Determining if RISC is "
+		       "loaded...\n", ha->host_no);
+	if (qla1280_isp_firmware(ha)) {
+		if (qla1280_verbose)
+			printk(KERN_INFO "scsi(%ld): Verifying chip...\n",
+			       ha->host_no);
+		if (!(status = qla1280_chip_diag (ha))) {
+			if (qla1280_verbose)
+				printk(KERN_INFO "scsi(%ld): Setup chip...\n",
+				       ha->host_no);
+			status = qla1280_setup_chip(ha);
+		}
+	} else {
+		printk(KERN_ERR "initialize: isp_firmware() failed!\n");
+		status = 1;
+	}
+
+	if (!status) {
+		/* Setup adapter based on NVRAM parameters. */
+		if (qla1280_verbose)
+			printk(KERN_INFO
+			       "scsi(%ld): Configure NVRAM parameters...\n",
+			       ha->host_no);
+		qla1280_nvram_config(ha);
+
+		if (!ha->flags.disable_host_adapter
+		    && !qla1280_init_rings(ha)) {
+			/* Issue SCSI reset. */
+			/* dg 03/13 if we can't reset twice then bus is dead */
+			for (bus = 0; bus < ha->ports; bus++) {
+				if (!ha->bus_settings[bus].disable_scsi_reset){
+					if (qla1280_bus_reset(ha, bus)) {
+						if (qla1280_bus_reset(ha, bus)) {
+							ha->bus_settings[bus].scsi_bus_dead = TRUE;
+						}
+					}
+				}
+			}
+			do {
+				/* Issue marker command. */
+				ha->flags.reset_marker = FALSE;
+				for (bus = 0; bus < ha->ports; bus++) {
+					ha->bus_settings[bus].reset_marker = FALSE;
+					qla1280_marker(ha, bus, 0, 0,
+						       MK_SYNC_ALL);
+				}
+			} while (ha->flags.reset_marker);
+
+			ha->flags.online = TRUE;
+
+			/* Enable host adapter target mode. */
+			for (bus = 0; bus < ha->ports; bus++) {
+				if (!(status = qla1280_enable_tgt(ha, bus))) {
+#if 0
+					int cnt;
+					for (cnt = 0; cnt < MAX_LUNS; cnt++) {
+						qla1280_enable_lun(ha, bus,
+								   cnt);
+						qla1280_poll(ha);
+					}
+#endif
+				} else
+					break;
+			}
+		} else
+			status = 1;
+	} else
+		printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n",
+		       ha->host_no);
+
+	if (status)
+		dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n");
+
+	LEAVE("qla1280_initialize_adapter");
+	return status;
 }
 
 /*
@@ -2395,38 +2480,33 @@
  *      Enable target mode.
  *
  * Input:
- *      ha = adapter block pointer.
- *      b  = SCSI bus number.
+ *      ha   = adapter block pointer.
+ *      bus  = SCSI bus number.
  *
  * Returns:
  *      0 = success.
  */
-STATIC uint8_t
-qla1280_enable_tgt(scsi_qla_host_t *ha, uint8_t b)
+static int
+qla1280_enable_tgt(struct scsi_qla_host *ha, int bus)
 {
-    uint8_t     status = 0;
-    /*  uint16_t    mb[MAILBOX_REGISTER_COUNT]; */
+	int status = 0;
+	/*  uint16_t    mb[MAILBOX_REGISTER_COUNT]; */
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_enable_tgt: entered\n\r");
-#endif
+	dprintk(3, "qla1280_enable_tgt: entered\n");
 
-    /* Enable target mode. */
-    /*
-    mb[0] = MBC_ENABLE_TARGET_MODE;
-    mb[1] = BIT_15;
-    mb[2] = (uint16_t)(b << 15);
-    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
-    */
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_enable_tgt: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_enable_tgt: exiting normally\n\r");
+	/* Enable target mode. */
+#if 0
+	mb[0] = MBC_ENABLE_TARGET_MODE;
+	mb[1] = BIT_15;
+	mb[2] = (uint16_t) (bus << 15);
+	status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 #endif
-    return(status);
+	if (status)
+		dprintk(2, "qla1280_enable_tgt: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_enable_tgt: exiting normally\n");
+
+	return status;
 }
 
 /*
@@ -2440,83 +2520,77 @@
  * Returns:
  *      0 = firmware does not need to be loaded.
  */
-STATIC uint8_t
-qla1280_isp_firmware(scsi_qla_host_t *ha)
+static int
+qla1280_isp_firmware(struct scsi_qla_host *ha)
 {
-    nvram_t     *nv    = (nvram_t *)ha->response_ring; 
-    uint16_t    *wptr;
-    uint8_t     chksum;
-    uint8_t     cnt;
-    uint8_t     status = 0;    /* dg 2/27 always loads RISC */
-    uint16_t    mb[MAILBOX_REGISTER_COUNT];
-
-    ENTER("qla1280_isp_firmware");
-
-    /* Verify valid NVRAM checksum. */
-    wptr = (uint16_t *)ha->response_ring;
-    DEBUG(printk("qla1280_isp_firmware: Reading NVRAM\n"));
-    chksum = 0;
-    for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++)
-    {
-        *wptr = qla1280_get_nvram_word(ha, cnt);
-        chksum += (uint8_t)*wptr;
-        chksum += (uint8_t)(*wptr >> 8);
-        wptr++;
-    }
-    DEBUG(printk("qla1280_isp_firmware: Completed Reading NVRAM\n"));
-
-#if defined(QL_DEBUG_LEVEL_3)
-    sprintf(debug_buff,"qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n\r",(char *) nv->id[0],nv->id[1],nv->id[2]);
-    qla1280_print(debug_buff);
-#endif
-
-    /* Bad NVRAM data, load RISC code. */
-    if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
-        nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1)
-    {
-        printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic number or version in NVRAM.\n");
-        ha->flags.disable_risc_code_load = FALSE;
-    }
-    else
-        ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code;
-
-    if (ha->flags.disable_risc_code_load)
-    {
-#if defined(QL_DEBUG_LEVEL_3)
-        qla1280_print("qla1280_isp_firmware: Telling RISC to verify checksum of loaded BIOS code.\n\r");
-#endif
-        /* Verify checksum of loaded RISC code. */
-        mb[0] = MBC_VERIFY_CHECKSUM;
-        /* mb[1] = ql12_risc_code_addr01; */
-        mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
-
-        if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0])))
-        {
-            /* Start firmware execution. */
-#if defined(QL_DEBUG_LEVEL_3)
-            qla1280_print("qla1280_isp_firmware: Startng F/W execution.\n\r");
-#endif
-            mb[0] = MBC_EXECUTE_FIRMWARE;
-            /* mb[1] = ql12_risc_code_addr01; */
-            mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
-            qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
-        }
-        else
-            printk(KERN_INFO "qla1280: RISC checksum failed.\n");
-    }
-    else
-    {
-        DEBUG(printk("qla1280: NVRAM configured to load RISC load.\n"));
-        status = 1;
-     }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print(
-                "qla1280_isp_firmware: **** Load RISC code ****\n\r");
-#endif
-    LEAVE("qla1280_isp_firmware");
-    return(status);
+	nvram_t *nv = (nvram_t *) ha->response_ring;
+	uint16_t *wptr;
+	int status = 0;		/* dg 2/27 always loads RISC */
+	int cnt;
+	uint8_t chksum;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+
+	ENTER("qla1280_isp_firmware");
+
+	/* Verify valid NVRAM checksum. */
+	wptr = (uint16_t *) ha->response_ring;
+	dprintk(1, "qla1280_isp_firmware: Reading NVRAM\n");
+
+	chksum = 0;
+	for (cnt = 0; cnt < sizeof(nvram_t) / 2; cnt++) {
+		*wptr = qla1280_get_nvram_word (ha, cnt);
+		chksum += (uint8_t) * wptr;
+		chksum += (uint8_t) (*wptr >> 8);
+		wptr++;
+	}
+	dprintk(1, "qla1280_isp_firmware: Completed Reading NVRAM\n");
+
+	dprintk(3, "qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n",
+		(char *)nv->id[0], nv->id[1], nv->id[2]);
+
+	/* Bad NVRAM data, load RISC code. */
+	if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
+	    nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1) {
+		printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic "
+		       "number or version in NVRAM.\n");
+		ha->flags.disable_risc_code_load = FALSE;
+	} else
+		ha->flags.disable_risc_code_load =
+			nv->cntr_flags_1.disable_loading_risc_code;
+
+	if (ha->flags.disable_risc_code_load) {
+		dprintk(3,
+			"qla1280_isp_firmware: Telling RISC to verify checksum "
+			"of loaded BIOS code.\n");
+
+		/* Verify checksum of loaded RISC code. */
+		mb[0] = MBC_VERIFY_CHECKSUM;
+		/* mb[1] = ql12_risc_code_addr01; */
+		mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+
+		if (!
+		    (status =
+		     qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
+			/* Start firmware execution. */
+			dprintk(3, "qla1280_isp_firmware: Startng F/W "
+				"execution.\n");
+
+			mb[0] = MBC_EXECUTE_FIRMWARE;
+			/* mb[1] = ql12_risc_code_addr01; */
+			mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+			qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+		} else
+			printk(KERN_INFO "qla1280: RISC checksum failed.\n");
+	} else {
+		dprintk(1, "qla1280: NVRAM configured to load RISC load.\n");
+		status = 1;
+	}
+
+	if (status)
+		dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n");
+
+	LEAVE("qla1280_isp_firmware");
+	return status;
 }
 
 /*
@@ -2529,75 +2603,69 @@
  * Returns:
  *      0 = success.
  */
-STATIC uint8_t
-qla1280_pci_config(scsi_qla_host_t *ha)
+static int
+qla1280_pci_config(struct scsi_qla_host *ha)
 {
-    uint8_t      status = 1;
-    uint32_t     command;
 #if MEMORY_MAPPED_IO
-    uint32_t  page_offset, base;
-    uint32_t   mmapbase;
+	uint32_t page_offset, base;
+	uint32_t mmapbase;
 #endif
-    config_reg_t *creg = 0;
-    uint16_t     buf_wd;
+	uint16_t buf_wd;
+	int status = 1;
 
-    ENTER("qla1280_pci_config");
+	ENTER("qla1280_pci_config");
 
-    /* Get command register. */
-    if (pci_read_config_word(ha->pdev,OFFSET(creg->command), &buf_wd) == PCIBIOS_SUCCESSFUL)
-    {
-        command = buf_wd;
-        /*
-        * Set Bus Master Enable, Memory Address Space Enable and
-        * reset any error bits.
-        */
-        buf_wd &= ~0x7;
+	pci_set_master(ha->pdev);
+	/*
+	 * Set Bus Master Enable, Memory Address Space Enable and
+	 * reset any error bits, in the command register.
+	 */
+	pci_read_config_word (ha->pdev, PCI_COMMAND, &buf_wd);
 #if MEMORY_MAPPED_IO
-        DEBUG(printk("qla1280: MEMORY MAPPED IO is enabled.\n"));
-        buf_wd |= BIT_2 + BIT_1 + BIT_0;
+	dprintk(1, "qla1280: MEMORY MAPPED IO is enabled.\n");
+	buf_wd |= PCI_COMMAND_MEMORY + PCI_COMMAND_IO;
 #else
-        buf_wd |= BIT_2 + BIT_0;
+	buf_wd |= PCI_COMMAND_IO;
 #endif
-        if( pci_write_config_word(ha->pdev,OFFSET(creg->command), buf_wd) )
-        {
-            printk(KERN_WARNING "qla1280: Could not write config word.\n");
-        }
-        /* Get expansion ROM address. */
-        if (pci_read_config_word(ha->pdev,OFFSET(creg->expansion_rom), &buf_wd) == PCIBIOS_SUCCESSFUL)
-        {
-            /* Reset expansion ROM address decode enable. */
-            buf_wd &= ~BIT_0;
-            if (pci_write_config_word(ha->pdev,OFFSET(creg->expansion_rom), buf_wd) == PCIBIOS_SUCCESSFUL)
-            {
+	pci_write_config_word (ha->pdev, PCI_COMMAND, buf_wd);
+	/*
+	 * Reset expansion ROM address decode enable.
+	 */
+	pci_read_config_word (ha->pdev, PCI_ROM_ADDRESS, &buf_wd);
+	buf_wd &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_word (ha->pdev, PCI_ROM_ADDRESS, buf_wd);
+
+	ha->host->io_port = pci_resource_start(ha->pdev, 0);
+	ha->host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
+	ha->iobase = (struct device_reg *) ha->host->io_port;
+
 #if MEMORY_MAPPED_IO
-                /* Get memory mapped I/O address. */
-                pci_read_config_dword(ha->pdev,OFFSET(cfgp->mem_base_addr), &mmapbase);
-                mmapbase &= PCI_BASE_ADDRESS_MEM_MASK;
-
-                /* Find proper memory chunk for memory map I/O reg. */
-                base = mmapbase & PAGE_MASK;
-                page_offset = mmapbase - base;
-                /* Get virtual address for I/O registers. */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-                ha->mmpbase = ioremap_nocache(base, page_offset + 256);
-#else
-                ha->mmpbase = vremap(base,page_offset + 256);
-#endif
-                if( ha->mmpbase )
-                {
-                    ha->mmpbase += page_offset;
-                    /* ha->iobase = ha->mmpbase; */
-                    status = 0;
-                }
-#else /* MEMORY_MAPPED_IO */
-                status = 0;
-#endif /* MEMORY_MAPPED_IO */
-            }
-        }
-    }
+	/*
+	 * Get memory mapped I/O address.
+	 */
+	pci_read_config_word (ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase);
+	mmapbase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	/*
+	 * Find proper memory chunk for memory map I/O reg.
+	 */
+	base = mmapbase & PAGE_MASK;
+	page_offset = mmapbase - base;
+	/*
+	 * Get virtual address for I/O registers.
+	 */
+	ha->mmpbase = ioremap(base, page_offset + 256);
+	if (ha->mmpbase) {
+		ha->mmpbase += page_offset;
+		/* ha->iobase = ha->mmpbase; */
+		status = 0;
+	}
+#else				/* MEMORY_MAPPED_IO */
+	status = 0;
+#endif				/* MEMORY_MAPPED_IO */
 
-    LEAVE("qla1280_pci_config");
-    return(status);
+	LEAVE("qla1280_pci_config");
+	return status;
 }
 
 /*
@@ -2610,109 +2678,116 @@
  * Returns:
  *      0 = success.
  */
-STATIC uint8_t
-qla1280_chip_diag(scsi_qla_host_t *ha)
+static int
+qla1280_chip_diag(struct scsi_qla_host *ha)
 {
-    device_reg_t *reg   = ha->iobase;
-    uint8_t      status = 0;
-    uint16_t     data;
-    uint32_t     cnt;
-    uint16_t     mb[MAILBOX_REGISTER_COUNT];
-
-#ifdef QL_DEBUG_LEVEL_3
-    sprintf(debug_buff, "qla1280_chip_diag: testing device at 0x%p \n\r",&reg->id_l);
-    qla1280_print(debug_buff);
-#endif
-
-    /* Soft reset chip and wait for it to finish. */
-    WRT_REG_WORD(&reg->ictrl, ISP_RESET); 
-    data = qla1280_debounce_register(&reg->ictrl);
-    for (cnt = 6000000; cnt && data & ISP_RESET; cnt--)
-    {
-        SYS_DELAY(5);
-        data = RD_REG_WORD(&reg->ictrl);
-    }
-    if (cnt)
-    {
-        /* Reset register not cleared by chip reset. */
-#if defined(QL_DEBUG_LEVEL_3)
-        qla1280_print("qla1280_chip_diag: reset register cleared by chip reset\n\r");
-#endif
-        WRT_REG_WORD(&reg->cfg_1, 0);
-
-        /* Reset RISC and disable BIOS which
-        allows RISC to execute out of RAM. */
-        WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
-        WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
-        WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
-        data = qla1280_debounce_register(&reg->mailbox0);
-        for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--)
-        {
-            SYS_DELAY(5);
-            data = RD_REG_WORD(&reg->mailbox0);
-        }
-
-        if (cnt)
-        {
-            /* Check product ID of chip */
-#if defined(QL_DEBUG_LEVEL_3)
-            qla1280_print("qla1280_chip_diag: Checking product ID of chip\n\r");
-#endif
-            if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
-                (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
-                RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
-                RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
-                RD_REG_WORD(&reg->mailbox4) != PROD_ID_4)
-            {
-                printk(KERN_INFO "qla1280: Wrong product ID = 0x%x,0x%x,0x%x,0x%x\n",
-                        RD_REG_WORD(&reg->mailbox1),
-                        RD_REG_WORD(&reg->mailbox2),
-                        RD_REG_WORD(&reg->mailbox3),
-                        RD_REG_WORD(&reg->mailbox4) );
-                status = 1;
-            }
-            else
-            {
-                DEBUG(printk("qla1280_chip_diag: Checking mailboxes of chip\n"));
-                /* Wrap Incoming Mailboxes Test. */
-                mb[0] = MBC_MAILBOX_REGISTER_TEST;
-                mb[1] = 0xAAAA;
-                mb[2] = 0x5555;
-                mb[3] = 0xAA55;
-                mb[4] = 0x55AA;
-                mb[5] = 0xA5A5;
-                mb[6] = 0x5A5A;
-                mb[7] = 0x2525;
-                if (!(status = qla1280_mailbox_command(ha,
-                    (BIT_7|BIT_6|BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0),
-                    &mb[0])))
-                {
-                    if (mb[1] != 0xAAAA || mb[2] != 0x5555 ||
-                        mb[3] != 0xAA55 || mb[4] != 0x55AA)
-                        status = 1;
-                    if (mb[5] != 0xA5A5 || mb[6] != 0x5A5A ||
-                        mb[7] != 0x2525)
-                        status = 1;
-                    if( status == 1 )
-                        printk(KERN_INFO "qla1280: Failed mailbox check\n");
-                }
-            }
-        }
-        else
-            status = 1;
-    }
-    else
-        status = 1;
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_chip_diag: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_chip_diag: exiting normally\n\r");
-#endif
-    return(status);
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	struct device_reg *reg = ha->iobase;
+	int status = 0;
+	int cnt;
+	uint16_t data;
+
+	dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", &reg->id_l);
+
+	/* Soft reset chip and wait for it to finish. */
+	WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+	data = qla1280_debounce_register(&reg->ictrl);
+	/*
+	 * This is *AWESOME*
+	 */
+	for (cnt = 6000000; cnt && data & ISP_RESET; cnt--) {
+		udelay(5);
+		data = RD_REG_WORD(&reg->ictrl);
+	}
+	if (cnt) {
+		/* Reset register not cleared by chip reset. */
+		dprintk(3,
+			"qla1280_chip_diag: reset register cleared by chip reset\n");
+
+		WRT_REG_WORD(&reg->cfg_1, 0);
+
+		/* Reset RISC and disable BIOS which
+		   allows RISC to execute out of RAM. */
+		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
+		WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+		WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
+		data = qla1280_debounce_register(&reg->mailbox0);
+		/*
+		 * I *LOVE* this code!
+		 */
+		for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--) {
+			udelay(5);
+			data = RD_REG_WORD(&reg->mailbox0);
+		}
+
+		if (cnt) {
+			/* Check product ID of chip */
+			dprintk(3,
+				"qla1280_chip_diag: Checking product ID of chip\n");
+
+			if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
+			    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
+			     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
+			    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
+			    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
+				printk(KERN_INFO
+				       "qla1280: Wrong product ID = 0x%x,0x%x,0x%x,"
+				       "0x%x\n", RD_REG_WORD(&reg->mailbox1),
+				       RD_REG_WORD(&reg->mailbox2),
+				       RD_REG_WORD(&reg->mailbox3),
+				       RD_REG_WORD(&reg->mailbox4));
+				status = 1;
+			} else {
+				/*
+				 * Enable ints early!!!
+				 */
+				qla1280_enable_intrs(ha);
+				dprintk(1,
+					"qla1280_chip_diag: Checking mailboxes of chip\n");
+				/* Wrap Incoming Mailboxes Test. */
+				mb[0] = MBC_MAILBOX_REGISTER_TEST;
+				mb[1] = 0xAAAA;
+				mb[2] = 0x5555;
+				mb[3] = 0xAA55;
+				mb[4] = 0x55AA;
+				mb[5] = 0xA5A5;
+				mb[6] = 0x5A5A;
+				mb[7] = 0x2525;
+				if (!(status = qla1280_mailbox_command(ha,
+								       BIT_7 |
+								       BIT_6 |
+								       BIT_5 |
+								       BIT_4 |
+								       BIT_3 |
+								       BIT_2 |
+								       BIT_1 |
+								       BIT_0,
+								       &mb
+								       [0]))) {
+					if (mb[1] != 0xAAAA ||
+					    mb[2] != 0x5555 ||
+					    mb[3] != 0xAA55 ||
+					    mb[4] != 0x55AA ||
+					    mb[5] != 0xA5A5 ||
+					    mb[6] != 0x5A5A ||
+					    mb[7] != 0x2525)
+						status = 1;
+					if (status == 1)
+						printk(KERN_INFO
+						       "qla1280: Failed mailbox check\n");
+				}
+			}
+		} else
+			status = 1;
+	} else
+		status = 1;
+
+	if (status)
+		dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_chip_diag: exiting normally\n");
+
+	return status;
 }
 
 /*
@@ -2725,173 +2800,142 @@
  * Returns:
  *      0 = success.
  */
-STATIC uint8_t
-qla1280_setup_chip(scsi_qla_host_t *ha)
-{
-    uint8_t      status = 0;
-    uint16_t     risc_address;
-    uint16_t     *risc_code_address;
-    long         risc_code_size;
-    uint16_t     mb[MAILBOX_REGISTER_COUNT];
-#ifdef QLA1280_UNUSED
-    uint8_t	*sp;
-    int i;
-#endif
-    uint16_t     cnt;
-    int          num;
-    uint8_t    *tbuf;
-    u_long     p_tbuf;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_setup_chip");
-#endif
-
-	if( (tbuf = (uint8_t *)KMALLOC(8000) ) == NULL )
-        {
-            printk("setup_chip: couldn't alloacte memory\n");
-            return(1);
-        }
-        p_tbuf =  VIRT_TO_BUS(tbuf);
-    /* Load RISC code. */
-    /* 
-    risc_address      = ql12_risc_code_addr01;
-    risc_code_address = &ql12_risc_code01[0];
-    risc_code_size    = ql12_risc_code_length01;
-    */
-    risc_address = *QLBoardTbl[ha->devnum].fwstart;  
-    risc_code_address = QLBoardTbl[ha->devnum].fwcode;  
-    risc_code_size    = (long)(*QLBoardTbl[ha->devnum].fwlen & 0xffff);  
-
-    DEBUG(printk("qla1280: DMAing RISC code (%d) words.\n",(int)risc_code_size));
-    DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  Loading RISC code size =(%ld).\n\r",risc_code_size);)
-    DEBUG(qla1280_print(debug_buff));
-    num =0;
-    while (risc_code_size > 0 && !status)
-    {
-        cnt = 2000 >> 1;
-
-        if ( cnt > risc_code_size ) 
-            cnt = risc_code_size;
-
-        DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);)
-        DEBUG(qla1280_print(debug_buff));
-        DEBUG(printk("qla1280_setup_chip:  loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address));
-        BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1));
-        mb[0] = MBC_LOAD_RAM; 
-        /* mb[0] = MBC_LOAD_RAM_A64; */
-        mb[1] = risc_address;
-        mb[4] = cnt;
-        mb[3] = (uint16_t)  ha->request_dma & 0xffff;
-        mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff;
-        mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff);
-        mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff;
-        DEBUG(printk("qla1280_setup_chip: op=%d  0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3]));
-        if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
-            &mb[0]))  )
-        {
-            printk("Failed to load partial segment of f/w\n");
-            break;
-        }
-        /* dump it back */
+#define DUMP_IT_BACK 0		/* for debug of RISC loading */
+static int
+qla1280_setup_chip(struct scsi_qla_host *ha)
+{
+	int status = 0;
+	uint16_t risc_address;
+	uint16_t *risc_code_address;
+	int risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	uint16_t cnt;
+	int num;
+#if DUMP_IT_BACK
+	int i;
+	uint8_t *sp;
+	uint8_t *tbuf;
+#ifdef QLA_64BIT_PTR
+	dma_addr_t p_tbuf;
+#else
+	uint32_t p_tbuf;
+#endif
+#endif
 
-#if 0
-        mb[0] = MBC_DUMP_RAM_A64;
-        mb[1] = risc_address;
-        mb[4] = cnt;
-        mb[3] = (uint16_t)  p_tbuf & 0xffff;
-        mb[2] = (uint16_t) (p_tbuf >> 16) & 0xffff;
-        mb[7] = (uint16_t) (p_tbuf >> 32) & 0xffff;
-        mb[6] = (uint16_t) (p_tbuf >> 48) & 0xffff;
-
-        if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
-            &mb[0]))  )
-        {
-            printk("Failed to dump partial segment of f/w\n");
-            break;
-        }
-        sp =  (uint8_t *)ha->request_ring;
-        for (i = 0; i < (cnt<< 1) ; i++)
-        {
-            if( tbuf[i] != sp[i] )
-            {
-               printk("qla1280 : firmware compare error @ byte (0x%x)\n",i);
-                break;
-            }
-        }
-
-#endif
-        risc_address += cnt;
-        risc_code_size = risc_code_size - cnt;
-        risc_code_address = risc_code_address + cnt;
-        num++;
-    }
-#ifdef QLA1280_UNUSED
-    DEBUG(ql_debug_print = 0;)
-    {
-        for (i = 0; i < ql12_risc_code_length01; i++)
-        {
-            mb[0] = 0x4;
-            mb[1] = ql12_risc_code_addr01 + i;
-            mb[2] = ql12_risc_code01[i];
-
-            status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0,
-                    &mb[0]);
-            if (status)
-            {
-                printk("qla1280 : firmware load failure\n");
-                break;
-            }
-
-            mb[0] = 0x5;
-            mb[1] = ql12_risc_code_addr01 + i;
-            mb[2] = 0;
-
-            status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0,
-                    &mb[0]);
-            if (status)
-            {
-                printk("qla1280 : firmware dump failure\n");
-                break;
-            }
-            if( mb[2] != ql12_risc_code01[i] )
-                printk("qla1280 : firmware compare error @ (0x%x)\n",ql12_risc_code_addr01+i);
-        }
-    }
-    DEBUG(ql_debug_print = 1;)
-#endif
-
-    /* Verify checksum of loaded RISC code. */
-    if (!status)
-    {
-        DEBUG(printk("qla1280_setup_chip: Verifying checksum of loaded RISC code.\n");)
-        mb[0] = MBC_VERIFY_CHECKSUM;
-        /* mb[1] = ql12_risc_code_addr01; */
-        mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
-        
-        if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0])))
-        {
-            /* Start firmware execution. */
-            DEBUG(qla1280_print("qla1280_setup_chip: start firmware running.\n\r");)
-            mb[0] = MBC_EXECUTE_FIRMWARE;
-            /* mb[1] = ql12_risc_code_addr01; */
-            mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
-            qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
-        }
-        else
-            printk("qla1280_setup_chip: Failed checksum.\n");
-    }
-
-	KMFREE(tbuf,8000);
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_setup_chip: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_setup_chip");
+	ENTER("qla1280_setup_chip");
+
+	/* 3.13 */
+#if DUMP_IT_BACK
+	/* get consistent memory allocated for setup_chip */
+	tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf);
+#endif
+
+	/* Load RISC code. */
+	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+	risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen;
+
+	dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n",
+		risc_code_size);
+
+	num = 0;
+	while (risc_code_size > 0 && !status) {
+		cnt = 2000 >> 1;
+
+		if (cnt > risc_code_size)
+			cnt = risc_code_size;
+
+		dprintk(1, "qla1280_setup_chip:  loading risc @ =(0x%p),"
+			"%d,%d(0x%x)\n",
+			risc_code_address, cnt, num, risc_address);
+		memcpy(ha->request_ring, risc_code_address, (cnt << 1));
+
+		flush_cache_all();
+
+		mb[0] = MBC_LOAD_RAM;
+		mb[1] = risc_address;
+		mb[4] = cnt;
+		mb[3] = ha->request_dma & 0xffff;
+		mb[2] = (ha->request_dma >> 16) & 0xffff;
+		mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
+		mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
+		dprintk(1, "qla1280_setup_chip: op=%d  0x%p = 0x%4x,0x%4x,"
+			"0x%4x,0x%4x\n",
+			mb[0], ha->request_dma, mb[6], mb[7], mb[2], mb[3]);
+		if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 |
+						      BIT_2 | BIT_1 | BIT_0,
+						      &mb[0]))) {
+			printk(KERN_ERR
+			       "Failed to load partial segment of f/w\n");
+			break;
+		}
+#if DUMP_IT_BACK
+		mb[0] = MBC_READ_RAM_WORD;
+		mb[1] = risc_address;
+		mb[4] = cnt;
+		mb[3] = p_tbuf & 0xffff;
+		mb[2] = (p_tbuf >> 16) & 0xffff;
+		mb[7] = pci_dma_hi32(p_tbuf) & 0xffff;
+		mb[6] = pci_dma_hi32(p_tbuf) >> 16;
+
+		if ((status = qla1280_mailbox_command(ha,
+						      BIT_4 | BIT_3 | BIT_2 |
+						      BIT_1 | BIT_0,
+						      &mb[0]))) {
+			printk(KERN_ERR
+			       "Failed to dump partial segment of f/w\n");
+			break;
+		}
+		sp = (uint8_t *)ha->request_ring;
+		for (i = 0; i < (cnt << 1); i++) {
+			if (tbuf[i] != sp[i]) {
+				printk(KERN_ERR "qla1280_setup_chip: FW "
+				       "compare error @ byte(0x%x) loop#=%x\n",
+				       i, num);
+				printk(KERN_ERR "setup_chip: FWbyte=%x  "
+				       "FWfromChip=%x\n", sp[i], tbuf[i]);
+				/*break; */
+			}
+		}
+#endif
+		risc_address += cnt;
+		risc_code_size = risc_code_size - cnt;
+		risc_code_address = risc_code_address + cnt;
+		num++;
+	}
+
+	/* Verify checksum of loaded RISC code. */
+	if (!status) {
+		dprintk(1, "qla1280_setup_chip: Verifying checksum of "
+			"loaded RISC code.\n");
+		mb[0] = MBC_VERIFY_CHECKSUM;
+		/* mb[1] = ql12_risc_code_addr01; */
+		mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+
+		if (!(status =
+		      qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
+			/* Start firmware execution. */
+			dprintk(1,
+				"qla1280_setup_chip: start firmware running.\n");
+			mb[0] = MBC_EXECUTE_FIRMWARE;
+			mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+			qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+		} else
+			printk(KERN_ERR
+			       "qla1280_setup_chip: Failed checksum.\n");
+	}
+
+	/* 3.13 */
+#if DUMP_IT_BACK
+	/* free consistent memory allocated for setup_chip */
+	pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
 #endif
-    return(status);
+
+	if (status)
+		dprintk(2, "qla1280_setup_chip: **** FAILED ****\n");
+
+	LEAVE("qla1280_setup_chip");
+	return status;
 }
 
 /*
@@ -2907,61 +2951,55 @@
  * Returns:
  *      0 = success.
  */
-STATIC uint8_t
-qla1280_init_rings(scsi_qla_host_t *ha)
+static int
+qla1280_init_rings(struct scsi_qla_host *ha)
 {
-    uint8_t     status = 0;
-    uint16_t    cnt;
-    uint16_t    mb[MAILBOX_REGISTER_COUNT];
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_init_rings");
-#endif
-    /* Clear outstanding commands array. */
-    for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
-        ha->outstanding_cmds[cnt] = 0;
-
-    /* Initialize request queue. */
-    ha->request_ring_ptr = ha->request_ring;
-    ha->req_ring_index   = 0;
-    ha->req_q_cnt        = REQUEST_ENTRY_CNT;
-    /* mb[0] = MBC_INIT_REQUEST_QUEUE; */
-    mb[0] = MBC_INIT_REQUEST_QUEUE_A64;
-    mb[1] = REQUEST_ENTRY_CNT;
-    mb[3] = (uint16_t)LS_64BITS(ha->request_dma);
-    mb[2] = (uint16_t)( LS_64BITS(ha->request_dma) >> 16);
-    mb[4] = 0;
-    mb[7] = (uint16_t)MS_64BITS(ha->request_dma);
-    mb[6] = (uint16_t)( MS_64BITS(ha->request_dma) >> 16);
-    if (!(status = qla1280_mailbox_command(ha,
-        BIT_7|BIT_6|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
-        &mb[0])))
-    {
-        /* Initialize response queue. */
-        ha->response_ring_ptr = ha->response_ring;
-        ha->rsp_ring_index    = 0;
-        /* mb[0] = MBC_INIT_RESPONSE_QUEUE; */
-        mb[0] = MBC_INIT_RESPONSE_QUEUE_A64;
-        mb[1] = RESPONSE_ENTRY_CNT;
-        mb[3] = (uint16_t)LS_64BITS(ha->response_dma);
-        mb[2] = (uint16_t)(LS_64BITS(ha->response_dma) >> 16);
-        mb[5] = 0;
-        mb[7] = (uint16_t)MS_64BITS(ha->response_dma);
-        mb[6] = (uint16_t)(MS_64BITS(ha->response_dma) >> 16);
-        status = qla1280_mailbox_command(ha,
-                BIT_7|BIT_6|BIT_5|BIT_3|BIT_2|BIT_1|BIT_0,
-                &mb[0]);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_init_rings: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_init_rings");
-#endif
-    return(status);
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status = 0;
+	int cnt;
+
+	ENTER("qla1280_init_rings");
+
+	/* Clear outstanding commands array. */
+	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+		ha->outstanding_cmds[cnt] = 0;
+
+	/* Initialize request queue. */
+	ha->request_ring_ptr = ha->request_ring;
+	ha->req_ring_index = 0;
+	ha->req_q_cnt = REQUEST_ENTRY_CNT;
+	/* mb[0] = MBC_INIT_REQUEST_QUEUE; */
+	mb[0] = MBC_INIT_REQUEST_QUEUE_A64;
+	mb[1] = REQUEST_ENTRY_CNT;
+	mb[3] = ha->request_dma & 0xffff;
+	mb[2] = (ha->request_dma >> 16) & 0xffff;
+	mb[4] = 0;
+	mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
+	mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
+	if (!(status = qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_4 |
+					       BIT_3 | BIT_2 | BIT_1 | BIT_0,
+					       &mb[0]))) {
+		/* Initialize response queue. */
+		ha->response_ring_ptr = ha->response_ring;
+		ha->rsp_ring_index = 0;
+		/* mb[0] = MBC_INIT_RESPONSE_QUEUE; */
+		mb[0] = MBC_INIT_RESPONSE_QUEUE_A64;
+		mb[1] = RESPONSE_ENTRY_CNT;
+		mb[3] = ha->response_dma & 0xffff;
+		mb[2] = (ha->response_dma >> 16) & 0xffff;
+		mb[5] = 0;
+		mb[7] = pci_dma_hi32(ha->response_dma) & 0xffff;
+		mb[6] = pci_dma_hi32(ha->response_dma) >> 16;
+		status = qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_5 |
+						 BIT_3 | BIT_2 | BIT_1 | BIT_0,
+						 &mb[0]);
+	}
+
+	if (status)
+		dprintk(2, "qla1280_init_rings: **** FAILED ****\n");
+
+	LEAVE("qla1280_init_rings");
+	return status;
 }
 
 /*
@@ -2977,322 +3015,313 @@
  * Returns:
  *      0 = success.
  */
-STATIC uint8_t
-qla1280_nvram_config(scsi_qla_host_t *ha)
+static int
+qla1280_nvram_config(struct scsi_qla_host *ha)
 {
-    device_reg_t *reg   = ha->iobase;
-    nvram_t      *nv    = (nvram_t *)ha->response_ring; 
-    uint8_t      status = 0;
-    uint32_t     b, t, l;
-    uint16_t     *wptr;
-    uint16_t     mb[MAILBOX_REGISTER_COUNT];
-    uint8_t      cnt;
-    uint8_t      chksum;
-    uint32_t     nvsize;
-
-#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
-    uint8_t      saved_print_status = ql_debug_print;
-#endif
-    ENTER("qla1280_nvram_config");
-#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
-    ql_debug_print = FALSE;
-#endif
-
-    /* Verify valid NVRAM checksum. */
-#if  USE_NVRAM_DEFAULTS
-    chksum = 1;
+	struct device_reg *reg = ha->iobase;
+	nvram_t *nv = (nvram_t *)ha->response_ring;
+	int status = 0;
+	int cnt;
+	int bus, target, lun;
+	uint16_t *wptr;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	uint8_t chksum;
+	int nvsize;
+
+#if DEBUG_PRINT_NVRAM
+	int saved_print_status = ql_debug_print;
+#endif
+	ENTER("qla1280_nvram_config");
+
+	/* Verify valid NVRAM checksum. */
+#if USE_NVRAM_DEFAULTS
+	chksum = 1;
 #else
-    wptr = (uint16_t *)ha->response_ring;
-    chksum = 0;
-    if( ha->device_id == QLA12160_DEVICE_ID ||  
-        ha->device_id == QLA10160_DEVICE_ID )  
-    nvsize = sizeof(nvram160_t)/2;
-    else
-    nvsize = sizeof(nvram_t)/2;
-    for( cnt = 0; cnt < nvsize; cnt++ ) 
-    {
-        *wptr = qla1280_get_nvram_word(ha, cnt); 
-        chksum += (uint8_t)*wptr;
-        chksum += (uint8_t)(*wptr >> 8);
-        wptr++;
-    }
+	wptr = (uint16_t *) ha->response_ring;
+	chksum = 0;
+	if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
+	    ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160)
+		nvsize = sizeof(nvram160_t) / 2;
+	else
+		nvsize = sizeof(nvram_t) / 2;
+	for (cnt = 0; cnt < nvsize; cnt++) {
+		*wptr = qla1280_get_nvram_word(ha, cnt);
+		chksum += (uint8_t) * wptr;
+		chksum += (uint8_t) (*wptr >> 8);
+		wptr++;
+	}
 #endif
 
+	/* Bad NVRAM data, set defaults parameters. */
+	if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
+	    nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1) {
+#if USE_NVRAM_DEFAULTS
+		dprintk(1, "Using defaults for NVRAM\n");
+#else
+		dprintk(1, "Using defaults for NVRAM: \n");
+		dprintk(1, "checksum=0x%x, Id=%c, version=0x%x\n",
+			chksum, nv->id[0], nv->version);
+		memset(ha->response_ring, 0, sizeof(nvram_t));
+#endif
+
+		/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
+		nv->firmware_feature.w = BIT_0;
+		nv->termination.f.scsi_bus_0_control = 3;
+		nv->termination.f.scsi_bus_1_control = 3;
+		nv->termination.f.auto_term_support = 1;
+
+		for (bus = 0; bus < MAX_BUSES; bus++) {
+			nv->bus[bus].config_1.initiator_id = 7;
+			nv->bus[bus].bus_reset_delay = 5;
+			nv->bus[bus].config_2.async_data_setup_time = 9;
+			nv->bus[bus].config_2.req_ack_active_negation = 1;
+			nv->bus[bus].config_2.data_line_active_negation = 1;
+			nv->bus[bus].selection_timeout = 250;
+			nv->bus[bus].max_queue_depth = 256;
+
+			for (target = 0; target < MAX_TARGETS; target++) {
+				nv->bus[bus].target[target].parameter.f.
+					auto_request_sense = 1;
+				nv->bus[bus].target[target].parameter.f.
+					disconnect_allowed = 1;
+				nv->bus[bus].target[target].parameter.f.
+					tag_queuing = 1;
+				nv->bus[bus].target[target].flags.
+					device_enable = 1;
+			}
+		}
 
-    /* Bad NVRAM data, set defaults parameters. */
-    if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
-        nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1)
-    {
-#if  USE_NVRAM_DEFAULTS
-        DEBUG(printk("Using defaults for NVRAM\n"));
+#if USE_NVRAM_DEFAULTS
+		status = 0;
 #else
-        DEBUG(printk("Using defaults for NVRAM: \n"));
-        DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n",chksum,nv->id[0],nv->version));
-#if defined(QL_DEBUG_LEVEL_3)
-        /* ql_debug_print = 1;
-        qla1280_dump_buffer((caddr_t)ha->response_ring, REQUEST_ENTRY_SIZE);
-        ql_debug_print = 0; */
-#endif
-                wptr = (uint16_t *)ha->response_ring;
-        for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++)
-            *wptr++ = 0;
+		status = 1;
+#endif
+	} else {
+		/* Always force AUTO sense for LINUX SCSI */
+		for (bus = 0; bus < MAX_BUSES; bus++)
+			for (target = 0; target < MAX_TARGETS; target++) {
+				nv->bus[bus].target[target].parameter.f.
+					auto_request_sense = 1;
+			}
+	}
+#if DEBUG_PRINT_NVRAM
+	ql_debug_print = 1;
+#endif
+	dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n",
+		nv->bus[0].config_1.initiator_id);
+	dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n",
+		nv->bus[1].config_1.initiator_id);
+
+	dprintk(1, "qla1280 : bus reset delay[0]=%d\n",
+		nv->bus[0].bus_reset_delay);
+	dprintk(1, "qla1280 : bus reset delay[1]=%d\n",
+		nv->bus[1].bus_reset_delay);
+
+	dprintk(1, "qla1280 : retry count[0]=%d\n", nv->bus[0].retry_count);
+	dprintk(1, "qla1280 : retry delay[0]=%d\n", nv->bus[0].retry_delay);
+	dprintk(1, "qla1280 : retry count[1]=%d\n", nv->bus[1].retry_count);
+	dprintk(1, "qla1280 : retry delay[1]=%d\n", nv->bus[1].retry_delay);
+
+	dprintk(1, "qla1280 : async data setup time[0]=%d\n",
+		nv->bus[0].config_2.async_data_setup_time);
+	dprintk(1, "qla1280 : async data setup time[1]=%d\n",
+		nv->bus[1].config_2.async_data_setup_time);
+
+	dprintk(1, "qla1280 : req/ack active negation[0]=%d\n",
+		nv->bus[0].config_2.req_ack_active_negation);
+	dprintk(1, "qla1280 : req/ack active negation[1]=%d\n",
+		nv->bus[1].config_2.req_ack_active_negation);
+
+	dprintk(1, "qla1280 : data line active negation[0]=%d\n",
+		nv->bus[0].config_2.data_line_active_negation);
+	dprintk(1, "qla1280 : data line active negation[1]=%d\n",
+		nv->bus[1].config_2.data_line_active_negation);
+
+	dprintk(1, "qla1280 : disable loading risc code=%d\n",
+		nv->cntr_flags_1.disable_loading_risc_code);
+
+	dprintk(1, "qla1280 : enable 64bit addressing=%d\n",
+		nv->cntr_flags_1.enable_64bit_addressing);
+
+	dprintk(1, "qla1280 : selection timeout limit[0]=%d\n",
+		nv->bus[0].selection_timeout);
+	dprintk(1, "qla1280 : selection timeout limit[1]=%d\n",
+		nv->bus[1].selection_timeout);
+
+	dprintk(1, "qla1280 : max queue depth[0]=%d\n",
+		nv->bus[0].max_queue_depth);
+	dprintk(1, "qla1280 : max queue depth[1]=%d\n",
+		nv->bus[1].max_queue_depth);
+
+	/* Disable RISC load of firmware. */
+	ha->flags.disable_risc_code_load =
+		nv->cntr_flags_1.disable_loading_risc_code;
+
+#ifdef QLA_64BIT_PTR
+	/* Enable 64bit addressing for OS/System combination supporting it   */
+	/* actual NVRAM bit is: nv->cntr_flags_1.enable_64bit_addressing     */
+	/* but we will ignore it and use BITS_PER_LONG macro to setup for    */
+	/* 64 or 32 bit access of host memory in all x86/ia-64/Alpha systems */
+	ha->flags.enable_64bit_addressing = 1;
+#else
+	ha->flags.enable_64bit_addressing = 0;
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
+	if (ha->flags.enable_64bit_addressing) {
+		printk(KERN_INFO "scsi(%li): 64 Bit PCI Addressing Enabled\n",
+		       ha->host_no);
 
-        /* nv->cntr_flags_1.disable_loading_risc_code = 1; */
-        nv->firmware_feature.w = BIT_0;
-        nv->termination.f.scsi_bus_0_control = 3;
-        nv->termination.f.scsi_bus_1_control = 3;
-        nv->termination.f.auto_term_support = 1;
-
-        for (b = 0; b < MAX_BUSES; b++)
-        {
-            nv->bus[b].config_1.initiator_id = 7;
-            nv->bus[b].bus_reset_delay = 5;
-            nv->bus[b].config_2.async_data_setup_time = 9;
-            nv->bus[b].config_2.req_ack_active_negation = 1;
-            nv->bus[b].config_2.data_line_active_negation = 1;
-            nv->bus[b].selection_timeout = 250;
-            nv->bus[b].max_queue_depth = 256;
-
-            for (t = 0; t < MAX_TARGETS; t++)
-            {
-                nv->bus[b].target[t].parameter.f.auto_request_sense = 1;
-                nv->bus[b].target[t].parameter.f.disconnect_allowed = 1;
-                nv->bus[b].target[t].parameter.f.tag_queuing = 1;
-                nv->bus[b].target[t].flags.device_enable = 1;
-            }
-        }
-
-#if  USE_NVRAM_DEFAULTS
-        status = 0;
-#else
-        status = 1;
+		pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL);
+	}
 #endif
-    }
-    else
-    {
-        /* Always force AUTO sense for LINUX SCSI */
-        for (b = 0; b < MAX_BUSES; b++)
-            for (t = 0; t < MAX_TARGETS; t++)
-            {
-                nv->bus[b].target[t].parameter.f.auto_request_sense = 1;
-            }
-    }
-#if  DEBUG_PRINT_NVRAM
-    ql_debug_print = 1;
-    sprintf(debug_buff,"qla1280 : initiator scsi id bus[0]=%d\n\r",
-            nv->bus[0].config_1.initiator_id);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : initiator scsi id bus[1]=%d\n\r",
-            nv->bus[1].config_1.initiator_id);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : bus reset delay[0]=%d\n\r",
-            nv->bus[0].bus_reset_delay);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : bus reset delay[1]=%d\n\r",
-            nv->bus[1].bus_reset_delay);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : retry count[0]=%d\n\r",
-            nv->bus[0].retry_count);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : retry delay[0]=%d\n\r",
-            nv->bus[0].retry_delay);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : retry count[1]=%d\n\r",
-            nv->bus[1].retry_count);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : retry delay[1]=%d\n\r",
-            nv->bus[1].retry_delay);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : async data setup time[0]=%d\n\r",
-            nv->bus[0].config_2.async_data_setup_time);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : async data setup time[1]=%d\n\r",
-            nv->bus[1].config_2.async_data_setup_time);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : req/ack active negation[0]=%d\n\r",
-            nv->bus[0].config_2.req_ack_active_negation);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : req/ack active negation[1]=%d\n\r",
-            nv->bus[1].config_2.req_ack_active_negation);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : data line active negation[0]=%d\n\r",
-            nv->bus[0].config_2.data_line_active_negation);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : data line active negation[1]=%d\n\r",
-            nv->bus[1].config_2.data_line_active_negation);
-    qla1280_print(debug_buff);
-
-
-    sprintf(debug_buff,"qla1280 : disable loading risc code=%d\n\r",
-            nv->cntr_flags_1.disable_loading_risc_code);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : enable 64bit addressing=%d\n\r",
-            nv->cntr_flags_1.enable_64bit_addressing);
-    qla1280_print(debug_buff);
-
-    sprintf(debug_buff,"qla1280 : selection timeout limit[0]=%d\n\r",
-            nv->bus[0].selection_timeout);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : selection timeout limit[1]=%d\n\r",
-            nv->bus[1].selection_timeout);
-
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : max queue depth[0]=%d\n\r",
-            nv->bus[0].max_queue_depth);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"qla1280 : max queue depth[1]=%d\n\r",
-            nv->bus[1].max_queue_depth);
-    qla1280_print(debug_buff);
-#endif
-
-    DEBUG(ql_debug_print = 0;)
-
-    /* Disable RISC load of firmware. */
-    ha->flags.disable_risc_code_load =
-            nv->cntr_flags_1.disable_loading_risc_code;
-    /* Enable 64bit addressing. */
-    ha->flags.enable_64bit_addressing =
-            nv->cntr_flags_1.enable_64bit_addressing;
-
-    /* Set ISP hardware DMA burst */
-    mb[0] = nv->isp_config.c;
-    WRT_REG_WORD(&reg->cfg_1, mb[0]);
-
-    /* Set SCSI termination. */
-    WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
-    mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
-    WRT_REG_WORD(&reg->gpio_data, mb[0]);
-
-    /* ISP parameter word. */
-    mb[0] = MBC_SET_SYSTEM_PARAMETER;
-    mb[1] = nv->isp_parameter;
-    status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
-
-    /* Firmware feature word. */
-    mb[0] = MBC_SET_FIRMWARE_FEATURES;
-    mb[1] = nv->firmware_feature.w & (BIT_1|BIT_0);
-    status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
-
-    /* Retry count and delay. */
-    mb[0] = MBC_SET_RETRY_COUNT;
-    mb[1] = nv->bus[0].retry_count;
-    mb[2] = nv->bus[0].retry_delay;
-    mb[6] = nv->bus[1].retry_count;
-    mb[7] = nv->bus[1].retry_delay;
-    status |= qla1280_mailbox_command(ha, BIT_7|BIT_6|BIT_2|BIT_1|BIT_0, &mb[0]);
-
-    /* ASYNC data setup time. */
-    mb[0] = MBC_SET_ASYNC_DATA_SETUP;
-    mb[1] = nv->bus[0].config_2.async_data_setup_time;
-    mb[2] = nv->bus[1].config_2.async_data_setup_time;
-    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
-
-    /* Active negation states. */
-    mb[0] = MBC_SET_ACTIVE_NEGATION;
-    mb[1] = 0;
-    if (nv->bus[0].config_2.req_ack_active_negation)
-        mb[1] |= BIT_5;
-    if (nv->bus[0].config_2.data_line_active_negation)
-        mb[1] |= BIT_4;
-    mb[2] = 0;
-    if (nv->bus[1].config_2.req_ack_active_negation)
-        mb[2] |= BIT_5;
-    if (nv->bus[1].config_2.data_line_active_negation)
-        mb[2] |= BIT_4;
-    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
-
-    /* Selection timeout. */
-    mb[0] = MBC_SET_SELECTION_TIMEOUT;
-    mb[1] = nv->bus[0].selection_timeout;
-    mb[2] = nv->bus[1].selection_timeout;
-    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
-
-    for (b = 0; b < ha->ports; b++)
-    {
-        /* SCSI Reset Disable. */
-        ha->bus_settings[b].disable_scsi_reset = nv->bus[b].config_1.scsi_reset_disable;
-
-        /* Initiator ID. */
-        ha->bus_settings[b].id = nv->bus[b].config_1.initiator_id;
-        mb[0] = MBC_SET_INITIATOR_ID;
-        mb[1] = b ? ha->bus_settings[b].id | BIT_7 : ha->bus_settings[b].id;
-        status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
-
-        /* Reset Delay. */
-        ha->bus_settings[b].bus_reset_delay = nv->bus[b].bus_reset_delay;
-
-        /* Command queue depth per device. */
-        ha->bus_settings[b].hiwat = nv->bus[b].max_queue_depth - 1;
-
-        /* Set target parameters. */
-        for (t = 0; t < MAX_TARGETS; t++)
-        {
-            if( ha->device_id == QLA12160_DEVICE_ID ||  
-                ha->device_id == QLA10160_DEVICE_ID )  
-            {
-                status = qla12160_set_target_parameters(ha,b,t,0,(nvram160_t *)nv);
-            }
-			else
-            {
-                /* Set Target Parameters. */
-                mb[0] = MBC_SET_TARGET_PARAMETERS;
-                mb[1] = (uint16_t)(b ? t | BIT_7 :t);
-                mb[1] <<= 8;
-                mb[2] = nv->bus[b].target[t].parameter.c << 8;
-                mb[2] |= TP_AUTO_REQUEST_SENSE;
-                mb[2] &= ~TP_STOP_QUEUE;
-                mb[3] = nv->bus[b].target[t].flags.sync_offset << 8;
-                mb[3] |= nv->bus[b].target[t].sync_period;
-                status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0,
-                    &mb[0]);
-            }
-
-            /* Save Tag queuing enable flag. */
-            mb[0] = BIT_0 << t;
-            if (nv->bus[b].target[t].parameter.f.tag_queuing)
-                ha->bus_settings[b].qtag_enables |= mb[0];
-
-            /* Save Device enable flag. */
-            if (nv->bus[b].target[t].flags.device_enable)
-                ha->bus_settings[b].device_enables |= mb[0];
-
-            /* Save LUN disable flag. */
-            if (nv->bus[b].target[t].flags.lun_disable)
-                ha->bus_settings[b].lun_disables |= mb[0];
-
-            /* Set Device Queue Parameters. */
-            for (l = 0; l < MAX_LUNS; l++)
-            {
-                mb[0] = MBC_SET_DEVICE_QUEUE;
-                mb[1] = (uint16_t)(b ? t | BIT_7 :t);
-                mb[1] = mb[1] << 8 | l;
-                mb[2] = nv->bus[b].max_queue_depth;
-                mb[3] = nv->bus[b].target[t].execution_throttle;
-                status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0,
-                        &mb[0]);
-            }
-        }
-    }
-    DEBUG(ql_debug_print = 0;)
-
-#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
-    ql_debug_print = saved_print_status;
-#endif
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    DEBUG(if (status))
-        DEBUG(qla1280_print("qla1280_nvram_config: **** FAILED ****\n\r");)
+
+	/* Set ISP hardware DMA burst */
+	mb[0] = nv->isp_config.c;
+	WRT_REG_WORD(&reg->cfg_1, mb[0]);
+
+	/* Set SCSI termination. */
+	WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
+	mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
+	WRT_REG_WORD(&reg->gpio_data, mb[0]);
+
+	/* ISP parameter word. */
+	mb[0] = MBC_SET_SYSTEM_PARAMETER;
+	mb[1] = nv->isp_parameter;
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
+	/* Firmware feature word. */
+	mb[0] = MBC_SET_FIRMWARE_FEATURES;
+	mb[1] = nv->firmware_feature.w & (BIT_1 | BIT_0);
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
+	/* Retry count and delay. */
+	mb[0] = MBC_SET_RETRY_COUNT;
+	mb[1] = nv->bus[0].retry_count;
+	mb[2] = nv->bus[0].retry_delay;
+	mb[6] = nv->bus[1].retry_count;
+	mb[7] = nv->bus[1].retry_delay;
+	status |=
+		qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_2 | BIT_1 | BIT_0,
+					&mb[0]);
+
+	/* ASYNC data setup time. */
+	mb[0] = MBC_SET_ASYNC_DATA_SETUP;
+	mb[1] = nv->bus[0].config_2.async_data_setup_time;
+	mb[2] = nv->bus[1].config_2.async_data_setup_time;
+	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	/* Active negation states. */
+	mb[0] = MBC_SET_ACTIVE_NEGATION;
+	mb[1] = 0;
+	if (nv->bus[0].config_2.req_ack_active_negation)
+		mb[1] |= BIT_5;
+	if (nv->bus[0].config_2.data_line_active_negation)
+		mb[1] |= BIT_4;
+	mb[2] = 0;
+	if (nv->bus[1].config_2.req_ack_active_negation)
+		mb[2] |= BIT_5;
+	if (nv->bus[1].config_2.data_line_active_negation)
+		mb[2] |= BIT_4;
+	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	/* Selection timeout. */
+	mb[0] = MBC_SET_SELECTION_TIMEOUT;
+	mb[1] = nv->bus[0].selection_timeout;
+	mb[2] = nv->bus[1].selection_timeout;
+	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	for (bus = 0; bus < ha->ports; bus++) {
+		/* SCSI Reset Disable. */
+		ha->bus_settings[bus].disable_scsi_reset =
+			nv->bus[bus].config_1.scsi_reset_disable;
+
+		/* Initiator ID. */
+		ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
+		mb[0] = MBC_SET_INITIATOR_ID;
+		mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
+			ha->bus_settings[bus].id;
+		status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
+		/* Reset Delay. */
+		ha->bus_settings[bus].bus_reset_delay =
+			nv->bus[bus].bus_reset_delay;
+
+		/* Command queue depth per device. */
+		ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
+
+		/* Set target parameters. */
+		for (target = 0; target < MAX_TARGETS; target++) {
+			uint8_t mr = BIT_3 | BIT_2 | BIT_1 | BIT_0;
+
+			/* Set Target Parameters. */
+			mb[0] = MBC_SET_TARGET_PARAMETERS;
+			mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
+			mb[1] <<= 8;
+
+			mb[2] = nv->bus[bus].target[target].parameter.c << 8;
+			mb[2] |= TP_AUTO_REQUEST_SENSE;
+			mb[2] &= ~TP_STOP_QUEUE;
+
+			mb[3] =
+				nv->bus[bus].target[target].flags.sync_offset << 8;
+			mb[3] |= nv->bus[bus].target[target].sync_period;
+
+			if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
+			    ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) {
+				nvram160_t *nv2 = (nvram160_t *) nv;
+				mb[2] |=
+					nv2->bus[bus].target[target].flags.
+					enable_ppr << 5;
+
+				mb[6] =
+					nv2->bus[bus].target[target].flags.
+					ppr_options << 8;
+				mb[6] |=
+					nv2->bus[bus].target[target].flags.
+					ppr_bus_width;
+				mr |= BIT_6;
+			}
+			status = qla1280_mailbox_command(ha, mr, &mb[0]);
+
+			/* Save Tag queuing enable flag. */
+			mb[0] = BIT_0 << target;
+			if (nv->bus[bus].target[target].parameter.f.tag_queuing)
+				ha->bus_settings[bus].qtag_enables |= mb[0];
+
+			/* Save Device enable flag. */
+			if (nv->bus[bus].target[target].flags.device_enable)
+				ha->bus_settings[bus].device_enables |= mb[0];
+
+			/* Save LUN disable flag. */
+			if (nv->bus[bus].target[target].flags.lun_disable)
+				ha->bus_settings[bus].lun_disables |= mb[0];
+
+			/* Set Device Queue Parameters. */
+			for (lun = 0; lun < MAX_LUNS; lun++) {
+				mb[0] = MBC_SET_DEVICE_QUEUE;
+				mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
+				mb[1] = mb[1] << 8 | lun;
+				mb[2] = nv->bus[bus].max_queue_depth;
+				mb[3] = nv->bus[bus].target[target].execution_throttle;
+				status |=
+					qla1280_mailbox_command(ha,
+								BIT_3 | BIT_2 |
+								BIT_1 | BIT_0,
+								&mb[0]);
+			}
+		}
+	}
+
+#if DEBUG_PRINT_NVRAM
+	ql_debug_print = saved_print_status;
 #endif
-    LEAVE("qla1280_nvram_config");
-    return(status);
+
+	if (status)
+		dprintk(2, "qla1280_nvram_config: **** FAILED ****\n");
+
+	LEAVE("qla1280_nvram_config");
+	return status;
 }
 
 /*
@@ -3307,36 +3336,32 @@
  * Returns:
  *      data word.
  */
-STATIC uint16_t
-qla1280_get_nvram_word(scsi_qla_host_t *ha, uint32_t address)
+static uint16_t
+qla1280_get_nvram_word(struct scsi_qla_host *ha, uint32_t address)
 {
-    uint32_t nv_cmd;
-    uint16_t data;
+	uint32_t nv_cmd;
+	uint16_t data;
 
 #ifdef QL_DEBUG_ROUTINES
-    uint8_t  saved_print_status = ql_debug_print;
-#endif
-#ifdef QL_DEBUG_LEVEL_4
-    ENTER("qla1280_get_nvram_word");
+	int saved_print_status = ql_debug_print;
 #endif
 
-    nv_cmd = address << 16;
-    nv_cmd |= NV_READ_OP;
+	nv_cmd = address << 16;
+	nv_cmd |= NV_READ_OP;
 
 #ifdef QL_DEBUG_ROUTINES
-    ql_debug_print = FALSE;
+	ql_debug_print = FALSE;
 #endif
-    data = qla1280_nvram_request(ha, nv_cmd);
+	data = qla1280_nvram_request(ha, nv_cmd);
 #ifdef QL_DEBUG_ROUTINES
-    ql_debug_print = saved_print_status;
+	ql_debug_print = saved_print_status;
 #endif
 
-#ifdef QL_DEBUG_LEVEL_4
-    qla1280_print("qla1280_get_nvram_word: exiting normally NVRAM data = ");
-    qla1280_output_number((uint32_t)data, 16);
-    qla1280_print("\n\r");
-#endif
-    return(data);
+	dprintk(4,
+		"qla1280_get_nvram_word: exiting normally NVRAM data = 0x%x",
+		data);
+
+	return data;
 }
 
 /*
@@ -3353,76 +3378,57 @@
  * Returns:
  *      data word.
  */
-STATIC uint16_t
-qla1280_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
+static uint16_t
+qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd)
+{
+	struct device_reg *reg = ha->iobase;
+	int cnt;
+	uint16_t data = 0;
+	uint16_t reg_data;
+
+	/* Send command to NVRAM. */
+
+	nv_cmd <<= 5;
+	for (cnt = 0; cnt < 11; cnt++) {
+		if (nv_cmd & BIT_31)
+			qla1280_nv_write(ha, NV_DATA_OUT);
+		else
+			qla1280_nv_write(ha, 0);
+		nv_cmd <<= 1;
+	}
+
+	/* Read data from NVRAM. */
+
+	for (cnt = 0; cnt < 16; cnt++) {
+		WRT_REG_WORD(&reg->nvram, (NV_SELECT | NV_CLOCK));
+		NVRAM_DELAY();
+		data <<= 1;
+		reg_data = RD_REG_WORD(&reg->nvram);
+		if (reg_data & NV_DATA_IN)
+			data |= BIT_0;
+		WRT_REG_WORD(&reg->nvram, NV_SELECT);
+		NVRAM_DELAY();
+	}
+
+	/* Deselect chip. */
+
+	WRT_REG_WORD(&reg->nvram, NV_DESELECT);
+	NVRAM_DELAY();
+
+	return data;
+}
+
+static void
+qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data)
 {
-    uint8_t      cnt;
-    device_reg_t *reg = ha->iobase;
-    uint16_t     data = 0;
-    uint16_t     reg_data;
-
-    /* Send command to NVRAM. */
-
-    nv_cmd <<= 5;
-    for (cnt = 0; cnt < 11; cnt++)
-    {
-        if (nv_cmd & BIT_31)
-            qla1280_nv_write(ha, NV_DATA_OUT);
-        else
-            qla1280_nv_write(ha, 0);
-        nv_cmd <<= 1;
-    }
-
-    /* Read data from NVRAM. */
-
-    for (cnt = 0; cnt < 16; cnt++)
-    {
-        WRT_REG_WORD(&reg->nvram, NV_SELECT+NV_CLOCK);
-        /* qla1280_nv_delay(ha); */
-        NVRAM_DELAY();
-        data <<= 1;
-        reg_data = RD_REG_WORD(&reg->nvram);
-        if (reg_data & NV_DATA_IN)
-            data |= BIT_0;
-        WRT_REG_WORD(&reg->nvram, NV_SELECT);
-        /* qla1280_nv_delay(ha); */
-        NVRAM_DELAY();
-    }
-
-    /* Deselect chip. */
-
-    WRT_REG_WORD(&reg->nvram, NV_DESELECT);
-    /* qla1280_nv_delay(ha); */
-    NVRAM_DELAY();
-
-    return(data);
-}
-
-STATIC void
-qla1280_nv_write(scsi_qla_host_t *ha, uint16_t data)
-{
-    device_reg_t *reg = ha->iobase;
-
-    WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
-    NVRAM_DELAY();
-    /* qla1280_nv_delay(ha); */
-    WRT_REG_WORD(&reg->nvram, data | NV_SELECT | NV_CLOCK);
-    /* qla1280_nv_delay(ha); */
-    NVRAM_DELAY();
-    WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
-    /* qla1280_nv_delay(ha); */
-    NVRAM_DELAY();
-}
-
-STATIC void
-qla1280_nv_delay(scsi_qla_host_t *ha)
-{
-    device_reg_t *reg = ha->iobase;
-    int          cnt  = NV_DELAY_COUNT;
-    uint16_t     data = 0;
+	struct device_reg *reg = ha->iobase;
 
-    while (cnt--)
-        data |= RD_REG_WORD(&reg->nvram);
+	WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
+	NVRAM_DELAY();
+	WRT_REG_WORD(&reg->nvram, data | NV_SELECT | NV_CLOCK);
+	NVRAM_DELAY();
+	WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
+	NVRAM_DELAY();
 }
 
 /*
@@ -3440,112 +3446,110 @@
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_mailbox_command(scsi_qla_host_t *ha, uint8_t mr, uint16_t *mb)
+static int
+qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t * mb)
 {
-    device_reg_t *reg   = ha->iobase;
-    uint8_t      status = 0;
-    uint32_t     cnt;
-    uint16_t     *optr, *iptr;
-    uint16_t     data;
-    srb_t        *done_q_first = 0;
-    srb_t        *done_q_last = 0;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_mailbox_command");
-#endif
-
-    /* Acquire interrupt specific lock */
-    QLA1280_INTR_LOCK(ha);
-    DRIVER_LOCK
-            ha->flags.mbox_busy = TRUE;
-
-    /* Load mailbox registers. */
-    optr = (uint16_t *)&reg->mailbox0;
-    iptr = mb;
-    for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++)
-    {
-        if (mr & BIT_0)
-        {
-            WRT_REG_WORD(optr, (*iptr));
-        }
-
-        mr >>= 1;
-        optr++;
-        iptr++;
-    }
-    /* Issue set host interrupt command. */
-    ha->flags.mbox_int = FALSE;
-    WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
-    data = qla1280_debounce_register(&reg->istatus);
-
-    /* Wait for 30 seconds for command to finish. */
-    for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--)
-    {
-        /* Check for pending interrupts. */
-        if (data & RISC_INT)
-        {
-            qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
-        }
-        SYS_DELAY(1);
-        data = RD_REG_WORD(&reg->istatus);
-    }
-
-    /* Check for mailbox command timeout. */
-    if ( !cnt )
-    {
-#ifdef QL_DEBUG_LEVEL_2
-        qla1280_print(
-                "qla1280_mailbox_command: **** Command Timeout, mailbox0 = ");
-        qla1280_output_number((uint32_t)mb[0], 16);
-        qla1280_print(" ****\n\r");
-#endif
-        ha->flags.isp_abort_needed = TRUE; 
-        status = 1;
-    }
-    else if (ha->mailbox_out[0] != MBS_CMD_CMP)
-        status = 1;
-
-    /* Load return mailbox registers. */
-    optr = mb;
-    iptr = (uint16_t *)&ha->mailbox_out[0];
-    mr = MAILBOX_REGISTER_COUNT;
-    while (mr--)
-        *optr++ = *iptr++;
-
-    /* Go check for any response interrupts pending. */
-    ha->flags.mbox_busy = FALSE;
-    qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
-
-    /* Release interrupt specific lock */
-    QLA1280_INTR_UNLOCK(ha);
-    DRIVER_UNLOCK
-
-            if (ha->flags.isp_abort_needed)
-        qla1280_abort_isp(ha);
-
-    if (ha->flags.reset_marker)
-        qla1280_rst_aen(ha);
-
-    if (done_q_first)
-        qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-    {
-        qla1280_print("qla1280_mailbox_command: **** FAILED, mailbox0 = ");
-        qla1280_output_number((uint32_t)mb[0], 16);
-        qla1280_print(" ****\n\r");
-    }
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_mailbox_command");
+	struct device_reg *reg = ha->iobase;
+#if 0
+	srb_t *done_q_first = 0;
+	srb_t *done_q_last = 0;
+#endif
+	int status = 0;
+	int cnt;
+	uint16_t *optr, *iptr;
+	uint16_t data;
+
+	ENTER("qla1280_mailbox_command");
+
+	ha->flags.mbox_busy = TRUE;
+
+	if (!ha->flags.ints_enabled)
+		printk(KERN_DEBUG
+		       "Running qla1280_mailbox_command() with interrupts "
+		       "disabled!\n");
+	/*
+	 * We really should start out by verifying that the mailbox is available
+	 * before starting sending the command data
+	 */
+	/* Load mailbox registers. */
+	optr = (uint16_t *) &reg->mailbox0;
+	iptr = mb;
+	for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++) {
+		if (mr & BIT_0) {
+			WRT_REG_WORD(optr, (*iptr));
+		}
+
+		mr >>= 1;
+		optr++;
+		iptr++;
+	}
+
+	/* Issue set host interrupt command. */
+	ha->flags.mbox_int = FALSE;
+	ha->flags.mbox_busy = FALSE;
+	WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
+	data = qla1280_debounce_register(&reg->istatus);
+
+	/*
+	 * This is insane - instead of looping to wait for the interrupt 
+	 * to appear and run the handler (this is insane!!), use a waitqueue
+	 * and go to sleep.
+	 *
+	 * We are never called here from interrupt context anyway!    /Jes
+	 */
+	/* Wait for 30 seconds for command to finish. */
+	for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--) {
+		/* Check for pending interrupts. */
+#if 0
+		if (data & RISC_INT) {
+			qla1280_isr(ha, &done_q_first, &done_q_last);
+		} else
+#endif
+			udelay(1);
+
+		data = RD_REG_WORD(&reg->istatus);
+	}
+
+	/* Check for mailbox command timeout. */
+	if (!cnt) {
+		printk(KERN_WARNING
+		       "qla1280_mailbox_command: **** Command Timeout, "
+		       "mailbox0 = 0x%x****\n", mb[0]);
+
+		ha->flags.isp_abort_needed = TRUE;
+		status = 1;
+	} else if (ha->mailbox_out[0] != MBS_CMD_CMP)
+		status = 1;
+
+	/* Load return mailbox registers. */
+	optr = mb;
+	iptr = (uint16_t *) &ha->mailbox_out[0];
+	mr = MAILBOX_REGISTER_COUNT;
+	memcpy(optr, iptr, MAILBOX_REGISTER_COUNT * sizeof(uint16_t));
+
+#if 0
+	/* Go check for any response interrupts pending. */
+	qla1280_isr(ha, &done_q_first, &done_q_last);
 #endif
-    return(status);
+
+	if (ha->flags.isp_abort_needed)
+		qla1280_abort_isp(ha);
+
+	if (ha->flags.reset_marker)
+		qla1280_rst_aen(ha);
+
+#if 0
+	if (done_q_first)
+		qla1280_done (ha, &done_q_first, &done_q_last);
+#endif
+
+	if (status)
+		dprintk(2,
+			"qla1280_mailbox_command: **** FAILED, mailbox0 = 0x%x "
+			"****n", mb[0]);
+
+	LEAVE("qla1280_mailbox_command");
+	return status;
 }
 
 /*
@@ -3555,43 +3559,32 @@
  * Input:
  *      ha = adapter block pointer.
  */
-STATIC void
-qla1280_poll(scsi_qla_host_t *ha)
+static void
+qla1280_poll(struct scsi_qla_host *ha)
 {
-    device_reg_t    *reg   = ha->iobase;
-    uint16_t        data;
-    srb_t           *done_q_first = 0;
-    srb_t           *done_q_last = 0;
-
-#ifdef QL_DEBUG_LEVEL_3
-    /* ENTER("qla1280_poll"); */
-#endif
-
-    /* Acquire interrupt specific lock */
-    QLA1280_INTR_LOCK(ha);
-
-    /* Check for pending interrupts. */
-    data = RD_REG_WORD(&reg->istatus);
-    if (data & RISC_INT)
-        qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
-
-    /* Release interrupt specific lock */
-    QLA1280_INTR_UNLOCK(ha);
-
-    if (!ha->flags.mbox_busy)
-    {
-        if (ha->flags.isp_abort_needed)
-            qla1280_abort_isp(ha);
-        if (ha->flags.reset_marker)
-            qla1280_rst_aen(ha);
-    }
+	struct device_reg *reg = ha->iobase;
+	uint16_t data;
+	srb_t *done_q_first = 0;
+	srb_t *done_q_last = 0;
+
+	/* ENTER("qla1280_poll"); */
+
+	/* Check for pending interrupts. */
+	data = RD_REG_WORD(&reg->istatus);
+	if (data & RISC_INT)
+		qla1280_isr(ha, &done_q_first, &done_q_last);
+
+	if (!ha->flags.mbox_busy) {
+		if (ha->flags.isp_abort_needed)
+			qla1280_abort_isp(ha);
+		if (ha->flags.reset_marker)
+			qla1280_rst_aen(ha);
+	}
 
-    if (done_q_first)
-        qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+	if (done_q_first)
+		qla1280_done(ha, &done_q_first, &done_q_last);
 
-#ifdef QL_DEBUG_LEVEL_3
-    /* LEAVE("qla1280_poll"); */
-#endif
+	/* LEAVE("qla1280_poll"); */
 }
 
 /*
@@ -3599,54 +3592,54 @@
  *      Issue SCSI bus reset.
  *
  * Input:
- *      ha = adapter block pointer.
- *      b  = SCSI bus number.
+ *      ha  = adapter block pointer.
+ *      bus = SCSI bus number.
  *
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_bus_reset(scsi_qla_host_t *ha, uint8_t b)
+static int
+qla1280_bus_reset(struct scsi_qla_host *ha, int bus)
 {
-    uint8_t     status;
-    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status;
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_bus_reset: entered\n\r");
+	dprintk(3, "qla1280_bus_reset: entered\n");
+
+	if (qla1280_verbose)
+		printk(KERN_INFO "scsi(%li): Resetting SCSI BUS (%i)\n",
+		       ha->host_no, bus);
+
+	mb[0] = MBC_BUS_RESET;
+	mb[1] = ha->bus_settings[bus].bus_reset_delay;
+	mb[2] = (uint16_t) bus;
+	status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	if (status) {
+		if (ha->bus_settings[bus].failed_reset_count > 2)	/* dg - 03/13/99 */
+			ha->bus_settings[bus].scsi_bus_dead = TRUE;
+		ha->bus_settings[bus].failed_reset_count++;
+	} else {
+		/*
+		 * Eeeeep! This is evil! /Jes
+		 */
+#if 0
+		mdelay(4000);
+#else
+		schedule_timeout(4 * HZ);
 #endif
-   if( qla1280_verbose )
-   {
-    printk("scsi(%d): Resetting SCSI BUS (%d)\n",(int)ha->host_no,b);
-   }
-
-    mb[0] = MBC_BUS_RESET;
-    mb[1] = ha->bus_settings[b].bus_reset_delay;
-    mb[2] = (uint16_t)b;
-    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
-
-    if (status)
-    {
-        if (ha->bus_settings[b].failed_reset_count > 2)                  /* dg - 03/13/99 */
-            ha->bus_settings[b].scsi_bus_dead = TRUE;
-        ha->bus_settings[b].failed_reset_count++;
-    }
+		ha->bus_settings[bus].scsi_bus_dead = FALSE;	/* dg - 03/13/99 */
+		ha->bus_settings[bus].failed_reset_count = 0;
+		/* Issue marker command. */
+		qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL);
+	}
+
+	if (status)
+		dprintk(2, "qla1280_bus_reset: **** FAILED ****\n");
 	else
-    {
-       QLA1280_DELAY(4);
-       ha->bus_settings[b].scsi_bus_dead = FALSE;                         /* dg - 03/13/99 */
-       ha->bus_settings[b].failed_reset_count = 0;
-       /* Issue marker command. */
-       qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
-    }
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_bus_reset: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_bus_reset: exiting normally\n\r");
-#endif
-    return(status);
+		dprintk(3, "qla1280_bus_reset: exiting normally\n");
+
+	return status;
 }
 
 /*
@@ -3654,40 +3647,34 @@
  *      Issue bus device reset message to the target.
  *
  * Input:
- *      ha = adapter block pointer.
- *      b  = SCSI BUS number.
- *      t  = SCSI ID.
+ *      ha      = adapter block pointer.
+ *      bus     = SCSI BUS number.
+ *      target  = SCSI ID.
  *
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_device_reset(scsi_qla_host_t *ha, uint8_t b, uint32_t t)
+static int
+qla1280_device_reset(struct scsi_qla_host *ha, int bus, int target)
 {
-    uint8_t     status;
-    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status;
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_device_reset");
-#endif
+	ENTER("qla1280_device_reset");
 
-    mb[0] = MBC_ABORT_TARGET;
-    mb[1] = (b ? (t | BIT_7) : t) << 8;
-    mb[2] = 1;
-    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+	mb[0] = MBC_ABORT_TARGET;
+	mb[1] = (bus ? (target | BIT_7) : target) << 8;
+	mb[2] = 1;
+	status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
-    /* Issue marker command. */
-    qla1280_marker(ha, b, t, 0, MK_SYNC_ID);
+	/* Issue marker command. */
+	qla1280_marker(ha, bus, target, 0, MK_SYNC_ID);
 
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_device_reset: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_device_reset");
-#endif
-    return(status);
+	if (status)
+		dprintk(2, "qla1280_device_reset: **** FAILED ****\n");
+
+	LEAVE("qla1280_device_reset");
+	return status;
 }
 
 /*
@@ -3695,40 +3682,34 @@
  *      Issue an abort message to the device
  *
  * Input:
- *      ha = adapter block pointer.
- *      b  = SCSI BUS.
- *      t  = SCSI ID.
- *      l  = SCSI LUN.
+ *      ha     = adapter block pointer.
+ *      bus    = SCSI BUS.
+ *      target = SCSI ID.
+ *      lun    = SCSI LUN.
  *
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_abort_device(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l)
+static int
+qla1280_abort_device(struct scsi_qla_host *ha, int bus, int target, int lun)
 {
-    uint8_t     status;
-    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status;
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_abort_device");
-#endif
+	ENTER("qla1280_abort_device");
 
-    mb[0] = MBC_ABORT_DEVICE;
-    mb[1] = (b ? t | BIT_7 : t) << 8 | l;
-    status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+	mb[0] = MBC_ABORT_DEVICE;
+	mb[1] = (bus ? target | BIT_7 : target) << 8 | lun;
+	status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
 
-    /* Issue marker command. */
-    qla1280_marker(ha, b, t, l, MK_SYNC_ID_LUN);
+	/* Issue marker command. */
+	qla1280_marker(ha, bus, target, lun, MK_SYNC_ID_LUN);
 
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_abort_device: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_abort_device");
-#endif
-    return(status);
+	if (status)
+		dprintk(2, "qla1280_abort_device: **** FAILED ****\n");
+
+	LEAVE("qla1280_abort_device");
+	return status;
 }
 
 /*
@@ -3742,41 +3723,39 @@
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+static int
+qla1280_abort_command(struct scsi_qla_host *ha, srb_t * sp)
 {
-    uint8_t         status;
-    uint16_t        mb[MAILBOX_REGISTER_COUNT];
-    uint32_t        b, t, l;
-    uint32_t        handle;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	unsigned int bus, target, lun;
+	uint32_t handle;
+	int status;
+
+	ENTER("qla1280_abort_command");
+
+	/* Locate handle number. */
+	for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++)
+		if (ha->outstanding_cmds[handle] == sp)
+			break;
+
+	bus = SCSI_BUS_32(sp->cmd);
+	target = SCSI_TCN_32(sp->cmd);
+	lun = SCSI_LUN_32(sp->cmd);
+
+	mb[0] = MBC_ABORT_COMMAND;
+	mb[1] = (bus ? target | BIT_7 : target) << 8 | lun;
+	mb[2] = handle >> 16;
+	mb[3] = handle & 0xffff;
+	status =
+		qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_abort_command");
-#endif
-
-    /* Locate handle number. */
-    for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++)
-        if (ha->outstanding_cmds[handle] == sp)
-            break;
-
-                b  = SCSI_BUS_32(sp->cmd);
-        t  = SCSI_TCN_32(sp->cmd);
-        l  = SCSI_LUN_32(sp->cmd);
+	if (status)
+		dprintk(2, "qla1280_abort_command: **** FAILED ****\n");
 
-        mb[0] = MBC_ABORT_COMMAND;
-        mb[1] = (b ? t | BIT_7 : t) << 8 | l;
-        mb[2] = handle >> 16;
-        mb[3] = (uint16_t)handle;
-        status = qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]);
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-        if (status)
-            qla1280_print("qla1280_abort_command: **** FAILED ****\n\r");
-#endif
-        sp->flags |= SRB_ABORT_PENDING;
+	sp->flags |= SRB_ABORT_PENDING;
 
-        LEAVE("qla1280_abort_command");
-        return(status);
+	LEAVE("qla1280_abort_command");
+	return status;
 }
 
 /*
@@ -3786,25 +3765,21 @@
  * Input:
  *      ha = adapter block pointer.
  */
-STATIC void
-qla1280_reset_adapter(scsi_qla_host_t *ha)
+static void
+qla1280_reset_adapter(struct scsi_qla_host *ha)
 {
-    device_reg_t *reg = ha->iobase;
+	struct device_reg *reg = ha->iobase;
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_reset_adapter");
-#endif
+	ENTER("qla1280_reset_adapter");
 
-    /* Disable ISP chip */
-    ha->flags.online = FALSE;
-    WRT_REG_WORD(&reg->ictrl, ISP_RESET);
-    WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
-    WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
-    WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
+	/* Disable ISP chip */
+	ha->flags.online = FALSE;
+	WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+	WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
+	WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+	WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
 
-#ifdef QL_DEBUG_LEVEL_3
-    LEAVE("qla1280_reset_adapter");
-#endif
+	LEAVE("qla1280_reset_adapter");
 }
 
 /*
@@ -3813,38 +3788,33 @@
  *
  * Input:
  *      ha   = adapter block pointer.
- *      b    = SCSI BUS number
- *      t    = SCSI ID
- *      l    = SCSI LUN
+ *      bus  = SCSI BUS number
+ *      id   = SCSI ID
+ *      lun  = SCSI LUN
  *      type = marker modifier
  */
-STATIC void
-qla1280_marker(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l, uint8_t type)
+static void
+qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type)
 {
-    mrk_entry_t     *pkt;
+	mrk_entry_t *pkt;
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_marker");
-#endif
+	ENTER("qla1280_marker");
 
-    /* Get request packet. */
-    if ( (pkt = (mrk_entry_t *)qla1280_req_pkt(ha)) )
-    {
-        pkt->entry_type = MARKER_TYPE;
-        pkt->lun = (uint8_t)l;
-        pkt->target = (uint8_t)(b ? (t | BIT_7) : t);
-        pkt->modifier = type;
+	/* Get request packet. */
+	if ((pkt = (mrk_entry_t *) qla1280_req_pkt(ha))) {
+		pkt->entry_type = MARKER_TYPE;
+		pkt->lun = (uint8_t) lun;
+		pkt->target = (uint8_t) (bus ? (id | BIT_7) : id);
+		pkt->modifier = type;
 
-        /* Issue command to ISP */
-        qla1280_isp_cmd(ha);
-    }
+		/* Issue command to ISP */
+		qla1280_isp_cmd(ha);
+	}
 
-#ifdef QL_DEBUG_LEVEL_3
-    LEAVE("qla1280_marker");
-#endif
+	LEAVE("qla1280_marker");
 }
 
-#if  QLA1280_64BIT_SUPPORT
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18)
 /*
  * qla1280_64bit_start_scsi
  *      The start SCSI is responsible for building request packets on
@@ -3857,296 +3827,280 @@
  * Returns:
  *      0 = success, was able to issue command.
  */
-STATIC uint8_t
-qla1280_64bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp)
+static int
+qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp)
 {
-    device_reg_t    *reg   = ha->iobase;
-    uint8_t         status = 0;
-    Scsi_Cmnd       *cmd = sp->cmd;
-    uint32_t        cnt;
-    cmd_a64_entry_t     *pkt;
-    uint16_t        req_cnt;
-    uint16_t        seg_cnt;
-    struct scatterlist    *sg = (struct scatterlist *) NULL;
-    uint32_t        *dword_ptr;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_64bit_start_scsi:");
-#endif
-
-    if( qla1280_check_for_dead_scsi_bus(ha, sp) )
-    {
-        return(0);
-    }
-
-    /* Calculate number of entries and segments required. */
-    seg_cnt = 0;
-    req_cnt = 1;
-    if (cmd->use_sg)
-    {
-        seg_cnt =  cmd->use_sg;
-        sg = (struct scatterlist *) cmd->request_buffer;
-            
-        if (seg_cnt > 2)
-        {
-           req_cnt += (uint16_t)(seg_cnt - 2) / 5;
-           if ((uint16_t)(seg_cnt - 2) % 5)
-               req_cnt++;
-        }
-    }
-    else if (cmd->request_bufflen)  /* If data transfer. */
-    {
-        DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen));
-        seg_cnt = 1;
-    }
-
-    /* Acquire ring specific lock */
-    QLA1280_RING_LOCK(ha);
-
-    if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt)
-    {
-        /* Calculate number of free request entries. */
-        cnt = RD_REG_WORD(&reg->mailbox4);
-        if (ha->req_ring_index < cnt)
-            ha->req_q_cnt = cnt - ha->req_ring_index;
-        else
-            ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
-    }
-
-    /* If room for request in request ring. */
-    if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt)
-    {
-        /* Check for room in outstanding command list. */
-        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
-            ha->outstanding_cmds[cnt] != 0; cnt++)
-            ;
-
-        if (cnt < MAX_OUTSTANDING_COMMANDS)
-        {
-            ha->outstanding_cmds[cnt] = sp;
-            ha->req_q_cnt -= req_cnt;
-            CMD_HANDLE(sp->cmd) = (unsigned char *) (u_long) cnt;
-
-            /*
-            * Build command packet.
-            */
-            pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
-
-            pkt->entry_type = COMMAND_A64_TYPE;
-            pkt->entry_count = (uint8_t)req_cnt;
-            pkt->sys_define = (uint8_t)ha->req_ring_index;
-            pkt->handle = (uint32_t)cnt;
-
-            /* Zero out remaining portion of packet. */
-            dword_ptr = (uint32_t *)pkt + 2;
-            for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
-                *dword_ptr++ = 0;
-
-            /* Set ISP command timeout. */
-            pkt->timeout = (uint16_t)30;
-
-            /* Set device target ID and LUN */
-            pkt->lun = SCSI_LUN_32(cmd);
-            pkt->target = SCSI_BUS_32(cmd) ?
-                    (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
-
-            /* Enable simple tag queuing if device supports it. */
-            if (cmd->device->tagged_queue )
-                pkt->control_flags |= BIT_3;
-
-            /* Load SCSI command packet. */
-            pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
-            BCOPY(&(CMD_CDBP(cmd)), pkt->scsi_cdb, pkt->cdb_len);
-            DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]));
-
-            /*
-            * Load data segments.
-            */
-            if (seg_cnt)                /* If data transfer. */
-            {
-                /* Set transfer direction. */
-                if ( (cmd->data_cmnd[0] == WRITE_6) )
-                    pkt->control_flags |= BIT_6;
-                else
-                    pkt->control_flags |= (BIT_5|BIT_6);
-                    
-                sp->dir = pkt->control_flags & (BIT_5|BIT_6);
-
-                /* Set total data segment count. */
-                pkt->dseg_count = seg_cnt;
-
-                /* Setup packet address segment pointer. */
-                dword_ptr = (uint32_t *)&pkt->dseg_0_address;
-
-                if (cmd->use_sg)              /* If scatter gather */
-                {
-                    /* Load command entry data segments. */
-                    for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--)
-                    {
-                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
-                        DEBUG(qla1280_print(debug_buff));
-                        *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address));
-                        *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address));
-                        *dword_ptr++ = sg->length;
-                        sg++;
-                    }
-#ifdef QL_DEBUG_LEVEL_5
-                    qla1280_print(
-                            "qla1280_64bit_start_scsi: Scatter/gather command packet data - ");
-                    qla1280_print("b ");
-                    qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
-                    qla1280_print(" t ");
-                    qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
-                    qla1280_print(" d ");
-                    qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
-                    qla1280_print("\n\r");
-                    qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
-#endif
-                    /*
-                    * Build continuation packets.
-                    */
-                    while (seg_cnt > 0)
-                    {
-                        /* Adjust ring index. */
-                        ha->req_ring_index++;
-                        if (ha->req_ring_index == REQUEST_ENTRY_CNT)
-                        {
-                            ha->req_ring_index = 0;
-                            ha->request_ring_ptr = ha->request_ring;
-                        }
-                        else
-                            ha->request_ring_ptr++;
-
-                        pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
-
-                        /* Zero out packet. */
-                        dword_ptr = (uint32_t *)pkt;
-                        for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++)
-                            *dword_ptr++ = 0;
-
-                        /* Load packet defaults. */
-                        ((cont_a64_entry_t *)pkt)->entry_type =
-                                CONTINUE_A64_TYPE;
-                        ((cont_a64_entry_t *)pkt)->entry_count = 1;
-                        ((cont_a64_entry_t *)pkt)->sys_define = (uint8_t)
-                                ha->req_ring_index;
-
-                        /* Setup packet address segment pointer. */
-                        dword_ptr = (uint32_t *)
-                                &((cont_a64_entry_t *)pkt)->dseg_0_address;
-
-                        /* Load continuation entry data segments. */
-                        for (cnt = 0; cnt < 5 && seg_cnt; cnt++, seg_cnt--)
-                        {
-                            *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address));
-                            *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address));
-                            *dword_ptr++ = sg->length;
-                            sg++;
-                        }
-#ifdef QL_DEBUG_LEVEL_5
-                        qla1280_print(
-                                "qla1280_64bit_start_scsi: continuation packet data - c");
-                        qla1280_print(" b ");
-                        qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
-
-                        qla1280_print(" t ");
-                        qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
-                        qla1280_print(" d ");
-                        qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
-                        qla1280_print("\n\r");
-                        qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
-#endif
-                    }
-                }
-                else                    /* No scatter gather data transfer */
-                {
-                    *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(cmd->request_buffer));
-                    *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(cmd->request_buffer));
-                    *dword_ptr = (uint32_t) cmd->request_bufflen;
-#ifdef QL_DEBUG_LEVEL_5
-                    qla1280_print(
-                            "qla1280_64bit_start_scsi: No scatter/gather command packet data - c");
-                    qla1280_print(" b ");
-                    qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
-                    qla1280_print(" t ");
-                    qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
-                    qla1280_print(" d ");
-                    qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
-                    qla1280_print("\n\r");
-                    qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
-#endif
-                }
-            }
-#ifdef QL_DEBUG_LEVEL_5
-            else                            /* No data transfer */
-            {
-                *dword_ptr++ = (uint32_t) 0;
-                *dword_ptr++ = (uint32_t) 0;
-                *dword_ptr = (uint32_t)  0;
-                qla1280_print(
-                        "qla1280_64bit_start_scsi: No data, command packet data - c");
-                qla1280_print(" b ");
-                qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
-                qla1280_print(" t ");
-                qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
-                qla1280_print(" d ");
-                qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
-                qla1280_print("\n\r");
-                qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
-            }
-#endif
-            /* Adjust ring index. */
-            ha->req_ring_index++;
-            if (ha->req_ring_index == REQUEST_ENTRY_CNT)
-            {
-                ha->req_ring_index = 0;
-                ha->request_ring_ptr = ha->request_ring;
-            }
-            else
-                ha->request_ring_ptr++;
-
-            /* Set chip new ring index. */
-            WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
-        }
-        else
-        {
-            status = 1;
-#ifdef QL_DEBUG_LEVEL_2
-            qla1280_print(
-                    "qla1280_64bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r");
-            qla1280_print(" req_q_cnt=");
-            qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
-#endif
-        }
-    }
-    else
-    {
-        status = 1;
-#ifdef QL_DEBUG_LEVEL_2
-        qla1280_print("qla1280_64bit_start_scsi: in-ptr=");
-        qla1280_output_number((uint32_t)ha->req_ring_index, 16);
-        qla1280_print(" req_q_cnt=");
-        qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
-        qla1280_print(" req_cnt=");
-        qla1280_output_number((uint32_t)req_cnt, 16);
-        qla1280_print("\n\r");
-#endif
-    }
-
-    /* Release ring specific lock */
-    QLA1280_RING_UNLOCK(ha);
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (status)
-        qla1280_print("qla1280_64bit_start_scsi: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_64bit_start_scsi: exiting normally\n\r");
-#endif
-    return(status);
+	struct device_reg *reg = ha->iobase;
+	Scsi_Cmnd *cmd = sp->cmd;
+	cmd_a64_entry_t *pkt;
+	struct scatterlist *sg = NULL;
+	u32 *dword_ptr;
+	dma_addr_t dma_handle;
+	int status = 0;
+	int cnt;
+	int req_cnt;
+	u16 seg_cnt;
+
+	ENTER("qla1280_64bit_start_scsi:");
+
+	dprintk(1, "64bit_start: cmd=%p sp=%p CDB=%x\n", cmd, sp,
+		cmd->cmnd[0]);
+
+	/* Calculate number of entries and segments required. */
+	req_cnt = 1;
+	if (cmd->use_sg) {	/* 3.13 64 bit */
+		sg = (struct scatterlist *) cmd->request_buffer;
+		seg_cnt = pci_map_sg (ha->pdev, sg, cmd->use_sg,
+				      scsi_to_pci_dma_dir(cmd->sc_data_direction));
+
+		if (seg_cnt > 2) {
+			req_cnt += (seg_cnt - 2) / 5;
+			if ((seg_cnt - 2) % 5)
+				req_cnt++;
+		}
+	} else if (cmd->request_bufflen) {	/* If data transfer. */
+		seg_cnt = 1;
+	} else {
+		seg_cnt = 0;
+	}
+
+	if ((req_cnt + 2) >= ha->req_q_cnt) {
+		/* Calculate number of free request entries. */
+		cnt = RD_REG_WORD(&reg->mailbox4);
+		if (ha->req_ring_index < cnt)
+			ha->req_q_cnt = cnt - ha->req_ring_index;
+		else
+			ha->req_q_cnt =
+				REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+	}
+
+	/* If room for request in request ring. */
+	if ((req_cnt + 2) < ha->req_q_cnt) {
+		/* Check for room in outstanding command list. */
+		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
+			     ha->outstanding_cmds[cnt] != 0; cnt++) ;
+
+		if (cnt < MAX_OUTSTANDING_COMMANDS) {
+			ha->outstanding_cmds[cnt] = sp;
+			ha->req_q_cnt -= req_cnt;
+			CMD_HANDLE(sp->cmd) =
+				(unsigned char *)(unsigned long)cnt;
+
+			/*
+			 * Build command packet.
+			 */
+			pkt = (cmd_a64_entry_t *) ha->request_ring_ptr;
+
+			pkt->entry_type = COMMAND_A64_TYPE;
+			pkt->entry_count = (uint8_t) req_cnt;
+			pkt->sys_define = (uint8_t) ha->req_ring_index;
+			pkt->handle = (uint32_t) cnt;
+
+			/* Zero out remaining portion of packet. */
+			memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
+
+			/* Set ISP command timeout. */
+			pkt->timeout = 30;
+
+			/* Set device target ID and LUN */
+			pkt->lun = SCSI_LUN_32(cmd);
+			pkt->target = SCSI_BUS_32(cmd) ?
+				(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+			/* Enable simple tag queuing if device supports it. */
+			if (cmd->device->tagged_queue)
+				pkt->control_flags |= BIT_3;
+
+			/* Load SCSI command packet. */
+			pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
+			memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), pkt->cdb_len);
+			/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
+
+			/*
+			 * Load data segments.
+			 */
+			if (seg_cnt) {	/* If data transfer. */
+				/* Set transfer direction. */
+				if ((cmd->data_cmnd[0] == WRITE_6))
+					pkt->control_flags |= BIT_6;
+				else
+					pkt->control_flags |= (BIT_5 | BIT_6);
+
+				sp->dir = pkt->control_flags & (BIT_5 | BIT_6);
+
+				/* Set total data segment count. */
+				pkt->dseg_count = seg_cnt;
+
+				/* Setup packet address segment pointer. */
+				dword_ptr = (u32 *)&pkt->dseg_0_address;
+
+				if (cmd->use_sg) {	/* If scatter gather */
+					/* Load command entry data segments. */
+					for (cnt = 0; cnt < 2 && seg_cnt;
+					     cnt++, seg_cnt--) {
+						/* 3.13 64 bit */
+						*dword_ptr++ =
+							cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
+						*dword_ptr++ =
+							cpu_to_le32(pci_dma_hi32(sg_dma_address(sg)));
+						*dword_ptr++ =
+							cpu_to_le32(sg_dma_len(sg));
+						sg++;
+						dprintk(1,
+							"S/G Segment phys_addr=%x %x, len=0x%x\n",
+							cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))),
+							cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
+							cpu_to_le32(sg_dma_len(sg)));
+					}
+					dprintk(5,
+						"qla1280_64bit_start_scsi: Scatter/gather "
+						"command packet data - b %i, t %i, l %i \n",
+						SCSI_BUS_32(cmd),
+						SCSI_TCN_32(cmd),
+						SCSI_LUN_32(cmd));
+					qla1280_dump_buffer(5, (char *)pkt,
+							    REQUEST_ENTRY_SIZE);
+
+					/*
+					 * Build continuation packets.
+					 */
+					dprintk(1,
+						"S/G Building Continuation...seg_cnt=0x%x "
+						"remains\n", seg_cnt);
+
+					while (seg_cnt > 0) {
+						/* Adjust ring index. */
+						ha->req_ring_index++;
+						if (ha->req_ring_index ==
+						    REQUEST_ENTRY_CNT) {
+							ha->req_ring_index = 0;
+							ha->request_ring_ptr =
+								ha->request_ring;
+						} else
+							ha->request_ring_ptr++;
+
+						pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
+
+						/* Zero out packet. */
+						memset(pkt, 0,
+						       REQUEST_ENTRY_SIZE);
+
+						/* Load packet defaults. */
+						((cont_a64_entry_t *) pkt)->entry_type =
+							CONTINUE_A64_TYPE;
+						((cont_a64_entry_t *) pkt)->entry_count = 1;
+						((cont_a64_entry_t *) pkt)->sys_define =
+							(uint8_t)ha->req_ring_index;
+						/* Setup packet address segment pointer. */
+						dword_ptr =
+							(u32 *)&((cont_a64_entry_t *) pkt)->dseg_0_address;
+
+						/* Load continuation entry data segments. */
+						for (cnt = 0;
+						     cnt < 5 && seg_cnt;
+						     cnt++, seg_cnt--) {
+							/* 3.13 64 bit */
+							*dword_ptr++ =
+								cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
+							*dword_ptr++ =
+								cpu_to_le32(pci_dma_hi32(sg_dma_address(sg)));
+							*dword_ptr++ =
+								cpu_to_le32(sg_dma_len(sg));
+							dprintk(1,
+								"S/G Segment Cont. phys_addr=%x %x, len=0x%x\n",
+								cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))),
+								cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
+								cpu_to_le32(sg_dma_len(sg)));
+							sg++;
+						}
+						dprintk(5,
+							"qla1280_64bit_start_scsi: continuation "
+							"packet data - b %i, t %i, l %i \n",
+							SCSI_BUS_32(cmd),
+							SCSI_TCN_32(cmd),
+							SCSI_LUN_32(cmd));
+						qla1280_dump_buffer(5,
+								    (char *)pkt,
+								    REQUEST_ENTRY_SIZE);
+					}
+				} else {	/* No scatter gather data transfer */
+					/* 3.13 64 bit */
+					dma_handle = pci_map_single(ha->pdev,
+								    cmd->request_buffer,
+								    cmd->request_bufflen,
+								    scsi_to_pci_dma_dir(cmd->sc_data_direction));
+					/* save dma_handle for pci_unmap_single */
+					sp->saved_dma_handle = dma_handle;
+
+					*dword_ptr++ =
+						cpu_to_le32(pci_dma_lo32(dma_handle));
+					*dword_ptr++ =
+						cpu_to_le32(pci_dma_hi32(dma_handle));
+					*dword_ptr =
+						(uint32_t)cmd->request_bufflen;
+					/* dprintk(1,
+					   "No S/G map_single saved_dma_handle=%lx\n",dma_handle);
+					*/
+					dprintk(5,
+						"qla1280_64bit_start_scsi: No scatter/gather "
+						"command packet data - b %i, t %i, l %i \n",
+						SCSI_BUS_32(cmd),
+						SCSI_TCN_32(cmd),
+						SCSI_LUN_32(cmd));
+					qla1280_dump_buffer(5, (char *)pkt,
+							    REQUEST_ENTRY_SIZE);
+				}
+			} else {	/* No data transfer */
+
+				dword_ptr = (uint32_t *)(pkt + 1);
+				*dword_ptr++ = 0;
+				*dword_ptr++ = 0;
+				*dword_ptr = 0;
+				dprintk(5,
+					"qla1280_64bit_start_scsi: No data, command "
+					"packet data - b %i, t %i, l %i \n",
+					SCSI_BUS_32(cmd), SCSI_TCN_32(cmd),
+					SCSI_LUN_32(cmd));
+				qla1280_dump_buffer(5, (char *)pkt,
+						    REQUEST_ENTRY_SIZE);
+			}
+			/* Adjust ring index. */
+			ha->req_ring_index++;
+			if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
+				ha->req_ring_index = 0;
+				ha->request_ring_ptr = ha->request_ring;
+			} else
+				ha->request_ring_ptr++;
+
+			/* Set chip new ring index. */
+			dprintk(1,
+				"qla1280_64bit_start_scsi: Wakeup RISC for pending command\n");
+			ha->qthreads--;
+			sp->flags |= SRB_SENT;
+			ha->actthreads++;
+			WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+		} else {
+			status = 1;
+			dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN "
+				"OUTSTANDING ARRAY, req_q_cnt=0x%x",
+				ha->req_q_cnt);
+		}
+	} else {
+		status = 1;
+		dprintk(2,
+			"qla1280_64bit_start_scsi: in-ptr=0x%x  req_q_cnt=0x%x"
+			"req_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
+			req_cnt);
+	}
+
+	if (status)
+		dprintk(2, "qla1280_64bit_start_scsi: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_64bit_start_scsi: exiting normally\n");
+
+	return status;
 }
-#endif  /* QLA1280_64BIT_SUPPORT */
+#endif
 
 /*
  * qla1280_32bit_start_scsi
@@ -4155,9 +4109,9 @@
  *
  *      The Qlogic firmware interface allows every queue slot to have a SCSI
  *      command and up to 4 scatter/gather (SG) entries.  If we need more
- *      than 4 SG entries, then continuation entries are used that can 
+ *      than 4 SG entries, then continuation entries are used that can
  *      hold another 7 entries each.  The start routine determines if there
- *      is eought empty slots then build the combination of requests to 
+ *      is eought empty slots then build the combination of requests to
  *      fulfill the OS request.
  *
  * Input:
@@ -4167,302 +4121,313 @@
  * Returns:
  *      0 = success, was able to issue command.
  */
-STATIC uint8_t
-qla1280_32bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp)
+static int
+qla1280_32bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp)
 {
-    device_reg_t    *reg   = ha->iobase;
-    uint8_t         status = 0;
-    Scsi_Cmnd       *cmd = sp->cmd;
-    uint32_t        cnt;
-    cmd_entry_t     *pkt;
-    uint16_t        req_cnt;
-    uint16_t        seg_cnt;
-    struct scatterlist    *sg = (struct scatterlist *) NULL;
-    uint8_t        *data_ptr;
-    uint32_t        *dword_ptr;
-
-    ENTER("qla1280_32bit_start_scsi");
-
-
-    if( qla1280_check_for_dead_scsi_bus(ha, sp) )
-    {
-        return(0);
-    }
-
-    /* Calculate number of entries and segments required. */
-    req_cnt = 1;
-    if (cmd->use_sg)
-    {
-        /*
-        * We must build an SG list in adapter format, as the kernel's SG list
-        * cannot be used directly because of data field size (__alpha__)
-        * differences and the kernel SG list uses virtual addresses where
-        * we need physical addresses.
-        */
-        seg_cnt =  cmd->use_sg;
-        sg = (struct scatterlist *) cmd->request_buffer;
-        /* 
-        * if greater than four sg entries then we need to allocate
-        * continuation entries
-        */
-        if (seg_cnt > 4)
-        {
-            req_cnt += (uint16_t)(seg_cnt - 4) / 7;
-            if ((uint16_t)(seg_cnt - 4) % 7)
-                req_cnt++;
-        }
-        DEBUG(sprintf(debug_buff,"S/G for data transfer -num segs(%d), req blk cnt(%d)\n\r",seg_cnt,req_cnt));
-        DEBUG(qla1280_print(debug_buff));
-    }
-    else if (cmd->request_bufflen)  /* If data transfer. */
-    {
-        DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen));
-        seg_cnt = 1;
-    }
-    else
-    {
-        DEBUG(printk("No data transfer \n"));
-        seg_cnt = 0;
-    }
-
-    /* Acquire ring specific lock */
-    QLA1280_RING_LOCK(ha);
-
-    if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt)
-    {
-        /* Calculate number of free request entries. */
-        cnt = RD_REG_WORD(&reg->mailbox4);
-        if (ha->req_ring_index < cnt)
-            ha->req_q_cnt = cnt - ha->req_ring_index;
-        else
-            ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
-    }
-
-    DEBUG(sprintf(debug_buff,"Number of free entries = (%d)\n\r",ha->req_q_cnt));
-    DEBUG(qla1280_print(debug_buff));
-    /* If room for request in request ring. */
-    if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt)
-    {
-        /* Check for empty slot in outstanding command list. */
-        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
-            (ha->outstanding_cmds[cnt] != 0); cnt++)
-            ;
-
-        if (cnt < MAX_OUTSTANDING_COMMANDS)
-        {
-            CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)cnt;
-            ha->outstanding_cmds[cnt] = sp;
-            ha->req_q_cnt -= req_cnt;
-
-            /*
-            * Build command packet.
-            */
-            pkt = (cmd_entry_t *)ha->request_ring_ptr;
-
-            pkt->entry_type = COMMAND_TYPE;
-            pkt->entry_count = (uint8_t)req_cnt;
-            pkt->sys_define = (uint8_t)ha->req_ring_index;
-            pkt->handle = (uint32_t)cnt;
-
-            /* Zero out remaining portion of packet. */
-            dword_ptr = (uint32_t *)pkt + 2;
-            for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
-                *dword_ptr++ = 0;
-
-            /* Set ISP command timeout. */
-            pkt->timeout = (uint16_t)30;
-
-            /* Set device target ID and LUN */
-            pkt->lun = SCSI_LUN_32(cmd);
-            pkt->target = SCSI_BUS_32(cmd) ?
-                    (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
-
-            /* Enable simple tag queuing if device supports it. */
-            if (cmd->device->tagged_queue )
-                pkt->control_flags |= BIT_3;
-
-            /* Load SCSI command packet. */
-            pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
-            data_ptr = (uint8_t *) &(CMD_CDBP(cmd));
-            for (cnt = 0; cnt < pkt->cdb_len; cnt++)
-                pkt->scsi_cdb[cnt] = *data_ptr++;
-            DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]));
-            /*
-            * Load data segments.
-            */
-            if (seg_cnt)
-            {
-                DEBUG(printk("loading data segments..\n"));
-                /* Set transfer direction (READ and WRITE) */
-                /* Linux doesn't tell us                   */
-
-                /*
-                * 3/10 dg - Normally, we should need this check with our F/W
-                * but because of a small issue with it we do.
-                *
-                * For block devices, cmd->request.cmd has the operation 
-                * For character devices, this isn't always set properly, so
-                * we need to check data_cmnd[0].  This catches the conditions
-                * for st.c, but not sg. Generic commands are pass down to us.
-                */
-                if ( (cmd->data_cmnd[0] == WRITE_6) )
-                    pkt->control_flags |= BIT_6;
-                else
-                    pkt->control_flags |= (BIT_5|BIT_6);
-                    
-                sp->dir = pkt->control_flags & (BIT_5|BIT_6);
-
-                /* Set total data segment count. */
-                pkt->dseg_count = seg_cnt;
-
-                /* Setup packet address segment pointer. */
-                dword_ptr = (uint32_t *)&pkt->dseg_0_address;
-
-                if (cmd->use_sg)     /* If scatter gather */
-                {
-                    DEBUG(qla1280_print("Building S/G data segments..\n\r"));
-                    DEBUG(qla1280_dump_buffer((caddr_t)sg, 4*16 ));
-                    /* Load command entry data segments. */
-                    for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--)
-                    {
-                        *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(sg->address));
-                        *dword_ptr++ = sg->length;
-                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
-                        DEBUG(qla1280_print(debug_buff));
-                        sg++;
-                    }
-                    /*
-                    * Build continuation packets.
-                    */
-                    while (seg_cnt > 0)
-                    {
-                        /* Adjust ring index. */
-                        ha->req_ring_index++;
-                        if (ha->req_ring_index == REQUEST_ENTRY_CNT)
-                        {
-                            ha->req_ring_index = 0;
-                            ha->request_ring_ptr = ha->request_ring;
-                        }
-                        else
-                            ha->request_ring_ptr++;
-
-                        pkt = (cmd_entry_t *)ha->request_ring_ptr;
-
-                        /* Zero out packet. */
-                        dword_ptr = (uint32_t *)pkt;
-                        for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++)
-                            *dword_ptr++ = 0;
-
-                        /* Load packet defaults. */
-                        ((cont_entry_t *)pkt)->entry_type =
-                                CONTINUE_TYPE;
-                        ((cont_entry_t *)pkt)->entry_count = 1;
-
-                        ((cont_entry_t *)pkt)->sys_define = (uint8_t)
-                                ha->req_ring_index;
-
-                        /* Setup packet address segment pointer. */
-                        dword_ptr = (uint32_t *)
-                                &((cont_entry_t *)pkt)->dseg_0_address;
-
-                        /* Load continuation entry data segments. */
-                        for (cnt = 0; cnt < 7 && seg_cnt; cnt++, seg_cnt--)
-                        {
-                            *dword_ptr++ = (u_int) cpu_to_le32(VIRT_TO_BUS(sg->address));
-                            *dword_ptr++ = sg->length;
-                            sg++;
-                        }
-#ifdef QL_DEBUG_LEVEL_5
-                        qla1280_print(
-                                "qla1280_32bit_start_scsi: continuation packet data - scsi(");
-                        qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
-                        qla1280_print(":");
-                        qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
-                        qla1280_print(":");
-                        qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
-                        qla1280_print(")\n\r");
-                        qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
-#endif
-                    }
-                }
-                else                    /* No scatter gather data transfer */
-                {
-                    *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
-                    *dword_ptr = (uint32_t) cmd->request_bufflen;
-                    DEBUG(printk("Single Segment ap=0x%p, len=0x%x\n",cmd->request_buffer,cmd->request_bufflen));
-                }
-            }
-            else                            /* No data transfer */
-            {
-                *dword_ptr++ = (uint32_t) 0;
-                *dword_ptr = (uint32_t)  0;
-#ifdef QL_DEBUG_LEVEL_5
-                qla1280_print(
-                        "qla1280_32bit_start_scsi: No data, command packet data - ");
-                qla1280_print("\n\r");
-                qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
-#endif
-            }
-#ifdef QL_DEBUG_LEVEL_5
-            qla1280_print("qla1280_32bit_start_scsi: First IOCB block:\n\r");
-            qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE);
-#endif
-            /* Adjust ring index. */
-            ha->req_ring_index++;
-            if (ha->req_ring_index == REQUEST_ENTRY_CNT)
-            {
-                ha->req_ring_index = 0;
-                ha->request_ring_ptr = ha->request_ring;
-            }
-            else
-                ha->request_ring_ptr++;
-
-            /* Set chip new ring index. */
-            DEBUG(qla1280_print("qla1280_32bit_start_scsi: Wakeup RISC for pending command\n\r"));
-            ha->qthreads--;
-            sp->u_start = jiffies;
-            sp->flags |= SRB_SENT;
-            ha->actthreads++;
-            /* qla1280_output_number((uint32_t)ha->actthreads++, 16); */
-            WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
-        }
-        else
-        {
-            status = 1;
-#ifdef QL_DEBUG_LEVEL_2
-            qla1280_print(
-                    "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r");
-            qla1280_print(" req_q_cnt=");
-            qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
-            qla1280_print("\n\r");
-#endif
-        }
-    }
-    else
-    {
-        status = 1;
-#ifdef QL_DEBUG_LEVEL_2
-        /*  qla1280_print("qla1280_32bit_start_scsi: in-ptr=");
-        qla1280_output_number((uint32_t)ha->req_ring_index, 16);
-        qla1280_print(" req_q_cnt=");
-        qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
-        qla1280_print(" req_cnt=");
-        qla1280_output_number((uint32_t)req_cnt, 16);
-        qla1280_print("\n\r"); */
-#endif
-    }
-
-    /* Release ring specific lock */
-    QLA1280_RING_UNLOCK(ha);
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    /* if (status)
-    qla1280_print("qla1280_32bit_start_scsi: **** FAILED ****\n\r"); */
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-            LEAVE("qla1280_32bit_start_scsi");
-#endif
-    return(status);
+	struct device_reg *reg = ha->iobase;
+	Scsi_Cmnd *cmd = sp->cmd;
+	cmd_entry_t *pkt;
+	struct scatterlist *sg = NULL;
+	uint32_t *dword_ptr;
+	int status = 0;
+	int cnt;
+	int req_cnt;
+	uint16_t seg_cnt;
+	dma_addr_t dma_handle;
+
+	ENTER("qla1280_32bit_start_scsi");
+
+	dprintk(1, "32bit_start: cmd=%p sp=%p CDB=%x\n", cmd, sp,
+		cmd->cmnd[0]);
+
+	/* Calculate number of entries and segments required. */
+	req_cnt = 1;
+	if (cmd->use_sg) {
+		/*
+		 * We must build an SG list in adapter format, as the kernel's SG list
+		 * cannot be used directly because of data field size (__alpha__)
+		 * differences and the kernel SG list uses virtual addresses where
+		 * we need physical addresses.
+		 */
+		sg = (struct scatterlist *) cmd->request_buffer;
+		/* 3.13 32 bit */
+		seg_cnt = pci_map_sg (ha->pdev, sg, cmd->use_sg,
+				      scsi_to_pci_dma_dir(cmd->sc_data_direction));
+
+		/*
+		 * if greater than four sg entries then we need to allocate
+		 * continuation entries
+		 */
+		if (seg_cnt > 4) {
+			req_cnt += (seg_cnt - 4) / 7;
+			if ((seg_cnt - 4) % 7)
+				req_cnt++;
+		}
+		dprintk(1, "S/G Transfer cmd=%p seg_cnt=0x%x, req_cnt=%x\n",
+			cmd, seg_cnt, req_cnt);
+	} else if (cmd->request_bufflen) {	/* If data transfer. */
+		dprintk(1, "No S/G transfer t=%x cmd=%p len=%x CDB=%x\n",
+			SCSI_TCN_32(cmd), cmd, cmd->request_bufflen,
+			cmd->cmnd[0]);
+		seg_cnt = 1;
+	} else {
+		/* dprintk(1, "No data transfer \n"); */
+		seg_cnt = 0;
+	}
+
+	if ((req_cnt + 2) >= ha->req_q_cnt) {
+		/* Calculate number of free request entries. */
+		cnt = RD_REG_WORD(&reg->mailbox4);
+		if (ha->req_ring_index < cnt)
+			ha->req_q_cnt = cnt - ha->req_ring_index;
+		else
+			ha->req_q_cnt =
+				REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+	}
+
+	dprintk(1, "Number of free entries=(%d) seg_cnt=0x%x\n",
+		ha->req_q_cnt, seg_cnt);
+	/* If room for request in request ring. */
+	if ((req_cnt + 2) < ha->req_q_cnt) {
+		/* Check for empty slot in outstanding command list. */
+		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
+			     (ha->outstanding_cmds[cnt] != 0); cnt++) ;
+
+		if (cnt < MAX_OUTSTANDING_COMMANDS) {
+			CMD_HANDLE(sp->cmd) =
+				(unsigned char *) (unsigned long) cnt;
+			ha->outstanding_cmds[cnt] = sp;
+			ha->req_q_cnt -= req_cnt;
+
+			/*
+			 * Build command packet.
+			 */
+			pkt = (cmd_entry_t *) ha->request_ring_ptr;
+
+			pkt->entry_type = COMMAND_TYPE;
+			pkt->entry_count = (uint8_t) req_cnt;
+			pkt->sys_define = (uint8_t) ha->req_ring_index;
+			pkt->handle = (uint32_t) cnt;
+
+			/* Zero out remaining portion of packet. */
+			memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
+
+			/* Set ISP command timeout. */
+			pkt->timeout = 30;
+
+			/* Set device target ID and LUN */
+			pkt->lun = SCSI_LUN_32(cmd);
+			pkt->target = SCSI_BUS_32(cmd) ?
+				(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+			/* Enable simple tag queuing if device supports it. */
+			if (cmd->device->tagged_queue)
+				pkt->control_flags |= BIT_3;
+
+			/* Load SCSI command packet. */
+			pkt->cdb_len = (uint16_t) CMD_CDBLEN(cmd);
+			memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), pkt->cdb_len);
+
+			/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
+			/*
+			 * Load data segments.
+			 */
+			if (seg_cnt) {
+				/* Set transfer direction (READ and WRITE) */
+				/* Linux doesn't tell us                   */
+				/*
+				 * For block devices, cmd->request.cmd has the operation
+				 * For character devices, this isn't always set properly, so
+				 * we need to check data_cmnd[0].  This catches the conditions
+				 * for st.c, but not sg. Generic commands are pass down to us.
+				 */
+				if ((cmd->data_cmnd[0] == WRITE_6))
+					pkt->control_flags |= BIT_6;
+				else
+					pkt->control_flags |= (BIT_5 | BIT_6);
+
+				sp->dir = pkt->control_flags & (BIT_5 | BIT_6);
+
+				/* Set total data segment count. */
+				pkt->dseg_count = seg_cnt;
+
+				/* Setup packet address segment pointer. */
+				dword_ptr = &pkt->dseg_0_address;
+
+				if (cmd->use_sg) {	/* If scatter gather */
+					dprintk(1, "Building S/G data "
+						"segments..\n");
+					qla1280_dump_buffer(1, (char *)sg,
+							    4 * 16);
+
+					/* Load command entry data segments. */
+					for (cnt = 0; cnt < 4 && seg_cnt;
+					     cnt++, seg_cnt--) {
+						/* 3.13 32 bit */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+						*dword_ptr++ =
+							cpu_to_le32(virt_to_bus(sg->address));
+						*dword_ptr++ = sg->length;
+						dprintk(1,
+							"S/G Segment phys_addr=0x%x, len=0x%x\n",
+							cpu_to_le32(virt_to_bus(sg->address)),
+							sg->length);
+#else
+						*dword_ptr++ =
+							cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
+						*dword_ptr++ =
+							cpu_to_le32(sg_dma_len(sg));
+						dprintk(1, "S/G Segment phys_addr=0x%x, len=0x%x\n",
+							cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
+							cpu_to_le32(sg_dma_len(sg)));
+#endif
+						sg++;
+					}
+					/*
+					 * Build continuation packets.
+					 */
+					dprintk(1, "S/G Building Continuation"
+						"...seg_cnt=0x%x remains\n",
+						seg_cnt);
+					while (seg_cnt > 0) {
+						/* Adjust ring index. */
+						ha->req_ring_index++;
+						if (ha->req_ring_index ==
+						    REQUEST_ENTRY_CNT) {
+							ha->req_ring_index = 0;
+							ha->request_ring_ptr =
+								ha->request_ring;
+						} else
+							ha->request_ring_ptr++;
+
+						pkt = (cmd_entry_t *)
+							ha->request_ring_ptr;
+
+						/* Zero out packet. */
+						memset(pkt, 0,
+						       REQUEST_ENTRY_SIZE);
+
+						/* Load packet defaults. */
+						((cont_entry_t *) pkt)->
+							entry_type = CONTINUE_TYPE;
+						((cont_entry_t *) pkt)->
+							entry_count = 1;
+
+						((cont_entry_t *) pkt)->
+							sys_define =
+							(uint8_t) ha->
+							req_ring_index;
+
+						/* Setup packet address segment pointer. */
+						dword_ptr =
+							&((cont_entry_t *) pkt)->dseg_0_address;
+
+						/* Load continuation entry data segments. */
+						for (cnt = 0;
+						     cnt < 7 && seg_cnt;
+						     cnt++, seg_cnt--) {
+							/* 3.13 32 bit */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+							*dword_ptr++ =
+								cpu_to_le32(virt_to_bus(sg->address));
+							*dword_ptr++ = sg->length;
+							dprintk(1,
+								"S/G Segment Cont. phys_addr=0x%x, len=0x%x\n",
+								cpu_to_le32(pci_dma_lo32(virt_to_bus(sg->address))), sg->length);
+#else
+							*dword_ptr++ =
+								cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
+							*dword_ptr++ =
+								cpu_to_le32(sg_dma_len(sg));
+							dprintk(1,
+								"S/G Segment Cont. phys_addr=0x%x, "
+								"len=0x%x\n",
+								cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
+								cpu_to_le32(sg_dma_len(sg)));
+#endif
+							sg++;
+						}
+						dprintk(5,
+							"qla1280_32bit_start_scsi: continuation "
+							"packet data - scsi(%i:%i:%i)\n",
+							SCSI_BUS_32(cmd),
+							SCSI_TCN_32(cmd),
+							SCSI_LUN_32(cmd));
+						qla1280_dump_buffer(5,
+								    (char *)pkt,
+								    REQUEST_ENTRY_SIZE);
+					}
+				} else {	/* No S/G data transfer */
+
+					/* 3.13 32 bit */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+					*dword_ptr++ =
+						cpu_to_le32 (virt_to_bus
+							     (cmd->request_buffer));
+#else
+					dma_handle = pci_map_single(ha->pdev,
+								    cmd->request_buffer,
+								    cmd->request_bufflen,
+								    scsi_to_pci_dma_dir(cmd->sc_data_direction));
+					sp->saved_dma_handle = dma_handle;
+
+					*dword_ptr++ =
+						cpu_to_le32(pci_dma_lo32(dma_handle));
+#endif
+					*dword_ptr =
+						(uint32_t)cmd->request_bufflen;
+				}
+			} else {	/* No data transfer at all */
+
+				dword_ptr = (uint32_t *)(pkt + 1);
+				*dword_ptr++ = 0;
+				*dword_ptr = 0;
+				dprintk(5,
+					"qla1280_32bit_start_scsi: No data, command "
+					"packet data - \n");
+				qla1280_dump_buffer(5, (char *)pkt,
+						    REQUEST_ENTRY_SIZE);
+			}
+			dprintk(5,
+				"qla1280_32bit_start_scsi: First IOCB block:\n");
+			qla1280_dump_buffer(5, (char *)ha->request_ring_ptr,
+					    REQUEST_ENTRY_SIZE);
+
+			/* Adjust ring index. */
+			ha->req_ring_index++;
+			if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
+				ha->req_ring_index = 0;
+				ha->request_ring_ptr = ha->request_ring;
+			} else
+				ha->request_ring_ptr++;
+
+			/* Set chip new ring index. */
+			dprintk(1, "qla1280_32bit_start_scsi: Wakeup RISC "
+				"for pending command\n");
+			ha->qthreads--;
+			sp->flags |= SRB_SENT;
+			ha->actthreads++;
+			WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+		} else {
+			status = 1;
+			dprintk(2,
+				"qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING "
+				"ARRAY, req_q_cnt=0x%x\n", ha->req_q_cnt);
+		}
+	} else {
+		status = 1;
+		dprintk(2,
+			"qla1280_32bit_start_scsi: in-ptr=0x%x, req_q_cnt=0x%x, "
+			"req_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
+			req_cnt);
+	}
+
+	if (status)
+		dprintk(2, "qla1280_32bit_start_scsi: **** FAILED ****\n");
+
+	LEAVE("qla1280_32bit_start_scsi");
+
+	return status;
 }
 
 /*
@@ -4476,73 +4441,60 @@
  * Returns:
  *      0 = failed to get slot.
  */
-STATIC request_t *
-qla1280_req_pkt(scsi_qla_host_t *ha)
+static request_t *
+qla1280_req_pkt(struct scsi_qla_host *ha)
 {
-    device_reg_t    *reg = ha->iobase;
-    request_t       *pkt = 0;
-    uint16_t        cnt;
-    uint32_t        *dword_ptr;
-    uint32_t        timer;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_req_pkt");
-#endif
-
-    /* Wait for 30 seconds for slot. */
-    for (timer = 15000000; timer; timer--)
-    {
-        /* Acquire ring specific lock */
-        QLA1280_RING_LOCK(ha);
-
-        if (ha->req_q_cnt > 0)
-        {
-            /* Calculate number of free request entries. */
-            cnt = RD_REG_WORD(&reg->mailbox4);
-            if (ha->req_ring_index < cnt)
-                ha->req_q_cnt = cnt - ha->req_ring_index;
-            else
-                ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
-        }
-
-        /* Found empty request ring slot? */
-        if (ha->req_q_cnt > 0)
-        {
-            ha->req_q_cnt--;
-            pkt = ha->request_ring_ptr;
-
-            /* Zero out packet. */
-            dword_ptr = (uint32_t *)pkt;
-            for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
-                *dword_ptr++ = 0;
-
-            /* Set system defined field. */
-            pkt->sys_define = (uint8_t)ha->req_ring_index;
-
-            /* Set entry count. */
-            pkt->entry_count = 1;
-
-            break;
-        }
-
-        /* Release ring specific lock */
-        QLA1280_RING_UNLOCK(ha);
-
-        SYS_DELAY(2);   /* 10 */ 
-
-        /* Check for pending interrupts. */
-        qla1280_poll(ha);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_req_pkt: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_req_pkt: exiting normally\n\r");
-#endif
-    return(pkt);
+	struct device_reg *reg = ha->iobase;
+	request_t *pkt = 0;
+	int cnt;
+	uint32_t timer;
+
+	ENTER("qla1280_req_pkt");
+
+	/*
+	 * This can be called from interrupt context, damn it!!!
+	 */
+	/* Wait for 30 seconds for slot. */
+	for (timer = 15000000; timer; timer--) {
+		if (ha->req_q_cnt > 0) {
+			/* Calculate number of free request entries. */
+			cnt = RD_REG_WORD(&reg->mailbox4);
+			if (ha->req_ring_index < cnt)
+				ha->req_q_cnt = cnt - ha->req_ring_index;
+			else
+				ha->req_q_cnt =
+					REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+		}
+
+		/* Found empty request ring slot? */
+		if (ha->req_q_cnt > 0) {
+			ha->req_q_cnt--;
+			pkt = ha->request_ring_ptr;
+
+			/* Zero out packet. */
+			memset(pkt, 0, REQUEST_ENTRY_SIZE);
+
+			/* Set system defined field. */
+			pkt->sys_define = (uint8_t) ha->req_ring_index;
+
+			/* Set entry count. */
+			pkt->entry_count = 1;
+
+			break;
+		}
+
+		udelay(2);	/* 10 */
+
+		/* Check for pending interrupts. */
+		qla1280_poll(ha);
+	}
+
+	if (!pkt)
+		dprintk(2, "qla1280_req_pkt: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_req_pkt: exiting normally\n");
+
+	return pkt;
 }
 
 /*
@@ -4553,85 +4505,71 @@
  * Input:
  *      ha  = adapter block pointer.
  */
-STATIC void
-qla1280_isp_cmd(scsi_qla_host_t *ha)
+static void
+qla1280_isp_cmd(struct scsi_qla_host *ha)
 {
-    device_reg_t    *reg = ha->iobase;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_isp_cmd");
-#endif
+	struct device_reg *reg = ha->iobase;
 
-#ifdef QL_DEBUG_LEVEL_5
-    qla1280_print("qla1280_isp_cmd: IOCB data:\n\r");
-    qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE); 
-#endif
+	ENTER("qla1280_isp_cmd");
 
-    /* Adjust ring index. */
-    ha->req_ring_index++;
-    if (ha->req_ring_index == REQUEST_ENTRY_CNT)
-    {
-        ha->req_ring_index = 0;
-        ha->request_ring_ptr = ha->request_ring;
-    }
-    else
-        ha->request_ring_ptr++;
+	dprintk(5, "qla1280_isp_cmd: IOCB data:\n");
+	qla1280_dump_buffer(5, (char *)ha->request_ring_ptr,
+			    REQUEST_ENTRY_SIZE);
 
-    /* Set chip new ring index. */
-    WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+	/* Adjust ring index. */
+	ha->req_ring_index++;
+	if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
+		ha->req_ring_index = 0;
+		ha->request_ring_ptr = ha->request_ring;
+	} else
+		ha->request_ring_ptr++;
 
-    /* Release ring specific lock */
-    QLA1280_RING_UNLOCK(ha);
+	/* Set chip new ring index. */
+	WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
 
-#ifdef QL_DEBUG_LEVEL_3
-    LEAVE("qla1280_isp_cmd");
-#endif
+	LEAVE("qla1280_isp_cmd");
 }
 
+#if QL1280_LUN_SUPPORT
 /*
  * qla1280_enable_lun
  *      Issue enable LUN entry IOCB.
  *
  * Input:
- *      ha = adapter block pointer.
- *      b  = SCSI BUS number.
- *      l  = LUN number.
+ *      ha  = adapter block pointer.
+ *      bus = SCSI BUS number.
+ *      lun  = LUN number.
  */
-STATIC void
-qla1280_enable_lun(scsi_qla_host_t *ha, uint8_t b, uint32_t l)
+static void
+qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun)
 {
-    elun_entry_t    *pkt;
+	elun_entry_t *pkt;
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_enable_lun: entered\n\r");
-#endif
-
-    /* Get request packet. */
-    /*
-    if (pkt = (elun_entry_t *)qla1280_req_pkt(ha))
-    {
-    pkt->entry_type = ENABLE_LUN_TYPE;
-    pkt->lun = (uint16_t)(b ? l | BIT_15 : l);
-    pkt->command_count = 32;
-    pkt->immed_notify_count = 1;
-    pkt->group_6_length = MAX_CMDSZ;
-    pkt->group_7_length = MAX_CMDSZ;
-    pkt->timeout = 0x30;
-
-    qla1280_isp_cmd(ha);
-    }
-    */
-    pkt = (elun_entry_t *)1;
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_enable_lun: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_enable_lun: exiting normally\n\r");
-#endif
+	ENTER("qla1280_enable_lun");
+
+	/* Get request packet. */
+	/*
+	  if (pkt = (elun_entry_t *)qla1280_req_pkt(ha))
+	  {
+	  pkt->entry_type = ENABLE_LUN_TYPE;
+	  pkt->lun = (uint16_t)(bus ? lun | BIT_15 : lun);
+	  pkt->command_count = 32;
+	  pkt->immed_notify_count = 1;
+	  pkt->group_6_length = MAX_CMDSZ;
+	  pkt->group_7_length = MAX_CMDSZ;
+	  pkt->timeout = 0x30;
+
+	  qla1280_isp_cmd(ha);
+	  }
+	*/
+	pkt = (elun_entry_t *) 1;
+
+	if (!pkt)
+		dprintk(2, "qla1280_enable_lun: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_enable_lun: exiting normally\n");
 }
+#endif
 
 #if QL1280_TARGET_MODE_SUPPORT
 /****************************************************************************/
@@ -4648,39 +4586,32 @@
  *      ha      = adapter block pointer.
  *      inotify = immediate notify entry pointer.
  */
-STATIC void
-qla1280_notify_ack(scsi_qla_host_t *ha, notify_entry_t *inotify)
+static void
+qla1280_notify_ack(struct scsi_qla_host *ha, notify_entry_t * inotify)
 {
-    nack_entry_t    *pkt;
+	nack_entry_t *pkt;
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_notify_ack: entered\n\r");
-#endif
+	dprintk(3, "qla1280_notify_ack: entered\n");
 
-    /* Get request packet. */
-    if (pkt = (nack_entry_t *)qla1280_req_pkt(ha))
-    {
-        pkt->entry_type = NOTIFY_ACK_TYPE;
-        pkt->lun = inotify->lun;
-        pkt->initiator_id = inotify->initiator_id;
-        pkt->target_id = inotify->target_id;
-        if (inotify->seq_id == 0)
-            pkt->event = BIT_7;
-        else
-            pkt->seq_id = inotify->seq_id;
-
-        /* Issue command to ISP */
-        qla1280_isp_cmd(ha);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_notify_ack: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_notify_ack: exiting normally\n\r");
-#endif
+	/* Get request packet. */
+	if (pkt = (nack_entry_t *) qla1280_req_pkt(ha)) {
+		pkt->entry_type = NOTIFY_ACK_TYPE;
+		pkt->lun = inotify->lun;
+		pkt->initiator_id = inotify->initiator_id;
+		pkt->target_id = inotify->target_id;
+		if (inotify->seq_id == 0)
+			pkt->event = BIT_7;
+		else
+			pkt->seq_id = inotify->seq_id;
+
+		/* Issue command to ISP */
+		qla1280_isp_cmd(ha);
+	}
+
+	if (!pkt)
+		dprintk(2, "qla1280_notify_ack: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_notify_ack: exiting normally\n");
 }
 
 /*
@@ -4691,36 +4622,29 @@
  *      ha      = adapter block pointer.
  *      inotify = immediate notify entry pointer.
  */
-STATIC void
-qla1280_immed_notify(scsi_qla_host_t *ha, notify_entry_t *inotify)
+static void
+qla1280_immed_notify(struct scsi_qla_host *ha, notify_entry_t * inotify)
 {
-    notify_entry_t    *pkt;
+	notify_entry_t *pkt;
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_immed_notify: entered\n\r");
-#endif
+	dprintk(3, "qla1280_immed_notify: entered\n");
 
-    /* Get request packet. */
-    if (pkt = (notify_entry_t *)qla1280_req_pkt(ha))
-    {
-        pkt->entry_type = IMMED_NOTIFY_TYPE;
-        pkt->lun = inotify->lun;
-        pkt->initiator_id = inotify->initiator_id;
-        pkt->target_id = inotify->target_id;
-        pkt->status = 1;
-
-        /* Issue command to ISP */
-        qla1280_isp_cmd(ha);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_immed_notify: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_immed_notify: exiting normally\n\r");
-#endif
+	/* Get request packet. */
+	if (pkt = (notify_entry_t *) qla1280_req_pkt(ha)) {
+		pkt->entry_type = IMMED_NOTIFY_TYPE;
+		pkt->lun = inotify->lun;
+		pkt->initiator_id = inotify->initiator_id;
+		pkt->target_id = inotify->target_id;
+		pkt->status = 1;
+
+		/* Issue command to ISP */
+		qla1280_isp_cmd(ha);
+	}
+
+	if (!pkt)
+		dprintk(2, "qla1280_immed_notify: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_immed_notify: exiting normally\n");
 }
 
 /*
@@ -4731,37 +4655,30 @@
  *      ha = adapter block pointer.
  *      ctio = ctio returned entry pointer.
  */
-STATIC void
-qla1280_accept_io(scsi_qla_host_t *ha, ctio_ret_entry_t *ctio)
+static void
+qla1280_accept_io(struct scsi_qla_host *ha, ctio_ret_entry_t * ctio)
 {
-    atio_entry_t    *pkt;
+	atio_entry_t *pkt;
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_accept_io: entered\n\r");
-#endif
+	dprintk(3, "qla1280_accept_io: entered\n");
 
-    /* Get request packet. */
-    if (pkt = (atio_entry_t *)qla1280_req_pkt(ha))
-    {
-        pkt->entry_type = ACCEPT_TGT_IO_TYPE;
-        pkt->lun = ctio->lun;
-        pkt->initiator_id = ctio->initiator_id;
-        pkt->target_id = ctio->target_id;
-        pkt->tag_value = ctio->tag_value;
-        pkt->status = 1;
-
-        /* Issue command to ISP */
-        qla1280_isp_cmd(ha);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_accept_io: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_accept_io: exiting normally\n\r");
-#endif
+	/* Get request packet. */
+	if (pkt = (atio_entry_t *) qla1280_req_pkt(ha)) {
+		pkt->entry_type = ACCEPT_TGT_IO_TYPE;
+		pkt->lun = ctio->lun;
+		pkt->initiator_id = ctio->initiator_id;
+		pkt->target_id = ctio->target_id;
+		pkt->tag_value = ctio->tag_value;
+		pkt->status = 1;
+
+		/* Issue command to ISP */
+		qla1280_isp_cmd(ha);
+	}
+
+	if (!pkt)
+		dprintk(2, "qla1280_accept_io: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_accept_io: exiting normally\n");
 }
 
 /*
@@ -4774,50 +4691,42 @@
  *      len  = total bytecount.
  *      addr = physical address pointer.
  */
-STATIC void
-qla1280_64bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len,
-                    paddr32_t *addr)
-{
-    ctio_a64_entry_t *pkt;
-    uint32_t         *dword_ptr;
-
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_64bit_continue_io: entered\n\r");
-#endif
-
-    /* Get request packet. */
-    if (pkt = (ctio_a64_entry_t *)qla1280_req_pkt(ha))
-    {
-        pkt->entry_type = CTIO_A64_TYPE;
-        pkt->lun = atio->lun;
-        pkt->initiator_id = atio->initiator_id;
-        pkt->target_id = atio->target_id;
-        pkt->option_flags = atio->option_flags;
-        pkt->tag_value = atio->tag_value;
-        pkt->scsi_status = atio->scsi_status;
-
-        if (len)
-        {
-            pkt->dseg_count = 1;
-            pkt->transfer_length = len;
-            pkt->dseg_0_length = len;
-            dword_ptr = (uint32_t *)addr;
-            pkt->dseg_0_address[0] = *dword_ptr++;
-            pkt->dseg_0_address[1] = *dword_ptr;
-        }
-
-        /* Issue command to ISP */
-        qla1280_isp_cmd(ha);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_64bit_continue_io: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_64bit_continue_io: exiting normally\n\r");
-#endif
+static void
+qla1280_64bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio,
+			  uint32_t len, paddr32_t * addr)
+{
+	ctio_a64_entry_t *pkt;
+	uint32_t *dword_ptr;
+
+	dprintk(3, "qla1280_64bit_continue_io: entered\n");
+
+	/* Get request packet. */
+	if (pkt = (ctio_a64_entry_t *) qla1280_req_pkt(ha)) {
+		pkt->entry_type = CTIO_A64_TYPE;
+		pkt->lun = atio->lun;
+		pkt->initiator_id = atio->initiator_id;
+		pkt->target_id = atio->target_id;
+		pkt->option_flags = atio->option_flags;
+		pkt->tag_value = atio->tag_value;
+		pkt->scsi_status = atio->scsi_status;
+
+		if (len) {
+			pkt->dseg_count = 1;
+			pkt->transfer_length = len;
+			pkt->dseg_0_length = len;
+			dword_ptr = (uint32_t *) addr;
+			pkt->dseg_0_address[0] = *dword_ptr++;
+			pkt->dseg_0_address[1] = *dword_ptr;
+		}
+
+		/* Issue command to ISP */
+		qla1280_isp_cmd(ha);
+	}
+
+	if (!pkt)
+		dprintk(2, "qla1280_64bit_continue_io: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_64bit_continue_io: exiting normally\n");
 }
 
 /*
@@ -4830,51 +4739,43 @@
  *      len  = total bytecount.
  *      addr = physical address pointer.
  */
-STATIC void
-qla1280_32bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len,
-                    paddr32_t *addr)
-{
-    ctio_entry_t *pkt;
-    uint32_t     *dword_ptr;
-
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_32bit_continue_io: entered\n\r");
-#endif
-
-    /* Get request packet. */
-    if (pkt = (ctio_entry_t *)qla1280_req_pkt(ha))
-    {
-        pkt->entry_type = CONTINUE_TGT_IO_TYPE;
-        pkt->lun = atio->lun;
-        pkt->initiator_id = atio->initiator_id;
-        pkt->target_id = atio->target_id;
-        pkt->option_flags = atio->option_flags;
-        pkt->tag_value = atio->tag_value;
-        pkt->scsi_status = atio->scsi_status;
-
-        if (len)
-        {
-            pkt->dseg_count = 1;
-            pkt->transfer_length = len;
-            pkt->dseg_0_length = len;
-            dword_ptr = (uint32_t *)addr;
-            pkt->dseg_0_address = *dword_ptr;
-        }
-
-        /* Issue command to ISP */
-        qla1280_isp_cmd(ha);
-    }
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-    if (!pkt)
-        qla1280_print("qla1280_32bit_continue_io: **** FAILED ****\n\r");
-#endif
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        qla1280_print("qla1280_32bit_continue_io: exiting normally\n\r");
-#endif
+static void
+qla1280_32bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio,
+			  uint32_t len, paddr32_t * addr)
+{
+	ctio_entry_t *pkt;
+	uint32_t *dword_ptr;
+
+	dprintk(3, "qla1280_32bit_continue_io: entered\n");
+
+	/* Get request packet. */
+	if (pkt = (ctio_entry_t *) qla1280_req_pkt(ha)) {
+		pkt->entry_type = CONTINUE_TGT_IO_TYPE;
+		pkt->lun = atio->lun;
+		pkt->initiator_id = atio->initiator_id;
+		pkt->target_id = atio->target_id;
+		pkt->option_flags = atio->option_flags;
+		pkt->tag_value = atio->tag_value;
+		pkt->scsi_status = atio->scsi_status;
+
+		if (len) {
+			pkt->dseg_count = 1;
+			pkt->transfer_length = len;
+			pkt->dseg_0_length = len;
+			dword_ptr = (uint32_t *) addr;
+			pkt->dseg_0_address = *dword_ptr;
+		}
+
+		/* Issue command to ISP */
+		qla1280_isp_cmd(ha);
+	}
+
+	if (!pkt)
+		dprintk(2, "qla1280_32bit_continue_io: **** FAILED ****\n");
+	else
+		dprintk(3, "qla1280_32bit_continue_io: exiting normally\n");
 }
-#endif /* QL1280_TARGET_MODE_SUPPORT */
+#endif				/* QL1280_TARGET_MODE_SUPPORT */
 
 /****************************************************************************/
 /*                        Interrupt Service Routine.                        */
@@ -4888,314 +4789,292 @@
  *      ha           = adapter block pointer.
  *      done_q_first = done queue first pointer.
  *      done_q_last  = done queue last pointer.
- *      INTR_LOCK must be already obtained.
  ****************************************************************************/
-STATIC void
-qla1280_isr(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last)
-{
-    device_reg_t    *reg = ha->iobase;
-    response_t      *pkt;
-    srb_t           *sp;
-    uint16_t        mailbox[MAILBOX_REGISTER_COUNT];
-    uint16_t        *wptr;
-    uint32_t        index;
-
-    ENTER("qla1280_isr");
-
-
-    /* Save mailbox register 5 */
-    mailbox[5] = RD_REG_WORD(&reg->mailbox5);
-
-    /* Check for mailbox interrupt. */
-
-    mailbox[0] = RD_REG_WORD(&reg->semaphore);
-    if (mailbox[0] & BIT_0)
-    {
-        /* Get mailbox data. */
-
-        wptr = &mailbox[0];
-        *wptr++ = RD_REG_WORD(&reg->mailbox0);
-        *wptr++ = RD_REG_WORD(&reg->mailbox1);
-        *wptr = RD_REG_WORD(&reg->mailbox2);
-        if (mailbox[0] != MBA_SCSI_COMPLETION)
-        {
-            wptr++;
-            *wptr++ = RD_REG_WORD(&reg->mailbox3);
-            *wptr++ = RD_REG_WORD(&reg->mailbox4);
-            wptr++;
-            *wptr++ = RD_REG_WORD(&reg->mailbox6);
-            *wptr   = RD_REG_WORD(&reg->mailbox7);
-        }
-
-        /* Release mailbox registers. */
-
-        WRT_REG_WORD(&reg->semaphore, 0);
-        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
-
-#ifdef QL_DEBUG_LEVEL_5
-        qla1280_print("qla1280_isr: mailbox interrupt mailbox[0] = ");
-        qla1280_output_number((uint32_t)mailbox[0], 16);
-        qla1280_print("\n\r");
-#endif
-
-        /* Handle asynchronous event */
-
-        switch (mailbox[0])
-        {
-            case MBA_SCSI_COMPLETION:   /* Response completion */
-#ifdef QL_DEBUG_LEVEL_5
-                qla1280_print("qla1280_isr: mailbox response completion\n\r");
-#endif
-                if (ha->flags.online)
-                {
-                    /* Get outstanding command index. */
-                    index = (uint32_t)(mailbox[2] << 16 | mailbox[1]);
-
-                    /* Validate handle. */
-                    if (index < MAX_OUTSTANDING_COMMANDS)
-                        sp = ha->outstanding_cmds[index];
-                    else
-                        sp = 0;
-
-                    if (sp)
-                    {
-                        /* Free outstanding command slot. */
-                        ha->outstanding_cmds[index] = 0;
-
-                        /* Save ISP completion status */
-                        CMD_RESULT(sp->cmd) = 0;
-
-                        /* Place block on done queue */
-                        sp->s_next = NULL;
-                        sp->s_prev = *done_q_last;
-                        if (!*done_q_first)
-                            *done_q_first = sp;
-                        else
-                            (*done_q_last)->s_next = sp;
-                        *done_q_last = sp;
-                    }
-                    else
-                    {
-#ifdef QL_DEBUG_LEVEL_2
-                            qla1280_print("qla1280_isr: ISP invalid handle\n\r");
-#endif
-                            printk(KERN_WARNING "qla1280: ISP invalid handle");
-                            ha->flags.isp_abort_needed = TRUE;
-                    }
-                }
-                break;
-            case MBA_BUS_RESET:         /* SCSI Bus Reset */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print("qla1280_isr: asynchronous BUS_RESET\n\r");
-#endif
-                ha->flags.reset_marker = TRUE;
-                index = mailbox[6] & BIT_0;
-                ha->bus_settings[index].reset_marker = TRUE;
-                break;
-            case MBA_SYSTEM_ERR:        /* System Error */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print("qla1280_isr: ISP System Error - mbx1=");
-                qla1280_output_number((uint32_t)mailbox[1], 16);
-                qla1280_print(", mbx2=");
-                qla1280_output_number((uint32_t)mailbox[2], 16);
-                qla1280_print(", mbx3=");
-                qla1280_output_number((uint32_t)mailbox[3], 16);
-                qla1280_print("\n\r");
-#endif
-                printk(KERN_WARNING
-                        "qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
-                        mailbox[1], mailbox[2], mailbox[3]);
-                ha->flags.isp_abort_needed = TRUE;
-                break;
-            case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print("qla1280_isr: ISP Request Transfer Error\n\r");
-#endif
-                printk(KERN_WARNING "qla1280: ISP Request Transfer Error\n");
-                ha->flags.isp_abort_needed = TRUE;
-                break;
-            case MBA_RSP_TRANSFER_ERR:  /* Response Transfer Error */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print("qla1280_isr: ISP Response Transfer Error\n\r");
-#endif
-                printk(KERN_WARNING "qla1280: ISP Response Transfer Error\n");
-                ha->flags.isp_abort_needed = TRUE;
-                break;
-            case MBA_WAKEUP_THRES:      /* Request Queue Wake-up */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print("qla1280_isr: asynchronous WAKEUP_THRES\n\r");
-#endif
-                break;
-            case MBA_TIMEOUT_RESET:     /* Execution Timeout Reset */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print("qla1280_isr: asynchronous TIMEOUT_RESET\n\r");
-#endif
-                break;
-            case MBA_DEVICE_RESET:         /* Bus Device Reset */
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print(
-                        "qla1280_isr: asynchronous BUS_DEVICE_RESET\n\r");
-#endif
-                ha->flags.reset_marker = TRUE;
-                index = mailbox[6] & BIT_0;
-                ha->bus_settings[index].reset_marker = TRUE;
-                break;
-            case MBA_BUS_MODE_CHANGE:
-#ifdef QL_DEBUG_LEVEL_2
-                qla1280_print(
-                        "qla1280_isr: asynchronous BUS_MODE_CHANGE\n\r");
-#endif
-                break;
-            default:
-                if (mailbox[0] < MBA_ASYNC_EVENT)
-                {
-                        wptr = &mailbox[0];
-                        ha->mailbox_out[0] = *wptr++;
-                        ha->mailbox_out[1] = *wptr++;
-                        ha->mailbox_out[2] = *wptr++;
-                        ha->mailbox_out[3] = *wptr++;
-                        ha->mailbox_out[4] = *wptr++;
-                        ha->mailbox_out[5] = *wptr++;
-                        ha->mailbox_out[6] = *wptr++;
-                        ha->mailbox_out[7] = *wptr;
-                        ha->flags.mbox_int = TRUE;
-                }
-                break;
-        }
-    }
-    else
-        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
-
-    /*
-    * Response ring
-    */
-    if (ha->flags.online && !ha->flags.mbox_busy)
-    {
-        if (mailbox[5] < RESPONSE_ENTRY_CNT)
-        {
-            while (ha->rsp_ring_index != mailbox[5])
-            {
-                pkt = ha->response_ring_ptr;
-
-#ifdef QL_DEBUG_LEVEL_5
-                qla1280_print("qla1280_isr: ha->rsp_ring_index = ");
-                qla1280_output_number((uint32_t)ha->rsp_ring_index, 16);
-                qla1280_print(" mailbox[5] = ");
-                qla1280_output_number((uint32_t)mailbox[5], 16);
-                qla1280_print("\n\rqla1280_isr: response packet data\n\r");
-                qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE);
-#endif
-
-#if defined(QL_DEBUG_LEVEL_2) && !defined(QL_DEBUG_LEVEL_5)
-                if (pkt->entry_type == STATUS_TYPE)
-                {
-                    if ((uint8_t)(pkt->scsi_status) || pkt->comp_status ||
-                        pkt->entry_status)
-                    {
-                        DEBUG(qla1280_print("qla1280_isr: ha->rsp_ring_index = ");)
-                        DEBUG(qla1280_output_number((uint32_t)ha->rsp_ring_index,
-                                16);)
-                        DEBUG(qla1280_print(" mailbox[5] = ");)
-                        DEBUG(qla1280_output_number((uint32_t)mailbox[5], 16);)
-                        DEBUG(qla1280_print( "\n\r comp_status = ");)
-                        DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);)
-                        DEBUG(qla1280_print( ", ");)
-                        DEBUG(qla1280_print( " scsi_status = ");)
-                        DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);)
-                        DEBUG(qla1280_print( "\n\r");)
-                        /* qla1280_print(
-                        "\n\rqla1280_isr: response packet data\n\r");
-                        qla1280_dump_buffer((caddr_t)pkt,
-                        RESPONSE_ENTRY_SIZE); */
-                    }
-                }
-                else
-                {
-                    qla1280_print("qla1280_isr: ha->rsp_ring_index = ");
-                    qla1280_output_number((uint32_t)ha->rsp_ring_index, 16);
-                    qla1280_print(" mailbox[5] = ");
-                    qla1280_output_number((uint32_t)mailbox[5], 16);
-                    qla1280_print(
-                            "\n\rqla1280_isr: response packet data\n\r");
-                    qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE);
-                }
-#endif
-                if (pkt->entry_type == STATUS_TYPE || pkt->entry_status)
-                {
-                    if (pkt->entry_type == STATUS_TYPE)
-                        qla1280_status_entry(ha, (sts_entry_t *)pkt,
-                                done_q_first, done_q_last);
-                    else
-                        qla1280_error_entry(ha, pkt,
-                                done_q_first, done_q_last);
-
-                    /* Adjust ring index. */
-                    ha->rsp_ring_index++;
-                    if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT)
-                    {
-                        ha->rsp_ring_index = 0;
-                        ha->response_ring_ptr = ha->response_ring;
-                    }
-                    else
-                        ha->response_ring_ptr++;
-                    WRT_REG_WORD(&reg->mailbox5, ha->rsp_ring_index);
-                }
-#if QLA1280_TARGET_MODE_SUPPORT
-                else
-                {
-                    pkt = &response_entry;
-
-                    /* Copy packet. */
-                    dptr1 = (uint32_t *)ha->response_ring_ptr;
-                    dptr2 = (uint32_t *)pkt;
-                    for (index = 0; index < RESPONSE_ENTRY_SIZE/4; index++)
-                        *dptr2++ = *dptr1++;
-
-                    /* Adjust ring index. */
-                    ha->rsp_ring_index++;
-                    if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT)
-                    {
-                        ha->rsp_ring_index = 0;
-                        ha->response_ring_ptr = ha->response_ring;
-                    }
-                    else
-                        ha->response_ring_ptr++;
-                    WRT_REG_WORD(&reg->mailbox5, ha->rsp_ring_index);
-
-                    /* Release interrupt specific lock */
-                    QLA1280_INTR_UNLOCK(ha);
-
-                    switch (pkt->entry_type)
-                    {
-                        case ACCEPT_TGT_IO_TYPE:
-                            qla1280_atio_entry(ha, (atio_entry_t *)pkt);
-                            break;
-                        case IMMED_NOTIFY_TYPE:
-                            qla1280_notify_entry(ha, (notify_entry_t *)pkt);
-                            break;
-                        case CTIO_RET_TYPE:
-                            qla1280_accept_io(ha, (ctio_ret_entry_t *)pkt);
-                            break;
-                        default:
-                            break;
-                    }
-
-                    /* Acquire interrupt specific lock */
-                    QLA1280_INTR_LOCK(ha);
-                }
-#endif
-            }
-        }
-        else
-        {
-            ha->flags.isp_abort_needed = TRUE;
-#ifdef QL_DEBUG_LEVEL_2
-            qla1280_print("qla1280_isr: Response pointer Error\n");
+static void
+qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first,
+	    srb_t ** done_q_last)
+{
+	struct device_reg *reg = ha->iobase;
+	response_t *pkt;
+	srb_t *sp = 0;
+	uint16_t mailbox[MAILBOX_REGISTER_COUNT];
+	uint16_t *wptr;
+	uint32_t index;
+	u16 istatus;
+
+	ENTER("qla1280_isr");
+
+	istatus = RD_REG_WORD(&reg->istatus);
+	if (!(istatus & (RISC_INT | PCI_INT)))
+		return;
+
+	/* Save mailbox register 5 */
+	mailbox[5] = RD_REG_WORD(&reg->mailbox5);
+
+	/* Check for mailbox interrupt. */
+
+	mailbox[0] = RD_REG_WORD(&reg->semaphore);
+
+	if (mailbox[0] & BIT_0) {
+		/* Get mailbox data. */
+		/* dprintk(1, "qla1280_isr: In Get mailbox data \n"); */
+
+		wptr = &mailbox[0];
+		*wptr++ = RD_REG_WORD(&reg->mailbox0);
+		*wptr++ = RD_REG_WORD(&reg->mailbox1);
+		*wptr = RD_REG_WORD(&reg->mailbox2);
+		if (mailbox[0] != MBA_SCSI_COMPLETION) {
+			wptr++;
+			*wptr++ = RD_REG_WORD(&reg->mailbox3);
+			*wptr++ = RD_REG_WORD(&reg->mailbox4);
+			wptr++;
+			*wptr++ = RD_REG_WORD(&reg->mailbox6);
+			*wptr = RD_REG_WORD(&reg->mailbox7);
+		}
+
+		/* Release mailbox registers. */
+
+		WRT_REG_WORD(&reg->semaphore, 0);
+		WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+
+		dprintk(5, "qla1280_isr: mailbox interrupt mailbox[0] = 0x%x",
+			mailbox[0]);
+
+		/* Handle asynchronous event */
+		switch (mailbox[0]) {
+		case MBA_SCSI_COMPLETION:	/* Response completion */
+			dprintk(5,
+				"qla1280_isr: mailbox SCSI response completion\n");
+
+			if (ha->flags.online) {
+				/* Get outstanding command index. */
+				index = mailbox[2] << 16 | mailbox[1];
+
+				/* Validate handle. */
+				if (index < MAX_OUTSTANDING_COMMANDS)
+					sp = ha->outstanding_cmds[index];
+				else
+					sp = 0;
+
+				if (sp) {
+					/* Free outstanding command slot. */
+					ha->outstanding_cmds[index] = 0;
+
+					/* Save ISP completion status */
+					CMD_RESULT(sp->cmd) = 0;
+
+					/* Place block on done queue */
+					sp->s_next = NULL;
+					sp->s_prev = *done_q_last;
+					if (!*done_q_first)
+						*done_q_first = sp;
+					else
+						(*done_q_last)->s_next = sp;
+					*done_q_last = sp;
+				} else {
+					/*
+					 * If we get here we have a real problem!
+					 */
+					printk(KERN_WARNING
+					       "qla1280: ISP invalid handle");
+					ha->flags.isp_abort_needed = TRUE;
+				}
+			}
+			break;
+
+		case MBA_BUS_RESET:	/* SCSI Bus Reset */
+			ha->flags.reset_marker = TRUE;
+			index = mailbox[6] & BIT_0;
+			ha->bus_settings[index].reset_marker = TRUE;
+
+			printk(KERN_DEBUG
+			       "qla1280_isr(): index %i asynchronous "
+			       "BUS_RESET\n", index);
+			break;
+
+		case MBA_SYSTEM_ERR:	/* System Error */
+			printk(KERN_WARNING
+			       "qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, "
+			       "mbx3=%xh\n", mailbox[1], mailbox[2],
+			       mailbox[3]);
+			ha->flags.isp_abort_needed = TRUE;
+			break;
+
+		case MBA_REQ_TRANSFER_ERR:	/* Request Transfer Error */
+			printk(KERN_WARNING
+			       "qla1280: ISP Request Transfer Error\n");
+			ha->flags.isp_abort_needed = TRUE;
+			break;
+
+		case MBA_RSP_TRANSFER_ERR:	/* Response Transfer Error */
+			printk(KERN_WARNING
+			       "qla1280: ISP Response Transfer Error\n");
+			ha->flags.isp_abort_needed = TRUE;
+			break;
+
+		case MBA_WAKEUP_THRES:	/* Request Queue Wake-up */
+			dprintk(2, "qla1280_isr: asynchronous WAKEUP_THRES\n");
+			break;
+
+		case MBA_TIMEOUT_RESET:	/* Execution Timeout Reset */
+			dprintk(2,
+				"qla1280_isr: asynchronous TIMEOUT_RESET\n");
+			break;
+
+		case MBA_DEVICE_RESET:	/* Bus Device Reset */
+			dprintk(2,
+				"qla1280_isr: asynchronous BUS_DEVICE_RESET\n");
+			printk(KERN_INFO "qla1280_isr(): asynchronous "
+			       "BUS_DEVICE_RESET\n");
+
+			ha->flags.reset_marker = TRUE;
+			index = mailbox[6] & BIT_0;
+			ha->bus_settings[index].reset_marker = TRUE;
+			break;
+
+		case MBA_BUS_MODE_CHANGE:
+			dprintk(2,
+				"qla1280_isr: asynchronous BUS_MODE_CHANGE\n");
+			break;
+
+		default:
+			/* dprintk(1, "qla1280_isr: default case of switch MB \n"); */
+			if (mailbox[0] < MBA_ASYNC_EVENT) {
+				wptr = &mailbox[0];
+				memcpy((uint16_t *) ha->mailbox_out, wptr,
+				       MAILBOX_REGISTER_COUNT *
+				       sizeof(uint16_t));
+				ha->flags.mbox_int = TRUE;
+			}
+			break;
+		}
+	} else {
+		WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+	}
+
+	/*
+	 * Response ring - waiting for the mbox_busy flag here seems
+	 * unnecessary as the mailbox data has been copied to ha->mailbox_out
+	 * by the time we actually get here!
+	 */
+	if (ha->flags.online
+#if 0
+	    && !ha->flags.mbox_busy
 #endif
-        }
-    }
+		) {
+		if (mailbox[5] < RESPONSE_ENTRY_CNT) {
+			while (ha->rsp_ring_index != mailbox[5]) {
+				pkt = ha->response_ring_ptr;
+
+				dprintk(5,
+					"qla1280_isr: ha->rsp_ring_index = 0x%x, "
+					"mailbox[5] = 0x%x\n",
+					ha->rsp_ring_index, mailbox[5]);
+				dprintk(5,
+					"qla1280_isr: response packet data\n");
+				qla1280_dump_buffer(5, (char *)pkt,
+						    RESPONSE_ENTRY_SIZE);
+
+				if (pkt->entry_type == STATUS_TYPE) {
+					if ((pkt->scsi_status & 0xff)
+					    || pkt->comp_status
+					    || pkt->entry_status) {
+						dprintk(2,
+							"qla1280_isr: ha->rsp_ring_index = 0x%x"
+							"mailbox[5] = 0x%x, comp_status = 0x%x, "
+							"scsi_status = 0x%x\n",
+							ha->rsp_ring_index,
+							mailbox[5],
+							pkt->comp_status,
+							pkt->scsi_status);
+					}
+				} else {
+					dprintk(2,
+						"qla1280_isr: ha->rsp_ring_index = 0x%x, "
+						"mailbox[5] = 0x%x\n",
+						ha->rsp_ring_index,
+						mailbox[5]);
+					dprintk(2,
+						"qla1280_isr: response packet data\n");
+					qla1280_dump_buffer(2, (char *)pkt,
+							    RESPONSE_ENTRY_SIZE);
+				}
+
+				if (pkt->entry_type == STATUS_TYPE
+				    || pkt->entry_status) {
+					if (pkt->entry_type == STATUS_TYPE)
+						qla1280_status_entry(ha,
+								     (sts_entry_t *) pkt,
+								     done_q_first,
+								     done_q_last);
+					else
+						qla1280_error_entry(ha, pkt,
+								    done_q_first,
+								    done_q_last);
+
+					/* Adjust ring index. */
+					ha->rsp_ring_index++;
+					if (ha->rsp_ring_index ==
+					    RESPONSE_ENTRY_CNT) {
+						ha->rsp_ring_index = 0;
+						ha->response_ring_ptr =
+							ha->response_ring;
+					} else
+						ha->response_ring_ptr++;
+					WRT_REG_WORD(&reg->mailbox5,
+						     ha->rsp_ring_index);
+				}
+#if QLA1280_TARGET_MODE_SUPPORT
+				else {
+					pkt = &response_entry;
+
+					/* Copy packet. */
+					dptr1 =
+						(uint32_t *)ha->response_ring_ptr;
+					dptr2 = (uint32_t *) pkt;
+					for (index = 0;
+					     index < RESPONSE_ENTRY_SIZE / 4;
+					     index++)
+						*dptr2++ = *dptr1++;
+
+					/* Adjust ring index. */
+					ha->rsp_ring_index++;
+					if (ha->rsp_ring_index ==
+					    RESPONSE_ENTRY_CNT) {
+						ha->rsp_ring_index = 0;
+						ha->response_ring_ptr =
+							ha->response_ring;
+					} else
+						ha->response_ring_ptr++;
+					WRT_REG_WORD(&reg->mailbox5,
+						     ha->rsp_ring_index);
+
+					switch (pkt->entry_type) {
+					case ACCEPT_TGT_IO_TYPE:
+						qla1280_atio_entry(ha,
+								   (atio_entry_t *) pkt);
+						break;
+					case IMMED_NOTIFY_TYPE:
+						qla1280_notify_entry(ha,
+								     (notify_entry_t *) pkt);
+						break;
+					case CTIO_RET_TYPE:
+						qla1280_accept_io(ha,
+								  (ctio_ret_entry_t *) pkt);
+						break;
+					default:
+						break;
+					}
+				}
+#endif
+			}
+		} else {
+			ha->flags.isp_abort_needed = TRUE;
+			dprintk(2, "qla1280_isr: Response pointer Error\n");
+		}
+	}
 
-    LEAVE("qla1280_isr");
+	LEAVE("qla1280_isr");
 }
 
 /*
@@ -5205,55 +5084,51 @@
  * Input:
  *      ha  = adapter block pointer.
  */
-STATIC void
-qla1280_rst_aen(scsi_qla_host_t *ha)
+static void
+qla1280_rst_aen(struct scsi_qla_host *ha)
 {
 #if QL1280_TARGET_MODE_SUPPORT
-    notify_entry_t  nentry;
+	notify_entry_t nentry;
 #endif
-    uint8_t         b;
+	uint8_t bus;
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_rst_aen");
-#endif
+	ENTER("qla1280_rst_aen");
 
-    if (ha->flags.online && !ha->flags.reset_active &&
-        !ha->flags.abort_isp_active)
-    {
-        ha->flags.reset_active = TRUE;
-        while (ha->flags.reset_marker)
-        {
-            /* Issue marker command. */
-            ha->flags.reset_marker = FALSE;
-            for (b = 0; b < ha->ports && !ha->flags.reset_marker; b++)
-            {
-                if (ha->bus_settings[b].reset_marker)
-                {
-                    ha->bus_settings[b].reset_marker = FALSE;
-                    qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+	if (ha->flags.online && !ha->flags.reset_active &&
+	    !ha->flags.abort_isp_active) {
+		ha->flags.reset_active = TRUE;
+		while (ha->flags.reset_marker) {
+			/* Issue marker command. */
+			ha->flags.reset_marker = FALSE;
+			for (bus = 0; bus < ha->ports &&
+				     !ha->flags.reset_marker; bus++) {
+				if (ha->bus_settings[bus].reset_marker) {
+					ha->bus_settings[bus].reset_marker =
+						FALSE;
+					qla1280_marker(ha, bus, 0, 0,
+						       MK_SYNC_ALL);
 
-                    if (!ha->flags.reset_marker)
-                    {
+					if (!ha->flags.reset_marker) {
 #if QL1280_TARGET_MODE_SUPPORT
-                        /* Issue notify acknowledgement command. */
-                        bzero((caddr_t)&nentry, sizeof(notify_entry_t));
-
-                        nentry.initiator_id = nentry.target_id = b ?
-                                ha->bus_settings[b].id | BIT_7 :
-                        ha->bus_settings[b].id;
-                        qla1280_notify_entry(ha, &nentry);
-#endif
-
-                        /* Asynchronous event notification */
-                    }
-                }
-            }
-        }
-    }
+						/* Issue notify acknowledgement command. */
+						memset(&nentry, 0,
+						       sizeof(notify_entry_t));
+
+						nentry.initiator_id =
+							nentry.target_id =
+							bus ? ha->bus_settings[bus].id | BIT_7 :
+							ha->bus_settings[bus].id;
+						qla1280_notify_entry(ha,
+								     &nentry);
+#endif
+						/* Asynchronous event notification */
+					}
+				}
+			}
+		}
+	}
 
-#ifdef QL_DEBUG_LEVEL_3
-    LEAVE("qla1280_rst_aen");
-#endif
+	LEAVE("qla1280_rst_aen");
 }
 
 #if QL1280_TARGET_MODE_SUPPORT
@@ -5265,426 +5140,399 @@
  *      ha  = adapter block pointer.
  *      pkt = entry pointer.
  */
-STATIC void
-qla1280_atio_entry(scsi_qla_host_t *ha, atio_entry_t *pkt)
+static void
+qla1280_atio_entry(struct scsi_qla_host *ha, atio_entry_t * pkt)
 {
-    uint64_t    *a64;
-    uint64_t    *end_a64;
-    paddr32_t   phy_addr[2];
-    paddr32_t   end_addr[2];
-    uint32_t    len;
-    uint32_t    offset;
-    uint8_t     t;
-    uint8_t     *sense_ptr;
-
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_atio_entry: entered\n\r");
-#endif
-
-    t = pkt->initiator_id;
-    sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE;
-    a64 = (uint64_t *)&phy_addr[0];
-    end_a64 = (uint64_t *)&end_addr[0];
-
-    switch (pkt->status & ~BIT_7)
-    {
-        case 7:                         /* Path invalid */
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-            qla1280_print("qla1280_atio_entry: Path invalid\n\r");
-#endif
-            break;
-        case 0x14:                  /* Target Bus Phase Sequence Failure */
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-            qla1280_print(
-                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
-#endif
-            if (pkt->status & BIT_7)
-            {
-                BCOPY((caddr_t)&pkt->sense_data, sense_ptr,TARGET_SENSE_SIZE);
-            }
-            else
-            {
-                    bzero(sense_ptr, TARGET_SENSE_SIZE);
-                    *sense_ptr = 0x70;
-                    *(sense_ptr+2) = SD_HARDERR;
-                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                    *(sense_ptr+12) = SC_SELFAIL;
-            }
-            pkt->scsi_status = S_CKCON;
-            pkt->option_flags |= (uint32_t)OF_SSTS | (uint32_t)OF_NO_DATA;
-            if (ha->flags.enable_64bit_addressing)
-                qla1280_64bit_continue_io(ha, pkt, 0, 0);
-            else
-                qla1280_32bit_continue_io(ha, pkt, 0, 0);
-            break;
-        case 0x16:                  /* Requested Capability Not Available */
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-            qla1280_print(
-                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
-#endif
-            break;
-        case 0x17:                  /* Bus Device Reset Message Received */
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-            qla1280_print(
-                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
-#endif
-            break;
-        case 0x3D:                  /* CDB Received */
-
-            /* Check for invalid LUN */
-            if (pkt->lun && pkt->cdb[0] != SS_INQUIR &&
-                pkt->cdb[0] != SS_REQSEN)
-                pkt->cdb[0] = SS_TEST;
-
-            switch (pkt->cdb[0])
-            {
-                case SS_TEST:
-#ifdef QL_DEBUG_LEVEL_3
-                    qla1280_print("qla1280_atio_entry: SS_TEST\n\r");
-#endif
-                    bzero(sense_ptr, TARGET_SENSE_SIZE);
-                    len = 0;
-                    if (pkt->lun == 0)
-                        pkt->scsi_status = S_GOOD;
-                    else
-                    {
-                        *sense_ptr = 0x70;
-                        *(sense_ptr+2) = SD_ILLREQ;
-                        *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                        *(sense_ptr+12) = SC_INVLUN;
-                        pkt->scsi_status = S_CKCON;
-                    }
-
-                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                            (uint32_t)OF_NO_DATA;
-                    break;
-                case SS_REQSEN:
-#ifdef QL_DEBUG_LEVEL_3
-                    qla1280_print("qla1280_atio_entry: SS_REQSEN\n\r");
-#endif
-                    phy_addr[0] = ha->tsense_dma;
-                    phy_addr[1] = 0;
-                    *a64 += t * TARGET_SENSE_SIZE;
-                    if (pkt->cdb[4] > TARGET_SENSE_SIZE)
-                        len = TARGET_SENSE_SIZE;
-                    else
-                        len = pkt->cdb[4];
-                    pkt->scsi_status = S_GOOD;
-                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                            (uint32_t)OF_DATA_IN;
-                    break;
-                case SS_INQUIR:
-#ifdef QL_DEBUG_LEVEL_3
-                    qla1280_print("qla1280_atio_entry: SS_INQUIR\n\r");
-#endif
-                    bzero(sense_ptr, TARGET_SENSE_SIZE);
-                    phy_addr[0] = ha->tbuf_dma;
-                    phy_addr[1] = 0;
-                    *a64 += TARGET_INQ_OFFSET;
-
-                    if (pkt->lun == 0)
-                    {
-                            ha->tbuf->inq.id_type = ID_PROCESOR;
-                            ha->tbuf->inq.id_pqual = ID_QOK;
-                    }
-                    else
-                    {
-                            ha->tbuf->inq.id_type = ID_NODEV;
-                            ha->tbuf->inq.id_pqual = ID_QNOLU;
-                    }
-
-                    if (pkt->cdb[4] > sizeof(struct ident))
-                        len = sizeof(struct ident);
-                    else
-                        len = pkt->cdb[4];
-                    pkt->scsi_status = S_GOOD;
-                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                            (uint32_t)OF_DATA_IN;
-                    break;
-                case SM_WRDB:
-                    bzero(sense_ptr, TARGET_SENSE_SIZE);
-                    offset = pkt->cdb[5];
-                    offset |= pkt->cdb[4] << 8;
-                    offset |= pkt->cdb[3] << 16;
-                    len = pkt->cdb[8];
-                    len |= pkt->cdb[7] << 8;
-                    len |= pkt->cdb[6] << 16;
-                    end_addr[0] = phy_addr[0] = ha->tbuf_dma;
-                    end_addr[1] = phy_addr[1] = 0;
-                    *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
-                    switch (pkt->cdb[1] & 7)
-                    {
-                        case RW_BUF_HDATA:
-#ifdef QL_DEBUG_LEVEL_3
-                            qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_HDATA\n\r");
-#endif
-                            if (len > TARGET_DATA_SIZE + 4)
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                qla1280_print("qla1280_atio_entry: SM_WRDB, length > buffer size\n\r");
-#endif
-                                *sense_ptr = 0x70;
-                                *(sense_ptr+2) = SD_ILLREQ;
-                                *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                                *(sense_ptr+12) = SC_ILLCDB;
-                                pkt->scsi_status = S_CKCON;
-                                pkt->option_flags |= (uint32_t)OF_SSTS |
-                                        (uint32_t)OF_NO_DATA;
-                                len = 0;
-                            }
-                            else if (len)
-                            {
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_DATA_OUT;
-#ifdef QL_DEBUG_LEVEL_3
-                                    qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r");
-#endif
-                                    sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
-                                            pkt->target_id, pkt->lun, 0, offset);
-                            }
-                            else
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                    qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r");
-#endif
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_NO_DATA;
-                            }
-
-                            break;
-                        case RW_BUF_DATA:
-#ifdef QL_DEBUG_LEVEL_3
-                            qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA\n\r");
-#endif
-                            *a64 += offset + TARGET_DATA_OFFSET;
-                            if (pkt->cdb[2] != 0 || *a64 >= *end_a64 ||
-                                *a64 + len > *end_a64)
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                    qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA BAD\n\r");
-                                    qla1280_print("buf_id=");
-                                    qla1280_output_number((uint32_t)pkt->cdb[2], 16);
-                                    qla1280_print(", offset=");
-                                    qla1280_output_number((uint32_t)offset, 16);
-                                    qla1280_print(", length=");
-                                    qla1280_output_number((uint32_t)len, 16);
-                                    qla1280_print("\n\r");
-#endif
-                                    *sense_ptr = 0x70;
-                                    *(sense_ptr+2) = SD_ILLREQ;
-                                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                                    *(sense_ptr+12) = SC_ILLCDB;
-                                    len = 0;
-                                    pkt->scsi_status = S_CKCON;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_NO_DATA;
-                            }
-                            else if (len)
-                            {
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_DATA_OUT;
-#ifdef QL_DEBUG_LEVEL_3
-                                    qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r");
-#endif
-                                    sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
-                                            pkt->target_id, pkt->lun, 0, offset);
-                            }
-                            else
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                    qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r");
-#endif
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_NO_DATA;
-                            }
-                            break;
-                        default:
-#ifdef QL_DEBUG_LEVEL_2
-                            qla1280_print("qla1280_atio_entry: SM_WRDB unknown mode\n\r");
-#endif
-                            *sense_ptr = 0x70;
-                            *(sense_ptr+2) = SD_ILLREQ;
-                            *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                            *(sense_ptr+12) = SC_ILLCDB;
-                            len = 0;
-                            pkt->scsi_status = S_CKCON;
-                            pkt->option_flags |= (uint32_t)OF_SSTS |
-                                    (uint32_t)OF_NO_DATA;
-                            break;
-                    }
-                    break;
-                case SM_RDDB:
-                    bzero(sense_ptr, TARGET_SENSE_SIZE);
-                    offset = pkt->cdb[5];
-                    offset |= pkt->cdb[4] << 8;
-                    offset |= pkt->cdb[3] << 16;
-                    len = pkt->cdb[8];
-                    len |= pkt->cdb[7] << 8;
-                    len |= pkt->cdb[6] << 16;
-                    end_addr[0] = phy_addr[0] = ha->tbuf_dma;
-                    end_addr[1] = phy_addr[1] = 0;
-                    *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
-                    switch (pkt->cdb[1] & 7)
-                    {
-                        case RW_BUF_HDATA:
-#ifdef QL_DEBUG_LEVEL_3
-                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_HDATA\n\r");
-#endif
-                            if (len)
-                            {
-                                ha->tbuf->hdr[0] = 0;
-                                ha->tbuf->hdr[1] =
-                                        (uint8_t)(TARGET_DATA_SIZE >> 16);
-                                ha->tbuf->hdr[2] =
-                                        (uint8_t)(TARGET_DATA_SIZE >> 8);
-                                ha->tbuf->hdr[3] = (uint8_t)TARGET_DATA_SIZE;
-                                if (len > TARGET_DATA_SIZE + 4)
-                                    len = TARGET_DATA_SIZE + 4;
-                                pkt->scsi_status = S_GOOD;
-                                pkt->option_flags |= (uint32_t)OF_SSTS |
-                                        (uint32_t)OF_DATA_IN;
-                            }
-                            else
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                    qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
-#endif
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_NO_DATA;
-                            }
-                            break;
-                        case RW_BUF_DATA:
-#ifdef QL_DEBUG_LEVEL_3
-                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA\n\r");
-#endif
-                            *a64 += offset + TARGET_DATA_OFFSET;
-                            if (pkt->cdb[2] != 0 || *a64 >= *end_a64)
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                    qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA BAD\n\r");
-                                    qla1280_print("buf_id=");
-                                    qla1280_output_number((uint32_t)pkt->cdb[2], 16);
-                                    qla1280_print(", offset=");
-                                    qla1280_output_number((uint32_t)offset, 16);
-                                    qla1280_print("\n\r");
-#endif
-                                    *sense_ptr = 0x70;
-                                    *(sense_ptr+2) = SD_ILLREQ;
-                                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                                    *(sense_ptr+12) = SC_ILLCDB;
-                                    len = 0;
-                                    pkt->scsi_status = S_CKCON;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_NO_DATA;
-                            }
-                            else
-                            {
-                                    if (*a64 + len > *end_a64)
-                                        len = *end_a64 - *a64;
-                                    if (len)
-                                    {
-                                        pkt->scsi_status = S_GOOD;
-                                        pkt->option_flags |= (uint32_t)OF_SSTS |
-                                                (uint32_t)OF_DATA_IN;
-                                    }
-                                    else
-                                    {
-#ifdef QL_DEBUG_LEVEL_2
-                                            qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
-#endif
-                                            pkt->scsi_status = S_GOOD;
-                                            pkt->option_flags |= (uint32_t)OF_SSTS |
-                                                    (uint32_t)OF_NO_DATA;
-                                    }
-                            }
-                            break;
-                        case RW_BUF_DESC:
-#ifdef QL_DEBUG_LEVEL_3
-                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DESC\n\r");
-#endif
-                            if (len)
-                            {
-                                    if (len > 4)
-                                        len = 4;
-
-                                    ha->tbuf->hdr[0] = 0;
-                                    if (pkt->cdb[2] != 0)
-                                    {
-                                        ha->tbuf->hdr[1] = 0;
-                                        ha->tbuf->hdr[2] = 0;
-                                        ha->tbuf->hdr[3] = 0;
-                                    }
-                                    else
-                                    {
-                                            ha->tbuf->hdr[1] =
-                                                    (uint8_t)(TARGET_DATA_SIZE >> 16);
-                                            ha->tbuf->hdr[2] =
-                                                    (uint8_t)(TARGET_DATA_SIZE >> 8);
-                                            ha->tbuf->hdr[3] =
-                                                    (uint8_t)TARGET_DATA_SIZE;
-                                    }
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_DATA_IN;
-                            }
-                            else
-                            {
-#ifdef QL_DEBUG_LEVEL_2
-                                    qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
-#endif
-                                    pkt->scsi_status = S_GOOD;
-                                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                                            (uint32_t)OF_NO_DATA;
-                            }
-                            break;
-                        default:
-#ifdef QL_DEBUG_LEVEL_2
-                            qla1280_print("qla1280_atio_entry: SM_RDDB unknown mode\n\r");
-#endif
-                            *sense_ptr = 0x70;
-                            *(sense_ptr+2) = SD_ILLREQ;
-                            *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                            *(sense_ptr+12) = SC_ILLCDB;
-                            len = 0;
-                            pkt->scsi_status = S_CKCON;
-                            pkt->option_flags |= (uint32_t)OF_SSTS |
-                                    (uint32_t)OF_NO_DATA;
-                            break;
-                    }
-                    break;
-                default:
-#ifdef QL_DEBUG_LEVEL_2
-                    qla1280_print("qla1280_atio_entry: Unknown SCSI command\n\r");
-                    qla1280_dump_buffer((caddr_t)&pkt->cdb[0], pkt->cdb_len);
-#endif
-                    bzero(sense_ptr, TARGET_SENSE_SIZE);
-                    *sense_ptr = 0x70;
-                    *(sense_ptr+2) = SD_ILLREQ;
-                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
-                    *(sense_ptr+12) = SC_INVOPCODE;
-                    len = 0;
-                    pkt->scsi_status = S_CKCON;
-                    pkt->option_flags |= (uint32_t)OF_SSTS |
-                            (uint32_t)OF_NO_DATA;
-                    break;
-            }
-            if (ha->flags.enable_64bit_addressing)
-                qla1280_64bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr);
-            else
-                qla1280_32bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr);
-            break;
-        default:
-            break;
-    }
+	uint64_t *a64;
+	uint64_t *end_a64;
+	paddr32_t phy_addr[2];
+	paddr32_t end_addr[2];
+	uint32_t len;
+	uint32_t offset;
+	uint8_t t;
+	uint8_t *sense_ptr;
+
+	dprintk(3, "qla1280_atio_entry: entered\n");
+
+	t = pkt->initiator_id;
+	sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE;
+	a64 = (uint64_t *)&phy_addr[0];
+	end_a64 = (uint64_t *)&end_addr[0];
+
+	switch (pkt->status & ~BIT_7) {
+	case 7:		/* Path invalid */
+		dprintk(2, "qla1280_atio_entry: Path invalid\n");
+		break;
+
+	case 0x14:		/* Target Bus Phase Sequence Failure */
+		dprintk(2, "qla1280_atio_entry: Target Bus Phase "
+			"Sequence Failure\n");
+
+		if (pkt->status & BIT_7) {
+			memcpy(sense_ptr, &pkt->sense_data, TARGET_SENSE_SIZE);
+		} else {
+			memset(sense_ptr, 0, TARGET_SENSE_SIZE);
+			*sense_ptr = 0x70;
+			*(sense_ptr + 2) = SD_HARDERR;
+			*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
+			*(sense_ptr + 12) = SC_SELFAIL;
+		}
+		pkt->scsi_status = S_CKCON;
+		pkt->option_flags |= OF_SSTS | OF_NO_DATA;
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_atio_entry: exiting normally\n\r");
-#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
+		if (ha->flags.enable_64bit_addressing)
+			qla1280_64bit_continue_io(ha, pkt, 0, 0);
+		else
+#endif
+			qla1280_32bit_continue_io(ha, pkt, 0, 0);
+		break;
+
+	case 0x16:		/* Requested Capability Not Available */
+		dprintk(2, "qla1280_atio_entry: Target Bus Phase "
+			"Sequence Failure\n");
+		break;
+
+	case 0x17:		/* Bus Device Reset Message Received */
+		dprintk(2, "qla1280_atio_entry: Target Bus Phase "
+			"Sequence Failure\n");
+		break;
+
+	case 0x3D:		/* CDB Received */
+
+		/* Check for invalid LUN */
+		if (pkt->lun && pkt->cdb[0] != SS_INQUIR &&
+		    pkt->cdb[0] != SS_REQSEN)
+			pkt->cdb[0] = SS_TEST;
+
+		switch (pkt->cdb[0]) {
+		case SS_TEST:
+			dprintk(3, "qla1280_atio_entry: SS_TEST\n");
+
+			memset(sense_ptr, 0, TARGET_SENSE_SIZE);
+			len = 0;
+			if (pkt->lun == 0)
+				pkt->scsi_status = S_GOOD;
+			else {
+				*sense_ptr = 0x70;
+				*(sense_ptr + 2) = SD_ILLREQ;
+				*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
+				*(sense_ptr + 12) = SC_INVLUN;
+				pkt->scsi_status = S_CKCON;
+			}
+
+			pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
+			break;
+
+		case SS_REQSEN:
+			dprintk(3, "qla1280_atio_entry: SS_REQSEN\n");
+
+			phy_addr[0] = ha->tsense_dma;
+			phy_addr[1] = 0;
+			*a64 += t * TARGET_SENSE_SIZE;
+			if (pkt->cdb[4] > TARGET_SENSE_SIZE)
+				len = TARGET_SENSE_SIZE;
+			else
+				len = pkt->cdb[4];
+			pkt->scsi_status = S_GOOD;
+			pkt->option_flags |= (OF_SSTS | OF_DATA_IN);
+			break;
+
+		case SS_INQUIR:
+			dprintk(3, "qla1280_atio_entry: SS_INQUIR\n");
+
+			memset(sense_ptr, 0, TARGET_SENSE_SIZE);
+			phy_addr[0] = ha->tbuf_dma;
+			phy_addr[1] = 0;
+			*a64 += TARGET_INQ_OFFSET;
+
+			if (pkt->lun == 0) {
+				ha->tbuf->inq.id_type = ID_PROCESOR;
+				ha->tbuf->inq.id_pqual = ID_QOK;
+			} else {
+				ha->tbuf->inq.id_type = ID_NODEV;
+				ha->tbuf->inq.id_pqual = ID_QNOLU;
+			}
+
+			if (pkt->cdb[4] > sizeof(struct ident))
+				len = sizeof(struct ident);
+			else
+				len = pkt->cdb[4];
+			pkt->scsi_status = S_GOOD;
+			pkt->option_flags |= (OF_SSTS | OF_DATA_IN);
+			break;
+
+		case SM_WRDB:
+			memset(sense_ptr, 0, TARGET_SENSE_SIZE);
+			offset = pkt->cdb[5];
+			offset |= pkt->cdb[4] << 8;
+			offset |= pkt->cdb[3] << 16;
+			len = pkt->cdb[8];
+			len |= pkt->cdb[7] << 8;
+			len |= pkt->cdb[6] << 16;
+			end_addr[0] = phy_addr[0] = ha->tbuf_dma;
+			end_addr[1] = phy_addr[1] = 0;
+			*end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
+			switch (pkt->cdb[1] & 7) {
+			case RW_BUF_HDATA:
+				dprintk(3, "qla1280_atio_entry: SM_WRDB, "
+					"RW_BUF_HDATA\n");
+
+				if (len > TARGET_DATA_SIZE + 4) {
+					dprintk(2,
+						"qla1280_atio_entry: SM_WRDB, "
+						"length > buffer size\n");
+
+					*sense_ptr = 0x70;
+					*(sense_ptr + 2) = SD_ILLREQ;
+					*(sense_ptr + 7) =
+						TARGET_SENSE_SIZE - 8;
+					*(sense_ptr + 12) = SC_ILLCDB;
+					pkt->scsi_status = S_CKCON;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+					len = 0;
+				} else if (len) {
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_DATA_OUT);
+					dprintk(3,
+						"qla1280_atio_entry: Issuing "
+						"SDI_TARMOD_WRCOMP\n");
+
+					sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
+						 pkt->target_id, pkt->lun, 0,
+						 offset);
+				} else {
+					dprintk(2,
+						"qla1280_atio_entry: SM_WRDB, "
+						"zero length\n");
+
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+				}
+
+				break;
+			case RW_BUF_DATA:
+				dprintk(3, "qla1280_atio_entry: SM_WRDB, "
+					"RW_BUF_DATA\n");
+
+				*a64 += offset + TARGET_DATA_OFFSET;
+				if (pkt->cdb[2] != 0 || *a64 >= *end_a64 ||
+				    *a64 + len > *end_a64) {
+					dprintk(2,
+						"qla1280_atio_entry: SM_WRDB, "
+						"RW_BUF_DATA BAD\n");
+					dprintk(2, "buf_id=0x%x, offset=0x%x, "
+						"length=0x%x\n", pkt->cdb[2],
+						offset, len);
+
+					*sense_ptr = 0x70;
+					*(sense_ptr + 2) = SD_ILLREQ;
+					*(sense_ptr + 7) =
+						TARGET_SENSE_SIZE - 8;
+					*(sense_ptr + 12) = SC_ILLCDB;
+					len = 0;
+					pkt->scsi_status = S_CKCON;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+				} else if (len) {
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_DATA_OUT);
+					dprintk(3,
+						"qla1280_atio_entry: Issuing "
+						"SDI_TARMOD_WRCOMP\n");
+
+					sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
+						 pkt->target_id, pkt->lun, 0,
+						 offset);
+				} else {
+					dprintk(2,
+						"qla1280_atio_entry: SM_WRDB, "
+						"zero length\n");
+
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+				}
+				break;
+
+			default:
+				dprintk(2, "qla1280_atio_entry: SM_WRDB "
+					"unknown mode\n");
+
+				*sense_ptr = 0x70;
+				*(sense_ptr + 2) = SD_ILLREQ;
+				*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
+				*(sense_ptr + 12) = SC_ILLCDB;
+				len = 0;
+				pkt->scsi_status = S_CKCON;
+				pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
+				break;
+			}
+			break;
+
+		case SM_RDDB:
+			memset(sense_ptr, 0, TARGET_SENSE_SIZE);
+			offset = pkt->cdb[5];
+			offset |= pkt->cdb[4] << 8;
+			offset |= pkt->cdb[3] << 16;
+			len = pkt->cdb[8];
+			len |= pkt->cdb[7] << 8;
+			len |= pkt->cdb[6] << 16;
+			end_addr[0] = phy_addr[0] = ha->tbuf_dma;
+			end_addr[1] = phy_addr[1] = 0;
+			*end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
+			switch (pkt->cdb[1] & 7) {
+			case RW_BUF_HDATA:
+				dprintk(3, "qla1280_atio_entry: SM_RDDB, "
+					"RW_BUF_HDATA\n");
+
+				if (len) {
+					ha->tbuf->hdr[0] = 0;
+					ha->tbuf->hdr[1] =
+						(TARGET_DATA_SIZE >> 16) & 0xff;
+					ha->tbuf->hdr[2] =
+						(TARGET_DATA_SIZE >> 8) & 0xff;
+					ha->tbuf->hdr[3] =
+						TARGET_DATA_SIZE & 0xff;
+					if (len > TARGET_DATA_SIZE + 4)
+						len = TARGET_DATA_SIZE + 4;
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_DATA_IN);
+				} else {
+					dprintk(2,
+						"qla1280_atio_entry: SM_RDDB, "
+						"zero length\n");
+
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+				}
+				break;
+			case RW_BUF_DATA:
+				dprintk(3, "qla1280_atio_entry: SM_RDDB, "
+					"RW_BUF_DATA\n");
+
+				*a64 += offset + TARGET_DATA_OFFSET;
+				if (pkt->cdb[2] != 0 || *a64 >= *end_a64) {
+					dprintk(2,
+						"qla1280_atio_entry: SM_RDDB, "
+						"RW_BUF_DATA BAD\n");
+					dprintk(2, "buf_id=0x%x, offset=0x%x\n"
+						pkt->cdb[2], offset);
+
+					*sense_ptr = 0x70;
+					*(sense_ptr + 2) = SD_ILLREQ;
+					*(sense_ptr + 7) =
+						TARGET_SENSE_SIZE - 8;
+					*(sense_ptr + 12) = SC_ILLCDB;
+					len = 0;
+					pkt->scsi_status = S_CKCON;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+				} else {
+					if (*a64 + len > *end_a64)
+						len = *end_a64 - *a64;
+					if (len) {
+						pkt->scsi_status = S_GOOD;
+						pkt->option_flags |=
+							(OF_SSTS | OF_DATA_IN);
+					} else {
+						dprintk(2,
+							"qla1280_atio_entry: SM_RDDB, "
+							"zero length\n");
+
+						pkt->scsi_status = S_GOOD;
+						pkt->option_flags |=
+							(OF_SSTS | OF_NO_DATA);
+					}
+				}
+				break;
+			case RW_BUF_DESC:
+				dprintk(3, "qla1280_atio_entry: SM_RDDB, "
+					"RW_BUF_DESC\n");
+
+				if (len) {
+					if (len > 4)
+						len = 4;
+
+					ha->tbuf->hdr[0] = 0;
+					if (pkt->cdb[2] != 0) {
+						ha->tbuf->hdr[1] = 0;
+						ha->tbuf->hdr[2] = 0;
+						ha->tbuf->hdr[3] = 0;
+					} else {
+						ha->tbuf->hdr[1] =
+							(TARGET_DATA_SIZE >> 16) &
+							0xff;
+						ha->tbuf->hdr[2] =
+							(TARGET_DATA_SIZE >> 8) &
+							0xff;
+						ha->tbuf->hdr[3] =
+							TARGET_DATA_SIZE & 0xff;
+					}
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_DATA_IN);
+				} else {
+					dprintk(2,
+						"qla1280_atio_entry: SM_RDDB,"
+						" zero length\n");
+
+					pkt->scsi_status = S_GOOD;
+					pkt->option_flags |=
+						(OF_SSTS | OF_NO_DATA);
+				}
+				break;
+			default:
+				dprintk(2, "qla1280_atio_entry: SM_RDDB "
+					"unknown mode\n");
+
+				*sense_ptr = 0x70;
+				*(sense_ptr + 2) = SD_ILLREQ;
+				*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
+				*(sense_ptr + 12) = SC_ILLCDB;
+				len = 0;
+				pkt->scsi_status = S_CKCON;
+				pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
+				break;
+			}
+			break;
+
+		default:
+			dprintk(2,
+				"qla1280_atio_entry: Unknown SCSI command\n");
+			qla1280_dump_buffer(2, &pkt->cdb[0], pkt->cdb_len);
+
+			memset(sense_ptr, 0, TARGET_SENSE_SIZE);
+			*sense_ptr = 0x70;
+			*(sense_ptr + 2) = SD_ILLREQ;
+			*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
+			*(sense_ptr + 12) = SC_INVOPCODE;
+			len = 0;
+			pkt->scsi_status = S_CKCON;
+			pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
+			break;
+		}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
+		if (ha->flags.enable_64bit_addressing)
+			qla1280_64bit_continue_io(ha, pkt, len,
+						  (paddr32_t *)&phy_addr);
+		else
+#endif
+			qla1280_32bit_continue_io(ha, pkt, len,
+						  (paddr32_t *)&phy_addr);
+		break;
+
+	default:
+		break;
+	}
+
+	dprintk(3, "qla1280_atio_entry: exiting normally\n");
 }
 
 /*
@@ -5695,25 +5543,21 @@
  *      ha  = adapter block pointer.
  *      pkt = entry pointer.
  */
-STATIC void
-qla1280_notify_entry(scsi_qla_host_t *ha, notify_entry_t *pkt)
+static void
+qla1280_notify_entry(struct scsi_qla_host *ha, notify_entry_t * pkt)
 {
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_notify_entry: entered\n\r");
-#endif
+	dprintk(3, "qla1280_notify_entry: entered\n");
 
-    /* Acknowledge immediate notify */
-    qla1280_notify_ack(ha, pkt);
+	/* Acknowledge immediate notify */
+	qla1280_notify_ack(ha, pkt);
 
-    /* Issue notify entry to increment resource count */
-    qla1280_immed_notify(ha, pkt);
+	/* Issue notify entry to increment resource count */
+	qla1280_immed_notify(ha, pkt);
 
-#ifdef QL_DEBUG_LEVEL_3
-    qla1280_print("qla1280_notify_entry: exiting normally\n\r");
-#endif
+	dprintk(3, "qla1280_notify_entry: exiting normally\n");
 }
+#endif				/* QLA1280_TARGET_MODE_SUPPORT */
 
-#endif  /* QLA1280_TARGET_MODE_SUPPORT */
 /*
  *  qla1280_status_entry
  *      Processes received ISP status entry.
@@ -5724,104 +5568,88 @@
  *      done_q_first = done queue first pointer.
  *      done_q_last  = done queue last pointer.
  */
-STATIC void
-qla1280_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt, srb_t **done_q_first,
-                     srb_t **done_q_last)
-{
-    uint32_t        b, t, l;
-    uint8_t         sense_sz = 0;
-    srb_t           *sp;
-    scsi_lu_t       *q;
-    Scsi_Cmnd       *cp;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_status_entry");
-#endif
-
-    /* Validate handle. */
-    if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
-        sp = ha->outstanding_cmds[pkt->handle];
-    else
-        sp = 0;
-
-    if (sp)
-    {
-        /* Free outstanding command slot. */
-        ha->outstanding_cmds[pkt->handle] = 0;
-
-        cp = sp->cmd;
-        /* Generate LU queue on cntrl, target, LUN */
-        b = SCSI_BUS_32(cp);
-        t = SCSI_TCN_32(cp);
-        l = SCSI_LUN_32(cp);
-        q = LU_Q(ha, b, t, l);
-        if( pkt->comp_status || pkt->scsi_status )
-        {
-            DEBUG(qla1280_print( "scsi: comp_status = ");)
-            DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);)
-            DEBUG(qla1280_print( ", ");)
-            DEBUG(qla1280_print( " scsi_status = ");)
-            DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);)
-            DEBUG(qla1280_print( "\n\r");)
-            DEBUG(qla1280_print(", handle = ");)
-            DEBUG(qla1280_output_number((uint32_t)pkt->handle, 16);)
-            DEBUG(qla1280_print("\n\r");)
-        }
-
-        /* Target busy */
-        if ( pkt->scsi_status & SS_BUSY_CONDITION &&
-            pkt->scsi_status != SS_RESERVE_CONFLICT   )
-        {
-            CMD_RESULT(cp) = (int) (DID_BUS_BUSY << 16) |
-                    (pkt->scsi_status & 0xff);
-        }
-        else
-        {
-
-            /* Save ISP completion status */
-            CMD_RESULT(cp) = qla1280_return_status( pkt, cp );
-
-            if (pkt->scsi_status & SS_CHECK_CONDITION)
-            {
-                BZERO(cp->sense_buffer, CMD_SNSLEN(cp));
-                if (pkt->comp_status != CS_ARS_FAILED)
-                {
-                    if ( pkt->req_sense_length < CMD_SNSLEN(cp)  )
-                        sense_sz = pkt->req_sense_length;
-                    else
-                        sense_sz = CMD_SNSLEN(cp) - 1;
-
-                    BCOPY((caddr_t)&pkt->req_sense_data, cp->sense_buffer, sense_sz);
-
-                }
-#ifdef QL_DEBUG_LEVEL_2
-                DEBUG(qla1280_print(
-                        "qla1280_status_entry: Check condition Sense data, b");)
-                DEBUG(qla1280_output_number((uint32_t)b, 10);)
-                DEBUG(qla1280_print("t");)
-                DEBUG(qla1280_output_number((uint32_t)t, 10);)
-                DEBUG(qla1280_print("d");)
-                DEBUG(qla1280_output_number((uint32_t)l, 10);)
-                DEBUG(qla1280_print("\n\r");)
-                DEBUG(if (sense_sz))
-                    DEBUG(qla1280_dump_buffer(cp->sense_buffer, sense_sz);)
-#endif
-            }
-        }
-        /* Place command on done queue. */
-        qla1280_done_q_put(sp, done_q_first, done_q_last);
-    }
-    else
-    {
-#ifdef QL_DEBUG_LEVEL_2
-        qla1280_print("qla1280_status_entry: ISP Invalid handle\n\r");
-#endif
-        printk(KERN_WARNING "qla1280: Status Entry invalid handle\n");
-        ha->flags.isp_abort_needed = TRUE;
-    }
-#ifdef QL_DEBUG_LEVEL_3
-    LEAVE("qla1280_status_entry");
-#endif
+static void
+qla1280_status_entry(struct scsi_qla_host *ha, sts_entry_t * pkt,
+		     srb_t ** done_q_first, srb_t ** done_q_last)
+{
+	unsigned int bus, target, lun;
+	int sense_sz;
+	srb_t *sp;
+	scsi_lu_t *q;
+	Scsi_Cmnd *cmd;
+
+	ENTER("qla1280_status_entry");
+
+	/* Validate handle. */
+	if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+		sp = ha->outstanding_cmds[pkt->handle];
+	else
+		sp = 0;
+
+	if (sp) {
+		/* Free outstanding command slot. */
+		ha->outstanding_cmds[pkt->handle] = 0;
+
+		cmd = sp->cmd;
+
+		/* Generate LU queue on cntrl, target, LUN */
+		bus = SCSI_BUS_32(cmd);
+		target = SCSI_TCN_32(cmd);
+		lun = SCSI_LUN_32(cmd);
+		q = LU_Q(ha, bus, target, lun);
+
+		if (pkt->comp_status || pkt->scsi_status) {
+			dprintk(1, "scsi: comp_status = 0x%x, scsi_status = "
+				"0x%x, handle = 0x%x\n", pkt->comp_status,
+				pkt->scsi_status, pkt->handle);
+		}
+
+		/* Target busy */
+		if (pkt->scsi_status & SS_BUSY_CONDITION &&
+		    pkt->scsi_status != SS_RESERVE_CONFLICT) {
+			CMD_RESULT(cmd) =
+				DID_BUS_BUSY << 16 | (pkt->scsi_status & 0xff);
+		} else {
+
+			/* Save ISP completion status */
+			CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd);
+
+			if (pkt->scsi_status & SS_CHECK_CONDITION) {
+				if (pkt->comp_status != CS_ARS_FAILED) {
+					if (pkt->req_sense_length <
+					    CMD_SNSLEN(cmd))
+						sense_sz = pkt->req_sense_length;
+					else
+						/*
+						 * Scsi_Cmnd->sense_buffer is
+						 * 64 bytes, why only copy 63?
+						 * This looks wrong! /Jes
+						 */
+						sense_sz = CMD_SNSLEN(cmd) - 1;
+
+					memcpy(cmd->sense_buffer,
+					       &pkt->req_sense_data, sense_sz);
+				} else
+					sense_sz = 0;
+				memset(cmd->sense_buffer + sense_sz, 0,
+				       sizeof(cmd->sense_buffer) - sense_sz);
+
+				dprintk(2, "qla1280_status_entry: Check "
+					"condition Sense data, b %i, t %i, "
+					"l %i\n", bus, target, lun);
+				if (sense_sz)
+					qla1280_dump_buffer(2, (char *)cmd->sense_buffer,
+							    sense_sz);
+			}
+		}
+		/* Place command on done queue. */
+		qla1280_done_q_put(sp, done_q_first, done_q_last);
+	} else {
+		printk(KERN_WARNING "qla1280: Status Entry invalid handle\n");
+		ha->flags.isp_abort_needed = TRUE;
+	}
+
+	LEAVE("qla1280_status_entry");
 }
 
 /*
@@ -5834,71 +5662,55 @@
  *      done_q_first = done queue first pointer.
  *      done_q_last  = done queue last pointer.
  */
-STATIC void
-qla1280_error_entry(scsi_qla_host_t *ha, response_t *pkt, srb_t **done_q_first,
-                    srb_t **done_q_last)
-{
-    srb_t   *sp;
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_error_entry");
-#endif
-
-#ifdef QL_DEBUG_LEVEL_2
-    if (pkt->entry_status & BIT_3)
-        qla1280_print("qla1280_error_entry: BAD PAYLOAD flag error\n\r");
-    else if (pkt->entry_status & BIT_2)
-        qla1280_print("qla1280_error_entry: BAD HEADER flag error\n\r");
-    else if (pkt->entry_status & BIT_1)
-        qla1280_print("qla1280_error_entry: FULL flag error\n\r");
-    else
-        qla1280_print("qla1280_error_entry: UNKNOWN flag error\n\r");
-#endif
-
-    /* Validate handle. */
-    if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
-        sp = ha->outstanding_cmds[pkt->handle];
-    else
-        sp = 0;
-
-    if (sp)
-    {
-        /* Free outstanding command slot. */
-        ha->outstanding_cmds[pkt->handle] = 0;
-
-        /* Bad payload or header */
-        if (pkt->entry_status & (BIT_3 + BIT_2))
-        {
-            /* Bad payload or header, set error status. */
-            /* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */
-            CMD_RESULT(sp->cmd) = (int) DID_ERROR << 16;
-        }
-        else if (pkt->entry_status & BIT_1 ) /* FULL flag */
-        {
-            CMD_RESULT(sp->cmd) = (int) DID_BUS_BUSY << 16;
-        }
-        else
-        {
-            /* Set error status. */
-            CMD_RESULT(sp->cmd) =(int)  DID_ERROR << 16;
-        }
-        /* Place command on done queue. */
-        qla1280_done_q_put(sp, done_q_first, done_q_last);
-    }
-#if  QLA1280_64BIT_SUPPORT
-    else if (pkt->entry_type == COMMAND_A64_TYPE)
-    {
-#ifdef QL_DEBUG_LEVEL_2
-        qla1280_print("qla1280_error_entry: ISP Invalid handle\n\r");
-#endif
-        printk(KERN_WARNING "!qla1280: Error Entry invalid handle");
-        ha->flags.isp_abort_needed = TRUE;
-    }
-#endif
+static void
+qla1280_error_entry(struct scsi_qla_host *ha, response_t * pkt,
+		    srb_t ** done_q_first, srb_t ** done_q_last)
+{
+	srb_t *sp;
+
+	ENTER("qla1280_error_entry");
+
+	if (pkt->entry_status & BIT_3)
+		dprintk(2, "qla1280_error_entry: BAD PAYLOAD flag error\n");
+	else if (pkt->entry_status & BIT_2)
+		dprintk(2, "qla1280_error_entry: BAD HEADER flag error\n");
+	else if (pkt->entry_status & BIT_1)
+		dprintk(2, "qla1280_error_entry: FULL flag error\n");
+	else
+		dprintk(2, "qla1280_error_entry: UNKNOWN flag error\n");
+
+	/* Validate handle. */
+	if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+		sp = ha->outstanding_cmds[pkt->handle];
+	else
+		sp = 0;
 
-#ifdef QL_DEBUG_LEVEL_3
-    LEAVE("qla1280_error_entry");
+	if (sp) {
+		/* Free outstanding command slot. */
+		ha->outstanding_cmds[pkt->handle] = 0;
+
+		/* Bad payload or header */
+		if (pkt->entry_status & (BIT_3 + BIT_2)) {
+			/* Bad payload or header, set error status. */
+			/* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */
+			CMD_RESULT(sp->cmd) = DID_ERROR << 16;
+		} else if (pkt->entry_status & BIT_1) {	/* FULL flag */
+			CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16;
+		} else {
+			/* Set error status. */
+			CMD_RESULT(sp->cmd) = DID_ERROR << 16;
+		}
+		/* Place command on done queue. */
+		qla1280_done_q_put(sp, done_q_first, done_q_last);
+	}
+#ifdef QLA_64BIT_PTR
+	else if (pkt->entry_type == COMMAND_A64_TYPE) {
+		printk(KERN_WARNING "!qla1280: Error Entry invalid handle");
+		ha->flags.isp_abort_needed = TRUE;
+	}
 #endif
+
+	LEAVE("qla1280_error_entry");
 }
 
 /*
@@ -5911,138 +5723,117 @@
  * Returns:
  *      0 = success
  */
-STATIC uint8_t
-qla1280_abort_isp(scsi_qla_host_t *ha)
+static int
+qla1280_abort_isp(struct scsi_qla_host *ha)
 {
-    device_reg_t    *reg = ha->iobase;
-    uint8_t         status = 0;
-    uint16_t        cnt;
-    srb_t           *sp;
-    scsi_lu_t       *q;
-    uint32_t        b, t, l;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-    unsigned long cpu_flags = 0;
-#endif
-
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_abort_isp");
-#endif
-
-    DRIVER_LOCK
-            ha->flags.isp_abort_needed = FALSE;
-    if (!ha->flags.abort_isp_active && ha->flags.online)
-    {
-        ha->flags.abort_isp_active = TRUE;
-
-        /* Disable ISP interrupts. */
-        WRT_REG_WORD(&reg->ictrl, 0);
-
-        /* Dequeue all commands in outstanding command list. */
-        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
-        {
-            sp = ha->outstanding_cmds[cnt];
-            if (sp)
-            {
-                ha->outstanding_cmds[cnt] = 0;
-
-                /* Generate LU queue on controller, target, LUN */
-                b = SCSI_BUS_32(sp->cmd);
-                t = SCSI_TCN_32(sp->cmd);
-                l = SCSI_LUN_32(sp->cmd);
-
-                q = (scsi_lu_t       *)LU_Q(ha, b, t, l);
-
-                /* Reset outstanding command count. */
-                q->q_outcnt = 0;
-                q->q_flag &= ~QLA1280_QBUSY;
-                q->q_flag =  0;
-
-                /* Adjust watchdog timer for command. */
-                /* if (sp->flags & SRB_WATCHDOG)
-                sp->timeout += 2; */
-
-                /* Place request back on top of device queue. */
-                /* sp->flags &= ~(SRB_SENT | SRB_TIMEOUT); */ 
-                sp->flags = 0;
-                qla1280_putq_t(q, sp);
-            }
-        }
-
-        /* If firmware needs to be loaded */
-        if (qla1280_isp_firmware(ha))
-        {
-            if (!(status = qla1280_chip_diag(ha)))
-                status = qla1280_setup_chip(ha); 
-        }
-
-        if (!status)
-        {
-            /* Setup adapter based on NVRAM parameters. */
-            qla1280_nvram_config(ha); 
-
-            if (!(status = qla1280_init_rings(ha)))
-            {
-                /* Issue SCSI reset. */
-                for (b = 0; b < ha->ports; b++)
-                {
-                    qla1280_bus_reset(ha, b);
-                }
-                do
-                {
-                    /* Issue marker command. */
-                    ha->flags.reset_marker = FALSE;
-                    for (b = 0; b < ha->ports; b++)
-                    {
-                        ha->bus_settings[b].reset_marker = FALSE;
-                        qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
-                    }
-                }while (ha->flags.reset_marker);
-
-                /* Enable host adapter target mode. */
-                for (b = 0; b < ha->ports; b++)
-                {
-                    if (!(status = qla1280_enable_tgt(ha, b)))
-                    {
-                        for (cnt = 0; cnt < MAX_LUNS; cnt++)
-                        {
-                            /* qla1280_enable_lun(ha, b, cnt); */
-                            qla1280_poll(ha);
-                        }
-                    }
-                    else
-                        break;
-                }
-
-                if (!status)
-                { 
-                    /* Enable ISP interrupts. */
-                    WRT_REG_WORD(&reg->ictrl, ISP_EN_INT + ISP_EN_RISC);
-                    ha->flags.abort_isp_active = FALSE;
-                    /* Restart queues that may have been stopped. */
-                    qla1280_restart_queues(ha);
-                }
-            }
-        }
-    }
-
-    if (status)
-    {
-        printk(KERN_WARNING
-                "qla1280: ISP error recovery failed, board disabled");
-        qla1280_reset_adapter(ha);
-        qla1280_abort_queues(ha);
-
-#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
-        qla1280_print("qla1280_abort_isp: **** FAILED ****\n\r");
-#endif
-    }
-#ifdef QL_DEBUG_LEVEL_3
-    else
-        LEAVE("qla1280_abort_isp");
+#if 0
+	struct device_reg *reg = ha->iobase;
 #endif
-    DRIVER_UNLOCK
+	srb_t *sp;
+	scsi_lu_t *q;
+	int status = 0;
+	int cnt;
+	int bus, target, lun;
+
+	ENTER("qla1280_abort_isp");
+
+	ha->flags.isp_abort_needed = FALSE;
+	if (!ha->flags.abort_isp_active && ha->flags.online) {
+		ha->flags.abort_isp_active = TRUE;
+
+		/* Disable ISP interrupts. */
+		qla1280_disable_intrs(ha);
+
+		/* Dequeue all commands in outstanding command list. */
+		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+			sp = ha->outstanding_cmds[cnt];
+			if (sp) {
+				ha->outstanding_cmds[cnt] = 0;
+
+				/* Generate LU queue on controller, target, LUN */
+				bus = SCSI_BUS_32(sp->cmd);
+				target = SCSI_TCN_32(sp->cmd);
+				lun = SCSI_LUN_32(sp->cmd);
+
+				q = LU_Q(ha, bus, target, lun);
+
+				/* Reset outstanding command count. */
+				q->q_outcnt = 0;
+				q->q_flag &= ~QLA1280_QBUSY;
+				q->q_flag = 0;
+
+				/* Adjust watchdog timer for command. */
+				/* if (sp->flags & SRB_WATCHDOG)
+				   sp->timeout += 2; */
+
+				/* Place request back on top of device queue. */
+				sp->flags = 0;
+				qla1280_putq_t(q, sp);
+			}
+		}
+
+		/* If firmware needs to be loaded */
+		if (qla1280_isp_firmware (ha)) {
+			if (!(status = qla1280_chip_diag(ha)))
+				status = qla1280_setup_chip(ha);
+		}
+
+		if (!status) {
+			/* Setup adapter based on NVRAM parameters. */
+			qla1280_nvram_config (ha);
+
+			if (!(status = qla1280_init_rings(ha))) {
+				/* Issue SCSI reset. */
+				for (bus = 0; bus < ha->ports; bus++) {
+					qla1280_bus_reset(ha, bus);
+				}
+				do {
+					/* Issue marker command. */
+					ha->flags.reset_marker = FALSE;
+					for (bus = 0; bus < ha->ports; bus++) {
+						ha->bus_settings[bus].
+							reset_marker = FALSE;
+						qla1280_marker(ha, bus, 0, 0,
+							       MK_SYNC_ALL);
+					}
+				} while (ha->flags.reset_marker);
+
+				/* Enable host adapter target mode. */
+				for (bus = 0; bus < ha->ports; bus++) {
+					if (!
+					    (status =
+					     qla1280_enable_tgt(ha, bus))) {
+						for (cnt = 0; cnt < MAX_LUNS;
+						     cnt++) {
+							/* qla1280_enable_lun(ha, bus, cnt); */
+							qla1280_poll(ha);
+						}
+					} else
+						break;
+				}
+
+				if (!status) {
+					/* Enable ISP interrupts. */
+					qla1280_enable_intrs(ha);
+					ha->flags.abort_isp_active = FALSE;
+					/* Restart queues that may have been stopped. */
+					qla1280_restart_queues(ha);
+				}
+			}
+		}
+	}
+
+	if (status) {
+		printk(KERN_WARNING
+		       "qla1280: ISP error recovery failed, board disabled");
+		qla1280_reset_adapter(ha);
+		qla1280_abort_queues(ha);
+
+		dprintk(2, "qla1280_abort_isp: **** FAILED ****\n");
+	}
 
-            return(status);
+	LEAVE("qla1280_abort_isp");
+	return status;
 }
 
 /*
@@ -6052,36 +5843,24 @@
  * Input:
  *      ha = adapter block pointer.
  */
-STATIC void
-qla1280_restart_queues(scsi_qla_host_t *ha)
+static void
+qla1280_restart_queues(struct scsi_qla_host *ha)
 {
-    scsi_lu_t *q;
-    uint32_t  b, t, l;
+	scsi_lu_t *q;
+	int bus, target, lun;
 
-#ifdef QL_DEBUG_LEVEL_3
-    ENTER("qla1280_restart_queues");
-#endif
+	ENTER("qla1280_restart_queues");
 
-    for (b = 0; b < ha->ports; b++)
-        for (t = 0; t < MAX_TARGETS; t++)
-            for (l = 0; l < MAX_LUNS; l++)
-            {
-                q = (scsi_lu_t *) LU_Q(ha, b, t, l);
-                if (q != NULL)
-                {
-                    /* Acquire LU queue specific lock */
-                    QLA1280_SCSILU_LOCK(q);
-
-                    if (q->q_first)
-                        qla1280_next(ha, q, b);
-                    else
-                        /* Release LU queue specific lock */
-                        QLA1280_SCSILU_UNLOCK(q);
-                }
-            }
-#ifdef QL_DEBUG_LEVEL_3
-            qla1280_print("qla1280_restart_queues: exiting normally\n");
-#endif
+	for (bus = 0; bus < ha->ports; bus++)
+		for (target = 0; target < MAX_TARGETS; target++)
+			for (lun = 0; lun < MAX_LUNS; lun++) {
+				q = LU_Q(ha, bus, target, lun);
+				if (q != NULL) {
+					if (q->q_first)
+						qla1280_next(ha, q, bus);
+				}
+			}
+	dprintk(3, "qla1280_restart_queues: exiting normally\n");
 }
 
 /*
@@ -6091,32 +5870,28 @@
  * Input:
  *      ha = adapter block pointer.
  */
-STATIC void qla1280_abort_queue_single(scsi_qla_host_t *ha,uint32_t b,uint32_t t,uint32_t l,uint32_t stat)
-{
-    scsi_lu_t *q;
-    srb_t     *sp, *sp_next; 
-
-    ENTER("qla1280_abort_queue_single");
-    q = (scsi_lu_t * )LU_Q(ha, b, t, l);
-    if (q != NULL)
-    {
-        /* Acquire LU queue specific lock */
-        QLA1280_SCSILU_LOCK(q);
-
-        sp = q->q_first;
-        q->q_first = q->q_last = NULL;
-
-        QLA1280_SCSILU_UNLOCK(q);
-
-        while (sp)
-        {
-            sp_next = sp->s_next;
-            CMD_RESULT(sp->cmd) = stat;
-            qla1280_done_q_put(sp, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
-            sp = sp_next;
-        }
-    }
-    LEAVE("qla1280_abort_queue_single");
+static void
+qla1280_abort_queue_single(struct scsi_qla_host *ha, int bus,
+			   int target, int lun, uint32_t stat)
+{
+	scsi_lu_t *q;
+	srb_t *sp, *sp_next;
+
+	ENTER("qla1280_abort_queue_single");
+	q = LU_Q(ha, bus, target, lun);
+	if (q != NULL) {
+		sp = q->q_first;
+		q->q_first = q->q_last = NULL;
+
+		while (sp) {
+			sp_next = sp->s_next;
+			CMD_RESULT(sp->cmd) = stat;
+			qla1280_done_q_put(sp, &ha->done_q_first,
+					   &ha->done_q_last);
+			sp = sp_next;
+		}
+	}
+	LEAVE("qla1280_abort_queue_single");
 }
 
 /*
@@ -6126,19 +5901,20 @@
  * Input:
  *      ha = adapter block pointer.
  */
-STATIC void
-qla1280_abort_queues(scsi_qla_host_t *ha)
+static void
+qla1280_abort_queues(struct scsi_qla_host *ha)
 {
-    uint32_t  b, t, l;
+	uint32_t bus, target, lun;
 
-    ENTER("qla1280_abort_queues");
+	ENTER("qla1280_abort_queues");
 
-    for (b = 0; b < ha->ports; b++)
-        for (t = 0; t < MAX_TARGETS; t++)
-            for (l = 0; l < MAX_LUNS; l++)
-                qla1280_abort_queue_single(ha,b,t,l,DID_RESET);
+	for (bus = 0; bus < ha->ports; bus++)
+		for (target = 0; target < MAX_TARGETS; target++)
+			for (lun = 0; lun < MAX_LUNS; lun++)
+				qla1280_abort_queue_single(ha, bus, target,
+							   lun, DID_RESET);
 
-            LEAVE("qla1280_abort_queues");
+	LEAVE("qla1280_abort_queues");
 }
 
 /*
@@ -6151,28 +5927,36 @@
  * Returns:
  *      register value.
  */
-STATIC uint16_t
-qla1280_debounce_register(volatile uint16_t *addr)
+static u16
+qla1280_debounce_register(volatile u16 * addr)
 {
-    volatile uint16_t ret;
-    volatile uint16_t ret2;
+	volatile u16 ret;
+	volatile u16 ret2;
 
-    do
-    {
-        ret = RD_REG_WORD(addr);
-        ret2 = RD_REG_WORD(addr);
-    }while (ret != ret2);
+	ret = RD_REG_WORD(addr);
+	ret2 = RD_REG_WORD(addr);
 
-    return(ret);
-}
+	if (ret == ret2)
+		return ret;
 
+	do {
+		cpu_relax();
+		ret = RD_REG_WORD(addr);
+		ret2 = RD_REG_WORD(addr);
+	} while (ret != ret2);
 
-/*
- * Declarations for load module
- */
-static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
+	return ret;
+}
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#ifdef MODULE
+Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
 #include "scsi_module.c"
+#endif
+#else				/* new kernel scsi initialization scheme */
+static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
+#include "scsi_module.c"
+#endif
 
 /************************************************************************
  * qla1280_check_for_dead_scsi_bus                                      *
@@ -6181,91 +5965,73 @@
  ************************************************************************/
 #define SET_SXP_BANK            0x0100
 #define SCSI_PHASE_INVALID      0x87FF
-int  qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp)
+static int
+qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus)
 {
-    uint16_t  config_reg, scsi_control;
-    device_reg_t    *reg = ha->iobase;
-    uint32_t  b;
-    Scsi_Cmnd       *cp;
-
-    /*
-     * If SCSI Bus is Dead because of bad termination,
-     * we will return a status of Selection timeout.
-     */
- 
-     cp = sp->cmd;
-     b = SCSI_BUS_32(cp);
-    if (ha->bus_settings[b].scsi_bus_dead)
-    {
-        WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
-        config_reg = RD_REG_WORD(&reg->cfg_1);
-        WRT_REG_WORD(&reg->cfg_1,SET_SXP_BANK);
-        scsi_control = RD_REG_WORD(&reg->scsiControlPins);
-        WRT_REG_WORD(&reg->cfg_1,config_reg);
-        WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
-
-        if (scsi_control == SCSI_PHASE_INVALID)
-        {
-            CMD_RESULT(cp) = DID_NO_CONNECT << 16;
-            CMD_HANDLE(cp) = (unsigned char *) 0;
-            /* ha->actthreads--; */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-            sti(); 
-            (*(cp)->scsi_done)(cp);
-            cli(); 
-#else
-            (*(cp)->scsi_done)(cp);
-#endif
-            return(TRUE);   /* bus is dead */
-        }
-        else
-        {
-            ha->bus_settings[b].scsi_bus_dead = FALSE;
-            ha->bus_settings[b].failed_reset_count= 0; 
-        }
-    }
-    return(FALSE);   /* bus is not dead */
-}
-
-STATIC uint8_t
-qla12160_set_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l, nvram160_t *nv)
-{
-    uint16_t        mb[MAILBOX_REGISTER_COUNT];
-
-    /* Set Target Parameters. */
-    mb[0] = MBC_SET_TARGET_PARAMETERS;
-    mb[1] = (uint16_t)(b ? t | BIT_7 :t);
-    mb[1] <<= 8;
-    mb[2] = nv->bus[b].target[t].parameter.c << 8;
-    mb[2] |= TP_AUTO_REQUEST_SENSE;
-    mb[2] &= ~TP_STOP_QUEUE;
-    mb[2] |=  (nv->bus[b].target[t].flags.enable_ppr << 5);
-    mb[3] = nv->bus[b].target[t].flags.sync_offset << 8;
-    mb[3] |= nv->bus[b].target[t].sync_period;
-
-    mb[6] = nv->bus[b].target[t].flags.ppr_options << 8;
-    mb[6] |= nv->bus[b].target[t].flags.ppr_bus_width;
-    return( qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]) ) ;
-}
-
-STATIC void
-qla12160_get_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l)
-{
-    uint16_t        mb[MAILBOX_REGISTER_COUNT];
-
-    mb[0] = MBC_GET_TARGET_PARAMETERS;
-    mb[1] = (uint16_t)(b ? t | BIT_7 :t);
-    mb[1] <<= 8;
-    qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]);
-    if( mb[3] != 0 )
-    printk(KERN_INFO "scsi(%d:%d:%d:%d): Synchronous tranfer at period %d, offset %d. \n",
-        (int)ha->host_no, b, t, l, (mb[3] &0xff), (mb[3] >> 8));
-
-    if ( (mb[2] & BIT_5) &&  ((mb[6] >> 8) & 0xff) >= 2 )
-            printk(KERN_INFO "scsi(%d:%d:%d:%d): Dual Transition enabled.\n",
-                          (int)ha->host_no, b, t, l);
+	uint16_t config_reg, scsi_control;
+	struct device_reg *reg = ha->iobase;
+#if 0
+	unsigned int bus;
+	Scsi_Cmnd *cp;
+
+	/*
+	 * If SCSI Bus is Dead because of bad termination,
+	 * we will return a status of Selection timeout.
+	 */
+
+	cp = sp->cmd;
+	bus = SCSI_BUS_32(cp);
+#endif
+	if (ha->bus_settings[bus].scsi_bus_dead) {
+		WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
+		config_reg = RD_REG_WORD(&reg->cfg_1);
+		WRT_REG_WORD(&reg->cfg_1, SET_SXP_BANK);
+		scsi_control = RD_REG_WORD(&reg->scsiControlPins);
+		WRT_REG_WORD(&reg->cfg_1, config_reg);
+		WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+
+		if (scsi_control == SCSI_PHASE_INVALID) {
+			ha->bus_settings[bus].scsi_bus_dead = TRUE;
+#if 0
+			CMD_RESULT(cp) = DID_NO_CONNECT << 16;
+			CMD_HANDLE(cp) = NULL;
+			/* ha->actthreads--; */
+
+			(*(cp)->scsi_done)(cp);
+#endif
+			return TRUE;	/* bus is dead */
+		} else {
+			ha->bus_settings[bus].scsi_bus_dead = FALSE;
+			ha->bus_settings[bus].failed_reset_count = 0;
+		}
+	}
+	return FALSE;		/* bus is not dead */
 }
 
+static void
+qla12160_get_target_parameters(struct scsi_qla_host *ha, uint32_t bus,
+			       uint32_t target, uint32_t lun)
+{
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+
+	mb[0] = MBC_GET_TARGET_PARAMETERS;
+	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
+	mb[1] <<= 8;
+	qla1280_mailbox_command(ha, BIT_6 | BIT_3 | BIT_2 | BIT_1 | BIT_0,
+				&mb[0]);
+	if (mb[3] != 0) {
+		printk(KERN_INFO
+		       "scsi(%ld:%d:%d:%d): Synchronous transfer at period "
+		       "%d, offset %d. \n", ha->host_no, bus, target, lun,
+		       (mb[3] & 0xff), (mb[3] >> 8));
+	}
+
+	if ((mb[2] & BIT_5) && ((mb[6] >> 8) & 0xff) >= 2) {
+		printk(KERN_INFO
+		       "scsi(%ld:%d:%d:%d): Dual Transition enabled.\n",
+		       ha->host_no, bus, target, lun);
+	}
+}
 
 #ifdef QL_DEBUG_ROUTINES
 /****************************************************************************/
@@ -6275,484 +6041,276 @@
 /*
  *  Get byte from I/O port
  */
-STATIC uint8_t
-qla1280_getbyte(uint8_t *port)
+static u8
+qla1280_getbyte (u8 * port)
 {
-    uint8_t ret;
+	u8 ret;
 
 #if MEMORY_MAPPED_IO
-    ret = *port;
+	ret = readb((unsigned long) port);
 #else
-    ret = inb((int)port);
+	ret = inb((unsigned long) port);
 #endif
 
-    if (ql_debug_print)
-    {
-        qla1280_print("qla1280_getbyte: address = ");
-        qla1280_output_number((uint32_t)port, 16);
-        qla1280_print(" data = 0x");
-        qla1280_output_number((uint32_t)ret, 16);
-        qla1280_print("\n\r");
-    }
+	if (ql_debug_print)
+		printk(KERN_DEBUG
+		       "qla1280_getbyte: address = 0x%p, data = 0x%x", port,
+		       ret);
 
-    return(ret);
+	return ret;
 }
 
 /*
  *  Get word from I/O port
  */
-STATIC uint16_t
-qla1280_getword(uint16_t *port)
+static u16
+qla1280_getword (u16 * port)
 {
-    uint16_t ret;
+	u16 ret;
 
 #if MEMORY_MAPPED_IO
-    ret = *port;
+	ret = readw(unsigned long) port;
 #else
-    ret = inw((int)port);
+	ret = inw((unsigned long) port);
 #endif
 
-    if (ql_debug_print)
-    {
-        qla1280_print("qla1280_getword: address = ");
-        qla1280_output_number((uint32_t)port, 16);
-        qla1280_print(" data = 0x");
-        qla1280_output_number((uint32_t)ret, 16);
-        qla1280_print("\n\r");
-    }
+	if (ql_debug_print)
+		printk(KERN_DEBUG
+		       "qla1280_getbyte: address = 0x%p, data = 0x%x", port,
+		       ret);
 
-    return(ret);
+	return ret;
 }
 
 /*
  *  Get double word from I/O port
  */
-STATIC uint32_t
-qla1280_getdword(uint32_t *port)
+static u32
+qla1280_getdword (u32 * port)
 {
-    uint32_t ret;
+	u32 ret;
 
 #if MEMORY_MAPPED_IO
-    ret = *port;
+	ret = readl((unsigned long) port);
 #else
-    ret = inl((int)port);
+	ret = inl((unsigned long) port);
 #endif
 
-    if (ql_debug_print)
-    {
-        qla1280_print("qla1280_getdword: address = ");
-        qla1280_output_number((uint32_t)port, 16);
-        qla1280_print(" data = 0x");
-        qla1280_output_number((uint32_t)ret, 16);
-        qla1280_print("\n\r");
-    }
+	if (ql_debug_print)
+		printk(KERN_DEBUG
+		       "qla1280_getbyte: address = 0x%p, data = 0x%x", port,
+		       ret);
 
-    return(ret);
+	return ret;
 }
 
 /*
  *  Send byte to I/O port
  */
-STATIC void
-qla1280_putbyte(uint8_t *port, uint8_t data)
+static void
+qla1280_putbyte(u8 * port, u8 data)
 {
 #if MEMORY_MAPPED_IO
-    *port = data;
+	writeb(data, (unsigned long) port);
 #else
-    outb(data, (int)port);
+	outb(data, (unsigned long) port);
 #endif
 
-    if (ql_debug_print)
-    {
-        qla1280_print("qla1280_putbyte: address = ");
-        qla1280_output_number((uint32_t)port, 16);
-        qla1280_print(" data = 0x");
-        qla1280_output_number((uint32_t)data, 16);
-        qla1280_print("\n\r");
-    }
+	if (ql_debug_print)
+		printk(KERN_DEBUG
+		       "qla1280_getbyte: address = 0x%p, data = 0x%x", port,
+		       data);
 }
 
 /*
  *  Send word to I/O port
  */
-STATIC void
-qla1280_putword(uint16_t *port, uint16_t data)
+static void
+qla1280_putword(u16 * port, u16 data)
 {
 #if MEMORY_MAPPED_IO
-    *port = data;
+	writew(data, (unsigned long) port);
 #else
-#ifdef _LINUX_IOPORTS
-    outw(data, (int)port);
-#else
-    outw((int)port, data);
-#endif
+	outw(data, (unsigned long) port);
 #endif
 
-    if (ql_debug_print)
-    {
-        qla1280_print("qla1280_putword: address = ");
-        qla1280_output_number((uint32_t)port, 16);
-        qla1280_print(" data = 0x");
-        qla1280_output_number((uint32_t)data, 16);
-        qla1280_print("\n\r");
-    }
+	if (ql_debug_print)
+		printk(KERN_DEBUG
+		       "qla1280_getbyte: address = 0x%p, data = 0x%x", port,
+		       data);
 }
 
 /*
  *  Send double word to I/O port
  */
-STATIC void
-qla1280_putdword(uint32_t *port, uint32_t data)
+static void
+qla1280_putdword(u32 * port, u32 data)
 {
 #if MEMORY_MAPPED_IO
-    *port = data;
-#else
-#ifdef _LINUX_IOPORTS
-    outl(data,(int)port);
+	writel(data, (unsigned long) port);
 #else
-    outl((int)port, data);
-#endif
+	outl(data, (unsigned long) port);
 #endif
 
-    if (ql_debug_print)
-    {
-        qla1280_print("qla1280_putdword: address = ");
-        qla1280_output_number((uint32_t)port, 16);
-        qla1280_print(" data = 0x");
-        qla1280_output_number((uint32_t)data, 16);
-        qla1280_print("\n\r");
-    }
+	if (ql_debug_print)
+		printk(KERN_DEBUG
+		       "qla1280_getbyte: address = 0x%p, data = 0x%x", port,
+		       data);
 }
 
 /*
  * Dummy function to prevent warnings for
  * declared and unused debug functions
  */
-void
+static void
 qla1280_debug(void)
 {
-    qla1280_getbyte(0);
-    qla1280_getword(0);
-    qla1280_getdword(0);
-    qla1280_putbyte(0, 0);
-    qla1280_putword(0, 0);
-    qla1280_putdword(0, 0);
+	qla1280_getbyte(0);
+	qla1280_getword(0);
+	qla1280_getdword(0);
+	qla1280_putbyte(0, 0);
+	qla1280_putword(0, 0);
+	qla1280_putdword(0, 0);
+}
+
+static void
+__qla1280_dump_buffer(char *b, int size)
+{
+	int cnt;
+	u8 c;
+
+	if (ql_debug_print) {
+		printk(KERN_DEBUG
+		       " 0   1   2   3   4   5   6   7   8   9   Ah  "
+		       "Bh  Ch  Dh  Eh  Fh\n");
+		printk(KERN_DEBUG
+		       "---------------------------------------------"
+		       "------------------\n");
+
+		for (cnt = 0; cnt < size;) {
+			c = *b++;
+			if (c < 16)
+				printk(' ');
+			printk("0x%x", c);
+			cnt++;
+			if (!(cnt % 16))
+				printk("\n");
+			else if (c < 10)
+				printk("  ");
+			else
+				printk(' ');
+		}
+		if (cnt % 16)
+			printk("\n");
+	}
 }
 
-/*
- *  Out character to COM2 port.
- *      PORT must be at standard address for COM2 = 0x2F8,
- *      or COM1 = 0x3F8
- */
-#define OUTB(addr,data)   outb((data),(addr))
-
-STATIC void
-qla1280_putc(uint8_t c)
-{
-#ifdef QL_DEBUG_CONSOLE
-    printk("%c", c);
-#else
-    int     com_addr              = 0x2f8;
-    int     hardware_flow_control = 1;
-    int     software_flow_control = 0;
-    uint8_t data;
-
-    /* Wait for transmitter holding and shift registers for empty. */
-    do
-    {
-        data = inb(com_addr+5);
-    }while (!(data & BIT_6));
-
-    /*
-    * Set BAUD rate for COM2 to 19200 (0x6)
-    */
-
-    /* Select rate divisor. */
-    OUTB(com_addr+3, 0x83); 
-
-    /* BAUD rate divisor LSB. */
-    OUTB(com_addr, 0xc);                    /* 0xC = 9600 baud */
-
-    /* BAUD rate divisor MSB. */
-    OUTB(com_addr+1, 0);
-
-    /* Set No parity, 8 bits, 1 stop bit and
-    select interrupt enable register. */
-    OUTB(com_addr+3, 3);
-
-    /* Disable interrupts. */
-    OUTB(com_addr+1, 0);
-
-    /* Set data terminal ready and request to send */
-    OUTB(com_addr+4,3);
-
-    if (hardware_flow_control)
-    {
-        /* Wait for clear-to-send and data-set-ready */
-        do
-        {
-            data = inb(com_addr+6) & (BIT_5 + BIT_4);
-        }while (data != (BIT_5 + BIT_4));
-    }
-    else if (software_flow_control)
-    {
-        /* Test for data ready. */
-        data = inb(com_addr+5);
-        if (data & BIT_0)
-        {
-            /* If XOFF */
-            data = inb(com_addr);
-            if (data == '\023')
-            {
-                /* Wait for XON */
-                do
-                {
-                    /* Wait for char */
-                    do
-                    {
-                        data = inb(com_addr+5);
-                    }while (!(data & BIT_0));
-                    data = inb(com_addr);
-                }while (data != '\021');
-            }
-        }
-    }
-
-    /* Output character. */
-    OUTB(com_addr, c);
-#endif
-}
-
-/*
- *  Out NULL terminated string to COM port.
- */
-STATIC void
-qla1280_print(caddr_t s)
-{
-    if (ql_debug_print)
-    {
-#ifdef QL_DEBUG_CONSOLE
-        printk("%s",s);
-#else
-        /* Output string. */
-        while (*s)
-            qla1280_putc(*s++);
-#endif
-    }
-}
-
-/*
- *  Output long number to COM port.
- */
-STATIC void
-qla1280_output_number(uint32_t n, uint8_t base)
-{
-    int8_t str[12];
-    int8_t *s     = &str[11];
-    int8_t output = 0;
-    int8_t hex    = FALSE;
-
-    if (ql_debug_print)
-    {
-        if (base == 10 || base == 16)
-        {
-            if (base == 16 && n > 9)
-                hex = TRUE;
-
-            *s = 0;
-            do
-            {
-                s--;
-                *s = n % base;
-                if (*s > 9)
-                    *s += 55;
-                else
-                    *s += '0';
-                n /= base;
-            }while (n);
-
-            for (; *s; s++)
-            {
-                if (*s != '0')
-                    output = 1;
-                if (output)
-                    qla1280_putc(*s);
-            }
-            if (!output)
-                qla1280_putc(*--s);
-
-            if (hex)
-                qla1280_putc('h');
-        }
-    }
-}
-
-STATIC void
-qla1280_dump_buffer(caddr_t b, uint32_t size)
-{
-    uint32_t cnt;
-    uint8_t c;
-
-    if (ql_debug_print)
-    {
-        qla1280_print(
-                " 0   1   2   3   4   5   6   7   8   9   Ah  Bh  Ch  Dh  Eh  Fh\n\r");
-        qla1280_print(
-                "---------------------------------------------------------------\n\r");
-
-        for (cnt = 0; cnt < size; )
-        {
-            c = *b++;
-            if (c < 16)
-                qla1280_putc(' ');
-            qla1280_output_number((uint32_t)c, 16);
-            cnt++;
-            if (!(cnt % 16))
-                qla1280_print("\n\r");
-            else if (c < 10)
-                qla1280_print("  ");
-            else
-                qla1280_putc(' ');
-        }
-        if (cnt % 16)
-            qla1280_print("\n\r");
-    }
-}
 /**************************************************************************
  *   ql1280_print_scsi_cmd
  *
  **************************************************************************/
-void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd)
+static void
+qla1280_print_scsi_cmd(Scsi_Cmnd * cmd)
 {
-    scsi_qla_host_t *ha;
-    struct Scsi_Host  *host = cmd->host;
-    srb_t           *sp;
-   /* struct scatterlist *sg; */
-
-    int i;
-    ha = (scsi_qla_host_t *) host->hostdata;
-
-    ql_debug_print = 1;
-    sp = (srb_t *) CMD_SP(cmd);
-    sprintf(debug_buff,"SCSI Command @= 0x%p, Handle=0x%p\n\r", cmd, CMD_HANDLE(cmd));
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"  chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n\r",
-            cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
-    qla1280_print(debug_buff);
-    qla1280_print(" CDB = ");
-    for (i = 0; i < cmd->cmd_len; i++)
-    {
-        sprintf(debug_buff,"0x%02x ", cmd->cmnd[i]);
-        qla1280_print(debug_buff);
-    }
-    sprintf(debug_buff,"  seg_cnt =%d\n\r",cmd->use_sg);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"  request buffer=0x%p, request buffer len=0x%x\n\r",cmd->request_buffer,cmd->request_bufflen);
-    qla1280_print(debug_buff);
-    /* if( cmd->use_sg )
-    {
-       sg = (struct scatterlist *) cmd->request_buffer;
-       qla1280_print("  SG buffer: \n\r");
-       qla1280_dump_buffer((caddr_t)sg, (cmd->use_sg*sizeof(struct scatterlist)) );
-    } */
-    sprintf(debug_buff,"  tag=%d, flags=0x%x, transfersize=0x%x \n\r", 
-            cmd->tag, cmd->flags,cmd->transfersize );
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"  Pid=%d, SP=0x%p\n\r", (int)cmd->pid, CMD_SP(cmd));
-    qla1280_print(debug_buff);
-    sprintf(debug_buff,"  r_start=0x%lx, u_start=0x%lx\n\r",sp->r_start,sp->u_start);
-    qla1280_print(debug_buff);
-    sprintf(debug_buff," underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n\r", cmd->underflow, sp->dir,cmd->request.cmd);    
-    qla1280_print(debug_buff);
+	struct scsi_qla_host *ha;
+	struct Scsi_Host *host = cmd->host;
+	srb_t *sp;
+	/* struct scatterlist *sg; */
+
+	int i;
+	ha = (struct scsi_qla_host *)host->hostdata;
+
+	sp = (srb_t *)CMD_SP(cmd);
+	printk("SCSI Command @= 0x%p, Handle=0x%p\n", cmd, CMD_HANDLE(cmd));
+	printk("  chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
+	       cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
+	printk(" CDB = ");
+	for (i = 0; i < cmd->cmd_len; i++) {
+		printk("0x%02x ", cmd->cmnd[i]);
+	}
+	printk("  seg_cnt =%d\n", cmd->use_sg);
+	printk("  request buffer=0x%p, request buffer len=0x%x\n",
+	       cmd->request_buffer, cmd->request_bufflen);
+	/* if (cmd->use_sg)
+	   {
+	   sg = (struct scatterlist *) cmd->request_buffer;
+	   printk("  SG buffer: \n");
+	   qla1280_dump_buffer(1, (char *)sg, (cmd->use_sg*sizeof(struct scatterlist)));
+	   } */
+	printk("  tag=%d, flags=0x%x, transfersize=0x%x \n",
+	       cmd->tag, cmd->flags, cmd->transfersize);
+	printk("  Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd));
+	printk(" underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n",
+	       cmd->underflow, sp->dir, cmd->request.cmd);
 }
+
 /**************************************************************************
  *   ql1280_dump_device
  *
  **************************************************************************/
 void
-ql1280_dump_device(scsi_qla_host_t *ha)
+ql1280_dump_device(struct scsi_qla_host *ha)
 {
 
-    Scsi_Cmnd       *cp;
-    srb_t           *sp;
-    int i;
-    qla1280_print("Outstanding Commands on controller:\n\r");   
-    for ( i=0; i < MAX_OUTSTANDING_COMMANDS; i++ )
-    {
-        if( (sp = ha->outstanding_cmds[i]) == NULL )
-            continue;
-        if( (cp = sp->cmd) == NULL )
-            continue;
-        qla1280_print_scsi_cmd(cp);
-    }
-
-}
-#endif
-
-#ifdef  QLA1280_UNUSED 
-/**************************************************************************
- *   ql1280_dump_regs
- *
- **************************************************************************/
-static void qla1280_dump_regs(struct Scsi_Host *host)
-{
-    printk("Mailbox registers:\n");
-    printk("qla1280 : mbox 0 0x%04x \n", inw(host->io_port + 0x70));
-    printk("qla1280 : mbox 1 0x%04x \n", inw(host->io_port + 0x72));
-    printk("qla1280 : mbox 2 0x%04x \n", inw(host->io_port + 0x74));
-    printk("qla1280 : mbox 3 0x%04x \n", inw(host->io_port + 0x76));
-    printk("qla1280 : mbox 4 0x%04x \n", inw(host->io_port + 0x78));
-    printk("qla1280 : mbox 5 0x%04x \n", inw(host->io_port + 0x7a));
+	Scsi_Cmnd *cp;
+	srb_t *sp;
+	int i;
+	if (ql_debug_print) {
+		printk(KERN_DEBUG "Outstanding Commands on controller:\n");
+
+		for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) {
+			if ((sp = ha->outstanding_cmds[i]) == NULL)
+				continue;
+			if ((cp = sp->cmd) == NULL)
+				continue;
+			qla1280_print_scsi_cmd(1, cp);
+		}
+	}
 }
 #endif
 
-
-
-#if  STOP_ON_ERROR 
+#if STOP_ON_ERROR
 /**************************************************************************
  *   ql1280_panic
  *
  **************************************************************************/
-static void qla1280_panic(char *cp, struct Scsi_Host *host)
+static void
+qla1280_panic(char *cp, struct Scsi_Host *host)
 {
-    scsi_qla_host_t *ha;
-    long  *fp;
+	struct scsi_qla_host *ha;
+	long *fp;
 
-    ha = (scsi_qla_host_t *) host->hostdata;
-    printk("qla1280 - PANIC:  %s\n",cp);
-    printk("Current time=0x%lx\n", jiffies);
-    printk("Number of pending commands =0x%lx\n", ha->actthreads);
-    printk("Number of SCSI queued commands =0x%lx\n", ha->qthreads);
-    printk("Number of free entries = (%d)\n",ha->req_q_cnt);
-    printk("Request Queue @ 0x%lx, Response Queue @ 0x%lx\n",
-                        ha->request_dma,
-                        ha->response_dma);
-    printk("Request In Ptr %d\n", ha->req_ring_index );
-    fp = (long *) &ha->flags;
-    printk("HA flags =0x%lx\n", *fp);
-    DEBUG2(ql_debug_print = 1;)
-    /* DEBUG2(ql1280_dump_device((scsi_qla_host_t *) host->hostdata)); */
-#ifdef  QLA1280_UNUSED 
-    qla1280_dump_regs(host);
-#endif
-    sti();  
-    panic("Ooops");  
-    /* cli(); 
-    for(;;)
-    { 
-        barrier();
-    sti();  
-    }
-    */
-}
+	ha = (struct scsi_qla_host *)host->hostdata;
+	printk(KERN_ERR "qla1280 - PANIC:  %s\n", cp);
+	printk(KERN_ERR "Current time=0x%lx\n", jiffies);
+	printk(KERN_ERR "Number of pending commands =0x%lx\n", ha->actthreads);
+	printk(KERN_ERR "Number of SCSI queued commands =0x%lx\n",
+	       ha->qthreads);
+	printk(KERN_ERR "Number of free entries = (%d)\n", ha->req_q_cnt);
+	printk(KERN_ERR "Request Queue @ 0x%lx, Response Queue @ 0x%lx\n",
+	       ha->request_dma, ha->response_dma);
+	printk(KERN_ERR "Request In Ptr %d\n", ha->req_ring_index);
+	fp = (long *) &ha->flags;
+	printk(KERN_ERR "HA flags =0x%lx\n", *fp);
+	if (ql_debug_level >= 2) {
+		ql_debug_print = 1;
+#if 0
+		ql1280_dump_device((struct scsi_qla_host *)host->hostdata);
 #endif
-
-#ifdef  QLA1280_UNUSED 
-static void qla1280_set_flags(char * s)
-{
+	}
+	sti();
+	panic("Ooops");
+	/* cli();
+	   for(;;)
+	   {
+	   barrier();
+	   sti();
+	   }
+	*/
 }
 #endif
 
+#ifdef MODULE
 /**************************************************************************
  *   qla1280_setup
  *
@@ -6763,56 +6321,36 @@
 void
 qla1280_setup(char *s, int *dummy)
 {
-    char *end, *str, *cp;
+	char *end, *str, *cp;
 
-#ifdef  QLA1280_UNUSED 
-    static struct
-    {
-        const char *name;
-        int      siz;
-        void  (*func)();
-        int   arg;
-    } options[] =
-    {
-        { "dump_regs", 9,  &qla1280_dump_regs, 0 
-        },
-        { "verbose", 7, &qla1280_set_flags, 0x1 
-        },
-        { "",    0, NULL, 0 
-        }
-    };
-#endif
-
-    printk("scsi: Processing Option str = %s\n", s);
-    end = strchr(s, '\0');
-    /* locate command */
-    str = s;
-    for( cp = s; *cp && cp != end; cp++ ) 
-    {
-       cp = qla1280_get_token(cp, str);
-       printk("scsi: token str = %s\n", str);
-       /* if found execute routine */
-
-    }
-    
-}
-
-static char	*qla1280_get_token(char *cmdline, char *str )
-{
-    register	char 	*cp = cmdline;
-
-        /* skip preceeding spaces */
-        while(strchr(cp,' '))
-            ++cp;
-        /* symbol starts here */
-        str = cp;
-        /* skip char if not a space or : */
-        while (*cp && !( strchr(cp,' ') || strchr(cp,':'))  )
-            cp++;
-        *cp = '\0';
-        return( cp );
+	printk(KERN_INFO "scsi: Processing Option str = %s\n", s);
+	end = strchr (s, '\0');
+	/* locate command */
+	str = s;
+	for (cp = s; *cp && cp != end; cp++) {
+		cp = qla1280_get_token(cp, str);
+		printk(KERN_INFO "scsi: token str = %s\n", str);
+		/* if found execute routine */
+	}
 }
-MODULE_LICENSE("GPL");
+
+static char *
+qla1280_get_token(char *cmdline, char *str)
+{
+	register char *cp = cmdline;
+
+	/* skip preceeding spaces */
+	while (strchr (cp, ' '))
+		++cp;
+	/* symbol starts here */
+	str = cp;
+	/* skip char if not a space or : */
+	while (*cp && !(strchr (cp, ' ') || strchr (cp, ':')))
+		cp++;
+	*cp = '\0';
+	return cp;
+}
+#endif
 
 /*
  * Overrides for Emacs so that we almost follow Linus's tabbing style.
@@ -6821,15 +6359,7 @@
  * of the file.
  * ---------------------------------------------------------------------------
  * Local variables:
- * c-indent-level: 2
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -2
- * c-argdecl-indent: 2
- * c-label-offset: -2
- * c-continued-statement-offset: 2
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
+ * c-basic-offset: 8
  * tab-width: 8
  * End:
  */
-
diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
--- a/drivers/scsi/qla1280.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/scsi/qla1280.h	Sun Apr 14 12:16:58 2002
@@ -1,291 +1,74 @@
-/*************************************************************************
- *                  QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.x).
- *
- * COPYRIGHT (C) 1996-2000 QLOGIC CORPORATION    
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Qlogic's Linux Software License.
- *
- * This program is WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistribution's or source code must retain the above copyright
- *    notice, this list of conditions, and the following disclaimer,
- *    without modification, immediately at the beginning of the file.
- * 2. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- *****************************************************************************/
- 
-/*************************************************************************************
-			QLOGIC CORPORATION SOFTWARE
-           "GNU" GENERAL PUBLIC LICENSE
-    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
-                 AND MODIFICATION
-
-This GNU General Public License ("License") applies solely to QLogic Linux 
-Software ("Software") and may be distributed under the terms of this License.  
- 
-1. You may copy and distribute verbatim copies of the Software's source code as 
-you receive it, in any medium, provided that you conspicuously and appropriately 
-publish on each copy an appropriate copyright notice and disclaimer of warranty;
-keep intact all the notices that refer to this License and to the absence of any
-warranty; and give any other recipients of the Software a copy of this License along
-with the Software. 
-
-You may charge a fee for the physical act of transferring a copy, and you may at your
-option offer warranty protection in exchange for a fee.
- 
-2. You may modify your copy or copies of the Software or any portion of it, thus forming
-a work based on the Software, and copy and distribute such modifications or work under
-the terms of Section 1 above, provided that you also meet all of these conditions:
- 
-* a) You must cause the modified files to carry prominent notices stating that you
-changed the files and the date of any change. 
-
-* b) You must cause any work that you distribute or publish that in whole or in part
-contains or is derived from the Software or any part thereof, to be licensed as a
-whole at no charge to all third parties under the terms of this License. 
-
-* c) If the modified Software normally reads commands interactively when run, you
-must cause it, when started running for such interactive use in the most ordinary way,
-to print or display an announcement including an appropriate copyright notice and a 
-notice that there is no warranty (or else, saying that you provide a warranty) and that
-users may redistribute the Software under these conditions, and telling the user how to
-view a copy of this License. (Exception:if the Software itself is interactive but does 
-not normally print such an announcement, your work based on the Software is not required
-to print an announcement.) 
-
-These requirements apply to the modified work as a whole. If identifiable sections of
-that work are not derived from the Software, and can be reasonably considered independent
-and separate works in themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you distribute the same
-sections as part of a whole which is a work based on the Software, the distribution of the
-whole must be on the terms of this License, whose permissions for other licensees extend
-to the entire whole, and thus to each and every part regardless of who wrote it. 
-
-3. You may copy and distribute the Software (or a work based on it, under Section 2) in 
-object code or executable form under the terms of Sections 1 and 2 above provided that
-you also do one of the following: 
-
-* a) Accompany it with the complete corresponding machine-readable source code, which must
-be distributed under the terms of Sections 1 and 2 above on a medium customarily used for
-software interchange; or, 
-
-* b) Accompany it with a written offer, valid for at least three years, to give any third
-party, for a charge no more than your cost of physically performing source distribution,
-a complete machine-readable copy of the corresponding source code, to be distributed under
-the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
-or,
-
-* c) Accompany it with the information you received as to the offer to distribute 
-corresponding source code. (This alternative is allowed only for noncommercial distribution
-and only if you received the Software in object code or executable form with such an offer,
-in accord with Subsection b above.) 
-
-The source code for a work means the preferred form of the work for making modifications
-to it. For an executable work, complete source code means all the source code for all 
-modules it contains, plus any associated interface definition files, plus the scripts used
-to control compilation and installation of the executable.     
-
-If distribution of executable or object code is made by offering access to copy from a 
-designated place, then offering equivalent access to copy the source code from the same
-place counts as distribution of the source code, even though third parties are not 
-compelled to copy the source along with the object code. 
-
-4. You may not copy, modify, sublicense, or distribute the Software except as expressly 
-provided under this License. Any attempt otherwise to copy, modify, sublicense or 
-distribute the Software is void, and will automatically terminate your rights under this
-License. However, parties who have received copies, or rights, from you under this License
-will not have their licenses terminated so long as such parties remain in full compliance. 
-
-5. This license grants you world wide, royalty free non-exclusive rights to modify or 
-distribute the Software or its derivative works. These actions are prohibited by law 
-if you do not accept this License. Therefore, by modifying or distributing the Software
-(or any work based on the Software), you indicate your acceptance of this License to do
-so, and all its terms and conditions for copying, distributing or modifying the Software
-or works based on it.
- 
-6. Each time you redistribute the Software (or any work based on the Software), the 
-recipient automatically receives a license from the original licensor to copy, distribute
-or modify the Software subject to these terms and conditions. You may not impose any 
-further restrictions on the recipients' exercise of the rights granted herein. You are
-not responsible for enforcing compliance by third parties to this License.
- 
-7. If, as a consequence of a court judgment or allegation of patent infringement or for
-any other reason (not limited to patent issues), conditions are imposed on you 
-(whether by court order, agreement or otherwise) that contradict the conditions of this
-License, they do not excuse you from the conditions of this License. If you cannot 
-distribute so as to satisfy simultaneously your obligations under this License 
-and any other pertinent obligations, then as a consequence you may not distribute the
-Software at all.    
-
-If any portion of this section is held invalid or unenforceable under any particular 
-circumstance, the balance of the section is intended to apply and the section as a whole
-is intended to apply in other circumstances. 
-NO WARRANTY
-
-11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO 
-WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
-OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, 
-EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
-ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. 
-SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
-NECESSARY SERVICING, REPAIR OR CORRECTION.
- 
-12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
-REDISTRIBUTE THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
-DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
-DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING 
-BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 
-LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO 
-OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 
-BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
-END OF TERMS AND CONDITIONS 
-
-*************************************************************************************/ 
-
- 
-#ifndef _IO_HBA_QLA1280_H           /* wrapper symbol for kernel use */
-#define _IO_HBA_QLA1280_H           /* subject to change without notice */
+/******************************************************************************
+*                  QLOGIC LINUX SOFTWARE
+*
+* QLogic ISP1280 (Ultra2) /12160 (Ultra3) SCSI driver
+* Copyright (C) 2000 Qlogic Corporation
+* (www.qlogic.com)
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2, or (at your option) any
+* later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+******************************************************************************/
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include <linux/version.h>
+#ifndef	_IO_HBA_QLA1280_H	/* wrapper symbol for kernel use */
+#define	_IO_HBA_QLA1280_H	/* subject to change without notice */
 
+#ifndef HOSTS_C			/* included in hosts.c */
 /*
  * Enable define statement to ignore Data Underrun Errors,
  * remove define statement to enable detection.
  */
 /* #define  DATA_UNDERRUN_ERROR_DISABLE */
 
-/*
- * Driver debug definitions.
- */
-/* #define QL_DEBUG_LEVEL_1 */       /* Output register accesses to COM2. */
-/* #define QL_DEBUG_LEVEL_2 */           /* Output error msgs to COM2. */
-/* #define QL_DEBUG_LEVEL_3 */          /* Output function trace msgs to COM2. */
-/* #define QL_DEBUG_LEVEL_4 */       /* Output NVRAM trace msgs to COM2. */
-/* #define QL_DEBUG_LEVEL_5 */         /* Output ring trace msgs to COM2. */
-/* #define QL_DEBUG_LEVEL_6 */      /* Output WATCHDOG timer trace to COM2. */
-/* #define QL_DEBUG_LEVEL_7 */      /* Output RISC load trace msgs to COM2. */
-
-#define QL_DEBUG_CONSOLE              /* Output to console instead of COM2. */
-
 #ifndef TRUE
-#  define TRUE 1
+#define TRUE 1
 #endif
 #ifndef FALSE
-#  define FALSE 0
-#endif
-
-
-#ifndef KERNEL_VERSION
-#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
-#endif
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
-#  if defined(__sparc_v9__) || defined(__powerpc__)
-#    error "PPC and Sparc platforms are only support under 2.1.92 and above"
-#  endif
-#endif
-
-
-/* 
- * Locking
- */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
-#  include <linux/spinlock.h>
-#  include <linux/smp.h>
-#  define cpuid smp_processor_id()
-#  if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-#    define DRIVER_LOCK_INIT \
-       spin_lock_init(&ha->spin_lock);
-#    define DRIVER_LOCK \
-       if(!ha->cpu_lock_count[cpuid]) { \
-         spin_lock_irqsave(&ha->spin_lock, cpu_flags); \
-         ha->cpu_lock_count[cpuid]++; \
-       } else { \
-         ha->cpu_lock_count[cpuid]++; \
-       }
-#    define DRIVER_UNLOCK \
-       if(--ha->cpu_lock_count[cpuid] == 0) \
-         spin_unlock_irqrestore(&ha->spin_lock, cpu_flags);
-#  else
-#    define DRIVER_LOCK_INIT
-#    define DRIVER_LOCK
-#    define DRIVER_UNLOCK
-#  endif 
-#else
-#  define cpuid 0
-#  define DRIVER_LOCK_INIT
-#  define DRIVER_LOCK \
-       save_flags(cpu_flags); \
-       cli();
-#  define DRIVER_UNLOCK \
-       restore_flags(cpu_flags);
-#  define le32_to_cpu(x) (x)
-#  define cpu_to_le32(x) (x)
+#define FALSE 0
 #endif
 
 /*
  * Data bit definitions.
  */
-#define BIT_0   0x1
-#define BIT_1   0x2
-#define BIT_2   0x4
-#define BIT_3   0x8
-#define BIT_4   0x10
-#define BIT_5   0x20
-#define BIT_6   0x40
-#define BIT_7   0x80
-#define BIT_8   0x100
-#define BIT_9   0x200
-#define BIT_10  0x400
-#define BIT_11  0x800
-#define BIT_12  0x1000
-#define BIT_13  0x2000
-#define BIT_14  0x4000
-#define BIT_15  0x8000
-#define BIT_16  0x10000
-#define BIT_17  0x20000
-#define BIT_18  0x40000
-#define BIT_19  0x80000
-#define BIT_20  0x100000
-#define BIT_21  0x200000
-#define BIT_22  0x400000
-#define BIT_23  0x800000
-#define BIT_24  0x1000000
-#define BIT_25  0x2000000
-#define BIT_26  0x4000000
-#define BIT_27  0x8000000
-#define BIT_28  0x10000000
-#define BIT_29  0x20000000
-#define BIT_30  0x40000000
-#define BIT_31  0x80000000
-
-/*
- * Common size type definitions
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-typedef unsigned char  uint8_t; 
-typedef unsigned short uint16_t; 
-typedef unsigned long  uint32_t; 
-typedef char  int8_t; 
-typedef short int16_t; 
-typedef long  int32_t; 
-#endif
+#define BIT_0	0x1
+#define BIT_1	0x2
+#define BIT_2	0x4
+#define BIT_3	0x8
+#define BIT_4	0x10
+#define BIT_5	0x20
+#define BIT_6	0x40
+#define BIT_7	0x80
+#define BIT_8	0x100
+#define BIT_9	0x200
+#define BIT_10	0x400
+#define BIT_11	0x800
+#define BIT_12	0x1000
+#define BIT_13	0x2000
+#define BIT_14	0x4000
+#define BIT_15	0x8000
+#define BIT_16	0x10000
+#define BIT_17	0x20000
+#define BIT_18	0x40000
+#define BIT_19	0x80000
+#define BIT_20	0x100000
+#define BIT_21	0x200000
+#define BIT_22	0x400000
+#define BIT_23	0x800000
+#define BIT_24	0x1000000
+#define BIT_25	0x2000000
+#define BIT_26	0x4000000
+#define BIT_27	0x8000000
+#define BIT_28	0x10000000
+#define BIT_29	0x20000000
+#define BIT_30	0x40000000
+#define BIT_31	0x80000000
 
 /*
  *  Local Macro Definitions.
@@ -294,1154 +77,1068 @@
     defined(QL_DEBUG_LEVEL_3) || defined(QL_DEBUG_LEVEL_4) || \
     defined(QL_DEBUG_LEVEL_5) || defined(QL_DEBUG_LEVEL_6) || \
     defined(QL_DEBUG_LEVEL_7)
-    #define QL_DEBUG_ROUTINES
+#define QL_DEBUG_ROUTINES
 #endif
 
 /*
  * I/O port macros
 */
-#define LINUX_IOPORTS                     /* Linux in/out routines are define*/
-                                          /* differently from other OSs      */
-/* #define MEMORY_MAPPED_IO */            /* Enable memory mapped I/O */
-#undef MEMORY_MAPPED_IO            /* Disable memory mapped I/O */
+/* #define MEMORY_MAPPED_IO *//* Enable memory mapped I/O */
+#undef MEMORY_MAPPED_IO		/* Disable memory mapped I/O */
 
 #ifdef QL_DEBUG_LEVEL_1
-#define RD_REG_BYTE(addr)         qla1280_getbyte((uint8_t *)addr)
-#define RD_REG_WORD(addr)         qla1280_getword((uint16_t *)addr)
-#define RD_REG_DWORD(addr)        qla1280_getdword((uint32_t *)addr)
-#define WRT_REG_BYTE(addr, data)  qla1280_putbyte((uint8_t *)addr, data)
-#define WRT_REG_WORD(addr, data)  qla1280_putword((uint16_t *)addr, data)
-#define WRT_REG_DWORD(addr, data) qla1280_putdword((uint32_t *)addr, data)
-#else  /* QL_DEBUG_LEVEL_1 */
+#define RD_REG_BYTE(addr)		qla1280_getbyte((u8 *)addr)
+#define RD_REG_WORD(addr)		qla1280_getword((u16 *)addr)
+#define RD_REG_DWORD(addr)		qla1280_getdword((u32 *)addr)
+#define WRT_REG_BYTE(addr, data)	qla1280_putbyte((u8 *)addr, data)
+#define WRT_REG_WORD(addr, data)	qla1280_putword((u16 *)addr, data)
+#define WRT_REG_DWORD(addr, data)	qla1280_putdword((u32 *)addr, data)
+#else				/* QL_DEBUG_LEVEL_1 */
+
 #ifdef MEMORY_MAPPED_IO
-       #define RD_REG_BYTE(addr)         readb((unsigned long) (addr)
-       #define RD_REG_WORD(addr)         readw((unsigned long) (addr)
-       #define RD_REG_DWORD(addr)        readl((unsigned long) (addr)
-       #define WRT_REG_BYTE(addr, data)  writeb((data), (unsigned long) (addr))
-       #define WRT_REG_WORD(addr, data)  writew((data), (unsigned long) (addr))
-       #define WRT_REG_DWORD(addr, data) writel((data), (unsigned long) (addr))
-#else   /* MEMORY_MAPPED_IO */
-#define RD_REG_BYTE(addr)         (inb((unsigned long)addr))
-#define RD_REG_WORD(addr)         (inw((unsigned long)addr))
-#define RD_REG_DWORD(addr)        (inl((unsigned long)addr))
-#ifdef LINUX_IOPORTS
+#define RD_REG_BYTE(addr)		readb(addr)
+#define RD_REG_WORD(addr)		readw(addr)
+#define RD_REG_DWORD(addr)		readl(addr)
+#define WRT_REG_BYTE(addr, data)	writeb(data, addr)
+#define WRT_REG_WORD(addr, data)	writew(data, addr)
+#define WRT_REG_DWORD(addr, data)	writel(data, addr)
+#else				/* MEMORY_MAPPED_IO */
+#define RD_REG_BYTE(addr)		inb((unsigned long)addr)
+#define RD_REG_WORD(addr)		inw((unsigned long)addr)
+#define RD_REG_DWORD(addr)		inl((unsigned long)addr)
 /* Parameters are reversed in Linux */
-#define WRT_REG_BYTE(addr, data)  (outb(data,(unsigned long)addr))
-#define WRT_REG_WORD(addr, data)  (outw(data,(unsigned long)addr))
-#define WRT_REG_DWORD(addr, data) (outl(data,(unsigned long)addr))
-#else
-#define WRT_REG_BYTE(addr, data)  (outb((unsigned long)addr, data))
-#define WRT_REG_WORD(addr, data)  (outw((unsigned long)addr, data))
-#define WRT_REG_DWORD(addr, data) (outl((unsigned long)addr, data))
-#endif
-#endif  /* MEMORY_MAPPED_IO */
-#endif    /* QL_DEBUG_LEVEL_1 */
+#define WRT_REG_BYTE(addr, data)	outb(data, (unsigned long)addr)
+#define WRT_REG_WORD(addr, data)	outw(data, (unsigned long)addr)
+#define WRT_REG_DWORD(addr, data)	outl(data, (unsigned long)addr)
+#endif				/* MEMORY_MAPPED_IO */
+#endif				/* QL_DEBUG_LEVEL_1 */
 
 /*
  * Host adapter default definitions.
  */
-#define MAX_BUSES       2             /* 2 */
-#define MAX_B_BITS      1
+#define MAX_BUSES	2	/* 2 */
+#define MAX_B_BITS	1
 
-#define MAX_TARGETS     16             /* 16 */
-#define MAX_T_BITS      4              /* 4 */
+#define MAX_TARGETS	16	/* 16 */
+#define MAX_T_BITS	4	/* 4 */
 
-#define MAX_LUNS        8              /* 32 */
-#define MAX_L_BITS      3               /* 5 */
+#define MAX_LUNS	8	/* 32 */
+#define MAX_L_BITS	3	/* 5 */
 
 /*
  * Watchdog time quantum
  */
-#define QLA1280_WDG_TIME_QUANTUM   5    /* In seconds */
+#define QLA1280_WDG_TIME_QUANTUM	5	/* In seconds */
 
 /* Command retry count (0-65535) */
-#define COMMAND_RETRY_COUNT   255
+#define COMMAND_RETRY_COUNT		255
 
 /* Maximum outstanding commands in ISP queues (1-65535) */
-#define MAX_OUTSTANDING_COMMANDS   512
+#define MAX_OUTSTANDING_COMMANDS	512
 
 /* ISP request and response entry counts (37-65535) */
-#define REQUEST_ENTRY_CNT       256     /* Number of request entries. */
-#define RESPONSE_ENTRY_CNT      16      /* Number of response entries. */
+#define REQUEST_ENTRY_CNT		256 /* Number of request entries. */
+#define RESPONSE_ENTRY_CNT		16  /* Number of response entries. */
 
 /* Maximum equipage per controller */
-#define MAX_EQ          (MAX_BUSES * MAX_TARGETS * MAX_LUNS)
+#define MAX_EQ				(MAX_BUSES * MAX_TARGETS * MAX_LUNS)
 
 /* Number of segments 1 - 65535 */
-#define SG_SEGMENTS     32             /* Cmd entry + 6 continuations */
-
+#define SG_SEGMENTS			32  /* Cmd entry + 6 continuations */
 
 /*
- * SCSI Request Block structure
+ * SCSI Request Block structure  (sp)  that is placed
+ * on cmd->SCp location of every I/O
  */
-typedef struct srb
-{
-    Scsi_Cmnd  *cmd;                 /* (4) SCSI command block */
-    struct srb  *s_next;             /* (4) Next block on LU queue */
-    struct srb  *s_prev;             /* (4) Previous block on LU queue */
-    uint8_t     flags;               /* (1) Status flags. */
-    uint8_t     dir;                 /* direction of transfer */
-    uint8_t     unused[2];
-    u_long      r_start;             /* jiffies at start of request */
-    u_long      u_start;             /* jiffies when sent to F/W    */
-}srb_t;
+typedef struct srb {
+	Scsi_Cmnd *cmd;		/* (4/8) SCSI command block */
+	struct srb *s_next;	/* (4/8) Next block on LU queue */
+	struct srb *s_prev;	/* (4/8) Previous block on LU queue */
+	uint8_t flags;		/* (1) Status flags. */
+	uint8_t dir;		/* direction of transfer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
+	dma_addr_t saved_dma_handle;	/* for unmap of single transfers */
+#endif
+
+} srb_t;
 
 /*
  * SRB flag definitions
  */
-#define SRB_TIMEOUT     BIT_0           /* Command timed out */
-#define SRB_SENT        BIT_1           /* Command sent to ISP */
-#define SRB_ABORT_PENDING     BIT_2     /* Command abort sent to device */
-#define SRB_ABORTED     BIT_3           /* Command aborted command already */
-
+#define SRB_TIMEOUT		BIT_0	/* Command timed out */
+#define SRB_SENT		BIT_1	/* Command sent to ISP */
+#define SRB_ABORT_PENDING	BIT_2	/* Command abort sent to device */
+#define SRB_ABORTED		BIT_3	/* Command aborted command already */
 
 /*
  * Logical Unit Queue structure
  */
-typedef struct scsi_lu
-{
-    srb_t           *q_first;           /* First block on LU queue */
-    srb_t           *q_last;            /* Last block on LU queue */
-    uint8_t         q_flag;             /* LU queue state flags */
-    uint8_t         q_sense[16];        /* sense data */
-    u_long          io_cnt;             /* total xfer count */
-    u_long          resp_time;          /* total response time (start - finish) */
-    u_long          act_time;           /* total actived time (minus queuing time) */
-    u_long          w_cnt;              /* total writes */
-    u_long          r_cnt;              /* total reads */
-    uint16_t        q_outcnt;           /* Pending jobs for this LU */
+typedef struct scsi_lu {
+	srb_t *q_first;		/* First block on LU queue */
+	srb_t *q_last;		/* Last block on LU queue */
+	uint8_t q_flag;		/* LU queue state flags */
+	uint8_t q_sense[16];	/* sense data */
+	unsigned long io_cnt;	/* total xfer count */
+	unsigned long resp_time;/* total response time (start - finish) */
+	unsigned long act_time;	/* total actived time (minus queuing time) */
+	unsigned long w_cnt;	/* total writes */
+	unsigned long r_cnt;	/* total reads */
+	uint16_t q_outcnt;	/* Pending jobs for this LU */
 #if QL1280_TARGET_MODE_SUPPORT
-    void            (*q_func)();        /* Target driver event handler */
-    int32_t         q_param;            /* Target driver event param */
-    uint8_t         q_lock;            /* Device Queue Lock */
+	void (*q_func)();	/* Target driver event handler */
+	int32_t q_param;	/* Target driver event param */
+	uint8_t q_lock;		/* Device Queue Lock */
 #endif
-}scsi_lu_t;
+} scsi_lu_t;
 
 /*
- * Logical Unit flags 
+ * Logical Unit flags
  */
-#define QLA1280_QBUSY   BIT_0
-#define QLA1280_QWAIT   BIT_1
-#define QLA1280_QSUSP   BIT_2
-#define QLA1280_QSENSE  BIT_3           /* Sense data cache valid */
-#define QLA1280_QRESET  BIT_4
-#define QLA1280_QHBA    BIT_5
-#define QLA1280_BSUSP   BIT_6           /* controller is suspended */
-#define QLA1280_BREM    BIT_7           /* controller is removed */
-
-/*
- *  ISP PCI Configuration Register Set
- */
-typedef volatile struct
-{
-    uint16_t vendor_id;                 /* 0x0 */
-    uint16_t device_id;                 /* 0x2 */
-    uint16_t command;                   /* 0x4 */
-    uint16_t status;                    /* 0x6 */
-    uint8_t revision_id;                /* 0x8 */
-    uint8_t programming_interface;      /* 0x9 */
-    uint8_t sub_class;                  /* 0xa */
-    uint8_t base_class;                 /* 0xb */
-    uint8_t cache_line;                 /* 0xc */
-    uint8_t latency_timer;              /* 0xd */
-    uint8_t header_type;                /* 0xe */
-    uint8_t bist;                       /* 0xf */
-    uint32_t base_port;                  /* 0x10 */
-    uint32_t mem_base_addr;              /* 0x14 */
-    uint32_t base_addr[4];               /* 0x18-0x24 */
-    uint32_t reserved_1[2];              /* 0x28-0x2c */
-    uint16_t expansion_rom;             /* 0x30 */
-    uint32_t reserved_2[2];              /* 0x34-0x38 */
-    uint8_t interrupt_line;             /* 0x3c */
-    uint8_t interrupt_pin;              /* 0x3d */
-    uint8_t min_grant;                  /* 0x3e */
-    uint8_t max_latency;                /* 0x3f */
-}config_reg_t;
+#define QLA1280_QBUSY	BIT_0
+#define QLA1280_QWAIT	BIT_1
+#define QLA1280_QSUSP	BIT_2
+#define QLA1280_QSENSE	BIT_3	/* Sense data cache valid */
+#define QLA1280_QRESET	BIT_4
+#define QLA1280_QHBA	BIT_5
+#define QLA1280_BSUSP	BIT_6	/* controller is suspended */
+#define QLA1280_BREM	BIT_7	/* controller is removed */
 
 /*
  *  ISP I/O Register Set structure definitions.
  */
-typedef volatile struct
-{
-    uint16_t id_l;                      /* ID low */
-    uint16_t id_h;                      /* ID high */
-    uint16_t cfg_0;                     /* Configuration 0 */
-    uint16_t cfg_1;                     /* Configuration 1 */
-    uint16_t ictrl;                     /* Interface control */
-        #define ISP_RESET       BIT_0   /* ISP soft reset */
-        #define ISP_EN_INT      BIT_1   /* ISP enable interrupts. */
-        #define ISP_EN_RISC     BIT_2   /* ISP enable RISC interrupts. */
-    uint16_t istatus;                   /* Interface status */
-        #define PCI_64BIT_SLOT  BIT_14  /* PCI 64-bit slot indicator. */
-        #define RISC_INT        BIT_2   /* RISC interrupt */
-        #define PCI_INT         BIT_1   /* PCI interrupt */
-    uint16_t semaphore;                 /* Semaphore */
-    uint16_t nvram;                     /* NVRAM register. */
-        #define NV_DESELECT     0
-        #define NV_CLOCK        BIT_0
-        #define NV_SELECT       BIT_1
-        #define NV_DATA_OUT     BIT_2
-        #define NV_DATA_IN      BIT_3
-    uint16_t flash_data;                /* Flash BIOS data */
-    uint16_t flash_address;             /* Flash BIOS address */
-
-    uint16_t unused_1[0x2e];            /* 0x14-0x6f Gap */
-
-    uint16_t mailbox0;                  /* Mailbox 0 */
-    uint16_t mailbox1;                  /* Mailbox 1 */
-    uint16_t mailbox2;                  /* Mailbox 2 */
-    uint16_t mailbox3;                  /* Mailbox 3 */
-    uint16_t mailbox4;                  /* Mailbox 4 */
-    uint16_t mailbox5;                  /* Mailbox 5 */
-    uint16_t mailbox6;                  /* Mailbox 6 */
-    uint16_t mailbox7;                  /* Mailbox 7 */
-
-    uint16_t unused_2[0x20];            /* 0x80-0xbf Gap */
-
-    uint16_t host_cmd;                  /* Host command and control */
-        #define HOST_INT      BIT_7     /* host interrupt bit */
-        #define BIOS_ENABLE   BIT_0
-
-    uint16_t unused_6[0x5];             /* 0xc2-0xcb Gap */
-
-    uint16_t gpio_data;
-    uint16_t gpio_enable;
+struct device_reg {
+	uint16_t id_l;		/* ID low */
+	uint16_t id_h;		/* ID high */
+	uint16_t cfg_0;		/* Configuration 0 */
+	uint16_t cfg_1;		/* Configuration 1 */
+	uint16_t ictrl;		/* Interface control */
+#define ISP_RESET        BIT_0	/* ISP soft reset */
+#define ISP_EN_INT       BIT_1	/* ISP enable interrupts. */
+#define ISP_EN_RISC      BIT_2	/* ISP enable RISC interrupts. */
+#define ISP_FLASH_ENABLE BIT_8	/* Flash BIOS Read/Write enable */
+#define ISP_FLASH_UPPER  BIT_9	/* Flash upper bank select */
+	uint16_t istatus;	/* Interface status */
+#define PCI_64BIT_SLOT   BIT_14	/* PCI 64-bit slot indicator. */
+#define RISC_INT         BIT_2	/* RISC interrupt */
+#define PCI_INT          BIT_1	/* PCI interrupt */
+	uint16_t semaphore;	/* Semaphore */
+	uint16_t nvram;		/* NVRAM register. */
+#define NV_DESELECT     0
+#define NV_CLOCK        BIT_0
+#define NV_SELECT       BIT_1
+#define NV_DATA_OUT     BIT_2
+#define NV_DATA_IN      BIT_3
+	uint16_t flash_data;	/* Flash BIOS data */
+	uint16_t flash_address;	/* Flash BIOS address */
+
+	uint16_t unused_1[0x2e];	/* 0x14-0x6f Gap */
+
+	uint16_t mailbox0;	/* Mailbox 0 */
+	uint16_t mailbox1;	/* Mailbox 1 */
+	uint16_t mailbox2;	/* Mailbox 2 */
+	uint16_t mailbox3;	/* Mailbox 3 */
+	uint16_t mailbox4;	/* Mailbox 4 */
+	uint16_t mailbox5;	/* Mailbox 5 */
+	uint16_t mailbox6;	/* Mailbox 6 */
+	uint16_t mailbox7;	/* Mailbox 7 */
+
+	uint16_t unused_2[0x20];/* 0x80-0xbf Gap */
+
+	uint16_t host_cmd;	/* Host command and control */
+#define HOST_INT      BIT_7	/* host interrupt bit */
+#define BIOS_ENABLE   BIT_0
+
+	uint16_t unused_6[0x5];	/* 0xc2-0xcb Gap */
+
+	uint16_t gpio_data;
+	uint16_t gpio_enable;
+
+	uint16_t unused_7[0x11];	/* d0-f0 */
+	uint16_t scsiControlPins;	/* f2 */
+};
 
-    uint16_t unused_7[0x11];			/* d0-f0	*/
-    uint16_t scsiControlPins;           /* f2 */
-
-}device_reg_t;
-
-#define MAILBOX_REGISTER_COUNT  8
+#define MAILBOX_REGISTER_COUNT	8
 
 /*
  *  ISP product identification definitions in mailboxes after reset.
  */
-#define PROD_ID_1           0x4953
-#define PROD_ID_2           0x0000
-#define PROD_ID_2a          0x5020
-#define PROD_ID_3           0x2020
-#define PROD_ID_4           0x1
+#define PROD_ID_1		0x4953
+#define PROD_ID_2		0x0000
+#define PROD_ID_2a		0x5020
+#define PROD_ID_3		0x2020
+#define PROD_ID_4		0x1
 
 /*
  * ISP host command and control register command definitions
  */
-#define HC_RESET_RISC       0x1000      /* Reset RISC */
-#define HC_PAUSE_RISC       0x2000      /* Pause RISC */
-#define HC_RELEASE_RISC     0x3000      /* Release RISC from reset. */
-#define HC_SET_HOST_INT     0x5000      /* Set host interrupt */
-#define HC_CLR_HOST_INT     0x6000      /* Clear HOST interrupt */
-#define HC_CLR_RISC_INT     0x7000      /* Clear RISC interrupt */
-#define HC_DISABLE_BIOS     0x9000      /* Disable BIOS. */
+#define HC_RESET_RISC		0x1000	/* Reset RISC */
+#define HC_PAUSE_RISC		0x2000	/* Pause RISC */
+#define HC_RELEASE_RISC		0x3000	/* Release RISC from reset. */
+#define HC_SET_HOST_INT		0x5000	/* Set host interrupt */
+#define HC_CLR_HOST_INT		0x6000	/* Clear HOST interrupt */
+#define HC_CLR_RISC_INT		0x7000	/* Clear RISC interrupt */
+#define HC_DISABLE_BIOS		0x9000	/* Disable BIOS. */
 
 /*
  * ISP mailbox Self-Test status codes
  */
-#define MBS_FRM_ALIVE       0           /* Firmware Alive. */
-#define MBS_CHKSUM_ERR      1           /* Checksum Error. */
-#define MBS_SHADOW_LD_ERR   2           /* Shadow Load Error. */
-#define MBS_BUSY            4           /* Busy. */
+#define MBS_FRM_ALIVE		0	/* Firmware Alive. */
+#define MBS_CHKSUM_ERR		1	/* Checksum Error. */
+#define MBS_SHADOW_LD_ERR	2	/* Shadow Load Error. */
+#define MBS_BUSY		4	/* Busy. */
 
 /*
  * ISP mailbox command complete status codes
  */
-#define MBS_CMD_CMP         0x4000      /* Command Complete. */
-#define MBS_INV_CMD         0x4001      /* Invalid Command. */
-#define MBS_HOST_INF_ERR    0x4002      /* Host Interface Error. */
-#define MBS_TEST_FAILED     0x4003      /* Test Failed. */
-#define MBS_CMD_ERR         0x4005      /* Command Error. */
-#define MBS_CMD_PARAM_ERR   0x4006      /* Command Parameter Error. */
+#define MBS_CMD_CMP		0x4000	/* Command Complete. */
+#define MBS_INV_CMD		0x4001	/* Invalid Command. */
+#define MBS_HOST_INF_ERR	0x4002	/* Host Interface Error. */
+#define MBS_TEST_FAILED		0x4003	/* Test Failed. */
+#define MBS_CMD_ERR		0x4005	/* Command Error. */
+#define MBS_CMD_PARAM_ERR	0x4006	/* Command Parameter Error. */
 
 /*
  * ISP mailbox asynchronous event status codes
  */
-#define MBA_ASYNC_EVENT         0x8000  /* Asynchronous event. */
-#define MBA_BUS_RESET           0x8001  /* SCSI Bus Reset. */
-#define MBA_SYSTEM_ERR          0x8002  /* System Error. */
-#define MBA_REQ_TRANSFER_ERR    0x8003  /* Request Transfer Error. */
-#define MBA_RSP_TRANSFER_ERR    0x8004  /* Response Transfer Error. */
-#define MBA_WAKEUP_THRES        0x8005  /* Request Queue Wake-up. */
-#define MBA_TIMEOUT_RESET       0x8006  /* Execution Timeout Reset. */
-#define MBA_DEVICE_RESET        0x8007  /* Bus Device Reset. */
-#define MBA_BUS_MODE_CHANGE     0x800E  /* SCSI bus mode transition. */
-#define MBA_SCSI_COMPLETION     0x8020  /* Completion response. */
+#define MBA_ASYNC_EVENT		0x8000	/* Asynchronous event. */
+#define MBA_BUS_RESET		0x8001	/* SCSI Bus Reset. */
+#define MBA_SYSTEM_ERR		0x8002	/* System Error. */
+#define MBA_REQ_TRANSFER_ERR	0x8003	/* Request Transfer Error. */
+#define MBA_RSP_TRANSFER_ERR	0x8004	/* Response Transfer Error. */
+#define MBA_WAKEUP_THRES	0x8005	/* Request Queue Wake-up. */
+#define MBA_TIMEOUT_RESET	0x8006	/* Execution Timeout Reset. */
+#define MBA_DEVICE_RESET	0x8007	/* Bus Device Reset. */
+#define MBA_BUS_MODE_CHANGE	0x800E	/* SCSI bus mode transition. */
+#define MBA_SCSI_COMPLETION	0x8020	/* Completion response. */
 
 /*
  * ISP mailbox commands
  */
-#define MBC_NOP                     0       /* No Operation. */
-#define MBC_LOAD_RAM                1       /* Load RAM. */
-#define MBC_EXECUTE_FIRMWARE        2       /* Execute firmware. */
-#define MBC_WRITE_RAM_WORD          4       /* Write ram word. */
-#define MBC_READ_RAM_WORD           5       /* Read ram word. */
-#define MBC_MAILBOX_REGISTER_TEST   6       /* Wrap incoming mailboxes */
-#define MBC_VERIFY_CHECKSUM         7       /* Verify checksum. */
-#define MBC_ABOUT_FIRMWARE          8       /* Get firmware revision. */
-#define MBC_INIT_REQUEST_QUEUE      0x10    /* Initialize request queue. */
-#define MBC_INIT_RESPONSE_QUEUE     0x11    /* Initialize response queue. */
-#define MBC_EXECUTE_IOCB            0x12    /* Execute IOCB command. */
-#define MBC_ABORT_COMMAND           0x15    /* Abort IOCB command. */
-#define MBC_ABORT_DEVICE            0x16    /* Abort device (ID/LUN). */
-#define MBC_ABORT_TARGET            0x17    /* Abort target (ID). */
-#define MBC_BUS_RESET               0x18    /* SCSI bus reset. */
-#define MBC_GET_RETRY_COUNT         0x22    /* Get retry count and delay. */
-#define MBC_GET_TARGET_PARAMETERS   0x28    /* Get target parameters. */
-#define MBC_SET_INITIATOR_ID        0x30    /* Set initiator SCSI ID. */
-#define MBC_SET_SELECTION_TIMEOUT   0x31    /* Set selection timeout. */
-#define MBC_SET_RETRY_COUNT         0x32    /* Set retry count and delay. */
-#define MBC_SET_TAG_AGE_LIMIT       0x33    /* Set tag age limit. */
-#define MBC_SET_CLOCK_RATE          0x34    /* Set clock rate. */
-#define MBC_SET_ACTIVE_NEGATION     0x35    /* Set active negation state. */
-#define MBC_SET_ASYNC_DATA_SETUP    0x36    /* Set async data setup time. */
-#define MBC_SET_PCI_CONTROL         0x37    /* Set BUS control parameters. */
-#define MBC_SET_TARGET_PARAMETERS   0x38    /* Set target parameters. */
-#define MBC_SET_DEVICE_QUEUE        0x39    /* Set device queue parameters */
-#define MBC_SET_SYSTEM_PARAMETER    0x45    /* Set system parameter word. */
-#define MBC_SET_FIRMWARE_FEATURES   0x4A    /* Set firmware feature word. */
-#define MBC_INIT_REQUEST_QUEUE_A64  0x52    /* Initialize request queue A64 */
-#define MBC_INIT_RESPONSE_QUEUE_A64 0x53    /* Initialize response q A64. */
-#define MBC_ENABLE_TARGET_MODE      0x55    /* Enable target mode. */
+#define MBC_NOP                     0	/* No Operation. */
+#define MBC_LOAD_RAM                1	/* Load RAM. */
+#define MBC_EXECUTE_FIRMWARE        2	/* Execute firmware. */
+#define MBC_WRITE_RAM_WORD          4	/* Write ram word. */
+#define MBC_READ_RAM_WORD           5	/* Read ram word. */
+#define MBC_MAILBOX_REGISTER_TEST   6	/* Wrap incoming mailboxes */
+#define MBC_VERIFY_CHECKSUM         7	/* Verify checksum. */
+#define MBC_ABOUT_FIRMWARE          8	/* Get firmware revision. */
+#define MBC_INIT_REQUEST_QUEUE      0x10	/* Initialize request queue. */
+#define MBC_INIT_RESPONSE_QUEUE     0x11	/* Initialize response queue. */
+#define MBC_EXECUTE_IOCB            0x12	/* Execute IOCB command. */
+#define MBC_ABORT_COMMAND           0x15	/* Abort IOCB command. */
+#define MBC_ABORT_DEVICE            0x16	/* Abort device (ID/LUN). */
+#define MBC_ABORT_TARGET            0x17	/* Abort target (ID). */
+#define MBC_BUS_RESET               0x18	/* SCSI bus reset. */
+#define MBC_GET_RETRY_COUNT         0x22	/* Get retry count and delay. */
+#define MBC_GET_TARGET_PARAMETERS   0x28	/* Get target parameters. */
+#define MBC_SET_INITIATOR_ID        0x30	/* Set initiator SCSI ID. */
+#define MBC_SET_SELECTION_TIMEOUT   0x31	/* Set selection timeout. */
+#define MBC_SET_RETRY_COUNT         0x32	/* Set retry count and delay. */
+#define MBC_SET_TAG_AGE_LIMIT       0x33	/* Set tag age limit. */
+#define MBC_SET_CLOCK_RATE          0x34	/* Set clock rate. */
+#define MBC_SET_ACTIVE_NEGATION     0x35	/* Set active negation state. */
+#define MBC_SET_ASYNC_DATA_SETUP    0x36	/* Set async data setup time. */
+#define MBC_SET_PCI_CONTROL         0x37	/* Set BUS control parameters. */
+#define MBC_SET_TARGET_PARAMETERS   0x38	/* Set target parameters. */
+#define MBC_SET_DEVICE_QUEUE        0x39	/* Set device queue parameters */
+#define MBC_SET_SYSTEM_PARAMETER    0x45	/* Set system parameter word. */
+#define MBC_SET_FIRMWARE_FEATURES   0x4A	/* Set firmware feature word. */
+#define MBC_INIT_REQUEST_QUEUE_A64  0x52	/* Initialize request queue A64 */
+#define MBC_INIT_RESPONSE_QUEUE_A64 0x53	/* Initialize response q A64. */
+#define MBC_ENABLE_TARGET_MODE      0x55	/* Enable target mode. */
 
 /*
  * ISP Get/Set Target Parameters mailbox command control flags.
  */
-#define TP_RENEGOTIATE          BIT_8   /* Renegotiate on error. */
-#define TP_STOP_QUEUE           BIT_9   /* Stop que on check condition */
-#define TP_AUTO_REQUEST_SENSE   BIT_10  /* Automatic request sense. */
-#define TP_TAGGED_QUEUE         BIT_11  /* Tagged queuing. */
-#define TP_SYNC                 BIT_12  /* Synchronous data transfers. */
-#define TP_WIDE                 BIT_13  /* Wide data transfers. */
-#define TP_PARITY               BIT_14  /* Parity checking. */
-#define TP_DISCONNECT           BIT_15  /* Disconnect privilege. */
+#define TP_RENEGOTIATE          BIT_8	/* Renegotiate on error. */
+#define TP_STOP_QUEUE           BIT_9	/* Stop que on check condition */
+#define TP_AUTO_REQUEST_SENSE   BIT_10	/* Automatic request sense. */
+#define TP_TAGGED_QUEUE         BIT_11	/* Tagged queuing. */
+#define TP_SYNC                 BIT_12	/* Synchronous data transfers. */
+#define TP_WIDE                 BIT_13	/* Wide data transfers. */
+#define TP_PARITY               BIT_14	/* Parity checking. */
+#define TP_DISCONNECT           BIT_15	/* Disconnect privilege. */
 
 /*
  * NVRAM Command values.
  */
-#define NV_START_BIT            BIT_2
-#define NV_WRITE_OP             (BIT_26+BIT_24)
-#define NV_READ_OP              (BIT_26+BIT_25)
-#define NV_ERASE_OP             (BIT_26+BIT_25+BIT_24)
-#define NV_MASK_OP              (BIT_26+BIT_25+BIT_24)
-#define NV_DELAY_COUNT          10
+#define NV_START_BIT		BIT_2
+#define NV_WRITE_OP		(BIT_26 | BIT_24)
+#define NV_READ_OP		(BIT_26 | BIT_25)
+#define NV_ERASE_OP		(BIT_26 | BIT_25 | BIT_24)
+#define NV_MASK_OP		(BIT_26 | BIT_25 | BIT_24)
+#define NV_DELAY_COUNT		10
 
 /*
  *  QLogic ISP1280 NVRAM structure definition.
  */
-typedef struct
-{
-    uint8_t id[4];                                  /* 0, 1, 2, 3 */
-    uint8_t version;                                /* 4 */
-
-    struct
-    {
-        uint8_t bios_configuration_mode     :2;
-        uint8_t bios_disable                :1;
-        uint8_t selectable_scsi_boot_enable :1;
-        uint8_t cd_rom_boot_enable          :1;
-        uint8_t disable_loading_risc_code   :1;
-        uint8_t enable_64bit_addressing     :1;
-        uint8_t unused_7                    :1;
-    }cntr_flags_1;                                  /* 5 */
-
-    struct
-    {
-        uint8_t boot_lun_number    :5;
-        uint8_t scsi_bus_number    :1;
-        uint8_t unused_6           :1;
-        uint8_t unused_7           :1;
-        uint8_t boot_target_number :4;
-        uint8_t unused_12          :1;
-        uint8_t unused_13          :1;
-        uint8_t unused_14          :1;
-        uint8_t unused_15          :1;
-    }cntr_flags_2;                                  /* 6, 7 */
-
-    uint16_t unused_8;                              /* 8, 9 */
-    uint16_t unused_10;                             /* 10, 11 */
-    uint16_t unused_12;                             /* 12, 13 */
-    uint16_t unused_14;                              /* 14, 15 */
-
-    union
-    {
-        uint8_t c;
-        struct
-        {
-            uint8_t reserved        :2;
-            uint8_t burst_enable    :1;
-            uint8_t reserved_1      :1;
-            uint8_t fifo_threshold  :4;
-        }f;
-    }isp_config;                                    /* 16 */
-
-    /* Termination
-     * 0 = Disable, 1 = high only, 3 = Auto term
-     */
-    union
-    {
-        uint8_t c;
-        struct
-        {
-            uint8_t scsi_bus_1_control  :2;
-            uint8_t scsi_bus_0_control  :2;
-            uint8_t unused_0            :1;
-            uint8_t unused_1            :1;
-            uint8_t unused_2            :1;
-            uint8_t auto_term_support   :1;
-        }f;
-    }termination;                                   /* 17 */
-
-    uint16_t isp_parameter;                         /* 18, 19 */
-
-    union
-    {
-        uint16_t w;
-        struct
-        {
-            uint8_t enable_fast_posting       :1;
-            uint8_t report_lvd_bus_transition :1;
-            uint8_t unused_2                  :1;
-            uint8_t unused_3                  :1;
-            uint8_t unused_4                  :1;
-            uint8_t unused_5                  :1;
-            uint8_t unused_6                  :1;
-            uint8_t unused_7                  :1;
-            uint8_t unused_8                  :1;
-            uint8_t unused_9                  :1;
-            uint8_t unused_10                 :1;
-            uint8_t unused_11                 :1;
-            uint8_t unused_12                 :1;
-            uint8_t unused_13                 :1;
-            uint8_t unused_14                 :1;
-            uint8_t unused_15                 :1;
-        }f;
-    }firmware_feature;                              /* 20, 21 */
-
-    uint16_t unused_22;                             /* 22, 23 */
-
-    struct
-    {
-        struct
-        {
-            uint8_t initiator_id       :4;
-            uint8_t scsi_reset_disable :1;
-            uint8_t scsi_bus_size      :1;
-            uint8_t scsi_bus_type      :1;
-            uint8_t unused_7           :1;
-        }config_1;                                  /* 24 */
-
-        uint8_t bus_reset_delay;                    /* 25 */
-        uint8_t retry_count;                        /* 26 */
-        uint8_t retry_delay;                        /* 27 */
-
-        struct
-        {
-            uint8_t async_data_setup_time     :4;
-            uint8_t req_ack_active_negation   :1;
-            uint8_t data_line_active_negation :1;
-            uint8_t unused_6                  :1;
-            uint8_t unused_7                  :1;
-        }config_2;                                  /* 28 */
-
-        uint8_t unused_29;                          /* 29 */
-
-        uint16_t selection_timeout;                 /* 30, 31 */
-        uint16_t max_queue_depth;                   /* 32, 33 */
-
-        uint16_t unused_34;                         /* 34, 35 */
-        uint16_t unused_36;                         /* 36, 37 */
-        uint16_t unused_38;                         /* 38, 39 */
-
-        struct
-        {
-            union
-            {
-                uint8_t c;
-                struct
-                {
-                    uint8_t renegotiate_on_error :1;
-                    uint8_t stop_queue_on_check  :1;
-                    uint8_t auto_request_sense   :1;
-                    uint8_t tag_queuing          :1;
-                    uint8_t sync_data_transfers  :1;
-                    uint8_t wide_data_transfers  :1;
-                    uint8_t parity_checking      :1;
-                    uint8_t disconnect_allowed   :1;
-                }f;
-            }parameter;                             /* 40 */
-
-            uint8_t execution_throttle;             /* 41 */
-            uint8_t sync_period;                    /* 42 */
-
-            struct
-            {
-                uint8_t sync_offset   :4;
-                uint8_t device_enable :1;
-                uint8_t lun_disable   :1;
-                uint8_t unused_6      :1;
-                uint8_t unused_7      :1;
-            }flags;                                 /* 43 */
-
-            uint16_t unused_44;                     /* 44, 45 */
-        }target[MAX_TARGETS];
-    }bus[MAX_BUSES];
+typedef struct {
+	uint8_t id[4];		/* 0, 1, 2, 3 */
+	uint8_t version;	/* 4 */
+
+	struct {
+		uint8_t bios_configuration_mode:2;
+		uint8_t bios_disable:1;
+		uint8_t selectable_scsi_boot_enable:1;
+		uint8_t cd_rom_boot_enable:1;
+		uint8_t disable_loading_risc_code:1;
+		uint8_t enable_64bit_addressing:1;
+		uint8_t unused_7:1;
+	} cntr_flags_1;		/* 5 */
+
+	struct {
+		uint8_t boot_lun_number:5;
+		uint8_t scsi_bus_number:1;
+		uint8_t unused_6:1;
+		uint8_t unused_7:1;
+		uint8_t boot_target_number:4;
+		uint8_t unused_12:1;
+		uint8_t unused_13:1;
+		uint8_t unused_14:1;
+		uint8_t unused_15:1;
+	} cntr_flags_2;		/* 6, 7 */
+
+	uint16_t unused_8;	/* 8, 9 */
+	uint16_t unused_10;	/* 10, 11 */
+	uint16_t unused_12;	/* 12, 13 */
+	uint16_t unused_14;	/* 14, 15 */
+
+	union {
+		uint8_t c;
+		struct {
+			uint8_t reserved:2;
+			uint8_t burst_enable:1;
+			uint8_t reserved_1:1;
+			uint8_t fifo_threshold:4;
+		} f;
+	} isp_config;		/* 16 */
+
+	/* Termination
+	 * 0 = Disable, 1 = high only, 3 = Auto term
+	 */
+	union {
+		uint8_t c;
+		struct {
+			uint8_t scsi_bus_1_control:2;
+			uint8_t scsi_bus_0_control:2;
+			uint8_t unused_0:1;
+			uint8_t unused_1:1;
+			uint8_t unused_2:1;
+			uint8_t auto_term_support:1;
+		} f;
+	} termination;		/* 17 */
+
+	uint16_t isp_parameter;	/* 18, 19 */
+
+	union {
+		uint16_t w;
+		struct {
+			uint8_t enable_fast_posting:1;
+			uint8_t report_lvd_bus_transition:1;
+			uint8_t unused_2:1;
+			uint8_t unused_3:1;
+			uint8_t unused_4:1;
+			uint8_t unused_5:1;
+			uint8_t unused_6:1;
+			uint8_t unused_7:1;
+			uint8_t unused_8:1;
+			uint8_t unused_9:1;
+			uint8_t unused_10:1;
+			uint8_t unused_11:1;
+			uint8_t unused_12:1;
+			uint8_t unused_13:1;
+			uint8_t unused_14:1;
+			uint8_t unused_15:1;
+		} f;
+	} firmware_feature;	/* 20, 21 */
+
+	uint16_t unused_22;	/* 22, 23 */
+
+	struct {
+		struct {
+			uint8_t initiator_id:4;
+			uint8_t scsi_reset_disable:1;
+			uint8_t scsi_bus_size:1;
+			uint8_t scsi_bus_type:1;
+			uint8_t unused_7:1;
+		} config_1;	/* 24 */
+
+		uint8_t bus_reset_delay;	/* 25 */
+		uint8_t retry_count;	/* 26 */
+		uint8_t retry_delay;	/* 27 */
+
+		struct {
+			uint8_t async_data_setup_time:4;
+			uint8_t req_ack_active_negation:1;
+			uint8_t data_line_active_negation:1;
+			uint8_t unused_6:1;
+			uint8_t unused_7:1;
+		} config_2;	/* 28 */
+
+		uint8_t unused_29;	/* 29 */
+
+		uint16_t selection_timeout;	/* 30, 31 */
+		uint16_t max_queue_depth;	/* 32, 33 */
+
+		uint16_t unused_34;	/* 34, 35 */
+		uint16_t unused_36;	/* 36, 37 */
+		uint16_t unused_38;	/* 38, 39 */
+
+		struct {
+			union {
+				uint8_t c;
+				struct {
+					uint8_t renegotiate_on_error:1;
+					uint8_t stop_queue_on_check:1;
+					uint8_t auto_request_sense:1;
+					uint8_t tag_queuing:1;
+					uint8_t sync_data_transfers:1;
+					uint8_t wide_data_transfers:1;
+					uint8_t parity_checking:1;
+					uint8_t disconnect_allowed:1;
+				} f;
+			} parameter;	/* 40 */
+
+			uint8_t execution_throttle;	/* 41 */
+			uint8_t sync_period;	/* 42 */
+
+			struct {
+				uint8_t sync_offset:4;
+				uint8_t device_enable:1;
+				uint8_t lun_disable:1;
+				uint8_t unused_6:1;
+				uint8_t unused_7:1;
+			} flags;	/* 43 */
+
+			uint16_t unused_44;	/* 44, 45 */
+		} target[MAX_TARGETS];
+	} bus[MAX_BUSES];
 
-    uint16_t unused_248;                        /* 248, 249 */
+	uint16_t unused_248;	/* 248, 249 */
 
-    uint16_t subsystem_id[2];                   /* 250, 251, 252, 253 */
+	uint16_t subsystem_id[2];	/* 250, 251, 252, 253 */
 
-    uint8_t  unused_254;                        /* 254 */
+	uint8_t unused_254;	/* 254 */
 
-    uint8_t chksum;                             /* 255 */
-}nvram_t;
+	uint8_t chksum;		/* 255 */
+} nvram_t;
 
 /*
  *  QLogic ISP12160 NVRAM structure definition.
  */
-typedef struct
-{
-    uint8_t id[4];                                  /* 0, 1, 2, 3 */
-    uint8_t version;                                /* 4 */
-    /* Host/Bios Flags */ 
-    struct
-    {
-        uint8_t bios_configuration_mode     :2;
-        uint8_t bios_disable                :1;
-        uint8_t selectable_scsi_boot_enable :1;
-        uint8_t cd_rom_boot_enable          :1;
-        uint8_t disable_loading_risc_code   :1;
-        uint8_t unused_6                    :1;
-        uint8_t unused_7                    :1;
-    }cntr_flags_1;                                  /* 5 */
-    /* Selectable Boot Support */
-    struct
-    {
-        uint8_t boot_lun_number    :5;
-        uint8_t scsi_bus_number    :1;
-        uint8_t unused_6           :1;
-        uint8_t unused_7           :1;
-        uint8_t boot_target_number :4;
-        uint8_t unused_12          :1;
-        uint8_t unused_13          :1;
-        uint8_t unused_14          :1;
-        uint8_t unused_15          :1;
-    }cntr_flags_2;                                  /* 6, 7 */
-
-    uint16_t unused_8;                              /* 8, 9 */
-    uint16_t unused_10;                             /* 10, 11 */
-    uint16_t unused_12;                             /* 12, 13 */
-    uint16_t unused_14;                              /* 14, 15 */
-
-    /* ISP Config Parameters */
-    union
-    {
-        uint8_t c;  
-        struct
-        {
-            uint8_t reserved        :2;
-            uint8_t burst_enable    :1;
-            uint8_t reserved_1      :1;
-            uint8_t fifo_threshold  :4;
-        }f;
-    }isp_config;                                    /* 16 */
-
-    /* Termination
-     * 0 = Disable, 1 = high only, 3 = Auto term
-     */
-    union
-    {
-        uint8_t c;
-        struct
-        {
-            uint8_t scsi_bus_1_control  :2;
-            uint8_t scsi_bus_0_control  :2;
-            uint8_t unused_0            :1;
-            uint8_t unused_1            :1;
-            uint8_t unused_2            :1;
-            uint8_t auto_term_support   :1;
-        }f;
-    }termination;                                   /* 17 */
-								/* Auto Term - 3                          */
-								/* High Only - 1 (GPIO2 = 1 & GPIO3 = 0)  */
-								/* Disable - 0 (GPIO2 = 0 & GPIO3 = X)    */
-
-    uint16_t isp_parameter;                         /* 18, 19 */
-
-    union
-    {
-        uint16_t w;
-        struct
-        {
-            uint8_t enable_fast_posting       :1;
-            uint8_t report_lvd_bus_transition :1;
-            uint8_t unused_2                  :1;
-            uint8_t unused_3                  :1;
-            uint8_t unused_4                  :1;
-            uint8_t unused_5                  :1;
-            uint8_t unused_6                  :1;
-            uint8_t unused_7                  :1;
-            uint8_t unused_8                  :1;
-            uint8_t unused_9                  :1;
-            uint8_t unused_10                 :1;
-            uint8_t unused_11                 :1;
-            uint8_t unused_12                 :1;
-            uint8_t unused_13                 :1;
-            uint8_t unused_14                 :1;
-            uint8_t unused_15                 :1;
-        }f;
-    }firmware_feature;                              /* 20, 21 */
-
-    uint16_t unused_22;                             /* 22, 23 */
-
-    struct
-    {
-        struct
-        {
-            uint8_t initiator_id       :4;
-            uint8_t scsi_reset_disable :1;
-            uint8_t scsi_bus_size      :1;
-            uint8_t scsi_bus_type      :1;
-            uint8_t unused_7           :1;
-        }config_1;                                  /* 24 */
-
-        uint8_t bus_reset_delay;                    /* 25 */
-        uint8_t retry_count;                        /* 26 */
-        uint8_t retry_delay;                        /* 27 */
-                /* Adapter Capabilities bits */
-        struct
-        {
-            uint8_t async_data_setup_time     :4;
-            uint8_t req_ack_active_negation   :1;
-            uint8_t data_line_active_negation :1;
-            uint8_t unused_6                  :1;
-            uint8_t unused_7                  :1;
-        }config_2;                                  /* 28 */
-
-        uint8_t unused_29;                          /* 29 */
-
-        uint16_t selection_timeout;                 /* 30, 31 */
-        uint16_t max_queue_depth;                   /* 32, 33 */
-
-        uint16_t unused_34;                         /* 34, 35 */
-        uint16_t unused_36;                         /* 36, 37 */
-        uint16_t unused_38;                         /* 38, 39 */
-
-        struct
-        {
-            union
-            {
-                uint8_t c;
-                struct
-                {
-                    uint8_t renegotiate_on_error :1;
-                    uint8_t stop_queue_on_check  :1;
-                    uint8_t auto_request_sense   :1;
-                    uint8_t tag_queuing          :1;
-                    uint8_t sync_data_transfers  :1;
-                    uint8_t wide_data_transfers  :1;
-                    uint8_t parity_checking      :1;
-                    uint8_t disconnect_allowed   :1;
-                }f;
-            }parameter;                             /* 40 */
-
-            uint8_t execution_throttle;             /* 41 */
-            uint8_t sync_period;                    /* 42 */
-
-            struct
-            {
-                uint8_t sync_offset   :5;
-                uint8_t device_enable :1;
-                uint8_t unused_6      :1;
-                uint8_t unused_7      :1;
-                uint8_t	ppr_options	  :4;
-                uint8_t	ppr_bus_width :2;
-	            uint8_t	unused_8	  :1;
-	            uint8_t	enable_ppr	  :1;  
-            }flags;                                 /* 43, 44 */
-
-            uint8_t unused_45;                     /* 45 */
-        }target[MAX_TARGETS];
-    }bus[MAX_BUSES];
+typedef struct {
+	uint8_t id[4];		/* 0, 1, 2, 3 */
+	uint8_t version;	/* 4 */
+	/* Host/Bios Flags */
+	struct {
+		uint8_t bios_configuration_mode:2;
+		uint8_t bios_disable:1;
+		uint8_t selectable_scsi_boot_enable:1;
+		uint8_t cd_rom_boot_enable:1;
+		uint8_t disable_loading_risc_code:1;
+		uint8_t unused_6:1;
+		uint8_t unused_7:1;
+	} cntr_flags_1;		/* 5 */
+	/* Selectable Boot Support */
+	struct {
+		uint8_t boot_lun_number:5;
+		uint8_t scsi_bus_number:1;
+		uint8_t unused_6:1;
+		uint8_t unused_7:1;
+		uint8_t boot_target_number:4;
+		uint8_t unused_12:1;
+		uint8_t unused_13:1;
+		uint8_t unused_14:1;
+		uint8_t unused_15:1;
+	} cntr_flags_2;		/* 6, 7 */
+
+	uint16_t unused_8;	/* 8, 9 */
+	uint16_t unused_10;	/* 10, 11 */
+	uint16_t unused_12;	/* 12, 13 */
+	uint16_t unused_14;	/* 14, 15 */
+
+	/* ISP Config Parameters */
+	union {
+		uint8_t c;
+		struct {
+			uint8_t reserved:2;
+			uint8_t burst_enable:1;
+			uint8_t reserved_1:1;
+			uint8_t fifo_threshold:4;
+		} f;
+	} isp_config;		/* 16 */
+
+	/* Termination
+	 * 0 = Disable, 1 = high only, 3 = Auto term
+	 */
+	union {
+		uint8_t c;
+		struct {
+			uint8_t scsi_bus_1_control:2;
+			uint8_t scsi_bus_0_control:2;
+			uint8_t unused_0:1;
+			uint8_t unused_1:1;
+			uint8_t unused_2:1;
+			uint8_t auto_term_support:1;
+		} f;
+	} termination;		/* 17 */
+	/* Auto Term - 3                          */
+	/* High Only - 1 (GPIO2 = 1 & GPIO3 = 0)  */
+	/* Disable - 0 (GPIO2 = 0 & GPIO3 = X)    */
+
+	uint16_t isp_parameter;	/* 18, 19 */
+
+	union {
+		uint16_t w;
+		struct {
+			uint8_t enable_fast_posting:1;
+			uint8_t report_lvd_bus_transition:1;
+			uint8_t unused_2:1;
+			uint8_t unused_3:1;
+			uint8_t unused_4:1;
+			uint8_t unused_5:1;
+			uint8_t unused_6:1;
+			uint8_t unused_7:1;
+			uint8_t unused_8:1;
+			uint8_t unused_9:1;
+			uint8_t unused_10:1;
+			uint8_t unused_11:1;
+			uint8_t unused_12:1;
+			uint8_t unused_13:1;
+			uint8_t unused_14:1;
+			uint8_t unused_15:1;
+		} f;
+	} firmware_feature;	/* 20, 21 */
+
+	uint16_t unused_22;	/* 22, 23 */
+
+	struct {
+		struct {
+			uint8_t initiator_id:4;
+			uint8_t scsi_reset_disable:1;
+			uint8_t scsi_bus_size:1;
+			uint8_t scsi_bus_type:1;
+			uint8_t unused_7:1;
+		} config_1;	/* 24 */
+
+		uint8_t bus_reset_delay;	/* 25 */
+		uint8_t retry_count;	/* 26 */
+		uint8_t retry_delay;	/* 27 */
+		/* Adapter Capabilities bits */
+		struct {
+			uint8_t async_data_setup_time:4;
+			uint8_t req_ack_active_negation:1;
+			uint8_t data_line_active_negation:1;
+			uint8_t unused_6:1;
+			uint8_t unused_7:1;
+		} config_2;	/* 28 */
+
+		uint8_t unused_29;	/* 29 */
+
+		uint16_t selection_timeout;	/* 30, 31 */
+		uint16_t max_queue_depth;	/* 32, 33 */
+
+		uint16_t unused_34;	/* 34, 35 */
+		uint16_t unused_36;	/* 36, 37 */
+		uint16_t unused_38;	/* 38, 39 */
+
+		struct {
+			union {
+				uint8_t c;
+				struct {
+					uint8_t renegotiate_on_error:1;
+					uint8_t stop_queue_on_check:1;
+					uint8_t auto_request_sense:1;
+					uint8_t tag_queuing:1;
+					uint8_t sync_data_transfers:1;
+					uint8_t wide_data_transfers:1;
+					uint8_t parity_checking:1;
+					uint8_t disconnect_allowed:1;
+				} f;
+			} parameter;	/* 40 */
+
+			uint8_t execution_throttle;	/* 41 */
+			uint8_t sync_period;	/* 42 */
+
+			struct {
+				uint8_t sync_offset:5;
+				uint8_t device_enable:1;
+				uint8_t unused_6:1;
+				uint8_t unused_7:1;
+				uint8_t ppr_options:4;
+				uint8_t ppr_bus_width:2;
+				uint8_t unused_8:1;
+				uint8_t enable_ppr:1;
+			} flags;	/* 43, 44 */
+
+			uint8_t unused_45;	/* 45 */
+		} target[MAX_TARGETS];
+	} bus[MAX_BUSES];
 
-    uint16_t unused_248;                        /* 248, 249 */
+	uint16_t unused_248;	/* 248, 249 */
 
-    uint16_t subsystem_id[2];                   /* 250, 251, 252, 253 */
+	uint16_t subsystem_id[2];	/* 250, 251, 252, 253 */
 
-    uint8_t  System_Id_Pointer;                   /* 254 */
+	uint8_t System_Id_Pointer;	/* 254 */
 
-    uint8_t chksum;                             /* 255 */
-}nvram160_t;
+	uint8_t chksum;		/* 255 */
+} nvram160_t;
 
 /*
  * ISP queue - command entry structure definition.
  */
-#define MAX_CMDSZ   12                  /* SCSI maximum CDB size. */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define COMMAND_TYPE    1       /* Command entry */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t handle;                    /* System handle. */
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  target;                    /* SCSI ID */
-    uint16_t cdb_len;                   /* SCSI command length. */
-    uint16_t control_flags;             /* Control flags. */
-    uint16_t reserved;
-    uint16_t timeout;                   /* Command timeout. */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint8_t  scsi_cdb[MAX_CMDSZ];       /* SCSI command words. */
-    uint32_t dseg_0_address;            /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address;            /* Data segment 1 address. */
-    uint32_t dseg_1_length;             /* Data segment 1 length. */
-    uint32_t dseg_2_address;            /* Data segment 2 address. */
-    uint32_t dseg_2_length;             /* Data segment 2 length. */
-    uint32_t dseg_3_address;            /* Data segment 3 address. */
-    uint32_t dseg_3_length;             /* Data segment 3 length. */
-}cmd_entry_t;
+#define MAX_CMDSZ	12		/* SCSI maximum CDB size. */
+typedef struct {
+	uint8_t entry_type;		/* Entry type. */
+#define COMMAND_TYPE    1		/* Command entry */
+	uint8_t entry_count;		/* Entry count. */
+	uint8_t sys_define;		/* System defined. */
+	uint8_t entry_status;		/* Entry Status. */
+	uint32_t handle;		/* System handle. */
+	uint8_t lun;			/* SCSI LUN */
+	uint8_t target;			/* SCSI ID */
+	uint16_t cdb_len;		/* SCSI command length. */
+	uint16_t control_flags;		/* Control flags. */
+	uint16_t reserved;
+	uint16_t timeout;		/* Command timeout. */
+	uint16_t dseg_count;		/* Data segment count. */
+	uint8_t scsi_cdb[MAX_CMDSZ];	/* SCSI command words. */
+	uint32_t dseg_0_address;	/* Data segment 0 address. */
+	uint32_t dseg_0_length;		/* Data segment 0 length. */
+	uint32_t dseg_1_address;	/* Data segment 1 address. */
+	uint32_t dseg_1_length;		/* Data segment 1 length. */
+	uint32_t dseg_2_address;	/* Data segment 2 address. */
+	uint32_t dseg_2_length;		/* Data segment 2 length. */
+	uint32_t dseg_3_address;	/* Data segment 3 address. */
+	uint32_t dseg_3_length;		/* Data segment 3 length. */
+} cmd_entry_t;
 
 /*
  * ISP queue - continuation entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define CONTINUE_TYPE   2       /* Continuation entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved;                  /* Reserved */
-    uint32_t dseg_0_address;            /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address;            /* Data segment 1 address. */
-    uint32_t dseg_1_length;             /* Data segment 1 length. */
-    uint32_t dseg_2_address;            /* Data segment 2 address. */
-    uint32_t dseg_2_length;             /* Data segment 2 length. */
-    uint32_t dseg_3_address;            /* Data segment 3 address. */
-    uint32_t dseg_3_length;             /* Data segment 3 length. */
-    uint32_t dseg_4_address;            /* Data segment 4 address. */
-    uint32_t dseg_4_length;             /* Data segment 4 length. */
-    uint32_t dseg_5_address;            /* Data segment 5 address. */
-    uint32_t dseg_5_length;             /* Data segment 5 length. */
-    uint32_t dseg_6_address;            /* Data segment 6 address. */
-    uint32_t dseg_6_length;             /* Data segment 6 length. */
-}cont_entry_t;
+typedef struct {
+	uint8_t entry_type;		/* Entry type. */
+#define CONTINUE_TYPE   2		/* Continuation entry. */
+	uint8_t entry_count;		/* Entry count. */
+	uint8_t sys_define;		/* System defined. */
+	uint8_t entry_status;		/* Entry Status. */
+	uint32_t reserved;		/* Reserved */
+	uint32_t dseg_0_address;	/* Data segment 0 address. */
+	uint32_t dseg_0_length;		/* Data segment 0 length. */
+	uint32_t dseg_1_address;	/* Data segment 1 address. */
+	uint32_t dseg_1_length;		/* Data segment 1 length. */
+	uint32_t dseg_2_address;	/* Data segment 2 address. */
+	uint32_t dseg_2_length;		/* Data segment 2 length. */
+	uint32_t dseg_3_address;	/* Data segment 3 address. */
+	uint32_t dseg_3_length;		/* Data segment 3 length. */
+	uint32_t dseg_4_address;	/* Data segment 4 address. */
+	uint32_t dseg_4_length;		/* Data segment 4 length. */
+	uint32_t dseg_5_address;	/* Data segment 5 address. */
+	uint32_t dseg_5_length;		/* Data segment 5 length. */
+	uint32_t dseg_6_address;	/* Data segment 6 address. */
+	uint32_t dseg_6_length;		/* Data segment 6 length. */
+} cont_entry_t;
 
 /*
  * ISP queue - status entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define STATUS_TYPE     3       /* Status entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-        #define RF_CONT         BIT_0   /* Continuation. */
-        #define RF_FULL         BIT_1   /* Full */
-        #define RF_BAD_HEADER   BIT_2   /* Bad header. */
-        #define RF_BAD_PAYLOAD  BIT_3   /* Bad payload. */
-    uint32_t handle;                    /* System handle. */
-    uint16_t scsi_status;               /* SCSI status. */
-    uint16_t comp_status;               /* Completion status. */
-    uint16_t state_flags;               /* State flags. */
-        #define SF_TRANSFER_CMPL BIT_14  /* Transfer Complete. */
-        #define SF_GOT_SENSE    BIT_13   /* Got Sense */
-        #define SF_GOT_STATUS    BIT_12   /* Got Status */
-        #define SF_TRANSFERRED_DATA BIT_11  /* Transferred data */
-        #define SF_SENT_CDB   BIT_10     /* Send CDB */
-        #define SF_GOT_TARGET  BIT_9   /*  */
-        #define SF_GOT_BUS     BIT_8   /*  */
-    uint16_t status_flags;              /* Status flags. */
-    uint16_t time;                      /* Time. */
-    uint16_t req_sense_length;          /* Request sense data length. */
-    uint32_t residual_length;           /* Residual transfer length. */
-    uint16_t reserved[4];
-    uint8_t  req_sense_data[32];        /* Request sense data. */
-}sts_entry_t, response_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define STATUS_TYPE     3	/* Status entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t sys_define;	/* System defined. */
+	uint8_t entry_status;	/* Entry Status. */
+#define RF_CONT         BIT_0	/* Continuation. */
+#define RF_FULL         BIT_1	/* Full */
+#define RF_BAD_HEADER   BIT_2	/* Bad header. */
+#define RF_BAD_PAYLOAD  BIT_3	/* Bad payload. */
+	uint32_t handle;	/* System handle. */
+	uint16_t scsi_status;	/* SCSI status. */
+	uint16_t comp_status;	/* Completion status. */
+	uint16_t state_flags;	/* State flags. */
+#define SF_TRANSFER_CMPL BIT_14	/* Transfer Complete. */
+#define SF_GOT_SENSE    BIT_13	/* Got Sense */
+#define SF_GOT_STATUS    BIT_12	/* Got Status */
+#define SF_TRANSFERRED_DATA BIT_11	/* Transferred data */
+#define SF_SENT_CDB   BIT_10	/* Send CDB */
+#define SF_GOT_TARGET  BIT_9	/*  */
+#define SF_GOT_BUS     BIT_8	/*  */
+	uint16_t status_flags;	/* Status flags. */
+	uint16_t time;		/* Time. */
+	uint16_t req_sense_length;	/* Request sense data length. */
+	uint32_t residual_length;	/* Residual transfer length. */
+	uint16_t reserved[4];
+	uint8_t req_sense_data[32];	/* Request sense data. */
+} sts_entry_t, response_t;
 
 /*
  * ISP queue - marker entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define MARKER_TYPE     4       /* Marker entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved;
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  target;                    /* SCSI ID */
-    uint8_t  modifier;                  /* Modifier (7-0). */
-        #define MK_SYNC_ID_LUN      0   /* Synchronize ID/LUN */
-        #define MK_SYNC_ID          1   /* Synchronize ID */
-        #define MK_SYNC_ALL         2   /* Synchronize all ID/LUN */
-    uint8_t  reserved_1[53];
-}mrk_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define MARKER_TYPE     4	/* Marker entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t sys_define;	/* System defined. */
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved;
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t target;		/* SCSI ID */
+	uint8_t modifier;	/* Modifier (7-0). */
+#define MK_SYNC_ID_LUN      0	/* Synchronize ID/LUN */
+#define MK_SYNC_ID          1	/* Synchronize ID */
+#define MK_SYNC_ALL         2	/* Synchronize all ID/LUN */
+	uint8_t reserved_1[53];
+} mrk_entry_t;
 
 /*
  * ISP queue - extended command entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define EXTENDED_CMD_TYPE  5    /* Extended command entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t handle;                    /* System handle. */
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  target;                    /* SCSI ID */
-    uint16_t cdb_len;                   /* SCSI command length. */
-    uint16_t control_flags;             /* Control flags. */
-    uint16_t reserved;
-    uint16_t timeout;                   /* Command timeout. */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint8_t  scsi_cdb[88];              /* SCSI command words. */
-}ecmd_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define EXTENDED_CMD_TYPE  5	/* Extended command entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t sys_define;	/* System defined. */
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t handle;	/* System handle. */
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t target;		/* SCSI ID */
+	uint16_t cdb_len;	/* SCSI command length. */
+	uint16_t control_flags;	/* Control flags. */
+	uint16_t reserved;
+	uint16_t timeout;	/* Command timeout. */
+	uint16_t dseg_count;	/* Data segment count. */
+	uint8_t scsi_cdb[88];	/* SCSI command words. */
+} ecmd_entry_t;
 
 /*
  * ISP queue - 64-Bit addressing, command entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define COMMAND_A64_TYPE 9      /* Command A64 entry */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t handle;                    /* System handle. */
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  target;                    /* SCSI ID */
-    uint16_t cdb_len;                   /* SCSI command length. */
-    uint16_t control_flags;             /* Control flags. */
-    uint16_t reserved;
-    uint16_t timeout;                   /* Command timeout. */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint8_t  scsi_cdb[MAX_CMDSZ];       /* SCSI command words. */
-    uint32_t reserved_1[2];             /* unused */
-    uint32_t dseg_0_address[2];         /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address[2];         /* Data segment 1 address. */
-    uint32_t dseg_1_length;             /* Data segment 1 length. */
-}cmd_a64_entry_t, request_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define COMMAND_A64_TYPE 9	/* Command A64 entry */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t sys_define;	/* System defined. */
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t handle;	/* System handle. */
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t target;		/* SCSI ID */
+	uint16_t cdb_len;	/* SCSI command length. */
+	uint16_t control_flags;	/* Control flags. */
+	uint16_t reserved;
+	uint16_t timeout;	/* Command timeout. */
+	uint16_t dseg_count;	/* Data segment count. */
+	uint8_t scsi_cdb[MAX_CMDSZ];	/* SCSI command words. */
+	uint32_t reserved_1[2];	/* unused */
+	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
+	uint32_t dseg_0_length;	/* Data segment 0 length. */
+	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
+	uint32_t dseg_1_length;	/* Data segment 1 length. */
+} cmd_a64_entry_t, request_t;
 
 /*
  * ISP queue - 64-Bit addressing, continuation entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define CONTINUE_A64_TYPE 0xA   /* Continuation A64 entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  sys_define;                /* System defined. */
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t dseg_0_address[2];         /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address[2];         /* Data segment 1 address. */
-    uint32_t dseg_1_length;             /* Data segment 1 length. */
-    uint32_t dseg_2_address[2];         /* Data segment 2 address. */
-    uint32_t dseg_2_length;             /* Data segment 2 length. */
-    uint32_t dseg_3_address[2];         /* Data segment 3 address. */
-    uint32_t dseg_3_length;             /* Data segment 3 length. */
-    uint32_t dseg_4_address[2];         /* Data segment 4 address. */
-    uint32_t dseg_4_length;             /* Data segment 4 length. */
-}cont_a64_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define CONTINUE_A64_TYPE 0xA	/* Continuation A64 entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t sys_define;	/* System defined. */
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
+	uint32_t dseg_0_length;	/* Data segment 0 length. */
+	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
+	uint32_t dseg_1_length;	/* Data segment 1 length. */
+	uint32_t dseg_2_address[2];	/* Data segment 2 address. */
+	uint32_t dseg_2_length;	/* Data segment 2 length. */
+	uint32_t dseg_3_address[2];	/* Data segment 3 address. */
+	uint32_t dseg_3_length;	/* Data segment 3 length. */
+	uint32_t dseg_4_address[2];	/* Data segment 4 address. */
+	uint32_t dseg_4_length;	/* Data segment 4 length. */
+} cont_a64_entry_t;
 
 /*
  * ISP queue - enable LUN entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define ENABLE_LUN_TYPE 0xB     /* Enable LUN entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status not used. */
-    uint32_t reserved_2;
-    uint16_t lun;                       /* Bit 15 is bus number. */
-    uint16_t reserved_4;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  reserved_5;
-    uint8_t  command_count;             /* Number of ATIOs allocated. */
-    uint8_t  immed_notify_count;        /* Number of Immediate Notify */
-                                        /* entries allocated. */
-    uint8_t  group_6_length;            /* SCSI CDB length for group 6 */
-                                        /* commands (2-26). */
-    uint8_t  group_7_length;            /* SCSI CDB length for group 7 */
-                                        /* commands (2-26). */
-    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
-    uint16_t reserved_6[20];
-}elun_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define ENABLE_LUN_TYPE 0xB	/* Enable LUN entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status not used. */
+	uint32_t reserved_2;
+	uint16_t lun;		/* Bit 15 is bus number. */
+	uint16_t reserved_4;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t reserved_5;
+	uint8_t command_count;	/* Number of ATIOs allocated. */
+	uint8_t immed_notify_count;	/* Number of Immediate Notify */
+	/* entries allocated. */
+	uint8_t group_6_length;	/* SCSI CDB length for group 6 */
+	/* commands (2-26). */
+	uint8_t group_7_length;	/* SCSI CDB length for group 7 */
+	/* commands (2-26). */
+	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
+	uint16_t reserved_6[20];
+} elun_entry_t;
 
 /*
  * ISP queue - modify LUN entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define MODIFY_LUN_TYPE 0xC     /* Modify LUN entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  reserved_3;
-    uint8_t  operators;
-    uint8_t  reserved_4;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  reserved_5;
-    uint8_t  command_count;             /* Number of ATIOs allocated. */
-    uint8_t  immed_notify_count;        /* Number of Immediate Notify */
-                                        /* entries allocated. */
-    uint16_t reserved_6;
-    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
-    uint16_t reserved_7[20];
-}modify_lun_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define MODIFY_LUN_TYPE 0xC	/* Modify LUN entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t reserved_3;
+	uint8_t operators;
+	uint8_t reserved_4;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t reserved_5;
+	uint8_t command_count;	/* Number of ATIOs allocated. */
+	uint8_t immed_notify_count;	/* Number of Immediate Notify */
+	/* entries allocated. */
+	uint16_t reserved_6;
+	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
+	uint16_t reserved_7[20];
+} modify_lun_entry_t;
 
 /*
  * ISP queue - immediate notify entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define IMMED_NOTIFY_TYPE 0xD   /* Immediate notify entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;
-    uint8_t  initiator_id;
-    uint8_t  reserved_3;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  reserved_4;
-    uint8_t  tag_value;                 /* Received queue tag message value */
-    uint8_t  tag_type;                  /* Received queue tag message type */
-                                        /* entries allocated. */
-    uint16_t seq_id;
-    uint8_t  scsi_msg[8];               /* SCSI message not handled by ISP */
-    uint16_t reserved_5[8];
-    uint8_t  sense_data[18];
-}notify_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define IMMED_NOTIFY_TYPE 0xD	/* Immediate notify entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;
+	uint8_t initiator_id;
+	uint8_t reserved_3;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t reserved_4;
+	uint8_t tag_value;	/* Received queue tag message value */
+	uint8_t tag_type;	/* Received queue tag message type */
+	/* entries allocated. */
+	uint16_t seq_id;
+	uint8_t scsi_msg[8];	/* SCSI message not handled by ISP */
+	uint16_t reserved_5[8];
+	uint8_t sense_data[18];
+} notify_entry_t;
 
 /*
  * ISP queue - notify acknowledge entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define NOTIFY_ACK_TYPE 0xE     /* Notify acknowledge entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;
-    uint8_t  initiator_id;
-    uint8_t  reserved_3;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  event;
-    uint16_t seq_id;
-    uint16_t reserved_4[22];
-}nack_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define NOTIFY_ACK_TYPE 0xE	/* Notify acknowledge entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;
+	uint8_t initiator_id;
+	uint8_t reserved_3;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t event;
+	uint16_t seq_id;
+	uint16_t reserved_4[22];
+} nack_entry_t;
 
 /*
  * ISP queue - Accept Target I/O (ATIO) entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define ACCEPT_TGT_IO_TYPE 6    /* Accept target I/O entry. */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;
-    uint8_t  initiator_id;
-    uint8_t  cdb_len;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  scsi_status;
-    uint8_t  tag_value;                 /* Received queue tag message value */
-    uint8_t  tag_type;                  /* Received queue tag message type */
-    uint8_t  cdb[26];
-    uint8_t  sense_data[18];
-}atio_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define ACCEPT_TGT_IO_TYPE 6	/* Accept target I/O entry. */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;
+	uint8_t initiator_id;
+	uint8_t cdb_len;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t scsi_status;
+	uint8_t tag_value;	/* Received queue tag message value */
+	uint8_t tag_type;	/* Received queue tag message type */
+	uint8_t cdb[26];
+	uint8_t sense_data[18];
+} atio_entry_t;
 
 /*
  * ISP queue - Continue Target I/O (CTIO) entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define CONTINUE_TGT_IO_TYPE 7  /* CTIO entry */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  initiator_id;
-    uint8_t  reserved_3;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  scsi_status;
-    uint8_t  tag_value;                 /* Received queue tag message value */
-    uint8_t  tag_type;                  /* Received queue tag message type */
-    uint32_t transfer_length;
-    uint32_t residual;
-    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint32_t dseg_0_address;            /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address;            /* Data segment 1 address. */
-    uint32_t dseg_1_length;             /* Data segment 1 length. */
-    uint32_t dseg_2_address;            /* Data segment 2 address. */
-    uint32_t dseg_2_length;             /* Data segment 2 length. */
-    uint32_t dseg_3_address;            /* Data segment 3 address. */
-    uint32_t dseg_3_length;             /* Data segment 3 length. */
-}ctio_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define CONTINUE_TGT_IO_TYPE 7	/* CTIO entry */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t initiator_id;
+	uint8_t reserved_3;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t scsi_status;
+	uint8_t tag_value;	/* Received queue tag message value */
+	uint8_t tag_type;	/* Received queue tag message type */
+	uint32_t transfer_length;
+	uint32_t residual;
+	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
+	uint16_t dseg_count;	/* Data segment count. */
+	uint32_t dseg_0_address;	/* Data segment 0 address. */
+	uint32_t dseg_0_length;	/* Data segment 0 length. */
+	uint32_t dseg_1_address;	/* Data segment 1 address. */
+	uint32_t dseg_1_length;	/* Data segment 1 length. */
+	uint32_t dseg_2_address;	/* Data segment 2 address. */
+	uint32_t dseg_2_length;	/* Data segment 2 length. */
+	uint32_t dseg_3_address;	/* Data segment 3 address. */
+	uint32_t dseg_3_length;	/* Data segment 3 length. */
+} ctio_entry_t;
 
 /*
  * ISP queue - CTIO returned entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define CTIO_RET_TYPE   7       /* CTIO return entry */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  initiator_id;
-    uint8_t  reserved_3;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  scsi_status;
-    uint8_t  tag_value;                 /* Received queue tag message value */
-    uint8_t  tag_type;                  /* Received queue tag message type */
-    uint32_t transfer_length;
-    uint32_t residual;
-    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint32_t dseg_0_address;            /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address;            /* Data segment 1 address. */
-    uint16_t dseg_1_length;             /* Data segment 1 length. */
-    uint8_t  sense_data[18];
-}ctio_ret_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define CTIO_RET_TYPE   7	/* CTIO return entry */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t initiator_id;
+	uint8_t reserved_3;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t scsi_status;
+	uint8_t tag_value;	/* Received queue tag message value */
+	uint8_t tag_type;	/* Received queue tag message type */
+	uint32_t transfer_length;
+	uint32_t residual;
+	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
+	uint16_t dseg_count;	/* Data segment count. */
+	uint32_t dseg_0_address;	/* Data segment 0 address. */
+	uint32_t dseg_0_length;	/* Data segment 0 length. */
+	uint32_t dseg_1_address;	/* Data segment 1 address. */
+	uint16_t dseg_1_length;	/* Data segment 1 length. */
+	uint8_t sense_data[18];
+} ctio_ret_entry_t;
 
 /*
  * ISP queue - CTIO A64 entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define CTIO_A64_TYPE 0xF       /* CTIO A64 entry */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  initiator_id;
-    uint8_t  reserved_3;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  scsi_status;
-    uint8_t  tag_value;                 /* Received queue tag message value */
-    uint8_t  tag_type;                  /* Received queue tag message type */
-    uint32_t transfer_length;
-    uint32_t residual;
-    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint32_t reserved_4[2];
-    uint32_t dseg_0_address[2];         /* Data segment 0 address. */
-    uint32_t dseg_0_length;             /* Data segment 0 length. */
-    uint32_t dseg_1_address[2];         /* Data segment 1 address. */
-    uint32_t dseg_1_length;             /* Data segment 1 length. */
-}ctio_a64_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define CTIO_A64_TYPE 0xF	/* CTIO A64 entry */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t initiator_id;
+	uint8_t reserved_3;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t scsi_status;
+	uint8_t tag_value;	/* Received queue tag message value */
+	uint8_t tag_type;	/* Received queue tag message type */
+	uint32_t transfer_length;
+	uint32_t residual;
+	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
+	uint16_t dseg_count;	/* Data segment count. */
+	uint32_t reserved_4[2];
+	uint32_t dseg_0_address[2];	/* Data segment 0 address. */
+	uint32_t dseg_0_length;	/* Data segment 0 length. */
+	uint32_t dseg_1_address[2];	/* Data segment 1 address. */
+	uint32_t dseg_1_length;	/* Data segment 1 length. */
+} ctio_a64_entry_t;
 
 /*
  * ISP queue - CTIO returned entry structure definition.
  */
-typedef struct
-{
-    uint8_t  entry_type;                /* Entry type. */
-        #define CTIO_A64_RET_TYPE 0xF   /* CTIO A64 returned entry */
-    uint8_t  entry_count;               /* Entry count. */
-    uint8_t  reserved_1;
-    uint8_t  entry_status;              /* Entry Status. */
-    uint32_t reserved_2;
-    uint8_t  lun;                       /* SCSI LUN */
-    uint8_t  initiator_id;
-    uint8_t  reserved_3;
-    uint8_t  target_id;
-    uint32_t option_flags;
-    uint8_t  status;
-    uint8_t  scsi_status;
-    uint8_t  tag_value;                 /* Received queue tag message value */
-    uint8_t  tag_type;                  /* Received queue tag message type */
-    uint32_t transfer_length;
-    uint32_t residual;
-    uint16_t timeout;                   /* 0 = 30 seconds, 0xFFFF = disable */
-    uint16_t dseg_count;                /* Data segment count. */
-    uint16_t reserved_4[7];
-    uint8_t  sense_data[18];
-}ctio_a64_ret_entry_t;
+typedef struct {
+	uint8_t entry_type;	/* Entry type. */
+#define CTIO_A64_RET_TYPE 0xF	/* CTIO A64 returned entry */
+	uint8_t entry_count;	/* Entry count. */
+	uint8_t reserved_1;
+	uint8_t entry_status;	/* Entry Status. */
+	uint32_t reserved_2;
+	uint8_t lun;		/* SCSI LUN */
+	uint8_t initiator_id;
+	uint8_t reserved_3;
+	uint8_t target_id;
+	uint32_t option_flags;
+	uint8_t status;
+	uint8_t scsi_status;
+	uint8_t tag_value;	/* Received queue tag message value */
+	uint8_t tag_type;	/* Received queue tag message type */
+	uint32_t transfer_length;
+	uint32_t residual;
+	uint16_t timeout;	/* 0 = 30 seconds, 0xFFFF = disable */
+	uint16_t dseg_count;	/* Data segment count. */
+	uint16_t reserved_4[7];
+	uint8_t sense_data[18];
+} ctio_a64_ret_entry_t;
 
 /*
  * ISP request and response queue entry sizes
  */
-#define RESPONSE_ENTRY_SIZE     (sizeof(response_t))
-#define REQUEST_ENTRY_SIZE      (sizeof(request_t))
+#define RESPONSE_ENTRY_SIZE	(sizeof(response_t))
+#define REQUEST_ENTRY_SIZE	(sizeof(request_t))
 
 /*
  * ISP status entry - completion status definitions.
  */
-#define CS_COMPLETE         0x0         /* No errors */
-#define CS_INCOMPLETE       0x1         /* Incomplete transfer of cmd. */
-#define CS_DMA              0x2         /* A DMA direction error. */
-#define CS_TRANSPORT        0x3         /* Transport error. */
-#define CS_RESET            0x4         /* SCSI bus reset occurred */
-#define CS_ABORTED          0x5         /* System aborted command. */
-#define CS_TIMEOUT          0x6         /* Timeout error. */
-#define CS_DATA_OVERRUN     0x7         /* Data overrun. */
-#define CS_COMMAND_OVERRUN  0x8         /* Command Overrun. */
-#define CS_STATUS_OVERRUN   0x9         /* Status Overrun. */
-#define CS_BAD_MSG          0xA         /* Bad msg after status phase. */
-#define CS_NO_MSG_OUT       0xB         /* No msg out after selection. */
-#define CS_EXTENDED_ID      0xC         /* Extended ID failed. */
-#define CS_IDE_MSG          0xD         /* Target rejected IDE msg. */
-#define CS_ABORT_MSG        0xE         /* Target rejected abort msg. */
-#define CS_REJECT_MSG       0xF         /* Target rejected reject msg. */
-#define CS_NOP_MSG          0x10        /* Target rejected NOP msg. */
-#define CS_PARITY_MSG       0x11        /* Target rejected parity msg. */
-#define CS_DEV_RESET_MSG    0x12        /* Target rejected dev rst msg. */
-#define CS_ID_MSG           0x13        /* Target rejected ID msg. */
-#define CS_FREE             0x14        /* Unexpected bus free. */
-#define CS_DATA_UNDERRUN    0x15        /* Data Underrun. */
-#define CS_TRANACTION_1     0x18        /* Transaction error 1 */
-#define CS_TRANACTION_2     0x19        /* Transaction error 2 */
-#define CS_TRANACTION_3     0x1a        /* Transaction error 3 */
-#define CS_INV_ENTRY_TYPE   0x1b        /* Invalid entry type */
-#define CS_DEV_QUEUE_FULL   0x1c        /* Device queue full */
-#define CS_PHASED_SKIPPED   0x1d        /* SCSI phase skipped */
-#define CS_ARS_FAILED       0x1e        /* ARS failed */
-#define CS_LVD_BUS_ERROR    0x21        /* LVD bus error */
-#define CS_BAD_PAYLOAD      0x80        /* Driver defined */
-#define CS_UNKNOWN          0x81        /* Driver defined */
-#define CS_RETRY            0x82        /* Driver defined */
+#define CS_COMPLETE         0x0	/* No errors */
+#define CS_INCOMPLETE       0x1	/* Incomplete transfer of cmd. */
+#define CS_DMA              0x2	/* A DMA direction error. */
+#define CS_TRANSPORT        0x3	/* Transport error. */
+#define CS_RESET            0x4	/* SCSI bus reset occurred */
+#define CS_ABORTED          0x5	/* System aborted command. */
+#define CS_TIMEOUT          0x6	/* Timeout error. */
+#define CS_DATA_OVERRUN     0x7	/* Data overrun. */
+#define CS_COMMAND_OVERRUN  0x8	/* Command Overrun. */
+#define CS_STATUS_OVERRUN   0x9	/* Status Overrun. */
+#define CS_BAD_MSG          0xA	/* Bad msg after status phase. */
+#define CS_NO_MSG_OUT       0xB	/* No msg out after selection. */
+#define CS_EXTENDED_ID      0xC	/* Extended ID failed. */
+#define CS_IDE_MSG          0xD	/* Target rejected IDE msg. */
+#define CS_ABORT_MSG        0xE	/* Target rejected abort msg. */
+#define CS_REJECT_MSG       0xF	/* Target rejected reject msg. */
+#define CS_NOP_MSG          0x10	/* Target rejected NOP msg. */
+#define CS_PARITY_MSG       0x11	/* Target rejected parity msg. */
+#define CS_DEV_RESET_MSG    0x12	/* Target rejected dev rst msg. */
+#define CS_ID_MSG           0x13	/* Target rejected ID msg. */
+#define CS_FREE             0x14	/* Unexpected bus free. */
+#define CS_DATA_UNDERRUN    0x15	/* Data Underrun. */
+#define CS_TRANACTION_1     0x18	/* Transaction error 1 */
+#define CS_TRANACTION_2     0x19	/* Transaction error 2 */
+#define CS_TRANACTION_3     0x1a	/* Transaction error 3 */
+#define CS_INV_ENTRY_TYPE   0x1b	/* Invalid entry type */
+#define CS_DEV_QUEUE_FULL   0x1c	/* Device queue full */
+#define CS_PHASED_SKIPPED   0x1d	/* SCSI phase skipped */
+#define CS_ARS_FAILED       0x1e	/* ARS failed */
+#define CS_LVD_BUS_ERROR    0x21	/* LVD bus error */
+#define CS_BAD_PAYLOAD      0x80	/* Driver defined */
+#define CS_UNKNOWN          0x81	/* Driver defined */
+#define CS_RETRY            0x82	/* Driver defined */
 
 /*
  * ISP status entry - SCSI status byte bit definitions.
@@ -1454,256 +1151,183 @@
 /*
  * ISP target entries - Option flags bit definitions.
  */
-#define OF_ENABLE_TAG       BIT_1       /* Tagged queue action enable */
-#define OF_DATA_IN          BIT_6       /* Data in to initiator */
-                                        /*  (data from target to initiator) */
-#define OF_DATA_OUT         BIT_7       /* Data out from initiator */
-                                        /*  (data from initiator to target) */
+#define OF_ENABLE_TAG       BIT_1	/* Tagged queue action enable */
+#define OF_DATA_IN          BIT_6	/* Data in to initiator */
+					/*  (data from target to initiator) */
+#define OF_DATA_OUT         BIT_7	/* Data out from initiator */
+					/*  (data from initiator to target) */
 #define OF_NO_DATA          (BIT_7 | BIT_6)
-#define OF_DISC_DISABLED    BIT_15      /* Disconnects disabled */
-#define OF_DISABLE_SDP      BIT_24      /* Disable sending save data ptr */
-#define OF_SEND_RDP         BIT_26      /* Send restore data pointers msg */
-#define OF_FORCE_DISC       BIT_30      /* Disconnects mandatory */
-#define OF_SSTS             BIT_31      /* Send SCSI status */
+#define OF_DISC_DISABLED    BIT_15	/* Disconnects disabled */
+#define OF_DISABLE_SDP      BIT_24	/* Disable sending save data ptr */
+#define OF_SEND_RDP         BIT_26	/* Send restore data pointers msg */
+#define OF_FORCE_DISC       BIT_30	/* Disconnects mandatory */
+#define OF_SSTS             BIT_31	/* Send SCSI status */
 
 #if QL1280_TARGET_MODE_SUPPORT
 /*
  * Target Read/Write buffer structure.
  */
-#define TARGET_DATA_OFFSET  4
-#define TARGET_DATA_SIZE    0x2000      /* 8K */
-#define TARGET_INQ_OFFSET   (TARGET_DATA_OFFSET + TARGET_DATA_SIZE)
-#define TARGET_SENSE_SIZE   18
-#define TARGET_BUF_SIZE     36
-
-typedef struct
-{
-    uint8_t         hdr[4];
-    uint8_t         data[TARGET_DATA_SIZE];
-    struct ident    inq;
-}tgt_t;
+#define TARGET_DATA_OFFSET	4
+#define TARGET_DATA_SIZE	0x2000	/* 8K */
+#define TARGET_INQ_OFFSET	(TARGET_DATA_OFFSET + TARGET_DATA_SIZE)
+#define TARGET_SENSE_SIZE	18
+#define TARGET_BUF_SIZE		36
+
+typedef struct {
+	uint8_t hdr[4];
+	uint8_t data[TARGET_DATA_SIZE];
+	struct ident inq;
+} tgt_t;
 #endif
 
 /*
  * BUS parameters/settings structure
  */
-typedef struct
-{
-    uint8_t     id;                    /* Host adapter SCSI id */
-    uint8_t     bus_reset_delay;       /* SCSI bus reset delay. */
-    uint8_t     failed_reset_count;    /* number of time reset failed */
-	uint8_t     unused;
-    uint16_t    device_enables;        /* Device enable bits. */
-    uint16_t    lun_disables;          /* LUN disable bits. */
-    uint16_t    qtag_enables;          /* Tag queue enables. */
-    uint16_t    hiwat;                 /* High water mark per device. */
-    uint8_t     reset_marker       :1;
-    uint8_t     disable_scsi_reset :1;
-    uint8_t     scsi_bus_dead      :1; /* SCSI Bus is Dead, when 5 back to back resets failed */
+typedef struct {
+	uint8_t id;		/* Host adapter SCSI id */
+	uint8_t bus_reset_delay;	/* SCSI bus reset delay. */
+	uint8_t failed_reset_count;	/* number of time reset failed */
+	uint8_t unused;
+	uint16_t device_enables;	/* Device enable bits. */
+	uint16_t lun_disables;	/* LUN disable bits. */
+	uint16_t qtag_enables;	/* Tag queue enables. */
+	uint16_t hiwat;		/* High water mark per device. */
+	uint8_t reset_marker:1;
+	uint8_t disable_scsi_reset:1;
+	uint8_t scsi_bus_dead:1;	/* SCSI Bus is Dead, when 5 back to back resets failed */
 
-}bus_param_t;
+} bus_param_t;
 
 /*
  * Linux Host Adapter structure
  */
-typedef struct scsi_qla_host
-{
-    /* Linux adapter configuration data */
-    struct Scsi_Host *host;             /* pointer to host data */
-    struct scsi_qla_host   *next;
-    device_reg_t     *iobase;           /* Base Memory-mapped I/O address */
-    uint8_t          pci_bus;
-    uint8_t          pci_device_fn;
-    uint8_t          devnum;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
-    struct pci_dev *pdev;
-#endif
-    volatile unsigned char  *mmpbase;      /* memory mapped address */
-    unsigned long            host_no;
-    unsigned long            instance;
-    uint8_t           revision;
-    uint8_t           ports;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
-    spinlock_t               spin_lock;
-#endif
-    volatile unsigned char   cpu_lock_count[NR_CPUS];
-    unsigned long            actthreads;
-    unsigned long            qthreads;
-    unsigned long            isr_count;        /* Interrupt count */
-    unsigned long            spurious_int;
-
-    uint32_t           device_id;
+struct scsi_qla_host {
+	/* Linux adapter configuration data */
+	struct Scsi_Host *host;	/* pointer to host data */
+	struct scsi_qla_host *next;
+	struct device_reg *iobase;	/* Base Memory-mapped I/O address */
+	uint8_t pci_bus;
+	uint8_t pci_device_fn;
+	uint8_t devnum;
+	struct pci_dev *pdev;
+
+	volatile unsigned char *mmpbase;	/* memory mapped address */
+	unsigned long host_no;
+	unsigned long instance;
+	uint8_t revision;
+	uint8_t ports;
+
+	unsigned long actthreads;
+	unsigned long qthreads;
+	unsigned long isr_count;	/* Interrupt count */
+	unsigned long spurious_int;
+
+	uint32_t device_id;
+
+	/* Outstandings ISP commands. */
+	srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS];
+
+	/* BUS configuration data */
+	bus_param_t bus_settings[MAX_BUSES];
 
-    /* Outstandings ISP commands. */
-    srb_t           *outstanding_cmds[MAX_OUTSTANDING_COMMANDS];
+	/* Device LUN queues. */
+	struct scsi_lu *dev[MAX_EQ];	/* Logical unit queues */
 
-    /* BUS configuration data */
-    bus_param_t bus_settings[MAX_BUSES];
+	/* bottom half run queue */
+	struct tq_struct run_qla_bh;
 
-    /* Device LUN queues. */
-    scsi_lu_t       *dev[MAX_EQ];      /* Logical unit queues */
+	/* Received ISP mailbox data. */
+	volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
 
 #ifdef UNUSED
-    /* Interrupt lock, and data */
-    uint8_t          intr_lock;         /* Lock for interrupt locking */
+	struct timer_list dev_timer[MAX_TARGETS];
 #endif
 
-    /* bottom half run queue */
-    struct tq_struct run_qla_bh;
-
-    /* Received ISP mailbox data. */
-    volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
-
-#ifdef UNUSED
-    /* ISP ring lock, rings, and indexes */
-    uint8_t          ring_lock;         /* ISP ring lock */
-    struct timer_list        dev_timer[MAX_TARGETS];
-#endif
-
-    request_t       req[REQUEST_ENTRY_CNT+1];
-    response_t      res[RESPONSE_ENTRY_CNT+1];
-    unsigned long   request_dma;        /* Physical address. */
-    request_t       *request_ring;      /* Base virtual address */
-    request_t       *request_ring_ptr;  /* Current address. */
-    uint16_t        req_ring_index;     /* Current index. */
-    uint16_t        req_q_cnt;          /* Number of available entries. */
-
-    unsigned long   response_dma;       /* Physical address. */
-    response_t      *response_ring;     /* Base virtual address */
-    response_t      *response_ring_ptr; /* Current address. */
-    uint16_t        rsp_ring_index;     /* Current index. */
+	dma_addr_t request_dma;		/* Physical Address */
+	request_t *request_ring;	/* Base virtual address */
+	request_t *request_ring_ptr;	/* Current address. */
+	uint16_t req_ring_index;	/* Current index. */
+	uint16_t req_q_cnt;		/* Number of available entries. */
+
+	dma_addr_t response_dma;	/* Physical address. */
+	response_t *response_ring;	/* Base virtual address */
+	response_t *response_ring_ptr;	/* Current address. */
+	uint16_t rsp_ring_index;	/* Current index. */
 
 #if QL1280_TARGET_MODE_SUPPORT
-    /* Target buffer and sense data. */
-    uint32_t        tbuf_dma;           /* Physical address. */
-    tgt_t           *tbuf;
-    uint32_t        tsense_dma;         /* Physical address. */
-    uint8_t         *tsense;
+	/* Target buffer and sense data. */
+	dma_addr_t tbuf_dma;	/* Physical address. */
+	dma_addr_t tsense_dma;	/* Physical address. */
+	tgt_t *tbuf;
+	uint8_t *tsense;
 #endif
 
-#if  WATCHDOGTIMER
-    /* Watchdog queue, lock and total timer */
-    uint8_t          watchdog_q_lock;   /* Lock for watchdog queue */
-    srb_t           *wdg_q_first;       /* First job on watchdog queue */
-    srb_t           *wdg_q_last;        /* Last job on watchdog queue */
-    uint32_t         total_timeout;     /* Total timeout (quantum count) */
-    uint32_t         watchdogactive;
+#if WATCHDOGTIMER
+	/* Watchdog queue, lock and total timer */
+	uint8_t watchdog_q_lock;	/* Lock for watchdog queue */
+	srb_t *wdg_q_first;	/* First job on watchdog queue */
+	srb_t *wdg_q_last;	/* Last job on watchdog queue */
+	uint32_t total_timeout;	/* Total timeout (quantum count) */
+	uint32_t watchdogactive;
 #endif
 
-    srb_t           *done_q_first;       /* First job on done queue */
-    srb_t           *done_q_last;        /* Last job on done queue */
+	srb_t *done_q_first;	/* First job on done queue */
+	srb_t *done_q_last;	/* Last job on done queue */
 
-    volatile struct
-    {
-        uint32_t     watchdog_enabled        :1;   /* 0 */
-        uint32_t     mbox_int                :1;   /* 1 */
-        uint32_t     mbox_busy               :1;   /* 2 */
-        uint32_t     online                  :1;   /* 3 */
-        uint32_t     reset_marker            :1;   /* 4 */
-        uint32_t     isp_abort_needed        :1;   /* 5 */
-        uint32_t     pci_64bit_slot          :1;   /* 6 */
-        uint32_t     disable_host_adapter    :1;   /* 7 */
-        uint32_t     reset_active            :1;   /* 8 */
-        uint32_t     abort_isp_active        :1;   /* 9 */
-        uint32_t     disable_risc_code_load  :1;   /* 10 */
-        uint32_t     enable_64bit_addressing :1;   /* 11 */
-#define QLA1280_IN_ISR_BIT      12
-        uint32_t     in_isr                  :1;   /* 12 */
-        uint32_t     in_abort                :1;   /* 13 */
-        uint32_t     in_reset                :1;   /* 14 */
-       uint32_t     dpc                     :1;   /* 15 */
-       uint32_t     dpc_sched               :1;   /* 16 */
-       uint32_t     interrupts_on               :1;   /* 17 */
-    }flags;
+	volatile struct {
+		uint32_t mbox_int:1;	/* 0 */
+		uint32_t mbox_busy:1;	/* 1 */
+		uint32_t online:1;	/* 2 */
+		uint32_t reset_marker:1;	/* 3 */
+		uint32_t isp_abort_needed:1;	/* 4 */
+		uint32_t disable_host_adapter:1;	/* 5 */
+		uint32_t reset_active:1;	/* 6 */
+		uint32_t abort_isp_active:1;	/* 7 */
+		uint32_t disable_risc_code_load:1;	/* 8 */
+		uint32_t enable_64bit_addressing:1;	/* 9 */
+		uint32_t in_reset:1;	/* 10 */
+		uint32_t ints_enabled:1;
+	} flags;
+
+	/* needed holders for PCI ordered list of hosts */
+	unsigned long io_port;
+	uint32_t irq;
 
-}scsi_qla_host_t;
+};
 
 /*
  * Macros to help code, maintain, etc.
  */
-#define SUBDEV(b, t, l)  ( (b << (MAX_T_BITS + MAX_L_BITS)) | (t << MAX_L_BITS) | l)
-#define LU_Q(ha, b, t, l)  (ha->dev[SUBDEV(b, t, l)])
+#define SUBDEV(b, t, l)		((b << (MAX_T_BITS + MAX_L_BITS)) | (t << MAX_L_BITS) | l)
+#define LU_Q(ha, b, t, l)	(ha->dev[SUBDEV(b, t, l)])
 
-/*
- * Locking Macro Definitions
- *
- * LOCK/UNLOCK definitions are lock/unlock primitives for multi-processor
- * or spl/splx for uniprocessor.
- */
-#define QLA1280_HIER   HBA_HIER_BASE  /* Locking hierarchy base for hba */
+#endif				/* HOSTS_C */
 
-#define QLA1280_WATCHDOG_Q_LOCK(ha, p)   
-#define QLA1280_WATCHDOG_Q_UNLOCK(ha, p) 
-
-#define QLA1280_SCSILU_LOCK(q)  
-#define QLA1280_SCSILU_UNLOCK(q) 
-
-#define QLA1280_INTR_LOCK(ha)
-#define QLA1280_INTR_UNLOCK(ha)     
-
-#define QLA1280_RING_LOCK(ha)  
-#define QLA1280_RING_UNLOCK(ha)   
-
-#if defined(__cplusplus)
-}
-#endif
 /*
  *  Linux - SCSI Driver Interface Function Prototypes.
  */
-int qla1280_proc_info ( char *, char **, off_t, int, int, int);
-const char * qla1280_info(struct Scsi_Host *host);
+int qla1280_proc_info(char *, char **, off_t, int, int, int);
+const char *qla1280_info(struct Scsi_Host *host);
 int qla1280_detect(Scsi_Host_Template *);
 int qla1280_release(struct Scsi_Host *);
-const char * qla1280_info(struct Scsi_Host *);
-int qla1280_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int qla1280_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
 int qla1280_abort(Scsi_Cmnd *);
 int qla1280_reset(Scsi_Cmnd *, unsigned int);
 int qla1280_biosparam(Disk *, kdev_t, int[]);
 void qla1280_intr_handler(int, void *, struct pt_regs *);
 void qla1280_setup(char *s, int *dummy);
-#if defined(__386__)
-#  define QLA1280_BIOSPARAM  qla1280_biosparam
-#else
-#  define QLA1280_BIOSPARAM  NULL
-#endif
 
 /*
- * Scsi_Host_template (see hosts.h) 
+ * Scsi_Host_template (see hosts.h)
  * Device driver Interfaces to mid-level SCSI driver.
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
-/* This interface is now obsolete !!! */ 
-#define QLA1280_LINUX_TEMPLATE {		                 \
-        next:           NULL,                                    \
-        usage_count:    NULL,                                    \
-	proc_dir:		NULL,          	                 \
-	proc_info:		NULL,	                         \
-	name:			"Qlogic ISP 1280",               \
-	detect:			qla1280_detect,	                 \
-	release:		qla1280_release,                 \
-	info:			qla1280_info,	                 \
-        command:        NULL,                                    \
-	queuecommand:	qla1280_queuecommand,	                 \
-	abort:			qla1280_abort,	                 \
-	reset:			qla1280_reset,	                 \
-        slave_attach:   NULL,                                    \
-	bios_param:		QLA1280_BIOSPARAM,               \
-	can_queue:		255, /* MAX_OUTSTANDING_COMMANDS */   \
-	this_id:		-1,  /* scsi id of host adapter */        \
-	sg_tablesize:	SG_ALL,	 \
-	cmd_per_lun:	3,	  /* max commands per lun */	       \
-	present:	    0,    /* number of 1280s present */	       \
-	unchecked_isa_dma: 0, /* no memeory DMA restrictions */    \
-	use_clustering:	ENABLE_CLUSTERING			               \
-}
-#else
 
-#define QLA1280_LINUX_TEMPLATE {		                 \
+#define QLA1280_LINUX_TEMPLATE {				\
 	next: NULL,						\
 	module: NULL,						\
 	proc_dir: NULL,						\
 	proc_info: qla1280_proc_info,				\
-	name:			"Qlogic ISP 1280\1080",               \
+	name: "Qlogic ISP 1280/12160",				\
 	detect: qla1280_detect,					\
 	release: qla1280_release,				\
 	info: qla1280_info,					\
@@ -1715,20 +1339,19 @@
 	eh_device_reset_handler: NULL,				\
 	eh_bus_reset_handler: NULL,				\
 	eh_host_reset_handler: NULL,				\
+/*	use_new_eh_code: 0, */					\
 	abort: qla1280_abort,					\
 	reset: qla1280_reset,					\
 	slave_attach: NULL,					\
-	bios_param: QLA1280_BIOSPARAM,				\
+	bios_param: qla1280_biosparam,				\
 	can_queue: 255,		/* max simultaneous cmds      */\
 	this_id: -1,		/* scsi id of host adapter    */\
 	sg_tablesize: SG_ALL,	/* max scatter-gather cmds    */\
 	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
-	present: 0,		/* number of 7xxx's present   */\
+	present: 0,		/* number of 1280's present   */\
 	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
 	use_clustering: ENABLE_CLUSTERING,			\
-	emulated: 0					        \
+	emulated: 0						\
 }
-#endif
-
 
-#endif /* _IO_HBA_QLA1280_H */
+#endif				/* _IO_HBA_QLA1280_H */
diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
--- a/drivers/scsi/scsi.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/scsi/scsi.c	Sun Apr 14 12:16:59 2002
@@ -2387,7 +2387,7 @@
 				       kdevname(SCpnt->request.rq_dev),
 				       SCpnt->request.sector,
 				       SCpnt->request.nr_sectors,
-				       SCpnt->request.current_nr_sectors,
+				       (long)SCpnt->request.current_nr_sectors,
 				       SCpnt->request.rq_status,
 				       SCpnt->use_sg,
 
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/scsi/sd.c	Sun Apr 14 12:16:56 2002
@@ -373,7 +373,7 @@
 
 	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
 				   nbuff,
-		   (SCpnt->request.cmd == WRITE) ? "writing" : "reading",
+		   (rq_data_dir(&SCpnt->request) == WRITE) ? "writing" : "reading",
 				 this_count, SCpnt->request.nr_sectors));
 
 	SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
--- a/drivers/scsi/sun3x_esp.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/scsi/sun3x_esp.c	Sun Apr 14 12:16:56 2002
@@ -376,3 +376,5 @@
 static Scsi_Host_Template driver_template = SCSI_SUN3X_ESP;
 
 #include "scsi_module.c"
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/scsi/tmscsim.c	Sun Apr 14 12:16:59 2002
@@ -2468,68 +2468,68 @@
  * '-' means no change
  *******************************************************************/
 
-static int dc390_scanf (char** p1, char** p2, int* var)
+static int dc390_scanf (char** buffer, char** pos, char** p0, int* var)
 {
-   *p2 = *p1;
-   *var = simple_strtoul (*p2, p1, 10);
-   if (*p2 == *p1) return -1;
-   *p1 = strtok (0, " \t\n:=,;.");
+   *p0 = *pos;
+   *var = simple_strtoul (*p0, pos, 10);
+   if (*p0 == *pos) return -1;
+   *pos = strsep (buffer, " \t\n:=,;.");
    return 0;
 };
 
-#define SCANF(p1, p2, var, min, max)		\
-if (dc390_scanf (&p1, &p2, &var)) goto einv;	\
+#define SCANF(buffer, pos, p0, var, min, max)		\
+if (dc390_scanf (&buffer, &pos, &p0, &var)) goto einv;	\
 else if (var<min || var>max) goto einv2
 
-static int dc390_yesno (char** p, char* var, char bmask)
+static int dc390_yesno (char** buffer, char** pos, char* var, char bmask)
 {
-   switch (**p)
+   switch (**pos)
      {
       case 'Y': *var |= bmask; break;
       case 'N': *var &= ~bmask; break;
       case '-': break;
       default: return -1;
      }
-   *p = strtok (0, " \t\n:=,;");
+   *pos = strsep (buffer, " \t\n:=,;");
    return 0;
 };
 
-#define YESNO(p, var, bmask)			\
-if (dc390_yesno (&p, &var, bmask)) goto einv;	\
+#define YESNO(buffer, pos, var, bmask)			\
+if (dc390_yesno (&buffer, &pos, &var, bmask)) goto einv;	\
 else dc390_updateDCB (pACB, pDCB);		\
 if (!p) goto ok
 
-static int dc390_search (char **p1, char **p2, char *var, char* txt, int max, int scale, char* ign)
+static int dc390_search (char** buffer, char** pos, char** p0, char* var, char* txt, int max, int scale, char* ign)
 {
    int dum;
-   if (! memcmp (*p1, txt, strlen(txt)))
+   if (! memcmp (*pos, txt, strlen(txt)))
      {
-	*p2 = strtok (0, " \t\n:=,;");
-	if (!*p2) return -1;
-	dum = simple_strtoul (*p2, p1, 10);
-	if (*p2 == *p1) return -1;
+	*p0 = strsep (buffer, " \t\n:=,;");
+	if (!*p0) return -1;
+	dum = simple_strtoul (*p0, pos, 10);
+	if (*p0 == *pos) return -1;
 	if (dum >= 0 && dum <= max) 
 	  { *var = (dum * 100) / scale; }
 	else return -2;
-	*p1 = strtok (0, " \t\n:=,;");
-	if (*ign && *p1 && strlen(*p1) >= strlen(ign) && 
-	    !(memcmp (*p1, ign, strlen(ign)))) 
-		*p1 = strtok (0, " \t\n:=,;");
+	*pos = strsep (buffer, " \t\n:=,;");
+	if (*ign && *pos && strlen(*pos) >= strlen(ign) && 
+	    !(memcmp (*pos, ign, strlen(ign)))) 
+		*pos = strsep (buffer, " \t\n:=,;");
 
      }
    return 0;
 };
 
-#define SEARCH(p1, p2, var, txt, max)						\
-if (dc390_search (&p1, &p2, (PUCHAR)(&var), txt, max, 100, "")) goto einv2;	\
+#define SEARCH(buffer, pos, p0, var, txt, max)						\
+if (dc390_search (&buffer, &pos, &p0, (PUCHAR)(&var), txt, max, 100, "")) goto einv2;	\
 else if (!p1) goto ok2
 
-#define SEARCH2(p1, p2, var, txt, max, scale)					\
-if (dc390_search (&p1, &p2, &var, txt, max, scale, "")) goto einv2; 		\
+#define SEARCH2(buffer, pos, p0, var, txt, max, scale)					\
+if (dc390_search (&buffer, &pos, &p0, &var, txt, max, scale, "")) goto einv2; 		\
 else if (!p1) goto ok2
 
-#define SEARCH3(p1, p2, var, txt, max, scale, ign)				\
-if (dc390_search (&p1, &p2, &var, txt, max, scale, ign)) goto einv2;		\
+#define SEARCH3(buffer, pos, &p0, var, txt, max, scale, ign)				\
+if (dc390_search (&buffer, &pos, p0, &var, txt, max, scale, ign)) goto einv2;		\
 else if (!p1) goto ok2
 
 
@@ -2565,12 +2565,9 @@
   while (*pos) 
     { if (*pos >='a' && *pos <= 'z') *pos = *pos + 'A' - 'a'; pos++; };
   
-  /* We should protect __strtok ! */
-  /* spin_lock (strtok_lock); */
-
   /* Remove WS */
-  pos = strtok (buffer, " \t:\n=,;");
-  if (!pos) goto ok;
+  pos = strsep (&buffer, " \t:\n=,;");
+  if (!*pos) goto ok;
    
  next:
   if (!memcmp (pos, "RESET", 5)) goto reset;
@@ -2586,10 +2583,10 @@
       int dev, id, lun; char* pdec;
       char olddevmode;
       
-      SCANF (pos, p0, dev, 0, pACB->DCBCnt-1);
-      if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
-      if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
-      if (!pos) goto einv;
+      SCANF (buffer, pos, p0, dev, 0, pACB->DCBCnt-1);
+      if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv;
+      if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv;
+      if (!*pos) goto einv;
       
       PARSEDEBUG(printk (KERN_INFO "DC390: config line %i %i %i:\"%s\"\n", dev, id, lun, prstr (pos, &buffer[length]));)
       pDCB = pACB->pLinkDCB;
@@ -2610,20 +2607,20 @@
       };
 	  
       olddevmode = pDCB->DevMode;
-      YESNO (pos, pDCB->DevMode, PARITY_CHK_);
+      YESNO (buffer, pos, pDCB->DevMode, PARITY_CHK_);
       needs_inquiry++;
-      YESNO (pos, pDCB->DevMode, SYNC_NEGO_);
+      YESNO (buffer, pos, pDCB->DevMode, SYNC_NEGO_);
       if ((olddevmode & SYNC_NEGO_) == (pDCB->DevMode & SYNC_NEGO_)) needs_inquiry--;
       needs_inquiry++;
-      YESNO (pos, pDCB->DevMode, EN_DISCONNECT_);
+      YESNO (buffer, pos, pDCB->DevMode, EN_DISCONNECT_);
       if ((olddevmode & EN_DISCONNECT_) == (pDCB->DevMode & EN_DISCONNECT_)) needs_inquiry--;
-      YESNO (pos, pDCB->DevMode, SEND_START_);
+      YESNO (buffer, pos, pDCB->DevMode, SEND_START_);
       needs_inquiry++;
-      YESNO (pos, pDCB->DevMode, TAG_QUEUEING_);
+      YESNO (buffer, pos, pDCB->DevMode, TAG_QUEUEING_);
       if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--;
 
       dc390_updateDCB (pACB, pDCB);
-      if (!pos) goto ok;
+      if (!*pos) goto ok;
        
       olddevmode = pDCB->NegoPeriod;
       /* Look for decimal point (Speed) */
@@ -2632,22 +2629,22 @@
       /* NegoPeriod */
       if (*pos != '-')
 	{
-	  SCANF (pos, p0, dum, 72, 800); 
+	  SCANF (buffer, pos, p0, dum, 72, 800); 
 	  pDCB->NegoPeriod = dum >> 2;
 	  if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
 	  if (!pos) goto ok;
-	  if (memcmp (pos, "NS", 2) == 0) pos = strtok (0, " \t\n:=,;.");
+	  if (memcmp (pos, "NS", 2) == 0) pos = strsep (*pos, " \t\n:=,;.");
 	}
-      else pos = strtok (0, " \t\n:=,;.");
-      if (!pos) goto ok;
+      else pos = strsep (*pos, " \t\n:=,;.");
+      if (!*pos) goto ok;
       
       /* Sync Speed in MHz */
       if (*pos != '-')
 	{
-	  SCANF (pos, p0, dum, 1, 13); 
+	  SCANF (buffer, pos, p0, dum, 1, 13); 
 	  pDCB->NegoPeriod = (1000/dum) >> 2;
 	  if (pDCB->NegoPeriod != olddevmode && !pos) needs_inquiry++;
-	  if (!pos) goto ok;
+	  if (!*pos) goto ok;
 	  /* decimal */
 	  if (pos-1 == pdec)
 	     {
@@ -2656,38 +2653,38 @@
 		for (; p0-pos > 1; p0--) dum /= 10;
 		pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2;
 		if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19;
-		pos = strtok (0, " \t\n:=,;");
-		if (!pos) goto ok;
+		pos = strsep (*pos, " \t\n:=,;");
+		if (!*pos) goto ok;
 	     };
-	  if (*pos == 'M') pos = strtok (0, " \t\n:=,;");
+	  if (*pos == 'M') pos = strsep (*pos, " \t\n:=,;");
 	  if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
 	}
-      else pos = strtok (0, " \t\n:=,;");
+      else pos = strsep (*pos, " \t\n:=,;");
       /* dc390_updateDCB (pACB, pDCB); */
-      if (!pos) goto ok;
+      if (!*pos) goto ok;
 
       olddevmode = pDCB->SyncOffset;
       /* SyncOffs */
       if (*pos != '-')
 	{
-	  SCANF (pos, p0, dum, 0, 0x0f); 
+	  SCANF (buffer, pos, p0, dum, 0, 0x0f); 
 	  pDCB->SyncOffset = dum;
 	  if (pDCB->SyncOffset > olddevmode) needs_inquiry++;
 	}
-      else pos = strtok (0, " \t\n:=,;");
-      if (!pos) goto ok;
+      else pos = strsep (*pos, " \t\n:=,;");
+      if (!*pos) goto ok;
       dc390_updateDCB (pACB, pDCB);
 
       //olddevmode = pDCB->MaxCommand;
       /* MaxCommand (Tags) */
       if (*pos != '-')
 	{
-	  SCANF (pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/);
+	  SCANF (buffer, pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/);
 	  if (pDCB->SyncMode & EN_TAG_QUEUEING)
 		pDCB->MaxCommand = dum;
 	  else printk (KERN_INFO "DC390: Can't set MaxCmd larger than one without Tag Queueing!\n");
 	}
-      else pos = strtok (0, " \t\n:=,;");
+      else pos = strsep (*pos, " \t\n:=,;");
 
     }
   else
@@ -2696,14 +2693,14 @@
       PARSEDEBUG(printk (KERN_INFO "DC390: chg adapt cfg \"%s\"\n", prstr (pos, &buffer[length]));)
       dum = GLITCH_TO_NS (pACB->glitch_cfg);
       /* Adapter setting */
-      SEARCH (pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); 
-      SEARCH (pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); 
-      SEARCH (pos, p0, newadaptid, "ADAPTERID", 7);
-      SEARCH (pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32);
-      SEARCH (pos, p0, pACB->ACBFlag, "ACBFLAG", 255);
-      SEARCH3 (pos, p0, dum, "GLITCHEATER", 40, 1000, "NS");
-      SEARCH3 (pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS");
-      SEARCH3 (pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S");
+      SEARCH (buffer, pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); 
+      SEARCH (buffer, pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); 
+      SEARCH (buffer, pos, p0, newadaptid, "ADAPTERID", 7);
+      SEARCH (buffer, pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32);
+      SEARCH (buffer, pos, p0, pACB->ACBFlag, "ACBFLAG", 255);
+      SEARCH3 (buffer, pos, p0, dum, "GLITCHEATER", 40, 1000, "NS");
+      SEARCH3 (buffer, pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS");
+      SEARCH3 (buffer, pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S");
     ok2:
       pACB->glitch_cfg = NS_TO_GLITCH (dum);
       if (pACB->sel_timeout < 60) pACB->sel_timeout = 60;
@@ -2719,10 +2716,9 @@
       // All devs should be INQUIRED now
       if (pos == p1) goto einv;
     }
-  if (pos) goto next;
+  if (*pos) goto next;
       
  ok:
-  /* spin_unlock (strtok_lock); */
   DC390_UNLOCK_ACB;
   if (needs_inquiry) 
      { dc390_updateDCB (pACB, pDCB); dc390_inquiry (pACB, pDCB); };
@@ -2732,7 +2728,6 @@
  einv2:
   pos = p0;
  einv:
-  /* spin_unlock (strtok_lock); */
   DC390_UNLOCK_ACB;
   DC390_UNLOCK_IO(pACB.pScsiHost);
   printk (KERN_WARNING "DC390: parse error near \"%s\"\n", (pos? pos: "NULL"));
@@ -2758,7 +2753,7 @@
 	
  inquiry:
      {
-	pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
+	pos = strsep (*pos, " \t\n.:;="); if (!*pos) goto einv;
 	dev = simple_strtoul (pos, &p0, 10);
 	if (dev >= pACB->DCBCnt) goto einv_dev;
 	for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
@@ -2772,7 +2767,7 @@
 
  remove:
      {
-	pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
+	pos = strsep (*pos, " \t\n.:;="); if (!*pos) goto einv;
 	dev = simple_strtoul (pos, &p0, 10);
 	if (dev >= pACB->DCBCnt) goto einv_dev;
 	for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
@@ -2788,9 +2783,9 @@
  add:
      {
 	int id, lun;
-	pos = strtok (0, " \t\n.:;=");
-	if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
-	if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
+	pos = strsep (*pos, " \t\n.:;=");
+	if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv;
+	if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv;
 	pDCB = dc390_findDCB (pACB, id, lun);
 	if (pDCB) { printk ("DC390: ADD: Device already existing\n"); goto einv; };
 	dc390_initDCB (pACB, &pDCB, id, lun);
@@ -2803,9 +2798,9 @@
  start:
      {
 	int id, lun;
-	pos = strtok (0, " \t\n.:;=");
-	if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
-	if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
+	pos = strsep (*pos, " \t\n.:;=");
+	if (*pos) { SCANF (buffer, pos, p0, id, 0, 7); } else goto einv;
+	if (*pos) { SCANF (buffer, pos, p0, lun, 0, 7); } else goto einv;
 	pDCB = dc390_findDCB (pACB, id, lun);
 	if (pDCB) printk ("DC390: SendStart: Device already existing ...\n");
 	else dc390_initDCB (pACB, &pDCB, id, lun);
diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
--- a/drivers/scsi/u14-34f.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/scsi/u14-34f.c	Sun Apr 14 12:16:57 2002
@@ -171,7 +171,7 @@
  *          Auto detects if U14F boards have an old firmware revision.
  *          Max number of scatter/gather lists set to 16 for all boards
  *          (most installation run fine using 33 sglists, while other
- *          has problems when using more then 16).
+ *          has problems when using more than 16).
  *
  *      16 Jan 1995 rev. 1.13 for linux 1.1.81
  *          Display a message if check_region detects a port address
@@ -279,7 +279,7 @@
  *
  *  For U34F boards the latest bios prom is 38008-002 (BIOS rev. 2.01),
  *  the latest firmware prom is 28008-006. Older firmware 28008-005 has
- *  problems when using more then 16 scatter/gather lists.
+ *  problems when using more than 16 scatter/gather lists.
  *
  *  The list of i/o ports to be probed can be totally replaced by the
  *  boot command line option: "u14-34f=port0,port1,port2,...", where the
diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c
--- a/drivers/tc/zs.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/tc/zs.c	Sun Apr 14 12:16:57 2002
@@ -1472,7 +1472,7 @@
 		schedule_timeout(char_time);
 		if (signal_pending(current))
 			break;
-		if (timeout && ((orig_jiffies + timeout) < jiffies))
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
 			break;
 	}
 	current->state = TASK_RUNNING;
diff -Nru a/drivers/usb/CDCEther.c b/drivers/usb/CDCEther.c
--- a/drivers/usb/CDCEther.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1365 +0,0 @@
-// Portions of this file taken from 
-// Petko Manolov - Petkan (petkan@dce.bg)
-// from his driver pegasus.c
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include <linux/module.h>
-#include "CDCEther.h"
-
-static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
-
-/* Take any CDC device, and sort it out in probe() */
-static struct usb_device_id CDCEther_ids[] = {
-	{ USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
-	{ } /* Terminating null entry */
-};
-
-/* 
- * module parameter that provides an alternate upper limit on the 
- * number of multicast filters we use, with a default to use all
- * the filters available to us. Note that the actual number used
- * is the lesser of this parameter and the number returned in the
- * descriptor for the particular device. See Table 41 of the CDC
- * spec for more info on the descriptor limit.
- */
-static int multicast_filter_limit = 32767;
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Callback routines from USB device /////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static void read_bulk_callback( struct urb *urb )
-{
-	ether_dev_t *ether_dev = urb->context;
-	struct net_device *net;
-	int count = urb->actual_length, res;
-	struct sk_buff	*skb;
-
-	// Sanity check 
-	if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
-		dbg("BULK IN callback but driver is not active!");
-		return;
-	}
-
-	net = ether_dev->net;
-	if ( !netif_device_present(net) ) {
-		// Somebody killed our network interface...
-		return;
-	}
-
-	if ( ether_dev->flags & CDC_ETHER_RX_BUSY ) {
-		// Are we already trying to receive a frame???
-		ether_dev->stats.rx_errors++;
-		dbg("ether_dev Rx busy");
-		return;
-	}
-
-	// We are busy, leave us alone!
-	ether_dev->flags |= CDC_ETHER_RX_BUSY;
-
-	switch ( urb->status ) {
-		case 0:
-			break;
-		case -ETIMEDOUT:
-			dbg( "no repsonse in BULK IN" );
-			ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
-			break;
-		default:
-			dbg( "%s: RX status %d", net->name, urb->status );
-			goto goon;
-	}
-
-	// Check to make sure we got some data...
-	if ( !count ) {
-		// We got no data!!!
-		goto goon;
-	}
-
-	// Tell the kernel we want some memory
-	if ( !(skb = dev_alloc_skb(count)) ) {
-		// We got no receive buffer.
-		goto goon;
-	}
-
-	// Here's where it came from
-	skb->dev = net;
-	
-	// Now we copy it over
-	eth_copy_and_sum(skb, ether_dev->rx_buff, count, 0);
-	
-	// Not sure
-	skb_put(skb, count);
-	// Not sure here either
-	skb->protocol = eth_type_trans(skb, net);
-	
-	// Ship it off to the kernel
-	netif_rx(skb);
-	
-	// update out statistics
-	ether_dev->stats.rx_packets++;
-	ether_dev->stats.rx_bytes += count;
-
-goon:
-	// Prep the USB to wait for another frame
-	FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
-			usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
-			ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
-			read_bulk_callback, ether_dev );
-			
-	// Give this to the USB subsystem so it can tell us 
-	// when more data arrives.
-	if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) ) {
-		warn( __FUNCTION__ " failed submint rx_urb %d", res);
-	}
-	
-	// We are no longer busy, show us the frames!!!
-	ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
-}
-
-static void write_bulk_callback( struct urb *urb )
-{
-	ether_dev_t *ether_dev = urb->context;
-
-	// Sanity check
-	if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
-		// We are insane!!!
-		err( "write_bulk_callback: device not running" );
-		return;
-	}
-
-	// Do we still have a valid kernel network device?
-	if ( !netif_device_present(ether_dev->net) ) {
-		// Someone killed our network interface.
-		err( "write_bulk_callback: net device not present" );
-		return;
-	}
-
-	// Hmm...  What on Earth could have happened???
-	if ( urb->status ) {
-		info("%s: TX status %d", ether_dev->net->name, urb->status);
-	}
-
-	// Update the network interface and tell it we are
-	// ready for another frame
-	ether_dev->net->trans_start = jiffies;
-	netif_wake_queue( ether_dev->net );
-}
-
-//static void intr_callback( struct urb *urb )
-//{
-//	ether_dev_t *ether_dev = urb->context;
-//	struct net_device *net;
-//	__u8	*d;
-//
-//	if ( !ether_dev )
-//		return;
-//		
-//	switch ( urb->status ) {
-//		case 0:
-//			break;
-//		case -ENOENT:
-//			return;
-//		default:
-//			info("intr status %d", urb->status);
-//	}
-//
-//	d = urb->transfer_buffer;
-//	net = ether_dev->net;
-//	if ( d[0] & 0xfc ) {
-//		ether_dev->stats.tx_errors++;
-//		if ( d[0] & TX_UNDERRUN )
-//			ether_dev->stats.tx_fifo_errors++;
-//		if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
-//			ether_dev->stats.tx_aborted_errors++;
-//		if ( d[0] & LATE_COL )
-//			ether_dev->stats.tx_window_errors++;
-//		if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
-//			ether_dev->stats.tx_carrier_errors++;
-//	}
-//}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines for turning net traffic on and off on the USB side ///////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static inline int enable_net_traffic( ether_dev_t *ether_dev )
-{
-	struct usb_device *usb = ether_dev->usb;
-
-	// Here would be the time to set the data interface to the configuration where
-	// it has two endpoints that use a protocol we can understand.
-
-	if (usb_set_interface( usb, 
-	                        ether_dev->data_bInterfaceNumber, 
-	                        ether_dev->data_bAlternateSetting_with_traffic ) )  {
-		err("usb_set_interface() failed" );
-		err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
-		err("To alternate setting       %d", ether_dev->data_bAlternateSetting_with_traffic);
-		return -1;
-	}
-	return 0;
-}
-
-static inline void disable_net_traffic( ether_dev_t *ether_dev )
-{
-	// The thing to do is to set the data interface to the alternate setting that has
-	// no endpoints.  This is what the spec suggests.
-
-	if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
-		if (usb_set_interface( ether_dev->usb, 
-		                        ether_dev->data_bInterfaceNumber, 
-		                        ether_dev->data_bAlternateSetting_without_traffic ) ) 	{
-			err("usb_set_interface() failed");
-		}
-	} else {
-		// Some devices just may not support this...
-		warn("No way to disable net traffic");
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Callback routines for kernel Ethernet Device //////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static void CDCEther_tx_timeout( struct net_device *net )
-{
-	ether_dev_t *ether_dev = net->priv;
-
-	// Sanity check
-	if ( !ether_dev ) {
-		// Seems to be a case of insanity here
-		return;
-	}
-
-	// Tell syslog we are hosed.
-	warn("%s: Tx timed out.", net->name);
-	
-	// Tear the waiting frame off the list
-	ether_dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
-	usb_unlink_urb( ether_dev->tx_urb );
-	
-	// Update statistics
-	ether_dev->stats.tx_errors++;
-}
-
-static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net )
-{
-	ether_dev_t	*ether_dev = net->priv;
-	int 	count;
-	int 	res;
-
-	// If we are told to transmit an ethernet frame that fits EXACTLY 
-	// into an integer number of USB packets, we force it to send one 
-	// more byte so the device will get a runt USB packet signalling the 
-	// end of the ethernet frame
-	if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) {
-		// It was not an exact multiple
-		// no need to add anything extra
-		count = skb->len;
-	} else {
-		// Add one to make it NOT an exact multiple
-		count = skb->len + 1;
-	}
-
-	// Tell the kernel, "No more frames 'til we are done
-	// with this one.'
-	netif_stop_queue( net );
-
-	// Copy it from kernel memory to OUR memory
-	memcpy(ether_dev->tx_buff, skb->data, skb->len);
-
-	// Fill in the URB for shipping it out.
-	FILL_BULK_URB( ether_dev->tx_urb, ether_dev->usb,
-			usb_sndbulkpipe(ether_dev->usb, ether_dev->data_ep_out),
-			ether_dev->tx_buff, ether_dev->wMaxSegmentSize, 
-			write_bulk_callback, ether_dev );
-
-	// Tell the URB how much it will be transporting today
-	ether_dev->tx_urb->transfer_buffer_length = count;
-	
-	// Send the URB on its merry way.
-	if ((res = usb_submit_urb(ether_dev->tx_urb, GFP_KERNEL)))  {
-		// Hmm...  It didn't go. Tell someone...
-		warn("failed tx_urb %d", res);
-		// update some stats...
-		ether_dev->stats.tx_errors++;
-		// and tell the kernel to give us another.
-		// Maybe we'll get it right next time.
-		netif_start_queue( net );
-	} else {
-		// Okay, it went out.
-		// Update statistics
-		ether_dev->stats.tx_packets++;
-		ether_dev->stats.tx_bytes += skb->len;
-		// And tell the kernel when the last transmit occurred.
-		net->trans_start = jiffies;
-	}
-
-	// We are done with the kernel's memory
-	dev_kfree_skb(skb);
-
-	// We are done here.
-	return 0;
-}
-
-static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
-{
-	// Easy enough!
-	return &((ether_dev_t *)net->priv)->stats;
-}
-
-static int CDCEther_open(struct net_device *net)
-{
-	ether_dev_t *ether_dev = (ether_dev_t *)net->priv;
-	int	res;
-
-	// Turn on the USB and let the packets flow!!!
-	if ( (res = enable_net_traffic( ether_dev )) ) {
-		err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
-		return -EIO;
-	}
-
-	// Prep a receive URB
-	FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
-			usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
-			ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
-			read_bulk_callback, ether_dev );
-
-	// Put it out there so the device can send us stuff
-	if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) )
-	{
-		// Hmm...  Okay...
-		warn( __FUNCTION__ " failed rx_urb %d", res );
-	}
-
-	// Tell the kernel we are ready to start receiving from it
-	netif_start_queue( net );
-	
-	// We are up and running.
-	ether_dev->flags |= CDC_ETHER_RUNNING;
-
-	// Let's get ready to move frames!!!
-	return 0;
-}
-
-static int CDCEther_close( struct net_device *net )
-{
-	ether_dev_t	*ether_dev = net->priv;
-
-	// We are no longer running.
-	ether_dev->flags &= ~CDC_ETHER_RUNNING;
-	
-	// Tell the kernel to stop sending us stuff
-	netif_stop_queue( net );
-	
-	// If we are not already unplugged, turn off USB
-	// traffic
-	if ( !(ether_dev->flags & CDC_ETHER_UNPLUG) ) {
-		disable_net_traffic( ether_dev );
-	}
-
-	// We don't need the URBs anymore.
-	usb_unlink_urb( ether_dev->rx_urb );
-	usb_unlink_urb( ether_dev->tx_urb );
-	usb_unlink_urb( ether_dev->intr_urb );
-	
-	// That's it.  I'm done.
-	return 0;
-}
-
-static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
-{
-	//__u16 *data = (__u16 *)&rq->ifr_data;
-	//ether_dev_t	*ether_dev = net->priv;
-
-	// No support here yet.
-	// Do we need support???
-	switch(cmd) {
-		case SIOCDEVPRIVATE:
-			return -EOPNOTSUPP;
-		case SIOCDEVPRIVATE+1:
-			return -EOPNOTSUPP;
-		case SIOCDEVPRIVATE+2:
-			//return 0;
-			return -EOPNOTSUPP;
-		default:
-			return -EOPNOTSUPP;
-	}
-}
-
-static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
-{
-	usb_control_msg(ether_dev->usb,
-			usb_sndctrlpipe(ether_dev->usb, 0),
-			SET_ETHERNET_PACKET_FILTER, /* request */
-			USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
-			cpu_to_le16(ether_dev->mode_flags), /* value */
-			cpu_to_le16((u16)ether_dev->comm_interface), /* index */
-			NULL,
-			0, /* size */
-			HZ); /* timeout */
-}	
-
-
-static void CDCEther_set_multicast( struct net_device *net )
-{
-	ether_dev_t *ether_dev = net->priv;
-	int i;
-	__u8 *buff;
-	
-
-	// Tell the kernel to stop sending us frames while we get this
-	// all set up.
-	netif_stop_queue(net);
-
-      /* Note: do not reorder, GCC is clever about common statements. */
-        if (net->flags & IFF_PROMISC) {
-                /* Unconditionally log net taps. */
-                info( "%s: Promiscuous mode enabled", net->name);
-		ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
-			MODE_FLAG_ALL_MULTICAST |
-			MODE_FLAG_DIRECTED |
-			MODE_FLAG_BROADCAST |
-			MODE_FLAG_MULTICAST;
-        } else if (net->mc_count > ether_dev->wNumberMCFilters) {
-                /* Too many to filter perfectly -- accept all multicasts. */
-		info("%s: set too many MC filters, using allmulti", net->name);
-		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
-			MODE_FLAG_DIRECTED |
-			MODE_FLAG_BROADCAST |
-			MODE_FLAG_MULTICAST;
-	} else if (net->flags & IFF_ALLMULTI) {
-                /* Filter in software */
-		info("%s: using allmulti", net->name);
-		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
-			MODE_FLAG_DIRECTED |
-			MODE_FLAG_BROADCAST |
-			MODE_FLAG_MULTICAST;
-        } else {
-		/* do multicast filtering in hardware */
-                struct dev_mc_list *mclist;
-		info("%s: set multicast filters", net->name);
-		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
-			MODE_FLAG_DIRECTED |
-			MODE_FLAG_BROADCAST |
-			MODE_FLAG_MULTICAST;
-		buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-                for (i = 0, mclist = net->mc_list;
-		     mclist && i < net->mc_count;
-                     i++, mclist = mclist->next) {
-			memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
-		}
-#if 0
-		usb_control_msg(ether_dev->usb,
-				usb_sndctrlpipe(ether_dev->usb, 0),
-				SET_ETHERNET_MULTICAST_FILTER, /* request */
-				USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
-				cpu_to_le16(net->mc_count), /* value */
-				cpu_to_le16((u16)ether_dev->comm_interface), /* index */
-				buff,
-				(6* net->mc_count), /* size */
-				HZ); /* timeout */
-#endif
-		kfree(buff);
-	}
-
-#if 0 
-	CDC_SetEthernetPacketFilter(ether_dev);
-#endif	
-        // Tell the kernel to start giving frames to us again.
-	netif_wake_queue(net);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines used to parse out the Functional Descriptors /////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int parse_header_functional_descriptor( int *bFunctionLength, 
-                                               int bDescriptorType, 
-                                               int bDescriptorSubtype,
-                                               unsigned char *data,
-                                               ether_dev_t *ether_dev,
-                                               int *requirements )
-{
-	// Check to make sure we haven't seen one of these already.
-	if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
-		err( "Multiple Header Functional Descriptors found." );
-		return -1;
-	}
-	
-	// Is it the right size???
-	if (*bFunctionLength != 5) {
-		info( "Invalid length in Header Functional Descriptor" );
-		// This is a hack to get around a particular device (NO NAMES)
-		// It has this function length set to the length of the
-		// whole class-specific descriptor
-		*bFunctionLength = 5;
-	}
-	
-	// Nothing extremely useful here.
-	// We'll keep it for posterity
-	ether_dev->bcdCDC = data[0] + (data[1] << 8);
-	dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
-
-	// We've seen one of these
-	*requirements &= ~REQ_HDR_FUNC_DESCR;
-	
-	// It's all good.
-	return 0;
-}
-
-static int parse_union_functional_descriptor( int *bFunctionLength, 
-                                              int bDescriptorType, 
-                                              int bDescriptorSubtype,
-                                              unsigned char *data,
-                                              ether_dev_t *ether_dev,
-                                              int *requirements )
-{
-	// Check to make sure we haven't seen one of these already.
-	if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
-		err( "Multiple Union Functional Descriptors found." );
-		return -1;
-	}
-
-	// Is it the right size?
-	if (*bFunctionLength != 5) {
-		// It is NOT the size we expected.
-		err( "Unsupported length in Union Functional Descriptor" );
-		return -1;
-	}
-	
-	// Sanity check of sorts
-	if (ether_dev->comm_interface != data[0]) {
-		// This tells us that we are chasing the wrong comm
-		// interface or we are crazy or something else weird.
-		if (ether_dev->comm_interface == data[1]) {
-			info( "Probably broken Union descriptor, fudging data interface" );
-			// We'll need this in a few microseconds, 
-			// so guess here, and hope for the best
-			ether_dev->data_interface = data[0];
-		} else {
-			err( "Union Functional Descriptor is broken beyond repair" );
-			return -1;
-		}
-	} else{ // Descriptor is OK
-       		// We'll need this in a few microseconds!
-		ether_dev->data_interface = data[1];
-	}
-
-	// We've seen one of these now.
-	*requirements &= ~REQ_UNION_FUNC_DESCR;
-	
-	// Done
-	return 0;
-}
-
-static int parse_ethernet_functional_descriptor( int *bFunctionLength, 
-                                                 int bDescriptorType, 
-                                                 int bDescriptorSubtype,
-                                                 unsigned char *data,
-                                                 ether_dev_t *ether_dev,
-                                                 int *requirements )
-{
-	// Check to make sure we haven't seen one of these already.
-	if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
-		err( "Multiple Ethernet Functional Descriptors found." );
-		return -1;
-	}
-	
-	// Is it the right size?
-	if (*bFunctionLength != 13) {
-		err( "Invalid length in Ethernet Networking Functional Descriptor" );
-		return -1;
-	}
-	
-	// Lots of goodies from this one.  They are all important.
-	ether_dev->iMACAddress = data[0];
-	ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
-	ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
-	ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
-	if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
-		ether_dev->wNumberMCFilters = multicast_filter_limit;
-		}	
-	ether_dev->bNumberPowerFilters = data[9];
-	
-	// We've seen one of these now.
-	*requirements &= ~REQ_ETH_FUNC_DESCR;
-	
-	// That's all she wrote.
-	return 0;
-}
-
-static int parse_protocol_unit_functional_descriptor( int *bFunctionLength, 
-                                                      int bDescriptorType, 
-                                                      int bDescriptorSubtype,
-                                                      unsigned char *data,
-                                                      ether_dev_t *ether_dev,
-                                                      int *requirements )
-{
-	// There should only be one type if we are sane
-	if (bDescriptorType != CS_INTERFACE) {
-		info( "Invalid bDescriptorType found." );
-		return -1;
-	}
-
-	// The Subtype tells the tale.
-	switch (bDescriptorSubtype){
-		case 0x00:	// Header Functional Descriptor
-			return parse_header_functional_descriptor( bFunctionLength,
-			                                           bDescriptorType,
-			                                           bDescriptorSubtype,
-			                                           data,
-			                                           ether_dev,
-			                                           requirements );
-			break;
-		case 0x06:	// Union Functional Descriptor
-			return parse_union_functional_descriptor( bFunctionLength,
-			                                          bDescriptorType,
-			                                          bDescriptorSubtype,
-			                                          data,
-			                                          ether_dev,
-			                                          requirements );
-			break;
-		case 0x0F:	// Ethernet Networking Functional Descriptor
-			return parse_ethernet_functional_descriptor( bFunctionLength,
-			                                             bDescriptorType,
-			                                             bDescriptorSubtype,
-			                                             data,
-			                                             ether_dev,
-			                                             requirements );
-			break;
-		default:	// We don't support this at this time...
-			// However that doesn't necessarily indicate an error.
-			dbg( "Unexpected header type %x:", bDescriptorSubtype );
-			return 0;
-	}
-	// How did we get here???
-	return -1;
-}
-
-static int parse_ethernet_class_information( unsigned char *data, int length, ether_dev_t *ether_dev )
-{
-	int loc = 0;
-	int rc;
-	int bFunctionLength;
-	int bDescriptorType;
-	int bDescriptorSubtype;
-	int requirements = REQUIREMENTS_TOTAL;
-
-	// As long as there is something here, we will try to parse it
-	while (loc < length) {
-		// Length
-		bFunctionLength = data[loc];
-		loc++;
-		
-		// Type
-		bDescriptorType = data[loc];
-		loc++;
-		
-		// Subtype
-		bDescriptorSubtype = data[loc];
-		loc++;
-		
-		// ship this off to be processed elsewhere.
-		rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, 
-		                                                bDescriptorType, 
-		                                                bDescriptorSubtype, 
-		                                                &data[loc],
-		                                                ether_dev,
-		                                                &requirements );
-		// Did it process okay?
-		if (rc)	{
-			// Something was hosed somewhere.
-			// No need to continue;
-			err("Bad descriptor parsing: %x", rc );
-			return -1;
-		}
-		// We have already taken three bytes.
-		loc += (bFunctionLength - 3);
-	}
-	// Check to see if we got everything we need.
-	if (requirements) {
-		// We missed some of the requirements...
-		err( "Not all required functional descriptors present 0x%08X", requirements );
-		return -1;
-	}
-	// We got everything.
-	return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to check for the existence of the Functional Descriptors //////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int find_and_parse_ethernet_class_information( struct usb_device *device, ether_dev_t *ether_dev )
-{
-	struct usb_config_descriptor *conf = NULL;
-	struct usb_interface *comm_intf_group = NULL;
-	struct usb_interface_descriptor *comm_intf = NULL;
-	int rc = -1;
-	// The assumption here is that find_ethernet_comm_interface
-	// and find_valid_configuration 
-	// have already filled in the information about where to find
-	// the a valid commication interface.
-
-	conf = &( device->config[ether_dev->configuration_num] );
-	comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
-	comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
-	// Let's check and see if it has the extra information we need...
-
-	if (comm_intf->extralen > 0) {
-		// This is where the information is SUPPOSED to be.
-		rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
-	} else if (conf->extralen > 0) {
-		// This is a hack.  The spec says it should be at the interface 
-		// location checked above.  However I have seen it here also.
-		// This is the same device that requires the functional descriptor hack above
-		warn( "Ethernet information found at device configuration.  This is broken." );
-		rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
-	} else 	{
-		// I don't know where else to look.
-		warn( "No ethernet information found." );
-		rc = -1;
-	}
-	return rc;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines to verify the data interface /////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int get_data_interface_endpoints( struct usb_device *device, ether_dev_t *ether_dev )
-{
-	struct usb_config_descriptor *conf = NULL;
-	struct usb_interface *data_intf_group = NULL;
-	struct usb_interface_descriptor *data_intf = NULL;
-	
-	// Walk through and get to the data interface we are checking.
-	conf = &( device->config[ether_dev->configuration_num] );
-	data_intf_group = &( conf->interface[ether_dev->data_interface] );
-	data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
-
-	// Start out assuming we won't find anything we can use
-	ether_dev->data_ep_in = 0;
-	ether_dev->data_ep_out = 0;
-	
-	// If these are not BULK endpoints, we don't want them
-	if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
-		return -1;
-	} if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
-		return -1;
-	}
-
-	// Check the first endpoint to see if it is IN or OUT
-	if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
-		// This endpoint is IN
-		ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
-	} else {
-		// This endpoint is OUT
-		ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;
-		ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
-	}
-
-	// Check the second endpoint to see if it is IN or OUT
-	if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
-		// This endpoint is IN
-		ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
-	} else	{
-		// This endpoint is OUT
-		ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;
-		ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
-	}
-	
-	// Now make sure we got both an IN and an OUT
-	if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
-		// We did get both, we are in good shape...
-		info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
-		return 0;
-	}
-	return -1;
-}
-
-static int verify_ethernet_data_interface( struct usb_device *device, ether_dev_t *ether_dev )
-{
-	struct usb_config_descriptor *conf = NULL;
-	struct usb_interface *data_intf_group = NULL;
-	struct usb_interface_descriptor *data_intf = NULL;
-	int rc = -1;
-	int status;
-	int altset_num;
-
-	// The assumption here is that parse_ethernet_class_information()
-	// and find_valid_configuration() 
-	// have already filled in the information about where to find
-	// a data interface
-	conf = &( device->config[ether_dev->configuration_num] );
-	data_intf_group = &( conf->interface[ether_dev->data_interface] );
-
-	// start out assuming we won't find what we are looking for.
-	ether_dev->data_interface_altset_num_with_traffic = -1;
-	ether_dev->data_bAlternateSetting_with_traffic = -1;
-	ether_dev->data_interface_altset_num_without_traffic = -1;
-	ether_dev->data_bAlternateSetting_without_traffic = -1;
-
-	// Walk through every possible setting for this interface until
-	// we find what makes us happy.
-	for ( altset_num = 0; altset_num < data_intf_group->num_altsetting; altset_num++ ) {
-		data_intf = &( data_intf_group->altsetting[altset_num] );
-
-		// Is this a data interface we like?
-		if ( ( data_intf->bInterfaceClass == 0x0A )
-		   && ( data_intf->bInterfaceSubClass == 0x00 )
-		   && ( data_intf->bInterfaceProtocol == 0x00 ) ) {
-			if ( data_intf->bNumEndpoints == 2 ) {
-				// We are required to have one of these.
-				// An interface with 2 endpoints to send Ethernet traffic back and forth
-				// It actually may be possible that the device might only
-				// communicate in a vendor specific manner.
-				// That would not be very nice.
-				// We can add that one later.
-				ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
-				ether_dev->data_interface_altset_num_with_traffic = altset_num;
-				ether_dev->data_bAlternateSetting_with_traffic = data_intf->bAlternateSetting;
-				status = get_data_interface_endpoints( device, ether_dev );
-				if (!status) {
-					rc = 0;
-				}
-			}
-			if ( data_intf->bNumEndpoints == 0 ) {
-				// According to the spec we are SUPPOSED to have one of these
-				// In fact the device is supposed to come up in this state.
-				// However, I have seen a device that did not have such an interface.
-				// So it must be just optional for our driver...
-				ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
-				ether_dev->data_interface_altset_num_without_traffic = altset_num;
-				ether_dev->data_bAlternateSetting_without_traffic = data_intf->bAlternateSetting;
-			}
-		}
-	}
-	return rc;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to find a communication interface /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int find_ethernet_comm_interface( struct usb_device *device, ether_dev_t *ether_dev )
-{
-	struct usb_config_descriptor *conf = NULL;
-	struct usb_interface *comm_intf_group = NULL;
-	struct usb_interface_descriptor *comm_intf = NULL;
-	int intf_num;
-	int altset_num;
-	int rc;
-
-	conf = &( device->config[ether_dev->configuration_num] );
-
-	// We need to check and see if any of these interfaces are something we want.
-	// Walk through each interface one at a time
-	for ( intf_num = 0; intf_num < conf->bNumInterfaces; intf_num++ ) {
-		comm_intf_group = &( conf->interface[intf_num] );
-		// Now for each of those interfaces, check every possible
-		// alternate setting.
-		for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
-			comm_intf = &( comm_intf_group->altsetting[altset_num] );
-
-			// Is this a communication class of interface of the
-			// ethernet subclass variety.
-			if ( ( comm_intf->bInterfaceClass == 0x02 )
-			   && ( comm_intf->bInterfaceSubClass == 0x06 )
-			   && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
-				if ( comm_intf->bNumEndpoints == 1 ) {
-					// Good, we found one, we will try this one
-					// Fill in the structure...
-					ether_dev->comm_interface = intf_num;
-					ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
-					ether_dev->comm_interface_altset_num = altset_num;
-					ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
-
-					// Look for the Ethernet Functional Descriptors
-					rc = find_and_parse_ethernet_class_information( device, ether_dev );
-					if (rc) {
-						// Nope this was no good after all.
-						continue;
-					}
-
-					// Check that we really can talk to the data
-					// interface 
-					// This includes # of endpoints, protocols,
-					// etc.
-					rc = verify_ethernet_data_interface( device, ether_dev );
-					if (rc)	{
-						// We got something we didn't like
-						continue;
-					}
-					// This communication interface seems to give us everything
-					// we require.  We have all the ethernet info we need.
-					// Let's get out of here and go home right now.
-					return 0;
-				} else {
-                                        // bNumEndPoints != 1
-					// We found an interface that had the wrong number of 
-					// endpoints but would have otherwise been okay
-				} // end bNumEndpoints check.
-			} // end interface specifics check.
-		} // end for altset_num
-	} // end for intf_num
-	return -1;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to go through all configurations and find one that ////////////////
-// is an Ethernet Networking Device //////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int find_valid_configuration( struct usb_device *device, ether_dev_t *ether_dev )
-{
-	struct usb_config_descriptor *conf = NULL;
-	int conf_num;
-	int rc;
-
-	// We will try each and every possible configuration
-	for ( conf_num = 0; conf_num < device->descriptor.bNumConfigurations; conf_num++ ) {
-		conf = &( device->config[conf_num] );
-
-		// Our first requirement : 2 interfaces
-		if ( conf->bNumInterfaces != 2 ) {
-			// I currently don't know how to handle devices with any number of interfaces
-			// other than 2.
-			continue;
-		}
-
-		// This one passed our first check, fill in some 
-		// useful data
-		ether_dev->configuration_num = conf_num;
-		ether_dev->bConfigurationValue = conf->bConfigurationValue;
-
-		// Now run it through the ringers and see what comes
-		// out the other side.
-		rc = find_ethernet_comm_interface( device, ether_dev );
-
-		// Check if we found an ethernet Communcation Device
-		if ( !rc ) {
-			// We found one.
-			return 0;
-		}
-	}
-	// None of the configurations suited us.
-	return -1;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine that checks a given configuration to see if any driver ////////////
-// has claimed any of the devices interfaces /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static int check_for_claimed_interfaces( struct usb_config_descriptor *config )
-{
-	struct usb_interface *comm_intf_group;
-	int intf_num;
-
-	// Go through all the interfaces and make sure none are 
-	// claimed by anybody else.
-	for ( intf_num = 0; intf_num < config->bNumInterfaces; intf_num++ ) {
-		comm_intf_group = &( config->interface[intf_num] );
-		if ( usb_interface_claimed( comm_intf_group ) )	{
-			// Somebody has beat us to this guy.
-			// We can't change the configuration out from underneath of whoever
-			// is using this device, so we will go ahead and give up.
-			return -1;
-		}
-	}
-	// We made it all the way through.
-	// I guess no one has claimed any of these interfaces.
-	return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routines to ask for and set the kernel network interface's MAC address ////
-// Used by driver's probe routine ////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static inline unsigned char hex2dec( unsigned char digit )
-{
-	// Is there a standard way to do this???
-	// I have written this code TOO MANY times.
-	if ( (digit >= '0') && (digit <= '9') )	{
-		return (digit - '0');
-	}
-	if ( (digit >= 'a') && (digit <= 'f') )	{
-		return (digit - 'a' + 10);
-	}
-	if ( (digit >= 'A') && (digit <= 'F') )	{
-		return (digit - 'A' + 10);
-	}
-	return 0;
-}
-
-static void set_ethernet_addr( ether_dev_t *ether_dev )
-{
-	unsigned char	mac_addr[6];
-	int		i;
-	int 		len;
-	unsigned char	buffer[13];
-
-	// Let's assume we don't get anything...
-	mac_addr[0] = 0x00;
-	mac_addr[1] = 0x00;
-	mac_addr[2] = 0x00;
-	mac_addr[3] = 0x00;
-	mac_addr[4] = 0x00;
-	mac_addr[5] = 0x00;
-
-	// Let's ask the device...
-	len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
-
-	// Sanity check!
-	if (len != 12)	{
-		// You gotta love failing sanity checks
-		err("Attempting to get MAC address returned %d bytes", len);
-		return;
-	}
-
-	// Fill in the mac_addr
-	for (i = 0; i < 6; i++)	{
-		mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
-	}
-
-	// Now copy it over to the kernel's network driver.
-	memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Routine to print to syslog information about the driver ///////////////////
-// Used by driver's probe routine ////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-void log_device_info(ether_dev_t *ether_dev)
-{
-	int len;
-	int string_num;
-	unsigned char manu[256];
-	unsigned char prod[256];
-	unsigned char sern[256];
-	unsigned char *mac_addr;
-
-	// Default empty strings in case we don't find a real one
-	manu[0] = 0x00;
-	prod[0] = 0x00;
-	sern[0] = 0x00;
-
-	// Try to get the device Manufacturer
-	string_num = ether_dev->usb->descriptor.iManufacturer;
-	if (string_num)	{
-		// Put it into its buffer
-		len = usb_string(ether_dev->usb, string_num, manu, 255);
-		// Just to be safe
-		manu[len] = 0x00;
-	}
-
-	// Try to get the device Product Name
-	string_num = ether_dev->usb->descriptor.iProduct;
-	if (string_num)	{
-		// Put it into its buffer
-		len = usb_string(ether_dev->usb, string_num, prod, 255);
-		// Just to be safe
-		prod[len] = 0x00;
-	}
-
-	// Try to get the device Serial Number
-	string_num = ether_dev->usb->descriptor.iSerialNumber;
-	if (string_num)	{
-		// Put it into its buffer
-		len = usb_string(ether_dev->usb, string_num, sern, 255);
-		// Just to be safe
-		sern[len] = 0x00;
-	}
-
-	// This makes it easier for us to print
-	mac_addr = ether_dev->net->dev_addr;
-
-	// Now send everything we found to the syslog
-	info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X", 
-	      ether_dev->net->name, manu, prod, sern, mac_addr[0], 
-	      mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], 
-	      mac_addr[5] );
-}
-
-/* Forward declaration */
-static struct usb_driver CDCEther_driver ;
-
-//////////////////////////////////////////////////////////////////////////////
-// Module's probe routine ////////////////////////////////////////////////////
-// claims interfaces if they are for an Ethernet CDC /////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
-			     const struct usb_device_id *id)
-{
-	struct net_device	*net;
-	ether_dev_t		*ether_dev;
-	int 			rc;
-
-	// First we should check the active configuration to see if 
-	// any other driver has claimed any of the interfaces.
-	if ( check_for_claimed_interfaces( usb->actconfig ) ) {
-		// Someone has already put there grubby paws on this device.
-		// We don't want it now...
-		return NULL;
-	}
-
-	// We might be finding a device we can use.
-	// We all go ahead and allocate our storage space.
-	// We need to because we have to start filling in the data that
-	// we are going to need later.
-	if(!(ether_dev = kmalloc(sizeof(ether_dev_t), GFP_KERNEL))) {
-		err("out of memory allocating device structure");
-		return NULL;
-	}
-
-	// Zero everything out.
-	memset(ether_dev, 0, sizeof(ether_dev_t));
-
-	ether_dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ether_dev->rx_urb) {
-		kfree(ether_dev);
-		return NULL;
-	}
-	ether_dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ether_dev->tx_urb) {
-		usb_free_urb(ether_dev->rx_urb);
-		kfree(ether_dev);
-		return NULL;
-	}
-	ether_dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!ether_dev->intr_urb) {
-		usb_free_urb(ether_dev->tx_urb);
-		usb_free_urb(ether_dev->rx_urb);
-		kfree(ether_dev);
-		return NULL;
-	}
-
-	// Let's see if we can find a configuration we can use.
-	rc = find_valid_configuration( usb, ether_dev );
-	if (rc)	{
-		// Nope we couldn't find one we liked.
-		// This device was not meant for us to control.
-		kfree( ether_dev );
-		return	NULL;
-	}
-
-	// Now that we FOUND a configuration. let's try to make the 
-	// device go into it.
-	if ( usb_set_configuration( usb, ether_dev->bConfigurationValue ) ) {
-		err("usb_set_configuration() failed");
-		kfree( ether_dev );
-		return NULL;
-	}
-
-	// Now set the communication interface up as required.
-	if (usb_set_interface(usb, ether_dev->comm_bInterfaceNumber, ether_dev->comm_bAlternateSetting)) {
-		err("usb_set_interface() failed");
-		kfree( ether_dev );
-		return NULL;
-	}
-
-	// Only turn traffic on right now if we must...
-	if (ether_dev->data_interface_altset_num_without_traffic >= 0)	{
-		// We found an alternate setting for the data
-		// interface that allows us to turn off traffic.
-		// We should use it.
-		if (usb_set_interface( usb, 
-		                       ether_dev->data_bInterfaceNumber, 
-		                       ether_dev->data_bAlternateSetting_without_traffic)) {
-			err("usb_set_interface() failed");
-			kfree( ether_dev );
-			return NULL;
-		}
-	} else	{
-		// We didn't find an alternate setting for the data
-		// interface that would let us turn off traffic.
-		// Oh well, let's go ahead and do what we must...
-		if (usb_set_interface( usb, 
-		                       ether_dev->data_bInterfaceNumber, 
-		                       ether_dev->data_bAlternateSetting_with_traffic)) {
-			err("usb_set_interface() failed");
-			kfree( ether_dev );
-			return NULL;
-		}
-	}
-
-	// Now we need to get a kernel Ethernet interface.
-	net = init_etherdev( NULL, 0 );
-	if ( !net ) {
-		// Hmm...  The kernel is not sharing today...
-		// Fine, we didn't want it anyway...
-		err( "Unable to initialize ethernet device" );
-		kfree( ether_dev );
-		return	NULL;
-	}
-
-	// Now that we have an ethernet device, let's set it up
-	// (And I don't mean "set [it] up the bomb".)
-	net->priv = ether_dev;
-	SET_MODULE_OWNER(net);
-	net->open = CDCEther_open;
-	net->stop = CDCEther_close;
-	net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;
-	net->tx_timeout = CDCEther_tx_timeout;   // TX timeout function
-	net->do_ioctl = CDCEther_ioctl;
-	net->hard_start_xmit = CDCEther_start_xmit;
-	net->set_multicast_list = CDCEther_set_multicast;
-	net->get_stats = CDCEther_netdev_stats;
-	net->mtu = ether_dev->wMaxSegmentSize - 14;
-
-	// We'll keep track of this information for later...
-	ether_dev->usb = usb;
-	ether_dev->net = net;
-	
-	// and don't forget the MAC address.
-	set_ethernet_addr( ether_dev );
-
-	// Send a message to syslog about what we are handling
-	log_device_info( ether_dev );
-
-	// I claim this interface to be a CDC Ethernet Networking device
-	usb_driver_claim_interface( &CDCEther_driver, 
-	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), 
-	                            ether_dev );
-	// I claim this interface to be a CDC Ethernet Networking device
-	usb_driver_claim_interface( &CDCEther_driver, 
-	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), 
-	                            ether_dev );
-
-	// Does this REALLY do anything???
-	usb_inc_dev_use( usb );
-
-	// TODO - last minute HACK
-	ether_dev->comm_ep_in = 5;
-
-	// Okay, we are finally done...
-	return NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// Module's disconnect routine ///////////////////////////////////////////////
-// Called when the driver is unloaded or the device is unplugged /////////////
-// (Whichever happens first assuming the driver suceeded at its probe) ///////
-//////////////////////////////////////////////////////////////////////////////
-
-static void CDCEther_disconnect( struct usb_device *usb, void *ptr )
-{
-	ether_dev_t *ether_dev = ptr;
-
-	// Sanity check!!!
-	if ( !ether_dev || !ether_dev->usb ) {
-		// We failed.  We are insane!!!
-		warn("unregistering non-existant device");
-		return;
-	}
-
-	// Make sure we fail the sanity check if we try this again.
-	ether_dev->usb = NULL;
-	
-	// It is possible that this function is called before
-	// the "close" function.
-	// This tells the close function we are already disconnected
-	ether_dev->flags |= CDC_ETHER_UNPLUG;
-	
-	// We don't need the network device any more
-	unregister_netdev( ether_dev->net );
-	
-	// For sanity checks
-	ether_dev->net = NULL;
-
-	// I ask again, does this do anything???
-	usb_dec_dev_use( usb );
-
-	// We are done with this interface
-	usb_driver_release_interface( &CDCEther_driver, 
-	                              &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]) );
-
-	// We are done with this interface too
-	usb_driver_release_interface( &CDCEther_driver, 
-	                              &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]) );
-
-	// No more tied up kernel memory
-	usb_free_urb(ether_dev->intr_urb);
-	usb_free_urb(ether_dev->rx_urb);
-	usb_free_urb(ether_dev->rx_urb);
-	kfree( ether_dev );
-	
-	// This does no good, but it looks nice!
-	ether_dev = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Driver info ///////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-static struct usb_driver CDCEther_driver = {
-	name:		"CDCEther",
-	probe:		CDCEther_probe,
-	disconnect:	CDCEther_disconnect,
-	id_table:	CDCEther_ids,
-};
-
-//////////////////////////////////////////////////////////////////////////////
-// init and exit routines called when driver is installed and uninstalled ////
-//////////////////////////////////////////////////////////////////////////////
-
-int __init CDCEther_init(void)
-{
-	info( "%s", version );
-	return usb_register( &CDCEther_driver );
-}
-
-void __exit CDCEther_exit(void)
-{
-	usb_deregister( &CDCEther_driver );
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Module info ///////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-module_init( CDCEther_init );
-module_exit( CDCEther_exit );
-
-MODULE_AUTHOR("Brad Hards and another");
-MODULE_DESCRIPTION("USB CDC Ethernet driver");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM (multicast_filter_limit, "i");
-MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
-
-MODULE_DEVICE_TABLE (usb, CDCEther_ids);
-
-//////////////////////////////////////////////////////////////////////////////
-// End of file ///////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
diff -Nru a/drivers/usb/CDCEther.h b/drivers/usb/CDCEther.h
--- a/drivers/usb/CDCEther.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,98 +0,0 @@
-// Portions of this file taken from 
-// Petko Manolov - Petkan (petkan@dce.bg)
-// from his driver pegasus.h
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#define CS_INTERFACE			0x24
-
-#define	CDC_ETHER_MAX_MTU		1536
-
-#define	CDC_ETHER_PRESENT		0x00000001
-#define	CDC_ETHER_RUNNING		0x00000002
-#define	CDC_ETHER_TX_BUSY		0x00000004
-#define	CDC_ETHER_RX_BUSY		0x00000008
-#define	CDC_ETHER_UNPLUG		0x00000040
-
-#define	CDC_ETHER_TX_TIMEOUT	(HZ*10)
-
-#define	TX_UNDERRUN				0x80
-#define	EXCESSIVE_COL			0x40
-#define	LATE_COL				0x20
-#define	NO_CARRIER				0x10
-#define	LOSS_CARRIER			0x08
-#define	JABBER_TIMEOUT			0x04
-
-#define	CDC_ETHER_REQT_READ		0xc0
-#define	CDC_ETHER_REQT_WRITE	0x40
-#define	CDC_ETHER_REQ_GET_REGS	0xf0
-#define	CDC_ETHER_REQ_SET_REGS	0xf1
-#define	CDC_ETHER_REQ_SET_REG	PIPERIDER_REQ_SET_REGS
-#define	ALIGN(x)		x __attribute__((aligned(L1_CACHE_BYTES)))
-
-#define MODE_FLAG_PROMISCUOUS   (1<<0)
-#define MODE_FLAG_ALL_MULTICAST (1<<1)
-#define MODE_FLAG_DIRECTED      (1<<2)
-#define MODE_FLAG_BROADCAST     (1<<3)
-#define MODE_FLAG_MULTICAST     (1<<4)
-
-#define SET_ETHERNET_MULTICAST_FILTER    0x40
-#define SET_ETHERNET_PACKET_FILTER       0x43
-
-typedef struct _ether_dev_t {
-	struct usb_device	*usb;
-	struct net_device	*net;
-	struct net_device_stats	stats;
-	unsigned		flags;
-	int			configuration_num;
-	int			bConfigurationValue;
-	int			comm_interface;
-	int			comm_bInterfaceNumber;
-	int			comm_interface_altset_num;
-	int			comm_bAlternateSetting;
-	int			comm_ep_in;
-	int			data_interface;
-	int			data_bInterfaceNumber;
-	int			data_interface_altset_num_with_traffic;
-	int			data_bAlternateSetting_with_traffic;
-	int			data_interface_altset_num_without_traffic;
-	int			data_bAlternateSetting_without_traffic;
-	int			data_ep_in;
-	int			data_ep_out;
-	int			data_ep_out_size;
-	__u16			bcdCDC;
-	__u8			iMACAddress;
-	__u32			bmEthernetStatistics;
-	__u16			wMaxSegmentSize;
-	__u16                   mode_flags;
-	__u16			wNumberMCFilters;
-	__u8			bNumberPowerFilters;
-	int			intr_interval;
-	struct urb		*rx_urb, *tx_urb, *intr_urb;
-	unsigned char		ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
-	unsigned char		ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
-	unsigned char		ALIGN(intr_buff[8]);
-} ether_dev_t;
-
-#define REQ_HDR_FUNC_DESCR	0x0001
-#define REQ_UNION_FUNC_DESCR	0x0002
-#define REQ_ETH_FUNC_DESCR	0x0004
-#define REQUIREMENTS_TOTAL	0x0007
-
-
-
diff -Nru a/drivers/usb/Config.help b/drivers/usb/Config.help
--- a/drivers/usb/Config.help	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/Config.help	Sun Apr 14 12:16:58 2002
@@ -37,442 +37,6 @@
   If you have an MGE Ellipse UPS, or you see timeouts in HID
   transactions, say Y; otherwise say N.
 
-CONFIG_USB_UHCI
-  The Universal Host Controller Interface is a standard by Intel for
-  accessing the USB hardware in the PC (which is also called the USB
-  host controller). If your USB host controller conforms to this
-  standard, you may want to say Y, but see below. All recent boards
-  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
-  i810, i820) conform to this standard. Also all VIA PCI chipsets
-  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
-  133).
-
-  Currently there exist two drivers for UHCI host controllers: this
-  one and the so-called JE driver, which you can get from
-  "UHCI alternate (JE) support", below. You need only one.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called usb-uhci.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_UHCI_ALT
-  The Universal Host Controller Interface is a standard by Intel for
-  accessing the USB hardware in the PC (which is also called the USB
-  host controller). If your USB host controller conforms to this
-  standard, you may want to say Y, but see below. All recent boards
-  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
-  i810, i820) conform to this standard. Also all VIA PCI chipsets
-  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
-  133). If unsure, say Y.
-
-  Currently there exist two drivers for UHCI host controllers: this
-  so-called JE driver, and the one you get from "UHCI support", above.
-  You need only one.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called uhci.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_OHCI
-  The Open Host Controller Interface is a standard by
-  Compaq/Microsoft/National for accessing the USB PC hardware (also
-  called USB host controller). If your USB host controller conforms to
-  this standard, say Y. The USB host controllers on most non-Intel
-  architectures and on several x86 compatibles with non-Intel chipsets
-  -- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
-  Aladdin Pro..) -- conform to this standard.
-
-  You may want to read <file:Documentation/usb/ohci.txt>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called usb-ohci.o. If you want to compile it
-  as a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_HID
-  Say Y here if you want full HID support to connect keyboards,
-  mice, joysticks, graphic tablets, or any other HID based devices
-  to your computer via USB. You can't use this driver and the
-  HIDBP (Boot Protocol) keyboard and mouse drivers at the same time.
-  More information is available: <file:Documentation/input/input.txt>.
-
-  If unsure, say Y.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called hid.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_HIDDEV
-  Say Y here if you want to support HID devices (from the USB
-  specification standpoint) that aren't strictly user interface
-  devices, like monitor controls and Uninterruptable Power Supplies.
-
-  This module supports these devices separately using a separate
-  event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
-  This driver requires CONFIG_USB_HID.
-
-  If unsure, say N.
-
-CONFIG_USB_KBD
-  Say Y here if you don't want to use the generic HID driver for your
-  USB keyboard and prefer to use the keyboard in its limited Boot
-  Protocol mode instead. This driver is much smaller than the HID one.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called usbkbd.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-  If unsure, say N.
-
-CONFIG_USB_MOUSE
-  Say Y here if you don't want to use the generic HID driver for your
-  USB mouse and prefer to use the mouse in its limited Boot Protocol
-  mode instead. This driver is much smaller than the HID one.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called usbmouse.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-  If unsure, say N.
-
-CONFIG_USB_WACOM
-  Say Y here if you want to use the USB version of the Wacom Intuos
-  or Graphire tablet.  Make sure to say Y to "Mouse support"
-  (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
-  (CONFIG_INPUT_EVDEV) as well.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called wacom.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_SCANNER
-  Say Y here if you want to connect a USB scanner to your computer's
-  USB port. Please read <file:Documentation/usb/scanner.txt> and
-  <file:Documentation/usb/scanner-hp-sane.txt> for more information.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called scanner.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_AUDIO
-  Say Y here if you want to connect USB audio equipment such as
-  speakers to your computer's USB port.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called audio.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_EMI26
-  This driver loads firmware to Emagic EMI 2|6 low latency USB
-  Audio interface.
-
-  After firmware load the device is handled with standard linux
-  USB Audio driver.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called audio.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_ACM
-  This driver supports USB modems and ISDN adapters which support the
-  Communication Device Class Abstract Control Model interface.
-  Please read <file:Documentation/usb/acm.txt> for details.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called acm.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_PRINTER
-  Say Y here if you want to connect a USB printer to your computer's
-  USB port.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called printer.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_IBMCAM
-  Say Y here if you want to connect a IBM "C-It" camera, also known as
-  "Xirlink PC Camera" to your computer's USB port.  For more
-  information, read <file:Documentation/usb/ibmcam.txt>.
-
-  This driver uses the Video For Linux API.  You must enable
-  (Y or M in config) Video For Linux (under Character Devices)
-  to use this driver.  Information on this API and pointers to
-  "v4l" programs may be found on the WWW at
-  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called ibmcam.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>. This
-  camera has several configuration options which can be specified when
-  you load the module.  Read <file:Documentation/usb/ibmcam.txt> to
-  learn more.
-
-CONFIG_USB_OV511
-  Say Y here if you want to connect this type of camera to your
-  computer's USB port. See <file:Documentation/usb/ov511.txt> for more
-  information and for a list of supported cameras.
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Character Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called ov511.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_CDCETHER
-  This driver supports devices conforming to the Communication Device
-  Class Ethernet Control Model.  This is used in some cable modems.
-  For more details on the specification, get the Communication Device
-  Class specification from <http://www.usb.org/>.
-
-  This driver should work with the following devices:
-        * Ericsson PipeRider (all variants)
-        * Motorola (DM100 and SB4100)
-        * Broadcom Cable Modem (reference design)
-        * Toshiba PCX1100U and possibly other cable modems
-
-  The device creates a network device (ethX, where X depends on what
-  other networking devices you have in use), as for a normal PCI
-  or ISA based ethernet network card.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called CDCEther.o.  If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_PWC
-  Say Y or M here if you want to use one of these Philips USB webcams:
-  PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
-  the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
-  by this driver and never will be.
-
-  This driver has an optional plugin, which is distributed as a binary
-  module only.  It contains code that allow you to use higher
-  resolutions and framerates but may not be distributed as source.
-  But even without this plugin you can these cams for most
-  applications.
-
-  See <file:Documentation/usb/philips.txt> for more information and
-  installation instructions.
-
-  The built-in microphone is enabled by selecting USB Audio support.
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Character Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called pwc.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_SE401
-  Say Y here if you want to connect this type of camera to your
-  computer's USB port. See <file:Documentation/usb/se401.txt> for more
-  information and for a list of supported cameras.
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Multimedia Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called se401.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_STV680
-  Say Y here if you want to connect this type of camera to your
-  computer's USB port. This includes the Pencam line of cameras.
-  See <file:Documentation/usb/stv680.txt> for more information and for
-  a list of supported cameras.
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Multimedia Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called stv680.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_VICAM
-  Say Y here if you have 3com homeconnect camera (vicam).
-
-  This driver uses the Video For Linux API. You must say Y or M to
-  "Video For Linux" (under Multimedia Devices) to use this driver.
-  Information on this API and pointers to "v4l" programs may be found
-  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called vicam.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_PEGASUS
-  Say Y here if you know you have Pegasus or Pegasus-II based adapter.
-  If in doubt then look at linux/drivers/usb/pegasus.h for the complete
-  list of supported devices.
-  If your particular adapter is not in the list and you are _sure_ it
-  is Pegasus or Pegasus II based then send me (pmanolov@users.sourceforge.net)
-  vendor and device IDs.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called pegasus.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_KAWETH
-  Say Y here if you want to use one of the following 10Mbps only
-  USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
-       3Com 3C19250
-       ADS USB-10BT
-       ATEN USB Ethernet
-       ASANTE USB To Ethernet Adapter
-       AOX Endpoints USB Ethernet
-       Correga K.K.
-       D-Link DSB-650C and DU-E10
-       Entrega / Portgear E45
-       I-O DATA USB-ET/T
-       Jaton USB Ethernet Device Adapter
-       Kingston Technology USB Ethernet Adapter
-       Linksys USB10T
-       Mobility USB-Ethernet Adapter
-       NetGear EA-101
-       Peracom Enet and Enet2
-       Portsmith Express Ethernet Adapter
-       Shark Pocket Adapter
-       SMC 2202USB
-       Sony Vaio port extender
-
-  This driver is likely to work with most 10Mbps only USB Ethernet
-  adapters, including some "no brand" devices. It does NOT work on
-  SmartBridges smartNIC or on Belkin F5U111 devices - you should use
-  the CATC NetMate driver for those. If you are not sure which one
-  you need, select both, and the correct one should be selected for
-  you.
-
-  This driver makes the adapter appear as a normal Ethernet interface,
-  typically on eth0, if it is the only ethernet device, or perhaps on
-  eth1, if you have a PCI or ISA ethernet card installed.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called kaweth.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_CATC
-  Say Y if you want to use one of the following 10Mbps USB Ethernet
-  device based on the EL1210A chip. Supported devices are:
-    Belkin F5U011
-    Belkin F5U111
-    CATC NetMate
-    CATC NetMate II
-    smartBridges smartNIC
-
-  This driver makes the adapter appear as a normal Ethernet interface,
-  typically on eth0, if it is the only ethernet device, or perhaps on
-  eth1, if you have a PCI or ISA ethernet card installed.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called catc.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_DC2XX
-  Say Y here if you want to connect this type of still camera to your
-  computer's USB port.  See <file:Documentation/usb/dc2xx.txt> for
-  more information; some non-Kodak cameras may also work with this
-  driver, given application support (such as <http://www.gphoto.org/>).
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called dc2xx.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_MDC800
-  Say Y here if you want to connect this type of still camera to
-  your computer's USB port. This driver can be used with gphoto 0.4.3
-  and higher (look at <http://www.gphoto.org/>).
-  To use it create a device node with "mknod /dev/mustek c 180 32" and
-  configure it in your software.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called mdc800.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_STORAGE
-  Say Y here if you want to connect USB mass storage devices to your
-  computer's USB port.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called usb-storage.o. If you want to compile it
-  as a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_STORAGE_DEBUG
-  Say Y here in order to have the USB Mass Storage code generate
-  verbose debugging messages.
-
-CONFIG_USB_STORAGE_ISD200
-  Say Y here if you want to use USB Mass Store devices based
-  on the In-Systems Design ISD-200 USB/ATA bridge.
-
-  Some of the products that use this chip are:
-
-    - Archos Jukebox 6000
-    - ISD SmartCable for Storage
-    - Taiwan Skymaster CD530U/DEL-0241 IDE bridge
-    - Sony CRX10U CD-R/RW drive
-    - CyQ've CQ8060A CDRW drive
-    - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
-
-CONFIG_USB_USS720
-  This driver is for USB parallel port adapters that use the Lucent
-  Technologies USS-720 chip. These cables are plugged into your USB
-  port and provide USB compatibility to peripherals designed with
-  parallel port interfaces.
-
-  The chip has two modes: automatic mode and manual mode. In automatic
-  mode, it looks to the computer like a standard USB printer. Only
-  printers may be connected to the USS-720 in this mode. The generic
-  USB printer driver ("USB Printer support", above) may be used in
-  that mode, and you can say N here if you want to use the chip only
-  in this mode.
-
-  Manual mode is not limited to printers, any parallel port
-  device should work. This driver utilizes manual mode.
-  Note however that some operations are three orders of magnitude
-  slower than on a PCI/ISA Parallel Port, so timing critical
-  applications might not work.
-
-  Say Y here if you own an USS-720 USB->Parport cable and intend to
-  connect anything other than a printer to it.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called uss720.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
 CONFIG_USB_DEVICEFS
   If you say Y here (and to "/proc file system support" in the "File
   systems section, above), you will get a file /proc/bus/usb/devices
@@ -485,8 +49,8 @@
   meaning they are generated on the fly and not stored on the hard
   drive.
 
-  You may need to mount the usbdevfs file system to see the files, use
-   mount -t usbdevfs none /proc/bus/usb
+  You may need to mount the usbfs file system to see the files, use
+     mount -t usbfs none /proc/bus/usb
 
   For the format of the various /proc/bus/usb/ files, please read
   <file:Documentation/usb/proc_usb_info.txt>.
@@ -505,124 +69,3 @@
   If you say N here, these conditions will cause warning messages
   about USB bandwidth usage to be logged and some devices or
   drivers may not work correctly.
-
-CONFIG_USB_DABUSB
-  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
-  brought to you by the DAB-Team (<http://dab.in.tum.de/>).  This
-  driver can be taken as an example for URB-based bulk, control, and
-  isochronous transactions. URB's are explained in
-  <file:Documentation/usb/URB.txt>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called dabusb.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_KONICAWC
-  Say Y here if you want support for webcams based on a Konica
-  chipset. This is known to work with the Intel YC76 webcam.
-
-  This driver uses the Video For Linux API.  You must enable
-  (Y or M in config) Video For Linux (under Character Devices)
-  to use this driver.  Information on this API and pointers to
-  "v4l" programs may be found on the WWW at
-  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called konicawc.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_USBNET
-  This driver supports network links over USB with USB "Network"
-  or "data transfer" cables, often used to network laptops to PCs.
-  Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
-  (GeneLink), NetChip and Prolific. Intelligent USB devices could also
-  use this approach to provide Internet access, using standard USB
-  cabling. You can find these chips also on some motherboards with
-  USB PC2PC support.
-
-  These links will have names like "usb0", "usb1", etc.  They act
-  like two-node Ethernets, so you can use 802.1d Ethernet Bridging
-  (CONFIG_BRIDGE) to simplify your network routing.
-
-  This code is also available as a kernel module (code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called usbnet.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_STORAGE_FREECOM
-  Support for the Freecom USB to IDE/ATAPI adaptor.
-  Freecom has a web page at <http://www.freecom.de/>.
-
-CONFIG_USB_STORAGE_DPCM
-  Say Y here to support the Microtech ZiO! CompactFlash/SmartMedia
-  reader, details at <http://www.microtechint.com/zio/index.html>.
-  This driver treats the flash card as a removable storage device.
-
-CONFIG_USB_STORAGE_SDDR09
-  Say Y here to include additional code to support the Sandisk SDDR-09
-  SmartMedia reader in the USB Mass Storage driver.
-
-CONFIG_USB_RIO500
-  Say Y here if you want to connect a USB Rio500 mp3 player to your
-  computer's USB port. Please read <file:Documentation/usb/rio.txt>
-  for more information.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called rio500.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_AUERSWALD
-  Say Y here if you want to connect an Auerswald USB ISDN Device
-  to your computer's USB port.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called auerswald.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_DSBR
-  Say Y here if you want to connect this type of radio to your
-  computer's USB port. Note that the audio is not digital, and
-  you must connect the line out connector to a sound card or a
-  set of speakers.
-
-  This driver uses the Video For Linux API.  You must enable
-  (Y or M in config) Video For Linux (under Character Devices)
-  to use this driver.  Information on this API and pointers to
-  "v4l" programs may be found on the WWW at
-  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called dsbr100.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_MICROTEK
-  Say Y here if you want support for the Microtek X6USB and
-  possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
-  Support for anything but the X6 is experimental.
-  Please report failures and successes.
-  The scanner will appear as a scsi generic device to the rest
-  of the system. Scsi support is required.
-  This driver can be compiled as a module, called microtek.o.
-
-CONFIG_USB_HPUSBSCSI
-  Say Y here if you want support for the HP 53xx series of scanners
-  and the Minolta Scan Dual. This driver is experimental.
-  The scanner will be accessible as a SCSI device.
-  This can be compiled as a module, called hpusbscsi.o.
-
-CONFIG_USB_BLUETOOTH
-  Say Y here if you want to connect a USB Bluetooth device to your
-  computer's USB port. You will need the Bluetooth stack (available
-  at <http://developer.axis.com/software/index.shtml>) to fully use
-  the device.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called bluetooth.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
-
diff -Nru a/drivers/usb/Config.in b/drivers/usb/Config.in
--- a/drivers/usb/Config.in	Sun Apr 14 12:16:57 2002
+++ b/drivers/usb/Config.in	Sun Apr 14 12:16:57 2002
@@ -6,101 +6,41 @@
 
 dep_tristate 'Support for USB' CONFIG_USB $CONFIG_PCI
 if [ "$CONFIG_USB" = "y" -o  "$CONFIG_USB" = "m" ]; then
-   bool '  USB verbose debug messages' CONFIG_USB_DEBUG
+   source drivers/usb/core/Config.in
 
-   comment 'Miscellaneous USB options'
-   bool '  USB device filesystem' CONFIG_USB_DEVICEFS
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      bool '  Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
-   else
-      define_bool CONFIG_USB_BANDWIDTH n
-   fi
-   bool '  Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
+   source drivers/usb/host/Config.in
 
-   comment 'USB Host Controller Drivers'
-   source drivers/usb/hcd/Config.in
-   if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
-      dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
-   fi
-   if [ "$CONFIG_USB_UHCI" != "y" ]; then
-      dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
-   else
-      define_bool CONFIG_USB_UHCI_ALT n
-   fi
-   dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
+   source drivers/usb/class/Config.in
 
-   comment 'USB Device Class drivers'
-   dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
-   dep_tristate '    EMI 2|6 USB Audio interface support' CONFIG_USB_EMI26 $CONFIG_USB_AUDIO
-   dep_tristate '  USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL
-   if [ "$CONFIG_SCSI" = "n" ]; then
-      comment '  SCSI support is needed for USB Storage'
-   fi
-   dep_tristate '  USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
-      dep_mbool '    USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
-      dep_mbool '    Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
-      dep_mbool '    Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM  $CONFIG_USB_STORAGE
-      dep_mbool '    ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
-      dep_mbool '    Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
-      dep_mbool '    HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
-      dep_mbool '    SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
-      dep_mbool '    Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
-   dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
-
-   comment 'USB Human Interface Devices (HID)'
-   if [ "$CONFIG_INPUT" = "n" ]; then
-      comment '  Input core support is needed for USB HID'
-   else
-      dep_tristate '  USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB $CONFIG_INPUT
-         dep_mbool '    /dev/hiddev raw HID device support (EXPERIMENTAL)' CONFIG_USB_HIDDEV $CONFIG_USB_HID
-      if [ "$CONFIG_USB_HID" != "y" ]; then
-         dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
-         dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
-      fi
-      dep_tristate '  Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
-   fi
+   source drivers/usb/storage/Config.in
 
-   comment 'USB Imaging devices'
-   dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
-   dep_tristate '  USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
-   dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
-   dep_tristate '  Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
-   dep_tristate '  HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
-
-   comment 'USB Multimedia devices'
-   if [ "$CONFIG_VIDEO_DEV" = "n" ]; then
-      comment '  Video4Linux support is needed for USB Multimedia device support'
-   else
-      dep_tristate '  USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
-      dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
-      dep_tristate '  USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
-      dep_tristate '  USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
-      dep_tristate '  USB STV680 (Pencam) Camera support' CONFIG_USB_STV680 $CONFIG_USB $CONFIG_VIDEO_DEV
-      dep_tristate '  USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
-      dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
-      dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
-      dep_tristate '  USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV
-   fi
+   source drivers/usb/input/Config.in
+ 
+   source drivers/usb/image/Config.in
 
-   comment 'USB Network adaptors'
-   if [ "$CONFIG_NET" = "n" ]; then
-      comment '  Networking support is needed for USB Networking device support'
-   else
-      dep_tristate '  USB Pegasus/Pegasus-II based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-      dep_tristate '  USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-      dep_tristate '  USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-      dep_tristate '  USB Communication Class Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-      dep_tristate '  USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
-   fi
+   source drivers/usb/media/Config.in
+
+   source drivers/usb/net/Config.in
 
    comment 'USB port drivers'
    dep_tristate '  USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
+
    source drivers/usb/serial/Config.in
 
    comment 'USB Miscellaneous drivers'
-   dep_tristate '  USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
+   dep_tristate '  EMI 2|6 USB Audio interface support' CONFIG_USB_EMI26 $CONFIG_USB_AUDIO
+   dep_tristate '  Texas Instruments Graph Link USB (aka SilverLink) cable support' CONFIG_USB_TIGL $CONFIG_USB
    dep_tristate '  USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD $CONFIG_USB $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL
+
+   # Turn on CONFIG_USB_MISC if any of the drivers are compiled into the kernel
+   # to make our Makefile logic a bit simpler
+   if [ "$CONFIG_USB_USS720" = "y" -o "$CONFIG_USB_EMI26" = "y" -o "$CONFIG_USB_RIO500" = "y" ]; then
+      define_bool CONFIG_USB_MISC y
+   fi
+   if [ "$CONFIG_USB_AUERSWALD" = "y" -o "$CONFIG_USB_TIGL" = "y" ]; then
+      define_bool CONFIG_USB_MISC y
+   fi
 
 fi
 endmenu
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	Sun Apr 14 12:16:59 2002
+++ b/drivers/usb/Makefile	Sun Apr 14 12:16:59 2002
@@ -2,116 +2,90 @@
 # Makefile for the kernel USB device drivers.
 #
 
-# Subdirs.
-
-# The target object and module list name.
-
 O_TARGET	:= usbdrv.o
 
-# Objects that export symbols.
-
-export-objs		:= usb.o hcd.o ov511.o pwc-uncompress.o
-
-# Multipart objects.
-
-list-multi		:= usbcore.o hid.o pwc.o
-usbcore-objs		:= usb.o usb-debug.o hub.o hcd.o
-hid-objs		:= hid-core.o hid-input.o
-pwc-objs		:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
-
-
-# Optional parts of multipart objects.
-
-ifeq ($(CONFIG_USB_DEVICEFS),y)
-	usbcore-objs	+= devio.o inode.o drivers.o devices.o
-endif
+# Object files in subdirectories
+mod-subdirs	:= core host class media net serial storage image misc input
 
-ifeq ($(CONFIG_USB_HIDDEV),y)
-	hid-objs	+= hiddev.o
+subdir-$(CONFIG_USB)		+= core
+ifeq ($(CONFIG_USB),y)
+	obj-y += core/usb-core.o
+endif
+
+subdir-$(CONFIG_USB_EHCI_HCD)	+= host
+subdir-$(CONFIG_USB_OHCI_HCD)	+= host
+subdir-$(CONFIG_USB_OHCI)	+= host
+subdir-$(CONFIG_USB_UHCI_ALT)	+= host
+subdir-$(CONFIG_USB_UHCI)	+= host
+ifeq ($(CONFIG_USB_HOST),y)
+	obj-y += host/usb-host.o
+endif
+
+subdir-$(CONFIG_USB_ACM)	+= class
+subdir-$(CONFIG_USB_AUDIO)	+= class
+subdir-$(CONFIG_USB_BLUETOOTH)	+= class
+subdir-$(CONFIG_USB_PRINTER)	+= class
+ifeq ($(CONFIG_USB_CLASS),y)
+	obj-y += class/usb-class.o
 endif
 
-# Object file lists.
-
-obj-y	:=
-obj-m	:=
-obj-n	:=
-obj-	:=
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_USB)		+= usbcore.o
-
-# EHCI needs to be linked before the other HCD drivers
-ifeq ($(CONFIG_USB_EHCI_HCD),y)
-	obj-y += hcd/ehci-hcd.o
+subdir-$(CONFIG_USB_STORAGE)	+= storage
+ifeq ($(CONFIG_USB_STORAGE),y)
+	obj-y += storage/storage.o
 endif
 
-ifeq ($(CONFIG_USB_OHCI_HCD),y)
-	obj-y += hcd/ohci-hcd.o
+subdir-$(CONFIG_USB_HID)	+= input
+subdir-$(CONFIG_USB_KBD)	+= input
+subdir-$(CONFIG_USB_MOUSE)	+= input
+subdir-$(CONFIG_USB_WACOM)	+= input
+ifeq ($(CONFIG_USB_INPUT),y)
+	obj-y += input/usb-input.o
+endif
+
+subdir-$(CONFIG_USB_DABUSB)	+= media
+subdir-$(CONFIG_USB_DSBR)	+= media
+subdir-$(CONFIG_USB_IBMCAM)	+= media
+subdir-$(CONFIG_USB_KONICAWC)	+= media
+subdir-$(CONFIG_USB_OV511)	+= media
+subdir-$(CONFIG_USB_PWC)	+= media
+subdir-$(CONFIG_USB_SE401)	+= media
+subdir-$(CONFIG_USB_STV680)	+= media
+subdir-$(CONFIG_USB_VICAM)	+= media
+ifeq ($(CONFIG_USB_MEDIA),y)
+	obj-y += media/usb-media.o
+endif
+
+subdir-$(CONFIG_USB_CATC)	+= net
+subdir-$(CONFIG_USB_CDCETHER)	+= net
+subdir-$(CONFIG_USB_KAWETH)	+= net
+subdir-$(CONFIG_USB_PEGASUS)	+= net
+subdir-$(CONFIG_USB_RTL8150)	+= net
+subdir-$(CONFIG_USB_USBNET)	+= net
+ifeq ($(CONFIG_USB_NET),y)
+	obj-y += net/usb-net.o
+endif
+
+subdir-$(CONFIG_USB_DC2XX)	+= image
+subdir-$(CONFIG_USB_HPUSBSCSI)	+= image
+subdir-$(CONFIG_USB_MDC800)	+= image
+subdir-$(CONFIG_USB_MICROTEK)	+= image
+subdir-$(CONFIG_USB_SCANNER)	+= image
+ifeq ($(CONFIG_USB_IMAGE),y)
+	obj-y += image/usb-image.o
 endif
 
-obj-$(CONFIG_USB_UHCI)		+= usb-uhci.o
-obj-$(CONFIG_USB_UHCI_ALT)	+= uhci.o
-obj-$(CONFIG_USB_OHCI)		+= usb-ohci.o
-
-obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o
-obj-$(CONFIG_USB_HID)		+= hid.o
-obj-$(CONFIG_USB_KBD)		+= usbkbd.o
-obj-$(CONFIG_USB_WACOM)		+= wacom.o
-
-obj-$(CONFIG_USB_SCANNER)	+= scanner.o
-obj-$(CONFIG_USB_ACM)		+= acm.o
-obj-$(CONFIG_USB_PRINTER)	+= printer.o
-obj-$(CONFIG_USB_AUDIO)		+= audio.o
-obj-$(CONFIG_USB_EMI26)		+= emi26.o
-obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o usbvideo.o ultracam.o
-obj-$(CONFIG_USB_KONICAWC)	+= konicawc.o usbvideo.o
-obj-$(CONFIG_USB_PWC)		+= pwc.o
-obj-$(CONFIG_USB_DC2XX)		+= dc2xx.o
-obj-$(CONFIG_USB_MDC800)	+= mdc800.o
-obj-$(CONFIG_USB_USS720)	+= uss720.o
-obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
-obj-$(CONFIG_USB_VICAM)		+= vicam.o
-obj-$(CONFIG_USB_OV511)		+= ov511.o
-obj-$(CONFIG_USB_SE401)		+= se401.o
-obj-$(CONFIG_USB_STV680)	+= stv680.o
-obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
-obj-$(CONFIG_USB_CATC)		+= catc.o
-obj-$(CONFIG_USB_KAWETH)        += kaweth.o
-obj-$(CONFIG_USB_CDCETHER)	+= CDCEther.o
-obj-$(CONFIG_USB_RIO500)	+= rio500.o
-obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
-obj-$(CONFIG_USB_MICROTEK)	+= microtek.o
-obj-$(CONFIG_USB_HPUSBSCSI)	+= hpusbscsi.o
-obj-$(CONFIG_USB_BLUETOOTH)	+= bluetooth.o
-obj-$(CONFIG_USB_USBNET)	+= usbnet.o
-obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
-
-# Object files in subdirectories
-mod-subdirs	:= serial hcd
-
-subdir-$(CONFIG_USB_EHCI_HCD)	+= hcd
-subdir-$(CONFIG_USB_OHCI_HCD)	+= hcd
 subdir-$(CONFIG_USB_SERIAL)	+= serial
-subdir-$(CONFIG_USB_STORAGE)	+= storage
-
 ifeq ($(CONFIG_USB_SERIAL),y)
 	obj-y += serial/usb-serial.o
 endif
 
-ifeq ($(CONFIG_USB_STORAGE),y)
-	obj-y += storage/storage.o
+subdir-$(CONFIG_USB_AUERSWALD)	+= misc
+subdir-$(CONFIG_USB_EMI26)	+= misc
+subdir-$(CONFIG_USB_RIO500)	+= misc
+subdir-$(CONFIG_USB_TIGL)	+= misc
+subdir-$(CONFIG_USB_USS720)	+= misc
+ifeq ($(CONFIG_USB_MISC),y)
+	obj-y += misc/usb-misc.o
 endif
 
 include $(TOPDIR)/Rules.make
-
-# Link rules for multi-part drivers.
-
-usbcore.o: $(usbcore-objs)
-	$(LD) -r -o $@ $(usbcore-objs)
-
-hid.o: $(hid-objs)
-	$(LD) -r -o $@ $(hid-objs)
-
-pwc.o: $(pwc-objs)
-	$(LD) -r -o $@ $(pwc-objs)
diff -Nru a/drivers/usb/Makefile.lib b/drivers/usb/Makefile.lib
--- a/drivers/usb/Makefile.lib	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1 +0,0 @@
-obj-$(CONFIG_USB_CATC)		+= crc32.o
diff -Nru a/drivers/usb/README b/drivers/usb/README
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/README	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,33 @@
+Here is a list of what each subdirectory here is, and what is contained in
+them.
+
+core/		- This is for the core USB host code, including the
+		  usbfs files.
+
+host/		- This is for all of the USB host drivers.  This
+		  includes UHCI, OHCI, EHCI, and any others that might
+		  be created in the future.
+
+device/		- This is for all of the USB device controller drivers. 
+
+
+Individual USB driver directories.  A new driver should be added to the
+first subdirectory in the list below that it fits into.
+
+image/		- This is for still image drivers, like scanners or
+		  digital cameras.
+input/		- This if for any driver that uses the input subsystem,
+		  like keyboard, mice, touchscreens, tablets, etc.
+media/		- This is for multimedia drivers, like video cameras,
+		  radios, and any other drivers that talk to the v4l
+		  subsystem.
+net/		- This is for network drivers.
+serial/		- This is for USB to serial drivers.
+storage/	- This is for USB mass-storage drivers.
+class/		- This is for all USB device drivers that do not fit
+		  into any of the above categories, and work for a range
+		  of USB Class specified devices. 
+misc/		- This is for all USB device drivers that do not fit
+		  into any of the above categories.
+	  
+
diff -Nru a/drivers/usb/acm.c b/drivers/usb/acm.c
--- a/drivers/usb/acm.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,739 +0,0 @@
-/*
- * acm.c  Version 0.21
- *
- * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
- * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
- * Copyright (c) 1999 Johannes Erdfelt	<johannes@erdfelt.com>
- * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
- *
- * USB Abstract Control Model driver for USB modems and ISDN adapters
- *
- * Sponsored by SuSE
- *
- * ChangeLog:
- *	v0.9  - thorough cleaning, URBification, almost a rewrite
- *	v0.10 - some more cleanups
- *	v0.11 - fixed flow control, read error doesn't stop reads
- *	v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
- *	v0.13 - added termios, added hangup
- *	v0.14 - sized down struct acm
- *	v0.15 - fixed flow control again - characters could be lost
- *	v0.16 - added code for modems with swapped data and control interfaces
- *	v0.17 - added new style probing
- *	v0.18 - fixed new style probing for devices with more configurations
- *	v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan)
- *	v0.20 - switched to probing on interface (rather than device) class
- *	v0.21 - revert to probing on device for devices with multiple configs
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/smp_lock.h>
-#undef DEBUG
-#include <linux/usb.h>
-#include <asm/byteorder.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.21"
-#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
-#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
-
-/*
- * CMSPAR, some architectures can't have space and mark parity.
- */
-
-#ifndef CMSPAR
-#define CMSPAR			0
-#endif
-
-/*
- * Major and minor numbers.
- */
-
-#define ACM_TTY_MAJOR		166
-#define ACM_TTY_MINORS		32
-
-/*
- * Requests.
- */
-
-#define USB_RT_ACM		(USB_TYPE_CLASS | USB_RECIP_INTERFACE)
-
-#define ACM_REQ_COMMAND		0x00
-#define ACM_REQ_RESPONSE	0x01
-#define ACM_REQ_SET_FEATURE	0x02
-#define ACM_REQ_GET_FEATURE	0x03
-#define ACM_REQ_CLEAR_FEATURE	0x04
-
-#define ACM_REQ_SET_LINE	0x20
-#define ACM_REQ_GET_LINE	0x21
-#define ACM_REQ_SET_CONTROL	0x22
-#define ACM_REQ_SEND_BREAK	0x23
-
-/*
- * IRQs.
- */
-
-#define ACM_IRQ_NETWORK		0x00
-#define ACM_IRQ_LINE_STATE	0x20
-
-/*
- * Output control lines.
- */
-
-#define ACM_CTRL_DTR		0x01
-#define ACM_CTRL_RTS		0x02
-
-/*
- * Input control lines and line errors.
- */
-
-#define ACM_CTRL_DCD		0x01
-#define ACM_CTRL_DSR		0x02
-#define ACM_CTRL_BRK		0x04
-#define ACM_CTRL_RI		0x08
-
-#define ACM_CTRL_FRAMING	0x10
-#define ACM_CTRL_PARITY		0x20
-#define ACM_CTRL_OVERRUN	0x40
-
-/*
- * Line speed and caracter encoding.
- */
-
-struct acm_line {
-	__u32 speed;
-	__u8 stopbits;
-	__u8 parity;
-	__u8 databits;
-} __attribute__ ((packed));
-
-/*
- * Internal driver structures.
- */
-
-struct acm {
-	struct usb_device *dev;				/* the coresponding usb device */
-	struct usb_interface *iface;			/* the interfaces - +0 control +1 data */
-	struct tty_struct *tty;				/* the coresponding tty */
-	struct urb ctrlurb, readurb, writeurb;		/* urbs */
-	struct acm_line line;				/* line coding (bits, stop, parity) */
-	struct tq_struct tqueue;			/* task queue for line discipline waking up */
-	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
-	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
-	unsigned int writesize;				/* max packet size for the output bulk endpoint */
-	unsigned int used;				/* someone has this acm's device open */
-	unsigned int minor;				/* acm minor number */
-	unsigned char throttle;				/* throttled by tty layer */
-	unsigned char clocal;				/* termios CLOCAL */
-};
-
-static struct usb_driver acm_driver;
-static struct tty_driver acm_tty_driver;
-static struct acm *acm_table[ACM_TTY_MINORS];
-
-#define ACM_READY(acm)	(acm && acm->dev && acm->used)
-
-/*
- * Functions for ACM control messages.
- */
-
-static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
-{
-	int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
-		request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
-	dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
-	return retval < 0 ? retval : 0;
-}
-
-#define acm_set_control(acm, control)	acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
-#define acm_set_line(acm, line)		acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
-#define acm_send_break(acm, ms)		acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
-
-/*
- * Interrupt handler for various ACM control events
- */
-
-static void acm_ctrl_irq(struct urb *urb)
-{
-	struct acm *acm = urb->context;
-	struct usb_ctrlrequest *dr = urb->transfer_buffer;
-	unsigned char *data = (unsigned char *)(dr + 1);
-	int newctrl;
-
-	if (!ACM_READY(acm)) return;
-
-	if (urb->status < 0) {
-		dbg("nonzero ctrl irq status received: %d", urb->status);
-		return;
-	}
-
-	switch (dr->bRequest) {
-
-		case ACM_IRQ_NETWORK:
-
-			dbg("%s network", data[0] ? "connected to" : "disconnected from");
-			return;
-
-		case ACM_IRQ_LINE_STATE:
-
-			newctrl = le16_to_cpup((__u16 *) data);
-
-			if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
-				dbg("calling hangup");
-				tty_hangup(acm->tty);
-			}
-
-			acm->ctrlin = newctrl;
-
-			dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
-				acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',	acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
-				acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',	acm->ctrlin & ACM_CTRL_RI  ? '+' : '-',
-				acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',	acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
-				acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
-
-			return;
-
-		default:
-			dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
-				dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
-			return;
-	}
-}
-
-static void acm_read_bulk(struct urb *urb)
-{
-	struct acm *acm = urb->context;
-	struct tty_struct *tty = acm->tty;
-	unsigned char *data = urb->transfer_buffer;
-	int i = 0;
-
-	if (!ACM_READY(acm)) return;
-
-	if (urb->status)
-		dbg("nonzero read bulk status received: %d", urb->status);
-
-	if (!urb->status & !acm->throttle)  {
-		for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters,
-			 * we drop them. */
-			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			tty_insert_flip_char(tty, data[i], 0);
-		}
-		tty_flip_buffer_push(tty);
-	}
-
-	if (acm->throttle) {
-		memmove(data, data + i, urb->actual_length - i);
-		urb->actual_length -= i;
-		return;
-	}
-
-	urb->actual_length = 0;
-	urb->dev = acm->dev;
-
-	if (usb_submit_urb(urb, GFP_KERNEL))
-		dbg("failed resubmitting read urb");
-}
-
-static void acm_write_bulk(struct urb *urb)
-{
-	struct acm *acm = (struct acm *)urb->context;
-
-	if (!ACM_READY(acm)) return;
-
-	if (urb->status)
-		dbg("nonzero write bulk status received: %d", urb->status);
-
-	queue_task(&acm->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-static void acm_softint(void *private)
-{
-	struct acm *acm = private;
-	struct tty_struct *tty = acm->tty;
-
-	if (!ACM_READY(acm)) return;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
-	wake_up_interruptible(&tty->write_wait);
-}
-
-/*
- * TTY handlers
- */
-
-static int acm_tty_open(struct tty_struct *tty, struct file *filp)
-{
-	struct acm *acm = acm_table[minor(tty->device)];
-
-	if (!acm || !acm->dev) return -EINVAL;
-
-	tty->driver_data = acm;
-	acm->tty = tty;
-
-	MOD_INC_USE_COUNT;
-
-        lock_kernel();
-
-	if (acm->used++) {
-                unlock_kernel();
-                return 0;
-        }
-
-        unlock_kernel();
-
-	acm->ctrlurb.dev = acm->dev;
-	if (usb_submit_urb(&acm->ctrlurb, GFP_KERNEL))
-		dbg("usb_submit_urb(ctrl irq) failed");
-
-	acm->readurb.dev = acm->dev;
-	if (usb_submit_urb(&acm->readurb, GFP_KERNEL))
-		dbg("usb_submit_urb(read bulk) failed");
-
-	acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
-
-	/* force low_latency on so that our tty_push actually forces the data through, 
-	   otherwise it is scheduled, and with high data rates data can get lost. */
-	tty->low_latency = 1;
-
-	return 0;
-}
-
-static void acm_tty_close(struct tty_struct *tty, struct file *filp)
-{
-	struct acm *acm = tty->driver_data;
-
-	if (!acm || !acm->used) return;
-
-	if (!--acm->used) {
-		if (acm->dev) {
-			acm_set_control(acm, acm->ctrlout = 0);
-			usb_unlink_urb(&acm->ctrlurb);
-			usb_unlink_urb(&acm->writeurb);
-			usb_unlink_urb(&acm->readurb);
-		} else {
-			tty_unregister_devfs(&acm_tty_driver, acm->minor);
-			acm_table[acm->minor] = NULL;
-			kfree(acm);
-		}
-	}
-	MOD_DEC_USE_COUNT;
-}
-
-static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
-{
-	struct acm *acm = tty->driver_data;
-
-	if (!ACM_READY(acm)) return -EINVAL;
-	if (acm->writeurb.status == -EINPROGRESS) return 0;
-	if (!count) return 0;
-
-	count = (count > acm->writesize) ? acm->writesize : count;
-
-	if (from_user)
-		copy_from_user(acm->writeurb.transfer_buffer, buf, count);
-	else
-		memcpy(acm->writeurb.transfer_buffer, buf, count);
-
-	acm->writeurb.transfer_buffer_length = count;
-	acm->writeurb.dev = acm->dev;
-
-	if (usb_submit_urb(&acm->writeurb, GFP_KERNEL))
-		dbg("usb_submit_urb(write bulk) failed");
-
-	return count;
-}
-
-static int acm_tty_write_room(struct tty_struct *tty)
-{
-	struct acm *acm = tty->driver_data;
-	if (!ACM_READY(acm)) return -EINVAL;
-	return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize;
-}
-
-static int acm_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct acm *acm = tty->driver_data;
-	if (!ACM_READY(acm)) return -EINVAL;
-	return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length : 0;
-}
-
-static void acm_tty_throttle(struct tty_struct *tty)
-{
-	struct acm *acm = tty->driver_data;
-	if (!ACM_READY(acm)) return;
-	acm->throttle = 1;
-}
-
-static void acm_tty_unthrottle(struct tty_struct *tty)
-{
-	struct acm *acm = tty->driver_data;
-	if (!ACM_READY(acm)) return;
-	acm->throttle = 0;
-	if (acm->readurb.status != -EINPROGRESS)
-		acm_read_bulk(&acm->readurb);
-}
-
-static void acm_tty_break_ctl(struct tty_struct *tty, int state)
-{
-	struct acm *acm = tty->driver_data;
-	if (!ACM_READY(acm)) return;
-	if (acm_send_break(acm, state ? 0xffff : 0))
-		dbg("send break failed");
-}
-
-static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct acm *acm = tty->driver_data;
-	unsigned int mask, newctrl;
-
-	if (!ACM_READY(acm)) return -EINVAL;
-
-	switch (cmd) {
-
-		case TIOCMGET:
-
-			return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
-				(acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
-				(acm->ctrlin  & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
-				(acm->ctrlin  & ACM_CTRL_RI  ? TIOCM_RI  : 0) |
-				(acm->ctrlin  & ACM_CTRL_DCD ? TIOCM_CD  : 0) |
-				 TIOCM_CTS, (unsigned long *) arg);
-
-		case TIOCMSET:
-		case TIOCMBIS:
-		case TIOCMBIC:
-
-			if (get_user(mask, (unsigned long *) arg))
-				return -EFAULT;
-
-			newctrl = acm->ctrlout;
-			mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
-
-			switch (cmd) {
-				case TIOCMSET: newctrl  =  mask; break;
-				case TIOCMBIS: newctrl |=  mask; break;
-				case TIOCMBIC: newctrl &= ~mask; break;
-			}
-
-			if (acm->ctrlout == newctrl) return 0;
-			return acm_set_control(acm, acm->ctrlout = newctrl);
-	}
-
-	return -ENOIOCTLCMD;
-}
-
-static __u32 acm_tty_speed[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600,
-	1200, 1800, 2400, 4800, 9600, 19200, 38400,
-	57600, 115200, 230400, 460800, 500000, 576000,
-	921600, 1000000, 1152000, 1500000, 2000000,
-	2500000, 3000000, 3500000, 4000000
-};
-
-static __u8 acm_tty_size[] = {
-	5, 6, 7, 8
-};
-
-static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
-{
-	struct acm *acm = tty->driver_data;
-	struct termios *termios = tty->termios;
-	struct acm_line newline;
-	int newctrl = acm->ctrlout;
-
-	if (!ACM_READY(acm)) return;
-
-	newline.speed = cpu_to_le32p(acm_tty_speed +
-		(termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
-	newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
-	newline.parity = termios->c_cflag & PARENB ?
-		(termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
-	newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
-
-	acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
-
-	if (!newline.speed) {
-		newline.speed = acm->line.speed;
-		newctrl &= ~ACM_CTRL_DTR;
-	} else  newctrl |=  ACM_CTRL_DTR;
-
-	if (newctrl != acm->ctrlout)
-		acm_set_control(acm, acm->ctrlout = newctrl);
-
-	if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
-		memcpy(&acm->line, &newline, sizeof(struct acm_line));
-		dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
-		acm_set_line(acm, &acm->line);
-	}
-}
-
-/*
- * USB probe and disconnect routines.
- */
-
-static void *acm_probe(struct usb_device *dev, unsigned int ifnum,
-		       const struct usb_device_id *id)
-{
-	struct acm *acm;
-	struct usb_config_descriptor *cfacm;
-	struct usb_interface_descriptor *ifcom, *ifdata;
-	struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
-	int readsize, ctrlsize, minor, i;
-	unsigned char *buf;
-
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-
-		cfacm = dev->config + i;
-
-		dbg("probing config %d", cfacm->bConfigurationValue);
-
-		if (cfacm->bNumInterfaces != 2 ||
-		    usb_interface_claimed(cfacm->interface + 0) ||
-		    usb_interface_claimed(cfacm->interface + 1))
-			continue;
-
-		ifcom = cfacm->interface[0].altsetting + 0;
-		ifdata = cfacm->interface[1].altsetting + 0;
-
-		if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) {
-			ifcom = cfacm->interface[1].altsetting + 0;
-			ifdata = cfacm->interface[0].altsetting + 0;
-			if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2)
-				continue;
-		}
-
-		if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
-		    ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1)
-			continue;
-
-		epctrl = ifcom->endpoint + 0;
-		epread = ifdata->endpoint + 0;
-		epwrite = ifdata->endpoint + 1;
-
-		if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
-		   (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
-		   ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
-			continue;
-
-		if ((epread->bEndpointAddress & 0x80) != 0x80) {
-			epread = ifdata->endpoint + 1;
-			epwrite = ifdata->endpoint + 0;
-		}
-
-		usb_set_configuration(dev, cfacm->bConfigurationValue);
-
-		for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
-		if (acm_table[minor]) {
-			err("no more free acm devices");
-			return NULL;
-		}
-
-		if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
-			err("out of memory");
-			return NULL;
-		}
-		memset(acm, 0, sizeof(struct acm));
-
-		ctrlsize = epctrl->wMaxPacketSize;
-		readsize = epread->wMaxPacketSize;
-		acm->writesize = epwrite->wMaxPacketSize;
-		acm->iface = cfacm->interface;
-		acm->minor = minor;
-		acm->dev = dev;
-
-		acm->tqueue.routine = acm_softint;
-		acm->tqueue.data = acm;
-
-		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
-			err("out of memory");
-			kfree(acm);
-			return NULL;
-		}
-
-		FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
-			buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
-
-		FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
-			buf += ctrlsize, readsize, acm_read_bulk, acm);
-		acm->readurb.transfer_flags |= USB_NO_FSBR;
-
-		FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
-			buf += readsize, acm->writesize, acm_write_bulk, acm);
-		acm->writeurb.transfer_flags |= USB_NO_FSBR;
-
-		printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
-
-		acm_set_control(acm, acm->ctrlout);
-
-		acm->line.speed = cpu_to_le32(9600);
-		acm->line.databits = 8;
-		acm_set_line(acm, &acm->line);
-
-		usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
-		usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
-
-		tty_register_devfs(&acm_tty_driver, 0, minor);
-		return acm_table[minor] = acm;
-	}
-
-	return NULL;
-}
-
-static void acm_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct acm *acm = ptr;
-
-	if (!acm || !acm->dev) {
-		dbg("disconnect on nonexisting interface");
-		return;
-	}
-
-	acm->dev = NULL;
-
-	usb_unlink_urb(&acm->ctrlurb);
-	usb_unlink_urb(&acm->readurb);
-	usb_unlink_urb(&acm->writeurb);
-
-	kfree(acm->ctrlurb.transfer_buffer);
-
-	usb_driver_release_interface(&acm_driver, acm->iface + 0);
-	usb_driver_release_interface(&acm_driver, acm->iface + 1);
-
-	if (!acm->used) {
-		tty_unregister_devfs(&acm_tty_driver, acm->minor);
-		acm_table[acm->minor] = NULL;
-		kfree(acm);
-		return;
-	}
-
-	if (acm->tty)
-		tty_hangup(acm->tty);
-}
-
-/*
- * USB driver structure.
- */
-
-static struct usb_device_id acm_ids[] = {
-	{ USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE (usb, acm_ids);
-
-static struct usb_driver acm_driver = {
-	name:		"acm",
-	probe:		acm_probe,
-	disconnect:	acm_disconnect,
-	id_table:	acm_ids,
-};
-
-/*
- * TTY driver structures.
- */
-
-static int acm_tty_refcount;
-
-static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
-static struct termios *acm_tty_termios[ACM_TTY_MINORS];
-static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
-
-static struct tty_driver acm_tty_driver = {
-	magic:			TTY_DRIVER_MAGIC,
-	driver_name:		"acm",
-	name:			"usb/acm/%d",
-	major:			ACM_TTY_MAJOR,
-	minor_start:		0,
-	num:			ACM_TTY_MINORS,
-	type:			TTY_DRIVER_TYPE_SERIAL,
-	subtype:		SERIAL_TYPE_NORMAL,
-	flags:			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
-
-	refcount:		&acm_tty_refcount,
-
-	table:			acm_tty_table,
-	termios:		acm_tty_termios,
-	termios_locked:		acm_tty_termios_locked,
-
-	open:			acm_tty_open,
-	close:			acm_tty_close,
-	write:			acm_tty_write,
-	write_room:		acm_tty_write_room,
-	ioctl:			acm_tty_ioctl,
-	throttle:		acm_tty_throttle,
-	unthrottle:		acm_tty_unthrottle,
-	chars_in_buffer:	acm_tty_chars_in_buffer,
-	break_ctl:		acm_tty_break_ctl,
-	set_termios:		acm_tty_set_termios
-};
-
-/*
- * Init / exit.
- */
-
-static int __init acm_init(void)
-{
-	acm_tty_driver.init_termios =		tty_std_termios;
-	acm_tty_driver.init_termios.c_cflag =	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-
-	if (tty_register_driver(&acm_tty_driver))
-		return -1;
-
-	if (usb_register(&acm_driver) < 0) {
-		tty_unregister_driver(&acm_tty_driver);
-		return -1;
-	}
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-}
-
-static void __exit acm_exit(void)
-{
-	usb_deregister(&acm_driver);
-	tty_unregister_driver(&acm_tty_driver);
-}
-
-module_init(acm_init);
-module_exit(acm_exit);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/audio.c b/drivers/usb/audio.c
--- a/drivers/usb/audio.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,3874 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	audio.c  --  USB Audio Class driver
- *
- *	Copyright (C) 1999, 2000, 2001
- *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
- *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	This program is free software; you can redistribute it and/or 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.
- *
- * Debugging:
- * 	Use the 'lsusb' utility to dump the descriptors.
- *
- * 1999-09-07:  Alan Cox
- *		Parsing Audio descriptor patch
- * 1999-09-08:  Thomas Sailer
- *		Added OSS compatible data io functions; both parts of the
- *		driver remain to be glued together
- * 1999-09-10:  Thomas Sailer
- *		Beautified the driver. Added sample format conversions.
- *		Still not properly glued with the parsing code.
- *		The parsing code seems to have its problems btw,
- *		Since it parses all available configs but doesn't
- *		store which iface/altsetting belongs to which config.
- * 1999-09-20:  Thomas Sailer
- *		Threw out Alan's parsing code and implemented my own one.
- *		You cannot reasonnably linearly parse audio descriptors,
- *		especially the AudioClass descriptors have to be considered
- *		pointer lists. Mixer parsing untested, due to lack of device.
- *		First stab at synch pipe implementation, the Dallas USB DAC
- *		wants to use an Asynch out pipe. usb_audio_state now basically
- *		only contains lists of mixer and wave devices. We can therefore
- *		now have multiple mixer/wave devices per USB device.
- * 1999-10-28:  Thomas Sailer
- *		Converted to URB API. Fixed a taskstate/wakeup semantics mistake
- *		that made the driver consume all available CPU cycles.
- *		Now runs stable on UHCI-Acher/Fliegl/Sailer.
- * 1999-10-31:  Thomas Sailer
- *		Audio can now be unloaded if it is not in use by any mixer
- *		or dsp client (formerly you had to disconnect the audio devices
- *		from the USB port)
- *		Finally, about three months after ordering, my "Maxxtro SPK222"
- *		speakers arrived, isn't disdata a great mail order company 8-)
- *		Parse class specific endpoint descriptor of the audiostreaming
- *		interfaces and take the endpoint attributes from there.
- *		Unbelievably, the Philips USB DAC has a sampling rate range
- *		of over a decade, yet does not support the sampling rate control!
- *		No wonder it sounds so bad, has very audible sampling rate
- *		conversion distortion. Don't try to listen to it using
- *		decent headphones!
- *		"Let's make things better" -> but please Philips start with your
- *		own stuff!!!!
- * 1999-11-02:  Thomas Sailer
- *		It takes the Philips boxes several seconds to acquire synchronisation
- *		that means they won't play short sounds. Should probably maintain
- *		the ISO datastream even if there's nothing to play.
- *		Fix counting the total_bytes counter, RealPlayer G2 depends on it.
- * 1999-12-20:  Thomas Sailer
- *		Fix bad bug in conversion to per interface probing.
- *		disconnect was called multiple times for the audio device,
- *		leading to a premature freeing of the audio structures
- * 2000-05-13:  Thomas Sailer
- *		I don't remember who changed the find_format routine,
- *              but the change was completely broken for the Dallas
- *              chip. Anyway taking sampling rate into account in find_format
- *              is bad and should not be done unless there are devices with
- *              completely broken audio descriptors. Unless someone shows
- *              me such a descriptor, I will not allow find_format to
- *              take the sampling rate into account.
- *              Also, the former find_format made:
- *              - mpg123 play mono instead of stereo
- *              - sox completely fail for wav's with sample rates < 44.1kHz
- *                  for the Dallas chip.
- *              Also fix a rather long standing problem with applications that
- *              use "small" writes producing no sound at all.
- * 2000-05-15:  Thomas Sailer
- *		My fears came true, the Philips camera indeed has pretty stupid
- *              audio descriptors.
- * 2000-05-17:  Thomas Sailer
- *		Nemsoft spotted my stupid last minute change, thanks
- * 2000-05-19:  Thomas Sailer
- *		Fixed FEATURE_UNIT thinkos found thanks to the KC Technology
- *              Xtend device. Basically the driver treated FEATURE_UNIT's sourced
- *              by mono terminals as stereo.
- * 2000-05-20:  Thomas Sailer
- *		SELECTOR support (and thus selecting record channels from the mixer).
- *              Somewhat peculiar due to OSS interface limitations. Only works
- *              for channels where a "slider" is already in front of it (i.e.
- *              a MIXER unit or a FEATURE unit with volume capability).
- * 2000-11-26:  Thomas Sailer
- *              Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for
- *              its 8 bit modes, but expects signed data (and should therefore have used PCM).
- * 2001-03-10:  Thomas Sailer
- *              provide abs function, prevent picking up a bogus kernel macro
- *              for abs. Bug report by Andrew Morton <andrewm@uow.edu.au>
- * 2001-06-16:  Bryce Nesbitt <bryce@obviously.com>
- *              Fix SNDCTL_DSP_STEREO API violation
- */
-
-/*
- * Strategy:
- *
- * Alan Cox and Thomas Sailer are starting to dig at opposite ends and
- * are hoping to meet in the middle, just like tunnel diggers :)
- * Alan tackles the descriptor parsing, Thomas the actual data IO and the
- * OSS compatible interface.
- *
- * Data IO implementation issues
- *
- * A mmap'able ring buffer per direction is implemented, because
- * almost every OSS app expects it. It is however impractical to
- * transmit/receive USB data directly into and out of the ring buffer,
- * due to alignment and synchronisation issues. Instead, the ring buffer
- * feeds a constant time delay line that handles the USB issues.
- *
- * Now we first try to find an alternate setting that exactly matches
- * the sample format requested by the user. If we find one, we do not
- * need to perform any sample rate conversions. If there is no matching
- * altsetting, we choose the closest one and perform sample format
- * conversions. We never do sample rate conversion; these are too
- * expensive to be performed in the kernel.
- *
- * Current status: no known HCD-specific issues.
- *
- * Generally: Due to the brokenness of the Audio Class spec
- * it seems generally impossible to write a generic Audio Class driver,
- * so a reasonable driver should implement the features that are actually
- * used.
- *
- * Parsing implementation issues
- *
- * One cannot reasonably parse the AudioClass descriptors linearly.
- * Therefore the current implementation features routines to look
- * for a specific descriptor in the descriptor list.
- *
- * How does the parsing work? First, all interfaces are searched
- * for an AudioControl class interface. If found, the config descriptor
- * that belongs to the current configuration is fetched from the device.
- * Then the HEADER descriptor is fetched. It contains a list of
- * all AudioStreaming and MIDIStreaming devices. This list is then walked,
- * and all AudioStreaming interfaces are classified into input and output
- * interfaces (according to the endpoint0 direction in altsetting1) (MIDIStreaming
- * is currently not supported). The input & output list is then used
- * to group inputs and outputs together and issued pairwise to the
- * AudioStreaming class parser. Finally, all OUTPUT_TERMINAL descriptors
- * are walked and issued to the mixer construction routine.
- *
- * The AudioStreaming parser simply enumerates all altsettings belonging
- * to the specified interface. It looks for AS_GENERAL and FORMAT_TYPE
- * class specific descriptors to extract the sample format/sample rate
- * data. Only sample format types PCM and PCM8 are supported right now, and
- * only FORMAT_TYPE_I is handled. The isochronous data endpoint needs to
- * be the first endpoint of the interface, and the optional synchronisation
- * isochronous endpoint the second one.
- *
- * Mixer construction works as follows: The various TERMINAL and UNIT
- * descriptors span a tree from the root (OUTPUT_TERMINAL) through the
- * intermediate nodes (UNITs) to the leaves (INPUT_TERMINAL). We walk
- * that tree in a depth first manner. FEATURE_UNITs may contribute volume,
- * bass and treble sliders to the mixer, MIXER_UNITs volume sliders.
- * The terminal type encoded in the INPUT_TERMINALs feeds a heuristic
- * to determine "meaningful" OSS slider numbers, however we will see
- * how well this works in practice. Other features are not used at the
- * moment, they seem less often used. Also, it seems difficult at least
- * to construct recording source switches from SELECTOR_UNITs, but
- * since there are not many USB ADC's available, we leave that for later.
- */
-
-/*****************************************************************************/
-
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/module.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/wrapper.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <linux/usb.h>
-
-#include "audio.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.0.0"
-#define DRIVER_AUTHOR "Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)"
-#define DRIVER_DESC "USB Audio Class driver"
-
-#define AUDIO_DEBUG 1
-
-#define SND_DEV_DSP16   5 
-
-#define dprintk(x)
-
-#undef abs
-extern int abs(int __x) __attribute__ ((__const__)); /* Shut up warning */
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Linked list of all audio devices...
- */
-static struct list_head audiodevs = LIST_HEAD_INIT(audiodevs);
-static DECLARE_MUTEX(open_sem);
-
-/*
- * wait queue for processes wanting to open an USB audio device
- */
-static DECLARE_WAIT_QUEUE_HEAD(open_wait);
-
-
-#define MAXFORMATS        MAX_ALT
-#define DMABUFSHIFT       17  /* 128k worth of DMA buffer */
-#define NRSGBUF           (1U<<(DMABUFSHIFT-PAGE_SHIFT))
-
-/*
- * This influences:
- * - Latency
- * - Interrupt rate
- * - Synchronisation behaviour
- * Don't touch this if you don't understand all of the above.
- */
-#define DESCFRAMES  5
-#define SYNCFRAMES  DESCFRAMES
-
-#define MIXFLG_STEREOIN   1
-#define MIXFLG_STEREOOUT  2
-
-struct mixerchannel {
-	__u16 value;
-	__u16 osschannel;  /* number of the OSS channel */
-	__s16 minval, maxval;
-	__u16 slctunitid;
-	__u8 unitid;
-	__u8 selector;
-	__u8 chnum;
-	__u8 flags;
-};
-
-struct audioformat {
-	unsigned int format;
-	unsigned int sratelo;
-	unsigned int sratehi;
-	unsigned char altsetting;
-	unsigned char attributes;
-};
-
-struct dmabuf {
-	/* buffer data format */
-	unsigned int format;
-	unsigned int srate;
-	/* physical buffer */
-	unsigned char *sgbuf[NRSGBUF];
-	unsigned bufsize;
-	unsigned numfrag;
-	unsigned fragshift;
-	unsigned wrptr, rdptr;
-	unsigned total_bytes;
-	int count;
-	unsigned error; /* over/underrun */
-	wait_queue_head_t wait;
-	/* redundant, but makes calculations easier */
-	unsigned fragsize;
-	unsigned dmasize;
-	/* OSS stuff */
-	unsigned mapped:1;
-	unsigned ready:1;
-	unsigned ossfragshift;
-	int ossmaxfrags;
-	unsigned subdivision;
-};
-
-struct usb_audio_state;
-
-#define FLG_URB0RUNNING   1
-#define FLG_URB1RUNNING   2
-#define FLG_SYNC0RUNNING  4
-#define FLG_SYNC1RUNNING  8
-#define FLG_RUNNING      16
-#define FLG_CONNECTED    32
-
-struct my_data_urb {
-	struct urb *urb;
-};
-
-struct my_sync_urb {
-	struct urb *urb;
-};
-
-
-struct usb_audiodev {
-	struct list_head list;
-	struct usb_audio_state *state;
-	
-	/* soundcore stuff */
-	int dev_audio;
-
-	/* wave stuff */
-	mode_t open_mode;
-	spinlock_t lock;         /* DMA buffer access spinlock */
-
-	struct usbin {
-		int interface;           /* Interface number, -1 means not used */
-		unsigned int format;     /* USB data format */
-		unsigned int datapipe;   /* the data input pipe */
-		unsigned int syncpipe;   /* the synchronisation pipe - 0 for anything but adaptive IN mode */
-		unsigned int syncinterval;  /* P for adaptive IN mode, 0 otherwise */
-		unsigned int freqn;      /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */
-		unsigned int freqmax;    /* maximum sampling rate, used for buffer management */
-		unsigned int phase;      /* phase accumulator */
-		unsigned int flags;      /* see FLG_ defines */
-		
-		struct my_data_urb durb[2];  /* ISO descriptors for the data endpoint */
-		struct my_sync_urb surb[2];  /* ISO sync pipe descriptor if needed */
-		
-		struct dmabuf dma;
-	} usbin;
-
-	struct usbout {
-		int interface;           /* Interface number, -1 means not used */
-		unsigned int format;     /* USB data format */
-		unsigned int datapipe;   /* the data input pipe */
-		unsigned int syncpipe;   /* the synchronisation pipe - 0 for anything but asynchronous OUT mode */
-		unsigned int syncinterval;  /* P for asynchronous OUT mode, 0 otherwise */
-		unsigned int freqn;      /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */
-		unsigned int freqm;      /* momentary sampling rate in USB format, i.e. fs/1000 in Q10.14 */
-		unsigned int freqmax;    /* maximum sampling rate, used for buffer management */
-		unsigned int phase;      /* phase accumulator */
-		unsigned int flags;      /* see FLG_ defines */
-
-		struct my_data_urb durb[2];  /* ISO descriptors for the data endpoint */
-		struct my_sync_urb surb[2];  /* ISO sync pipe descriptor if needed */
-		
-		struct dmabuf dma;
-	} usbout;
-
-
-	unsigned int numfmtin, numfmtout;
-	struct audioformat fmtin[MAXFORMATS];
-	struct audioformat fmtout[MAXFORMATS];
-};  
-
-struct usb_mixerdev {
-	struct list_head list;
-	struct usb_audio_state *state;
-
-	/* soundcore stuff */
-	int dev_mixer;
-
-	unsigned char iface;  /* interface number of the AudioControl interface */
-
-	/* USB format descriptions */
-	unsigned int numch, modcnt;
-
-	/* mixch is last and gets allocated dynamically */
-	struct mixerchannel ch[0];
-};
-
-struct usb_audio_state {
-	struct list_head audiodev;
-
-	/* USB device */
-	struct usb_device *usbdev;
-
-	struct list_head audiolist;
-	struct list_head mixerlist;
-
-	unsigned count;  /* usage counter; NOTE: the usb stack is also considered a user */
-};
-
-/* private audio format extensions */
-#define AFMT_STEREO        0x80000000
-#define AFMT_ISSTEREO(x)   ((x) & AFMT_STEREO)
-#define AFMT_IS16BIT(x)    ((x) & (AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE))
-#define AFMT_ISUNSIGNED(x) ((x) & (AFMT_U8|AFMT_U16_LE|AFMT_U16_BE))
-#define AFMT_BYTESSHIFT(x) ((AFMT_ISSTEREO(x) ? 1 : 0) + (AFMT_IS16BIT(x) ? 1 : 0))
-#define AFMT_BYTES(x)      (1<<AFMT_BYTESSHFIT(x))
-
-/* --------------------------------------------------------------------- */
-
-/* prevent picking up a bogus abs macro */
-#undef abs
-extern inline int abs(int x)
-{
-        if (x < 0)
-		return -x;
-	return x;
-}
-                                
-/* --------------------------------------------------------------------- */
-
-extern inline unsigned ld2(unsigned int x)
-{
-	unsigned r = 0;
-	
-	if (x >= 0x10000) {
-		x >>= 16;
-		r += 16;
-	}
-	if (x >= 0x100) {
-		x >>= 8;
-		r += 8;
-	}
-	if (x >= 0x10) {
-		x >>= 4;
-		r += 4;
-	}
-	if (x >= 4) {
-		x >>= 2;
-		r += 2;
-	}
-	if (x >= 2)
-		r++;
-	return r;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * OSS compatible ring buffer management. The ring buffer may be mmap'ed into
- * an application address space.
- *
- * I first used the rvmalloc stuff copied from bttv. Alan Cox did not like it, so
- * we now use an array of pointers to a single page each. This saves us the
- * kernel page table manipulations, but we have to do a page table alike mechanism
- * (though only one indirection) in software.
- */
-
-static void dmabuf_release(struct dmabuf *db)
-{
-	unsigned int nr;
-	void *p;
-
-	for(nr = 0; nr < NRSGBUF; nr++) {
-		if (!(p = db->sgbuf[nr]))
-			continue;
-		mem_map_unreserve(virt_to_page(p));
-		free_page((unsigned long)p);
-		db->sgbuf[nr] = NULL;
-	}
-	db->mapped = db->ready = 0;
-}
-
-static int dmabuf_init(struct dmabuf *db)
-{
-	unsigned int nr, bytepersec, bufs;
-	void *p;
-
-	/* initialize some fields */
-	db->rdptr = db->wrptr = db->total_bytes = db->count = db->error = 0;
-	/* calculate required buffer size */
-	bytepersec = db->srate << AFMT_BYTESSHIFT(db->format);
-	bufs = 1U << DMABUFSHIFT;
-	if (db->ossfragshift) {
-		if ((1000 << db->ossfragshift) < bytepersec)
-			db->fragshift = ld2(bytepersec/1000);
-		else
-			db->fragshift = db->ossfragshift;
-	} else {
-		db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
-		if (db->fragshift < 3)
-			db->fragshift = 3;
-	}
-	db->numfrag = bufs >> db->fragshift;
-	while (db->numfrag < 4 && db->fragshift > 3) {
-		db->fragshift--;
-		db->numfrag = bufs >> db->fragshift;
-	}
-	db->fragsize = 1 << db->fragshift;
-	if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
-		db->numfrag = db->ossmaxfrags;
-	db->dmasize = db->numfrag << db->fragshift;
-	for(nr = 0; nr < NRSGBUF; nr++) {
-		if (!db->sgbuf[nr]) {
-			p = (void *)get_free_page(GFP_KERNEL);
-			if (!p)
-				return -ENOMEM;
-			db->sgbuf[nr] = p;
-			mem_map_reserve(virt_to_page(p));
-		}
-		memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE);
-		if ((nr << PAGE_SHIFT) >= db->dmasize)
-			break;
-	}
-	db->bufsize = nr << PAGE_SHIFT;
-	db->ready = 1;
-	dprintk((KERN_DEBUG "usbaudio: dmabuf_init bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d "
-	         "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x srate %d\n",
-	         bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize,
-	         db->numfrag, db->dmasize, db->bufsize, db->format, db->srate));
-	return 0;
-}
-
-static int dmabuf_mmap(struct vm_area_struct *vma, struct dmabuf *db, unsigned long start, unsigned long size, pgprot_t prot)
-{
-	unsigned int nr;
-
-	if (!db->ready || db->mapped || (start | size) & (PAGE_SIZE-1) || size > db->bufsize)
-		return -EINVAL;
-	size >>= PAGE_SHIFT;
-	for(nr = 0; nr < size; nr++)
-		if (!db->sgbuf[nr])
-			return -EINVAL;
-	db->mapped = 1;
-	for(nr = 0; nr < size; nr++) {
-		if (remap_page_range(vma, start, virt_to_phys(db->sgbuf[nr]), PAGE_SIZE, prot))
-			return -EAGAIN;
-		start += PAGE_SIZE;
-	}
-	return 0;
-}
-
-static void dmabuf_copyin(struct dmabuf *db, const void *buffer, unsigned int size)
-{
-	unsigned int pgrem, rem;
-
-	db->total_bytes += size;
-	for (;;) {
-		if (size <= 0)
-			return;
-		pgrem = ((~db->wrptr) & (PAGE_SIZE-1)) + 1;
-		if (pgrem > size)
-			pgrem = size;
-		rem = db->dmasize - db->wrptr;
-		if (pgrem > rem)
-			pgrem = rem;
-		memcpy((db->sgbuf[db->wrptr >> PAGE_SHIFT]) + (db->wrptr & (PAGE_SIZE-1)), buffer, pgrem);
-		size -= pgrem;
-		(char *)buffer += pgrem;
-		db->wrptr += pgrem;
-		if (db->wrptr >= db->dmasize)
-			db->wrptr = 0;
-	}
-}
-
-static void dmabuf_copyout(struct dmabuf *db, void *buffer, unsigned int size)
-{
-	unsigned int pgrem, rem;
-
-	db->total_bytes += size;
-	for (;;) {
-		if (size <= 0)
-			return;
-		pgrem = ((~db->rdptr) & (PAGE_SIZE-1)) + 1;
-		if (pgrem > size)
-			pgrem = size;
-		rem = db->dmasize - db->rdptr;
-		if (pgrem > rem)
-			pgrem = rem;
-		memcpy(buffer, (db->sgbuf[db->rdptr >> PAGE_SHIFT]) + (db->rdptr & (PAGE_SIZE-1)), pgrem);
-		size -= pgrem;
-		(char *)buffer += pgrem;
-		db->rdptr += pgrem;
-		if (db->rdptr >= db->dmasize)
-			db->rdptr = 0;
-	}
-}
-
-static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *buffer, unsigned int size)
-{
-	unsigned int pgrem, rem;
-
-	if (!db->ready || db->mapped)
-		return -EINVAL;
-	for (;;) {
-		if (size <= 0)
-			return 0;
-		pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1;
-		if (pgrem > size)
-			pgrem = size;
-		rem = db->dmasize - ptr;
-		if (pgrem > rem)
-			pgrem = rem;
-		if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem))
-			return -EFAULT;
-		size -= pgrem;
-		(char *)buffer += pgrem;
-		ptr += pgrem;
-		if (ptr >= db->dmasize)
-			ptr = 0;
-	}
-}
-
-static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *buffer, unsigned int size)
-{
-	unsigned int pgrem, rem;
-
-	if (!db->ready || db->mapped)
-		return -EINVAL;
-	for (;;) {
-		if (size <= 0)
-			return 0;
-		pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1;
-		if (pgrem > size)
-			pgrem = size;
-		rem = db->dmasize - ptr;
-		if (pgrem > rem)
-			pgrem = rem;
-		if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem))
-			return -EFAULT;
-		size -= pgrem;
-		(char *)buffer += pgrem;
-		ptr += pgrem;
-		if (ptr >= db->dmasize)
-			ptr = 0;
-	}
-}
-
-/* --------------------------------------------------------------------- */
-/*
- * USB I/O code. We do sample format conversion if necessary
- */
-
-static void usbin_stop(struct usb_audiodev *as)
-{
-	struct usbin *u = &as->usbin;
-	unsigned long flags;
-	unsigned int i, notkilled = 1;
-
-	spin_lock_irqsave(&as->lock, flags);
-	u->flags &= ~FLG_RUNNING;
-	i = u->flags;
-	spin_unlock_irqrestore(&as->lock, flags);
-	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
-		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-		spin_lock_irqsave(&as->lock, flags);
-		i = u->flags;
-		spin_unlock_irqrestore(&as->lock, flags);
-		if (notkilled && signal_pending(current)) {
-			if (i & FLG_URB0RUNNING)
-				usb_unlink_urb(u->durb[0].urb);
-			if (i & FLG_URB1RUNNING)
-				usb_unlink_urb(u->durb[1].urb);
-			if (i & FLG_SYNC0RUNNING)
-				usb_unlink_urb(u->surb[0].urb);
-			if (i & FLG_SYNC1RUNNING)
-				usb_unlink_urb(u->surb[1].urb);
-			notkilled = 0;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	if (u->durb[0].urb->transfer_buffer)
-		kfree(u->durb[0].urb->transfer_buffer);
-	if (u->durb[1].urb->transfer_buffer)
-		kfree(u->durb[1].urb->transfer_buffer);
-	if (u->surb[0].urb->transfer_buffer)
-		kfree(u->surb[0].urb->transfer_buffer);
-	if (u->surb[1].urb->transfer_buffer)
-		kfree(u->surb[1].urb->transfer_buffer);
-	u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = 
-		u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL;
-}
-
-static inline void usbin_release(struct usb_audiodev *as)
-{
-	usbin_stop(as);
-}
-
-static void usbin_disc(struct usb_audiodev *as)
-{
-	struct usbin *u = &as->usbin;
-
-	unsigned long flags;
-
-	spin_lock_irqsave(&as->lock, flags);
-	u->flags &= ~(FLG_RUNNING | FLG_CONNECTED);
-	spin_unlock_irqrestore(&as->lock, flags);
-	usbin_stop(as);
-}
-
-static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt)
-{
-	unsigned int cnt, i;
-	__s16 *sp, *sp2, s;
-	unsigned char *bp;
-
-	cnt = scnt;
-	if (AFMT_ISSTEREO(ifmt))
-		cnt <<= 1;
-	sp = ((__s16 *)tmp) + cnt;
-	switch (ifmt & ~AFMT_STEREO) {
-	case AFMT_U8:
-		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {
-			bp--;
-			sp--;
-			*sp = (*bp ^ 0x80) << 8;
-		}
-		break;
-			
-	case AFMT_S8:
-		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {
-			bp--;
-			sp--;
-			*sp = *bp << 8;
-		}
-		break;
-		
-	case AFMT_U16_LE:
-		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
-			bp -= 2;
-			sp--;
-			*sp = (bp[0] | (bp[1] << 8)) ^ 0x8000;
-		}
-		break;
-
-	case AFMT_U16_BE:
-		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
-			bp -= 2;
-			sp--;
-			*sp = (bp[1] | (bp[0] << 8)) ^ 0x8000;
-		}
-		break;
-
-	case AFMT_S16_LE:
-		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
-			bp -= 2;
-			sp--;
-			*sp = bp[0] | (bp[1] << 8);
-		}
-		break;
-
-	case AFMT_S16_BE:
-		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
-			bp -= 2;
-			sp--;
-			*sp = bp[1] | (bp[0] << 8);
-		}
-		break;
-	}
-	if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) {
-		/* expand from mono to stereo */
-		for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) {
-			sp--;
-			sp2 -= 2;
-			sp2[0] = sp2[1] = sp[0];
-		}
-	}
-	if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) {
-		/* contract from stereo to mono */
-		for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2)
-			sp[0] = (sp2[0] + sp2[1]) >> 1;
-	}
-	cnt = scnt;
-	if (AFMT_ISSTEREO(ofmt))
-		cnt <<= 1;
-	sp = ((__s16 *)tmp);
-	bp = ((unsigned char *)obuf);
-	switch (ofmt & ~AFMT_STEREO) {
-	case AFMT_U8:
-		for (i = 0; i < cnt; i++, sp++, bp++)
-			*bp = (*sp >> 8) ^ 0x80;
-		break;
-
-	case AFMT_S8:
-		for (i = 0; i < cnt; i++, sp++, bp++)
-			*bp = *sp >> 8;
-		break;
-
-	case AFMT_U16_LE:
-		for (i = 0; i < cnt; i++, sp++, bp += 2) {
-			s = *sp;
-			bp[0] = s;
-			bp[1] = (s >> 8) ^ 0x80;
-		}
-		break;
-
-	case AFMT_U16_BE:
-		for (i = 0; i < cnt; i++, sp++, bp += 2) {
-			s = *sp;
-			bp[1] = s;
-			bp[0] = (s >> 8) ^ 0x80;
-		}
-		break;
-
-	case AFMT_S16_LE:
-		for (i = 0; i < cnt; i++, sp++, bp += 2) {
-			s = *sp;
-			bp[0] = s;
-			bp[1] = s >> 8;
-		}
-		break;
-
-	case AFMT_S16_BE:
-		for (i = 0; i < cnt; i++, sp++, bp += 2) {
-			s = *sp;
-			bp[1] = s;
-			bp[0] = s >> 8;
-		}
-		break;
-	}
-	
-}
-
-static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples)
-{
-	union {
-		__s16 s[64];
-		unsigned char b[0];
-	} tmp;
-	unsigned int scnt, maxs, ufmtsh, dfmtsh;
-
-	ufmtsh = AFMT_BYTESSHIFT(u->format);
-	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
-	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;
-	while (samples > 0) {
-		scnt = samples;
-		if (scnt > maxs)
-			scnt = maxs;
-		conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt);
-		dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh);
-		buffer += scnt << ufmtsh;
-		samples -= scnt;
-	}
-}		
-
-static int usbin_prepare_desc(struct usbin *u, struct urb *urb)
-{
-	unsigned int i, maxsize, offs;
-
-	maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
-	//printk(KERN_DEBUG "usbin_prepare_desc: maxsize %d freq 0x%x format 0x%x\n", maxsize, u->freqn, u->format);
-	for (i = offs = 0; i < DESCFRAMES; i++, offs += maxsize) {
-		urb->iso_frame_desc[i].length = maxsize;
-		urb->iso_frame_desc[i].offset = offs;
-	}
-	return 0;
-}
-
-/*
- * return value: 0 if descriptor should be restarted, -1 otherwise
- * convert sample format on the fly if necessary
- */
-static int usbin_retire_desc(struct usbin *u, struct urb *urb)
-{
-	unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;
-	unsigned char *cp;
-
-	ufmtsh = AFMT_BYTESSHIFT(u->format);
-	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
-	for (i = 0; i < DESCFRAMES; i++) {
-		cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset;
-		if (urb->iso_frame_desc[i].status) {
-			dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
-			continue;
-		}
-		scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh;
-		if (!scnt)
-			continue;
-		cnt = scnt << dfmtsh;
-		if (!u->dma.mapped) {
-			dmafree = u->dma.dmasize - u->dma.count;
-			if (cnt > dmafree) {
-				scnt = dmafree >> dfmtsh;
-				cnt = scnt << dfmtsh;
-				err++;
-			}
-		}
-		u->dma.count += cnt;
-		if (u->format == u->dma.format) {
-			/* we do not need format conversion */
-			dprintk((KERN_DEBUG "usbaudio: no sample format conversion\n"));
-			dmabuf_copyin(&u->dma, cp, cnt);
-		} else {
-			/* we need sampling format conversion */
-			dprintk((KERN_DEBUG "usbaudio: sample format conversion %x != %x\n", u->format, u->dma.format));
-			usbin_convert(u, cp, scnt);
-		}
-	}
-	if (err)
-		u->dma.error++;
-	if (u->dma.count >= (signed)u->dma.fragsize)
-		wake_up(&u->dma.wait);
-	return err ? -1 : 0;
-}
-
-static void usbin_completed(struct urb *urb)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
-	struct usbin *u = &as->usbin;
-	unsigned long flags;
-	unsigned int mask;
-	int suret = 0;
-
-#if 0
-	printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
-#endif
-	if (urb == u->durb[0].urb)
-		mask = FLG_URB0RUNNING;
-	else if (urb == u->durb[1].urb)
-		mask = FLG_URB1RUNNING;
-	else {
-		mask = 0;
-		printk(KERN_ERR "usbin_completed: panic: unknown URB\n");
-	}
-	urb->dev = as->state->usbdev;
-	spin_lock_irqsave(&as->lock, flags);
-	if (!usbin_retire_desc(u, urb) &&
-	    u->flags & FLG_RUNNING &&
-	    !usbin_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
-		u->flags |= mask;
-	} else {
-		u->flags &= ~(mask | FLG_RUNNING);
-		wake_up(&u->dma.wait);
-		printk(KERN_DEBUG "usbin_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret);
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-}
-
-/*
- * we output sync data
- */
-static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb)
-{
-	unsigned char *cp = urb->transfer_buffer;
-	unsigned int i, offs;
-	
-	for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3, cp += 3) {
-		urb->iso_frame_desc[i].length = 3;
-		urb->iso_frame_desc[i].offset = offs;
-		cp[0] = u->freqn;
-		cp[1] = u->freqn >> 8;
-		cp[2] = u->freqn >> 16;
-	}
-	return 0;
-}
-
-/*
- * return value: 0 if descriptor should be restarted, -1 otherwise
- */
-static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb)
-{
-	unsigned int i;
-	
-	for (i = 0; i < SYNCFRAMES; i++)
-		if (urb->iso_frame_desc[0].status)
-			dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
-	return 0;
-}
-
-static void usbin_sync_completed(struct urb *urb)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
-	struct usbin *u = &as->usbin;
-	unsigned long flags;
-	unsigned int mask;
-	int suret = 0;
-
-#if 0
-	printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
-#endif
-	if (urb == u->surb[0].urb)
-		mask = FLG_SYNC0RUNNING;
-	else if (urb == u->surb[1].urb)
-		mask = FLG_SYNC1RUNNING;
-	else {
-		mask = 0;
-		printk(KERN_ERR "usbin_sync_completed: panic: unknown URB\n");
-	}
-	urb->dev = as->state->usbdev;
-	spin_lock_irqsave(&as->lock, flags);
-	if (!usbin_sync_retire_desc(u, urb) &&
-	    u->flags & FLG_RUNNING &&
-	    !usbin_sync_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
-		u->flags |= mask;
-	} else {
-		u->flags &= ~(mask | FLG_RUNNING);
-		wake_up(&u->dma.wait);
-		dprintk((KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-}
-
-static int usbin_start(struct usb_audiodev *as)
-{
-	struct usb_device *dev = as->state->usbdev;
-	struct usbin *u = &as->usbin;
-	struct urb *urb;
-	unsigned long flags;
-	unsigned int maxsze, bufsz;
-
-#if 0
-	printk(KERN_DEBUG "usbin_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n",
-	       dev->devnum, u->format, u->dma.format, u->dma.srate);
-#endif
-	/* allocate USB storage if not already done */
-	spin_lock_irqsave(&as->lock, flags);
-	if (!(u->flags & FLG_CONNECTED)) {
-		spin_unlock_irqrestore(&as->lock, flags);
-		return -EIO;
-	}
-	if (!(u->flags & FLG_RUNNING)) {
-		spin_unlock_irqrestore(&as->lock, flags);
-		u->freqn = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */
-		u->freqmax = u->freqn + (u->freqn >> 2);
-		u->phase = 0;
-		maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
-		bufsz = DESCFRAMES * maxsze;
-		if (u->durb[0].urb->transfer_buffer)
-			kfree(u->durb[0].urb->transfer_buffer);
-		u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
-		u->durb[0].urb->transfer_buffer_length = bufsz;
-		if (u->durb[1].urb->transfer_buffer)
-			kfree(u->durb[1].urb->transfer_buffer);
-		u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
-		u->durb[1].urb->transfer_buffer_length = bufsz;
-		if (u->syncpipe) {
-			if (u->surb[0].urb->transfer_buffer)
-				kfree(u->surb[0].urb->transfer_buffer);
-			u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
-			u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES;
-			if (u->surb[1].urb->transfer_buffer)
-				kfree(u->surb[1].urb->transfer_buffer);
-			u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
-			u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES;
-		}
-		if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || 
-		    (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) {
-			printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);
-			return 0;
-		}
-		spin_lock_irqsave(&as->lock, flags);
-	}
-	if (u->dma.count >= u->dma.dmasize && !u->dma.mapped) {
-		spin_unlock_irqrestore(&as->lock, flags);
-		return 0;
-	}
-	u->flags |= FLG_RUNNING;
-	if (!(u->flags & FLG_URB0RUNNING)) {
-		urb = u->durb[0].urb;
-		urb->dev = dev;
-		urb->pipe = u->datapipe;
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->number_of_packets = DESCFRAMES;
-		urb->context = as;
-		urb->complete = usbin_completed;
-		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-			u->flags |= FLG_URB0RUNNING;
-		else
-			u->flags &= ~FLG_RUNNING;
-	}
-	if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {
-		urb = u->durb[1].urb;
-		urb->dev = dev;
-		urb->pipe = u->datapipe;
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->number_of_packets = DESCFRAMES;
-		urb->context = as;
-		urb->complete = usbin_completed;
-		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-			u->flags |= FLG_URB1RUNNING;
-		else
-			u->flags &= ~FLG_RUNNING;
-	}
-	if (u->syncpipe) {
-		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {
-			urb = u->surb[0].urb;
-			urb->dev = dev;
-			urb->pipe = u->syncpipe;
-			urb->transfer_flags = USB_ISO_ASAP;
-			urb->number_of_packets = SYNCFRAMES;
-			urb->context = as;
-			urb->complete = usbin_sync_completed;
-			/* stride: u->syncinterval */
-			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-				u->flags |= FLG_SYNC0RUNNING;
-			else
-				u->flags &= ~FLG_RUNNING;
-		}
-		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {
-			urb = u->surb[1].urb;
-			urb->dev = dev;
-			urb->pipe = u->syncpipe;
-			urb->transfer_flags = USB_ISO_ASAP;
-			urb->number_of_packets = SYNCFRAMES;
-			urb->context = as;
-			urb->complete = usbin_sync_completed;
-			/* stride: u->syncinterval */
-			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-				u->flags |= FLG_SYNC1RUNNING;
-			else
-				u->flags &= ~FLG_RUNNING;
-		}
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-	return 0;
-}
-
-static void usbout_stop(struct usb_audiodev *as)
-{
-	struct usbout *u = &as->usbout;
-	unsigned long flags;
-	unsigned int i, notkilled = 1;
-
-	spin_lock_irqsave(&as->lock, flags);
-	u->flags &= ~FLG_RUNNING;
-	i = u->flags;
-	spin_unlock_irqrestore(&as->lock, flags);
-	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
-		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-		spin_lock_irqsave(&as->lock, flags);
-		i = u->flags;
-		spin_unlock_irqrestore(&as->lock, flags);
-		if (notkilled && signal_pending(current)) {
-			if (i & FLG_URB0RUNNING)
-				usb_unlink_urb(u->durb[0].urb);
-			if (i & FLG_URB1RUNNING)
-				usb_unlink_urb(u->durb[1].urb);
-			if (i & FLG_SYNC0RUNNING)
-				usb_unlink_urb(u->surb[0].urb);
-			if (i & FLG_SYNC1RUNNING)
-				usb_unlink_urb(u->surb[1].urb);
-			notkilled = 0;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	if (u->durb[0].urb->transfer_buffer)
-		kfree(u->durb[0].urb->transfer_buffer);
-	if (u->durb[1].urb->transfer_buffer)
-		kfree(u->durb[1].urb->transfer_buffer);
-	if (u->surb[0].urb->transfer_buffer)
-		kfree(u->surb[0].urb->transfer_buffer);
-	if (u->surb[1].urb->transfer_buffer)
-		kfree(u->surb[1].urb->transfer_buffer);
-	u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = 
-		u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL;
-}
-
-static inline void usbout_release(struct usb_audiodev *as)
-{
-	usbout_stop(as);
-}
-
-static void usbout_disc(struct usb_audiodev *as)
-{
-	struct usbout *u = &as->usbout;
-	unsigned long flags;
-
-	spin_lock_irqsave(&as->lock, flags);
-	u->flags &= ~(FLG_RUNNING | FLG_CONNECTED);
-	spin_unlock_irqrestore(&as->lock, flags);
-	usbout_stop(as);
-}
-
-static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int samples)
-{
-	union {
-		__s16 s[64];
-		unsigned char b[0];
-	} tmp;
-	unsigned int scnt, maxs, ufmtsh, dfmtsh;
-
-	ufmtsh = AFMT_BYTESSHIFT(u->format);
-	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
-	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;
-	while (samples > 0) {
-		scnt = samples;
-		if (scnt > maxs)
-			scnt = maxs;
-		dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh);
-		conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt);
-		buffer += scnt << ufmtsh;
-		samples -= scnt;
-	}
-}		
-
-static int usbout_prepare_desc(struct usbout *u, struct urb *urb)
-{
-	unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;
-	unsigned char *cp = urb->transfer_buffer;
-
-	ufmtsh = AFMT_BYTESSHIFT(u->format);
-	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
-	for (i = offs = 0; i < DESCFRAMES; i++) {
-		urb->iso_frame_desc[i].offset = offs;
-		u->phase = (u->phase & 0x3fff) + u->freqm;
-		scnt = u->phase >> 14;
-		if (!scnt) {
-			urb->iso_frame_desc[i].length = 0;
-			continue;
-		}
-		cnt = scnt << dfmtsh;
-		if (!u->dma.mapped) {
-			if (cnt > u->dma.count) {
-				scnt = u->dma.count >> dfmtsh;
-				cnt = scnt << dfmtsh;
-				err++;
-			}
-			u->dma.count -= cnt;
-		} else
-			u->dma.count += cnt;
-		if (u->format == u->dma.format) {
-			/* we do not need format conversion */
-			dmabuf_copyout(&u->dma, cp, cnt);
-		} else {
-			/* we need sampling format conversion */
-			usbout_convert(u, cp, scnt);
-		}
-		cnt = scnt << ufmtsh;
-		urb->iso_frame_desc[i].length = cnt;
-		offs += cnt;
-		cp += cnt;
-	}
-	if (err)
-		u->dma.error++;
-	if (u->dma.mapped) {
-		if (u->dma.count >= (signed)u->dma.fragsize)
-			wake_up(&u->dma.wait);
-	} else {
-		if ((signed)u->dma.dmasize >= u->dma.count + (signed)u->dma.fragsize)
-			wake_up(&u->dma.wait);
-	}
-	return err ? -1 : 0;
-}
-
-/*
- * return value: 0 if descriptor should be restarted, -1 otherwise
- */
-static int usbout_retire_desc(struct usbout *u, struct urb *urb)
-{
-	unsigned int i;
-
-	for (i = 0; i < DESCFRAMES; i++) {
-		if (urb->iso_frame_desc[i].status) {
-			dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
-			continue;
-		}
-	}
-	return 0;
-}
-
-static void usbout_completed(struct urb *urb)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
-	struct usbout *u = &as->usbout;
-	unsigned long flags;
-	unsigned int mask;
-	int suret = 0;
-
-#if 0
-	printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
-#endif
-	if (urb == u->durb[0].urb)
-		mask = FLG_URB0RUNNING;
-	else if (urb == u->durb[1].urb)
-		mask = FLG_URB1RUNNING;
-	else {
-		mask = 0;
-		printk(KERN_ERR "usbout_completed: panic: unknown URB\n");
-	}
-	urb->dev = as->state->usbdev;
-	spin_lock_irqsave(&as->lock, flags);
-	if (!usbout_retire_desc(u, urb) &&
-	    u->flags & FLG_RUNNING &&
-	    !usbout_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
-		u->flags |= mask;
-	} else {
-		u->flags &= ~(mask | FLG_RUNNING);
-		wake_up(&u->dma.wait);
-		dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-}
-
-static int usbout_sync_prepare_desc(struct usbout *u, struct urb *urb)
-{
-	unsigned int i, offs;
-
-	for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3) {
-		urb->iso_frame_desc[i].length = 3;
-		urb->iso_frame_desc[i].offset = offs;
-	}
-	return 0;
-}
-
-/*
- * return value: 0 if descriptor should be restarted, -1 otherwise
- */
-static int usbout_sync_retire_desc(struct usbout *u, struct urb *urb)
-{
-	unsigned char *cp = urb->transfer_buffer;
-	unsigned int f, i;
-
-	for (i = 0; i < SYNCFRAMES; i++, cp += 3) {
-		if (urb->iso_frame_desc[i].status) {
-			dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
-			continue;
-		}
-		if (urb->iso_frame_desc[i].actual_length < 3) {
-			dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length));
-			continue;
-		}
-		f = cp[0] | (cp[1] << 8) | (cp[2] << 16);
-		if (abs(f - u->freqn) > (u->freqn >> 3) || f > u->freqmax) {
-			printk(KERN_WARNING "usbout_sync_retire_desc: requested frequency %u (nominal %u) out of range!\n", f, u->freqn);
-			continue;
-		}
-		u->freqm = f;
-	}
-	return 0;
-}
-
-static void usbout_sync_completed(struct urb *urb)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
-	struct usbout *u = &as->usbout;
-	unsigned long flags;
-	unsigned int mask;
-	int suret = 0;
-
-#if 0
-	printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
-#endif
-	if (urb == u->surb[0].urb)
-		mask = FLG_SYNC0RUNNING;
-	else if (urb == u->surb[1].urb)
-		mask = FLG_SYNC1RUNNING;
-	else {
-		mask = 0;
-		printk(KERN_ERR "usbout_sync_completed: panic: unknown URB\n");
-	}
-	urb->dev = as->state->usbdev;
-	spin_lock_irqsave(&as->lock, flags);
-	if (!usbout_sync_retire_desc(u, urb) &&
-	    u->flags & FLG_RUNNING &&
-	    !usbout_sync_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
-		u->flags |= mask;
-	} else {
-		u->flags &= ~(mask | FLG_RUNNING);
-		wake_up(&u->dma.wait);
-		dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-}
-
-static int usbout_start(struct usb_audiodev *as)
-{
-	struct usb_device *dev = as->state->usbdev;
-	struct usbout *u = &as->usbout;
-	struct urb *urb;
-	unsigned long flags;
-	unsigned int maxsze, bufsz;
-
-#if 0
-	printk(KERN_DEBUG "usbout_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n",
-	       dev->devnum, u->format, u->dma.format, u->dma.srate);
-#endif
-	/* allocate USB storage if not already done */
-	spin_lock_irqsave(&as->lock, flags);
-	if (!(u->flags & FLG_CONNECTED)) {
-		spin_unlock_irqrestore(&as->lock, flags);
-		return -EIO;
-	}
-	if (!(u->flags & FLG_RUNNING)) {
-		spin_unlock_irqrestore(&as->lock, flags);
-		u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */
-		u->freqmax = u->freqn + (u->freqn >> 2);
-		u->phase = 0;
-		maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
-		bufsz = DESCFRAMES * maxsze;
-		if (u->durb[0].urb->transfer_buffer)
-			kfree(u->durb[0].urb->transfer_buffer);
-		u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
-		u->durb[0].urb->transfer_buffer_length = bufsz;
-		if (u->durb[1].urb->transfer_buffer)
-			kfree(u->durb[1].urb->transfer_buffer);
-		u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
-		u->durb[1].urb->transfer_buffer_length = bufsz;
-		if (u->syncpipe) {
-			if (u->surb[0].urb->transfer_buffer)
-				kfree(u->surb[0].urb->transfer_buffer);
-			u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
-			u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES;
-			if (u->surb[1].urb->transfer_buffer)
-				kfree(u->surb[1].urb->transfer_buffer);
-			u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
-			u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES;
-		}
-		if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || 
-		    (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) {
-			printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);
-			return 0;
-		}
-		spin_lock_irqsave(&as->lock, flags);
-	}
-	if (u->dma.count <= 0 && !u->dma.mapped) {
-		spin_unlock_irqrestore(&as->lock, flags);
-		return 0;
-	}
-       	u->flags |= FLG_RUNNING;
-	if (!(u->flags & FLG_URB0RUNNING)) {
-		urb = u->durb[0].urb;
-		urb->dev = dev;
-		urb->pipe = u->datapipe;
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->number_of_packets = DESCFRAMES;
-		urb->context = as;
-		urb->complete = usbout_completed;
-		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-			u->flags |= FLG_URB0RUNNING;
-		else
-			u->flags &= ~FLG_RUNNING;
-	}
-	if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {
-		urb = u->durb[1].urb;
-		urb->dev = dev;
-		urb->pipe = u->datapipe;
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->number_of_packets = DESCFRAMES;
-		urb->context = as;
-		urb->complete = usbout_completed;
-		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-			u->flags |= FLG_URB1RUNNING;
-		else
-			u->flags &= ~FLG_RUNNING;
-	}
-	if (u->syncpipe) {
-		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {
-			urb = u->surb[0].urb;
-			urb->dev = dev;
-			urb->pipe = u->syncpipe;
-			urb->transfer_flags = USB_ISO_ASAP;
-			urb->number_of_packets = SYNCFRAMES;
-			urb->context = as;
-			urb->complete = usbout_sync_completed;
-			/* stride: u->syncinterval */
-			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-				u->flags |= FLG_SYNC0RUNNING;
-			else
-				u->flags &= ~FLG_RUNNING;
-		}
-		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {
-			urb = u->surb[1].urb;
-			urb->dev = dev;
-			urb->pipe = u->syncpipe;
-			urb->transfer_flags = USB_ISO_ASAP;
-			urb->number_of_packets = SYNCFRAMES;
-			urb->context = as;
-			urb->complete = usbout_sync_completed;
-			/* stride: u->syncinterval */
-			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
-				u->flags |= FLG_SYNC1RUNNING;
-			else
-				u->flags &= ~FLG_RUNNING;
-		}
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate)
-{
-	unsigned int g = 0;
-
-	if (srate < afp->sratelo)
-		g += afp->sratelo - srate;
-	if (srate > afp->sratehi)
-		g += srate - afp->sratehi;
-	if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt))
-		g += 0x100000;
-	if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt))
-		g += 0x400000;
-	if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt))
-		g += 0x100000;
-	if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt))
-		g += 0x400000;
-	return g;
-}
-
-static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate)
-{
-	unsigned int i, g, gb = ~0;
-	int j = -1; /* default to failure */
-
-	/* find "best" format (according to format_goodness) */
-	for (i = 0; i < nr; i++) {
-		g = format_goodness(&afp[i], fmt, srate);
-		if (g >= gb) 
-			continue;
-		j = i;
-		gb = g;
-	}
-       	return j;
-}
-
-static int set_format_in(struct usb_audiodev *as)
-{
-	struct usb_device *dev = as->state->usbdev;
-	struct usb_config_descriptor *config = dev->actconfig;
-	struct usb_interface_descriptor *alts;
-	struct usb_interface *iface;
-	struct usbin *u = &as->usbin;
-	struct dmabuf *d = &u->dma;
-	struct audioformat *fmt;
-	unsigned int ep;
-	unsigned char data[3];
-	int fmtnr, ret;
-
-	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
-		return 0;
-	iface = &config->interface[u->interface];
-
-	fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate);
-	if (fmtnr < 0) {
-		printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired format/speed combination.\n");
-		return -1;
-	}
-
-	fmt = as->fmtin + fmtnr;
-	alts = &iface->altsetting[fmt->altsetting];
-	u->format = fmt->format;
-	u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);
-	u->syncpipe = u->syncinterval = 0;
-	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x08) {
-		if (alts->bNumEndpoints < 2 ||
-		    alts->endpoint[1].bmAttributes != 0x01 ||
-		    alts->endpoint[1].bSynchAddress != 0 ||
-		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress & 0x7f)) {
-			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
-			       dev->devnum, u->interface, fmt->altsetting);
-			return -1;
-		}
-		u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
-		u->syncinterval = alts->endpoint[1].bRefresh;
-	}
-	if (d->srate < fmt->sratelo)
-		d->srate = fmt->sratelo;
-	if (d->srate > fmt->sratehi)
-		d->srate = fmt->sratehi;
-	dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));
-	if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
-		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
-		       dev->devnum, u->interface, fmt->altsetting);
-		return -1;
-	}
-	if (fmt->sratelo == fmt->sratehi)
-		return 0;
-	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);
-	/* if endpoint has pitch control, enable it */
-	if (fmt->attributes & 0x02) {
-		data[0] = 1;
-		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
-			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
-			       ret, dev->devnum, u->interface, ep, d->srate);
-			return -1;
-		}
-	}
-	/* if endpoint has sampling rate control, set it */
-	if (fmt->attributes & 0x01) {
-		data[0] = d->srate;
-		data[1] = d->srate >> 8;
-		data[2] = d->srate >> 16;
-		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n",
-			       ret, dev->devnum, u->interface, ep, d->srate);
-			return -1;
-		}
-		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n",
-			       ret, dev->devnum, u->interface, ep);
-			return -1;
-		}
-		dprintk((KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n",
-		        dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));
-		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
-	}
-	dprintk((KERN_DEBUG "usbaudio: set_format_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));
-	return 0;
-}
-
-static int set_format_out(struct usb_audiodev *as)
-{
-	struct usb_device *dev = as->state->usbdev;
-	struct usb_config_descriptor *config = dev->actconfig;
-	struct usb_interface_descriptor *alts;
-	struct usb_interface *iface;	
-	struct usbout *u = &as->usbout;
-	struct dmabuf *d = &u->dma;
-	struct audioformat *fmt;
-	unsigned int ep;
-	unsigned char data[3];
-	int fmtnr, ret;
-
-	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
-		return 0;
-	iface = &config->interface[u->interface];
-
-	fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate);
-	if (fmtnr < 0) {
-		printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired format/speed combination.\n");
-		return -1;
-	}
-
-	fmt = as->fmtout + fmtnr;
-	u->format = fmt->format;
-	alts = &iface->altsetting[fmt->altsetting];
-	u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);
-	u->syncpipe = u->syncinterval = 0;
-	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x04) {
-#if 0
-		printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n"
-		       KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n"
-		       KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints,
-		       alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress,
-		       alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress);
-#endif
-		if (alts->bNumEndpoints < 2 ||
-		    alts->endpoint[1].bmAttributes != 0x01 ||
-		    alts->endpoint[1].bSynchAddress != 0 ||
-		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress | 0x80)) {
-			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
-			       dev->devnum, u->interface, fmt->altsetting);
-			return -1;
-		}
-		u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
-		u->syncinterval = alts->endpoint[1].bRefresh;
-	}
-	if (d->srate < fmt->sratelo)
-		d->srate = fmt->sratelo;
-	if (d->srate > fmt->sratehi)
-		d->srate = fmt->sratehi;
-	dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));
-	if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
-		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
-		       dev->devnum, u->interface, fmt->altsetting);
-		return -1;
-	}
-	if (fmt->sratelo == fmt->sratehi)
-		return 0;
-	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);
-	/* if endpoint has pitch control, enable it */
-	if (fmt->attributes & 0x02) {
-		data[0] = 1;
-		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
-			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
-			       ret, dev->devnum, u->interface, ep, d->srate);
-			return -1;
-		}
-	}
-	/* if endpoint has sampling rate control, set it */
-	if (fmt->attributes & 0x01) {
-		data[0] = d->srate;
-		data[1] = d->srate >> 8;
-		data[2] = d->srate >> 16;
-		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n",
-			       ret, dev->devnum, u->interface, ep, d->srate);
-			return -1;
-		}
-		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n",
-			       ret, dev->devnum, u->interface, ep);
-			return -1;
-		}
-		dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",
-		        dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));
-		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
-	}
-	dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));
-	return 0;
-}
-
-static int set_format(struct usb_audiodev *s, unsigned int fmode, unsigned int fmt, unsigned int srate)
-{
-	int ret1 = 0, ret2 = 0;
-
-	if (!(fmode & (FMODE_READ|FMODE_WRITE)))
-		return -EINVAL;
-	if (fmode & FMODE_READ) {
-		usbin_stop(s);
-		s->usbin.dma.ready = 0;
-		if (fmt == AFMT_QUERY)
-			fmt = s->usbin.dma.format;
-		else
-			s->usbin.dma.format = fmt;
-		if (!srate)
-			srate = s->usbin.dma.srate;
-		else
-			s->usbin.dma.srate = srate;
-	}
-	if (fmode & FMODE_WRITE) {
-		usbout_stop(s);
-		s->usbout.dma.ready = 0;
-		if (fmt == AFMT_QUERY)
-			fmt = s->usbout.dma.format;
-		else
-			s->usbout.dma.format = fmt;
-		if (!srate)
-			srate = s->usbout.dma.srate;
-		else
-			s->usbout.dma.srate = srate;
-	}
-	if (fmode & FMODE_READ)
-		ret1 = set_format_in(s);
-	if (fmode & FMODE_WRITE)
-		ret2 = set_format_out(s);
-	return ret1 ? ret1 : ret2;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value)
-{
-	struct usb_device *dev = ms->state->usbdev;
-	unsigned char data[2];
-	struct mixerchannel *ch;
-	int v1, v2, v3;
-
-	if (mixch >= ms->numch)
-		return -1;
-	ch = &ms->ch[mixch];
-	v3 = ch->maxval - ch->minval;
-	v1 = value & 0xff;
-	v2 = (value >> 8) & 0xff;
-	if (v1 > 100)
-		v1 = 100;
-	if (v2 > 100)
-		v2 = 100;
-	if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
-		v2 = v1;
-	ch->value = v1 | (v2 << 8);
-	v1 = (v1 * v3) / 100 + ch->minval;
-	v2 = (v2 * v3) / 100 + ch->minval;
-	switch (ch->selector) {
-	case 0:  /* mixer unit request */
-		data[0] = v1;
-		data[1] = v1 >> 8;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
-			goto err;
-		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
-			return 0;
-		data[0] = v2;
-		data[1] = v2 >> 8;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
-				    ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
-			goto err;
-		return 0;
-
-		/* various feature unit controls */
-	case VOLUME_CONTROL:
-		data[0] = v1;
-		data[1] = v1 >> 8;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
-			goto err;
-		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
-			return 0;
-		data[0] = v2;
-		data[1] = v2 >> 8;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
-			goto err;
-		return 0;
-                
-	case BASS_CONTROL:
-	case MID_CONTROL:
-	case TREBLE_CONTROL:
-		data[0] = v1 >> 8;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
-			goto err;
-		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
-			return 0;
-		data[0] = v2 >> 8;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
-			goto err;
-		return 0;
-
-	default:
-		return -1;
-	}
-	return 0;
-
- err:
-	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
-		dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector);
-	return -1;
-}
-
-static int get_rec_src(struct usb_mixerdev *ms)
-{
-	struct usb_device *dev = ms->state->usbdev;
-	unsigned int mask = 0, retmask = 0;
-	unsigned int i, j;
-	unsigned char buf;
-	int err = 0;
-
-	for (i = 0; i < ms->numch; i++) {
-		if (!ms->ch[i].slctunitid || (mask & (1 << i)))
-			continue;
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
-			err = -EIO;
-			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 
-			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
-			continue;
-		}
-		for (j = i; j < ms->numch; j++) {
-			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
-				continue;
-			mask |= 1 << j;
-			if (buf == (ms->ch[j].slctunitid >> 8))
-				retmask |= 1 << ms->ch[j].osschannel;
-		}
-	}
-	if (err)
-		return -EIO;
-	return retmask;
-}
-
-static int set_rec_src(struct usb_mixerdev *ms, int srcmask)
-{
-	struct usb_device *dev = ms->state->usbdev;
-	unsigned int mask = 0, smask, bmask;
-	unsigned int i, j;
-	unsigned char buf;
-	int err = 0;
-
-	for (i = 0; i < ms->numch; i++) {
-		if (!ms->ch[i].slctunitid || (mask & (1 << i)))
-			continue;
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
-			err = -EIO;
-			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 
-			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
-			continue;
-		}
-		/* first generate smask */
-		smask = bmask = 0;
-		for (j = i; j < ms->numch; j++) {
-			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
-				continue;
-			smask |= 1 << ms->ch[j].osschannel;
-			if (buf == (ms->ch[j].slctunitid >> 8))
-				bmask |= 1 << ms->ch[j].osschannel;
-			mask |= 1 << j;
-		}
-		/* check for multiple set sources */
-		j = hweight32(srcmask & smask);
-		if (j == 0)
-			continue;
-		if (j > 1)
-			srcmask &= ~bmask;
-		for (j = i; j < ms->numch; j++) {
-			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
-				continue;
-			if (!(srcmask & (1 << ms->ch[j].osschannel)))
-				continue;
-			buf = ms->ch[j].slctunitid >> 8;
-			if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, HZ) < 0) {
-				err = -EIO;
-				printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", 
-				       dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff);
-				continue;
-			}
-		}
-	}
-	return err ? -EIO : 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * should be called with open_sem hold, so that no new processes
- * look at the audio device to be destroyed
- */
-
-static void release(struct usb_audio_state *s)
-{
-	struct usb_audiodev *as;
-	struct usb_mixerdev *ms;
-
-	s->count--;
-	if (s->count) {
-		up(&open_sem);
-		return;
-	}
-	up(&open_sem);
-	wake_up(&open_wait);
-	while (!list_empty(&s->audiolist)) {
-		as = list_entry(s->audiolist.next, struct usb_audiodev, list);
-		list_del(&as->list);
-		usbin_release(as);
-		usbout_release(as);
-		dmabuf_release(&as->usbin.dma);
-		dmabuf_release(&as->usbout.dma);
-		usb_free_urb(as->usbin.durb[0].urb);
-		usb_free_urb(as->usbin.durb[1].urb);
-		usb_free_urb(as->usbin.surb[0].urb);
-		usb_free_urb(as->usbin.surb[1].urb);
-		usb_free_urb(as->usbout.durb[0].urb);
-		usb_free_urb(as->usbout.durb[1].urb);
-		usb_free_urb(as->usbout.surb[0].urb);
-		usb_free_urb(as->usbout.surb[1].urb);
-		kfree(as);
-	}
-	while (!list_empty(&s->mixerlist)) {
-		ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list);
-		list_del(&ms->list);
-		kfree(ms);
-	}
-	kfree(s);
-}
-
-extern inline int prog_dmabuf_in(struct usb_audiodev *as)
-{
-	usbin_stop(as);
-	return dmabuf_init(&as->usbin.dma);
-}
-
-extern inline int prog_dmabuf_out(struct usb_audiodev *as)
-{
-	usbout_stop(as);
-	return dmabuf_init(&as->usbout.dma);
-}
-
-/* --------------------------------------------------------------------- */
-
-static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
-{
-	unsigned int minor = minor(inode->i_rdev);
-	struct list_head *devs, *mdevs;
-	struct usb_mixerdev *ms;
-	struct usb_audio_state *s;
-
-	down(&open_sem);
-	for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
-		s = list_entry(devs, struct usb_audio_state, audiodev);
-		for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) {
-			ms = list_entry(mdevs, struct usb_mixerdev, list);
-			if (ms->dev_mixer == minor)
-				goto mixer_found;
-		}
-	}
-	up(&open_sem);
-	return -ENODEV;
-
- mixer_found:
-	if (!s->usbdev) {
-		up(&open_sem);
-		return -EIO;
-	}
-	file->private_data = ms;
-	s->count++;
-
-	up(&open_sem);
-	return 0;
-}
-
-static int usb_audio_release_mixdev(struct inode *inode, struct file *file)
-{
-	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
-	struct usb_audio_state *s;
-
-	lock_kernel();
-	s = ms->state;
-	down(&open_sem);
-	release(s);
-	unlock_kernel();
-	return 0;
-}
-
-static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
-	int i, j, val;
-
-	if (!ms->state->usbdev)
-		return -ENODEV;
-  
-	if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		strncpy(info.id, "USB_AUDIO", sizeof(info.id));
-		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));
-		info.modify_counter = ms->modcnt;
-		if (copy_to_user((void *)arg, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		strncpy(info.id, "USB_AUDIO", sizeof(info.id));
-		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));
-		if (copy_to_user((void *)arg, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, (int *)arg);
-	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
-		return -EINVAL;
-	if (_IOC_DIR(cmd) == _IOC_READ) {
-		switch (_IOC_NR(cmd)) {
-		case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-			val = get_rec_src(ms);
-			if (val < 0)
-				return val;
-			return put_user(val, (int *)arg);
-
-		case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
-			for (val = i = 0; i < ms->numch; i++)
-				val |= 1 << ms->ch[i].osschannel;
-			return put_user(val, (int *)arg);
-
-		case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
-			for (val = i = 0; i < ms->numch; i++)
-				if (ms->ch[i].slctunitid)
-					val |= 1 << ms->ch[i].osschannel;
-			return put_user(val, (int *)arg);
-
-		case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
-			for (val = i = 0; i < ms->numch; i++)
-				if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))
-					val |= 1 << ms->ch[i].osschannel;
-			return put_user(val, (int *)arg);
-			
-		case SOUND_MIXER_CAPS:
-			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
-
-		default:
-			i = _IOC_NR(cmd);
-			if (i >= SOUND_MIXER_NRDEVICES)
-				return -EINVAL;
-			for (j = 0; j < ms->numch; j++) {
-				if (ms->ch[j].osschannel == i) {
-					return put_user(ms->ch[j].value, (int *)arg);
-				}
-			}
-			return -EINVAL;
-		}
-	}
-	if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
-		return -EINVAL;
-	ms->modcnt++;
-	switch (_IOC_NR(cmd)) {
-	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		return set_rec_src(ms, val);
-
-	default:
-		i = _IOC_NR(cmd);
-		if (i >= SOUND_MIXER_NRDEVICES)
-			return -EINVAL;
-		for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);
-		if (j >= ms->numch)
-			return -EINVAL;
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (wrmixer(ms, j, val))
-			return -EIO;
-		return put_user(ms->ch[j].value, (int *)arg);
-	}
-}
-
-static /*const*/ struct file_operations usb_mixer_fops = {
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	ioctl:		usb_audio_ioctl_mixdev,
-	open:		usb_audio_open_mixdev,
-	release:	usb_audio_release_mixdev,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int drain_out(struct usb_audiodev *as, int nonblock)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int count, tmo;
-	
-	if (as->usbout.dma.mapped || !as->usbout.dma.ready)
-		return 0;
-	usbout_start(as);
-	add_wait_queue(&as->usbout.dma.wait, &wait);
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&as->lock, flags);
-		count = as->usbout.dma.count;
-		spin_unlock_irqrestore(&as->lock, flags);
-		if (count <= 0)
-			break;
-		if (signal_pending(current))
-			break;
-		if (nonblock) {
-			remove_wait_queue(&as->usbout.dma.wait, &wait);
-			set_current_state(TASK_RUNNING);
-			return -EBUSY;
-		}
-		tmo = 3 * HZ * count / as->usbout.dma.srate;
-		tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format);
-		if (!schedule_timeout(tmo + 1)) {
-			printk(KERN_DEBUG "usbaudio: dma timed out??\n");
-			break;
-		}
-	}
-	remove_wait_queue(&as->usbout.dma.wait, &wait);
-	set_current_state(TASK_RUNNING);
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-static ssize_t usb_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-	ssize_t ret = 0;
-	unsigned long flags;
-	unsigned int ptr;
-	int cnt, err;
-
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	if (as->usbin.dma.mapped)
-		return -ENXIO;
-	if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as)))
-		return ret;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	add_wait_queue(&as->usbin.dma.wait, &wait);
-	while (count > 0) {
-		spin_lock_irqsave(&as->lock, flags);
-		ptr = as->usbin.dma.rdptr;
-		cnt = as->usbin.dma.count;
-		/* set task state early to avoid wakeup races */
-		if (cnt <= 0)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&as->lock, flags);
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			if (usbin_start(as)) {
-				if (!ret)
-					ret = -ENODEV;
-				break;
-			}
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret)
-					ret = -EAGAIN;
-				break;
-			}
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				break;
-			}
-			continue;
-		}
-		if ((err = dmabuf_copyout_user(&as->usbin.dma, ptr, buffer, cnt))) {
-			if (!ret)
-				ret = err;
-			break;
-		}
-		ptr += cnt;
-		if (ptr >= as->usbin.dma.dmasize)
-			ptr -= as->usbin.dma.dmasize;
-		spin_lock_irqsave(&as->lock, flags);
-		as->usbin.dma.rdptr = ptr;
-		as->usbin.dma.count -= cnt;
-		spin_unlock_irqrestore(&as->lock, flags);
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&as->usbin.dma.wait, &wait);
-	return ret;
-}
-
-static ssize_t usb_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-	ssize_t ret = 0;
-	unsigned long flags;
-	unsigned int ptr;
-	unsigned int start_thr;
-	int cnt, err;
-
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	if (as->usbout.dma.mapped)
-		return -ENXIO;
-	if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as)))
-		return ret;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES));
-	add_wait_queue(&as->usbout.dma.wait, &wait);
-	while (count > 0) {
-#if 0
-		printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n",
-		       count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize,
-		       as->usbout.flags, current->state);
-#endif
-		spin_lock_irqsave(&as->lock, flags);
-		if (as->usbout.dma.count < 0) {
-			as->usbout.dma.count = 0;
-			as->usbout.dma.rdptr = as->usbout.dma.wrptr;
-		}
-		ptr = as->usbout.dma.wrptr;
-		cnt = as->usbout.dma.dmasize - as->usbout.dma.count;
-		/* set task state early to avoid wakeup races */
-		if (cnt <= 0)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&as->lock, flags);
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			if (usbout_start(as)) {
-				if (!ret)
-					ret = -ENODEV;
-				break;
-			}
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret)
-					ret = -EAGAIN;
-				break;
-			}
-			schedule();
-			if (signal_pending(current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				break;
-			}
-			continue;
-		}
-		if ((err = dmabuf_copyin_user(&as->usbout.dma, ptr, buffer, cnt))) {
-			if (!ret)
-				ret = err;
-			break;
-		}
-		ptr += cnt;
-		if (ptr >= as->usbout.dma.dmasize)
-			ptr -= as->usbout.dma.dmasize;
-		spin_lock_irqsave(&as->lock, flags);
-		as->usbout.dma.wrptr = ptr;
-		as->usbout.dma.count += cnt;
-		spin_unlock_irqrestore(&as->lock, flags);
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		if (as->usbout.dma.count >= start_thr && usbout_start(as)) {
-			if (!ret)
-				ret = -ENODEV;
-			break;
-		}
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&as->usbout.dma.wait, &wait);
-	return ret;
-}
-
-/* Called without the kernel lock - fine */
-static unsigned int usb_audio_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	if (file->f_mode & FMODE_WRITE) {
-		if (!as->usbout.dma.ready)
-			prog_dmabuf_out(as);
-		poll_wait(file, &as->usbout.dma.wait, wait);
-	}
-	if (file->f_mode & FMODE_READ) {
-		if (!as->usbin.dma.ready)
-			prog_dmabuf_in(as);
-		poll_wait(file, &as->usbin.dma.wait, wait);
-	}
-	spin_lock_irqsave(&as->lock, flags);
-	if (file->f_mode & FMODE_READ) {
-		if (as->usbin.dma.count >= (signed)as->usbin.dma.fragsize)
-			mask |= POLLIN | POLLRDNORM;
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		if (as->usbout.dma.mapped) {
-			if (as->usbout.dma.count >= (signed)as->usbout.dma.fragsize) 
-				mask |= POLLOUT | POLLWRNORM;
-		} else {
-			if ((signed)as->usbout.dma.dmasize >= as->usbout.dma.count + (signed)as->usbout.dma.fragsize)
-				mask |= POLLOUT | POLLWRNORM;
-		}
-	}
-	spin_unlock_irqrestore(&as->lock, flags);
-	return mask;
-}
-
-static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
-	struct dmabuf *db;
-	int ret = -EINVAL;
-
-	lock_kernel();
-	if (vma->vm_flags & VM_WRITE) {
-		if ((ret = prog_dmabuf_out(as)) != 0)
-			goto out;
-		db = &as->usbout.dma;
-	} else if (vma->vm_flags & VM_READ) {
-		if ((ret = prog_dmabuf_in(as)) != 0)
-			goto out;
-		db = &as->usbin.dma;
-	} else
-		goto out;
-
-	ret = -EINVAL;
-	if (vma->vm_pgoff != 0)
-		goto out;
-
-	ret = dmabuf_mmap(vma, db,  vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
-out:
-	unlock_kernel();
-	return ret;
-}
-
-static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
-	struct usb_audio_state *s = as->state;
-	unsigned long flags;
-	audio_buf_info abinfo;
-	count_info cinfo;
-	int val = 0;
-	int val2, mapped, ret;
-
-	if (!s->usbdev)
-		return -EIO;
-	mapped = ((file->f_mode & FMODE_WRITE) && as->usbout.dma.mapped) ||
-		((file->f_mode & FMODE_READ) && as->usbin.dma.mapped);
-#if 0
-	if (arg)
-		get_user(val, (int *)arg);
-	printk(KERN_DEBUG "usbaudio: usb_audio_ioctl cmd=%x arg=%lx *arg=%d\n", cmd, arg, val)
-#endif
-	switch (cmd) {
-	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, (int *)arg);
-
-	case SNDCTL_DSP_SYNC:
-		if (file->f_mode & FMODE_WRITE)
-			return drain_out(as, 0/*file->f_flags & O_NONBLOCK*/);
-		return 0;
-
-	case SNDCTL_DSP_SETDUPLEX:
-		return 0;
-
-	case SNDCTL_DSP_GETCAPS:
-		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 
-				DSP_CAP_MMAP | DSP_CAP_BATCH, (int *)arg);
-
-	case SNDCTL_DSP_RESET:
-		if (file->f_mode & FMODE_WRITE) {
-			usbout_stop(as);
-			as->usbout.dma.rdptr = as->usbout.dma.wrptr = as->usbout.dma.count = as->usbout.dma.total_bytes = 0;
-		}
-		if (file->f_mode & FMODE_READ) {
-			usbin_stop(as);
-			as->usbin.dma.rdptr = as->usbin.dma.wrptr = as->usbin.dma.count = as->usbin.dma.total_bytes = 0;
-		}
-		return 0;
-
-	case SNDCTL_DSP_SPEED:
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (val >= 0) {
-			if (val < 4000)
-				val = 4000;
-			if (val > 100000)
-				val = 100000;
-			if (set_format(as, file->f_mode, AFMT_QUERY, val))
-				return -EIO;
-		}
-		return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
-
-	case SNDCTL_DSP_STEREO:
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		if (val)
-			val2 |= AFMT_STEREO;
-		else
-			val2 &= ~AFMT_STEREO;
-		if (set_format(as, file->f_mode, val2, 0))
-			return -EIO;
-		return 0;
-
-	case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (val != 0) {
-			val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-			if (val == 1)
-				val2 &= ~AFMT_STEREO;
-			else
-				val2 |= AFMT_STEREO;
-			if (set_format(as, file->f_mode, val2, 0))
-				return -EIO;
-		}
-		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
-
-	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
-		return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE |
-				AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg);
-
-	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (val != AFMT_QUERY) {
-			if (hweight32(val) != 1)
-				return -EINVAL;
-			if (!(val & (AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE |
-				     AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE)))
-				return -EINVAL;
-			val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-			val |= val2 & AFMT_STEREO;
-			if (set_format(as, file->f_mode, val, 0))
-				return -EIO;
-		}
-		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(val2 & ~AFMT_STEREO, (int *)arg);
-
-	case SNDCTL_DSP_POST:
-		return 0;
-
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-		if (file->f_mode & FMODE_READ && as->usbin.flags & FLG_RUNNING) 
-			val |= PCM_ENABLE_INPUT;
-		if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) 
-			val |= PCM_ENABLE_OUTPUT;
-		return put_user(val, (int *)arg);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			if (val & PCM_ENABLE_INPUT) {
-				if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as)))
-					return ret;
-				if (usbin_start(as))
-					return -ENODEV;
-			} else
-				usbin_stop(as);
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			if (val & PCM_ENABLE_OUTPUT) {
-				if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as)))
-					return ret;
-				if (usbout_start(as))
-					return -ENODEV;
-			} else
-				usbout_stop(as);
-		}
-		return 0;
-
-	case SNDCTL_DSP_GETOSPACE:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!(as->usbout.flags & FLG_RUNNING) && (val = prog_dmabuf_out(as)) != 0)
-			return val;
-		spin_lock_irqsave(&as->lock, flags);
-		abinfo.fragsize = as->usbout.dma.fragsize;
-		abinfo.bytes = as->usbout.dma.dmasize - as->usbout.dma.count;
-		abinfo.fragstotal = as->usbout.dma.numfrag;
-		abinfo.fragments = abinfo.bytes >> as->usbout.dma.fragshift;      
-		spin_unlock_irqrestore(&as->lock, flags);
-		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETISPACE:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!(as->usbin.flags & FLG_RUNNING) && (val = prog_dmabuf_in(as)) != 0)
-			return val;
-		spin_lock_irqsave(&as->lock, flags);
-		abinfo.fragsize = as->usbin.dma.fragsize;
-		abinfo.bytes = as->usbin.dma.count;
-		abinfo.fragstotal = as->usbin.dma.numfrag;
-		abinfo.fragments = abinfo.bytes >> as->usbin.dma.fragshift;      
-		spin_unlock_irqrestore(&as->lock, flags);
-		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-		
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-
-	case SNDCTL_DSP_GETODELAY:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		spin_lock_irqsave(&as->lock, flags);
-		val = as->usbout.dma.count;
-		spin_unlock_irqrestore(&as->lock, flags);
-		return put_user(val, (int *)arg);
-
-	case SNDCTL_DSP_GETIPTR:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		spin_lock_irqsave(&as->lock, flags);
-		cinfo.bytes = as->usbin.dma.total_bytes;
-		cinfo.blocks = as->usbin.dma.count >> as->usbin.dma.fragshift;
-		cinfo.ptr = as->usbin.dma.wrptr;
-		if (as->usbin.dma.mapped)
-			as->usbin.dma.count &= as->usbin.dma.fragsize-1;
-		spin_unlock_irqrestore(&as->lock, flags);
-		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
-
-	case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		spin_lock_irqsave(&as->lock, flags);
-		cinfo.bytes = as->usbout.dma.total_bytes;
-		cinfo.blocks = as->usbout.dma.count >> as->usbout.dma.fragshift;
-		cinfo.ptr = as->usbout.dma.rdptr;
-		if (as->usbout.dma.mapped)
-			as->usbout.dma.count &= as->usbout.dma.fragsize-1;
-		spin_unlock_irqrestore(&as->lock, flags);
-		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
-
-       case SNDCTL_DSP_GETBLKSIZE:
-		if (file->f_mode & FMODE_WRITE) {
-			if ((val = prog_dmabuf_out(as)))
-				return val;
-			return put_user(as->usbout.dma.fragsize, (int *)arg);
-		}
-		if ((val = prog_dmabuf_in(as)))
-			return val;
-		return put_user(as->usbin.dma.fragsize, (int *)arg);
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			as->usbin.dma.ossfragshift = val & 0xffff;
-			as->usbin.dma.ossmaxfrags = (val >> 16) & 0xffff;
-			if (as->usbin.dma.ossfragshift < 4)
-				as->usbin.dma.ossfragshift = 4;
-			if (as->usbin.dma.ossfragshift > 15)
-				as->usbin.dma.ossfragshift = 15;
-			if (as->usbin.dma.ossmaxfrags < 4)
-				as->usbin.dma.ossmaxfrags = 4;
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			as->usbout.dma.ossfragshift = val & 0xffff;
-			as->usbout.dma.ossmaxfrags = (val >> 16) & 0xffff;
-			if (as->usbout.dma.ossfragshift < 4)
-				as->usbout.dma.ossfragshift = 4;
-			if (as->usbout.dma.ossfragshift > 15)
-				as->usbout.dma.ossfragshift = 15;
-			if (as->usbout.dma.ossmaxfrags < 4)
-				as->usbout.dma.ossmaxfrags = 4;
-		}
-		return 0;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) ||
-		    (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision))
-			return -EINVAL;
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		if (val != 1 && val != 2 && val != 4)
-			return -EINVAL;
-		if (file->f_mode & FMODE_READ)
-			as->usbin.dma.subdivision = val;
-		if (file->f_mode & FMODE_WRITE)
-			as->usbout.dma.subdivision = val;
-		return 0;
-
-	case SOUND_PCM_READ_RATE:
-		return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
-
-	case SOUND_PCM_READ_CHANNELS:
-		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
-
-	case SOUND_PCM_READ_BITS:
-		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
-		return put_user(AFMT_IS16BIT(val2) ? 16 : 8, (int *)arg);
-
-	case SOUND_PCM_WRITE_FILTER:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_READ_FILTER:
-		return -EINVAL;
-	}
-	dprintk((KERN_DEBUG "usbaudio: usb_audio_ioctl - no command found\n"));
-	return -ENOIOCTLCMD;
-}
-
-static int usb_audio_open(struct inode *inode, struct file *file)
-{
-	unsigned int minor = minor(inode->i_rdev);
-	DECLARE_WAITQUEUE(wait, current);
-	struct list_head *devs, *adevs;
-	struct usb_audiodev *as;
-	struct usb_audio_state *s;
-
-	for (;;) {
-		down(&open_sem);
-		for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
-			s = list_entry(devs, struct usb_audio_state, audiodev);
-			for (adevs = s->audiolist.next; adevs != &s->audiolist; adevs = adevs->next) {
-				as = list_entry(adevs, struct usb_audiodev, list);
-				if (!((as->dev_audio ^ minor) & ~0xf))
-					goto device_found;
-			}
-		}
-		up(&open_sem);
-		return -ENODEV;
-
-	device_found:
-		if (!s->usbdev) {
-			up(&open_sem);
-			return -EIO;
-		}
-		/* wait for device to become free */
-		if (!(as->open_mode & file->f_mode))
-			break;
-		if (file->f_flags & O_NONBLOCK) {
-			up(&open_sem);
-			return -EBUSY;
-		}
-		__set_current_state(TASK_INTERRUPTIBLE);
-		add_wait_queue(&open_wait, &wait);
-		up(&open_sem);
-		schedule();
-		__set_current_state(TASK_RUNNING);
-		remove_wait_queue(&open_wait, &wait);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-	}
-	if (file->f_mode & FMODE_READ)
-		as->usbin.dma.ossfragshift = as->usbin.dma.ossmaxfrags = as->usbin.dma.subdivision = 0;
-	if (file->f_mode & FMODE_WRITE)
-		as->usbout.dma.ossfragshift = as->usbout.dma.ossmaxfrags = as->usbout.dma.subdivision = 0;
-	if (set_format(as, file->f_mode, ((minor & 0xf) == SND_DEV_DSP16) ? AFMT_S16_LE : AFMT_U8 /* AFMT_ULAW */, 8000)) {
-		up(&open_sem);
-		return -EIO;
-	}
-	file->private_data = as;
-	as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-	s->count++;
-	up(&open_sem);
-	return 0;
-}
-
-static int usb_audio_release(struct inode *inode, struct file *file)
-{
-	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
-	struct usb_audio_state *s;
-	struct usb_device *dev;
-	struct usb_interface *iface;
-
-	lock_kernel();
-	s = as->state;
-	dev = s->usbdev;
-	if (file->f_mode & FMODE_WRITE)
-		drain_out(as, file->f_flags & O_NONBLOCK);
-	down(&open_sem);
-	if (file->f_mode & FMODE_WRITE) {
-		usbout_stop(as);
-		if (dev && as->usbout.interface >= 0) {
-			iface = &dev->actconfig->interface[as->usbout.interface];
-			usb_set_interface(dev, iface->altsetting->bInterfaceNumber, 0);
-		}
-		dmabuf_release(&as->usbout.dma);
-		usbout_release(as);
-	}
-	if (file->f_mode & FMODE_READ) {
-		usbin_stop(as);
-		if (dev && as->usbin.interface >= 0) {
-			iface = &dev->actconfig->interface[as->usbin.interface];
-			usb_set_interface(dev, iface->altsetting->bInterfaceNumber, 0);
-		}
-		dmabuf_release(&as->usbin.dma);
-		usbin_release(as);
-	}
-	as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-	release(s);
-	wake_up(&open_wait);
-	unlock_kernel();
-	return 0;
-}
-
-static /*const*/ struct file_operations usb_audio_fops = {
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	read:		usb_audio_read,
-	write:		usb_audio_write,
-	poll:		usb_audio_poll,
-	ioctl:		usb_audio_ioctl,
-	mmap:		usb_audio_mmap,
-	open:		usb_audio_open,
-	release:	usb_audio_release,
-};
-
-/* --------------------------------------------------------------------- */
-
-static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
-			      const struct usb_device_id *id);
-static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
-
-static struct usb_device_id usb_audio_ids [] = {
-    { match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
-      bInterfaceClass: USB_CLASS_AUDIO, bInterfaceSubClass: 1},
-    { }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_audio_ids);
-
-static struct usb_driver usb_audio_driver = {
-	name:		"audio",
-	probe:		usb_audio_probe,
-	disconnect:	usb_audio_disconnect,
-	driver_list:	LIST_HEAD_INIT(usb_audio_driver.driver_list), 
-	id_table:	usb_audio_ids,
-};
-
-static void *find_descriptor(void *descstart, unsigned int desclen, void *after, 
-			     u8 dtype, int iface, int altsetting)
-{
-	u8 *p, *end, *next;
-	int ifc = -1, as = -1;
-
-	p = descstart;
-	end = p + desclen;
-	for (; p < end;) {
-		if (p[0] < 2)
-			return NULL;
-		next = p + p[0];
-		if (next > end)
-			return NULL;
-		if (p[1] == USB_DT_INTERFACE) {
-			/* minimum length of interface descriptor */
-			if (p[0] < 9)
-				return NULL;
-			ifc = p[2];
-			as = p[3];
-		}
-		if (p[1] == dtype && (!after || (void *)p > after) &&
-		    (iface == -1 || iface == ifc) && (altsetting == -1 || altsetting == as)) {
-			return p;
-		}
-		p = next;
-	}
-	return NULL;
-}
-
-static void *find_csinterface_descriptor(void *descstart, unsigned int desclen, void *after, u8 dsubtype, int iface, int altsetting)
-{
-	unsigned char *p;
-
-	p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, altsetting);
-	while (p) {
-		if (p[0] >= 3 && p[2] == dsubtype)
-			return p;
-		p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, altsetting);
-	}
-	return NULL;
-}
-
-static void *find_audiocontrol_unit(void *descstart, unsigned int desclen, void *after, u8 unit, int iface)
-{
-	unsigned char *p;
-
-	p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, -1);
-	while (p) {
-		if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT && p[3] == unit)
-			return p;
-		p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, -1);
-	}
-	return NULL;
-}
-
-static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, int asifin, int asifout)
-{
-	struct usb_device *dev = s->usbdev;
-	struct usb_audiodev *as;
-	struct usb_config_descriptor *config = dev->actconfig;
-	struct usb_interface_descriptor *alts;
-	struct usb_interface *iface;
-	struct audioformat *fp;
-	unsigned char *fmt, *csep;
-	unsigned int i, j, k, format;
-
-	if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL)))
-		return;
-	memset(as, 0, sizeof(struct usb_audiodev));
-	init_waitqueue_head(&as->usbin.dma.wait);
-	init_waitqueue_head(&as->usbout.dma.wait);
-	spin_lock_init(&as->lock);
-	as->usbin.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
-	as->usbin.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
-	as->usbin.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
-	as->usbin.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
-	as->usbout.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
-	as->usbout.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
-	as->usbout.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
-	as->usbout.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
-	if ((!as->usbin.durb[0].urb) ||
-	    (!as->usbin.durb[1].urb) ||
-	    (!as->usbin.surb[0].urb) ||
-	    (!as->usbin.surb[1].urb) ||
-	    (!as->usbout.durb[0].urb) ||
-	    (!as->usbout.durb[1].urb) ||
-	    (!as->usbout.surb[0].urb) ||
-	    (!as->usbout.surb[1].urb)) {
-		usb_free_urb(as->usbin.durb[0].urb);
-		usb_free_urb(as->usbin.durb[1].urb);
-		usb_free_urb(as->usbin.surb[0].urb);
-		usb_free_urb(as->usbin.surb[1].urb);
-		usb_free_urb(as->usbout.durb[0].urb);
-		usb_free_urb(as->usbout.durb[1].urb);
-		usb_free_urb(as->usbout.surb[0].urb);
-		usb_free_urb(as->usbout.surb[1].urb);
-		kfree(as);
-		return;
-	}
-	as->state = s;
-	as->usbin.interface = asifin;
-	as->usbout.interface = asifout;
-	/* search for input formats */
-	if (asifin >= 0) {
-		as->usbin.flags = FLG_CONNECTED;
-		iface = &config->interface[asifin];
-		for (i = 0; i < iface->num_altsetting; i++) {
-			alts = &iface->altsetting[i];
-			if (alts->bInterfaceClass != USB_CLASS_AUDIO || alts->bInterfaceSubClass != 2)
-				continue;
-			if (alts->bNumEndpoints < 1) {
-				if (i != 0) {  /* altsetting 0 has no endpoints (Section B.3.4.1) */
-					printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
-					       dev->devnum, asifin, i);
-				}
-				continue;
-			}
-			if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
-			    !(alts->endpoint[0].bEndpointAddress & 0x80)) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous in\n", 
-				       dev->devnum, asifin, i);
-				continue;
-			}
-			fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifin, i);
-			if (!fmt) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
-				       dev->devnum, asifin, i);
-				continue;
-			}
-			if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", 
-				       dev->devnum, asifin, i);
-				continue;
-			}
-			format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
-			fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifin, i);
-			if (!fmt) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
-				       dev->devnum, asifin, i);
-				continue;
-			}
-			if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
-				       dev->devnum, asifin, i);
-				continue;
-			}
-			if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
-				       dev->devnum, asifin, i, fmt[4], fmt[5]);
-				continue;
-			}
-			csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifin, i);
-			if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", 
-				       dev->devnum, asifin, i);
-				continue;
-			}
-			if (as->numfmtin >= MAXFORMATS)
-				continue;
-			fp = &as->fmtin[as->numfmtin++];
-			if (fmt[5] == 2)
-				format &= (AFMT_U16_LE | AFMT_S16_LE);
-			else
-				format &= (AFMT_U8 | AFMT_S8);
-			if (fmt[4] == 2)
-				format |= AFMT_STEREO;
-			fp->format = format;
-			fp->altsetting = i;
-			fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16);
-			printk(KERN_INFO "usbaudio: valid input sample rate %u\n", fp->sratelo);
-			for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) {
-				k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16);
-				printk(KERN_INFO "usbaudio: valid input sample rate %u\n", k);
-				if (k > fp->sratehi)
-					fp->sratehi = k;
-				if (k < fp->sratelo)
-					fp->sratelo = k;
-			}
-			fp->attributes = csep[3];
-			printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", 
-			       dev->devnum, asifin, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes);
-		}
-	}
-	/* search for output formats */
-	if (asifout >= 0) {
-		as->usbout.flags = FLG_CONNECTED;
-		iface = &config->interface[asifout];
-		for (i = 0; i < iface->num_altsetting; i++) {
-			alts = &iface->altsetting[i];
-			if (alts->bInterfaceClass != USB_CLASS_AUDIO || alts->bInterfaceSubClass != 2)
-				continue;
-			if (alts->bNumEndpoints < 1) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
-			    (alts->endpoint[0].bEndpointAddress & 0x80)) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous out\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			/* See USB audio formats manual, section 2 */
-			fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifout, i);
-			if (!fmt) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
-			/* Dallas DS4201 workaround */
-			if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201)
-				format = (AFMT_S16_LE | AFMT_S8);
-			fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i);
-			if (!fmt) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
-				       dev->devnum, asifout, i, fmt[4], fmt[5]);
-				continue;
-			}
-			csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifout, i);
-			if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
-				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", 
-				       dev->devnum, asifout, i);
-				continue;
-			}
-			if (as->numfmtout >= MAXFORMATS)
-				continue;
-			fp = &as->fmtout[as->numfmtout++];
-			if (fmt[5] == 2)
-				format &= (AFMT_U16_LE | AFMT_S16_LE);
-			else
-				format &= (AFMT_U8 | AFMT_S8);
-			if (fmt[4] == 2)
-				format |= AFMT_STEREO;
-			fp->format = format;
-			fp->altsetting = i;
-			fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16);
-			printk(KERN_INFO "usbaudio: valid output sample rate %u\n", fp->sratelo);
-			for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) {
-				k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16);
-				printk(KERN_INFO "usbaudio: valid output sample rate %u\n", k);
-				if (k > fp->sratehi)
-					fp->sratehi = k;
-				if (k < fp->sratelo)
-					fp->sratelo = k;
-			}
-			fp->attributes = csep[3];
-			printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", 
-			       dev->devnum, asifout, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes);
-		}
-	}
-	if (as->numfmtin == 0 && as->numfmtout == 0) {
-		usb_free_urb(as->usbin.durb[0].urb);
-		usb_free_urb(as->usbin.durb[1].urb);
-		usb_free_urb(as->usbin.surb[0].urb);
-		usb_free_urb(as->usbin.surb[1].urb);
-		usb_free_urb(as->usbout.durb[0].urb);
-		usb_free_urb(as->usbout.durb[1].urb);
-		usb_free_urb(as->usbout.surb[0].urb);
-		usb_free_urb(as->usbout.surb[1].urb);
-		kfree(as);
-		return;
-	}
-	if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) {
-		printk(KERN_ERR "usbaudio: cannot register dsp\n");
-		usb_free_urb(as->usbin.durb[0].urb);
-		usb_free_urb(as->usbin.durb[1].urb);
-		usb_free_urb(as->usbin.surb[0].urb);
-		usb_free_urb(as->usbin.surb[1].urb);
-		usb_free_urb(as->usbout.durb[0].urb);
-		usb_free_urb(as->usbout.durb[1].urb);
-		usb_free_urb(as->usbout.surb[0].urb);
-		usb_free_urb(as->usbout.surb[1].urb);
-		kfree(as);
-		return;
-	}
-	printk(KERN_INFO "usbaudio: registered dsp 14,%d\n", as->dev_audio);
-	/* everything successful */
-	list_add_tail(&as->list, &s->audiolist);
-}
-
-struct consmixstate {
-	struct usb_audio_state *s;
-	unsigned char *buffer;
-	unsigned int buflen;
-	unsigned int ctrlif;
-	struct mixerchannel mixch[SOUND_MIXER_NRDEVICES];
-	unsigned int nrmixch;
-	unsigned int mixchmask;
-	unsigned long unitbitmap[32/sizeof(unsigned long)];
-	/* return values */
-	unsigned int nrchannels;
-	unsigned int termtype;
-	unsigned int chconfig;
-};
-
-static struct mixerchannel *getmixchannel(struct consmixstate *state, unsigned int nr)
-{
-	struct mixerchannel *c;
-
-	if (nr >= SOUND_MIXER_NRDEVICES) {
-		printk(KERN_ERR "usbaudio: invalid OSS mixer channel %u\n", nr);
-		return NULL;
-	}
-	if (!(state->mixchmask & (1 << nr))) {
-		printk(KERN_WARNING "usbaudio: OSS mixer channel %u already in use\n", nr);
-		return NULL;
-	}
-	c = &state->mixch[state->nrmixch++];
-	c->osschannel = nr;
-	state->mixchmask &= ~(1 << nr);
-	return c;
-}
-
-static unsigned int getvolchannel(struct consmixstate *state)
-{
-	unsigned int u;
-
-	if ((state->termtype & 0xff00) == 0x0000 && (state->mixchmask & SOUND_MASK_VOLUME))
-		return SOUND_MIXER_VOLUME;
-	if ((state->termtype & 0xff00) == 0x0100) {
-		if (state->mixchmask & SOUND_MASK_PCM)
-			return SOUND_MIXER_PCM;
-		if (state->mixchmask & SOUND_MASK_ALTPCM)
-			return SOUND_MIXER_ALTPCM;
-	}
-	if ((state->termtype & 0xff00) == 0x0200 && (state->mixchmask & SOUND_MASK_MIC))
-		return SOUND_MIXER_MIC;
-	if ((state->termtype & 0xff00) == 0x0300 && (state->mixchmask & SOUND_MASK_SPEAKER))
-		return SOUND_MIXER_SPEAKER;
-	if ((state->termtype & 0xff00) == 0x0500) {
-		if (state->mixchmask & SOUND_MASK_PHONEIN)
-			return SOUND_MIXER_PHONEIN;
-		if (state->mixchmask & SOUND_MASK_PHONEOUT)
-			return SOUND_MIXER_PHONEOUT;
-	}
-	if (state->termtype >= 0x710 && state->termtype <= 0x711 && (state->mixchmask & SOUND_MASK_RADIO))
-		return SOUND_MIXER_RADIO;
-	if (state->termtype >= 0x709 && state->termtype <= 0x70f && (state->mixchmask & SOUND_MASK_VIDEO))
-		return SOUND_MIXER_VIDEO;
-	u = ffs(state->mixchmask & (SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_LINE3 |
-				    SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 | SOUND_MASK_DIGITAL3));
-	return u-1;
-}
-
-static void prepmixch(struct consmixstate *state)
-{
-	struct usb_device *dev = state->s->usbdev;
-	struct mixerchannel *ch;
-	unsigned char buf[2];
-	__s16 v1;
-	unsigned int v2, v3;
-
-	if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES)
-		return;
-	ch = &state->mixch[state->nrmixch-1];
-	switch (ch->selector) {
-	case 0:  /* mixer unit request */
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-		ch->minval = buf[0] | (buf[1] << 8);
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-		ch->maxval = buf[0] | (buf[1] << 8);
-		v2 = ch->maxval - ch->minval;
-		if (!v2)
-			v2 = 1;
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-		v1 = buf[0] | (buf[1] << 8);
-		v3 = v1 - ch->minval;
-		v3 = 100 * v3 / v2;
-		if (v3 > 100)
-			v3 = 100;
-		ch->value = v3;
-		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
-			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-					    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
-					    state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-			v1 = buf[0] | (buf[1] << 8);
-			v3 = v1 - ch->minval;
-			v3 = 100 * v3 / v2;
-			if (v3 > 100)
-				v3 = 100;
-		}
-		ch->value |= v3 << 8;
-		break;
-
-		/* various feature unit controls */
-	case VOLUME_CONTROL:
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-		ch->minval = buf[0] | (buf[1] << 8);
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-		ch->maxval = buf[0] | (buf[1] << 8);
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-			goto err;
-		v1 = buf[0] | (buf[1] << 8);
-		v2 = ch->maxval - ch->minval;
-		v3 = v1 - ch->minval;
-		if (!v2)
-			v2 = 1;
-		v3 = 100 * v3 / v2;
-		if (v3 > 100)
-			v3 = 100;
-		ch->value = v3;
-		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
-			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
-				goto err;
-			v1 = buf[0] | (buf[1] << 8);
-			v3 = v1 - ch->minval;
-			v3 = 100 * v3 / v2;
-			if (v3 > 100)
-				v3 = 100;
-		}
-		ch->value |= v3 << 8;
-		break;
-		
-	case BASS_CONTROL:
-	case MID_CONTROL:
-	case TREBLE_CONTROL:
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
-			goto err;
-		ch->minval = buf[0] << 8;
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
-			goto err;
-		ch->maxval = buf[0] << 8;
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
-			goto err;
-		v1 = buf[0] << 8;
-		v2 = ch->maxval - ch->minval;
-		v3 = v1 - ch->minval;
-		if (!v2)
-			v2 = 1;
-		v3 = 100 * v3 / v2;
-		if (v3 > 100)
-			v3 = 100;
-		ch->value = v3;
-		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
-			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
-				goto err;
-			v1 = buf[0] << 8;
-			v3 = v1 - ch->minval;
-			v3 = 100 * v3 / v2;
-			if (v3 > 100)
-				v3 = 100;
-		}
-		ch->value |= v3 << 8;
-		break;
-		
-	default:
-		goto err;
-	}
-	return;
-
- err:
-	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
-	       dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector);
-	if (state->nrmixch)
-		state->nrmixch--;
-}
-
-
-static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid);
-
-extern inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
-{
-	unsigned int idx;
-
-	idx = inidx*numoch;
-	if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7))))
-		return 0;
-	if (!(flg & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
-		return 1;
-	idx = (inidx+!!(flg & MIXFLG_STEREOIN))*numoch+!!(flg & MIXFLG_STEREOOUT);
-	if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7))))
-		return 0;
-	return 1;
-}
-
-static void usb_audio_mixerunit(struct consmixstate *state, unsigned char *mixer)
-{
-	unsigned int nroutch = mixer[5+mixer[4]];
-	unsigned int chidx[SOUND_MIXER_NRDEVICES+1];
-	unsigned int termt[SOUND_MIXER_NRDEVICES];
-	unsigned char flg = (nroutch >= 2) ? MIXFLG_STEREOOUT : 0;
-	unsigned char *bmap = &mixer[9+mixer[4]];
-	unsigned int bmapsize;
-	struct mixerchannel *ch;
-	unsigned int i;
-
-	if (!mixer[4]) {
-		printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor\n", mixer[3]);
-		return;
-	}
-	if (mixer[4] > SOUND_MIXER_NRDEVICES) {
-		printk(KERN_ERR "usbaudio: mixer unit %u: too many input pins\n", mixer[3]);
-		return;
-	}
-	chidx[0] = 0;
-	for (i = 0; i < mixer[4]; i++) {
-		usb_audio_recurseunit(state, mixer[5+i]);
-		chidx[i+1] = chidx[i] + state->nrchannels;
-		termt[i] = state->termtype;
-	}
-	state->termtype = 0;
-	state->chconfig = mixer[6+mixer[4]] | (mixer[7+mixer[4]] << 8);
-	bmapsize = (nroutch * chidx[mixer[4]] + 7) >> 3;
-	bmap += bmapsize - 1;
-	if (mixer[0] < 10+mixer[4]+bmapsize) {
-		printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor (bitmap too small)\n", mixer[3]);
-		return;
-	}
-	for (i = 0; i < mixer[4]; i++) {
-		state->termtype = termt[i];
-		if (chidx[i+1]-chidx[i] >= 2) {
-			flg |= MIXFLG_STEREOIN;
-			if (checkmixbmap(bmap, flg, chidx[i], nroutch)) {
-				ch = getmixchannel(state, getvolchannel(state));
-				if (ch) {
-					ch->unitid = mixer[3];
-					ch->selector = 0;
-					ch->chnum = chidx[i]+1;
-					ch->flags = flg;
-					prepmixch(state);
-				}
-				continue;
-			}
-		}
-		flg &= ~MIXFLG_STEREOIN;
-		if (checkmixbmap(bmap, flg, chidx[i], nroutch)) {
-			ch = getmixchannel(state, getvolchannel(state));
-			if (ch) {
-				ch->unitid = mixer[3];
-				ch->selector = 0;
-				ch->chnum = chidx[i]+1;
-				ch->flags = flg;
-				prepmixch(state);
-			}
-		}
-	}	
-	state->termtype = 0;
-}
-
-static struct mixerchannel *slctsrc_findunit(struct consmixstate *state, __u8 unitid)
-{
-	unsigned int i;
-	
-	for (i = 0; i < state->nrmixch; i++)
-		if (state->mixch[i].unitid == unitid)
-			return &state->mixch[i];
-	return NULL;
-}
-
-static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *selector)
-{
-	unsigned int chnum, i, mixch;
-	struct mixerchannel *mch;
-
-	if (!selector[4]) {
-		printk(KERN_ERR "usbaudio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]);
-		return;
-	}
-	mixch = state->nrmixch;
-	usb_audio_recurseunit(state, selector[5]);
-	if (state->nrmixch != mixch) {
-		mch = &state->mixch[state->nrmixch-1];
-		mch->slctunitid = selector[3] | (1 << 8);
-	} else if ((mch = slctsrc_findunit(state, selector[5]))) {
-		mch->slctunitid = selector[3] | (1 << 8);
-	} else {
-		printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n", selector[3]);
-	}
-	chnum = state->nrchannels;
-	for (i = 1; i < selector[4]; i++) {
-		mixch = state->nrmixch;
-		usb_audio_recurseunit(state, selector[5+i]);
-		if (chnum != state->nrchannels) {
-			printk(KERN_ERR "usbaudio: selector unit %u: input pins with varying channel numbers\n", selector[3]);
-			state->termtype = 0;
-			state->chconfig = 0;
-			state->nrchannels = 0;
-			return;
-		}
-		if (state->nrmixch != mixch) {
-			mch = &state->mixch[state->nrmixch-1];
-			mch->slctunitid = selector[3] | ((i + 1) << 8);
-		} else if ((mch = slctsrc_findunit(state, selector[5+i]))) {
-			mch->slctunitid = selector[3] | ((i + 1) << 8);
-		} else {
-			printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel %u\n", selector[3], i+1);
-		}
-	}
-	state->termtype = 0;
-	state->chconfig = 0;
-}
-
-/* in the future we might try to handle 3D etc. effect units */
-
-static void usb_audio_processingunit(struct consmixstate *state, unsigned char *proc)
-{
-	unsigned int i;
-
-	for (i = 0; i < proc[6]; i++)
-		usb_audio_recurseunit(state, proc[7+i]);
-	state->nrchannels = proc[7+proc[6]];
-	state->termtype = 0;
-	state->chconfig = proc[8+proc[6]] | (proc[9+proc[6]] << 8);
-}
-
-
-/* See Audio Class Spec, section 4.3.2.5 */
-static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr)
-{
-	struct mixerchannel *ch;
-	unsigned short chftr, mchftr;
-#if 0
-	struct usb_device *dev = state->s->usbdev;
-	unsigned char data[1];
-#endif
-	unsigned char nr_logical_channels, i;
-
-	usb_audio_recurseunit(state, ftr[4]);
-
-	if (ftr[5] == 0 ) {
-		printk(KERN_ERR "usbaudio: wrong controls size in feature unit %u\n",ftr[3]);
-		return;
-	}
-
-	if (state->nrchannels == 0) {
-		printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]);
-		return;
-	}
-	if (state->nrchannels > 2)
-		printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
-
-	nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
-
-	if (nr_logical_channels != state->nrchannels) {
-		printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels);
-
-		if (state->nrchannels == 1 && nr_logical_channels==0) {
-			printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n");
-		} else if (state->nrchannels == 1 && nr_logical_channels==2) {
-			printk(KERN_INFO "usbaudio: assuming that a stereo channel connected directly to a mixer is missing in search (got Labtec headset?). Should be fine.\n");
-			state->nrchannels=nr_logical_channels;
-		} else {
-			printk(KERN_WARNING "usbaudio: no idea what's going on..., contact linux-usb-devel@lists.sourceforge.net\n");
-		}
-	}
-
-	/* There is always a master channel */
-	mchftr = ftr[6];
-	/* Binary AND over logical channels if they exist */
-	if (nr_logical_channels) {
-		chftr = ftr[6+ftr[5]];
-		for (i = 2; i <= nr_logical_channels; i++)
-			chftr &= ftr[6+i*ftr[5]];
-	} else {
-		chftr = 0;
-	}
-
-	/* volume control */
-	if (chftr & 2) {
-		ch = getmixchannel(state, getvolchannel(state));
-		if (ch) {
-			ch->unitid = ftr[3];
-			ch->selector = VOLUME_CONTROL;
-			ch->chnum = 1;
-			ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0;
-			prepmixch(state);
-		}
-	} else if (mchftr & 2) {
-		ch = getmixchannel(state, getvolchannel(state));
-		if (ch) {
-			ch->unitid = ftr[3];
-			ch->selector = VOLUME_CONTROL;
-			ch->chnum = 0;
-			ch->flags = 0;
-			prepmixch(state);
-		}
-	}
-	/* bass control */
-	if (chftr & 4) {
-		ch = getmixchannel(state, SOUND_MIXER_BASS);
-		if (ch) {
-			ch->unitid = ftr[3];
-			ch->selector = BASS_CONTROL;
-			ch->chnum = 1;
-			ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0;
-			prepmixch(state);
-		}
-	} else if (mchftr & 4) {
-		ch = getmixchannel(state, SOUND_MIXER_BASS);
-		if (ch) {
-			ch->unitid = ftr[3];
-			ch->selector = BASS_CONTROL;
-			ch->chnum = 0;
-			ch->flags = 0;
-			prepmixch(state);
-		}
-	}
-	/* treble control */
-	if (chftr & 16) {
-		ch = getmixchannel(state, SOUND_MIXER_TREBLE);
-		if (ch) {
-			ch->unitid = ftr[3];
-			ch->selector = TREBLE_CONTROL;
-			ch->chnum = 1;
-			ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0;
-			prepmixch(state);
-		}
-	} else if (mchftr & 16) {
-		ch = getmixchannel(state, SOUND_MIXER_TREBLE);
-		if (ch) {
-			ch->unitid = ftr[3];
-			ch->selector = TREBLE_CONTROL;
-			ch->chnum = 0;
-			ch->flags = 0;
-			prepmixch(state);
-		}
-	}
-#if 0
-	/* if there are mute controls, unmute them */
-	/* does not seem to be necessary, and the Dallas chip does not seem to support the "all" channel (255) */
-	if ((chftr & 1) || (mchftr & 1)) {
-		printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif);
-		data[0] = 0;
-		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, HZ) < 0)
-			printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif);
- 	}
-#endif
-}
-
-static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid)
-{
-	unsigned char *p1;
-	unsigned int i, j;
-
-	if (test_and_set_bit(unitid, &state->unitbitmap)) {
-		printk(KERN_INFO "usbaudio: mixer path revisits unit %d\n", unitid);
-		return;
-	}
-	p1 = find_audiocontrol_unit(state->buffer, state->buflen, NULL, unitid, state->ctrlif);
-	if (!p1) {
-		printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid);
-		return;
-	}
-	state->nrchannels = 0;
-	state->termtype = 0;
-	state->chconfig = 0;
-	switch (p1[2]) {
-	case INPUT_TERMINAL:
-		if (p1[0] < 12) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid INPUT_TERMINAL descriptor\n", unitid);
-			return;
-		}
-		state->nrchannels = p1[7];
-		state->termtype = p1[4] | (p1[5] << 8);
-		state->chconfig = p1[8] | (p1[9] << 8);
-		return;
-
-	case MIXER_UNIT:
-		if (p1[0] < 10 || p1[0] < 10+p1[4]) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid MIXER_UNIT descriptor\n", unitid);
-			return;
-		}
-		usb_audio_mixerunit(state, p1);
-		return;
-
-	case SELECTOR_UNIT:
-		if (p1[0] < 6 || p1[0] < 6+p1[4]) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid SELECTOR_UNIT descriptor\n", unitid);
-			return;
-		}
-		usb_audio_selectorunit(state, p1);
-		return;
-
-	case FEATURE_UNIT: /* See USB Audio Class Spec 4.3.2.5 */
-		if (p1[0] < 7 || p1[0] < 7+p1[5]) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid);
-			return;
-		}
-		usb_audio_featureunit(state, p1);
-		return;		
-
-	case PROCESSING_UNIT:
-		if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]] || p1[0] < 13+p1[6]+p1[11+p1[6]]+p1[13+p1[6]+p1[11+p1[6]]]) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid PROCESSING_UNIT descriptor\n", unitid);
-			return;
-		}
-		usb_audio_processingunit(state, p1);
-		return;		
-
-	case EXTENSION_UNIT:
-		if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid EXTENSION_UNIT descriptor\n", unitid);
-			return;
-		}
-		for (j = i = 0; i < p1[6]; i++) {
-			usb_audio_recurseunit(state, p1[7+i]);
-			if (!i)
-				j = state->termtype;
-			else if (j != state->termtype)
-				j = 0;
-		}
-		state->nrchannels = p1[7+p1[6]];
-		state->chconfig = p1[8+p1[6]] | (p1[9+p1[6]] << 8);
-		state->termtype = j;
-		return;
-
-	default:
-		printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
-		return;
-	}
-}
-
-static void usb_audio_constructmixer(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif, unsigned char *oterm)
-{
-	struct usb_mixerdev *ms;
-	struct consmixstate state;
-
-	memset(&state, 0, sizeof(state));
-	state.s = s;
-	state.nrmixch = 0;
-	state.mixchmask = ~0;
-	state.buffer = buffer;
-	state.buflen = buflen;
-	state.ctrlif = ctrlif;
-	set_bit(oterm[3], &state.unitbitmap);  /* mark terminal ID as visited */
-	printk(KERN_DEBUG "usbaudio: constructing mixer for Terminal %u type 0x%04x\n",
-	       oterm[3], oterm[4] | (oterm[5] << 8));
-	usb_audio_recurseunit(&state, oterm[7]);
-	if (!state.nrmixch) {
-		printk(KERN_INFO "usbaudio: no mixer controls found for Terminal %u\n", oterm[3]);
-		return;
-	}
-	if (!(ms = kmalloc(sizeof(struct usb_mixerdev)+state.nrmixch*sizeof(struct mixerchannel), GFP_KERNEL)))
-		return;
-	memset(ms, 0, sizeof(struct usb_mixerdev));
-	memcpy(&ms->ch, &state.mixch, state.nrmixch*sizeof(struct mixerchannel));
-	ms->state = s;
-	ms->iface = ctrlif;
-	ms->numch = state.nrmixch;
-	if ((ms->dev_mixer = register_sound_mixer(&usb_mixer_fops, -1)) < 0) {
-		printk(KERN_ERR "usbaudio: cannot register mixer\n");
-		kfree(ms);
-		return;
-	}
-	printk(KERN_INFO "usbaudio: registered mixer 14,%d\n", ms->dev_mixer);
-	list_add_tail(&ms->list, &s->mixerlist);
-}
-
-static void *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
-{
-	struct usb_audio_state *s;
-	struct usb_config_descriptor *config = dev->actconfig;
-	struct usb_interface *iface;
-	unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES];
-	unsigned char *p1;
-	unsigned int i, j, k, numifin = 0, numifout = 0;
-	
-	if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL)))
-		return NULL;
-	memset(s, 0, sizeof(struct usb_audio_state));
-	INIT_LIST_HEAD(&s->audiolist);
-	INIT_LIST_HEAD(&s->mixerlist);
-	s->usbdev = dev;
-	s->count = 1;
-
-	/* find audiocontrol interface */
-	if (!(p1 = find_csinterface_descriptor(buffer, buflen, NULL, HEADER, ctrlif, -1))) {
-		printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u no HEADER found\n",
-		       dev->devnum, ctrlif);
-		goto ret;
-	}
-	if (p1[0] < 8 + p1[7]) {
-		printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u HEADER error\n",
-		       dev->devnum, ctrlif);
-		goto ret;
-	}
-	if (!p1[7])
-		printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has no AudioStreaming and MidiStreaming interfaces\n",
-		       dev->devnum, ctrlif);
-	for (i = 0; i < p1[7]; i++) {
-		j = p1[8+i];
-		if (j >= config->bNumInterfaces) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n",
-			       dev->devnum, ctrlif, j);
-			continue;
-		}
-		iface = &config->interface[j];
-		if (iface->altsetting[0].bInterfaceClass != USB_CLASS_AUDIO) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n",
-			       dev->devnum, ctrlif, j);
-			continue;
-		}
-		if (iface->altsetting[0].bInterfaceSubClass == 3) {
-			printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n",
-			       dev->devnum, ctrlif, j);
-			continue;
-		}
-		if (iface->altsetting[0].bInterfaceSubClass != 2) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n",
-			       dev->devnum, ctrlif, j);
-			continue;
-		}
-		if (iface->num_altsetting == 0) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has no working interface.\n", dev->devnum, ctrlif);
-			continue;
-		}
-		if (iface->num_altsetting == 1) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif);
-			continue;
-		}
-		if (iface->altsetting[0].bNumEndpoints > 0) {
-			/* Check all endpoints; should they all have a bandwidth of 0 ? */
-			for (k = 0; k < iface->altsetting[0].bNumEndpoints; k++) {
-				if (iface->altsetting[0].endpoint[k].wMaxPacketSize > 0) {
-					printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k);
-					break;
-				}
-			}
-			if (k < iface->altsetting[0].bNumEndpoints)
-				continue;
-		}
-		if (iface->altsetting[1].bNumEndpoints < 1) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n",
-			       dev->devnum, ctrlif, j);
-			continue;
-		}
-		/* note: this requires the data endpoint to be ep0 and the optional sync
-		   ep to be ep1, which seems to be the case */
-		if (iface->altsetting[1].endpoint[0].bEndpointAddress & USB_DIR_IN) {
-			if (numifin < USB_MAXINTERFACES) {
-				ifin[numifin++] = j;
-				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
-			}
-		} else {
-			if (numifout < USB_MAXINTERFACES) {
-				ifout[numifout++] = j;
-				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
-			}
-		}
-	}
-	printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n",
-	       dev->devnum, ctrlif, numifin, numifout);
-	for (i = 0; i < numifin && i < numifout; i++)
-		usb_audio_parsestreaming(s, buffer, buflen, ifin[i], ifout[i]);
-	for (j = i; j < numifin; j++)
-		usb_audio_parsestreaming(s, buffer, buflen, ifin[i], -1);
-	for (j = i; j < numifout; j++)
-		usb_audio_parsestreaming(s, buffer, buflen, -1, ifout[i]);
-	/* now walk through all OUTPUT_TERMINAL descriptors to search for mixers */
-	p1 = find_csinterface_descriptor(buffer, buflen, NULL, OUTPUT_TERMINAL, ctrlif, -1);
-	while (p1) {
-		if (p1[0] >= 9)
-			usb_audio_constructmixer(s, buffer, buflen, ctrlif, p1);
-		p1 = find_csinterface_descriptor(buffer, buflen, p1, OUTPUT_TERMINAL, ctrlif, -1);
-	}
-
-ret:
-	if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) {
-		kfree(s);
-		return NULL;
-	}
-	/* everything successful */
-	down(&open_sem);
-	list_add_tail(&s->audiodev, &audiodevs);
-	up(&open_sem);
-	printk(KERN_DEBUG "usb_audio_parsecontrol: usb_audio_state at %p\n", s);
-	return s;
-}
-
-/* we only care for the currently active configuration */
-
-static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
-			     const struct usb_device_id *id)
-{
-	struct usb_config_descriptor *config = dev->actconfig;	
-	unsigned char *buffer;
-	unsigned char buf[8];
-	unsigned int i, buflen;
-	int ret;
-
-#if 0
-	printk(KERN_DEBUG "usbaudio: Probing if %i: IC %x, ISC %x\n", ifnum,
-	       config->interface[ifnum].altsetting[0].bInterfaceClass,
-	       config->interface[ifnum].altsetting[0].bInterfaceSubClass);
-#endif
-
-	/*
-	 * audiocontrol interface found
-	 * find which configuration number is active
-	 */
-	i = dev->actconfig - config;
-
-	if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
-		printk(KERN_ERR "usbaudio: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue);
-		return NULL;
-	}
-	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8);
-	if (ret < 0) {
-		printk(KERN_ERR "usbaudio: cannot get first 8 bytes of config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
-		return NULL;
-	}
-	if (buf[1] != USB_DT_CONFIG || buf[0] < 9) {
-		printk(KERN_ERR "usbaudio: invalid config descriptor %d of device %d\n", i, dev->devnum);
-		return NULL;
-	}
-	buflen = buf[2] | (buf[3] << 8);
-	if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
-		return NULL;
-	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
-	if (ret < 0) {
-		kfree(buffer);
-		printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
-		return NULL;
-	}
-	return usb_audio_parsecontrol(dev, buffer, buflen, ifnum);
-}
-
-
-/* a revoke facility would make things simpler */
-
-static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_audio_state *s = (struct usb_audio_state *)ptr;
-	struct list_head *list;
-	struct usb_audiodev *as;
-	struct usb_mixerdev *ms;
-
-	/* we get called with -1 for every audiostreaming interface registered */
-	if (s == (struct usb_audio_state *)-1) {
-		dprintk((KERN_DEBUG "usbaudio: note, usb_audio_disconnect called with -1\n"));
-		return;
-	}
-	if (!s->usbdev) {
-		dprintk((KERN_DEBUG "usbaudio: error,  usb_audio_disconnect already called for %p!\n", s));
-		return;
-	}
-	down(&open_sem);
-	list_del(&s->audiodev);
-	INIT_LIST_HEAD(&s->audiodev);
-	s->usbdev = NULL;
-	/* deregister all audio and mixer devices, so no new processes can open this device */
-	for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
-		as = list_entry(list, struct usb_audiodev, list);
-		usbin_disc(as);
-		usbout_disc(as);
-		wake_up(&as->usbin.dma.wait);
-		wake_up(&as->usbout.dma.wait);
-		if (as->dev_audio >= 0) {
-			unregister_sound_dsp(as->dev_audio);
-			printk(KERN_INFO "usbaudio: unregister dsp 14,%d\n", as->dev_audio);
-		}
-		as->dev_audio = -1;
-	}
-	for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) {
-		ms = list_entry(list, struct usb_mixerdev, list);
-		if (ms->dev_mixer >= 0) {
-			unregister_sound_mixer(ms->dev_mixer);
-			printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer);
-		}
-		ms->dev_mixer = -1;
-	}
-	release(s);
-	wake_up(&open_wait);
-}
-
-static int __init usb_audio_init(void)
-{
-	usb_register(&usb_audio_driver);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-
-static void __exit usb_audio_cleanup(void)
-{
-	usb_deregister(&usb_audio_driver);
-}
-
-module_init(usb_audio_init);
-module_exit(usb_audio_cleanup);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/audio.h b/drivers/usb/audio.h
--- a/drivers/usb/audio.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,116 +0,0 @@
-#define USB_DT_CS_DEVICE                0x21
-#define USB_DT_CS_CONFIG                0x22
-#define USB_DT_CS_STRING                0x23
-#define USB_DT_CS_INTERFACE             0x24
-#define USB_DT_CS_ENDPOINT              0x25
-
-#define CS_AUDIO_UNDEFINED		0x20
-#define CS_AUDIO_DEVICE			0x21
-#define CS_AUDIO_CONFIGURATION		0x22
-#define CS_AUDIO_STRING			0x23
-#define CS_AUDIO_INTERFACE		0x24
-#define CS_AUDIO_ENDPOINT		0x25
-
-#define HEADER				0x01
-#define INPUT_TERMINAL			0x02
-#define OUTPUT_TERMINAL			0x03
-#define MIXER_UNIT			0x04
-#define SELECTOR_UNIT			0x05
-#define FEATURE_UNIT			0x06
-#define PROCESSING_UNIT			0x07
-#define EXTENSION_UNIT			0x08
-
-#define AS_GENERAL			0x01
-#define FORMAT_TYPE			0x02
-#define FORMAT_SPECIFIC			0x03
-
-#define EP_GENERAL			0x01
-
-#define MAX_CHAN			9
-#define MAX_FREQ			16
-#define MAX_IFACE			8
-#define MAX_FORMAT			8
-#define MAX_ALT				32 	/* Sorry, we need quite a few for the Philips webcams */
-
-struct usb_audio_terminal
-{	
-	u8	flags;
-	u8	assoc;
-	u16	type;			/* Mic etc */
-	u8	channels;
-	u8	source;
-	u16	chancfg;
-};
-
-struct usb_audio_format
-{
-	u8	type;
-	u8	channels;
-	u8	num_freq;
-	u8	sfz;
-	u8	bits;
-	u16	freq[MAX_FREQ];
-};
-
-struct usb_audio_interface
-{
-	u8	terminal;
-	u8	delay;
-	u16	num_formats;
-	u16	format_type;
-	u8	flags;
-	u8	idleconf;	/* Idle config */
-#define AU_IFACE_FOUND	1
-	struct  usb_audio_format format[MAX_FORMAT];
-};
-
-struct usb_audio_device
-{
-	struct list_head list;
-	u8	mixer;
-	u8	selector;
-	void	*irq_handle;
-	u8	num_channels;
-	u8	num_dsp_iface;
-	u8	channel_map[MAX_CHAN];
-	struct usb_audio_terminal terminal[MAX_CHAN];
-	struct usb_audio_interface interface[MAX_IFACE][MAX_ALT];
-};
-
-
-
-/* Audio Class specific Request Codes */
-
-#define SET_CUR    0x01
-#define GET_CUR    0x81
-#define SET_MIN    0x02
-#define GET_MIN    0x82
-#define SET_MAX    0x03
-#define GET_MAX    0x83
-#define SET_RES    0x04
-#define GET_RES    0x84
-#define SET_MEM    0x05
-#define GET_MEM    0x85
-#define GET_STAT   0xff
-
-/* Terminal Control Selectors */
-
-#define COPY_PROTECT_CONTROL       0x01
-
-/* Feature Unit Control Selectors */
-
-#define MUTE_CONTROL               0x01
-#define VOLUME_CONTROL             0x02
-#define BASS_CONTROL               0x03
-#define MID_CONTROL                0x04
-#define TREBLE_CONTROL             0x05
-#define GRAPHIC_EQUALIZER_CONTROL  0x06
-#define AUTOMATIC_GAIN_CONTROL     0x07
-#define DELAY_CONTROL              0x08
-#define BASS_BOOST_CONTROL         0x09
-#define LOUDNESS_CONTROL           0x0a
-
-/* Endpoint Control Selectors */
-
-#define SAMPLING_FREQ_CONTROL      0x01
-#define PITCH_CONTROL              0x02
diff -Nru a/drivers/usb/auerswald.c b/drivers/usb/auerswald.c
--- a/drivers/usb/auerswald.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2188 +0,0 @@
-/*****************************************************************************/
-/*
- *      auerswald.c  --  Auerswald PBX/System Telephone usb driver.
- *
- *      Copyright (C) 2001  Wolfgang Mües (wmues@nexgo.de)
- *
- *      Very much code of this driver is borrowed from dabusb.c (Deti Fliegl)
- *      and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you.
- *
- *      This program is free software; you can redistribute it and/or 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.
- */
- /*****************************************************************************/
-
-/* Standard Linux module include files */
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#undef DEBUG   		/* include debug macros until it's done	*/
-#include <linux/usb.h>
-
-/*-------------------------------------------------------------------*/
-/* Debug support 						     */
-#ifdef DEBUG
-#define dump( adr, len) \
-do {			\
-	unsigned int u;	\
-	printk (KERN_DEBUG); \
-	for (u = 0; u < len; u++) \
-		printk (" %02X", adr[u] & 0xFF); \
-	printk ("\n"); \
-} while (0)
-#else
-#define dump( adr, len)
-#endif
-
-/*-------------------------------------------------------------------*/
-/* Version Information */
-#define DRIVER_VERSION "0.9.11"
-#define DRIVER_AUTHOR  "Wolfgang Mües <wmues@nexgo.de>"
-#define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
-
-/*-------------------------------------------------------------------*/
-/* Private declarations for Auerswald USB driver                     */
-
-/* Auerswald Vendor ID */
-#define ID_AUERSWALD  	0x09BF
-
-#ifndef AUER_MINOR_BASE		/* allow external override */
-#define AUER_MINOR_BASE	112	/* auerswald driver minor number */
-#endif
-
-/* we can have up to this number of device plugged in at once */
-#define AUER_MAX_DEVICES 16
-
-/* prefix for the device descriptors in /dev/usb */
-#define AU_PREFIX	"auer"
-
-/* Number of read buffers for each device */
-#define AU_RBUFFERS     10
-
-/* Number of chain elements for each control chain */
-#define AUCH_ELEMENTS   20
-
-/* Number of retries in communication */
-#define AU_RETRIES	10
-
-/*-------------------------------------------------------------------*/
-/* vendor specific protocol                                          */
-/* Header Byte */
-#define AUH_INDIRMASK   0x80    /* mask for direct/indirect bit */
-#define AUH_DIRECT      0x00    /* data is for USB device */
-#define AUH_INDIRECT    0x80    /* USB device is relay */
-
-#define AUH_SPLITMASK   0x40    /* mask for split bit */
-#define AUH_UNSPLIT     0x00    /* data block is full-size */
-#define AUH_SPLIT       0x40    /* data block is part of a larger one,
-                                   split-byte follows */
-
-#define AUH_TYPEMASK    0x3F    /* mask for type of data transfer */
-#define AUH_TYPESIZE    0x40    /* different types */
-#define AUH_DCHANNEL    0x00    /* D channel data */
-#define AUH_B1CHANNEL   0x01    /* B1 channel transparent */
-#define AUH_B2CHANNEL   0x02    /* B2 channel transparent */
-/*                0x03..0x0F       reserved for driver internal use */
-#define AUH_COMMAND     0x10    /* Command channel */
-#define AUH_BPROT       0x11    /* Configuration block protocol */
-#define AUH_DPROTANA    0x12    /* D channel protocol analyzer */
-#define AUH_TAPI        0x13    /* telephone api data (ATD) */
-/*                0x14..0x3F       reserved for other protocols */
-#define AUH_UNASSIGNED  0xFF    /* if char device has no assigned service */
-#define AUH_FIRSTUSERCH 0x11    /* first channel which is available for driver users */
-
-#define AUH_SIZE	1 	/* Size of Header Byte */
-
-/* Split Byte. Only present if split bit in header byte set.*/
-#define AUS_STARTMASK   0x80    /* mask for first block of splitted frame */
-#define AUS_FIRST       0x80    /* first block */
-#define AUS_FOLLOW      0x00    /* following block */
-
-#define AUS_ENDMASK     0x40    /* mask for last block of splitted frame */
-#define AUS_END         0x40    /* last block */
-#define AUS_NOEND       0x00    /* not the last block */
-
-#define AUS_LENMASK     0x3F    /* mask for block length information */
-
-/* Request types */
-#define AUT_RREQ        (USB_DIR_IN  | USB_TYPE_VENDOR | USB_RECIP_OTHER)   /* Read Request */
-#define AUT_WREQ        (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER)   /* Write Request */
-
-/* Vendor Requests */
-#define AUV_GETINFO     0x00    /* GetDeviceInfo */
-#define AUV_WBLOCK      0x01    /* Write Block */
-#define AUV_RBLOCK      0x02    /* Read Block */
-#define AUV_CHANNELCTL  0x03    /* Channel Control */
-#define AUV_DUMMY	0x04	/* Dummy Out for retry */
-
-/* Device Info Types */
-#define AUDI_NUMBCH     0x0000  /* Number of supported B channels */
-#define AUDI_OUTFSIZE   0x0001  /* Size of OUT B channel fifos */
-#define AUDI_MBCTRANS   0x0002  /* max. Blocklength of control transfer */
-
-/* Interrupt endpoint definitions */
-#define AU_IRQENDP      1       /* Endpoint number */
-#define AU_IRQCMDID     16      /* Command-block ID */
-#define AU_BLOCKRDY     0       /* Command: Block data ready on ctl endpoint */
-#define AU_IRQMINSIZE	5	/* Nr. of bytes decoded in this driver */
-
-/* Device String Descriptors */
-#define AUSI_VENDOR   	1	/* "Auerswald GmbH & Co. KG" */
-#define AUSI_DEVICE   	2	/* Name of the Device */
-#define AUSI_SERIALNR 	3	/* Serial Number */
-#define AUSI_MSN      	4	/* "MSN ..." (first) Multiple Subscriber Number */
-
-#define AUSI_DLEN	100	/* Max. Length of Device Description */
-
-#define AUV_RETRY	0x101	/* First Firmware version which can do control retries */
-
-/*-------------------------------------------------------------------*/
-/* External data structures / Interface                              */
-typedef struct
-{
-        char *buf;               /* return buffer for string contents */
-        unsigned int bsize;      /* size of return buffer */
-} audevinfo_t,*paudevinfo_t;
-
-/* IO controls */
-#define IOCTL_AU_SLEN	  _IOR( 'U', 0xF0, int)         /* return the max. string descriptor length */
-#define IOCTL_AU_DEVINFO  _IOWR('U', 0xF1, audevinfo_t) /* get name of a specific device */
-#define IOCTL_AU_SERVREQ  _IOW( 'U', 0xF2, int) 	/* request a service channel */
-#define IOCTL_AU_BUFLEN	  _IOR( 'U', 0xF3, int)         /* return the max. buffer length for the device */
-#define IOCTL_AU_RXAVAIL  _IOR( 'U', 0xF4, int)         /* return != 0 if Receive Data available */
-#define IOCTL_AU_CONNECT  _IOR( 'U', 0xF5, int)         /* return != 0 if connected to a service channel */
-#define IOCTL_AU_TXREADY  _IOR( 'U', 0xF6, int)         /* return != 0 if Transmitt channel ready to send */
-/*                              'U'  0xF7..0xFF reseved */
-
-/*-------------------------------------------------------------------*/
-/* Internal data structures                                          */
-
-/* ..................................................................*/
-/* urb chain element */
-struct  auerchain;                      /* forward for circular reference */
-typedef struct
-{
-        struct auerchain *chain;        /* pointer to the chain to which this element belongs */
-        struct urb * urbp;                   /* pointer to attached urb */
-        void *context;                  /* saved URB context */
-        usb_complete_t complete;        /* saved URB completion function */
-        struct list_head list;          /* to include element into a list */
-} auerchainelement_t,*pauerchainelement_t;
-
-/* urb chain */
-typedef struct auerchain
-{
-        pauerchainelement_t active;     /* element which is submitted to urb */
-	spinlock_t lock;                /* protection agains interrupts */
-        struct list_head waiting_list;  /* list of waiting elements */
-        struct list_head free_list;     /* list of available elements */
-} auerchain_t,*pauerchain_t;
-
-/* urb blocking completion helper struct */
-typedef struct
-{
-	wait_queue_head_t wqh;    	/* wait for completion */
-	unsigned int done;		/* completion flag */
-} auerchain_chs_t,*pauerchain_chs_t;
-
-/* ...................................................................*/
-/* buffer element */
-struct  auerbufctl;                     /* forward */
-typedef struct
-{
-        char *bufp;                     /* reference to allocated data buffer */
-        unsigned int len;               /* number of characters in data buffer */
-	unsigned int retries;		/* for urb retries */
-        struct usb_ctrlrequest *dr;	/* for setup data in control messages */
-        struct urb * urbp;                   /* USB urb */
-        struct auerbufctl *list;        /* pointer to list */
-        struct list_head buff_list;     /* reference to next buffer in list */
-} auerbuf_t,*pauerbuf_t;
-
-/* buffer list control block */
-typedef struct auerbufctl
-{
-        spinlock_t lock;                /* protection in interrupt */
-        struct list_head free_buff_list;/* free buffers */
-        struct list_head rec_buff_list; /* buffers with receive data */
-} auerbufctl_t,*pauerbufctl_t;
-
-/* ...................................................................*/
-/* service context */
-struct  auerscon;                       /* forward */
-typedef void (*auer_dispatch_t)(struct auerscon*, pauerbuf_t);
-typedef void (*auer_disconn_t) (struct auerscon*);
-typedef struct auerscon
-{
-        unsigned int id;                /* protocol service id AUH_xxxx */
-        auer_dispatch_t dispatch;       /* dispatch read buffer */
-	auer_disconn_t disconnect;	/* disconnect from device, wake up all char readers */
-} auerscon_t,*pauerscon_t;
-
-/* ...................................................................*/
-/* USB device context */
-typedef struct
-{
-	struct semaphore 	mutex;         	    /* protection in user context */
-	char 			name[16];	    /* name of the /dev/usb entry */
-	unsigned int		dtindex;	    /* index in the device table */
-	devfs_handle_t 		devfs;	 	    /* devfs device node */
-	struct usb_device *	usbdev;      	    /* USB device handle */
-	int			open_count;	    /* count the number of open character channels */
-        char 			dev_desc[AUSI_DLEN];/* for storing a textual description */
-        unsigned int 		maxControlLength;   /* max. Length of control paket (without header) */
-        struct urb * 		inturbp;            /* interrupt urb */
-        char *			intbufp;            /* data buffer for interrupt urb */
-	unsigned int 		irqsize;	    /* size of interrupt endpoint 1 */
-        struct auerchain 	controlchain;  	    /* for chaining of control messages */
-	auerbufctl_t 		bufctl;             /* Buffer control for control transfers */
-        pauerscon_t 	     	services[AUH_TYPESIZE];/* context pointers for each service */
-	unsigned int		version;	    /* Version of the device */
-	wait_queue_head_t 	bufferwait;         /* wait for a control buffer */
-} auerswald_t,*pauerswald_t;
-
-/* the global usb devfs handle */
-extern devfs_handle_t usb_devfs_handle;
-
-/* array of pointers to our devices that are currently connected */
-static pauerswald_t dev_table[AUER_MAX_DEVICES];
-
-/* lock to protect the dev_table structure */
-static struct semaphore dev_table_mutex;
-
-/* ................................................................... */
-/* character device context */
-typedef struct
-{
-	struct semaphore mutex;         /* protection in user context */
-	pauerswald_t auerdev;           /* context pointer of assigned device */
-        auerbufctl_t bufctl;            /* controls the buffer chain */
-        auerscon_t scontext;            /* service context */
-	wait_queue_head_t readwait;     /* for synchronous reading */
-	struct semaphore readmutex;     /* protection against multiple reads */
-	pauerbuf_t readbuf;		/* buffer held for partial reading */
-	unsigned int readoffset;	/* current offset in readbuf */
-	unsigned int removed;		/* is != 0 if device is removed */
-} auerchar_t,*pauerchar_t;
-
-
-/*-------------------------------------------------------------------*/
-/* Forwards */
-static void auerswald_ctrlread_complete (struct urb * urb);
-static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
-
-
-/*-------------------------------------------------------------------*/
-/* USB chain helper functions                                        */
-/* --------------------------                                        */
-
-/* completion function for chained urbs */
-static void auerchain_complete (struct urb * urb)
-{
-	unsigned long flags;
-        int result;
-
-        /* get pointer to element and to chain */
-        pauerchainelement_t acep = (pauerchainelement_t) urb->context;
-        pauerchain_t         acp = acep->chain;
-
-        /* restore original entries in urb */
-        urb->context  = acep->context;
-        urb->complete = acep->complete;
-
-        dbg ("auerchain_complete called");
-
-        /* call original completion function
-           NOTE: this function may lead to more urbs submitted into the chain.
-                 (no chain lock at calling complete()!)
-                 acp->active != NULL is protecting us against recursion.*/
-        urb->complete (urb);
-
-        /* detach element from chain data structure */
-	spin_lock_irqsave (&acp->lock, flags);
-        if (acp->active != acep) /* paranoia debug check */
-	        dbg ("auerchain_complete: completion on non-active element called!");
-        else
-                acp->active = NULL;
-
-        /* add the used chain element to the list of free elements */
-	list_add_tail (&acep->list, &acp->free_list);
-        acep = NULL;
-
-        /* is there a new element waiting in the chain? */
-        if (!acp->active && !list_empty (&acp->waiting_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = acp->waiting_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-                acp->active = acep;
-        }
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* submit the new urb */
-        if (acep) {
-                urb    = acep->urbp;
-                dbg ("auerchain_complete: submitting next urb from chain");
-		urb->status = 0;	/* needed! */
-		result = usb_submit_urb(urb, GFP_KERNEL);
-
-                /* check for submit errors */
-                if (result) {
-                        urb->status = result;
-                        dbg("auerchain_complete: usb_submit_urb with error code %d", result);
-                        /* and do error handling via *this* completion function (recursive) */
-                        auerchain_complete( urb);
-                }
-        } else {
-                /* simple return without submitting a new urb.
-                   The empty chain is detected with acp->active == NULL. */
-        };
-}
-
-
-/* submit function for chained urbs
-   this function may be called from completion context or from user space!
-   early = 1 -> submit in front of chain
-*/
-static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int early)
-{
-        int result;
-        unsigned long flags;
-        pauerchainelement_t acep = NULL;
-
-        dbg ("auerchain_submit_urb called");
-
-        /* try to get a chain element */
-        spin_lock_irqsave (&acp->lock, flags);
-        if (!list_empty (&acp->free_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = acp->free_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-        }
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* if no chain element available: return with error */
-        if (!acep) {
-                return -ENOMEM;
-        }
-
-        /* fill in the new chain element values */
-        acep->chain    = acp;
-        acep->context  = urb->context;
-        acep->complete = urb->complete;
-        acep->urbp     = urb;
-        INIT_LIST_HEAD (&acep->list);
-
-        /* modify urb */
-        urb->context   = acep;
-        urb->complete  = auerchain_complete;
-        urb->status    = -EINPROGRESS;    /* usb_submit_urb does this, too */
-
-        /* add element to chain - or start it immediately */
-        spin_lock_irqsave (&acp->lock, flags);
-        if (acp->active) {
-                /* there is traffic in the chain, simple add element to chain */
-		if (early) {
-			dbg ("adding new urb to head of chain");
-			list_add (&acep->list, &acp->waiting_list);
-		} else {
-			dbg ("adding new urb to end of chain");
-			list_add_tail (&acep->list, &acp->waiting_list);
-		}
-		acep = NULL;
-        } else {
-                /* the chain is empty. Prepare restart */
-                acp->active = acep;
-        }
-        /* Spin has to be removed before usb_submit_urb! */
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* Submit urb if immediate restart */
-        if (acep) {
-                dbg("submitting urb immediate");
-		urb->status = 0;	/* needed! */
-                result = usb_submit_urb(urb, GFP_KERNEL);
-                /* check for submit errors */
-                if (result) {
-                        urb->status = result;
-                        dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
-                        /* and do error handling via completion function */
-                        auerchain_complete( urb);
-                }
-        }
-
-        return 0;
-}
-
-/* submit function for chained urbs
-   this function may be called from completion context or from user space!
-*/
-static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb)
-{
-	return auerchain_submit_urb_list (acp, urb, 0);
-}
-
-/* cancel an urb which is submitted to the chain
-   the result is 0 if the urb is cancelled, or -EINPROGRESS if
-   USB_ASYNC_UNLINK is set and the function is successfully started.
-*/
-static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
-{
-	unsigned long flags;
-        struct urb * urbp;
-        pauerchainelement_t acep;
-        struct list_head *tmp;
-
-        dbg ("auerchain_unlink_urb called");
-
-        /* search the chain of waiting elements */
-        spin_lock_irqsave (&acp->lock, flags);
-        list_for_each (tmp, &acp->waiting_list) {
-                acep = list_entry (tmp, auerchainelement_t, list);
-                if (acep->urbp == urb) {
-                        list_del (tmp);
-                        urb->context = acep->context;
-                        urb->complete = acep->complete;
-                        list_add_tail (&acep->list, &acp->free_list);
-                        spin_unlock_irqrestore (&acp->lock, flags);
-                        dbg ("unlink waiting urb");
-                        urb->status = -ENOENT;
-                        urb->complete (urb);
-                        return 0;
-                }
-        }
-        /* not found. */
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* get the active urb */
-        acep = acp->active;
-        if (acep) {
-                urbp = acep->urbp;
-
-                /* check if we have to cancel the active urb */
-                if (urbp == urb) {
-                        /* note that there is a race condition between the check above
-                           and the unlink() call because of no lock. This race is harmless,
-                           because the usb module will detect the unlink() after completion.
-                           We can't use the acp->lock here because the completion function
-                           wants to grab it.
-			*/
-                        dbg ("unlink active urb");
-                        return usb_unlink_urb (urbp);
-                }
-        }
-
-        /* not found anyway
-           ... is some kind of success
-	*/
-        dbg ("urb to unlink not found in chain");
-        return 0;
-}
-
-/* cancel all urbs which are in the chain.
-   this function must not be called from interrupt or completion handler.
-*/
-static void auerchain_unlink_all (pauerchain_t acp)
-{
-	unsigned long flags;
-        struct urb * urbp;
-        pauerchainelement_t acep;
-
-        dbg ("auerchain_unlink_all called");
-
-        /* clear the chain of waiting elements */
-        spin_lock_irqsave (&acp->lock, flags);
-        while (!list_empty (&acp->waiting_list)) {
-                /* get the next entry */
-                struct list_head *tmp = acp->waiting_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-                urbp = acep->urbp;
-                urbp->context = acep->context;
-                urbp->complete = acep->complete;
-                list_add_tail (&acep->list, &acp->free_list);
-                spin_unlock_irqrestore (&acp->lock, flags);
-                dbg ("unlink waiting urb");
-                urbp->status = -ENOENT;
-                urbp->complete (urbp);
-                spin_lock_irqsave (&acp->lock, flags);
-        }
-        spin_unlock_irqrestore (&acp->lock, flags);
-
-        /* clear the active urb */
-        acep = acp->active;
-        if (acep) {
-                urbp = acep->urbp;
-                urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
-                dbg ("unlink active urb");
-                usb_unlink_urb (urbp);
-        }
-}
-
-
-/* free the chain.
-   this function must not be called from interrupt or completion handler.
-*/
-static void auerchain_free (pauerchain_t acp)
-{
-	unsigned long flags;
-        pauerchainelement_t acep;
-
-        dbg ("auerchain_free called");
-
-        /* first, cancel all pending urbs */
-        auerchain_unlink_all (acp);
-
-        /* free the elements */
-        spin_lock_irqsave (&acp->lock, flags);
-        while (!list_empty (&acp->free_list)) {
-                /* get the next entry */
-                struct list_head *tmp = acp->free_list.next;
-                list_del (tmp);
-                spin_unlock_irqrestore (&acp->lock, flags);
-		acep = list_entry (tmp, auerchainelement_t, list);
-                kfree (acep);
-	        spin_lock_irqsave (&acp->lock, flags);
-	}
-        spin_unlock_irqrestore (&acp->lock, flags);
-}
-
-
-/* Init the chain control structure */
-static void auerchain_init (pauerchain_t acp)
-{
-        /* init the chain data structure */
-        acp->active = NULL;
-	spin_lock_init (&acp->lock);
-        INIT_LIST_HEAD (&acp->waiting_list);
-        INIT_LIST_HEAD (&acp->free_list);
-}
-
-/* setup a chain.
-   It is assumed that there is no concurrency while setting up the chain
-   requirement: auerchain_init()
-*/
-static int auerchain_setup (pauerchain_t acp, unsigned int numElements)
-{
-        pauerchainelement_t acep;
-
-        dbg ("auerchain_setup called with %d elements", numElements);
-
-        /* fill the list of free elements */
-        for (;numElements; numElements--) {
-                acep = (pauerchainelement_t) kmalloc (sizeof (auerchainelement_t), GFP_KERNEL);
-                if (!acep) goto ac_fail;
-		memset (acep, 0, sizeof (auerchainelement_t));
-                INIT_LIST_HEAD (&acep->list);
-                list_add_tail (&acep->list, &acp->free_list);
-        }
-        return 0;
-
-ac_fail:/* free the elements */
-        while (!list_empty (&acp->free_list)) {
-                /* get the next entry */
-                struct list_head *tmp = acp->free_list.next;
-                list_del (tmp);
-                acep = list_entry (tmp, auerchainelement_t, list);
-                kfree (acep);
-        }
-        return -ENOMEM;
-}
-
-
-/* completion handler for synchronous chained URBs */
-static void auerchain_blocking_completion (struct urb *urb)
-{
-	pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
-	pchs->done = 1;
-	wmb();
-	wake_up (&pchs->wqh);
-}
-
-
-/* Starts chained urb and waits for completion or timeout */
-static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
-{
-	DECLARE_WAITQUEUE (wait, current);
-	auerchain_chs_t chs;
-	int status;
-
-	dbg ("auerchain_start_wait_urb called");
-	init_waitqueue_head (&chs.wqh);
-	chs.done = 0;
-
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	add_wait_queue (&chs.wqh, &wait);
-	urb->context = &chs;
-	status = auerchain_submit_urb (acp, urb);
-	if (status) {
-		/* something went wrong */
-		set_current_state (TASK_RUNNING);
-		remove_wait_queue (&chs.wqh, &wait);
-		return status;
-	}
-
-	while (timeout && !chs.done)
-	{
-		timeout = schedule_timeout (timeout);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		rmb();
-	}
-
-	set_current_state (TASK_RUNNING);
-	remove_wait_queue (&chs.wqh, &wait);
-
-	if (!timeout && !chs.done) {
-		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
-			dbg ("auerchain_start_wait_urb: raced timeout");
-			status = urb->status;
-		} else {
-			dbg ("auerchain_start_wait_urb: timeout");
-			auerchain_unlink_urb (acp, urb);  /* remove urb safely */
-			status = -ETIMEDOUT;
-		}
-	} else
-		status = urb->status;
-
-	if (actual_length)
-		*actual_length = urb->actual_length;
-
-  	return status;
-}
-
-
-/* auerchain_control_msg - Builds a control urb, sends it off and waits for completion
-   acp: pointer to the auerchain
-   dev: pointer to the usb device to send the message to
-   pipe: endpoint "pipe" to send the message to
-   request: USB message request value
-   requesttype: USB message request type value
-   value: USB message value
-   index: USB message index value
-   data: pointer to the data to send
-   size: length in bytes of the data to send
-   timeout: time to wait for the message to complete before timing out (if 0 the wait is forever)
-
-   This function sends a simple control message to a specified endpoint
-   and waits for the message to complete, or timeout.
-
-   If successful, it returns the transfered length, othwise a negative error number.
-
-   Don't use this function from within an interrupt context, like a
-   bottom half handler.  If you need a asyncronous message, or need to send
-   a message from within interrupt context, use auerchain_submit_urb()
-*/
-static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
-			          __u16 value, __u16 index, void *data, __u16 size, int timeout)
-{
-	int ret;
-	struct usb_ctrlrequest *dr;
-	struct urb *urb;
-        int length;
-
-        dbg ("auerchain_control_msg");
-        dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
-	if (!dr)
-		return -ENOMEM;
-	urb = usb_alloc_urb (0, GFP_KERNEL);
-	if (!urb) {
-        	kfree (dr);
-		return -ENOMEM;
-        }
-
-	dr->bRequestType = requesttype;
-	dr->bRequest = request;
-	dr->wValue  = cpu_to_le16 (value);
-	dr->wIndex  = cpu_to_le16 (index);
-	dr->wLength = cpu_to_le16 (size);
-
-	FILL_CONTROL_URB (urb, dev, pipe, (unsigned char*)dr, data, size,    /* build urb */
-		          (usb_complete_t)auerchain_blocking_completion,0);
-	ret = auerchain_start_wait_urb (acp, urb, timeout, &length);
-
-	usb_free_urb (urb);
-	kfree (dr);
-
-        if (ret < 0)
-		return ret;
-	else
-		return length;
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Buffer List helper functions                                      */
-
-/* free a single auerbuf */
-static void auerbuf_free (pauerbuf_t bp)
-{
-	if (bp->bufp) {
-		kfree (bp->bufp);
-	}
-	if (bp->dr) {
-		kfree (bp->dr);
-	}
-	if (bp->urbp) {
-		usb_free_urb (bp->urbp);
-	}
-	kfree (bp);
-}
-
-/* free the buffers from an auerbuf list */
-static void auerbuf_free_list (struct list_head *q)
-{
-        struct list_head *tmp;
-	struct list_head *p;
-	pauerbuf_t bp;
-
-	dbg ("auerbuf_free_list");
-	for (p = q->next; p != q;) {
-		bp = list_entry (p, auerbuf_t, buff_list);
-		tmp = p->next;
-		list_del (p);
-		p = tmp;
-		auerbuf_free (bp);
-	}
-}
-
-/* init the members of a list control block */
-static void auerbuf_init (pauerbufctl_t bcp)
-{
-	dbg ("auerbuf_init");
-	spin_lock_init (&bcp->lock);
-        INIT_LIST_HEAD (&bcp->free_buff_list);
-        INIT_LIST_HEAD (&bcp->rec_buff_list);
-}
-
-/* free all buffers from an auerbuf chain */
-static void auerbuf_free_buffers (pauerbufctl_t bcp)
-{
-	unsigned long flags;
-	dbg ("auerbuf_free_buffers");
-
-        spin_lock_irqsave (&bcp->lock, flags);
-
-	auerbuf_free_list (&bcp->free_buff_list);
-	auerbuf_free_list (&bcp->rec_buff_list);
-
-        spin_unlock_irqrestore (&bcp->lock, flags);
-}
-
-/* setup a list of buffers */
-/* requirement: auerbuf_init() */
-static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned int bufsize)
-{
-        pauerbuf_t bep;
-
-        dbg ("auerbuf_setup called with %d elements of %d bytes", numElements, bufsize);
-
-        /* fill the list of free elements */
-        for (;numElements; numElements--) {
-                bep = (pauerbuf_t) kmalloc (sizeof (auerbuf_t), GFP_KERNEL);
-                if (!bep) goto bl_fail;
-	        memset (bep, 0, sizeof (auerbuf_t));
-                bep->list = bcp;
-                INIT_LIST_HEAD (&bep->buff_list);
-                bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL);
-                if (!bep->bufp) goto bl_fail;
-                bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
-                if (!bep->dr) goto bl_fail;
-                bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
-                if (!bep->urbp) goto bl_fail;
-                list_add_tail (&bep->buff_list, &bcp->free_buff_list);
-        }
-        return 0;
-
-bl_fail:/* not enought memory. Free allocated elements */
-        dbg ("auerbuf_setup: no more memory");
-        auerbuf_free_buffers (bcp);
-        return -ENOMEM;
-}
-
-/* insert a used buffer into the free list */
-static void auerbuf_releasebuf( pauerbuf_t bp)
-{
-        unsigned long flags;
-        pauerbufctl_t bcp = bp->list;
-	bp->retries = 0;
-
-        dbg ("auerbuf_releasebuf called");
-        spin_lock_irqsave (&bcp->lock, flags);
-	list_add_tail (&bp->buff_list, &bcp->free_buff_list);
-        spin_unlock_irqrestore (&bcp->lock, flags);
-}
-
-
-/*-------------------------------------------------------------------*/
-/* Completion handlers */
-
-/* Values of urb->status or results of usb_submit_urb():
-0		Initial, OK
--EINPROGRESS	during submission until end
--ENOENT		if urb is unlinked
--ETIMEDOUT	Transfer timed out, NAK
--ENOMEM		Memory Overflow
--ENODEV		Specified USB-device or bus doesn't exist
--ENXIO		URB already queued
--EINVAL		a) Invalid transfer type specified (or not supported)
-		b) Invalid interrupt interval (0n256)
--EAGAIN		a) Specified ISO start frame too early
-		b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again.
--EFBIG		Too much ISO frames requested (currently uhci900)
--EPIPE		Specified pipe-handle/Endpoint is already stalled
--EMSGSIZE	Endpoint message size is zero, do interface/alternate setting
--EPROTO		a) Bitstuff error
-		b) Unknown USB error
--EILSEQ		CRC mismatch
--ENOSR		Buffer error
--EREMOTEIO	Short packet detected
--EXDEV		ISO transfer only partially completed look at individual frame status for details
--EINVAL		ISO madness, if this happens: Log off and go home
--EOVERFLOW	babble
-*/
-
-/* check if a status code allows a retry */
-static int auerswald_status_retry (int status)
-{
-	switch (status) {
-	case 0:
-	case -ETIMEDOUT:
-	case -EOVERFLOW:
-	case -EAGAIN:
-	case -EPIPE:
-	case -EPROTO:
-	case -EILSEQ:
-	case -ENOSR:
-	case -EREMOTEIO:
-		return 1; /* do a retry */
-	}
-	return 0;	/* no retry possible */
-}
-
-/* Completion of asynchronous write block */
-static void auerchar_ctrlwrite_complete (struct urb * urb)
-{
-	pauerbuf_t bp = (pauerbuf_t) urb->context;
-	pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
-	dbg ("auerchar_ctrlwrite_complete called");
-
-	/* reuse the buffer */
-	auerbuf_releasebuf (bp);
-	/* Wake up all processes waiting for a buffer */
-	wake_up (&cp->bufferwait);
-}
-
-/* Completion handler for dummy retry packet */
-static void auerswald_ctrlread_wretcomplete (struct urb * urb)
-{
-        pauerbuf_t bp = (pauerbuf_t) urb->context;
-        pauerswald_t cp;
-	int ret;
-        dbg ("auerswald_ctrlread_wretcomplete called");
-        dbg ("complete with status: %d", urb->status);
-	cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
-
-	/* check if it is possible to advance */
-	if (!auerswald_status_retry (urb->status) || !cp->usbdev) {
-		/* reuse the buffer */
-		err ("control dummy: transmission error %d, can not retry", urb->status);
-		auerbuf_releasebuf (bp);
-		/* Wake up all processes waiting for a buffer */
-		wake_up (&cp->bufferwait);
-		return;
-	}
-
-	/* fill the control message */
-	bp->dr->bRequestType = AUT_RREQ;
-	bp->dr->bRequest     = AUV_RBLOCK;
-	bp->dr->wLength      = bp->dr->wValue;	/* temporary stored */
-	bp->dr->wValue       = cpu_to_le16 (1);	/* Retry Flag */
-	/* bp->dr->index    = channel id;          remains */
-	FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),
-                          (unsigned char*)bp->dr, bp->bufp, le16_to_cpu (bp->dr->wLength),
-		          (usb_complete_t)auerswald_ctrlread_complete,bp);
-
-	/* submit the control msg as next paket */
-	ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);
-        if (ret) {
-        	dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
-        	bp->urbp->status = ret;
-        	auerswald_ctrlread_complete (bp->urbp);
-    	}
-}
-
-/* completion handler for receiving of control messages */
-static void auerswald_ctrlread_complete (struct urb * urb)
-{
-        unsigned int  serviceid;
-        pauerswald_t  cp;
-        pauerscon_t   scp;
-        pauerbuf_t    bp  = (pauerbuf_t) urb->context;
-	int ret;
-        dbg ("auerswald_ctrlread_complete called");
-
-	cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
-
-	/* check if there is valid data in this urb */
-        if (urb->status) {
-		dbg ("complete with non-zero status: %d", urb->status);
-		/* should we do a retry? */
-		if (!auerswald_status_retry (urb->status)
-		 || !cp->usbdev
-		 || (cp->version < AUV_RETRY)
-                 || (bp->retries >= AU_RETRIES)) {
-			/* reuse the buffer */
-			err ("control read: transmission error %d, can not retry", urb->status);
-			auerbuf_releasebuf (bp);
-			/* Wake up all processes waiting for a buffer */
-			wake_up (&cp->bufferwait);
-			return;
-		}
-		bp->retries++;
-		dbg ("Retry count = %d", bp->retries);
-		/* send a long dummy control-write-message to allow device firmware to react */
-		bp->dr->bRequestType = AUT_WREQ;
-		bp->dr->bRequest     = AUV_DUMMY;
-		bp->dr->wValue       = bp->dr->wLength; /* temporary storage */
-		// bp->dr->wIndex    channel ID remains
-		bp->dr->wLength      = cpu_to_le16 (32); /* >= 8 bytes */
-		FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),
-  			(unsigned char*)bp->dr, bp->bufp, 32,
-	   		(usb_complete_t)auerswald_ctrlread_wretcomplete,bp);
-
-		/* submit the control msg as next paket */
-       		ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);
-       		if (ret) {
-               		dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
-               		bp->urbp->status = ret;
-               		auerswald_ctrlread_wretcomplete (bp->urbp);
-		}
-                return;
-        }
-
-        /* get the actual bytecount (incl. headerbyte) */
-        bp->len = urb->actual_length;
-        serviceid = bp->bufp[0] & AUH_TYPEMASK;
-        dbg ("Paket with serviceid %d and %d bytes received", serviceid, bp->len);
-
-        /* dispatch the paket */
-        scp = cp->services[serviceid];
-        if (scp) {
-                /* look, Ma, a listener! */
-                scp->dispatch (scp, bp);
-        }
-
-        /* release the paket */
-        auerbuf_releasebuf (bp);
-	/* Wake up all processes waiting for a buffer */
-	wake_up (&cp->bufferwait);
-}
-
-/*-------------------------------------------------------------------*/
-/* Handling of Interrupt Endpoint                                    */
-/* This interrupt Endpoint is used to inform the host about waiting
-   messages from the USB device.
-*/
-/* int completion handler. */
-static void auerswald_int_complete (struct urb * urb)
-{
-        unsigned long flags;
-        unsigned  int channelid;
-        unsigned  int bytecount;
-        int ret;
-        pauerbuf_t   bp = NULL;
-        pauerswald_t cp = (pauerswald_t) urb->context;
-
-        dbg ("auerswald_int_complete called");
-
-        /* do not respond to an error condition */
-        if (urb->status != 0) {
-                dbg ("nonzero URB status = %d", urb->status);
-                return;
-        }
-
-        /* check if all needed data was received */
-	if (urb->actual_length < AU_IRQMINSIZE) {
-                dbg ("invalid data length received: %d bytes", urb->actual_length);
-                return;
-        }
-
-        /* check the command code */
-        if (cp->intbufp[0] != AU_IRQCMDID) {
-                dbg ("invalid command received: %d", cp->intbufp[0]);
-                return;
-        }
-
-        /* check the command type */
-        if (cp->intbufp[1] != AU_BLOCKRDY) {
-                dbg ("invalid command type received: %d", cp->intbufp[1]);
-                return;
-        }
-
-        /* now extract the information */
-        channelid = cp->intbufp[2];
-        bytecount = le16_to_cpup (&cp->intbufp[3]);
-
-        /* check the channel id */
-        if (channelid >= AUH_TYPESIZE) {
-                dbg ("invalid channel id received: %d", channelid);
-                return;
-        }
-
-        /* check the byte count */
-        if (bytecount > (cp->maxControlLength+AUH_SIZE)) {
-                dbg ("invalid byte count received: %d", bytecount);
-                return;
-        }
-        dbg ("Service Channel = %d", channelid);
-        dbg ("Byte Count = %d", bytecount);
-
-        /* get a buffer for the next data paket */
-        spin_lock_irqsave (&cp->bufctl.lock, flags);
-        if (!list_empty (&cp->bufctl.free_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = cp->bufctl.free_buff_list.next;
-                list_del (tmp);
-                bp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&cp->bufctl.lock, flags);
-
-        /* if no buffer available: skip it */
-        if (!bp) {
-                dbg ("auerswald_int_complete: no data buffer available");
-                /* can we do something more?
-		   This is a big problem: if this int packet is ignored, the
-		   device will wait forever and not signal any more data.
-		   The only real solution is: having enought buffers!
-		   Or perhaps temporary disabling the int endpoint?
-		*/
-		return;
-        }
-
-	/* fill the control message */
-        bp->dr->bRequestType = AUT_RREQ;
-	bp->dr->bRequest     = AUV_RBLOCK;
-	bp->dr->wValue       = cpu_to_le16 (0);
-	bp->dr->wIndex       = cpu_to_le16 (channelid | AUH_DIRECT | AUH_UNSPLIT);
-	bp->dr->wLength      = cpu_to_le16 (bytecount);
-	FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),
-                          (unsigned char*)bp->dr, bp->bufp, bytecount,
-		          (usb_complete_t)auerswald_ctrlread_complete,bp);
-
-        /* submit the control msg */
-        ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
-        if (ret) {
-                dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
-                bp->urbp->status = ret;
-                auerswald_ctrlread_complete( bp->urbp);
-		/* here applies the same problem as above: device locking! */
-        }
-}
-
-/* int memory deallocation
-   NOTE: no mutex please!
-*/
-static void auerswald_int_free (pauerswald_t cp)
-{
-        if (cp->inturbp) {
-                usb_free_urb (cp->inturbp);
-                cp->inturbp = NULL;
-        }
-        if (cp->intbufp) {
-                kfree (cp->intbufp);
-                cp->intbufp = NULL;
-        }
-}
-
-/* This function is called to activate the interrupt
-   endpoint. This function returns 0 if successfull or an error code.
-   NOTE: no mutex please!
-*/
-static int auerswald_int_open (pauerswald_t cp)
-{
-        int ret;
-	struct usb_endpoint_descriptor *ep;
-	int irqsize;
-	dbg ("auerswald_int_open");
-
-	ep = usb_epnum_to_ep_desc (cp->usbdev, USB_DIR_IN | AU_IRQENDP);
-	if (!ep) {
-		ret = -EFAULT;
-  		goto intoend;
-    	}
-	irqsize = ep->wMaxPacketSize;
-	cp->irqsize = irqsize;
-
-	/* allocate the urb and data buffer */
-        if (!cp->inturbp) {
-                cp->inturbp = usb_alloc_urb (0, GFP_KERNEL);
-                if (!cp->inturbp) {
-                        ret = -ENOMEM;
-                        goto intoend;
-                }
-        }
-        if (!cp->intbufp) {
-                cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL);
-                if (!cp->intbufp) {
-                        ret = -ENOMEM;
-                        goto intoend;
-                }
-        }
-        /* setup urb */
-        FILL_INT_URB (cp->inturbp, cp->usbdev, usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp, irqsize, auerswald_int_complete, cp, ep->bInterval);
-        /* start the urb */
-	cp->inturbp->status = 0;	/* needed! */
-	ret = usb_submit_urb (cp->inturbp, GFP_KERNEL);
-
-intoend:
-        if (ret < 0) {
-                /* activation of interrupt endpoint has failed. Now clean up. */
-                dbg ("auerswald_int_open: activation of int endpoint failed");
-
-                /* deallocate memory */
-                auerswald_int_free (cp);
-        }
-        return ret;
-}
-
-/* This function is called to deactivate the interrupt
-   endpoint. This function returns 0 if successfull or an error code.
-   NOTE: no mutex please!
-*/
-static int auerswald_int_release (pauerswald_t cp)
-{
-        int ret = 0;
-        dbg ("auerswald_int_release");
-
-        /* stop the int endpoint */
-        if (cp->inturbp) {
-                ret = usb_unlink_urb (cp->inturbp);
-                if (ret)
-	                dbg ("nonzero int unlink result received: %d", ret);
-        }
-
-        /* deallocate memory */
-        auerswald_int_free (cp);
-
-        return ret;
-}
-
-/* --------------------------------------------------------------------- */
-/* Helper functions                                                      */
-
-/* wake up waiting readers */
-static void auerchar_disconnect (pauerscon_t scp)
-{
-        pauerchar_t ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));
-	dbg ("auerchar_disconnect called");
-	ccp->removed = 1;
-	wake_up (&ccp->readwait);
-}
-
-
-/* dispatch a read paket to a waiting character device */
-static void auerchar_ctrlread_dispatch (pauerscon_t scp, pauerbuf_t bp)
-{
-	unsigned long flags;
-        pauerchar_t ccp;
-        pauerbuf_t newbp = NULL;
-        char * charp;
-        dbg ("auerchar_ctrlread_dispatch called");
-        ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));
-
-        /* get a read buffer from character device context */
-        spin_lock_irqsave (&ccp->bufctl.lock, flags);
-        if (!list_empty (&ccp->bufctl.free_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = ccp->bufctl.free_buff_list.next;
-                list_del (tmp);
-                newbp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
-
-        if (!newbp) {
-                dbg ("No read buffer available, discard paket!");
-                return;     /* no buffer, no dispatch */
-        }
-
-        /* copy information to new buffer element
-           (all buffers have the same length) */
-        charp = newbp->bufp;
-        newbp->bufp = bp->bufp;
-        bp->bufp = charp;
-        newbp->len = bp->len;
-
-        /* insert new buffer in read list */
-        spin_lock_irqsave (&ccp->bufctl.lock, flags);
-	list_add_tail (&newbp->buff_list, &ccp->bufctl.rec_buff_list);
-        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
-        dbg ("read buffer appended to rec_list");
-
-        /* wake up pending synchronous reads */
-	wake_up (&ccp->readwait);
-}
-
-
-/* Delete an auerswald driver context */
-static void auerswald_delete( pauerswald_t cp)
-{
-	dbg( "auerswald_delete");
-	if (cp == NULL) return;
-
-	/* Wake up all processes waiting for a buffer */
-	wake_up (&cp->bufferwait);
-
-	/* Cleaning up */
-	auerswald_int_release (cp);
-	auerchain_free (&cp->controlchain);
-	auerbuf_free_buffers (&cp->bufctl);
-
-	/* release the memory */
-	kfree( cp);
-}
-
-
-/* Delete an auerswald character context */
-static void auerchar_delete( pauerchar_t ccp)
-{
-	dbg ("auerchar_delete");
-	if (ccp == NULL) return;
-
-        /* wake up pending synchronous reads */
-	ccp->removed = 1;
-	wake_up (&ccp->readwait);
-
-	/* remove the read buffer */
-	if (ccp->readbuf) {
-		auerbuf_releasebuf (ccp->readbuf);
-		ccp->readbuf = NULL;
-	}
-
-	/* remove the character buffers */
-	auerbuf_free_buffers (&ccp->bufctl);
-
-	/* release the memory */
-	kfree( ccp);
-}
-
-
-/* add a new service to the device
-   scp->id must be set!
-   return: 0 if OK, else error code
-*/
-static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp)
-{
-	int ret;
-
-	/* is the device available? */
-	if (!cp->usbdev) {
-		dbg ("usbdev == NULL");
-		return -EIO;	/*no: can not add a service, sorry*/
-	}
-
-	/* is the service available? */
-	if (cp->services[scp->id]) {
-		dbg ("service is busy");
-                return -EBUSY;
-	}
-
-	/* device is available, service is free */
-	cp->services[scp->id] = scp;
-
-	/* register service in device */
-	ret = auerchain_control_msg(
-		&cp->controlchain,                      /* pointer to control chain */
-		cp->usbdev,                             /* pointer to device */
-		usb_sndctrlpipe (cp->usbdev, 0),        /* pipe to control endpoint */
-		AUV_CHANNELCTL,                         /* USB message request value */
-		AUT_WREQ,                               /* USB message request type value */
-		0x01,              /* open                 USB message value */
-		scp->id,            		        /* USB message index value */
-		NULL,                                   /* pointer to the data to send */
-		0,                                      /* length in bytes of the data to send */
-		HZ * 2);                                /* time to wait for the message to complete before timing out */
-	if (ret < 0) {
-		dbg ("auerswald_addservice: auerchain_control_msg returned error code %d", ret);
-		/* undo above actions */
-		cp->services[scp->id] = NULL;
-		return ret;
-	}
-
-	dbg ("auerswald_addservice: channel open OK");
-	return 0;
-}
-
-
-/* remove a service from the the device
-   scp->id must be set! */
-static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp)
-{
-	dbg ("auerswald_removeservice called");
-
-	/* check if we have a service allocated */
-	if (scp->id == AUH_UNASSIGNED) return;
-
-	/* If there is a device: close the channel */
-	if (cp->usbdev) {
-		/* Close the service channel inside the device */
-		int ret = auerchain_control_msg(
-		&cp->controlchain,            		/* pointer to control chain */
-		cp->usbdev,         		        /* pointer to device */
-		usb_sndctrlpipe (cp->usbdev, 0),	/* pipe to control endpoint */
-		AUV_CHANNELCTL,                         /* USB message request value */
-		AUT_WREQ,                               /* USB message request type value */
-		0x00,              // close             /* USB message value */
-		scp->id,            		        /* USB message index value */
-		NULL,                                   /* pointer to the data to send */
-		0,                                      /* length in bytes of the data to send */
-		HZ * 2);                                /* time to wait for the message to complete before timing out */
-		if (ret < 0) {
-			dbg ("auerswald_removeservice: auerchain_control_msg returned error code %d", ret);
-		}
-		else {
-			dbg ("auerswald_removeservice: channel close OK");
-		}
-	}
-
-	/* remove the service from the device */
-	cp->services[scp->id] = NULL;
-	scp->id = AUH_UNASSIGNED;
-}
-
-
-/* --------------------------------------------------------------------- */
-/* Char device functions                                                 */
-
-/* Open a new character device */
-static int auerchar_open (struct inode *inode, struct file *file)
-{
-	int dtindex = minor(inode->i_rdev) - AUER_MINOR_BASE;
-	pauerswald_t cp = NULL;
-	pauerchar_t ccp = NULL;
-        int ret;
-
-        /* minor number in range? */
-	if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) {
-		return -ENODEV;
-        }
-	/* usb device available? */
-	if (down_interruptible (&dev_table_mutex)) {
-		return -ERESTARTSYS;
-	}
-	cp = dev_table[dtindex];
-	if (cp == NULL) {
-		up (&dev_table_mutex);
-		return -ENODEV;
-	}
-	if (down_interruptible (&cp->mutex)) {
-		up (&dev_table_mutex);
-		return -ERESTARTSYS;
-	}
-	up (&dev_table_mutex);
-
-	/* we have access to the device. Now lets allocate memory */
-	ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
-	if (ccp == NULL) {
-		err ("out of memory");
-		ret = -ENOMEM;
-		goto ofail;
-	}
-
-	/* Initialize device descriptor */
-	memset( ccp, 0, sizeof(auerchar_t));
-	init_MUTEX( &ccp->mutex);
-	init_MUTEX( &ccp->readmutex);
-        auerbuf_init (&ccp->bufctl);
-        ccp->scontext.id = AUH_UNASSIGNED;
-        ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
-	ccp->scontext.disconnect = auerchar_disconnect;
-	init_waitqueue_head (&ccp->readwait);
-
-	ret = auerbuf_setup (&ccp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE);
-       	if (ret) {
-		goto ofail;
-	}
-
-	cp->open_count++;
-	ccp->auerdev = cp;
-	dbg("open %s as /dev/usb/%s", cp->dev_desc, cp->name);
-	up (&cp->mutex);
-
-	/* file IO stuff */
-	file->f_pos = 0;
-	file->private_data = ccp;
-	return 0;
-
-	/* Error exit */
-ofail:	up (&cp->mutex);
-	auerchar_delete (ccp);
-	return ret;
-}
-
-
-/* IOCTL functions */
-static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	pauerchar_t ccp = (pauerchar_t) file->private_data;
-	int ret = 0;
-        audevinfo_t devinfo;
-        pauerswald_t cp = NULL;
-	unsigned int u;
-        dbg ("ioctl");
-
-	/* get the mutexes */
-	if (down_interruptible (&ccp->mutex)) {
-		return -ERESTARTSYS;
-	}
-	cp = ccp->auerdev;
-	if (!cp) {
-		up (&ccp->mutex);
-                return -ENODEV;
-	}
-	if (down_interruptible (&cp->mutex)) {
-		up(&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-
-	/* Check for removal */
-	if (!cp->usbdev) {
-		up(&cp->mutex);
-		up(&ccp->mutex);
-                return -ENODEV;
-	}
-
-	switch (cmd) {
-
-	/* return != 0 if Transmitt channel ready to send */
-	case IOCTL_AU_TXREADY:
-		dbg ("IOCTL_AU_TXREADY");
-		u   = ccp->auerdev
-		   && (ccp->scontext.id != AUH_UNASSIGNED)
-		   && !list_empty (&cp->bufctl.free_buff_list);
-	        ret = put_user (u, (unsigned int *) arg);
-		break;
-
-	/* return != 0 if connected to a service channel */
-	case IOCTL_AU_CONNECT:
-		dbg ("IOCTL_AU_CONNECT");
-		u = (ccp->scontext.id != AUH_UNASSIGNED);
-	        ret = put_user (u, (unsigned int *) arg);
-		break;
-
-	/* return != 0 if Receive Data available */
-	case IOCTL_AU_RXAVAIL:
-		dbg ("IOCTL_AU_RXAVAIL");
-		if (ccp->scontext.id == AUH_UNASSIGNED) {
-                        ret = -EIO;
-                        break;
-                }
-		u = 0;	/* no data */
-		if (ccp->readbuf) {
-			int restlen = ccp->readbuf->len - ccp->readoffset;
-			if (restlen > 0) u = 1;
-		}
-		if (!u) {
-        		if (!list_empty (&ccp->bufctl.rec_buff_list)) {
-				u = 1;
-			}
-		}
-	        ret = put_user (u, (unsigned int *) arg);
-		break;
-
-	/* return the max. buffer length for the device */
-	case IOCTL_AU_BUFLEN:
-		dbg ("IOCTL_AU_BUFLEN");
-		u = cp->maxControlLength;
-	        ret = put_user (u, (unsigned int *) arg);
-		break;
-
-	/* requesting a service channel */
-        case IOCTL_AU_SERVREQ:
-		dbg ("IOCTL_AU_SERVREQ");
-                /* requesting a service means: release the previous one first */
-		auerswald_removeservice (cp, &ccp->scontext);
-		/* get the channel number */
-		ret = get_user (u, (unsigned int *) arg);
-		if (ret) {
-			break;
-		}
-		if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) {
-                        ret = -EIO;
-                        break;
-                }
-                dbg ("auerchar service request parameters are ok");
-		ccp->scontext.id = u;
-
-		/* request the service now */
-		ret = auerswald_addservice (cp, &ccp->scontext);
-		if (ret) {
-			/* no: revert service entry */
-                	ccp->scontext.id = AUH_UNASSIGNED;
-		}
-		break;
-
-	/* get a string descriptor for the device */
-	case IOCTL_AU_DEVINFO:
-		dbg ("IOCTL_AU_DEVINFO");
-                if (copy_from_user (&devinfo, (void *) arg, sizeof (audevinfo_t))) {
-        		ret = -EFAULT;
-	        	break;
-                }
-		u = strlen(cp->dev_desc)+1;
-		if (u > devinfo.bsize) {
-			u = devinfo.bsize;
-		}
-		ret = copy_to_user(devinfo.buf, cp->dev_desc, u);
-		break;
-
-	/* get the max. string descriptor length */
-        case IOCTL_AU_SLEN:
-		dbg ("IOCTL_AU_SLEN");
-		u = AUSI_DLEN;
-	        ret = put_user (u, (unsigned int *) arg);
-		break;
-
-	default:
-		dbg ("IOCTL_AU_UNKNOWN");
-		ret = -ENOIOCTLCMD;
-		break;
-        }
-	/* release the mutexes */
-	up(&cp->mutex);
-	up(&ccp->mutex);
-	return ret;
-}
-
-/* Read data from the device */
-static ssize_t auerchar_read (struct file *file, char *buf, size_t count, loff_t * ppos)
-{
-        unsigned long flags;
-	pauerchar_t ccp = (pauerchar_t) file->private_data;
-        pauerbuf_t   bp = NULL;
-	wait_queue_t wait;
-
-        dbg ("auerchar_read");
-
-	/* Error checking */
-	if (!ccp)
-		return -EIO;
-	if (*ppos)
- 		return -ESPIPE;
-        if (count == 0)
-		return 0;
-
-	/* get the mutex */
-	if (down_interruptible (&ccp->mutex))
-		return -ERESTARTSYS;
-
-	/* Can we expect to read something? */
-	if (ccp->scontext.id == AUH_UNASSIGNED) {
-		up (&ccp->mutex);
-                return -EIO;
-	}
-
-	/* only one reader per device allowed */
-	if (down_interruptible (&ccp->readmutex)) {
-		up (&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-
-	/* read data from readbuf, if available */
-doreadbuf:
-	bp = ccp->readbuf;
-	if (bp) {
-		/* read the maximum bytes */
-		int restlen = bp->len - ccp->readoffset;
-		if (restlen < 0)
-			restlen = 0;
-		if (count > restlen)
-			count = restlen;
-		if (count) {
-			if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {
-				dbg ("auerswald_read: copy_to_user failed");
-				up (&ccp->readmutex);
-				up (&ccp->mutex);
-				return -EFAULT;
-			}
-		}
-		/* advance the read offset */
-		ccp->readoffset += count;
-		restlen -= count;
-		// reuse the read buffer
-		if (restlen <= 0) {
-			auerbuf_releasebuf (bp);
-			ccp->readbuf = NULL;
-		}
-		/* return with number of bytes read */
-		if (count) {
-			up (&ccp->readmutex);
-			up (&ccp->mutex);
-			return count;
-		}
-	}
-
-	/* a read buffer is not available. Try to get the next data block. */
-doreadlist:
-	/* Preparing for sleep */
-	init_waitqueue_entry (&wait, current);
-	set_current_state (TASK_INTERRUPTIBLE);
-	add_wait_queue (&ccp->readwait, &wait);
-
-	bp = NULL;
-	spin_lock_irqsave (&ccp->bufctl.lock, flags);
-        if (!list_empty (&ccp->bufctl.rec_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = ccp->bufctl.rec_buff_list.next;
-                list_del (tmp);
-                bp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
-
-	/* have we got data? */
-	if (bp) {
-		ccp->readbuf = bp;
-		ccp->readoffset = AUH_SIZE; /* for headerbyte */
-		set_current_state (TASK_RUNNING);
-		remove_wait_queue (&ccp->readwait, &wait);
-		goto doreadbuf;		  /* now we can read! */
-	}
-
-	/* no data available. Should we wait? */
-	if (file->f_flags & O_NONBLOCK) {
-                dbg ("No read buffer available, returning -EAGAIN");
-		set_current_state (TASK_RUNNING);
-		remove_wait_queue (&ccp->readwait, &wait);
-		up (&ccp->readmutex);
-		up (&ccp->mutex);
-		return -EAGAIN;  /* nonblocking, no data available */
-        }
-
-	/* yes, we should wait! */
-	up (&ccp->mutex); /* allow other operations while we wait */
-	schedule();
-	remove_wait_queue (&ccp->readwait, &wait);
-	if (signal_pending (current)) {
-		/* waked up by a signal */
-		up (&ccp->readmutex);
-		return -ERESTARTSYS;
-	}
-
-	/* Anything left to read? */
-	if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
-		up (&ccp->readmutex);
-		return -EIO;
-	}
-
-	if (down_interruptible (&ccp->mutex)) {
-		up (&ccp->readmutex);
-		return -ERESTARTSYS;
-	}
-
-	/* try to read the incomming data again */
-	goto doreadlist;
-}
-
-
-/* Write a data block into the right service channel of the device */
-static ssize_t auerchar_write (struct file *file, const char *buf, size_t len, loff_t *ppos)
-{
-	pauerchar_t ccp = (pauerchar_t) file->private_data;
-        pauerswald_t cp = NULL;
-        pauerbuf_t bp;
-        unsigned long flags;
-	int ret;
-	wait_queue_t wait;
-
-        dbg ("auerchar_write %d bytes", len);
-
-	/* Error checking */
-	if (!ccp)
-		return -EIO;
-        if (*ppos)
-		return -ESPIPE;
-        if (len == 0)
-                return 0;
-
-write_again:
-	/* get the mutex */
-	if (down_interruptible (&ccp->mutex))
-		return -ERESTARTSYS;
-
-	/* Can we expect to write something? */
-	if (ccp->scontext.id == AUH_UNASSIGNED) {
-		up (&ccp->mutex);
-                return -EIO;
-	}
-
-	cp = ccp->auerdev;
-	if (!cp) {
-		up (&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-	if (down_interruptible (&cp->mutex)) {
-		up (&ccp->mutex);
-		return -ERESTARTSYS;
-	}
-	if (!cp->usbdev) {
-		up (&cp->mutex);
-		up (&ccp->mutex);
-		return -EIO;
-	}
-	/* Prepare for sleep */
-	init_waitqueue_entry (&wait, current);
-	set_current_state (TASK_INTERRUPTIBLE);
-	add_wait_queue (&cp->bufferwait, &wait);
-
-	/* Try to get a buffer from the device pool.
-	   We can't use a buffer from ccp->bufctl because the write
-	   command will last beond a release() */
-	bp = NULL;
-	spin_lock_irqsave (&cp->bufctl.lock, flags);
-        if (!list_empty (&cp->bufctl.free_buff_list)) {
-                /* yes: get the entry */
-                struct list_head *tmp = cp->bufctl.free_buff_list.next;
-                list_del (tmp);
-                bp = list_entry (tmp, auerbuf_t, buff_list);
-        }
-        spin_unlock_irqrestore (&cp->bufctl.lock, flags);
-
-	/* are there any buffers left? */
-	if (!bp) {
-		up (&cp->mutex);
-		up (&ccp->mutex);
-
-		/* NONBLOCK: don't wait */
-		if (file->f_flags & O_NONBLOCK) {
-			set_current_state (TASK_RUNNING);
-			remove_wait_queue (&cp->bufferwait, &wait);
-			return -EAGAIN;
-		}
-
-		/* BLOCKING: wait */
-		schedule();
-		remove_wait_queue (&cp->bufferwait, &wait);
-		if (signal_pending (current)) {
-			/* waked up by a signal */
-			return -ERESTARTSYS;
-		}
-		goto write_again;
-	} else {
-		set_current_state (TASK_RUNNING);
-		remove_wait_queue (&cp->bufferwait, &wait);
-	}
-
-	/* protect against too big write requests */
-	if (len > cp->maxControlLength) len = cp->maxControlLength;
-
-	/* Fill the buffer */
-	if (copy_from_user ( bp->bufp+AUH_SIZE, buf, len)) {
-		dbg ("copy_from_user failed");
-		auerbuf_releasebuf (bp);
-		/* Wake up all processes waiting for a buffer */
-		wake_up (&cp->bufferwait);
-		up (&cp->mutex);
-		up (&ccp->mutex);
-		return -EIO;
-	}
-
-	/* set the header byte */
-        *(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT;
-
-	/* Set the transfer Parameters */
-	bp->len = len+AUH_SIZE;
-        bp->dr->bRequestType = AUT_WREQ;
-	bp->dr->bRequest     = AUV_WBLOCK;
-	bp->dr->wValue       = cpu_to_le16 (0);
-	bp->dr->wIndex       = cpu_to_le16 (ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT);
-	bp->dr->wLength      = cpu_to_le16 (len+AUH_SIZE);
-	FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),
-                   (unsigned char*)bp->dr, bp->bufp, len+AUH_SIZE,
-		    auerchar_ctrlwrite_complete, bp);
-	/* up we go */
-	ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
-	up (&cp->mutex);
-	if (ret) {
-		dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
-		auerbuf_releasebuf (bp);
-		/* Wake up all processes waiting for a buffer */
-		wake_up (&cp->bufferwait);
-		up (&ccp->mutex);
-		return -EIO;
-	}
-	else {
-		dbg ("auerchar_write: Write OK");
-		up (&ccp->mutex);
-		return len;
-	}
-}
-
-
-/* Close a character device */
-static int auerchar_release (struct inode *inode, struct file *file)
-{
-	pauerchar_t ccp = (pauerchar_t) file->private_data;
-	pauerswald_t cp;
-	dbg("release");
-
-	/* get the mutexes */
-	if (down_interruptible (&ccp->mutex)) {
-		return -ERESTARTSYS;
-	}
-	cp = ccp->auerdev;
-	if (cp) {
-		if (down_interruptible (&cp->mutex)) {
-			up (&ccp->mutex);
-			return -ERESTARTSYS;
-		}
-		/* remove an open service */
-		auerswald_removeservice (cp, &ccp->scontext);
-		/* detach from device */
-		if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
-			/* usb device waits for removal */
-			up (&cp->mutex);
-			auerswald_delete (cp);
-		} else {
-			up (&cp->mutex);
-		}
-		cp = NULL;
-		ccp->auerdev = NULL;
-	}
-	up (&ccp->mutex);
-	auerchar_delete (ccp);
-
-	return 0;
-}
-
-
-/*----------------------------------------------------------------------*/
-/* File operation structure                                             */
-static struct file_operations auerswald_fops =
-{
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	read:		auerchar_read,
-	write:          auerchar_write,
-	ioctl:		auerchar_ioctl,
-	open:		auerchar_open,
-	release:	auerchar_release,
-};
-
-
-/* --------------------------------------------------------------------- */
-/* Special USB driver functions                                          */
-
-/* Probe if this driver wants to serve an USB device
-
-   This entry point is called whenever a new device is attached to the bus.
-   Then the device driver has to create a new instance of its internal data
-   structures for the new device.
-
-   The  dev argument specifies the device context, which contains pointers
-   to all USB descriptors. The  interface argument specifies the interface
-   number. If a USB driver wants to bind itself to a particular device and
-   interface it has to return a pointer. This pointer normally references
-   the device driver's context structure.
-
-   Probing normally is done by checking the vendor and product identifications
-   or the class and subclass definitions. If they match the interface number
-   is compared with the ones supported by the driver. When probing is done
-   class based it might be necessary to parse some more USB descriptors because
-   the device properties can differ in a wide range.
-*/
-static void *auerswald_probe (struct usb_device *usbdev, unsigned int ifnum,
-			      const struct usb_device_id *id)
-{
-	pauerswald_t cp = NULL;
-	DECLARE_WAIT_QUEUE_HEAD (wqh);
-	unsigned int dtindex;
-	unsigned int u = 0;
-	char *pbuf;
-	int ret;
-
-	dbg ("probe: vendor id 0x%x, device id 0x%x ifnum:%d",
-	     usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
-
-	/* See if the device offered us matches that we can accept */
-	if (usbdev->descriptor.idVendor != ID_AUERSWALD) return NULL;
-
-        /* we use only the first -and only- interface */
-        if (ifnum != 0) return NULL;
-
-	/* prevent module unloading while sleeping */
-	MOD_INC_USE_COUNT;
-
-	/* allocate memory for our device and intialize it */
-	cp = kmalloc (sizeof(auerswald_t), GFP_KERNEL);
-	if (cp == NULL) {
-		err ("out of memory");
-		goto pfail;
-	}
-
-	/* Initialize device descriptor */
-	memset (cp, 0, sizeof(auerswald_t));
-	init_MUTEX (&cp->mutex);
-	cp->usbdev = usbdev;
-	auerchain_init (&cp->controlchain);
-        auerbuf_init (&cp->bufctl);
-	init_waitqueue_head (&cp->bufferwait);
-
-	/* find a free slot in the device table */
-	down (&dev_table_mutex);
-	for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
-		if (dev_table[dtindex] == NULL)
-			break;
-	}
-	if ( dtindex >= AUER_MAX_DEVICES) {
-		err ("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
-		up (&dev_table_mutex);
-		goto pfail;
-	}
-
-	/* Give the device a name */
-	sprintf (cp->name, AU_PREFIX "%d", dtindex);
-
-	/* Store the index */
-	cp->dtindex = dtindex;
-	dev_table[dtindex] = cp;
-	up (&dev_table_mutex);
-
-	/* initialize the devfs node for this device and register it */
-	cp->devfs = devfs_register (usb_devfs_handle, cp->name,
-				    DEVFS_FL_DEFAULT, USB_MAJOR,
-				    AUER_MINOR_BASE + dtindex,
-				    S_IFCHR | S_IRUGO | S_IWUGO,
-				    &auerswald_fops, NULL);
-
-	/* Get the usb version of the device */
-	cp->version = cp->usbdev->descriptor.bcdDevice;
-	dbg ("Version is %X", cp->version);
-
-	/* allow some time to settle the device */
-	sleep_on_timeout (&wqh, HZ / 3 );
-
-	/* Try to get a suitable textual description of the device */
-	/* Device name:*/
-	ret = usb_string( cp->usbdev, AUSI_DEVICE, cp->dev_desc, AUSI_DLEN-1);
-	if (ret >= 0) {
-		u += ret;
-		/* Append Serial Number */
-		memcpy(&cp->dev_desc[u], ",Ser# ", 6);
-		u += 6;
-		ret = usb_string( cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u], AUSI_DLEN-u-1);
-		if (ret >= 0) {
-			u += ret;
-			/* Append subscriber number */
-			memcpy(&cp->dev_desc[u], ", ", 2);
-			u += 2;
-			ret = usb_string( cp->usbdev, AUSI_MSN, &cp->dev_desc[u], AUSI_DLEN-u-1);
-			if (ret >= 0) {
-				u += ret;
-			}
-		}
-	}
-	cp->dev_desc[u] = '\0';
-	info("device is a %s", cp->dev_desc);
-
-        /* get the maximum allowed control transfer length */
-        pbuf = (char *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
-        if (!pbuf) {
-		err( "out of memory");
-		goto pfail;
-	}
-        ret = usb_control_msg(cp->usbdev,           /* pointer to device */
-                usb_rcvctrlpipe( cp->usbdev, 0 ),   /* pipe to control endpoint */
-                AUV_GETINFO,                        /* USB message request value */
-                AUT_RREQ,                           /* USB message request type value */
-                0,                                  /* USB message value */
-                AUDI_MBCTRANS,                      /* USB message index value */
-                pbuf,                               /* pointer to the receive buffer */
-                2,                                  /* length of the buffer */
-                HZ * 2);                            /* time to wait for the message to complete before timing out */
-        if (ret == 2) {
-	        cp->maxControlLength = le16_to_cpup(pbuf);
-                kfree(pbuf);
-                dbg("setup: max. allowed control transfersize is %d bytes", cp->maxControlLength);
-        } else {
-                kfree(pbuf);
-                err("setup: getting max. allowed control transfer length failed with error %d", ret);
-		goto pfail;
-        }
-
-	/* allocate a chain for the control messages */
-        if (auerchain_setup (&cp->controlchain, AUCH_ELEMENTS)) {
-		err ("out of memory");
-		goto pfail;
-	}
-
-        /* allocate buffers for control messages */
-	if (auerbuf_setup (&cp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE)) {
-		err ("out of memory");
-		goto pfail;
-	}
-
-	/* start the interrupt endpoint */
-	if (auerswald_int_open (cp)) {
-		err ("int endpoint failed");
-		goto pfail;
-	}
-
-	/* all OK */
-	return cp;
-
-	/* Error exit: clean up the memory */
-pfail:	auerswald_delete (cp);
-	MOD_DEC_USE_COUNT;
-	return NULL;
-}
-
-
-/* Disconnect driver from a served device
-
-   This function is called whenever a device which was served by this driver
-   is disconnected.
-
-   The argument  dev specifies the device context and the  driver_context
-   returns a pointer to the previously registered  driver_context of the
-   probe function. After returning from the disconnect function the USB
-   framework completly deallocates all data structures associated with
-   this device. So especially the usb_device structure must not be used
-   any longer by the usb driver.
-*/
-static void auerswald_disconnect (struct usb_device *usbdev, void *driver_context)
-{
-	pauerswald_t cp = (pauerswald_t) driver_context;
-	unsigned int u;
-
-	down (&cp->mutex);
-	info ("device /dev/usb/%s now disconnecting", cp->name);
-
-	/* remove from device table */
-	/* Nobody can open() this device any more */
-	down (&dev_table_mutex);
-	dev_table[cp->dtindex] = NULL;
-	up (&dev_table_mutex);
-
-	/* remove our devfs node */
-	/* Nobody can see this device any more */
-	devfs_unregister (cp->devfs);
-
-	/* Stop the interrupt endpoint */
-	auerswald_int_release (cp);
-
-	/* remove the control chain allocated in auerswald_probe
-	   This has the benefit of
-	   a) all pending (a)synchronous urbs are unlinked
-	   b) all buffers dealing with urbs are reclaimed
-	*/
-	auerchain_free (&cp->controlchain);
-
-	if (cp->open_count == 0) {
-		/* nobody is using this device. So we can clean up now */
-		up (&cp->mutex);/* up() is possible here because no other task
-				   can open the device (see above). I don't want
-				   to kfree() a locked mutex. */
-		auerswald_delete (cp);
-	} else {
-		/* device is used. Remove the pointer to the
-		   usb device (it's not valid any more). The last
-		   release() will do the clean up */
-		cp->usbdev = NULL;
-		up (&cp->mutex);
-		/* Terminate waiting writers */
-		wake_up (&cp->bufferwait);
-		/* Inform all waiting readers */
-		for ( u = 0; u < AUH_TYPESIZE; u++) {
-			pauerscon_t scp = cp->services[u];
-			if (scp) scp->disconnect( scp);
-		}
-	}
-
-	/* The device releases this module */
-	MOD_DEC_USE_COUNT;
-}
-
-/* Descriptor for the devices which are served by this driver.
-   NOTE: this struct is parsed by the usbmanager install scripts.
-         Don't change without caution!
-*/
-static struct usb_device_id auerswald_ids [] = {
-	{ USB_DEVICE (ID_AUERSWALD, 0x00C0) },          /* COMpact 2104 USB */
-	{ USB_DEVICE (ID_AUERSWALD, 0x00DB) },          /* COMpact 4410/2206 USB */
-	{ USB_DEVICE (ID_AUERSWALD, 0x00F1) },          /* Comfort 2000 System Telephone */
-	{ USB_DEVICE (ID_AUERSWALD, 0x00F2) },          /* Comfort 1200 System Telephone */
-        { }			                        /* Terminating entry */
-};
-
-/* Standard module device table */
-MODULE_DEVICE_TABLE (usb, auerswald_ids);
-
-/* Standard usb driver struct */
-static struct usb_driver auerswald_driver = {
-	name:		"auerswald",
-	probe:		auerswald_probe,
-	disconnect:	auerswald_disconnect,
-	fops:		&auerswald_fops,
-	minor:		AUER_MINOR_BASE,
-	id_table:	auerswald_ids,
-};
-
-
-/* --------------------------------------------------------------------- */
-/* Module loading/unloading                                              */
-
-/* Driver initialisation. Called after module loading.
-   NOTE: there is no concurrency at _init
-*/
-static int __init auerswald_init (void)
-{
-	int result;
-	dbg ("init");
-
-	/* initialize the device table */
-	memset (&dev_table, 0, sizeof(dev_table));
-	init_MUTEX (&dev_table_mutex);
-
-	/* register driver at the USB subsystem */
-	result = usb_register (&auerswald_driver);
-	if (result < 0) {
-		err ("driver could not be registered");
-		return -1;
-	}
-	return 0;
-}
-
-/* Driver deinit. Called before module removal.
-   NOTE: there is no concurrency at _cleanup
-*/
-static void __exit auerswald_cleanup (void)
-{
-	dbg ("cleanup");
-	usb_deregister (&auerswald_driver);
-}
-
-/* --------------------------------------------------------------------- */
-/* Linux device driver module description                                */
-
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
-
-module_init (auerswald_init);
-module_exit (auerswald_cleanup);
-
-/* --------------------------------------------------------------------- */
-
diff -Nru a/drivers/usb/bluetooth.c b/drivers/usb/bluetooth.c
--- a/drivers/usb/bluetooth.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1364 +0,0 @@
-/*
- * bluetooth.c   Version 0.13
- *
- * Copyright (c) 2000, 2001 Greg Kroah-Hartman	<greg@kroah.com>
- * Copyright (c) 2000 Mark Douglas Corner	<mcorner@umich.edu>
- *
- * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
- * 
- * (2001/11/30) Version 0.13 gkh
- *	- added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
- *	- removed active variable, as open_count will do.
- *
- * (2001/07/09) Version 0.12 gkh
- *	- removed in_interrupt() call, as it doesn't make sense to do 
- *	  that anymore.
- *
- * (2001/06/05) Version 0.11 gkh
- *	- Fixed problem with read urb status saying that we have shutdown,
- *	  and that we shouldn't resubmit the urb.  Patch from unknown.
- *
- * (2001/05/28) Version 0.10 gkh
- *	- Fixed problem with using data from userspace in the bluetooth_write
- *	  function as found by the CHECKER project.
- *	- Added a buffer to the write_urb_pool which reduces the number of
- *	  buffers being created and destroyed for ever write.  Also cleans
- *	  up the logic a bit.
- *	- Added a buffer to the control_urb_pool which fixes a memory leak
- *	  when the device is removed from the system.
- *
- * (2001/05/28) Version 0.9 gkh
- *	Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback
- *	which was found by both the CHECKER project and Mikko Rahkonen.
- *
- * (08/04/2001) gb
- *	Identify version on module load.
- *
- * (2001/03/10) Version 0.8 gkh
- *	Fixed problem with not unlinking interrupt urb on device close
- *	and resubmitting the read urb on error with bluetooth struct.
- *	Thanks to Narayan Mohanram <narayan@RovingNetworks.com> for the
- *	fixes.
- *
- * (11/29/2000) Version 0.7 gkh
- *	Fixed problem with overrunning the tty flip buffer.
- *	Removed unneeded NULL pointer initialization.
- *
- * (10/05/2000) Version 0.6 gkh
- *	Fixed bug with urb->dev not being set properly, now that the usb
- *	core needs it.
- *	Got a real major id number and name.
- *
- * (08/06/2000) Version 0.5 gkh
- *	Fixed problem of not resubmitting the bulk read urb if there is
- *	an error in the callback.  Ericsson devices seem to need this.
- *
- * (07/11/2000) Version 0.4 gkh
- *	Fixed bug in disconnect for when we call tty_hangup
- *	Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not
- *	getting attached to the control urb properly.
- *	Fixed bug in bluetooth_write where we pay attention to the result
- *	of bluetooth_ctrl_msg.
- *
- * (08/03/2000) Version 0.3 gkh mdc
- *	Merged in Mark's changes to make the driver play nice with the Axis
- *	stack.
- *	Made the write bulk use an urb pool to enable larger transfers with
- *	fewer calls to the driver.
- *	Fixed off by one bug in acl pkt receive
- *	Made packet counters specific to each bluetooth device 
- *	Added checks for zero length callbacks
- *	Added buffers for int and bulk packets.  Had to do this otherwise 
- *	packet types could intermingle.
- *	Made a control urb pool for the control messages.
- *
- * (07/11/2000) Version 0.2 gkh
- *	Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe 
- *	function.
- *
- * (07/09/2000) Version 0.1 gkh
- *	Initial release. Has support for sending ACL data (which is really just
- *	a HCI frame.) Raw HCI commands and HCI events are not supported.
- *	A ioctl will probably be needed for the HCI commands and events in the
- *	future. All isoch endpoints are ignored at this time also.
- *	This driver should work for all currently shipping USB Bluetooth 
- *	devices at this time :)
- * 
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-
-#define DEBUG
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.13"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
-#define DRIVER_DESC "USB Bluetooth tty driver"
-
-/* define this if you have hardware that is not good */
-/*#define	BTBUGGYHARDWARE */
-
-/* Class, SubClass, and Protocol codes that describe a Bluetooth device */
-#define WIRELESS_CLASS_CODE			0xe0
-#define RF_SUBCLASS_CODE			0x01
-#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE	0x01
-
-
-#define BLUETOOTH_TTY_MAJOR	216	/* real device node major id */
-#define BLUETOOTH_TTY_MINORS	256	/* whole lotta bluetooth devices */
-
-#define USB_BLUETOOTH_MAGIC	0x6d02	/* magic number for bluetooth struct */
-
-#define BLUETOOTH_CONTROL_REQUEST_TYPE	0x20
-
-/* Bluetooth packet types */
-#define CMD_PKT			0x01
-#define ACL_PKT			0x02
-#define SCO_PKT			0x03
-#define EVENT_PKT		0x04
-#define ERROR_PKT		0x05
-#define NEG_PKT			0x06
-
-/* Message sizes */
-#define MAX_EVENT_SIZE		0xFF
-#define EVENT_HDR_SIZE		3	/* 2 for the header + 1 for the type indicator */
-#define EVENT_BUFFER_SIZE	(MAX_EVENT_SIZE + EVENT_HDR_SIZE)
-
-#define MAX_ACL_SIZE		0xFFFF
-#define ACL_HDR_SIZE		5	/* 4 for the header + 1 for the type indicator */
-#define ACL_BUFFER_SIZE		(MAX_ACL_SIZE + ACL_HDR_SIZE)
-
-/* parity check flag */
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-#define CHAR2INT16(c1,c0)	(((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
-
-#define NUM_BULK_URBS		24
-#define NUM_CONTROL_URBS	16
-
-struct usb_bluetooth {
-	int			magic;
-	struct usb_device *	dev;
-	struct tty_driver *	tty_driver;	/* the tty_driver for this device */
-	struct tty_struct *	tty;		/* the coresponding tty for this port */
-
-	unsigned char		minor;		/* the starting minor number for this device */
-	int			throttle;	/* throttled by tty layer */
-	int			open_count;
-	
-	__u8			control_out_bInterfaceNum;
-	struct urb *		control_urb_pool[NUM_CONTROL_URBS];
-	struct usb_ctrlrequest	dr[NUM_CONTROL_URBS];
-
-	unsigned char *		interrupt_in_buffer;
-	struct urb *		interrupt_in_urb;
-	__u8			interrupt_in_endpointAddress;
-	__u8			interrupt_in_interval;
-	int			interrupt_in_buffer_size;
-
-	unsigned char *		bulk_in_buffer;
-	struct urb *		read_urb;
-	__u8			bulk_in_endpointAddress;
-	int			bulk_in_buffer_size;
-
-	int			bulk_out_buffer_size;
-	struct urb *		write_urb_pool[NUM_BULK_URBS];
-	__u8			bulk_out_endpointAddress;
-
-	wait_queue_head_t	write_wait;
-
-	struct tq_struct	tqueue;		/* task queue for line discipline waking up */
-	
-	unsigned int		int_packet_pos;
-	unsigned char		int_buffer[EVENT_BUFFER_SIZE];
-	unsigned int		bulk_packet_pos;
-	unsigned char		bulk_buffer[ACL_BUFFER_SIZE];	/* 64k preallocated, fix? */
-	struct semaphore	lock;
-};
-
-
-/* local function prototypes */
-static int  bluetooth_open		(struct tty_struct *tty, struct file *filp);
-static void bluetooth_close		(struct tty_struct *tty, struct file *filp);
-static int  bluetooth_write		(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static int  bluetooth_write_room	(struct tty_struct *tty);
-static int  bluetooth_chars_in_buffer	(struct tty_struct *tty);
-static void bluetooth_throttle		(struct tty_struct *tty);
-static void bluetooth_unthrottle	(struct tty_struct *tty);
-static int  bluetooth_ioctl		(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void bluetooth_set_termios	(struct tty_struct *tty, struct termios *old);
-
-static void bluetooth_int_callback		(struct urb *urb);
-static void bluetooth_ctrl_callback		(struct urb *urb);
-static void bluetooth_read_bulk_callback	(struct urb *urb);
-static void bluetooth_write_bulk_callback	(struct urb *urb);
-
-static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
-			 	  const struct usb_device_id *id);
-static void usb_bluetooth_disconnect	(struct usb_device *dev, void *ptr);
-
-
-static struct usb_device_id usb_bluetooth_ids [] = {
-	{ USB_DEVICE_INFO(WIRELESS_CLASS_CODE, RF_SUBCLASS_CODE, BLUETOOTH_PROGRAMMING_PROTOCOL_CODE) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
-
-static struct usb_driver usb_bluetooth_driver = {
-	name:		"bluetooth",
-	probe:		usb_bluetooth_probe,
-	disconnect:	usb_bluetooth_disconnect,
-	id_table:	usb_bluetooth_ids,
-};
-
-static int			bluetooth_refcount;
-static struct tty_driver	bluetooth_tty_driver;
-static struct tty_struct *	bluetooth_tty[BLUETOOTH_TTY_MINORS];
-static struct termios *		bluetooth_termios[BLUETOOTH_TTY_MINORS];
-static struct termios *		bluetooth_termios_locked[BLUETOOTH_TTY_MINORS];
-static struct usb_bluetooth	*bluetooth_table[BLUETOOTH_TTY_MINORS];
-
-
-static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
-{
-	if (!bluetooth) {
-		dbg("%s - bluetooth == NULL", function);
-		return -1;
-	}
-	if (bluetooth->magic != USB_BLUETOOTH_MAGIC) {
-		dbg("%s - bad magic number for bluetooth", function);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function)
-{
-	if (!bluetooth || 
-	    bluetooth_paranoia_check (bluetooth, function)) { 
-		/* then say that we dont have a valid usb_bluetooth thing, which will
-		 * end up generating -ENODEV return values */
-		return NULL;
-	}
-
-	return bluetooth;
-}
-
-
-static inline struct usb_bluetooth *get_bluetooth_by_minor (int minor)
-{
-	return bluetooth_table[minor];
-}
-
-
-static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
-{
-	struct urb *urb = NULL;
-	struct usb_ctrlrequest *dr = NULL;
-	int i;
-	int status;
-
-	dbg (__FUNCTION__);
-
-	/* try to find a free urb in our list */
-	for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-		if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) {
-			urb = bluetooth->control_urb_pool[i];
-			dr = &bluetooth->dr[i];
-			break;
-		}
-	}
-	if (urb == NULL) {
-		dbg (__FUNCTION__ " - no free urbs");
-		return -ENOMEM;
-	}
-
-	/* keep increasing the urb transfer buffer to fit the size of the message */
-	if (urb->transfer_buffer == NULL) {
-		urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
-		if (urb->transfer_buffer == NULL) {
-			err (__FUNCTION__" - out of memory");
-			return -ENOMEM;
-		}
-	}
-	if (urb->transfer_buffer_length < len) {
-		kfree (urb->transfer_buffer);
-		urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
-		if (urb->transfer_buffer == NULL) {
-			err (__FUNCTION__" - out of memory");
-			return -ENOMEM;
-		}
-	}
-	memcpy (urb->transfer_buffer, buf, len);
-
-	dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16((u16) value);
-	dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
-	dr->wLength = cpu_to_le16((u16) len);
-	
-	FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
-			  (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
-
-	/* send it down the pipe */
-	status = usb_submit_urb(urb, GFP_KERNEL);
-	if (status)
-		dbg(__FUNCTION__ " - usb_submit_urb(control) failed with status = %d", status);
-	
-	return status;
-}
-
-
-
-
-
-/*****************************************************************************
- * Driver tty interface functions
- *****************************************************************************/
-static int bluetooth_open (struct tty_struct *tty, struct file * filp)
-{
-	struct usb_bluetooth *bluetooth;
-	int result;
-
-	dbg(__FUNCTION__);
-
-	/* initialize the pointer incase something fails */
-	tty->driver_data = NULL;
-
-	/* get the bluetooth object associated with this tty pointer */
-	bluetooth = get_bluetooth_by_minor (minor(tty->device));
-
-	if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
-		return -ENODEV;
-	}
-
-	down (&bluetooth->lock);
- 
-	++bluetooth->open_count;
-	if (bluetooth->open_count == 1) {
-		/* set up our structure making the tty driver remember our object, and us it */
-		tty->driver_data = bluetooth;
-		bluetooth->tty = tty;
-
-		/* force low_latency on so that our tty_push actually forces the data through, 
-	 	* otherwise it is scheduled, and with high data rates (like with OHCI) data
-	 	* can get lost. */
-		bluetooth->tty->low_latency = 1;
-	
-		/* Reset the packet position counters */
-		bluetooth->int_packet_pos = 0;
-		bluetooth->bulk_packet_pos = 0;
-
-#ifndef BTBUGGYHARDWARE
-		/* Start reading from the device */
-		FILL_BULK_URB (bluetooth->read_urb, bluetooth->dev, 
-			       usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-			       bluetooth->bulk_in_buffer,
-			       bluetooth->bulk_in_buffer_size,
-			       bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-		if (result)
-			dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
-#endif
-		FILL_INT_URB (bluetooth->interrupt_in_urb, bluetooth->dev,
-			      usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
-			      bluetooth->interrupt_in_buffer,
-			      bluetooth->interrupt_in_buffer_size,
-			      bluetooth_int_callback, bluetooth,
-			      bluetooth->interrupt_in_interval);
-		result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL);
-		if (result)
-			dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
-	}
-	
-	up(&bluetooth->lock);
-
-	return 0;
-}
-
-
-static void bluetooth_close (struct tty_struct *tty, struct file * filp)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int i;
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not opened");
-		return;
-	}
-
-	down (&bluetooth->lock);
- 
-	--bluetooth->open_count;
-	if (bluetooth->open_count <= 0) {
-		bluetooth->open_count = 0;
-
-		/* shutdown any bulk reads and writes that might be going on */
-		for (i = 0; i < NUM_BULK_URBS; ++i)
-			usb_unlink_urb (bluetooth->write_urb_pool[i]);
-		usb_unlink_urb (bluetooth->read_urb);
-		usb_unlink_urb (bluetooth->interrupt_in_urb);
-	}
-	up(&bluetooth->lock);
-}
-
-
-static int bluetooth_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	struct urb *urb = NULL;
-	unsigned char *temp_buffer = NULL;
-	const unsigned char *current_buffer;
-	const unsigned char *current_position;
-	int bytes_sent;
-	int buffer_size;
-	int i;
-	int retval = 0;
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	dbg(__FUNCTION__ " - %d byte(s)", count);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not opened");
-		return -EINVAL;
-	}
-
-	if (count == 0) {
-		dbg(__FUNCTION__ " - write request of 0 bytes");
-		return 0;
-	}
-	if (count == 1) {
-		dbg(__FUNCTION__ " - write request only included type %d", buf[0]);
-		return 1;
-	}
-
-#ifdef DEBUG
-	printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
-	for (i = 0; i < count; ++i) {
-		printk ("%.2x ", buf[i]);
-	}
-	printk ("\n");
-#endif
-
-	if (from_user) {
-		temp_buffer = kmalloc (count, GFP_KERNEL);
-		if (temp_buffer == NULL) {
-			err (__FUNCTION__ "- out of memory.");
-			retval = -ENOMEM;
-			goto exit;
-		}
-		copy_from_user (temp_buffer, buf, count);
-		current_buffer = temp_buffer;
-	} else {
-		current_buffer = buf;
-	}
-
-	switch (*current_buffer) {
-		/* First byte indicates the type of packet */
-		case CMD_PKT:
-			/* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/
-
-			retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, &current_buffer[1], count-1);
-			if (retval) {
-				goto exit;
-			}
-			retval = count;
-			break;
-
-		case ACL_PKT:
-			current_position = current_buffer;
-			++current_position;
-			--count;
-			bytes_sent = 0;
-
-			while (count > 0) {
-				urb = NULL;
-
-				/* try to find a free urb in our list */
-				for (i = 0; i < NUM_BULK_URBS; ++i) {
-					if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
-						urb = bluetooth->write_urb_pool[i];
-						break;
-					}
-				}
-				if (urb == NULL) {
-					dbg (__FUNCTION__ " - no free urbs");
-					retval = bytes_sent;
-					goto exit;
-				}
-				
-
-				buffer_size = min (count, bluetooth->bulk_out_buffer_size);
-				memcpy (urb->transfer_buffer, current_position, buffer_size);
-
-				/* build up our urb */
-				FILL_BULK_URB (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress),
-						urb->transfer_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth);
-				urb->transfer_flags |= USB_QUEUE_BULK;
-
-				/* send it down the pipe */
-				retval = usb_submit_urb(urb, GFP_KERNEL);
-				if (retval) {
-					dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with error = %d", retval);
-					goto exit;
-				}
-#ifdef BTBUGGYHARDWARE
-				/* A workaround for the stalled data bug */
-				/* May or may not be needed...*/
-				if (count != 0) {
-					udelay(500);
-				}
-#endif
-				current_position += buffer_size;
-				bytes_sent += buffer_size;
-				count -= buffer_size;
-			}
-
-			retval = bytes_sent + 1;
-			break;
-		
-		default :
-			dbg(__FUNCTION__" - unsupported (at this time) write type");
-			retval = -EINVAL;
-			break;
-	}
-
-exit:
-	if (temp_buffer != NULL)
-		kfree (temp_buffer);
-
-	return retval;
-} 
-
-
-static int bluetooth_write_room (struct tty_struct *tty) 
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int room = 0;
-	int i;
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < NUM_BULK_URBS; ++i) {
-		if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
-			room += bluetooth->bulk_out_buffer_size;
-		}
-	}
-
-	dbg(__FUNCTION__ " - returns %d", room);
-	return room;
-}
-
-
-static int bluetooth_chars_in_buffer (struct tty_struct *tty) 
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int chars = 0;
-	int i;
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < NUM_BULK_URBS; ++i) {
-		if (bluetooth->write_urb_pool[i]->status == -EINPROGRESS) {
-			chars += bluetooth->write_urb_pool[i]->transfer_buffer_length;
-		}
-	}
-
-	dbg (__FUNCTION__ " - returns %d", chars);
-	return chars;
-}
-
-
-static void bluetooth_throttle (struct tty_struct * tty)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return;
-	}
-	
-	dbg(__FUNCTION__ " unsupported (at this time)");
-
-	return;
-}
-
-
-static void bluetooth_unthrottle (struct tty_struct * tty)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return;
-	}
-
-	dbg(__FUNCTION__ " unsupported (at this time)");
-}
-
-
-static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	dbg(__FUNCTION__ " - cmd 0x%.4x", cmd);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return -ENODEV;
-	}
-
-	/* FIXME!!! */
-	return -ENOIOCTLCMD;
-}
-
-
-static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return;
-	}
-
-	/* FIXME!!! */
-
-	return;
-}
-
-
-#ifdef BTBUGGYHARDWARE
-void btusb_enable_bulk_read(struct tty_struct *tty){
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int result;
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return;
-	}
-
-	if (bluetooth->read_urb) {
-		FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
-			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-			      bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-		if (result)
-			err (__FUNCTION__ " - failed submitting read urb, error %d", result);
-	}
-}
-
-void btusb_disable_bulk_read(struct tty_struct *tty){
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth->open_count) {
-		dbg (__FUNCTION__ " - device not open");
-		return;
-	}
-
-	if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length))
-		usb_unlink_urb(bluetooth->read_urb);
-}
-#endif
-
-
-/*****************************************************************************
- * urb callback functions
- *****************************************************************************/
-
-
-static void bluetooth_int_callback (struct urb *urb)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-	unsigned char *data = urb->transfer_buffer;
-	unsigned int i;
-	unsigned int count = urb->actual_length;
-	unsigned int packet_size;
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth) {
-		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
-		return;
-	}
-
-	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero int status received: %d", urb->status);
-		return;
-	}
-
-	if (!count) {
-		dbg(__FUNCTION__ " - zero length int");
-		return;
-	}
-
-
-#ifdef DEBUG
-	if (count) {
-		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
-		for (i = 0; i < count; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
-
-#ifdef BTBUGGYHARDWARE
-	if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) {
-		data += 2;
-		count -= 2;
-	}
-	if (count == 0) {
-		urb->actual_length = 0;
-		return;
-	}
-#endif
-	/* We add  a packet type identifier to the beginning of each
-	   HCI frame.  This makes the data in the tty look like a
-	   serial USB devices.  Each HCI frame can be broken across
-	   multiple URBs so we buffer them until we have a full hci
-	   packet */
-
-	if (!bluetooth->int_packet_pos) {
-		bluetooth->int_buffer[0] = EVENT_PKT;
-		bluetooth->int_packet_pos++;
-	}
-	
-	if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
-		err(__FUNCTION__ " - exceeded EVENT_BUFFER_SIZE");
-		bluetooth->int_packet_pos = 0;
-		return;
-	}
-
-	memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos],
-		urb->transfer_buffer, count);
-	bluetooth->int_packet_pos += count;
-	urb->actual_length = 0;
-
-	if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE)
-		packet_size = bluetooth->int_buffer[2];
-	else
-		return;
-
-	if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
-		err(__FUNCTION__ " - packet was too long");
-		bluetooth->int_packet_pos = 0;
-		return;
-	}
-
-	if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
-		for (i = 0; i < bluetooth->int_packet_pos; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
-			if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(bluetooth->tty);
-			}
-			tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
-		}
-		tty_flip_buffer_push(bluetooth->tty);
-
-		bluetooth->int_packet_pos = 0;
-	}
-}
-
-
-static void bluetooth_ctrl_callback (struct urb *urb)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth) {
-		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
-		return;
-	}
-
-	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
-		return;
-	}
-}
-
-
-static void bluetooth_read_bulk_callback (struct urb *urb)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-	unsigned char *data = urb->transfer_buffer;
-	unsigned int count = urb->actual_length;
-	unsigned int i;
-	unsigned int packet_size;
-	int result;
-
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth) {
-		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
-		return;
-	}
-
-	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
-		if (urb->status == -ENOENT) {                   
-			dbg(__FUNCTION__ " - URB canceled, won't reschedule");
-			return;
-		}
-		goto exit;
-	}
-
-	if (!count) {
-		dbg(__FUNCTION__ " - zero length read bulk");
-		goto exit;
-	}
-
-#ifdef DEBUG
-	if (count) {
-		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
-		for (i = 0; i < count; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
-#ifdef BTBUGGYHARDWARE
-	if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00)
-	    && (data[2] == 0x00) && (data[3] == 0x00)) {
-		urb->actual_length = 0;
-		FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
-			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-			      bluetooth_read_bulk_callback, bluetooth);
-		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-		if (result)
-			err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
-
-		return;
-	}
-#endif
-	/* We add  a packet type identifier to the beginning of each
-	   HCI frame.  This makes the data in the tty look like a
-	   serial USB devices.  Each HCI frame can be broken across
-	   multiple URBs so we buffer them until we have a full hci
-	   packet */
-	
-	if (!bluetooth->bulk_packet_pos) {
-		bluetooth->bulk_buffer[0] = ACL_PKT;
-		bluetooth->bulk_packet_pos++;
-	}
-
-	if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
-		err(__FUNCTION__ " - exceeded ACL_BUFFER_SIZE");
-		bluetooth->bulk_packet_pos = 0;
-		goto exit;
-	}
-
-	memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos],
-		urb->transfer_buffer, count);
-	bluetooth->bulk_packet_pos += count;
-	urb->actual_length = 0;
-
-	if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) {
-		packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]);
-	} else {
-		goto exit;
-	}
-
-	if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
-		err(__FUNCTION__ " - packet was too long");
-		bluetooth->bulk_packet_pos = 0;
-		goto exit;
-	}
-
-	if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
-		for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
-			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
-			if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(bluetooth->tty);
-			}
-			tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
-		}
-		tty_flip_buffer_push(bluetooth->tty);
-		bluetooth->bulk_packet_pos = 0;
-	}	
-
-exit:
-	if (!bluetooth || !bluetooth->open_count)
-		return;
-
-	FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
-		      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-		      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-		      bluetooth_read_bulk_callback, bluetooth);
-	result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
-	if (result)
-		err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
-
-	return;
-}
-
-
-static void bluetooth_write_bulk_callback (struct urb *urb)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth) {
-		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
-		return;
-	}
-
-	if (urb->status) {
-		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
-		return;
-	}
-
-	/* wake up our little function to let the tty layer know that something happened */
-	queue_task(&bluetooth->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-	return;
-}
-
-
-static void bluetooth_softint(void *private)
-{
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
-	struct tty_struct *tty;
-
-	dbg(__FUNCTION__);
-
-	if (!bluetooth) {
-		return;
-	}
-
-	tty = bluetooth->tty;
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		dbg(__FUNCTION__ " - write wakeup call.");
-		(tty->ldisc.write_wakeup)(tty);
-	}
-
-	wake_up_interruptible(&tty->write_wait);
-}
-
-
-static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
-			 	  const struct usb_device_id *id)
-{
-	struct usb_bluetooth *bluetooth = NULL;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_endpoint_descriptor *interrupt_in_endpoint[8];
-	struct usb_endpoint_descriptor *bulk_in_endpoint[8];
-	struct usb_endpoint_descriptor *bulk_out_endpoint[8];
-	int control_out_endpoint;
-
-	int minor;
-	int buffer_size;
-	int i;
-	int num_interrupt_in = 0;
-	int num_bulk_in = 0;
-	int num_bulk_out = 0;
-
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
-	control_out_endpoint = interface->bInterfaceNumber;
-
-	/* find the endpoints that we need */
-	for (i = 0; i < interface->bNumEndpoints; ++i) {
-		endpoint = &interface->endpoint[i];
-
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found a bulk in endpoint */
-			dbg("found bulk in");
-			bulk_in_endpoint[num_bulk_in] = endpoint;
-			++num_bulk_in;
-		}
-
-		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found a bulk out endpoint */
-			dbg("found bulk out");
-			bulk_out_endpoint[num_bulk_out] = endpoint;
-			++num_bulk_out;
-		}
-
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x03)) {
-			/* we found a interrupt in endpoint */
-			dbg("found interrupt in");
-			interrupt_in_endpoint[num_interrupt_in] = endpoint;
-			++num_interrupt_in;
-		}
-	}
-
-	/* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */
-	if ((num_bulk_in != 1) ||
-	    (num_bulk_out != 1) ||
-	    (num_interrupt_in != 1)) {
-		dbg (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound.");
-		return NULL;
-	}
-
-	MOD_INC_USE_COUNT;
-	info("USB Bluetooth converter detected");
-
-	for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor)
-		;
-	if (bluetooth_table[minor]) {
-		err("No more free Bluetooth devices");
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
-
-	if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) {
-		err("Out of memory");
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
-
-	memset(bluetooth, 0, sizeof(struct usb_bluetooth));
-
-	bluetooth->magic = USB_BLUETOOTH_MAGIC;
-	bluetooth->dev = dev;
-	bluetooth->minor = minor;
-	bluetooth->tqueue.routine = bluetooth_softint;
-	bluetooth->tqueue.data = bluetooth;
-	init_MUTEX(&bluetooth->lock);
-
-	/* record the interface number for the control out */
-	bluetooth->control_out_bInterfaceNum = control_out_endpoint;
-	
-	/* create our control out urb pool */ 
-	for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-		struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (urb == NULL) {
-			err("No free urbs available");
-			goto probe_error;
-		}
-		urb->transfer_buffer = NULL;
-		bluetooth->control_urb_pool[i] = urb;
-	}
-
-	/* set up the endpoint information */
-	endpoint = bulk_in_endpoint[0];
-	bluetooth->read_urb = usb_alloc_urb (0, GFP_KERNEL);
-	if (!bluetooth->read_urb) {
-		err("No free urbs available");
-		goto probe_error;
-	}
-	bluetooth->bulk_in_buffer_size = buffer_size = endpoint->wMaxPacketSize;
-	bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress;
-	bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-	if (!bluetooth->bulk_in_buffer) {
-		err("Couldn't allocate bulk_in_buffer");
-		goto probe_error;
-	}
-	FILL_BULK_URB(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
-		      bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth);
-
-	endpoint = bulk_out_endpoint[0];
-	bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
-	
-	/* create our write urb pool */ 
-	for (i = 0; i < NUM_BULK_URBS; ++i) {
-		struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (urb == NULL) {
-			err("No free urbs available");
-			goto probe_error;
-		}
-		urb->transfer_buffer = kmalloc (bluetooth->bulk_out_buffer_size, GFP_KERNEL);
-		if (urb->transfer_buffer == NULL) {
-			err("out of memory");
-			goto probe_error;
-		}
-		bluetooth->write_urb_pool[i] = urb;
-	}
-	
-	bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
-
-	endpoint = interrupt_in_endpoint[0];
-	bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!bluetooth->interrupt_in_urb) {
-		err("No free urbs available");
-		goto probe_error;
-	}
-	bluetooth->interrupt_in_buffer_size = buffer_size = endpoint->wMaxPacketSize;
-	bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
-	bluetooth->interrupt_in_interval = endpoint->bInterval;
-	bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-	if (!bluetooth->interrupt_in_buffer) {
-		err("Couldn't allocate interrupt_in_buffer");
-		goto probe_error;
-	}
-	FILL_INT_URB(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-		     bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback,
-		     bluetooth, endpoint->bInterval);
-
-	/* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
-	tty_register_devfs (&bluetooth_tty_driver, 0, minor);
-	info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
-
-	bluetooth_table[minor] = bluetooth;
-
-	return bluetooth; /* success */
-
-probe_error:
-	if (bluetooth->read_urb)
-		usb_free_urb (bluetooth->read_urb);
-	if (bluetooth->bulk_in_buffer)
-		kfree (bluetooth->bulk_in_buffer);
-	if (bluetooth->interrupt_in_urb)
-		usb_free_urb (bluetooth->interrupt_in_urb);
-	if (bluetooth->interrupt_in_buffer)
-		kfree (bluetooth->interrupt_in_buffer);
-	for (i = 0; i < NUM_BULK_URBS; ++i)
-		if (bluetooth->write_urb_pool[i]) {
-			if (bluetooth->write_urb_pool[i]->transfer_buffer)
-				kfree (bluetooth->write_urb_pool[i]->transfer_buffer);
-			usb_free_urb (bluetooth->write_urb_pool[i]);
-		}
-	for (i = 0; i < NUM_CONTROL_URBS; ++i) 
-		if (bluetooth->control_urb_pool[i]) {
-			if (bluetooth->control_urb_pool[i]->transfer_buffer)
-				kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
-			usb_free_urb (bluetooth->control_urb_pool[i]);
-		}
-
-	bluetooth_table[minor] = NULL;
-
-	/* free up any memory that we allocated */
-	kfree (bluetooth);
-	MOD_DEC_USE_COUNT;
-	return NULL;
-}
-
-
-static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_bluetooth *bluetooth = (struct usb_bluetooth *) ptr;
-	int i;
-
-	if (bluetooth) {
-		if ((bluetooth->open_count) && (bluetooth->tty))
-			tty_hangup(bluetooth->tty);
-
-		bluetooth->open_count = 0;
-
-		if (bluetooth->read_urb) {
-			usb_unlink_urb (bluetooth->read_urb);
-			usb_free_urb (bluetooth->read_urb);
-		}
-		if (bluetooth->bulk_in_buffer)
-			kfree (bluetooth->bulk_in_buffer);
-
-		if (bluetooth->interrupt_in_urb) {
-			usb_unlink_urb (bluetooth->interrupt_in_urb);
-			usb_free_urb (bluetooth->interrupt_in_urb);
-		}
-		if (bluetooth->interrupt_in_buffer)
-			kfree (bluetooth->interrupt_in_buffer);
-
-		tty_unregister_devfs (&bluetooth_tty_driver, bluetooth->minor);
-
-		for (i = 0; i < NUM_BULK_URBS; ++i) {
-			if (bluetooth->write_urb_pool[i]) {
-				usb_unlink_urb (bluetooth->write_urb_pool[i]);
-				if (bluetooth->write_urb_pool[i]->transfer_buffer)
-					kfree (bluetooth->write_urb_pool[i]->transfer_buffer);
-				usb_free_urb (bluetooth->write_urb_pool[i]);
-			}
-		}
-		for (i = 0; i < NUM_CONTROL_URBS; ++i) {
-			if (bluetooth->control_urb_pool[i]) {
-				usb_unlink_urb (bluetooth->control_urb_pool[i]);
-				if (bluetooth->control_urb_pool[i]->transfer_buffer)
-					kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
-				usb_free_urb (bluetooth->control_urb_pool[i]);
-			}
-		}
-		
-		info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor);
-
-		bluetooth_table[bluetooth->minor] = NULL;
-
-		/* free up any memory that we allocated */
-		kfree (bluetooth);
-
-	} else {
-		info("device disconnected");
-	}
-
-	MOD_DEC_USE_COUNT;
-}
-
-
-static struct tty_driver bluetooth_tty_driver = {
-	magic:			TTY_DRIVER_MAGIC,
-	driver_name:		"usb-bluetooth",
-	name:			"usb/ttub/%d",
-	major:			BLUETOOTH_TTY_MAJOR,
-	minor_start:		0,
-	num:			BLUETOOTH_TTY_MINORS,
-	type:			TTY_DRIVER_TYPE_SERIAL,
-	subtype:		SERIAL_TYPE_NORMAL,
-	flags:			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
-
-	refcount:		&bluetooth_refcount,
-	table:			bluetooth_tty,
-	termios:		bluetooth_termios,
-	termios_locked:		bluetooth_termios_locked,
-
-	open:			bluetooth_open,
-	close:			bluetooth_close,
-	write:			bluetooth_write,
-	write_room:		bluetooth_write_room,
-	ioctl:			bluetooth_ioctl,
-	set_termios:		bluetooth_set_termios,
-	throttle:		bluetooth_throttle,
-	unthrottle:		bluetooth_unthrottle,
-	chars_in_buffer:	bluetooth_chars_in_buffer,
-};
-
-
-int usb_bluetooth_init(void)
-{
-	int i;
-	int result;
-
-	/* Initalize our global data */
-	for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) {
-		bluetooth_table[i] = NULL;
-	}
-
-	info ("USB Bluetooth support registered");
-
-	/* register the tty driver */
-	bluetooth_tty_driver.init_termios          = tty_std_termios;
-	bluetooth_tty_driver.init_termios.c_cflag  = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	if (tty_register_driver (&bluetooth_tty_driver)) {
-		err(__FUNCTION__ " - failed to register tty driver");
-		return -1;
-	}
-
-	/* register the USB driver */
-	result = usb_register(&usb_bluetooth_driver);
-	if (result < 0) {
-		tty_unregister_driver(&bluetooth_tty_driver);
-		err("usb_register failed for the USB bluetooth driver. Error number %d", result);
-		return -1;
-	}
-
-	info(DRIVER_DESC " " DRIVER_VERSION);
-
-	return 0;
-}
-
-
-void usb_bluetooth_exit(void)
-{
-	usb_deregister(&usb_bluetooth_driver);
-	tty_unregister_driver(&bluetooth_tty_driver);
-}
-
-
-module_init(usb_bluetooth_init);
-module_exit(usb_bluetooth_exit);
-
-/* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/catc.c b/drivers/usb/catc.c
--- a/drivers/usb/catc.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,965 +0,0 @@
-/*
- *  Copyright (c) 2001 Vojtech Pavlik
- *
- *  CATC EL1210A NetMate USB Ethernet driver
- *
- *  Sponsored by SuSE
- *
- *  Based on the work of
- *		Donald Becker
- * 
- *  Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
- *    - adds support for Belkin F5U011
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/ethtool.h>
-#include <linux/crc32.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-
-#undef DEBUG
-
-#include <linux/usb.h>
-
-/*
- * Version information.
- */
-
-#define DRIVER_VERSION "v2.8"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
-#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
-#define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-/*
- * Some defines.
- */ 
-
-#define STATS_UPDATE		(HZ)	/* Time between stats updates */
-#define TX_TIMEOUT		(5*HZ)	/* Max time the queue can be stopped */
-#define PKT_SZ			1536	/* Max Ethernet packet size */
-#define RX_MAX_BURST		15	/* Max packets per rx buffer (> 0, < 16) */
-#define TX_MAX_BURST		15	/* Max full sized packets per tx buffer (> 0) */
-#define CTRL_QUEUE		16	/* Max control requests in flight (power of two) */
-#define RX_PKT_SZ		1600	/* Max size of receive packet for F5U011 */
-
-/*
- * Control requests.
- */
-
-enum control_requests {
-	ReadMem =	0xf1,
-	GetMac =	0xf2,
-	Reset =		0xf4,
-	SetMac =	0xf5,
-	SetRxMode =     0xf5,  /* F5U011 only */
-	WriteROM =	0xf8,
-	SetReg =	0xfa,
-	GetReg =	0xfb,
-	WriteMem =	0xfc,
-	ReadROM =	0xfd,
-};
-
-/*
- * Registers.
- */
-
-enum register_offsets {
-	TxBufCount =	0x20,
-	RxBufCount =	0x21,
-	OpModes =	0x22,
-	TxQed =		0x23,
-	RxQed =		0x24,
-	MaxBurst =	0x25,
-	RxUnit =	0x60,
-	EthStatus =	0x61,
-	StationAddr0 =	0x67,
-	EthStats =	0x69,
-	LEDCtrl =	0x81,
-};
-
-enum eth_stats {
-	TxSingleColl =	0x00,
-        TxMultiColl =	0x02,
-        TxExcessColl =	0x04,
-        RxFramErr =	0x06,
-};
-
-enum op_mode_bits {
-	Op3MemWaits =	0x03,
-	OpLenInclude =	0x08,
-	OpRxMerge =	0x10,
-	OpTxMerge =	0x20,
-	OpWin95bugfix =	0x40,
-	OpLoopback =	0x80,
-};
-
-enum rx_filter_bits {
-	RxEnable =	0x01,
-	RxPolarity =	0x02,
-	RxForceOK =	0x04,
-	RxMultiCast =	0x08,
-	RxPromisc =	0x10,
-	AltRxPromisc =  0x20, /* F5U011 uses different bit */
-};
-
-enum led_values {
-	LEDFast = 	0x01,
-	LEDSlow =	0x02,
-	LEDFlash =	0x03,
-	LEDPulse =	0x04,
-	LEDLink =	0x08,
-};
-
-enum link_status {
-	LinkNoChange = 0,
-	LinkGood     = 1,
-	LinkBad      = 2
-};
-
-/*
- * The catc struct.
- */
-
-#define CTRL_RUNNING	0
-#define RX_RUNNING	1
-#define TX_RUNNING	2
-
-struct catc {
-	struct net_device *netdev;
-	struct usb_device *usbdev;
-
-	struct net_device_stats stats;
-	unsigned long flags;
-
-	unsigned int tx_ptr, tx_idx;
-	unsigned int ctrl_head, ctrl_tail;
-	spinlock_t tx_lock, ctrl_lock;
-
-	u8 tx_buf[2][TX_MAX_BURST * (PKT_SZ + 2)];
-	u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)];
-	u8 irq_buf[2];
-	u8 ctrl_buf[64];
-	struct usb_ctrlrequest ctrl_dr;
-
-	struct timer_list timer;
-	u8 stats_buf[8];
-	u16 stats_vals[4];
-	unsigned long last_stats;
-
-	u8 multicast[64];
-
-	struct ctrl_queue {
-		u8 dir;
-		u8 request;
-		u16 value;
-		u16 index;
-		void *buf;
-		int len;
-		void (*callback)(struct catc *catc, struct ctrl_queue *q);
-	} ctrl_queue[CTRL_QUEUE];
-
-	struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
-
-	u8 is_f5u011;	/* Set if device is an F5U011 */
-	u8 rxmode[2];	/* Used for F5U011 */
-	atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
-};
-
-/*
- * Useful macros.
- */
-
-#define catc_get_mac(catc, mac)				catc_ctrl_msg(catc, USB_DIR_IN,  GetMac, 0, 0, mac,  6)
-#define catc_reset(catc)				catc_ctrl_msg(catc, USB_DIR_OUT, Reset, 0, 0, NULL, 0)
-#define catc_set_reg(catc, reg, val)			catc_ctrl_msg(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0)
-#define catc_get_reg(catc, reg, buf)			catc_ctrl_msg(catc, USB_DIR_IN,  GetReg, 0, reg, buf, 1)
-#define catc_write_mem(catc, addr, buf, size)		catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
-#define catc_read_mem(catc, addr, buf, size)		catc_ctrl_msg(catc, USB_DIR_IN,  ReadMem, 0, addr, buf, size)
-
-#define f5u011_rxmode(catc, rxmode)			catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
-#define f5u011_rxmode_async(catc, rxmode)		catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
-#define f5u011_mchash_async(catc, hash)			catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
-
-#define catc_set_reg_async(catc, reg, val)		catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
-#define catc_get_reg_async(catc, reg, cb)		catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
-#define catc_write_mem_async(catc, addr, buf, size)	catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
-
-/*
- * Receive routines.
- */
-
-static void catc_rx_done(struct urb *urb)
-{
-	struct catc *catc = urb->context;
-	u8 *pkt_start = urb->transfer_buffer;
-	struct sk_buff *skb;
-	int pkt_len, pkt_offset = 0;
-
-	if (!catc->is_f5u011) {
-		clear_bit(RX_RUNNING, &catc->flags);
-		pkt_offset = 2;
-	}
-
-	if (urb->status) {
-		dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
-		return;
-	}
-
-	do {
-		if(!catc->is_f5u011) {
-			pkt_len = le16_to_cpup((u16*)pkt_start);
-			if (pkt_len > urb->actual_length) {
-				catc->stats.rx_length_errors++;
-				catc->stats.rx_errors++;
-				break;
-			}
-		} else {
-			pkt_len = urb->actual_length;
-		}
-
-		if (!(skb = dev_alloc_skb(pkt_len)))
-			return;
-
-		skb->dev = catc->netdev;
-		eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
-		skb_put(skb, pkt_len);
-
-		skb->protocol = eth_type_trans(skb, catc->netdev);
-		netif_rx(skb);
-
-		catc->stats.rx_packets++;
-		catc->stats.rx_bytes += pkt_len;
-
-		/* F5U011 only does one packet per RX */
-		if (catc->is_f5u011)
-			break;
-		pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
-
-	} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
-
-	catc->netdev->last_rx = jiffies;
-
-	if (catc->is_f5u011) {
-		if (atomic_read(&catc->recq_sz)) {
-			int status;
-			atomic_dec(&catc->recq_sz);
-			dbg("getting extra packet");
-			urb->dev = catc->usbdev;
-			if ((status = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
-				dbg("submit(rx_urb) status %d", status);
-			}
-		} else {
-			clear_bit(RX_RUNNING, &catc->flags);
-		}
-	}
-}
-
-static void catc_irq_done(struct urb *urb)
-{
-	struct catc *catc = urb->context;
-	u8 *data = urb->transfer_buffer;
-	int status;
-	unsigned int hasdata = 0, linksts = LinkNoChange;
-
-	if (!catc->is_f5u011) {
-		hasdata = data[1] & 0x80;
-		if (data[1] & 0x40)
-			linksts = LinkGood;
-		else if (data[1] & 0x20)
-			linksts = LinkBad;
-	} else {
-		hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
-		if (data[0] == 0x90)
-			linksts = LinkGood;
-		else if (data[0] == 0xA0)
-			linksts = LinkBad;
-	}
-
-	if (urb->status) {
-		dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
-		return;
-	}
-
-	if (linksts == LinkGood) {
-		netif_carrier_on(catc->netdev);
-		dbg("link ok");
-	}
-
-	if (linksts == LinkBad) {
-		netif_carrier_off(catc->netdev);
-		dbg("link bad");
-	}
-
-	if (hasdata) {
-		if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
-			if (catc->is_f5u011)
-				atomic_inc(&catc->recq_sz);
-		} else {
-			catc->rx_urb->dev = catc->usbdev;
-			if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
-				err("submit(rx_urb) status %d", status);
-			}
-		} 
-	}
-}
-
-/*
- * Transmit routines.
- */
-
-static void catc_tx_run(struct catc *catc)
-{
-	int status;
-
-	if (catc->is_f5u011)
-		catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
-
-	catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
-	catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
-	catc->tx_urb->dev = catc->usbdev;
-
-	if ((status = usb_submit_urb(catc->tx_urb, GFP_KERNEL)) < 0)
-		err("submit(tx_urb), status %d", status);
-
-	catc->tx_idx = !catc->tx_idx;
-	catc->tx_ptr = 0;
-
-	catc->netdev->trans_start = jiffies;
-}
-
-static void catc_tx_done(struct urb *urb)
-{
-	struct catc *catc = urb->context;
-	unsigned long flags;
-
-	if (urb->status == -ECONNRESET) {
-		dbg("Tx Reset.");
-		urb->transfer_flags &= ~USB_ASYNC_UNLINK;
-		urb->status = 0;
-		catc->netdev->trans_start = jiffies;
-		catc->stats.tx_errors++;
-		clear_bit(TX_RUNNING, &catc->flags);
-		netif_wake_queue(catc->netdev);
-		return;
-	}
-
-	if (urb->status) {
-		dbg("tx_done, status %d, length %d", urb->status, urb->actual_length);
-		return;
-	}
-
-	spin_lock_irqsave(&catc->tx_lock, flags);
-
-	if (catc->tx_ptr)
-		catc_tx_run(catc);
-	else
-		clear_bit(TX_RUNNING, &catc->flags);
-
-	netif_wake_queue(catc->netdev);
-
-	spin_unlock_irqrestore(&catc->tx_lock, flags);
-}
-
-static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
-{
-	struct catc *catc = netdev->priv;
-	unsigned long flags;
-	char *tx_buf;
-
-	spin_lock_irqsave(&catc->tx_lock, flags);
-
-	catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
-	tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
-	*((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
-	memcpy(tx_buf + 2, skb->data, skb->len);
-	catc->tx_ptr += skb->len + 2;
-
-	if (!test_and_set_bit(TX_RUNNING, &catc->flags))
-		catc_tx_run(catc);
-
-	if ((catc->is_f5u011 && catc->tx_ptr)
-	     || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
-		netif_stop_queue(netdev);
-
-	spin_unlock_irqrestore(&catc->tx_lock, flags);
-
-	catc->stats.tx_bytes += skb->len;
-	catc->stats.tx_packets++;
-
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-static void catc_tx_timeout(struct net_device *netdev)
-{
-	struct catc *catc = netdev->priv;
-
-	warn("Transmit timed out.");
-	catc->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
-	usb_unlink_urb(catc->tx_urb);
-}
-
-/*
- * Control messages.
- */
-
-static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
-{
-        int retval = usb_control_msg(catc->usbdev,
-		dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0),
-		 request, 0x40 | dir, value, index, buf, len, HZ);
-        return retval < 0 ? retval : 0;
-}
-
-static void catc_ctrl_run(struct catc *catc)
-{
-	struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
-	struct usb_device *usbdev = catc->usbdev;
-	struct urb *urb = catc->ctrl_urb;
-	struct usb_ctrlrequest *dr = &catc->ctrl_dr;
-	int status;
-
-	dr->bRequest = q->request;
-	dr->bRequestType = 0x40 | q->dir;
-	dr->wValue = cpu_to_le16(q->value);
-	dr->wIndex = cpu_to_le16(q->index);
-	dr->wLength = cpu_to_le16(q->len);
-
-        urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);
-	urb->transfer_buffer_length = q->len;
-	urb->transfer_buffer = catc->ctrl_buf;
-	urb->setup_packet = (void *) dr;
-	urb->dev = usbdev;
-
-	if (!q->dir && q->buf && q->len)
-		memcpy(catc->ctrl_buf, q->buf, q->len);
-
-	if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))
-		err("submit(ctrl_urb) status %d", status);
-}
-
-static void catc_ctrl_done(struct urb *urb)
-{
-	struct catc *catc = urb->context;
-	struct ctrl_queue *q;
-	long flags;
-
-	if (urb->status)
-		dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
-
-	spin_lock_irqsave(&catc->ctrl_lock, flags);
-
-	q = catc->ctrl_queue + catc->ctrl_tail;
-
-	if (q->dir) {
-		if (q->buf && q->len)
-			memcpy(q->buf, catc->ctrl_buf, q->len);
-		else
-			q->buf = catc->ctrl_buf;
-	}
-
-	if (q->callback)
-		q->callback(catc, q);
-
-	catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
-
-	if (catc->ctrl_head != catc->ctrl_tail)
-		catc_ctrl_run(catc);
-	else
-		clear_bit(CTRL_RUNNING, &catc->flags);
-
-	spin_unlock_irqrestore(&catc->ctrl_lock, flags);
-}
-
-static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value,
-	u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q))
-{
-	struct ctrl_queue *q;
-	int retval = 0;
-	long flags;
-
-	spin_lock_irqsave(&catc->ctrl_lock, flags);
-	
-	q = catc->ctrl_queue + catc->ctrl_head;
-
-	q->dir = dir;
-	q->request = request;
-	q->value = value;
-	q->index = index;
-	q->buf = buf;
-	q->len = len;
-	q->callback = callback;
-
-	catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1);
-
-	if (catc->ctrl_head == catc->ctrl_tail) {
-		err("ctrl queue full");
-		catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
-		retval = -1;
-	}
-
-	if (!test_and_set_bit(CTRL_RUNNING, &catc->flags))
-		catc_ctrl_run(catc);
-
-	spin_unlock_irqrestore(&catc->ctrl_lock, flags);
-
-	return retval;
-}
-
-/*
- * Statistics.
- */
-
-static void catc_stats_done(struct catc *catc, struct ctrl_queue *q)
-{
-	int index = q->index - EthStats;
-	u16 data, last;
-
-	catc->stats_buf[index] = *((char *)q->buf);
-
-	if (index & 1)
-		return;
-
-	data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1];
-	last = catc->stats_vals[index >> 1];
-
-	switch (index) {
-		case TxSingleColl:
-		case TxMultiColl:
-			catc->stats.collisions += data - last;
-			break;
-		case TxExcessColl:
-			catc->stats.tx_aborted_errors += data - last;
-			catc->stats.tx_errors += data - last;
-			break;
-		case RxFramErr:
-			catc->stats.rx_frame_errors += data - last;
-			catc->stats.rx_errors += data - last;
-			break;
-	}
-
-	catc->stats_vals[index >> 1] = data;
-}
-
-static void catc_stats_timer(unsigned long data)
-{
-	struct catc *catc = (void *) data;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done);
-
-	mod_timer(&catc->timer, jiffies + STATS_UPDATE);
-}
-
-static struct net_device_stats *catc_get_stats(struct net_device *netdev)
-{
-	struct catc *catc = netdev->priv;
-	return &catc->stats;
-}
-
-/*
- * Receive modes. Broadcast, Multicast, Promisc.
- */
-
-static void catc_multicast(unsigned char *addr, u8 *multicast)
-{
-	u32 crc;
-
-	crc = ether_crc_le(6, addr);
-	multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
-}
-
-static void catc_set_multicast_list(struct net_device *netdev)
-{
-	struct catc *catc = netdev->priv;
-	struct dev_mc_list *mc;
-	u8 broadcast[6];
-	u8 rx = RxEnable | RxPolarity | RxMultiCast;
-	int i;
-
-	memset(broadcast, 0xff, 6);
-	memset(catc->multicast, 0, 64);
-
-	catc_multicast(broadcast, catc->multicast);
-	catc_multicast(netdev->dev_addr, catc->multicast);
-
-	if (netdev->flags & IFF_PROMISC) {
-		memset(catc->multicast, 0xff, 64);
-		rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
-	} 
-
-	if (netdev->flags & IFF_ALLMULTI) {
-		memset(catc->multicast, 0xff, 64);
-	} else {
-		for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
-			u32 crc = ether_crc_le(6, mc->dmi_addr);
-			if (!catc->is_f5u011) {
-				catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
-			} else {
-				catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
-			}
-		}
-	}
-	if (!catc->is_f5u011) {
-		catc_set_reg_async(catc, RxUnit, rx);
-		catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
-	} else {
-		f5u011_mchash_async(catc, catc->multicast);
-		if (catc->rxmode[0] != rx) {
-			catc->rxmode[0] = rx;
-			dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
-			f5u011_rxmode_async(catc, catc->rxmode);
-		}
-	}
-}
-
-/*
- * ioctl's
- */
-static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
-{
-        struct catc *catc = dev->priv;
-        u32 cmd;
-	char tmp[40];
-        
-        if (get_user(cmd, (u32 *)useraddr))
-                return -EFAULT;
-
-        switch (cmd) {
-        /* get driver info */
-        case ETHTOOL_GDRVINFO: {
-                struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-                strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
-                strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
-		sprintf(tmp, "usb%d:%d", catc->usbdev->bus->busnum, catc->usbdev->devnum);
-                strncpy(info.bus_info, tmp,ETHTOOL_BUSINFO_LEN);
-                if (copy_to_user(useraddr, &info, sizeof(info)))
-                        return -EFAULT;
-                return 0;
-        }
-
-	/* get settings */
-	case ETHTOOL_GSET:
-		if (catc->is_f5u011) {
-			struct ethtool_cmd ecmd = { ETHTOOL_GSET, 
-						    SUPPORTED_10baseT_Half | SUPPORTED_TP, 
-						    ADVERTISED_10baseT_Half | ADVERTISED_TP, 
-						    SPEED_10, 
-						    DUPLEX_HALF, 
-						    PORT_TP, 
-						    0, 
-						    XCVR_INTERNAL, 
-						    AUTONEG_DISABLE, 
-						    1, 
-						    1 
-			};
-			if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-				return -EFAULT;
-			return 0;
-		} else {
-			return -EOPNOTSUPP;
-		}
-
-        /* get link status */
-        case ETHTOOL_GLINK: {
-                struct ethtool_value edata = {ETHTOOL_GLINK};
-                edata.data = netif_carrier_ok(dev);
-                if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                        return -EFAULT;
-                return 0;
-        }
-	}
-        
-        return -EOPNOTSUPP;
-}
-
-static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-        switch(cmd) {
-        case SIOCETHTOOL:
-                return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-        default:
-                return -EOPNOTSUPP;
-        }
-}
-
-
-/*
- * Open, close.
- */
-
-static int catc_open(struct net_device *netdev)
-{
-	struct catc *catc = netdev->priv;
-	int status;
-
-	catc->irq_urb->dev = catc->usbdev;
-	if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) {
-		err("submit(irq_urb) status %d", status);
-		return -1;
-	}
-
-	netif_start_queue(netdev);
-
-	if (!catc->is_f5u011)
-		mod_timer(&catc->timer, jiffies + STATS_UPDATE);
-
-	return 0;
-}
-
-static int catc_stop(struct net_device *netdev)
-{
-	struct catc *catc = netdev->priv;
-
-	netif_stop_queue(netdev);
-
-	if (!catc->is_f5u011)
-		del_timer_sync(&catc->timer);
-
-	usb_unlink_urb(catc->rx_urb);
-	usb_unlink_urb(catc->tx_urb);
-	usb_unlink_urb(catc->irq_urb);
-	usb_unlink_urb(catc->ctrl_urb);
-
-	return 0;
-}
-
-/*
- * USB probe, disconnect.
- */
-
-static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id)
-{
-	struct net_device *netdev;
-	struct catc *catc;
-	u8 broadcast[6];
-	int i, pktsz;
-
-	if (usb_set_interface(usbdev, ifnum, 1)) {
-                err("Can't set altsetting 1.");
-		return NULL;
-	}
-
-	catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
-	if (!catc)
-		return NULL;
-
-	memset(catc, 0, sizeof(struct catc));
-
-	netdev = init_etherdev(0, 0);
-	if (!netdev) {
-		kfree(catc);
-		return NULL;
-	}
-
-	netdev->open = catc_open;
-	netdev->hard_start_xmit = catc_hard_start_xmit;
-	netdev->stop = catc_stop;
-	netdev->get_stats = catc_get_stats;
-	netdev->tx_timeout = catc_tx_timeout;
-	netdev->watchdog_timeo = TX_TIMEOUT;
-	netdev->set_multicast_list = catc_set_multicast_list;
-	netdev->do_ioctl = catc_ioctl;
-	netdev->priv = catc;
-
-	catc->usbdev = usbdev;
-	catc->netdev = netdev;
-
-	catc->tx_lock = SPIN_LOCK_UNLOCKED;
-	catc->ctrl_lock = SPIN_LOCK_UNLOCKED;
-
-	init_timer(&catc->timer);
-	catc->timer.data = (long) catc;
-	catc->timer.function = catc_stats_timer;
-
-	catc->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
-	catc->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	catc->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	catc->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
-	    (!catc->rx_urb) || (!catc->irq_urb)) {
-		err("No free urbs available.");
-		if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
-		if (catc->tx_urb)   usb_free_urb(catc->tx_urb);
-		if (catc->rx_urb)   usb_free_urb(catc->rx_urb);
-		if (catc->irq_urb)  usb_free_urb(catc->irq_urb);
-		kfree(netdev);
-		kfree(catc);
-		return NULL;
-	}
-
-	/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
-	if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
-	   catc->usbdev->descriptor.bcdDevice == 0x0130	) {
-		dbg("Testing for f5u011");
-		catc->is_f5u011 = 1;		
-		atomic_set(&catc->recq_sz, 0);
-		pktsz = RX_PKT_SZ;
-	} else {
-		pktsz = RX_MAX_BURST * (PKT_SZ + 2);
-	}
-	
-	FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
-		NULL, NULL, 0, catc_ctrl_done, catc);
-
-	FILL_BULK_URB(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),
-		NULL, 0, catc_tx_done, catc);
-
-	FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
-		catc->rx_buf, pktsz, catc_rx_done, catc);
-
-	FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
-                catc->irq_buf, 2, catc_irq_done, catc, 1);
-
-	if (!catc->is_f5u011) {
-		dbg("Checking memory size\n");
-
-		i = 0x12345678;
-		catc_write_mem(catc, 0x7a80, &i, 4);
-		i = 0x87654321;	
-		catc_write_mem(catc, 0xfa80, &i, 4);
-		catc_read_mem(catc, 0x7a80, &i, 4);
-	  
-		switch (i) {
-		case 0x12345678:
-			catc_set_reg(catc, TxBufCount, 8);
-			catc_set_reg(catc, RxBufCount, 32);
-			dbg("64k Memory\n");
-			break;
-		default:
-			warn("Couldn't detect memory size, assuming 32k");
-		case 0x87654321:
-			catc_set_reg(catc, TxBufCount, 4);
-			catc_set_reg(catc, RxBufCount, 16);
-			dbg("32k Memory\n");
-			break;
-		}
-	  
-		dbg("Getting MAC from SEEROM.");
-	  
-		catc_get_mac(catc, netdev->dev_addr);
-		
-		dbg("Setting MAC into registers.");
-	  
-		for (i = 0; i < 6; i++)
-			catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
-		
-		dbg("Filling the multicast list.");
-	  
-		memset(broadcast, 0xff, 6);
-		catc_multicast(broadcast, catc->multicast);
-		catc_multicast(netdev->dev_addr, catc->multicast);
-		catc_write_mem(catc, 0xfa80, catc->multicast, 64);
-		
-		dbg("Clearing error counters.");
-		
-		for (i = 0; i < 8; i++)
-			catc_set_reg(catc, EthStats + i, 0);
-		catc->last_stats = jiffies;
-		
-		dbg("Enabling.");
-		
-		catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
-		catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
-		catc_set_reg(catc, LEDCtrl, LEDLink);
-		catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
-	} else {
-		dbg("Performing reset\n");
-		catc_reset(catc);
-		catc_get_mac(catc, netdev->dev_addr);
-		
-		dbg("Setting RX Mode");
-		catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
-		catc->rxmode[1] = 0;
-		f5u011_rxmode(catc, catc->rxmode);
-	}
-	dbg("Init done.");
-	printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
-	       netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
-	       usbdev->bus->busnum, usbdev->devnum, ifnum);
-	for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
-	printk("%2.2x.\n", netdev->dev_addr[i]);
-	return catc;
-}
-
-static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
-{
-	struct catc *catc = dev_ptr;
-	unregister_netdev(catc->netdev);
-	usb_free_urb(catc->ctrl_urb);
-	usb_free_urb(catc->tx_urb);
-	usb_free_urb(catc->rx_urb);
-	usb_free_urb(catc->irq_urb);
-	kfree(catc->netdev);
-	kfree(catc);
-}
-
-/*
- * Module functions and tables.
- */
-
-static struct usb_device_id catc_id_table [] = {
-	{ USB_DEVICE(0x0423, 0xa) },	/* CATC Netmate, Belkin F5U011 */
-	{ USB_DEVICE(0x0423, 0xc) },	/* CATC Netmate II, Belkin F5U111 */
-	{ USB_DEVICE(0x08d1, 0x1) },	/* smartBridges smartNIC */
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, catc_id_table);
-
-static struct usb_driver catc_driver = {
-	name:		"catc",
-	probe:		catc_probe,
-	disconnect:	catc_disconnect,
-	id_table:	catc_id_table,
-};
-
-static int __init catc_init(void)
-{
-	info(DRIVER_VERSION " " DRIVER_DESC);
-	usb_register(&catc_driver);
-	return 0;
-}
-
-static void __exit catc_exit(void)
-{
-	usb_deregister(&catc_driver);
-}
-
-module_init(catc_init);
-module_exit(catc_exit);
diff -Nru a/drivers/usb/class/Config.help b/drivers/usb/class/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,44 @@
+CONFIG_USB_ACM
+  This driver supports USB modems and ISDN adapters which support the
+  Communication Device Class Abstract Control Model interface.
+  Please read <file:Documentation/usb/acm.txt> for details.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called acm.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_AUDIO
+  Say Y here if you want to connect USB audio equipment such as
+  speakers to your computer's USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called audio.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_BLUETOOTH_TTY
+  Say Y here if you want to connect a USB Bluetooth device to your
+  computer's USB port. You will need the Bluetooth stack (available
+  at <http://developer.axis.com/software/index.shtml>) to fully use
+  the device.
+
+  This driver implements a tty inteface to a Bluetooth device.  If
+  you want to use a socket based Bluetooth stack (like the BlueZ
+  stack), do not use this driver.
+
+  If in doubt, say N here.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called bluetty.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_PRINTER
+  Say Y here if you want to connect a USB printer to your computer's
+  USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called printer.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/class/Config.in b/drivers/usb/class/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,19 @@
+#
+# USB Class driver configuration
+#
+comment 'USB Device Class drivers'
+dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND
+dep_tristate '  USB Bluetooth TTY support' CONFIG_USB_BLUETOOTH_TTY $CONFIG_USB
+dep_tristate '  USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
+dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+
+
+# Turn on CONFIG_USB_CLASS if any of the drivers are compiled into the kernel
+# to make our Makefile logic a bit simpler.
+if [ "$CONFIG_USB_AUDIO" = "y" -o "$CONFIG_USB_BLUETOOTH_TTY" = "y" ]; then
+   define_bool CONFIG_USB_CLASS y
+fi
+if [ "$CONFIG_USB_ACM" = "y" -o "$CONFIG_USB_PRINTER" = "y" ]; then
+   define_bool CONFIG_USB_CLASS y
+fi
+   
diff -Nru a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,14 @@
+#
+# Makefile for USB Class drivers
+# (one step up from the misc category)
+#
+
+O_TARGET	:= usb-class.o
+
+obj-$(CONFIG_USB_ACM)		+= cdc-acm.o
+obj-$(CONFIG_USB_AUDIO)		+= audio.o
+obj-$(CONFIG_USB_BLUETOOTH_TTY)	+= bluetty.o
+obj-$(CONFIG_USB_PRINTER)	+= printer.o
+
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/class/Makefile.lib b/drivers/usb/class/Makefile.lib
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/Makefile.lib	Sun Apr 14 12:16:54 2002
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_CATC)		+= crc32.o
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/audio.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,3876 @@
+/*****************************************************************************/
+
+/*
+ *	audio.c  --  USB Audio Class driver
+ *
+ *	Copyright (C) 1999, 2000, 2001
+ *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
+ *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *	This program is free software; you can redistribute it and/or 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.
+ *
+ * Debugging:
+ * 	Use the 'lsusb' utility to dump the descriptors.
+ *
+ * 1999-09-07:  Alan Cox
+ *		Parsing Audio descriptor patch
+ * 1999-09-08:  Thomas Sailer
+ *		Added OSS compatible data io functions; both parts of the
+ *		driver remain to be glued together
+ * 1999-09-10:  Thomas Sailer
+ *		Beautified the driver. Added sample format conversions.
+ *		Still not properly glued with the parsing code.
+ *		The parsing code seems to have its problems btw,
+ *		Since it parses all available configs but doesn't
+ *		store which iface/altsetting belongs to which config.
+ * 1999-09-20:  Thomas Sailer
+ *		Threw out Alan's parsing code and implemented my own one.
+ *		You cannot reasonnably linearly parse audio descriptors,
+ *		especially the AudioClass descriptors have to be considered
+ *		pointer lists. Mixer parsing untested, due to lack of device.
+ *		First stab at synch pipe implementation, the Dallas USB DAC
+ *		wants to use an Asynch out pipe. usb_audio_state now basically
+ *		only contains lists of mixer and wave devices. We can therefore
+ *		now have multiple mixer/wave devices per USB device.
+ * 1999-10-28:  Thomas Sailer
+ *		Converted to URB API. Fixed a taskstate/wakeup semantics mistake
+ *		that made the driver consume all available CPU cycles.
+ *		Now runs stable on UHCI-Acher/Fliegl/Sailer.
+ * 1999-10-31:  Thomas Sailer
+ *		Audio can now be unloaded if it is not in use by any mixer
+ *		or dsp client (formerly you had to disconnect the audio devices
+ *		from the USB port)
+ *		Finally, about three months after ordering, my "Maxxtro SPK222"
+ *		speakers arrived, isn't disdata a great mail order company 8-)
+ *		Parse class specific endpoint descriptor of the audiostreaming
+ *		interfaces and take the endpoint attributes from there.
+ *		Unbelievably, the Philips USB DAC has a sampling rate range
+ *		of over a decade, yet does not support the sampling rate control!
+ *		No wonder it sounds so bad, has very audible sampling rate
+ *		conversion distortion. Don't try to listen to it using
+ *		decent headphones!
+ *		"Let's make things better" -> but please Philips start with your
+ *		own stuff!!!!
+ * 1999-11-02:  Thomas Sailer
+ *		It takes the Philips boxes several seconds to acquire synchronisation
+ *		that means they won't play short sounds. Should probably maintain
+ *		the ISO datastream even if there's nothing to play.
+ *		Fix counting the total_bytes counter, RealPlayer G2 depends on it.
+ * 1999-12-20:  Thomas Sailer
+ *		Fix bad bug in conversion to per interface probing.
+ *		disconnect was called multiple times for the audio device,
+ *		leading to a premature freeing of the audio structures
+ * 2000-05-13:  Thomas Sailer
+ *		I don't remember who changed the find_format routine,
+ *              but the change was completely broken for the Dallas
+ *              chip. Anyway taking sampling rate into account in find_format
+ *              is bad and should not be done unless there are devices with
+ *              completely broken audio descriptors. Unless someone shows
+ *              me such a descriptor, I will not allow find_format to
+ *              take the sampling rate into account.
+ *              Also, the former find_format made:
+ *              - mpg123 play mono instead of stereo
+ *              - sox completely fail for wav's with sample rates < 44.1kHz
+ *                  for the Dallas chip.
+ *              Also fix a rather long standing problem with applications that
+ *              use "small" writes producing no sound at all.
+ * 2000-05-15:  Thomas Sailer
+ *		My fears came true, the Philips camera indeed has pretty stupid
+ *              audio descriptors.
+ * 2000-05-17:  Thomas Sailer
+ *		Nemsoft spotted my stupid last minute change, thanks
+ * 2000-05-19:  Thomas Sailer
+ *		Fixed FEATURE_UNIT thinkos found thanks to the KC Technology
+ *              Xtend device. Basically the driver treated FEATURE_UNIT's sourced
+ *              by mono terminals as stereo.
+ * 2000-05-20:  Thomas Sailer
+ *		SELECTOR support (and thus selecting record channels from the mixer).
+ *              Somewhat peculiar due to OSS interface limitations. Only works
+ *              for channels where a "slider" is already in front of it (i.e.
+ *              a MIXER unit or a FEATURE unit with volume capability).
+ * 2000-11-26:  Thomas Sailer
+ *              Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for
+ *              its 8 bit modes, but expects signed data (and should therefore have used PCM).
+ * 2001-03-10:  Thomas Sailer
+ *              provide abs function, prevent picking up a bogus kernel macro
+ *              for abs. Bug report by Andrew Morton <andrewm@uow.edu.au>
+ * 2001-06-16:  Bryce Nesbitt <bryce@obviously.com>
+ *              Fix SNDCTL_DSP_STEREO API violation
+ */
+
+/*
+ * Strategy:
+ *
+ * Alan Cox and Thomas Sailer are starting to dig at opposite ends and
+ * are hoping to meet in the middle, just like tunnel diggers :)
+ * Alan tackles the descriptor parsing, Thomas the actual data IO and the
+ * OSS compatible interface.
+ *
+ * Data IO implementation issues
+ *
+ * A mmap'able ring buffer per direction is implemented, because
+ * almost every OSS app expects it. It is however impractical to
+ * transmit/receive USB data directly into and out of the ring buffer,
+ * due to alignment and synchronisation issues. Instead, the ring buffer
+ * feeds a constant time delay line that handles the USB issues.
+ *
+ * Now we first try to find an alternate setting that exactly matches
+ * the sample format requested by the user. If we find one, we do not
+ * need to perform any sample rate conversions. If there is no matching
+ * altsetting, we choose the closest one and perform sample format
+ * conversions. We never do sample rate conversion; these are too
+ * expensive to be performed in the kernel.
+ *
+ * Current status: no known HCD-specific issues.
+ *
+ * Generally: Due to the brokenness of the Audio Class spec
+ * it seems generally impossible to write a generic Audio Class driver,
+ * so a reasonable driver should implement the features that are actually
+ * used.
+ *
+ * Parsing implementation issues
+ *
+ * One cannot reasonably parse the AudioClass descriptors linearly.
+ * Therefore the current implementation features routines to look
+ * for a specific descriptor in the descriptor list.
+ *
+ * How does the parsing work? First, all interfaces are searched
+ * for an AudioControl class interface. If found, the config descriptor
+ * that belongs to the current configuration is fetched from the device.
+ * Then the HEADER descriptor is fetched. It contains a list of
+ * all AudioStreaming and MIDIStreaming devices. This list is then walked,
+ * and all AudioStreaming interfaces are classified into input and output
+ * interfaces (according to the endpoint0 direction in altsetting1) (MIDIStreaming
+ * is currently not supported). The input & output list is then used
+ * to group inputs and outputs together and issued pairwise to the
+ * AudioStreaming class parser. Finally, all OUTPUT_TERMINAL descriptors
+ * are walked and issued to the mixer construction routine.
+ *
+ * The AudioStreaming parser simply enumerates all altsettings belonging
+ * to the specified interface. It looks for AS_GENERAL and FORMAT_TYPE
+ * class specific descriptors to extract the sample format/sample rate
+ * data. Only sample format types PCM and PCM8 are supported right now, and
+ * only FORMAT_TYPE_I is handled. The isochronous data endpoint needs to
+ * be the first endpoint of the interface, and the optional synchronisation
+ * isochronous endpoint the second one.
+ *
+ * Mixer construction works as follows: The various TERMINAL and UNIT
+ * descriptors span a tree from the root (OUTPUT_TERMINAL) through the
+ * intermediate nodes (UNITs) to the leaves (INPUT_TERMINAL). We walk
+ * that tree in a depth first manner. FEATURE_UNITs may contribute volume,
+ * bass and treble sliders to the mixer, MIXER_UNITs volume sliders.
+ * The terminal type encoded in the INPUT_TERMINALs feeds a heuristic
+ * to determine "meaningful" OSS slider numbers, however we will see
+ * how well this works in practice. Other features are not used at the
+ * moment, they seem less often used. Also, it seems difficult at least
+ * to construct recording source switches from SELECTOR_UNITs, but
+ * since there are not many USB ADC's available, we leave that for later.
+ */
+
+/*****************************************************************************/
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/module.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <linux/usb.h>
+
+#include "audio.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "Alan Cox <alan@lxorguk.ukuu.org.uk>, Thomas Sailer (sailer@ife.ee.ethz.ch)"
+#define DRIVER_DESC "USB Audio Class driver"
+
+#define AUDIO_DEBUG 1
+
+#define SND_DEV_DSP16   5 
+
+#define dprintk(x)
+
+#undef abs
+extern int abs(int __x) __attribute__ ((__const__)); /* Shut up warning */
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Linked list of all audio devices...
+ */
+static struct list_head audiodevs = LIST_HEAD_INIT(audiodevs);
+static DECLARE_MUTEX(open_sem);
+
+/*
+ * wait queue for processes wanting to open an USB audio device
+ */
+static DECLARE_WAIT_QUEUE_HEAD(open_wait);
+
+
+#define MAXFORMATS        MAX_ALT
+#define DMABUFSHIFT       17  /* 128k worth of DMA buffer */
+#define NRSGBUF           (1U<<(DMABUFSHIFT-PAGE_SHIFT))
+
+/*
+ * This influences:
+ * - Latency
+ * - Interrupt rate
+ * - Synchronisation behaviour
+ * Don't touch this if you don't understand all of the above.
+ */
+#define DESCFRAMES  5
+#define SYNCFRAMES  DESCFRAMES
+
+#define MIXFLG_STEREOIN   1
+#define MIXFLG_STEREOOUT  2
+
+struct mixerchannel {
+	__u16 value;
+	__u16 osschannel;  /* number of the OSS channel */
+	__s16 minval, maxval;
+	__u16 slctunitid;
+	__u8 unitid;
+	__u8 selector;
+	__u8 chnum;
+	__u8 flags;
+};
+
+struct audioformat {
+	unsigned int format;
+	unsigned int sratelo;
+	unsigned int sratehi;
+	unsigned char altsetting;
+	unsigned char attributes;
+};
+
+struct dmabuf {
+	/* buffer data format */
+	unsigned int format;
+	unsigned int srate;
+	/* physical buffer */
+	unsigned char *sgbuf[NRSGBUF];
+	unsigned bufsize;
+	unsigned numfrag;
+	unsigned fragshift;
+	unsigned wrptr, rdptr;
+	unsigned total_bytes;
+	int count;
+	unsigned error; /* over/underrun */
+	wait_queue_head_t wait;
+	/* redundant, but makes calculations easier */
+	unsigned fragsize;
+	unsigned dmasize;
+	/* OSS stuff */
+	unsigned mapped:1;
+	unsigned ready:1;
+	unsigned ossfragshift;
+	int ossmaxfrags;
+	unsigned subdivision;
+};
+
+struct usb_audio_state;
+
+#define FLG_URB0RUNNING   1
+#define FLG_URB1RUNNING   2
+#define FLG_SYNC0RUNNING  4
+#define FLG_SYNC1RUNNING  8
+#define FLG_RUNNING      16
+#define FLG_CONNECTED    32
+
+struct my_data_urb {
+	struct urb *urb;
+};
+
+struct my_sync_urb {
+	struct urb *urb;
+};
+
+
+struct usb_audiodev {
+	struct list_head list;
+	struct usb_audio_state *state;
+	
+	/* soundcore stuff */
+	int dev_audio;
+
+	/* wave stuff */
+	mode_t open_mode;
+	spinlock_t lock;         /* DMA buffer access spinlock */
+
+	struct usbin {
+		int interface;           /* Interface number, -1 means not used */
+		unsigned int format;     /* USB data format */
+		unsigned int datapipe;   /* the data input pipe */
+		unsigned int syncpipe;   /* the synchronisation pipe - 0 for anything but adaptive IN mode */
+		unsigned int syncinterval;  /* P for adaptive IN mode, 0 otherwise */
+		unsigned int freqn;      /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */
+		unsigned int freqmax;    /* maximum sampling rate, used for buffer management */
+		unsigned int phase;      /* phase accumulator */
+		unsigned int flags;      /* see FLG_ defines */
+		
+		struct my_data_urb durb[2];  /* ISO descriptors for the data endpoint */
+		struct my_sync_urb surb[2];  /* ISO sync pipe descriptor if needed */
+		
+		struct dmabuf dma;
+	} usbin;
+
+	struct usbout {
+		int interface;           /* Interface number, -1 means not used */
+		unsigned int format;     /* USB data format */
+		unsigned int datapipe;   /* the data input pipe */
+		unsigned int syncpipe;   /* the synchronisation pipe - 0 for anything but asynchronous OUT mode */
+		unsigned int syncinterval;  /* P for asynchronous OUT mode, 0 otherwise */
+		unsigned int freqn;      /* nominal sampling rate in USB format, i.e. fs/1000 in Q10.14 */
+		unsigned int freqm;      /* momentary sampling rate in USB format, i.e. fs/1000 in Q10.14 */
+		unsigned int freqmax;    /* maximum sampling rate, used for buffer management */
+		unsigned int phase;      /* phase accumulator */
+		unsigned int flags;      /* see FLG_ defines */
+
+		struct my_data_urb durb[2];  /* ISO descriptors for the data endpoint */
+		struct my_sync_urb surb[2];  /* ISO sync pipe descriptor if needed */
+		
+		struct dmabuf dma;
+	} usbout;
+
+
+	unsigned int numfmtin, numfmtout;
+	struct audioformat fmtin[MAXFORMATS];
+	struct audioformat fmtout[MAXFORMATS];
+};  
+
+struct usb_mixerdev {
+	struct list_head list;
+	struct usb_audio_state *state;
+
+	/* soundcore stuff */
+	int dev_mixer;
+
+	unsigned char iface;  /* interface number of the AudioControl interface */
+
+	/* USB format descriptions */
+	unsigned int numch, modcnt;
+
+	/* mixch is last and gets allocated dynamically */
+	struct mixerchannel ch[0];
+};
+
+struct usb_audio_state {
+	struct list_head audiodev;
+
+	/* USB device */
+	struct usb_device *usbdev;
+
+	struct list_head audiolist;
+	struct list_head mixerlist;
+
+	unsigned count;  /* usage counter; NOTE: the usb stack is also considered a user */
+};
+
+/* private audio format extensions */
+#define AFMT_STEREO        0x80000000
+#define AFMT_ISSTEREO(x)   ((x) & AFMT_STEREO)
+#define AFMT_IS16BIT(x)    ((x) & (AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE))
+#define AFMT_ISUNSIGNED(x) ((x) & (AFMT_U8|AFMT_U16_LE|AFMT_U16_BE))
+#define AFMT_BYTESSHIFT(x) ((AFMT_ISSTEREO(x) ? 1 : 0) + (AFMT_IS16BIT(x) ? 1 : 0))
+#define AFMT_BYTES(x)      (1<<AFMT_BYTESSHFIT(x))
+
+/* --------------------------------------------------------------------- */
+
+/* prevent picking up a bogus abs macro */
+#undef abs
+extern inline int abs(int x)
+{
+        if (x < 0)
+		return -x;
+	return x;
+}
+                                
+/* --------------------------------------------------------------------- */
+
+extern inline unsigned ld2(unsigned int x)
+{
+	unsigned r = 0;
+	
+	if (x >= 0x10000) {
+		x >>= 16;
+		r += 16;
+	}
+	if (x >= 0x100) {
+		x >>= 8;
+		r += 8;
+	}
+	if (x >= 0x10) {
+		x >>= 4;
+		r += 4;
+	}
+	if (x >= 4) {
+		x >>= 2;
+		r += 2;
+	}
+	if (x >= 2)
+		r++;
+	return r;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * OSS compatible ring buffer management. The ring buffer may be mmap'ed into
+ * an application address space.
+ *
+ * I first used the rvmalloc stuff copied from bttv. Alan Cox did not like it, so
+ * we now use an array of pointers to a single page each. This saves us the
+ * kernel page table manipulations, but we have to do a page table alike mechanism
+ * (though only one indirection) in software.
+ */
+
+static void dmabuf_release(struct dmabuf *db)
+{
+	unsigned int nr;
+	void *p;
+
+	for(nr = 0; nr < NRSGBUF; nr++) {
+		if (!(p = db->sgbuf[nr]))
+			continue;
+		mem_map_unreserve(virt_to_page(p));
+		free_page((unsigned long)p);
+		db->sgbuf[nr] = NULL;
+	}
+	db->mapped = db->ready = 0;
+}
+
+static int dmabuf_init(struct dmabuf *db)
+{
+	unsigned int nr, bytepersec, bufs;
+	void *p;
+
+	/* initialize some fields */
+	db->rdptr = db->wrptr = db->total_bytes = db->count = db->error = 0;
+	/* calculate required buffer size */
+	bytepersec = db->srate << AFMT_BYTESSHIFT(db->format);
+	bufs = 1U << DMABUFSHIFT;
+	if (db->ossfragshift) {
+		if ((1000 << db->ossfragshift) < bytepersec)
+			db->fragshift = ld2(bytepersec/1000);
+		else
+			db->fragshift = db->ossfragshift;
+	} else {
+		db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
+		if (db->fragshift < 3)
+			db->fragshift = 3;
+	}
+	db->numfrag = bufs >> db->fragshift;
+	while (db->numfrag < 4 && db->fragshift > 3) {
+		db->fragshift--;
+		db->numfrag = bufs >> db->fragshift;
+	}
+	db->fragsize = 1 << db->fragshift;
+	if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
+		db->numfrag = db->ossmaxfrags;
+	db->dmasize = db->numfrag << db->fragshift;
+	for(nr = 0; nr < NRSGBUF; nr++) {
+		if (!db->sgbuf[nr]) {
+			p = (void *)get_free_page(GFP_KERNEL);
+			if (!p)
+				return -ENOMEM;
+			db->sgbuf[nr] = p;
+			mem_map_reserve(virt_to_page(p));
+		}
+		memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE);
+		if ((nr << PAGE_SHIFT) >= db->dmasize)
+			break;
+	}
+	db->bufsize = nr << PAGE_SHIFT;
+	db->ready = 1;
+	dprintk((KERN_DEBUG "usbaudio: dmabuf_init bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d "
+	         "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x srate %d\n",
+	         bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize,
+	         db->numfrag, db->dmasize, db->bufsize, db->format, db->srate));
+	return 0;
+}
+
+static int dmabuf_mmap(struct vm_area_struct *vma, struct dmabuf *db, unsigned long start, unsigned long size, pgprot_t prot)
+{
+	unsigned int nr;
+
+	if (!db->ready || db->mapped || (start | size) & (PAGE_SIZE-1) || size > db->bufsize)
+		return -EINVAL;
+	size >>= PAGE_SHIFT;
+	for(nr = 0; nr < size; nr++)
+		if (!db->sgbuf[nr])
+			return -EINVAL;
+	db->mapped = 1;
+	for(nr = 0; nr < size; nr++) {
+		if (remap_page_range(vma, start, virt_to_phys(db->sgbuf[nr]), PAGE_SIZE, prot))
+			return -EAGAIN;
+		start += PAGE_SIZE;
+	}
+	return 0;
+}
+
+static void dmabuf_copyin(struct dmabuf *db, const void *buffer, unsigned int size)
+{
+	unsigned int pgrem, rem;
+
+	db->total_bytes += size;
+	for (;;) {
+		if (size <= 0)
+			return;
+		pgrem = ((~db->wrptr) & (PAGE_SIZE-1)) + 1;
+		if (pgrem > size)
+			pgrem = size;
+		rem = db->dmasize - db->wrptr;
+		if (pgrem > rem)
+			pgrem = rem;
+		memcpy((db->sgbuf[db->wrptr >> PAGE_SHIFT]) + (db->wrptr & (PAGE_SIZE-1)), buffer, pgrem);
+		size -= pgrem;
+		(char *)buffer += pgrem;
+		db->wrptr += pgrem;
+		if (db->wrptr >= db->dmasize)
+			db->wrptr = 0;
+	}
+}
+
+static void dmabuf_copyout(struct dmabuf *db, void *buffer, unsigned int size)
+{
+	unsigned int pgrem, rem;
+
+	db->total_bytes += size;
+	for (;;) {
+		if (size <= 0)
+			return;
+		pgrem = ((~db->rdptr) & (PAGE_SIZE-1)) + 1;
+		if (pgrem > size)
+			pgrem = size;
+		rem = db->dmasize - db->rdptr;
+		if (pgrem > rem)
+			pgrem = rem;
+		memcpy(buffer, (db->sgbuf[db->rdptr >> PAGE_SHIFT]) + (db->rdptr & (PAGE_SIZE-1)), pgrem);
+		size -= pgrem;
+		(char *)buffer += pgrem;
+		db->rdptr += pgrem;
+		if (db->rdptr >= db->dmasize)
+			db->rdptr = 0;
+	}
+}
+
+static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *buffer, unsigned int size)
+{
+	unsigned int pgrem, rem;
+
+	if (!db->ready || db->mapped)
+		return -EINVAL;
+	for (;;) {
+		if (size <= 0)
+			return 0;
+		pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1;
+		if (pgrem > size)
+			pgrem = size;
+		rem = db->dmasize - ptr;
+		if (pgrem > rem)
+			pgrem = rem;
+		if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem))
+			return -EFAULT;
+		size -= pgrem;
+		(char *)buffer += pgrem;
+		ptr += pgrem;
+		if (ptr >= db->dmasize)
+			ptr = 0;
+	}
+}
+
+static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *buffer, unsigned int size)
+{
+	unsigned int pgrem, rem;
+
+	if (!db->ready || db->mapped)
+		return -EINVAL;
+	for (;;) {
+		if (size <= 0)
+			return 0;
+		pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1;
+		if (pgrem > size)
+			pgrem = size;
+		rem = db->dmasize - ptr;
+		if (pgrem > rem)
+			pgrem = rem;
+		if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem))
+			return -EFAULT;
+		size -= pgrem;
+		(char *)buffer += pgrem;
+		ptr += pgrem;
+		if (ptr >= db->dmasize)
+			ptr = 0;
+	}
+}
+
+/* --------------------------------------------------------------------- */
+/*
+ * USB I/O code. We do sample format conversion if necessary
+ */
+
+static void usbin_stop(struct usb_audiodev *as)
+{
+	struct usbin *u = &as->usbin;
+	unsigned long flags;
+	unsigned int i, notkilled = 1;
+
+	spin_lock_irqsave(&as->lock, flags);
+	u->flags &= ~FLG_RUNNING;
+	i = u->flags;
+	spin_unlock_irqrestore(&as->lock, flags);
+	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
+		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+		spin_lock_irqsave(&as->lock, flags);
+		i = u->flags;
+		spin_unlock_irqrestore(&as->lock, flags);
+		if (notkilled && signal_pending(current)) {
+			if (i & FLG_URB0RUNNING)
+				usb_unlink_urb(u->durb[0].urb);
+			if (i & FLG_URB1RUNNING)
+				usb_unlink_urb(u->durb[1].urb);
+			if (i & FLG_SYNC0RUNNING)
+				usb_unlink_urb(u->surb[0].urb);
+			if (i & FLG_SYNC1RUNNING)
+				usb_unlink_urb(u->surb[1].urb);
+			notkilled = 0;
+		}
+	}
+	set_current_state(TASK_RUNNING);
+	if (u->durb[0].urb->transfer_buffer)
+		kfree(u->durb[0].urb->transfer_buffer);
+	if (u->durb[1].urb->transfer_buffer)
+		kfree(u->durb[1].urb->transfer_buffer);
+	if (u->surb[0].urb->transfer_buffer)
+		kfree(u->surb[0].urb->transfer_buffer);
+	if (u->surb[1].urb->transfer_buffer)
+		kfree(u->surb[1].urb->transfer_buffer);
+	u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = 
+		u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL;
+}
+
+static inline void usbin_release(struct usb_audiodev *as)
+{
+	usbin_stop(as);
+}
+
+static void usbin_disc(struct usb_audiodev *as)
+{
+	struct usbin *u = &as->usbin;
+
+	unsigned long flags;
+
+	spin_lock_irqsave(&as->lock, flags);
+	u->flags &= ~(FLG_RUNNING | FLG_CONNECTED);
+	spin_unlock_irqrestore(&as->lock, flags);
+	usbin_stop(as);
+}
+
+static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt)
+{
+	unsigned int cnt, i;
+	__s16 *sp, *sp2, s;
+	unsigned char *bp;
+
+	cnt = scnt;
+	if (AFMT_ISSTEREO(ifmt))
+		cnt <<= 1;
+	sp = ((__s16 *)tmp) + cnt;
+	switch (ifmt & ~AFMT_STEREO) {
+	case AFMT_U8:
+		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {
+			bp--;
+			sp--;
+			*sp = (*bp ^ 0x80) << 8;
+		}
+		break;
+			
+	case AFMT_S8:
+		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {
+			bp--;
+			sp--;
+			*sp = *bp << 8;
+		}
+		break;
+		
+	case AFMT_U16_LE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = (bp[0] | (bp[1] << 8)) ^ 0x8000;
+		}
+		break;
+
+	case AFMT_U16_BE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = (bp[1] | (bp[0] << 8)) ^ 0x8000;
+		}
+		break;
+
+	case AFMT_S16_LE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = bp[0] | (bp[1] << 8);
+		}
+		break;
+
+	case AFMT_S16_BE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = bp[1] | (bp[0] << 8);
+		}
+		break;
+	}
+	if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) {
+		/* expand from mono to stereo */
+		for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) {
+			sp--;
+			sp2 -= 2;
+			sp2[0] = sp2[1] = sp[0];
+		}
+	}
+	if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) {
+		/* contract from stereo to mono */
+		for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2)
+			sp[0] = (sp2[0] + sp2[1]) >> 1;
+	}
+	cnt = scnt;
+	if (AFMT_ISSTEREO(ofmt))
+		cnt <<= 1;
+	sp = ((__s16 *)tmp);
+	bp = ((unsigned char *)obuf);
+	switch (ofmt & ~AFMT_STEREO) {
+	case AFMT_U8:
+		for (i = 0; i < cnt; i++, sp++, bp++)
+			*bp = (*sp >> 8) ^ 0x80;
+		break;
+
+	case AFMT_S8:
+		for (i = 0; i < cnt; i++, sp++, bp++)
+			*bp = *sp >> 8;
+		break;
+
+	case AFMT_U16_LE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[0] = s;
+			bp[1] = (s >> 8) ^ 0x80;
+		}
+		break;
+
+	case AFMT_U16_BE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[1] = s;
+			bp[0] = (s >> 8) ^ 0x80;
+		}
+		break;
+
+	case AFMT_S16_LE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[0] = s;
+			bp[1] = s >> 8;
+		}
+		break;
+
+	case AFMT_S16_BE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[1] = s;
+			bp[0] = s >> 8;
+		}
+		break;
+	}
+	
+}
+
+static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples)
+{
+	union {
+		__s16 s[64];
+		unsigned char b[0];
+	} tmp;
+	unsigned int scnt, maxs, ufmtsh, dfmtsh;
+
+	ufmtsh = AFMT_BYTESSHIFT(u->format);
+	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
+	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;
+	while (samples > 0) {
+		scnt = samples;
+		if (scnt > maxs)
+			scnt = maxs;
+		conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt);
+		dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh);
+		buffer += scnt << ufmtsh;
+		samples -= scnt;
+	}
+}		
+
+static int usbin_prepare_desc(struct usbin *u, struct urb *urb)
+{
+	unsigned int i, maxsize, offs;
+
+	maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
+	//printk(KERN_DEBUG "usbin_prepare_desc: maxsize %d freq 0x%x format 0x%x\n", maxsize, u->freqn, u->format);
+	for (i = offs = 0; i < DESCFRAMES; i++, offs += maxsize) {
+		urb->iso_frame_desc[i].length = maxsize;
+		urb->iso_frame_desc[i].offset = offs;
+	}
+	urb->interval = 1;
+	return 0;
+}
+
+/*
+ * return value: 0 if descriptor should be restarted, -1 otherwise
+ * convert sample format on the fly if necessary
+ */
+static int usbin_retire_desc(struct usbin *u, struct urb *urb)
+{
+	unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;
+	unsigned char *cp;
+
+	ufmtsh = AFMT_BYTESSHIFT(u->format);
+	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
+	for (i = 0; i < DESCFRAMES; i++) {
+		cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset;
+		if (urb->iso_frame_desc[i].status) {
+			dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
+			continue;
+		}
+		scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh;
+		if (!scnt)
+			continue;
+		cnt = scnt << dfmtsh;
+		if (!u->dma.mapped) {
+			dmafree = u->dma.dmasize - u->dma.count;
+			if (cnt > dmafree) {
+				scnt = dmafree >> dfmtsh;
+				cnt = scnt << dfmtsh;
+				err++;
+			}
+		}
+		u->dma.count += cnt;
+		if (u->format == u->dma.format) {
+			/* we do not need format conversion */
+			dprintk((KERN_DEBUG "usbaudio: no sample format conversion\n"));
+			dmabuf_copyin(&u->dma, cp, cnt);
+		} else {
+			/* we need sampling format conversion */
+			dprintk((KERN_DEBUG "usbaudio: sample format conversion %x != %x\n", u->format, u->dma.format));
+			usbin_convert(u, cp, scnt);
+		}
+	}
+	if (err)
+		u->dma.error++;
+	if (u->dma.count >= (signed)u->dma.fragsize)
+		wake_up(&u->dma.wait);
+	return err ? -1 : 0;
+}
+
+static void usbin_completed(struct urb *urb)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
+	struct usbin *u = &as->usbin;
+	unsigned long flags;
+	unsigned int mask;
+	int suret = 0;
+
+#if 0
+	printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
+#endif
+	if (urb == u->durb[0].urb)
+		mask = FLG_URB0RUNNING;
+	else if (urb == u->durb[1].urb)
+		mask = FLG_URB1RUNNING;
+	else {
+		mask = 0;
+		printk(KERN_ERR "usbin_completed: panic: unknown URB\n");
+	}
+	urb->dev = as->state->usbdev;
+	spin_lock_irqsave(&as->lock, flags);
+	if (!usbin_retire_desc(u, urb) &&
+	    u->flags & FLG_RUNNING &&
+	    !usbin_prepare_desc(u, urb) && 
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
+		u->flags |= mask;
+	} else {
+		u->flags &= ~(mask | FLG_RUNNING);
+		wake_up(&u->dma.wait);
+		printk(KERN_DEBUG "usbin_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret);
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+}
+
+/*
+ * we output sync data
+ */
+static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb)
+{
+	unsigned char *cp = urb->transfer_buffer;
+	unsigned int i, offs;
+	
+	for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3, cp += 3) {
+		urb->iso_frame_desc[i].length = 3;
+		urb->iso_frame_desc[i].offset = offs;
+		cp[0] = u->freqn;
+		cp[1] = u->freqn >> 8;
+		cp[2] = u->freqn >> 16;
+	}
+	urb->interval = 1;
+	return 0;
+}
+
+/*
+ * return value: 0 if descriptor should be restarted, -1 otherwise
+ */
+static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb)
+{
+	unsigned int i;
+	
+	for (i = 0; i < SYNCFRAMES; i++)
+		if (urb->iso_frame_desc[0].status)
+			dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
+	return 0;
+}
+
+static void usbin_sync_completed(struct urb *urb)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
+	struct usbin *u = &as->usbin;
+	unsigned long flags;
+	unsigned int mask;
+	int suret = 0;
+
+#if 0
+	printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
+#endif
+	if (urb == u->surb[0].urb)
+		mask = FLG_SYNC0RUNNING;
+	else if (urb == u->surb[1].urb)
+		mask = FLG_SYNC1RUNNING;
+	else {
+		mask = 0;
+		printk(KERN_ERR "usbin_sync_completed: panic: unknown URB\n");
+	}
+	urb->dev = as->state->usbdev;
+	spin_lock_irqsave(&as->lock, flags);
+	if (!usbin_sync_retire_desc(u, urb) &&
+	    u->flags & FLG_RUNNING &&
+	    !usbin_sync_prepare_desc(u, urb) && 
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
+		u->flags |= mask;
+	} else {
+		u->flags &= ~(mask | FLG_RUNNING);
+		wake_up(&u->dma.wait);
+		dprintk((KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+}
+
+static int usbin_start(struct usb_audiodev *as)
+{
+	struct usb_device *dev = as->state->usbdev;
+	struct usbin *u = &as->usbin;
+	struct urb *urb;
+	unsigned long flags;
+	unsigned int maxsze, bufsz;
+
+#if 0
+	printk(KERN_DEBUG "usbin_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n",
+	       dev->devnum, u->format, u->dma.format, u->dma.srate);
+#endif
+	/* allocate USB storage if not already done */
+	spin_lock_irqsave(&as->lock, flags);
+	if (!(u->flags & FLG_CONNECTED)) {
+		spin_unlock_irqrestore(&as->lock, flags);
+		return -EIO;
+	}
+	if (!(u->flags & FLG_RUNNING)) {
+		spin_unlock_irqrestore(&as->lock, flags);
+		u->freqn = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */
+		u->freqmax = u->freqn + (u->freqn >> 2);
+		u->phase = 0;
+		maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
+		bufsz = DESCFRAMES * maxsze;
+		if (u->durb[0].urb->transfer_buffer)
+			kfree(u->durb[0].urb->transfer_buffer);
+		u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+		u->durb[0].urb->transfer_buffer_length = bufsz;
+		if (u->durb[1].urb->transfer_buffer)
+			kfree(u->durb[1].urb->transfer_buffer);
+		u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+		u->durb[1].urb->transfer_buffer_length = bufsz;
+		if (u->syncpipe) {
+			if (u->surb[0].urb->transfer_buffer)
+				kfree(u->surb[0].urb->transfer_buffer);
+			u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+			u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES;
+			if (u->surb[1].urb->transfer_buffer)
+				kfree(u->surb[1].urb->transfer_buffer);
+			u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+			u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES;
+		}
+		if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || 
+		    (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) {
+			printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);
+			return 0;
+		}
+		spin_lock_irqsave(&as->lock, flags);
+	}
+	if (u->dma.count >= u->dma.dmasize && !u->dma.mapped) {
+		spin_unlock_irqrestore(&as->lock, flags);
+		return 0;
+	}
+	u->flags |= FLG_RUNNING;
+	if (!(u->flags & FLG_URB0RUNNING)) {
+		urb = u->durb[0].urb;
+		urb->dev = dev;
+		urb->pipe = u->datapipe;
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->number_of_packets = DESCFRAMES;
+		urb->context = as;
+		urb->complete = usbin_completed;
+		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+			u->flags |= FLG_URB0RUNNING;
+		else
+			u->flags &= ~FLG_RUNNING;
+	}
+	if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {
+		urb = u->durb[1].urb;
+		urb->dev = dev;
+		urb->pipe = u->datapipe;
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->number_of_packets = DESCFRAMES;
+		urb->context = as;
+		urb->complete = usbin_completed;
+		if (!usbin_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+			u->flags |= FLG_URB1RUNNING;
+		else
+			u->flags &= ~FLG_RUNNING;
+	}
+	if (u->syncpipe) {
+		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {
+			urb = u->surb[0].urb;
+			urb->dev = dev;
+			urb->pipe = u->syncpipe;
+			urb->transfer_flags = USB_ISO_ASAP;
+			urb->number_of_packets = SYNCFRAMES;
+			urb->context = as;
+			urb->complete = usbin_sync_completed;
+			/* stride: u->syncinterval */
+			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+				u->flags |= FLG_SYNC0RUNNING;
+			else
+				u->flags &= ~FLG_RUNNING;
+		}
+		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {
+			urb = u->surb[1].urb;
+			urb->dev = dev;
+			urb->pipe = u->syncpipe;
+			urb->transfer_flags = USB_ISO_ASAP;
+			urb->number_of_packets = SYNCFRAMES;
+			urb->context = as;
+			urb->complete = usbin_sync_completed;
+			/* stride: u->syncinterval */
+			if (!usbin_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+				u->flags |= FLG_SYNC1RUNNING;
+			else
+				u->flags &= ~FLG_RUNNING;
+		}
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+	return 0;
+}
+
+static void usbout_stop(struct usb_audiodev *as)
+{
+	struct usbout *u = &as->usbout;
+	unsigned long flags;
+	unsigned int i, notkilled = 1;
+
+	spin_lock_irqsave(&as->lock, flags);
+	u->flags &= ~FLG_RUNNING;
+	i = u->flags;
+	spin_unlock_irqrestore(&as->lock, flags);
+	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
+		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+		spin_lock_irqsave(&as->lock, flags);
+		i = u->flags;
+		spin_unlock_irqrestore(&as->lock, flags);
+		if (notkilled && signal_pending(current)) {
+			if (i & FLG_URB0RUNNING)
+				usb_unlink_urb(u->durb[0].urb);
+			if (i & FLG_URB1RUNNING)
+				usb_unlink_urb(u->durb[1].urb);
+			if (i & FLG_SYNC0RUNNING)
+				usb_unlink_urb(u->surb[0].urb);
+			if (i & FLG_SYNC1RUNNING)
+				usb_unlink_urb(u->surb[1].urb);
+			notkilled = 0;
+		}
+	}
+	set_current_state(TASK_RUNNING);
+	if (u->durb[0].urb->transfer_buffer)
+		kfree(u->durb[0].urb->transfer_buffer);
+	if (u->durb[1].urb->transfer_buffer)
+		kfree(u->durb[1].urb->transfer_buffer);
+	if (u->surb[0].urb->transfer_buffer)
+		kfree(u->surb[0].urb->transfer_buffer);
+	if (u->surb[1].urb->transfer_buffer)
+		kfree(u->surb[1].urb->transfer_buffer);
+	u->durb[0].urb->transfer_buffer = u->durb[1].urb->transfer_buffer = 
+		u->surb[0].urb->transfer_buffer = u->surb[1].urb->transfer_buffer = NULL;
+}
+
+static inline void usbout_release(struct usb_audiodev *as)
+{
+	usbout_stop(as);
+}
+
+static void usbout_disc(struct usb_audiodev *as)
+{
+	struct usbout *u = &as->usbout;
+	unsigned long flags;
+
+	spin_lock_irqsave(&as->lock, flags);
+	u->flags &= ~(FLG_RUNNING | FLG_CONNECTED);
+	spin_unlock_irqrestore(&as->lock, flags);
+	usbout_stop(as);
+}
+
+static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int samples)
+{
+	union {
+		__s16 s[64];
+		unsigned char b[0];
+	} tmp;
+	unsigned int scnt, maxs, ufmtsh, dfmtsh;
+
+	ufmtsh = AFMT_BYTESSHIFT(u->format);
+	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
+	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;
+	while (samples > 0) {
+		scnt = samples;
+		if (scnt > maxs)
+			scnt = maxs;
+		dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh);
+		conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt);
+		buffer += scnt << ufmtsh;
+		samples -= scnt;
+	}
+}		
+
+static int usbout_prepare_desc(struct usbout *u, struct urb *urb)
+{
+	unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;
+	unsigned char *cp = urb->transfer_buffer;
+
+	ufmtsh = AFMT_BYTESSHIFT(u->format);
+	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
+	for (i = offs = 0; i < DESCFRAMES; i++) {
+		urb->iso_frame_desc[i].offset = offs;
+		u->phase = (u->phase & 0x3fff) + u->freqm;
+		scnt = u->phase >> 14;
+		if (!scnt) {
+			urb->iso_frame_desc[i].length = 0;
+			continue;
+		}
+		cnt = scnt << dfmtsh;
+		if (!u->dma.mapped) {
+			if (cnt > u->dma.count) {
+				scnt = u->dma.count >> dfmtsh;
+				cnt = scnt << dfmtsh;
+				err++;
+			}
+			u->dma.count -= cnt;
+		} else
+			u->dma.count += cnt;
+		if (u->format == u->dma.format) {
+			/* we do not need format conversion */
+			dmabuf_copyout(&u->dma, cp, cnt);
+		} else {
+			/* we need sampling format conversion */
+			usbout_convert(u, cp, scnt);
+		}
+		cnt = scnt << ufmtsh;
+		urb->iso_frame_desc[i].length = cnt;
+		offs += cnt;
+		cp += cnt;
+	}
+	if (err)
+		u->dma.error++;
+	if (u->dma.mapped) {
+		if (u->dma.count >= (signed)u->dma.fragsize)
+			wake_up(&u->dma.wait);
+	} else {
+		if ((signed)u->dma.dmasize >= u->dma.count + (signed)u->dma.fragsize)
+			wake_up(&u->dma.wait);
+	}
+	return err ? -1 : 0;
+}
+
+/*
+ * return value: 0 if descriptor should be restarted, -1 otherwise
+ */
+static int usbout_retire_desc(struct usbout *u, struct urb *urb)
+{
+	unsigned int i;
+
+	for (i = 0; i < DESCFRAMES; i++) {
+		if (urb->iso_frame_desc[i].status) {
+			dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
+			continue;
+		}
+	}
+	return 0;
+}
+
+static void usbout_completed(struct urb *urb)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
+	struct usbout *u = &as->usbout;
+	unsigned long flags;
+	unsigned int mask;
+	int suret = 0;
+
+#if 0
+	printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
+#endif
+	if (urb == u->durb[0].urb)
+		mask = FLG_URB0RUNNING;
+	else if (urb == u->durb[1].urb)
+		mask = FLG_URB1RUNNING;
+	else {
+		mask = 0;
+		printk(KERN_ERR "usbout_completed: panic: unknown URB\n");
+	}
+	urb->dev = as->state->usbdev;
+	spin_lock_irqsave(&as->lock, flags);
+	if (!usbout_retire_desc(u, urb) &&
+	    u->flags & FLG_RUNNING &&
+	    !usbout_prepare_desc(u, urb) && 
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
+		u->flags |= mask;
+	} else {
+		u->flags &= ~(mask | FLG_RUNNING);
+		wake_up(&u->dma.wait);
+		dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+}
+
+static int usbout_sync_prepare_desc(struct usbout *u, struct urb *urb)
+{
+	unsigned int i, offs;
+
+	for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3) {
+		urb->iso_frame_desc[i].length = 3;
+		urb->iso_frame_desc[i].offset = offs;
+	}
+	return 0;
+}
+
+/*
+ * return value: 0 if descriptor should be restarted, -1 otherwise
+ */
+static int usbout_sync_retire_desc(struct usbout *u, struct urb *urb)
+{
+	unsigned char *cp = urb->transfer_buffer;
+	unsigned int f, i;
+
+	for (i = 0; i < SYNCFRAMES; i++, cp += 3) {
+		if (urb->iso_frame_desc[i].status) {
+			dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));
+			continue;
+		}
+		if (urb->iso_frame_desc[i].actual_length < 3) {
+			dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length));
+			continue;
+		}
+		f = cp[0] | (cp[1] << 8) | (cp[2] << 16);
+		if (abs(f - u->freqn) > (u->freqn >> 3) || f > u->freqmax) {
+			printk(KERN_WARNING "usbout_sync_retire_desc: requested frequency %u (nominal %u) out of range!\n", f, u->freqn);
+			continue;
+		}
+		u->freqm = f;
+	}
+	return 0;
+}
+
+static void usbout_sync_completed(struct urb *urb)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;
+	struct usbout *u = &as->usbout;
+	unsigned long flags;
+	unsigned int mask;
+	int suret = 0;
+
+#if 0
+	printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
+#endif
+	if (urb == u->surb[0].urb)
+		mask = FLG_SYNC0RUNNING;
+	else if (urb == u->surb[1].urb)
+		mask = FLG_SYNC1RUNNING;
+	else {
+		mask = 0;
+		printk(KERN_ERR "usbout_sync_completed: panic: unknown URB\n");
+	}
+	urb->dev = as->state->usbdev;
+	spin_lock_irqsave(&as->lock, flags);
+	if (!usbout_sync_retire_desc(u, urb) &&
+	    u->flags & FLG_RUNNING &&
+	    !usbout_sync_prepare_desc(u, urb) && 
+	    (suret = usb_submit_urb(urb, GFP_KERNEL)) == 0) {
+		u->flags |= mask;
+	} else {
+		u->flags &= ~(mask | FLG_RUNNING);
+		wake_up(&u->dma.wait);
+		dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+}
+
+static int usbout_start(struct usb_audiodev *as)
+{
+	struct usb_device *dev = as->state->usbdev;
+	struct usbout *u = &as->usbout;
+	struct urb *urb;
+	unsigned long flags;
+	unsigned int maxsze, bufsz;
+
+#if 0
+	printk(KERN_DEBUG "usbout_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n",
+	       dev->devnum, u->format, u->dma.format, u->dma.srate);
+#endif
+	/* allocate USB storage if not already done */
+	spin_lock_irqsave(&as->lock, flags);
+	if (!(u->flags & FLG_CONNECTED)) {
+		spin_unlock_irqrestore(&as->lock, flags);
+		return -EIO;
+	}
+	if (!(u->flags & FLG_RUNNING)) {
+		spin_unlock_irqrestore(&as->lock, flags);
+		u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */
+		u->freqmax = u->freqn + (u->freqn >> 2);
+		u->phase = 0;
+		maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));
+		bufsz = DESCFRAMES * maxsze;
+		if (u->durb[0].urb->transfer_buffer)
+			kfree(u->durb[0].urb->transfer_buffer);
+		u->durb[0].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+		u->durb[0].urb->transfer_buffer_length = bufsz;
+		if (u->durb[1].urb->transfer_buffer)
+			kfree(u->durb[1].urb->transfer_buffer);
+		u->durb[1].urb->transfer_buffer = kmalloc(bufsz, GFP_KERNEL);
+		u->durb[1].urb->transfer_buffer_length = bufsz;
+		if (u->syncpipe) {
+			if (u->surb[0].urb->transfer_buffer)
+				kfree(u->surb[0].urb->transfer_buffer);
+			u->surb[0].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+			u->surb[0].urb->transfer_buffer_length = 3*SYNCFRAMES;
+			if (u->surb[1].urb->transfer_buffer)
+				kfree(u->surb[1].urb->transfer_buffer);
+			u->surb[1].urb->transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);
+			u->surb[1].urb->transfer_buffer_length = 3*SYNCFRAMES;
+		}
+		if (!u->durb[0].urb->transfer_buffer || !u->durb[1].urb->transfer_buffer || 
+		    (u->syncpipe && (!u->surb[0].urb->transfer_buffer || !u->surb[1].urb->transfer_buffer))) {
+			printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);
+			return 0;
+		}
+		spin_lock_irqsave(&as->lock, flags);
+	}
+	if (u->dma.count <= 0 && !u->dma.mapped) {
+		spin_unlock_irqrestore(&as->lock, flags);
+		return 0;
+	}
+       	u->flags |= FLG_RUNNING;
+	if (!(u->flags & FLG_URB0RUNNING)) {
+		urb = u->durb[0].urb;
+		urb->dev = dev;
+		urb->pipe = u->datapipe;
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->number_of_packets = DESCFRAMES;
+		urb->context = as;
+		urb->complete = usbout_completed;
+		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+			u->flags |= FLG_URB0RUNNING;
+		else
+			u->flags &= ~FLG_RUNNING;
+	}
+	if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {
+		urb = u->durb[1].urb;
+		urb->dev = dev;
+		urb->pipe = u->datapipe;
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->number_of_packets = DESCFRAMES;
+		urb->context = as;
+		urb->complete = usbout_completed;
+		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+			u->flags |= FLG_URB1RUNNING;
+		else
+			u->flags &= ~FLG_RUNNING;
+	}
+	if (u->syncpipe) {
+		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {
+			urb = u->surb[0].urb;
+			urb->dev = dev;
+			urb->pipe = u->syncpipe;
+			urb->transfer_flags = USB_ISO_ASAP;
+			urb->number_of_packets = SYNCFRAMES;
+			urb->context = as;
+			urb->complete = usbout_sync_completed;
+			/* stride: u->syncinterval */
+			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+				u->flags |= FLG_SYNC0RUNNING;
+			else
+				u->flags &= ~FLG_RUNNING;
+		}
+		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {
+			urb = u->surb[1].urb;
+			urb->dev = dev;
+			urb->pipe = u->syncpipe;
+			urb->transfer_flags = USB_ISO_ASAP;
+			urb->number_of_packets = SYNCFRAMES;
+			urb->context = as;
+			urb->complete = usbout_sync_completed;
+			/* stride: u->syncinterval */
+			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb, GFP_KERNEL))
+				u->flags |= FLG_SYNC1RUNNING;
+			else
+				u->flags &= ~FLG_RUNNING;
+		}
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate)
+{
+	unsigned int g = 0;
+
+	if (srate < afp->sratelo)
+		g += afp->sratelo - srate;
+	if (srate > afp->sratehi)
+		g += srate - afp->sratehi;
+	if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt))
+		g += 0x100000;
+	if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt))
+		g += 0x400000;
+	if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt))
+		g += 0x100000;
+	if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt))
+		g += 0x400000;
+	return g;
+}
+
+static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate)
+{
+	unsigned int i, g, gb = ~0;
+	int j = -1; /* default to failure */
+
+	/* find "best" format (according to format_goodness) */
+	for (i = 0; i < nr; i++) {
+		g = format_goodness(&afp[i], fmt, srate);
+		if (g >= gb) 
+			continue;
+		j = i;
+		gb = g;
+	}
+       	return j;
+}
+
+static int set_format_in(struct usb_audiodev *as)
+{
+	struct usb_device *dev = as->state->usbdev;
+	struct usb_config_descriptor *config = dev->actconfig;
+	struct usb_interface_descriptor *alts;
+	struct usb_interface *iface;
+	struct usbin *u = &as->usbin;
+	struct dmabuf *d = &u->dma;
+	struct audioformat *fmt;
+	unsigned int ep;
+	unsigned char data[3];
+	int fmtnr, ret;
+
+	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
+		return 0;
+	iface = &config->interface[u->interface];
+
+	fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate);
+	if (fmtnr < 0) {
+		printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired format/speed combination.\n");
+		return -1;
+	}
+
+	fmt = as->fmtin + fmtnr;
+	alts = &iface->altsetting[fmt->altsetting];
+	u->format = fmt->format;
+	u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);
+	u->syncpipe = u->syncinterval = 0;
+	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x08) {
+		if (alts->bNumEndpoints < 2 ||
+		    alts->endpoint[1].bmAttributes != 0x01 ||
+		    alts->endpoint[1].bSynchAddress != 0 ||
+		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress & 0x7f)) {
+			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
+			       dev->devnum, u->interface, fmt->altsetting);
+			return -1;
+		}
+		u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
+		u->syncinterval = alts->endpoint[1].bRefresh;
+	}
+	if (d->srate < fmt->sratelo)
+		d->srate = fmt->sratelo;
+	if (d->srate > fmt->sratehi)
+		d->srate = fmt->sratehi;
+	dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));
+	if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
+		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
+		       dev->devnum, u->interface, fmt->altsetting);
+		return -1;
+	}
+	if (fmt->sratelo == fmt->sratehi)
+		return 0;
+	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);
+	/* if endpoint has pitch control, enable it */
+	if (fmt->attributes & 0x02) {
+		data[0] = 1;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
+	}
+	/* if endpoint has sampling rate control, set it */
+	if (fmt->attributes & 0x01) {
+		data[0] = d->srate;
+		data[1] = d->srate >> 8;
+		data[2] = d->srate >> 16;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
+		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n",
+			       ret, dev->devnum, u->interface, ep);
+			return -1;
+		}
+		dprintk((KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n",
+		        dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));
+		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
+	}
+	dprintk((KERN_DEBUG "usbaudio: set_format_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));
+	return 0;
+}
+
+static int set_format_out(struct usb_audiodev *as)
+{
+	struct usb_device *dev = as->state->usbdev;
+	struct usb_config_descriptor *config = dev->actconfig;
+	struct usb_interface_descriptor *alts;
+	struct usb_interface *iface;	
+	struct usbout *u = &as->usbout;
+	struct dmabuf *d = &u->dma;
+	struct audioformat *fmt;
+	unsigned int ep;
+	unsigned char data[3];
+	int fmtnr, ret;
+
+	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
+		return 0;
+	iface = &config->interface[u->interface];
+
+	fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate);
+	if (fmtnr < 0) {
+		printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired format/speed combination.\n");
+		return -1;
+	}
+
+	fmt = as->fmtout + fmtnr;
+	u->format = fmt->format;
+	alts = &iface->altsetting[fmt->altsetting];
+	u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);
+	u->syncpipe = u->syncinterval = 0;
+	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x04) {
+#if 0
+		printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n"
+		       KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n"
+		       KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints,
+		       alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress,
+		       alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress);
+#endif
+		if (alts->bNumEndpoints < 2 ||
+		    alts->endpoint[1].bmAttributes != 0x01 ||
+		    alts->endpoint[1].bSynchAddress != 0 ||
+		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress | 0x80)) {
+			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
+			       dev->devnum, u->interface, fmt->altsetting);
+			return -1;
+		}
+		u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);
+		u->syncinterval = alts->endpoint[1].bRefresh;
+	}
+	if (d->srate < fmt->sratelo)
+		d->srate = fmt->sratelo;
+	if (d->srate > fmt->sratehi)
+		d->srate = fmt->sratehi;
+	dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));
+	if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
+		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
+		       dev->devnum, u->interface, fmt->altsetting);
+		return -1;
+	}
+	if (fmt->sratelo == fmt->sratehi)
+		return 0;
+	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);
+	/* if endpoint has pitch control, enable it */
+	if (fmt->attributes & 0x02) {
+		data[0] = 1;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
+	}
+	/* if endpoint has sampling rate control, set it */
+	if (fmt->attributes & 0x01) {
+		data[0] = d->srate;
+		data[1] = d->srate >> 8;
+		data[2] = d->srate >> 16;
+		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n",
+			       ret, dev->devnum, u->interface, ep, d->srate);
+			return -1;
+		}
+		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+			printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n",
+			       ret, dev->devnum, u->interface, ep);
+			return -1;
+		}
+		dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",
+		        dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));
+		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);
+	}
+	dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));
+	return 0;
+}
+
+static int set_format(struct usb_audiodev *s, unsigned int fmode, unsigned int fmt, unsigned int srate)
+{
+	int ret1 = 0, ret2 = 0;
+
+	if (!(fmode & (FMODE_READ|FMODE_WRITE)))
+		return -EINVAL;
+	if (fmode & FMODE_READ) {
+		usbin_stop(s);
+		s->usbin.dma.ready = 0;
+		if (fmt == AFMT_QUERY)
+			fmt = s->usbin.dma.format;
+		else
+			s->usbin.dma.format = fmt;
+		if (!srate)
+			srate = s->usbin.dma.srate;
+		else
+			s->usbin.dma.srate = srate;
+	}
+	if (fmode & FMODE_WRITE) {
+		usbout_stop(s);
+		s->usbout.dma.ready = 0;
+		if (fmt == AFMT_QUERY)
+			fmt = s->usbout.dma.format;
+		else
+			s->usbout.dma.format = fmt;
+		if (!srate)
+			srate = s->usbout.dma.srate;
+		else
+			s->usbout.dma.srate = srate;
+	}
+	if (fmode & FMODE_READ)
+		ret1 = set_format_in(s);
+	if (fmode & FMODE_WRITE)
+		ret2 = set_format_out(s);
+	return ret1 ? ret1 : ret2;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value)
+{
+	struct usb_device *dev = ms->state->usbdev;
+	unsigned char data[2];
+	struct mixerchannel *ch;
+	int v1, v2, v3;
+
+	if (mixch >= ms->numch)
+		return -1;
+	ch = &ms->ch[mixch];
+	v3 = ch->maxval - ch->minval;
+	v1 = value & 0xff;
+	v2 = (value >> 8) & 0xff;
+	if (v1 > 100)
+		v1 = 100;
+	if (v2 > 100)
+		v2 = 100;
+	if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
+		v2 = v1;
+	ch->value = v1 | (v2 << 8);
+	v1 = (v1 * v3) / 100 + ch->minval;
+	v2 = (v2 * v3) / 100 + ch->minval;
+	switch (ch->selector) {
+	case 0:  /* mixer unit request */
+		data[0] = v1;
+		data[1] = v1 >> 8;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+			goto err;
+		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
+			return 0;
+		data[0] = v2;
+		data[1] = v2 >> 8;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
+				    ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+			goto err;
+		return 0;
+
+		/* various feature unit controls */
+	case VOLUME_CONTROL:
+		data[0] = v1;
+		data[1] = v1 >> 8;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+			goto err;
+		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
+			return 0;
+		data[0] = v2;
+		data[1] = v2 >> 8;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+			goto err;
+		return 0;
+                
+	case BASS_CONTROL:
+	case MID_CONTROL:
+	case TREBLE_CONTROL:
+		data[0] = v1 >> 8;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
+			goto err;
+		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
+			return 0;
+		data[0] = v2 >> 8;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
+			goto err;
+		return 0;
+
+	default:
+		return -1;
+	}
+	return 0;
+
+ err:
+	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
+		dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector);
+	return -1;
+}
+
+static int get_rec_src(struct usb_mixerdev *ms)
+{
+	struct usb_device *dev = ms->state->usbdev;
+	unsigned int mask = 0, retmask = 0;
+	unsigned int i, j;
+	unsigned char buf;
+	int err = 0;
+
+	for (i = 0; i < ms->numch; i++) {
+		if (!ms->ch[i].slctunitid || (mask & (1 << i)))
+			continue;
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
+			err = -EIO;
+			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 
+			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
+			continue;
+		}
+		for (j = i; j < ms->numch; j++) {
+			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
+				continue;
+			mask |= 1 << j;
+			if (buf == (ms->ch[j].slctunitid >> 8))
+				retmask |= 1 << ms->ch[j].osschannel;
+		}
+	}
+	if (err)
+		return -EIO;
+	return retmask;
+}
+
+static int set_rec_src(struct usb_mixerdev *ms, int srcmask)
+{
+	struct usb_device *dev = ms->state->usbdev;
+	unsigned int mask = 0, smask, bmask;
+	unsigned int i, j;
+	unsigned char buf;
+	int err = 0;
+
+	for (i = 0; i < ms->numch; i++) {
+		if (!ms->ch[i].slctunitid || (mask & (1 << i)))
+			continue;
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
+			err = -EIO;
+			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 
+			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
+			continue;
+		}
+		/* first generate smask */
+		smask = bmask = 0;
+		for (j = i; j < ms->numch; j++) {
+			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
+				continue;
+			smask |= 1 << ms->ch[j].osschannel;
+			if (buf == (ms->ch[j].slctunitid >> 8))
+				bmask |= 1 << ms->ch[j].osschannel;
+			mask |= 1 << j;
+		}
+		/* check for multiple set sources */
+		j = hweight32(srcmask & smask);
+		if (j == 0)
+			continue;
+		if (j > 1)
+			srcmask &= ~bmask;
+		for (j = i; j < ms->numch; j++) {
+			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)
+				continue;
+			if (!(srcmask & (1 << ms->ch[j].osschannel)))
+				continue;
+			buf = ms->ch[j].slctunitid >> 8;
+			if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, HZ) < 0) {
+				err = -EIO;
+				printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", 
+				       dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff);
+				continue;
+			}
+		}
+	}
+	return err ? -EIO : 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * should be called with open_sem hold, so that no new processes
+ * look at the audio device to be destroyed
+ */
+
+static void release(struct usb_audio_state *s)
+{
+	struct usb_audiodev *as;
+	struct usb_mixerdev *ms;
+
+	s->count--;
+	if (s->count) {
+		up(&open_sem);
+		return;
+	}
+	up(&open_sem);
+	wake_up(&open_wait);
+	while (!list_empty(&s->audiolist)) {
+		as = list_entry(s->audiolist.next, struct usb_audiodev, list);
+		list_del(&as->list);
+		usbin_release(as);
+		usbout_release(as);
+		dmabuf_release(&as->usbin.dma);
+		dmabuf_release(&as->usbout.dma);
+		usb_free_urb(as->usbin.durb[0].urb);
+		usb_free_urb(as->usbin.durb[1].urb);
+		usb_free_urb(as->usbin.surb[0].urb);
+		usb_free_urb(as->usbin.surb[1].urb);
+		usb_free_urb(as->usbout.durb[0].urb);
+		usb_free_urb(as->usbout.durb[1].urb);
+		usb_free_urb(as->usbout.surb[0].urb);
+		usb_free_urb(as->usbout.surb[1].urb);
+		kfree(as);
+	}
+	while (!list_empty(&s->mixerlist)) {
+		ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list);
+		list_del(&ms->list);
+		kfree(ms);
+	}
+	kfree(s);
+}
+
+extern inline int prog_dmabuf_in(struct usb_audiodev *as)
+{
+	usbin_stop(as);
+	return dmabuf_init(&as->usbin.dma);
+}
+
+extern inline int prog_dmabuf_out(struct usb_audiodev *as)
+{
+	usbout_stop(as);
+	return dmabuf_init(&as->usbout.dma);
+}
+
+/* --------------------------------------------------------------------- */
+
+static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
+{
+	unsigned int minor = minor(inode->i_rdev);
+	struct list_head *devs, *mdevs;
+	struct usb_mixerdev *ms;
+	struct usb_audio_state *s;
+
+	down(&open_sem);
+	for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+		s = list_entry(devs, struct usb_audio_state, audiodev);
+		for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) {
+			ms = list_entry(mdevs, struct usb_mixerdev, list);
+			if (ms->dev_mixer == minor)
+				goto mixer_found;
+		}
+	}
+	up(&open_sem);
+	return -ENODEV;
+
+ mixer_found:
+	if (!s->usbdev) {
+		up(&open_sem);
+		return -EIO;
+	}
+	file->private_data = ms;
+	s->count++;
+
+	up(&open_sem);
+	return 0;
+}
+
+static int usb_audio_release_mixdev(struct inode *inode, struct file *file)
+{
+	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
+	struct usb_audio_state *s;
+
+	lock_kernel();
+	s = ms->state;
+	down(&open_sem);
+	release(s);
+	unlock_kernel();
+	return 0;
+}
+
+static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;
+	int i, j, val;
+
+	if (!ms->state->usbdev)
+		return -ENODEV;
+  
+	if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		strncpy(info.id, "USB_AUDIO", sizeof(info.id));
+		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));
+		info.modify_counter = ms->modcnt;
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == SOUND_OLD_MIXER_INFO) {
+		_old_mixer_info info;
+		strncpy(info.id, "USB_AUDIO", sizeof(info.id));
+		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *)arg);
+	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+		return -EINVAL;
+	if (_IOC_DIR(cmd) == _IOC_READ) {
+		switch (_IOC_NR(cmd)) {
+		case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+			val = get_rec_src(ms);
+			if (val < 0)
+				return val;
+			return put_user(val, (int *)arg);
+
+		case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
+			for (val = i = 0; i < ms->numch; i++)
+				val |= 1 << ms->ch[i].osschannel;
+			return put_user(val, (int *)arg);
+
+		case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
+			for (val = i = 0; i < ms->numch; i++)
+				if (ms->ch[i].slctunitid)
+					val |= 1 << ms->ch[i].osschannel;
+			return put_user(val, (int *)arg);
+
+		case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
+			for (val = i = 0; i < ms->numch; i++)
+				if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))
+					val |= 1 << ms->ch[i].osschannel;
+			return put_user(val, (int *)arg);
+			
+		case SOUND_MIXER_CAPS:
+			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
+
+		default:
+			i = _IOC_NR(cmd);
+			if (i >= SOUND_MIXER_NRDEVICES)
+				return -EINVAL;
+			for (j = 0; j < ms->numch; j++) {
+				if (ms->ch[j].osschannel == i) {
+					return put_user(ms->ch[j].value, (int *)arg);
+				}
+			}
+			return -EINVAL;
+		}
+	}
+	if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
+		return -EINVAL;
+	ms->modcnt++;
+	switch (_IOC_NR(cmd)) {
+	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		return set_rec_src(ms, val);
+
+	default:
+		i = _IOC_NR(cmd);
+		if (i >= SOUND_MIXER_NRDEVICES)
+			return -EINVAL;
+		for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);
+		if (j >= ms->numch)
+			return -EINVAL;
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (wrmixer(ms, j, val))
+			return -EIO;
+		return put_user(ms->ch[j].value, (int *)arg);
+	}
+}
+
+static /*const*/ struct file_operations usb_mixer_fops = {
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	ioctl:		usb_audio_ioctl_mixdev,
+	open:		usb_audio_open_mixdev,
+	release:	usb_audio_release_mixdev,
+};
+
+/* --------------------------------------------------------------------- */
+
+static int drain_out(struct usb_audiodev *as, int nonblock)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int count, tmo;
+	
+	if (as->usbout.dma.mapped || !as->usbout.dma.ready)
+		return 0;
+	usbout_start(as);
+	add_wait_queue(&as->usbout.dma.wait, &wait);
+	for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		spin_lock_irqsave(&as->lock, flags);
+		count = as->usbout.dma.count;
+		spin_unlock_irqrestore(&as->lock, flags);
+		if (count <= 0)
+			break;
+		if (signal_pending(current))
+			break;
+		if (nonblock) {
+			remove_wait_queue(&as->usbout.dma.wait, &wait);
+			set_current_state(TASK_RUNNING);
+			return -EBUSY;
+		}
+		tmo = 3 * HZ * count / as->usbout.dma.srate;
+		tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format);
+		if (!schedule_timeout(tmo + 1)) {
+			printk(KERN_DEBUG "usbaudio: dma timed out??\n");
+			break;
+		}
+	}
+	remove_wait_queue(&as->usbout.dma.wait, &wait);
+	set_current_state(TASK_RUNNING);
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static ssize_t usb_audio_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	unsigned long flags;
+	unsigned int ptr;
+	int cnt, err;
+
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (as->usbin.dma.mapped)
+		return -ENXIO;
+	if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as)))
+		return ret;
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+	add_wait_queue(&as->usbin.dma.wait, &wait);
+	while (count > 0) {
+		spin_lock_irqsave(&as->lock, flags);
+		ptr = as->usbin.dma.rdptr;
+		cnt = as->usbin.dma.count;
+		/* set task state early to avoid wakeup races */
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&as->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			if (usbin_start(as)) {
+				if (!ret)
+					ret = -ENODEV;
+				break;
+			}
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			continue;
+		}
+		if ((err = dmabuf_copyout_user(&as->usbin.dma, ptr, buffer, cnt))) {
+			if (!ret)
+				ret = err;
+			break;
+		}
+		ptr += cnt;
+		if (ptr >= as->usbin.dma.dmasize)
+			ptr -= as->usbin.dma.dmasize;
+		spin_lock_irqsave(&as->lock, flags);
+		as->usbin.dma.rdptr = ptr;
+		as->usbin.dma.count -= cnt;
+		spin_unlock_irqrestore(&as->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&as->usbin.dma.wait, &wait);
+	return ret;
+}
+
+static ssize_t usb_audio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t ret = 0;
+	unsigned long flags;
+	unsigned int ptr;
+	unsigned int start_thr;
+	int cnt, err;
+
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (as->usbout.dma.mapped)
+		return -ENXIO;
+	if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as)))
+		return ret;
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES));
+	add_wait_queue(&as->usbout.dma.wait, &wait);
+	while (count > 0) {
+#if 0
+		printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n",
+		       count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize,
+		       as->usbout.flags, current->state);
+#endif
+		spin_lock_irqsave(&as->lock, flags);
+		if (as->usbout.dma.count < 0) {
+			as->usbout.dma.count = 0;
+			as->usbout.dma.rdptr = as->usbout.dma.wrptr;
+		}
+		ptr = as->usbout.dma.wrptr;
+		cnt = as->usbout.dma.dmasize - as->usbout.dma.count;
+		/* set task state early to avoid wakeup races */
+		if (cnt <= 0)
+			__set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&as->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			if (usbout_start(as)) {
+				if (!ret)
+					ret = -ENODEV;
+				break;
+			}
+			if (file->f_flags & O_NONBLOCK) {
+				if (!ret)
+					ret = -EAGAIN;
+				break;
+			}
+			schedule();
+			if (signal_pending(current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			continue;
+		}
+		if ((err = dmabuf_copyin_user(&as->usbout.dma, ptr, buffer, cnt))) {
+			if (!ret)
+				ret = err;
+			break;
+		}
+		ptr += cnt;
+		if (ptr >= as->usbout.dma.dmasize)
+			ptr -= as->usbout.dma.dmasize;
+		spin_lock_irqsave(&as->lock, flags);
+		as->usbout.dma.wrptr = ptr;
+		as->usbout.dma.count += cnt;
+		spin_unlock_irqrestore(&as->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		if (as->usbout.dma.count >= start_thr && usbout_start(as)) {
+			if (!ret)
+				ret = -ENODEV;
+			break;
+		}
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&as->usbout.dma.wait, &wait);
+	return ret;
+}
+
+/* Called without the kernel lock - fine */
+static unsigned int usb_audio_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (!as->usbout.dma.ready)
+			prog_dmabuf_out(as);
+		poll_wait(file, &as->usbout.dma.wait, wait);
+	}
+	if (file->f_mode & FMODE_READ) {
+		if (!as->usbin.dma.ready)
+			prog_dmabuf_in(as);
+		poll_wait(file, &as->usbin.dma.wait, wait);
+	}
+	spin_lock_irqsave(&as->lock, flags);
+	if (file->f_mode & FMODE_READ) {
+		if (as->usbin.dma.count >= (signed)as->usbin.dma.fragsize)
+			mask |= POLLIN | POLLRDNORM;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		if (as->usbout.dma.mapped) {
+			if (as->usbout.dma.count >= (signed)as->usbout.dma.fragsize) 
+				mask |= POLLOUT | POLLWRNORM;
+		} else {
+			if ((signed)as->usbout.dma.dmasize >= as->usbout.dma.count + (signed)as->usbout.dma.fragsize)
+				mask |= POLLOUT | POLLWRNORM;
+		}
+	}
+	spin_unlock_irqrestore(&as->lock, flags);
+	return mask;
+}
+
+static int usb_audio_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
+	struct dmabuf *db;
+	int ret = -EINVAL;
+
+	lock_kernel();
+	if (vma->vm_flags & VM_WRITE) {
+		if ((ret = prog_dmabuf_out(as)) != 0)
+			goto out;
+		db = &as->usbout.dma;
+	} else if (vma->vm_flags & VM_READ) {
+		if ((ret = prog_dmabuf_in(as)) != 0)
+			goto out;
+		db = &as->usbin.dma;
+	} else
+		goto out;
+
+	ret = -EINVAL;
+	if (vma->vm_pgoff != 0)
+		goto out;
+
+	ret = dmabuf_mmap(vma, db,  vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+static int usb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
+	struct usb_audio_state *s = as->state;
+	unsigned long flags;
+	audio_buf_info abinfo;
+	count_info cinfo;
+	int val = 0;
+	int val2, mapped, ret;
+
+	if (!s->usbdev)
+		return -EIO;
+	mapped = ((file->f_mode & FMODE_WRITE) && as->usbout.dma.mapped) ||
+		((file->f_mode & FMODE_READ) && as->usbin.dma.mapped);
+#if 0
+	if (arg)
+		get_user(val, (int *)arg);
+	printk(KERN_DEBUG "usbaudio: usb_audio_ioctl cmd=%x arg=%lx *arg=%d\n", cmd, arg, val)
+#endif
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_SYNC:
+		if (file->f_mode & FMODE_WRITE)
+			return drain_out(as, 0/*file->f_flags & O_NONBLOCK*/);
+		return 0;
+
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_GETCAPS:
+		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 
+				DSP_CAP_MMAP | DSP_CAP_BATCH, (int *)arg);
+
+	case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_WRITE) {
+			usbout_stop(as);
+			as->usbout.dma.rdptr = as->usbout.dma.wrptr = as->usbout.dma.count = as->usbout.dma.total_bytes = 0;
+		}
+		if (file->f_mode & FMODE_READ) {
+			usbin_stop(as);
+			as->usbin.dma.rdptr = as->usbin.dma.wrptr = as->usbin.dma.count = as->usbin.dma.total_bytes = 0;
+		}
+		return 0;
+
+	case SNDCTL_DSP_SPEED:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val >= 0) {
+			if (val < 4000)
+				val = 4000;
+			if (val > 100000)
+				val = 100000;
+			if (set_format(as, file->f_mode, AFMT_QUERY, val))
+				return -EIO;
+		}
+		return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
+
+	case SNDCTL_DSP_STEREO:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+		if (val)
+			val2 |= AFMT_STEREO;
+		else
+			val2 &= ~AFMT_STEREO;
+		if (set_format(as, file->f_mode, val2, 0))
+			return -EIO;
+		return 0;
+
+	case SNDCTL_DSP_CHANNELS:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != 0) {
+			val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+			if (val == 1)
+				val2 &= ~AFMT_STEREO;
+			else
+				val2 |= AFMT_STEREO;
+			if (set_format(as, file->f_mode, val2, 0))
+				return -EIO;
+		}
+		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
+
+	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+		return put_user(AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE |
+				AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE, (int *)arg);
+
+	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != AFMT_QUERY) {
+			if (hweight32(val) != 1)
+				return -EINVAL;
+			if (!(val & (AFMT_U8 | AFMT_U16_LE | AFMT_U16_BE |
+				     AFMT_S8 | AFMT_S16_LE | AFMT_S16_BE)))
+				return -EINVAL;
+			val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+			val |= val2 & AFMT_STEREO;
+			if (set_format(as, file->f_mode, val, 0))
+				return -EIO;
+		}
+		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+		return put_user(val2 & ~AFMT_STEREO, (int *)arg);
+
+	case SNDCTL_DSP_POST:
+		return 0;
+
+	case SNDCTL_DSP_GETTRIGGER:
+		val = 0;
+		if (file->f_mode & FMODE_READ && as->usbin.flags & FLG_RUNNING) 
+			val |= PCM_ENABLE_INPUT;
+		if (file->f_mode & FMODE_WRITE && as->usbout.flags & FLG_RUNNING) 
+			val |= PCM_ENABLE_OUTPUT;
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_SETTRIGGER:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			if (val & PCM_ENABLE_INPUT) {
+				if (!as->usbin.dma.ready && (ret = prog_dmabuf_in(as)))
+					return ret;
+				if (usbin_start(as))
+					return -ENODEV;
+			} else
+				usbin_stop(as);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			if (val & PCM_ENABLE_OUTPUT) {
+				if (!as->usbout.dma.ready && (ret = prog_dmabuf_out(as)))
+					return ret;
+				if (usbout_start(as))
+					return -ENODEV;
+			} else
+				usbout_stop(as);
+		}
+		return 0;
+
+	case SNDCTL_DSP_GETOSPACE:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		if (!(as->usbout.flags & FLG_RUNNING) && (val = prog_dmabuf_out(as)) != 0)
+			return val;
+		spin_lock_irqsave(&as->lock, flags);
+		abinfo.fragsize = as->usbout.dma.fragsize;
+		abinfo.bytes = as->usbout.dma.dmasize - as->usbout.dma.count;
+		abinfo.fragstotal = as->usbout.dma.numfrag;
+		abinfo.fragments = abinfo.bytes >> as->usbout.dma.fragshift;      
+		spin_unlock_irqrestore(&as->lock, flags);
+		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_GETISPACE:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		if (!(as->usbin.flags & FLG_RUNNING) && (val = prog_dmabuf_in(as)) != 0)
+			return val;
+		spin_lock_irqsave(&as->lock, flags);
+		abinfo.fragsize = as->usbin.dma.fragsize;
+		abinfo.bytes = as->usbin.dma.count;
+		abinfo.fragstotal = as->usbin.dma.numfrag;
+		abinfo.fragments = abinfo.bytes >> as->usbin.dma.fragshift;      
+		spin_unlock_irqrestore(&as->lock, flags);
+		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		
+	case SNDCTL_DSP_NONBLOCK:
+		file->f_flags |= O_NONBLOCK;
+		return 0;
+
+	case SNDCTL_DSP_GETODELAY:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&as->lock, flags);
+		val = as->usbout.dma.count;
+		spin_unlock_irqrestore(&as->lock, flags);
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_GETIPTR:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		spin_lock_irqsave(&as->lock, flags);
+		cinfo.bytes = as->usbin.dma.total_bytes;
+		cinfo.blocks = as->usbin.dma.count >> as->usbin.dma.fragshift;
+		cinfo.ptr = as->usbin.dma.wrptr;
+		if (as->usbin.dma.mapped)
+			as->usbin.dma.count &= as->usbin.dma.fragsize-1;
+		spin_unlock_irqrestore(&as->lock, flags);
+		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+	case SNDCTL_DSP_GETOPTR:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&as->lock, flags);
+		cinfo.bytes = as->usbout.dma.total_bytes;
+		cinfo.blocks = as->usbout.dma.count >> as->usbout.dma.fragshift;
+		cinfo.ptr = as->usbout.dma.rdptr;
+		if (as->usbout.dma.mapped)
+			as->usbout.dma.count &= as->usbout.dma.fragsize-1;
+		spin_unlock_irqrestore(&as->lock, flags);
+		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+       case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE) {
+			if ((val = prog_dmabuf_out(as)))
+				return val;
+			return put_user(as->usbout.dma.fragsize, (int *)arg);
+		}
+		if ((val = prog_dmabuf_in(as)))
+			return val;
+		return put_user(as->usbin.dma.fragsize, (int *)arg);
+
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			as->usbin.dma.ossfragshift = val & 0xffff;
+			as->usbin.dma.ossmaxfrags = (val >> 16) & 0xffff;
+			if (as->usbin.dma.ossfragshift < 4)
+				as->usbin.dma.ossfragshift = 4;
+			if (as->usbin.dma.ossfragshift > 15)
+				as->usbin.dma.ossfragshift = 15;
+			if (as->usbin.dma.ossmaxfrags < 4)
+				as->usbin.dma.ossmaxfrags = 4;
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			as->usbout.dma.ossfragshift = val & 0xffff;
+			as->usbout.dma.ossmaxfrags = (val >> 16) & 0xffff;
+			if (as->usbout.dma.ossfragshift < 4)
+				as->usbout.dma.ossfragshift = 4;
+			if (as->usbout.dma.ossfragshift > 15)
+				as->usbout.dma.ossfragshift = 15;
+			if (as->usbout.dma.ossmaxfrags < 4)
+				as->usbout.dma.ossmaxfrags = 4;
+		}
+		return 0;
+
+	case SNDCTL_DSP_SUBDIVIDE:
+		if ((file->f_mode & FMODE_READ && as->usbin.dma.subdivision) ||
+		    (file->f_mode & FMODE_WRITE && as->usbout.dma.subdivision))
+			return -EINVAL;
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != 1 && val != 2 && val != 4)
+			return -EINVAL;
+		if (file->f_mode & FMODE_READ)
+			as->usbin.dma.subdivision = val;
+		if (file->f_mode & FMODE_WRITE)
+			as->usbout.dma.subdivision = val;
+		return 0;
+
+	case SOUND_PCM_READ_RATE:
+		return put_user((file->f_mode & FMODE_READ) ? as->usbin.dma.srate : as->usbout.dma.srate, (int *)arg);
+
+	case SOUND_PCM_READ_CHANNELS:
+		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+		return put_user(AFMT_ISSTEREO(val2) ? 2 : 1, (int *)arg);
+
+	case SOUND_PCM_READ_BITS:
+		val2 = (file->f_mode & FMODE_READ) ? as->usbin.dma.format : as->usbout.dma.format;
+		return put_user(AFMT_IS16BIT(val2) ? 16 : 8, (int *)arg);
+
+	case SOUND_PCM_WRITE_FILTER:
+	case SNDCTL_DSP_SETSYNCRO:
+	case SOUND_PCM_READ_FILTER:
+		return -EINVAL;
+	}
+	dprintk((KERN_DEBUG "usbaudio: usb_audio_ioctl - no command found\n"));
+	return -ENOIOCTLCMD;
+}
+
+static int usb_audio_open(struct inode *inode, struct file *file)
+{
+	unsigned int minor = minor(inode->i_rdev);
+	DECLARE_WAITQUEUE(wait, current);
+	struct list_head *devs, *adevs;
+	struct usb_audiodev *as;
+	struct usb_audio_state *s;
+
+	for (;;) {
+		down(&open_sem);
+		for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+			s = list_entry(devs, struct usb_audio_state, audiodev);
+			for (adevs = s->audiolist.next; adevs != &s->audiolist; adevs = adevs->next) {
+				as = list_entry(adevs, struct usb_audiodev, list);
+				if (!((as->dev_audio ^ minor) & ~0xf))
+					goto device_found;
+			}
+		}
+		up(&open_sem);
+		return -ENODEV;
+
+	device_found:
+		if (!s->usbdev) {
+			up(&open_sem);
+			return -EIO;
+		}
+		/* wait for device to become free */
+		if (!(as->open_mode & file->f_mode))
+			break;
+		if (file->f_flags & O_NONBLOCK) {
+			up(&open_sem);
+			return -EBUSY;
+		}
+		__set_current_state(TASK_INTERRUPTIBLE);
+		add_wait_queue(&open_wait, &wait);
+		up(&open_sem);
+		schedule();
+		__set_current_state(TASK_RUNNING);
+		remove_wait_queue(&open_wait, &wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+	if (file->f_mode & FMODE_READ)
+		as->usbin.dma.ossfragshift = as->usbin.dma.ossmaxfrags = as->usbin.dma.subdivision = 0;
+	if (file->f_mode & FMODE_WRITE)
+		as->usbout.dma.ossfragshift = as->usbout.dma.ossmaxfrags = as->usbout.dma.subdivision = 0;
+	if (set_format(as, file->f_mode, ((minor & 0xf) == SND_DEV_DSP16) ? AFMT_S16_LE : AFMT_U8 /* AFMT_ULAW */, 8000)) {
+		up(&open_sem);
+		return -EIO;
+	}
+	file->private_data = as;
+	as->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+	s->count++;
+	up(&open_sem);
+	return 0;
+}
+
+static int usb_audio_release(struct inode *inode, struct file *file)
+{
+	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
+	struct usb_audio_state *s;
+	struct usb_device *dev;
+	struct usb_interface *iface;
+
+	lock_kernel();
+	s = as->state;
+	dev = s->usbdev;
+	if (file->f_mode & FMODE_WRITE)
+		drain_out(as, file->f_flags & O_NONBLOCK);
+	down(&open_sem);
+	if (file->f_mode & FMODE_WRITE) {
+		usbout_stop(as);
+		if (dev && as->usbout.interface >= 0) {
+			iface = &dev->actconfig->interface[as->usbout.interface];
+			usb_set_interface(dev, iface->altsetting->bInterfaceNumber, 0);
+		}
+		dmabuf_release(&as->usbout.dma);
+		usbout_release(as);
+	}
+	if (file->f_mode & FMODE_READ) {
+		usbin_stop(as);
+		if (dev && as->usbin.interface >= 0) {
+			iface = &dev->actconfig->interface[as->usbin.interface];
+			usb_set_interface(dev, iface->altsetting->bInterfaceNumber, 0);
+		}
+		dmabuf_release(&as->usbin.dma);
+		usbin_release(as);
+	}
+	as->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+	release(s);
+	wake_up(&open_wait);
+	unlock_kernel();
+	return 0;
+}
+
+static /*const*/ struct file_operations usb_audio_fops = {
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	read:		usb_audio_read,
+	write:		usb_audio_write,
+	poll:		usb_audio_poll,
+	ioctl:		usb_audio_ioctl,
+	mmap:		usb_audio_mmap,
+	open:		usb_audio_open,
+	release:	usb_audio_release,
+};
+
+/* --------------------------------------------------------------------- */
+
+static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
+			      const struct usb_device_id *id);
+static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
+
+static struct usb_device_id usb_audio_ids [] = {
+    { match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
+      bInterfaceClass: USB_CLASS_AUDIO, bInterfaceSubClass: 1},
+    { }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_audio_ids);
+
+static struct usb_driver usb_audio_driver = {
+	name:		"audio",
+	probe:		usb_audio_probe,
+	disconnect:	usb_audio_disconnect,
+	driver_list:	LIST_HEAD_INIT(usb_audio_driver.driver_list), 
+	id_table:	usb_audio_ids,
+};
+
+static void *find_descriptor(void *descstart, unsigned int desclen, void *after, 
+			     u8 dtype, int iface, int altsetting)
+{
+	u8 *p, *end, *next;
+	int ifc = -1, as = -1;
+
+	p = descstart;
+	end = p + desclen;
+	for (; p < end;) {
+		if (p[0] < 2)
+			return NULL;
+		next = p + p[0];
+		if (next > end)
+			return NULL;
+		if (p[1] == USB_DT_INTERFACE) {
+			/* minimum length of interface descriptor */
+			if (p[0] < 9)
+				return NULL;
+			ifc = p[2];
+			as = p[3];
+		}
+		if (p[1] == dtype && (!after || (void *)p > after) &&
+		    (iface == -1 || iface == ifc) && (altsetting == -1 || altsetting == as)) {
+			return p;
+		}
+		p = next;
+	}
+	return NULL;
+}
+
+static void *find_csinterface_descriptor(void *descstart, unsigned int desclen, void *after, u8 dsubtype, int iface, int altsetting)
+{
+	unsigned char *p;
+
+	p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, altsetting);
+	while (p) {
+		if (p[0] >= 3 && p[2] == dsubtype)
+			return p;
+		p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, altsetting);
+	}
+	return NULL;
+}
+
+static void *find_audiocontrol_unit(void *descstart, unsigned int desclen, void *after, u8 unit, int iface)
+{
+	unsigned char *p;
+
+	p = find_descriptor(descstart, desclen, after, USB_DT_CS_INTERFACE, iface, -1);
+	while (p) {
+		if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT && p[3] == unit)
+			return p;
+		p = find_descriptor(descstart, desclen, p, USB_DT_CS_INTERFACE, iface, -1);
+	}
+	return NULL;
+}
+
+static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, int asifin, int asifout)
+{
+	struct usb_device *dev = s->usbdev;
+	struct usb_audiodev *as;
+	struct usb_config_descriptor *config = dev->actconfig;
+	struct usb_interface_descriptor *alts;
+	struct usb_interface *iface;
+	struct audioformat *fp;
+	unsigned char *fmt, *csep;
+	unsigned int i, j, k, format;
+
+	if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL)))
+		return;
+	memset(as, 0, sizeof(struct usb_audiodev));
+	init_waitqueue_head(&as->usbin.dma.wait);
+	init_waitqueue_head(&as->usbout.dma.wait);
+	spin_lock_init(&as->lock);
+	as->usbin.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
+	as->usbin.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
+	as->usbin.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
+	as->usbin.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
+	as->usbout.durb[0].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
+	as->usbout.durb[1].urb = usb_alloc_urb (DESCFRAMES, GFP_KERNEL);
+	as->usbout.surb[0].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
+	as->usbout.surb[1].urb = usb_alloc_urb (SYNCFRAMES, GFP_KERNEL);
+	if ((!as->usbin.durb[0].urb) ||
+	    (!as->usbin.durb[1].urb) ||
+	    (!as->usbin.surb[0].urb) ||
+	    (!as->usbin.surb[1].urb) ||
+	    (!as->usbout.durb[0].urb) ||
+	    (!as->usbout.durb[1].urb) ||
+	    (!as->usbout.surb[0].urb) ||
+	    (!as->usbout.surb[1].urb)) {
+		usb_free_urb(as->usbin.durb[0].urb);
+		usb_free_urb(as->usbin.durb[1].urb);
+		usb_free_urb(as->usbin.surb[0].urb);
+		usb_free_urb(as->usbin.surb[1].urb);
+		usb_free_urb(as->usbout.durb[0].urb);
+		usb_free_urb(as->usbout.durb[1].urb);
+		usb_free_urb(as->usbout.surb[0].urb);
+		usb_free_urb(as->usbout.surb[1].urb);
+		kfree(as);
+		return;
+	}
+	as->state = s;
+	as->usbin.interface = asifin;
+	as->usbout.interface = asifout;
+	/* search for input formats */
+	if (asifin >= 0) {
+		as->usbin.flags = FLG_CONNECTED;
+		iface = &config->interface[asifin];
+		for (i = 0; i < iface->num_altsetting; i++) {
+			alts = &iface->altsetting[i];
+			if (alts->bInterfaceClass != USB_CLASS_AUDIO || alts->bInterfaceSubClass != 2)
+				continue;
+			if (alts->bNumEndpoints < 1) {
+				if (i != 0) {  /* altsetting 0 has no endpoints (Section B.3.4.1) */
+					printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
+					       dev->devnum, asifin, i);
+				}
+				continue;
+			}
+			if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
+			    !(alts->endpoint[0].bEndpointAddress & 0x80)) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous in\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
+			fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifin, i);
+			if (!fmt) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
+			if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
+			format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
+			fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifin, i);
+			if (!fmt) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
+			if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
+			if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
+				       dev->devnum, asifin, i, fmt[4], fmt[5]);
+				continue;
+			}
+			csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifin, i);
+			if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", 
+				       dev->devnum, asifin, i);
+				continue;
+			}
+			if (as->numfmtin >= MAXFORMATS)
+				continue;
+			fp = &as->fmtin[as->numfmtin++];
+			if (fmt[5] == 2)
+				format &= (AFMT_U16_LE | AFMT_S16_LE);
+			else
+				format &= (AFMT_U8 | AFMT_S8);
+			if (fmt[4] == 2)
+				format |= AFMT_STEREO;
+			fp->format = format;
+			fp->altsetting = i;
+			fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16);
+			printk(KERN_INFO "usbaudio: valid input sample rate %u\n", fp->sratelo);
+			for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) {
+				k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16);
+				printk(KERN_INFO "usbaudio: valid input sample rate %u\n", k);
+				if (k > fp->sratehi)
+					fp->sratehi = k;
+				if (k < fp->sratelo)
+					fp->sratelo = k;
+			}
+			fp->attributes = csep[3];
+			printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", 
+			       dev->devnum, asifin, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes);
+		}
+	}
+	/* search for output formats */
+	if (asifout >= 0) {
+		as->usbout.flags = FLG_CONNECTED;
+		iface = &config->interface[asifout];
+		for (i = 0; i < iface->num_altsetting; i++) {
+			alts = &iface->altsetting[i];
+			if (alts->bInterfaceClass != USB_CLASS_AUDIO || alts->bInterfaceSubClass != 2)
+				continue;
+			if (alts->bNumEndpoints < 1) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			if ((alts->endpoint[0].bmAttributes & 0x03) != 0x01 ||
+			    (alts->endpoint[0].bEndpointAddress & 0x80)) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u first endpoint not isochronous out\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			/* See USB audio formats manual, section 2 */
+			fmt = find_csinterface_descriptor(buffer, buflen, NULL, AS_GENERAL, asifout, i);
+			if (!fmt) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			if (fmt[0] < 7 || fmt[6] != 0 || (fmt[5] != 1 && fmt[5] != 2)) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u format not supported\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
+			/* Dallas DS4201 workaround */
+			if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201)
+				format = (AFMT_S16_LE | AFMT_S8);
+			fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i);
+			if (!fmt) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			if (fmt[0] < 8+3*(fmt[7] ? fmt[7] : 2) || fmt[3] != 1) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not supported\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			if (fmt[4] < 1 || fmt[4] > 2 || fmt[5] < 1 || fmt[5] > 2) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u unsupported channels %u framesize %u\n", 
+				       dev->devnum, asifout, i, fmt[4], fmt[5]);
+				continue;
+			}
+			csep = find_descriptor(buffer, buflen, NULL, USB_DT_CS_ENDPOINT, asifout, i);
+			if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
+				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u no or invalid class specific endpoint descriptor\n", 
+				       dev->devnum, asifout, i);
+				continue;
+			}
+			if (as->numfmtout >= MAXFORMATS)
+				continue;
+			fp = &as->fmtout[as->numfmtout++];
+			if (fmt[5] == 2)
+				format &= (AFMT_U16_LE | AFMT_S16_LE);
+			else
+				format &= (AFMT_U8 | AFMT_S8);
+			if (fmt[4] == 2)
+				format |= AFMT_STEREO;
+			fp->format = format;
+			fp->altsetting = i;
+			fp->sratelo = fp->sratehi = fmt[8] | (fmt[9] << 8) | (fmt[10] << 16);
+			printk(KERN_INFO "usbaudio: valid output sample rate %u\n", fp->sratelo);
+			for (j = fmt[7] ? (fmt[7]-1) : 1; j > 0; j--) {
+				k = fmt[8+3*j] | (fmt[9+3*j] << 8) | (fmt[10+3*j] << 16);
+				printk(KERN_INFO "usbaudio: valid output sample rate %u\n", k);
+				if (k > fp->sratehi)
+					fp->sratehi = k;
+				if (k < fp->sratelo)
+					fp->sratelo = k;
+			}
+			fp->attributes = csep[3];
+			printk(KERN_INFO "usbaudio: device %u interface %u altsetting %u: format 0x%08x sratelo %u sratehi %u attributes 0x%02x\n", 
+			       dev->devnum, asifout, i, fp->format, fp->sratelo, fp->sratehi, fp->attributes);
+		}
+	}
+	if (as->numfmtin == 0 && as->numfmtout == 0) {
+		usb_free_urb(as->usbin.durb[0].urb);
+		usb_free_urb(as->usbin.durb[1].urb);
+		usb_free_urb(as->usbin.surb[0].urb);
+		usb_free_urb(as->usbin.surb[1].urb);
+		usb_free_urb(as->usbout.durb[0].urb);
+		usb_free_urb(as->usbout.durb[1].urb);
+		usb_free_urb(as->usbout.surb[0].urb);
+		usb_free_urb(as->usbout.surb[1].urb);
+		kfree(as);
+		return;
+	}
+	if ((as->dev_audio = register_sound_dsp(&usb_audio_fops, -1)) < 0) {
+		printk(KERN_ERR "usbaudio: cannot register dsp\n");
+		usb_free_urb(as->usbin.durb[0].urb);
+		usb_free_urb(as->usbin.durb[1].urb);
+		usb_free_urb(as->usbin.surb[0].urb);
+		usb_free_urb(as->usbin.surb[1].urb);
+		usb_free_urb(as->usbout.durb[0].urb);
+		usb_free_urb(as->usbout.durb[1].urb);
+		usb_free_urb(as->usbout.surb[0].urb);
+		usb_free_urb(as->usbout.surb[1].urb);
+		kfree(as);
+		return;
+	}
+	printk(KERN_INFO "usbaudio: registered dsp 14,%d\n", as->dev_audio);
+	/* everything successful */
+	list_add_tail(&as->list, &s->audiolist);
+}
+
+struct consmixstate {
+	struct usb_audio_state *s;
+	unsigned char *buffer;
+	unsigned int buflen;
+	unsigned int ctrlif;
+	struct mixerchannel mixch[SOUND_MIXER_NRDEVICES];
+	unsigned int nrmixch;
+	unsigned int mixchmask;
+	unsigned long unitbitmap[32/sizeof(unsigned long)];
+	/* return values */
+	unsigned int nrchannels;
+	unsigned int termtype;
+	unsigned int chconfig;
+};
+
+static struct mixerchannel *getmixchannel(struct consmixstate *state, unsigned int nr)
+{
+	struct mixerchannel *c;
+
+	if (nr >= SOUND_MIXER_NRDEVICES) {
+		printk(KERN_ERR "usbaudio: invalid OSS mixer channel %u\n", nr);
+		return NULL;
+	}
+	if (!(state->mixchmask & (1 << nr))) {
+		printk(KERN_WARNING "usbaudio: OSS mixer channel %u already in use\n", nr);
+		return NULL;
+	}
+	c = &state->mixch[state->nrmixch++];
+	c->osschannel = nr;
+	state->mixchmask &= ~(1 << nr);
+	return c;
+}
+
+static unsigned int getvolchannel(struct consmixstate *state)
+{
+	unsigned int u;
+
+	if ((state->termtype & 0xff00) == 0x0000 && (state->mixchmask & SOUND_MASK_VOLUME))
+		return SOUND_MIXER_VOLUME;
+	if ((state->termtype & 0xff00) == 0x0100) {
+		if (state->mixchmask & SOUND_MASK_PCM)
+			return SOUND_MIXER_PCM;
+		if (state->mixchmask & SOUND_MASK_ALTPCM)
+			return SOUND_MIXER_ALTPCM;
+	}
+	if ((state->termtype & 0xff00) == 0x0200 && (state->mixchmask & SOUND_MASK_MIC))
+		return SOUND_MIXER_MIC;
+	if ((state->termtype & 0xff00) == 0x0300 && (state->mixchmask & SOUND_MASK_SPEAKER))
+		return SOUND_MIXER_SPEAKER;
+	if ((state->termtype & 0xff00) == 0x0500) {
+		if (state->mixchmask & SOUND_MASK_PHONEIN)
+			return SOUND_MIXER_PHONEIN;
+		if (state->mixchmask & SOUND_MASK_PHONEOUT)
+			return SOUND_MIXER_PHONEOUT;
+	}
+	if (state->termtype >= 0x710 && state->termtype <= 0x711 && (state->mixchmask & SOUND_MASK_RADIO))
+		return SOUND_MIXER_RADIO;
+	if (state->termtype >= 0x709 && state->termtype <= 0x70f && (state->mixchmask & SOUND_MASK_VIDEO))
+		return SOUND_MIXER_VIDEO;
+	u = ffs(state->mixchmask & (SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_LINE3 |
+				    SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 | SOUND_MASK_DIGITAL3));
+	return u-1;
+}
+
+static void prepmixch(struct consmixstate *state)
+{
+	struct usb_device *dev = state->s->usbdev;
+	struct mixerchannel *ch;
+	unsigned char buf[2];
+	__s16 v1;
+	unsigned int v2, v3;
+
+	if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES)
+		return;
+	ch = &state->mixch[state->nrmixch-1];
+	switch (ch->selector) {
+	case 0:  /* mixer unit request */
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+		ch->minval = buf[0] | (buf[1] << 8);
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+		ch->maxval = buf[0] | (buf[1] << 8);
+		v2 = ch->maxval - ch->minval;
+		if (!v2)
+			v2 = 1;
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+		v1 = buf[0] | (buf[1] << 8);
+		v3 = v1 - ch->minval;
+		v3 = 100 * v3 / v2;
+		if (v3 > 100)
+			v3 = 100;
+		ch->value = v3;
+		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
+			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+					    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
+					    state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+			v1 = buf[0] | (buf[1] << 8);
+			v3 = v1 - ch->minval;
+			v3 = 100 * v3 / v2;
+			if (v3 > 100)
+				v3 = 100;
+		}
+		ch->value |= v3 << 8;
+		break;
+
+		/* various feature unit controls */
+	case VOLUME_CONTROL:
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+		ch->minval = buf[0] | (buf[1] << 8);
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+		ch->maxval = buf[0] | (buf[1] << 8);
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+			goto err;
+		v1 = buf[0] | (buf[1] << 8);
+		v2 = ch->maxval - ch->minval;
+		v3 = v1 - ch->minval;
+		if (!v2)
+			v2 = 1;
+		v3 = 100 * v3 / v2;
+		if (v3 > 100)
+			v3 = 100;
+		ch->value = v3;
+		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
+			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				goto err;
+			v1 = buf[0] | (buf[1] << 8);
+			v3 = v1 - ch->minval;
+			v3 = 100 * v3 / v2;
+			if (v3 > 100)
+				v3 = 100;
+		}
+		ch->value |= v3 << 8;
+		break;
+		
+	case BASS_CONTROL:
+	case MID_CONTROL:
+	case TREBLE_CONTROL:
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+			goto err;
+		ch->minval = buf[0] << 8;
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+			goto err;
+		ch->maxval = buf[0] << 8;
+		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+			goto err;
+		v1 = buf[0] << 8;
+		v2 = ch->maxval - ch->minval;
+		v3 = v1 - ch->minval;
+		if (!v2)
+			v2 = 1;
+		v3 = 100 * v3 / v2;
+		if (v3 > 100)
+			v3 = 100;
+		ch->value = v3;
+		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
+			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+				goto err;
+			v1 = buf[0] << 8;
+			v3 = v1 - ch->minval;
+			v3 = 100 * v3 / v2;
+			if (v3 > 100)
+				v3 = 100;
+		}
+		ch->value |= v3 << 8;
+		break;
+		
+	default:
+		goto err;
+	}
+	return;
+
+ err:
+	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
+	       dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector);
+	if (state->nrmixch)
+		state->nrmixch--;
+}
+
+
+static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid);
+
+extern inline int checkmixbmap(unsigned char *bmap, unsigned char flg, unsigned int inidx, unsigned int numoch)
+{
+	unsigned int idx;
+
+	idx = inidx*numoch;
+	if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7))))
+		return 0;
+	if (!(flg & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
+		return 1;
+	idx = (inidx+!!(flg & MIXFLG_STEREOIN))*numoch+!!(flg & MIXFLG_STEREOOUT);
+	if (!(bmap[-(idx >> 3)] & (0x80 >> (idx & 7))))
+		return 0;
+	return 1;
+}
+
+static void usb_audio_mixerunit(struct consmixstate *state, unsigned char *mixer)
+{
+	unsigned int nroutch = mixer[5+mixer[4]];
+	unsigned int chidx[SOUND_MIXER_NRDEVICES+1];
+	unsigned int termt[SOUND_MIXER_NRDEVICES];
+	unsigned char flg = (nroutch >= 2) ? MIXFLG_STEREOOUT : 0;
+	unsigned char *bmap = &mixer[9+mixer[4]];
+	unsigned int bmapsize;
+	struct mixerchannel *ch;
+	unsigned int i;
+
+	if (!mixer[4]) {
+		printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor\n", mixer[3]);
+		return;
+	}
+	if (mixer[4] > SOUND_MIXER_NRDEVICES) {
+		printk(KERN_ERR "usbaudio: mixer unit %u: too many input pins\n", mixer[3]);
+		return;
+	}
+	chidx[0] = 0;
+	for (i = 0; i < mixer[4]; i++) {
+		usb_audio_recurseunit(state, mixer[5+i]);
+		chidx[i+1] = chidx[i] + state->nrchannels;
+		termt[i] = state->termtype;
+	}
+	state->termtype = 0;
+	state->chconfig = mixer[6+mixer[4]] | (mixer[7+mixer[4]] << 8);
+	bmapsize = (nroutch * chidx[mixer[4]] + 7) >> 3;
+	bmap += bmapsize - 1;
+	if (mixer[0] < 10+mixer[4]+bmapsize) {
+		printk(KERN_ERR "usbaudio: unit %u invalid MIXER_UNIT descriptor (bitmap too small)\n", mixer[3]);
+		return;
+	}
+	for (i = 0; i < mixer[4]; i++) {
+		state->termtype = termt[i];
+		if (chidx[i+1]-chidx[i] >= 2) {
+			flg |= MIXFLG_STEREOIN;
+			if (checkmixbmap(bmap, flg, chidx[i], nroutch)) {
+				ch = getmixchannel(state, getvolchannel(state));
+				if (ch) {
+					ch->unitid = mixer[3];
+					ch->selector = 0;
+					ch->chnum = chidx[i]+1;
+					ch->flags = flg;
+					prepmixch(state);
+				}
+				continue;
+			}
+		}
+		flg &= ~MIXFLG_STEREOIN;
+		if (checkmixbmap(bmap, flg, chidx[i], nroutch)) {
+			ch = getmixchannel(state, getvolchannel(state));
+			if (ch) {
+				ch->unitid = mixer[3];
+				ch->selector = 0;
+				ch->chnum = chidx[i]+1;
+				ch->flags = flg;
+				prepmixch(state);
+			}
+		}
+	}	
+	state->termtype = 0;
+}
+
+static struct mixerchannel *slctsrc_findunit(struct consmixstate *state, __u8 unitid)
+{
+	unsigned int i;
+	
+	for (i = 0; i < state->nrmixch; i++)
+		if (state->mixch[i].unitid == unitid)
+			return &state->mixch[i];
+	return NULL;
+}
+
+static void usb_audio_selectorunit(struct consmixstate *state, unsigned char *selector)
+{
+	unsigned int chnum, i, mixch;
+	struct mixerchannel *mch;
+
+	if (!selector[4]) {
+		printk(KERN_ERR "usbaudio: unit %u invalid SELECTOR_UNIT descriptor\n", selector[3]);
+		return;
+	}
+	mixch = state->nrmixch;
+	usb_audio_recurseunit(state, selector[5]);
+	if (state->nrmixch != mixch) {
+		mch = &state->mixch[state->nrmixch-1];
+		mch->slctunitid = selector[3] | (1 << 8);
+	} else if ((mch = slctsrc_findunit(state, selector[5]))) {
+		mch->slctunitid = selector[3] | (1 << 8);
+	} else {
+		printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel 1\n", selector[3]);
+	}
+	chnum = state->nrchannels;
+	for (i = 1; i < selector[4]; i++) {
+		mixch = state->nrmixch;
+		usb_audio_recurseunit(state, selector[5+i]);
+		if (chnum != state->nrchannels) {
+			printk(KERN_ERR "usbaudio: selector unit %u: input pins with varying channel numbers\n", selector[3]);
+			state->termtype = 0;
+			state->chconfig = 0;
+			state->nrchannels = 0;
+			return;
+		}
+		if (state->nrmixch != mixch) {
+			mch = &state->mixch[state->nrmixch-1];
+			mch->slctunitid = selector[3] | ((i + 1) << 8);
+		} else if ((mch = slctsrc_findunit(state, selector[5+i]))) {
+			mch->slctunitid = selector[3] | ((i + 1) << 8);
+		} else {
+			printk(KERN_INFO "usbaudio: selector unit %u: ignoring channel %u\n", selector[3], i+1);
+		}
+	}
+	state->termtype = 0;
+	state->chconfig = 0;
+}
+
+/* in the future we might try to handle 3D etc. effect units */
+
+static void usb_audio_processingunit(struct consmixstate *state, unsigned char *proc)
+{
+	unsigned int i;
+
+	for (i = 0; i < proc[6]; i++)
+		usb_audio_recurseunit(state, proc[7+i]);
+	state->nrchannels = proc[7+proc[6]];
+	state->termtype = 0;
+	state->chconfig = proc[8+proc[6]] | (proc[9+proc[6]] << 8);
+}
+
+
+/* See Audio Class Spec, section 4.3.2.5 */
+static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr)
+{
+	struct mixerchannel *ch;
+	unsigned short chftr, mchftr;
+#if 0
+	struct usb_device *dev = state->s->usbdev;
+	unsigned char data[1];
+#endif
+	unsigned char nr_logical_channels, i;
+
+	usb_audio_recurseunit(state, ftr[4]);
+
+	if (ftr[5] == 0 ) {
+		printk(KERN_ERR "usbaudio: wrong controls size in feature unit %u\n",ftr[3]);
+		return;
+	}
+
+	if (state->nrchannels == 0) {
+		printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]);
+		return;
+	}
+	if (state->nrchannels > 2)
+		printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
+
+	nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
+
+	if (nr_logical_channels != state->nrchannels) {
+		printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels);
+
+		if (state->nrchannels == 1 && nr_logical_channels==0) {
+			printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n");
+		} else if (state->nrchannels == 1 && nr_logical_channels==2) {
+			printk(KERN_INFO "usbaudio: assuming that a stereo channel connected directly to a mixer is missing in search (got Labtec headset?). Should be fine.\n");
+			state->nrchannels=nr_logical_channels;
+		} else {
+			printk(KERN_WARNING "usbaudio: no idea what's going on..., contact linux-usb-devel@lists.sourceforge.net\n");
+		}
+	}
+
+	/* There is always a master channel */
+	mchftr = ftr[6];
+	/* Binary AND over logical channels if they exist */
+	if (nr_logical_channels) {
+		chftr = ftr[6+ftr[5]];
+		for (i = 2; i <= nr_logical_channels; i++)
+			chftr &= ftr[6+i*ftr[5]];
+	} else {
+		chftr = 0;
+	}
+
+	/* volume control */
+	if (chftr & 2) {
+		ch = getmixchannel(state, getvolchannel(state));
+		if (ch) {
+			ch->unitid = ftr[3];
+			ch->selector = VOLUME_CONTROL;
+			ch->chnum = 1;
+			ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0;
+			prepmixch(state);
+		}
+	} else if (mchftr & 2) {
+		ch = getmixchannel(state, getvolchannel(state));
+		if (ch) {
+			ch->unitid = ftr[3];
+			ch->selector = VOLUME_CONTROL;
+			ch->chnum = 0;
+			ch->flags = 0;
+			prepmixch(state);
+		}
+	}
+	/* bass control */
+	if (chftr & 4) {
+		ch = getmixchannel(state, SOUND_MIXER_BASS);
+		if (ch) {
+			ch->unitid = ftr[3];
+			ch->selector = BASS_CONTROL;
+			ch->chnum = 1;
+			ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0;
+			prepmixch(state);
+		}
+	} else if (mchftr & 4) {
+		ch = getmixchannel(state, SOUND_MIXER_BASS);
+		if (ch) {
+			ch->unitid = ftr[3];
+			ch->selector = BASS_CONTROL;
+			ch->chnum = 0;
+			ch->flags = 0;
+			prepmixch(state);
+		}
+	}
+	/* treble control */
+	if (chftr & 16) {
+		ch = getmixchannel(state, SOUND_MIXER_TREBLE);
+		if (ch) {
+			ch->unitid = ftr[3];
+			ch->selector = TREBLE_CONTROL;
+			ch->chnum = 1;
+			ch->flags = (state->nrchannels > 1) ? (MIXFLG_STEREOIN | MIXFLG_STEREOOUT) : 0;
+			prepmixch(state);
+		}
+	} else if (mchftr & 16) {
+		ch = getmixchannel(state, SOUND_MIXER_TREBLE);
+		if (ch) {
+			ch->unitid = ftr[3];
+			ch->selector = TREBLE_CONTROL;
+			ch->chnum = 0;
+			ch->flags = 0;
+			prepmixch(state);
+		}
+	}
+#if 0
+	/* if there are mute controls, unmute them */
+	/* does not seem to be necessary, and the Dallas chip does not seem to support the "all" channel (255) */
+	if ((chftr & 1) || (mchftr & 1)) {
+		printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif);
+		data[0] = 0;
+		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+				    (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, HZ) < 0)
+			printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif);
+ 	}
+#endif
+}
+
+static void usb_audio_recurseunit(struct consmixstate *state, unsigned char unitid)
+{
+	unsigned char *p1;
+	unsigned int i, j;
+
+	if (test_and_set_bit(unitid, &state->unitbitmap)) {
+		printk(KERN_INFO "usbaudio: mixer path revisits unit %d\n", unitid);
+		return;
+	}
+	p1 = find_audiocontrol_unit(state->buffer, state->buflen, NULL, unitid, state->ctrlif);
+	if (!p1) {
+		printk(KERN_ERR "usbaudio: unit %d not found!\n", unitid);
+		return;
+	}
+	state->nrchannels = 0;
+	state->termtype = 0;
+	state->chconfig = 0;
+	switch (p1[2]) {
+	case INPUT_TERMINAL:
+		if (p1[0] < 12) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid INPUT_TERMINAL descriptor\n", unitid);
+			return;
+		}
+		state->nrchannels = p1[7];
+		state->termtype = p1[4] | (p1[5] << 8);
+		state->chconfig = p1[8] | (p1[9] << 8);
+		return;
+
+	case MIXER_UNIT:
+		if (p1[0] < 10 || p1[0] < 10+p1[4]) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid MIXER_UNIT descriptor\n", unitid);
+			return;
+		}
+		usb_audio_mixerunit(state, p1);
+		return;
+
+	case SELECTOR_UNIT:
+		if (p1[0] < 6 || p1[0] < 6+p1[4]) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid SELECTOR_UNIT descriptor\n", unitid);
+			return;
+		}
+		usb_audio_selectorunit(state, p1);
+		return;
+
+	case FEATURE_UNIT: /* See USB Audio Class Spec 4.3.2.5 */
+		if (p1[0] < 7 || p1[0] < 7+p1[5]) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid);
+			return;
+		}
+		usb_audio_featureunit(state, p1);
+		return;		
+
+	case PROCESSING_UNIT:
+		if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]] || p1[0] < 13+p1[6]+p1[11+p1[6]]+p1[13+p1[6]+p1[11+p1[6]]]) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid PROCESSING_UNIT descriptor\n", unitid);
+			return;
+		}
+		usb_audio_processingunit(state, p1);
+		return;		
+
+	case EXTENSION_UNIT:
+		if (p1[0] < 13 || p1[0] < 13+p1[6] || p1[0] < 13+p1[6]+p1[11+p1[6]]) {
+			printk(KERN_ERR "usbaudio: unit %u: invalid EXTENSION_UNIT descriptor\n", unitid);
+			return;
+		}
+		for (j = i = 0; i < p1[6]; i++) {
+			usb_audio_recurseunit(state, p1[7+i]);
+			if (!i)
+				j = state->termtype;
+			else if (j != state->termtype)
+				j = 0;
+		}
+		state->nrchannels = p1[7+p1[6]];
+		state->chconfig = p1[8+p1[6]] | (p1[9+p1[6]] << 8);
+		state->termtype = j;
+		return;
+
+	default:
+		printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
+		return;
+	}
+}
+
+static void usb_audio_constructmixer(struct usb_audio_state *s, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif, unsigned char *oterm)
+{
+	struct usb_mixerdev *ms;
+	struct consmixstate state;
+
+	memset(&state, 0, sizeof(state));
+	state.s = s;
+	state.nrmixch = 0;
+	state.mixchmask = ~0;
+	state.buffer = buffer;
+	state.buflen = buflen;
+	state.ctrlif = ctrlif;
+	set_bit(oterm[3], &state.unitbitmap);  /* mark terminal ID as visited */
+	printk(KERN_DEBUG "usbaudio: constructing mixer for Terminal %u type 0x%04x\n",
+	       oterm[3], oterm[4] | (oterm[5] << 8));
+	usb_audio_recurseunit(&state, oterm[7]);
+	if (!state.nrmixch) {
+		printk(KERN_INFO "usbaudio: no mixer controls found for Terminal %u\n", oterm[3]);
+		return;
+	}
+	if (!(ms = kmalloc(sizeof(struct usb_mixerdev)+state.nrmixch*sizeof(struct mixerchannel), GFP_KERNEL)))
+		return;
+	memset(ms, 0, sizeof(struct usb_mixerdev));
+	memcpy(&ms->ch, &state.mixch, state.nrmixch*sizeof(struct mixerchannel));
+	ms->state = s;
+	ms->iface = ctrlif;
+	ms->numch = state.nrmixch;
+	if ((ms->dev_mixer = register_sound_mixer(&usb_mixer_fops, -1)) < 0) {
+		printk(KERN_ERR "usbaudio: cannot register mixer\n");
+		kfree(ms);
+		return;
+	}
+	printk(KERN_INFO "usbaudio: registered mixer 14,%d\n", ms->dev_mixer);
+	list_add_tail(&ms->list, &s->mixerlist);
+}
+
+static void *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
+{
+	struct usb_audio_state *s;
+	struct usb_config_descriptor *config = dev->actconfig;
+	struct usb_interface *iface;
+	unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES];
+	unsigned char *p1;
+	unsigned int i, j, k, numifin = 0, numifout = 0;
+	
+	if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL)))
+		return NULL;
+	memset(s, 0, sizeof(struct usb_audio_state));
+	INIT_LIST_HEAD(&s->audiolist);
+	INIT_LIST_HEAD(&s->mixerlist);
+	s->usbdev = dev;
+	s->count = 1;
+
+	/* find audiocontrol interface */
+	if (!(p1 = find_csinterface_descriptor(buffer, buflen, NULL, HEADER, ctrlif, -1))) {
+		printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u no HEADER found\n",
+		       dev->devnum, ctrlif);
+		goto ret;
+	}
+	if (p1[0] < 8 + p1[7]) {
+		printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u HEADER error\n",
+		       dev->devnum, ctrlif);
+		goto ret;
+	}
+	if (!p1[7])
+		printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has no AudioStreaming and MidiStreaming interfaces\n",
+		       dev->devnum, ctrlif);
+	for (i = 0; i < p1[7]; i++) {
+		j = p1[8+i];
+		if (j >= config->bNumInterfaces) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n",
+			       dev->devnum, ctrlif, j);
+			continue;
+		}
+		iface = &config->interface[j];
+		if (iface->altsetting[0].bInterfaceClass != USB_CLASS_AUDIO) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n",
+			       dev->devnum, ctrlif, j);
+			continue;
+		}
+		if (iface->altsetting[0].bInterfaceSubClass == 3) {
+			printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n",
+			       dev->devnum, ctrlif, j);
+			continue;
+		}
+		if (iface->altsetting[0].bInterfaceSubClass != 2) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n",
+			       dev->devnum, ctrlif, j);
+			continue;
+		}
+		if (iface->num_altsetting == 0) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has no working interface.\n", dev->devnum, ctrlif);
+			continue;
+		}
+		if (iface->num_altsetting == 1) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif);
+			continue;
+		}
+		if (iface->altsetting[0].bNumEndpoints > 0) {
+			/* Check all endpoints; should they all have a bandwidth of 0 ? */
+			for (k = 0; k < iface->altsetting[0].bNumEndpoints; k++) {
+				if (iface->altsetting[0].endpoint[k].wMaxPacketSize > 0) {
+					printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k);
+					break;
+				}
+			}
+			if (k < iface->altsetting[0].bNumEndpoints)
+				continue;
+		}
+		if (iface->altsetting[1].bNumEndpoints < 1) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n",
+			       dev->devnum, ctrlif, j);
+			continue;
+		}
+		/* note: this requires the data endpoint to be ep0 and the optional sync
+		   ep to be ep1, which seems to be the case */
+		if (iface->altsetting[1].endpoint[0].bEndpointAddress & USB_DIR_IN) {
+			if (numifin < USB_MAXINTERFACES) {
+				ifin[numifin++] = j;
+				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
+			}
+		} else {
+			if (numifout < USB_MAXINTERFACES) {
+				ifout[numifout++] = j;
+				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
+			}
+		}
+	}
+	printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n",
+	       dev->devnum, ctrlif, numifin, numifout);
+	for (i = 0; i < numifin && i < numifout; i++)
+		usb_audio_parsestreaming(s, buffer, buflen, ifin[i], ifout[i]);
+	for (j = i; j < numifin; j++)
+		usb_audio_parsestreaming(s, buffer, buflen, ifin[i], -1);
+	for (j = i; j < numifout; j++)
+		usb_audio_parsestreaming(s, buffer, buflen, -1, ifout[i]);
+	/* now walk through all OUTPUT_TERMINAL descriptors to search for mixers */
+	p1 = find_csinterface_descriptor(buffer, buflen, NULL, OUTPUT_TERMINAL, ctrlif, -1);
+	while (p1) {
+		if (p1[0] >= 9)
+			usb_audio_constructmixer(s, buffer, buflen, ctrlif, p1);
+		p1 = find_csinterface_descriptor(buffer, buflen, p1, OUTPUT_TERMINAL, ctrlif, -1);
+	}
+
+ret:
+	if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) {
+		kfree(s);
+		return NULL;
+	}
+	/* everything successful */
+	down(&open_sem);
+	list_add_tail(&s->audiodev, &audiodevs);
+	up(&open_sem);
+	printk(KERN_DEBUG "usb_audio_parsecontrol: usb_audio_state at %p\n", s);
+	return s;
+}
+
+/* we only care for the currently active configuration */
+
+static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
+			     const struct usb_device_id *id)
+{
+	struct usb_config_descriptor *config = dev->actconfig;	
+	unsigned char *buffer;
+	unsigned char buf[8];
+	unsigned int i, buflen;
+	int ret;
+
+#if 0
+	printk(KERN_DEBUG "usbaudio: Probing if %i: IC %x, ISC %x\n", ifnum,
+	       config->interface[ifnum].altsetting[0].bInterfaceClass,
+	       config->interface[ifnum].altsetting[0].bInterfaceSubClass);
+#endif
+
+	/*
+	 * audiocontrol interface found
+	 * find which configuration number is active
+	 */
+	i = dev->actconfig - config;
+
+	if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
+		printk(KERN_ERR "usbaudio: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue);
+		return NULL;
+	}
+	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8);
+	if (ret < 0) {
+		printk(KERN_ERR "usbaudio: cannot get first 8 bytes of config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
+		return NULL;
+	}
+	if (buf[1] != USB_DT_CONFIG || buf[0] < 9) {
+		printk(KERN_ERR "usbaudio: invalid config descriptor %d of device %d\n", i, dev->devnum);
+		return NULL;
+	}
+	buflen = buf[2] | (buf[3] << 8);
+	if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
+		return NULL;
+	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
+	if (ret < 0) {
+		kfree(buffer);
+		printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
+		return NULL;
+	}
+	return usb_audio_parsecontrol(dev, buffer, buflen, ifnum);
+}
+
+
+/* a revoke facility would make things simpler */
+
+static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_audio_state *s = (struct usb_audio_state *)ptr;
+	struct list_head *list;
+	struct usb_audiodev *as;
+	struct usb_mixerdev *ms;
+
+	/* we get called with -1 for every audiostreaming interface registered */
+	if (s == (struct usb_audio_state *)-1) {
+		dprintk((KERN_DEBUG "usbaudio: note, usb_audio_disconnect called with -1\n"));
+		return;
+	}
+	if (!s->usbdev) {
+		dprintk((KERN_DEBUG "usbaudio: error,  usb_audio_disconnect already called for %p!\n", s));
+		return;
+	}
+	down(&open_sem);
+	list_del(&s->audiodev);
+	INIT_LIST_HEAD(&s->audiodev);
+	s->usbdev = NULL;
+	/* deregister all audio and mixer devices, so no new processes can open this device */
+	for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
+		as = list_entry(list, struct usb_audiodev, list);
+		usbin_disc(as);
+		usbout_disc(as);
+		wake_up(&as->usbin.dma.wait);
+		wake_up(&as->usbout.dma.wait);
+		if (as->dev_audio >= 0) {
+			unregister_sound_dsp(as->dev_audio);
+			printk(KERN_INFO "usbaudio: unregister dsp 14,%d\n", as->dev_audio);
+		}
+		as->dev_audio = -1;
+	}
+	for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) {
+		ms = list_entry(list, struct usb_mixerdev, list);
+		if (ms->dev_mixer >= 0) {
+			unregister_sound_mixer(ms->dev_mixer);
+			printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer);
+		}
+		ms->dev_mixer = -1;
+	}
+	release(s);
+	wake_up(&open_wait);
+}
+
+static int __init usb_audio_init(void)
+{
+	usb_register(&usb_audio_driver);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+
+static void __exit usb_audio_cleanup(void)
+{
+	usb_deregister(&usb_audio_driver);
+}
+
+module_init(usb_audio_init);
+module_exit(usb_audio_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/class/audio.h b/drivers/usb/class/audio.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/audio.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,116 @@
+#define USB_DT_CS_DEVICE                0x21
+#define USB_DT_CS_CONFIG                0x22
+#define USB_DT_CS_STRING                0x23
+#define USB_DT_CS_INTERFACE             0x24
+#define USB_DT_CS_ENDPOINT              0x25
+
+#define CS_AUDIO_UNDEFINED		0x20
+#define CS_AUDIO_DEVICE			0x21
+#define CS_AUDIO_CONFIGURATION		0x22
+#define CS_AUDIO_STRING			0x23
+#define CS_AUDIO_INTERFACE		0x24
+#define CS_AUDIO_ENDPOINT		0x25
+
+#define HEADER				0x01
+#define INPUT_TERMINAL			0x02
+#define OUTPUT_TERMINAL			0x03
+#define MIXER_UNIT			0x04
+#define SELECTOR_UNIT			0x05
+#define FEATURE_UNIT			0x06
+#define PROCESSING_UNIT			0x07
+#define EXTENSION_UNIT			0x08
+
+#define AS_GENERAL			0x01
+#define FORMAT_TYPE			0x02
+#define FORMAT_SPECIFIC			0x03
+
+#define EP_GENERAL			0x01
+
+#define MAX_CHAN			9
+#define MAX_FREQ			16
+#define MAX_IFACE			8
+#define MAX_FORMAT			8
+#define MAX_ALT				32 	/* Sorry, we need quite a few for the Philips webcams */
+
+struct usb_audio_terminal
+{	
+	u8	flags;
+	u8	assoc;
+	u16	type;			/* Mic etc */
+	u8	channels;
+	u8	source;
+	u16	chancfg;
+};
+
+struct usb_audio_format
+{
+	u8	type;
+	u8	channels;
+	u8	num_freq;
+	u8	sfz;
+	u8	bits;
+	u16	freq[MAX_FREQ];
+};
+
+struct usb_audio_interface
+{
+	u8	terminal;
+	u8	delay;
+	u16	num_formats;
+	u16	format_type;
+	u8	flags;
+	u8	idleconf;	/* Idle config */
+#define AU_IFACE_FOUND	1
+	struct  usb_audio_format format[MAX_FORMAT];
+};
+
+struct usb_audio_device
+{
+	struct list_head list;
+	u8	mixer;
+	u8	selector;
+	void	*irq_handle;
+	u8	num_channels;
+	u8	num_dsp_iface;
+	u8	channel_map[MAX_CHAN];
+	struct usb_audio_terminal terminal[MAX_CHAN];
+	struct usb_audio_interface interface[MAX_IFACE][MAX_ALT];
+};
+
+
+
+/* Audio Class specific Request Codes */
+
+#define SET_CUR    0x01
+#define GET_CUR    0x81
+#define SET_MIN    0x02
+#define GET_MIN    0x82
+#define SET_MAX    0x03
+#define GET_MAX    0x83
+#define SET_RES    0x04
+#define GET_RES    0x84
+#define SET_MEM    0x05
+#define GET_MEM    0x85
+#define GET_STAT   0xff
+
+/* Terminal Control Selectors */
+
+#define COPY_PROTECT_CONTROL       0x01
+
+/* Feature Unit Control Selectors */
+
+#define MUTE_CONTROL               0x01
+#define VOLUME_CONTROL             0x02
+#define BASS_CONTROL               0x03
+#define MID_CONTROL                0x04
+#define TREBLE_CONTROL             0x05
+#define GRAPHIC_EQUALIZER_CONTROL  0x06
+#define AUTOMATIC_GAIN_CONTROL     0x07
+#define DELAY_CONTROL              0x08
+#define BASS_BOOST_CONTROL         0x09
+#define LOUDNESS_CONTROL           0x0a
+
+/* Endpoint Control Selectors */
+
+#define SAMPLING_FREQ_CONTROL      0x01
+#define PITCH_CONTROL              0x02
diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/bluetty.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,1364 @@
+/*
+ * bluetty.c   Version 0.13
+ *
+ * Copyright (c) 2000, 2001 Greg Kroah-Hartman	<greg@kroah.com>
+ * Copyright (c) 2000 Mark Douglas Corner	<mcorner@umich.edu>
+ *
+ * USB Bluetooth TTY driver, based on the Bluetooth Spec version 1.0B
+ * 
+ * (2001/11/30) Version 0.13 gkh
+ *	- added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
+ *	- removed active variable, as open_count will do.
+ *
+ * (2001/07/09) Version 0.12 gkh
+ *	- removed in_interrupt() call, as it doesn't make sense to do 
+ *	  that anymore.
+ *
+ * (2001/06/05) Version 0.11 gkh
+ *	- Fixed problem with read urb status saying that we have shutdown,
+ *	  and that we shouldn't resubmit the urb.  Patch from unknown.
+ *
+ * (2001/05/28) Version 0.10 gkh
+ *	- Fixed problem with using data from userspace in the bluetooth_write
+ *	  function as found by the CHECKER project.
+ *	- Added a buffer to the write_urb_pool which reduces the number of
+ *	  buffers being created and destroyed for ever write.  Also cleans
+ *	  up the logic a bit.
+ *	- Added a buffer to the control_urb_pool which fixes a memory leak
+ *	  when the device is removed from the system.
+ *
+ * (2001/05/28) Version 0.9 gkh
+ *	Fixed problem with bluetooth==NULL for bluetooth_read_bulk_callback
+ *	which was found by both the CHECKER project and Mikko Rahkonen.
+ *
+ * (08/04/2001) gb
+ *	Identify version on module load.
+ *
+ * (2001/03/10) Version 0.8 gkh
+ *	Fixed problem with not unlinking interrupt urb on device close
+ *	and resubmitting the read urb on error with bluetooth struct.
+ *	Thanks to Narayan Mohanram <narayan@RovingNetworks.com> for the
+ *	fixes.
+ *
+ * (11/29/2000) Version 0.7 gkh
+ *	Fixed problem with overrunning the tty flip buffer.
+ *	Removed unneeded NULL pointer initialization.
+ *
+ * (10/05/2000) Version 0.6 gkh
+ *	Fixed bug with urb->dev not being set properly, now that the usb
+ *	core needs it.
+ *	Got a real major id number and name.
+ *
+ * (08/06/2000) Version 0.5 gkh
+ *	Fixed problem of not resubmitting the bulk read urb if there is
+ *	an error in the callback.  Ericsson devices seem to need this.
+ *
+ * (07/11/2000) Version 0.4 gkh
+ *	Fixed bug in disconnect for when we call tty_hangup
+ *	Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not
+ *	getting attached to the control urb properly.
+ *	Fixed bug in bluetooth_write where we pay attention to the result
+ *	of bluetooth_ctrl_msg.
+ *
+ * (08/03/2000) Version 0.3 gkh mdc
+ *	Merged in Mark's changes to make the driver play nice with the Axis
+ *	stack.
+ *	Made the write bulk use an urb pool to enable larger transfers with
+ *	fewer calls to the driver.
+ *	Fixed off by one bug in acl pkt receive
+ *	Made packet counters specific to each bluetooth device 
+ *	Added checks for zero length callbacks
+ *	Added buffers for int and bulk packets.  Had to do this otherwise 
+ *	packet types could intermingle.
+ *	Made a control urb pool for the control messages.
+ *
+ * (07/11/2000) Version 0.2 gkh
+ *	Fixed a small bug found by Nils Faerber in the usb_bluetooth_probe 
+ *	function.
+ *
+ * (07/09/2000) Version 0.1 gkh
+ *	Initial release. Has support for sending ACL data (which is really just
+ *	a HCI frame.) Raw HCI commands and HCI events are not supported.
+ *	A ioctl will probably be needed for the HCI commands and events in the
+ *	future. All isoch endpoints are ignored at this time also.
+ *	This driver should work for all currently shipping USB Bluetooth 
+ *	devices at this time :)
+ * 
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+
+#define DEBUG
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.13"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
+#define DRIVER_DESC "USB Bluetooth tty driver"
+
+/* define this if you have hardware that is not good */
+/*#define	BTBUGGYHARDWARE */
+
+/* Class, SubClass, and Protocol codes that describe a Bluetooth device */
+#define WIRELESS_CLASS_CODE			0xe0
+#define RF_SUBCLASS_CODE			0x01
+#define BLUETOOTH_PROGRAMMING_PROTOCOL_CODE	0x01
+
+
+#define BLUETOOTH_TTY_MAJOR	216	/* real device node major id */
+#define BLUETOOTH_TTY_MINORS	256	/* whole lotta bluetooth devices */
+
+#define USB_BLUETOOTH_MAGIC	0x6d02	/* magic number for bluetooth struct */
+
+#define BLUETOOTH_CONTROL_REQUEST_TYPE	0x20
+
+/* Bluetooth packet types */
+#define CMD_PKT			0x01
+#define ACL_PKT			0x02
+#define SCO_PKT			0x03
+#define EVENT_PKT		0x04
+#define ERROR_PKT		0x05
+#define NEG_PKT			0x06
+
+/* Message sizes */
+#define MAX_EVENT_SIZE		0xFF
+#define EVENT_HDR_SIZE		3	/* 2 for the header + 1 for the type indicator */
+#define EVENT_BUFFER_SIZE	(MAX_EVENT_SIZE + EVENT_HDR_SIZE)
+
+#define MAX_ACL_SIZE		0xFFFF
+#define ACL_HDR_SIZE		5	/* 4 for the header + 1 for the type indicator */
+#define ACL_BUFFER_SIZE		(MAX_ACL_SIZE + ACL_HDR_SIZE)
+
+/* parity check flag */
+#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+#define CHAR2INT16(c1,c0)	(((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
+
+#define NUM_BULK_URBS		24
+#define NUM_CONTROL_URBS	16
+
+struct usb_bluetooth {
+	int			magic;
+	struct usb_device *	dev;
+	struct tty_driver *	tty_driver;	/* the tty_driver for this device */
+	struct tty_struct *	tty;		/* the coresponding tty for this port */
+
+	unsigned char		minor;		/* the starting minor number for this device */
+	int			throttle;	/* throttled by tty layer */
+	int			open_count;
+	
+	__u8			control_out_bInterfaceNum;
+	struct urb *		control_urb_pool[NUM_CONTROL_URBS];
+	struct usb_ctrlrequest	dr[NUM_CONTROL_URBS];
+
+	unsigned char *		interrupt_in_buffer;
+	struct urb *		interrupt_in_urb;
+	__u8			interrupt_in_endpointAddress;
+	__u8			interrupt_in_interval;
+	int			interrupt_in_buffer_size;
+
+	unsigned char *		bulk_in_buffer;
+	struct urb *		read_urb;
+	__u8			bulk_in_endpointAddress;
+	int			bulk_in_buffer_size;
+
+	int			bulk_out_buffer_size;
+	struct urb *		write_urb_pool[NUM_BULK_URBS];
+	__u8			bulk_out_endpointAddress;
+
+	wait_queue_head_t	write_wait;
+
+	struct tq_struct	tqueue;		/* task queue for line discipline waking up */
+	
+	unsigned int		int_packet_pos;
+	unsigned char		int_buffer[EVENT_BUFFER_SIZE];
+	unsigned int		bulk_packet_pos;
+	unsigned char		bulk_buffer[ACL_BUFFER_SIZE];	/* 64k preallocated, fix? */
+	struct semaphore	lock;
+};
+
+
+/* local function prototypes */
+static int  bluetooth_open		(struct tty_struct *tty, struct file *filp);
+static void bluetooth_close		(struct tty_struct *tty, struct file *filp);
+static int  bluetooth_write		(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static int  bluetooth_write_room	(struct tty_struct *tty);
+static int  bluetooth_chars_in_buffer	(struct tty_struct *tty);
+static void bluetooth_throttle		(struct tty_struct *tty);
+static void bluetooth_unthrottle	(struct tty_struct *tty);
+static int  bluetooth_ioctl		(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
+static void bluetooth_set_termios	(struct tty_struct *tty, struct termios *old);
+
+static void bluetooth_int_callback		(struct urb *urb);
+static void bluetooth_ctrl_callback		(struct urb *urb);
+static void bluetooth_read_bulk_callback	(struct urb *urb);
+static void bluetooth_write_bulk_callback	(struct urb *urb);
+
+static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
+			 	  const struct usb_device_id *id);
+static void usb_bluetooth_disconnect	(struct usb_device *dev, void *ptr);
+
+
+static struct usb_device_id usb_bluetooth_ids [] = {
+	{ USB_DEVICE_INFO(WIRELESS_CLASS_CODE, RF_SUBCLASS_CODE, BLUETOOTH_PROGRAMMING_PROTOCOL_CODE) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
+
+static struct usb_driver usb_bluetooth_driver = {
+	name:		"bluetty",
+	probe:		usb_bluetooth_probe,
+	disconnect:	usb_bluetooth_disconnect,
+	id_table:	usb_bluetooth_ids,
+};
+
+static int			bluetooth_refcount;
+static struct tty_driver	bluetooth_tty_driver;
+static struct tty_struct *	bluetooth_tty[BLUETOOTH_TTY_MINORS];
+static struct termios *		bluetooth_termios[BLUETOOTH_TTY_MINORS];
+static struct termios *		bluetooth_termios_locked[BLUETOOTH_TTY_MINORS];
+static struct usb_bluetooth	*bluetooth_table[BLUETOOTH_TTY_MINORS];
+
+
+static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
+{
+	if (!bluetooth) {
+		dbg("%s - bluetooth == NULL", function);
+		return -1;
+	}
+	if (bluetooth->magic != USB_BLUETOOTH_MAGIC) {
+		dbg("%s - bad magic number for bluetooth", function);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static inline struct usb_bluetooth* get_usb_bluetooth (struct usb_bluetooth *bluetooth, const char *function)
+{
+	if (!bluetooth || 
+	    bluetooth_paranoia_check (bluetooth, function)) { 
+		/* then say that we dont have a valid usb_bluetooth thing, which will
+		 * end up generating -ENODEV return values */
+		return NULL;
+	}
+
+	return bluetooth;
+}
+
+
+static inline struct usb_bluetooth *get_bluetooth_by_minor (int minor)
+{
+	return bluetooth_table[minor];
+}
+
+
+static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int value, const unsigned char *buf, int len)
+{
+	struct urb *urb = NULL;
+	struct usb_ctrlrequest *dr = NULL;
+	int i;
+	int status;
+
+	dbg (__FUNCTION__);
+
+	/* try to find a free urb in our list */
+	for (i = 0; i < NUM_CONTROL_URBS; ++i) {
+		if (bluetooth->control_urb_pool[i]->status != -EINPROGRESS) {
+			urb = bluetooth->control_urb_pool[i];
+			dr = &bluetooth->dr[i];
+			break;
+		}
+	}
+	if (urb == NULL) {
+		dbg (__FUNCTION__ " - no free urbs");
+		return -ENOMEM;
+	}
+
+	/* keep increasing the urb transfer buffer to fit the size of the message */
+	if (urb->transfer_buffer == NULL) {
+		urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
+		if (urb->transfer_buffer == NULL) {
+			err (__FUNCTION__" - out of memory");
+			return -ENOMEM;
+		}
+	}
+	if (urb->transfer_buffer_length < len) {
+		kfree (urb->transfer_buffer);
+		urb->transfer_buffer = kmalloc (len, GFP_KERNEL);
+		if (urb->transfer_buffer == NULL) {
+			err (__FUNCTION__" - out of memory");
+			return -ENOMEM;
+		}
+	}
+	memcpy (urb->transfer_buffer, buf, len);
+
+	dr->bRequestType= BLUETOOTH_CONTROL_REQUEST_TYPE;
+	dr->bRequest = request;
+	dr->wValue = cpu_to_le16((u16) value);
+	dr->wIndex = cpu_to_le16((u16) bluetooth->control_out_bInterfaceNum);
+	dr->wLength = cpu_to_le16((u16) len);
+	
+	FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
+			  (unsigned char*)dr, urb->transfer_buffer, len, bluetooth_ctrl_callback, bluetooth);
+
+	/* send it down the pipe */
+	status = usb_submit_urb(urb, GFP_KERNEL);
+	if (status)
+		dbg(__FUNCTION__ " - usb_submit_urb(control) failed with status = %d", status);
+	
+	return status;
+}
+
+
+
+
+
+/*****************************************************************************
+ * Driver tty interface functions
+ *****************************************************************************/
+static int bluetooth_open (struct tty_struct *tty, struct file * filp)
+{
+	struct usb_bluetooth *bluetooth;
+	int result;
+
+	dbg(__FUNCTION__);
+
+	/* initialize the pointer incase something fails */
+	tty->driver_data = NULL;
+
+	/* get the bluetooth object associated with this tty pointer */
+	bluetooth = get_bluetooth_by_minor (minor(tty->device));
+
+	if (bluetooth_paranoia_check (bluetooth, __FUNCTION__)) {
+		return -ENODEV;
+	}
+
+	down (&bluetooth->lock);
+ 
+	++bluetooth->open_count;
+	if (bluetooth->open_count == 1) {
+		/* set up our structure making the tty driver remember our object, and us it */
+		tty->driver_data = bluetooth;
+		bluetooth->tty = tty;
+
+		/* force low_latency on so that our tty_push actually forces the data through, 
+	 	* otherwise it is scheduled, and with high data rates (like with OHCI) data
+	 	* can get lost. */
+		bluetooth->tty->low_latency = 1;
+	
+		/* Reset the packet position counters */
+		bluetooth->int_packet_pos = 0;
+		bluetooth->bulk_packet_pos = 0;
+
+#ifndef BTBUGGYHARDWARE
+		/* Start reading from the device */
+		FILL_BULK_URB (bluetooth->read_urb, bluetooth->dev, 
+			       usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
+			       bluetooth->bulk_in_buffer,
+			       bluetooth->bulk_in_buffer_size,
+			       bluetooth_read_bulk_callback, bluetooth);
+		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
+		if (result)
+			dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
+#endif
+		FILL_INT_URB (bluetooth->interrupt_in_urb, bluetooth->dev,
+			      usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
+			      bluetooth->interrupt_in_buffer,
+			      bluetooth->interrupt_in_buffer_size,
+			      bluetooth_int_callback, bluetooth,
+			      bluetooth->interrupt_in_interval);
+		result = usb_submit_urb(bluetooth->interrupt_in_urb, GFP_KERNEL);
+		if (result)
+			dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
+	}
+	
+	up(&bluetooth->lock);
+
+	return 0;
+}
+
+
+static void bluetooth_close (struct tty_struct *tty, struct file * filp)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+	int i;
+
+	if (!bluetooth) {
+		return;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not opened");
+		return;
+	}
+
+	down (&bluetooth->lock);
+ 
+	--bluetooth->open_count;
+	if (bluetooth->open_count <= 0) {
+		bluetooth->open_count = 0;
+
+		/* shutdown any bulk reads and writes that might be going on */
+		for (i = 0; i < NUM_BULK_URBS; ++i)
+			usb_unlink_urb (bluetooth->write_urb_pool[i]);
+		usb_unlink_urb (bluetooth->read_urb);
+		usb_unlink_urb (bluetooth->interrupt_in_urb);
+	}
+	up(&bluetooth->lock);
+}
+
+
+static int bluetooth_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+	struct urb *urb = NULL;
+	unsigned char *temp_buffer = NULL;
+	const unsigned char *current_buffer;
+	const unsigned char *current_position;
+	int bytes_sent;
+	int buffer_size;
+	int i;
+	int retval = 0;
+
+	if (!bluetooth) {
+		return -ENODEV;
+	}
+
+	dbg(__FUNCTION__ " - %d byte(s)", count);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not opened");
+		return -EINVAL;
+	}
+
+	if (count == 0) {
+		dbg(__FUNCTION__ " - write request of 0 bytes");
+		return 0;
+	}
+	if (count == 1) {
+		dbg(__FUNCTION__ " - write request only included type %d", buf[0]);
+		return 1;
+	}
+
+#ifdef DEBUG
+	printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ " - length = %d, data = ", count);
+	for (i = 0; i < count; ++i) {
+		printk ("%.2x ", buf[i]);
+	}
+	printk ("\n");
+#endif
+
+	if (from_user) {
+		temp_buffer = kmalloc (count, GFP_KERNEL);
+		if (temp_buffer == NULL) {
+			err (__FUNCTION__ "- out of memory.");
+			retval = -ENOMEM;
+			goto exit;
+		}
+		copy_from_user (temp_buffer, buf, count);
+		current_buffer = temp_buffer;
+	} else {
+		current_buffer = buf;
+	}
+
+	switch (*current_buffer) {
+		/* First byte indicates the type of packet */
+		case CMD_PKT:
+			/* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/
+
+			retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, &current_buffer[1], count-1);
+			if (retval) {
+				goto exit;
+			}
+			retval = count;
+			break;
+
+		case ACL_PKT:
+			current_position = current_buffer;
+			++current_position;
+			--count;
+			bytes_sent = 0;
+
+			while (count > 0) {
+				urb = NULL;
+
+				/* try to find a free urb in our list */
+				for (i = 0; i < NUM_BULK_URBS; ++i) {
+					if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
+						urb = bluetooth->write_urb_pool[i];
+						break;
+					}
+				}
+				if (urb == NULL) {
+					dbg (__FUNCTION__ " - no free urbs");
+					retval = bytes_sent;
+					goto exit;
+				}
+				
+
+				buffer_size = min (count, bluetooth->bulk_out_buffer_size);
+				memcpy (urb->transfer_buffer, current_position, buffer_size);
+
+				/* build up our urb */
+				FILL_BULK_URB (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress),
+						urb->transfer_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth);
+				urb->transfer_flags |= USB_QUEUE_BULK;
+
+				/* send it down the pipe */
+				retval = usb_submit_urb(urb, GFP_KERNEL);
+				if (retval) {
+					dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with error = %d", retval);
+					goto exit;
+				}
+#ifdef BTBUGGYHARDWARE
+				/* A workaround for the stalled data bug */
+				/* May or may not be needed...*/
+				if (count != 0) {
+					udelay(500);
+				}
+#endif
+				current_position += buffer_size;
+				bytes_sent += buffer_size;
+				count -= buffer_size;
+			}
+
+			retval = bytes_sent + 1;
+			break;
+		
+		default :
+			dbg(__FUNCTION__" - unsupported (at this time) write type");
+			retval = -EINVAL;
+			break;
+	}
+
+exit:
+	if (temp_buffer != NULL)
+		kfree (temp_buffer);
+
+	return retval;
+} 
+
+
+static int bluetooth_write_room (struct tty_struct *tty) 
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+	int room = 0;
+	int i;
+
+	if (!bluetooth) {
+		return -ENODEV;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < NUM_BULK_URBS; ++i) {
+		if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
+			room += bluetooth->bulk_out_buffer_size;
+		}
+	}
+
+	dbg(__FUNCTION__ " - returns %d", room);
+	return room;
+}
+
+
+static int bluetooth_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+	int chars = 0;
+	int i;
+
+	if (!bluetooth) {
+		return -ENODEV;
+	}
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < NUM_BULK_URBS; ++i) {
+		if (bluetooth->write_urb_pool[i]->status == -EINPROGRESS) {
+			chars += bluetooth->write_urb_pool[i]->transfer_buffer_length;
+		}
+	}
+
+	dbg (__FUNCTION__ " - returns %d", chars);
+	return chars;
+}
+
+
+static void bluetooth_throttle (struct tty_struct * tty)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+
+	if (!bluetooth) {
+		return;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return;
+	}
+	
+	dbg(__FUNCTION__ " unsupported (at this time)");
+
+	return;
+}
+
+
+static void bluetooth_unthrottle (struct tty_struct * tty)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+
+	if (!bluetooth) {
+		return;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return;
+	}
+
+	dbg(__FUNCTION__ " unsupported (at this time)");
+}
+
+
+static int bluetooth_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+
+	if (!bluetooth) {
+		return -ENODEV;
+	}
+
+	dbg(__FUNCTION__ " - cmd 0x%.4x", cmd);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return -ENODEV;
+	}
+
+	/* FIXME!!! */
+	return -ENOIOCTLCMD;
+}
+
+
+static void bluetooth_set_termios (struct tty_struct *tty, struct termios * old)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+
+	if (!bluetooth) {
+		return;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return;
+	}
+
+	/* FIXME!!! */
+
+	return;
+}
+
+
+#ifdef BTBUGGYHARDWARE
+void btusb_enable_bulk_read(struct tty_struct *tty){
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+	int result;
+
+	if (!bluetooth) {
+		return;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return;
+	}
+
+	if (bluetooth->read_urb) {
+		FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
+			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
+			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
+			      bluetooth_read_bulk_callback, bluetooth);
+		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
+		if (result)
+			err (__FUNCTION__ " - failed submitting read urb, error %d", result);
+	}
+}
+
+void btusb_disable_bulk_read(struct tty_struct *tty){
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
+
+	if (!bluetooth) {
+		return;
+	}
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth->open_count) {
+		dbg (__FUNCTION__ " - device not open");
+		return;
+	}
+
+	if ((bluetooth->read_urb) && (bluetooth->read_urb->actual_length))
+		usb_unlink_urb(bluetooth->read_urb);
+}
+#endif
+
+
+/*****************************************************************************
+ * urb callback functions
+ *****************************************************************************/
+
+
+static void bluetooth_int_callback (struct urb *urb)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
+	unsigned char *data = urb->transfer_buffer;
+	unsigned int i;
+	unsigned int count = urb->actual_length;
+	unsigned int packet_size;
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth) {
+		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
+		return;
+	}
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero int status received: %d", urb->status);
+		return;
+	}
+
+	if (!count) {
+		dbg(__FUNCTION__ " - zero length int");
+		return;
+	}
+
+
+#ifdef DEBUG
+	if (count) {
+		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
+		for (i = 0; i < count; ++i) {
+			printk ("%.2x ", data[i]);
+		}
+		printk ("\n");
+	}
+#endif
+
+#ifdef BTBUGGYHARDWARE
+	if ((count >= 2) && (data[0] == 0xFF) && (data[1] == 0x00)) {
+		data += 2;
+		count -= 2;
+	}
+	if (count == 0) {
+		urb->actual_length = 0;
+		return;
+	}
+#endif
+	/* We add  a packet type identifier to the beginning of each
+	   HCI frame.  This makes the data in the tty look like a
+	   serial USB devices.  Each HCI frame can be broken across
+	   multiple URBs so we buffer them until we have a full hci
+	   packet */
+
+	if (!bluetooth->int_packet_pos) {
+		bluetooth->int_buffer[0] = EVENT_PKT;
+		bluetooth->int_packet_pos++;
+	}
+	
+	if (bluetooth->int_packet_pos + count > EVENT_BUFFER_SIZE) {
+		err(__FUNCTION__ " - exceeded EVENT_BUFFER_SIZE");
+		bluetooth->int_packet_pos = 0;
+		return;
+	}
+
+	memcpy (&bluetooth->int_buffer[bluetooth->int_packet_pos],
+		urb->transfer_buffer, count);
+	bluetooth->int_packet_pos += count;
+	urb->actual_length = 0;
+
+	if (bluetooth->int_packet_pos >= EVENT_HDR_SIZE)
+		packet_size = bluetooth->int_buffer[2];
+	else
+		return;
+
+	if (packet_size + EVENT_HDR_SIZE < bluetooth->int_packet_pos) {
+		err(__FUNCTION__ " - packet was too long");
+		bluetooth->int_packet_pos = 0;
+		return;
+	}
+
+	if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
+		for (i = 0; i < bluetooth->int_packet_pos; ++i) {
+			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
+			if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(bluetooth->tty);
+			}
+			tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
+		}
+		tty_flip_buffer_push(bluetooth->tty);
+
+		bluetooth->int_packet_pos = 0;
+	}
+}
+
+
+static void bluetooth_ctrl_callback (struct urb *urb)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth) {
+		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
+		return;
+	}
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+}
+
+
+static void bluetooth_read_bulk_callback (struct urb *urb)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
+	unsigned char *data = urb->transfer_buffer;
+	unsigned int count = urb->actual_length;
+	unsigned int i;
+	unsigned int packet_size;
+	int result;
+
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth) {
+		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
+		return;
+	}
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		if (urb->status == -ENOENT) {                   
+			dbg(__FUNCTION__ " - URB canceled, won't reschedule");
+			return;
+		}
+		goto exit;
+	}
+
+	if (!count) {
+		dbg(__FUNCTION__ " - zero length read bulk");
+		goto exit;
+	}
+
+#ifdef DEBUG
+	if (count) {
+		printk (KERN_DEBUG __FILE__ ": " __FUNCTION__ "- length = %d, data = ", count);
+		for (i = 0; i < count; ++i) {
+			printk ("%.2x ", data[i]);
+		}
+		printk ("\n");
+	}
+#endif
+#ifdef BTBUGGYHARDWARE
+	if ((count == 4) && (data[0] == 0x00) && (data[1] == 0x00)
+	    && (data[2] == 0x00) && (data[3] == 0x00)) {
+		urb->actual_length = 0;
+		FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
+			      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
+			      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
+			      bluetooth_read_bulk_callback, bluetooth);
+		result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
+		if (result)
+			err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+
+		return;
+	}
+#endif
+	/* We add  a packet type identifier to the beginning of each
+	   HCI frame.  This makes the data in the tty look like a
+	   serial USB devices.  Each HCI frame can be broken across
+	   multiple URBs so we buffer them until we have a full hci
+	   packet */
+	
+	if (!bluetooth->bulk_packet_pos) {
+		bluetooth->bulk_buffer[0] = ACL_PKT;
+		bluetooth->bulk_packet_pos++;
+	}
+
+	if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
+		err(__FUNCTION__ " - exceeded ACL_BUFFER_SIZE");
+		bluetooth->bulk_packet_pos = 0;
+		goto exit;
+	}
+
+	memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos],
+		urb->transfer_buffer, count);
+	bluetooth->bulk_packet_pos += count;
+	urb->actual_length = 0;
+
+	if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) {
+		packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]);
+	} else {
+		goto exit;
+	}
+
+	if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
+		err(__FUNCTION__ " - packet was too long");
+		bluetooth->bulk_packet_pos = 0;
+		goto exit;
+	}
+
+	if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
+		for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
+			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+			if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(bluetooth->tty);
+			}
+			tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
+		}
+		tty_flip_buffer_push(bluetooth->tty);
+		bluetooth->bulk_packet_pos = 0;
+	}	
+
+exit:
+	if (!bluetooth || !bluetooth->open_count)
+		return;
+
+	FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
+		      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
+		      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
+		      bluetooth_read_bulk_callback, bluetooth);
+	result = usb_submit_urb(bluetooth->read_urb, GFP_KERNEL);
+	if (result)
+		err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+
+	return;
+}
+
+
+static void bluetooth_write_bulk_callback (struct urb *urb)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)urb->context, __FUNCTION__);
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth) {
+		dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
+		return;
+	}
+
+	if (urb->status) {
+		dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+		return;
+	}
+
+	/* wake up our little function to let the tty layer know that something happened */
+	queue_task(&bluetooth->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+	return;
+}
+
+
+static void bluetooth_softint(void *private)
+{
+	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
+	struct tty_struct *tty;
+
+	dbg(__FUNCTION__);
+
+	if (!bluetooth) {
+		return;
+	}
+
+	tty = bluetooth->tty;
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
+		dbg(__FUNCTION__ " - write wakeup call.");
+		(tty->ldisc.write_wakeup)(tty);
+	}
+
+	wake_up_interruptible(&tty->write_wait);
+}
+
+
+static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum,
+			 	  const struct usb_device_id *id)
+{
+	struct usb_bluetooth *bluetooth = NULL;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_endpoint_descriptor *interrupt_in_endpoint[8];
+	struct usb_endpoint_descriptor *bulk_in_endpoint[8];
+	struct usb_endpoint_descriptor *bulk_out_endpoint[8];
+	int control_out_endpoint;
+
+	int minor;
+	int buffer_size;
+	int i;
+	int num_interrupt_in = 0;
+	int num_bulk_in = 0;
+	int num_bulk_out = 0;
+
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	control_out_endpoint = interface->bInterfaceNumber;
+
+	/* find the endpoints that we need */
+	for (i = 0; i < interface->bNumEndpoints; ++i) {
+		endpoint = &interface->endpoint[i];
+
+		if ((endpoint->bEndpointAddress & 0x80) &&
+		    ((endpoint->bmAttributes & 3) == 0x02)) {
+			/* we found a bulk in endpoint */
+			dbg("found bulk in");
+			bulk_in_endpoint[num_bulk_in] = endpoint;
+			++num_bulk_in;
+		}
+
+		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+		    ((endpoint->bmAttributes & 3) == 0x02)) {
+			/* we found a bulk out endpoint */
+			dbg("found bulk out");
+			bulk_out_endpoint[num_bulk_out] = endpoint;
+			++num_bulk_out;
+		}
+
+		if ((endpoint->bEndpointAddress & 0x80) &&
+		    ((endpoint->bmAttributes & 3) == 0x03)) {
+			/* we found a interrupt in endpoint */
+			dbg("found interrupt in");
+			interrupt_in_endpoint[num_interrupt_in] = endpoint;
+			++num_interrupt_in;
+		}
+	}
+
+	/* according to the spec, we can only have 1 bulk_in, 1 bulk_out, and 1 interrupt_in endpoints */
+	if ((num_bulk_in != 1) ||
+	    (num_bulk_out != 1) ||
+	    (num_interrupt_in != 1)) {
+		dbg (__FUNCTION__ " - improper number of endpoints. Bluetooth driver not bound.");
+		return NULL;
+	}
+
+	MOD_INC_USE_COUNT;
+	info("USB Bluetooth converter detected");
+
+	for (minor = 0; minor < BLUETOOTH_TTY_MINORS && bluetooth_table[minor]; ++minor)
+		;
+	if (bluetooth_table[minor]) {
+		err("No more free Bluetooth devices");
+		MOD_DEC_USE_COUNT;
+		return NULL;
+	}
+
+	if (!(bluetooth = kmalloc(sizeof(struct usb_bluetooth), GFP_KERNEL))) {
+		err("Out of memory");
+		MOD_DEC_USE_COUNT;
+		return NULL;
+	}
+
+	memset(bluetooth, 0, sizeof(struct usb_bluetooth));
+
+	bluetooth->magic = USB_BLUETOOTH_MAGIC;
+	bluetooth->dev = dev;
+	bluetooth->minor = minor;
+	bluetooth->tqueue.routine = bluetooth_softint;
+	bluetooth->tqueue.data = bluetooth;
+	init_MUTEX(&bluetooth->lock);
+
+	/* record the interface number for the control out */
+	bluetooth->control_out_bInterfaceNum = control_out_endpoint;
+	
+	/* create our control out urb pool */ 
+	for (i = 0; i < NUM_CONTROL_URBS; ++i) {
+		struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (urb == NULL) {
+			err("No free urbs available");
+			goto probe_error;
+		}
+		urb->transfer_buffer = NULL;
+		bluetooth->control_urb_pool[i] = urb;
+	}
+
+	/* set up the endpoint information */
+	endpoint = bulk_in_endpoint[0];
+	bluetooth->read_urb = usb_alloc_urb (0, GFP_KERNEL);
+	if (!bluetooth->read_urb) {
+		err("No free urbs available");
+		goto probe_error;
+	}
+	bluetooth->bulk_in_buffer_size = buffer_size = endpoint->wMaxPacketSize;
+	bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress;
+	bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+	if (!bluetooth->bulk_in_buffer) {
+		err("Couldn't allocate bulk_in_buffer");
+		goto probe_error;
+	}
+	FILL_BULK_URB(bluetooth->read_urb, dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
+		      bluetooth->bulk_in_buffer, buffer_size, bluetooth_read_bulk_callback, bluetooth);
+
+	endpoint = bulk_out_endpoint[0];
+	bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
+	
+	/* create our write urb pool */ 
+	for (i = 0; i < NUM_BULK_URBS; ++i) {
+		struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (urb == NULL) {
+			err("No free urbs available");
+			goto probe_error;
+		}
+		urb->transfer_buffer = kmalloc (bluetooth->bulk_out_buffer_size, GFP_KERNEL);
+		if (urb->transfer_buffer == NULL) {
+			err("out of memory");
+			goto probe_error;
+		}
+		bluetooth->write_urb_pool[i] = urb;
+	}
+	
+	bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
+
+	endpoint = interrupt_in_endpoint[0];
+	bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!bluetooth->interrupt_in_urb) {
+		err("No free urbs available");
+		goto probe_error;
+	}
+	bluetooth->interrupt_in_buffer_size = buffer_size = endpoint->wMaxPacketSize;
+	bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
+	bluetooth->interrupt_in_interval = endpoint->bInterval;
+	bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+	if (!bluetooth->interrupt_in_buffer) {
+		err("Couldn't allocate interrupt_in_buffer");
+		goto probe_error;
+	}
+	FILL_INT_URB(bluetooth->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+		     bluetooth->interrupt_in_buffer, buffer_size, bluetooth_int_callback,
+		     bluetooth, endpoint->bInterval);
+
+	/* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */
+	tty_register_devfs (&bluetooth_tty_driver, 0, minor);
+	info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor);
+
+	bluetooth_table[minor] = bluetooth;
+
+	return bluetooth; /* success */
+
+probe_error:
+	if (bluetooth->read_urb)
+		usb_free_urb (bluetooth->read_urb);
+	if (bluetooth->bulk_in_buffer)
+		kfree (bluetooth->bulk_in_buffer);
+	if (bluetooth->interrupt_in_urb)
+		usb_free_urb (bluetooth->interrupt_in_urb);
+	if (bluetooth->interrupt_in_buffer)
+		kfree (bluetooth->interrupt_in_buffer);
+	for (i = 0; i < NUM_BULK_URBS; ++i)
+		if (bluetooth->write_urb_pool[i]) {
+			if (bluetooth->write_urb_pool[i]->transfer_buffer)
+				kfree (bluetooth->write_urb_pool[i]->transfer_buffer);
+			usb_free_urb (bluetooth->write_urb_pool[i]);
+		}
+	for (i = 0; i < NUM_CONTROL_URBS; ++i) 
+		if (bluetooth->control_urb_pool[i]) {
+			if (bluetooth->control_urb_pool[i]->transfer_buffer)
+				kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
+			usb_free_urb (bluetooth->control_urb_pool[i]);
+		}
+
+	bluetooth_table[minor] = NULL;
+
+	/* free up any memory that we allocated */
+	kfree (bluetooth);
+	MOD_DEC_USE_COUNT;
+	return NULL;
+}
+
+
+static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_bluetooth *bluetooth = (struct usb_bluetooth *) ptr;
+	int i;
+
+	if (bluetooth) {
+		if ((bluetooth->open_count) && (bluetooth->tty))
+			tty_hangup(bluetooth->tty);
+
+		bluetooth->open_count = 0;
+
+		if (bluetooth->read_urb) {
+			usb_unlink_urb (bluetooth->read_urb);
+			usb_free_urb (bluetooth->read_urb);
+		}
+		if (bluetooth->bulk_in_buffer)
+			kfree (bluetooth->bulk_in_buffer);
+
+		if (bluetooth->interrupt_in_urb) {
+			usb_unlink_urb (bluetooth->interrupt_in_urb);
+			usb_free_urb (bluetooth->interrupt_in_urb);
+		}
+		if (bluetooth->interrupt_in_buffer)
+			kfree (bluetooth->interrupt_in_buffer);
+
+		tty_unregister_devfs (&bluetooth_tty_driver, bluetooth->minor);
+
+		for (i = 0; i < NUM_BULK_URBS; ++i) {
+			if (bluetooth->write_urb_pool[i]) {
+				usb_unlink_urb (bluetooth->write_urb_pool[i]);
+				if (bluetooth->write_urb_pool[i]->transfer_buffer)
+					kfree (bluetooth->write_urb_pool[i]->transfer_buffer);
+				usb_free_urb (bluetooth->write_urb_pool[i]);
+			}
+		}
+		for (i = 0; i < NUM_CONTROL_URBS; ++i) {
+			if (bluetooth->control_urb_pool[i]) {
+				usb_unlink_urb (bluetooth->control_urb_pool[i]);
+				if (bluetooth->control_urb_pool[i]->transfer_buffer)
+					kfree (bluetooth->control_urb_pool[i]->transfer_buffer);
+				usb_free_urb (bluetooth->control_urb_pool[i]);
+			}
+		}
+		
+		info("Bluetooth converter now disconnected from ttyUB%d", bluetooth->minor);
+
+		bluetooth_table[bluetooth->minor] = NULL;
+
+		/* free up any memory that we allocated */
+		kfree (bluetooth);
+
+	} else {
+		info("device disconnected");
+	}
+
+	MOD_DEC_USE_COUNT;
+}
+
+
+static struct tty_driver bluetooth_tty_driver = {
+	magic:			TTY_DRIVER_MAGIC,
+	driver_name:		"usb-bluetooth",
+	name:			"usb/ttub/%d",
+	major:			BLUETOOTH_TTY_MAJOR,
+	minor_start:		0,
+	num:			BLUETOOTH_TTY_MINORS,
+	type:			TTY_DRIVER_TYPE_SERIAL,
+	subtype:		SERIAL_TYPE_NORMAL,
+	flags:			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
+
+	refcount:		&bluetooth_refcount,
+	table:			bluetooth_tty,
+	termios:		bluetooth_termios,
+	termios_locked:		bluetooth_termios_locked,
+
+	open:			bluetooth_open,
+	close:			bluetooth_close,
+	write:			bluetooth_write,
+	write_room:		bluetooth_write_room,
+	ioctl:			bluetooth_ioctl,
+	set_termios:		bluetooth_set_termios,
+	throttle:		bluetooth_throttle,
+	unthrottle:		bluetooth_unthrottle,
+	chars_in_buffer:	bluetooth_chars_in_buffer,
+};
+
+
+int usb_bluetooth_init(void)
+{
+	int i;
+	int result;
+
+	/* Initalize our global data */
+	for (i = 0; i < BLUETOOTH_TTY_MINORS; ++i) {
+		bluetooth_table[i] = NULL;
+	}
+
+	info ("USB Bluetooth support registered");
+
+	/* register the tty driver */
+	bluetooth_tty_driver.init_termios          = tty_std_termios;
+	bluetooth_tty_driver.init_termios.c_cflag  = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	if (tty_register_driver (&bluetooth_tty_driver)) {
+		err(__FUNCTION__ " - failed to register tty driver");
+		return -1;
+	}
+
+	/* register the USB driver */
+	result = usb_register(&usb_bluetooth_driver);
+	if (result < 0) {
+		tty_unregister_driver(&bluetooth_tty_driver);
+		err("usb_register failed for the USB bluetooth driver. Error number %d", result);
+		return -1;
+	}
+
+	info(DRIVER_DESC " " DRIVER_VERSION);
+
+	return 0;
+}
+
+
+void usb_bluetooth_exit(void)
+{
+	usb_deregister(&usb_bluetooth_driver);
+	tty_unregister_driver(&bluetooth_tty_driver);
+}
+
+
+module_init(usb_bluetooth_init);
+module_exit(usb_bluetooth_exit);
+
+/* Module information */
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/cdc-acm.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,739 @@
+/*
+ * acm.c  Version 0.21
+ *
+ * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
+ * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
+ * Copyright (c) 1999 Johannes Erdfelt	<johannes@erdfelt.com>
+ * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
+ *
+ * USB Abstract Control Model driver for USB modems and ISDN adapters
+ *
+ * Sponsored by SuSE
+ *
+ * ChangeLog:
+ *	v0.9  - thorough cleaning, URBification, almost a rewrite
+ *	v0.10 - some more cleanups
+ *	v0.11 - fixed flow control, read error doesn't stop reads
+ *	v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
+ *	v0.13 - added termios, added hangup
+ *	v0.14 - sized down struct acm
+ *	v0.15 - fixed flow control again - characters could be lost
+ *	v0.16 - added code for modems with swapped data and control interfaces
+ *	v0.17 - added new style probing
+ *	v0.18 - fixed new style probing for devices with more configurations
+ *	v0.19 - fixed CLOCAL handling (thanks to Richard Shih-Ping Chan)
+ *	v0.20 - switched to probing on interface (rather than device) class
+ *	v0.21 - revert to probing on device for devices with multiple configs
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#undef DEBUG
+#include <linux/usb.h>
+#include <asm/byteorder.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.21"
+#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
+#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
+
+/*
+ * CMSPAR, some architectures can't have space and mark parity.
+ */
+
+#ifndef CMSPAR
+#define CMSPAR			0
+#endif
+
+/*
+ * Major and minor numbers.
+ */
+
+#define ACM_TTY_MAJOR		166
+#define ACM_TTY_MINORS		32
+
+/*
+ * Requests.
+ */
+
+#define USB_RT_ACM		(USB_TYPE_CLASS | USB_RECIP_INTERFACE)
+
+#define ACM_REQ_COMMAND		0x00
+#define ACM_REQ_RESPONSE	0x01
+#define ACM_REQ_SET_FEATURE	0x02
+#define ACM_REQ_GET_FEATURE	0x03
+#define ACM_REQ_CLEAR_FEATURE	0x04
+
+#define ACM_REQ_SET_LINE	0x20
+#define ACM_REQ_GET_LINE	0x21
+#define ACM_REQ_SET_CONTROL	0x22
+#define ACM_REQ_SEND_BREAK	0x23
+
+/*
+ * IRQs.
+ */
+
+#define ACM_IRQ_NETWORK		0x00
+#define ACM_IRQ_LINE_STATE	0x20
+
+/*
+ * Output control lines.
+ */
+
+#define ACM_CTRL_DTR		0x01
+#define ACM_CTRL_RTS		0x02
+
+/*
+ * Input control lines and line errors.
+ */
+
+#define ACM_CTRL_DCD		0x01
+#define ACM_CTRL_DSR		0x02
+#define ACM_CTRL_BRK		0x04
+#define ACM_CTRL_RI		0x08
+
+#define ACM_CTRL_FRAMING	0x10
+#define ACM_CTRL_PARITY		0x20
+#define ACM_CTRL_OVERRUN	0x40
+
+/*
+ * Line speed and caracter encoding.
+ */
+
+struct acm_line {
+	__u32 speed;
+	__u8 stopbits;
+	__u8 parity;
+	__u8 databits;
+} __attribute__ ((packed));
+
+/*
+ * Internal driver structures.
+ */
+
+struct acm {
+	struct usb_device *dev;				/* the coresponding usb device */
+	struct usb_interface *iface;			/* the interfaces - +0 control +1 data */
+	struct tty_struct *tty;				/* the coresponding tty */
+	struct urb ctrlurb, readurb, writeurb;		/* urbs */
+	struct acm_line line;				/* line coding (bits, stop, parity) */
+	struct tq_struct tqueue;			/* task queue for line discipline waking up */
+	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
+	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
+	unsigned int writesize;				/* max packet size for the output bulk endpoint */
+	unsigned int used;				/* someone has this acm's device open */
+	unsigned int minor;				/* acm minor number */
+	unsigned char throttle;				/* throttled by tty layer */
+	unsigned char clocal;				/* termios CLOCAL */
+};
+
+static struct usb_driver acm_driver;
+static struct tty_driver acm_tty_driver;
+static struct acm *acm_table[ACM_TTY_MINORS];
+
+#define ACM_READY(acm)	(acm && acm->dev && acm->used)
+
+/*
+ * Functions for ACM control messages.
+ */
+
+static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
+{
+	int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
+		request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
+	dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
+	return retval < 0 ? retval : 0;
+}
+
+#define acm_set_control(acm, control)	acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
+#define acm_set_line(acm, line)		acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
+#define acm_send_break(acm, ms)		acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
+
+/*
+ * Interrupt handler for various ACM control events
+ */
+
+static void acm_ctrl_irq(struct urb *urb)
+{
+	struct acm *acm = urb->context;
+	struct usb_ctrlrequest *dr = urb->transfer_buffer;
+	unsigned char *data = (unsigned char *)(dr + 1);
+	int newctrl;
+
+	if (!ACM_READY(acm)) return;
+
+	if (urb->status < 0) {
+		dbg("nonzero ctrl irq status received: %d", urb->status);
+		return;
+	}
+
+	switch (dr->bRequest) {
+
+		case ACM_IRQ_NETWORK:
+
+			dbg("%s network", data[0] ? "connected to" : "disconnected from");
+			return;
+
+		case ACM_IRQ_LINE_STATE:
+
+			newctrl = le16_to_cpup((__u16 *) data);
+
+			if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+				dbg("calling hangup");
+				tty_hangup(acm->tty);
+			}
+
+			acm->ctrlin = newctrl;
+
+			dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
+				acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',	acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
+				acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',	acm->ctrlin & ACM_CTRL_RI  ? '+' : '-',
+				acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',	acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
+				acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
+
+			return;
+
+		default:
+			dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
+				dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
+			return;
+	}
+}
+
+static void acm_read_bulk(struct urb *urb)
+{
+	struct acm *acm = urb->context;
+	struct tty_struct *tty = acm->tty;
+	unsigned char *data = urb->transfer_buffer;
+	int i = 0;
+
+	if (!ACM_READY(acm)) return;
+
+	if (urb->status)
+		dbg("nonzero read bulk status received: %d", urb->status);
+
+	if (!urb->status & !acm->throttle)  {
+		for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
+			/* if we insert more than TTY_FLIPBUF_SIZE characters,
+			 * we drop them. */
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+			}
+			tty_insert_flip_char(tty, data[i], 0);
+		}
+		tty_flip_buffer_push(tty);
+	}
+
+	if (acm->throttle) {
+		memmove(data, data + i, urb->actual_length - i);
+		urb->actual_length -= i;
+		return;
+	}
+
+	urb->actual_length = 0;
+	urb->dev = acm->dev;
+
+	if (usb_submit_urb(urb, GFP_KERNEL))
+		dbg("failed resubmitting read urb");
+}
+
+static void acm_write_bulk(struct urb *urb)
+{
+	struct acm *acm = (struct acm *)urb->context;
+
+	if (!ACM_READY(acm)) return;
+
+	if (urb->status)
+		dbg("nonzero write bulk status received: %d", urb->status);
+
+	queue_task(&acm->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+static void acm_softint(void *private)
+{
+	struct acm *acm = private;
+	struct tty_struct *tty = acm->tty;
+
+	if (!ACM_READY(acm)) return;
+
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+
+	wake_up_interruptible(&tty->write_wait);
+}
+
+/*
+ * TTY handlers
+ */
+
+static int acm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct acm *acm = acm_table[minor(tty->device)];
+
+	if (!acm || !acm->dev) return -EINVAL;
+
+	tty->driver_data = acm;
+	acm->tty = tty;
+
+	MOD_INC_USE_COUNT;
+
+        lock_kernel();
+
+	if (acm->used++) {
+                unlock_kernel();
+                return 0;
+        }
+
+        unlock_kernel();
+
+	acm->ctrlurb.dev = acm->dev;
+	if (usb_submit_urb(&acm->ctrlurb, GFP_KERNEL))
+		dbg("usb_submit_urb(ctrl irq) failed");
+
+	acm->readurb.dev = acm->dev;
+	if (usb_submit_urb(&acm->readurb, GFP_KERNEL))
+		dbg("usb_submit_urb(read bulk) failed");
+
+	acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS);
+
+	/* force low_latency on so that our tty_push actually forces the data through, 
+	   otherwise it is scheduled, and with high data rates data can get lost. */
+	tty->low_latency = 1;
+
+	return 0;
+}
+
+static void acm_tty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct acm *acm = tty->driver_data;
+
+	if (!acm || !acm->used) return;
+
+	if (!--acm->used) {
+		if (acm->dev) {
+			acm_set_control(acm, acm->ctrlout = 0);
+			usb_unlink_urb(&acm->ctrlurb);
+			usb_unlink_urb(&acm->writeurb);
+			usb_unlink_urb(&acm->readurb);
+		} else {
+			tty_unregister_devfs(&acm_tty_driver, acm->minor);
+			acm_table[acm->minor] = NULL;
+			kfree(acm);
+		}
+	}
+	MOD_DEC_USE_COUNT;
+}
+
+static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
+{
+	struct acm *acm = tty->driver_data;
+
+	if (!ACM_READY(acm)) return -EINVAL;
+	if (acm->writeurb.status == -EINPROGRESS) return 0;
+	if (!count) return 0;
+
+	count = (count > acm->writesize) ? acm->writesize : count;
+
+	if (from_user)
+		copy_from_user(acm->writeurb.transfer_buffer, buf, count);
+	else
+		memcpy(acm->writeurb.transfer_buffer, buf, count);
+
+	acm->writeurb.transfer_buffer_length = count;
+	acm->writeurb.dev = acm->dev;
+
+	if (usb_submit_urb(&acm->writeurb, GFP_KERNEL))
+		dbg("usb_submit_urb(write bulk) failed");
+
+	return count;
+}
+
+static int acm_tty_write_room(struct tty_struct *tty)
+{
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return -EINVAL;
+	return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize;
+}
+
+static int acm_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return -EINVAL;
+	return acm->writeurb.status == -EINPROGRESS ? acm->writeurb.transfer_buffer_length : 0;
+}
+
+static void acm_tty_throttle(struct tty_struct *tty)
+{
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return;
+	acm->throttle = 1;
+}
+
+static void acm_tty_unthrottle(struct tty_struct *tty)
+{
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return;
+	acm->throttle = 0;
+	if (acm->readurb.status != -EINPROGRESS)
+		acm_read_bulk(&acm->readurb);
+}
+
+static void acm_tty_break_ctl(struct tty_struct *tty, int state)
+{
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return;
+	if (acm_send_break(acm, state ? 0xffff : 0))
+		dbg("send break failed");
+}
+
+static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct acm *acm = tty->driver_data;
+	unsigned int mask, newctrl;
+
+	if (!ACM_READY(acm)) return -EINVAL;
+
+	switch (cmd) {
+
+		case TIOCMGET:
+
+			return put_user((acm->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) |
+				(acm->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
+				(acm->ctrlin  & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
+				(acm->ctrlin  & ACM_CTRL_RI  ? TIOCM_RI  : 0) |
+				(acm->ctrlin  & ACM_CTRL_DCD ? TIOCM_CD  : 0) |
+				 TIOCM_CTS, (unsigned long *) arg);
+
+		case TIOCMSET:
+		case TIOCMBIS:
+		case TIOCMBIC:
+
+			if (get_user(mask, (unsigned long *) arg))
+				return -EFAULT;
+
+			newctrl = acm->ctrlout;
+			mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
+
+			switch (cmd) {
+				case TIOCMSET: newctrl  =  mask; break;
+				case TIOCMBIS: newctrl |=  mask; break;
+				case TIOCMBIC: newctrl &= ~mask; break;
+			}
+
+			if (acm->ctrlout == newctrl) return 0;
+			return acm_set_control(acm, acm->ctrlout = newctrl);
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static __u32 acm_tty_speed[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600,
+	1200, 1800, 2400, 4800, 9600, 19200, 38400,
+	57600, 115200, 230400, 460800, 500000, 576000,
+	921600, 1000000, 1152000, 1500000, 2000000,
+	2500000, 3000000, 3500000, 4000000
+};
+
+static __u8 acm_tty_size[] = {
+	5, 6, 7, 8
+};
+
+static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
+{
+	struct acm *acm = tty->driver_data;
+	struct termios *termios = tty->termios;
+	struct acm_line newline;
+	int newctrl = acm->ctrlout;
+
+	if (!ACM_READY(acm)) return;
+
+	newline.speed = cpu_to_le32p(acm_tty_speed +
+		(termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
+	newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
+	newline.parity = termios->c_cflag & PARENB ?
+		(termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
+	newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+
+	acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
+
+	if (!newline.speed) {
+		newline.speed = acm->line.speed;
+		newctrl &= ~ACM_CTRL_DTR;
+	} else  newctrl |=  ACM_CTRL_DTR;
+
+	if (newctrl != acm->ctrlout)
+		acm_set_control(acm, acm->ctrlout = newctrl);
+
+	if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
+		memcpy(&acm->line, &newline, sizeof(struct acm_line));
+		dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
+		acm_set_line(acm, &acm->line);
+	}
+}
+
+/*
+ * USB probe and disconnect routines.
+ */
+
+static void *acm_probe(struct usb_device *dev, unsigned int ifnum,
+		       const struct usb_device_id *id)
+{
+	struct acm *acm;
+	struct usb_config_descriptor *cfacm;
+	struct usb_interface_descriptor *ifcom, *ifdata;
+	struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
+	int readsize, ctrlsize, minor, i;
+	unsigned char *buf;
+
+	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+
+		cfacm = dev->config + i;
+
+		dbg("probing config %d", cfacm->bConfigurationValue);
+
+		if (cfacm->bNumInterfaces != 2 ||
+		    usb_interface_claimed(cfacm->interface + 0) ||
+		    usb_interface_claimed(cfacm->interface + 1))
+			continue;
+
+		ifcom = cfacm->interface[0].altsetting + 0;
+		ifdata = cfacm->interface[1].altsetting + 0;
+
+		if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) {
+			ifcom = cfacm->interface[1].altsetting + 0;
+			ifdata = cfacm->interface[0].altsetting + 0;
+			if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2)
+				continue;
+		}
+
+		if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
+		    ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1)
+			continue;
+
+		epctrl = ifcom->endpoint + 0;
+		epread = ifdata->endpoint + 0;
+		epwrite = ifdata->endpoint + 1;
+
+		if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
+		   (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
+		   ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
+			continue;
+
+		if ((epread->bEndpointAddress & 0x80) != 0x80) {
+			epread = ifdata->endpoint + 1;
+			epwrite = ifdata->endpoint + 0;
+		}
+
+		usb_set_configuration(dev, cfacm->bConfigurationValue);
+
+		for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+		if (acm_table[minor]) {
+			err("no more free acm devices");
+			return NULL;
+		}
+
+		if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+			err("out of memory");
+			return NULL;
+		}
+		memset(acm, 0, sizeof(struct acm));
+
+		ctrlsize = epctrl->wMaxPacketSize;
+		readsize = epread->wMaxPacketSize;
+		acm->writesize = epwrite->wMaxPacketSize;
+		acm->iface = cfacm->interface;
+		acm->minor = minor;
+		acm->dev = dev;
+
+		acm->tqueue.routine = acm_softint;
+		acm->tqueue.data = acm;
+
+		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+			err("out of memory");
+			kfree(acm);
+			return NULL;
+		}
+
+		FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
+			buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
+
+		FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+			buf += ctrlsize, readsize, acm_read_bulk, acm);
+		acm->readurb.transfer_flags |= USB_NO_FSBR;
+
+		FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+			buf += readsize, acm->writesize, acm_write_bulk, acm);
+		acm->writeurb.transfer_flags |= USB_NO_FSBR;
+
+		printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
+
+		acm_set_control(acm, acm->ctrlout);
+
+		acm->line.speed = cpu_to_le32(9600);
+		acm->line.databits = 8;
+		acm_set_line(acm, &acm->line);
+
+		usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
+		usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
+
+		tty_register_devfs(&acm_tty_driver, 0, minor);
+		return acm_table[minor] = acm;
+	}
+
+	return NULL;
+}
+
+static void acm_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct acm *acm = ptr;
+
+	if (!acm || !acm->dev) {
+		dbg("disconnect on nonexisting interface");
+		return;
+	}
+
+	acm->dev = NULL;
+
+	usb_unlink_urb(&acm->ctrlurb);
+	usb_unlink_urb(&acm->readurb);
+	usb_unlink_urb(&acm->writeurb);
+
+	kfree(acm->ctrlurb.transfer_buffer);
+
+	usb_driver_release_interface(&acm_driver, acm->iface + 0);
+	usb_driver_release_interface(&acm_driver, acm->iface + 1);
+
+	if (!acm->used) {
+		tty_unregister_devfs(&acm_tty_driver, acm->minor);
+		acm_table[acm->minor] = NULL;
+		kfree(acm);
+		return;
+	}
+
+	if (acm->tty)
+		tty_hangup(acm->tty);
+}
+
+/*
+ * USB driver structure.
+ */
+
+static struct usb_device_id acm_ids[] = {
+	{ USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE (usb, acm_ids);
+
+static struct usb_driver acm_driver = {
+	name:		"acm",
+	probe:		acm_probe,
+	disconnect:	acm_disconnect,
+	id_table:	acm_ids,
+};
+
+/*
+ * TTY driver structures.
+ */
+
+static int acm_tty_refcount;
+
+static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
+static struct termios *acm_tty_termios[ACM_TTY_MINORS];
+static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
+
+static struct tty_driver acm_tty_driver = {
+	magic:			TTY_DRIVER_MAGIC,
+	driver_name:		"acm",
+	name:			"usb/acm/%d",
+	major:			ACM_TTY_MAJOR,
+	minor_start:		0,
+	num:			ACM_TTY_MINORS,
+	type:			TTY_DRIVER_TYPE_SERIAL,
+	subtype:		SERIAL_TYPE_NORMAL,
+	flags:			TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
+
+	refcount:		&acm_tty_refcount,
+
+	table:			acm_tty_table,
+	termios:		acm_tty_termios,
+	termios_locked:		acm_tty_termios_locked,
+
+	open:			acm_tty_open,
+	close:			acm_tty_close,
+	write:			acm_tty_write,
+	write_room:		acm_tty_write_room,
+	ioctl:			acm_tty_ioctl,
+	throttle:		acm_tty_throttle,
+	unthrottle:		acm_tty_unthrottle,
+	chars_in_buffer:	acm_tty_chars_in_buffer,
+	break_ctl:		acm_tty_break_ctl,
+	set_termios:		acm_tty_set_termios
+};
+
+/*
+ * Init / exit.
+ */
+
+static int __init acm_init(void)
+{
+	acm_tty_driver.init_termios =		tty_std_termios;
+	acm_tty_driver.init_termios.c_cflag =	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+
+	if (tty_register_driver(&acm_tty_driver))
+		return -1;
+
+	if (usb_register(&acm_driver) < 0) {
+		tty_unregister_driver(&acm_tty_driver);
+		return -1;
+	}
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+
+	return 0;
+}
+
+static void __exit acm_exit(void)
+{
+	usb_deregister(&acm_driver);
+	tty_unregister_driver(&acm_tty_driver);
+}
+
+module_init(acm_init);
+module_exit(acm_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/class/printer.c b/drivers/usb/class/printer.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/class/printer.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,1116 @@
+/*
+ * printer.c  Version 0.12
+ *
+ * Copyright (c) 1999 Michael Gee	<michael@linuxspecific.com>
+ * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
+ * Copyright (c) 2000 Randy Dunlap	<randy.dunlap@intel.com>
+ * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
+ # Copyright (c) 2001 Pete Zaitcev	<zaitcev@redhat.com>
+ # Copyright (c) 2001 David Paschal	<paschal@rcsis.com>
+ *
+ * USB Printer Device Class driver for USB printers and printer cables
+ *
+ * Sponsored by SuSE
+ *
+ * ChangeLog:
+ *	v0.1 - thorough cleaning, URBification, almost a rewrite
+ *	v0.2 - some more cleanups
+ *	v0.3 - cleaner again, waitqueue fixes
+ *	v0.4 - fixes in unidirectional mode
+ *	v0.5 - add DEVICE_ID string support
+ *	v0.6 - never time out
+ *	v0.7 - fixed bulk-IN read and poll (David Paschal)
+ *	v0.8 - add devfs support
+ *	v0.9 - fix unplug-while-open paths
+ *	v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
+ *	v0.11 - add proto_bias option (Pete Zaitcev)
+ *	v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/signal.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/lp.h>
+#include <linux/devfs_fs_kernel.h>
+#undef DEBUG
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.12"
+#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
+#define DRIVER_DESC "USB Printer Device Class driver"
+
+#define USBLP_BUF_SIZE		8192
+#define DEVICE_ID_SIZE		1024
+
+/* ioctls: */
+#define LPGETSTATUS		0x060b		/* same as in drivers/char/lp.c */
+#define IOCNR_GET_DEVICE_ID		1
+#define IOCNR_GET_PROTOCOLS		2
+#define IOCNR_SET_PROTOCOL		3
+#define IOCNR_HP_SET_CHANNEL		4
+#define IOCNR_GET_BUS_ADDRESS		5
+#define IOCNR_GET_VID_PID		6
+/* Get device_id string: */
+#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
+/* The following ioctls were added for http://hpoj.sourceforge.net: */
+/* Get two-int array:
+ * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
+ * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
+#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
+/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
+#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
+/* Set channel number (HP Vendor-specific command): */
+#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
+/* Get two-int array: [0]=bus number, [1]=device address: */
+#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
+/* Get two-int array: [0]=vendor ID, [1]=product ID: */
+#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
+
+/*
+ * A DEVICE_ID string may include the printer's serial number.
+ * It should end with a semi-colon (';').
+ * An example from an HP 970C DeskJet printer is (this is one long string,
+ * with the serial number changed):
+MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ:                    ;
+ */
+
+/*
+ * USB Printer Requests
+ */
+
+#define USBLP_REQ_GET_ID			0x00
+#define USBLP_REQ_GET_STATUS			0x01
+#define USBLP_REQ_RESET				0x02
+#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00	/* HP Vendor-specific */
+
+#define USBLP_MINORS		16
+#define USBLP_MINOR_BASE	0
+
+#define USBLP_WRITE_TIMEOUT	(5*HZ)			/* 5 seconds */
+
+#define USBLP_FIRST_PROTOCOL	1
+#define USBLP_LAST_PROTOCOL	3
+#define USBLP_MAX_PROTOCOLS	(USBLP_LAST_PROTOCOL+1)
+
+struct usblp {
+	struct usb_device 	*dev;			/* USB device */
+	devfs_handle_t		devfs;			/* devfs device */
+	struct semaphore	sem;			/* locks this struct, especially "dev" */
+	char			*buf;		/* writeurb->transfer_buffer */
+	struct urb		*readurb, *writeurb;	/* The urbs */
+	wait_queue_head_t	wait;			/* Zzzzz ... */
+	int			readcount;		/* Counter for reads */
+	int			ifnum;			/* Interface number */
+	/* Alternate-setting numbers and endpoints for each protocol
+	 * (7/1/{index=1,2,3}) that the device supports: */
+	struct {
+		int				alt_setting;
+		struct usb_endpoint_descriptor	*epwrite;
+		struct usb_endpoint_descriptor	*epread;
+	}			protocol[USBLP_MAX_PROTOCOLS];
+	int			current_protocol;
+	int			minor;			/* minor number of device */
+	int			wcomplete;		/* writing is completed */
+	int			rcomplete;		/* reading is completed */
+	unsigned int		quirks;			/* quirks flags */
+	unsigned char		used;			/* True if open */
+	unsigned char		bidir;			/* interface is bidirectional */
+	unsigned char		*device_id_string;	/* IEEE 1284 DEVICE ID string (ptr) */
+							/* first 2 bytes are (big-endian) length */
+};
+
+#ifdef DEBUG
+static void usblp_dump(struct usblp *usblp) {
+	int p;
+
+	dbg("usblp=0x%p", usblp);
+	dbg("dev=0x%p", usblp->dev);
+	dbg("devfs=0x%p", usblp->devfs);
+	dbg("buf=0x%p", usblp->buf);
+	dbg("readcount=%d", usblp->readcount);
+	dbg("ifnum=%d", usblp->ifnum);
+    for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
+	dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
+	dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
+	dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
+    }
+	dbg("current_protocol=%d", usblp->current_protocol);
+	dbg("minor=%d", usblp->minor);
+	dbg("wcomplete=%d", usblp->wcomplete);
+	dbg("rcomplete=%d", usblp->rcomplete);
+	dbg("quirks=%d", usblp->quirks);
+	dbg("used=%d", usblp->used);
+	dbg("bidir=%d", usblp->bidir);
+	dbg("device_id_string=\"%s\"",
+		usblp->device_id_string ?
+			usblp->device_id_string + 2 :
+			(unsigned char *)"(null)");
+}
+#endif
+
+extern devfs_handle_t usb_devfs_handle;			/* /dev/usb dir. */
+
+static struct usblp *usblp_table[USBLP_MINORS];
+
+/* Quirks: various printer quirks are handled by this table & its flags. */
+
+struct quirk_printer_struct {
+	__u16 vendorId;
+	__u16 productId;
+	unsigned int quirks;
+};
+
+#define USBLP_QUIRK_BIDIR	0x1	/* reports bidir but requires unidirectional mode (no INs/reads) */
+#define USBLP_QUIRK_USB_INIT	0x2	/* needs vendor USB init string */
+
+static struct quirk_printer_struct quirk_printers[] = {
+	{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
+	{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
+	{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
+	{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
+	{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
+	{ 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */
+	{ 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */   
+	{ 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */   
+	{ 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */
+	{ 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
+	{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
+	{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
+	{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
+	{ 0, 0 }
+};
+
+static int usblp_select_alts(struct usblp *usblp);
+static int usblp_set_protocol(struct usblp *usblp, int protocol);
+static int usblp_cache_device_id_string(struct usblp *usblp);
+
+
+/*
+ * Functions for usblp control messages.
+ */
+
+static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
+{
+	int retval = usb_control_msg(usblp->dev,
+		dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
+		request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
+	dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
+		request, !!dir, recip, value, len, retval);
+	return retval < 0 ? retval : 0;
+}
+
+#define usblp_read_status(usblp, status)\
+	usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
+#define usblp_get_id(usblp, config, id, maxlen)\
+	usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
+#define usblp_reset(usblp)\
+	usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
+
+#define usblp_hp_channel_change_request(usblp, channel, buffer) \
+	usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
+
+/*
+ * See the description for usblp_select_alts() below for the usage
+ * explanation.  Look into your /proc/bus/usb/devices and dmesg in
+ * case of any trouble.
+ */
+static int proto_bias = -1;
+
+/*
+ * URB callback.
+ */
+
+static void usblp_bulk_read(struct urb *urb)
+{
+	struct usblp *usblp = urb->context;
+
+	if (!usblp || !usblp->dev || !usblp->used)
+		return;
+
+	if (unlikely(urb->status))
+		warn("usblp%d: nonzero read/write bulk status received: %d",
+			usblp->minor, urb->status);
+	usblp->rcomplete = 1;
+	wake_up_interruptible(&usblp->wait);
+}
+
+static void usblp_bulk_write(struct urb *urb)
+{
+	struct usblp *usblp = urb->context;
+
+	if (!usblp || !usblp->dev || !usblp->used)
+		return;
+
+	if (unlikely(urb->status))
+		warn("usblp%d: nonzero read/write bulk status received: %d",
+			usblp->minor, urb->status);
+	usblp->wcomplete = 1;
+	wake_up_interruptible(&usblp->wait);
+}
+
+/*
+ * Get and print printer errors.
+ */
+
+static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
+
+static int usblp_check_status(struct usblp *usblp, int err)
+{
+	unsigned char status, newerr = 0;
+	int error;
+
+	error = usblp_read_status (usblp, &status);
+	if (error < 0) {
+		err("usblp%d: error %d reading printer status",
+			usblp->minor, error);
+		return 0;
+	}
+
+	if (~status & LP_PERRORP) {
+		newerr = 3;
+		if (status & LP_POUTPA) newerr = 1;
+		if (~status & LP_PSELECD) newerr = 2;
+	}
+
+	if (newerr != err)
+		info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
+
+	return newerr;
+}
+
+/*
+ * File op functions.
+ */
+
+static int usblp_open(struct inode *inode, struct file *file)
+{
+	int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
+	struct usblp *usblp;
+	int retval;
+
+	if (minor < 0 || minor >= USBLP_MINORS)
+		return -ENODEV;
+
+	lock_kernel();
+	usblp  = usblp_table[minor];
+
+	retval = -ENODEV;
+	if (!usblp || !usblp->dev)
+		goto out;
+
+	retval = -EBUSY;
+	if (usblp->used)
+		goto out;
+
+	/*
+	 * TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ???
+	 * This is #if 0-ed because we *don't* want to fail an open
+	 * just because the printer is off-line.
+	 */
+#if 0
+	if ((retval = usblp_check_status(usblp, 0))) {
+		retval = retval > 1 ? -EIO : -ENOSPC;
+		goto out;
+	}
+#else
+	retval = 0;
+#endif
+
+	usblp->used = 1;
+	file->private_data = usblp;
+
+	usblp->writeurb->transfer_buffer_length = 0;
+	usblp->writeurb->status = 0;
+	usblp->wcomplete = 1; /* we begin writeable */
+	usblp->rcomplete = 0;
+
+	if (usblp->bidir) {
+		usblp->readcount = 0;
+		usblp->readurb->dev = usblp->dev;
+		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
+			retval = -EIO;
+			usblp->used = 0;
+			file->private_data = NULL;
+		}
+	}
+out:
+	unlock_kernel();
+	return retval;
+}
+
+static void usblp_cleanup (struct usblp *usblp)
+{
+	devfs_unregister (usblp->devfs);
+	usblp_table [usblp->minor] = NULL;
+	info("usblp%d: removed", usblp->minor);
+
+	kfree (usblp->writeurb->transfer_buffer);
+	kfree (usblp->device_id_string);
+	usb_free_urb(usblp->writeurb);
+	usb_free_urb(usblp->readurb);
+	kfree (usblp);
+}
+
+static void usblp_unlink_urbs(struct usblp *usblp)
+{
+	usb_unlink_urb(usblp->writeurb);
+	if (usblp->bidir)
+		usb_unlink_urb(usblp->readurb);
+}
+
+static int usblp_release(struct inode *inode, struct file *file)
+{
+	struct usblp *usblp = file->private_data;
+
+	down (&usblp->sem);
+	lock_kernel();
+	usblp->used = 0;
+	if (usblp->dev) {
+		usblp_unlink_urbs(usblp);
+		up(&usblp->sem);
+	} else 		/* finish cleanup from disconnect */
+		usblp_cleanup (usblp);
+	unlock_kernel();
+	return 0;
+}
+
+/* No kernel lock - fine */
+static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct usblp *usblp = file->private_data;
+	poll_wait(file, &usblp->wait, wait);
+ 	return ((!usblp->bidir || usblp->readurb->status  == -EINPROGRESS) ? 0 : POLLIN  | POLLRDNORM)
+ 			       | (usblp->writeurb->status == -EINPROGRESS  ? 0 : POLLOUT | POLLWRNORM);
+}
+
+static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct usblp *usblp = file->private_data;
+	int length, err, i;
+	unsigned char status, newChannel;
+	int twoints[2];
+	int retval = 0;
+
+	down (&usblp->sem);
+	if (!usblp->dev) {
+		retval = -ENODEV;
+		goto done;
+	}
+
+	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */
+
+		switch (_IOC_NR(cmd)) {
+
+			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
+				if (_IOC_DIR(cmd) != _IOC_READ) {
+					retval = -EINVAL;
+					goto done;
+				}
+
+				length = usblp_cache_device_id_string(usblp);
+				if (length < 0) {
+					retval = length;
+					goto done;
+				}
+				if (length > _IOC_SIZE(cmd))
+					length = _IOC_SIZE(cmd); /* truncate */
+
+				if (copy_to_user((unsigned char *) arg,
+						usblp->device_id_string,
+						(unsigned long) length)) {
+					retval = -EFAULT;
+					goto done;
+				}
+
+				break;
+
+			case IOCNR_GET_PROTOCOLS:
+				if (_IOC_DIR(cmd) != _IOC_READ ||
+				    _IOC_SIZE(cmd) < sizeof(twoints)) {
+					retval = -EINVAL;
+					goto done;
+				}
+
+				twoints[0] = usblp->current_protocol;
+				twoints[1] = 0;
+				for (i = USBLP_FIRST_PROTOCOL;
+				     i <= USBLP_LAST_PROTOCOL; i++) {
+					if (usblp->protocol[i].alt_setting >= 0)
+						twoints[1] |= (1<<i);
+				}
+
+				if (copy_to_user((unsigned char *)arg,
+						(unsigned char *)twoints,
+						sizeof(twoints))) {
+					retval = -EFAULT;
+					goto done;
+				}
+
+				break;
+
+			case IOCNR_SET_PROTOCOL:
+				if (_IOC_DIR(cmd) != _IOC_WRITE) {
+					retval = -EINVAL;
+					goto done;
+				}
+
+#ifdef DEBUG
+				if (arg == -10) {
+					usblp_dump(usblp);
+					break;
+				}
+#endif
+
+				usblp_unlink_urbs(usblp);
+				retval = usblp_set_protocol(usblp, arg);
+				if (retval < 0) {
+					usblp_set_protocol(usblp,
+						usblp->current_protocol);
+				}
+				break;
+
+			case IOCNR_HP_SET_CHANNEL:
+				if (_IOC_DIR(cmd) != _IOC_WRITE ||
+				    usblp->dev->descriptor.idVendor != 0x03F0 ||
+				    usblp->quirks & USBLP_QUIRK_BIDIR) {
+					retval = -EINVAL;
+					goto done;
+				}
+
+				err = usblp_hp_channel_change_request(usblp,
+					arg, &newChannel);
+				if (err < 0) {
+					err("usblp%d: error = %d setting "
+						"HP channel",
+						usblp->minor, err);
+					retval = -EIO;
+					goto done;
+				}
+
+				dbg("usblp%d requested/got HP channel %ld/%d",
+					usblp->minor, arg, newChannel);
+				break;
+
+			case IOCNR_GET_BUS_ADDRESS:
+				if (_IOC_DIR(cmd) != _IOC_READ ||
+				    _IOC_SIZE(cmd) < sizeof(twoints)) {
+					retval = -EINVAL;
+					goto done;
+				}
+
+				twoints[0] = usblp->dev->bus->busnum;
+				twoints[1] = usblp->dev->devnum;
+				if (copy_to_user((unsigned char *)arg,
+						(unsigned char *)twoints,
+						sizeof(twoints))) {
+					retval = -EFAULT;
+					goto done;
+				}
+
+				dbg("usblp%d is bus=%d, device=%d",
+					usblp->minor, twoints[0], twoints[1]);
+				break;
+
+			case IOCNR_GET_VID_PID:
+				if (_IOC_DIR(cmd) != _IOC_READ ||
+				    _IOC_SIZE(cmd) < sizeof(twoints)) {
+					retval = -EINVAL;
+					goto done;
+				}
+
+				twoints[0] = usblp->dev->descriptor.idVendor;
+				twoints[1] = usblp->dev->descriptor.idProduct;
+				if (copy_to_user((unsigned char *)arg,
+						(unsigned char *)twoints,
+						sizeof(twoints))) {
+					retval = -EFAULT;
+					goto done;
+				}
+
+				dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
+					usblp->minor, twoints[0], twoints[1]);
+				break;
+
+			default:
+				retval = -EINVAL;
+		}
+	else	/* old-style ioctl value */
+		switch (cmd) {
+
+			case LPGETSTATUS:
+				if (usblp_read_status(usblp, &status)) {
+					err("usblp%d: failed reading printer status", usblp->minor);
+					retval = -EIO;
+					goto done;
+				}
+				if (copy_to_user ((unsigned char *)arg, &status, 1))
+					retval = -EFAULT;
+				break;
+
+			default:
+				retval = -EINVAL;
+		}
+
+done:
+	up (&usblp->sem);
+	return retval;
+}
+
+static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct usblp *usblp = file->private_data;
+	int timeout, err = 0, writecount = 0;
+
+	while (writecount < count) {
+		if (!usblp->wcomplete) {
+			barrier();
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			timeout = USBLP_WRITE_TIMEOUT;
+			add_wait_queue(&usblp->wait, &wait);
+			while ( 1==1 ) {
+
+				if (signal_pending(current)) {
+					remove_wait_queue(&usblp->wait, &wait);
+					return writecount ? writecount : -EINTR;
+				}
+				set_current_state(TASK_INTERRUPTIBLE);
+				if (timeout && !usblp->wcomplete) {
+					timeout = schedule_timeout(timeout);
+				} else {
+					set_current_state(TASK_RUNNING);
+					break;
+				}
+			}
+			remove_wait_queue(&usblp->wait, &wait);
+		}
+
+		down (&usblp->sem);
+		if (!usblp->dev) {
+			up (&usblp->sem);
+			return -ENODEV;
+		}
+
+		if (usblp->writeurb->status != 0) {
+			if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+				if (!usblp->wcomplete)
+					err("usblp%d: error %d writing to printer",
+						usblp->minor, usblp->writeurb->status);
+				err = usblp->writeurb->status;
+			} else
+				err = usblp_check_status(usblp, err);
+			up (&usblp->sem);
+
+			/* if the fault was due to disconnect, let khubd's
+			 * call to usblp_disconnect() grab usblp->sem ...
+			 */
+			schedule ();
+			continue;
+		}
+
+		writecount += usblp->writeurb->transfer_buffer_length;
+		usblp->writeurb->transfer_buffer_length = 0;
+
+		if (writecount == count) {
+			up (&usblp->sem);
+			break;
+		}
+
+		usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
+							  (count - writecount) : USBLP_BUF_SIZE;
+
+		if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount,
+				usblp->writeurb->transfer_buffer_length)) return -EFAULT;
+
+		usblp->writeurb->dev = usblp->dev;
+		usblp->wcomplete = 0;
+		if (usb_submit_urb(usblp->writeurb, GFP_KERNEL)) {
+			count = -EIO;
+			up (&usblp->sem);
+			break;
+		}
+		up (&usblp->sem);
+	}
+
+	return count;
+}
+
+static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct usblp *usblp = file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (!usblp->bidir)
+		return -EINVAL;
+
+	down (&usblp->sem);
+	if (!usblp->dev) {
+		count = -ENODEV;
+		goto done;
+	}
+
+	if (!usblp->rcomplete) {
+		barrier();
+
+		if (file->f_flags & O_NONBLOCK) {
+			count = -EAGAIN;
+			goto done;
+		}
+
+		// FIXME:  only use urb->status inside completion
+		// callbacks; this way is racey...
+		add_wait_queue(&usblp->wait, &wait);
+		while (1==1) {
+			if (signal_pending(current)) {
+				count = -EINTR;
+				remove_wait_queue(&usblp->wait, &wait);
+				goto done;
+			}
+			up (&usblp->sem);
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!usblp->rcomplete) {
+				schedule();
+			} else {
+				set_current_state(TASK_RUNNING);
+				break;
+			}
+			down (&usblp->sem);
+		}
+		remove_wait_queue(&usblp->wait, &wait);
+	}
+
+	if (!usblp->dev) {
+		count = -ENODEV;
+		goto done;
+	}
+
+	if (usblp->readurb->status) {
+		err("usblp%d: error %d reading from printer",
+			usblp->minor, usblp->readurb->status);
+		usblp->readurb->dev = usblp->dev;
+ 		usblp->readcount = 0;
+		usb_submit_urb(usblp->readurb, GFP_KERNEL);
+		count = -EIO;
+		goto done;
+	}
+
+	count = count < usblp->readurb->actual_length - usblp->readcount ?
+		count :	usblp->readurb->actual_length - usblp->readcount;
+
+	if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
+		count = -EFAULT;
+		goto done;
+	}
+
+	if ((usblp->readcount += count) == usblp->readurb->actual_length) {
+		usblp->readcount = 0;
+		usblp->readurb->dev = usblp->dev;
+		usblp->rcomplete = 0;
+		if (usb_submit_urb(usblp->readurb, GFP_KERNEL)) {
+			count = -EIO;
+			goto done;
+		}
+	}
+
+done:
+	up (&usblp->sem);
+	return count;
+}
+
+/*
+ * Checks for printers that have quirks, such as requiring unidirectional
+ * communication but reporting bidirectional; currently some HP printers
+ * have this flaw (HP 810, 880, 895, etc.), or needing an init string
+ * sent at each open (like some Epsons).
+ * Returns 1 if found, 0 if not found.
+ *
+ * HP recommended that we use the bidirectional interface but
+ * don't attempt any bulk IN transfers from the IN endpoint.
+ * Here's some more detail on the problem:
+ * The problem is not that it isn't bidirectional though. The problem
+ * is that if you request a device ID, or status information, while
+ * the buffers are full, the return data will end up in the print data
+ * buffer. For example if you make sure you never request the device ID
+ * while you are sending print data, and you don't try to query the
+ * printer status every couple of milliseconds, you will probably be OK.
+ */
+static unsigned int usblp_quirks (__u16 vendor, __u16 product)
+{
+	int i;
+
+	for (i = 0; quirk_printers[i].vendorId; i++) {
+		if (vendor == quirk_printers[i].vendorId &&
+		    product == quirk_printers[i].productId)
+			return quirk_printers[i].quirks;
+ 	}
+	return 0;
+}
+
+static struct file_operations usblp_fops = {
+	owner:		THIS_MODULE,
+	read:		usblp_read,
+	write:		usblp_write,
+	poll:		usblp_poll,
+	ioctl:		usblp_ioctl,
+	open:		usblp_open,
+	release:	usblp_release,
+};
+
+static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
+			 const struct usb_device_id *id)
+{
+	struct usblp *usblp = 0;
+	int protocol;
+	char name[6];
+
+	/* Malloc and start initializing usblp structure so we can use it
+	 * directly. */
+	if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
+		err("out of memory for usblp");
+		goto abort;
+	}
+	memset(usblp, 0, sizeof(struct usblp));
+	usblp->dev = dev;
+	init_MUTEX (&usblp->sem);
+	init_waitqueue_head(&usblp->wait);
+	usblp->ifnum = ifnum;
+
+	/* Look for a free usblp_table entry. */
+	while (usblp_table[usblp->minor]) {
+		usblp->minor++;
+		if (usblp->minor >= USBLP_MINORS) {
+			err("no more free usblp devices");
+			goto abort;
+		}
+	}
+
+	usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!usblp->writeurb) {
+		err("out of memory");
+		goto abort;
+	}
+	usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!usblp->readurb) {
+		err("out of memory");
+		goto abort;
+	}
+
+	/* Malloc device ID string buffer to the largest expected length,
+	 * since we can re-query it on an ioctl and a dynamic string
+	 * could change in length. */
+	if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
+		err("out of memory for device_id_string");
+		goto abort;
+	}
+
+	/* Malloc write/read buffers in one chunk.  We somewhat wastefully
+	 * malloc both regardless of bidirectionality, because the
+	 * alternate setting can be changed later via an ioctl. */
+	if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
+		err("out of memory for buf");
+		goto abort;
+	}
+
+	/* Lookup quirks for this printer. */
+	usblp->quirks = usblp_quirks(
+		dev->descriptor.idVendor,
+		dev->descriptor.idProduct);
+
+	/* Analyze and pick initial alternate settings and endpoints. */
+	protocol = usblp_select_alts(usblp);
+	if (protocol < 0) {
+		dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
+			dev->descriptor.idVendor,
+			dev->descriptor.idProduct);
+		goto abort;
+	}
+
+	/* Setup the selected alternate setting and endpoints. */
+	if (usblp_set_protocol(usblp, protocol) < 0)
+		goto abort;
+
+	/* Retrieve and store the device ID string. */
+	usblp_cache_device_id_string(usblp);
+
+#ifdef DEBUG
+	usblp_check_status(usblp, 0);
+#endif
+
+	/* If we have devfs, create with perms=660. */
+	sprintf(name, "lp%d", usblp->minor);
+	usblp->devfs = devfs_register(usb_devfs_handle, name,
+				      DEVFS_FL_DEFAULT, USB_MAJOR,
+				      USBLP_MINOR_BASE + usblp->minor,
+				      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
+				      S_IWGRP, &usblp_fops, NULL);
+
+	info("usblp%d: USB %sdirectional printer dev %d "
+		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
+		usblp->protocol[usblp->current_protocol].alt_setting,
+		usblp->current_protocol, usblp->dev->descriptor.idVendor,
+		usblp->dev->descriptor.idProduct);
+
+	return usblp_table[usblp->minor] = usblp;
+
+abort:
+	if (usblp) {
+		usb_free_urb(usblp->writeurb);
+		usb_free_urb(usblp->readurb);
+		if (usblp->buf) kfree(usblp->buf);
+		if (usblp->device_id_string) kfree(usblp->device_id_string);
+		kfree(usblp);
+	}
+	return NULL;
+}
+
+/*
+ * We are a "new" style driver with usb_device_id table,
+ * but our requirements are too intricate for simple match to handle.
+ *
+ * The "proto_bias" option may be used to specify the preferred protocol
+ * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3).  If the device
+ * supports the preferred protocol, then we bind to it.
+ *
+ * The best interface for us is 7/1/2, because it is compatible
+ * with a stream of characters. If we find it, we bind to it.
+ *
+ * Note that the people from hpoj.sourceforge.net need to be able to
+ * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
+ *
+ * Failing 7/1/2, we look for 7/1/3, even though it's probably not
+ * stream-compatible, because this matches the behaviour of the old code.
+ *
+ * If nothing else, we bind to 7/1/1 - the unidirectional interface.
+ */
+static int usblp_select_alts(struct usblp *usblp)
+{
+	struct usb_interface *if_alt;
+	struct usb_interface_descriptor *ifd;
+	struct usb_endpoint_descriptor *epd, *epwrite, *epread;
+	int p, i, e;
+
+	if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
+
+	for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
+		usblp->protocol[p].alt_setting = -1;
+
+	/* Find out what we have. */
+	for (i = 0; i < if_alt->num_altsetting; i++) {
+		ifd = &if_alt->altsetting[i];
+
+		if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
+			continue;
+
+		if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
+		    ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
+			continue;
+
+		/* Look for bulk OUT and IN endpoints. */
+		epwrite = epread = 0;
+		for (e = 0; e < ifd->bNumEndpoints; e++) {
+			epd = &ifd->endpoint[e];
+
+			if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
+			    USB_ENDPOINT_XFER_BULK)
+				continue;
+
+			if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
+				if (!epwrite) epwrite=epd;
+
+			} else {
+				if (!epread) epread=epd;
+			}
+		}
+
+		/* Ignore buggy hardware without the right endpoints. */
+		if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
+			continue;
+
+		/* Turn off reads for 7/1/1 (unidirectional) interfaces
+		 * and buggy bidirectional printers. */
+		if (ifd->bInterfaceProtocol == 1) {
+			epread = NULL;
+		} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+			info("Disabling reads from problem bidirectional "
+				"printer on usblp%d", usblp->minor);
+			epread = NULL;
+		}
+
+		usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
+		usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
+		usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
+	}
+
+	/* If our requested protocol is supported, then use it. */
+	if (proto_bias >= USBLP_FIRST_PROTOCOL &&
+	    proto_bias <= USBLP_LAST_PROTOCOL &&
+	    usblp->protocol[proto_bias].alt_setting != -1)
+		return proto_bias;
+
+	/* Ordering is important here. */
+	if (usblp->protocol[2].alt_setting != -1) return 2;
+	if (usblp->protocol[1].alt_setting != -1) return 1;
+	if (usblp->protocol[3].alt_setting != -1) return 3;
+
+	/* If nothing is available, then don't bind to this device. */
+	return -1;
+}
+
+static int usblp_set_protocol(struct usblp *usblp, int protocol)
+{
+	int r, alts;
+
+	if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
+		return -EINVAL;
+
+	alts = usblp->protocol[protocol].alt_setting;
+	if (alts < 0) return -EINVAL;
+	r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
+	if (r < 0) {
+		err("can't set desired altsetting %d on interface %d",
+			alts, usblp->ifnum);
+		return r;
+	}
+
+	FILL_BULK_URB(usblp->writeurb, usblp->dev,
+		usb_sndbulkpipe(usblp->dev,
+		 usblp->protocol[protocol].epwrite->bEndpointAddress),
+		usblp->buf, 0,
+		usblp_bulk_write, usblp);
+
+	usblp->bidir = (usblp->protocol[protocol].epread != 0);
+	if (usblp->bidir)
+		FILL_BULK_URB(usblp->readurb, usblp->dev,
+			usb_rcvbulkpipe(usblp->dev,
+			 usblp->protocol[protocol].epread->bEndpointAddress),
+			usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
+			usblp_bulk_read, usblp);
+
+	usblp->current_protocol = protocol;
+	dbg("usblp%d set protocol %d", usblp->minor, protocol);
+	return 0;
+}
+
+/* Retrieves and caches device ID string.
+ * Returns length, including length bytes but not null terminator.
+ * On error, returns a negative errno value. */
+static int usblp_cache_device_id_string(struct usblp *usblp)
+{
+	int err, length;
+
+	err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
+	if (err < 0) {
+		dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
+			usblp->minor, err);
+		usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
+		return -EIO;
+	}
+
+	/* First two bytes are length in big-endian.
+	 * They count themselves, and we copy them into
+	 * the user's buffer. */
+	length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
+	if (length < 2)
+		length = 2;
+	else if (length >= DEVICE_ID_SIZE)
+		length = DEVICE_ID_SIZE - 1;
+	usblp->device_id_string[length] = '\0';
+
+	dbg("usblp%d Device ID string [len=%d]=\"%s\"",
+		usblp->minor, length, &usblp->device_id_string[2]);
+
+	return length;
+}
+
+static void usblp_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usblp *usblp = ptr;
+
+	if (!usblp || !usblp->dev) {
+		err("bogus disconnect");
+		BUG ();
+	}
+
+	down (&usblp->sem);
+	lock_kernel();
+	usblp->dev = NULL;
+
+	usblp_unlink_urbs(usblp);
+
+	if (!usblp->used)
+		usblp_cleanup (usblp);
+	else 	/* cleanup later, on close */
+		up (&usblp->sem);
+	unlock_kernel();
+}
+
+static struct usb_device_id usblp_ids [] = {
+	{ USB_DEVICE_INFO(7, 1, 1) },
+	{ USB_DEVICE_INFO(7, 1, 2) },
+	{ USB_DEVICE_INFO(7, 1, 3) },
+	{ USB_INTERFACE_INFO(7, 1, 1) },
+	{ USB_INTERFACE_INFO(7, 1, 2) },
+	{ USB_INTERFACE_INFO(7, 1, 3) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usblp_ids);
+
+static struct usb_driver usblp_driver = {
+	owner:		THIS_MODULE,
+	name:		"usblp",
+	probe:		usblp_probe,
+	disconnect:	usblp_disconnect,
+	fops:		&usblp_fops,
+	minor:		USBLP_MINOR_BASE,
+	id_table:	usblp_ids,
+};
+
+static int __init usblp_init(void)
+{
+	if (usb_register(&usblp_driver))
+		return -1;
+	info(DRIVER_VERSION ": " DRIVER_DESC);
+	return 0;
+}
+
+static void __exit usblp_exit(void)
+{
+	usb_deregister(&usblp_driver);
+}
+
+module_init(usblp_init);
+module_exit(usblp_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_PARM(proto_bias, "i");
+MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/core/Config.in b/drivers/usb/core/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,14 @@
+#
+# USB Core configuration
+#
+bool '  USB verbose debug messages' CONFIG_USB_DEBUG
+
+comment 'Miscellaneous USB options'
+bool '  USB device filesystem' CONFIG_USB_DEVICEFS
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   bool '  Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
+else
+   define_bool CONFIG_USB_BANDWIDTH n
+fi
+bool '  Long timeout for slow-responding devices (some MGE Ellipse UPSes)' CONFIG_USB_LONG_TIMEOUT
+
diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,17 @@
+#
+# Makefile for USB Core files and filesystem
+#
+
+O_TARGET	:= usb-core.o
+
+export-objs	:= usb.o hcd.o
+
+usbcore-objs	:= usb.o usb-debug.o hub.o hcd.o
+
+ifeq ($(CONFIG_USB_DEVICEFS),y)
+	usbcore-objs	+= devio.o inode.o drivers.o devices.o
+endif
+
+obj-$(CONFIG_USB)	+= usbcore.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/devices.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,662 @@
+/*
+ * devices.c
+ * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * This program is free software; you can redistribute it and/or 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
+ *
+ *************************************************************
+ *
+ * <mountpoint>/devices contains USB topology, device, config, class,
+ * interface, & endpoint data.
+ *
+ * I considered using /proc/bus/usb/devices/device# for each device
+ * as it is attached or detached, but I didn't like this for some
+ * reason -- maybe it's just too deep of a directory structure.
+ * I also don't like looking in multiple places to gather and view
+ * the data.  Having only one file for ./devices also prevents race
+ * conditions that could arise if a program was reading device info
+ * for devices that are being removed (unplugged).  (That is, the
+ * program may find a directory for devnum_12 then try to open it,
+ * but it was just unplugged, so the directory is now deleted.
+ * But programs would just have to be prepared for situations like
+ * this in any plug-and-play environment.)
+ *
+ * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Converted the whole proc stuff to real
+ *   read methods. Now not the whole device list needs to fit
+ *   into one page, only the device list for one bus.
+ *   Added a poll method to /proc/bus/usb/devices, to wake
+ *   up an eventual usbd
+ * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Turned into its own filesystem
+ * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
+ *   Converted file reading routine to dump to buffer once
+ *   per device, not per bus
+ *
+ * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+#include <linux/usbdevice_fs.h>
+#include <asm/uaccess.h>
+
+#include "hcd.h"
+
+#define MAX_TOPO_LEVEL		6
+
+/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
+#define ALLOW_SERIAL_NUMBER
+
+static char *format_topo =
+/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
+  "T:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
+
+static char *format_string_manufacturer =
+/* S:  Manufacturer=xxxx */
+  "S:  Manufacturer=%.100s\n";
+
+static char *format_string_product =
+/* S:  Product=xxxx */
+  "S:  Product=%.100s\n";
+
+#ifdef ALLOW_SERIAL_NUMBER
+static char *format_string_serialnumber =
+/* S:  SerialNumber=xxxx */
+  "S:  SerialNumber=%.100s\n";
+#endif
+
+static char *format_bandwidth =
+/* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
+  "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
+  
+static char *format_device1 =
+/* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
+  "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
+
+static char *format_device2 =
+/* P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx */
+  "P:  Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
+
+static char *format_config =
+/* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
+  "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
+  
+static char *format_iface =
+/* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
+  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
+
+static char *format_endpt =
+/* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
+  "E:  Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
+
+
+/*
+ * Need access to the driver and USB bus lists.
+ * extern struct list_head usb_driver_list;
+ * extern struct list_head usb_bus_list;
+ * However, these will come from functions that return ptrs to each of them.
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
+static unsigned int conndiscevcnt = 0;
+
+/* this struct stores the poll state for <mountpoint>/devices pollers */
+struct usb_device_status {
+	unsigned int lastev;
+};
+
+struct class_info {
+	int class;
+	char *class_name;
+};
+
+static const struct class_info clas_info[] =
+{					/* max. 5 chars. per name string */
+	{USB_CLASS_PER_INTERFACE,	">ifc"},
+	{USB_CLASS_AUDIO,		"audio"},
+	{USB_CLASS_COMM,		"comm."},
+	{USB_CLASS_HID,			"HID"},
+	{USB_CLASS_HUB,			"hub"},
+	{USB_CLASS_PHYSICAL,		"PID"},
+	{USB_CLASS_PRINTER,		"print"},
+	{USB_CLASS_MASS_STORAGE,	"stor."},
+	{USB_CLASS_CDC_DATA,		"data"},
+	{USB_CLASS_APP_SPEC,		"app."},
+	{USB_CLASS_VENDOR_SPEC,		"vend."},
+	{USB_CLASS_STILL_IMAGE,		"still"},
+	{USB_CLASS_CSCID,		"scard"},
+	{USB_CLASS_CONTENT_SEC,		"c-sec"},
+	{-1,				"unk."}		/* leave as last */
+};
+
+/*****************************************************************/
+
+void usbdevfs_conn_disc_event(void)
+{
+	wake_up(&deviceconndiscwq);
+	conndiscevcnt++;
+}
+
+static const char *class_decode(const int class)
+{
+	int ix;
+
+	for (ix = 0; clas_info[ix].class != -1; ix++)
+		if (clas_info[ix].class == class)
+			break;
+	return (clas_info[ix].class_name);
+}
+
+static char *usb_dump_endpoint_descriptor (
+	int speed,
+	char *start,
+	char *end,
+	const struct usb_endpoint_descriptor *desc
+)
+{
+	char dir, unit, *type;
+	unsigned interval, in, bandwidth = 1;
+
+	if (start > end)
+		return start;
+	in = (desc->bEndpointAddress & USB_DIR_IN);
+	dir = in ? 'I' : 'O';
+	if (speed == USB_SPEED_HIGH) {
+		switch (desc->wMaxPacketSize & (0x03 << 11)) {
+		case 1 << 11:	bandwidth = 2; break;
+		case 2 << 11:	bandwidth = 3; break;
+		}
+	}
+
+	/* this isn't checking for illegal values */
+	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		type = "Ctrl";
+		if (speed == USB_SPEED_HIGH) 	/* uframes per NAK */
+			interval = desc->bInterval;
+		else
+			interval = 0;
+		dir = 'B';			/* ctrl is bidirectional */
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		type = "Isoc";
+		interval = 1 << (desc->bInterval - 1);
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		type = "Bulk";
+		if (speed == USB_SPEED_HIGH && !in)	/* uframes per NAK */
+			interval = desc->bInterval;
+		else
+			interval = 0;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		type = "Int.";
+		if (speed == USB_SPEED_HIGH) {
+			interval = 1 << (desc->bInterval - 1);
+		} else
+			interval = desc->bInterval;
+		break;
+	default:	/* "can't happen" */
+		return start;
+	}
+	interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
+	if (interval % 1000)
+		unit = 'u';
+	else {
+		unit = 'm';
+		interval /= 1000;
+	}
+
+	start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
+			 desc->bmAttributes, type,
+			 (desc->wMaxPacketSize & 0x07ff) * bandwidth,
+			 interval, unit);
+	return start;
+}
+
+static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
+{
+	struct usb_interface_descriptor *desc = &iface->altsetting[setno];
+
+	if (start > end)
+		return start;
+	start += sprintf(start, format_iface,
+			 desc->bInterfaceNumber,
+			 desc->bAlternateSetting,
+			 desc->bNumEndpoints,
+			 desc->bInterfaceClass,
+			 class_decode(desc->bInterfaceClass),
+			 desc->bInterfaceSubClass,
+			 desc->bInterfaceProtocol,
+			 iface->driver ? iface->driver->name : "(none)");
+	return start;
+}
+
+static char *usb_dump_interface(
+	int speed,
+	char *start,
+	char *end,
+	const struct usb_interface *iface,
+	int setno
+) {
+	struct usb_interface_descriptor *desc = &iface->altsetting[setno];
+	int i;
+
+	start = usb_dump_interface_descriptor(start, end, iface, setno);
+	for (i = 0; i < desc->bNumEndpoints; i++) {
+		if (start > end)
+			return start;
+		start = usb_dump_endpoint_descriptor(speed,
+				start, end, desc->endpoint + i);
+	}
+	return start;
+}
+
+/* TBD:
+ * 0. TBDs
+ * 1. marking active config and ifaces (code lists all, but should mark
+ *    which ones are active, if any)
+ * 2. add <halted> status to each endpoint line
+ */
+
+static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
+{
+	if (start > end)
+		return start;
+	start += sprintf(start, format_config,
+			 active ? '*' : ' ',	/* mark active/actual/current cfg. */
+			 desc->bNumInterfaces,
+			 desc->bConfigurationValue,
+			 desc->bmAttributes,
+			 desc->MaxPower * 2);
+	return start;
+}
+
+static char *usb_dump_config (
+	int speed,
+	char *start,
+	char *end,
+	const struct usb_config_descriptor *config,
+	int active
+)
+{
+	int i, j;
+	struct usb_interface *interface;
+
+	if (start > end)
+		return start;
+	if (!config)		/* getting these some in 2.3.7; none in 2.3.6 */
+		return start + sprintf(start, "(null Cfg. desc.)\n");
+	start = usb_dump_config_descriptor(start, end, config, active);
+	for (i = 0; i < config->bNumInterfaces; i++) {
+		interface = config->interface + i;
+		if (!interface)
+			break;
+		for (j = 0; j < interface->num_altsetting; j++) {
+			if (start > end)
+				return start;
+			start = usb_dump_interface(speed,
+					start, end, interface, j);
+		}
+	}
+	return start;
+}
+
+/*
+ * Dump the different USB descriptors.
+ */
+static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
+{
+	if (start > end)
+		return start;
+	start += sprintf (start, format_device1,
+			  desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
+			  desc->bDeviceClass,
+			  class_decode (desc->bDeviceClass),
+			  desc->bDeviceSubClass,
+			  desc->bDeviceProtocol,
+			  desc->bMaxPacketSize0,
+			  desc->bNumConfigurations);
+	if (start > end)
+		return start;
+	start += sprintf(start, format_device2,
+			 desc->idVendor, desc->idProduct,
+			 desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
+	return start;
+}
+
+/*
+ * Dump the different strings that this device holds.
+ */
+static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
+{
+	char *buf;
+
+	if (start > end)
+		return start;
+	buf = kmalloc(128, GFP_KERNEL);
+	if (!buf)
+		return start;
+	if (dev->descriptor.iManufacturer) {
+		if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0)
+			start += sprintf(start, format_string_manufacturer, buf);
+	}				
+	if (start > end)
+		goto out;
+	if (dev->descriptor.iProduct) {
+		if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0)
+			start += sprintf(start, format_string_product, buf);
+	}
+	if (start > end)
+		goto out;
+#ifdef ALLOW_SERIAL_NUMBER
+	if (dev->descriptor.iSerialNumber) {
+		if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0)
+			start += sprintf(start, format_string_serialnumber, buf);
+	}
+#endif
+ out:
+	kfree(buf);
+	return start;
+}
+
+static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
+{
+	int i;
+
+	if (start > end)
+		return start;
+		
+	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
+
+	if (start > end)
+		return start;
+	
+	start = usb_dump_device_strings (start, end, dev);
+	
+	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+		if (start > end)
+			return start;
+		start = usb_dump_config(dev->speed,
+				start, end, dev->config + i,
+				/* active ? */
+				(dev->config + i) == dev->actconfig);
+	}
+	return start;
+}
+
+
+#ifdef PROC_EXTRA /* TBD: may want to add this code later */
+
+static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
+{
+	int leng = USB_DT_HUB_NONVAR_SIZE;
+	unsigned char *ptr = (unsigned char *)desc;
+
+	if (start > end)
+		return start;
+	start += sprintf(start, "Interface:");
+	while (leng && start <= end) {
+		start += sprintf(start, " %02x", *ptr);
+		ptr++; leng--;
+	}
+	*start++ = '\n';
+	return start;
+}
+
+static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
+{
+	if (start > end)
+		return start;
+	start += sprintf(start, "Interface:");
+	if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
+		start += sprintf(start, "%s: %.100s ", id, dev->stringindex[index]);
+	return start;
+}
+
+#endif /* PROC_EXTRA */
+
+/*****************************************************************/
+
+/* This is a recursive function. Parameters:
+ * buffer - the user-space buffer to write data into
+ * nbytes - the maximum number of bytes to write
+ * skip_bytes - the number of bytes to skip before writing anything
+ * file_offset - the offset into the devices file on completion
+ */
+static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
+				struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
+{
+	int chix;
+	int ret, cnt = 0;
+	int parent_devnum = 0;
+	char *pages_start, *data_end, *speed;
+	unsigned int length;
+	ssize_t total_written = 0;
+	
+	/* don't bother with anything else if we're not writing any data */
+	if (*nbytes <= 0)
+		return 0;
+	
+	if (level > MAX_TOPO_LEVEL)
+		return total_written;
+	/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
+        if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
+                return -ENOMEM;
+		
+	if (usbdev->parent && usbdev->parent->devnum != -1)
+		parent_devnum = usbdev->parent->devnum;
+	/*
+	 * So the root hub's parent is 0 and any device that is
+	 * plugged into the root hub has a parent of 0.
+	 */
+	switch (usbdev->speed) {
+	case USB_SPEED_LOW:
+		speed = "1.5"; break;
+	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
+	case USB_SPEED_FULL:
+		speed = "12 "; break;
+	case USB_SPEED_HIGH:
+		speed = "480"; break;
+	default:
+		speed = "?? ";
+	}
+	data_end = pages_start + sprintf(pages_start, format_topo,
+			bus->busnum, level, parent_devnum,
+			index, count, usbdev->devnum,
+			speed, usbdev->maxchild);
+	/*
+	 * level = topology-tier level;
+	 * parent_devnum = parent device number;
+	 * index = parent's connector number;
+	 * count = device count at this level
+	 */
+	/* If this is the root hub, display the bandwidth information */
+	if (level == 0) {
+		int	max;
+
+		/* high speed reserves 80%, full/low reserves 90% */
+		if (usbdev->speed == USB_SPEED_HIGH)
+			max = 800;
+		else
+			max = FRAME_TIME_MAX_USECS_ALLOC;
+
+		/* report "average" periodic allocation over a microsecond.
+		 * the schedules are actually bursty, HCDs need to deal with
+		 * that and just compute/report this average.
+		 */
+		data_end += sprintf(data_end, format_bandwidth,
+				bus->bandwidth_allocated, max,
+				(100 * bus->bandwidth_allocated + max / 2)
+					/ max,
+			         bus->bandwidth_int_reqs,
+				 bus->bandwidth_isoc_reqs);
+	
+	}
+	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
+	
+	if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
+		data_end += sprintf(data_end, "(truncated)\n");
+	
+	length = data_end - pages_start;
+	/* if we can start copying some data to the user */
+	if (length > *skip_bytes) {
+		length -= *skip_bytes;
+		if (length > *nbytes)
+			length = *nbytes;
+		if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
+			free_pages((unsigned long)pages_start, 1);
+			
+			if (total_written == 0)
+				return -EFAULT;
+			return total_written;
+		}
+		*nbytes -= length;
+		*file_offset += length;
+		total_written += length;
+		*buffer += length;
+		*skip_bytes = 0;
+	} else
+		*skip_bytes -= length;
+	
+	free_pages((unsigned long)pages_start, 1);
+	
+	/* Now look at all of this device's children. */
+	for (chix = 0; chix < usbdev->maxchild; chix++) {
+		if (usbdev->children[chix]) {
+			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix],
+					bus, level + 1, chix, ++cnt);
+			if (ret == -EFAULT)
+				return total_written;
+			total_written += ret;
+		}
+	}
+	return total_written;
+}
+
+static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+	struct list_head *buslist;
+	struct usb_bus *bus;
+	ssize_t ret, total_written = 0;
+	loff_t skip_bytes = *ppos;
+
+	if (*ppos < 0)
+		return -EINVAL;
+	if (nbytes <= 0)
+		return 0;
+	if (!access_ok(VERIFY_WRITE, buf, nbytes))
+		return -EFAULT;
+
+	/* enumerate busses */
+	down (&usb_bus_list_lock);
+	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
+		/* print devices for this bus */
+		bus = list_entry(buslist, struct usb_bus, bus_list);
+		/* recurse through all children of the root hub */
+		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
+		if (ret < 0)
+			return ret;
+		total_written += ret;
+	}
+	up (&usb_bus_list_lock);
+	return total_written;
+}
+
+/* Kernel lock for "lastev" protection */
+static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct usb_device_status *st = (struct usb_device_status *)file->private_data;
+	unsigned int mask = 0;
+
+	lock_kernel();
+	if (!st) {
+		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
+		if (!st) {
+			unlock_kernel();
+			return POLLIN;
+		}
+		/*
+		 * need to prevent the module from being unloaded, since
+		 * proc_unregister does not call the release method and
+		 * we would have a memory leak
+		 */
+		st->lastev = conndiscevcnt;
+		file->private_data = st;
+		mask = POLLIN;
+	}
+	if (file->f_mode & FMODE_READ)
+                poll_wait(file, &deviceconndiscwq, wait);
+	if (st->lastev != conndiscevcnt)
+		mask |= POLLIN;
+	st->lastev = conndiscevcnt;
+	unlock_kernel();
+	return mask;
+}
+
+static int usb_device_open(struct inode *inode, struct file *file)
+{
+        file->private_data = NULL;
+        return 0;
+}
+
+static int usb_device_release(struct inode *inode, struct file *file)
+{
+	if (file->private_data) {
+		kfree(file->private_data);
+		file->private_data = NULL;
+	}
+
+        return 0;
+}
+
+static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
+{
+	loff_t ret;
+
+	lock_kernel();
+
+	switch (orig) {
+	case 0:
+		file->f_pos = offset;
+		ret = file->f_pos;
+		break;
+	case 1:
+		file->f_pos += offset;
+		ret = file->f_pos;
+		break;
+	case 2:
+	default:
+		ret = -EINVAL;
+	}
+
+	unlock_kernel();
+	return ret;
+}
+
+struct file_operations usbdevfs_devices_fops = {
+	llseek:		usb_device_lseek,
+	read:		usb_device_read,
+	poll:		usb_device_poll,
+	open:		usb_device_open,
+	release:	usb_device_release,
+};
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/devio.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,1249 @@
+/*****************************************************************************/
+
+/*
+ *      devio.c  --  User space communication with USB devices.
+ *
+ *      Copyright (C) 1999-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or 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.
+ *
+ *  $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $
+ *
+ *  This file implements the usbdevfs/x/y files, where
+ *  x is the bus number and y the device number.
+ *
+ *  It allows user space programs/"drivers" to communicate directly
+ *  with USB devices without intervening kernel driver.
+ *
+ *  Revision history
+ *    22.12.1999   0.1   Initial release (split from proc_usb.c)
+ *    04.01.2000   0.2   Turned into its own filesystem
+ */
+
+/*****************************************************************************/
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/signal.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+
+struct async {
+        struct list_head asynclist;
+        struct dev_state *ps;
+	struct task_struct *task;
+	unsigned int signr;
+	void *userbuffer;
+        void *userurb;
+        struct urb *urb;
+};
+
+static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
+{
+	loff_t ret;
+
+	lock_kernel();
+
+	switch (orig) {
+	case 0:
+		file->f_pos = offset;
+		ret = file->f_pos;
+		break;
+	case 1:
+		file->f_pos += offset;
+		ret = file->f_pos;
+		break;
+	case 2:
+	default:
+		ret = -EINVAL;
+	}
+
+	unlock_kernel();
+	return ret;
+}
+
+static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos)
+{
+	struct dev_state *ps = (struct dev_state *)file->private_data;
+	ssize_t ret = 0;
+	unsigned len;
+	loff_t pos;
+	int i;
+
+	pos = *ppos;
+	down_read(&ps->devsem);
+	if (!ps->dev) {
+		ret = -ENODEV;
+		goto err;
+	} else if (pos < 0) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (pos < sizeof(struct usb_device_descriptor)) {
+		len = sizeof(struct usb_device_descriptor) - pos;
+		if (len > nbytes)
+			len = nbytes;
+		if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) {
+			ret = -EFAULT;
+			goto err;
+		}
+
+		*ppos += len;
+		buf += len;
+		nbytes -= len;
+		ret += len;
+	}
+
+	pos = sizeof(struct usb_device_descriptor);
+	for (i = 0; nbytes && i < ps->dev->descriptor.bNumConfigurations; i++) {
+		struct usb_config_descriptor *config =
+			(struct usb_config_descriptor *)ps->dev->rawdescriptors[i];
+		unsigned int length = le16_to_cpu(config->wTotalLength);
+
+		if (*ppos < pos + length) {
+			len = length - (*ppos - pos);
+			if (len > nbytes)
+				len = nbytes;
+
+			if (copy_to_user(buf,
+			    ps->dev->rawdescriptors[i] + (*ppos - pos), len)) {
+				ret = -EFAULT;
+				goto err;
+			}
+
+			*ppos += len;
+			buf += len;
+			nbytes -= len;
+			ret += len;
+		}
+
+		pos += length;
+	}
+
+err:
+	up_read(&ps->devsem);
+	return ret;
+}
+
+extern inline unsigned int ld2(unsigned int x)
+{
+        unsigned int r = 0;
+        
+        if (x >= 0x10000) {
+                x >>= 16;
+                r += 16;
+        }
+        if (x >= 0x100) {
+                x >>= 8;
+                r += 8;
+        }
+        if (x >= 0x10) {
+                x >>= 4;
+                r += 4;
+        }
+        if (x >= 4) {
+                x >>= 2;
+                r += 2;
+        }
+        if (x >= 2)
+                r++;
+        return r;
+}
+
+/*
+ * async list handling
+ */
+
+static struct async *alloc_async(unsigned int numisoframes)
+{
+        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
+        struct async *as = kmalloc(assize, GFP_KERNEL);
+        if (!as)
+                return NULL;
+        memset(as, 0, assize);
+	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
+	if (!as->urb) {
+		kfree(as);
+		return NULL;
+	}
+        return as;
+}
+
+static void free_async(struct async *as)
+{
+        if (as->urb->transfer_buffer)
+                kfree(as->urb->transfer_buffer);
+        if (as->urb->setup_packet)
+                kfree(as->urb->setup_packet);
+	usb_free_urb(as->urb);
+        kfree(as);
+}
+
+extern __inline__ void async_newpending(struct async *as)
+{
+        struct dev_state *ps = as->ps;
+        unsigned long flags;
+        
+        spin_lock_irqsave(&ps->lock, flags);
+        list_add_tail(&as->asynclist, &ps->async_pending);
+        spin_unlock_irqrestore(&ps->lock, flags);
+}
+
+extern __inline__ void async_removepending(struct async *as)
+{
+        struct dev_state *ps = as->ps;
+        unsigned long flags;
+        
+        spin_lock_irqsave(&ps->lock, flags);
+        list_del(&as->asynclist);
+        INIT_LIST_HEAD(&as->asynclist);
+        spin_unlock_irqrestore(&ps->lock, flags);
+}
+
+extern __inline__ struct async *async_getcompleted(struct dev_state *ps)
+{
+        unsigned long flags;
+        struct async *as = NULL;
+
+        spin_lock_irqsave(&ps->lock, flags);
+        if (!list_empty(&ps->async_completed)) {
+                as = list_entry(ps->async_completed.next, struct async, asynclist);
+                list_del(&as->asynclist);
+                INIT_LIST_HEAD(&as->asynclist);
+        }
+        spin_unlock_irqrestore(&ps->lock, flags);
+        return as;
+}
+
+extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb)
+{
+        unsigned long flags;
+        struct async *as;
+        struct list_head *p;
+
+        spin_lock_irqsave(&ps->lock, flags);
+        for (p = ps->async_pending.next; p != &ps->async_pending; ) {
+                as = list_entry(p, struct async, asynclist);
+                p = p->next;
+                if (as->userurb != userurb)
+                        continue;
+                list_del(&as->asynclist);
+                INIT_LIST_HEAD(&as->asynclist);
+                spin_unlock_irqrestore(&ps->lock, flags);
+                return as;
+        }
+        spin_unlock_irqrestore(&ps->lock, flags);
+        return NULL;
+}
+
+static void async_completed(struct urb *urb)
+{
+        struct async *as = (struct async *)urb->context;
+        struct dev_state *ps = as->ps;
+	struct siginfo sinfo;
+
+        spin_lock(&ps->lock);
+        list_del(&as->asynclist);
+        list_add_tail(&as->asynclist, &ps->async_completed);
+        spin_unlock(&ps->lock);
+        wake_up(&ps->wait);
+	if (as->signr) {
+		sinfo.si_signo = as->signr;
+		sinfo.si_errno = as->urb->status;
+		sinfo.si_code = SI_ASYNCIO;
+		sinfo.si_addr = as->userurb;
+		send_sig_info(as->signr, &sinfo, as->task);
+	}
+}
+
+static void destroy_all_async(struct dev_state *ps)
+{
+        struct async *as;
+        unsigned long flags;
+
+        spin_lock_irqsave(&ps->lock, flags);
+        while (!list_empty(&ps->async_pending)) {
+                as = list_entry(ps->async_pending.next, struct async, asynclist);
+                list_del(&as->asynclist);
+                INIT_LIST_HEAD(&as->asynclist);
+                spin_unlock_irqrestore(&ps->lock, flags);
+                /* usb_unlink_urb calls the completion handler with status == -ENOENT */
+                usb_unlink_urb(as->urb);
+                spin_lock_irqsave(&ps->lock, flags);
+        }
+        spin_unlock_irqrestore(&ps->lock, flags);
+        while ((as = async_getcompleted(ps)))
+                free_async(as);
+}
+
+/*
+ * interface claiming
+ */
+
+static void *driver_probe(struct usb_device *dev, unsigned int intf,
+			  const struct usb_device_id *id)
+{
+	return NULL;
+}
+
+static void driver_disconnect(struct usb_device *dev, void *context)
+{
+	struct dev_state *ps = (struct dev_state *)context;
+
+	if (ps)
+		ps->ifclaimed = 0;
+}
+
+struct usb_driver usbdevfs_driver = {
+	name:		"usbfs",
+	probe:		driver_probe,
+	disconnect:	driver_disconnect,
+};
+
+static int claimintf(struct dev_state *ps, unsigned int intf)
+{
+	struct usb_device *dev = ps->dev;
+	struct usb_interface *iface;
+	int err;
+
+	if (intf >= 8*sizeof(ps->ifclaimed) || !dev || intf >= dev->actconfig->bNumInterfaces)
+		return -EINVAL;
+	/* already claimed */
+	if (test_bit(intf, &ps->ifclaimed))
+		return 0;
+	iface = &dev->actconfig->interface[intf];
+	err = -EBUSY;
+	lock_kernel();
+	if (!usb_interface_claimed(iface)) {
+		usb_driver_claim_interface(&usbdevfs_driver, iface, ps);
+		set_bit(intf, &ps->ifclaimed);
+		err = 0;
+	}
+	unlock_kernel();
+	return err;
+}
+
+static int releaseintf(struct dev_state *ps, unsigned int intf)
+{
+	struct usb_device *dev;
+	struct usb_interface *iface;
+	int err;
+
+	if (intf >= 8*sizeof(ps->ifclaimed))
+		return -EINVAL;
+	err = -EINVAL;
+	lock_kernel();
+	dev = ps->dev;
+	if (dev && test_and_clear_bit(intf, &ps->ifclaimed)) {
+		iface = &dev->actconfig->interface[intf];
+		usb_driver_release_interface(&usbdevfs_driver, iface);
+		err = 0;
+	}
+	unlock_kernel();
+	return err;
+}
+
+static int checkintf(struct dev_state *ps, unsigned int intf)
+{
+	if (intf >= 8*sizeof(ps->ifclaimed))
+		return -EINVAL;
+	if (test_bit(intf, &ps->ifclaimed))
+		return 0;
+	/* if not yet claimed, claim it for the driver */
+	printk(KERN_WARNING "usbfs: process %d (%s) did not claim interface %u before use\n",
+	       current->pid, current->comm, intf);
+	return claimintf(ps, intf);
+}
+
+static int findintfep(struct usb_device *dev, unsigned int ep)
+{
+	unsigned int i, j, e;
+        struct usb_interface *iface;
+	struct usb_interface_descriptor *alts;
+	struct usb_endpoint_descriptor *endpt;
+
+	if (ep & ~(USB_DIR_IN|0xf))
+		return -EINVAL;
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+		iface = &dev->actconfig->interface[i];
+		for (j = 0; j < iface->num_altsetting; j++) {
+                        alts = &iface->altsetting[j];
+			for (e = 0; e < alts->bNumEndpoints; e++) {
+				endpt = &alts->endpoint[e];
+				if (endpt->bEndpointAddress == ep)
+					return i;
+			}
+		}
+	}
+	return -ENOENT; 
+}
+
+static int findintfif(struct usb_device *dev, unsigned int ifn)
+{
+	unsigned int i, j;
+        struct usb_interface *iface;
+	struct usb_interface_descriptor *alts;
+
+	if (ifn & ~0xff)
+		return -EINVAL;
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+		iface = &dev->actconfig->interface[i];
+		for (j = 0; j < iface->num_altsetting; j++) {
+                        alts = &iface->altsetting[j];
+			if (alts->bInterfaceNumber == ifn)
+				return i;
+		}
+	}
+	return -ENOENT; 
+}
+
+extern struct list_head usb_driver_list;
+
+#if 0
+static int finddriver(struct usb_driver **driver, char *name)
+{
+	struct list_head *tmp;
+
+	tmp = usb_driver_list.next;
+	while (tmp != &usb_driver_list) {
+		struct usb_driver *d = list_entry(tmp, struct usb_driver,
+							driver_list);
+
+		if (!strcmp(d->name, name)) {
+			*driver = d;
+			return 0;
+		}
+
+		tmp = tmp->next;
+	}
+
+	return -EINVAL;
+}
+#endif
+
+static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
+{
+	int ret;
+
+	if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
+		return 0;
+
+	switch (requesttype & USB_RECIP_MASK) {
+	case USB_RECIP_ENDPOINT:
+		if ((ret = findintfep(ps->dev, index & 0xff)) < 0)
+			return ret;
+		if ((ret = checkintf(ps, ret)))
+			return ret;
+		break;
+
+	case USB_RECIP_INTERFACE:
+		if ((ret = findintfif(ps->dev, index & 0xff)) < 0)
+			return ret;
+		if ((ret = checkintf(ps, ret)))
+			return ret;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * file operations
+ */
+static int usbdev_open(struct inode *inode, struct file *file)
+{
+	struct usb_device *dev;
+	struct dev_state *ps;
+	int ret;
+
+	/* 
+	 * no locking necessary here, as both sys_open (actually filp_open)
+	 * and the hub thread have the kernel lock
+	 * (still acquire the kernel lock for safety)
+	 */
+	lock_kernel();
+	ret = -ENOENT;
+	dev = inode->u.generic_ip;
+	if (!dev)
+		goto out;
+	ret = -ENOMEM;
+	if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+		goto out;
+	ret = 0;
+	ps->dev = dev;
+	ps->file = file;
+	spin_lock_init(&ps->lock);
+	INIT_LIST_HEAD(&ps->async_pending);
+	INIT_LIST_HEAD(&ps->async_completed);
+	init_waitqueue_head(&ps->wait);
+	init_rwsem(&ps->devsem);
+	ps->discsignr = 0;
+	ps->disctask = current;
+	ps->disccontext = NULL;
+	ps->ifclaimed = 0;
+	wmb();
+	list_add_tail(&ps->list, &dev->filelist);
+	file->private_data = ps;
+ out:
+	unlock_kernel();
+        return ret;
+}
+
+static int usbdev_release(struct inode *inode, struct file *file)
+{
+	struct dev_state *ps = (struct dev_state *)file->private_data;
+	unsigned int i;
+
+	lock_kernel();
+	list_del(&ps->list);
+	INIT_LIST_HEAD(&ps->list);
+	if (ps->dev) {
+		for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
+			if (test_bit(i, &ps->ifclaimed))
+				releaseintf(ps, i);
+	}
+	unlock_kernel();
+	destroy_all_async(ps);
+	kfree(ps);
+        return 0;
+}
+
+static int proc_control(struct dev_state *ps, void *arg)
+{
+	struct usb_device *dev = ps->dev;
+	struct usbdevfs_ctrltransfer ctrl;
+	unsigned int tmo;
+	unsigned char *tbuf;
+	int i, ret;
+
+	if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl)))
+		return -EFAULT;
+	if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
+		return ret;
+	if (ctrl.wLength > PAGE_SIZE)
+		return -EINVAL;
+	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	tmo = (ctrl.timeout * HZ + 999) / 1000;
+	if (ctrl.bRequestType & 0x80) {
+		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
+			free_page((unsigned long)tbuf);
+			return -EINVAL;
+		}
+		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
+				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		if ((i > 0) && ctrl.wLength) {
+			if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
+				free_page((unsigned long)tbuf);
+				return -EFAULT;
+			}
+		}
+	} else {
+		if (ctrl.wLength) {
+			if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
+				free_page((unsigned long)tbuf);
+				return -EFAULT;
+			}
+		}
+		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
+				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+	}
+	free_page((unsigned long)tbuf);
+	if (i<0) {
+		printk(KERN_DEBUG "usbfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d\n", 
+		       dev->devnum, ctrl.bRequestType, ctrl.bRequest, ctrl.wLength, i);
+	}
+	return i;
+}
+
+static int proc_bulk(struct dev_state *ps, void *arg)
+{
+	struct usb_device *dev = ps->dev;
+	struct usbdevfs_bulktransfer bulk;
+	unsigned int tmo, len1, pipe;
+	int len2;
+	unsigned char *tbuf;
+	int i, ret;
+
+	if (copy_from_user(&bulk, (void *)arg, sizeof(bulk)))
+		return -EFAULT;
+	if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+		return ret;
+	if ((ret = checkintf(ps, ret)))
+		return ret;
+	if (bulk.ep & USB_DIR_IN)
+		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+	else
+		pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
+		return -EINVAL;
+	len1 = bulk.len;
+	if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
+		return -ENOMEM;
+	tmo = (bulk.timeout * HZ + 999) / 1000;
+	if (bulk.ep & 0x80) {
+		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+			kfree(tbuf);
+			return -EINVAL;
+		}
+		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		if (!i && len2) {
+			if (copy_to_user(bulk.data, tbuf, len2)) {
+				kfree(tbuf);
+				return -EFAULT;
+			}
+		}
+	} else {
+		if (len1) {
+			if (copy_from_user(tbuf, bulk.data, len1)) {
+				kfree(tbuf);
+				return -EFAULT;
+			}
+		}
+		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+	}
+	kfree(tbuf);
+	if (i < 0) {
+		printk(KERN_WARNING "usbfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n", 
+		       dev->devnum, bulk.ep, bulk.len, i);
+		return i;
+	}
+	return len2;
+}
+
+static int proc_resetep(struct dev_state *ps, void *arg)
+{
+	unsigned int ep;
+	int ret;
+
+	if (get_user(ep, (unsigned int *)arg))
+		return -EFAULT;
+	if ((ret = findintfep(ps->dev, ep)) < 0)
+		return ret;
+	if ((ret = checkintf(ps, ret)))
+		return ret;
+	usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
+	return 0;
+}
+
+static int proc_clearhalt(struct dev_state *ps, void *arg)
+{
+	unsigned int ep;
+	int pipe;
+	int ret;
+
+	if (get_user(ep, (unsigned int *)arg))
+		return -EFAULT;
+	if ((ret = findintfep(ps->dev, ep)) < 0)
+		return ret;
+	if ((ret = checkintf(ps, ret)))
+		return ret;
+	if (ep & USB_DIR_IN)
+                pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
+        else
+                pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
+
+	return usb_clear_halt(ps->dev, pipe);
+}
+		
+
+static int proc_getdriver(struct dev_state *ps, void *arg)
+{
+	struct usbdevfs_getdriver gd;
+	struct usb_interface *interface;
+	int ret;
+
+	if (copy_from_user(&gd, arg, sizeof(gd)))
+		return -EFAULT;
+	if ((ret = findintfif(ps->dev, gd.interface)) < 0)
+		return ret;
+	interface = usb_ifnum_to_if(ps->dev, gd.interface);
+	if (!interface)
+		return -EINVAL;
+	if (!interface->driver)
+		return -ENODATA;
+	strcpy(gd.driver, interface->driver->name);
+	if (copy_to_user(arg, &gd, sizeof(gd)))
+		return -EFAULT;
+	return 0;
+}
+
+static int proc_connectinfo(struct dev_state *ps, void *arg)
+{
+	struct usbdevfs_connectinfo ci;
+
+	ci.devnum = ps->dev->devnum;
+	ci.slow = ps->dev->speed == USB_SPEED_LOW;
+	if (copy_to_user(arg, &ci, sizeof(ci)))
+		return -EFAULT;
+	return 0;
+}
+
+static int proc_resetdevice(struct dev_state *ps)
+{
+	int i, ret;
+
+	ret = usb_reset_device(ps->dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ps->dev->actconfig->bNumInterfaces; i++) {
+		struct usb_interface *intf = &ps->dev->actconfig->interface[i];
+
+		/* Don't simulate interfaces we've claimed */
+		if (test_bit(i, &ps->ifclaimed))
+			continue;
+
+		if (intf->driver) {
+			const struct usb_device_id *id;
+			down(&intf->driver->serialize);
+			intf->driver->disconnect(ps->dev, intf->private_data);
+			id = usb_match_id(ps->dev,intf,intf->driver->id_table);
+			intf->driver->probe(ps->dev, i, id);
+			up(&intf->driver->serialize);
+		}
+	}
+
+	return 0;
+}
+
+static int proc_setintf(struct dev_state *ps, void *arg)
+{
+	struct usbdevfs_setinterface setintf;
+	struct usb_interface *interface;
+	int ret;
+
+	if (copy_from_user(&setintf, arg, sizeof(setintf)))
+		return -EFAULT;
+	if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
+		return ret;
+	interface = usb_ifnum_to_if(ps->dev, setintf.interface);
+	if (!interface)
+		return -EINVAL;
+	if (interface->driver) {
+		if ((ret = checkintf(ps, ret)))
+			return ret;
+	}
+	if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting))
+		return -EINVAL;
+	return 0;
+}
+
+static int proc_setconfig(struct dev_state *ps, void *arg)
+{
+	unsigned int u;
+
+	if (get_user(u, (unsigned int *)arg))
+		return -EFAULT;
+	if (usb_set_configuration(ps->dev, u) < 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int proc_submiturb(struct dev_state *ps, void *arg)
+{
+	struct usbdevfs_urb uurb;
+	struct usbdevfs_iso_packet_desc *isopkt = NULL;
+	struct usb_endpoint_descriptor *ep_desc;
+	struct async *as;
+	struct usb_ctrlrequest *dr = NULL;
+	unsigned int u, totlen, isofrmlen;
+	int ret;
+
+	if (copy_from_user(&uurb, arg, sizeof(uurb)))
+		return -EFAULT;
+	if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD|USBDEVFS_URB_QUEUE_BULK|
+			   USB_NO_FSBR|USB_ZERO_PACKET))
+		return -EINVAL;
+	if (!uurb.buffer)
+		return -EINVAL;
+	if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
+		return -EINVAL;
+	if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+		if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
+			return ret;
+		if ((ret = checkintf(ps, ret)))
+			return ret;
+	}
+	switch(uurb.type) {
+	case USBDEVFS_URB_TYPE_CONTROL:
+		if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0) {
+			if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
+				return -ENOENT;
+			if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL)
+				return -EINVAL;
+		}
+		/* min 8 byte setup packet, max arbitrary */
+		if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
+			return -EINVAL;
+		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
+			return -ENOMEM;
+		if (copy_from_user(dr, (unsigned char*)uurb.buffer, 8)) {
+			kfree(dr);
+			return -EFAULT;
+		}
+		if (uurb.buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
+			kfree(dr);
+			return -EINVAL;
+		}
+		if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)))) {
+			kfree(dr);
+			return ret;
+		}
+		uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
+		uurb.number_of_packets = 0;
+		uurb.buffer_length = le16_to_cpup(&dr->wLength);
+		uurb.buffer += 8;
+		if (!access_ok((uurb.endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
+			kfree(dr);
+			return -EFAULT;
+		}
+		break;
+
+	case USBDEVFS_URB_TYPE_BULK:
+		uurb.number_of_packets = 0;
+		if (uurb.buffer_length > 16384)
+			return -EINVAL;
+		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+			return -EFAULT;
+		break;
+
+	case USBDEVFS_URB_TYPE_ISO:
+		/* arbitrary limit */
+		if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
+			return -EINVAL;
+		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
+		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+			return -ENOMEM;
+		if (copy_from_user(isopkt, &((struct usbdevfs_urb *)arg)->iso_frame_desc, isofrmlen)) {
+			kfree(isopkt);
+			return -EFAULT;
+		}
+		for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+			if (isopkt[u].length > 1023) {
+				kfree(isopkt);
+				return -EINVAL;
+			}
+			totlen += isopkt[u].length;
+		}
+		if (totlen > 32768) {
+			kfree(isopkt);
+			return -EINVAL;
+		}
+		uurb.buffer_length = totlen;
+		break;
+
+	case USBDEVFS_URB_TYPE_INTERRUPT:
+		uurb.number_of_packets = 0;
+		if (uurb.buffer_length > 16384)
+			return -EINVAL;
+		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+			return -EFAULT;   
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	if (!(as = alloc_async(uurb.number_of_packets))) {
+		if (isopkt)
+			kfree(isopkt);
+		if (dr)
+			kfree(dr);
+		return -ENOMEM;
+	}
+	if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
+		if (isopkt)
+			kfree(isopkt);
+		if (dr)
+			kfree(dr);
+		free_async(as);
+		return -ENOMEM;
+	}
+        as->urb->next = NULL;
+        as->urb->dev = ps->dev;
+        as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
+        as->urb->transfer_flags = uurb.flags;
+	as->urb->transfer_buffer_length = uurb.buffer_length;
+	as->urb->setup_packet = (unsigned char*)dr;
+	as->urb->start_frame = uurb.start_frame;
+	as->urb->number_of_packets = uurb.number_of_packets;
+        as->urb->context = as;
+        as->urb->complete = async_completed;
+	for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+		as->urb->iso_frame_desc[u].offset = totlen;
+		as->urb->iso_frame_desc[u].length = isopkt[u].length;
+		totlen += isopkt[u].length;
+	}
+	if (isopkt)
+		kfree(isopkt);
+	as->ps = ps;
+        as->userurb = arg;
+	if (uurb.endpoint & USB_DIR_IN)
+		as->userbuffer = uurb.buffer;
+	else
+		as->userbuffer = NULL;
+	as->signr = uurb.signr;
+	as->task = current;
+	if (!(uurb.endpoint & USB_DIR_IN)) {
+		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
+			free_async(as);
+			return -EFAULT;
+		}
+	}
+        async_newpending(as);
+        if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
+		printk(KERN_DEBUG "usbfs: usb_submit_urb returned %d\n", ret);
+                async_removepending(as);
+                free_async(as);
+                return ret;
+        }
+        return 0;
+}
+
+static int proc_unlinkurb(struct dev_state *ps, void *arg)
+{
+	struct async *as;
+
+	as = async_getpending(ps, arg);
+	if (!as)
+		return -EINVAL;
+	usb_unlink_urb(as->urb);
+	return 0;
+}
+
+static int processcompl(struct async *as)
+{
+	struct urb *urb = as->urb;
+	unsigned int i;
+
+	if (as->userbuffer)
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+			return -EFAULT;
+	if (put_user(urb->status,
+		     &((struct usbdevfs_urb *)as->userurb)->status))
+		return -EFAULT;
+	if (put_user(urb->actual_length,
+		     &((struct usbdevfs_urb *)as->userurb)->actual_length))
+		return -EFAULT;
+	if (put_user(urb->error_count,
+		     &((struct usbdevfs_urb *)as->userurb)->error_count))
+		return -EFAULT;
+
+	if (!(usb_pipeisoc(urb->pipe)))
+		return 0;
+	for (i = 0; i < urb->number_of_packets; i++) {
+		if (put_user(urb->iso_frame_desc[i].actual_length, 
+			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))
+			return -EFAULT;
+		if (put_user(urb->iso_frame_desc[i].status, 
+			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int proc_reapurb(struct dev_state *ps, void *arg)
+{
+        DECLARE_WAITQUEUE(wait, current);
+	struct async *as = NULL;
+	void *addr;
+	int ret;
+
+	add_wait_queue(&ps->wait, &wait);
+	while (ps->dev) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		if ((as = async_getcompleted(ps)))
+			break;
+		if (signal_pending(current))
+			break;
+		up_read(&ps->devsem);
+		schedule();
+		down_read(&ps->devsem);
+	}
+	remove_wait_queue(&ps->wait, &wait);
+	set_current_state(TASK_RUNNING);
+	if (as) {
+		ret = processcompl(as);
+		addr = as->userurb;
+		free_async(as);
+		if (ret)
+			return ret;
+		if (put_user(addr, (void **)arg))
+			return -EFAULT;
+		return 0;
+	}
+	if (signal_pending(current))
+		return -EINTR;
+	return -EIO;
+}
+
+static int proc_reapurbnonblock(struct dev_state *ps, void *arg)
+{
+	struct async *as;
+	void *addr;
+	int ret;
+
+	if (!(as = async_getcompleted(ps)))
+		return -EAGAIN;
+	ret = processcompl(as);
+	addr = as->userurb;
+	free_async(as);
+	if (ret)
+		return ret;
+	if (put_user(addr, (void **)arg))
+		return -EFAULT;
+	return 0;
+}
+
+static int proc_disconnectsignal(struct dev_state *ps, void *arg)
+{
+	struct usbdevfs_disconnectsignal ds;
+
+	if (copy_from_user(&ds, arg, sizeof(ds)))
+		return -EFAULT;
+	if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))
+		return -EINVAL;
+	ps->discsignr = ds.signr;
+	ps->disccontext = ds.context;
+	return 0;
+}
+
+static int proc_claiminterface(struct dev_state *ps, void *arg)
+{
+	unsigned int intf;
+	int ret;
+
+	if (get_user(intf, (unsigned int *)arg))
+		return -EFAULT;
+	if ((ret = findintfif(ps->dev, intf)) < 0)
+		return ret;
+	return claimintf(ps, ret);
+}
+
+static int proc_releaseinterface(struct dev_state *ps, void *arg)
+{
+	unsigned int intf;
+	int ret;
+
+	if (get_user(intf, (unsigned int *)arg))
+		return -EFAULT;
+	if ((ret = findintfif(ps->dev, intf)) < 0)
+		return ret;
+	return releaseintf(ps, intf);
+}
+
+static int proc_ioctl (struct dev_state *ps, void *arg)
+{
+	struct usbdevfs_ioctl	ctrl;
+	int			size;
+	void			*buf = 0;
+	int			retval = 0;
+       struct usb_interface    *ifp = 0;
+       struct usb_driver       *driver = 0;
+
+	/* get input parameters and alloc buffer */
+	if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl)))
+		return -EFAULT;
+	if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
+		if ((buf = kmalloc (size, GFP_KERNEL)) == 0)
+			return -ENOMEM;
+		if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
+			if (copy_from_user (buf, ctrl.data, size)) {
+				kfree (buf);
+				return -EFAULT;
+			}
+		} else {
+			memset (buf, 0, size);
+		}
+	}
+
+       if (!ps->dev)
+               retval = -ENODEV;
+       else if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
+               retval = -EINVAL;
+       else switch (ctrl.ioctl_code) {
+
+       /* disconnect kernel driver from interface, leaving it unbound.  */
+       case USBDEVFS_DISCONNECT:
+               driver = ifp->driver;
+               if (driver) {
+                       down (&driver->serialize);
+                       dbg ("disconnect '%s' from dev %d interface %d",
+                               driver->name, ps->dev->devnum, ctrl.ifno);
+                       driver->disconnect (ps->dev, ifp->private_data);
+                       usb_driver_release_interface (driver, ifp);
+                       up (&driver->serialize);
+               } else
+			retval = -EINVAL;
+               break;
+
+       /* let kernel drivers try to (re)bind to the interface */
+       case USBDEVFS_CONNECT:
+               usb_find_interface_driver_for_ifnum (ps->dev, ctrl.ifno);
+               break;
+
+       /* talk directly to the interface's driver */
+       default:
+               driver = ifp->driver;
+               if (driver == 0 || driver->ioctl == 0)
+                       retval = -ENOSYS;
+		else {
+			if (ifp->driver->owner)
+				__MOD_INC_USE_COUNT(ifp->driver->owner);
+			/* ifno might usefully be passed ... */
+                       retval = driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
+			/* size = min_t(int, size, retval)? */
+			if (ifp->driver->owner)
+				__MOD_DEC_USE_COUNT(ifp->driver->owner);
+		}
+	}
+
+	/* cleanup and return */
+	if (retval >= 0
+			&& (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
+			&& size > 0
+			&& copy_to_user (ctrl.data, buf, size) != 0)
+		retval = -EFAULT;
+	if (buf != 0)
+		kfree (buf);
+	return retval;
+}
+
+static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct dev_state *ps = (struct dev_state *)file->private_data;
+	int ret = -ENOIOCTLCMD;
+
+	if (!(file->f_mode & FMODE_WRITE))
+		return -EPERM;
+	down_read(&ps->devsem);
+	if (!ps->dev) {
+		up_read(&ps->devsem);
+		return -ENODEV;
+	}
+	switch (cmd) {
+	case USBDEVFS_CONTROL:
+		ret = proc_control(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_BULK:
+		ret = proc_bulk(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_RESETEP:
+		ret = proc_resetep(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_RESET:
+		ret = proc_resetdevice(ps);
+		break;
+	
+	case USBDEVFS_CLEAR_HALT:
+		ret = proc_clearhalt(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_GETDRIVER:
+		ret = proc_getdriver(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_CONNECTINFO:
+		ret = proc_connectinfo(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_SETINTERFACE:
+		ret = proc_setintf(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_SETCONFIGURATION:
+		ret = proc_setconfig(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_SUBMITURB:
+		ret = proc_submiturb(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_DISCARDURB:
+		ret = proc_unlinkurb(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_REAPURB:
+		ret = proc_reapurb(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_REAPURBNDELAY:
+		ret = proc_reapurbnonblock(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_DISCSIGNAL:
+		ret = proc_disconnectsignal(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_CLAIMINTERFACE:
+		ret = proc_claiminterface(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_RELEASEINTERFACE:
+		ret = proc_releaseinterface(ps, (void *)arg);
+		break;
+
+	case USBDEVFS_IOCTL:
+		ret = proc_ioctl(ps, (void *) arg);
+		break;
+	}
+	up_read(&ps->devsem);
+	if (ret >= 0)
+		inode->i_atime = CURRENT_TIME;
+	return ret;
+}
+
+/* No kernel lock - fine */
+static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct dev_state *ps = (struct dev_state *)file->private_data;
+        unsigned int mask = 0;
+
+	poll_wait(file, &ps->wait, wait);
+	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
+		mask |= POLLOUT | POLLWRNORM;
+	if (!ps->dev)
+		mask |= POLLERR | POLLHUP;
+	return mask;
+}
+
+struct file_operations usbdevfs_device_file_operations = {
+	llseek:		usbdev_lseek,
+	read:		usbdev_read,
+	poll:		usbdev_poll,
+	ioctl:		usbdev_ioctl,
+	open:		usbdev_open,
+	release:	usbdev_release,
+};
diff -Nru a/drivers/usb/core/drivers.c b/drivers/usb/core/drivers.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/drivers.c	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,123 @@
+/*
+ * drivers.c
+ * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999, 2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * $id$
+ *
+ * This program is free software; you can redistribute it and/or 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
+ *
+ *************************************************************
+ *
+ * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Converted the whole proc stuff to real
+ *   read methods. Now not the whole device list needs to fit
+ *   into one page, only the device list for one bus.
+ *   Added a poll method to /proc/bus/usb/devices, to wake
+ *   up an eventual usbd
+ * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Turned into its own filesystem
+ *
+ * $Id: drivers.c,v 1.3 2000/01/11 13:58:24 tom Exp $
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+/*****************************************************************/
+
+/*
+ * Dump usb_driver_list.
+ *
+ * We now walk the list of registered USB drivers.
+ */
+static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+	struct list_head *tmp = usb_driver_list.next;
+	char *page, *start, *end;
+	ssize_t ret = 0;
+	unsigned int pos, len;
+
+	if (*ppos < 0)
+		return -EINVAL;
+	if (nbytes <= 0)
+		return 0;
+	if (!access_ok(VERIFY_WRITE, buf, nbytes))
+		return -EFAULT;
+        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+                return -ENOMEM;
+	start = page;
+	end = page + (PAGE_SIZE - 100);
+	pos = *ppos;
+	for (; tmp != &usb_driver_list; tmp = tmp->next) {
+		struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
+		int minor = driver->fops ? driver->minor : -1;
+		if (minor == -1)
+			start += sprintf (start, "         %s\n", driver->name);
+		else
+			start += sprintf (start, "%3d-%3d: %s\n", minor, minor + 15, driver->name);
+		if (start > end) {
+			start += sprintf(start, "(truncated)\n");
+			break;
+		}
+	}
+	if (start == page)
+		start += sprintf(start, "(none)\n");
+	len = start - page;
+	if (len > pos) {
+		len -= pos;
+		if (len > nbytes)
+			len = nbytes;
+		ret = len;
+		if (copy_to_user(buf, page + pos, len))
+			ret = -EFAULT;
+		else
+			*ppos += len;
+	}
+	free_page((unsigned long)page);
+	return ret;
+}
+
+static loff_t usb_driver_lseek(struct file * file, loff_t offset, int orig)
+{
+	loff_t ret;
+
+	lock_kernel();
+	switch (orig) {
+	case 0:
+		file->f_pos = offset;
+		ret = file->f_pos;
+		break;
+	case 1:
+		file->f_pos += offset;
+		ret = file->f_pos;
+		break;
+	case 2:
+	default:
+		ret = -EINVAL;
+	}
+	unlock_kernel();
+	return ret;
+}
+
+struct file_operations usbdevfs_drivers_fops = {
+	llseek:		usb_driver_lseek,
+	read:		usb_driver_read,
+};
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/hcd.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,1813 @@
+/*
+ * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999-2001
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
+ * (C) Copyright Deti Fliegl 1999
+ * (C) Copyright Randy Dunlap 2000
+ * (C) Copyright David Brownell 2000-2002
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/uts.h>			/* for UTS_SYSNAME */
+
+
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/usb.h>
+#include "hcd.h"
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+
+// #define USB_BANDWIDTH_MESSAGES
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * USB Host Controller Driver framework
+ *
+ * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing
+ * HCD-specific behaviors/bugs.
+ *
+ * This does error checks, tracks devices and urbs, and delegates to a
+ * "hc_driver" only for code (and data) that really needs to know about
+ * hardware differences.  That includes root hub registers, i/o queues,
+ * and so on ... but as little else as possible.
+ *
+ * Shared code includes most of the "root hub" code (these are emulated,
+ * though each HC's hardware works differently) and PCI glue, plus request
+ * tracking overhead.  The HCD code should only block on spinlocks or on
+ * hardware handshaking; blocking on software events (such as other kernel
+ * threads releasing resources, or completing actions) is all generic.
+ *
+ * Happens the USB 2.0 spec says this would be invisible inside the "USBD",
+ * and includes mostly a "HCDI" (HCD Interface) along with some APIs used
+ * only by the hub driver ... and that neither should be seen or used by
+ * usb client device drivers.
+ *
+ * Contributors of ideas or unattributed patches include: David Brownell,
+ * Roman Weissgaerber, Rory Bolt, Greg Kroah-Hartman, ...
+ *
+ * HISTORY:
+ * 2002-02-21	Pull in most of the usb_bus support from usb.c; some
+ *		associated cleanup.  "usb_hcd" still != "usb_bus".
+ * 2001-12-12	Initial patch version for Linux 2.5.1 kernel.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* host controllers we manage */
+LIST_HEAD (usb_bus_list);
+
+/* used when allocating bus numbers */
+#define USB_MAXBUS		64
+struct usb_busmap {
+	unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];
+};
+static struct usb_busmap busmap;
+
+/* used when updating list of hcds */
+DECLARE_MUTEX (usb_bus_list_lock);	/* exported only for usbfs */
+
+/* used when updating hcd data */
+static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
+
+static struct usb_operations hcd_operations;
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Sharable chunks of root hub code.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+#define KERNEL_REL	((LINUX_VERSION_CODE >> 16) & 0x0ff)
+#define KERNEL_VER	((LINUX_VERSION_CODE >> 8) & 0x0ff)
+
+/* usb 2.0 root hub device descriptor */
+static const u8 usb2_rh_dev_descriptor [18] = {
+	0x12,       /*  __u8  bLength; */
+	0x01,       /*  __u8  bDescriptorType; Device */
+	0x00, 0x02, /*  __u16 bcdUSB; v2.0 */
+
+	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,	    /*  __u8  bDeviceSubClass; */
+	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
+	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+
+	0x00, 0x00, /*  __u16 idVendor; */
+ 	0x00, 0x00, /*  __u16 idProduct; */
+	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
+
+	0x03,       /*  __u8  iManufacturer; */
+	0x02,       /*  __u8  iProduct; */
+	0x01,       /*  __u8  iSerialNumber; */
+	0x01        /*  __u8  bNumConfigurations; */
+};
+
+/* no usb 2.0 root hub "device qualifier" descriptor: one speed only */
+
+/* usb 1.1 root hub device descriptor */
+static const u8 usb11_rh_dev_descriptor [18] = {
+	0x12,       /*  __u8  bLength; */
+	0x01,       /*  __u8  bDescriptorType; Device */
+	0x10, 0x01, /*  __u16 bcdUSB; v1.1 */
+
+	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,	    /*  __u8  bDeviceSubClass; */
+	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
+	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+
+	0x00, 0x00, /*  __u16 idVendor; */
+ 	0x00, 0x00, /*  __u16 idProduct; */
+	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
+
+	0x03,       /*  __u8  iManufacturer; */
+	0x02,       /*  __u8  iProduct; */
+	0x01,       /*  __u8  iSerialNumber; */
+	0x01        /*  __u8  bNumConfigurations; */
+};
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Configuration descriptors for our root hubs */
+
+static const u8 fs_rh_config_descriptor [] = {
+
+	/* one configuration */
+	0x09,       /*  __u8  bLength; */
+	0x02,       /*  __u8  bDescriptorType; Configuration */
+	0x19, 0x00, /*  __u16 wTotalLength; */
+	0x01,       /*  __u8  bNumInterfaces; (1) */
+	0x01,       /*  __u8  bConfigurationValue; */
+	0x00,       /*  __u8  iConfiguration; */
+	0x40,       /*  __u8  bmAttributes; 
+				 Bit 7: Bus-powered,
+				     6: Self-powered,
+				     5 Remote-wakwup,
+				     4..0: resvd */
+	0x00,       /*  __u8  MaxPower; */
+      
+	/* USB 1.1:
+	 * USB 2.0, single TT organization (mandatory):
+	 *	one interface, protocol 0
+	 *
+	 * USB 2.0, multiple TT organization (optional):
+	 *	two interfaces, protocols 1 (like single TT)
+	 *	and 2 (multiple TT mode) ... config is
+	 *	sometimes settable
+	 *	NOT IMPLEMENTED
+	 */
+
+	/* one interface */
+	0x09,       /*  __u8  if_bLength; */
+	0x04,       /*  __u8  if_bDescriptorType; Interface */
+	0x00,       /*  __u8  if_bInterfaceNumber; */
+	0x00,       /*  __u8  if_bAlternateSetting; */
+	0x01,       /*  __u8  if_bNumEndpoints; */
+	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,       /*  __u8  if_bInterfaceSubClass; */
+	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
+	0x00,       /*  __u8  if_iInterface; */
+     
+	/* one endpoint (status change endpoint) */
+	0x07,       /*  __u8  ep_bLength; */
+	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+ 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+ 	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+	0xff        /*  __u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+};
+
+static const u8 hs_rh_config_descriptor [] = {
+
+	/* one configuration */
+	0x09,       /*  __u8  bLength; */
+	0x02,       /*  __u8  bDescriptorType; Configuration */
+	0x19, 0x00, /*  __u16 wTotalLength; */
+	0x01,       /*  __u8  bNumInterfaces; (1) */
+	0x01,       /*  __u8  bConfigurationValue; */
+	0x00,       /*  __u8  iConfiguration; */
+	0x40,       /*  __u8  bmAttributes; 
+				 Bit 7: Bus-powered,
+				     6: Self-powered,
+				     5 Remote-wakwup,
+				     4..0: resvd */
+	0x00,       /*  __u8  MaxPower; */
+      
+	/* USB 1.1:
+	 * USB 2.0, single TT organization (mandatory):
+	 *	one interface, protocol 0
+	 *
+	 * USB 2.0, multiple TT organization (optional):
+	 *	two interfaces, protocols 1 (like single TT)
+	 *	and 2 (multiple TT mode) ... config is
+	 *	sometimes settable
+	 *	NOT IMPLEMENTED
+	 */
+
+	/* one interface */
+	0x09,       /*  __u8  if_bLength; */
+	0x04,       /*  __u8  if_bDescriptorType; Interface */
+	0x00,       /*  __u8  if_bInterfaceNumber; */
+	0x00,       /*  __u8  if_bAlternateSetting; */
+	0x01,       /*  __u8  if_bNumEndpoints; */
+	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,       /*  __u8  if_bInterfaceSubClass; */
+	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
+	0x00,       /*  __u8  if_iInterface; */
+     
+	/* one endpoint (status change endpoint) */
+	0x07,       /*  __u8  ep_bLength; */
+	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+ 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+ 	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+	0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * helper routine for returning string descriptors in UTF-16LE
+ * input can actually be ISO-8859-1; ASCII is its 7-bit subset
+ */
+static int ascii2utf (char *s, u8 *utf, int utfmax)
+{
+	int retval;
+
+	for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
+		*utf++ = *s++;
+		*utf++ = 0;
+	}
+	return retval;
+}
+
+/*
+ * rh_string - provides manufacturer, product and serial strings for root hub
+ * @id: the string ID number (1: serial number, 2: product, 3: vendor)
+ * @pci_desc: PCI device descriptor for the relevant HC
+ * @type: string describing our driver 
+ * @data: return packet in UTF-16 LE
+ * @len: length of the return packet
+ *
+ * Produces either a manufacturer, product or serial number string for the
+ * virtual root hub device.
+ */
+static int rh_string (
+	int		id,
+	struct usb_hcd	*hcd,
+	u8		*data,
+	int		len
+) {
+	char buf [100];
+
+	// language ids
+	if (id == 0) {
+		*data++ = 4; *data++ = 3;	/* 4 bytes string data */
+		*data++ = 0; *data++ = 0;	/* some language id */
+		return 4;
+
+	// serial number
+	} else if (id == 1) {
+		strcpy (buf, hcd->bus_name);
+
+	// product description
+	} else if (id == 2) {
+                strcpy (buf, hcd->product_desc);
+
+ 	// id 3 == vendor description
+	} else if (id == 3) {
+                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
+			hcd->description);
+
+	// unsupported IDs --> "protocol stall"
+	} else
+	    return 0;
+
+	data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
+	data [1] = 3;	/* type == string */
+	return data [0];
+}
+
+
+/* Root hub control transfers execute synchronously */
+static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
+{
+	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+ 	u16		typeReq, wValue, wIndex, wLength;
+	const u8	*bufp = 0;
+	u8		*ubuf = urb->transfer_buffer;
+	int		len = 0;
+
+	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
+	wValue   = le16_to_cpu (cmd->wValue);
+	wIndex   = le16_to_cpu (cmd->wIndex);
+	wLength  = le16_to_cpu (cmd->wLength);
+
+	if (wLength > urb->transfer_buffer_length)
+		goto error;
+
+	/* set up for success */
+	urb->status = 0;
+	urb->actual_length = wLength;
+	switch (typeReq) {
+
+	/* DEVICE REQUESTS */
+
+	case DeviceRequest | USB_REQ_GET_STATUS:
+		// DEVICE_REMOTE_WAKEUP
+		ubuf [0] = 1; // selfpowered
+		ubuf [1] = 0;
+			/* FALLTHROUGH */
+	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+	case DeviceOutRequest | USB_REQ_SET_FEATURE:
+		dbg ("no device features yet yet");
+		break;
+	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+		ubuf [0] = 1;
+			/* FALLTHROUGH */
+	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+		break;
+	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+		switch (wValue & 0xff00) {
+		case USB_DT_DEVICE << 8:
+			if (hcd->driver->flags & HCD_USB2)
+				bufp = usb2_rh_dev_descriptor;
+			else if (hcd->driver->flags & HCD_USB11)
+				bufp = usb11_rh_dev_descriptor;
+			else
+				goto error;
+			len = 18;
+			break;
+		case USB_DT_CONFIG << 8:
+			if (hcd->driver->flags & HCD_USB2) {
+				bufp = hs_rh_config_descriptor;
+				len = sizeof hs_rh_config_descriptor;
+			} else {
+				bufp = fs_rh_config_descriptor;
+				len = sizeof fs_rh_config_descriptor;
+			}
+			break;
+		case USB_DT_STRING << 8:
+			urb->actual_length = rh_string (
+				wValue & 0xff, hcd,
+				ubuf, wLength);
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case DeviceRequest | USB_REQ_GET_INTERFACE:
+		ubuf [0] = 0;
+			/* FALLTHROUGH */
+	case DeviceOutRequest | USB_REQ_SET_INTERFACE:
+		break;
+	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+		// wValue == urb->dev->devaddr
+		dbg ("%s root hub device address %d",
+			hcd->bus_name, wValue);
+		break;
+
+	/* INTERFACE REQUESTS (no defined feature/status flags) */
+
+	/* ENDPOINT REQUESTS */
+
+	case EndpointRequest | USB_REQ_GET_STATUS:
+		// ENDPOINT_HALT flag
+		ubuf [0] = 0;
+		ubuf [1] = 0;
+			/* FALLTHROUGH */
+	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+	case EndpointOutRequest | USB_REQ_SET_FEATURE:
+		dbg ("no endpoint features yet");
+		break;
+
+	/* CLASS REQUESTS (and errors) */
+
+	default:
+		/* non-generic request */
+		urb->status = hcd->driver->hub_control (hcd,
+			typeReq, wValue, wIndex,
+			ubuf, wLength);
+		break;
+error:
+		/* "protocol stall" on error */
+		urb->status = -EPIPE;
+		dbg ("unsupported hub control message (maxchild %d)",
+				urb->dev->maxchild);
+	}
+	if (urb->status) {
+		urb->actual_length = 0;
+		dbg ("CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d",
+			typeReq, wValue, wIndex, wLength, urb->status);
+	}
+	if (bufp) {
+		if (urb->transfer_buffer_length < len)
+			len = urb->transfer_buffer_length;
+		urb->actual_length = len;
+		// always USB_DIR_IN, toward host
+		memcpy (ubuf, bufp, len);
+	}
+
+	/* any errors get returned through the urb completion */
+	usb_hcd_giveback_urb (hcd, urb);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Root Hub interrupt transfers are synthesized with a timer.
+ * Completions are called in_interrupt() but not in_irq().
+ */
+
+static void rh_report_status (unsigned long ptr);
+
+static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) 
+{
+	int	len = 1 + (urb->dev->maxchild / 8);
+
+	/* rh_timer protected by hcd_data_lock */
+	if (timer_pending (&hcd->rh_timer)
+			|| urb->status != -EINPROGRESS
+			|| !HCD_IS_RUNNING (hcd->state)
+			|| urb->transfer_buffer_length < len) {
+		dbg ("not queuing status urb, stat %d", urb->status);
+		return -EINVAL;
+	}
+
+	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
+	init_timer (&hcd->rh_timer);
+	hcd->rh_timer.function = rh_report_status;
+	hcd->rh_timer.data = (unsigned long) urb;
+	/* USB 2.0 spec says 256msec; this is close enough */
+	hcd->rh_timer.expires = jiffies + HZ/4;
+	add_timer (&hcd->rh_timer);
+	return 0;
+}
+
+/* timer callback */
+
+static void rh_report_status (unsigned long ptr)
+{
+	struct urb	*urb;
+	struct usb_hcd	*hcd;
+	int		length;
+	unsigned long	flags;
+
+	urb = (struct urb *) ptr;
+	spin_lock_irqsave (&urb->lock, flags);
+	if (!urb->dev) {
+		spin_unlock_irqrestore (&urb->lock, flags);
+		return;
+	}
+
+	hcd = urb->dev->bus->hcpriv;
+	if (urb->status == -EINPROGRESS) {
+		if (HCD_IS_RUNNING (hcd->state)) {
+			length = hcd->driver->hub_status_data (hcd,
+					urb->transfer_buffer);
+			spin_unlock_irqrestore (&urb->lock, flags);
+			if (length > 0) {
+				urb->actual_length = length;
+				urb->status = 0;
+				urb->complete (urb);
+			}
+			spin_lock_irqsave (&hcd_data_lock, flags);
+			urb->status = -EINPROGRESS;
+			if (HCD_IS_RUNNING (hcd->state)
+					&& rh_status_urb (hcd, urb) != 0) {
+				/* another driver snuck in? */
+				dbg ("%s, can't resubmit roothub status urb?",
+					hcd->bus_name);
+				spin_unlock_irqrestore (&hcd_data_lock, flags);
+				BUG ();
+			}
+			spin_unlock_irqrestore (&hcd_data_lock, flags);
+		} else
+			spin_unlock_irqrestore (&urb->lock, flags);
+	} else {
+		/* this urb's been unlinked */
+		urb->hcpriv = 0;
+		spin_unlock_irqrestore (&urb->lock, flags);
+
+		usb_hcd_giveback_urb (hcd, urb);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
+{
+	if (usb_pipeint (urb->pipe)) {
+		int		retval;
+		unsigned long	flags;
+
+		spin_lock_irqsave (&hcd_data_lock, flags);
+		retval = rh_status_urb (hcd, urb);
+		spin_unlock_irqrestore (&hcd_data_lock, flags);
+		return retval;
+	}
+	if (usb_pipecontrol (urb->pipe))
+		return rh_call_control (hcd, urb);
+	else
+		return -EINVAL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	del_timer_sync (&hcd->rh_timer);
+	hcd->rh_timer.data = 0;
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+	/* we rely on RH callback code not unlinking its URB! */
+	usb_hcd_giveback_urb (hcd, urb);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* exported only within usbcore */
+void usb_bus_get (struct usb_bus *bus)
+{
+	atomic_inc (&bus->refcnt);
+}
+
+/* exported only within usbcore */
+void usb_bus_put (struct usb_bus *bus)
+{
+	if (atomic_dec_and_test (&bus->refcnt))
+		kfree (bus);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* shared initialization code */
+static void usb_init_bus (struct usb_bus *bus)
+{
+	memset (&bus->devmap, 0, sizeof(struct usb_devmap));
+
+#ifdef DEVNUM_ROUND_ROBIN
+	bus->devnum_next = 1;
+#endif /* DEVNUM_ROUND_ROBIN */
+
+	bus->root_hub = NULL;
+	bus->hcpriv = NULL;
+	bus->busnum = -1;
+	bus->bandwidth_allocated = 0;
+	bus->bandwidth_int_reqs  = 0;
+	bus->bandwidth_isoc_reqs = 0;
+
+	INIT_LIST_HEAD (&bus->bus_list);
+
+	atomic_set (&bus->refcnt, 1);
+}
+
+/**
+ * usb_alloc_bus - creates a new USB host controller structure
+ * @op: pointer to a struct usb_operations that this bus structure should use
+ * Context: !in_interrupt()
+ *
+ * Creates a USB host controller bus structure with the specified 
+ * usb_operations and initializes all the necessary internal objects.
+ *
+ * If no memory is available, NULL is returned.
+ *
+ * The caller should call usb_free_bus() when it is finished with the structure.
+ */
+struct usb_bus *usb_alloc_bus (struct usb_operations *op)
+{
+	struct usb_bus *bus;
+
+	bus = kmalloc (sizeof *bus, GFP_KERNEL);
+	if (!bus)
+		return NULL;
+	usb_init_bus (bus);
+	bus->op = op;
+	return bus;
+}
+EXPORT_SYMBOL (usb_alloc_bus);
+
+/**
+ * usb_free_bus - frees the memory used by a bus structure
+ * @bus: pointer to the bus to free
+ *
+ * To be invoked by a HCD, only as the last step of decoupling from
+ * hardware.  It is an error to call this if the reference count is
+ * anything but one.  That would indicate that some system component
+ * did not correctly shut down, and thought the hardware was still
+ * accessible.
+ */
+void usb_free_bus (struct usb_bus *bus)
+{
+	if (!bus)
+		return;
+	if (atomic_read (&bus->refcnt) != 1)
+		err ("usb_free_bus #%d, count != 1", bus->busnum);
+	usb_bus_put (bus);
+}
+EXPORT_SYMBOL (usb_free_bus);
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_register_bus - registers the USB host controller with the usb core
+ * @bus: pointer to the bus to register
+ * Context: !in_interrupt()
+ *
+ * Assigns a bus number, and links the controller into usbcore data
+ * structures so that it can be seen by scanning the bus list.
+ */
+void usb_register_bus(struct usb_bus *bus)
+{
+	int busnum;
+
+	down (&usb_bus_list_lock);
+	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
+	if (busnum < USB_MAXBUS) {
+		set_bit (busnum, busmap.busmap);
+		bus->busnum = busnum;
+	} else
+		warn ("too many buses");
+
+	usb_bus_get (bus);
+
+	/* Add it to the list of buses */
+	list_add (&bus->bus_list, &usb_bus_list);
+	up (&usb_bus_list_lock);
+
+	usbfs_add_bus (bus);
+
+	info ("new USB bus registered, assigned bus number %d", bus->busnum);
+}
+EXPORT_SYMBOL (usb_register_bus);
+
+/**
+ * usb_deregister_bus - deregisters the USB host controller
+ * @bus: pointer to the bus to deregister
+ * Context: !in_interrupt()
+ *
+ * Recycles the bus number, and unlinks the controller from usbcore data
+ * structures so that it won't be seen by scanning the bus list.
+ */
+void usb_deregister_bus (struct usb_bus *bus)
+{
+	info ("USB bus %d deregistered", bus->busnum);
+
+	/*
+	 * NOTE: make sure that all the devices are removed by the
+	 * controller code, as well as having it call this when cleaning
+	 * itself up
+	 */
+	down (&usb_bus_list_lock);
+	list_del (&bus->bus_list);
+	up (&usb_bus_list_lock);
+
+	usbfs_remove_bus (bus);
+
+	clear_bit (bus->busnum, busmap.busmap);
+
+	usb_bus_put (bus);
+}
+EXPORT_SYMBOL (usb_deregister_bus);
+
+/**
+ * usb_register_root_hub - called by HCD to register its root hub 
+ * @usb_dev: the usb root hub device to be registered.
+ * @parent_dev: the parent device of this root hub.
+ *
+ * The USB host controller calls this function to register the root hub
+ * properly with the USB subsystem.  It sets up the device properly in
+ * the driverfs tree, and then calls usb_new_device() to register the
+ * usb device.
+ */
+int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
+{
+	int retval;
+
+	usb_dev->dev.parent = parent_dev;
+	strcpy (&usb_dev->dev.name[0], "usb_name");
+	strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
+	retval = usb_new_device (usb_dev);
+	if (retval)
+		put_device (&usb_dev->dev);
+	return retval;
+}
+EXPORT_SYMBOL (usb_register_root_hub);
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * usb_calc_bus_time:
+ * Returns approximate bus time in nanoseconds for a periodic transaction.
+ * See USB 2.0 spec section 5.11.3
+ */
+static long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount)
+{
+	unsigned long	tmp;
+
+	switch (speed) {
+	case USB_SPEED_LOW: 	/* INTR only */
+		if (is_input) {
+			tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;
+			return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
+		} else {
+			tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;
+			return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
+		}
+	case USB_SPEED_FULL:	/* ISOC or INTR */
+		if (isoc) {
+			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
+			return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
+		} else {
+			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
+			return (9107L + BW_HOST_DELAY + tmp);
+		}
+	case USB_SPEED_HIGH:	/* ISOC or INTR */
+		// FIXME merge from EHCI code; caller will need to handle
+		// each part of a split separately.
+		return 0;
+	default:
+		dbg ("bogus device speed!");
+		return -1;
+	}
+}
+
+/*
+ * usb_check_bandwidth():
+ *
+ * old_alloc is from host_controller->bandwidth_allocated in microseconds;
+ * bustime is from calc_bus_time(), but converted to microseconds.
+ *
+ * returns <bustime in us> if successful,
+ * or -ENOSPC if bandwidth request fails.
+ *
+ * FIXME:
+ * This initial implementation does not use Endpoint.bInterval
+ * in managing bandwidth allocation.
+ * It probably needs to be expanded to use Endpoint.bInterval.
+ * This can be done as a later enhancement (correction).
+ *
+ * This will also probably require some kind of
+ * frame allocation tracking...meaning, for example,
+ * that if multiple drivers request interrupts every 10 USB frames,
+ * they don't all have to be allocated at
+ * frame numbers N, N+10, N+20, etc.  Some of them could be at
+ * N+11, N+21, N+31, etc., and others at
+ * N+12, N+22, N+32, etc.
+ *
+ * Similarly for isochronous transfers...
+ *
+ * Individual HCDs can schedule more directly ... this logic
+ * is not correct for high speed transfers.
+ */
+int usb_check_bandwidth (struct usb_device *dev, struct urb *urb)
+{
+	unsigned int	pipe = urb->pipe;
+	long		bustime;
+	int		is_in = usb_pipein (pipe);
+	int		is_iso = usb_pipeisoc (pipe);
+	int		old_alloc = dev->bus->bandwidth_allocated;
+	int		new_alloc;
+
+
+	bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso,
+			usb_maxpacket (dev, pipe, !is_in)));
+	if (is_iso)
+		bustime /= urb->number_of_packets;
+
+	new_alloc = old_alloc + (int) bustime;
+	if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) {
+#ifdef	DEBUG
+		char	*mode = 
+#ifdef CONFIG_USB_BANDWIDTH
+			"";
+#else
+			"would have ";
+#endif
+		dbg ("usb_check_bandwidth %sFAILED: %d + %ld = %d usec",
+			mode, old_alloc, bustime, new_alloc);
+#endif
+#ifdef CONFIG_USB_BANDWIDTH
+		bustime = -ENOSPC;	/* report error */
+#endif
+	}
+
+	return bustime;
+}
+EXPORT_SYMBOL (usb_check_bandwidth);
+
+
+/**
+ * usb_claim_bandwidth - records bandwidth for a periodic transfer
+ * @dev: source/target of request
+ * @urb: request (urb->dev == dev)
+ * @bustime: bandwidth consumed, in (average) microseconds per frame
+ * @isoc: true iff the request is isochronous
+ *
+ * Bus bandwidth reservations are recorded purely for diagnostic purposes.
+ * HCDs are expected not to overcommit periodic bandwidth, and to record such
+ * reservations whenever endpoints are added to the periodic schedule.
+ *
+ * FIXME averaging per-frame is suboptimal.  Better to sum over the HCD's
+ * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable
+ * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how
+ * large its periodic schedule is.
+ */
+void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
+{
+	dev->bus->bandwidth_allocated += bustime;
+	if (isoc)
+		dev->bus->bandwidth_isoc_reqs++;
+	else
+		dev->bus->bandwidth_int_reqs++;
+	urb->bandwidth = bustime;
+
+#ifdef USB_BANDWIDTH_MESSAGES
+	dbg ("bandwidth alloc increased by %d (%s) to %d for %d requesters",
+		bustime,
+		isoc ? "ISOC" : "INTR",
+		dev->bus->bandwidth_allocated,
+		dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+#endif
+}
+EXPORT_SYMBOL (usb_claim_bandwidth);
+
+
+/**
+ * usb_release_bandwidth - reverses effect of usb_claim_bandwidth()
+ * @dev: source/target of request
+ * @urb: request (urb->dev == dev)
+ * @isoc: true iff the request is isochronous
+ *
+ * This records that previously allocated bandwidth has been released.
+ * Bandwidth is released when endpoints are removed from the host controller's
+ * periodic schedule.
+ */
+void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc)
+{
+	dev->bus->bandwidth_allocated -= urb->bandwidth;
+	if (isoc)
+		dev->bus->bandwidth_isoc_reqs--;
+	else
+		dev->bus->bandwidth_int_reqs--;
+
+#ifdef USB_BANDWIDTH_MESSAGES
+	dbg ("bandwidth alloc reduced by %d (%s) to %d for %d requesters",
+		urb->bandwidth,
+		isoc ? "ISOC" : "INTR",
+		dev->bus->bandwidth_allocated,
+		dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
+#endif
+	urb->bandwidth = 0;
+}
+EXPORT_SYMBOL (usb_release_bandwidth);
+
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PCI
+
+/* PCI-based HCs are normal, but custom bus glue should be ok */
+
+static void hcd_irq (int irq, void *__hcd, struct pt_regs *r);
+static void hc_died (struct usb_hcd *hcd);
+
+/*-------------------------------------------------------------------------*/
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/**
+ * usb_hcd_pci_probe - initialize PCI-based HCDs
+ * @dev: USB Host Controller being probed
+ * @id: pci hotplug id connecting controller to HCD framework
+ * Context: !in_interrupt()
+ *
+ * Allocates basic PCI resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct hc_driver	*driver;
+	unsigned long		resource, len;
+	void			*base;
+	u8			latency, limit;
+	struct usb_hcd		*hcd;
+	int			retval, region;
+	char			buf [8], *bufp = buf;
+
+	if (!id || !(driver = (struct hc_driver *) id->driver_data))
+		return -EINVAL;
+
+	if (pci_enable_device (dev) < 0)
+		return -ENODEV;
+	
+        if (!dev->irq) {
+        	err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
+			dev->slot_name);
+   	        return -ENODEV;
+        }
+	
+	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
+		region = 0;
+		resource = pci_resource_start (dev, 0);
+		len = pci_resource_len (dev, 0);
+		if (!request_mem_region (resource, len, driver->description)) {
+			dbg ("controller already in use");
+			return -EBUSY;
+		}
+		base = ioremap_nocache (resource, len);
+		if (base == NULL) {
+			dbg ("error mapping memory");
+			retval = -EFAULT;
+clean_1:
+			release_mem_region (resource, len);
+			err ("init %s fail, %d", dev->slot_name, retval);
+			return retval;
+		}
+
+	} else { 				// UHCI
+		resource = len = 0;
+		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
+			if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
+				continue;
+
+			resource = pci_resource_start (dev, region);
+			len = pci_resource_len (dev, region);
+			if (request_region (resource, len,
+					driver->description))
+				break;
+		}
+		if (region == PCI_ROM_RESOURCE) {
+			dbg ("no i/o regions available");
+			return -EBUSY;
+		}
+		base = (void *) resource;
+	}
+
+	// driver->start(), later on, will transfer device from
+	// control by SMM/BIOS to control by Linux (if needed)
+
+	pci_set_master (dev);
+	hcd = driver->hcd_alloc ();
+	if (hcd == NULL){
+		dbg ("hcd alloc fail");
+		retval = -ENOMEM;
+clean_2:
+		if (driver->flags & HCD_MEMORY) {
+			iounmap (base);
+			goto clean_1;
+		} else {
+			release_region (resource, len);
+			err ("init %s fail, %d", dev->slot_name, retval);
+			return retval;
+		}
+	}
+	pci_set_drvdata(dev, hcd);
+	hcd->driver = driver;
+	hcd->description = driver->description;
+	hcd->pdev = dev;
+	info ("%s @ %s, %s", hcd->description,  dev->slot_name, dev->name);
+
+	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+	if (latency) {
+		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
+		if (limit && limit < latency) {
+			dbg ("PCI latency reduced to max %d", limit);
+			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
+		}
+	}
+
+#ifndef __sparc__
+	sprintf (buf, "%d", dev->irq);
+#else
+	bufp = __irq_itoa(dev->irq);
+#endif
+	if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd)
+			!= 0) {
+		err ("request interrupt %s failed", bufp);
+		retval = -EBUSY;
+		driver->hcd_free (hcd);
+		goto clean_2;
+	}
+	hcd->irq = dev->irq;
+
+	hcd->regs = base;
+	hcd->region = region;
+	info ("irq %s, %s %p", bufp,
+		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
+		base);
+
+	usb_init_bus (&hcd->self);
+	hcd->self.op = &hcd_operations;
+	hcd->self.hcpriv = (void *) hcd;
+	hcd->bus = &hcd->self;
+	hcd->bus_name = dev->slot_name;
+	hcd->product_desc = dev->name;
+
+	INIT_LIST_HEAD (&hcd->dev_list);
+
+	usb_register_bus (&hcd->self);
+
+	if ((retval = driver->start (hcd)) < 0)
+		usb_hcd_pci_remove (dev);
+
+	return retval;
+} 
+EXPORT_SYMBOL (usb_hcd_pci_probe);
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_pci_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ * Store this function in the HCD's struct pci_driver as remove().
+ */
+void usb_hcd_pci_remove (struct pci_dev *dev)
+{
+	struct usb_hcd		*hcd;
+	struct usb_device	*hub;
+
+	hcd = pci_get_drvdata(dev);
+	if (!hcd)
+		return;
+	info ("remove: %s, state %x", hcd->bus_name, hcd->state);
+
+	if (in_interrupt ()) BUG ();
+
+	hub = hcd->bus->root_hub;
+	hcd->state = USB_STATE_QUIESCING;
+
+	dbg ("%s: roothub graceful disconnect", hcd->bus_name);
+	usb_disconnect (&hub);
+	// usb_disconnect (&hcd->bus->root_hub);
+
+	hcd->driver->stop (hcd);
+	hcd->state = USB_STATE_HALT;
+
+	free_irq (hcd->irq, hcd);
+	if (hcd->driver->flags & HCD_MEMORY) {
+		iounmap (hcd->regs);
+		release_mem_region (pci_resource_start (dev, 0),
+			pci_resource_len (dev, 0));
+	} else {
+		release_region (pci_resource_start (dev, hcd->region),
+			pci_resource_len (dev, hcd->region));
+	}
+
+	usb_deregister_bus (hcd->bus);
+	if (atomic_read (&hcd->self.refcnt) != 1)
+		err ("usb_hcd_pci_remove %s, count != 1", hcd->bus_name);
+	hcd->bus = NULL;
+
+	hcd->driver->hcd_free (hcd);
+}
+EXPORT_SYMBOL (usb_hcd_pci_remove);
+
+
+#ifdef	CONFIG_PM
+
+/*
+ * Some "sleep" power levels imply updating struct usb_driver
+ * to include a callback asking hcds to do their bit by checking
+ * if all the drivers can suspend.  Gets involved with remote wakeup.
+ *
+ * If there are pending urbs, then HCs will need to access memory,
+ * causing extra power drain.  New sleep()/wakeup() PM calls might
+ * be needed, beyond PCI suspend()/resume().  The root hub timer
+ * still be accessing memory though ...
+ *
+ * FIXME:  USB should have some power budgeting support working with
+ * all kinds of hubs.
+ *
+ * FIXME:  This assumes only D0->D3 suspend and D3->D0 resume.
+ * D1 and D2 states should do something, yes?
+ *
+ * FIXME:  Should provide generic enable_wake(), calling pci_enable_wake()
+ * for all supported states, so that USB remote wakeup can work for any
+ * devices that support it (and are connected via powered hubs).
+ *
+ * FIXME:  resume doesn't seem to work right any more...
+ */
+
+
+// 2.4 kernels have issued concurrent resumes (w/APM)
+// we defend against that error; PCI doesn't yet.
+
+/**
+ * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
+ * @dev: USB Host Controller being suspended
+ *
+ * Store this function in the HCD's struct pci_driver as suspend().
+ */
+int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
+{
+	struct usb_hcd		*hcd;
+	int			retval;
+
+	hcd = pci_get_drvdata(dev);
+	info ("suspend %s to state %d", hcd->bus_name, state);
+
+	pci_save_state (dev, hcd->pci_state);
+
+	// FIXME for all connected devices, leaf-to-root:
+	// driver->suspend()
+	// proposed "new 2.5 driver model" will automate that
+
+	/* driver may want to disable DMA etc */
+	retval = hcd->driver->suspend (hcd, state);
+	hcd->state = USB_STATE_SUSPENDED;
+
+ 	pci_set_power_state (dev, state);
+	return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_suspend);
+
+/**
+ * usb_hcd_pci_resume - power management resume of a PCI-based HCD
+ * @dev: USB Host Controller being resumed
+ *
+ * Store this function in the HCD's struct pci_driver as resume().
+ */
+int usb_hcd_pci_resume (struct pci_dev *dev)
+{
+	struct usb_hcd		*hcd;
+	int			retval;
+
+	hcd = pci_get_drvdata(dev);
+	info ("resume %s", hcd->bus_name);
+
+	/* guard against multiple resumes (APM bug?) */
+	atomic_inc (&hcd->resume_count);
+	if (atomic_read (&hcd->resume_count) != 1) {
+		err ("concurrent PCI resumes for %s", hcd->bus_name);
+		retval = 0;
+		goto done;
+	}
+
+	retval = -EBUSY;
+	if (hcd->state != USB_STATE_SUSPENDED) {
+		dbg ("can't resume, not suspended!");
+		goto done;
+	}
+	hcd->state = USB_STATE_RESUMING;
+
+	pci_set_power_state (dev, 0);
+	pci_restore_state (dev, hcd->pci_state);
+
+	retval = hcd->driver->resume (hcd);
+	if (!HCD_IS_RUNNING (hcd->state)) {
+		dbg ("resume %s failure, retval %d", hcd->bus_name, retval);
+		hc_died (hcd);
+// FIXME:  recover, reset etc.
+	} else {
+		// FIXME for all connected devices, root-to-leaf:
+		// driver->resume ();
+		// proposed "new 2.5 driver model" will automate that
+	}
+
+done:
+	atomic_dec (&hcd->resume_count);
+	return retval;
+}
+EXPORT_SYMBOL (usb_hcd_pci_resume);
+
+#endif	/* CONFIG_PM */
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Generic HC operations.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* called from khubd, or root hub init threads for hcd-private init */
+static int hcd_alloc_dev (struct usb_device *udev)
+{
+	struct hcd_dev		*dev;
+	struct usb_hcd		*hcd;
+	unsigned long		flags;
+
+	if (!udev || udev->hcpriv)
+		return -EINVAL;
+	if (!udev->bus || !udev->bus->hcpriv)
+		return -ENODEV;
+	hcd = udev->bus->hcpriv;
+	if (hcd->state == USB_STATE_QUIESCING)
+		return -ENOLINK;
+
+	dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL);
+	if (dev == NULL)
+		return -ENOMEM;
+	memset (dev, 0, sizeof *dev);
+
+	INIT_LIST_HEAD (&dev->dev_list);
+	INIT_LIST_HEAD (&dev->urb_list);
+
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	list_add (&dev->dev_list, &hcd->dev_list);
+	// refcount is implicit
+	udev->hcpriv = dev;
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void hc_died (struct usb_hcd *hcd)
+{
+	struct list_head	*devlist, *urblist;
+	struct hcd_dev		*dev;
+	struct urb		*urb;
+	unsigned long		flags;
+	
+	/* flag every pending urb as done */
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	list_for_each (devlist, &hcd->dev_list) {
+		dev = list_entry (devlist, struct hcd_dev, dev_list);
+		list_for_each (urblist, &dev->urb_list) {
+			urb = list_entry (urblist, struct urb, urb_list);
+			dbg ("shutdown %s urb %p pipe %x, current status %d",
+				hcd->bus_name, urb, urb->pipe, urb->status);
+			if (urb->status == -EINPROGRESS)
+				urb->status = -ESHUTDOWN;
+		}
+	}
+	urb = (struct urb *) hcd->rh_timer.data;
+	if (urb)
+		urb->status = -ESHUTDOWN;
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+	if (urb)
+		rh_status_dequeue (hcd, urb);
+	hcd->driver->stop (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void urb_unlink (struct urb *urb)
+{
+	unsigned long		flags;
+	struct usb_device	*dev;
+
+	/* Release any periodic transfer bandwidth */
+	if (urb->bandwidth)
+		usb_release_bandwidth (urb->dev, urb,
+			usb_pipeisoc (urb->pipe));
+
+	/* clear all state linking urb to this dev (and hcd) */
+
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	list_del_init (&urb->urb_list);
+	dev = urb->dev;
+	urb->dev = NULL;
+	usb_dec_dev_use (dev);
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+}
+
+
+/* may be called in any context with a valid urb->dev usecount */
+/* caller surrenders "ownership" of urb */
+
+static int hcd_submit_urb (struct urb *urb, int mem_flags)
+{
+	int			status;
+	struct usb_hcd		*hcd;
+	struct hcd_dev		*dev;
+	unsigned long		flags;
+	int			pipe, temp, max;
+
+	if (!urb || urb->hcpriv || !urb->complete)
+		return -EINVAL;
+
+	urb->status = -EINPROGRESS;
+	urb->actual_length = 0;
+	urb->bandwidth = 0;
+	INIT_LIST_HEAD (&urb->urb_list);
+
+	if (!urb->dev || !urb->dev->bus || urb->dev->devnum <= 0)
+		return -ENODEV;
+	hcd = urb->dev->bus->hcpriv;
+	dev = urb->dev->hcpriv;
+	if (!hcd || !dev)
+		return -ENODEV;
+
+	/* can't submit new urbs when quiescing, halted, ... */
+	if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state))
+		return -ESHUTDOWN;
+	pipe = urb->pipe;
+	temp = usb_pipetype (urb->pipe);
+	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe),
+			usb_pipeout (pipe)))
+		return -EPIPE;
+
+	/* FIXME there should be a sharable lock protecting us against
+	 * config/altsetting changes and disconnects, kicking in here.
+	 */
+
+	/* Sanity check, so HCDs can rely on clean data */
+	max = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
+	if (max <= 0) {
+		err ("bogus endpoint (bad maxpacket)");
+		return -EINVAL;
+	}
+
+	/* "high bandwidth" mode, 1-3 packets/uframe? */
+	if (urb->dev->speed == USB_SPEED_HIGH) {
+		int	mult;
+		switch (temp) {
+		case PIPE_ISOCHRONOUS:
+		case PIPE_INTERRUPT:
+			mult = 1 + ((max >> 11) & 0x03);
+			max &= 0x03ff;
+			max *= mult;
+		}
+	}
+
+	/* periodic transfers limit size per frame/uframe */
+	switch (temp) {
+	case PIPE_ISOCHRONOUS: {
+		int	n, len;
+
+		if (urb->number_of_packets <= 0)		    
+			return -EINVAL;
+		for (n = 0; n < urb->number_of_packets; n++) {
+			len = urb->iso_frame_desc [n].length;
+			if (len < 0 || len > max) 
+				return -EINVAL;
+		}
+
+		}
+		break;
+	case PIPE_INTERRUPT:
+		if (urb->transfer_buffer_length > max)
+			return -EINVAL;
+	}
+
+	/* the I/O buffer must usually be mapped/unmapped */
+	if (urb->transfer_buffer_length < 0)
+		return -EINVAL;
+
+	if (urb->next) {
+		warn ("use explicit queuing not urb->next");
+		return -EINVAL;
+	}
+
+#ifdef DEBUG
+	/* stuff that drivers shouldn't do, but which shouldn't
+	 * cause problems in HCDs if they get it wrong.
+	 */
+	{
+	unsigned int	orig_flags = urb->transfer_flags;
+	unsigned int	allowed;
+
+	/* enforce simple/standard policy */
+	allowed = USB_ASYNC_UNLINK;	// affects later unlinks
+	allowed |= USB_NO_FSBR;		// only affects UHCI
+	switch (temp) {
+	case PIPE_CONTROL:
+		allowed |= USB_DISABLE_SPD;
+		break;
+	case PIPE_BULK:
+		allowed |= USB_DISABLE_SPD | USB_QUEUE_BULK
+				| USB_ZERO_PACKET | URB_NO_INTERRUPT;
+		break;
+	case PIPE_INTERRUPT:
+		allowed |= USB_DISABLE_SPD;
+		break;
+	case PIPE_ISOCHRONOUS:
+		allowed |= USB_ISO_ASAP;
+		break;
+	}
+	urb->transfer_flags &= allowed;
+
+	/* fail if submitter gave bogus flags */
+	if (urb->transfer_flags != orig_flags) {
+		err ("BOGUS urb flags, %x --> %x",
+			orig_flags, urb->transfer_flags);
+		return -EINVAL;
+	}
+	}
+#endif
+	/*
+	 * Force periodic transfer intervals to be legal values that are
+	 * a power of two (so HCDs don't need to).
+	 *
+	 * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
+	 * supports different values... this uses EHCI/UHCI defaults (and
+	 * EHCI can use smaller non-default values).
+	 */
+	switch (temp) {
+	case PIPE_ISOCHRONOUS:
+	case PIPE_INTERRUPT:
+		/* too small? */
+		if (urb->interval <= 0)
+			return -EINVAL;
+		/* too big? */
+		switch (urb->dev->speed) {
+		case USB_SPEED_HIGH:	/* units are microframes */
+			// NOTE usb handles 2^15
+			if (urb->interval > (1024 * 8))
+				urb->interval = 1024 * 8;
+			temp = 1024 * 8;
+			break;
+		case USB_SPEED_FULL:	/* units are frames/msec */
+		case USB_SPEED_LOW:
+			if (temp == PIPE_INTERRUPT) {
+				if (urb->interval > 255)
+					return -EINVAL;
+				// NOTE ohci only handles up to 32
+				temp = 128;
+			} else {
+				if (urb->interval > 1024)
+					urb->interval = 1024;
+				// NOTE usb and ohci handle up to 2^15
+				temp = 1024;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+		/* power of two? */
+		while (temp > urb->interval)
+			temp >>= 1;
+		urb->interval = temp;
+	}
+
+
+	/*
+	 * FIXME:  make urb timeouts be generic, keeping the HCD cores
+	 * as simple as possible.
+	 */
+
+	// NOTE:  a generic device/urb monitoring hook would go here.
+	// hcd_monitor_hook(MONITOR_URB_SUBMIT, urb)
+	// It would catch submission paths for all urbs.
+
+	/* increment urb's reference count, we now control it. */
+	urb = usb_get_urb(urb);
+
+	/*
+	 * Atomically queue the urb,  first to our records, then to the HCD.
+	 * Access to urb->status is controlled by urb->lock ... changes on
+	 * i/o completion (normal or fault) or unlinking.
+	 */
+
+	// FIXME:  verify that quiescing hc works right (RH cleans up)
+
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) {
+		usb_inc_dev_use (urb->dev);
+		list_add (&urb->urb_list, &dev->urb_list);
+		status = 0;
+	} else {
+		INIT_LIST_HEAD (&urb->urb_list);
+		status = -ESHUTDOWN;
+	}
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+	if (status)
+		return status;
+
+	/* temporarily up refcount while queueing it in the HCD,
+	 * since we report some queuing/setup errors ourselves
+	 */
+	urb = usb_get_urb (urb);
+	if (urb->dev == hcd->bus->root_hub)
+		status = rh_urb_enqueue (hcd, urb);
+	else
+		status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+	/* urb->dev got nulled if hcd called giveback for us */
+	if (status && urb->dev)
+		urb_unlink (urb);
+	usb_put_urb (urb);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* called in any context */
+static int hcd_get_frame_number (struct usb_device *udev)
+{
+	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
+	return hcd->driver->get_frame_number (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+struct completion_splice {		// modified urb context:
+	/* did we complete? */
+	struct completion	done;
+
+	/* original urb data */
+	void			(*complete)(struct urb *);
+	void			*context;
+};
+
+static void unlink_complete (struct urb *urb)
+{
+	struct completion_splice	*splice;
+
+	splice = (struct completion_splice *) urb->context;
+
+	/* issue original completion call */
+	urb->complete = splice->complete;
+	urb->context = splice->context;
+	urb->complete (urb);
+
+	/* then let the synchronous unlink call complete */
+	complete (&splice->done);
+}
+
+/*
+ * called in any context; note ASYNC_UNLINK restrictions
+ *
+ * caller guarantees urb won't be recycled till both unlink()
+ * and the urb's completion function return
+ */
+static int hcd_unlink_urb (struct urb *urb)
+{
+	struct hcd_dev			*dev;
+	struct usb_hcd			*hcd = 0;
+	unsigned long			flags;
+	struct completion_splice	splice;
+	int				retval;
+
+	if (!urb)
+		return -EINVAL;
+
+	/*
+	 * we contend for urb->status with the hcd core,
+	 * which changes it while returning the urb.
+	 *
+	 * Caller guaranteed that the urb pointer hasn't been freed, and
+	 * that it was submitted.  But as a rule it can't know whether or
+	 * not it's already been unlinked ... so we respect the reversed
+	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
+	 * (urb lock, then hcd_data_lock) in case some other CPU is now
+	 * unlinking it.
+	 */
+	spin_lock_irqsave (&urb->lock, flags);
+	spin_lock (&hcd_data_lock);
+	if (!urb->hcpriv || urb->transfer_flags & USB_TIMEOUT_KILLED) {
+		retval = -EINVAL;
+		goto done;
+	}
+
+	if (!urb->dev || !urb->dev->bus) {
+		retval = -ENODEV;
+		goto done;
+	}
+
+	/* giveback clears dev; non-null means it's linked at this level */
+	dev = urb->dev->hcpriv;
+	hcd = urb->dev->bus->hcpriv;
+	if (!dev || !hcd) {
+		retval = -ENODEV;
+		goto done;
+	}
+
+	/* For non-periodic transfers, any status except -EINPROGRESS means
+	 * the HCD has already started to unlink this URB from the hardware.
+	 * In that case, there's no more work to do.
+	 *
+	 * For periodic transfers, this is the only way to trigger unlinking
+	 * from the hardware.  Since we (currently) overload urb->status to
+	 * tell the driver to unlink, error status might get clobbered ...
+	 * unless that transfer hasn't yet restarted.  One such case is when
+	 * the URB gets unlinked from its completion handler.
+	 *
+	 * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
+	 */
+	switch (usb_pipetype (urb->pipe)) {
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+		if (urb->status != -EINPROGRESS) {
+			retval = -EINVAL;
+			goto done;
+		}
+	}
+
+	/* maybe set up to block on completion notification */
+	if ((urb->transfer_flags & USB_TIMEOUT_KILLED))
+		urb->status = -ETIMEDOUT;
+	else if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
+		if (in_interrupt ()) {
+			dbg ("non-async unlink in_interrupt");
+			retval = -EWOULDBLOCK;
+			goto done;
+		}
+		/* synchronous unlink: block till we see the completion */
+		init_completion (&splice.done);
+		splice.complete = urb->complete;
+		splice.context = urb->context;
+		urb->complete = unlink_complete;
+		urb->context = &splice;
+		urb->status = -ENOENT;
+	} else {
+		/* asynchronous unlink */
+		urb->status = -ECONNRESET;
+	}
+	spin_unlock (&hcd_data_lock);
+	spin_unlock_irqrestore (&urb->lock, flags);
+
+	if (urb == (struct urb *) hcd->rh_timer.data) {
+		rh_status_dequeue (hcd, urb);
+		retval = 0;
+	} else {
+		retval = hcd->driver->urb_dequeue (hcd, urb);
+// FIXME:  if retval and we tried to splice, whoa!!
+if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
+	}
+
+    	/* block till giveback, if needed */
+	if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED))
+			&& HCD_IS_RUNNING (hcd->state)
+			&& !retval) {
+		dbg ("%s: wait for giveback urb %p",
+			hcd->bus_name, urb);
+		wait_for_completion (&splice.done);
+	} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
+		return -EINPROGRESS;
+	}
+	goto bye;
+done:
+	spin_unlock (&hcd_data_lock);
+	spin_unlock_irqrestore (&urb->lock, flags);
+bye:
+	if (retval)
+		dbg ("%s: hcd_unlink_urb fail %d",
+		    hcd ? hcd->bus_name : "(no bus?)",
+		    retval);
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup */
+
+// FIXME:  likely best to have explicit per-setting (config+alt)
+// setup primitives in the usbcore-to-hcd driver API, so nothing
+// is implicit.  kernel 2.5 needs a bunch of config cleanup...
+
+static int hcd_free_dev (struct usb_device *udev)
+{
+	struct hcd_dev		*dev;
+	struct usb_hcd		*hcd;
+	unsigned long		flags;
+
+	if (!udev || !udev->hcpriv)
+		return -EINVAL;
+
+	if (!udev->bus || !udev->bus->hcpriv)
+		return -ENODEV;
+
+	// should udev->devnum == -1 ??
+
+	dev = udev->hcpriv;
+	hcd = udev->bus->hcpriv;
+
+	/* device driver problem with refcounts? */
+	if (!list_empty (&dev->urb_list)) {
+		dbg ("free busy dev, %s devnum %d (bug!)",
+			hcd->bus_name, udev->devnum);
+		return -EINVAL;
+	}
+
+	hcd->driver->free_config (hcd, udev);
+
+	spin_lock_irqsave (&hcd_data_lock, flags);
+	list_del (&dev->dev_list);
+	udev->hcpriv = NULL;
+	spin_unlock_irqrestore (&hcd_data_lock, flags);
+
+	kfree (dev);
+	return 0;
+}
+
+static struct usb_operations hcd_operations = {
+	allocate:		hcd_alloc_dev,
+	get_frame_number:	hcd_get_frame_number,
+	submit_urb:		hcd_submit_urb,
+	unlink_urb:		hcd_unlink_urb,
+	deallocate:		hcd_free_dev,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
+{
+	struct usb_hcd		*hcd = __hcd;
+	int			start = hcd->state;
+
+	if (unlikely (hcd->state == USB_STATE_HALT))	/* irq sharing? */
+		return;
+
+	hcd->driver->irq (hcd);
+	if (hcd->state != start && hcd->state == USB_STATE_HALT)
+		hc_died (hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_hcd_giveback_urb - return URB from HCD to device driver
+ * @hcd: host controller returning the URB
+ * @urb: urb being returned to the USB device driver.
+ * Context: in_interrupt()
+ *
+ * This hands the URB from HCD to its USB device driver, using its
+ * completion function.  The HCD has freed all per-urb resources
+ * (and is done using urb->hcpriv).  It also released all HCD locks;
+ * the device driver won't cause deadlocks if it resubmits this URB,
+ * and won't confuse things by modifying and resubmitting this one.
+ * Bandwidth and other resources will be deallocated.
+ *
+ * HCDs must not use this for periodic URBs that are still scheduled
+ * and will be reissued.  They should just call their completion handlers
+ * until the urb is returned to the device driver by unlinking.
+ *
+ * NOTE that no urb->next processing is done, even for isochronous URBs.
+ * ISO streaming functionality can be achieved by having completion handlers
+ * re-queue URBs.  Such explicit queuing doesn't discard error reports.
+ */
+void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
+{
+	urb_unlink (urb);
+
+	// NOTE:  a generic device/urb monitoring hook would go here.
+	// hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
+	// It would catch exit/unlink paths for all urbs, but non-exit
+	// completions for periodic urbs need hooks inside the HCD.
+	// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
+
+	if (urb->status)
+		dbg ("giveback urb %p status %d len %d",
+			urb, urb->status, urb->actual_length);
+
+	/* pass ownership to the completion handler */
+	urb->complete (urb);
+	usb_put_urb (urb);
+}
+EXPORT_SYMBOL (usb_hcd_giveback_urb);
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/hcd.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2001-2002 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef __KERNEL__
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * USB Host Controller Driver (usb_hcd) framework
+ *
+ * Since "struct usb_bus" is so thin, you can't share much code in it.
+ * This framework is a layer over that, and should be more sharable.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+struct usb_hcd {	/* usb_bus.hcpriv points to this */
+
+	/*
+	 * housekeeping
+	 */
+	struct usb_bus		*bus;		/* FIXME only use "self" */
+	struct usb_bus		self;		/* hcd is-a bus */
+
+	const char		*bus_name;
+	const char		*product_desc;	/* product/vendor string */
+	const char		*description;	/* "ehci-hcd" etc */
+
+	struct timer_list	rh_timer;	/* drives root hub */
+	struct list_head	dev_list;	/* devices on this bus */
+
+	/*
+	 * hardware info/state
+	 */
+	struct hc_driver	*driver;	/* hw-specific hooks */
+	int			irq;		/* irq allocated */
+	void			*regs;		/* device memory/io */
+
+#ifdef	CONFIG_PCI
+	/* a few non-PCI controllers exist, mostly for OHCI */
+	struct pci_dev		*pdev;		/* pci is typical */
+	int			region;		/* pci region for regs */
+	u32			pci_state [16];	/* for PM state save */
+	atomic_t		resume_count;	/* multiple resumes issue */
+#endif
+
+	int			state;
+#	define	__ACTIVE		0x01
+#	define	__SLEEPY		0x02
+#	define	__SUSPEND		0x04
+#	define	__TRANSIENT		0x80
+
+#	define	USB_STATE_HALT		0
+#	define	USB_STATE_RUNNING	(__ACTIVE)
+#	define	USB_STATE_READY		(__ACTIVE|__SLEEPY)
+#	define	USB_STATE_QUIESCING	(__SUSPEND|__TRANSIENT|__ACTIVE)
+#	define	USB_STATE_RESUMING	(__SUSPEND|__TRANSIENT)
+#	define	USB_STATE_SUSPENDED	(__SUSPEND)
+
+#define	HCD_IS_RUNNING(state) ((state) & __ACTIVE)
+#define	HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
+
+	/* more shared queuing code would be good; it should support
+	 * smarter scheduling, handle transaction translators, etc;
+	 * input size of periodic table to an interrupt scheduler. 
+	 * (ohci 32, uhci 1024, ehci 256/512/1024).
+	 */
+};
+
+struct hcd_dev {	/* usb_device.hcpriv points to this */
+	struct list_head	dev_list;	/* on this hcd */
+	struct list_head	urb_list;	/* pending on this dev */
+
+	/* per-configuration HC/HCD state, such as QH or ED */
+	void			*ep[32];
+};
+
+// urb.hcpriv is really hardware-specific
+
+struct hcd_timeout {	/* timeouts we allocate */
+	struct list_head	timeout_list;
+	struct timer_list	timer;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * FIXME usb_operations should vanish or become hc_driver,
+ * when usb_bus and usb_hcd become the same thing.
+ */
+
+struct usb_operations {
+	int (*allocate)(struct usb_device *);
+	int (*deallocate)(struct usb_device *);
+	int (*get_frame_number) (struct usb_device *usb_dev);
+	int (*submit_urb) (struct urb *urb, int mem_flags);
+	int (*unlink_urb) (struct urb *urb);
+};
+
+/* each driver provides one of these, and hardware init support */
+
+struct hc_driver {
+	const char	*description;	/* "ehci-hcd" etc */
+
+	/* irq handler */
+	void	(*irq) (struct usb_hcd *hcd);
+
+	int	flags;
+#define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
+#define	HCD_USB11	0x0010		/* USB 1.1 */
+#define	HCD_USB2	0x0020		/* USB 2.0 */
+
+	/* called to init HCD and root hub */
+	int	(*start) (struct usb_hcd *hcd);
+
+	/* called after all devices were suspended */
+	int	(*suspend) (struct usb_hcd *hcd, u32 state);
+
+	/* called before any devices get resumed */
+	int	(*resume) (struct usb_hcd *hcd);
+
+	/* cleanly make HCD stop writing memory and doing I/O */
+	void	(*stop) (struct usb_hcd *hcd);
+
+	/* return current frame number */
+	int	(*get_frame_number) (struct usb_hcd *hcd);
+
+	/* memory lifecycle */
+	struct usb_hcd	*(*hcd_alloc) (void);
+	void		(*hcd_free) (struct usb_hcd *hcd);
+
+	/* manage i/o requests, device state */
+	int	(*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
+					int mem_flags);
+	int	(*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
+
+	// frees configuration resources -- allocated as needed during
+	// urb_enqueue, and not freed by urb_dequeue
+	void		(*free_config) (struct usb_hcd *hcd,
+				struct usb_device *dev);
+
+	/* root hub support */
+	int		(*hub_status_data) (struct usb_hcd *hcd, char *buf);
+	int		(*hub_control) (struct usb_hcd *hcd,
+				u16 typeReq, u16 wValue, u16 wIndex,
+				char *buf, u16 wLength);
+};
+
+extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
+
+#ifdef CONFIG_PCI
+struct pci_dev;
+struct pci_device_id;
+extern int usb_hcd_pci_probe (struct pci_dev *dev,
+				const struct pci_device_id *id);
+extern void usb_hcd_pci_remove (struct pci_dev *dev);
+
+#ifdef CONFIG_PM
+// FIXME:  see Documentation/power/pci.txt (2.4.6 and later?)
+// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
+extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
+extern int usb_hcd_pci_resume (struct pci_dev *dev);
+// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
+#endif /* CONFIG_PM */
+
+#endif /* CONFIG_PCI */
+
+/* -------------------------------------------------------------------------- */
+
+/* Enumeration is only for the hub driver, or HCD virtual root hubs */
+extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
+	struct usb_bus *);
+extern void usb_free_dev(struct usb_device *);
+extern int usb_new_device(struct usb_device *dev);
+extern void usb_connect(struct usb_device *dev);
+extern void usb_disconnect(struct usb_device **);
+
+#ifndef _LINUX_HUB_H
+/* exported to hub driver ONLY to support usb_reset_device () */
+extern int usb_get_configuration(struct usb_device *dev);
+extern void usb_set_maxpacket(struct usb_device *dev);
+extern void usb_destroy_configuration(struct usb_device *dev);
+extern int usb_set_address(struct usb_device *dev);
+#endif /* _LINUX_HUB_H */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * HCD Root Hub support
+ */
+
+#include "hub.h"
+
+/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
+#define DeviceRequest \
+	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
+#define DeviceOutRequest \
+	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
+
+#define InterfaceRequest \
+	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+
+#define EndpointRequest \
+	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+#define EndpointOutRequest \
+	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
+
+/* table 9.6 standard features */
+#define DEVICE_REMOTE_WAKEUP	1
+#define ENDPOINT_HALT		0
+
+/* class requests from the USB 2.0 hub spec, table 11-15 */
+/* GetBusState and SetHubDescriptor are optional, omitted */
+#define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
+#define ClearPortFeature	(0x2300 | USB_REQ_CLEAR_FEATURE)
+#define GetHubDescriptor	(0xa000 | USB_REQ_GET_DESCRIPTOR)
+#define GetHubStatus		(0xa000 | USB_REQ_GET_STATUS)
+#define GetPortStatus		(0xa300 | USB_REQ_GET_STATUS)
+#define SetHubFeature		(0x2000 | USB_REQ_SET_FEATURE)
+#define SetPortFeature		(0x2300 | USB_REQ_SET_FEATURE)
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Generic bandwidth allocation constants/support
+ */
+#define FRAME_TIME_USECS	1000L
+#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
+		/* Trying not to use worst-case bit-stuffing
+                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+		/* bytecount = data payload byte count */
+
+#define NS_TO_US(ns)	((ns + 500L) / 1000L)
+			/* convert & round nanoseconds to microseconds */
+
+extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
+		int bustime, int isoc);
+extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
+		int isoc);
+
+/*
+ * Full/low speed bandwidth allocation constants/support.
+ */
+#define BW_HOST_DELAY	1000L		/* nanoseconds */
+#define BW_HUB_LS_SETUP	333L		/* nanoseconds */
+                        /* 4 full-speed bit times (est.) */
+
+#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
+#define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
+#define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
+
+extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
+
+/*-------------------------------------------------------------------------*/
+
+extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
+extern void usb_free_bus (struct usb_bus *);
+
+extern void usb_register_bus (struct usb_bus *);
+extern void usb_deregister_bus (struct usb_bus *);
+
+extern int usb_register_root_hub (struct usb_device *usb_dev,
+		struct device *parent_dev);
+
+/*-------------------------------------------------------------------------*/
+
+/* exported only within usbcore */
+
+extern struct list_head usb_bus_list;
+extern struct semaphore usb_bus_list_lock;
+
+extern void usb_bus_get (struct usb_bus *bus);
+extern void usb_bus_put (struct usb_bus *bus);
+
+/*-------------------------------------------------------------------------*/
+
+/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
+// bleech -- resurfaced in 2.4.11 or 2.4.12
+#define bitmap 	DeviceRemovable
+
+
+/*-------------------------------------------------------------------------*/
+
+/* random stuff */
+
+#define	RUN_CONTEXT (in_irq () ? "in_irq" \
+		: (in_interrupt () ? "in_interrupt" : "can sleep"))
+
+
+#endif /* __KERNEL__ */
+
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/hub.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,1169 @@
+/*
+ * USB hub driver.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Gregory P. Smith
+ * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
+
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+#include "hcd.h"
+#include "hub.h"
+
+/* Wakes up khubd */
+static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_MUTEX(usb_address0_sem);
+
+static LIST_HEAD(hub_event_list);	/* List of hubs needing servicing */
+static LIST_HEAD(hub_list);		/* List of all hubs (for cleanup) */
+
+static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
+static int khubd_pid = 0;			/* PID of khubd */
+static DECLARE_COMPLETION(khubd_exited);
+
+#ifdef	DEBUG
+static inline char *portspeed (int portstatus)
+{
+	if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
+    		return "480 Mb/s";
+	else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
+		return "1.5 Mb/s";
+	else
+		return "12 Mb/s";
+}
+#endif
+
+/* USB 2.0 spec Section 11.24.4.5 */
+static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
+		USB_DT_HUB << 8, 0, data, size, HZ);
+}
+
+/*
+ * USB 2.0 spec Section 11.24.2.1
+ */
+static int usb_clear_hub_feature(struct usb_device *dev, int feature)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
+}
+
+/*
+ * USB 2.0 spec Section 11.24.2.2
+ * BUG: doesn't handle port indicator selector in high byte of wIndex
+ */
+static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
+}
+
+/*
+ * USB 2.0 spec Section 11.24.2.13
+ * BUG: doesn't handle port indicator selector in high byte of wIndex
+ */
+static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
+}
+
+/*
+ * USB 2.0 spec Section 11.24.2.6
+ */
+static int usb_get_hub_status(struct usb_device *dev, void *data)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+		data, sizeof(struct usb_hub_status), HZ);
+}
+
+/*
+ * USB 2.0 spec Section 11.24.2.7
+ */
+static int usb_get_port_status(struct usb_device *dev, int port, void *data)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
+		data, sizeof(struct usb_hub_status), HZ);
+}
+
+/* completion function, fires on port status changes and various faults */
+static void hub_irq(struct urb *urb)
+{
+	struct usb_hub *hub = (struct usb_hub *)urb->context;
+	unsigned long flags;
+
+	switch (urb->status) {
+	case -ENOENT:		/* synchronous unlink */
+	case -ECONNRESET:	/* async unlink */
+	case -ESHUTDOWN:	/* hardware going away */
+		return;
+
+	default:		/* presumably an error */
+		/* Cause a hub reset after 10 consecutive errors */
+		dbg("hub '%s' status %d for interrupt transfer",
+			urb->dev->devpath, urb->status);
+		if ((++hub->nerrors < 10) || hub->error)
+			return;
+		hub->error = urb->status;
+		/* FALL THROUGH */
+	
+	/* let khubd handle things */
+	case 0:			/* we got data:  port status changed */
+		break;
+	}
+
+	hub->nerrors = 0;
+
+	/* Something happened, let khubd figure it out */
+	spin_lock_irqsave(&hub_event_lock, flags);
+	if (list_empty(&hub->event_list)) {
+		list_add(&hub->event_list, &hub_event_list);
+		wake_up(&khubd_wait);
+	}
+	spin_unlock_irqrestore(&hub_event_lock, flags);
+}
+
+static void usb_hub_power_on(struct usb_hub *hub)
+{
+	int i;
+
+	/* Enable power to the ports */
+	dbg("enabling power on all ports");
+	for (i = 0; i < hub->descriptor->bNbrPorts; i++)
+		usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER);
+
+	/* Wait for power to be enabled */
+	wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
+}
+
+static int usb_hub_configure(struct usb_hub *hub,
+	struct usb_endpoint_descriptor *endpoint)
+{
+	struct usb_device *dev = hub->dev;
+	struct usb_hub_status hubstatus;
+	char portstr[USB_MAXCHILDREN + 1];
+	unsigned int pipe;
+	int i, maxp, ret;
+
+	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+	if (!hub->descriptor) {
+		err("Unable to kmalloc %Zd bytes for hub descriptor",
+			sizeof(*hub->descriptor));
+		return -1;
+	}
+
+	/* Request the entire hub descriptor.
+	 * hub->descriptor can handle USB_MAXCHILDREN ports,
+	 * but the hub can/will return fewer bytes here.
+	 */
+	ret = usb_get_hub_descriptor(dev, hub->descriptor,
+			sizeof(*hub->descriptor));
+	if (ret < 0) {
+		err("Unable to get hub descriptor (err = %d)", ret);
+		kfree(hub->descriptor);
+		return -1;
+	} else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
+		err("Hub is too big! %d children", hub->descriptor->bNbrPorts);
+		kfree(hub->descriptor);
+		return -1;
+	}
+
+	dev->maxchild = hub->descriptor->bNbrPorts;
+	info("%d port%s detected", dev->maxchild,
+		(dev->maxchild == 1) ? "" : "s");
+
+	le16_to_cpus(&hub->descriptor->wHubCharacteristics);
+
+	if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND)
+		dbg("part of a compound device");
+	else
+		dbg("standalone hub");
+
+	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
+		case 0x00:
+			dbg("ganged power switching");
+			break;
+		case 0x01:
+			dbg("individual port power switching");
+			break;
+		case 0x02:
+		case 0x03:
+			dbg("unknown reserved power switching mode");
+			break;
+	}
+
+	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
+		case 0x00:
+			dbg("global over-current protection");
+			break;
+		case 0x08:
+			dbg("individual port over-current protection");
+			break;
+		case 0x10:
+		case 0x18:
+			dbg("no over-current protection");
+                        break;
+	}
+
+	switch (dev->descriptor.bDeviceProtocol) {
+		case 0:
+			break;
+		case 1:
+			dbg("Single TT");
+			hub->tt.hub = dev;
+			break;
+		case 2:
+			dbg("TT per port");
+			hub->tt.hub = dev;
+			hub->tt.multi = 1;
+			break;
+		default:
+			dbg("Unrecognized hub protocol %d",
+				dev->descriptor.bDeviceProtocol);
+			break;
+	}
+
+	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) {
+		case 0x00:
+			if (dev->descriptor.bDeviceProtocol != 0)
+				dbg("TT requires at most 8 FS bit times");
+			break;
+		case 0x20:
+			dbg("TT requires at most 16 FS bit times");
+			break;
+		case 0x40:
+			dbg("TT requires at most 24 FS bit times");
+			break;
+		case 0x60:
+			dbg("TT requires at most 32 FS bit times");
+			break;
+	}
+
+	dbg("Port indicators are %s supported", 
+	    (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND)
+	    	? "" : "not");
+
+	dbg("power on to power good time: %dms",
+		hub->descriptor->bPwrOn2PwrGood * 2);
+	dbg("hub controller current requirement: %dmA",
+		hub->descriptor->bHubContrCurrent);
+
+	for (i = 0; i < dev->maxchild; i++)
+		portstr[i] = hub->descriptor->DeviceRemovable
+			    [((i + 1) / 8)] & (1 << ((i + 1) % 8))
+			? 'F' : 'R';
+	portstr[dev->maxchild] = 0;
+
+	dbg("port removable status: %s", portstr);
+
+	ret = usb_get_hub_status(dev, &hubstatus);
+	if (ret < 0) {
+		err("Unable to get hub status (err = %d)", ret);
+		kfree(hub->descriptor);
+		return -1;
+	}
+
+	le16_to_cpus(&hubstatus.wHubStatus);
+
+	dbg("local power source is %s",
+		(hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
+		? "lost (inactive)" : "good");
+
+	dbg("%sover-current condition exists",
+		(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
+
+	/* Start the interrupt endpoint */
+	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	if (maxp > sizeof(hub->buffer))
+		maxp = sizeof(hub->buffer);
+
+	hub->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!hub->urb) {
+		err("couldn't allocate interrupt urb");
+		kfree(hub->descriptor);
+		return -1;
+	}
+
+	FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
+		hub, endpoint->bInterval);
+	ret = usb_submit_urb(hub->urb, GFP_KERNEL);
+	if (ret) {
+		err("usb_submit_urb failed (%d)", ret);
+		kfree(hub->descriptor);
+		return -1;
+	}
+		
+	/* Wake up khubd */
+	wake_up(&khubd_wait);
+
+	usb_hub_power_on(hub);
+
+	return 0;
+}
+
+static void *hub_probe(struct usb_device *dev, unsigned int i,
+		       const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_hub *hub;
+	unsigned long flags;
+
+	interface = &dev->actconfig->interface[i].altsetting[0];
+
+	/* Some hubs have a subclass of 1, which AFAICT according to the */
+	/*  specs is not defined, but it works */
+	if ((interface->bInterfaceSubClass != 0) &&
+	    (interface->bInterfaceSubClass != 1)) {
+		err("invalid subclass (%d) for USB hub device #%d",
+			interface->bInterfaceSubClass, dev->devnum);
+		return NULL;
+	}
+
+	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
+	if (interface->bNumEndpoints != 1) {
+		err("invalid bNumEndpoints (%d) for USB hub device #%d",
+			interface->bNumEndpoints, dev->devnum);
+		return NULL;
+	}
+
+	endpoint = &interface->endpoint[0];
+
+	/* Output endpoint? Curiousier and curiousier.. */
+	if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
+		err("Device #%d is hub class, but has output endpoint?",
+			dev->devnum);
+		return NULL;
+	}
+
+	/* If it's not an interrupt endpoint, we'd better punt! */
+	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			!= USB_ENDPOINT_XFER_INT) {
+		err("Device #%d is hub class, but endpoint is not interrupt?",
+			dev->devnum);
+		return NULL;
+	}
+
+	/* We found a hub */
+	info("USB hub found at %s", dev->devpath);
+
+	hub = kmalloc(sizeof(*hub), GFP_KERNEL);
+	if (!hub) {
+		err("couldn't kmalloc hub struct");
+		return NULL;
+	}
+
+	memset(hub, 0, sizeof(*hub));
+
+	INIT_LIST_HEAD(&hub->event_list);
+	hub->dev = dev;
+	init_MUTEX(&hub->khubd_sem);
+
+	/* Record the new hub's existence */
+	spin_lock_irqsave(&hub_event_lock, flags);
+	INIT_LIST_HEAD(&hub->hub_list);
+	list_add(&hub->hub_list, &hub_list);
+	spin_unlock_irqrestore(&hub_event_lock, flags);
+
+	if (usb_hub_configure(hub, endpoint) >= 0)
+		return hub;
+
+	err("hub configuration failed for device at %s", dev->devpath);
+
+	/* free hub, but first clean up its list. */
+	spin_lock_irqsave(&hub_event_lock, flags);
+
+	/* Delete it and then reset it */
+	list_del(&hub->event_list);
+	INIT_LIST_HEAD(&hub->event_list);
+	list_del(&hub->hub_list);
+	INIT_LIST_HEAD(&hub->hub_list);
+
+	spin_unlock_irqrestore(&hub_event_lock, flags);
+
+	kfree(hub);
+
+	return NULL;
+}
+
+static void hub_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_hub *hub = (struct usb_hub *)ptr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hub_event_lock, flags);
+
+	/* Delete it and then reset it */
+	list_del(&hub->event_list);
+	INIT_LIST_HEAD(&hub->event_list);
+	list_del(&hub->hub_list);
+	INIT_LIST_HEAD(&hub->hub_list);
+
+	spin_unlock_irqrestore(&hub_event_lock, flags);
+
+	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
+	up(&hub->khubd_sem);
+
+	if (hub->urb) {
+		usb_unlink_urb(hub->urb);
+		usb_free_urb(hub->urb);
+		hub->urb = NULL;
+	}
+
+	if (hub->descriptor) {
+		kfree(hub->descriptor);
+		hub->descriptor = NULL;
+	}
+
+	/* Free the memory */
+	kfree(hub);
+}
+
+static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
+{
+	/* assert ifno == 0 (part of hub spec) */
+	switch (code) {
+	case USBDEVFS_HUB_PORTINFO: {
+		struct usbdevfs_hub_portinfo *info = user_data;
+		unsigned long flags;
+		int i;
+
+		spin_lock_irqsave(&hub_event_lock, flags);
+		if (hub->devnum <= 0)
+			info->nports = 0;
+		else {
+			info->nports = hub->maxchild;
+			for (i = 0; i < info->nports; i++) {
+				if (hub->children[i] == NULL)
+					info->port[i] = 0;
+				else
+					info->port[i] =
+						hub->children[i]->devnum;
+			}
+		}
+		spin_unlock_irqrestore(&hub_event_lock, flags);
+
+		return info->nports + 1;
+		}
+
+	default:
+		return -ENOSYS;
+	}
+}
+
+static int usb_hub_reset(struct usb_hub *hub)
+{
+	struct usb_device *dev = hub->dev;
+	int i;
+
+	/* Disconnect any attached devices */
+	for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
+		if (dev->children[i])
+			usb_disconnect(&dev->children[i]);
+	}
+
+	/* Attempt to reset the hub */
+	if (hub->urb)
+		usb_unlink_urb(hub->urb);
+	else
+		return -1;
+
+	if (usb_reset_device(dev))
+		return -1;
+
+	hub->urb->dev = dev;                                                    
+	if (usb_submit_urb(hub->urb, GFP_KERNEL))
+		return -1;
+
+	usb_hub_power_on(hub);
+
+	return 0;
+}
+
+static void usb_hub_disconnect(struct usb_device *dev)
+{
+	struct usb_device *parent = dev->parent;
+	int i;
+
+	/* Find the device pointer to disconnect */
+	if (parent) {
+		for (i = 0; i < parent->maxchild; i++) {
+			if (parent->children[i] == dev) {
+				usb_disconnect(&parent->children[i]);
+				return;
+			}
+		}
+	}
+
+	err("cannot disconnect hub %s", dev->devpath);
+}
+
+static int usb_hub_port_status(struct usb_device *hub, int port,
+			       u16 *status, u16 *change)
+{
+	struct usb_port_status *portsts;
+	int ret = -ENOMEM;
+
+	portsts = kmalloc(sizeof(*portsts), GFP_KERNEL);
+	if (portsts) {
+		ret = usb_get_port_status(hub, port + 1, portsts);
+		if (ret < 0)
+			err("%s(%s) failed (err = %d)", __FUNCTION__, hub->devpath, ret);
+		else {
+			*status = le16_to_cpu(portsts->wPortStatus);
+			*change = le16_to_cpu(portsts->wPortChange); 
+			dbg("port %d, portstatus %x, change %x, %s", port + 1,
+				*status, *change, portspeed(*status));
+			ret = 0;
+		}
+		kfree(portsts);
+	}
+	return ret;
+}
+
+#define HUB_RESET_TRIES		5
+#define HUB_PROBE_TRIES		2
+#define HUB_SHORT_RESET_TIME	10
+#define HUB_LONG_RESET_TIME	200
+#define HUB_RESET_TIMEOUT	500
+
+/* return: -1 on error, 0 on success, 1 on disconnect.  */
+static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
+				struct usb_device *dev, unsigned int delay)
+{
+	int delay_time, ret;
+	u16 portstatus;
+	u16 portchange;
+
+	for (delay_time = 0;
+			delay_time < HUB_RESET_TIMEOUT;
+			delay_time += delay) {
+		/* wait to give the device a chance to reset */
+		wait_ms(delay);
+
+		/* read and decode port status */
+		ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
+		if (ret < 0) {
+			return -1;
+		}
+
+		/* Device went away? */
+		if (!(portstatus & USB_PORT_STAT_CONNECTION))
+			return 1;
+
+		/* bomb out completely if something weird happened */
+		if ((portchange & USB_PORT_STAT_C_CONNECTION))
+			return -1;
+
+		/* if we`ve finished resetting, then break out of the loop */
+		if (!(portstatus & USB_PORT_STAT_RESET) &&
+		    (portstatus & USB_PORT_STAT_ENABLE)) {
+			if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+				dev->speed = USB_SPEED_HIGH;
+			else if (portstatus & USB_PORT_STAT_LOW_SPEED)
+				dev->speed = USB_SPEED_LOW;
+			else
+				dev->speed = USB_SPEED_FULL;
+			return 0;
+		}
+
+		/* switch to the long delay after two short delay failures */
+		if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
+			delay = HUB_LONG_RESET_TIME;
+
+		dbg("port %d of hub %s not reset yet, waiting %dms", port + 1,
+			hub->devpath, delay);
+	}
+
+	return -1;
+}
+
+/* return: -1 on error, 0 on success, 1 on disconnect.  */
+static int usb_hub_port_reset(struct usb_device *hub, int port,
+				struct usb_device *dev, unsigned int delay)
+{
+	int i, status;
+
+	/* Reset the port */
+	for (i = 0; i < HUB_RESET_TRIES; i++) {
+		usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
+
+		/* return on disconnect or reset */
+		status = usb_hub_port_wait_reset(hub, port, dev, delay);
+		if (status != -1) {
+			usb_clear_port_feature(hub,
+				port + 1, USB_PORT_FEAT_C_RESET);
+			return status;
+		}
+
+		dbg("port %d of hub %s not enabled, trying reset again...",
+			port + 1, hub->devpath);
+		delay = HUB_LONG_RESET_TIME;
+	}
+
+	err("Cannot enable port %i of hub %s, disabling port.",
+		port + 1, hub->devpath);
+	err("Maybe the USB cable is bad?");
+
+	return -1;
+}
+
+void usb_hub_port_disable(struct usb_device *hub, int port)
+{
+	int ret;
+
+	ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
+	if (ret)
+		err("cannot disable port %d of hub %s (err = %d)",
+			port + 1, hub->devpath, ret);
+}
+
+/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
+ *
+ * Between connect detection and reset signaling there must be a delay
+ * of 100ms at least for debounce and power-settling. The corresponding
+ * timer shall restart whenever the downstream port detects a disconnect.
+ * 
+ * Apparently there are some bluetooth and irda-dongles and a number
+ * of low-speed devices which require longer delays of about 200-400ms.
+ * Not covered by the spec - but easy to deal with.
+ *
+ * This implementation uses 400ms minimum debounce timeout and checks
+ * every 100ms for transient disconnects to restart the delay.
+ */
+
+#define HUB_DEBOUNCE_TIMEOUT	400
+#define HUB_DEBOUNCE_STEP	100
+
+/* return: -1 on error, 0 on success, 1 on disconnect.  */
+static int usb_hub_port_debounce(struct usb_device *hub, int port)
+{
+	int ret;
+	unsigned delay_time;
+	u16 portchange, portstatus;
+
+	for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) {
+
+		/* wait debounce step increment */
+		wait_ms(HUB_DEBOUNCE_STEP);
+
+		ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
+		if (ret < 0)
+			return -1;
+
+		if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
+			usb_clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION);
+			delay_time = 0;
+		}
+		else
+			delay_time += HUB_DEBOUNCE_STEP;
+	}
+	return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
+}
+
+static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
+					u16 portstatus, u16 portchange)
+{
+	struct usb_device *hub = hubstate->dev;
+	struct usb_device *dev;
+	unsigned int delay = HUB_SHORT_RESET_TIME;
+	int i;
+
+	dbg("hub %s port %d, portstatus %x, change %x, %s",
+		hub->devpath, port + 1,
+		portstatus, portchange, portspeed (portstatus));
+
+	/* Clear the connection change status */
+	usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
+
+	/* Disconnect any existing devices under this port */
+	if (hub->children[port])
+		usb_disconnect(&hub->children[port]);
+
+	/* Return now if nothing is connected */
+	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
+		if (portstatus & USB_PORT_STAT_ENABLE)
+			usb_hub_port_disable(hub, port);
+
+		return;
+	}
+
+	if (usb_hub_port_debounce(hub, port)) {
+		err("connect-debounce failed, port %d disabled", port+1);
+		usb_hub_port_disable(hub, port);
+		return;
+	}
+
+	/* Some low speed devices have problems with the quick delay, so */
+	/*  be a bit pessimistic with those devices. RHbug #23670 */
+	if (portstatus & USB_PORT_STAT_LOW_SPEED)
+		delay = HUB_LONG_RESET_TIME;
+
+	down(&usb_address0_sem);
+
+	for (i = 0; i < HUB_PROBE_TRIES; i++) {
+		struct usb_device *pdev;
+		int	len;
+
+		/* Allocate a new device struct */
+		dev = usb_alloc_dev(hub, hub->bus);
+		if (!dev) {
+			err("couldn't allocate usb_device");
+			break;
+		}
+
+		hub->children[port] = dev;
+
+		/* Reset the device, and detect its speed */
+		if (usb_hub_port_reset(hub, port, dev, delay)) {
+			usb_free_dev(dev);
+			break;
+		}
+
+		/* Find a new address for it */
+		usb_connect(dev);
+
+		/* Set up TT records, if needed  */
+		if (hub->tt) {
+			dev->tt = hub->tt;
+			dev->ttport = hub->ttport;
+		} else if (dev->speed != USB_SPEED_HIGH
+				&& hub->speed == USB_SPEED_HIGH) {
+			dev->tt = &hubstate->tt;
+			dev->ttport = port + 1;
+		}
+
+		/* Save readable and stable topology id, distinguishing
+		 * devices by location for diagnostics, tools, etc.  The
+		 * string is a path along hub ports, from the root.  Each
+		 * device's id will be stable until USB is re-cabled, and
+		 * hubs are often labled with these port numbers.
+		 *
+		 * Initial size: "/NN" times five hubs + NUL = 16 bytes max
+		 * (quite rare, since most hubs have 4-6 ports).
+		 */
+		pdev = dev->parent;
+		if (pdev->devpath [1] != '\0')	/* parent not root */
+			len = snprintf (dev->devpath, sizeof dev->devpath,
+				"%s/%d", pdev->devpath, port + 1);
+		else	/* root == "/", root port 2 == "/2" */
+			len = snprintf (dev->devpath, sizeof dev->devpath,
+				"/%d", port + 1);
+		if (len == sizeof dev->devpath)
+			warn ("devpath size! usb/%03d/%03d path %s",
+				dev->bus->busnum, dev->devnum, dev->devpath);
+		info("new USB device on bus %d path %s, assigned address %d",
+			dev->bus->busnum, dev->devpath, dev->devnum);
+
+		/* put the device in the global device tree */
+		dev->dev.parent = &dev->parent->dev;
+		sprintf (&dev->dev.name[0], "USB device %04x:%04x",
+			 dev->descriptor.idVendor,
+			 dev->descriptor.idProduct);
+		/* find the number of the port this device is connected to */
+		sprintf (&dev->dev.bus_id[0], "unknown_port_%03d", dev->devnum);
+		for (i = 0; i < USB_MAXCHILDREN; ++i) {
+			if (dev->parent->children[i] == dev) {
+				sprintf (&dev->dev.bus_id[0], "%02d", i);
+				break;
+			}
+		}
+
+		/* Run it through the hoops (find a driver, etc) */
+		if (!usb_new_device(dev))
+			goto done;
+
+		/* Free the configuration if there was an error */
+		usb_free_dev(dev);
+
+		/* Switch to a long reset time */
+		delay = HUB_LONG_RESET_TIME;
+	}
+
+	hub->children[port] = NULL;
+	usb_hub_port_disable(hub, port);
+done:
+	up(&usb_address0_sem);
+}
+
+static void usb_hub_events(void)
+{
+	unsigned long flags;
+	struct list_head *tmp;
+	struct usb_device *dev;
+	struct usb_hub *hub;
+	struct usb_hub_status hubsts;
+	u16 hubstatus;
+	u16 hubchange;
+	u16 portstatus;
+	u16 portchange;
+	int i, ret;
+
+	/*
+	 *  We restart the list everytime to avoid a deadlock with
+	 * deleting hubs downstream from this one. This should be
+	 * safe since we delete the hub from the event list.
+	 * Not the most efficient, but avoids deadlocks.
+	 */
+	while (1) {
+		spin_lock_irqsave(&hub_event_lock, flags);
+
+		if (list_empty(&hub_event_list))
+			break;
+
+		/* Grab the next entry from the beginning of the list */
+		tmp = hub_event_list.next;
+
+		hub = list_entry(tmp, struct usb_hub, event_list);
+		dev = hub->dev;
+
+		list_del(tmp);
+		INIT_LIST_HEAD(tmp);
+
+		down(&hub->khubd_sem); /* never blocks, we were on list */
+		spin_unlock_irqrestore(&hub_event_lock, flags);
+
+		if (hub->error) {
+			dbg("resetting hub %s for error %d",
+				dev->devpath, hub->error);
+
+			if (usb_hub_reset(hub)) {
+				err("error resetting hub %s - disconnecting",
+					dev->devpath);
+				up(&hub->khubd_sem);
+				usb_hub_disconnect(dev);
+				continue;
+			}
+
+			hub->nerrors = 0;
+			hub->error = 0;
+		}
+
+		for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
+			ret = usb_hub_port_status(dev, i, &portstatus, &portchange);
+			if (ret < 0) {
+				continue;
+			}
+
+			if (portchange & USB_PORT_STAT_C_CONNECTION) {
+				dbg("hub %s port %d connection change",
+					dev->devpath, i + 1);
+				usb_hub_port_connect_change(hub, i, portstatus, portchange);
+			} else if (portchange & USB_PORT_STAT_C_ENABLE) {
+				dbg("hub %s port %d enable change, status %x",
+					dev->devpath, i + 1, portstatus);
+				usb_clear_port_feature(dev,
+					i + 1, USB_PORT_FEAT_C_ENABLE);
+
+				/*
+				 * EM interference sometimes causes badly
+				 * shielded USB devices to be shutdown by
+				 * the hub, this hack enables them again.
+				 * Works at least with mouse driver. 
+				 */
+				if (!(portstatus & USB_PORT_STAT_ENABLE)
+				    && (portstatus & USB_PORT_STAT_CONNECTION)
+				    && (dev->children[i])) {
+					err("already running hub %s port %i "
+					    "disabled by hub (EMI?), "
+					    "re-enabling...",
+						dev->devpath, i + 1);
+					usb_hub_port_connect_change(hub,
+						i, portstatus, portchange);
+				}
+			}
+
+			if (portchange & USB_PORT_STAT_C_SUSPEND) {
+				dbg("hub %s port %d suspend change",
+					dev->devpath, i + 1);
+				usb_clear_port_feature(dev,
+					i + 1,  USB_PORT_FEAT_C_SUSPEND);
+			}
+			
+			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
+				err("hub %s port %d over-current change",
+					dev->devpath, i + 1);
+				usb_clear_port_feature(dev,
+					i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+				usb_hub_power_on(hub);
+			}
+
+			if (portchange & USB_PORT_STAT_C_RESET) {
+				dbg("hub %s port %d reset change",
+					dev->devpath, i + 1);
+				usb_clear_port_feature(dev,
+					i + 1, USB_PORT_FEAT_C_RESET);
+			}
+		} /* end for i */
+
+		/* deal with hub status changes */
+		if (usb_get_hub_status(dev, &hubsts) < 0)
+			err("get_hub_status %s failed", dev->devpath);
+		else {
+			hubstatus = le16_to_cpup(&hubsts.wHubStatus);
+			hubchange = le16_to_cpup(&hubsts.wHubChange);
+			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
+				dbg("hub %s power change", dev->devpath);
+				usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
+			}
+			if (hubchange & HUB_CHANGE_OVERCURRENT) {
+				dbg("hub %s overcurrent change", dev->devpath);
+				wait_ms(500);	/* Cool down */
+				usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
+                        	usb_hub_power_on(hub);
+			}
+		}
+		up(&hub->khubd_sem);
+        } /* end while (1) */
+
+	spin_unlock_irqrestore(&hub_event_lock, flags);
+}
+
+static int usb_hub_thread(void *__hub)
+{
+	lock_kernel();
+
+	/*
+	 * This thread doesn't need any user-level access,
+	 * so get rid of all our resources
+	 */
+
+	daemonize();
+
+	/* Setup a nice name */
+	strcpy(current->comm, "khubd");
+
+	/* Send me a signal to get me die (for debugging) */
+	do {
+		usb_hub_events();
+		interruptible_sleep_on(&khubd_wait);
+	} while (!signal_pending(current));
+
+	dbg("usb_hub_thread exiting");
+
+	unlock_kernel();
+	complete_and_exit(&khubd_exited, 0);
+}
+
+static struct usb_device_id hub_id_table [] = {
+    { match_flags: USB_DEVICE_ID_MATCH_DEV_CLASS,
+      bDeviceClass: USB_CLASS_HUB},
+    { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
+      bInterfaceClass: USB_CLASS_HUB},
+    { }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, hub_id_table);
+
+static struct usb_driver hub_driver = {
+	name:		"hub",
+	probe:		hub_probe,
+	ioctl:		hub_ioctl,
+	disconnect:	hub_disconnect,
+	id_table:	hub_id_table,
+};
+
+/*
+ * This should be a separate module.
+ */
+int usb_hub_init(void)
+{
+	int pid;
+
+	if (usb_register(&hub_driver) < 0) {
+		err("Unable to register USB hub driver");
+		return -1;
+	}
+
+	pid = kernel_thread(usb_hub_thread, NULL,
+		CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+	if (pid >= 0) {
+		khubd_pid = pid;
+
+		return 0;
+	}
+
+	/* Fall through if kernel_thread failed */
+	usb_deregister(&hub_driver);
+	err("failed to start usb_hub_thread");
+
+	return -1;
+}
+
+void usb_hub_cleanup(void)
+{
+	int ret;
+
+	/* Kill the thread */
+	ret = kill_proc(khubd_pid, SIGTERM, 1);
+
+	wait_for_completion(&khubd_exited);
+
+	/*
+	 * Hub resources are freed for us by usb_deregister. It calls
+	 * usb_driver_purge on every device which in turn calls that
+	 * devices disconnect function if it is using this driver.
+	 * The hub_disconnect function takes care of releasing the
+	 * individual hub resources. -greg
+	 */
+	usb_deregister(&hub_driver);
+} /* usb_hub_cleanup() */
+
+/*
+ * WARNING - If a driver calls usb_reset_device, you should simulate a
+ * disconnect() and probe() for other interfaces you doesn't claim. This
+ * is left up to the driver writer right now. This insures other drivers
+ * have a chance to re-setup their interface.
+ *
+ * Take a look at proc_resetdevice in devio.c for some sample code to
+ * do this.
+ */
+int usb_reset_device(struct usb_device *dev)
+{
+	struct usb_device *parent = dev->parent;
+	struct usb_device_descriptor descriptor;
+	int i, ret, port = -1;
+
+	if (!parent) {
+		err("attempting to reset root hub!");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < parent->maxchild; i++)
+		if (parent->children[i] == dev) {
+			port = i;
+			break;
+		}
+
+	if (port < 0)
+		return -ENOENT;
+
+	down(&usb_address0_sem);
+
+	/* Send a reset to the device */
+	if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) {
+		usb_hub_port_disable(parent, port);
+		up(&usb_address0_sem);
+		return(-ENODEV);
+	}
+
+	/* Reprogram the Address */
+	ret = usb_set_address(dev);
+	if (ret < 0) {
+		err("USB device not accepting new address (error=%d)", ret);
+		usb_hub_port_disable(parent, port);
+		up(&usb_address0_sem);
+		return ret;
+	}
+
+	/* Let the SET_ADDRESS settle */
+	wait_ms(10);
+
+	up(&usb_address0_sem);
+
+	/*
+	 * Now we fetch the configuration descriptors for the device and
+	 * see if anything has changed. If it has, we dump the current
+	 * parsed descriptors and reparse from scratch. Then we leave
+	 * the device alone for the caller to finish setting up.
+	 *
+	 * If nothing changed, we reprogram the configuration and then
+	 * the alternate settings.
+	 */
+	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
+			sizeof(descriptor));
+	if (ret < 0)
+		return ret;
+
+	le16_to_cpus(&descriptor.bcdUSB);
+	le16_to_cpus(&descriptor.idVendor);
+	le16_to_cpus(&descriptor.idProduct);
+	le16_to_cpus(&descriptor.bcdDevice);
+
+	if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) {
+		usb_destroy_configuration(dev);
+
+		ret = usb_get_device_descriptor(dev);
+		if (ret < sizeof(dev->descriptor)) {
+			if (ret < 0)
+				err("unable to get device %s descriptor "
+					"(error=%d)", dev->devpath, ret);
+			else
+				err("USB device %s descriptor short read "
+					"(expected %Zi, got %i)",
+					dev->devpath,
+					sizeof(dev->descriptor), ret);
+        
+			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+			dev->devnum = -1;
+			return -EIO;
+		}
+
+		ret = usb_get_configuration(dev);
+		if (ret < 0) {
+			err("unable to get configuration (error=%d)", ret);
+			usb_destroy_configuration(dev);
+			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+			dev->devnum = -1;
+			return 1;
+		}
+
+		dev->actconfig = dev->config;
+		usb_set_maxpacket(dev);
+
+		return 1;
+	}
+
+	ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
+	if (ret < 0) {
+		err("failed to set dev %s active configuration (error=%d)",
+			dev->devpath, ret);
+		return ret;
+	}
+
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+		struct usb_interface *intf = &dev->actconfig->interface[i];
+		struct usb_interface_descriptor *as;
+
+		as = &intf->altsetting[intf->act_altsetting];
+		ret = usb_set_interface(dev, as->bInterfaceNumber,
+			as->bAlternateSetting);
+		if (ret < 0) {
+			err("failed to set active alternate setting "
+				"for dev %s interface %d (error=%d)",
+				dev->devpath, i, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/hub.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,156 @@
+#ifndef __LINUX_HUB_H
+#define __LINUX_HUB_H
+
+/*
+ * Hub protocol and driver data structures.
+ *
+ * Some of these are known to the "virtual root hub" code
+ * in host controller drivers.
+ */
+
+#include <linux/list.h>
+
+/*
+ * Hub request types
+ */
+
+#define USB_RT_HUB	(USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT	(USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+/*
+ * Hub class requests
+ * See USB 2.0 spec Table 11-16
+ */
+#define HUB_CLEAR_TT_BUFFER	8
+#define HUB_RESET_TT		9
+#define HUB_GET_TT_STATE	10
+#define HUB_STOP_TT		11
+
+/*
+ * Hub Class feature numbers
+ * See USB 2.0 spec Table 11-17
+ */
+#define C_HUB_LOCAL_POWER	0
+#define C_HUB_OVER_CURRENT	1
+
+/*
+ * Port feature numbers
+ * See USB 2.0 spec Table 11-17
+ */
+#define USB_PORT_FEAT_CONNECTION	0
+#define USB_PORT_FEAT_ENABLE		1
+#define USB_PORT_FEAT_SUSPEND		2
+#define USB_PORT_FEAT_OVER_CURRENT	3
+#define USB_PORT_FEAT_RESET		4
+#define USB_PORT_FEAT_POWER		8
+#define USB_PORT_FEAT_LOWSPEED		9
+#define USB_PORT_FEAT_HIGHSPEED		10
+#define USB_PORT_FEAT_C_CONNECTION	16
+#define USB_PORT_FEAT_C_ENABLE		17
+#define USB_PORT_FEAT_C_SUSPEND		18
+#define USB_PORT_FEAT_C_OVER_CURRENT	19
+#define USB_PORT_FEAT_C_RESET		20
+#define USB_PORT_FEAT_TEST              21
+#define USB_PORT_FEAT_INDICATOR         22
+
+/* 
+ * Hub Status and Hub Change results
+ * See USB 2.0 spec Table 11-19 and Table 11-20
+ */
+struct usb_port_status {
+	__u16 wPortStatus;
+	__u16 wPortChange;	
+} __attribute__ ((packed));
+
+/* 
+ * wPortStatus bit field
+ * See USB 2.0 spec Table 11-21
+ */
+#define USB_PORT_STAT_CONNECTION	0x0001
+#define USB_PORT_STAT_ENABLE		0x0002
+#define USB_PORT_STAT_SUSPEND		0x0004
+#define USB_PORT_STAT_OVERCURRENT	0x0008
+#define USB_PORT_STAT_RESET		0x0010
+/* bits 5 to 7 are reserved */
+#define USB_PORT_STAT_POWER		0x0100
+#define USB_PORT_STAT_LOW_SPEED		0x0200
+#define USB_PORT_STAT_HIGH_SPEED        0x0400
+#define USB_PORT_STAT_TEST              0x0800
+#define USB_PORT_STAT_INDICATOR         0x1000
+/* bits 13 to 15 are reserved */
+
+/* 
+ * wPortChange bit field
+ * See USB 2.0 spec Table 11-22
+ * Bits 0 to 4 shown, bits 5 to 15 are reserved
+ */
+#define USB_PORT_STAT_C_CONNECTION	0x0001
+#define USB_PORT_STAT_C_ENABLE		0x0002
+#define USB_PORT_STAT_C_SUSPEND		0x0004
+#define USB_PORT_STAT_C_OVERCURRENT	0x0008
+#define USB_PORT_STAT_C_RESET		0x0010
+
+/*
+ * wHubCharacteristics (masks) 
+ * See USB 2.0 spec Table 11-13, offset 3
+ */
+#define HUB_CHAR_LPSM		0x0003 /* D1 .. D0 */
+#define HUB_CHAR_COMPOUND	0x0004 /* D2       */
+#define HUB_CHAR_OCPM		0x0018 /* D4 .. D3 */
+#define HUB_CHAR_TTTT           0x0060 /* D6 .. D5 */
+#define HUB_CHAR_PORTIND        0x0080 /* D7       */
+
+struct usb_hub_status {
+	__u16 wHubStatus;
+	__u16 wHubChange;
+} __attribute__ ((packed));
+
+/*
+ * Hub Status & Hub Change bit masks
+ * See USB 2.0 spec Table 11-19 and Table 11-20
+ * Bits 0 and 1 for wHubStatus and wHubChange
+ * Bits 2 to 15 are reserved for both
+ */
+#define HUB_STATUS_LOCAL_POWER	0x0001
+#define HUB_STATUS_OVERCURRENT	0x0002
+#define HUB_CHANGE_LOCAL_POWER	0x0001
+#define HUB_CHANGE_OVERCURRENT	0x0002
+
+
+/* 
+ * Hub descriptor 
+ * See USB 2.0 spec Table 11-13
+ */
+struct usb_hub_descriptor {
+	__u8  bDescLength;
+	__u8  bDescriptorType;
+	__u8  bNbrPorts;
+	__u16 wHubCharacteristics;
+	__u8  bPwrOn2PwrGood;
+	__u8  bHubContrCurrent;
+	    	/* add 1 bit for hub status change; round to bytes */
+	__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+	__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
+} __attribute__ ((packed));
+
+struct usb_device;
+
+struct usb_hub {
+	struct usb_device	*dev;		/* the "real" device */
+	struct urb		*urb;		/* for interrupt polling pipe */
+
+	/* buffer for urb ... 1 bit each for hub and children, rounded up */
+	char			buffer[(USB_MAXCHILDREN + 1 + 7) / 8];
+
+	int			error;		/* last reported error */
+	int			nerrors;	/* track consecutive errors */
+
+	struct list_head	hub_list;	/* all hubs */
+	struct list_head	event_list;	/* hubs w/data or errs ready */
+
+	struct usb_hub_descriptor *descriptor;	/* class descriptor */
+	struct semaphore	khubd_sem;
+	struct usb_tt		tt;		/* Transaction Translator */
+};
+
+#endif /* __LINUX_HUB_H */
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/inode.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,735 @@
+/*****************************************************************************/
+
+/*
+ *	inode.c  --  Inode/Dentry functions for the USB device file system.
+ *
+ *	Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *	Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  History:
+ *   0.1  04.01.2000  Created
+ *   0.2  10.12.2001  converted to use the vfs layer better
+ */
+
+/*****************************************************************************/
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
+#include <linux/smp_lock.h>
+#include <asm/byteorder.h>
+
+static struct super_operations usbfs_ops;
+static struct file_operations default_file_operations;
+static struct inode_operations usbfs_dir_inode_operations;
+static struct vfsmount *usbfs_mount;
+static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
+static int mount_count;	/* = 0 */
+
+static struct dentry *devices_dentry;
+static struct dentry *drivers_dentry;
+static int num_buses;	/* = 0 */
+
+static uid_t devuid;	/* = 0 */
+static uid_t busuid;	/* = 0 */
+static uid_t listuid;	/* = 0 */
+static gid_t devgid;	/* = 0 */
+static gid_t busgid;	/* = 0 */
+static gid_t listgid;	/* = 0 */
+static umode_t devmode = S_IWUSR | S_IRUGO;
+static umode_t busmode = S_IXUGO | S_IRUGO;
+static umode_t listmode = S_IRUGO;
+
+static int parse_options(struct super_block *s, char *data)
+{
+	char *curopt = NULL, *value;
+
+	while ((curopt = strsep(&data, ",")) != NULL) {
+		if (!*curopt)
+			continue;
+		if ((value = strchr(curopt, '=')) != NULL)
+			*value++ = 0;
+		if (!strcmp(curopt, "devuid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			devuid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "devgid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			devgid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "devmode")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "busuid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			busuid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "busgid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			busgid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "busmode")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "listuid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			listuid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "listgid")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			listgid = simple_strtoul(value, &value, 0);
+			if (*value)
+				return -EINVAL;
+		}
+		if (!strcmp(curopt, "listmode")) {
+			if (!value || !value[0])
+				return -EINVAL;
+			listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+			if (*value)
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+
+/* --------------------------------------------------------------------- */
+
+static struct inode *usbfs_get_inode (struct super_block *sb, int mode, int dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_rdev = NODEV;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+		case S_IFREG:
+			inode->i_fop = &default_file_operations;
+			break;
+		case S_IFDIR:
+			inode->i_op = &usbfs_dir_inode_operations;
+			inode->i_fop = &simple_dir_operations;
+			break;
+		}
+	}
+	return inode; 
+}
+
+/* SMP-safe */
+static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
+			int dev)
+{
+	struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev);
+	int error = -ENOSPC;
+
+	if (inode) {
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
+{
+	return usbfs_mknod (dir, dentry, mode | S_IFDIR, 0);
+}
+
+static int usbfs_create (struct inode *dir, struct dentry *dentry, int mode)
+{
+ 	return usbfs_mknod (dir, dentry, mode | S_IFREG, 0);
+}
+
+static inline int usbfs_positive (struct dentry *dentry)
+{
+	return dentry->d_inode && !d_unhashed(dentry);
+}
+
+static int usbfs_empty (struct dentry *dentry)
+{
+	struct list_head *list;
+
+	spin_lock(&dcache_lock);
+
+	list_for_each(list, &dentry->d_subdirs) {
+		struct dentry *de = list_entry(list, struct dentry, d_child);
+		if (usbfs_positive(de)) {
+			spin_unlock(&dcache_lock);
+			return 0;
+		}
+	}
+
+	spin_unlock(&dcache_lock);
+	return 1;
+}
+
+static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
+{
+	int error = -ENOTEMPTY;
+
+	if (usbfs_empty(dentry)) {
+		struct inode *inode = dentry->d_inode;
+
+		lock_kernel();
+		inode->i_nlink--;
+		unlock_kernel();
+		dput(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+#define usbfs_rmdir usbfs_unlink
+
+/* default file operations */
+static ssize_t default_read_file (struct file *file, char *buf,
+				  size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static ssize_t default_write_file (struct file *file, const char *buf,
+				   size_t count, loff_t *ppos)
+{
+	return count;
+}
+
+static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
+{
+	loff_t retval = -EINVAL;
+
+	lock_kernel();
+	switch(orig) {
+	case 0:
+		if (offset > 0) {
+			file->f_pos = offset;
+			retval = file->f_pos;
+		} 
+		break;
+	case 1:
+		if ((offset + file->f_pos) > 0) {
+			file->f_pos += offset;
+			retval = file->f_pos;
+		} 
+		break;
+	default:
+		break;
+	}
+	unlock_kernel();
+	return retval;
+}
+
+static int default_open (struct inode *inode, struct file *filp)
+{
+	if (inode->u.generic_ip)
+		filp->private_data = inode->u.generic_ip;
+
+	return 0;
+}
+
+static struct file_operations default_file_operations = {
+	read:		default_read_file,
+	write:		default_write_file,
+	open:		default_open,
+	llseek:		default_file_lseek,
+};
+
+static struct inode_operations usbfs_dir_inode_operations = {
+	create:		usbfs_create,
+	lookup:		simple_lookup,
+	unlink:		usbfs_unlink,
+	mkdir:		usbfs_mkdir,
+	rmdir:		usbfs_rmdir,
+};
+
+static struct super_operations usbfs_ops = {
+	statfs:		simple_statfs,
+	put_inode:	force_delete,
+};
+
+static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *inode;
+	struct dentry *root;
+
+	if (parse_options(sb, data)) {
+		warn("usbfs: mount parameter error:");
+		return -EINVAL;
+	}
+
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = USBDEVICE_SUPER_MAGIC;
+	sb->s_op = &usbfs_ops;
+	inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
+
+	if (!inode) {
+		dbg("%s: could not get inode!\n",__FUNCTION__);
+		return -ENOMEM;
+	}
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		dbg("%s: could not get root dentry!\n",__FUNCTION__);
+		iput(inode);
+		return -ENOMEM;
+	}
+	sb->s_root = root;
+	return 0;
+}
+
+/**
+ * fs_create_by_name - create a file, given a name
+ * @name:	name of file
+ * @mode:	type of file
+ * @parent:	dentry of directory to create it in
+ * @dentry:	resulting dentry of file
+ *
+ * There is a bit of overhead in creating a file - basically, we 
+ * have to hash the name of the file, then look it up. This will
+ * prevent files of the same name. 
+ * We then call the proper vfs_ function to take care of all the 
+ * file creation details. 
+ * This function handles both regular files and directories.
+ */
+static int fs_create_by_name (const char *name, mode_t mode,
+			      struct dentry *parent, struct dentry **dentry)
+{
+	struct dentry *d = NULL;
+	struct qstr qstr;
+	int error;
+
+	/* If the parent is not specified, we create it in the root.
+	 * We need the root dentry to do this, which is in the super 
+	 * block. A pointer to that is in the struct vfsmount that we
+	 * have around.
+	 */
+	if (!parent ) {
+		if (usbfs_mount && usbfs_mount->mnt_sb) {
+			parent = usbfs_mount->mnt_sb->s_root;
+		}
+	}
+
+	if (!parent) {
+		dbg("Ah! can not find a parent!\n");
+		return -EFAULT;
+	}
+
+	*dentry = NULL;
+	qstr.name = name;
+	qstr.len = strlen(name);
+ 	qstr.hash = full_name_hash(name,qstr.len);
+
+	parent = dget(parent);
+
+	down(&parent->d_inode->i_sem);
+
+	d = lookup_hash(&qstr,parent);
+
+	error = PTR_ERR(d);
+	if (!IS_ERR(d)) {
+		switch(mode & S_IFMT) {
+			case 0: 
+			case S_IFREG:
+				error = vfs_create(parent->d_inode,d,mode);
+				break;
+			case S_IFDIR:
+				error = vfs_mkdir(parent->d_inode,d,mode);
+				break;
+			default:
+				err("cannot create special files\n");
+		}
+		*dentry = d;
+	}
+	up(&parent->d_inode->i_sem);
+
+	dput(parent);
+	return error;
+}
+
+static struct dentry *fs_create_file (const char *name, mode_t mode,
+				      struct dentry *parent, void *data,
+				      struct file_operations *fops,
+				      uid_t uid, gid_t gid)
+{
+	struct dentry *dentry;
+	int error;
+
+	dbg("creating file '%s'\n",name);
+
+	error = fs_create_by_name(name,mode,parent,&dentry);
+	if (error) {
+		dentry = NULL;
+	} else {
+		if (dentry->d_inode) {
+			if (data)
+				dentry->d_inode->u.generic_ip = data;
+			if (fops)
+				dentry->d_inode->i_fop = fops;
+			dentry->d_inode->i_uid = uid;
+			dentry->d_inode->i_gid = gid;
+		}
+	}
+
+	return dentry;
+}
+
+static void fs_remove_file (struct dentry *dentry)
+{
+	struct dentry *parent = dentry->d_parent;
+	
+	if (!parent || !parent->d_inode)
+		return;
+
+	down(&parent->d_inode->i_sem);
+	if (usbfs_positive(dentry)) {
+		if (dentry->d_inode) {
+			if (S_ISDIR(dentry->d_inode->i_mode))
+				vfs_rmdir(parent->d_inode,dentry);
+			else
+				vfs_unlink(parent->d_inode,dentry);
+		}
+
+		dput(dentry);
+	}
+	up(&parent->d_inode->i_sem);
+}
+
+/* --------------------------------------------------------------------- */
+
+
+
+/*
+ * The usbdevfs name is now deprecated (as of 2.5.1).
+ * It will be removed when the 2.7.x development cycle is started.
+ * You have been warned :)
+ */
+
+static struct super_block *usb_get_sb(struct file_system_type *fs_type,
+	int flags, char *dev_name, void *data)
+{
+	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
+}
+
+static struct file_system_type usbdevice_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"usbdevfs",
+	get_sb:		usb_get_sb,
+	kill_sb:	kill_anon_super,
+};
+
+static struct file_system_type usb_fs_type = {
+	owner:		THIS_MODULE,
+	name:		"usbfs",
+	get_sb:		usb_get_sb,
+	kill_sb:	kill_anon_super,
+};
+
+/* --------------------------------------------------------------------- */
+static int get_mount (void)
+{
+	struct vfsmount *mnt;
+
+	spin_lock (&mount_lock);
+	if (usbfs_mount) {
+		mntget(usbfs_mount);
+		++mount_count;
+		spin_unlock (&mount_lock);
+		goto go_ahead;
+	}
+
+	spin_unlock (&mount_lock);
+	mnt = kern_mount (&usbdevice_fs_type);
+	if (IS_ERR(mnt)) {
+		err ("could not mount the fs...erroring out!\n");
+		return -ENODEV;
+	}
+	spin_lock (&mount_lock);
+	if (!usbfs_mount) {
+		usbfs_mount = mnt;
+		++mount_count;
+		spin_unlock (&mount_lock);
+		goto go_ahead;
+	}
+	mntget(usbfs_mount);
+	++mount_count;
+	spin_unlock (&mount_lock);
+	mntput(mnt);
+
+go_ahead:
+	dbg("mount_count = %d\n", mount_count);
+	return 0;
+}
+
+static void remove_mount (void)
+{
+	struct vfsmount *mnt;
+
+	spin_lock (&mount_lock);
+	mnt = usbfs_mount;
+	--mount_count;
+	if (!mount_count)
+		usbfs_mount = NULL;
+
+	spin_unlock (&mount_lock);
+	mntput(mnt);
+	dbg("mount_count = %d\n", mount_count);
+}
+
+static int create_special_files (void)
+{
+	int retval;
+
+	/* create the devices and drivers special files */
+	retval = get_mount ();
+	if (retval)
+		return retval;
+	devices_dentry = fs_create_file ("devices",
+					 listmode | S_IFREG,
+					 NULL, NULL,
+					 &usbdevfs_devices_fops,
+					 listuid, listgid);
+	if (devices_dentry == NULL) {
+		err ("Unable to create devices usbfs file");
+		return -ENODEV;
+	}
+
+	drivers_dentry = fs_create_file ("drivers",
+					 listmode | S_IFREG,
+					 NULL, NULL,
+					 &usbdevfs_drivers_fops,
+					 listuid, listgid);
+	if (drivers_dentry == NULL) {
+		err ("Unable to create drivers usbfs file");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void remove_special_files (void)
+{
+	if (devices_dentry)
+		fs_remove_file (devices_dentry);
+	if (drivers_dentry)
+		fs_remove_file (drivers_dentry);
+	devices_dentry = NULL;
+	drivers_dentry = NULL;
+	remove_mount();
+}
+
+void usbfs_update_special (void)
+{
+	struct inode *inode;
+
+	if (devices_dentry) {
+		inode = devices_dentry->d_inode;
+		if (inode)
+			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	}
+	if (drivers_dentry) {
+		inode = devices_dentry->d_inode;
+		if (inode)
+			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	}
+}
+
+void usbfs_add_bus(struct usb_bus *bus)
+{
+	char name[8];
+	int retval;
+
+	/* create the special files if this is the first bus added */
+	if (num_buses == 0) {
+		retval = create_special_files();
+		if (retval)
+			return;
+	}
+	++num_buses;
+
+	sprintf (name, "%03d", bus->busnum);
+	bus->dentry = fs_create_file (name,
+				      busmode | S_IFDIR,
+				      NULL, bus, NULL,
+				      busuid, busgid);
+	if (bus->dentry == NULL)
+		return;
+
+	usbfs_update_special();
+	usbdevfs_conn_disc_event();
+}
+
+
+void usbfs_remove_bus(struct usb_bus *bus)
+{
+	if (bus->dentry) {
+		fs_remove_file (bus->dentry);
+		bus->dentry = NULL;
+	}
+
+	--num_buses;
+	if (num_buses <= 0) {
+		remove_special_files();
+		num_buses = 0;
+	}
+
+	usbfs_update_special();
+	usbdevfs_conn_disc_event();
+}
+
+void usbfs_add_device(struct usb_device *dev)
+{
+	char name[8];
+	int i;
+	int i_size;
+
+	sprintf (name, "%03d", dev->devnum);
+	dev->dentry = fs_create_file (name,
+				      devmode | S_IFREG,
+				      dev->bus->dentry, dev,
+				      &usbdevfs_device_file_operations,
+				      devuid, devgid);
+	if (dev->dentry == NULL)
+		return;
+
+	/* Set the size of the device's file to be
+	 * equal to the size of the device descriptors. */
+	i_size = sizeof (struct usb_device_descriptor);
+	for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) {
+		struct usb_config_descriptor *config =
+			(struct usb_config_descriptor *)dev->rawdescriptors[i];
+		i_size += le16_to_cpu (config->wTotalLength);
+	}
+	if (dev->dentry->d_inode)
+		dev->dentry->d_inode->i_size = i_size;
+
+	usbfs_update_special();
+	usbdevfs_conn_disc_event();
+}
+
+void usbfs_remove_device(struct usb_device *dev)
+{
+	struct dev_state *ds;
+	struct siginfo sinfo;
+
+	if (dev->dentry) {
+		fs_remove_file (dev->dentry);
+		dev->dentry = NULL;
+	}
+	while (!list_empty(&dev->filelist)) {
+		ds = list_entry(dev->filelist.next, struct dev_state, list);
+		list_del(&ds->list);
+		INIT_LIST_HEAD(&ds->list);
+		down_write(&ds->devsem);
+		ds->dev = NULL;
+		up_write(&ds->devsem);
+		if (ds->discsignr) {
+			sinfo.si_signo = SIGPIPE;
+			sinfo.si_errno = EPIPE;
+			sinfo.si_code = SI_ASYNCIO;
+			sinfo.si_addr = ds->disccontext;
+			send_sig_info(ds->discsignr, &sinfo, ds->disctask);
+		}
+	}
+	usbfs_update_special();
+	usbdevfs_conn_disc_event();
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef CONFIG_PROC_FS		
+static struct proc_dir_entry *usbdir = NULL;
+#endif	
+
+int __init usbfs_init(void)
+{
+	int retval;
+
+	retval = usb_register(&usbdevfs_driver);
+	if (retval)
+		return retval;
+
+	retval = register_filesystem(&usb_fs_type);
+	if (retval) {
+		usb_deregister(&usbdevfs_driver);
+		return retval;
+	}
+	retval = register_filesystem(&usbdevice_fs_type);
+	if (retval) {
+		unregister_filesystem(&usb_fs_type);
+		usb_deregister(&usbdevfs_driver);
+		return retval;
+	}
+
+#ifdef CONFIG_PROC_FS		
+	/* create mount point for usbdevfs */
+	usbdir = proc_mkdir("usb", proc_bus);
+#endif	
+
+	return 0;
+}
+
+void __exit usbfs_cleanup(void)
+{
+	usb_deregister(&usbdevfs_driver);
+	unregister_filesystem(&usb_fs_type);
+	unregister_filesystem(&usbdevice_fs_type);
+#ifdef CONFIG_PROC_FS	
+	if (usbdir)
+		remove_proc_entry("usb", proc_bus);
+#endif
+}
+
diff -Nru a/drivers/usb/core/usb-debug.c b/drivers/usb/core/usb-debug.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/usb-debug.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,203 @@
+/*
+ * debug.c - USB debug helper routines.
+ *
+ * I just want these out of the way where they aren't in your
+ * face, but so that you can still use them..
+ */
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)
+{
+	usb_show_endpoint_descriptor(endpoint);
+}
+
+static void usb_show_interface(struct usb_interface_descriptor *altsetting)
+{
+	int i;
+
+	usb_show_interface_descriptor(altsetting);
+
+	for (i = 0; i < altsetting->bNumEndpoints; i++)
+		usb_show_endpoint(altsetting->endpoint + i);
+}
+
+static void usb_show_config(struct usb_config_descriptor *config)
+{
+	int i, j;
+	struct usb_interface *ifp;
+
+	usb_show_config_descriptor(config);
+	for (i = 0; i < config->bNumInterfaces; i++) {
+		ifp = config->interface + i;
+
+		if (!ifp)
+			break;
+
+		printk("\n  Interface: %d\n", i);
+		for (j = 0; j < ifp->num_altsetting; j++)
+			usb_show_interface(ifp->altsetting + j);
+	}
+}
+
+void usb_show_device(struct usb_device *dev)
+{
+	int i;
+
+	usb_show_device_descriptor(&dev->descriptor);
+	for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
+		usb_show_config(dev->config + i);
+}
+
+/*
+ * Parse and show the different USB descriptors.
+ */
+void usb_show_device_descriptor(struct usb_device_descriptor *desc)
+{
+	if (!desc)
+	{
+		printk("Invalid USB device descriptor (NULL POINTER)\n");
+		return;
+	}
+	printk("  Length              = %2d%s\n", desc->bLength,
+		desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
+	printk("  DescriptorType      = %02x\n", desc->bDescriptorType);
+
+	printk("  USB version         = %x.%02x\n",
+		desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
+	printk("  Vendor:Product      = %04x:%04x\n",
+		desc->idVendor, desc->idProduct);
+	printk("  MaxPacketSize0      = %d\n", desc->bMaxPacketSize0);
+	printk("  NumConfigurations   = %d\n", desc->bNumConfigurations);
+	printk("  Device version      = %x.%02x\n",
+		desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
+
+	printk("  Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
+		desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
+	switch (desc->bDeviceClass) {
+	case 0:
+		printk("    Per-interface classes\n");
+		break;
+	case USB_CLASS_AUDIO:
+		printk("    Audio device class\n");
+		break;
+	case USB_CLASS_COMM:
+		printk("    Communications class\n");
+		break;
+	case USB_CLASS_HID:
+		printk("    Human Interface Devices class\n");
+		break;
+	case USB_CLASS_PRINTER:
+		printk("    Printer device class\n");
+		break;
+	case USB_CLASS_MASS_STORAGE:
+		printk("    Mass Storage device class\n");
+		break;
+	case USB_CLASS_HUB:
+		printk("    Hub device class\n");
+		break;
+	case USB_CLASS_VENDOR_SPEC:
+		printk("    Vendor class\n");
+		break;
+	default:
+		printk("    Unknown class\n");
+	}
+}
+
+void usb_show_config_descriptor(struct usb_config_descriptor *desc)
+{
+	printk("Configuration:\n");
+	printk("  bLength             = %4d%s\n", desc->bLength,
+		desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
+	printk("  bDescriptorType     =   %02x\n", desc->bDescriptorType);
+	printk("  wTotalLength        = %04x\n", desc->wTotalLength);
+	printk("  bNumInterfaces      =   %02x\n", desc->bNumInterfaces);
+	printk("  bConfigurationValue =   %02x\n", desc->bConfigurationValue);
+	printk("  iConfiguration      =   %02x\n", desc->iConfiguration);
+	printk("  bmAttributes        =   %02x\n", desc->bmAttributes);
+	printk("  MaxPower            = %4dmA\n", desc->MaxPower * 2);
+}
+
+void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
+{
+	printk("  Alternate Setting: %2d\n", desc->bAlternateSetting);
+	printk("    bLength             = %4d%s\n", desc->bLength,
+		desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
+	printk("    bDescriptorType     =   %02x\n", desc->bDescriptorType);
+	printk("    bInterfaceNumber    =   %02x\n", desc->bInterfaceNumber);
+	printk("    bAlternateSetting   =   %02x\n", desc->bAlternateSetting);
+	printk("    bNumEndpoints       =   %02x\n", desc->bNumEndpoints);
+	printk("    bInterface Class:SubClass:Protocol =   %02x:%02x:%02x\n",
+		desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol);
+	printk("    iInterface          =   %02x\n", desc->iInterface);
+}
+
+void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
+{
+	char *LengthCommentString = (desc->bLength ==
+		USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
+		USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
+	char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
+
+	printk("    Endpoint:\n");
+	printk("      bLength             = %4d%s\n",
+		desc->bLength, LengthCommentString);
+	printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
+	printk("      bEndpointAddress    =   %02x (%s)\n", desc->bEndpointAddress,
+		(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+			USB_ENDPOINT_XFER_CONTROL ? "i/o" :
+		(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out");
+	printk("      bmAttributes        =   %02x (%s)\n", desc->bmAttributes,
+		EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]);
+	printk("      wMaxPacketSize      = %04x\n", desc->wMaxPacketSize);
+	printk("      bInterval           =   %02x\n", desc->bInterval);
+
+	/* Audio extensions to the endpoint descriptor */
+	if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
+		printk("      bRefresh            =   %02x\n", desc->bRefresh);
+		printk("      bSynchAddress       =   %02x\n", desc->bSynchAddress);
+	}
+}
+
+void usb_show_string(struct usb_device *dev, char *id, int index)
+{
+	char *buf;
+
+	if (!index)
+		return;
+	if (!(buf = kmalloc(256, GFP_KERNEL)))
+		return;
+	if (usb_string(dev, index, buf, 256) > 0)
+		printk(KERN_INFO "%s: %s\n", id, buf);
+	kfree(buf);
+}
+
+void usb_dump_urb (struct urb *urb)
+{
+	printk ("urb                   :%p\n", urb);
+	printk ("next                  :%p\n", urb->next);
+	printk ("dev                   :%p\n", urb->dev);
+	printk ("pipe                  :%08X\n", urb->pipe);
+	printk ("status                :%d\n", urb->status);
+	printk ("transfer_flags        :%08X\n", urb->transfer_flags);
+	printk ("transfer_buffer       :%p\n", urb->transfer_buffer);
+	printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
+	printk ("actual_length         :%d\n", urb->actual_length);
+	printk ("setup_packet          :%p\n", urb->setup_packet);
+	printk ("start_frame           :%d\n", urb->start_frame);
+	printk ("number_of_packets     :%d\n", urb->number_of_packets);
+	printk ("interval              :%d\n", urb->interval);
+	printk ("error_count           :%d\n", urb->error_count);
+	printk ("context               :%p\n", urb->context);
+	printk ("complete              :%p\n", urb->complete);
+}
+
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/core/usb.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,2711 @@
+/*
+ * drivers/usb/usb.c
+ *
+ * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999-2001
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
+ * (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ * (C) Copyright Randy Dunlap 2000
+ * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
+ 	more docs, etc)
+ * (C) Copyright Yggdrasil Computing, Inc. 2000
+ *     (usb_device_id matching changes by Adam J. Richter)
+ *
+ * NOTE! This is not actually a driver at all, rather this is
+ * just a collection of helper routines that implement the
+ * generic USB things that the real drivers can use..
+ *
+ * Think of this as a "USB library" rather than anything else.
+ * It should be considered a slave, with no callbacks. Callbacks
+ * are evil.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>  /* for in_interrupt() */
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/spinlock.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "hcd.h"
+
+extern int  usb_hub_init(void);
+extern void usb_hub_cleanup(void);
+
+/*
+ * Prototypes for the device driver probing/loading functions
+ */
+static void usb_find_drivers(struct usb_device *);
+static int  usb_find_interface_driver(struct usb_device *, unsigned int);
+static void usb_check_support(struct usb_device *);
+
+/*
+ * We have a per-interface "registered driver" list.
+ */
+LIST_HEAD(usb_driver_list);
+
+devfs_handle_t usb_devfs_handle;	/* /dev/usb dir. */
+
+static struct usb_driver *usb_minors[16];
+
+/**
+ *	usb_register - register a USB driver
+ *	@new_driver: USB operations for the driver
+ *
+ *	Registers a USB driver with the USB core.  The list of unattached
+ *	interfaces will be rescanned whenever a new driver is added, allowing
+ *	the new driver to attach to any recognized devices.
+ *	Returns a negative error code on failure and 0 on success.
+ */
+int usb_register(struct usb_driver *new_driver)
+{
+	if (new_driver->fops != NULL) {
+		if (usb_minors[new_driver->minor/16]) {
+			 err("error registering %s driver", new_driver->name);
+			return -EINVAL;
+		}
+		usb_minors[new_driver->minor/16] = new_driver;
+	}
+
+	info("registered new driver %s", new_driver->name);
+
+	init_MUTEX(&new_driver->serialize);
+
+	/* Add it to the list of known drivers */
+	list_add_tail(&new_driver->driver_list, &usb_driver_list);
+
+	usb_scan_devices();
+
+	usbfs_update_special();
+
+	return 0;
+}
+
+/**
+ *	usb_scan_devices - scans all unclaimed USB interfaces
+ *	Context: !in_interrupt ()
+ *
+ *	Goes through all unclaimed USB interfaces, and offers them to all
+ *	registered USB drivers through the 'probe' function.
+ *	This will automatically be called after usb_register is called.
+ *	It is called by some of the subsystems layered over USB
+ *	after one of their subdrivers are registered.
+ */
+void usb_scan_devices(void)
+{
+	struct list_head *tmp;
+
+	down (&usb_bus_list_lock);
+	tmp = usb_bus_list.next;
+	while (tmp != &usb_bus_list) {
+		struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
+
+		tmp = tmp->next;
+		usb_check_support(bus->root_hub);
+	}
+	up (&usb_bus_list_lock);
+}
+
+/*
+ * This function is part of a depth-first search down the device tree,
+ * removing any instances of a device driver.
+ */
+static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
+{
+	int i;
+
+	if (!dev) {
+		err("null device being purged!!!");
+		return;
+	}
+
+	for (i=0; i<USB_MAXCHILDREN; i++)
+		if (dev->children[i])
+			usb_drivers_purge(driver, dev->children[i]);
+
+	if (!dev->actconfig)
+		return;
+			
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+		struct usb_interface *interface = &dev->actconfig->interface[i];
+		
+		if (interface->driver == driver) {
+			if (driver->owner)
+				__MOD_INC_USE_COUNT(driver->owner);
+			down(&driver->serialize);
+			driver->disconnect(dev, interface->private_data);
+			up(&driver->serialize);
+			if (driver->owner)
+				__MOD_DEC_USE_COUNT(driver->owner);
+			/* if driver->disconnect didn't release the interface */
+			if (interface->driver)
+				usb_driver_release_interface(driver, interface);
+			/*
+			 * This will go through the list looking for another
+			 * driver that can handle the device
+			 */
+			usb_find_interface_driver(dev, i);
+		}
+	}
+}
+
+/**
+ *	usb_deregister - unregister a USB driver
+ *	@driver: USB operations of the driver to unregister
+ *	Context: !in_interrupt ()
+ *
+ *	Unlinks the specified driver from the internal USB driver list.
+ */
+void usb_deregister(struct usb_driver *driver)
+{
+	struct list_head *tmp;
+
+	info("deregistering driver %s", driver->name);
+	if (driver->fops != NULL)
+		usb_minors[driver->minor/16] = NULL;
+
+	/*
+	 * first we remove the driver, to be sure it doesn't get used by
+	 * another thread while we are stepping through removing entries
+	 */
+	list_del(&driver->driver_list);
+
+	down (&usb_bus_list_lock);
+	tmp = usb_bus_list.next;
+	while (tmp != &usb_bus_list) {
+		struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
+
+		tmp = tmp->next;
+		usb_drivers_purge(driver, bus->root_hub);
+	}
+	up (&usb_bus_list_lock);
+
+	usbfs_update_special();
+}
+
+/**
+ * usb_ifnum_to_ifpos - convert the interface number to the interface position
+ * @dev: the device to use
+ * @ifnum: the interface number (bInterfaceNumber); not interface position
+ *
+ * This is used to convert the interface _number_ (as in
+ * interface.bInterfaceNumber) to the interface _position_ (as in
+ * dev->actconfig->interface + position).  Note that the number is the same as
+ * the position for all interfaces _except_ devices with interfaces not
+ * sequentially numbered (e.g., 0, 2, 3, etc).
+ */
+int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum)
+{
+	int i;
+
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+		if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)
+			return i;
+
+	return -EINVAL;
+}
+
+/**
+ * usb_ifnum_to_if - get the interface object with a given interface number
+ * @dev: the device whose current configuration is considered
+ * @ifnum: the desired interface
+ *
+ * This walks the device descriptor for the currently active configuration
+ * and returns a pointer to the interface with that particular interface
+ * number, or null.
+ *
+ * Note that configuration descriptors are not required to assign interface
+ * numbers sequentially, so that it would be incorrect to assume that
+ * the first interface in that descriptor corresponds to interface zero.
+ * This routine helps device drivers avoid such mistakes.
+ * However, you should make sure that you do the right thing with any
+ * alternate settings available for this interfaces.
+ */
+struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
+{
+	int i;
+
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+		if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)
+			return &dev->actconfig->interface[i];
+
+	return NULL;
+}
+
+/**
+ * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
+ * @dev: the device whose current configuration is considered
+ * @epnum: the desired endpoint
+ *
+ * This walks the device descriptor for the currently active configuration,
+ * and returns a pointer to the endpoint with that particular endpoint
+ * number, or null.
+ *
+ * Note that interface descriptors are not required to assign endpont
+ * numbers sequentially, so that it would be incorrect to assume that
+ * the first endpoint in that descriptor corresponds to interface zero.
+ * This routine helps device drivers avoid such mistakes.
+ */
+struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
+{
+	int i, j, k;
+
+	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+		for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++)
+			for (k = 0; k < dev->actconfig->interface[i].altsetting[j].bNumEndpoints; k++)
+				if (epnum == dev->actconfig->interface[i].altsetting[j].endpoint[k].bEndpointAddress)
+					return &dev->actconfig->interface[i].altsetting[j].endpoint[k];
+
+	return NULL;
+}
+
+/*
+ * This function is for doing a depth-first search for devices which
+ * have support, for dynamic loading of driver modules.
+ */
+static void usb_check_support(struct usb_device *dev)
+{
+	int i;
+
+	if (!dev) {
+		err("null device being checked!!!");
+		return;
+	}
+
+	for (i=0; i<USB_MAXCHILDREN; i++)
+		if (dev->children[i])
+			usb_check_support(dev->children[i]);
+
+	if (!dev->actconfig)
+		return;
+
+	/* now we check this device */
+	if (dev->devnum > 0)
+		for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+			usb_find_interface_driver(dev, i);
+}
+
+
+/**
+ * usb_driver_claim_interface - bind a driver to an interface
+ * @driver: the driver to be bound
+ * @iface: the interface to which it will be bound
+ * @priv: driver data associated with that interface
+ *
+ * This is used by usb device drivers that need to claim more than one
+ * interface on a device when probing (audio and acm are current examples).
+ * No device driver should directly modify internal usb_interface or
+ * usb_device structure members.
+ *
+ * Few drivers should need to use this routine, since the most natural
+ * way to bind to an interface is to return the private data from
+ * the driver's probe() method.  Any driver that does use this must
+ * first be sure that no other driver has claimed the interface, by
+ * checking with usb_interface_claimed().
+ */
+void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
+{
+	if (!iface || !driver)
+		return;
+
+	// FIXME change API to report an error in this case
+	if (iface->driver)
+	    err ("%s driver booted %s off interface %p",
+	    	driver->name, iface->driver->name, iface);
+	else
+	    dbg("%s driver claimed interface %p", driver->name, iface);
+
+	iface->driver = driver;
+	iface->private_data = priv;
+} /* usb_driver_claim_interface() */
+
+/**
+ * usb_interface_claimed - returns true iff an interface is claimed
+ * @iface: the interface being checked
+ *
+ * This should be used by drivers to check other interfaces to see if
+ * they are available or not.  If another driver has claimed the interface,
+ * they may not claim it.  Otherwise it's OK to claim it using
+ * usb_driver_claim_interface().
+ *
+ * Returns true (nonzero) iff the interface is claimed, else false (zero).
+ */
+int usb_interface_claimed(struct usb_interface *iface)
+{
+	if (!iface)
+		return 0;
+
+	return (iface->driver != NULL);
+} /* usb_interface_claimed() */
+
+/**
+ * usb_driver_release_interface - unbind a driver from an interface
+ * @driver: the driver to be unbound
+ * @iface: the interface from which it will be unbound
+ * 
+ * This should be used by drivers to release their claimed interfaces.
+ * It is normally called in their disconnect() methods, and only for
+ * drivers that bound to more than one interface in their probe().
+ *
+ * When the USB subsystem disconnect()s a driver from some interface,
+ * it automatically invokes this method for that interface.  That
+ * means that even drivers that used usb_driver_claim_interface()
+ * usually won't need to call this.
+ */
+void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
+{
+	/* this should never happen, don't release something that's not ours */
+	if (!iface || iface->driver != driver)
+		return;
+
+	iface->driver = NULL;
+	iface->private_data = NULL;
+}
+
+
+/**
+ * usb_match_id - find first usb_device_id matching device or interface
+ * @dev: the device whose descriptors are considered when matching
+ * @interface: the interface of interest
+ * @id: array of usb_device_id structures, terminated by zero entry
+ *
+ * usb_match_id searches an array of usb_device_id's and returns
+ * the first one matching the device or interface, or null.
+ * This is used when binding (or rebinding) a driver to an interface.
+ * Most USB device drivers will use this indirectly, through the usb core,
+ * but some layered driver frameworks use it directly.
+ * These device tables are exported with MODULE_DEVICE_TABLE, through
+ * modutils and "modules.usbmap", to support the driver loading
+ * functionality of USB hotplugging.
+ *
+ * What Matches:
+ *
+ * The "match_flags" element in a usb_device_id controls which
+ * members are used.  If the corresponding bit is set, the
+ * value in the device_id must match its corresponding member
+ * in the device or interface descriptor, or else the device_id
+ * does not match.
+ *
+ * "driver_info" is normally used only by device drivers,
+ * but you can create a wildcard "matches anything" usb_device_id
+ * as a driver's "modules.usbmap" entry if you provide an id with
+ * only a nonzero "driver_info" field.  If you do this, the USB device
+ * driver's probe() routine should use additional intelligence to
+ * decide whether to bind to the specified interface.
+ * 
+ * What Makes Good usb_device_id Tables:
+ *
+ * The match algorithm is very simple, so that intelligence in
+ * driver selection must come from smart driver id records.
+ * Unless you have good reasons to use another selection policy,
+ * provide match elements only in related groups, and order match
+ * specifiers from specific to general.  Use the macros provided
+ * for that purpose if you can.
+ *
+ * The most specific match specifiers use device descriptor
+ * data.  These are commonly used with product-specific matches;
+ * the USB_DEVICE macro lets you provide vendor and product IDs,
+ * and you can also match against ranges of product revisions.
+ * These are widely used for devices with application or vendor
+ * specific bDeviceClass values.
+ *
+ * Matches based on device class/subclass/protocol specifications
+ * are slightly more general; use the USB_DEVICE_INFO macro, or
+ * its siblings.  These are used with single-function devices
+ * where bDeviceClass doesn't specify that each interface has
+ * its own class. 
+ *
+ * Matches based on interface class/subclass/protocol are the
+ * most general; they let drivers bind to any interface on a
+ * multiple-function device.  Use the USB_INTERFACE_INFO
+ * macro, or its siblings, to match class-per-interface style 
+ * devices (as recorded in bDeviceClass).
+ *  
+ * Within those groups, remember that not all combinations are
+ * meaningful.  For example, don't give a product version range
+ * without vendor and product IDs; or specify a protocol without
+ * its associated class and subclass.
+ */   
+const struct usb_device_id *
+usb_match_id(struct usb_device *dev, struct usb_interface *interface,
+	     const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor	*intf = 0;
+
+	/* proc_connectinfo in devio.c may call us with id == NULL. */
+	if (id == NULL)
+		return NULL;
+
+	/* It is important to check that id->driver_info is nonzero,
+	   since an entry that is all zeroes except for a nonzero
+	   id->driver_info is the way to create an entry that
+	   indicates that the driver want to examine every
+	   device and interface. */
+	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+	       id->driver_info; id++) {
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+		    id->idVendor != dev->descriptor.idVendor)
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+		    id->idProduct != dev->descriptor.idProduct)
+			continue;
+
+		/* No need to test id->bcdDevice_lo != 0, since 0 is never
+		   greater than any unsigned number. */
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+		    (id->bcdDevice_lo > dev->descriptor.bcdDevice))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+		    (id->bcdDevice_hi < dev->descriptor.bcdDevice))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+		    (id->bDeviceClass != dev->descriptor.bDeviceClass))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+			continue;
+
+		intf = &interface->altsetting [interface->act_altsetting];
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
+		    (id->bInterfaceClass != intf->bInterfaceClass))
+			continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
+		    (id->bInterfaceSubClass != intf->bInterfaceSubClass))
+		    continue;
+
+		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
+		    (id->bInterfaceProtocol != intf->bInterfaceProtocol))
+		    continue;
+
+		return id;
+	}
+
+	return NULL;
+}
+
+/*
+ * This entrypoint gets called for each new device.
+ *
+ * We now walk the list of registered USB drivers,
+ * looking for one that will accept this interface.
+ *
+ * "New Style" drivers use a table describing the devices and interfaces
+ * they handle.  Those tables are available to user mode tools deciding
+ * whether to load driver modules for a new device.
+ *
+ * The probe return value is changed to be a private pointer.  This way
+ * the drivers don't have to dig around in our structures to set the
+ * private pointer if they only need one interface. 
+ *
+ * Returns: 0 if a driver accepted the interface, -1 otherwise
+ */
+static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
+{
+	struct list_head *tmp;
+	struct usb_interface *interface;
+	void *private;
+	const struct usb_device_id *id;
+	struct usb_driver *driver;
+	int i;
+	
+	if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
+		err("bad find_interface_driver params");
+		return -1;
+	}
+
+	down(&dev->serialize);
+
+	interface = dev->actconfig->interface + ifnum;
+
+	if (usb_interface_claimed(interface))
+		goto out_err;
+
+	private = NULL;
+	for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {
+		driver = list_entry(tmp, struct usb_driver, driver_list);
+		tmp = tmp->next;
+
+		if (driver->owner)
+			__MOD_INC_USE_COUNT(driver->owner);
+		id = driver->id_table;
+		/* new style driver? */
+		if (id) {
+			for (i = 0; i < interface->num_altsetting; i++) {
+			  	interface->act_altsetting = i;
+				id = usb_match_id(dev, interface, id);
+				if (id) {
+					down(&driver->serialize);
+					private = driver->probe(dev,ifnum,id);
+					up(&driver->serialize);
+					if (private != NULL)
+						break;
+				}
+			}
+
+			/* if driver not bound, leave defaults unchanged */
+			if (private == NULL)
+				interface->act_altsetting = 0;
+		} else { /* "old style" driver */
+			down(&driver->serialize);
+			private = driver->probe(dev, ifnum, NULL);
+			up(&driver->serialize);
+		}
+		if (driver->owner)
+			__MOD_DEC_USE_COUNT(driver->owner);
+
+		/* probe() may have changed the config on us */
+		interface = dev->actconfig->interface + ifnum;
+
+		if (private) {
+			usb_driver_claim_interface(driver, interface, private);
+			up(&dev->serialize);
+			return 0;
+		}
+	}
+
+out_err:
+	up(&dev->serialize);
+	return -1;
+}
+
+/**
+ * usb_find_interface_driver_for_ifnum - finds a usb interface driver for the specified ifnum
+ * @dev: the device to use
+ * @ifnum: the interface number (bInterfaceNumber); not interface position!
+ *
+ * This converts a ifnum to ifpos via a call to usb_ifnum_to_ifpos and then
+ * calls usb_find_interface_driver() with the found ifpos.  Note
+ * usb_find_interface_driver's ifnum parameter is actually interface position.
+ */
+int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned ifnum)
+{
+	int ifpos = usb_ifnum_to_ifpos(dev, ifnum);
+
+	if (0 > ifpos)
+		return -EINVAL;
+
+	return usb_find_interface_driver(dev, ifpos);
+}
+
+#ifdef	CONFIG_HOTPLUG
+
+/*
+ * USB hotplugging invokes what /proc/sys/kernel/hotplug says
+ * (normally /sbin/hotplug) when USB devices get added or removed.
+ *
+ * This invokes a user mode policy agent, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ * Some synchronization is important: removes can't start processing
+ * before the add-device processing completes, and vice versa.  That keeps
+ * a stack of USB-related identifiers stable while they're in use.  If we
+ * know that agents won't complete after they return (such as by forking
+ * a process that completes later), it's enough to just waitpid() for the
+ * agent -- as is currently done.
+ *
+ * The reason: we know we're called either from khubd (the typical case)
+ * or from root hub initialization (init, kapmd, modprobe, etc).  In both
+ * cases, we know no other thread can recycle our address, since we must
+ * already have been serialized enough to prevent that.
+ */
+static void call_policy (char *verb, struct usb_device *dev)
+{
+	char *argv [3], **envp, *buf, *scratch;
+	int i = 0, value;
+
+	if (!hotplug_path [0])
+		return;
+	if (in_interrupt ()) {
+		dbg ("In_interrupt");
+		return;
+	}
+	if (!current->fs->root) {
+		/* statically linked USB is initted rather early */
+		dbg ("call_policy %s, num %d -- no FS yet", verb, dev->devnum);
+		return;
+	}
+	if (dev->devnum < 0) {
+		dbg ("device already deleted ??");
+		return;
+	}
+	if (!(envp = (char **) kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
+		dbg ("enomem");
+		return;
+	}
+	if (!(buf = kmalloc (256, GFP_KERNEL))) {
+		kfree (envp);
+		dbg ("enomem2");
+		return;
+	}
+
+	/* only one standardized param to hotplug command: type */
+	argv [0] = hotplug_path;
+	argv [1] = "usb";
+	argv [2] = 0;
+
+	/* minimal command environment */
+	envp [i++] = "HOME=/";
+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+#ifdef	DEBUG
+	/* hint that policy agent should enter no-stdout debug mode */
+	envp [i++] = "DEBUG=kernel";
+#endif
+	/* extensible set of named bus-specific parameters,
+	 * supporting multiple driver selection algorithms.
+	 */
+	scratch = buf;
+
+	/* action:  add, remove */
+	envp [i++] = scratch;
+	scratch += sprintf (scratch, "ACTION=%s", verb) + 1;
+
+#ifdef	CONFIG_USB_DEVICEFS
+	/* If this is available, userspace programs can directly read
+	 * all the device descriptors we don't tell them about.  Or
+	 * even act as usermode drivers.
+	 *
+	 * FIXME reduce hardwired intelligence here
+	 */
+	envp [i++] = "DEVFS=/proc/bus/usb";
+	envp [i++] = scratch;
+	scratch += sprintf (scratch, "DEVICE=/proc/bus/usb/%03d/%03d",
+		dev->bus->busnum, dev->devnum) + 1;
+#endif
+
+	/* per-device configuration hacks are common */
+	envp [i++] = scratch;
+	scratch += sprintf (scratch, "PRODUCT=%x/%x/%x",
+		dev->descriptor.idVendor,
+		dev->descriptor.idProduct,
+		dev->descriptor.bcdDevice) + 1;
+
+	/* class-based driver binding models */
+	envp [i++] = scratch;
+	scratch += sprintf (scratch, "TYPE=%d/%d/%d",
+			    dev->descriptor.bDeviceClass,
+			    dev->descriptor.bDeviceSubClass,
+			    dev->descriptor.bDeviceProtocol) + 1;
+	if (dev->descriptor.bDeviceClass == 0) {
+		int alt = dev->actconfig->interface [0].act_altsetting;
+
+		/* a simple/common case: one config, one interface, one driver
+		 * with current altsetting being a reasonable setting.
+		 * everything needs a smart agent and usbfs; or can rely on
+		 * device-specific binding policies.
+		 */
+		envp [i++] = scratch;
+		scratch += sprintf (scratch, "INTERFACE=%d/%d/%d",
+			dev->actconfig->interface [0].altsetting [alt].bInterfaceClass,
+			dev->actconfig->interface [0].altsetting [alt].bInterfaceSubClass,
+			dev->actconfig->interface [0].altsetting [alt].bInterfaceProtocol)
+			+ 1;
+		/* INTERFACE-0, INTERFACE-1, ... ? */
+	}
+	envp [i++] = 0;
+	/* assert: (scratch - buf) < sizeof buf */
+
+	/* NOTE: user mode daemons can call the agents too */
+
+	dbg ("kusbd: %s %s %d", argv [0], verb, dev->devnum);
+	value = call_usermodehelper (argv [0], argv, envp);
+	kfree (buf);
+	kfree (envp);
+	if (value != 0)
+		dbg ("kusbd policy returned 0x%x", value);
+}
+
+#else
+
+static inline void
+call_policy (char *verb, struct usb_device *dev)
+{ } 
+
+#endif	/* CONFIG_HOTPLUG */
+
+
+/*
+ * This entrypoint gets called for each new device.
+ *
+ * All interfaces are scanned for matching drivers.
+ */
+static void usb_find_drivers(struct usb_device *dev)
+{
+	unsigned ifnum;
+	unsigned rejected = 0;
+	unsigned claimed = 0;
+
+	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
+		struct usb_interface *interface = &dev->actconfig->interface[ifnum];
+		
+		/* register this interface with driverfs */
+		interface->dev.parent = &dev->dev;
+		sprintf (&interface->dev.bus_id[0], "%03d", ifnum);
+		sprintf (&interface->dev.name[0], "figure out some name...");
+		device_register (&interface->dev);
+
+		/* if this interface hasn't already been claimed */
+		if (!usb_interface_claimed(interface)) {
+			if (usb_find_interface_driver(dev, ifnum))
+				rejected++;
+			else
+				claimed++;
+		}
+	}
+ 
+	if (rejected)
+		dbg("unhandled interfaces on device");
+
+	if (!claimed) {
+		warn("USB device %d (vend/prod 0x%x/0x%x) is not claimed by any active driver.",
+			dev->devnum,
+			dev->descriptor.idVendor,
+			dev->descriptor.idProduct);
+#ifdef DEBUG
+		usb_show_device(dev);
+#endif
+	}
+}
+
+/**
+ * usb_alloc_dev - allocate a usb device structure (usbcore-internal)
+ * @parent: hub to which device is connected
+ * @bus: bus used to access the device
+ * Context: !in_interrupt ()
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ */
+struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
+{
+	struct usb_device *dev;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	memset(dev, 0, sizeof(*dev));
+
+	usb_bus_get(bus);
+
+	if (!parent)
+		dev->devpath [0] = '/';
+	dev->bus = bus;
+	dev->parent = parent;
+	atomic_set(&dev->refcnt, 1);
+	INIT_LIST_HEAD(&dev->filelist);
+
+	init_MUTEX(&dev->serialize);
+
+	dev->bus->op->allocate(dev);
+
+	return dev;
+}
+
+/**
+ * usb_free_dev - free a usb device structure (usbcore-internal)
+ * @dev: device that's been disconnected
+ * Context: !in_interrupt ()
+ *
+ * Used by hub and virtual root hub drivers.  The device is completely
+ * gone, everything is cleaned up, so it's time to get rid of these last
+ * records of this device.
+ */
+void usb_free_dev(struct usb_device *dev)
+{
+	if (in_interrupt ())
+		BUG ();
+	if (!atomic_dec_and_test (&dev->refcnt)) {
+		/* MUST go to zero here, else someone's hanging on to
+		 * a device that's supposed to have been cleaned up!!
+		 */
+		BUG ();
+	}
+
+	dev->bus->op->deallocate (dev);
+	usb_destroy_configuration (dev);
+	usb_bus_put (dev->bus);
+	kfree (dev);
+}
+
+/**
+ * usb_alloc_urb - creates a new urb for a USB driver to use
+ * @iso_packets: number of iso packets for this urb
+ * @mem_flags: the type of memory to allocate, see kmalloc() for a list of
+ *	valid options for this.
+ *
+ * Creates an urb for the USB driver to use, initializes a few internal
+ * structures, incrementes the usage counter, and returns a pointer to it.
+ *
+ * If no memory is available, NULL is returned.
+ *
+ * If the driver want to use this urb for interrupt, control, or bulk
+ * endpoints, pass '0' as the number of iso packets.
+ *
+ * The driver must call usb_free_urb() when it is finished with the urb.
+ */
+struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
+{
+	struct urb *urb;
+
+	urb = (struct urb *)kmalloc(sizeof(struct urb) + 
+		iso_packets * sizeof(struct usb_iso_packet_descriptor),
+		mem_flags);
+	if (!urb) {
+		err("alloc_urb: kmalloc failed");
+		return NULL;
+	}
+
+	memset(urb, 0, sizeof(*urb));
+	urb->count = (atomic_t)ATOMIC_INIT(1);
+	spin_lock_init(&urb->lock);
+
+	return urb;
+}
+
+/**
+ * usb_free_urb - frees the memory used by a urb when all users of it are finished
+ * @urb: pointer to the urb to free
+ *
+ * Must be called when a user of a urb is finished with it.  When the last user
+ * of the urb calls this function, the memory of the urb is freed.
+ *
+ * Note: The transfer buffer associated with the urb is not freed, that must be
+ * done elsewhere.
+ */
+void usb_free_urb(struct urb *urb)
+{
+	if (urb)
+		if (atomic_dec_and_test(&urb->count))
+			kfree(urb);
+}
+
+/**
+ * usb_get_urb - incrementes the reference count of the urb
+ * @urb: pointer to the urb to modify
+ *
+ * This must be  called whenever a urb is transfered from a device driver to a
+ * host controller driver.  This allows proper reference counting to happen
+ * for urbs.
+ *
+ * A pointer to the urb with the incremented reference counter is returned.
+ */
+struct urb * usb_get_urb(struct urb *urb)
+{
+	if (urb) {
+		atomic_inc(&urb->count);
+		return urb;
+	} else
+		return NULL;
+}
+		
+		
+/*-------------------------------------------------------------------*/
+
+/**
+ * usb_submit_urb - asynchronously issue a transfer request for an endpoint
+ * @urb: pointer to the urb describing the request
+ * @mem_flags: the type of memory to allocate, see kmalloc() for a list
+ *	of valid options for this.
+ *
+ * This submits a transfer request, and transfers control of the URB
+ * describing that request to the USB subsystem.  Request completion will
+ * indicated later, asynchronously, by calling the completion handler.
+ * This call may be issued in interrupt context.
+ *
+ * The caller must have correctly initialized the URB before submitting
+ * it.  Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
+ * available to ensure that most fields are correctly initialized, for
+ * the particular kind of transfer, although they will not initialize
+ * any transfer flags.
+ *
+ * Successful submissions return 0; otherwise this routine returns a
+ * negative error number.  If the submission is successful, the complete
+ * fuction of the urb will be called when the USB host driver is
+ * finished with the urb (either a successful transmission, or some
+ * error case.)
+ *
+ * Unreserved Bandwidth Transfers:
+ *
+ * Bulk or control requests complete only once.  When the completion
+ * function is called, control of the URB is returned to the device
+ * driver which issued the request.  The completion handler may then
+ * immediately free or reuse that URB.
+ *
+ * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set
+ * in the URB.  This can be used to maximize bandwidth utilization by
+ * letting the USB controller start work on the next URB without any
+ * delay to report completion (scheduling and processing an interrupt)
+ * and then submit that next request.
+ *
+ * For control endpoints, the synchronous usb_control_msg() call is
+ * often used (in non-interrupt context) instead of this call.
+ *
+ * Reserved Bandwidth Transfers:
+ *
+ * Periodic URBs (interrupt or isochronous) are completed repeatedly,
+ * until the original request is aborted.  When the completion callback
+ * indicates the URB has been unlinked (with a special status code),
+ * control of that URB returns to the device driver.  Otherwise, the
+ * completion handler does not control the URB, and should not change
+ * any of its fields.
+ *
+ * Note that isochronous URBs should be submitted in a "ring" data
+ * structure (using urb->next) to ensure that they are resubmitted
+ * appropriately.
+ *
+ * If the USB subsystem can't reserve sufficient bandwidth to perform
+ * the periodic request, and bandwidth reservation is being done for
+ * this controller, submitting such a periodic request will fail.
+ *
+ * Memory Flags:
+ *
+ * General rules for how to decide which mem_flags to use:
+ * 
+ * Basically the rules are the same as for kmalloc.  There are four
+ * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
+ * GFP_ATOMIC.
+ *
+ * GFP_NOFS is not ever used, as it has not been implemented yet.
+ *
+ * There are three situations you must use GFP_ATOMIC.
+ *    a) you are inside a completion handler, an interrupt, bottom half,
+ *       tasklet or timer.
+ *    b) you are holding a spinlock or rwlock (does not apply to
+ *       semaphores)
+ *    c) current->state != TASK_RUNNING, this is the case only after
+ *       you've changed it.
+ * 
+ * GFP_NOIO is used in the block io path and error handling of storage
+ * devices.
+ *
+ * All other situations use GFP_KERNEL.
+ *
+ * Specfic rules for how to decide which mem_flags to use:
+ *
+ *    - start_xmit, timeout, and receive methods of network drivers must
+ *      use GFP_ATOMIC (spinlock)
+ *    - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
+ *    - If you use a kernel thread with a network driver you must use
+ *      GFP_NOIO, unless b) or c) apply
+ *    - After you have done a down() you use GFP_KERNEL, unless b) or c)
+ *      apply or your are in a storage driver's block io path
+ *    - probe and disconnect use GFP_KERNEL unless b) or c) apply
+ *    - Changing firmware on a running storage or net device uses
+ *      GFP_NOIO, unless b) or c) apply
+ *
+ */
+int usb_submit_urb(struct urb *urb, int mem_flags)
+{
+	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
+		return urb->dev->bus->op->submit_urb(urb, mem_flags);
+	else
+		return -ENODEV;
+}
+
+/*-------------------------------------------------------------------*/
+
+/**
+ * usb_unlink_urb - abort/cancel a transfer request for an endpoint
+ * @urb: pointer to urb describing a previously submitted request
+ *
+ * This routine cancels an in-progress request.  The requests's
+ * completion handler will be called with a status code indicating
+ * that the request has been canceled, and that control of the URB
+ * has been returned to that device driver.  This is the only way
+ * to stop an interrupt transfer, so long as the device is connected.
+ *
+ * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this
+ * request is synchronous.  Success is indicated by returning zero,
+ * at which time the urb will have been unlinked,
+ * and the completion function will see status -ENOENT.  Failure is
+ * indicated by any other return value.  This mode may not be used
+ * when unlinking an urb from an interrupt context, such as a bottom
+ * half or a completion handler,
+ *
+ * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this
+ * request is asynchronous.  Success is indicated by returning -EINPROGRESS,
+ * at which time the urb will normally not have been unlinked,
+ * and the completion function will see status -ECONNRESET.  Failure is
+ * indicated by any other return value.
+ */
+int usb_unlink_urb(struct urb *urb)
+{
+	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
+		return urb->dev->bus->op->unlink_urb(urb);
+	else
+		return -ENODEV;
+}
+/*-------------------------------------------------------------------*
+ *                         SYNCHRONOUS CALLS                         *
+ *-------------------------------------------------------------------*/
+
+struct usb_api_data {
+	wait_queue_head_t wqh;
+	int done;
+};
+
+static void usb_api_blocking_completion(struct urb *urb)
+{
+	struct usb_api_data *awd = (struct usb_api_data *)urb->context;
+
+	awd->done = 1;
+	wmb();
+	wake_up(&awd->wqh);
+}
+
+// Starts urb and waits for completion or timeout
+static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+{ 
+	DECLARE_WAITQUEUE(wait, current);
+	struct usb_api_data awd;
+	int status;
+
+	init_waitqueue_head(&awd.wqh); 	
+	awd.done = 0;
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	add_wait_queue(&awd.wqh, &wait);
+
+	urb->context = &awd;
+	status = usb_submit_urb(urb, GFP_KERNEL);
+	if (status) {
+		// something went wrong
+		usb_free_urb(urb);
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&awd.wqh, &wait);
+		return status;
+	}
+
+	while (timeout && !awd.done)
+	{
+		timeout = schedule_timeout(timeout);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		rmb();
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&awd.wqh, &wait);
+
+	if (!timeout && !awd.done) {
+		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
+			printk(KERN_ERR "usb: raced timeout, "
+			    "pipe 0x%x status %d time left %d\n",
+			    urb->pipe, urb->status, timeout);
+			status = urb->status;
+		} else {
+			printk("usb_control/bulk_msg: timeout\n");
+			usb_unlink_urb(urb);  // remove urb safely
+			status = -ETIMEDOUT;
+		}
+	} else
+		status = urb->status;
+
+	if (actual_length)
+		*actual_length = urb->actual_length;
+
+	usb_free_urb(urb);
+  	return status;
+}
+
+/*-------------------------------------------------------------------*/
+// returns status (negative) or length (positive)
+int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, 
+			    struct usb_ctrlrequest *cmd,  void *data, int len, int timeout)
+{
+	struct urb *urb;
+	int retv;
+	int length;
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return -ENOMEM;
+  
+	FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
+		   usb_api_blocking_completion, 0);
+
+	retv = usb_start_wait_urb(urb, timeout, &length);
+	if (retv < 0)
+		return retv;
+	else
+		return length;
+}
+
+/**
+ *	usb_control_msg - Builds a control urb, sends it off and waits for completion
+ *	@dev: pointer to the usb device to send the message to
+ *	@pipe: endpoint "pipe" to send the message to
+ *	@request: USB message request value
+ *	@requesttype: USB message request type value
+ *	@value: USB message value
+ *	@index: USB message index value
+ *	@data: pointer to the data to send
+ *	@size: length in bytes of the data to send
+ *	@timeout: time in jiffies to wait for the message to complete before
+ *		timing out (if 0 the wait is forever)
+ *	Context: !in_interrupt ()
+ *
+ *	This function sends a simple control message to a specified endpoint
+ *	and waits for the message to complete, or timeout.
+ *	
+ *	If successful, it returns 0, otherwise a negative error number.
+ *
+ *	Don't use this function from within an interrupt context, like a
+ *	bottom half handler.  If you need an asynchronous message, or need to send
+ *	a message from within interrupt context, use usb_submit_urb()
+ */
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
+			 __u16 value, __u16 index, void *data, __u16 size, int timeout)
+{
+	struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
+	int ret;
+	
+	if (!dr)
+		return -ENOMEM;
+
+	dr->bRequestType= requesttype;
+	dr->bRequest = request;
+	dr->wValue = cpu_to_le16p(&value);
+	dr->wIndex = cpu_to_le16p(&index);
+	dr->wLength = cpu_to_le16p(&size);
+
+	//dbg("usb_control_msg");	
+
+	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
+
+	kfree(dr);
+
+	return ret;
+}
+
+
+/**
+ *	usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
+ *	@usb_dev: pointer to the usb device to send the message to
+ *	@pipe: endpoint "pipe" to send the message to
+ *	@data: pointer to the data to send
+ *	@len: length in bytes of the data to send
+ *	@actual_length: pointer to a location to put the actual length transferred in bytes
+ *	@timeout: time in jiffies to wait for the message to complete before
+ *		timing out (if 0 the wait is forever)
+ *	Context: !in_interrupt ()
+ *
+ *	This function sends a simple bulk message to a specified endpoint
+ *	and waits for the message to complete, or timeout.
+ *	
+ *	If successful, it returns 0, otherwise a negative error number.
+ *	The number of actual bytes transferred will be stored in the 
+ *	actual_length paramater.
+ *
+ *	Don't use this function from within an interrupt context, like a
+ *	bottom half handler.  If you need an asynchronous message, or need to
+ *	send a message from within interrupt context, use usb_submit_urb()
+ */
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
+			void *data, int len, int *actual_length, int timeout)
+{
+	struct urb *urb;
+
+	if (len < 0)
+		return -EINVAL;
+
+	urb=usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return -ENOMEM;
+
+	FILL_BULK_URB(urb, usb_dev, pipe, data, len,
+		    usb_api_blocking_completion, 0);
+
+	return usb_start_wait_urb(urb,timeout,actual_length);
+}
+
+/**
+ * usb_get_current_frame_number - return current bus frame number
+ * @dev: the device whose bus is being queried
+ *
+ * Returns the current frame number for the USB host controller
+ * used with the given USB device.  This can be used when scheduling
+ * isochronous requests.
+ *
+ * Note that different kinds of host controller have different
+ * "scheduling horizons".  While one type might support scheduling only
+ * 32 frames into the future, others could support scheduling up to
+ * 1024 frames into the future.
+ */
+int usb_get_current_frame_number(struct usb_device *dev)
+{
+	return dev->bus->op->get_frame_number (dev);
+}
+
+/*-------------------------------------------------------------------*/
+
+static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
+{
+	struct usb_descriptor_header *header;
+	unsigned char *begin;
+	int parsed = 0, len, numskipped;
+
+	header = (struct usb_descriptor_header *)buffer;
+
+	/* Everything should be fine being passed into here, but we sanity */
+	/*  check JIC */
+	if (header->bLength > size) {
+		err("ran out of descriptors parsing");
+		return -1;
+	}
+		
+	if (header->bDescriptorType != USB_DT_ENDPOINT) {
+		warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
+			endpoint->bDescriptorType, USB_DT_ENDPOINT);
+		return parsed;
+	}
+
+	if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
+		memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
+	else
+		memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
+	
+	le16_to_cpus(&endpoint->wMaxPacketSize);
+
+	buffer += header->bLength;
+	size -= header->bLength;
+	parsed += header->bLength;
+
+	/* Skip over the rest of the Class Specific or Vendor Specific */
+	/*  descriptors */
+	begin = buffer;
+	numskipped = 0;
+	while (size >= sizeof(struct usb_descriptor_header)) {
+		header = (struct usb_descriptor_header *)buffer;
+
+		if (header->bLength < 2) {
+			err("invalid descriptor length of %d", header->bLength);
+			return -1;
+		}
+
+		/* If we find another "proper" descriptor then we're done  */
+		if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
+		    (header->bDescriptorType == USB_DT_INTERFACE) ||
+		    (header->bDescriptorType == USB_DT_CONFIG) ||
+		    (header->bDescriptorType == USB_DT_DEVICE))
+			break;
+
+		dbg("skipping descriptor 0x%X",
+			header->bDescriptorType);
+		numskipped++;
+
+		buffer += header->bLength;
+		size -= header->bLength;
+		parsed += header->bLength;
+	}
+	if (numskipped)
+		dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
+
+	/* Copy any unknown descriptors into a storage area for drivers */
+	/*  to later parse */
+	len = (int)(buffer - begin);
+	if (!len) {
+		endpoint->extra = NULL;
+		endpoint->extralen = 0;
+		return parsed;
+	}
+
+	endpoint->extra = kmalloc(len, GFP_KERNEL);
+
+	if (!endpoint->extra) {
+		err("couldn't allocate memory for endpoint extra descriptors");
+		endpoint->extralen = 0;
+		return parsed;
+	}
+
+	memcpy(endpoint->extra, begin, len);
+	endpoint->extralen = len;
+
+	return parsed;
+}
+
+static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
+{
+	int i, len, numskipped, retval, parsed = 0;
+	struct usb_descriptor_header *header;
+	struct usb_interface_descriptor *ifp;
+	unsigned char *begin;
+
+	interface->act_altsetting = 0;
+	interface->num_altsetting = 0;
+	interface->max_altsetting = USB_ALTSETTINGALLOC;
+
+	interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
+	
+	if (!interface->altsetting) {
+		err("couldn't kmalloc interface->altsetting");
+		return -1;
+	}
+
+	while (size > 0) {
+		if (interface->num_altsetting >= interface->max_altsetting) {
+			void *ptr;
+			int oldmas;
+
+			oldmas = interface->max_altsetting;
+			interface->max_altsetting += USB_ALTSETTINGALLOC;
+			if (interface->max_altsetting > USB_MAXALTSETTING) {
+				warn("too many alternate settings (max %d)",
+					USB_MAXALTSETTING);
+				return -1;
+			}
+
+			ptr = interface->altsetting;
+			interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
+			if (!interface->altsetting) {
+				err("couldn't kmalloc interface->altsetting");
+				interface->altsetting = ptr;
+				return -1;
+			}
+			memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas);
+
+			kfree(ptr);
+		}
+
+		ifp = interface->altsetting + interface->num_altsetting;
+		ifp->endpoint = NULL;
+		ifp->extra = NULL;
+		ifp->extralen = 0;
+		interface->num_altsetting++;
+
+		memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
+
+		/* Skip over the interface */
+		buffer += ifp->bLength;
+		parsed += ifp->bLength;
+		size -= ifp->bLength;
+
+		begin = buffer;
+		numskipped = 0;
+
+		/* Skip over any interface, class or vendor descriptors */
+		while (size >= sizeof(struct usb_descriptor_header)) {
+			header = (struct usb_descriptor_header *)buffer;
+
+			if (header->bLength < 2) {
+				err("invalid descriptor length of %d", header->bLength);
+				return -1;
+			}
+
+			/* If we find another "proper" descriptor then we're done  */
+			if ((header->bDescriptorType == USB_DT_INTERFACE) ||
+			    (header->bDescriptorType == USB_DT_ENDPOINT) ||
+			    (header->bDescriptorType == USB_DT_CONFIG) ||
+			    (header->bDescriptorType == USB_DT_DEVICE))
+				break;
+
+			numskipped++;
+
+			buffer += header->bLength;
+			parsed += header->bLength;
+			size -= header->bLength;
+		}
+
+		if (numskipped)
+			dbg("skipped %d class/vendor specific interface descriptors", numskipped);
+
+		/* Copy any unknown descriptors into a storage area for */
+		/*  drivers to later parse */
+		len = (int)(buffer - begin);
+		if (len) {
+			ifp->extra = kmalloc(len, GFP_KERNEL);
+
+			if (!ifp->extra) {
+				err("couldn't allocate memory for interface extra descriptors");
+				ifp->extralen = 0;
+				return -1;
+			}
+			memcpy(ifp->extra, begin, len);
+			ifp->extralen = len;
+		}
+
+		/* Did we hit an unexpected descriptor? */
+		header = (struct usb_descriptor_header *)buffer;
+		if ((size >= sizeof(struct usb_descriptor_header)) &&
+		    ((header->bDescriptorType == USB_DT_CONFIG) ||
+		     (header->bDescriptorType == USB_DT_DEVICE)))
+			return parsed;
+
+		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
+			warn("too many endpoints");
+			return -1;
+		}
+
+		ifp->endpoint = (struct usb_endpoint_descriptor *)
+			kmalloc(ifp->bNumEndpoints *
+			sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
+		if (!ifp->endpoint) {
+			err("out of memory");
+			return -1;	
+		}
+
+		memset(ifp->endpoint, 0, ifp->bNumEndpoints *
+			sizeof(struct usb_endpoint_descriptor));
+	
+		for (i = 0; i < ifp->bNumEndpoints; i++) {
+			header = (struct usb_descriptor_header *)buffer;
+
+			if (header->bLength > size) {
+				err("ran out of descriptors parsing");
+				return -1;
+			}
+		
+			retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
+			if (retval < 0)
+				return retval;
+
+			buffer += retval;
+			parsed += retval;
+			size -= retval;
+		}
+
+		/* We check to see if it's an alternate to this one */
+		ifp = (struct usb_interface_descriptor *)buffer;
+		if (size < USB_DT_INTERFACE_SIZE ||
+		    ifp->bDescriptorType != USB_DT_INTERFACE ||
+		    !ifp->bAlternateSetting)
+			return parsed;
+	}
+
+	return parsed;
+}
+
+int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
+{
+	int i, retval, size;
+	struct usb_descriptor_header *header;
+
+	memcpy(config, buffer, USB_DT_CONFIG_SIZE);
+	le16_to_cpus(&config->wTotalLength);
+	size = config->wTotalLength;
+
+	if (config->bNumInterfaces > USB_MAXINTERFACES) {
+		warn("too many interfaces");
+		return -1;
+	}
+
+	config->interface = (struct usb_interface *)
+		kmalloc(config->bNumInterfaces *
+		sizeof(struct usb_interface), GFP_KERNEL);
+	dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces);
+	if (!config->interface) {
+		err("out of memory");
+		return -1;	
+	}
+
+	memset(config->interface, 0,
+	       config->bNumInterfaces * sizeof(struct usb_interface));
+
+	buffer += config->bLength;
+	size -= config->bLength;
+	
+	config->extra = NULL;
+	config->extralen = 0;
+
+	for (i = 0; i < config->bNumInterfaces; i++) {
+		int numskipped, len;
+		char *begin;
+
+		/* Skip over the rest of the Class Specific or Vendor */
+		/*  Specific descriptors */
+		begin = buffer;
+		numskipped = 0;
+		while (size >= sizeof(struct usb_descriptor_header)) {
+			header = (struct usb_descriptor_header *)buffer;
+
+			if ((header->bLength > size) || (header->bLength < 2)) {
+				err("invalid descriptor length of %d", header->bLength);
+				return -1;
+			}
+
+			/* If we find another "proper" descriptor then we're done  */
+			if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
+			    (header->bDescriptorType == USB_DT_INTERFACE) ||
+			    (header->bDescriptorType == USB_DT_CONFIG) ||
+			    (header->bDescriptorType == USB_DT_DEVICE))
+				break;
+
+			dbg("skipping descriptor 0x%X", header->bDescriptorType);
+			numskipped++;
+
+			buffer += header->bLength;
+			size -= header->bLength;
+		}
+		if (numskipped)
+			dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
+
+		/* Copy any unknown descriptors into a storage area for */
+		/*  drivers to later parse */
+		len = (int)(buffer - begin);
+		if (len) {
+			if (config->extralen) {
+				warn("extra config descriptor");
+			} else {
+				config->extra = kmalloc(len, GFP_KERNEL);
+				if (!config->extra) {
+					err("couldn't allocate memory for config extra descriptors");
+					config->extralen = 0;
+					return -1;
+				}
+
+				memcpy(config->extra, begin, len);
+				config->extralen = len;
+			}
+		}
+
+		retval = usb_parse_interface(config->interface + i, buffer, size);
+		if (retval < 0)
+			return retval;
+
+		buffer += retval;
+		size -= retval;
+	}
+
+	return size;
+}
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally on disconnect/destroy path
+void usb_destroy_configuration(struct usb_device *dev)
+{
+	int c, i, j, k;
+	
+	if (!dev->config)
+		return;
+
+	if (dev->rawdescriptors) {
+		for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
+			kfree(dev->rawdescriptors[i]);
+
+		kfree(dev->rawdescriptors);
+	}
+
+	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
+		struct usb_config_descriptor *cf = &dev->config[c];
+
+		if (!cf->interface)
+			break;
+
+		for (i = 0; i < cf->bNumInterfaces; i++) {
+			struct usb_interface *ifp =
+				&cf->interface[i];
+				
+			if (!ifp->altsetting)
+				break;
+
+			for (j = 0; j < ifp->num_altsetting; j++) {
+				struct usb_interface_descriptor *as =
+					&ifp->altsetting[j];
+					
+				if(as->extra) {
+					kfree(as->extra);
+				}
+
+				if (!as->endpoint)
+					break;
+					
+				for(k = 0; k < as->bNumEndpoints; k++) {
+					if(as->endpoint[k].extra) {
+						kfree(as->endpoint[k].extra);
+					}
+				}	
+				kfree(as->endpoint);
+			}
+
+			kfree(ifp->altsetting);
+		}
+		kfree(cf->interface);
+	}
+	kfree(dev->config);
+}
+
+/* for returning string descriptors in UTF-16LE */
+static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
+{
+	int retval;
+
+	for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
+		*utf++ = *ascii++ & 0x7f;
+		*utf++ = 0;
+	}
+	return retval;
+}
+
+/*
+ * root_hub_string is used by each host controller's root hub code,
+ * so that they're identified consistently throughout the system.
+ */
+int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
+{
+	char buf [30];
+
+	// assert (len > (2 * (sizeof (buf) + 1)));
+	// assert (strlen (type) <= 8);
+
+	// language ids
+	if (id == 0) {
+		*data++ = 4; *data++ = 3;	/* 4 bytes data */
+		*data++ = 0; *data++ = 0;	/* some language id */
+		return 4;
+
+	// serial number
+	} else if (id == 1) {
+		sprintf (buf, "%x", serial);
+
+	// product description
+	} else if (id == 2) {
+		sprintf (buf, "USB %s Root Hub", type);
+
+	// id 3 == vendor description
+
+	// unsupported IDs --> "stall"
+	} else
+	    return 0;
+
+	data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
+	data [1] = 3;
+	return data [0];
+}
+
+/*
+ * __usb_get_extra_descriptor() finds a descriptor of specific type in the
+ * extra field of the interface and endpoint descriptor structs.
+ */
+
+int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr)
+{
+	struct usb_descriptor_header *header;
+
+	while (size >= sizeof(struct usb_descriptor_header)) {
+		header = (struct usb_descriptor_header *)buffer;
+
+		if (header->bLength < 2) {
+			err("invalid descriptor length of %d", header->bLength);
+			return -1;
+		}
+
+		if (header->bDescriptorType == type) {
+			*ptr = header;
+			return 0;
+		}
+
+		buffer += header->bLength;
+		size -= header->bLength;
+	}
+	return -1;
+}
+
+/**
+ * usb_disconnect - disconnect a device (usbcore-internal)
+ * @pdev: pointer to device being disconnected
+ * Context: !in_interrupt ()
+ *
+ * Something got disconnected. Get rid of it, and all of its children.
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ */
+void usb_disconnect(struct usb_device **pdev)
+{
+	struct usb_device * dev = *pdev;
+	int i;
+
+	if (!dev)
+		return;
+
+	*pdev = NULL;
+
+	info("USB disconnect on device %d", dev->devnum);
+
+	if (dev->actconfig) {
+		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+			struct usb_interface *interface = &dev->actconfig->interface[i];
+			struct usb_driver *driver = interface->driver;
+			if (driver) {
+				if (driver->owner)
+					__MOD_INC_USE_COUNT(driver->owner);
+				down(&driver->serialize);
+				driver->disconnect(dev, interface->private_data);
+				up(&driver->serialize);
+				if (driver->owner)
+					__MOD_DEC_USE_COUNT(driver->owner);
+				/* if driver->disconnect didn't release the interface */
+				if (interface->driver)
+					usb_driver_release_interface(driver, interface);
+			}
+			/* remove our device node for this interface */
+			put_device(&interface->dev);
+		}
+	}
+
+	/* Free up all the children.. */
+	for (i = 0; i < USB_MAXCHILDREN; i++) {
+		struct usb_device **child = dev->children + i;
+		if (*child)
+			usb_disconnect(child);
+	}
+
+	/* Let policy agent unload modules etc */
+	call_policy ("remove", dev);
+
+	/* Free the device number and remove the /proc/bus/usb entry */
+	if (dev->devnum > 0) {
+		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+		usbfs_remove_device(dev);
+		put_device(&dev->dev);
+	}
+
+	/* Free up the device itself */
+	usb_free_dev(dev);
+}
+
+/**
+ * usb_connect - connects a new device during enumeration (usbcore-internal)
+ * @dev: partially enumerated device
+ *
+ * Connect a new USB device. This basically just initializes
+ * the USB device information and sets up the topology - it's
+ * up to the low-level driver to reset the port and actually
+ * do the setup (the upper levels don't know how to do that).
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ */
+void usb_connect(struct usb_device *dev)
+{
+	int devnum;
+	// FIXME needs locking for SMP!!
+	/* why? this is called only from the hub thread, 
+	 * which hopefully doesn't run on multiple CPU's simultaneously 8-)
+	 * ... it's also called from modprobe/rmmod/apmd threads as part
+	 * of virtual root hub init/reinit.  In the init case, the hub code 
+	 * won't have seen this, but not so for reinit ... 
+	 */
+	dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */
+#ifndef DEVNUM_ROUND_ROBIN
+	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
+#else	/* round_robin alloc of devnums */
+	/* Try to allocate the next devnum beginning at bus->devnum_next. */
+	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);
+	if (devnum >= 128)
+		devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
+
+	dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+#endif	/* round_robin alloc of devnums */
+
+	if (devnum < 128) {
+		set_bit(devnum, dev->bus->devmap.devicemap);
+		dev->devnum = devnum;
+	}
+}
+
+/*
+ * These are the actual routines to send
+ * and receive control messages.
+ */
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for usb_new_device()
+int usb_set_address(struct usb_device *dev)
+{
+	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
+		// FIXME USB_CTRL_SET_TIMEOUT
+		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+/**
+ * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
+ * @dev: the device whose descriptor is being retrieved
+ * @type: the descriptor type (USB_DT_*)
+ * @index: the number of the descriptor
+ * @buf: where to put the descriptor
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Gets a USB descriptor.  Convenience functions exist to simplify
+ * getting some types of descriptors.  Use
+ * usb_get_device_descriptor() for USB_DT_DEVICE,
+ * and usb_get_string() or usb_string() for USB_DT_STRING.
+ * Configuration descriptors (USB_DT_CONFIG) are part of the device
+ * structure, at least for the current configuration.
+ * In addition to a number of USB-standard descriptors, some
+ * devices also use class-specific or vendor-specific descriptors.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
+{
+	int i = 5;
+	int result;
+	
+	memset(buf,0,size);	// Make sure we parse really received data
+
+	while (i--) {
+		/* retries if the returned length was 0; flakey device */
+		if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+				    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+				    (type << 8) + index, 0, buf, size,
+				    HZ * USB_CTRL_GET_TIMEOUT)) > 0
+				|| result == -EPIPE)
+			break;
+	}
+	return result;
+}
+
+/**
+ * usb_get_string - gets a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @langid: code for language chosen (from string descriptor zero)
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
+ * in little-endian byte order).
+ * The usb_string() function will often be a convenient way to turn
+ * these strings into kernel-printable form.
+ *
+ * Strings may be referenced in device, configuration, interface, or other
+ * descriptors, and could also be used in vendor-specific ways.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+		(USB_DT_STRING << 8) + index, langid, buf, size,
+		HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+/**
+ * usb_get_device_descriptor - (re)reads the device descriptor
+ * @dev: the device whose device descriptor is being updated
+ * Context: !in_interrupt ()
+ *
+ * Updates the copy of the device descriptor stored in the device structure,
+ * which dedicates space for this purpose.  Note that several fields are
+ * converted to the host CPU's byte order:  the USB version (bcdUSB), and
+ * vendors product and version fields (idVendor, idProduct, and bcdDevice).
+ * That lets device drivers compare against non-byteswapped constants.
+ *
+ * There's normally no need to use this call, although some devices
+ * will change their descriptors after events like updating firmware.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_get_device_descriptor(struct usb_device *dev)
+{
+	int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
+				     sizeof(dev->descriptor));
+	if (ret >= 0) {
+		le16_to_cpus(&dev->descriptor.bcdUSB);
+		le16_to_cpus(&dev->descriptor.idVendor);
+		le16_to_cpus(&dev->descriptor.idProduct);
+		le16_to_cpus(&dev->descriptor.bcdDevice);
+	}
+	return ret;
+}
+
+/**
+ * usb_get_status - issues a GET_STATUS call
+ * @dev: the device whose status is being checked
+ * @type: USB_RECIP_*; for device, interface, or endpoint
+ * @target: zero (for device), else interface or endpoint number
+ * @data: pointer to two bytes of bitmap data
+ * Context: !in_interrupt ()
+ *
+ * Returns device, interface, or endpoint status.  Normally only of
+ * interest to see if the device is self powered, or has enabled the
+ * remote wakeup facility; or whether a bulk or interrupt endpoint
+ * is halted ("stalled").
+ *
+ * Bits in these status bitmaps are set using the SET_FEATURE request,
+ * and cleared using the CLEAR_FEATURE request.  The usb_clear_halt()
+ * function should be used to clear halt ("stall") status.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_get_status(struct usb_device *dev, int type, int target, void *data)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
+		HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for config/altsetting reconfig.
+void usb_set_maxpacket(struct usb_device *dev)
+{
+	int i, b;
+
+	for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
+		struct usb_interface *ifp = dev->actconfig->interface + i;
+		struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;
+		struct usb_endpoint_descriptor *ep = as->endpoint;
+		int e;
+
+		for (e=0; e<as->bNumEndpoints; e++) {
+			b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+				USB_ENDPOINT_XFER_CONTROL) {	/* Control => bidirectional */
+				dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+				dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+				}
+			else if (usb_endpoint_out(ep[e].bEndpointAddress)) {
+				if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
+					dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+			}
+			else {
+				if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
+					dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+			}
+		}
+	}
+}
+
+/**
+ * usb_clear_halt - tells device to clear endpoint halt/stall condition
+ * @dev: device whose endpoint is halted
+ * @pipe: endpoint "pipe" being cleared
+ * Context: !in_interrupt ()
+ *
+ * This is used to clear halt conditions for bulk and interrupt endpoints,
+ * as reported by URB completion status.  Endpoints that are halted are
+ * sometimes referred to as being "stalled".  Such endpoints are unable
+ * to transmit or receive data until the halt status is cleared.  Any URBs
+ * queued queued for such an endpoint should normally be unlinked before
+ * clearing the halt condition.
+ *
+ * Note that control and isochronous endpoints don't halt, although control
+ * endpoints report "protocol stall" (for unsupported requests) using the
+ * same status code used to report a true stall.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_clear_halt(struct usb_device *dev, int pipe)
+{
+	int result;
+	__u16 status;
+	unsigned char *buffer;
+	int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
+
+/*
+	if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
+		return 0;
+*/
+
+	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
+		HZ * USB_CTRL_SET_TIMEOUT);
+
+	/* don't clear if failed */
+	if (result < 0)
+		return result;
+
+	buffer = kmalloc(sizeof(status), GFP_KERNEL);
+	if (!buffer) {
+		err("unable to allocate memory for configuration descriptors");
+		return -ENOMEM;
+	}
+
+	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
+		// FIXME USB_CTRL_GET_TIMEOUT, yes?  why not usb_get_status() ?
+		buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
+
+	memcpy(&status, buffer, sizeof(status));
+	kfree(buffer);
+
+	if (result < 0)
+		return result;
+
+	if (le16_to_cpu(status) & 1)
+		return -EPIPE;		/* still halted */
+
+	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+
+	/* toggle is reset on clear */
+
+	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+
+	return 0;
+}
+
+/**
+ * usb_set_interface - Makes a particular alternate setting be current
+ * @dev: the device whose interface is being updated
+ * @interface: the interface being updated
+ * @alternate: the setting being chosen.
+ * Context: !in_interrupt ()
+ *
+ * This is used to enable data transfers on interfaces that may not
+ * be enabled by default.  Not all devices support such configurability.
+ *
+ * Within any given configuration, each interface may have several
+ * alternative settings.  These are often used to control levels of
+ * bandwidth consumption.  For example, the default setting for a high
+ * speed interrupt endpoint may not send more than about 4KBytes per
+ * microframe, and isochronous endpoints may never be part of a an
+ * interface's default setting.  To access such bandwidth, alternate
+ * interface setting must be made current.
+ *
+ * Note that in the Linux USB subsystem, bandwidth associated with
+ * an endpoint in a given alternate setting is not reserved until an
+ * is submitted that needs that bandwidth.  Some other operating systems
+ * allocate bandwidth early, when a configuration is chosen.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *iface_as;
+	int i, ret;
+
+	iface = usb_ifnum_to_if(dev, interface);
+	if (!iface) {
+		warn("selecting invalid interface %d", interface);
+		return -EINVAL;
+	}
+
+	/* 9.4.10 says devices don't need this, if the interface
+	   only has one alternate setting */
+	if (iface->num_altsetting == 1) {
+		dbg("ignoring set_interface for dev %d, iface %d, alt %d",
+			dev->devnum, interface, alternate);
+		return 0;
+	}
+
+	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+	    USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
+	    interface, NULL, 0, HZ * 5)) < 0)
+		return ret;
+
+	iface->act_altsetting = alternate;
+
+	/* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
+	 *
+	 * Note:
+	 * Despite EP0 is always present in all interfaces/AS, the list of
+	 * endpoints from the descriptor does not contain EP0. Due to its
+	 * omnipresence one might expect EP0 being considered "affected" by
+	 * any SetInterface request and hence assume toggles need to be reset.
+	 * However, EP0 toggles are re-synced for every individual transfer
+	 * during the SETUP stage - hence EP0 toggles are "don't care" here.
+	 */
+
+	iface_as = &iface->altsetting[alternate];
+	for (i = 0; i < iface_as->bNumEndpoints; i++) {
+		u8	ep = iface_as->endpoint[i].bEndpointAddress;
+
+		usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
+	}
+
+	/* usb_set_maxpacket() sets the maxpacket size for all EP in all
+	 * interfaces but it shouldn't do any harm here: we have changed
+	 * the AS for the requested interface only, hence for unaffected
+	 * interfaces it's just re-application of still-valid values.
+	 */
+	usb_set_maxpacket(dev);
+	return 0;
+}
+
+/**
+ * usb_set_configuration - Makes a particular device setting be current
+ * @dev: the device whose configuration is being updated
+ * @configuration: the configuration being chosen.
+ * Context: !in_interrupt ()
+ *
+ * This is used to enable non-default device modes.  Not all devices
+ * support this kind of configurability.  By default, configuration
+ * zero is selected after enumeration; many devices only have a single
+ * configuration.
+ *
+ * USB devices may support one or more configurations, which affect
+ * power consumption and the functionality available.  For example,
+ * the default configuration is limited to using 100mA of bus power,
+ * so that when certain device functionality requires more power,
+ * and the device is bus powered, that functionality will be in some
+ * non-default device configuration.  Other device modes may also be
+ * reflected as configuration options, such as whether two ISDN
+ * channels are presented as independent 64Kb/s interfaces or as one
+ * bonded 128Kb/s interface.
+ *
+ * Note that USB has an additional level of device configurability,
+ * associated with interfaces.  That configurability is accessed using
+ * usb_set_interface().
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
+int usb_set_configuration(struct usb_device *dev, int configuration)
+{
+	int i, ret;
+	struct usb_config_descriptor *cp = NULL;
+	
+	for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
+		if (dev->config[i].bConfigurationValue == configuration) {
+			cp = &dev->config[i];
+			break;
+		}
+	}
+	if (!cp) {
+		warn("selecting invalid configuration %d", configuration);
+		return -EINVAL;
+	}
+
+	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
+		return ret;
+
+	dev->actconfig = cp;
+	dev->toggle[0] = 0;
+	dev->toggle[1] = 0;
+	usb_set_maxpacket(dev);
+
+	return 0;
+}
+
+// hub-only!! ... and only in reset path, or usb_new_device()
+// (used by real hubs and virtual root hubs)
+int usb_get_configuration(struct usb_device *dev)
+{
+	int result;
+	unsigned int cfgno, length;
+	unsigned char *buffer;
+	unsigned char *bigbuffer;
+ 	struct usb_config_descriptor *desc;
+
+	if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
+		warn("too many configurations");
+		return -EINVAL;
+	}
+
+	if (dev->descriptor.bNumConfigurations < 1) {
+		warn("not enough configurations");
+		return -EINVAL;
+	}
+
+	dev->config = (struct usb_config_descriptor *)
+		kmalloc(dev->descriptor.bNumConfigurations *
+		sizeof(struct usb_config_descriptor), GFP_KERNEL);
+	if (!dev->config) {
+		err("out of memory");
+		return -ENOMEM;	
+	}
+	memset(dev->config, 0, dev->descriptor.bNumConfigurations *
+		sizeof(struct usb_config_descriptor));
+
+	dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
+		dev->descriptor.bNumConfigurations, GFP_KERNEL);
+	if (!dev->rawdescriptors) {
+		err("out of memory");
+		return -ENOMEM;
+	}
+
+	buffer = kmalloc(8, GFP_KERNEL);
+	if (!buffer) {
+		err("unable to allocate memory for configuration descriptors");
+		return -ENOMEM;
+	}
+	desc = (struct usb_config_descriptor *)buffer;
+
+	for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
+		/* We grab the first 8 bytes so we know how long the whole */
+		/*  configuration is */
+		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
+		if (result < 8) {
+			if (result < 0)
+				err("unable to get descriptor");
+			else {
+				err("config descriptor too short (expected %i, got %i)", 8, result);
+				result = -EINVAL;
+			}
+			goto err;
+		}
+
+  	  	/* Get the full buffer */
+		length = le16_to_cpu(desc->wTotalLength);
+
+		bigbuffer = kmalloc(length, GFP_KERNEL);
+		if (!bigbuffer) {
+			err("unable to allocate memory for configuration descriptors");
+			result = -ENOMEM;
+			goto err;
+		}
+
+		/* Now that we know the length, get the whole thing */
+		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
+		if (result < 0) {
+			err("couldn't get all of config descriptors");
+			kfree(bigbuffer);
+			goto err;
+		}	
+	
+		if (result < length) {
+			err("config descriptor too short (expected %i, got %i)", length, result);
+			result = -EINVAL;
+			kfree(bigbuffer);
+			goto err;
+		}
+
+		dev->rawdescriptors[cfgno] = bigbuffer;
+
+		result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
+		if (result > 0)
+			dbg("descriptor data left");
+		else if (result < 0) {
+			result = -EINVAL;
+			goto err;
+		}
+	}
+
+	kfree(buffer);
+	return 0;
+err:
+	kfree(buffer);
+	dev->descriptor.bNumConfigurations = cfgno;
+	return result;
+}
+
+/**
+ * usb_string - returns ISO 8859-1 version of a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ * 
+ * This converts the UTF-16LE encoded strings returned by devices, from
+ * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
+ * that are more usable in most kernel contexts.  Note that all characters
+ * in the chosen descriptor that can't be encoded using ISO-8859-1
+ * are converted to the question mark ("?") character, and this function
+ * chooses strings in the first language supported by the device.
+ *
+ * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
+ * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
+ * and is appropriate for use many uses of English and several other
+ * Western European languages.  (But it doesn't include the "Euro" symbol.)
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns length of the string (>= 0) or usb_control_msg status (< 0).
+ */
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+{
+	unsigned char *tbuf;
+	int err;
+	unsigned int u, idx;
+
+	if (size <= 0 || !buf || !index)
+		return -EINVAL;
+	buf[0] = 0;
+	tbuf = kmalloc(256, GFP_KERNEL);
+	if (!tbuf)
+		return -ENOMEM;
+
+	/* get langid for strings if it's not yet known */
+	if (!dev->have_langid) {
+		err = usb_get_string(dev, 0, 0, tbuf, 4);
+		if (err < 0) {
+			err("error getting string descriptor 0 (error=%d)", err);
+			goto errout;
+		} else if (tbuf[0] < 4) {
+			err("string descriptor 0 too short");
+			err = -EINVAL;
+			goto errout;
+		} else {
+			dev->have_langid = -1;
+			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+				/* always use the first langid listed */
+			dbg("USB device number %d default language ID 0x%x",
+				dev->devnum, dev->string_langid);
+		}
+	}
+
+	/*
+	 * Just ask for a maximum length string and then take the length
+	 * that was returned.
+	 */
+	err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
+	if (err < 0)
+		goto errout;
+
+	size--;		/* leave room for trailing NULL char in output buffer */
+	for (idx = 0, u = 2; u < err; u += 2) {
+		if (idx >= size)
+			break;
+		if (tbuf[u+1])			/* high byte */
+			buf[idx++] = '?';  /* non ISO-8859-1 character */
+		else
+			buf[idx++] = tbuf[u];
+	}
+	buf[idx] = 0;
+	err = idx;
+
+ errout:
+	kfree(tbuf);
+	return err;
+}
+
+/**
+ * usb_make_path - returns device path in the hub tree
+ * @dev: the device whose path is being constructed
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * Context: !in_interrupt ()
+ *
+ * Returns length of the string (>= 0) or out of memory status (< 0).
+ *
+ * NOTE:  prefer to use use dev->devpath directly.
+ */
+int usb_make_path(struct usb_device *dev, char *buf, size_t size)
+{
+	struct usb_device *pdev = dev->parent;
+	char *tmp;
+	char *port;
+	int i;
+
+	if (!(port = kmalloc(size, GFP_KERNEL)))
+		return -ENOMEM;
+	if (!(tmp = kmalloc(size, GFP_KERNEL))) {
+		kfree(port);
+		return -ENOMEM;
+	}
+
+	*port = 0;
+	while (pdev) {
+		for (i = 0; i < pdev->maxchild; i++)
+			if (pdev->children[i] == dev)
+				break;
+
+		if (pdev->children[i] != dev) {
+			kfree(port);
+			kfree(tmp);
+			return -ENODEV;
+		}
+
+		strcpy(tmp, port);
+		snprintf(port, size, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
+
+		dev = pdev;
+		pdev = dev->parent;
+	}
+
+	snprintf(buf, size, "usb%d:%s", dev->bus->busnum, port);
+	kfree(port);
+	kfree(tmp);
+	return strlen(buf);
+}
+
+/*
+ * By the time we get here, the device has gotten a new device ID
+ * and is in the default state. We need to identify the thing and
+ * get the ball rolling..
+ *
+ * Returns 0 for success, != 0 for error.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ */
+int usb_new_device(struct usb_device *dev)
+{
+	int err;
+
+	/* USB v1.1 5.5.3 */
+	/* We read the first 8 bytes from the device descriptor to get to */
+	/*  the bMaxPacketSize0 field. Then we set the maximum packet size */
+	/*  for the control pipe, and retrieve the rest */
+	dev->epmaxpacketin [0] = 8;
+	dev->epmaxpacketout[0] = 8;
+
+	err = usb_set_address(dev);
+	if (err < 0) {
+		err("USB device not accepting new address=%d (error=%d)",
+			dev->devnum, err);
+		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+		dev->devnum = -1;
+		return 1;
+	}
+
+	wait_ms(10);	/* Let the SET_ADDRESS settle */
+
+	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
+	if (err < 8) {
+		if (err < 0)
+			err("USB device not responding, giving up (error=%d)", err);
+		else
+			err("USB device descriptor short read (expected %i, got %i)", 8, err);
+		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+		dev->devnum = -1;
+		return 1;
+	}
+	dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
+	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
+
+	err = usb_get_device_descriptor(dev);
+	if (err < (signed)sizeof(dev->descriptor)) {
+		if (err < 0)
+			err("unable to get device descriptor (error=%d)", err);
+		else
+			err("USB device descriptor short read (expected %Zi, got %i)",
+				sizeof(dev->descriptor), err);
+	
+		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+		dev->devnum = -1;
+		return 1;
+	}
+
+	err = usb_get_configuration(dev);
+	if (err < 0) {
+		err("unable to get device %d configuration (error=%d)",
+			dev->devnum, err);
+		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+		dev->devnum = -1;
+		return 1;
+	}
+
+	/* we set the default configuration here */
+	err = usb_set_configuration(dev, dev->config[0].bConfigurationValue);
+	if (err) {
+		err("failed to set device %d default configuration (error=%d)",
+			dev->devnum, err);
+		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+		dev->devnum = -1;
+		return 1;
+	}
+
+	dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d",
+		dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
+#ifdef DEBUG
+	if (dev->descriptor.iManufacturer)
+		usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
+	if (dev->descriptor.iProduct)
+		usb_show_string(dev, "Product", dev->descriptor.iProduct);
+	if (dev->descriptor.iSerialNumber)
+		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
+#endif
+
+	/* register this device in the driverfs tree */
+	err = device_register (&dev->dev);
+	if (err)
+		return err;
+
+	/* now that the basic setup is over, add a /proc/bus/usb entry */
+	usbfs_add_device(dev);
+
+	/* find drivers willing to handle this device */
+	usb_find_drivers(dev);
+
+	/* userspace may load modules and/or configure further */
+	call_policy ("add", dev);
+
+	return 0;
+}
+
+static int usb_open(struct inode * inode, struct file * file)
+{
+	int minor = minor(inode->i_rdev);
+	struct usb_driver *c = usb_minors[minor/16];
+	int err = -ENODEV;
+	struct file_operations *old_fops, *new_fops = NULL;
+
+	/*
+	 * No load-on-demand? Randy, could you ACK that it's really not
+	 * supposed to be done?					-- AV
+	 */
+	if (!c || !(new_fops = fops_get(c->fops)))
+		return err;
+	old_fops = file->f_op;
+	file->f_op = new_fops;
+	/* Curiouser and curiouser... NULL ->open() as "no device" ? */
+	if (file->f_op->open)
+		err = file->f_op->open(inode,file);
+	if (err) {
+		fops_put(file->f_op);
+		file->f_op = fops_get(old_fops);
+	}
+	fops_put(old_fops);
+	return err;
+}
+
+static struct file_operations usb_fops = {
+	owner:		THIS_MODULE,
+	open:		usb_open,
+};
+
+int usb_major_init(void)
+{
+	if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
+		err("unable to get major %d for usb devices", USB_MAJOR);
+		return -EBUSY;
+	}
+
+	usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
+
+	return 0;
+}
+
+void usb_major_cleanup(void)
+{
+	devfs_unregister(usb_devfs_handle);
+	devfs_unregister_chrdev(USB_MAJOR, "usb");
+}
+
+
+#ifdef CONFIG_PROC_FS
+struct list_head *usb_driver_get_list(void)
+{
+	return &usb_driver_list;
+}
+
+struct list_head *usb_bus_get_list(void)
+{
+	return &usb_bus_list;
+}
+#endif
+
+
+/*
+ * Init
+ */
+static int __init usb_init(void)
+{
+	usb_major_init();
+	usbfs_init();
+	usb_hub_init();
+
+	return 0;
+}
+
+/*
+ * Cleanup
+ */
+static void __exit usb_exit(void)
+{
+	usb_major_cleanup();
+	usbfs_cleanup();
+	usb_hub_cleanup();
+}
+
+subsys_initcall(usb_init);
+module_exit(usb_exit);
+
+/*
+ * USB may be built into the kernel or be built as modules.
+ * If the USB core [and maybe a host controller driver] is built
+ * into the kernel, and other device drivers are built as modules,
+ * then these symbols need to be exported for the modules to use.
+ */
+EXPORT_SYMBOL(usb_ifnum_to_ifpos);
+EXPORT_SYMBOL(usb_ifnum_to_if);
+EXPORT_SYMBOL(usb_epnum_to_ep_desc);
+
+EXPORT_SYMBOL(usb_register);
+EXPORT_SYMBOL(usb_deregister);
+EXPORT_SYMBOL(usb_scan_devices);
+
+EXPORT_SYMBOL(usb_alloc_dev);
+EXPORT_SYMBOL(usb_free_dev);
+EXPORT_SYMBOL(usb_inc_dev_use);
+
+EXPORT_SYMBOL(usb_find_interface_driver_for_ifnum);
+EXPORT_SYMBOL(usb_driver_claim_interface);
+EXPORT_SYMBOL(usb_interface_claimed);
+EXPORT_SYMBOL(usb_driver_release_interface);
+EXPORT_SYMBOL(usb_match_id);
+
+EXPORT_SYMBOL(usb_root_hub_string);
+EXPORT_SYMBOL(usb_new_device);
+EXPORT_SYMBOL(usb_reset_device);
+EXPORT_SYMBOL(usb_connect);
+EXPORT_SYMBOL(usb_disconnect);
+
+EXPORT_SYMBOL(__usb_get_extra_descriptor);
+
+EXPORT_SYMBOL(usb_get_current_frame_number);
+
+// asynchronous request completion model
+EXPORT_SYMBOL(usb_alloc_urb);
+EXPORT_SYMBOL(usb_free_urb);
+EXPORT_SYMBOL(usb_get_urb);
+EXPORT_SYMBOL(usb_submit_urb);
+EXPORT_SYMBOL(usb_unlink_urb);
+
+// synchronous request completion model
+EXPORT_SYMBOL(usb_control_msg);
+EXPORT_SYMBOL(usb_bulk_msg);
+// synchronous control message convenience routines
+EXPORT_SYMBOL(usb_get_descriptor);
+EXPORT_SYMBOL(usb_get_device_descriptor);
+EXPORT_SYMBOL(usb_get_status);
+EXPORT_SYMBOL(usb_get_string);
+EXPORT_SYMBOL(usb_string);
+EXPORT_SYMBOL(usb_clear_halt);
+EXPORT_SYMBOL(usb_set_configuration);
+EXPORT_SYMBOL(usb_set_interface);
+
+EXPORT_SYMBOL(usb_make_path);
+EXPORT_SYMBOL(usb_devfs_handle);
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/dabfirmware.h b/drivers/usb/dabfirmware.h
--- a/drivers/usb/dabfirmware.h	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1408 +0,0 @@
-/*
- * dabdata.h - dab usb firmware and bitstream data
- */
-
-static INTEL_HEX_RECORD firmware[] = {
-
-{  2, 0x0000, 0, {0x21,0x57} },
-{  3, 0x0003, 0, {0x02,0x01,0x66} },
-{  3, 0x000b, 0, {0x02,0x01,0x66} },
-{  3, 0x0013, 0, {0x02,0x01,0x66} },
-{  3, 0x001b, 0, {0x02,0x01,0x66} },
-{  3, 0x0023, 0, {0x02,0x01,0x66} },
-{  3, 0x002b, 0, {0x02,0x01,0x66} },
-{  3, 0x0033, 0, {0x02,0x03,0x0f} },
-{  3, 0x003b, 0, {0x02,0x01,0x66} },
-{  3, 0x0043, 0, {0x02,0x01,0x00} },
-{  3, 0x004b, 0, {0x02,0x01,0x66} },
-{  3, 0x0053, 0, {0x02,0x01,0x66} },
-{  3, 0x005b, 0, {0x02,0x04,0xbd} },
-{  3, 0x0063, 0, {0x02,0x01,0x67} },
-{  3, 0x0100, 0, {0x02,0x0c,0x5a} },
-{  3, 0x0104, 0, {0x02,0x01,0xed} },
-{  3, 0x0108, 0, {0x02,0x02,0x51} },
-{  3, 0x010c, 0, {0x02,0x02,0x7c} },
-{  3, 0x0110, 0, {0x02,0x02,0xe4} },
-{  1, 0x0114, 0, {0x32} },
-{  1, 0x0118, 0, {0x32} },
-{  3, 0x011c, 0, {0x02,0x05,0xfd} },
-{  3, 0x0120, 0, {0x02,0x00,0x00} },
-{  3, 0x0124, 0, {0x02,0x00,0x00} },
-{  3, 0x0128, 0, {0x02,0x04,0x3c} },
-{  3, 0x012c, 0, {0x02,0x04,0x6a} },
-{  3, 0x0130, 0, {0x02,0x00,0x00} },
-{  3, 0x0134, 0, {0x02,0x00,0x00} },
-{  3, 0x0138, 0, {0x02,0x00,0x00} },
-{  3, 0x013c, 0, {0x02,0x00,0x00} },
-{  3, 0x0140, 0, {0x02,0x00,0x00} },
-{  3, 0x0144, 0, {0x02,0x00,0x00} },
-{  3, 0x0148, 0, {0x02,0x00,0x00} },
-{  3, 0x014c, 0, {0x02,0x00,0x00} },
-{  3, 0x0150, 0, {0x02,0x00,0x00} },
-{  3, 0x0154, 0, {0x02,0x00,0x00} },
-{ 10, 0x0157, 0, {0x75,0x81,0x7f,0xe5,0x82,0x60,0x03,0x02,0x01,0x61} },
-{  5, 0x0161, 0, {0x12,0x07,0x6f,0x21,0x64} },
-{  1, 0x0166, 0, {0x32} },
-{ 14, 0x0167, 0, {0xc0,0xd0,0xc0,0x86,0xc0,0x82,0xc0,0x83,0xc0,0xe0,0x90,0x7f,0x97,0xe0} },
-{ 14, 0x0175, 0, {0x44,0x80,0xf0,0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
-{ 14, 0x0183, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
-{ 14, 0x0191, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x90,0x7f,0x97,0xe0} },
-{  3, 0x019f, 0, {0x55,0x7f,0xf0} },
-{ 14, 0x01a2, 0, {0x90,0x7f,0x9a,0xe0,0x30,0xe4,0x23,0x90,0x7f,0x68,0xf0,0xf0,0xf0,0xf0} },
-{ 14, 0x01b0, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
-{ 14, 0x01be, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
-{ 14, 0x01cc, 0, {0xe5,0xd8,0xc2,0xe3,0xf5,0xd8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0xd0,0x86} },
-{  3, 0x01da, 0, {0xd0,0xd0,0x32} },
-{  8, 0x01dd, 0, {0x75,0x86,0x00,0x90,0xff,0xc3,0x7c,0x05} },
-{  7, 0x01e5, 0, {0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} },
-{  1, 0x01ec, 0, {0x22} },
-{ 14, 0x01ed, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0xd0} },
-{ 14, 0x01fb, 0, {0x75,0xd0,0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91} },
-{ 13, 0x0209, 0, {0x90,0x88,0x00,0xe0,0xf5,0x41,0x90,0x7f,0xab,0x74,0x02,0xf0,0x90} },
-{  9, 0x0216, 0, {0x7f,0xab,0x74,0x02,0xf0,0xe5,0x32,0x60,0x21} },
-{  4, 0x021f, 0, {0x7a,0x00,0x7b,0x00} },
-{ 11, 0x0223, 0, {0xc3,0xea,0x94,0x18,0xeb,0x64,0x80,0x94,0x80,0x50,0x12} },
-{ 14, 0x022e, 0, {0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0a,0xba,0x00} },
-{  2, 0x023c, 0, {0x01,0x0b} },
-{  2, 0x023e, 0, {0x80,0xe3} },
-{  2, 0x0240, 0, {0xd0,0x86} },
-{ 14, 0x0242, 0, {0xd0,0xd0,0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0} },
-{  1, 0x0250, 0, {0x32} },
-{ 14, 0x0251, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 14, 0x025f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} },
-{  4, 0x026d, 0, {0x04,0xf0,0xd0,0x86} },
-{ 11, 0x0271, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x027c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
-{ 14, 0x028a, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
-{ 13, 0x0298, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} },
-{ 12, 0x02a5, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0x6e,0x00,0x75,0x6f,0x02,0x12} },
-{  6, 0x02b1, 0, {0x11,0x44,0x75,0x70,0x39,0x75} },
-{  6, 0x02b7, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} },
-{ 12, 0x02bd, 0, {0x11,0x75,0x90,0x7f,0xd6,0xe4,0xf0,0x75,0xd8,0x20,0xd0,0x86} },
-{ 14, 0x02c9, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
-{ 13, 0x02d7, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x02e4, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 14, 0x02f2, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} },
-{  4, 0x0300, 0, {0x10,0xf0,0xd0,0x86} },
-{ 11, 0x0304, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x030f, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
-{ 14, 0x031d, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
-{ 12, 0x032b, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0x75,0x6e,0x00,0x75,0x6f,0x02} },
-{  7, 0x0337, 0, {0x12,0x11,0x44,0x75,0x70,0x40,0x75} },
-{  6, 0x033e, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} },
-{ 14, 0x0344, 0, {0x11,0x75,0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0} },
-{  5, 0x0352, 0, {0x75,0xd8,0x10,0xd0,0x86} },
-{ 14, 0x0357, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
-{ 13, 0x0365, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 13, 0x0372, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} },
-{ 12, 0x037f, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x42,0xf0,0x12,0x10,0x1b,0x90} },
-{ 13, 0x038b, 0, {0x7f,0xa6,0xe5,0x43,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40} },
-{  1, 0x0398, 0, {0xf0} },
-{  1, 0x0399, 0, {0x22} },
-{ 13, 0x039a, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} },
-{ 12, 0x03a7, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x44,0xf0,0x12,0x10,0x1b,0x90} },
-{ 12, 0x03b3, 0, {0x7f,0xa6,0xe5,0x45,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0xe5} },
-{ 11, 0x03bf, 0, {0x46,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40,0xf0} },
-{  1, 0x03ca, 0, {0x22} },
-{ 10, 0x03cb, 0, {0x75,0x44,0x02,0x75,0x45,0x00,0x75,0x46,0x00,0x12} },
-{  9, 0x03d5, 0, {0x03,0x9a,0x75,0x42,0x03,0x75,0x43,0x00,0x12} },
-{  2, 0x03de, 0, {0x03,0x72} },
-{  1, 0x03e0, 0, {0x22} },
-{ 12, 0x03e1, 0, {0x90,0x88,0x00,0xe5,0x36,0xf0,0x90,0x88,0x00,0x74,0x10,0x25} },
-{  9, 0x03ed, 0, {0x36,0xf0,0x12,0x01,0xdd,0x75,0x42,0x01,0x75} },
-{  9, 0x03f6, 0, {0x43,0x18,0x12,0x03,0x72,0x75,0x44,0x02,0x75} },
-{  9, 0x03ff, 0,{0x45,0x00,0x75,0x46,0x00,0x12,0x03,0x9a,0x75} },
-{  8, 0x0408, 0,{0x42,0x03,0x75,0x43,0x44,0x12,0x03,0x72} },
-{  1, 0x0410, 0,{0x22} },
-{ 14, 0x0411, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 14, 0x041f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} },
-{  4, 0x042d, 0, {0x02,0xf0,0xd0,0x86} },
-{ 11, 0x0431, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x043c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 14, 0x044a, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xa9,0x74} },
-{  7, 0x0458, 0, {0x04,0xf0,0x75,0x30,0x01,0xd0,0x86} },
-{ 11, 0x045f, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x046a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 14, 0x0478, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} },
-{  7, 0x0486, 0, {0x04,0xf0,0x75,0x31,0x01,0xd0,0x86} },
-{ 11, 0x048d, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x0498, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 12, 0x04a6, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe5,0xf5,0x91,0xd0,0x86} },
-{ 11, 0x04b2, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x04bd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
-{ 12, 0x04cb, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe7,0xf5,0x91,0xd0,0x86} },
-{ 11, 0x04d7, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 12, 0x04e2, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x20,0x90,0x7f,0x96,0xe4,0xf0} },
-{  1, 0x04ee, 0, {0x22} },
-{  7, 0x04ef, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x21} },
-{  1, 0x04f6, 0, {0x22} },
-{ 14, 0x04f7, 0, {0x90,0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xe0,0xfb,0x74,0x80,0x2a,0xfa} },
-{ 14, 0x0505, 0, {0x74,0x80,0x2b,0xfb,0xea,0x03,0x03,0x54,0x3f,0xfc,0xea,0xc4,0x23,0x54} },
-{ 14, 0x0513, 0, {0x1f,0xfa,0x2c,0xfa,0xeb,0x03,0x03,0x54,0x3f,0xfc,0xeb,0xc4,0x23,0x54} },
-{ 11, 0x0521, 0, {0x1f,0xfb,0x2c,0xfb,0x90,0x17,0x0a,0xe0,0xfc,0x60,0x02} },
-{  2, 0x052c, 0, {0x7a,0x00} },
-{  7, 0x052e, 0, {0x90,0x17,0x0c,0xe0,0xfc,0x60,0x02} },
-{  2, 0x0535, 0, {0x7b,0x00} },
-{ 11, 0x0537, 0, {0xea,0x2b,0xfc,0xc3,0x13,0xf5,0x3a,0x75,0x44,0x02,0x8b} },
-{  7, 0x0542, 0, {0x45,0x8a,0x46,0x12,0x03,0x9a,0x75} },
-{  9, 0x0549, 0, {0x6e,0x08,0x75,0x6f,0x00,0x12,0x11,0x44,0x75} },
-{  4, 0x0552, 0, {0x70,0x47,0x75,0x71} },
-{  8, 0x0556, 0, {0x0c,0x75,0x72,0x02,0x12,0x11,0x75,0x85} },
-{  5, 0x055e, 0, {0x3a,0x73,0x12,0x11,0xa0} },
-{  1, 0x0563, 0, {0x22} },
-{ 14, 0x0564, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} },
-{ 14, 0x0572, 0, {0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xef,0xe0,0xfc} },
-{ 14, 0x0580, 0, {0x33,0x95,0xe0,0xfd,0x8c,0x05,0x7c,0x00,0x90,0x7f,0xee,0xe0,0xfe,0x33} },
-{ 14, 0x058e, 0, {0x95,0xe0,0xff,0xec,0x2e,0xfc,0xed,0x3f,0xfd,0x90,0x7f,0xe9,0xe0,0xfe} },
-{  5, 0x059c, 0, {0xbe,0x01,0x02,0x80,0x03} },
-{  3, 0x05a1, 0, {0x02,0x05,0xf9} },
-{  6, 0x05a4, 0, {0xbc,0x01,0x21,0xbd,0x00,0x1e} },
-{ 14, 0x05aa, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfc,0xeb,0x25,0xe0,0xfd,0x2c,0x24,0x00,0xfc} },
-{ 14, 0x05b8, 0, {0xe4,0x34,0x17,0xfd,0x90,0x7e,0xc0,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0} },
-{  2, 0x05c6, 0, {0x80,0x31} },
-{ 14, 0x05c8, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfa,0xeb,0x25,0xe0,0xfb,0x2a,0xfa,0x24,0x00} },
-{ 14, 0x05d6, 0, {0xfb,0xe4,0x34,0x17,0xfc,0x90,0x7e,0xc0,0xe0,0xfd,0x8b,0x82,0x8c,0x83} },
-{ 14, 0x05e4, 0, {0xf0,0x74,0x01,0x2a,0x24,0x00,0xfa,0xe4,0x34,0x17,0xfb,0x90,0x7e,0xc1} },
-{  7, 0x05f2, 0, {0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0} },
-{  3, 0x05f9, 0, {0x75,0x38,0x01} },
-{  1, 0x05fc, 0, {0x22} },
-{ 14, 0x05fd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
-{ 14, 0x060b, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
-{ 13, 0x0619, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} },
-{ 13, 0x0626, 0, {0x7f,0xaa,0x74,0x01,0xf0,0x12,0x05,0x64,0x75,0x37,0x00,0xd0,0x86} },
-{ 14, 0x0633, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
-{ 13, 0x0641, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 14, 0x064e, 0, {0x90,0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xee,0xe0} },
-{ 14, 0x065c, 0, {0xfc,0x33,0x95,0xe0,0xfd,0x90,0x7f,0x96,0xe0,0xfe,0x90,0x7f,0x96,0x74} },
-{ 14, 0x066a, 0, {0x80,0x65,0x06,0xf0,0x90,0x7f,0x00,0x74,0x01,0xf0,0xea,0xc4,0x03,0x54} },
-{ 14, 0x0678, 0, {0xf8,0xfe,0xeb,0x25,0xe0,0xfb,0x2e,0xfe,0x24,0x00,0xfb,0xe4,0x34,0x17} },
-{ 14, 0x0686, 0, {0xff,0x8b,0x82,0x8f,0x83,0xe0,0xfb,0x74,0x01,0x2e,0x24,0x00,0xfe,0xe4} },
-{ 14, 0x0694, 0, {0x34,0x17,0xff,0x8e,0x82,0x8f,0x83,0xe0,0xfe,0x90,0x7f,0xe9,0xe0,0xff} },
-{  3, 0x06a2, 0, {0xbf,0x81,0x0a} },
-{ 10, 0x06a5, 0, {0x90,0x7f,0x00,0xeb,0xf0,0x90,0x7f,0x01,0xee,0xf0} },
-{  8, 0x06af, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x82,0x1a} },
-{  3, 0x06b7, 0, {0xba,0x01,0x0c} },
-{ 12, 0x06ba, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} },
-{ 11, 0x06c6, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0xb5,0xf0} },
-{  8, 0x06d1, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x83,0x1b} },
-{  3, 0x06d9, 0, {0xba,0x01,0x0d} },
-{ 13, 0x06dc, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} },
-{ 11, 0x06e9, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0x12,0xf0} },
-{  8, 0x06f4, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x84,0x1c} },
-{  3, 0x06fc, 0, {0xba,0x01,0x0d} },
-{ 13, 0x06ff, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0c} },
-{ 12, 0x070c, 0, {0x90,0x7f,0x00,0x74,0x80,0xf0,0x90,0x7f,0x01,0x74,0x01,0xf0} },
-{  5, 0x0718, 0, {0x90,0x7f,0xb5,0xec,0xf0} },
-{  1, 0x071d, 0, {0x22} },
-{ 12, 0x071e, 0, {0x75,0x36,0x0d,0x90,0x88,0x00,0x74,0x1d,0xf0,0x75,0x6b,0x80} },
-{ 10, 0x072a, 0, {0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} },
-{  9, 0x0734, 0, {0x6c,0x0f,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} },
-{  9, 0x073d, 0, {0x6c,0x06,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} },
-{  7, 0x0746, 0, {0x6c,0x01,0x12,0x10,0xe2,0x7a,0x00} },
-{  3, 0x074d, 0, {0xba,0xff,0x00} },
-{  2, 0x0750, 0, {0x50,0x0a} },
-{ 10, 0x0752, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} },
-{ 10, 0x075c, 0, {0x75,0x6b,0x80,0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75} },
-{  8, 0x0766, 0, {0x6b,0x80,0x75,0x6c,0x0f,0x12,0x10,0xe2} },
-{  1, 0x076e, 0, {0x22} },
-{ 14, 0x076f, 0, {0x90,0x7f,0xa1,0xe4,0xf0,0x90,0x7f,0xaf,0x74,0x01,0xf0,0x90,0x7f,0x92} },
-{ 14, 0x077d, 0, {0x74,0x02,0xf0,0x75,0x8e,0x31,0x75,0x89,0x21,0x75,0x88,0x00,0x75,0xc8} },
-{ 14, 0x078b, 0, {0x00,0x75,0x8d,0x40,0x75,0x98,0x40,0x75,0xc0,0x40,0x75,0x87,0x00,0x75} },
-{  9, 0x0799, 0, {0x20,0x00,0x75,0x21,0x00,0x75,0x22,0x00,0x75} },
-{  5, 0x07a2, 0, {0x23,0x00,0x75,0x47,0x00} },
-{  7, 0x07a7, 0, {0xc3,0xe5,0x47,0x94,0x20,0x50,0x11} },
-{ 13, 0x07ae, 0, {0xe5,0x47,0x24,0x00,0xf5,0x82,0xe4,0x34,0x17,0xf5,0x83,0xe4,0xf0} },
-{  4, 0x07bb, 0, {0x05,0x47,0x80,0xe8} },
-{  9, 0x07bf, 0, {0xe4,0xf5,0x40,0xf5,0x3f,0xe4,0xf5,0x3c,0xf5} },
-{  7, 0x07c8, 0, {0x3b,0xe4,0xf5,0x3e,0xf5,0x3d,0x75} },
-{ 11, 0x07cf, 0, {0x32,0x00,0x75,0x37,0x00,0x75,0x39,0x00,0x90,0x7f,0x93} },
-{ 14, 0x07da, 0, {0x74,0x3c,0xf0,0x90,0x7f,0x9c,0x74,0xff,0xf0,0x90,0x7f,0x96,0x74,0x80} },
-{ 14, 0x07e8, 0, {0xf0,0x90,0x7f,0x94,0x74,0x70,0xf0,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} },
-{ 14, 0x07f6, 0, {0x7f,0x97,0xe4,0xf0,0x90,0x7f,0x95,0x74,0xc2,0xf0,0x90,0x7f,0x98,0x74} },
-{ 14, 0x0804, 0, {0x28,0xf0,0x90,0x7f,0x9e,0x74,0x28,0xf0,0x90,0x7f,0xf0,0xe4,0xf0,0x90} },
-{ 14, 0x0812, 0, {0x7f,0xf1,0xe4,0xf0,0x90,0x7f,0xf2,0xe4,0xf0,0x90,0x7f,0xf3,0xe4,0xf0} },
-{ 14, 0x0820, 0, {0x90,0x7f,0xf4,0xe4,0xf0,0x90,0x7f,0xf5,0xe4,0xf0,0x90,0x7f,0xf6,0xe4} },
-{ 14, 0x082e, 0, {0xf0,0x90,0x7f,0xf7,0xe4,0xf0,0x90,0x7f,0xf8,0xe4,0xf0,0x90,0x7f,0xf9} },
-{ 14, 0x083c, 0, {0x74,0x38,0xf0,0x90,0x7f,0xfa,0x74,0xa0,0xf0,0x90,0x7f,0xfb,0x74,0xa0} },
-{ 14, 0x084a, 0, {0xf0,0x90,0x7f,0xfc,0x74,0xa0,0xf0,0x90,0x7f,0xfd,0x74,0xa0,0xf0,0x90} },
-{ 14, 0x0858, 0, {0x7f,0xfe,0x74,0xa0,0xf0,0x90,0x7f,0xff,0x74,0xa0,0xf0,0x90,0x7f,0xe0} },
-{ 14, 0x0866, 0, {0x74,0x03,0xf0,0x90,0x7f,0xe1,0x74,0x01,0xf0,0x90,0x7f,0xdd,0x74,0x80} },
-{ 11, 0x0874, 0, {0xf0,0x12,0x12,0x43,0x12,0x07,0x1e,0x7a,0x00,0x7b,0x00} },
-{  9, 0x087f, 0, {0xc3,0xea,0x94,0x1e,0xeb,0x94,0x00,0x50,0x17} },
-{ 12, 0x0888, 0, {0x90,0x88,0x00,0xe0,0xf5,0x47,0x90,0x88,0x0b,0xe0,0xf5,0x47} },
-{  9, 0x0894, 0, {0x90,0x7f,0x68,0xf0,0x0a,0xba,0x00,0x01,0x0b} },
-{  2, 0x089d, 0, {0x80,0xe0} },
-{ 12, 0x089f, 0, {0x12,0x03,0xe1,0x90,0x7f,0xd6,0xe4,0xf0,0x7a,0x00,0x7b,0x00} },
-{ 13, 0x08ab, 0, {0x8a,0x04,0x8b,0x05,0xc3,0xea,0x94,0xe0,0xeb,0x94,0x2e,0x50,0x1a} },
-{ 14, 0x08b8, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} },
-{ 10, 0x08c6, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} },
-{  2, 0x08d0, 0, {0x80,0xd9} },
-{ 13, 0x08d2, 0, {0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0,0x90} },
-{ 14, 0x08df, 0, {0x7f,0xde,0x74,0x05,0xf0,0x90,0x7f,0xdf,0x74,0x05,0xf0,0x90,0x7f,0xac} },
-{ 14, 0x08ed, 0, {0xe4,0xf0,0x90,0x7f,0xad,0x74,0x05,0xf0,0x75,0xa8,0x80,0x75,0xf8,0x10} },
-{ 13, 0x08fb, 0, {0x90,0x7f,0xae,0x74,0x0b,0xf0,0x90,0x7f,0xe2,0x74,0x88,0xf0,0x90} },
-{ 12, 0x0908, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0xe8,0x11,0x75,0x32,0x01,0x75} },
-{ 12, 0x0914, 0, {0x31,0x00,0x75,0x30,0x00,0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7} },
-{ 10, 0x0920, 0, {0xd0,0x05,0xd0,0x04,0x75,0x34,0x00,0x75,0x35,0x01} },
-{ 13, 0x092a, 0, {0x90,0x7f,0xae,0x74,0x03,0xf0,0x8c,0x02,0xba,0x00,0x02,0x80,0x03} },
-{  3, 0x0937, 0, {0x02,0x0a,0x3f} },
-{ 12, 0x093a, 0, {0x85,0x33,0x34,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90,0x7f,0x97} },
-{ 14, 0x0946, 0, {0x74,0x08,0xf0,0x90,0x7f,0x9d,0x74,0x88,0xf0,0x90,0x7f,0x9a,0xe0,0xfa} },
-{ 12, 0x0954, 0, {0x74,0x05,0x5a,0xf5,0x33,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} },
-{ 13, 0x0960, 0, {0x7f,0x97,0x74,0x02,0xf0,0x90,0x7f,0x9d,0x74,0x82,0xf0,0xe5,0x33} },
-{ 13, 0x096d, 0, {0x25,0xe0,0xfa,0x90,0x7f,0x9a,0xe0,0x54,0x05,0xfb,0x4a,0xf5,0x33} },
-{  2, 0x097a, 0, {0x60,0x0c} },
-{ 12, 0x097c, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x4a,0xf0} },
-{ 11, 0x0988, 0, {0x75,0x6e,0x00,0x75,0x6f,0x00,0xc0,0x04,0xc0,0x05,0x12} },
-{ 14, 0x0993, 0, {0x11,0x44,0xd0,0x05,0xd0,0x04,0x90,0x17,0x13,0xe0,0xfa,0x74,0x80,0x2a} },
-{  6, 0x09a1, 0, {0xfa,0xe5,0x33,0xb4,0x04,0x29} },
-{  3, 0x09a7, 0, {0xba,0xa0,0x00} },
-{  2, 0x09aa, 0, {0x50,0x24} },
-{ 13, 0x09ac, 0, {0x90,0x17,0x13,0xe0,0x04,0xfb,0x0b,0x90,0x17,0x13,0xeb,0xf0,0x90} },
-{ 14, 0x09b9, 0, {0x17,0x13,0xe0,0xfb,0x90,0x17,0x15,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05} },
-{  9, 0x09c7, 0, {0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02} },
-{  5, 0x09d0, 0, {0xe5,0x33,0xb4,0x02,0x26} },
-{  6, 0x09d5, 0, {0xc3,0x74,0x04,0x9a,0x50,0x20} },
-{ 13, 0x09db, 0, {0x90,0x17,0x13,0xe0,0xfa,0x1a,0x1a,0x90,0x17,0x13,0xea,0xf0,0x90} },
-{ 13, 0x09e8, 0, {0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xf0,0xc0,0x04,0xc0,0x05,0x12} },
-{  6, 0x09f5, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04} },
-{  5, 0x09fb, 0, {0xe5,0x33,0xb4,0x08,0x1d} },
-{  4, 0x0a00, 0, {0xe5,0x34,0x70,0x19} },
-{ 10, 0x0a04, 0, {0x74,0x01,0x25,0x35,0x54,0x0f,0xf5,0x35,0x85,0x35} },
-{ 12, 0x0a0e, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} },
-{  3, 0x0a1a, 0, {0x05,0xd0,0x04} },
-{  5, 0x0a1d, 0, {0xe5,0x33,0xb4,0x01,0x1d} },
-{  4, 0x0a22, 0, {0xe5,0x34,0x70,0x19} },
-{ 10, 0x0a26, 0, {0xe5,0x35,0x24,0xff,0x54,0x0f,0xf5,0x35,0x85,0x35} },
-{ 12, 0x0a30, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} },
-{  3, 0x0a3c, 0, {0x05,0xd0,0x04} },
-{ 14, 0x0a3f, 0, {0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0,0x04,0x90,0x7f,0x96} },
-{ 14, 0x0a4d, 0, {0xe0,0xfa,0x90,0x7f,0x96,0x74,0x7f,0x5a,0xf0,0x90,0x7f,0x97,0x74,0x08} },
-{ 10, 0x0a5b, 0, {0xf0,0xc3,0xec,0x94,0x00,0xed,0x94,0x02,0x40,0x08} },
-{  8, 0x0a65, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x20,0xe6,0x08} },
-{  8, 0x0a6d, 0, {0xc3,0xe4,0x9c,0x74,0x08,0x9d,0x50,0x13} },
-{ 14, 0x0a75, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x40,0x65,0x02,0xf0,0x7c} },
-{  5, 0x0a83, 0, {0x00,0x7d,0x00,0x80,0x05} },
-{  5, 0x0a88, 0, {0x0c,0xbc,0x00,0x01,0x0d} },
-{  5, 0x0a8d, 0, {0xe5,0x38,0xb4,0x01,0x0e} },
-{ 13, 0x0a92, 0, {0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0x75,0x38} },
-{  1, 0x0a9f, 0, {0x00} },
-{  7, 0x0aa0, 0, {0xe5,0x31,0x70,0x03,0x02,0x09,0x2a} },
-{ 10, 0x0aa7, 0, {0x90,0x7f,0xc9,0xe0,0xfa,0x70,0x03,0x02,0x0c,0x2d} },
-{ 14, 0x0ab1, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} },
-{  9, 0x0abf, 0, {0x7d,0xc0,0xe0,0xfa,0xba,0x2c,0x02,0x80,0x03} },
-{  3, 0x0ac8, 0, {0x02,0x0b,0x36} },
-{  5, 0x0acb, 0, {0x75,0x32,0x00,0x7b,0x00} },
-{  3, 0x0ad0, 0, {0xbb,0x64,0x00} },
-{  2, 0x0ad3, 0, {0x50,0x1c} },
-{ 14, 0x0ad5, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} },
-{ 13, 0x0ae3, 0, {0x04,0xd0,0x03,0xd0,0x02,0x90,0x88,0x0f,0xe0,0xf5,0x47,0x0b,0x80} },
-{  1, 0x0af0, 0, {0xdf} },
-{ 13, 0x0af1, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x07,0x1e,0x12,0x03,0xe1,0x12} },
-{ 12, 0x0afe, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x75,0x6e,0x00,0x75} },
-{ 13, 0x0b0a, 0, {0x6f,0x01,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0x44,0xd0,0x05} },
-{  9, 0x0b17, 0, {0xd0,0x04,0xd0,0x02,0x75,0x70,0x4d,0x75,0x71} },
-{ 11, 0x0b20, 0, {0x0c,0x75,0x72,0x02,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} },
-{ 11, 0x0b2b, 0, {0x11,0x75,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x02,0x0c,0x2d} },
-{  3, 0x0b36, 0, {0xba,0x2a,0x3b} },
-{ 13, 0x0b39, 0, {0x90,0x7f,0x98,0x74,0x20,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} },
-{ 14, 0x0b46, 0, {0x01,0xdd,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x90,0x7f,0x98,0x74,0x28,0xf0} },
-{  2, 0x0b54, 0, {0x7b,0x00} },
-{  3, 0x0b56, 0, {0xbb,0x0a,0x00} },
-{  5, 0x0b59, 0, {0x40,0x03,0x02,0x0c,0x2d} },
-{ 14, 0x0b5e, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} },
-{  8, 0x0b6c, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0b,0x80,0xe2} },
-{  3, 0x0b74, 0, {0xba,0x2b,0x1a} },
-{  8, 0x0b77, 0, {0x90,0x7f,0xc9,0xe0,0xfb,0xbb,0x40,0x12} },
-{ 14, 0x0b7f, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x12,0x05,0xd0,0x05,0xd0,0x04,0xd0} },
-{  4, 0x0b8d, 0, {0x02,0x02,0x0c,0x2d} },
-{  3, 0x0b91, 0, {0xba,0x10,0x1f} },
-{ 14, 0x0b94, 0, {0x90,0x7f,0x96,0xe0,0xfb,0x90,0x7f,0x96,0x74,0x80,0x65,0x03,0xf0,0xc0} },
-{ 14, 0x0ba2, 0, {0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x3d,0xd0,0x05,0xd0,0x04,0xd0,0x02} },
-{  3, 0x0bb0, 0, {0x02,0x0c,0x2d} },
-{  3, 0x0bb3, 0, {0xba,0x11,0x12} },
-{ 14, 0x0bb6, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x6a,0xd0,0x05,0xd0,0x04,0xd0} },
-{  4, 0x0bc4, 0, {0x02,0x02,0x0c,0x2d} },
-{  3, 0x0bc8, 0, {0xba,0x12,0x12} },
-{ 14, 0x0bcb, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x8f,0xd0,0x05,0xd0,0x04,0xd0} },
-{  4, 0x0bd9, 0, {0x02,0x02,0x0c,0x2d} },
-{  3, 0x0bdd, 0, {0xba,0x13,0x0b} },
-{ 11, 0x0be0, 0, {0x90,0x7d,0xc1,0xe0,0xfb,0x90,0x88,0x00,0xf0,0x80,0x42} },
-{  3, 0x0beb, 0, {0xba,0x14,0x11} },
-{ 14, 0x0bee, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0xdd,0xd0,0x05,0xd0,0x04,0xd0} },
-{  3, 0x0bfc, 0, {0x02,0x80,0x2e} },
-{  3, 0x0bff, 0, {0xba,0x15,0x1d} },
-{ 12, 0x0c02, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x75,0x90,0x7d,0xc2,0xe0,0xf5,0x76} },
-{ 14, 0x0c0e, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0,0x05,0xd0,0x04,0xd0} },
-{  3, 0x0c1c, 0, {0x02,0x80,0x0e} },
-{  3, 0x0c1f, 0, {0xba,0x16,0x0b} },
-{ 11, 0x0c22, 0, {0xc0,0x04,0xc0,0x05,0x12,0x13,0xa3,0xd0,0x05,0xd0,0x04} },
-{ 11, 0x0c2d, 0, {0x90,0x7f,0xc9,0xe4,0xf0,0x75,0x31,0x00,0x02,0x09,0x2a} },
-{  1, 0x0c38, 0, {0x22} },
-{  7, 0x0c39, 0, {0x53,0x55,0x50,0x45,0x4e,0x44,0x00} },
-{  7, 0x0c40, 0, {0x52,0x45,0x53,0x55,0x4d,0x45,0x00} },
-{  6, 0x0c47, 0, {0x20,0x56,0x6f,0x6c,0x20,0x00} },
-{ 13, 0x0c4d, 0, {0x44,0x41,0x42,0x55,0x53,0x42,0x20,0x76,0x31,0x2e,0x30,0x30,0x00} },
-{ 14, 0x0c5a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
-{ 14, 0x0c68, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
-{ 13, 0x0c76, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} },
-{ 14, 0x0c83, 0, {0x7f,0xab,0x74,0x01,0xf0,0x90,0x7f,0xe8,0xe0,0xfa,0x90,0x7f,0xe9,0xe0} },
-{  6, 0x0c91, 0, {0xfb,0xbb,0x00,0x02,0x80,0x03} },
-{  3, 0x0c97, 0, {0x02,0x0d,0x38} },
-{  3, 0x0c9a, 0, {0xba,0x80,0x14} },
-{ 14, 0x0c9d, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5} },
-{  6, 0x0cab, 0, {0x74,0x02,0xf0,0x02,0x0e,0xcd} },
-{  5, 0x0cb1, 0, {0xba,0x82,0x02,0x80,0x03} },
-{  3, 0x0cb6, 0, {0x02,0x0d,0x1d} },
-{  8, 0x0cb9, 0, {0x90,0x7f,0xec,0xe0,0xfc,0xbc,0x01,0x00} },
-{  2, 0x0cc1, 0, {0x40,0x21} },
-{  6, 0x0cc3, 0, {0xc3,0x74,0x07,0x9c,0x40,0x1b} },
-{ 14, 0x0cc9, 0, {0xec,0x24,0xff,0x25,0xe0,0xfd,0x24,0xc6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
-{ 13, 0x0cd7, 0, {0x83,0xe0,0xfd,0x53,0x05,0x01,0x90,0x7f,0x00,0xed,0xf0,0x80,0x2b} },
-{  3, 0x0ce4, 0, {0xbc,0x81,0x00} },
-{  2, 0x0ce7, 0, {0x40,0x21} },
-{  6, 0x0ce9, 0, {0xc3,0x74,0x87,0x9c,0x40,0x1b} },
-{ 14, 0x0cef, 0, {0xec,0x24,0x7f,0x25,0xe0,0xfc,0x24,0xb6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
-{ 13, 0x0cfd, 0, {0x83,0xe0,0xfc,0x53,0x04,0x01,0x90,0x7f,0x00,0xec,0xf0,0x80,0x05} },
-{  5, 0x0d0a, 0, {0x90,0x7f,0x00,0xe4,0xf0} },
-{ 14, 0x0d0f, 0, {0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x02,0x0e,0xcd} },
-{  5, 0x0d1d, 0, {0xba,0x81,0x02,0x80,0x03} },
-{  3, 0x0d22, 0, {0x02,0x0e,0xc5} },
-{ 14, 0x0d25, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74} },
-{  5, 0x0d33, 0, {0x02,0xf0,0x02,0x0e,0xcd} },
-{  3, 0x0d38, 0, {0xbb,0x01,0x2d} },
-{  6, 0x0d3b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} },
-{  3, 0x0d41, 0, {0xba,0x02,0x11} },
-{ 13, 0x0d44, 0, {0x75,0x59,0x00,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} },
-{  4, 0x0d51, 0, {0x02,0x02,0x0e,0xcd} },
-{  5, 0x0d55, 0, {0xba,0x21,0x02,0x80,0x03} },
-{  3, 0x0d5a, 0, {0x02,0x0e,0xcd} },
-{ 11, 0x0d5d, 0, {0x75,0x37,0x01,0x90,0x7f,0xc5,0xe4,0xf0,0x02,0x0e,0xcd} },
-{  3, 0x0d68, 0, {0xbb,0x03,0x1f} },
-{  6, 0x0d6b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} },
-{  5, 0x0d71, 0, {0xba,0x02,0x02,0x80,0x03} },
-{  3, 0x0d76, 0, {0x02,0x0e,0xcd} },
-{ 13, 0x0d79, 0, {0x75,0x59,0x01,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} },
-{  4, 0x0d86, 0, {0x02,0x02,0x0e,0xcd} },
-{  3, 0x0d8a, 0, {0xbb,0x06,0x54} },
-{  5, 0x0d8d, 0, {0xba,0x80,0x02,0x80,0x03} },
-{  3, 0x0d92, 0, {0x02,0x0e,0xc5} },
-{  8, 0x0d95, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x01,0x15} },
-{ 12, 0x0d9d, 0, {0x7c,0xfb,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} },
-{  9, 0x0da9, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} },
-{ 10, 0x0db2, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x02,0x02,0x80,0x03} },
-{  3, 0x0dbc, 0, {0x02,0x0e,0xc5} },
-{ 10, 0x0dbf, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x02,0x80,0x03} },
-{  3, 0x0dc9, 0, {0x02,0x0e,0xc5} },
-{ 12, 0x0dcc, 0, {0x7c,0x3b,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} },
-{  9, 0x0dd8, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} },
-{  6, 0x0de1, 0, {0xbb,0x07,0x03,0x02,0x0e,0xc5} },
-{  3, 0x0de7, 0, {0xbb,0x08,0x10} },
-{ 13, 0x0dea, 0, {0xac,0x48,0x90,0x7f,0x00,0xec,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} },
-{  3, 0x0df7, 0, {0x02,0x0e,0xcd} },
-{  3, 0x0dfa, 0, {0xbb,0x09,0x31} },
-{  5, 0x0dfd, 0, {0xba,0x00,0x02,0x80,0x03} },
-{  3, 0x0e02, 0, {0x02,0x0e,0xc5} },
-{ 14, 0x0e05, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xc3,0x74,0x01,0x9c,0x50,0x03,0x02,0x0e,0xc5} },
-{  8, 0x0e13, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x0a} },
-{ 10, 0x0e1b, 0, {0x90,0x17,0x21,0xe4,0xf0,0x90,0x17,0x22,0xe4,0xf0} },
-{  9, 0x0e25, 0, {0x90,0x7f,0xea,0xe0,0xf5,0x48,0x02,0x0e,0xcd} },
-{  3, 0x0e2e, 0, {0xbb,0x0a,0x27} },
-{  5, 0x0e31, 0, {0xba,0x81,0x02,0x80,0x03} },
-{  3, 0x0e36, 0, {0x02,0x0e,0xc5} },
-{ 14, 0x0e39, 0, {0x90,0x7f,0xec,0xe0,0xfa,0x24,0x20,0xfa,0xe4,0x34,0x17,0xfc,0x8a,0x82} },
-{ 14, 0x0e47, 0, {0x8c,0x83,0xe0,0xfa,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} },
-{  3, 0x0e55, 0, {0x02,0x0e,0xcd} },
-{  5, 0x0e58, 0, {0xbb,0x0b,0x02,0x80,0x03} },
-{  3, 0x0e5d, 0, {0x02,0x0e,0xa9} },
-{ 13, 0x0e60, 0, {0x90,0x17,0x20,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0xfa,0xba,0x01,0x1a} },
-{  8, 0x0e6d, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x12} },
-{ 14, 0x0e75, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x90,0x17,0x21,0xf0,0xc0,0x03,0x12,0x04,0xe2} },
-{  4, 0x0e83, 0, {0xd0,0x03,0x80,0x46} },
-{  8, 0x0e87, 0, {0x90,0x7f,0xec,0xe0,0xfa,0xba,0x02,0x3e} },
-{  8, 0x0e8f, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x36} },
-{ 13, 0x0e97, 0, {0xc0,0x03,0x12,0x04,0xef,0xd0,0x03,0x90,0x7f,0xea,0xe0,0xfa,0x90} },
-{  5, 0x0ea4, 0, {0x17,0x22,0xf0,0x80,0x24} },
-{  5, 0x0ea9, 0, {0xbb,0x12,0x02,0x80,0x17} },
-{  5, 0x0eae, 0, {0xbb,0x81,0x02,0x80,0x0d} },
-{  5, 0x0eb3, 0, {0xbb,0x83,0x02,0x80,0x08} },
-{  5, 0x0eb8, 0, {0xbb,0x82,0x02,0x80,0x03} },
-{  3, 0x0ebd, 0, {0xbb,0x84,0x05} },
-{  5, 0x0ec0, 0, {0x12,0x06,0x4e,0x80,0x08} },
-{  8, 0x0ec5, 0, {0x90,0x7f,0xb4,0x74,0x03,0xf0,0x80,0x06} },
-{  6, 0x0ecd, 0, {0x90,0x7f,0xb4,0x74,0x02,0xf0} },
-{  2, 0x0ed3, 0, {0xd0,0x86} },
-{ 14, 0x0ed5, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
-{ 13, 0x0ee3, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
-{ 11, 0x0ef0, 0, {0x90,0x7f,0xec,0xe0,0xf5,0x5a,0xc3,0x94,0x01,0x40,0x1d} },
-{  7, 0x0efb, 0, {0xc3,0x74,0x07,0x95,0x5a,0x40,0x16} },
-{ 13, 0x0f02, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xc6,0xf5,0x82,0xe4,0x34} },
-{  9, 0x0f0f, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0,0x80,0x22} },
-{  7, 0x0f18, 0, {0xc3,0xe5,0x5a,0x94,0x81,0x40,0x1b} },
-{  7, 0x0f1f, 0, {0xc3,0x74,0x87,0x95,0x5a,0x40,0x14} },
-{ 13, 0x0f26, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xb6,0xf5,0x82,0xe4,0x34} },
-{  7, 0x0f33, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0} },
-{  1, 0x0f3a, 0, {0x22} },
-{ 14, 0x0f3b, 0, {0x09,0x02,0xba,0x00,0x03,0x01,0x00,0x40,0x00,0x09,0x04,0x00,0x00,0x00} },
-{ 14, 0x0f49, 0, {0x01,0x01,0x00,0x00,0x09,0x24,0x01,0x00,0x01,0x3d,0x00,0x01,0x01,0x0c} },
-{ 14, 0x0f57, 0, {0x24,0x02,0x01,0x10,0x07,0x00,0x02,0x03,0x00,0x00,0x00,0x0d,0x24,0x06} },
-{ 14, 0x0f65, 0, {0x03,0x01,0x02,0x15,0x00,0x03,0x00,0x03,0x00,0x00,0x09,0x24,0x03,0x02} },
-{ 14, 0x0f73, 0, {0x01,0x01,0x00,0x01,0x00,0x09,0x24,0x03,0x04,0x02,0x03,0x00,0x03,0x00} },
-{ 14, 0x0f81, 0, {0x09,0x24,0x03,0x05,0x03,0x06,0x00,0x01,0x00,0x09,0x04,0x01,0x00,0x00} },
-{ 14, 0x0f8f, 0, {0x01,0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x07} },
-{ 14, 0x0f9d, 0, {0x24,0x01,0x02,0x01,0x01,0x00,0x0b,0x24,0x02,0x01,0x02,0x02,0x10,0x01} },
-{ 14, 0x0fab, 0, {0x80,0xbb,0x00,0x09,0x05,0x88,0x05,0x00,0x01,0x01,0x00,0x00,0x07,0x25} },
-{ 14, 0x0fb9, 0, {0x01,0x00,0x00,0x00,0x00,0x09,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00} },
-{ 14, 0x0fc7, 0, {0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00} },
-{ 14, 0x0fd5, 0, {0x09,0x04,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x07,0x05,0x82,0x02,0x40} },
-{ 14, 0x0fe3, 0, {0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00,0x09,0x05,0x89,0x05,0xa0} },
-{ 10, 0x0ff1, 0, {0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00} },
-{ 14, 0x0ffb, 0, {0x12,0x01,0x00,0x01,0x00,0x00,0x00,0x40,0x47,0x05,0x99,0x99,0x00,0x01} },
-{ 14, 0x1009, 0, {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x02,0xba} },
-{  4, 0x1017, 0, {0x00,0x03,0x01,0x00} },
-{  2, 0x101b, 0, {0x7a,0x00} },
-{  3, 0x101d, 0, {0xba,0x05,0x00} },
-{  2, 0x1020, 0, {0x50,0x17} },
-{  8, 0x1022, 0, {0x90,0x7f,0xa5,0xe0,0xfb,0x30,0xe0,0x05} },
-{  5, 0x102a, 0, {0x90,0x00,0x01,0x80,0x0d} },
-{ 10, 0x102f, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xe4} },
-{  3, 0x1039, 0, {0x90,0x00,0x01} },
-{  1, 0x103c, 0, {0x22} },
-{ 14, 0x103d, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0x00,0x7d} },
-{  4, 0x104b, 0, {0x7e,0xeb,0x60,0x12} },
-{ 14, 0x104f, 0, {0x89,0x82,0x8a,0x83,0xe0,0xa3,0xa9,0x82,0xaa,0x83,0x8c,0x82,0x8d,0x83} },
-{  4, 0x105d, 0, {0xf0,0x0c,0xdb,0xee} },
-{  8, 0x1061, 0, {0x90,0x7d,0xc3,0xe0,0x90,0x7f,0xb9,0xf0} },
-{  1, 0x1069, 0, {0x22} },
-{ 14, 0x106a, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0xc4,0x7d} },
-{  4, 0x1078, 0, {0x7d,0xeb,0x60,0xe5} },
-{ 14, 0x107c, 0, {0x8c,0x82,0x8d,0x83,0xe0,0x0c,0x89,0x82,0x8a,0x83,0xf0,0xa3,0xa9,0x82} },
-{  4, 0x108a, 0, {0xaa,0x83,0xdb,0xee} },
-{  1, 0x108e, 0, {0x22} },
-{ 14, 0x108f, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x05,0x86,0x90,0x7d,0xc1,0xe0,0x05,0x86} },
-{ 14, 0x109d, 0, {0xa3,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0x05,0x86,0xa3,0xa3,0xe0,0xf9} },
-{  5, 0x10ab, 0, {0x60,0x16,0xa3,0x05,0x86} },
-{ 13, 0x10b0, 0, {0x90,0x7f,0xa6,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xc0,0x01,0x12} },
-{  6, 0x10bd, 0, {0x10,0x1b,0xd0,0x01,0xd9,0xed} },
-{  6, 0x10c3, 0, {0x90,0x7f,0xa5,0x74,0x40,0xf0} },
-{  1, 0x10c9, 0, {0x22} },
-{  8, 0x10ca, 0, {0x90,0x88,0x02,0x74,0x01,0xf0,0x7a,0x00} },
-{  3, 0x10d2, 0, {0xba,0xff,0x00} },
-{  2, 0x10d5, 0, {0x50,0x0a} },
-{ 10, 0x10d7, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} },
-{  1, 0x10e1, 0, {0x22} },
-{  5, 0x10e2, 0, {0xe5,0x6b,0xb4,0xc0,0x08} },
-{  8, 0x10e7, 0, {0x90,0x88,0x03,0xe5,0x6c,0xf0,0x80,0x06} },
-{  6, 0x10ef, 0, {0x90,0x88,0x02,0xe5,0x6c,0xf0} },
-{  4, 0x10f5, 0, {0x7a,0x00,0x7b,0x00} },
-{ 11, 0x10f9, 0, {0xc3,0xea,0x94,0x32,0xeb,0x64,0x80,0x94,0x80,0x50,0x07} },
-{  5, 0x1104, 0, {0x0a,0xba,0x00,0x01,0x0b} },
-{  2, 0x1109, 0, {0x80,0xee} },
-{  1, 0x110b, 0, {0x22} },
-{ 10, 0x110c, 0, {0x90,0x88,0x03,0xe5,0x6d,0xf0,0x05,0x39,0x7a,0x00} },
-{  3, 0x1116, 0, {0xba,0x28,0x00} },
-{  2, 0x1119, 0, {0x50,0x03} },
-{  3, 0x111b, 0, {0x0a,0x80,0xf8} },
-{  5, 0x111e, 0, {0xe5,0x39,0xb4,0x10,0x08} },
-{  8, 0x1123, 0, {0x90,0x88,0x02,0x74,0xc0,0xf0,0x80,0x0e} },
-{  5, 0x112b, 0, {0xe5,0x39,0xb4,0x20,0x09} },
-{  9, 0x1130, 0, {0x90,0x88,0x02,0x74,0x80,0xf0,0x75,0x39,0x00} },
-{  2, 0x1139, 0, {0x7a,0x00} },
-{  3, 0x113b, 0, {0xba,0x28,0x00} },
-{  2, 0x113e, 0, {0x50,0x03} },
-{  3, 0x1140, 0, {0x0a,0x80,0xf8} },
-{  1, 0x1143, 0, {0x22} },
-{  4, 0x1144, 0, {0xe5,0x6f,0x60,0x02} },
-{  2, 0x1148, 0, {0x80,0x07} },
-{  7, 0x114a, 0, {0x7a,0x00,0x75,0x39,0x00,0x80,0x05} },
-{  5, 0x1151, 0, {0x7a,0x40,0x75,0x39,0x10} },
-{  9, 0x1156, 0, {0xe5,0x6e,0x2a,0xfa,0xe5,0x6e,0x25,0x39,0xf5} },
-{ 10, 0x115f, 0, {0x39,0x90,0x88,0x02,0x74,0x80,0x2a,0xf0,0x7a,0x00} },
-{  8, 0x1169, 0, {0xc3,0xea,0x64,0x80,0x94,0xa8,0x50,0x03} },
-{  3, 0x1171, 0, {0x0a,0x80,0xf5} },
-{  1, 0x1174, 0, {0x22} },
-{  6, 0x1175, 0, {0xaa,0x70,0xab,0x71,0xac,0x72} },
-{ 12, 0x117b, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x14,0xee,0xfd,0x60,0x18} },
-{ 13, 0x1187, 0, {0x8d,0x6d,0xc0,0x02,0xc0,0x03,0xc0,0x04,0x12,0x11,0x0c,0xd0,0x04} },
-{  9, 0x1194, 0, {0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} },
-{  2, 0x119d, 0, {0x80,0xdc} },
-{  1, 0x119f, 0, {0x22} },
-{ 13, 0x11a0, 0, {0xe5,0x73,0xc4,0x54,0x0f,0xfa,0x53,0x02,0x0f,0xc3,0x74,0x09,0x9a} },
-{  2, 0x11ad, 0, {0x50,0x06} },
-{  6, 0x11af, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} },
-{  4, 0x11b5, 0, {0x74,0x30,0x2a,0xfb} },
-{ 12, 0x11b9, 0, {0x8b,0x6d,0xc0,0x03,0x12,0x11,0x0c,0xd0,0x03,0xaa,0x73,0x53} },
-{  8, 0x11c5, 0, {0x02,0x0f,0xc3,0x74,0x09,0x9a,0x50,0x06} },
-{  6, 0x11cd, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} },
-{  4, 0x11d3, 0, {0x74,0x30,0x2a,0xfb} },
-{  5, 0x11d7, 0, {0x8b,0x6d,0x12,0x11,0x0c} },
-{  1, 0x11dc, 0, {0x22} },
-{  7, 0x11dd, 0, {0x90,0x7d,0xc3,0xe0,0xfa,0x60,0x0f} },
-{ 12, 0x11e4, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x6e,0x90,0x7d,0xc2,0xe0,0xf5,0x6f} },
-{  3, 0x11f0, 0, {0x12,0x11,0x44} },
-{ 12, 0x11f3, 0, {0x90,0x7d,0xff,0xe4,0xf0,0x75,0x70,0xc4,0x75,0x71,0x7d,0x75} },
-{  5, 0x11ff, 0, {0x72,0x01,0x12,0x11,0x75} },
-{  1, 0x1204, 0, {0x22} },
-{  2, 0x1205, 0, {0x7a,0x04} },
-{  3, 0x1207, 0, {0xba,0x40,0x00} },
-{  2, 0x120a, 0, {0x50,0x36} },
-{ 14, 0x120c, 0, {0xea,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfb,0x7c,0x00} },
-{  3, 0x121a, 0, {0xbc,0x08,0x00} },
-{  2, 0x121d, 0, {0x50,0x20} },
-{  6, 0x121f, 0, {0x8b,0x05,0xed,0x30,0xe7,0x0b} },
-{ 11, 0x1225, 0, {0x90,0x7f,0x96,0x74,0x42,0xf0,0x74,0xc3,0xf0,0x80,0x08} },
-{  8, 0x1230, 0, {0x90,0x7f,0x96,0xe4,0xf0,0x74,0x81,0xf0} },
-{  7, 0x1238, 0, {0xeb,0x25,0xe0,0xfb,0x0c,0x80,0xdb} },
-{  3, 0x123f, 0, {0x0a,0x80,0xc5} },
-{  1, 0x1242, 0, {0x22} },
-{  4, 0x1243, 0, {0x7a,0x00,0x7b,0xef} },
-{  3, 0x1247, 0, {0xba,0x10,0x00} },
-{  2, 0x124a, 0, {0x50,0x20} },
-{ 14, 0x124c, 0, {0x74,0x11,0x2b,0xfb,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0x8c,0x82,0x8d} },
-{ 14, 0x125a, 0, {0x83,0xe4,0xf0,0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe4} },
-{  4, 0x1268, 0, {0xf0,0x0a,0x80,0xdb} },
-{  1, 0x126c, 0, {0x22} },
-{ 14, 0x126d, 0, {0x74,0xf8,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
-{ 14, 0x127b, 0, {0x74,0xf9,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
-{ 14, 0x1289, 0, {0x74,0xfa,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
-{ 14, 0x1297, 0, {0x74,0xfb,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
-{ 14, 0x12a5, 0, {0x74,0xff,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
-{  1, 0x12b3, 0, {0x22} },
-{ 14, 0x12b4, 0, {0x12,0x03,0xcb,0x12,0x12,0x6d,0x7a,0xc0,0x7b,0x87,0x7c,0x01,0x74,0x01} },
-{ 14, 0x12c2, 0, {0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74} },
-{ 14, 0x12d0, 0, {0x01,0x12,0x14,0xbf,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e} },
-{ 14, 0x12de, 0, {0x83,0x8f,0xf0,0x74,0x06,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b} },
-{ 14, 0x12ec, 0, {0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74} },
-{ 14, 0x12fa, 0, {0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0} },
-{ 14, 0x1308, 0, {0x74,0x0b,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07} },
-{ 14, 0x1316, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74,0x08,0x12,0x14,0xbf,0x74,0x01,0x2d} },
-{ 14, 0x1324, 0, {0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x01} },
-{ 14, 0x1332, 0, {0x12,0x14,0xbf,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83} },
-{ 14, 0x1340, 0, {0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74,0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f} },
-{ 14, 0x134e, 0, {0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x03,0x12,0x14,0xbf,0x7d,0x00} },
-{  3, 0x135c, 0, {0xbd,0x06,0x00} },
-{  2, 0x135f, 0, {0x50,0x12} },
-{ 11, 0x1361, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x0a,0xba,0x00,0x01,0x0b} },
-{  7, 0x136c, 0, {0xe4,0x12,0x14,0xbf,0x0d,0x80,0xe9} },
-{ 13, 0x1373, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe5,0x74,0x12,0x14,0xbf,0x74,0xf9} },
-{ 14, 0x1380, 0, {0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x0f,0xf0,0x74} },
-{ 14, 0x138e, 0, {0xfe,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x01,0xf0} },
-{  6, 0x139c, 0, {0x12,0x03,0xe1,0x12,0x04,0xf7} },
-{  1, 0x13a2, 0, {0x22} },
-{ 13, 0x13a3, 0, {0x90,0x7d,0xc1,0xe0,0xfa,0x24,0x00,0xfb,0xe4,0x34,0x19,0xfc,0x90} },
-{ 14, 0x13b0, 0, {0x7d,0xc2,0xe0,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x75,0xf0,0x11,0xea,0xa4} },
-{  3, 0x13be, 0, {0xfa,0x7b,0x00} },
-{  3, 0x13c1, 0, {0xbb,0x10,0x00} },
-{  2, 0x13c4, 0, {0x50,0x24} },
-{ 14, 0x13c6, 0, {0xea,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0xeb,0x2c,0xfc,0xe4,0x3d,0xfd} },
-{ 14, 0x13d4, 0, {0x74,0x04,0x2b,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfe} },
-{  8, 0x13e2, 0, {0x8c,0x82,0x8d,0x83,0xf0,0x0b,0x80,0xd7} },
-{ 14, 0x13ea, 0, {0xea,0x24,0x00,0xfa,0xe4,0x34,0x18,0xfb,0x74,0x10,0x2a,0xf5,0x82,0xe4} },
-{  5, 0x13f8, 0, {0x3b,0xf5,0x83,0xe4,0xf0} },
-{  1, 0x13fd, 0, {0x22} },
-{  4, 0x13fe, 0, {0xe5,0x76,0x60,0x02} },
-{  2, 0x1402, 0, {0x80,0x16} },
-{ 12, 0x1404, 0, {0x74,0x0f,0x55,0x75,0xfa,0x8a,0x75,0x24,0x00,0xf5,0x82,0xe4} },
-{ 10, 0x1410, 0, {0x34,0x19,0xf5,0x83,0xe0,0xf5,0x74,0x12,0x12,0xb4} },
-{ 10, 0x141a, 0, {0x12,0x10,0xca,0x75,0x6e,0x00,0x75,0x6f,0x00,0x12} },
-{  6, 0x1424, 0, {0x11,0x44,0x75,0x70,0xb9,0x75} },
-{  6, 0x142a, 0, {0x71,0x14,0x75,0x72,0x02,0x12} },
-{ 11, 0x1430, 0, {0x11,0x75,0xe5,0x76,0xb4,0x02,0x04,0x74,0x01,0x80,0x01} },
-{  1, 0x143b, 0, {0xe4} },
-{  3, 0x143c, 0, {0xfa,0x70,0x0f} },
-{ 12, 0x143f, 0, {0x74,0x01,0x25,0x75,0xf5,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0} },
-{  3, 0x144b, 0, {0x02,0x80,0x0a} },
-{ 10, 0x144e, 0, {0x85,0x75,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0,0x02} },
-{ 12, 0x1458, 0, {0x75,0x6e,0x00,0x75,0x6f,0x01,0xc0,0x02,0x12,0x11,0x44,0xd0} },
-{  4, 0x1464, 0, {0x02,0xea,0x70,0x1a} },
-{ 13, 0x1468, 0, {0x75,0xf0,0x11,0xe5,0x75,0xa4,0xfa,0x24,0x00,0xfa,0xe4,0x34,0x18} },
-{  9, 0x1475, 0, {0xfb,0x8a,0x70,0x8b,0x71,0x75,0x72,0x01,0x12} },
-{  4, 0x147e, 0, {0x11,0x75,0x80,0x36} },
-{  2, 0x1482, 0, {0x7a,0x00} },
-{  3, 0x1484, 0, {0xba,0x10,0x00} },
-{  2, 0x1487, 0, {0x50,0x2f} },
-{ 13, 0x1489, 0, {0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe0,0xfb,0xe5} },
-{  4, 0x1496, 0, {0x75,0xb5,0x03,0x1b} },
-{ 14, 0x149a, 0, {0x75,0xf0,0x11,0xea,0xa4,0xfb,0x24,0x00,0xfb,0xe4,0x34,0x18,0xfc,0x8b} },
-{  9, 0x14a8, 0, {0x70,0x8c,0x71,0x75,0x72,0x01,0xc0,0x02,0x12} },
-{  4, 0x14b1, 0, {0x11,0x75,0xd0,0x02} },
-{  3, 0x14b5, 0, {0x0a,0x80,0xcc} },
-{  1, 0x14b8, 0, {0x22} },
-{  6, 0x14b9, 0, {0x50,0x72,0x6f,0x67,0x20,0x00} },
-{ 14, 0x14bf, 0, {0xc8,0xc0,0xe0,0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0b,0x14,0x60,0x0f,0x14} },
-{  7, 0x14cd, 0, {0x60,0x11,0x14,0x60,0x12,0x80,0x15} },
-{  7, 0x14d4, 0, {0xd0,0xe0,0xa8,0x82,0xf6,0x80,0x0e} },
-{  5, 0x14db, 0, {0xd0,0xe0,0xf0,0x80,0x09} },
-{  4, 0x14e0, 0, {0xd0,0xe0,0x80,0x05} },
-{  5, 0x14e4, 0, {0xd0,0xe0,0xa8,0x82,0xf2} },
-{  4, 0x14e9, 0, {0xc8,0xd0,0xe0,0xc8} },
-{  1, 0x14ed, 0, {0x22} },
-{ 14, 0x14ee, 0, {0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0d,0x14,0x60,0x0f,0x14,0x60,0x0f,0x14} },
-{  6, 0x14fc, 0, {0x60,0x10,0x74,0xff,0x80,0x0f} },
-{  5, 0x1502, 0, {0xa8,0x82,0xe6,0x80,0x0a} },
-{  3, 0x1507, 0, {0xe0,0x80,0x07} },
-{  4, 0x150a, 0, {0xe4,0x93,0x80,0x03} },
-{  3, 0x150e, 0, {0xa8,0x82,0xe2} },
-{  4, 0x1511, 0, {0xf8,0xd0,0xe0,0xc8} },
-{  1, 0x1515, 0, {0x22} },
-{  0, 0x0000, 1, {0} }
-
-};
-
-static unsigned char bitstream[] = {
-
-0x00,0x09,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0, 0x0F,0xF0,0x00,0x00,0x01,0x61,0x00,0x0D,
-0x64,0x61,0x62,0x75,0x73,0x62,0x74,0x72, 0x2E,0x6E,0x63,0x64,0x00,0x62,0x00,0x0B,
-0x73,0x31,0x30,0x78,0x6C,0x76,0x71,0x31, 0x30,0x30,0x00,0x63,0x00,0x0B,0x31,0x39,
-0x39,0x39,0x2F,0x30,0x39,0x2F,0x32,0x34, 0x00,0x64,0x00,0x09,0x31,0x30,0x3A,0x34,
-0x32,0x3A,0x34,0x36,0x00,0x65,0x00,0x00, 0x2E,0xC0,0xFF,0x20,0x17,0x5F,0x9F,0x5B,
-0xFE,0xFB,0xBB,0xB7,0xBB,0xBB,0xFB,0xBF, 0xAF,0xEF,0xFB,0xDF,0xB7,0xFB,0xFB,0x7F,
-0xBF,0xB7,0xEF,0xF2,0xFF,0xFB,0xFE,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xBF,0xFF,0xFF,
-0xFF,0xFF,0xAF,0xFF,0xFA,0xFF,0xFF,0xFF, 0xC9,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xA3,0xFF,0xFB,
-0xFE,0xFF,0xBF,0xEF,0xE3,0xFE,0xFF,0xBF, 0xE3,0xFE,0xFF,0xBF,0x6F,0xFB,0xF6,0xFF,
-0xBF,0xFF,0x47,0xFF,0xFF,0x9F,0xEE,0xF9, 0xFE,0xCF,0x9F,0xEF,0xFB,0xCF,0x9B,0xEE,
-0xF8,0xFE,0xEF,0x8F,0xEE,0xFB,0xFE,0x0B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xBF,0xFF,0xFF,0xFB,0xFF,0xFF, 0xBF,0xFF,0xFF,0xFC,0x17,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xFF,
-0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0xFF, 0xFF,0xFD,0xFF,0xFF,0xDB,0xFF,0xFD,0xFF,
-0x77,0xFF,0xFD,0xFF,0xFF,0xDF,0xFE,0xFD, 0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,
-0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,
-0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0x7F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x2F,0xFF,
-0xF3,0xFD,0xFF,0x7F,0xDE,0xF7,0xFD,0xFF, 0x7F,0xF7,0x7D,0xFF,0x7F,0xDF,0xF7,0xBD,
-0xFF,0x7F,0xFF,0x1F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xEF,0xFB,
-0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, 0x3F,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,
-0x9F,0xE7,0xFA,0x7F,0x9F,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xFF,0xFC,0x7F,0xBF,0xBF,
-0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xB7, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,
-0xFF,0xE0,0xFD,0xF9,0xFE,0x7F,0x9F,0xE7, 0xF9,0xFE,0x7F,0x9D,0xF9,0xFE,0x7D,0x9D,
-0xE7,0xF9,0xFE,0x7F,0x9F,0xED,0xED,0xFF, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,
-0xDF,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF, 0x7F,0xDF,0xFF,0x9B,0xFF,0xEF,0xFB,0xFE,
-0xFB,0xBF,0xEF,0xBB,0xFE,0xFF,0xAF,0xBB, 0xBE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF,
-0xB7,0xBF,0xDB,0xF6,0xBD,0xBF,0x6B,0xDB, 0xF6,0xF9,0xBF,0x5B,0xD6,0xF9,0xBF,0x6F,
-0xDB,0xF6,0xFD,0xBF,0xFF,0x0E,0xFF,0xFF, 0xFF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0x7F,
-0xF7,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xDF,0x9F,0xFF,0xFF,0xFF,0xFE,0xFF,
-0xFF,0xEF,0xFE,0xFE,0xFF,0xFF,0x77,0xFF, 0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F,
-0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xF4,0x7F,0xFF,0xFE,0xFD, 0xBE,0xFF,0xDF,0xFE,0xFF,0xFF,0xEF,0x7F,
-0xFF,0xCF,0xFF,0xCF,0xFF,0xFF,0xFF,0xDF, 0xE6,0xFF,0xFF,0x7F,0xDF,0xF7,0xDD,0x7F,
-0x7F,0xDF,0xF7,0xFF,0x7F,0xDF,0xD7,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFF,0xCD,0xFF,0xF2,
-0xFF,0xFF,0x4F,0x7F,0xF4,0xFF,0xFF,0xFF, 0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xBB,0xFF,0xEF,0xFF,0xFE,0xFF, 0xFF,0xFF,0xEF,0xFF,0xFF,0xEF,0xFF,0xFB,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x65, 0xEF,0xFF,0xFF,0x7F,0xFF,0xFD,0xEF,0xFF,
-0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xCF,0xDF,0xFE,0xFF,
-0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xEF,0xEB,0xFF,0xFE,0xBF,0xFF, 0xEB,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xEE,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xD6,0xFF,0xFD,0xBF,0xFF,0xFB,0xFF,0xFE,
-0xFD,0xFF,0xFF,0xFD,0xEF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0x7F,0xBF, 0xFF,0x5F,0xDF,0xFF,0xFF,0xBF,0x77,0xFF,
-0xFF,0xFF,0x7F,0xD7,0xFF,0xFF,0xFF,0xFF, 0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xDF,0xEF,
-0xFF,0xFF,0xFE,0xFB,0xFF,0xFF,0xDF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xB7,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xAF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xBF,0xDF,0xF3,0xFD,0xFB,0xFF,0x5B,
-0xFD,0xFF,0xBF,0xEF,0xF7,0xFF,0xFF,0x7D, 0xFF,0xFF,0xFF,0xFF,0xF8,0x3B,0xFF,0xBF,
-0x6F,0xFF,0xFE,0xFF,0xBF,0xFF,0xEB,0x7D, 0xFF,0xEF,0xFB,0xFE,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xF2,0x7F,0xFC,0xFF,0x3F,0xDF,0xED, 0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0x5F,0xF7,
-0xB5,0xFF,0xEF,0xFF,0xFF,0xFF,0xE0,0x3F, 0x9F,0x9E,0xFF,0xFF,0xEF,0xFF,0xDF,0xFF,
-0xBF,0x5F,0xBF,0xCF,0xF3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x69,0xAF,0x33,0xFD,0xFF,
-0xFB,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0x7F, 0xD9,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xF5,
-0xA3,0xDF,0x6E,0xDE,0xFF,0xFF,0xBD,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFE,0xE7,0xFD,
-0xFF,0xFF,0xFF,0xF9,0xEF,0xC6,0xFE,0xB7, 0xAD,0xE5,0xF9,0xFF,0xFF,0xFF,0xCF,0xFF,
-0xFF,0xFF,0xCD,0xFB,0x7F,0xFF,0xFF,0xFF, 0xF9,0xF6,0x0F,0xDF,0xEC,0xCF,0x7F,0xFF,
-0xFB,0x7F,0xFF,0xFF,0xFF,0xFD,0xFF,0xFE, 0xF9,0xFD,0x7F,0xFF,0x7F,0xFF,0xF9,0x5B,
-0xFF,0x73,0xDC,0xFD,0x7B,0xDF,0xFF,0xFF, 0xFF,0x7B,0xFF,0xFF,0xF7,0x53,0xD6,0xFF,
-0xFF,0xFF,0xFF,0xD8,0x9F,0xFE,0xFF,0xEF, 0x7F,0xEE,0xFF,0xFF,0xFF,0xFB,0xED,0xED,
-0xFD,0xFF,0xFE,0xFF,0xFF,0xFB,0x7F,0xFF, 0xE2,0x7F,0xFF,0x6F,0xD8,0x57,0xF7,0xFF,
-0xFF,0xFF,0xDF,0xFF,0xE8,0xFF,0xFF,0xFD, 0xFF,0xFF,0xFC,0x7F,0xFF,0xE4,0xFF,0xFB,
-0xEF,0xFB,0xFE,0xDF,0xB7,0xED,0xFF,0xFE, 0xDF,0x7F,0xFF,0xFE,0x7F,0xB7,0xFF,0xFF,
-0xFF,0xFF,0x89,0xFF,0xFF,0xCF,0xF3,0xFE, 0x7F,0xFF,0xEF,0xFF,0xFE,0x7E,0x7F,0xFB,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1, 0xFF,0xEB,0x7A,0xD5,0xBF,0x6F,0xDB,0xBE,
-0xFD,0xB7,0xD8,0xF6,0xE5,0xBF,0x6F,0xFB, 0xFE,0xF5,0xBD,0x7E,0x06,0xFF,0xDF,0xF7,
-0xFB,0xF6,0xFF,0x3F,0xFF,0xDB,0xFF,0xFF, 0x6F,0xFB,0xF7,0xFF,0xFF,0xFF,0xFB,0xFE,
-0xF7,0xAF,0xFF,0xB7,0xED,0xEF,0xF7,0xFE, 0xFF,0xFF,0xDF,0xFF,0xFE,0xFF,0xEF,0xFF,
-0xFF,0xFF,0xFF,0xBF,0xF7,0xFC,0x1F,0xEE, 0xFB,0xFE,0xBD,0xFF,0x7F,0x5F,0xD7,0xFD,
-0xFB,0x43,0xFF,0xFF,0xFD,0xFF,0x5F,0xFF, 0xF7,0xFF,0xF9,0x3F,0xFF,0xCF,0xF3,0xFD,
-0xF7,0x7E,0xEF,0xA7,0xF9,0xFE,0x8F,0xA7, 0xE9,0xF3,0x7E,0x9F,0xFB,0xF8,0xFF,0xFF,
-0x3F,0xFD,0x7F,0x5F,0xDF,0xFD,0xFF,0xFF, 0x5F,0xFF,0xFD,0x5F,0xFF,0xFF,0x7F,0xFD,
-0x7F,0xFD,0x9F,0xFF,0xE0,0xFF,0xFA,0xF8, 0xBE,0x6F,0x9F,0xE6,0xF8,0xBE,0x3F,0x9A,
-0xF9,0xBE,0x6F,0x9F,0xE2,0xF9,0xFE,0x6F, 0x9F,0xF9,0xFF,0xF5,0xFD,0x7F,0xCF,0xDF,
-0xFD,0xFD,0x7F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xF7,0xF5,0xFD,0x0F,0xDB,0xFF,0xD3,0xFF,
-0xEB,0xFA,0xFF,0xFF,0xBF,0xFF,0xFA,0xFF, 0xFF,0xCB,0xFB,0xFE,0xFF,0xFF,0xEB,0xFA,
-0xFE,0xFF,0xFF,0xB7,0xFF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xDF,0xF5,0xFF,0xFF,0xD7,0xFF,
-0xFF,0xFF,0xDF,0xD7,0xF5,0xFF,0x7F,0xFE, 0x4F,0xFF,0xFD,0xFF,0x7F,0x7F,0xFF,0xAD,
-0xEB,0xFB,0xFF,0xAD,0xFF,0xFF,0xFF,0xFF, 0xAF,0xEB,0xFB,0xFF,0xFC,0x0D,0xFF,0xFF,
-0xDF,0xD2,0xFD,0xFF,0xFF,0xFD,0xF6,0xFF, 0xFF,0x7F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,
-0xFF,0xFB,0x3F,0x7D,0xEB,0x32,0xFE,0xBF, 0x2F,0xEB,0xFA,0xAE,0xBD,0xE0,0xFA,0x7E,
-0xBF,0xAD,0xEB,0xFA,0xFE,0xBF,0xF5,0x7F, 0xFF,0xDE,0xFE,0xE3,0xFB,0xFF,0xFF,0xFF,
-0xDF,0xEF,0x4F,0xDF,0xFF,0x7F,0xDF,0xFF, 0xF7,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xEF,
-0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xDF, 0xED,0xFB,0xDF,0xFF,0xBF,0xFF,0xFF,0xFF,
-0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFF,0xFE,0xDD,0xFE,0xEF,0xFD,0xFF,
-0xFF,0xFB,0xFE,0xF7,0xFF,0x93,0xFD,0xFB, 0x7E,0xFF,0xFE,0x87,0xE9,0xFF,0x7F,0xB3,
-0x9F,0xFE,0xFE,0xFF,0xAF,0xFD,0xFE,0x7E, 0x3F,0xFE,0x67,0xFF,0xFF,0xF7,0xFF,0xFF,
-0xFC,0xF7,0xDF,0xFD,0xFF,0x7F,0xFF,0xFF, 0x7F,0x6D,0xFF,0xFF,0xFE,0xFF,0xFF,0x2F,
-0xFF,0xBF,0xFF,0xFF,0xEE,0xFF,0xBE,0xFF, 0xFF,0xFE,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF,
-0xEF,0xFF,0xFF,0xFA,0x5F,0xFF,0xFF,0xFB, 0xFF,0xFF,0xEF,0xFF,0xFB,0xFE,0xFD,0xFF,
-0xFE,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFE,0xBF,0xDF,0xFF,0xFB,0xFF,0xFF,0xF7,
-0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x7F,0xFF,
-0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xF3,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF,
-0xFF,0xDF,0xE2,0xFF,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xE7,0xFF,0xFD,
-0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xED, 0xEF,0xFD,0xFF,0xFF,0xDF,0xD7,0xF5,0xFD,
-0x7F,0x5D,0xFD,0xFF,0x7F,0xDF,0x97,0xF4, 0xFD,0x7B,0x5F,0xFF,0xC9,0xFF,0xFB,0xFE,
-0xFF,0xBF,0xFF,0x5F,0xFF,0xFF,0xF7,0xFF, 0xEF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xF7,0xFF,0xD7,0xFD,0x7D,0x7F,0xFF, 0xFF,0xFF,0xFF,0xEF,0xDF,0xF7,0xFD,0xFF,
-0xBB,0xFF,0xFF,0x7F,0xFF,0xFE,0xE3,0xFF, 0xF9,0xFE,0x7F,0xBF,0xEF,0xFB,0xFE,0xFF,
-0xBF,0xF9,0xFE,0xFF,0x9F,0xEF,0xF9,0xFE, 0xFF,0xBF,0xF3,0xDA,0xFF,0x37,0xCD,0xF3,
-0x7C,0xDF,0x37,0xCD,0xF3,0x7F,0x37,0xCD, 0xF3,0x7C,0xDF,0x37,0xCC,0xF3,0x7F,0x5A,
-0xBD,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFD, 0xBF,0x6F,0xDE,0xFD,0xBF,0x6F,0xDB,0xF6,
-0xFD,0xBF,0x6F,0xFE,0xF1,0x6F,0xEB,0x7A, 0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7,0xAF,
-0x7A,0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7, 0xFF,0x7E,0xFF,0xFE,0xCD,0xB3,0x6C,0xDB,
-0x36,0xCD,0xB3,0x6C,0xDE,0xCD,0xB3,0x6C, 0xDB,0x36,0xCD,0xB3,0x6C,0xDF,0xC9,0xBF,
-0xF7,0xBD,0xEF,0x7A,0x9E,0xA7,0xA9,0xEA, 0x7A,0xB7,0xBD,0xEA,0x7B,0xDE,0xA7,0xBD,
-0xCA,0x72,0x8D,0x91,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xF7,0xEF,0xFB,
-0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFE, 0x87,0xFF,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,
-0xFD,0xBF,0x6F,0xF6,0xFD,0xBF,0x6F,0xDB, 0xF6,0xFD,0xBF,0x6F,0xFE,0x4F,0xFF,0xBF,
-0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,0xEF, 0xBE,0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,
-0xEF,0xFC,0x5F,0xFF,0xFF,0xFF,0x3F,0xCF, 0xF3,0xFC,0xFF,0x3F,0xCF,0xFC,0xFF,0x3F,
-0xCF,0xF3,0xFC,0xFF,0x3F,0xCF,0xFD,0x9F, 0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,
-0xEB,0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFF,0xE1,0x6F,0xFD,0xFF,0x7F,
-0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFD,0xFF, 0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,
-0x7A,0xBF,0xFB,0xFE,0xDF,0xB7,0xED,0xFB, 0x7E,0xDF,0xB7,0xFB,0x7E,0xDF,0xB7,0xED,
-0xFB,0x7E,0xDF,0xB7,0xFF,0xC9,0xFF,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,
-0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEE, 0xFB,0xFE,0xBB,0xFF,0xFE,0xFF,0xBF,0xEF,
-0xFB,0xFE,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0x3F,0xCF,0xFF,0xE7,
-0xFE,0xFF,0xF5,0xFD,0x77,0x5D,0xD7,0x35, 0xDD,0x77,0xD7,0xF5,0xCD,0x7B,0x5D,0xD7,
-0xF5,0xDD,0x77,0xFE,0x27,0xFF,0xFF,0x8B, 0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9,0xAF,
-0x8B,0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9, 0xFE,0x1F,0xFF,0x5F,0xD7,0xF5,0xFD,0x7F,
-0x5F,0xD7,0xF5,0xFF,0x5F,0xD7,0xF5,0xFD, 0x7F,0x5F,0xD7,0xF5,0xFF,0xFA,0x3F,0xFE,
-0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xEB, 0xEC,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,
-0xEB,0xFF,0xFE,0x7F,0xFD,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6, 0xFF,0xFA,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,
-0xF7,0xFC,0xFF,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFD,0xFF,0xF5,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0x02,0xFF,0xFE,0xBF,0xAB,0xEB,0xFA, 0xBE,0xBF,0x23,0xEB,0xDE,0x1F,0xAF,0xEA,
-0xFA,0xFE,0xAF,0xAF,0xEB,0xFD,0x97,0xFF, 0xF3,0xFC,0x7B,0x1F,0xCF,0xF1,0xFC,0x7F,
-0x1F,0xF1,0xFC,0x77,0x1F,0xCD,0xF1,0xFC, 0xFF,0x1F,0xFE,0x87,0xFF,0xAF,0xEF,0xFA,
-0xFE,0xFF,0xAF,0xEF,0xFA,0xFD,0xBF,0x2B, 0xFB,0x7E,0xBF,0xBF,0xEB,0xFB,0xFB,0xFB,
-0xDF,0xFF,0xFB,0xF7,0xFF,0xFF,0x7F,0xF7, 0xF7,0xFF,0xFD,0xDF,0xFE,0xFC,0xDF,0xFF,
-0xDF,0xFF,0xFD,0xFF,0xDA,0xBF,0xFF,0xBB, 0xEF,0xFB,0xF9,0xFF,0xBE,0xEF,0xFB,0xFB,
-0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xF7,0x7F,0xFD,0xD7,0xFF,0xFF,0x7F,
-0xFF,0xFF,0xFF,0xFE,0xF7,0xFF,0xFE,0xFF, 0xF7,0xFF,0xFF,0x7F,0xFF,0xFF,0xEC,0xFF,
-0xFF,0xFE,0xDF,0xBF,0xFF,0xFB,0xFE,0xFF, 0xBB,0x68,0xAE,0x1F,0xAE,0xFB,0xFB,0xFF,
-0xFF,0xBF,0xFF,0xD5,0xFF,0x7F,0xFF,0xFF, 0xF7,0xFE,0xFE,0xFF,0xBF,0xEF,0x9F,0xFD,
-0x7F,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,0xFF, 0xBB,0xF7,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF,
-0xFF,0xBF,0xFB,0xFF,0xFF,0xFF,0xDE,0x3F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0xFF,0xFF,
-0xFF,0xFF,0xEF,0xFF,0x7F,0xFB,0xFD,0xFB, 0x7F,0xFF,0xFF,0xFF,0xFF,0xCF,0xF3,0x7C,
-0xFF,0x7F,0x8D,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFB,0xFF,0xF7,0xFB,0xFE,0xFD,0xFF,0xFF,
-0xFF,0xFF,0xF7,0xFD,0xFF,0x7F,0xFD,0x1F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xBF,0xDF,0xFF,
-0xFF,0xFE,0x5C,0xFF,0x6D,0xFF,0x7F,0xAB, 0xE7,0xF1,0xFF,0xFD,0x9F,0xFF,0xFF,0xAD,
-0xEB,0x7A,0x3F,0x1F,0xFF,0xFF,0xFE,0xBF, 0xAF,0xF3,0xDE,0xF5,0xFF,0x8F,0xFB,0xDF,
-0xE6,0x7F,0xFF,0xDF,0xF3,0xFD,0xFF,0x7E, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF7,0xF3,
-0x7F,0xDF,0xF7,0xEF,0xFF,0xF6,0x3F,0x9F, 0xDF,0xFF,0xFF,0xEE,0xFF,0xFF,0xEF,0xFB,
-0xFF,0xFF,0xF9,0xFB,0xFE,0x4F,0xBF,0xEF, 0xBB,0xFF,0x69,0xAF,0xAF,0xFC,0xFF,0x3F,
-0xDD,0xFF,0xFC,0xBF,0x8F,0xFF,0xFD,0xF3, 0xBF,0xED,0x9E,0xFC,0xBF,0x6F,0xF5,0xD3,
-0xDF,0xFF,0xDB,0xD6,0xF5,0xEF,0xFD,0xFE, 0xFF,0xB9,0xFF,0x1F,0xD2,0xA9,0xAF,0xFF,
-0xDB,0xF7,0xBF,0xEF,0x46,0xFF,0xFF,0xAD, 0xEB,0x7A,0xDF,0xEF,0xF7,0xFF,0x7F,0xF7,
-0x9F,0xED,0xFF,0x7F,0xFF,0xAD,0xEB,0x7F, 0xF5,0x6F,0xFF,0xFD,0xFB,0xD6,0xF4,0xF7,
-0xFB,0xF9,0x7E,0x7F,0xFF,0x5F,0xC2,0xFE, 0xBF,0xFD,0xFB,0x33,0xDF,0xF9,0x5B,0xFF,
-0xFF,0xDD,0x67,0x7D,0xCF,0xEF,0xDB,0xEC, 0xFF,0x77,0xDD,0xF7,0xFD,0xFF,0xFF,0xDE,
-0xA7,0xBF,0xD4,0x9F,0xFF,0xFF,0xBF,0xEF, 0xFE,0xFF,0xDF,0xEF,0xBB,0xFF,0xFF,0xEF,
-0xEB,0xFA,0xFF,0xEF,0xBD,0xFB,0xFF,0xE2, 0x7F,0xFF,0xDF,0xDF,0xF7,0xFD,0xBF,0xBB,
-0x73,0xF7,0xFD,0x7F,0xDF,0xDE,0xF7,0xBF, 0xEA,0xDB,0xF6,0xFF,0xD6,0xFF,0xFF,0x66,
-0xFF,0xBE,0xFF,0xBF,0x6B,0xD9,0xF6,0xDF, 0xFF,0xFB,0x7E,0x7F,0xB7,0x7E,0xFF,0xFE,
-0xFF,0xCD,0xFF,0xFE,0x7F,0xFF,0xFC,0xFD, 0x3F,0xFB,0xFB,0xF7,0xFF,0xFF,0xFB,0xF6,
-0x7D,0xFE,0x7F,0xFF,0xFC,0xFF,0xB9,0xFF, 0xF9,0xFA,0xFE,0xBF,0xAF,0x5B,0xD6,0xED,
-0xAD,0x7B,0xF6,0xF9,0xBF,0xEF,0xF8,0xFA, 0xFE,0xBF,0xFE,0xE6,0xFF,0xFF,0xF7,0xFD,
-0xFF,0x7F,0xBF,0xEF,0xF3,0xFF,0xFF,0x6F, 0xF7,0xFE,0xFF,0xFF,0xF7,0xFD,0xFE,0xF7,
-0xEF,0xFF,0xFB,0xEF,0xFB,0x7E,0xDE,0xFE, 0xFF,0xBF,0xFF,0xFE,0xFF,0xFF,0xFB,0xFF,
-0xFF,0xEF,0xFB,0x6F,0xFC,0x1F,0xFE,0xE7, 0xFF,0xFF,0xFF,0xEF,0xFF,0xD3,0xB4,0xBB,
-0xFF,0xFF,0xFD,0xBF,0x6F,0xE3,0xFE,0xFF, 0xBF,0xFC,0xBF,0xF7,0xCF,0xF7,0xFD,0xFF,
-0x2F,0xDF,0xAB,0xEA,0xFF,0xDF,0xE7,0xEA, 0x9A,0xAF,0xEF,0xFB,0xFE,0xFF,0xF5,0x3F,
-0xFD,0x7E,0xFF,0xD7,0xF5,0xFB,0xFF,0xFD, 0xF7,0xFF,0x7F,0xFE,0xF7,0xFD,0xFF,0xD7,
-0xFF,0xD7,0x7F,0xEE,0x7F,0xFA,0x79,0xFE, 0x2F,0x8B,0xE6,0xF9,0xFE,0x3F,0x9E,0xF9,
-0xBE,0x2F,0x0B,0xE7,0xF9,0xFE,0x2F,0x9F, 0xFD,0xFF,0xFE,0x7D,0x7F,0x5F,0xD7,0xFF,
-0xFF,0x7F,0xFF,0xFD,0xFF,0x7F,0x5F,0x97, 0xFF,0xFD,0x7F,0x5F,0xFF,0xE3,0xFF,0xFF,
-0xFA,0xFE,0xBF,0xAF,0xFB,0xFB,0xFF,0xFF, 0xCF,0xEB,0xFE,0xBF,0xAF,0xFF,0xFA,0xFE,
-0xBF,0xFF,0x87,0xFF,0xFF,0xF5,0xFF,0xFF, 0xFF,0xFF,0xFD,0xFF,0x7F,0xFF,0xFF,0xFF,
-0xFB,0xFF,0xFF,0xF5,0xFF,0xFF,0xFE,0x0F, 0xFF,0xFD,0xEB,0xFF,0xFF,0xF7,0xFF,0xEF,
-0x7B,0xDF,0xFE,0xFF,0xFF,0xDF,0xF7,0xFD, 0xEB,0x7F,0xDF,0xFF,0x5F,0xFF,0xFF,0xFF,
-0xFF,0xFD,0xBF,0xFF,0x7E,0xFA,0xBF,0xC7, 0xDB,0xF7,0xBD,0x3F,0xFB,0xFF,0xF6,0xFF,
-0xFA,0xAF,0xFF,0xEB,0xFA,0xFE,0x3F,0x2F, 0xEA,0xFA,0x3E,0xAD,0xC9,0xBA,0xF6,0xAD,
-0xAF,0xEB,0xFA,0xF6,0xBF,0xFE,0x7F,0xFF, 0xFF,0xFD,0xFF,0xF1,0x7F,0x3F,0xCF,0xF1,
-0xEF,0xFF,0x7F,0xFF,0xBC,0xDF,0xDF,0xF7, 0xDD,0xFF,0xE0,0x7F,0xFF,0xFF,0xFE,0xFF,
-0xFA,0xEC,0xBB,0x7F,0x5F,0xFF,0xFB,0xEC, 0xFF,0xEF,0xB7,0xFF,0xF7,0xFF,0xFF,0xB5,
-0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEE,0xDF, 0x5F,0xDF,0xDE,0xFF,0xAE,0xE7,0x77,0xFF,
-0xFF,0xDF,0xF7,0xFF,0xE3,0xFF,0xFA,0xBB, 0xFE,0xFF,0xAF,0xFD,0xFB,0xFE,0xBF,0xAB,
-0xF9,0xFE,0xFF,0xBF,0x7F,0xBF,0xFE,0xBD, 0xFE,0xD7,0xFF,0x9F,0xFD,0xFF,0xBE,0xEF,
-0xFF,0xEE,0xFD,0xBB,0x5B,0xEF,0xFF,0x7F, 0xEF,0xFF,0xEF,0xFF,0x7F,0xFF,0x4F,0xFF,
-0xEF,0xFB,0xBC,0xFC,0xFF,0xFF,0xFF,0xFE, 0xFE,0xFD,0xFA,0xFE,0xFB,0xFF,0xFD,0xF3,
-0xFB,0xFF,0xF8,0x5F,0xFF,0xFF,0xD7,0xF5, 0xFD,0xDF,0xEF,0xFF,0xF3,0xDC,0x5F,0xCE,
-0xF5,0xBD,0xFF,0xFF,0xD7,0xFF,0xFF,0xF9, 0x3F,0xFF,0xDF,0xF7,0xFF,0xFE,0xFF,0xFD,
-0xFF,0xFB,0xFF,0xF7,0xB9,0x7D,0xFE,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF9,0x7F,0xFF,0xFE,
-0xFF,0xFF,0x7F,0xFF,0xFE,0xFF,0xFF,0xF7, 0xF6,0xFF,0xBF,0xF1,0xF8,0xFF,0xFF,0xFF,
-0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF,
-0x9B,0xFB,0x7F,0xFF,0xFF,0xFF,0xC1,0xFF, 0xDF,0xFF,0x3F,0x5F,0xD7,0xBF,0xEF,0xBB,
-0xDE,0xEE,0xFF,0x7F,0xDF,0xFF,0xFE,0xF5, 0x7F,0xDF,0xFF,0x99,0xFF,0xFF,0xFA,0xFF,
-0xBF,0xFD,0xEB,0x7A,0xFF,0xB7,0xFE,0xFE, 0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xBF,0xFF,
-0x97,0xFF,0xFD,0xF7,0xFF,0x7F,0xF7,0xFF, 0xFF,0xFD,0x5F,0xFE,0xF3,0xF9,0xDF,0xDF,
-0xFF,0xFF,0xFC,0xFF,0xFF,0x83,0xFF,0xFF, 0xFE,0xFF,0x9E,0xEC,0xFB,0xEE,0xFF,0x9F,
-0xBF,0xEF,0xFF,0xFE,0xED,0x7B,0xFF,0xFF, 0xFF,0xF1,0x5A,0xFF,0xFF,0xFD,0xFF,0x7C,
-0x69,0x3B,0xDF,0xFF,0x7F,0x1F,0xDF,0xFF, 0xFD,0xBA,0xFF,0xFF,0xFB,0xFF,0x5B,0xBD,
-0xFF,0xFF,0xFF,0xFF,0xD7,0xB6,0xED,0xE9, 0xFF,0xD6,0xBD,0x6F,0x5F,0xFB,0xFF,0xEF,
-0xFF,0x5F,0xFE,0xF6,0x6F,0xFF,0xFF,0xFF, 0xFF,0xF7,0xEB,0x7A,0xDF,0xFF,0x9F,0x7F,
-0x7F,0xFF,0xB7,0xFF,0xFF,0xFE,0xDF,0xFF, 0x6C,0xFF,0xFB,0xFF,0xBB,0x6F,0xEB,0xFE,
-0xCC,0xF7,0xA5,0xFA,0x5C,0xF5,0x75,0xBB, 0xB7,0xDF,0xFE,0x6F,0x5F,0xC5,0xBF,0xFD,
-0x7B,0xFE,0xFF,0x95,0xE7,0x29,0xCF,0x4F, 0xF5,0x91,0xEE,0x6B,0xDF,0xEF,0xFD,0x54,
-0xF5,0xBD,0xB1,0xFF,0xEF,0xEE,0xFB,0xBE, 0xBF,0xAF,0xFE,0xDE,0xBD,0x6F,0xDA,0xF2,
-0xFF,0xAF,0xBE,0xFF,0xFF,0xFD,0x7E,0xA7, 0xFF,0xF7,0xFF,0xBF,0xEF,0x7B,0xF6,0xFD,
-0xBD,0x4A,0xF2,0x85,0x85,0xBF,0x5B,0xFE, 0xB5,0xFD,0xFA,0xFF,0x4F,0xFF,0xFE,0xDF,
-0xFF,0xED,0xFF,0xBF,0xFF,0xBF,0x7F,0xFE, 0xFF,0xB7,0x6D,0xFF,0xF7,0xBF,0xBF,0xEF,
-0xFD,0x1F,0xFF,0xFE,0x7D,0xFF,0x67,0xFF, 0xFF,0xFF,0x3F,0x7F,0xFE,0xBF,0xFF,0xE7,
-0xDF,0xE7,0xFF,0xEF,0x6B,0xFC,0x1F,0xFF, 0xBF,0xEF,0xFB,0xFE,0xDE,0xBF,0xAF,0xFA,
-0xFF,0xB6,0xEF,0xF9,0xFE,0xFF,0x8F,0xEF, 0xDB,0xEF,0xAB,0x6F,0xFB,0xFE,0xFF,0xFF,
-0xEF,0xFD,0xFF,0x7F,0xFF,0xFF,0xDE,0xFF, 0xFF,0xEF,0xFF,0xFF,0xFF,0x3F,0xFF,0x6C,
-0xFF,0xBF,0xFB,0xFF,0xFE,0xFF,0xFB,0xFE, 0xDF,0xFF,0xFF,0xEF,0xFF,0xFF,0xBF,0xFF,
-0xFF,0xFE,0xFB,0xFF,0xD5,0x7F,0xFF,0xFF, 0xEF,0xFB,0xFF,0xFF,0xBF,0xEF,0x43,0xB5,
-0xFD,0x6F,0xCF,0xD6,0xBE,0x3F,0x7F,0xDB, 0xFE,0xC3,0xFF,0xFD,0xFF,0xAF,0xEB,0xFB,
-0xFC,0xFF,0x3E,0xEF,0xE8,0xFA,0xBD,0xCD, 0xAA,0xFE,0xFE,0x7D,0xCF,0xFF,0xB7,0xFF,
-0xF7,0xFF,0xFF,0xFF,0xFD,0xFF,0x75,0xCD, 0x52,0xD7,0xFD,0xFB,0xF7,0xDD,0xFB,0xEF,
-0xEB,0xFF,0xFF,0x4F,0xFF,0xBF,0x9F,0xE7, 0xF9,0xFC,0x7F,0x8B,0xC3,0xF9,0xAF,0x8F,
-0xE7,0xE9,0xBE,0x7F,0x9F,0xE6,0xF9,0xFC, 0x5F,0xFF,0xFF,0xF7,0xFD,0xFF,0x7A,0x5F,
-0xD7,0xED,0xFF,0xFF,0xD7,0xFF,0xDD,0x7F, 0xE7,0xFF,0xFC,0xFF,0xFC,0x3F,0xFF,0xFF,
-0xFF,0xFB,0xFF,0xFE,0xBF,0xAF,0xFF,0xFD, 0xFF,0xEF,0xFF,0xEB,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xF7,0x7F,0xFF,0x7F,0xDF,0xFF,0xFD, 0xFD,0x7F,0xFE,0xF7,0xFD,0x7F,0xDF,0xFF,
-0xFD,0xFF,0xFF,0xDF,0xFB,0xFF,0xEE,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7A,0xDF,0xF5,
-0xFD,0xFA,0xDF,0xF7,0xFC,0xFF,0x7F,0xDF, 0xBF,0xED,0xFF,0xC9,0xFF,0xDF,0xFF,0xBF,
-0x2F,0xFB,0xFF,0xBC,0xAD,0xFF,0xF7,0xFF, 0xFF,0xEF,0xD3,0xFF,0x7D,0xBF,0x6F,0xFF,
-0xFA,0xFF,0xFE,0xBF,0xAE,0xEA,0xFA,0xBE, 0xAD,0xA5,0xEB,0xCE,0xBF,0xA7,0xEB,0x5A,
-0xDE,0xBD,0xAF,0x6B,0xFD,0x57,0xFF,0xFF, 0xF4,0x7F,0x1F,0x7F,0xFD,0xFF,0x7F,0x36,
-0xF0,0xDF,0x79,0xFF,0xFF,0xFF,0xF7,0xFD, 0xBF,0xFF,0x87,0xFF,0xFB,0xF3,0xFC,0xFF,
-0xFF,0xFF,0xFF,0x7E,0xFF,0xBF,0xDF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xF8,0x9F,
-0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFD, 0xF7,0xFC,0xBD,0xFF,0xFE,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFB,0xF9,0xBF,0xFF,0xFF,0xEB, 0xE2,0xFE,0xFF,0xBF,0xEF,0xA9,0xBA,0x2F,
-0xEB,0xF9,0xFE,0x77,0xDF,0xF7,0xFF,0xFF, 0xF9,0x7F,0xFF,0xFF,0x7F,0xEF,0xD7,0xFF,
-0xFD,0xFF,0xFB,0xF5,0xFF,0xBF,0x6F,0xDF, 0xFF,0xFF,0xFD,0xFF,0xFF,0xF0,0xFF,0xFF,
-0xFF,0x3F,0xCF,0xFF,0xBA,0xEE,0x9B,0xBF, 0xEE,0xD7,0xFE,0xCD,0xEF,0xFF,0xDF,0xBF,
-0xFF,0xFF,0xC5,0xFF,0xFF,0xFD,0x7F,0x4F, 0xFD,0xF6,0xD9,0xFF,0x4F,0xD6,0xFD,0xBF,
-0x6E,0xFF,0xFF,0xF4,0x7F,0xFF,0x7F,0x8B, 0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF9,0xFE,
-0x37,0xFF,0xD9,0xFB,0xF5,0xAF,0xFD,0xFF, 0xFF,0xFB,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,
-0xFB,0xF7,0xFF,0xFD,0xFF,0x7C,0xFA,0x7E, 0x4F,0xFC,0xDF,0x1D,0xC7,0xFF,0xFF,0xFF,
-0xFF,0xAE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFB, 0xFF,0xFF,0xFE,0xFE,0xFC,0xFF,0x7F,0x7F,
-0xBF,0xEF,0xFE,0xFF,0xFF,0xFF,0x5F,0xFD, 0xFF,0xFF,0xFF,0xFD,0x6F,0x5A,0xD7,0x7B,
-0xBE,0x5F,0xFE,0x39,0xFF,0xF7,0xFF,0xF7, 0xFD,0xFE,0xAA,0x1F,0xFF,0xFF,0xFF,0xFF,
-0xFE,0xFE,0xAB,0xAF,0xFD,0xFE,0xBF,0xFF, 0xF7,0xFF,0x7F,0xFE,0x8F,0xE3,0xFB,0xEE,
-0x7F,0xFF,0xFF,0xFF,0xFF,0xEB,0xFB,0xFF, 0xFD,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFB,0xE4,0x3F,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF3,0xEF,0xBB,0xFB,
-0xBF,0xEF,0xBB,0xFF,0xD7,0xBF,0xFF,0xFF, 0xFF,0x29,0xAF,0xF7,0xFF,0xFF,0xFB,0xFF,
-0xFB,0xE6,0xFF,0x0F,0xFB,0x3F,0xDF,0x0F, 0xFF,0xAF,0xFF,0xFF,0xFF,0xF5,0xC3,0xDF,
-0x5F,0xFF,0xFF,0xFF,0xFE,0x6B,0xCA,0xBE, 0xBC,0xFF,0x9F,0xF2,0xBF,0xFF,0xFE,0xFA,
-0xFF,0xFF,0xEF,0x16,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFC,0xDF,0x97,0xFD,0x79,0xFF,0x37,
-0xE7,0x7F,0xFF,0xFF,0xB5,0xFF,0xFF,0xF6, 0x2F,0xFF,0xFD,0xFB,0xFE,0xFF,0xFF,0xFD,
-0x5F,0x57,0x5F,0xFF,0xDB,0x52,0xDF,0xFF, 0xFD,0xBF,0xFF,0xFF,0xFC,0xDB,0xFF,0x7B,
-0xB5,0xFD,0x7F,0xFF,0x71,0x9C,0x6E,0xFF, 0xF6,0x35,0xA5,0x9B,0xFF,0xFF,0xFD,0xFF,
-0xFF,0xDB,0x9E,0x7F,0xFE,0xEF,0xFB,0xFF, 0xFF,0xBD,0xEF,0xFF,0xDE,0xB7,0xF9,0x4B,
-0xFF,0xF5,0xEF,0xFF,0xFF,0xFF,0xE8,0x7E, 0xFF,0xEA,0xDF,0xF7,0xFF,0xFD,0x69,0x5B,
-0xFC,0x9F,0xEF,0x78,0xD6,0xFF,0xEB,0xEF, 0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xED,0xFF,
-0xFF,0xFF,0xFF,0xE3,0xF9,0xF6,0xBF,0xFF, 0xFF,0xFE,0xDF,0xFF,0x7F,0xFF,0xFF,0xFF,
-0xD1,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF, 0xE7,0xF9,0xFF,0xBF,0x7F,0xD9,0xFF,0xFD,
-0xFE,0x7F,0xFF,0xFE,0xFF,0xF9,0xFF,0xFB, 0xD6,0xDF,0xBF,0xEF,0x5B,0xD6,0xFF,0xBF,
-0xFB,0xF6,0xFF,0xBF,0xEF,0xF8,0xF6,0xDD, 0xBE,0xFE,0x16,0xFF,0xBF,0xEF,0xFF,0xFE,
-0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0x6F,0xFB, 0xFF,0xFF,0xFF,0x6F,0xF3,0xFF,0xF7,0xEF,
-0xFB,0xFF,0xBF,0xFF,0xEF,0xFE,0xFF,0xBF, 0xFF,0xFF,0xFF,0xBE,0xBF,0xFF,0xEF,0xFF,
-0x7F,0xEF,0xFF,0xFD,0x17,0xFB,0x7B,0xFF, 0xFF,0xFD,0x7F,0xDB,0xF6,0xF4,0x7F,0xFA,
-0xFE,0xF5,0xBF,0xEB,0xE3,0xF7,0xFF,0xFF, 0xE9,0xBF,0xFF,0xAF,0xF7,0xFD,0xF3,0x7E,
-0x8F,0xA3,0xEA,0xFF,0xCB,0xF3,0xEE,0xFF, 0xBF,0xEF,0xF7,0xF9,0xFF,0xFE,0x7F,0xFF,
-0xFF,0xFF,0xFF,0xF5,0xFB,0xF6,0xFF,0xF5, 0x2F,0xFE,0xFB,0xD7,0xBF,0xFF,0xBE,0xDF,
-0x9F,0xFF,0xF0,0xFF,0xFF,0xF9,0xFE,0x7F, 0x8F,0xA3,0xF8,0xFE,0x6F,0x9F,0xF9,0xF6,
-0x2F,0x9F,0xE7,0xF9,0xFE,0x2F,0x9F,0xE1, 0xFF,0xFF,0xFF,0x7F,0xDF,0xF7,0xF5,0xFD,
-0x7F,0x7F,0xF5,0xFF,0x9F,0x5F,0xFB,0xFE, 0xFF,0x7F,0xFF,0xFF,0xCB,0xFF,0xFF,0xFB,
-0xFE,0xFF,0xBF,0xAF,0xFB,0xFE,0xFF,0xDF, 0xFE,0xFE,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xC7,0xFF,0xFF,0xFD,0xFF,0x7F,0xDD, 0xF7,0xFD,0xFF,0xFF,0xD7,0xFF,0xFD,0x7F,
-0xFF,0xFB,0xFD,0xFF,0xFF,0xFE,0xEF,0x7F, 0xFD,0xEF,0xFB,0xFE,0xFB,0xFD,0xFF,0x7F,
-0xDF,0xFD,0xFF,0x7A,0xDF,0xF7,0xFD,0xFF, 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xD3,0xF7,
-0xFF,0xFF,0x6F,0xDB,0xFF,0xFF,0xEF,0xCB, 0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
-0x29,0xFF,0xE8,0xDA,0x76,0x9F,0xAF,0x6A, 0xDA,0xFE,0x35,0xEB,0xDA,0xD6,0xBF,0xAB,
-0xEB,0x7A,0xDE,0xBF,0xD7,0x7F,0xFF,0xFE, 0xFF,0xBF,0xEF,0xFD,0xDF,0x77,0xBF,0xFD,
-0x37,0xEF,0xFF,0xEF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xF7,0x7E,
-0xDF,0xFF,0xFF,0xFF,0xFA,0xB7,0x7F,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x89,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x9F,0xFB,0xFF,0xFF,0xFF,0xE7,0xFF,
-0xFF,0xFF,0xFF,0xAA,0xFF,0xAB,0xFB,0xFA, 0xEF,0xBF,0xFF,0xDF,0xFA,0x7B,0xB9,0xFE,
-0xFE,0xFF,0xFD,0xFF,0xF7,0xFE,0x3F,0xFF, 0xB7,0xFF,0xF7,0xEE,0xFF,0x7F,0xEF,0xFF,
-0xFF,0x7F,0xFF,0x1F,0xFB,0xFF,0xBF,0xFB, 0xFE,0xFF,0xBD,0xFF,0xFF,0x2F,0xFF,0xBF,
-0xFF,0x7F,0xDF,0xFA,0xFF,0xFF,0xFC,0xEE, 0xF5,0xF3,0xBE,0xFB,0x0F,0xEF,0xF3,0xBE,
-0xEF,0xFC,0x5F,0xFF,0x5A,0xFF,0xF7,0xDF, 0xFF,0xFF,0xFE,0xD5,0xFC,0x5F,0xFB,0xF2,
-0xFF,0xFF,0x2F,0xBB,0xF3,0xFF,0xFF,0xBF, 0xFF,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
-0xBF,0xFF,0xFF,0xFD,0x7B,0xFF,0xDF,0xB9, 0xFF,0xFB,0xFF,0xD8,0x7F,0xFF,0xFF,0xFF,
-0xFB,0xFF,0xFC,0x7F,0x1F,0xBF,0xE0,0xDF, 0xF7,0xEF,0xFF,0xFD,0x7F,0xFE,0xDF,0xFF,
-0xE0,0xFF,0xFF,0xFD,0xEF,0xFB,0xFF,0xFE, 0xF7,0xDF,0xFF,0xEB,0x5F,0xFF,0xF7,0xFF,
-0xFF,0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0xFD, 0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,0x3B,0xDC,
-0xFD,0x6D,0x7B,0x5F,0x57,0xF5,0xFD,0x7F, 0x5F,0xFF,0xB1,0xFF,0xEB,0xFF,0xFF,0xFF,
-0xFB,0xFB,0xFE,0xFF,0xBF,0xFB,0xBE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xAF,0xFE,0xF7,
-0xDF,0xDF,0xFF,0xFF,0xFF,0x7F,0xCF,0xF3, 0xF8,0xFF,0xD7,0xFB,0xFF,0x5F,0xBF,0xF7,
-0xFB,0xFF,0x7F,0xFE,0x23,0xFF,0xFF,0xFE, 0x7F,0xF3,0xFF,0xFB,0xFE,0xFF,0xFF,0xF3,
-0xFF,0xFF,0xF5,0xF9,0xFF,0x3F,0xFF,0xFF, 0xF0,0x9A,0xFF,0xBE,0x7F,0xFF,0xFC,0xF9,
-0xFF,0xFD,0xAF,0xEB,0xFE,0xBF,0xFF,0xCF, 0xF3,0xFE,0x7F,0xFF,0xFF,0x5B,0xBD,0xFF,
-0xBC,0xEB,0xFF,0xD7,0xD4,0xAF,0xAF,0xFD, 0xFF,0xCF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,
-0xFD,0xFE,0xFF,0x6F,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFD,0x7F,0x5E,0xFD,0xBF,0xDB,0xF6,
-0xFD,0xBF,0x6F,0xFB,0xEE,0xFD,0xFF,0x7A, 0xFF,0xFA,0xFB,0xFF,0x3F,0xFB,0xB7,0x5F,
-0xD6,0xF7,0x1F,0x71,0xDC,0x77,0x1D,0xC7, 0x31,0xDC,0x77,0xDF,0xF9,0xBF,0xF5,0x5B,
-0xF4,0xD7,0x9D,0xAE,0xFF,0xBF,0xFD,0xBF, 0xDB,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFE,
-0x3D,0x81,0xFF,0xEB,0xFE,0xFE,0xFE,0xFF, 0xEB,0x7A,0xDF,0x7D,0x77,0x7D,0xF5,0x79,
-0xDF,0x57,0xDD,0xF5,0x7D,0x7E,0xE6,0xFF, 0xD6,0x3F,0xBF,0x7F,0xFF,0xD4,0xF5,0x3F,
-0xBF,0xFB,0xBE,0xEF,0xB3,0xEE,0xFB,0x9E, 0xEF,0xBB,0xFE,0x8B,0xFF,0xFE,0xDF,0xB7,
-0xED,0xFF,0xF7,0xFD,0xFE,0xFF,0xEF,0xBB, 0xEE,0xFF,0xBE,0xEF,0xBB,0xEE,0xEB,0xFC,
-0x1F,0xFF,0xFF,0xFD,0xFF,0xE7,0xFF,0xF7, 0xFD,0xFF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB,
-0xFE,0xFF,0xBF,0xEB,0xFA,0x1F,0xFF,0xB7, 0xEF,0x5B,0xFE,0xFF,0xAF,0xEB,0xDD,0xE7,
-0xDE,0x77,0x9D,0xE7,0x79,0xDE,0x77,0x9D, 0xBF,0xE6,0x6F,0xFF,0xFE,0xFF,0xBF,0xEF,
-0xFB,0xFE,0xFD,0xBF,0x6F,0xF6,0xFD,0xBF, 0x6F,0xDB,0xF6,0xFD,0xBF,0xFF,0x7E,0xFF,
-0xFF,0xFB,0xFE,0xFE,0xFF,0xEF,0xFB,0xFD, 0xEF,0x7E,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7,
-0xBD,0xEF,0xFF,0xD5,0xFF,0xBF,0xFF,0xEF, 0xFE,0xFF,0xFC,0x3F,0x0F,0xE7,0xFE,0x7F,
-0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFE, 0xF3,0xFF,0xFE,0xDF,0xAD,0xDF,0x67,0xEE,
-0xFB,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFF,0x23,0xFF,0xFF,
-0xFF,0xFF,0x7F,0xFF,0xF3,0xBC,0xDB,0xFE, 0xFB,0xFF,0xFB,0xBE,0xF7,0xFB,0xFF,0x7F,
-0xDF,0xFF,0xCF,0xFB,0xFF,0x9F,0xE3,0xF9, 0xBE,0x3F,0x8F,0xE7,0x79,0xFF,0x9D,0xE7,
-0xF9,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x5F, 0xFF,0xCF,0xF7,0xFF,0xFF,0xFF,0xDF,0xF7,
-0xFE,0x7F,0xE7,0xF9,0xFE,0x7F,0xFF,0xFF, 0xFB,0xFE,0xFF,0xFF,0xBF,0xFF,0xBF,0xBF,
-0xFF,0xFE,0xFF,0xBF,0xEF,0xFF,0xFD,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,
-0xFF,0x3F,0xFF,0xBF,0xFF,0xF7,0xFF,0xFF, 0x7F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0xEF,0xFF, 0x5F,0xF7,0xBF,0xF9,0xFE,0xDF,0xB7,0xFD,
-0xFF,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xDD,0xFF,0xF2,0xFF,0xBF,0xFF,
-0xFF,0xBF,0xFF,0xFF,0x2F,0xF2,0xFF,0xBF, 0x2F,0x7B,0xD2,0xF7,0xBF,0x2F,0xFF,0xBB,
-0xFF,0xEE,0x8F,0xAF,0xEB,0xFA,0xFE,0x3F, 0xA7,0x69,0xCE,0x8F,0xA4,0xEA,0xFA,0xEE,
-0xB7,0xAE,0xEB,0xFD,0xC7,0xFF,0xF7,0xF7, 0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3E,0xF3,
-0x74,0xFF,0x3F,0x4F,0xFF,0xE7,0xFF,0x3F, 0xFE,0xA7,0xFF,0xFF,0xDF,0xF7,0xB7,0xFF,
-0xF7,0xFF,0xBA,0xEF,0x37,0xEB,0xFB,0xFE, 0xBF,0xFB,0xFE,0xF3,0xFF,0xF9,0xDF,0xFF,
-0xBF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFD,0xDF,0xFF,0xFD,0xFF,0xFF,0xFB,0xFE,
-0xFD,0xFF,0xFB,0xBF,0xFE,0x3F,0xED,0xFF, 0xDF,0xBE,0x3D,0xA7,0xFB,0xFA,0x3F,0xE6,
-0xE1,0xFE,0xFE,0x3F,0xEF,0xE3,0xDF,0xF5, 0x7F,0xFE,0xFF,0x7E,0xFF,0xFF,0xFF,0xFF,
-0xEF,0x6F,0xF6,0xFF,0x7D,0xEF,0xD7,0xDE, 0xFF,0x7D,0xEF,0xFF,0xF2,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0x7B,0xDE,0xFB,0xE6,0xEE, 0xEF,0x37,0x6E,0xF3,0x7E,0xEB,0x37,0xEF,
-0xFF,0xC1,0xFF,0xFE,0xFF,0xF7,0xEF,0xFF, 0xFF,0xFF,0xBF,0x3F,0xD2,0xDF,0xBF,0x2F,
-0x7B,0xE2,0xFF,0xFE,0x3B,0xBD,0xDB,0xFF, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFE,
-0xFF,0xFB,0xFF,0xFF,0xBF,0xFF,0xFB,0xDF, 0xFF,0xBF,0xFF,0xB7,0xFF,0xFF,0xBF,0xEF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, 0x7F,0xFF,0x1F,0xEF,0xF1,0xFD,0xFF,0xF6,
-0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF, 0xFF,0xFF,0xFE,0x9F,0xFF,0xFF,0xFF,0x77,
-0xEF,0xF7,0xFB,0xFF,0xFE,0x5F,0xFF,0xFF, 0xBF,0xCF,0xFB,0xF7,0xDD,0xF7,0xF5,0xFF,
-0x5F,0xD5,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5, 0xFF,0xFB,0x0F,0xFF,0xFF,0xA9,0xEA,0x7A,
-0xFF,0xAF,0x8F,0xFE,0xDF,0xAF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFB,0xDF,0xE5,0x5F,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x57,0xFF, 0xFF,0x6F,0x77,0xBF,0xF7,0xFB,0xFF,0x7F,
-0xBF,0xF7,0xFF,0xFC,0xBF,0xFF,0x9F,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF,0x1F,
-0xCF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFB, 0x65,0xAF,0xF3,0x7C,0xFF,0x3F,0xDF,0xFF,
-0xFD,0xE9,0xFE,0x7F,0xE7,0xFF,0xFE,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFD,0xE3,0xDF,0xFB,
-0xDB,0xF6,0xFD,0xEF,0x5B,0xFB,0xFF,0xDF, 0xFC,0xFF,0x3F,0xDF,0xF3,0xFD,0xFF,0x7F,
-0xDF,0xEF,0x66,0xFF,0xDF,0xAD,0xEB,0x7A, 0xDE,0xF7,0xF7,0xE7,0xD9,0xFD,0x9F,0x67,
-0xD9,0xF6,0x7D,0x9F,0xE7,0xDF,0xF5,0x47, 0xFD,0x65,0x5B,0xD6,0xF4,0xFE,0xFF,0xEF,
-0xFF,0x6D,0xF6,0xDD,0xB7,0x6D,0xDB,0x76, 0xDC,0xB7,0x7D,0xFA,0x9B,0xF6,0x6D,0x9D,
-0x67,0x59,0xDF,0xF7,0xDD,0xFF,0xEB,0xFE, 0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xE3,
-0xD1,0x9F,0xFF,0xBD,0xBF,0xEF,0xFE,0xF7, 0xBF,0xBF,0xF7,0xD7,0x7F,0xDD,0xF7,0x9D,
-0xDF,0x7F,0xDF,0xF7,0xFF,0xE0,0x7F,0xFD, 0xC1,0xDF,0xF7,0xFD,0xC7,0x7F,0x7F,0xFB,
-0xFF,0xBB,0xEC,0xFB,0x3E,0xFF,0xBF,0xEC, 0xFB,0xFF,0xD8,0x7F,0xBF,0x6C,0xFF,0xBE,
-0xFF,0xBF,0xED,0xFF,0xEF,0xFE,0xFB,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEE,0xFF,0xC5,
-0xFF,0xAF,0x6F,0xFF,0xFC,0xFD,0x3F,0xE7, 0xFF,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,
-0xEF,0xFB,0xFE,0xBF,0x89,0xFE,0xFA,0xBA, 0xFE,0xBF,0xAF,0xFB,0xF6,0xF5,0xD9,0x7D,
-0x97,0x65,0xD9,0x74,0x5D,0x97,0x65,0xD3, 0xFE,0xD6,0xFF,0xBF,0xF7,0xFD,0xFF,0x7F,
-0xBF,0xCF,0xFB,0xFE,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFF,0xF6,0x8F,0xFB,
-0xFF,0xEF,0xFB,0x7E,0xDB,0xFE,0xFF,0xBE, 0xEF,0xEE,0xFB,0xBE,0xEF,0xBB,0xEE,0xFB,
-0xBE,0xFF,0xFF,0xDF,0xFF,0x43,0xFF,0xFF, 0xFB,0xEF,0x5F,0xB7,0xFE,0x7F,0xE7,0xF9,
-0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xF9, 0xBF,0xFE,0xAF,0x77,0xFD,0xFF,0x2F,0xAF,
-0xA7,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xF1,0x7F,0xEF,0xDF,
-0xFF,0x97,0xF5,0xEF,0xFF,0xDF,0xFF,0xFF, 0xBF,0xFF,0xBF,0xFF,0xFF,0xFE,0xFF,0xFF,
-0xFF,0xE0,0xFF,0xFF,0xF9,0xFE,0x2F,0x8B, 0xE3,0xF8,0xBE,0x77,0x9F,0xF9,0xDA,0x77,
-0x9D,0xE7,0x79,0xDE,0x77,0x9F,0xDD,0xFF, 0xFD,0xFD,0x7F,0x5F,0xD7,0xFD,0xFF,0x7F,
-0xE7,0xFE,0x7F,0x97,0xE7,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFF,0xAB,0xFF,0xEF,0xFA,0xFE,
-0xBF,0xAF,0xFF,0xFA,0xFF,0xFF,0xDF,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,
-0x67,0xFF,0xF7,0xF5,0xFF,0xFF,0xFF,0xDF, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xBD, 0xEB,0xFF,0xFF,0xF7,0xAD,0xEB,0xFF,0xDF,
-0xFD,0xFF,0x3F,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0xFD,
-0xBF,0xFF,0xCB,0xF4,0xFF,0x7F,0xD3,0xF7, 0xFD,0x3F,0x7F,0xD3,0xF7,0xFF,0xFC,0x3F,
-0xFF,0xEA,0xFA,0xBE,0xAF,0xAB,0xEB,0xBA, 0xF4,0x95,0x6B,0x52,0xD4,0xAD,0x2F,0x4A,
-0xD2,0xF6,0xBF,0xD2,0x7F,0xF7,0x3F,0xFF, 0xFF,0xF3,0x7F,0xFF,0xFF,0xF7,0xFF,0xBA,
-0xDF,0xFB,0xFD,0xFF,0xBF,0xFF,0xFB,0xFF, 0xF8,0x7F,0xEA,0xFF,0xFE,0xFE,0xDF,0xFF,
-0xF7,0xFF,0x7F,0xBB,0xFF,0xFF,0xBF,0xDF, 0xFB,0xFF,0xFF,0xBF,0xFF,0xB1,0x7F,0xFF,
-0xFB,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, 0xCF,0xFE,0xFF,0xFF,0xEF,0xFF,0xF7,0xFF,
-0xFF,0xFF,0xF1,0xFF,0x69,0xBE,0xFA,0xBF, 0xAF,0xE2,0xFF,0xFE,0xFD,0xAF,0xF3,0xFE,
-0xFF,0xBF,0xEF,0xFB,0xFC,0xFF,0xFF,0x07, 0xFD,0x95,0xDB,0xDF,0x7F,0xDF,0xAF,0xFF,
-0xF7,0xAF,0x36,0xFE,0xBF,0x65,0xEB,0xF6, 0xFE,0x9F,0x6F,0xFE,0x07,0xFF,0xCF,0xFF,
-0xF8,0xFE,0xFF,0xCF,0xFF,0xF6,0xFA,0xE7, 0xFB,0xFE,0xFF,0xBB,0xED,0xF9,0xFF,0xFF,
-0xFF,0x5F,0xFF,0xFF,0xFF,0x75,0xFF,0xEF, 0x7E,0xFD,0xE0,0xE8,0x5E,0xD3,0xE5,0xF9,
-0x3E,0x5F,0xD7,0xF7,0xFF,0xFA,0x2F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0x7F,
-0x7F,0xD7,0xF5,0x7D,0x5F,0x57,0xD5,0xF5, 0xEF,0xFF,0xF3,0x7F,0xFC,0x7F,0xFF,0xC7,
-0xF1,0xFF,0xFF,0x1F,0xCF,0xB0,0xFF,0x3F, 0xCF,0xF3,0xFC,0xFF,0x3F,0xCE,0xFF,0xE4,
-0xFF,0xDF,0x7F,0xFE,0xF7,0xBB,0xFF,0xFF, 0xDF,0xEF,0xEE,0xFF,0xBF,0xEF,0xFB,0xFE,
-0xBF,0xBF,0xEF,0xFF,0xD1,0xFF,0xFF,0xFF, 0xFD,0xFB,0xFF,0xFD,0xFF,0xFB,0x9F,0xE9,
-0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xBF, 0xFF,0xB3,0xFF,0xFF,0xF7,0xFF,0xFF,0xAF,
-0xF7,0xFF,0xB6,0x3F,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFA,0xFE,0xBF,0xFE,0xA7,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF, 0xFE,0x9F,0xF7,0xF9,0xFF,0x7F,0x9F,0xE7,
-0xFF,0xFF,0xFE,0xAF,0x6F,0xFF,0xFF,0xFF, 0x9F,0xFF,0xDF,0xFF,0x7D,0x5F,0xDD,0xFF,
-0xFB,0xBF,0xE7,0xBB,0xFF,0xFB,0xDF,0x6D, 0x5F,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xEB,0xF7,0xFF,0xE7,0xEF,0xF7,0xFF,0xFF, 0x7F,0xFF,0xF7,0xFF,0xFC,0x8F,0xFF,0xEF,
-0xFD,0xFE,0xFF,0xBE,0xF4,0xF2,0x7D,0xD7, 0xCF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xCF,0x6B,0xFF,0xBF,0x3F,0xFB,0xF2, 0xFC,0x7F,0xEB,0xFF,0x9F,0xFA,0xFF,0xFF,
-0x3F,0xFF,0xF3,0xFF,0xFF,0xFD,0x70,0xF7, 0xFF,0xFF,0xBF,0xFF,0xFB,0xD7,0xFE,0xF5,
-0x77,0xFF,0x15,0xDD,0x77,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFB,0xCD,0xBF,0xFF,0xFD,0xFF,
-0xFF,0xDF,0x37,0xCD,0xF9,0xEC,0xFE,0xEF, 0xBB,0xF4,0xFB,0x3F,0x4F,0xB3,0xFF,0xFD,
-0xCB,0xFF,0xE9,0x7E,0x54,0x9F,0xE5,0x4B, 0xB7,0xFF,0xDD,0x7D,0xC7,0x71,0xDD,0x77,
-0x5D,0xD7,0x75,0xCD,0x7F,0xD6,0xFF,0xD3, 0xF6,0xF9,0x3F,0x6D,0x95,0xAF,0x7F,0xFE,
-0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xF6,0xC7,0xFF,0xAD,0x7B,0xCA,0xFF,
-0xBF,0xBF,0xEF,0xFD,0xE3,0xDF,0xB7,0xED, 0xFB,0x7E,0xDF,0x37,0xED,0xE3,0xFB,0xDF,
-0xFF,0x52,0x5C,0x15,0xFD,0xCF,0x7F,0xDF, 0xFE,0xEF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEC,
-0x7B,0xFE,0xFF,0xFE,0x3E,0x7F,0xDA,0xF7, 0xFD,0xFF,0x7F,0xFF,0xFF,0xFB,0xEF,0xBB,
-0x6F,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, 0xF7,0x7D,0xFF,0xD8,0xFF,0xFD,0xBF,0x7F,
-0xFB,0xFF,0xFF,0x9F,0xFB,0xFE,0x7F,0x9F, 0xE7,0xF9,0xFE,0x7F,0x9F,0xEA,0x7F,0xF6,
-0xBF,0xBD,0x6A,0x5A,0xF6,0xE5,0xBF,0x77, 0x5F,0x6D,0xDD,0x77,0x5D,0xD7,0x75,0xDD,
-0x77,0xFF,0xA5,0xBF,0xCF,0xFB,0xFF,0xFF, 0xBF,0xCF,0xFB,0xFD,0xFF,0xBF,0xF3,0xFE,
-0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD,0xAB, 0xFF,0xBF,0xBF,0xFF,0xFB,0xFF,0x7F,0xEF,
-0xFF,0xBE,0xFB,0xEE,0xFB,0xBE,0xEF,0xBB, 0xEE,0xFB,0xBF,0xFF,0xB5,0xFF,0xD0,0xBC,
-0xFD,0x2F,0x4B,0xF7,0xFF,0xFF,0x9F,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,
-0xFA,0x8F,0xFD,0xAB,0xFA,0xDA,0xBF,0xAF, 0xB3,0xFD,0xFF,0xBF,0xFB,0xFE,0xFF,0xBF,
-0xEF,0xFB,0xFE,0xF7,0xBF,0xFF,0x9F,0xFF, 0x77,0xF7,0xBD,0xFD,0x77,0xDF,0xFF,0x7E,
-0xDF,0xED,0xBB,0xFE,0xFF,0xBE,0xEF,0xFB, 0xFE,0xFF,0xFA,0x3F,0xFF,0xBE,0x6F,0x8F,
-0xE6,0xF9,0xFE,0x7F,0x9F,0xC7,0xFE,0x7F, 0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFB,
-0x7F,0xFF,0x7F,0xCF,0xFF,0xFD,0xFF,0xFF, 0xDF,0xFB,0xAF,0xBF,0xEF,0xFF,0xFE,0xFF,
-0x9F,0xEF,0xFB,0xFF,0xFC,0xFF,0xFB,0xFE, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF7,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF5,0xFF,0xFF,0xFF,0x3F,0xDF,0xF7,
-0xFF,0xFF,0x7F,0xEF,0xFE,0xFF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xEF,0xFF,0xB3,0x7F,
-0xFF,0x7B,0x5E,0xF7,0xFD,0xFF,0x7B,0x7F, 0xF7,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,
-0xDF,0xF7,0xFF,0x17,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xDD,0xF6,0xFC,0xBF,0xCB,0xF2,
-0xBC,0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xFE, 0x8F,0xFF,0xFA,0x7E,0xBF,0xA7,0xEB,0xDA,
-0xFC,0xBF,0xAF,0x7A,0xFE,0xBF,0xAF,0xEA, 0xFA,0xFE,0xBF,0xAF,0xF4,0xDF,0xFE,0xFF,
-0xF3,0x3C,0x7F,0x3E,0xFF,0xCF,0xF8,0xBF, 0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xE7,0xE8,
-0xFF,0xFC,0x9F,0xFF,0xFF,0xCF,0xEB,0xB3, 0xE7,0xFB,0x7B,0xF3,0xFE,0xFF,0xCF,0xDB,
-0xFB,0xFB,0xBF,0x6F,0x6F,0xDF,0xEC,0x7F, 0xFF,0xFF,0xF7,0xFD,0xFD,0xFF,0xFF,0xFF,
-0xFF,0xB2,0xBF,0xFF,0xDE,0xFD,0xBD,0xEF, 0xFB,0xF6,0xDF,0xEA,0xE7,0xDB,0xFE,0xBB,
-0xFF,0xEB,0xFB,0xBF,0x9F,0x8F,0xE8,0xFE, 0x3F,0x8F,0xA3,0xF8,0xFE,0x3F,0x8F,0xFF,
-0xF8,0x7E,0xFD,0xFD,0x7F,0xFF,0xFB,0xCD, 0xFF,0xFD,0xFF,0x5F,0xEF,0xFD,0xFF,0xFF,
-0xDF,0xF7,0xFD,0xFF,0xBE,0x90,0xFF,0xFF, 0xEE,0xFF,0x3F,0xBF,0xF3,0xBB,0xFE,0xB7,
-0xAB,0xFA,0xFE,0xAF,0xAD,0xEA,0xFA,0xDE, 0xAB,0xFF,0x63,0xFF,0xFE,0xF2,0xFF,0xB3,
-0xFF,0xDF,0xEE,0x7D,0xFF,0x03,0xF1,0xF4, 0x3F,0x1F,0xC3,0xF1,0xEC,0x7F,0xFE,0x6F,
-0xFF,0xFB,0xFB,0xFF,0x9F,0xFF,0xBF,0xFF, 0x7B,0x5F,0xFD,0xFF,0xDF,0xF7,0xFD,0xFD,
-0x7F,0x7F,0xDF,0xFE,0xCF,0xFB,0xFF,0xFF, 0xAF,0xFB,0xFF,0x1F,0xEF,0xA5,0xFD,0xBF,
-0xDF,0xFB,0x7D,0xFF,0xBF,0xDF,0xFB,0xFF, 0xFD,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,
-0xAF,0xF3,0xFF,0xFB,0x7F,0xBF,0xD7,0xFB, 0xBF,0x7F,0xBB,0xF7,0xFF,0xF8,0x7F,0xFF,
-0xFA,0x5F,0xD7,0xFF,0xDF,0x7F,0xEF,0xFF, 0xFF,0x7F,0xDB,0xF7,0xFD,0xFF,0x7F,0xDF,
-0xB7,0xFB,0xEC,0xFF,0xFF,0xF7,0xBF,0xEF, 0xFD,0xFC,0xFB,0xFF,0xEF,0xF0,0xFE,0x3F,
-0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xEF,0x8D, 0xFF,0xFF,0xEF,0x7F,0xBF,0xFF,0xFB,0xFF,
-0xDB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0xD8,0xFF,0x2E,0x7F,
-0xBE,0xEF,0xFE,0x6E,0xFF,0xBF,0xF9,0xFF, 0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFC,0x66,0xBE,0x47,0xF3,0x7F,0xDF,0xFE, 0x87,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x6F,0x7C, 0xFB,0x4F,0xD2,0xFF,0xFD,0x2B,0xFE,0xFF,
-0xFF,0xFD,0x5F,0xD7,0xD5,0xF5,0x7D,0xFF, 0xFF,0xFF,0xBF,0x9B,0xFF,0xFF,0xDF,0xB7,
-0xFF,0xFF,0xDF,0xFF,0x3F,0xCF,0xFE,0x7F, 0xBF,0xEF,0xFB,0xFC,0xFF,0x3F,0xFF,0xD9,
-0xBF,0xFE,0x97,0xEC,0x8F,0xB7,0xFE,0x9B, 0x7D,0xFD,0xB7,0xDD,0x77,0x1D,0xC7,0x71,
-0xDD,0x77,0x5D,0xD7,0xF3,0x6F,0xFD,0x3F, 0x73,0xDD,0xAF,0xFD,0x7A,0xFF,0xFF,0xAF,
-0xFE,0xFD,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0x66,0x7F,0xFF,0xFF,0xBF,0xBF,0xFF,
-0xFB,0xFF,0xF7,0xDF,0xFD,0xFB,0x7D,0xDF, 0xB7,0xCD,0xF3,0x7C,0x5F,0x3F,0x91,0x3F,
-0xFF,0x3D,0xEF,0x7B,0xFF,0xFC,0xFF,0xCA, 0xEF,0xFE,0xFF,0xBD,0xEF,0xFB,0x1E,0xE7,
-0xBB,0xEC,0x7F,0xB3,0xFF,0xFD,0x9F,0xFF, 0xFF,0xFE,0xFF,0xFF,0x7F,0xBF,0xFB,0xFE,
-0xFF,0xBF,0xEF,0xFB,0xEE,0xFB,0xBF,0xDF, 0x67,0xFF,0xFF,0xBF,0xEF,0xDB,0xFF,0xBC,
-0xFE,0x7F,0xFB,0xFF,0x9F,0xEF,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x87,0xFF,0xEE,
-0xFB,0xBE,0xE5,0xBF,0xEF,0xF9,0xD7,0x65, 0xF7,0xDD,0xE7,0x7D,0xDF,0x77,0x5D,0xD7,
-0x7F,0xF8,0x9B,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xBF,0xEF,0xFB,0xFF,0x7F,0xCF,
-0xF3,0xFC,0xFF,0xBF,0xEF,0xFF,0xDB,0x3F, 0xEF,0xFB,0xFE,0xFF,0xDF,0xFF,0xFE,0xFB,
-0xBB,0xEF,0xBF,0xEF,0xBB,0xEE,0xFB,0xBE, 0xEF,0xBB,0xFF,0xFC,0x7F,0xFD,0x3B,0x5B,
-0xD6,0xE5,0xFD,0x4F,0xC3,0xFB,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF,
-0xB4,0xFF,0xFA,0xBC,0x8F,0xB2,0xE9,0xD2, 0x2E,0xCF,0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,
-0xFF,0xBF,0xEF,0xFB,0xFF,0xEC,0xFF,0xFD, 0xFD,0x7F,0xDF,0xF7,0xE4,0xDF,0x5F,0xFF,
-0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xC3,0xFF,0xEF,0xE6,0xF8,0xFE,
-0x3F,0x8B,0x83,0xF9,0xFE,0x7F,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x17,
-0xFD,0xFF,0xFF,0xFF,0x7F,0x5F,0xF7,0x2C, 0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xE7,0xF9,
-0xFE,0x7F,0x9F,0xFE,0x2F,0xFF,0xFF,0xEF, 0xFF,0xFE,0xBF,0xEF,0xAD,0xFF,0xFF,0x7F,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFE,0xDF,0xFF,0xDF,0xFF,0xFD,0xFD,0x7F,
-0xDF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x3F,0xFE,
-0xF7,0xFD,0xEF,0x7A,0xFF,0xB1,0xBD,0xFF, 0x7F,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,
-0xFF,0x7F,0xF3,0x27,0xFF,0xDF,0xFF,0xDD, 0xFF,0xFC,0x9B,0xFF,0xCB,0xFC,0xBF,0x2F,
-0xCB,0xF2,0xFC,0xBF,0x2F,0xC9,0xFF,0xDE, 0xFF,0xDF,0xAF,0xEB,0xDA,0xFE,0xBB,0xAF,
-0xEB,0xF8,0xF7,0xAF,0xE8,0xFA,0xFE,0xBF, 0xAF,0xEB,0xF2,0xFF,0xFD,0xFF,0xFF,0xEF,
-0xBD,0xD7,0xBF,0xFF,0xFF,0xDE,0x8F,0xB8, 0xDE,0x37,0x8D,0xA3,0x78,0xDA,0x3F,0x8F,
-0xFF,0xA1,0xFF,0xFF,0xFB,0xFB,0xFF,0xFF, 0xFF,0xFF,0xA7,0xBD,0xFB,0x76,0xFD,0xBF,
-0xEF,0xDB,0xFE,0xBB,0xBF,0xFE,0x27,0x7F, 0xFF,0xFE,0xFE,0xFD,0xF5,0xFF,0xEF,0xF5,
-0xDF,0x1F,0xE7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xFF,0xCD,0xFD,0xAE,0xFF,0xFA,
-0x3E,0x3F,0xAB,0xFD,0xF8,0x7E,0x8F,0xE3, 0xF8,0xFE,0x3E,0x8F,0xE3,0xF8,0xFF,0xFE,
-0x1F,0xEF,0xDF,0xBF,0xFE,0xDE,0xDF,0xD9, 0xFF,0xDF,0xBC,0xFF,0xFF,0x7F,0xFF,0xEF,
-0xFD,0x7F,0xDF,0xF7,0xF9,0x3F,0xFE,0xFF, 0xFF,0x6F,0xFE,0xDE,0xBF,0xF7,0xED,0xEA,
-0xFD,0x8F,0x83,0xF8,0xEA,0x3F,0x8F,0xEF, 0xFF,0xF4,0x7F,0xFF,0xEF,0xEF,0x7B,0xF3,
-0xF1,0x5F,0xFF,0xFF,0xF1,0x3B,0x7F,0xDF, 0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,
-0xFF,0xFF,0xF7,0xFF,0x6F,0xFF,0x7F,0xFF, 0xFF,0xF7,0xDE,0xF7,0xBF,0xEF,0xFB,0xF7,
-0xFD,0xFF,0xFF,0xF5,0xFA,0xFF,0xFF,0xFB, 0xE7,0xFF,0xF3,0xF8,0x7F,0xF3,0xDF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0xEF, 0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,
-0xFF,0x7F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xCF,0xFF,0x37,0xFF,0xFF,
-0x7F,0xDF,0x77,0x5D,0xE7,0xFC,0xFF,0xBF, 0xF7,0xF5,0xFB,0xFF,0xFF,0xD7,0xF5,0xFB,
-0xFF,0xFF,0x45,0xFD,0x7F,0xEA,0xFD,0xBE, 0xBF,0xDF,0xF7,0xFF,0xFF,0xDB,0xFB,0xFE,
-0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFB,0x5F, 0x7F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFE,0xFF,0xEF,0xFD,0xFF,0x7F,0xDF, 0xFF,0xEF,0xFB,0xF8,0x0F,0xF3,0xFF,0xF9,
-0x2E,0xFB,0xFE,0xFC,0xF3,0xEF,0xFF,0xFF, 0xBF,0xFF,0xFB,0xE7,0xFF,0xFE,0x7E,0xFF,
-0xC0,0x6B,0xCF,0xFF,0x34,0xDF,0xF1,0xFD, 0xFF,0xEF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFD,
-0xCF,0x7F,0x9C,0xFD,0xFD,0x6C,0xF7,0xFF, 0xF6,0xFD,0xEB,0x2B,0x9F,0xFF,0xFC,0xFE,
-0x7E,0xFF,0xFF,0xFF,0xFF,0xD7,0xF3,0xF7, 0xFF,0xFB,0xE1,0xBF,0xFF,0xEB,0x7A,0xDE,
-0xD7,0xFB,0xFF,0xF9,0xFE,0xFF,0xFF,0xF3, 0xDE,0x7F,0xFD,0xE7,0x7F,0xFF,0xFD,0xBB,
-0xFF,0xFF,0x7E,0xCC,0xF6,0xAF,0x5F,0x7F, 0xFE,0xF4,0x7D,0xF7,0xFD,0xBB,0x6E,0xDB,
-0xB7,0xFF,0xF7,0xDF,0x66,0xFF,0xFF,0xF7, 0x3D,0xCF,0xDE,0xBD,0xFF,0xFF,0xDE,0xDB,
-0x8D,0xF7,0x7E,0xDF,0xB7,0xEF,0x7F,0xFF, 0xF6,0x87,0xFF,0xFF,0xEF,0xFE,0xDE,0xBF,
-0xFF,0xFF,0xFF,0xBB,0xEF,0xFD,0xFF,0x7B, 0xDE,0xF7,0x3F,0xFF,0xBF,0xFB,0xDB,0xFF,
-0xF2,0xB6,0xFD,0xBD,0x7F,0xE7,0xFF,0xFF, 0xFF,0x6F,0xF7,0xFF,0xFF,0xFF,0xFE,0x77,
-0xFF,0xBF,0xF8,0xAF,0xFF,0xDF,0xBF,0xFF, 0xBF,0x7F,0xFB,0xFF,0xFF,0xFF,0xDB,0xFE,
-0xFF,0xBF,0xFF,0xFA,0xFF,0xFD,0xFF,0xF6, 0x7F,0xFF,0x9F,0xFF,0xFF,0x3F,0xEF,0xF8,
-0xEE,0x7E,0x9F,0xBA,0xFE,0xBF,0x8F,0xEF, 0xFE,0xFE,0xF9,0xFF,0xFA,0x7F,0xFE,0x7E,
-0xBF,0xAF,0xFB,0x96,0xFD,0x9F,0xEF,0x5E, 0x65,0xBE,0xEF,0x5B,0xB6,0xFF,0xBE,0xE3,
-0xFF,0xB5,0xBF,0xFF,0xFD,0xFF,0x7F,0xFF, 0xEF,0xDF,0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,
-0xBF,0xCF,0xFF,0xFF,0xFF,0xFD,0x9B,0xFF, 0xFE,0xFB,0xFE,0xDF,0xFF,0x7F,0xFF,0xF7,
-0xFE,0xFF,0xDF,0xFB,0xFB,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xB7,0xFE,0xFA,0xFF,0xAB,
-0xEF,0xFF,0xFD,0xB5,0x7B,0x7F,0xFB,0xF7, 0xFD,0xFF,0xFF,0xDD,0xFF,0xEF,0x8F,0xFF,
-0x2F,0xFF,0xFB,0x7C,0xFF,0x3F,0xDF,0x73, 0xEB,0xFE,0x3F,0xFF,0xEF,0xFB,0xFE,0xFF,
-0xEF,0xFD,0xFF,0xBF,0xFD,0x0F,0xFF,0xFF, 0xFF,0xF5,0xF9,0xFF,0x7F,0xD7,0xFD,0xFF,
-0xDF,0xFF,0xF7,0xFB,0xFF,0x7F,0xBF,0xFF, 0xFF,0xF0,0x9F,0xFF,0xFE,0x7F,0x8B,0xE3,
-0xF9,0xDE,0x27,0x9B,0xE6,0xBE,0x7F,0x9B, 0xC3,0xF8,0xDE,0x7F,0x9D,0xE7,0xFE,0x7F,
-0xFF,0xFF,0x5F,0xD7,0xFF,0xFF,0xFF,0x4F, 0xFB,0xFF,0xFF,0x7F,0xFF,0xAF,0xFF,0x9F,
-0x7F,0xFB,0xFF,0xE8,0xFF,0xFF,0xFE,0xBF, 0xAF,0xFF,0xFF,0xFE,0xBF,0xEF,0xF7,0xFF,
-0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFC,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,
-0xFD,0x3F,0xCF,0xFF,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFD,0x7F,0xFF,0xFF,0x93,0xFF,0xFF,
-0x7A,0xDF,0xF7,0xFF,0xFF,0x7B,0x7F,0xB7, 0xEF,0xFF,0xFF,0xFD,0xBF,0xFD,0xFB,0xFF,
-0xF7,0xFF,0xD7,0xFF,0xFF,0xFF,0xFC,0x9F, 0x6F,0xCB,0xFF,0xF4,0xBB,0xDF,0xD6,0xFD,
-0xBF,0x2F,0xD3,0xF7,0xFF,0xDF,0xFF,0xCF, 0xFF,0xFA,0xBE,0xBD,0xAF,0x6A,0xDA,0xBE,
-0xBB,0xAB,0x3A,0xBE,0x2D,0xAE,0xEB,0xDA, 0xF6,0x3F,0xAD,0xF5,0xDD,0xFF,0xCF,0xF1,
-0xFF,0xF9,0x7F,0xFF,0x73,0xFE,0xFF,0xCF, 0xC3,0xF4,0xF7,0x2F,0xF3,0xFF,0xFC,0xFF,
-0x7C,0x1F,0xFF,0x3F,0x4F,0xFF,0x7E,0xFF, 0xEF,0xBD,0xF6,0xFE,0xFF,0x2B,0xEF,0xDC,
-0xFB,0xFD,0xFF,0xFB,0xFF,0xEA,0x7B,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xF7,0xDF,0xFF,
-0xE3,0x7D,0xFF,0xB7,0xFF,0xBF,0xFF,0xFF, 0xDF,0xFF,0xF8,0xFF,0xBF,0xFF,0xBF,0xEB,
-0xE7,0xFA,0xFE,0x3D,0xBF,0xE9,0xFC,0xBF, 0xFF,0xFA,0xFB,0xFE,0xFF,0xFF,0xFF,0xD9,
-0xFF,0xFF,0xFF,0xF6,0x7F,0xFF,0xF6,0x7D, 0xFF,0xDF,0xCF,0xFD,0xBF,0xFB,0xEF,0x7E,
-0xFF,0x7F,0xFF,0xFF,0xD3,0xFF,0xFD,0xFB, 0xFF,0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xBF,
-0xFE,0xFF,0xF7,0xEF,0xFF,0xFF,0xFF,0xFB, 0xFF,0x87,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,
-0x7B,0xFE,0xFF,0xFE,0x3B,0xF7,0xF7,0xFF, 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,
-0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFF,0xAD,0xFF,0xFE,0xF7,0xFF,0xFF,
-0x5F,0xFF,0xFF,0xDF,0xFF,0xFD,0xFF,0xF5, 0xFF,0xDF,0xFF,0xBD,0xFF,0xE9,0xFF,0xC7,
-0xF3,0xFF,0xFF,0xF7,0xFF,0xF3,0xFF,0xF8, 0x3B,0xFF,0xFF,0x7B,0xDF,0xBF,0xFB,0xEF,
-0xFB,0xFF,0xFB,0xF7,0xF7,0xBB,0xFF,0xFF, 0xFF,0xFF,0xFB,0xFF,0xFE,0x7F,0xF3,0x7F,
-0x5E,0xB7,0xBF,0xFD,0x7F,0xFF,0xF9,0x7F, 0xFB,0xFF,0xEB,0xFD,0x7F,0x7F,0xFF,0xEF,
-0xFB,0xE0,0x3F,0xFE,0xBF,0xBF,0xDF,0xFF, 0x7E,0xFF,0xF7,0xFF,0xFF,0xFE,0xBF,0xFF,
-0xDB,0x78,0xFF,0xFF,0xFF,0xEE,0xA1,0xBF, 0xF5,0xDE,0xFB,0xF7,0xFF,0xFB,0xFF,0xFF,
-0xFF,0xFF,0xFB,0xFF,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xEF,0xF0,0xFF,0xFF,0xFF,0xF3,
-0xF7,0xFF,0xEF,0xFF,0xE7,0xCF,0xFF,0xFB, 0xFF,0xEF,0xFF,0xFF,0x9F,0x9F,0xEF,0xFC,
-0x16,0xBF,0xFE,0xF3,0xE4,0xFF,0xFF,0xC6, 0xFF,0xE7,0xFF,0xFF,0xFD,0xFF,0xBF,0xFF,
-0xFF,0x3F,0xFF,0xBF,0xD6,0xAF,0x7F,0xFE, 0x6B,0x7E,0x7F,0xFF,0xAF,0xFF,0xFF,0xBF,
-0xFF,0x5F,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF, 0xFF,0xBD,0xDB,0xFF,0xFE,0x5F,0xF2,0xFF,
-0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xEF,0x7F,0xFF,0xFF,0xFF,0xFF,0xDE,0xBF,
-0xFF,0xFF,0xEF,0xFB,0x77,0xFE,0xBD,0x7F, 0x5F,0xFF,0xFF,0xFF,0xDF,0x6F,0xED,0xFF,
-0xFD,0xFF,0x7F,0xFD,0x6F,0xFF,0xFF,0x77, 0xDA,0xCF,0xFD,0x5F,0xFF,0xBF,0xFF,0xFF,
-0xDF,0x7F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, 0x66,0x7F,0xFF,0xFE,0xBF,0xE7,0xBF,0xFA,
-0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0x59, 0xEF,0xFF,0xEF,0xFB,0x7F,0x89,0xFF,0xFF,
-0xE9,0xFF,0x6F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xFF,0xFF,0x7F,0xF2,0xF7,0xFF,0xFF,0xEF,
-0xF8,0x7F,0xFB,0xFF,0xFD,0xFF,0xFF,0xD9, 0xFF,0xEF,0xBB,0xFF,0xFF,0xFF,0xBF,0xEF,
-0xDE,0xFF,0xFF,0x9F,0x7F,0xDF,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xAF,
-0xFF,0xFF,0xF7,0x3F,0xEB,0x9F,0xFE,0x7F, 0x9E,0x7F,0x9F,0xFE,0x87,0xFF,0xED,0xDB,
-0x56,0xFF,0xBF,0xAF,0x0B,0xD2,0xFF,0xEF, 0xDB,0x6E,0x7D,0xBD,0x6F,0xF8,0xFE,0x3F,
-0xFA,0x5B,0xFF,0xFD,0xBF,0xEF,0xFF,0xBF, 0x6F,0xDB,0xE6,0xFF,0xFF,0x3F,0xFF,0xDF,
-0xFE,0xFF,0xFF,0xFF,0xFF,0xDA,0x3F,0xFF, 0xFB,0xFE,0xFE,0xFF,0xFF,0xDF,0xF7,0xBD,
-0xFF,0xFD,0xFF,0xFE,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xF1,0x5F,0xFD,0x9F,0xDF,0xFD,
-0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,0xFF,0x76, 0xFA,0xFF,0xFF,0x7F,0xE3,0xF8,0xFF,0xAE,
-0xFF,0xFB,0x7E,0x9D,0x73,0xFF,0xFA,0x7F, 0xDF,0xFF,0xFF,0x7F,0xFF,0xFB,0xCD,0xFF,
-0x7F,0xEF,0xFB,0xFF,0xFD,0xFF,0xF7,0x7F, 0x7F,0xEF,0xFF,0xED,0xFF,0xFF,0xFF,0xB5,
-0xFF,0xBF,0xFF,0xBF,0xFD,0xEF,0xDB,0xF7, 0xFF,0x93,0xFF,0xEF,0xE2,0xF9,0xBE,0x7F,
-0x8B,0xE7,0xF9,0xFE,0x6B,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x47,0xFF,
-0xFF,0xFD,0xFF,0x9F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xF5,0xFF,0x9F,0xFF,0xF7,0xFE,
-0xFF,0xBF,0xFE,0x6F,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xAF,0xFF,0xFF,0xFF,0x7F,0xFB,
-0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xDF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xDF,
-0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,0xFF,0xFF, 0x5F,0xFB,0xFE,0xFF,0xF8,0x37,0xFF,0xFF,
-0xEF,0xFF,0x7F,0xFE,0xBF,0xFF,0xFF,0xFE, 0xBF,0xFF,0xFF,0x7F,0xFF,0xBF,0xFD,0xFF,
-0x7F,0xFA,0x7F,0xFF,0xFF,0x6F,0xFF,0xFF, 0x7D,0xFF,0xCF,0xFF,0xFF,0xFF,0x4F,0xFF,
-0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xBF, 0xFF,0xAE,0xEB,0xFA,0xFE,0xBB,0xAD,0xEB,
-0xFA,0xF7,0xAF,0x6B,0xFA,0xF6,0xBF,0x25, 0xE9,0xF2,0x7F,0x45,0xFF,0xFF,0xFD,0xF7,
-0xF7,0xBF,0xFF,0xDF,0xFF,0xFF,0xBF,0xFB, 0xFF,0xDF,0xF3,0xFF,0xF7,0x3F,0xCF,0xFF,
-0xA1,0xFF,0xFF,0xBF,0xE7,0xFF,0xFF,0x7F, 0xFF,0x3D,0xFF,0xFF,0xFF,0xF7,0xFF,0x2F,
-0xFF,0xFB,0xF5,0x7F,0xFE,0x57,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,
-0x3F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,0xFE, 0xF7,0xEE,0xAF,0xFE,0xEE,0xE7,0xFA,0xFF,
-0xFE,0x9D,0xF9,0x5E,0xFE,0xFF,0xEB,0xFF, 0xFF,0xDF,0xA7,0xFF,0xFF,0xFF,0xFC,0xDB,
-0xFF,0xFF,0xFF,0x7E,0xFB,0xFF,0xFF,0xEF, 0xFB,0xFD,0xFF,0xDB,0xFF,0xFF,0xFF,0xEF,
-0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,0xBF,0xFF, 0x6F,0x7F,0xFF,0xF7,0xFF,0xFF,0xF9,0xFF,
-0xF7,0xFF,0xBF,0xDE,0xF7,0xFF,0xFF,0xFF, 0xFA,0x7F,0xFD,0xBF,0x5F,0xFF,0xFF,0xBF,
-0xFF,0xED,0xFF,0xF7,0xBF,0xFF,0xFF,0xEF, 0xFF,0xDF,0xFF,0xFF,0xFF,0xE6,0xFF,0xFB,
-0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,
-0xFD,0xFF,0xF5,0xFF,0xF6,0x7F,0xDF,0xBD, 0xCF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,
-0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3, 0xFF,0xEE,0xBF,0xFF,0x7D,0xEF,0xFE,0xFF,
-0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xB5,0xAE,
-0xFF,0xFF,0xB6,0xFE,0xBF,0xFF,0xFF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0x27,0xFF,0xEF,0xFE,0x7F,0xDF,0xFF, 0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFD,0xFF,0xF7,0xF9,0x9F,0xFF, 0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
-0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x0F,0xFF,0xE7,0xBF,0xFE,
-0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBF, 0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xC4,
-0x6B,0xFF,0x29,0x1F,0xFB,0xAF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0x1B,0xFE,0xFF,0xFC,
-0x6F,0xFF,0xFF,0xFD,0x6A,0xF7,0xD7,0xF5, 0xBF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFE,0xBF,0xFF,0xFF,0xFA,0xFF,0xFF,0xF7, 0xFB,0xDD,0xBF,0xFF,0xE7,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7F,0xFF, 0xFF,0xF5,0xFF,0xFF,0xF7,0xFD,0xB3,0xEF,
-0xFD,0x7E,0x5D,0xFF,0xFD,0xFF,0xFF,0xFF, 0xFD,0x7F,0xD2,0xF5,0xFB,0x7E,0xCB,0xB7,
-0xFF,0xFF,0xFF,0xC6,0xFF,0xFD,0xEE,0x63, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFD,0x65,
-0x5B,0xDF,0xFF,0xD5,0xFF,0xFF,0xFF,0xF6, 0xE7,0xBF,0xF7,0xA9,0xFF,0xFF,0xED,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFF,0xFF, 0xAF,0xFF,0xFF,0xFF,0xF8,0x1B,0xFF,0xE3,
-0xD0,0xBF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF, 0xFF,0xD7,0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,
-0xFF,0xFF,0xAF,0xFF,0xDB,0x76,0xBF,0xFF, 0x7F,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,
-0xFB,0xFE,0xFF,0xFF,0xFF,0xBF,0xF2,0x7F, 0xFF,0x9F,0xFE,0xBD,0xFE,0x7F,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF7,0x3F,0xEC,0x7F,0xF6,0x95,0xBB,
-0xEF,0xF8,0xFE,0xFC,0xBF,0x2F,0xDA,0xFC, 0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xEF,0xFF,
-0xA9,0xBF,0xCF,0xFB,0xFF,0xFF,0xFF,0xFE, 0xDD,0xB7,0x6D,0xF6,0xD9,0xB6,0x6D,0x9B,
-0x76,0xD9,0xBF,0xFB,0xFD,0xA3,0xFF,0xBF, 0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0x7F,0xDF,
-0xFD,0xEF,0x7B,0xDE,0xF7,0xFD,0xEF,0x7F, 0xFF,0xFF,0x05,0xFF,0xFA,0xFE,0x7F,0xEF,
-0xE3,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, 0xFF,0x5F,0xFF,0xFF,0xFD,0x7F,0xFB,0xAF,
-0xFF,0x63,0xC8,0xFF,0xBF,0xEF,0xFF,0xFF, 0xFA,0x7F,0xFF,0xFF,0xFF,0xFE,0x9F,0xF7,
-0xFF,0xFA,0xBF,0xFE,0x9F,0xFB,0x7F,0xFF, 0xFF,0xEF,0xD7,0xFF,0xFF,0xF5,0xFF,0xFF,
-0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xBF,0xFF, 0xF9,0xBF,0xFF,0xBE,0x27,0x9F,0xE7,0xF9,
-0xFE,0x7F,0x8B,0xE7,0xFE,0x7F,0x9F,0xE2, 0xF9,0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,
-0xFF,0xFF,0xFB,0xFE,0xFF,0xFF,0xFF,0xD7, 0xFF,0xFF,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF,
-0xD7,0xFF,0xFA,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF,0xAF,0xF7,0xFF,0xFF,
-0xFF,0xEB,0xFF,0xFF,0xFF,0xAF,0xFF,0xC4, 0xFF,0xF7,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,
-0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xD7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFB,0x7A,
-0xDF,0xF7,0xFD,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0x7F,0xFF,0xAF,0xFF,0xFF,0xFF,0xF7,
-0xEF,0xE3,0xFF,0xDD,0xD2,0xFF,0xDF,0xFF, 0xFF,0xF2,0xFC,0xBF,0xCB,0xF6,0xFD,0xBF,
-0x2F,0xCB,0xFF,0x7F,0xDF,0xDE,0xAF,0xFF, 0xDA,0xEE,0xBF,0xAF,0xE9,0xFA,0xF4,0xBD,
-0xAF,0x5A,0xAE,0xBB,0xAB,0x6B,0xDA,0xDE, 0xBF,0xAD,0xD7,0x5E,0xFF,0xFF,0xBF,0xFC,
-0xFF,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xDF, 0xF7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFA,
-0x1F,0xFF,0xFE,0xFB,0xEF,0xBF,0xFD,0xFF, 0xFD,0xBD,0x77,0xFF,0xFF,0xFF,0xFF,0x9D,
-0xEF,0xFF,0xFF,0xFF,0xEF,0x7D,0xFF,0xFB, 0xFE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE, 0xBF,0xE4,0xFB,0xFF,0xFE,0x3F,0xFE,0xFF,
-0xFF,0xFF,0xFF,0xAF,0xEA,0xFE,0xBF,0xAF, 0xEB,0xFA,0xFE,0xFF,0xFF,0xFF,0x55,0xF6,
-0xFF,0xFE,0xF7,0xFF,0x7F,0xFF,0xEB,0xF7, 0x5F,0xC5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF,
-0x6F,0xFB,0xFF,0x8A,0xFF,0xFF,0xFF,0xFF, 0xEB,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xBF,
-0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0x77,0xDF,0xFB,0xFF,0xFD,0x7F,0xEF,0xFF,
-0xFF,0xFF,0xBF,0x7F,0xFF,0xDF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xFF,0xFE,0xEF,0xDF,0xFF,
-0xFE,0xFF,0x9F,0xEF,0x7D,0xFF,0xF7,0xFF, 0x7F,0xFF,0xFF,0xDF,0xF7,0xFD,0xFF,0xEF,
-0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB,
-0xFD,0xFF,0xBF,0xDF,0xD1,0xFF,0xF8,0x3B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0x7E,0xDB,0xFD,0xFF,0x77,0xDB,0xB7,0x7D, 0xBF,0xFB,0xFF,0xF8,0x7F,0xED,0x7B,0x5E,
-0xFF,0xFE,0xFF,0xFF,0x4F,0xD7,0xFD,0x7F, 0xDF,0xD7,0xF5,0xFF,0x7F,0xFF,0xFF,0xFF,
-0xF2,0x3F,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFF,0xBF,0xEF,0xFE,0xFF,0x3B,0xEE,0xFF,
-0xFC,0xEF,0xFF,0xFF,0xFF,0x85,0xFF,0xFD, 0xFE,0xFF,0xF5,0xFF,0xFF,0xFE,0xFF,0xDF,
-0xFB,0xFF,0x5F,0xBF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xA8,0xFF,0xFF,0x9F,0x9E,0xFF,
-0xFF,0xFF,0x7F,0xF3,0xFF,0xFF,0xCF,0xFF, 0xF7,0xFD,0xFF,0x7F,0xFF,0xFF,0xFC,0x16,
-0xBF,0xCF,0xA3,0xE5,0xEF,0x7F,0xFF,0xF3, 0xE4,0xFF,0xCF,0x93,0xFC,0xFF,0x3F,0xCF,
-0xFF,0xFF,0xFF,0xD6,0x0F,0x7D,0xBF,0x6E, 0xFB,0xF4,0xFC,0xAF,0x6D,0xDB,0x77,0xB7,
-0x6D,0xDB,0xF6,0xFD,0xBF,0xFF,0xFF,0xFF, 0xBF,0x9B,0xFA,0xDE,0xB7,0xB7,0xED,0xF9,
-0x7E,0xB7,0xAC,0xEB,0xD6,0xB3,0xAD,0xEB, 0x7A,0xDF,0xFF,0xFF,0xFF,0xD8,0xBF,0xFF,
-0xB7,0xED,0x9F,0x6F,0xDD,0xF7,0x68,0xDB, 0x37,0xB3,0x6C,0xDB,0x36,0xCD,0xB3,0x7F,
-0xFF,0x7F,0xF5,0x6F,0xFD,0xEF,0x79,0x3D, 0xF7,0x93,0xE4,0x7A,0x9E,0xAD,0xEA,0x7A,
-0x9E,0xF7,0xBD,0xEF,0xFF,0xFF,0xFF,0x76, 0x7F,0xFB,0xC6,0xFF,0xBB,0xEF,0xDA,0xFE,
-0xFD,0xBF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xFB,0xFF,0xA5,0xFF,0xFD,0xAB,
-0x6F,0x78,0xDE,0x17,0x8F,0x79,0xDF,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xFF,0xFB,
-0xFF,0xFB,0xFF,0xEF,0xFB,0xEF,0xFB,0xFE, 0xFF,0xBB,0xDA,0xF3,0xEF,0x3B,0xCE,0xF3,
-0xBC,0xEF,0x3F,0xCF,0xDF,0xFF,0xB7,0xFF, 0xFF,0xFF,0xCF,0x73,0xFF,0xBF,0xEF,0xFF,
-0xF3,0xFF,0x3F,0xCF,0xF3,0xFC,0xFF,0x3D, 0xCF,0x9F,0xFE,0x07,0xFF,0xAF,0xEB,0xFE,
-0xFD,0xBF,0xEF,0xEB,0xFA,0xFF,0xAF,0xEB, 0xFA,0xFE,0xBF,0xAF,0xFB,0xFE,0x3F,0xFB,
-0x9B,0xFF,0x7F,0xDF,0xFF,0xF3,0xFE,0xFF, 0xDE,0xF7,0xBF,0x7B,0xDE,0xF7,0xBD,0xEF,
-0x7B,0xFE,0xFF,0xFF,0xDF,0x3F,0xFE,0xFF, 0xB7,0xFF,0xEF,0xF7,0xFF,0xBF,0xED,0xFE,
-0xDF,0xB7,0xED,0xFB,0x7E,0xDF,0xFF,0xFF, 0xFF,0xFD,0x5F,0xEF,0xEB,0xFA,0xFE,0xF5,
-0xBF,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xF8,0xFF,0xA8,0xFF,
-0xFF,0xBF,0xEF,0xFB,0x6A,0xFB,0xB7,0xEF, 0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,
-0xEF,0xFB,0xFF,0xE0,0xFF,0xFF,0xFD,0x7F, 0x5C,0xD7,0x7D,0xDF,0xF3,0x5C,0xF5,0xCD,
-0x73,0x5E,0xD7,0xB5,0xFD,0x7F,0xEF,0xFF, 0xDB,0xFF,0xFF,0xE2,0xF8,0xBE,0x2F,0x8F,
-0xE7,0xF8,0xBE,0x6B,0xE2,0xF8,0xBE,0x2F, 0x8B,0xE2,0xF9,0xFE,0x7F,0xE7,0xFF,0xD7,
-0xF5,0xFD,0x7F,0xFF,0xF7,0xF5,0xFD,0x7F, 0xD7,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF,
-0xFF,0xFF,0x8F,0xFF,0xAF,0xEB,0xFA,0xFF, 0xFF,0xBF,0xEB,0xFA,0xFF,0x2F,0xEB,0xFA,
-0xFE,0xBF,0xAF,0xEB,0xFF,0xFF,0xFE,0x5F, 0xFF,0x5F,0xFF,0xFF,0xFD,0xFF,0xFF,0xD7,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFE,0xB7,0xFD,
-0xFF,0x7E,0xDF,0xF7,0xAD,0xFF,0x7F,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,
-0xF6,0x7F,0xFF,0xFF,0xFF,0xDB,0xF6,0xFC, 0xAF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xBF,0xFF, 0xAF,0xEB,0xFA,0xF6,0xAB,0x8F,0xEB,0xFA,
-0xF7,0xA5,0xEB,0xFA,0xBE,0xBF,0xAF,0xEB, 0xFA,0xFF,0x6D,0xFF,0xFF,0x7F,0xDF,0x33,
-0xDD,0xFF,0x7F,0xFE,0xF7,0xFC,0x7F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,
-0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xDF, 0xFF,0xFF,0xEF,0xEF,0xFD,0xFF,0x7F,0xFF,
-0xFF,0xFF,0xFF,0xFE,0xA7,0xFF,0xFF,0xFF, 0x77,0xDF,0xF7,0xFD,0x9F,0x7F,0xFE,0x77,
-0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xAF,0xBF,0xAF,0xFF,0xF9,0xBE,0xBF,
-0x8F,0xFB,0xFE,0xFE,0xEF,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFF,0xFF,0xFD,0xDF,0x6F,
-0xEF,0xFF,0x7F,0xFF,0xBF,0xBF,0xDF,0xFF, 0xFC,0xFF,0xDF,0xF7,0xFD,0xEF,0x7F,0xDF,
-0xFF,0xFF,0xFF,0x3F,0xF6,0xFF,0xCF,0xFF, 0xDB,0xFB,0xF7,0xFF,0xEB,0x7A,0xFF,0xFF,
-0xFF,0xBF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFE, 0x6D,0xFD,0xFF,0x5F,0xFB,0xFF,0xFF,0xF7,
-0xFF,0x5F,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFB,0xFF,
-0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xE7,0xF6, 0xBF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,
-0xFF,0xC9,0xFF,0xFF,0xFF,0xBD,0xFF,0xBF, 0xAF,0xEF,0xEF,0x3F,0xD1,0xFC,0x7F,0xFB,
-0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF, 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x77,0xFF,
-0xDF,0xB7,0xFD,0xF7,0xFD,0xF7,0xFF,0xFF, 0xFF,0xFF,0xFF,0x57,0xFF,0xF7,0xA5,0xFD,
-0x3F,0xDF,0xBF,0xBF,0xFE,0x7F,0xFF,0xFF, 0xFF,0xDF,0xFA,0xFD,0xFF,0xFF,0xFF,0xFE,
-0x87,0xFF,0xE9,0xFF,0xFE,0xEF,0xBF,0xEF, 0xFE,0xFE,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFA,0x9F,0xFF,0x3F, 0xFF,0xFD,0xFD,0x57,0xDF,0xFD,0xF3,0xFF,
-0xDF,0xFD,0xFF,0x5F,0xDF,0xF5,0xFD,0xFF, 0xFF,0xF9,0x8F,0xFF,0xFF,0xFF,0xEE,0x7F,
-0xFF,0xFF,0xBF,0x5E,0xFE,0xEC,0xFB,0x3F, 0x7F,0x9F,0xEF,0xF9,0xFF,0xFF,0xCD,0x6B,
-0xFF,0xFF,0xFF,0xC5,0xF3,0xFC,0xFA,0x38, 0xFF,0xAF,0x3F,0xEE,0x7F,0x9F,0xFF,0xD9,
-0xFF,0xFF,0xFD,0x7A,0xF7,0xFF,0xF3,0xFF, 0xAF,0x6F,0xDB,0xF2,0xB9,0xE9,0xFB,0xFF,
-0xFF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFB, 0xC5,0xBF,0xFF,0xEF,0xFF,0x5E,0xB7,0xAD,
-0xCD,0x79,0x7C,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0x93,0xFF,0xEF,
-0xEA,0xFE,0xBF,0xEF,0x5B,0xD2,0xCD,0xF5, 0x6D,0x77,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,
-0xFF,0xFF,0x66,0xFF,0xD5,0x65,0x7D,0x5F, 0x75,0x9D,0x65,0x7F,0xD6,0xFB,0x4F,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xC7, 0xFF,0xBF,0xEF,0xFA,0xFE,0xFF,0xBF,0xEB,
-0xFF,0xDF,0xFF,0x7E,0xFF,0xFF,0xEF,0xFD, 0x7E,0xD7,0xFF,0x78,0xDF,0xFF,0x5F,0xDF,
-0xF5,0xBF,0x7F,0xDF,0xC5,0xFF,0x3F,0xF6, 0x7E,0xFF,0x0F,0xEF,0xF2,0x3E,0xBF,0xFF,
-0xFB,0x3F,0xFF,0xFB,0x7F,0xFF,0xB3,0xFE, 0xFB,0xF6,0xFD,0xFF,0xDA,0xF7,0xFD,0xFF,
-0x7F,0xDF,0xF7,0xBF,0xFF,0xFA,0x7F,0xFF, 0xFF,0xFF,0xFF,0x9F,0xFF,0xF3,0xDC,0xF9,
-0xBF,0xCE,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7, 0xFF,0xFF,0xE2,0x7F,0xFE,0xFF,0xBF,0xEF,
-0xEB,0xFA,0xFF,0x9F,0x67,0x1E,0xFF,0x8F, 0xE7,0xF8,0xFE,0x7F,0x8F,0xEF,0xFF,0xBD,
-0xBF,0xFF,0xFB,0xFF,0xFF,0xDF,0xF7,0xFF, 0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xEF, 0xFF,0xFF,0xBF,0xED,0xFF,0xFB,0xEE,0xFE,
-0xFF,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFF,0xB5,0xFF,0xB7,0xFD,0xFD,0x6E,0xFF,
-0xFF,0xFE,0xFD,0x2F,0xD8,0xFE,0xBF,0x8F, 0xEB,0xF9,0xFE,0x3F,0xFF,0xFA,0xCF,0xFF,
-0xE7,0xD9,0xFA,0xBF,0xDF,0x77,0xFC,0xFB, 0x3F,0xAB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,
-0xFF,0xFF,0xEE,0x1F,0xFF,0xDF,0xF7,0xFF, 0xFF,0xFF,0x5F,0x97,0x35,0xBF,0x5E,0xFE,
-0xBF,0xEF,0xFF,0xF7,0xFD,0xFF,0xFF,0xFA, 0xBF,0xFF,0xBE,0x6F,0x9F,0xE7,0xF8,0xBE,
-0x2F,0x8B,0x66,0x94,0x7D,0x9D,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,0xFF,
-0xFF,0xF7,0xF5,0xFD,0x7F,0x5F,0xFB,0xFD, 0x9E,0xFF,0xFB,0xFE,0xFF,0xFF,0xEF,0xFF,
-0xFF,0xA0,0xFF,0xFF,0xFF,0xBF,0xEF,0xEB, 0xFA,0xFE,0xBF,0xB7,0xF7,0xF7,0xFF,0xFF,
-0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xFD,0xFF,0xFF,0xFF,0xD7,0xFF,0xFF,0xFF,
-0x7F,0xF5,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xFF,0xAB,0xFE,0xFB,0xFE,0xFF,
-0xF7,0xAF,0xFF,0xFF,0xDE,0xF7,0xEB,0x5F, 0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,0xFF,
-0xB3,0xFF,0xC9,0xFE,0xFF,0xFF,0xFF,0xFF, 0xD6,0xFF,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFC,0x8F,0xFF,0xBA, 0xBE,0xBF,0xAF,0xEB,0x78,0xFE,0xB7,0xAD,
-0x3A,0xFE,0xB7,0xAF,0xEB,0x7A,0xFE,0xBF, 0xAF,0xFF,0x9F,0xFF,0xFF,0xDF,0xFC,0xFF,
-0xFF,0xFE,0xC3,0xFE,0xFF,0xFF,0x33,0xFC, 0xFF,0xBF,0xDF,0xF3,0xFF,0xFF,0xBB,0x9F,
-0xFF,0xFF,0xFF,0xEB,0xDF,0xFF,0xFF,0xAF, 0xF7,0x6F,0xF9,0xBF,0xEF,0xFD,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xFD,0xFB,0xF7,0xFF,
-0xDF,0xF7,0xFF,0xFE,0xEF,0x5F,0xBD,0xFF, 0xFA,0xFF,0xF8,0xFF,0xBF,0xAF,0xFB,0xFE,
-0xFE,0x3F,0xEF,0xE8,0xFF,0xDF,0xF3,0xFD, 0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xFB,
-0xFD,0xFF,0xAF,0xFF,0xFF,0xFE,0xFE,0xBF, 0xDB,0xFF,0xFF,0xFF,0xBF,0xFF,0xDF,0xFF,
-0xFD,0xFF,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF, 0xBF,0x6F,0xFF,0x7F,0xB7,0xB3,0xFF,0xFF,
-0xDF,0xFF,0xFB,0xEF,0xFF,0xFF,0xFF,0x07, 0xFF,0xFB,0xFF,0xFF,0xFF,0xED,0xFF,0xF5,
-0x7C,0xFF,0x7F,0xFE,0xFF,0xFF,0xEF,0xCF, 0xFF,0xFB,0xFF,0xFF,0x2F,0xFF,0xFF,0xFF,
-0xFF,0xF3,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,
-0xFD,0x1B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFE,0x7C,0xFF,0xFF,0xFF,0xFF,
-0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0x7F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,
-0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xEF,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xEF,0xFA,0xB5,0xFF,0xFF,0xFF, 0xF7,0xF7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFB,
-0xFC,0xFF,0xFF,0xFE,0xFF,0x7F,0xDF,0xBF, 0xFF,0xCB,0xBF,0xF9,0xFE,0x7F,0x9F,0xE7,
-0xF9,0xFE,0x7F,0x97,0xE1,0xFE,0x79,0x9F, 0xE7,0xFD,0xFE,0x7F,0xDF,0xFE,0x37,0xFF,
-0xFB,0xDE,0xDE,0xBD,0xEF,0xF3,0xFE,0xFB, 0xAF,0xEB,0xFE,0xFF,0xFF,0xCF,0xFF,0xFE,
-0xFF,0xBF,0xFF,0x8F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xE7,0xF9,0x5E,0x7F,0xEF,0xFB,
-0xDA,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD, 0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,
-0xFF,0xFF,0x7F,0xFF,0xFF,0xF7,0xFB,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xBF,
-0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0x7B,0x7F, 0xBF,0xEF,0xFB,0xFE,0xFF,0xB5,0xEF,0xFB,
-0xBF,0xFA,0x7F,0xFC,0xFF,0x3F,0xCF,0xF3, 0xFC,0xFF,0x3F,0xCF,0xBC,0xFF,0x3F,0xEF,
-0xF3,0xFC,0xFE,0x3F,0xCF,0xFF,0xEE,0xEF, 0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0x6A,0xD7,
-0xB7,0xFB,0xF8,0xFF,0xB7,0xEF,0xBA,0xFE, 0xFF,0xBF,0x7F,0xE9,0xFF,0xF9,0x7E,0x5F,
-0x97,0xE5,0xF9,0xFE,0x7F,0xBF,0xF9,0x7E, 0x5F,0x9F,0xE5,0xFB,0xFE,0x5F,0xB7,0xFF,
-0xA3,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0x5E,0xF7,0x7D,0xFF,0x77,0xDF,
-0xF7,0xFD,0xFF,0x7F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xDF,0xFB,0x7F,
-0xFF,0xFF,0xEF,0xFF,0xFE,0xFB,0xFF,0xFF, 0xBF,0xFE,0x8F,0xFF,0xDF,0xF7,0xFD,0xFD,
-0x7F,0xDF,0xF7,0xFD,0x3E,0xDF,0xF5,0xBD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xF7,0xFF,0x9F,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xBE,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFD,0x3F,0xFF,0xDF,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xCF,
-0x77,0xFC,0xFF,0x5F,0xDF,0xF7,0xFD,0xFF, 0xF4,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xED,0xFB,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFB,0xFF,0xFF,0xFF,0xD3,0xFF,0xFF,
-0xBF,0x3F,0xFB,0xFF,0xFF,0xFF,0xFB,0xF3, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xFF,
-0xDF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xDF,0xFF,0xFD,0xFF,0xFF,0xDF,0xF7,
-0xFF,0x4F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,
-0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x9F,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFF,0xFF,0x7A,0x3F,0xFF,0xFF,0xFF,0xFF,
-0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,
-0x7F,0xFF,0xFB,0xFE,0xFF,0xBF,0xEF,0xF8, 0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,0x8F,0xEC,
-0xFB,0xFE,0xFF,0xBF,0xF8,0xF7,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFD,0xBF,0xCF,0xEC,
-0xFF,0x3F,0xEF,0xDB,0xF8,0xFF,0xBF,0xCF, 0xFF,0xF9,0xFF,0xFF,0xBF,0xFF,0xFB,0xFF,
-0xFF,0xFF,0xEF,0xFB,0xDF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xBB,0xFF,
-0xEF,0xFB,0xFE,0xEF,0xBF,0xEE,0xEB,0xFB, 0xFE,0xFF,0xEF,0xFE,0xEE,0xBF,0xFE,0xEB,
-0xFF,0xEF,0xFF,0x17,0xFF,0x7E,0xEB,0xBB, 0xFE,0xBF,0xBE,0xFB,0xEF,0x5B,0xF7,0xBD,
-0xFB,0xCF,0xBF,0xBF,0xBB,0xFB,0x7E,0xCC, 0xEF,0xFF
-
-};
diff -Nru a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c
--- a/drivers/usb/dabusb.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,857 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      dabusb.c  --  dab usb driver.
- *
- *      Copyright (C) 1999  Deti Fliegl (deti@fliegl.de)
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *
- *  $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/miscdevice.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/delay.h>
-#include <linux/usb.h>
-#include <linux/smp_lock.h>
-
-#include "dabusb.h"
-#include "dabfirmware.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.54"
-#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
-#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999"
-
-/* --------------------------------------------------------------------- */
-
-#define NRDABUSB 4
-
-/*-------------------------------------------------------------------*/
-
-static dabusb_t dabusb[NRDABUSB];
-static int buffers = 256;
-
-/*-------------------------------------------------------------------*/
-
-static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
-{
-	unsigned long flags;
-	struct list_head *tmp;
-	int ret = 0;
-
-	spin_lock_irqsave (&s->lock, flags);
-
-	if (list_empty (src)) {
-		// no elements in source buffer
-		ret = -1;
-		goto err;
-	}
-	tmp = src->next;
-	list_del (tmp);
-	list_add_tail (tmp, dst);
-
-  err:	spin_unlock_irqrestore (&s->lock, flags);
-	return ret;
-}
-/*-------------------------------------------------------------------*/
-#ifdef DEBUG 
-static void dump_urb (struct urb *urb)
-{
-	dbg("urb                   :%p", urb);
-	dbg("next                  :%p", urb->next);
-	dbg("dev                   :%p", urb->dev);
-	dbg("pipe                  :%08X", urb->pipe);
-	dbg("status                :%d", urb->status);
-	dbg("transfer_flags        :%08X", urb->transfer_flags);
-	dbg("transfer_buffer       :%p", urb->transfer_buffer);
-	dbg("transfer_buffer_length:%d", urb->transfer_buffer_length);
-	dbg("actual_length         :%d", urb->actual_length);
-	dbg("setup_packet          :%p", urb->setup_packet);
-	dbg("start_frame           :%d", urb->start_frame);
-	dbg("number_of_packets     :%d", urb->number_of_packets);
-	dbg("interval              :%d", urb->interval);
-	dbg("error_count           :%d", urb->error_count);
-	dbg("context               :%p", urb->context);
-	dbg("complete              :%p", urb->complete);
-}
-#endif
-/*-------------------------------------------------------------------*/
-static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
-{
-	unsigned long flags;
-	struct list_head *p;
-	pbuff_t b;
-
-	dbg("dabusb_cancel_queue");
-
-	spin_lock_irqsave (&s->lock, flags);
-
-	for (p = q->next; p != q; p = p->next) {
-		b = list_entry (p, buff_t, buff_list);
-
-#ifdef DEBUG
-		dump_urb(b->purb);
-#endif
-		usb_unlink_urb (b->purb);
-	}
-	spin_unlock_irqrestore (&s->lock, flags);
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_free_queue (struct list_head *q)
-{
-	struct list_head *tmp;
-	struct list_head *p;
-	pbuff_t b;
-
-	dbg("dabusb_free_queue");
-	for (p = q->next; p != q;) {
-		b = list_entry (p, buff_t, buff_list);
-
-#ifdef DEBUG 
-		dump_urb(b->purb);
-#endif
-		if (b->purb->transfer_buffer)
-			kfree (b->purb->transfer_buffer);
-		usb_free_urb(b->purb);
-		tmp = p->next;
-		list_del (p);
-		kfree (b);
-		p = tmp;
-	}
-
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_free_buffers (pdabusb_t s)
-{
-	unsigned long flags;
-	dbg("dabusb_free_buffers");
-
-	spin_lock_irqsave(&s->lock, flags);
-
-	dabusb_free_queue (&s->free_buff_list);
-	dabusb_free_queue (&s->rec_buff_list);
-
-	spin_unlock_irqrestore(&s->lock, flags);
-
-	s->got_mem = 0;
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-static void dabusb_iso_complete (struct urb *purb)
-{
-	pbuff_t b = purb->context;
-	pdabusb_t s = b->s;
-	int i;
-	int len;
-	int dst = 0;
-	void *buf = purb->transfer_buffer;
-
-	dbg("dabusb_iso_complete");
-
-	// process if URB was not killed
-	if (purb->status != -ENOENT) {
-		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
-		int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
-		for (i = 0; i < purb->number_of_packets; i++)
-			if (!purb->iso_frame_desc[i].status) {
-				len = purb->iso_frame_desc[i].actual_length;
-				if (len <= pipesize) {
-					memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
-					dst += len;
-				}
-				else
-					err("dabusb_iso_complete: invalid len %d", len);
-			}
-			else
-				warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
-		if (dst != purb->actual_length)
-			err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
-	}
-
-	if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
-		s->overruns++;
-		err("overrun (%d)", s->overruns);
-	}
-	wake_up (&s->wait);
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_alloc_buffers (pdabusb_t s)
-{
-	int buffers = 0;
-	pbuff_t b;
-	unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
-	int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
-	int packets = _ISOPIPESIZE / pipesize;
-	int transfer_buffer_length = packets * pipesize;
-	int i;
-
-	dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
-		 pipesize, packets, transfer_buffer_length);
-
-	while (buffers < (s->total_buffer_size << 10)) {
-		b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
-		if (!b) {
-			err("kmalloc(sizeof(buff_t))==NULL");
-			goto err;
-		}
-		memset (b, 0, sizeof (buff_t));
-		b->s = s;
-		b->purb = usb_alloc_urb(packets, GFP_KERNEL);
-		if (!b->purb) {
-			err("usb_alloc_urb == NULL");
-			kfree (b);
-			goto err;
-		}
-
-		b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
-		if (!b->purb->transfer_buffer) {
-			kfree (b->purb);
-			kfree (b);
-			err("kmalloc(%d)==NULL", transfer_buffer_length);
-			goto err;
-		}
-
-		b->purb->transfer_buffer_length = transfer_buffer_length;
-		b->purb->number_of_packets = packets;
-		b->purb->complete = dabusb_iso_complete;
-		b->purb->context = b;
-		b->purb->dev = s->usbdev;
-		b->purb->pipe = pipe;
-		b->purb->transfer_flags = USB_ISO_ASAP;
-
-		for (i = 0; i < packets; i++) {
-			b->purb->iso_frame_desc[i].offset = i * pipesize;
-			b->purb->iso_frame_desc[i].length = pipesize;
-		}
-
-		buffers += transfer_buffer_length;
-		list_add_tail (&b->buff_list, &s->free_buff_list);
-	}
-	s->got_mem = buffers;
-
-	return 0;
-
-	err:
-	dabusb_free_buffers (s);
-	return -ENOMEM;
-}
-/*-------------------------------------------------------------------*/
-static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
-{
-	int ret;
-	unsigned int pipe;
-	int actual_length;
-
-	dbg("dabusb_bulk");
-
-	if (!pb->pipe)
-		pipe = usb_rcvbulkpipe (s->usbdev, 2);
-	else
-		pipe = usb_sndbulkpipe (s->usbdev, 2);
-
-	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
-	if(ret<0) {
-		err("dabusb: usb_bulk_msg failed(%d)",ret);
-
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-			err("set_interface failed");
-			return -EINVAL;
-		}
-
-	}
-	
-	if( ret == -EPIPE ) {
-		warn("CLEAR_FEATURE request to remove STALL condition.");
-		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
-			err("request failed");
-	}
-
-	pb->size = actual_length;
-	return ret;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len)
-{
-	int ret;
-	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
-
-	if (!transfer_buffer) {
-		err("dabusb_writemem: kmalloc(%d) failed.", len);
-		return -ENOMEM;
-	}
-
-	memcpy (transfer_buffer, data, len);
-
-	ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
-
-	kfree (transfer_buffer);
-	return ret;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
-{
-	dbg("dabusb_8051_reset: %d",reset_bit);
-	return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_loadmem (pdabusb_t s, const char *fname)
-{
-	int ret;
-	PINTEL_HEX_RECORD ptr = firmware;
-
-	dbg("Enter dabusb_loadmem (internal)");
-	
-	ret = dabusb_8051_reset (s, 1);
-	while (ptr->Type == 0) {
-
-		dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
-
-		ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
-		if (ret < 0) {
-			err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length);
-			break;
-		}
-		ptr++;
-	}
-	ret = dabusb_8051_reset (s, 0);
-
-	dbg("dabusb_loadmem: exit");
-
-	return ret;
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b)
-{
-	b->size = 4;
-	b->data[0] = 0x2a;
-	b->data[1] = 0;
-	b->data[2] = 0;
-	b->data[3] = 0;
-
-	dbg("dabusb_fpga_clear");
-
-	return dabusb_bulk (s, b);
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
-{
-	b->size = 4;
-	b->data[0] = 0x2c;
-	b->data[1] = 0;
-	b->data[2] = 0;
-	b->data[3] = 0;
-
-	dbg("dabusb_fpga_init");
-
-	return dabusb_bulk (s, b);
-}
-/* --------------------------------------------------------------------- */
-static int dabusb_fpga_download (pdabusb_t s, const char *fname)
-{
-	pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
-	unsigned int blen, n;
-	int ret;
-	unsigned char *buf = bitstream;
-
-	dbg("Enter dabusb_fpga_download (internal)");
-
-	if (!b) {
-		err("kmalloc(sizeof(bulk_transfer_t))==NULL");
-		return -ENOMEM;
-	}
-
-	b->pipe = 1;
-	ret = dabusb_fpga_clear (s, b);
-	mdelay (10);
-	blen = buf[73] + (buf[72] << 8);
-
-	dbg("Bitstream len: %i", blen);
-
-	b->data[0] = 0x2b;
-	b->data[1] = 0;
-	b->data[2] = 0;
-	b->data[3] = 60;
-
-	for (n = 0; n <= blen + 60; n += 60) {
-		// some cclks for startup
-		b->size = 64;
-		memcpy (b->data + 4, buf + 74 + n, 60);
-		ret = dabusb_bulk (s, b);
-		if (ret < 0) {
-			err("dabusb_bulk failed.");
-			break;
-		}
-		mdelay (1);
-	}
-
-	ret = dabusb_fpga_init (s, b);
-	kfree (b);
-
-	dbg("exit dabusb_fpga_download");
-
-	return ret;
-}
-
-static int dabusb_stop (pdabusb_t s)
-{
-	dbg("dabusb_stop");
-
-	s->state = _stopped;
-	dabusb_cancel_queue (s, &s->rec_buff_list);
-
-	dbg("pending_io: %d", s->pending_io.counter);
-
-	s->pending_io.counter = 0;
-	return 0;
-}
-
-static int dabusb_startrek (pdabusb_t s)
-{
-	if (!s->got_mem && s->state != _started) {
-
-		dbg("dabusb_startrek");
-
-		if (dabusb_alloc_buffers (s) < 0)
-			return -ENOMEM;
-		dabusb_stop (s);
-		s->state = _started;
-		s->readptr = 0;
-	}
-
-	if (!list_empty (&s->free_buff_list)) {
-		pbuff_t end;
-		int ret;
-		
-	while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
-
-			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
-
-			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
-
-			ret = usb_submit_urb (end->purb, GFP_KERNEL);
-			if (ret) {
-				err("usb_submit_urb returned:%d", ret);
-				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-					err("startrek: dabusb_add_buf_tail failed");
-				break;
-			}
-			else
-				atomic_inc (&s->pending_io);
-		}
-		dbg("pending_io: %d",s->pending_io.counter);
-	}
-
-	return 0;
-}
-
-static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
-{
-	pdabusb_t s = (pdabusb_t) file->private_data;
-	unsigned long flags;
-	unsigned ret = 0;
-	int rem;
-	int cnt;
-	pbuff_t b;
-	struct urb *purb = NULL;
-
-	dbg("dabusb_read");
-
-	if (*ppos)
-		return -ESPIPE;
-
-	if (s->remove_pending)
-		return -EIO;
-
-
-	if (!s->usbdev)
-		return -EIO;
-
-	while (count > 0) {
-		dabusb_startrek (s);
-
-		spin_lock_irqsave (&s->lock, flags);
-
-		if (list_empty (&s->rec_buff_list)) {
-
-			spin_unlock_irqrestore(&s->lock, flags);
-
-			err("error: rec_buf_list is empty");
-			goto err;
-		}
-		
-		b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
-		purb = b->purb;
-
-		spin_unlock_irqrestore(&s->lock, flags);
-
-		if (purb->status == -EINPROGRESS) {
-			if (file->f_flags & O_NONBLOCK)		// return nonblocking
-			 {
-				if (!ret)
-					ret = -EAGAIN;
-				goto err;
-			}
-
-			interruptible_sleep_on (&s->wait);
-
-			if (signal_pending (current)) {
-				if (!ret)
-					ret = -ERESTARTSYS;
-				goto err;
-			}
-
-			spin_lock_irqsave (&s->lock, flags);
-
-			if (list_empty (&s->rec_buff_list)) {
-				spin_unlock_irqrestore(&s->lock, flags);
-				err("error: still no buffer available.");
-				goto err;
-			}
-			spin_unlock_irqrestore(&s->lock, flags);
-			s->readptr = 0;
-		}
-		if (s->remove_pending) {
-			ret = -EIO;
-			goto err;
-		}
-
-		rem = purb->actual_length - s->readptr;		// set remaining bytes to copy
-
-		if (count >= rem)
-			cnt = rem;
-		else
-			cnt = count;
-
-		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
-
-		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
-			err("read: copy_to_user failed");
-			if (!ret)
-				ret = -EFAULT;
-			goto err;
-		}
-
-		s->readptr += cnt;
-		count -= cnt;
-		buf += cnt;
-		ret += cnt;
-
-		if (s->readptr == purb->actual_length) {
-			// finished, take next buffer
-			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
-				err("read: dabusb_add_buf_tail failed");
-			s->readptr = 0;
-		}
-	}
-      err:			//up(&s->mutex);
-	return ret;
-}
-
-static int dabusb_open (struct inode *inode, struct file *file)
-{
-	int devnum = minor (inode->i_rdev);
-	pdabusb_t s;
-
-	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
-		return -EIO;
-
-	s = &dabusb[devnum - DABUSB_MINOR];
-
-	dbg("dabusb_open");
-	down (&s->mutex);
-
-	while (!s->usbdev || s->opened) {
-		up (&s->mutex);
-
-		if (file->f_flags & O_NONBLOCK) {
-			return -EBUSY;
-		}
-		schedule_timeout (HZ / 2);
-
-		if (signal_pending (current)) {
-			return -EAGAIN;
-		}
-		down (&s->mutex);
-	}
-	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
-		err("set_interface failed");
-		return -EINVAL;
-	}
-	s->opened = 1;
-	up (&s->mutex);
-
-	file->f_pos = 0;
-	file->private_data = s;
-
-	return 0;
-}
-
-static int dabusb_release (struct inode *inode, struct file *file)
-{
-	pdabusb_t s = (pdabusb_t) file->private_data;
-
-	dbg("dabusb_release");
-
-	down (&s->mutex);
-	dabusb_stop (s);
-	dabusb_free_buffers (s);
-	up (&s->mutex);
-
-	if (!s->remove_pending) {
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
-			err("set_interface failed");
-	}
-	else
-		wake_up (&s->remove_ok);
-
-	s->opened = 0;
-	return 0;
-}
-
-static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	pdabusb_t s = (pdabusb_t) file->private_data;
-	pbulk_transfer_t pbulk;
-	int ret = 0;
-	int version = DABUSB_VERSION;
-
-	dbg("dabusb_ioctl");
-
-	if (s->remove_pending)
-		return -EIO;
-
-	down (&s->mutex);
-
-	if (!s->usbdev) {
-		up (&s->mutex);
-		return -EIO;
-	}
-
-	switch (cmd) {
-
-	case IOCTL_DAB_BULK:
-		pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
-
-		if (!pbulk) {
-			ret = -ENOMEM;
-			break;
-		}
-
-		if (copy_from_user (pbulk, (void *) arg, sizeof (bulk_transfer_t))) {
-			ret = -EFAULT;
-			kfree (pbulk);
-			break;
-		}
-
-		ret=dabusb_bulk (s, pbulk);
-		if(ret==0)
-			ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t));
-		kfree (pbulk);
-		break;
-
-	case IOCTL_DAB_OVERRUNS:
-		ret = put_user (s->overruns, (unsigned int *) arg);
-		break;
-
-	case IOCTL_DAB_VERSION:
-		ret = put_user (version, (unsigned int *) arg);
-		break;
-
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-	up (&s->mutex);
-	return ret;
-}
-
-static struct file_operations dabusb_fops =
-{
-	owner:		THIS_MODULE,
-	llseek:		no_llseek,
-	read:		dabusb_read,
-	ioctl:		dabusb_ioctl,
-	open:		dabusb_open,
-	release:	dabusb_release,
-};
-
-static int dabusb_find_struct (void)
-{
-	int u;
-
-	for (u = 0; u < NRDABUSB; u++) {
-		pdabusb_t s = &dabusb[u];
-		if (!s->usbdev)
-			return u;
-	}
-	return -1;
-}
-
-/* --------------------------------------------------------------------- */
-static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum,
-			   const struct usb_device_id *id)
-{
-	int devnum;
-	pdabusb_t s;
-
-	dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
-	  usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
-
-	/* We don't handle multiple configurations */
-	if (usbdev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-	if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
-		return NULL;
-
-	devnum = dabusb_find_struct ();
-	if (devnum == -1)
-		return NULL;
-
-	s = &dabusb[devnum];
-
-	down (&s->mutex);
-	s->remove_pending = 0;
-	s->usbdev = usbdev;
-
-	if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
-		err("set_configuration failed");
-		goto reject;
-	}
-	if (usbdev->descriptor.idProduct == 0x2131) {
-		dabusb_loadmem (s, NULL);
-		goto reject;
-	}
-	else {
-		dabusb_fpga_download (s, NULL);
-
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
-			err("set_interface failed");
-			goto reject;
-		}
-	}
-	dbg("bound to interface: %d", ifnum);
-	up (&s->mutex);
-	MOD_INC_USE_COUNT;
-	return s;
-
-      reject:
-	up (&s->mutex);
-	s->usbdev = NULL;
-	return NULL;
-}
-
-static void dabusb_disconnect (struct usb_device *usbdev, void *ptr)
-{
-	pdabusb_t s = (pdabusb_t) ptr;
-
-	dbg("dabusb_disconnect");
-
-	s->remove_pending = 1;
-	wake_up (&s->wait);
-	if (s->state == _started)
-		sleep_on (&s->remove_ok);
-	s->usbdev = NULL;
-	s->overruns = 0;
-	MOD_DEC_USE_COUNT;
-}
-
-static struct usb_device_id dabusb_ids [] = {
-	{ USB_DEVICE(0x0547, 0x2131) },
-	{ USB_DEVICE(0x0547, 0x9999) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dabusb_ids);
-
-static struct usb_driver dabusb_driver =
-{
-	name:		"dabusb",
-	probe:		dabusb_probe,
-	disconnect:	dabusb_disconnect,
-	fops:		&dabusb_fops,
-	minor:		DABUSB_MINOR,
-	id_table:	dabusb_ids,
-};
-
-/* --------------------------------------------------------------------- */
-
-static int __init dabusb_init (void)
-{
-	unsigned u;
-
-	/* initialize struct */
-	for (u = 0; u < NRDABUSB; u++) {
-		pdabusb_t s = &dabusb[u];
-		memset (s, 0, sizeof (dabusb_t));
-		init_MUTEX (&s->mutex);
-		s->usbdev = NULL;
-		s->total_buffer_size = buffers;
-		init_waitqueue_head (&s->wait);
-		init_waitqueue_head (&s->remove_ok);
-		spin_lock_init (&s->lock);
-		INIT_LIST_HEAD (&s->free_buff_list);
-		INIT_LIST_HEAD (&s->rec_buff_list);
-	}
-
-	/* register misc device */
-	if (usb_register(&dabusb_driver))
-		return -1;
-
-	dbg("dabusb_init: driver registered");
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-}
-
-static void __exit dabusb_cleanup (void)
-{
-	dbg("dabusb_cleanup");
-
-	usb_deregister (&dabusb_driver);
-}
-
-/* --------------------------------------------------------------------- */
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
-MODULE_PARM (buffers, "i");
-MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
-
-module_init (dabusb_init);
-module_exit (dabusb_cleanup);
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/dabusb.h b/drivers/usb/dabusb.h
--- a/drivers/usb/dabusb.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,84 +0,0 @@
-#define _BULK_DATA_LEN 64
-typedef struct
-{
-	unsigned char data[_BULK_DATA_LEN];
-	unsigned int size;
-	unsigned int pipe;
-}bulk_transfer_t,*pbulk_transfer_t;
-
-#define DABUSB_MINOR 240		/* some unassigned USB minor */
-#define DABUSB_VERSION 0x1000
-#define IOCTL_DAB_BULK              _IOWR('d', 0x30, bulk_transfer_t)
-#define IOCTL_DAB_OVERRUNS	    _IOR('d',  0x15, int)
-#define IOCTL_DAB_VERSION           _IOR('d', 0x3f, int) 
-
-#ifdef __KERNEL__
-
-typedef enum { _stopped=0, _started } driver_state_t;
-
-typedef struct
-{
-	struct semaphore mutex;
-	struct usb_device *usbdev;
-	wait_queue_head_t wait;
-	wait_queue_head_t remove_ok;
-	spinlock_t lock;
-	atomic_t pending_io;
-	driver_state_t state;
-	int remove_pending;
-	int got_mem;
-	int total_buffer_size;
-	unsigned int overruns;
-	int readptr;
-	int opened;
-	struct list_head free_buff_list;
-	struct list_head rec_buff_list;
-} dabusb_t,*pdabusb_t;
-
-typedef struct 
-{
-	pdabusb_t s;
-	struct urb *purb;
-	struct list_head buff_list;
-} buff_t,*pbuff_t;
-
-typedef struct
-{
-	wait_queue_head_t wait;
-} bulk_completion_context_t, *pbulk_completion_context_t;
-
-
-#define _DABUSB_IF 2
-#define _DABUSB_ISOPIPE 0x09
-#define _ISOPIPESIZE	16384
-
-#define _BULK_DATA_LEN 64
-// Vendor specific request code for Anchor Upload/Download
-// This one is implemented in the core
-#define ANCHOR_LOAD_INTERNAL  0xA0
-
-// EZ-USB Control and Status Register.  Bit 0 controls 8051 reset
-#define CPUCS_REG    0x7F92
-#define _TOTAL_BUFFERS 384
-
-#define MAX_INTEL_HEX_RECORD_LENGTH 16
-
-#ifndef _BYTE_DEFINED
-#define _BYTE_DEFINED
-typedef unsigned char BYTE;
-#endif // !_BYTE_DEFINED
-
-#ifndef _WORD_DEFINED
-#define _WORD_DEFINED
-typedef unsigned short WORD;
-#endif // !_WORD_DEFINED
-
-typedef struct _INTEL_HEX_RECORD
-{
-   BYTE  Length;
-   WORD  Address;
-   BYTE  Type;
-   BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
-} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
-
-#endif
diff -Nru a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c
--- a/drivers/usb/dc2xx.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,538 +0,0 @@
-/*
- * Copyright (C) 1999-2000 by David Brownell <dbrownell@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- 
- 
-/*
- * USB driver for Kodak DC-2XX series digital still cameras
- *
- * The protocol here is the same as the one going over a serial line, but
- * it uses USB for speed.  Set up /dev/kodak, get gphoto (www.gphoto.org),
- * and have fun!
- *
- * This should also work for a number of other digital (non-Kodak) cameras,
- * by adding the vendor and product IDs to the table below.  They'll need
- * to be the sort using USB just as a fast bulk data channel.
- */
-
-/*
- * HISTORY
- *
- * 26 August, 1999 -- first release (0.1), works with my DC-240.
- * 	The DC-280 (2Mpixel) should also work, but isn't tested.
- *	If you use gphoto, make sure you have the USB updates.
- *	Lives in a 2.3.14 or so Linux kernel, in drivers/usb.
- * 31 August, 1999 -- minor update to recognize DC-260 and handle
- *	its endpoints being in a different order.  Note that as
- *	of gPhoto 0.36pre, the USB updates are integrated.
- * 12 Oct, 1999 -- handle DC-280 interface class (0xff not 0x0);
- *	added timeouts to bulk_msg calls.  Minor updates, docs.
- * 03 Nov, 1999 -- update for 2.3.25 kernel API changes.
- * 08 Jan, 2000 .. multiple camera support
- * 12 Aug, 2000 .. add some real locking, remove an Oops
- * 10 Oct, 2000 .. usb_device_id table created. 
- * 01 Nov, 2000 .. usb_device_id support added by Adam J. Richter
- * 08 Apr, 2001 .. Identify version on module load. gb
- *
- * Thanks to:  the folk who've provided USB product IDs, sent in
- * patches, and shared their successes!
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-
-/* /dev/usb dir. */
-extern devfs_handle_t usb_devfs_handle;			
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.0.0"
-#define DRIVER_AUTHOR "David Brownell, <dbrownell@users.sourceforge.net>"
-#define DRIVER_DESC "USB Camera Driver for Kodak DC-2xx series cameras"
-
-
-/* current USB framework handles max of 16 USB devices per driver */
-#define	MAX_CAMERAS		16
-
-/* USB char devs use USB_MAJOR and from USB_CAMERA_MINOR_BASE up */
-#define	USB_CAMERA_MINOR_BASE	80
-
-
-// XXX remove packet size limit, now that bulk transfers seem fixed
-
-/* Application protocol limit is 0x8002; USB has disliked that limit! */
-#define	MAX_PACKET_SIZE		0x2000		/* e.g. image downloading */
-
-#define	MAX_READ_RETRY		5		/* times to retry reads */
-#define	MAX_WRITE_RETRY		5		/* times to retry writes */
-#define	RETRY_TIMEOUT		(HZ)		/* sleep between retries */
-
-
-/* table of cameras that work through this driver */
-static struct usb_device_id camera_table [] = {
-	/* These have the same application level protocol */  
-	{ USB_DEVICE(0x040a, 0x0120) },		// Kodak DC-240
-	{ USB_DEVICE(0x040a, 0x0130) },		// Kodak DC-280
-	{ USB_DEVICE(0x040a, 0x0131) },		// Kodak DC-5000
-	{ USB_DEVICE(0x040a, 0x0132) },		// Kodak DC-3400
-
-	/* These have a different application level protocol which
-	 * is part of the Flashpoint "DigitaOS".  That supports some
-	 * non-camera devices, and some non-Kodak cameras.
-	 * Use this driver to get USB and "OpenDis" to talk.
-	 */  
-	{ USB_DEVICE(0x040a, 0x0100) },		// Kodak DC-220
-	{ USB_DEVICE(0x040a, 0x0110) },		// Kodak DC-260
-	{ USB_DEVICE(0x040a, 0x0111) },		// Kodak DC-265
-	{ USB_DEVICE(0x040a, 0x0112) },		// Kodak DC-290
-	{ USB_DEVICE(0xf003, 0x6002) },		// HP PhotoSmart C500
-	{ USB_DEVICE(0x03f0, 0x4102) },		// HP PhotoSmart C618
-	{ USB_DEVICE(0x0a17, 0x1001) },		// Pentax EI-200
-
-	/* Other USB devices may well work here too, so long as they
-	 * just stick to half duplex bulk packet exchanges.  That
-	 * means, among other things, no iso or interrupt endpoints.
-	 */
-
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, camera_table);
-
-
-struct camera_state {
-	struct usb_device	*dev;		/* USB device handle */
-	int			inEP;		/* read endpoint */
-	int			outEP;		/* write endpoint */
-	const struct usb_device_id	*info;	/* DC-240, etc */
-	int			subminor;	/* which minor dev #? */
-	struct semaphore	sem;		/* locks this struct */
-
-	/* this is non-null iff the device is open */
-	char			*buf;		/* buffer for I/O */
-
-	devfs_handle_t		devfs;		/* devfs device */
-
-	/* always valid */
-	wait_queue_head_t	wait;		/* for timed waits */
-};
-
-/* Support multiple cameras, possibly of different types.  */
-static struct camera_state *minor_data [MAX_CAMERAS];
-
-/* make this an rwlock if contention becomes an issue */
-static DECLARE_MUTEX (state_table_mutex);
-
-static ssize_t camera_read (struct file *file,
-	char *buf, size_t len, loff_t *ppos)
-{
-	struct camera_state	*camera;
-	int			retries;
-	int			retval = 0;
-
-	if (len > MAX_PACKET_SIZE)
-		return -EINVAL;
-
-	camera = (struct camera_state *) file->private_data;
-	down (&camera->sem);
-	if (!camera->dev) {
-		up (&camera->sem);
-		return -ENODEV;
-	}
-
-	/* Big reads are common, for image downloading.  Smaller ones
-	 * are also common (even "directory listing" commands don't
-	 * send very much data).  We preserve packet boundaries here,
-	 * they matter in the application protocol.
-	 */
-	for (retries = 0; retries < MAX_READ_RETRY; retries++) {
-		int			count;
-
-		if (signal_pending (current)) {
-			retval = -EINTR;
-			break;
-		}
-
-		retval = usb_bulk_msg (camera->dev,
-			  usb_rcvbulkpipe (camera->dev, camera->inEP),
-			  camera->buf, len, &count, HZ*10);
-
-		dbg ("read (%Zd) - 0x%x %d", len, retval, count);
-
-		if (!retval) {
-			if (copy_to_user (buf, camera->buf, count))
-				retval = -EFAULT;
-			else
-				retval = count;
-			break;
-		}
-		if (retval != -ETIMEDOUT)
-			break;
-		interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
-
-		dbg ("read (%Zd) - retry", len);
-	}
-	up (&camera->sem);
-	return retval;
-}
-
-static ssize_t camera_write (struct file *file,
-	const char *buf, size_t len, loff_t *ppos)
-{
-	struct camera_state	*camera;
-	ssize_t			bytes_written = 0;
-
-	if (len > MAX_PACKET_SIZE)
-		return -EINVAL;
-
-	camera = (struct camera_state *) file->private_data;
-	down (&camera->sem);
-	if (!camera->dev) {
-		up (&camera->sem);
-		return -ENODEV;
-	}
-	
-	/* most writes will be small: simple commands, sometimes with
-	 * parameters.  putting images (like borders) into the camera
-	 * would be the main use of big writes.
-	 */
-	while (len > 0) {
-		char		*obuf = camera->buf;
-		int		maxretry = MAX_WRITE_RETRY;
-		unsigned long	copy_size, thistime;
-
-		/* it's not clear that retrying can do any good ... or that
-		 * fragmenting application packets into N writes is correct.
-		 */
-		thistime = copy_size = len;
-		if (copy_from_user (obuf, buf, copy_size)) {
-			bytes_written = -EFAULT;
-			break;
-		}
-		while (thistime) {
-			int		result;
-			int		count;
-
-			if (signal_pending (current)) {
-				if (!bytes_written)
-					bytes_written = -EINTR;
-				goto done;
-			}
-
-			result = usb_bulk_msg (camera->dev,
-				 usb_sndbulkpipe (camera->dev, camera->outEP),
-				 obuf, thistime, &count, HZ*10);
-
-			if (result)
-				dbg ("write USB err - %d", result);
-
-			if (count) {
-				obuf += count;
-				thistime -= count;
-				maxretry = MAX_WRITE_RETRY;
-				continue;
-			} else if (!result)
-				break;
-				
-			if (result == -ETIMEDOUT) {	/* NAK - delay a bit */
-				if (!maxretry--) {
-					if (!bytes_written)
-						bytes_written = -ETIME;
-					goto done;
-				}
-                                interruptible_sleep_on_timeout (&camera->wait,
-					RETRY_TIMEOUT);
-				continue;
-			} 
-			if (!bytes_written)
-				bytes_written = -EIO;
-			goto done;
-		}
-		bytes_written += copy_size;
-		len -= copy_size;
-		buf += copy_size;
-	}
-done:
-	up (&camera->sem);
-	dbg ("wrote %Zd", bytes_written); 
-	return bytes_written;
-}
-
-static int camera_open (struct inode *inode, struct file *file)
-{
-	struct camera_state	*camera = NULL;
-	int			subminor;
-	int			value = 0;
-
-	down (&state_table_mutex);
-	subminor = minor (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
-	if (subminor < 0 || subminor >= MAX_CAMERAS
-			|| !(camera = minor_data [subminor])) {
-		up (&state_table_mutex);
-		return -ENODEV;
-	}
-	down (&camera->sem);
-	up (&state_table_mutex);
-
-	if (camera->buf) {
-		value = -EBUSY;
-		goto done;
-	}
-
-	if (!(camera->buf = (char *) kmalloc (MAX_PACKET_SIZE, GFP_KERNEL))) {
-		value = -ENOMEM;
-		goto done;
-	}
-
-	dbg ("open #%d", subminor); 
-
-	file->private_data = camera;
-done:
-	up (&camera->sem);
-	return value;
-}
-
-static int camera_release (struct inode *inode, struct file *file)
-{
-	struct camera_state	*camera;
-	int			subminor;
-
-	camera = (struct camera_state *) file->private_data;
-	down (&state_table_mutex);
-	down (&camera->sem);
-
-	if (camera->buf) {
-		kfree (camera->buf);
-		camera->buf = 0;
-	}
-	subminor = camera->subminor;
-
-	/* If camera was unplugged with open file ... */
-	if (!camera->dev) {
-		minor_data [subminor] = NULL;
-		kfree (camera);
-	} else
-		up (&camera->sem);
-	
-	up (&state_table_mutex);
-
-	dbg ("close #%d", subminor); 
-
-	return 0;
-}
-
-	/* XXX should define some ioctls to expose camera type
-	 * to applications ... what USB exposes should suffice.
-	 * apps should be able to see the camera type.
-	 */
-static /* const */ struct file_operations usb_camera_fops = {
-	    /* Uses GCC initializer extension; simpler to maintain */
-	owner:		THIS_MODULE,
-	read:		camera_read,
-	write:		camera_write,
-	open:		camera_open,
-	release:	camera_release,
-};
-
-
-
-static void *
-camera_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *camera_info)
-{
-	int				i;
-	struct usb_interface_descriptor	*interface;
-	struct usb_endpoint_descriptor	*endpoint;
-	int				direction, ep;
-	char name[8];
-	struct camera_state		*camera = NULL;
-
-
-	/* these have one config, one interface */
-	if (dev->descriptor.bNumConfigurations != 1
-			|| dev->config[0].bNumInterfaces != 1) {
-		dbg ("Bogus camera config info");
-		return NULL;
-	}
-
-	/* models differ in how they report themselves */
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
-	if ((interface->bInterfaceClass != USB_CLASS_PER_INTERFACE
-		&& interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC)
-			|| interface->bInterfaceSubClass != 0
-			|| interface->bInterfaceProtocol != 0
-			|| interface->bNumEndpoints != 2
-			) {
-		dbg ("Bogus camera interface info");
-		return NULL;
-	}
-
-
-	/* select "subminor" number (part of a minor number) */
-	down (&state_table_mutex);
-	for (i = 0; i < MAX_CAMERAS; i++) {
-		if (!minor_data [i])
-			break;
-	}
-	if (i >= MAX_CAMERAS) {
-		info ("Ignoring additional USB Camera");
-		goto bye;
-	}
-
-	/* allocate & init camera state */
-	camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
-	if (!camera) {
-		err ("no memory!");
-		goto bye;
-	}
-
-	init_MUTEX (&camera->sem);
-	camera->info = camera_info;
-	camera->subminor = i;
-	camera->buf = NULL;
-	init_waitqueue_head (&camera->wait);
-
-
-	/* get input and output endpoints (either order) */
-	endpoint = interface->endpoint;
-	camera->outEP = camera->inEP =  -1;
-
-	ep = endpoint [0].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-	direction = endpoint [0].bEndpointAddress & USB_ENDPOINT_DIR_MASK;
-	if (direction == USB_DIR_IN)
-		camera->inEP = ep;
-	else
-		camera->outEP = ep;
-
-	ep = endpoint [1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-	direction = endpoint [1].bEndpointAddress & USB_ENDPOINT_DIR_MASK;
-	if (direction == USB_DIR_IN)
-		camera->inEP = ep;
-	else
-		camera->outEP = ep;
-
-	if (camera->outEP == -1 || camera->inEP == -1
-			|| endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
-			|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
-			) {
-		dbg ("Bogus endpoints");
-		goto error;
-	}
-
-	info ("USB Camera #%d connected, major/minor %d/%d", camera->subminor,
-		USB_MAJOR, USB_CAMERA_MINOR_BASE + camera->subminor);
-
-	camera->dev = dev;
-	usb_inc_dev_use (dev);
-
-	/* If we have devfs, register the device */
-	sprintf(name, "dc2xx%d", camera->subminor);
-	camera->devfs = devfs_register(usb_devfs_handle, name,
-				       DEVFS_FL_DEFAULT, USB_MAJOR,
-				       USB_CAMERA_MINOR_BASE + camera->subminor,
-				       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				       S_IWGRP, &usb_camera_fops, NULL);
-
-	goto bye;
-
-error:
-	minor_data [camera->subminor] = NULL;
-	kfree (camera);
-	camera = NULL;
-bye:
-	up (&state_table_mutex);
-	return camera;
-}
-
-static void camera_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct camera_state	*camera = (struct camera_state *) ptr;
-	int			subminor = camera->subminor;
-
-	down (&state_table_mutex);
-	down (&camera->sem);
-
-	devfs_unregister(camera->devfs); 
-
-	/* If camera's not opened, we can clean up right away.
-	 * Else apps see a disconnect on next I/O; the release cleans.
-	 */
-	if (!camera->buf) {
-		minor_data [subminor] = NULL;
-		kfree (camera);
-		camera = NULL;
-	} else
-		camera->dev = NULL;
-
-	info ("USB Camera #%d disconnected", subminor);
-	usb_dec_dev_use (dev);
-
-	if (camera != NULL)
-		up (&camera->sem);
-	up (&state_table_mutex);
-}
-
-static /* const */ struct usb_driver camera_driver = {
-	name:		"dc2xx",
-
-	id_table:	camera_table,
-	probe:		camera_probe,
-	disconnect:	camera_disconnect,
-
-	fops:		&usb_camera_fops,
-	minor:		USB_CAMERA_MINOR_BASE
-};
-
-
-int __init usb_dc2xx_init(void)
-{
- 	if (usb_register (&camera_driver) < 0)
- 		return -1;
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-void __exit usb_dc2xx_cleanup(void)
-{
-	usb_deregister (&camera_driver);
-}
-
-module_init (usb_dc2xx_init);
-module_exit (usb_dc2xx_cleanup);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/devices.c b/drivers/usb/devices.c
--- a/drivers/usb/devices.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,589 +0,0 @@
-/*
- * devices.c
- * (C) Copyright 1999 Randy Dunlap.
- * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
- * (C) Copyright 1999 Deti Fliegl (new USB architecture)
- *
- * This program is free software; you can redistribute it and/or 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
- *
- *************************************************************
- *
- * <mountpoint>/devices contains USB topology, device, config, class,
- * interface, & endpoint data.
- *
- * I considered using /proc/bus/usb/devices/device# for each device
- * as it is attached or detached, but I didn't like this for some
- * reason -- maybe it's just too deep of a directory structure.
- * I also don't like looking in multiple places to gather and view
- * the data.  Having only one file for ./devices also prevents race
- * conditions that could arise if a program was reading device info
- * for devices that are being removed (unplugged).  (That is, the
- * program may find a directory for devnum_12 then try to open it,
- * but it was just unplugged, so the directory is now deleted.
- * But programs would just have to be prepared for situations like
- * this in any plug-and-play environment.)
- *
- * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *   Converted the whole proc stuff to real
- *   read methods. Now not the whole device list needs to fit
- *   into one page, only the device list for one bus.
- *   Added a poll method to /proc/bus/usb/devices, to wake
- *   up an eventual usbd
- * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *   Turned into its own filesystem
- * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
- *   Converted file reading routine to dump to buffer once
- *   per device, not per bus
- *
- * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
- */
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/usb.h>
-#include <linux/smp_lock.h>
-#include <linux/usbdevice_fs.h>
-#include <asm/uaccess.h>
-
-#include "hcd.h"
-
-#define MAX_TOPO_LEVEL		6
-
-/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
-#define ALLOW_SERIAL_NUMBER
-
-static char *format_topo =
-/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
-  "T:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
-
-static char *format_string_manufacturer =
-/* S:  Manufacturer=xxxx */
-  "S:  Manufacturer=%.100s\n";
-
-static char *format_string_product =
-/* S:  Product=xxxx */
-  "S:  Product=%.100s\n";
-
-#ifdef ALLOW_SERIAL_NUMBER
-static char *format_string_serialnumber =
-/* S:  SerialNumber=xxxx */
-  "S:  SerialNumber=%.100s\n";
-#endif
-
-static char *format_bandwidth =
-/* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
-  "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-  
-static char *format_device1 =
-/* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
-  "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
-
-static char *format_device2 =
-/* P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx */
-  "P:  Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
-
-static char *format_config =
-/* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
-  "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-  
-static char *format_iface =
-/* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
-  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
-
-static char *format_endpt =
-/* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
-  "E:  Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
-
-
-/*
- * Need access to the driver and USB bus lists.
- * extern struct list_head usb_driver_list;
- * extern struct list_head usb_bus_list;
- * However, these will come from functions that return ptrs to each of them.
- */
-
-static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-static unsigned int conndiscevcnt = 0;
-
-/* this struct stores the poll state for <mountpoint>/devices pollers */
-struct usb_device_status {
-	unsigned int lastev;
-};
-
-struct class_info {
-	int class;
-	char *class_name;
-};
-
-static const struct class_info clas_info[] =
-{					/* max. 5 chars. per name string */
-	{USB_CLASS_PER_INTERFACE,	">ifc"},
-	{USB_CLASS_AUDIO,		"audio"},
-	{USB_CLASS_COMM,		"comm."},
-	{USB_CLASS_HID,			"HID"},
-	{USB_CLASS_HUB,			"hub"},
-	{USB_CLASS_PHYSICAL,		"PID"},
-	{USB_CLASS_PRINTER,		"print"},
-	{USB_CLASS_MASS_STORAGE,	"stor."},
-	{USB_CLASS_CDC_DATA,		"data"},
-	{USB_CLASS_APP_SPEC,		"app."},
-	{USB_CLASS_VENDOR_SPEC,		"vend."},
-	{USB_CLASS_STILL_IMAGE,		"still"},
-	{USB_CLASS_CSCID,		"scard"},
-	{USB_CLASS_CONTENT_SEC,		"c-sec"},
-	{-1,				"unk."}		/* leave as last */
-};
-
-/*****************************************************************/
-
-void usbdevfs_conn_disc_event(void)
-{
-	wake_up(&deviceconndiscwq);
-	conndiscevcnt++;
-}
-
-static const char *class_decode(const int class)
-{
-	int ix;
-
-	for (ix = 0; clas_info[ix].class != -1; ix++)
-		if (clas_info[ix].class == class)
-			break;
-	return (clas_info[ix].class_name);
-}
-
-static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct usb_endpoint_descriptor *desc)
-{
-	char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
-
-	if (start > end)
-		return start;
-	start += sprintf(start, format_endpt, desc->bEndpointAddress,
-			 (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL
-			 	? 'B' :			/* bidirectional */
-			 (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
-			 desc->bmAttributes, EndpointType[desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK],
-			 desc->wMaxPacketSize, desc->bInterval);
-	return start;
-}
-
-static char *usb_dump_endpoint(char *start, char *end, const struct usb_endpoint_descriptor *endpoint)
-{
-	return usb_dump_endpoint_descriptor(start, end, endpoint);
-}
-
-static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
-{
-	struct usb_interface_descriptor *desc = &iface->altsetting[setno];
-
-	if (start > end)
-		return start;
-	start += sprintf(start, format_iface,
-			 desc->bInterfaceNumber,
-			 desc->bAlternateSetting,
-			 desc->bNumEndpoints,
-			 desc->bInterfaceClass,
-			 class_decode(desc->bInterfaceClass),
-			 desc->bInterfaceSubClass,
-			 desc->bInterfaceProtocol,
-			 iface->driver ? iface->driver->name : "(none)");
-	return start;
-}
-
-static char *usb_dump_interface(char *start, char *end, const struct usb_interface *iface, int setno)
-{
-	struct usb_interface_descriptor *desc = &iface->altsetting[setno];
-	int i;
-
-	start = usb_dump_interface_descriptor(start, end, iface, setno);
-	for (i = 0; i < desc->bNumEndpoints; i++) {
-		if (start > end)
-			return start;
-		start = usb_dump_endpoint(start, end, desc->endpoint + i);
-	}
-	return start;
-}
-
-/* TBD:
- * 0. TBDs
- * 1. marking active config and ifaces (code lists all, but should mark
- *    which ones are active, if any)
- * 2. add <halted> status to each endpoint line
- */
-
-static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
-{
-	if (start > end)
-		return start;
-	start += sprintf(start, format_config,
-			 active ? '*' : ' ',	/* mark active/actual/current cfg. */
-			 desc->bNumInterfaces,
-			 desc->bConfigurationValue,
-			 desc->bmAttributes,
-			 desc->MaxPower * 2);
-	return start;
-}
-
-static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, int active)
-{
-	int i, j;
-	struct usb_interface *interface;
-
-	if (start > end)
-		return start;
-	if (!config)		/* getting these some in 2.3.7; none in 2.3.6 */
-		return start + sprintf(start, "(null Cfg. desc.)\n");
-	start = usb_dump_config_descriptor(start, end, config, active);
-	for (i = 0; i < config->bNumInterfaces; i++) {
-		interface = config->interface + i;
-		if (!interface)
-			break;
-		for (j = 0; j < interface->num_altsetting; j++) {
-			if (start > end)
-				return start;
-			start = usb_dump_interface(start, end, interface, j);
-		}
-	}
-	return start;
-}
-
-/*
- * Dump the different USB descriptors.
- */
-static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
-{
-	if (start > end)
-		return start;
-	start += sprintf (start, format_device1,
-			  desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
-			  desc->bDeviceClass,
-			  class_decode (desc->bDeviceClass),
-			  desc->bDeviceSubClass,
-			  desc->bDeviceProtocol,
-			  desc->bMaxPacketSize0,
-			  desc->bNumConfigurations);
-	if (start > end)
-		return start;
-	start += sprintf(start, format_device2,
-			 desc->idVendor, desc->idProduct,
-			 desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
-	return start;
-}
-
-/*
- * Dump the different strings that this device holds.
- */
-static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
-{
-	char *buf;
-
-	if (start > end)
-		return start;
-	buf = kmalloc(128, GFP_KERNEL);
-	if (!buf)
-		return start;
-	if (dev->descriptor.iManufacturer) {
-		if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0)
-			start += sprintf(start, format_string_manufacturer, buf);
-	}				
-	if (start > end)
-		goto out;
-	if (dev->descriptor.iProduct) {
-		if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0)
-			start += sprintf(start, format_string_product, buf);
-	}
-	if (start > end)
-		goto out;
-#ifdef ALLOW_SERIAL_NUMBER
-	if (dev->descriptor.iSerialNumber) {
-		if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0)
-			start += sprintf(start, format_string_serialnumber, buf);
-	}
-#endif
- out:
-	kfree(buf);
-	return start;
-}
-
-static char *usb_dump_desc(char *start, char *end, struct usb_device *dev)
-{
-	int i;
-
-	if (start > end)
-		return start;
-		
-	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
-
-	if (start > end)
-		return start;
-	
-	start = usb_dump_device_strings (start, end, dev);
-	
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-		if (start > end)
-			return start;
-		start = usb_dump_config(start, end, dev->config + i,
-					(dev->config + i) == dev->actconfig); /* active ? */
-	}
-	return start;
-}
-
-
-#ifdef PROC_EXTRA /* TBD: may want to add this code later */
-
-static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
-{
-	int leng = USB_DT_HUB_NONVAR_SIZE;
-	unsigned char *ptr = (unsigned char *)desc;
-
-	if (start > end)
-		return start;
-	start += sprintf(start, "Interface:");
-	while (leng && start <= end) {
-		start += sprintf(start, " %02x", *ptr);
-		ptr++; leng--;
-	}
-	*start++ = '\n';
-	return start;
-}
-
-static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
-{
-	if (start > end)
-		return start;
-	start += sprintf(start, "Interface:");
-	if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
-		start += sprintf(start, "%s: %.100s ", id, dev->stringindex[index]);
-	return start;
-}
-
-#endif /* PROC_EXTRA */
-
-/*****************************************************************/
-
-/* This is a recursive function. Parameters:
- * buffer - the user-space buffer to write data into
- * nbytes - the maximum number of bytes to write
- * skip_bytes - the number of bytes to skip before writing anything
- * file_offset - the offset into the devices file on completion
- */
-static ssize_t usb_device_dump(char **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset,
-				struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count)
-{
-	int chix;
-	int ret, cnt = 0;
-	int parent_devnum = 0;
-	char *pages_start, *data_end, *speed;
-	unsigned int length;
-	ssize_t total_written = 0;
-	
-	/* don't bother with anything else if we're not writing any data */
-	if (*nbytes <= 0)
-		return 0;
-	
-	if (level > MAX_TOPO_LEVEL)
-		return total_written;
-	/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
-        if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
-                return -ENOMEM;
-		
-	if (usbdev->parent && usbdev->parent->devnum != -1)
-		parent_devnum = usbdev->parent->devnum;
-	/*
-	 * So the root hub's parent is 0 and any device that is
-	 * plugged into the root hub has a parent of 0.
-	 */
-	switch (usbdev->speed) {
-	case USB_SPEED_LOW:
-		speed = "1.5"; break;
-	case USB_SPEED_UNKNOWN:		/* usb 1.1 root hub code */
-	case USB_SPEED_FULL:
-		speed = "12 "; break;
-	case USB_SPEED_HIGH:
-		speed = "480"; break;
-	default:
-		speed = "?? ";
-	}
-	data_end = pages_start + sprintf(pages_start, format_topo,
-			bus->busnum, level, parent_devnum,
-			index, count, usbdev->devnum,
-			speed, usbdev->maxchild);
-	/*
-	 * level = topology-tier level;
-	 * parent_devnum = parent device number;
-	 * index = parent's connector number;
-	 * count = device count at this level
-	 */
-	/* If this is the root hub, display the bandwidth information */
-	    /* FIXME high speed reserves 20% frametime for non-periodic,
-	     * while full/low speed reserves only 10% ... so this is wrong
-	     * for high speed busses.  also, change how bandwidth is recorded.
-	     */
-	if (level == 0)
-		data_end += sprintf(data_end, format_bandwidth, bus->bandwidth_allocated,
-				FRAME_TIME_MAX_USECS_ALLOC,
-				(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
-			         bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-	
-	data_end = usb_dump_desc(data_end, pages_start + (2 * PAGE_SIZE) - 256, usbdev);
-	
-	if (data_end > (pages_start + (2 * PAGE_SIZE) - 256))
-		data_end += sprintf(data_end, "(truncated)\n");
-	
-	length = data_end - pages_start;
-	/* if we can start copying some data to the user */
-	if (length > *skip_bytes) {
-		length -= *skip_bytes;
-		if (length > *nbytes)
-			length = *nbytes;
-		if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
-			free_pages((unsigned long)pages_start, 1);
-			
-			if (total_written == 0)
-				return -EFAULT;
-			return total_written;
-		}
-		*nbytes -= length;
-		*file_offset += length;
-		total_written += length;
-		*buffer += length;
-		*skip_bytes = 0;
-	} else
-		*skip_bytes -= length;
-	
-	free_pages((unsigned long)pages_start, 1);
-	
-	/* Now look at all of this device's children. */
-	for (chix = 0; chix < usbdev->maxchild; chix++) {
-		if (usbdev->children[chix]) {
-			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix],
-					bus, level + 1, chix, ++cnt);
-			if (ret == -EFAULT)
-				return total_written;
-			total_written += ret;
-		}
-	}
-	return total_written;
-}
-
-static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
-	struct list_head *buslist;
-	struct usb_bus *bus;
-	ssize_t ret, total_written = 0;
-	loff_t skip_bytes = *ppos;
-
-	if (*ppos < 0)
-		return -EINVAL;
-	if (nbytes <= 0)
-		return 0;
-	if (!access_ok(VERIFY_WRITE, buf, nbytes))
-		return -EFAULT;
-
-	/* enumerate busses */
-	down (&usb_bus_list_lock);
-	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
-		/* print devices for this bus */
-		bus = list_entry(buslist, struct usb_bus, bus_list);
-		/* recurse through all children of the root hub */
-		ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
-		if (ret < 0)
-			return ret;
-		total_written += ret;
-	}
-	up (&usb_bus_list_lock);
-	return total_written;
-}
-
-/* Kernel lock for "lastev" protection */
-static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct usb_device_status *st = (struct usb_device_status *)file->private_data;
-	unsigned int mask = 0;
-
-	lock_kernel();
-	if (!st) {
-		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-		if (!st) {
-			unlock_kernel();
-			return POLLIN;
-		}
-		/*
-		 * need to prevent the module from being unloaded, since
-		 * proc_unregister does not call the release method and
-		 * we would have a memory leak
-		 */
-		st->lastev = conndiscevcnt;
-		file->private_data = st;
-		mask = POLLIN;
-	}
-	if (file->f_mode & FMODE_READ)
-                poll_wait(file, &deviceconndiscwq, wait);
-	if (st->lastev != conndiscevcnt)
-		mask |= POLLIN;
-	st->lastev = conndiscevcnt;
-	unlock_kernel();
-	return mask;
-}
-
-static int usb_device_open(struct inode *inode, struct file *file)
-{
-        file->private_data = NULL;
-        return 0;
-}
-
-static int usb_device_release(struct inode *inode, struct file *file)
-{
-	if (file->private_data) {
-		kfree(file->private_data);
-		file->private_data = NULL;
-	}
-
-        return 0;
-}
-
-static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
-{
-	loff_t ret;
-
-	lock_kernel();
-
-	switch (orig) {
-	case 0:
-		file->f_pos = offset;
-		ret = file->f_pos;
-		break;
-	case 1:
-		file->f_pos += offset;
-		ret = file->f_pos;
-		break;
-	case 2:
-	default:
-		ret = -EINVAL;
-	}
-
-	unlock_kernel();
-	return ret;
-}
-
-struct file_operations usbdevfs_devices_fops = {
-	llseek:		usb_device_lseek,
-	read:		usb_device_read,
-	poll:		usb_device_poll,
-	open:		usb_device_open,
-	release:	usb_device_release,
-};
diff -Nru a/drivers/usb/devio.c b/drivers/usb/devio.c
--- a/drivers/usb/devio.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1241 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      devio.c  --  User space communication with USB devices.
- *
- *      Copyright (C) 1999-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *      This program is free software; you can redistribute it and/or 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.
- *
- *  $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $
- *
- *  This file implements the usbdevfs/x/y files, where
- *  x is the bus number and y the device number.
- *
- *  It allows user space programs/"drivers" to communicate directly
- *  with USB devices without intervening kernel driver.
- *
- *  Revision history
- *    22.12.1999   0.1   Initial release (split from proc_usb.c)
- *    04.01.2000   0.2   Turned into its own filesystem
- */
-
-/*****************************************************************************/
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/signal.h>
-#include <linux/poll.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usbdevice_fs.h>
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-
-
-struct async {
-        struct list_head asynclist;
-        struct dev_state *ps;
-	struct task_struct *task;
-	unsigned int signr;
-	void *userbuffer;
-        void *userurb;
-        struct urb *urb;
-};
-
-static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
-{
-	loff_t ret;
-
-	lock_kernel();
-
-	switch (orig) {
-	case 0:
-		file->f_pos = offset;
-		ret = file->f_pos;
-		break;
-	case 1:
-		file->f_pos += offset;
-		ret = file->f_pos;
-		break;
-	case 2:
-	default:
-		ret = -EINVAL;
-	}
-
-	unlock_kernel();
-	return ret;
-}
-
-static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos)
-{
-	struct dev_state *ps = (struct dev_state *)file->private_data;
-	ssize_t ret = 0;
-	unsigned len;
-	loff_t pos;
-	int i;
-
-	pos = *ppos;
-	down_read(&ps->devsem);
-	if (!ps->dev) {
-		ret = -ENODEV;
-		goto err;
-	} else if (pos < 0) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	if (pos < sizeof(struct usb_device_descriptor)) {
-		len = sizeof(struct usb_device_descriptor) - pos;
-		if (len > nbytes)
-			len = nbytes;
-		if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len)) {
-			ret = -EFAULT;
-			goto err;
-		}
-
-		*ppos += len;
-		buf += len;
-		nbytes -= len;
-		ret += len;
-	}
-
-	pos = sizeof(struct usb_device_descriptor);
-	for (i = 0; nbytes && i < ps->dev->descriptor.bNumConfigurations; i++) {
-		struct usb_config_descriptor *config =
-			(struct usb_config_descriptor *)ps->dev->rawdescriptors[i];
-		unsigned int length = le16_to_cpu(config->wTotalLength);
-
-		if (*ppos < pos + length) {
-			len = length - (*ppos - pos);
-			if (len > nbytes)
-				len = nbytes;
-
-			if (copy_to_user(buf,
-			    ps->dev->rawdescriptors[i] + (*ppos - pos), len)) {
-				ret = -EFAULT;
-				goto err;
-			}
-
-			*ppos += len;
-			buf += len;
-			nbytes -= len;
-			ret += len;
-		}
-
-		pos += length;
-	}
-
-err:
-	up_read(&ps->devsem);
-	return ret;
-}
-
-extern inline unsigned int ld2(unsigned int x)
-{
-        unsigned int r = 0;
-        
-        if (x >= 0x10000) {
-                x >>= 16;
-                r += 16;
-        }
-        if (x >= 0x100) {
-                x >>= 8;
-                r += 8;
-        }
-        if (x >= 0x10) {
-                x >>= 4;
-                r += 4;
-        }
-        if (x >= 4) {
-                x >>= 2;
-                r += 2;
-        }
-        if (x >= 2)
-                r++;
-        return r;
-}
-
-/*
- * async list handling
- */
-
-static struct async *alloc_async(unsigned int numisoframes)
-{
-        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor);
-        struct async *as = kmalloc(assize, GFP_KERNEL);
-        if (!as)
-                return NULL;
-        memset(as, 0, assize);
-	as->urb = usb_alloc_urb(numisoframes, GFP_KERNEL);
-	if (!as->urb) {
-		kfree(as);
-		return NULL;
-	}
-        return as;
-}
-
-static void free_async(struct async *as)
-{
-        if (as->urb->transfer_buffer)
-                kfree(as->urb->transfer_buffer);
-        if (as->urb->setup_packet)
-                kfree(as->urb->setup_packet);
-	usb_free_urb(as->urb);
-        kfree(as);
-}
-
-extern __inline__ void async_newpending(struct async *as)
-{
-        struct dev_state *ps = as->ps;
-        unsigned long flags;
-        
-        spin_lock_irqsave(&ps->lock, flags);
-        list_add_tail(&as->asynclist, &ps->async_pending);
-        spin_unlock_irqrestore(&ps->lock, flags);
-}
-
-extern __inline__ void async_removepending(struct async *as)
-{
-        struct dev_state *ps = as->ps;
-        unsigned long flags;
-        
-        spin_lock_irqsave(&ps->lock, flags);
-        list_del(&as->asynclist);
-        INIT_LIST_HEAD(&as->asynclist);
-        spin_unlock_irqrestore(&ps->lock, flags);
-}
-
-extern __inline__ struct async *async_getcompleted(struct dev_state *ps)
-{
-        unsigned long flags;
-        struct async *as = NULL;
-
-        spin_lock_irqsave(&ps->lock, flags);
-        if (!list_empty(&ps->async_completed)) {
-                as = list_entry(ps->async_completed.next, struct async, asynclist);
-                list_del(&as->asynclist);
-                INIT_LIST_HEAD(&as->asynclist);
-        }
-        spin_unlock_irqrestore(&ps->lock, flags);
-        return as;
-}
-
-extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb)
-{
-        unsigned long flags;
-        struct async *as;
-        struct list_head *p;
-
-        spin_lock_irqsave(&ps->lock, flags);
-        for (p = ps->async_pending.next; p != &ps->async_pending; ) {
-                as = list_entry(p, struct async, asynclist);
-                p = p->next;
-                if (as->userurb != userurb)
-                        continue;
-                list_del(&as->asynclist);
-                INIT_LIST_HEAD(&as->asynclist);
-                spin_unlock_irqrestore(&ps->lock, flags);
-                return as;
-        }
-        spin_unlock_irqrestore(&ps->lock, flags);
-        return NULL;
-}
-
-static void async_completed(struct urb *urb)
-{
-        struct async *as = (struct async *)urb->context;
-        struct dev_state *ps = as->ps;
-	struct siginfo sinfo;
-
-        spin_lock(&ps->lock);
-        list_del(&as->asynclist);
-        list_add_tail(&as->asynclist, &ps->async_completed);
-        spin_unlock(&ps->lock);
-        wake_up(&ps->wait);
-	if (as->signr) {
-		sinfo.si_signo = as->signr;
-		sinfo.si_errno = as->urb->status;
-		sinfo.si_code = SI_ASYNCIO;
-		sinfo.si_addr = as->userurb;
-		send_sig_info(as->signr, &sinfo, as->task);
-	}
-}
-
-static void destroy_all_async(struct dev_state *ps)
-{
-        struct async *as;
-        unsigned long flags;
-
-        spin_lock_irqsave(&ps->lock, flags);
-        while (!list_empty(&ps->async_pending)) {
-                as = list_entry(ps->async_pending.next, struct async, asynclist);
-                list_del(&as->asynclist);
-                INIT_LIST_HEAD(&as->asynclist);
-                spin_unlock_irqrestore(&ps->lock, flags);
-                /* usb_unlink_urb calls the completion handler with status == -ENOENT */
-                usb_unlink_urb(as->urb);
-                spin_lock_irqsave(&ps->lock, flags);
-        }
-        spin_unlock_irqrestore(&ps->lock, flags);
-        while ((as = async_getcompleted(ps)))
-                free_async(as);
-}
-
-/*
- * interface claiming
- */
-
-static void *driver_probe(struct usb_device *dev, unsigned int intf,
-			  const struct usb_device_id *id)
-{
-	return NULL;
-}
-
-static void driver_disconnect(struct usb_device *dev, void *context)
-{
-	struct dev_state *ps = (struct dev_state *)context;
-
-	if (ps)
-		ps->ifclaimed = 0;
-}
-
-struct usb_driver usbdevfs_driver = {
-	name:		"usbfs",
-	probe:		driver_probe,
-	disconnect:	driver_disconnect,
-};
-
-static int claimintf(struct dev_state *ps, unsigned int intf)
-{
-	struct usb_device *dev = ps->dev;
-	struct usb_interface *iface;
-	int err;
-
-	if (intf >= 8*sizeof(ps->ifclaimed) || !dev || intf >= dev->actconfig->bNumInterfaces)
-		return -EINVAL;
-	/* already claimed */
-	if (test_bit(intf, &ps->ifclaimed))
-		return 0;
-	iface = &dev->actconfig->interface[intf];
-	err = -EBUSY;
-	lock_kernel();
-	if (!usb_interface_claimed(iface)) {
-		usb_driver_claim_interface(&usbdevfs_driver, iface, ps);
-		set_bit(intf, &ps->ifclaimed);
-		err = 0;
-	}
-	unlock_kernel();
-	return err;
-}
-
-static int releaseintf(struct dev_state *ps, unsigned int intf)
-{
-	struct usb_device *dev;
-	struct usb_interface *iface;
-	int err;
-
-	if (intf >= 8*sizeof(ps->ifclaimed))
-		return -EINVAL;
-	err = -EINVAL;
-	lock_kernel();
-	dev = ps->dev;
-	if (dev && test_and_clear_bit(intf, &ps->ifclaimed)) {
-		iface = &dev->actconfig->interface[intf];
-		usb_driver_release_interface(&usbdevfs_driver, iface);
-		err = 0;
-	}
-	unlock_kernel();
-	return err;
-}
-
-static int checkintf(struct dev_state *ps, unsigned int intf)
-{
-	if (intf >= 8*sizeof(ps->ifclaimed))
-		return -EINVAL;
-	if (test_bit(intf, &ps->ifclaimed))
-		return 0;
-	/* if not yet claimed, claim it for the driver */
-	printk(KERN_WARNING "usbfs: process %d (%s) did not claim interface %u before use\n",
-	       current->pid, current->comm, intf);
-	return claimintf(ps, intf);
-}
-
-static int findintfep(struct usb_device *dev, unsigned int ep)
-{
-	unsigned int i, j, e;
-        struct usb_interface *iface;
-	struct usb_interface_descriptor *alts;
-	struct usb_endpoint_descriptor *endpt;
-
-	if (ep & ~(USB_DIR_IN|0xf))
-		return -EINVAL;
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-		iface = &dev->actconfig->interface[i];
-		for (j = 0; j < iface->num_altsetting; j++) {
-                        alts = &iface->altsetting[j];
-			for (e = 0; e < alts->bNumEndpoints; e++) {
-				endpt = &alts->endpoint[e];
-				if (endpt->bEndpointAddress == ep)
-					return i;
-			}
-		}
-	}
-	return -ENOENT; 
-}
-
-static int findintfif(struct usb_device *dev, unsigned int ifn)
-{
-	unsigned int i, j;
-        struct usb_interface *iface;
-	struct usb_interface_descriptor *alts;
-
-	if (ifn & ~0xff)
-		return -EINVAL;
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-		iface = &dev->actconfig->interface[i];
-		for (j = 0; j < iface->num_altsetting; j++) {
-                        alts = &iface->altsetting[j];
-			if (alts->bInterfaceNumber == ifn)
-				return i;
-		}
-	}
-	return -ENOENT; 
-}
-
-extern struct list_head usb_driver_list;
-
-#if 0
-static int finddriver(struct usb_driver **driver, char *name)
-{
-	struct list_head *tmp;
-
-	tmp = usb_driver_list.next;
-	while (tmp != &usb_driver_list) {
-		struct usb_driver *d = list_entry(tmp, struct usb_driver,
-							driver_list);
-
-		if (!strcmp(d->name, name)) {
-			*driver = d;
-			return 0;
-		}
-
-		tmp = tmp->next;
-	}
-
-	return -EINVAL;
-}
-#endif
-
-static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
-{
-	int ret;
-
-	if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
-		return 0;
-
-	switch (requesttype & USB_RECIP_MASK) {
-	case USB_RECIP_ENDPOINT:
-		if ((ret = findintfep(ps->dev, index & 0xff)) < 0)
-			return ret;
-		if ((ret = checkintf(ps, ret)))
-			return ret;
-		break;
-
-	case USB_RECIP_INTERFACE:
-		if ((ret = findintfif(ps->dev, index & 0xff)) < 0)
-			return ret;
-		if ((ret = checkintf(ps, ret)))
-			return ret;
-		break;
-	}
-	return 0;
-}
-
-/*
- * file operations
- */
-static int usbdev_open(struct inode *inode, struct file *file)
-{
-	struct usb_device *dev;
-	struct dev_state *ps;
-	int ret;
-
-	/* 
-	 * no locking necessary here, as both sys_open (actually filp_open)
-	 * and the hub thread have the kernel lock
-	 * (still acquire the kernel lock for safety)
-	 */
-	lock_kernel();
-	ret = -ENOENT;
-	dev = inode->u.generic_ip;
-	if (!dev)
-		goto out;
-	ret = -ENOMEM;
-	if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
-		goto out;
-	ret = 0;
-	ps->dev = dev;
-	ps->file = file;
-	spin_lock_init(&ps->lock);
-	INIT_LIST_HEAD(&ps->async_pending);
-	INIT_LIST_HEAD(&ps->async_completed);
-	init_waitqueue_head(&ps->wait);
-	init_rwsem(&ps->devsem);
-	ps->discsignr = 0;
-	ps->disctask = current;
-	ps->disccontext = NULL;
-	ps->ifclaimed = 0;
-	wmb();
-	list_add_tail(&ps->list, &dev->filelist);
-	file->private_data = ps;
- out:
-	unlock_kernel();
-        return ret;
-}
-
-static int usbdev_release(struct inode *inode, struct file *file)
-{
-	struct dev_state *ps = (struct dev_state *)file->private_data;
-	unsigned int i;
-
-	lock_kernel();
-	list_del(&ps->list);
-	INIT_LIST_HEAD(&ps->list);
-	if (ps->dev) {
-		for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
-			if (test_bit(i, &ps->ifclaimed))
-				releaseintf(ps, i);
-	}
-	unlock_kernel();
-	destroy_all_async(ps);
-	kfree(ps);
-        return 0;
-}
-
-static int proc_control(struct dev_state *ps, void *arg)
-{
-	struct usb_device *dev = ps->dev;
-	struct usbdevfs_ctrltransfer ctrl;
-	unsigned int tmo;
-	unsigned char *tbuf;
-	int i, ret;
-
-	if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl)))
-		return -EFAULT;
-	if ((ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex)))
-		return ret;
-	if (ctrl.wLength > PAGE_SIZE)
-		return -EINVAL;
-	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	tmo = (ctrl.timeout * HZ + 999) / 1000;
-	if (ctrl.bRequestType & 0x80) {
-		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
-			free_page((unsigned long)tbuf);
-			return -EINVAL;
-		}
-		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
-		if ((i > 0) && ctrl.wLength) {
-			if (copy_to_user(ctrl.data, tbuf, ctrl.wLength)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
-		}
-	} else {
-		if (ctrl.wLength) {
-			if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
-		}
-		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
-				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
-	}
-	free_page((unsigned long)tbuf);
-	if (i<0) {
-		printk(KERN_DEBUG "usbfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d\n", 
-		       dev->devnum, ctrl.bRequestType, ctrl.bRequest, ctrl.wLength, i);
-	}
-	return i;
-}
-
-static int proc_bulk(struct dev_state *ps, void *arg)
-{
-	struct usb_device *dev = ps->dev;
-	struct usbdevfs_bulktransfer bulk;
-	unsigned int tmo, len1, pipe;
-	int len2;
-	unsigned char *tbuf;
-	int i, ret;
-
-	if (copy_from_user(&bulk, (void *)arg, sizeof(bulk)))
-		return -EFAULT;
-	if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
-		return ret;
-	if ((ret = checkintf(ps, ret)))
-		return ret;
-	if (bulk.ep & USB_DIR_IN)
-		pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
-	else
-		pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
-	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
-		return -EINVAL;
-	len1 = bulk.len;
-	if (len1 > PAGE_SIZE)
-		return -EINVAL;
-	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	tmo = (bulk.timeout * HZ + 999) / 1000;
-	if (bulk.ep & 0x80) {
-		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
-			free_page((unsigned long)tbuf);
-			return -EINVAL;
-		}
-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
-		if (!i && len2) {
-			if (copy_to_user(bulk.data, tbuf, len2)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
-		}
-	} else {
-		if (len1) {
-			if (copy_from_user(tbuf, bulk.data, len1)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
-		}
-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
-	}
-	free_page((unsigned long)tbuf);
-	if (i < 0) {
-		printk(KERN_WARNING "usbfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n", 
-		       dev->devnum, bulk.ep, bulk.len, i);
-		return i;
-	}
-	return len2;
-}
-
-static int proc_resetep(struct dev_state *ps, void *arg)
-{
-	unsigned int ep;
-	int ret;
-
-	if (get_user(ep, (unsigned int *)arg))
-		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
-		return ret;
-	if ((ret = checkintf(ps, ret)))
-		return ret;
-	usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
-	return 0;
-}
-
-static int proc_clearhalt(struct dev_state *ps, void *arg)
-{
-	unsigned int ep;
-	int pipe;
-	int ret;
-
-	if (get_user(ep, (unsigned int *)arg))
-		return -EFAULT;
-	if ((ret = findintfep(ps->dev, ep)) < 0)
-		return ret;
-	if ((ret = checkintf(ps, ret)))
-		return ret;
-	if (ep & USB_DIR_IN)
-                pipe = usb_rcvbulkpipe(ps->dev, ep & 0x7f);
-        else
-                pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
-
-	return usb_clear_halt(ps->dev, pipe);
-}
-		
-
-static int proc_getdriver(struct dev_state *ps, void *arg)
-{
-	struct usbdevfs_getdriver gd;
-	struct usb_interface *interface;
-	int ret;
-
-	if (copy_from_user(&gd, arg, sizeof(gd)))
-		return -EFAULT;
-	if ((ret = findintfif(ps->dev, gd.interface)) < 0)
-		return ret;
-	interface = usb_ifnum_to_if(ps->dev, gd.interface);
-	if (!interface)
-		return -EINVAL;
-	if (!interface->driver)
-		return -ENODATA;
-	strcpy(gd.driver, interface->driver->name);
-	if (copy_to_user(arg, &gd, sizeof(gd)))
-		return -EFAULT;
-	return 0;
-}
-
-static int proc_connectinfo(struct dev_state *ps, void *arg)
-{
-	struct usbdevfs_connectinfo ci;
-
-	ci.devnum = ps->dev->devnum;
-	ci.slow = ps->dev->speed == USB_SPEED_LOW;
-	if (copy_to_user(arg, &ci, sizeof(ci)))
-		return -EFAULT;
-	return 0;
-}
-
-static int proc_resetdevice(struct dev_state *ps)
-{
-	int i, ret;
-
-	ret = usb_reset_device(ps->dev);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < ps->dev->actconfig->bNumInterfaces; i++) {
-		struct usb_interface *intf = &ps->dev->actconfig->interface[i];
-
-		/* Don't simulate interfaces we've claimed */
-		if (test_bit(i, &ps->ifclaimed))
-			continue;
-
-		if (intf->driver) {
-			const struct usb_device_id *id;
-			down(&intf->driver->serialize);
-			intf->driver->disconnect(ps->dev, intf->private_data);
-			id = usb_match_id(ps->dev,intf,intf->driver->id_table);
-			intf->driver->probe(ps->dev, i, id);
-			up(&intf->driver->serialize);
-		}
-	}
-
-	return 0;
-}
-
-static int proc_setintf(struct dev_state *ps, void *arg)
-{
-	struct usbdevfs_setinterface setintf;
-	struct usb_interface *interface;
-	int ret;
-
-	if (copy_from_user(&setintf, arg, sizeof(setintf)))
-		return -EFAULT;
-	if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
-		return ret;
-	interface = usb_ifnum_to_if(ps->dev, setintf.interface);
-	if (!interface)
-		return -EINVAL;
-	if (interface->driver) {
-		if ((ret = checkintf(ps, ret)))
-			return ret;
-	}
-	if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting))
-		return -EINVAL;
-	return 0;
-}
-
-static int proc_setconfig(struct dev_state *ps, void *arg)
-{
-	unsigned int u;
-
-	if (get_user(u, (unsigned int *)arg))
-		return -EFAULT;
-	if (usb_set_configuration(ps->dev, u) < 0)
-		return -EINVAL;
-	return 0;
-}
-
-static int proc_submiturb(struct dev_state *ps, void *arg)
-{
-	struct usbdevfs_urb uurb;
-	struct usbdevfs_iso_packet_desc *isopkt = NULL;
-	struct usb_endpoint_descriptor *ep_desc;
-	struct async *as;
-	struct usb_ctrlrequest *dr = NULL;
-	unsigned int u, totlen, isofrmlen;
-	int ret;
-
-	if (copy_from_user(&uurb, arg, sizeof(uurb)))
-		return -EFAULT;
-	if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD|USBDEVFS_URB_QUEUE_BULK|
-			   USB_NO_FSBR|USB_ZERO_PACKET))
-		return -EINVAL;
-	if (!uurb.buffer)
-		return -EINVAL;
-	if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
-		return -EINVAL;
-	if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
-		if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
-			return ret;
-		if ((ret = checkintf(ps, ret)))
-			return ret;
-	}
-	switch(uurb.type) {
-	case USBDEVFS_URB_TYPE_CONTROL:
-		if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0) {
-			if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
-				return -ENOENT;
-			if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL)
-				return -EINVAL;
-		}
-		/* min 8 byte setup packet, max arbitrary */
-		if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
-			return -EINVAL;
-		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
-			return -ENOMEM;
-		if (copy_from_user(dr, (unsigned char*)uurb.buffer, 8)) {
-			kfree(dr);
-			return -EFAULT;
-		}
-		if (uurb.buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
-			kfree(dr);
-			return -EINVAL;
-		}
-		if ((ret = check_ctrlrecip(ps, dr->bRequestType, le16_to_cpup(&dr->wIndex)))) {
-			kfree(dr);
-			return ret;
-		}
-		uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
-		uurb.number_of_packets = 0;
-		uurb.buffer_length = le16_to_cpup(&dr->wLength);
-		uurb.buffer += 8;
-		if (!access_ok((uurb.endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
-			kfree(dr);
-			return -EFAULT;
-		}
-		break;
-
-	case USBDEVFS_URB_TYPE_BULK:
-		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > 16384)
-			return -EINVAL;
-		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
-			return -EFAULT;
-		break;
-
-	case USBDEVFS_URB_TYPE_ISO:
-		/* arbitrary limit */
-		if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
-			return -EINVAL;
-		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
-		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
-			return -ENOMEM;
-		if (copy_from_user(isopkt, &((struct usbdevfs_urb *)arg)->iso_frame_desc, isofrmlen)) {
-			kfree(isopkt);
-			return -EFAULT;
-		}
-		for (totlen = u = 0; u < uurb.number_of_packets; u++) {
-			if (isopkt[u].length > 1023) {
-				kfree(isopkt);
-				return -EINVAL;
-			}
-			totlen += isopkt[u].length;
-		}
-		if (totlen > 32768) {
-			kfree(isopkt);
-			return -EINVAL;
-		}
-		uurb.buffer_length = totlen;
-		break;
-
-	case USBDEVFS_URB_TYPE_INTERRUPT:
-		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > 16384)
-			return -EINVAL;
-		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
-			return -EFAULT;   
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (!(as = alloc_async(uurb.number_of_packets))) {
-		if (isopkt)
-			kfree(isopkt);
-		if (dr)
-			kfree(dr);
-		return -ENOMEM;
-	}
-	if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
-		if (isopkt)
-			kfree(isopkt);
-		if (dr)
-			kfree(dr);
-		free_async(as);
-		return -ENOMEM;
-	}
-        as->urb->next = NULL;
-        as->urb->dev = ps->dev;
-        as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
-        as->urb->transfer_flags = uurb.flags;
-	as->urb->transfer_buffer_length = uurb.buffer_length;
-	as->urb->setup_packet = (unsigned char*)dr;
-	as->urb->start_frame = uurb.start_frame;
-	as->urb->number_of_packets = uurb.number_of_packets;
-        as->urb->context = as;
-        as->urb->complete = async_completed;
-	for (totlen = u = 0; u < uurb.number_of_packets; u++) {
-		as->urb->iso_frame_desc[u].offset = totlen;
-		as->urb->iso_frame_desc[u].length = isopkt[u].length;
-		totlen += isopkt[u].length;
-	}
-	if (isopkt)
-		kfree(isopkt);
-	as->ps = ps;
-        as->userurb = arg;
-	if (uurb.endpoint & USB_DIR_IN)
-		as->userbuffer = uurb.buffer;
-	else
-		as->userbuffer = NULL;
-	as->signr = uurb.signr;
-	as->task = current;
-	if (!(uurb.endpoint & USB_DIR_IN)) {
-		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
-			free_async(as);
-			return -EFAULT;
-		}
-	}
-        async_newpending(as);
-        if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
-		printk(KERN_DEBUG "usbfs: usb_submit_urb returned %d\n", ret);
-                async_removepending(as);
-                free_async(as);
-                return ret;
-        }
-        return 0;
-}
-
-static int proc_unlinkurb(struct dev_state *ps, void *arg)
-{
-	struct async *as;
-
-	as = async_getpending(ps, arg);
-	if (!as)
-		return -EINVAL;
-	usb_unlink_urb(as->urb);
-	return 0;
-}
-
-static int processcompl(struct async *as)
-{
-	struct urb *urb = as->urb;
-	unsigned int i;
-
-	if (as->userbuffer)
-		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
-			return -EFAULT;
-	if (put_user(urb->status,
-		     &((struct usbdevfs_urb *)as->userurb)->status))
-		return -EFAULT;
-	if (put_user(urb->actual_length,
-		     &((struct usbdevfs_urb *)as->userurb)->actual_length))
-		return -EFAULT;
-	if (put_user(urb->error_count,
-		     &((struct usbdevfs_urb *)as->userurb)->error_count))
-		return -EFAULT;
-
-	if (!(usb_pipeisoc(urb->pipe)))
-		return 0;
-	for (i = 0; i < urb->number_of_packets; i++) {
-		if (put_user(urb->iso_frame_desc[i].actual_length, 
-			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length))
-			return -EFAULT;
-		if (put_user(urb->iso_frame_desc[i].status, 
-			     &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-static int proc_reapurb(struct dev_state *ps, void *arg)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	struct async *as = NULL;
-	void *addr;
-	int ret;
-
-	add_wait_queue(&ps->wait, &wait);
-	while (ps->dev) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if ((as = async_getcompleted(ps)))
-			break;
-		if (signal_pending(current))
-			break;
-		up_read(&ps->devsem);
-		schedule();
-		down_read(&ps->devsem);
-	}
-	remove_wait_queue(&ps->wait, &wait);
-	set_current_state(TASK_RUNNING);
-	if (as) {
-		ret = processcompl(as);
-		addr = as->userurb;
-		free_async(as);
-		if (ret)
-			return ret;
-		if (put_user(addr, (void **)arg))
-			return -EFAULT;
-		return 0;
-	}
-	if (signal_pending(current))
-		return -EINTR;
-	return -EIO;
-}
-
-static int proc_reapurbnonblock(struct dev_state *ps, void *arg)
-{
-	struct async *as;
-	void *addr;
-	int ret;
-
-	if (!(as = async_getcompleted(ps)))
-		return -EAGAIN;
-	ret = processcompl(as);
-	addr = as->userurb;
-	free_async(as);
-	if (ret)
-		return ret;
-	if (put_user(addr, (void **)arg))
-		return -EFAULT;
-	return 0;
-}
-
-static int proc_disconnectsignal(struct dev_state *ps, void *arg)
-{
-	struct usbdevfs_disconnectsignal ds;
-
-	if (copy_from_user(&ds, arg, sizeof(ds)))
-		return -EFAULT;
-	if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))
-		return -EINVAL;
-	ps->discsignr = ds.signr;
-	ps->disccontext = ds.context;
-	return 0;
-}
-
-static int proc_claiminterface(struct dev_state *ps, void *arg)
-{
-	unsigned int intf;
-	int ret;
-
-	if (get_user(intf, (unsigned int *)arg))
-		return -EFAULT;
-	if ((ret = findintfif(ps->dev, intf)) < 0)
-		return ret;
-	return claimintf(ps, ret);
-}
-
-static int proc_releaseinterface(struct dev_state *ps, void *arg)
-{
-	unsigned int intf;
-	int ret;
-
-	if (get_user(intf, (unsigned int *)arg))
-		return -EFAULT;
-	if ((ret = findintfif(ps->dev, intf)) < 0)
-		return ret;
-	return releaseintf(ps, intf);
-}
-
-static int proc_ioctl (struct dev_state *ps, void *arg)
-{
-	struct usbdevfs_ioctl	ctrl;
-	int			size;
-	void			*buf = 0;
-	int			retval = 0;
-
-	/* get input parameters and alloc buffer */
-	if (copy_from_user(&ctrl, (void *) arg, sizeof (ctrl)))
-		return -EFAULT;
-	if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
-		if ((buf = kmalloc (size, GFP_KERNEL)) == 0)
-			return -ENOMEM;
-		if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
-			if (copy_from_user (buf, ctrl.data, size)) {
-				kfree (buf);
-				return -EFAULT;
-			}
-		} else {
-			memset (buf, 0, size);
-		}
-	}
-
-	/* ioctl to device */
-	if (ctrl.ifno < 0) {
-		switch (ctrl.ioctl_code) {
-		/* access/release token for issuing control messages
-		 * ask a particular driver to bind/unbind, ... etc
-		 */
-		}
-		retval = -ENOSYS;
-
-	/* ioctl to the driver which has claimed a given interface */
-	} else {
-		struct usb_interface	*ifp = 0;
-		if (!ps->dev)
-			retval = -ENODEV;
-		else if (ctrl.ifno >= ps->dev->actconfig->bNumInterfaces)
-			retval = -EINVAL;
-		else {
-			if (!(ifp = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
-				retval = -EINVAL;
-			else if (ifp->driver == 0 || ifp->driver->ioctl == 0)
-				retval = -ENOSYS;
-		}
-		if (retval == 0) {
-			if (ifp->driver->owner)
-				__MOD_INC_USE_COUNT(ifp->driver->owner);
-			/* ifno might usefully be passed ... */
-			retval = ifp->driver->ioctl (ps->dev, ctrl.ioctl_code, buf);
-			/* size = min_t(int, size, retval)? */
-			if (ifp->driver->owner)
-				__MOD_DEC_USE_COUNT(ifp->driver->owner);
-		}
-	}
-
-	/* cleanup and return */
-	if (retval >= 0
-			&& (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
-			&& size > 0
-			&& copy_to_user (ctrl.data, buf, size) != 0)
-		retval = -EFAULT;
-	if (buf != 0)
-		kfree (buf);
-	return retval;
-}
-
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct dev_state *ps = (struct dev_state *)file->private_data;
-	int ret = -ENOIOCTLCMD;
-
-	if (!(file->f_mode & FMODE_WRITE))
-		return -EPERM;
-	down_read(&ps->devsem);
-	if (!ps->dev) {
-		up_read(&ps->devsem);
-		return -ENODEV;
-	}
-	switch (cmd) {
-	case USBDEVFS_CONTROL:
-		ret = proc_control(ps, (void *)arg);
-		if (ret >= 0)
-			inode->i_mtime = CURRENT_TIME;
-		break;
-
-	case USBDEVFS_BULK:
-		ret = proc_bulk(ps, (void *)arg);
-		if (ret >= 0)
-			inode->i_mtime = CURRENT_TIME;
-		break;
-
-	case USBDEVFS_RESETEP:
-		ret = proc_resetep(ps, (void *)arg);
-		if (ret >= 0)
-			inode->i_mtime = CURRENT_TIME;
-		break;
-
-	case USBDEVFS_RESET:
-		ret = proc_resetdevice(ps);
-		break;
-	
-	case USBDEVFS_CLEAR_HALT:
-		ret = proc_clearhalt(ps, (void *)arg);
-		if (ret >= 0)
-			inode->i_mtime = CURRENT_TIME;
-		break;
-
-	case USBDEVFS_GETDRIVER:
-		ret = proc_getdriver(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_CONNECTINFO:
-		ret = proc_connectinfo(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_SETINTERFACE:
-		ret = proc_setintf(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_SETCONFIGURATION:
-		ret = proc_setconfig(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_SUBMITURB:
-		ret = proc_submiturb(ps, (void *)arg);
-		if (ret >= 0)
-			inode->i_mtime = CURRENT_TIME;
-		break;
-
-	case USBDEVFS_DISCARDURB:
-		ret = proc_unlinkurb(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_REAPURB:
-		ret = proc_reapurb(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_REAPURBNDELAY:
-		ret = proc_reapurbnonblock(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_DISCSIGNAL:
-		ret = proc_disconnectsignal(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_CLAIMINTERFACE:
-		ret = proc_claiminterface(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_RELEASEINTERFACE:
-		ret = proc_releaseinterface(ps, (void *)arg);
-		break;
-
-	case USBDEVFS_IOCTL:
-		ret = proc_ioctl(ps, (void *) arg);
-		break;
-	}
-	up_read(&ps->devsem);
-	if (ret >= 0)
-		inode->i_atime = CURRENT_TIME;
-	return ret;
-}
-
-/* No kernel lock - fine */
-static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct dev_state *ps = (struct dev_state *)file->private_data;
-        unsigned int mask = 0;
-
-	poll_wait(file, &ps->wait, wait);
-	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
-		mask |= POLLOUT | POLLWRNORM;
-	if (!ps->dev)
-		mask |= POLLERR | POLLHUP;
-	return mask;
-}
-
-struct file_operations usbdevfs_device_file_operations = {
-	llseek:		usbdev_lseek,
-	read:		usbdev_read,
-	poll:		usbdev_poll,
-	ioctl:		usbdev_ioctl,
-	open:		usbdev_open,
-	release:	usbdev_release,
-};
diff -Nru a/drivers/usb/drivers.c b/drivers/usb/drivers.c
--- a/drivers/usb/drivers.c	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,123 +0,0 @@
-/*
- * drivers.c
- * (C) Copyright 1999 Randy Dunlap.
- * (C) Copyright 1999, 2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
- * (C) Copyright 1999 Deti Fliegl (new USB architecture)
- *
- * $id$
- *
- * This program is free software; you can redistribute it and/or 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
- *
- *************************************************************
- *
- * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *   Converted the whole proc stuff to real
- *   read methods. Now not the whole device list needs to fit
- *   into one page, only the device list for one bus.
- *   Added a poll method to /proc/bus/usb/devices, to wake
- *   up an eventual usbd
- * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *   Turned into its own filesystem
- *
- * $Id: drivers.c,v 1.3 2000/01/11 13:58:24 tom Exp $
- */
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/usb.h>
-#include <linux/usbdevice_fs.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-
-/*****************************************************************/
-
-/*
- * Dump usb_driver_list.
- *
- * We now walk the list of registered USB drivers.
- */
-static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
-	struct list_head *tmp = usb_driver_list.next;
-	char *page, *start, *end;
-	ssize_t ret = 0;
-	unsigned int pos, len;
-
-	if (*ppos < 0)
-		return -EINVAL;
-	if (nbytes <= 0)
-		return 0;
-	if (!access_ok(VERIFY_WRITE, buf, nbytes))
-		return -EFAULT;
-        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-                return -ENOMEM;
-	start = page;
-	end = page + (PAGE_SIZE - 100);
-	pos = *ppos;
-	for (; tmp != &usb_driver_list; tmp = tmp->next) {
-		struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
-		int minor = driver->fops ? driver->minor : -1;
-		if (minor == -1)
-			start += sprintf (start, "         %s\n", driver->name);
-		else
-			start += sprintf (start, "%3d-%3d: %s\n", minor, minor + 15, driver->name);
-		if (start > end) {
-			start += sprintf(start, "(truncated)\n");
-			break;
-		}
-	}
-	if (start == page)
-		start += sprintf(start, "(none)\n");
-	len = start - page;
-	if (len > pos) {
-		len -= pos;
-		if (len > nbytes)
-			len = nbytes;
-		ret = len;
-		if (copy_to_user(buf, page + pos, len))
-			ret = -EFAULT;
-		else
-			*ppos += len;
-	}
-	free_page((unsigned long)page);
-	return ret;
-}
-
-static loff_t usb_driver_lseek(struct file * file, loff_t offset, int orig)
-{
-	loff_t ret;
-
-	lock_kernel();
-	switch (orig) {
-	case 0:
-		file->f_pos = offset;
-		ret = file->f_pos;
-		break;
-	case 1:
-		file->f_pos += offset;
-		ret = file->f_pos;
-		break;
-	case 2:
-	default:
-		ret = -EINVAL;
-	}
-	unlock_kernel();
-	return ret;
-}
-
-struct file_operations usbdevfs_drivers_fops = {
-	llseek:		usb_driver_lseek,
-	read:		usb_driver_read,
-};
diff -Nru a/drivers/usb/dsbr100.c b/drivers/usb/dsbr100.c
--- a/drivers/usb/dsbr100.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,369 +0,0 @@
-/* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
- into both the USB and an analog audio input, so this thing
- only deals with initialisation and frequency setting, the
- audio data has to be handled by a sound driver.
-
- Major issue: I can't find out where the device reports the signal
- strength, and indeed the windows software appearantly just looks
- at the stereo indicator as well.  So, scanning will only find
- stereo stations.  Sad, but I can't help it.
-
- Also, the windows program sends oodles of messages over to the
- device, and I couldn't figure out their meaning.  My suspicion
- is that they don't have any:-)
-
- You might find some interesting stuff about this module at
- http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
-
- Copyright (c) 2000 Markus Demleitner <msdemlei@tucana.harvard.edu>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- History:
-
- Version 0.24:
- 	Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
-	right.  Some minor cleanup, improved standalone compilation
-
- Version 0.23:
- 	Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
-
- Version 0.22:
- 	Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, 
-	thanks to Mike Cox for pointing the problem out.
-
- Version 0.21:
- 	Markus: Minor cleanup, warnings if something goes wrong, lame attempt
-	to adhere to Documentation/CodingStyle
-
- Version 0.2: 
- 	Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
-	Markus: Copyright clarification
-
- Version 0.01: Markus: initial release
-
-*/
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/videodev.h>
-#include <linux/usb.h>
-#include <linux/smp_lock.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.24"
-#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
-#define DRIVER_DESC "D-Link DSB-R100 USB radio driver"
-
-#define DSB100_VENDOR 0x04b4
-#define DSB100_PRODUCT 0x1002
-
-#define TB_LEN 16
-
-static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum,
-			 const struct usb_device_id *id);
-static void usb_dsbr100_disconnect(struct usb_device *dev, void *ptr);
-static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, void *arg);
-static int usb_dsbr100_open(struct inode *inode, struct file *file);
-static int usb_dsbr100_close(struct inode *inode, struct file *file);
-
-static int radio_nr = -1;
-MODULE_PARM(radio_nr, "i");
-
-typedef struct
-{
-	struct usb_device *dev;
-	unsigned char transfer_buffer[TB_LEN];
-	int curfreq;
-	int stereo;
-	int ifnum;
-} usb_dsbr100;
-
-
-static struct file_operations usb_dsbr100_fops = {
-	owner:		THIS_MODULE,
-	open:		usb_dsbr100_open,
-	release:       	usb_dsbr100_close,
-	ioctl:          video_generic_ioctl,
-	llseek:         no_llseek,
-};
-static struct video_device usb_dsbr100_radio=
-{
-	owner:		THIS_MODULE,
-	name:		"D-Link DSB R-100 USB radio",
-	type:		VID_TYPE_TUNER,
-	hardware:	VID_HARDWARE_AZTECH,
-	fops:           &usb_dsbr100_fops,
-	kernel_ioctl:  	usb_dsbr100_ioctl,
-};
-
-static int users = 0;
-
-static struct usb_device_id usb_dsbr100_table [] = {
-	{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_dsbr100_table);
-
-static struct usb_driver usb_dsbr100_driver = {
-	name:		"dsbr100",
-	probe:		usb_dsbr100_probe,
-	disconnect:	usb_dsbr100_disconnect,
-	fops:		NULL,
-	minor:		0,
-	id_table:	usb_dsbr100_table,
-};
-
-
-static int dsbr100_start(usb_dsbr100 *radio)
-{
-	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x00, 0xC0, 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
-	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x02, 0xC0, 0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
-		return -1;
-	return (radio->transfer_buffer)[0];
-}
-
-
-static int dsbr100_stop(usb_dsbr100 *radio)
-{
-	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x00, 0xC0, 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
-	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x02, 0xC0, 0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
-		return -1;
-	return (radio->transfer_buffer)[0];
-}
-
-
-static int dsbr100_setfreq(usb_dsbr100 *radio, int freq)
-{
-	freq = (freq/16*80)/1000+856;
-	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x01, 0xC0, (freq>>8)&0x00ff, freq&0xff, 
-		radio->transfer_buffer, 8, 300)<0 ||
-	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x00, 0xC0, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
-	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x00, 0xC0, 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
-		radio->stereo = -1;
-		return -1;
-	}
-	radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
-	return (radio->transfer_buffer)[0];
-}
-
-static void dsbr100_getstat(usb_dsbr100 *radio)
-{
-	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-		0x00, 0xC0, 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
-		radio->stereo = -1;
-	else
-		radio->stereo = ! (radio->transfer_buffer[0]&0x01);
-}
-
-
-static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum,
-			 const struct usb_device_id *id)
-{
-	usb_dsbr100 *radio;
-
-	if (!(radio = kmalloc(sizeof(usb_dsbr100),GFP_KERNEL)))
-		return NULL;
-	usb_dsbr100_radio.priv = radio;
-	radio->dev = dev;
-	radio->ifnum = ifnum;
-	radio->curfreq = 1454000;
-	return (void*)radio;
-}
-
-static void usb_dsbr100_disconnect(struct usb_device *dev, void *ptr)
-{
-	usb_dsbr100 *radio=ptr;
-
-	lock_kernel();
-	if (users) {
-		unlock_kernel();
-		return;
-	}
-	kfree(radio);
-	usb_dsbr100_radio.priv = NULL;
-	unlock_kernel();
-}
-
-static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, void *arg)
-{
-	struct video_device *dev = video_devdata(file);
-	usb_dsbr100 *radio=dev->priv;
-
-	if (!radio)
-		return -EINVAL;
-
-	switch(cmd)
-	{
-		case VIDIOCGCAP: {
-			struct video_capability *v = arg;
-			memset(v,0,sizeof(*v));
-			v->type=VID_TYPE_TUNER;
-			v->channels=1;
-			v->audios=1;
-			strcpy(v->name, "D-Link R-100 USB Radio");
-			return 0;
-		}
-		case VIDIOCGTUNER: {
-			struct video_tuner *v = arg;
-			dsbr100_getstat(radio);
-			if(v->tuner)	/* Only 1 tuner */ 
-				return -EINVAL;
-			v->rangelow = 87*16000;
-			v->rangehigh = 108*16000;
-			v->flags = VIDEO_TUNER_LOW;
-			v->mode = VIDEO_MODE_AUTO;
-			v->signal = radio->stereo*0x7000;
-				/* Don't know how to get signal strength */
-			v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;
-			strcpy(v->name, "DSB R-100");
-			return 0;
-		}
-		case VIDIOCSTUNER: {
-			struct video_tuner *v = arg;
-			if(v->tuner!=0)
-				return -EINVAL;
-			/* Only 1 tuner so no setting needed ! */
-			return 0;
-		}
-		case VIDIOCGFREQ:
-		{
-			int *freq = arg;
-			if (radio->curfreq==-1)
-				return -EINVAL;
-			*freq = radio->curfreq;
-			return 0;
-		}
-		case VIDIOCSFREQ:
-		{
-			int *freq = arg;
-			*freq = radio->curfreq;
-			if (dsbr100_setfreq(radio, radio->curfreq)==-1)
-				warn("set frequency failed");
-			return 0;
-		}
-		case VIDIOCGAUDIO: {
-			struct video_audio *v = arg;
-			memset(v,0, sizeof(*v));
-			v->flags|=VIDEO_AUDIO_MUTABLE;
-			v->mode=VIDEO_SOUND_STEREO;
-			v->volume=1;
-			v->step=1;
-			strcpy(v->name, "Radio");
-			return 0;			
-		}
-		case VIDIOCSAUDIO: {
-			struct video_audio *v = arg;
-			if(v->audio) 
-				return -EINVAL;
-
-			if(v->flags&VIDEO_AUDIO_MUTE) {
-				if (dsbr100_stop(radio)==-1)
-					warn("radio did not respond properly");
-			}
-			else
-				if (dsbr100_start(radio)==-1)
-					warn("radio did not respond properly");
-			return 0;
-		}
-		default:
-			return -ENOIOCTLCMD;
-	}
-}
-
-
-static int usb_dsbr100_open(struct inode *inode, struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	usb_dsbr100 *radio=dev->priv;
-
-	if (! radio) {
-		warn("radio not initialised");
-		return -EAGAIN;
-	}
-	if(users)
-	{
-		warn("radio in use");
-		return -EBUSY;
-	}
-	users++;
-	if (dsbr100_start(radio)<0)
-		warn("radio did not start up properly");
-	dsbr100_setfreq(radio,radio->curfreq);
-	return 0;
-}
-
-static int usb_dsbr100_close(struct inode *inode, struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	usb_dsbr100 *radio=dev->priv;
-
-	if (!radio)
-		return -ENODEV;
-	users--;
-	dsbr100_stop(radio);
-	return 0;
-}
-
-static int __init dsbr100_init(void)
-{
-	usb_dsbr100_radio.priv = NULL;
-	usb_register(&usb_dsbr100_driver);
-	if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO,radio_nr)==-1) {	
-		warn("couldn't register video device");
-		return -EINVAL;
-	}
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-static void __exit dsbr100_exit(void)
-{
-	usb_dsbr100 *radio=usb_dsbr100_radio.priv;
-
-	if (radio)
-		dsbr100_stop(radio);
-	video_unregister_device(&usb_dsbr100_radio);
-	usb_deregister(&usb_dsbr100_driver);
-}
-
-module_init (dsbr100_init);
-module_exit (dsbr100_exit);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
-/*
-vi: ts=8
-Sigh.  Of course, I am one of the ts=2 heretics, but Linus' wish is
-my command.
-*/
diff -Nru a/drivers/usb/emi26.c b/drivers/usb/emi26.c
--- a/drivers/usb/emi26.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,239 +0,0 @@
-/* 
- * Emagic EMI 2|6 usb audio interface firmware loader.
- * Copyright (C) 2002
- * 	Tapio Laxström (tapio.laxstrom@iptime.fi)
- *
- * This program is free software; 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.
- * 
- * emi26.c,v 1.13 2002/03/08 13:10:26 tapio Exp
- */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#define MAX_INTEL_HEX_RECORD_LENGTH 16
-typedef struct _INTEL_HEX_RECORD
-{
-	__u32	length;
-	__u32	address;
-	__u32	type;
-	__u8	data[MAX_INTEL_HEX_RECORD_LENGTH];
-} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
-
-/* include firmware (variables) */
-#include "emi26_fw.h"
-
-#define EMI26_VENDOR_ID 		0x086a  /* Emagic Soft-und Hardware GmBH */
-#define EMI26_PRODUCT_ID		0x0100	/* EMI 2|6 without firmware */
-
-#define ANCHOR_LOAD_INTERNAL	0xA0	/* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
-#define ANCHOR_LOAD_EXTERNAL	0xA3	/* This command is not implemented in the core. Requires firmware */
-#define ANCHOR_LOAD_FPGA	0xA5	/* This command is not implemented in the core. Requires firmware. Emagic extension */
-#define MAX_INTERNAL_ADDRESS	0x1B3F	/* This is the highest internal RAM address for the AN2131Q */
-#define CPUCS_REG		0x7F92  /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */ 
-#define INTERNAL_RAM(address)   (address <= MAX_INTERNAL_ADDRESS)
-
-static int emi26_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest);
-static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
-static int emi26_load_firmware (struct usb_device *dev);
-static void *emi26_probe(struct usb_device *dev, unsigned int if_num, const struct usb_device_id *id);
-static void emi26_disconnect(struct usb_device *dev, void *drv_context);
-static int __init emi26_init (void);
-static void __exit emi26_exit (void);
-
-
-/* thanks to drivers/usb/serial/keyspan_pda.c code */
-static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
-{
-	int result;
-	unsigned char *buffer =  kmalloc (length, GFP_KERNEL);
-
-	if (!buffer) {
-		printk(KERN_ERR "emi26: kmalloc(%d) failed.", length);
-		return -ENOMEM;
-	}
-	memcpy (buffer, data, length);
-	/* Note: usb_control_msg returns negative value on error or length of the
-	 * 		 data that was written! */
-	result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
-	kfree (buffer);
-	return result;
-}
-
-/* thanks to drivers/usb/serial/keyspan_pda.c code */
-static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit)
-{
-	int response;
-	printk(KERN_INFO "%s - %d", __FUNCTION__, reset_bit);
-	/* printk(KERN_DEBUG "%s - %d", __FUNCTION__, reset_bit); */
-	response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
-	if (response < 0) {
-		printk(KERN_ERR "emi26: set_reset (%d) failed", reset_bit);
-	}
-	return response;
-}
-
-static int emi26_load_firmware (struct usb_device *dev)
-{
-	int err;
-	int i;
-	int pos = 0;	/* Position in hex record */
-	__u32 addr;	/* Address to write */
-	__u8 buf[1023];
-
-	/* Assert reset (stop the CPU in the EMI) */
-	err = emi26_set_reset(dev,1);
-	if (err < 0) {
-		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-		return err;
-	}
-
-	/* 1. We need to put the loader for the FPGA into the EZ-USB */
-	for (i=0; g_Loader[i].type == 0; i++) {
-		err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
-		if (err < 0) {
-			printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-			return err;
-		}
-	}
-
-	/* De-assert reset (let the CPU run) */
-	err = emi26_set_reset(dev,0);
-
-	/* 2. We upload the FPGA firmware into the EMI
-	 * Note: collect up to 1023 (yes!) bytes and send them with
-	 * a single request. This is _much_ faster! */
-	do {
-		i = 0;
-		addr = g_bitstream[pos].address;
-
-		/* intel hex records are terminated with type 0 element */
-		while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < sizeof(buf))) {
-			memcpy(buf + i, g_bitstream[pos].data, g_bitstream[pos].length);
-			i += g_bitstream[pos].length;
-			pos++;
-		}
-		err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
-		if (err < 0) {
-			printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-			return err;
-		}
-	} while (i > 0);
-
-	/* Assert reset (stop the CPU in the EMI) */
-	err = emi26_set_reset(dev,1);
-	if (err < 0) {
-		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-		return err;
-	}
-
-	/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
-	for (i=0; g_Loader[i].type == 0; i++) {
-		err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
-		if (err < 0) {
-			printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-			return err;
-		}
-	}
-
-	/* De-assert reset (let the CPU run) */
-	err = emi26_set_reset(dev,0);
-	if (err < 0) {
-		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-		return err;
-	}
-
-	/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
-	for (i=0; g_Firmware[i].type == 0; i++) {
-		if (!INTERNAL_RAM(g_Firmware[i].address)) {
-			err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL);
-			if (err < 0) {
-				printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-				return err;
-			}
-		}
-	}
-	
-	/* Assert reset (stop the CPU in the EMI) */
-	err = emi26_set_reset(dev,1);
-	if (err < 0) {
-		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-		return err;
-	}
-
-	for (i=0; g_Firmware[i].type == 0; i++) {
-		if (INTERNAL_RAM(g_Firmware[i].address)) {
-			err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL);
-			if (err < 0) {
-				printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-				return err;
-			}
-		}
-	}
-
-	/* De-assert reset (let the CPU run) */
-	err = emi26_set_reset(dev,0);
-	if (err < 0) {
-		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
-		return err;
-	}
-
-	/* return 1 to fail the driver inialization
-	 * and give real driver change to load */
-	return 1;
-}
-
-static __devinitdata struct usb_device_id id_table [] = {
-	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
-	{ }                                             /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, id_table);
-
-static void * emi26_probe(struct usb_device *dev, unsigned int if_num, const struct usb_device_id *id)
-{
-	printk(KERN_INFO "%s start", __FUNCTION__); 
-	
-	if((dev->descriptor.idVendor == EMI26_VENDOR_ID) && (dev->descriptor.idProduct == EMI26_PRODUCT_ID)) {
-		emi26_load_firmware(dev);
-	}
-	
-	/* do not return the driver context, let real audio driver do that */
-	return 0;
-}
-
-static void emi26_disconnect(struct usb_device *dev, void *drv_context)
-{
-}
-
-struct usb_driver emi26_driver = {
-name:			"emi26 - firmware loader",
-probe:			emi26_probe,
-disconnect:		emi26_disconnect,
-id_table:		NULL,
-};
-
-static int __init emi26_init (void)
-{
-	usb_register (&emi26_driver);
-	return 0;
-}
-
-static void __exit emi26_exit (void)
-{
-	usb_deregister (&emi26_driver);
-}
-
-module_init(emi26_init);
-module_exit(emi26_exit);
-
-MODULE_AUTHOR("tapio laxström");
-MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader.");
-MODULE_LICENSE("GPL");
-
-/* vi:ai:syntax=c:sw=8:ts=8:tw=80
- */
diff -Nru a/drivers/usb/emi26_fw.h b/drivers/usb/emi26_fw.h
--- a/drivers/usb/emi26_fw.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,5775 +0,0 @@
-/*
- * This file is generated from three different files, provided by Emagic.
- */
-/* generated Fri Mar 8 15:11:35 EET 2002 */
-
-/*
- * This firmware is for the Emagic EMI 2|6 Audio Interface
- *
- * The firmware contained herein is Copyright (c) 1999-2002 Emagic
- * as an unpublished work. This notice does not imply unrestricted
- * or public access to this firmware which is a trade secret of Emagic,
- * and which may not be reproduced, used, sold or transferred to
- * any third party without Emagic's written consent. All Rights Reserved.
- *
- * This firmware may not be modified and may only be used with the
- * Emagic EMI 2|6 Audio Interface. Distribution and/or Modification of
- * any driver which includes this firmware, in whole or in part,
- * requires the inclusion of this statement.
- */
-INTEL_HEX_RECORD g_bitstream[]={
-{  16, 0x8010, 0, {0xff,0xff,0xff,0xff,0xaa,0x99,0x55,0x66,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x07 } },
-{  16, 0x8020, 0, {0x30,0x01,0x60,0x01,0x00,0x00,0x00,0x0b,0x30,0x01,0x20,0x01,0x00,0x80,0x3f,0x2d } },
-{  16, 0x8030, 0, {0x30,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x09 } },
-{  16, 0x8040, 0, {0x30,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x01 } },
-{  16, 0x8050, 0, {0x30,0x00,0x40,0x00,0x50,0x00,0x3e,0x04,0x08,0x12,0x10,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04 } },
-{  16, 0x8080, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x10,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8090, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x84 } },
-{  16, 0x80b0, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00 } },
-{  16, 0x80e0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8110, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8120, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04 } },
-{  16, 0x8140, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x13,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8150, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8170, 0, {0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8190, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84 } },
-{  16, 0x81a0, 0, {0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf7,0x10,0x01,0x14,0x00,0x25,0x00,0x05 } },
-{  16, 0x81b0, 0, {0x40,0x01,0x50,0x00,0x94,0x00,0x15,0x00,0x07,0x40,0x01,0xd0,0x00,0x94,0x00,0x25 } },
-{  16, 0x81c0, 0, {0x80,0x01,0x60,0x02,0xd8,0x00,0xf6,0x00,0x2f,0x80,0x02,0xe0,0x04,0xd8,0x37,0x44 } },
-{  16, 0x81d0, 0, {0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf2,0x00,0xcc,0x90,0x39,0x20 } },
-{  16, 0x81e0, 0, {0x0d,0x98,0x03,0xd2,0x00,0xe7,0x80,0x37,0x04,0x0e,0xf1,0x83,0x7e,0x00,0xdf,0x90 } },
-{  16, 0x81f0, 0, {0x31,0xe4,0x8f,0x79,0x03,0x7c,0x20,0xdf,0x22,0x33,0xc0,0x0c,0xf0,0x22,0x30,0x00 } },
-{  16, 0x8200, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0x62,0x00,0x80,0x24,0x22,0x20 } },
-{  16, 0x8210, 0, {0x08,0x98,0x12,0xe2,0x00,0x8b,0x81,0x20,0x94,0x08,0x74,0x02,0x2e,0x00,0x8a,0x01 } },
-{  16, 0x8220, 0, {0x22,0xc8,0x08,0x92,0x02,0x3d,0x80,0x8b,0x60,0x22,0x80,0x08,0xb0,0x02,0x20,0x04 } },
-{  16, 0x8230, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc8,0x00,0xa0,0x00,0x20,0x00 } },
-{  16, 0x8240, 0, {0x0b,0x10,0x02,0xc0,0x00,0xa1,0x00,0x24,0x09,0x4a,0x32,0x02,0x48,0x00,0xb1,0x00 } },
-{  16, 0x8250, 0, {0x62,0xc0,0x09,0xa0,0x46,0xcc,0x24,0x93,0x49,0x2a,0x80,0x48,0x30,0x22,0x62,0x01 } },
-{  16, 0x8260, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa8,0x12,0xa8,0x00,0x22,0x00 } },
-{  16, 0x8270, 0, {0x08,0x90,0x02,0xe0,0x00,0x89,0x80,0x22,0x44,0x08,0xb0,0x12,0xa8,0x00,0xa9,0x40 } },
-{  16, 0x8280, 0, {0x22,0xc0,0x08,0x90,0x82,0xac,0x00,0x9b,0x04,0x2a,0xc4,0x08,0xb0,0x02,0x70,0x04 } },
-{  16, 0x8290, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x84,0x00,0xe9,0x80,0xb2,0x64 } },
-{  16, 0x82a0, 0, {0x4d,0xa0,0x03,0xea,0x20,0xe9,0xc0,0x36,0x40,0x0e,0xb0,0x03,0x44,0x00,0xfb,0x90 } },
-{  16, 0x82b0, 0, {0xb2,0x88,0x0d,0xbc,0x03,0xec,0x08,0x5b,0x00,0x38,0x60,0x2c,0xb0,0x63,0x40,0x04 } },
-{  16, 0x82c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x26,0xdd,0x90,0x37,0x40 } },
-{  16, 0x82d0, 0, {0x4f,0xe0,0x13,0xf2,0x80,0xfd,0x00,0x3d,0xa0,0x0d,0x70,0x03,0x75,0x00,0x5e,0x00 } },
-{  16, 0x82e0, 0, {0x3f,0xa4,0x0d,0xf9,0x03,0x5c,0x10,0xeb,0x00,0x37,0x20,0x0f,0x30,0x03,0xb8,0x00 } },
-{  16, 0x82f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xe9,0x80,0x32,0x40 } },
-{  16, 0x8300, 0, {0x0c,0xa1,0x83,0xe8,0x00,0xe9,0x00,0x32,0x42,0x0e,0xb0,0x03,0xac,0x48,0xe9,0x00 } },
-{  16, 0x8310, 0, {0x3a,0x80,0x0e,0xa4,0x03,0xec,0x00,0xeb,0x00,0xb2,0x03,0x0e,0xb0,0x0b,0x10,0x04 } },
-{  16, 0x8320, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2e,0x80,0x89,0xd1,0x20,0x40 } },
-{  16, 0x8330, 0, {0x08,0xa0,0x02,0xc0,0x00,0x81,0x80,0x22,0x58,0x08,0xf5,0x02,0x2f,0x40,0x8b,0x00 } },
-{  16, 0x8340, 0, {0x20,0xc0,0x08,0x30,0x43,0x7c,0x00,0x87,0x00,0x22,0x40,0x08,0xf0,0x02,0x32,0x00 } },
-{  16, 0x8350, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x42,0x01,0x9a,0x44,0x28,0xa2 } },
-{  16, 0x8360, 0, {0x08,0x18,0x02,0xc0,0x80,0xa1,0x80,0xa0,0x00,0x08,0x30,0x02,0x8e,0x00,0xab,0x00 } },
-{  16, 0x8370, 0, {0x2c,0x40,0x0a,0x30,0x02,0x0c,0x00,0xa3,0x00,0x20,0x44,0x0a,0x30,0x02,0x38,0x00 } },
-{  16, 0x8380, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x32,0x00,0x96,0x82,0x2b,0xa2 } },
-{  16, 0x8390, 0, {0x88,0x5a,0x02,0xf2,0x00,0x05,0x80,0x29,0xa0,0x08,0x78,0x42,0xbe,0x00,0x8e,0x84 } },
-{  16, 0x83a0, 0, {0x2f,0x61,0x0a,0xd8,0x02,0x4e,0x10,0xa7,0x80,0x20,0x28,0x08,0x78,0x02,0x18,0x00 } },
-{  16, 0x83b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x00,0xf2,0x24,0x38,0x80 } },
-{  16, 0x83c0, 0, {0x2c,0x1a,0x03,0xc4,0x00,0xe0,0x58,0xa0,0x80,0x2e,0x30,0x03,0x88,0x41,0xe3,0x02 } },
-{  16, 0x83d0, 0, {0x3c,0x40,0x06,0x20,0x03,0x8c,0x00,0xe3,0x00,0x10,0x00,0x0e,0x31,0x43,0x12,0x02 } },
-{  16, 0x83e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x98,0x00,0xee,0x01,0x37,0x84 } },
-{  16, 0x83f0, 0, {0x9f,0xd9,0x03,0xf0,0x48,0xfd,0x10,0x37,0xc0,0x07,0xb0,0x03,0x5c,0x00,0xf6,0x10 } },
-{  16, 0x8400, 0, {0x33,0xc0,0x0d,0xe1,0x03,0xed,0x20,0xdf,0x10,0x3f,0x48,0x0f,0xf0,0x23,0xd0,0x06 } },
-{  16, 0x8410, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x02,0xcb,0x80,0x30,0xc0 } },
-{  16, 0x8420, 0, {0x0c,0xa0,0x03,0xe2,0x02,0xc9,0x00,0x3a,0x40,0x0d,0xb6,0x03,0x64,0x00,0xeb,0x00 } },
-{  16, 0x8430, 0, {0x3e,0xc0,0x0f,0xb0,0x03,0xed,0x00,0xfb,0x01,0x3e,0xe0,0x0c,0xb0,0x02,0xea,0x00 } },
-{  16, 0x8440, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x00,0x87,0x00,0x21,0xc0 } },
-{  16, 0x8450, 0, {0x28,0x60,0x02,0xd0,0x00,0x85,0x00,0x2d,0x80,0x48,0xf0,0x82,0x1c,0x00,0xb7,0x00 } },
-{  16, 0x8460, 0, {0x2d,0x00,0x0b,0x50,0x02,0xdc,0x00,0xb7,0xa0,0x2f,0x80,0x28,0x7a,0x02,0xd2,0x04 } },
-{  16, 0x8470, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x00,0xbe,0x00,0x87,0x80,0x21,0xe0 } },
-{  16, 0x8480, 0, {0x28,0x68,0x02,0xd7,0x00,0x84,0x80,0x2d,0xe0,0x49,0x79,0x06,0x53,0x09,0xb5,0x80 } },
-{  16, 0x8490, 0, {0x2d,0xe2,0x0b,0x78,0x02,0xde,0x80,0xb7,0x90,0x2d,0xb0,0x08,0x79,0x02,0xf0,0x00 } },
-{  16, 0x84a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x10,0x83,0x01,0x28,0xc8 } },
-{  16, 0x84b0, 0, {0x08,0x20,0x02,0xc2,0x06,0x81,0x00,0x2c,0xc8,0x88,0x30,0x62,0x0e,0x21,0xb3,0xa0 } },
-{  16, 0x84c0, 0, {0x2c,0xc1,0x0b,0xb6,0x02,0xcc,0x00,0xb3,0x00,0x2c,0xe0,0x08,0x30,0x02,0xd2,0x04 } },
-{  16, 0x84d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xca,0x40,0xb0,0x80 } },
-{  16, 0x84e0, 0, {0x0c,0x2c,0x02,0xf8,0x00,0xc6,0x20,0x3f,0x90,0x0d,0xa0,0x03,0x7b,0x01,0xee,0xe0 } },
-{  16, 0x84f0, 0, {0x3f,0xb4,0x0f,0xec,0x03,0xe8,0x00,0xfa,0x00,0x3f,0xa0,0x0c,0xa0,0x03,0xfa,0x04 } },
-{  16, 0x8500, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe3,0x00,0xf8,0x09,0x26,0x00 } },
-{  16, 0x8510, 0, {0x0f,0xc1,0x83,0xe0,0x10,0xf8,0x40,0x3c,0x00,0x0f,0x80,0x03,0xe0,0x01,0xf8,0x00 } },
-{  16, 0x8520, 0, {0x3e,0x00,0x0f,0x81,0x03,0xe0,0x04,0xf8,0x00,0x3e,0x10,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0x8530, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x02,0xc9,0x00,0x3e,0x40 } },
-{  16, 0x8540, 0, {0x4f,0x90,0x63,0x26,0x84,0x39,0x02,0xb2,0x40,0x0c,0x91,0x03,0x24,0x00,0xf9,0x00 } },
-{  16, 0x8550, 0, {0x3e,0x40,0x0f,0x90,0x03,0x24,0x00,0xf1,0x00,0x3a,0x44,0x0f,0x90,0x03,0xc2,0x04 } },
-{  16, 0x8560, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x45,0x00,0x89,0x40,0x2e,0x40 } },
-{  16, 0x8570, 0, {0x08,0x92,0x0a,0x24,0x00,0xb9,0x31,0x22,0x60,0x88,0x94,0x8a,0x24,0x20,0xb9,0x00 } },
-{  16, 0x8580, 0, {0x2e,0x40,0x0b,0x90,0x02,0x24,0x00,0xb9,0x00,0x22,0x68,0x0b,0x90,0x02,0xe0,0x00 } },
-{  16, 0x8590, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0xa0,0x8d,0x84,0x2f,0x40 } },
-{  16, 0x85a0, 0, {0x0b,0xd1,0x02,0x24,0x00,0xb9,0x00,0x22,0x4a,0x08,0x10,0x02,0x2c,0x40,0xb9,0x00 } },
-{  16, 0x85b0, 0, {0x2e,0x40,0x0b,0x90,0x02,0x24,0x00,0xb9,0x00,0x2a,0x40,0x0b,0x90,0x02,0xc6,0x00 } },
-{  16, 0x85c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x14,0x00,0x85,0x80,0x2d,0x40 } },
-{  16, 0x85d0, 0, {0x08,0x50,0x02,0x04,0x0c,0xb9,0x00,0xa0,0x50,0x08,0x14,0x22,0x04,0x00,0xb1,0x00 } },
-{  16, 0x85e0, 0, {0x2c,0x40,0x0b,0x10,0x02,0x04,0x00,0xb1,0x28,0x20,0x4a,0x0b,0x13,0x02,0xc2,0x01 } },
-{  16, 0x85f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xc0,0x50,0x3e,0x80 } },
-{  16, 0x8600, 0, {0x0f,0xc0,0x43,0x20,0x00,0xf8,0x00,0x30,0x00,0x2c,0x80,0x23,0x20,0x00,0xf8,0x51 } },
-{  16, 0x8610, 0, {0x3e,0x14,0x8f,0x85,0x0b,0x21,0x40,0xf8,0x70,0x3a,0x08,0x0f,0x84,0x83,0xee,0x03 } },
-{  16, 0x8620, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xc4,0x00,0xf9,0x04,0x3e,0x40 } },
-{  16, 0x8630, 0, {0x0f,0x90,0x23,0xd4,0x00,0xfd,0x00,0x3f,0x50,0x0f,0x94,0x03,0xf4,0x04,0xfd,0x00 } },
-{  16, 0x8640, 0, {0x3f,0x41,0x8f,0xd0,0x43,0xe5,0x0c,0xf9,0x02,0x3f,0x4a,0x0f,0x92,0x03,0xe6,0x02 } },
-{  16, 0x8650, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xd4,0x01,0xfd,0x00,0x3d,0x40 } },
-{  16, 0x8660, 0, {0x0c,0xd0,0x13,0xf4,0x00,0xd5,0x00,0x33,0x6a,0x1c,0xdc,0x83,0x34,0x00,0xd1,0x04 } },
-{  16, 0x8670, 0, {0x3e,0x50,0x0c,0x91,0x03,0xe6,0xc0,0xdd,0xb0,0x33,0x6a,0x2c,0x9c,0x83,0xe6,0x00 } },
-{  16, 0x8680, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x09,0xf8,0x80,0x2e,0x00 } },
-{  16, 0x8690, 0, {0x88,0x80,0x00,0xe8,0x00,0xba,0x00,0x22,0xb0,0x08,0x8e,0x02,0x28,0x00,0x88,0xa8 } },
-{  16, 0x86a0, 0, {0x26,0x28,0x08,0x8a,0x22,0xe2,0x00,0x88,0xe4,0x22,0x30,0x08,0x8c,0x02,0xce,0x04 } },
-{  16, 0x86b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x28,0x2e,0x40 } },
-{  16, 0x86c0, 0, {0x08,0x10,0x02,0xc4,0x00,0x99,0x00,0x20,0x42,0x48,0x10,0x02,0x64,0x01,0x91,0x80 } },
-{  16, 0x86d0, 0, {0x2c,0x48,0x08,0x10,0x02,0xc4,0xc0,0x81,0x40,0x20,0x4a,0x08,0x12,0x02,0xc2,0x01 } },
-{  16, 0x86e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x94,0xa9,0x02,0x2e,0x40 } },
-{  16, 0x86f0, 0, {0x0a,0x90,0x02,0x64,0x00,0xb9,0x00,0x82,0x60,0x08,0x90,0x02,0x66,0x00,0x89,0x10 } },
-{  16, 0x8700, 0, {0x24,0x62,0x08,0x90,0x02,0xe4,0x00,0x89,0x02,0x22,0x40,0x18,0x90,0x02,0xc6,0x04 } },
-{  16, 0x8710, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe6,0x00,0xb9,0x04,0x3e,0x40 } },
-{  16, 0x8720, 0, {0x0c,0x90,0x13,0xe4,0x00,0xd1,0xc0,0x12,0x50,0x28,0x90,0x03,0x44,0x00,0xd9,0x00 } },
-{  16, 0x8730, 0, {0x3e,0x40,0x28,0x92,0x03,0xe4,0x02,0xd9,0x00,0x32,0x42,0x8c,0x90,0x12,0xe8,0x04 } },
-{  16, 0x8740, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa6,0x20,0xf9,0x00,0x3e,0x41 } },
-{  16, 0x8750, 0, {0x2d,0x90,0x03,0xe4,0x00,0xf9,0x20,0x3e,0x40,0x4f,0x90,0x01,0xa4,0x00,0xf9,0x00 } },
-{  16, 0x8760, 0, {0x36,0x40,0x8f,0x92,0x07,0xe4,0x00,0xf1,0x00,0xbe,0x40,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0x8770, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xc8,0x00,0x3e,0x20 } },
-{  16, 0x8780, 0, {0x0c,0x80,0x03,0xe0,0x40,0xf8,0x00,0x36,0x12,0x2c,0x00,0x03,0xe0,0xc0,0xf8,0x00 } },
-{  16, 0x8790, 0, {0x32,0x10,0x0d,0x84,0x03,0xa0,0x00,0xf8,0x02,0x3e,0x08,0x0f,0x80,0x00,0xca,0x04 } },
-{  16, 0x87a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x3a,0x90,0x8e,0x00,0x2d,0xa0 } },
-{  16, 0x87b0, 0, {0x80,0xe8,0x02,0xfa,0x00,0xbe,0x40,0x23,0x80,0x08,0xe8,0x02,0xfa,0x00,0x8a,0x00 } },
-{  16, 0x87c0, 0, {0x36,0x80,0x08,0xa0,0x02,0xe8,0x00,0xba,0x00,0x2f,0x80,0x0b,0xa0,0x03,0x8a,0x00 } },
-{  16, 0x87d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x46,0x02,0x83,0x00,0x2c,0x80 } },
-{  16, 0x87e0, 0, {0x08,0x22,0x42,0xc6,0x80,0xb1,0x60,0x2e,0xf4,0x08,0x38,0x22,0xce,0x00,0xa3,0x00 } },
-{  16, 0x87f0, 0, {0x20,0xc0,0x08,0x30,0x02,0xac,0x00,0xb1,0x00,0x2e,0x40,0x0b,0x30,0x02,0xca,0x00 } },
-{  16, 0x8800, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x02,0x85,0x01,0x2d,0xc2 } },
-{  16, 0x8810, 0, {0xa8,0x44,0x02,0xd4,0x00,0xbd,0x01,0x29,0x40,0x18,0x68,0xd2,0xdc,0x00,0x8f,0x80 } },
-{  16, 0x8820, 0, {0x25,0xcc,0x28,0x73,0x42,0xdc,0x80,0xb5,0x30,0x2d,0xc0,0x1b,0x72,0x02,0xe8,0x00 } },
-{  16, 0x8830, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x04,0xc6,0x82,0x3d,0xe0 } },
-{  16, 0x8840, 0, {0x0c,0x48,0x12,0xd6,0x10,0xf5,0x80,0x3c,0xa0,0x0c,0x70,0x03,0xde,0x00,0xe7,0x90 } },
-{  16, 0x8850, 0, {0x23,0xea,0x04,0x7a,0x03,0x9e,0x00,0xf5,0x80,0x3d,0xe0,0x0f,0x7a,0x03,0xea,0x02 } },
-{  16, 0x8860, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0d,0xac,0x00,0x9c,0x00,0x3e,0xc0 } },
-{  16, 0x8870, 0, {0x0f,0x80,0x03,0xe4,0x10,0xf9,0x00,0x36,0x01,0x0f,0xa0,0x03,0xc0,0x00,0xeb,0x00 } },
-{  16, 0x8880, 0, {0x3e,0xd8,0x4e,0xb0,0x83,0xec,0x00,0xf9,0x00,0x3e,0xc0,0x0f,0xb4,0x43,0x82,0x06 } },
-{  16, 0x8890, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xde,0x00,0xcf,0x84,0x31,0xe0 } },
-{  16, 0x88a0, 0, {0x0e,0xc8,0x43,0xd6,0x00,0xcd,0x80,0x33,0xe0,0xcd,0xd9,0x03,0x3a,0x00,0xff,0x88 } },
-{  16, 0x88b0, 0, {0x33,0xe0,0x0f,0xf9,0x13,0xfe,0x24,0xfd,0x80,0x3f,0x20,0x0c,0xf6,0x83,0x10,0x00 } },
-{  16, 0x88c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0x85,0x00,0x21,0xc4 } },
-{  16, 0x88d0, 0, {0x28,0x40,0x82,0xd0,0x00,0xd5,0x00,0x23,0x80,0x48,0xc9,0x02,0x1c,0x00,0xb7,0x00 } },
-{  16, 0x88e0, 0, {0x21,0xc0,0x0b,0x71,0x02,0xde,0x80,0xb5,0x10,0x2d,0xc0,0x28,0xf0,0x02,0x2a,0x04 } },
-{  16, 0x88f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x9c,0x00,0x96,0x00,0x21,0xc0 } },
-{  16, 0x8900, 0, {0x0a,0x41,0x02,0xf5,0x40,0x8d,0x00,0x21,0x40,0x09,0x52,0x02,0x98,0x20,0xb7,0x00 } },
-{  16, 0x8910, 0, {0x21,0xc0,0x0b,0x70,0x06,0xdc,0x80,0xb5,0x00,0x2d,0xc0,0x08,0x70,0x02,0x04,0x00 } },
-{  16, 0x8920, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xcc,0x10,0x98,0x00,0x00,0xc0 } },
-{  16, 0x8930, 0, {0x88,0x04,0x82,0xc0,0x00,0x91,0x04,0x20,0x03,0x09,0x00,0x02,0x8a,0x00,0xb3,0x0a } },
-{  16, 0x8940, 0, {0x20,0xc4,0x8b,0x34,0x02,0xcc,0x00,0xb9,0x00,0x2c,0xc0,0x00,0x30,0x02,0x18,0x04 } },
-{  16, 0x8950, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x15,0xac,0x00,0xdb,0x00,0xb0,0xc0 } },
-{  16, 0x8960, 0, {0x0e,0x9c,0x02,0xc5,0x00,0xc1,0x10,0xb2,0xc0,0x0d,0xb0,0x0b,0xa7,0x08,0xff,0x00 } },
-{  16, 0x8970, 0, {0xb3,0xc0,0x0f,0xfa,0x03,0xfc,0x00,0xfd,0x00,0x3e,0xd4,0x0c,0xf0,0x0b,0x2e,0x04 } },
-{  16, 0x8980, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x04,0xed,0x00,0x3e,0x40 } },
-{  16, 0x8990, 0, {0x0f,0x84,0x03,0xe5,0x40,0xf9,0x40,0x3e,0x60,0xce,0xb4,0x43,0x64,0x00,0xfb,0x80 } },
-{  16, 0x89a0, 0, {0x3e,0xc2,0x0f,0xb0,0x13,0xec,0x00,0xf9,0x02,0x3e,0xc0,0x4f,0xb0,0x03,0xe1,0x00 } },
-{  16, 0x89b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x10,0xff,0x00,0xce,0x00,0x33,0xc0 } },
-{  16, 0x89c0, 0, {0x0e,0xc0,0x07,0x74,0x04,0xec,0x00,0x11,0x80,0x0c,0xca,0x03,0xfe,0x60,0xff,0x00 } },
-{  16, 0x89d0, 0, {0x3f,0xc0,0x0f,0xf0,0x83,0x3c,0x00,0xdd,0x00,0xb3,0x50,0x2c,0xf0,0x03,0x20,0x04 } },
-{  16, 0x89e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x4c,0x04,0x8b,0x0b,0x22,0x70 } },
-{  16, 0x89f0, 0, {0x08,0x08,0x03,0x67,0x20,0x8a,0x88,0xa2,0x00,0x28,0x84,0x02,0xe7,0x00,0xbb,0x00 } },
-{  16, 0x8a00, 0, {0x3e,0xc0,0x0b,0xb0,0x02,0x2c,0x00,0xb9,0x00,0x22,0x61,0x08,0xb0,0x03,0x60,0x40 } },
-{  16, 0x8a10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x20,0x22,0xe2 } },
-{  16, 0x8a20, 0, {0x0a,0x8c,0x02,0x26,0x00,0xa9,0x80,0x2a,0xc0,0x08,0xb4,0x42,0xed,0x00,0xbb,0x00 } },
-{  16, 0x8a30, 0, {0x2e,0xc0,0x0b,0x30,0x02,0x2c,0x00,0xb9,0x00,0x20,0x80,0x08,0x30,0x02,0x60,0x00 } },
-{  16, 0x8a40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0e,0x01,0x81,0x00,0xa0,0xc0 } },
-{  16, 0x8a50, 0, {0x08,0x81,0x02,0x44,0x00,0x81,0x00,0x28,0x81,0x08,0x32,0x02,0xcc,0x00,0xb3,0x00 } },
-{  16, 0x8a60, 0, {0x28,0xc0,0x0b,0x30,0x02,0x0c,0x80,0xb1,0x00,0x20,0xc0,0x08,0x30,0x12,0x42,0x01 } },
-{  16, 0x8a70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0d,0x6c,0x00,0xc2,0x01,0x32,0xc0 } },
-{  16, 0x8a80, 0, {0x2e,0x80,0x16,0x2c,0x08,0xe9,0x00,0x3a,0x40,0x0c,0x80,0x03,0xec,0x00,0xf7,0x00 } },
-{  16, 0x8a90, 0, {0x2f,0xc0,0x0f,0xf0,0x0b,0x2c,0x00,0xd9,0x00,0x30,0x40,0x0c,0xf0,0x03,0x60,0x03 } },
-{  16, 0x8aa0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x0d,0xf8,0x08,0xff,0x00,0x3f,0xc0 } },
-{  16, 0x8ab0, 0, {0x0f,0xc2,0x17,0xfc,0x00,0xf7,0x00,0x37,0x00,0x0f,0x84,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0x8ac0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xed,0x00,0xfd,0x00,0x3f,0x40,0x0f,0xf0,0x03,0xe8,0x06 } },
-{  16, 0x8ad0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xcf,0x30,0x17,0x48 } },
-{  16, 0x8ae0, 0, {0x0c,0x59,0x03,0xb9,0x00,0xdf,0x28,0x35,0x24,0x0d,0x82,0xa3,0x7c,0x80,0xff,0x00 } },
-{  16, 0x8af0, 0, {0x3f,0xc8,0x0f,0xf2,0x03,0xe4,0xa0,0xef,0x80,0x3f,0xe1,0x8c,0xd8,0x43,0x30,0x00 } },
-{  16, 0x8b00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xed,0x48,0x89,0x34,0xa3,0x70 } },
-{  16, 0x8b10, 0, {0x28,0xb0,0x23,0x60,0x00,0x8b,0xc0,0x22,0x40,0x08,0xb4,0x82,0x2f,0x40,0xbf,0xd1 } },
-{  16, 0x8b20, 0, {0x6f,0xf4,0x8e,0xbd,0x02,0xe7,0x00,0xbb,0x80,0x3a,0xe0,0x08,0x98,0x0a,0x28,0x04 } },
-{  16, 0x8b30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0xb0,0x91,0x00,0xa8,0x50 } },
-{  16, 0x8b40, 0, {0x08,0xb2,0x02,0xc8,0x84,0x93,0x00,0x24,0x49,0x0b,0x02,0x02,0x4c,0x00,0xb3,0x04 } },
-{  16, 0x8b50, 0, {0x2c,0xc0,0x0b,0x30,0x42,0x84,0x00,0xb3,0x00,0x2e,0x00,0x0a,0xb0,0x12,0x22,0x01 } },
-{  16, 0x8b60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xac,0x02,0x99,0x18,0x2a,0x44 } },
-{  16, 0x8b70, 0, {0x08,0xb8,0x82,0xa2,0x01,0xbb,0x00,0x28,0x60,0x0a,0xa0,0x12,0x6c,0x00,0xbb,0x00 } },
-{  16, 0x8b80, 0, {0x6e,0xc0,0x0a,0xb0,0x02,0xe4,0x00,0xbb,0x00,0x2a,0x00,0x2a,0xb0,0x02,0x38,0x04 } },
-{  16, 0x8b90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0xe4,0x08,0xda,0xc0,0x3a,0x60 } },
-{  16, 0x8ba0, 0, {0x0c,0x18,0x0a,0xeb,0x04,0xdb,0x00,0x36,0xe0,0x07,0x85,0x83,0x6c,0x00,0xfb,0x00 } },
-{  16, 0x8bb0, 0, {0x2e,0xc0,0x0f,0xb0,0x43,0xe4,0x00,0xeb,0x00,0x3e,0x88,0x0e,0x18,0x03,0x10,0x04 } },
-{  16, 0x8bc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x41,0x9c,0x10,0xe9,0x00,0x37,0x60 } },
-{  16, 0x8bd0, 0, {0x87,0xf0,0x17,0x70,0x00,0xcf,0x01,0x37,0xc0,0x4c,0x98,0x03,0xbc,0x00,0xfb,0x00 } },
-{  16, 0x8be0, 0, {0x3f,0xc2,0x0f,0xf0,0x03,0xe4,0x00,0xff,0x40,0x3f,0xe4,0x0d,0xd9,0x03,0xf0,0x00 } },
-{  16, 0x8bf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa4,0x00,0xf4,0x00,0x30,0x40 } },
-{  16, 0x8c00, 0, {0x0f,0xb4,0x03,0x99,0x00,0xfb,0x00,0x3e,0xc0,0x0d,0x04,0x23,0x2c,0x08,0xfb,0x88 } },
-{  16, 0x8c10, 0, {0x32,0xc0,0x0f,0xb0,0x03,0xe6,0x00,0xdb,0x10,0x3e,0x02,0x0f,0xb0,0x83,0xd0,0x04 } },
-{  16, 0x8c20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xb9,0x50,0xa2,0x48 } },
-{  16, 0x8c30, 0, {0x8b,0xb0,0x03,0x20,0x00,0xd7,0x80,0x2e,0xd8,0x00,0x80,0x02,0x3c,0x00,0xbf,0x80 } },
-{  16, 0x8c40, 0, {0x23,0xe8,0x8b,0xf0,0x02,0xf4,0x40,0x8b,0x40,0x0c,0x42,0x03,0xb6,0x02,0xf2,0x00 } },
-{  16, 0x8c50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb2,0x44,0x00,0xc8 } },
-{  16, 0x8c60, 0, {0x0b,0x30,0x12,0x8c,0x00,0xa3,0x80,0x24,0xc8,0x0b,0x00,0x0a,0xcc,0x00,0xb3,0x44 } },
-{  16, 0x8c70, 0, {0x04,0xc0,0x1b,0x36,0x02,0xc5,0x01,0x83,0x0c,0x2c,0xa0,0x0b,0x30,0x02,0xf8,0x00 } },
-{  16, 0x8c80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x08,0xb7,0x90,0x21,0x64 } },
-{  16, 0x8c90, 0, {0x0b,0xf8,0x02,0x4a,0x04,0x97,0x81,0x2f,0xe4,0x0a,0x78,0x02,0x9e,0x00,0xb7,0x80 } },
-{  16, 0x8ca0, 0, {0x21,0xe0,0x8b,0x78,0x82,0xd6,0x86,0x87,0x84,0x2d,0xa0,0x0b,0x78,0x02,0xc0,0x00 } },
-{  16, 0x8cb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x04,0x00,0xf2,0x00,0x30,0xc0 } },
-{  16, 0x8cc0, 0, {0x0f,0x30,0x03,0x8c,0x00,0xe3,0x0a,0x3c,0xc0,0x0f,0x18,0x03,0x8c,0x00,0xf3,0x02 } },
-{  16, 0x8cd0, 0, {0x30,0xc0,0x1f,0x30,0x01,0xc6,0x80,0xc3,0x00,0x3c,0xc0,0x0f,0x12,0x03,0xda,0x02 } },
-{  16, 0x8ce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x0d,0xbc,0x00,0xff,0x00,0x3f,0x41 } },
-{  16, 0x8cf0, 0, {0x0f,0xf0,0x03,0xb8,0x08,0xff,0x08,0x3f,0xc0,0x0d,0xf0,0x03,0x3c,0x20,0xff,0x08 } },
-{  16, 0x8d00, 0, {0x3b,0xd2,0x0f,0xf0,0x03,0xf4,0x40,0xef,0x00,0x3f,0xc4,0x0f,0xd0,0x03,0xd0,0x06 } },
-{  16, 0x8d10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x00,0xfe,0x00,0x32,0xc2 } },
-{  16, 0x8d20, 0, {0x0c,0x30,0x0b,0x26,0x00,0xfb,0x80,0x36,0xc0,0x0d,0xa0,0x03,0xec,0x00,0xfb,0xe0 } },
-{  16, 0x8d30, 0, {0x32,0xd0,0x0f,0xb8,0x43,0x64,0x44,0xdb,0x04,0x3e,0x80,0x0f,0xb0,0x03,0xe2,0x00 } },
-{  16, 0x8d40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb7,0x00,0xa1,0xc0 } },
-{  16, 0x8d50, 0, {0x88,0x70,0x03,0x10,0x00,0xb7,0x20,0x21,0xc0,0x08,0x70,0x02,0xdc,0x80,0xb3,0x30 } },
-{  16, 0x8d60, 0, {0x31,0xc8,0x0b,0x74,0x02,0x14,0x00,0x87,0x40,0x2d,0xc0,0x4b,0x70,0x02,0xd2,0x00 } },
-{  16, 0x8d70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x96,0x20,0xb6,0x80,0x20,0xe0 } },
-{  16, 0x8d80, 0, {0x28,0xf8,0x02,0x94,0x10,0xb7,0x81,0x27,0xe2,0x09,0x78,0x02,0xde,0x00,0xb7,0xa0 } },
-{  16, 0x8d90, 0, {0xa9,0xe8,0x0b,0x38,0x02,0x76,0x00,0x87,0x80,0x2d,0xa0,0x0b,0x58,0x02,0xf0,0x00 } },
-{  16, 0x8da0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xce,0x10,0xb3,0x00,0x20,0xc4 } },
-{  16, 0x8db0, 0, {0x08,0x20,0x02,0x80,0x10,0xb3,0x00,0x22,0xc8,0x08,0xb0,0x02,0xcc,0x11,0xb3,0x02 } },
-{  16, 0x8dc0, 0, {0x28,0xc0,0x0b,0x30,0x02,0x04,0x00,0x93,0x80,0x2c,0xd2,0x0b,0x10,0x02,0xd2,0x04 } },
-{  16, 0x8dd0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfe,0x40,0x32,0xa0 } },
-{  16, 0x8de0, 0, {0x0c,0xe4,0x03,0x98,0x80,0xfa,0x00,0x37,0xa0,0x0d,0xe0,0x83,0xe8,0x00,0xfe,0x00 } },
-{  16, 0x8df0, 0, {0x3a,0x80,0x0b,0xa0,0x03,0x68,0x00,0xd8,0xa0,0x3f,0x90,0x0f,0xa0,0x03,0xfa,0x04 } },
-{  16, 0x8e00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x08,0xf8,0x08,0x3e,0x00 } },
-{  16, 0x8e10, 0, {0x0f,0x80,0x03,0x20,0x00,0xf8,0x40,0x3e,0x00,0x0f,0x80,0x03,0xe0,0x00,0xf8,0x04 } },
-{  16, 0x8e20, 0, {0x30,0x10,0x0f,0x80,0x03,0xe0,0x02,0xe8,0x00,0x3e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0x8e30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf1,0x00,0x32,0x40 } },
-{  16, 0x8e40, 0, {0x0e,0x90,0x83,0xa4,0x00,0xc9,0x80,0x3e,0x40,0x0e,0x90,0x03,0xa4,0x00,0xf9,0x00 } },
-{  16, 0x8e50, 0, {0x3e,0x40,0x0c,0x90,0x03,0xe4,0x00,0xc8,0x00,0x3e,0x40,0x8f,0x90,0x03,0x02,0x04 } },
-{  16, 0x8e60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x40,0xa0,0x62 } },
-{  16, 0x8e70, 0, {0x08,0x10,0x02,0x24,0x10,0x89,0x00,0x2e,0x40,0x08,0x90,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0x8e80, 0, {0x2e,0x52,0x08,0x94,0x02,0xc4,0x00,0x89,0x40,0x2e,0x40,0x0b,0x10,0x03,0x60,0x10 } },
-{  16, 0x8e90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x18,0x22,0x44 } },
-{  16, 0x8ea0, 0, {0x0a,0x90,0x02,0xac,0x00,0x89,0x10,0x2e,0xc0,0x0a,0x90,0x02,0xa4,0x00,0xb9,0x80 } },
-{  16, 0x8eb0, 0, {0x2e,0x60,0x08,0x98,0x02,0xe6,0x02,0x89,0x08,0x2e,0x40,0x0b,0x90,0x02,0x06,0x00 } },
-{  16, 0x8ec0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0xb1,0x20,0xa0,0x48 } },
-{  16, 0x8ed0, 0, {0x08,0x90,0x02,0x24,0x08,0x81,0x23,0x2c,0x50,0x08,0x10,0x02,0x04,0x80,0xb1,0x20 } },
-{  16, 0x8ee0, 0, {0x2c,0x48,0x28,0x12,0x02,0xe4,0x80,0x81,0x20,0x2c,0x40,0x0b,0x98,0x02,0x42,0x05 } },
-{  16, 0x8ef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x50,0x32,0x00 } },
-{  16, 0x8f00, 0, {0x0e,0x85,0x03,0xa1,0xe0,0xca,0x00,0x3e,0x00,0x0e,0x85,0x03,0xa0,0x00,0xf8,0x00 } },
-{  16, 0x8f10, 0, {0x2e,0x00,0x9c,0xa0,0x03,0xe0,0x00,0xc8,0x28,0x3e,0x00,0x0f,0x80,0x03,0x2e,0x01 } },
-{  16, 0x8f20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xf5,0x10,0x3f,0x44 } },
-{  16, 0x8f30, 0, {0x0f,0xd0,0x03,0xf4,0x00,0xf1,0x10,0x3d,0x40,0x8f,0xd4,0x03,0xe4,0x50,0xf9,0x10 } },
-{  16, 0x8f40, 0, {0x3e,0x45,0x0f,0x91,0x03,0xd4,0x40,0xfc,0x00,0x3f,0xc0,0x8f,0xd0,0x23,0xe6,0x04 } },
-{  16, 0x8f50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0x20,0xcd,0xa8,0x33,0x40 } },
-{  16, 0x8f60, 0, {0x8d,0xd0,0x03,0x26,0x80,0xcd,0x00,0x3d,0x50,0x0c,0x9a,0x03,0x64,0x00,0xf9,0xa0 } },
-{  16, 0x8f70, 0, {0x7a,0x6a,0x0f,0x9a,0x63,0xe6,0x80,0xc9,0x80,0x3e,0x40,0x0f,0x90,0x03,0x06,0x00 } },
-{  16, 0x8f80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x00,0x88,0xe0,0x36,0x00 } },
-{  16, 0x8f90, 0, {0x08,0x80,0x0a,0x21,0x42,0xc8,0x00,0x2e,0x29,0x0c,0xa4,0x42,0x20,0x00,0xb8,0x40 } },
-{  16, 0x8fa0, 0, {0x2e,0x00,0x0b,0x81,0x02,0xe1,0x00,0x88,0x02,0x3a,0x01,0x0b,0xc0,0x02,0x0e,0x04 } },
-{  16, 0x8fb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x02,0x81,0x08,0x24,0x40 } },
-{  16, 0x8fc0, 0, {0x09,0x10,0x02,0x04,0x00,0x91,0x00,0x2c,0x40,0x4b,0x14,0x02,0x44,0x00,0xb5,0x10 } },
-{  16, 0x8fd0, 0, {0x29,0x40,0x0b,0x50,0x02,0xf5,0x00,0xb5,0x00,0x2d,0x40,0x0b,0xd0,0x02,0x02,0x01 } },
-{  16, 0x8fe0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa6,0x01,0x89,0x00,0x26,0x40 } },
-{  16, 0x8ff0, 0, {0x08,0x94,0x02,0x24,0x01,0x89,0x00,0x2e,0x40,0x1a,0x90,0x02,0x6c,0x00,0xbf,0x02 } },
-{  16, 0x9000, 0, {0x2f,0x40,0x0b,0xd0,0x02,0xf4,0x02,0xbd,0x80,0x2b,0x40,0x8b,0xd8,0x3a,0x06,0x04 } },
-{  16, 0x9010, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xc9,0x05,0x36,0x41 } },
-{  16, 0x9020, 0, {0x0d,0x1c,0x03,0x24,0x00,0xd9,0x00,0x3e,0x42,0x2f,0x94,0x03,0x64,0x00,0xf9,0x00 } },
-{  16, 0x9030, 0, {0x3a,0x40,0x0f,0x90,0x03,0xc4,0x00,0xf9,0x00,0x3e,0x70,0x0f,0x10,0x03,0x28,0x04 } },
-{  16, 0x9040, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x84,0x08,0xf9,0x24,0x3e,0x40 } },
-{  16, 0x9050, 0, {0x0f,0x91,0x03,0xe4,0x00,0xf9,0x00,0x3e,0x41,0x0d,0x10,0x03,0xa4,0x00,0xf9,0x00 } },
-{  16, 0x9060, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe4,0x00,0xc9,0x00,0x3e,0x64,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0x9070, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x08,0xc8,0x80,0x32,0x02 } },
-{  16, 0x9080, 0, {0x0f,0x80,0x03,0x00,0x00,0xc8,0x08,0x3a,0x10,0xce,0x84,0x03,0xe0,0x00,0xfc,0x00 } },
-{  16, 0x9090, 0, {0x3f,0x00,0x8f,0xc0,0x03,0xf0,0x80,0xfc,0x00,0x3f,0x18,0x0f,0xc0,0x43,0xca,0x04 } },
-{  16, 0x90a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8e,0x00,0xa1,0x80 } },
-{  16, 0x90b0, 0, {0x0b,0xe0,0x02,0x28,0x00,0xde,0xc2,0x23,0x90,0x00,0xa0,0x02,0xe8,0x00,0xba,0x00 } },
-{  16, 0x90c0, 0, {0x2e,0x80,0x0b,0xa0,0x02,0xe8,0x00,0xfa,0x00,0x2e,0x80,0x0b,0xa0,0x02,0xca,0x00 } },
-{  16, 0x90d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x99,0x81,0x60,0xc0 } },
-{  16, 0x90e0, 0, {0x0b,0x10,0x02,0x0c,0x00,0x90,0x10,0x2a,0xfc,0x0b,0x30,0x02,0xcc,0x00,0xb3,0x00 } },
-{  16, 0x90f0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x00,0xb3,0x00,0x2c,0xc0,0x0b,0x30,0x02,0xca,0x00 } },
-{  16, 0x9100, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x82,0x95,0x40,0x21,0xc0 } },
-{  16, 0x9110, 0, {0x0b,0x50,0x02,0x1c,0x80,0x90,0x80,0x23,0x01,0x09,0x72,0x12,0xdc,0x00,0xb6,0x00 } },
-{  16, 0x9120, 0, {0x2d,0x00,0x0b,0x40,0x02,0xd0,0x00,0xb4,0x09,0x2d,0x00,0x4b,0x40,0x82,0xe8,0x00 } },
-{  16, 0x9130, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x80,0xdd,0x80,0xb1,0xe0 } },
-{  16, 0x9140, 0, {0x0f,0xda,0x03,0x0f,0x80,0xd4,0x80,0x39,0xe0,0x0b,0x7a,0x03,0xde,0x00,0xf5,0x80 } },
-{  16, 0x9150, 0, {0x3d,0x20,0x0f,0x48,0x03,0xd6,0x10,0xf6,0x81,0x3d,0xe0,0x8f,0x68,0x03,0xea,0x02 } },
-{  16, 0x9160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xed,0x00,0x3e,0x00 } },
-{  16, 0x9170, 0, {0x0f,0x91,0x0b,0xec,0x10,0xf8,0x00,0x3e,0x00,0x0e,0xb0,0x03,0xec,0x00,0xf8,0x00 } },
-{  16, 0x9180, 0, {0x3e,0xc0,0x4f,0xb0,0x03,0xe8,0x00,0xe9,0x01,0x3e,0x00,0x0f,0x90,0x03,0xc2,0x06 } },
-{  16, 0x9190, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x20,0xbf,0x81,0x33,0xa4 } },
-{  16, 0x91a0, 0, {0x8c,0x19,0x03,0x3e,0x00,0xcd,0x80,0x3f,0xe0,0x0f,0xf8,0x83,0x3e,0x00,0xef,0x80 } },
-{  16, 0x91b0, 0, {0x3f,0xe0,0x0f,0xf9,0x13,0xfa,0x10,0xfd,0x80,0x3f,0xa4,0x0f,0xd8,0x03,0xc0,0x00 } },
-{  16, 0x91c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xbf,0x20,0x31,0xc2 } },
-{  16, 0x91d0, 0, {0x08,0x5a,0x02,0x3c,0x02,0x87,0x00,0x2d,0x94,0x0b,0x70,0x0a,0x1c,0x40,0x86,0x10 } },
-{  16, 0x91e0, 0, {0x2d,0x00,0x0b,0x40,0x02,0xd4,0x00,0xf6,0x00,0x2d,0x40,0x4b,0x60,0x02,0xea,0x04 } },
-{  16, 0x91f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x01,0x23,0x80 } },
-{  16, 0x9200, 0, {0x28,0x50,0x02,0x1c,0x00,0x84,0x00,0x2d,0xc0,0x0b,0x30,0x02,0x1c,0x00,0xb5,0x00 } },
-{  16, 0x9210, 0, {0x2d,0x00,0x0b,0x40,0x06,0xd0,0x40,0xb4,0x08,0x2d,0x80,0x0b,0x48,0x02,0xc0,0x00 } },
-{  16, 0x9220, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0xb3,0x08,0xa0,0x20 } },
-{  16, 0x9230, 0, {0x08,0x11,0x8a,0x0e,0x00,0x80,0x00,0x2c,0x90,0x0b,0x37,0x02,0x0c,0x00,0x90,0x00 } },
-{  16, 0x9240, 0, {0x2c,0xc0,0x0b,0x30,0x42,0xcc,0x04,0xa3,0x80,0x2c,0x50,0x0b,0x30,0x02,0xc8,0x04 } },
-{  16, 0x9250, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xf9,0x80,0x32,0x60 } },
-{  16, 0x9260, 0, {0x0c,0xd4,0x03,0x3c,0x80,0x88,0x00,0x3e,0xd0,0x0f,0xf8,0x03,0x28,0x00,0xfa,0x00 } },
-{  16, 0x9270, 0, {0x3e,0xc0,0x0f,0xb0,0x07,0xec,0x01,0xbb,0x80,0x3e,0x54,0x0f,0xb0,0x06,0xea,0x04 } },
-{  16, 0x9280, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xee,0x08,0xf9,0x80,0x3a,0xc0 } },
-{  16, 0x9290, 0, {0x0f,0x90,0x03,0xec,0x00,0xf8,0x40,0x3e,0x58,0x0f,0xb0,0x43,0xe9,0x00,0xeb,0x44 } },
-{  16, 0x92a0, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x0d,0xf8,0x00,0x3e,0x80,0x0f,0x80,0x03,0xe0,0x00 } },
-{  16, 0x92b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xcf,0x00,0x33,0x40 } },
-{  16, 0x92c0, 0, {0x0c,0xd0,0x03,0x3c,0x30,0xcc,0x00,0x3b,0xc0,0x2d,0xf0,0x03,0xd8,0x02,0xcc,0x00 } },
-{  16, 0x92d0, 0, {0x3d,0x00,0x0c,0xc0,0x03,0xf4,0x00,0xee,0x02,0x37,0x40,0x0c,0xe0,0x03,0xc0,0x44 } },
-{  16, 0x92e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x18,0x83,0x84,0x20,0x00 } },
-{  16, 0x92f0, 0, {0x4a,0x10,0x02,0x0c,0x00,0xa8,0x48,0x2e,0x60,0x08,0xb0,0x02,0xe9,0x00,0x89,0x40 } },
-{  16, 0x9300, 0, {0x2e,0xc0,0x08,0xb0,0x02,0xe8,0x10,0xb1,0x01,0x20,0x80,0x0a,0x90,0x03,0xa0,0x40 } },
-{  16, 0x9310, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x82,0x22,0x08 } },
-{  16, 0x9320, 0, {0x08,0x90,0x02,0x2c,0x14,0x88,0x04,0x2c,0x08,0x08,0xb0,0x12,0xe8,0x00,0x8a,0x00 } },
-{  16, 0x9330, 0, {0x2e,0xc0,0x0a,0xb0,0x02,0xe8,0x01,0xb9,0x00,0x26,0x04,0x08,0x90,0x02,0xe0,0x00 } },
-{  16, 0x9340, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x80,0xa2,0xc0 } },
-{  16, 0x9350, 0, {0x0a,0x92,0x02,0x2c,0x00,0xa2,0x00,0x2c,0x00,0x08,0x34,0x02,0xc8,0x00,0x83,0x00 } },
-{  16, 0x9360, 0, {0x2c,0x00,0x28,0x00,0x02,0xc4,0x01,0xba,0x00,0x22,0xc0,0x02,0x20,0x06,0xc2,0x01 } },
-{  16, 0x9370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xca,0x00,0xb2,0x00 } },
-{  16, 0x9380, 0, {0x0c,0x92,0x0b,0x2c,0x04,0xc8,0x04,0x3a,0x00,0x0c,0xb4,0x03,0xe8,0x00,0xc8,0x00 } },
-{  16, 0x9390, 0, {0x2e,0x00,0x0c,0x80,0x33,0xe1,0x40,0xe8,0x00,0x36,0x00,0x0c,0x80,0x03,0xc0,0x03 } },
-{  16, 0x93a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x3d,0x00 } },
-{  16, 0x93b0, 0, {0x0f,0xd1,0x0b,0xfc,0x01,0xfc,0x00,0x3f,0x00,0x0f,0xf0,0x03,0xd8,0x00,0xfd,0x00 } },
-{  16, 0x93c0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x80,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x07,0xa8,0x06 } },
-{  16, 0x93d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xf3,0x00,0xcf,0x80,0x35,0x60 } },
-{  16, 0x93e0, 0, {0x4e,0x68,0x43,0x5c,0x00,0xe7,0x80,0x39,0xc0,0x0c,0xc1,0x03,0x7e,0x00,0xcf,0x34 } },
-{  16, 0x93f0, 0, {0x35,0xe1,0x4d,0xf2,0x03,0x7c,0x00,0xdf,0x38,0x3f,0xc8,0x0f,0xf8,0x03,0xf0,0x00 } },
-{  16, 0x9400, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x18,0xc8,0x00,0xdb,0x84,0x22,0x60 } },
-{  16, 0x9410, 0, {0x08,0xac,0x0a,0x2c,0x00,0x8b,0x80,0x22,0x30,0x08,0x91,0x22,0x2c,0x90,0x27,0x61 } },
-{  16, 0x9420, 0, {0x22,0xca,0x88,0xfc,0x22,0xbf,0x00,0x8b,0x62,0x2f,0xd0,0x09,0xb8,0x03,0xb0,0x04 } },
-{  16, 0x9430, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xe2,0x80,0xa9,0x02,0x24,0x40 } },
-{  16, 0x9440, 0, {0x82,0x34,0x42,0x04,0x00,0xa9,0x00,0x28,0xc5,0x48,0x32,0x02,0x4c,0x20,0x83,0x30 } },
-{  16, 0x9450, 0, {0x20,0xc0,0x08,0x31,0x02,0x0d,0x00,0xb3,0x20,0x2c,0xc4,0x0b,0x30,0x02,0xf2,0x01 } },
-{  16, 0x9460, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xaa,0x02,0xb9,0x04,0x22,0x60 } },
-{  16, 0x9470, 0, {0x28,0xb2,0x02,0x26,0x00,0x89,0x88,0x02,0xc0,0x08,0x31,0x12,0xec,0x00,0x8b,0x00 } },
-{  16, 0x9480, 0, {0x2a,0xd0,0x08,0xb0,0x02,0xac,0x00,0x2b,0x00,0x2e,0xc0,0x0b,0xb0,0x02,0xb0,0x04 } },
-{  16, 0x9490, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xe2,0x00,0xe3,0x00,0x36,0x20 } },
-{  16, 0x94a0, 0, {0x0e,0xa4,0x63,0x6e,0x00,0xe1,0xc0,0x1a,0xc1,0x0c,0x80,0x03,0x68,0x70,0xcb,0x00 } },
-{  16, 0x94b0, 0, {0x36,0x80,0x0d,0xb0,0x03,0x4c,0x00,0xfb,0x04,0x3e,0xc1,0x0f,0xb0,0x03,0xd0,0x04 } },
-{  16, 0x94c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x04,0xdf,0x00,0x3f,0x00 } },
-{  16, 0x94d0, 0, {0x0f,0xe8,0x03,0xfc,0x00,0xfd,0x00,0x3f,0x00,0x2b,0x98,0x03,0x3a,0x00,0x77,0x00 } },
-{  16, 0x94e0, 0, {0x27,0xe4,0x0f,0xf0,0x03,0xfc,0x00,0xdf,0x00,0x3e,0xc0,0x0d,0xf0,0x43,0xf8,0x00 } },
-{  16, 0x94f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0xa4,0x68,0xcb,0x20,0x3a,0x90 } },
-{  16, 0x9500, 0, {0x0f,0x24,0xa3,0xac,0x00,0xe9,0x50,0x3a,0xc0,0x0e,0xb4,0x83,0x2c,0x08,0xeb,0x00 } },
-{  16, 0x9510, 0, {0x3a,0x90,0x0e,0xb0,0x8b,0xec,0x80,0xfb,0x00,0x3e,0xc0,0x0e,0xb0,0x03,0x90,0x04 } },
-{  16, 0x9520, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x01,0x0a,0x00,0x8b,0xa0,0x20,0x80 } },
-{  16, 0x9530, 0, {0x0d,0xa8,0x02,0x2c,0x04,0x89,0x40,0x28,0xe8,0x08,0xb2,0x02,0x2c,0x00,0xaf,0x00 } },
-{  16, 0x9540, 0, {0x02,0x80,0x08,0x7c,0x03,0x3d,0x80,0x3f,0x00,0x2f,0xc0,0x08,0xb0,0x02,0x36,0x00 } },
-{  16, 0x9550, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x49,0x00,0x03,0x40,0x28,0xc0 } },
-{  16, 0x9560, 0, {0x2b,0x28,0x4a,0x28,0x00,0xa1,0x00,0x68,0xd2,0x0a,0x20,0x42,0xa4,0x01,0xa3,0x00 } },
-{  16, 0x9570, 0, {0x02,0x40,0x0a,0x34,0x02,0x0d,0x00,0x33,0x00,0x2c,0xc0,0x0a,0x30,0x00,0xb8,0x00 } },
-{  16, 0x9580, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x01,0x1a,0x00,0x87,0x90,0x21,0xe4 } },
-{  16, 0x9590, 0, {0x2b,0xc8,0x12,0x3a,0x00,0x85,0xc0,0x2b,0x21,0x28,0x68,0x02,0xb6,0x00,0xa7,0x84 } },
-{  16, 0x95a0, 0, {0x23,0x60,0x08,0x38,0x80,0x1e,0x00,0xb7,0x80,0x2d,0xe0,0x08,0x78,0x02,0x2e,0x00 } },
-{  16, 0x95b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x00,0xc1,0x00,0x38,0x54 } },
-{  16, 0x95c0, 0, {0x0f,0x26,0x83,0x80,0x00,0xe0,0x34,0x28,0xc8,0x0e,0x2c,0x0b,0x8c,0x00,0xe3,0x00 } },
-{  16, 0x95d0, 0, {0x78,0x45,0x0e,0x30,0x03,0x8e,0x80,0xf3,0x00,0x3c,0xc8,0x0e,0x30,0x03,0x92,0x02 } },
-{  16, 0x95e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb8,0x00,0xf5,0x02,0x3f,0x44 } },
-{  16, 0x95f0, 0, {0x0d,0x90,0x03,0xf8,0x00,0xbd,0x14,0x1f,0xc0,0x0f,0xe1,0x23,0x5c,0x44,0x9f,0x42 } },
-{  16, 0x9600, 0, {0x3f,0xc0,0x0f,0xf4,0x82,0x7d,0x40,0xff,0x10,0x3f,0xc0,0x4f,0x70,0x07,0xd0,0x06 } },
-{  16, 0x9610, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x02,0xcb,0x00,0x38,0xc0 } },
-{  16, 0x9620, 0, {0x3c,0xa0,0x03,0xec,0x00,0xe9,0x00,0x3e,0xc0,0x0c,0xb0,0x03,0x20,0x04,0xfb,0x21 } },
-{  16, 0x9630, 0, {0x3e,0x80,0x4f,0xb4,0x03,0xcf,0x00,0xcb,0x00,0x3e,0xcc,0x4f,0xb0,0x43,0xea,0x00 } },
-{  16, 0x9640, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x91,0x98,0x00,0x87,0x00,0x21,0xc0 } },
-{  16, 0x9650, 0, {0x08,0x40,0x02,0xdc,0x04,0xb5,0x00,0x2d,0x00,0x2d,0x70,0x02,0x1c,0x1c,0xb7,0x02 } },
-{  16, 0x9660, 0, {0x2d,0xc0,0x0b,0x72,0x02,0xdc,0x00,0x87,0x40,0x2d,0xca,0x8b,0x70,0x02,0xf2,0x04 } },
-{  16, 0x9670, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xba,0x00,0x87,0x88,0x2b,0xe0 } },
-{  16, 0x9680, 0, {0x18,0x78,0x22,0xd6,0x11,0xa4,0x82,0x2f,0xe0,0x08,0x78,0x02,0x12,0x00,0xb7,0x94 } },
-{  16, 0x9690, 0, {0x6d,0x60,0x4b,0x7a,0x02,0xde,0x40,0xb7,0xa0,0x2d,0xe0,0x0b,0x78,0x06,0xe0,0x00 } },
-{  16, 0x96a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xc9,0x12,0x83,0x82,0x28,0xd4 } },
-{  16, 0x96b0, 0, {0x98,0x00,0x06,0xef,0x05,0xb1,0x90,0x2c,0xc1,0x09,0xb4,0x02,0x0c,0x04,0xb3,0x01 } },
-{  16, 0x96c0, 0, {0x6c,0xf0,0x0b,0x30,0x02,0xcc,0x00,0xbb,0x00,0x2e,0xc0,0x0b,0x30,0x02,0xd2,0x04 } },
-{  16, 0x96d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x40,0xca,0x80,0x3b,0xa0 } },
-{  16, 0x96e0, 0, {0x4c,0xe5,0x02,0xf8,0x80,0xee,0x00,0x3d,0x80,0x2c,0xe0,0x0f,0x38,0x80,0xfa,0x00 } },
-{  16, 0x96f0, 0, {0x3f,0xa9,0x0f,0xa0,0x03,0xe8,0x00,0xba,0x02,0x3e,0x80,0x8b,0xa0,0x03,0xfa,0x04 } },
-{  16, 0x9700, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x10,0xf8,0x00,0x26,0x02 } },
-{  16, 0x9710, 0, {0x0f,0x84,0x03,0xe0,0x24,0xf8,0x00,0x3e,0x00,0x4f,0x80,0xa3,0xe0,0x30,0xf8,0x00 } },
-{  16, 0x9720, 0, {0x36,0x02,0x0f,0x80,0x23,0xe0,0x04,0x08,0x00,0x3e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0x9730, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xd9,0x00,0xb6,0x41 } },
-{  16, 0x9740, 0, {0x4e,0x99,0x0b,0xa4,0x00,0x69,0x10,0x3e,0x40,0x0c,0x90,0x03,0xa4,0x10,0xc9,0x00 } },
-{  16, 0x9750, 0, {0x3e,0x40,0x0d,0x92,0x03,0xe6,0x00,0xf9,0x00,0x3a,0x40,0x0e,0x90,0x03,0xc2,0x04 } },
-{  16, 0x9760, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x81,0x00,0x20,0x42 } },
-{  16, 0x9770, 0, {0x08,0x14,0x9a,0x24,0x00,0x89,0x00,0x6e,0x50,0x00,0x90,0x02,0x24,0x10,0xd9,0x02 } },
-{  16, 0x9780, 0, {0x6e,0x40,0x0b,0x94,0x03,0xa7,0x00,0xb9,0x00,0x22,0x40,0x08,0x90,0x03,0xe0,0x00 } },
-{  16, 0x9790, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x06,0x00,0x99,0x00,0xa6,0x41 } },
-{  16, 0x97a0, 0, {0x0a,0x90,0x06,0x2c,0x00,0xa9,0x09,0x6e,0x50,0x08,0x91,0x02,0x84,0x04,0x89,0x00 } },
-{  16, 0x97b0, 0, {0x0e,0x40,0x0b,0x94,0x02,0xe5,0x49,0xb9,0x00,0x0a,0x40,0x0a,0x90,0x02,0xc6,0x00 } },
-{  16, 0x97c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x06,0x00,0x81,0x00,0x22,0x40 } },
-{  16, 0x97d0, 0, {0x08,0x12,0x22,0x04,0x81,0xa1,0x00,0x2c,0x40,0x08,0x16,0x02,0x04,0x00,0x91,0x20 } },
-{  16, 0x97e0, 0, {0x2c,0x40,0x0b,0x12,0x42,0x84,0x89,0xb1,0x20,0x20,0x48,0x08,0x10,0x02,0xc2,0x01 } },
-{  16, 0x97f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xd8,0x00,0x36,0x00 } },
-{  16, 0x9800, 0, {0x0a,0x80,0x03,0xa1,0x40,0xe8,0x00,0x2e,0x00,0x0c,0x00,0x23,0xa1,0x40,0xc8,0x50 } },
-{  16, 0x9810, 0, {0x2e,0x14,0x0d,0x80,0x03,0xe0,0x00,0xf8,0x50,0x3a,0x00,0x0e,0x80,0x03,0xee,0x03 } },
-{  16, 0x9820, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x1d,0xd4,0x00,0xf5,0x00,0xbf,0x40 } },
-{  16, 0x9830, 0, {0x0f,0xd1,0x03,0xf4,0x44,0xdd,0x02,0x3d,0x50,0x2b,0xd1,0x23,0xf4,0x00,0xf9,0x10 } },
-{  16, 0x9840, 0, {0x3f,0x40,0x0d,0x91,0x03,0xa4,0x48,0xf9,0x12,0x3e,0x4e,0x1f,0x90,0x03,0xa6,0x02 } },
-{  16, 0x9850, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xf4,0x00,0xc5,0x04,0x3b,0x40 } },
-{  16, 0x9860, 0, {0x0f,0xd8,0x03,0xa7,0x80,0xfd,0x00,0xb3,0x68,0x0d,0xd8,0x43,0xa5,0x10,0xc9,0xa0 } },
-{  16, 0x9870, 0, {0x32,0x51,0x4f,0x5a,0x43,0x36,0x00,0xc9,0xa0,0x7a,0x68,0x0b,0xd0,0x03,0xc6,0x01 } },
-{  16, 0x9880, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x18,0xca,0x88,0x88,0x02,0x02,0x00 } },
-{  16, 0x9890, 0, {0x8d,0x84,0x22,0x23,0x42,0xf8,0x00,0x22,0x04,0x28,0x8a,0xa2,0xaa,0x94,0x88,0xe9 } },
-{  16, 0x98a0, 0, {0x20,0xa8,0x0a,0x80,0x0a,0x21,0x40,0x80,0xe2,0x2e,0x28,0x0b,0x80,0x02,0xce,0x04 } },
-{  16, 0x98b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc4,0x20,0xa1,0x04,0xa8,0xc0 } },
-{  16, 0x98c0, 0, {0x0b,0x1c,0x2a,0x24,0x00,0x39,0x04,0x20,0x40,0x2a,0x1e,0x02,0xe4,0x80,0xb1,0x10 } },
-{  16, 0x98d0, 0, {0x2a,0x48,0x09,0x14,0x46,0x04,0x00,0x81,0x38,0x2c,0x5b,0x0b,0x10,0x02,0xd2,0x00 } },
-{  16, 0x98e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xa4,0x12,0xa9,0x24,0x22,0x40 } },
-{  16, 0x98f0, 0, {0x29,0x90,0x02,0x24,0x00,0x39,0x00,0x02,0x58,0x08,0x18,0x10,0xe6,0x01,0xb9,0x00 } },
-{  16, 0x9900, 0, {0xaa,0x44,0x08,0x90,0x02,0x24,0x00,0x89,0x00,0x0e,0x41,0x0b,0x90,0x02,0xc6,0x04 } },
-{  16, 0x9910, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x05,0xe4,0x00,0xe1,0x01,0x2a,0x64 } },
-{  16, 0x9920, 0, {0x2f,0x94,0x13,0x24,0x02,0x71,0x60,0x12,0x60,0x4d,0x90,0x00,0xc5,0x02,0xf9,0x00 } },
-{  16, 0x9930, 0, {0x3a,0x40,0x0f,0x90,0x23,0x24,0x02,0xc9,0x02,0x3a,0x40,0x0f,0x90,0x02,0xe8,0x04 } },
-{  16, 0x9940, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x01,0xa4,0x00,0xd9,0x00,0x3e,0x60 } },
-{  16, 0x9950, 0, {0xaf,0x90,0x83,0x64,0x88,0xf9,0x20,0x3e,0x62,0x03,0x90,0x83,0xa4,0x00,0xc9,0x00 } },
-{  16, 0x9960, 0, {0x36,0x60,0x0f,0x10,0x03,0xc4,0x00,0xf9,0x00,0x7e,0x40,0x0f,0x90,0x03,0xda,0x00 } },
-{  16, 0x9970, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa1,0x00,0xc8,0x82,0x32,0x00 } },
-{  16, 0x9980, 0, {0x6f,0x00,0x03,0xa0,0x00,0xd8,0x40,0x30,0x00,0x0e,0x80,0x03,0x60,0x04,0xf8,0x01 } },
-{  16, 0x9990, 0, {0x3e,0x10,0x4f,0x80,0x8b,0x22,0x00,0xf8,0x00,0x32,0x01,0x0e,0x80,0x03,0xca,0x04 } },
-{  16, 0x99a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x38,0x00,0x0e,0x00,0xa9,0x90 } },
-{  16, 0x99b0, 0, {0x2f,0xe6,0x20,0x88,0x00,0x9e,0x80,0x23,0x80,0x0a,0xe8,0x03,0x28,0x00,0xba,0x00 } },
-{  16, 0x99c0, 0, {0x18,0x80,0x0d,0xec,0x02,0x38,0x80,0xba,0x00,0xa2,0x80,0x08,0xa0,0x03,0x8a,0x00 } },
-{  16, 0x99d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x6c,0x02,0x83,0x80,0x20,0xc8 } },
-{  16, 0x99e0, 0, {0x0b,0x20,0x02,0x0c,0x01,0x92,0x10,0x68,0xc0,0x3a,0x3c,0x02,0xcc,0x10,0x3b,0x02 } },
-{  16, 0x99f0, 0, {0x0c,0xc0,0x28,0x3c,0x02,0x4e,0x00,0xb3,0x00,0x28,0xc0,0x28,0x30,0x02,0xca,0x00 } },
-{  16, 0x9a00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x14,0x00,0x87,0x42,0x2b,0xc0 } },
-{  16, 0x9a10, 0, {0x29,0x70,0x22,0x9c,0x00,0xb6,0x00,0x2b,0xc2,0x0a,0x60,0x86,0x1c,0x00,0xb7,0x21 } },
-{  16, 0x9a20, 0, {0x29,0xc0,0x00,0x74,0x02,0x5c,0x00,0x37,0x91,0x01,0xe0,0x08,0x74,0x02,0xa8,0x00 } },
-{  16, 0x9a30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xc7,0x80,0x21,0xe0 } },
-{  16, 0x9a40, 0, {0x2f,0x78,0x02,0x9e,0x00,0x96,0x80,0x39,0xe0,0x2e,0xf8,0x03,0xde,0x30,0xf7,0xd0 } },
-{  16, 0x9a50, 0, {0x2d,0xf2,0x00,0x78,0x03,0x52,0x00,0xf7,0xa2,0x3b,0xe0,0x0e,0x78,0x07,0xea,0x02 } },
-{  16, 0x9a60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xb4,0x00,0xfb,0x00,0x0c,0xc0 } },
-{  16, 0x9a70, 0, {0x0f,0x30,0x03,0xec,0x10,0xd3,0x00,0xb4,0xc0,0x2f,0x80,0x03,0x6c,0x48,0xfb,0x00 } },
-{  16, 0x9a80, 0, {0x3e,0xc8,0x4d,0x90,0x03,0xa4,0x00,0xfb,0x20,0x1e,0xc0,0x0f,0xb0,0x03,0xc2,0x06 } },
-{  16, 0x9a90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xcc,0x80,0x2b,0x2c } },
-{  16, 0x9aa0, 0, {0x2f,0xf8,0x03,0x7e,0x00,0x6e,0x80,0x3b,0xa1,0x0d,0xd8,0x43,0x3e,0x00,0xff,0x90 } },
-{  16, 0x9ab0, 0, {0x33,0xe0,0x0f,0xe9,0x33,0xfe,0x00,0xcf,0xc0,0x3f,0xe2,0x0f,0xd8,0x03,0xc0,0x00 } },
-{  16, 0x9ac0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0xb4,0x40,0x87,0x00,0x21,0x04 } },
-{  16, 0x9ad0, 0, {0x08,0x78,0x02,0x1c,0x00,0x86,0x00,0x21,0xc0,0x28,0x90,0x02,0xdc,0x00,0xb7,0x10 } },
-{  16, 0x9ae0, 0, {0x21,0xc0,0x0f,0x73,0x02,0xcc,0x00,0x87,0x00,0x2d,0xc0,0x0b,0x50,0x02,0xea,0x00 } },
-{  16, 0x9af0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9d,0x00,0xa4,0x00,0x29,0x48 } },
-{  16, 0x9b00, 0, {0x6a,0xf0,0x82,0x4c,0x00,0xae,0x00,0xa1,0xc4,0x29,0x74,0x02,0x5c,0x40,0xa3,0x10 } },
-{  16, 0x9b10, 0, {0x61,0xc2,0x0b,0x60,0x06,0xc8,0x00,0x87,0x00,0x2d,0xc0,0x0b,0x50,0x02,0xc0,0x04 } },
-{  16, 0x9b20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xe6,0x01,0xa3,0x02,0x20,0x40 } },
-{  16, 0x9b30, 0, {0x28,0x3c,0x02,0x0c,0x00,0x83,0x42,0x20,0xc8,0x08,0x10,0x02,0xcd,0x00,0xb3,0x00 } },
-{  16, 0x9b40, 0, {0x28,0xf0,0x0b,0x30,0x02,0xcc,0x01,0x83,0x04,0x2c,0xc0,0x83,0x10,0x02,0xc8,0x04 } },
-{  16, 0x9b50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xaa,0x80,0xeb,0x00,0x38,0xc0 } },
-{  16, 0x9b60, 0, {0x0a,0x90,0x03,0x7c,0x22,0xa2,0x40,0x32,0x48,0x0d,0xb0,0x0b,0x3e,0x00,0xff,0x00 } },
-{  16, 0x9b70, 0, {0x33,0xf4,0x0f,0x90,0x03,0xec,0x00,0x8f,0x02,0x3f,0xc0,0x0f,0x90,0x03,0xea,0x04 } },
-{  16, 0x9b80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe0,0x00,0xd9,0x02,0x3e,0xc0 } },
-{  16, 0x9b90, 0, {0x0e,0xb6,0x03,0xec,0x00,0xfa,0x20,0x3e,0xc0,0x4f,0x24,0x23,0xac,0x60,0xfb,0x00 } },
-{  16, 0x9ba0, 0, {0xa6,0xc0,0x0e,0x90,0x03,0xe4,0x00,0xfb,0x00,0x3c,0xc1,0x0f,0x90,0x03,0xe0,0x00 } },
-{  16, 0x9bb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xf8,0x02,0xcf,0x00,0x33,0xe0 } },
-{  16, 0x9bc0, 0, {0x2c,0xf0,0x13,0xbc,0x00,0x2e,0x10,0xb1,0x64,0x2e,0xf0,0x02,0x3c,0x00,0xff,0x02 } },
-{  16, 0x9bd0, 0, {0x3f,0xc1,0x4d,0xec,0x63,0xfe,0x00,0xb7,0x00,0x3b,0xc0,0x0c,0xd8,0x03,0xc0,0x44 } },
-{  16, 0x9be0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x6c,0x28,0x81,0x81,0x22,0xe0 } },
-{  16, 0x9bf0, 0, {0x0a,0x38,0x02,0x3c,0x04,0xba,0xc9,0x32,0xe0,0x20,0x84,0x02,0x2c,0x00,0xbb,0x00 } },
-{  16, 0x9c00, 0, {0x2e,0xc0,0x0b,0x9c,0x02,0xe7,0x81,0xbb,0x04,0x22,0xc0,0x0a,0x99,0x02,0xe0,0x00 } },
-{  16, 0x9c10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x28,0x40,0x88,0x80,0x22,0x88 } },
-{  16, 0x9c20, 0, {0x28,0xbc,0x42,0xac,0x00,0xba,0x00,0x2a,0x80,0x08,0x84,0x02,0xac,0x00,0xbb,0x00 } },
-{  16, 0x9c30, 0, {0x2e,0xc0,0x0b,0xb0,0x82,0xe8,0x90,0xab,0x00,0x62,0xc0,0x08,0xb0,0x12,0xe0,0x00 } },
-{  16, 0x9c40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x89,0x00,0x2a,0x80 } },
-{  16, 0x9c50, 0, {0x28,0xb2,0x02,0x0c,0x00,0xba,0x00,0x20,0xc0,0x08,0x00,0x02,0x8c,0x00,0xb3,0x00 } },
-{  16, 0x9c60, 0, {0x2c,0xc0,0x0b,0x30,0x20,0x4c,0x14,0xb3,0x00,0x20,0xc0,0x08,0x30,0x02,0xc2,0x01 } },
-{  16, 0x9c70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x68,0x00,0xc8,0x00,0xb2,0xc0 } },
-{  16, 0x9c80, 0, {0x2c,0xb2,0x03,0xac,0x00,0xfa,0x00,0x3a,0xc0,0x4e,0xa5,0x03,0xbc,0x00,0xff,0x00 } },
-{  16, 0x9c90, 0, {0x3f,0xc0,0x09,0xa0,0x03,0xe9,0x04,0xef,0x00,0xba,0xc0,0x0c,0xb0,0x01,0xc0,0x01 } },
-{  16, 0x9ca0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xf5,0x00,0x35,0xc0 } },
-{  16, 0x9cb0, 0, {0xaf,0x34,0x03,0xfc,0x00,0xf4,0x00,0x39,0xc0,0x0f,0xc2,0x03,0x7c,0x00,0xff,0x01 } },
-{  16, 0x9cc0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0xa0,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x03,0xe8,0x05 } },
-{  16, 0x9cd0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xff,0x29,0x3d,0x20 } },
-{  16, 0x9ce0, 0, {0x8e,0xc1,0x03,0x32,0x48,0xdc,0x80,0x23,0x25,0x0e,0xf2,0x03,0x3c,0xc0,0xdf,0x84 } },
-{  16, 0x9cf0, 0, {0x33,0xc9,0x0f,0xf2,0x03,0xfc,0x00,0xcf,0x80,0x33,0x40,0x0c,0xf2,0x03,0x30,0x00 } },
-{  16, 0x9d00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0xc0,0xbb,0x60,0x2e,0x08 } },
-{  16, 0x9d10, 0, {0x08,0x81,0x02,0x20,0x04,0x88,0x20,0x20,0x48,0x08,0xf1,0x82,0x2d,0xc0,0x83,0x00 } },
-{  16, 0x9d20, 0, {0x22,0xd4,0x09,0xf5,0x02,0xfc,0x08,0x8b,0x01,0x22,0x40,0x28,0xb4,0x02,0x20,0x04 } },
-{  16, 0x9d30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x20,0xb3,0x09,0x2c,0x82 } },
-{  16, 0x9d40, 0, {0x08,0x10,0x16,0xa0,0x10,0x90,0x08,0x28,0x48,0x0a,0x32,0x02,0x0c,0x00,0xbb,0x00 } },
-{  16, 0x9d50, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x02,0x93,0x01,0x20,0x00,0x8a,0x31,0x22,0xe2,0x01 } },
-{  16, 0x9d60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x04,0xbb,0x00,0x2c,0x80 } },
-{  16, 0x9d70, 0, {0x08,0x86,0x02,0xa0,0x20,0xa0,0x00,0x2a,0x60,0x0a,0xb0,0x10,0x2c,0x00,0xab,0x0c } },
-{  16, 0x9d80, 0, {0x6e,0xc0,0x09,0xb0,0x02,0xcc,0x00,0x9b,0x00,0x22,0x60,0x0a,0xb0,0x02,0xf0,0x04 } },
-{  16, 0x9d90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xec,0x00,0xbb,0x00,0x3e,0x34 } },
-{  16, 0x9da0, 0, {0x08,0xa0,0x0b,0x83,0x00,0xd9,0x02,0x3a,0xe0,0x2e,0xb0,0x0b,0x2c,0x00,0xf8,0x80 } },
-{  16, 0x9db0, 0, {0x3e,0xc0,0x4f,0xb0,0x03,0xec,0x00,0xca,0x40,0xb2,0x72,0x0e,0xb0,0x0b,0xc0,0x04 } },
-{  16, 0x9dc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x10,0xfb,0x00,0x3f,0x00 } },
-{  16, 0x9dd0, 0, {0x0d,0xf8,0x13,0x70,0x48,0xdd,0x40,0x37,0xc2,0x8d,0xf0,0x03,0xdc,0x00,0xdd,0xc8 } },
-{  16, 0x9de0, 0, {0x13,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xee,0x40,0x7f,0x40,0x0d,0x70,0x03,0x38,0x00 } },
-{  16, 0x9df0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x01,0x32,0xc0 } },
-{  16, 0x9e00, 0, {0x04,0x10,0x03,0x20,0x40,0xe8,0x10,0x3a,0xc0,0x0d,0xb0,0x03,0xac,0x08,0xf8,0x40 } },
-{  16, 0x9e10, 0, {0xb2,0xc0,0x2c,0xb0,0x33,0xa4,0x82,0xda,0x40,0xba,0x40,0x0f,0xb0,0x03,0xd0,0x04 } },
-{  16, 0x9e20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3c,0x08,0xbf,0x80,0x22,0xc8 } },
-{  16, 0x9e30, 0, {0x08,0xb7,0x00,0x23,0x44,0x88,0xd0,0x22,0xd0,0x08,0x70,0x82,0xfc,0x00,0xb2,0xe0 } },
-{  16, 0x9e40, 0, {0x03,0xf4,0x08,0xf5,0x02,0x37,0x04,0x8b,0xd1,0x22,0x60,0x4b,0xfd,0x02,0xf2,0x00 } },
-{  16, 0x9e50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb3,0x10,0xa4,0x40 } },
-{  16, 0x9e60, 0, {0x08,0x00,0x02,0x48,0x00,0xa0,0x42,0x2a,0xd0,0x01,0x30,0x02,0x8c,0x00,0xb3,0x80 } },
-{  16, 0x9e70, 0, {0x2c,0xc0,0x09,0x31,0x02,0xcc,0x00,0x89,0x00,0x22,0xe8,0x03,0x38,0x02,0xf8,0x00 } },
-{  16, 0x9e80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x1e,0x00,0xb7,0x80,0x27,0x64 } },
-{  16, 0x9e90, 0, {0x68,0x4a,0x02,0x52,0x00,0x8c,0x80,0x21,0xe0,0x08,0x78,0x02,0xde,0x00,0xb7,0x80 } },
-{  16, 0x9ea0, 0, {0x2d,0xe2,0x19,0x39,0x02,0x5e,0x30,0x85,0x98,0x21,0xe4,0x0b,0x79,0x02,0xd8,0x00 } },
-{  16, 0x9eb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xf3,0x20,0x34,0x00 } },
-{  16, 0x9ec0, 0, {0x0c,0xb8,0x03,0x48,0x80,0xe2,0x22,0x38,0xc0,0x0d,0x30,0x03,0x8c,0x00,0xf3,0x00 } },
-{  16, 0x9ed0, 0, {0x3e,0xc0,0x0d,0x31,0x03,0xec,0x00,0xcb,0x00,0x38,0x06,0x0f,0x30,0x83,0xd2,0x02 } },
-{  16, 0x9ee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0xff,0x00,0x3b,0x01 } },
-{  16, 0x9ef0, 0, {0x0f,0xd0,0x03,0x90,0x00,0xf6,0x00,0x3f,0xc0,0x0f,0xf4,0x01,0xfc,0x00,0xff,0x01 } },
-{  16, 0x9f00, 0, {0x33,0xc2,0x0e,0xf5,0x13,0xbc,0x00,0xed,0x00,0x3f,0xc4,0x0f,0xf0,0x03,0xd0,0x06 } },
-{  16, 0x9f10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x00,0xfb,0x00,0x3c,0xc0 } },
-{  16, 0x9f20, 0, {0x0e,0xa0,0x01,0x64,0x01,0xd8,0x00,0x32,0xe0,0x2c,0xb5,0x03,0x2c,0x00,0xf2,0x00 } },
-{  16, 0x9f30, 0, {0x7a,0xc0,0x0d,0xb4,0x03,0x2d,0x80,0xc9,0x02,0x32,0xc0,0x0c,0xb0,0x03,0x2a,0x00 } },
-{  16, 0x9f40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x80,0xb7,0x00,0x2d,0xc0 } },
-{  16, 0x9f50, 0, {0x0d,0x60,0x02,0xd0,0x01,0x84,0x00,0x21,0xc0,0x08,0x30,0x02,0x1d,0x00,0xb7,0x00 } },
-{  16, 0x9f60, 0, {0x21,0xc8,0x0b,0xf4,0x03,0x1e,0xc0,0x86,0x00,0x21,0xc0,0x08,0x7c,0x03,0x52,0x04 } },
-{  16, 0x9f70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0xc0,0xb7,0x90,0x2d,0xe0 } },
-{  16, 0x9f80, 0, {0x08,0x78,0x06,0xd6,0x01,0xb4,0x82,0x21,0xe0,0x08,0x78,0x0a,0x1e,0x00,0xb5,0xc0 } },
-{  16, 0x9f90, 0, {0x29,0xe8,0x09,0x78,0x02,0x36,0xc1,0x97,0x80,0x28,0xb0,0x0a,0x7a,0x02,0x30,0x00 } },
-{  16, 0x9fa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xbb,0x00,0x2c,0xe0 } },
-{  16, 0x9fb0, 0, {0x09,0x35,0x82,0xc0,0xc1,0xa0,0x51,0x20,0xe4,0x08,0x30,0x02,0x8c,0x00,0xbb,0xc4 } },
-{  16, 0x9fc0, 0, {0x20,0xc0,0x0b,0x30,0x02,0x06,0x00,0x93,0x18,0xaa,0xb0,0x2a,0x30,0x0a,0x52,0x04 } },
-{  16, 0x9fd0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfa,0x01,0x3d,0xac } },
-{  16, 0x9fe0, 0, {0x4c,0xec,0x13,0x78,0x10,0xf6,0x80,0xb3,0x90,0x0c,0xa0,0x03,0x28,0x00,0xfe,0x00 } },
-{  16, 0x9ff0, 0, {0x3a,0x81,0x0d,0xa0,0x0f,0x2a,0x80,0xde,0x04,0x3b,0xa0,0x0e,0xa0,0x03,0x3a,0x04 } },
-{  16, 0xa000, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x00,0xf8,0x00,0x3e,0x00 } },
-{  16, 0xa010, 0, {0x0d,0x80,0x02,0xe1,0x00,0xd8,0x48,0x3e,0x12,0x0f,0x80,0x13,0x60,0x00,0xf8,0x60 } },
-{  16, 0xa020, 0, {0x3e,0x00,0x07,0x80,0x03,0xa0,0x02,0xe8,0x04,0x26,0x08,0x05,0x80,0x03,0x92,0x00 } },
-{  16, 0xa030, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf9,0x04,0x3a,0x40 } },
-{  16, 0xa040, 0, {0x0c,0x12,0x03,0x24,0x82,0xc9,0x00,0x36,0x44,0x0f,0x10,0x03,0x24,0x00,0xf9,0x00 } },
-{  16, 0xa050, 0, {0x36,0x40,0x04,0x90,0x03,0x04,0x00,0xc9,0x00,0x12,0x40,0x0c,0x90,0x03,0x02,0x04 } },
-{  16, 0xa060, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x81,0x22,0x40 } },
-{  16, 0xa070, 0, {0x08,0x90,0x1a,0x24,0x00,0x89,0x00,0x22,0x68,0x0b,0x99,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0xa080, 0, {0x22,0x40,0x68,0x90,0x0a,0x24,0x00,0x89,0x00,0xa2,0x40,0x08,0x90,0x0a,0x20,0x00 } },
-{  16, 0xa090, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x10,0x22,0xe0 } },
-{  16, 0xa0a0, 0, {0x08,0x94,0x00,0x04,0x04,0x8b,0x08,0x26,0xc0,0x0b,0x90,0x02,0x24,0x04,0xb9,0x0c } },
-{  16, 0xa0b0, 0, {0x24,0x40,0x0a,0x10,0x02,0x24,0x00,0x23,0x02,0x2a,0x40,0xa8,0x10,0x02,0x06,0x00 } },
-{  16, 0xa0c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x90,0xb1,0x20,0x22,0x40 } },
-{  16, 0xa0d0, 0, {0x08,0x12,0x02,0x0c,0x10,0x81,0x02,0xa0,0x50,0x0b,0x12,0x02,0x04,0x80,0xb1,0x05 } },
-{  16, 0xa0e0, 0, {0x00,0x48,0x0a,0x10,0x02,0x04,0xa0,0xa1,0x00,0x28,0x4a,0x08,0x12,0x00,0x02,0x01 } },
-{  16, 0xa0f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x50,0xba,0x14 } },
-{  16, 0xa100, 0, {0x0c,0x85,0x03,0x01,0x42,0xc8,0x50,0x34,0x00,0x0f,0x85,0x03,0x21,0x40,0xf8,0x00 } },
-{  16, 0xa110, 0, {0x36,0x00,0x0e,0x80,0x13,0x20,0x80,0xe0,0x00,0x1a,0x08,0x0c,0x00,0x03,0x2e,0x03 } },
-{  16, 0xa120, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x44,0xf9,0x10,0x3f,0x40 } },
-{  16, 0xa130, 0, {0x2f,0xd1,0x13,0xf4,0x04,0xf5,0x00,0x3f,0x40,0x0f,0x91,0x0b,0xe4,0x40,0xff,0x28 } },
-{  16, 0xa140, 0, {0xbe,0x4e,0x0d,0x96,0x83,0xd4,0xa2,0xdd,0x28,0x37,0x4a,0x0f,0x93,0x83,0xe6,0x06 } },
-{  16, 0xa150, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x05,0xe4,0x10,0xcd,0x00,0x3f,0x40 } },
-{  16, 0xa160, 0, {0x0f,0xd0,0x03,0x35,0x02,0x5d,0x01,0x31,0x44,0x0f,0xd0,0x03,0x24,0x00,0xf9,0x00 } },
-{  16, 0xa170, 0, {0x32,0x60,0x0c,0x98,0x83,0xe6,0x40,0xd9,0x00,0x36,0x6a,0x0c,0x9e,0x83,0x26,0x01 } },
-{  16, 0xa180, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0x88,0x00,0x2e,0x00 } },
-{  16, 0xa190, 0, {0x0b,0x80,0x42,0x02,0x80,0x8a,0x00,0x22,0x20,0x88,0x80,0x03,0x20,0x08,0xb8,0x82 } },
-{  16, 0xa1a0, 0, {0x22,0x21,0x08,0x88,0x82,0xe2,0x42,0x88,0xa8,0x22,0x20,0x08,0xce,0x02,0x0e,0x04 } },
-{  16, 0xa1b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x02,0x81,0x00,0x68,0x40 } },
-{  16, 0xa1c0, 0, {0x0b,0x10,0x02,0x84,0x01,0xb9,0x00,0x20,0x40,0x49,0x10,0x0a,0x04,0x00,0xb5,0x08 } },
-{  16, 0xa1d0, 0, {0x21,0x46,0x08,0x50,0x02,0xd4,0x00,0x8d,0x20,0x25,0x4a,0x0b,0x50,0x02,0x42,0x01 } },
-{  16, 0xa1e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0x89,0x04,0x6e,0x54 } },
-{  16, 0xa1f0, 0, {0x0b,0x10,0x12,0xa4,0x01,0xa9,0x00,0xa2,0x40,0x18,0x90,0x16,0x24,0x00,0xb9,0x00 } },
-{  16, 0xa200, 0, {0x23,0x40,0x18,0xd0,0x02,0xf4,0x00,0x8d,0x40,0x21,0x4a,0x0b,0xd0,0x02,0x46,0x04 } },
-{  16, 0xa210, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xc9,0x00,0x3a,0x50 } },
-{  16, 0xa220, 0, {0x8f,0x96,0x0b,0x84,0x02,0xf1,0x01,0x30,0x48,0x8d,0x90,0x03,0x24,0x10,0xf9,0x00 } },
-{  16, 0xa230, 0, {0xb2,0x40,0x2c,0x90,0x03,0xe6,0x40,0xd1,0xc0,0x36,0x50,0x2f,0x90,0x0b,0x68,0x04 } },
-{  16, 0xa240, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x00,0x3e,0x60 } },
-{  16, 0xa250, 0, {0x0f,0x99,0xc3,0x64,0x00,0xd9,0x28,0x3e,0x40,0x0d,0x90,0x03,0xa4,0x00,0xf9,0x40 } },
-{  16, 0xa260, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe4,0x20,0xf9,0x40,0x3e,0x40,0x0c,0x90,0x03,0x8a,0x00 } },
-{  16, 0xa270, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x01,0x36,0x00 } },
-{  16, 0xa280, 0, {0x8f,0x80,0x03,0xe0,0x02,0xf8,0x04,0x32,0x00,0x0d,0x80,0x43,0x20,0x02,0xcc,0x00 } },
-{  16, 0xa290, 0, {0x3f,0x00,0x0f,0xc0,0x13,0x90,0x02,0xdc,0x40,0x3f,0x10,0x4c,0xc0,0x23,0x0a,0x04 } },
-{  16, 0xa2a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xba,0x00,0x22,0x80 } },
-{  16, 0xa2b0, 0, {0x0b,0xe8,0x20,0xf8,0x00,0x4e,0xc0,0x23,0xa0,0x08,0xa0,0x03,0x68,0x00,0x8a,0x00 } },
-{  16, 0xa2c0, 0, {0x2e,0x80,0x1f,0xa0,0x02,0x2a,0x06,0x8a,0x00,0x2e,0xa0,0x02,0x60,0x03,0x0a,0x00 } },
-{  16, 0xa2d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x6c,0x00,0xb3,0x00,0x20,0xc0 } },
-{  16, 0xa2e0, 0, {0x0b,0x3d,0x02,0xc0,0x03,0x23,0x00,0x20,0xe0,0x01,0xb0,0x06,0x4c,0x00,0x8b,0x00 } },
-{  16, 0xa2f0, 0, {0x2e,0xc0,0x4b,0x30,0x02,0x8e,0x08,0x83,0x80,0x2c,0xc4,0x00,0x34,0x8e,0x4a,0x00 } },
-{  16, 0xa300, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x80,0xb5,0x80,0x61,0xc0 } },
-{  16, 0xa310, 0, {0x0b,0x40,0x02,0xd4,0x00,0x84,0x08,0x23,0xc2,0x08,0x50,0x02,0x5e,0xc0,0x84,0x01 } },
-{  16, 0xa320, 0, {0x2d,0x00,0x8a,0x08,0x02,0x10,0x24,0x84,0x08,0x6d,0x00,0x0a,0x03,0x12,0x28,0x00 } },
-{  16, 0xa330, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf5,0x82,0x21,0x60 } },
-{  16, 0xa340, 0, {0x0f,0x78,0x03,0xd6,0x04,0xae,0x80,0x31,0xe0,0x0d,0x58,0x23,0x7e,0x00,0xc6,0x80 } },
-{  16, 0xa350, 0, {0x2d,0xe0,0x0b,0x78,0x03,0x8e,0x00,0xd7,0x82,0x3d,0xf0,0x0c,0x7a,0x03,0x6a,0x02 } },
-{  16, 0xa360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf1,0x00,0xba,0xd8 } },
-{  16, 0xa370, 0, {0x0f,0x80,0x03,0xe4,0x12,0xf8,0x00,0xbe,0x80,0x0e,0x10,0x03,0xec,0x00,0xf9,0x00 } },
-{  16, 0xa380, 0, {0x3e,0x00,0x5f,0x80,0x03,0xe0,0x08,0xf8,0x04,0x3c,0x00,0x0f,0x80,0x03,0xc2,0x06 } },
-{  16, 0xa390, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x20,0xff,0x80,0x3f,0xf0 } },
-{  16, 0xa3a0, 0, {0x0f,0xf8,0x03,0xd2,0x00,0xef,0x84,0xb3,0x61,0x0c,0xb9,0x03,0xfe,0x00,0xff,0x80 } },
-{  16, 0xa3b0, 0, {0x33,0xe0,0x0c,0xf8,0x13,0x22,0x11,0xcd,0x90,0x3f,0x60,0x0c,0xe8,0x03,0x10,0x00 } },
-{  16, 0xa3c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xf5,0x00,0x2d,0xc0 } },
-{  16, 0xa3d0, 0, {0x0b,0x00,0x02,0xd4,0x04,0x84,0x20,0x23,0x40,0x08,0x5a,0x02,0xdc,0x00,0xb4,0x00 } },
-{  16, 0xa3e0, 0, {0x21,0x00,0x28,0xc2,0x02,0x1e,0x04,0x86,0x04,0x2d,0x88,0x08,0xd0,0x02,0x2a,0x04 } },
-{  16, 0xa3f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x9c,0x00,0xb5,0x00,0x2d,0x40 } },
-{  16, 0xa400, 0, {0x0b,0x70,0x02,0xf4,0x20,0xa7,0x04,0x21,0xc0,0x0a,0x50,0x02,0xdc,0x00,0xbe,0x00 } },
-{  16, 0xa410, 0, {0x21,0xc0,0x08,0x70,0x12,0x00,0x00,0x85,0x00,0x2d,0x40,0x88,0x68,0x0a,0x04,0x00 } },
-{  16, 0xa420, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xcc,0x00,0xa1,0x00,0x2e,0xc0 } },
-{  16, 0xa430, 0, {0x1b,0x08,0x06,0xc4,0x20,0x80,0x00,0x20,0x98,0x1a,0x10,0x02,0xcc,0x00,0xb1,0x08 } },
-{  16, 0xa440, 0, {0x20,0x00,0x08,0x00,0x02,0x0c,0x01,0x82,0xc0,0x2c,0xac,0x28,0x90,0x22,0x18,0x04 } },
-{  16, 0xa450, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xb3,0x00,0x3e,0x40 } },
-{  16, 0xa460, 0, {0x0f,0xba,0x03,0xe5,0x02,0xe9,0x04,0x32,0x90,0xae,0xb0,0x03,0xfc,0x10,0xfb,0x40 } },
-{  16, 0xa470, 0, {0xb2,0x00,0x0c,0x80,0x0b,0x2c,0x02,0x82,0x18,0x3f,0xa0,0x0c,0xd0,0x03,0x2e,0x04 } },
-{  16, 0xa480, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0xec,0x04,0xfb,0x01,0x3e,0x40 } },
-{  16, 0xa490, 0, {0x0f,0xb6,0x43,0xe4,0x00,0xf8,0x00,0x3e,0x80,0x01,0x90,0x03,0xec,0x00,0xf8,0x81 } },
-{  16, 0xa4a0, 0, {0x3e,0xd0,0x0d,0xb4,0x53,0xe0,0x00,0xf9,0x40,0x3e,0x40,0x0f,0xa0,0x03,0xe0,0x00 } },
-{  16, 0xa4b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xdc,0x02,0xcd,0x80,0x33,0x60 } },
-{  16, 0xa4c0, 0, {0x2c,0xda,0x03,0xfc,0x00,0xec,0x00,0x33,0x40,0x0f,0xf2,0x03,0x7c,0x04,0xfe,0x00 } },
-{  16, 0xa4d0, 0, {0x32,0x00,0x0c,0xc8,0x03,0x3c,0x00,0xce,0x00,0x31,0x80,0x0c,0xd1,0x03,0x24,0x04 } },
-{  16, 0xa4e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0x04,0x6c,0x00,0x09,0x00,0x2a,0x64 } },
-{  16, 0xa4f0, 0, {0x08,0x8e,0x02,0xc2,0x10,0xa0,0x10,0x3e,0x10,0x0b,0x98,0x02,0xec,0x00,0xb9,0x00 } },
-{  16, 0xa500, 0, {0x02,0xd8,0x08,0xbe,0x22,0x20,0x00,0x89,0x00,0x22,0x50,0x08,0xa0,0x02,0x20,0x40 } },
-{  16, 0xa510, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x0b,0x20,0x22,0x40 } },
-{  16, 0xa520, 0, {0x08,0xa0,0x02,0xe5,0x42,0xab,0x04,0x22,0x18,0x0b,0xb0,0x02,0x6c,0x00,0xb3,0x00 } },
-{  16, 0xa530, 0, {0x20,0x04,0x08,0x01,0x02,0x00,0x04,0xa8,0x40,0x22,0x10,0x08,0x80,0x02,0x20,0x00 } },
-{  16, 0xa540, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x08,0x83,0x00,0x28,0x40 } },
-{  16, 0xa550, 0, {0x08,0x04,0x02,0xc4,0x02,0xa8,0x00,0x2c,0x00,0x0b,0x12,0x02,0xcc,0x00,0xb0,0x00 } },
-{  16, 0xa560, 0, {0x20,0xc0,0x40,0x30,0x02,0x0c,0x00,0x8b,0x00,0xa8,0xc0,0x08,0x30,0x02,0x02,0x11 } },
-{  16, 0xa570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0d,0x6c,0x00,0xc9,0x00,0x33,0x40 } },
-{  16, 0xa580, 0, {0x0c,0xb0,0x03,0xec,0x02,0xeb,0x00,0x32,0x40,0x0f,0xb0,0x03,0x6c,0x00,0xfa,0x00 } },
-{  16, 0xa590, 0, {0x32,0x00,0x0c,0x80,0x03,0x20,0x80,0xc8,0x00,0x30,0x00,0x0c,0x80,0x03,0x20,0x03 } },
-{  16, 0xa5a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xfd,0x00,0x3f,0x40 } },
-{  16, 0xa5b0, 0, {0x0f,0xc2,0x13,0xf0,0x00,0xf4,0x00,0x3f,0x00,0x4f,0xd4,0x03,0xfc,0x00,0xf5,0x00 } },
-{  16, 0xa5c0, 0, {0x3f,0xc0,0x8f,0xf0,0x03,0xfc,0x40,0xff,0x00,0x37,0xc0,0x2f,0xf0,0x03,0xe8,0x06 } },
-{  16, 0xa5d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0x00,0xcc,0x00,0x33,0x00 } },
-{  16, 0xa5e0, 0, {0x0e,0xd0,0x0b,0x33,0x00,0xcc,0x00,0x33,0xe0,0x0f,0xc0,0x83,0x7c,0x00,0xcf,0x20 } },
-{  16, 0xa5f0, 0, {0x7b,0x09,0x8c,0xf8,0x03,0xfe,0x50,0xcf,0x38,0x3f,0xe1,0x0d,0xc2,0x03,0xf0,0x00 } },
-{  16, 0xa600, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe2,0x00,0x98,0x08,0x20,0x80 } },
-{  16, 0xa610, 0, {0x08,0x98,0x02,0x20,0x00,0x88,0xd0,0x22,0xe0,0x0e,0xb4,0x22,0x7d,0x19,0x9f,0x69 } },
-{  16, 0xa620, 0, {0x2e,0x90,0x08,0x30,0x92,0x28,0x81,0xdb,0x64,0x2e,0xe1,0x88,0x16,0xa2,0xe0,0x04 } },
-{  16, 0xa630, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc8,0x00,0x90,0x24,0x20,0x01 } },
-{  16, 0xa640, 0, {0x08,0x10,0x16,0x00,0x82,0x83,0x01,0x28,0xc1,0x0b,0x02,0x82,0x0c,0xe0,0xa3,0x10 } },
-{  16, 0xa650, 0, {0x28,0x0e,0x1b,0x92,0x02,0x84,0x84,0x93,0x20,0x2e,0xc0,0x08,0x31,0x02,0xe2,0x01 } },
-{  16, 0xa660, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa8,0x10,0x98,0x00,0x22,0x80 } },
-{  16, 0xa670, 0, {0x08,0x90,0x02,0x00,0x60,0x8a,0x10,0x2a,0xc0,0x0a,0x20,0x02,0x6c,0x18,0xbb,0x00 } },
-{  16, 0xa680, 0, {0x6e,0x60,0x2b,0x90,0x02,0x46,0x20,0x8b,0x00,0x2e,0xc2,0x08,0xb1,0x82,0xf0,0x04 } },
-{  16, 0xa690, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0xe4,0x02,0xcb,0x00,0xb2,0x40 } },
-{  16, 0xa6a0, 0, {0x2c,0x92,0x03,0x27,0x00,0x88,0x00,0xba,0xc0,0x0f,0x88,0x03,0x2c,0x00,0xeb,0x04 } },
-{  16, 0xa6b0, 0, {0x3a,0xa0,0xcf,0x2c,0xa3,0xed,0x00,0x9b,0x00,0x3c,0xf0,0x2d,0x8c,0x33,0xd0,0x04 } },
-{  16, 0xa6c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x04,0xef,0x00,0x3f,0xc0 } },
-{  16, 0xa6d0, 0, {0x0d,0x51,0x03,0xf0,0x00,0xf1,0x81,0x37,0xc0,0x0e,0xf4,0x03,0x9c,0x10,0xcf,0x00 } },
-{  16, 0xa6e0, 0, {0x3d,0x80,0x0c,0xec,0x07,0xb8,0x08,0xff,0x02,0x1f,0xc4,0x0f,0xc8,0x03,0xf8,0x00 } },
-{  16, 0xa6f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x9e,0x00,0xc3,0x00,0x38,0x40 } },
-{  16, 0xa700, 0, {0x0c,0x92,0x03,0xa4,0x80,0xfb,0x20,0x3a,0xc0,0x0d,0x94,0x03,0x2c,0x40,0xfb,0x00 } },
-{  16, 0xa710, 0, {0x3e,0x01,0x0f,0x80,0x03,0xe5,0x00,0xeb,0x00,0x3a,0xc0,0x0d,0x84,0x0b,0x10,0x04 } },
-{  16, 0xa720, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x08,0x8b,0x02,0x22,0xc0 } },
-{  16, 0xa730, 0, {0x08,0x92,0x03,0x21,0x00,0x8b,0x48,0x22,0xc0,0x0b,0xb7,0x02,0x3d,0x40,0x3f,0x01 } },
-{  16, 0xa740, 0, {0x22,0x74,0x0b,0x90,0x02,0x28,0x04,0xbf,0x00,0xb2,0xc0,0x0b,0x85,0x02,0x32,0x00 } },
-{  16, 0xa750, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x40,0x01,0x80,0x00,0x28,0x00 } },
-{  16, 0xa760, 0, {0x08,0x2c,0x12,0x88,0x40,0xb0,0x40,0x08,0xc0,0x0b,0x18,0x02,0x0e,0x00,0xb3,0x00 } },
-{  16, 0xa770, 0, {0x28,0x20,0x11,0x30,0x02,0x0c,0x00,0xb3,0x00,0x24,0x00,0x09,0x00,0x06,0x38,0x00 } },
-{  16, 0xa780, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x12,0x00,0x84,0x80,0x21,0xa0 } },
-{  16, 0xa790, 0, {0x28,0x68,0x12,0x3a,0x00,0x84,0x80,0x25,0xe0,0x8b,0x58,0x02,0x1e,0x40,0xb7,0x82 } },
-{  16, 0xa7a0, 0, {0x21,0xa6,0x0b,0x78,0x02,0x1a,0x00,0xb7,0x80,0x21,0x20,0x0b,0x58,0x02,0x08,0x00 } },
-{  16, 0xa7b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x00,0xc8,0x21,0x38,0x09 } },
-{  16, 0xa7c0, 0, {0x0c,0x28,0x03,0x80,0x01,0xf1,0x00,0x38,0xc0,0x0d,0x85,0x02,0x0c,0x00,0xfb,0x00 } },
-{  16, 0xa7d0, 0, {0x38,0x85,0x0f,0x10,0x03,0x8c,0x00,0xeb,0x10,0x3c,0xc8,0x0d,0x30,0x03,0x12,0x02 } },
-{  16, 0xa7e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x98,0x00,0xfc,0x01,0x3f,0x80 } },
-{  16, 0xa7f0, 0, {0x0f,0x68,0x03,0xd0,0x40,0xfc,0x00,0x3b,0xc0,0x0d,0xc0,0x03,0xfc,0x20,0xff,0x00 } },
-{  16, 0xa800, 0, {0x3b,0xc5,0x0f,0xf0,0x0b,0xb4,0x40,0xff,0x18,0x3f,0x00,0x0f,0xf1,0x03,0xd0,0x06 } },
-{  16, 0xa810, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x00,0xeb,0x00,0xb0,0x41 } },
-{  16, 0xa820, 0, {0x0c,0xa0,0x03,0xe0,0x04,0xca,0x04,0xb0,0xe0,0x0e,0xb0,0x03,0xec,0x80,0xcb,0x20 } },
-{  16, 0xa830, 0, {0x32,0x81,0x0c,0xa0,0x03,0xee,0x00,0xdb,0x00,0x3e,0x00,0x0e,0xb0,0x03,0x2a,0x00 } },
-{  16, 0xa840, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x04,0x87,0x00,0x21,0xc0 } },
-{  16, 0xa850, 0, {0x48,0x60,0x02,0xf0,0x00,0x87,0x00,0x21,0xc0,0x08,0x70,0x02,0xfc,0xa0,0x83,0x28 } },
-{  16, 0xa860, 0, {0xa3,0x80,0x08,0x60,0x02,0xdc,0x00,0x87,0x20,0x2d,0xc0,0x0b,0x70,0x02,0x12,0x04 } },
-{  16, 0xa870, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9c,0x02,0xa3,0x80,0x21,0x60 } },
-{  16, 0xa880, 0, {0x08,0x68,0x02,0xd2,0x00,0x87,0x80,0x21,0xe0,0x29,0x78,0x02,0xde,0x80,0x87,0x90 } },
-{  16, 0xa890, 0, {0x21,0xa0,0x19,0x48,0x02,0xfe,0x00,0x97,0x80,0x2d,0xe0,0x0a,0x38,0x82,0x30,0x00 } },
-{  16, 0xa8a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x01,0x83,0x80,0x20,0xc0 } },
-{  16, 0xa8b0, 0, {0x08,0x20,0x42,0xc0,0x30,0x83,0x70,0xa0,0xc0,0x89,0x34,0x02,0xcc,0x02,0x83,0x00 } },
-{  16, 0xa8c0, 0, {0x60,0xc0,0x29,0x00,0x02,0xce,0x00,0x83,0x00,0x2c,0xc8,0x0b,0xbc,0x02,0x12,0x04 } },
-{  16, 0xa8d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa9,0x00,0xea,0xe2,0x32,0x90 } },
-{  16, 0xa8e0, 0, {0x2c,0xe0,0x03,0xfb,0x02,0xce,0xc0,0x32,0x80,0x0f,0xe4,0x03,0xe8,0x00,0x8a,0x00 } },
-{  16, 0xa8f0, 0, {0x33,0x88,0x0d,0x64,0xc3,0xfa,0x00,0xda,0x00,0x3d,0x90,0x0e,0xe0,0x0b,0x3a,0x04 } },
-{  16, 0xa900, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xc0,0x24,0xf8,0x08,0x3e,0x12 } },
-{  16, 0xa910, 0, {0x0f,0xc0,0x03,0xe0,0x48,0xf0,0x00,0x3e,0x00,0x0e,0x80,0x93,0xc0,0x00,0xf8,0x00 } },
-{  16, 0xa920, 0, {0x7e,0x01,0x0e,0x80,0xc2,0xe0,0x40,0xf8,0x00,0x7e,0x00,0x8f,0x84,0x03,0xd2,0x00 } },
-{  16, 0xa930, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe5,0x00,0xc1,0x01,0x32,0x48 } },
-{  16, 0xa940, 0, {0x0c,0x98,0x03,0xe6,0x40,0xc9,0x00,0x32,0x40,0x0f,0x90,0x03,0x66,0x00,0xc9,0x00 } },
-{  16, 0xa950, 0, {0x18,0x61,0x0c,0x90,0x03,0x64,0x20,0xf9,0x05,0x3e,0x40,0x0c,0x90,0x83,0x02,0x04 } },
-{  16, 0xa960, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x66,0x20,0x89,0x00,0x20,0x52 } },
-{  16, 0xa970, 0, {0x28,0x10,0xc2,0x26,0x02,0xa9,0x00,0x22,0x40,0x0b,0x90,0x0a,0x27,0x00,0xa9,0x00 } },
-{  16, 0xa980, 0, {0x22,0x70,0x08,0x90,0x02,0x24,0x08,0xb9,0x00,0x2e,0x40,0x0a,0x90,0x0a,0x20,0x00 } },
-{  16, 0xa990, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x02,0x8d,0x00,0x23,0x40 } },
-{  16, 0xa9a0, 0, {0x08,0xd1,0x02,0x84,0x20,0x89,0x00,0x22,0x60,0x0b,0x11,0xf2,0x24,0xb0,0x81,0x00 } },
-{  16, 0xa9b0, 0, {0x2a,0x46,0x08,0x90,0x42,0x64,0x08,0xb9,0x00,0x2e,0x40,0x08,0x92,0x02,0x06,0x00 } },
-{  16, 0xa9c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x14,0x80,0x85,0x20,0x23,0x48 } },
-{  16, 0xa9d0, 0, {0x08,0x52,0x02,0x84,0x08,0x81,0x00,0x20,0x40,0x0b,0x12,0x02,0x04,0x80,0xa1,0x20 } },
-{  16, 0xa9e0, 0, {0x28,0x49,0x28,0x90,0x02,0x04,0x00,0x31,0x20,0x2e,0x40,0x08,0x32,0x02,0x02,0x01 } },
-{  16, 0xa9f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xc8,0x50,0xb2,0x14 } },
-{  16, 0xaa00, 0, {0x0c,0xc0,0x03,0xa1,0x40,0xc8,0x00,0xb2,0x00,0x07,0x85,0x03,0x21,0x40,0xc8,0x50 } },
-{  16, 0xaa10, 0, {0x3a,0x15,0x0c,0x85,0x03,0x61,0x40,0xf8,0x51,0x3e,0x00,0x2c,0x85,0x03,0x2e,0x03 } },
-{  16, 0xaa20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xc4,0x48,0xf9,0x10,0x3e,0x44 } },
-{  16, 0xaa30, 0, {0x4f,0x91,0x03,0x74,0x00,0xf5,0x44,0x3e,0x40,0x0f,0xd1,0x03,0xe4,0x40,0xf9,0x10 } },
-{  16, 0xaa40, 0, {0x37,0x44,0x0f,0xd0,0x03,0xd4,0x00,0xf9,0x10,0x3f,0xc0,0x0f,0xd1,0x03,0xe6,0x06 } },
-{  16, 0xaa50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xf6,0xa0,0xdd,0x8c,0x33,0x78 } },
-{  16, 0xaa60, 0, {0x0e,0xda,0x03,0x35,0x00,0xcd,0xa0,0x33,0x40,0x0d,0xf8,0x0b,0x36,0x81,0xe9,0x80 } },
-{  16, 0xaa70, 0, {0x33,0x70,0x0c,0x91,0x03,0xe4,0x40,0xf9,0xc0,0x3e,0xc0,0x0f,0xdc,0x03,0xc6,0x00 } },
-{  16, 0xaa80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x04,0xb8,0x40,0x20,0x3c } },
-{  16, 0xaa90, 0, {0x0c,0x85,0x02,0x02,0x84,0x8a,0x40,0x22,0x00,0x08,0x8f,0x82,0x23,0x00,0xb8,0xe8 } },
-{  16, 0xaaa0, 0, {0x22,0x20,0x08,0x88,0x02,0xe2,0x00,0xb8,0xd0,0x2e,0x00,0x0b,0x8c,0x02,0xce,0x04 } },
-{  16, 0xaab0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0x91,0x00,0x60,0x48 } },
-{  16, 0xaac0, 0, {0x4b,0x10,0x02,0x04,0x8a,0x81,0x40,0x60,0x40,0x49,0x10,0x02,0x8d,0xa0,0xa1,0x41 } },
-{  16, 0xaad0, 0, {0x20,0x50,0x09,0x12,0x22,0xc4,0x80,0xb1,0x20,0x2c,0x40,0x4b,0x3e,0x02,0xc2,0x01 } },
-{  16, 0xaae0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x08,0xb9,0x04,0xa0,0x40 } },
-{  16, 0xaaf0, 0, {0x48,0xb0,0x02,0x24,0x00,0x89,0x00,0x82,0x40,0x08,0x90,0xa6,0xa4,0x00,0xb9,0x04 } },
-{  16, 0xab00, 0, {0x22,0x54,0x29,0x95,0x02,0xe5,0x40,0xb9,0x00,0x6e,0x40,0x0b,0x92,0x02,0xc6,0x04 } },
-{  16, 0xab10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x05,0xe4,0x00,0x91,0x00,0x32,0x40 } },
-{  16, 0xab20, 0, {0x0f,0x90,0x09,0x24,0x00,0x89,0x90,0x32,0x40,0x0d,0x94,0x03,0xa4,0x00,0xe9,0x02 } },
-{  16, 0xab30, 0, {0x72,0x60,0x0d,0x94,0x03,0xe4,0x01,0xf9,0x01,0x3e,0x60,0x0f,0x90,0x03,0xe8,0x04 } },
-{  16, 0xab40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x40,0xf9,0x00,0x3e,0x40 } },
-{  16, 0xab50, 0, {0x4f,0x90,0x03,0xe7,0x10,0xf9,0x80,0x3e,0x40,0x0f,0x10,0x13,0x64,0x00,0xf1,0x00 } },
-{  16, 0xab60, 0, {0xbe,0x40,0x0e,0x90,0x03,0xe6,0x08,0xf9,0x01,0x3e,0x64,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0xab70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa0,0x00,0xf8,0x00,0x32,0x08 } },
-{  16, 0xab80, 0, {0x0c,0x01,0x0b,0x20,0x40,0xc8,0x40,0x32,0x00,0x0e,0x84,0x83,0x20,0x00,0xf8,0x04 } },
-{  16, 0xab90, 0, {0x3e,0x04,0x0f,0x80,0x03,0x21,0x00,0xe8,0x00,0x3e,0x10,0x0f,0x88,0x03,0xca,0x04 } },
-{  16, 0xaba0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x38,0x00,0x3e,0x04,0x23,0x80 } },
-{  16, 0xabb0, 0, {0x08,0xec,0x12,0x39,0x44,0xa6,0x00,0x28,0x81,0x08,0xe0,0x00,0x38,0x08,0xba,0x00 } },
-{  16, 0xabc0, 0, {0x3f,0x80,0x0b,0xa0,0x02,0xa8,0x00,0x8a,0x02,0x2e,0x80,0x0b,0xe0,0x02,0xca,0x00 } },
-{  16, 0xabd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x48,0x00,0x31,0x00,0x24,0xd0 } },
-{  16, 0xabe0, 0, {0x08,0x3e,0x12,0xae,0x08,0x81,0xa0,0x2c,0xc0,0x0a,0x38,0x00,0x4c,0x00,0xb3,0x00 } },
-{  16, 0xabf0, 0, {0x6e,0xc0,0x0a,0x30,0x02,0x0c,0x00,0xa3,0x00,0x6c,0xc0,0x0b,0x30,0x02,0xca,0x00 } },
-{  16, 0xac00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x18,0x00,0xb5,0x10,0x25,0xc0 } },
-{  16, 0xac10, 0, {0x28,0x60,0x12,0x90,0x10,0xa5,0x08,0x2d,0xc2,0x08,0x64,0x22,0x58,0x18,0xb7,0x00 } },
-{  16, 0xac20, 0, {0x2d,0x80,0x0b,0x79,0x02,0xbe,0xc0,0x87,0x01,0x6d,0xc0,0x0b,0x60,0x02,0xe8,0x00 } },
-{  16, 0xac30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf5,0x84,0x35,0x20 } },
-{  16, 0xac40, 0, {0x8c,0x18,0x02,0x92,0x10,0xc5,0x80,0x3d,0x60,0x0e,0xc8,0x0b,0x5a,0x08,0x77,0xf3 } },
-{  16, 0xac50, 0, {0x3d,0xa0,0x0f,0xf8,0x03,0x1e,0xb0,0xe7,0x85,0x3d,0xe0,0x0f,0x78,0x03,0xea,0x02 } },
-{  16, 0xac60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf1,0x04,0xba,0x01 } },
-{  16, 0xac70, 0, {0x0f,0xa0,0x43,0x60,0x09,0xe1,0x00,0x38,0x40,0x0e,0xa0,0x03,0xa8,0x14,0xfb,0x20 } },
-{  16, 0xac80, 0, {0x3a,0x80,0x0f,0xb4,0x1b,0x4c,0x80,0xfb,0x29,0x3e,0xc0,0x0f,0xb0,0x23,0xc2,0x06 } },
-{  16, 0xac90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfa,0x00,0xcd,0x80,0x3b,0xe0 } },
-{  16, 0xaca0, 0, {0x4e,0xf8,0x03,0xf2,0x02,0xd4,0x81,0x3b,0xe0,0x8e,0x98,0x07,0x3e,0x44,0xef,0x91 } },
-{  16, 0xacb0, 0, {0x3f,0xe0,0x4f,0xfc,0x07,0xee,0xd0,0xcf,0x98,0x33,0xe4,0x0f,0xf8,0x03,0xc0,0x00 } },
-{  16, 0xacc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x01,0x98,0x00,0x85,0x10,0x2d,0xc4 } },
-{  16, 0xacd0, 0, {0x0d,0x11,0x02,0xf0,0x00,0x85,0x20,0x31,0xc4,0x0b,0x7b,0x00,0x38,0x40,0xd7,0x10 } },
-{  16, 0xace0, 0, {0x2d,0x80,0x0b,0x70,0x62,0xfe,0xe1,0x87,0x14,0x39,0xc0,0x0b,0x60,0x02,0xea,0x04 } },
-{  16, 0xacf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xbc,0x40,0xa5,0x00,0x29,0x40 } },
-{  16, 0xad00, 0, {0x0b,0x50,0x82,0xdc,0x40,0x84,0x04,0x2d,0xc0,0x0b,0x10,0x06,0x58,0x44,0xa7,0x10 } },
-{  16, 0xad10, 0, {0x2d,0x80,0x0b,0x71,0x02,0xdc,0x00,0x87,0x04,0x21,0xc2,0x0b,0x50,0x02,0xc0,0x10 } },
-{  16, 0xad20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x0a,0xa1,0x01,0x2c,0x40 } },
-{  16, 0xad30, 0, {0x89,0x18,0x02,0xc1,0x00,0xa1,0x08,0x20,0xc0,0x0b,0x34,0x06,0x40,0x00,0x93,0x05 } },
-{  16, 0xad40, 0, {0x2c,0x14,0x0b,0x3c,0x86,0xce,0x10,0x83,0x01,0x28,0xf1,0x0b,0x14,0x02,0xc8,0x04 } },
-{  16, 0xad50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xa0,0x00,0xed,0x00,0x3a,0xc0 } },
-{  16, 0xad60, 0, {0x07,0xbc,0x63,0xed,0x00,0x81,0x40,0x3e,0xc0,0x0e,0x88,0x03,0x64,0x00,0xef,0x00 } },
-{  16, 0xad70, 0, {0x7e,0x50,0x0f,0xf0,0x02,0xfd,0x42,0xcf,0x00,0x72,0xc0,0x1f,0xb4,0x03,0xea,0x04 } },
-{  16, 0xad80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe8,0x00,0x99,0x00,0x3e,0xe0 } },
-{  16, 0xad90, 0, {0x4f,0xb4,0x83,0xed,0x90,0x09,0x40,0x3e,0xc0,0x0f,0xa1,0x83,0xa8,0x01,0xeb,0x01 } },
-{  16, 0xada0, 0, {0x3e,0x00,0x0f,0xb1,0x13,0xec,0x0c,0xfb,0x00,0x3a,0xc0,0x5f,0x20,0x23,0xe0,0x00 } },
-{  16, 0xadb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xf8,0x00,0xfd,0x04,0x3f,0xb0 } },
-{  16, 0xadc0, 0, {0x0d,0x60,0x03,0x3e,0x00,0xcd,0x00,0x33,0xf0,0x0f,0xf2,0x01,0xf0,0x00,0xff,0x03 } },
-{  16, 0xadd0, 0, {0x3f,0x03,0x0f,0xf0,0x01,0xfc,0x00,0xfb,0x02,0x33,0xc2,0x0f,0xf0,0xe3,0x00,0x44 } },
-{  16, 0xade0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6a,0x00,0xb9,0x02,0x2e,0xa0 } },
-{  16, 0xadf0, 0, {0x4a,0xac,0x02,0x0e,0x80,0xf9,0xc0,0x36,0xe1,0x0b,0xa0,0x02,0x2a,0x08,0xbb,0x00 } },
-{  16, 0xae00, 0, {0x2e,0x20,0x0e,0xb0,0x02,0xec,0x00,0xeb,0x00,0x22,0xc0,0x8b,0xb0,0x02,0x20,0x40 } },
-{  16, 0xae10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x23,0x00,0xa9,0x00,0x28,0xc0 } },
-{  16, 0xae20, 0, {0x09,0xb2,0x22,0x6c,0x40,0x89,0x89,0x2a,0xc0,0x0b,0x14,0x06,0x26,0x00,0xab,0x02 } },
-{  16, 0xae30, 0, {0x6e,0xe0,0x09,0xb0,0x06,0x6c,0x00,0xb3,0x02,0x22,0xc0,0x0b,0xb0,0x02,0x20,0x00 } },
-{  16, 0xae40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x08,0x00,0xb1,0x00,0x2c,0xc0 } },
-{  16, 0xae50, 0, {0x0a,0x30,0x02,0x2c,0x00,0xbb,0x00,0x64,0xc0,0x0b,0x32,0x0a,0x08,0x00,0x33,0x00 } },
-{  16, 0xae60, 0, {0x6c,0x80,0x02,0x30,0x46,0xcc,0x18,0xa3,0x00,0x20,0xc0,0x0b,0x28,0x02,0x02,0x11 } },
-{  16, 0xae70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x68,0x00,0xe9,0x00,0x38,0xc1 } },
-{  16, 0xae80, 0, {0x0d,0xb1,0x0b,0x2c,0x00,0x89,0x00,0x3a,0xc0,0x0b,0x90,0x03,0x60,0x00,0xff,0x02 } },
-{  16, 0xae90, 0, {0x3e,0x80,0x0f,0xf0,0x03,0xfc,0x80,0xff,0x00,0x32,0xc0,0x8f,0x80,0x0b,0x00,0x03 } },
-{  16, 0xaea0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x11,0xd8,0x00,0xfd,0x04,0x3f,0xc0 } },
-{  16, 0xaeb0, 0, {0x2f,0xf2,0x03,0xfc,0x11,0xef,0x00,0x3f,0xc0,0x0f,0xf4,0x43,0x70,0x00,0xff,0x00 } },
-{  16, 0xaec0, 0, {0x3f,0x00,0x46,0xf0,0x03,0xfd,0x00,0xef,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xe8,0x06 } },
-{  16, 0xaed0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfe,0x00,0xff,0x80,0x3d,0xe0 } },
-{  16, 0xaee0, 0, {0x0c,0xf9,0x13,0xde,0x00,0x7f,0x80,0xb3,0xe0,0x0f,0xfc,0x03,0xbe,0x40,0xcf,0x80 } },
-{  16, 0xaef0, 0, {0x33,0xf0,0x0f,0xf8,0x03,0x7c,0x04,0xcc,0x80,0x33,0xa0,0x0c,0xf0,0x0b,0x30,0x01 } },
-{  16, 0xaf00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe0,0x20,0x88,0x00,0x2e,0x20 } },
-{  16, 0xaf10, 0, {0x08,0x82,0x12,0xe0,0x80,0xa8,0x81,0x22,0x02,0x0b,0x80,0x02,0x20,0x80,0xa8,0x80 } },
-{  16, 0xaf20, 0, {0x22,0x08,0x0b,0x80,0x02,0x2c,0x02,0x88,0x04,0xaa,0x20,0x08,0xb0,0x02,0x20,0x04 } },
-{  16, 0xaf30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xec,0x00,0xa3,0x08,0x2c,0x80 } },
-{  16, 0xaf40, 0, {0x08,0x32,0x02,0xc4,0x20,0xa3,0x00,0x28,0x40,0x0b,0x92,0x02,0x84,0x00,0xa9,0x01 } },
-{  16, 0xaf50, 0, {0x28,0xc8,0x1b,0x12,0x82,0xcc,0x40,0xa8,0x00,0x24,0xe0,0x0a,0x30,0x42,0x22,0x01 } },
-{  16, 0xaf60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xa8,0x80,0xa8,0x02,0x2e,0x40 } },
-{  16, 0xaf70, 0, {0x68,0x80,0x10,0xc8,0x00,0xb8,0x40,0x2a,0x90,0x0b,0xa0,0x00,0x28,0x00,0xaa,0x08 } },
-{  16, 0xaf80, 0, {0x2a,0x02,0x03,0x20,0x02,0x8c,0x00,0xa8,0x88,0x2e,0x20,0x0a,0xb0,0x02,0x30,0x04 } },
-{  16, 0xaf90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe8,0x04,0xfa,0x00,0x3c,0x40 } },
-{  16, 0xafa0, 0, {0x0c,0xa0,0x03,0xe8,0x00,0xeb,0x00,0x3a,0xc0,0x0f,0x20,0x53,0xa8,0x00,0xe3,0x40 } },
-{  16, 0xafb0, 0, {0x2a,0x40,0x0f,0xa0,0x03,0x6c,0x00,0xa8,0x80,0x34,0x20,0x1e,0xb0,0x03,0x10,0x04 } },
-{  16, 0xafc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x00,0x9d,0x91,0x3f,0x80 } },
-{  16, 0xafd0, 0, {0x0f,0xda,0x23,0xf4,0x00,0xcc,0x20,0x37,0x00,0x07,0xd0,0x13,0x74,0x00,0xbc,0x00 } },
-{  16, 0xafe0, 0, {0xb7,0x80,0x0b,0xd0,0x43,0x7c,0x00,0xdc,0x04,0x3b,0x00,0x6d,0xf0,0x03,0xf8,0x00 } },
-{  16, 0xaff0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa8,0x00,0xfa,0x80,0x3a,0x00 } },
-{  16, 0xb000, 0, {0x2c,0xa0,0x0b,0x20,0x02,0xcb,0x62,0x3e,0x50,0x0e,0x88,0x03,0x20,0x00,0xd9,0x10 } },
-{  16, 0xb010, 0, {0x3e,0x70,0x8c,0x80,0x33,0xec,0x80,0xd8,0x40,0x3a,0x02,0x0d,0xb0,0x03,0x10,0x04 } },
-{  16, 0xb020, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x01,0x0c,0x00,0x39,0x80,0x22,0xc0 } },
-{  16, 0xb030, 0, {0x0c,0x9d,0x82,0x2c,0x10,0xd0,0x40,0x2e,0xa0,0x08,0xb8,0x03,0x4e,0x02,0x8a,0x40 } },
-{  16, 0xb040, 0, {0x0e,0xa0,0x0d,0xb0,0x03,0x3d,0x00,0xd0,0x90,0x36,0x10,0x0b,0xf0,0x02,0xb2,0x00 } },
-{  16, 0xb050, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb1,0x00,0x60,0xc0 } },
-{  16, 0xb060, 0, {0x8a,0x18,0x02,0x8c,0x08,0x80,0x40,0x0c,0xa0,0x02,0x30,0x02,0xce,0x00,0x82,0x48 } },
-{  16, 0xb070, 0, {0x2c,0x80,0x2b,0x30,0x06,0x8c,0x00,0x81,0x02,0x20,0x90,0x09,0xb0,0x02,0x38,0x00 } },
-{  16, 0xb080, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x12,0x00,0xb6,0x90,0xa3,0x30 } },
-{  16, 0xb090, 0, {0x08,0xe8,0x22,0xb2,0x14,0x87,0x80,0x2d,0x60,0x08,0x49,0x12,0x12,0x61,0x95,0x90 } },
-{  16, 0xb0a0, 0, {0x2d,0x61,0x0a,0x48,0x16,0x1e,0x80,0x95,0x80,0x25,0x20,0x0b,0x78,0x02,0x88,0x00 } },
-{  16, 0xb0b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xf1,0x00,0x28,0x8c } },
-{  16, 0xb0c0, 0, {0x8e,0x10,0x03,0x84,0x80,0x80,0x00,0x2c,0x02,0x0a,0x9a,0x02,0xe4,0x00,0xd0,0x00 } },
-{  16, 0xb0d0, 0, {0x3e,0x80,0x0b,0x91,0x03,0x8e,0x80,0xc2,0x08,0x38,0x80,0x0d,0xb0,0x03,0x12,0x02 } },
-{  16, 0xb0e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb0,0x00,0xf6,0x00,0x3f,0x44 } },
-{  16, 0xb0f0, 0, {0x0f,0x21,0x13,0x78,0x00,0xff,0x00,0x3d,0xc0,0x0f,0xe0,0x03,0x78,0x00,0xef,0x04 } },
-{  16, 0xb100, 0, {0x3f,0x40,0x8d,0xe8,0x03,0xdc,0x04,0xf6,0x00,0x3f,0x00,0x0f,0xf0,0x83,0xd0,0x06 } },
-{  16, 0xb110, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x00,0xe8,0x80,0x32,0x40 } },
-{  16, 0xb120, 0, {0x0f,0x88,0x0b,0x28,0x00,0x78,0x02,0x3e,0x80,0x0e,0x28,0x03,0x28,0x00,0xca,0x80 } },
-{  16, 0xb130, 0, {0x32,0x00,0x0f,0xa0,0x03,0xec,0x00,0xc9,0x80,0x32,0x80,0x0f,0xb0,0x03,0x2a,0x00 } },
-{  16, 0xb140, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x8c,0x00,0x8f,0x00,0xa1,0x80 } },
-{  16, 0xb150, 0, {0x0b,0x70,0x42,0x14,0x00,0xb7,0x00,0x2d,0x41,0x0b,0x50,0x42,0x14,0x00,0xa5,0x00 } },
-{  16, 0xb160, 0, {0xa1,0xc0,0x0b,0x50,0x02,0xfc,0x80,0xa5,0x00,0x21,0x00,0x0b,0xf2,0x02,0x12,0x04 } },
-{  16, 0xb170, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0xba,0x00,0xa4,0x80,0x29,0x30 } },
-{  16, 0xb180, 0, {0x4b,0x48,0x06,0x52,0x08,0xb4,0x80,0x2d,0x20,0x0b,0x48,0x42,0x32,0x00,0x84,0x80 } },
-{  16, 0xb190, 0, {0x21,0x20,0x0b,0x48,0x12,0xde,0x40,0x86,0x81,0x29,0xa0,0x0b,0x78,0x0a,0x30,0x00 } },
-{  16, 0xb1a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0x83,0x05,0x20,0xe0 } },
-{  16, 0xb1b0, 0, {0x0b,0x34,0x02,0x6c,0x10,0xb3,0x00,0x2c,0xc0,0x0b,0x36,0x4a,0x0d,0x0d,0xa3,0x00 } },
-{  16, 0xb1c0, 0, {0x20,0xc0,0x0b,0x34,0x82,0xcc,0x02,0xa2,0x00,0x28,0x00,0x0b,0x30,0x02,0x12,0x04 } },
-{  16, 0xb1d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa9,0x20,0xea,0x40,0x30,0xa0 } },
-{  16, 0xb1e0, 0, {0x07,0xa0,0x43,0x69,0x40,0xfa,0x00,0x3c,0x80,0x0f,0xa0,0x03,0x08,0x40,0xca,0x00 } },
-{  16, 0xb1f0, 0, {0x30,0xa0,0x0f,0xa4,0x03,0xe8,0x00,0xce,0x00,0x3b,0x98,0x0f,0xa0,0x03,0x3a,0x04 } },
-{  16, 0xb200, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xd2,0x00,0xfc,0x08,0x3f,0x00 } },
-{  16, 0xb210, 0, {0x0b,0xc2,0x03,0xb0,0x00,0xfc,0x00,0x3f,0x00,0x0f,0xc0,0x03,0xf0,0x00,0xfc,0x00 } },
-{  16, 0xb220, 0, {0x3f,0x04,0x0f,0xc0,0x03,0xe0,0x00,0xf8,0x00,0xb6,0x02,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xb230, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xd9,0x00,0x3e,0x68 } },
-{  16, 0xb240, 0, {0x4c,0x91,0x01,0xe4,0x08,0xc9,0x00,0x3e,0x40,0x2c,0x92,0x03,0xe4,0x02,0xc9,0xa0 } },
-{  16, 0xb250, 0, {0x3e,0x70,0x0e,0x90,0x03,0xc6,0x42,0xc9,0x00,0x3e,0x40,0x0f,0x10,0x03,0x02,0x04 } },
-{  16, 0xb260, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x86,0x0e,0x60 } },
-{  16, 0xb270, 0, {0x08,0x98,0x02,0xe4,0x08,0x89,0x10,0x2e,0x60,0x08,0x90,0x02,0xe4,0x00,0x89,0x0c } },
-{  16, 0xb280, 0, {0x2e,0x60,0x08,0x90,0x02,0xe6,0x88,0x89,0x00,0x2e,0x40,0x0b,0x90,0x02,0xa0,0x00 } },
-{  16, 0xb290, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x9d,0x10,0x2f,0x40 } },
-{  16, 0xb2a0, 0, {0x28,0xd0,0x06,0xf4,0x02,0xad,0x00,0x2f,0x60,0x08,0xd0,0x02,0xf4,0x00,0x8d,0x00 } },
-{  16, 0xb2b0, 0, {0x2f,0x40,0x0a,0xd0,0x02,0xe4,0x00,0x89,0x00,0x2e,0x60,0x0b,0x90,0x02,0x06,0x00 } },
-{  16, 0xb2c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x34,0x00,0x85,0x00,0x2d,0x40 } },
-{  16, 0xb2d0, 0, {0x08,0x58,0x02,0xd4,0x00,0xa5,0x02,0x2d,0x40,0x08,0x50,0x00,0xd4,0x00,0x85,0x00 } },
-{  16, 0xb2e0, 0, {0x2d,0x40,0x08,0x54,0x02,0xc4,0x80,0x81,0x00,0x2c,0x60,0x0b,0x14,0x02,0x82,0x01 } },
-{  16, 0xb2f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xd8,0x52,0x3e,0x00 } },
-{  16, 0xb300, 0, {0x0c,0x05,0x03,0xe1,0x40,0xe8,0x04,0x3e,0x14,0x0c,0x85,0x03,0xe1,0x40,0xc8,0x00 } },
-{  16, 0xb310, 0, {0x3e,0x14,0x0e,0xc0,0x03,0xe0,0x00,0xc0,0x02,0x3e,0x00,0x4f,0x80,0x23,0x2e,0x03 } },
-{  16, 0xb320, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x00,0xf9,0x01,0x3e,0x40 } },
-{  16, 0xb330, 0, {0x4f,0x90,0x13,0xe4,0x00,0xd9,0x00,0x1e,0x40,0x0f,0x90,0x03,0xc4,0x10,0xf1,0x00 } },
-{  16, 0xb340, 0, {0x1e,0x40,0x0f,0x90,0x03,0xe4,0xe0,0xfd,0x28,0x3f,0x40,0x0f,0x94,0x03,0xe6,0x06 } },
-{  16, 0xb350, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xa4,0x00,0xfd,0x00,0x3f,0x40 } },
-{  16, 0xb360, 0, {0x4d,0x50,0x02,0xe4,0x00,0x95,0x04,0x33,0x40,0x28,0xd0,0x03,0xf4,0x00,0xfd,0x00 } },
-{  16, 0xb370, 0, {0x33,0x40,0x0f,0x91,0x03,0x34,0x00,0xcd,0x40,0x33,0x40,0x0f,0x98,0x81,0x06,0x00 } },
-{  16, 0xb380, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x10,0xb8,0x00,0x2e,0x00 } },
-{  16, 0xb390, 0, {0x0b,0x80,0x02,0xe0,0x10,0xb8,0x00,0x22,0x00,0x08,0x80,0x02,0xe0,0x00,0xb8,0x00 } },
-{  16, 0xb3a0, 0, {0x22,0x00,0x0b,0x88,0x03,0xc2,0x80,0x88,0x80,0x22,0x00,0x0b,0x8c,0x02,0x0e,0x04 } },
-{  16, 0xb3b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0xc4,0x00,0xb1,0x00,0x2c,0xc0 } },
-{  16, 0xb3c0, 0, {0x0b,0x10,0x02,0xc4,0x00,0xbb,0x00,0x22,0x40,0x08,0x10,0x02,0xc4,0x01,0xb9,0x00 } },
-{  16, 0xb3d0, 0, {0x20,0x40,0x1b,0x90,0x02,0x04,0x22,0x89,0x00,0x20,0x60,0x0b,0x12,0x82,0x02,0x01 } },
-{  16, 0xb3e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x44,0xb9,0x00,0x2e,0xc0 } },
-{  16, 0xb3f0, 0, {0x4b,0x90,0x02,0xe4,0x10,0xb9,0x02,0x02,0x40,0x08,0x91,0x42,0xe4,0x00,0xb9,0x80 } },
-{  16, 0xb400, 0, {0x22,0x40,0x0b,0x92,0x02,0xc4,0x00,0x99,0x40,0x22,0x40,0x4b,0x90,0x12,0x06,0x04 } },
-{  16, 0xb410, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe6,0x00,0xb9,0x01,0x3e,0x58 } },
-{  16, 0xb420, 0, {0x0d,0x90,0x03,0xe6,0x00,0xd1,0x00,0x32,0x60,0x0c,0x98,0x02,0xe6,0x40,0xf9,0x00 } },
-{  16, 0xb430, 0, {0xb2,0x40,0x0f,0x18,0x03,0x24,0x00,0xc9,0x80,0x32,0x50,0x0f,0x90,0x23,0x28,0x04 } },
-{  16, 0xb440, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x00,0x3e,0x42 } },
-{  16, 0xb450, 0, {0x0b,0x90,0x03,0xe7,0x08,0xf9,0x00,0xbe,0x48,0x0f,0x90,0x03,0xe4,0x00,0xf9,0x00 } },
-{  16, 0xb460, 0, {0x3e,0x40,0x0f,0x98,0x03,0xa4,0x00,0xe9,0xa0,0xbe,0x40,0x0f,0x10,0x0b,0x4a,0x00 } },
-{  16, 0xb470, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xd8,0x01,0x3e,0x00 } },
-{  16, 0xb480, 0, {0x0f,0x80,0x8b,0x20,0x00,0xf8,0x20,0x3e,0x01,0x0f,0x81,0x03,0xe0,0x00,0xf8,0x08 } },
-{  16, 0xb490, 0, {0x3a,0x00,0x0c,0x80,0x03,0xe0,0x00,0xd8,0x40,0x32,0x00,0x0f,0x80,0x13,0x0a,0x04 } },
-{  16, 0xb4a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8a,0x80,0x2f,0x91 } },
-{  16, 0xb4b0, 0, {0x0b,0xee,0x02,0x28,0x01,0xbe,0x00,0x20,0x80,0x0b,0xa0,0x02,0xea,0x80,0xb6,0x48 } },
-{  16, 0xb4c0, 0, {0x22,0x80,0x0d,0xa0,0x02,0xfa,0x02,0x86,0x41,0xa3,0xa6,0x0b,0xa0,0x03,0x0a,0x00 } },
-{  16, 0xb4d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0x80,0x2c,0xc0 } },
-{  16, 0xb4e0, 0, {0x0b,0x30,0x02,0x0c,0x10,0xb3,0x00,0x28,0xc0,0x0b,0x38,0x02,0xcc,0x00,0xb3,0x00 } },
-{  16, 0xb4f0, 0, {0x28,0xc0,0x09,0x30,0x02,0xc6,0x01,0x83,0x60,0x20,0x70,0x0b,0x30,0x0a,0x4a,0x00 } },
-{  16, 0xb500, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x2e,0x88,0x85,0x08,0x2d,0x80 } },
-{  16, 0xb510, 0, {0x4b,0xf8,0x06,0x1c,0x80,0xb7,0x00,0x21,0xc0,0x0b,0x50,0x02,0xd4,0x00,0xb6,0x00 } },
-{  16, 0xb520, 0, {0x29,0x60,0x09,0x70,0x02,0xd0,0xa0,0x8d,0x00,0x21,0x40,0x0b,0x32,0x02,0x28,0x00 } },
-{  16, 0xb530, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xd5,0x80,0x3d,0xe0 } },
-{  16, 0xb540, 0, {0x8f,0x78,0x03,0x1e,0x84,0xb7,0x82,0x3d,0x60,0x0f,0x59,0x03,0xde,0x00,0xf7,0x80 } },
-{  16, 0xb550, 0, {0x29,0x60,0x15,0x78,0x03,0xde,0x00,0xc7,0x80,0x31,0x60,0x0f,0x7c,0x03,0x6a,0x02 } },
-{  16, 0xb560, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x40,0xe9,0x00,0x3e,0x80 } },
-{  16, 0xb570, 0, {0x0f,0xa0,0x03,0xed,0x30,0xfb,0x00,0x36,0xc1,0x0f,0x96,0x03,0xe4,0x00,0xb3,0x00 } },
-{  16, 0xb580, 0, {0x34,0x40,0x0f,0xb7,0x83,0xec,0x40,0x21,0x00,0x3e,0x40,0x0f,0xb0,0x03,0xc2,0x06 } },
-{  16, 0xb590, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xff,0x81,0x33,0xe0 } },
-{  16, 0xb5a0, 0, {0x0f,0xf9,0x03,0xde,0x20,0xcf,0x81,0x3f,0xe0,0x07,0x78,0x03,0x3e,0x00,0xff,0x80 } },
-{  16, 0xb5b0, 0, {0x3f,0xe0,0x04,0xf8,0x13,0xfe,0x02,0xde,0x80,0x33,0x60,0x0f,0xf8,0x03,0x00,0x00 } },
-{  16, 0xb5c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xb7,0x00,0x21,0xc4 } },
-{  16, 0xb5d0, 0, {0x0b,0x5a,0x02,0xdc,0x48,0x86,0x50,0x2d,0xc0,0x0b,0x31,0x02,0x94,0x60,0xb4,0x18 } },
-{  16, 0xb5e0, 0, {0x2d,0x40,0x48,0x70,0x02,0xe8,0x00,0xa5,0x10,0x21,0x40,0x0b,0x71,0x02,0x2a,0x04 } },
-{  16, 0xb5f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xbd,0x00,0x21,0x42 } },
-{  16, 0xb600, 0, {0x0b,0x70,0x02,0xfc,0x02,0x85,0x00,0x25,0x40,0x0b,0x50,0x02,0x9c,0x00,0xb7,0x00 } },
-{  16, 0xb610, 0, {0x2f,0x40,0x28,0x71,0x02,0xdc,0x00,0xa6,0x00,0x21,0xc0,0x0b,0x70,0x02,0x00,0x00 } },
-{  16, 0xb620, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0x6d,0x80,0xb1,0x20,0xa0,0x50 } },
-{  16, 0xb630, 0, {0x0b,0xb2,0x06,0xce,0x00,0xa0,0x34,0x2e,0xf0,0x0b,0x18,0x02,0x85,0x20,0xb3,0x4a } },
-{  16, 0xb640, 0, {0x2c,0x54,0x88,0x38,0x02,0xcc,0x10,0xa1,0x00,0x20,0xb0,0x0b,0x30,0x02,0x08,0x04 } },
-{  16, 0xb650, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbe,0x80,0xf3,0x08,0x10,0x54 } },
-{  16, 0xb660, 0, {0x0b,0x88,0x13,0xff,0x00,0xc0,0x80,0x3e,0x64,0x0f,0xb4,0x83,0x07,0x00,0xf9,0xc0 } },
-{  16, 0xb670, 0, {0x3e,0xf0,0x0c,0xfc,0x13,0xf4,0x00,0xea,0x00,0x32,0x70,0x0f,0xf0,0x0b,0x2a,0x04 } },
-{  16, 0xb680, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xf9,0x00,0x3e,0x10 } },
-{  16, 0xb690, 0, {0x07,0x91,0x03,0xec,0xc0,0x58,0x00,0x3e,0x44,0x0f,0x92,0x03,0xe4,0x00,0xf9,0x00 } },
-{  16, 0xb6a0, 0, {0x3e,0xc0,0x8f,0xb3,0x03,0xe0,0x00,0xbb,0x00,0xbe,0x44,0x0f,0xb0,0x03,0xe0,0x00 } },
-{  16, 0xb6b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x02,0xcd,0x04,0x33,0xe0 } },
-{  16, 0xb6c0, 0, {0x0c,0xc0,0x03,0x3c,0x08,0xfe,0x00,0x33,0x60,0x2c,0xd0,0x02,0xb4,0x80,0xcf,0x00 } },
-{  16, 0xb6d0, 0, {0x3f,0x52,0x07,0xf0,0x13,0xfc,0x00,0xce,0x10,0x33,0x42,0x0c,0xb0,0x03,0xc0,0x44 } },
-{  16, 0xb6e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x00,0x89,0x00,0x2a,0xb0 } },
-{  16, 0xb6f0, 0, {0x08,0x88,0x02,0x2c,0x00,0xba,0x00,0x36,0x44,0x08,0x90,0x00,0x26,0x00,0xdb,0xc0 } },
-{  16, 0xb700, 0, {0x2e,0x40,0x0b,0xb0,0x02,0xec,0x00,0x83,0xc0,0x28,0x40,0x0a,0xb0,0x02,0xe0,0x40 } },
-{  16, 0xb710, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x00,0x22,0x08 } },
-{  16, 0xb720, 0, {0x1a,0xa2,0x02,0x2c,0x10,0xb9,0x20,0x22,0x40,0x08,0x30,0x02,0x2c,0x04,0xaa,0x54 } },
-{  16, 0xb730, 0, {0x2e,0xc0,0x0b,0xb0,0x12,0xcc,0x00,0x8b,0x08,0x22,0x40,0x08,0xb0,0x02,0xe0,0x00 } },
-{  16, 0xb740, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x04,0x2a,0x00 } },
-{  16, 0xb750, 0, {0x0a,0x08,0x82,0x0c,0x00,0xb8,0x00,0x64,0x40,0x08,0x30,0x02,0xa4,0x00,0xb0,0x00 } },
-{  16, 0xb760, 0, {0x2c,0xc0,0x8b,0x30,0x10,0xc8,0x02,0x8b,0x00,0x2a,0x40,0x0a,0x30,0x02,0xc2,0x01 } },
-{  16, 0xb770, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xc9,0x00,0x32,0x00 } },
-{  16, 0xb780, 0, {0x1a,0x82,0x03,0x3c,0x00,0xf9,0x00,0x32,0x40,0x0c,0xd1,0x03,0xac,0x00,0xeb,0x00 } },
-{  16, 0xb790, 0, {0x3e,0x40,0x0f,0xf0,0x03,0xed,0x00,0xc3,0x00,0x32,0xc0,0x8c,0xb0,0x03,0xc0,0x03 } },
-{  16, 0xb7a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xf5,0x00,0x3f,0x00 } },
-{  16, 0xb7b0, 0, {0x0d,0x80,0x4b,0xfc,0x00,0x7c,0x00,0x3f,0x40,0x0f,0xd2,0x0b,0x74,0x00,0xdf,0x00 } },
-{  16, 0xb7c0, 0, {0x1d,0x40,0x8f,0xf0,0x03,0xfc,0xa0,0xff,0x00,0x3f,0x80,0x0f,0xf0,0x03,0xe8,0x06 } },
-{  16, 0xb7d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xdf,0x84,0x3b,0xe0 } },
-{  16, 0xb7e0, 0, {0x0f,0xf8,0x0b,0x3e,0x00,0xec,0x80,0x33,0xe1,0x0c,0x30,0x03,0x3c,0x80,0xcf,0x48 } },
-{  16, 0xb7f0, 0, {0x37,0xc0,0x0e,0x40,0x03,0xe0,0xc0,0xc7,0x91,0xb3,0x04,0x0c,0xf0,0x03,0x30,0x00 } },
-{  16, 0xb800, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xef,0x04,0x8b,0x80,0x22,0x41 } },
-{  16, 0xb810, 0, {0x0b,0xb0,0x82,0x2e,0x00,0x88,0x80,0xa2,0xe0,0x0a,0xa2,0x92,0xad,0x80,0x87,0x42 } },
-{  16, 0xb820, 0, {0x23,0xd8,0x8a,0xad,0x02,0xe0,0xc0,0x8b,0x00,0x20,0x4c,0x48,0xa4,0x02,0x20,0x04 } },
-{  16, 0xb830, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x58,0xbb,0x00,0x28,0x80 } },
-{  16, 0xb840, 0, {0x0b,0xb2,0x42,0x24,0x00,0xa8,0x00,0x2a,0xc0,0x0a,0x10,0x02,0x04,0x60,0xa3,0x20 } },
-{  16, 0xb850, 0, {0x24,0xd2,0x08,0x00,0x42,0x8c,0x83,0x9b,0x01,0x20,0x49,0x08,0x33,0xc2,0x22,0x01 } },
-{  16, 0xb860, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x00,0xab,0x88,0x22,0xa0 } },
-{  16, 0xb870, 0, {0x0b,0xb8,0x02,0x26,0x0c,0xa8,0x00,0x2a,0xc0,0x0a,0x92,0x02,0xa4,0x00,0xab,0x06 } },
-{  16, 0xb880, 0, {0x22,0xc0,0x0a,0xb0,0x02,0xe8,0x00,0x9b,0x00,0x02,0x40,0x08,0xa0,0x42,0x30,0x04 } },
-{  16, 0xb890, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xd3,0x80,0x3a,0xe0 } },
-{  16, 0xb8a0, 0, {0x0f,0x18,0x01,0x06,0x00,0xe8,0x30,0x38,0x66,0x0e,0xb8,0x03,0x2a,0x40,0xeb,0x00 } },
-{  16, 0xb8b0, 0, {0x36,0xc1,0x0e,0x96,0x03,0xe2,0x80,0xda,0x08,0x32,0x80,0x2c,0xbb,0x03,0x10,0x04 } },
-{  16, 0xb8c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x9c,0x00,0xdf,0x00,0x3f,0xc0 } },
-{  16, 0xb8d0, 0, {0x0f,0xd0,0x03,0xf4,0x00,0xdc,0x80,0x37,0x60,0x0f,0xe8,0x03,0xfa,0x00,0xdf,0x01 } },
-{  16, 0xb8e0, 0, {0x3f,0xc0,0x0f,0xc0,0x43,0xe6,0x4c,0xef,0xa0,0x3f,0x44,0x0f,0xa0,0x03,0xf8,0x00 } },
-{  16, 0xb8f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x40,0xdb,0x00,0x36,0x80 } },
-{  16, 0xb900, 0, {0x0c,0x98,0x03,0x26,0x00,0xf8,0x00,0x3e,0xc0,0x0e,0x18,0x03,0x84,0x02,0xe3,0x01 } },
-{  16, 0xb910, 0, {0x38,0xc1,0x0e,0xb4,0x03,0xac,0x80,0xca,0x18,0x3a,0xd0,0x2c,0x30,0x03,0x10,0x04 } },
-{  16, 0xb920, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3f,0x40,0xb9,0x88,0x2e,0x80 } },
-{  16, 0xb930, 0, {0x08,0xbc,0x02,0xa3,0x00,0xb0,0x00,0x0e,0xc0,0x08,0xb0,0x06,0x20,0x00,0x8f,0x04 } },
-{  16, 0xb940, 0, {0x23,0xc1,0x08,0xb9,0x12,0x2f,0x00,0x83,0x80,0x36,0x40,0x08,0xad,0x02,0x32,0x00 } },
-{  16, 0xb950, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb2,0x00,0x2c,0xc0 } },
-{  16, 0xb960, 0, {0x09,0x32,0x02,0x84,0x00,0x33,0x00,0x2c,0xb2,0x0a,0x36,0x12,0x8c,0x08,0x93,0x05 } },
-{  16, 0xb970, 0, {0x20,0xc0,0x0b,0x18,0x02,0xed,0x00,0x91,0x80,0x6a,0x00,0x08,0x10,0x02,0x38,0x00 } },
-{  16, 0xb980, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0xb7,0x80,0x2d,0xe0 } },
-{  16, 0xb990, 0, {0x09,0x78,0x02,0x97,0x40,0xb4,0x80,0x2f,0xa0,0x08,0xe8,0x02,0x0e,0x40,0x97,0x82 } },
-{  16, 0xb9a0, 0, {0x21,0xe0,0x98,0x68,0x82,0x1a,0x18,0x9d,0x90,0x2d,0xa1,0x18,0x58,0x02,0x08,0x00 } },
-{  16, 0xb9b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0xc0,0xf3,0x00,0x3e,0xc0 } },
-{  16, 0xb9c0, 0, {0x0d,0xb0,0x43,0x84,0x40,0xf0,0x00,0x3c,0x82,0x0e,0x38,0x12,0x8c,0x44,0xf3,0x30 } },
-{  16, 0xb9d0, 0, {0xba,0xc1,0x1e,0x10,0x47,0x8e,0x22,0xd1,0x10,0x38,0x18,0x0c,0x30,0x83,0x12,0x02 } },
-{  16, 0xb9e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x40,0xff,0x00,0x3f,0xc0 } },
-{  16, 0xb9f0, 0, {0x0e,0xe0,0x03,0xf4,0x40,0xfc,0x00,0x3d,0xc4,0x0f,0xd0,0x01,0xf4,0x41,0xef,0x18 } },
-{  16, 0xba00, 0, {0x3f,0xc4,0x1f,0xf0,0x03,0xf8,0x48,0xef,0x14,0x33,0x80,0x0f,0xc1,0x03,0xd0,0x06 } },
-{  16, 0xba10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xfc,0x40,0xfb,0x00,0x3e,0xc0 } },
-{  16, 0xba20, 0, {0x0f,0x98,0x03,0x24,0x00,0xcb,0x00,0x3e,0x40,0x0f,0xb0,0x03,0xa8,0x00,0xdb,0x28 } },
-{  16, 0xba30, 0, {0x3e,0xc4,0x1f,0x90,0x23,0xec,0x00,0xca,0x00,0x32,0xe0,0x0c,0x90,0x03,0xea,0x00 } },
-{  16, 0xba40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x80,0xb7,0x00,0x2d,0xc0 } },
-{  16, 0xba50, 0, {0x4b,0x50,0x52,0x14,0x00,0xd4,0x01,0x2d,0x80,0x0b,0x60,0x02,0xd8,0x00,0xa7,0x20 } },
-{  16, 0xba60, 0, {0x2d,0xc5,0x0b,0x40,0x16,0xdc,0x00,0x84,0x00,0x23,0xc0,0x08,0x40,0x02,0xd2,0x04 } },
-{  16, 0xba70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x80,0xb7,0x80,0x2d,0xe0 } },
-{  16, 0xba80, 0, {0x0b,0x78,0x0a,0x96,0x00,0x94,0x80,0x2d,0x60,0x1b,0x78,0x06,0xd2,0x00,0xa7,0x80 } },
-{  16, 0xba90, 0, {0x2d,0xe0,0x0b,0x78,0x22,0xde,0x00,0x87,0x82,0x21,0xe0,0x08,0x58,0x02,0xf0,0x00 } },
-{  16, 0xbaa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0xe4,0x2c,0xc0 } },
-{  16, 0xbab0, 0, {0x1b,0x21,0x02,0x81,0x00,0x90,0x00,0x2c,0xc8,0x0b,0x39,0x02,0xce,0x00,0xa3,0x00 } },
-{  16, 0xbac0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcd,0x00,0x8b,0x20,0x20,0xf0,0x08,0xb2,0x02,0xd2,0x04 } },
-{  16, 0xbad0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfe,0xa0,0x3f,0x82 } },
-{  16, 0xbae0, 0, {0x0f,0xe8,0x03,0x98,0x30,0xd6,0x00,0x3f,0xa0,0x0f,0xe0,0x03,0xba,0xc0,0xfa,0x00 } },
-{  16, 0xbaf0, 0, {0x3e,0x80,0x0f,0xec,0x33,0xf8,0x02,0xce,0x00,0xb3,0xb8,0x2c,0xec,0x83,0xfa,0x04 } },
-{  16, 0xbb00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x18,0xf8,0x40,0x3e,0x00 } },
-{  16, 0xbb10, 0, {0x0f,0x80,0x02,0x60,0x84,0xf8,0x05,0x2e,0x04,0x8f,0x80,0x41,0xe0,0x00,0x78,0x02 } },
-{  16, 0xbb20, 0, {0x3e,0x00,0x0f,0x81,0x83,0xe0,0x20,0xf8,0x00,0xbe,0x02,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xbb30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe6,0x18,0xf9,0x20,0x3e,0x40 } },
-{  16, 0xbb40, 0, {0x0f,0x9c,0x03,0xe4,0x40,0xc9,0x00,0x32,0x61,0x0c,0x90,0x13,0xc4,0x08,0xc9,0x01 } },
-{  16, 0xbb50, 0, {0x3e,0x41,0x0f,0x18,0x03,0x24,0x00,0xc9,0xa0,0x32,0x40,0x0f,0x98,0x43,0x02,0x04 } },
-{  16, 0xbb60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x65,0x00,0xb1,0xc0,0x22,0x40 } },
-{  16, 0xbb70, 0, {0x0b,0x9c,0x02,0xe7,0x10,0x89,0x00,0x28,0x44,0x08,0x94,0x22,0xe4,0x10,0x89,0x00 } },
-{  16, 0xbb80, 0, {0x2e,0x40,0x0b,0x9f,0x22,0x26,0x60,0x89,0x80,0x22,0x40,0x0b,0x91,0x0a,0x20,0x00 } },
-{  16, 0xbb90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x80,0xb9,0x00,0x2e,0xc0 } },
-{  16, 0xbba0, 0, {0x4b,0xb4,0x02,0xe4,0x20,0x89,0x20,0x22,0x40,0x08,0x94,0x02,0xec,0x00,0x89,0x00 } },
-{  16, 0xbbb0, 0, {0x2e,0x41,0x0b,0x90,0x02,0x04,0x00,0x89,0x40,0x22,0x40,0x0b,0x90,0x02,0x06,0x00 } },
-{  16, 0xbbc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb1,0x04,0x20,0x40 } },
-{  16, 0xbbd0, 0, {0x8b,0x10,0x02,0xe4,0x05,0x81,0x00,0x28,0x40,0x28,0x12,0x12,0xc4,0x82,0x81,0x20 } },
-{  16, 0xbbe0, 0, {0x2c,0x48,0x0b,0x12,0x0a,0x04,0x82,0x81,0x00,0x20,0x48,0x0b,0x12,0x02,0x02,0x01 } },
-{  16, 0xbbf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x68,0xa0,0xfa,0x02,0x3e,0x14 } },
-{  16, 0xbc00, 0, {0x0f,0x85,0x03,0xe0,0x00,0xc8,0x00,0x32,0x00,0x0c,0x85,0x03,0xc1,0x40,0xc8,0x53 } },
-{  16, 0xbc10, 0, {0x3e,0x14,0x0f,0x80,0x03,0x01,0x48,0xc0,0x50,0xb2,0x14,0x0f,0x85,0x03,0x2e,0x03 } },
-{  16, 0xbc20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x00,0xfd,0x00,0xbf,0x40 } },
-{  16, 0xbc30, 0, {0x0f,0x50,0x13,0xd4,0x02,0xfd,0x00,0x2f,0xc0,0x0f,0xd1,0x03,0xf4,0x40,0xf9,0x10 } },
-{  16, 0xbc40, 0, {0x3e,0x44,0x0f,0xd1,0x03,0xf4,0x40,0xff,0x00,0xbf,0x44,0x0f,0xd1,0x03,0xe6,0x06 } },
-{  16, 0xbc50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0xa0,0xfd,0x01,0x3e,0x44 } },
-{  16, 0xbc60, 0, {0x0f,0xd1,0x03,0xd4,0x00,0xc5,0x00,0x33,0x41,0x0f,0xdb,0x03,0x27,0x20,0xd9,0xe0 } },
-{  16, 0xbc70, 0, {0xb2,0x70,0x0d,0xda,0x83,0xf6,0x40,0xcf,0x10,0x32,0x78,0x2d,0xda,0x03,0x06,0x00 } },
-{  16, 0xbc80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x00,0xb8,0x00,0x2e,0x28 } },
-{  16, 0xbc90, 0, {0x0b,0x88,0x42,0xe0,0x10,0xd8,0x00,0x22,0x00,0x0b,0x8c,0x0a,0x23,0x00,0x88,0xc0 } },
-{  16, 0xbca0, 0, {0x22,0x28,0x08,0x84,0x02,0xc2,0x80,0x80,0xa0,0x22,0x30,0x48,0xaa,0x82,0x0e,0x04 } },
-{  16, 0xbcb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x2c,0x40 } },
-{  16, 0xbcc0, 0, {0x8b,0x12,0x02,0xc4,0x00,0x99,0x02,0x28,0x40,0x8b,0x16,0x02,0x84,0x81,0x91,0x30 } },
-{  16, 0xbcd0, 0, {0x20,0x58,0x09,0x10,0x02,0xc5,0x00,0x81,0x00,0x64,0x4d,0x08,0x34,0x02,0x02,0x01 } },
-{  16, 0xbce0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xac,0x0c,0xb9,0x04,0x2e,0x48 } },
-{  16, 0xbcf0, 0, {0x0b,0x94,0x06,0xe4,0x00,0x99,0x40,0xaa,0x40,0x0b,0x92,0x22,0xa4,0x00,0x89,0x00 } },
-{  16, 0xbd00, 0, {0x60,0x40,0x08,0x94,0x02,0xe4,0x00,0x89,0x80,0xa6,0x50,0x08,0x92,0x02,0x06,0x04 } },
-{  16, 0xbd10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x98,0x3e,0x48 } },
-{  16, 0xbd20, 0, {0x0f,0x98,0x03,0xe5,0x20,0xd9,0x00,0x3a,0x64,0x0f,0x94,0x83,0xa4,0xc0,0xd9,0x02 } },
-{  16, 0xbd30, 0, {0x72,0x40,0x4d,0x90,0x42,0xe4,0x82,0xc9,0x40,0x36,0x40,0x0c,0x90,0x0b,0x28,0x04 } },
-{  16, 0xbd40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xac,0x28,0xf9,0x88,0x3e,0x40 } },
-{  16, 0xbd50, 0, {0x0f,0x99,0x13,0xe7,0x00,0xf9,0xc0,0x36,0x60,0x0f,0x90,0x03,0x66,0x00,0xf1,0x00 } },
-{  16, 0xbd60, 0, {0x7e,0x40,0x0f,0x99,0x07,0xe4,0x60,0xf9,0x00,0x38,0x40,0x0f,0x98,0x03,0xca,0x00 } },
-{  16, 0xbd70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x10,0x32,0x00 } },
-{  16, 0xbd80, 0, {0x0f,0x82,0x0b,0x21,0x00,0xe8,0x00,0x36,0x04,0x0c,0x86,0x03,0xe1,0x00,0xd8,0x00 } },
-{  16, 0xbd90, 0, {0x32,0x00,0x0f,0x80,0x03,0x61,0x00,0xc8,0x00,0x32,0x00,0x0f,0x00,0x03,0x0a,0x04 } },
-{  16, 0xbda0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x20,0xbe,0x00,0x22,0x80 } },
-{  16, 0xbdb0, 0, {0x28,0xec,0x02,0x19,0x04,0x82,0x00,0x03,0x80,0x0d,0xe4,0x82,0xe8,0x00,0x8a,0x01 } },
-{  16, 0xbdc0, 0, {0xaa,0x80,0x8b,0xed,0x82,0x3b,0x80,0x8e,0x90,0x36,0x80,0x0b,0xe0,0x03,0x4a,0x00 } },
-{  16, 0xbdd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x42,0x00,0xb3,0x80,0x20,0xc0 } },
-{  16, 0xbde0, 0, {0x6b,0x34,0x16,0x40,0xc0,0x83,0x10,0x24,0x72,0x88,0xb0,0x02,0xec,0x00,0x83,0x00 } },
-{  16, 0xbdf0, 0, {0x24,0xc0,0x0b,0x04,0x02,0x6f,0x09,0x9b,0x00,0x24,0xc0,0x0b,0x30,0x02,0x0a,0x00 } },
-{  16, 0xbe00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x14,0x00,0xb7,0x80,0x23,0xe4 } },
-{  16, 0xbe10, 0, {0x28,0x78,0x82,0x74,0x14,0x8f,0x00,0x61,0xe0,0x09,0x50,0x12,0xdc,0x04,0x87,0x22 } },
-{  16, 0xbe20, 0, {0x25,0xc8,0x1b,0x78,0x02,0x14,0x00,0x94,0x40,0xa5,0xc0,0x0b,0x60,0x22,0x68,0x00 } },
-{  16, 0xbe30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x12,0x20,0xb7,0x80,0xb1,0xe0 } },
-{  16, 0xbe40, 0, {0x8f,0xf8,0x03,0x12,0x02,0xe7,0x80,0x35,0xe0,0x0c,0x68,0x06,0xcf,0xc2,0xcf,0xb0 } },
-{  16, 0xbe50, 0, {0x25,0xf4,0x0f,0x58,0x03,0x5a,0x02,0xd5,0x80,0x75,0xfa,0x4f,0xf8,0x03,0x2a,0x02 } },
-{  16, 0xbe60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xa5,0x90,0xf3,0x00,0x3d,0xc0 } },
-{  16, 0xbe70, 0, {0x4f,0xb0,0x13,0xa8,0x04,0xfb,0x00,0x3c,0xc0,0x0f,0x80,0x43,0xec,0x80,0xeb,0x60 } },
-{  16, 0xbe80, 0, {0x3a,0xc9,0x0f,0x30,0x03,0xec,0x00,0xe9,0x00,0x3e,0xc8,0x0f,0xa0,0x03,0xc2,0x06 } },
-{  16, 0xbe90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xf6,0x00,0xee,0x80,0x3f,0xe0 } },
-{  16, 0xbea0, 0, {0x0d,0x89,0x03,0xd2,0x40,0xe5,0x81,0x39,0xe0,0x3c,0xf9,0x07,0xfe,0x00,0xcf,0x88 } },
-{  16, 0xbeb0, 0, {0x3f,0xe0,0x0f,0xe8,0x03,0xf2,0x08,0xce,0x80,0x33,0xe0,0x0c,0xf8,0x03,0x00,0x00 } },
-{  16, 0xbec0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x94,0x44,0xc6,0x00,0x2f,0xc0 } },
-{  16, 0xbed0, 0, {0x08,0x58,0x02,0xd0,0xc4,0x85,0x24,0x21,0x90,0x08,0x54,0x12,0xdc,0x82,0x07,0x00 } },
-{  16, 0xbee0, 0, {0x2d,0xc0,0x0b,0x70,0x06,0xd4,0x00,0x8e,0x48,0x21,0xc0,0x0a,0x60,0x02,0x2a,0x04 } },
-{  16, 0xbef0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xa7,0x40,0x2d,0xc0 } },
-{  16, 0xbf00, 0, {0x08,0x42,0x02,0xd0,0x00,0xad,0x00,0x29,0xc0,0x08,0x70,0x22,0xdc,0x28,0x87,0x00 } },
-{  16, 0xbf10, 0, {0x2d,0xc0,0x0b,0x40,0x02,0x98,0x00,0x97,0x00,0xa0,0xc4,0x08,0x70,0x02,0x00,0x00 } },
-{  16, 0xbf20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x08,0x93,0x00,0x2c,0xe0 } },
-{  16, 0xbf30, 0, {0x08,0x3c,0x22,0xc1,0x00,0x81,0x00,0x20,0x80,0x88,0x15,0x02,0xce,0x30,0x83,0x00 } },
-{  16, 0xbf40, 0, {0x2c,0xc0,0x0b,0x3c,0x02,0xcc,0x04,0x93,0xc0,0x20,0xf4,0x4a,0x0c,0x82,0x08,0x04 } },
-{  16, 0xbf50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xa0,0x00,0xe3,0xc0,0x1f,0xe0 } },
-{  16, 0xbf60, 0, {0x6c,0x10,0x83,0xe0,0x04,0xeb,0x00,0x3a,0x52,0x4c,0xb4,0x03,0xfe,0x02,0xcf,0x00 } },
-{  16, 0xbf70, 0, {0x3f,0xc0,0x0f,0x84,0x43,0xe1,0x02,0xd8,0xc2,0x33,0xc0,0x0c,0x84,0x0b,0x2a,0x04 } },
-{  16, 0xbf80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe9,0x00,0xeb,0x10,0x3e,0xc4 } },
-{  16, 0xbf90, 0, {0x0e,0x94,0x03,0xe4,0x00,0xfb,0x18,0x3e,0xc2,0x0f,0xb6,0x03,0xec,0x00,0xfb,0x01 } },
-{  16, 0xbfa0, 0, {0x3e,0xc0,0x0f,0x35,0x03,0xc4,0x28,0xea,0x42,0x3e,0xc0,0x0f,0x81,0x03,0xe0,0x00 } },
-{  16, 0xbfb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x40,0xff,0x00,0x33,0xc0 } },
-{  16, 0xbfc0, 0, {0x0c,0xc0,0xa3,0x30,0x28,0xcd,0xa0,0x33,0xc0,0x0c,0xe8,0x03,0x0c,0x00,0xef,0x05 } },
-{  16, 0xbfd0, 0, {0x3d,0xc0,0x0c,0xca,0x83,0x3c,0x00,0xcd,0x08,0x3f,0xc2,0x0c,0xa0,0x03,0xc0,0x44 } },
-{  16, 0xbfe0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x67,0x00,0xbb,0x80,0x20,0xc0 } },
-{  16, 0xbff0, 0, {0x08,0xaa,0x02,0x08,0x00,0xa1,0x01,0x34,0xd1,0x08,0xa4,0x12,0x2c,0x00,0x8b,0x00 } },
-{  16, 0xc000, 0, {0x6e,0xc0,0x88,0xb2,0x02,0x2c,0x08,0x89,0x80,0x2e,0xc0,0x0a,0xa8,0x03,0xa0,0x40 } },
-{  16, 0xc010, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0xba,0x80,0xa2,0xc0 } },
-{  16, 0xc020, 0, {0x08,0xa8,0x0a,0xa0,0x00,0x8b,0x00,0xa2,0xc0,0x48,0x11,0x02,0xac,0x04,0x8b,0x00 } },
-{  16, 0xc030, 0, {0x2e,0xc0,0x00,0x80,0x12,0x2a,0x08,0x8b,0x14,0x2c,0xc0,0x08,0x88,0x02,0xe0,0x00 } },
-{  16, 0xc040, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xb2,0x00,0x22,0xc0 } },
-{  16, 0xc050, 0, {0x08,0xb2,0x12,0x80,0x00,0xab,0x01,0x24,0xc0,0x08,0x00,0x02,0x0c,0x04,0x83,0x00 } },
-{  16, 0xc060, 0, {0x2c,0xc0,0x08,0x30,0x02,0x07,0x00,0x82,0x00,0x24,0xc0,0x08,0x08,0x02,0x82,0x01 } },
-{  16, 0xc070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xfb,0x00,0x32,0xc0 } },
-{  16, 0xc080, 0, {0x0c,0xa2,0x03,0xa0,0x00,0xc9,0x00,0x32,0xc0,0x24,0x94,0x03,0x3c,0x02,0xcf,0x00 } },
-{  16, 0xc090, 0, {0x2f,0xc0,0x04,0x80,0x0b,0x09,0x02,0xcb,0x01,0x3f,0xc0,0x2c,0xa0,0x03,0xc0,0x03 } },
-{  16, 0xc0a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xdc,0x00,0xfd,0x02,0x3f,0xc0 } },
-{  16, 0xc0b0, 0, {0x4f,0xe4,0x13,0x70,0x00,0xfd,0x00,0x3f,0xc0,0x0f,0xc2,0x83,0xfc,0x00,0xff,0x00 } },
-{  16, 0xc0c0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xa8,0x06 } },
-{  16, 0xc0d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x20,0xef,0x30,0x3f,0x04 } },
-{  16, 0xc0e0, 0, {0x6c,0x88,0x03,0x3a,0x42,0xe4,0x91,0x3f,0x0d,0x0d,0x48,0x03,0x3c,0xc0,0xff,0x02 } },
-{  16, 0xc0f0, 0, {0x33,0x44,0x0c,0xf4,0x03,0xfc,0x82,0xdf,0x30,0x33,0x60,0x0d,0xf1,0x03,0x30,0x00 } },
-{  16, 0xc100, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0xed,0x00,0x8b,0x70,0x2e,0x18 } },
-{  16, 0xc110, 0, {0x88,0x22,0x4a,0x2c,0x82,0xea,0x26,0x2e,0x0c,0x0b,0xb8,0x42,0x3d,0x80,0xbf,0x90 } },
-{  16, 0xc120, 0, {0x2a,0x54,0x28,0xb4,0x02,0xcd,0x00,0xdb,0x40,0x2a,0x4a,0x48,0x30,0x02,0xa0,0x04 } },
-{  16, 0xc130, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0xb0,0xa3,0x00,0x6c,0x10 } },
-{  16, 0xc140, 0, {0x09,0x00,0x82,0x20,0x82,0xa0,0x20,0x2c,0x88,0x4b,0x80,0x00,0x0c,0x40,0xb3,0x01 } },
-{  16, 0xc150, 0, {0x20,0x48,0x0b,0x36,0x02,0x8c,0xe0,0x83,0x64,0x24,0x40,0x28,0x32,0x02,0x22,0x01 } },
-{  16, 0xc160, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x11,0xac,0x00,0x8b,0x00,0x2e,0x00 } },
-{  16, 0xc170, 0, {0x09,0x80,0x80,0xa6,0x00,0xba,0x11,0x2e,0x88,0x0b,0xb0,0x00,0x2c,0x00,0xbb,0x02 } },
-{  16, 0xc180, 0, {0x02,0x40,0x09,0xb0,0x02,0xec,0x00,0x8b,0x00,0x2c,0xc8,0x08,0xb8,0x82,0xb0,0x04 } },
-{  16, 0xc190, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xeb,0x00,0x3e,0x92 } },
-{  16, 0xc1a0, 0, {0x0d,0x80,0x03,0x0a,0x20,0xe9,0x00,0x3e,0x50,0x45,0x80,0x01,0x2c,0x04,0xf3,0x00 } },
-{  16, 0xc1b0, 0, {0x90,0x60,0x09,0xb0,0x03,0xec,0x00,0x8b,0x02,0x26,0x50,0x8d,0xbc,0x03,0x10,0x04 } },
-{  16, 0xc1c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0xbc,0x00,0xff,0x02,0x3f,0x80 } },
-{  16, 0xc1d0, 0, {0x0e,0xf9,0x02,0x7c,0x22,0xaf,0x00,0x3f,0x60,0x03,0xc0,0x0b,0xfc,0x10,0xff,0x00 } },
-{  16, 0xc1e0, 0, {0x3f,0x4a,0x4e,0xf0,0x03,0xfc,0x00,0xf7,0x00,0x2b,0x60,0x0f,0x70,0x03,0xf8,0x00 } },
-{  16, 0xc1f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x00,0xb0,0x00 } },
-{  16, 0xc200, 0, {0x0f,0x82,0x0b,0xa9,0x00,0xc9,0x00,0x32,0xd2,0x0f,0xa0,0x83,0xac,0x00,0xcb,0x10 } },
-{  16, 0xc210, 0, {0x3e,0x40,0x0c,0xb0,0x03,0xec,0x00,0xdb,0x00,0x32,0x50,0x2c,0x95,0x03,0x10,0x04 } },
-{  16, 0xc220, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3c,0x04,0xbf,0x02,0x22,0x80 } },
-{  16, 0xc230, 0, {0x0b,0x98,0x00,0x29,0x00,0xcb,0x40,0x22,0xc0,0x0b,0x24,0x02,0x3c,0x08,0x8f,0x50 } },
-{  16, 0xc240, 0, {0x2e,0x50,0x0d,0xf0,0x02,0xfd,0x42,0x8f,0x58,0x22,0xe0,0x48,0xb5,0x02,0x32,0x00 } },
-{  16, 0xc250, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x6c,0x00,0xb3,0x00,0x24,0x40 } },
-{  16, 0xc260, 0, {0x4b,0x94,0x00,0x49,0x00,0x90,0x80,0x04,0x30,0x09,0x00,0x0e,0x4c,0x00,0x83,0x80 } },
-{  16, 0xc270, 0, {0x2c,0xc0,0x09,0x30,0x22,0x6e,0x42,0x83,0x80,0x20,0x48,0x08,0x38,0x02,0x38,0x00 } },
-{  16, 0xc280, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0xb7,0x80,0x65,0x20 } },
-{  16, 0xc290, 0, {0x0b,0x78,0x82,0x7a,0x08,0x8c,0xc0,0x25,0xa3,0x4b,0x78,0x02,0x5e,0x04,0x87,0x84 } },
-{  16, 0xc2a0, 0, {0x2d,0x61,0x89,0x78,0x02,0xde,0x04,0x87,0x80,0xe9,0x62,0x08,0x78,0x02,0x08,0x00 } },
-{  16, 0xc2b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xfb,0x00,0x34,0x48 } },
-{  16, 0xc2c0, 0, {0x0f,0x3b,0x03,0x48,0x00,0x93,0x48,0x34,0x50,0x0d,0x00,0x03,0x6c,0x00,0xc3,0x10 } },
-{  16, 0xc2d0, 0, {0x1c,0xc2,0x05,0x30,0x03,0xcc,0x40,0xcb,0x00,0x32,0x40,0x0c,0x20,0x03,0x12,0x02 } },
-{  16, 0xc2e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x20,0xff,0x01,0x03,0x40 } },
-{  16, 0xc2f0, 0, {0x0f,0xf0,0x23,0x1c,0x00,0xff,0x00,0x3b,0x80,0x0f,0xb0,0x23,0x3c,0x02,0xff,0x50 } },
-{  16, 0xc300, 0, {0x3d,0xc4,0x0f,0xf1,0x03,0xec,0x00,0xef,0x00,0xb7,0xc0,0x0f,0xe1,0x03,0xd0,0x06 } },
-{  16, 0xc310, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xec,0x00,0xfb,0x02,0x3e,0xe0 } },
-{  16, 0xc320, 0, {0x0c,0x80,0x03,0x48,0x02,0xc8,0x81,0x32,0x00,0x0f,0x90,0x42,0xec,0xa0,0xfb,0x10 } },
-{  16, 0xc330, 0, {0x3e,0xe0,0x0c,0xb1,0x03,0xec,0x40,0xfb,0x10,0x32,0x40,0x1f,0xf0,0x03,0x2a,0x00 } },
-{  16, 0xc340, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb7,0x24,0x2d,0x80 } },
-{  16, 0xc350, 0, {0x08,0x70,0x42,0xd8,0x10,0x8c,0x02,0x21,0x40,0x0b,0x50,0x02,0xdd,0x00,0xe7,0x20 } },
-{  16, 0xc360, 0, {0x2f,0x40,0x08,0x70,0x02,0xdc,0x05,0xb7,0x00,0x21,0xc0,0x0b,0xf0,0x02,0x12,0x04 } },
-{  16, 0xc370, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x90,0x2f,0x40 } },
-{  16, 0xc380, 0, {0x0a,0x68,0x02,0x7a,0x00,0x97,0x80,0x21,0xe0,0x0b,0x78,0x02,0xde,0x00,0xb7,0x80 } },
-{  16, 0xc390, 0, {0x2d,0xe0,0x08,0x78,0x06,0xde,0x00,0xb7,0xa0,0x21,0x60,0x0b,0x78,0x42,0x30,0x00 } },
-{  16, 0xc3a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0x00,0x2c,0xc0 } },
-{  16, 0xc3b0, 0, {0x0a,0x34,0x02,0xc8,0x00,0x83,0x4a,0x20,0xf8,0x0b,0x31,0x02,0xcc,0x00,0xa3,0x00 } },
-{  16, 0xc3c0, 0, {0x2c,0xc0,0x08,0x30,0x02,0xcc,0x00,0xb3,0x00,0x20,0xb2,0x0b,0x20,0x42,0x12,0x04 } },
-{  16, 0xc3d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xba,0x00,0x3f,0x88 } },
-{  16, 0xc3e0, 0, {0x2e,0xe0,0x43,0x59,0x88,0xde,0x00,0x33,0xb0,0x0f,0x6c,0x03,0xe8,0x00,0xfa,0x00 } },
-{  16, 0xc3f0, 0, {0x3e,0x80,0x2c,0xa0,0x03,0xe8,0x04,0xfa,0x00,0x23,0xb8,0x0f,0xe0,0x8b,0x3a,0x04 } },
-{  16, 0xc400, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x04,0xf8,0x01,0x3e,0x00 } },
-{  16, 0xc410, 0, {0x09,0x82,0x21,0xe0,0x00,0xf8,0x40,0xbe,0x14,0x0f,0x84,0x81,0xe0,0x00,0xe8,0x00 } },
-{  16, 0xc420, 0, {0x3e,0x00,0x1f,0x80,0x03,0xe0,0x00,0xf8,0x00,0xbe,0x00,0x0f,0x88,0x03,0xd2,0x00 } },
-{  16, 0xc430, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xe1,0x00,0x32,0x40 } },
-{  16, 0xc440, 0, {0x0c,0x90,0x43,0xe4,0x20,0xd9,0x00,0x3c,0x44,0x08,0x90,0x03,0x24,0x00,0xf9,0x01 } },
-{  16, 0xc450, 0, {0x3e,0x48,0x0f,0x10,0x43,0x25,0x00,0xc9,0x00,0xb2,0x40,0x0c,0x90,0x03,0x02,0x04 } },
-{  16, 0xc460, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x00,0xa0,0x40 } },
-{  16, 0xc470, 0, {0x08,0x98,0x02,0xe6,0x08,0xa9,0x60,0x2e,0x49,0x08,0x94,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0xc480, 0, {0x2e,0x70,0x0b,0x90,0x02,0x26,0x02,0x89,0x00,0xa0,0x40,0x0a,0x90,0x0a,0x20,0x00 } },
-{  16, 0xc490, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x00,0x22,0x40 } },
-{  16, 0xc4a0, 0, {0x08,0x98,0x04,0xe6,0x00,0x99,0x80,0x2e,0x40,0x0a,0xb1,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0xc4b0, 0, {0x0e,0x40,0x0b,0x90,0x0a,0x04,0x00,0x81,0x01,0x22,0xc0,0x08,0x10,0x02,0x06,0x00 } },
-{  16, 0xc4c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0xb1,0x20,0x22,0x48 } },
-{  16, 0xc4d0, 0, {0x08,0x18,0x06,0xc4,0x00,0xa1,0x00,0x2c,0x48,0x2a,0x30,0x02,0x04,0x80,0xb1,0x22 } },
-{  16, 0xc4e0, 0, {0x2c,0x48,0x0b,0x12,0x02,0x05,0x80,0x81,0x60,0x22,0x50,0x0a,0x14,0x02,0x02,0x01 } },
-{  16, 0xc4f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x50,0x32,0x14 } },
-{  16, 0xc500, 0, {0x0c,0x85,0x03,0xe1,0x40,0xd8,0x50,0x3e,0x14,0x0e,0x80,0x0b,0x21,0x40,0xfa,0x00 } },
-{  16, 0xc510, 0, {0x3e,0x94,0x0f,0x85,0x03,0x20,0x00,0xc0,0x00,0x32,0x00,0x0c,0x80,0x03,0x2e,0x03 } },
-{  16, 0xc520, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x41,0xf9,0x10,0x3d,0x45 } },
-{  16, 0xc530, 0, {0x0f,0xd0,0x03,0xf4,0x00,0xff,0x00,0x3f,0x45,0x0d,0xd0,0x03,0xe4,0x40,0xf9,0x10 } },
-{  16, 0xc540, 0, {0x3f,0x44,0x0f,0x91,0x03,0xe4,0x42,0xf9,0x10,0x3f,0x40,0x0f,0xd4,0x03,0xe6,0x06 } },
-{  16, 0xc550, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe4,0x00,0xf9,0x00,0x3e,0x40 } },
-{  16, 0xc560, 0, {0x0c,0xd0,0x03,0xf4,0x08,0x8d,0x02,0x3f,0x40,0x0f,0xd0,0x03,0xe4,0x00,0xcd,0x00 } },
-{  16, 0xc570, 0, {0x33,0x40,0x0c,0x90,0x03,0x24,0x00,0xf9,0x00,0x32,0x40,0x4c,0x98,0x23,0x06,0x00 } },
-{  16, 0xc580, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0xe8,0x00,0x2e,0x00 } },
-{  16, 0xc590, 0, {0x48,0x80,0x02,0xe8,0x00,0xd0,0x00,0x2e,0x80,0x0b,0x80,0x12,0xe0,0x02,0x88,0x00 } },
-{  16, 0xc5a0, 0, {0xa2,0x00,0x0a,0x80,0x12,0x22,0x00,0xb8,0x81,0x22,0x28,0x08,0xcf,0x02,0x0e,0x04 } },
-{  16, 0xc5b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x2c,0x40 } },
-{  16, 0xc5c0, 0, {0x28,0x10,0x02,0xc4,0x00,0x81,0x00,0x2c,0x40,0x0b,0x10,0x02,0xc4,0x00,0x91,0x00 } },
-{  16, 0xc5d0, 0, {0x26,0x40,0x09,0x10,0x02,0x54,0xa0,0xb5,0x2c,0xa5,0x42,0x08,0x50,0x82,0x02,0x01 } },
-{  16, 0xc5e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0xa9,0x00,0x2e,0x50 } },
-{  16, 0xc5f0, 0, {0x58,0x90,0x02,0xe4,0x80,0x9b,0x00,0x2e,0x45,0x8b,0x92,0x02,0xe4,0x00,0x99,0x00 } },
-{  16, 0xc600, 0, {0x26,0x44,0x0b,0x90,0x02,0x64,0x08,0xb5,0x00,0x25,0x4a,0x08,0x51,0x02,0x06,0x04 } },
-{  16, 0xc610, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x00,0x3e,0x54 } },
-{  16, 0xc620, 0, {0x0c,0x90,0x43,0xc4,0x00,0xc9,0x90,0x3e,0x70,0x0f,0x98,0x03,0xe4,0x00,0xd9,0x00 } },
-{  16, 0xc630, 0, {0x34,0x60,0x4d,0x90,0x0a,0x64,0x00,0xf9,0x00,0x36,0x40,0x2c,0x9e,0x03,0x28,0x04 } },
-{  16, 0xc640, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x00,0x3c,0x40 } },
-{  16, 0xc650, 0, {0x0f,0x9c,0x03,0xe6,0x30,0xf9,0x00,0x3e,0x62,0x0f,0x90,0x03,0xe4,0x00,0xe9,0x00 } },
-{  16, 0xc660, 0, {0x3a,0x40,0x4e,0x90,0x03,0xa4,0x00,0x79,0x0c,0x3a,0x40,0x0f,0x90,0x1b,0xca,0x00 } },
-{  16, 0xc670, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x00,0x3e,0x00 } },
-{  16, 0xc680, 0, {0x0c,0x81,0x13,0xe1,0x08,0xc8,0x48,0x32,0x00,0x3c,0x80,0x03,0xc0,0x00,0xf0,0x10 } },
-{  16, 0xc690, 0, {0x3e,0x06,0x0c,0x80,0x03,0xf0,0x08,0xcc,0x00,0x33,0x04,0x0c,0xc0,0x03,0x0a,0x04 } },
-{  16, 0xc6a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xba,0x00,0x2e,0x80 } },
-{  16, 0xc6b0, 0, {0x08,0xec,0x42,0xfa,0x20,0x8e,0x00,0x23,0xa0,0x08,0xe8,0x42,0xe8,0x00,0xbe,0x80 } },
-{  16, 0xc6c0, 0, {0x2f,0x80,0x08,0xa0,0x02,0xe8,0x00,0xda,0x00,0x22,0x80,0x48,0xe0,0x02,0x0a,0x00 } },
-{  16, 0xc6d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb3,0x00,0x2c,0xc0 } },
-{  16, 0xc6e0, 0, {0x09,0x34,0x82,0xc9,0x00,0x83,0x80,0x20,0xf0,0x08,0x30,0x82,0xcc,0x00,0xb3,0x80 } },
-{  16, 0xc6f0, 0, {0x2c,0xf0,0x08,0xb0,0x02,0xc1,0x20,0x80,0x00,0xa0,0x32,0x08,0x00,0x02,0x0a,0x00 } },
-{  16, 0xc700, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0xc0,0xb7,0x01,0x2f,0xc8 } },
-{  16, 0xc710, 0, {0x89,0x50,0x02,0xd8,0x02,0x87,0xc4,0x21,0xe2,0x48,0x70,0x82,0xdc,0x00,0xb7,0x00 } },
-{  16, 0xc720, 0, {0x2c,0x40,0x08,0x72,0x02,0xce,0x00,0x97,0x08,0x23,0xc0,0x08,0x70,0x02,0x28,0x00 } },
-{  16, 0xc730, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf7,0xe1,0x3d,0xe8 } },
-{  16, 0xc740, 0, {0x2d,0x68,0x03,0xf2,0x00,0xc7,0x80,0xb0,0xe0,0x08,0x68,0x03,0xdf,0x80,0xf6,0x80 } },
-{  16, 0xc750, 0, {0x3d,0xe0,0x8c,0x7e,0x03,0xda,0x00,0xcc,0x80,0x31,0x20,0x0c,0xc8,0x0b,0x2a,0x02 } },
-{  16, 0xc760, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x08,0xfb,0x00,0x3c,0xc0 } },
-{  16, 0xc770, 0, {0x0e,0x80,0x03,0xe0,0x08,0xf9,0x00,0x3e,0x40,0x0f,0xb0,0x02,0xec,0x00,0xfa,0x00 } },
-{  16, 0xc780, 0, {0x3e,0x40,0x2f,0xb0,0x03,0xe4,0x00,0xfb,0x00,0x3c,0xc0,0x2f,0xb0,0x03,0xc2,0x06 } },
-{  16, 0xc790, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xff,0x92,0x7f,0xea } },
-{  16, 0xc7a0, 0, {0x0c,0xf8,0x03,0xfe,0x00,0xcc,0xa0,0x3f,0x20,0x0d,0xf9,0x03,0x3e,0x00,0xcf,0x80 } },
-{  16, 0xc7b0, 0, {0x33,0x60,0x0f,0xf8,0x03,0xf6,0x00,0xef,0x84,0x33,0xe0,0x2c,0xc8,0x03,0x00,0x00 } },
-{  16, 0xc7c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xb7,0x00,0x2f,0xc8 } },
-{  16, 0xc7d0, 0, {0x08,0x54,0x02,0xd8,0x00,0xd6,0x04,0x2d,0x01,0x08,0x69,0x02,0x1c,0x00,0x85,0x00 } },
-{  16, 0xc7e0, 0, {0x21,0x43,0x0b,0x70,0x03,0x9a,0xc0,0x8c,0x00,0xa3,0x02,0x08,0xf1,0x02,0x2a,0x04 } },
-{  16, 0xc7f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x01,0x2d,0xcc } },
-{  16, 0xc800, 0, {0x08,0x70,0x02,0xd4,0x00,0x94,0x28,0x2d,0xc2,0x08,0xc2,0x02,0x5c,0x00,0x86,0x00 } },
-{  16, 0xc810, 0, {0x21,0x80,0x0b,0x71,0x02,0xdc,0x00,0xa7,0x10,0x21,0xc0,0x08,0x48,0x02,0x40,0x00 } },
-{  16, 0xc820, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x08,0xb3,0x00,0x2c,0xf0 } },
-{  16, 0xc830, 0, {0x08,0x05,0x02,0xc0,0x20,0x90,0x80,0x2e,0x00,0x08,0x00,0x82,0x4c,0x02,0x80,0x00 } },
-{  16, 0xc840, 0, {0xa0,0x61,0x0b,0x30,0x02,0xa0,0x00,0x80,0x00,0xa0,0x30,0x88,0xb1,0x0a,0x48,0x04 } },
-{  16, 0xc850, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xff,0x00,0x2d,0xc8 } },
-{  16, 0xc860, 0, {0x0c,0x3d,0x03,0xe4,0x00,0xdb,0x02,0x3e,0xf0,0x2c,0x90,0x4b,0x7c,0x00,0xc1,0x00 } },
-{  16, 0xc870, 0, {0x32,0x20,0x4f,0xf0,0x13,0xe0,0x00,0xe8,0x01,0x32,0x00,0x8c,0xac,0x03,0x6a,0x04 } },
-{  16, 0xc880, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x04,0x3e,0xc2 } },
-{  16, 0xc890, 0, {0x4f,0xb0,0x03,0xe0,0x04,0xfa,0x40,0x3e,0xc2,0x4e,0x98,0x23,0xac,0x10,0xf8,0x00 } },
-{  16, 0xc8a0, 0, {0x3e,0x50,0x07,0xb0,0x13,0xac,0x00,0xfb,0x00,0x3e,0xc2,0x0f,0x92,0x03,0xa0,0x00 } },
-{  16, 0xc8b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xcf,0x00,0x3f,0xc0 } },
-{  16, 0xc8c0, 0, {0x0c,0xc8,0x23,0x36,0x82,0xcf,0x80,0x3f,0x80,0x0c,0xe0,0x03,0xec,0x00,0xf9,0x20 } },
-{  16, 0xc8d0, 0, {0x33,0xc0,0x0e,0xf0,0x03,0xf8,0x10,0xdc,0x00,0x33,0x00,0x4c,0xe8,0x21,0x00,0x44 } },
-{  16, 0xc8e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x00,0xab,0x00,0x2e,0xc0 } },
-{  16, 0xc8f0, 0, {0x4a,0x8d,0x42,0x21,0x00,0x8b,0x42,0x2e,0xd2,0x08,0xb0,0x03,0xec,0x00,0xb8,0x88 } },
-{  16, 0xc900, 0, {0x34,0x62,0x0d,0xb0,0x02,0xe4,0x00,0x8b,0x00,0x22,0xc0,0x08,0x90,0x0a,0x20,0x40 } },
-{  16, 0xc910, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x00,0x2e,0xc0 } },
-{  16, 0xc920, 0, {0x08,0xa0,0x02,0x0d,0x00,0x89,0x10,0x2e,0x08,0x28,0x92,0x02,0xec,0x04,0xbb,0x00 } },
-{  16, 0xc930, 0, {0x22,0xa0,0x08,0xb0,0x02,0x64,0x02,0xb3,0x02,0x20,0xc0,0x08,0xa2,0x02,0xa0,0x00 } },
-{  16, 0xc940, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xa3,0x00,0x2e,0xc0 } },
-{  16, 0xc950, 0, {0x0a,0x90,0x22,0x0c,0x10,0x80,0x00,0x2c,0x00,0x18,0x02,0x82,0xcc,0x00,0xb0,0x00 } },
-{  16, 0xc960, 0, {0x26,0x40,0x09,0x30,0x02,0xc8,0x20,0x80,0x00,0x20,0x00,0x08,0x10,0x06,0x82,0x01 } },
-{  16, 0xc970, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xcb,0x00,0x2e,0xc0 } },
-{  16, 0xc980, 0, {0x0c,0xa1,0x02,0x24,0x00,0x88,0x00,0x3c,0x00,0x0c,0x80,0x03,0xec,0x00,0xfb,0x00 } },
-{  16, 0xc990, 0, {0x32,0x80,0x0e,0xb0,0x03,0xcc,0x80,0xdb,0x00,0x32,0xc0,0x0c,0xa0,0x03,0x80,0x03 } },
-{  16, 0xc9a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x3f,0xc0 } },
-{  16, 0xc9b0, 0, {0x4f,0xc2,0x13,0xd4,0x10,0xfc,0x00,0x3f,0x00,0x0f,0x00,0x03,0xbc,0x00,0xfc,0x00 } },
-{  16, 0xc9c0, 0, {0x3f,0x40,0x0f,0xf0,0x23,0xe0,0x12,0xfc,0x01,0xbf,0x00,0x0f,0xd0,0x03,0x68,0x02 } },
-{  16, 0xc9d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xc7,0x80,0x33,0xc0 } },
-{  16, 0xc9e0, 0, {0x8b,0xb4,0x03,0xb0,0xc0,0xcf,0x2e,0x1f,0x0c,0x4f,0xc3,0x03,0x30,0x80,0xff,0x01 } },
-{  16, 0xc9f0, 0, {0x3f,0x08,0x0f,0xf0,0x00,0x7c,0x00,0xff,0x21,0x33,0xe4,0x0c,0xe0,0x03,0x30,0x00 } },
-{  16, 0xca00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xee,0x00,0x8b,0x82,0x23,0xf0 } },
-{  16, 0xca10, 0, {0x0b,0xb5,0x12,0x0d,0x88,0x88,0xc0,0x0e,0x98,0x0b,0x86,0x02,0x21,0x00,0xbb,0xc0 } },
-{  16, 0xca20, 0, {0x2e,0xe4,0x4b,0xf7,0x83,0x2f,0x44,0xbf,0x90,0x22,0xc8,0x48,0xa6,0x82,0x20,0x04 } },
-{  16, 0xca30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x09,0x8a,0x00,0x20,0x50 } },
-{  16, 0xca40, 0, {0x4b,0xb2,0x0a,0x80,0xcc,0x83,0x01,0x0c,0x8c,0x0b,0x23,0x0a,0x04,0x60,0xb3,0x14 } },
-{  16, 0xca50, 0, {0x24,0x40,0x4b,0x30,0x02,0xcc,0x10,0xb3,0x00,0x20,0xc8,0xe9,0x11,0x06,0x62,0x01 } },
-{  16, 0xca60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x01,0x8a,0x80,0xa2,0x44 } },
-{  16, 0xca70, 0, {0x0b,0xb0,0x02,0xa1,0x04,0x88,0x40,0x2e,0xa0,0x0b,0x20,0x02,0x28,0x20,0xbb,0x40 } },
-{  16, 0xca80, 0, {0x2e,0x40,0x0b,0xb0,0x02,0x2c,0x08,0xbb,0x00,0x22,0xc0,0x09,0xb0,0x02,0x70,0x04 } },
-{  16, 0xca90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xc3,0x83,0x32,0xe0 } },
-{  16, 0xcaa0, 0, {0x8f,0x00,0x03,0xa0,0x02,0xcb,0xc4,0x3e,0x28,0x07,0x8b,0x03,0x21,0x00,0xf9,0xc0 } },
-{  16, 0xcab0, 0, {0x3e,0x10,0x0f,0xb0,0x03,0xec,0x00,0x7b,0x00,0x32,0xc0,0x0d,0xa0,0x03,0x50,0x04 } },
-{  16, 0xcac0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x9c,0x02,0xff,0x00,0x3f,0xe0 } },
-{  16, 0xcad0, 0, {0x0f,0xf4,0x43,0x5e,0x80,0xfc,0x94,0x3f,0x00,0x0f,0xc0,0x2b,0xf2,0x50,0xfd,0x21 } },
-{  16, 0xcae0, 0, {0x7e,0x84,0x8f,0xf0,0x03,0x6c,0x0c,0xff,0x00,0x3f,0xc0,0x0e,0x62,0x03,0xb8,0x00 } },
-{  16, 0xcaf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xeb,0x00,0x32,0x40 } },
-{  16, 0xcb00, 0, {0x2c,0x80,0x03,0x69,0x00,0xcb,0x30,0xb2,0x00,0x4f,0xb3,0x43,0xe5,0x00,0xcb,0x40 } },
-{  16, 0xcb10, 0, {0x72,0x18,0x2c,0xb0,0x03,0xec,0x28,0xc3,0x21,0x3a,0xc1,0x0f,0x94,0x03,0x10,0x04 } },
-{  16, 0xcb20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3c,0x00,0x8b,0x20,0x22,0x50 } },
-{  16, 0xcb30, 0, {0x08,0xb0,0x02,0x28,0x00,0x88,0xc0,0x2a,0x00,0x8b,0xb4,0x02,0xe8,0x00,0xdb,0x00 } },
-{  16, 0xcb40, 0, {0x62,0x30,0x08,0xf0,0x02,0xfc,0x00,0x8f,0x80,0x22,0xc0,0x0b,0x95,0x47,0x32,0x00 } },
-{  16, 0xcb50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb1,0x00,0x20,0xc2 } },
-{  16, 0xcb60, 0, {0x48,0x30,0x02,0x49,0x80,0x83,0x42,0x60,0x12,0x0b,0x30,0x02,0xc8,0x00,0x82,0x02 } },
-{  16, 0xcb70, 0, {0x2c,0x30,0x09,0xb0,0x02,0xcf,0x01,0x83,0x50,0x2a,0xc0,0x0b,0x20,0x02,0xb8,0x00 } },
-{  16, 0xcb80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0x9d,0x80,0xa0,0xe0 } },
-{  16, 0xcb90, 0, {0x08,0x79,0x22,0x5e,0x60,0x87,0x90,0x29,0xa0,0x0b,0x78,0x02,0xc6,0x00,0x92,0x81 } },
-{  16, 0xcba0, 0, {0x05,0xe0,0x09,0x78,0x02,0xde,0x40,0x87,0x80,0x21,0xe0,0x0b,0x29,0x02,0x08,0x00 } },
-{  16, 0xcbb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x40,0xf2,0x00,0x30,0xc0 } },
-{  16, 0xcbc0, 0, {0x08,0x3a,0x03,0x44,0x04,0xc3,0x14,0x30,0xc0,0x0f,0x22,0x03,0xcc,0x80,0xc2,0x00 } },
-{  16, 0xcbd0, 0, {0xa4,0xd2,0x0d,0x30,0x13,0xcc,0x20,0xc3,0x00,0x38,0xc4,0x4f,0x04,0x43,0x12,0x02 } },
-{  16, 0xcbe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x9c,0x00,0xee,0x00,0x3f,0xe0 } },
-{  16, 0xcbf0, 0, {0x0f,0x70,0x03,0xb4,0x02,0xf4,0x10,0x3f,0xc0,0x8f,0xa0,0x03,0xfc,0x00,0x7e,0x00 } },
-{  16, 0xcc00, 0, {0x3b,0xc0,0x0e,0xf0,0x83,0xec,0x00,0xf7,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xd0,0x06 } },
-{  16, 0xcc10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xfc,0x00,0xf9,0x00,0x3e,0xc0 } },
-{  16, 0xcc20, 0, {0x0f,0xa0,0x03,0xaa,0x12,0xcb,0x01,0x32,0x80,0x0f,0xb0,0x13,0x28,0x14,0xf9,0x80 } },
-{  16, 0xcc30, 0, {0x3a,0x40,0x03,0xb4,0x03,0xec,0x42,0xcb,0x18,0x3e,0xc0,0x0f,0xb0,0x03,0x2a,0x00 } },
-{  16, 0xcc40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9d,0x00,0xb5,0x00,0x2d,0xc4 } },
-{  16, 0xcc50, 0, {0x0b,0x70,0x4b,0x7c,0x00,0x84,0x00,0x21,0x80,0x0b,0x70,0x02,0x94,0x10,0xb2,0x00 } },
-{  16, 0xcc60, 0, {0x29,0xc0,0x0b,0x72,0x82,0xdc,0x00,0x87,0x20,0x2d,0xc1,0x0e,0x70,0x02,0x12,0x04 } },
-{  16, 0xcc70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x80,0x2d,0xe0 } },
-{  16, 0xcc80, 0, {0x0b,0x68,0x02,0x9e,0x00,0x83,0x80,0x21,0xe0,0x5b,0x38,0x02,0x1e,0x00,0xb4,0xc0 } },
-{  16, 0xcc90, 0, {0x25,0xe0,0x09,0x78,0x32,0xce,0x00,0x97,0x80,0x2d,0xe0,0x0b,0x5c,0x4e,0x30,0x00 } },
-{  16, 0xcca0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0x44,0x2c,0xc0 } },
-{  16, 0xccb0, 0, {0x0b,0x3c,0x02,0xcc,0x40,0x93,0x08,0x20,0xe0,0x0b,0x30,0x02,0x8c,0x10,0xb3,0xc0 } },
-{  16, 0xccc0, 0, {0x28,0xd8,0x1b,0x30,0x02,0xcc,0x08,0x93,0x01,0x6c,0xc0,0x0a,0xb8,0x82,0x12,0x04 } },
-{  16, 0xccd0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xf6,0x10,0x3e,0x80 } },
-{  16, 0xcce0, 0, {0x4b,0xed,0x83,0xb8,0x00,0xce,0xe4,0xb3,0xa3,0x0f,0xe0,0x03,0x38,0x00,0xfe,0x00 } },
-{  16, 0xccf0, 0, {0x3b,0x80,0x0d,0xa0,0x02,0xe8,0x00,0xda,0x00,0x3e,0x80,0x0f,0xe8,0x02,0x3a,0x04 } },
-{  16, 0xcd00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x10,0xf8,0x40,0x3e,0x00 } },
-{  16, 0xcd10, 0, {0x0f,0x80,0x13,0x60,0x00,0xe0,0x00,0x3e,0x00,0x43,0x08,0x03,0xe0,0x00,0xf8,0x08 } },
-{  16, 0xcd20, 0, {0x3a,0x00,0x0f,0x80,0x03,0xe0,0x00,0xe8,0x40,0x3e,0x00,0x0e,0x80,0x23,0xd2,0x00 } },
-{  16, 0xcd30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xc4,0x00,0xd9,0xc0,0xbe,0x40 } },
-{  16, 0xcd40, 0, {0x0f,0x90,0x03,0xe6,0x00,0xf9,0x00,0x32,0x40,0x01,0x9a,0x03,0x24,0x00,0xf9,0x00 } },
-{  16, 0xcd50, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc4,0x40,0x09,0x10,0x0e,0x40,0x0f,0x9a,0x03,0x02,0x04 } },
-{  16, 0xcd60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x04,0x89,0x04,0xa2,0x60 } },
-{  16, 0xcd70, 0, {0x8b,0x9d,0x80,0xa6,0x00,0xb9,0x80,0x22,0x40,0x48,0x98,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0xcd80, 0, {0x2e,0x40,0x8b,0x90,0x02,0xe4,0x94,0x89,0x60,0x2e,0x40,0x0b,0x94,0x0b,0x20,0x00 } },
-{  16, 0xcd90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x99,0x08,0xae,0x48 } },
-{  16, 0xcda0, 0, {0x4b,0x10,0x02,0xe5,0x81,0xb9,0x10,0x20,0x44,0x1b,0x94,0x02,0x24,0x10,0xb9,0x00 } },
-{  16, 0xcdb0, 0, {0x6e,0x60,0x0b,0x90,0x02,0xe4,0x00,0x89,0x00,0x2e,0x40,0x0b,0x94,0x02,0x06,0x00 } },
-{  16, 0xcdc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0x89,0x00,0xa0,0x68 } },
-{  16, 0xcdd0, 0, {0x0b,0x12,0x02,0x84,0x89,0xb1,0x20,0x20,0x48,0x1a,0x12,0x12,0x04,0x80,0xb1,0x22 } },
-{  16, 0xcde0, 0, {0x0c,0x48,0x0b,0x12,0x02,0xc4,0x81,0xa1,0x20,0x2c,0x40,0x0b,0x12,0x02,0x02,0x01 } },
-{  16, 0xcdf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xd8,0x00,0xbe,0x00 } },
-{  16, 0xce00, 0, {0x0f,0x05,0x0b,0xe1,0x40,0xf8,0x00,0x32,0x14,0x0f,0x85,0x03,0x21,0x40,0xf8,0x00 } },
-{  16, 0xce10, 0, {0x2e,0x80,0x0f,0x85,0x13,0xe0,0x02,0xc8,0x00,0x3e,0x14,0x0f,0x05,0x01,0x2e,0x03 } },
-{  16, 0xce20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x40,0xfd,0x00,0xbf,0x44 } },
-{  16, 0xce30, 0, {0x0f,0xd1,0x03,0xf4,0x40,0x7d,0x10,0xbf,0x44,0x45,0xf1,0x2b,0xf4,0x40,0xfd,0x10 } },
-{  16, 0xce40, 0, {0x3f,0x44,0x0f,0x91,0x03,0xe4,0x40,0xd9,0x10,0x3e,0x40,0x0f,0xd1,0x03,0xa6,0x06 } },
-{  16, 0xce50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x00,0xfd,0x00,0x1f,0x62 } },
-{  16, 0xce60, 0, {0x0f,0xd8,0x82,0x36,0x00,0xbd,0xa0,0x3b,0x68,0x0c,0xdc,0x83,0x26,0xc8,0xd9,0xa0 } },
-{  16, 0xce70, 0, {0x33,0x60,0x0d,0x99,0x83,0x56,0x20,0xd5,0xa8,0x2e,0x44,0x0c,0xd8,0x83,0x86,0x04 } },
-{  16, 0xce80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x48,0xb8,0x00,0x2e,0x00 } },
-{  16, 0xce90, 0, {0x0b,0x0a,0x82,0x22,0x20,0xb8,0x50,0x22,0xba,0x08,0x8a,0x22,0x22,0x80,0x88,0x00 } },
-{  16, 0xcea0, 0, {0x22,0x01,0x08,0x0c,0x02,0x20,0x00,0x88,0x00,0x2e,0x28,0x88,0x88,0x02,0xce,0x04 } },
-{  16, 0xceb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x2c,0x40 } },
-{  16, 0xcec0, 0, {0x1b,0x10,0x0a,0x84,0x40,0xb1,0x00,0x28,0x58,0x0a,0x32,0x02,0x05,0x00,0x99,0x40 } },
-{  16, 0xced0, 0, {0x20,0x65,0x09,0x10,0x42,0xc4,0x00,0x91,0x00,0x2c,0x40,0x0a,0x30,0x82,0xc2,0x01 } },
-{  16, 0xcee0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0xb9,0x00,0x2e,0x40 } },
-{  16, 0xcef0, 0, {0x1b,0x90,0x02,0xa5,0x80,0xb9,0x10,0x22,0x48,0x08,0x10,0x42,0x04,0x10,0x09,0x00 } },
-{  16, 0xcf00, 0, {0x22,0x40,0x08,0x90,0x02,0xe4,0x00,0x9b,0x00,0x2c,0x40,0x0a,0x94,0x22,0xc6,0x04 } },
-{  16, 0xcf10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x20,0x3e,0x40 } },
-{  16, 0xcf20, 0, {0x0f,0x90,0x13,0xa7,0x10,0xf9,0x60,0xba,0x50,0x2e,0x9c,0x0a,0x25,0x84,0xd1,0xf0 } },
-{  16, 0xcf30, 0, {0xb2,0x60,0x0d,0x90,0x03,0xe4,0x00,0xd9,0x00,0x3e,0x40,0x0e,0x90,0x03,0xa8,0x00 } },
-{  16, 0xcf40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x0c,0xf9,0x90,0x3e,0x6a } },
-{  16, 0xcf50, 0, {0x8f,0x90,0x23,0x66,0x00,0xf1,0x08,0x3c,0x40,0x0f,0x9c,0x43,0xe4,0x40,0xf9,0x80 } },
-{  16, 0xcf60, 0, {0x3a,0x44,0x0f,0x90,0x03,0x24,0x04,0xe9,0x02,0x3e,0x40,0x2d,0x91,0x13,0xca,0x00 } },
-{  16, 0xcf70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xe8,0x20,0x3e,0x01 } },
-{  16, 0xcf80, 0, {0x0c,0x00,0x03,0xa1,0x20,0xe8,0x50,0x32,0x10,0x2c,0x8c,0x03,0x21,0x00,0xe8,0x00 } },
-{  16, 0xcf90, 0, {0x32,0x02,0x0f,0x00,0x13,0x20,0x88,0xc8,0x08,0x32,0x00,0x0f,0x8c,0x03,0xca,0x00 } },
-{  16, 0xcfa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x20,0x8e,0xe3,0x2f,0x90 } },
-{  16, 0xcfb0, 0, {0x0a,0xe0,0x06,0x3b,0x00,0xee,0x04,0x23,0x90,0x08,0xe0,0x02,0x28,0x08,0x8a,0x02 } },
-{  16, 0xcfc0, 0, {0x75,0x90,0x8b,0xa0,0x41,0x58,0x90,0x8e,0x80,0x2a,0x81,0x0b,0xe0,0x03,0x8a,0x10 } },
-{  16, 0xcfd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4e,0x00,0xa3,0x00,0x6c,0x60 } },
-{  16, 0xcfe0, 0, {0x08,0x38,0x1a,0x8e,0x40,0xa0,0x80,0x20,0xcc,0x09,0x30,0x02,0x0c,0x05,0xa3,0x04 } },
-{  16, 0xcff0, 0, {0x28,0xc4,0x0b,0x30,0x02,0x0d,0x01,0x83,0xc0,0x20,0xc0,0x0b,0x30,0x02,0xca,0x00 } },
-{  16, 0xd000, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x08,0x87,0x00,0x2d,0x62 } },
-{  16, 0xd010, 0, {0x0b,0x70,0x92,0x1c,0x08,0xa0,0x00,0x61,0xc0,0x09,0x60,0x06,0x1c,0x80,0xa7,0x00 } },
-{  16, 0xd020, 0, {0x21,0xc0,0x0b,0x72,0x02,0x58,0x01,0x87,0x88,0x29,0xc0,0x0b,0x60,0x12,0xa8,0x00 } },
-{  16, 0xd030, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xe6,0x80,0x3d,0x60 } },
-{  16, 0xd040, 0, {0x0c,0x78,0x42,0x96,0x00,0xe4,0x80,0xa3,0x60,0x0d,0x78,0x03,0x3f,0x00,0xe3,0x80 } },
-{  16, 0xd050, 0, {0x21,0xe0,0x0f,0x7b,0x03,0x16,0x08,0xc7,0x80,0x31,0xe2,0x4f,0x78,0x43,0xea,0x02 } },
-{  16, 0xd060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0x8c,0x01,0xf8,0x00,0x3c,0x40 } },
-{  16, 0xd070, 0, {0x0e,0xb0,0x02,0xec,0x00,0xf8,0x01,0x3e,0x40,0x4e,0x30,0x33,0xed,0x20,0xdb,0x01 } },
-{  16, 0xd080, 0, {0xbe,0xc0,0x0f,0xb4,0x03,0xec,0x00,0xfb,0x00,0x3e,0xd8,0x0f,0xa0,0x03,0xc2,0x06 } },
-{  16, 0xd090, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xc7,0x84,0x23,0x60 } },
-{  16, 0xd0a0, 0, {0x0c,0x78,0x0b,0xbe,0x00,0xfd,0x80,0x3f,0xe0,0x0f,0xeb,0x03,0x3e,0x00,0xcf,0x80 } },
-{  16, 0xd0b0, 0, {0x3b,0x25,0x0c,0xf8,0x83,0x7e,0x40,0xcd,0x80,0x33,0xe2,0x0b,0xf9,0x03,0x00,0x00 } },
-{  16, 0xd0c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x02,0x87,0x00,0x15,0x48 } },
-{  16, 0xd0d0, 0, {0x08,0x70,0x02,0x14,0x20,0xb6,0x00,0x35,0x9a,0x49,0xc8,0x03,0x9c,0x84,0xa7,0x00 } },
-{  16, 0xd0e0, 0, {0x39,0xd0,0x0a,0x70,0x02,0x1a,0x08,0xa4,0x00,0x21,0xc0,0x09,0x61,0x42,0x2a,0x04 } },
-{  16, 0xd0f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x87,0x00,0x21,0x40 } },
-{  16, 0xd100, 0, {0x08,0x71,0x02,0x94,0x00,0xb5,0x00,0x2d,0x40,0x0b,0xf1,0x22,0x5c,0x02,0x07,0x08 } },
-{  16, 0xd110, 0, {0x2c,0x50,0x08,0x70,0x02,0x50,0x00,0x87,0x00,0x2d,0xc4,0x0b,0x50,0x42,0x00,0x00 } },
-{  16, 0xd120, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0x83,0x02,0x24,0x40 } },
-{  16, 0xd130, 0, {0x18,0x3d,0x0a,0x01,0x00,0xb0,0x58,0x24,0x20,0x09,0x30,0x02,0x8f,0x40,0x83,0xe0 } },
-{  16, 0xd140, 0, {0x2c,0xc1,0x0a,0x30,0x42,0x08,0x00,0xb3,0x01,0x6c,0xc0,0x09,0x08,0x16,0x08,0x04 } },
-{  16, 0xd150, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0x8c,0x00,0x8b,0x00,0x32,0x40 } },
-{  16, 0xd160, 0, {0x0c,0x25,0x03,0xa8,0x48,0xf8,0x81,0x3e,0x80,0x0f,0x80,0x63,0x7c,0x00,0xcb,0x80 } },
-{  16, 0xd170, 0, {0x3a,0xc0,0x0c,0xf0,0x03,0x6c,0x00,0xca,0x02,0xbf,0xc0,0x0f,0x98,0x8b,0x2a,0x04 } },
-{  16, 0xd180, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xf9,0x00,0x3e,0x50 } },
-{  16, 0xd190, 0, {0x2f,0xa4,0x0b,0xc8,0x00,0xf0,0x40,0x3e,0xd0,0x0f,0xa0,0x33,0xec,0x20,0xfb,0x04 } },
-{  16, 0xd1a0, 0, {0x7a,0xe0,0x0f,0xb0,0x03,0xed,0x08,0xe9,0x03,0x32,0xc0,0x0d,0x90,0x03,0xe0,0x00 } },
-{  16, 0xd1b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xec,0x40,0xee,0x00,0x3e,0xc0 } },
-{  16, 0xd1c0, 0, {0x0c,0xda,0x03,0x70,0x04,0xcc,0x02,0xb1,0xa0,0x0e,0xf0,0x23,0xec,0x00,0xff,0x00 } },
-{  16, 0xd1d0, 0, {0x37,0x20,0xcd,0xb0,0x73,0xec,0x88,0xfb,0x80,0x3f,0xc0,0x0f,0x30,0x03,0x00,0x44 } },
-{  16, 0xd1e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6e,0x00,0x88,0x80,0x2c,0xe1 } },
-{  16, 0xd1f0, 0, {0x08,0x94,0x0a,0xa9,0x02,0x88,0x40,0x22,0xd0,0x08,0xb9,0x42,0xec,0x04,0xbb,0x00 } },
-{  16, 0xd200, 0, {0x2c,0xd4,0x0d,0xb0,0x02,0xed,0x20,0xbb,0xd0,0x2e,0xc0,0x0b,0xb0,0x02,0xa0,0x40 } },
-{  16, 0xd210, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x24,0x00,0xab,0x80,0x2e,0xf0 } },
-{  16, 0xd220, 0, {0x29,0xa0,0x82,0x6d,0x00,0x88,0x08,0x22,0x04,0x08,0x90,0x42,0xec,0x00,0xbb,0x00 } },
-{  16, 0xd230, 0, {0x2a,0x81,0x08,0xb0,0x02,0xe4,0x09,0xba,0x04,0x2e,0xc1,0x4b,0x98,0x82,0x20,0x00 } },
-{  16, 0xd240, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x83,0x00,0x2c,0xc0 } },
-{  16, 0xd250, 0, {0x0a,0x21,0x02,0x84,0x10,0x82,0x00,0xe0,0x00,0x18,0x0a,0x12,0xcc,0x00,0xb3,0x00 } },
-{  16, 0xd260, 0, {0x0c,0xc0,0x09,0x30,0x02,0xcc,0x90,0xb0,0x00,0x2c,0xc0,0x0b,0x10,0x02,0x82,0x01 } },
-{  16, 0xd270, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x64,0x00,0xeb,0x00,0x3e,0x00 } },
-{  16, 0xd280, 0, {0x2c,0xb4,0x03,0x64,0x08,0x88,0x00,0xb2,0x00,0x0c,0xb2,0x43,0xfc,0x00,0xfb,0x00 } },
-{  16, 0xd290, 0, {0x56,0x00,0x0c,0xf0,0x01,0xe4,0x00,0xfb,0x00,0x3f,0xc0,0x0f,0x80,0x0b,0x00,0x03 } },
-{  16, 0xd2a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf4,0x00,0xff,0x00,0x3f,0x40 } },
-{  16, 0xd2b0, 0, {0x2d,0xf0,0x61,0xf0,0x00,0xf4,0x00,0x27,0x01,0x0d,0xb1,0x11,0xfc,0x00,0xff,0x02 } },
-{  16, 0xd2c0, 0, {0x07,0xc0,0x0f,0xf0,0x03,0xec,0x40,0xff,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0x68,0x06 } },
-{  16, 0xd2d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf6,0x00,0xef,0x90,0x3d,0x4c } },
-{  16, 0xd2e0, 0, {0x2c,0xc0,0x13,0xf4,0x08,0xfd,0x20,0x37,0x4c,0x8e,0x82,0x83,0x74,0x84,0xdc,0xc2 } },
-{  16, 0xd2f0, 0, {0x3f,0xd8,0x0d,0xf2,0x03,0xec,0xc0,0xff,0x81,0x3f,0x00,0x0c,0xf8,0x03,0xf0,0x00 } },
-{  16, 0xd300, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe6,0x00,0x8b,0x24,0x2e,0x5c } },
-{  16, 0xd310, 0, {0x08,0x8d,0x02,0xff,0x48,0xb9,0x90,0x2f,0x54,0x0b,0x84,0x82,0x3e,0x40,0xa0,0x80 } },
-{  16, 0xd320, 0, {0x2e,0xc4,0x0a,0xfc,0x42,0xed,0x80,0xb9,0x80,0x2e,0x60,0x0a,0x98,0x12,0xe0,0x04 } },
-{  16, 0xd330, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xe4,0x01,0xa3,0x00,0x28,0x48 } },
-{  16, 0xd340, 0, {0x0a,0x00,0x42,0xc4,0x00,0xb1,0x00,0x2c,0x49,0x0b,0x0a,0x42,0x04,0xa2,0x91,0x21 } },
-{  16, 0xd350, 0, {0x2c,0xc9,0x08,0x31,0x02,0x8c,0xc1,0xa3,0x00,0x2c,0x40,0x08,0x18,0x02,0xa2,0x01 } },
-{  16, 0xd360, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa0,0x20,0x8b,0x82,0x2e,0x44 } },
-{  16, 0xd370, 0, {0x58,0x80,0x02,0xe4,0x00,0xbb,0x10,0x2e,0x40,0x0b,0xa1,0x12,0x0c,0x01,0x89,0x10 } },
-{  16, 0xd380, 0, {0x2e,0xc0,0x0a,0xb0,0x02,0xec,0x01,0xb8,0x80,0x2e,0xe2,0x0a,0xa1,0x02,0xf0,0x04 } },
-{  16, 0xd390, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xeb,0x40,0xeb,0x40,0x3e,0x60 } },
-{  16, 0xd3a0, 0, {0x0e,0x87,0x33,0xe4,0x00,0xb9,0xa1,0x36,0xc0,0x0e,0xa8,0x0b,0x26,0x00,0xda,0xc0 } },
-{  16, 0xd3b0, 0, {0x3e,0xc0,0x8d,0xb0,0x03,0xec,0x00,0xfb,0x85,0x3e,0xe1,0x08,0xb8,0x03,0x90,0x05 } },
-{  16, 0xd3c0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x00,0xff,0x02,0x2f,0x60 } },
-{  16, 0xd3d0, 0, {0x03,0xe8,0x83,0xfc,0x10,0xfd,0x80,0x1f,0x40,0x1f,0xd0,0x13,0xbe,0x40,0xee,0x04 } },
-{  16, 0xd3e0, 0, {0x3f,0xc0,0x0f,0xf0,0x43,0xfc,0x08,0xfd,0x00,0x3c,0xc0,0x0f,0xd0,0x11,0xf8,0x00 } },
-{  16, 0xd3f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa4,0x00,0xdb,0x00,0xb2,0x40 } },
-{  16, 0xd400, 0, {0x0e,0x94,0x03,0x24,0x00,0xd9,0x00,0xba,0xc0,0x0c,0x20,0x03,0xe4,0x90,0xfb,0x00 } },
-{  16, 0xd410, 0, {0x3a,0xc0,0x0c,0xb0,0x03,0xec,0x01,0xfa,0x00,0x3e,0xd0,0x2c,0x98,0x03,0x90,0x04 } },
-{  16, 0xd420, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x03,0x00,0x8b,0x00,0x22,0x48 } },
-{  16, 0xd430, 0, {0x08,0x84,0x22,0x2c,0x00,0xb9,0x00,0x22,0xc0,0x08,0xa0,0x02,0xed,0x00,0x8b,0xa0 } },
-{  16, 0xd440, 0, {0x21,0xc0,0x08,0xf0,0x02,0xfc,0x00,0xb9,0x80,0x2e,0xc0,0x08,0xa0,0x02,0x32,0x00 } },
-{  16, 0xd450, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x45,0x20,0x93,0x00,0x22,0xf8 } },
-{  16, 0xd460, 0, {0x0b,0x30,0x0a,0x84,0x40,0xb2,0x00,0x20,0x40,0x08,0x10,0x02,0xc4,0x00,0x80,0x80 } },
-{  16, 0xd470, 0, {0x28,0xc0,0x28,0x39,0x02,0x4c,0x00,0xb1,0x00,0x2c,0xc0,0x08,0x30,0x02,0xb8,0x00 } },
-{  16, 0xd480, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x36,0x00,0x9f,0x80,0x21,0x60 } },
-{  16, 0xd490, 0, {0x09,0x38,0x02,0x9e,0x00,0xb2,0xc0,0x20,0x60,0x48,0x48,0x12,0xd6,0xc6,0x86,0xd0 } },
-{  16, 0xd4a0, 0, {0x21,0xe0,0x08,0x78,0x00,0xde,0x80,0xb7,0x82,0x2d,0xe0,0x08,0xf8,0x02,0x08,0x00 } },
-{  16, 0xd4b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x20,0xd3,0x10,0x30,0xc8 } },
-{  16, 0xd4c0, 0, {0x0f,0x30,0x03,0x84,0x00,0xf1,0x00,0x30,0x40,0x24,0x19,0x03,0xe4,0xc0,0xe0,0x40 } },
-{  16, 0xd4d0, 0, {0x3a,0xc0,0x0c,0x32,0x03,0xce,0x80,0xb1,0x28,0x3c,0xc0,0x0c,0x30,0x13,0x92,0x02 } },
-{  16, 0xd4e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x9c,0x00,0xe6,0x00,0x7f,0xc0 } },
-{  16, 0xd4f0, 0, {0x0e,0xf0,0x23,0x74,0x40,0xff,0x10,0x3f,0x40,0x4f,0xd0,0x03,0xfc,0xd2,0xce,0x04 } },
-{  16, 0xd500, 0, {0x3f,0xc0,0x0f,0xf4,0x03,0xfc,0x00,0xfe,0x00,0x3f,0xc0,0x0f,0x71,0x03,0xd0,0x12 } },
-{  16, 0xd510, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xee,0x00,0xcb,0x00,0x16,0xc0 } },
-{  16, 0xd520, 0, {0x0d,0x80,0x03,0x27,0x20,0xcb,0x00,0x3e,0xc2,0x0a,0xb0,0x53,0xe4,0x28,0xc1,0x81 } },
-{  16, 0xd530, 0, {0x32,0xc1,0x0e,0xb9,0x03,0x2c,0x00,0xf1,0x80,0x35,0xe0,0x0c,0xb8,0x03,0x2a,0x04 } },
-{  16, 0xd540, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x02,0x87,0x10,0x2d,0x40 } },
-{  16, 0xd550, 0, {0x08,0x70,0x03,0x5c,0x00,0xa7,0x00,0x2d,0x40,0x28,0x70,0x02,0xd4,0x04,0x87,0x04 } },
-{  16, 0xd560, 0, {0xa1,0xd0,0x0b,0x72,0x02,0x1d,0x00,0xf7,0x00,0x21,0xc0,0x0d,0x50,0x02,0x12,0x04 } },
-{  16, 0xd570, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0x85,0x80,0x25,0xe0 } },
-{  16, 0xd580, 0, {0x09,0x78,0x02,0x37,0x03,0x87,0x80,0x2f,0xe0,0x08,0x78,0x12,0xc6,0x10,0x8d,0x80 } },
-{  16, 0xd590, 0, {0x25,0xe8,0x0b,0x38,0x02,0x1e,0x80,0xbc,0x84,0x25,0xe0,0x08,0x58,0x02,0x70,0x00 } },
-{  16, 0xd5a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcd,0x80,0x83,0x88,0x2c,0xc0 } },
-{  16, 0xd5b0, 0, {0x08,0x3c,0x02,0x4e,0x01,0xa3,0xd2,0x2e,0xc4,0x08,0xb1,0x02,0xcc,0x00,0x83,0x80 } },
-{  16, 0xd5c0, 0, {0x24,0xc1,0x0b,0x30,0x02,0x0c,0x00,0xb3,0x40,0xa0,0xd2,0x09,0x30,0x12,0x52,0x00 } },
-{  16, 0xd5d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xba,0x00,0xca,0xc0,0x36,0x80 } },
-{  16, 0xd5e0, 0, {0x0d,0x67,0x13,0x28,0x00,0xce,0x00,0x3e,0xa0,0x0c,0xed,0x03,0xe8,0x00,0xce,0xe0 } },
-{  16, 0xd5f0, 0, {0x36,0x80,0x1e,0xa0,0x0b,0x28,0x04,0xfe,0x00,0xb7,0xb2,0x0c,0xe0,0x0b,0x7a,0x00 } },
-{  16, 0xd600, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x40,0xf8,0x10,0x2e,0x10 } },
-{  16, 0xd610, 0, {0x0f,0x80,0x03,0xe0,0x01,0xd8,0x0a,0x3e,0x00,0x0f,0x80,0x03,0xc0,0x02,0xf8,0x08 } },
-{  16, 0xd620, 0, {0x3a,0x00,0x0f,0x80,0x03,0xe0,0x10,0xe8,0x20,0xbe,0x00,0x0f,0x80,0x13,0x92,0x00 } },
-{  16, 0xd630, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe5,0x00,0xfb,0x00,0x3e,0x40 } },
-{  16, 0xd640, 0, {0x0c,0x91,0x03,0x26,0x00,0x61,0x80,0x32,0x40,0x0c,0x90,0x03,0x24,0x00,0xc9,0x00 } },
-{  16, 0xd650, 0, {0x1e,0x40,0x0c,0x9c,0x03,0xe4,0x01,0xf9,0x00,0x3e,0x40,0x0f,0x90,0x03,0xc2,0x00 } },
-{  16, 0xd660, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x67,0x00,0xb9,0x00,0x2c,0x40 } },
-{  16, 0xd670, 0, {0x00,0x9c,0x02,0xa6,0x00,0x79,0x00,0x22,0x40,0x28,0x90,0x02,0x24,0x00,0x89,0x00 } },
-{  16, 0xd680, 0, {0x2c,0x44,0x08,0x98,0x02,0xe4,0x00,0xb9,0x80,0x2e,0x40,0x0b,0x90,0x02,0xe0,0x01 } },
-{  16, 0xd690, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x24,0x00,0xbb,0x00,0x26,0x50 } },
-{  16, 0xd6a0, 0, {0x28,0x90,0x82,0x24,0x84,0x99,0x20,0x22,0x40,0x49,0x90,0x02,0x24,0x00,0x89,0x00 } },
-{  16, 0xd6b0, 0, {0x2e,0x40,0x08,0x90,0x02,0xe4,0x00,0xb9,0x60,0x2e,0x40,0x0b,0x90,0x02,0xc6,0x04 } },
-{  16, 0xd6c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x06,0x00,0xb1,0x00,0x2e,0x48 } },
-{  16, 0xd6d0, 0, {0x08,0x12,0x02,0x84,0x80,0xb1,0x20,0xa0,0x48,0x09,0x12,0x0a,0x04,0x80,0x81,0x00 } },
-{  16, 0xd6e0, 0, {0x2c,0x48,0x28,0x12,0x42,0xc4,0x88,0x31,0x00,0x2c,0x40,0x0b,0x18,0x02,0xc2,0x01 } },
-{  16, 0xd6f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xf8,0x50,0x36,0x14 } },
-{  16, 0xd700, 0, {0x0c,0x80,0x03,0x20,0x00,0xe8,0x00,0x32,0x14,0x0c,0x85,0x03,0x21,0x40,0xc8,0x50 } },
-{  16, 0xd710, 0, {0x3e,0x14,0x0c,0x80,0x03,0xe1,0x40,0x38,0x00,0x3e,0x00,0x8f,0x80,0x03,0xee,0x03 } },
-{  16, 0xd720, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xd4,0x00,0xfb,0x04,0x3d,0x44 } },
-{  16, 0xd730, 0, {0x0f,0x51,0x23,0xd4,0x48,0xed,0x10,0x3d,0x44,0x4e,0xd1,0x23,0xf4,0x42,0xfd,0x00 } },
-{  16, 0xd740, 0, {0x3e,0x44,0x8f,0x91,0x03,0xe4,0x58,0xfd,0x00,0x3f,0x50,0x0f,0x50,0x03,0xe6,0x06 } },
-{  16, 0xd750, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf4,0x00,0xf9,0x00,0x3d,0x40 } },
-{  16, 0xd760, 0, {0x0c,0xd0,0x03,0xf4,0x00,0xdd,0x02,0x3e,0x40,0x0c,0x90,0x03,0xe4,0x40,0xc9,0x10 } },
-{  16, 0xd770, 0, {0x37,0x40,0x07,0xd0,0x07,0x24,0x00,0xe5,0x00,0x2f,0x6a,0x0f,0x70,0x03,0x06,0x00 } },
-{  16, 0xd780, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0xb8,0x00,0x3a,0x00 } },
-{  16, 0xd790, 0, {0x80,0x80,0x02,0xe0,0x00,0x88,0x00,0x2e,0x00,0x0a,0x80,0x53,0xa2,0x80,0x2c,0xa0 } },
-{  16, 0xd7a0, 0, {0x22,0x00,0x0b,0x80,0x0a,0x20,0x00,0xb8,0x00,0x2e,0x10,0x09,0x80,0x03,0x0e,0x04 } },
-{  16, 0xd7b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x6c,0x40 } },
-{  16, 0xd7c0, 0, {0x2a,0x10,0x02,0x84,0x01,0x81,0x80,0x2e,0x40,0x09,0x10,0x02,0xf4,0x00,0x8d,0x04 } },
-{  16, 0xd7d0, 0, {0x20,0x40,0x0b,0x10,0x02,0x84,0x00,0xb1,0x00,0x2c,0x40,0x0b,0x98,0x02,0x42,0x01 } },
-{  16, 0xd7e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x20,0xb9,0x00,0x2a,0x40 } },
-{  16, 0xd7f0, 0, {0x88,0xb4,0x02,0xe6,0x01,0xa9,0x20,0x2e,0x48,0x0a,0x90,0x00,0xa4,0x40,0xad,0x40 } },
-{  16, 0xd800, 0, {0x22,0x40,0x0b,0x90,0x12,0xa4,0x04,0xb9,0x01,0x2e,0x41,0x0b,0x90,0x02,0x06,0x04 } },
-{  16, 0xd810, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0xc0,0x3e,0x60 } },
-{  16, 0xd820, 0, {0x0c,0x94,0x13,0xa6,0x02,0xd9,0x42,0x1c,0x60,0x0c,0x9e,0x01,0xc6,0x04,0xc1,0x00 } },
-{  16, 0xd830, 0, {0xb2,0x40,0x1f,0x90,0x02,0xa4,0x00,0xe9,0x08,0x3e,0x68,0x4f,0x98,0x0b,0x68,0x04 } },
-{  16, 0xd840, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa6,0x40,0xf9,0x20,0x38,0x70 } },
-{  16, 0xd850, 0, {0x0f,0x91,0x03,0xe4,0x00,0xd9,0x80,0x3e,0x40,0x0f,0x9c,0x13,0xa4,0x00,0xf9,0x00 } },
-{  16, 0xd860, 0, {0x3e,0x40,0x0f,0x10,0x03,0x64,0x10,0xf9,0x0a,0x3e,0x50,0x0d,0x9a,0x03,0xca,0x00 } },
-{  16, 0xd870, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x00,0xd8,0x04,0x3e,0x00 } },
-{  16, 0xd880, 0, {0x0c,0x81,0x13,0xc0,0x02,0xd8,0x20,0x3e,0x00,0x2d,0x84,0x03,0xe0,0x00,0xcc,0x08 } },
-{  16, 0xd890, 0, {0x3a,0x00,0x0f,0x80,0x43,0xe0,0x00,0xf8,0x41,0x32,0x00,0x07,0x81,0x8b,0x0a,0x04 } },
-{  16, 0xd8a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x3a,0x60,0x8a,0x00,0x2f,0xa8 } },
-{  16, 0xd8b0, 0, {0x0a,0xe0,0x22,0xe8,0x02,0x7e,0x48,0x2e,0x80,0x08,0xa0,0x42,0xe8,0x04,0x8e,0x00 } },
-{  16, 0xd8c0, 0, {0x23,0xa8,0x0b,0xa8,0x82,0xe8,0x00,0xee,0x00,0xa2,0x80,0x4b,0x60,0x02,0x0a,0x00 } },
-{  16, 0xd8d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0x00,0x6c,0xc0 } },
-{  16, 0xd8e0, 0, {0x08,0x30,0x02,0xcc,0x00,0x13,0x81,0x2c,0xc0,0x08,0x30,0x02,0xce,0x40,0x82,0x40 } },
-{  16, 0xd8f0, 0, {0x28,0xe0,0x0b,0x38,0x02,0xcc,0x00,0xb3,0x10,0x24,0xc0,0x8b,0x38,0x02,0x0a,0x00 } },
-{  16, 0xd900, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x00,0x87,0x20,0x2f,0xc0 } },
-{  16, 0xd910, 0, {0x0a,0x70,0x02,0xdc,0x0a,0xb6,0x00,0x2c,0xc8,0x88,0x72,0x06,0xd8,0x00,0x86,0x00 } },
-{  16, 0xd920, 0, {0x21,0xc0,0x0b,0x70,0x02,0xdc,0x84,0xaf,0x80,0xa5,0xc0,0x0b,0xd0,0x02,0x28,0x00 } },
-{  16, 0xd930, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xd7,0x80,0x3d,0xa0 } },
-{  16, 0xd940, 0, {0x1c,0x78,0x13,0xd6,0x02,0xd7,0x80,0x3d,0xec,0x08,0x7e,0x23,0xfe,0x00,0xce,0x80 } },
-{  16, 0xd950, 0, {0x39,0x60,0x0f,0x78,0x03,0xdf,0x00,0xf6,0x80,0x75,0xe0,0x0f,0x78,0x03,0x2a,0x02 } },
-{  16, 0xd960, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0x8c,0x00,0xfb,0x10,0x3e,0x80 } },
-{  16, 0xd970, 0, {0x1f,0xa0,0x21,0xcc,0x00,0xfa,0x00,0x3e,0xc0,0x0e,0xb0,0x03,0xe8,0x02,0xfa,0x00 } },
-{  16, 0xd980, 0, {0x3e,0x40,0x0f,0xb0,0x13,0xec,0x00,0xea,0x01,0x3a,0xc0,0x0f,0x90,0x03,0xc2,0x06 } },
-{  16, 0xd990, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfc,0x00,0xff,0x80,0x3f,0x60 } },
-{  16, 0xd9a0, 0, {0x08,0x99,0x07,0x7e,0x00,0xdd,0x80,0x3f,0xe2,0x0c,0xf8,0x03,0xf6,0x02,0xdf,0x80 } },
-{  16, 0xd9b0, 0, {0xb3,0xe0,0x0c,0xf8,0x03,0x3e,0x41,0xcc,0x80,0x33,0xe4,0x0f,0xf8,0x03,0xc0,0x00 } },
-{  16, 0xd9c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x40,0xb7,0x00,0x2d,0xc0 } },
-{  16, 0xd9d0, 0, {0x0d,0x5a,0x22,0xdc,0x80,0x75,0x00,0x2d,0xc0,0x08,0x71,0x02,0xf0,0x20,0x87,0x00 } },
-{  16, 0xd9e0, 0, {0x21,0xc0,0x0a,0x70,0x02,0x1c,0x00,0xd4,0x28,0x21,0xc0,0x0b,0x72,0x02,0xea,0x04 } },
-{  16, 0xd9f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x40,0xb7,0x00,0x2d,0x00 } },
-{  16, 0xda00, 0, {0x08,0x72,0x22,0xf4,0x00,0x87,0x00,0x2d,0xc2,0x08,0x70,0x02,0xd4,0x00,0x87,0x80 } },
-{  16, 0xda10, 0, {0x25,0x40,0x09,0x30,0x02,0x5c,0x01,0xad,0x00,0x29,0xd0,0x4b,0x70,0x02,0xc0,0x00 } },
-{  16, 0xda20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0xbb,0xc8,0x2c,0xa0 } },
-{  16, 0xda30, 0, {0x09,0x20,0x02,0xce,0x00,0xa3,0x00,0x2c,0xe0,0xa8,0x3d,0x42,0xc2,0x00,0x8b,0x80 } },
-{  16, 0xda40, 0, {0x24,0x40,0x0b,0x30,0x0a,0x6c,0x08,0xa3,0x40,0xa8,0xe0,0x0b,0x34,0x02,0xc8,0x04 } },
-{  16, 0xda50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xad,0x00,0xff,0x48,0x3c,0x28 } },
-{  16, 0xda60, 0, {0x0c,0xa9,0x23,0x6c,0x80,0x8b,0x00,0x3f,0xc0,0x0c,0xfc,0x03,0xec,0x00,0xd8,0x80 } },
-{  16, 0xda70, 0, {0x34,0x40,0x0d,0x30,0x03,0x7c,0x02,0xa3,0x40,0x38,0x68,0x0f,0x24,0x03,0xea,0x04 } },
-{  16, 0xda80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xed,0x88,0xfb,0x00,0x3e,0x50 } },
-{  16, 0xda90, 0, {0x0f,0xa1,0x03,0xec,0x04,0x3a,0xc0,0x3e,0xc0,0x0f,0xb0,0x83,0xe8,0x02,0xf8,0x10 } },
-{  16, 0xdaa0, 0, {0x3a,0x41,0x0e,0x90,0x03,0xac,0x00,0x9b,0x08,0xb6,0x40,0x0f,0x81,0x03,0xe0,0x00 } },
-{  16, 0xdab0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xff,0x00,0xb3,0x20 } },
-{  16, 0xdac0, 0, {0x0c,0x50,0x13,0x1c,0x09,0xcd,0x83,0x33,0xc0,0x83,0x70,0x00,0x3c,0x00,0xdc,0x10 } },
-{  16, 0xdad0, 0, {0x32,0x60,0x0e,0xf1,0x43,0x2c,0x00,0xce,0x04,0x3b,0x70,0x0c,0xf0,0x83,0x00,0x44 } },
-{  16, 0xdae0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x67,0x80,0xbb,0x01,0x62,0x21 } },
-{  16, 0xdaf0, 0, {0x8a,0x89,0x20,0x2c,0x00,0x80,0xe0,0x22,0xc0,0x0b,0xb0,0x03,0xd8,0x10,0x8c,0x04 } },
-{  16, 0xdb00, 0, {0x22,0x40,0x05,0x90,0x02,0xac,0x00,0xd8,0x80,0x36,0x40,0x0a,0x90,0x02,0x20,0x40 } },
-{  16, 0xdb10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x26,0x00,0xbb,0x00,0x22,0x06 } },
-{  16, 0xdb20, 0, {0x08,0x80,0x02,0x2e,0x00,0x88,0x20,0x22,0xc0,0x09,0xb0,0x02,0xa4,0x00,0x99,0x00 } },
-{  16, 0xdb30, 0, {0x62,0xc4,0x08,0xb0,0x06,0x2c,0x00,0x88,0x80,0x22,0x41,0x08,0xa0,0x02,0x20,0x00 } },
-{  16, 0xdb40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xb3,0x00,0x20,0x40 } },
-{  16, 0xdb50, 0, {0x0a,0x00,0x82,0x0c,0x00,0x80,0x00,0x20,0xc0,0x0b,0x30,0x22,0xa0,0x00,0x81,0x00 } },
-{  16, 0xdb60, 0, {0xa0,0xc0,0x09,0x30,0x02,0x8c,0x00,0x90,0x00,0x24,0x40,0x0a,0x28,0x02,0x02,0x01 } },
-{  16, 0xdb70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x60,0x00,0xfb,0x02,0x20,0x00 } },
-{  16, 0xdb80, 0, {0x2c,0x92,0x03,0x2c,0x02,0x88,0x00,0x31,0xc0,0x0b,0xb5,0x02,0xa4,0x00,0xd1,0x04 } },
-{  16, 0xdb90, 0, {0x32,0x40,0x0e,0x90,0x03,0x2c,0x40,0xc9,0x00,0x3a,0x40,0x8c,0xa0,0x03,0x00,0x03 } },
-{  16, 0xdba0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf4,0x00,0xff,0x00,0x2f,0x00 } },
-{  16, 0xdbb0, 0, {0x0f,0xc0,0x03,0xdc,0x00,0xfc,0x00,0x3f,0xc1,0x0f,0xf0,0x43,0xf0,0x00,0xfd,0x00 } },
-{  16, 0xdbc0, 0, {0x3f,0x40,0x4f,0xd0,0x03,0xfc,0x00,0xf5,0x00,0x3f,0x40,0x0f,0xe0,0x03,0xe8,0x06 } },
-{  16, 0xdbd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xd8,0x80,0xcc,0x00,0xb7,0x04 } },
-{  16, 0xdbe0, 0, {0x4e,0xe1,0x03,0x3c,0x20,0xdf,0x10,0x31,0x80,0x06,0xf0,0x03,0x7f,0x00,0xff,0xc0 } },
-{  16, 0xdbf0, 0, {0x3b,0xc0,0x0e,0xf2,0x03,0x5e,0x00,0xef,0x10,0x33,0xd0,0x2c,0xf2,0x03,0x30,0x00 } },
-{  16, 0xdc00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x10,0xe9,0x00,0x88,0xc6,0x20,0x5c } },
-{  16, 0xdc10, 0, {0x08,0xa4,0x57,0x65,0x00,0x8f,0x52,0x2a,0xf0,0x09,0xfc,0x02,0x04,0x00,0xbb,0x00 } },
-{  16, 0xdc20, 0, {0x2d,0xd9,0x09,0x74,0x83,0x64,0x28,0x83,0x44,0x22,0x84,0x88,0x06,0x82,0x30,0x04 } },
-{  16, 0xdc30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xc9,0x00,0x80,0x10,0x20,0x08 } },
-{  16, 0xdc40, 0, {0x08,0x31,0x12,0x04,0xb2,0xa3,0x00,0x20,0x84,0x1b,0x34,0x02,0x0c,0x80,0xb3,0x20 } },
-{  16, 0xdc50, 0, {0x2c,0xc7,0x09,0x36,0x02,0x8c,0x80,0x93,0x40,0xac,0xc8,0x08,0x31,0x28,0x32,0x01 } },
-{  16, 0xdc60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa9,0x00,0x88,0x00,0xa2,0x50 } },
-{  16, 0xdc70, 0, {0x08,0x35,0x02,0x24,0x00,0x8b,0x04,0x2e,0xc1,0x09,0xb0,0x02,0x24,0x94,0xbb,0x00 } },
-{  16, 0xdc80, 0, {0x2e,0xc0,0x0b,0xb0,0x02,0xcc,0x60,0x8b,0x00,0x2e,0x80,0x08,0x80,0x00,0x30,0x04 } },
-{  16, 0xdc90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xe7,0x02,0xcb,0x18,0xb2,0x80 } },
-{  16, 0xdca0, 0, {0x2c,0xac,0x0a,0x2e,0x08,0xeb,0x00,0x32,0x12,0x4e,0xb0,0x03,0x2b,0x80,0xfb,0x00 } },
-{  16, 0xdcb0, 0, {0x3a,0xc0,0x0a,0xb0,0x03,0xab,0x08,0xeb,0x04,0x2e,0x48,0x0c,0xb8,0x83,0x00,0x04 } },
-{  16, 0xdcc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb6,0x80,0xff,0x80,0x39,0xca } },
-{  16, 0xdcd0, 0, {0x0d,0xe8,0x03,0xd6,0x40,0xe7,0x04,0x3b,0x66,0x4e,0x70,0x03,0xb8,0x00,0xff,0x01 } },
-{  16, 0xdce0, 0, {0x3f,0xc0,0x6c,0xf0,0x03,0x70,0x06,0xe7,0x00,0x31,0x04,0x0f,0xc1,0x43,0xf8,0x00 } },
-{  16, 0xdcf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x85,0x00,0xcb,0x40,0x32,0x90 } },
-{  16, 0xdd00, 0, {0x2f,0xb0,0x0b,0x64,0x80,0xfb,0x08,0xba,0x10,0x0d,0xb0,0xa7,0x2d,0x00,0xfb,0x04 } },
-{  16, 0xdd10, 0, {0x3e,0xc0,0x8e,0xb0,0x03,0x6d,0x00,0xdb,0x01,0x32,0x40,0x8c,0x33,0x03,0x90,0x04 } },
-{  16, 0xdd20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0x24,0x00,0x83,0xe0,0xa2,0xd0 } },
-{  16, 0xdd30, 0, {0x40,0xb0,0x02,0x25,0x04,0xbf,0x80,0xa0,0x50,0x08,0xf8,0x02,0x20,0x00,0x8b,0x02 } },
-{  16, 0xdd40, 0, {0x2f,0xd0,0x08,0xf0,0x02,0x24,0x00,0x8f,0x80,0x36,0x01,0x08,0x84,0x42,0x36,0x00 } },
-{  16, 0xdd50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x05,0x44,0x00,0x83,0x48,0x20,0xc4 } },
-{  16, 0xdd60, 0, {0x09,0x00,0x02,0x46,0x00,0xb3,0x01,0xa8,0x90,0x19,0x30,0x12,0x8c,0x00,0xa3,0x04 } },
-{  16, 0xdd70, 0, {0x2e,0xe2,0x0a,0xb0,0x02,0x0c,0x00,0x83,0x49,0x28,0xc0,0x09,0x3c,0x02,0x38,0x00 } },
-{  16, 0xdd80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x36,0x04,0x83,0x80,0x21,0xe1 } },
-{  16, 0xdd90, 0, {0x08,0x38,0x12,0x1e,0x28,0xb3,0x98,0x21,0xa0,0x19,0x38,0x82,0x96,0x00,0x87,0x83 } },
-{  16, 0xdda0, 0, {0x2d,0xe2,0x08,0x78,0x22,0x36,0x8c,0x87,0x80,0x2d,0xe0,0x09,0x79,0x02,0x3e,0x00 } },
-{  16, 0xddb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x04,0x00,0xc3,0x30,0x30,0xc8 } },
-{  16, 0xddc0, 0, {0x4d,0x00,0x0b,0x4c,0x80,0xf3,0x12,0x38,0xc0,0x0d,0x3a,0x02,0x8c,0x80,0xf3,0x00 } },
-{  16, 0xddd0, 0, {0x3c,0xc0,0x0e,0x30,0x0b,0x0e,0x00,0xc3,0x0c,0x3a,0xc0,0x0d,0x30,0x03,0x12,0x02 } },
-{  16, 0xdde0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb4,0x06,0xff,0x10,0x3f,0xc0 } },
-{  16, 0xddf0, 0, {0x0f,0xb0,0x13,0xbc,0x00,0xff,0x10,0x7f,0xc0,0x0e,0xf1,0xa3,0x7c,0x00,0xff,0x12 } },
-{  16, 0xde00, 0, {0x3f,0xc2,0x0f,0xf5,0x23,0xbc,0x41,0xef,0x18,0x37,0x80,0xae,0xc0,0x03,0x50,0x06 } },
-{  16, 0xde10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x00,0xdb,0x00,0x3e,0xda } },
-{  16, 0xde20, 0, {0x0c,0x80,0x03,0x66,0x10,0x8b,0x00,0x32,0x80,0x8c,0xb6,0x03,0x4a,0x00,0x4b,0x80 } },
-{  16, 0xde30, 0, {0x32,0xc8,0x0c,0xb4,0x03,0x0a,0x10,0xdb,0x00,0x3e,0xc1,0x0c,0xb0,0x43,0x2a,0x00 } },
-{  16, 0xde40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x11,0xb4,0x00,0x87,0x04,0x2c,0xc0 } },
-{  16, 0xde50, 0, {0x0d,0x70,0x03,0x1c,0x08,0x87,0x48,0x20,0x81,0x0d,0x72,0x82,0x5c,0x00,0xd7,0x00 } },
-{  16, 0xde60, 0, {0x21,0xcc,0x28,0xf0,0x02,0x1c,0x10,0x87,0x20,0x2c,0x00,0x08,0x40,0x0a,0x32,0x04 } },
-{  16, 0xde70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x96,0x00,0xb7,0x81,0x2d,0xe0 } },
-{  16, 0xde80, 0, {0x08,0x48,0x02,0x0e,0x04,0x87,0x80,0x21,0xe0,0x08,0x78,0x02,0x3e,0x01,0x87,0x80 } },
-{  16, 0xde90, 0, {0x21,0xe0,0x18,0x79,0x02,0x3a,0x01,0x97,0xa0,0x2d,0x60,0x08,0x38,0x02,0x20,0x00 } },
-{  16, 0xdea0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xc6,0x00,0xa3,0xc6,0x2c,0xc0 } },
-{  16, 0xdeb0, 0, {0x09,0x30,0x02,0x0c,0x01,0x83,0x00,0x20,0xe0,0x09,0x30,0x02,0x4e,0x00,0x93,0x00 } },
-{  16, 0xdec0, 0, {0x20,0xc0,0x49,0x30,0x22,0x0f,0x64,0x83,0x02,0x6c,0xd4,0x28,0x30,0x02,0x12,0x04 } },
-{  16, 0xded0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x11,0xab,0x80,0xfa,0xe0,0x3c,0x88 } },
-{  16, 0xdee0, 0, {0x0c,0xe0,0x02,0x28,0x02,0xca,0x00,0xb3,0xa9,0x0c,0xa0,0x03,0x3b,0x10,0xca,0x00 } },
-{  16, 0xdef0, 0, {0xa2,0x80,0x0c,0xa0,0x0b,0x38,0x00,0xda,0x00,0x3f,0xb0,0x0c,0xe6,0x03,0x3a,0x04 } },
-{  16, 0xdf00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xc0,0x20,0x98,0x08,0x3e,0x00 } },
-{  16, 0xdf10, 0, {0x0f,0x80,0x0b,0xe1,0x00,0xf8,0x01,0x3c,0x10,0x4f,0x00,0x03,0xa0,0x40,0xf8,0x00 } },
-{  16, 0xdf20, 0, {0x3e,0x10,0x0e,0x80,0x03,0xe0,0x00,0xf8,0x00,0x3c,0x02,0x2f,0x04,0x93,0xd2,0x00 } },
-{  16, 0xdf30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xc1,0xc1,0x32,0x40 } },
-{  16, 0xdf40, 0, {0x0c,0x98,0x03,0x26,0x40,0xf9,0x00,0x32,0x40,0x0c,0x98,0x03,0x24,0x24,0xf9,0x00 } },
-{  16, 0xdf50, 0, {0x3c,0x60,0x0c,0x10,0x03,0xa4,0x00,0xf9,0x82,0x32,0x40,0x0c,0x90,0x03,0x02,0x04 } },
-{  16, 0xdf60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x00,0x22,0x50 } },
-{  16, 0xdf70, 0, {0x0d,0x98,0x02,0x25,0x80,0xb9,0x00,0x22,0x52,0x0d,0x9c,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0xdf80, 0, {0x2e,0x60,0x08,0x90,0x42,0x24,0x00,0xb9,0x40,0x36,0x40,0x08,0x90,0x0a,0x20,0x00 } },
-{  16, 0xdf90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x8d,0x00,0x23,0x40 } },
-{  16, 0xdfa0, 0, {0x08,0x12,0x02,0x24,0x00,0xa1,0x10,0xa2,0x60,0x08,0x92,0x8a,0x24,0x00,0xb9,0x01 } },
-{  16, 0xdfb0, 0, {0x2e,0x46,0x08,0x90,0x02,0xa4,0x00,0xb1,0x50,0x22,0x40,0x28,0x90,0x82,0x06,0x00 } },
-{  16, 0xdfc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x84,0x85,0x20,0xa1,0xd8 } },
-{  16, 0xdfd0, 0, {0x09,0x10,0x02,0x04,0x80,0xb3,0x20,0x20,0x40,0x29,0x12,0x06,0x04,0x00,0xb1,0x01 } },
-{  16, 0xdfe0, 0, {0x2c,0x48,0x28,0x12,0x02,0x04,0x00,0xb1,0x20,0x24,0x48,0x08,0x12,0x02,0x02,0x01 } },
-{  16, 0xdff0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x42,0x8a,0x00,0xb3,0x00 } },
-{  16, 0xe000, 0, {0x0c,0x05,0x03,0x21,0x40,0xe0,0x50,0xb2,0x00,0x2c,0x80,0x02,0x21,0x40,0xf0,0x50 } },
-{  16, 0xe010, 0, {0x3c,0x14,0x0c,0x85,0x13,0xa1,0x50,0xf8,0x50,0x32,0x14,0x0c,0x85,0x23,0x2e,0x03 } },
-{  16, 0xe020, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xf9,0x10,0x3e,0x44 } },
-{  16, 0xe030, 0, {0x0f,0xd4,0x0b,0xf4,0x44,0xf9,0x10,0x3f,0x50,0x4f,0x11,0x03,0xf4,0x00,0xf9,0x00 } },
-{  16, 0xe040, 0, {0x3e,0x44,0x0f,0x91,0x53,0xf4,0x14,0xf9,0x10,0x3f,0x44,0x0f,0xd1,0x03,0xe6,0x02 } },
-{  16, 0xe050, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x05,0xe6,0xa0,0xdd,0x88,0xb3,0x66 } },
-{  16, 0xe060, 0, {0x0c,0xdc,0x83,0x36,0x88,0xbd,0xa0,0x37,0x6a,0x0c,0xda,0x0b,0x25,0x02,0xc9,0x40 } },
-{  16, 0xe070, 0, {0x3f,0x78,0x4f,0x98,0xb3,0xe5,0x04,0xcd,0xa0,0x72,0x78,0x0c,0xd8,0x8b,0x26,0x14 } },
-{  16, 0xe080, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe3,0x00,0x88,0x42,0x22,0x31 } },
-{  16, 0xe090, 0, {0x08,0x0a,0x02,0x22,0xa0,0xb8,0xf9,0x22,0x10,0x0d,0x84,0x12,0x6a,0x80,0x88,0x80 } },
-{  16, 0xe0a0, 0, {0x2e,0x20,0x0b,0x08,0x02,0xe2,0x80,0xa8,0xa8,0xa2,0x38,0x48,0xa8,0x02,0x0e,0x00 } },
-{  16, 0xe0b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc4,0xa2,0x81,0x00,0x20,0x48 } },
-{  16, 0xe0c0, 0, {0x08,0x12,0x42,0x45,0x00,0xb1,0x00,0x24,0x40,0x09,0x14,0x02,0x24,0x00,0x81,0x20 } },
-{  16, 0xe0d0, 0, {0x2c,0x58,0x0b,0x10,0x82,0xc4,0x04,0x91,0x40,0x64,0x6c,0x08,0x30,0x82,0x12,0x05 } },
-{  16, 0xe0e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0x89,0x00,0x22,0x41 } },
-{  16, 0xe0f0, 0, {0x08,0x90,0x8a,0x64,0x80,0xb9,0x00,0x22,0x50,0x09,0x90,0x06,0x64,0x08,0x99,0x00 } },
-{  16, 0xe100, 0, {0x2e,0x40,0x0b,0x90,0x06,0xc4,0x01,0xb9,0x02,0x26,0x61,0x88,0x90,0x02,0x06,0x04 } },
-{  16, 0xe110, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xc9,0x00,0x22,0x40 } },
-{  16, 0xe120, 0, {0x2c,0x94,0x23,0x64,0x00,0xb9,0x00,0x36,0x40,0x09,0x90,0x13,0x05,0x00,0xc9,0x00 } },
-{  16, 0xe130, 0, {0x3e,0x40,0x4f,0x90,0x13,0xe5,0xc0,0xd9,0x00,0x26,0x40,0x2c,0x94,0x03,0x28,0x00 } },
-{  16, 0xe140, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x01,0xa4,0x02,0xe9,0x08,0x3c,0x40 } },
-{  16, 0xe150, 0, {0x0f,0x90,0x0b,0xa4,0x00,0xf1,0x00,0x3e,0x41,0x0f,0x90,0x43,0xa4,0x88,0xe9,0x04 } },
-{  16, 0xe160, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe6,0x00,0xe1,0x00,0x3a,0x40,0x9f,0x92,0x63,0xda,0x00 } },
-{  16, 0xe170, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0x80,0x10,0xe0,0x01,0x32,0x00 } },
-{  16, 0xe180, 0, {0x8f,0x80,0x03,0x20,0x00,0xd8,0x08,0x30,0x01,0x8c,0x00,0x03,0xe1,0x02,0xc8,0x04 } },
-{  16, 0xe190, 0, {0x3e,0x00,0x0c,0x80,0x0b,0x21,0x00,0xc8,0x00,0x78,0x00,0x0f,0x86,0x03,0x0a,0x00 } },
-{  16, 0xe1a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8e,0x40,0x2b,0x82 } },
-{  16, 0xe1b0, 0, {0x0b,0xa0,0x02,0x3a,0x00,0x8e,0x80,0x23,0x82,0x08,0xe2,0x02,0x28,0x10,0x8a,0x00 } },
-{  16, 0xe1c0, 0, {0x2f,0x98,0x28,0xa0,0x12,0x28,0x00,0x8e,0x20,0x2e,0x80,0x4b,0xe4,0x02,0x0a,0x00 } },
-{  16, 0xe1d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x02,0xa2,0x40,0x20,0x80 } },
-{  16, 0xe1e0, 0, {0x0b,0xb0,0x02,0x4e,0x40,0x93,0xc0,0xa0,0x20,0x08,0x36,0x02,0x8c,0x00,0x93,0x00 } },
-{  16, 0xe1f0, 0, {0x2c,0xe2,0x08,0x30,0x06,0x4c,0x12,0x93,0x08,0x28,0xc0,0x0b,0xb0,0x02,0x0a,0x00 } },
-{  16, 0xe200, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x08,0x82,0x40,0x29,0x40 } },
-{  16, 0xe210, 0, {0x0b,0x70,0x02,0x5e,0x08,0x84,0x08,0x23,0x40,0x08,0x70,0x06,0x1c,0x80,0x87,0x00 } },
-{  16, 0xe220, 0, {0x2d,0x20,0x08,0x79,0x12,0x5c,0x00,0x94,0x00,0x2d,0xc0,0x0b,0x30,0x42,0x28,0x00 } },
-{  16, 0xe230, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x00,0xe4,0x80,0x31,0xa1 } },
-{  16, 0xe240, 0, {0x0f,0x58,0x13,0x76,0x00,0xd0,0x80,0x31,0xc0,0x0c,0x38,0x03,0xbe,0x80,0xd7,0x81 } },
-{  16, 0xe250, 0, {0x3f,0x20,0x8c,0x79,0x03,0x7f,0x01,0xd6,0x80,0x39,0xe8,0x4f,0x68,0x03,0x2a,0x00 } },
-{  16, 0xe260, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xbe,0x00,0xfa,0x00,0x3e,0x00 } },
-{  16, 0xe270, 0, {0x8f,0x96,0x0b,0xa4,0x00,0xea,0x00,0x3c,0xc0,0x0f,0x90,0x03,0xac,0x20,0xfb,0x40 } },
-{  16, 0xe280, 0, {0x2e,0x00,0x0f,0xb2,0x03,0xad,0xa0,0xea,0x00,0x3e,0xc0,0x0f,0xa0,0x1b,0xc2,0x04 } },
-{  16, 0xe290, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x08,0xde,0x81,0x33,0xa4 } },
-{  16, 0xe2a0, 0, {0x0e,0xfc,0x13,0x3e,0x00,0xfc,0x80,0x13,0x20,0x0c,0x68,0x03,0x3e,0x20,0xff,0xc8 } },
-{  16, 0xe2b0, 0, {0x3f,0x60,0x1d,0xf8,0x03,0x7e,0x00,0xc7,0x80,0x33,0xe2,0x0c,0xd8,0x03,0x10,0x00 } },
-{  16, 0xe2c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0x86,0x41,0x31,0xc4 } },
-{  16, 0xe2d0, 0, {0x08,0x79,0x42,0x9c,0x00,0xbc,0x10,0x21,0x40,0x85,0x35,0x03,0x5c,0x00,0xb7,0x00 } },
-{  16, 0xe2e0, 0, {0x2d,0xc0,0x08,0x72,0x02,0x2c,0x00,0xa7,0x01,0x37,0xc0,0x08,0x51,0x42,0x2a,0x00 } },
-{  16, 0xe2f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x8c,0x40,0x82,0x00,0x24,0x81 } },
-{  16, 0xe300, 0, {0x08,0xd8,0x02,0x14,0x20,0xb5,0x00,0x20,0x40,0x09,0x60,0x02,0x1c,0x40,0xb7,0x00 } },
-{  16, 0xe310, 0, {0x2c,0x40,0x0b,0x30,0x22,0xdc,0x00,0x97,0x00,0x21,0xc4,0x08,0x40,0x02,0x44,0x00 } },
-{  16, 0xe320, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xec,0x00,0x92,0x06,0x20,0x90 } },
-{  16, 0xe330, 0, {0x38,0x15,0x02,0x86,0x00,0xb8,0x00,0x60,0x50,0x09,0x30,0x02,0x4e,0x01,0xbb,0x00 } },
-{  16, 0xe340, 0, {0x2e,0x40,0x0b,0x30,0x02,0xce,0x20,0xb3,0x00,0x24,0xf0,0x48,0x02,0x0a,0x58,0x04 } },
-{  16, 0xe350, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xca,0x00,0xa6,0x94 } },
-{  16, 0xe360, 0, {0x2c,0x90,0x03,0x2e,0x00,0xfb,0x05,0xb2,0x85,0x0d,0x90,0x03,0x3f,0x90,0xff,0x00 } },
-{  16, 0xe370, 0, {0x7e,0x80,0x1f,0xf0,0x43,0xfc,0x21,0x9a,0x00,0x33,0xc8,0x3c,0xb2,0x03,0x6a,0x04 } },
-{  16, 0xe380, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0xec,0x02,0xea,0x40,0x3d,0x80 } },
-{  16, 0xe390, 0, {0x0f,0x10,0x93,0xed,0x00,0xfb,0x40,0x3e,0x90,0x8f,0x30,0x03,0xec,0x80,0xfb,0x00 } },
-{  16, 0xe3a0, 0, {0x3e,0x91,0x1c,0xb0,0x03,0x2c,0x10,0xe8,0x00,0x3e,0xc8,0x1f,0x90,0x03,0xa5,0x10 } },
-{  16, 0xe3b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xfc,0x02,0xe4,0x00,0x73,0xa0 } },
-{  16, 0xe3c0, 0, {0x0c,0xfc,0x03,0x7c,0x02,0xff,0x10,0x13,0xc4,0x1c,0xc0,0x03,0x3c,0x00,0xff,0x00 } },
-{  16, 0xe3d0, 0, {0x37,0xe0,0x0d,0xf0,0x03,0xfc,0x00,0xed,0x80,0x31,0xc0,0x0c,0x32,0x63,0x20,0x04 } },
-{  16, 0xe3e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x6c,0x00,0x8a,0xc0,0x22,0xb1 } },
-{  16, 0xe3f0, 0, {0x8a,0xb8,0x43,0x4a,0x10,0xdb,0x20,0x20,0xf0,0x0a,0x94,0x03,0x6c,0x00,0xbb,0x07 } },
-{  16, 0xe400, 0, {0x22,0xb8,0x08,0xb0,0x02,0xec,0x11,0xe8,0xc0,0xb2,0xc0,0x2a,0x92,0x1a,0x20,0x00 } },
-{  16, 0xe410, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x2c,0x00,0xaa,0x80,0x22,0x98 } },
-{  16, 0xe420, 0, {0x08,0x90,0x02,0x2f,0x03,0xbb,0x01,0x2a,0x83,0x08,0xb2,0x4e,0x2c,0x04,0xab,0x02 } },
-{  16, 0xe430, 0, {0x22,0xc4,0x28,0xb0,0x22,0xec,0x09,0xb3,0x50,0x62,0xc0,0x08,0xb0,0x02,0x20,0x00 } },
-{  16, 0xe440, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x01,0x83,0x00,0x60,0x80 } },
-{  16, 0xe450, 0, {0x08,0x12,0x0a,0x44,0x00,0x93,0x00,0x2a,0x80,0x4a,0x30,0x02,0x0c,0x00,0xb3,0x00 } },
-{  16, 0xe460, 0, {0x60,0xc0,0x08,0x30,0x02,0xcc,0x00,0xb3,0x02,0x60,0xc0,0x08,0x00,0x46,0x02,0x01 } },
-{  16, 0xe470, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0d,0x6c,0x00,0xe8,0x02,0x22,0x80 } },
-{  16, 0xe480, 0, {0x2c,0xf2,0x43,0x2c,0x00,0xfb,0x00,0xba,0xc0,0x08,0xa5,0x02,0x3c,0x00,0xef,0x00 } },
-{  16, 0xe490, 0, {0x36,0xc0,0x4d,0xf0,0x13,0xfd,0x51,0xfb,0x00,0x32,0xc0,0x0c,0xb0,0x03,0x20,0x01 } },
-{  16, 0xe4a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0x7e,0x04,0x3f,0x80 } },
-{  16, 0xe4b0, 0, {0x0f,0x31,0x43,0xf0,0x02,0xff,0x00,0x37,0xc0,0x0f,0xf0,0x03,0xfc,0x08,0xff,0x00 } },
-{  16, 0xe4c0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xef,0x00,0x3b,0xc0,0x0f,0xc0,0x03,0xe8,0x16 } },
-{  16, 0xe4d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf2,0x40,0xfc,0x80,0x3f,0x24 } },
-{  16, 0xe4e0, 0, {0x0d,0xd8,0x53,0xd6,0x04,0xdf,0x32,0x3f,0xcc,0x4c,0xc0,0x43,0xfc,0x00,0xdf,0x60 } },
-{  16, 0xe4f0, 0, {0x37,0xc0,0x0f,0xc4,0x03,0x7c,0xd0,0xdf,0x20,0x33,0xd8,0x0d,0xf8,0x43,0xf0,0x00 } },
-{  16, 0xe500, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x18,0xe8,0x80,0xb0,0x01,0x2e,0x08 } },
-{  16, 0xe510, 0, {0x88,0x90,0x02,0xec,0x20,0x8b,0x70,0x2f,0xcc,0x08,0xb3,0x82,0xfd,0xe0,0xbf,0x40 } },
-{  16, 0xe520, 0, {0x22,0xd8,0x0b,0x93,0x02,0xfd,0xc0,0xaf,0x10,0x28,0xf0,0x08,0xbc,0x12,0xf0,0x04 } },
-{  16, 0xe530, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x00,0xb0,0x00,0x2e,0x01 } },
-{  16, 0xe540, 0, {0x0a,0x12,0x82,0xec,0x80,0xb3,0x00,0x2c,0xc8,0x0a,0x00,0x32,0x8c,0x00,0xa3,0x30 } },
-{  16, 0xe550, 0, {0x20,0xd2,0x09,0x00,0x02,0x8c,0x80,0x83,0x00,0x28,0xd8,0x0b,0x34,0x12,0xf2,0x01 } },
-{  16, 0xe560, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xac,0x01,0xb8,0x02,0x2e,0x00 } },
-{  16, 0xe570, 0, {0x0a,0x90,0x12,0xec,0x10,0x8b,0x00,0x2e,0xc0,0x0a,0xb0,0x00,0xec,0x00,0xb3,0x00 } },
-{  16, 0xe580, 0, {0x22,0xc1,0x0b,0x92,0x02,0xcc,0x01,0xab,0x00,0x2a,0xc0,0x02,0xb0,0x02,0xf0,0x04 } },
-{  16, 0xe590, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe0,0x00,0xfa,0x0c,0x3e,0xc0 } },
-{  16, 0xe5a0, 0, {0x0f,0xa0,0x13,0xee,0x20,0xdb,0x00,0x3e,0xc0,0x2e,0x88,0x53,0xec,0x00,0xfb,0x00 } },
-{  16, 0xe5b0, 0, {0xb2,0xc0,0x8f,0xac,0x83,0xac,0x08,0xdb,0x00,0x1a,0xc0,0x4f,0xb0,0x03,0xc0,0x04 } },
-{  16, 0xe5c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x00,0xfe,0x00,0x3f,0xc0 } },
-{  16, 0xe5d0, 0, {0x2d,0xe0,0x03,0xfe,0x80,0x7f,0x00,0x3f,0xc0,0x0d,0xd2,0x03,0xfc,0x00,0xbf,0x01 } },
-{  16, 0xe5e0, 0, {0x3e,0xc0,0x0d,0xc8,0x03,0xfc,0x0c,0xff,0x00,0x3f,0xc0,0x09,0xf0,0x23,0xf8,0x00 } },
-{  16, 0xe5f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa4,0x00,0xfa,0x40,0x32,0xc1 } },
-{  16, 0xe600, 0, {0x0f,0xa0,0x03,0x29,0x08,0xdb,0x00,0x3e,0xc0,0x0e,0x85,0x03,0xec,0x20,0xcb,0x00 } },
-{  16, 0xe610, 0, {0x3a,0xc0,0x0e,0xa4,0x03,0xec,0x00,0xfb,0x00,0x3a,0xc2,0x0e,0xb0,0x03,0x10,0x04 } },
-{  16, 0xe620, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xba,0x60,0x20,0xc0 } },
-{  16, 0xe630, 0, {0x0b,0xa0,0x02,0x08,0x00,0xaf,0x00,0x2f,0xd0,0x0b,0xb5,0x02,0xfe,0x02,0x8f,0x00 } },
-{  16, 0xe640, 0, {0x2f,0xc0,0x0d,0x80,0x0a,0x3c,0x00,0xb7,0x00,0x23,0xc2,0x05,0xf0,0x22,0x36,0x00 } },
-{  16, 0xe650, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x04,0x40,0x00,0xb1,0x88,0x20,0x00 } },
-{  16, 0xe660, 0, {0x0b,0x10,0x02,0x0c,0x00,0x83,0x00,0x2e,0xc8,0x0b,0x08,0x06,0x4d,0x40,0x83,0x00 } },
-{  16, 0xe670, 0, {0x20,0xc0,0x08,0x30,0x06,0x0c,0x08,0x93,0x20,0x0a,0xe0,0x4a,0x30,0x02,0x38,0x00 } },
-{  16, 0xe680, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x5a,0x00,0xb5,0x90,0x21,0x20 } },
-{  16, 0xe690, 0, {0x0b,0x58,0x42,0x3e,0x00,0xa7,0x80,0x2d,0xe0,0x0b,0x69,0x02,0xde,0x40,0x87,0x92 } },
-{  16, 0xe6a0, 0, {0x2d,0xe0,0x09,0x18,0x02,0x9e,0x01,0xb7,0x80,0x29,0xe0,0x03,0x70,0x02,0x3e,0x00 } },
-{  16, 0xe6b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x44,0x00,0xf1,0x01,0x30,0x00 } },
-{  16, 0xe6c0, 0, {0x5f,0x18,0x03,0x0c,0x10,0x83,0x00,0x3c,0xc4,0x0e,0x04,0x03,0xec,0x00,0x83,0x00 } },
-{  16, 0xe6d0, 0, {0x30,0xc4,0x0c,0x31,0x03,0x8c,0x00,0xf3,0x00,0x38,0xc8,0x0e,0x31,0x03,0x12,0x02 } },
-{  16, 0xe6e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xbc,0x00,0xfd,0x04,0xbf,0x04 } },
-{  16, 0xe6f0, 0, {0x4f,0x58,0x03,0xf8,0x08,0xef,0x08,0x3f,0xc0,0x0f,0xf0,0x01,0xfc,0x00,0xff,0x4c } },
-{  16, 0xe700, 0, {0x3f,0xc1,0x0f,0xd0,0x03,0x3c,0x00,0xf7,0x00,0x37,0xc2,0x0d,0x72,0x03,0xd0,0x06 } },
-{  16, 0xe710, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xe2,0x00,0xdb,0x00,0x32,0xc0 } },
-{  16, 0xe720, 0, {0x4d,0xa8,0x03,0x2c,0x08,0xfb,0x00,0x7e,0xc8,0x8f,0xb0,0x0b,0x6f,0x45,0xeb,0xc2 } },
-{  16, 0xe730, 0, {0x36,0xc0,0x07,0xa0,0x03,0xef,0x20,0xcb,0x50,0xb2,0xc0,0x0c,0x79,0x03,0x2a,0x00 } },
-{  16, 0xe740, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x19,0x98,0x00,0x8f,0x00,0x21,0xc0 } },
-{  16, 0xe750, 0, {0x0b,0x60,0x03,0x5c,0x00,0x37,0x00,0x2d,0xd2,0x0b,0x30,0x02,0x0c,0xa8,0x87,0x24 } },
-{  16, 0xe760, 0, {0x21,0xd0,0x09,0x70,0x02,0xdd,0x88,0x87,0x2a,0x23,0xe8,0x08,0x70,0x02,0x32,0x04 } },
-{  16, 0xe770, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xb6,0x00,0x97,0x80,0x21,0xe0 } },
-{  16, 0xe780, 0, {0x0b,0x68,0x02,0x1e,0x00,0xb7,0x80,0x2d,0xe8,0x8b,0x48,0x82,0x1e,0x80,0xa3,0x84 } },
-{  16, 0xe790, 0, {0x25,0xe8,0x0b,0x68,0x02,0xce,0x02,0x87,0x80,0x21,0xe0,0x08,0x7a,0x02,0x20,0x00 } },
-{  16, 0xe7a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x04,0xcc,0x08,0x83,0x82,0x20,0xe0 } },
-{  16, 0xe7b0, 0, {0x8b,0x2a,0x02,0x48,0x40,0xb3,0x00,0x2c,0xc0,0x0b,0x30,0x82,0x0c,0x00,0x83,0x00 } },
-{  16, 0xe7c0, 0, {0x00,0xc1,0x09,0x31,0x02,0xcc,0x00,0x83,0x00,0x20,0xc0,0x08,0x30,0x0a,0x12,0x04 } },
-{  16, 0xe7d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xe8,0x00,0xda,0xa0,0x32,0xa8 } },
-{  16, 0xe7e0, 0, {0x8d,0xa8,0x03,0x3b,0x00,0xfa,0x00,0x3e,0x80,0x0f,0xe4,0x03,0x68,0x00,0xea,0x02 } },
-{  16, 0xe7f0, 0, {0x36,0x80,0x0f,0xe4,0x03,0xe8,0x00,0xca,0x00,0x32,0x80,0x2c,0xa0,0x03,0x3a,0x04 } },
-{  16, 0xe800, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x01,0xa0,0x10,0xf8,0x00,0xbe,0x20 } },
-{  16, 0xe810, 0, {0x8f,0xc1,0x03,0xe0,0x24,0xf8,0x00,0x3e,0x10,0x0f,0x84,0x03,0xe0,0x00,0xf8,0x01 } },
-{  16, 0xe820, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x00,0xf8,0x01,0xbe,0x10,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xe830, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xa4,0x00,0xf9,0x40,0x32,0x40 } },
-{  16, 0xe840, 0, {0xcf,0x90,0x03,0xe4,0x00,0xc9,0x00,0x0e,0x50,0x0f,0x1a,0x03,0x26,0x00,0xf9,0x00 } },
-{  16, 0xe850, 0, {0x3e,0x40,0x0f,0x90,0x81,0xe4,0x00,0xf9,0x80,0x32,0x40,0x0c,0x90,0x03,0xc2,0x04 } },
-{  16, 0xe860, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x04,0xb1,0x04,0x22,0x40 } },
-{  16, 0xe870, 0, {0x0b,0x90,0x02,0xe4,0x00,0xa9,0x00,0x2e,0x53,0x0b,0x92,0x0a,0x26,0x48,0xb9,0x04 } },
-{  16, 0xe880, 0, {0x2e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb9,0x80,0x02,0x50,0x08,0x90,0x02,0xe0,0x00 } },
-{  16, 0xe890, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x05,0x24,0x00,0xbd,0x00,0x23,0x40 } },
-{  16, 0xe8a0, 0, {0x0b,0xd0,0x12,0xc4,0x00,0x89,0x02,0x2e,0x40,0x0b,0x90,0x22,0x24,0x00,0xb9,0x00 } },
-{  16, 0xe8b0, 0, {0x2e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb1,0x20,0x20,0x40,0x68,0x90,0x22,0xc6,0x00 } },
-{  16, 0xe8c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x14,0x14,0x00,0xbf,0x12,0xa1,0x40 } },
-{  16, 0xe8d0, 0, {0x0b,0x50,0x02,0xc4,0x00,0xa1,0x20,0x2c,0x48,0x0b,0x12,0x02,0x04,0x10,0xb1,0x11 } },
-{  16, 0xe8e0, 0, {0x2c,0x48,0x0b,0x13,0x22,0xc4,0x00,0xb1,0x40,0x20,0x5a,0x08,0x10,0x02,0xc2,0x01 } },
-{  16, 0xe8f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x40,0x32,0x14 } },
-{  16, 0xe900, 0, {0x0f,0x45,0x03,0xe1,0x40,0xc8,0x50,0x3e,0x15,0x8f,0x85,0x03,0x21,0xe8,0xf8,0x68 } },
-{  16, 0xe910, 0, {0x3e,0x14,0x0f,0x84,0x03,0xe1,0xe0,0xf0,0x28,0x32,0xa8,0xcc,0x80,0x23,0xee,0x03 } },
-{  16, 0xe920, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x15,0xc4,0x10,0xf9,0x20,0x3e,0x40 } },
-{  16, 0xe930, 0, {0x0f,0x90,0x03,0xf4,0x00,0xf9,0x10,0x3e,0x44,0x0f,0xd1,0x03,0xe4,0x00,0xf9,0x20 } },
-{  16, 0xe940, 0, {0x3e,0x44,0x0f,0xd3,0x03,0xe4,0x00,0xf9,0x00,0xbe,0x40,0x0f,0x94,0x03,0xe6,0x06 } },
-{  16, 0xe950, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xe4,0x00,0xfd,0x10,0x33,0x40 } },
-{  16, 0xe960, 0, {0x0c,0xd0,0x03,0x24,0x00,0xd9,0x00,0x3f,0x40,0x4c,0xd0,0x03,0xf6,0x00,0xfd,0x90 } },
-{  16, 0xe970, 0, {0x3a,0x40,0x0c,0x90,0x03,0xe6,0xa0,0xfd,0xa8,0x37,0x68,0x0c,0xd8,0x83,0x26,0x00 } },
-{  16, 0xe980, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x08,0xc8,0xa0,0x22,0x00 } },
-{  16, 0xe990, 0, {0x08,0x80,0x02,0x20,0x00,0x88,0x00,0x2e,0x00,0x0c,0x80,0x12,0xe0,0x00,0xb8,0x80 } },
-{  16, 0xe9a0, 0, {0x22,0x00,0x0d,0x0a,0x02,0xe3,0x80,0xb0,0xc0,0x20,0x34,0x08,0x84,0x03,0x4e,0x04 } },
-{  16, 0xe9b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x84,0x09,0xa1,0x00,0x20,0x41 } },
-{  16, 0xe9c0, 0, {0x08,0x90,0x02,0x24,0x00,0x91,0x00,0x2c,0x40,0x08,0x10,0x02,0xc5,0x00,0xb1,0x60 } },
-{  16, 0xe9d0, 0, {0x20,0x40,0x08,0x10,0xa2,0xc4,0x20,0xb1,0x28,0x24,0x4a,0x08,0x10,0x02,0x52,0x01 } },
-{  16, 0xe9e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x14,0xa4,0x01,0x81,0x00,0xa2,0x40 } },
-{  16, 0xe9f0, 0, {0xa8,0x90,0x00,0x25,0x40,0x89,0x01,0x2c,0x40,0x08,0x94,0x02,0xe4,0x00,0xb9,0x00 } },
-{  16, 0xea00, 0, {0x2a,0x40,0x09,0x90,0x02,0xe4,0x01,0xb9,0x04,0x22,0x41,0x48,0x90,0x02,0x46,0x04 } },
-{  16, 0xea10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x14,0xa5,0x20,0xe9,0x00,0x32,0x40 } },
-{  16, 0xea20, 0, {0x4c,0x10,0x0b,0x26,0x00,0xd9,0x00,0x3e,0x40,0x2c,0x98,0x03,0xe4,0x00,0xf9,0x00 } },
-{  16, 0xea30, 0, {0xb2,0x40,0x0c,0x90,0x03,0xe4,0x00,0xf9,0x00,0x36,0x40,0x2c,0x90,0x03,0x68,0x04 } },
-{  16, 0xea40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x01,0xa4,0x00,0xe9,0x00,0x3e,0x40 } },
-{  16, 0xea50, 0, {0x0f,0x90,0x03,0xe6,0x00,0xf9,0x00,0x3e,0x40,0x0e,0x9a,0x03,0xe4,0x00,0xf9,0x00 } },
-{  16, 0xea60, 0, {0x36,0x40,0x0f,0x90,0x03,0xe4,0x00,0xf9,0x00,0x3c,0x40,0x0f,0x90,0x03,0xda,0x00 } },
-{  16, 0xea70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xa1,0x00,0xf8,0x00,0x32,0x00 } },
-{  16, 0xea80, 0, {0x0f,0x80,0x13,0xa0,0x00,0xc8,0x00,0x32,0x04,0x8c,0x80,0x03,0xa0,0xc0,0xf8,0x00 } },
-{  16, 0xea90, 0, {0x3a,0x00,0x0f,0x80,0x03,0x20,0x00,0xc0,0x09,0x32,0x00,0x4c,0x80,0x01,0x0a,0x04 } },
-{  16, 0xeaa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xbe,0x00,0x20,0x80 } },
-{  16, 0xeab0, 0, {0x0b,0xe0,0x02,0x88,0x00,0xaa,0x00,0x03,0xa0,0x0a,0xe6,0x02,0xfa,0x00,0x8a,0x00 } },
-{  16, 0xeac0, 0, {0x32,0x80,0x0b,0xa0,0x02,0x28,0x00,0x8e,0x80,0xa3,0x80,0x28,0x20,0x02,0x8a,0x00 } },
-{  16, 0xead0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x6c,0x00,0xb3,0x48,0x20,0x40 } },
-{  16, 0xeae0, 0, {0x0b,0x10,0x02,0x0c,0x00,0x83,0x00,0x20,0xc0,0x08,0x34,0x82,0x8e,0x04,0x99,0x00 } },
-{  16, 0xeaf0, 0, {0x0a,0xc0,0x1b,0x30,0x02,0x0c,0x02,0x90,0x50,0x20,0x60,0x08,0x30,0x02,0x0a,0x00 } },
-{  16, 0xeb00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x11,0x1c,0x80,0xbd,0x0a,0x21,0x48 } },
-{  16, 0xeb10, 0, {0x0b,0x52,0x02,0x9c,0x40,0xa3,0xa0,0x20,0x80,0x0a,0x60,0x02,0xce,0x00,0x85,0x20 } },
-{  16, 0xeb20, 0, {0x21,0xc4,0x0b,0x7a,0x06,0x1e,0x80,0x95,0x20,0x21,0x90,0x08,0x70,0x02,0x28,0x00 } },
-{  16, 0xeb30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x08,0x1e,0x80,0xf7,0x80,0xb1,0x79 } },
-{  16, 0xeb40, 0, {0x0f,0xdb,0x02,0x3e,0x20,0xc7,0xa0,0xb1,0x60,0xcc,0x78,0x13,0x96,0x00,0xf1,0xf0 } },
-{  16, 0xeb50, 0, {0x39,0xe2,0x0f,0x7b,0x13,0x0f,0x00,0xd4,0xa0,0x31,0x60,0x2c,0x70,0x03,0x2a,0x02 } },
-{  16, 0xeb60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x15,0xac,0x00,0xf7,0x00,0x3e,0x40 } },
-{  16, 0xeb70, 0, {0x0f,0x90,0x03,0xed,0x80,0xfb,0x10,0x3e,0x40,0x0b,0xb0,0x23,0xec,0x00,0xf9,0x20 } },
-{  16, 0xeb80, 0, {0x3a,0xd8,0x0f,0xb0,0x0b,0xed,0x81,0xed,0x10,0x3e,0x80,0x0f,0x30,0x03,0xc2,0x06 } },
-{  16, 0xeb90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xbe,0x20,0xee,0x80,0x33,0x60 } },
-{  16, 0xeba0, 0, {0x0c,0xd8,0x83,0x1e,0x00,0x6f,0x80,0x33,0xe0,0x0f,0xb8,0x11,0x32,0x04,0xf5,0x80 } },
-{  16, 0xebb0, 0, {0x33,0xe0,0x0f,0xf8,0x83,0x2f,0x40,0xfe,0x80,0xb3,0xe0,0x0c,0xf8,0x03,0x10,0x00 } },
-{  16, 0xebc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x18,0x9c,0x00,0xbc,0x00,0xa1,0x44 } },
-{  16, 0xebd0, 0, {0x08,0x10,0x03,0x5c,0x00,0x8f,0x00,0x21,0x80,0x0b,0xea,0x22,0x1c,0x80,0xb5,0x01 } },
-{  16, 0xebe0, 0, {0x21,0xc0,0x0b,0xf0,0x02,0x1e,0x80,0xbe,0x00,0x23,0x80,0x2a,0x70,0x02,0x2a,0x04 } },
-{  16, 0xebf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x20,0xa7,0x00,0x23,0x40 } },
-{  16, 0xec00, 0, {0x0b,0x50,0x0a,0x3c,0x00,0xa7,0x00,0x25,0xc0,0x0a,0x43,0x02,0x10,0x00,0xb5,0x00 } },
-{  16, 0xec10, 0, {0x21,0xc0,0x0b,0x70,0x82,0x1c,0x80,0xb4,0x00,0x21,0xc0,0x08,0x70,0x02,0x04,0x00 } },
-{  16, 0xec20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x04,0x8e,0x04,0xb3,0x00,0x22,0x40 } },
-{  16, 0xec30, 0, {0x09,0x14,0x02,0x4c,0x00,0x83,0x00,0x20,0xc0,0x0b,0x24,0x82,0x04,0x00,0xb1,0x00 } },
-{  16, 0xec40, 0, {0x20,0xc0,0x8b,0x3a,0x02,0x2c,0x01,0xb0,0x00,0x20,0x80,0x0a,0x30,0x02,0x1a,0x04 } },
-{  16, 0xec50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0x9e,0x00,0xeb,0x04,0x33,0x40 } },
-{  16, 0xec60, 0, {0x2d,0xdc,0x03,0x1d,0x60,0xef,0x00,0x32,0x00,0xcf,0x9a,0x03,0x28,0x00,0xfd,0x00 } },
-{  16, 0xec70, 0, {0x33,0xc1,0x8b,0xfc,0x0b,0x3c,0x00,0xfc,0x00,0x32,0x80,0x0c,0x90,0x03,0x2a,0x04 } },
-{  16, 0xec80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xac,0x10,0xf8,0x00,0x3e,0x40 } },
-{  16, 0xec90, 0, {0x0e,0x98,0x23,0xac,0x04,0xfb,0x00,0x3c,0x00,0x0f,0x84,0x20,0xed,0x00,0xf9,0x00 } },
-{  16, 0xeca0, 0, {0x3e,0xc0,0x4f,0xb0,0x03,0xec,0x00,0xfd,0x00,0x3e,0x80,0x0f,0x90,0x03,0xe4,0x00 } },
-{  16, 0xecb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x10,0xfc,0x00,0xcf,0x80,0x33,0x40 } },
-{  16, 0xecc0, 0, {0x0c,0xd0,0x83,0xfc,0x00,0xef,0x00,0x3f,0x40,0x0c,0xf1,0x41,0x30,0x10,0xcd,0x00 } },
-{  16, 0xecd0, 0, {0x3f,0xc0,0x00,0x70,0x13,0x3c,0x00,0xe4,0x00,0xb1,0xd0,0x0c,0x10,0x03,0x20,0x04 } },
-{  16, 0xece0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa1,0x04,0x2c,0x00,0x8a,0xe4,0x2a,0x40 } },
-{  16, 0xecf0, 0, {0x28,0x90,0x02,0xec,0x00,0x8b,0x00,0x3e,0x02,0x0a,0x80,0x02,0x2c,0x82,0x89,0x04 } },
-{  16, 0xed00, 0, {0x2e,0xc1,0x0a,0xb0,0x0a,0x2c,0x00,0x89,0x02,0x22,0xf2,0x2a,0x98,0x02,0x20,0x00 } },
-{  16, 0xed10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x02,0x80,0x14,0x2a,0x40 } },
-{  16, 0xed20, 0, {0x08,0x90,0x02,0xec,0x08,0xab,0x04,0x2e,0x84,0x08,0x10,0x82,0x80,0x10,0x89,0x03 } },
-{  16, 0xed30, 0, {0x2c,0xc0,0x4a,0xb0,0x22,0x2c,0x00,0xaa,0x00,0x22,0x80,0x08,0x91,0x02,0x20,0x00 } },
-{  16, 0xed40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x2c,0x00,0x80,0x00,0x28,0x40 } },
-{  16, 0xed50, 0, {0x08,0x11,0x02,0xec,0x00,0x83,0x00,0x2c,0x81,0x0a,0x00,0x5a,0x88,0x00,0x01,0x00 } },
-{  16, 0xed60, 0, {0x2c,0xc0,0x0a,0x30,0x02,0x0c,0x00,0x82,0x00,0x20,0x80,0x0a,0x10,0x02,0x02,0x01 } },
-{  16, 0xed70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xc9,0x00,0x3a,0x40 } },
-{  16, 0xed80, 0, {0x0c,0xd4,0x03,0xfc,0x00,0xeb,0x00,0x3e,0x40,0x0c,0x92,0x03,0xa0,0x00,0x4d,0x00 } },
-{  16, 0xed90, 0, {0x3f,0xc0,0x0e,0xf0,0x33,0x3c,0x80,0xe8,0x00,0x32,0xc0,0x0c,0x90,0x03,0x20,0x03 } },
-{  16, 0xeda0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x11,0xfc,0x00,0xfc,0x00,0x3d,0x40 } },
-{  16, 0xedb0, 0, {0x0f,0x50,0x03,0xfc,0x02,0x3f,0x04,0x3b,0x01,0x4f,0xc4,0x13,0x70,0x00,0xfd,0x00 } },
-{  16, 0xedc0, 0, {0x3f,0xc0,0x1f,0xf0,0x01,0xfc,0x40,0xfc,0x00,0x3f,0xc0,0x0f,0xd0,0x13,0xe8,0x06 } },
-{  16, 0xedd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf8,0xe0,0xff,0x80,0x3d,0xc0 } },
-{  16, 0xede0, 0, {0x0d,0xf3,0x82,0xf0,0x80,0xff,0x40,0x31,0xcb,0x0c,0xf3,0x03,0xfd,0x04,0xef,0xc1 } },
-{  16, 0xedf0, 0, {0x33,0xe0,0x0f,0x79,0x03,0xfe,0x00,0xcf,0x42,0x33,0xf0,0x4c,0xf8,0x03,0x30,0x00 } },
-{  16, 0xee00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x10,0xe9,0x08,0xb9,0x81,0x2f,0xf0 } },
-{  16, 0xee10, 0, {0x08,0xf4,0x52,0xe9,0x20,0xbf,0x40,0x23,0xf0,0x0a,0xf3,0x02,0xfd,0x08,0x8b,0x00 } },
-{  16, 0xee20, 0, {0x36,0xe0,0x0b,0x80,0x22,0xe8,0x80,0x8f,0x40,0x22,0xc0,0x08,0xb0,0x82,0x30,0x04 } },
-{  16, 0xee30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xcc,0x00,0xb1,0x80,0x2c,0xc5 } },
-{  16, 0xee40, 0, {0x09,0x32,0x42,0xc8,0xc0,0xb3,0x31,0x20,0xc1,0x08,0x32,0x02,0xcc,0xd4,0xbb,0x20 } },
-{  16, 0xee50, 0, {0x68,0xc0,0x0b,0x30,0x02,0xcc,0x20,0x93,0x60,0x20,0x88,0x08,0x32,0x02,0x32,0x01 } },
-{  16, 0xee60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x15,0xa0,0x00,0xbb,0x80,0x2e,0xc0 } },
-{  16, 0xee70, 0, {0x08,0xb0,0x02,0xea,0x00,0xbb,0x00,0x62,0xc1,0x0a,0xb0,0x02,0xcc,0x00,0xab,0x00 } },
-{  16, 0xee80, 0, {0x2e,0xc0,0x0b,0xa0,0x00,0xe8,0x00,0x83,0x00,0x22,0xc1,0x08,0x30,0x02,0x30,0x04 } },
-{  16, 0xee90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xe8,0x90,0xfb,0x80,0x3e,0xc0 } },
-{  16, 0xeea0, 0, {0x0d,0xb0,0x03,0xe2,0x10,0xfb,0x00,0x32,0xc0,0x4c,0xb0,0x13,0xec,0x00,0xe9,0x54 } },
-{  16, 0xeeb0, 0, {0x3a,0xc0,0x0f,0xb0,0x03,0xe6,0x00,0xcb,0x00,0xb2,0x40,0x0c,0xb0,0x03,0x04,0x04 } },
-{  16, 0xeec0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x00,0xff,0x00,0x3f,0xc0 } },
-{  16, 0xeed0, 0, {0x8f,0xf0,0x03,0xf0,0x00,0xf7,0x02,0xbf,0xc1,0x0f,0xf0,0x23,0xfc,0x00,0xdf,0x06 } },
-{  16, 0xeee0, 0, {0x37,0xc0,0x8f,0xc9,0x07,0xfa,0x92,0xff,0x04,0x3f,0x50,0x2f,0xf0,0x03,0xf8,0x00 } },
-{  16, 0xeef0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x10,0xac,0x00,0xc9,0x00,0x3e,0xc2 } },
-{  16, 0xef00, 0, {0x0e,0xb0,0x23,0xe4,0x00,0xeb,0x00,0x3a,0xc8,0x0e,0xb0,0x03,0xec,0x00,0xf9,0x00 } },
-{  16, 0xef10, 0, {0x3e,0xc0,0x0f,0xb4,0x03,0xa4,0x00,0xfb,0x00,0x3e,0x80,0x0f,0xb0,0x83,0xd0,0x04 } },
-{  16, 0xef20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x28,0x00,0x8b,0x74,0x2d,0xc0 } },
-{  16, 0xef30, 0, {0x08,0xf0,0x02,0xe4,0x00,0x8f,0x00,0x21,0xf0,0x08,0xf0,0x02,0xfc,0x10,0xd3,0x00 } },
-{  16, 0xef40, 0, {0x2e,0xc0,0x0b,0x90,0x12,0x2c,0x00,0xef,0x00,0x2e,0xc0,0x0b,0xb6,0x02,0xf6,0x00 } },
-{  16, 0xef50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x05,0x48,0x00,0xa3,0x00,0x2c,0xc4 } },
-{  16, 0xef60, 0, {0x0a,0x30,0x02,0xc0,0x00,0xa3,0x00,0x68,0xf0,0x0a,0x30,0x12,0xcc,0x04,0xa2,0x00 } },
-{  16, 0xef70, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xec,0x00,0xb3,0x01,0x2e,0xc0,0x0b,0x34,0x02,0xf8,0x00 } },
-{  16, 0xef80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x01,0x0c,0x00,0x87,0x80,0x2d,0xe8 } },
-{  16, 0xef90, 0, {0x08,0x78,0x42,0xda,0x00,0x87,0x80,0x25,0xe0,0x08,0x79,0x02,0xce,0x00,0x96,0x80 } },
-{  16, 0xefa0, 0, {0x2d,0xe0,0x0b,0xd9,0x02,0xde,0x00,0xa7,0x80,0x2d,0xe0,0x0b,0x78,0x02,0xfc,0x00 } },
-{  16, 0xefb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x40,0xe3,0x10,0x3c,0xc0 } },
-{  16, 0xefc0, 0, {0x0a,0x38,0x03,0xe8,0x00,0xeb,0x00,0x38,0xc2,0x0a,0x30,0x03,0xcc,0x00,0xe3,0x40 } },
-{  16, 0xefd0, 0, {0x3c,0xc0,0x0f,0x34,0x03,0xcd,0x00,0xf3,0x20,0x3c,0x88,0x0f,0x30,0x03,0xd2,0x02 } },
-{  16, 0xefe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb4,0x80,0xff,0x04,0x3f,0xc8 } },
-{  16, 0xeff0, 0, {0x0f,0xf0,0x83,0xf8,0x40,0xff,0x18,0x3b,0xc0,0x0f,0xf4,0x83,0xfc,0x00,0xee,0x02 } },
-{  16, 0xf000, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0x3c,0x00,0xef,0x08,0x3f,0x80,0x0f,0xf0,0x13,0xd0,0x06 } },
-{  16, 0xf010, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xe8,0x00,0xcb,0x00,0x3e,0xf2 } },
-{  16, 0xf020, 0, {0x4d,0xb2,0x13,0xe8,0x04,0xcb,0x01,0x32,0xf8,0x4d,0xb2,0x13,0x6d,0x20,0xf8,0x00 } },
-{  16, 0xf030, 0, {0x3e,0xc0,0x0f,0x30,0x03,0x24,0x00,0xfb,0x00,0x3e,0x40,0x8f,0xb8,0x03,0x2a,0x00 } },
-{  16, 0xf040, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x11,0x8c,0x00,0x86,0x00,0x2c,0xc0 } },
-{  16, 0xf050, 0, {0x08,0x73,0x02,0xd8,0x12,0x87,0x30,0x20,0xcb,0x08,0xf2,0x02,0x1d,0x05,0xb5,0x00 } },
-{  16, 0xf060, 0, {0x2d,0xc0,0x0b,0x60,0x03,0x50,0x10,0xb7,0x09,0x2d,0xc0,0x0b,0xf0,0x02,0x32,0x04 } },
-{  16, 0xf070, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x9e,0x00,0x87,0x80,0x2d,0xe4 } },
-{  16, 0xf080, 0, {0x09,0x7a,0x02,0xce,0x01,0x87,0x80,0x21,0xec,0x09,0x78,0x02,0x5e,0x80,0xb7,0xc0 } },
-{  16, 0xf090, 0, {0x2d,0xe0,0x0b,0xf8,0x02,0x1e,0x00,0xb7,0xa0,0x2d,0x60,0x0b,0x78,0x02,0x20,0x00 } },
-{  16, 0xf0a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xee,0x00,0x82,0x80,0x2c,0xc0 } },
-{  16, 0xf0b0, 0, {0x08,0x30,0x02,0xec,0x00,0x83,0x00,0xa0,0xc0,0x08,0x30,0x02,0x0c,0x00,0xb3,0x80 } },
-{  16, 0xf0c0, 0, {0x2c,0xc1,0x0b,0x30,0x02,0x4e,0x00,0xb3,0x00,0x2c,0xf1,0x0b,0x30,0x0a,0x12,0x04 } },
-{  16, 0xf0d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xba,0x80,0xc6,0x00,0x3e,0x80 } },
-{  16, 0xf0e0, 0, {0x0d,0xa0,0x03,0xf8,0x40,0xca,0x00,0x32,0x80,0x0d,0xa0,0x13,0x68,0x00,0xfe,0x02 } },
-{  16, 0xf0f0, 0, {0x7e,0x80,0x0f,0xed,0x83,0x39,0x10,0xfa,0x00,0x3f,0x8c,0x0f,0xa0,0x03,0x3a,0x04 } },
-{  16, 0xf100, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x12,0xf8,0x90,0x3e,0x00 } },
-{  16, 0xf110, 0, {0x0f,0x80,0x03,0xe0,0x00,0xf8,0x05,0x3e,0x00,0x0e,0x00,0x03,0xe0,0x00,0xf8,0x80 } },
-{  16, 0xf120, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x60,0xf8,0x00,0x7e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xf130, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xc9,0x80,0x32,0x64 } },
-{  16, 0xf140, 0, {0x0f,0x90,0x43,0xe4,0x06,0xc1,0x04,0x3a,0x40,0x0f,0x90,0x03,0xe4,0x00,0xe9,0x00 } },
-{  16, 0xf150, 0, {0x32,0x40,0x0f,0x90,0x03,0x24,0x00,0xc1,0x01,0x32,0x40,0x0c,0x90,0x03,0xc2,0x04 } },
-{  16, 0xf160, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0xc0,0x22,0x40 } },
-{  16, 0xf170, 0, {0x0b,0x90,0x02,0x24,0x00,0x89,0x00,0x22,0x50,0x1b,0x90,0x22,0x24,0x00,0x81,0x00 } },
-{  16, 0xf180, 0, {0x22,0x40,0x0b,0x90,0x22,0x24,0x08,0xc9,0x00,0x20,0x40,0x08,0x94,0x02,0xe0,0x00 } },
-{  16, 0xf190, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x99,0x20,0x22,0x40 } },
-{  16, 0xf1a0, 0, {0x0b,0x10,0x02,0xa4,0x00,0x89,0x00,0x2a,0x58,0x0b,0x90,0x02,0x84,0x00,0xa9,0x00 } },
-{  16, 0xf1b0, 0, {0x22,0x40,0x0b,0x10,0x0a,0x04,0x00,0x99,0x02,0x22,0xc1,0x08,0x90,0x82,0xc6,0x00 } },
-{  16, 0xf1c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x91,0x02,0xa0,0xc8 } },
-{  16, 0xf1d0, 0, {0x0b,0x12,0x02,0x04,0x80,0x81,0x22,0x20,0x48,0x9b,0x12,0x02,0x04,0x90,0x89,0x01 } },
-{  16, 0xf1e0, 0, {0x20,0x40,0x0b,0x10,0x02,0x04,0x02,0x81,0x22,0x22,0x40,0x08,0x10,0x02,0xc2,0x01 } },
-{  16, 0xf1f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x42,0xda,0x01,0x32,0x01 } },
-{  16, 0xf200, 0, {0x0f,0x85,0x03,0xa1,0x40,0xc0,0x50,0x3a,0x01,0x8b,0x85,0x23,0xa1,0x44,0xe8,0x50 } },
-{  16, 0xf210, 0, {0xb2,0x00,0x0f,0x85,0x03,0x21,0x48,0xd8,0x51,0x32,0x14,0x2c,0x85,0x03,0xee,0x03 } },
-{  16, 0xf220, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf5,0x00,0xed,0x02,0x3e,0x44 } },
-{  16, 0xf230, 0, {0x0f,0x91,0x03,0xf4,0x40,0xf9,0x10,0x3e,0x44,0x0f,0x91,0x03,0xe4,0x40,0xfd,0x00 } },
-{  16, 0xf240, 0, {0x3e,0x40,0x0f,0xd0,0x03,0xf4,0x00,0xe9,0x10,0xbf,0x40,0x0f,0x90,0x03,0x66,0x06 } },
-{  16, 0xf250, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0x21,0xc5,0x00,0x33,0x68 } },
-{  16, 0xf260, 0, {0x0f,0x9a,0x03,0x6f,0x88,0xc9,0xc0,0x33,0x68,0x0c,0x9e,0x03,0x27,0x80,0xd9,0x40 } },
-{  16, 0xf270, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc5,0x10,0xd9,0xe8,0x36,0x50,0x0c,0xd0,0x03,0xe6,0x00 } },
-{  16, 0xf280, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x08,0x88,0x00,0x82,0x00 } },
-{  16, 0xf290, 0, {0x0b,0x8e,0x82,0xeb,0xc8,0x88,0xe0,0x22,0x00,0x28,0x88,0x42,0xa2,0x80,0x8a,0x80 } },
-{  16, 0xf2a0, 0, {0x22,0x00,0x0b,0xaa,0x02,0xe2,0x00,0x88,0xc0,0x22,0xa9,0x08,0x8a,0x03,0x8e,0x04 } },
-{  16, 0xf2b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc4,0x00,0x81,0x00,0x20,0xd0 } },
-{  16, 0xf2c0, 0, {0x0b,0x11,0x32,0x84,0x84,0x81,0x60,0x60,0x50,0x08,0x16,0x06,0x05,0x00,0x91,0x20 } },
-{  16, 0xf2d0, 0, {0x20,0x40,0x0b,0x10,0x82,0xe4,0x09,0x91,0x20,0x24,0x40,0x08,0x10,0xc2,0xd2,0x01 } },
-{  16, 0xf2e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x04,0x89,0x04,0x22,0x40 } },
-{  16, 0xf2f0, 0, {0x0b,0x90,0x02,0xc4,0x00,0xa9,0x00,0x22,0x41,0x00,0x90,0x02,0xa4,0x00,0x81,0x00 } },
-{  16, 0xf300, 0, {0x22,0x40,0x0b,0x92,0x22,0xe5,0x80,0x99,0x01,0x22,0x61,0x08,0x90,0x02,0x86,0x04 } },
-{  16, 0xf310, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x14,0xa5,0x82,0x81,0x90,0x32,0x40 } },
-{  16, 0xf320, 0, {0x0f,0x90,0x13,0x67,0x02,0xc9,0x00,0x32,0x40,0x0c,0x90,0x23,0x24,0x04,0xd9,0xc0 } },
-{  16, 0xf330, 0, {0xb2,0x40,0x0f,0x9c,0x03,0xe6,0x00,0xd9,0x00,0x36,0x50,0x0c,0x90,0x03,0xe8,0x04 } },
-{  16, 0xf340, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0xa6,0x80,0xf9,0x00,0x3e,0x40 } },
-{  16, 0xf350, 0, {0x0f,0x90,0x03,0xe7,0x00,0xd9,0x00,0xbc,0x42,0x0f,0x90,0x53,0xe4,0x04,0xf9,0x10 } },
-{  16, 0xf360, 0, {0x3e,0x40,0x0f,0x98,0x03,0xe6,0x04,0xe1,0x00,0x3e,0x40,0x2f,0x90,0x03,0xda,0x00 } },
-{  16, 0xf370, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0x81,0x10,0x48,0x10,0x32,0x08 } },
-{  16, 0xf380, 0, {0x0c,0x80,0x0f,0x21,0x02,0xc8,0x00,0x3a,0x04,0x0f,0x80,0x07,0x60,0x00,0xf8,0x40 } },
-{  16, 0xf390, 0, {0xb2,0x00,0x0f,0x84,0x0b,0x20,0x00,0xd8,0x00,0x36,0x10,0x0c,0x80,0x03,0xca,0x04 } },
-{  16, 0xf3a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x04,0x28,0x04,0x8e,0x80,0x23,0x80 } },
-{  16, 0xf3b0, 0, {0x08,0xa0,0x42,0x28,0x00,0x8a,0x00,0x23,0xa0,0x4b,0xa0,0x02,0xe8,0x00,0xba,0x00 } },
-{  16, 0xf3c0, 0, {0x76,0x80,0x0b,0xa0,0x02,0x08,0x00,0x8a,0x00,0x32,0x80,0x08,0xe0,0x03,0xca,0x00 } },
-{  16, 0xf3d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x82,0x00,0x20,0xd0 } },
-{  16, 0xf3e0, 0, {0x08,0x30,0x02,0x0c,0x00,0x9b,0x00,0x28,0xc0,0x1a,0xb0,0x02,0x6c,0x00,0xb3,0x02 } },
-{  16, 0xf3f0, 0, {0x20,0xc0,0x0b,0x30,0x02,0x0c,0x00,0xa3,0x00,0x22,0xc0,0x28,0x34,0x82,0xca,0x00 } },
-{  16, 0xf400, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1c,0x00,0x87,0x00,0x20,0xe0 } },
-{  16, 0xf410, 0, {0x08,0x78,0x02,0x0c,0x00,0x97,0x20,0x25,0xc0,0x0b,0x71,0x02,0xdc,0x81,0xb7,0x20 } },
-{  16, 0xf420, 0, {0x21,0xc0,0x0b,0x7a,0x42,0x3c,0x80,0x87,0x20,0x21,0xc0,0x08,0x70,0x02,0xe8,0x00 } },
-{  16, 0xf430, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x08,0x0e,0x82,0xc7,0x80,0xb1,0xe0 } },
-{  16, 0xf440, 0, {0x2c,0xfa,0x06,0x1e,0x08,0xd3,0xb1,0x39,0x60,0x4e,0x78,0x12,0x5e,0xa0,0xff,0xf0 } },
-{  16, 0xf450, 0, {0x21,0xe0,0x0f,0xf8,0x03,0x1f,0x08,0xe3,0xa0,0x33,0xe0,0x0c,0x68,0x03,0xea,0x02 } },
-{  16, 0xf460, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x40,0xfb,0x00,0x3e,0xc0 } },
-{  16, 0xf470, 0, {0x0f,0xb2,0x03,0xed,0xa8,0xeb,0x10,0x3a,0x80,0x0f,0xb0,0xc3,0xec,0x40,0xfb,0x00 } },
-{  16, 0xf480, 0, {0x3e,0xc0,0x0f,0xb0,0x83,0xec,0x80,0xeb,0x70,0xbe,0xc4,0x0f,0xb0,0x03,0x82,0x06 } },
-{  16, 0xf490, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x00,0xce,0x80,0xb3,0x60 } },
-{  16, 0xf4a0, 0, {0x0f,0xfc,0x83,0x7e,0x20,0xef,0xb0,0x3b,0xe0,0x0f,0xb8,0x03,0x3e,0x00,0xcf,0x81 } },
-{  16, 0xf4b0, 0, {0x3f,0xe0,0x8f,0xf8,0x83,0xef,0x40,0xff,0xc2,0x33,0xe1,0x0c,0xf8,0x03,0xd0,0x00 } },
-{  16, 0xf4c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x82,0x87,0x18,0x21,0x80 } },
-{  16, 0xf4d0, 0, {0x0b,0x30,0x02,0x1c,0x60,0xd7,0x10,0x21,0xd0,0x0b,0x7b,0x02,0x3c,0x00,0xd7,0x00 } },
-{  16, 0xf4e0, 0, {0x2d,0xc0,0x0b,0x70,0x02,0xde,0x00,0xbf,0x00,0xa3,0xc4,0x08,0x70,0x03,0xaa,0x04 } },
-{  16, 0xf4f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x11,0x87,0x00,0x21,0xc0 } },
-{  16, 0xf500, 0, {0x0b,0x30,0x02,0x1c,0x00,0x93,0x20,0x69,0xc0,0x0b,0x70,0x02,0x1c,0x00,0x87,0x00 } },
-{  16, 0xf510, 0, {0x2d,0xc0,0x0b,0x71,0x02,0xdc,0x20,0xb7,0x10,0x21,0xc0,0x08,0x60,0x02,0x84,0x00 } },
-{  16, 0xf520, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xcd,0x00,0x83,0x40,0x20,0xc0 } },
-{  16, 0xf530, 0, {0x4b,0x30,0x02,0x0c,0x01,0x83,0x00,0x20,0xc0,0x0b,0x30,0x02,0x0c,0x00,0x93,0x80 } },
-{  16, 0xf540, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x01,0xb3,0x00,0x20,0xc0,0x08,0x30,0x22,0x98,0x04 } },
-{  16, 0xf550, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbf,0x20,0xca,0xc0,0x32,0x80 } },
-{  16, 0xf560, 0, {0x0f,0xf0,0x03,0x3e,0x00,0x9f,0x00,0x3a,0x80,0x0f,0xf0,0x0b,0x3c,0x00,0xcf,0x98 } },
-{  16, 0xf570, 0, {0x3e,0xc0,0x0f,0xf6,0x03,0xff,0x00,0xff,0x00,0x31,0xe0,0x2c,0xb0,0x03,0xae,0x04 } },
-{  16, 0xf580, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xcc,0x80,0xfb,0x00,0x3e,0x50 } },
-{  16, 0xf590, 0, {0x0f,0xb0,0x03,0xac,0x02,0xfb,0x00,0x7e,0x50,0x0f,0xb0,0x03,0xec,0x00,0xfb,0x00 } },
-{  16, 0xf5a0, 0, {0x3e,0xc0,0x0f,0xb2,0x03,0xec,0x20,0xf3,0x00,0x3e,0xc6,0x0f,0x90,0x03,0xa0,0x00 } },
-{  16, 0xf5b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x02,0xcf,0x98,0x73,0xc8 } },
-{  16, 0xf5c0, 0, {0x0f,0x70,0x03,0x3c,0x00,0xff,0x00,0x33,0x28,0x0f,0xb0,0x02,0x1c,0x00,0x4f,0x00 } },
-{  16, 0xf5d0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x01,0x33,0xc0,0x0c,0xe4,0x03,0xe4,0x04 } },
-{  16, 0xf5e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x6c,0x00,0x83,0x80,0xa2,0xf8 } },
-{  16, 0xf5f0, 0, {0x0b,0xb0,0x42,0x2c,0x00,0xbb,0x00,0x32,0x10,0x0f,0xb0,0x03,0x6c,0x04,0xab,0x00 } },
-{  16, 0xf600, 0, {0x2e,0xc0,0x0b,0xb0,0x12,0xec,0x04,0xeb,0x00,0x22,0xc0,0x4a,0x94,0x82,0xe0,0x00 } },
-{  16, 0xf610, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x6c,0x00,0x8a,0x00,0x22,0x00 } },
-{  16, 0xf620, 0, {0x0b,0xb0,0x02,0x2c,0x00,0xb3,0x00,0xa2,0xc0,0x0b,0x30,0x02,0xac,0x00,0xab,0x04 } },
-{  16, 0xf630, 0, {0x2e,0xc0,0x0b,0xb0,0x42,0xec,0x00,0xbb,0x00,0x22,0xc0,0x08,0xb0,0x22,0xe0,0x00 } },
-{  16, 0xf640, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0c,0x00,0x8b,0x01,0x20,0x00 } },
-{  16, 0xf650, 0, {0x0b,0x30,0x06,0x0c,0x00,0xb3,0x00,0x20,0xc0,0x0a,0x32,0x0a,0xcc,0x00,0xa3,0x00 } },
-{  16, 0xf660, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x00,0xa3,0x00,0x22,0xc0,0x4a,0x00,0x12,0xc2,0x01 } },
-{  16, 0xf670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x6c,0x00,0x8b,0x04,0x22,0xc0 } },
-{  16, 0xf680, 0, {0x0f,0xf1,0x03,0x1c,0x00,0xff,0x04,0x32,0xc0,0x0b,0xf2,0x03,0xbc,0x00,0xef,0x00 } },
-{  16, 0xf690, 0, {0x3e,0xc0,0x07,0xf0,0x03,0xfc,0x80,0xff,0x00,0xb2,0xc0,0x0c,0xa0,0x03,0xe0,0x03 } },
-{  16, 0xf6a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xdc,0x00,0xf5,0x00,0x3f,0xc0 } },
-{  16, 0xf6b0, 0, {0x0f,0xf0,0x03,0xfc,0x01,0xff,0x02,0x3b,0xc0,0x0f,0xf1,0x03,0x7c,0x00,0xff,0x00 } },
-{  16, 0xf6c0, 0, {0x3f,0xc0,0x0f,0xf0,0x13,0xfc,0x40,0xef,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xe8,0x06 } },
-{  16, 0xf6d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xf2,0x40,0xcc,0x80,0x37,0x20 } },
-{  16, 0xf6e0, 0, {0x0c,0xd8,0x03,0xb0,0x44,0xfc,0x08,0x3f,0x0e,0x0f,0xc1,0x03,0xfc,0x00,0xcc,0x94 } },
-{  16, 0xf6f0, 0, {0x3f,0x0a,0x2e,0xc4,0x03,0x7d,0x80,0xcf,0x10,0x3f,0xc0,0x0f,0xc0,0x83,0x30,0x00 } },
-{  16, 0xf700, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0xe0,0x90,0x88,0x02,0x22,0x81 } },
-{  16, 0xf710, 0, {0x08,0x92,0x13,0xa4,0x40,0x3b,0x60,0x22,0x18,0x0b,0x81,0x02,0xfc,0xd4,0x81,0x00 } },
-{  16, 0xf720, 0, {0x3a,0xb0,0x0a,0x94,0x02,0x3d,0x40,0xaf,0x63,0x2f,0xdf,0x0b,0x98,0x00,0x20,0x04 } },
-{  16, 0xf730, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xe0,0x00,0x88,0x00,0x20,0x40 } },
-{  16, 0xf740, 0, {0x88,0x30,0x82,0xc0,0x00,0xb0,0x08,0x28,0x80,0x0a,0x10,0x02,0xcc,0x20,0x80,0x01 } },
-{  16, 0xf750, 0, {0x2c,0x40,0x1b,0x06,0x02,0x8c,0x90,0x93,0x60,0x68,0xc0,0x4a,0x00,0x42,0x22,0x01 } },
-{  16, 0xf760, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xa0,0x02,0x88,0x00,0x22,0xc0 } },
-{  16, 0xf770, 0, {0x08,0xb0,0x02,0xe4,0x20,0xbb,0x88,0x26,0x98,0x0b,0x80,0x42,0xcc,0x18,0x8a,0x00 } },
-{  16, 0xf780, 0, {0x2e,0xc2,0x1b,0x98,0x02,0xac,0x00,0xab,0x00,0x2e,0xc0,0x0b,0x98,0x82,0x30,0x04 } },
-{  16, 0xf790, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xe3,0xc0,0xcb,0x02,0x32,0x00 } },
-{  16, 0xf7a0, 0, {0x2c,0x80,0x03,0xae,0x08,0xb9,0x00,0x3e,0x70,0x0f,0xb9,0x03,0xec,0x02,0x48,0x48 } },
-{  16, 0xf7b0, 0, {0x3c,0xc0,0x0f,0x8c,0x93,0xec,0x00,0xdb,0x00,0x1a,0xc0,0x0e,0xac,0x03,0x10,0x04 } },
-{  16, 0xf7c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb2,0x00,0xff,0x00,0xbb,0x80 } },
-{  16, 0xf7d0, 0, {0x0f,0xc0,0x43,0xb6,0x40,0xbd,0x00,0x3b,0x60,0x0f,0xe8,0x03,0xfc,0x00,0xff,0x94 } },
-{  16, 0xf7e0, 0, {0x3b,0xe4,0x0e,0x60,0x0f,0x6c,0x08,0xef,0x01,0x3f,0xc0,0x0f,0x60,0x03,0xf8,0x00 } },
-{  16, 0xf7f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa1,0x00,0xfb,0x00,0x3e,0x60 } },
-{  16, 0xf800, 0, {0x0f,0xa0,0x03,0xed,0x00,0xf9,0x40,0x3a,0x00,0x0f,0x90,0x03,0xec,0x02,0xc9,0x04 } },
-{  16, 0xf810, 0, {0x32,0xd0,0x0f,0x90,0x03,0x2c,0x08,0xdb,0x00,0xb6,0xc0,0x0d,0xb4,0x03,0xd0,0x04 } },
-{  16, 0xf820, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x00,0x00,0xb3,0x89,0x2e,0xe0 } },
-{  16, 0xf830, 0, {0x0b,0xa4,0x03,0xa4,0x01,0xb9,0x00,0x2e,0x01,0x0b,0x90,0x42,0xfc,0x10,0x89,0x50 } },
-{  16, 0xf840, 0, {0xa2,0xc0,0x8d,0xb4,0x02,0x3c,0x44,0x8f,0x00,0x23,0xc0,0x08,0xb0,0x02,0xf2,0x00 } },
-{  16, 0xf850, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x04,0x0c,0x00,0xb0,0x80,0x2e,0x00 } },
-{  16, 0xf860, 0, {0x0b,0x12,0x02,0xc8,0x00,0xba,0x00,0x2c,0xc0,0x0b,0x20,0x02,0xcc,0x00,0xa2,0x00 } },
-{  16, 0xf870, 0, {0x20,0x00,0x2b,0x2d,0x9a,0x2e,0x42,0x83,0x00,0x28,0xc0,0x08,0x20,0x02,0xf8,0x00 } },
-{  16, 0xf880, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x1e,0x04,0xb4,0x80,0x2d,0xa0 } },
-{  16, 0xf890, 0, {0x0b,0x58,0x02,0x92,0x00,0xb6,0x80,0x2d,0xe0,0x0b,0x68,0x02,0xde,0x40,0xa6,0x80 } },
-{  16, 0xf8a0, 0, {0x21,0x24,0x29,0x48,0x02,0x1e,0x80,0x87,0x80,0x69,0xe0,0x08,0x61,0x02,0xc8,0x00 } },
-{  16, 0xf8b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x18,0x0c,0x00,0xf0,0x30,0x3c,0x4c } },
-{  16, 0xf8c0, 0, {0x0f,0x32,0x03,0xc8,0x80,0xb2,0x00,0x38,0x80,0x0f,0x1b,0x03,0xec,0x00,0xe0,0x30 } },
-{  16, 0xf8d0, 0, {0x30,0x04,0x0f,0xb1,0x03,0x0e,0x85,0xcb,0x00,0x3a,0xc0,0x0c,0x31,0x03,0xd2,0x02 } },
-{  16, 0xf8e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1c,0xbc,0x00,0xfc,0x11,0x3f,0xc4 } },
-{  16, 0xf8f0, 0, {0x0f,0xb8,0x13,0xb0,0x04,0xfe,0x02,0x3f,0x80,0x0f,0xc0,0x03,0xfd,0x00,0xdf,0x12 } },
-{  16, 0xf900, 0, {0x1d,0x04,0x0f,0xd0,0x43,0xbc,0x01,0xef,0x10,0x33,0xc4,0x0e,0xf3,0x03,0xd0,0x06 } },
-{  16, 0xf910, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xee,0x00,0xcb,0x00,0x3e,0x00 } },
-{  16, 0xf920, 0, {0x0f,0x80,0x03,0x28,0x00,0xf8,0x00,0x3e,0x40,0x3d,0xb0,0x03,0xef,0x08,0xc9,0x00 } },
-{  16, 0xf930, 0, {0x3a,0x00,0x0c,0xa0,0x03,0xec,0x98,0xfb,0x20,0x32,0xd2,0x0c,0xa8,0x03,0x2a,0x02 } },
-{  16, 0xf940, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0x87,0x01,0x2d,0x80 } },
-{  16, 0xf950, 0, {0x0b,0x40,0x42,0x1c,0x04,0x37,0x00,0xa1,0x40,0x08,0x60,0x02,0xcc,0x80,0x87,0x00 } },
-{  16, 0xf960, 0, {0x2d,0x80,0x2e,0x70,0x02,0xdc,0xa9,0xb7,0x28,0x21,0xd0,0x08,0x70,0x02,0x12,0x00 } },
-{  16, 0xf970, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xbe,0x02,0x87,0x80,0x2d,0x60 } },
-{  16, 0xf980, 0, {0x4b,0xe8,0x02,0x5a,0x01,0xb4,0x88,0x28,0xe0,0x88,0x78,0xc2,0xde,0x52,0x86,0xc0 } },
-{  16, 0xf990, 0, {0x29,0x60,0x08,0x68,0x02,0xde,0x40,0xb3,0x92,0xe1,0xe8,0x28,0x28,0x02,0x70,0x00 } },
-{  16, 0xf9a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x14,0xcc,0x00,0x8b,0x80,0x2e,0xc0 } },
-{  16, 0xf9b0, 0, {0x0b,0x20,0x02,0x4d,0x80,0x9b,0x20,0x20,0xe0,0x08,0x38,0x02,0xcc,0x00,0x83,0x80 } },
-{  16, 0xf9c0, 0, {0x2c,0xc0,0x0a,0xb0,0x02,0xcc,0x08,0xb3,0x00,0x20,0xc0,0x08,0x31,0x02,0x52,0x04 } },
-{  16, 0xf9d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x05,0xa8,0x00,0xca,0xe0,0x3e,0x80 } },
-{  16, 0xf9e0, 0, {0x1f,0xa4,0x0b,0x79,0x00,0xfe,0x00,0x3f,0x82,0x1d,0xe0,0x03,0xe8,0x00,0xce,0x40 } },
-{  16, 0xf9f0, 0, {0x3b,0x88,0x2c,0xe4,0x03,0xe8,0x01,0xfa,0x00,0x32,0x80,0x0c,0xe8,0x03,0x7a,0x04 } },
-{  16, 0xfa00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0xa0,0x00,0xf8,0x09,0x3e,0x00 } },
-{  16, 0xfa10, 0, {0x8f,0xc0,0x83,0xa0,0x18,0xf8,0x00,0x3c,0x20,0x0f,0x88,0x03,0xe0,0x00,0xf8,0x08 } },
-{  16, 0xfa20, 0, {0x3e,0x20,0x0e,0x80,0x83,0xe1,0x01,0xf0,0x00,0x3c,0x00,0x0f,0x80,0x0b,0x92,0x00 } },
-{  16, 0xfa30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xa4,0x00,0xf9,0x42,0x32,0x40 } },
-{  16, 0xfa40, 0, {0x4c,0x98,0x03,0x04,0x00,0xc9,0x00,0x3a,0x40,0x0f,0x90,0x23,0x24,0x00,0xb9,0x81 } },
-{  16, 0xfa50, 0, {0x3c,0x40,0x0c,0x92,0x03,0x24,0x00,0xf9,0x05,0x32,0x40,0x6c,0x90,0xc3,0xc2,0x04 } },
-{  16, 0xfa60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x24,0x14,0xb9,0x00,0xa2,0x54 } },
-{  16, 0xfa70, 0, {0x08,0x9b,0x1a,0x24,0x02,0x89,0x00,0x22,0x40,0x28,0x90,0x02,0xa4,0x00,0xb9,0x90 } },
-{  16, 0xfa80, 0, {0x2e,0x40,0x28,0x9c,0x82,0x25,0x04,0xb9,0x00,0x22,0x40,0x08,0x98,0x12,0xe0,0x00 } },
-{  16, 0xfa90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xad,0x00,0x23,0x40 } },
-{  16, 0xfaa0, 0, {0x08,0x50,0x02,0x64,0x00,0x89,0x00,0x2a,0x40,0x08,0x10,0x02,0x64,0x00,0xb9,0x00 } },
-{  16, 0xfab0, 0, {0x6e,0x40,0x08,0x90,0x02,0x25,0x00,0xa9,0x00,0x22,0x40,0x08,0x91,0x06,0xc6,0x00 } },
-{  16, 0xfac0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x14,0x00,0xb5,0x10,0xa1,0x44 } },
-{  16, 0xfad0, 0, {0x28,0x50,0x02,0x44,0x80,0x81,0x30,0x20,0x48,0x08,0x12,0x02,0x84,0x40,0xb1,0x80 } },
-{  16, 0xfae0, 0, {0x6c,0xc8,0x08,0x12,0x02,0x04,0x80,0xb1,0x34,0x20,0x48,0x08,0x12,0x02,0xc2,0x01 } },
-{  16, 0xfaf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xe8,0x40,0x32,0x90 } },
-{  16, 0xfb00, 0, {0x0c,0xc5,0x03,0x61,0x40,0xc0,0x40,0x3a,0x14,0x0f,0x85,0x03,0x21,0xb0,0xf8,0x50 } },
-{  16, 0xfb10, 0, {0x3e,0x00,0x0c,0x85,0x03,0x21,0x40,0xf8,0x40,0xb0,0x14,0x0c,0x80,0x03,0xee,0x01 } },
-{  16, 0xfb20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x1d,0xc4,0x04,0xf9,0x22,0x0e,0x48 } },
-{  16, 0xfb30, 0, {0x0f,0x10,0x13,0xb4,0x40,0xfd,0x30,0x3f,0x44,0x4f,0xd1,0x00,0xe4,0x84,0xff,0x01 } },
-{  16, 0xfb40, 0, {0x3d,0x44,0x0f,0xd1,0x0b,0xe4,0x40,0xf9,0x30,0x3e,0x44,0x0f,0xd1,0x03,0xe6,0x04 } },
-{  16, 0xfb50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x05,0xe4,0x00,0xdd,0x40,0x3f,0x50 } },
-{  16, 0xfb60, 0, {0x0c,0xd0,0x03,0x2c,0x00,0xc9,0x00,0x36,0x40,0x0f,0x90,0x13,0x27,0x04,0xf5,0x01 } },
-{  16, 0xfb70, 0, {0x37,0x40,0x0c,0xf0,0x03,0xf6,0x20,0xf9,0xa8,0x32,0x68,0x0c,0xd0,0x03,0xc6,0x00 } },
-{  16, 0xfb80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xe0,0x00,0x88,0xa0,0x2e,0x28 } },
-{  16, 0xfb90, 0, {0x28,0x80,0x02,0x20,0x00,0x88,0xa0,0x22,0x00,0x0b,0x80,0x0a,0x62,0x80,0xb8,0x00 } },
-{  16, 0xfba0, 0, {0x22,0x00,0x08,0x80,0x02,0xe1,0x00,0xb8,0xe0,0x22,0x3a,0x08,0xa0,0x02,0xce,0x04 } },
-{  16, 0xfbb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x84,0x02,0x81,0x00,0x2e,0x40 } },
-{  16, 0xfbc0, 0, {0x08,0x10,0x0a,0x44,0x02,0x81,0x08,0x24,0x40,0x0a,0x10,0x02,0x45,0x80,0xb9,0x00 } },
-{  16, 0xfbd0, 0, {0x24,0x40,0x29,0x10,0x02,0xc4,0x00,0xb1,0x08,0x24,0x44,0x08,0x10,0x02,0xc2,0x01 } },
-{  16, 0xfbe0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x14,0xa4,0x04,0x89,0x01,0x2e,0x50 } },
-{  16, 0xfbf0, 0, {0x48,0xb2,0x02,0x64,0x00,0x91,0x00,0x22,0x46,0x0b,0x90,0x02,0x64,0x00,0xb9,0x01 } },
-{  16, 0xfc00, 0, {0x26,0xc0,0x09,0xb0,0x12,0xe4,0x00,0xb1,0x00,0x26,0x40,0x08,0x90,0x02,0xc6,0x04 } },
-{  16, 0xfc10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x04,0xe4,0x00,0xc9,0x00,0x3c,0x40 } },
-{  16, 0xfc20, 0, {0x0c,0x90,0x03,0x64,0x00,0xc9,0x02,0x36,0x50,0x0e,0x93,0x03,0x24,0x00,0xf9,0x90 } },
-{  16, 0xfc30, 0, {0x36,0x48,0x0d,0x94,0x83,0xe4,0x08,0xf9,0x00,0xb6,0x40,0x0c,0x94,0x03,0xe8,0x04 } },
-{  16, 0xfc40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x10,0xa4,0x00,0xe9,0x00,0x3e,0x40 } },
-{  16, 0xfc50, 0, {0x0f,0x90,0x13,0xa4,0x00,0xe9,0x02,0x2e,0x61,0x05,0x90,0x03,0xa4,0x00,0xf9,0x00 } },
-{  16, 0xfc60, 0, {0x3a,0x40,0x0e,0x90,0x43,0xe4,0x10,0xf9,0x00,0x38,0x40,0x2f,0x90,0x03,0xca,0x00 } },
-{  16, 0xfc70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xd8,0x01,0x32,0x04 } },
-{  16, 0xfc80, 0, {0x0f,0x80,0x43,0xc0,0x01,0xc8,0x00,0xb2,0x01,0x0c,0x80,0x03,0x20,0x00,0xc8,0x40 } },
-{  16, 0xfc90, 0, {0x30,0x00,0x8c,0x84,0x83,0xe0,0x00,0xc8,0x00,0x32,0x00,0x6c,0x84,0x03,0xca,0x04 } },
-{  16, 0xfca0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x28,0x00,0xba,0x00,0x23,0x80 } },
-{  16, 0xfcb0, 0, {0x0b,0xea,0x02,0xe8,0x00,0xaa,0x00,0x22,0x80,0x08,0xa0,0x02,0x28,0x00,0x86,0x20 } },
-{  16, 0xfcc0, 0, {0x37,0xa0,0x8d,0xe4,0x02,0xf8,0x00,0xda,0x00,0x22,0x80,0x08,0xa0,0x02,0xca,0x00 } },
-{  16, 0xfcd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x6c,0x00,0xb3,0x00,0x20,0xc0 } },
-{  16, 0xfce0, 0, {0x0b,0xb8,0x02,0x4c,0x04,0x83,0x00,0x20,0xc0,0x08,0xb0,0x02,0x0c,0x02,0x83,0x00 } },
-{  16, 0xfcf0, 0, {0x20,0x40,0x28,0x34,0x02,0xce,0x90,0x83,0x00,0xa0,0xc0,0x08,0x30,0x02,0xca,0x00 } },
-{  16, 0xfd00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1c,0xc0,0xb5,0x88,0x21,0x40 } },
-{  16, 0xfd10, 0, {0x0b,0x70,0x02,0xdc,0x80,0xa3,0x20,0x21,0xe0,0x48,0x32,0x42,0x0e,0x90,0x8e,0x01 } },
-{  16, 0xfd20, 0, {0x65,0x50,0x09,0x70,0x02,0xde,0x20,0x93,0x21,0x21,0xc0,0x08,0x70,0x02,0xe8,0x00 } },
-{  16, 0xfd30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x18,0x1e,0x00,0xff,0x80,0xb1,0xa0 } },
-{  16, 0xfd40, 0, {0x0f,0x48,0x02,0x7e,0x00,0x87,0xa0,0x33,0xe0,0x28,0x7a,0x0b,0x1f,0x00,0xc4,0x80 } },
-{  16, 0xfd50, 0, {0x31,0x60,0x8c,0x58,0x03,0xfe,0x00,0xc7,0xc8,0x33,0xe8,0x0c,0x58,0x03,0xea,0x02 } },
-{  16, 0xfd60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xff,0x00,0x3e,0x00 } },
-{  16, 0xfd70, 0, {0x0f,0x90,0x23,0xec,0xa0,0xfb,0x40,0x3e,0xc0,0x8f,0xb5,0x03,0xed,0x80,0xf8,0x00 } },
-{  16, 0xfd80, 0, {0x3c,0x40,0x0f,0xb0,0x03,0xe8,0x00,0xfb,0x02,0x3e,0xd0,0x0f,0x90,0x03,0xc2,0x06 } },
-{  16, 0xfd90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x04,0xbe,0x00,0xff,0x80,0x3f,0xe0 } },
-{  16, 0xfda0, 0, {0x0f,0xd9,0x03,0xfe,0x20,0xcf,0xc8,0x33,0xea,0x8f,0xfc,0x03,0x3f,0x00,0xfd,0x80 } },
-{  16, 0xfdb0, 0, {0x3f,0x60,0x0e,0xe8,0x03,0xf2,0x00,0xcf,0x80,0x2f,0xfe,0x0c,0x78,0x03,0x00,0x00 } },
-{  16, 0xfdc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x00,0x9c,0x00,0xb5,0x02,0x2d,0xc0 } },
-{  16, 0xfdd0, 0, {0x0b,0x58,0x42,0xdc,0x80,0xcf,0x00,0x21,0xc1,0x0b,0x30,0x12,0x1c,0x40,0xb4,0x02 } },
-{  16, 0xfde0, 0, {0x2d,0x46,0x08,0x71,0x12,0xc8,0x00,0xe7,0x00,0x2d,0xc4,0x08,0x70,0x03,0x6a,0x04 } },
-{  16, 0xfdf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x00,0x2d,0x02 } },
-{  16, 0xfe00, 0, {0x0b,0x46,0x02,0xdc,0x08,0x97,0x00,0x21,0xc9,0x0a,0x30,0x22,0x1c,0x00,0xb4,0x00 } },
-{  16, 0xfe10, 0, {0x2d,0x40,0x0a,0x50,0x82,0xc4,0x00,0xb7,0x00,0x2c,0xc8,0x28,0x50,0x02,0x40,0x10 } },
-{  16, 0xfe20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x14,0x8c,0x18,0xb3,0x00,0x2e,0x20 } },
-{  16, 0xfe30, 0, {0x0b,0x18,0x02,0xcf,0x4a,0x83,0xc2,0x20,0xc1,0x0b,0x34,0x22,0x0c,0x04,0xb8,0x58 } },
-{  16, 0xfe40, 0, {0x2c,0x40,0x0b,0x28,0x02,0xc8,0x00,0xa3,0x00,0x2c,0xc0,0x08,0x14,0x02,0x48,0x04 } },
-{  16, 0xfe50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xbc,0x00,0xfb,0x00,0x3e,0x80 } },
-{  16, 0xfe60, 0, {0x0f,0xa0,0x02,0xfc,0x00,0xdf,0xa0,0xb3,0xc0,0x0e,0xf0,0x0b,0x3c,0x00,0xfb,0xc0 } },
-{  16, 0xfe70, 0, {0x3c,0xa0,0x0e,0xbd,0x03,0xec,0x00,0xff,0x00,0x3f,0xc0,0x0c,0x30,0x03,0x6a,0x04 } },
-{  16, 0xfe80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0xec,0x00,0xf9,0x00,0x3e,0x01 } },
-{  16, 0xfe90, 0, {0x8f,0xb1,0x43,0xec,0x00,0xf3,0x00,0x3e,0xc0,0x4f,0xb0,0x13,0xec,0x00,0xfb,0x00 } },
-{  16, 0xfea0, 0, {0x3e,0x80,0x0c,0x84,0x03,0xe1,0x00,0x73,0x00,0x3e,0xc1,0x0f,0xb2,0x43,0xe0,0x00 } },
-{  16, 0xfeb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x50,0xfc,0x10,0xff,0x80,0x37,0xc0 } },
-{  16, 0xfec0, 0, {0x0c,0xe0,0x03,0xfc,0x20,0xff,0x08,0x33,0xc0,0x0f,0xf0,0x83,0xbc,0x00,0xff,0x00 } },
-{  16, 0xfed0, 0, {0x33,0xc0,0x2e,0x40,0x03,0x1c,0x01,0xcf,0x00,0x11,0xc0,0x4c,0xd0,0x03,0x00,0x44 } },
-{  16, 0xfee0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x04,0xb3,0x02,0x22,0x72 } },
-{  16, 0xfef0, 0, {0x08,0xa1,0x16,0xec,0x00,0xbb,0x04,0x22,0xc0,0x0b,0xb0,0x42,0xec,0x00,0xba,0x19 } },
-{  16, 0xff00, 0, {0xb6,0xd0,0x08,0x9c,0x4a,0x26,0x80,0xdb,0x00,0x22,0xc0,0x08,0x90,0x03,0x60,0x40 } },
-{  16, 0xff10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0xb9,0x10,0x62,0x20 } },
-{  16, 0xff20, 0, {0x48,0xa0,0x02,0xec,0x00,0xbb,0x00,0x22,0xc0,0x0b,0xb0,0x02,0xec,0x10,0xbb,0x00 } },
-{  16, 0xff30, 0, {0x66,0x08,0x0a,0xa8,0x12,0x26,0x10,0x9b,0x00,0x2a,0xc0,0x28,0xb0,0x26,0x20,0x00 } },
-{  16, 0xff40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0c,0x00,0xb9,0x00,0x20,0x00 } },
-{  16, 0xff50, 0, {0x08,0x32,0x02,0xcc,0x04,0xb3,0x00,0x20,0xc0,0x4b,0x30,0x02,0xcc,0x00,0xb3,0x00 } },
-{  16, 0xff60, 0, {0x20,0x00,0x08,0x00,0x02,0x01,0x00,0x93,0x00,0x28,0xc0,0x08,0x30,0x06,0x42,0x11 } },
-{  16, 0xff70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x6c,0x00,0xf9,0x00,0xb2,0x40 } },
-{  16, 0xff80, 0, {0x0c,0x82,0x02,0xdc,0x01,0xff,0x00,0xb2,0xc0,0x0b,0xf1,0x03,0xbc,0x00,0xf9,0x00 } },
-{  16, 0xff90, 0, {0x26,0x40,0x2e,0x80,0x03,0x21,0x04,0xcf,0x00,0xbb,0xc0,0x0c,0x90,0x03,0x00,0x03 } },
-{  16, 0xffa0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xfd,0x00,0x3f,0x40 } },
-{  16, 0xffb0, 0, {0x0f,0x81,0x03,0xfc,0x00,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x23,0xfc,0x00,0xfc,0x00 } },
-{  16, 0xffc0, 0, {0x2d,0x40,0x2f,0xc0,0x03,0xf0,0x88,0xff,0x00,0x37,0xc0,0x8f,0xd0,0x03,0xe8,0x02 } },
-{  16, 0xffd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfe,0x40,0xff,0x80,0x33,0xc2 } },
-{  16, 0xffe0, 0, {0x0c,0xf8,0x03,0x7c,0xa0,0xff,0x90,0x3f,0xc4,0x2c,0xb4,0x03,0xbc,0x80,0xcf,0x40 } },
-{  16, 0xfff0, 0, {0x37,0xe0,0x0f,0xf1,0x93,0x6e,0x44,0xbf,0x30,0x3f,0x20,0x2c,0xf8,0x63,0xf0,0x04 } },
-{  16, 0x8010, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0x00,0xeb,0x20,0x23,0xf0 } },
-{  16, 0x8020, 0, {0x08,0xb8,0x52,0x3d,0x00,0xb3,0x00,0x2e,0xdc,0x08,0xf4,0x42,0x1c,0x42,0x8b,0x40 } },
-{  16, 0x8030, 0, {0x22,0xc8,0x0b,0xf6,0x03,0x6c,0x88,0xbb,0x30,0x2e,0x00,0x08,0xb2,0x02,0xe0,0x04 } },
-{  16, 0x8040, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x00,0xbb,0x08,0x20,0xc0 } },
-{  16, 0x8050, 0, {0x08,0x30,0x02,0x4c,0xa0,0xb3,0x20,0x26,0x80,0x88,0x36,0x02,0xcc,0xa0,0x93,0x60 } },
-{  16, 0x8060, 0, {0xa4,0xc2,0x0a,0x32,0x42,0x4c,0x90,0xb3,0x20,0x2c,0x0b,0x88,0x30,0x82,0xe2,0x01 } },
-{  16, 0x8070, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x08,0xbb,0x22,0xa2,0xc0 } },
-{  16, 0x8080, 0, {0x08,0xb0,0x02,0x2c,0x00,0xbb,0x00,0x2e,0x90,0x08,0xb0,0x02,0xec,0x00,0x9b,0x00 } },
-{  16, 0x8090, 0, {0x22,0xc0,0x0b,0xb0,0x02,0x6c,0x00,0xbb,0x02,0x2e,0x20,0x08,0xb0,0x02,0xf0,0x00 } },
-{  16, 0x80a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xb1,0x83,0x32,0xc0 } },
-{  16, 0x80b0, 0, {0x0c,0x1a,0x03,0x6c,0x10,0xfb,0x00,0x34,0xc0,0x0c,0xb0,0x03,0xec,0x08,0xda,0x00 } },
-{  16, 0x80c0, 0, {0x36,0xc0,0x0e,0xb0,0x0b,0x6c,0x00,0xfb,0x00,0x3e,0x28,0x0c,0xb0,0x02,0xd0,0x00 } },
-{  16, 0x80d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x00,0xed,0x80,0x3f,0xc0 } },
-{  16, 0x80e0, 0, {0x0f,0xd4,0x03,0xec,0x00,0xff,0x00,0x3f,0xc8,0x0f,0xb0,0x03,0x3c,0x00,0xee,0x40 } },
-{  16, 0x80f0, 0, {0x3f,0xc0,0x0f,0x70,0x03,0xfc,0x00,0xff,0x00,0x3f,0x80,0x0f,0xf0,0x03,0xf8,0x00 } },
-{  16, 0x8100, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x20,0xb0,0xc0 } },
-{  16, 0x8110, 0, {0x0f,0xb4,0x03,0xac,0x02,0xcb,0x00,0x32,0x90,0x0e,0xb0,0x03,0x6c,0x00,0xeb,0x00 } },
-{  16, 0x8120, 0, {0x3a,0xc0,0x0c,0xb0,0x02,0xec,0x00,0xfb,0x00,0x3e,0x91,0x0f,0xb0,0x03,0x90,0x00 } },
-{  16, 0x8130, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xbb,0x80,0x23,0xd7 } },
-{  16, 0x8140, 0, {0x0b,0x90,0x02,0x3c,0x14,0x8b,0x00,0x6a,0x08,0x28,0xf0,0x00,0xbc,0x00,0x83,0x00 } },
-{  16, 0x8150, 0, {0xbe,0xc0,0x88,0xf0,0x13,0x2c,0x00,0xef,0x00,0x2e,0x80,0x0b,0xb0,0x07,0xb2,0x00 } },
-{  16, 0x8160, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb3,0x40,0x20,0xd0 } },
-{  16, 0x8170, 0, {0x0b,0x28,0x02,0x8c,0x00,0x83,0x01,0x20,0xc0,0x1a,0xb8,0x00,0x6c,0x10,0xa1,0x00 } },
-{  16, 0x8180, 0, {0x68,0xc0,0x2a,0x30,0x02,0x8c,0x00,0xb3,0x02,0x2e,0x00,0x4b,0x30,0x02,0xf8,0x04 } },
-{  16, 0x8190, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0xb7,0xa0,0x21,0xe0 } },
-{  16, 0x81a0, 0, {0x0b,0xec,0xc2,0x1e,0x04,0x87,0x80,0x29,0xe4,0x08,0x79,0x82,0x9e,0x40,0xaf,0x90 } },
-{  16, 0x81b0, 0, {0x29,0xe0,0x0a,0x38,0x00,0x1e,0x00,0xa7,0x90,0x2d,0x24,0x0b,0x78,0x02,0x88,0x00 } },
-{  16, 0x81c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x50,0xfb,0x09,0x30,0xc0 } },
-{  16, 0x81d0, 0, {0x0f,0x20,0x02,0x8c,0x40,0xc3,0x00,0x20,0xc0,0x0a,0x38,0x03,0x4c,0x44,0xe1,0x00 } },
-{  16, 0x81e0, 0, {0xaa,0xc0,0x0e,0x31,0x43,0x8e,0x00,0xf3,0x00,0x3c,0x00,0x0f,0x30,0x03,0xd2,0x02 } },
-{  16, 0x81f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x4d,0xbc,0x00,0xff,0x20,0x3f,0xd0 } },
-{  16, 0x8200, 0, {0x4f,0x70,0x03,0xfc,0x00,0xff,0x00,0x3d,0xc0,0x0f,0xf3,0x43,0xfc,0x40,0xd7,0x00 } },
-{  16, 0x8210, 0, {0xbf,0xc0,0x0d,0xf4,0xc3,0xfc,0x40,0xff,0x00,0x3f,0x40,0x0f,0xf0,0x03,0xd0,0x06 } },
-{  16, 0x8220, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x00,0xfb,0x00,0x32,0xd0 } },
-{  16, 0x8230, 0, {0x0d,0x90,0x01,0xed,0xc0,0xfb,0x00,0x3e,0xc0,0x1f,0xba,0x03,0xac,0xc0,0xc8,0x00 } },
-{  16, 0x8240, 0, {0x32,0xe0,0x8d,0xb4,0x43,0xec,0x00,0xfb,0x00,0x36,0xa0,0x0c,0xb0,0x03,0x6a,0x00 } },
-{  16, 0x8250, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb7,0x00,0x21,0xc8 } },
-{  16, 0x8260, 0, {0x08,0x60,0x02,0xdc,0x20,0xb7,0x00,0x2d,0xc0,0x0f,0x74,0xa2,0x1c,0x28,0xd6,0x00 } },
-{  16, 0x8270, 0, {0x35,0xc0,0x08,0x72,0x02,0x5c,0x08,0xb7,0x44,0xa1,0x80,0x48,0x70,0x02,0x12,0x00 } },
-{  16, 0x8280, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x80,0x20,0xe4 } },
-{  16, 0x8290, 0, {0x09,0x78,0x26,0xde,0x00,0xb7,0x80,0x2d,0xe2,0x0a,0x70,0x12,0x8c,0x88,0x81,0x80 } },
-{  16, 0x82a0, 0, {0x21,0xe0,0x09,0x78,0x02,0xde,0x00,0xb3,0xa0,0x25,0xa0,0x28,0x78,0x02,0x70,0x04 } },
-{  16, 0x82b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x01,0xbb,0x80,0x20,0xc0 } },
-{  16, 0x82c0, 0, {0x08,0x30,0x42,0xec,0x00,0xb3,0x00,0x2c,0xc0,0x0a,0x30,0x22,0x0c,0x00,0x93,0x00 } },
-{  16, 0x82d0, 0, {0x24,0xc1,0x08,0x30,0x02,0xcc,0x00,0xb3,0x00,0x20,0xe0,0x08,0xb0,0x02,0x12,0x04 } },
-{  16, 0x82e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfa,0x08,0xb2,0x80 } },
-{  16, 0x82f0, 0, {0x0d,0xe2,0x03,0xe8,0x00,0xfa,0x00,0x3f,0x80,0x0a,0xa0,0x03,0xa8,0x00,0xce,0x50 } },
-{  16, 0x8300, 0, {0x32,0x80,0x05,0xa0,0x03,0xe8,0x00,0xfa,0x00,0x37,0xa8,0x0c,0xa0,0x03,0x7a,0x04 } },
-{  16, 0x8310, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x60,0x08,0xf8,0x00,0x3c,0x00 } },
-{  16, 0x8320, 0, {0x0f,0x88,0x01,0xe0,0x00,0xf8,0x04,0x3c,0x00,0x4f,0x00,0x13,0xc0,0x00,0xf8,0x00 } },
-{  16, 0x8330, 0, {0x3e,0x00,0x0f,0x80,0x03,0x60,0x00,0xf8,0x02,0x3e,0x01,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0x8340, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf9,0x90,0x12,0x40 } },
-{  16, 0x8350, 0, {0x0c,0x90,0x03,0xa4,0x00,0xc9,0x00,0x3e,0x70,0x0e,0x94,0x33,0x24,0x08,0xc9,0x00 } },
-{  16, 0x8360, 0, {0x2a,0x40,0x0b,0x90,0x03,0xe4,0x00,0xf9,0x00,0x3a,0x40,0x0f,0x90,0x03,0x02,0x04 } },
-{  16, 0x8370, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x42,0x22,0x60 } },
-{  16, 0x8380, 0, {0x08,0x10,0x02,0x24,0x00,0x89,0x03,0x2e,0x40,0x08,0x90,0x02,0xa4,0x01,0x81,0x04 } },
-{  16, 0x8390, 0, {0x3e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb9,0x02,0x22,0x40,0x0e,0x90,0x02,0x20,0x00 } },
-{  16, 0x83a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x40,0x2a,0x4a } },
-{  16, 0x83b0, 0, {0x08,0x91,0x02,0xa4,0x00,0x89,0x00,0x2e,0x40,0x1a,0x90,0x0a,0x24,0x04,0x89,0x00 } },
-{  16, 0x83c0, 0, {0x2a,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb1,0x00,0x2a,0x40,0x0b,0x90,0x02,0x06,0x00 } },
-{  16, 0x83d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb1,0x01,0xa8,0x48 } },
-{  16, 0x83e0, 0, {0x88,0x90,0x02,0x04,0x80,0x81,0x40,0x2c,0x50,0x18,0x14,0x0a,0x84,0x10,0x89,0x40 } },
-{  16, 0x83f0, 0, {0x2c,0x40,0x0b,0x10,0x02,0xc4,0x00,0x31,0x20,0x20,0x40,0x0a,0x10,0x0a,0x02,0x01 } },
-{  16, 0x8400, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf0,0x50,0x3a,0x00 } },
-{  16, 0x8410, 0, {0x2c,0xa0,0x02,0xa1,0x42,0xc8,0x00,0x3e,0x00,0xde,0x00,0x23,0x21,0x42,0x88,0x00 } },
-{  16, 0x8420, 0, {0x38,0x14,0x0f,0x85,0x03,0xe1,0x40,0xf8,0x50,0x38,0x14,0x0f,0x05,0x03,0x2e,0x01 } },
-{  16, 0x8430, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x08,0xfd,0x00,0x36,0x44 } },
-{  16, 0x8440, 0, {0x0f,0xd0,0x03,0x64,0x40,0xf9,0x00,0x3d,0x50,0x0f,0x94,0x03,0xe5,0x00,0x7d,0x40 } },
-{  16, 0x8450, 0, {0x3e,0x40,0x0f,0x94,0x03,0xe4,0x00,0xf9,0x10,0x3f,0x40,0x0e,0x90,0x03,0xe6,0x04 } },
-{  16, 0x8460, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe4,0x00,0xfd,0x40,0x33,0x68 } },
-{  16, 0x8470, 0, {0x0c,0xd0,0x03,0xe7,0x81,0xf9,0x00,0x33,0x78,0x0d,0xd8,0x13,0x26,0xa0,0xcd,0xa0 } },
-{  16, 0x8480, 0, {0x32,0x40,0x0d,0x9b,0x03,0x24,0x00,0xf9,0xa0,0x3c,0x44,0x2c,0x90,0x07,0x86,0x00 } },
-{  16, 0x8490, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0xb8,0xa0,0xa2,0x10 } },
-{  16, 0x84a0, 0, {0x18,0x80,0x03,0x82,0x84,0xb8,0x80,0x36,0x2c,0x2e,0x0f,0x02,0xa3,0xa0,0xd8,0xe0 } },
-{  16, 0x84b0, 0, {0x36,0x22,0x8b,0x08,0x03,0x42,0xa0,0xf8,0xe0,0x2e,0x28,0x08,0x88,0x02,0xce,0x04 } },
-{  16, 0x84c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0xa0,0x50 } },
-{  16, 0x84d0, 0, {0x28,0x30,0x02,0xc5,0x80,0xb1,0x08,0x20,0x40,0x09,0x10,0xa2,0x44,0x08,0x81,0x48 } },
-{  16, 0x84e0, 0, {0x20,0x40,0x0b,0x14,0x02,0x04,0x80,0xb1,0x38,0x2c,0x48,0x08,0x12,0x82,0x82,0x01 } },
-{  16, 0x84f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0xb1,0x00,0x22,0x40 } },
-{  16, 0x8500, 0, {0x08,0x92,0x02,0xe4,0x00,0xb9,0x02,0x26,0x58,0x4a,0x90,0x02,0xe4,0x08,0x99,0x40 } },
-{  16, 0x8510, 0, {0x26,0x40,0x0b,0x90,0x02,0x64,0x08,0xb9,0x01,0x2c,0x48,0x08,0x90,0x12,0xc6,0x04 } },
-{  16, 0x8520, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x80,0x32,0x40 } },
-{  16, 0x8530, 0, {0x08,0x98,0x83,0xe4,0x04,0xb9,0x01,0x30,0x40,0x0d,0x90,0x0b,0x64,0x02,0xc9,0x00 } },
-{  16, 0x8540, 0, {0x32,0x40,0x0f,0x90,0x03,0x24,0x00,0xf9,0x00,0x1e,0x58,0x0c,0x90,0x03,0xa8,0x04 } },
-{  16, 0x8550, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x20,0x3c,0x40 } },
-{  16, 0x8560, 0, {0x0f,0x98,0x03,0xa4,0x00,0xb9,0x00,0x3e,0x42,0x8e,0x10,0x4b,0x84,0x04,0xf9,0x00 } },
-{  16, 0x8570, 0, {0x3e,0x40,0x8f,0x90,0x03,0xe4,0x00,0xe9,0x00,0x3e,0x40,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0x8580, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xd8,0x00,0x32,0x08 } },
-{  16, 0x8590, 0, {0x0f,0x84,0x83,0xa0,0x04,0xc8,0x04,0x3e,0x00,0x83,0x80,0x01,0x20,0x00,0xc0,0x00 } },
-{  16, 0x85a0, 0, {0x32,0x00,0x0f,0x00,0x03,0xa0,0x00,0xc8,0x00,0x32,0x10,0x4e,0x80,0x13,0xca,0x04 } },
-{  16, 0x85b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8e,0x90,0xa3,0x80 } },
-{  16, 0x85c0, 0, {0x0b,0xe4,0x02,0x28,0x00,0xca,0x00,0x2f,0x80,0x4a,0xa0,0x13,0xa8,0x00,0xaa,0x00 } },
-{  16, 0x85d0, 0, {0x36,0x81,0x0b,0xa0,0x02,0x28,0x00,0x8a,0x00,0x22,0x80,0x08,0xa0,0x03,0x8a,0x00 } },
-{  16, 0x85e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0xc0,0x20,0xd0 } },
-{  16, 0x85f0, 0, {0x0b,0x34,0x02,0x8c,0x00,0x8b,0x00,0x2c,0xf0,0x8b,0x18,0x02,0x4c,0x00,0x83,0x00 } },
-{  16, 0x8600, 0, {0x60,0xc0,0x0b,0x30,0x02,0x8c,0x02,0x83,0x00,0x28,0xc1,0x0a,0x30,0x02,0xca,0x00 } },
-{  16, 0x8610, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x00,0xb4,0x0b,0x69,0xc0 } },
-{  16, 0x8620, 0, {0x09,0x58,0x06,0x1e,0x80,0x97,0x10,0x2f,0xc2,0x48,0x70,0x82,0x9c,0x80,0xa7,0x08 } },
-{  16, 0x8630, 0, {0x25,0xcc,0x0b,0x70,0x02,0x1e,0x81,0x87,0xa2,0xab,0xc4,0x08,0x73,0x02,0xe8,0x00 } },
-{  16, 0x8640, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x10,0xdc,0x84,0x21,0xe0 } },
-{  16, 0x8650, 0, {0x0f,0x78,0x42,0x9f,0x02,0xc7,0x88,0x3d,0xe0,0x2f,0x71,0x03,0x4e,0x00,0xcf,0x80 } },
-{  16, 0x8660, 0, {0x21,0xe2,0x0f,0x78,0x83,0x9e,0x49,0xcf,0xd0,0x39,0xe8,0x0e,0x78,0x03,0xea,0x02 } },
-{  16, 0x8670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x4d,0xac,0x40,0xca,0x00,0x36,0x00 } },
-{  16, 0x8680, 0, {0x8f,0x30,0x23,0xec,0xa8,0xeb,0x40,0x3c,0xc0,0x0f,0x96,0x43,0xed,0x80,0xfb,0x00 } },
-{  16, 0x8690, 0, {0x3e,0xd8,0x8f,0xb1,0x43,0xed,0x80,0xfb,0x20,0x36,0xca,0x0f,0xb0,0xa3,0x82,0x06 } },
-{  16, 0x86a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x80,0xfc,0x80,0x31,0xe0 } },
-{  16, 0x86b0, 0, {0x05,0xaa,0x10,0xfe,0x44,0xff,0x90,0x3f,0xe1,0xcf,0xf9,0x17,0x3f,0x20,0xd7,0x80 } },
-{  16, 0x86c0, 0, {0x8b,0xe4,0x0f,0xf8,0x03,0x3e,0x30,0xff,0x80,0x37,0xe0,0x0f,0xf8,0x00,0x40,0x00 } },
-{  16, 0x86d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xbd,0x10,0x21,0xc0 } },
-{  16, 0x86e0, 0, {0x08,0x4a,0x02,0xdc,0xc0,0xb7,0x00,0x2d,0xc2,0x0c,0xd3,0x02,0x1c,0x80,0x87,0x00 } },
-{  16, 0x86f0, 0, {0x29,0xc0,0x4b,0x72,0x02,0x1c,0x00,0xb7,0x01,0x21,0xc0,0x0b,0xf0,0x12,0x2a,0x04 } },
-{  16, 0x8700, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x90,0x34,0x00,0x21,0x80 } },
-{  16, 0x8710, 0, {0x09,0x70,0x00,0x5c,0x0c,0xb7,0x00,0x2d,0xc4,0x08,0x50,0x1a,0x0c,0x00,0x97,0x00 } },
-{  16, 0x8720, 0, {0x21,0xc0,0x4b,0x30,0x02,0x1c,0x00,0xb7,0x00,0x25,0xc0,0x0b,0x70,0x02,0x40,0x00 } },
-{  16, 0x8730, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0xb0,0x00,0x60,0x00 } },
-{  16, 0x8740, 0, {0x08,0x3e,0x02,0xcc,0x00,0xb3,0x02,0x0c,0xe0,0x2b,0xb0,0x02,0x0c,0x00,0x93,0x00 } },
-{  16, 0x8750, 0, {0x28,0xc0,0x0b,0xb0,0x02,0x2c,0x10,0xb3,0x00,0x20,0xd6,0x03,0x30,0x02,0x08,0x04 } },
-{  16, 0x8760, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xfb,0x00,0xb2,0x00 } },
-{  16, 0x8770, 0, {0x05,0xbe,0x03,0x7c,0x00,0xff,0x00,0x3e,0x20,0x0c,0xb0,0x03,0x3c,0x00,0xd9,0x80 } },
-{  16, 0x8780, 0, {0x33,0xc0,0x8b,0xf0,0x03,0x3c,0x00,0xff,0x00,0x37,0xe0,0x0f,0xf0,0x03,0x6a,0x04 } },
-{  16, 0x8790, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x04,0x3e,0x00 } },
-{  16, 0x87a0, 0, {0x0f,0xa4,0x23,0xcc,0x00,0xfb,0x00,0x3e,0x81,0x08,0x90,0x03,0xec,0x00,0xe9,0x14 } },
-{  16, 0x87b0, 0, {0x3e,0xc0,0x0f,0xb0,0x03,0xec,0x10,0xfb,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0xe0,0x00 } },
-{  16, 0x87c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xff,0x00,0x37,0x80 } },
-{  16, 0x87d0, 0, {0x0f,0xfa,0x03,0xfc,0x00,0xcf,0x00,0x3f,0x90,0x06,0xdc,0x23,0x3c,0x00,0xfd,0x10 } },
-{  16, 0x87e0, 0, {0x33,0xc0,0x0f,0xf0,0x0b,0x3c,0x00,0x43,0x00,0x33,0xc0,0x0f,0xf0,0x03,0xc0,0x44 } },
-{  16, 0x87f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x6c,0x09,0xbb,0x19,0x22,0x32 } },
-{  16, 0x8800, 0, {0x0b,0xbe,0x03,0x6c,0x00,0x8b,0x00,0x2c,0x90,0x0d,0xb8,0x02,0xac,0x00,0xb1,0x00 } },
-{  16, 0x8810, 0, {0xf2,0xc0,0x0b,0xb0,0x12,0xac,0x00,0x8b,0x00,0x22,0xc0,0x0b,0xb0,0x03,0xa0,0x40 } },
-{  16, 0x8820, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x10,0xb3,0x00,0x26,0x20 } },
-{  16, 0x8830, 0, {0x0b,0x90,0x12,0xec,0x01,0x8b,0x00,0x2a,0xc2,0x0a,0x90,0x02,0x2c,0x00,0xbb,0x00 } },
-{  16, 0x8840, 0, {0xa2,0xc0,0x0b,0xb0,0x02,0x2c,0x00,0xab,0x00,0x2a,0xc0,0x0b,0xb0,0x02,0xe0,0x00 } },
-{  16, 0x8850, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x01,0xb3,0x00,0x20,0x00 } },
-{  16, 0x8860, 0, {0x0b,0x00,0x02,0x8c,0x00,0x83,0x00,0x2e,0xc0,0x0b,0x34,0x02,0x8c,0x00,0xbb,0x00 } },
-{  16, 0x8870, 0, {0x20,0xc0,0x0b,0x30,0x02,0x0d,0x00,0xa3,0x00,0xa0,0xc0,0x0b,0x30,0x02,0x82,0x01 } },
-{  16, 0x8880, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xbb,0x04,0x36,0x80 } },
-{  16, 0x8890, 0, {0x0f,0xb2,0x02,0xfc,0x02,0xcf,0x02,0x38,0xc0,0x0e,0xf0,0x03,0x3c,0x00,0xfb,0x00 } },
-{  16, 0x88a0, 0, {0x23,0xc0,0x0f,0xf0,0x03,0x3d,0x02,0xef,0x00,0x33,0xc0,0x0f,0xf0,0x43,0xc0,0x03 } },
-{  16, 0x88b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x3f,0x00 } },
-{  16, 0x88c0, 0, {0x0f,0xf4,0x23,0x7c,0x00,0xff,0x00,0x3f,0xc0,0x0d,0xd0,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0x88d0, 0, {0x3b,0xc0,0x0f,0xf0,0x03,0xfc,0x88,0xdf,0x00,0x3f,0xc0,0x0f,0xf0,0x03,0xa8,0x06 } },
-{  16, 0x88e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0x50,0xce,0x12,0x33,0xd0 } },
-{  16, 0x88f0, 0, {0x4c,0x86,0x83,0x30,0x80,0x5f,0x68,0x33,0xc4,0x0f,0xf3,0x83,0x3c,0xc0,0xcc,0x38 } },
-{  16, 0x8900, 0, {0xb3,0x08,0x0c,0xc6,0x03,0xf1,0xa0,0xff,0x00,0x33,0x24,0x0c,0xc2,0x03,0xf0,0x00 } },
-{  16, 0x8910, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0x80,0xd2,0x20,0x23,0xd8 } },
-{  16, 0x8920, 0, {0x0d,0x96,0x02,0x88,0x60,0xaf,0x40,0x23,0xdc,0x0b,0xf6,0x02,0x3c,0xc2,0x88,0x60 } },
-{  16, 0x8930, 0, {0x22,0x52,0x08,0x91,0x22,0xe1,0x00,0xb7,0x24,0xa2,0x48,0x8a,0x84,0x82,0x60,0x04 } },
-{  16, 0x8940, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x00,0x81,0x00,0xe0,0xc4 } },
-{  16, 0x8950, 0, {0x0a,0x00,0x02,0x04,0x80,0xa3,0x20,0xa8,0xc0,0x1b,0x30,0x0a,0x0c,0x00,0xa0,0x00 } },
-{  16, 0x8960, 0, {0x28,0x0c,0x09,0x02,0x02,0xc4,0x80,0xb3,0x1c,0x22,0x08,0x19,0x03,0x02,0xe2,0x11 } },
-{  16, 0x8970, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa4,0x00,0x99,0x80,0x62,0xc0 } },
-{  16, 0x8980, 0, {0x0b,0xa0,0x32,0xa4,0x51,0xab,0x00,0x2a,0xc0,0x8b,0xb0,0x00,0x0c,0x00,0xa9,0xc0 } },
-{  16, 0x8990, 0, {0x2a,0x21,0x08,0xb8,0x22,0xe2,0x00,0xbb,0x00,0x22,0x84,0x1b,0xa8,0x42,0x70,0x04 } },
-{  16, 0x89a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe2,0x00,0xcb,0xc9,0x32,0xc0 } },
-{  16, 0x89b0, 0, {0x0e,0x8b,0x13,0x22,0x10,0xdb,0x01,0x32,0xc0,0x0f,0xb0,0x0b,0x2c,0x00,0x68,0x81 } },
-{  16, 0x89c0, 0, {0x3a,0x22,0x2c,0x88,0x23,0xe3,0x00,0xfb,0x00,0x30,0x30,0x8d,0x9c,0x83,0xd0,0x04 } },
-{  16, 0x89d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xba,0x40,0xf7,0x04,0x3e,0xc2 } },
-{  16, 0x89e0, 0, {0x0d,0xd8,0x23,0xd8,0x00,0x7b,0x00,0x37,0xc0,0x0f,0x70,0x33,0xfc,0x10,0xd2,0x00 } },
-{  16, 0x89f0, 0, {0x35,0xc0,0x8f,0xc0,0x03,0xf4,0x00,0xf7,0x02,0x3f,0xe0,0x0e,0x80,0x03,0xf8,0x00 } },
-{  16, 0x8a00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x81,0x20,0xc8,0x08,0x30,0xc0 } },
-{  16, 0x8a10, 0, {0x0c,0x00,0x83,0x24,0x40,0xc3,0x89,0x3a,0xc0,0x0e,0xb0,0x0b,0x2c,0x08,0xc9,0x48 } },
-{  16, 0x8a20, 0, {0x72,0x54,0x0f,0x91,0x03,0xed,0x02,0xeb,0x8a,0x3a,0x62,0x8c,0x80,0x0b,0x10,0x04 } },
-{  16, 0x8a30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2b,0x04,0x88,0x40,0xa3,0xc2 } },
-{  16, 0x8a40, 0, {0x02,0xae,0x12,0x27,0x42,0x8f,0x44,0x23,0xc2,0x0b,0xf4,0x02,0x3d,0x00,0x0a,0x40 } },
-{  16, 0x8a50, 0, {0x22,0xe0,0x0b,0xb5,0x02,0xec,0x20,0x8f,0x44,0xa2,0x40,0x8d,0xbd,0x23,0x32,0x00 } },
-{  16, 0x8a60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x49,0x40,0x83,0x81,0x24,0xc1 } },
-{  16, 0x8a70, 0, {0x08,0x28,0x02,0x01,0x00,0x93,0x00,0xa0,0xe8,0x0a,0x30,0x82,0x8f,0x60,0xb3,0x90 } },
-{  16, 0x8a80, 0, {0x60,0xb8,0x0b,0x28,0x12,0x4a,0x00,0x93,0x00,0x20,0x90,0x09,0x20,0x02,0x78,0x00 } },
-{  16, 0x8a90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x02,0x87,0xa8,0x25,0xe0 } },
-{  16, 0x8aa0, 0, {0x0a,0x7b,0x02,0x1a,0x04,0x87,0x80,0x21,0xe4,0x0b,0x78,0x82,0x8e,0x02,0x96,0x91 } },
-{  16, 0x8ab0, 0, {0x21,0x21,0x0b,0x69,0x40,0xdb,0x40,0x97,0x92,0x23,0xa0,0x89,0x58,0x82,0x08,0x00 } },
-{  16, 0x8ac0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x25,0x82,0xc3,0x00,0x34,0xc0 } },
-{  16, 0x8ad0, 0, {0x0c,0x9b,0x43,0x08,0xd0,0xd3,0x20,0x38,0xc0,0x0e,0xb0,0x03,0x8c,0x00,0xb3,0x00 } },
-{  16, 0x8ae0, 0, {0x20,0x80,0x07,0x10,0x03,0xe0,0x00,0xd3,0x10,0x38,0x18,0x0d,0x30,0x03,0x52,0x02 } },
-{  16, 0x8af0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb4,0x00,0x7f,0x20,0x1b,0xd0 } },
-{  16, 0x8b00, 0, {0x0f,0xf1,0x03,0xf8,0x40,0xef,0x00,0x3f,0xc0,0x0f,0xb4,0x03,0x7c,0x20,0xcf,0x04 } },
-{  16, 0x8b10, 0, {0xbf,0x40,0x0f,0xf0,0x03,0xe4,0x10,0xef,0x18,0x3d,0xc0,0x0f,0xe0,0x03,0xd0,0x06 } },
-{  16, 0x8b20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x00,0xe3,0x00,0xb2,0xc4 } },
-{  16, 0x8b30, 0, {0x0c,0xa0,0x03,0x24,0x00,0xdb,0x68,0x32,0xc8,0x0c,0xb4,0x03,0xec,0x80,0xc8,0x80 } },
-{  16, 0x8b40, 0, {0xb6,0xe0,0x0c,0xa0,0x03,0x2e,0x00,0xcb,0xe0,0xb2,0x60,0x0c,0xb8,0x0b,0x2a,0x00 } },
-{  16, 0x8b50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x02,0x87,0x00,0xa1,0xc8 } },
-{  16, 0x8b60, 0, {0x08,0x70,0x02,0x1c,0x08,0x97,0x02,0x21,0xd4,0x08,0x74,0x02,0xdc,0xc0,0x07,0x00 } },
-{  16, 0x8b70, 0, {0x21,0xc0,0x88,0x70,0x02,0x18,0x00,0x83,0x08,0x21,0xc0,0x08,0x50,0x02,0x12,0x04 } },
-{  16, 0x8b80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x20,0xad,0x80,0x29,0xe0 } },
-{  16, 0x8b90, 0, {0x08,0x58,0x02,0x1e,0x00,0x97,0xb0,0x21,0xe8,0x08,0x78,0x02,0xde,0x10,0x15,0x80 } },
-{  16, 0x8ba0, 0, {0x21,0xa1,0x08,0x48,0x02,0x5e,0x00,0x87,0xa4,0x65,0xa0,0x08,0x78,0x02,0x30,0x00 } },
-{  16, 0x8bb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcf,0x10,0x81,0x70,0xa8,0xc0 } },
-{  16, 0x8bc0, 0, {0x38,0x30,0x0a,0x0d,0x00,0x93,0x00,0xa0,0xc1,0x28,0x30,0x02,0xcc,0x02,0x83,0x88 } },
-{  16, 0x8bd0, 0, {0x20,0xe0,0x38,0x34,0x0a,0x4d,0x72,0x83,0x00,0x24,0xe8,0x28,0x34,0x82,0x12,0x04 } },
-{  16, 0x8be0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xba,0x40,0xee,0xc0,0xba,0x80 } },
-{  16, 0x8bf0, 0, {0x0c,0xe0,0x03,0x39,0x10,0xda,0x00,0x32,0x80,0x0c,0xa0,0x03,0xe8,0x00,0xde,0xc8 } },
-{  16, 0x8c00, 0, {0x33,0xa0,0x0c,0xe0,0x03,0x7b,0x00,0xca,0x00,0x37,0xb1,0x0c,0xe4,0x23,0x3a,0x04 } },
-{  16, 0x8c10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xc1,0x00,0xf8,0x00,0x36,0x00 } },
-{  16, 0x8c20, 0, {0x0f,0x80,0x03,0xc0,0x20,0x38,0x00,0x3e,0x00,0x0f,0x00,0x03,0xe0,0x00,0xf8,0x02 } },
-{  16, 0x8c30, 0, {0x3a,0x24,0x0f,0x80,0x83,0xa0,0x01,0xf8,0x04,0x3a,0x04,0x0d,0x80,0x13,0xd2,0x00 } },
-{  16, 0x8c40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x44,0xc1,0x00,0x32,0x40 } },
-{  16, 0x8c50, 0, {0x0c,0x90,0x32,0x24,0x0c,0xc1,0x06,0x38,0x40,0x0d,0x90,0x09,0x04,0x00,0xd9,0x00 } },
-{  16, 0x8c60, 0, {0x3e,0x40,0x0f,0x18,0x03,0x24,0x00,0xf9,0x01,0x3e,0x40,0x0f,0x90,0x03,0xc2,0x04 } },
-{  16, 0x8c70, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x06,0x89,0x00,0x2a,0x50 } },
-{  16, 0x8c80, 0, {0x08,0x94,0x0a,0x24,0x00,0x89,0x42,0x22,0x50,0x0a,0x90,0x12,0x25,0x00,0x89,0x00 } },
-{  16, 0x8c90, 0, {0x2e,0x50,0x0b,0x9c,0x0a,0x25,0x10,0xb9,0x00,0x2e,0x50,0x0b,0x90,0x02,0xe0,0x00 } },
-{  16, 0x8ca0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x20,0x89,0x00,0x20,0x42 } },
-{  16, 0x8cb0, 0, {0x08,0x10,0xc2,0xac,0x10,0x89,0x08,0x2a,0x42,0x09,0x90,0x02,0x24,0x20,0x99,0x00 } },
-{  16, 0x8cc0, 0, {0x2e,0x42,0x0a,0xb1,0x82,0x2c,0x20,0xb9,0x00,0x6e,0x42,0x0b,0x90,0x02,0xc6,0x00 } },
-{  16, 0x8cd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x83,0x00,0x28,0x48 } },
-{  16, 0x8ce0, 0, {0x08,0x12,0x62,0x8c,0x80,0x81,0x00,0x20,0x40,0x02,0x10,0x02,0x84,0x80,0x81,0x20 } },
-{  16, 0x8cf0, 0, {0x2c,0x49,0x0b,0x12,0x06,0x04,0x84,0xb3,0x02,0x6c,0x40,0x0b,0x12,0x02,0xc2,0x01 } },
-{  16, 0x8d00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x41,0xe0,0xc8,0x78,0x30,0x14 } },
-{  16, 0x8d10, 0, {0x4c,0x05,0x13,0xa1,0x42,0xc0,0x78,0x38,0x1e,0x0d,0x87,0x83,0x01,0x40,0xd0,0x50 } },
-{  16, 0x8d20, 0, {0x3c,0x14,0x0e,0x05,0x03,0x01,0x40,0xf8,0x78,0x3c,0x14,0x0f,0x05,0x03,0xee,0x03 } },
-{  16, 0x8d30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xfc,0x00,0xff,0x00,0x0e,0x44 } },
-{  16, 0x8d40, 0, {0x2f,0xf1,0x03,0x74,0x40,0xf9,0x00,0x3e,0x40,0x0d,0x90,0x03,0x64,0x40,0xfd,0x10 } },
-{  16, 0x8d50, 0, {0x3f,0x44,0x0f,0xd1,0x01,0xf4,0x40,0xf9,0x01,0x3f,0xc0,0x0f,0xd1,0x03,0xe6,0x06 } },
-{  16, 0x8d60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0x22,0xe9,0x88,0xb2,0x40 } },
-{  16, 0x8d70, 0, {0x0f,0x90,0x03,0x24,0x16,0xc9,0x8c,0x36,0x7b,0x8f,0x9c,0x83,0xa7,0x90,0xc9,0x00 } },
-{  16, 0x8d80, 0, {0x3e,0x50,0x04,0x94,0x13,0x24,0x50,0xc9,0xe0,0x3e,0x50,0x0f,0x90,0x03,0x06,0x00 } },
-{  16, 0x8d90, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe2,0x80,0x88,0xa0,0x22,0x28 } },
-{  16, 0x8da0, 0, {0x0b,0x8a,0x02,0x2a,0x80,0x88,0xa4,0x22,0x30,0x08,0x8e,0x0a,0x22,0x02,0x88,0xa0 } },
-{  16, 0x8db0, 0, {0x2e,0x28,0x88,0xaa,0x12,0x22,0x90,0x88,0xf4,0x2e,0x20,0x0b,0xc8,0x02,0x0e,0x04 } },
-{  16, 0x8dc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xd4,0x20,0xa5,0x08,0x21,0x42 } },
-{  16, 0x8dd0, 0, {0x0b,0x50,0x82,0x14,0x31,0x85,0x08,0x25,0x40,0x0a,0x50,0x22,0x94,0x40,0x85,0x08 } },
-{  16, 0x8de0, 0, {0x6d,0x40,0x08,0x50,0x02,0x54,0x02,0x95,0x00,0x2d,0x48,0x0b,0x50,0x82,0x42,0x01 } },
-{  16, 0x8df0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0x84,0x00,0x8d,0x10,0x23,0x40 } },
-{  16, 0x8e00, 0, {0x0b,0xd0,0x00,0x34,0x01,0x8d,0x00,0x23,0x41,0x58,0xd0,0x02,0x34,0x00,0x8d,0x08 } },
-{  16, 0x8e10, 0, {0x2f,0x50,0x08,0xd2,0x02,0x74,0x80,0x9d,0x00,0x2f,0x48,0x0b,0xdc,0x02,0x46,0x04 } },
-{  16, 0x8e20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe7,0x40,0xe9,0xc0,0x32,0x40 } },
-{  16, 0x8e30, 0, {0x0f,0x90,0x09,0x26,0x00,0xc9,0x04,0x36,0x40,0x1f,0x90,0x23,0xa4,0x08,0xc9,0x40 } },
-{  16, 0x8e40, 0, {0x3e,0x40,0x0c,0x94,0x0b,0x64,0x20,0xd9,0x02,0x3e,0x41,0x0f,0x94,0x03,0x68,0x04 } },
-{  16, 0x8e50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x80,0x3e,0x40 } },
-{  16, 0x8e60, 0, {0x0f,0x14,0x03,0xc5,0x08,0xf9,0x00,0x3e,0x40,0x1f,0x90,0x23,0xe4,0x00,0xf9,0x00 } },
-{  16, 0x8e70, 0, {0x3c,0x40,0xaf,0x98,0x03,0x86,0x00,0xe9,0x00,0x3e,0x40,0x0f,0x10,0x0b,0x8a,0x00 } },
-{  16, 0x8e80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xb0,0x00,0xdc,0x40,0xb3,0x00 } },
-{  16, 0x8e90, 0, {0x0f,0xc0,0x03,0x31,0x02,0xc4,0x04,0xb1,0x00,0x3c,0x40,0x03,0x10,0x00,0xfc,0x40 } },
-{  16, 0x8ea0, 0, {0x33,0x00,0x0c,0xc4,0x03,0xb1,0x00,0xcc,0x00,0xb3,0x00,0x0c,0xc4,0x03,0xca,0x04 } },
-{  16, 0x8eb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8a,0x80,0x22,0xa0 } },
-{  16, 0x8ec0, 0, {0x0b,0xa0,0x02,0x2a,0x00,0x8a,0x84,0x22,0xa1,0x08,0xa0,0x02,0x28,0x08,0xba,0x01 } },
-{  16, 0x8ed0, 0, {0x22,0x80,0x08,0xa0,0x2b,0x28,0x00,0x8a,0x80,0x2a,0x80,0x08,0xe0,0x02,0xca,0x00 } },
-{  16, 0x8ee0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x02,0x9b,0x81,0x20,0xe0 } },
-{  16, 0x8ef0, 0, {0x8b,0x38,0x06,0xce,0x00,0x93,0x80,0x20,0xc0,0x08,0x38,0x02,0x0c,0x00,0xb3,0x80 } },
-{  16, 0x8f00, 0, {0x6c,0xe0,0x0a,0xb0,0x02,0x4c,0x00,0x93,0x00,0x20,0xe0,0x08,0x30,0x02,0xca,0x00 } },
-{  16, 0x8f10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x10,0x04,0x80,0x08,0x21,0x02 } },
-{  16, 0x8f20, 0, {0x4b,0x44,0x06,0xd0,0x20,0x90,0x08,0x21,0x02,0x80,0x44,0x02,0x10,0x00,0xb4,0xc0 } },
-{  16, 0x8f30, 0, {0x2d,0x10,0x48,0x40,0x02,0x00,0x00,0x94,0x89,0x29,0x30,0x08,0x40,0x02,0xe8,0x00 } },
-{  16, 0x8f40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x32,0x00,0xd6,0x80,0x31,0xa0 } },
-{  16, 0x8f50, 0, {0x0f,0xe8,0x0b,0xca,0x00,0xd6,0x80,0x23,0xa0,0x04,0xf8,0x0b,0x1a,0x00,0xff,0x80 } },
-{  16, 0x8f60, 0, {0xbf,0xa0,0x2e,0xc8,0x13,0xda,0x02,0x5e,0x80,0x73,0xa0,0x2c,0x78,0x03,0xea,0x02 } },
-{  16, 0x8f70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf9,0x00,0x3e,0x40 } },
-{  16, 0x8f80, 0, {0x0f,0x90,0x03,0x24,0x00,0xe9,0x00,0x3e,0x40,0x0e,0x80,0x03,0xe4,0x00,0xf8,0x00 } },
-{  16, 0x8f90, 0, {0x32,0x40,0x0f,0xb0,0x03,0xe4,0x01,0xe9,0x04,0x36,0x40,0x0f,0x80,0x03,0xc2,0x06 } },
-{  16, 0x8fa0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xcd,0x80,0x33,0x60 } },
-{  16, 0x8fb0, 0, {0x0c,0xd8,0x43,0x36,0x00,0xcd,0x80,0x33,0x60,0x0c,0xd9,0x23,0xbe,0x00,0x4d,0x80 } },
-{  16, 0x8fc0, 0, {0x33,0x60,0x08,0xf8,0x0b,0x3e,0x00,0xfd,0x84,0x3f,0x60,0x0f,0xf9,0x03,0xc0,0x00 } },
-{  16, 0x8fd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x90,0x04,0xde,0x00,0x23,0x80 } },
-{  16, 0x8fe0, 0, {0x08,0x60,0x02,0xb8,0x20,0x8e,0x04,0x23,0x80,0x08,0x68,0x02,0x10,0x00,0x8e,0x20 } },
-{  16, 0x8ff0, 0, {0x23,0x82,0x08,0x40,0x02,0x12,0x00,0xf6,0x00,0x2d,0x80,0x0b,0x41,0xa0,0xea,0x04 } },
-{  16, 0x9000, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x84,0x00,0x21,0x00 } },
-{  16, 0x9010, 0, {0x08,0x41,0x02,0x50,0x40,0x94,0x00,0x21,0x00,0x0a,0x52,0x02,0xd8,0x00,0x85,0x02 } },
-{  16, 0x9020, 0, {0x25,0x04,0x08,0x40,0x22,0x18,0x08,0xb4,0x00,0x2d,0x10,0x0b,0x78,0x40,0xc0,0x00 } },
-{  16, 0x9030, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xee,0x22,0x93,0x00,0x20,0xc0 } },
-{  16, 0x9040, 0, {0x08,0x38,0x02,0xec,0x00,0x93,0x00,0x20,0xc1,0x2a,0x20,0x02,0x64,0x02,0x82,0x10 } },
-{  16, 0x9050, 0, {0x24,0xf0,0x0a,0x3c,0x42,0x24,0x28,0xb3,0x00,0x2c,0xe0,0x0b,0x88,0x82,0xc8,0x04 } },
-{  16, 0x9060, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xad,0x00,0xcb,0x00,0xb2,0xc0 } },
-{  16, 0x9070, 0, {0xac,0xbe,0x03,0x6e,0x02,0xdb,0x00,0xb2,0xc0,0x1e,0xa0,0x03,0xe4,0x00,0xca,0x11 } },
-{  16, 0x9080, 0, {0xb6,0xd0,0xac,0xbc,0x03,0x24,0x00,0xfb,0x00,0x3e,0xc0,0xcf,0x84,0x03,0xea,0x04 } },
-{  16, 0x9090, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe0,0x40,0xf8,0x00,0x3c,0x00 } },
-{  16, 0x90a0, 0, {0x2f,0x82,0x03,0xa0,0x00,0xe8,0x00,0x3e,0x00,0x1d,0x90,0x13,0xa8,0x00,0xf9,0x00 } },
-{  16, 0x90b0, 0, {0x3a,0x00,0x81,0x83,0x43,0xe8,0x00,0xe8,0x03,0x3e,0x04,0x0f,0xb0,0x03,0xe0,0x00 } },
-{  16, 0x90c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xe0,0x00,0xd6,0x00,0x37,0x80 } },
-{  16, 0x90d0, 0, {0x0c,0xa0,0x03,0xf8,0x00,0xce,0x00,0x33,0x80,0x0d,0xa0,0x13,0x20,0x08,0xce,0x00 } },
-{  16, 0x90e0, 0, {0x33,0x82,0x0c,0x40,0x73,0x30,0x18,0xce,0x00,0x1f,0x80,0x4f,0xc1,0x43,0x00,0x44 } },
-{  16, 0x90f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x7c,0x00,0x8d,0x00,0x23,0x40 } },
-{  16, 0x9100, 0, {0x0a,0xd0,0x02,0xf4,0x00,0x8d,0x00,0x23,0x40,0x08,0xd4,0x80,0x3e,0x42,0x8d,0x40 } },
-{  16, 0x9110, 0, {0x23,0x40,0x08,0xf0,0x02,0x3e,0x40,0x8d,0x00,0x0f,0x40,0x0b,0xf4,0x02,0x20,0x40 } },
-{  16, 0x9120, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x99,0x00,0xa6,0x40 } },
-{  16, 0x9130, 0, {0x08,0x90,0x06,0xe4,0x00,0x91,0x00,0x20,0x40,0x88,0x00,0x02,0x24,0x08,0x80,0x40 } },
-{  16, 0x9140, 0, {0x20,0x40,0x0a,0xb0,0x02,0x24,0x00,0x89,0x00,0x0e,0x40,0x0b,0x84,0x02,0x20,0x00 } },
-{  16, 0x9150, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x82,0x00,0x20,0x80 } },
-{  16, 0x9160, 0, {0x0a,0x21,0x06,0xc8,0x01,0x82,0x00,0x20,0x80,0x08,0x32,0x82,0x08,0x08,0x83,0x00 } },
-{  16, 0x9170, 0, {0x60,0x80,0x0a,0x00,0x12,0x08,0x80,0x82,0x00,0x2c,0x80,0x0b,0x30,0x0a,0x02,0x01 } },
-{  16, 0x9180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x60,0x00,0xd8,0x00,0x36,0x00 } },
-{  16, 0x9190, 0, {0x0c,0x84,0x23,0xe0,0x00,0xc8,0x00,0x32,0x00,0x0d,0x82,0x0b,0x20,0x02,0xc8,0x00 } },
-{  16, 0x91a0, 0, {0x32,0x00,0x0e,0x00,0x03,0x20,0x02,0xc8,0x00,0x3e,0x00,0x0f,0x80,0x03,0x00,0x03 } },
-{  16, 0x91b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xbf,0x00,0x3f,0xc0 } },
-{  16, 0x91c0, 0, {0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00,0xbf,0xc0,0x8f,0xb0,0x03,0xfc,0x08,0xff,0x02 } },
-{  16, 0x91d0, 0, {0x3f,0xc0,0x0d,0xf0,0x03,0xed,0x00,0xff,0x02,0x3f,0xc0,0x0f,0xf0,0x03,0xe8,0x06 } },
-{  16, 0x91e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0xf0,0x8c,0xff,0x00,0x3d,0x60 } },
-{  16, 0x91f0, 0, {0x2c,0xb2,0x83,0x7c,0x90,0xdf,0x38,0x31,0xe0,0x0f,0xf8,0x03,0x3c,0x00,0xff,0x20 } },
-{  16, 0x9200, 0, {0x3f,0xc4,0x0e,0xf4,0x03,0x7c,0x00,0xf4,0x80,0x33,0x00,0x0d,0xf8,0x03,0xf0,0x00 } },
-{  16, 0x9210, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe1,0x20,0xbb,0x62,0x2e,0x42 } },
-{  16, 0x9220, 0, {0x28,0xf4,0x42,0x3e,0x40,0x8f,0x44,0x22,0xe0,0x0b,0xb0,0x83,0x7f,0x44,0xbf,0xc1 } },
-{  16, 0x9230, 0, {0x2d,0xdc,0x2a,0xf6,0x02,0x3f,0x45,0xb8,0x80,0x22,0x61,0x88,0xb8,0x02,0xe0,0x04 } },
-{  16, 0x9240, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc5,0x80,0xb2,0x18,0x2e,0xc8 } },
-{  16, 0x9250, 0, {0x29,0x30,0x32,0x0c,0x08,0xb3,0x20,0x20,0xc0,0x4b,0x92,0x02,0x0c,0x00,0xb3,0x40 } },
-{  16, 0x9260, 0, {0x2c,0xc0,0x89,0x34,0x12,0x4c,0x00,0xb0,0x00,0x24,0xc1,0x49,0x30,0x02,0xe2,0x01 } },
-{  16, 0x9270, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xa4,0x00,0xba,0x0c,0x2e,0xe0 } },
-{  16, 0x9280, 0, {0xa9,0xb0,0x06,0x2c,0x00,0x8b,0x00,0xa2,0xc0,0x0b,0x90,0x00,0x6c,0x00,0xbb,0x00 } },
-{  16, 0x9290, 0, {0x2e,0xc0,0x0b,0x30,0x02,0x6c,0x00,0xba,0x80,0x26,0xf0,0x08,0xb0,0x02,0xf0,0x04 } },
-{  16, 0x92a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0xee,0x00,0xfb,0xc4,0x3e,0x78 } },
-{  16, 0x92b0, 0, {0x2d,0xb0,0x03,0x6c,0x08,0xfb,0x00,0x32,0xc0,0x8b,0x24,0x83,0x2c,0x00,0xfb,0x00 } },
-{  16, 0x92c0, 0, {0x3e,0xc0,0x8f,0xb0,0x0b,0x6c,0x08,0xb2,0xe0,0x16,0x60,0x8d,0xb0,0x23,0xd0,0x04 } },
-{  16, 0x92d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbe,0x98,0xff,0x40,0x3f,0xc0 } },
-{  16, 0x92e0, 0, {0x0e,0x70,0x03,0xdc,0x00,0xff,0x00,0x3f,0xc0,0x0f,0xe0,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0x92f0, 0, {0x3f,0xc0,0x0e,0xf0,0x03,0xac,0x00,0xfe,0x00,0xb9,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
-{  16, 0x9300, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xad,0x00,0xfa,0x40,0x3e,0xd0 } },
-{  16, 0x9310, 0, {0x0e,0xb2,0x03,0xec,0x00,0xc3,0x00,0x3e,0xc0,0x0c,0xa0,0x03,0x2c,0x01,0xfb,0x00 } },
-{  16, 0x9320, 0, {0x3c,0xc0,0x0e,0xb8,0x03,0xec,0x00,0xda,0x00,0x3a,0xd0,0x4f,0xb0,0x23,0xd0,0x04 } },
-{  16, 0x9330, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xba,0x00,0x2c,0xc0 } },
-{  16, 0x9340, 0, {0x08,0xf4,0x07,0xbc,0x14,0xdf,0x00,0x3e,0xc0,0x1a,0xa0,0x52,0xbc,0x00,0xbf,0x04 } },
-{  16, 0x9350, 0, {0x3f,0xc0,0x8a,0xf0,0x03,0xbc,0x00,0xfa,0x00,0x22,0xc8,0x0f,0xb0,0x03,0xf2,0x00 } },
-{  16, 0x9360, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x48,0x01,0xb1,0x00,0x6c,0xc2 } },
-{  16, 0x9370, 0, {0x0a,0x30,0x42,0xcc,0x00,0x83,0x05,0x2c,0xc0,0x08,0x30,0x02,0x8c,0x01,0xb3,0x04 } },
-{  16, 0x9380, 0, {0x2c,0xc0,0x0a,0x30,0x22,0x8c,0x00,0x80,0x80,0x28,0xc0,0x0b,0x30,0x22,0xf8,0x00 } },
-{  16, 0x9390, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x08,0xb7,0x80,0x6f,0xe0 } },
-{  16, 0x93a0, 0, {0x18,0x78,0x02,0x8e,0x40,0xb7,0x80,0x2d,0xe0,0x0a,0x78,0x02,0x9e,0x00,0xb7,0x80 } },
-{  16, 0x93b0, 0, {0x29,0xe1,0x0a,0x78,0x02,0x9e,0x01,0xbc,0x80,0x29,0xe4,0x0b,0x78,0x02,0xc8,0x00 } },
-{  16, 0x93c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x09,0x40,0xf1,0x20,0x3c,0xc4 } },
-{  16, 0x93d0, 0, {0x0e,0x39,0x02,0xcc,0x00,0xc3,0x00,0x2c,0xc4,0x08,0x92,0x03,0x8c,0x88,0xb3,0x10 } },
-{  16, 0x93e0, 0, {0x2c,0xc4,0x0e,0xb0,0x07,0x8c,0x00,0xc2,0x08,0x38,0xc0,0x0f,0x30,0x43,0xd2,0x02 } },
-{  16, 0x93f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x10,0xfc,0x00,0x7f,0xc0 } },
-{  16, 0x9400, 0, {0x0f,0xf0,0x83,0xfc,0x21,0xdf,0x08,0x3b,0xc0,0x8f,0x90,0x01,0xfc,0x21,0xff,0x0c } },
-{  16, 0x9410, 0, {0x3f,0xc2,0x0f,0xf1,0x03,0xec,0x00,0xef,0x00,0x77,0xc0,0x1e,0xf0,0x03,0x90,0x06 } },
-{  16, 0x9420, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x01,0xf9,0x00,0x32,0xc0 } },
-{  16, 0x9430, 0, {0x0f,0xb2,0x03,0xee,0x90,0xdb,0xe1,0x3a,0xc0,0x4d,0x38,0x13,0x2d,0x30,0xfb,0x00 } },
-{  16, 0x9440, 0, {0x3e,0xe0,0x4f,0xba,0x43,0x2c,0x40,0xfa,0x00,0x3f,0xc0,0x8c,0xb0,0x03,0xea,0x00 } },
-{  16, 0x9450, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb1,0x00,0x21,0xc0 } },
-{  16, 0x9460, 0, {0x0b,0x71,0x02,0xcc,0x20,0xa7,0x28,0x21,0xc0,0x0b,0x70,0x13,0x5c,0x08,0xb7,0x10 } },
-{  16, 0x9470, 0, {0x2d,0xc4,0x4b,0x34,0x83,0x1c,0xc1,0xb7,0x02,0x2d,0xc0,0x1a,0x70,0x02,0xd2,0x04 } },
-{  16, 0x9480, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9a,0x20,0xb4,0xc4,0x25,0xa2 } },
-{  16, 0x9490, 0, {0x0b,0x78,0x06,0xde,0x00,0x83,0x80,0x29,0xe0,0x1b,0xf8,0x02,0x5e,0x80,0xa7,0xa0 } },
-{  16, 0x94a0, 0, {0x2d,0xc8,0x0a,0x72,0x02,0x1e,0x00,0xa6,0x80,0x28,0xe0,0x08,0x78,0x02,0xf0,0x00 } },
-{  16, 0x94b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xed,0x00,0xb3,0x40,0x24,0xc3 } },
-{  16, 0x94c0, 0, {0x0b,0x30,0x42,0xcc,0x00,0xa3,0x00,0x20,0xc0,0x1b,0x34,0x02,0x4c,0x00,0xb3,0x00 } },
-{  16, 0x94d0, 0, {0x2c,0xc0,0x4b,0x30,0x02,0x0c,0x00,0xb3,0x88,0x2c,0xd4,0x0a,0x30,0x02,0xd2,0x04 } },
-{  16, 0x94e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x00,0xfe,0x40,0xb7,0xa0 } },
-{  16, 0x94f0, 0, {0x0f,0xa0,0x03,0xe8,0x00,0xda,0x00,0x3a,0x80,0x0f,0xe2,0x03,0x68,0x00,0xfa,0x00 } },
-{  16, 0x9500, 0, {0x3e,0x80,0x0f,0xa0,0x0b,0x28,0x00,0xee,0xe0,0x3f,0xb0,0x04,0xa0,0x03,0xfa,0x04 } },
-{  16, 0x9510, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x04,0xf0,0x08,0x3a,0x10 } },
-{  16, 0x9520, 0, {0x0f,0x84,0x03,0xe0,0x10,0xf8,0x00,0x3e,0x00,0x4f,0x80,0x83,0xe0,0x00,0xf8,0x00 } },
-{  16, 0x9530, 0, {0x3c,0x00,0x0f,0x80,0x03,0x80,0x00,0xf8,0x40,0x3e,0x09,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0x9540, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x20,0xe9,0x00,0x32,0x44 } },
-{  16, 0x9550, 0, {0x0c,0x90,0x03,0x24,0x00,0xf9,0x00,0x3e,0x40,0x0f,0x90,0x13,0xe4,0x00,0xb9,0x00 } },
-{  16, 0x9560, 0, {0x1e,0x40,0x0c,0x10,0x03,0x24,0x00,0xc9,0xa0,0x3c,0x64,0x0c,0x90,0x03,0x82,0x04 } },
-{  16, 0x9570, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x00,0x22,0x68 } },
-{  16, 0x9580, 0, {0x08,0x13,0x02,0x24,0x08,0xf9,0x00,0x2e,0x48,0x1b,0x90,0x02,0xe4,0x00,0xb9,0x00 } },
-{  16, 0x9590, 0, {0x3e,0x40,0x0c,0x90,0x02,0x24,0x08,0xf9,0x40,0x2e,0x60,0x0a,0x90,0x06,0xe0,0x00 } },
-{  16, 0x95a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x24,0x00,0xa9,0x00,0x20,0x40 } },
-{  16, 0x95b0, 0, {0x08,0x90,0x02,0x24,0x00,0xb9,0x01,0x2e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb9,0x00 } },
-{  16, 0x95c0, 0, {0x2e,0x40,0x08,0x92,0x22,0x24,0x00,0x89,0x00,0x2e,0x40,0x08,0x90,0x02,0xc6,0x00 } },
-{  16, 0x95d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0x81,0x21,0xe0,0x50 } },
-{  16, 0x95e0, 0, {0x28,0x16,0x0a,0x04,0x80,0xa1,0x40,0x2c,0x40,0x4b,0x14,0x22,0xc4,0x00,0xb1,0x00 } },
-{  16, 0x95f0, 0, {0x2c,0x50,0x09,0x14,0x02,0x04,0x04,0xb1,0x00,0x2c,0x40,0x0a,0x10,0x02,0xc2,0x01 } },
-{  16, 0x9600, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xe8,0x50,0x32,0x00 } },
-{  16, 0x9610, 0, {0x8c,0x80,0x02,0x20,0x00,0xb8,0x00,0x3e,0x00,0x0b,0x80,0x33,0xe0,0x10,0xf8,0x00 } },
-{  16, 0x9620, 0, {0x3e,0x00,0x0c,0x80,0x03,0x20,0x08,0xca,0x00,0x3e,0x00,0x0c,0x80,0x03,0xae,0x03 } },
-{  16, 0x9630, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xfc,0x40,0xfd,0x10,0x2f,0x41 } },
-{  16, 0x9640, 0, {0x4f,0x91,0x03,0xe4,0x40,0xf9,0x40,0x3e,0x40,0x4f,0xd0,0x63,0xe5,0x00,0xf9,0x40 } },
-{  16, 0x9650, 0, {0x3a,0x50,0x2e,0x94,0x03,0x65,0x00,0xed,0x00,0x3f,0x50,0x0f,0x90,0x03,0xe6,0x06 } },
-{  16, 0x9660, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xe6,0x00,0xf9,0xe0,0x33,0x50 } },
-{  16, 0x9670, 0, {0x0c,0xda,0x03,0xa6,0x00,0xd9,0x80,0x3f,0x40,0x0f,0x91,0x03,0xa6,0x00,0xf9,0x88 } },
-{  16, 0x9680, 0, {0x3e,0x68,0x0c,0xde,0x03,0x66,0x00,0xed,0x00,0x3b,0x69,0x0c,0x90,0x03,0xc6,0x00 } },
-{  16, 0x9690, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x08,0xb8,0xe0,0x20,0x20 } },
-{  16, 0x96a0, 0, {0x18,0x8e,0x26,0xe1,0x00,0x80,0xa0,0x2e,0x00,0x4b,0x88,0x42,0xe1,0x50,0xb8,0x40 } },
-{  16, 0x96b0, 0, {0x2e,0x2a,0x0d,0x0a,0x02,0x20,0x08,0xb8,0x00,0x2e,0x14,0x0d,0x80,0x02,0xce,0x04 } },
-{  16, 0x96c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc5,0x00,0xb1,0x60,0x20,0x40 } },
-{  16, 0x96d0, 0, {0x08,0x31,0xa2,0xc5,0x00,0x91,0x48,0x2c,0x40,0x1b,0x12,0x02,0x84,0x00,0xb1,0x00 } },
-{  16, 0x96e0, 0, {0x2c,0x50,0x09,0x16,0x02,0x05,0x00,0xa3,0x04,0x28,0x40,0x08,0x10,0x02,0xc2,0x01 } },
-{  16, 0x96f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xa4,0x00,0xb9,0x08,0x20,0x70 } },
-{  16, 0x9700, 0, {0x28,0x90,0x02,0xe4,0x00,0x89,0x00,0x2e,0x40,0x0b,0x90,0x02,0xe4,0x08,0xb9,0x03 } },
-{  16, 0x9710, 0, {0x2c,0x40,0x29,0x90,0x02,0x64,0x00,0xb9,0x00,0x2e,0x62,0x09,0x90,0x02,0xc6,0x04 } },
-{  16, 0x9720, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x05,0xe5,0x00,0xf9,0xd0,0xb2,0x70 } },
-{  16, 0x9730, 0, {0x08,0x90,0x03,0xe4,0x00,0xd9,0x04,0x3e,0x40,0x0f,0x90,0x03,0xa4,0x10,0xf9,0x02 } },
-{  16, 0x9740, 0, {0x3e,0x40,0x0d,0x90,0x2b,0x64,0x00,0xe9,0x8d,0x3a,0x60,0x0c,0x90,0x03,0xe8,0x04 } },
-{  16, 0x9750, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x80,0x3e,0x42 } },
-{  16, 0x9760, 0, {0x0f,0x90,0x03,0xe4,0x00,0xf9,0x00,0x3e,0x40,0x0f,0x9a,0x03,0xe4,0x00,0xf9,0x00 } },
-{  16, 0x9770, 0, {0x3e,0x40,0x2f,0x10,0x03,0xa4,0x00,0xf9,0x22,0x3c,0x40,0x4f,0x90,0x03,0xca,0x00 } },
-{  16, 0x9780, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa0,0x00,0xf0,0x40,0x32,0x00 } },
-{  16, 0x9790, 0, {0x0c,0x80,0x03,0xc0,0x00,0xf8,0x00,0x32,0x20,0x1f,0x80,0x03,0xe0,0x00,0xc8,0x00 } },
-{  16, 0x97a0, 0, {0x32,0x00,0x0c,0x80,0x02,0x20,0x00,0xc8,0xc0,0x3e,0x00,0x0c,0x80,0x03,0xca,0x04 } },
-{  16, 0x97b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x15,0x28,0x10,0xba,0x00,0x23,0xa0 } },
-{  16, 0x97c0, 0, {0x0a,0xe4,0x02,0xe8,0x00,0xba,0x00,0x2b,0xa1,0x0b,0xa0,0x02,0xe8,0x00,0xaa,0x00 } },
-{  16, 0x97d0, 0, {0x2a,0x81,0x0a,0xa0,0x03,0xe8,0x08,0xde,0x00,0x2e,0x80,0x0a,0xa0,0x02,0xca,0x00 } },
-{  16, 0x97e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb3,0x04,0xa0,0xb1 } },
-{  16, 0x97f0, 0, {0x08,0x36,0x22,0xcc,0x00,0xb3,0x00,0x20,0xe4,0x0b,0x30,0x02,0xcc,0x00,0x83,0x00 } },
-{  16, 0x9800, 0, {0x20,0xc0,0x08,0x18,0x02,0x0c,0x00,0x91,0x01,0x2c,0xc0,0x08,0x30,0x06,0xca,0x00 } },
-{  16, 0x9810, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0xc8,0xb3,0x21,0x21,0xc2 } },
-{  16, 0x9820, 0, {0x2a,0x70,0x02,0xdc,0x00,0xb7,0xa0,0x29,0xc0,0x0b,0x72,0x02,0xce,0x00,0xa7,0x81 } },
-{  16, 0x9830, 0, {0x29,0xc0,0x4a,0x74,0x02,0xfe,0x00,0x97,0x01,0x2c,0xc0,0x0a,0x70,0x12,0xe8,0x00 } },
-{  16, 0x9840, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x80,0xf7,0xc0,0x31,0xe0 } },
-{  16, 0x9850, 0, {0x0c,0x48,0x03,0xde,0x11,0xf7,0x80,0x21,0xe0,0x0b,0x7a,0x03,0xde,0x00,0xc3,0x80 } },
-{  16, 0x9860, 0, {0x33,0xd8,0x6c,0x78,0x03,0x3e,0x00,0xd6,0x80,0x3d,0xe0,0x0c,0x78,0x03,0xea,0x02 } },
-{  16, 0x9870, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0d,0xac,0x08,0xfb,0x80,0x3e,0xc0 } },
-{  16, 0x9880, 0, {0x0f,0xd0,0x03,0xec,0x04,0xfb,0x3c,0x3e,0xc0,0x0f,0xb6,0x07,0x6c,0x01,0xfb,0x00 } },
-{  16, 0x9890, 0, {0x3e,0xd0,0x0f,0x94,0x07,0xec,0x01,0xea,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0xc2,0x06 } },
-{  16, 0x98a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xfe,0x00,0xcf,0xa4,0x3b,0x60 } },
-{  16, 0x98b0, 0, {0x08,0xd9,0x03,0x7e,0x00,0xcf,0x80,0x3f,0x25,0x4f,0xfc,0x87,0xbe,0x00,0xcf,0x80 } },
-{  16, 0x98c0, 0, {0x7f,0xfc,0x0c,0xfc,0x03,0x7c,0x00,0xf6,0x90,0x33,0xe0,0x0f,0xf8,0x03,0xc0,0x00 } },
-{  16, 0x98d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x08,0x8f,0x28,0x21,0x40 } },
-{  16, 0x98e0, 0, {0x08,0xd0,0x02,0x1c,0x40,0xa7,0x20,0x31,0x04,0x1b,0x78,0x02,0xdc,0x80,0xd7,0x00 } },
-{  16, 0x98f0, 0, {0x2f,0xc4,0x1a,0xd0,0x02,0x1e,0x48,0xb6,0x00,0x61,0xc0,0x0b,0x70,0x06,0xea,0x04 } },
-{  16, 0x9900, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x00,0x87,0x30,0x69,0x44 } },
-{  16, 0x9910, 0, {0x08,0x50,0x22,0x0c,0x00,0x87,0x01,0x2d,0x44,0x8b,0x70,0x06,0x8c,0x10,0x87,0x00 } },
-{  16, 0x9920, 0, {0x29,0xc9,0x08,0x50,0x02,0x1c,0x44,0xa6,0x00,0x61,0xc0,0x0b,0x70,0x02,0xc0,0x00 } },
-{  16, 0x9930, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcd,0x00,0x83,0x88,0x60,0x40 } },
-{  16, 0x9940, 0, {0x00,0x10,0x02,0x4c,0x00,0x2b,0x00,0x2c,0x41,0x1b,0x30,0x02,0xcc,0x00,0x93,0x00 } },
-{  16, 0x9950, 0, {0x2c,0xc0,0x0a,0x30,0x42,0x0c,0x00,0xb2,0x40,0x20,0xf1,0x0b,0x30,0x02,0xc8,0x04 } },
-{  16, 0x9960, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbd,0x41,0xcf,0xc0,0xba,0xf0 } },
-{  16, 0x9970, 0, {0x28,0x90,0x1b,0x6c,0x08,0xcf,0x00,0x2c,0xc0,0x0f,0xf0,0x03,0xac,0x00,0x8b,0x00 } },
-{  16, 0x9980, 0, {0x3f,0xc0,0x6c,0xb0,0x4b,0x2c,0x01,0xfb,0x40,0x22,0xc8,0x0f,0xb0,0x03,0xea,0x04 } },
-{  16, 0x9990, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x04,0xfb,0x04,0x3f,0xd4 } },
-{  16, 0x99a0, 0, {0x0f,0x10,0x03,0xac,0x00,0xfb,0x00,0x32,0xc0,0x5f,0xb0,0x03,0xec,0x00,0xfb,0x04 } },
-{  16, 0x99b0, 0, {0x3e,0xc0,0x4f,0x10,0x13,0xec,0x00,0xfb,0x88,0x3e,0xc0,0x4f,0xb0,0x03,0xe0,0x00 } },
-{  16, 0x99c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xc7,0x00,0x33,0x62 } },
-{  16, 0x99d0, 0, {0x0c,0xc0,0x0b,0x3c,0x00,0xef,0x00,0x33,0xe0,0x1c,0xf0,0x13,0x3c,0x08,0xf7,0x00 } },
-{  16, 0x99e0, 0, {0x31,0xc0,0x0e,0xd8,0x03,0xbc,0x00,0xfe,0x00,0x3d,0xc6,0x0c,0xf0,0x03,0xc0,0x44 } },
-{  16, 0x99f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x00,0xcb,0x03,0x22,0x47 } },
-{  16, 0x9a00, 0, {0x08,0x98,0x42,0x2c,0x00,0x9b,0x00,0x2a,0xc0,0x0a,0xb0,0x02,0x2c,0x00,0xbb,0x04 } },
-{  16, 0x9a10, 0, {0x2a,0xc0,0x0a,0xb0,0x02,0xac,0x08,0xfa,0x00,0x2e,0x60,0x08,0xb0,0x02,0xe0,0x40 } },
-{  16, 0x9a20, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x9b,0x00,0x20,0x40 } },
-{  16, 0x9a30, 0, {0x08,0x98,0x02,0x2c,0x00,0xbb,0x00,0x22,0x88,0x08,0x30,0x02,0x2c,0x00,0xbb,0x00 } },
-{  16, 0x9a40, 0, {0x22,0xc0,0x8a,0x92,0x02,0xac,0x00,0xaa,0x80,0x2e,0xc0,0x08,0xb0,0x06,0xe0,0x00 } },
-{  16, 0x9a50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x00,0xa0,0x40 } },
-{  16, 0x9a60, 0, {0x08,0x10,0x02,0x0c,0x00,0xb3,0x00,0x28,0x80,0x0a,0x32,0x12,0x0c,0x00,0xb3,0x04 } },
-{  16, 0x9a70, 0, {0x28,0xc0,0x0a,0x30,0x22,0x8c,0x20,0xb2,0x00,0x2c,0xc0,0x08,0x30,0x02,0xc2,0x01 } },
-{  16, 0x9a80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x02,0xcb,0x00,0x30,0x40 } },
-{  16, 0x9a90, 0, {0x1c,0x94,0x03,0x2c,0x00,0xef,0x00,0x32,0xc0,0x88,0xf0,0x8b,0x2c,0x00,0xfb,0x00 } },
-{  16, 0x9aa0, 0, {0x33,0xc0,0xae,0xf0,0x03,0xac,0x80,0xea,0x01,0x3e,0xc0,0x2c,0xb0,0x03,0xc0,0x03 } },
-{  16, 0x9ab0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x2f,0x40 } },
-{  16, 0x9ac0, 0, {0x07,0xd2,0x83,0xfc,0x00,0xdf,0x04,0x3f,0xc0,0x0f,0xb0,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0x9ad0, 0, {0x3f,0xc0,0x0f,0xd0,0x0b,0xec,0x00,0xee,0x00,0x3f,0x40,0x0f,0xf0,0x03,0xe8,0x06 } },
-{  16, 0x9ae0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf5,0x00,0xcf,0x08,0x3f,0x48 } },
-{  16, 0x9af0, 0, {0x0f,0xc3,0x93,0x70,0xd0,0xdc,0x30,0x3f,0xd8,0x0c,0xb2,0x03,0x3c,0xc0,0xff,0x40 } },
-{  16, 0x9b00, 0, {0x33,0xc4,0x2c,0xf1,0x03,0x62,0x50,0xfc,0x34,0x33,0x00,0x0f,0x5c,0x03,0xf0,0x00 } },
-{  16, 0x9b10, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xc4,0x80,0x8b,0x00,0x2f,0x5a } },
-{  16, 0x9b20, 0, {0x0b,0xa6,0x12,0x21,0xc0,0x89,0x70,0x2f,0xdc,0x08,0xf2,0xc2,0x3d,0xd0,0xbf,0x40 } },
-{  16, 0x9b30, 0, {0x37,0xdc,0x88,0xf5,0x0a,0x20,0x80,0xe8,0x10,0x2a,0x16,0x0b,0x90,0x02,0xe0,0x04 } },
-{  16, 0x9b40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc0,0x00,0x83,0x08,0x2c,0x44 } },
-{  16, 0x9b50, 0, {0x0b,0x02,0x02,0x0c,0x00,0x80,0x00,0x2c,0xc8,0x08,0x33,0x42,0x8c,0x90,0xb3,0x30 } },
-{  16, 0x9b60, 0, {0x28,0xc8,0x4a,0x32,0x12,0x80,0x0c,0xb0,0xa0,0x28,0x28,0x0b,0x12,0x02,0xe2,0x01 } },
-{  16, 0x9b70, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa2,0x00,0x8b,0x00,0x2e,0x48 } },
-{  16, 0x9b80, 0, {0x0b,0xa0,0x22,0x20,0x20,0x88,0x80,0x2e,0xc0,0x28,0xb0,0x0a,0xac,0x00,0xbb,0x00 } },
-{  16, 0x9b90, 0, {0x2e,0xc0,0x0a,0xb0,0x02,0xa0,0x00,0xab,0x82,0x2a,0xa0,0x0b,0xb2,0x02,0xf0,0x04 } },
-{  16, 0x9ba0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe7,0x00,0xcb,0x00,0x3e,0xc0 } },
-{  16, 0x9bb0, 0, {0xcf,0x9c,0x0b,0x21,0x00,0xd8,0x88,0x3e,0xc0,0x0c,0xb0,0x03,0xac,0x00,0xfb,0x00 } },
-{  16, 0x9bc0, 0, {0x3a,0xc0,0x0e,0xb0,0x43,0xe8,0x40,0xf8,0x80,0x3a,0x60,0x0f,0x98,0x03,0xd0,0x04 } },
-{  16, 0x9bd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x00,0xff,0x00,0x0f,0xe0 } },
-{  16, 0x9be0, 0, {0x07,0xa1,0x03,0xe8,0x02,0xfb,0x00,0x3f,0xc0,0x0f,0x70,0x23,0x7c,0x00,0xff,0x02 } },
-{  16, 0x9bf0, 0, {0x35,0xc0,0x4d,0xb0,0x03,0x74,0x20,0xfc,0x01,0x3f,0x00,0x0f,0xf8,0x03,0xf8,0x00 } },
-{  16, 0x9c00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa5,0x00,0xcb,0x00,0xba,0x40 } },
-{  16, 0x9c10, 0, {0x0c,0x14,0x0b,0x2f,0x22,0xc9,0x40,0x32,0xc0,0x8e,0xb0,0x03,0xac,0x00,0xfb,0x00 } },
-{  16, 0x9c20, 0, {0x3e,0xc0,0x0e,0xb0,0x03,0xe4,0x00,0xc9,0x00,0x32,0x00,0x2c,0x90,0x03,0x10,0x04 } },
-{  16, 0x9c30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x01,0x24,0x00,0x8f,0x00,0x22,0x40 } },
-{  16, 0x9c40, 0, {0x2c,0xa5,0x42,0x29,0x00,0x8b,0x04,0xa3,0xc1,0x0d,0xf0,0x0a,0x3c,0x00,0xbf,0x00 } },
-{  16, 0x9c50, 0, {0x3f,0xc0,0x08,0xf0,0x01,0x69,0x00,0xda,0x05,0x22,0xd0,0x08,0x94,0x03,0x72,0x00 } },
-{  16, 0x9c60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x60,0x40,0x83,0x01,0x20,0xc0 } },
-{  16, 0x9c70, 0, {0x09,0x00,0x02,0x20,0x00,0x82,0x60,0x22,0xc0,0x08,0x30,0x42,0x4c,0x10,0xbb,0x02 } },
-{  16, 0x9c80, 0, {0x2c,0xc0,0x08,0xb0,0x12,0x05,0x00,0x9b,0x00,0x20,0x82,0x09,0x32,0x02,0x38,0x00 } },
-{  16, 0x9c90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x90,0x87,0x80,0x20,0xe0 } },
-{  16, 0x9ca0, 0, {0x08,0x58,0x02,0x16,0x14,0x84,0x81,0x21,0xe0,0x29,0x39,0x02,0x5e,0x00,0xb7,0x80 } },
-{  16, 0x9cb0, 0, {0x28,0xe0,0x08,0x78,0x02,0x7a,0x80,0x96,0x81,0x21,0xe0,0x09,0xf8,0x02,0x48,0x00 } },
-{  16, 0x9cc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x09,0x8b,0x10,0x38,0x44 } },
-{  16, 0x9cd0, 0, {0x4d,0x25,0x12,0x0c,0x00,0xc2,0x10,0x22,0xc8,0x0a,0x38,0x03,0xcc,0x00,0xf3,0x10 } },
-{  16, 0x9ce0, 0, {0x2c,0xc0,0x0c,0x30,0x03,0x8a,0xc0,0xd9,0x10,0x32,0x40,0x2d,0x10,0x03,0x12,0x02 } },
-{  16, 0x9cf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x80,0xff,0x00,0x3f,0x40 } },
-{  16, 0x9d00, 0, {0x0f,0xf0,0x03,0xf4,0x40,0xed,0x00,0x3f,0xc0,0x0e,0xf3,0x03,0xbc,0x04,0xff,0x00 } },
-{  16, 0x9d10, 0, {0x3f,0xc2,0x0f,0xf0,0x0b,0xd4,0x00,0xff,0x10,0xbf,0x80,0x0e,0xf0,0x03,0xd0,0x06 } },
-{  16, 0x9d20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xfa,0x00,0xcb,0x02,0x3e,0xc0 } },
-{  16, 0x9d30, 0, {0x0f,0x90,0x03,0xa0,0x00,0xcb,0x00,0x3a,0xca,0x0c,0xb3,0x13,0xaf,0x24,0xcb,0x48 } },
-{  16, 0x9d40, 0, {0x1e,0xc8,0x0f,0xb6,0x03,0x2c,0x00,0xfa,0x00,0x3e,0xc0,0x0f,0x90,0x03,0xea,0x00 } },
-{  16, 0x9d50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x08,0x87,0x20,0x2d,0xc4 } },
-{  16, 0x9d60, 0, {0x0b,0x50,0x12,0xdc,0x04,0x87,0x00,0x2c,0xc0,0x08,0x70,0xa2,0x1d,0x00,0xa7,0x40 } },
-{  16, 0x9d70, 0, {0x25,0xcb,0x8b,0x74,0x82,0x1c,0x00,0xb7,0x00,0x2d,0xc1,0x0b,0x70,0x02,0xd2,0x04 } },
-{  16, 0x9d80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9a,0x01,0x87,0x90,0x2d,0xe0 } },
-{  16, 0x9d90, 0, {0x0b,0x78,0x02,0xce,0x00,0x86,0x80,0x2d,0xe4,0x29,0x7a,0x02,0x9e,0x80,0x87,0xa0 } },
-{  16, 0x9da0, 0, {0x6d,0xe8,0x0b,0x78,0x02,0x1e,0x00,0xb5,0x80,0x2d,0x60,0x0b,0x78,0x02,0xf0,0x00 } },
-{  16, 0x9db0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcd,0x00,0x83,0x02,0x2c,0xe0 } },
-{  16, 0x9dc0, 0, {0x0b,0x30,0x02,0xcc,0x00,0x83,0xe0,0x2c,0xc0,0x08,0x30,0x02,0x0c,0x00,0xa3,0x00 } },
-{  16, 0x9dd0, 0, {0x24,0xc0,0x0b,0xb0,0x02,0x0e,0x20,0xb3,0x08,0x2c,0xc0,0x0b,0x30,0x02,0xd2,0x04 } },
-{  16, 0x9de0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x82,0xca,0x00,0x3e,0xa8 } },
-{  16, 0x9df0, 0, {0x0f,0xe0,0x03,0xf8,0x02,0x8e,0x80,0x3e,0x80,0x0d,0xa0,0x5b,0xa8,0x00,0xca,0x00 } },
-{  16, 0x9e00, 0, {0x3e,0x80,0x0f,0xa0,0x03,0x3b,0x80,0xfe,0x42,0x2f,0x80,0x0f,0xa8,0x03,0xfa,0x04 } },
-{  16, 0x9e10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x20,0xf8,0x00,0x3e,0x00 } },
-{  16, 0x9e20, 0, {0x0f,0x06,0x03,0xc0,0x00,0xf8,0x11,0x3e,0x00,0x0f,0x00,0x03,0xe0,0x00,0xf8,0x00 } },
-{  16, 0x9e30, 0, {0x36,0x00,0x0f,0x80,0x0b,0xe0,0x00,0xf8,0x04,0x3e,0x20,0x0f,0x81,0x03,0xd2,0x00 } },
-{  16, 0x9e40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf9,0x00,0x3e,0x40 } },
-{  16, 0x9e50, 0, {0x0c,0x9a,0x03,0x24,0x40,0xc9,0xc0,0x3e,0x40,0x4c,0x90,0x03,0x24,0x00,0xf9,0x00 } },
-{  16, 0x9e60, 0, {0x36,0x40,0x07,0x90,0x03,0x24,0x00,0xc9,0x04,0x32,0x60,0x0f,0x90,0x03,0xc2,0x04 } },
-{  16, 0x9e70, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x02,0x2e,0x40 } },
-{  16, 0x9e80, 0, {0x0a,0x92,0x02,0x25,0x02,0x89,0xe0,0x2e,0x40,0x98,0x90,0x02,0x24,0x00,0xb9,0x00 } },
-{  16, 0x9e90, 0, {0x22,0x40,0x09,0x90,0x02,0x04,0x00,0xd9,0x00,0x22,0x44,0x0b,0x9c,0x02,0xe0,0x00 } },
-{  16, 0x9ea0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x2c,0x00,0xb9,0x00,0x2c,0x40 } },
-{  16, 0x9eb0, 0, {0x08,0x90,0x02,0x24,0x28,0x89,0x00,0x2c,0x40,0x68,0x90,0x42,0x24,0x0c,0xb1,0x04 } },
-{  16, 0x9ec0, 0, {0x26,0x40,0x0b,0x90,0x0a,0x2c,0x80,0x81,0x00,0x22,0x40,0xcb,0x92,0x82,0xc6,0x00 } },
-{  16, 0x9ed0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb1,0x20,0x2c,0x48 } },
-{  16, 0x9ee0, 0, {0x0a,0x12,0x02,0x04,0x80,0x81,0x21,0x2c,0x4c,0x08,0x11,0x02,0x04,0x08,0xb1,0x10 } },
-{  16, 0x9ef0, 0, {0x20,0x4c,0x09,0x12,0x02,0x24,0x01,0x91,0x20,0xa0,0x48,0x0b,0x10,0x02,0xc2,0x01 } },
-{  16, 0x9f00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x41,0xe0,0xf8,0x50,0x3e,0x14 } },
-{  16, 0x9f10, 0, {0x0c,0x85,0x03,0x21,0x40,0xc8,0x50,0x3e,0x10,0x08,0x06,0x83,0x01,0xf0,0xf8,0x68 } },
-{  16, 0x9f20, 0, {0x36,0x10,0x0f,0x05,0x03,0x29,0x40,0xc8,0x50,0x32,0x94,0x0f,0x85,0x03,0xee,0x03 } },
-{  16, 0x9f30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x00,0xf9,0x10,0x3f,0x44 } },
-{  16, 0x9f40, 0, {0x0f,0xd1,0x0b,0xf4,0x40,0xfd,0x12,0x2e,0x4c,0x03,0x92,0x0b,0xe4,0x00,0xf9,0x20 } },
-{  16, 0x9f50, 0, {0x3e,0x4c,0x0f,0x91,0x03,0xfc,0x00,0xfd,0x10,0x3f,0x44,0x0f,0xd0,0x03,0xe6,0x06 } },
-{  16, 0x9f60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x20,0xc9,0x01,0x3e,0x40 } },
-{  16, 0x9f70, 0, {0x0f,0xd0,0x03,0x3c,0x00,0xbd,0x00,0x32,0x63,0x0c,0x9e,0x43,0x27,0x00,0xe9,0xc0 } },
-{  16, 0x9f80, 0, {0x3e,0x68,0x0c,0x98,0x03,0x34,0x00,0xf9,0x10,0x3f,0x40,0x0f,0xd0,0x03,0xc6,0x00 } },
-{  16, 0x9f90, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xc2,0x20,0xd8,0x00,0x2e,0x00 } },
-{  16, 0x9fa0, 0, {0x0b,0x80,0x52,0x28,0x04,0xb8,0x00,0x22,0x38,0x08,0x88,0x03,0x62,0x00,0x88,0xf0 } },
-{  16, 0x9fb0, 0, {0x2e,0x3a,0x48,0x8f,0x0a,0x20,0x00,0xb0,0x80,0x2e,0x00,0x0b,0x80,0x02,0xce,0x04 } },
-{  16, 0x9fc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x80,0x81,0x00,0x2c,0x40 } },
-{  16, 0x9fd0, 0, {0x0b,0x10,0x02,0x04,0x00,0xb1,0x00,0x20,0x42,0x48,0x14,0x42,0x05,0x80,0xa1,0x20 } },
-{  16, 0x9fe0, 0, {0x2c,0x44,0x08,0x10,0x82,0x04,0x00,0xb1,0x20,0x2c,0x40,0x0b,0x10,0x02,0xc2,0x01 } },
-{  16, 0x9ff0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa5,0x01,0x99,0x00,0x2e,0x40 } },
-{  16, 0xa000, 0, {0x0b,0x90,0x02,0x24,0x40,0xbb,0x01,0x22,0x41,0x08,0x90,0x12,0x24,0x00,0xa9,0x00 } },
-{  16, 0xa010, 0, {0x2c,0x40,0x08,0x10,0x40,0x24,0x08,0xb9,0x40,0x6e,0x50,0x0b,0x92,0x02,0xc6,0x04 } },
-{  16, 0xa020, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe7,0x14,0xc9,0x05,0x3e,0x41 } },
-{  16, 0xa030, 0, {0x0f,0x90,0x0b,0x24,0x04,0xf9,0x08,0xb2,0x40,0x2c,0x90,0x0a,0x24,0x00,0xe9,0x00 } },
-{  16, 0xa040, 0, {0x3e,0x40,0x2c,0x90,0x03,0x27,0x00,0xf9,0x80,0x3e,0x60,0x0f,0x90,0x03,0xe8,0x04 } },
-{  16, 0xa050, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x84,0x88,0xf9,0x00,0x3e,0x48 } },
-{  16, 0xa060, 0, {0x0f,0x99,0x03,0xe6,0x00,0xf9,0x02,0x3c,0x40,0xaf,0x10,0x03,0xe4,0x12,0xd9,0x04 } },
-{  16, 0xa070, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe5,0x00,0xf9,0xc0,0x3e,0x64,0x0f,0x90,0x83,0xca,0x00 } },
-{  16, 0xa080, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x00,0xc8,0x00,0x3e,0x00 } },
-{  16, 0xa090, 0, {0x0f,0x80,0x03,0x21,0x00,0xc8,0x40,0xb2,0x00,0x0c,0x80,0x03,0x20,0x10,0xc8,0x00 } },
-{  16, 0xa0a0, 0, {0x32,0x00,0x0c,0x80,0x03,0xe0,0x80,0xf8,0x04,0x32,0x00,0x2c,0x80,0x0b,0x0a,0x04 } },
-{  16, 0xa0b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xca,0x00,0x2e,0x80 } },
-{  16, 0xa0c0, 0, {0x0b,0xe8,0x0a,0x38,0x10,0x8e,0xc0,0x22,0x80,0x0d,0xa0,0x02,0x28,0x00,0x0a,0x04 } },
-{  16, 0xa0d0, 0, {0x02,0x80,0x28,0xa0,0x02,0xfb,0x00,0xba,0x00,0x37,0xb0,0x48,0xea,0x02,0x0a,0x00 } },
-{  16, 0xa0e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0x01,0x2c,0xc0 } },
-{  16, 0xa0f0, 0, {0x8b,0xb0,0x42,0x0c,0x90,0x9b,0x20,0x20,0xc0,0x48,0x30,0x42,0x2c,0x00,0x83,0x00 } },
-{  16, 0xa100, 0, {0x20,0xc0,0x08,0x30,0x02,0xcd,0x40,0xb3,0x00,0x24,0xc8,0x08,0x38,0x02,0x0a,0x00 } },
-{  16, 0xa110, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x14,0x00,0x87,0x00,0x2d,0xc0 } },
-{  16, 0xa120, 0, {0x0b,0x24,0x06,0x16,0x00,0x93,0x08,0x21,0xc8,0x09,0x31,0x02,0x0c,0x80,0x87,0xa0 } },
-{  16, 0xa130, 0, {0x21,0xc0,0x18,0x72,0x02,0xdc,0x00,0xb7,0xb4,0x24,0xe3,0x08,0x78,0x02,0x28,0x00 } },
-{  16, 0xa140, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x02,0x97,0xa0,0x3d,0xf0 } },
-{  16, 0xa150, 0, {0x0f,0x48,0x03,0x3e,0x00,0xd6,0x80,0x30,0xe0,0x2c,0x7a,0x02,0x1e,0x82,0xc3,0xf0 } },
-{  16, 0xa160, 0, {0x33,0xec,0x0c,0x7c,0x03,0xd6,0x00,0xf7,0x80,0x35,0xe0,0x0c,0xd8,0x03,0x2a,0x02 } },
-{  16, 0xa170, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x19,0xa5,0xa0,0xfb,0x00,0x3e,0xca } },
-{  16, 0xa180, 0, {0x0f,0x80,0x03,0xec,0x02,0xea,0x00,0x3e,0xc6,0x0f,0xb4,0x0b,0xed,0x40,0xfb,0x00 } },
-{  16, 0xa190, 0, {0xbe,0xc0,0x0f,0xb6,0x43,0xe0,0x00,0xfb,0x02,0x3e,0x80,0x0f,0x90,0x03,0xc2,0x06 } },
-{  16, 0xa1a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x02,0xcf,0x88,0x3f,0xe0 } },
-{  16, 0xa1b0, 0, {0x0c,0xb9,0x03,0xfe,0x00,0xdd,0x81,0x33,0xe0,0x8c,0xfc,0x03,0x3f,0x04,0xcf,0x80 } },
-{  16, 0xa1c0, 0, {0x33,0xe2,0x4f,0xfc,0x03,0x3e,0x00,0xcf,0xc0,0x33,0x64,0x0c,0xf8,0x03,0xc0,0x00 } },
-{  16, 0xa1d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x94,0x40,0x87,0x00,0x2f,0xc1 } },
-{  16, 0xa1e0, 0, {0x0d,0x69,0xa2,0xd0,0x40,0xbc,0x00,0x23,0xc0,0x08,0xf0,0x02,0x9c,0x00,0x87,0x00 } },
-{  16, 0xa1f0, 0, {0x21,0xc0,0x0b,0x70,0x0a,0x3c,0x04,0x87,0x10,0x21,0x4c,0x08,0x60,0x02,0xea,0x04 } },
-{  16, 0xa200, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9e,0x00,0x87,0x00,0x2d,0xc0 } },
-{  16, 0xa210, 0, {0x09,0x62,0x02,0xd8,0x00,0x97,0x00,0x21,0xc4,0x08,0x70,0x02,0x0c,0x40,0x97,0x00 } },
-{  16, 0xa220, 0, {0x21,0xc4,0x0b,0x30,0x02,0x58,0x00,0xa7,0x08,0x21,0x80,0x08,0x60,0x82,0xc0,0x00 } },
-{  16, 0xa230, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xe4,0x25,0x83,0x00,0x2c,0xc0 } },
-{  16, 0xa240, 0, {0x09,0x22,0x02,0xcc,0x20,0xb2,0x00,0x20,0xc0,0x28,0xb0,0x02,0x8c,0x00,0x93,0x00 } },
-{  16, 0xa250, 0, {0x20,0xc0,0x0b,0x30,0x42,0x6c,0x20,0x83,0x08,0x20,0xe2,0x08,0xb8,0x02,0xc8,0x04 } },
-{  16, 0xa260, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xa4,0x00,0xcf,0x00,0x3f,0xc0 } },
-{  16, 0xa270, 0, {0x0d,0x9c,0x03,0xe8,0x00,0xdb,0x80,0x33,0xc0,0x0c,0xf0,0x0b,0x3c,0x06,0xdf,0x00 } },
-{  16, 0xa280, 0, {0xb3,0xc0,0x0b,0xf0,0x07,0x68,0x00,0xef,0x40,0x32,0xa8,0x0c,0xa8,0x03,0xea,0x04 } },
-{  16, 0xa290, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x00,0x2e,0xc0 } },
-{  16, 0xa2a0, 0, {0x0f,0x94,0x03,0xc5,0x40,0xfa,0x30,0x3e,0xc0,0x0f,0xb0,0x03,0x6c,0x00,0xeb,0x00 } },
-{  16, 0xa2b0, 0, {0x3e,0xc0,0x0f,0x30,0x13,0xad,0x40,0xfb,0x02,0x3e,0xd0,0x0f,0xb4,0x03,0xe0,0x00 } },
-{  16, 0xa2c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xe4,0x00,0xc7,0x00,0x31,0xc1 } },
-{  16, 0xa2d0, 0, {0x8c,0xd0,0x03,0x34,0x00,0xcd,0x00,0x3d,0xc0,0x0c,0xf0,0x01,0x7c,0x00,0xdb,0x01 } },
-{  16, 0xa2e0, 0, {0x3d,0xc0,0x4c,0xf0,0x0b,0x30,0x02,0xc3,0x00,0x32,0x00,0x0f,0xd0,0x03,0x00,0x44 } },
-{  16, 0xa2f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6e,0x40,0x8b,0x00,0x2a,0xc0 } },
-{  16, 0xa300, 0, {0x28,0x84,0x42,0x22,0x80,0x88,0x80,0x3a,0xc0,0x0d,0xb0,0x02,0xac,0x08,0x8b,0x00 } },
-{  16, 0xa310, 0, {0x2e,0xc0,0x08,0xb0,0x02,0x23,0x20,0x8b,0x00,0x22,0x30,0x8b,0x8c,0x02,0x20,0x40 } },
-{  16, 0xa320, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x24,0x00,0x8b,0x00,0x22,0xc0 } },
-{  16, 0xa330, 0, {0x08,0x38,0x86,0x2a,0x00,0x89,0x80,0x2a,0xc0,0x08,0xb0,0x02,0xcc,0x00,0x9b,0x00 } },
-{  16, 0xa340, 0, {0x2e,0xc0,0x08,0xb0,0x42,0x26,0x00,0x8b,0x00,0x22,0x71,0x0b,0x8c,0x02,0x20,0x00 } },
-{  16, 0xa350, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x00,0x28,0xc0 } },
-{  16, 0xa360, 0, {0x08,0x32,0x42,0x00,0x00,0x81,0x00,0x28,0xc0,0x09,0x30,0x52,0x8c,0x08,0x83,0x00 } },
-{  16, 0xa370, 0, {0x2c,0xc0,0x18,0x30,0x06,0x00,0x00,0x83,0x00,0xa0,0x00,0x0b,0x00,0x02,0x02,0x01 } },
-{  16, 0xa380, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x74,0x02,0x8b,0x00,0x33,0xc0 } },
-{  16, 0xa390, 0, {0x0c,0x92,0x0b,0x20,0x02,0xc8,0x00,0x3b,0xc0,0x0c,0xf5,0x03,0xfc,0x00,0xdf,0x01 } },
-{  16, 0xa3a0, 0, {0x3f,0xc1,0x04,0xf0,0x33,0x21,0x40,0xcf,0x00,0x32,0x00,0x0f,0x80,0x0b,0x00,0x03 } },
-{  16, 0xa3b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xff,0x00,0x3f,0xc0 } },
-{  16, 0xa3c0, 0, {0x0f,0xc4,0x03,0xf0,0x00,0x9c,0x00,0x3b,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0xa3d0, 0, {0x2f,0xc0,0x0f,0xf0,0x03,0xf0,0x80,0xff,0x00,0x3f,0x00,0x0f,0xc0,0x03,0xe8,0x06 } },
-{  16, 0xa3e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0xc0,0xff,0xa0,0x31,0x24 } },
-{  16, 0xa3f0, 0, {0x0e,0xf0,0x63,0x10,0x04,0xef,0x64,0x3f,0xc0,0x4c,0xf3,0x03,0x1c,0x80,0xdf,0x08 } },
-{  16, 0xa400, 0, {0x37,0xc0,0x0f,0xf0,0x03,0xf0,0xa0,0xfc,0x00,0x31,0x08,0x2c,0xd2,0x03,0xf0,0x00 } },
-{  16, 0xa410, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe1,0x00,0xbb,0xc1,0x22,0x48 } },
-{  16, 0xa420, 0, {0x08,0xfd,0x02,0x2e,0x00,0x97,0x00,0x2f,0xc2,0x48,0x71,0x23,0x7e,0x40,0xbf,0x00 } },
-{  16, 0xa430, 0, {0x21,0xc5,0x4b,0xf5,0x02,0xef,0x00,0xbb,0x40,0x36,0xe0,0x08,0xa8,0x02,0xe0,0x04 } },
-{  16, 0xa440, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc5,0x84,0xb3,0x11,0xa2,0xc9 } },
-{  16, 0xa450, 0, {0x0a,0x30,0x02,0x00,0x01,0xb3,0x30,0x28,0xc4,0x08,0x32,0x42,0x0c,0x00,0xa3,0x08 } },
-{  16, 0xa460, 0, {0xa0,0xca,0x0a,0x32,0x82,0x80,0x10,0xb0,0x41,0x24,0x11,0x08,0x31,0x02,0xe2,0x01 } },
-{  16, 0xa470, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa5,0x00,0xbb,0x00,0x22,0xe1 } },
-{  16, 0xa480, 0, {0x28,0xb0,0x02,0x2c,0x80,0x9b,0x00,0x2e,0xc0,0x08,0xb0,0x02,0x6c,0x00,0xb3,0x00 } },
-{  16, 0xa490, 0, {0x22,0xc0,0x0b,0xb0,0x00,0xec,0x20,0xbb,0x00,0x26,0xc0,0x08,0x80,0x02,0xf0,0x04 } },
-{  16, 0xa4a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe3,0x40,0xf7,0x04,0x32,0xc0 } },
-{  16, 0xa4b0, 0, {0x4e,0xb0,0x23,0x2e,0x20,0xeb,0x00,0x1e,0xc0,0x0c,0xb0,0x01,0x2c,0x00,0xfb,0x00 } },
-{  16, 0xa4c0, 0, {0x36,0xc0,0x1f,0xb0,0x03,0xe1,0x40,0xfb,0x00,0x36,0x98,0x0c,0x90,0x03,0xd0,0x04 } },
-{  16, 0xa4d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb6,0x04,0xff,0x02,0x3f,0xc0 } },
-{  16, 0xa4e0, 0, {0x0f,0xf0,0x03,0xfe,0x00,0xef,0x02,0x3d,0xc0,0x0f,0xf0,0x23,0xfc,0x00,0xff,0x00 } },
-{  16, 0xa4f0, 0, {0x3f,0xc0,0x4f,0xf0,0x03,0xfc,0x00,0xf4,0x00,0x3b,0x40,0x0f,0xa0,0x13,0xf8,0x00 } },
-{  16, 0xa500, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xaa,0x20,0xeb,0x10,0x36,0xc0 } },
-{  16, 0xa510, 0, {0x0d,0xb0,0x07,0xec,0x20,0xdb,0x00,0x32,0xc0,0x0c,0xb0,0x02,0x6c,0x20,0xeb,0x00 } },
-{  16, 0xa520, 0, {0x3e,0xc1,0x0d,0xb0,0x03,0xe0,0x20,0xdb,0xa0,0x32,0x90,0x4c,0xb0,0x0b,0x10,0x04 } },
-{  16, 0xa530, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2d,0x00,0x8f,0x80,0x20,0xc1 } },
-{  16, 0xa540, 0, {0x08,0x70,0x12,0xcf,0x00,0x8f,0x00,0xa3,0xc0,0x0d,0xf0,0x02,0x3c,0x00,0x8f,0x00 } },
-{  16, 0xa550, 0, {0x37,0xc0,0x88,0xf0,0x02,0xec,0x00,0x88,0x00,0x20,0x40,0x08,0x80,0x02,0x32,0x00 } },
-{  16, 0xa560, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xa3,0x80,0x24,0x81 } },
-{  16, 0xa570, 0, {0x09,0x30,0x06,0xcc,0x40,0x93,0x00,0x28,0xc1,0x08,0xb0,0x02,0xcf,0x40,0xa3,0x00 } },
-{  16, 0xa580, 0, {0x2c,0xc0,0x09,0x30,0x02,0xcd,0x00,0x90,0x40,0x60,0x40,0x28,0x10,0x02,0x38,0x00 } },
-{  16, 0xa590, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x0e,0x00,0x87,0x80,0x23,0xe0 } },
-{  16, 0xa5a0, 0, {0x48,0x79,0x02,0xde,0x41,0x97,0x80,0x29,0xe0,0x19,0x78,0x06,0x9e,0x00,0x87,0x80 } },
-{  16, 0xa5b0, 0, {0x25,0xe0,0x08,0x78,0x02,0xd2,0x03,0x83,0x80,0x21,0xa0,0x08,0x68,0x02,0x08,0x00 } },
-{  16, 0xa5c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xa3,0x00,0x34,0xc0 } },
-{  16, 0xa5d0, 0, {0x0d,0x30,0x42,0xcc,0x01,0xd3,0x10,0x3a,0xc5,0x0c,0x39,0x03,0xcc,0x00,0xe3,0x04 } },
-{  16, 0xa5e0, 0, {0x3c,0xc4,0x0d,0x30,0x03,0xce,0x00,0xd0,0x00,0x30,0x40,0x0c,0x30,0x03,0x12,0x02 } },
-{  16, 0xa5f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0xf7,0x00,0x3f,0xc0 } },
-{  16, 0xa600, 0, {0x1f,0xf0,0x53,0xfc,0x00,0xef,0x08,0x37,0xd1,0x0f,0xf0,0x83,0x7c,0x00,0xf7,0x40 } },
-{  16, 0xa610, 0, {0x3f,0xc1,0x0f,0xf1,0x03,0xd0,0x00,0xff,0x00,0xbf,0x84,0x0f,0xc8,0x03,0xd0,0x06 } },
-{  16, 0xa620, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe0,0x00,0xfb,0x00,0x3e,0xe0 } },
-{  16, 0xa630, 0, {0x2c,0xbe,0x83,0xec,0x00,0xeb,0x40,0x3e,0xc0,0x0f,0xb4,0x03,0xed,0x20,0xfb,0x10 } },
-{  16, 0xa640, 0, {0xb6,0xd2,0x0f,0xb4,0x83,0xec,0x00,0xdb,0x80,0x36,0xc1,0x0c,0x90,0x21,0x2a,0x00 } },
-{  16, 0xa650, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x00,0xb7,0x00,0x2f,0xc0 } },
-{  16, 0xa660, 0, {0x08,0x36,0x02,0x0c,0x08,0x87,0x30,0x2d,0xd9,0x8b,0x72,0x86,0xdd,0x00,0xb3,0x20 } },
-{  16, 0xa670, 0, {0x21,0xc8,0x0b,0x74,0x02,0xd0,0x02,0x84,0x00,0xa0,0x00,0x28,0x20,0x02,0x12,0x04 } },
-{  16, 0xa680, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9a,0x00,0xb7,0x80,0x2d,0xe0 } },
-{  16, 0xa690, 0, {0x08,0x7a,0x02,0x9d,0x00,0xa7,0xa0,0x2d,0xe0,0x0b,0x78,0x02,0x9e,0x80,0xa7,0x80 } },
-{  16, 0xa6a0, 0, {0x21,0xe4,0x08,0x7a,0x26,0x9e,0x18,0x83,0x04,0x21,0xe0,0x08,0x78,0x0a,0x70,0x00 } },
-{  16, 0xa6b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0x00,0x2c,0xe0 } },
-{  16, 0xa6c0, 0, {0x58,0x30,0x12,0x0e,0x82,0x83,0x00,0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x01,0xb3,0x00 } },
-{  16, 0xa6d0, 0, {0x20,0xc1,0x0b,0x30,0x02,0xc0,0x08,0x88,0xd2,0x20,0x20,0x08,0x00,0x02,0x52,0x04 } },
-{  16, 0xa6e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x60,0xfa,0x00,0x3f,0x82 } },
-{  16, 0xa6f0, 0, {0x0c,0xa0,0x03,0xfa,0x00,0xaa,0x00,0x1e,0x80,0x8f,0xa0,0x03,0xe8,0x00,0xf2,0x00 } },
-{  16, 0xa700, 0, {0x32,0x80,0x1f,0xa0,0x03,0xe8,0x00,0xda,0x00,0x36,0x88,0xac,0xe0,0x03,0x7a,0x04 } },
-{  16, 0xa710, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe1,0x00,0xf8,0x00,0x3e,0x20 } },
-{  16, 0xa720, 0, {0x4f,0x80,0x03,0xe1,0x00,0xf0,0x00,0x3c,0x00,0x0b,0x80,0x03,0xe0,0x00,0xf8,0x02 } },
-{  16, 0xa730, 0, {0x3a,0x00,0x0f,0x80,0x43,0xf1,0x00,0xfc,0x0a,0x3d,0x00,0x0f,0xc0,0x03,0x92,0x00 } },
-{  16, 0xa740, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe6,0x00,0xc9,0x90,0x3e,0x40 } },
-{  16, 0xa750, 0, {0x0f,0x92,0x03,0xe4,0x00,0xd9,0x00,0x32,0x40,0x04,0x90,0x07,0xe7,0x00,0xf9,0x10 } },
-{  16, 0xa760, 0, {0x30,0x40,0x0c,0x90,0x43,0xe4,0x09,0xd9,0x80,0x22,0x40,0x2c,0x10,0x0b,0x02,0x04 } },
-{  16, 0xa770, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x60,0x89,0xc0,0x2e,0x40 } },
-{  16, 0xa780, 0, {0x0b,0x98,0x26,0xc5,0x80,0x89,0x00,0x22,0x40,0x28,0x90,0x12,0xe7,0x10,0xb9,0x00 } },
-{  16, 0xa790, 0, {0x36,0x40,0x28,0x90,0x12,0xc5,0x83,0xc9,0x80,0xb6,0x40,0x08,0x90,0x02,0x20,0x00 } },
-{  16, 0xa7a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x04,0x00,0x89,0x40,0x2e,0x41 } },
-{  16, 0xa7b0, 0, {0x4b,0x90,0x02,0xe4,0x00,0x99,0x00,0xa2,0x40,0x0a,0x90,0x02,0xe5,0x00,0xb9,0x00 } },
-{  16, 0xa7c0, 0, {0xe2,0x41,0x08,0x90,0x42,0xe4,0x00,0x9d,0x50,0xab,0x4a,0x08,0xd0,0x26,0x06,0x00 } },
-{  16, 0xa7d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x82,0x81,0x20,0x2c,0x50 } },
-{  16, 0xa7e0, 0, {0x0b,0x10,0x02,0xe4,0x00,0x81,0x40,0x20,0x50,0x4a,0x14,0x32,0xc4,0x00,0xb1,0x40 } },
-{  16, 0xa7f0, 0, {0x24,0x51,0x18,0x14,0x12,0xd4,0x00,0x85,0x40,0x2d,0x40,0x08,0x50,0x06,0x02,0x01 } },
-{  16, 0xa800, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xc8,0x00,0x3e,0x00 } },
-{  16, 0xa810, 0, {0x0f,0x80,0x02,0xe0,0x00,0xd8,0x00,0x32,0x00,0x0a,0x80,0x02,0xe0,0x10,0xf8,0x00 } },
-{  16, 0xa820, 0, {0x32,0x00,0x04,0x80,0x03,0xe0,0x00,0xd8,0x00,0x3a,0x00,0x0c,0xc0,0x03,0x2e,0x03 } },
-{  16, 0xa830, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xf9,0x10,0x3f,0x41 } },
-{  16, 0xa840, 0, {0x0f,0x94,0x03,0xf5,0x00,0xf9,0x40,0x3e,0x50,0x0d,0x94,0x03,0xe5,0x10,0xf9,0x40 } },
-{  16, 0xa850, 0, {0x3e,0x50,0x4f,0x94,0x03,0xc5,0x00,0xe9,0x41,0x36,0x50,0x0f,0x94,0x03,0xe6,0x06 } },
-{  16, 0xa860, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x00,0xfd,0xa8,0x3a,0x40 } },
-{  16, 0xa870, 0, {0x0c,0xd8,0x23,0x36,0x00,0xe9,0xa0,0x3e,0x78,0x0f,0x9e,0x03,0xb6,0x80,0xcd,0xe2 } },
-{  16, 0xa880, 0, {0x32,0x68,0x0c,0x9b,0x03,0x36,0x82,0x4d,0xa0,0x37,0x68,0x8c,0x98,0x03,0x06,0x00 } },
-{  16, 0xa890, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xeb,0xa0,0xb8,0x40,0x20,0x20 } },
-{  16, 0xa8a0, 0, {0x08,0x85,0x02,0x21,0x51,0x88,0xc0,0x2e,0x29,0x0b,0x8e,0x02,0xe1,0x00,0xd8,0xe0 } },
-{  16, 0xa8b0, 0, {0x22,0x32,0x0d,0x8d,0x23,0x61,0x48,0x98,0xd4,0xa2,0x10,0x28,0x84,0x02,0x0e,0x04 } },
-{  16, 0xa8c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc5,0x00,0xb3,0x00,0x2a,0x4a } },
-{  16, 0xa8d0, 0, {0x28,0x10,0x4e,0xa4,0x08,0xa1,0x68,0x28,0x44,0x0b,0x14,0x02,0xc5,0x00,0x81,0x40 } },
-{  16, 0xa8e0, 0, {0xa0,0x50,0x08,0x10,0x02,0x04,0x02,0x91,0x2a,0x20,0x44,0x28,0x14,0x4a,0x02,0x01 } },
-{  16, 0xa8f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xac,0x80,0xb9,0x00,0x22,0x40 } },
-{  16, 0xa900, 0, {0x48,0x90,0x06,0xa4,0x00,0xa9,0x00,0x2e,0x40,0x0b,0x90,0x22,0xe4,0x00,0x99,0x00 } },
-{  16, 0xa910, 0, {0x22,0x40,0x09,0x10,0x02,0x64,0x02,0x99,0x00,0x22,0x40,0x08,0x90,0x02,0x06,0x04 } },
-{  16, 0xa920, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x00,0x38,0x58 } },
-{  16, 0xa930, 0, {0x0c,0x90,0x53,0x84,0x14,0xa9,0x04,0x3e,0x40,0x0f,0x90,0x03,0xe4,0x00,0xc9,0x00 } },
-{  16, 0xa940, 0, {0x32,0x40,0x0c,0x90,0x03,0x24,0x04,0xd9,0x00,0xb6,0x40,0x4c,0x90,0x0b,0x28,0x04 } },
-{  16, 0xa950, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x02,0x3e,0x49 } },
-{  16, 0xa960, 0, {0x0f,0x10,0x43,0x64,0x00,0xd9,0x00,0x3e,0x40,0x0f,0x90,0x03,0xc4,0x00,0xf1,0x02 } },
-{  16, 0xa970, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc4,0x02,0xe9,0x04,0x3c,0x40,0x0f,0x1c,0x03,0xca,0x00 } },
-{  16, 0xa980, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x80,0xc8,0x20,0x3e,0x00 } },
-{  16, 0xa990, 0, {0x8c,0x80,0x0b,0x20,0x00,0xe8,0x02,0x3e,0x00,0x0f,0x80,0x03,0xa0,0x82,0xc8,0x00 } },
-{  16, 0xa9a0, 0, {0x6c,0x00,0x0f,0x80,0x03,0x20,0x10,0xc8,0x00,0x32,0x02,0x0c,0x80,0x03,0x0a,0x04 } },
-{  16, 0xa9b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x38,0x00,0x86,0x00,0x2e,0x80 } },
-{  16, 0xa9c0, 0, {0x68,0xa8,0x80,0x3a,0x00,0x8a,0x00,0x2e,0x80,0x0b,0xa0,0x02,0xf8,0x00,0x8a,0x00 } },
-{  16, 0xa9d0, 0, {0x2e,0x80,0x0b,0xa0,0x0a,0x3a,0x00,0x8e,0x10,0x23,0x80,0x08,0xa0,0x03,0x0a,0x00 } },
-{  16, 0xa9e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4d,0x00,0x83,0x00,0x2c,0xc0 } },
-{  16, 0xa9f0, 0, {0x08,0x38,0x00,0x0c,0x60,0x23,0x00,0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x40,0x83,0x00 } },
-{  16, 0xaa00, 0, {0x2c,0xc0,0x0b,0x30,0x02,0x0c,0x02,0x8a,0x80,0xa0,0xe0,0x28,0x30,0x0a,0x4a,0x00 } },
-{  16, 0xaa10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x16,0x20,0x87,0x02,0x2d,0xc1 } },
-{  16, 0xaa20, 0, {0x48,0x70,0x12,0x7c,0x00,0xa7,0x20,0x2d,0xc9,0x0b,0x72,0x00,0xdc,0x00,0x87,0x08 } },
-{  16, 0xaa30, 0, {0x2d,0xc4,0x1b,0x32,0x02,0x1d,0x01,0x87,0x42,0x21,0xc2,0x08,0x70,0x02,0x28,0x00 } },
-{  16, 0xaa40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x02,0xc7,0x80,0x3d,0xec } },
-{  16, 0xaa50, 0, {0x0c,0x58,0x03,0x1e,0x00,0xe7,0x80,0x3d,0xec,0x0f,0x7f,0x03,0x96,0x00,0xc7,0x80 } },
-{  16, 0xaa60, 0, {0x2d,0xe2,0x07,0x79,0x03,0x0a,0x06,0xc3,0x80,0x30,0x20,0x8c,0x38,0x03,0x6a,0x02 } },
-{  16, 0xaa70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xfb,0x00,0x3e,0xc0 } },
-{  16, 0xaa80, 0, {0x0f,0x10,0x43,0x8c,0x00,0xdb,0x38,0x3e,0xd8,0x0f,0xb0,0x03,0xcc,0x04,0xfb,0x44 } },
-{  16, 0xaa90, 0, {0x3e,0xc0,0x8f,0xb6,0x13,0xec,0x02,0xff,0x02,0x3e,0x00,0x0f,0xb0,0x03,0xc2,0x06 } },
-{  16, 0xaaa0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfa,0x00,0xff,0x80,0x31,0xe3 } },
-{  16, 0xaab0, 0, {0x0e,0xf8,0x23,0xfe,0x02,0xdf,0x80,0xb7,0xe2,0x0e,0xf8,0x03,0x7e,0x00,0x6d,0xd0 } },
-{  16, 0xaac0, 0, {0x33,0xe0,0x0c,0xf8,0x9b,0x76,0xc0,0xdf,0x84,0xb3,0xe0,0x04,0xf8,0x03,0xc0,0x00 } },
-{  16, 0xaad0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x90,0x40,0xb7,0x02,0x21,0xc4 } },
-{  16, 0xaae0, 0, {0x08,0x7b,0x42,0xdc,0x00,0x87,0x00,0x21,0xc4,0x0b,0x30,0x00,0x10,0x80,0x8d,0x00 } },
-{  16, 0xaaf0, 0, {0x23,0xc0,0x0d,0xf2,0x02,0x04,0x42,0x8f,0x00,0x29,0xc8,0x28,0x70,0x02,0xea,0x04 } },
-{  16, 0xab00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x00,0xb6,0x00,0x23,0xc0 } },
-{  16, 0xab10, 0, {0x0a,0x72,0x02,0x8c,0x00,0x87,0x00,0x21,0xc0,0x0a,0x30,0x02,0x04,0x01,0xa7,0x02 } },
-{  16, 0xab20, 0, {0x21,0xc0,0x08,0x70,0x42,0x00,0x8a,0x87,0x00,0x21,0xc0,0x28,0x70,0x02,0xc0,0x00 } },
-{  16, 0xab30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xc5,0x00,0xb0,0x00,0xa0,0xd0 } },
-{  16, 0xab40, 0, {0x08,0xb0,0x02,0xc9,0x42,0x8b,0x00,0x20,0xc0,0x0b,0x30,0x22,0x04,0x00,0x83,0x00 } },
-{  16, 0xab50, 0, {0xa0,0xc0,0x49,0x30,0x02,0x45,0x40,0x93,0xc0,0xa8,0xd4,0x00,0x35,0x02,0xc8,0x04 } },
-{  16, 0xab60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xbb,0x00,0x31,0xc0 } },
-{  16, 0xab70, 0, {0x0e,0xb0,0x23,0xcd,0x00,0xdf,0x00,0x37,0xc0,0x0e,0xf0,0x01,0x68,0x00,0xe3,0x00 } },
-{  16, 0xab80, 0, {0x33,0xc0,0x1c,0xf0,0x03,0x45,0x00,0xda,0xc8,0x92,0xd4,0x2c,0xb4,0x03,0xea,0x04 } },
-{  16, 0xab90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe5,0x20,0xfb,0x00,0x3e,0xc0 } },
-{  16, 0xaba0, 0, {0x0f,0xb0,0x03,0xec,0x00,0xfb,0x00,0x3e,0xc0,0x4f,0xb0,0x03,0xad,0x00,0xfb,0x00 } },
-{  16, 0xabb0, 0, {0x7e,0xc0,0x1f,0x30,0x03,0xa4,0x80,0xe9,0x20,0x3c,0xc0,0x0f,0x32,0x03,0xe0,0x00 } },
-{  16, 0xabc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xc7,0x00,0x33,0xc2 } },
-{  16, 0xabd0, 0, {0x2c,0xf0,0x03,0x3e,0x20,0xdb,0x00,0x13,0xc0,0x0c,0x70,0x03,0x3c,0x80,0xef,0x04 } },
-{  16, 0xabe0, 0, {0x73,0xc1,0x0f,0xf0,0x22,0x30,0x00,0xc6,0x00,0xb2,0xc0,0x0c,0xf0,0x03,0x00,0x44 } },
-{  16, 0xabf0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x69,0x00,0x8b,0x44,0xa2,0xc1 } },
-{  16, 0xac00, 0, {0x88,0xb0,0x03,0x6c,0x00,0x8b,0x00,0x22,0xc0,0x28,0xb0,0x0a,0x2d,0x00,0xbb,0x00 } },
-{  16, 0xac10, 0, {0x62,0xc0,0x0b,0xb0,0x02,0x26,0x02,0x8b,0x80,0x22,0xc0,0x08,0xb0,0x03,0x20,0x40 } },
-{  16, 0xac20, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x28,0x01,0x8a,0x08,0x22,0xc0 } },
-{  16, 0xac30, 0, {0x08,0xb2,0x02,0x6c,0x40,0x9b,0x00,0x28,0xc0,0x48,0xb0,0x16,0x29,0x04,0xb9,0x01 } },
-{  16, 0xac40, 0, {0x22,0xc0,0x49,0xb0,0x06,0xae,0x09,0x8b,0x80,0x22,0xe0,0x48,0xb0,0x02,0x20,0x00 } },
-{  16, 0xac50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x02,0x82,0x00,0x22,0xc0 } },
-{  16, 0xac60, 0, {0x88,0xb0,0x02,0x44,0x00,0x83,0x00,0x28,0xc0,0x08,0x30,0x02,0x08,0x00,0xb1,0x00 } },
-{  16, 0xac70, 0, {0x20,0xc0,0x0b,0x30,0x02,0x8c,0x00,0x83,0x80,0x20,0xe0,0x08,0x30,0x0a,0x02,0x01 } },
-{  16, 0xac80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x64,0x00,0xca,0x00,0x33,0xc0 } },
-{  16, 0xac90, 0, {0x0c,0xb2,0x03,0x2c,0x00,0xdf,0x00,0x3b,0xc0,0x4c,0xf5,0x13,0x2c,0x04,0xef,0x00 } },
-{  16, 0xaca0, 0, {0xa3,0xc0,0x0d,0xf0,0x03,0xa8,0x40,0xcb,0x00,0xb2,0x00,0x2c,0xb0,0x03,0x00,0x03 } },
-{  16, 0xacb0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf0,0x00,0xf4,0x00,0x3f,0xc0 } },
-{  16, 0xacc0, 0, {0x0f,0xb1,0x03,0xf0,0x00,0xff,0x00,0x37,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0xacd0, 0, {0x3f,0xc0,0x07,0xf0,0x0b,0x7c,0x08,0xff,0x01,0x3f,0x00,0x0f,0xf0,0x03,0xa8,0x06 } },
-{  16, 0xace0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0xc5,0xed,0x33,0x3b,0xcc } },
-{  16, 0xacf0, 0, {0x0c,0xf0,0x03,0x30,0x40,0xff,0x25,0x3f,0xcc,0x0c,0xf3,0x83,0x3c,0xd0,0xdf,0x48 } },
-{  16, 0xad00, 0, {0x37,0x30,0x4c,0xf3,0x03,0xfd,0x80,0xcf,0x28,0x33,0xd8,0x0c,0xf1,0x03,0x30,0x00 } },
-{  16, 0xad10, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0xd0,0xbb,0x31,0x20,0xcc } },
-{  16, 0xad20, 0, {0x88,0xf3,0x42,0x20,0x50,0xbf,0x90,0x2f,0xc4,0x0a,0xf6,0x02,0x7d,0xc0,0x8f,0x40 } },
-{  16, 0xad30, 0, {0x26,0x40,0x8f,0xf6,0x02,0xfd,0x00,0xff,0x08,0x39,0xc8,0x08,0xf6,0x02,0xa0,0x04 } },
-{  16, 0xad40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x80,0xa1,0x20,0x28,0xc9 } },
-{  16, 0xad50, 0, {0x08,0x30,0x9a,0x00,0x09,0xb3,0x00,0x2c,0xc0,0x20,0x30,0x02,0x4c,0x90,0x83,0x20 } },
-{  16, 0xad60, 0, {0x02,0x08,0x0b,0x33,0x12,0xcd,0x80,0x93,0x20,0x24,0xd8,0x08,0x34,0x22,0x22,0x01 } },
-{  16, 0xad70, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xae,0x00,0xbb,0x10,0x22,0xc0 } },
-{  16, 0xad80, 0, {0x08,0xb0,0x02,0x26,0x01,0x3b,0x01,0x6e,0xc0,0x08,0xb0,0x02,0x4c,0x08,0x8b,0x00 } },
-{  16, 0xad90, 0, {0xa2,0x89,0x0b,0xb0,0x02,0xec,0x00,0xab,0x00,0x6a,0xc1,0x28,0xb0,0x02,0xb0,0x04 } },
-{  16, 0xada0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0x6e,0x00,0xe8,0xc1,0x3a,0xc0 } },
-{  16, 0xadb0, 0, {0x2c,0xb0,0x43,0x26,0x00,0xfb,0x06,0x3e,0xc1,0x0c,0xb0,0x0b,0x2c,0x02,0xcb,0x00 } },
-{  16, 0xadc0, 0, {0x34,0x22,0x9f,0xb0,0x43,0xec,0x00,0x9b,0x02,0x36,0xc1,0x8c,0xb0,0x03,0x10,0x04 } },
-{  16, 0xadd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x00,0xfc,0x80,0x3d,0xd0 } },
-{  16, 0xade0, 0, {0x2f,0xf0,0x03,0xfc,0x00,0xfb,0x00,0x3d,0xc0,0x07,0x30,0x03,0xbc,0x00,0xef,0x04 } },
-{  16, 0xadf0, 0, {0x3f,0xe0,0x5e,0xb0,0x01,0xfc,0x00,0xff,0x00,0x1b,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
-{  16, 0xae00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xcb,0x01,0x3e,0xc9 } },
-{  16, 0xae10, 0, {0x0c,0xb0,0x17,0x20,0x84,0xeb,0x00,0xb2,0xc1,0x0d,0xb0,0x03,0x6c,0x00,0xc3,0x00 } },
-{  16, 0xae20, 0, {0x32,0x50,0x0f,0xb0,0x03,0x0c,0x40,0xc3,0x00,0x7e,0xc0,0x0c,0x30,0x03,0x10,0x04 } },
-{  16, 0xae30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0x8a,0x58,0x2e,0xe0 } },
-{  16, 0xae40, 0, {0x48,0xf0,0x02,0x2d,0x00,0xef,0x01,0x23,0xc0,0x08,0xf0,0x22,0x3c,0x04,0x8f,0x60 } },
-{  16, 0xae50, 0, {0x36,0x54,0x0b,0xf0,0x0a,0x3d,0x40,0x8f,0x00,0x2f,0xc0,0x08,0xf0,0x03,0x72,0x00 } },
-{  16, 0xae60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x40,0x00,0x89,0x80,0x2c,0x10 } },
-{  16, 0xae70, 0, {0x08,0xb0,0x02,0x49,0x00,0xa3,0xa0,0x24,0xc0,0x09,0x30,0x02,0x4c,0x00,0x83,0xc9 } },
-{  16, 0xae80, 0, {0x20,0x90,0x42,0x30,0x12,0x4d,0x00,0x83,0x00,0x6a,0xc0,0x09,0x30,0x02,0x38,0x00 } },
-{  16, 0xae90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x00,0x85,0x80,0x6d,0x62 } },
-{  16, 0xaea0, 0, {0x08,0x7e,0x02,0x56,0x40,0x27,0x80,0x25,0xe0,0x19,0x78,0x06,0x0e,0x00,0x83,0x80 } },
-{  16, 0xaeb0, 0, {0x61,0xa0,0x0b,0x78,0x02,0x4e,0x00,0x87,0x82,0x6d,0xe0,0x09,0x79,0x02,0x48,0x00 } },
-{  16, 0xaec0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x2c,0x02,0xc3,0x61,0x3c,0x88 } },
-{  16, 0xaed0, 0, {0x2c,0xba,0x12,0x49,0x10,0xe3,0x2c,0x36,0xc0,0x0d,0x30,0x53,0x4c,0x44,0xc3,0x00 } },
-{  16, 0xaee0, 0, {0x20,0x01,0x0f,0x31,0x03,0x4c,0x00,0xc3,0x01,0x3c,0xc0,0x2d,0xb1,0x03,0x12,0x02 } },
-{  16, 0xaef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0xff,0x00,0x3f,0x00 } },
-{  16, 0xaf00, 0, {0x4f,0xf1,0x09,0xb0,0x00,0xff,0x00,0x3b,0xc0,0x0e,0xf4,0x01,0xfd,0x24,0xff,0x40 } },
-{  16, 0xaf10, 0, {0xbf,0xc0,0x07,0xf0,0x03,0xbc,0x00,0x6f,0x10,0x3f,0xc4,0x1e,0xf1,0x83,0xd0,0x06 } },
-{  16, 0xaf20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xc4,0x00,0xe8,0x04,0x32,0x00 } },
-{  16, 0xaf30, 0, {0x0c,0xb6,0x03,0xe8,0x02,0xcb,0x00,0x36,0xca,0x0f,0xb5,0x03,0xad,0x00,0xfb,0x20 } },
-{  16, 0xaf40, 0, {0x3e,0x40,0x0f,0xb3,0x03,0xec,0x80,0xfb,0xa8,0x32,0xc6,0x8c,0xb6,0x03,0x2a,0x00 } },
-{  16, 0xaf50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x02,0xe6,0x00,0x20,0x00 } },
-{  16, 0xaf60, 0, {0x08,0x73,0x02,0xdc,0x00,0x87,0x70,0x2d,0xd0,0x0b,0xf0,0x02,0x1c,0x84,0xb7,0x20 } },
-{  16, 0xaf70, 0, {0x2d,0xc0,0x0b,0x70,0x82,0xdd,0x24,0xb7,0x40,0x34,0xc9,0x28,0x72,0x82,0x92,0x04 } },
-{  16, 0xaf80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0xbe,0x02,0xac,0x80,0xa1,0x20 } },
-{  16, 0xaf90, 0, {0x08,0x79,0x00,0xce,0x04,0x87,0x80,0x65,0xe0,0x0b,0x7a,0x02,0x9e,0x00,0xb7,0x90 } },
-{  16, 0xafa0, 0, {0x6d,0xa0,0x0b,0x78,0x02,0xde,0x00,0xb7,0x80,0x21,0xe0,0x08,0x78,0x02,0x30,0x00 } },
-{  16, 0xafb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xed,0x82,0xab,0xe0,0x20,0xe4 } },
-{  16, 0xafc0, 0, {0x08,0x30,0x02,0xee,0x04,0x83,0x00,0x2c,0xc1,0x1b,0x30,0x02,0x0c,0x08,0xb3,0x00 } },
-{  16, 0xafd0, 0, {0x64,0xf6,0x0b,0xb0,0x02,0xcc,0x04,0xb3,0x00,0x26,0xc0,0x08,0x30,0x02,0x92,0x04 } },
-{  16, 0xafe0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xbb,0x80,0xee,0x49,0x31,0xa0 } },
-{  16, 0xaff0, 0, {0x2c,0xa0,0x03,0xfa,0x00,0xca,0x02,0x36,0x80,0x0f,0xa0,0x03,0xa8,0x00,0xfa,0x02 } },
-{  16, 0xb000, 0, {0x3f,0x90,0x0f,0xa0,0x63,0xe8,0x00,0xfa,0x00,0x32,0x80,0x0c,0xa0,0x23,0x3a,0x04 } },
-{  16, 0xb010, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x0a,0xe8,0x00,0x3e,0x08 } },
-{  16, 0xb020, 0, {0x0f,0x80,0x03,0xe3,0x50,0xf0,0x00,0x3e,0x00,0x0f,0x80,0x13,0xe0,0x00,0xf8,0x00 } },
-{  16, 0xb030, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x01,0xf8,0x01,0x7e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xb040, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x40,0xc9,0xa1,0x32,0x40 } },
-{  16, 0xb050, 0, {0x20,0x11,0x01,0xa6,0x40,0xc9,0x84,0x36,0x40,0x0d,0x90,0x03,0x44,0x00,0x41,0x00 } },
-{  16, 0xb060, 0, {0x32,0x40,0x0f,0x90,0x0b,0x24,0x00,0xf9,0x00,0x3e,0x40,0x4c,0x10,0x03,0x02,0x04 } },
-{  16, 0xb070, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x82,0xa2,0x40 } },
-{  16, 0xb080, 0, {0x08,0x9c,0x02,0x25,0x00,0x89,0xc8,0x22,0x40,0x08,0x90,0x42,0x24,0x00,0x89,0x20 } },
-{  16, 0xb090, 0, {0x22,0x60,0x0b,0x90,0x02,0x24,0x10,0xb9,0x00,0x2e,0x40,0x08,0x90,0x03,0x60,0x00 } },
-{  16, 0xb0a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x89,0x04,0x22,0xca } },
-{  16, 0xb0b0, 0, {0x0a,0x90,0x0a,0x25,0x02,0x89,0x20,0x20,0x40,0x28,0x10,0x02,0x64,0x01,0xa9,0x00 } },
-{  16, 0xb0c0, 0, {0x22,0x4b,0x0b,0x90,0x02,0x24,0x01,0xb9,0x00,0x2e,0x41,0x28,0x90,0x02,0x06,0x00 } },
-{  16, 0xb0d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x90,0x81,0xa0,0x20,0x48 } },
-{  16, 0xb0e0, 0, {0x0a,0x32,0x02,0x04,0x80,0x81,0x00,0x20,0x44,0x08,0x11,0x02,0x04,0xd0,0xa1,0x20 } },
-{  16, 0xb0f0, 0, {0x20,0x40,0x0b,0x11,0x02,0x06,0x00,0xb1,0x31,0x2c,0x48,0x08,0x14,0x02,0x42,0x01 } },
-{  16, 0xb100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x42,0xc8,0x54,0x32,0x14 } },
-{  16, 0xb110, 0, {0x0e,0x85,0x03,0x21,0x44,0xc8,0x28,0xb2,0x1a,0x4c,0x86,0x93,0x61,0x14,0xe8,0x50 } },
-{  16, 0xb120, 0, {0x22,0x14,0x0f,0x86,0x83,0x21,0x40,0xf0,0x40,0x1e,0x14,0x0c,0x00,0x03,0x2e,0x03 } },
-{  16, 0xb130, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0x74,0x44,0xf5,0x10,0x3f,0x44 } },
-{  16, 0xb140, 0, {0x0d,0x91,0x03,0x74,0x40,0xf9,0x00,0x3e,0x48,0x0b,0x92,0x03,0xe4,0xc2,0xd9,0x10 } },
-{  16, 0xb150, 0, {0xbf,0x40,0x0f,0x92,0x03,0xe5,0x04,0xf9,0x30,0x3e,0x44,0x0f,0x94,0x43,0xe6,0x06 } },
-{  16, 0xb160, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x22,0xcd,0xa1,0x33,0x61 } },
-{  16, 0xb170, 0, {0x0c,0xd8,0xd3,0x34,0x10,0xcd,0xa8,0x3e,0x60,0x8e,0x9c,0x93,0xa7,0x08,0xcd,0x80 } },
-{  16, 0xb180, 0, {0x33,0x40,0x0e,0x9a,0xd3,0x36,0xa0,0xc9,0x80,0x32,0x60,0x0c,0x99,0x03,0x06,0x00 } },
-{  16, 0xb190, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe3,0x88,0x8a,0xa0,0x20,0x28 } },
-{  16, 0xb1a0, 0, {0x08,0x80,0x22,0x20,0x12,0x88,0x40,0x2c,0x28,0x08,0x8a,0x02,0x22,0x00,0x88,0x00 } },
-{  16, 0xb1b0, 0, {0x22,0x00,0x0b,0x8c,0x03,0x21,0x00,0x88,0xd0,0xa2,0x3e,0x28,0x8d,0x02,0x0e,0x04 } },
-{  16, 0xb1c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xce,0x20,0xa1,0x48,0x20,0x52 } },
-{  16, 0xb1d0, 0, {0x29,0x10,0x02,0x24,0x03,0x81,0x00,0x2c,0x52,0x0a,0x10,0x12,0x85,0x10,0x91,0x40 } },
-{  16, 0xb1e0, 0, {0xa4,0x40,0x0a,0x12,0x82,0x44,0x00,0x91,0x28,0x24,0x40,0x28,0x12,0x02,0x02,0x01 } },
-{  16, 0xb1f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0xa9,0x14,0x22,0x40 } },
-{  16, 0xb200, 0, {0x09,0x90,0x02,0xa4,0x01,0x89,0x04,0x2c,0x40,0x08,0x90,0x02,0x24,0x00,0x99,0x00 } },
-{  16, 0xb210, 0, {0x22,0x44,0x4b,0x10,0x42,0x24,0x14,0x99,0x00,0x26,0x40,0x08,0x10,0x02,0x06,0x04 } },
-{  16, 0xb220, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x40,0xe9,0x40,0xb2,0x78 } },
-{  16, 0xb230, 0, {0x0d,0x90,0x0b,0x24,0x22,0xc9,0x03,0x3e,0x41,0x0e,0x90,0x03,0xa4,0x02,0xd9,0x00 } },
-{  16, 0xb240, 0, {0x16,0x58,0x06,0x90,0x0b,0x64,0x02,0xd9,0x00,0x36,0x40,0x0c,0x90,0x0b,0x28,0x04 } },
-{  16, 0xb250, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x84,0x00,0xd9,0x80,0x3e,0x4a } },
-{  16, 0xb260, 0, {0x0e,0x90,0x03,0x64,0x20,0xf9,0x08,0x3e,0x41,0x0f,0x90,0x03,0xe4,0x00,0xe1,0x08 } },
-{  16, 0xb270, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc4,0x00,0xe1,0x00,0x38,0x40,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0xb280, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x09,0xf0,0x40,0xb0,0x10 } },
-{  16, 0xb290, 0, {0x4c,0x00,0x0b,0x20,0x00,0xf8,0x00,0x3a,0x00,0x1c,0x00,0x03,0xe0,0x00,0xc8,0x00 } },
-{  16, 0xb2a0, 0, {0x36,0x00,0x0c,0x80,0x03,0x20,0x00,0xc8,0x00,0x32,0x00,0x0f,0x80,0x03,0x0a,0x04 } },
-{  16, 0xb2b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x3e,0x88,0x23,0xa2 } },
-{  16, 0xb2c0, 0, {0x48,0xe0,0x00,0x19,0x80,0xbe,0x88,0x2e,0x80,0x0d,0xa0,0x42,0xe8,0x00,0x8e,0x00 } },
-{  16, 0xb2d0, 0, {0x23,0x90,0x08,0xa0,0x0a,0x3a,0x00,0xda,0x00,0x36,0x80,0x0b,0xa0,0x0a,0x0a,0x00 } },
-{  16, 0xb2e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb3,0x80,0x20,0xe0 } },
-{  16, 0xb2f0, 0, {0x28,0x30,0xc2,0x0f,0x10,0xb3,0x40,0x28,0xc0,0x0b,0x30,0x02,0xec,0x11,0x83,0x40 } },
-{  16, 0xb300, 0, {0x28,0xd2,0x0a,0x30,0x02,0x0c,0xc0,0x83,0x00,0x20,0xc0,0x0b,0x30,0x02,0x0a,0x00 } },
-{  16, 0xb310, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x00,0xb6,0x00,0x21,0xc0 } },
-{  16, 0xb320, 0, {0x08,0x20,0xc2,0x1c,0x10,0xb5,0x00,0x2d,0xc8,0x0a,0x72,0x02,0xdc,0x40,0x85,0x08 } },
-{  16, 0xb330, 0, {0x29,0xa2,0x1a,0x72,0x22,0x0c,0x00,0x93,0x30,0x05,0xc4,0x0b,0x32,0x22,0x28,0x00 } },
-{  16, 0xb340, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x16,0x00,0xb2,0x80,0x31,0x20 } },
-{  16, 0xb350, 0, {0x0c,0x58,0x03,0x1e,0x00,0xf7,0x80,0x39,0xf8,0x0b,0x7c,0x22,0xce,0x40,0xcf,0x80 } },
-{  16, 0xb360, 0, {0x9b,0x60,0x2e,0x3b,0x03,0x1a,0x00,0xc7,0xa8,0x11,0xe0,0x0f,0x78,0x03,0x2a,0x02 } },
-{  16, 0xb370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xa4,0x00,0xfa,0x00,0x3e,0xc0 } },
-{  16, 0xb380, 0, {0x0f,0x90,0x23,0xe8,0x00,0xfb,0x00,0x3e,0xd0,0x2d,0xb6,0x03,0xed,0x02,0xf9,0x00 } },
-{  16, 0xb390, 0, {0x32,0x40,0x0d,0xb0,0x07,0xec,0x00,0xfb,0x60,0x3e,0xc8,0x0f,0xb5,0x03,0xc2,0x06 } },
-{  16, 0xb3a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xff,0x80,0x33,0xa0 } },
-{  16, 0xb3b0, 0, {0x0c,0xf8,0x0b,0x32,0x40,0xce,0x81,0x37,0xf0,0x0c,0xbc,0x03,0xfe,0x00,0xff,0x84 } },
-{  16, 0xb3c0, 0, {0x33,0xe0,0x2c,0xf8,0x83,0xe6,0x02,0xcf,0x85,0x33,0xf0,0x0c,0xfc,0x03,0x00,0x14 } },
-{  16, 0xb3d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xbe,0x00,0x35,0xc6 } },
-{  16, 0xb3e0, 0, {0x28,0x30,0x02,0x30,0x40,0x87,0x00,0x23,0xc0,0x08,0x7a,0x02,0xdc,0x00,0xbe,0x00 } },
-{  16, 0xb3f0, 0, {0x23,0xc0,0x08,0x70,0x12,0xfe,0x00,0x87,0x00,0x21,0xc0,0x08,0xf0,0x02,0x2a,0x04 } },
-{  16, 0xb400, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x20,0xb6,0x00,0x20,0x80 } },
-{  16, 0xb410, 0, {0x08,0x31,0x02,0x5c,0x01,0x87,0x00,0x25,0xc0,0x08,0x72,0x02,0xdc,0x00,0xb6,0x00 } },
-{  16, 0xb420, 0, {0x21,0xd0,0x09,0x70,0x02,0xd4,0x08,0x93,0x00,0x20,0xc0,0x08,0x70,0x02,0x00,0x00 } },
-{  16, 0xb430, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xc4,0x00,0xb0,0xe0,0x24,0x60 } },
-{  16, 0xb440, 0, {0x08,0x20,0x06,0x48,0x01,0x80,0x00,0x20,0xc0,0x08,0x30,0x02,0xcc,0x04,0xb3,0x00 } },
-{  16, 0xb450, 0, {0x20,0x84,0x0b,0x30,0x02,0xe8,0x00,0x9b,0x00,0x20,0xc0,0x08,0x30,0x02,0x08,0x04 } },
-{  16, 0xb460, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xb9,0xe0,0x32,0x80 } },
-{  16, 0xb470, 0, {0x6c,0xb0,0x23,0x6f,0x00,0xc3,0x00,0x37,0xc1,0x3c,0xf0,0x03,0xfc,0x00,0xfa,0x00 } },
-{  16, 0xb480, 0, {0xb0,0xc0,0x09,0xf0,0x03,0xec,0x10,0xdf,0x00,0x73,0xc0,0x0c,0xf0,0x0b,0x2a,0x00 } },
-{  16, 0xb490, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x10,0xf8,0x00,0x3e,0x42 } },
-{  16, 0xb4a0, 0, {0x0f,0x24,0x03,0xa8,0x60,0xf8,0x00,0x3c,0xc1,0x0f,0xb0,0x03,0xec,0x00,0xf9,0x40 } },
-{  16, 0xb4b0, 0, {0x3e,0x80,0x04,0xb0,0x23,0xe1,0x00,0xeb,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0xe0,0x00 } },
-{  16, 0xb4c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xf4,0x00,0xee,0x00,0x3d,0x30 } },
-{  16, 0xb4d0, 0, {0x0c,0xc0,0x03,0x14,0x00,0xcc,0xa0,0xb3,0xc0,0x4c,0x70,0x03,0x5c,0x10,0xdf,0x00 } },
-{  16, 0xb4e0, 0, {0x3f,0x00,0x0c,0xf0,0x03,0xf8,0x00,0xcf,0x00,0x23,0xc0,0x0c,0xf0,0x03,0x00,0x40 } },
-{  16, 0xb4f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x64,0x00,0xba,0x81,0x2e,0x58 } },
-{  16, 0xb500, 0, {0x08,0x88,0x02,0x27,0x80,0x89,0x20,0x22,0xc0,0x28,0xb0,0x02,0x2c,0x00,0x88,0x83 } },
-{  16, 0xb510, 0, {0x2e,0x20,0x05,0xb0,0x62,0xe3,0x00,0x8b,0x00,0x2a,0xc0,0x08,0xb0,0x03,0x60,0x40 } },
-{  16, 0xb520, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x26,0x00,0xb9,0x81,0x2e,0x40 } },
-{  16, 0xb530, 0, {0x08,0x8c,0x06,0x26,0x00,0x88,0x00,0x22,0xc0,0x08,0xb0,0x16,0x6c,0x00,0x98,0x88 } },
-{  16, 0xb540, 0, {0x2e,0x20,0x08,0xb0,0x04,0xe3,0x01,0x0b,0x00,0x28,0xc0,0x08,0x30,0x02,0x20,0x00 } },
-{  16, 0xb550, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb0,0x00,0x2c,0xc0 } },
-{  16, 0xb560, 0, {0x28,0x00,0x0e,0x00,0x10,0x80,0x00,0x20,0xc0,0x08,0x32,0x02,0x0c,0x00,0x80,0x04 } },
-{  16, 0xb570, 0, {0x2e,0x20,0x09,0x30,0x02,0xc4,0x12,0x83,0x00,0x28,0xc0,0x08,0x30,0x02,0x42,0x01 } },
-{  16, 0xb580, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xfa,0x00,0x3e,0x00 } },
-{  16, 0xb590, 0, {0x2c,0x91,0x03,0x20,0x00,0x8a,0x00,0x33,0xc0,0x0c,0xf0,0x03,0x7c,0x00,0xd8,0x00 } },
-{  16, 0xb5a0, 0, {0x2e,0x40,0x0c,0xf0,0x03,0xe0,0x80,0xcf,0x00,0x3b,0xc0,0x0c,0xf0,0x03,0x00,0x03 } },
-{  16, 0xb5b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xfc,0x01,0x3f,0x40 } },
-{  16, 0xb5c0, 0, {0x0f,0xc0,0x13,0xf0,0x00,0xf4,0x00,0x3f,0xc1,0x0f,0xf4,0x23,0xfc,0x08,0xfc,0x00 } },
-{  16, 0xb5d0, 0, {0x3f,0x00,0x0f,0xf0,0x03,0xf0,0x40,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x03,0xe8,0x06 } },
-{  16, 0xb5e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x20,0xcd,0x10,0x39,0xc8 } },
-{  16, 0xb5f0, 0, {0x0d,0xc1,0x03,0x3c,0x80,0xef,0x90,0x23,0xd8,0x0f,0xf8,0x00,0xfe,0x00,0xcf,0x80 } },
-{  16, 0xb600, 0, {0x1f,0xd0,0x0f,0xf9,0x03,0xff,0x00,0xe7,0xc0,0x33,0xc4,0x0f,0xf0,0x03,0xb0,0x00 } },
-{  16, 0xb610, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x10,0xfe,0x02,0x89,0x40,0x23,0xf0 } },
-{  16, 0xb620, 0, {0x08,0x85,0x10,0x3c,0x00,0x8b,0x00,0xa3,0xdc,0x4b,0xb2,0x82,0xec,0x20,0x8b,0x00 } },
-{  16, 0xb630, 0, {0x26,0xc0,0x4b,0xb0,0x02,0xec,0x10,0xb9,0x04,0x2a,0xc9,0x0b,0xb5,0x80,0xf0,0x04 } },
-{  16, 0xb640, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xcc,0x00,0x81,0x64,0x28,0xc4 } },
-{  16, 0xb650, 0, {0x09,0xb2,0x0a,0x0c,0xf0,0xa3,0x20,0x20,0xc8,0x0b,0x32,0x02,0xec,0x02,0x83,0x08 } },
-{  16, 0xb660, 0, {0x2c,0xc8,0x09,0x32,0x02,0xcc,0x80,0xab,0xa0,0x20,0xc8,0x0b,0x32,0x00,0xb2,0x01 } },
-{  16, 0xb670, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x10,0x89,0x00,0x22,0xc0 } },
-{  16, 0xb680, 0, {0x08,0xb2,0x12,0x2c,0x02,0x0b,0x00,0x22,0xc0,0x0b,0xb8,0x02,0xec,0x00,0x8b,0x00 } },
-{  16, 0xb690, 0, {0x26,0xc0,0x4b,0xb0,0x46,0xec,0x00,0xb9,0x00,0x0a,0xc0,0x0b,0xb0,0x02,0xf0,0x04 } },
-{  16, 0xb6a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x15,0xec,0x10,0xc9,0xe0,0x3a,0xc0 } },
-{  16, 0xb6b0, 0, {0x0d,0x28,0x03,0x2c,0x00,0xeb,0x10,0x32,0xc0,0x0f,0x82,0x03,0xc4,0x00,0xcb,0x00 } },
-{  16, 0xb6c0, 0, {0x3e,0xc1,0x0f,0xb0,0x06,0xec,0x08,0xe9,0x00,0xb2,0xc0,0x0f,0xb0,0x13,0x90,0x04 } },
-{  16, 0xb6d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x9c,0x00,0xf5,0xa0,0x3f,0xc0 } },
-{  16, 0xb6e0, 0, {0x0f,0xe8,0x03,0xfc,0x08,0xff,0x00,0x3f,0xc0,0x8f,0xc0,0x03,0xfc,0x00,0xff,0x00 } },
-{  16, 0xb6f0, 0, {0x37,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x04,0x3e,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
-{  16, 0xb700, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x10,0xac,0x00,0xf9,0x40,0x34,0xc0 } },
-{  16, 0xb710, 0, {0x0d,0xb4,0x03,0x2c,0x00,0xdb,0x40,0x3e,0xc0,0x2c,0x80,0x03,0x64,0x08,0xfb,0x10 } },
-{  16, 0xb720, 0, {0x3e,0xc6,0x8f,0xb0,0x03,0xec,0x00,0xf9,0x80,0x32,0xc0,0x0c,0xb0,0x0b,0x14,0x04 } },
-{  16, 0xb730, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3e,0x20,0xe9,0xc8,0x37,0xd4 } },
-{  16, 0xb740, 0, {0x48,0xaa,0x22,0x1c,0x00,0x8b,0x00,0x6f,0xe0,0x08,0x85,0x82,0xed,0x40,0xbb,0x84 } },
-{  16, 0xb750, 0, {0x2f,0xc0,0x4b,0xb8,0x03,0xad,0x40,0xb3,0x00,0x23,0xd4,0x08,0xf7,0x02,0x32,0x00 } },
-{  16, 0xb760, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x4c,0x00,0xb1,0x64,0xa4,0xc0 } },
-{  16, 0xb770, 0, {0x09,0x20,0x0a,0x0c,0x04,0xb8,0x00,0x6c,0xc0,0x08,0x38,0x02,0xc8,0x40,0xb3,0x80 } },
-{  16, 0xb780, 0, {0x2c,0xd1,0x0b,0x30,0x02,0xcc,0x04,0xb3,0x00,0x28,0xc0,0x08,0x30,0x02,0x3a,0x00 } },
-{  16, 0xb790, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x01,0x1e,0x00,0xa5,0x80,0x25,0xe0 } },
-{  16, 0xb7a0, 0, {0x88,0x3a,0x12,0x1e,0x00,0xa6,0x90,0x2d,0xe2,0x08,0x79,0x02,0xda,0x00,0xb7,0x82 } },
-{  16, 0xb7b0, 0, {0x2d,0xe0,0x03,0x78,0x82,0x9e,0x00,0xbc,0xc1,0x29,0xe0,0x08,0x78,0x02,0x2c,0x10 } },
-{  16, 0xb7c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x08,0x0c,0x00,0xf3,0x00,0x34,0xc0 } },
-{  16, 0xb7d0, 0, {0x0d,0x3e,0x03,0x0c,0x00,0xf0,0x40,0x2e,0xc0,0x0c,0x30,0x43,0xc8,0x00,0xf3,0x00 } },
-{  16, 0xb7e0, 0, {0x3c,0xc0,0x07,0x30,0x03,0xcc,0x80,0xf2,0x00,0x38,0xc0,0x0c,0x30,0x03,0x12,0x02 } },
-{  16, 0xb7f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x19,0xbd,0x20,0xf7,0x00,0x3f,0xc2 } },
-{  16, 0xb800, 0, {0x0f,0xf1,0x0b,0xdc,0x20,0xde,0x04,0x3f,0xd2,0x07,0xf0,0x13,0xf8,0x40,0xff,0x00 } },
-{  16, 0xb810, 0, {0x3f,0xc0,0x07,0xf0,0x03,0xfc,0x00,0xfd,0x00,0x37,0xc0,0x0f,0x70,0x03,0xd0,0x06 } },
-{  16, 0xb820, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x05,0xcf,0x00,0xdc,0x00,0x3e,0xca } },
-{  16, 0xb830, 0, {0x0f,0xa0,0x00,0xac,0x92,0xc9,0x00,0x32,0xc0,0x0f,0xb0,0x11,0xa4,0x08,0xfb,0x00 } },
-{  16, 0xb840, 0, {0x2e,0xc0,0x4f,0xb0,0x23,0xec,0x00,0xf9,0x00,0x3e,0xc4,0x0f,0xb0,0x03,0xea,0x00 } },
-{  16, 0xb850, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x91,0x9c,0x00,0x84,0x00,0x01,0xc0 } },
-{  16, 0xb860, 0, {0x4b,0x70,0x22,0x1c,0xc0,0x87,0x00,0x21,0xc0,0x4b,0x70,0x02,0x1c,0x00,0xb7,0x01 } },
-{  16, 0xb870, 0, {0x25,0xd8,0x0b,0x70,0x22,0xdc,0x00,0xb6,0x00,0x2d,0xc0,0x0b,0x72,0x22,0xf2,0x04 } },
-{  16, 0xb880, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x9e,0x80,0x97,0x80,0xa9,0xe0 } },
-{  16, 0xb890, 0, {0x0b,0xf8,0x02,0xce,0x08,0x85,0x80,0x29,0xe8,0x0b,0xfc,0x02,0x17,0x00,0xb7,0x80 } },
-{  16, 0xb8a0, 0, {0x2d,0xe0,0x8b,0x78,0x02,0xde,0x00,0xb4,0xc0,0x2d,0xe8,0x0b,0x79,0x02,0xe0,0x00 } },
-{  16, 0xb8b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0x83,0x08,0xa0,0xc0 } },
-{  16, 0xb8c0, 0, {0x8b,0x3c,0x02,0x4c,0x00,0x83,0x00,0xa0,0xc0,0x1b,0x3c,0x0a,0x0f,0x29,0xb3,0x00 } },
-{  16, 0xb8d0, 0, {0x24,0xc0,0x0b,0x30,0x02,0xcc,0x00,0xb3,0x80,0x2c,0xc0,0x0b,0x30,0x02,0xd2,0x04 } },
-{  16, 0xb8e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xde,0x00,0x3a,0x80 } },
-{  16, 0xb8f0, 0, {0x0f,0xea,0x02,0xe8,0x00,0xce,0x00,0x3a,0x80,0x0f,0xe0,0x03,0x38,0x00,0xfa,0x00 } },
-{  16, 0xb900, 0, {0x3e,0x80,0x0f,0xa0,0x03,0xe8,0x00,0xfe,0x00,0x3e,0x80,0x0b,0xa0,0x03,0xfa,0x04 } },
-{  16, 0xb910, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x00,0xf8,0x04,0xba,0x01 } },
-{  16, 0xb920, 0, {0x0f,0x82,0x0b,0x80,0x04,0xf8,0x80,0x3e,0x00,0x0f,0x86,0x03,0x60,0x00,0xf8,0x00 } },
-{  16, 0xb930, 0, {0x36,0x00,0x0f,0x80,0x23,0xe1,0x00,0xf8,0x00,0x3e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xb940, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x01,0xf9,0x00,0x32,0x40 } },
-{  16, 0xb950, 0, {0x0f,0x90,0x03,0xe4,0x00,0x49,0x00,0x32,0x40,0x0b,0x90,0x03,0x24,0x00,0x49,0x00 } },
-{  16, 0xb960, 0, {0x3c,0x40,0x0d,0x90,0x03,0xe4,0x08,0xc9,0x00,0x3e,0x60,0x0c,0x90,0x03,0x02,0x04 } },
-{  16, 0xb970, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x40,0xa2,0x64 } },
-{  16, 0xb980, 0, {0x0b,0x18,0x02,0x25,0x00,0xd1,0x50,0x36,0x50,0x4e,0x90,0x0a,0x24,0x02,0x89,0x40 } },
-{  16, 0xb990, 0, {0x3a,0x51,0x08,0x94,0x02,0xe5,0x22,0x89,0x44,0x2e,0x60,0x28,0x90,0x0a,0x20,0x00 } },
-{  16, 0xb9a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x24,0x00,0xb1,0x08,0x22,0x40 } },
-{  16, 0xb9b0, 0, {0x4b,0x92,0x82,0xa5,0x00,0xa9,0x08,0x22,0x50,0x0a,0x10,0x02,0x0c,0x00,0xa9,0x40 } },
-{  16, 0xb9c0, 0, {0x6e,0x50,0x0b,0x94,0x02,0xc4,0x04,0x89,0x44,0x6c,0x48,0x88,0x10,0x02,0x46,0x00 } },
-{  16, 0xb9d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x00,0xb1,0x40,0xe0,0x40 } },
-{  16, 0xb9e0, 0, {0x1b,0x14,0x0a,0x04,0x00,0xb9,0x00,0x24,0x40,0x1a,0x10,0x22,0x04,0x00,0xa1,0x00 } },
-{  16, 0xb9f0, 0, {0x28,0x40,0x0a,0x10,0x12,0xc4,0x00,0x81,0x02,0x6c,0x40,0x08,0x12,0x02,0x42,0x01 } },
-{  16, 0xba00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x08,0xb0,0x00,0x32,0x00 } },
-{  16, 0xba10, 0, {0x4f,0x80,0x02,0xa1,0x50,0xe0,0x50,0x32,0x14,0x0e,0xa5,0x23,0x21,0x40,0xe8,0x50 } },
-{  16, 0xba20, 0, {0x3e,0x14,0x0f,0x85,0x03,0xe1,0x40,0xc8,0x50,0x1e,0x14,0x0c,0x85,0x43,0x6e,0x03 } },
-{  16, 0xba30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0x19,0xe5,0x00,0xfd,0x40,0x3e,0x50 } },
-{  16, 0xba40, 0, {0x0f,0x74,0x03,0xa5,0x00,0x5d,0x00,0x3e,0x50,0x0a,0x50,0x13,0xf4,0x00,0xd9,0x00 } },
-{  16, 0xba50, 0, {0x3a,0x50,0x0d,0x90,0x13,0xe4,0x00,0xff,0x00,0x3e,0x50,0x0f,0x91,0x03,0xa6,0x06 } },
-{  16, 0xba60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x90,0xbd,0xe8,0x23,0x6b } },
-{  16, 0xba70, 0, {0x0b,0xda,0x0b,0x36,0x80,0xc9,0x00,0x32,0x68,0x46,0x90,0x43,0xe4,0x00,0x49,0x00 } },
-{  16, 0xba80, 0, {0x32,0x68,0x0c,0x90,0x03,0x24,0x40,0xf9,0x00,0x32,0x60,0x0c,0x9c,0x03,0xc6,0x01 } },
-{  16, 0xba90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x10,0xe1,0x00,0xb8,0xe0,0xa2,0x11 } },
-{  16, 0xbaa0, 0, {0x0b,0x8e,0x0a,0x23,0x22,0x88,0x80,0x2a,0x31,0x28,0x88,0x02,0x62,0x00,0x88,0x80 } },
-{  16, 0xbab0, 0, {0xa2,0x30,0x28,0x88,0x8a,0x22,0x00,0xb8,0xa8,0xa2,0x39,0x08,0xca,0x02,0xce,0x04 } },
-{  16, 0xbac0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc5,0x08,0x21,0x00,0x00,0x40 } },
-{  16, 0xbad0, 0, {0x03,0x14,0x82,0x85,0x80,0xad,0x08,0x21,0x52,0x98,0x50,0x82,0x34,0x23,0x85,0x08 } },
-{  16, 0xbae0, 0, {0x21,0x52,0x08,0x50,0x06,0x54,0x00,0xb5,0x20,0x21,0x5a,0x09,0x54,0x02,0xd2,0x01 } },
-{  16, 0xbaf0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0xb9,0x61,0x22,0x40 } },
-{  16, 0xbb00, 0, {0x0b,0x90,0x06,0x04,0x00,0xad,0x00,0x69,0x40,0x08,0xd0,0x02,0x74,0x00,0x85,0x00 } },
-{  16, 0xbb10, 0, {0x01,0x40,0x00,0x70,0x06,0x74,0x04,0xb5,0x00,0x23,0x40,0x09,0xd0,0x02,0xc6,0x04 } },
-{  16, 0xbb20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x14,0xa4,0x00,0xe9,0x00,0x32,0x40 } },
-{  16, 0xbb30, 0, {0x4f,0x95,0x0b,0xa4,0x00,0xe9,0x00,0x32,0x40,0x8c,0x90,0x03,0x24,0x00,0xc9,0x00 } },
-{  16, 0xbb40, 0, {0x32,0x40,0x0c,0x90,0x03,0x64,0x08,0xf9,0x00,0x32,0x40,0x3d,0x90,0x03,0xe8,0x04 } },
-{  16, 0xbb50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x01,0xa4,0x08,0xf9,0x00,0x3e,0x40 } },
-{  16, 0xbb60, 0, {0x4f,0x90,0x8b,0xe4,0x04,0xd9,0x01,0x3e,0x40,0x0d,0x90,0x03,0x64,0x00,0xd9,0x01 } },
-{  16, 0xbb70, 0, {0x3e,0x40,0x0f,0x90,0x03,0xa4,0x00,0xf9,0x00,0x3c,0x40,0x0e,0x90,0x03,0xda,0x00 } },
-{  16, 0xbb80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x40,0x36,0x20 } },
-{  16, 0xbb90, 0, {0x17,0x84,0x03,0x20,0x21,0xc8,0x00,0x7e,0x02,0x2c,0x80,0x43,0x20,0x00,0xe8,0x02 } },
-{  16, 0xbba0, 0, {0x3e,0x01,0x0f,0x80,0x03,0xe0,0x00,0xc8,0x40,0x1e,0x00,0x0f,0x80,0x03,0xca,0x04 } },
-{  16, 0xbbb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x2a,0x88,0xb6,0x02,0x23,0xa0 } },
-{  16, 0xbbc0, 0, {0x0b,0xec,0x42,0x2b,0x00,0xd2,0x80,0x6e,0xb1,0x08,0xa0,0x22,0x08,0x00,0xea,0x04 } },
-{  16, 0xbbd0, 0, {0x3a,0x80,0x9f,0xa0,0x03,0xa8,0x00,0x8a,0x04,0x2e,0x80,0x0b,0xa8,0x02,0xca,0x00 } },
-{  16, 0xbbe0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb2,0x00,0xa4,0xe1 } },
-{  16, 0xbbf0, 0, {0x8b,0xb4,0x32,0x47,0x45,0x83,0x90,0x2c,0xf4,0x4b,0x38,0x12,0x0e,0x44,0xa3,0x01 } },
-{  16, 0xbc00, 0, {0x2c,0xc0,0x4b,0x30,0x02,0xce,0x00,0x93,0x00,0x6c,0xc0,0x0b,0x38,0x02,0xca,0x00 } },
-{  16, 0xbc10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x00,0xb7,0x44,0x21,0xc2 } },
-{  16, 0xbc20, 0, {0x0b,0x54,0x02,0x54,0x05,0x87,0x00,0x2c,0x40,0x9b,0x6c,0x02,0x18,0x10,0xa7,0x04 } },
-{  16, 0xbc30, 0, {0x29,0xc0,0x0a,0x70,0x02,0x9b,0x00,0x97,0x04,0x0d,0x80,0x0b,0x60,0x82,0xe8,0x00 } },
-{  16, 0xbc40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf3,0x80,0x35,0xe0 } },
-{  16, 0xbc50, 0, {0x0b,0x38,0x02,0x52,0x10,0x84,0x80,0x2d,0xa0,0x0f,0xf8,0x0b,0x1e,0x00,0xe6,0x80 } },
-{  16, 0xbc60, 0, {0x1d,0xa0,0x0b,0x68,0x03,0xfe,0x02,0xd6,0x80,0x3d,0xe0,0x0f,0x78,0x03,0xea,0x02 } },
-{  16, 0xbc70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1d,0xac,0x00,0xfb,0x00,0x3e,0xc1 } },
-{  16, 0xbc80, 0, {0x8b,0x90,0x0b,0x80,0x0a,0xb8,0x01,0x2e,0x00,0x0c,0xb0,0x03,0xe8,0x00,0xfa,0x00 } },
-{  16, 0xbc90, 0, {0x3e,0xc0,0x0f,0xa0,0x43,0xec,0x00,0xeb,0x00,0x3e,0x80,0x0f,0xa6,0x23,0xc2,0x02 } },
-{  16, 0xbca0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xfe,0x80,0x33,0x20 } },
-{  16, 0xbcb0, 0, {0x4e,0xc9,0x12,0xf6,0x50,0xef,0x90,0x3f,0xe0,0x0c,0x19,0x00,0xb6,0x42,0xcf,0x21 } },
-{  16, 0xbcc0, 0, {0x3f,0xe0,0x0e,0xf9,0x02,0xe6,0xc0,0xff,0x80,0x3f,0xe0,0x4c,0xdc,0x03,0x40,0x00 } },
-{  16, 0xbcd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x11,0x94,0x00,0xb7,0x00,0x81,0x40 } },
-{  16, 0xbce0, 0, {0x08,0x03,0x02,0x14,0xc4,0x87,0x01,0x2d,0xc8,0x08,0x6a,0x12,0x38,0x40,0x87,0x02 } },
-{  16, 0xbcf0, 0, {0x2d,0xc0,0x08,0x71,0x12,0xd2,0x80,0xb7,0x00,0x2d,0x80,0x08,0x60,0x02,0x2a,0x04 } },
-{  16, 0xbd00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x10,0x21,0x80 } },
-{  16, 0xbd10, 0, {0x08,0xf4,0x12,0x94,0x04,0xa6,0x00,0x2c,0xc0,0x18,0xd2,0x02,0x14,0x48,0x86,0x10 } },
-{  16, 0xbd20, 0, {0x2d,0x80,0x0a,0x61,0x32,0xd4,0x00,0xb6,0x18,0x2d,0xc4,0x08,0x58,0x02,0x00,0x10 } },
-{  16, 0xbd30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xc4,0x00,0xb3,0x00,0x20,0xc0 } },
-{  16, 0xbd40, 0, {0x40,0xb0,0x22,0x04,0x00,0x82,0x81,0x0c,0xc0,0x08,0x30,0x0a,0x0a,0x00,0x8a,0x00 } },
-{  16, 0xbd50, 0, {0x2e,0xc0,0x08,0xa0,0x02,0xc4,0x00,0xbb,0x00,0x2e,0x80,0x08,0x20,0x02,0x08,0x04 } },
-{  16, 0xbd60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xfb,0x00,0xa0,0xc0 } },
-{  16, 0xbd70, 0, {0x24,0x94,0x23,0xac,0x10,0xeb,0xa0,0x0e,0xc0,0x0c,0xb0,0x02,0x2e,0x20,0xc9,0x00 } },
-{  16, 0xbd80, 0, {0x2e,0x40,0x0e,0x90,0x03,0xec,0x00,0xf9,0x80,0x3e,0x40,0x6c,0xa0,0x0b,0x2a,0x04 } },
-{  16, 0xbd90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xcc,0x00,0xfb,0x00,0x3e,0xc0 } },
-{  16, 0xbda0, 0, {0x89,0x90,0x03,0x2c,0x00,0xfb,0x02,0x3e,0x40,0x4f,0xa0,0x03,0x6d,0x01,0xfb,0x41 } },
-{  16, 0xbdb0, 0, {0x3e,0xc0,0x8f,0xb4,0x03,0xe8,0x00,0xfb,0x20,0x3e,0x50,0x0f,0xa4,0x03,0xe0,0x00 } },
-{  16, 0xbdc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xc3,0x20,0xb2,0xc0 } },
-{  16, 0xbdd0, 0, {0x0d,0xd0,0x03,0x38,0x00,0xcd,0x00,0x3f,0x80,0x0d,0xf0,0x03,0xfc,0x00,0xfd,0x02 } },
-{  16, 0xbde0, 0, {0x36,0x00,0x0c,0xd0,0x03,0x3f,0x08,0xfc,0x04,0x12,0xc0,0x0c,0xa0,0x03,0xc0,0x44 } },
-{  16, 0xbdf0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x6c,0x02,0x8b,0xc8,0x22,0xc0 } },
-{  16, 0xbe00, 0, {0x08,0x98,0x0a,0x2a,0x40,0x89,0x20,0x2e,0x01,0x8e,0xb0,0x12,0xec,0x80,0xbb,0xf0 } },
-{  16, 0xbe10, 0, {0x22,0xe5,0x08,0xbd,0x02,0x2e,0x00,0xbb,0x90,0x22,0xed,0x08,0xa2,0x02,0xe0,0x00 } },
-{  16, 0xbe20, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x01,0x22,0x00 } },
-{  16, 0xbe30, 0, {0x49,0xa8,0x1e,0x04,0x00,0x8b,0x01,0x2e,0xc0,0x49,0x90,0x02,0xe4,0x00,0xb9,0x00 } },
-{  16, 0xbe40, 0, {0x22,0x40,0x0a,0x90,0x02,0x2c,0x00,0xb9,0x00,0x2a,0x40,0x08,0x80,0x02,0xe0,0x00 } },
-{  16, 0xbe50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x81,0x00,0x20,0x40 } },
-{  16, 0xbe60, 0, {0x08,0x20,0x02,0x04,0x00,0x83,0x00,0x2c,0xc0,0x0a,0x20,0x42,0xcc,0x00,0xb3,0x00 } },
-{  16, 0xbe70, 0, {0x20,0xc0,0x02,0x30,0x02,0x08,0x84,0xb3,0x04,0x08,0x40,0x08,0x20,0x02,0xc2,0x11 } },
-{  16, 0xbe80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0x8b,0x00,0xb2,0x80 } },
-{  16, 0xbe90, 0, {0x0d,0xb1,0x03,0x24,0x02,0xcb,0x01,0x3e,0xc0,0x4d,0x90,0x43,0xe4,0x00,0xf9,0x00 } },
-{  16, 0xbea0, 0, {0xb2,0x00,0x2e,0x90,0x0b,0x2c,0x80,0xf8,0x00,0xba,0xc0,0x2c,0x80,0x03,0xc0,0x03 } },
-{  16, 0xbeb0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf4,0x00,0x7d,0x00,0x3f,0xc0 } },
-{  16, 0xbec0, 0, {0x0f,0x72,0x03,0xd4,0x00,0xff,0x00,0x3f,0xc0,0x0e,0xf1,0x47,0xfc,0x00,0xff,0x00 } },
-{  16, 0xbed0, 0, {0x3b,0xc0,0x0d,0xf0,0x13,0xfc,0x50,0xff,0x00,0x37,0xc0,0x0f,0xe0,0x03,0xe8,0x06 } },
-{  16, 0xbee0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0xc4,0xcc,0x33,0x3f,0x04 } },
-{  16, 0xbef0, 0, {0x2c,0xf6,0x03,0x38,0x60,0xcc,0x90,0xb3,0x20,0x0f,0xf1,0x23,0xf0,0x60,0xff,0x01 } },
-{  16, 0xbf00, 0, {0x23,0xc8,0x0c,0xf2,0x8a,0x3c,0x81,0xdf,0x30,0x3f,0x64,0x0c,0xd8,0x03,0x30,0x04 } },
-{  16, 0xbf10, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe0,0xc2,0x8a,0x30,0x2e,0x18 } },
-{  16, 0xbf20, 0, {0x08,0xf5,0x30,0xa5,0x94,0x58,0x22,0x22,0x21,0x4b,0xf3,0x02,0xe1,0x00,0x9f,0x70 } },
-{  16, 0xbf30, 0, {0x2b,0xe4,0x0a,0xf4,0x12,0x1d,0x40,0xaf,0x72,0x2c,0x49,0x2f,0x30,0x82,0xa0,0x06 } },
-{  16, 0xbf40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x80,0x80,0xa0,0x2c,0x98 } },
-{  16, 0xbf50, 0, {0x08,0x32,0x22,0x08,0x00,0x82,0x00,0x28,0x00,0x03,0x32,0x02,0xc0,0x84,0xb3,0x0c } },
-{  16, 0xbf60, 0, {0x20,0xc0,0x58,0x32,0x92,0x8c,0x30,0xa3,0x20,0x2e,0xc0,0x48,0x12,0x42,0x62,0x01 } },
-{  16, 0xbf70, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa8,0x00,0x8b,0x00,0x2e,0x20 } },
-{  16, 0xbf80, 0, {0x08,0xb0,0x0a,0x20,0x01,0x98,0x00,0x2a,0x22,0x0b,0xb0,0x02,0xe6,0x00,0x9b,0x00 } },
-{  16, 0xbf90, 0, {0x22,0xc0,0x0a,0xb0,0x12,0xac,0x04,0xab,0x00,0x2e,0xc0,0x03,0xb0,0x02,0xf0,0x00 } },
-{  16, 0xbfa0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xe5,0x00,0xc8,0x00,0x3e,0xb0 } },
-{  16, 0xbfb0, 0, {0x0c,0xb0,0x03,0x29,0x00,0xc8,0x00,0x3a,0x20,0x4f,0xb0,0x03,0xe2,0x20,0xfb,0x01 } },
-{  16, 0xbfc0, 0, {0xb0,0xc0,0x0c,0xb0,0x03,0x2c,0x00,0xfb,0x02,0x3c,0x41,0x0c,0x90,0x43,0x48,0x04 } },
-{  16, 0xbfd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xa2,0x80,0xfe,0x40,0x3e,0x00 } },
-{  16, 0xbfe0, 0, {0x0f,0xf0,0x63,0xec,0x00,0xbf,0xc4,0x17,0x42,0x0f,0xf0,0x03,0xec,0x00,0xff,0x00 } },
-{  16, 0xbff0, 0, {0x1f,0xc1,0x0f,0xb0,0x03,0x5c,0x00,0xfb,0x00,0x3f,0x40,0x4f,0xf0,0x00,0xb8,0x00 } },
-{  16, 0xc000, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa5,0x02,0xc8,0x00,0x3e,0x90 } },
-{  16, 0xc010, 0, {0x2c,0xb0,0x0b,0x01,0x06,0xcb,0x01,0x3e,0x50,0x5f,0xb0,0x13,0x21,0x10,0xcb,0x00 } },
-{  16, 0xc020, 0, {0x7e,0xc0,0x0c,0xb0,0x0b,0x2c,0x00,0xcb,0x00,0x32,0xc0,0x0c,0x90,0x03,0x10,0x04 } },
-{  16, 0xc030, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x28,0x01,0x8b,0xd0,0x2c,0x34 } },
-{  16, 0xc040, 0, {0x48,0xff,0x02,0x30,0x00,0xaa,0x04,0x2e,0x69,0x0f,0xf0,0x03,0x68,0x10,0xdf,0x00 } },
-{  16, 0xc050, 0, {0x2f,0xd4,0x0d,0xf0,0x02,0x3e,0x00,0x5f,0x04,0xb6,0xc0,0x08,0xb0,0x03,0x72,0x00 } },
-{  16, 0xc060, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x69,0x90,0x81,0x80,0x2c,0x00 } },
-{  16, 0xc070, 0, {0x48,0xb8,0x02,0x08,0x09,0x99,0x00,0x4c,0xb0,0x0b,0x30,0x02,0x0c,0x00,0x8b,0x00 } },
-{  16, 0xc080, 0, {0x2c,0xc0,0x09,0xb0,0x40,0x0c,0x40,0x83,0x00,0x00,0x40,0x0a,0x90,0x02,0x30,0x00 } },
-{  16, 0xc090, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x00,0x84,0x88,0x2d,0xe4 } },
-{  16, 0xc0a0, 0, {0x48,0x39,0x02,0x16,0x00,0xb4,0x80,0x2d,0xe0,0x0a,0x7b,0x06,0x5e,0x00,0x97,0x80 } },
-{  16, 0xc0b0, 0, {0x2d,0xe2,0x09,0x78,0x02,0x1e,0x90,0x97,0x80,0x25,0x64,0x8a,0x78,0x02,0x48,0x00 } },
-{  16, 0xc0c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0d,0x00,0x81,0x10,0x2c,0x96 } },
-{  16, 0xc0d0, 0, {0x08,0x31,0x23,0x0c,0x00,0x90,0x20,0x3c,0xc4,0x1b,0xb8,0x02,0x08,0x40,0xc3,0x00 } },
-{  16, 0xc0e0, 0, {0x2c,0xc4,0x0d,0x30,0x03,0x0e,0x40,0xc3,0x10,0x30,0xc0,0x4e,0x10,0x07,0x1a,0x12 } },
-{  16, 0xc0f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0x7d,0x05,0x3f,0xc5 } },
-{  16, 0xc100, 0, {0x0f,0xb1,0x0b,0xf4,0x00,0xef,0x00,0x1f,0x45,0x0f,0xf0,0x43,0xfc,0x01,0xff,0x40 } },
-{  16, 0xc110, 0, {0x3d,0xc4,0x1f,0xf0,0x06,0xfc,0x10,0xff,0x00,0x3b,0xc1,0x2d,0xf1,0x03,0xd0,0x06 } },
-{  16, 0xc120, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x04,0xcb,0x04,0x3e,0xa0 } },
-{  16, 0xc130, 0, {0x44,0xb6,0x03,0x28,0x04,0xcb,0x80,0x32,0x80,0x0f,0xb3,0x93,0x60,0x08,0xfb,0x20 } },
-{  16, 0xc140, 0, {0x3e,0xd2,0x1f,0xb3,0x03,0x2d,0x80,0xfb,0x61,0x7e,0x40,0x8c,0x98,0x03,0x2a,0x00 } },
-{  16, 0xc150, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x84,0x0c,0x86,0x05,0x2d,0xc0 } },
-{  16, 0xc160, 0, {0x08,0xf4,0x82,0x8c,0x90,0x85,0x00,0xa1,0xc0,0x0b,0xf0,0x02,0x5c,0x00,0x37,0x00 } },
-{  16, 0xc170, 0, {0x2d,0xd0,0x0b,0x71,0x02,0x1c,0xc8,0xb7,0x48,0x2d,0x40,0x0a,0x70,0x02,0x12,0x04 } },
-{  16, 0xc180, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0x87,0x80,0x2d,0xa1 } },
-{  16, 0xc190, 0, {0x60,0x78,0x4a,0x16,0xd0,0xa7,0x80,0x29,0xe0,0x0b,0x78,0x52,0x96,0x01,0xb7,0x90 } },
-{  16, 0xc1a0, 0, {0x2d,0xe8,0x0b,0x7a,0x22,0x5e,0x40,0xb7,0xa0,0x2f,0xe1,0x48,0x50,0x22,0x30,0x00 } },
-{  16, 0xc1b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x10,0x83,0x84,0x2c,0xc0 } },
-{  16, 0xc1c0, 0, {0x08,0x30,0x02,0xa4,0x10,0x83,0xcb,0x28,0xe0,0x0b,0x30,0x2a,0x4f,0x40,0x93,0x00 } },
-{  16, 0xc1d0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0x4c,0x10,0xb3,0x02,0x2c,0xc0,0xaa,0x30,0x02,0x12,0x04 } },
-{  16, 0xc1e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x00,0xce,0xa0,0x3f,0x80 } },
-{  16, 0xc1f0, 0, {0x4c,0xa0,0x2b,0x3a,0x00,0xce,0x40,0x3b,0xb8,0x0f,0xa0,0x03,0xb9,0x00,0xba,0x00 } },
-{  16, 0xc200, 0, {0x3e,0x80,0x0f,0xa0,0x03,0x68,0x00,0xfa,0x00,0x7e,0x80,0x1c,0xa0,0x0b,0x3a,0x04 } },
-{  16, 0xc210, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x02,0xf8,0x00,0x3e,0x04 } },
-{  16, 0xc220, 0, {0x8f,0x00,0x03,0xe0,0x4a,0xf8,0x10,0x26,0x18,0x0f,0x80,0x03,0xa0,0x80,0xf8,0x02 } },
-{  16, 0xc230, 0, {0x3e,0x00,0x8f,0x00,0x0b,0xa0,0x00,0xf8,0x02,0x3e,0x00,0x0f,0x80,0x13,0xd2,0x00 } },
-{  16, 0xc240, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x20,0xc9,0x00,0x32,0x40 } },
-{  16, 0xc250, 0, {0x4d,0x99,0x03,0x24,0x00,0xc9,0x02,0x3e,0x68,0x0f,0x90,0x02,0x24,0x00,0xe9,0x00 } },
-{  16, 0xc260, 0, {0x30,0x40,0x8c,0x90,0x03,0x04,0x40,0xc9,0x00,0x3e,0x40,0x0c,0x90,0x03,0x02,0x04 } },
-{  16, 0xc270, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x20,0x89,0x06,0x22,0x50 } },
-{  16, 0xc280, 0, {0x8b,0x9c,0xc2,0x24,0x00,0xd9,0x01,0x2e,0x40,0x0b,0x90,0x42,0x24,0x08,0xb9,0x01 } },
-{  16, 0xc290, 0, {0x22,0x46,0x0d,0x90,0x0a,0x26,0x02,0x89,0x00,0x2c,0x40,0x0a,0x10,0x02,0x20,0x00 } },
-{  16, 0xc2a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x06,0x00,0x91,0x40,0x42,0x70 } },
-{  16, 0xc2b0, 0, {0x0b,0x90,0x12,0x2c,0x02,0x8b,0x00,0x2e,0x40,0x0b,0x10,0x22,0xe4,0x10,0xb1,0x00 } },
-{  16, 0xc2c0, 0, {0xa2,0x40,0x48,0x90,0x12,0x24,0x08,0x99,0x02,0x2e,0x40,0x08,0x90,0x02,0x06,0x00 } },
-{  16, 0xc2d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x92,0x91,0x20,0xe0,0x48 } },
-{  16, 0xc2e0, 0, {0x0b,0x12,0x02,0x04,0x02,0x91,0x10,0x2c,0xc0,0x0b,0x10,0x06,0x84,0xc0,0xb1,0x10 } },
-{  16, 0xc2f0, 0, {0x20,0x48,0x89,0x11,0x02,0x05,0x80,0x91,0x40,0x2e,0x44,0x2a,0x94,0x02,0x02,0x01 } },
-{  16, 0xc300, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xd8,0x50,0x30,0x14 } },
-{  16, 0xc310, 0, {0x0f,0x85,0x0b,0x21,0xe0,0x80,0x40,0x3e,0x00,0x0f,0x87,0x8b,0xe1,0x0c,0xf8,0x6c } },
-{  16, 0xc320, 0, {0x32,0x00,0x84,0x06,0x83,0x20,0x04,0xd8,0x28,0x3e,0x10,0x0c,0x00,0x03,0x2e,0x03 } },
-{  16, 0xc330, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xad,0x10,0x3f,0x45 } },
-{  16, 0xc340, 0, {0x0f,0x91,0x03,0xfc,0x18,0x7d,0x20,0x1f,0x41,0x0f,0x90,0x03,0x74,0xc0,0xf9,0x21 } },
-{  16, 0xc350, 0, {0x3e,0x44,0x0f,0x92,0x01,0xe4,0x40,0xe9,0x00,0x3d,0x48,0x4f,0xd0,0x03,0xe6,0x06 } },
-{  16, 0xc360, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf7,0x80,0xfd,0xe0,0x33,0x70 } },
-{  16, 0xc370, 0, {0x0c,0xda,0x03,0x26,0x20,0xc9,0x40,0x31,0x40,0x0e,0x9a,0x03,0x24,0x00,0xf9,0x80 } },
-{  16, 0xc380, 0, {0x3b,0x60,0x0f,0x9c,0x83,0x36,0xa0,0xf9,0xa1,0xb0,0x40,0x0f,0x91,0x03,0xc6,0x00 } },
-{  16, 0xc390, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe2,0x90,0xb8,0xa0,0x22,0x28 } },
-{  16, 0xc3a0, 0, {0x28,0x88,0x0a,0x22,0x02,0x88,0xa0,0x22,0x00,0x08,0x88,0x02,0xc2,0x80,0xb8,0x88 } },
-{  16, 0xc3b0, 0, {0x22,0x04,0x0b,0x8e,0x03,0x22,0x80,0xb8,0xd0,0x2a,0x20,0x0b,0x88,0x02,0xce,0x04 } },
-{  16, 0xc3c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc5,0x80,0xb1,0x61,0x00,0x58 } },
-{  16, 0xc3d0, 0, {0x48,0x16,0x8a,0x04,0xa0,0x89,0x01,0x22,0x40,0x1a,0x14,0x88,0x04,0x20,0xb1,0x40 } },
-{  16, 0xc3e0, 0, {0x28,0x40,0x0b,0x10,0x0a,0x04,0x20,0xb1,0x2c,0x20,0x4a,0x0b,0x12,0x02,0xc2,0x01 } },
-{  16, 0xc3f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa5,0x90,0xbb,0x40,0x20,0x40 } },
-{  16, 0xc400, 0, {0x08,0x90,0x02,0x24,0x40,0x89,0x42,0x62,0x58,0x08,0x10,0x02,0xe5,0x00,0xb9,0x03 } },
-{  16, 0xc410, 0, {0x22,0xc0,0x0b,0x90,0x02,0xa4,0x14,0x31,0x00,0x2a,0x44,0x0b,0x90,0x02,0xc6,0x04 } },
-{  16, 0xc420, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0xa5,0x00,0xf9,0x01,0x32,0x40 } },
-{  16, 0xc430, 0, {0x8c,0x90,0x03,0x27,0x00,0xc1,0x94,0x30,0x40,0x0e,0x90,0x03,0x24,0x00,0xf9,0x00 } },
-{  16, 0xc440, 0, {0x3a,0x40,0x0f,0x90,0x03,0x24,0x00,0xf9,0x00,0x32,0x60,0x07,0x90,0x27,0xe8,0x05 } },
-{  16, 0xc450, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa4,0x18,0xf9,0x00,0xbe,0x44 } },
-{  16, 0xc460, 0, {0x0f,0x90,0x03,0xc4,0x00,0xf9,0x00,0xbe,0x61,0x8f,0x90,0x03,0xa4,0x00,0xf1,0x00 } },
-{  16, 0xc470, 0, {0x1e,0x40,0x0f,0x10,0x03,0x24,0x08,0xf9,0x00,0x7e,0x40,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0xc480, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x81,0xf8,0x00,0x32,0x04 } },
-{  16, 0xc490, 0, {0x0c,0x00,0xd3,0x21,0x00,0xd8,0x04,0x3a,0x14,0x9c,0x80,0x03,0x21,0x01,0xc8,0x00 } },
-{  16, 0xc4a0, 0, {0x36,0x00,0x0c,0x80,0x13,0x20,0x10,0xc8,0x00,0x32,0x00,0x2c,0x80,0x03,0xca,0x04 } },
-{  16, 0xc4b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x04,0x3a,0x00,0xbe,0x84,0x23,0x85 } },
-{  16, 0xc4c0, 0, {0x08,0xec,0x83,0x68,0x04,0x8a,0x00,0x2f,0x90,0x4d,0xa0,0x02,0x28,0x01,0xda,0x00 } },
-{  16, 0xc4d0, 0, {0x23,0xb0,0x0a,0xa0,0x02,0x2a,0x08,0xda,0x01,0x22,0x80,0x0f,0xa0,0x02,0xca,0x00 } },
-{  16, 0xc4e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xbb,0xf0,0x20,0xc0 } },
-{  16, 0xc4f0, 0, {0x08,0x3c,0x0a,0x0c,0x00,0x93,0x01,0x28,0xc8,0x89,0x30,0x06,0x4c,0x00,0x83,0x02 } },
-{  16, 0xc500, 0, {0x2c,0xf6,0x08,0x30,0x02,0x04,0x00,0xa3,0x00,0x20,0xc0,0x0a,0x30,0x02,0xca,0x00 } },
-{  16, 0xc510, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1d,0x11,0xb3,0x00,0xa0,0xc0 } },
-{  16, 0xc520, 0, {0x08,0x50,0x02,0x5c,0x10,0x87,0x01,0x6d,0x81,0x49,0x32,0x52,0x1e,0xc3,0x87,0x00 } },
-{  16, 0xc530, 0, {0x28,0xe0,0x0a,0x32,0x26,0x1f,0x00,0x37,0x00,0x23,0xe0,0x0b,0x72,0x02,0xc8,0x00 } },
-{  16, 0xc540, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x08,0x12,0x00,0xb7,0x82,0x31,0x20 } },
-{  16, 0xc550, 0, {0x08,0x08,0x37,0x0f,0x08,0xd7,0xe0,0x39,0x60,0x19,0x7a,0x0b,0x5e,0x0c,0x83,0xb2 } },
-{  16, 0xc560, 0, {0x7d,0xe0,0x0c,0x7a,0x0b,0x3e,0x02,0xaf,0xa0,0xb1,0xe0,0x0e,0x7a,0x03,0xca,0x02 } },
-{  16, 0xc570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xa0,0x10,0xfb,0x00,0x3e,0xc0 } },
-{  16, 0xc580, 0, {0x6f,0xb0,0x43,0xec,0x11,0xfb,0x00,0x3e,0x40,0x0f,0xb5,0x03,0xec,0x20,0xfb,0x50 } },
-{  16, 0xc590, 0, {0x36,0x00,0x0f,0xb5,0x43,0xe5,0xa1,0xdb,0x78,0x3e,0xc0,0x0f,0xb4,0x03,0xc2,0x06 } },
-{  16, 0xc5a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x00,0xff,0xa0,0x3f,0xa0 } },
-{  16, 0xc5b0, 0, {0x0d,0xc9,0x13,0x3e,0x00,0xcf,0xd0,0x3d,0xe8,0x02,0xff,0x13,0x3e,0x00,0xcf,0x82 } },
-{  16, 0xc5c0, 0, {0x3f,0x60,0x0c,0xfc,0x23,0x3e,0x10,0xef,0x80,0x33,0xf2,0x0c,0xfc,0x83,0x10,0x00 } },
-{  16, 0xc5d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x40,0xb5,0x01,0x2d,0xd0 } },
-{  16, 0xc5e0, 0, {0x08,0x58,0x02,0x1c,0x40,0x57,0x10,0x2d,0x5a,0x28,0x31,0x02,0xbc,0x01,0x97,0x10 } },
-{  16, 0xc5f0, 0, {0x2d,0x00,0x0a,0x70,0x02,0x84,0x04,0xcf,0x00,0x29,0xc0,0x0a,0xf0,0x02,0x2a,0x04 } },
-{  16, 0xc600, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0xb7,0x2a,0x2d,0x82 } },
-{  16, 0xc610, 0, {0x08,0x42,0x22,0x3c,0x00,0x87,0x11,0x0d,0xcc,0x88,0x32,0x02,0x1d,0x00,0x97,0x00 } },
-{  16, 0xc620, 0, {0x2c,0xc4,0x08,0x30,0x02,0x14,0x00,0xa7,0x00,0x23,0xc0,0x09,0x70,0x82,0x00,0x00 } },
-{  16, 0xc630, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xc0,0x20,0xb0,0x20,0x2c,0x50 } },
-{  16, 0xc640, 0, {0x08,0x10,0x02,0x2d,0xc0,0x93,0xe2,0x2c,0x21,0x08,0x30,0x02,0x0e,0x08,0x93,0x00 } },
-{  16, 0xc650, 0, {0x2c,0x40,0x0a,0x30,0x02,0x8c,0x00,0x93,0x00,0x2a,0xc0,0x0b,0x30,0x02,0x18,0x04 } },
-{  16, 0xc660, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xf8,0xc0,0x3e,0x80 } },
-{  16, 0xc670, 0, {0x2c,0xa0,0x0b,0x3f,0x00,0xc7,0x60,0x3e,0xd0,0x0c,0xf0,0x0b,0x3c,0x00,0xcf,0x00 } },
-{  16, 0xc680, 0, {0x3e,0x80,0x0c,0xf0,0x0b,0x2c,0x00,0xef,0x00,0x33,0xc1,0x0d,0xf0,0x0b,0x2a,0x04 } },
-{  16, 0xc690, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x40,0xf3,0x40,0x3e,0x50 } },
-{  16, 0xc6a0, 0, {0x8e,0xb4,0x03,0xec,0x10,0xfb,0x00,0x3e,0x09,0x0f,0xb0,0x13,0xec,0x42,0xeb,0x00 } },
-{  16, 0xc6b0, 0, {0x3c,0x00,0x8f,0xb0,0x13,0xc4,0x11,0xe3,0x00,0x3e,0xc0,0x0e,0xb0,0x03,0xe0,0x00 } },
-{  16, 0xc6c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xfc,0x80,0x31,0x22 } },
-{  16, 0xc6d0, 0, {0x0c,0xa8,0x03,0x3c,0x00,0xcf,0x00,0x33,0xa0,0x0e,0xf0,0x03,0xdc,0x00,0xcf,0x00 } },
-{  16, 0xc6e0, 0, {0x1f,0xf0,0x0c,0xf0,0x03,0xf4,0x00,0xcf,0x02,0x33,0xc0,0x0c,0xf0,0x02,0x00,0x54 } },
-{  16, 0xc6f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6f,0x00,0xbb,0xc0,0x22,0x70 } },
-{  16, 0xc700, 0, {0x0a,0xb9,0x42,0x2c,0x10,0x8b,0x00,0x76,0x11,0x83,0xb0,0x02,0xec,0x10,0xab,0x00 } },
-{  16, 0xc710, 0, {0x2e,0xb0,0x0a,0xb0,0x03,0xec,0x04,0x8b,0x00,0xa2,0xc0,0x28,0xb0,0x02,0x20,0x40 } },
-{  16, 0xc720, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x65,0x40,0xb8,0x20,0x22,0x44 } },
-{  16, 0xc730, 0, {0x58,0x34,0x0a,0x2c,0x00,0x8b,0x00,0x22,0x84,0x4b,0xb0,0x02,0xec,0x00,0x8b,0x00 } },
-{  16, 0xc740, 0, {0x6e,0xc0,0x08,0xb0,0x42,0xe6,0x04,0x8b,0x00,0x02,0xc0,0x08,0x30,0x02,0xa0,0x01 } },
-{  16, 0xc750, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0xb1,0x00,0x20,0xc0 } },
-{  16, 0xc760, 0, {0x0a,0x30,0x0a,0x0c,0x00,0x8b,0x03,0x24,0x80,0x0b,0x30,0x02,0xcc,0x00,0xa3,0x00 } },
-{  16, 0xc770, 0, {0x6c,0x00,0x0a,0x30,0x02,0x8d,0x00,0x83,0x00,0x20,0xc0,0x18,0x30,0x02,0x82,0x00 } },
-{  16, 0xc780, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x64,0x00,0xf8,0x00,0x30,0x00 } },
-{  16, 0xc790, 0, {0x4c,0xa0,0x0b,0x2c,0x02,0xcf,0x00,0x22,0x40,0x0e,0xf5,0x03,0xfc,0x00,0xcf,0x01 } },
-{  16, 0xc7a0, 0, {0x3e,0x00,0x0c,0xf0,0x12,0xdd,0x02,0xcf,0x02,0x33,0xc0,0x4c,0xf0,0x0b,0x80,0x03 } },
-{  16, 0xc7b0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x19,0xf0,0x00,0xfc,0x00,0x3f,0x40 } },
-{  16, 0xc7c0, 0, {0x0f,0xb1,0x03,0xdc,0x00,0xbf,0x01,0x3f,0x00,0x0f,0xf2,0x23,0xfc,0x10,0xff,0x00 } },
-{  16, 0xc7d0, 0, {0x3f,0x00,0x0f,0xf0,0x01,0xf4,0x84,0xff,0x00,0x3d,0xc0,0x4f,0xf0,0x13,0x68,0x06 } },
-{  16, 0xc7e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfe,0x40,0xdf,0x80,0x33,0xc8 } },
-{  16, 0xc7f0, 0, {0x0c,0xf8,0x03,0x3c,0x0a,0x9f,0xc0,0x3f,0xf0,0x08,0xb8,0x02,0x3e,0x00,0xff,0x80 } },
-{  16, 0xc800, 0, {0x3f,0xd8,0x0c,0xf9,0x61,0x2e,0x40,0x6f,0x90,0x3f,0xe4,0x8f,0xf1,0x83,0x30,0x00 } },
-{  16, 0xc810, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0x04,0x8b,0x80,0x23,0xf0 } },
-{  16, 0xc820, 0, {0x08,0xb8,0x02,0x3d,0x40,0xab,0x00,0x0e,0x08,0x48,0x22,0x82,0x6c,0x20,0xbb,0x00 } },
-{  16, 0xc830, 0, {0x2f,0xd0,0x48,0xb0,0x02,0x2c,0x00,0xbb,0x00,0x2e,0xc1,0x0b,0xb0,0x02,0x30,0x04 } },
-{  16, 0xc840, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x02,0x83,0x01,0xa0,0xc5 } },
-{  16, 0xc850, 0, {0x08,0xb0,0x4a,0x4c,0xa0,0x80,0x24,0x28,0xc8,0x09,0x32,0x02,0x4c,0x00,0xb3,0x08 } },
-{  16, 0xc860, 0, {0x2e,0xd1,0x29,0xb2,0x3a,0x0c,0x84,0xa3,0x21,0x2c,0xc8,0x4b,0xb2,0x0a,0x32,0x01 } },
-{  16, 0xc870, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x08,0x8b,0x00,0x22,0xc0 } },
-{  16, 0xc880, 0, {0x08,0xb0,0x02,0x4c,0x00,0x88,0x21,0x24,0x21,0x09,0xb0,0x46,0x6c,0x00,0xbb,0x06 } },
-{  16, 0xc890, 0, {0x2e,0xc0,0x09,0xb0,0x02,0x2c,0x10,0xbb,0x00,0x2e,0xc0,0x0b,0xb0,0x02,0x30,0x04 } },
-{  16, 0xc8a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xcb,0x00,0x32,0xc0 } },
-{  16, 0xc8b0, 0, {0x0c,0xb9,0x02,0x6c,0x00,0xcb,0xc8,0x3a,0xc0,0x2d,0x90,0x0b,0x2c,0x08,0xfb,0x00 } },
-{  16, 0xc8c0, 0, {0x3e,0xc0,0x0d,0x30,0x42,0x2c,0x00,0xeb,0x00,0x3e,0xc0,0x0f,0xb0,0x13,0x00,0x04 } },
-{  16, 0xc8d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x00,0xef,0x00,0x3d,0xc0 } },
-{  16, 0xc8e0, 0, {0x0f,0xf0,0x03,0xbc,0x06,0xef,0x82,0x3f,0x40,0x4e,0xc9,0x83,0xbc,0x00,0xff,0x00 } },
-{  16, 0xc8f0, 0, {0x7f,0xc0,0x1c,0xf0,0x13,0x7c,0x00,0xff,0x04,0x3f,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
-{  16, 0xc900, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x02,0x3e,0xc0 } },
-{  16, 0xc910, 0, {0x0e,0xb0,0x03,0xac,0x20,0xd8,0x40,0x3e,0xc0,0x8c,0x90,0x0b,0x2c,0x00,0xfb,0x00 } },
-{  16, 0xc920, 0, {0x3e,0xc9,0x0d,0xb0,0x33,0xec,0x08,0xfb,0x02,0x3e,0xc0,0x0f,0xb0,0x0b,0x54,0x04 } },
-{  16, 0xc930, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xb3,0x00,0x2f,0xc0 } },
-{  16, 0xc940, 0, {0x0b,0x30,0x12,0xfc,0x00,0x88,0xa0,0x2e,0x40,0x28,0x94,0x02,0x2c,0x10,0xbb,0x04 } },
-{  16, 0xc950, 0, {0x2d,0xc0,0x28,0xb0,0x02,0xec,0x00,0xbb,0x00,0x2e,0xc0,0x0b,0x72,0x06,0x32,0x00 } },
-{  16, 0xc960, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x6c,0x00,0xb3,0x00,0x2c,0xe0 } },
-{  16, 0xc970, 0, {0x0a,0x10,0x02,0xcd,0x00,0x93,0x00,0x2c,0xc0,0x08,0xb0,0x02,0x4c,0x00,0xb3,0x00 } },
-{  16, 0xc980, 0, {0x28,0xc0,0x08,0x30,0x02,0xcc,0x00,0xb3,0x00,0x2c,0xc0,0x0b,0x30,0x02,0x3a,0x00 } },
-{  16, 0xc990, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x40,0xb7,0x80,0x2d,0xe2 } },
-{  16, 0xc9a0, 0, {0x0b,0x58,0x02,0xde,0x02,0x97,0x81,0x2f,0xa0,0x08,0x68,0x02,0x5e,0x00,0xb7,0x81 } },
-{  16, 0xc9b0, 0, {0x2f,0xe0,0x08,0x79,0x02,0xde,0x00,0xb7,0x81,0x2d,0xe0,0x0b,0x78,0x02,0x3c,0x00 } },
-{  16, 0xc9c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xf3,0x00,0x3c,0xc0 } },
-{  16, 0xc9d0, 0, {0x0e,0x32,0x03,0xcc,0x80,0xd3,0x00,0x3c,0xc4,0x0c,0x39,0x03,0x4c,0x08,0xf3,0x1a } },
-{  16, 0xc9e0, 0, {0x3c,0xc6,0x0d,0x30,0x03,0xce,0x20,0xf3,0x08,0x3c,0xc0,0x0f,0x30,0x03,0x52,0x02 } },
-{  16, 0xc9f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xac,0x00,0xfb,0x00,0x2e,0xc0 } },
-{  16, 0xca00, 0, {0x0b,0xb0,0x03,0xcc,0x20,0xeb,0x00,0x3c,0x80,0x0f,0xb0,0x41,0xac,0x00,0xfb,0x00 } },
-{  16, 0xca10, 0, {0x3c,0xc2,0x0f,0xb0,0x03,0xec,0x40,0xfb,0x00,0x3e,0xc0,0x0f,0x30,0x03,0xd0,0x06 } },
-{  16, 0xca20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xee,0x02,0xc3,0x80,0x30,0xce } },
-{  16, 0xca30, 0, {0x0d,0x98,0x03,0xac,0xa0,0xc3,0x80,0xb2,0xc0,0x0f,0xb0,0x03,0xec,0x00,0xfb,0x00 } },
-{  16, 0xca40, 0, {0x3e,0xd2,0x4f,0xb0,0x09,0x2e,0x08,0x4b,0x01,0x3e,0xc0,0x24,0xb0,0x03,0xea,0x00 } },
-{  16, 0xca50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0x87,0x01,0x21,0xc0 } },
-{  16, 0xca60, 0, {0x48,0x50,0x12,0x4c,0x00,0x87,0x00,0x35,0xc0,0x4b,0x60,0x02,0xdc,0x04,0xb7,0x01 } },
-{  16, 0xca70, 0, {0x2d,0xc0,0x0b,0x70,0x02,0x1c,0x00,0x87,0x00,0x2d,0xc1,0x0c,0x72,0x02,0xf2,0x04 } },
-{  16, 0xca80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0x87,0x80,0x23,0xe0 } },
-{  16, 0xca90, 0, {0x08,0xf8,0x02,0xde,0x80,0x8f,0x81,0x21,0xe0,0x4b,0x78,0x12,0xde,0x04,0x37,0x80 } },
-{  16, 0xcaa0, 0, {0x2d,0xe8,0x0b,0xf8,0x02,0x3e,0x18,0x87,0x80,0x2f,0xe0,0x09,0x79,0x02,0xe0,0x00 } },
-{  16, 0xcab0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0x83,0x00,0xa0,0xc0 } },
-{  16, 0xcac0, 0, {0x28,0x30,0x42,0x4c,0x00,0x83,0x00,0x24,0xc0,0x0b,0x38,0x06,0xcc,0x04,0xb3,0x00 } },
-{  16, 0xcad0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0x0c,0x02,0x83,0x00,0x2c,0xc0,0x08,0x30,0x02,0xd2,0x04 } },
-{  16, 0xcae0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xca,0x00,0x31,0x80 } },
-{  16, 0xcaf0, 0, {0x08,0xe0,0x02,0x98,0x02,0xce,0x00,0x33,0x84,0x0b,0xea,0x03,0xe8,0x00,0xba,0x00 } },
-{  16, 0xcb00, 0, {0x3f,0x81,0x0f,0xa0,0x03,0x28,0x00,0xca,0x00,0x3e,0x80,0x0d,0xe0,0x03,0xfa,0x04 } },
-{  16, 0xcb10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x00,0xf8,0x00,0x3e,0x00 } },
-{  16, 0xcb20, 0, {0x0e,0x84,0x23,0xa0,0x00,0xf8,0x00,0x3a,0x10,0x0f,0x80,0x03,0xe0,0x00,0xf8,0x00 } },
-{  16, 0xcb30, 0, {0x3e,0x10,0x0f,0x80,0x13,0xe0,0x00,0xf8,0x00,0x3e,0x00,0x0d,0x80,0x03,0xd2,0x00 } },
-{  16, 0xcb40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x01,0xf9,0x00,0x3e,0x40 } },
-{  16, 0xcb50, 0, {0x0c,0x9a,0x13,0xe4,0x00,0xc9,0x00,0x3e,0x40,0x0c,0x98,0x23,0xe4,0x80,0xf9,0x00 } },
-{  16, 0xcb60, 0, {0x3e,0x40,0x2c,0x98,0x03,0x64,0x00,0xf9,0x00,0x3e,0x40,0x0c,0x90,0x03,0xc2,0x04 } },
-{  16, 0xcb70, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x04,0xb9,0x00,0x2e,0x40 } },
-{  16, 0xcb80, 0, {0x68,0x9c,0x22,0xe4,0x02,0x89,0x01,0x7c,0x50,0x8d,0x98,0x22,0xe4,0x80,0xb9,0x20 } },
-{  16, 0xcb90, 0, {0x2e,0x50,0x48,0x10,0x0b,0x25,0x00,0xb9,0x44,0x2c,0x40,0x28,0x90,0x00,0xe0,0x00 } },
-{  16, 0xcba0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x00,0x2e,0x50 } },
-{  16, 0xcbb0, 0, {0x08,0x90,0x02,0xe4,0x04,0x89,0x00,0x2e,0x50,0x0a,0x92,0x02,0xe4,0x00,0xb9,0x00 } },
-{  16, 0xcbc0, 0, {0x2c,0x40,0x08,0x91,0x02,0x24,0x00,0xb9,0x00,0x2e,0x40,0x08,0x90,0x02,0xc6,0x00 } },
-{  16, 0xcbd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x05,0x00,0xb1,0x01,0x2c,0x40 } },
-{  16, 0xcbe0, 0, {0x48,0x30,0x02,0xe4,0x00,0x81,0x00,0x2a,0x40,0x4b,0x10,0x02,0xc4,0x00,0xb1,0x00 } },
-{  16, 0xcbf0, 0, {0x0c,0xc0,0x08,0x90,0x02,0x0c,0x00,0xb3,0x00,0x2e,0x40,0x48,0x12,0x02,0xc2,0x01 } },
-{  16, 0xcc00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xb8,0x01,0x3e,0x00 } },
-{  16, 0xcc10, 0, {0x1c,0x80,0x07,0xe1,0x50,0xc8,0x50,0x2e,0x14,0x1e,0x85,0x03,0xe1,0x41,0xf8,0x50 } },
-{  16, 0xcc20, 0, {0x3e,0x14,0x0c,0x85,0x13,0x21,0x48,0xf8,0x50,0x3e,0x14,0x0c,0x85,0x43,0xee,0x03 } },
-{  16, 0xcc30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0xc4,0x00,0xf9,0x00,0x3e,0x51 } },
-{  16, 0xcc40, 0, {0x0f,0x50,0x03,0xe5,0x00,0xfd,0x00,0x3f,0x40,0x1d,0xd0,0x03,0xf4,0x10,0xf9,0x00 } },
-{  16, 0xcc50, 0, {0x3e,0x50,0x0f,0x50,0x00,0x94,0x00,0xf9,0x00,0x3d,0x40,0x0f,0x91,0x03,0xe6,0x06 } },
-{  16, 0xcc60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0xe4,0x50,0xcd,0x00,0x31,0x60 } },
-{  16, 0xcc70, 0, {0x04,0xd0,0x03,0x36,0x80,0xc1,0x42,0x2e,0x50,0x1f,0x94,0x03,0xe5,0x00,0xe9,0x02 } },
-{  16, 0xcc80, 0, {0x2e,0x72,0x0a,0x90,0x22,0x05,0x08,0xe9,0x40,0x3e,0x50,0x40,0x9c,0x03,0x26,0x00 } },
-{  16, 0xcc90, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xc2,0x82,0x88,0x00,0x22,0x15 } },
-{  16, 0xcca0, 0, {0x08,0x80,0x02,0x23,0x58,0x88,0xa0,0x2e,0x28,0x0b,0xaa,0x42,0xe2,0x82,0x88,0x80 } },
-{  16, 0xccb0, 0, {0x2e,0x38,0x28,0x88,0x02,0x22,0x80,0xb8,0xa0,0x3a,0x28,0x08,0xcd,0x02,0x0e,0x04 } },
-{  16, 0xccc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0x81,0x00,0xa6,0x40 } },
-{  16, 0xccd0, 0, {0x28,0x10,0x0a,0x24,0x26,0x95,0x00,0x0d,0x40,0x0b,0x50,0x02,0x74,0x00,0x85,0x08 } },
-{  16, 0xcce0, 0, {0x2f,0x40,0x79,0xd2,0xaa,0x14,0x00,0xa5,0x01,0x2f,0x40,0x38,0x50,0x02,0x12,0x01 } },
-{  16, 0xccf0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x04,0x89,0x00,0x26,0x40 } },
-{  16, 0xcd00, 0, {0x08,0x91,0x02,0x24,0x10,0x9d,0x08,0x2f,0x40,0x0b,0xd0,0x02,0xf4,0x00,0x8d,0x02 } },
-{  16, 0xcd10, 0, {0x2f,0x40,0x09,0xd0,0x00,0x34,0x00,0xbd,0x00,0x0b,0x40,0x18,0x70,0x02,0x06,0x04 } },
-{  16, 0xcd20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xc4,0x00,0xc9,0x05,0x36,0x41 } },
-{  16, 0xcd30, 0, {0x4c,0x90,0x63,0x24,0x00,0xd9,0x00,0x3e,0x40,0x0b,0x90,0x03,0x44,0x08,0xc9,0x00 } },
-{  16, 0xcd40, 0, {0x3e,0x40,0x15,0x10,0x03,0x24,0x00,0xe9,0x00,0x3c,0x40,0x0c,0x90,0x03,0x28,0x04 } },
-{  16, 0xcd50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x04,0xf9,0x00,0x3a,0x40 } },
-{  16, 0xcd60, 0, {0x4f,0x98,0x03,0xe4,0x00,0xe9,0x99,0x3e,0x40,0x4f,0x90,0x03,0xe4,0x20,0xf9,0x0a } },
-{  16, 0xcd70, 0, {0x3e,0x40,0x0e,0x90,0x43,0x64,0x24,0xf9,0x08,0x3a,0x42,0x0f,0x90,0x8b,0xda,0x00 } },
-{  16, 0xcd80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xc8,0x00,0x12,0x00 } },
-{  16, 0xcd90, 0, {0x0c,0x80,0x43,0xe0,0x00,0xc8,0x40,0x32,0x00,0x0f,0x84,0x53,0xe0,0x10,0xf8,0x00 } },
-{  16, 0xcda0, 0, {0x3e,0x00,0x0d,0x80,0x23,0x20,0x00,0xd8,0x00,0x3e,0x00,0x0f,0x80,0x03,0x0a,0x04 } },
-{  16, 0xcdb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x38,0x02,0x82,0x00,0xa1,0x88 } },
-{  16, 0xcdc0, 0, {0x08,0x60,0x22,0xc8,0x00,0x8a,0x40,0x36,0xa1,0x0b,0xa0,0x02,0xe9,0x10,0xba,0x44 } },
-{  16, 0xcdd0, 0, {0x2c,0x80,0x0c,0xa4,0x12,0x29,0x02,0x8a,0x44,0x2e,0x98,0x0b,0xa4,0x02,0x0a,0x00 } },
-{  16, 0xcde0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x10,0x83,0x00,0x20,0xe0 } },
-{  16, 0xcdf0, 0, {0x18,0x30,0x92,0xc4,0x08,0x93,0x40,0x20,0xe0,0x0b,0x30,0x02,0xcd,0x00,0xb3,0x40 } },
-{  16, 0xce00, 0, {0x2c,0xc0,0x0b,0x3a,0x42,0xcd,0x00,0x83,0x40,0x2c,0xd0,0x0b,0x38,0x02,0x4a,0x00 } },
-{  16, 0xce10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x41,0x1c,0x00,0x87,0x00,0x21,0xc0 } },
-{  16, 0xce20, 0, {0x28,0x70,0x02,0xd1,0x00,0x9d,0x80,0x25,0xc2,0x4b,0x60,0x02,0xdc,0x08,0xb7,0x02 } },
-{  16, 0xce30, 0, {0x2c,0xc0,0x0a,0x74,0x02,0xfe,0x00,0x87,0x00,0x2d,0xc0,0x0b,0x34,0x02,0x68,0x00 } },
-{  16, 0xce40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xc7,0x84,0x31,0xe0 } },
-{  16, 0xce50, 0, {0x0c,0x68,0x03,0xd6,0x00,0x97,0x80,0x31,0xa0,0x0f,0x58,0x13,0xde,0x08,0xf7,0x82 } },
-{  16, 0xce60, 0, {0x3d,0xa0,0x0f,0xf8,0x0b,0xde,0x00,0xc7,0x80,0x3d,0xe0,0x0f,0x78,0x8b,0x6a,0x02 } },
-{  16, 0xce70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xad,0x80,0xf3,0x00,0x3e,0xc1 } },
-{  16, 0xce80, 0, {0x0f,0xa0,0x23,0xc0,0x02,0xe9,0x00,0x3e,0x81,0x0f,0x80,0x03,0xec,0x00,0xfb,0x00 } },
-{  16, 0xce90, 0, {0x3e,0xc0,0x0d,0xb0,0x13,0x2c,0x00,0xeb,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0x82,0x02 } },
-{  16, 0xcea0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xff,0x32,0xc7,0x80,0x33,0x60 } },
-{  16, 0xceb0, 0, {0x0f,0x78,0x03,0x3e,0xc8,0x4e,0x80,0x23,0x64,0x0c,0xf8,0x03,0x3a,0x00,0xce,0x80 } },
-{  16, 0xcec0, 0, {0x13,0xec,0x06,0xd8,0x03,0x3a,0x00,0xde,0x80,0x33,0xa4,0x0c,0xc8,0x03,0xd0,0x00 } },
-{  16, 0xced0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0x87,0x10,0x01,0xc0 } },
-{  16, 0xcee0, 0, {0x0b,0x70,0x02,0x18,0x50,0x84,0x00,0x2b,0x44,0x08,0x60,0x12,0x98,0x00,0x86,0x13 } },
-{  16, 0xcef0, 0, {0x21,0xc4,0x88,0x50,0x02,0x18,0x80,0x86,0x00,0x21,0x80,0x08,0x61,0x02,0xea,0x04 } },
-{  16, 0xcf00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x87,0x00,0x21,0x40 } },
-{  16, 0xcf10, 0, {0x0b,0xf1,0x02,0x5c,0x80,0x06,0x00,0x21,0x00,0x88,0xd0,0x02,0x5c,0x00,0x87,0x00 } },
-{  16, 0xcf20, 0, {0x20,0x89,0x8a,0xf1,0x02,0x1c,0x08,0x87,0x10,0x21,0x81,0x88,0x48,0x02,0xc6,0x00 } },
-{  16, 0xcf30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x10,0x83,0x04,0xa0,0xc1 } },
-{  16, 0xcf40, 0, {0x0b,0x30,0x0a,0x48,0x0c,0x88,0x06,0x60,0x38,0x08,0x04,0x42,0xec,0x01,0x8b,0x04 } },
-{  16, 0xcf50, 0, {0x22,0xc1,0x08,0x30,0x0a,0x2c,0x00,0x8b,0x00,0x22,0x80,0x00,0x20,0x02,0xd8,0x04 } },
-{  16, 0xcf60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xc3,0x00,0x22,0x80 } },
-{  16, 0xcf70, 0, {0x8f,0x90,0x03,0x64,0x0a,0xcb,0x02,0xb2,0xf2,0x20,0x35,0x12,0x64,0x0a,0xc9,0x00 } },
-{  16, 0xcf80, 0, {0xb2,0x40,0x0e,0xa0,0x03,0x24,0x0a,0xc9,0x00,0xa2,0x40,0x2c,0xa0,0x03,0xee,0x04 } },
-{  16, 0xcf90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x00,0x3c,0x80 } },
-{  16, 0xcfa0, 0, {0x0f,0x90,0x03,0xa5,0x00,0xdb,0x40,0x3e,0xd0,0x4d,0xb4,0x13,0xa4,0x08,0xfb,0x01 } },
-{  16, 0xcfb0, 0, {0x3e,0xc0,0x1c,0xa0,0x03,0x6c,0x00,0xfb,0x04,0x3e,0x50,0x4f,0xa4,0x03,0xe0,0x00 } },
-{  16, 0xcfc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xff,0x00,0x33,0xc0 } },
-{  16, 0xcfd0, 0, {0x0c,0xe8,0x43,0x26,0x00,0xdf,0x80,0xb3,0xe0,0x0f,0xf8,0x03,0x7c,0x00,0xcd,0x00 } },
-{  16, 0xcfe0, 0, {0x33,0x04,0x0c,0xe0,0x23,0x34,0x40,0xcd,0x00,0x23,0x40,0x0c,0xe0,0x03,0xe0,0x04 } },
-{  16, 0xcff0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x10,0xbb,0x00,0xa2,0xd2 } },
-{  16, 0xd000, 0, {0x08,0x28,0x02,0x04,0x60,0x8b,0x19,0x22,0xc6,0x0e,0xb1,0x8a,0x2e,0x40,0x8b,0x90 } },
-{  16, 0xd010, 0, {0x22,0xc1,0x08,0xa4,0x82,0x2c,0x00,0x8b,0x90,0x22,0x64,0x48,0xa4,0x02,0xe0,0x00 } },
-{  16, 0xd020, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0xbb,0x00,0x22,0x00 } },
-{  16, 0xd030, 0, {0x08,0x91,0x2e,0x24,0x00,0x9b,0x00,0x22,0xc0,0x8b,0xb0,0x12,0x20,0x04,0x88,0x00 } },
-{  16, 0xd040, 0, {0x22,0x40,0x08,0x10,0x22,0x20,0x00,0x88,0x01,0x2a,0xd0,0x08,0x80,0x42,0xe0,0x00 } },
-{  16, 0xd050, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xb3,0x04,0x20,0x80 } },
-{  16, 0xd060, 0, {0x08,0x10,0x06,0x04,0x10,0x83,0x00,0x20,0xc0,0x8b,0xb0,0x12,0x00,0x00,0x82,0x00 } },
-{  16, 0xd070, 0, {0x20,0xc0,0x28,0x10,0x42,0x09,0x06,0x82,0x00,0x28,0xc0,0x08,0x20,0x02,0xc2,0x01 } },
-{  16, 0xd080, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x7c,0x00,0xbb,0x00,0x32,0x40 } },
-{  16, 0xd090, 0, {0x2c,0xb0,0x03,0x24,0x00,0xd3,0x00,0x32,0xc0,0x5f,0xb5,0x03,0x0c,0x02,0xc1,0x00 } },
-{  16, 0xd0a0, 0, {0xb2,0x00,0x0c,0xb0,0x0b,0x05,0x00,0xc1,0x00,0xb8,0xc0,0x2c,0x80,0x13,0xe0,0x03 } },
-{  16, 0xd0b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xdc,0x00,0xff,0x00,0x1f,0xc0 } },
-{  16, 0xd0c0, 0, {0x87,0xf0,0x01,0xf4,0x00,0xff,0x00,0x3f,0xc0,0x0e,0x70,0x43,0xfc,0x10,0x7f,0x00 } },
-{  16, 0xd0d0, 0, {0x3f,0xc0,0x0f,0x70,0x03,0xfc,0x00,0xff,0x00,0x37,0xc0,0x0f,0xe0,0x03,0xe8,0x06 } },
-{  16, 0xd0e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf1,0x84,0xfe,0x61,0x31,0xd8 } },
-{  16, 0xd0f0, 0, {0x0c,0xb2,0xc3,0xfc,0xe0,0xcc,0x80,0x7b,0xc0,0x0e,0xf1,0x03,0x7c,0xe0,0xcc,0x83 } },
-{  16, 0xd100, 0, {0x3f,0x20,0x0f,0xf0,0xcb,0x32,0x44,0xdc,0x84,0x3f,0x25,0x4c,0xf2,0x43,0x30,0x00 } },
-{  16, 0xd110, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe4,0x48,0xb0,0x10,0x22,0xdc } },
-{  16, 0xd120, 0, {0x08,0xb6,0x02,0xfd,0x92,0x88,0x85,0x23,0xf4,0x40,0xf1,0x02,0xed,0x00,0x88,0x2d } },
-{  16, 0xd130, 0, {0x0e,0x60,0x0b,0xbc,0x12,0x2c,0x10,0xa8,0x82,0x2e,0x00,0x0a,0xfc,0x22,0xa0,0x04 } },
-{  16, 0xd140, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc0,0x80,0xb3,0x22,0x28,0xc0 } },
-{  16, 0xd150, 0, {0x08,0x30,0x82,0xcc,0x01,0x88,0x00,0x2c,0xc0,0x4a,0x32,0x02,0xcc,0x00,0x01,0x01 } },
-{  16, 0xd160, 0, {0x28,0x00,0x4b,0xb0,0x02,0xa0,0x00,0x80,0x00,0x2c,0x09,0x08,0x34,0x02,0x62,0x01 } },
-{  16, 0xd170, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x04,0xb2,0x10,0x2a,0xc1 } },
-{  16, 0xd180, 0, {0x08,0xb0,0x02,0xec,0x10,0x89,0x80,0x22,0xc0,0x08,0xb0,0x02,0xec,0x08,0x88,0x00 } },
-{  16, 0xd190, 0, {0x2e,0x40,0x83,0xb0,0x02,0xa0,0x40,0xb9,0x80,0x2c,0x21,0x0a,0xb0,0x02,0xf0,0x04 } },
-{  16, 0xd1a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xfa,0x00,0xba,0xc0 } },
-{  16, 0xd1b0, 0, {0x2c,0xb0,0x43,0xec,0x00,0xc0,0x80,0x3e,0xc0,0x8e,0xb0,0x03,0x4c,0x0c,0xc8,0x10 } },
-{  16, 0xd1c0, 0, {0x3e,0x80,0x8f,0xb0,0x03,0x82,0x10,0xd8,0x82,0x3e,0x28,0x0c,0xb0,0x0b,0x50,0x04 } },
-{  16, 0xd1d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb6,0x80,0xfd,0x02,0x37,0xc1 } },
-{  16, 0xd1e0, 0, {0x0f,0xb0,0x03,0xfc,0x00,0xfd,0x00,0x3e,0xc0,0x0f,0xb0,0x53,0xfc,0x02,0xff,0x01 } },
-{  16, 0xd1f0, 0, {0x2f,0xa4,0x8b,0xf0,0x83,0x7c,0x00,0xad,0x02,0x2f,0x40,0x03,0x70,0x03,0xb8,0x00 } },
-{  16, 0xd200, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x04,0x32,0xc0 } },
-{  16, 0xd210, 0, {0x4c,0xb0,0x23,0x2c,0x00,0xf8,0x40,0x3e,0xc2,0x0c,0xb0,0x03,0x2c,0x00,0xfb,0x41 } },
-{  16, 0xd220, 0, {0x32,0xc2,0x0f,0xb0,0x43,0x2d,0x00,0xc8,0x50,0x3e,0x40,0x0c,0xb0,0x0b,0x10,0x04 } },
-{  16, 0xd230, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2f,0x90,0xb9,0x50,0x03,0xc0 } },
-{  16, 0xd240, 0, {0x18,0xf0,0x1a,0x3c,0x00,0xb9,0x32,0x2d,0xe0,0x38,0xf0,0x60,0x3c,0x04,0xf9,0x00 } },
-{  16, 0xd250, 0, {0x3e,0xf0,0x0b,0x7c,0x80,0x2c,0x00,0xd9,0xc0,0x2e,0x40,0x0d,0xf0,0x02,0x32,0x00 } },
-{  16, 0xd260, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4b,0x24,0xb2,0x10,0x02,0xc1 } },
-{  16, 0xd270, 0, {0x28,0x30,0x02,0x6c,0x04,0xb2,0xc1,0x2c,0xc0,0x08,0x30,0x00,0x0c,0x00,0xb2,0x00 } },
-{  16, 0xd280, 0, {0x28,0x24,0x03,0x3c,0x0a,0x00,0x00,0x82,0xc8,0x2c,0xa0,0x08,0x30,0x02,0x38,0x00 } },
-{  16, 0xd290, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x00,0xb4,0x80,0x21,0xe4 } },
-{  16, 0xd2a0, 0, {0x48,0x7b,0x02,0x5e,0x00,0xb6,0x80,0x6d,0xe2,0x48,0x79,0x22,0x1e,0x40,0xac,0x84 } },
-{  16, 0xd2b0, 0, {0x2d,0xe0,0x0b,0xfa,0x00,0x52,0x40,0x96,0x80,0x2d,0xe8,0x19,0x38,0x02,0x08,0x00 } },
-{  16, 0xd2c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x40,0xf3,0x10,0xb0,0xc4 } },
-{  16, 0xd2d0, 0, {0x08,0x3a,0x02,0x4c,0x90,0xf3,0x10,0x3c,0xcc,0x08,0x31,0x03,0x0c,0x49,0xb0,0x40 } },
-{  16, 0xd2e0, 0, {0x30,0x05,0x0f,0x30,0x07,0x21,0x40,0x43,0x01,0x3e,0xc2,0x1c,0x30,0x43,0x12,0x02 } },
-{  16, 0xd2f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x0d,0xbc,0x10,0xfc,0x10,0x3f,0xc5 } },
-{  16, 0xd300, 0, {0x0f,0xf1,0x01,0xbc,0x04,0xff,0x04,0x3f,0xc4,0x0f,0xb1,0x4b,0xfc,0x64,0xf7,0x00 } },
-{  16, 0xd310, 0, {0x37,0xc0,0x0f,0x72,0x53,0xac,0x44,0xff,0x01,0x3f,0xc9,0x0f,0xf4,0x03,0xd0,0x06 } },
-{  16, 0xd320, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x08,0xfa,0x00,0x3e,0xe0 } },
-{  16, 0xd330, 0, {0x0c,0xb0,0x03,0x2c,0x00,0xcb,0x02,0x3e,0xca,0x0f,0xb2,0x07,0x2e,0x00,0xdb,0x02 } },
-{  16, 0xd340, 0, {0x32,0x08,0x0f,0x31,0x03,0x2c,0x00,0xcb,0x04,0x3e,0x80,0x0c,0x35,0x03,0x2a,0x00 } },
-{  16, 0xd350, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x00,0xb5,0x00,0x2d,0xc8 } },
-{  16, 0xd360, 0, {0x08,0x70,0x0a,0x1c,0x22,0x87,0x00,0x2d,0xc9,0x0b,0xf2,0x82,0x9c,0x80,0xa6,0x00 } },
-{  16, 0xd370, 0, {0x09,0x8b,0x0b,0x70,0x0a,0x1c,0x02,0x85,0x00,0x2d,0x40,0x08,0x70,0x02,0x92,0x04 } },
-{  16, 0xd380, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x80,0x2c,0xec } },
-{  16, 0xd390, 0, {0x08,0x7b,0x02,0x5e,0x40,0x85,0x89,0x2d,0xec,0x8b,0x7b,0x02,0x4e,0x84,0x8f,0x80 } },
-{  16, 0xd3a0, 0, {0x25,0x64,0x0b,0xfa,0x02,0x12,0x08,0x97,0x80,0x6f,0xe1,0x08,0x7a,0x02,0x30,0x00 } },
-{  16, 0xd3b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x20,0xb3,0x64,0x2c,0xc0 } },
-{  16, 0xd3c0, 0, {0x08,0x30,0x06,0x0c,0x10,0x83,0x8a,0x6c,0xc0,0x5b,0x30,0x42,0xcc,0x00,0xab,0x10 } },
-{  16, 0xd3d0, 0, {0x2c,0xf2,0x0b,0x30,0x02,0x0d,0x00,0x93,0x04,0x2c,0xd5,0x08,0x30,0x0a,0x92,0x04 } },
-{  16, 0xd3e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xbb,0x00,0xfe,0xc0,0x3e,0x80 } },
-{  16, 0xd3f0, 0, {0x2c,0xa0,0x03,0x68,0x00,0xc6,0x40,0x3f,0x80,0x0f,0xa0,0x02,0x68,0x00,0xce,0x44 } },
-{  16, 0xd400, 0, {0x36,0x90,0x4f,0x60,0x03,0x1b,0x70,0xde,0xd8,0x3f,0xa0,0x0c,0x20,0x03,0x3a,0x04 } },
-{  16, 0xd410, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x40,0xf8,0x10,0x3e,0x00 } },
-{  16, 0xd420, 0, {0x0f,0x80,0x03,0xa0,0x10,0xf8,0x42,0x3e,0x10,0x1f,0x80,0x03,0xa0,0x00,0xe8,0x0c } },
-{  16, 0xd430, 0, {0x3a,0x04,0x1f,0x80,0x03,0xe0,0x00,0xe8,0x45,0x7e,0x02,0x2f,0x80,0x03,0xd2,0x00 } },
-{  16, 0xd440, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x64,0x00,0xe9,0x80,0x32,0x40 } },
-{  16, 0xd450, 0, {0x0f,0x90,0x0b,0x04,0x08,0xd9,0x80,0x36,0x40,0x0f,0x10,0x13,0x24,0x08,0xf9,0x00 } },
-{  16, 0xd460, 0, {0x72,0x70,0x0f,0x91,0x13,0x24,0x10,0xc9,0x10,0x3e,0x69,0x0c,0x90,0x03,0x02,0x04 } },
-{  16, 0xd470, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x08,0xb9,0x80,0x22,0x40 } },
-{  16, 0xd480, 0, {0x0b,0x10,0x02,0x24,0x00,0x89,0xc4,0x22,0x52,0x0b,0x90,0x42,0x24,0x00,0xb9,0x00 } },
-{  16, 0xd490, 0, {0x22,0xe0,0x0b,0x90,0x12,0x24,0x04,0xd9,0x4a,0x2e,0x60,0x08,0x90,0x03,0x60,0x00 } },
-{  16, 0xd4a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb1,0x18,0x22,0x40 } },
-{  16, 0xd4b0, 0, {0x0b,0x90,0x02,0x24,0x00,0x8b,0x20,0x26,0x49,0x0b,0x90,0x02,0x64,0x00,0xb9,0x00 } },
-{  16, 0xd4c0, 0, {0xa2,0x40,0x0b,0x90,0x8a,0x24,0x00,0x8b,0x00,0x2c,0x40,0xa8,0x90,0x02,0x06,0x00 } },
-{  16, 0xd4d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x84,0xb1,0x20,0xa0,0x48 } },
-{  16, 0xd4e0, 0, {0x0b,0x11,0x06,0x04,0x00,0x83,0x00,0x00,0x40,0x4b,0x11,0x02,0x04,0x49,0xb1,0x10 } },
-{  16, 0xd4f0, 0, {0x28,0x40,0x0b,0x10,0x02,0x24,0x41,0x91,0x00,0x2c,0x50,0x08,0x10,0x02,0x42,0x01 } },
-{  16, 0xd500, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x69,0x40,0xe8,0x50,0x32,0x14 } },
-{  16, 0xd510, 0, {0x0f,0x86,0x93,0x21,0xe2,0xc8,0x00,0x36,0x0a,0x0b,0x86,0x8b,0x61,0xa8,0xf8,0x40 } },
-{  16, 0xd520, 0, {0x22,0x80,0x0f,0x82,0xa3,0x21,0x08,0xc8,0x02,0x3e,0x00,0x0c,0x80,0x43,0x2e,0x03 } },
-{  16, 0xd530, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x48,0xfd,0x12,0x3e,0x44 } },
-{  16, 0xd540, 0, {0x0f,0x12,0x03,0xc4,0x00,0x7d,0x01,0x1e,0x40,0x0b,0x92,0x03,0xe4,0x80,0xf5,0x20 } },
-{  16, 0xd550, 0, {0x36,0x40,0x0f,0x90,0x03,0xd4,0x90,0x7d,0x00,0x3d,0x40,0x0f,0x94,0x03,0xe6,0x06 } },
-{  16, 0xd560, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0xf6,0xc1,0xdd,0x88,0x32,0x72 } },
-{  16, 0xd570, 0, {0x0c,0x98,0x03,0x26,0x22,0xdd,0x00,0x3f,0x62,0x2c,0x99,0x83,0x46,0xa0,0xc9,0x40 } },
-{  16, 0xd580, 0, {0xb2,0x40,0x0f,0xd8,0x03,0x24,0x00,0xfd,0x00,0x33,0x51,0x2c,0xd8,0x83,0x06,0x00 } },
-{  16, 0xd590, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe3,0xc2,0x88,0xc0,0x22,0x30 } },
-{  16, 0xd5a0, 0, {0x08,0x8c,0x42,0x22,0x11,0x8a,0x01,0x2e,0x00,0x08,0x88,0x52,0x23,0x00,0x80,0xa3 } },
-{  16, 0xd5b0, 0, {0x2a,0x00,0x4b,0x80,0x42,0x22,0xa0,0xb8,0x00,0x22,0x28,0x08,0x84,0x02,0x8e,0x04 } },
-{  16, 0xd5c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0x81,0x2d,0x20,0x48 } },
-{  16, 0xd5d0, 0, {0x68,0x14,0x80,0x04,0x20,0x81,0x00,0x2e,0x40,0x0b,0x12,0x12,0x04,0x24,0x81,0x20 } },
-{  16, 0xd5e0, 0, {0x20,0x40,0x0b,0x94,0x32,0x04,0x90,0xb9,0x00,0x20,0x40,0x48,0x10,0x4a,0x02,0x01 } },
-{  16, 0xd5f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0x89,0x20,0x22,0x40 } },
-{  16, 0xd600, 0, {0x08,0x90,0x12,0x24,0x00,0x89,0x00,0x2e,0x40,0x08,0x90,0x02,0x24,0x08,0x89,0x40 } },
-{  16, 0xd610, 0, {0x22,0x50,0x0b,0xb0,0x02,0x24,0x20,0xb9,0x09,0xa2,0x44,0x08,0x90,0x02,0x86,0x04 } },
-{  16, 0xd620, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xd9,0x08,0xb2,0x40 } },
-{  16, 0xd630, 0, {0x4c,0x10,0x23,0x04,0x04,0xd9,0xc1,0x3e,0x40,0x8f,0x90,0x0b,0x04,0x08,0xc1,0x40 } },
-{  16, 0xd640, 0, {0x12,0x40,0x0f,0x90,0x43,0x24,0x04,0xf1,0x41,0x30,0x78,0x0c,0x90,0x03,0x28,0x04 } },
-{  16, 0xd650, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x86,0x64,0xf9,0x80,0x3e,0x40 } },
-{  16, 0xd660, 0, {0x0f,0x90,0x0b,0xe4,0x00,0xf9,0x98,0x3e,0x40,0x2f,0x10,0x03,0xa4,0x02,0xf9,0x10 } },
-{  16, 0xd670, 0, {0x3e,0x40,0x0f,0x90,0x0b,0xe6,0x40,0xf9,0x90,0x3e,0x60,0x0f,0x90,0x03,0xca,0x00 } },
-{  16, 0xd680, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xc8,0x41,0x32,0x00 } },
-{  16, 0xd690, 0, {0x0c,0x80,0x07,0x20,0x10,0xc8,0x10,0x3e,0x0c,0x0e,0x80,0x03,0xe0,0x04,0xc8,0x00 } },
-{  16, 0xd6a0, 0, {0xba,0x00,0x0f,0x81,0x43,0x20,0x00,0xf8,0x70,0x3e,0x00,0x0f,0x00,0x0b,0x0a,0x04 } },
-{  16, 0xd6b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x39,0x02,0x8e,0x20,0xa3,0x80 } },
-{  16, 0xd6c0, 0, {0x28,0xe0,0x0a,0x38,0x10,0xae,0x04,0x3d,0xa1,0x8e,0xe0,0x02,0xf8,0x00,0x8e,0x00 } },
-{  16, 0xd6d0, 0, {0x76,0x80,0x0b,0x60,0x03,0x78,0x00,0xbe,0x40,0x2f,0x82,0x0b,0xa0,0x03,0xca,0x00 } },
-{  16, 0xd6e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4d,0x00,0x8b,0x88,0x22,0xc0 } },
-{  16, 0xd6f0, 0, {0x18,0x30,0x02,0x0c,0x00,0x83,0x44,0x2c,0xd0,0x1b,0x30,0x12,0xcc,0x06,0x83,0x00 } },
-{  16, 0xd700, 0, {0x20,0xc1,0x0b,0x30,0x82,0x0c,0x01,0xb3,0x00,0x2c,0x40,0x0b,0x30,0x02,0x0a,0x00 } },
-{  16, 0xd710, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x00,0x85,0x00,0x20,0xcc } },
-{  16, 0xd720, 0, {0x08,0x70,0x06,0x1c,0x84,0xa7,0x01,0x29,0xc0,0x0b,0x72,0x22,0xdc,0x80,0x87,0x34 } },
-{  16, 0xd730, 0, {0x61,0x80,0x0b,0x10,0x02,0x5c,0x00,0xb7,0x00,0x2d,0xc0,0x0b,0x70,0x02,0xe8,0x00 } },
-{  16, 0xd740, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x0e,0x00,0x8c,0x80,0x31,0xe0 } },
-{  16, 0xd750, 0, {0x0c,0xfe,0x02,0x3f,0x00,0xc5,0x80,0x2d,0xe0,0x0e,0x78,0x03,0xdf,0xa0,0xc7,0xa0 } },
-{  16, 0xd760, 0, {0x21,0x60,0x0f,0x78,0x03,0x1e,0x80,0xf7,0x80,0x3d,0xe0,0x0f,0x78,0x03,0x2a,0x02 } },
-{  16, 0xd770, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf9,0x00,0x3e,0xc0 } },
-{  16, 0xd780, 0, {0x0f,0xb0,0x03,0xec,0x00,0xfa,0x00,0x3e,0xc0,0x06,0xb0,0x03,0xec,0x80,0xfb,0x28 } },
-{  16, 0xd790, 0, {0x36,0xd8,0x4f,0xa0,0x03,0xec,0x10,0xfa,0x00,0x3e,0x50,0x0f,0x30,0x03,0xc2,0x06 } },
-{  16, 0xd7a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfa,0x00,0xcc,0x80,0xb3,0xe0 } },
-{  16, 0xd7b0, 0, {0x0f,0xf8,0x03,0x3e,0x00,0xcf,0x90,0x3f,0x60,0x4f,0xf8,0xc3,0x3e,0x00,0xef,0x80 } },
-{  16, 0xd7c0, 0, {0x33,0xf0,0x0c,0x7a,0x03,0x3e,0x70,0xc5,0x90,0x33,0xf1,0x0c,0x78,0x03,0x00,0x00 } },
-{  16, 0xd7d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0xb8,0x00,0x87,0x00,0x21,0xc0 } },
-{  16, 0xd7e0, 0, {0x0b,0x70,0x4a,0x1c,0x00,0x87,0x10,0x2d,0xc0,0x4b,0x71,0x0a,0x3c,0x44,0x8f,0x12 } },
-{  16, 0xd7f0, 0, {0x21,0x86,0x0d,0x72,0x02,0x1e,0x00,0x87,0x00,0x23,0x40,0x08,0x70,0x0a,0x2a,0x04 } },
-{  16, 0xd800, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x84,0x00,0x25,0xc0 } },
-{  16, 0xd810, 0, {0x0b,0x71,0x0a,0x0c,0x00,0xa7,0x12,0x2d,0x84,0x0b,0x70,0x0a,0x1c,0x00,0xb7,0x08 } },
-{  16, 0xd820, 0, {0x23,0x40,0x09,0xf3,0x1a,0x5c,0x86,0x97,0x08,0x25,0x40,0x08,0x70,0x02,0x00,0x00 } },
-{  16, 0xd830, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x20,0x81,0x20,0x26,0xc0 } },
-{  16, 0xd840, 0, {0x0b,0x30,0x02,0x2c,0x00,0x82,0x42,0x2c,0x80,0x0b,0x30,0x22,0x0c,0x08,0x9b,0x80 } },
-{  16, 0xd850, 0, {0x20,0xe0,0x09,0x20,0x02,0x4d,0x08,0x92,0x00,0x24,0xe5,0x08,0x30,0x0a,0x08,0x04 } },
-{  16, 0xd860, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xae,0x82,0xca,0xe0,0xb7,0xc0 } },
-{  16, 0xd870, 0, {0x0f,0xf0,0x13,0x3c,0x0a,0xc9,0xc8,0x3e,0x40,0x0f,0xf0,0x03,0x3c,0x04,0xff,0x84 } },
-{  16, 0xd880, 0, {0x32,0xc0,0x0d,0x90,0x13,0x7c,0x00,0xd9,0x00,0xf6,0xc0,0x2c,0x10,0x03,0x2a,0x04 } },
-{  16, 0xd890, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe4,0x00,0xf3,0x00,0x3a,0xc1 } },
-{  16, 0xd8a0, 0, {0x4f,0xb0,0x03,0xec,0x00,0xf9,0x08,0x3c,0x00,0x0f,0x30,0x13,0xec,0x00,0xeb,0x04 } },
-{  16, 0xd8b0, 0, {0xbe,0x18,0x0f,0x90,0x23,0xac,0x60,0xe9,0x02,0x3a,0x40,0x4f,0x90,0x03,0xe0,0x00 } },
-{  16, 0xd8c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xca,0x00,0x33,0xc0 } },
-{  16, 0xd8d0, 0, {0x0c,0xf0,0x03,0xfc,0x00,0xcd,0x02,0x7f,0x40,0x0c,0xf0,0x42,0x3c,0x00,0xcf,0x08 } },
-{  16, 0xd8e0, 0, {0x37,0x10,0x0f,0xd0,0x03,0xfc,0x10,0xcd,0x08,0x3f,0x66,0x2c,0xd9,0x03,0x00,0x44 } },
-{  16, 0xd8f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x63,0x80,0x8b,0xe0,0x22,0xc0 } },
-{  16, 0xd900, 0, {0x08,0xb0,0x22,0xec,0x00,0xd8,0x80,0x6e,0x20,0x68,0xb0,0x1a,0x2c,0x01,0xfb,0x00 } },
-{  16, 0xd910, 0, {0x22,0x18,0x0b,0x88,0x43,0x4c,0x00,0x88,0xa0,0x2c,0xc0,0x1d,0x90,0x02,0x20,0x40 } },
-{  16, 0xd920, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x08,0x80,0x8b,0x20,0x22,0xc0 } },
-{  16, 0xd930, 0, {0x08,0xb0,0x22,0xec,0x00,0x88,0x88,0x2e,0x62,0x48,0xb0,0x1a,0xcc,0x00,0x8b,0x00 } },
-{  16, 0xd940, 0, {0x26,0xc0,0x4a,0x88,0x02,0xec,0x00,0x08,0x84,0x2e,0x40,0x09,0x90,0x02,0x20,0x00 } },
-{  16, 0xd950, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x83,0x00,0x60,0xc0 } },
-{  16, 0xd960, 0, {0x08,0x30,0x02,0xcc,0x00,0x90,0x06,0x6c,0x00,0x08,0x30,0x02,0x8c,0x00,0xa3,0x04 } },
-{  16, 0xd970, 0, {0x20,0x00,0x8b,0x00,0x06,0x4c,0x21,0x80,0x00,0x6c,0xc0,0x49,0x10,0x0a,0x02,0x01 } },
-{  16, 0xd980, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xca,0x00,0xb2,0xc1 } },
-{  16, 0xd990, 0, {0x88,0xb4,0x03,0xec,0x10,0xc8,0x00,0x2e,0x00,0x0c,0xb0,0x0b,0xbc,0x08,0x8f,0x00 } },
-{  16, 0xd9a0, 0, {0x36,0x00,0x06,0x80,0x03,0xec,0x80,0xc8,0x02,0x3f,0xc1,0x0c,0x90,0x03,0x00,0x03 } },
-{  16, 0xd9b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf0,0x00,0xff,0x00,0x3f,0xc0 } },
-{  16, 0xd9c0, 0, {0x0f,0x72,0x83,0xfc,0x18,0xfc,0x03,0x3f,0x00,0x8f,0x70,0x03,0x7c,0x00,0xff,0x00 } },
-{  16, 0xd9d0, 0, {0x3d,0x00,0x0f,0xc0,0x23,0x8c,0x06,0xfc,0x00,0x3f,0x40,0x0e,0xd0,0x03,0xe8,0x06 } },
-{  16, 0xd9e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x41,0x03,0x70,0x40,0xdc,0x10 } },
-{  16, 0xd9f0, 0, {0x37,0x04,0x0d,0xc1,0x03,0x70,0x40,0xdc,0x10,0x37,0x04,0x0d,0xc1,0x01,0x70,0x40 } },
-{  16, 0xda00, 0, {0x9c,0x10,0x17,0x14,0x05,0xc1,0x03,0x70,0x40,0xdc,0x10,0x17,0x04,0x0d,0xc0,0x31 } },
-{  16, 0xda10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x44,0x05,0x71,0x01,0x5c,0x40 } },
-{  16, 0xda20, 0, {0x57,0x10,0x15,0xc4,0x05,0x21,0x01,0x5c,0x40,0x57,0x10,0x15,0xc4,0x01,0x71,0x01 } },
-{  16, 0xda30, 0, {0x5c,0x40,0x17,0x10,0x05,0xc4,0x05,0x71,0x05,0x5c,0x41,0x57,0x10,0x15,0xc0,0x11 } },
-{  16, 0xda40, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x01,0x20,0x80,0x48,0x20 } },
-{  16, 0xda50, 0, {0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80 } },
-{  16, 0xda60, 0, {0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x80,0x20 } },
-{  16, 0xda70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x60,0x00,0x58,0x00 } },
-{  16, 0xda80, 0, {0x16,0x00,0x05,0x80,0x01,0x60,0x00,0x58,0x00,0x16,0x00,0x05,0x80,0x05,0x60,0x00 } },
-{  16, 0xda90, 0, {0x58,0x00,0x16,0x18,0x01,0x80,0x01,0x60,0x00,0x58,0x00,0x56,0x00,0x05,0x80,0x20 } },
-{  16, 0xdaa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x48,0x05,0x22,0x01,0x1c,0x80 } },
-{  16, 0xdab0, 0, {0x47,0x20,0x11,0xc8,0x04,0x72,0x01,0x5c,0x80,0x57,0x20,0x11,0xc8,0x04,0x72,0x41 } },
-{  16, 0xdac0, 0, {0x5c,0x80,0x57,0x20,0x11,0xc8,0x04,0x72,0x01,0x1c,0x80,0x47,0x20,0x15,0xc0,0x31 } },
-{  16, 0xdad0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x00,0x60,0x00,0x18,0x00 } },
-{  16, 0xdae0, 0, {0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00 } },
-{  16, 0xdaf0, 0, {0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x31 } },
-{  16, 0xdb00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x48,0x04,0x22,0x01,0x08,0x80 } },
-{  16, 0xdb10, 0, {0x42,0x20,0x10,0x88,0x04,0x22,0x01,0x08,0x80,0x42,0x20,0x10,0x80,0x04,0x23,0x01 } },
-{  16, 0xdb20, 0, {0x08,0x80,0x42,0x20,0x10,0x88,0x04,0x22,0x01,0x08,0x00,0x42,0x20,0x10,0x80,0x21 } },
-{  16, 0xdb30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x4a,0x05,0x42,0x81,0x50,0xa0 } },
-{  16, 0xdb40, 0, {0x44,0x2c,0x11,0x0b,0x04,0x42,0x81,0x10,0xe0,0x54,0x28,0x11,0x02,0x00,0x42,0x81 } },
-{  16, 0xdb50, 0, {0x10,0xa0,0x44,0x38,0x11,0x0b,0x05,0x42,0x81,0x10,0x21,0x14,0x28,0x15,0x00,0x31 } },
-{  16, 0xdb60, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0c,0x01,0x57,0x00,0x54,0xc0 } },
-{  16, 0xdb70, 0, {0x15,0x30,0x04,0x4c,0x01,0x13,0x00,0x54,0xc0,0x15,0x70,0x05,0x4c,0x01,0x53,0x00 } },
-{  16, 0xdb80, 0, {0x54,0xc0,0x15,0x30,0x85,0x4c,0x01,0x13,0x00,0x54,0xc0,0x15,0x30,0x05,0x40,0x21 } },
-{  16, 0xdb90, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x40,0x00,0x10,0x00 } },
-{  16, 0xdba0, 0, {0x04,0x00,0x00,0x40,0x00,0x10,0x00,0x10,0x62,0x04,0x00,0x01,0x08,0x04,0x41,0x00 } },
-{  16, 0xdbb0, 0, {0x10,0x00,0x44,0x18,0x11,0x00,0x00,0x10,0x00,0x10,0x80,0x04,0x00,0x01,0x01,0x20 } },
-{  16, 0xdbc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x60,0x02,0x08,0x00,0x82,0x00 } },
-{  16, 0xdbd0, 0, {0x20,0x80,0x08,0x60,0x02,0x18,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x00,0x08,0x20 } },
-{  16, 0xdbe0, 0, {0x82,0x00,0x00,0x80,0x80,0x20,0x02,0x18,0x00,0x82,0x00,0x20,0x80,0x08,0x01,0x31 } },
-{  16, 0xdbf0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x05,0x64,0x01,0x58,0x00 } },
-{  16, 0xdc00, 0, {0x56,0x00,0x15,0x80,0x05,0x60,0x01,0x58,0x00,0x56,0x40,0x15,0x80,0x05,0x60,0x01 } },
-{  16, 0xdc10, 0, {0x58,0x00,0x56,0x00,0x15,0x80,0x05,0x60,0x01,0x58,0x00,0x76,0x00,0x15,0x80,0x31 } },
-{  16, 0xdc20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x03,0x60,0x00,0xd8,0x00 } },
-{  16, 0xdc30, 0, {0x36,0x00,0x0d,0x80,0x03,0x60,0x00,0x98,0x00,0x36,0x00,0x1d,0x88,0x05,0x60,0x00 } },
-{  16, 0xdc40, 0, {0xd8,0x00,0x16,0x00,0x0d,0x80,0x03,0x60,0x00,0xd8,0x80,0x46,0x00,0x0d,0x80,0x31 } },
-{  16, 0xdc50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x04,0x30,0x81,0x0c,0x20 } },
-{  16, 0xdc60, 0, {0x43,0x08,0x10,0xc2,0x04,0x30,0x81,0x0c,0x22,0x41,0x08,0x18,0xc2,0x04,0x30,0x89 } },
-{  16, 0xdc70, 0, {0x0c,0x20,0x03,0x08,0x10,0xc2,0x04,0x30,0x81,0x0c,0x20,0x43,0x08,0x10,0xc0,0x10 } },
-{  16, 0xdc80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x30,0x00,0x0c,0x00 } },
-{  16, 0xdc90, 0, {0x03,0x00,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0xc0,0x00,0x30,0x00 } },
-{  16, 0xdca0, 0, {0x0c,0x00,0x03,0x00,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0xc0,0x01 } },
-{  16, 0xdcb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x01,0x30,0x80,0x4c,0x20 } },
-{  16, 0xdcc0, 0, {0x13,0x08,0x04,0xc2,0x01,0x30,0x80,0x4c,0x20,0x13,0x08,0x04,0xc3,0x01,0x30,0x80 } },
-{  16, 0xdcd0, 0, {0x4c,0x20,0x13,0x08,0x04,0xc2,0x01,0x30,0x80,0x4c,0x30,0x13,0x08,0x04,0xc0,0x21 } },
-{  16, 0xdce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x05,0x60,0x81,0x58,0x20 } },
-{  16, 0xdcf0, 0, {0x56,0x08,0x11,0x82,0x05,0x60,0x81,0x58,0x20,0x56,0x08,0x11,0x83,0x00,0x60,0x81 } },
-{  16, 0xdd00, 0, {0x58,0x20,0x46,0x08,0x11,0x82,0x04,0x60,0x81,0x18,0x30,0x56,0x08,0x15,0x80,0x30 } },
-{  16, 0xdd10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x00,0x20,0x80,0x08,0x20 } },
-{  16, 0xdd20, 0, {0x02,0x08,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x02,0x08,0x00,0x82,0x00,0x30,0x80 } },
-{  16, 0xdd30, 0, {0x08,0x20,0x02,0x00,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x03,0x08,0x00,0x80,0x31 } },
-{  16, 0xdd40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x04,0x60,0x81,0x18,0x20 } },
-{  16, 0xdd50, 0, {0x46,0x48,0x11,0x92,0x04,0x60,0x81,0x19,0x20,0x46,0x28,0x11,0x82,0x00,0x34,0x81 } },
-{  16, 0xdd60, 0, {0x18,0x20,0x46,0x48,0x11,0x92,0x04,0x60,0x81,0x18,0x20,0x43,0x08,0x11,0x80,0x11 } },
-{  16, 0xdd70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x60,0x04,0x58,0x01,0x56,0x00 } },
-{  16, 0xdd80, 0, {0x55,0x80,0x15,0x60,0x04,0x58,0x01,0x16,0x00,0x55,0x80,0x01,0x60,0x04,0x18,0x01 } },
-{  16, 0xdd90, 0, {0x56,0x00,0x45,0x80,0x11,0x60,0x04,0x58,0x01,0x16,0x00,0x41,0x80,0x11,0x40,0x31 } },
-{  16, 0xdda0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x06,0x01,0x41,0x80,0x50,0x60 } },
-{  16, 0xddb0, 0, {0x14,0x18,0x05,0x06,0x01,0x41,0x80,0x50,0x60,0x04,0x18,0x05,0x06,0x00,0x41,0x80 } },
-{  16, 0xddc0, 0, {0x10,0x60,0x14,0x18,0x05,0x06,0x01,0x41,0x80,0x50,0x60,0x14,0x18,0x05,0x00,0x20 } },
-{  16, 0xddd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x80,0x40,0x20 } },
-{  16, 0xdde0, 0, {0x10,0x48,0x04,0x12,0x01,0x00,0x80,0x41,0x20,0x10,0x08,0x04,0x02,0x01,0x04,0x80 } },
-{  16, 0xddf0, 0, {0x40,0x20,0x50,0x48,0x04,0x12,0x01,0x00,0x84,0x40,0x20,0x10,0x08,0x04,0x00,0x20 } },
-{  16, 0xde00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x46,0x03,0x51,0x80,0xd4,0x60 } },
-{  16, 0xde10, 0, {0x30,0x18,0x0d,0x46,0x03,0x51,0x80,0xd5,0x60,0x35,0x18,0x0d,0x46,0x03,0x05,0x80 } },
-{  16, 0xde20, 0, {0xd4,0x60,0x15,0x18,0x0d,0x46,0x03,0x11,0x80,0xd4,0x60,0x35,0x18,0x0d,0x40,0x31 } },
-{  16, 0xde30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x46,0x05,0x71,0x80,0x5c,0x60 } },
-{  16, 0xde40, 0, {0x97,0x18,0x15,0xc6,0x05,0x71,0x81,0x5c,0x20,0x57,0x18,0x15,0xc6,0x03,0x70,0x81 } },
-{  16, 0xde50, 0, {0x5c,0x60,0x57,0x18,0x11,0xc6,0x05,0x31,0x81,0x5c,0x60,0x77,0x18,0x15,0xc0,0x31 } },
-{  16, 0xde60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x46,0x03,0x71,0x80,0xdc,0x60 } },
-{  16, 0xde70, 0, {0x37,0x18,0x0d,0xc6,0x03,0x71,0x80,0xdd,0x60,0x37,0x18,0x05,0xc6,0x01,0x75,0x81 } },
-{  16, 0xde80, 0, {0xdc,0x60,0x37,0x18,0x0d,0xc6,0x03,0x71,0x84,0x5c,0x60,0x17,0x18,0x19,0xc0,0x11 } },
-{  16, 0xde90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x46,0x05,0x71,0x81,0x5c,0x60 } },
-{  16, 0xdea0, 0, {0x57,0x18,0x14,0x86,0x05,0x71,0x81,0x5c,0x60,0x57,0x18,0x05,0xc6,0x04,0x31,0x81 } },
-{  16, 0xdeb0, 0, {0x5c,0x60,0x57,0x18,0x15,0xc6,0x05,0x71,0x80,0x5c,0x60,0x43,0x18,0x15,0xc0,0x11 } },
-{  16, 0xdec0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x20,0x80,0x48,0x20 } },
-{  16, 0xded0, 0, {0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x70,0x80 } },
-{  16, 0xdee0, 0, {0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x17,0x08,0x04,0x80,0x00 } },
-{  16, 0xdef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x01,0x61,0x80,0x58,0x60 } },
-{  16, 0xdf00, 0, {0x16,0x18,0x41,0x86,0x01,0x61,0x80,0x18,0x60,0x06,0x3c,0x05,0x86,0x04,0x61,0x80 } },
-{  16, 0xdf10, 0, {0x18,0x60,0x16,0x18,0x01,0x86,0x00,0x61,0x80,0x58,0x60,0x56,0x18,0x15,0x80,0x10 } },
-{  16, 0xdf20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x40,0x05,0x70,0x01,0x5c,0x00 } },
-{  16, 0xdf30, 0, {0x57,0x00,0x15,0xc0,0x04,0x70,0x01,0x5c,0x00,0x57,0x00,0x10,0xc0,0x04,0x70,0x00 } },
-{  16, 0xdf40, 0, {0x1c,0x00,0x47,0x00,0x11,0xc0,0x04,0x70,0x01,0x5c,0x00,0x47,0x00,0x01,0xc0,0x11 } },
-{  16, 0xdf50, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x42,0x00,0x60,0x80,0x18,0x20 } },
-{  16, 0xdf60, 0, {0x06,0x08,0x01,0x82,0x00,0x60,0x80,0x18,0x20,0x06,0x08,0x00,0x82,0x00,0x60,0x80 } },
-{  16, 0xdf70, 0, {0x18,0x20,0x06,0x08,0x01,0x82,0x00,0x60,0x80,0x18,0x20,0x06,0x08,0x01,0x80,0x11 } },
-{  16, 0xdf80, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x42,0x04,0x20,0x81,0x08,0x20 } },
-{  16, 0xdf90, 0, {0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x42,0x08,0x11,0x82,0x04,0x20,0x80 } },
-{  16, 0xdfa0, 0, {0x08,0x20,0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x42,0x08,0x00,0x80,0x11 } },
-{  16, 0xdfb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x42,0x05,0x40,0x81,0x50,0x20 } },
-{  16, 0xdfc0, 0, {0x54,0x08,0x15,0x02,0x05,0x40,0x81,0x10,0x20,0x54,0x0c,0x15,0x42,0x00,0x40,0x81 } },
-{  16, 0xdfd0, 0, {0x50,0x20,0x44,0x08,0x11,0x02,0x05,0x40,0x81,0x10,0x20,0x14,0x08,0x05,0x00,0x11 } },
-{  16, 0xdfe0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x01,0x50,0xc0,0x54,0x30 } },
-{  16, 0xdff0, 0, {0x15,0x08,0x05,0x42,0x01,0x50,0xc0,0x54,0x30,0x15,0x0c,0x05,0x43,0x01,0x50,0xc0 } },
-{  16, 0xe000, 0, {0x54,0x30,0x15,0x0c,0x05,0x42,0x01,0x50,0xc0,0x54,0x30,0x15,0x0c,0x05,0x40,0x10 } },
-{  16, 0xe010, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x00,0x10,0x80 } },
-{  16, 0xe020, 0, {0x04,0x20,0x01,0x88,0x00,0x62,0x00,0x10,0x80,0x04,0x00,0x11,0x08,0x00,0x42,0x00 } },
-{  16, 0xe030, 0, {0x10,0x80,0x04,0x20,0x01,0x08,0x00,0x42,0x01,0x10,0x80,0x04,0x20,0x01,0x00,0x00 } },
-{  16, 0xe040, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x42,0x02,0x00,0x80,0x80,0x20 } },
-{  16, 0xe050, 0, {0x20,0x08,0x08,0x02,0x02,0x20,0x80,0x80,0x20,0x20,0x28,0x00,0x02,0x02,0x00,0x80 } },
-{  16, 0xe060, 0, {0x80,0x20,0x20,0x0a,0x08,0x02,0x02,0x00,0x80,0x00,0x20,0x20,0x08,0x08,0x00,0x11 } },
-{  16, 0xe070, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x40,0x05,0x60,0x01,0x58,0x00 } },
-{  16, 0xe080, 0, {0x56,0x00,0x05,0x80,0x05,0x60,0x01,0x58,0x08,0x56,0x00,0x15,0x80,0x07,0x60,0x02 } },
-{  16, 0xe090, 0, {0x58,0x00,0x56,0x40,0x15,0x80,0x05,0x60,0x03,0x18,0x00,0x76,0x00,0x15,0x80,0x11 } },
-{  16, 0xe0a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x03,0x60,0x00,0xd8,0x00 } },
-{  16, 0xe0b0, 0, {0x36,0x00,0x0d,0x80,0x01,0x60,0x00,0xd8,0x0a,0x36,0x00,0x0d,0x80,0x05,0x70,0x09 } },
-{  16, 0xe0c0, 0, {0xd8,0x01,0x36,0x00,0x0d,0x80,0x03,0x60,0x00,0xd8,0x00,0x57,0x00,0x0d,0x80,0x00 } },
-{  16, 0xe0d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x30,0x01,0x0c,0x00 } },
-{  16, 0xe0e0, 0, {0x43,0x00,0x10,0xc0,0x00,0x30,0x01,0x0c,0x00,0x43,0x20,0x10,0xc0,0x04,0x60,0x01 } },
-{  16, 0xe0f0, 0, {0x0c,0x00,0x43,0x40,0x50,0xc1,0x04,0x30,0x01,0x0c,0x00,0x46,0x00,0x10,0xc0,0x00 } },
-{  16, 0xe100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0c,0x00 } },
-{  16, 0xe110, 0, {0x01,0x00,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0xd0,0x00,0x20,0x00 } },
-{  16, 0xe120, 0, {0x0c,0x00,0x03,0x40,0x00,0xc0,0x00,0x30,0x00,0x0d,0x00,0x02,0x00,0x00,0xc0,0x00 } },
-{  16, 0xe130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,0x31,0x40,0x4c,0x50 } },
-{  16, 0xe140, 0, {0x13,0x10,0x04,0xc4,0x01,0x31,0x40,0x4c,0x50,0x13,0x14,0x04,0xc5,0x11,0x31,0x41 } },
-{  16, 0xe150, 0, {0x4c,0x50,0x13,0x14,0x04,0xc5,0x01,0x31,0x40,0x4c,0x50,0x13,0x14,0x04,0xc0,0x00 } },
-{  16, 0xe160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x05,0x68,0xc1,0x5a,0x30 } },
-{  16, 0xe170, 0, {0x56,0x8c,0x11,0xa3,0x04,0x68,0xc1,0x1a,0x30,0x56,0x8c,0x11,0xa3,0x05,0x68,0xc0 } },
-{  16, 0xe180, 0, {0x5a,0x30,0x46,0x8c,0x11,0xa3,0x04,0x68,0xc1,0x5a,0x30,0x16,0x8c,0x15,0x80,0x00 } },
-{  16, 0xe190, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x00 } },
-{  16, 0xe1a0, 0, {0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x00,0x02,0x20,0x00,0x90,0x00,0x20,0x00 } },
-{  16, 0xe1b0, 0, {0x08,0x00,0x02,0x40,0x00,0x80,0x00,0x20,0x00,0x09,0x00,0x02,0x00,0x00,0x80,0x00 } },
-{  16, 0xe1c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x44,0x62,0x01,0x18,0x84 } },
-{  16, 0xe1d0, 0, {0x46,0x21,0x11,0x88,0x44,0x62,0x11,0x18,0x84,0x46,0x01,0x11,0x88,0x44,0x62,0x10 } },
-{  16, 0xe1e0, 0, {0x18,0x84,0x46,0x21,0x11,0x88,0x44,0x62,0x11,0x18,0x84,0x06,0x21,0x11,0x80,0x00 } },
-{  16, 0xe1f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x50,0x11,0x54,0x04 } },
-{  16, 0xe200, 0, {0x55,0x01,0x11,0x40,0x45,0x50,0x11,0x14,0x00,0x45,0x01,0x11,0x40,0x44,0x50,0x00 } },
-{  16, 0xe210, 0, {0x14,0x04,0x45,0x00,0x15,0x40,0x44,0x50,0x11,0x14,0x04,0x55,0x01,0x11,0x40,0x00 } },
-{  16, 0xe220, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x21,0x42,0x08,0x50,0x82 } },
-{  16, 0xe230, 0, {0x14,0x20,0x85,0x08,0x21,0x42,0x08,0x50,0x82,0x04,0x20,0x85,0x08,0x21,0x42,0x08 } },
-{  16, 0xe240, 0, {0x50,0x82,0x14,0x20,0x05,0x08,0x21,0x42,0x08,0x50,0x82,0x14,0x20,0x85,0x00,0x00 } },
-{  16, 0xe250, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x01,0x02,0x80,0x40,0xa0 } },
-{  16, 0xe260, 0, {0x10,0x28,0x04,0x0a,0x01,0x02,0x80,0x40,0xa0,0x10,0x28,0x40,0x0a,0x01,0x02,0x80 } },
-{  16, 0xe270, 0, {0x40,0xa0,0x10,0x28,0x44,0x0a,0x01,0x02,0x80,0x40,0xa0,0x10,0x28,0x04,0x00,0x00 } },
-{  16, 0xe280, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x03,0x53,0x00,0xd4,0xc0 } },
-{  16, 0xe290, 0, {0x35,0x30,0x0d,0x4c,0x01,0x53,0x00,0xd4,0xc0,0x35,0x10,0x0c,0x4c,0x03,0x53,0x00 } },
-{  16, 0xe2a0, 0, {0xd4,0xc0,0x35,0x30,0x0d,0x4c,0x03,0x53,0x00,0xd4,0xc0,0x35,0x30,0x0d,0x40,0x00 } },
-{  16, 0xe2b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x72,0x01,0x5c,0x80 } },
-{  16, 0xe2c0, 0, {0x17,0x20,0x05,0xc8,0x06,0x72,0x01,0x5c,0x80,0x57,0x20,0x15,0xc8,0x02,0x72,0x01 } },
-{  16, 0xe2d0, 0, {0x5c,0x80,0x57,0x20,0x15,0xc8,0x05,0x72,0x01,0x5c,0x80,0x37,0x20,0x11,0xc0,0x00 } },
-{  16, 0xe2e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x18,0x40,0xc6,0x12,0x31 } },
-{  16, 0xe2f0, 0, {0x84,0x8c,0x21,0x23,0x08,0x48,0xc6,0x12,0x30,0x84,0x0c,0x61,0x23,0x10,0x48,0xc2 } },
-{  16, 0xe300, 0, {0x12,0x31,0x84,0x8c,0x01,0x23,0x08,0x48,0xc6,0x12,0x31,0x04,0x8c,0x61,0x00,0x00 } },
-{  16, 0xe310, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x4f,0xff,0xd3,0xff } },
-{  16, 0xe320, 0, {0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff } },
-{  16, 0xe330, 0, {0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x00,0x00 } },
-{  16, 0xe340, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xe350, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xe360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xe370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xdb,0x0f,0xb6,0xc2,0xcd } },
-{  16, 0xe380, 0, {0xb0,0xb3,0x6c,0x2c,0xdb,0x0b,0x36,0xc2,0xdf,0xb0,0xb3,0x6c,0x2c,0xdb,0x0b,0x7e } },
-{  16, 0xe390, 0, {0xc2,0xcd,0xb0,0xb7,0xfd,0x2c,0xdb,0x0b,0x36,0xc2,0xcd,0xb0,0xb3,0x6c,0x00,0x00 } },
-{  16, 0xe3a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x3c,0x4f,0xcf,0x13,0x33 } },
-{  16, 0xe3b0, 0, {0xc4,0xcc,0xf1,0x33,0x3c,0x4c,0xcf,0x13,0x3f,0xc4,0xcc,0xf1,0x33,0x3c,0x4c,0xff } },
-{  16, 0xe3c0, 0, {0x13,0x33,0xc4,0xcf,0xfd,0x33,0x3c,0x4c,0xcf,0x13,0x33,0xc4,0xcc,0xf1,0x00,0x00 } },
-{  16, 0xe3d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3b,0x7e,0x4e,0xdf,0x93,0xb7 } },
-{  16, 0xe3e0, 0, {0xe4,0xec,0x79,0x3b,0x1e,0x4e,0xdf,0x93,0xbf,0xe4,0x8d,0xf9,0x3b,0x78,0x4e,0xff } },
-{  16, 0xe3f0, 0, {0x93,0xb7,0xe4,0xed,0xfd,0x3b,0x1e,0x4e,0xdf,0x93,0xb7,0x84,0xed,0xf9,0x00,0x00 } },
-{  16, 0xe400, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x70,0x40,0x9c,0x10 } },
-{  16, 0xe410, 0, {0x27,0x1c,0x09,0xc1,0x01,0x30,0x40,0x1c,0x10,0x67,0x04,0x09,0xc1,0x02,0x70,0x41 } },
-{  16, 0xe420, 0, {0x9c,0x11,0x07,0x14,0x01,0xc1,0x02,0x70,0x40,0x9c,0x50,0x07,0x1c,0x01,0xc0,0x00 } },
-{  16, 0xe430, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x05,0x71,0x01,0x5c,0x40 } },
-{  16, 0xe440, 0, {0x57,0x10,0x55,0xc4,0x01,0x31,0x00,0x5c,0x40,0x57,0x10,0x15,0xc4,0x05,0x71,0x01 } },
-{  16, 0xe450, 0, {0xdc,0x40,0x17,0x18,0x1d,0xc4,0x05,0x71,0x05,0x5c,0x40,0x57,0x10,0x1d,0xc0,0x00 } },
-{  16, 0xe460, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x20,0x80,0x48,0x20 } },
-{  16, 0xe470, 0, {0x12,0x00,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80 } },
-{  16, 0xe480, 0, {0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x60,0x12,0x08,0x04,0x80,0x00 } },
-{  16, 0xe490, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00 } },
-{  16, 0xe4a0, 0, {0x06,0x00,0x41,0x80,0x00,0x60,0x00,0x18,0x00,0x46,0x00,0x01,0x80,0x00,0x60,0x00 } },
-{  16, 0xe4b0, 0, {0x10,0x00,0x06,0x10,0x01,0x80,0x00,0x60,0x00,0x18,0x20,0x46,0x10,0x01,0x80,0x00 } },
-{  16, 0xe4c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x72,0x01,0x1c,0x80 } },
-{  16, 0xe4d0, 0, {0x47,0x20,0x11,0xc8,0x04,0x72,0x01,0x1c,0x80,0x07,0x20,0x11,0xc8,0x04,0x73,0x00 } },
-{  16, 0xe4e0, 0, {0x1c,0x80,0x47,0x20,0x11,0xcc,0x04,0x72,0x01,0x1c,0x80,0x47,0x20,0x11,0xc0,0x00 } },
-{  16, 0xe4f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00 } },
-{  16, 0xe500, 0, {0x06,0x00,0x01,0x84,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x40 } },
-{  16, 0xe510, 0, {0x18,0x00,0x06,0x04,0x01,0x81,0x00,0x60,0x00,0x18,0x00,0x06,0x14,0x01,0x80,0x00 } },
-{  16, 0xe520, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x22,0x01,0x08,0x80 } },
-{  16, 0xe530, 0, {0x42,0x70,0x10,0x8c,0x04,0x22,0x01,0x08,0xc0,0x02,0x20,0x10,0x88,0x04,0x22,0x00 } },
-{  16, 0xe540, 0, {0x08,0x80,0x42,0x50,0x10,0x08,0x04,0x22,0x01,0x09,0x00,0x42,0x40,0x10,0x80,0x00 } },
-{  16, 0xe550, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x04,0x4a,0x81,0x12,0xa0 } },
-{  16, 0xe560, 0, {0x44,0xa8,0x11,0x2a,0x04,0x4a,0x81,0x12,0xa0,0x04,0xa8,0x11,0x2a,0x04,0x4b,0x80 } },
-{  16, 0xe570, 0, {0x12,0xa0,0x44,0x88,0x01,0x2e,0x04,0x4a,0x81,0x12,0x20,0x04,0x98,0x01,0x00,0x00 } },
-{  16, 0xe580, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x0e,0x00,0x53,0x00,0x14,0xc0 } },
-{  16, 0xe590, 0, {0x05,0x30,0x01,0x4c,0x00,0x53,0x00,0x14,0xe0,0x05,0x30,0x01,0x4c,0x00,0x53,0x00 } },
-{  16, 0xe5a0, 0, {0x04,0xc0,0x05,0x30,0x00,0x4c,0x00,0x03,0x00,0x14,0xc0,0x05,0x30,0x00,0x40,0x10 } },
-{  16, 0xe5b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x04,0x00,0x40,0x00,0x10,0x00 } },
-{  16, 0xe5c0, 0, {0x04,0x58,0x01,0x04,0x00,0x40,0x00,0x10,0x00,0x04,0x00,0x01,0x00,0x00,0x41,0x00 } },
-{  16, 0xe5d0, 0, {0x04,0x00,0x44,0x58,0x10,0x44,0x00,0x00,0x00,0x11,0x80,0x04,0x50,0x10,0x40,0x30 } },
-{  16, 0xe5e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x40,0x02,0x00,0x00,0x80,0x00 } },
-{  16, 0xe5f0, 0, {0x20,0x00,0x08,0x00,0x40,0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x00,0x02,0x00,0x00 } },
-{  16, 0xe600, 0, {0x84,0x00,0x00,0x00,0x08,0x40,0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x40,0x30 } },
-{  16, 0xe610, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x40,0x00,0x60,0x01,0x18,0x00 } },
-{  16, 0xe620, 0, {0x46,0x00,0x01,0x80,0x06,0x60,0x01,0x98,0x00,0x46,0x00,0x11,0x80,0x04,0x60,0x01 } },
-{  16, 0xe630, 0, {0x18,0x00,0x46,0x00,0x11,0x80,0x04,0x20,0x01,0x18,0x00,0x66,0x00,0x11,0x80,0x30 } },
-{  16, 0xe640, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x01,0x40,0x00,0x60,0x00,0x98,0x00 } },
-{  16, 0xe650, 0, {0x26,0x00,0x09,0x80,0x02,0x60,0x01,0x98,0x00,0x06,0x00,0x0c,0x80,0x02,0x60,0x00 } },
-{  16, 0xe660, 0, {0x18,0x00,0x06,0x00,0x01,0x80,0x02,0x60,0x00,0x98,0x80,0x06,0x00,0x01,0x82,0x00 } },
-{  16, 0xe670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x00,0x30,0x81,0x0c,0x20 } },
-{  16, 0xe680, 0, {0x43,0x08,0x10,0xc2,0x24,0x30,0x81,0x8c,0x20,0x03,0x08,0x10,0xc2,0x04,0x20,0x80 } },
-{  16, 0xe690, 0, {0x0c,0x20,0x03,0x08,0x18,0xc2,0x04,0x30,0x81,0x0c,0x20,0x43,0x08,0x18,0xc0,0x11 } },
-{  16, 0xe6a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x30,0x00,0x0c,0x00 } },
-{  16, 0xe6b0, 0, {0x03,0x00,0x00,0xc0,0x40,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0x80,0x00,0x30,0x00 } },
-{  16, 0xe6c0, 0, {0x0c,0x00,0x03,0x20,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x20,0x00,0xc0,0x00 } },
-{  16, 0xe6d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x02,0x10,0x30,0x80,0x0c,0x20 } },
-{  16, 0xe6e0, 0, {0x03,0x08,0x00,0xc2,0x00,0x30,0x80,0x0c,0x20,0x03,0x08,0x00,0xc2,0x01,0x20,0x80 } },
-{  16, 0xe6f0, 0, {0x0c,0x20,0x03,0x2c,0x00,0xc2,0x00,0x30,0x80,0x0c,0x30,0x43,0x2c,0x00,0xc0,0x00 } },
-{  16, 0xe700, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x04,0x60,0x81,0x18,0x20 } },
-{  16, 0xe710, 0, {0x46,0x08,0x11,0x82,0x04,0x60,0x80,0x18,0x20,0x46,0x08,0x11,0x82,0x04,0x60,0x81 } },
-{  16, 0xe720, 0, {0x18,0x20,0x46,0x0c,0x11,0xc2,0x04,0x60,0x81,0x18,0x30,0x46,0x0c,0x11,0xc0,0x11 } },
-{  16, 0xe730, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x42,0x00,0x20,0x80,0x08,0x20 } },
-{  16, 0xe740, 0, {0x02,0x28,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x02,0x08,0x00,0x82,0x00,0x20,0x80 } },
-{  16, 0xe750, 0, {0x08,0x20,0x02,0x08,0x01,0x82,0x00,0x20,0x80,0x08,0x20,0x03,0x08,0x01,0x80,0x00 } },
-{  16, 0xe760, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x01,0x42,0x04,0x60,0x81,0x18,0x20 } },
-{  16, 0xe770, 0, {0x46,0x28,0x11,0x82,0x04,0x60,0x80,0x18,0x20,0x46,0x08,0x11,0x82,0x04,0x60,0x81 } },
-{  16, 0xe780, 0, {0x18,0x20,0x46,0x08,0x10,0x82,0x04,0x60,0x81,0x18,0x20,0x43,0x08,0x10,0x80,0x00 } },
-{  16, 0xe790, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x40,0x04,0x50,0x01,0x14,0x00 } },
-{  16, 0xe7a0, 0, {0x45,0x00,0x11,0x40,0x25,0x00,0x00,0x14,0x00,0x45,0x00,0x11,0x40,0x04,0x50,0x01 } },
-{  16, 0xe7b0, 0, {0x14,0x00,0x45,0x00,0x00,0x40,0x04,0x50,0x01,0x40,0x00,0x01,0x00,0x00,0x42,0x11 } },
-{  16, 0xe7c0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x06,0x00,0x41,0x80,0x10,0x60 } },
-{  16, 0xe7d0, 0, {0x04,0x18,0x01,0x06,0x00,0x41,0x80,0x10,0x60,0x04,0x18,0x01,0x06,0x00,0x41,0x80 } },
-{  16, 0xe7e0, 0, {0x10,0x60,0x04,0x18,0x01,0x06,0x00,0x41,0x80,0x10,0x60,0x04,0x18,0x01,0x00,0x00 } },
-{  16, 0xe7f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x02,0x05,0x00,0x80,0x40,0x21 } },
-{  16, 0xe800, 0, {0x10,0x08,0x04,0x00,0x01,0x00,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x00,0x80 } },
-{  16, 0xe810, 0, {0x40,0x20,0x50,0x08,0x14,0x02,0x11,0x00,0x84,0x40,0x20,0x10,0x08,0x14,0x00,0x00 } },
-{  16, 0xe820, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x46,0x01,0x51,0x80,0xd4,0x60 } },
-{  16, 0xe830, 0, {0x35,0x18,0x0d,0x46,0x03,0x51,0x80,0xd4,0x60,0x15,0x18,0x0d,0x46,0x03,0x51,0x80 } },
-{  16, 0xe840, 0, {0x54,0x60,0x15,0x18,0x0d,0x46,0x03,0x51,0x80,0xd4,0x60,0x35,0x18,0x0d,0x40,0x11 } },
-{  16, 0xe850, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x46,0x04,0x71,0x81,0x1c,0x60 } },
-{  16, 0xe860, 0, {0x45,0x18,0x11,0xd6,0x04,0x71,0x81,0x1c,0x60,0x67,0x18,0x11,0xc6,0x04,0x71,0x81 } },
-{  16, 0xe870, 0, {0x9c,0x60,0x47,0x18,0x11,0xc6,0x04,0x71,0x81,0x1c,0x60,0x67,0x18,0x11,0xc0,0x00 } },
-{  16, 0xe880, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x46,0x02,0x71,0x80,0x9c,0x60 } },
-{  16, 0xe890, 0, {0x27,0x18,0x09,0xc6,0x00,0x71,0x80,0x9c,0x60,0x67,0x18,0x09,0xc6,0x02,0x71,0x80 } },
-{  16, 0xe8a0, 0, {0x9c,0x61,0x27,0x18,0x01,0xc6,0x02,0x71,0x80,0x9c,0x60,0x07,0x18,0x01,0xc0,0x00 } },
-{  16, 0xe8b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x45,0x46,0x05,0x71,0x81,0x5c,0x60 } },
-{  16, 0xe8c0, 0, {0x57,0x18,0x55,0xd6,0x01,0x71,0x81,0x5c,0x60,0x57,0x18,0x15,0xc6,0x05,0x71,0x81 } },
-{  16, 0xe8d0, 0, {0x5c,0x60,0x57,0x18,0x18,0xc6,0x05,0x71,0x81,0x5c,0x60,0x43,0x18,0x18,0x82,0x11 } },
-{  16, 0xe8e0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x52,0x01,0x20,0x80,0x48,0x20 } },
-{  16, 0xe8f0, 0, {0x12,0x48,0x04,0x90,0x01,0x20,0x80,0x49,0x20,0x12,0x08,0x04,0x82,0x01,0x24,0x80 } },
-{  16, 0xe900, 0, {0x48,0x20,0x12,0x48,0x00,0x92,0x01,0x20,0x80,0x48,0x20,0x17,0x48,0x04,0x80,0x01 } },
-{  16, 0xe910, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x06,0x00,0x61,0x80,0x18,0x60 } },
-{  16, 0xe920, 0, {0x06,0x3c,0x01,0x86,0x00,0x61,0x80,0x18,0x60,0x46,0x18,0x01,0x86,0x00,0x61,0x80 } },
-{  16, 0xe930, 0, {0x18,0x60,0x06,0x18,0x01,0x86,0x00,0x61,0x80,0x18,0x60,0x46,0x18,0x01,0x80,0x01 } },
-{  16, 0xe940, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x60,0x04,0x78,0x01,0x1e,0x00 } },
-{  16, 0xe950, 0, {0x47,0x80,0x11,0xe0,0x24,0x78,0x01,0x1e,0x00,0x07,0x80,0x11,0xe0,0x04,0x78,0x01 } },
-{  16, 0xe960, 0, {0x1e,0x00,0x47,0x80,0x11,0xe0,0x04,0x38,0x01,0x1e,0x00,0x47,0x80,0x11,0xc0,0x11 } },
-{  16, 0xe970, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x12,0x00,0x60,0x80,0x18,0x20 } },
-{  16, 0xe980, 0, {0x06,0x48,0x01,0x92,0x00,0x60,0x80,0x19,0x20,0x06,0x08,0x01,0x82,0x00,0x64,0x80 } },
-{  16, 0xe990, 0, {0x18,0x20,0x06,0x48,0x01,0x93,0x00,0x20,0x80,0x18,0x20,0x06,0x48,0x01,0x80,0x00 } },
-{  16, 0xe9a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x42,0x04,0x20,0x81,0x08,0x20 } },
-{  16, 0xe9b0, 0, {0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x02,0x08,0x10,0x82,0x04,0x20,0x81 } },
-{  16, 0xe9c0, 0, {0x08,0x20,0x42,0x08,0x10,0x8a,0x04,0x60,0x81,0x08,0x20,0x42,0x08,0x10,0x80,0x00 } },
-{  16, 0xe9d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x04,0x40,0x81,0x10,0x20 } },
-{  16, 0xe9e0, 0, {0x44,0x08,0x11,0x02,0x04,0x40,0x81,0x10,0x20,0x04,0x08,0x11,0x02,0x04,0x40,0x81 } },
-{  16, 0xe9f0, 0, {0x10,0x21,0x44,0x08,0x01,0x02,0x04,0x50,0x81,0x10,0x20,0x04,0x08,0x01,0x00,0x11 } },
-{  16, 0xea00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,0x50,0xc0,0x14,0x30 } },
-{  16, 0xea10, 0, {0x05,0x0c,0x01,0x43,0x00,0x50,0xc0,0x14,0x30,0x05,0x0c,0x01,0x43,0x00,0x50,0x80 } },
-{  16, 0xea20, 0, {0x14,0x30,0x05,0x08,0x01,0x4a,0x00,0x50,0xc0,0x14,0x30,0x05,0x08,0x01,0x40,0x00 } },
-{  16, 0xea30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x00,0x42,0x00,0x10,0x80 } },
-{  16, 0xea40, 0, {0x04,0x20,0x01,0x08,0x00,0x42,0x00,0x10,0x80,0x04,0x20,0x01,0x08,0x00,0x42,0x00 } },
-{  16, 0xea50, 0, {0x10,0x80,0x04,0x20,0x11,0x00,0x00,0x42,0x00,0x10,0x80,0x04,0x20,0x11,0x00,0x10 } },
-{  16, 0xea60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x02,0x00,0x80,0x80,0x20 } },
-{  16, 0xea70, 0, {0x20,0x08,0x08,0x02,0x00,0x00,0x80,0x80,0x20,0x20,0x08,0x08,0x02,0x02,0x00,0x80 } },
-{  16, 0xea80, 0, {0x80,0x20,0x20,0x08,0x08,0x02,0x02,0x00,0x80,0x80,0x20,0x20,0x08,0x08,0x00,0x11 } },
-{  16, 0xea90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x00,0x60,0x01,0x18,0x00 } },
-{  16, 0xeaa0, 0, {0x46,0x00,0x11,0x80,0x06,0x60,0x01,0x18,0x00,0x46,0x00,0x11,0x80,0x04,0x60,0x01 } },
-{  16, 0xeab0, 0, {0x18,0x00,0x46,0x00,0x11,0x80,0x04,0x60,0x01,0x18,0x00,0x66,0x00,0x11,0x80,0x10 } },
-{  16, 0xeac0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x02,0x64,0x00,0x98,0x00 } },
-{  16, 0xead0, 0, {0x26,0x00,0x09,0x90,0x06,0x60,0x01,0x98,0x00,0x26,0x40,0x09,0x80,0x02,0x60,0x00 } },
-{  16, 0xeae0, 0, {0x98,0x00,0x26,0x00,0x00,0x90,0x02,0x60,0x00,0x98,0x00,0x07,0x00,0x01,0x80,0x00 } },
-{  16, 0xeaf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x60,0x04,0x38,0x05,0x0e,0x00 } },
-{  16, 0xeb00, 0, {0x43,0x80,0x10,0xe0,0x44,0x38,0x01,0x0e,0x00,0x43,0x80,0x10,0xe0,0x04,0x38,0x01 } },
-{  16, 0xeb10, 0, {0x0e,0x00,0x43,0x80,0x18,0xa0,0x04,0x38,0x01,0x0e,0x00,0x46,0x80,0x18,0x80,0x11 } },
-{  16, 0xeb20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,0x30,0x40,0x0c,0x10 } },
-{  16, 0xeb30, 0, {0x03,0x04,0x00,0xc5,0x00,0x30,0x40,0x0c,0x10,0x03,0x14,0x00,0xc1,0x00,0x30,0x40 } },
-{  16, 0xeb40, 0, {0x0c,0x10,0x03,0x04,0x00,0x87,0x40,0x30,0x40,0x0c,0x10,0x02,0x04,0x00,0x80,0x00 } },
-{  16, 0xeb50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x05,0x00,0x35,0x40,0x0c,0x50 } },
-{  16, 0xeb60, 0, {0x03,0x14,0x00,0xd5,0x04,0x31,0x41,0x0c,0x50,0x03,0x5c,0x00,0xc5,0x00,0x31,0x00 } },
-{  16, 0xeb70, 0, {0x0c,0x50,0x03,0x10,0x00,0x94,0x00,0x31,0x40,0x0c,0x50,0x43,0x10,0x00,0xc2,0x00 } },
-{  16, 0xeb80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x43,0x05,0x20,0xc1,0x18,0x30 } },
-{  16, 0xeb90, 0, {0x46,0x0c,0x11,0x97,0x00,0x60,0xc0,0x18,0x30,0x46,0x1c,0x11,0x83,0x04,0x60,0xc1 } },
-{  16, 0xeba0, 0, {0x18,0x30,0x52,0x0c,0x11,0x87,0x04,0x60,0xc1,0x18,0x30,0x46,0x0c,0x11,0x80,0x11 } },
-{  16, 0xebb0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x21,0x40,0x08,0x00 } },
-{  16, 0xebc0, 0, {0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x00,0x02,0x00,0x00,0x80,0x00,0x20,0x00 } },
-{  16, 0xebd0, 0, {0x08,0x00,0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x00,0x02,0x00,0x00,0x80,0x00 } },
-{  16, 0xebe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x48,0x44,0x22,0x01,0x18,0x84 } },
-{  16, 0xebf0, 0, {0x46,0x21,0x11,0x98,0x00,0x62,0x10,0x18,0x84,0x44,0x20,0x11,0x88,0x44,0x62,0x11 } },
-{  16, 0xec00, 0, {0x18,0x84,0x42,0x21,0x11,0x80,0x44,0x62,0x11,0x18,0x84,0x46,0x21,0x11,0x80,0x00 } },
-{  16, 0xec10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x40,0x04,0x50,0x11,0x14,0x04 } },
-{  16, 0xec20, 0, {0x45,0x00,0x11,0x41,0x00,0x50,0x10,0x14,0x00,0x45,0x01,0x11,0x40,0x44,0x50,0x11 } },
-{  16, 0xec30, 0, {0x14,0x04,0x45,0x01,0x01,0x40,0x44,0x50,0x11,0x14,0x04,0x05,0x01,0x01,0x40,0x11 } },
-{  16, 0xec40, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x20,0x42,0x08,0x10,0x82 } },
-{  16, 0xec50, 0, {0x04,0x20,0x01,0x08,0x20,0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x42,0x08 } },
-{  16, 0xec60, 0, {0x10,0x82,0x04,0x22,0x81,0x08,0x20,0x52,0x08,0x10,0x8a,0x04,0x22,0x81,0x00,0x00 } },
-{  16, 0xec70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x01,0x02,0x84,0x40,0xa1 } },
-{  16, 0xec80, 0, {0x10,0x28,0x00,0x0a,0x01,0x02,0x80,0x40,0xa0,0x10,0x28,0x04,0x0a,0x01,0x02,0x80 } },
-{  16, 0xec90, 0, {0x40,0xa0,0x10,0x2c,0x14,0x0a,0x00,0x02,0x80,0x40,0xb0,0x10,0x2c,0x14,0x00,0x00 } },
-{  16, 0xeca0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x4d,0x03,0x53,0x40,0xd4,0xd0 } },
-{  16, 0xecb0, 0, {0x35,0x30,0x0c,0x4d,0x03,0x53,0x40,0xd4,0xd0,0x35,0x34,0x0d,0x4d,0x03,0x53,0x40 } },
-{  16, 0xecc0, 0, {0xd4,0xd0,0x35,0x34,0x0d,0x4d,0x02,0x13,0x40,0xd4,0xd0,0x35,0x34,0x0d,0x40,0x11 } },
-{  16, 0xecd0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x08,0x04,0x72,0x01,0x1c,0x80 } },
-{  16, 0xece0, 0, {0x47,0x20,0x15,0xc8,0x04,0x72,0x01,0x1c,0x80,0x47,0x20,0x11,0xc8,0x04,0x72,0x11 } },
-{  16, 0xecf0, 0, {0x1c,0x80,0x47,0x26,0x11,0xc8,0x44,0x72,0x01,0x1c,0x90,0x67,0x26,0x11,0xc0,0x00 } },
-{  16, 0xed00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x08,0x40,0xc6,0x12,0x31 } },
-{  16, 0xed10, 0, {0x84,0x8c,0x01,0x03,0x08,0x48,0xc6,0x12,0x30,0x84,0x0c,0x61,0x23,0x18,0x48,0xc2 } },
-{  16, 0xed20, 0, {0x12,0x31,0x84,0x8c,0x01,0x03,0x08,0x48,0xc6,0x12,0x31,0x04,0x8c,0x01,0x00,0x00 } },
-{  16, 0xed30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x4f,0xff,0xd3,0xff } },
-{  16, 0xed40, 0, {0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff } },
-{  16, 0xed50, 0, {0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x00,0x00 } },
-{  16, 0xed60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xed70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xed80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xed90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0xfb,0x0f,0xb6,0xc2,0xcd } },
-{  16, 0xeda0, 0, {0xb0,0xb7,0xfd,0x3f,0xfb,0x0b,0x36,0xc2,0xdf,0xb0,0xfb,0x6c,0x2c,0xdb,0x0b,0x7e } },
-{  16, 0xedb0, 0, {0xc2,0xcd,0xb0,0xb7,0xfd,0x3f,0xfb,0x0b,0x36,0xc2,0xcd,0xf4,0xb7,0xfd,0x00,0x00 } },
-{  16, 0xedc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0xfc,0x4f,0xcf,0x13,0x33 } },
-{  16, 0xedd0, 0, {0xc4,0xcf,0xfd,0x3f,0xfc,0x4c,0xcf,0x13,0x3f,0xc4,0xfc,0xf1,0x33,0x3c,0x4c,0xff } },
-{  16, 0xede0, 0, {0x13,0x33,0xc4,0xcf,0xfd,0x3f,0xfc,0x4c,0xcf,0x13,0x33,0xf4,0xcf,0xfd,0x00,0x00 } },
-{  16, 0xedf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3b,0x7e,0x4e,0xdf,0x93,0xb7 } },
-{  16, 0xee00, 0, {0xe4,0xed,0xf9,0x3f,0xfe,0x4e,0xdf,0x93,0xb7,0xe4,0xed,0xf9,0x3b,0x7e,0x4e,0xc7 } },
-{  16, 0xee10, 0, {0x93,0xb7,0xe4,0xec,0x61,0x23,0x1e,0x4e,0xdf,0x93,0xb7,0x84,0xec,0x61,0x00,0x00 } },
-{  16, 0xee20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x24,0xa1,0x4a,0x24 } },
-{  16, 0xee30, 0, {0x63,0x01,0x14,0x02,0x44,0x00,0x81,0x0b,0x28,0x71,0x02,0x10,0x82,0x40,0x38,0x11 } },
-{  16, 0xee40, 0, {0x41,0x04,0x50,0x08,0x18,0x82,0x87,0x38,0x31,0xc3,0x2c,0x52,0x0a,0x10,0x00,0x00 } },
-{  16, 0xee50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x45,0x12,0x81,0x44,0x80 } },
-{  16, 0xee60, 0, {0x71,0x21,0x1c,0x0a,0x07,0x1a,0x81,0x02,0xa0,0x52,0x20,0x14,0x48,0x07,0x12,0x81 } },
-{  16, 0xee70, 0, {0xc6,0x80,0x60,0x20,0x08,0x88,0x47,0x02,0x01,0x4a,0x80,0x70,0x20,0x10,0x00,0x00 } },
-{  16, 0xee80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc5,0x2c,0x01,0x4a,0x00 } },
-{  16, 0xee90, 0, {0x52,0x09,0x1c,0x80,0x07,0x24,0x21,0x08,0x08,0x71,0x02,0x10,0x80,0x45,0x20,0xa1 } },
-{  16, 0xeea0, 0, {0x49,0x28,0x52,0x01,0x14,0xc0,0x45,0x00,0x91,0xc4,0x00,0x72,0x02,0x10,0x00,0x00 } },
-{  16, 0xeeb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x07,0x20,0x01,0xc1,0x00 } },
-{  16, 0xeec0, 0, {0x71,0x09,0x10,0x80,0x07,0x00,0x01,0x01,0x00,0x70,0x08,0x18,0x80,0x07,0x00,0x01 } },
-{  16, 0xeed0, 0, {0x89,0x20,0x52,0x01,0x0c,0x80,0x46,0x30,0x81,0x45,0x04,0x60,0x00,0x10,0x00,0x00 } },
-{  16, 0xeee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc2,0x02,0x20,0x00,0x88 } },
-{  16, 0xeef0, 0, {0x20,0x22,0x00,0x08,0xc2,0x22,0x80,0x40,0x88,0x02,0x22,0x00,0x08,0x82,0x0a,0xa0 } },
-{  16, 0xef00, 0, {0x0c,0xa8,0x02,0x22,0x00,0x08,0x80,0x0a,0x00,0x80,0x8c,0x02,0x22,0x00,0x00,0x00 } },
-{  16, 0xef10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x43,0x00,0x00,0x40,0x20 } },
-{  16, 0xef20, 0, {0x30,0x08,0x04,0x40,0x41,0x30,0x10,0xc8,0x00,0x00,0x00,0x00,0x02,0x03,0x00,0x10 } },
-{  16, 0xef30, 0, {0xc0,0x00,0x11,0x08,0x00,0xc2,0x43,0x10,0x80,0xc0,0x20,0x01,0x08,0x00,0x02,0x00 } },
-{  16, 0xef40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0xc3,0x0a,0x20,0xc1,0x8c } },
-{  16, 0xef50, 0, {0x12,0x22,0x04,0x88,0x01,0x36,0x20,0xc3,0x08,0x12,0x28,0x04,0x08,0x01,0x04,0x00 } },
-{  16, 0xef60, 0, {0x4a,0xa8,0x22,0x01,0x04,0xc8,0x41,0x26,0x30,0xc0,0x88,0x02,0x21,0x00,0x02,0x00 } },
-{  16, 0xef70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x0a,0x10,0xc1,0x80 } },
-{  16, 0xef80, 0, {0x32,0x21,0x0c,0x88,0x43,0x02,0x80,0x44,0x80,0x12,0x29,0x04,0x08,0x42,0x0a,0x90 } },
-{  16, 0xef90, 0, {0x8a,0x80,0x00,0x20,0x04,0x48,0x03,0x0a,0x10,0x82,0x80,0x00,0x20,0x00,0x02,0x00 } },
-{  16, 0xefa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x87,0x02,0xa1,0x80,0xac } },
-{  16, 0xefb0, 0, {0x43,0x29,0x14,0x8a,0x84,0x02,0xa1,0x00,0xac,0x41,0x20,0x10,0x08,0x06,0x26,0x31 } },
-{  16, 0xefc0, 0, {0x80,0xa4,0x60,0x20,0x14,0x4a,0x44,0x32,0x81,0x81,0xac,0x60,0x2a,0x18,0x02,0x00 } },
-{  16, 0xefd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x07,0x22,0x01,0xc5,0x80 } },
-{  16, 0xefe0, 0, {0x73,0x21,0x1c,0xc8,0x07,0x2a,0x01,0x0c,0x80,0x72,0x20,0x10,0x48,0x47,0x26,0x11 } },
-{  16, 0xeff0, 0, {0xc5,0x80,0x73,0x20,0x1c,0x88,0x07,0x2a,0x11,0x49,0x80,0x70,0x20,0x14,0x02,0x00 } },
-{  16, 0xf000, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x45,0x10,0x31,0xc9,0x0c } },
-{  16, 0xf010, 0, {0x73,0x02,0x1c,0xc0,0x47,0x04,0x01,0x0a,0x0c,0x51,0x0a,0x10,0x82,0x47,0x20,0x31 } },
-{  16, 0xf020, 0, {0xc8,0x00,0x72,0x02,0x1c,0x40,0x05,0x30,0x11,0xc4,0x00,0x72,0x01,0x18,0x02,0x00 } },
-{  16, 0xf030, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x10,0x06,0x24,0x01,0x45,0x04 } },
-{  16, 0xf040, 0, {0x51,0x81,0x18,0x90,0x47,0x14,0x01,0x04,0x04,0x71,0x88,0x10,0x12,0x05,0x34,0x01 } },
-{  16, 0xf050, 0, {0x44,0x04,0x51,0x40,0x18,0xd0,0x07,0x38,0x01,0xc4,0x04,0x52,0x01,0x14,0xc2,0x04 } },
-{  16, 0xf060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x00,0x21,0x89,0x0c } },
-{  16, 0xf070, 0, {0x60,0x01,0x1c,0xd0,0x45,0x24,0x01,0xc1,0x0c,0x42,0x01,0x00,0x00,0xc5,0x20,0x31 } },
-{  16, 0xf080, 0, {0x41,0x08,0x40,0x00,0x18,0x80,0x45,0x00,0x21,0x41,0x0c,0x70,0x42,0x1c,0xc2,0x00 } },
-{  16, 0xf090, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x1c,0x80,0xc4,0x20 } },
-{  16, 0xf0a0, 0, {0x31,0x08,0x10,0x42,0x42,0x08,0x80,0xc6,0x20,0x31,0x09,0x00,0x20,0x03,0x1c,0x90 } },
-{  16, 0xf0b0, 0, {0xc4,0x20,0x01,0x49,0x0c,0x42,0x43,0x10,0x80,0x44,0x20,0x31,0x08,0x10,0x00,0x00 } },
-{  16, 0xf0c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x83,0x20,0x30,0x48,0x0c } },
-{  16, 0xf0d0, 0, {0x32,0x40,0x10,0x90,0x81,0x24,0x20,0xc8,0x04,0x32,0x40,0x10,0x20,0xc3,0x20,0x80 } },
-{  16, 0xf0e0, 0, {0xc8,0x00,0x02,0x4a,0x0c,0xa0,0x01,0x24,0x10,0xc8,0x08,0x32,0x41,0x10,0x00,0x00 } },
-{  16, 0xf0f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x90,0x03,0x00,0x00,0xc9,0x04 } },
-{  16, 0xf100, 0, {0x30,0x40,0x00,0x90,0x00,0x20,0x00,0x80,0x00,0x10,0x40,0x10,0x00,0x40,0x20,0x10 } },
-{  16, 0xf110, 0, {0xc2,0x00,0x00,0x80,0x08,0x20,0x43,0x08,0x10,0x81,0x00,0x32,0x40,0x0c,0xc0,0x04 } },
-{  16, 0xf120, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x40,0x00,0x00,0x00 } },
-{  16, 0xf130, 0, {0x10,0x00,0x00,0xf0,0x10,0x20,0x00,0x00,0x00,0x10,0x00,0x00,0xf0,0x10,0x80,0x40 } },
-{  16, 0xf140, 0, {0x00,0x00,0x00,0x40,0x00,0xf0,0x10,0x90,0x80,0x00,0x00,0x00,0x00,0x00,0xc0,0x00 } },
-{  16, 0xf150, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x10,0x80,0x90,0x40,0x00,0x00 } },
-{  16, 0xf160, 0, {0x00,0x80,0x10,0x90,0xa0,0x90,0x00,0x00,0x00,0x00,0x00,0x10,0x90,0x80,0x80,0x00 } },
-{  16, 0xf170, 0, {0x00,0x00,0x00,0x00,0x10,0x90,0x80,0x90,0x00,0x00,0x00,0x00,0x40,0x10,0x8f,0x0f } },
-{  16, 0xf180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xc6,0xba,0x06,0xc0,0x1c } },
-{  16, 0xf190, 0, {0x49,0x28,0x61,0x14,0x2b,0x1c,0x0e,0x40,0x3f,0xd9,0xbf,0xd9,0xaa,0xbc,0x1a,0x5f } },
-{  16, 0xf1a0, 0, {0x00,0x10,0xa6,0x50,0x3b,0x61,0xb3,0x25,0xbc,0x40,0x19,0xbf,0xff,0xe9,0x80,0x00 } },
-{  16, 0xf1b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x92,0x14,0x94,0x80,0x0c } },
-{  16, 0xf1c0, 0, {0x07,0x3f,0x2b,0x94,0x86,0x14,0x84,0x80,0x28,0x00,0x00,0x49,0x14,0x04,0x86,0x12 } },
-{  16, 0xf1d0, 0, {0x80,0x00,0x41,0x27,0x34,0xd0,0x90,0x84,0x92,0x00,0x2d,0x8a,0x21,0x1e,0x80,0x00 } },
-{  16, 0xf1e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xa2 } },
-{  16, 0xf1f0, 0, {0xb1,0x01,0x01,0x00,0x00,0x00,0x00,0x08,0x84,0xb1,0x78,0x28,0x00,0x00,0x00,0x00 } },
-{  16, 0xf200, 0, {0x08,0xb1,0x32,0x14,0x14,0x00,0x00,0x00,0x00,0x08,0xa8,0x23,0x54,0x21,0x40,0x00 } },
-{  16, 0xf210, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf220, 0, {0x00,0x00,0x00,0x2f,0xff,0xfe,0xf7,0xc0,0x00,0x00,0x00,0x00,0x2f,0xd7,0xfe,0xef } },
-{  16, 0xf230, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0x7f,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf240, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf250, 0, {0x00,0x00,0x00,0x0f,0xef,0x77,0xff,0xc0,0x00,0x00,0x00,0x00,0x3e,0xff,0xfe,0xef } },
-{  16, 0xf260, 0, {0x40,0x00,0x00,0x00,0x00,0x3f,0xff,0xbf,0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf270, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf280, 0, {0x00,0x00,0x00,0x3f,0xff,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff } },
-{  16, 0xf290, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0x7f,0x2f,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf2a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf2b0, 0, {0x00,0x00,0x00,0x1f,0xff,0xff,0xef,0xc0,0x00,0x00,0x00,0x00,0x1f,0xef,0xef,0xef } },
-{  16, 0xf2c0, 0, {0xc0,0x00,0x00,0x00,0x00,0x2f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf2d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf2e0, 0, {0x00,0x00,0x00,0x3f,0xff,0xef,0xff,0xc0,0x00,0x00,0x00,0x00,0x2f,0xaf,0xdf,0xff } },
-{  16, 0xf2f0, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xef,0xff,0xf7,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf300, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf310, 0, {0x00,0x00,0x00,0x3f,0xdf,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff } },
-{  16, 0xf320, 0, {0xc0,0x00,0x00,0x00,0x00,0x1f,0xff,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf330, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc4,0x24,0xa1,0x00,0x2c } },
-{  16, 0xf340, 0, {0x52,0x0b,0x18,0xc2,0x86,0x2c,0xa1,0x80,0x38,0x62,0x0a,0x08,0x40,0xc4,0x2c,0xa1 } },
-{  16, 0xf350, 0, {0x08,0x28,0x42,0x0b,0x14,0x00,0x85,0x14,0xa1,0x08,0x28,0x43,0x0a,0x10,0x00,0x00 } },
-{  16, 0xf360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x12,0x01,0x03,0x80 } },
-{  16, 0xf370, 0, {0x61,0x20,0x10,0x08,0x07,0x12,0x41,0x42,0x80,0x70,0x20,0x1c,0x08,0x04,0x1a,0x01 } },
-{  16, 0xf380, 0, {0x84,0x81,0x40,0x20,0x18,0x08,0x46,0x36,0x81,0x05,0x80,0x63,0x20,0x10,0x00,0x01 } },
-{  16, 0xf390, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x24,0x21,0x00,0x0c } },
-{  16, 0xf3a0, 0, {0x52,0x02,0x14,0x00,0x87,0x28,0x21,0x81,0x08,0x72,0x06,0x1c,0x82,0x84,0x20,0x21 } },
-{  16, 0xf3b0, 0, {0x48,0x18,0x42,0x03,0x54,0x80,0x45,0x30,0x25,0x4a,0x18,0x53,0x02,0x10,0x00,0x01 } },
-{  16, 0xf3c0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x22,0x01,0x01,0x80 } },
-{  16, 0xf3d0, 0, {0x42,0x20,0x18,0xc8,0x44,0x22,0x01,0x80,0x84,0x42,0x20,0x1c,0x88,0x04,0x22,0x01 } },
-{  16, 0xf3e0, 0, {0x00,0x80,0x40,0x20,0x10,0x88,0x44,0x36,0x01,0x40,0x80,0x41,0x00,0x10,0x00,0x00 } },
-{  16, 0xf3f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x08,0x20,0x00,0x0c } },
-{  16, 0xf400, 0, {0x22,0x03,0x04,0x40,0x81,0x00,0x20,0x84,0x08,0x03,0x00,0x00,0x80,0xc2,0x00,0x20 } },
-{  16, 0xf410, 0, {0xc4,0x08,0x00,0x03,0x08,0x88,0x82,0x16,0xa0,0x40,0x88,0x32,0x22,0x80,0x00,0x00 } },
-{  16, 0xf420, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x01,0x00,0x80,0x04,0x20 } },
-{  16, 0xf430, 0, {0x10,0x08,0x0c,0xc2,0x12,0x10,0x84,0xc8,0x22,0x12,0x08,0x04,0x02,0x03,0x00,0x88 } },
-{  16, 0xf440, 0, {0x00,0x21,0x00,0x0c,0x0c,0x40,0x41,0x30,0x00,0x84,0x20,0x10,0x08,0x00,0x02,0x00 } },
-{  16, 0xf450, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x82,0x06,0x20,0x08,0x8c } },
-{  16, 0xf460, 0, {0x32,0x22,0x0c,0x88,0x81,0x26,0x20,0x4d,0x88,0x23,0x22,0x80,0x88,0x83,0x06,0x20 } },
-{  16, 0xf470, 0, {0x08,0x88,0x00,0x23,0x04,0x8a,0x81,0x36,0x20,0x4b,0x88,0x32,0x22,0x00,0x00,0x00 } },
-{  16, 0xf480, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x02,0x02,0x00,0x09,0x80 } },
-{  16, 0xf490, 0, {0x32,0x20,0x04,0x88,0x60,0x22,0x00,0x89,0x84,0x00,0x20,0x08,0x98,0x00,0x02,0x00 } },
-{  16, 0xf4a0, 0, {0x00,0x80,0x00,0x20,0x00,0x08,0x02,0x3a,0x80,0x48,0x80,0x30,0x20,0x00,0x02,0x00 } },
-{  16, 0xf4b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0a,0xc4,0x1a,0xa1,0x80,0xa8 } },
-{  16, 0xf4c0, 0, {0x41,0x2a,0x10,0xca,0xc7,0x1a,0xa1,0x04,0xad,0x71,0x2a,0x18,0x4a,0xd4,0x06,0xb1 } },
-{  16, 0xf4d0, 0, {0x00,0xa8,0x71,0x2a,0x10,0x08,0x84,0x26,0x29,0x06,0xac,0x52,0x2a,0x10,0x02,0x00 } },
-{  16, 0xf4e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x04,0x2a,0x01,0x41,0x80 } },
-{  16, 0xf4f0, 0, {0x42,0x20,0x1c,0x00,0x04,0x0a,0x01,0x09,0x84,0x51,0x20,0x1c,0x88,0x44,0x02,0x01 } },
-{  16, 0xf500, 0, {0x08,0x80,0x40,0x20,0x10,0x4a,0x47,0x02,0x01,0x48,0x80,0x63,0x20,0x10,0x02,0x00 } },
-{  16, 0xf510, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0xc4,0x10,0x21,0x81,0x0c } },
-{  16, 0xf520, 0, {0x41,0x02,0x0c,0x00,0xc0,0x20,0x61,0x0d,0x0e,0x72,0x02,0x1c,0x40,0xc4,0x08,0x31 } },
-{  16, 0xf530, 0, {0x04,0x18,0x42,0x02,0x10,0x80,0x87,0x20,0xb1,0xc4,0x0c,0x53,0x02,0x10,0x00,0x00 } },
-{  16, 0xf540, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x20,0x07,0x24,0x01,0xcc,0x00 } },
-{  16, 0xf550, 0, {0x72,0x40,0x14,0x00,0x04,0x24,0x01,0x08,0x00,0x73,0x41,0x10,0xc0,0x07,0x30,0x11 } },
-{  16, 0xf560, 0, {0xcc,0x00,0x71,0x01,0x10,0x02,0x04,0x20,0x81,0x46,0x10,0x42,0x40,0x10,0x02,0x04 } },
-{  16, 0xf570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0xc5,0x10,0x21,0x00,0x08 } },
-{  16, 0xf580, 0, {0x62,0x02,0x1c,0x90,0xc5,0x24,0x21,0x00,0x0c,0x70,0x82,0x1c,0x10,0xc4,0x20,0x31 } },
-{  16, 0xf590, 0, {0x88,0x02,0x40,0x06,0x1c,0x00,0x85,0x00,0xa1,0x00,0x0c,0x40,0x42,0x00,0x02,0x00 } },
-{  16, 0xf5a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x05,0x14,0x80,0x01,0x20 } },
-{  16, 0xf5b0, 0, {0x30,0x08,0x0c,0x42,0x06,0x00,0x80,0x01,0x24,0x51,0x08,0x0c,0x02,0x41,0x00,0x80 } },
-{  16, 0xf5c0, 0, {0x4c,0x20,0x00,0x08,0x0c,0x30,0x42,0x04,0x00,0x04,0x20,0x00,0x08,0x00,0x00,0x00 } },
-{  16, 0xf5d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xc6,0x24,0x20,0x00,0x0c } },
-{  16, 0xf5e0, 0, {0x32,0xc2,0x04,0x80,0xc7,0x30,0x20,0x00,0x0c,0x53,0xc2,0x04,0x10,0xc2,0x28,0x70 } },
-{  16, 0xf5f0, 0, {0x0c,0x09,0x02,0x02,0x4c,0x80,0x81,0x04,0x30,0x09,0x0c,0x02,0x42,0x10,0x00,0x00 } },
-{  16, 0xf600, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x80,0x01,0x38,0x00,0x02,0x00 } },
-{  16, 0xf610, 0, {0x12,0x40,0x0c,0x20,0x07,0x34,0x04,0x02,0x00,0x63,0x01,0x08,0x10,0x00,0x24,0x10 } },
-{  16, 0xf620, 0, {0x04,0x00,0x02,0x01,0x04,0x82,0x01,0x08,0x80,0x09,0x10,0x02,0x40,0x10,0x00,0x04 } },
-{  16, 0xf630, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x20,0x10,0x80,0x00,0x00 } },
-{  16, 0xf640, 0, {0x20,0x80,0x00,0xf0,0x20,0x10,0x80,0x00,0x00,0x20,0x80,0x00,0xd0,0x80,0x00,0x00 } },
-{  16, 0xf650, 0, {0x40,0x00,0x00,0x00,0x00,0x30,0x10,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0xcc,0x40 } },
-{  16, 0xf660, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x10,0x80,0x80,0x00,0x00,0x00 } },
-{  16, 0xf670, 0, {0x00,0x00,0x10,0x90,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x10,0x90,0x80,0x00,0x90 } },
-{  16, 0xf680, 0, {0x80,0x00,0x10,0x00,0x00,0x10,0xa0,0x80,0x00,0x00,0x00,0x20,0x00,0x10,0x8c,0x08 } },
-{  16, 0xf690, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x1a,0xbe,0x17,0x80,0x00 } },
-{  16, 0xf6a0, 0, {0x3e,0x40,0x26,0x6f,0xba,0xe3,0x24,0x80,0x00,0x16,0x59,0xbd,0x82,0x81,0x82,0xd8 } },
-{  16, 0xf6b0, 0, {0x80,0x00,0x00,0x19,0x99,0x86,0x80,0x64,0x80,0xc0,0x3f,0xd9,0x99,0x80,0x00,0x01 } },
-{  16, 0xf6c0, 0, {0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x16,0x02,0x94,0x00,0x16 } },
-{  16, 0xf6d0, 0, {0xc0,0x16,0x94,0x82,0x90,0x16,0x10,0x80,0x21,0x18,0x28,0x28,0x02,0x0a,0x02,0x08 } },
-{  16, 0xf6e0, 0, {0x80,0x00,0x00,0x00,0x00,0x02,0x82,0x80,0x14,0x00,0x01,0x14,0x11,0xa0,0x40,0x00 } },
-{  16, 0xf6f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x84 } },
-{  16, 0xf700, 0, {0x02,0x84,0xa8,0x80,0x00,0x00,0x00,0x08,0x91,0x22,0x84,0x41,0xa2,0x08,0x24,0x01 } },
-{  16, 0xf710, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x84,0x01,0x44,0x01,0x00,0x00 } },
-{  16, 0xf720, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf730, 0, {0x00,0x00,0x00,0x3e,0xf7,0xff,0xf7,0xc0,0x00,0x00,0x00,0x00,0x2f,0xe7,0xb7,0xff } },
-{  16, 0xf740, 0, {0xc0,0x00,0x00,0x00,0x00,0x2f,0xfe,0x7f,0xf7,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf750, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf760, 0, {0x00,0x00,0x00,0x36,0xbf,0xfe,0xdf,0xc0,0x00,0x00,0x00,0x00,0x0f,0xf7,0xdf,0xff } },
-{  16, 0xf770, 0, {0xc0,0x00,0x00,0x00,0x00,0x3d,0xb7,0xb7,0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf780, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf790, 0, {0x00,0x00,0x00,0x1f,0xdf,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x0f,0xdf,0xdf,0xff } },
-{  16, 0xf7a0, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xef,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf7b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf7c0, 0, {0x00,0x00,0x00,0x3f,0xbf,0x7f,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0x7f,0xf7 } },
-{  16, 0xf7d0, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xdf,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf7e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf7f0, 0, {0x00,0x00,0x00,0x3f,0x7e,0xff,0xff,0x40,0x00,0x00,0x00,0x00,0x3f,0xfe,0xff,0xff } },
-{  16, 0xf800, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf810, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
-{  16, 0xf820, 0, {0x00,0x00,0x00,0x37,0xff,0x6f,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff } },
-{  16, 0xf830, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf840, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf850, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf860, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf870, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x20,0x01,0x02,0x00,0x00,0x00 } },
-{  16, 0xf880, 0, {0x30,0x00,0x43,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf890, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf8a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf8b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf8c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf8d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf8e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf8f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x00,0x00,0x00,0x00,0x30 } },
-{  16, 0xf900, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf910, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf920, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf930, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf940, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf950, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x00 } },
-{  16, 0xf960, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf970, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf980, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf990, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf9a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf9b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x30,0xc0,0x30 } },
-{  16, 0xf9c0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf9d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf9e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xf9f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x0f } },
-{  16, 0xfa20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x00,0x00,0x00,0x00,0x3f } },
-{  16, 0xfa80, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfa90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfaa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfab0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfac0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfad0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x30,0xc0,0x30,0xc0,0x0f } },
-{  16, 0xfae0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfaf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x6b,0x00,0xc0,0x00,0xcf,0x2c } },
-{  16, 0xfb40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfb90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x00 } },
-{  16, 0xfba0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfbb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfbc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfbd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfbe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfbf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x0f,0x00,0x0f,0x00,0x30 } },
-{  16, 0xfc00, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x3f,0xc0,0x00 } },
-{  16, 0xfc60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfc90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfca0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfcb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x3f,0xc0,0x3f,0xc0,0x30 } },
-{  16, 0xfcc0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfcd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfcf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x0f,0x00,0x0f } },
-{  16, 0xfd20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x0f,0x00,0x0f,0x00,0x3f } },
-{  16, 0xfd80, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfd90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfda0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfdb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfdc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfdd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x3f,0xc0,0x3f,0xc0,0x0f } },
-{  16, 0xfde0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfdf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x33,0x5d,0x80,0xc0,0x00,0xfd,0xac } },
-{  16, 0xfe40, 0, {0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfe90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfea0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfeb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfec0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfed0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x00,0x00,0x00,0x00,0x30 } },
-{  16, 0xff00, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x00 } },
-{  16, 0xff60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xff90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xffa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xffb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x30,0xc0,0x30 } },
-{  16, 0xffc0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xffd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xffe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0xfff0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8010, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8020, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x0f } },
-{  16, 0x8030, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8040, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8050, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8080, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x00,0x00,0x00,0x00,0x3f } },
-{  16, 0x8090, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x80e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x30,0xc0,0x30,0xc0,0x0f } },
-{  16, 0x80f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8110, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8120, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8140, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x74,0xc0,0xc0,0x00,0xf0,0xec } },
-{  16, 0x8150, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8170, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8190, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x81a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x00 } },
-{  16, 0x81b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x81c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x81d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x81e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x81f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8200, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x0f,0x00,0x0f,0x00,0x30 } },
-{  16, 0x8210, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8220, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8230, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8240, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8250, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8260, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x3f,0xc0,0x00 } },
-{  16, 0x8270, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8280, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8290, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x82a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x82b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x82c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x86,0x10,0x80,0x30,0x82,0x3d } },
-{  16, 0x82d0, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x82e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x82f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8300, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8310, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8320, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x0f,0x00,0x0f } },
-{  16, 0x8330, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8340, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8350, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8380, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x0f,0x00,0x0f,0x00,0x3f } },
-{  16, 0x8390, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x83a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x83b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x83c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x83d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x83e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x3f,0xc0,0x3f,0xc0,0x0f } },
-{  16, 0x83f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8400, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8410, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8420, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8430, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8440, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x65,0x25,0xe4,0x80,0x00,0xb0,0x88 } },
-{  16, 0x8450, 0, {0xab,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8460, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8470, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8480, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8490, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x84a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x84b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x84c0, 0, {0x00,0x00,0x00,0x00,0x30,0x00,0x20,0x01,0x02,0x02,0x00,0x00,0x30,0x00,0x43,0x00 } },
-{  16, 0x84d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x84e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x84f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8500, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8510, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8520, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8530, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8540, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8550, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8560, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8580, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8590, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x85a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x85b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x85c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x85d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x85e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x85f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8600, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8610, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8620, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8630, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8640, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8650, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8660, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8680, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8690, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x86a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x86b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x86c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x86d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x86e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x86f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8700, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8710, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8720, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8730, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8740, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8750, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8760, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8770, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8780, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8790, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x87a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x87b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x87c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x87d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x87e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x87f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8800, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8810, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8820, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8830, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8840, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8850, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8860, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8870, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8880, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8890, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x88a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x88b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x88c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x88d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x88e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x88f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8900, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8910, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8920, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8930, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8940, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8950, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8960, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8970, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8980, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8990, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x89a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x89b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x89c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x89d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x89e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x89f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8a90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8aa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ab0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ac0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ad0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ae0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8af0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8b90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ba0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8bb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8bc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8bd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8be0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8bf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8c90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ca0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8cb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8cc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8cd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8cf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8d90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8da0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8db0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8dc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8dd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8de0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8df0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8e90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ea0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8eb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ec0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ed0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8f90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8fa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8fb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8fc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8fd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8fe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x8ff0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9000, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9010, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9020, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9030, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9040, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9050, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9080, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9090, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x90a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x90b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x90c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x90d0, 0, {0x30,0x00,0x00,0x01,0x00,0x00,0x44,0x72,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x03 } },
-{  16, 0x90e0, 0, {0x30,0x00,0x40,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x90f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  16, 0x9110, 0, {0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x05,0x30,0x00,0xa0,0x01 } },
-{  16, 0x9120, 0, {0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x01,0x00,0x00,0xe1,0x5a,0x00,0x00,0x00,0x00 } },
-{  12, 0x9130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
-{  0 , 0x0000, 1, {0 }}
-};
-// VERSION=1.1.1.131
-// DATE=2001dec06
-// PRODUCT=EMI 2|6
-/*
- * This firmware is for the Emagic EMI 2|6 Audio Interface
- *
- * The firmware contained herein is Copyright (c) 1999-2002 Emagic
- * as an unpublished work. This notice does not imply unrestricted
- * or public access to this firmware which is a trade secret of Emagic,
- * and which may not be reproduced, used, sold or transferred to
- * any third party without Emagic's written consent. All Rights Reserved.
- *
- * This firmware may not be modified and may only be used with the
- * Emagic EMI 2|6 Audio Interface. Distribution and/or Modification of
- * any driver which includes this firmware, in whole or in part,
- * requires the inclusion of this statement.
- */
-INTEL_HEX_RECORD g_Firmware[] = {
-{   3,0x0000,0,{0x02,0x43,0x56} },
-{   3,0x0003,0,{0x02,0x4b,0xcd} },
-{   3,0x000b,0,{0x02,0x4b,0xd2} },
-{   3,0x0013,0,{0x02,0x4b,0x92} },
-{   3,0x001b,0,{0x02,0x4b,0xd5} },
-{   3,0x0023,0,{0x02,0x1b,0x39} },
-{   3,0x002b,0,{0x02,0x43,0xe2} },
-{   3,0x0033,0,{0x02,0x3f,0xf3} },
-{   3,0x003b,0,{0x02,0x4b,0xc0} },
-{   3,0x0043,0,{0x02,0x47,0x00} },
-{   3,0x004b,0,{0x02,0x3f,0xfc} },
-{   3,0x0053,0,{0x02,0x37,0xfa} },
-{   3,0x005b,0,{0x02,0x4b,0xc7} },
-{   3,0x0063,0,{0x02,0x46,0xfc} },
-{  16,0x0500,0,{0x12,0x01,0x10,0x01,0x00,0x00,0x00,0x40,0x6a,0x08,0x01,0x01,0x00,0x01,0x01,0x02} },
-{  16,0x0510,0,{0x00,0x01,0x09,0x02,0xb8,0x01,0x03,0x01,0x00,0x80,0xa0,0x09,0x04,0x00,0x00,0x00} },
-{  16,0x0520,0,{0x01,0x01,0x00,0x00,0x0a,0x24,0x01,0x00,0x01,0x56,0x00,0x02,0x01,0x02,0x0c,0x24} },
-{  16,0x0530,0,{0x02,0x01,0x01,0x01,0x00,0x06,0x00,0x00,0x00,0x00,0x15,0x24,0x06,0x05,0x01,0x02} },
-{  16,0x0540,0,{0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09} },
-{  16,0x0550,0,{0x24,0x03,0x02,0x04,0x03,0x00,0x05,0x00,0x0c,0x24,0x02,0x03,0x01,0x02,0x00,0x02} },
-{  16,0x0560,0,{0x00,0x00,0x00,0x00,0x0d,0x24,0x06,0x06,0x03,0x02,0x03,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x0570,0,{0x00,0x09,0x24,0x03,0x04,0x01,0x01,0x00,0x06,0x00,0x09,0x04,0x01,0x00,0x00,0x01} },
-{  16,0x0580,0,{0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x02,0x01,0x02,0x00,0x00,0x07,0x24,0x01,0x01} },
-{  16,0x0590,0,{0x00,0x01,0x00,0x11,0x24,0x02,0x01,0x02,0x02,0x10,0x03,0x44,0xac,0x00,0x80,0xbb} },
-{  16,0x05a0,0,{0x00,0x00,0x77,0x01,0x09,0x05,0x0a,0x05,0x84,0x01,0x01,0x00,0x8f,0x07,0x25,0x01} },
-{  16,0x05b0,0,{0x01,0x00,0x00,0x00,0x09,0x05,0x8f,0x01,0x03,0x00,0x01,0x06,0x00,0x09,0x04,0x01} },
-{  16,0x05c0,0,{0x02,0x02,0x01,0x02,0x00,0x00,0x07,0x24,0x01,0x01,0x00,0x01,0x00,0x0e,0x24,0x02} },
-{  16,0x05d0,0,{0x01,0x06,0x02,0x10,0x02,0x44,0xac,0x00,0x80,0xbb,0x00,0x09,0x05,0x0a,0x05,0x4c} },
-{  16,0x05e0,0,{0x02,0x01,0x00,0x8f,0x07,0x25,0x01,0x01,0x00,0x00,0x00,0x09,0x05,0x8f,0x01,0x03} },
-{  16,0x05f0,0,{0x00,0x01,0x06,0x00,0x09,0x04,0x01,0x03,0x02,0x01,0x02,0x00,0x00,0x07,0x24,0x01} },
-{  16,0x0600,0,{0x01,0x00,0x01,0x00,0x0e,0x24,0x02,0x01,0x06,0x03,0x18,0x02,0x44,0xac,0x00,0x80} },
-{  16,0x0610,0,{0xbb,0x00,0x09,0x05,0x0a,0x05,0x72,0x03,0x01,0x00,0x8f,0x07,0x25,0x01,0x01,0x00} },
-{  16,0x0620,0,{0x00,0x00,0x09,0x05,0x8f,0x01,0x03,0x00,0x01,0x06,0x00,0x09,0x04,0x01,0x04,0x02} },
-{  16,0x0630,0,{0x01,0x02,0x00,0x00,0x07,0x24,0x01,0x01,0x00,0x01,0x00,0x0b,0x24,0x02,0x01,0x02} },
-{  16,0x0640,0,{0x03,0x18,0x01,0x00,0x77,0x01,0x09,0x05,0x0a,0x05,0x46,0x02,0x01,0x00,0x8f,0x07} },
-{  16,0x0650,0,{0x25,0x01,0x01,0x00,0x00,0x00,0x09,0x05,0x8f,0x01,0x03,0x00,0x01,0x06,0x00,0x09} },
-{  16,0x0660,0,{0x04,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x09,0x04,0x02,0x01,0x01,0x01,0x02,0x00} },
-{  16,0x0670,0,{0x00,0x07,0x24,0x01,0x04,0x00,0x01,0x00,0x11,0x24,0x02,0x01,0x02,0x02,0x10,0x03} },
-{  16,0x0680,0,{0x44,0xac,0x00,0x80,0xbb,0x00,0x00,0x77,0x01,0x09,0x05,0x8c,0x05,0x84,0x01,0x01} },
-{  16,0x0690,0,{0x00,0x00,0x07,0x25,0x01,0x01,0x02,0x00,0x00,0x09,0x04,0x02,0x02,0x01,0x01,0x02} },
-{  16,0x06a0,0,{0x00,0x00,0x07,0x24,0x01,0x04,0x00,0x01,0x00,0x11,0x24,0x02,0x01,0x02,0x03,0x18} },
-{  16,0x06b0,0,{0x03,0x44,0xac,0x00,0x80,0xbb,0x00,0x00,0x77,0x01,0x09,0x05,0x8c,0x05,0x46,0x02} },
-{  16,0x06c0,0,{0x01,0x00,0x00,0x07,0x25,0x01,0x01,0x02,0x00,0x00,0x05,0x0c,0x09,0x01,0xa1,0x01} },
-{  16,0x06d0,0,{0x05,0x0c,0x09,0xe9,0x05,0x0c,0x09,0xea,0x15,0x00,0x25,0x01,0x95,0x02,0x75,0x01} },
-{  16,0x06e0,0,{0x81,0x42,0x95,0x01,0x75,0x06,0x81,0x01,0x05,0x0c,0x09,0x00,0x05,0x0c,0x09,0x00} },
-{  16,0x06f0,0,{0x15,0x00,0x25,0x01,0x95,0x02,0x75,0x01,0x91,0x06,0x95,0x01,0x75,0x06,0x91,0x03} },
-{  16,0x0700,0,{0xc0,0x04,0x03,0x09,0x04,0x18,0x03,0x45,0x00,0x4d,0x00,0x41,0x00,0x47,0x00,0x49} },
-{  16,0x0710,0,{0x00,0x43,0x00,0x20,0x00,0x47,0x00,0x6d,0x00,0x62,0x00,0x48,0x00,0x1e,0x03,0x45} },
-{  16,0x0720,0,{0x00,0x6d,0x00,0x61,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x45,0x00,0x4d} },
-{  16,0x0730,0,{0x00,0x49,0x00,0x20,0x00,0x32,0x00,0x7c,0x00,0x36,0x00,0x2a,0x03,0x43,0x00,0x6f} },
-{  16,0x0740,0,{0x00,0x6e,0x00,0x66,0x00,0x69,0x00,0x67,0x00,0x75,0x00,0x72,0x00,0x61,0x00,0x74} },
-{  16,0x0750,0,{0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69} },
-{  16,0x0760,0,{0x00,0x6e,0x00,0x67,0x00,0x22,0x03,0x49,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x72} },
-{  16,0x0770,0,{0x00,0x66,0x00,0x61,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x72} },
-{   9,0x0780,0,{0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x00,0x00} },
-{  16,0x0789,0,{0x74,0x00,0xf5,0x86,0x90,0xfd,0xa5,0x7c,0x05,0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} },
-{   1,0x0799,0,{0x22} },
-{  16,0x079a,0,{0x90,0x7f,0xd6,0xe0,0x44,0x80,0xf0,0x43,0x87,0x01,0x00,0x00,0x00,0x00,0x00,0x22} },
-{  16,0x07aa,0,{0xc0,0xd0,0xc0,0xe0,0x8f,0xe0,0xc0,0xe0,0x8e,0xe0,0xc0,0xe0,0x8d,0xe0,0xc0,0xe0} },
-{  16,0x07ba,0,{0x8c,0xe0,0xc0,0xe0,0xc0,0x82,0xc0,0x83,0x05,0x86,0xc0,0x84,0xc0,0x85,0xe5,0x18} },
-{  16,0x07ca,0,{0xb4,0x02,0x03,0x02,0x07,0xd9,0xb4,0x01,0x03,0x02,0x07,0xde,0x02,0x07,0xfa,0x7d} },
-{  16,0x07da,0,{0x01,0x02,0x08,0x16,0xe5,0x19,0x14,0xf5,0x19,0xc3,0xb5,0x13,0x03,0x02,0x07,0xf5} },
-{  16,0x07ea,0,{0x50,0x09,0xb4,0x00,0xea,0x75,0x19,0x0a,0x02,0x07,0xd9,0x7d,0x00,0x02,0x08,0x16} },
-{  16,0x07fa,0,{0xe5,0x19,0x14,0xf5,0x19,0xc3,0xb5,0x14,0x03,0x02,0x08,0x11,0x50,0x09,0xb4,0x00} },
-{  16,0x080a,0,{0xce,0x75,0x19,0x0a,0x02,0x07,0xd9,0x7d,0x02,0x02,0x08,0x16,0x7c,0x05,0x90,0x7f} },
-{  16,0x081a,0,{0x99,0xe0,0x54,0x40,0xdc,0x03,0x02,0x08,0x43,0xb4,0x00,0x1d,0x90,0x7f,0xe3,0x74} },
-{  16,0x082a,0,{0x7b,0xf0,0xa3,0x74,0x80,0xf0,0x90,0x7f,0xe2,0x74,0x40,0xf0,0x90,0x7f,0xe5,0xf0} },
-{  16,0x083a,0,{0x90,0x7f,0xe2,0x74,0x00,0xf0,0x02,0x08,0x18,0x05,0x86,0x90,0x7f,0xe2,0x74,0x80} },
-{  16,0x084a,0,{0xf0,0x90,0x79,0x65,0xe0,0xb4,0x01,0x03,0x02,0x08,0x9e,0xb4,0x02,0x03,0x02,0x08} },
-{  16,0x085a,0,{0x96,0xb4,0x03,0x03,0x02,0x08,0x8e,0xb4,0x04,0x03,0x02,0x08,0x86,0xb4,0x05,0x03} },
-{  16,0x086a,0,{0x02,0x08,0x7e,0xb4,0x06,0x03,0x02,0x08,0x76,0x02,0x08,0xf4,0x05,0x86,0x90,0x7f} },
-{  16,0x087a,0,{0x6c,0x02,0x08,0xe9,0x05,0x86,0x90,0x7f,0x6c,0x02,0x08,0xdd,0x05,0x86,0x90,0x7f} },
-{  16,0x088a,0,{0x6c,0x02,0x08,0xcf,0x05,0x86,0x90,0x7f,0x6c,0x02,0x08,0xc0,0x05,0x86,0x90,0x7f} },
-{  16,0x089a,0,{0x6c,0x02,0x08,0xb2,0x05,0x86,0x90,0x7f,0x6c,0xf0,0x00,0xf0,0x00,0xf0,0x00,0xf0} },
-{  16,0x08aa,0,{0x0d,0xed,0xb4,0x2d,0xf4,0x02,0x08,0xf4,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0d,0xed} },
-{  16,0x08ba,0,{0xb4,0x2d,0xf5,0x02,0x08,0xf4,0xf0,0x00,0xf0,0x00,0xf0,0x00,0xf0,0x0d,0xed,0xb4} },
-{  16,0x08ca,0,{0x31,0xf4,0x02,0x08,0xf4,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0d,0xed,0xb4,0x31,0xf5} },
-{  16,0x08da,0,{0x02,0x08,0xf4,0xf0,0xf0,0xf0,0xf0,0x0d,0xed,0xb4,0x61,0xf7,0x02,0x08,0xf4,0xf0} },
-{  16,0x08ea,0,{0xf0,0xf0,0xf0,0xf0,0xf0,0x0d,0xed,0xb4,0x61,0xf5,0x90,0x7f,0xe2,0x74,0x00,0xf0} },
-{  16,0x08fa,0,{0xd0,0x85,0xd0,0x84,0x05,0x86,0xd0,0x83,0xd0,0x82,0xd0,0xe0,0xfc,0xd0,0xe0,0xfd} },
-{   5,0x090a,0,{0xd0,0xe0,0xfe,0xd0,0xe0} },
-{   6,0x090f,0,{0xff,0xd0,0xe0,0xd0,0xd0,0x22} },
-{  16,0x0915,0,{0xc0,0xd0,0xc0,0xe0,0xc0,0x82,0xc0,0x83,0x90,0x7f,0x6f,0xe5,0x0c,0xf0,0xe5,0x0d} },
-{  13,0x0925,0,{0xf0,0xe5,0x0e,0xf0,0xd0,0x83,0xd0,0x82,0xd0,0xe0,0xd0,0xd0,0x22} },
-{  16,0x0932,0,{0xc0,0xd0,0xc0,0xe0,0x8f,0xe0,0xc0,0xe0,0x8e,0xe0,0xc0,0xe0,0xc0,0x82,0xc0,0x83} },
-{  16,0x0942,0,{0x05,0x86,0xc0,0x84,0xc0,0x85,0x90,0x79,0x70,0xe0,0xff,0xbf,0x00,0x03,0x02,0x0a} },
-{  16,0x0952,0,{0xb8,0x90,0x7f,0x96,0xe0,0x44,0x80,0xf0,0x90,0x7f,0xe2,0x74,0x80,0xf0,0x90,0x7f} },
-{  16,0x0962,0,{0x62,0xe0,0x05,0x86,0x90,0x7f,0xe2,0x74,0x00,0xf0,0x90,0x7f,0x96,0xe0,0x54,0x7f} },
-{  16,0x0972,0,{0xf0,0x90,0x7f,0xe2,0x74,0x80,0xf0,0x90,0x79,0x88,0xe0,0xb4,0x01,0x03,0x02,0x09} },
-{  16,0x0982,0,{0xbe,0xb4,0x02,0x03,0x02,0x09,0xc3,0xb4,0x03,0x03,0x02,0x09,0xac,0xb4,0x04,0x03} },
-{  16,0x0992,0,{0x02,0x09,0x9a,0x05,0x86,0x02,0x0a,0xb2,0xef,0x54,0x03,0xfe,0xef,0x03,0x03,0x54} },
-{  16,0x09a2,0,{0x3f,0xff,0x90,0x7f,0x63,0x05,0x86,0x02,0x09,0xc9,0xef,0x54,0x03,0xfe,0xef,0x03} },
-{  16,0x09b2,0,{0x03,0x54,0x3f,0xff,0x90,0x7f,0x63,0x05,0x86,0x02,0x0a,0x36,0x05,0x86,0x02,0x0a} },
-{  16,0x09c2,0,{0xa5,0x05,0x86,0x02,0x0a,0x8e,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0} },
-{  16,0x09d2,0,{0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86} },
-{  16,0x09e2,0,{0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0} },
-{  16,0x09f2,0,{0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86,0xdf,0xca,0xee,0xb4,0x00,0x03} },
-{  16,0x0a02,0,{0x02,0x0a,0xb2,0xb4,0x01,0x03,0x02,0x0a,0x25,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05} },
-{  16,0x0a12,0,{0x86,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0} },
-{  16,0x0a22,0,{0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86} },
-{  16,0x0a32,0,{0x02,0x0a,0xb2,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0} },
-{  13,0x0a42,0,{0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86} },
-{  16,0x0a4f,0,{0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xdf,0xd6} },
-{  16,0x0a5f,0,{0xee,0xb4,0x00,0x03,0x02,0x0a,0xb2,0xb4,0x01,0x03,0x02,0x0a,0x80,0xe0,0xe0,0xe0} },
-{  16,0x0a6f,0,{0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05} },
-{  16,0x0a7f,0,{0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0x02,0x0a,0xb2,0xe0,0xe0} },
-{  16,0x0a8f,0,{0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0} },
-{  16,0x0a9f,0,{0xdf,0xec,0x02,0x0a,0xb2,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0} },
-{  16,0x0aaf,0,{0xe0,0xdf,0xf2,0x90,0x7f,0xe2,0x74,0x00,0xf0,0xd0,0x85,0xd0,0x84,0x05,0x86,0xd0} },
-{  14,0x0abf,0,{0x83,0xd0,0x82,0xd0,0xe0,0xfe,0xd0,0xe0,0xff,0xd0,0xe0,0xd0,0xd0,0x22} },
-{  16,0x0acd,0,{0xc0,0x82,0xc0,0x83,0xc0,0xe0,0xe8,0xc0,0xe0,0x78,0xd1,0xe8,0x14,0xf8,0x70,0xfb} },
-{  10,0x0add,0,{0xd0,0xe0,0xf8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0x22} },
-{  16,0x0ae7,0,{0xc0,0xd0,0xc0,0xe0,0x8f,0xe0,0xc0,0xe0,0x8e,0xe0,0xc0,0xe0,0x8d,0xe0,0xc0,0xe0} },
-{  16,0x0af7,0,{0x8c,0xe0,0xc0,0xe0,0x75,0x86,0x00,0xc0,0x82,0xc0,0x83,0x05,0x86,0xc0,0x84,0xc0} },
-{  16,0x0b07,0,{0x85,0x7e,0x00,0x90,0x79,0x8e,0xe0,0xb4,0x00,0x16,0x74,0x01,0xf0,0x90,0x06,0xca} },
-{  16,0x0b17,0,{0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xe0,0xff,0x90,0x79,0x8d,0xf0,0x02,0x0b,0x39} },
-{  16,0x0b27,0,{0x90,0x79,0x8d,0xe0,0xff,0x90,0x79,0x8f,0xe0,0xfd,0x90,0x79,0x90,0xe0,0xfc,0x02} },
-{  16,0x0b37,0,{0x0b,0x46,0x90,0x06,0xca,0x05,0x86,0x90,0x7f,0x00,0x05,0x86,0x02,0x0b,0x51,0x8d} },
-{  16,0x0b47,0,{0x84,0x8c,0x85,0x05,0x86,0x90,0x7f,0x00,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xa3} },
-{  16,0x0b57,0,{0x0e,0xee,0xb4,0x40,0x03,0x02,0x0b,0x6c,0x05,0x86,0xdf,0xee,0x90,0x79,0x8e,0x74} },
-{  16,0x0b67,0,{0x00,0xf0,0x02,0x0b,0x82,0x05,0x86,0xad,0x84,0xac,0x85,0x90,0x79,0x8f,0xed,0xf0} },
-{  16,0x0b77,0,{0x90,0x79,0x90,0xec,0xf0,0x90,0x79,0x8d,0x1f,0xef,0xf0,0x90,0x7f,0xb5,0xee,0xf0} },
-{  16,0x0b87,0,{0xd0,0x85,0xd0,0x84,0x05,0x86,0xd0,0x83,0xd0,0x82,0xd0,0xe0,0xfc,0xd0,0xe0,0xfd} },
-{  11,0x0b97,0,{0xd0,0xe0,0xfe,0xd0,0xe0,0xff,0xd0,0xe0,0xd0,0xd0,0x22} },
-{  16,0x0ba2,0,{0xc0,0xd0,0xc0,0xe0,0xc0,0x82,0xc0,0x83,0x90,0x7f,0xae,0xe0,0x54,0xe0,0xf0,0x90} },
-{  16,0x0bb2,0,{0x7f,0x96,0xe0,0x44,0x08,0x54,0xfb,0xf0,0x90,0x7f,0x97,0xe0,0x54,0xbf,0xf0,0x90} },
-{  16,0x0bc2,0,{0x7f,0xe3,0x74,0x7b,0xf0,0x90,0x7f,0xe4,0x74,0x40,0xf0,0x90,0x79,0x78,0xe0,0x90} },
-{  16,0x0bd2,0,{0x7b,0x40,0xf0,0x90,0x7f,0xe2,0x74,0x48,0xf0,0x90,0x7f,0xe5,0xe0,0x90,0x7f,0xe2} },
-{  16,0x0be2,0,{0x74,0x00,0xf0,0x90,0x7f,0x96,0xe0,0x54,0xf7,0x44,0x04,0xf0,0x90,0x7f,0xe3,0x74} },
-{  16,0x0bf2,0,{0x7b,0xf0,0x90,0x7f,0xe4,0x74,0x40,0xf0,0x90,0x79,0x79,0xe0,0x90,0x7b,0x40,0xf0} },
-{  16,0x0c02,0,{0x90,0x7f,0xe2,0x74,0x48,0xf0,0x90,0x7f,0xe5,0xe0,0x90,0x7f,0xe2,0x74,0x00,0xf0} },
-{  16,0x0c12,0,{0x90,0x7f,0x96,0xe0,0x54,0xf3,0xf0,0x90,0x7f,0xae,0xe0,0x44,0x1f,0xf0,0xd0,0x83} },
-{   7,0x0c22,0,{0xd0,0x82,0xd0,0xe0,0xd0,0xd0,0x22} },
-{  16,0x0c29,0,{0xc0,0xd0,0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x90,0x79,0x2f,0xe0,0x64,0xff,0xc3,0x24} },
-{  11,0x0c39,0,{0x01,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0xd0,0xd0,0x22} },
-{  16,0x0c44,0,{0xbb,0x01,0x06,0x89,0x82,0x8a,0x83,0xe0,0x22,0x50,0x02,0xe7,0x22,0xbb,0xfe,0x02} },
-{   9,0x0c54,0,{0xe3,0x22,0x89,0x82,0x8a,0x83,0xe4,0x93,0x22} },
-{  16,0x0c5d,0,{0xbb,0x01,0x0c,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe0,0x22,0x50} },
-{  16,0x0c6d,0,{0x06,0xe9,0x25,0x82,0xf8,0xe6,0x22,0xbb,0xfe,0x06,0xe9,0x25,0x82,0xf8,0xe2,0x22} },
-{  13,0x0c7d,0,{0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe4,0x93,0x22} },
-{  16,0x0c8a,0,{0xbb,0x01,0x06,0x89,0x82,0x8a,0x83,0xf0,0x22,0x50,0x02,0xf7,0x22,0xbb,0xfe,0x01} },
-{   2,0x0c9a,0,{0xf3,0x22} },
-{  16,0x0c9c,0,{0xf8,0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe8,0xf0} },
-{  16,0x0cac,0,{0x22,0x50,0x06,0xe9,0x25,0x82,0xc8,0xf6,0x22,0xbb,0xfe,0x05,0xe9,0x25,0x82,0xc8} },
-{   2,0x0cbc,0,{0xf2,0x22} },
-{  16,0x0cbe,0,{0xc2,0xd5,0xec,0x30,0xe7,0x09,0xb2,0xd5,0xe4,0xc3,0x9d,0xfd,0xe4,0x9c,0xfc,0xee} },
-{  16,0x0cce,0,{0x30,0xe7,0x15,0xb2,0xd5,0xe4,0xc3,0x9f,0xff,0xe4,0x9e,0xfe,0x12,0x0e,0x40,0xc3} },
-{  16,0x0cde,0,{0xe4,0x9d,0xfd,0xe4,0x9c,0xfc,0x80,0x03,0x12,0x0e,0x40,0x30,0xd5,0x07,0xc3,0xe4} },
-{   6,0x0cee,0,{0x9f,0xff,0xe4,0x9e,0xfe,0x22} },
-{  16,0x0cf4,0,{0xc5,0xf0,0xf8,0xa3,0xe0,0x28,0xf0,0xc5,0xf0,0xf8,0xe5,0x82,0x15,0x82,0x70,0x02} },
-{   6,0x0d04,0,{0x15,0x83,0xe0,0x38,0xf0,0x22} },
-{  16,0x0d0a,0,{0xbb,0x01,0x10,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe0,0xf5,0xf0} },
-{  16,0x0d1a,0,{0xa3,0xe0,0x22,0x50,0x09,0xe9,0x25,0x82,0xf8,0x86,0xf0,0x08,0xe6,0x22,0xbb,0xfe} },
-{  16,0x0d2a,0,{0x0a,0xe9,0x25,0x82,0xf8,0xe2,0xf5,0xf0,0x08,0xe2,0x22,0xe5,0x83,0x2a,0xf5,0x83} },
-{   8,0x0d3a,0,{0xe9,0x93,0xf5,0xf0,0xa3,0xe9,0x93,0x22} },
-{  16,0x0d42,0,{0xe8,0x8f,0xf0,0xa4,0xcc,0x8b,0xf0,0xa4,0x2c,0xfc,0xe9,0x8e,0xf0,0xa4,0x2c,0xfc} },
-{  16,0x0d52,0,{0x8a,0xf0,0xed,0xa4,0x2c,0xfc,0xea,0x8e,0xf0,0xa4,0xcd,0xa8,0xf0,0x8b,0xf0,0xa4} },
-{  16,0x0d62,0,{0x2d,0xcc,0x38,0x25,0xf0,0xfd,0xe9,0x8f,0xf0,0xa4,0x2c,0xcd,0x35,0xf0,0xfc,0xeb} },
-{  16,0x0d72,0,{0x8e,0xf0,0xa4,0xfe,0xa9,0xf0,0xeb,0x8f,0xf0,0xa4,0xcf,0xc5,0xf0,0x2e,0xcd,0x39} },
-{  15,0x0d82,0,{0xfe,0xe4,0x3c,0xfc,0xea,0xa4,0x2d,0xce,0x35,0xf0,0xfd,0xe4,0x3c,0xfc,0x22} },
-{  16,0x0d91,0,{0xeb,0x9f,0xf5,0xf0,0xea,0x9e,0x42,0xf0,0xe9,0x9d,0x42,0xf0,0xe8,0x9c,0x45,0xf0} },
-{   1,0x0da1,0,{0x22} },
-{  16,0x0da2,0,{0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0e,0xa1} },
-{  16,0x0db2,0,{0x50,0x07,0xe9,0x25,0x82,0xf8,0x02,0x0e,0x95,0xbb,0xfe,0x07,0xe9,0x25,0x82,0xf8} },
-{  16,0x0dc2,0,{0x02,0x0e,0xad,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0e,0xb9} },
-{  16,0x0dd2,0,{0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0e,0xd5} },
-{  16,0x0de2,0,{0x50,0x07,0xe9,0x25,0x82,0xf8,0x02,0x0e,0xc9,0xbb,0xfe,0x07,0xe9,0x25,0x82,0xf8} },
-{   4,0x0df2,0,{0x02,0x0e,0xe1,0x22} },
-{  16,0x0df6,0,{0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0f,0x06} },
-{  16,0x0e06,0,{0x50,0x07,0xe9,0x25,0x82,0xf8,0x02,0x0e,0xed,0xbb,0xfe,0x07,0xe9,0x25,0x82,0xf8} },
-{   4,0x0e16,0,{0x02,0x0f,0x37,0x22} },
-{  16,0x0e1a,0,{0xd0,0x83,0xd0,0x82,0xf8,0xe4,0x93,0x70,0x12,0x74,0x01,0x93,0x70,0x0d,0xa3,0xa3} },
-{  16,0x0e2a,0,{0x93,0xf8,0x74,0x01,0x93,0xf5,0x82,0x88,0x83,0xe4,0x73,0x74,0x02,0x93,0x68,0x60} },
-{   6,0x0e3a,0,{0xef,0xa3,0xa3,0xa3,0x80,0xdf} },
-{  16,0x0e40,0,{0xbc,0x00,0x0b,0xbe,0x00,0x29,0xef,0x8d,0xf0,0x84,0xff,0xad,0xf0,0x22,0xe4,0xcc} },
-{  16,0x0e50,0,{0xf8,0x75,0xf0,0x08,0xef,0x2f,0xff,0xee,0x33,0xfe,0xec,0x33,0xfc,0xee,0x9d,0xec} },
-{  16,0x0e60,0,{0x98,0x40,0x05,0xfc,0xee,0x9d,0xfe,0x0f,0xd5,0xf0,0xe9,0xe4,0xce,0xfd,0x22,0xed} },
-{  16,0x0e70,0,{0xf8,0xf5,0xf0,0xee,0x84,0x20,0xd2,0x1c,0xfe,0xad,0xf0,0x75,0xf0,0x08,0xef,0x2f} },
-{  16,0x0e80,0,{0xff,0xed,0x33,0xfd,0x40,0x07,0x98,0x50,0x06,0xd5,0xf0,0xf2,0x22,0xc3,0x98,0xfd} },
-{   5,0x0e90,0,{0x0f,0xd5,0xf0,0xea,0x22} },
-{  12,0x0e95,0,{0xe6,0xfc,0x08,0xe6,0xfd,0x08,0xe6,0xfe,0x08,0xe6,0xff,0x22} },
-{  12,0x0ea1,0,{0xe0,0xfc,0xa3,0xe0,0xfd,0xa3,0xe0,0xfe,0xa3,0xe0,0xff,0x22} },
-{  12,0x0ead,0,{0xe2,0xfc,0x08,0xe2,0xfd,0x08,0xe2,0xfe,0x08,0xe2,0xff,0x22} },
-{  16,0x0eb9,0,{0xe4,0x93,0xfc,0xa3,0xe4,0x93,0xfd,0xa3,0xe4,0x93,0xfe,0xa3,0xe4,0x93,0xff,0x22} },
-{  12,0x0ec9,0,{0xec,0xf6,0x08,0xed,0xf6,0x08,0xee,0xf6,0x08,0xef,0xf6,0x22} },
-{  12,0x0ed5,0,{0xec,0xf0,0xa3,0xed,0xf0,0xa3,0xee,0xf0,0xa3,0xef,0xf0,0x22} },
-{  12,0x0ee1,0,{0xec,0xf2,0x08,0xed,0xf2,0x08,0xee,0xf2,0x08,0xef,0xf2,0x22} },
-{  16,0x0eed,0,{0xd0,0x83,0xd0,0x82,0xe4,0x93,0xf6,0x08,0x74,0x01,0x93,0xf6,0x08,0x74,0x02,0x93} },
-{   9,0x0efd,0,{0xf6,0x08,0x74,0x03,0x93,0xf6,0x74,0x04,0x73} },
-{  16,0x0f06,0,{0xa8,0x82,0x85,0x83,0xf0,0xd0,0x83,0xd0,0x82,0x12,0x0f,0x1d,0x12,0x0f,0x1d,0x12} },
-{  16,0x0f16,0,{0x0f,0x1d,0x12,0x0f,0x1d,0xe4,0x73,0xe4,0x93,0xa3,0xc5,0x83,0xc5,0xf0,0xc5,0x83} },
-{  16,0x0f26,0,{0xc8,0xc5,0x82,0xc8,0xf0,0xa3,0xc5,0x83,0xc5,0xf0,0xc5,0x83,0xc8,0xc5,0x82,0xc8} },
-{   1,0x0f36,0,{0x22} },
-{  16,0x0f37,0,{0xd0,0x83,0xd0,0x82,0xe4,0x93,0xf2,0x08,0x74,0x01,0x93,0xf2,0x08,0x74,0x02,0x93} },
-{   9,0x0f47,0,{0xf2,0x08,0x74,0x03,0x93,0xf2,0x74,0x04,0x73} },
-{  16,0x0f50,0,{0xc2,0xaf,0xd2,0x2c,0x90,0x7f,0x93,0x74,0x30,0xf0,0x90,0x7f,0x9c,0x74,0xbf,0xf0} },
-{  16,0x0f60,0,{0x90,0x7f,0x96,0xe0,0x54,0x30,0xf0,0x90,0x7f,0x94,0x74,0x30,0xf0,0x90,0x7f,0x9d} },
-{  16,0x0f70,0,{0x74,0xcf,0xf0,0x90,0x7f,0x97,0x74,0xa0,0xf0,0x90,0x7f,0x95,0x74,0xcc,0xf0,0xe4} },
-{  16,0x0f80,0,{0x90,0x7f,0x9e,0xf0,0xc2,0x2d,0xc2,0x2a,0xc2,0x2b,0xc2,0x2e,0x90,0x79,0x74,0x04} },
-{  16,0x0f90,0,{0xf0,0x12,0x2e,0x94,0x12,0x49,0xe2,0x12,0x4b,0xe6,0x12,0x32,0x0d,0x12,0x3b,0x0d} },
-{  16,0x0fa0,0,{0x12,0x41,0xfd,0x12,0x3e,0x99,0xe5,0x1f,0x70,0x18,0x75,0x1f,0x01,0x12,0x17,0xff} },
-{  16,0x0fb0,0,{0x12,0x2f,0xff,0x12,0x49,0xc8,0x12,0x4b,0xd8,0x12,0x4b,0xda,0x12,0x49,0x6f,0x12} },
-{  16,0x0fc0,0,{0x1b,0x40,0x12,0x39,0x8d,0x90,0x7f,0xaf,0xe0,0x44,0x01,0xf0,0x90,0x7f,0xae,0xe0} },
-{  16,0x0fd0,0,{0x44,0x1f,0xf0,0x90,0x7f,0xac,0x74,0xff,0xf0,0x90,0x7f,0xad,0xf0,0x90,0x7f,0xde} },
-{  16,0x0fe0,0,{0xf0,0x90,0x7f,0xdf,0xf0,0x90,0x7f,0xab,0xf0,0x90,0x7f,0xa9,0xf0,0x90,0x7f,0xaa} },
-{  16,0x0ff0,0,{0xf0,0x53,0x91,0xef,0x43,0xd8,0x20,0xd2,0xe8,0x43,0xd8,0x20,0x43,0xa8,0x80,0x22} },
-{  16,0x1000,0,{0x90,0x79,0x63,0xe0,0x14,0x60,0x44,0x14,0x70,0x02,0x21,0xd0,0x14,0x70,0x02,0x41} },
-{  16,0x1010,0,{0xd9,0x14,0x70,0x02,0x61,0xd7,0x24,0x04,0x60,0x02,0x81,0x56,0xe4,0x90,0x79,0x78} },
-{  16,0x1020,0,{0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x54,0xfd,0xf0,0x90} },
-{  16,0x1030,0,{0x79,0x7b,0xf0,0xe4,0x90,0x79,0x88,0xf0,0xa2,0xaf,0x33,0xf5,0x12,0xc2,0xaf,0x12} },
-{  16,0x1040,0,{0x0b,0xa2,0xe5,0x12,0x70,0x02,0x81,0x56,0xd2,0xaf,0x22,0x90,0x79,0x2d,0xe0,0x64} },
-{  16,0x1050,0,{0x01,0x70,0x79,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x30,0xf0,0x90,0x7f,0xff} },
-{  16,0x1060,0,{0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0} },
-{  16,0x1070,0,{0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12} },
-{  16,0x1080,0,{0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90} },
-{  16,0x1090,0,{0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe} },
-{  16,0x10a0,0,{0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd} },
-{  16,0x10b0,0,{0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x04} },
-{  16,0x10c0,0,{0xf0,0x90,0x79,0x88,0x14,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d,0xe0} },
-{  16,0x10d0,0,{0x64,0x02,0x70,0x79,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x34,0xf0,0x90,0x7f} },
-{  16,0x10e0,0,{0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79} },
-{  16,0x10f0,0,{0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5} },
-{  16,0x1100,0,{0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0} },
-{  16,0x1110,0,{0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54} },
-{  16,0x1120,0,{0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44} },
-{  16,0x1130,0,{0x02,0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74} },
-{  16,0x1140,0,{0x04,0xf0,0x90,0x79,0x88,0x14,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d} },
-{  16,0x1150,0,{0xe0,0x64,0x03,0x60,0x02,0x81,0x56,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x64} },
-{  16,0x1160,0,{0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0} },
-{  16,0x1170,0,{0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf} },
-{  16,0x1180,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90} },
-{  16,0x1190,0,{0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79} },
-{  16,0x11a0,0,{0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79} },
-{  16,0x11b0,0,{0x79,0xe0,0x44,0x04,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74} },
-{  16,0x11c0,0,{0x04,0xf0,0x90,0x79,0x88,0x14,0xf0,0xe5,0x12,0x70,0x02,0x81,0x56,0xd2,0xaf,0x22} },
-{  16,0x11d0,0,{0x90,0x79,0x2d,0xe0,0x64,0x01,0x70,0x7a,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74} },
-{  16,0x11e0,0,{0x88,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b} },
-{  16,0x11f0,0,{0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x54,0xfd,0xf0,0x90,0x79,0x7b,0xf0,0xa2} },
-{  16,0x1200,0,{0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0} },
-{  16,0x1210,0,{0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90} },
-{  16,0x1220,0,{0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90} },
-{  16,0x1230,0,{0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2} },
-{  16,0x1240,0,{0x90,0x79,0x82,0x74,0x0c,0xf0,0x90,0x79,0x88,0x74,0x01,0xf0,0xe5,0x12,0x60,0x02} },
-{  16,0x1250,0,{0xd2,0xaf,0x90,0x79,0x2d,0xe0,0x64,0x02,0x60,0x02,0x81,0x56,0x90,0x7f,0xf2,0xf0} },
-{  16,0x1260,0,{0x90,0x7f,0xf3,0x74,0x94,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78} },
-{  16,0x1270,0,{0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x54,0xfd,0xf0,0x90} },
-{  16,0x1280,0,{0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79} },
-{  16,0x1290,0,{0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0} },
-{  16,0x12a0,0,{0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0} },
-{  16,0x12b0,0,{0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84} },
-{  16,0x12c0,0,{0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x0c,0xf0,0x90,0x79,0x88,0x74,0x01,0xf0} },
-{  16,0x12d0,0,{0xe5,0x12,0x70,0x02,0x81,0x56,0xd2,0xaf,0x22,0x90,0x79,0x2d,0xe0,0x64,0x01,0x70} },
-{  16,0x12e0,0,{0x77,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0xcc,0xf0,0x90,0x7f,0xff,0x74,0xfc} },
-{  16,0x12f0,0,{0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfc} },
-{  16,0x1300,0,{0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2} },
-{  16,0x1310,0,{0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79} },
-{  16,0x1320,0,{0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79} },
-{  16,0x1330,0,{0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0,0x90} },
-{  16,0x1340,0,{0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x12,0xf0,0x90,0x79,0x88,0x74} },
-{  16,0x1350,0,{0x02,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d,0xe0,0x64,0x02,0x70,0x77} },
-{  16,0x1360,0,{0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0xe0,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0} },
-{  16,0x1370,0,{0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfc,0xf0} },
-{  16,0x1380,0,{0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90} },
-{  16,0x1390,0,{0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f} },
-{  16,0x13a0,0,{0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79} },
-{  16,0x13b0,0,{0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0,0x54,0xfb,0xf0,0x90,0x79} },
-{  16,0x13c0,0,{0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x12,0xf0,0x90,0x79,0x88,0x74,0x02} },
-{  16,0x13d0,0,{0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d,0xe0,0x64,0x03,0x70,0x77,0x90} },
-{  16,0x13e0,0,{0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x94,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4} },
-{  16,0x13f0,0,{0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfe,0xf0,0x44} },
-{  16,0x1400,0,{0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
-{  16,0x1410,0,{0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90} },
-{  16,0x1420,0,{0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90} },
-{  16,0x1430,0,{0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x90,0x79,0x84} },
-{  16,0x1440,0,{0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x06,0xf0,0x90,0x79,0x88,0x74,0x04,0xf0} },
-{   7,0x1450,0,{0xe5,0x12,0x60,0x02,0xd2,0xaf,0x22} },
-{  16,0x1457,0,{0xc2,0x28,0xc2,0x29,0x90,0x7f,0xe8,0xe0,0x12,0x0e,0x1a,0x14,0x84,0x00,0x14,0xe0} },
-{  16,0x1467,0,{0x01,0x14,0xf6,0x02,0x16,0x7c,0x21,0x16,0xbe,0x22,0x15,0x91,0x80,0x15,0xd1,0x81} },
-{  16,0x1477,0,{0x16,0x2e,0x82,0x16,0xcf,0xa1,0x17,0x05,0xa2,0x00,0x00,0x17,0x0a,0x90,0x7f,0xe9} },
-{  16,0x1487,0,{0xe0,0x14,0x60,0x11,0x24,0xfe,0x60,0x28,0x24,0xfe,0x60,0x3b,0x24,0xfc,0x70,0x40} },
-{  16,0x1497,0,{0x12,0x4a,0x2a,0xe1,0x16,0x12,0x4b,0xe0,0x40,0x02,0xe1,0x16,0x90,0x7f,0xea,0xe0} },
-{  16,0x14a7,0,{0xb4,0x01,0x04,0xc2,0x2a,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16} },
-{  16,0x14b7,0,{0x12,0x4b,0xe2,0x90,0x7f,0xea,0xe0,0xb4,0x01,0x04,0xd2,0x2a,0xe1,0x16,0x90,0x7f} },
-{  16,0x14c7,0,{0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16} },
-{  16,0x14d7,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x24,0xf5,0x70} },
-{  16,0x14e7,0,{0x05,0x12,0x47,0x9c,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90} },
-{  16,0x14f7,0,{0x7f,0xe9,0xe0,0x24,0xfd,0x60,0x54,0x24,0x02,0x60,0x02,0xa1,0x88,0x12,0x4b,0xe0} },
-{  16,0x1507,0,{0x40,0x02,0xe1,0x16,0x90,0x7f,0xea,0xe0,0x70,0x38,0x90,0x7f,0xec,0xe0,0xf4,0x54} },
-{  16,0x1517,0,{0x80,0xff,0xc4,0x54,0x0f,0xff,0xe0,0x54,0x07,0x2f,0x25,0xe0,0x24,0xb4,0xf5,0x82} },
-{  16,0x1527,0,{0xe4,0x34,0x7f,0xf5,0x83,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0x54,0x80,0xff,0x13,0x13} },
-{  16,0x1537,0,{0x13,0x54,0x1f,0xff,0xe0,0x54,0x07,0x2f,0x90,0x7f,0xd7,0xf0,0xe0,0x44,0x20,0xf0} },
-{  16,0x1547,0,{0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x12,0x4b,0xe2,0x40,0x02} },
-{  16,0x1557,0,{0xe1,0x16,0x90,0x7f,0xea,0xe0,0x70,0x20,0x90,0x7f,0xec,0xe0,0xf4,0x54,0x80,0xff} },
-{  16,0x1567,0,{0xc4,0x54,0x0f,0xff,0xe0,0x54,0x07,0x2f,0x25,0xe0,0x24,0xb4,0xf5,0x82,0xe4,0x34} },
-{  16,0x1577,0,{0x7f,0xf5,0x83,0x74,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1} },
-{  16,0x1587,0,{0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x60,0x12} },
-{  16,0x1597,0,{0x24,0xf8,0x60,0x09,0x24,0x02,0x70,0x29,0x12,0x17,0x1e,0xe1,0x16,0x12,0x4b,0xa0} },
-{  16,0x15a7,0,{0xe1,0x16,0x12,0x4b,0xde,0xa2,0x2a,0xe4,0x33,0xff,0x25,0xe0,0xff,0xa2,0x2b,0xe4} },
-{  16,0x15b7,0,{0x33,0x4f,0x90,0x7f,0x00,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0xe1} },
-{  16,0x15c7,0,{0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x60,0x37} },
-{  16,0x15d7,0,{0x24,0xf6,0x60,0x2e,0x24,0x04,0x70,0x41,0x90,0x7f,0xeb,0xe0,0x24,0xde,0x60,0x0e} },
-{  16,0x15e7,0,{0x04,0x70,0x16,0xd2,0x29,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0xd2,0x29} },
-{  16,0x15f7,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{  16,0x1607,0,{0xe1,0x16,0x12,0x44,0x63,0xe1,0x16,0x12,0x4b,0xde,0xe4,0x90,0x7f,0x00,0xf0,0xa3} },
-{  16,0x1617,0,{0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0xe1,0x16,0x20,0x29,0x07,0x90,0x7f,0xb4,0xe0} },
-{  16,0x1627,0,{0x44,0x01,0xf0,0xc2,0x29,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x24,0xf4,0x60,0x34,0x24} },
-{  16,0x1637,0,{0x0c,0x70,0x39,0x12,0x4b,0xde,0x90,0x7f,0xec,0xe0,0xf4,0x54,0x80,0xff,0xc4,0x54} },
-{  16,0x1647,0,{0x0f,0xff,0xe0,0x54,0x07,0x2f,0x25,0xe0,0x24,0xb4,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
-{  16,0x1657,0,{0x83,0xe0,0x54,0xfd,0x90,0x7f,0x00,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x02} },
-{  16,0x1667,0,{0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0} },
-{  16,0x1677,0,{0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x24,0xf6,0x60,0x12,0x14,0x60,0x1a} },
-{  16,0x1687,0,{0x24,0x02,0x70,0x1d,0xd2,0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x12,0xd2} },
-{  16,0x1697,0,{0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
-{  16,0x16a7,0,{0xf0,0x20,0x28,0x0f,0x90,0x79,0x85,0x74,0x01,0xf0,0x12,0x49,0x6f,0x90,0x7f,0xc5} },
-{  16,0x16b7,0,{0x74,0x02,0xf0,0xc2,0x28,0x80,0x58,0x90,0x79,0x86,0x74,0x01,0xf0,0x12,0x49,0x6f} },
-{  16,0x16c7,0,{0x90,0x7f,0xc5,0x74,0x02,0xf0,0x80,0x47,0x90,0x7f,0xe9,0xe0,0x24,0xfe,0x60,0x12} },
-{  16,0x16d7,0,{0x14,0x60,0x1a,0x24,0x02,0x70,0x1d,0xd2,0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{  16,0x16e7,0,{0x80,0x12,0xd2,0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x07,0x90,0x7f,0xb4} },
-{  16,0x16f7,0,{0xe0,0x44,0x01,0xf0,0x20,0x28,0x03,0x12,0x1a,0x7b,0xc2,0x28,0x80,0x11,0x12,0x2c} },
-{  16,0x1707,0,{0x2b,0x80,0x0c,0x12,0x4b,0xe4,0x50,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x90} },
-{   7,0x1717,0,{0x7f,0xb4,0xe0,0x44,0x02,0xf0,0x22} },
-{  16,0x171e,0,{0x12,0x4b,0xdc,0x40,0x02,0xe1,0xe3,0x90,0x7f,0xeb,0xe0,0x24,0xfe,0x60,0x1e,0x14} },
-{  16,0x172e,0,{0x60,0x46,0x14,0x60,0x6e,0x14,0x70,0x02,0xe1,0xd4,0x24,0x04,0x60,0x02,0xe1,0xdc} },
-{  16,0x173e,0,{0x74,0x05,0x90,0x7f,0xd4,0xf0,0x74,0x00,0x90,0x7f,0xd5,0xf0,0x22,0x90,0x7f,0xea} },
-{  16,0x174e,0,{0xe0,0xff,0x12,0x3f,0xa2,0x8b,0x33,0x8a,0x34,0x89,0x35,0xea,0x49,0x60,0x11,0xce} },
-{  16,0x175e,0,{0xea,0xce,0xee,0x90,0x7f,0xd4,0xf0,0xcf,0xe9,0xcf,0xef,0x90,0x7f,0xd5,0xf0,0x22} },
-{  16,0x176e,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xea,0xe0,0xff,0x12,0x48,0x00} },
-{  16,0x177e,0,{0x8b,0x33,0x8a,0x34,0x89,0x35,0xea,0x49,0x60,0x11,0xce,0xea,0xce,0xee,0x90,0x7f} },
-{  16,0x178e,0,{0xd4,0xf0,0xcf,0xe9,0xcf,0xef,0x90,0x7f,0xd5,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44} },
-{  16,0x179e,0,{0x01,0xf0,0x22,0x90,0x7f,0xea,0xe0,0xff,0x90,0x7e,0xc0,0xe0,0xfd,0xa3,0xe0,0xfb} },
-{  16,0x17ae,0,{0x12,0x44,0xd2,0x8b,0x33,0x8a,0x34,0x89,0x35,0xea,0x49,0x60,0x11,0xce,0xea,0xce} },
-{  16,0x17be,0,{0xee,0x90,0x7f,0xd4,0xf0,0xcf,0xe9,0xcf,0xef,0x90,0x7f,0xd5,0xf0,0x22,0x90,0x7f} },
-{  16,0x17ce,0,{0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f} },
-{   5,0x17de,0,{0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x17e3,0,{0x22} },
-{  16,0x17e4,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x90,0x7f,0xc4,0xe4,0xf0,0x53,0x91,0xef,0x90,0x7f} },
-{  11,0x17f4,0,{0xab,0x74,0x04,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{   1,0x17ff,0,{0x22} },
-{  16,0x1800,0,{0xe4,0x90,0x78,0x15,0xf0,0x7b,0x01,0x90,0x78,0x12,0x04,0xf0,0xa3,0x74,0x78,0xf0} },
-{  16,0x1810,0,{0xa3,0x74,0x58,0xf0,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
-{  16,0x1820,0,{0x00,0x01,0x12,0x0c,0x5d,0xff,0x90,0x79,0x9a,0xe0,0x6f,0x60,0x18,0x90,0x78,0x15} },
-{  16,0x1830,0,{0xe0,0xc3,0x94,0x06,0x50,0x0f,0xe0,0x04,0xf0,0x90,0x78,0x13,0xe4,0x75,0xf0,0x0f} },
-{  16,0x1840,0,{0x12,0x0c,0xf4,0x80,0xcf,0x90,0x78,0x15,0xe0,0xb4,0x06,0x08,0x90,0x7f,0xb4,0xe0} },
-{  16,0x1850,0,{0x44,0x01,0xf0,0x22,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12} },
-{  16,0x1860,0,{0x0c,0x44,0xff,0x24,0xbf,0x70,0x02,0x41,0x7a,0x24,0xe0,0x70,0x02,0x41,0x4c,0x24} },
-{  16,0x1870,0,{0x21,0x60,0x02,0x41,0x73,0x90,0x79,0x97,0xe0,0x24,0xfe,0x70,0x02,0x21,0x9a,0x14} },
-{  16,0x1880,0,{0x70,0x02,0x21,0xef,0x24,0x02,0x60,0x02,0x41,0x44,0x90,0x79,0x2d,0xe0,0xa3,0xf0} },
-{  16,0x1890,0,{0x90,0x79,0x23,0xe0,0xff,0xe4,0xfc,0xfd,0xfe,0xfb,0xfa,0x79,0x01,0xf8,0x12,0x0d} },
-{  16,0x18a0,0,{0x42,0xc8,0xec,0xc8,0xc9,0xed,0xc9,0xca,0xee,0xca,0xcb,0xef,0xcb,0x90,0x79,0x22} },
-{  16,0x18b0,0,{0xe0,0xfe,0xe4,0xfc,0xfd,0x2b,0xfb,0xea,0x3e,0xfa,0xed,0x39,0xf9,0xec,0x38,0xf8} },
-{  16,0x18c0,0,{0x90,0x79,0x21,0xe0,0xff,0xe4,0xfe,0xeb,0x2f,0xff,0xee,0x3a,0xfe,0xed,0x39,0xfd} },
-{  16,0x18d0,0,{0xec,0x38,0xfc,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
-{  16,0x18e0,0,{0x02,0x12,0x0d,0xd2,0x90,0x00,0x02,0x12,0x0d,0xa2,0x7b,0x44,0x7a,0xac,0x79,0x00} },
-{  16,0x18f0,0,{0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x05,0x90,0x79,0x2d,0x04,0xf0,0x90,0x78,0x12} },
-{  16,0x1900,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12,0x0d,0xa2,0x7b,0x80} },
-{  16,0x1910,0,{0x7a,0xbb,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x06,0x90,0x79,0x2d,0x74} },
-{  16,0x1920,0,{0x02,0xf0,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02} },
-{  16,0x1930,0,{0x12,0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70} },
-{  16,0x1940,0,{0x06,0x90,0x79,0x2d,0x74,0x03,0xf0,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0x75} },
-{  16,0x1950,0,{0x0c,0x67,0x75,0x0d,0x06,0x75,0x0e,0x0b,0xef,0xb4,0x02,0x08,0xe4,0xf5,0x0c,0xf5} },
-{  16,0x1960,0,{0x0d,0x75,0x0e,0x0c,0xef,0xb4,0x03,0x08,0xe4,0xf5,0x0c,0xf5,0x0d,0x75,0x0e,0x18} },
-{  16,0x1970,0,{0xef,0xb4,0x03,0x0d,0x90,0x79,0x2e,0xe0,0x64,0x03,0x60,0x05,0xd2,0x2f,0x12,0x3d} },
-{  16,0x1980,0,{0x79,0x90,0x79,0x2d,0xe0,0x64,0x03,0x60,0x0a,0xa3,0xe0,0xb4,0x03,0x05,0xc2,0x2f} },
-{  16,0x1990,0,{0x12,0x3d,0x79,0x12,0x10,0x00,0x12,0x28,0x01,0x22,0x90,0x79,0x23,0xe0,0xff,0xe4} },
-{  16,0x19a0,0,{0xfc,0xfd,0xfe,0xfb,0xfa,0x79,0x01,0xf8,0x12,0x0d,0x42,0xc8,0xec,0xc8,0xc9,0xed} },
-{  16,0x19b0,0,{0xc9,0xca,0xee,0xca,0xcb,0xef,0xcb,0x90,0x79,0x22,0xe0,0xfe,0xe4,0xfc,0xfd,0x2b} },
-{  16,0x19c0,0,{0xfb,0xea,0x3e,0xfa,0xed,0x39,0xf9,0xec,0x38,0xf8,0x90,0x79,0x21,0xe0,0xff,0xe4} },
-{  16,0x19d0,0,{0xfe,0xeb,0x2f,0xff,0xee,0x3a,0xfe,0xed,0x39,0xfd,0xec,0x38,0xfc,0x90,0x78,0x12} },
-{  16,0x19e0,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x06,0x12,0x0d,0xd2,0x22,0x90} },
-{  16,0x19f0,0,{0x79,0x23,0xe0,0xff,0xe4,0xfc,0xfd,0xfe,0xfb,0xfa,0x79,0x01,0xf8,0x12,0x0d,0x42} },
-{  16,0x1a00,0,{0xc8,0xec,0xc8,0xc9,0xed,0xc9,0xca,0xee,0xca,0xcb,0xef,0xcb,0x90,0x79,0x22,0xe0} },
-{  16,0x1a10,0,{0xfe,0xe4,0xfc,0xfd,0x2b,0xfb,0xea,0x3e,0xfa,0xed,0x39,0xf9,0xec,0x38,0xf8,0x90} },
-{  16,0x1a20,0,{0x79,0x21,0xe0,0xff,0xe4,0xfe,0xeb,0x2f,0xff,0xee,0x3a,0xfe,0xed,0x39,0xfd,0xec} },
-{  16,0x1a30,0,{0x38,0xfc,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a} },
-{  16,0x1a40,0,{0x12,0x0d,0xd2,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0} },
-{  16,0x1a50,0,{0x14,0x70,0x18,0x90,0x79,0x21,0xe0,0xff,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x1a60,0,{0xa3,0xe0,0xf9,0x90,0x00,0x0e,0xef,0x12,0x0c,0x9c,0x22,0x90,0x7f,0xb4,0xe0,0x44} },
-{  10,0x1a70,0,{0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x1a7a,0,{0x22} },
-{  16,0x1a7b,0,{0xe4,0xff,0xfe,0x7b,0x01,0x90,0x78,0x0f,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74} },
-{  16,0x1a8b,0,{0x2b,0xf0,0x90,0x78,0x0f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02} },
-{  16,0x1a9b,0,{0x12,0x0c,0x5d,0xfd,0x90,0x7f,0xec,0xe0,0x6d,0x60,0x13,0xef,0xc3,0x94,0x05,0x50} },
-{  16,0x1aab,0,{0x0d,0x0f,0x90,0x78,0x10,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd4,0x8d,0x33} },
-{  16,0x1abb,0,{0x90,0x78,0x0f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c} },
-{  16,0x1acb,0,{0x5d,0xfd,0x90,0x7f,0xed,0xe0,0x6d,0x60,0x13,0xee,0xc3,0x94,0x0b,0x50,0x0d,0x0e} },
-{  16,0x1adb,0,{0x90,0x78,0x10,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd4,0x90,0x7f,0xed,0xe0} },
-{  16,0x1aeb,0,{0xf5,0x34,0xef,0x64,0x05,0x60,0x03,0xbe,0x0b,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
-{  16,0x1afb,0,{0xf0,0x22,0x90,0x78,0x0f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44} },
-{  16,0x1b0b,0,{0xff,0x24,0xf0,0x60,0x08,0x24,0x0f,0x70,0x0e,0x12,0x49,0x2a,0x22,0x12,0x4b,0x83} },
-{  14,0x1b1b,0,{0x90,0x79,0x20,0xe5,0x34,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x1b29,0,{0x22} },
-{  15,0x1b2a,0,{0x90,0x7f,0xea,0xe0,0xb4,0xff,0x04,0x12,0x34,0x16,0x22,0x12,0x38,0x00,0x22} },
-{   7,0x1b39,0,{0x53,0x98,0xfe,0x53,0x98,0xfd,0x32} },
-{  16,0x1b40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1b50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1b60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1b70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1b80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1b90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ba0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1bb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1bc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1bd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1be0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1bf0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c00,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c10,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c20,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c30,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1c90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ca0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1cb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1cc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1cd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ce0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1cf0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d00,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d10,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d20,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d30,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1d90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1da0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1db0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1dc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1dd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1de0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1df0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e00,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e10,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e20,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e30,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1e90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ea0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  14,0x1eb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ebe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ece,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ede,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1eee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1efe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f0e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f1e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f2e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{   2,0x1f3e,0,{0x00,0x00} },
-{  16,0x1f40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1f90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1fa0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1fb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1fc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1fd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1fe0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x1ff0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2000,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2010,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2020,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2030,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2040,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2050,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2060,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2070,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2080,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2090,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x20a0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x20b0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x20c0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x20d0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x20e0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x20f0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2100,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2110,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2120,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2130,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2140,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2150,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2160,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2170,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2180,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2190,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x21a0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x21b0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x21c0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x21d0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x21e0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x21f0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2200,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2210,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2220,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2230,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2240,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2250,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2260,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2270,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2280,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2290,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x22a0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x22b0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x22c0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x22d0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x22e0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x22f0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2300,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2310,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2320,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2330,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2340,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2350,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x2360,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  14,0x2370,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x237e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x238e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x239e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x23ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x23be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x23ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x23de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x23ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x23fe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x240e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x241e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x242e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x243e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x244e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x245e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x246e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x247e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x248e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x249e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x24ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x24be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x24ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x24de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x24ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x24fe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x250e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x251e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x252e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x253e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x254e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x255e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x256e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x257e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x258e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x259e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x25ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x25be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x25ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x25de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x25ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x25fe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x260e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x261e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x262e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x263e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x264e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x265e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x266e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x267e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x268e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x269e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x26ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x26be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x26ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x26de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  14,0x26ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x26fc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x270c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x271c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x272c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x273c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x274c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x275c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x276c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x277c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x278c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x279c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x27ac,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x27bc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x27cc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x27dc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{  16,0x27ec,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
-{   5,0x27fc,0,{0x00,0x00,0x00,0x00,0x22} },
-{  16,0x2801,0,{0x90,0x79,0x64,0xe0,0x14,0x60,0x46,0x14,0x70,0x02,0x41,0x3c,0x24,0x02,0x60,0x02} },
-{  16,0x2811,0,{0x81,0x2a,0x90,0x7f,0xfc,0x74,0xcc,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79} },
-{  16,0x2821,0,{0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfd,0xf0,0x44} },
-{  16,0x2831,0,{0x01,0xf0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
-{  16,0x2841,0,{0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x7a,0xf0,0x22,0x90,0x79,0x2d} },
-{  16,0x2851,0,{0xe0,0x64,0x01,0x60,0x02,0x01,0xf1,0x90,0x7f,0xfc,0x74,0xcc,0xf0,0x90,0x7f,0xff} },
-{  16,0x2861,0,{0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79} },
-{  16,0x2871,0,{0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79} },
-{  16,0x2881,0,{0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79} },
-{  16,0x2891,0,{0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
-{  16,0x28a1,0,{0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90} },
-{  16,0x28b1,0,{0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90} },
-{  16,0x28c1,0,{0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0} },
-{  16,0x28d1,0,{0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0,0x90,0x79,0x65} },
-{  16,0x28e1,0,{0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0} },
-{  16,0x28f1,0,{0x90,0x79,0x2d,0xe0,0x64,0x02,0x60,0x02,0x21,0x96,0x90,0x7f,0xfc,0x74,0xc8,0xf0} },
-{  16,0x2901,0,{0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0} },
-{  16,0x2911,0,{0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01} },
-{  16,0x2921,0,{0x09,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb} },
-{  16,0x2931,0,{0xf0,0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2} },
-{  16,0x2941,0,{0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79} },
-{  16,0x2951,0,{0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0} },
-{  16,0x2961,0,{0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0} },
-{  16,0x2971,0,{0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0} },
-{  16,0x2981,0,{0x90,0x79,0x65,0x74,0x03,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c} },
-{  16,0x2991,0,{0xf0,0x90,0x79,0x8b,0xf0,0x90,0x79,0x2d,0xe0,0x64,0x03,0x60,0x02,0x81,0x2a,0x90} },
-{  16,0x29a1,0,{0x7f,0xfc,0x74,0x98,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01} },
-{  16,0x29b1,0,{0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90} },
-{  16,0x29c1,0,{0x79,0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90} },
-{  16,0x29d1,0,{0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf} },
-{  16,0x29e1,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90} },
-{  16,0x29f1,0,{0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79} },
-{  16,0x2a01,0,{0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79} },
-{  16,0x2a11,0,{0x79,0xe0,0x54,0xfd,0xf0,0x44,0x04,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90} },
-{  16,0x2a21,0,{0x79,0x7a,0x74,0x01,0xf0,0x90,0x79,0x65,0x74,0x05,0xf0,0xe5,0x12,0x60,0x02,0xd2} },
-{  16,0x2a31,0,{0xaf,0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x22,0x90,0x79,0x2d,0xe0,0x64} },
-{  16,0x2a41,0,{0x01,0x60,0x02,0x41,0xe0,0x90,0x7f,0xfc,0x74,0xb4,0xf0,0x90,0x7f,0xff,0x74,0xfc} },
-{  16,0x2a51,0,{0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x54} },
-{  16,0x2a61,0,{0xfe,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0} },
-{  16,0x2a71,0,{0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79,0x79,0xe0} },
-{  16,0x2a81,0,{0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90} },
-{  16,0x2a91,0,{0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f} },
-{  16,0x2aa1,0,{0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79} },
-{  16,0x2ab1,0,{0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0,0x90,0x79} },
-{  16,0x2ac1,0,{0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0,0x90,0x79,0x65,0x04,0xf0} },
-{  16,0x2ad1,0,{0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x90} },
-{  16,0x2ae1,0,{0x79,0x2d,0xe0,0x64,0x02,0x60,0x02,0x61,0x85,0x90,0x7f,0xfc,0x74,0xb0,0xf0,0x90} },
-{  16,0x2af1,0,{0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90} },
-{  16,0x2b01,0,{0x79,0x79,0xf0,0x54,0xfe,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09} },
-{  16,0x2b11,0,{0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0} },
-{  16,0x2b21,0,{0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf} },
-{  16,0x2b31,0,{0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79} },
-{  16,0x2b41,0,{0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80} },
-{  16,0x2b51,0,{0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0,0x54} },
-{  16,0x2b61,0,{0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0,0x90} },
-{  16,0x2b71,0,{0x79,0x65,0x74,0x04,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c,0xf0} },
-{  16,0x2b81,0,{0x90,0x79,0x8b,0xf0,0x90,0x79,0x2d,0xe0,0x64,0x03,0x60,0x02,0x81,0x2a,0x90,0x7f} },
-{  16,0x2b91,0,{0xfc,0x74,0x68,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0} },
-{  16,0x2ba1,0,{0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfe,0xf0,0x44,0x02,0xf0,0x90,0x79} },
-{  16,0x2bb1,0,{0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79} },
-{  16,0x2bc1,0,{0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4} },
-{  16,0x2bd1,0,{0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79} },
-{  16,0x2be1,0,{0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79} },
-{  16,0x2bf1,0,{0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79} },
-{  16,0x2c01,0,{0xe0,0x54,0xfd,0xf0,0x44,0x04,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79} },
-{  16,0x2c11,0,{0x7a,0x74,0x01,0xf0,0x90,0x79,0x65,0x74,0x06,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf} },
-{  10,0x2c21,0,{0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x22} },
-{  16,0x2c2b,0,{0xe4,0xff,0x7b,0x01,0x90,0x78,0x16,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0x58} },
-{  16,0x2c3b,0,{0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12} },
-{  16,0x2c4b,0,{0x0c,0x5d,0xfe,0x90,0x7f,0xec,0xe0,0x6e,0x60,0x13,0xef,0xc3,0x94,0x06,0x50,0x0d} },
-{  16,0x2c5b,0,{0x0f,0x90,0x78,0x17,0xe4,0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x80,0xd4,0xbf,0x06,0x08} },
-{  16,0x2c6b,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x2c7b,0,{0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xff,0x24,0x9f,0x70,0x02,0xc1,0x66,0x24,0x21,0x60} },
-{  16,0x2c8b,0,{0x02,0xc1,0x8c,0x90,0x7f,0xe9,0xe0,0x24,0x7e,0x70,0x02,0xa1,0x30,0x14,0x70,0x02} },
-{  16,0x2c9b,0,{0xa1,0xc8,0x24,0x02,0x60,0x02,0xc1,0x5e,0x90,0x00,0x02,0x12,0x0d,0xa2,0x7b,0x44} },
-{  16,0x2cab,0,{0x7a,0xac,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74} },
-{  16,0x2cbb,0,{0x44,0xf0,0xa3,0x74,0xac,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90} },
-{  16,0x2ccb,0,{0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12,0x0d,0xa2} },
-{  16,0x2cdb,0,{0x7b,0x80,0x7a,0xbb,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f} },
-{  16,0x2ceb,0,{0x00,0x74,0x80,0xf0,0xa3,0x74,0xbb,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03} },
-{  16,0x2cfb,0,{0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12} },
-{  16,0x2d0b,0,{0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01,0x78,0x00,0xc3,0x12,0x0d,0x91,0x60,0x02} },
-{  16,0x2d1b,0,{0xc1,0x93,0x90,0x7f,0x00,0xf0,0xa3,0x74,0x77,0xf0,0xa3,0x74,0x01,0xf0,0x90,0x7f} },
-{  16,0x2d2b,0,{0xb5,0x74,0x03,0xf0,0x22,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
-{  16,0x2d3b,0,{0x90,0x00,0x06,0x12,0x0d,0xa2,0x7b,0x44,0x7a,0xac,0x79,0x00,0x78,0x00,0xc3,0x12} },
-{  16,0x2d4b,0,{0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74,0x44,0xf0,0xa3,0x74,0xac,0xf0,0xe4,0xa3} },
-{  16,0x2d5b,0,{0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3} },
-{  16,0x2d6b,0,{0xe0,0xf9,0x90,0x00,0x06,0x12,0x0d,0xa2,0x7b,0x80,0x7a,0xbb,0x79,0x00,0x78,0x00} },
-{  16,0x2d7b,0,{0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74,0x80,0xf0,0xa3,0x74,0xbb,0xf0} },
-{  16,0x2d8b,0,{0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0} },
-{  16,0x2d9b,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x06,0x12,0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01} },
-{  16,0x2dab,0,{0x78,0x00,0xc3,0x12,0x0d,0x91,0x60,0x02,0xc1,0x93,0x90,0x7f,0x00,0xf0,0xa3,0x74} },
-{  16,0x2dbb,0,{0x77,0xf0,0xa3,0x74,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x22,0x90,0x78,0x16} },
-{  16,0x2dcb,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a,0x12,0x0d,0xa2,0x7b,0x44} },
-{  16,0x2ddb,0,{0x7a,0xac,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74} },
-{  16,0x2deb,0,{0x44,0xf0,0xa3,0x74,0xac,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90} },
-{  16,0x2dfb,0,{0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a,0x12,0x0d,0xa2} },
-{  16,0x2e0b,0,{0x7b,0x80,0x7a,0xbb,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f} },
-{  16,0x2e1b,0,{0x00,0x74,0x80,0xf0,0xa3,0x74,0xbb,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03} },
-{  16,0x2e2b,0,{0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a,0x12} },
-{  16,0x2e3b,0,{0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x48} },
-{  16,0x2e4b,0,{0x90,0x7f,0x00,0xf0,0xa3,0x74,0x77,0xf0,0xa3,0x74,0x01,0xf0,0x90,0x7f,0xb5,0x74} },
-{  16,0x2e5b,0,{0x03,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24} },
-{  16,0x2e6b,0,{0x7f,0x70,0x16,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
-{  16,0x2e7b,0,{0x0e,0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   8,0x2e8b,0,{0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x2e93,0,{0x22} },
-{  16,0x2e94,0,{0x75,0x36,0x25,0x75,0x37,0x24,0x90,0x79,0x74,0xe0,0x64,0x01,0x70,0x54,0xf0,0xf5} },
-{  16,0x2ea4,0,{0x35,0x75,0x22,0x01,0xe5,0x22,0x64,0x01,0x70,0x48,0x90,0x7f,0xa5,0xe0,0x44,0x80} },
-{  16,0x2eb4,0,{0xf0,0x90,0x7f,0xa6,0xe5,0x36,0xf0,0x12,0x46,0xc0,0x74,0x4f,0x25,0x35,0xf5,0x82} },
-{  16,0x2ec4,0,{0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x74,0x35,0x25} },
-{  16,0x2ed4,0,{0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0} },
-{  16,0x2ee4,0,{0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd,0x05,0x35,0xe5,0x35,0xc3,0x94,0x0d} },
-{  16,0x2ef4,0,{0x40,0xb2,0x90,0x79,0x75,0xe0,0x64,0x01,0x60,0x02,0xe1,0xde,0xf0,0x90,0x79,0x20} },
-{  16,0x2f04,0,{0xe0,0x64,0x05,0x60,0x02,0xe1,0x8d,0x7b,0x01,0x90,0x79,0x5c,0x04,0xf0,0xa3,0x74} },
-{  16,0x2f14,0,{0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x75,0x33,0x07,0x90,0x79,0x5c,0xe0,0xfb,0xa3,0xe0} },
-{  16,0x2f24,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c,0x5d,0x70,0x0f,0x90,0x00,0x04,0x12} },
-{  16,0x2f34,0,{0x0c,0x5d,0x90,0x79,0x2f,0xf0,0x12,0x0c,0x29,0x80,0x06,0x90,0x79,0x2f,0x74,0xff} },
-{  16,0x2f44,0,{0xf0,0xe4,0xf5,0x35,0x75,0x22,0x01,0x75,0x34,0x02,0xe5,0x22,0x64,0x01,0x70,0x39} },
-{  16,0x2f54,0,{0x90,0x7f,0xa5,0xe0,0x44,0x80,0xf0,0x90,0x7f,0xa6,0xe5,0x36,0xf0,0x12,0x46,0xc0} },
-{  16,0x2f64,0,{0xaf,0x34,0x05,0x34,0x90,0x7f,0xa6,0xef,0xf0,0x12,0x46,0xc0,0x90,0x79,0x2f,0xe0} },
-{  16,0x2f74,0,{0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd} },
-{  16,0x2f84,0,{0x05,0x35,0xe5,0x35,0xc3,0x94,0x06,0x40,0xc1,0x90,0x79,0x20,0xe0,0x64,0x06,0x70} },
-{  16,0x2f94,0,{0x49,0x7b,0x01,0x90,0x79,0x5f,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0} },
-{  16,0x2fa4,0,{0x75,0x33,0x03,0x90,0x79,0x5f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
-{  16,0x2fb4,0,{0x01,0x12,0x0c,0x5d,0x70,0x1c,0x90,0x00,0x04,0x12,0x0c,0x5d,0x90,0x79,0x33,0xf0} },
-{  16,0x2fc4,0,{0x70,0x03,0x74,0xff,0xf0,0x90,0x79,0x33,0xe0,0x54,0x7f,0xff,0xf0,0x25,0xe0,0xf0} },
-{  10,0x2fd4,0,{0x80,0x05,0xe4,0x90,0x79,0x33,0xf0,0x12,0x47,0xdf} },
-{   1,0x2fde,0,{0x22} },
-{  16,0x2fdf,0,{0x90,0x79,0x78,0x74,0x03,0xf0,0x90,0x79,0x83,0xe0,0x90,0x79,0x79,0xf0,0xa2,0xaf} },
-{  16,0x2fef,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x22} },
-{   1,0x2fff,0,{0x22} },
-{  16,0x3000,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x11,0x90,0x78,0x25,0x74,0x01,0xf0} },
-{  16,0x3010,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x75,0x35,0x07,0xed,0xb4,0x06,0x11,0x90} },
-{  16,0x3020,0,{0x78,0x25,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x75,0x35,0x03} },
-{  16,0x3030,0,{0x90,0x7f,0xeb,0xe0,0x14,0x60,0x11,0x14,0x60,0x5b,0x24,0x02,0x60,0x02,0x41,0x05} },
-{  16,0x3040,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24,0x7f,0x70,0x3d} },
-{  16,0x3050,0,{0xe4,0xff,0xef,0xc3,0x95,0x35,0x50,0x2f,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x3060,0,{0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00} },
-{  16,0x3070,0,{0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0} },
-{  16,0x3080,0,{0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xcb,0x90,0x7f,0xb5,0xee,0xf0,0x22,0x90,0x7f,0xb4} },
-{  16,0x3090,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24,0x7e,0x60,0x64,0x14,0x70,0x02} },
-{  16,0x30a0,0,{0x21,0x55,0x14,0x70,0x02,0x21,0xa9,0x24,0x03,0x60,0x02,0x21,0xfd,0xe4,0xff,0xef} },
-{  16,0x30b0,0,{0xc3,0x95,0x35,0x50,0x46,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
-{  16,0x30c0,0,{0x90,0x00,0x03,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82} },
-{  16,0x30d0,0,{0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x00,0x04,0x12,0x0c,0x5d,0xfd,0xcc,0xee} },
-{  16,0x30e0,0,{0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78} },
-{  16,0x30f0,0,{0x26,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0x90,0x7f,0xb5,0xee,0xf0} },
-{  16,0x3100,0,{0x22,0xe4,0xff,0xef,0xc3,0x95,0x35,0x50,0x46,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0} },
-{  16,0x3110,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x05,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74} },
-{  16,0x3120,0,{0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x00,0x06,0x12,0x0c} },
-{  16,0x3130,0,{0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83} },
-{  16,0x3140,0,{0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0x90} },
-{  16,0x3150,0,{0x7f,0xb5,0xee,0xf0,0x22,0xe4,0xff,0xef,0xc3,0x95,0x35,0x50,0x46,0x90,0x78,0x25} },
-{  16,0x3160,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x07,0x12,0x0c,0x5d,0xfd,0xcc} },
-{  16,0x3170,0,{0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90} },
-{  16,0x3180,0,{0x00,0x08,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4} },
-{  16,0x3190,0,{0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4} },
-{  16,0x31a0,0,{0x0f,0x80,0xb4,0x90,0x7f,0xb5,0xee,0xf0,0x22,0xe4,0xff,0xef,0xc3,0x95,0x35,0x50} },
-{  16,0x31b0,0,{0x46,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x09,0x12} },
-{  16,0x31c0,0,{0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
-{  16,0x31d0,0,{0x83,0xed,0xf0,0x90,0x00,0x0a,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00} },
-{  16,0x31e0,0,{0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0} },
-{  16,0x31f0,0,{0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0x90,0x7f,0xb5,0xee,0xf0,0x22,0x90,0x7f,0xb4} },
-{  12,0x3200,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x320c,0,{0x22} },
-{  16,0x320d,0,{0x7b,0x01,0x7a,0x78,0x79,0x2b,0x90,0x78,0x00,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9} },
-{  16,0x321d,0,{0xf0,0x74,0x01,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
-{  16,0x322d,0,{0xf9,0x90,0x00,0x01,0x74,0x01,0x12,0x0c,0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c} },
-{  16,0x323d,0,{0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
-{  16,0x324d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x10,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
-{  16,0x325d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x05,0x12,0x0c,0x9c,0x90,0x00,0x02} },
-{  16,0x326d,0,{0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78} },
-{  16,0x327d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78} },
-{  16,0x328d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x02,0x12,0x0c} },
-{  16,0x329d,0,{0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12} },
-{  16,0x32ad,0,{0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x01,0x12} },
-{  16,0x32bd,0,{0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01} },
-{  16,0x32cd,0,{0x74,0x03,0x12,0x0c,0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4} },
-{  16,0x32dd,0,{0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
-{  16,0x32ed,0,{0xf9,0x74,0x10,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
-{  16,0x32fd,0,{0xf9,0x90,0x00,0x01,0x74,0x06,0x12,0x0c,0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c} },
-{  16,0x330d,0,{0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
-{  16,0x331d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
-{  16,0x332d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x04,0x12,0x0c,0x9c,0x90,0x00,0x02} },
-{  16,0x333d,0,{0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78} },
-{  16,0x334d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78} },
-{  16,0x335d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x04,0x12,0x0c} },
-{  16,0x336d,0,{0x9c,0x90,0x00,0x02,0x74,0x04,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03} },
-{  16,0x337d,0,{0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02} },
-{  16,0x338d,0,{0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
-{  16,0x339d,0,{0x01,0x74,0x03,0x12,0x0c,0x9c,0x90,0x00,0x02,0x74,0x04,0x12,0x0c,0x9c,0x90,0x78} },
-{  16,0x33ad,0,{0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x33bd,0,{0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x33cd,0,{0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x02,0x12,0x0c,0x9c,0x90,0x00,0x02,0x74,0x04} },
-{  16,0x33dd,0,{0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00} },
-{  16,0x33ed,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78,0x00} },
-{  16,0x33fd,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x01,0x12,0x0c,0x9c} },
-{   8,0x340d,0,{0x90,0x00,0x02,0x74,0x04,0x12,0x0c,0x9c} },
-{   1,0x3415,0,{0x22} },
-{  16,0x3416,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x11,0x90,0x78,0x1f,0x74,0x01,0xf0} },
-{  16,0x3426,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x75,0x35,0x07,0xed,0xb4,0x06,0x11,0x90} },
-{  16,0x3436,0,{0x78,0x1f,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x75,0x35,0x03} },
-{  16,0x3446,0,{0x90,0x79,0x99,0xe0,0x14,0x60,0x11,0x14,0x60,0x5b,0x24,0x02,0x60,0x02,0xc1,0x06} },
-{  16,0x3456,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0,0x14,0x70,0x3e,0xe4} },
-{  16,0x3466,0,{0xff,0xef,0xc3,0x95,0x35,0x50,0x2f,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82} },
-{  16,0x3476,0,{0xe4,0x34,0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3} },
-{  16,0x3486,0,{0xe0,0xf9,0x90,0x00,0x01,0xed,0x12,0x0c,0x9c,0x90,0x78,0x20,0xe4,0x75,0xf0,0x0b} },
-{  16,0x3496,0,{0x12,0x0c,0xf4,0x0f,0x80,0xcb,0x90,0x79,0x75,0x74,0x01,0xf0,0x22,0x90,0x7f,0xb4} },
-{  16,0x34a6,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0,0x24,0xfe,0x60,0x63,0x14,0x70,0x02} },
-{  16,0x34b6,0,{0xa1,0x64,0x14,0x70,0x02,0xa1,0xb2,0x24,0x03,0x60,0x02,0xa1,0xfe,0xe4,0xff,0xef} },
-{  16,0x34c6,0,{0xc3,0x95,0x35,0x50,0x44,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82,0xe4,0x34} },
-{  16,0x34d6,0,{0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
-{  16,0x34e6,0,{0x90,0x00,0x03,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82} },
-{  16,0x34f6,0,{0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x04,0x12,0x0c,0x9c,0x90,0x78,0x20,0xe4} },
-{  16,0x3506,0,{0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb6,0x90,0x79,0x75,0x74,0x01,0xf0,0x22} },
-{  16,0x3516,0,{0xe4,0xff,0xef,0xc3,0x95,0x35,0x40,0x02,0xc1,0x0d,0xcd,0xee,0xcd,0x0e,0x74,0x21} },
-{  16,0x3526,0,{0x2d,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3} },
-{  16,0x3536,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x05,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e} },
-{  16,0x3546,0,{0x74,0x21,0x2d,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x06,0x12,0x0c} },
-{  16,0x3556,0,{0x9c,0x90,0x78,0x20,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0xe4,0xff} },
-{  16,0x3566,0,{0xef,0xc3,0x95,0x35,0x40,0x02,0xc1,0x0d,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5} },
-{  16,0x3576,0,{0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x3586,0,{0xa3,0xe0,0xf9,0x90,0x00,0x07,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e,0x74,0x21} },
-{  16,0x3596,0,{0x2d,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x08,0x12,0x0c,0x9c,0x90} },
-{  16,0x35a6,0,{0x78,0x20,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0xe4,0xff,0xef,0xc3} },
-{  16,0x35b6,0,{0x95,0x35,0x50,0x53,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82,0xe4,0x34,0x79} },
-{  16,0x35c6,0,{0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
-{  16,0x35d6,0,{0x00,0x09,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82,0xe4} },
-{  16,0x35e6,0,{0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x0a,0x12,0x0c,0x9c,0x90,0x78,0x20,0xe4,0x75} },
-{  16,0x35f6,0,{0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb6,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22} },
-{   7,0x3606,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x360d,0,{0x22} },
-{  16,0x360e,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x10,0x90,0x78,0x28,0x74,0x01,0xf0} },
-{  16,0x361e,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x7f,0x07,0xed,0xb4,0x06,0x10,0x90,0x78} },
-{  16,0x362e,0,{0x28,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x7f,0x03,0x90,0x78} },
-{  16,0x363e,0,{0x28,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xfd,0x90,0x7f,0xea} },
-{  16,0x364e,0,{0xe0,0x6d,0x60,0x12,0xee,0xc3,0x9f,0x50,0x0d,0x90,0x78,0x29,0xe4,0x75,0xf0,0x0b} },
-{  16,0x365e,0,{0x12,0x0c,0xf4,0x0e,0x80,0xd8,0x90,0x7f,0xeb,0xe0,0x14,0x60,0x11,0x14,0x60,0x46} },
-{  16,0x366e,0,{0x24,0x02,0x60,0x02,0xe1,0x9a,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f} },
-{  16,0x367e,0,{0xe9,0xe0,0x24,0x7f,0x70,0x28,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
-{  16,0x368e,0,{0xf0,0x22,0x90,0x78,0x28,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01} },
-{  16,0x369e,0,{0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0,0x22,0x90,0x7f} },
-{  16,0x36ae,0,{0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24,0x7e,0x60,0x40,0x14,0x60} },
-{  16,0x36be,0,{0x6f,0x14,0x70,0x02,0xe1,0x60,0x24,0x03,0x60,0x02,0xe1,0x92,0xee,0x6f,0x70,0x08} },
-{  16,0x36ce,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x28,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x36de,0,{0xa3,0xe0,0xf9,0x90,0x00,0x03,0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x90,0x00,0x04} },
-{  16,0x36ee,0,{0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x22,0xee,0x6f} },
-{  16,0x36fe,0,{0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x28,0xe0,0xfb,0xa3} },
-{  16,0x370e,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x05,0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x90} },
-{  16,0x371e,0,{0x00,0x06,0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x22} },
-{  16,0x372e,0,{0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x28,0xe0} },
-{  16,0x373e,0,{0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x07,0x12,0x0c,0x5d,0x90,0x7f,0x00} },
-{  16,0x374e,0,{0xf0,0x90,0x00,0x08,0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x02} },
-{  16,0x375e,0,{0xf0,0x22,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78} },
-{  16,0x376e,0,{0x28,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x09,0x12,0x0c,0x5d,0x90} },
-{  16,0x377e,0,{0x7f,0x00,0xf0,0x90,0x00,0x0a,0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5} },
-{  16,0x378e,0,{0x74,0x02,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0} },
-{   3,0x379e,0,{0x44,0x01,0xf0} },
-{   1,0x37a1,0,{0x22} },
-{  16,0x37a2,0,{0xc0,0xe0,0xc0,0xf0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0} },
-{  16,0x37b2,0,{0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef} },
-{  16,0x37c2,0,{0xc0,0xe0,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x10,0xf0,0x90,0x79,0x83,0xe0,0x54} },
-{  16,0x37d2,0,{0xfd,0xf0,0x12,0x2f,0xdf,0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0} },
-{  16,0x37e2,0,{0xfc,0xd0,0xe0,0xfb,0xd0,0xe0,0xfa,0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0} },
-{   8,0x37f2,0,{0x82,0xd0,0x83,0xd0,0xf0,0xd0,0xe0,0x32} },
-{   6,0x37fa,0,{0x53,0x91,0xbf,0xd2,0x26,0x32} },
-{  16,0x3800,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x10,0x90,0x78,0x22,0x74,0x01,0xf0} },
-{  16,0x3810,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x7f,0x07,0xed,0xb4,0x06,0x10,0x90,0x78} },
-{  16,0x3820,0,{0x22,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x7f,0x03,0x90,0x78} },
-{  16,0x3830,0,{0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xfd,0x90,0x79,0x98} },
-{  16,0x3840,0,{0xe0,0x6d,0x60,0x12,0xee,0xc3,0x9f,0x50,0x0d,0x90,0x78,0x23,0xe4,0x75,0xf0,0x0b} },
-{  16,0x3850,0,{0x12,0x0c,0xf4,0x0e,0x80,0xd8,0x90,0x79,0x99,0xe0,0x14,0x60,0x11,0x14,0x60,0x48} },
-{  16,0x3860,0,{0x24,0x02,0x60,0x02,0x21,0x85,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79} },
-{  16,0x3870,0,{0x97,0xe0,0x14,0x70,0x2b,0xee,0x6f,0x70,0x09,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{  16,0x3880,0,{0x80,0x17,0x90,0x79,0x21,0xe0,0xfd,0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3} },
-{  16,0x3890,0,{0xe0,0xf9,0x90,0x00,0x01,0xed,0x12,0x0c,0x9c,0x90,0x79,0x75,0x74,0x01,0xf0,0x22} },
-{  16,0x38a0,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0,0x24,0xfe,0x60,0x43} },
-{  16,0x38b0,0,{0x14,0x60,0x6e,0x14,0x70,0x02,0x21,0x4f,0x24,0x03,0x60,0x02,0x21,0x7d,0xee,0x6f} },
-{  16,0x38c0,0,{0x70,0x09,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x21,0x90,0x79,0x21,0xe0,0xfd} },
-{  16,0x38d0,0,{0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x03,0xed,0x12} },
-{  16,0x38e0,0,{0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x04,0x12,0x0c,0x9c,0x90,0x79,0x75,0x74} },
-{  16,0x38f0,0,{0x01,0xf0,0x22,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90} },
-{  16,0x3900,0,{0x79,0x21,0xe0,0xfd,0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
-{  16,0x3910,0,{0x00,0x05,0xed,0x12,0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x06,0x12,0x0c,0x9c} },
-{  16,0x3920,0,{0x22,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x21} },
-{  16,0x3930,0,{0xe0,0xfd,0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x07} },
-{  16,0x3940,0,{0xed,0x12,0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x08,0x12,0x0c,0x9c,0x22,0xee} },
-{  16,0x3950,0,{0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x21,0xe0,0xfe} },
-{  16,0x3960,0,{0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x09,0xee,0x12} },
-{  16,0x3970,0,{0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x0a,0x12,0x0c,0x9c,0x22,0x90,0x7f,0xb4} },
-{  12,0x3980,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x398c,0,{0x22} },
-{  16,0x398d,0,{0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xe4,0x90,0x79,0x83,0xf0,0x12,0x2f,0xdf,0x90,0x7f} },
-{  16,0x399d,0,{0xe0,0x74,0x90,0xf0,0x90,0x7f,0xe1,0x74,0x04,0xf0,0xe4,0x90,0x7f,0xdd,0xf0,0x90} },
-{  16,0x39ad,0,{0x7f,0xa1,0xf0,0x53,0x8e,0xf8,0x75,0x88,0x05,0x75,0xb8,0x20,0x75,0xf8,0x01,0x43} },
-{  16,0x39bd,0,{0x8e,0x30,0xf5,0xc8,0x75,0xca,0x7f,0x75,0xcb,0xf8,0x43,0xa8,0x20,0x90,0x79,0x74} },
-{  16,0x39cd,0,{0x04,0xf0,0xc2,0x22,0xe4,0xf5,0x0f,0x90,0x79,0x78,0xf0,0xa3,0xf0,0x90,0x79,0x62} },
-{  16,0x39dd,0,{0xf0,0xa3,0xf0,0xa3,0xf0,0x90,0x79,0x66,0xf0,0xa3,0xf0,0x90,0x79,0x7b,0xf0,0xa3} },
-{  16,0x39ed,0,{0xf0,0x90,0x79,0x84,0xf0,0x90,0x79,0x7d,0xf0,0x90,0x79,0x75,0xf0,0xa3,0xf0,0xa3} },
-{  16,0x39fd,0,{0xf0,0xc2,0x23,0xc2,0x24,0xc2,0x25,0xc2,0x26,0xc2,0x20,0x90,0x7f,0x9b,0xe0,0xf5} },
-{  16,0x3a0d,0,{0x0a,0x54,0x20,0xf5,0x0a,0x70,0x06,0x90,0x79,0x7e,0xf0,0x80,0x06,0x90,0x79,0x7e} },
-{  16,0x3a1d,0,{0x74,0x01,0xf0,0x90,0x7f,0x9b,0xe0,0xf5,0x0a,0x54,0x02,0xf5,0x0a,0x70,0x06,0x90} },
-{  16,0x3a2d,0,{0x79,0x7f,0xf0,0x80,0x06,0x90,0x79,0x7f,0x74,0x01,0xf0,0x90,0x79,0x78,0x74,0x02} },
-{  16,0x3a3d,0,{0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09} },
-{  16,0x3a4d,0,{0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0} },
-{  16,0x3a5d,0,{0x90,0x79,0x79,0xe0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x01} },
-{  16,0x3a6d,0,{0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09} },
-{  16,0x3a7d,0,{0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0} },
-{  16,0x3a8d,0,{0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0x12,0x0b,0xa2,0xe4,0x90,0x79,0x78,0xf0} },
-{  16,0x3a9d,0,{0xa3,0x04,0xf0,0xe4,0x90,0x79,0x88,0xf0,0x12,0x0b,0xa2,0x90,0x7f,0xfc,0x74,0xdd} },
-{  16,0x3aad,0,{0xf0,0x90,0x7f,0xff,0x74,0xff,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0xa3,0xf0,0x12} },
-{  16,0x3abd,0,{0x0b,0xa2,0xe4,0x90,0x79,0x7a,0xf0,0x90,0x79,0x83,0x04,0xf0,0x12,0x2f,0xdf,0xe4} },
-{  16,0x3acd,0,{0x90,0x79,0x30,0xf0,0x90,0x79,0x85,0xf0,0xa3,0xf0,0xa3,0xf0,0x12,0x2e,0x94,0x90} },
-{  16,0x3add,0,{0x79,0x2d,0x74,0x02,0xf0,0x90,0x79,0x88,0x14,0xf0,0xc2,0x2f,0xe4,0x90,0x79,0x68} },
-{  16,0x3aed,0,{0xf0,0x90,0x79,0x8a,0xf0,0x90,0x79,0x6a,0xf0,0xa3,0xf0,0x75,0x13,0x08,0x75,0x14} },
-{  16,0x3afd,0,{0x08,0xf5,0x16,0xf5,0x15,0xf5,0x17,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x22} },
-{  16,0x3b0d,0,{0x7b,0x01,0x7a,0x78,0x79,0x58,0x90,0x78,0x03,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9} },
-{  16,0x3b1d,0,{0xf0,0x74,0x40,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
-{  16,0x3b2d,0,{0xf9,0x90,0x00,0x01,0x74,0x0a,0x12,0x0c,0x9c,0x90,0x00,0x02,0x12,0x0d,0xf6,0x00} },
-{  16,0x3b3d,0,{0x00,0xbb,0x80,0x90,0x00,0x06,0x12,0x0d,0xf6,0x00,0x00,0xac,0x44,0x90,0x00,0x0a} },
-{  16,0x3b4d,0,{0x12,0x0d,0xf6,0x00,0x01,0x77,0x00,0x90,0x78,0x04,0xe4,0x75,0xf0,0x0f,0x12,0x0c} },
-{  16,0x3b5d,0,{0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x40,0x12,0x0c} },
-{  16,0x3b6d,0,{0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74} },
-{  16,0x3b7d,0,{0x8c,0x12,0x0c,0x9c,0x90,0x00,0x02,0x12,0x0d,0xf6,0x00,0x00,0xbb,0x80,0x90,0x00} },
-{  16,0x3b8d,0,{0x06,0x12,0x0d,0xf6,0x00,0x00,0xac,0x44,0x90,0x00,0x0a,0x12,0x0d,0xf6,0x00,0x01} },
-{  16,0x3b9d,0,{0x77,0x00,0x90,0x78,0x04,0xe4,0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0} },
-{  16,0x3bad,0,{0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x40,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0} },
-{  16,0x3bbd,0,{0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x8f,0x12,0x0c,0x9c,0x90} },
-{  16,0x3bcd,0,{0x78,0x04,0xe4,0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0} },
-{  16,0x3bdd,0,{0xfa,0xa3,0xe0,0xf9,0x74,0x41,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0} },
-{  16,0x3bed,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x84,0x12,0x0c,0x9c,0x90,0x78,0x04,0xe4} },
-{  16,0x3bfd,0,{0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
-{  16,0x3c0d,0,{0xf9,0x74,0x61,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
-{  16,0x3c1d,0,{0xf9,0x90,0x00,0x01,0x74,0x81,0x12,0x0c,0x9c,0x90,0x78,0x04,0xe4,0x75,0xf0,0x0f} },
-{  16,0x3c2d,0,{0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x61} },
-{  16,0x3c3d,0,{0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
-{   6,0x3c4d,0,{0x01,0x74,0x01,0x12,0x0c,0x9c} },
-{   1,0x3c53,0,{0x22} },
-{  16,0x3c54,0,{0xc0,0xe0,0xc0,0xf0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0} },
-{  16,0x3c64,0,{0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef} },
-{   2,0x3c74,0,{0xc0,0xe0} },
-{  16,0x3c76,0,{0x90,0x7f,0xa2,0xe0,0xf5,0x0b,0x90,0x7f,0x74,0xe0,0x90,0x79,0x70,0xf0,0x90,0x7f} },
-{  16,0x3c86,0,{0x75,0xe0,0x90,0x79,0x71,0xf0,0x90,0x79,0x83,0xe0,0xff,0xfe,0x54,0x02,0xfe,0x70} },
-{  16,0x3c96,0,{0x0d,0xef,0x44,0x02,0xf0,0x12,0x2f,0xdf,0x90,0x79,0x74,0x74,0x01,0xf0,0xe5,0x0b} },
-{  16,0x3ca6,0,{0x20,0xe2,0x28,0x90,0x79,0x70,0xe0,0xfe,0xa3,0xe0,0x7c,0x00,0x24,0x00,0xf5,0x11} },
-{  16,0x3cb6,0,{0xec,0x3e,0xf5,0x10,0x90,0x79,0x82,0xe0,0xfd,0xae,0x10,0xaf,0x11,0x12,0x0c,0xbe} },
-{  16,0x3cc6,0,{0x90,0x79,0x70,0xef,0xf0,0x90,0x79,0x89,0x74,0x01,0xf0,0x12,0x48,0x43,0x12,0x48} },
-{  16,0x3cd6,0,{0x76,0x90,0x79,0x89,0xe0,0x64,0x01,0x70,0x32,0x12,0x41,0x08,0x90,0x79,0x89,0xe4} },
-{  16,0x3ce6,0,{0xf0,0x90,0x7f,0x98,0xe0,0x44,0x40,0xf0,0x90,0x7f,0x9e,0xe0,0x44,0x40,0xf0,0x90} },
-{  16,0x3cf6,0,{0x7f,0x95,0x74,0x80,0xf0,0x75,0xe8,0x01,0x12,0x09,0x32,0x75,0xe8,0x0d,0x90,0x7f} },
-{  16,0x3d06,0,{0x95,0x74,0xc0,0xf0,0x75,0xe8,0x0d,0xd2,0x20,0x80,0x05,0x75,0xe8,0x01,0xc2,0x20} },
-{  16,0x3d16,0,{0x20,0x20,0x2b,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0x75,0x0c,0x67,0x75,0x0d} },
-{  16,0x3d26,0,{0x06,0x75,0x0e,0x0b,0xef,0xb4,0x02,0x09,0x75,0x0c,0x00,0x75,0x0d,0x00,0x75,0x0e} },
-{  16,0x3d36,0,{0x0c,0xef,0xb4,0x03,0x09,0x75,0x0c,0x00,0x75,0x0d,0x00,0x75,0x0e,0x18,0x75,0xca} },
-{  16,0x3d46,0,{0x6f,0x75,0xcb,0xfe,0xd2,0xca,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x02,0xf0,0xf0} },
-{  16,0x3d56,0,{0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0,0xfc,0xd0,0xe0,0xfb,0xd0} },
-{  16,0x3d66,0,{0xe0,0xfa,0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0,0x82,0xd0,0x83,0xd0,0xf0} },
-{   3,0x3d76,0,{0xd0,0xe0,0x32} },
-{  16,0x3d79,0,{0x75,0x33,0x25,0x75,0x34,0x24,0x90,0x79,0x5c,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0} },
-{  16,0x3d89,0,{0xa3,0x74,0xb2,0xf0,0x20,0x2f,0x02,0xc1,0x17,0xe4,0xf5,0x35,0x75,0x22,0x01,0x90} },
-{  16,0x3d99,0,{0x79,0x5c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x04,0x12,0x0c,0x5d} },
-{  16,0x3da9,0,{0xf5,0x36,0x75,0x35,0x06,0x74,0x42,0x25,0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83} },
-{  16,0x3db9,0,{0xe5,0x36,0xf0,0x05,0x35,0xe5,0x35,0xb4,0x0c,0xeb,0xe5,0x35,0xc3,0x94,0x0d,0x40} },
-{  16,0x3dc9,0,{0x02,0xc1,0x98,0xe5,0x22,0x64,0x01,0x60,0x02,0xc1,0x98,0x90,0x7f,0xa5,0xe0,0x44} },
-{  16,0x3dd9,0,{0x80,0xf0,0x90,0x7f,0xa6,0xe5,0x33,0xf0,0x12,0x46,0xc0,0x74,0x4f,0x25,0x35,0xf5} },
-{  16,0x3de9,0,{0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x74,0x42} },
-{  16,0x3df9,0,{0x25,0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46} },
-{  16,0x3e09,0,{0xc0,0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd,0x05,0x35,0x80,0xac,0xe4,0xf5} },
-{  16,0x3e19,0,{0x35,0x75,0x22,0x01,0x90,0x79,0x5c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
-{  16,0x3e29,0,{0x00,0x04,0x12,0x0c,0x5d,0xf5,0x36,0x75,0x35,0x06,0x74,0x35,0x25,0x35,0xf5,0x82} },
-{  16,0x3e39,0,{0xe4,0x34,0x79,0xf5,0x83,0xe5,0x36,0xf0,0x05,0x35,0xe5,0x35,0xb4,0x0c,0xeb,0xe5} },
-{  16,0x3e49,0,{0x35,0xc3,0x94,0x0d,0x50,0x49,0xe5,0x22,0x64,0x01,0x70,0x43,0x90,0x7f,0xa5,0xe0} },
-{  16,0x3e59,0,{0x44,0x80,0xf0,0x90,0x7f,0xa6,0xe5,0x33,0xf0,0x12,0x46,0xc0,0x74,0x4f,0x25,0x35} },
-{  16,0x3e69,0,{0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x74} },
-{  16,0x3e79,0,{0x35,0x25,0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12} },
-{  15,0x3e89,0,{0x46,0xc0,0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd,0x05,0x35,0x80,0xb0} },
-{   1,0x3e98,0,{0x22} },
-{  16,0x3e99,0,{0x90,0x78,0x09,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0xe4,0xff} },
-{  16,0x3ea9,0,{0xfe,0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xef,0x12,0x0c,0x8a} },
-{  16,0x3eb9,0,{0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0xe4,0x12} },
-{  16,0x3ec9,0,{0x0c,0x9c,0x90,0x00,0x02,0x74,0x15,0x12,0x0c,0x9c,0x90,0x00,0x03,0xe4,0x12,0x0c} },
-{  16,0x3ed9,0,{0x9c,0x90,0x00,0x04,0x74,0xff,0x12,0x0c,0x9c,0x90,0x00,0x05,0xe4,0x12,0x0c,0x9c} },
-{  16,0x3ee9,0,{0x90,0x00,0x06,0x74,0xc3,0x12,0x0c,0x9c,0x90,0x00,0x07,0xe4,0x12,0x0c,0x9c,0x90} },
-{  16,0x3ef9,0,{0x00,0x08,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x09,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x0a} },
-{  16,0x3f09,0,{0x74,0x01,0x12,0x0c,0x9c,0x90,0x78,0x0a,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f} },
-{  16,0x3f19,0,{0x0e,0xbe,0x07,0x8d,0x90,0x78,0x09,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74} },
-{  16,0x3f29,0,{0xff,0xf0,0xe4,0xff,0xfe,0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
-{  16,0x3f39,0,{0xef,0x12,0x0c,0x8a,0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
-{  16,0x3f49,0,{0x00,0x01,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x02,0x74,0x15,0x12,0x0c,0x9c,0x90,0x00} },
-{  16,0x3f59,0,{0x03,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x04,0x74,0x80,0x12,0x0c,0x9c,0x90,0x00,0x05} },
-{  16,0x3f69,0,{0xe4,0x12,0x0c,0x9c,0x90,0x00,0x06,0x74,0xc3,0x12,0x0c,0x9c,0x90,0x00,0x07,0xe4} },
-{  16,0x3f79,0,{0x12,0x0c,0x9c,0x90,0x00,0x08,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x09,0xe4,0x12,0x0c} },
-{  16,0x3f89,0,{0x9c,0x90,0x00,0x0a,0x74,0x01,0x12,0x0c,0x9c,0x90,0x78,0x0a,0xe4,0x75,0xf0,0x0b} },
-{   8,0x3f99,0,{0x12,0x0c,0xf4,0x0f,0x0e,0xbe,0x03,0x8d} },
-{   1,0x3fa1,0,{0x22} },
-{  16,0x3fa2,0,{0xe4,0xfe,0x75,0x3d,0xff,0x75,0x3e,0x05,0x75,0x3f,0x12,0xab,0x3d,0xaa,0x3e,0xa9} },
-{  16,0x3fb2,0,{0x3f,0x90,0x00,0x01,0x12,0x0c,0x5d,0x64,0x02,0x70,0x2f,0xcd,0xee,0xcd,0x0e,0xed} },
-{  16,0x3fc2,0,{0x6f,0x70,0x01,0x22,0x90,0x00,0x02,0x12,0x0d,0x0a,0x85,0xf0,0x3b,0xf5,0x3c,0x62} },
-{  16,0x3fd2,0,{0x3b,0xe5,0x3b,0x62,0x3c,0xe5,0x3c,0x62,0x3b,0x29,0xfd,0xe5,0x3b,0x3a,0xc9,0xed} },
-{  16,0x3fe2,0,{0xc9,0x75,0x3d,0xff,0xf5,0x3e,0x89,0x3f,0x80,0xc1,0x7b,0x00,0x7a,0x00,0x79,0x00} },
-{   1,0x3ff2,0,{0x22} },
-{   9,0x3ff3,0,{0x53,0xd8,0xef,0x43,0xd8,0x20,0xc2,0x2d,0x32} },
-{   4,0x3ffc,0,{0x53,0x91,0xdf,0x32} },
-{  16,0x4000,0,{0x90,0x79,0x87,0xe0,0xb4,0x01,0x1d,0x90,0x79,0x85,0xe0,0xb4,0x01,0x03,0x12,0x42} },
-{  16,0x4010,0,{0xaa,0x90,0x79,0x86,0xe0,0xb4,0x01,0x03,0x12,0x18,0x00,0xe4,0x90,0x79,0x85,0xf0} },
-{  16,0x4020,0,{0xa3,0xf0,0xa3,0xf0,0x12,0x2e,0x94,0x90,0x7f,0x9b,0xe0,0xf5,0x0a,0x54,0x02,0xf5} },
-{  16,0x4030,0,{0x0a,0x70,0x04,0x90,0x79,0x7f,0xf0,0x90,0x7f,0x9b,0xe0,0xf5,0x0a,0x54,0x02,0xff} },
-{  16,0x4040,0,{0xf5,0x0a,0xbf,0x02,0x06,0x90,0x79,0x7f,0x74,0x01,0xf0,0x90,0x7f,0x9b,0xe0,0xf5} },
-{  16,0x4050,0,{0x0a,0x54,0x20,0xf5,0x0a,0x70,0x04,0x90,0x79,0x7e,0xf0,0x90,0x7f,0x9b,0xe0,0xf5} },
-{  16,0x4060,0,{0x0a,0x54,0x20,0xff,0xf5,0x0a,0xbf,0x20,0x06,0x90,0x79,0x7e,0x74,0x01,0xf0,0x90} },
-{  16,0x4070,0,{0x79,0x7f,0xe0,0xff,0x90,0x79,0x81,0xe0,0x6f,0x60,0x38,0x90,0x79,0x78,0x74,0x02} },
-{  16,0x4080,0,{0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0xef,0xb4,0x01,0x06,0xe0,0x54,0xfe} },
-{  16,0x4090,0,{0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x90,0x79} },
-{  16,0x40a0,0,{0x84,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0xe5,0x12,0x60} },
-{  16,0x40b0,0,{0x02,0xd2,0xaf,0x90,0x79,0x7e,0xe0,0xff,0x90,0x79,0x80,0xe0,0x6f,0x60,0x38,0x90} },
-{  16,0x40c0,0,{0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0xef,0xb4,0x01} },
-{  16,0x40d0,0,{0x06,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79} },
-{  16,0x40e0,0,{0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
-{  16,0x40f0,0,{0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x7f,0xe0,0x90,0x79,0x81,0xf0,0x90} },
-{   8,0x4100,0,{0x79,0x7e,0xe0,0x90,0x79,0x80,0xf0,0x22} },
-{  16,0x4108,0,{0x90,0x79,0x2d,0xe0,0x64,0x01,0x70,0x35,0x90,0x79,0x70,0xe0,0xff,0xd3,0x94,0x2d} },
-{  16,0x4118,0,{0x40,0x2b,0x90,0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0,0xe0,0xd3} },
-{  16,0x4128,0,{0x94,0x0f,0x40,0x19,0xe4,0xf0,0xef,0xd3,0x94,0x31,0x40,0x08,0x90,0x79,0x2d,0x74} },
-{  16,0x4138,0,{0x03,0xf0,0x80,0x06,0x90,0x79,0x2d,0x74,0x02,0xf0,0x12,0x10,0x00,0x90,0x79,0x2d} },
-{  16,0x4148,0,{0xe0,0xb4,0x02,0x2c,0x90,0x79,0x70,0xe0,0xff,0xc3,0x94,0x2f,0x50,0x22,0xef,0xd3} },
-{  16,0x4158,0,{0x94,0x2a,0x40,0x1c,0x90,0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0} },
-{  16,0x4168,0,{0xe0,0xd3,0x94,0x0f,0x40,0x0a,0xe4,0xf0,0x90,0x79,0x2d,0x04,0xf0,0x12,0x10,0x00} },
-{  16,0x4178,0,{0x90,0x79,0x2d,0xe0,0xb4,0x02,0x26,0x90,0x79,0x70,0xe0,0xd3,0x94,0x31,0x40,0x1d} },
-{  16,0x4188,0,{0x90,0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0,0xe0,0xd3,0x94,0x0f} },
-{  16,0x4198,0,{0x40,0x0b,0xe4,0xf0,0x90,0x79,0x2d,0x74,0x03,0xf0,0x12,0x10,0x00,0x90,0x79,0x2d} },
-{  16,0x41a8,0,{0xe0,0x64,0x03,0x70,0x3f,0x90,0x79,0x70,0xe0,0xff,0xc3,0x94,0x5f,0x50,0x35,0x90} },
-{  16,0x41b8,0,{0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0,0xe0,0xd3,0x94,0x0f,0x40} },
-{  16,0x41c8,0,{0x23,0xe4,0xf0,0xef,0xc3,0x94,0x2f,0x50,0x0c,0xef,0xd3,0x94,0x2a,0x40,0x06,0x90} },
-{  16,0x41d8,0,{0x79,0x2d,0x74,0x01,0xf0,0xef,0xd3,0x94,0x2f,0x40,0x06,0x90,0x79,0x2d,0x74,0x02} },
-{  16,0x41e8,0,{0xf0,0x12,0x10,0x00,0x90,0x79,0x69,0xe0,0x70,0x05,0x90,0x79,0x68,0xf0,0x22,0xe4} },
-{   5,0x41f8,0,{0x90,0x79,0x69,0xf0,0x22} },
-{  16,0x41fd,0,{0x7b,0x01,0x7a,0x78,0x79,0x4c,0x90,0x78,0x06,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9} },
-{  16,0x420d,0,{0xf0,0xe4,0x12,0x0c,0x8a,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
-{  16,0x421d,0,{0x90,0x00,0x01,0x74,0x01,0x12,0x0c,0x9c,0x90,0x78,0x07,0xe4,0x75,0xf0,0x03,0x12} },
-{  16,0x422d,0,{0x0c,0xf4,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xe4,0x12,0x0c} },
-{  16,0x423d,0,{0x8a,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74} },
-{  16,0x424d,0,{0x02,0x12,0x0c,0x9c,0x90,0x78,0x07,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78} },
-{  16,0x425d,0,{0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xe4,0x12,0x0c,0x8a,0x90,0x78,0x06} },
-{  16,0x426d,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x03,0x12,0x0c,0x9c} },
-{  16,0x427d,0,{0x90,0x78,0x07,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x06,0xe0,0xfb,0xa3} },
-{  16,0x428d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0xe4,0x12,0x0c,0x8a,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0} },
-{  12,0x429d,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x04,0x12,0x0c,0x9c} },
-{   1,0x42a9,0,{0x22} },
-{  16,0x42aa,0,{0xe4,0xff,0xfe,0x7b,0x01,0x90,0x78,0x0c,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74} },
-{  16,0x42ba,0,{0x2b,0xf0,0x90,0x78,0x0c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02} },
-{  16,0x42ca,0,{0x12,0x0c,0x5d,0xfd,0x90,0x79,0x9a,0xe0,0x6d,0x60,0x13,0xef,0xc3,0x94,0x05,0x50} },
-{  16,0x42da,0,{0x0d,0x0f,0x90,0x78,0x0d,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd4,0x8d,0x33} },
-{  16,0x42ea,0,{0x90,0x78,0x0c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c} },
-{  16,0x42fa,0,{0x5d,0xfd,0x90,0x79,0x9b,0xe0,0xfc,0x6d,0x60,0x13,0xee,0xc3,0x94,0x0b,0x50,0x0d} },
-{  16,0x430a,0,{0x0e,0x90,0x78,0x0d,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd3,0x8c,0x34,0xef} },
-{  16,0x431a,0,{0x64,0x05,0x60,0x03,0xbe,0x0b,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90} },
-{  16,0x432a,0,{0x78,0x0c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xff,0x24,0xf0} },
-{  16,0x433a,0,{0x60,0x08,0x24,0x0e,0x70,0x0e,0x12,0x49,0x4d,0x22,0x90,0x79,0x20,0xe5,0x34,0xf0} },
-{  11,0x434a,0,{0x12,0x1b,0x2a,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
-{   1,0x4355,0,{0x22} },
-{  12,0x4356,0,{0x78,0x7f,0xe4,0xf6,0xd8,0xfd,0x75,0x81,0x3f,0x02,0x43,0x9d} },
-{  16,0x4362,0,{0x02,0x48,0xa9,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0x40,0x03,0xf6,0x80,0x01,0xf2} },
-{  16,0x4372,0,{0x08,0xdf,0xf4,0x80,0x29,0xe4,0x93,0xa3,0xf8,0x54,0x07,0x24,0x0c,0xc8,0xc3,0x33} },
-{  16,0x4382,0,{0xc4,0x54,0x0f,0x44,0x20,0xc8,0x83,0x40,0x04,0xf4,0x56,0x80,0x01,0x46,0xf6,0xdf} },
-{  16,0x4392,0,{0xe4,0x80,0x0b,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x90,0x46,0x61,0xe4,0x7e} },
-{  16,0x43a2,0,{0x01,0x93,0x60,0xbc,0xa3,0xff,0x54,0x3f,0x30,0xe5,0x09,0x54,0x1f,0xfe,0xe4,0x93} },
-{  16,0x43b2,0,{0xa3,0x60,0x01,0x0e,0xcf,0x54,0xc0,0x25,0xe0,0x60,0xa8,0x40,0xb8,0xe4,0x93,0xa3} },
-{  16,0x43c2,0,{0xfa,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca} },
-{  16,0x43d2,0,{0xf0,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca,0xdf,0xe9,0xde,0xe7,0x80,0xbe} },
-{  16,0x43e2,0,{0xc0,0xe0,0xc0,0xf0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0} },
-{  16,0x43f2,0,{0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef} },
-{  16,0x4402,0,{0xc0,0xe0,0xc2,0xca,0xc2,0xcf,0x90,0x79,0x7a,0xe0,0xb4,0x01,0x1f,0x12,0x4b,0xae} },
-{  16,0x4412,0,{0x12,0x47,0x58,0x53,0xa8,0xa0,0x90,0x7f,0xae,0xe4,0xf0,0x12,0x07,0xaa,0x12,0x4b} },
-{  16,0x4422,0,{0xb7,0x90,0x7f,0xae,0x74,0x1f,0xf0,0x43,0xa8,0x05,0x80,0x03,0x53,0xa8,0xa0,0x53} },
-{  16,0x4432,0,{0xa8,0xfa,0x75,0xe8,0x01,0x12,0x09,0x15,0x75,0xe8,0x0d,0x43,0xa8,0x05,0xd0,0xe0} },
-{  16,0x4442,0,{0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0,0xfc,0xd0,0xe0,0xfb,0xd0,0xe0,0xfa} },
-{  16,0x4452,0,{0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0,0x82,0xd0,0x83,0xd0,0xf0,0xd0,0xe0} },
-{   1,0x4462,0,{0x32} },
-{  16,0x4463,0,{0x90,0x7f,0xec,0xe0,0xf5,0x09,0x14,0x60,0x1d,0x14,0x60,0x2a,0x14,0x60,0x37,0x14} },
-{  16,0x4473,0,{0x60,0x44,0x24,0x04,0x70,0x50,0x90,0x79,0x62,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
-{  16,0x4483,0,{0xb5,0x74,0x01,0xf0,0x80,0x47,0x90,0x79,0x63,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
-{  16,0x4493,0,{0xb5,0x74,0x01,0xf0,0x80,0x37,0x90,0x79,0x64,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
-{  16,0x44a3,0,{0xb5,0x74,0x01,0xf0,0x80,0x27,0x90,0x79,0x66,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
-{  16,0x44b3,0,{0xb5,0x74,0x01,0xf0,0x80,0x17,0x90,0x79,0x67,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
-{  15,0x44c3,0,{0xb5,0x74,0x01,0xf0,0x80,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xd3,0x22} },
-{   4,0x44d2,0,{0x8d,0x36,0x8b,0x37} },
-{  16,0x44d6,0,{0x12,0x3f,0xa2,0xea,0x49,0x60,0x57,0x12,0x0c,0x44,0x7e,0x00,0x29,0xff,0xee,0x3a} },
-{  16,0x44e6,0,{0xc9,0xef,0xc9,0x75,0x38,0xff,0xf5,0x39,0x89,0x3a,0xab,0x38,0xaa,0x39,0xa9,0x3a} },
-{  16,0x44f6,0,{0x90,0x00,0x01,0x12,0x0c,0x5d,0xff,0x64,0x04,0x60,0x05,0xef,0x64,0x05,0x70,0x2e} },
-{  16,0x4506,0,{0xef,0xb4,0x04,0x15,0x90,0x00,0x02,0x12,0x0c,0x5d,0x65,0x36,0x70,0x0b,0x90,0x00} },
-{  16,0x4516,0,{0x03,0x12,0x0c,0x5d,0x65,0x37,0x70,0x01,0x22,0x12,0x0c,0x44,0x7e,0x00,0x29,0xff} },
-{  16,0x4526,0,{0xee,0x3a,0xc9,0xef,0xc9,0x75,0x38,0xff,0xf5,0x39,0x89,0x3a,0x80,0xbc,0x7b,0x00} },
-{   4,0x4536,0,{0x7a,0x00,0x79,0x00} },
-{   1,0x453a,0,{0x22} },
-{  16,0x453b,0,{0xe4,0xff,0x7b,0x01,0x90,0x78,0x1c,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0x4c} },
-{  16,0x454b,0,{0xf0,0x90,0x78,0x1c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12} },
-{  16,0x455b,0,{0x0c,0x5d,0xfe,0x90,0x7f,0xec,0xe0,0x6e,0x60,0x13,0xef,0xc3,0x94,0x04,0x50,0x0d} },
-{  16,0x456b,0,{0x90,0x78,0x1d,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x0f,0x80,0xd4,0xbf,0x04,0x09} },
-{  16,0x457b,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x14,0x90,0x79,0x21,0xe0,0xff,0x90,0x78} },
-{  16,0x458b,0,{0x1c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xef,0x12,0x0c,0x8a,0x90,0x7f,0xc5} },
-{   3,0x459b,0,{0x74,0x01,0xf0} },
-{   1,0x459e,0,{0x22} },
-{  14,0x459f,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xee,0xc0,0xe0,0xef,0xc0,0xe0} },
-{  16,0x45ad,0,{0x90,0x79,0x85,0xe0,0x64,0x01,0x60,0x05,0xa3,0xe0,0xb4,0x01,0x2d,0x90,0x79,0x87} },
-{  16,0x45bd,0,{0x74,0x01,0xf0,0xe4,0xff,0x90,0x7f,0xc5,0xe0,0xfe,0xef,0xc3,0x9e,0x50,0x1b,0x74} },
-{  16,0x45cd,0,{0xc0,0x2f,0xf5,0x82,0xe4,0x34,0x7e,0xf5,0x83,0xe0,0xfe,0x74,0x21,0x2f,0xf5,0x82} },
-{  16,0x45dd,0,{0xe4,0x34,0x79,0xf5,0x83,0xee,0xf0,0x0f,0x80,0xdb,0x53,0x91,0xef,0x90,0x7f,0xaa} },
-{   4,0x45ed,0,{0xe0,0x44,0x01,0xf0} },
-{  15,0x45f1,0,{0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xd0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4600,0,{0xe4,0xff,0x7b,0x01,0x90,0x78,0x19,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0x4c} },
-{  16,0x4610,0,{0xf0,0x90,0x78,0x19,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12} },
-{  16,0x4620,0,{0x0c,0x5d,0xfe,0x90,0x7f,0xec,0xe0,0x6e,0x60,0x13,0xef,0xc3,0x94,0x04,0x50,0x0d} },
-{  16,0x4630,0,{0x90,0x78,0x1a,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x0f,0x80,0xd4,0xbf,0x04,0x08} },
-{  16,0x4640,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x19,0xe0,0xfb,0xa3,0xe0,0xfa} },
-{  16,0x4650,0,{0xa3,0xe0,0xf9,0x12,0x0c,0x44,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} },
-{   1,0x4660,0,{0x22} },
-{  16,0x4661,0,{0x01,0x18,0x02,0x01,0x19,0x0a,0x01,0x1c,0x00,0xc1,0x28,0xc1,0x29,0x01,0x1f,0x01} },
-{  15,0x4671,0,{0x44,0x79,0x9f,0x00,0x00,0x00,0x00,0x41,0x79,0xa3,0x00,0x41,0x79,0xa4,0x00} },
-{   4,0x4680,0,{0x41,0x79,0x89,0x00} },
-{  16,0x4684,0,{0x01,0x22,0x01,0x41,0x79,0x31,0xff,0x41,0x79,0x34,0x00,0x4d,0x79,0x35,0x3f,0x3f} },
-{  16,0x4694,0,{0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x4d,0x79,0x42,0x3f,0x3f} },
-{  16,0x46a4,0,{0x06,0x08,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x4d,0x79,0x4f,0x0a,0x0a} },
-{  11,0x46b4,0,{0x09,0x00,0x01,0x09,0x02,0x03,0x04,0x05,0x06,0x07,0x08} },
-{   1,0x46bf,0,{0x00} },
-{  16,0x46c0,0,{0x12,0x0a,0xcd,0x90,0x7f,0xa5,0xe0,0xf5,0x21,0xe5,0x21,0x54,0x01,0xf5,0x21,0x64} },
-{  16,0x46d0,0,{0x01,0x60,0x28,0xe5,0x22,0x64,0x01,0x70,0x22,0x90,0x7f,0xa5,0xe0,0xf5,0x21,0x54} },
-{  16,0x46e0,0,{0x02,0xf5,0x21,0x70,0x03,0x75,0x22,0x01,0x90,0x7f,0xa5,0xe0,0xf5,0x21,0x54,0x04} },
-{  12,0x46f0,0,{0xff,0xf5,0x21,0xbf,0x04,0xd3,0x75,0x22,0x01,0x80,0xce,0x22} },
-{   4,0x46fc,0,{0x53,0xd8,0xf7,0x32} },
-{  16,0x4700,0,{0x02,0x49,0xfa,0x00,0x02,0x3c,0x54,0x00,0x02,0x17,0xe4,0x00,0x02,0x4a,0x12,0x00} },
-{  16,0x4710,0,{0x02,0x37,0xa2,0x00,0x02,0x47,0xff,0x00,0x02,0x4a,0x41,0x00,0x02,0x45,0x9f,0x00} },
-{  16,0x4720,0,{0x02,0x49,0x8e,0x00,0x02,0x49,0xab,0x00,0x02,0x4a,0x58,0x00,0x02,0x4a,0x6f,0x00} },
-{  16,0x4730,0,{0x02,0x4a,0x86,0x00,0x02,0x4a,0x9d,0x00,0x02,0x4a,0xb4,0x00,0x02,0x4a,0xcb,0x00} },
-{  16,0x4740,0,{0x02,0x4a,0xe2,0x00,0x02,0x4a,0xf9,0x00,0x02,0x4b,0x10,0x00,0x02,0x4b,0x27,0x00} },
-{   8,0x4750,0,{0x02,0x4b,0x3e,0x00,0x02,0x4b,0x55,0x00} },
-{  16,0x4758,0,{0xe5,0x18,0x70,0x14,0x90,0x79,0x8c,0xe0,0x04,0xf0,0x90,0x79,0x8b,0xe0,0xc3,0x94} },
-{  16,0x4768,0,{0x00,0x40,0x15,0xe0,0x14,0xf0,0x80,0x10,0x90,0x79,0x8b,0xe0,0x04,0xf0,0xa3,0xe0} },
-{  16,0x4778,0,{0xc3,0x94,0x00,0x40,0x03,0xe0,0x14,0xf0,0x90,0x79,0x8b,0xe0,0xd3,0x94,0x14,0x40} },
-{  16,0x4788,0,{0x04,0xe4,0xf5,0x18,0xf0,0x90,0x79,0x8c,0xe0,0xd3,0x94,0x14,0x40,0x05,0x75,0x18} },
-{   4,0x4798,0,{0x01,0xe4,0xf0,0x22} },
-{  16,0x479c,0,{0x90,0x7f,0xd7,0xe0,0xf5,0x33,0x90,0x7f,0xec,0xe0,0xf5,0x09,0x14,0x60,0x11,0x14} },
-{  16,0x47ac,0,{0x60,0x1b,0x24,0x02,0x70,0x24,0x90,0x7f,0xea,0xe0,0x90,0x79,0x62,0xf0,0x80,0x21} },
-{  16,0x47bc,0,{0x90,0x7f,0xea,0xe0,0x90,0x79,0x63,0xf0,0x12,0x10,0x00,0x80,0x14,0x90,0x7f,0xea} },
-{  16,0x47cc,0,{0xe0,0x90,0x79,0x64,0xf0,0x12,0x28,0x01,0x80,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
-{   2,0x47dc,0,{0xf0,0xd3} },
-{   1,0x47de,0,{0x22} },
-{  16,0x47df,0,{0x90,0x79,0x78,0x74,0x04,0xf0,0x90,0x79,0x33,0xe0,0x90,0x79,0x79,0xf0,0xa2,0xaf} },
-{  16,0x47ef,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x22} },
-{   1,0x47ff,0,{0x32} },
-{   2,0x4800,0,{0x8f,0x36} },
-{  16,0x4802,0,{0xe4,0xf5,0x37,0x75,0x38,0xff,0x75,0x39,0x07,0x75,0x3a,0x01,0xab,0x38,0xaa,0x39} },
-{  16,0x4812,0,{0xa9,0x3a,0x90,0x00,0x01,0x12,0x0c,0x5d,0xb4,0x03,0x1f,0xaf,0x37,0x05,0x37,0xef} },
-{  16,0x4822,0,{0x65,0x36,0x70,0x01,0x22,0x12,0x0c,0x44,0x7e,0x00,0x29,0xff,0xee,0x3a,0xc9,0xef} },
-{  16,0x4832,0,{0xc9,0x75,0x38,0xff,0xf5,0x39,0x89,0x3a,0x80,0xd2,0x7b,0x00,0x7a,0x00,0x79,0x00} },
-{   1,0x4842,0,{0x22} },
-{  16,0x4843,0,{0x30,0x26,0x2f,0xc2,0x26,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0xe4,0xf5,0x0c} },
-{  16,0x4853,0,{0x75,0x0d,0xf8,0x75,0x0e,0x0a,0xef,0xb4,0x02,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0xf0} },
-{  16,0x4863,0,{0x75,0x0e,0x0b,0xef,0xb4,0x03,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0xf8,0x75,0x0e,0x17} },
-{   3,0x4873,0,{0xd2,0x22,0x22} },
-{  16,0x4876,0,{0x30,0x25,0x2f,0xc2,0x25,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0x75,0x0c,0xc0} },
-{  16,0x4886,0,{0x75,0x0d,0x14,0x75,0x0e,0x0b,0xef,0xb4,0x02,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0x10} },
-{  16,0x4896,0,{0x75,0x0e,0x0c,0xef,0xb4,0x03,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0x18,0x75,0x0e,0x18} },
-{   3,0x48a6,0,{0xd2,0x22,0x22} },
-{  16,0x48a9,0,{0xe4,0xf5,0x32,0x12,0x0f,0x50,0x20,0x2e,0x10,0xe5,0x32,0xc3,0x94,0x02,0x50,0x09} },
-{  16,0x48b9,0,{0x05,0x32,0xd2,0x30,0x12,0x49,0x05,0x80,0xed,0x30,0x2e,0x05,0x12,0x14,0x57,0xc2} },
-{  15,0x48c9,0,{0x2e,0x30,0x2d,0x06,0x12,0x07,0x9a,0x12,0x48,0xd9,0x12,0x40,0x00,0x80,0xea} },
-{   1,0x48d8,0,{0x22} },
-{  16,0x48d9,0,{0x90,0x7f,0xd6,0xe0,0xf5,0x1d,0x54,0x80,0xf5,0x1d,0x64,0x80,0x70,0x1d,0xc2,0xaf} },
-{  16,0x48e9,0,{0xe0,0x44,0x80,0xf0,0xe0,0x44,0x01,0xf0,0x7f,0x0c,0x7e,0x00,0x12,0x4b,0x6c,0x90} },
-{  12,0x48f9,0,{0x7f,0xd6,0xe0,0x54,0xfe,0xf0,0x53,0x87,0xfe,0xd2,0xaf,0x22} },
-{  16,0x4905,0,{0x90,0x7f,0xd6,0xe0,0x54,0xfb,0xf0,0xe0,0x44,0x08,0xf0,0x30,0x30,0x04,0xe0,0x44} },
-{  16,0x4915,0,{0x02,0xf0,0x7f,0xdc,0x7e,0x05,0x12,0x4b,0x6c,0x90,0x7f,0xd6,0xe0,0x54,0xf7,0xf0} },
-{   5,0x4925,0,{0xe0,0x44,0x04,0xf0,0x22} },
-{  16,0x492a,0,{0x90,0x7f,0xeb,0xe0,0x14,0x70,0x14,0x90,0x7f,0xe9,0xe0,0x24,0x7f,0x70,0x04,0x12} },
-{  16,0x493a,0,{0x46,0x00,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44} },
-{   3,0x494a,0,{0x01,0xf0,0x22} },
-{  16,0x494d,0,{0x90,0x7f,0xeb,0xe0,0x14,0x70,0x13,0x90,0x7f,0xe9,0xe0,0x14,0x70,0x04,0x12,0x45} },
-{  16,0x495d,0,{0x3b,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
-{   2,0x496d,0,{0xf0,0x22} },
-{  16,0x496f,0,{0xe4,0xff,0x74,0xe8,0x2f,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xe0,0xfe,0x74,0x96} },
-{  14,0x497f,0,{0x2f,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xee,0xf0,0x0f,0xbf,0x08,0xe4} },
-{   1,0x498d,0,{0x22} },
-{  16,0x498e,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x02,0xf0} },
-{  13,0x499e,0,{0x90,0x7f,0xb7,0x74,0x03,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x49ab,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x02,0xf0} },
-{  13,0x49bb,0,{0x90,0x7f,0xc7,0x74,0x03,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x49c8,0,{0x90,0x7f,0xd6,0xe0,0x30,0xe7,0x12,0xe0,0x44,0x01,0xf0,0x7f,0x14,0x7e,0x00,0x12} },
-{  10,0x49d8,0,{0x4b,0x6c,0x90,0x7f,0xd6,0xe0,0x54,0xfe,0xf0,0x22} },
-{  16,0x49e2,0,{0xe4,0xf5,0x1a,0x75,0x1b,0x01,0x90,0x79,0x91,0x04,0xf0,0xa3,0xf0,0xe4,0xa3,0xf0} },
-{   8,0x49f2,0,{0xa3,0x74,0x0a,0xf0,0xe4,0xa3,0xf0,0x22} },
-{  16,0x49fa,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xd2,0x2e,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x01} },
-{   8,0x4a0a,0,{0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4a12,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xd2,0x2d,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x08} },
-{   8,0x4a22,0,{0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4a2a,0,{0x90,0x7f,0xea,0xe0,0xf5,0x08,0xe4,0x90,0x79,0x62,0xf0,0xa3,0xf0,0xa3,0xf0,0x90} },
-{   7,0x4a3a,0,{0x79,0x66,0xf0,0xa3,0xf0,0xd3,0x22} },
-{  16,0x4a41,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x01,0xf0} },
-{   7,0x4a51,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4a58,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x04,0xf0} },
-{   7,0x4a68,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4a6f,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x04,0xf0} },
-{   7,0x4a7f,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4a86,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x08,0xf0} },
-{   7,0x4a96,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4a9d,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x08,0xf0} },
-{   7,0x4aad,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4ab4,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x10,0xf0} },
-{   7,0x4ac4,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4acb,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x10,0xf0} },
-{   7,0x4adb,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4ae2,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x20,0xf0} },
-{   7,0x4af2,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4af9,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x20,0xf0} },
-{   7,0x4b09,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4b10,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x40,0xf0} },
-{   7,0x4b20,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4b27,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x40,0xf0} },
-{   7,0x4b37,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4b3e,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x80,0xf0} },
-{   7,0x4b4e,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4b55,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x80,0xf0} },
-{   7,0x4b65,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x4b6c,0,{0x8e,0x33,0x8f,0x34,0xe5,0x34,0x15,0x34,0xae,0x33,0x70,0x02,0x15,0x33,0x4e,0x60} },
-{   7,0x4b7c,0,{0x05,0x12,0x07,0x89,0x80,0xee,0x22} },
-{  15,0x4b83,0,{0x90,0x7f,0xea,0xe0,0xb4,0xff,0x04,0x12,0x30,0x00,0x22,0x12,0x36,0x0e,0x22} },
-{  14,0x4b92,0,{0xc0,0xe0,0xc2,0x8b,0xd2,0x24,0x30,0x23,0x02,0xc2,0x23,0xd0,0xe0,0x32} },
-{  14,0x4ba0,0,{0x90,0x7f,0x00,0xe5,0x08,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0,0xd3,0x22} },
-{   9,0x4bae,0,{0x30,0x24,0x05,0xc2,0x24,0x75,0x18,0x01,0x22} },
-{   9,0x4bb7,0,{0x30,0x23,0x05,0xc2,0x23,0xe4,0xf5,0x18,0x22} },
-{   7,0x4bc0,0,{0x53,0xc0,0xfe,0x53,0xc0,0xfd,0x32} },
-{   6,0x4bc7,0,{0x53,0x91,0x7f,0xd2,0x25,0x32} },
-{   5,0x4bcd,0,{0xc2,0x89,0xd2,0x23,0x32} },
-{   3,0x4bd2,0,{0xc2,0x8d,0x32} },
-{   3,0x4bd5,0,{0xc2,0x8f,0x32} },
-{   2,0x4bd8,0,{0xd3,0x22} },
-{   2,0x4bda,0,{0xd3,0x22} },
-{   2,0x4bdc,0,{0xd3,0x22} },
-{   2,0x4bde,0,{0xd3,0x22} },
-{   2,0x4be0,0,{0xd3,0x22} },
-{   2,0x4be2,0,{0xd3,0x22} },
-{   2,0x4be4,0,{0xc3,0x22} },
-{   1,0x4be6,0,{0x22} },
-{   0,0x0000,1,{0 }}
-};
-/*
-VERSION=1.0.2.916
-DATE=12.02.2002
-*/
-/*
- * This firmware is for the Emagic EMI 2|6 Audio Interface
- *
- * The firmware contained herein is Copyright (c) 1999-2002 Emagic
- * as an unpublished work. This notice does not imply unrestricted
- * or public access to this firmware which is a trade secret of Emagic,
- * and which may not be reproduced, used, sold or transferred to
- * any third party without Emagic's written consent. All Rights Reserved.
- *
- * This firmware may not be modified and may only be used with the
- * Emagic EMI 2|6 Audio Interface. Distribution and/or Modification of
- * any driver which includes this firmware, in whole or in part,
- * requires the inclusion of this statement.
- */
-INTEL_HEX_RECORD g_Loader[] = {
-{   3,0x0000,0,{0x02,0x03,0x1c} },
-{   3,0x0043,0,{0x02,0x04,0x00} },
-{  16,0x0100,0,{0x90,0x7f,0xe9,0xe0,0x24,0x5b,0x60,0x60,0x24,0x02,0x60,0x03,0x02,0x01,0xbe,0x90} },
-{  16,0x0110,0,{0x7f,0xea,0xe0,0x75,0x0a,0x00,0xf5,0x0b,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x0a,0x90} },
-{  16,0x0120,0,{0x7f,0xee,0xe0,0x75,0x15,0x00,0xf5,0x16,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x15,0xe5} },
-{  16,0x0130,0,{0x16,0x45,0x15,0x70,0x03,0x02,0x01,0xbe,0xe4,0x90,0x7f,0xc5,0xf0,0x90,0x7f,0xb4} },
-{  16,0x0140,0,{0xe0,0x20,0xe3,0xf9,0x90,0x7f,0xc5,0xe0,0xf5,0x0c,0x12,0x02,0x77,0xaf,0x0c,0x7e} },
-{  16,0x0150,0,{0x00,0xef,0x25,0x0b,0xf5,0x0b,0xee,0x35,0x0a,0xf5,0x0a,0xc3,0xe5,0x16,0x9f,0xf5} },
-{  16,0x0160,0,{0x16,0xe5,0x15,0x9e,0xf5,0x15,0x80,0xc7,0x90,0x7f,0xea,0xe0,0x75,0x0a,0x00,0xf5} },
-{  16,0x0170,0,{0x0b,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x0a,0x90,0x7f,0xee,0xe0,0x75,0x15,0x00,0xf5} },
-{  16,0x0180,0,{0x16,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x15,0xe5,0x16,0x45,0x15,0x60,0x30,0xe4,0x90} },
-{  16,0x0190,0,{0x7f,0xc5,0xf0,0x90,0x7f,0xb4,0xe0,0x20,0xe3,0xf9,0x90,0x7f,0xc5,0xe0,0xf5,0x0c} },
-{  16,0x01a0,0,{0x12,0x02,0x8f,0xaf,0x0c,0x7e,0x00,0xef,0x25,0x0b,0xf5,0x0b,0xee,0x35,0x0a,0xf5} },
-{  15,0x01b0,0,{0x0a,0xc3,0xe5,0x16,0x9f,0xf5,0x16,0xe5,0x15,0x9e,0xf5,0x15,0x80,0xca,0xc3} },
-{   1,0x01bf,0,{0x22} },
-{  16,0x01c0,0,{0xc2,0x20,0xd2,0xe8,0x43,0xd8,0x20,0x90,0x7f,0xab,0x74,0xff,0xf0,0x90,0x7f,0xa9} },
-{  16,0x01d0,0,{0xf0,0x90,0x7f,0xaa,0xf0,0x53,0x91,0xef,0x90,0x7f,0x95,0xe0,0x44,0xc0,0xf0,0x90} },
-{  16,0x01e0,0,{0x7f,0x98,0xe0,0x44,0xc0,0xf0,0x90,0x7f,0x9e,0xe0,0x44,0xc0,0xf0,0xe4,0x90,0x7f} },
-{  16,0x01f0,0,{0x94,0xf0,0x90,0x7f,0x9d,0xe0,0x44,0x0f,0xf0,0x90,0x7f,0x97,0xe0,0x54,0xf0,0xf0} },
-{  16,0x0200,0,{0x90,0x7f,0xaf,0xe0,0x44,0x01,0xf0,0x90,0x7f,0xae,0xe0,0x44,0x0d,0xf0,0xd2,0xaf} },
-{  16,0x0210,0,{0x90,0x7f,0x97,0xe0,0x54,0xf0,0xf0,0x20,0x20,0x42,0x75,0x14,0x00,0x75,0x13,0x00} },
-{  16,0x0220,0,{0x75,0x12,0x00,0x75,0x11,0x00,0x7f,0x48,0x7e,0x92,0x7d,0x00,0x7c,0x00,0xab,0x14} },
-{  16,0x0230,0,{0xaa,0x13,0xa9,0x12,0xa8,0x11,0xc3,0x12,0x04,0x9a,0x50,0xdb,0x20,0x20,0xd8,0x7a} },
-{  16,0x0240,0,{0x00,0x79,0x00,0x78,0x00,0xe5,0x14,0x24,0x01,0xf5,0x14,0xea,0x35,0x13,0xf5,0x13} },
-{  16,0x0250,0,{0xe9,0x35,0x12,0xf5,0x12,0xe8,0x35,0x11,0xf5,0x11,0x80,0xca,0x30,0x20,0xfd,0x12} },
-{  16,0x0260,0,{0x01,0x00,0x50,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x90,0x7f,0xb4,0xe0,0x44} },
-{   6,0x0270,0,{0x02,0xf0,0xc2,0x20,0x80,0xe6} },
-{   1,0x0276,0,{0x22} },
-{  16,0x0277,0,{0xe5,0x0c,0xff,0xe5,0x0b,0xf5,0x82,0xe5,0x0a,0xf5,0x83,0x75,0x92,0x7e,0x74,0xc0} },
-{   8,0x0287,0,{0xf8,0xe2,0x08,0xf0,0xa3,0xdf,0xfa,0x22} },
-{  16,0x028f,0,{0x90,0x7f,0x96,0x85,0x83,0x92,0xa8,0x82,0x79,0x02,0x90,0x00,0x00,0xe0,0xb4,0x00} },
-{  16,0x029f,0,{0x37,0x74,0x01,0xf0,0x90,0x7f,0x93,0xe0,0x54,0xfc,0xf0,0x90,0x7f,0x96,0xe0,0x54} },
-{  16,0x02af,0,{0xfc,0xf0,0x90,0x7f,0x9c,0xe0,0x44,0x03,0xf0,0x90,0x7f,0x94,0xe0,0x54,0x7f,0xf0} },
-{  16,0x02bf,0,{0x90,0x7f,0x97,0xe0,0x44,0x80,0xf0,0x90,0x7f,0x9d,0xe0,0x44,0x80,0xf0,0x90,0x7f} },
-{  16,0x02cf,0,{0x97,0xe0,0x54,0x7f,0xf0,0x44,0x80,0xf0,0xe5,0x0c,0xff,0x90,0x7e,0xc0,0xe0,0xf5} },
-{  16,0x02df,0,{0x28,0xe4,0xa2,0x47,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x46,0x33,0xf2,0x69,0xf2,0xe4} },
-{  16,0x02ef,0,{0xa2,0x45,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x44,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x43} },
-{  16,0x02ff,0,{0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x42,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x41,0x33,0xf2} },
-{  13,0x030f,0,{0x69,0xf2,0xe4,0xa2,0x40,0x33,0xf2,0x69,0xf2,0xa3,0xdf,0xc2,0x22} },
-{  12,0x031c,0,{0x78,0x7f,0xe4,0xf6,0xd8,0xfd,0x75,0x81,0x29,0x02,0x03,0x63} },
-{  16,0x0328,0,{0x02,0x01,0xc0,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0x40,0x03,0xf6,0x80,0x01,0xf2} },
-{  16,0x0338,0,{0x08,0xdf,0xf4,0x80,0x29,0xe4,0x93,0xa3,0xf8,0x54,0x07,0x24,0x0c,0xc8,0xc3,0x33} },
-{  16,0x0348,0,{0xc4,0x54,0x0f,0x44,0x20,0xc8,0x83,0x40,0x04,0xf4,0x56,0x80,0x01,0x46,0xf6,0xdf} },
-{  16,0x0358,0,{0xe4,0x80,0x0b,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x90,0x04,0x84,0xe4,0x7e} },
-{  16,0x0368,0,{0x01,0x93,0x60,0xbc,0xa3,0xff,0x54,0x3f,0x30,0xe5,0x09,0x54,0x1f,0xfe,0xe4,0x93} },
-{  16,0x0378,0,{0xa3,0x60,0x01,0x0e,0xcf,0x54,0xc0,0x25,0xe0,0x60,0xa8,0x40,0xb8,0xe4,0x93,0xa3} },
-{  16,0x0388,0,{0xfa,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca} },
-{  16,0x0398,0,{0xf0,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca,0xdf,0xe9,0xde,0xe7,0x80,0xbe} },
-{  16,0x03a8,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x90,0x7f,0xc4,0xe4,0xf0,0x53,0x91,0xef,0x90,0x7f} },
-{  11,0x03b8,0,{0xab,0x74,0x04,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x03c3,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xd2,0x20,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x01} },
-{   8,0x03d3,0,{0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x03db,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x02,0xf0,0xd0} },
-{   6,0x03eb,0,{0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{   1,0x03f1,0,{0x32} },
-{   1,0x03f2,0,{0x32} },
-{   1,0x03f3,0,{0x32} },
-{   1,0x03f4,0,{0x32} },
-{   1,0x03f5,0,{0x32} },
-{   1,0x03f6,0,{0x32} },
-{   1,0x03f7,0,{0x32} },
-{   1,0x03f8,0,{0x32} },
-{   1,0x03f9,0,{0x32} },
-{   1,0x03fa,0,{0x32} },
-{   1,0x03fb,0,{0x32} },
-{   1,0x03fc,0,{0x32} },
-{   1,0x03fd,0,{0x32} },
-{   1,0x03fe,0,{0x32} },
-{   1,0x03ff,0,{0x32} },
-{  16,0x0400,0,{0x02,0x03,0xc3,0x00,0x02,0x03,0xdb,0x00,0x02,0x03,0xa8,0x00,0x02,0x04,0x6e,0x00} },
-{  16,0x0410,0,{0x02,0x04,0x58,0x00,0x02,0x03,0xf1,0x00,0x02,0x03,0xf2,0x00,0x02,0x03,0xf3,0x00} },
-{  16,0x0420,0,{0x02,0x03,0xf4,0x00,0x02,0x03,0xf5,0x00,0x02,0x03,0xf6,0x00,0x02,0x03,0xf7,0x00} },
-{  16,0x0430,0,{0x02,0x03,0xf8,0x00,0x02,0x03,0xf9,0x00,0x02,0x03,0xfa,0x00,0x02,0x03,0xfb,0x00} },
-{  16,0x0440,0,{0x02,0x03,0xfc,0x00,0x02,0x03,0xfd,0x00,0x02,0x03,0xfe,0x00,0x02,0x03,0xff,0x00} },
-{   8,0x0450,0,{0x02,0x04,0xab,0x00,0x02,0x04,0xac,0x00} },
-{  16,0x0458,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x10,0xf0,0xd0} },
-{   6,0x0468,0,{0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x046e,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x08,0xf0,0xd0} },
-{   6,0x047e,0,{0x82,0xd0,0x83,0xd0,0xe0,0x32} },
-{  16,0x0484,0,{0x02,0x0a,0x00,0x0f,0x01,0x0c,0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x41,0x00,0x00} },
-{   1,0x0494,0,{0x00} },
-{   4,0x0495,0,{0x02,0x17,0x00,0x00} },
-{   1,0x0499,0,{0x00} },
-{  16,0x049a,0,{0xeb,0x9f,0xf5,0xf0,0xea,0x9e,0x42,0xf0,0xe9,0x9d,0x42,0xf0,0xe8,0x9c,0x45,0xf0} },
-{   1,0x04aa,0,{0x22} },
-{   1,0x04ab,0,{0x32} },
-{   1,0x04ac,0,{0x32} },
-{  16,0x1100,0,{0x12,0x01,0x10,0x01,0x00,0x00,0x00,0x40,0x6a,0x08,0x01,0x01,0x00,0x01,0x01,0x02} },
-{  16,0x1110,0,{0x00,0x01,0x09,0x02,0x20,0x00,0x01,0x01,0x03,0xa0,0x00,0x09,0x04,0x00,0x00,0x02} },
-{  16,0x1120,0,{0xff,0x00,0x00,0x04,0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40} },
-{  16,0x1130,0,{0x00,0x00,0x04,0x03,0x09,0x04,0x26,0x03,0x41,0x00,0x6e,0x00,0x63,0x00,0x68,0x00} },
-{  16,0x1140,0,{0x6f,0x00,0x72,0x00,0x20,0x00,0x43,0x00,0x68,0x00,0x69,0x00,0x70,0x00,0x73,0x00} },
-{  16,0x1150,0,{0x2c,0x00,0x20,0x00,0x49,0x00,0x6e,0x00,0x63,0x00,0x2e,0x00,0x28,0x03,0x46,0x00} },
-{  16,0x1160,0,{0x69,0x00,0x72,0x00,0x6d,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00} },
-{  16,0x1170,0,{0x46,0x00,0x72,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x57,0x00,0x6f,0x00,0x72,0x00} },
-{  16,0x1180,0,{0x6b,0x00,0x73,0x00,0x2a,0x03,0x43,0x00,0x6f,0x00,0x6e,0x00,0x66,0x00,0x69,0x00} },
-{  16,0x1190,0,{0x67,0x00,0x75,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00} },
-{  16,0x11a0,0,{0x20,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x22,0x03} },
-{  16,0x11b0,0,{0x49,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x66,0x00,0x61,0x00,0x63,0x00} },
-{  16,0x11c0,0,{0x65,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x67,0x00} },
-{   2,0x11d0,0,{0x00,0x00} },
-{   0,0x0000,1,{0 }}
-};
diff -Nru a/drivers/usb/hcd/Config.help b/drivers/usb/hcd/Config.help
--- a/drivers/usb/hcd/Config.help	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,37 +0,0 @@
-CONFIG_USB_EHCI_HCD
-  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
-  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
-  If your USB host controller supports USB 2.0, you will likely want to
-  configure this Host Controller Driver.  At this writing, the primary
-  implementation of EHCI is a chip from NEC, widely available in add-on
-  PCI cards, but implementations are in the works from other vendors
-  including Intel and Philips.  Motherboard support is appearing.
-
-  EHCI controllers are packaged with "companion" host controllers (OHCI
-  or UHCI) to handle USB 1.1 devices connected to root hub ports.  Ports
-  will connect to EHCI if it the device is high speed, otherwise they
-  connect to a companion controller.  If you configure EHCI, you should
-  probably configure the OHCI (for NEC and some other vendors) USB Host
-  Controller Driver too.
-
-  You may want to read <file:Documentation/usb/ehci.txt>.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called ehci-hcd.o. If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.
-
-CONFIG_USB_OHCI_HCD
-  The Open Host Controller Interface (OHCI) is a standard for accessing
-  USB 1.1 host controller hardware.  It does more in hardware than Intel's
-  UHCI specification.  If your USB host controller follows the OHCI spec,
-  say Y.  On most non-x86 systems, and on x86 hardware that's not using a
-  USB controller from Intel or VIA, this is appropriate.  If your host
-  controller doesn't use PCI, this is probably appropriate.  For a PCI
-  based system where you're not sure, the "lspci -v" entry will list the
-  right "prog-if" for your USB controller(s):  EHCI, OHCI, or UHCI.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called ohci-hcd.o. If you want to compile it
-  as a module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/hcd/Config.in b/drivers/usb/hcd/Config.in
--- a/drivers/usb/hcd/Config.in	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,7 +0,0 @@
-#
-# USB Host Controller Drivers
-#
-dep_tristate '  EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-dep_tristate '  OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-# dep_tristate '  UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
-
diff -Nru a/drivers/usb/hcd/Makefile b/drivers/usb/hcd/Makefile
--- a/drivers/usb/hcd/Makefile	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-#
-# Makefile for USB Host Controller Driver
-# framework and drivers
-#
-
-O_TARGET	:=
-
-obj-$(CONFIG_USB_EHCI_HCD)			+= ehci-hcd.o
-obj-$(CONFIG_USB_OHCI_HCD)			+= ohci-hcd.o
-# obj-$(CONFIG_USB_UHCI_HCD)			+= uhci-hcd.o
-
-# Extract lists of the multi-part drivers.
-# The 'int-*' lists are the intermediate files used to build the multi's.
-multi-y		:= $(filter $(list-multi), $(obj-y))
-multi-m		:= $(filter $(list-multi), $(obj-m))
-int-y		:= $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
-int-m		:= $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
-
-# Take multi-part drivers out of obj-y and put components in.
-obj-y		:= $(filter-out $(list-multi), $(obj-y)) $(int-y)
-
-# Translate to Rules.make lists.
-OX_OBJS		:= $(obj-y)
-MX_OBJS		:= $(obj-m)
-MIX_OBJS	:= $(int-m)
-
-include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/hcd/ehci-dbg.c b/drivers/usb/hcd/ehci-dbg.c
--- a/drivers/usb/hcd/ehci-dbg.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2001 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* this file is part of ehci-hcd.c */
-
-#ifdef EHCI_VERBOSE_DEBUG
-#	define vdbg dbg
-#else
-	static inline void vdbg (char *fmt, ...) { }
-#endif
-
-#ifdef	DEBUG
-
-/* check the values in the HCSPARAMS register - host controller structural parameters */
-/* see EHCI 0.95 Spec, Table 2-4 for each value */
-static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
-{
-	u32	params = readl (&ehci->caps->hcs_params);
-
-	dbg ("%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d",
-		label, params,
-		HCS_DEBUG_PORT (params),
-		HCS_INDICATOR (params) ? " ind" : "",
-		HCS_N_CC (params),
-		HCS_N_PCC (params),
-	        HCS_PORTROUTED (params) ? "" : " ordered",
-		HCS_PPC (params) ? "" : " !ppc",
-		HCS_N_PORTS (params)
-		);
-	/* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */
-	if (HCS_PORTROUTED (params)) {
-		int i;
-		char buf [46], tmp [7], byte;
-
-		buf[0] = 0;
-		for (i = 0; i < HCS_N_PORTS (params); i++) {
-			byte = readb (&ehci->caps->portroute[(i>>1)]);
-			sprintf(tmp, "%d ", 
-				((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
-			strcat(buf, tmp);
-		}
-		dbg ("%s: %s portroute %s", 
-			ehci->hcd.bus_name, label,
-			buf);
-	}
-}
-#else
-
-static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {}
-
-#endif
-
-#ifdef	DEBUG
-
-/* check the values in the HCCPARAMS register - host controller capability parameters */
-/* see EHCI 0.95 Spec, Table 2-5 for each value */
-static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
-{
-	u32	params = readl (&ehci->caps->hcc_params);
-
-	if (HCC_EXT_CAPS (params)) {
-		// EHCI 0.96 ... could interpret these (legacy?)
-		dbg ("%s extended capabilities at pci %d",
-			label, HCC_EXT_CAPS (params));
-	}
-	if (HCC_ISOC_CACHE (params)) {
-		dbg ("%s hcc_params 0x%04x caching frame %s%s%s",
-		     label, params,
-		     HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
-		     HCC_CANPARK (params) ? " park" : "",
-		     HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
-	} else {
-		dbg ("%s hcc_params 0x%04x caching %d uframes %s%s%s",
-		     label,
-		     params,
-		     HCC_ISOC_THRES (params),
-		     HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
-		     HCC_CANPARK (params) ? " park" : "",
-		     HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
-	}
-}
-#else
-
-static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
-
-#endif
-
-#ifdef	DEBUG
-
-#if 0
-static void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
-{
-	dbg ("%s %p info1 %x info2 %x hw_curr %x qtd_next %x", label,
-		qh, qh->hw_info1, qh->hw_info2,
-		qh->hw_current, qh->hw_qtd_next);
-	dbg ("  alt+errs= %x, token= %x, page0= %x, page1= %x",
-		qh->hw_alt_next, qh->hw_token,
-		qh->hw_buf [0], qh->hw_buf [1]);
-	if (qh->hw_buf [2]) {
-		dbg ("  page2= %x, page3= %x, page4= %x",
-			qh->hw_buf [2], qh->hw_buf [3],
-			qh->hw_buf [4]);
-	}
-}
-#endif
-
-static const char *const fls_strings [] =
-    { "1024", "512", "256", "??" };
-
-#else
-#if 0
-static inline void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {}
-#endif
-#endif	/* DEBUG */
-
-/* functions have the "wrong" filename when they're output... */
-
-#define dbg_status(ehci, label, status) \
-	dbg ("%s status 0x%x%s%s%s%s%s%s%s%s%s%s", \
-		label, status, \
-		(status & STS_ASS) ? " Async" : "", \
-		(status & STS_PSS) ? " Periodic" : "", \
-		(status & STS_RECL) ? " Recl" : "", \
-		(status & STS_HALT) ? " Halt" : "", \
-		(status & STS_IAA) ? " IAA" : "", \
-		(status & STS_FATAL) ? " FATAL" : "", \
-		(status & STS_FLR) ? " FLR" : "", \
-		(status & STS_PCD) ? " PCD" : "", \
-		(status & STS_ERR) ? " ERR" : "", \
-		(status & STS_INT) ? " INT" : "" \
-		)
-
-#define dbg_cmd(ehci, label, command) \
-	dbg ("%s %x cmd %s=%d ithresh=%d%s%s%s%s period=%s%s %s", \
-		label, command, \
-		(command & CMD_PARK) ? "park" : "(park)", \
-		CMD_PARK_CNT (command), \
-		(command >> 16) & 0x3f, \
-		(command & CMD_LRESET) ? " LReset" : "", \
-		(command & CMD_IAAD) ? " IAAD" : "", \
-		(command & CMD_ASE) ? " Async" : "", \
-		(command & CMD_PSE) ? " Periodic" : "", \
-		fls_strings [(command >> 2) & 0x3], \
-		(command & CMD_RESET) ? " Reset" : "", \
-		(command & CMD_RUN) ? "RUN" : "HALT" \
-		)
-
-#define dbg_port(hcd, label, port, status) \
-	dbg ("%s port %d status 0x%x%s%s speed=%d%s%s%s%s%s%s%s%s%s", \
-		label, port, status, \
-		(status & PORT_OWNER) ? " OWNER" : "", \
-		(status & PORT_POWER) ? " POWER" : "", \
-		(status >> 10) & 3, \
-		(status & PORT_RESET) ? " RESET" : "", \
-		(status & PORT_SUSPEND) ? " SUSPEND" : "", \
-		(status & PORT_RESUME) ? " RESUME" : "", \
-		(status & PORT_OCC) ? " OCC" : "", \
-		(status & PORT_OC) ? " OC" : "", \
-		(status & PORT_PEC) ? " PEC" : "", \
-		(status & PORT_PE) ? " PE" : "", \
-		(status & PORT_CSC) ? " CSC" : "", \
-		(status & PORT_CONNECT) ? " CONNECT" : "" \
-	    )
-
diff -Nru a/drivers/usb/hcd/ehci-hcd.c b/drivers/usb/hcd/ehci-hcd.c
--- a/drivers/usb/hcd/ehci-hcd.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,761 +0,0 @@
-/*
- * Copyright (c) 2000-2002 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
-#include <linux/usb.h>
-#include "../hcd.h"
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-
-//#undef KERN_DEBUG
-//#define KERN_DEBUG ""
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI hc_driver implementation ... experimental, incomplete.
- * Based on the 0.96 register interface specification.
- *
- * There are lots of things to help out with here ... notably
- * everything "periodic", and of course testing with all sorts
- * of usb 2.0 devices and configurations.
- *
- * USB 2.0 shows up in upcoming www.pcmcia.org technology.
- * First was PCMCIA, like ISA; then CardBus, which is PCI.
- * Next comes "CardBay", using USB 2.0 signals.
- *
- * Contains additional contributions by:
- *	Brad Hards
- *	Rory Bolt
- *	...
- *
- * HISTORY:
- *
- * 2002-03-05	Initial high-speed ISO support; reduce ITD memory; shift
- *	more checking to generic hcd framework (db).  Make it work with
- *	Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
- * 2002-01-14	Minor cleanup; version synch.
- * 2002-01-08	Fix roothub handoff of FS/LS to companion controllers.
- * 2002-01-04	Control/Bulk queuing behaves.
- *
- * 2001-12-12	Initial patch version for Linux 2.5.1 kernel.
- * 2001-June	Works with usb-storage and NEC EHCI on 2.4
- */
-
-#define DRIVER_VERSION "$Revision: 0.27 $"
-#define DRIVER_AUTHOR "David Brownell"
-#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
-
-
-// #define EHCI_VERBOSE_DEBUG
-// #define have_split_iso
-
-#ifdef	CONFIG_DEBUG_SLAB
-#	define	EHCI_SLAB_FLAGS		(SLAB_POISON)
-#else
-#	define	EHCI_SLAB_FLAGS		0
-#endif
-
-/* magic numbers that can affect system performance */
-#define	EHCI_TUNE_CERR		3	/* 0-3 qtd retries; 0 == don't stop */
-#define	EHCI_TUNE_RL_HS		0	/* nak throttle; see 4.9 */
-#define	EHCI_TUNE_RL_TT		0
-#define	EHCI_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
-#define	EHCI_TUNE_MULT_TT	1
-
-/* Initial IRQ latency:  lower than default */
-static int log2_irq_thresh = 0;		// 0 to 6
-MODULE_PARM (log2_irq_thresh, "i");
-MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
-
-#define	INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT)
-
-/*-------------------------------------------------------------------------*/
-
-#include "ehci.h"
-#include "ehci-dbg.c"
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * hc states include: unknown, halted, ready, running
- * transitional states are messy just now
- * trying to avoid "running" unless urbs are active
- * a "ready" hc can be finishing prefetched work
- */
-
-/* halt a non-running controller */
-static void ehci_reset (struct ehci_hcd *ehci)
-{
-	u32	command = readl (&ehci->regs->command);
-
-	command |= CMD_RESET;
-	dbg_cmd (ehci, "reset", command);
-	writel (command, &ehci->regs->command);
-	while (readl (&ehci->regs->command) & CMD_RESET)
-		continue;
-	ehci->hcd.state = USB_STATE_HALT;
-}
-
-/* idle the controller (from running) */
-static void ehci_ready (struct ehci_hcd *ehci)
-{
-	u32	command;
-
-#ifdef DEBUG
-	if (!HCD_IS_RUNNING (ehci->hcd.state))
-		BUG ();
-#endif
-
-	while (!(readl (&ehci->regs->status) & (STS_ASS | STS_PSS)))
-		udelay (100);
-	command = readl (&ehci->regs->command);
-	command &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
-	writel (command, &ehci->regs->command);
-
-	// hardware can take 16 microframes to turn off ...
-	ehci->hcd.state = USB_STATE_READY;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#include "ehci-hub.c"
-#include "ehci-mem.c"
-#include "ehci-q.c"
-#include "ehci-sched.c"
-
-/*-------------------------------------------------------------------------*/
-
-static void ehci_tasklet (unsigned long param);
-
-/* called by khubd or root hub init threads */
-
-static int ehci_start (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	u32			temp;
-	struct usb_device	*udev;
-	int			retval;
-	u32			hcc_params;
-	u8                      tempbyte;
-
-	// FIXME:  given EHCI 0.96 or later, and a controller with
-	// the USBLEGSUP/USBLEGCTLSTS extended capability, make sure
-	// the BIOS doesn't still own this controller.
-
-	spin_lock_init (&ehci->lock);
-
-	ehci->caps = (struct ehci_caps *) hcd->regs;
-	ehci->regs = (struct ehci_regs *) (hcd->regs + ehci->caps->length);
-	dbg_hcs_params (ehci, "ehci_start");
-	dbg_hcc_params (ehci, "ehci_start");
-
-	/* cache this readonly data; minimize PCI reads */
-	ehci->hcs_params = readl (&ehci->caps->hcs_params);
-
-	/*
-	 * hw default: 1K periodic list heads, one per frame.
-	 * periodic_size can shrink by USBCMD update if hcc_params allows.
-	 */
-	ehci->periodic_size = DEFAULT_I_TDPS;
-	if ((retval = ehci_mem_init (ehci, EHCI_SLAB_FLAGS | SLAB_KERNEL)) < 0)
-		return retval;
-	hcc_params = readl (&ehci->caps->hcc_params);
-
-	/* controllers may cache some of the periodic schedule ... */
-	if (HCC_ISOC_CACHE (hcc_params)) 	// full frame cache
-		ehci->i_thresh = 8;
-	else					// N microframes cached
-		ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params);
-
-	ehci->async = 0;
-	ehci->reclaim = 0;
-	ehci->next_uframe = -1;
-
-	/* controller state:  unknown --> reset */
-
-	/* EHCI spec section 4.1 */
-	ehci_reset (ehci);
-	writel (INTR_MASK, &ehci->regs->intr_enable);
-	writel (ehci->periodic_dma, &ehci->regs->frame_list);
-
-	/*
-	 * hcc_params controls whether ehci->regs->segment must (!!!)
-	 * be used; it constrains QH/ITD/SITD and QTD locations.
-	 * By default, pci_alloc_consistent() won't hand out addresses
-	 * above 4GB (via pdev->dma_mask) so we know this value.
-	 *
-	 * NOTE:  that pdev->dma_mask setting means that all DMA mappings
-	 * for I/O buffers will have the same restriction, though it's
-	 * neither necessary nor desirable in that case.
-	 */
-	if (HCC_64BIT_ADDR (hcc_params)) {
-		writel (0, &ehci->regs->segment);
-		info ("using segment 0 for 64bit DMA addresses ...");
-	}
-
-	/* clear interrupt enables, set irq latency */
-	temp = readl (&ehci->regs->command) & 0xff;
-	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
-	    log2_irq_thresh = 0;
-	temp |= 1 << (16 + log2_irq_thresh);
-	// keeping default periodic framelist size
-	temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE),
-	writel (temp, &ehci->regs->command);
-	dbg_cmd (ehci, "init", temp);
-
-	/* set async sleep time = 10 us ... ? */
-
-	ehci->tasklet.func = ehci_tasklet;
-	ehci->tasklet.data = (unsigned long) ehci;
-
-	/* wire up the root hub */
-	hcd->bus->root_hub = udev = usb_alloc_dev (NULL, hcd->bus);
-	if (!udev) {
-done2:
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-
-	/*
-	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
-	 * are explicitly handed to companion controller(s), so no TT is
-	 * involved with the root hub.
-	 */
-	ehci->hcd.state = USB_STATE_READY;
-	writel (FLAG_CF, &ehci->regs->configured_flag);
-	readl (&ehci->regs->command);	/* unblock posted write */
-
-        /* PCI Serial Bus Release Number is at 0x60 offset */
-	pci_read_config_byte(hcd->pdev, 0x60, &tempbyte);
-	temp = readw (&ehci->caps->hci_version);
-	info ("USB %x.%x support enabled, EHCI rev %x.%2x",
-	      ((tempbyte & 0xf0)>>4),
-	      (tempbyte & 0x0f),
-	       temp >> 8,
-	       temp & 0xff);
-
-	/*
-	 * From here on, khubd concurrently accesses the root
-	 * hub; drivers will be talking to enumerated devices.
-	 *
-	 * Before this point the HC was idle/ready.  After, khubd
-	 * and device drivers may start it running.
-	 */
-	usb_connect (udev);
-	udev->speed = USB_SPEED_HIGH;
-	if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) {
-		if (hcd->state == USB_STATE_RUNNING)
-			ehci_ready (ehci);
-		while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
-			udelay (100);
-		ehci_reset (ehci);
-		// usb_disconnect (udev); 
-		hcd->bus->root_hub = 0;
-		usb_free_dev (udev); 
-		retval = -ENODEV;
-		goto done2;
-	}
-
-	return 0;
-}
-
-/* always called by thread; normally rmmod */
-
-static void ehci_stop (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-
-	dbg ("%s: stop", hcd->bus_name);
-
-	if (hcd->state == USB_STATE_RUNNING)
-		ehci_ready (ehci);
-	while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
-		udelay (100);
-	ehci_reset (ehci);
-
-	// root hub is shut down separately (first, when possible)
-	scan_async (ehci);
-	if (ehci->next_uframe != -1)
-		scan_periodic (ehci);
-	ehci_mem_cleanup (ehci);
-
-	dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
-}
-
-static int ehci_get_frame (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-
-/* suspend/resume, section 4.3 */
-
-static int ehci_suspend (struct usb_hcd *hcd, u32 state)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	int			ports;
-	int			i;
-
-	dbg ("%s: suspend to %d", hcd->bus_name, state);
-
-	ports = HCS_N_PORTS (ehci->hcs_params);
-
-	// FIXME:  This assumes what's probably a D3 level suspend...
-
-	// FIXME:  usb wakeup events on this bus should resume the machine.
-	// pci config register PORTWAKECAP controls which ports can do it;
-	// bios may have initted the register...
-
-	/* suspend each port, then stop the hc */
-	for (i = 0; i < ports; i++) {
-		int	temp = readl (&ehci->regs->port_status [i]);
-
-		if ((temp & PORT_PE) == 0
-				|| (temp & PORT_OWNER) != 0)
-			continue;
-dbg ("%s: suspend port %d", hcd->bus_name, i);
-		temp |= PORT_SUSPEND;
-		writel (temp, &ehci->regs->port_status [i]);
-	}
-
-	if (hcd->state == USB_STATE_RUNNING)
-		ehci_ready (ehci);
-	while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
-		udelay (100);
-	writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command);
-
-// save pci FLADJ value
-
-	/* who tells PCI to reduce power consumption? */
-
-	return 0;
-}
-
-static int ehci_resume (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	int			ports;
-	int			i;
-
-	dbg ("%s: resume", hcd->bus_name);
-
-	ports = HCS_N_PORTS (ehci->hcs_params);
-
-	// FIXME:  if controller didn't retain state,
-	// return and let generic code clean it up
-	// test configured_flag ?
-
-	/* resume HC and each port */
-// restore pci FLADJ value
-	// khubd and drivers will set HC running, if needed;
-	hcd->state = USB_STATE_READY;
-	for (i = 0; i < ports; i++) {
-		int	temp = readl (&ehci->regs->port_status [i]);
-
-		if ((temp & PORT_PE) == 0
-				|| (temp & PORT_SUSPEND) != 0)
-			continue;
-dbg ("%s: resume port %d", hcd->bus_name, i);
-		temp |= PORT_RESUME;
-		writel (temp, &ehci->regs->port_status [i]);
-		readl (&ehci->regs->command);	/* unblock posted writes */
-
-		wait_ms (20);
-		temp &= ~PORT_RESUME;
-		writel (temp, &ehci->regs->port_status [i]);
-	}
-	readl (&ehci->regs->command);	/* unblock posted writes */
-	return 0;
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * tasklet scheduled by some interrupts and other events
- * calls driver completion functions ... but not in_irq()
- */
-static void ehci_tasklet (unsigned long param)
-{
-	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
-
-	if (ehci->reclaim_ready)
-		end_unlink_async (ehci);
-	scan_async (ehci);
-	if (ehci->next_uframe != -1)
-		scan_periodic (ehci);
-
-	// FIXME:  when nothing is connected to the root hub,
-	// turn off the RUN bit so the host can enter C3 "sleep" power
-	// saving mode; make root hub code scan memory less often.
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void ehci_irq (struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	u32			status = readl (&ehci->regs->status);
-	int			bh;
-
-	status &= INTR_MASK;
-	if (!status)			/* irq sharing? */
-		return;
-
-	/* clear (just) interrupts */
-	writel (status, &ehci->regs->status);
-	readl (&ehci->regs->command);	/* unblock posted write */
-	bh = 0;
-
-#ifdef	EHCI_VERBOSE_DEBUG
-	/* unrequested/ignored: Port Change Detect, Frame List Rollover */
-	dbg_status (ehci, "irq", status);
-#endif
-
-	/* INT, ERR, and IAA interrupt rates can be throttled */
-
-	/* normal [4.15.1.2] or error [4.15.1.1] completion */
-	if (likely ((status & (STS_INT|STS_ERR)) != 0))
-		bh = 1;
-
-	/* complete the unlinking of some qh [4.15.2.3] */
-	if (status & STS_IAA) {
-		ehci->reclaim_ready = 1;
-		bh = 1;
-	}
-
-	/* PCI errors [4.15.2.4] */
-	if (unlikely ((status & STS_FATAL) != 0)) {
-		err ("%s: fatal error, state %x", hcd->bus_name, hcd->state);
-		ehci_reset (ehci);
-		// generic layer kills/unlinks all urbs
-		// then tasklet cleans up the rest
-		bh = 1;
-	}
-
-	/* most work doesn't need to be in_irq() */
-	if (likely (bh == 1))
-		tasklet_schedule (&ehci->tasklet);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * non-error returns are a promise to giveback() the urb later
- * we drop ownership so next owner (or urb unlink) can get it
- *
- * urb + dev is in hcd_dev.urb_list
- * we're queueing TDs onto software and hardware lists
- *
- * hcd-specific init for hcpriv hasn't been done yet
- *
- * NOTE:  EHCI queues control and bulk requests transparently, like OHCI.
- */
-static int ehci_urb_enqueue (
-	struct usb_hcd	*hcd,
-	struct urb	*urb,
-	int		mem_flags
-) {
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	struct list_head	qtd_list;
-
-	urb->transfer_flags &= ~EHCI_STATE_UNLINK;
-	INIT_LIST_HEAD (&qtd_list);
-	switch (usb_pipetype (urb->pipe)) {
-
-	case PIPE_CONTROL:
-	case PIPE_BULK:
-		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
-			return -ENOMEM;
-		submit_async (ehci, urb, &qtd_list, mem_flags);
-		break;
-
-	case PIPE_INTERRUPT:
-		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
-			return -ENOMEM;
-		return intr_submit (ehci, urb, &qtd_list, mem_flags);
-
-	case PIPE_ISOCHRONOUS:
-		if (urb->dev->speed == USB_SPEED_HIGH)
-			return itd_submit (ehci, urb, mem_flags);
-#ifdef have_split_iso
-		else
-			return sitd_submit (ehci, urb, mem_flags);
-#else
-		dbg ("no split iso support yet");
-		return -ENOSYS;
-#endif /* have_split_iso */
-
-	}
-	return 0;
-}
-
-/* remove from hardware lists
- * completions normally happen asynchronously
- */
-
-static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	struct ehci_qh		*qh = (struct ehci_qh *) urb->hcpriv;
-	unsigned long		flags;
-
-	dbg ("%s urb_dequeue %p qh state %d",
-		hcd->bus_name, urb, qh->qh_state);
-
-	switch (usb_pipetype (urb->pipe)) {
-	case PIPE_CONTROL:
-	case PIPE_BULK:
-		spin_lock_irqsave (&ehci->lock, flags);
-		if (ehci->reclaim) {
-dbg ("dq: reclaim busy, %s", RUN_CONTEXT);
-			if (in_interrupt ()) {
-				spin_unlock_irqrestore (&ehci->lock, flags);
-				return -EAGAIN;
-			}
-			while (qh->qh_state == QH_STATE_LINKED
-					&& ehci->reclaim
-					&& ehci->hcd.state != USB_STATE_HALT
-					) {
-				spin_unlock_irqrestore (&ehci->lock, flags);
-// yeech ... this could spin for up to two frames!
-dbg ("wait for dequeue: state %d, reclaim %p, hcd state %d",
-    qh->qh_state, ehci->reclaim, ehci->hcd.state
-);
-				udelay (100);
-				spin_lock_irqsave (&ehci->lock, flags);
-			}
-		}
-		if (qh->qh_state == QH_STATE_LINKED)
-			start_unlink_async (ehci, qh);
-		spin_unlock_irqrestore (&ehci->lock, flags);
-		return 0;
-
-	case PIPE_INTERRUPT:
-		intr_deschedule (ehci, urb->start_frame, qh, urb->interval);
-		if (ehci->hcd.state == USB_STATE_HALT)
-			urb->status = -ESHUTDOWN;
-		qh_completions (ehci, &qh->qtd_list, 1);
-		return 0;
-
-	case PIPE_ISOCHRONOUS:
-		// itd or sitd ...
-
-		// wait till next completion, do it then.
-		// completion irqs can wait up to 128 msec,
-		urb->transfer_flags |= EHCI_STATE_UNLINK;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// bulk qh holds the data toggle
-
-static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
-{
-	struct hcd_dev		*dev = (struct hcd_dev *)udev->hcpriv;
-	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
-	int			i;
-	unsigned long		flags;
-
-	/* ASSERT:  nobody can be submitting urbs for this any more */
-
-	dbg ("%s: free_config devnum %d", hcd->bus_name, udev->devnum);
-
-	spin_lock_irqsave (&ehci->lock, flags);
-	for (i = 0; i < 32; i++) {
-		if (dev->ep [i]) {
-			struct ehci_qh		*qh;
-
-			// FIXME:  this might be an itd/sitd too ...
-			// or an interrupt urb (not on async list)
-			// can use "union ehci_shadow"
-
-			qh = (struct ehci_qh *) dev->ep [i];
-			vdbg ("free_config, ep 0x%02x qh %p", i, qh);
-			if (!list_empty (&qh->qtd_list)) {
-				dbg ("ep 0x%02x qh %p not empty!", i, qh);
-				BUG ();
-			}
-			dev->ep [i] = 0;
-
-			/* wait_ms() won't spin here -- we're a thread */
-			while (qh->qh_state == QH_STATE_LINKED
-					&& ehci->reclaim
-					&& ehci->hcd.state != USB_STATE_HALT
-					) {
-				spin_unlock_irqrestore (&ehci->lock, flags);
-				wait_ms (1);
-				spin_lock_irqsave (&ehci->lock, flags);
-			}
-			if (qh->qh_state == QH_STATE_LINKED) {
-				start_unlink_async (ehci, qh);
-				while (qh->qh_state != QH_STATE_IDLE) {
-					spin_unlock_irqrestore (&ehci->lock,
-						flags);
-					wait_ms (1);
-					spin_lock_irqsave (&ehci->lock, flags);
-				}
-			}
-			qh_unput (ehci, qh);
-		}
-	}
-
-	spin_unlock_irqrestore (&ehci->lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const char	hcd_name [] = "ehci-hcd";
-
-static const struct hc_driver ehci_driver = {
-	description:		hcd_name,
-
-	/*
-	 * generic hardware linkage
-	 */
-	irq:			ehci_irq,
-	flags:			HCD_MEMORY | HCD_USB2,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	start:			ehci_start,
-#ifdef	CONFIG_PM
-	suspend:		ehci_suspend,
-	resume:			ehci_resume,
-#endif
-	stop:			ehci_stop,
-
-	/*
-	 * memory lifecycle (except per-request)
-	 */
-	hcd_alloc:		ehci_hcd_alloc,
-	hcd_free:		ehci_hcd_free,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	urb_enqueue:		ehci_urb_enqueue,
-	urb_dequeue:		ehci_urb_dequeue,
-	free_config:		ehci_free_config,
-
-	/*
-	 * scheduling support
-	 */
-	get_frame_number:	ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	hub_status_data:	ehci_hub_status_data,
-	hub_control:		ehci_hub_control,
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* EHCI spec says PCI is required. */
-
-/* PCI driver selection metadata; PCI hotplugging uses this */
-static const struct pci_device_id __devinitdata pci_ids [] = { {
-
-	/* handle any USB 2.0 EHCI controller */
-
-	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x20),
-	class_mask: 	~0,
-	driver_data:	(unsigned long) &ehci_driver,
-
-	/* no matter who makes it */
-	vendor:		PCI_ANY_ID,
-	device:		PCI_ANY_ID,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver ehci_pci_driver = {
-	name:		(char *) hcd_name,
-	id_table:	pci_ids,
-
-	probe:		usb_hcd_pci_probe,
-	remove:		usb_hcd_pci_remove,
-
-#ifdef	CONFIG_PM
-	suspend:	usb_hcd_pci_suspend,
-	resume:		usb_hcd_pci_resume,
-#endif
-};
-
-#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
-
-EXPORT_NO_SYMBOLS;
-MODULE_DESCRIPTION (DRIVER_INFO);
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_LICENSE ("GPL");
-
-static int __init init (void) 
-{
-	dbg (DRIVER_INFO);
-	dbg ("block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd",
-		sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
-		sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
-
-	return pci_module_init (&ehci_pci_driver);
-}
-module_init (init);
-
-static void __exit cleanup (void) 
-{	
-	pci_unregister_driver (&ehci_pci_driver);
-}
-module_exit (cleanup);
diff -Nru a/drivers/usb/hcd/ehci-hub.c b/drivers/usb/hcd/ehci-hub.c
--- a/drivers/usb/hcd/ehci-hub.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 2001-2002 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* this file is part of ehci-hcd.c */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Root Hub ... the nonsharable stuff
- *
- * Registers don't need cpu_to_le32, that happens transparently
- */
-
-/*-------------------------------------------------------------------------*/
-
-static int check_reset_complete (
-	struct ehci_hcd	*ehci,
-	int		index,
-	int		port_status
-) {
-	if (!(port_status & PORT_CONNECT)) {
-		ehci->reset_done [index] = 0;
-		return port_status;
-	}
-
-	/* if reset finished and it's still not enabled -- handoff */
-	if (!(port_status & PORT_PE)) {
-		dbg ("%s port %d full speed, give to companion, 0x%x",
-			ehci->hcd.bus_name, index + 1, port_status);
-
-		// what happens if HCS_N_CC(params) == 0 ?
-		port_status |= PORT_OWNER;
-		writel (port_status, &ehci->regs->port_status [index]);
-
-	} else
-		dbg ("%s port %d high speed", ehci->hcd.bus_name, index + 1);
-
-	return port_status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-
-/* build "status change" packet (one or two bytes) from HC registers */
-
-static int
-ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
-{
-	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
-	u32		temp, status = 0;
-	int		ports, i, retval = 1;
-	unsigned long	flags;
-
-	/* init status to no-changes */
-	buf [0] = 0;
-	ports = HCS_N_PORTS (ehci->hcs_params);
-	if (ports > 7) {
-		buf [1] = 0;
-		retval++;
-	}
-	
-	/* no hub change reports (bit 0) for now (power, ...) */
-
-	/* port N changes (bit N)? */
-	spin_lock_irqsave (&ehci->lock, flags);
-	for (i = 0; i < ports; i++) {
-		temp = readl (&ehci->regs->port_status [i]);
-		if (temp & PORT_OWNER) {
-			/* don't report this in GetPortStatus */
-			if (temp & PORT_CSC) {
-				temp &= ~PORT_CSC;
-				writel (temp, &ehci->regs->port_status [i]);
-			}
-			continue;
-		}
-		if (!(temp & PORT_CONNECT))
-			ehci->reset_done [i] = 0;
-		if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0) {
-			set_bit (i, buf);
-			status = STS_PCD;
-		}
-	}
-	spin_unlock_irqrestore (&ehci->lock, flags);
-	return status ? retval : 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-ehci_hub_descriptor (
-	struct ehci_hcd			*ehci,
-	struct usb_hub_descriptor	*desc
-) {
-	int		ports = HCS_N_PORTS (ehci->hcs_params);
-	u16		temp;
-
-	desc->bDescriptorType = 0x29;
-	desc->bPwrOn2PwrGood = 0;	/* FIXME: f(system power) */
-	desc->bHubContrCurrent = 0;
-
-	desc->bNbrPorts = ports;
-	temp = 1 + (ports / 8);
-	desc->bDescLength = 7 + 2 * temp;
-
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset (&desc->bitmap [0], 0, temp);
-	memset (&desc->bitmap [temp], 0xff, temp);
-
-	temp = 0x0008;			/* per-port overcurrent reporting */
-	if (HCS_PPC (ehci->hcs_params))
-		temp |= 0x0001;		/* per-port power control */
-	if (HCS_INDICATOR (ehci->hcs_params))
-		temp |= 0x0080;		/* per-port indicators (LEDs) */
-	desc->wHubCharacteristics = cpu_to_le16 (temp);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int ehci_hub_control (
-	struct usb_hcd	*hcd,
-	u16		typeReq,
-	u16		wValue,
-	u16		wIndex,
-	char		*buf,
-	u16		wLength
-) {
-	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
-	int		ports = HCS_N_PORTS (ehci->hcs_params);
-	u32		temp;
-	unsigned long	flags;
-	int		retval = 0;
-
-	/*
-	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
-	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
-	 * (track current state ourselves) ... blink for diagnostics,
-	 * power, "this is the one", etc.  EHCI spec supports this.
-	 */
-
-	spin_lock_irqsave (&ehci->lock, flags);
-	switch (typeReq) {
-	case ClearHubFeature:
-		switch (wValue) {
-		case C_HUB_LOCAL_POWER:
-		case C_HUB_OVER_CURRENT:
-			/* no hub-wide feature/status flags */
-			break;
-		default:
-			goto error;
-		}
-		break;
-	case ClearPortFeature:
-		if (!wIndex || wIndex > ports)
-			goto error;
-		wIndex--;
-		temp = readl (&ehci->regs->port_status [wIndex]);
-		if (temp & PORT_OWNER)
-			break;
-
-		switch (wValue) {
-		case USB_PORT_FEAT_ENABLE:
-			writel (temp & ~PORT_PE,
-				&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_C_ENABLE:
-			writel (temp | PORT_PEC,
-				&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_SUSPEND:
-		case USB_PORT_FEAT_C_SUSPEND:
-			/* ? */
-			break;
-		case USB_PORT_FEAT_POWER:
-			if (HCS_PPC (ehci->hcs_params))
-				writel (temp & ~PORT_POWER,
-					&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_C_CONNECTION:
-			writel (temp | PORT_CSC,
-				&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_C_OVER_CURRENT:
-			writel (temp | PORT_OCC,
-				&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_C_RESET:
-			/* GetPortStatus clears reset */
-			break;
-		default:
-			goto error;
-		}
-		readl (&ehci->regs->command);	/* unblock posted write */
-		break;
-	case GetHubDescriptor:
-		ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
-			buf);
-		break;
-	case GetHubStatus:
-		/* no hub-wide feature/status flags */
-		memset (buf, 0, 4);
-		//cpu_to_le32s ((u32 *) buf);
-		break;
-	case GetPortStatus:
-		if (!wIndex || wIndex > ports)
-			goto error;
-		wIndex--;
-		memset (buf, 0, 4);
-		temp = readl (&ehci->regs->port_status [wIndex]);
-
-		// wPortChange bits
-		if (temp & PORT_CSC)
-			set_bit (USB_PORT_FEAT_C_CONNECTION, buf);
-		if (temp & PORT_PEC)
-			set_bit (USB_PORT_FEAT_C_ENABLE, buf);
-		// USB_PORT_FEAT_C_SUSPEND
-		if (temp & PORT_OCC)
-			set_bit (USB_PORT_FEAT_C_OVER_CURRENT, buf);
-
-		/* whoever resets must GetPortStatus to complete it!! */
-		if ((temp & PORT_RESET)
-				&& jiffies > ehci->reset_done [wIndex]) {
-			set_bit (USB_PORT_FEAT_C_RESET, buf);
-
-			/* force reset to complete */
-			writel (temp & ~PORT_RESET,
-					&ehci->regs->port_status [wIndex]);
-			do {
-				temp = readl (
-					&ehci->regs->port_status [wIndex]);
-				udelay (10);
-			} while (temp & PORT_RESET);
-
-			/* see what we found out */
-			temp = check_reset_complete (ehci, wIndex, temp);
-		}
-
-		// don't show wPortStatus if it's owned by a companion hc
-		if (!(temp & PORT_OWNER)) {
-			if (temp & PORT_CONNECT) {
-				set_bit (USB_PORT_FEAT_CONNECTION, buf);
-				set_bit (USB_PORT_FEAT_HIGHSPEED, buf);
-			}
-			if (temp & PORT_PE)
-				set_bit (USB_PORT_FEAT_ENABLE, buf);
-			if (temp & PORT_SUSPEND)
-				set_bit (USB_PORT_FEAT_SUSPEND, buf);
-			if (temp & PORT_OC)
-				set_bit (USB_PORT_FEAT_OVER_CURRENT, buf);
-			if (temp & PORT_RESET)
-				set_bit (USB_PORT_FEAT_RESET, buf);
-			if (temp & PORT_POWER)
-				set_bit (USB_PORT_FEAT_POWER, buf);
-		}
-
-#ifndef	EHCI_VERBOSE_DEBUG
-	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
-#endif
-		dbg_port (hcd, "GetStatus", wIndex + 1, temp);
-		cpu_to_le32s ((u32 *) buf);
-		break;
-	case SetHubFeature:
-		switch (wValue) {
-		case C_HUB_LOCAL_POWER:
-		case C_HUB_OVER_CURRENT:
-			/* no hub-wide feature/status flags */
-			break;
-		default:
-			goto error;
-		}
-		break;
-	case SetPortFeature:
-		if (!wIndex || wIndex > ports)
-			goto error;
-		wIndex--;
-		temp = readl (&ehci->regs->port_status [wIndex]);
-		if (temp & PORT_OWNER)
-			break;
-
-		switch (wValue) {
-		case USB_PORT_FEAT_SUSPEND:
-			writel (temp | PORT_SUSPEND,
-				&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_POWER:
-			if (HCS_PPC (ehci->hcs_params))
-				writel (temp | PORT_POWER,
-					&ehci->regs->port_status [wIndex]);
-			break;
-		case USB_PORT_FEAT_RESET:
-			/* line status bits may report this as low speed */
-			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
-					&& PORT_USB11 (temp)) {
-				dbg ("%s port %d low speed, give to companion",
-					hcd->bus_name, wIndex + 1);
-				temp |= PORT_OWNER;
-			} else {
-				/* Philips 1562 wants CMD_RUN to reset */
-				if (!HCD_IS_RUNNING(ehci->hcd.state)) {
-					u32 cmd = readl (&ehci->regs->command);
-					cmd |= CMD_RUN;
-					writel (cmd, &ehci->regs->command);	
-					ehci->hcd.state = USB_STATE_RUNNING;
-				}
-				vdbg ("%s port %d reset",
-					hcd->bus_name, wIndex + 1);
-				temp |= PORT_RESET;
-				temp &= ~PORT_PE;
-
-				/*
-				 * caller must wait, then call GetPortStatus
-				 * usb 2.0 spec says 50 ms resets on root
-				 */
-				ehci->reset_done [wIndex] = jiffies
-				    	+ ((50 /* msec */ * HZ) / 1000);
-			}
-			writel (temp, &ehci->regs->port_status [wIndex]);
-			break;
-		default:
-			goto error;
-		}
-		readl (&ehci->regs->command);	/* unblock posted writes */
-		break;
-
-	default:
-error:
-		/* "stall" on error */
-		retval = -EPIPE;
-	}
-	spin_unlock_irqrestore (&ehci->lock, flags);
-	return retval;
-}
diff -Nru a/drivers/usb/hcd/ehci-mem.c b/drivers/usb/hcd/ehci-mem.c
--- a/drivers/usb/hcd/ehci-mem.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2001 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* this file is part of ehci-hcd.c */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * There's basically three types of memory:
- *	- data used only by the HCD ... kmalloc is fine
- *	- async and periodic schedules, shared by HC and HCD ... these
- *	  need to use pci_pool or pci_alloc_consistent
- *	- driver buffers, read/written by HC ... single shot DMA mapped 
- *
- * There's also PCI "register" data, which is memory mapped.
- * No memory seen by this driver is pagable.
- */
-
-/*-------------------------------------------------------------------------*/
-/* 
- * Allocator / cleanup for the per device structure
- * Called by hcd init / removal code
- */
-static struct usb_hcd *ehci_hcd_alloc (void)
-{
-	struct ehci_hcd *ehci;
-
-	ehci = (struct ehci_hcd *)
-		kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL);
-	if (ehci != 0) {
-		memset (ehci, 0, sizeof (struct ehci_hcd));
-		return &ehci->hcd;
-	}
-	return 0;
-}
-
-static void ehci_hcd_free (struct usb_hcd *hcd)
-{
-	kfree (hcd_to_ehci (hcd));
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Allocate the key transfer structures from the previously allocated pool */
-
-static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
-{
-	struct ehci_qtd		*qtd;
-	dma_addr_t		dma;
-
-	qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
-	if (qtd != 0) {
-		memset (qtd, 0, sizeof *qtd);
-		qtd->qtd_dma = dma;
-		qtd->hw_next = EHCI_LIST_END;
-		qtd->hw_alt_next = EHCI_LIST_END;
-		INIT_LIST_HEAD (&qtd->qtd_list);
-	}
-	return qtd;
-}
-
-static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
-{
-	pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
-}
-
-
-static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
-{
-	struct ehci_qh		*qh;
-	dma_addr_t		dma;
-
-	qh = (struct ehci_qh *)
-		pci_pool_alloc (ehci->qh_pool, flags, &dma);
-	if (qh) {
-		memset (qh, 0, sizeof *qh);
-		atomic_set (&qh->refcount, 1);
-		qh->qh_dma = dma;
-		// INIT_LIST_HEAD (&qh->qh_list);
-		INIT_LIST_HEAD (&qh->qtd_list);
-	}
-	return qh;
-}
-
-/* to share a qh (cpu threads, or hc) */
-static inline struct ehci_qh *qh_put (/* ehci, */ struct ehci_qh *qh)
-{
-	// dbg ("put %p (%d++)", qh, qh->refcount.counter);
-	atomic_inc (&qh->refcount);
-	return qh;
-}
-
-static void qh_unput (struct ehci_hcd *ehci, struct ehci_qh *qh)
-{
-	// dbg ("unput %p (--%d)", qh, qh->refcount.counter);
-	if (!atomic_dec_and_test (&qh->refcount))
-		return;
-	/* clean qtds first, and know this is not linked */
-	if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
-		dbg ("unused qh not empty!");
-		BUG ();
-	}
-	pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* The queue heads and transfer descriptors are managed from pools tied 
- * to each of the "per device" structures.
- * This is the initialisation and cleanup code.
- */
-
-static void ehci_mem_cleanup (struct ehci_hcd *ehci)
-{
-	/* PCI consistent memory and pools */
-	if (ehci->qtd_pool)
-		pci_pool_destroy (ehci->qtd_pool);
-	ehci->qtd_pool = 0;
-
-	if (ehci->qh_pool) {
-		pci_pool_destroy (ehci->qh_pool);
-		ehci->qh_pool = 0;
-	}
-
-	if (ehci->itd_pool)
-		pci_pool_destroy (ehci->itd_pool);
-	ehci->itd_pool = 0;
-
-	if (ehci->sitd_pool)
-		pci_pool_destroy (ehci->sitd_pool);
-	ehci->sitd_pool = 0;
-
-	if (ehci->periodic)
-		pci_free_consistent (ehci->hcd.pdev,
-			ehci->periodic_size * sizeof (u32),
-			ehci->periodic, ehci->periodic_dma);
-	ehci->periodic = 0;
-
-	/* shadow periodic table */
-	if (ehci->pshadow)
-		kfree (ehci->pshadow);
-	ehci->pshadow = 0;
-}
-
-/* remember to add cleanup code (above) if you add anything here */
-static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
-{
-	int i;
-
-	/* QTDs for control/bulk/intr transfers */
-	ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev,
-			sizeof (struct ehci_qtd),
-			32 /* byte alignment (for hw parts) */,
-			4096 /* can't cross 4K */,
-			flags);
-	if (!ehci->qtd_pool) {
-		dbg ("no qtd pool");
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-
-	/* QH for control/bulk/intr transfers */
-	ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev,
-			sizeof (struct ehci_qh),
-			32 /* byte alignment (for hw parts) */,
-			4096 /* can't cross 4K */,
-			flags);
-	if (!ehci->qh_pool) {
-		dbg ("no qh pool");
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-
-	/* ITD for high speed ISO transfers */
-	ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev,
-			sizeof (struct ehci_itd),
-			32 /* byte alignment (for hw parts) */,
-			4096 /* can't cross 4K */,
-			flags);
-	if (!ehci->itd_pool) {
-		dbg ("no itd pool");
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-
-	/* SITD for full/low speed split ISO transfers */
-	ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev,
-			sizeof (struct ehci_sitd),
-			32 /* byte alignment (for hw parts) */,
-			4096 /* can't cross 4K */,
-			flags);
-	if (!ehci->sitd_pool) {
-		dbg ("no sitd pool");
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-
-	/* Hardware periodic table */
-	ehci->periodic = (u32 *)
-		pci_alloc_consistent (ehci->hcd.pdev,
-			ehci->periodic_size * sizeof (u32),
-			&ehci->periodic_dma);
-	if (ehci->periodic == 0) {
-		dbg ("no hw periodic table");
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-	for (i = 0; i < ehci->periodic_size; i++)
-		ehci->periodic [i] = EHCI_LIST_END;
-
-	/* software shadow of hardware table */
-	ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *),
-		flags & ~EHCI_SLAB_FLAGS);
-	if (ehci->pshadow == 0) {
-		dbg ("no shadow periodic table");
-		ehci_mem_cleanup (ehci);
-		return -ENOMEM;
-	}
-	memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *));
-
-	return 0;
-}
diff -Nru a/drivers/usb/hcd/ehci-q.c b/drivers/usb/hcd/ehci-q.c
--- a/drivers/usb/hcd/ehci-q.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,976 +0,0 @@
-/*
- * Copyright (c) 2001-2002 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* this file is part of ehci-hcd.c */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI hardware queue manipulation
- *
- * Control, bulk, and interrupt traffic all use "qh" lists.  They list "qtd"
- * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
- * buffers needed for the larger number).  We use one QH per endpoint, queue
- * multiple (bulk or control) urbs per endpoint.  URBs may need several qtds.
- * A scheduled interrupt qh always has one qtd, one urb.
- *
- * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
- * interrupts) needs careful scheduling.  Performance improvements can be
- * an ongoing challenge.
- * 
- * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
- * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
- * (b) special fields in qh entries or (c) split iso entries.  TTs will
- * buffer low/full speed data so the host collects it at high speed.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* fill a qtd, returning how much of the buffer we were able to queue up */
-
-static int
-qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
-{
-	int	i, count;
-
-	/* one buffer entry per 4K ... first might be short or unaligned */
-	qtd->hw_buf [0] = cpu_to_le32 (buf);
-	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
-	if (likely (len < count))		/* ... iff needed */
-		count = len;
-	else {
-		buf +=  0x1000;
-		buf &= ~0x0fff;
-
-		/* per-qtd limit: from 16K to 20K (best alignment) */
-		for (i = 1; count < len && i < 5; i++) {
-			u64	addr = buf;
-			qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
-			qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
-			buf += 0x1000;
-			if ((count + 0x1000) < len)
-				count += 0x1000;
-			else
-				count = len;
-		}
-	}
-	qtd->hw_token = cpu_to_le32 ((count << 16) | token);
-	qtd->length = count;
-
-#if 0
-	vdbg ("  qtd_fill %p, token %8x bytes %d dma %x",
-		qtd, le32_to_cpu (qtd->hw_token), count, qtd->hw_buf [0]);
-#endif
-
-	return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* update halted (but potentially linked) qh */
-
-static inline void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
-{
-	qh->hw_current = 0;
-	qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
-	qh->hw_alt_next = EHCI_LIST_END;
-
-	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
-	qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
-{
-	/* count IN/OUT bytes, not SETUP (even short packets) */
-	if (likely (QTD_PID (token) != 2))
-		urb->actual_length += length - QTD_LENGTH (token);
-
-	/* don't modify error codes */
-	if (unlikely (urb->status == -EINPROGRESS && (token & QTD_STS_HALT))) {
-		if (token & QTD_STS_BABBLE) {
-			urb->status = -EOVERFLOW;
-		} else if (!QTD_CERR (token)) {
-			if (token & QTD_STS_DBE)
-				urb->status = (QTD_PID (token) == 1) /* IN ? */
-					? -ENOSR  /* hc couldn't read data */
-					: -ECOMM; /* hc couldn't write data */
-			else if (token & QTD_STS_MMF)	/* missed tt uframe */
-				urb->status = -EPROTO;
-			else if (token & QTD_STS_XACT) {
-				if (QTD_LENGTH (token))
-					urb->status = -EPIPE;
-				else {
-					dbg ("3strikes");
-					urb->status = -EPROTO;
-				}
-			} else	/* presumably a stall */
-				urb->status = -EPIPE;
-
-		/* CERR nonzero + data left + halt --> stall */
-		} else if (QTD_LENGTH (token))
-			urb->status = -EPIPE;
-		else	/* unknown */
-			urb->status = -EPROTO;
-		dbg ("ep %d-%s qtd token %08x --> status %d",
-			/* devpath */
-			usb_pipeendpoint (urb->pipe),
-			usb_pipein (urb->pipe) ? "in" : "out",
-			token, urb->status);
-
-		/* stall indicates some recovery action is needed */
-		if (urb->status == -EPIPE) {
-			int	pipe = urb->pipe;
-
-			if (!usb_pipecontrol (pipe))
-				usb_endpoint_halt (urb->dev,
-					usb_pipeendpoint (pipe),
-					usb_pipeout (pipe));
-			if (urb->dev->tt && !usb_pipeint (pipe)) {
-err ("must CLEAR_TT_BUFFER, hub port %d%s addr %d ep %d",
-    urb->dev->ttport, /* devpath */
-    urb->dev->tt->multi ? "" : " (all-ports TT)",
-    urb->dev->devnum, usb_pipeendpoint (urb->pipe));
-				// FIXME something (khubd?) should make the hub
-				// CLEAR_TT_BUFFER ASAP, it's blocking other
-				// fs/ls requests... hub_tt_clear_buffer() ?
-			}
-		}
-	}
-}
-
-static void ehci_urb_complete (
-	struct ehci_hcd		*ehci,
-	dma_addr_t		addr,
-	struct urb		*urb
-) {
-	if (urb->transfer_buffer_length && usb_pipein (urb->pipe))
-		pci_dma_sync_single (ehci->hcd.pdev, addr,
-			urb->transfer_buffer_length,
-			PCI_DMA_FROMDEVICE);
-
-	/* cleanse status if we saw no error */
-	if (likely (urb->status == -EINPROGRESS)) {
-		if (urb->actual_length != urb->transfer_buffer_length
-				&& (urb->transfer_flags & USB_DISABLE_SPD))
-			urb->status = -EREMOTEIO;
-		else
-			urb->status = 0;
-	}
-
-	/* only report unlinks once */
-	if (likely (urb->status != -ENOENT && urb->status != -ENOTCONN))
-		urb->complete (urb);
-}
-
-/* urb->lock ignored from here on (hcd is done with urb) */
-
-static void ehci_urb_done (
-	struct ehci_hcd		*ehci,
-	dma_addr_t		addr,
-	struct urb		*urb
-) {
-	if (urb->transfer_buffer_length)
-		pci_unmap_single (ehci->hcd.pdev,
-			addr,
-			urb->transfer_buffer_length,
-			usb_pipein (urb->pipe)
-			    ? PCI_DMA_FROMDEVICE
-			    : PCI_DMA_TODEVICE);
-	if (likely (urb->hcpriv != 0)) {
-		qh_unput (ehci, (struct ehci_qh *) urb->hcpriv);
-		urb->hcpriv = 0;
-	}
-
-	if (likely (urb->status == -EINPROGRESS)) {
-		if (urb->actual_length != urb->transfer_buffer_length
-				&& (urb->transfer_flags & USB_DISABLE_SPD))
-			urb->status = -EREMOTEIO;
-		else
-			urb->status = 0;
-	}
-
-	/* hand off urb ownership */
-	usb_hcd_giveback_urb (&ehci->hcd, urb);
-}
-
-
-/*
- * Process completed qtds for a qh, issuing completions if needed.
- * When freeing:  frees qtds, unmaps buf, returns URB to driver.
- * When not freeing (queued periodic qh):  retain qtds, mapping, and urb.
- * Races up to qh->hw_current; returns number of urb completions.
- */
-static int
-qh_completions (
-	struct ehci_hcd		*ehci,
-	struct list_head	*qtd_list,
-	int			freeing
-) {
-	struct ehci_qtd		*qtd, *last;
-	struct list_head	*next;
-	struct ehci_qh		*qh = 0;
-	int			unlink = 0, halted = 0;
-	unsigned long		flags;
-	int			retval = 0;
-
-	spin_lock_irqsave (&ehci->lock, flags);
-	if (unlikely (list_empty (qtd_list))) {
-		spin_unlock_irqrestore (&ehci->lock, flags);
-		return retval;
-	}
-
-	/* scan QTDs till end of list, or we reach an active one */
-	for (qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list),
-			    	last = 0, next = 0;
-			next != qtd_list;
-			last = qtd, qtd = list_entry (next,
-						struct ehci_qtd, qtd_list)) {
-		struct urb	*urb = qtd->urb;
-		u32		token = 0;
-
-		/* qh is non-null iff these qtds were queued to the HC */
-		qh = (struct ehci_qh *) urb->hcpriv;
-
-		/* clean up any state from previous QTD ...*/
-		if (last) {
-			if (likely (last->urb != urb)) {
-				/* complete() can reenter this HCD */
-				spin_unlock_irqrestore (&ehci->lock, flags);
-				if (likely (freeing != 0))
-					ehci_urb_done (ehci, last->buf_dma,
-						last->urb);
-				else
-					ehci_urb_complete (ehci, last->buf_dma,
-						last->urb);
-				spin_lock_irqsave (&ehci->lock, flags);
-				retval++;
-			}
-
-			/* qh overlays can have HC's old cached copies of
-			 * next qtd ptrs, if an URB was queued afterwards.
-			 */
-			if (qh && cpu_to_le32 (last->qtd_dma) == qh->hw_current
-					&& last->hw_next != qh->hw_qtd_next) {
-				qh->hw_alt_next = last->hw_alt_next;
-				qh->hw_qtd_next = last->hw_next;
-			}
-
-			if (likely (freeing != 0))
-				ehci_qtd_free (ehci, last);
-			last = 0;
-		}
-		next = qtd->qtd_list.next;
-
-		/* if these qtds were queued to the HC, some may be active.
-		 * else we're cleaning up after a failed URB submission.
-		 */
-		if (likely (qh != 0)) {
-			int		qh_halted;
-
-			qh_halted = __constant_cpu_to_le32 (QTD_STS_HALT)
-					& qh->hw_token;
-			token = le32_to_cpu (qtd->hw_token);
-			halted = halted
-				|| qh_halted
-				|| (ehci->hcd.state == USB_STATE_HALT)
-				|| (qh->qh_state == QH_STATE_IDLE);
-
-			/* QH halts only because of fault or unlink; in both
-			 * cases, queued URBs get unlinked.  But for unlink,
-			 * URBs at the head of the queue can stay linked.
-			 */
-			if (unlikely (halted != 0)) {
-
-				/* unlink everything because of HC shutdown? */
-				if (ehci->hcd.state == USB_STATE_HALT) {
-					freeing = unlink = 1;
-					urb->status = -ESHUTDOWN;
-
-				/* explicit unlink, starting here? */
-				} else if (qh->qh_state == QH_STATE_IDLE
-					&& (urb->status == -ECONNRESET
-						|| urb->status == -ENOENT)) {
-					freeing = unlink = 1;
-
-				/* unlink everything because of error? */
-				} else if (qh_halted
-						&& !(token & QTD_STS_HALT)) {
-					freeing = unlink = 1;
-					if (urb->status == -EINPROGRESS)
-						urb->status = -ECONNRESET;
-
-				/* unlink the rest? */
-				} else if (unlink) {
-					urb->status = -ECONNRESET;
-
-				/* QH halted to unlink urbs after this?  */
-				} else if ((token & QTD_STS_ACTIVE) != 0) {
-					qtd = 0;
-					continue;
-				}
-
-			/* Else QH is active, so we must not modify QTDs
-			 * that HC may be working on.  Break from loop.
-			 */
-			} else if (unlikely ((token & QTD_STS_ACTIVE) != 0)) {
-				next = qtd_list;
-				qtd = 0;
-				continue;
-			}
-
-			spin_lock (&urb->lock);
-			qtd_copy_status (urb, qtd->length, token);
-			spin_unlock (&urb->lock);
-		}
-
-		/*
-		 * NOTE:  this won't work right with interrupt urbs that
-		 * need multiple qtds ... only the first scan of qh->qtd_list
-		 * starts at the right qtd, yet multiple scans could happen
-		 * for transfers that are scheduled across multiple uframes. 
-		 * (Such schedules are not currently allowed!)
-		 */
-		if (likely (freeing != 0))
-			list_del (&qtd->qtd_list);
-		else {
-			/* restore everything the HC could change
-			 * from an interrupt QTD
-			 */
-			qtd->hw_token = (qtd->hw_token
-					& ~__constant_cpu_to_le32 (0x8300))
-				| cpu_to_le32 (qtd->length << 16)
-				| __constant_cpu_to_le32 (QTD_IOC
-					| (EHCI_TUNE_CERR << 10)
-					| QTD_STS_ACTIVE);
-			qtd->hw_buf [0] &= ~__constant_cpu_to_le32 (0x0fff);
-
-			/* this offset, and the length above,
-			 * are likely wrong on QTDs #2..N
-			 */
-			qtd->hw_buf [0] |= cpu_to_le32 (0x0fff & qtd->buf_dma);
-		}
-
-#if 0
-		if (urb->status == -EINPROGRESS)
-			vdbg ("  qtd %p ok, urb %p, token %8x, len %d",
-				qtd, urb, token, urb->actual_length);
-		else
-			vdbg ("urb %p status %d, qtd %p, token %8x, len %d",
-				urb, urb->status, qtd, token,
-				urb->actual_length);
-#endif
-
-		/* SETUP for control urb? */
-		if (unlikely (QTD_PID (token) == 2))
-			pci_unmap_single (ehci->hcd.pdev,
-				qtd->buf_dma, sizeof (struct usb_ctrlrequest),
-				PCI_DMA_TODEVICE);
-	}
-
-	/* patch up list head? */
-	if (unlikely (halted && qh && !list_empty (qtd_list))) {
-		qh_update (qh, list_entry (qtd_list->next,
-				struct ehci_qtd, qtd_list));
-	}
-	spin_unlock_irqrestore (&ehci->lock, flags);
-
-	/* last urb's completion might still need calling */
-	if (likely (last != 0)) {
-		if (likely (freeing != 0)) {
-			ehci_urb_done (ehci, last->buf_dma, last->urb);
-			ehci_qtd_free (ehci, last);
-		} else
-			ehci_urb_complete (ehci, last->buf_dma, last->urb);
-		retval++;
-	}
-	return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * create a list of filled qtds for this URB; won't link into qh.
- */
-static struct list_head *
-qh_urb_transaction (
-	struct ehci_hcd		*ehci,
-	struct urb		*urb,
-	struct list_head	*head,
-	int			flags
-) {
-	struct ehci_qtd		*qtd, *qtd_prev;
-	dma_addr_t		buf, map_buf;
-	int			len, maxpacket;
-	u32			token;
-
-	/*
-	 * URBs map to sequences of QTDs:  one logical transaction
-	 */
-	qtd = ehci_qtd_alloc (ehci, flags);
-	if (unlikely (!qtd))
-		return 0;
-	qtd_prev = 0;
-	list_add_tail (&qtd->qtd_list, head);
-	qtd->urb = urb;
-
-	token = QTD_STS_ACTIVE;
-	token |= (EHCI_TUNE_CERR << 10);
-	/* for split transactions, SplitXState initialized to zero */
-
-	if (usb_pipecontrol (urb->pipe)) {
-		/* control request data is passed in the "setup" pid */
-
-		/* NOTE:  this isn't smart about 64bit DMA, since it uses the
-		 * default (32bit) mask rather than using the whole address
-		 * space.  we could set pdev->dma_mask to all-ones while
-		 * getting this mapping, locking it and restoring before
-		 * allocating qtd/qh/... or maybe only do that for the main
-		 * data phase (below).
-		 */
-		qtd->buf_dma = pci_map_single (
-					ehci->hcd.pdev,
-					urb->setup_packet,
-					sizeof (struct usb_ctrlrequest),
-					PCI_DMA_TODEVICE);
-		if (unlikely (!qtd->buf_dma))
-			goto cleanup;
-
-		/* SETUP pid */
-		qtd_fill (qtd, qtd->buf_dma, sizeof (struct usb_ctrlrequest),
-			token | (2 /* "setup" */ << 8));
-
-		/* ... and always at least one more pid */
-		token ^= QTD_TOGGLE;
-		qtd_prev = qtd;
-		qtd = ehci_qtd_alloc (ehci, flags);
-		if (unlikely (!qtd))
-			goto cleanup;
-		qtd->urb = urb;
-		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
-		list_add_tail (&qtd->qtd_list, head);
-	} 
-
-	/*
-	 * data transfer stage:  buffer setup
-	 */
-	len = urb->transfer_buffer_length;
-	if (likely (len > 0)) {
-		/* NOTE:  sub-optimal mapping with 64bit DMA (see above) */
-		buf = map_buf = pci_map_single (ehci->hcd.pdev,
-			urb->transfer_buffer, len,
-			usb_pipein (urb->pipe)
-			    ? PCI_DMA_FROMDEVICE
-			    : PCI_DMA_TODEVICE);
-		if (unlikely (!buf))
-			goto cleanup;
-	} else
-		buf = map_buf = 0;
-
-	if (!buf || usb_pipein (urb->pipe))
-		token |= (1 /* "in" */ << 8);
-	/* else it's already initted to "out" pid (0 << 8) */
-
-	maxpacket = usb_maxpacket (urb->dev, urb->pipe,
-			usb_pipeout (urb->pipe));
-
-	/*
-	 * buffer gets wrapped in one or more qtds;
-	 * last one may be "short" (including zero len)
-	 * and may serve as a control status ack
-	 */
-	for (;;) {
-		int this_qtd_len;
-
-		qtd->urb = urb;
-		qtd->buf_dma = map_buf;
-		this_qtd_len = qtd_fill (qtd, buf, len, token);
-		len -= this_qtd_len;
-		buf += this_qtd_len;
-
-		/* qh makes control packets use qtd toggle; maybe switch it */
-		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
-			token ^= QTD_TOGGLE;
-
-		if (likely (len <= 0))
-			break;
-
-		qtd_prev = qtd;
-		qtd = ehci_qtd_alloc (ehci, flags);
-		if (unlikely (!qtd))
-			goto cleanup;
-		qtd->urb = urb;
-		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
-		list_add_tail (&qtd->qtd_list, head);
-	}
-
-	/*
-	 * control requests may need a terminating data "status" ack;
-	 * bulk ones may need a terminating short packet (zero length).
-	 */
-	if (likely (buf != 0)) {
-		int	one_more = 0;
-
-		if (usb_pipecontrol (urb->pipe)) {
-			one_more = 1;
-			token ^= 0x0100;	/* "in" <--> "out"  */
-			token |= QTD_TOGGLE;	/* force DATA1 */
-		} else if (usb_pipebulk (urb->pipe)
-				&& (urb->transfer_flags & USB_ZERO_PACKET)
-				&& !(urb->transfer_buffer_length % maxpacket)) {
-			one_more = 1;
-		}
-		if (one_more) {
-			qtd_prev = qtd;
-			qtd = ehci_qtd_alloc (ehci, flags);
-			if (unlikely (!qtd))
-				goto cleanup;
-			qtd->urb = urb;
-			qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
-			list_add_tail (&qtd->qtd_list, head);
-
-			/* never any data in such packets */
-			qtd_fill (qtd, 0, 0, token);
-		}
-	}
-
-	/* by default, enable interrupt on urb completion */
-	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
-		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
-	return head;
-
-cleanup:
-	urb->status = -ENOMEM;
-	qh_completions (ehci, head, 1);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Hardware maintains data toggle (like OHCI) ... here we (re)initialize
- * the hardware data toggle in the QH, and set the pseudo-toggle in udev
- * so we can see if usb_clear_halt() was called.  NOP for control, since
- * we set up qh->hw_info1 to always use the QTD toggle bits. 
- */
-static inline void
-clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh)
-{
-	vdbg ("clear toggle, dev %d ep 0x%x-%s",
-		udev->devnum, ep, is_out ? "out" : "in");
-	qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
-	usb_settoggle (udev, ep, is_out, 1);
-}
-
-// Would be best to create all qh's from config descriptors,
-// when each interface/altsetting is established.  Unlink
-// any previous qh and cancel its urbs first; endpoints are
-// implicitly reset then (data toggle too).
-// That'd mean updating how usbcore talks to HCDs. (2.5?)
-
-
-/*
- * Each QH holds a qtd list; a QH is used for everything except iso.
- *
- * For interrupt urbs, the scheduler must set the microframe scheduling
- * mask(s) each time the QH gets scheduled.  For highspeed, that's
- * just one microframe in the s-mask.  For split interrupt transactions
- * there are additional complications: c-mask, maybe FSTNs.
- */
-static struct ehci_qh *
-ehci_qh_make (
-	struct ehci_hcd		*ehci,
-	struct urb		*urb,
-	struct list_head	*qtd_list,
-	int			flags
-) {
-	struct ehci_qh		*qh = ehci_qh_alloc (ehci, flags);
-	u32			info1 = 0, info2 = 0;
-
-	if (!qh)
-		return qh;
-
-	/*
-	 * init endpoint/device data for this QH
-	 */
-	info1 |= usb_pipeendpoint (urb->pipe) << 8;
-	info1 |= usb_pipedevice (urb->pipe) << 0;
-
-	/* using TT? */
-	switch (urb->dev->speed) {
-	case USB_SPEED_LOW:
-		info1 |= (1 << 12);	/* EPS "low" */
-		/* FALL THROUGH */
-
-	case USB_SPEED_FULL:
-		/* EPS 0 means "full" */
-		info1 |= (EHCI_TUNE_RL_TT << 28);
-		if (usb_pipecontrol (urb->pipe)) {
-			info1 |= (1 << 27);	/* for TT */
-			info1 |= 1 << 14;	/* toggle from qtd */
-		}
-		info1 |= usb_maxpacket (urb->dev, urb->pipe,
-					usb_pipeout (urb->pipe)) << 16;
-
-		info2 |= (EHCI_TUNE_MULT_TT << 30);
-		info2 |= urb->dev->ttport << 23;
-		info2 |= urb->dev->tt->hub->devnum << 16;
-
-		/* NOTE:  if (usb_pipeint (urb->pipe)) { scheduler sets c-mask }
-		 * ... and a 0.96 scheduler might use FSTN nodes too
-		 */
-		break;
-
-	case USB_SPEED_HIGH:		/* no TT involved */
-		info1 |= (2 << 12);	/* EPS "high" */
-		info1 |= (EHCI_TUNE_RL_HS << 28);
-		if (usb_pipecontrol (urb->pipe)) {
-			info1 |= 64 << 16;	/* usb2 fixed maxpacket */
-			info1 |= 1 << 14;	/* toggle from qtd */
-			info2 |= (EHCI_TUNE_MULT_HS << 30);
-		} else if (usb_pipebulk (urb->pipe)) {
-			info1 |= 512 << 16;	/* usb2 fixed maxpacket */
-			info2 |= (EHCI_TUNE_MULT_HS << 30);
-		} else {
-			u32	temp;
-			temp = usb_maxpacket (urb->dev, urb->pipe,
-						usb_pipeout (urb->pipe));
-			info1 |= (temp & 0x3ff) << 16;	/* maxpacket */
-			/* HS intr can be "high bandwidth" */
-			temp = 1 + ((temp >> 11) & 0x03);
-			info2 |= temp << 30;		/* mult */
-		}
-		break;
-	default:
-#ifdef DEBUG
-		BUG ();
-#endif
-	}
-
-	/* NOTE:  if (usb_pipeint (urb->pipe)) { scheduler sets s-mask } */
-
-	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_info1 = cpu_to_le32 (info1);
-	qh->hw_info2 = cpu_to_le32 (info2);
-
-	/* initialize sw and hw queues with these qtds */
-	list_splice (qtd_list, &qh->qtd_list);
-	qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list));
-
-	/* initialize data toggle state */
-	if (!usb_pipecontrol (urb->pipe))
-		clear_toggle (urb->dev,
-			usb_pipeendpoint (urb->pipe),
-			usb_pipeout (urb->pipe),
-			qh);
-
-	return qh;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* move qh (and its qtds) onto async queue; maybe enable queue.  */
-
-static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
-{
-	u32		dma = QH_NEXT (qh->qh_dma);
-	struct ehci_qh	*q;
-
-	if (unlikely (!(q = ehci->async))) {
-		u32	cmd = readl (&ehci->regs->command);
-
-		/* in case a clear of CMD_ASE didn't take yet */
-		while (readl (&ehci->regs->status) & STS_ASS)
-			udelay (100);
-
-		qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
-		qh->qh_next.qh = qh;
-		qh->hw_next = dma;
-		ehci->async = qh;
-		writel ((u32)qh->qh_dma, &ehci->regs->async_next);
-		cmd |= CMD_ASE | CMD_RUN;
-		writel (cmd, &ehci->regs->command);
-		ehci->hcd.state = USB_STATE_RUNNING;
-		/* posted write need not be known to HC yet ... */
-	} else {
-		/* splice right after "start" of ring */
-		qh->hw_info1 &= ~__constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
-		qh->qh_next = q->qh_next;
-		qh->hw_next = q->hw_next;
-		q->qh_next.qh = qh;
-		q->hw_next = dma;
-	}
-	qh->qh_state = QH_STATE_LINKED;
-	/* qtd completions reported later by interrupt */
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-submit_async (
-	struct ehci_hcd		*ehci,
-	struct urb		*urb,
-	struct list_head	*qtd_list,
-	int			mem_flags
-) {
-	struct ehci_qtd		*qtd;
-	struct hcd_dev		*dev;
-	int			epnum;
-	unsigned long		flags;
-	struct ehci_qh		*qh = 0;
-
-	qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
-	dev = (struct hcd_dev *)urb->dev->hcpriv;
-	epnum = usb_pipeendpoint (urb->pipe);
-	if (usb_pipein (urb->pipe))
-		epnum |= 0x10;
-
-	vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]",
-		ehci->hcd.bus_name, urb, urb->transfer_buffer_length,
-		epnum & 0x0f, (epnum & 0x10) ? "in" : "out",
-		qtd, dev ? dev->ep [epnum] : (void *)~0);
-
-	spin_lock_irqsave (&ehci->lock, flags);
-
-	qh = (struct ehci_qh *) dev->ep [epnum];
-	if (likely (qh != 0)) {
-		u32	hw_next = QTD_NEXT (qtd->qtd_dma);
-
-		/* maybe patch the qh used for set_address */
-		if (unlikely (epnum == 0
-				&& le32_to_cpu (qh->hw_info1 & 0x7f) == 0))
-			qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe));
-
-		/* is an URB is queued to this qh already? */
-		if (unlikely (!list_empty (&qh->qtd_list))) {
-			struct ehci_qtd		*last_qtd;
-			int			short_rx = 0;
-
-			/* update the last qtd's "next" pointer */
-			// dbg_qh ("non-empty qh", ehci, qh);
-			last_qtd = list_entry (qh->qtd_list.prev,
-					struct ehci_qtd, qtd_list);
-			last_qtd->hw_next = hw_next;
-
-			/* previous urb allows short rx? maybe optimize. */
-			if (!(last_qtd->urb->transfer_flags & USB_DISABLE_SPD)
-					&& (epnum & 0x10)) {
-				// only the last QTD for now
-				last_qtd->hw_alt_next = hw_next;
-				short_rx = 1;
-			}
-
-			/* Adjust any old copies in qh overlay too.
-			 * Interrupt code must cope with case of HC having it
-			 * cached, and clobbering these updates.
-			 * ... complicates getting rid of extra interrupts!
-			 */
-			if (qh->hw_current == cpu_to_le32 (last_qtd->qtd_dma)) {
-				wmb ();
-				qh->hw_qtd_next = hw_next;
-				if (short_rx)
-					qh->hw_alt_next = hw_next
-				    		| (qh->hw_alt_next & 0x1e);
-				vdbg ("queue to qh %p, patch", qh);
-			}
-
-		/* no URB queued */
-		} else {
-			// dbg_qh ("empty qh", ehci, qh);
-
-// FIXME:  how handle usb_clear_halt() for an EP with queued URBs?
-// usbcore may not let us handle that cleanly...
-// likely must cancel them all first!
-
-			/* usb_clear_halt() means qh data toggle gets reset */
-			if (usb_pipebulk (urb->pipe)
-					&& unlikely (!usb_gettoggle (urb->dev,
-						(epnum & 0x0f),
-						!(epnum & 0x10)))) {
-				clear_toggle (urb->dev,
-					epnum & 0x0f, !(epnum & 0x10), qh);
-			}
-			qh_update (qh, qtd);
-		}
-		list_splice (qtd_list, qh->qtd_list.prev);
-
-	} else {
-		/* can't sleep here, we have ehci->lock... */
-		qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC);
-		if (likely (qh != 0)) {
-			// dbg_qh ("new qh", ehci, qh);
-			dev->ep [epnum] = qh;
-		} else
-			urb->status = -ENOMEM;
-	}
-
-	/* Control/bulk operations through TTs don't need scheduling,
-	 * the HC and TT handle it when the TT has a buffer ready.
-	 */
-	if (likely (qh != 0)) {
-		urb->hcpriv = qh_put (qh);
-		if (likely (qh->qh_state == QH_STATE_IDLE))
-			qh_link_async (ehci, qh_put (qh));
-	}
-	spin_unlock_irqrestore (&ehci->lock, flags);
-	if (unlikely (!qh))
-		qh_completions (ehci, qtd_list, 1);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* the async qh for the qtds being reclaimed are now unlinked from the HC */
-/* caller must not own ehci->lock */
-
-static void end_unlink_async (struct ehci_hcd *ehci)
-{
-	struct ehci_qh		*qh = ehci->reclaim;
-
-	qh->qh_state = QH_STATE_IDLE;
-	qh->qh_next.qh = 0;
-	qh_unput (ehci, qh);			// refcount from reclaim 
-	ehci->reclaim = 0;
-	ehci->reclaim_ready = 0;
-
-	qh_completions (ehci, &qh->qtd_list, 1);
-
-	// unlink any urb should now unlink all following urbs, so that
-	// relinking only happens for urbs before the unlinked ones.
-	if (!list_empty (&qh->qtd_list)
-			&& HCD_IS_RUNNING (ehci->hcd.state))
-		qh_link_async (ehci, qh);
-	else
-		qh_unput (ehci, qh);		// refcount from async list
-}
-
-
-/* makes sure the async qh will become idle */
-/* caller must own ehci->lock */
-
-static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
-{
-	int		cmd = readl (&ehci->regs->command);
-	struct ehci_qh	*prev;
-
-#ifdef DEBUG
-	if (ehci->reclaim
-			|| !ehci->async
-			|| qh->qh_state != QH_STATE_LINKED
-#ifdef CONFIG_SMP
-// this macro lies except on SMP compiles
-			|| !spin_is_locked (&ehci->lock)
-#endif
-			)
-		BUG ();
-#endif
-
-	qh->qh_state = QH_STATE_UNLINK;
-	ehci->reclaim = qh = qh_put (qh);
-
-	// dbg_qh ("start unlink", ehci, qh);
-
-	/* Remove the last QH (qhead)?  Stop async schedule first. */
-	if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) {
-		/* can't get here without STS_ASS set */
-		if (ehci->hcd.state != USB_STATE_HALT) {
-			if (cmd & CMD_PSE)
-				writel (cmd & ~CMD_ASE, &ehci->regs->command);
-			else {
-				ehci_ready (ehci);
-				while (readl (&ehci->regs->status) & STS_ASS)
-					udelay (100);
-			}
-		}
-		qh->qh_next.qh = ehci->async = 0;
-
-		ehci->reclaim_ready = 1;
-		tasklet_schedule (&ehci->tasklet);
-		return;
-	} 
-
-	if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
-		ehci->reclaim_ready = 1;
-		tasklet_schedule (&ehci->tasklet);
-		return;
-	}
-
-	prev = ehci->async;
-	while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async)
-		prev = prev->qh_next.qh;
-#ifdef DEBUG
-	if (prev->qh_next.qh != qh)
-		BUG ();
-#endif
-
-	if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) {
-		ehci->async = prev;
-		prev->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD);
-	}
-	prev->hw_next = qh->hw_next;
-	prev->qh_next = qh->qh_next;
-
-	ehci->reclaim_ready = 0;
-	cmd |= CMD_IAAD;
-	writel (cmd, &ehci->regs->command);
-	/* posted write need not be known to HC yet ... */
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void scan_async (struct ehci_hcd *ehci)
-{
-	struct ehci_qh		*qh;
-	unsigned long		flags;
-
-	spin_lock_irqsave (&ehci->lock, flags);
-rescan:
-	qh = ehci->async;
-	if (likely (qh != 0)) {
-		do {
-			/* clean any finished work for this qh */
-			if (!list_empty (&qh->qtd_list)) {
-				// dbg_qh ("scan_async", ehci, qh);
-				qh = qh_put (qh);
-				spin_unlock_irqrestore (&ehci->lock, flags);
-
-				/* concurrent unlink could happen here */
-				qh_completions (ehci, &qh->qtd_list, 1);
-
-				spin_lock_irqsave (&ehci->lock, flags);
-				qh_unput (ehci, qh);
-			}
-
-			/* unlink idle entries (reduces PCI usage) */
-			if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
-				if (qh->qh_next.qh != qh) {
-					// dbg ("irq/empty");
-					start_unlink_async (ehci, qh);
-				} else {
-					// FIXME:  arrange to stop
-					// after it's been idle a while.
-				}
-			}
-			qh = qh->qh_next.qh;
-			if (!qh)		/* unlinked? */
-				goto rescan;
-		} while (qh != ehci->async);
-	}
-
-	spin_unlock_irqrestore (&ehci->lock, flags);
-}
diff -Nru a/drivers/usb/hcd/ehci-sched.c b/drivers/usb/hcd/ehci-sched.c
--- a/drivers/usb/hcd/ehci-sched.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1212 +0,0 @@
-/*
- * Copyright (c) 2001-2002 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* this file is part of ehci-hcd.c */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI scheduled transaction support:  interrupt, iso, split iso
- * These are called "periodic" transactions in the EHCI spec.
- */
-
-/*
- * Ceiling microseconds (typical) for that many bytes at high speed
- * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
- * to preallocate bandwidth)
- */
-#define EHCI_HOST_DELAY	5	/* nsec, guess */
-#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
-	+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
-	+ EHCI_HOST_DELAY)
-#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
-	+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
-	+ EHCI_HOST_DELAY)
-	
-static int ehci_get_frame (struct usb_hcd *hcd);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * periodic_next_shadow - return "next" pointer on shadow list
- * @periodic: host pointer to qh/itd/sitd
- * @tag: hardware tag for type of this record
- */
-static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, int tag)
-{
-	switch (tag) {
-	case Q_TYPE_QH:
-		return &periodic->qh->qh_next;
-	case Q_TYPE_FSTN:
-		return &periodic->fstn->fstn_next;
-	case Q_TYPE_ITD:
-		return &periodic->itd->itd_next;
-#ifdef have_split_iso
-	case Q_TYPE_SITD:
-		return &periodic->sitd->sitd_next;
-#endif /* have_split_iso */
-	}
-	dbg ("BAD shadow %p tag %d", periodic->ptr, tag);
-	// BUG ();
-	return 0;
-}
-
-/* returns true after successful unlink */
-/* caller must hold ehci->lock */
-static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
-{
-	union ehci_shadow	*prev_p = &ehci->pshadow [frame];
-	u32			*hw_p = &ehci->periodic [frame];
-	union ehci_shadow	here = *prev_p;
-	union ehci_shadow	*next_p;
-
-	/* find predecessor of "ptr"; hw and shadow lists are in sync */
-	while (here.ptr && here.ptr != ptr) {
-		prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
-		hw_p = &here.qh->hw_next;
-		here = *prev_p;
-	}
-	/* an interrupt entry (at list end) could have been shared */
-	if (!here.ptr) {
-		dbg ("entry %p no longer on frame [%d]", ptr, frame);
-		return 0;
-	}
-	// vdbg ("periodic unlink %p from frame %d", ptr, frame);
-
-	/* update hardware list ... HC may still know the old structure, so
-	 * don't change hw_next until it'll have purged its cache
-	 */
-	next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
-	*hw_p = here.qh->hw_next;
-
-	/* unlink from shadow list; HCD won't see old structure again */
-	*prev_p = *next_p;
-	next_p->ptr = 0;
-
-	return 1;
-}
-
-/* how many of the uframe's 125 usecs are allocated? */
-static unsigned short
-periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
-{
-	u32			*hw_p = &ehci->periodic [frame];
-	union ehci_shadow	*q = &ehci->pshadow [frame];
-	unsigned		usecs = 0;
-
-	while (q->ptr) {
-		switch (Q_NEXT_TYPE (*hw_p)) {
-		case Q_TYPE_QH:
-			/* is it in the S-mask? */
-			if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
-				usecs += q->qh->usecs;
-			q = &q->qh->qh_next;
-			break;
-		case Q_TYPE_FSTN:
-			/* for "save place" FSTNs, count the relevant INTR
-			 * bandwidth from the previous frame
-			 */
-			if (q->fstn->hw_prev != EHCI_LIST_END) {
-				dbg ("not counting FSTN bandwidth yet ...");
-			}
-			q = &q->fstn->fstn_next;
-			break;
-		case Q_TYPE_ITD:
-			/* NOTE the "one uframe per itd" policy */
-			if (q->itd->hw_transaction [uframe] != 0)
-				usecs += q->itd->usecs;
-			q = &q->itd->itd_next;
-			break;
-#ifdef have_split_iso
-		case Q_TYPE_SITD:
-			temp = q->sitd->hw_fullspeed_ep &
-				__constant_cpu_to_le32 (1 << 31);
-
-			// FIXME:  this doesn't count data bytes right...
-
-			/* is it in the S-mask?  (count SPLIT, DATA) */
-			if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
-				if (temp)
-					usecs += HS_USECS (188);
-				else
-					usecs += HS_USECS (1);
-			}
-
-			/* ... C-mask?  (count CSPLIT, DATA) */
-			if (q->sitd->hw_uframe &
-					cpu_to_le32 (1 << (8 + uframe))) {
-				if (temp)
-					usecs += HS_USECS (0);
-				else
-					usecs += HS_USECS (188);
-			}
-			q = &q->sitd->sitd_next;
-			break;
-#endif /* have_split_iso */
-		default:
-			BUG ();
-		}
-	}
-#ifdef	DEBUG
-	if (usecs > 100)
-		err ("overallocated uframe %d, periodic is %d usecs",
-			frame * 8 + uframe, usecs);
-#endif
-	return usecs;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void enable_periodic (struct ehci_hcd *ehci)
-{
-	u32	cmd;
-
-	/* did clearing PSE did take effect yet?
-	 * takes effect only at frame boundaries...
-	 */
-	while (readl (&ehci->regs->status) & STS_PSS)
-		udelay (20);
-
-	cmd = readl (&ehci->regs->command) | CMD_PSE;
-	writel (cmd, &ehci->regs->command);
-	/* posted write ... PSS happens later */
-	ehci->hcd.state = USB_STATE_RUNNING;
-
-	/* make sure tasklet scans these */
-	ehci->next_uframe = readl (&ehci->regs->frame_index)
-				% (ehci->periodic_size << 3);
-}
-
-static void disable_periodic (struct ehci_hcd *ehci)
-{
-	u32	cmd;
-
-	/* did setting PSE not take effect yet?
-	 * takes effect only at frame boundaries...
-	 */
-	while (!(readl (&ehci->regs->status) & STS_PSS))
-		udelay (20);
-
-	cmd = readl (&ehci->regs->command) & ~CMD_PSE;
-	writel (cmd, &ehci->regs->command);
-	/* posted write ... */
-
-	ehci->next_uframe = -1;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void intr_deschedule (
-	struct ehci_hcd	*ehci,
-	unsigned	frame,
-	struct ehci_qh	*qh,
-	unsigned	period
-) {
-	unsigned long	flags;
-
-	spin_lock_irqsave (&ehci->lock, flags);
-
-	do {
-		periodic_unlink (ehci, frame, qh);
-		qh_unput (ehci, qh);
-		frame += period;
-	} while (frame < ehci->periodic_size);
-
-	qh->qh_state = QH_STATE_UNLINK;
-	qh->qh_next.ptr = 0;
-	ehci->periodic_urbs--;
-
-	/* maybe turn off periodic schedule */
-	if (!ehci->periodic_urbs)
-		disable_periodic (ehci);
-	else
-		vdbg ("periodic schedule still enabled");
-
-	spin_unlock_irqrestore (&ehci->lock, flags);
-
-	/*
-	 * If the hc may be looking at this qh, then delay a uframe
-	 * (yeech!) to be sure it's done.
-	 * No other threads may be mucking with this qh.
-	 */
-	if (((ehci_get_frame (&ehci->hcd) - frame) % period) == 0)
-		udelay (125);
-
-	qh->qh_state = QH_STATE_IDLE;
-	qh->hw_next = EHCI_LIST_END;
-
-	vdbg ("descheduled qh %p, per = %d frame = %d count = %d, urbs = %d",
-		qh, period, frame,
-		atomic_read (&qh->refcount), ehci->periodic_urbs);
-}
-
-static int intr_submit (
-	struct ehci_hcd		*ehci,
-	struct urb		*urb,
-	struct list_head	*qtd_list,
-	int			mem_flags
-) {
-	unsigned		epnum, period;
-	unsigned		temp;
-	unsigned short		usecs;
-	unsigned long		flags;
-	struct ehci_qh		*qh;
-	struct hcd_dev		*dev;
-	int			status = 0;
-
-	/* get endpoint and transfer data */
-	epnum = usb_pipeendpoint (urb->pipe);
-	if (usb_pipein (urb->pipe)) {
-		temp = urb->dev->epmaxpacketin [epnum];
-		epnum |= 0x10;
-	} else
-		temp = urb->dev->epmaxpacketout [epnum];
-	if (urb->dev->speed != USB_SPEED_HIGH) {
-		dbg ("no intr/tt scheduling yet"); 
-		status = -ENOSYS;
-		goto done;
-	}
-
-	/*
-	 * NOTE: current completion/restart logic doesn't handle more than
-	 * one qtd in a periodic qh ... 16-20 KB/urb is pretty big for this.
-	 * such big requests need many periods to transfer.
-	 */
-	if (unlikely (qtd_list->next != qtd_list->prev)) {
-		dbg ("only one intr qtd per urb allowed"); 
-		status = -EINVAL;
-		goto done;
-	}
-
-	usecs = HS_USECS (urb->transfer_buffer_length);
-
-	/* FIXME handle HS periods of less than 1 frame. */
-	if (urb->interval < 8)
-		period = 1;
-	else
-		period = urb->interval >> 8;
-		
-	spin_lock_irqsave (&ehci->lock, flags);
-
-	/* get the qh (must be empty and idle) */
-	dev = (struct hcd_dev *)urb->dev->hcpriv;
-	qh = (struct ehci_qh *) dev->ep [epnum];
-	if (qh) {
-		/* only allow one queued interrupt urb per EP */
-		if (unlikely (qh->qh_state != QH_STATE_IDLE
-				|| !list_empty (&qh->qtd_list))) {
-			dbg ("interrupt urb already queued");
-			status = -EBUSY;
-		} else {
-			/* maybe reset hardware's data toggle in the qh */
-			if (unlikely (!usb_gettoggle (urb->dev, epnum & 0x0f,
-					!(epnum & 0x10)))) {
-				qh->hw_token |=
-					__constant_cpu_to_le32 (QTD_TOGGLE);
-				usb_settoggle (urb->dev, epnum & 0x0f,
-					!(epnum & 0x10), 1);
-			}
-			/* trust the QH was set up as interrupt ... */
-			list_splice (qtd_list, &qh->qtd_list);
-			qh_update (qh, list_entry (qtd_list->next,
-						struct ehci_qtd, qtd_list));
-		}
-	} else {
-		/* can't sleep here, we have ehci->lock... */
-		qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC);
-		qtd_list = &qh->qtd_list;
-		if (likely (qh != 0)) {
-			// dbg ("new INTR qh %p", qh);
-			dev->ep [epnum] = qh;
-		} else
-			status = -ENOMEM;
-	}
-
-	/* Schedule this periodic QH. */
-	if (likely (status == 0)) {
-		unsigned	frame = urb->interval;
-
-		qh->hw_next = EHCI_LIST_END;
-		qh->usecs = usecs;
-
-		urb->hcpriv = qh_put (qh);
-		status = -ENOSPC;
-
-		/* pick a set of schedule slots, link the QH into them */
-		do {
-			int	uframe;
-
-			/* Select some frame 0..(urb->interval - 1) with a
-			 * microframe that can hold this transaction.
-			 *
-			 * FIXME for TT splits, need uframes for start and end.
-			 * FSTNs can put end into next frame (uframes 0 or 1).
-			 */
-			frame--;
-			for (uframe = 0; uframe < 8; uframe++) {
-				int	claimed;
-				claimed = periodic_usecs (ehci, frame, uframe);
-				/* 80% periodic == 100 usec max committed */
-				if ((claimed + usecs) <= 100) {
-					vdbg ("frame %d.%d: %d usecs, plus %d",
-						frame, uframe, claimed, usecs);
-					break;
-				}
-			}
-			if (uframe == 8)
-				continue;
-// FIXME delete when code below handles non-empty queues
-			if (ehci->pshadow [frame].ptr)
-				continue;
-
-			/* QH will run once each period, starting there  */
-			urb->start_frame = frame;
-			status = 0;
-
-			/* set S-frame mask */
-			qh->hw_info2 |= cpu_to_le32 (1 << uframe);
-			// dbg_qh ("Schedule INTR qh", ehci, qh);
-
-			/* stuff into the periodic schedule */
-			qh->qh_state = QH_STATE_LINKED;
-			vdbg ("qh %p usecs %d period %d starting %d.%d",
-				qh, qh->usecs, period, frame, uframe);
-			do {
-				if (unlikely (ehci->pshadow [frame].ptr != 0)) {
-// FIXME -- just link to the end, before any qh with a shorter period,
-// AND handle it already being (implicitly) linked into this frame
-					BUG ();
-				} else {
-					ehci->pshadow [frame].qh = qh_put (qh);
-					ehci->periodic [frame] =
-						QH_NEXT (qh->qh_dma);
-				}
-				frame += period;
-			} while (frame < ehci->periodic_size);
-
-			/* update bandwidth utilization records (for usbfs) */
-			usb_claim_bandwidth (urb->dev, urb, usecs, 0);
-
-			/* maybe enable periodic schedule processing */
-			if (!ehci->periodic_urbs++)
-				enable_periodic (ehci);
-			break;
-
-		} while (frame);
-	}
-	spin_unlock_irqrestore (&ehci->lock, flags);
-done:
-	if (status) {
-		usb_complete_t	complete = urb->complete;
-
-		urb->complete = 0;
-		urb->status = status;
-		qh_completions (ehci, qtd_list, 1);
-		urb->complete = complete;
-	}
-	return status;
-}
-
-static unsigned long
-intr_complete (
-	struct ehci_hcd	*ehci,
-	unsigned	frame,
-	struct ehci_qh	*qh,
-	unsigned long	flags		/* caller owns ehci->lock ... */
-) {
-	struct ehci_qtd	*qtd;
-	struct urb	*urb;
-	int		unlinking;
-
-	/* nothing to report? */
-	if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
-			!= 0))
-		return flags;
-	
-	qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list);
-	urb = qtd->urb;
-	unlinking = (urb->status == -ENOENT) || (urb->status == -ECONNRESET);
-
-	/* call any completions, after patching for reactivation */
-	spin_unlock_irqrestore (&ehci->lock, flags);
-	/* NOTE:  currently restricted to one qtd per qh! */
-	if (qh_completions (ehci, &qh->qtd_list, 0) == 0)
-		urb = 0;
-	spin_lock_irqsave (&ehci->lock, flags);
-
-	/* never reactivate requests that were unlinked ... */
-	if (likely (urb != 0)) {
-		if (unlinking
-				|| urb->status == -ECONNRESET
-				|| urb->status == -ENOENT
-				// || (urb->dev == null)
-				|| ehci->hcd.state == USB_STATE_HALT)
-			urb = 0;
-		// FIXME look at all those unlink cases ... we always
-		// need exactly one completion that reports unlink.
-		// the one above might not have been it!
-	}
-
-	/* normally reactivate */
-	if (likely (urb != 0)) {
-		if (usb_pipeout (urb->pipe))
-			pci_dma_sync_single (ehci->hcd.pdev,
-				qtd->buf_dma,
-				urb->transfer_buffer_length,
-				PCI_DMA_TODEVICE);
-		urb->status = -EINPROGRESS;
-		urb->actual_length = 0;
-
-		/* patch qh and restart */
-		qh_update (qh, qtd);
-	}
-	return flags;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
-{
-	struct ehci_itd *first_itd = urb->hcpriv;
-
-	pci_unmap_single (ehci->hcd.pdev,
-		first_itd->buf_dma, urb->transfer_buffer_length,
-		usb_pipein (urb->pipe)
-		    ? PCI_DMA_FROMDEVICE
-		    : PCI_DMA_TODEVICE);
-	while (!list_empty (&first_itd->itd_list)) {
-		struct ehci_itd	*itd;
-
-		itd = list_entry (
-			first_itd->itd_list.next,
-			struct ehci_itd, itd_list);
-		list_del (&itd->itd_list);
-		pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
-	}
-	pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma);
-	urb->hcpriv = 0;
-}
-
-static int
-itd_fill (
-	struct ehci_hcd	*ehci,
-	struct ehci_itd	*itd,
-	struct urb	*urb,
-	unsigned	index,		// urb->iso_frame_desc [index]
-	dma_addr_t	dma		// mapped transfer buffer
-) {
-	u64		temp;
-	u32		buf1;
-	unsigned	i, epnum, maxp, multi;
-	unsigned	length;
-
-	itd->hw_next = EHCI_LIST_END;
-	itd->urb = urb;
-	itd->index = index;
-
-	/* tell itd about its transfer buffer, max 2 pages */
-	length = urb->iso_frame_desc [index].length;
-	dma += urb->iso_frame_desc [index].offset;
-	temp = dma & ~0x0fff;
-	for (i = 0; i < 2; i++) {
-		itd->hw_bufp [i] = cpu_to_le32 ((u32) temp);
-		itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32));
-		temp += 0x1000;
-	}
-	itd->buf_dma = dma;
-
-	/*
-	 * this might be a "high bandwidth" highspeed endpoint,
-	 * as encoded in the ep descriptor's maxpacket field
-	 */
-	epnum = usb_pipeendpoint (urb->pipe);
-	if (usb_pipein (urb->pipe)) {
-		maxp = urb->dev->epmaxpacketin [epnum];
-		buf1 = (1 << 11);
-	} else {
-		maxp = urb->dev->epmaxpacketout [epnum];
-		buf1 = 0;
-	}
-	buf1 |= (maxp & 0x03ff);
-	multi = 1;
-	multi += (maxp >> 11) & 0x03;
-	maxp &= 0x03ff;
-	maxp *= multi;
-
-	/* transfer can't fit in any uframe? */ 
-	if (length < 0 || maxp < length) {
-		dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)",
-			length, maxp, urb, index,
-			urb->iso_frame_desc [index].length);
-		return -ENOSPC;
-	}
-	itd->usecs = HS_USECS_ISO (length);
-
-	/* "plus" info in low order bits of buffer pointers */
-	itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum);
-	itd->hw_bufp [1] |= cpu_to_le32 (buf1);
-	itd->hw_bufp [2] |= cpu_to_le32 (multi);
-
-	/* figure hw_transaction[] value (it's scheduled later) */
-	itd->transaction = EHCI_ISOC_ACTIVE;
-	itd->transaction |= dma & 0x0fff;		/* offset; buffer=0 */
-	if ((index + 1) == urb->number_of_packets)
-		itd->transaction |= EHCI_ITD_IOC; 	/* end-of-urb irq */
-	itd->transaction |= length << 16;
-	cpu_to_le32s (&itd->transaction);
-
-	return 0;
-}
-
-static int
-itd_urb_transaction (
-	struct ehci_hcd		*ehci,
-	struct urb		*urb,
-	int			mem_flags
-) {
-	int			frame_index;
-	struct ehci_itd		*first_itd, *itd;
-	int			status;
-	dma_addr_t		buf_dma, itd_dma;
-
-	/* set up one dma mapping for this urb */
-	buf_dma = pci_map_single (ehci->hcd.pdev,
-		urb->transfer_buffer, urb->transfer_buffer_length,
-		usb_pipein (urb->pipe)
-		    ? PCI_DMA_FROMDEVICE
-		    : PCI_DMA_TODEVICE);
-	if (buf_dma == 0)
-		return -ENOMEM;
-
-	/* allocate/init ITDs */
-	for (frame_index = 0, first_itd = 0;
-			frame_index < urb->number_of_packets;
-			frame_index++) {
-		itd = pci_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma);
-		if (!itd) {
-			status = -ENOMEM;
-			goto fail;
-		}
-		memset (itd, 0, sizeof *itd);
-		itd->itd_dma = itd_dma;
-
-		status = itd_fill (ehci, itd, urb, frame_index, buf_dma);
-		if (status != 0)
-			goto fail;
-
-		if (first_itd)
-			list_add_tail (&itd->itd_list,
-					&first_itd->itd_list);
-		else {
-			INIT_LIST_HEAD (&itd->itd_list);
-			urb->hcpriv = first_itd = itd;
-		}
-	}
-	urb->error_count = 0;
-	return 0;
-
-fail:
-	if (urb->hcpriv)
-		itd_free_list (ehci, urb);
-	return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline void
-itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
-{
-	/* always prepend ITD/SITD ... only QH tree is order-sensitive */
-	itd->itd_next = ehci->pshadow [frame];
-	itd->hw_next = ehci->periodic [frame];
-	ehci->pshadow [frame].itd = itd;
-	ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
-}
-
-/*
- * return zero on success, else -errno
- * - start holds first uframe to start scheduling into
- * - max is the first uframe it's NOT (!) OK to start scheduling into
- * math to be done modulo "mod" (ehci->periodic_size << 3)
- */
-static int get_iso_range (
-	struct ehci_hcd		*ehci,
-	struct urb		*urb,
-	unsigned		*start,
-	unsigned		*max,
-	unsigned		mod
-) {
-	struct list_head	*lh;
-	struct hcd_dev		*dev = urb->dev->hcpriv;
-	int			last = -1;
-	unsigned		now, span, end;
-
-	span = urb->interval * urb->number_of_packets;
-
-	/* first see if we know when the next transfer SHOULD happen */
-	list_for_each (lh, &dev->urb_list) {
-		struct urb	*u;
-		struct ehci_itd	*itd;
-		unsigned	s;
-
-		u = list_entry (lh, struct urb, urb_list);
-		if (u == urb || u->pipe != urb->pipe)
-			continue;
-		if (u->interval != urb->interval) {	/* must not change! */ 
-			dbg ("urb %p interval %d ... != %p interval %d",
-				u, u->interval, urb, urb->interval);
-			return -EINVAL;
-		}
-		
-		/* URB for this endpoint... covers through when?  */
-		itd = urb->hcpriv;
-		s = itd->uframe + u->interval * u->number_of_packets;
-		if (last < 0)
-			last = s;
-		else {
-			/*
-			 * So far we can only queue two ISO URBs...
-			 *
-			 * FIXME do interval math, figure out whether
-			 * this URB is "before" or not ... also, handle
-			 * the case where the URB might have completed,
-			 * but hasn't yet been processed.
-			 */
-			dbg ("NYET: queue >2 URBs per ISO endpoint");
-			return -EDOM;
-		}
-	}
-
-	/* calculate the legal range [start,max) */
-	now = readl (&ehci->regs->frame_index) + 1;	/* next uframe */
-	if (!ehci->periodic_urbs)
-		now += 8;				/* startup delay */
-	now %= mod;
-	end = now + mod;
-	if (last < 0) {
-		*start = now + ehci->i_thresh + /* paranoia */ 1;
-		*max = end - span;
-		if (*max < *start + 1)
-			*max = *start + 1;
-	} else {
-		*start = last % mod;
-		*max = (last + 1) % mod;
-	}
-
-	/* explicit start frame? */
-	if (!(urb->transfer_flags & USB_ISO_ASAP)) {
-		unsigned	temp;
-
-		/* sanity check: must be in range */
-		urb->start_frame %= ehci->periodic_size;
-		temp = urb->start_frame << 3;
-		if (temp < *start)
-			temp += mod;
-		if (temp > *max)
-			return -EDOM;
-
-		/* use that explicit start frame */
-		*start = urb->start_frame << 3;
-		temp += 8;
-		if (temp < *max)
-			*max = temp;
-	}
-
-	// FIXME minimize wraparound to "now" ... insist max+span
-	// (and start+span) remains a few frames short of "end"
-
-	*max %= ehci->periodic_size;
-	if ((*start + span) < end)
-		return 0;
-	return -EFBIG;
-}
-
-static int
-itd_schedule (struct ehci_hcd *ehci, struct urb *urb)
-{
-	unsigned	start, max, i;
-	int		status;
-	unsigned	mod = ehci->periodic_size << 3;
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		urb->iso_frame_desc [i].status = -EINPROGRESS;
-		urb->iso_frame_desc [i].actual_length = 0;
-	}
-
-	if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0)
-		return status;
-
-	do {
-		unsigned	uframe;
-		unsigned	usecs;
-		struct ehci_itd	*itd;
-
-		/* check schedule: enough space? */
-		itd = urb->hcpriv;
-		uframe = start;
-		for (i = 0, uframe = start;
-				i < urb->number_of_packets;
-				i++, uframe += urb->interval) {
-			uframe %= mod;
-
-			/* can't commit more than 80% periodic == 100 usec */
-			if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
-					> (100 - itd->usecs)) {
-				itd = 0;
-				break;
-			}
-			itd = list_entry (itd->itd_list.next,
-				struct ehci_itd, itd_list);
-		}
-		if (!itd)
-			continue;
-		
-		/* that's where we'll schedule this! */
-		itd = urb->hcpriv;
-		urb->start_frame = start >> 3;
-		vdbg ("ISO urb %p (%d packets period %d) starting %d.%d",
-			urb, urb->number_of_packets, urb->interval,
-			urb->start_frame, start & 0x7);
-		for (i = 0, uframe = start, usecs = 0;
-				i < urb->number_of_packets;
-				i++, uframe += urb->interval) {
-			uframe %= mod;
-
-			itd->uframe = uframe;
-			itd->hw_transaction [uframe & 0x07] = itd->transaction;
-			itd_link (ehci, (uframe >> 3) % ehci->periodic_size,
-				itd);
-			usecs += itd->usecs;
-
-			itd = list_entry (itd->itd_list.next,
-				struct ehci_itd, itd_list);
-		}
-
-		/* update bandwidth utilization records (for usbfs) */
-		/* FIXME usbcore expects per-frame average, which isn't
-		 * most accurate model... this provides the total claim,
-		 * and expects the average to be computed only display.
-		 */
-		usb_claim_bandwidth (urb->dev, urb, usecs, 1);
-
-		/* maybe enable periodic schedule processing */
-		if (!ehci->periodic_urbs++)
-			enable_periodic (ehci);
-
-		return 0;
-
-	} while ((start = ++start % mod) != max);
-
-	/* no room in the schedule */
-	dbg ("urb %p, CAN'T SCHEDULE", urb);
-	return -ENOSPC;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
-
-static unsigned long
-itd_complete (
-	struct ehci_hcd	*ehci,
-	struct ehci_itd	*itd,
-	unsigned	uframe,
-	unsigned long	flags
-) {
-	struct urb				*urb = itd->urb;
-	struct usb_iso_packet_descriptor	*desc;
-	u32					t;
-
-	/* update status for this uframe's transfers */
-	desc = &urb->iso_frame_desc [itd->index];
-
-	t = itd->hw_transaction [uframe];
-	itd->hw_transaction [uframe] = 0;
-	if (t & EHCI_ISOC_ACTIVE)
-		desc->status = -EXDEV;
-	else if (t & ISO_ERRS) {
-		urb->error_count++;
-		if (t & EHCI_ISOC_BUF_ERR)
-			desc->status = usb_pipein (urb->pipe)
-				? -ENOSR  /* couldn't read */
-				: -ECOMM; /* couldn't write */
-		else if (t & EHCI_ISOC_BABBLE)
-			desc->status = -EOVERFLOW;
-		else /* (t & EHCI_ISOC_XACTERR) */
-			desc->status = -EPROTO;
-
-		/* HC need not update length with this error */
-		if (!(t & EHCI_ISOC_BABBLE))
-			desc->actual_length += EHCI_ITD_LENGTH (t);
-	} else {
-		desc->status = 0;
-		desc->actual_length += EHCI_ITD_LENGTH (t);
-	}
-
-	vdbg ("itd %p urb %p packet %d/%d trans %x status %d len %d",
-		itd, urb, itd->index + 1, urb->number_of_packets,
-		t, desc->status, desc->actual_length);
-
-	/* handle completion now? */
-	if ((itd->index + 1) != urb->number_of_packets)
-		return flags;
-
-	/*
-	 * For now, always give the urb back to the driver ... expect it
-	 * to submit a new urb (or resubmit this), and to have another
-	 * already queued when un-interrupted transfers are needed.
-	 * No, that's not what OHCI or UHCI are now doing.
-	 *
-	 * FIXME Revisit the ISO URB model.  It's cleaner not to have all
-	 * the special case magic, but it'd be faster to reuse existing
-	 * ITD/DMA setup and schedule state.  Easy to dma_sync/complete(),
-	 * then either reschedule or, if unlinking, free and giveback().
-	 * But we can't overcommit like the full and low speed HCs do, and
-	 * there's no clean way to report an error when rescheduling...
-	 *
-	 * NOTE that for now we don't accelerate ISO unlinks; they just
-	 * happen according to the current schedule.  Means a delay of
-	 * up to about a second (max).
-	 */
-	itd_free_list (ehci, urb);
-	if (urb->status == -EINPROGRESS)
-		urb->status = 0;
-
-	spin_unlock_irqrestore (&ehci->lock, flags);
-	usb_hcd_giveback_urb (&ehci->hcd, urb);
-	spin_lock_irqsave (&ehci->lock, flags);
-
-	/* defer stopping schedule; completion can submit */
-	ehci->periodic_urbs--;
-	if (!ehci->periodic_urbs)
-		disable_periodic (ehci);
-
-	return flags;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
-{
-	int		status;
-	unsigned long	flags;
-
-	dbg ("itd_submit urb %p", urb);
-
-	/* NOTE DMA mapping assumes this ... */
-	if (urb->iso_frame_desc [0].offset != 0)
-		return -EINVAL;
-	
-	/*
-	 * NOTE doing this for now, anticipating periodic URB models
-	 * get updated to be "explicit resubmit".
-	 */
-	if (urb->next) {
-		dbg ("use explicit resubmit for ISO");
-		return -EINVAL;
-	}
-
-	/* allocate ITDs w/o locking anything */
-	status = itd_urb_transaction (ehci, urb, mem_flags);
-	if (status < 0)
-		return status;
-
-	/* schedule ... need to lock */
-	spin_lock_irqsave (&ehci->lock, flags);
-	status = itd_schedule (ehci, urb);
-	spin_unlock_irqrestore (&ehci->lock, flags);
-	if (status < 0)
-		itd_free_list (ehci, urb);
-
-	return status;
-}
-
-#ifdef have_split_iso
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * "Split ISO TDs" ... used for USB 1.1 devices going through
- * the TTs in USB 2.0 hubs.
- */
-
-static void
-sitd_free (struct ehci_hcd *ehci, struct ehci_sitd *sitd)
-{
-	pci_pool_free (ehci->sitd_pool, sitd, sitd->sitd_dma);
-}
-
-static struct ehci_sitd *
-sitd_make (
-	struct ehci_hcd	*ehci,
-	struct urb	*urb,
-	unsigned	index,		// urb->iso_frame_desc [index]
-	unsigned	uframe,		// scheduled start
-	dma_addr_t	dma,		// mapped transfer buffer
-	int		mem_flags
-) {
-	struct ehci_sitd	*sitd;
-	unsigned		length;
-
-	sitd = pci_pool_alloc (ehci->sitd_pool, mem_flags, &dma);
-	if (!sitd)
-		return sitd;
-	sitd->urb = urb;
-	length = urb->iso_frame_desc [index].length;
-	dma += urb->iso_frame_desc [index].offset;
-
-#if 0
-	// FIXME:  do the rest!
-#else
-	sitd_free (ehci, sitd);
-	return 0;
-#endif
-
-}
-
-static void
-sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
-{
-	u32		ptr;
-
-	ptr = cpu_to_le32 (sitd->sitd_dma | 2);	// type 2 == sitd
-	if (ehci->pshadow [frame].ptr) {
-		if (!sitd->sitd_next.ptr) {
-			sitd->sitd_next = ehci->pshadow [frame];
-			sitd->hw_next = ehci->periodic [frame];
-		} else if (sitd->sitd_next.ptr != ehci->pshadow [frame].ptr) {
-			dbg ("frame %d sitd link goof", frame);
-			BUG ();
-		}
-	}
-	ehci->pshadow [frame].sitd = sitd;
-	ehci->periodic [frame] = ptr;
-}
-
-static unsigned long
-sitd_complete (
-	struct ehci_hcd *ehci,
-	struct ehci_sitd	*sitd,
-	unsigned long		flags
-) {
-	// FIXME -- implement!
-
-	dbg ("NYI -- sitd_complete");
-	return flags;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
-{
-	// struct ehci_sitd	*first_sitd = 0;
-	unsigned		frame_index;
-	dma_addr_t		dma;
-
-	dbg ("NYI -- sitd_submit");
-
-	// FIXME -- implement!
-
-	// FIXME:  setup one big dma mapping
-	dma = 0;
-
-	for (frame_index = 0;
-			frame_index < urb->number_of_packets;
-			frame_index++) {
-		struct ehci_sitd	*sitd;
-		unsigned		uframe;
-
-		// FIXME:  use real arguments, schedule this!
-		uframe = -1;
-
-		sitd = sitd_make (ehci, urb, frame_index,
-				uframe, dma, mem_flags);
-
-		if (sitd) {
-    /*
-			if (first_sitd)
-				list_add_tail (&sitd->sitd_list,
-						&first_sitd->sitd_list);
-			else
-				first_sitd = sitd;
-    */
-		} else {
-			// FIXME:  clean everything up
-		}
-	}
-
-	// if we have a first sitd, then
-		// store them all into the periodic schedule!
-		// urb->hcpriv = first sitd in sitd_list
-
-	return -ENOSYS;
-}
-#endif /* have_split_iso */
-
-/*-------------------------------------------------------------------------*/
-
-static void scan_periodic (struct ehci_hcd *ehci)
-{
-	unsigned	frame, clock, now_uframe, mod;
-	unsigned long	flags;
-
-	mod = ehci->periodic_size << 3;
-	spin_lock_irqsave (&ehci->lock, flags);
-
-	/*
-	 * When running, scan from last scan point up to "now"
-	 * else clean up by scanning everything that's left.
-	 * Touches as few pages as possible:  cache-friendly.
-	 * Don't scan ISO entries more than once, though.
-	 */
-	frame = ehci->next_uframe >> 3;
-	if (HCD_IS_RUNNING (ehci->hcd.state))
-		now_uframe = readl (&ehci->regs->frame_index);
-	else
-		now_uframe = (frame << 3) - 1;
-	now_uframe %= mod;
-	clock = now_uframe >> 3;
-
-	for (;;) {
-		union ehci_shadow	q, *q_p;
-		u32			type, *hw_p;
-		unsigned		uframes;
-
-restart:
-		/* scan schedule to _before_ current frame index */
-		if (frame == clock)
-			uframes = now_uframe & 0x07;
-		else
-			uframes = 8;
-
-		q_p = &ehci->pshadow [frame];
-		hw_p = &ehci->periodic [frame];
-		q.ptr = q_p->ptr;
-		type = Q_NEXT_TYPE (*hw_p);
-
-		/* scan each element in frame's queue for completions */
-		while (q.ptr != 0) {
-			int			last;
-			unsigned		uf;
-			union ehci_shadow	temp;
-
-			switch (type) {
-			case Q_TYPE_QH:
-				last = (q.qh->hw_next == EHCI_LIST_END);
-				temp = q.qh->qh_next;
-				type = Q_NEXT_TYPE (q.qh->hw_next);
-				flags = intr_complete (ehci, frame,
-						qh_put (q.qh), flags);
-				qh_unput (ehci, q.qh);
-				q = temp;
-				break;
-			case Q_TYPE_FSTN:
-				last = (q.fstn->hw_next == EHCI_LIST_END);
-				/* for "save place" FSTNs, look at QH entries
-				 * in the previous frame for completions.
-				 */
-				if (q.fstn->hw_prev != EHCI_LIST_END) {
-					dbg ("ignoring completions from FSTNs");
-				}
-				type = Q_NEXT_TYPE (q.fstn->hw_next);
-				q = q.fstn->fstn_next;
-				break;
-			case Q_TYPE_ITD:
-				last = (q.itd->hw_next == EHCI_LIST_END);
-
-				/* Unlink each (S)ITD we see, since the ISO
-				 * URB model forces constant rescheduling.
-				 * That complicates sharing uframes in ITDs,
-				 * and means we need to skip uframes the HC
-				 * hasn't yet processed.
-				 */
-				for (uf = 0; uf < uframes; uf++) {
-					if (q.itd->hw_transaction [uf] != 0) {
-						temp = q;
-						*q_p = q.itd->itd_next;
-						*hw_p = q.itd->hw_next;
-						type = Q_NEXT_TYPE (*hw_p);
-
-						/* might free q.itd ... */
-						flags = itd_complete (ehci,
-							temp.itd, uf, flags);
-						break;
-					}
-				}
-				/* we might skip this ITD's uframe ... */
-				if (uf == uframes) {
-					q_p = &q.itd->itd_next;
-					hw_p = &q.itd->hw_next;
-					type = Q_NEXT_TYPE (q.itd->hw_next);
-				}
-
-				q = *q_p;
-				break;
-#ifdef have_split_iso
-			case Q_TYPE_SITD:
-				last = (q.sitd->hw_next == EHCI_LIST_END);
-				flags = sitd_complete (ehci, q.sitd, flags);
-				type = Q_NEXT_TYPE (q.sitd->hw_next);
-
-				// FIXME unlink SITD after split completes
-				q = q.sitd->sitd_next;
-				break;
-#endif /* have_split_iso */
-			default:
-				dbg ("corrupt type %d frame %d shadow %p",
-					type, frame, q.ptr);
-				// BUG ();
-				last = 1;
-				q.ptr = 0;
-			}
-
-			/* did completion remove an interior q entry? */
-			if (unlikely (q.ptr == 0 && !last))
-				goto restart;
-		}
-
-		/* stop when we catch up to the HC */
-
-		// FIXME:  this assumes we won't get lapped when
-		// latencies climb; that should be rare, but...
-		// detect it, and just go all the way around.
-		// FLR might help detect this case, so long as latencies
-		// don't exceed periodic_size msec (default 1.024 sec).
-
-		// FIXME:  likewise assumes HC doesn't halt mid-scan
-
-		if (frame == clock) {
-			unsigned	now;
-
-			if (!HCD_IS_RUNNING (ehci->hcd.state))
-				break;
-			ehci->next_uframe = now_uframe;
-			now = readl (&ehci->regs->frame_index) % mod;
-			if (now_uframe == now)
-				break;
-
-			/* rescan the rest of this frame, then ... */
-			now_uframe = now;
-			clock = now_uframe >> 3;
-		} else
-			frame = (frame + 1) % ehci->periodic_size;
-	} 
-	spin_unlock_irqrestore (&ehci->lock, flags);
-}
diff -Nru a/drivers/usb/hcd/ehci.h b/drivers/usb/hcd/ehci.h
--- a/drivers/usb/hcd/ehci.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,385 +0,0 @@
-/*
- * Copyright (c) 2001-2002 by David Brownell
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __LINUX_EHCI_HCD_H
-#define __LINUX_EHCI_HCD_H
-
-/* definitions used for the EHCI driver */
-
-/* ehci_hcd->lock guards shared data against other CPUs:
- *   ehci_hcd:	async, reclaim, periodic (and shadow), ...
- *   hcd_dev:	ep[]
- *   ehci_qh:	qh_next, qtd_list
- *   ehci_qtd:	qtd_list
- *
- * Also, hold this lock when talking to HC registers or
- * when updating hw_* fields in shared qh/qtd/... structures.
- */
-
-#define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
-
-struct ehci_hcd {			/* one per controller */
-	spinlock_t		lock;
-
-	/* async schedule support */
-	struct ehci_qh		*async;
-	struct ehci_qh		*reclaim;
-	int			reclaim_ready;
-
-	/* periodic schedule support */
-#define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
-	unsigned		periodic_size;
-	u32			*periodic;	/* hw periodic table */
-	dma_addr_t		periodic_dma;
-	unsigned		i_thresh;	/* uframes HC might cache */
-
-	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
-	int			next_uframe;	/* scan periodic, start here */
-	unsigned		periodic_urbs;	/* how many urbs scheduled? */
-
-	/* deferred work from IRQ, etc */
-	struct tasklet_struct	tasklet;
-
-	/* per root hub port */
-	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
-
-	/* glue to PCI and HCD framework */
-	struct usb_hcd		hcd;
-	struct ehci_caps	*caps;
-	struct ehci_regs	*regs;
-	u32			hcs_params;	/* cached register copy */
-
-	/* per-HC memory pools (could be per-PCI-bus, but ...) */
-	struct pci_pool		*qh_pool;	/* qh per active urb */
-	struct pci_pool		*qtd_pool;	/* one or more per qh */
-	struct pci_pool		*itd_pool;	/* itd per iso urb */
-	struct pci_pool		*sitd_pool;	/* sitd per split iso urb */
-};
-
-/* unwrap an HCD pointer to get an EHCI_HCD pointer */ 
-#define hcd_to_ehci(hcd_ptr) list_entry(hcd_ptr, struct ehci_hcd, hcd)
-
-/* NOTE:  urb->transfer_flags expected to not use this bit !!! */
-#define EHCI_STATE_UNLINK	0x8000		/* urb being unlinked */
-
-/*-------------------------------------------------------------------------*/
-
-/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
-
-/* Section 2.2 Host Controller Capability Registers */
-struct ehci_caps {
-	u8		length;		/* CAPLENGTH - size of this struct */
-	u8		reserved;       /* offset 0x1 */
-	u16		hci_version;    /* HCIVERSION - offset 0x2 */
-	u32		hcs_params;     /* HCSPARAMS - offset 0x4 */
-#define HCS_DEBUG_PORT(p)	(((p)>>20)&0xf)	/* bits 23:20, debug port? */
-#define HCS_INDICATOR(p)	((p)&(1 << 16))	/* true: has port indicators */
-#define HCS_N_CC(p)		(((p)>>12)&0xf)	/* bits 15:12, #companion HCs */
-#define HCS_N_PCC(p)		(((p)>>8)&0xf)	/* bits 11:8, ports per CC */
-#define HCS_PORTROUTED(p)	((p)&(1 << 7))	/* true: port routing */ 
-#define HCS_PPC(p)		((p)&(1 << 4))	/* true: port power control */ 
-#define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
-
-	u32		hcc_params;      /* HCCPARAMS - offset 0x8 */
-#define HCC_EXT_CAPS(p)		(((p)>>8)&0xff)	/* for pci extended caps */
-#define HCC_ISOC_CACHE(p)       ((p)&(1 << 7))  /* true: can cache isoc frame */
-#define HCC_ISOC_THRES(p)       (((p)>>4)&0x7)  /* bits 6:4, uframes cached */
-#define HCC_CANPARK(p)		((p)&(1 << 2))  /* true: can park on async qh */
-#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1))  /* true: periodic_size changes*/
-#define HCC_64BIT_ADDR(p)       ((p)&(1))       /* true: can use 64-bit addr */
-	u8		portroute [8];	 /* nibbles for routing - offset 0xC */
-} __attribute__ ((packed));
-
-
-/* Section 2.3 Host Controller Operational Registers */
-struct ehci_regs {
-
-	/* USBCMD: offset 0x00 */
-	u32		command;
-/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
-#define CMD_PARK	(1<<11)		/* enable "park" on async qh */
-#define CMD_PARK_CNT(c)	(((c)>>8)&3)	/* how many transfers to park for */
-#define CMD_LRESET	(1<<7)		/* partial reset (no ports, etc) */
-#define CMD_IAAD	(1<<6)		/* "doorbell" interrupt async advance */
-#define CMD_ASE		(1<<5)		/* async schedule enable */
-#define CMD_PSE  	(1<<4)		/* periodic schedule enable */
-/* 3:2 is periodic frame list size */
-#define CMD_RESET	(1<<1)		/* reset HC not bus */
-#define CMD_RUN		(1<<0)		/* start/stop HC */
-
-	/* USBSTS: offset 0x04 */
-	u32		status;
-#define STS_ASS		(1<<15)		/* Async Schedule Status */
-#define STS_PSS		(1<<14)		/* Periodic Schedule Status */
-#define STS_RECL	(1<<13)		/* Reclamation */
-#define STS_HALT	(1<<12)		/* Not running (any reason) */
-/* some bits reserved */
-	/* these STS_* flags are also intr_enable bits (USBINTR) */
-#define STS_IAA		(1<<5)		/* Interrupted on async advance */
-#define STS_FATAL	(1<<4)		/* such as some PCI access errors */
-#define STS_FLR		(1<<3)		/* frame list rolled over */
-#define STS_PCD		(1<<2)		/* port change detect */
-#define STS_ERR		(1<<1)		/* "error" completion (overflow, ...) */
-#define STS_INT		(1<<0)		/* "normal" completion (short, ...) */
-
-	/* USBINTR: offset 0x08 */
-	u32		intr_enable;
-
-	/* FRINDEX: offset 0x0C */
-	u32		frame_index;	/* current microframe number */
-	/* CTRLDSSEGMENT: offset 0x10 */
-	u32		segment; 	/* address bits 63:32 if needed */
-	/* PERIODICLISTBASE: offset 0x14 */
-	u32		frame_list; 	/* points to periodic list */
-	/* ASYNCICLISTADDR: offset 0x18 */
-	u32		async_next;	/* address of next async queue head */
-
-	u32		reserved [9];
-
-	/* CONFIGFLAG: offset 0x40 */
-	u32		configured_flag;
-#define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
-
-	/* PORTSC: offset 0x44 */
-	u32		port_status [0];	/* up to N_PORTS */
-/* 31:23 reserved */
-#define PORT_WKOC_E	(1<<22)		/* wake on overcurrent (enable) */
-#define PORT_WKDISC_E	(1<<21)		/* wake on disconnect (enable) */
-#define PORT_WKCONN_E	(1<<20)		/* wake on connect (enable) */
-/* 19:16 for port testing */
-/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */
-#define PORT_OWNER	(1<<13)		/* true: companion hc owns this port */
-#define PORT_POWER	(1<<12)		/* true: has power (see PPC) */
-#define PORT_USB11(x) (((x)&(3<<10))==(1<<10))	/* USB 1.1 device */
-/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
-/* 9 reserved */
-#define PORT_RESET	(1<<8)		/* reset port */
-#define PORT_SUSPEND	(1<<7)		/* suspend port */
-#define PORT_RESUME	(1<<6)		/* resume it */
-#define PORT_OCC	(1<<5)		/* over current change */
-#define PORT_OC		(1<<4)		/* over current active */
-#define PORT_PEC	(1<<3)		/* port enable change */
-#define PORT_PE		(1<<2)		/* port enable */
-#define PORT_CSC	(1<<1)		/* connect status change */
-#define PORT_CONNECT	(1<<0)		/* device connected */
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-#define	QTD_NEXT(dma)	cpu_to_le32((u32)dma)
-
-/*
- * EHCI Specification 0.95 Section 3.5
- * QTD: describe data transfer components (buffer, direction, ...) 
- * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
- *
- * These are associated only with "QH" (Queue Head) structures,
- * used with control, bulk, and interrupt transfers.
- */
-struct ehci_qtd {
-	/* first part defined by EHCI spec */
-	u32			hw_next;	  /* see EHCI 3.5.1 */
-	u32			hw_alt_next;      /* see EHCI 3.5.2 */
-	u32			hw_token;         /* see EHCI 3.5.3 */       
-#define	QTD_TOGGLE	(1 << 31)	/* data toggle */
-#define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
-#define	QTD_IOC		(1 << 15)	/* interrupt on complete */
-#define	QTD_CERR(tok)	(((tok)>>10) & 0x3)
-#define	QTD_PID(tok)	(((tok)>>8) & 0x3)
-#define	QTD_STS_ACTIVE	(1 << 7)	/* HC may execute this */
-#define	QTD_STS_HALT	(1 << 6)	/* halted on error */
-#define	QTD_STS_DBE	(1 << 5)	/* data buffer error (in HC) */
-#define	QTD_STS_BABBLE	(1 << 4)	/* device was babbling (qtd halted) */
-#define	QTD_STS_XACT	(1 << 3)	/* device gave illegal response */
-#define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
-#define	QTD_STS_STS	(1 << 1)	/* split transaction state */
-#define	QTD_STS_PING	(1 << 0)	/* issue PING? */
-	u32			hw_buf [5];        /* see EHCI 3.5.4 */
-	u32			hw_buf_hi [5];        /* Appendix B */
-
-	/* the rest is HCD-private */
-	dma_addr_t		qtd_dma;		/* qtd address */
-	struct list_head	qtd_list;		/* sw qtd list */
-
-	/* dma same in urb's qtds, except 1st control qtd (setup buffer) */
-	struct urb		*urb;			/* qtd's urb */
-	dma_addr_t		buf_dma;		/* buffer address */
-	size_t			length;			/* length of buffer */
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/* type tag from {qh,itd,sitd,fstn}->hw_next */
-#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
-
-/* values for that type tag */
-#define Q_TYPE_ITD	__constant_cpu_to_le32 (0 << 1)
-#define Q_TYPE_QH	__constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD 	__constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN 	__constant_cpu_to_le32 (3 << 1)
-
-/* next async queue entry, or pointer to interrupt/periodic QH */
-#define	QH_NEXT(dma)	(cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
-
-/* for periodic/async schedules and qtd lists, mark end of list */
-#define	EHCI_LIST_END	__constant_cpu_to_le32(1) /* "null pointer" to hw */
-
-/*
- * Entries in periodic shadow table are pointers to one of four kinds
- * of data structure.  That's dictated by the hardware; a type tag is
- * encoded in the low bits of the hardware's periodic schedule.  Use
- * Q_NEXT_TYPE to get the tag.
- *
- * For entries in the async schedule, the type tag always says "qh".
- */
-union ehci_shadow {
-	struct ehci_qh 		*qh;		/* Q_TYPE_QH */
-	struct ehci_itd		*itd;		/* Q_TYPE_ITD */
-	struct ehci_sitd	*sitd;		/* Q_TYPE_SITD */
-	struct ehci_fstn	*fstn;		/* Q_TYPE_FSTN */
-	void			*ptr;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.6
- * QH: describes control/bulk/interrupt endpoints
- * See Fig 3-7 "Queue Head Structure Layout".
- *
- * These appear in both the async and (for interrupt) periodic schedules.
- */
-
-struct ehci_qh {
-	/* first part defined by EHCI spec */
-	u32			hw_next;	 /* see EHCI 3.6.1 */
-	u32			hw_info1;        /* see EHCI 3.6.2 */
-#define	QH_HEAD		0x00008000
-	u32			hw_info2;        /* see EHCI 3.6.2 */
-	u32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
-	
-	/* qtd overlay (hardware parts of a struct ehci_qtd) */
-	u32			hw_qtd_next;
-	u32			hw_alt_next;
-	u32			hw_token;
-	u32			hw_buf [5];
-	u32			hw_buf_hi [5];
-
-	/* the rest is HCD-private */
-	dma_addr_t		qh_dma;		/* address of qh */
-	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
-	struct list_head	qtd_list;	/* sw qtd list */
-
-	atomic_t		refcount;
-	unsigned short		usecs;		/* intr bandwidth */
-	short			qh_state;
-#define	QH_STATE_LINKED		1		/* HC sees this */
-#define	QH_STATE_UNLINK		2		/* HC may still see this */
-#define	QH_STATE_IDLE		3		/* HC doesn't see this */
-
-#ifdef EHCI_SOFT_RETRIES
-	int			retries;
-#endif
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.3
- * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
- *
- * Schedule records for high speed iso xfers
- */
-struct ehci_itd {
-	/* first part defined by EHCI spec */
-	u32			hw_next;           /* see EHCI 3.3.1 */
-	u32			hw_transaction [8]; /* see EHCI 3.3.2 */
-#define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
-#define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
-#define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
-#define EHCI_ISOC_XACTERR       (1<<28)        /* XactErr - transaction error */
-#define	EHCI_ITD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
-#define	EHCI_ITD_IOC		(1 << 15)	/* interrupt on complete */
-
-	u32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
-	u32			hw_bufp_hi [7];	/* Appendix B */
-
-	/* the rest is HCD-private */
-	dma_addr_t		itd_dma;	/* for this itd */
-	union ehci_shadow	itd_next;	/* ptr to periodic q entry */
-
-	struct urb		*urb;
-	struct list_head	itd_list;	/* list of urb frames' itds */
-	dma_addr_t		buf_dma;	/* frame's buffer address */
-
-	/* for now, only one hw_transaction per itd */
-	u32			transaction;
-	u16			index;		/* in urb->iso_frame_desc */
-	u16			uframe;		/* in periodic schedule */
-	u16			usecs;
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.4 
- * siTD, aka split-transaction isochronous Transfer Descriptor
- *       ... describe low/full speed iso xfers through TT in hubs
- * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
- */
-struct ehci_sitd {
-	/* first part defined by EHCI spec */
-	u32			hw_next;
-/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	u32			hw_fullspeed_ep;  /* see EHCI table 3-9 */
-	u32                     hw_uframe;        /* see EHCI table 3-10 */
-        u32                     hw_tx_results1;   /* see EHCI table 3-11 */
-	u32                     hw_tx_results2;   /* see EHCI table 3-12 */
-	u32                     hw_tx_results3;   /* see EHCI table 3-12 */
-        u32                     hw_backpointer;   /* see EHCI table 3-13 */
-	u32			hw_buf_hi [2];	  /* Appendix B */
-
-	/* the rest is HCD-private */
-	dma_addr_t		sitd_dma;
-	union ehci_shadow	sitd_next;	/* ptr to periodic q entry */
-	struct urb		*urb;
-	dma_addr_t		buf_dma;	/* buffer address */
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.96 Section 3.7
- * Periodic Frame Span Traversal Node (FSTN)
- *
- * Manages split interrupt transactions (using TT) that span frame boundaries
- * into uframes 0/1; see 4.12.2.2.  In those uframes, a "save place" FSTN
- * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
- * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
- */
-struct ehci_fstn {
-	u32			hw_next;	/* any periodic q entry */
-	u32			hw_prev;	/* qh or EHCI_LIST_END */
-
-	/* the rest is HCD-private */
-	dma_addr_t		fstn_dma;
-	union ehci_shadow	fstn_next;	/* ptr to periodic q entry */
-} __attribute__ ((aligned (32)));
-
-#endif /* __LINUX_EHCI_HCD_H */
diff -Nru a/drivers/usb/hcd/ohci-dbg.c b/drivers/usb/hcd/ohci-dbg.c
--- a/drivers/usb/hcd/ohci-dbg.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,246 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- * 
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * This file is licenced under the GPL.
- * $Id: ohci-dbg.c,v 1.2 2002/01/19 00:15:45 dbrownell Exp $
- */
- 
-/*-------------------------------------------------------------------------*/
- 
-#ifdef DEBUG
-
-#define pipestring(pipe) ({ char *temp; \
-	switch (usb_pipetype (pipe)) { \
-	case PIPE_CONTROL:	temp = "CTRL"; break; \
-	case PIPE_BULK:		temp = "BULK"; break; \
-	case PIPE_INTERRUPT:	temp = "INTR"; break; \
-	default: 		temp = "ISOC"; break; \
-	}; temp;})
-
-/* debug| print the main components of an URB     
- * small: 0) header + data packets 1) just header
- */
-static void urb_print (struct urb * urb, char * str, int small)
-{
-	unsigned int pipe= urb->pipe;
-	
-	if (!urb->dev || !urb->dev->bus) {
-		dbg("%s URB: no dev", str);
-		return;
-	}
-	
-#ifndef	OHCI_VERBOSE_DEBUG
-	if (urb->status != 0)
-#endif
-	dbg("%s:[%4x] dev:%d,ep=%d-%c,%s,flags:%4x,len:%d/%d,stat:%d", 
-		    str,
-		    usb_get_current_frame_number (urb->dev), 
-		    usb_pipedevice (pipe),
-		    usb_pipeendpoint (pipe), 
-		    usb_pipeout (pipe)? 'O': 'I',
-		    pipestring (pipe),
-		    urb->transfer_flags, 
-		    urb->actual_length, 
-		    urb->transfer_buffer_length,
-		    urb->status);
-
-#ifdef	OHCI_VERBOSE_DEBUG
-	if (!small) {
-		int i, len;
-
-		if (usb_pipecontrol (pipe)) {
-			printk (KERN_DEBUG __FILE__ ": cmd(8):");
-			for (i = 0; i < 8 ; i++) 
-				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
-			printk ("\n");
-		}
-		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
-			printk (KERN_DEBUG __FILE__ ": data(%d/%d):", 
-				urb->actual_length, 
-				urb->transfer_buffer_length);
-			len = usb_pipeout (pipe)? 
-						urb->transfer_buffer_length: urb->actual_length;
-			for (i = 0; i < 16 && i < len; i++) 
-				printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
-			printk ("%s stat:%d\n", i < len? "...": "", urb->status);
-		}
-	} 
-#endif
-}
-
-static inline struct ed *
-dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma);
-
-#ifdef OHCI_VERBOSE_DEBUG
-/* print non-empty branches of the periodic ed tree */
-void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
-{
-	int i, j;
-	u32 *ed_p;
-	int printed = 0;
-
-	for (i= 0; i < 32; i++) {
-		j = 5;
-		ed_p = &(ohci->hcca->int_table [i]);
-		if (*ed_p == 0)
-			continue;
-		printed = 1;
-		printk (KERN_DEBUG "%s, ohci %s frame %2d:",
-				label, ohci->hcd.bus_name, i);
-		while (*ed_p != 0 && j--) {
-			struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
-			printk (" %p/%08x;", ed, ed->hwINFO);
-			ed_p = &ed->hwNextED;
-		}
-		printk ("\n");
-	}
-	if (!printed)
-		printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
-				label, ohci->hcd.bus_name);
-}
-#endif
-
-static void ohci_dump_intr_mask (char *label, __u32 mask)
-{
-	dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
-		label,
-		mask,
-		(mask & OHCI_INTR_MIE) ? " MIE" : "",
-		(mask & OHCI_INTR_OC) ? " OC" : "",
-		(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
-		(mask & OHCI_INTR_FNO) ? " FNO" : "",
-		(mask & OHCI_INTR_UE) ? " UE" : "",
-		(mask & OHCI_INTR_RD) ? " RD" : "",
-		(mask & OHCI_INTR_SF) ? " SF" : "",
-		(mask & OHCI_INTR_WDH) ? " WDH" : "",
-		(mask & OHCI_INTR_SO) ? " SO" : ""
-		);
-}
-
-static void maybe_print_eds (char *label, __u32 value)
-{
-	if (value)
-		dbg ("%s %08x", label, value);
-}
-
-static char *hcfs2string (int state)
-{
-	switch (state) {
-		case OHCI_USB_RESET:	return "reset";
-		case OHCI_USB_RESUME:	return "resume";
-		case OHCI_USB_OPER:	return "operational";
-		case OHCI_USB_SUSPEND:	return "suspend";
-	}
-	return "?";
-}
-
-// dump control and status registers
-static void ohci_dump_status (struct ohci_hcd *controller)
-{
-	struct ohci_regs	*regs = controller->regs;
-	__u32			temp;
-
-	temp = readl (&regs->revision) & 0xff;
-	dbg ("OHCI %d.%d, %s legacy support registers",
-		0x03 & (temp >> 4), (temp & 0x0f),
-		(temp & 0x10) ? "with" : "NO");
-
-	temp = readl (&regs->control);
-	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
-		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
-		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
-		(temp & OHCI_CTRL_IR) ? " IR" : "",
-		hcfs2string (temp & OHCI_CTRL_HCFS),
-		(temp & OHCI_CTRL_BLE) ? " BLE" : "",
-		(temp & OHCI_CTRL_CLE) ? " CLE" : "",
-		(temp & OHCI_CTRL_IE) ? " IE" : "",
-		(temp & OHCI_CTRL_PLE) ? " PLE" : "",
-		temp & OHCI_CTRL_CBSR
-		);
-
-	temp = readl (&regs->cmdstatus);
-	dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
-		(temp & OHCI_SOC) >> 16,
-		(temp & OHCI_OCR) ? " OCR" : "",
-		(temp & OHCI_BLF) ? " BLF" : "",
-		(temp & OHCI_CLF) ? " CLF" : "",
-		(temp & OHCI_HCR) ? " HCR" : ""
-		);
-
-	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
-	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
-	// intrdisable always same as intrenable
-	// ohci_dump_intr_mask ("intrdisable", readl (&regs->intrdisable));
-
-	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
-
-	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
-	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
-
-	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
-	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
-
-	maybe_print_eds ("donehead", readl (&regs->donehead));
-}
-
-static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
-{
-	__u32			temp, ndp, i;
-
-	temp = roothub_a (controller);
-	ndp = (temp & RH_A_NDP);
-
-	if (verbose) {
-		dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
-			((temp & RH_A_POTPGT) >> 24) & 0xff,
-			(temp & RH_A_NOCP) ? " NOCP" : "",
-			(temp & RH_A_OCPM) ? " OCPM" : "",
-			(temp & RH_A_DT) ? " DT" : "",
-			(temp & RH_A_NPS) ? " NPS" : "",
-			(temp & RH_A_PSM) ? " PSM" : "",
-			ndp
-			);
-		temp = roothub_b (controller);
-		dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
-			temp,
-			(temp & RH_B_PPCM) >> 16,
-			(temp & RH_B_DR)
-			);
-		temp = roothub_status (controller);
-		dbg ("roothub.status: %08x%s%s%s%s%s%s",
-			temp,
-			(temp & RH_HS_CRWE) ? " CRWE" : "",
-			(temp & RH_HS_OCIC) ? " OCIC" : "",
-			(temp & RH_HS_LPSC) ? " LPSC" : "",
-			(temp & RH_HS_DRWE) ? " DRWE" : "",
-			(temp & RH_HS_OCI) ? " OCI" : "",
-			(temp & RH_HS_LPS) ? " LPS" : ""
-			);
-	}
-	
-	for (i = 0; i < ndp; i++) {
-		temp = roothub_portstatus (controller, i);
-		dbg_port (controller, "", i, temp);
-	}
-}
-
-static void ohci_dump (struct ohci_hcd *controller, int verbose)
-{
-	dbg ("OHCI controller %s state", controller->hcd.bus_name);
-
-	// dumps some of the state we know about
-	ohci_dump_status (controller);
-#ifdef OHCI_VERBOSE_DEBUG
-	if (verbose)
-		ohci_dump_periodic (controller, "hcca");
-#endif
-	dbg ("hcca frame #%04x", controller->hcca->frame_no);
-	ohci_dump_roothub (controller, 1);
-}
-
-
-#endif
-
diff -Nru a/drivers/usb/hcd/ohci-hcd.c b/drivers/usb/hcd/ohci-hcd.c
--- a/drivers/usb/hcd/ohci-hcd.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,975 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * [ Initialisation is based on Linus'  ]
- * [ uhci code and gregs ohci fragments ]
- * [ (C) Copyright 1999 Linus Torvalds  ]
- * [ (C) Copyright 1999 Gregory P. Smith]
- * 
- * 
- * History:
- * 
- * 2002/01/18 package as a patch for 2.5.3; this should match the
- *	2.4.17 kernel modulo some bugs being fixed.
- *
- * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes
- *	from post-2.4.5 patches.
- * 2001/09/20 USB_ZERO_PACKET support; hcca_dma portability, OPTi warning
- * 2001/09/07 match PCI PM changes, errnos from Linus' tree
- * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify;
- *	pbook pci quirks gone (please fix pbook pci sw!) (db)
- *
- * 2001/04/08 Identify version on module load (gb)
- * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
- 	pci_map_single (db)
- * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
- * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
- *
- * 2000/09/26 fixed races in removing the private portion of the urb
- * 2000/09/07 disable bulk and control lists when unlinking the last
- *	endpoint descriptor in order to avoid unrecoverable errors on
- *	the Lucent chips. (rwc@sgi)
- * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
- *	urb unlink probs, indentation fixes
- * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
- *	device unplugs.
- * 2000/06/28 use PCI hotplug framework, for better power management
- *	and for Cardbus support (David Brownell)
- * 2000/earlier:  fixes for NEC/Lucent chips; suspend/resume handling
- *	when the controller loses power; handle UE; cleanup; ...
- *
- * v5.2 1999/12/07 URB 3rd preview, 
- * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
- * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume 
- * 	i386: HUB, Keyboard, Mouse, Printer 
- *
- * v4.3 1999/10/27 multiple HCs, bulk_request
- * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
- * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
- * v4.0 1999/08/18 
- * v3.0 1999/06/25 
- * v2.1 1999/05/09  code clean up
- * v2.0 1999/05/04 
- * v1.0 1999/04/27 initial release
- *
- * This file is licenced under the GPL.
- * $Id: ohci-hcd.c,v 1.7 2002/01/19 00:20:56 dbrownell Exp $
- */
- 
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>  /* for in_interrupt () */
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
-#include <linux/usb.h>
-#include "../hcd.h"
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-
-#ifdef CONFIG_PMAC_PBOOK
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
-#ifndef CONFIG_PM
-#	define CONFIG_PM
-#endif
-#endif
-
-/*
- * TO DO:
- *
- *	- "disabled" should be the hcd state
- *	- bandwidth alloc to generic code
- *	- lots more testing!!
- */
-
-#define DRIVER_VERSION "$Revision: 1.7 $"
-#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
-#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
-
-/*-------------------------------------------------------------------------*/
-
-#define OHCI_USE_NPS		// force NoPowerSwitching mode
-// #define OHCI_VERBOSE_DEBUG	/* not always helpful */
-
-/* For initializing controller (mask in an HCFS mode too) */
-#define	OHCI_CONTROL_INIT \
-	 (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
-
-#define OHCI_UNLINK_TIMEOUT	 (HZ / 10)
-
-/*-------------------------------------------------------------------------*/
-
-#include "ohci.h"
-
-#include "ohci-hub.c"
-#include "ohci-dbg.c"
-#include "ohci-mem.c"
-#include "ohci-q.c"
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * queue up an urb for anything except the root hub
- */
-static int ohci_urb_enqueue (
-	struct usb_hcd	*hcd,
-	struct urb	*urb,
-	int		mem_flags
-) {
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	struct ed	*ed;
-	urb_priv_t	*urb_priv;
-	unsigned int	pipe = urb->pipe;
-	int		i, size = 0;
-	unsigned long	flags;
-	int		bustime = 0;
-	
-#ifdef OHCI_VERBOSE_DEBUG
-	urb_print (urb, "SUB", usb_pipein (pipe));
-#endif
-	
-	/* every endpoint has a ed, locate and fill it */
-	if (! (ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
-		usb_dec_dev_use (urb->dev);	
-		return -ENOMEM;
-	}
-
-	/* for the private part of the URB we need the number of TDs (size) */
-	switch (usb_pipetype (pipe)) {
-		case PIPE_CONTROL:
-			/* 1 TD for setup, 1 for ACK, plus ... */
-			size = 2;
-			/* FALLTHROUGH */
-		case PIPE_BULK:
-			/* one TD for every 4096 Bytes (can be upto 8K) */
-			size += urb->transfer_buffer_length / 4096;
-			/* ... and for any remaining bytes ... */
-			if ((urb->transfer_buffer_length % 4096) != 0)
-				size++;
-			/* ... and maybe a zero length packet to wrap it up */
-			if (size == 0)
-				size++;
-			else if ((urb->transfer_flags & USB_ZERO_PACKET) != 0
-				&& (urb->transfer_buffer_length
-					% usb_maxpacket (urb->dev, pipe,
-						usb_pipeout (pipe))) != 0)
-				size++;
-			break;
-		case PIPE_ISOCHRONOUS: /* number of packets from URB */
-			size = urb->number_of_packets;
-			if (size <= 0) {
-				usb_dec_dev_use (urb->dev);	
-				return -EINVAL;
-			}
-			for (i = 0; i < urb->number_of_packets; i++) {
-  				urb->iso_frame_desc [i].actual_length = 0;
-  				urb->iso_frame_desc [i].status = -EXDEV;
-  			}
-			break;
-		case PIPE_INTERRUPT: /* one TD */
-			size = 1;
-			break;
-	}
-
-	/* allocate the private part of the URB */
-	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *),
-			mem_flags);
-	if (!urb_priv) {
-		usb_dec_dev_use (urb->dev);	
-		return -ENOMEM;
-	}
-	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
-	
-	/* fill the private part of the URB */
-	urb_priv->length = size;
-	urb_priv->ed = ed;	
-
-	/* allocate the TDs (updating hash chains) */
-	spin_lock_irqsave (&ohci->lock, flags);
-	for (i = 0; i < size; i++) { 
-		urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC);
-		if (!urb_priv->td [i]) {
-			urb_priv->length = i;
-			urb_free_priv (ohci, urb_priv);
-			spin_unlock_irqrestore (&ohci->lock, flags);
-			usb_dec_dev_use (urb->dev);	
-			return -ENOMEM;
-		}
-	}	
-
-// FIXME:  much of this switch should be generic, move to hcd code ...
-
-	/* allocate and claim bandwidth if needed; ISO
-	 * needs start frame index if it was't provided.
-	 */
-	switch (usb_pipetype (pipe)) {
-		case PIPE_ISOCHRONOUS:
-			if (urb->transfer_flags & USB_ISO_ASAP) { 
-				urb->start_frame = ( (ed->state == ED_OPER)
-					? (ed->last_iso + 1)
-					: (le16_to_cpu (ohci->hcca->frame_no)
-						+ 10)) & 0xffff;
-			}	
-			/* FALLTHROUGH */
-		case PIPE_INTERRUPT:
-			if (urb->bandwidth == 0) {
-				bustime = usb_check_bandwidth (urb->dev, urb);
-			}
-			if (bustime < 0) {
-				urb_free_priv (ohci, urb_priv);
-				spin_unlock_irqrestore (&ohci->lock, flags);
-				usb_dec_dev_use (urb->dev);	
-				return bustime;
-			}
-			usb_claim_bandwidth (urb->dev, urb,
-				bustime, usb_pipeisoc (urb->pipe));
-	}
-
-	urb->hcpriv = urb_priv;
-
-	/* link the ed into a chain if is not already */
-	if (ed->state != ED_OPER)
-		ep_link (ohci, ed);
-
-	/* fill the TDs and link them to the ed; and
-	 * enable that part of the schedule, if needed
-	 */
-	td_submit_urb (urb);
-
-	spin_unlock_irqrestore (&ohci->lock, flags);
-
-	return 0;	
-}
-
-/*
- * decouple the URB from the HC queues (TDs, urb_priv); it's
- * already marked for deletion.  reporting is always done
- * asynchronously, and we might be dealing with an urb that's
- * almost completed anyway...
- */
-static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	unsigned long		flags;
-	
-#ifdef DEBUG
-	urb_print (urb, "UNLINK", 1);
-#endif		  
-
-	if (!ohci->disabled) {
-		urb_priv_t  *urb_priv;
-
-		/* flag the urb's data for deletion in some upcoming
-		 * SF interrupt's delete list processing
-		 */
-		spin_lock_irqsave (&ohci->lock, flags);
-		urb_priv = urb->hcpriv;
-
-		if (!urb_priv || (urb_priv->state == URB_DEL)) {
-			spin_unlock_irqrestore (&ohci->lock, flags);
-			return 0;
-		}
-			
-		urb_priv->state = URB_DEL; 
-		ed_unlink (urb->dev, urb_priv->ed);
-		spin_unlock_irqrestore (&ohci->lock, flags);
-	} else {
-		/*
-		 * with HC dead, we won't respect hc queue pointers
-		 * any more ... just clean up every urb's memory.
-		 */
-		finish_urb (ohci, urb);
-	}	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	struct hcd_dev		*dev = (struct hcd_dev *) udev->hcpriv;
-	int			i;
-	unsigned long		flags;
-
-	/* free any eds, and dummy tds, still hanging around */
-	spin_lock_irqsave (&ohci->lock, flags);
-	for (i = 0; i < 32; i++) {
-		struct ed	*ed = dev->ep [i];
-		struct td	*tdTailP;
-
-		if (!ed)
-			continue;
-
-		ed->state &= ~ED_URB_DEL;
-		if (ohci->disabled && ed->state == ED_OPER)
-			ed->state = ED_UNLINK;
-		switch (ed->state) {
-		case ED_NEW:
-			break;
-		case ED_UNLINK:
-			tdTailP = dma_to_td (ohci,
-				le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
-			td_free (ohci, tdTailP); /* free dummy td */
-			hash_free_ed (ohci, ed);
-			break;
-
-		case ED_OPER:
-		default:
-			err ("illegal ED %d state in free_config, %d",
-				i, ed->state);
-#ifdef DEBUG
-			BUG ();
-#endif
-		}
-		ed_free (ohci, ed);
-	}
-	spin_unlock_irqrestore (&ohci->lock, flags);
-}
-
-static int ohci_get_frame (struct usb_hcd *hcd)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-
-#ifdef	OHCI_VERBOSE_DEBUG
-	dbg ("%s: ohci_get_frame", hcd->bus_name);
-#endif
-	return le16_to_cpu (ohci->hcca->frame_no);
-}
-
-/*-------------------------------------------------------------------------*
- * HC functions
- *-------------------------------------------------------------------------*/
-
-/* reset the HC and BUS */
-
-static int hc_reset (struct ohci_hcd *ohci)
-{
-	int timeout = 30;
-	int smm_timeout = 50; /* 0,5 sec */
-	 	
-	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
-		writel (OHCI_INTR_OC, &ohci->regs->intrenable);
-		writel (OHCI_OCR, &ohci->regs->cmdstatus);
-		dbg ("USB HC TakeOver from SMM");
-		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
-			wait_ms (10);
-			if (--smm_timeout == 0) {
-				err ("USB HC TakeOver failed!");
-				return -1;
-			}
-		}
-	}	
-		
-	/* Disable HC interrupts */
-	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
-
-	dbg ("USB HC reset_hc %s: ctrl = 0x%x ;",
-		ohci->hcd.bus_name,
-		readl (&ohci->regs->control));
-
-  	/* Reset USB (needed by some controllers) */
-	writel (0, &ohci->regs->control);
-      	
-	/* HC Reset requires max 10 ms delay */
-	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
-	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
-		if (--timeout == 0) {
-			err ("USB HC reset timed out!");
-			return -1;
-		}	
-		udelay (1);
-	}	 
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Start an OHCI controller, set the BUS operational
- * enable interrupts 
- * connect the virtual root hub
- */
-static int hc_start (struct ohci_hcd *ohci)
-{
-  	__u32			mask;
-  	unsigned int		fminterval;
-  	struct usb_device	*udev;
-	
-	spin_lock_init (&ohci->lock);
-	ohci->disabled = 1;
-	ohci->sleeping = 0;
-
-	/* Tell the controller where the control and bulk lists are
-	 * The lists are empty now. */
-	 
-	writel (0, &ohci->regs->ed_controlhead);
-	writel (0, &ohci->regs->ed_bulkhead);
-	
-	/* a reset clears this */
-	writel ((u32) ohci->hcca_dma, &ohci->regs->hcca);
-   
-  	fminterval = 0x2edf;
-	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
-	fminterval |= ((((fminterval - 210) * 6) / 7) << 16); 
-	writel (fminterval, &ohci->regs->fminterval);	
-	writel (0x628, &ohci->regs->lsthresh);
-
- 	/* start controller operations */
- 	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-	ohci->disabled = 0;
- 	writel (ohci->hc_control, &ohci->regs->control);
- 
-	/* Choose the interrupts we care about now, others later on demand */
-	mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
-	writel (mask, &ohci->regs->intrstatus);
-	writel (mask, &ohci->regs->intrenable);
-
-#ifdef	OHCI_USE_NPS
-	/* required for AMD-756 and some Mac platforms */
-	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
-		&ohci->regs->roothub.a);
-	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
-#endif	/* OHCI_USE_NPS */
-
-	// POTPGT delay is bits 24-31, in 2 ms units.
-	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
- 
-	/* connect the virtual root hub */
-	ohci->hcd.bus->root_hub = udev = usb_alloc_dev (NULL, ohci->hcd.bus);
-	ohci->hcd.state = USB_STATE_READY;
-	if (!udev) {
-	    ohci->disabled = 1;
-// FIXME cleanup
-	    return -ENOMEM;
-	}
-
-	usb_connect (udev);
-	udev->speed = USB_SPEED_FULL;
-	if (usb_register_root_hub (udev, &ohci->hcd.pdev->dev) != 0) {
-		usb_free_dev (udev); 
-		ohci->disabled = 1;
-// FIXME cleanup
-		return -ENODEV;
-	}
-	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* an interrupt happens */
-
-static void ohci_irq (struct usb_hcd *hcd)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	struct ohci_regs	*regs = ohci->regs;
- 	int			ints; 
-
-	if ((ohci->hcca->done_head != 0)
-			&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
-		ints =  OHCI_INTR_WDH;
-	} else if ((ints = (readl (&regs->intrstatus)
-			& readl (&regs->intrenable))) == 0) {
-		return;
-	} 
-
-	// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
-
-	if (ints & OHCI_INTR_UE) {
-		ohci->disabled++;
-		err ("OHCI Unrecoverable Error, %s disabled", hcd->bus_name);
-		// e.g. due to PCI Master/Target Abort
-
-#ifdef	DEBUG
-		ohci_dump (ohci, 1);
-#endif
-		hc_reset (ohci);
-	}
-  
-	if (ints & OHCI_INTR_WDH) {
-		writel (OHCI_INTR_WDH, &regs->intrdisable);	
-		dl_done_list (ohci, dl_reverse_done_list (ohci));
-		writel (OHCI_INTR_WDH, &regs->intrenable); 
-	}
-  
-	if (ints & OHCI_INTR_SO) {
-		dbg ("USB Schedule overrun");
-		writel (OHCI_INTR_SO, &regs->intrenable); 	 
-	}
-
-	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...
-	if (ints & OHCI_INTR_SF) { 
-		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
-		writel (OHCI_INTR_SF, &regs->intrdisable);	
-		if (ohci->ed_rm_list [!frame] != NULL) {
-			dl_del_list (ohci, !frame);
-		}
-		if (ohci->ed_rm_list [frame] != NULL)
-			writel (OHCI_INTR_SF, &regs->intrenable);	
-	}
-
-	writel (ints, &regs->intrstatus);
-	writel (OHCI_INTR_MIE, &regs->intrenable);	
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void ohci_stop (struct usb_hcd *hcd)
-{	
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-
-	dbg ("%s: stop %s controller%s",
-		hcd->bus_name,
-		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-		ohci->disabled ? " (disabled)" : ""
-		);
-#ifdef	DEBUG
-	ohci_dump (ohci, 1);
-#endif
-
-	if (!ohci->disabled)
-		hc_reset (ohci);
-	
-	ohci_mem_cleanup (ohci);
-
-#ifdef CONFIG_PCI
-	pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca,
-		ohci->hcca, ohci->hcca_dma);
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_start (struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ret;
-
-#ifdef CONFIG_PCI
-	if (hcd->pdev) {
-		ohci->hcca = pci_alloc_consistent (hcd->pdev,
-				sizeof *ohci->hcca, &ohci->hcca_dma);
-		if (!ohci->hcca)
-			return -ENOMEM;
-
-		/* AMD 756, for most chips (early revs), corrupts register
-		 * values on read ... so enable the vendor workaround.
-		 */
-		if (hcd->pdev->vendor == 0x1022
-				&& hcd->pdev->device == 0x740c) {
-			ohci->flags = OHCI_QUIRK_AMD756;
-			info ("%s: AMD756 erratum 4 workaround",
-				hcd->bus_name);
-		}
-
-		/* Apple's OHCI driver has a lot of bizarre workarounds
-		 * for this chip.  Evidently control and bulk lists
-		 * can get confused.  (B&W G3 models, and ...)
-		 */
-		else if (hcd->pdev->vendor == 0x1045
-				&& hcd->pdev->device == 0xc861) {
-			info ("%s: WARNING: OPTi workarounds unavailable",
-				hcd->bus_name);
-		}
-	}
-#else
-#	error "where's hcca coming from?"
-#endif /* CONFIG_PCI */
-
-        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
-	if ((ret = ohci_mem_init (ohci)) < 0) {
-		ohci_stop (hcd);
-		return ret;
-	}
-	ohci->regs = hcd->regs;
-
-	if (hc_reset (ohci) < 0) {
-		ohci_stop (hcd);
-		return -ENODEV;
-	}
-
-	if (hc_start (ohci) < 0) {
-		err ("can't start %s", ohci->hcd.bus_name);
-		ohci_stop (hcd);
-		return -EBUSY;
-	}
-
-#ifdef	DEBUG
-	ohci_dump (ohci, 1);
-#endif
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-
-static int ohci_suspend (struct usb_hcd *hcd, u32 state)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	unsigned long		flags;
-	u16			cmd;
-
-	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-		dbg ("can't suspend %s (state is %s)", hcd->bus_name,
-			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-		return -EIO;
-	}
-
-	/* act as if usb suspend can always be used */
-	dbg ("%s: suspend to %d", hcd->bus_name, state);
-	ohci->sleeping = 1;
-
-	/* First stop processing */
-  	spin_lock_irqsave (&ohci->lock, flags);
-	ohci->hc_control &=
-		~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
-	writel (ohci->hc_control, &ohci->regs->control);
-	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-	(void) readl (&ohci->regs->intrstatus);
-  	spin_unlock_irqrestore (&ohci->lock, flags);
-
-	/* Wait a frame or two */
-	mdelay (1);
-	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
-		mdelay (1);
-		
- #ifdef CONFIG_PMAC_PBOOK
-	if (_machine == _MACH_Pmac)
-		disable_irq (hcd->pdev->irq);
- 	/* else, 2.4 assumes shared irqs -- don't disable */
- #endif
-
-	/* Enable remote wakeup */
-	writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
-		&ohci->regs->intrenable);
-
-	/* Suspend chip and let things settle down a bit */
- 	ohci->hc_control = OHCI_USB_SUSPEND;
- 	writel (ohci->hc_control, &ohci->regs->control);
-	(void) readl (&ohci->regs->control);
-	mdelay (500); /* No schedule here ! */
-
-	switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
-		case OHCI_USB_RESET:
-			dbg ("%s suspend->reset ?", hcd->bus_name);
-			break;
-		case OHCI_USB_RESUME:
-			dbg ("%s suspend->resume ?", hcd->bus_name);
-			break;
-		case OHCI_USB_OPER:
-			dbg ("%s suspend->operational ?", hcd->bus_name);
-			break;
-		case OHCI_USB_SUSPEND:
-			dbg ("%s suspended", hcd->bus_name);
-			break;
-	}
-
-	/* In some rare situations, Apple's OHCI have happily trashed
-	 * memory during sleep. We disable its bus master bit during
-	 * suspend
-	 */
-	pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
-	cmd &= ~PCI_COMMAND_MASTER;
-	pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
-#ifdef CONFIG_PMAC_PBOOK
-	{
-	   	struct device_node	*of_node;
- 
-		/* Disable USB PAD & cell clock */
-		of_node = pci_device_to_OF_node (hcd->pdev);
-		if (of_node)
-			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
-	}
-#endif
-	return 0;
-}
-
-
-// FIXME:  this restart logic should be generic,
-// and handle full hcd state cleanup
-
-/* controller died; cleanup debris, then restart */
-/* must not be called from interrupt context */
-
-static int hc_restart (struct ohci_hcd *ohci)
-{
-	int temp;
-	int i;
-
-	ohci->disabled = 1;
-	ohci->sleeping = 0;
-	if (ohci->hcd.bus->root_hub)
-		usb_disconnect (&ohci->hcd.bus->root_hub);
-	
-	/* empty the interrupt branches */
-	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0;
-	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
-	
-	/* no EDs to remove */
-	ohci->ed_rm_list [0] = NULL;
-	ohci->ed_rm_list [1] = NULL;
-
-	/* empty control and bulk lists */	 
-	ohci->ed_isotail     = NULL;
-	ohci->ed_controltail = NULL;
-	ohci->ed_bulktail    = NULL;
-
-	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-		err ("can't restart %s, %d", ohci->hcd.bus_name, temp);
-		return temp;
-	} else
-		dbg ("restart %s completed", ohci->hcd.bus_name);
-	return 0;
-}
-
-static int ohci_resume (struct usb_hcd *hcd)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	int			temp;
-	int			retval = 0;
-	unsigned long		flags;
-
-#ifdef CONFIG_PMAC_PBOOK
-	{
-		struct device_node *of_node;
-
-		/* Re-enable USB PAD & cell clock */
-		of_node = pci_device_to_OF_node (hcd->pdev);
-		if (of_node)
-			pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
-	}
-#endif
-	/* did we suspend, or were we powered off? */
-	ohci->hc_control = readl (&ohci->regs->control);
-	temp = ohci->hc_control & OHCI_CTRL_HCFS;
-
-#ifdef DEBUG
-	/* the registers may look crazy here */
-	ohci_dump_status (ohci);
-#endif
-
-	/* Re-enable bus mastering */
-	pci_set_master (ohci->hcd.pdev);
-	
-	switch (temp) {
-
-	case OHCI_USB_RESET:	// lost power
-		info ("USB restart: %s", hcd->bus_name);
-		retval = hc_restart (ohci);
-		break;
-
-	case OHCI_USB_SUSPEND:	// host wakeup
-	case OHCI_USB_RESUME:	// remote wakeup
-		info ("USB continue: %s from %s wakeup", hcd->bus_name,
-			 (temp == OHCI_USB_SUSPEND)
-				? "host" : "remote");
-		ohci->hc_control = OHCI_USB_RESUME;
-		writel (ohci->hc_control, &ohci->regs->control);
-		(void) readl (&ohci->regs->control);
-		mdelay (20); /* no schedule here ! */
-		/* Some controllers (lucent) need a longer delay here */
-		mdelay (15);
-
-		temp = readl (&ohci->regs->control);
-		temp = ohci->hc_control & OHCI_CTRL_HCFS;
-		if (temp != OHCI_USB_RESUME) {
-			err ("controller %s won't resume", hcd->bus_name);
-			ohci->disabled = 1;
-			retval = -EIO;
-			break;
-		}
-
-		/* Some chips likes being resumed first */
-		writel (OHCI_USB_OPER, &ohci->regs->control);
-		(void) readl (&ohci->regs->control);
-		mdelay (3);
-
-		/* Then re-enable operations */
-		spin_lock_irqsave (&ohci->lock, flags);
-		ohci->disabled = 0;
-		ohci->sleeping = 0;
-		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-		if (!ohci->ed_rm_list [0] && !ohci->ed_rm_list [1]) {
-			if (ohci->ed_controltail)
-				ohci->hc_control |= OHCI_CTRL_CLE;
-			if (ohci->ed_bulktail)
-				ohci->hc_control |= OHCI_CTRL_BLE;
-		}
-		hcd->state = USB_STATE_READY;
-		writel (ohci->hc_control, &ohci->regs->control);
-
-		/* trigger a start-frame interrupt (why?) */
-		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-
-		/* Check for a pending done list */
-		writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);	
-		(void) readl (&ohci->regs->intrdisable);
-		spin_unlock_irqrestore (&ohci->lock, flags);
-
- #ifdef CONFIG_PMAC_PBOOK
-		if (_machine == _MACH_Pmac)
-			enable_irq (hcd->pdev->irq);
- #endif
-		if (ohci->hcca->done_head)
-			dl_done_list (ohci, dl_reverse_done_list (ohci));
-		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
-
-		/* assume there are TDs on the bulk and control lists */
-		writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
-
-// ohci_dump_status (ohci);
-dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);
-		break;
-
-	default:
-		warn ("odd PCI resume for %s", hcd->bus_name);
-	}
-	return retval;
-}
-
-#endif	/* CONFIG_PM */
-
-
-/*-------------------------------------------------------------------------*/
-
-static const char	hcd_name [] = "ohci-hcd";
-
-static const struct hc_driver ohci_driver = {
-	description:		hcd_name,
-
-	/*
-	 * generic hardware linkage
-	 */
-	irq:			ohci_irq,
-	flags:			HCD_MEMORY | HCD_USB11,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	start:			ohci_start,
-#ifdef	CONFIG_PM
-	suspend:		ohci_suspend,
-	resume:			ohci_resume,
-#endif
-	stop:			ohci_stop,
-
-	/*
-	 * memory lifecycle (except per-request)
-	 */
-	hcd_alloc:		ohci_hcd_alloc,
-	hcd_free:		ohci_hcd_free,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	urb_enqueue:		ohci_urb_enqueue,
-	urb_dequeue:		ohci_urb_dequeue,
-	free_config:		ohci_free_config,
-
-	/*
-	 * scheduling support
-	 */
-	get_frame_number:	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	hub_status_data:	ohci_hub_status_data,
-	hub_control:		ohci_hub_control,
-};
-
-#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
-
-EXPORT_NO_SYMBOLS;
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_INFO);
-MODULE_LICENSE ("GPL");
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PCI
-
-/* There do exist non-PCI implementations of OHCI ...
- * Examples include the SA-1111 (ARM) and some MIPS
- * and related hardware.
- */
-
-static const struct pci_device_id __devinitdata pci_ids [] = { {
-
-	/* handle any USB OHCI controller */
-	class:		(PCI_CLASS_SERIAL_USB << 8) | 0x10,
-	class_mask:	~0,
-	driver_data:	(unsigned long) &ohci_driver,
-
-	/* no matter who makes it */
-	vendor:		PCI_ANY_ID,
-	device:		PCI_ANY_ID,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-	}, { /* end: all zeroes */ }
-};
-MODULE_DEVICE_TABLE (pci, pci_ids);
-
-/* pci driver glue; this is a "new style" PCI driver module */
-static struct pci_driver ohci_pci_driver = {
-	name:		(char *) hcd_name,
-	id_table:	pci_ids,
-
-	probe:		usb_hcd_pci_probe,
-	remove:		usb_hcd_pci_remove,
-
-#ifdef	CONFIG_PM
-	suspend:	usb_hcd_pci_suspend,
-	resume:		usb_hcd_pci_resume,
-#endif
-};
-
- 
-static int __init ohci_hcd_init (void) 
-{
-	dbg (DRIVER_INFO);
-	dbg ("block sizes: ed %d td %d",
-		sizeof (struct ed), sizeof (struct td));
-	return pci_module_init (&ohci_pci_driver);
-}
-module_init (ohci_hcd_init);
-
-/*-------------------------------------------------------------------------*/
-
-static void __exit ohci_hcd_cleanup (void) 
-{	
-	pci_unregister_driver (&ohci_pci_driver);
-}
-module_exit (ohci_hcd_cleanup);
-
-#endif /* CONFIG_PCI */
-
diff -Nru a/drivers/usb/hcd/ohci-hub.c b/drivers/usb/hcd/ohci-hub.c
--- a/drivers/usb/hcd/ohci-hub.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,267 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- * 
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * This file is licenced under GPL
- * $Id: ohci-hub.c,v 1.2 2002/01/19 00:21:49 dbrownell Exp $
- */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * OHCI Root Hub ... the nonsharable stuff
- *
- * Registers don't need cpu_to_le32, that happens transparently
- */
-
-/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
- * The erratum (#4) description is incorrect.  AMD's workaround waits
- * till some bits (mostly reserved) are clear; ok for all revs.
- */
-#define read_roothub(hc, register, mask) ({ \
-	u32 temp = readl (&hc->regs->roothub.register); \
-	if (hc->flags & OHCI_QUIRK_AMD756) \
-		while (temp & mask) \
-			temp = readl (&hc->regs->roothub.register); \
-	temp; })
-
-static u32 roothub_a (struct ohci_hcd *hc)
-	{ return read_roothub (hc, a, 0xfc0fe000); }
-static inline u32 roothub_b (struct ohci_hcd *hc)
-	{ return readl (&hc->regs->roothub.b); }
-static inline u32 roothub_status (struct ohci_hcd *hc)
-	{ return readl (&hc->regs->roothub.status); }
-static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
-	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
-
-/*-------------------------------------------------------------------------*/
-
-#define dbg_port(hc,label,num,value) \
-	dbg ("%s: %s roothub.portstatus [%d] " \
-		"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", \
-		hc->hcd.bus_name, label, num, temp, \
-		(temp & RH_PS_PRSC) ? " PRSC" : "", \
-		(temp & RH_PS_OCIC) ? " OCIC" : "", \
-		(temp & RH_PS_PSSC) ? " PSSC" : "", \
-		(temp & RH_PS_PESC) ? " PESC" : "", \
-		(temp & RH_PS_CSC) ? " CSC" : "", \
- 		\
-		(temp & RH_PS_LSDA) ? " LSDA" : "", \
-		(temp & RH_PS_PPS) ? " PPS" : "", \
-		(temp & RH_PS_PRS) ? " PRS" : "", \
-		(temp & RH_PS_POCI) ? " POCI" : "", \
-		(temp & RH_PS_PSS) ? " PSS" : "", \
- 		\
-		(temp & RH_PS_PES) ? " PES" : "", \
-		(temp & RH_PS_CCS) ? " CCS" : "" \
-		);
-
-
-/*-------------------------------------------------------------------------*/
-
-/* build "status change" packet (one or two bytes) from HC registers */
-
-static int
-ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports, i, changed = 0, length = 1;
-
-	ports = roothub_a (ohci) & RH_A_NDP; 
-	if (ports > MAX_ROOT_PORTS) {
-		err ("%s: bogus NDP=%d", hcd->bus_name, ports);
-		err ("rereads as NDP=%d",
-			readl (&ohci->regs->roothub.a) & RH_A_NDP);
-		/* retry later; "should not happen" */
-		return 0;
-	}
-
-	/* init status */
-	if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
-		buf [0] = changed = 1;
-	else
-		buf [0] = 0;
-	if (ports > 7) {
-		buf [1] = 0;
-		length++;
-	}
-
-	/* look at each port */
-	for (i = 0; i < ports; i++) {
-		u32	status = roothub_portstatus (ohci, i);
-
-		status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
-				| RH_PS_OCIC | RH_PS_PRSC;
-		if (status) {
-			changed = 1;
-			set_bit (i + 1, buf);
-		}
-	}
-	return changed ? length : 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-ohci_hub_descriptor (
-	struct ohci_hcd			*ohci,
-	struct usb_hub_descriptor	*desc
-) {
-	u32		rh = roothub_a (ohci);
-	int		ports = rh & RH_A_NDP; 
-	u16		temp;
-
-	desc->bDescriptorType = 0x29;
-	desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
-	desc->bHubContrCurrent = 0;
-
-	desc->bNbrPorts = ports;
-	temp = 1 + (ports / 8);
-	desc->bDescLength = 7 + 2 * temp;
-
-	temp = 0;
-	if (rh & RH_A_PSM) 		/* per-port power switching? */
-	    temp |= 0x0001;
-	if (rh & RH_A_NOCP)		/* no overcurrent reporting? */
-	    temp |= 0x0010;
-	else if (rh & RH_A_OCPM)	/* per-port overcurrent reporting? */
-	    temp |= 0x0008;
-	desc->wHubCharacteristics = cpu_to_le16 (temp);
-
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	rh = roothub_b (ohci);
-	desc->bitmap [0] = rh & RH_B_DR;
-	if (ports > 7) {
-		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
-		desc->bitmap [2] = desc->bitmap [3] = 0xff;
-	} else
-		desc->bitmap [1] = 0xff;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hub_control (
-	struct usb_hcd	*hcd,
-	u16		typeReq,
-	u16		wValue,
-	u16		wIndex,
-	char		*buf,
-	u16		wLength
-) {
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ports;
-	u32		temp;
-	int		retval = 0;
-
-	// if (port request)
-		ports = roothub_a (ohci) & RH_A_NDP; 
-	switch (typeReq) {
-	case ClearHubFeature:
-		switch (wValue) {
-		case C_HUB_OVER_CURRENT:
-			writel (RH_HS_OCIC, &ohci->regs->roothub.status);
-		case C_HUB_LOCAL_POWER:
-			break;
-		default:
-			goto error;
-		}
-		break;
-	case ClearPortFeature:
-		if (!wIndex || wIndex > ports)
-			goto error;
-		wIndex--;
-
-		switch (wValue) {
-		case USB_PORT_FEAT_ENABLE:
-			temp = RH_PS_CCS;
-			break;
-		case USB_PORT_FEAT_C_ENABLE:
-			temp = RH_PS_PESC;
-			break;
-		case USB_PORT_FEAT_SUSPEND:
-			temp = RH_PS_POCI;
-			break;
-		case USB_PORT_FEAT_C_SUSPEND:
-			temp = RH_PS_PSSC;
-			break;
-		case USB_PORT_FEAT_POWER:
-			temp = RH_PS_LSDA;
-			break;
-		case USB_PORT_FEAT_C_CONNECTION:
-			temp = RH_PS_CSC;
-			break;
-		case USB_PORT_FEAT_C_OVER_CURRENT:
-			temp = RH_PS_OCIC;
-			break;
-		case USB_PORT_FEAT_C_RESET:
-			temp = RH_PS_PRSC;
-			break;
-		default:
-			goto error;
-		}
-		writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
-		// readl (&ohci->regs->roothub.portstatus [wIndex]);
-		break;
-	case GetHubDescriptor:
-		ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
-		break;
-	case GetHubStatus:
-		temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
-		*(u32 *) buf = cpu_to_le32 (temp);
-		break;
-	case GetPortStatus:
-		if (!wIndex || wIndex > ports)
-			goto error;
-		wIndex--;
-		temp = roothub_portstatus (ohci, wIndex);
-		*(u32 *) buf = cpu_to_le32 (temp);
-
-#ifndef	OHCI_VERBOSE_DEBUG
-	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
-#endif
-		dbg_port (ohci, "GetStatus", wIndex + 1, temp);
-		break;
-	case SetHubFeature:
-		switch (wValue) {
-		case C_HUB_OVER_CURRENT:
-			// FIXME:  this can be cleared, yes?
-		case C_HUB_LOCAL_POWER:
-			break;
-		default:
-			goto error;
-		}
-		break;
-	case SetPortFeature:
-		if (!wIndex || wIndex > ports)
-			goto error;
-		wIndex--;
-		switch (wValue) {
-		case USB_PORT_FEAT_SUSPEND:
-			writel (RH_PS_PSS,
-				&ohci->regs->roothub.portstatus [wIndex]);
-			break;
-		case USB_PORT_FEAT_POWER:
-			writel (RH_PS_PPS,
-				&ohci->regs->roothub.portstatus [wIndex]);
-			break;
-		case USB_PORT_FEAT_RESET:
-			temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
-			if (temp & RH_PS_CCS)
-				writel (RH_PS_PRS,
-				    &ohci->regs->roothub.portstatus [wIndex]);
-			break;
-		default:
-			goto error;
-		}
-		break;
-
-	default:
-error:
-		/* "protocol stall" on error */
-		retval = -EPIPE;
-	}
-	return retval;
-}
-
diff -Nru a/drivers/usb/hcd/ohci-mem.c b/drivers/usb/hcd/ohci-mem.c
--- a/drivers/usb/hcd/ohci-mem.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,252 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- * 
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * This file is licenced under the GPL.
- * $Id: ohci-mem.c,v 1.2 2002/01/19 00:22:13 dbrownell Exp $
- */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * There's basically three types of memory:
- *	- data used only by the HCD ... kmalloc is fine
- *	- async and periodic schedules, shared by HC and HCD ... these
- *	  need to use pci_pool or pci_alloc_consistent
- *	- driver buffers, read/written by HC ... single shot DMA mapped 
- *
- * There's also PCI "register" data, which is memory mapped.
- * No memory seen by this driver is pagable.
- */
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_hcd *ohci_hcd_alloc (void)
-{
-	struct ohci_hcd *ohci;
-
-	ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL);
-	if (ohci != 0) {
-		memset (ohci, 0, sizeof (struct ohci_hcd));
-		return &ohci->hcd;
-	}
-	return 0;
-}
-
-static void ohci_hcd_free (struct usb_hcd *hcd)
-{
-	kfree (hcd_to_ohci (hcd));
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_DEBUG_SLAB
-#	define OHCI_MEM_FLAGS	SLAB_POISON
-#else
-#	define OHCI_MEM_FLAGS	0
-#endif
- 
-#ifndef CONFIG_PCI
-#	error "usb-ohci currently requires PCI-based controllers"
-	/* to support non-PCI OHCIs, you need custom bus/mem/... glue */
-#endif
-
-
-/* Recover a TD/ED using its collision chain */
-static inline void *
-dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
-{
-	struct hash_t * scan = entry->head;
-	while (scan && scan->dma != dma)
-		scan = scan->next;
-	return scan->virt;
-}
-
-static struct ed *
-dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma)
-{
-	return (struct ed *) dma_to_ed_td(&(hc->ed_hash [ED_HASH_FUNC(ed_dma)]),
-				      ed_dma);
-}
-
-static struct td *
-dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
-{
-	td_dma &= TD_MASK;
-	return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]),
-				      td_dma);
-}
-
-// FIXME:  when updating the hashtables this way, mem_flags is unusable...
-
-/* Add a hash entry for a TD/ED; return true on success */
-static int
-hash_add_ed_td (
-	struct hash_list_t *entry,
-	void *virt,
-	dma_addr_t dma,
-	int mem_flags
-)
-{
-	struct hash_t * scan;
-	
-	scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags);
-	if (!scan)
-		return 0;
-	
-	if (!entry->tail) {
-		entry->head = entry->tail = scan;
-	} else {
-		entry->tail->next = scan;
-		entry->tail = scan;
-	}
-	
-	scan->virt = virt;
-	scan->dma = dma;
-	scan->next = NULL;
-	return 1;
-}
-
-static inline int
-hash_add_ed (struct ohci_hcd *hc, struct ed *ed, int mem_flags)
-{
-	return hash_add_ed_td (&(hc->ed_hash [ED_HASH_FUNC (ed->dma)]),
-			ed, ed->dma, mem_flags);
-}
-
-static inline int
-hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags)
-{
-	return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]),
-			td, td->td_dma, mem_flags);
-}
-
-
-static void
-hash_free_ed_td (struct hash_list_t *entry, void *virt)
-{
-	struct hash_t *scan, *prev;
-	scan = prev = entry->head;
-
-	// Find and unlink hash entry
-	while (scan && scan->virt != virt) {
-		prev = scan;
-		scan = scan->next;
-	}
-	if (scan) {
-		if (scan == entry->head) {
-			if (entry->head == entry->tail)
-				entry->head = entry->tail = NULL;
-			else
-				entry->head = scan->next;
-		} else if (scan == entry->tail) {
-			entry->tail = prev;
-			prev->next = NULL;
-		} else
-			prev->next = scan->next;
-		kfree(scan);
-	}
-}
-
-static inline void
-hash_free_ed (struct ohci_hcd *hc, struct ed * ed)
-{
-	hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed);
-}
-
-static inline void
-hash_free_td (struct ohci_hcd *hc, struct td * td)
-{
-	hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);
-}
-
-
-static int ohci_mem_init (struct ohci_hcd *ohci)
-{
-	ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
-		sizeof (struct td),
-		32 /* byte alignment */,
-		0 /* no page-crossing issues */,
-		GFP_KERNEL | OHCI_MEM_FLAGS);
-	if (!ohci->td_cache)
-		return -ENOMEM;
-	ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev,
-		sizeof (struct ed),
-		16 /* byte alignment */,
-		0 /* no page-crossing issues */,
-		GFP_KERNEL | OHCI_MEM_FLAGS);
-	if (!ohci->ed_cache) {
-		pci_pool_destroy (ohci->td_cache);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static void ohci_mem_cleanup (struct ohci_hcd *ohci)
-{
-	if (ohci->td_cache) {
-		pci_pool_destroy (ohci->td_cache);
-		ohci->td_cache = 0;
-	}
-	if (ohci->ed_cache) {
-		pci_pool_destroy (ohci->ed_cache);
-		ohci->ed_cache = 0;
-	}
-}
-
-/* TDs ... */
-static struct td *
-td_alloc (struct ohci_hcd *hc, int mem_flags)
-{
-	dma_addr_t	dma;
-	struct td	*td;
-
-	td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
-	if (td) {
-		td->td_dma = dma;
-		/* hash it for later reverse mapping */
-		if (!hash_add_td (hc, td, mem_flags)) {
-			pci_pool_free (hc->td_cache, td, dma);
-			return NULL;
-		}
-	}
-	return td;
-}
-
-static void
-td_free (struct ohci_hcd *hc, struct td *td)
-{
-	hash_free_td (hc, td);
-	pci_pool_free (hc->td_cache, td, td->td_dma);
-}
-
-
-/* EDs ... */
-static struct ed *
-ed_alloc (struct ohci_hcd *hc, int mem_flags)
-{
-	dma_addr_t	dma;
-	struct ed	*ed;
-
-	ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
-	if (ed) {
-		memset (ed, 0, sizeof (*ed));
-		ed->dma = dma;
-		/* hash it for later reverse mapping */
-		if (!hash_add_ed (hc, ed, mem_flags)) {
-			pci_pool_free (hc->ed_cache, ed, dma);
-			return NULL;
-		}
-	}
-	return ed;
-}
-
-static void
-ed_free (struct ohci_hcd *hc, struct ed *ed)
-{
-	hash_free_ed (hc, ed);
-	pci_pool_free (hc->ed_cache, ed, ed->dma);
-}
-
diff -Nru a/drivers/usb/hcd/ohci-q.c b/drivers/usb/hcd/ohci-q.c
--- a/drivers/usb/hcd/ohci-q.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1001 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- * 
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * This file is licenced under the GPL.
- * $Id: ohci-q.c,v 1.6 2002/01/19 00:23:15 dbrownell Exp $
- */
-
-static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
-{
-	int		last = urb_priv->length - 1;
-
-	if (last >= 0) {
-		int		i;
-		struct td	*td = urb_priv->td [0];
-#ifdef CONFIG_PCI
-		int		len = td->urb->transfer_buffer_length;
-		int		dir = usb_pipeout (td->urb->pipe)
-					? PCI_DMA_TODEVICE
-					: PCI_DMA_FROMDEVICE;
-
-		/* unmap CTRL URB setup buffer (always td 0) */
-		if (usb_pipecontrol (td->urb->pipe)) {
-			pci_unmap_single (hc->hcd.pdev, 
-					td->data_dma, 8, PCI_DMA_TODEVICE);
-			
-			/* CTRL data buffer starts at td 1 if len > 0 */
-			if (len && last > 0)
-				td = urb_priv->td [1]; 		
-		}
-		/* else:  ISOC, BULK, INTR data buffer starts at td 0 */
-
-		/* unmap data buffer */
-		if (len && td->data_dma)
-			pci_unmap_single (hc->hcd.pdev,
-					td->data_dma, len, dir);
-#else
-#	warning "assuming no buffer unmapping is needed"
-#endif
-
-		for (i = 0; i <= last; i++) {
-			td = urb_priv->td [i];
-			if (td)
-				td_free (hc, td);
-		}
-	}
-
-	kfree (urb_priv);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * URB goes back to driver, and isn't reissued.
- * It's completely gone from HC data structures, so no locking
- * is needed ... or desired! (Giveback can call back to hcd.)
- */
-static inline void finish_urb (struct ohci_hcd *ohci, struct urb *urb)
-{
-	if (urb->hcpriv) {
-		urb_free_priv (ohci, urb->hcpriv);
-		urb->hcpriv = NULL;
-	}
-	usb_hcd_giveback_urb (&ohci->hcd, urb);
-}
-
-static void td_submit_urb (struct urb *urb);
-
-/*
- * URB is reported to driver, is reissued if it's periodic.
- */
-static int return_urb (struct ohci_hcd *hc, struct urb *urb)
-{
-	urb_priv_t	*urb_priv = urb->hcpriv;
-	struct urb	*urbt;
-	unsigned long	flags;
-	int		i;
-
-#ifdef DEBUG
-	if (!urb_priv) {
-		err ("already unlinked!");
-		BUG ();
-	}
-
-	/* just to be sure */
-	if (!urb->complete) {
-		err ("no completion!");
-		BUG ();
-	}
-#endif
-
-#ifdef OHCI_VERBOSE_DEBUG
-	urb_print (urb, "RET", usb_pipeout (urb->pipe));
-#endif
-
-	switch (usb_pipetype (urb->pipe)) {
-  		case PIPE_INTERRUPT:
-#ifdef CONFIG_PCI
-// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
-// and requeue more cheaply, and only if needed.
-			pci_unmap_single (hc->hcd.pdev,
-				urb_priv->td [0]->data_dma,
-				urb->transfer_buffer_length,
-				usb_pipeout (urb->pipe)
-					? PCI_DMA_TODEVICE
-					: PCI_DMA_FROMDEVICE);
-#endif
-			/* FIXME: MP race.  If another CPU partially unlinks
-			 * this URB (urb->status was updated, hasn't yet told
-			 * us to dequeue) before we call complete() here, an
-			 * extra "unlinked" completion will be reported...
-			 */
-			urb->complete (urb);
-
-			/* always requeued, but ED_SKIP if complete() unlinks.
-			 * removed from periodic table only at SOF intr.
-			 */
-  			urb->actual_length = 0;
-			if (urb_priv->state != URB_DEL)
-				urb->status = -EINPROGRESS;
-			spin_lock_irqsave (&hc->lock, flags);
-			td_submit_urb (urb);
-			spin_unlock_irqrestore (&hc->lock, flags);
-  			break;
-
-		case PIPE_ISOCHRONOUS:
-			for (urbt = urb->next;
-					urbt && (urbt != urb);
-					urbt = urbt->next)
-				continue;
-			if (urbt) { /* send the reply and requeue URB */	
-#ifdef CONFIG_PCI
-// FIXME rewrite this resubmit path too
-				pci_unmap_single (hc->hcd.pdev,
-					urb_priv->td [0]->data_dma,
-					urb->transfer_buffer_length,
-					usb_pipeout (urb->pipe)
-						? PCI_DMA_TODEVICE
-						: PCI_DMA_FROMDEVICE);
-#endif
-				urb->complete (urb);
-				spin_lock_irqsave (&hc->lock, flags);
-				urb->actual_length = 0;
-  				urb->status = -EINPROGRESS;
-  				urb->start_frame = urb_priv->ed->last_iso + 1;
-  				if (urb_priv->state != URB_DEL) {
-  					for (i = 0; i < urb->number_of_packets;
-							i++) {
-  						urb->iso_frame_desc [i]
-							.actual_length = 0;
-  						urb->iso_frame_desc [i]
-							.status = -EXDEV;
-  					}
-  					td_submit_urb (urb);
-  				}
-// FIXME if not deleted, should have been "finished"
-  				spin_unlock_irqrestore (&hc->lock, flags);
-
-  			} else { /* not reissued */
-				finish_urb (hc, urb);
-			}		
-			break;
-
-		/*
-		 * C/B requests that get here are never reissued.
-		 */
-		case PIPE_BULK:
-		case PIPE_CONTROL:
-			finish_urb (hc, urb);
-			break;
-	}
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*
- * ED handling functions
- *-------------------------------------------------------------------------*/  
-
-/* search for the right branch to insert an interrupt ed into the int tree 
- * do some load balancing;
- * returns the branch and 
- * sets the interval to interval = 2^integer (ld (interval))
- */
-static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load)
-{
-	int	i, branch = 0;
-
-	/* search for the least loaded interrupt endpoint branch */
-	for (i = 0; i < NUM_INTS ; i++) 
-		if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i])
-			branch = i; 
-
-	branch = branch % interval;
-	for (i = branch; i < NUM_INTS; i += interval)
-		ohci->ohci_int_load [i] += load;
-
-	return branch;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*  2^int ( ld (inter)) */
-
-static int ep_2_n_interval (int inter)
-{	
-	int	i;
-
-	for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++)
-		continue;
-	return 1 << i;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* the int tree is a binary tree 
- * in order to process it sequentially the indexes of the branches have
- * to be mapped the mapping reverses the bits of a word of num_bits length
- */
-static int ep_rev (int num_bits, int word)
-{
-	int			i, wout = 0;
-
-	for (i = 0; i < num_bits; i++)
-		wout |= (( (word >> i) & 1) << (num_bits - i - 1));
-	return wout;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* link an ed into one of the HC chains */
-
-static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
-{	 
-	int			int_branch, i;
-	int			inter, interval, load;
-	__u32			*ed_p;
-	volatile struct ed	*ed = edi;
-
-	ed->state = ED_OPER;
-
-	switch (ed->type) {
-	case PIPE_CONTROL:
-		ed->hwNextED = 0;
-		if (ohci->ed_controltail == NULL) {
-			writel (ed->dma, &ohci->regs->ed_controlhead);
-		} else {
-			ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
-		}
-		ed->ed_prev = ohci->ed_controltail;
-		if (!ohci->ed_controltail
-				&& !ohci->ed_rm_list [0]
-				&& !ohci->ed_rm_list [1]
-				&& !ohci->sleeping
-				) {
-			ohci->hc_control |= OHCI_CTRL_CLE;
-			writel (ohci->hc_control, &ohci->regs->control);
-		}
-		ohci->ed_controltail = edi;	  
-		break;
-
-	case PIPE_BULK:
-		ed->hwNextED = 0;
-		if (ohci->ed_bulktail == NULL) {
-			writel (ed->dma, &ohci->regs->ed_bulkhead);
-		} else {
-			ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
-		}
-		ed->ed_prev = ohci->ed_bulktail;
-		if (!ohci->ed_bulktail
-				&& !ohci->ed_rm_list [0]
-				&& !ohci->ed_rm_list [1]
-				&& !ohci->sleeping
-				) {
-			ohci->hc_control |= OHCI_CTRL_BLE;
-			writel (ohci->hc_control, &ohci->regs->control);
-		}
-		ohci->ed_bulktail = edi;	  
-		break;
-
-	case PIPE_INTERRUPT:
-		load = ed->int_load;
-		interval = ep_2_n_interval (ed->int_period);
-		ed->int_interval = interval;
-		int_branch = ep_int_balance (ohci, interval, load);
-		ed->int_branch = int_branch;
-
-		for (i = 0; i < ep_rev (6, interval); i += inter) {
-			inter = 1;
-			for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i) + int_branch]); 
-				 (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); 
-				ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
-					inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-			ed->hwNextED = *ed_p; 
-			*ed_p = cpu_to_le32 (ed->dma);
-		}
-#ifdef OHCI_VERBOSE_DEBUG
-		ohci_dump_periodic (ohci, "LINK_INT");
-#endif
-		break;
-
-	case PIPE_ISOCHRONOUS:
-		ed->hwNextED = 0;
-		ed->int_interval = 1;
-		if (ohci->ed_isotail != NULL) {
-			ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
-			ed->ed_prev = ohci->ed_isotail;
-		} else {
-			for ( i = 0; i < NUM_INTS; i += inter) {
-				inter = 1;
-				for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); 
-					*ed_p != 0; 
-					ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
-						inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-				*ed_p = cpu_to_le32 (ed->dma);	
-			}	
-			ed->ed_prev = NULL;
-		}	
-		ohci->ed_isotail = edi;  
-#ifdef OHCI_VERBOSE_DEBUG
-		ohci_dump_periodic (ohci, "LINK_ISO");
-#endif
-		break;
-	}	 	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* unlink an ed from one of the HC chains. 
- * just the link to the ed is unlinked.
- * the link from the ed still points to another operational ed or 0
- * so the HC can eventually finish the processing of the unlinked ed
- */
-static int ep_unlink (struct ohci_hcd *ohci, struct ed *ed) 
-{
-	int	int_branch;
-	int	i;
-	int	inter;
-	int	interval;
-	__u32	*ed_p;
-
-	ed->hwINFO |= ED_SKIP;
-
-	switch (ed->type) {
-	case PIPE_CONTROL:
-		if (ed->ed_prev == NULL) {
-			if (!ed->hwNextED) {
-				ohci->hc_control &= ~OHCI_CTRL_CLE;
-				writel (ohci->hc_control, &ohci->regs->control);
-			}
-			writel (le32_to_cpup (&ed->hwNextED),
-				&ohci->regs->ed_controlhead);
-		} else {
-			ed->ed_prev->hwNextED = ed->hwNextED;
-		}
-		if (ohci->ed_controltail == ed) {
-			ohci->ed_controltail = ed->ed_prev;
-		} else {
-			 (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
-			 	->ed_prev = ed->ed_prev;
-		}
-		break;
-
-	case PIPE_BULK:
-		if (ed->ed_prev == NULL) {
-			if (!ed->hwNextED) {
-				ohci->hc_control &= ~OHCI_CTRL_BLE;
-				writel (ohci->hc_control, &ohci->regs->control);
-			}
-			writel (le32_to_cpup (&ed->hwNextED),
-				&ohci->regs->ed_bulkhead);
-		} else {
-			ed->ed_prev->hwNextED = ed->hwNextED;
-		}
-		if (ohci->ed_bulktail == ed) {
-			ohci->ed_bulktail = ed->ed_prev;
-		} else {
-			 (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
-			 	->ed_prev = ed->ed_prev;
-		}
-		break;
-
-	case PIPE_INTERRUPT:
-		int_branch = ed->int_branch;
-		interval = ed->int_interval;
-
-		for (i = 0; i < ep_rev (6, interval); i += inter) {
-			for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i) + int_branch]), inter = 1; 
-				 (*ed_p != 0) && (*ed_p != ed->hwNextED); 
-				ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED), 
-				inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval)) {				
-					if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
-			  			*ed_p = ed->hwNextED;		
-			  			break;
-			  		}
-			  }
-		}
-		for (i = int_branch; i < NUM_INTS; i += interval)
-		    ohci->ohci_int_load [i] -= ed->int_load;
-#ifdef OHCI_VERBOSE_DEBUG
-		ohci_dump_periodic (ohci, "UNLINK_INT");
-#endif
-		break;
-
-	case PIPE_ISOCHRONOUS:
-		if (ohci->ed_isotail == ed)
-			ohci->ed_isotail = ed->ed_prev;
-		if (ed->hwNextED != 0) 
-			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
-		    		->ed_prev = ed->ed_prev;
-
-		if (ed->ed_prev != NULL) {
-			ed->ed_prev->hwNextED = ed->hwNextED;
-		} else {
-			for (i = 0; i < NUM_INTS; i++) {
-				for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); 
-						*ed_p != 0; 
-						ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) {
-					// inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-					if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
-						*ed_p = ed->hwNextED;		
-						break;
-					}
-				}
-			}	
-		}	
-#ifdef OHCI_VERBOSE_DEBUG
-		ohci_dump_periodic (ohci, "UNLINK_ISO");
-#endif
-		break;
-	}
-
-	/* FIXME ED's "unlink" state is indeterminate;
-	 * the HC might still be caching it (till SOF).
-	 */
-	ed->state = ED_UNLINK;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* (re)init an endpoint; this _should_ be done once at the
- * usb_set_configuration command, but the USB stack is a bit stateless
- * so we do it at every transaction.
- * if the state of the ed is ED_NEW then a dummy td is added and the
- * state is changed to ED_UNLINK
- * in all other cases the state is left unchanged
- * the ed info fields are set even though most of them should
- * not change
- */
-static struct ed *ep_add_ed (
-	struct usb_device	*udev,
-	unsigned int		pipe,
-	int			interval,
-	int			load,
-	int			mem_flags
-) {
-   	struct ohci_hcd		*ohci = hcd_to_ohci (udev->bus->hcpriv);
-	struct hcd_dev		*dev = (struct hcd_dev *) udev->hcpriv;
-	struct td		*td;
-	struct ed		*ed; 
-	unsigned		ep;
-	unsigned long		flags;
-
-	spin_lock_irqsave (&ohci->lock, flags);
-
-	ep = usb_pipeendpoint (pipe) << 1;
-	if (!usb_pipecontrol (pipe) && usb_pipeout (pipe))
-		ep |= 1;
-	if (!(ed = dev->ep [ep])) {
-		ed = ed_alloc (ohci, SLAB_ATOMIC);
-		if (!ed) {
-			/* out of memory */
-			spin_unlock_irqrestore (&ohci->lock, flags);
-			return NULL;
-		}
-		dev->ep [ep] = ed;
-	}
-
-	if (ed->state & ED_URB_DEL) {
-		/* pending unlink request */
-		spin_unlock_irqrestore (&ohci->lock, flags);
-		return NULL;
-	}
-
-	if (ed->state == ED_NEW) {
-		ed->hwINFO = ED_SKIP;
-  		/* dummy td; end of td list for ed */
-		td = td_alloc (ohci, SLAB_ATOMIC);
- 		if (!td) {
-			/* out of memory */
-			spin_unlock_irqrestore (&ohci->lock, flags);
-			return NULL;
-		}
-		ed->hwTailP = cpu_to_le32 (td->td_dma);
-		ed->hwHeadP = ed->hwTailP;	
-		ed->state = ED_UNLINK;
-		ed->type = usb_pipetype (pipe);
-	}
-
-// FIXME:  don't do this if it's linked to the HC,
-// we might clobber data toggle or other state ...
-
-	ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
-			| usb_pipeendpoint (pipe) << 7
-			| (usb_pipeisoc (pipe)? 0x8000: 0)
-			| (usb_pipecontrol (pipe)
-				? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) 
-			| (udev->speed == USB_SPEED_LOW) << 13
-			| usb_maxpacket (udev, pipe, usb_pipeout (pipe))
-				<< 16);
-
-  	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
-  		ed->int_period = interval;
-  		ed->int_load = load;
-  	}
-
-	spin_unlock_irqrestore (&ohci->lock, flags);
-	return ed; 
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* request unlinking of an endpoint from an operational HC.
- * put the ep on the rm_list and stop the bulk or ctrl list 
- * real work is done at the next start frame (SF) hardware interrupt
- */
-static void ed_unlink (struct usb_device *usb_dev, struct ed *ed)
-{    
-	unsigned int		frame;
-   	struct ohci_hcd		*ohci = hcd_to_ohci (usb_dev->bus->hcpriv);
-
-	/* already pending? */
-	if (ed->state & ED_URB_DEL)
-		return;
-	ed->state |= ED_URB_DEL;
-
-	ed->hwINFO |= ED_SKIP;
-
-	switch (ed->type) {
-		case PIPE_CONTROL: /* stop control list */
-			ohci->hc_control &= ~OHCI_CTRL_CLE;
-			writel (ohci->hc_control,
-				&ohci->regs->control); 
-			break;
-		case PIPE_BULK: /* stop bulk list */
-			ohci->hc_control &= ~OHCI_CTRL_BLE;
-			writel (ohci->hc_control,
-				&ohci->regs->control); 
-			break;
-	}
-
-	frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1;
-	ed->ed_rm_list = ohci->ed_rm_list [frame];
-	ohci->ed_rm_list [frame] = ed;
-
-	/* enable SOF interrupt */
-	if (!ohci->sleeping) {
-		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-	}
-}
-
-/*-------------------------------------------------------------------------*
- * TD handling functions
- *-------------------------------------------------------------------------*/
-
-/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
-
-static void
-td_fill (struct ohci_hcd *ohci, unsigned int info,
-	dma_addr_t data, int len,
-	struct urb *urb, int index)
-{
-	volatile struct td	*td, *td_pt;
-	urb_priv_t		*urb_priv = urb->hcpriv;
-
-	if (index >= urb_priv->length) {
-		err ("internal OHCI error: TD index > length");
-		return;
-	}
-
-	/* use this td as the next dummy */
-	td_pt = urb_priv->td [index];
-	td_pt->hwNextTD = 0;
-
-	/* fill the old dummy TD */
-	td = urb_priv->td [index] = dma_to_td (ohci,
-			le32_to_cpup (&urb_priv->ed->hwTailP));
-
-	td->ed = urb_priv->ed;
-	td->next_dl_td = NULL;
-	td->index = index;
-	td->urb = urb; 
-	td->data_dma = data;
-	if (!len)
-		data = 0;
-
-	td->hwINFO = cpu_to_le32 (info);
-	if ((td->ed->type) == PIPE_ISOCHRONOUS) {
-		td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
-		td->ed->last_iso = info & 0xffff;
-	} else {
-		td->hwCBP = cpu_to_le32 (data); 
-	}			
-	if (data)
-		td->hwBE = cpu_to_le32 (data + len - 1);
-	else
-		td->hwBE = 0;
-	td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
-	td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
-
-	/* append to queue */
-	td->ed->hwTailP = td->hwNextTD;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* prepare all TDs of a transfer */
-
-static void td_submit_urb (struct urb *urb)
-{ 
-	urb_priv_t	*urb_priv = urb->hcpriv;
-	struct ohci_hcd *ohci = hcd_to_ohci (urb->dev->bus->hcpriv);
-	dma_addr_t	data;
-	int		data_len = urb->transfer_buffer_length;
-	int		cnt = 0; 
-	__u32		info = 0;
-  	unsigned int	toggle = 0;
-
-	/* OHCI handles the DATA-toggles itself, we just use the
-	 * USB-toggle bits for resetting
-	 */
-  	if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-			usb_pipeout (urb->pipe))) {
-  		toggle = TD_T_TOGGLE;
-	} else {
-  		toggle = TD_T_DATA0;
-		usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-			usb_pipeout (urb->pipe), 1);
-	}
-
-	urb_priv->td_cnt = 0;
-
-	if (data_len) {
-#ifdef CONFIG_PCI
-		data = pci_map_single (ohci->hcd.pdev,
-			urb->transfer_buffer, data_len,
-			usb_pipeout (urb->pipe)
-				? PCI_DMA_TODEVICE
-				: PCI_DMA_FROMDEVICE
-			);
-#else
-#	error "what dma addr to use"
-#endif
-	} else
-		data = 0;
-
-	switch (usb_pipetype (urb->pipe)) {
-		case PIPE_BULK:
-			info = usb_pipeout (urb->pipe)
-				? TD_CC | TD_DP_OUT
-				: TD_CC | TD_DP_IN ;
-			while (data_len > 4096) {		
-				td_fill (ohci,
-					info | (cnt? TD_T_TOGGLE:toggle),
-					data, 4096, urb, cnt);
-				data += 4096; data_len -= 4096; cnt++;
-			}
-			info = usb_pipeout (urb->pipe)?
-				TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
-			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
-				data, data_len, urb, cnt);
-			cnt++;
-			if ((urb->transfer_flags & USB_ZERO_PACKET)
-					&& cnt < urb_priv->length) {
-				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
-					0, 0, urb, cnt);
-				cnt++;
-			}
-			/* start bulk list */
-			if (!ohci->sleeping)
-				writel (OHCI_BLF, &ohci->regs->cmdstatus);
-			break;
-
-		case PIPE_INTERRUPT:
-			info = TD_CC | toggle;
-			info |= usb_pipeout (urb->pipe) 
-				?  TD_DP_OUT
-				:  TD_R | TD_DP_IN;
-			td_fill (ohci, info, data, data_len, urb, cnt++);
-			break;
-
-		case PIPE_CONTROL:
-			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
-			td_fill (ohci, info,
-#ifdef CONFIG_PCI
-				pci_map_single (ohci->hcd.pdev,
-					urb->setup_packet, 8,
-					PCI_DMA_TODEVICE),
-#else
-#	error "what dma addr to use"				
-#endif
-				8, urb, cnt++); 
-			if (data_len > 0) {  
-				info = TD_CC | TD_R | TD_T_DATA1;
-				info |= usb_pipeout (urb->pipe)
-				    ? TD_DP_OUT
-				    : TD_DP_IN;
-				/* NOTE:  mishandles transfers >8K, some >4K */
-				td_fill (ohci, info, data, data_len,
-						urb, cnt++);  
-			} 
-			info = usb_pipeout (urb->pipe)
-				? TD_CC | TD_DP_IN | TD_T_DATA1
-				: TD_CC | TD_DP_OUT | TD_T_DATA1;
-			td_fill (ohci, info, data, 0, urb, cnt++);
-			/* start control list */
-			if (!ohci->sleeping)
-				writel (OHCI_CLF, &ohci->regs->cmdstatus);
-			break;
-
-		case PIPE_ISOCHRONOUS:
-			for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
-				td_fill (ohci, TD_CC | TD_ISO
-					| ((urb->start_frame + cnt) & 0xffff), 
-				    data + urb->iso_frame_desc [cnt].offset, 
-				    urb->iso_frame_desc [cnt].length, urb, cnt); 
-			}
-			break;
-	} 
-	if (urb_priv->length != cnt) 
-		dbg ("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
-}
-
-/*-------------------------------------------------------------------------*
- * Done List handling functions
- *-------------------------------------------------------------------------*/
-
-/* calculate the transfer length and update the urb */
-
-static void dl_transfer_length (struct td *td)
-{
-	__u32		tdINFO, tdBE, tdCBP;
- 	__u16		tdPSW;
- 	struct urb	*urb = td->urb;
- 	urb_priv_t	*urb_priv = urb->hcpriv;
-	int		dlen = 0;
-	int		cc = 0;
-
-	tdINFO = le32_to_cpup (&td->hwINFO);
-  	tdBE   = le32_to_cpup (&td->hwBE);
-  	tdCBP  = le32_to_cpup (&td->hwCBP);
-
-
-  	if (tdINFO & TD_ISO) {
- 		tdPSW = le16_to_cpu (td->hwPSW [0]);
- 		cc = (tdPSW >> 12) & 0xF;
-		if (cc < 0xE)  {
-			if (usb_pipeout (urb->pipe)) {
-				dlen = urb->iso_frame_desc [td->index].length;
-			} else {
-				dlen = tdPSW & 0x3ff;
-			}
-			urb->actual_length += dlen;
-			urb->iso_frame_desc [td->index].actual_length = dlen;
-			if (! (urb->transfer_flags & USB_DISABLE_SPD)
-					&& (cc == TD_DATAUNDERRUN))
-				cc = TD_CC_NOERROR;
-
-			urb->iso_frame_desc [td->index].status
-				= cc_to_error [cc];
-		}
-	} else { /* BULK, INT, CONTROL DATA */
-		if (! (usb_pipetype (urb->pipe) == PIPE_CONTROL && 
-				 ((td->index == 0)
-				 || (td->index == urb_priv->length - 1)))) {
- 			if (tdBE != 0) {
-				urb->actual_length += (td->hwCBP == 0)
-					? (tdBE - td->data_dma + 1)
-					: (tdCBP - td->data_dma);
-			}
-  		}
-  	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* replies to the request have to be on a FIFO basis so
- * we unreverse the hc-reversed done-list
- */
-static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
-{
-	__u32		td_list_hc;
-	struct td	*td_rev = NULL;
-	struct td	*td_list = NULL;
-  	urb_priv_t	*urb_priv = NULL;
-  	unsigned long	flags;
-
-  	spin_lock_irqsave (&ohci->lock, flags);
-
-	td_list_hc = le32_to_cpup (&ohci->hcca->done_head);
-	ohci->hcca->done_head = 0;
-
-	while (td_list_hc) {		
-		td_list = dma_to_td (ohci, td_list_hc);
-
-		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
-			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
-			dbg (" USB-error/status: %x : %p", 
-				TD_CC_GET (le32_to_cpup (&td_list->hwINFO)),
-				td_list);
-			/* typically the endpoint halted too */
-			if (td_list->ed->hwHeadP & ED_H) {
-				if (urb_priv && ((td_list->index + 1)
-						< urb_priv->length)) {
-					td_list->ed->hwHeadP = 
-			    (urb_priv->td [urb_priv->length - 1]->hwNextTD
-				    & __constant_cpu_to_le32 (TD_MASK))
-			    | (td_list->ed->hwHeadP & ED_C);
-					urb_priv->td_cnt += urb_priv->length
-						- td_list->index - 1;
-				} else 
-					td_list->ed->hwHeadP &= ~ED_H;
-			}
-		}
-
-		td_list->next_dl_td = td_rev;	
-		td_rev = td_list;
-		td_list_hc = le32_to_cpup (&td_list->hwNextTD);
-	}	
-	spin_unlock_irqrestore (&ohci->lock, flags);
-	return td_list;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* there are some pending requests to unlink 
- * - some URBs/TDs if urb_priv->state == URB_DEL
- */
-static void dl_del_list (struct ohci_hcd *ohci, unsigned int frame)
-{
-	unsigned long	flags;
-	struct ed	*ed;
-	__u32		edINFO;
-	__u32		tdINFO;
-	struct td	*td = NULL, *td_next = NULL,
-			*tdHeadP = NULL, *tdTailP;
-	__u32		*td_p;
-	int		ctrl = 0, bulk = 0;
-
-	spin_lock_irqsave (&ohci->lock, flags);
-
-	for (ed = ohci->ed_rm_list [frame]; ed != NULL; ed = ed->ed_rm_list) {
-
-		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP));
-		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
-		edINFO = le32_to_cpup (&ed->hwINFO);
-		td_p = &ed->hwHeadP;
-
-		for (td = tdHeadP; td != tdTailP; td = td_next) {
-			struct urb *urb = td->urb;
-			urb_priv_t *urb_priv = td->urb->hcpriv;
-
-			td_next = dma_to_td (ohci,
-				le32_to_cpup (&td->hwNextTD));
-			if ((urb_priv->state == URB_DEL)) {
-				tdINFO = le32_to_cpup (&td->hwINFO);
-				if (TD_CC_GET (tdINFO) < 0xE)
-					dl_transfer_length (td);
-				*td_p = td->hwNextTD | (*td_p
-					& __constant_cpu_to_le32 (0x3));
-
-				/* URB is done; clean up */
-				if (++ (urb_priv->td_cnt) == urb_priv->length)
-// FIXME:  we shouldn't hold ohci->lock here, else the
-// completion function can't talk to this hcd ...
-					finish_urb (ohci, urb);
-			} else {
-				td_p = &td->hwNextTD;
-			}
-		}
-
-		ed->state &= ~ED_URB_DEL;
-		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
-
-		if (tdHeadP == tdTailP) {
-			if (ed->state == ED_OPER)
-				ep_unlink (ohci, ed);
-			td_free (ohci, tdTailP);
-			ed->hwINFO = ED_SKIP;
-			ed->state = ED_NEW;
-		} else
-			ed->hwINFO &= ~ED_SKIP;
-
-		switch (ed->type) {
-			case PIPE_CONTROL:
-				ctrl = 1;
-				break;
-			case PIPE_BULK:
-				bulk = 1;
-				break;
-		}
-   	}
-
-	/* maybe reenable control and bulk lists */ 
-	if (!ohci->disabled) {
-		if (ctrl) 	/* reset control list */
-			writel (0, &ohci->regs->ed_controlcurrent);
-		if (bulk)	/* reset bulk list */
-			writel (0, &ohci->regs->ed_bulkcurrent);
-		if (!ohci->ed_rm_list [!frame]) {
-			if (ohci->ed_controltail)
-				ohci->hc_control |= OHCI_CTRL_CLE;
-			if (ohci->ed_bulktail)
-				ohci->hc_control |= OHCI_CTRL_BLE;
-			writel (ohci->hc_control, &ohci->regs->control);   
-		}
-	}
-
-   	ohci->ed_rm_list [frame] = NULL;
-   	spin_unlock_irqrestore (&ohci->lock, flags);
-}
-
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * process normal completions (error or success) and some unlinked eds
- * this is the main path for handing urbs back to drivers
- */
-static void dl_done_list (struct ohci_hcd *ohci, struct td *td_list)
-{
-  	struct td	*td_list_next = NULL;
-	struct ed	*ed;
-	int		cc = 0;
-	struct urb	*urb;
-	urb_priv_t	*urb_priv;
- 	__u32		tdINFO;
-
- 	unsigned long flags;
-
-  	while (td_list) {
-   		td_list_next = td_list->next_dl_td;
-
-  		urb = td_list->urb;
-  		urb_priv = urb->hcpriv;
-  		tdINFO = le32_to_cpup (&td_list->hwINFO);
-
-   		ed = td_list->ed;
-
-   		dl_transfer_length (td_list);
-
-  		/* error code of transfer */
-  		cc = TD_CC_GET (tdINFO);
-  		if (cc == TD_CC_STALL)
-			usb_endpoint_halt (urb->dev,
-				usb_pipeendpoint (urb->pipe),
-				usb_pipeout (urb->pipe));
-
-  		if (! (urb->transfer_flags & USB_DISABLE_SPD)
-				&& (cc == TD_DATAUNDERRUN))
-			cc = TD_CC_NOERROR;
-
-  		if (++ (urb_priv->td_cnt) == urb_priv->length) {
-			/*
-			 * Except for periodic transfers, both branches do
-			 * the same thing.  Periodic urbs get reissued until
-			 * they're "deleted" (in SOF intr) by usb_unlink_urb.
-			 */
-			if ((ed->state & (ED_OPER | ED_UNLINK))
-					&& (urb_priv->state != URB_DEL)) {
-				spin_lock (&urb->lock);
-				if (urb->status == -EINPROGRESS)
-  					urb->status = cc_to_error [cc];
-				spin_unlock (&urb->lock);
-  				return_urb (ohci, urb);
-  			} else
-  				finish_urb (ohci, urb);
-  		}
-
-  		spin_lock_irqsave (&ohci->lock, flags);
-  		if (ed->state != ED_NEW) { 
-  			u32 edHeadP = ed->hwHeadP;
-
-			/* unlink eds if they are not busy */
-			edHeadP &= __constant_cpu_to_le32 (ED_MASK);
-     			if ((edHeadP == ed->hwTailP) && (ed->state == ED_OPER)) 
-     				ep_unlink (ohci, ed);
-     		}	
-     		spin_unlock_irqrestore (&ohci->lock, flags);
-
-    		td_list = td_list_next;
-  	}  
-}
-
diff -Nru a/drivers/usb/hcd/ohci.h b/drivers/usb/hcd/ohci.h
--- a/drivers/usb/hcd/ohci.h	Sun Apr 14 12:17:00 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,369 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- * 
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * This file is licenced under the GPL.
- * $Id: ohci.h,v 1.5 2002/01/19 00:24:01 dbrownell Exp $
- */
- 
-/*
- * OHCI Endpoint Descriptor (ED) ... holds TD queue
- * See OHCI spec, section 4.2
- */
-struct ed {
-	/* first fields are hardware-specified, le32 */
-	__u32			hwINFO;       	/* endpoint config bitmap */
-#define ED_ISO		__constant_cpu_to_le32(1 << 15)
-#define ED_SKIP		__constant_cpu_to_le32(1 << 14)
-#define ED_LOWSPEED	__constant_cpu_to_le32(1 << 13)
-#define ED_OUT		__constant_cpu_to_le32(0x01 << 11)
-#define ED_IN		__constant_cpu_to_le32(0x10 << 11)
-	__u32			hwTailP;	/* tail of TD list */
-	__u32			hwHeadP;	/* head of TD list */
-#define ED_C		__constant_cpu_to_le32(0x02)	/* toggle carry */
-#define ED_H		__constant_cpu_to_le32(0x01)	/* halted */
-	__u32			hwNextED;	/* next ED in list */
-
-	/* rest are purely for the driver's use */
-	struct ed		*ed_prev;  
-	__u8			int_period;
-	__u8			int_branch;
-	__u8			int_load; 
-	__u8			int_interval;
-	__u8			state;			// ED_{NEW,UNLINK,OPER}
-#define ED_NEW 		0x00		/* unused, no dummy td */
-#define ED_UNLINK 	0x01		/* dummy td, maybe linked to hc */
-#define ED_OPER		0x02		/* dummy td, _is_ linked to hc */
-#define ED_URB_DEL  	0x08		/* for unlinking; masked in */
-
-	__u8			type; 
-	__u16			last_iso;
-	struct ed		*ed_rm_list;
-
-	dma_addr_t		dma;			/* addr of ED */
-} __attribute__ ((aligned(16)));
-
-#define ED_MASK	((u32)~0x0f)		/* strip hw status in low addr bits */
-
- 
-/*
- * OHCI Transfer Descriptor (TD) ... one per transfer segment
- * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
- * and 4.3.2 (iso)
- */
-struct td {
-	/* first fields are hardware-specified, le32 */
-	__u32		hwINFO;		/* transfer info bitmask */
-#define TD_CC       0xf0000000			/* condition code */
-#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
-//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
-#define TD_EC       0x0C000000			/* error count */
-#define TD_T        0x03000000			/* data toggle state */
-#define TD_T_DATA0  0x02000000				/* DATA0 */
-#define TD_T_DATA1  0x03000000				/* DATA1 */
-#define TD_T_TOGGLE 0x00000000				/* uses ED_C */
-#define TD_DI       0x00E00000			/* frames before interrupt */
-//#define TD_DI_SET(X) (((X) & 0x07)<< 21)
-#define TD_DP       0x00180000			/* direction/pid */
-#define TD_DP_SETUP 0x00000000			/* SETUP pid */
-#define TD_DP_IN    0x00100000				/* IN pid */
-#define TD_DP_OUT   0x00080000				/* OUT pid */
-							/* 0x00180000 rsvd */
-#define TD_R        0x00040000			/* round: short packets OK? */
-					/* bits 0x1ffff are defined by HCD */
-#define TD_ISO	    0x00010000			/* copy of ED_ISO */
-
-  	__u32		hwCBP;		/* Current Buffer Pointer (or 0) */
-  	__u32		hwNextTD;	/* Next TD Pointer */
-  	__u32		hwBE;		/* Memory Buffer End Pointer */
-
-	/* PSW is only for ISO */
-#define MAXPSW 1		/* hardware allows 8 */
-  	__u16		hwPSW [MAXPSW];
-
-	/* rest are purely for the driver's use */
-  	__u8		index;
-  	struct ed	*ed;
-  	struct td	*next_dl_td;
-  	struct urb	*urb;
-
-	dma_addr_t	td_dma;		/* addr of this TD */
-	dma_addr_t	data_dma;	/* addr of data it points to */
-} __attribute__ ((aligned(32)));	/* c/b/i need 16; only iso needs 32 */
-
-#define TD_MASK	((u32)~0x1f)		/* strip hw status in low addr bits */
-
-/*
- * Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW
- */
-#define TD_CC_NOERROR      0x00
-#define TD_CC_CRC          0x01
-#define TD_CC_BITSTUFFING  0x02
-#define TD_CC_DATATOGGLEM  0x03
-#define TD_CC_STALL        0x04
-#define TD_DEVNOTRESP      0x05
-#define TD_PIDCHECKFAIL    0x06
-#define TD_UNEXPECTEDPID   0x07
-#define TD_DATAOVERRUN     0x08
-#define TD_DATAUNDERRUN    0x09
-    /* 0x0A, 0x0B reserved for hardware */
-#define TD_BUFFEROVERRUN   0x0C
-#define TD_BUFFERUNDERRUN  0x0D
-    /* 0x0E, 0x0F reserved for HCD */
-#define TD_NOTACCESSED     0x0F
-
-
-/* map OHCI TD status codes (CC) to errno values */ 
-static const int cc_to_error [16] = { 
-	/* No  Error  */               0,
-	/* CRC Error  */               -EILSEQ,
-	/* Bit Stuff  */               -EPROTO,
-	/* Data Togg  */               -EILSEQ,
-	/* Stall      */               -EPIPE,
-	/* DevNotResp */               -ETIMEDOUT,
-	/* PIDCheck   */               -EPROTO,
-	/* UnExpPID   */               -EPROTO,
-	/* DataOver   */               -EOVERFLOW,
-	/* DataUnder  */               -EREMOTEIO,
-	/* (for hw)   */               -EIO,
-	/* (for hw)   */               -EIO,
-	/* BufferOver */               -ECOMM,
-	/* BuffUnder  */               -ENOSR,
-	/* (for HCD)  */               -EALREADY,
-	/* (for HCD)  */               -EALREADY 
-};
-
-
-/*
- * The HCCA (Host Controller Communications Area) is a 256 byte
- * structure defined section 4.4.1 of the OHCI spec. The HC is
- * told the base address of it.  It must be 256-byte aligned.
- */
-struct ohci_hcca {
-#define NUM_INTS 32
-	__u32	int_table [NUM_INTS];	/* periodic schedule */
-	__u16	frame_no;		/* current frame number */
-	__u16	pad1;			/* set to 0 on each frame_no change */
-	__u32	done_head;		/* info returned for an interrupt */
-	u8	reserved_for_hc [116];
-	u8	what [4];		/* spec only identifies 252 bytes :) */
-} __attribute__ ((aligned(256)));
-
-  
-/*
- * This is the structure of the OHCI controller's memory mapped I/O region.
- * You must use readl() and writel() (in <asm/io.h>) to access these fields!!
- * Layout is in section 7 (and appendix B) of the spec.
- */
-struct ohci_regs {
-	/* control and status registers (section 7.1) */
-	__u32	revision;
-	__u32	control;
-	__u32	cmdstatus;
-	__u32	intrstatus;
-	__u32	intrenable;
-	__u32	intrdisable;
-
-	/* memory pointers (section 7.2) */
-	__u32	hcca;
-	__u32	ed_periodcurrent;
-	__u32	ed_controlhead;
-	__u32	ed_controlcurrent;
-	__u32	ed_bulkhead;
-	__u32	ed_bulkcurrent;
-	__u32	donehead;
-
-	/* frame counters (section 7.3) */
-	__u32	fminterval;
-	__u32	fmremaining;
-	__u32	fmnumber;
-	__u32	periodicstart;
-	__u32	lsthresh;
-
-	/* Root hub ports (section 7.4) */
-	struct	ohci_roothub_regs {
-		__u32	a;
-		__u32	b;
-		__u32	status;
-#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports (RH_A_NDP) */
-		__u32	portstatus [MAX_ROOT_PORTS];
-	} roothub;
-
-	/* and optional "legacy support" registers (appendix B) at 0x0100 */
-
-} __attribute__ ((aligned(32)));
-
-
-/* OHCI CONTROL AND STATUS REGISTER MASKS */
-
-/*
- * HcControl (control) register masks
- */
-#define OHCI_CTRL_CBSR	(3 << 0)	/* control/bulk service ratio */
-#define OHCI_CTRL_PLE	(1 << 2)	/* periodic list enable */
-#define OHCI_CTRL_IE	(1 << 3)	/* isochronous enable */
-#define OHCI_CTRL_CLE	(1 << 4)	/* control list enable */
-#define OHCI_CTRL_BLE	(1 << 5)	/* bulk list enable */
-#define OHCI_CTRL_HCFS	(3 << 6)	/* host controller functional state */
-#define OHCI_CTRL_IR	(1 << 8)	/* interrupt routing */
-#define OHCI_CTRL_RWC	(1 << 9)	/* remote wakeup connected */
-#define OHCI_CTRL_RWE	(1 << 10)	/* remote wakeup enable */
-
-/* pre-shifted values for HCFS */
-#	define OHCI_USB_RESET	(0 << 6)
-#	define OHCI_USB_RESUME	(1 << 6)
-#	define OHCI_USB_OPER	(2 << 6)
-#	define OHCI_USB_SUSPEND	(3 << 6)
-
-/*
- * HcCommandStatus (cmdstatus) register masks
- */
-#define OHCI_HCR	(1 << 0)	/* host controller reset */
-#define OHCI_CLF  	(1 << 1)	/* control list filled */
-#define OHCI_BLF  	(1 << 2)	/* bulk list filled */
-#define OHCI_OCR  	(1 << 3)	/* ownership change request */
-#define OHCI_SOC  	(3 << 16)	/* scheduling overrun count */
-
-/*
- * masks used with interrupt registers:
- * HcInterruptStatus (intrstatus)
- * HcInterruptEnable (intrenable)
- * HcInterruptDisable (intrdisable)
- */
-#define OHCI_INTR_SO	(1 << 0)	/* scheduling overrun */
-#define OHCI_INTR_WDH	(1 << 1)	/* writeback of done_head */
-#define OHCI_INTR_SF	(1 << 2)	/* start frame */
-#define OHCI_INTR_RD	(1 << 3)	/* resume detect */
-#define OHCI_INTR_UE	(1 << 4)	/* unrecoverable error */
-#define OHCI_INTR_FNO	(1 << 5)	/* frame number overflow */
-#define OHCI_INTR_RHSC	(1 << 6)	/* root hub status change */
-#define OHCI_INTR_OC	(1 << 30)	/* ownership change */
-#define OHCI_INTR_MIE	(1 << 31)	/* master interrupt enable */
-
-
-/* OHCI ROOT HUB REGISTER MASKS */
- 
-/* roothub.portstatus [i] bits */
-#define RH_PS_CCS            0x00000001   	/* current connect status */
-#define RH_PS_PES            0x00000002   	/* port enable status*/
-#define RH_PS_PSS            0x00000004   	/* port suspend status */
-#define RH_PS_POCI           0x00000008   	/* port over current indicator */
-#define RH_PS_PRS            0x00000010  	/* port reset status */
-#define RH_PS_PPS            0x00000100   	/* port power status */
-#define RH_PS_LSDA           0x00000200    	/* low speed device attached */
-#define RH_PS_CSC            0x00010000 	/* connect status change */
-#define RH_PS_PESC           0x00020000   	/* port enable status change */
-#define RH_PS_PSSC           0x00040000    	/* port suspend status change */
-#define RH_PS_OCIC           0x00080000    	/* over current indicator change */
-#define RH_PS_PRSC           0x00100000   	/* port reset status change */
-
-/* roothub.status bits */
-#define RH_HS_LPS	     0x00000001		/* local power status */
-#define RH_HS_OCI	     0x00000002		/* over current indicator */
-#define RH_HS_DRWE	     0x00008000		/* device remote wakeup enable */
-#define RH_HS_LPSC	     0x00010000		/* local power status change */
-#define RH_HS_OCIC	     0x00020000		/* over current indicator change */
-#define RH_HS_CRWE	     0x80000000		/* clear remote wakeup enable */
-
-/* roothub.b masks */
-#define RH_B_DR		0x0000ffff		/* device removable flags */
-#define RH_B_PPCM	0xffff0000		/* port power control mask */
-
-/* roothub.a masks */
-#define	RH_A_NDP	(0xff << 0)		/* number of downstream ports */
-#define	RH_A_PSM	(1 << 8)		/* power switching mode */
-#define	RH_A_NPS	(1 << 9)		/* no power switching */
-#define	RH_A_DT		(1 << 10)		/* device type (mbz) */
-#define	RH_A_OCPM	(1 << 11)		/* over current protection mode */
-#define	RH_A_NOCP	(1 << 12)		/* no over current protection */
-#define	RH_A_POTPGT	(0xff << 24)		/* power on to power good time */
-
-
-/* hcd-private per-urb state */
-typedef struct urb_priv {
-	struct ed		*ed;
-	__u16			length;		// # tds in this request
-	__u16			td_cnt;		// tds already serviced
-	int   			state;
-	struct td		*td [0];	// all TDs in this request
-
-} urb_priv_t;
-
-#define URB_DEL 1
-
-
-/* Hash struct used for TD/ED hashing */
-struct hash_t {
-	void		*virt;
-	dma_addr_t	dma;
-	struct hash_t	*next; // chaining for collision cases
-};
-
-/* List of TD/ED hash entries */
-struct hash_list_t {
-	struct hash_t	*head;
-	struct hash_t	*tail;
-};
-
-#define TD_HASH_SIZE    64    /* power'o'two */
-#define ED_HASH_SIZE    64    /* power'o'two */
-
-#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)
-#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE)
-
-
-/*
- * This is the full ohci controller description
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs. (Linus)
- */
-
-struct ohci_hcd {
-	spinlock_t		lock;
-
-	/*
-	 * I/O memory used to communicate with the HC (uncached);
-	 */
-	struct ohci_regs	*regs;
-
-	/*
-	 * main memory used to communicate with the HC (uncached)
-	 */
-	struct ohci_hcca	*hcca;
-	dma_addr_t		hcca_dma;
-
-	struct ed		*ed_rm_list [2];	/* to be removed */
-
-	struct ed		*ed_bulktail;		/* last in bulk list */
-	struct ed		*ed_controltail;	/* last in ctrl list */
- 	struct ed		*ed_isotail;		/* last in iso list */
-
-#ifdef CONFIG_PCI
-	struct pci_pool		*td_cache;
-	struct pci_pool		*ed_cache;
-	struct hash_list_t	td_hash [TD_HASH_SIZE];
-	struct hash_list_t	ed_hash [ED_HASH_SIZE];
-#endif
-
-	/*
-	 * driver state
-	 */
-	int			disabled;	/* e.g. got a UE, we're hung */
-	int			sleeping;
-	int			ohci_int_load [NUM_INTS];
-	u32 			hc_control;	/* copy of hc control reg */
-
-	unsigned long		flags;		/* for HC bugs */
-#define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
-
-	/*
-	 * framework state
-	 */
-	struct usb_hcd		hcd;
-};
-
-#define hcd_to_ohci(hcd_ptr) list_entry(hcd_ptr, struct ohci_hcd, hcd)
-
diff -Nru a/drivers/usb/hcd.c b/drivers/usb/hcd.c
--- a/drivers/usb/hcd.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1712 +0,0 @@
-/*
- * (C) Copyright Linus Torvalds 1999
- * (C) Copyright Johannes Erdfelt 1999-2001
- * (C) Copyright Andreas Gal 1999
- * (C) Copyright Gregory P. Smith 1999
- * (C) Copyright Deti Fliegl 1999
- * (C) Copyright Randy Dunlap 2000
- * (C) Copyright David Brownell 2000-2002
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/uts.h>			/* for UTS_SYSNAME */
-
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-
-#include <linux/usb.h>
-#include "hcd.h"
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-
-
-// #define USB_BANDWIDTH_MESSAGES
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * USB Host Controller Driver framework
- *
- * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing
- * HCD-specific behaviors/bugs.
- *
- * This does error checks, tracks devices and urbs, and delegates to a
- * "hc_driver" only for code (and data) that really needs to know about
- * hardware differences.  That includes root hub registers, i/o queues,
- * and so on ... but as little else as possible.
- *
- * Shared code includes most of the "root hub" code (these are emulated,
- * though each HC's hardware works differently) and PCI glue, plus request
- * tracking overhead.  The HCD code should only block on spinlocks or on
- * hardware handshaking; blocking on software events (such as other kernel
- * threads releasing resources, or completing actions) is all generic.
- *
- * Happens the USB 2.0 spec says this would be invisible inside the "USBD",
- * and includes mostly a "HCDI" (HCD Interface) along with some APIs used
- * only by the hub driver ... and that neither should be seen or used by
- * usb client device drivers.
- *
- * Contributors of ideas or unattributed patches include: David Brownell,
- * Roman Weissgaerber, Rory Bolt, Greg Kroah-Hartman, ...
- *
- * HISTORY:
- * 2002-02-21	Pull in most of the usb_bus support from usb.c; some
- *		associated cleanup.  "usb_hcd" still != "usb_bus".
- * 2001-12-12	Initial patch version for Linux 2.5.1 kernel.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* host controllers we manage */
-LIST_HEAD (usb_bus_list);
-
-/* used when allocating bus numbers */
-#define USB_MAXBUS		64
-struct usb_busmap {
-	unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];
-};
-static struct usb_busmap busmap;
-
-/* used when updating list of hcds */
-DECLARE_MUTEX (usb_bus_list_lock);	/* exported only for usbfs */
-
-/* used when updating hcd data */
-static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
-
-static struct usb_operations hcd_operations;
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Sharable chunks of root hub code.
- */
-
-/*-------------------------------------------------------------------------*/
-
-#define KERNEL_REL	((LINUX_VERSION_CODE >> 16) & 0x0ff)
-#define KERNEL_VER	((LINUX_VERSION_CODE >> 8) & 0x0ff)
-
-/* usb 2.0 root hub device descriptor */
-static const u8 usb2_rh_dev_descriptor [18] = {
-	0x12,       /*  __u8  bLength; */
-	0x01,       /*  __u8  bDescriptorType; Device */
-	0x00, 0x02, /*  __u16 bcdUSB; v2.0 */
-
-	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,	    /*  __u8  bDeviceSubClass; */
-	0x01,       /*  __u8  bDeviceProtocol; [ usb 2.0 single TT ]*/
-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
-
-	0x00, 0x00, /*  __u16 idVendor; */
- 	0x00, 0x00, /*  __u16 idProduct; */
-	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
-
-	0x03,       /*  __u8  iManufacturer; */
-	0x02,       /*  __u8  iProduct; */
-	0x01,       /*  __u8  iSerialNumber; */
-	0x01        /*  __u8  bNumConfigurations; */
-};
-
-/* no usb 2.0 root hub "device qualifier" descriptor: one speed only */
-
-/* usb 1.1 root hub device descriptor */
-static const u8 usb11_rh_dev_descriptor [18] = {
-	0x12,       /*  __u8  bLength; */
-	0x01,       /*  __u8  bDescriptorType; Device */
-	0x10, 0x01, /*  __u16 bcdUSB; v1.1 */
-
-	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,	    /*  __u8  bDeviceSubClass; */
-	0x00,       /*  __u8  bDeviceProtocol; [ low/full speeds only ] */
-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
-
-	0x00, 0x00, /*  __u16 idVendor; */
- 	0x00, 0x00, /*  __u16 idProduct; */
-	KERNEL_VER, KERNEL_REL, /*  __u16 bcdDevice */
-
-	0x03,       /*  __u8  iManufacturer; */
-	0x02,       /*  __u8  iProduct; */
-	0x01,       /*  __u8  iSerialNumber; */
-	0x01        /*  __u8  bNumConfigurations; */
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-/* Configuration descriptor for all our root hubs */
-
-static const u8 rh_config_descriptor [] = {
-
-	/* one configuration */
-	0x09,       /*  __u8  bLength; */
-	0x02,       /*  __u8  bDescriptorType; Configuration */
-	0x19, 0x00, /*  __u16 wTotalLength; */
-	0x01,       /*  __u8  bNumInterfaces; (1) */
-	0x01,       /*  __u8  bConfigurationValue; */
-	0x00,       /*  __u8  iConfiguration; */
-	0x40,       /*  __u8  bmAttributes; 
-				 Bit 7: Bus-powered,
-				     6: Self-powered,
-				     5 Remote-wakwup,
-				     4..0: resvd */
-	0x00,       /*  __u8  MaxPower; */
-      
-	/* USB 1.1:
-	 * USB 2.0, single TT organization (mandatory):
-	 *	one interface, protocol 0
-	 *
-	 * USB 2.0, multiple TT organization (optional):
-	 *	two interfaces, protocols 1 (like single TT)
-	 *	and 2 (multiple TT mode) ... config is
-	 *	sometimes settable
-	 *	NOT IMPLEMENTED
-	 */
-
-	/* one interface */
-	0x09,       /*  __u8  if_bLength; */
-	0x04,       /*  __u8  if_bDescriptorType; Interface */
-	0x00,       /*  __u8  if_bInterfaceNumber; */
-	0x00,       /*  __u8  if_bAlternateSetting; */
-	0x01,       /*  __u8  if_bNumEndpoints; */
-	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,       /*  __u8  if_bInterfaceSubClass; */
-	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
-	0x00,       /*  __u8  if_iInterface; */
-     
-	/* one endpoint (status change endpoint) */
-	0x07,       /*  __u8  ep_bLength; */
-	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
- 	0x02, 0x00, /*  __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
-	0x0c        /*  __u8  ep_bInterval; (12ms -- usb 2.0 spec) */
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * helper routine for returning string descriptors in UTF-16LE
- * input can actually be ISO-8859-1; ASCII is its 7-bit subset
- */
-static int ascii2utf (char *s, u8 *utf, int utfmax)
-{
-	int retval;
-
-	for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
-		*utf++ = *s++;
-		*utf++ = 0;
-	}
-	return retval;
-}
-
-/*
- * rh_string - provides manufacturer, product and serial strings for root hub
- * @id: the string ID number (1: serial number, 2: product, 3: vendor)
- * @pci_desc: PCI device descriptor for the relevant HC
- * @type: string describing our driver 
- * @data: return packet in UTF-16 LE
- * @len: length of the return packet
- *
- * Produces either a manufacturer, product or serial number string for the
- * virtual root hub device.
- */
-static int rh_string (
-	int		id,
-	struct usb_hcd	*hcd,
-	u8		*data,
-	int		len
-) {
-	char buf [100];
-
-	// language ids
-	if (id == 0) {
-		*data++ = 4; *data++ = 3;	/* 4 bytes string data */
-		*data++ = 0; *data++ = 0;	/* some language id */
-		return 4;
-
-	// serial number
-	} else if (id == 1) {
-		strcpy (buf, hcd->bus_name);
-
-	// product description
-	} else if (id == 2) {
-                strcpy (buf, hcd->product_desc);
-
- 	// id 3 == vendor description
-	} else if (id == 3) {
-                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
-			hcd->description);
-
-	// unsupported IDs --> "protocol stall"
-	} else
-	    return 0;
-
-	data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
-	data [1] = 3;	/* type == string */
-	return data [0];
-}
-
-
-/* Root hub control transfers execute synchronously */
-static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
-{
-	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
- 	u16		typeReq, wValue, wIndex, wLength;
-	const u8	*bufp = 0;
-	u8		*ubuf = urb->transfer_buffer;
-	int		len = 0;
-
-	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
-	wValue   = le16_to_cpu (cmd->wValue);
-	wIndex   = le16_to_cpu (cmd->wIndex);
-	wLength  = le16_to_cpu (cmd->wLength);
-
-	if (wLength > urb->transfer_buffer_length)
-		goto error;
-
-	/* set up for success */
-	urb->status = 0;
-	urb->actual_length = wLength;
-	switch (typeReq) {
-
-	/* DEVICE REQUESTS */
-
-	case DeviceRequest | USB_REQ_GET_STATUS:
-		// DEVICE_REMOTE_WAKEUP
-		ubuf [0] = 1; // selfpowered
-		ubuf [1] = 0;
-			/* FALLTHROUGH */
-	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
-	case DeviceOutRequest | USB_REQ_SET_FEATURE:
-		dbg ("no device features yet yet");
-		break;
-	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-		ubuf [0] = 1;
-			/* FALLTHROUGH */
-	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
-		break;
-	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
-		switch (wValue & 0xff00) {
-		case USB_DT_DEVICE << 8:
-			if (hcd->driver->flags & HCD_USB2)
-				bufp = usb2_rh_dev_descriptor;
-			else if (hcd->driver->flags & HCD_USB11)
-				bufp = usb11_rh_dev_descriptor;
-			else
-				goto error;
-			len = 18;
-			break;
-		case USB_DT_CONFIG << 8:
-			bufp = rh_config_descriptor;
-			len = sizeof rh_config_descriptor;
-			break;
-		case USB_DT_STRING << 8:
-			urb->actual_length = rh_string (
-				wValue & 0xff, hcd,
-				ubuf, wLength);
-			break;
-		default:
-			goto error;
-		}
-		break;
-	case DeviceRequest | USB_REQ_GET_INTERFACE:
-		ubuf [0] = 0;
-			/* FALLTHROUGH */
-	case DeviceOutRequest | USB_REQ_SET_INTERFACE:
-		break;
-	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-		// wValue == urb->dev->devaddr
-		dbg ("%s root hub device address %d",
-			hcd->bus_name, wValue);
-		break;
-
-	/* INTERFACE REQUESTS (no defined feature/status flags) */
-
-	/* ENDPOINT REQUESTS */
-
-	case EndpointRequest | USB_REQ_GET_STATUS:
-		// ENDPOINT_HALT flag
-		ubuf [0] = 0;
-		ubuf [1] = 0;
-			/* FALLTHROUGH */
-	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
-	case EndpointOutRequest | USB_REQ_SET_FEATURE:
-		dbg ("no endpoint features yet");
-		break;
-
-	/* CLASS REQUESTS (and errors) */
-
-	default:
-		/* non-generic request */
-		urb->status = hcd->driver->hub_control (hcd,
-			typeReq, wValue, wIndex,
-			ubuf, wLength);
-		break;
-error:
-		/* "protocol stall" on error */
-		urb->status = -EPIPE;
-		dbg ("unsupported hub control message (maxchild %d)",
-				urb->dev->maxchild);
-	}
-	if (urb->status) {
-		urb->actual_length = 0;
-		dbg ("CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d",
-			typeReq, wValue, wIndex, wLength, urb->status);
-	}
-	if (bufp) {
-		if (urb->transfer_buffer_length < len)
-			len = urb->transfer_buffer_length;
-		urb->actual_length = len;
-		// always USB_DIR_IN, toward host
-		memcpy (ubuf, bufp, len);
-	}
-
-	/* any errors get returned through the urb completion */
-	usb_hcd_giveback_urb (hcd, urb);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Root Hub interrupt transfers are synthesized with a timer.
- * Completions are called in_interrupt() but not in_irq().
- */
-
-static void rh_report_status (unsigned long ptr);
-
-static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) 
-{
-	int	len = 1 + (urb->dev->maxchild / 8);
-
-	/* rh_timer protected by hcd_data_lock */
-	if (timer_pending (&hcd->rh_timer)
-			|| urb->status != -EINPROGRESS
-			|| !HCD_IS_RUNNING (hcd->state)
-			|| urb->transfer_buffer_length < len) {
-		dbg ("not queuing status urb, stat %d", urb->status);
-		return -EINVAL;
-	}
-
-	urb->hcpriv = hcd;	/* nonzero to indicate it's queued */
-	init_timer (&hcd->rh_timer);
-	hcd->rh_timer.function = rh_report_status;
-	hcd->rh_timer.data = (unsigned long) urb;
-	hcd->rh_timer.expires = jiffies
-		+ (HZ * (urb->interval < 30
-				? 30
-				: urb->interval)) / 1000;
-	add_timer (&hcd->rh_timer);
-	return 0;
-}
-
-/* timer callback */
-
-static void rh_report_status (unsigned long ptr)
-{
-	struct urb	*urb;
-	struct usb_hcd	*hcd;
-	int		length;
-	unsigned long	flags;
-
-	urb = (struct urb *) ptr;
-	spin_lock_irqsave (&urb->lock, flags);
-	if (!urb->dev) {
-		spin_unlock_irqrestore (&urb->lock, flags);
-		return;
-	}
-
-	hcd = urb->dev->bus->hcpriv;
-	if (urb->status == -EINPROGRESS) {
-		if (HCD_IS_RUNNING (hcd->state)) {
-			length = hcd->driver->hub_status_data (hcd,
-					urb->transfer_buffer);
-			spin_unlock_irqrestore (&urb->lock, flags);
-			if (length > 0) {
-				urb->actual_length = length;
-				urb->status = 0;
-				urb->complete (urb);
-			}
-			spin_lock_irqsave (&hcd_data_lock, flags);
-			urb->status = -EINPROGRESS;
-			if (HCD_IS_RUNNING (hcd->state)
-					&& rh_status_urb (hcd, urb) != 0) {
-				/* another driver snuck in? */
-				dbg ("%s, can't resubmit roothub status urb?",
-					hcd->bus_name);
-				spin_unlock_irqrestore (&hcd_data_lock, flags);
-				BUG ();
-			}
-			spin_unlock_irqrestore (&hcd_data_lock, flags);
-		} else
-			spin_unlock_irqrestore (&urb->lock, flags);
-	} else {
-		/* this urb's been unlinked */
-		urb->hcpriv = 0;
-		spin_unlock_irqrestore (&urb->lock, flags);
-
-		usb_hcd_giveback_urb (hcd, urb);
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
-{
-	if (usb_pipeint (urb->pipe)) {
-		int		retval;
-		unsigned long	flags;
-
-		spin_lock_irqsave (&hcd_data_lock, flags);
-		retval = rh_status_urb (hcd, urb);
-		spin_unlock_irqrestore (&hcd_data_lock, flags);
-		return retval;
-	}
-	if (usb_pipecontrol (urb->pipe))
-		return rh_call_control (hcd, urb);
-	else
-		return -EINVAL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb)
-{
-	unsigned long	flags;
-
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	del_timer_sync (&hcd->rh_timer);
-	hcd->rh_timer.data = 0;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-	/* we rely on RH callback code not unlinking its URB! */
-	usb_hcd_giveback_urb (hcd, urb);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* exported only within usbcore */
-void usb_bus_get (struct usb_bus *bus)
-{
-	atomic_inc (&bus->refcnt);
-}
-
-/* exported only within usbcore */
-void usb_bus_put (struct usb_bus *bus)
-{
-	if (atomic_dec_and_test (&bus->refcnt))
-		kfree (bus);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* shared initialization code */
-static void usb_init_bus (struct usb_bus *bus)
-{
-	memset (&bus->devmap, 0, sizeof(struct usb_devmap));
-
-#ifdef DEVNUM_ROUND_ROBIN
-	bus->devnum_next = 1;
-#endif /* DEVNUM_ROUND_ROBIN */
-
-	bus->root_hub = NULL;
-	bus->hcpriv = NULL;
-	bus->busnum = -1;
-	bus->bandwidth_allocated = 0;
-	bus->bandwidth_int_reqs  = 0;
-	bus->bandwidth_isoc_reqs = 0;
-
-	INIT_LIST_HEAD (&bus->bus_list);
-
-	atomic_set (&bus->refcnt, 1);
-}
-
-/**
- * usb_alloc_bus - creates a new USB host controller structure
- * @op: pointer to a struct usb_operations that this bus structure should use
- * Context: !in_interrupt()
- *
- * Creates a USB host controller bus structure with the specified 
- * usb_operations and initializes all the necessary internal objects.
- *
- * If no memory is available, NULL is returned.
- *
- * The caller should call usb_free_bus() when it is finished with the structure.
- */
-struct usb_bus *usb_alloc_bus (struct usb_operations *op)
-{
-	struct usb_bus *bus;
-
-	bus = kmalloc (sizeof *bus, GFP_KERNEL);
-	if (!bus)
-		return NULL;
-	usb_init_bus (bus);
-	bus->op = op;
-	return bus;
-}
-EXPORT_SYMBOL (usb_alloc_bus);
-
-/**
- * usb_free_bus - frees the memory used by a bus structure
- * @bus: pointer to the bus to free
- *
- * To be invoked by a HCD, only as the last step of decoupling from
- * hardware.  It is an error to call this if the reference count is
- * anything but one.  That would indicate that some system component
- * did not correctly shut down, and thought the hardware was still
- * accessible.
- */
-void usb_free_bus (struct usb_bus *bus)
-{
-	if (!bus)
-		return;
-	if (atomic_read (&bus->refcnt) != 1)
-		err ("usb_free_bus #%d, count != 1", bus->busnum);
-	usb_bus_put (bus);
-}
-EXPORT_SYMBOL (usb_free_bus);
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * usb_register_bus - registers the USB host controller with the usb core
- * @bus: pointer to the bus to register
- * Context: !in_interrupt()
- *
- * Assigns a bus number, and links the controller into usbcore data
- * structures so that it can be seen by scanning the bus list.
- */
-void usb_register_bus(struct usb_bus *bus)
-{
-	int busnum;
-
-	down (&usb_bus_list_lock);
-	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
-	if (busnum < USB_MAXBUS) {
-		set_bit (busnum, busmap.busmap);
-		bus->busnum = busnum;
-	} else
-		warn ("too many buses");
-
-	usb_bus_get (bus);
-
-	/* Add it to the list of buses */
-	list_add (&bus->bus_list, &usb_bus_list);
-	up (&usb_bus_list_lock);
-
-	usbfs_add_bus (bus);
-
-	info ("new USB bus registered, assigned bus number %d", bus->busnum);
-}
-EXPORT_SYMBOL (usb_register_bus);
-
-/**
- * usb_deregister_bus - deregisters the USB host controller
- * @bus: pointer to the bus to deregister
- * Context: !in_interrupt()
- *
- * Recycles the bus number, and unlinks the controller from usbcore data
- * structures so that it won't be seen by scanning the bus list.
- */
-void usb_deregister_bus (struct usb_bus *bus)
-{
-	info ("USB bus %d deregistered", bus->busnum);
-
-	/*
-	 * NOTE: make sure that all the devices are removed by the
-	 * controller code, as well as having it call this when cleaning
-	 * itself up
-	 */
-	down (&usb_bus_list_lock);
-	list_del (&bus->bus_list);
-	up (&usb_bus_list_lock);
-
-	usbfs_remove_bus (bus);
-
-	clear_bit (bus->busnum, busmap.busmap);
-
-	usb_bus_put (bus);
-}
-EXPORT_SYMBOL (usb_deregister_bus);
-
-/**
- * usb_register_root_hub - called by HCD to register its root hub 
- * @usb_dev: the usb root hub device to be registered.
- * @parent_dev: the parent device of this root hub.
- *
- * The USB host controller calls this function to register the root hub
- * properly with the USB subsystem.  It sets up the device properly in
- * the driverfs tree, and then calls usb_new_device() to register the
- * usb device.
- */
-int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
-{
-	int retval;
-
-	usb_dev->dev.parent = parent_dev;
-	strcpy (&usb_dev->dev.name[0], "usb_name");
-	strcpy (&usb_dev->dev.bus_id[0], "usb_bus");
-	retval = usb_new_device (usb_dev);
-	if (retval)
-		put_device (&usb_dev->dev);
-	return retval;
-}
-EXPORT_SYMBOL (usb_register_root_hub);
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * usb_calc_bus_time:
- * Returns approximate bus time in nanoseconds for a periodic transaction.
- * See USB 2.0 spec section 5.11.3
- */
-static long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount)
-{
-	unsigned long	tmp;
-
-	switch (speed) {
-	case USB_SPEED_LOW: 	/* INTR only */
-		if (is_input) {
-			tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
-		} else {
-			tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
-		}
-	case USB_SPEED_FULL:	/* ISOC or INTR */
-		if (isoc) {
-			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
-		} else {
-			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (9107L + BW_HOST_DELAY + tmp);
-		}
-	case USB_SPEED_HIGH:	/* ISOC or INTR */
-		// FIXME merge from EHCI code; caller will need to handle
-		// each part of a split separately.
-		return 0;
-	default:
-		dbg ("bogus device speed!");
-		return -1;
-	}
-}
-
-/*
- * usb_check_bandwidth():
- *
- * old_alloc is from host_controller->bandwidth_allocated in microseconds;
- * bustime is from calc_bus_time(), but converted to microseconds.
- *
- * returns <bustime in us> if successful,
- * or -ENOSPC if bandwidth request fails.
- *
- * FIXME:
- * This initial implementation does not use Endpoint.bInterval
- * in managing bandwidth allocation.
- * It probably needs to be expanded to use Endpoint.bInterval.
- * This can be done as a later enhancement (correction).
- *
- * This will also probably require some kind of
- * frame allocation tracking...meaning, for example,
- * that if multiple drivers request interrupts every 10 USB frames,
- * they don't all have to be allocated at
- * frame numbers N, N+10, N+20, etc.  Some of them could be at
- * N+11, N+21, N+31, etc., and others at
- * N+12, N+22, N+32, etc.
- *
- * Similarly for isochronous transfers...
- *
- * Individual HCDs can schedule more directly ... this logic
- * is not correct for high speed transfers.
- */
-int usb_check_bandwidth (struct usb_device *dev, struct urb *urb)
-{
-	unsigned int	pipe = urb->pipe;
-	long		bustime;
-	int		is_in = usb_pipein (pipe);
-	int		is_iso = usb_pipeisoc (pipe);
-	int		old_alloc = dev->bus->bandwidth_allocated;
-	int		new_alloc;
-
-
-	bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso,
-			usb_maxpacket (dev, pipe, !is_in)));
-	if (is_iso)
-		bustime /= urb->number_of_packets;
-
-	new_alloc = old_alloc + (int) bustime;
-	if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) {
-#ifdef	DEBUG
-		char	*mode = 
-#ifdef CONFIG_USB_BANDWIDTH
-			"";
-#else
-			"would have ";
-#endif
-		dbg ("usb_check_bandwidth %sFAILED: %d + %ld = %d usec",
-			mode, old_alloc, bustime, new_alloc);
-#endif
-#ifdef CONFIG_USB_BANDWIDTH
-		bustime = -ENOSPC;	/* report error */
-#endif
-	}
-
-	return bustime;
-}
-EXPORT_SYMBOL (usb_check_bandwidth);
-
-
-/**
- * usb_claim_bandwidth - records bandwidth for a periodic transfer
- * @dev: source/target of request
- * @urb: request (urb->dev == dev)
- * @bustime: bandwidth consumed, in (average) microseconds per frame
- * @isoc: true iff the request is isochronous
- *
- * Bus bandwidth reservations are recorded purely for diagnostic purposes.
- * HCDs are expected not to overcommit periodic bandwidth, and to record such
- * reservations whenever endpoints are added to the periodic schedule.
- *
- * FIXME averaging per-frame is suboptimal.  Better to sum over the HCD's
- * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable
- * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how
- * large its periodic schedule is.
- */
-void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
-{
-	dev->bus->bandwidth_allocated += bustime;
-	if (isoc)
-		dev->bus->bandwidth_isoc_reqs++;
-	else
-		dev->bus->bandwidth_int_reqs++;
-	urb->bandwidth = bustime;
-
-#ifdef USB_BANDWIDTH_MESSAGES
-	dbg ("bandwidth alloc increased by %d (%s) to %d for %d requesters",
-		bustime,
-		isoc ? "ISOC" : "INTR",
-		dev->bus->bandwidth_allocated,
-		dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
-#endif
-}
-EXPORT_SYMBOL (usb_claim_bandwidth);
-
-
-/**
- * usb_release_bandwidth - reverses effect of usb_claim_bandwidth()
- * @dev: source/target of request
- * @urb: request (urb->dev == dev)
- * @isoc: true iff the request is isochronous
- *
- * This records that previously allocated bandwidth has been released.
- * Bandwidth is released when endpoints are removed from the host controller's
- * periodic schedule.
- */
-void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc)
-{
-	dev->bus->bandwidth_allocated -= urb->bandwidth;
-	if (isoc)
-		dev->bus->bandwidth_isoc_reqs--;
-	else
-		dev->bus->bandwidth_int_reqs--;
-
-#ifdef USB_BANDWIDTH_MESSAGES
-	dbg ("bandwidth alloc reduced by %d (%s) to %d for %d requesters",
-		urb->bandwidth,
-		isoc ? "ISOC" : "INTR",
-		dev->bus->bandwidth_allocated,
-		dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs);
-#endif
-	urb->bandwidth = 0;
-}
-EXPORT_SYMBOL (usb_release_bandwidth);
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PCI
-
-/* PCI-based HCs are normal, but custom bus glue should be ok */
-
-static void hcd_irq (int irq, void *__hcd, struct pt_regs *r);
-static void hc_died (struct usb_hcd *hcd);
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_hcd_pci_probe - initialize PCI-based HCDs
- * @dev: USB Host Controller being probed
- * @id: pci hotplug id connecting controller to HCD framework
- * Context: !in_interrupt()
- *
- * Allocates basic PCI resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
- */
-int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-	struct hc_driver	*driver;
-	unsigned long		resource, len;
-	void			*base;
-	u8			latency, limit;
-	struct usb_hcd		*hcd;
-	int			retval, region;
-	char			buf [8], *bufp = buf;
-
-	if (!id || !(driver = (struct hc_driver *) id->driver_data))
-		return -EINVAL;
-
-	if (pci_enable_device (dev) < 0)
-		return -ENODEV;
-	
-        if (!dev->irq) {
-        	err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
-			dev->slot_name);
-   	        return -ENODEV;
-        }
-	
-	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
-		region = 0;
-		resource = pci_resource_start (dev, 0);
-		len = pci_resource_len (dev, 0);
-		if (!request_mem_region (resource, len, driver->description)) {
-			dbg ("controller already in use");
-			return -EBUSY;
-		}
-		base = ioremap_nocache (resource, len);
-		if (base == NULL) {
-			dbg ("error mapping memory");
-			retval = -EFAULT;
-clean_1:
-			release_mem_region (resource, len);
-			err ("init %s fail, %d", dev->slot_name, retval);
-			return retval;
-		}
-
-	} else { 				// UHCI
-		resource = len = 0;
-		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
-			if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
-				continue;
-
-			resource = pci_resource_start (dev, region);
-			len = pci_resource_len (dev, region);
-			if (request_region (resource, len,
-					driver->description))
-				break;
-		}
-		if (region == PCI_ROM_RESOURCE) {
-			dbg ("no i/o regions available");
-			return -EBUSY;
-		}
-		base = (void *) resource;
-	}
-
-	// driver->start(), later on, will transfer device from
-	// control by SMM/BIOS to control by Linux (if needed)
-
-	pci_set_master (dev);
-	hcd = driver->hcd_alloc ();
-	if (hcd == NULL){
-		dbg ("hcd alloc fail");
-		retval = -ENOMEM;
-clean_2:
-		if (driver->flags & HCD_MEMORY) {
-			iounmap (base);
-			goto clean_1;
-		} else {
-			release_region (resource, len);
-			err ("init %s fail, %d", dev->slot_name, retval);
-			return retval;
-		}
-	}
-	pci_set_drvdata(dev, hcd);
-	hcd->driver = driver;
-	hcd->description = driver->description;
-	hcd->pdev = dev;
-	info ("%s @ %s, %s", hcd->description,  dev->slot_name, dev->name);
-
-	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-	if (latency) {
-		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
-		if (limit && limit < latency) {
-			dbg ("PCI latency reduced to max %d", limit);
-			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
-		}
-	}
-
-#ifndef __sparc__
-	sprintf (buf, "%d", dev->irq);
-#else
-	bufp = __irq_itoa(dev->irq);
-#endif
-	if (request_irq (dev->irq, hcd_irq, SA_SHIRQ, hcd->description, hcd)
-			!= 0) {
-		err ("request interrupt %s failed", bufp);
-		retval = -EBUSY;
-		driver->hcd_free (hcd);
-		goto clean_2;
-	}
-	hcd->irq = dev->irq;
-
-	hcd->regs = base;
-	hcd->region = region;
-	info ("irq %s, %s %p", bufp,
-		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
-		base);
-
-	usb_init_bus (&hcd->self);
-	hcd->self.op = &hcd_operations;
-	hcd->self.hcpriv = (void *) hcd;
-	hcd->bus = &hcd->self;
-	hcd->bus_name = dev->slot_name;
-	hcd->product_desc = dev->name;
-
-	INIT_LIST_HEAD (&hcd->dev_list);
-
-	usb_register_bus (&hcd->self);
-
-	if ((retval = driver->start (hcd)) < 0)
-		usb_hcd_pci_remove (dev);
-
-	return retval;
-} 
-EXPORT_SYMBOL (usb_hcd_pci_probe);
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_pci_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- * Store this function in the HCD's struct pci_driver as remove().
- */
-void usb_hcd_pci_remove (struct pci_dev *dev)
-{
-	struct usb_hcd		*hcd;
-	struct usb_device	*hub;
-
-	hcd = pci_get_drvdata(dev);
-	if (!hcd)
-		return;
-	info ("remove: %s, state %x", hcd->bus_name, hcd->state);
-
-	if (in_interrupt ()) BUG ();
-
-	hub = hcd->bus->root_hub;
-	hcd->state = USB_STATE_QUIESCING;
-
-	dbg ("%s: roothub graceful disconnect", hcd->bus_name);
-	usb_disconnect (&hub);
-	// usb_disconnect (&hcd->bus->root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd->state = USB_STATE_HALT;
-
-	free_irq (hcd->irq, hcd);
-	if (hcd->driver->flags & HCD_MEMORY) {
-		iounmap (hcd->regs);
-		release_mem_region (pci_resource_start (dev, 0),
-			pci_resource_len (dev, 0));
-	} else {
-		release_region (pci_resource_start (dev, hcd->region),
-			pci_resource_len (dev, hcd->region));
-	}
-
-	usb_deregister_bus (hcd->bus);
-	if (atomic_read (&hcd->self.refcnt) != 1)
-		err ("usb_hcd_pci_remove %s, count != 1", hcd->bus_name);
-	hcd->bus = NULL;
-
-	hcd->driver->hcd_free (hcd);
-}
-EXPORT_SYMBOL (usb_hcd_pci_remove);
-
-
-#ifdef	CONFIG_PM
-
-/*
- * Some "sleep" power levels imply updating struct usb_driver
- * to include a callback asking hcds to do their bit by checking
- * if all the drivers can suspend.  Gets involved with remote wakeup.
- *
- * If there are pending urbs, then HCs will need to access memory,
- * causing extra power drain.  New sleep()/wakeup() PM calls might
- * be needed, beyond PCI suspend()/resume().  The root hub timer
- * still be accessing memory though ...
- *
- * FIXME:  USB should have some power budgeting support working with
- * all kinds of hubs.
- *
- * FIXME:  This assumes only D0->D3 suspend and D3->D0 resume.
- * D1 and D2 states should do something, yes?
- *
- * FIXME:  Should provide generic enable_wake(), calling pci_enable_wake()
- * for all supported states, so that USB remote wakeup can work for any
- * devices that support it (and are connected via powered hubs).
- *
- * FIXME:  resume doesn't seem to work right any more...
- */
-
-
-// 2.4 kernels have issued concurrent resumes (w/APM)
-// we defend against that error; PCI doesn't yet.
-
-/**
- * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
- * @dev: USB Host Controller being suspended
- *
- * Store this function in the HCD's struct pci_driver as suspend().
- */
-int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
-{
-	struct usb_hcd		*hcd;
-	int			retval;
-
-	hcd = pci_get_drvdata(dev);
-	info ("suspend %s to state %d", hcd->bus_name, state);
-
-	pci_save_state (dev, hcd->pci_state);
-
-	// FIXME for all connected devices, leaf-to-root:
-	// driver->suspend()
-	// proposed "new 2.5 driver model" will automate that
-
-	/* driver may want to disable DMA etc */
-	retval = hcd->driver->suspend (hcd, state);
-	hcd->state = USB_STATE_SUSPENDED;
-
- 	pci_set_power_state (dev, state);
-	return retval;
-}
-EXPORT_SYMBOL (usb_hcd_pci_suspend);
-
-/**
- * usb_hcd_pci_resume - power management resume of a PCI-based HCD
- * @dev: USB Host Controller being resumed
- *
- * Store this function in the HCD's struct pci_driver as resume().
- */
-int usb_hcd_pci_resume (struct pci_dev *dev)
-{
-	struct usb_hcd		*hcd;
-	int			retval;
-
-	hcd = pci_get_drvdata(dev);
-	info ("resume %s", hcd->bus_name);
-
-	/* guard against multiple resumes (APM bug?) */
-	atomic_inc (&hcd->resume_count);
-	if (atomic_read (&hcd->resume_count) != 1) {
-		err ("concurrent PCI resumes for %s", hcd->bus_name);
-		retval = 0;
-		goto done;
-	}
-
-	retval = -EBUSY;
-	if (hcd->state != USB_STATE_SUSPENDED) {
-		dbg ("can't resume, not suspended!");
-		goto done;
-	}
-	hcd->state = USB_STATE_RESUMING;
-
-	pci_set_power_state (dev, 0);
-	pci_restore_state (dev, hcd->pci_state);
-
-	retval = hcd->driver->resume (hcd);
-	if (!HCD_IS_RUNNING (hcd->state)) {
-		dbg ("resume %s failure, retval %d", hcd->bus_name, retval);
-		hc_died (hcd);
-// FIXME:  recover, reset etc.
-	} else {
-		// FIXME for all connected devices, root-to-leaf:
-		// driver->resume ();
-		// proposed "new 2.5 driver model" will automate that
-	}
-
-done:
-	atomic_dec (&hcd->resume_count);
-	return retval;
-}
-EXPORT_SYMBOL (usb_hcd_pci_resume);
-
-#endif	/* CONFIG_PM */
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Generic HC operations.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* called from khubd, or root hub init threads for hcd-private init */
-static int hcd_alloc_dev (struct usb_device *udev)
-{
-	struct hcd_dev		*dev;
-	struct usb_hcd		*hcd;
-	unsigned long		flags;
-
-	if (!udev || udev->hcpriv)
-		return -EINVAL;
-	if (!udev->bus || !udev->bus->hcpriv)
-		return -ENODEV;
-	hcd = udev->bus->hcpriv;
-	if (hcd->state == USB_STATE_QUIESCING)
-		return -ENOLINK;
-
-	dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL);
-	if (dev == NULL)
-		return -ENOMEM;
-	memset (dev, 0, sizeof *dev);
-
-	INIT_LIST_HEAD (&dev->dev_list);
-	INIT_LIST_HEAD (&dev->urb_list);
-
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	list_add (&dev->dev_list, &hcd->dev_list);
-	// refcount is implicit
-	udev->hcpriv = dev;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void hc_died (struct usb_hcd *hcd)
-{
-	struct list_head	*devlist, *urblist;
-	struct hcd_dev		*dev;
-	struct urb		*urb;
-	unsigned long		flags;
-	
-	/* flag every pending urb as done */
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	list_for_each (devlist, &hcd->dev_list) {
-		dev = list_entry (devlist, struct hcd_dev, dev_list);
-		list_for_each (urblist, &dev->urb_list) {
-			urb = list_entry (urblist, struct urb, urb_list);
-			dbg ("shutdown %s urb %p pipe %x, current status %d",
-				hcd->bus_name, urb, urb->pipe, urb->status);
-			if (urb->status == -EINPROGRESS)
-				urb->status = -ESHUTDOWN;
-		}
-	}
-	urb = (struct urb *) hcd->rh_timer.data;
-	if (urb)
-		urb->status = -ESHUTDOWN;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-	if (urb)
-		rh_status_dequeue (hcd, urb);
-	hcd->driver->stop (hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* may be called in any context with a valid urb->dev usecount */
-/* caller surrenders "ownership" of urb (and chain at urb->next).  */
-
-static int hcd_submit_urb (struct urb *urb, int mem_flags)
-{
-	int			status;
-	struct usb_hcd		*hcd;
-	struct hcd_dev		*dev;
-	unsigned long		flags;
-	int			pipe, temp;
-
-	if (!urb || urb->hcpriv || !urb->complete)
-		return -EINVAL;
-
-	urb->status = -EINPROGRESS;
-	urb->actual_length = 0;
-	INIT_LIST_HEAD (&urb->urb_list);
-
-	if (!urb->dev || !urb->dev->bus || urb->dev->devnum <= 0)
-		return -ENODEV;
-	hcd = urb->dev->bus->hcpriv;
-	dev = urb->dev->hcpriv;
-	if (!hcd || !dev)
-		return -ENODEV;
-
-	/* can't submit new urbs when quiescing, halted, ... */
-	if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state))
-		return -ESHUTDOWN;
-	pipe = urb->pipe;
-	temp = usb_pipetype (urb->pipe);
-	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe),
-			usb_pipeout (pipe)))
-		return -EPIPE;
-
-#ifdef DEBUG
-	{
-	unsigned int	orig_flags = urb->transfer_flags;
-	unsigned int	allowed;
-
-	/* enforce simple/standard policy */
-	allowed = USB_ASYNC_UNLINK;	// affects later unlinks
-	allowed |= USB_NO_FSBR;		// only affects UHCI
-	switch (temp) {
-	case PIPE_CONTROL:
-		allowed |= USB_DISABLE_SPD;
-		break;
-	case PIPE_BULK:
-		allowed |= USB_DISABLE_SPD | USB_QUEUE_BULK
-				| USB_ZERO_PACKET | URB_NO_INTERRUPT;
-		break;
-	case PIPE_INTERRUPT:
-		allowed |= USB_DISABLE_SPD;
-		break;
-	case PIPE_ISOCHRONOUS:
-		allowed |= USB_ISO_ASAP;
-		break;
-	}
-	urb->transfer_flags &= allowed;
-
-	/* warn if submitter gave bogus flags */
-	if (urb->transfer_flags != orig_flags)
-		err ("BOGUS urb flags, %x --> %x",
-			orig_flags, urb->transfer_flags);
-	}
-#endif
-	/*
-	 * Force periodic transfer intervals to be legal values that are
-	 * a power of two (so HCDs don't need to).
-	 *
-	 * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
-	 * supports different values... this uses EHCI/UHCI defaults (and
-	 * EHCI can use smaller non-default values).
-	 */
-	switch (temp) {
-	case PIPE_ISOCHRONOUS:
-	case PIPE_INTERRUPT:
-		/* too small? */
-		if (urb->interval <= 0)
-			return -EINVAL;
-		/* too big? */
-		switch (urb->dev->speed) {
-		case USB_SPEED_HIGH:	/* units are microframes */
-			// NOTE usb handles 2^15
-			if (urb->interval > (1024 * 8))
-				urb->interval = 1024 * 8;
-			temp = 1024 * 8;
-			break;
-		case USB_SPEED_FULL:	/* units are frames/msec */
-		case USB_SPEED_LOW:
-			if (temp == PIPE_INTERRUPT) {
-				if (urb->interval > 255)
-					return -EINVAL;
-				// NOTE ohci only handles up to 32
-				temp = 128;
-			} else {
-				if (urb->interval > 1024)
-					urb->interval = 1024;
-				// NOTE usb and ohci handle up to 2^15
-				temp = 1024;
-			}
-		default:
-			return -EINVAL;
-		}
-		/* power of two? */
-		while (temp > urb->interval)
-			temp >>= 1;
-		urb->interval = temp;
-	}
-
-	/*
-	 * FIXME:  make urb timeouts be generic, keeping the HCD cores
-	 * as simple as possible.
-	 */
-
-	// NOTE:  a generic device/urb monitoring hook would go here.
-	// hcd_monitor_hook(MONITOR_URB_SUBMIT, urb)
-	// It would catch submission paths for all urbs.
-
-	/* increment the reference count of the urb, as we now also control it. */
-	urb = usb_get_urb(urb);
-
-	/*
-	 * Atomically queue the urb,  first to our records, then to the HCD.
-	 * Access to urb->status is controlled by urb->lock ... changes on
-	 * i/o completion (normal or fault) or unlinking.
-	 */
-
-	// FIXME:  verify that quiescing hc works right (RH cleans up)
-
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) {
-		usb_inc_dev_use (urb->dev);
-		list_add (&urb->urb_list, &dev->urb_list);
-		status = 0;
-	} else {
-		INIT_LIST_HEAD (&urb->urb_list);
-		status = -ESHUTDOWN;
-	}
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-	if (!status) {
-		if (urb->dev == hcd->bus->root_hub)
-			status = rh_urb_enqueue (hcd, urb);
-		else
-			status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
-	}
-	if (status) {
-		if (urb->dev) {
-			urb->status = status;
-			usb_hcd_giveback_urb (hcd, urb);
-		}
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* called in any context */
-static int hcd_get_frame_number (struct usb_device *udev)
-{
-	struct usb_hcd	*hcd = (struct usb_hcd *)udev->bus->hcpriv;
-	return hcd->driver->get_frame_number (hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-struct completion_splice {		// modified urb context:
-	/* did we complete? */
-	int			done;
-
-	/* original urb data */
-	void			(*complete)(struct urb *);
-	void			*context;
-};
-
-static void unlink_complete (struct urb *urb)
-{
-	struct completion_splice	*splice;
-
-	splice = (struct completion_splice *) urb->context;
-
-	/* issue original completion call */
-	urb->complete = splice->complete;
-	urb->context = splice->context;
-	urb->complete (urb);
-
-	splice->done = 1;
-}
-
-/*
- * called in any context; note ASYNC_UNLINK restrictions
- *
- * caller guarantees urb won't be recycled till both unlink()
- * and the urb's completion function return
- */
-static int hcd_unlink_urb (struct urb *urb)
-{
-	struct hcd_dev			*dev;
-	struct usb_hcd			*hcd = 0;
-	unsigned long			flags;
-	struct completion_splice	splice;
-	int				retval;
-
-	if (!urb)
-		return -EINVAL;
-
-	/*
-	 * we contend for urb->status with the hcd core,
-	 * which changes it while returning the urb.
-	 *
-	 * Caller guaranteed that the urb pointer hasn't been freed, and
-	 * that it was submitted.  But as a rule it can't know whether or
-	 * not it's already been unlinked ... so we respect the reversed
-	 * lock sequence needed for the usb_hcd_giveback_urb() code paths
-	 * (urb lock, then hcd_data_lock) in case some other CPU is now
-	 * unlinking it.
-	 */
-	spin_lock_irqsave (&urb->lock, flags);
-	spin_lock (&hcd_data_lock);
-	if (!urb->hcpriv || urb->transfer_flags & USB_TIMEOUT_KILLED) {
-		retval = -EINVAL;
-		goto done;
-	}
-
-	if (!urb->dev || !urb->dev->bus) {
-		retval = -ENODEV;
-		goto done;
-	}
-
-	/* giveback clears dev; non-null means it's linked at this level */
-	dev = urb->dev->hcpriv;
-	hcd = urb->dev->bus->hcpriv;
-	if (!dev || !hcd) {
-		retval = -ENODEV;
-		goto done;
-	}
-
-	/* For non-periodic transfers, any status except -EINPROGRESS means
-	 * the HCD has already started to unlink this URB from the hardware.
-	 * In that case, there's no more work to do.
-	 *
-	 * For periodic transfers, this is the only way to trigger unlinking
-	 * from the hardware.  Since we (currently) overload urb->status to
-	 * tell the driver to unlink, error status might get clobbered ...
-	 * unless that transfer hasn't yet restarted.  One such case is when
-	 * the URB gets unlinked from its completion handler.
-	 *
-	 * FIXME use an URB_UNLINKED flag to match URB_TIMEOUT_KILLED
-	 */
-	switch (usb_pipetype (urb->pipe)) {
-	case PIPE_CONTROL:
-	case PIPE_BULK:
-		if (urb->status != -EINPROGRESS) {
-			retval = 0;
-			goto done;
-		}
-	}
-
-	/* maybe set up to block on completion notification */
-	if ((urb->transfer_flags & USB_TIMEOUT_KILLED))
-		urb->status = -ETIMEDOUT;
-	else if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
-		if (in_interrupt ()) {
-			dbg ("non-async unlink in_interrupt");
-			retval = -EWOULDBLOCK;
-			goto done;
-		}
-		/* synchronous unlink: block till we see the completion */
-		splice.done = 0;
-		splice.complete = urb->complete;
-		splice.context = urb->context;
-		urb->complete = unlink_complete;
-		urb->context = &splice;
-		urb->status = -ENOENT;
-	} else {
-		/* asynchronous unlink */
-		urb->status = -ECONNRESET;
-	}
-	spin_unlock (&hcd_data_lock);
-	spin_unlock_irqrestore (&urb->lock, flags);
-
-	if (urb == (struct urb *) hcd->rh_timer.data) {
-		rh_status_dequeue (hcd, urb);
-		retval = 0;
-	} else {
-		retval = hcd->driver->urb_dequeue (hcd, urb);
-// FIXME:  if retval and we tried to splice, whoa!!
-if (retval && urb->status == -ENOENT) err ("whoa! retval %d", retval);
-	}
-
-    	/* block till giveback, if needed */
-	if (!(urb->transfer_flags & (USB_ASYNC_UNLINK|USB_TIMEOUT_KILLED))
-			&& HCD_IS_RUNNING (hcd->state)
-			&& !retval) {
-		while (!splice.done) {
-			set_current_state (TASK_UNINTERRUPTIBLE);
-			schedule_timeout ((2/*msec*/ * HZ) / 1000);
-			dbg ("%s: wait for giveback urb %p",
-				hcd->bus_name, urb);
-		}
-	} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
-		return -EINPROGRESS;
-	}
-	goto bye;
-done:
-	spin_unlock (&hcd_data_lock);
-	spin_unlock_irqrestore (&urb->lock, flags);
-bye:
-	if (retval)
-		dbg ("%s: hcd_unlink_urb fail %d",
-		    hcd ? hcd->bus_name : "(no bus?)",
-		    retval);
-	return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup */
-
-// FIXME:  likely best to have explicit per-setting (config+alt)
-// setup primitives in the usbcore-to-hcd driver API, so nothing
-// is implicit.  kernel 2.5 needs a bunch of config cleanup...
-
-static int hcd_free_dev (struct usb_device *udev)
-{
-	struct hcd_dev		*dev;
-	struct usb_hcd		*hcd;
-	unsigned long		flags;
-
-	if (!udev || !udev->hcpriv)
-		return -EINVAL;
-
-	if (!udev->bus || !udev->bus->hcpriv)
-		return -ENODEV;
-
-	// should udev->devnum == -1 ??
-
-	dev = udev->hcpriv;
-	hcd = udev->bus->hcpriv;
-
-	/* device driver problem with refcounts? */
-	if (!list_empty (&dev->urb_list)) {
-		dbg ("free busy dev, %s devnum %d (bug!)",
-			hcd->bus_name, udev->devnum);
-		return -EINVAL;
-	}
-
-	hcd->driver->free_config (hcd, udev);
-
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	list_del (&dev->dev_list);
-	udev->hcpriv = NULL;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-	kfree (dev);
-	return 0;
-}
-
-static struct usb_operations hcd_operations = {
-	allocate:		hcd_alloc_dev,
-	get_frame_number:	hcd_get_frame_number,
-	submit_urb:		hcd_submit_urb,
-	unlink_urb:		hcd_unlink_urb,
-	deallocate:		hcd_free_dev,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static void hcd_irq (int irq, void *__hcd, struct pt_regs * r)
-{
-	struct usb_hcd		*hcd = __hcd;
-	int			start = hcd->state;
-
-	if (unlikely (hcd->state == USB_STATE_HALT))	/* irq sharing? */
-		return;
-
-	hcd->driver->irq (hcd);
-	if (hcd->state != start && hcd->state == USB_STATE_HALT)
-		hc_died (hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * usb_hcd_giveback_urb - return URB from HCD to device driver
- * @hcd: host controller returning the URB
- * @urb: urb being returned to the USB device driver.
- * Context: in_interrupt()
- *
- * This hands the URB from HCD to its USB device driver, using its
- * completion function.  The HCD has freed all per-urb resources
- * (and is done using urb->hcpriv).  It also released all HCD locks;
- * the device driver won't cause deadlocks if it resubmits this URB,
- * and won't confuse things by modifying and resubmitting this one.
- * Bandwidth and other resources will be deallocated.
- *
- * HCDs must not use this for periodic URBs that are still scheduled
- * and will be reissued.  They should just call their completion handlers
- * until the urb is returned to the device driver by unlinking.
- *
- * In common cases, urb->next will be submitted before the completion
- * function gets called.  That's not done if the URB includes error
- * status (including unlinking).
- */
-void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
-{
-	unsigned long		flags;
-	struct usb_device	*dev;
-
-	/* Release periodic transfer bandwidth */
-	if (urb->bandwidth)
-		usb_release_bandwidth (urb->dev, urb,
-			usb_pipeisoc (urb->pipe));
-
-	/* clear all state linking urb to this dev (and hcd) */
-
-	spin_lock_irqsave (&hcd_data_lock, flags);
-	list_del_init (&urb->urb_list);
-	dev = urb->dev;
-	urb->dev = NULL;
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
-
-	// NOTE:  a generic device/urb monitoring hook would go here.
-	// hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
-	// It would catch exit/unlink paths for all urbs, but non-exit
-	// completions for periodic urbs need hooks inside the HCD.
-	// hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
-
-	if (urb->status)
-		dbg ("giveback urb %p status %d len %d",
-			urb, urb->status, urb->actual_length);
-
-	/* if no error, make sure urb->next progresses */
-	else if (urb->next) {
-		int 	status;
-
-		status = usb_submit_urb (urb->next, GFP_ATOMIC);
-		if (status) {
-			dbg ("urb %p chain fail, %d", urb->next, status);
-			urb->next->status = -ENOTCONN;
-		}
-
-		/* HCDs never modify the urb->next chain, and only use it here,
-		 * so that if urb->complete sees an URB there with -ENOTCONN,
-		 * it knows the driver chained it but it couldn't be submitted.
-		 */
-	}
-
-	/* pass ownership to the completion handler */
-	usb_dec_dev_use (dev);
-	urb->complete (urb);
-	usb_put_urb (urb);
-}
-EXPORT_SYMBOL (usb_hcd_giveback_urb);
diff -Nru a/drivers/usb/hcd.h b/drivers/usb/hcd.h
--- a/drivers/usb/hcd.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2001-2002 by David Brownell
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifdef __KERNEL__
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * USB Host Controller Driver (usb_hcd) framework
- *
- * Since "struct usb_bus" is so thin, you can't share much code in it.
- * This framework is a layer over that, and should be more sharable.
- */
-
-/*-------------------------------------------------------------------------*/
-
-struct usb_hcd {	/* usb_bus.hcpriv points to this */
-
-	/*
-	 * housekeeping
-	 */
-	struct usb_bus		*bus;		/* FIXME only use "self" */
-	struct usb_bus		self;		/* hcd is-a bus */
-
-	const char		*bus_name;
-	const char		*product_desc;	/* product/vendor string */
-	const char		*description;	/* "ehci-hcd" etc */
-
-	struct timer_list	rh_timer;	/* drives root hub */
-	struct list_head	dev_list;	/* devices on this bus */
-
-	/*
-	 * hardware info/state
-	 */
-	struct hc_driver	*driver;	/* hw-specific hooks */
-	int			irq;		/* irq allocated */
-	void			*regs;		/* device memory/io */
-
-#ifdef	CONFIG_PCI
-	/* a few non-PCI controllers exist, mostly for OHCI */
-	struct pci_dev		*pdev;		/* pci is typical */
-	int			region;		/* pci region for regs */
-	u32			pci_state [16];	/* for PM state save */
-	atomic_t		resume_count;	/* multiple resumes issue */
-#endif
-
-	int			state;
-#	define	__ACTIVE		0x01
-#	define	__SLEEPY		0x02
-#	define	__SUSPEND		0x04
-#	define	__TRANSIENT		0x80
-
-#	define	USB_STATE_HALT		0
-#	define	USB_STATE_RUNNING	(__ACTIVE)
-#	define	USB_STATE_READY		(__ACTIVE|__SLEEPY)
-#	define	USB_STATE_QUIESCING	(__SUSPEND|__TRANSIENT|__ACTIVE)
-#	define	USB_STATE_RESUMING	(__SUSPEND|__TRANSIENT)
-#	define	USB_STATE_SUSPENDED	(__SUSPEND)
-
-#define	HCD_IS_RUNNING(state) ((state) & __ACTIVE)
-#define	HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
-
-	/* more shared queuing code would be good; it should support
-	 * smarter scheduling, handle transaction translators, etc;
-	 * input size of periodic table to an interrupt scheduler. 
-	 * (ohci 32, uhci 1024, ehci 256/512/1024).
-	 */
-};
-
-struct hcd_dev {	/* usb_device.hcpriv points to this */
-	struct list_head	dev_list;	/* on this hcd */
-	struct list_head	urb_list;	/* pending on this dev */
-
-	/* per-configuration HC/HCD state, such as QH or ED */
-	void			*ep[32];
-};
-
-// urb.hcpriv is really hardware-specific
-
-struct hcd_timeout {	/* timeouts we allocate */
-	struct list_head	timeout_list;
-	struct timer_list	timer;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * FIXME usb_operations should vanish or become hc_driver,
- * when usb_bus and usb_hcd become the same thing.
- */
-
-struct usb_operations {
-	int (*allocate)(struct usb_device *);
-	int (*deallocate)(struct usb_device *);
-	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb *urb, int mem_flags);
-	int (*unlink_urb) (struct urb *urb);
-};
-
-/* each driver provides one of these, and hardware init support */
-
-struct hc_driver {
-	const char	*description;	/* "ehci-hcd" etc */
-
-	/* irq handler */
-	void	(*irq) (struct usb_hcd *hcd);
-
-	int	flags;
-#define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
-#define	HCD_USB11	0x0010		/* USB 1.1 */
-#define	HCD_USB2	0x0020		/* USB 2.0 */
-
-	/* called to init HCD and root hub */
-	int	(*start) (struct usb_hcd *hcd);
-
-	/* called after all devices were suspended */
-	int	(*suspend) (struct usb_hcd *hcd, u32 state);
-
-	/* called before any devices get resumed */
-	int	(*resume) (struct usb_hcd *hcd);
-
-	/* cleanly make HCD stop writing memory and doing I/O */
-	void	(*stop) (struct usb_hcd *hcd);
-
-	/* return current frame number */
-	int	(*get_frame_number) (struct usb_hcd *hcd);
-
-	/* memory lifecycle */
-	struct usb_hcd	*(*hcd_alloc) (void);
-	void		(*hcd_free) (struct usb_hcd *hcd);
-
-	/* manage i/o requests, device state */
-	int	(*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
-					int mem_flags);
-	int	(*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
-
-	// frees configuration resources -- allocated as needed during
-	// urb_enqueue, and not freed by urb_dequeue
-	void		(*free_config) (struct usb_hcd *hcd,
-				struct usb_device *dev);
-
-	/* root hub support */
-	int		(*hub_status_data) (struct usb_hcd *hcd, char *buf);
-	int		(*hub_control) (struct usb_hcd *hcd,
-				u16 typeReq, u16 wValue, u16 wIndex,
-				char *buf, u16 wLength);
-};
-
-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb);
-
-#ifdef CONFIG_PCI
-struct pci_dev;
-struct pci_device_id;
-extern int usb_hcd_pci_probe (struct pci_dev *dev,
-				const struct pci_device_id *id);
-extern void usb_hcd_pci_remove (struct pci_dev *dev);
-
-#ifdef CONFIG_PM
-// FIXME:  see Documentation/power/pci.txt (2.4.6 and later?)
-// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
-extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
-extern int usb_hcd_pci_resume (struct pci_dev *dev);
-// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
-#endif /* CONFIG_PM */
-
-#endif /* CONFIG_PCI */
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * HCD Root Hub support
- */
-
-#include "hub.h"
-
-/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
-#define DeviceRequest \
-	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
-#define DeviceOutRequest \
-	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
-
-#define InterfaceRequest \
-	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
-
-#define EndpointRequest \
-	((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
-#define EndpointOutRequest \
-	((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
-
-/* table 9.6 standard features */
-#define DEVICE_REMOTE_WAKEUP	1
-#define ENDPOINT_HALT		0
-
-/* class requests from the USB 2.0 hub spec, table 11-15 */
-/* GetBusState and SetHubDescriptor are optional, omitted */
-#define ClearHubFeature		(0x2000 | USB_REQ_CLEAR_FEATURE)
-#define ClearPortFeature	(0x2300 | USB_REQ_CLEAR_FEATURE)
-#define GetHubDescriptor	(0xa000 | USB_REQ_GET_DESCRIPTOR)
-#define GetHubStatus		(0xa000 | USB_REQ_GET_STATUS)
-#define GetPortStatus		(0xa300 | USB_REQ_GET_STATUS)
-#define SetHubFeature		(0x2000 | USB_REQ_SET_FEATURE)
-#define SetPortFeature		(0x2300 | USB_REQ_SET_FEATURE)
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Generic bandwidth allocation constants/support
- */
-#define FRAME_TIME_USECS	1000L
-#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
-		/* Trying not to use worst-case bit-stuffing
-                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
-		/* bytecount = data payload byte count */
-
-#define NS_TO_US(ns)	((ns + 500L) / 1000L)
-			/* convert & round nanoseconds to microseconds */
-
-extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
-		int bustime, int isoc);
-extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
-		int isoc);
-
-/*
- * Full/low speed bandwidth allocation constants/support.
- */
-#define BW_HOST_DELAY	1000L		/* nanoseconds */
-#define BW_HUB_LS_SETUP	333L		/* nanoseconds */
-                        /* 4 full-speed bit times (est.) */
-
-#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
-#define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
-#define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
-
-extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
-
-/*-------------------------------------------------------------------------*/
-
-extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-extern void usb_free_bus (struct usb_bus *);
-
-extern void usb_register_bus (struct usb_bus *);
-extern void usb_deregister_bus (struct usb_bus *);
-
-extern int usb_register_root_hub (struct usb_device *usb_dev,
-		struct device *parent_dev);
-
-/*-------------------------------------------------------------------------*/
-
-/* exported only within usbcore */
-
-extern struct list_head usb_bus_list;
-extern struct semaphore usb_bus_list_lock;
-
-extern void usb_bus_get (struct usb_bus *bus);
-extern void usb_bus_put (struct usb_bus *bus);
-
-/*-------------------------------------------------------------------------*/
-
-/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
-// bleech -- resurfaced in 2.4.11 or 2.4.12
-#define bitmap 	DeviceRemovable
-
-
-/*-------------------------------------------------------------------------*/
-
-/* random stuff */
-
-#define	RUN_CONTEXT (in_irq () ? "in_irq" \
-		: (in_interrupt () ? "in_interrupt" : "can sleep"))
-
-
-#endif /* __KERNEL__ */
-
diff -Nru a/drivers/usb/hid-core.c b/drivers/usb/hid-core.c
--- a/drivers/usb/hid-core.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1541 +0,0 @@
-/*
- * $Id: hid-core.c,v 1.42 2002/01/27 00:22:46 vojtech Exp $
- *
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *
- *  USB HID support for Linux
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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/slab.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/spinlock.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-#include <linux/input.h>
-
-#undef DEBUG
-#undef DEBUG_DATA
-
-#include <linux/usb.h>
-
-#include "hid.h"
-#ifdef CONFIG_USB_HIDDEV
-#include <linux/hiddev.h>
-#endif
-
-/*
- * Version Information
- */
-
-#define DRIVER_VERSION "v1.31"
-#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID core driver"
-#define DRIVER_LICENSE "GPL"
-
-static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
-				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
-
-/*
- * Register a new report for a device.
- */
-
-static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
-{
-	struct hid_report_enum *report_enum = device->report_enum + type;
-	struct hid_report *report;
-
-	if (report_enum->report_id_hash[id])
-		return report_enum->report_id_hash[id];
-
-	if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL)))
-		return NULL;
-	memset(report, 0, sizeof(struct hid_report));
-
-	if (id != 0) report_enum->numbered = 1;
-
-	report->id = id;
-	report->type = type;
-	report->size = 0;
-	report->device = device;
-	report_enum->report_id_hash[id] = report;
-
-	list_add_tail(&report->list, &report_enum->report_list);
-
-	return report;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
-{
-	struct hid_field *field;
-
-	if (report->maxfield == HID_MAX_FIELDS) {
-		dbg("too many fields in report");
-		return NULL;
-	}
-
-	if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
-		+ values * sizeof(unsigned), GFP_KERNEL))) return NULL;
-
-	memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
-		+ values * sizeof(unsigned));
-
-	report->field[report->maxfield] = field;
-	field->usage = (struct hid_usage *)(field + 1);
-	field->value = (unsigned *)(field->usage + usages);
-	field->report = report;
-	field->index = report->maxfield++;
-
-	return field;
-}
-
-/*
- * Open a collection. The type/usage is pushed on the stack.
- */
-
-static int open_collection(struct hid_parser *parser, unsigned type)
-{
-	struct hid_collection *collection;
-	unsigned usage;
-
-	usage = parser->local.usage[0];
-
-	if (type == HID_COLLECTION_APPLICATION
-		&& parser->device->maxapplication < HID_MAX_APPLICATIONS)
-			parser->device->application[parser->device->maxapplication++] = usage;
-
-	if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
-		dbg("collection stack overflow");
-		return -1;
-	}
-
-	collection = parser->collection_stack + parser->collection_stack_ptr++;
-	collection->type = type;
-	collection->usage = usage;
-
-	return 0;
-}
-
-/*
- * Close a collection.
- */
-
-static int close_collection(struct hid_parser *parser)
-{
-	if (!parser->collection_stack_ptr) {
-		dbg("collection stack underflow");
-		return -1;
-	}
-	parser->collection_stack_ptr--;
-	return 0;
-}
-
-/*
- * Climb up the stack, search for the specified collection type
- * and return the usage.
- */
-
-static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
-{
-	int n;
-	for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
-		if (parser->collection_stack[n].type == type)
-			return parser->collection_stack[n].usage;
-	return 0; /* we know nothing about this usage type */
-}
-
-/*
- * Add a usage to the temporary parser table.
- */
-
-static int hid_add_usage(struct hid_parser *parser, unsigned usage)
-{
-	if (parser->local.usage_index >= HID_MAX_USAGES) {
-		dbg("usage index exceeded");
-		return -1;
-	}
-	parser->local.usage[parser->local.usage_index++] = usage;
-	return 0;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
-{
-	struct hid_report *report;
-	struct hid_field *field;
-	int usages;
-	unsigned offset;
-	int i;
-
-	if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
-		dbg("hid_register_report failed");
-		return -1;
-	}
-
-	if (parser->global.logical_maximum <= parser->global.logical_minimum) {
-		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
-		return -1;
-	}
-	usages = parser->local.usage_index;
-
-	offset = report->size;
-	report->size += parser->global.report_size * parser->global.report_count;
-
-	if (usages == 0)
-		return 0; /* ignore padding fields */
-
-	if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
-		return 0;
-
-	field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
-	field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
-	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
-
-	for (i = 0; i < usages; i++)
-		field->usage[i].hid = parser->local.usage[i];
-
-	field->maxusage = usages;
-	field->flags = flags;
-	field->report_offset = offset;
-	field->report_type = report_type;
-	field->report_size = parser->global.report_size;
-	field->report_count = parser->global.report_count;
-	field->logical_minimum = parser->global.logical_minimum;
-	field->logical_maximum = parser->global.logical_maximum;
-	field->physical_minimum = parser->global.physical_minimum;
-	field->physical_maximum = parser->global.physical_maximum;
-	field->unit_exponent = parser->global.unit_exponent;
-	field->unit = parser->global.unit;
-
-	return 0;
-}
-
-/*
- * Read data value from item.
- */
-
-static __inline__ __u32 item_udata(struct hid_item *item)
-{
-	switch (item->size) {
-		case 1: return item->data.u8;
-		case 2: return item->data.u16;
-		case 4: return item->data.u32;
-	}
-	return 0;
-}
-
-static __inline__ __s32 item_sdata(struct hid_item *item)
-{
-	switch (item->size) {
-		case 1: return item->data.s8;
-		case 2: return item->data.s16;
-		case 4: return item->data.s32;
-	}
-	return 0;
-}
-
-/*
- * Process a global item.
- */
-
-static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
-{
-	switch (item->tag) {
-
-		case HID_GLOBAL_ITEM_TAG_PUSH:
-
-			if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
-				dbg("global enviroment stack overflow");
-				return -1;
-			}
-
-			memcpy(parser->global_stack + parser->global_stack_ptr++,
-				&parser->global, sizeof(struct hid_global));
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_POP:
-
-			if (!parser->global_stack_ptr) {
-				dbg("global enviroment stack underflow");
-				return -1;
-			}
-
-			memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
-				sizeof(struct hid_global));
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
-			parser->global.usage_page = item_udata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
-			parser->global.logical_minimum = item_sdata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
-			if (parser->global.logical_minimum < 0)
-				parser->global.logical_maximum = item_sdata(item);
-			else
-				parser->global.logical_maximum = item_udata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
-			parser->global.physical_minimum = item_sdata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
-			if (parser->global.physical_minimum < 0)
-				parser->global.physical_maximum = item_sdata(item);
-			else
-				parser->global.physical_maximum = item_udata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-			parser->global.unit_exponent = item_sdata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_UNIT:
-			parser->global.unit = item_udata(item);
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
-			if ((parser->global.report_size = item_udata(item)) > 32) {
-				dbg("invalid report_size %d", parser->global.report_size);
-				return -1;
-			}
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
-			if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
-				dbg("invalid report_count %d", parser->global.report_count);
-				return -1;
-			}
-			return 0;
-
-		case HID_GLOBAL_ITEM_TAG_REPORT_ID:
-			if ((parser->global.report_id = item_udata(item)) == 0) {
-				dbg("report_id 0 is invalid");
-				return -1;
-			}
-			return 0;
-
-		default:
-			dbg("unknown global tag 0x%x", item->tag);
-			return -1;
-	}
-}
-
-/*
- * Process a local item.
- */
-
-static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
-{
-	__u32 data;
-	unsigned n;
-
-	if (item->size == 0) {
-		dbg("item data expected for local item");
-		return -1;
-	}
-
-	data = item_udata(item);
-
-	switch (item->tag) {
-
-		case HID_LOCAL_ITEM_TAG_DELIMITER:
-
-			if (data) {
-				/*
-				 * We treat items before the first delimiter
-				 * as global to all usage sets (branch 0).
-				 * In the moment we process only these global
-				 * items and the first delimiter set.
-				 */
-				if (parser->local.delimiter_depth != 0) {
-					dbg("nested delimiters");
-					return -1;
-				}
-				parser->local.delimiter_depth++;
-				parser->local.delimiter_branch++;
-			} else {
-				if (parser->local.delimiter_depth < 1) {
-					dbg("bogus close delimiter");
-					return -1;
-				}
-				parser->local.delimiter_depth--;
-			}
-			return 1;
-
-		case HID_LOCAL_ITEM_TAG_USAGE:
-
-			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
-				return 0;
-			}
-
-			if (item->size <= 2)
-				data = (parser->global.usage_page << 16) + data;
-
-			return hid_add_usage(parser, data);
-
-		case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
-
-			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
-				return 0;
-			}
-
-			if (item->size <= 2)
-				data = (parser->global.usage_page << 16) + data;
-
-			parser->local.usage_minimum = data;
-			return 0;
-
-		case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
-
-			if (parser->local.delimiter_branch > 1) {
-				dbg("alternative usage ignored");
-				return 0;
-			}
-
-			if (item->size <= 2)
-				data = (parser->global.usage_page << 16) + data;
-
-			for (n = parser->local.usage_minimum; n <= data; n++)
-				if (hid_add_usage(parser, n)) {
-					dbg("hid_add_usage failed\n");
-					return -1;
-				}
-			return 0;
-
-		default:
-
-			dbg("unknown local item tag 0x%x", item->tag);
-			return 0;
-	}
-	return 0;
-}
-
-/*
- * Process a main item.
- */
-
-static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
-{
-	__u32 data;
-	int ret;
-
-	data = item_udata(item);
-
-	switch (item->tag) {
-		case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
-			ret = open_collection(parser, data & 3);
-			break;
-		case HID_MAIN_ITEM_TAG_END_COLLECTION:
-			ret = close_collection(parser);
-			break;
-		case HID_MAIN_ITEM_TAG_INPUT:
-			ret = hid_add_field(parser, HID_INPUT_REPORT, data);
-			break;
-		case HID_MAIN_ITEM_TAG_OUTPUT:
-			ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
-			break;
-		case HID_MAIN_ITEM_TAG_FEATURE:
-			ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
-			break;
-		default:
-			dbg("unknown main item tag 0x%x", item->tag);
-			ret = 0;
-	}
-
-	memset(&parser->local, 0, sizeof(parser->local));	/* Reset the local parser environment */
-
-	return ret;
-}
-
-/*
- * Process a reserved item.
- */
-
-static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
-{
-	dbg("reserved item type, tag 0x%x", item->tag);
-	return 0;
-}
-
-/*
- * Free a report and all registered fields. The field->usage and
- * field->value table's are allocated behind the field, so we need
- * only to free(field) itself.
- */
-
-static void hid_free_report(struct hid_report *report)
-{
-	unsigned n;
-
-	for (n = 0; n < report->maxfield; n++)
-		kfree(report->field[n]);
-	kfree(report);
-}
-
-/*
- * Free a device structure, all reports, and all fields.
- */
-
-static void hid_free_device(struct hid_device *device)
-{
-	unsigned i,j;
-
-	for (i = 0; i < HID_REPORT_TYPES; i++) {
-		struct hid_report_enum *report_enum = device->report_enum + i;
-
-		for (j = 0; j < 256; j++) {
-			struct hid_report *report = report_enum->report_id_hash[j];
-			if (report) hid_free_report(report);
-		}
-	}
-
-	if (device->rdesc) kfree(device->rdesc);
-}
-
-/*
- * Fetch a report description item from the data stream. We support long
- * items, though they are not used yet.
- */
-
-static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
-{
-	u8 b;
-
-	if ((end - start) <= 0)
-		return NULL;
-
-	b = *start++;
-
-	item->type = (b >> 2) & 3;
-	item->tag  = (b >> 4) & 15;
-
-	if (item->tag == HID_ITEM_TAG_LONG) {
-
-		item->format = HID_ITEM_FORMAT_LONG;
-
-		if ((end - start) < 2)
-			return NULL;
-
-		item->size = *start++;
-		item->tag  = *start++;
-
-		if ((end - start) < item->size) 
-			return NULL;
-
-		item->data.longdata = start;
-		start += item->size;
-		return start;
-	} 
-
-	item->format = HID_ITEM_FORMAT_SHORT;
-	item->size = b & 3;
-
-	switch (item->size) {
-
-		case 0:
-			return start;
-
-		case 1:
-			if ((end - start) < 1)
-				return NULL;
-			item->data.u8 = *start++;
-			return start;
-
-		case 2:
-			if ((end - start) < 2) 
-				return NULL;
-			item->data.u16 = le16_to_cpu(get_unaligned(((__u16*)start)++));
-			return start;
-
-		case 3:
-			item->size++;
-			if ((end - start) < 4)
-				return NULL;
-			item->data.u32 = le32_to_cpu(get_unaligned(((__u32*)start)++));
-			return start;
-	}
-
-	return NULL;
-}
-
-/*
- * Parse a report description into a hid_device structure. Reports are
- * enumerated, fields are attached to these reports.
- */
-
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
-{
-	struct hid_device *device;
-	struct hid_parser *parser;
-	struct hid_item item;
-	__u8 *end;
-	unsigned i;
-	static int (*dispatch_type[])(struct hid_parser *parser,
-				      struct hid_item *item) = {
-		hid_parser_main,
-		hid_parser_global,
-		hid_parser_local,
-		hid_parser_reserved
-	};
-
-	if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL)))
-		return NULL;
-	memset(device, 0, sizeof(struct hid_device));
-
-	for (i = 0; i < HID_REPORT_TYPES; i++)
-		INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
-	if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
-		kfree(device);
-		return NULL;
-	}
-	memcpy(device->rdesc, start, size);
-
-	if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
-		kfree(device->rdesc);
-		kfree(device);
-		return NULL;
-	}
-	memset(parser, 0, sizeof(struct hid_parser));
-	parser->device = device;
-
-	end = start + size;
-	while ((start = fetch_item(start, end, &item)) != 0) {
-
-		if (item.format != HID_ITEM_FORMAT_SHORT) {
-			dbg("unexpected long global item");
-			hid_free_device(device);
-			kfree(parser);
-			return NULL;
-		}
-
-		if (dispatch_type[item.type](parser, &item)) {
-			dbg("item %u %u %u %u parsing failed\n",
-				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
-			hid_free_device(device);
-			kfree(parser);
-			return NULL;
-		}
-
-		if (start == end) {
-			if (parser->collection_stack_ptr) {
-				dbg("unbalanced collection at end of report description");
-				hid_free_device(device);
-				kfree(parser);
-				return NULL;
-			}
-			if (parser->local.delimiter_depth) {
-				dbg("unbalanced delimiter at end of report description");
-				hid_free_device(device);
-				kfree(parser);
-				return NULL;
-			}
-			kfree(parser);
-			return device;
-		}
-	}
-
-	dbg("item fetching failed at offset %d\n", (int)(end - start));
-	hid_free_device(device);
-	kfree(parser);
-	return NULL;
-}
-
-/*
- * Convert a signed n-bit integer to signed 32-bit integer. Common
- * cases are done through the compiler, the screwed things has to be
- * done by hand.
- */
-
-static __inline__ __s32 snto32(__u32 value, unsigned n)
-{
-	switch (n) {
-		case 8:  return ((__s8)value);
-		case 16: return ((__s16)value);
-		case 32: return ((__s32)value);
-	}
-	return value & (1 << (n - 1)) ? value | (-1 << n) : value;
-}
-
-/*
- * Convert a signed 32-bit integer to a signed n-bit integer.
- */
-
-static __inline__ __u32 s32ton(__s32 value, unsigned n)
-{
-	__s32 a = value >> (n - 1);
-	if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
-	return value & ((1 << n) - 1);
-}
-
-/*
- * Extract/implement a data field from/to a report.
- */
-
-static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
-{
-	report += (offset >> 5) << 2; offset &= 31;
-	return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1);
-}
-
-static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
-{
-	report += (offset >> 5) << 2; offset &= 31;
-	put_unaligned((get_unaligned((__u64*)report)
-		& cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
-		| cpu_to_le64((__u64)value << offset), (__u64*)report);
-}
-
-/*
- * Search an array for a value.
- */
-
-static __inline__ int search(__s32 *array, __s32 value, unsigned n)
-{
-	while (n--) if (*array++ == value) return 0;
-	return -1;
-}
-
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
-	hid_dump_input(usage, value);
-	if (hid->claimed & HID_CLAIMED_INPUT)
-		hidinput_hid_event(hid, field, usage, value);
-#ifdef CONFIG_USB_HIDDEV
-	if (hid->claimed & HID_CLAIMED_HIDDEV) {
-		struct hiddev_usage_ref uref;
-		unsigned type = field->report_type;
-		uref.report_type = 
-		  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
-		  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : 
-		   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
-		uref.report_id = field->report->id;
-		uref.field_index = field->index;
-		uref.usage_index = (usage - field->usage);
-		uref.usage_code = usage->hid;
-		uref.value = value;
-		hiddev_hid_event(hid, &uref);
-	}
-#endif
-}
-
-/*
- * Analyse a received field, and fetch the data from it. The field
- * content is stored for next report processing (we do differential
- * reporting to the layer).
- */
-
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data)
-{
-	unsigned n;
-	unsigned count = field->report_count;
-	unsigned offset = field->report_offset;
-	unsigned size = field->report_size;
-	__s32 min = field->logical_minimum;
-	__s32 max = field->logical_maximum;
-	__s32 value[count]; /* WARNING: gcc specific */
-
-	for (n = 0; n < count; n++) {
-
-			value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
-						    extract(data, offset + n * size, size);
-
-			if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
-			    && value[n] >= min && value[n] <= max
-			    && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
-				return;
-	}
-
-	for (n = 0; n < count; n++) {
-
-		if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-
-			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-				if (!value[n]) continue;
-			} else {
-				if (value[n] == field->value[n]) continue;
-			}	
-			hid_process_event(hid, field, &field->usage[n], value[n]);
-			continue;
-		}
-
-		if (field->value[n] >= min && field->value[n] <= max
-			&& field->usage[field->value[n] - min].hid
-			&& search(value, field->value[n], count))
-				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0);
-
-		if (value[n] >= min && value[n] <= max
-			&& field->usage[value[n] - min].hid
-			&& search(field->value, value[n], count))
-				hid_process_event(hid, field, &field->usage[value[n] - min], 1);
-	}
-
-	memcpy(field->value, value, count * sizeof(__s32));
-}
-
-static int hid_input_report(int type, struct urb *urb)
-{
-	struct hid_device *hid = urb->context;
-	struct hid_report_enum *report_enum = hid->report_enum + type;
-	u8 *data = urb->transfer_buffer;
-	int len = urb->actual_length;
-	struct hid_report *report;
-	int n, size;
-
-	if (!len) {
-		dbg("empty report");
-		return -1;
-	}
-
-#ifdef DEBUG_DATA
-	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
-#endif
-
-	n = 0;				/* Normally report number is 0 */
-	if (report_enum->numbered) {	/* Device uses numbered reports, data[0] is report number */
-		n = *data++;
-		len--;
-	}
-
-#ifdef DEBUG_DATA
-	{
-		int i;
-		printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len);
-		for (i = 0; i < n; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
-#endif
-
-	if (!(report = report_enum->report_id_hash[n])) {
-		dbg("undefined report_id %d received", n);
-		return -1;
-	}
-
-#ifdef CONFIG_USB_HIDDEV
-	/* Notify listeners that a report has been received */
-	if (hid->claimed & HID_CLAIMED_HIDDEV) {
-		struct hiddev_usage_ref uref;
-		memset(&uref, 0, sizeof(uref));
-		uref.report_type = 
-		  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
-		  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : 
-		   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
-		uref.report_id = report->id;
-		uref.field_index = HID_FIELD_INDEX_NONE;
-		hiddev_hid_event(hid, &uref);
-	}
-#endif
-
-	size = ((report->size - 1) >> 3) + 1;
-
-	if (len < size) {
-		dbg("report %d is too short, (%d < %d)", report->id, len, size);
-		return -1;
-	}
-
-	for (n = 0; n < report->maxfield; n++)
-		hid_input_field(hid, report->field[n], data);
-
-	return 0;
-}
-
-/*
- * Input interrupt completion handler.
- */
-
-static void hid_irq_in(struct urb *urb)
-{
-	if (urb->status) {
-		dbg("nonzero status in input irq %d", urb->status);
-		return;
-	}
-
-	hid_input_report(HID_INPUT_REPORT, urb);
-}
-
-/*
- * Output the field into the report.
- */
-
-static void hid_output_field(struct hid_field *field, __u8 *data)
-{
-	unsigned count = field->report_count;
-	unsigned offset = field->report_offset;
-	unsigned size = field->report_size;
-	unsigned n;
-
-	for (n = 0; n < count; n++) {
-		if (field->logical_minimum < 0)	/* signed values */
-			implement(data, offset + n * size, size, s32ton(field->value[n], size));
-		 else				/* unsigned values */
-			implement(data, offset + n * size, size, field->value[n]);
-	}
-}
-
-/*
- * Create a report.
- */
-
-void hid_output_report(struct hid_report *report, __u8 *data)
-{
-	unsigned n;
-	for (n = 0; n < report->maxfield; n++)
-		hid_output_field(report->field[n], data);
-}
-
-/*
- * Set a field value. The report this field belongs to has to be
- * created and transfered to the device, to set this value in the
- * device.
- */
-
-int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
-{
-	unsigned size = field->report_size;
-
-	hid_dump_input(field->usage + offset, value);
-
-	if (offset >= field->report_count) {
-		dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
-		hid_dump_field(field, 8);
-		return -1;
-	}
-	if (field->logical_minimum < 0) {
-		if (value != snto32(s32ton(value, size), size)) {
-			dbg("value %d is out of range", value);
-			return -1;
-		}
-	}
-	field->value[offset] = value;
-	return 0;
-}
-
-int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
-{
-	struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
-	struct list_head *list = report_enum->report_list.next;
-	int i, j;
-
-	while (list != &report_enum->report_list) {
-		struct hid_report *report = (struct hid_report *) list;
-		list = list->next;
-		for (i = 0; i < report->maxfield; i++) {
-			*field = report->field[i];
-			for (j = 0; j < (*field)->maxusage; j++)
-				if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
-					return j;
-		}
-	}
-	return -1;
-}
-
-/*
- * Find a report with a specified HID usage.
- */
-
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type)
-{
-	struct hid_report_enum *report_enum = hid->report_enum + type;
-	struct list_head *list = report_enum->report_list.next;
-	int i, j;
-
-	while (list != &report_enum->report_list) {
-		*report = (struct hid_report *) list;
-		list = list->next;
-		for (i = 0; i < (*report)->maxfield; i++) {
-			struct hid_field *field = (*report)->field[i];
-			for (j = 0; j < field->maxusage; j++)
-				if (field->logical == wanted_usage)
-					return j;
-		}
-	}
-	return -1;
-}
-
-int hid_find_field_in_report(struct hid_report *report, __u32 wanted_usage, struct hid_field **field)
-{
-	int i, j;
-
-	for (i = 0; i < report->maxfield; i++) {
-		*field = report->field[i];
-		for (j = 0; j < (*field)->maxusage; j++)
-			if ((*field)->usage[j].hid == wanted_usage)
-				return j;
-	}
-
-	return -1;
-}
-
-static int hid_submit_out(struct hid_device *hid)
-{
-	struct hid_report *report;
-
-	report = hid->out[hid->outtail];
-
-	hid_output_report(report, hid->outbuf);
-	hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1;
-	hid->urbout->dev = hid->dev;
-
-	dbg("submitting out urb");
-
-	if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
-		err("usb_submit_urb(out) failed");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int hid_submit_ctrl(struct hid_device *hid)
-{
-	struct hid_report *report;
-	unsigned char dir;
-
-	report = hid->ctrl[hid->ctrltail].report;
-	dir = hid->ctrl[hid->ctrltail].dir;
-
-	if (dir == USB_DIR_OUT)
-		hid_output_report(report, hid->ctrlbuf);
-
-	hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && (dir != USB_DIR_OUT));
-	hid->urbctrl->pipe = (dir == USB_DIR_OUT) ?  usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);
-	hid->urbctrl->dev = hid->dev;
-
-	hid->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
-	hid->cr.bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
-	hid->cr.wValue = ((report->type + 1) << 8) | report->id;
-	hid->cr.wIndex = cpu_to_le16(hid->ifnum);
-	hid->cr.wLength = cpu_to_le16(hid->urbctrl->transfer_buffer_length);
-
-	dbg("submitting ctrl urb");
-
-	if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
-		err("usb_submit_urb(ctrl) failed");
-		return -1;
-	}
-
-	return 0;
-}
-
-/*
- * Output interrupt completion handler.
- */
-
-static void hid_irq_out(struct urb *urb)
-{
-	struct hid_device *hid = urb->context;
-	unsigned long flags;
-
-	if (urb->status)
-		warn("output irq status %d received", urb->status);
-
-	spin_lock_irqsave(&hid->outlock, flags);
-
-	hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
-
-	if (hid->outhead != hid->outtail) {
-		hid_submit_out(hid);
-		spin_unlock_irqrestore(&hid->outlock, flags);
-		return;
-	}
-
-	clear_bit(HID_OUT_RUNNING, &hid->iofl);
-
-	spin_unlock_irqrestore(&hid->outlock, flags);
-
-	wake_up(&hid->wait);
-}
-
-/*
- * Control pipe completion handler.
- */
-
-static void hid_ctrl(struct urb *urb)
-{
-	struct hid_device *hid = urb->context;
-	unsigned long flags;
-
-	if (urb->status)
-		warn("ctrl urb status %d received", urb->status);
-
-	spin_lock_irqsave(&hid->ctrllock, flags);
-
-	if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
-		hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb);
-
-	hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
-
-	if (hid->ctrlhead != hid->ctrltail) {
-		hid_submit_ctrl(hid);
-		spin_unlock_irqrestore(&hid->ctrllock, flags);
-		return;
-	}
-
-	clear_bit(HID_CTRL_RUNNING, &hid->iofl);
-
-	spin_unlock_irqrestore(&hid->ctrllock, flags);
-
-	wake_up(&hid->wait);
-}
-
-void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
-{
-	int head;
-	unsigned long flags;
-
-	if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
-		return;
-
-	if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
-
-		spin_lock_irqsave(&hid->outlock, flags);
-
-		if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
-			spin_unlock_irqrestore(&hid->outlock, flags);
-			warn("output queue full");
-			return;
-		}
-
-		hid->out[hid->outhead] = report;
-		hid->outhead = head;
-
-		if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
-			hid_submit_out(hid);
-
-		spin_unlock_irqrestore(&hid->outlock, flags);
-		return;
-	}
-
-	spin_lock_irqsave(&hid->ctrllock, flags);
-
-	if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
-		spin_unlock_irqrestore(&hid->ctrllock, flags);
-		warn("control queue full");
-		return;
-	}
-
-	hid->ctrl[hid->ctrlhead].report = report;
-	hid->ctrl[hid->ctrlhead].dir = dir;
-	hid->ctrlhead = head;
-
-	if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
-		hid_submit_ctrl(hid);
-
-	spin_unlock_irqrestore(&hid->ctrllock, flags);
-}
-
-int hid_wait_io(struct hid_device *hid)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int timeout = 10*HZ;
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&hid->wait, &wait);
-
-	while (timeout && test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
-			  test_bit(HID_OUT_RUNNING, &hid->iofl))
-		timeout = schedule_timeout(timeout);
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&hid->wait, &wait);
-
-	if (!timeout) {
-		dbg("timeout waiting for ctrl or out queue to clear");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
-		unsigned char type, void *buf, int size)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
-		(type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-int hid_open(struct hid_device *hid)
-{
-	if (hid->open++)
-		return 0;
-
-	hid->urbin->dev = hid->dev;
-
-	if (usb_submit_urb(hid->urbin, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-void hid_close(struct hid_device *hid)
-{
-	if (!--hid->open)
-		usb_unlink_urb(hid->urbin);
-}
-
-/*
- * Initialize all reports
- */
-
-void hid_init_reports(struct hid_device *hid)
-{
-	struct hid_report_enum *report_enum;
-	struct hid_report *report;
-	struct list_head *list;
-	int len;
-
-	report_enum = hid->report_enum + HID_INPUT_REPORT;
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
-		hid_submit_report(hid, report, USB_DIR_IN);
-		list = list->next;
-	}
-
-	report_enum = hid->report_enum + HID_FEATURE_REPORT;
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
-		hid_submit_report(hid, report, USB_DIR_IN);
-		list = list->next;
-	}
-
-	if (hid_wait_io(hid)) {
-		warn("timeout initializing reports\n");
-		return;
-	}
-
-	report_enum = hid->report_enum + HID_INPUT_REPORT;
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
-		len = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
-		if (len > hid->urbin->transfer_buffer_length)
-			hid->urbin->transfer_buffer_length = len < HID_BUFFER_SIZE ? len : HID_BUFFER_SIZE;
-		usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-			0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
-			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-		list = list->next;
-	}
-}
-
-#define USB_VENDOR_ID_WACOM		0x056a
-#define USB_DEVICE_ID_WACOM_GRAPHIRE	0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS	0x0020
-
-#define USB_VENDOR_ID_GRIFFIN		0x077d
-#define USB_DEVICE_ID_POWERMATE		0x0410
-#define USB_DEVICE_ID_SOUNDKNOB		0x04AA
-
-#define USB_VENDOR_ID_ATEN             0x0557  
-#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
-#define USB_DEVICE_ID_ATEN_CS124U      0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
-
-struct hid_blacklist {
-	__u16 idVendor;
-	__u16 idProduct;
-	unsigned quirks;
-} hid_blacklist[] = {
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE  },
-	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE  },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
-	{ 0, 0 }
-};
-
-static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
-{
-	struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
-	struct hid_descriptor *hdesc;
-	struct hid_device *hid;
-	unsigned quirks = 0, rsize = 0;
-	char *buf;
-	int n;
-
-	for (n = 0; hid_blacklist[n].idVendor; n++)
-		if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
-			(hid_blacklist[n].idProduct == dev->descriptor.idProduct))
-				quirks = hid_blacklist[n].quirks;
-
-	if (quirks & HID_QUIRK_IGNORE)
-		return NULL;
-
-	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
-		usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
-			dbg("class descriptor not present\n");
-			return NULL;
-	}
-
-	for (n = 0; n < hdesc->bNumDescriptors; n++)
-		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
-			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
-
-	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
-		dbg("weird size of report descriptor (%u)", rsize);
-		return NULL;
-	}
-
-	{
-		__u8 rdesc[rsize];
-
-		if ((n = hid_get_class_descriptor(dev, interface->bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
-			dbg("reading report descriptor failed");
-			return NULL;
-		}
-
-#ifdef DEBUG_DATA
-		printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
-		for (n = 0; n < rsize; n++)
-			printk(" %02x", (unsigned) rdesc[n]);
-		printk("\n");
-#endif
-
-		if (!(hid = hid_parse_report(rdesc, rsize))) {
-			dbg("parsing report descriptor failed");
-			return NULL;
-		}
-	}
-
-	hid->quirks = quirks;
-
-	for (n = 0; n < interface->bNumEndpoints; n++) {
-
-		struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
-		int pipe;
-
-		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
-			continue;
-
-		if (endpoint->bEndpointAddress & USB_DIR_IN) {
-			if (hid->urbin)
-				continue;
-			if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
-				goto fail;
-			pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-			FILL_INT_URB(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, endpoint->bInterval);
-		} else {
-			if (hid->urbout)
-				continue;
-			if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
-				goto fail;
-			pipe = usb_sndbulkpipe(dev, endpoint->bEndpointAddress);
-			FILL_BULK_URB(hid->urbout, dev, pipe, hid->outbuf, 0, hid_irq_out, hid);
-		}
-	}
-
-	if (!hid->urbin) {
-		err("couldn't find an input interrupt endpoint");
-		goto fail;
-	}
-
-	init_waitqueue_head(&hid->wait);
-	
-	hid->outlock = SPIN_LOCK_UNLOCKED;
-	hid->ctrllock = SPIN_LOCK_UNLOCKED;
-
-	hid->version = hdesc->bcdHID;
-	hid->country = hdesc->bCountryCode;
-	hid->dev = dev;
-	hid->ifnum = interface->bInterfaceNumber;
-
-	hid->name[0] = 0;
-
-	if (!(buf = kmalloc(64, GFP_KERNEL)))
-		goto fail;
-
-	if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
-		strcat(hid->name, buf);
-		if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
-			sprintf(hid->name, "%s %s", hid->name, buf);
-	} else
-		sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
-
-	usb_make_path(dev, buf, 63);
-	sprintf(hid->phys, "%s/input%d", buf, ifnum);
-
-	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
-		hid->uniq[0] = 0;
-
-	kfree(buf);
-
-	hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
-	FILL_CONTROL_URB(hid->urbctrl, dev, 0, (void*) &hid->cr, hid->ctrlbuf, 1, hid_ctrl, hid);
-
-	return hid;
-
-fail:
-
-	hid_free_device(hid);
-	if (hid->urbin) usb_free_urb(hid->urbin);
-	if (hid->urbout) usb_free_urb(hid->urbout);
-	if (hid->urbctrl) usb_free_urb(hid->urbctrl);
-
-	return NULL;
-}
-
-static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
-		       const struct usb_device_id *id)
-{
-	struct hid_device *hid;
-	char path[64];
-	int i;
-	char *c;
-
-	dbg("HID probe called for ifnum %d", ifnum);
-
-	if (!(hid = usb_hid_configure(dev, ifnum)))
-		return NULL;
-
-	hid_init_reports(hid);
-	hid_dump_device(hid);
-
-	if (!hidinput_connect(hid))
-		hid->claimed |= HID_CLAIMED_INPUT;
-#ifdef CONFIG_USB_HIDDEV
-	if (!hiddev_connect(hid))
-		hid->claimed |= HID_CLAIMED_HIDDEV;
-#endif
-
-	if (!hid->claimed) {
-		hid_free_device(hid);
-		return NULL;
-	}
-
-	printk(KERN_INFO);
-
-	if (hid->claimed & HID_CLAIMED_INPUT)
-		printk("input");
-	if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
-		printk(",");
-	if (hid->claimed & HID_CLAIMED_HIDDEV)
-		printk("hiddev%d", hid->minor);
-
-	c = "Device";
-	for (i = 0; i < hid->maxapplication; i++)
-		if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
-			c = hid_types[hid->application[i] & 0xffff];
-			break;
-		}
-
-	usb_make_path(dev, path, 63);
-
-	printk(": USB HID v%x.%02x %s [%s] on %s\n",
-		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
-
-	return hid;
-}
-
-static void hid_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct hid_device *hid = ptr;
-
-	usb_unlink_urb(hid->urbin);
-	usb_unlink_urb(hid->urbout);
-	usb_unlink_urb(hid->urbctrl);
-
-
-	if (hid->claimed & HID_CLAIMED_INPUT)
-		hidinput_disconnect(hid);
-#ifdef CONFIG_USB_HIDDEV
-	if (hid->claimed & HID_CLAIMED_HIDDEV)
-		hiddev_disconnect(hid);
-#endif
-
-	usb_free_urb(hid->urbin);
-	usb_free_urb(hid->urbctrl);
-	if (hid->urbout)
-		usb_free_urb(hid->urbout);
-
-	hid_free_device(hid);
-}
-
-static struct usb_device_id hid_usb_ids [] = {
-	{ match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
-	    bInterfaceClass: USB_INTERFACE_CLASS_HID },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hid_usb_ids);
-
-static struct usb_driver hid_driver = {
-	name:		"hid",
-	probe:		hid_probe,
-	disconnect:	hid_disconnect,
-	id_table:	hid_usb_ids,
-};
-
-static int __init hid_init(void)
-{
-#ifdef CONFIG_USB_HIDDEV
-	hiddev_init();
-#endif
-	usb_register(&hid_driver);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-}
-
-static void __exit hid_exit(void)
-{
-#ifdef CONFIG_USB_HIDDEV
-	hiddev_exit();
-#endif
-	usb_deregister(&hid_driver);
-}
-
-module_init(hid_init);
-module_exit(hid_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
diff -Nru a/drivers/usb/hid-debug.h b/drivers/usb/hid-debug.h
--- a/drivers/usb/hid-debug.h	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,386 +0,0 @@
-/*
- * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
- *
- *  (c) 1999 Andreas Gal		<gal@cs.uni-magdeburg.de>
- *  (c) 2000-2001 Vojtech Pavlik	<vojtech@ucw.cz>
- *
- *  Some debug stuff for the HID parser.
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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
- */
-
-struct hid_usage_entry {
-	unsigned  page;
-	unsigned  usage;
-	char     *description;
-};
-
-static struct hid_usage_entry hid_usage_table[] = {
-  {  0,      0, "Undefined" },
-  {  1,      0, "GenericDesktop" },
-    {0, 0x01, "Pointer"},
-    {0, 0x02, "Mouse"},
-    {0, 0x04, "Joystick"},
-    {0, 0x05, "GamePad"},
-    {0, 0x06, "Keyboard"},
-    {0, 0x07, "Keypad"},
-    {0, 0x08, "MultiAxis"},
-      {0, 0x30, "X"},
-      {0, 0x31, "Y"},
-      {0, 0x32, "Z"},
-      {0, 0x33, "Rx"},
-      {0, 0x34, "Ry"},
-      {0, 0x35, "Rz"},
-      {0, 0x36, "Slider"},
-      {0, 0x37, "Dial"},
-      {0, 0x38, "Wheel"},
-      {0, 0x39, "HatSwitch"},
-    {0, 0x3a, "CountedBuffer"},
-      {0, 0x3b, "ByteCount"},
-      {0, 0x3c, "MotionWakeup"},
-      {0, 0x3d, "Start"},
-      {0, 0x3e, "Select"},
-      {0, 0x40, "Vx"},
-      {0, 0x41, "Vy"},
-      {0, 0x42, "Vz"},
-      {0, 0x43, "Vbrx"},
-      {0, 0x44, "Vbry"},
-      {0, 0x45, "Vbrz"},
-      {0, 0x46, "Vno"},
-    {0, 0x80, "SystemControl"}, 
-      {0, 0x81, "SystemPowerDown"},
-      {0, 0x82, "SystemSleep"},
-      {0, 0x83, "SystemWakeUp"},
-      {0, 0x84, "SystemContextMenu"},
-      {0, 0x85, "SystemMainMenu"},
-      {0, 0x86, "SystemAppMenu"},
-      {0, 0x87, "SystemMenuHelp"},
-      {0, 0x88, "SystemMenuExit"},
-      {0, 0x89, "SystemMenuSelect"},
-      {0, 0x8a, "SystemMenuRight"},
-      {0, 0x8b, "SystemMenuLeft"},
-      {0, 0x8c, "SystemMenuUp"},
-      {0, 0x8d, "SystemMenuDown"},
-    {0, 0x90, "D-padUp"},
-    {0, 0x91, "D-padDown"},
-    {0, 0x92, "D-padRight"},
-    {0, 0x93, "D-padLeft"},
-  {  7, 0, "Keyboard" },
-  {  8, 0, "LED" },
-  {  9, 0, "Button" },
-  { 10, 0, "Ordinal" },
-  { 12, 0, "Hotkey" },
-  { 13, 0, "Digitizers" },
-    {0, 0x01, "Digitizer"},
-    {0, 0x02, "Pen"},
-    {0, 0x03, "LightPen"},
-    {0, 0x04, "TouchScreen"},
-    {0, 0x05, "TouchPad"},
-    {0, 0x20, "Stylus"},
-    {0, 0x21, "Puck"},
-    {0, 0x22, "Finger"},
-    {0, 0x30, "TipPressure"},
-    {0, 0x31, "BarrelPressure"},
-    {0, 0x32, "InRange"},
-    {0, 0x33, "Touch"},
-    {0, 0x34, "UnTouch"},
-    {0, 0x35, "Tap"},
-    {0, 0x39, "TabletFunctionKey"},
-    {0, 0x3a, "ProgramChangeKey"},
-    {0, 0x3c, "Invert"},
-    {0, 0x42, "TipSwitch"},
-    {0, 0x43, "SecondaryTipSwitch"},
-    {0, 0x44, "BarrelSwitch"},
-    {0, 0x45, "Eraser"},
-    {0, 0x46, "TabletPick"},
-  { 15, 0, "PhysicalInterfaceDevice" },
-    {0, 0x00, "Undefined"},
-    {0, 0x01, "Physical_Interface_Device"},
-      {0, 0x20, "Normal"},
-    {0, 0x21, "Set_Effect_Report"},
-      {0, 0x22, "Effect_Block_Index"},
-      {0, 0x23, "Parameter_Block_Offset"},
-      {0, 0x24, "ROM_Flag"},
-      {0, 0x25, "Effect_Type"},
-        {0, 0x26, "ET_Constant_Force"},
-        {0, 0x27, "ET_Ramp"},
-        {0, 0x28, "ET_Custom_Force_Data"},
-        {0, 0x30, "ET_Square"},
-        {0, 0x31, "ET_Sine"},
-        {0, 0x32, "ET_Triangle"},
-        {0, 0x33, "ET_Sawtooth_Up"},
-        {0, 0x34, "ET_Sawtooth_Down"},
-        {0, 0x40, "ET_Spring"},
-        {0, 0x41, "ET_Damper"},
-        {0, 0x42, "ET_Inertia"},
-        {0, 0x43, "ET_Friction"},
-      {0, 0x50, "Duration"},
-      {0, 0x51, "Sample_Period"},
-      {0, 0x52, "Gain"},
-      {0, 0x53, "Trigger_Button"},
-      {0, 0x54, "Trigger_Repeat_Interval"},
-      {0, 0x55, "Axes_Enable"},
-        {0, 0x56, "Direction_Enable"},
-      {0, 0x57, "Direction"},
-      {0, 0x58, "Type_Specific_Block_Offset"},
-        {0, 0x59, "Block_Type"},
-        {0, 0x5A, "Set_Envelope_Report"},
-          {0, 0x5B, "Attack_Level"},
-          {0, 0x5C, "Attack_Time"},
-          {0, 0x5D, "Fade_Level"},
-          {0, 0x5E, "Fade_Time"},
-        {0, 0x5F, "Set_Condition_Report"},
-        {0, 0x60, "CP_Offset"},
-        {0, 0x61, "Positive_Coefficient"},
-        {0, 0x62, "Negative_Coefficient"},
-        {0, 0x63, "Positive_Saturation"},
-        {0, 0x64, "Negative_Saturation"},
-        {0, 0x65, "Dead_Band"},
-      {0, 0x66, "Download_Force_Sample"},
-      {0, 0x67, "Isoch_Custom_Force_Enable"},
-      {0, 0x68, "Custom_Force_Data_Report"},
-        {0, 0x69, "Custom_Force_Data"},
-        {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
-      {0, 0x6B, "Set_Custom_Force_Report"},
-        {0, 0x6C, "Custom_Force_Data_Offset"},
-        {0, 0x6D, "Sample_Count"},
-      {0, 0x6E, "Set_Periodic_Report"},
-        {0, 0x6F, "Offset"},
-        {0, 0x70, "Magnitude"},
-        {0, 0x71, "Phase"},
-        {0, 0x72, "Period"},
-      {0, 0x73, "Set_Constant_Force_Report"},
-        {0, 0x74, "Set_Ramp_Force_Report"},
-        {0, 0x75, "Ramp_Start"},
-        {0, 0x76, "Ramp_End"},
-      {0, 0x77, "Effect_Operation_Report"},
-        {0, 0x78, "Effect_Operation"},
-          {0, 0x79, "Op_Effect_Start"},
-          {0, 0x7A, "Op_Effect_Start_Solo"},
-          {0, 0x7B, "Op_Effect_Stop"},
-          {0, 0x7C, "Loop_Count"},
-      {0, 0x7D, "Device_Gain_Report"},
-        {0, 0x7E, "Device_Gain"},
-    {0, 0x7F, "PID_Pool_Report"},
-      {0, 0x80, "RAM_Pool_Size"},
-      {0, 0x81, "ROM_Pool_Size"},
-      {0, 0x82, "ROM_Effect_Block_Count"},
-      {0, 0x83, "Simultaneous_Effects_Max"},
-      {0, 0x84, "Pool_Alignment"},
-    {0, 0x85, "PID_Pool_Move_Report"},
-      {0, 0x86, "Move_Source"},
-      {0, 0x87, "Move_Destination"},
-      {0, 0x88, "Move_Length"},
-    {0, 0x89, "PID_Block_Load_Report"},
-      {0, 0x8B, "Block_Load_Status"},
-      {0, 0x8C, "Block_Load_Success"},
-      {0, 0x8D, "Block_Load_Full"},
-      {0, 0x8E, "Block_Load_Error"},
-      {0, 0x8F, "Block_Handle"},
-      {0, 0x90, "PID_Block_Free_Report"},
-      {0, 0x91, "Type_Specific_Block_Handle"},
-    {0, 0x92, "PID_State_Report"},
-      {0, 0x94, "Effect_Playing"},
-      {0, 0x95, "PID_Device_Control_Report"},
-        {0, 0x96, "PID_Device_Control"},
-        {0, 0x97, "DC_Enable_Actuators"},
-        {0, 0x98, "DC_Disable_Actuators"},
-        {0, 0x99, "DC_Stop_All_Effects"},
-        {0, 0x9A, "DC_Device_Reset"},
-        {0, 0x9B, "DC_Device_Pause"},
-        {0, 0x9C, "DC_Device_Continue"},
-      {0, 0x9F, "Device_Paused"},
-      {0, 0xA0, "Actuators_Enabled"},
-      {0, 0xA4, "Safety_Switch"},
-      {0, 0xA5, "Actuator_Override_Switch"},
-      {0, 0xA6, "Actuator_Power"},
-    {0, 0xA7, "Start_Delay"},
-    {0, 0xA8, "Parameter_Block_Size"},
-    {0, 0xA9, "Device_Managed_Pool"},
-    {0, 0xAA, "Shared_Parameter_Blocks"},
-    {0, 0xAB, "Create_New_Effect_Report"},
-    {0, 0xAC, "RAM_Pool_Available"},
-  { 0, 0, NULL }
-};
-
-static void resolv_usage_page(unsigned page) {
-	struct hid_usage_entry *p;
-
-	for (p = hid_usage_table; p->description; p++)
-		if (p->page == page) {
-			printk("%s", p->description);
-			return;
-		}
-	printk("%04x", page);
-}
-
-static void resolv_usage(unsigned usage) {
-	struct hid_usage_entry *p;
-
-	resolv_usage_page(usage >> 16);
-	printk(".");
-	for (p = hid_usage_table; p->description; p++)
-		if (p->page == (usage >> 16)) {
-			for(++p; p->description && p->page == 0; p++)
-				if (p->usage == (usage & 0xffff)) {
-					printk("%s", p->description);
-					return;
-				}
-			break;
-		}
-	printk("%04x", usage & 0xffff);
-}
-
-__inline__ static void tab(int n) {
-	while (n--) printk(" ");
-}
-
-static void hid_dump_field(struct hid_field *field, int n) {
-	int j;
-	
-	if (field->physical) {
-		tab(n);
-		printk("Physical(");
-		resolv_usage(field->physical); printk(")\n");
-	}
-	if (field->logical) {
-		tab(n);
-		printk("Logical(");
-		resolv_usage(field->logical); printk(")\n");
-	}
-	tab(n); printk("Usage(%d)\n", field->maxusage);
-	for (j = 0; j < field->maxusage; j++) {
-		tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
-	}
-	if (field->logical_minimum != field->logical_maximum) {
-		tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
-		tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
-	}
-	if (field->physical_minimum != field->physical_maximum) {
-		tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
-		tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
-	}
-	if (field->unit_exponent) {
-		tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
-	}
-	if (field->unit) {
-		char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
-		char *units[5][8] = {
-			{ "None", "None", "None", "None", "None", "None", "None", "None" },
-			{ "None", "Centimeter", "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
-			{ "None", "Radians",    "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
-			{ "None", "Inch",       "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
-			{ "None", "Degrees",    "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
-		};
-
-		int i;
-		int sys;
-                __u32 data = field->unit;
-
-		/* First nibble tells us which system we're in. */
-		sys = data & 0xf;
-		data >>= 4;
-
-		if(sys > 4) {
-			tab(n); printk("Unit(Invalid)\n");
-		}
-		else {
-			int earlier_unit = 0;
-
-			tab(n); printk("Unit(%s : ", systems[sys]);
-
-			for (i=1 ; i<sizeof(__u32)*2 ; i++) {
-				char nibble = data & 0xf;
-				data >>= 4;
-				if (nibble != 0) {
-					if(earlier_unit++ > 0)
-						printk("*");
-					printk("%s", units[sys][i]);
-					if(nibble != 1) {
-						/* This is a _signed_ nibble(!) */
-	
-						int val = nibble & 0x7;
-						if(nibble & 0x08)
-							val = -((0x7 & ~val) +1);
-						printk("^%d", val);
-					}
-				}
-			}
-			printk(")\n");
-		}
-	}
-	tab(n); printk("Report Size(%u)\n", field->report_size);
-	tab(n); printk("Report Count(%u)\n", field->report_count);
-	tab(n); printk("Report Offset(%u)\n", field->report_offset);
-
-	tab(n); printk("Flags( ");
-	j = field->flags;
-	printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
-	printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
-	printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
-	printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
-	printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
-	printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
-	printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
-	printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
-	printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
-	printk(")\n");
-}
-
-static void hid_dump_device(struct hid_device *device) {
-	struct hid_report_enum *report_enum;
-	struct hid_report *report;
-	struct list_head *list;
-	unsigned i,k;
-	static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
-	
-	for (i = 0; i < device->maxapplication; i++) {
-		printk("Application(");
-		resolv_usage(device->application[i]);
-		printk(")\n");
-	}
-
-	for (i = 0; i < HID_REPORT_TYPES; i++) {
-		report_enum = device->report_enum + i;
-		list = report_enum->report_list.next;
-		while (list != &report_enum->report_list) {
-			report = (struct hid_report *) list;
-			tab(2);
-			printk("%s", table[i]);
-			if (report->id)
-				printk("(%d)", report->id);
-			printk("[%s]", table[report->type]);
-			printk("\n");
-			for (k = 0; k < report->maxfield; k++) {
-				tab(4);
-				printk("Field(%d)\n", k);
-				hid_dump_field(report->field[k], 6);
-			}
-			list = list->next;
-		}
-	}
-}
-
-static void hid_dump_input(struct hid_usage *usage, __s32 value) {
-	printk("hid-debug: input ");
-	resolv_usage(usage->hid);
-	printk(" = %d\n", value);
-}
diff -Nru a/drivers/usb/hid-input.c b/drivers/usb/hid-input.c
--- a/drivers/usb/hid-input.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,460 +0,0 @@
-/*
- * $Id: hid-input.c,v 1.18 2001/11/07 09:01:18 vojtech Exp $
- *
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- *
- *  USB HID to Linux Input mapping
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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/slab.h>
-#include <linux/kernel.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#include "hid.h"
-
-#define unk	KEY_UNKNOWN
-
-static unsigned char hid_keyboard[256] = {
-	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
-	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
-	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
-	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
-	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
-	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
-	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
-	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
-	115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189,
-	190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk,
-	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
-	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
-	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
-	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
-	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
-	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
-};
-
-static struct {
-	__s32 x;
-	__s32 y;
-}  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage)
-{
-	struct input_dev *input = &device->input;
-	int max;
-	int is_abs = 0;
-	unsigned long *bit;
-
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-		case HID_UP_KEYBOARD:
-
-			set_bit(EV_REP, input->evbit);
-			usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-
-			if ((usage->hid & HID_USAGE) < 256) {
-				if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE]))
-					return;
-				clear_bit(usage->code, bit);
-			} else
-				usage->code = KEY_UNKNOWN;
-
-			break;
-
-		case HID_UP_BUTTON:
-
-			usage->code = ((usage->hid - 1) & 0xf) + 0x100;
-			usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-
-			switch (field->application) {
-				case HID_GD_GAMEPAD:  usage->code += 0x10;
-				case HID_GD_JOYSTICK: usage->code += 0x10;
-				case HID_GD_MOUSE:    usage->code += 0x10; break;
-				default:
-					if (field->physical == HID_GD_POINTER)
-						usage->code += 0x10;
-					break;
-			}
-			break;
-
-		case HID_UP_GENDESK:
-
-			if ((usage->hid & 0xf0) == 0x80) {	/* SystemControl */
-				switch (usage->hid & 0xf) {
-					case 0x1: usage->code = KEY_POWER;  break;
-					case 0x2: usage->code = KEY_SLEEP;  break;
-					case 0x3: usage->code = KEY_WAKEUP; break;
-					default: usage->code = KEY_UNKNOWN; break;
-				}
-				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-				break;
-			}
-
-			usage->code = usage->hid & 0xf;
-
-			if (field->report_size == 1) {
-				usage->code = BTN_MISC;
-				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-				break;
-			}
-
-			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-				usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
-				break;
-			}
-
-			usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
-
-			if (usage->hid == HID_GD_HATSWITCH) {
-				usage->code = ABS_HAT0X;
-				usage->hat_min = field->logical_minimum;
-				usage->hat_max = field->logical_maximum;
-			}
-			break;
-
-		case HID_UP_LED:
-
-			usage->code = (usage->hid - 1) & 0xf;
-			usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
-			break;
-
-		case HID_UP_DIGITIZER:
-
-			switch (usage->hid & 0xff) {
-
-				case 0x30: /* TipPressure */
-
-					if (!test_bit(BTN_TOUCH, input->keybit)) {
-						device->quirks |= HID_QUIRK_NOTOUCH;
-						set_bit(EV_KEY, input->evbit);
-						set_bit(BTN_TOUCH, input->keybit);
-					}
-					usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
-					usage->code = ABS_PRESSURE;
-					clear_bit(usage->code, bit);
-					break;
-
-				case 0x32: /* InRange */
-
-					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-					switch (field->physical & 0xff) {
-						case 0x21: usage->code = BTN_TOOL_MOUSE; break;
-						case 0x22: usage->code = BTN_TOOL_FINGER; break;
-						default: usage->code = BTN_TOOL_PEN; break;
-					}
-					break;
-
-				case 0x3c: /* Invert */
-
-					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-					usage->code = BTN_TOOL_RUBBER;
-					clear_bit(usage->code, bit);
-					break;
-
-				case 0x33: /* Touch */
-				case 0x42: /* TipSwitch */
-				case 0x43: /* TipSwitch2 */
-
-					device->quirks &= ~HID_QUIRK_NOTOUCH;
-					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-					usage->code = BTN_TOUCH;
-					clear_bit(usage->code, bit);
-					break;
-
-				case 0x44: /* BarrelSwitch */
-
-					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-					usage->code = BTN_STYLUS;
-					clear_bit(usage->code, bit);
-					break;
-
-				default:  goto unknown;
-			}
-			break;
-
-		case HID_UP_CONSUMER:	/* USB HUT v1.1, pages 56-62 */
-
-			set_bit(EV_REP, input->evbit);
-			switch (usage->hid & HID_USAGE) {
-				case 0x000: usage->code = 0; break;
-				case 0x034: usage->code = KEY_SLEEP;		break;
-				case 0x036: usage->code = BTN_MISC;		break;
-				case 0x08a: usage->code = KEY_WWW;		break;
-				case 0x095: usage->code = KEY_HELP;		break;
-
-				case 0x0b0: usage->code = KEY_PLAY;		break;
-				case 0x0b1: usage->code = KEY_PAUSE;		break;
-				case 0x0b2: usage->code = KEY_RECORD;		break;
-				case 0x0b3: usage->code = KEY_FASTFORWARD;	break;
-				case 0x0b4: usage->code = KEY_REWIND;		break;
-				case 0x0b5: usage->code = KEY_NEXTSONG;		break;
-				case 0x0b6: usage->code = KEY_PREVIOUSSONG;	break;
-				case 0x0b7: usage->code = KEY_STOPCD;		break;
-				case 0x0b8: usage->code = KEY_EJECTCD;		break;
-				case 0x0cd: usage->code = KEY_PLAYPAUSE;	break;
-			        case 0x0e0: is_abs = 1;
-					    usage->code = ABS_VOLUME;
-					    break;
-				case 0x0e2: usage->code = KEY_MUTE;		break;
-				case 0x0e5: usage->code = KEY_BASSBOOST;	break;
-				case 0x0e9: usage->code = KEY_VOLUMEUP;		break;
-				case 0x0ea: usage->code = KEY_VOLUMEDOWN;	break;
-
-				case 0x183: usage->code = KEY_CONFIG;		break;
-				case 0x18a: usage->code = KEY_MAIL;		break;
-				case 0x192: usage->code = KEY_CALC;		break;
-				case 0x194: usage->code = KEY_FILE;		break;
-				case 0x21a: usage->code = KEY_UNDO;		break;
-				case 0x21b: usage->code = KEY_COPY;		break;
-				case 0x21c: usage->code = KEY_CUT;		break;
-				case 0x21d: usage->code = KEY_PASTE;		break;
-
-				case 0x221: usage->code = KEY_FIND;		break;
-				case 0x223: usage->code = KEY_HOMEPAGE;		break;
-				case 0x224: usage->code = KEY_BACK;		break;
-				case 0x225: usage->code = KEY_FORWARD;		break;
-				case 0x226: usage->code = KEY_STOP;		break;
-				case 0x227: usage->code = KEY_REFRESH;		break;
-				case 0x22a: usage->code = KEY_BOOKMARKS;	break;
-
-				default:    usage->code = KEY_UNKNOWN;		break;
-			}
-
-			if (is_abs) {
-			        usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
-			} else  {
-				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-			}
-			break;
-
-		case HID_UP_HPVENDOR:	/* Reported on a Dutch layout HP5308 */
-
-			set_bit(EV_REP, input->evbit);
-			switch (usage->hid & HID_USAGE) {
-			        case 0x021: usage->code = KEY_PRINT;            break;
-				case 0x070: usage->code = KEY_HP;		break;
-				case 0x071: usage->code = KEY_CAMERA;		break;
-				case 0x072: usage->code = KEY_SOUND;		break;
-				case 0x073: usage->code = KEY_QUESTION;		break;
-
-				case 0x080: usage->code = KEY_EMAIL;		break;
-				case 0x081: usage->code = KEY_CHAT;		break;
-				case 0x082: usage->code = KEY_SEARCH;		break;
-				case 0x083: usage->code = KEY_CONNECT;	        break;
-				case 0x084: usage->code = KEY_FINANCE;		break;
-				case 0x085: usage->code = KEY_SPORT;		break;
-				case 0x086: usage->code = KEY_SHOP;	        break;
-
-				default:    usage->code = KEY_UNKNOWN;		break;
-
-			}
-
-			usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-			break;
-
-		default:
-		unknown:
-
-			if (field->report_size == 1) {
-
-				if (field->report->type == HID_OUTPUT_REPORT) {
-					usage->code = LED_MISC;
-					usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
-					break;
-				}
-
-				usage->code = BTN_MISC;
-				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
-				break;
-			}
-
-			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-				usage->code = REL_MISC;
-				usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
-				break;
-			}
-
-			usage->code = ABS_MISC;
-			usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
-			break;
-	}
-
-	set_bit(usage->type, input->evbit);
-
-	while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
-		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
-	}
-
-	if (usage->code > max) return;
-
-	if (usage->type == EV_ABS) {
-		int a = field->logical_minimum;
-		int b = field->logical_maximum;
-
-		input->absmin[usage->code] = a;
-		input->absmax[usage->code] = b;
-		input->absfuzz[usage->code] = (b - a) >> 8;
-		input->absflat[usage->code] = (b - a) >> 4;
-	}
-
-	if (usage->hat_min != usage->hat_max) {
-		int i;
-		for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
-			input->absmax[i] = 1;
-			input->absmin[i] = -1;
-			input->absfuzz[i] = 0;
-			input->absflat[i] = 0;
-		}
-		set_bit(usage->code + 1, input->absbit);
-	}
-}
-
-void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
-	struct input_dev *input = &hid->input;
-	int *quirks = &hid->quirks;
-
-	if (usage->hat_min != usage->hat_max) {
-		value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
-		if (value < 0 || value > 8) value = 0;
-		input_event(input, usage->type, usage->code    , hid_hat_to_axis[value].x);
-		input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y);
-		return;
-	}
-
-	if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
-		*quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
-		return;
-	}
-
-	if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
-		if (value) {
-			input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
-			return;
-		}
-		input_event(input, usage->type, usage->code, 0);
-		input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
-		return;
-	}
-
-	if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
-		int a = field->logical_minimum;
-		int b = field->logical_maximum;
-		input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
-	}
-
-	if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
-		return;
-
-	input_event(input, usage->type, usage->code, value);
-
-	if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
-		input_event(input, usage->type, usage->code, 0);
-}
-
-static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	struct hid_device *hid = dev->private;
-	struct hid_field *field = NULL;
-	int offset;
-
-	if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
-		warn("event field not found");
-		return -1;
-	}
-
-	hid_set_field(field, offset, value);
-	hid_submit_report(hid, field->report, USB_DIR_OUT);
-
-	return 0;
-}
-
-static int hidinput_open(struct input_dev *dev)
-{
-	struct hid_device *hid = dev->private;
-	return hid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
-	struct hid_device *hid = dev->private;
-	hid_close(hid);
-}
-
-/*
- * Register the input device; print a message.
- * Configure the input layer interface
- * Read all reports and initalize the absoulte field values.
- */
-
-int hidinput_connect(struct hid_device *hid)
-{
-	struct usb_device *dev = hid->dev;
-	struct hid_report_enum *report_enum;
-	struct hid_report *report;
-	struct list_head *list;
-	int i, j, k;
-
-	for (i = 0; i < hid->maxapplication; i++)
-		if (IS_INPUT_APPLICATION(hid->application[i]))
-			break;
-
-	if (i == hid->maxapplication)
-		return -1;
-
-	hid->input.private = hid;
-	hid->input.event = hidinput_input_event;
-	hid->input.open = hidinput_open;
-	hid->input.close = hidinput_close;
-
-	hid->input.name = hid->name;
-	hid->input.phys = hid->phys;
-	hid->input.uniq = hid->uniq;
-	hid->input.idbus = BUS_USB;
-	hid->input.idvendor = dev->descriptor.idVendor;
-	hid->input.idproduct = dev->descriptor.idProduct;
-	hid->input.idversion = dev->descriptor.bcdDevice;
-
-	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
-		report_enum = hid->report_enum + k;
-		list = report_enum->report_list.next;
-		while (list != &report_enum->report_list) {
-			report = (struct hid_report *) list;
-			for (i = 0; i < report->maxfield; i++)
-				for (j = 0; j < report->field[i]->maxusage; j++)
-					hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j);
-			list = list->next;
-		}
-	}
-
-	input_register_device(&hid->input);
-
-	return 0;
-}
-
-void hidinput_disconnect(struct hid_device *hid)
-{
-	input_unregister_device(&hid->input);
-}
diff -Nru a/drivers/usb/hid.h b/drivers/usb/hid.h
--- a/drivers/usb/hid.h	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,415 +0,0 @@
-#ifndef __HID_H
-#define __HID_H
-
-/*
- * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $
- *
- *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2001 Vojtech Pavlik
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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/types.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-
-/*
- * USB HID (Human Interface Device) interface class code
- */
-
-#define USB_INTERFACE_CLASS_HID		3
-
-/*
- * HID class requests
- */
-
-#define HID_REQ_GET_REPORT		0x01
-#define HID_REQ_GET_IDLE		0x02
-#define HID_REQ_GET_PROTOCOL		0x03
-#define HID_REQ_SET_REPORT		0x09
-#define HID_REQ_SET_IDLE		0x0A
-#define HID_REQ_SET_PROTOCOL		0x0B
-
-/*
- * HID class descriptor types
- */
-
-#define HID_DT_HID			(USB_TYPE_CLASS | 0x01)
-#define HID_DT_REPORT			(USB_TYPE_CLASS | 0x02)
-#define HID_DT_PHYSICAL			(USB_TYPE_CLASS | 0x03)
-
-/*
- * We parse each description item into this structure. Short items data
- * values are expanded to 32-bit signed int, long items contain a pointer
- * into the data area.
- */
-
-struct hid_item {
-	unsigned  format;
-	__u8      size;
-	__u8      type;
-	__u8      tag;
-	union {
-	    __u8   u8;
-	    __s8   s8;
-	    __u16  u16;
-	    __s16  s16;
-	    __u32  u32;
-	    __s32  s32;
-	    __u8  *longdata;
-	} data;
-};
-
-/*
- * HID report item format
- */
-
-#define HID_ITEM_FORMAT_SHORT	0
-#define HID_ITEM_FORMAT_LONG	1
-
-/*
- * Special tag indicating long items
- */
-
-#define HID_ITEM_TAG_LONG	15
-
-/*
- * HID report descriptor item type (prefix bit 2,3)
- */
-
-#define HID_ITEM_TYPE_MAIN		0
-#define HID_ITEM_TYPE_GLOBAL		1
-#define HID_ITEM_TYPE_LOCAL		2
-#define HID_ITEM_TYPE_RESERVED		3
-
-/*
- * HID report descriptor main item tags
- */
-
-#define HID_MAIN_ITEM_TAG_INPUT			8
-#define HID_MAIN_ITEM_TAG_OUTPUT		9
-#define HID_MAIN_ITEM_TAG_FEATURE		11
-#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION	10
-#define HID_MAIN_ITEM_TAG_END_COLLECTION	12
-
-/*
- * HID report descriptor main item contents
- */
-
-#define HID_MAIN_ITEM_CONSTANT		0x001
-#define HID_MAIN_ITEM_VARIABLE		0x002
-#define HID_MAIN_ITEM_RELATIVE		0x004
-#define HID_MAIN_ITEM_WRAP		0x008	
-#define HID_MAIN_ITEM_NONLINEAR		0x010
-#define HID_MAIN_ITEM_NO_PREFERRED	0x020
-#define HID_MAIN_ITEM_NULL_STATE	0x040
-#define HID_MAIN_ITEM_VOLATILE		0x080
-#define HID_MAIN_ITEM_BUFFERED_BYTE	0x100
-
-/*
- * HID report descriptor collection item types
- */
-
-#define HID_COLLECTION_PHYSICAL		0
-#define HID_COLLECTION_APPLICATION	1
-#define HID_COLLECTION_LOGICAL		2
-
-/*
- * HID report descriptor global item tags
- */
-
-#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE		0
-#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM	1
-#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM	2
-#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM	3
-#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM	4
-#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT	5
-#define HID_GLOBAL_ITEM_TAG_UNIT		6
-#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE		7
-#define HID_GLOBAL_ITEM_TAG_REPORT_ID		8
-#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT	9
-#define HID_GLOBAL_ITEM_TAG_PUSH		10
-#define HID_GLOBAL_ITEM_TAG_POP			11
-
-/*
- * HID report descriptor local item tags
- */
-
-#define HID_LOCAL_ITEM_TAG_USAGE		0
-#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM	1
-#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM	2
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX	3
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM	4
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM	5
-#define HID_LOCAL_ITEM_TAG_STRING_INDEX		7
-#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM	8
-#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM	9
-#define HID_LOCAL_ITEM_TAG_DELIMITER		10
-
-/*
- * HID usage tables
- */
-
-#define HID_USAGE_PAGE		0xffff0000
-
-#define HID_UP_GENDESK 		0x00010000
-#define HID_UP_KEYBOARD 	0x00070000
-#define HID_UP_LED 		0x00080000
-#define HID_UP_BUTTON 		0x00090000
-#define HID_UP_ORDINAL 		0x000a0000
-#define HID_UP_CONSUMER		0x000c0000
-#define HID_UP_DIGITIZER 	0x000d0000
-#define HID_UP_PID 		0x000f0000
-#define HID_UP_HPVENDOR         0xff7f0000
-
-#define HID_USAGE		0x0000ffff
-
-#define HID_GD_POINTER		0x00010001
-#define HID_GD_MOUSE		0x00010002
-#define HID_GD_JOYSTICK		0x00010004
-#define HID_GD_GAMEPAD		0x00010005
-#define HID_GD_HATSWITCH	0x00010039
-
-/*
- * HID report types --- Ouch! HID spec says 1 2 3!
- */
-
-#define HID_INPUT_REPORT	0
-#define HID_OUTPUT_REPORT	1
-#define HID_FEATURE_REPORT	2
-
-/*
- * HID device quirks.
- */
-
-#define HID_QUIRK_INVERT	0x01
-#define HID_QUIRK_NOTOUCH	0x02
-#define HID_QUIRK_IGNORE	0x04
-#define HID_QUIRK_NOGET		0x08
-
-/*
- * This is the global enviroment of the parser. This information is
- * persistent for main-items. The global enviroment can be saved and
- * restored with PUSH/POP statements.
- */
-
-struct hid_global {
-	unsigned usage_page;
-	__s32    logical_minimum;
-	__s32    logical_maximum;
-	__s32    physical_minimum;
-	__s32    physical_maximum;
-	__s32    unit_exponent;
-	unsigned unit;
-	unsigned report_id;
-	unsigned report_size;
-	unsigned report_count;
-};
-
-/*
- * This is the local enviroment. It is resistent up the next main-item.
- */
-
-#define HID_MAX_DESCRIPTOR_SIZE		4096
-#define HID_MAX_USAGES			1024
-#define HID_MAX_APPLICATIONS		16
-
-struct hid_local {
-	unsigned usage[HID_MAX_USAGES]; /* usage array */
-	unsigned usage_index;
-	unsigned usage_minimum;
-	unsigned delimiter_depth;
-	unsigned delimiter_branch;
-};
-
-/*
- * This is the collection stack. We climb up the stack to determine
- * application and function of each field.
- */
-
-struct hid_collection {
-	unsigned type;
-	unsigned usage;
-};
-
-struct hid_usage {
-	unsigned  hid;			/* hid usage code */
-	__u16     code;			/* input driver code */
-	__u8      type;			/* input driver type */
-	__s8	  hat_min;		/* hat switch fun */
-	__s8	  hat_max;		/* ditto */
-};
-
-struct hid_field {
-	unsigned  physical;		/* physical usage for this field */
-	unsigned  logical;		/* logical usage for this field */
-	unsigned  application;		/* application usage for this field */
-	struct hid_usage *usage;	/* usage table for this function */
-	unsigned  maxusage;		/* maximum usage index */
-	unsigned  flags;		/* main-item flags (i.e. volatile,array,constant) */
-	unsigned  report_offset;	/* bit offset in the report */
-	unsigned  report_size;		/* size of this field in the report */
-	unsigned  report_count;		/* number of this field in the report */
-	unsigned  report_type;		/* (input,output,feature) */
-	__s32    *value;		/* last known value(s) */
-	__s32     logical_minimum;
-	__s32     logical_maximum;
-	__s32     physical_minimum;
-	__s32     physical_maximum;
-	__s32     unit_exponent;
-	unsigned  unit;
-	struct hid_report *report;	/* associated report */
-	unsigned index;			/* index into report->field[] */
-};
-
-#define HID_MAX_FIELDS 64
-
-struct hid_report {
-	struct list_head list;
-	unsigned id;					/* id of this report */
-	unsigned type;					/* report type */
-	struct hid_field *field[HID_MAX_FIELDS];	/* fields of the report */
-	unsigned maxfield;				/* maximum valid field index */
-	unsigned size;					/* size of the report (bits) */
-	struct hid_device *device;			/* associated device */
-};
-
-struct hid_report_enum {
-	unsigned numbered;
-	struct list_head report_list;
-	struct hid_report *report_id_hash[256];
-};
-
-#define HID_REPORT_TYPES 3
-
-#define HID_BUFFER_SIZE		32
-#define HID_CONTROL_FIFO_SIZE	64
-#define HID_OUTPUT_FIFO_SIZE	64
-
-struct hid_control_fifo {
-	unsigned char dir;
-	struct hid_report *report;
-};
-
-#define HID_CLAIMED_INPUT	1
-#define HID_CLAIMED_HIDDEV	2
-
-#define HID_CTRL_RUNNING	1
-#define HID_OUT_RUNNING		2
-
-struct hid_device {							/* device report descriptor */
-	 __u8 *rdesc;
-	unsigned rsize;
-	unsigned application[HID_MAX_APPLICATIONS];			/* List of HID applications */
-	unsigned maxapplication;					/* Number of applications */
-	unsigned version;						/* HID version */
-	unsigned country;						/* HID country */
-	struct hid_report_enum report_enum[HID_REPORT_TYPES];
-
-	struct usb_device *dev;						/* USB device */
-	int ifnum;							/* USB interface number */
-
-	unsigned long iofl;						/* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
-
-	struct urb *urbin;						/* Input URB */
-	char inbuf[HID_BUFFER_SIZE];					/* Input buffer */
-
-	struct urb *urbctrl;						/* Control URB */
-	struct usb_ctrlrequest cr;					/* Control request struct */
-	struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];		/* Control fifo */
-	unsigned char ctrlhead, ctrltail;				/* Control fifo head & tail */
-	char ctrlbuf[HID_BUFFER_SIZE];					/* Control buffer */
-	spinlock_t ctrllock;						/* Control fifo spinlock */
-
-	struct urb *urbout;						/* Output URB */
-	struct hid_report *out[HID_CONTROL_FIFO_SIZE];			/* Output pipe fifo */
-	unsigned char outhead, outtail;					/* Output pipe fifo head & tail */
-	char outbuf[HID_BUFFER_SIZE];					/* Output buffer */
-	spinlock_t outlock;						/* Output fifo spinlock */
-
-	unsigned claimed;						/* Claimed by hidinput, hiddev? */	
-	unsigned quirks;						/* Various quirks the device can pull on us */
-
-	struct input_dev input;						/* The input structure */
-	void *hiddev;							/* The hiddev structure */
-	int minor;							/* Hiddev minor number */
-
-	wait_queue_head_t wait;						/* For sleeping */
-
-	int open;							/* is the device open by anyone? */
-	char name[128];							/* Device name */
-	char phys[64];							/* Device physical location */
-	char uniq[64];							/* Device unique identifier (serial #) */
-};
-
-#define HID_GLOBAL_STACK_SIZE 4
-#define HID_COLLECTION_STACK_SIZE 4
-
-struct hid_parser {
-	struct hid_global     global;
-	struct hid_global     global_stack[HID_GLOBAL_STACK_SIZE];
-	unsigned              global_stack_ptr;
-	struct hid_local      local;
-	struct hid_collection collection_stack[HID_COLLECTION_STACK_SIZE];
-	unsigned              collection_stack_ptr;
-	struct hid_device    *device;
-};
-
-struct hid_class_descriptor {
-	__u8  bDescriptorType;
-	__u16 wDescriptorLength;
-} __attribute__ ((packed));
-
-struct hid_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u16 bcdHID;
-	__u8  bCountryCode;
-	__u8  bNumDescriptors;
-
-	struct hid_class_descriptor desc[1];
-} __attribute__ ((packed));
-
-void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
-int hidinput_connect(struct hid_device *);
-void hidinput_disconnect(struct hid_device *);
-
-#ifdef DEBUG
-#include "hid-debug.h"
-#else
-#define hid_dump_input(a,b)	do { } while (0)
-#define hid_dump_device(c)	do { } while (0)
-#define hid_dump_field(a,b)	do { } while (0)
-#endif
-
-#endif
-
-/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
-/* We ignore a few input applications that are not widely used */
-#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || ( a == 0x00010080) || ( a == 0x000c0001))
-
-int hid_open(struct hid_device *);
-void hid_close(struct hid_device *);
-int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
-int hid_set_field(struct hid_field *, unsigned, __s32);
-void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
-void hid_init_reports(struct hid_device *hid);
diff -Nru a/drivers/usb/hiddev.c b/drivers/usb/hiddev.c
--- a/drivers/usb/hiddev.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,721 +0,0 @@
-/*
- *  Copyright (c) 2001 Paul Stewart
- *  Copyright (c) 2001 Vojtech Pavlik
- *
- *  HID char devices, giving access to raw HID device events.
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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 Paul Stewart <stewart@wetlogic.net>
- */
-
-#define HIDDEV_MINOR_BASE	96
-#define HIDDEV_MINORS		16
-#define HIDDEV_BUFFER_SIZE	64
-
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include "hid.h"
-#include <linux/hiddev.h>
-
-struct hiddev {
-	int exist;
-	int open;
-	int minor;
-	wait_queue_head_t wait;
-	devfs_handle_t devfs;
-	struct hid_device *hid;
-	struct hiddev_list *list;
-};
-
-struct hiddev_list {
-	struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
-	int head;
-	int tail;
-	unsigned flags;
-	struct fasync_struct *fasync;
-	struct hiddev *hiddev;
-	struct hiddev_list *next;
-};
-
-static struct hiddev *hiddev_table[HIDDEV_MINORS];
-static devfs_handle_t hiddev_devfs_handle;
-
-/*
- * Find a report, given the report's type and ID.  The ID can be specified
- * indirectly by REPORT_ID_FIRST (which returns the first report of the given
- * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
- * given type which follows old_id.
- */
-static struct hid_report *
-hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
-{
-	struct hid_report_enum *report_enum;
-	struct list_head *list;
-
-	if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
-	    rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
-
-	report_enum = hid->report_enum +
-		(rinfo->report_type - HID_REPORT_TYPE_MIN);
-	if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) {
-		switch (rinfo->report_id & ~HID_REPORT_ID_MASK) {
-		case HID_REPORT_ID_FIRST:
-			list = report_enum->report_list.next;
-			if (list == &report_enum->report_list) return NULL;
-			rinfo->report_id = ((struct hid_report *) list)->id;
-			break;
-
-		case HID_REPORT_ID_NEXT:
-			list = (struct list_head *)
-				report_enum->report_id_hash[rinfo->report_id &
-							   HID_REPORT_ID_MASK];
-			if (list == NULL) return NULL;
-			list = list->next;
-			if (list == &report_enum->report_list) return NULL;
-			rinfo->report_id = ((struct hid_report *) list)->id;
-			break;
-
-		default:
-			return NULL;
-		}
-	}
-
-	return report_enum->report_id_hash[rinfo->report_id];
-}
-
-/*
- * Perform an exhaustive search of the report table for a usage, given its
- * type and usage id.
- */
-static struct hid_field *
-hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
-{
-	int i, j;
-	struct hid_report *report;
-	struct hid_report_enum *report_enum;
-	struct list_head *list;
-	struct hid_field *field;
-
-	if (uref->report_type < HID_REPORT_TYPE_MIN ||
-	    uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
-
-	report_enum = hid->report_enum +
-		(uref->report_type - HID_REPORT_TYPE_MIN);
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
-		for (i = 0; i < report->maxfield; i++) {
-			field = report->field[i];
-			for (j = 0; j < field->maxusage; j++) {
-				if (field->usage[j].hid == uref->usage_code) {
-					uref->report_id = report->id;
-					uref->field_index = i;
-					uref->usage_index = j;
-					return field;
-				}
-			}
-		}
-		list = list->next;
-	}
-
-	return NULL;
-}
-
-/*
- * This is where hid.c calls into hiddev to pass an event that occurred over
- * the interrupt pipe
- */
-void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
-{
-	struct hiddev *hiddev = hid->hiddev;
-	struct hiddev_list *list = hiddev->list;
-
-	while (list) {
-		if (uref->field_index != HID_FIELD_INDEX_NONE ||
-		    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
-			list->buffer[list->head] = *uref;
-			list->head = (list->head + 1) & 
-				(HIDDEV_BUFFER_SIZE - 1);
-			kill_fasync(&list->fasync, SIGIO, POLL_IN);
-		}
-
-		list = list->next;
-	}
-
-	wake_up_interruptible(&hiddev->wait);
-}
-
-/*
- * fasync file op
- */
-static int hiddev_fasync(int fd, struct file *file, int on)
-{
-	int retval;
-	struct hiddev_list *list = file->private_data;
-	retval = fasync_helper(fd, file, on, &list->fasync);
-	return retval < 0 ? retval : 0;
-}
-
-/*
- * De-allocate a hiddev structure
- */
-static void hiddev_cleanup(struct hiddev *hiddev)
-{
-	devfs_unregister(hiddev->devfs);
-	hiddev_table[hiddev->minor] = NULL;
-	kfree(hiddev);
-}
-
-/*
- * release file op
- */
-static int hiddev_release(struct inode * inode, struct file * file)
-{
-	struct hiddev_list *list = file->private_data;
-	struct hiddev_list **listptr;
-
-	listptr = &list->hiddev->list;
-	hiddev_fasync(-1, file, 0);
-
-	while (*listptr && (*listptr != list))
-		listptr = &((*listptr)->next);
-	*listptr = (*listptr)->next;
-
-	if (!--list->hiddev->open) {
-		if (list->hiddev->exist) 
-			hid_close(list->hiddev->hid);
-		else
-			hiddev_cleanup(list->hiddev);
-	}
-
-	kfree(list);
-
-	return 0;
-}
-
-/*
- * open file op
- */
-static int hiddev_open(struct inode * inode, struct file * file) {
-	struct hiddev_list *list;
-
-	int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
-
-	if (i >= HIDDEV_MINORS || !hiddev_table[i])
-		return -ENODEV;
-
-	if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
-		return -ENOMEM;
-	memset(list, 0, sizeof(struct hiddev_list));
-
-	list->hiddev = hiddev_table[i];
-	list->next = hiddev_table[i]->list;
-	hiddev_table[i]->list = list;
-
-	file->private_data = list;
-
-	if (!list->hiddev->open++)
-		if (list->hiddev->exist)
-			hid_open(hiddev_table[i]->hid);
-
-	return 0;
-}
-
-/*
- * "write" file op
- */
-static ssize_t hiddev_write(struct file * file, const char * buffer,
-			    size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-/*
- * "read" file op
- */
-static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
-			   loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct hiddev_list *list = file->private_data;
-	int event_size;
-	int retval = 0;
-
-	event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
-		sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
-
-	if (count < event_size) return 0;
-
-	while (retval == 0) {
-		if (list->head == list->tail) {
-			add_wait_queue(&list->hiddev->wait, &wait);
-			set_current_state(TASK_INTERRUPTIBLE);
-			
-			while (list->head == list->tail) {
-				if (file->f_flags & O_NONBLOCK) {
-					retval = -EAGAIN;
-					break;
-				}
-				if (signal_pending(current)) {
-					retval = -ERESTARTSYS;
-					break;
-				}
-				if (!list->hiddev->exist) {
-					retval = -EIO;
-					break;
-				}
-				
-				schedule();
-			}
-
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&list->hiddev->wait, &wait);
-		}
-
-		if (retval)
-			return retval;
-
-
-		while (list->head != list->tail && 
-		       retval + event_size <= count) {
-			if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
-				if (list->buffer[list->tail].field_index !=
-				    HID_FIELD_INDEX_NONE) {
-					struct hiddev_event event;
-					event.hid = list->buffer[list->tail].usage_code;
-					event.value = list->buffer[list->tail].value;
-					if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
-						return -EFAULT;
-					retval += sizeof(struct hiddev_event);
-				}
-			} else {
-				if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
-				    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
-					if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
-						return -EFAULT;
-					retval += sizeof(struct hiddev_usage_ref);
-				}
-			}
-			list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
-		}
-
-	}
-
-	return retval;
-}
-
-/*
- * "poll" file op
- * No kernel lock - fine
- */
-static unsigned int hiddev_poll(struct file *file, poll_table *wait)
-{
-	struct hiddev_list *list = file->private_data;
-	poll_wait(file, &list->hiddev->wait, wait);
-	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
-	if (!list->hiddev->exist)
-		return POLLERR | POLLHUP;
-	return 0;
-}
-
-#define GET_TIMEOUT 3
-#define SET_TIMEOUT 3
-
-/*
- * "ioctl" file op
- */
-static int hiddev_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, unsigned long arg)
-{
-	struct hiddev_list *list = file->private_data;
-	struct hiddev *hiddev = list->hiddev;
-	struct hid_device *hid = hiddev->hid;
-	struct usb_device *dev = hid->dev;
-	struct hiddev_report_info rinfo;
-	struct hiddev_usage_ref uref;
-	struct hid_report *report;
-	struct hid_field *field;
-
-	if (!hiddev->exist) return -EIO;
-
-	switch (cmd) {
-
-	case HIDIOCGVERSION:
-		return put_user(HID_VERSION, (int *) arg);
-
-	case HIDIOCAPPLICATION:
-		if (arg < 0 || arg >= hid->maxapplication)
-			return -EINVAL;
-		return hid->application[arg];
-
-	case HIDIOCGDEVINFO:
-	{
-		struct hiddev_devinfo dinfo;
-		dinfo.bustype = BUS_USB;
-		dinfo.busnum = dev->bus->busnum;
-		dinfo.devnum = dev->devnum;
-		dinfo.ifnum = hid->ifnum;
-		dinfo.vendor = dev->descriptor.idVendor;
-		dinfo.product = dev->descriptor.idProduct;
-		dinfo.version = dev->descriptor.bcdDevice;
-		dinfo.num_applications = hid->maxapplication;
-		return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
-	}
-
-	case HIDIOCGFLAG:
-		return put_user(list->flags, (int *) arg);
-
-	case HIDIOCSFLAG:
-		{
-			int newflags;
-			if (get_user(newflags, (int *) arg))
-				return -EFAULT;
-
-			if ((newflags & ~HIDDEV_FLAGS) != 0 ||
-			    ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
-			     (newflags & HIDDEV_FLAG_UREF) == 0))
-				return -EINVAL;
-
-			list->flags = newflags;
-
-			return 0;
-		}
-
-	case HIDIOCGSTRING:
-		{
-			int idx, len;
-			char *buf;
-
-			if (get_user(idx, (int *) arg))
-				return -EFAULT;
-
-			if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
-				return -ENOMEM;
-
-			if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
-				kfree(buf);
-				return -EINVAL;
-			}
-
-			if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) {
-				kfree(buf);
-				return -EFAULT;
-			}
-
-			kfree(buf);
-
-			return len;
-		}
-
-	case HIDIOCINITREPORT:
-
-		hid_init_reports(hid);
-
-		return 0;
-
-	case HIDIOCGREPORT:
-		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
-			return -EFAULT;
-
-		if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
-			return -EINVAL;
-
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		hid_submit_report(hid, report, USB_DIR_IN);
-
-		return 0;
-
-	case HIDIOCSREPORT:
-		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
-			return -EFAULT;
-
-		if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
-			return -EINVAL;
-
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		hid_submit_report(hid, report, USB_DIR_OUT);
-
-		return 0;
-
-	case HIDIOCGREPORTINFO:
-		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
-			return -EFAULT;
-
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		rinfo.num_fields = report->maxfield;
-
-		return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
-
-	case HIDIOCGFIELDINFO:
-	{
-		struct hiddev_field_info finfo;
-		if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
-			return -EFAULT;
-		rinfo.report_type = finfo.report_type;
-		rinfo.report_id = finfo.report_id;
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		if (finfo.field_index >= report->maxfield)
-			return -EINVAL;
-
-		field = report->field[finfo.field_index];
-		memset(&finfo, 0, sizeof(finfo));
-		finfo.report_type = rinfo.report_type;
-		finfo.report_id = rinfo.report_id;
-		finfo.field_index = field->report_count - 1;
-		finfo.maxusage = field->maxusage;
-		finfo.flags = field->flags;
-		finfo.physical = field->physical;
-		finfo.logical = field->logical;
-		finfo.application = field->application;
-		finfo.logical_minimum = field->logical_minimum;
-		finfo.logical_maximum = field->logical_maximum;
-		finfo.physical_minimum = field->physical_minimum;
-		finfo.physical_maximum = field->physical_maximum;
-		finfo.unit_exponent = field->unit_exponent;
-		finfo.unit = field->unit;
-
-		return copy_to_user((void *) arg, &finfo, sizeof(finfo));
-	}
-
-	case HIDIOCGUCODE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
-
-		rinfo.report_type = uref.report_type;
-		rinfo.report_id = uref.report_id;
-		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-			return -EINVAL;
-
-		if (uref.field_index >= report->maxfield)
-			return -EINVAL;
-
-		field = report->field[uref.field_index];
-		if (uref.usage_index >= field->maxusage)
-			return -EINVAL;
-
-		uref.usage_code = field->usage[uref.usage_index].hid;
-
-		return copy_to_user((void *) arg, &uref, sizeof(uref));
-
-	case HIDIOCGUSAGE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
-
-		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, &uref);
-			if (field == NULL)
-				return -EINVAL;
-		} else {
-			rinfo.report_type = uref.report_type;
-			rinfo.report_id = uref.report_id;
-			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-				return -EINVAL;
-
-			if (uref.field_index >= report->maxfield)
-				return -EINVAL;
-
-			field = report->field[uref.field_index];
-			if (uref.usage_index >= field->maxusage)
-				return -EINVAL;
-		}
-
-		uref.value = field->value[uref.usage_index];
-
-		return copy_to_user((void *) arg, &uref, sizeof(uref));
-
-	case HIDIOCSUSAGE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
-
-		if (uref.report_type == HID_REPORT_TYPE_INPUT)
-			return -EINVAL;
-
-		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, &uref);
-			if (field == NULL)
-				return -EINVAL;
-		} else {
-			rinfo.report_type = uref.report_type;
-			rinfo.report_id = uref.report_id;
-			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-				return -EINVAL;
-
-			if (uref.field_index >= report->maxfield)
-				return -EINVAL;
-
-			field = report->field[uref.field_index];
-			if (uref.usage_index >= field->maxusage)
-				return -EINVAL;
-		}
-
-		field->value[uref.usage_index] = uref.value;
-
-		return 0;
-
-	default:
-
-		if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
-			return -EINVAL;
-
-		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
-			int len;
-			if (!hid->name) return 0;
-			len = strlen(hid->name) + 1;
-			if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-			return copy_to_user((char *) arg, hid->name, len) ?
-				-EFAULT : len;
-		}
-	}
-	return -EINVAL;
-}
-
-static struct file_operations hiddev_fops = {
-	owner:		THIS_MODULE,
-	read:		hiddev_read,
-	write:		hiddev_write,
-	poll:		hiddev_poll,
-	open:		hiddev_open,
-	release:	hiddev_release,
-	ioctl:		hiddev_ioctl,
-	fasync:		hiddev_fasync,
-};
-
-/*
- * This is where hid.c calls us to connect a hid device to the hiddev driver
- */
-int hiddev_connect(struct hid_device *hid)
-{
-	struct hiddev *hiddev;
-	int minor, i;
-	char devfs_name[16];
-
-	for (i = 0; i < hid->maxapplication; i++)
-		if (!IS_INPUT_APPLICATION(hid->application[i]))
-			break;
-
-	if (i == hid->maxapplication)
-		return -1;
-
-	for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
-	if (minor == HIDDEV_MINORS) {
-		printk(KERN_ERR "hiddev: no more free hiddev devices\n");
-		return -1;
-	}
-
-	if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
-		return -1;
-	memset(hiddev, 0, sizeof(struct hiddev));
-
-	init_waitqueue_head(&hiddev->wait);
-
-	hiddev->minor = minor;
-	hiddev_table[minor] = hiddev;
-
-	hiddev->hid = hid;
-	hiddev->exist = 1;
-
-	sprintf(devfs_name, "hiddev%d", minor);
-	hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
-				       DEVFS_FL_DEFAULT, USB_MAJOR,
-				       minor + HIDDEV_MINOR_BASE,
-				       S_IFCHR | S_IRUGO | S_IWUSR,
-				       &hiddev_fops, NULL);
-	hid->minor = minor;
-	hid->hiddev = hiddev;
-
-	return 0;
-}
-
-/*
- * This is where hid.c calls us to disconnect a hiddev device from the
- * corresponding hid device (usually because the usb device has disconnected)
- */
-void hiddev_disconnect(struct hid_device *hid)
-{
-	struct hiddev *hiddev = hid->hiddev;
-
-	hiddev->exist = 0;
-
-	if (hiddev->open) {
-		hid_close(hiddev->hid);
-		wake_up_interruptible(&hiddev->wait);
-	} else {
-		hiddev_cleanup(hiddev);
-	}
-}
-
-/* Currently this driver is a USB driver.  It's not a conventional one in
- * the sense that it doesn't probe at the USB level.  Instead it waits to
- * be connected by HID through the hiddev_connect / hiddev_disconnect
- * routines.  The reason to register as a USB device is to gain part of the
- * minor number space from the USB major.
- *
- * In theory, should the HID code be generalized to more than one physical
- * medium (say, IEEE 1384), this driver will probably need to register its
- * own major number, and in doing so, no longer need to register with USB.
- * At that point the probe routine and hiddev_driver struct below will no
- * longer be useful.
- */
-
-
-/* We never attach in this manner, and rely on HID to connect us.  This
- * is why there is no disconnect routine defined in the usb_driver either.
- */
-static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum,
-			  const struct usb_device_id *hiddev_info)
-{
-	return NULL;
-}
-
-
-static /* const */ struct usb_driver hiddev_driver = {
-	name:	"hiddev",
-	probe:	hiddev_usbd_probe,
-	fops:	&hiddev_fops,
-	minor:	HIDDEV_MINOR_BASE
-};
-
-int __init hiddev_init(void)
-{
-	hiddev_devfs_handle =
-		devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL);
-	usb_register(&hiddev_driver);
-	return 0;
-}
-
-void __exit hiddev_exit(void)
-{
-	devfs_unregister(hiddev_devfs_handle);
-	usb_deregister(&hiddev_driver);
-}
diff -Nru a/drivers/usb/host/Config.help b/drivers/usb/host/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/Config.help	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,91 @@
+CONFIG_USB_EHCI_HCD
+  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
+  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
+  If your USB host controller supports USB 2.0, you will likely want to
+  configure this Host Controller Driver.  At this writing, the primary
+  implementation of EHCI is a chip from NEC, widely available in add-on
+  PCI cards, but implementations are in the works from other vendors
+  including Intel and Philips.  Motherboard support is appearing.
+
+  EHCI controllers are packaged with "companion" host controllers (OHCI
+  or UHCI) to handle USB 1.1 devices connected to root hub ports.  Ports
+  will connect to EHCI if it the device is high speed, otherwise they
+  connect to a companion controller.  If you configure EHCI, you should
+  probably configure the OHCI (for NEC and some other vendors) USB Host
+  Controller Driver too.
+
+  You may want to read <file:Documentation/usb/ehci.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ehci-hcd.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_OHCI_HCD
+  The Open Host Controller Interface (OHCI) is a standard for accessing
+  USB 1.1 host controller hardware.  It does more in hardware than Intel's
+  UHCI specification.  If your USB host controller follows the OHCI spec,
+  say Y.  On most non-x86 systems, and on x86 hardware that's not using a
+  USB controller from Intel or VIA, this is appropriate.  If your host
+  controller doesn't use PCI, this is probably appropriate.  For a PCI
+  based system where you're not sure, the "lspci -v" entry will list the
+  right "prog-if" for your USB controller(s):  EHCI, OHCI, or UHCI.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ohci-hcd.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_UHCI
+  The Universal Host Controller Interface is a standard by Intel for
+  accessing the USB hardware in the PC (which is also called the USB
+  host controller). If your USB host controller conforms to this
+  standard, you may want to say Y, but see below. All recent boards
+  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+  i810, i820) conform to this standard. Also all VIA PCI chipsets
+  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+  133).
+
+  Currently there exist two drivers for UHCI host controllers: this
+  one and the so-called JE driver, which you can get from
+  "UHCI alternate (JE) support", below. You need only one.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-uhci.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_UHCI_ALT
+  The Universal Host Controller Interface is a standard by Intel for
+  accessing the USB hardware in the PC (which is also called the USB
+  host controller). If your USB host controller conforms to this
+  standard, you may want to say Y, but see below. All recent boards
+  with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
+  i810, i820) conform to this standard. Also all VIA PCI chipsets
+  (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
+  133). If unsure, say Y.
+
+  Currently there exist two drivers for UHCI host controllers: this
+  so-called JE driver, and the one you get from "UHCI support", above.
+  You need only one.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called uhci.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_OHCI
+  The Open Host Controller Interface is a standard by
+  Compaq/Microsoft/National for accessing the USB PC hardware (also
+  called USB host controller). If your USB host controller conforms to
+  this standard, say Y. The USB host controllers on most non-Intel
+  architectures and on several x86 compatibles with non-Intel chipsets
+  -- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
+  Aladdin Pro..) -- conform to this standard.
+
+  You may want to read <file:Documentation/usb/ohci.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-ohci.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/host/Config.in b/drivers/usb/host/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/Config.in	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,25 @@
+#
+# USB Host Controller Drivers
+#
+comment 'USB Host Controller Drivers'
+dep_tristate '  EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate '  OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+# dep_tristate '  UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
+if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
+   dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
+fi
+if [ "$CONFIG_USB_UHCI" != "y" ]; then
+   dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
+else
+   define_bool CONFIG_USB_UHCI_ALT n
+fi
+dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
+
+# Turn on CONFIG_USB_HOST if any of the Host controller drivers are compiled
+# into the kernel to make our Makefile logic a bit simpler
+if [ "$CONFIG_USB_EHCI_HCD" = "y" -o "$CONFIG_USB_OHCI_HCD" = "y" -o "$CONFIG_USB_UHCI_HCD" = "y" ]; then
+   define_bool CONFIG_USB_HOST y
+fi
+if [ "$CONFIG_USB_UHCI" = "y" -o "$CONFIG_USB_UHCI_ALT" = "y" -o "$CONFIG_USB_OHCI" = "y" ]; then
+   define_bool CONFIG_USB_HOST y
+fi
diff -Nru a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/Makefile	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,16 @@
+#
+# Makefile for USB Host Controller Driver
+# framework and drivers
+#
+
+O_TARGET	:= usb-host.o
+
+obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
+obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
+# obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o
+
+obj-$(CONFIG_USB_UHCI)		+= usb-uhci.o
+obj-$(CONFIG_USB_UHCI_ALT)	+= uhci.o
+obj-$(CONFIG_USB_OHCI)		+= usb-ohci.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci-dbg.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+#ifdef EHCI_VERBOSE_DEBUG
+#	define vdbg dbg
+#else
+	static inline void vdbg (char *fmt, ...) { }
+#endif
+
+#ifdef	DEBUG
+
+/* check the values in the HCSPARAMS register - host controller structural parameters */
+/* see EHCI 0.95 Spec, Table 2-4 for each value */
+static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
+{
+	u32	params = readl (&ehci->caps->hcs_params);
+
+	dbg ("%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d",
+		label, params,
+		HCS_DEBUG_PORT (params),
+		HCS_INDICATOR (params) ? " ind" : "",
+		HCS_N_CC (params),
+		HCS_N_PCC (params),
+	        HCS_PORTROUTED (params) ? "" : " ordered",
+		HCS_PPC (params) ? "" : " !ppc",
+		HCS_N_PORTS (params)
+		);
+	/* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */
+	if (HCS_PORTROUTED (params)) {
+		int i;
+		char buf [46], tmp [7], byte;
+
+		buf[0] = 0;
+		for (i = 0; i < HCS_N_PORTS (params); i++) {
+			byte = readb (&ehci->caps->portroute[(i>>1)]);
+			sprintf(tmp, "%d ", 
+				((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
+			strcat(buf, tmp);
+		}
+		dbg ("%s: %s portroute %s", 
+			ehci->hcd.bus_name, label,
+			buf);
+	}
+}
+#else
+
+static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {}
+
+#endif
+
+#ifdef	DEBUG
+
+/* check the values in the HCCPARAMS register - host controller capability parameters */
+/* see EHCI 0.95 Spec, Table 2-5 for each value */
+static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
+{
+	u32	params = readl (&ehci->caps->hcc_params);
+
+	if (HCC_EXT_CAPS (params)) {
+		// EHCI 0.96 ... could interpret these (legacy?)
+		dbg ("%s extended capabilities at pci %d",
+			label, HCC_EXT_CAPS (params));
+	}
+	if (HCC_ISOC_CACHE (params)) {
+		dbg ("%s hcc_params 0x%04x caching frame %s%s%s",
+		     label, params,
+		     HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
+		     HCC_CANPARK (params) ? " park" : "",
+		     HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+	} else {
+		dbg ("%s hcc_params 0x%04x caching %d uframes %s%s%s",
+		     label,
+		     params,
+		     HCC_ISOC_THRES (params),
+		     HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
+		     HCC_CANPARK (params) ? " park" : "",
+		     HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+	}
+}
+#else
+
+static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
+
+#endif
+
+#ifdef	DEBUG
+
+#if 0
+static void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+	dbg ("%s %p info1 %x info2 %x hw_curr %x qtd_next %x", label,
+		qh, qh->hw_info1, qh->hw_info2,
+		qh->hw_current, qh->hw_qtd_next);
+	dbg ("  alt+errs= %x, token= %x, page0= %x, page1= %x",
+		qh->hw_alt_next, qh->hw_token,
+		qh->hw_buf [0], qh->hw_buf [1]);
+	if (qh->hw_buf [2]) {
+		dbg ("  page2= %x, page3= %x, page4= %x",
+			qh->hw_buf [2], qh->hw_buf [3],
+			qh->hw_buf [4]);
+	}
+}
+#endif
+
+static const char *const fls_strings [] =
+    { "1024", "512", "256", "??" };
+
+#else
+#if 0
+static inline void dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {}
+#endif
+#endif	/* DEBUG */
+
+/* functions have the "wrong" filename when they're output... */
+
+#define dbg_status(ehci, label, status) \
+	dbg ("%s status 0x%x%s%s%s%s%s%s%s%s%s%s", \
+		label, status, \
+		(status & STS_ASS) ? " Async" : "", \
+		(status & STS_PSS) ? " Periodic" : "", \
+		(status & STS_RECL) ? " Recl" : "", \
+		(status & STS_HALT) ? " Halt" : "", \
+		(status & STS_IAA) ? " IAA" : "", \
+		(status & STS_FATAL) ? " FATAL" : "", \
+		(status & STS_FLR) ? " FLR" : "", \
+		(status & STS_PCD) ? " PCD" : "", \
+		(status & STS_ERR) ? " ERR" : "", \
+		(status & STS_INT) ? " INT" : "" \
+		)
+
+#define dbg_cmd(ehci, label, command) \
+	dbg ("%s %x cmd %s=%d ithresh=%d%s%s%s%s period=%s%s %s", \
+		label, command, \
+		(command & CMD_PARK) ? "park" : "(park)", \
+		CMD_PARK_CNT (command), \
+		(command >> 16) & 0x3f, \
+		(command & CMD_LRESET) ? " LReset" : "", \
+		(command & CMD_IAAD) ? " IAAD" : "", \
+		(command & CMD_ASE) ? " Async" : "", \
+		(command & CMD_PSE) ? " Periodic" : "", \
+		fls_strings [(command >> 2) & 0x3], \
+		(command & CMD_RESET) ? " Reset" : "", \
+		(command & CMD_RUN) ? "RUN" : "HALT" \
+		)
+
+#define dbg_port(hcd, label, port, status) \
+	dbg ("%s port %d status 0x%x%s%s speed=%d%s%s%s%s%s%s%s%s%s", \
+		label, port, status, \
+		(status & PORT_OWNER) ? " OWNER" : "", \
+		(status & PORT_POWER) ? " POWER" : "", \
+		(status >> 10) & 3, \
+		(status & PORT_RESET) ? " RESET" : "", \
+		(status & PORT_SUSPEND) ? " SUSPEND" : "", \
+		(status & PORT_RESUME) ? " RESUME" : "", \
+		(status & PORT_OCC) ? " OCC" : "", \
+		(status & PORT_OC) ? " OC" : "", \
+		(status & PORT_PEC) ? " PEC" : "", \
+		(status & PORT_PE) ? " PE" : "", \
+		(status & PORT_CSC) ? " CSC" : "", \
+		(status & PORT_CONNECT) ? " CONNECT" : "" \
+	    )
+
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci-hcd.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,762 @@
+/*
+ * Copyright (c) 2000-2002 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/usb.h>
+#include "../core/hcd.h"
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+//#undef KERN_DEBUG
+//#define KERN_DEBUG ""
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI hc_driver implementation ... experimental, incomplete.
+ * Based on the 0.96 register interface specification.
+ *
+ * There are lots of things to help out with here ... notably
+ * everything "periodic", and of course testing with all sorts
+ * of usb 2.0 devices and configurations.
+ *
+ * USB 2.0 shows up in upcoming www.pcmcia.org technology.
+ * First was PCMCIA, like ISA; then CardBus, which is PCI.
+ * Next comes "CardBay", using USB 2.0 signals.
+ *
+ * Contains additional contributions by:
+ *	Brad Hards
+ *	Rory Bolt
+ *	...
+ *
+ * HISTORY:
+ *
+ * 2002-03-05	Initial high-speed ISO support; reduce ITD memory; shift
+ *	more checking to generic hcd framework (db).  Make it work with
+ *	Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
+ * 2002-01-14	Minor cleanup; version synch.
+ * 2002-01-08	Fix roothub handoff of FS/LS to companion controllers.
+ * 2002-01-04	Control/Bulk queuing behaves.
+ *
+ * 2001-12-12	Initial patch version for Linux 2.5.1 kernel.
+ * 2001-June	Works with usb-storage and NEC EHCI on 2.4
+ */
+
+#define DRIVER_VERSION "$Revision: 0.27 $"
+#define DRIVER_AUTHOR "David Brownell"
+#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
+
+
+// #define EHCI_VERBOSE_DEBUG
+// #define have_split_iso
+
+/* magic numbers that can affect system performance */
+#define	EHCI_TUNE_CERR		3	/* 0-3 qtd retries; 0 == don't stop */
+#define	EHCI_TUNE_RL_HS		0	/* nak throttle; see 4.9 */
+#define	EHCI_TUNE_RL_TT		0
+#define	EHCI_TUNE_MULT_HS	1	/* 1-3 transactions/uframe; 4.10.3 */
+#define	EHCI_TUNE_MULT_TT	1
+
+/* Initial IRQ latency:  lower than default */
+static int log2_irq_thresh = 0;		// 0 to 6
+MODULE_PARM (log2_irq_thresh, "i");
+MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
+
+#define	INTR_MASK (STS_IAA | STS_FATAL | STS_ERR | STS_INT)
+
+/*-------------------------------------------------------------------------*/
+
+#include "ehci.h"
+#include "ehci-dbg.c"
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * hc states include: unknown, halted, ready, running
+ * transitional states are messy just now
+ * trying to avoid "running" unless urbs are active
+ * a "ready" hc can be finishing prefetched work
+ */
+
+/* halt a non-running controller */
+static void ehci_reset (struct ehci_hcd *ehci)
+{
+	u32	command = readl (&ehci->regs->command);
+
+	command |= CMD_RESET;
+	dbg_cmd (ehci, "reset", command);
+	writel (command, &ehci->regs->command);
+	while (readl (&ehci->regs->command) & CMD_RESET)
+		continue;
+	ehci->hcd.state = USB_STATE_HALT;
+}
+
+/* idle the controller (from running) */
+static void ehci_ready (struct ehci_hcd *ehci)
+{
+	u32	command;
+
+#ifdef DEBUG
+	if (!HCD_IS_RUNNING (ehci->hcd.state))
+		BUG ();
+#endif
+
+	while (!(readl (&ehci->regs->status) & (STS_ASS | STS_PSS)))
+		udelay (100);
+	command = readl (&ehci->regs->command);
+	command &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
+	writel (command, &ehci->regs->command);
+
+	// hardware can take 16 microframes to turn off ...
+	ehci->hcd.state = USB_STATE_READY;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#include "ehci-hub.c"
+#include "ehci-mem.c"
+#include "ehci-q.c"
+#include "ehci-sched.c"
+
+/*-------------------------------------------------------------------------*/
+
+static void ehci_tasklet (unsigned long param);
+
+/* called by khubd or root hub init threads */
+
+static int ehci_start (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	u32			temp;
+	struct usb_device	*udev;
+	int			retval;
+	u32			hcc_params;
+	u8                      tempbyte;
+
+	// FIXME:  given EHCI 0.96 or later, and a controller with
+	// the USBLEGSUP/USBLEGCTLSTS extended capability, make sure
+	// the BIOS doesn't still own this controller.
+
+	spin_lock_init (&ehci->lock);
+
+	ehci->caps = (struct ehci_caps *) hcd->regs;
+	ehci->regs = (struct ehci_regs *) (hcd->regs + ehci->caps->length);
+	dbg_hcs_params (ehci, "ehci_start");
+	dbg_hcc_params (ehci, "ehci_start");
+
+	/* cache this readonly data; minimize PCI reads */
+	ehci->hcs_params = readl (&ehci->caps->hcs_params);
+
+	/*
+	 * hw default: 1K periodic list heads, one per frame.
+	 * periodic_size can shrink by USBCMD update if hcc_params allows.
+	 */
+	ehci->periodic_size = DEFAULT_I_TDPS;
+	if ((retval = ehci_mem_init (ehci, SLAB_KERNEL)) < 0)
+		return retval;
+	hcc_params = readl (&ehci->caps->hcc_params);
+
+	/* controllers may cache some of the periodic schedule ... */
+	if (HCC_ISOC_CACHE (hcc_params)) 	// full frame cache
+		ehci->i_thresh = 8;
+	else					// N microframes cached
+		ehci->i_thresh = 2 + HCC_ISOC_THRES (hcc_params);
+
+	ehci->async = 0;
+	ehci->reclaim = 0;
+	ehci->next_uframe = -1;
+
+	/* controller state:  unknown --> reset */
+
+	/* EHCI spec section 4.1 */
+	// FIXME require STS_HALT before reset...
+	ehci_reset (ehci);
+	writel (INTR_MASK, &ehci->regs->intr_enable);
+	writel (ehci->periodic_dma, &ehci->regs->frame_list);
+
+	/*
+	 * hcc_params controls whether ehci->regs->segment must (!!!)
+	 * be used; it constrains QH/ITD/SITD and QTD locations.
+	 * pci_pool consistent memory always uses segment zero.
+	 */
+	if (HCC_64BIT_ADDR (hcc_params)) {
+		writel (0, &ehci->regs->segment);
+		/*
+		 * FIXME Enlarge pci_set_dma_mask() when possible.  The DMA
+		 * mapping API spec now says that'll affect only single shot
+		 * mappings, and the pci_pool data will stay safe in seg 0.
+		 * That's what we want:  no extra copies for USB transfers.
+		 */
+		info ("restricting 64bit DMA mappings to segment 0 ...");
+	}
+
+	/* clear interrupt enables, set irq latency */
+	temp = readl (&ehci->regs->command) & 0xff;
+	if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
+	    log2_irq_thresh = 0;
+	temp |= 1 << (16 + log2_irq_thresh);
+	// keeping default periodic framelist size
+	temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE),
+	// Philips, Intel, and maybe others need CMD_RUN before the
+	// root hub will detect new devices (why?); NEC doesn't
+	temp |= CMD_RUN;
+	writel (temp, &ehci->regs->command);
+	dbg_cmd (ehci, "init", temp);
+
+	/* set async sleep time = 10 us ... ? */
+
+	ehci->tasklet.func = ehci_tasklet;
+	ehci->tasklet.data = (unsigned long) ehci;
+
+	/* wire up the root hub */
+	hcd->bus->root_hub = udev = usb_alloc_dev (NULL, hcd->bus);
+	if (!udev) {
+done2:
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
+	 * are explicitly handed to companion controller(s), so no TT is
+	 * involved with the root hub.
+	 */
+	ehci->hcd.state = USB_STATE_READY;
+	writel (FLAG_CF, &ehci->regs->configured_flag);
+	readl (&ehci->regs->command);	/* unblock posted write */
+
+        /* PCI Serial Bus Release Number is at 0x60 offset */
+	pci_read_config_byte (hcd->pdev, 0x60, &tempbyte);
+	temp = readw (&ehci->caps->hci_version);
+	info ("USB %x.%x support enabled, EHCI rev %x.%2x",
+	      ((tempbyte & 0xf0)>>4),
+	      (tempbyte & 0x0f),
+	       temp >> 8,
+	       temp & 0xff);
+
+	/*
+	 * From here on, khubd concurrently accesses the root
+	 * hub; drivers will be talking to enumerated devices.
+	 *
+	 * Before this point the HC was idle/ready.  After, khubd
+	 * and device drivers may start it running.
+	 */
+	usb_connect (udev);
+	udev->speed = USB_SPEED_HIGH;
+	if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) {
+		if (hcd->state == USB_STATE_RUNNING)
+			ehci_ready (ehci);
+		while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
+			udelay (100);
+		ehci_reset (ehci);
+		// usb_disconnect (udev); 
+		hcd->bus->root_hub = 0;
+		usb_free_dev (udev); 
+		retval = -ENODEV;
+		goto done2;
+	}
+
+	return 0;
+}
+
+/* always called by thread; normally rmmod */
+
+static void ehci_stop (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+
+	dbg ("%s: stop", hcd->bus_name);
+
+	if (hcd->state == USB_STATE_RUNNING)
+		ehci_ready (ehci);
+	while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
+		udelay (100);
+	ehci_reset (ehci);
+
+	// root hub is shut down separately (first, when possible)
+	scan_async (ehci);
+	if (ehci->next_uframe != -1)
+		scan_periodic (ehci);
+	ehci_mem_cleanup (ehci);
+
+	dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status));
+}
+
+static int ehci_get_frame (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+static int ehci_suspend (struct usb_hcd *hcd, u32 state)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	int			ports;
+	int			i;
+
+	dbg ("%s: suspend to %d", hcd->bus_name, state);
+
+	ports = HCS_N_PORTS (ehci->hcs_params);
+
+	// FIXME:  This assumes what's probably a D3 level suspend...
+
+	// FIXME:  usb wakeup events on this bus should resume the machine.
+	// pci config register PORTWAKECAP controls which ports can do it;
+	// bios may have initted the register...
+
+	/* suspend each port, then stop the hc */
+	for (i = 0; i < ports; i++) {
+		int	temp = readl (&ehci->regs->port_status [i]);
+
+		if ((temp & PORT_PE) == 0
+				|| (temp & PORT_OWNER) != 0)
+			continue;
+dbg ("%s: suspend port %d", hcd->bus_name, i);
+		temp |= PORT_SUSPEND;
+		writel (temp, &ehci->regs->port_status [i]);
+	}
+
+	if (hcd->state == USB_STATE_RUNNING)
+		ehci_ready (ehci);
+	while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS))
+		udelay (100);
+	writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command);
+
+// save pci FLADJ value
+
+	/* who tells PCI to reduce power consumption? */
+
+	return 0;
+}
+
+static int ehci_resume (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	int			ports;
+	int			i;
+
+	dbg ("%s: resume", hcd->bus_name);
+
+	ports = HCS_N_PORTS (ehci->hcs_params);
+
+	// FIXME:  if controller didn't retain state,
+	// return and let generic code clean it up
+	// test configured_flag ?
+
+	/* resume HC and each port */
+// restore pci FLADJ value
+	// khubd and drivers will set HC running, if needed;
+	hcd->state = USB_STATE_READY;
+	// FIXME Philips/Intel/... etc don't really have a "READY"
+	// state ... turn on CMD_RUN too
+	for (i = 0; i < ports; i++) {
+		int	temp = readl (&ehci->regs->port_status [i]);
+
+		if ((temp & PORT_PE) == 0
+				|| (temp & PORT_SUSPEND) != 0)
+			continue;
+dbg ("%s: resume port %d", hcd->bus_name, i);
+		temp |= PORT_RESUME;
+		writel (temp, &ehci->regs->port_status [i]);
+		readl (&ehci->regs->command);	/* unblock posted writes */
+
+		wait_ms (20);
+		temp &= ~PORT_RESUME;
+		writel (temp, &ehci->regs->port_status [i]);
+	}
+	readl (&ehci->regs->command);	/* unblock posted writes */
+	return 0;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * tasklet scheduled by some interrupts and other events
+ * calls driver completion functions ... but not in_irq()
+ */
+static void ehci_tasklet (unsigned long param)
+{
+	struct ehci_hcd		*ehci = (struct ehci_hcd *) param;
+
+	if (ehci->reclaim_ready)
+		end_unlink_async (ehci);
+	scan_async (ehci);
+	if (ehci->next_uframe != -1)
+		scan_periodic (ehci);
+
+	// FIXME:  when nothing is connected to the root hub,
+	// turn off the RUN bit so the host can enter C3 "sleep" power
+	// saving mode; make root hub code scan memory less often.
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void ehci_irq (struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	u32			status = readl (&ehci->regs->status);
+	int			bh;
+
+	status &= INTR_MASK;
+	if (!status)			/* irq sharing? */
+		return;
+
+	/* clear (just) interrupts */
+	writel (status, &ehci->regs->status);
+	readl (&ehci->regs->command);	/* unblock posted write */
+	bh = 0;
+
+#ifdef	EHCI_VERBOSE_DEBUG
+	/* unrequested/ignored: Port Change Detect, Frame List Rollover */
+	dbg_status (ehci, "irq", status);
+#endif
+
+	/* INT, ERR, and IAA interrupt rates can be throttled */
+
+	/* normal [4.15.1.2] or error [4.15.1.1] completion */
+	if (likely ((status & (STS_INT|STS_ERR)) != 0))
+		bh = 1;
+
+	/* complete the unlinking of some qh [4.15.2.3] */
+	if (status & STS_IAA) {
+		ehci->reclaim_ready = 1;
+		bh = 1;
+	}
+
+	/* PCI errors [4.15.2.4] */
+	if (unlikely ((status & STS_FATAL) != 0)) {
+		err ("%s: fatal error, state %x", hcd->bus_name, hcd->state);
+		ehci_reset (ehci);
+		// generic layer kills/unlinks all urbs
+		// then tasklet cleans up the rest
+		bh = 1;
+	}
+
+	/* most work doesn't need to be in_irq() */
+	if (likely (bh == 1))
+		tasklet_schedule (&ehci->tasklet);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * non-error returns are a promise to giveback() the urb later
+ * we drop ownership so next owner (or urb unlink) can get it
+ *
+ * urb + dev is in hcd_dev.urb_list
+ * we're queueing TDs onto software and hardware lists
+ *
+ * hcd-specific init for hcpriv hasn't been done yet
+ *
+ * NOTE:  EHCI queues control and bulk requests transparently, like OHCI.
+ */
+static int ehci_urb_enqueue (
+	struct usb_hcd	*hcd,
+	struct urb	*urb,
+	int		mem_flags
+) {
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	struct list_head	qtd_list;
+
+	urb->transfer_flags &= ~EHCI_STATE_UNLINK;
+	INIT_LIST_HEAD (&qtd_list);
+	switch (usb_pipetype (urb->pipe)) {
+
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+			return -ENOMEM;
+		submit_async (ehci, urb, &qtd_list, mem_flags);
+		break;
+
+	case PIPE_INTERRUPT:
+		if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
+			return -ENOMEM;
+		return intr_submit (ehci, urb, &qtd_list, mem_flags);
+
+	case PIPE_ISOCHRONOUS:
+		if (urb->dev->speed == USB_SPEED_HIGH)
+			return itd_submit (ehci, urb, mem_flags);
+#ifdef have_split_iso
+		else
+			return sitd_submit (ehci, urb, mem_flags);
+#else
+		dbg ("no split iso support yet");
+		return -ENOSYS;
+#endif /* have_split_iso */
+
+	}
+	return 0;
+}
+
+/* remove from hardware lists
+ * completions normally happen asynchronously
+ */
+
+static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	struct ehci_qh		*qh = (struct ehci_qh *) urb->hcpriv;
+	unsigned long		flags;
+
+	dbg ("%s urb_dequeue %p qh state %d",
+		hcd->bus_name, urb, qh->qh_state);
+
+	switch (usb_pipetype (urb->pipe)) {
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+		spin_lock_irqsave (&ehci->lock, flags);
+		if (ehci->reclaim) {
+dbg ("dq: reclaim busy, %s", RUN_CONTEXT);
+			if (in_interrupt ()) {
+				spin_unlock_irqrestore (&ehci->lock, flags);
+				return -EAGAIN;
+			}
+			while (qh->qh_state == QH_STATE_LINKED
+					&& ehci->reclaim
+					&& ehci->hcd.state != USB_STATE_HALT
+					) {
+				spin_unlock_irqrestore (&ehci->lock, flags);
+// yeech ... this could spin for up to two frames!
+dbg ("wait for dequeue: state %d, reclaim %p, hcd state %d",
+    qh->qh_state, ehci->reclaim, ehci->hcd.state
+);
+				udelay (100);
+				spin_lock_irqsave (&ehci->lock, flags);
+			}
+		}
+		if (qh->qh_state == QH_STATE_LINKED)
+			start_unlink_async (ehci, qh);
+		spin_unlock_irqrestore (&ehci->lock, flags);
+		return 0;
+
+	case PIPE_INTERRUPT:
+		intr_deschedule (ehci, urb->start_frame, qh, urb->interval);
+		if (ehci->hcd.state == USB_STATE_HALT)
+			urb->status = -ESHUTDOWN;
+		qh_completions (ehci, &qh->qtd_list, 1);
+		return 0;
+
+	case PIPE_ISOCHRONOUS:
+		// itd or sitd ...
+
+		// wait till next completion, do it then.
+		// completion irqs can wait up to 128 msec,
+		urb->transfer_flags |= EHCI_STATE_UNLINK;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+// bulk qh holds the data toggle
+
+static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct hcd_dev		*dev = (struct hcd_dev *)udev->hcpriv;
+	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
+	int			i;
+	unsigned long		flags;
+
+	/* ASSERT:  nobody can be submitting urbs for this any more */
+
+	dbg ("%s: free_config devnum %d", hcd->bus_name, udev->devnum);
+
+	spin_lock_irqsave (&ehci->lock, flags);
+	for (i = 0; i < 32; i++) {
+		if (dev->ep [i]) {
+			struct ehci_qh		*qh;
+
+			// FIXME:  this might be an itd/sitd too ...
+			// or an interrupt urb (not on async list)
+			// can use "union ehci_shadow"
+
+			qh = (struct ehci_qh *) dev->ep [i];
+			vdbg ("free_config, ep 0x%02x qh %p", i, qh);
+			if (!list_empty (&qh->qtd_list)) {
+				dbg ("ep 0x%02x qh %p not empty!", i, qh);
+				BUG ();
+			}
+			dev->ep [i] = 0;
+
+			/* wait_ms() won't spin here -- we're a thread */
+			while (qh->qh_state == QH_STATE_LINKED
+					&& ehci->reclaim
+					&& ehci->hcd.state != USB_STATE_HALT
+					) {
+				spin_unlock_irqrestore (&ehci->lock, flags);
+				wait_ms (1);
+				spin_lock_irqsave (&ehci->lock, flags);
+			}
+			if (qh->qh_state == QH_STATE_LINKED) {
+				start_unlink_async (ehci, qh);
+				while (qh->qh_state != QH_STATE_IDLE) {
+					spin_unlock_irqrestore (&ehci->lock,
+						flags);
+					wait_ms (1);
+					spin_lock_irqsave (&ehci->lock, flags);
+				}
+			}
+			qh_unput (ehci, qh);
+		}
+	}
+
+	spin_unlock_irqrestore (&ehci->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const char	hcd_name [] = "ehci-hcd";
+
+static const struct hc_driver ehci_driver = {
+	description:		hcd_name,
+
+	/*
+	 * generic hardware linkage
+	 */
+	irq:			ehci_irq,
+	flags:			HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	start:			ehci_start,
+#ifdef	CONFIG_PM
+	suspend:		ehci_suspend,
+	resume:			ehci_resume,
+#endif
+	stop:			ehci_stop,
+
+	/*
+	 * memory lifecycle (except per-request)
+	 */
+	hcd_alloc:		ehci_hcd_alloc,
+	hcd_free:		ehci_hcd_free,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	urb_enqueue:		ehci_urb_enqueue,
+	urb_dequeue:		ehci_urb_dequeue,
+	free_config:		ehci_free_config,
+
+	/*
+	 * scheduling support
+	 */
+	get_frame_number:	ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	hub_status_data:	ehci_hub_status_data,
+	hub_control:		ehci_hub_control,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI spec says PCI is required. */
+
+/* PCI driver selection metadata; PCI hotplugging uses this */
+static const struct pci_device_id __devinitdata pci_ids [] = { {
+
+	/* handle any USB 2.0 EHCI controller */
+
+	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x20),
+	class_mask: 	~0,
+	driver_data:	(unsigned long) &ehci_driver,
+
+	/* no matter who makes it */
+	vendor:		PCI_ANY_ID,
+	device:		PCI_ANY_ID,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+}, { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver ehci_pci_driver = {
+	name:		(char *) hcd_name,
+	id_table:	pci_ids,
+
+	probe:		usb_hcd_pci_probe,
+	remove:		usb_hcd_pci_remove,
+
+#ifdef	CONFIG_PM
+	suspend:	usb_hcd_pci_suspend,
+	resume:		usb_hcd_pci_resume,
+#endif
+};
+
+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+
+EXPORT_NO_SYMBOLS;
+MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_LICENSE ("GPL");
+
+static int __init init (void) 
+{
+	dbg (DRIVER_INFO);
+	dbg ("block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd",
+		sizeof (struct ehci_qh), sizeof (struct ehci_qtd),
+		sizeof (struct ehci_itd), sizeof (struct ehci_sitd));
+
+	return pci_module_init (&ehci_pci_driver);
+}
+module_init (init);
+
+static void __exit cleanup (void) 
+{	
+	pci_unregister_driver (&ehci_pci_driver);
+}
+module_exit (cleanup);
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci-hub.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2001-2002 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Root Hub ... the nonsharable stuff
+ *
+ * Registers don't need cpu_to_le32, that happens transparently
+ */
+
+/*-------------------------------------------------------------------------*/
+
+static int check_reset_complete (
+	struct ehci_hcd	*ehci,
+	int		index,
+	int		port_status
+) {
+	if (!(port_status & PORT_CONNECT)) {
+		ehci->reset_done [index] = 0;
+		return port_status;
+	}
+
+	/* if reset finished and it's still not enabled -- handoff */
+	if (!(port_status & PORT_PE)) {
+		dbg ("%s port %d full speed, give to companion, 0x%x",
+			ehci->hcd.bus_name, index + 1, port_status);
+
+		// what happens if HCS_N_CC(params) == 0 ?
+		port_status |= PORT_OWNER;
+		writel (port_status, &ehci->regs->port_status [index]);
+
+	} else
+		dbg ("%s port %d high speed", ehci->hcd.bus_name, index + 1);
+
+	return port_status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+
+/* build "status change" packet (one or two bytes) from HC registers */
+
+static int
+ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
+	u32		temp, status = 0;
+	int		ports, i, retval = 1;
+	unsigned long	flags;
+
+	/* init status to no-changes */
+	buf [0] = 0;
+	ports = HCS_N_PORTS (ehci->hcs_params);
+	if (ports > 7) {
+		buf [1] = 0;
+		retval++;
+	}
+	
+	/* no hub change reports (bit 0) for now (power, ...) */
+
+	/* port N changes (bit N)? */
+	spin_lock_irqsave (&ehci->lock, flags);
+	for (i = 0; i < ports; i++) {
+		temp = readl (&ehci->regs->port_status [i]);
+		if (temp & PORT_OWNER) {
+			/* don't report this in GetPortStatus */
+			if (temp & PORT_CSC) {
+				temp &= ~PORT_CSC;
+				writel (temp, &ehci->regs->port_status [i]);
+			}
+			continue;
+		}
+		if (!(temp & PORT_CONNECT))
+			ehci->reset_done [i] = 0;
+		if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0) {
+			set_bit (i, buf);
+			status = STS_PCD;
+		}
+	}
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	return status ? retval : 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+ehci_hub_descriptor (
+	struct ehci_hcd			*ehci,
+	struct usb_hub_descriptor	*desc
+) {
+	int		ports = HCS_N_PORTS (ehci->hcs_params);
+	u16		temp;
+
+	desc->bDescriptorType = 0x29;
+	desc->bPwrOn2PwrGood = 0;	/* FIXME: f(system power) */
+	desc->bHubContrCurrent = 0;
+
+	desc->bNbrPorts = ports;
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset (&desc->bitmap [0], 0, temp);
+	memset (&desc->bitmap [temp], 0xff, temp);
+
+	temp = 0x0008;			/* per-port overcurrent reporting */
+	if (HCS_PPC (ehci->hcs_params))
+		temp |= 0x0001;		/* per-port power control */
+	if (HCS_INDICATOR (ehci->hcs_params))
+		temp |= 0x0080;		/* per-port indicators (LEDs) */
+	desc->wHubCharacteristics = cpu_to_le16 (temp);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int ehci_hub_control (
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength
+) {
+	struct ehci_hcd	*ehci = hcd_to_ehci (hcd);
+	int		ports = HCS_N_PORTS (ehci->hcs_params);
+	u32		temp;
+	unsigned long	flags;
+	int		retval = 0;
+
+	/*
+	 * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
+	 * HCS_INDICATOR may say we can change LEDs to off/amber/green.
+	 * (track current state ourselves) ... blink for diagnostics,
+	 * power, "this is the one", etc.  EHCI spec supports this.
+	 */
+
+	spin_lock_irqsave (&ehci->lock, flags);
+	switch (typeReq) {
+	case ClearHubFeature:
+		switch (wValue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* no hub-wide feature/status flags */
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case ClearPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = readl (&ehci->regs->port_status [wIndex]);
+		if (temp & PORT_OWNER)
+			break;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			writel (temp & ~PORT_PE,
+				&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+			writel (temp | PORT_PEC,
+				&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+		case USB_PORT_FEAT_C_SUSPEND:
+			/* ? */
+			break;
+		case USB_PORT_FEAT_POWER:
+			if (HCS_PPC (ehci->hcs_params))
+				writel (temp & ~PORT_POWER,
+					&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_C_CONNECTION:
+			writel (temp | PORT_CSC,
+				&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			writel (temp | PORT_OCC,
+				&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_C_RESET:
+			/* GetPortStatus clears reset */
+			break;
+		default:
+			goto error;
+		}
+		readl (&ehci->regs->command);	/* unblock posted write */
+		break;
+	case GetHubDescriptor:
+		ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *)
+			buf);
+		break;
+	case GetHubStatus:
+		/* no hub-wide feature/status flags */
+		memset (buf, 0, 4);
+		//cpu_to_le32s ((u32 *) buf);
+		break;
+	case GetPortStatus:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		memset (buf, 0, 4);
+		temp = readl (&ehci->regs->port_status [wIndex]);
+
+		// wPortChange bits
+		if (temp & PORT_CSC)
+			set_bit (USB_PORT_FEAT_C_CONNECTION, buf);
+		if (temp & PORT_PEC)
+			set_bit (USB_PORT_FEAT_C_ENABLE, buf);
+		// USB_PORT_FEAT_C_SUSPEND
+		if (temp & PORT_OCC)
+			set_bit (USB_PORT_FEAT_C_OVER_CURRENT, buf);
+
+		/* whoever resets must GetPortStatus to complete it!! */
+		if ((temp & PORT_RESET)
+				&& jiffies > ehci->reset_done [wIndex]) {
+			set_bit (USB_PORT_FEAT_C_RESET, buf);
+
+			/* force reset to complete */
+			writel (temp & ~PORT_RESET,
+					&ehci->regs->port_status [wIndex]);
+			do {
+				temp = readl (
+					&ehci->regs->port_status [wIndex]);
+				udelay (10);
+			} while (temp & PORT_RESET);
+
+			/* see what we found out */
+			temp = check_reset_complete (ehci, wIndex, temp);
+		}
+
+		// don't show wPortStatus if it's owned by a companion hc
+		if (!(temp & PORT_OWNER)) {
+			if (temp & PORT_CONNECT) {
+				set_bit (USB_PORT_FEAT_CONNECTION, buf);
+				set_bit (USB_PORT_FEAT_HIGHSPEED, buf);
+			}
+			if (temp & PORT_PE)
+				set_bit (USB_PORT_FEAT_ENABLE, buf);
+			if (temp & PORT_SUSPEND)
+				set_bit (USB_PORT_FEAT_SUSPEND, buf);
+			if (temp & PORT_OC)
+				set_bit (USB_PORT_FEAT_OVER_CURRENT, buf);
+			if (temp & PORT_RESET)
+				set_bit (USB_PORT_FEAT_RESET, buf);
+			if (temp & PORT_POWER)
+				set_bit (USB_PORT_FEAT_POWER, buf);
+		}
+
+#ifndef	EHCI_VERBOSE_DEBUG
+	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
+#endif
+		dbg_port (hcd, "GetStatus", wIndex + 1, temp);
+		cpu_to_le32s ((u32 *) buf);
+		break;
+	case SetHubFeature:
+		switch (wValue) {
+		case C_HUB_LOCAL_POWER:
+		case C_HUB_OVER_CURRENT:
+			/* no hub-wide feature/status flags */
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case SetPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = readl (&ehci->regs->port_status [wIndex]);
+		if (temp & PORT_OWNER)
+			break;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			writel (temp | PORT_SUSPEND,
+				&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_POWER:
+			if (HCS_PPC (ehci->hcs_params))
+				writel (temp | PORT_POWER,
+					&ehci->regs->port_status [wIndex]);
+			break;
+		case USB_PORT_FEAT_RESET:
+			/* line status bits may report this as low speed */
+			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
+					&& PORT_USB11 (temp)) {
+				dbg ("%s port %d low speed, give to companion",
+					hcd->bus_name, wIndex + 1);
+				temp |= PORT_OWNER;
+			} else {
+				vdbg ("%s port %d reset",
+					hcd->bus_name, wIndex + 1);
+				temp |= PORT_RESET;
+				temp &= ~PORT_PE;
+
+				/*
+				 * caller must wait, then call GetPortStatus
+				 * usb 2.0 spec says 50 ms resets on root
+				 */
+				ehci->reset_done [wIndex] = jiffies
+				    	+ ((50 /* msec */ * HZ) / 1000);
+			}
+			writel (temp, &ehci->regs->port_status [wIndex]);
+			break;
+		default:
+			goto error;
+		}
+		readl (&ehci->regs->command);	/* unblock posted writes */
+		break;
+
+	default:
+error:
+		/* "stall" on error */
+		retval = -EPIPE;
+	}
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	return retval;
+}
diff -Nru a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci-mem.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2001 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * There's basically three types of memory:
+ *	- data used only by the HCD ... kmalloc is fine
+ *	- async and periodic schedules, shared by HC and HCD ... these
+ *	  need to use pci_pool or pci_alloc_consistent
+ *	- driver buffers, read/written by HC ... single shot DMA mapped 
+ *
+ * There's also PCI "register" data, which is memory mapped.
+ * No memory seen by this driver is pagable.
+ */
+
+/*-------------------------------------------------------------------------*/
+/* 
+ * Allocator / cleanup for the per device structure
+ * Called by hcd init / removal code
+ */
+static struct usb_hcd *ehci_hcd_alloc (void)
+{
+	struct ehci_hcd *ehci;
+
+	ehci = (struct ehci_hcd *)
+		kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL);
+	if (ehci != 0) {
+		memset (ehci, 0, sizeof (struct ehci_hcd));
+		return &ehci->hcd;
+	}
+	return 0;
+}
+
+static void ehci_hcd_free (struct usb_hcd *hcd)
+{
+	kfree (hcd_to_ehci (hcd));
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Allocate the key transfer structures from the previously allocated pool */
+
+static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
+{
+	struct ehci_qtd		*qtd;
+	dma_addr_t		dma;
+
+	qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma);
+	if (qtd != 0) {
+		memset (qtd, 0, sizeof *qtd);
+		qtd->qtd_dma = dma;
+		qtd->hw_next = EHCI_LIST_END;
+		qtd->hw_alt_next = EHCI_LIST_END;
+		INIT_LIST_HEAD (&qtd->qtd_list);
+	}
+	return qtd;
+}
+
+static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
+{
+	pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma);
+}
+
+
+static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
+{
+	struct ehci_qh		*qh;
+	dma_addr_t		dma;
+
+	qh = (struct ehci_qh *)
+		pci_pool_alloc (ehci->qh_pool, flags, &dma);
+	if (qh) {
+		memset (qh, 0, sizeof *qh);
+		atomic_set (&qh->refcount, 1);
+		qh->qh_dma = dma;
+		// INIT_LIST_HEAD (&qh->qh_list);
+		INIT_LIST_HEAD (&qh->qtd_list);
+	}
+	return qh;
+}
+
+/* to share a qh (cpu threads, or hc) */
+static inline struct ehci_qh *qh_put (/* ehci, */ struct ehci_qh *qh)
+{
+	// dbg ("put %p (%d++)", qh, qh->refcount.counter);
+	atomic_inc (&qh->refcount);
+	return qh;
+}
+
+static void qh_unput (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+	// dbg ("unput %p (--%d)", qh, qh->refcount.counter);
+	if (!atomic_dec_and_test (&qh->refcount))
+		return;
+	/* clean qtds first, and know this is not linked */
+	if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
+		dbg ("unused qh not empty!");
+		BUG ();
+	}
+	pci_pool_free (ehci->qh_pool, qh, qh->qh_dma);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* The queue heads and transfer descriptors are managed from pools tied 
+ * to each of the "per device" structures.
+ * This is the initialisation and cleanup code.
+ */
+
+static void ehci_mem_cleanup (struct ehci_hcd *ehci)
+{
+	/* PCI consistent memory and pools */
+	if (ehci->qtd_pool)
+		pci_pool_destroy (ehci->qtd_pool);
+	ehci->qtd_pool = 0;
+
+	if (ehci->qh_pool) {
+		pci_pool_destroy (ehci->qh_pool);
+		ehci->qh_pool = 0;
+	}
+
+	if (ehci->itd_pool)
+		pci_pool_destroy (ehci->itd_pool);
+	ehci->itd_pool = 0;
+
+	if (ehci->sitd_pool)
+		pci_pool_destroy (ehci->sitd_pool);
+	ehci->sitd_pool = 0;
+
+	if (ehci->periodic)
+		pci_free_consistent (ehci->hcd.pdev,
+			ehci->periodic_size * sizeof (u32),
+			ehci->periodic, ehci->periodic_dma);
+	ehci->periodic = 0;
+
+	/* shadow periodic table */
+	if (ehci->pshadow)
+		kfree (ehci->pshadow);
+	ehci->pshadow = 0;
+}
+
+/* remember to add cleanup code (above) if you add anything here */
+static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
+{
+	int i;
+
+	/* QTDs for control/bulk/intr transfers */
+	ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev,
+			sizeof (struct ehci_qtd),
+			32 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */,
+			flags);
+	if (!ehci->qtd_pool) {
+		dbg ("no qtd pool");
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+
+	/* QH for control/bulk/intr transfers */
+	ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev,
+			sizeof (struct ehci_qh),
+			32 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */,
+			flags);
+	if (!ehci->qh_pool) {
+		dbg ("no qh pool");
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+
+	/* ITD for high speed ISO transfers */
+	ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev,
+			sizeof (struct ehci_itd),
+			32 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */,
+			flags);
+	if (!ehci->itd_pool) {
+		dbg ("no itd pool");
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+
+	/* SITD for full/low speed split ISO transfers */
+	ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev,
+			sizeof (struct ehci_sitd),
+			32 /* byte alignment (for hw parts) */,
+			4096 /* can't cross 4K */,
+			flags);
+	if (!ehci->sitd_pool) {
+		dbg ("no sitd pool");
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+
+	/* Hardware periodic table */
+	ehci->periodic = (u32 *)
+		pci_alloc_consistent (ehci->hcd.pdev,
+			ehci->periodic_size * sizeof (u32),
+			&ehci->periodic_dma);
+	if (ehci->periodic == 0) {
+		dbg ("no hw periodic table");
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+	for (i = 0; i < ehci->periodic_size; i++)
+		ehci->periodic [i] = EHCI_LIST_END;
+
+	/* software shadow of hardware table */
+	ehci->pshadow = kmalloc (ehci->periodic_size * sizeof (void *), flags);
+	if (ehci->pshadow == 0) {
+		dbg ("no shadow periodic table");
+		ehci_mem_cleanup (ehci);
+		return -ENOMEM;
+	}
+	memset (ehci->pshadow, 0, ehci->periodic_size * sizeof (void *));
+
+	return 0;
+}
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci-q.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,967 @@
+/*
+ * Copyright (c) 2001-2002 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI hardware queue manipulation
+ *
+ * Control, bulk, and interrupt traffic all use "qh" lists.  They list "qtd"
+ * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
+ * buffers needed for the larger number).  We use one QH per endpoint, queue
+ * multiple (bulk or control) urbs per endpoint.  URBs may need several qtds.
+ * A scheduled interrupt qh always has one qtd, one urb.
+ *
+ * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
+ * interrupts) needs careful scheduling.  Performance improvements can be
+ * an ongoing challenge.
+ * 
+ * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
+ * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
+ * (b) special fields in qh entries or (c) split iso entries.  TTs will
+ * buffer low/full speed data so the host collects it at high speed.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* fill a qtd, returning how much of the buffer we were able to queue up */
+
+static int
+qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token)
+{
+	int	i, count;
+
+	/* one buffer entry per 4K ... first might be short or unaligned */
+	qtd->hw_buf [0] = cpu_to_le32 (buf);
+	count = 0x1000 - (buf & 0x0fff);	/* rest of that page */
+	if (likely (len < count))		/* ... iff needed */
+		count = len;
+	else {
+		buf +=  0x1000;
+		buf &= ~0x0fff;
+
+		/* per-qtd limit: from 16K to 20K (best alignment) */
+		for (i = 1; count < len && i < 5; i++) {
+			u64	addr = buf;
+			qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
+			qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
+			buf += 0x1000;
+			if ((count + 0x1000) < len)
+				count += 0x1000;
+			else
+				count = len;
+		}
+	}
+	qtd->hw_token = cpu_to_le32 ((count << 16) | token);
+	qtd->length = count;
+
+#if 0
+	vdbg ("  qtd_fill %p, token %8x bytes %d dma %x",
+		qtd, le32_to_cpu (qtd->hw_token), count, qtd->hw_buf [0]);
+#endif
+
+	return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* update halted (but potentially linked) qh */
+
+static inline void qh_update (struct ehci_qh *qh, struct ehci_qtd *qtd)
+{
+	qh->hw_current = 0;
+	qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
+	qh->hw_alt_next = EHCI_LIST_END;
+
+	/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
+	qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
+{
+	/* count IN/OUT bytes, not SETUP (even short packets) */
+	if (likely (QTD_PID (token) != 2))
+		urb->actual_length += length - QTD_LENGTH (token);
+
+	/* don't modify error codes */
+	if (unlikely (urb->status == -EINPROGRESS && (token & QTD_STS_HALT))) {
+		if (token & QTD_STS_BABBLE) {
+			urb->status = -EOVERFLOW;
+		} else if (!QTD_CERR (token)) {
+			if (token & QTD_STS_DBE)
+				urb->status = (QTD_PID (token) == 1) /* IN ? */
+					? -ENOSR  /* hc couldn't read data */
+					: -ECOMM; /* hc couldn't write data */
+			else if (token & QTD_STS_MMF)	/* missed tt uframe */
+				urb->status = -EPROTO;
+			else if (token & QTD_STS_XACT) {
+				if (QTD_LENGTH (token))
+					urb->status = -EPIPE;
+				else {
+					dbg ("3strikes");
+					urb->status = -EPROTO;
+				}
+			} else	/* presumably a stall */
+				urb->status = -EPIPE;
+
+		/* CERR nonzero + data left + halt --> stall */
+		} else if (QTD_LENGTH (token))
+			urb->status = -EPIPE;
+		else	/* unknown */
+			urb->status = -EPROTO;
+		dbg ("ep %d-%s qtd token %08x --> status %d",
+			/* devpath */
+			usb_pipeendpoint (urb->pipe),
+			usb_pipein (urb->pipe) ? "in" : "out",
+			token, urb->status);
+
+		/* stall indicates some recovery action is needed */
+		if (urb->status == -EPIPE) {
+			int	pipe = urb->pipe;
+
+			if (!usb_pipecontrol (pipe))
+				usb_endpoint_halt (urb->dev,
+					usb_pipeendpoint (pipe),
+					usb_pipeout (pipe));
+			if (urb->dev->tt && !usb_pipeint (pipe)) {
+err ("must CLEAR_TT_BUFFER, hub port %d%s addr %d ep %d",
+    urb->dev->ttport, /* devpath */
+    urb->dev->tt->multi ? "" : " (all-ports TT)",
+    urb->dev->devnum, usb_pipeendpoint (urb->pipe));
+				// FIXME something (khubd?) should make the hub
+				// CLEAR_TT_BUFFER ASAP, it's blocking other
+				// fs/ls requests... hub_tt_clear_buffer() ?
+			}
+		}
+	}
+}
+
+static void ehci_urb_complete (
+	struct ehci_hcd		*ehci,
+	dma_addr_t		addr,
+	struct urb		*urb
+) {
+	if (urb->transfer_buffer_length && usb_pipein (urb->pipe))
+		pci_dma_sync_single (ehci->hcd.pdev, addr,
+			urb->transfer_buffer_length,
+			PCI_DMA_FROMDEVICE);
+
+	/* cleanse status if we saw no error */
+	if (likely (urb->status == -EINPROGRESS)) {
+		if (urb->actual_length != urb->transfer_buffer_length
+				&& (urb->transfer_flags & USB_DISABLE_SPD))
+			urb->status = -EREMOTEIO;
+		else
+			urb->status = 0;
+	}
+
+	/* only report unlinks once */
+	if (likely (urb->status != -ENOENT && urb->status != -ENOTCONN))
+		urb->complete (urb);
+}
+
+/* urb->lock ignored from here on (hcd is done with urb) */
+
+static void ehci_urb_done (
+	struct ehci_hcd		*ehci,
+	dma_addr_t		addr,
+	struct urb		*urb
+) {
+	if (urb->transfer_buffer_length)
+		pci_unmap_single (ehci->hcd.pdev,
+			addr,
+			urb->transfer_buffer_length,
+			usb_pipein (urb->pipe)
+			    ? PCI_DMA_FROMDEVICE
+			    : PCI_DMA_TODEVICE);
+	if (likely (urb->hcpriv != 0)) {
+		qh_unput (ehci, (struct ehci_qh *) urb->hcpriv);
+		urb->hcpriv = 0;
+	}
+
+	if (likely (urb->status == -EINPROGRESS)) {
+		if (urb->actual_length != urb->transfer_buffer_length
+				&& (urb->transfer_flags & USB_DISABLE_SPD))
+			urb->status = -EREMOTEIO;
+		else
+			urb->status = 0;
+	}
+
+	/* hand off urb ownership */
+	usb_hcd_giveback_urb (&ehci->hcd, urb);
+}
+
+
+/*
+ * Process completed qtds for a qh, issuing completions if needed.
+ * When freeing:  frees qtds, unmaps buf, returns URB to driver.
+ * When not freeing (queued periodic qh):  retain qtds, mapping, and urb.
+ * Races up to qh->hw_current; returns number of urb completions.
+ */
+static int
+qh_completions (
+	struct ehci_hcd		*ehci,
+	struct list_head	*qtd_list,
+	int			freeing
+) {
+	struct ehci_qtd		*qtd, *last;
+	struct list_head	*next;
+	struct ehci_qh		*qh = 0;
+	int			unlink = 0, halted = 0;
+	unsigned long		flags;
+	int			retval = 0;
+
+	spin_lock_irqsave (&ehci->lock, flags);
+	if (unlikely (list_empty (qtd_list))) {
+		spin_unlock_irqrestore (&ehci->lock, flags);
+		return retval;
+	}
+
+	/* scan QTDs till end of list, or we reach an active one */
+	for (qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list),
+			    	last = 0, next = 0;
+			next != qtd_list;
+			last = qtd, qtd = list_entry (next,
+						struct ehci_qtd, qtd_list)) {
+		struct urb	*urb = qtd->urb;
+		u32		token = 0;
+
+		/* qh is non-null iff these qtds were queued to the HC */
+		qh = (struct ehci_qh *) urb->hcpriv;
+
+		/* clean up any state from previous QTD ...*/
+		if (last) {
+			if (likely (last->urb != urb)) {
+				/* complete() can reenter this HCD */
+				spin_unlock_irqrestore (&ehci->lock, flags);
+				if (likely (freeing != 0))
+					ehci_urb_done (ehci, last->buf_dma,
+						last->urb);
+				else
+					ehci_urb_complete (ehci, last->buf_dma,
+						last->urb);
+				spin_lock_irqsave (&ehci->lock, flags);
+				retval++;
+			}
+
+			/* qh overlays can have HC's old cached copies of
+			 * next qtd ptrs, if an URB was queued afterwards.
+			 */
+			if (qh && cpu_to_le32 (last->qtd_dma) == qh->hw_current
+					&& last->hw_next != qh->hw_qtd_next) {
+				qh->hw_alt_next = last->hw_alt_next;
+				qh->hw_qtd_next = last->hw_next;
+			}
+
+			if (likely (freeing != 0))
+				ehci_qtd_free (ehci, last);
+			last = 0;
+		}
+		next = qtd->qtd_list.next;
+
+		/* if these qtds were queued to the HC, some may be active.
+		 * else we're cleaning up after a failed URB submission.
+		 */
+		if (likely (qh != 0)) {
+			int		qh_halted;
+
+			qh_halted = __constant_cpu_to_le32 (QTD_STS_HALT)
+					& qh->hw_token;
+			token = le32_to_cpu (qtd->hw_token);
+			halted = halted
+				|| qh_halted
+				|| (ehci->hcd.state == USB_STATE_HALT)
+				|| (qh->qh_state == QH_STATE_IDLE);
+
+			/* QH halts only because of fault or unlink; in both
+			 * cases, queued URBs get unlinked.  But for unlink,
+			 * URBs at the head of the queue can stay linked.
+			 */
+			if (unlikely (halted != 0)) {
+
+				/* unlink everything because of HC shutdown? */
+				if (ehci->hcd.state == USB_STATE_HALT) {
+					freeing = unlink = 1;
+					urb->status = -ESHUTDOWN;
+
+				/* explicit unlink, starting here? */
+				} else if (qh->qh_state == QH_STATE_IDLE
+					&& (urb->status == -ECONNRESET
+						|| urb->status == -ENOENT)) {
+					freeing = unlink = 1;
+
+				/* unlink everything because of error? */
+				} else if (qh_halted
+						&& !(token & QTD_STS_HALT)) {
+					freeing = unlink = 1;
+					if (urb->status == -EINPROGRESS)
+						urb->status = -ECONNRESET;
+
+				/* unlink the rest? */
+				} else if (unlink) {
+					urb->status = -ECONNRESET;
+
+				/* QH halted to unlink urbs after this?  */
+				} else if ((token & QTD_STS_ACTIVE) != 0) {
+					qtd = 0;
+					continue;
+				}
+
+			/* Else QH is active, so we must not modify QTDs
+			 * that HC may be working on.  Break from loop.
+			 */
+			} else if (unlikely ((token & QTD_STS_ACTIVE) != 0)) {
+				next = qtd_list;
+				qtd = 0;
+				continue;
+			}
+
+			spin_lock (&urb->lock);
+			qtd_copy_status (urb, qtd->length, token);
+			spin_unlock (&urb->lock);
+		}
+
+		/*
+		 * NOTE:  this won't work right with interrupt urbs that
+		 * need multiple qtds ... only the first scan of qh->qtd_list
+		 * starts at the right qtd, yet multiple scans could happen
+		 * for transfers that are scheduled across multiple uframes. 
+		 * (Such schedules are not currently allowed!)
+		 */
+		if (likely (freeing != 0))
+			list_del (&qtd->qtd_list);
+		else {
+			/* restore everything the HC could change
+			 * from an interrupt QTD
+			 */
+			qtd->hw_token = (qtd->hw_token
+					& ~__constant_cpu_to_le32 (0x8300))
+				| cpu_to_le32 (qtd->length << 16)
+				| __constant_cpu_to_le32 (QTD_IOC
+					| (EHCI_TUNE_CERR << 10)
+					| QTD_STS_ACTIVE);
+			qtd->hw_buf [0] &= ~__constant_cpu_to_le32 (0x0fff);
+
+			/* this offset, and the length above,
+			 * are likely wrong on QTDs #2..N
+			 */
+			qtd->hw_buf [0] |= cpu_to_le32 (0x0fff & qtd->buf_dma);
+		}
+
+#if 0
+		if (urb->status == -EINPROGRESS)
+			vdbg ("  qtd %p ok, urb %p, token %8x, len %d",
+				qtd, urb, token, urb->actual_length);
+		else
+			vdbg ("urb %p status %d, qtd %p, token %8x, len %d",
+				urb, urb->status, qtd, token,
+				urb->actual_length);
+#endif
+
+		/* SETUP for control urb? */
+		if (unlikely (QTD_PID (token) == 2))
+			pci_unmap_single (ehci->hcd.pdev,
+				qtd->buf_dma, sizeof (struct usb_ctrlrequest),
+				PCI_DMA_TODEVICE);
+	}
+
+	/* patch up list head? */
+	if (unlikely (halted && qh && !list_empty (qtd_list))) {
+		qh_update (qh, list_entry (qtd_list->next,
+				struct ehci_qtd, qtd_list));
+	}
+	spin_unlock_irqrestore (&ehci->lock, flags);
+
+	/* last urb's completion might still need calling */
+	if (likely (last != 0)) {
+		if (likely (freeing != 0)) {
+			ehci_urb_done (ehci, last->buf_dma, last->urb);
+			ehci_qtd_free (ehci, last);
+		} else
+			ehci_urb_complete (ehci, last->buf_dma, last->urb);
+		retval++;
+	}
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * create a list of filled qtds for this URB; won't link into qh.
+ */
+static struct list_head *
+qh_urb_transaction (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	struct list_head	*head,
+	int			flags
+) {
+	struct ehci_qtd		*qtd, *qtd_prev;
+	dma_addr_t		buf, map_buf;
+	int			len, maxpacket;
+	u32			token;
+
+	/*
+	 * URBs map to sequences of QTDs:  one logical transaction
+	 */
+	qtd = ehci_qtd_alloc (ehci, flags);
+	if (unlikely (!qtd))
+		return 0;
+	qtd_prev = 0;
+	list_add_tail (&qtd->qtd_list, head);
+	qtd->urb = urb;
+
+	token = QTD_STS_ACTIVE;
+	token |= (EHCI_TUNE_CERR << 10);
+	/* for split transactions, SplitXState initialized to zero */
+
+	if (usb_pipecontrol (urb->pipe)) {
+		/* control request data is passed in the "setup" pid */
+		qtd->buf_dma = pci_map_single (
+					ehci->hcd.pdev,
+					urb->setup_packet,
+					sizeof (struct usb_ctrlrequest),
+					PCI_DMA_TODEVICE);
+		if (unlikely (!qtd->buf_dma))
+			goto cleanup;
+
+		/* SETUP pid */
+		qtd_fill (qtd, qtd->buf_dma, sizeof (struct usb_ctrlrequest),
+			token | (2 /* "setup" */ << 8));
+
+		/* ... and always at least one more pid */
+		token ^= QTD_TOGGLE;
+		qtd_prev = qtd;
+		qtd = ehci_qtd_alloc (ehci, flags);
+		if (unlikely (!qtd))
+			goto cleanup;
+		qtd->urb = urb;
+		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+		list_add_tail (&qtd->qtd_list, head);
+	} 
+
+	/*
+	 * data transfer stage:  buffer setup
+	 */
+	len = urb->transfer_buffer_length;
+	if (likely (len > 0)) {
+		buf = map_buf = pci_map_single (ehci->hcd.pdev,
+			urb->transfer_buffer, len,
+			usb_pipein (urb->pipe)
+			    ? PCI_DMA_FROMDEVICE
+			    : PCI_DMA_TODEVICE);
+		if (unlikely (!buf))
+			goto cleanup;
+	} else
+		buf = map_buf = 0;
+
+	if (!buf || usb_pipein (urb->pipe))
+		token |= (1 /* "in" */ << 8);
+	/* else it's already initted to "out" pid (0 << 8) */
+
+	maxpacket = usb_maxpacket (urb->dev, urb->pipe,
+			usb_pipeout (urb->pipe));
+
+	/*
+	 * buffer gets wrapped in one or more qtds;
+	 * last one may be "short" (including zero len)
+	 * and may serve as a control status ack
+	 */
+	for (;;) {
+		int this_qtd_len;
+
+		qtd->urb = urb;
+		qtd->buf_dma = map_buf;
+		this_qtd_len = qtd_fill (qtd, buf, len, token);
+		len -= this_qtd_len;
+		buf += this_qtd_len;
+
+		/* qh makes control packets use qtd toggle; maybe switch it */
+		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
+			token ^= QTD_TOGGLE;
+
+		if (likely (len <= 0))
+			break;
+
+		qtd_prev = qtd;
+		qtd = ehci_qtd_alloc (ehci, flags);
+		if (unlikely (!qtd))
+			goto cleanup;
+		qtd->urb = urb;
+		qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+		list_add_tail (&qtd->qtd_list, head);
+	}
+
+	/*
+	 * control requests may need a terminating data "status" ack;
+	 * bulk ones may need a terminating short packet (zero length).
+	 */
+	if (likely (buf != 0)) {
+		int	one_more = 0;
+
+		if (usb_pipecontrol (urb->pipe)) {
+			one_more = 1;
+			token ^= 0x0100;	/* "in" <--> "out"  */
+			token |= QTD_TOGGLE;	/* force DATA1 */
+		} else if (usb_pipebulk (urb->pipe)
+				&& (urb->transfer_flags & USB_ZERO_PACKET)
+				&& !(urb->transfer_buffer_length % maxpacket)) {
+			one_more = 1;
+		}
+		if (one_more) {
+			qtd_prev = qtd;
+			qtd = ehci_qtd_alloc (ehci, flags);
+			if (unlikely (!qtd))
+				goto cleanup;
+			qtd->urb = urb;
+			qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+			list_add_tail (&qtd->qtd_list, head);
+
+			/* never any data in such packets */
+			qtd_fill (qtd, 0, 0, token);
+		}
+	}
+
+	/* by default, enable interrupt on urb completion */
+	if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
+		qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
+	return head;
+
+cleanup:
+	urb->status = -ENOMEM;
+	qh_completions (ehci, head, 1);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Hardware maintains data toggle (like OHCI) ... here we (re)initialize
+ * the hardware data toggle in the QH, and set the pseudo-toggle in udev
+ * so we can see if usb_clear_halt() was called.  NOP for control, since
+ * we set up qh->hw_info1 to always use the QTD toggle bits. 
+ */
+static inline void
+clear_toggle (struct usb_device *udev, int ep, int is_out, struct ehci_qh *qh)
+{
+	vdbg ("clear toggle, dev %d ep 0x%x-%s",
+		udev->devnum, ep, is_out ? "out" : "in");
+	qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
+	usb_settoggle (udev, ep, is_out, 1);
+}
+
+// Would be best to create all qh's from config descriptors,
+// when each interface/altsetting is established.  Unlink
+// any previous qh and cancel its urbs first; endpoints are
+// implicitly reset then (data toggle too).
+// That'd mean updating how usbcore talks to HCDs. (2.5?)
+
+
+/*
+ * Each QH holds a qtd list; a QH is used for everything except iso.
+ *
+ * For interrupt urbs, the scheduler must set the microframe scheduling
+ * mask(s) each time the QH gets scheduled.  For highspeed, that's
+ * just one microframe in the s-mask.  For split interrupt transactions
+ * there are additional complications: c-mask, maybe FSTNs.
+ */
+static struct ehci_qh *
+ehci_qh_make (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	struct list_head	*qtd_list,
+	int			flags
+) {
+	struct ehci_qh		*qh = ehci_qh_alloc (ehci, flags);
+	u32			info1 = 0, info2 = 0;
+
+	if (!qh)
+		return qh;
+
+	/*
+	 * init endpoint/device data for this QH
+	 */
+	info1 |= usb_pipeendpoint (urb->pipe) << 8;
+	info1 |= usb_pipedevice (urb->pipe) << 0;
+
+	/* using TT? */
+	switch (urb->dev->speed) {
+	case USB_SPEED_LOW:
+		info1 |= (1 << 12);	/* EPS "low" */
+		/* FALL THROUGH */
+
+	case USB_SPEED_FULL:
+		/* EPS 0 means "full" */
+		info1 |= (EHCI_TUNE_RL_TT << 28);
+		if (usb_pipecontrol (urb->pipe)) {
+			info1 |= (1 << 27);	/* for TT */
+			info1 |= 1 << 14;	/* toggle from qtd */
+		}
+		info1 |= usb_maxpacket (urb->dev, urb->pipe,
+					usb_pipeout (urb->pipe)) << 16;
+
+		info2 |= (EHCI_TUNE_MULT_TT << 30);
+		info2 |= urb->dev->ttport << 23;
+		info2 |= urb->dev->tt->hub->devnum << 16;
+
+		/* NOTE:  if (usb_pipeint (urb->pipe)) { scheduler sets c-mask }
+		 * ... and a 0.96 scheduler might use FSTN nodes too
+		 */
+		break;
+
+	case USB_SPEED_HIGH:		/* no TT involved */
+		info1 |= (2 << 12);	/* EPS "high" */
+		info1 |= (EHCI_TUNE_RL_HS << 28);
+		if (usb_pipecontrol (urb->pipe)) {
+			info1 |= 64 << 16;	/* usb2 fixed maxpacket */
+			info1 |= 1 << 14;	/* toggle from qtd */
+			info2 |= (EHCI_TUNE_MULT_HS << 30);
+		} else if (usb_pipebulk (urb->pipe)) {
+			info1 |= 512 << 16;	/* usb2 fixed maxpacket */
+			info2 |= (EHCI_TUNE_MULT_HS << 30);
+		} else {
+			u32	temp;
+			temp = usb_maxpacket (urb->dev, urb->pipe,
+						usb_pipeout (urb->pipe));
+			info1 |= (temp & 0x3ff) << 16;	/* maxpacket */
+			/* HS intr can be "high bandwidth" */
+			temp = 1 + ((temp >> 11) & 0x03);
+			info2 |= temp << 30;		/* mult */
+		}
+		break;
+	default:
+#ifdef DEBUG
+		BUG ();
+#endif
+	}
+
+	/* NOTE:  if (usb_pipeint (urb->pipe)) { scheduler sets s-mask } */
+
+	qh->qh_state = QH_STATE_IDLE;
+	qh->hw_info1 = cpu_to_le32 (info1);
+	qh->hw_info2 = cpu_to_le32 (info2);
+
+	/* initialize sw and hw queues with these qtds */
+	list_splice (qtd_list, &qh->qtd_list);
+	qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list));
+
+	/* initialize data toggle state */
+	if (!usb_pipecontrol (urb->pipe))
+		clear_toggle (urb->dev,
+			usb_pipeendpoint (urb->pipe),
+			usb_pipeout (urb->pipe),
+			qh);
+
+	return qh;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* move qh (and its qtds) onto async queue; maybe enable queue.  */
+
+static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+	u32		dma = QH_NEXT (qh->qh_dma);
+	struct ehci_qh	*q;
+
+	if (unlikely (!(q = ehci->async))) {
+		u32	cmd = readl (&ehci->regs->command);
+
+		/* in case a clear of CMD_ASE didn't take yet */
+		while (readl (&ehci->regs->status) & STS_ASS)
+			udelay (100);
+
+		qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
+		qh->qh_next.qh = qh;
+		qh->hw_next = dma;
+		ehci->async = qh;
+		writel ((u32)qh->qh_dma, &ehci->regs->async_next);
+		cmd |= CMD_ASE | CMD_RUN;
+		writel (cmd, &ehci->regs->command);
+		ehci->hcd.state = USB_STATE_RUNNING;
+		/* posted write need not be known to HC yet ... */
+	} else {
+		/* splice right after "start" of ring */
+		qh->hw_info1 &= ~__constant_cpu_to_le32 (QH_HEAD); /* [4.8] */
+		qh->qh_next = q->qh_next;
+		qh->hw_next = q->hw_next;
+		q->qh_next.qh = qh;
+		q->hw_next = dma;
+	}
+	qh->qh_state = QH_STATE_LINKED;
+	/* qtd completions reported later by interrupt */
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+submit_async (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	struct list_head	*qtd_list,
+	int			mem_flags
+) {
+	struct ehci_qtd		*qtd;
+	struct hcd_dev		*dev;
+	int			epnum;
+	unsigned long		flags;
+	struct ehci_qh		*qh = 0;
+
+	qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
+	dev = (struct hcd_dev *)urb->dev->hcpriv;
+	epnum = usb_pipeendpoint (urb->pipe);
+	if (usb_pipein (urb->pipe))
+		epnum |= 0x10;
+
+	vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]",
+		ehci->hcd.bus_name, urb, urb->transfer_buffer_length,
+		epnum & 0x0f, (epnum & 0x10) ? "in" : "out",
+		qtd, dev ? dev->ep [epnum] : (void *)~0);
+
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	qh = (struct ehci_qh *) dev->ep [epnum];
+	if (likely (qh != 0)) {
+		u32	hw_next = QTD_NEXT (qtd->qtd_dma);
+
+		/* maybe patch the qh used for set_address */
+		if (unlikely (epnum == 0
+				&& le32_to_cpu (qh->hw_info1 & 0x7f) == 0))
+			qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe));
+
+		/* is an URB is queued to this qh already? */
+		if (unlikely (!list_empty (&qh->qtd_list))) {
+			struct ehci_qtd		*last_qtd;
+			int			short_rx = 0;
+
+			/* update the last qtd's "next" pointer */
+			// dbg_qh ("non-empty qh", ehci, qh);
+			last_qtd = list_entry (qh->qtd_list.prev,
+					struct ehci_qtd, qtd_list);
+			last_qtd->hw_next = hw_next;
+
+			/* previous urb allows short rx? maybe optimize. */
+			if (!(last_qtd->urb->transfer_flags & USB_DISABLE_SPD)
+					&& (epnum & 0x10)) {
+				// only the last QTD for now
+				last_qtd->hw_alt_next = hw_next;
+				short_rx = 1;
+			}
+
+			/* Adjust any old copies in qh overlay too.
+			 * Interrupt code must cope with case of HC having it
+			 * cached, and clobbering these updates.
+			 * ... complicates getting rid of extra interrupts!
+			 */
+			if (qh->hw_current == cpu_to_le32 (last_qtd->qtd_dma)) {
+				wmb ();
+				qh->hw_qtd_next = hw_next;
+				if (short_rx)
+					qh->hw_alt_next = hw_next
+				    		| (qh->hw_alt_next & 0x1e);
+				vdbg ("queue to qh %p, patch", qh);
+			}
+
+		/* no URB queued */
+		} else {
+			// dbg_qh ("empty qh", ehci, qh);
+
+// FIXME:  how handle usb_clear_halt() for an EP with queued URBs?
+// usbcore may not let us handle that cleanly...
+// likely must cancel them all first!
+
+			/* usb_clear_halt() means qh data toggle gets reset */
+			if (usb_pipebulk (urb->pipe)
+					&& unlikely (!usb_gettoggle (urb->dev,
+						(epnum & 0x0f),
+						!(epnum & 0x10)))) {
+				clear_toggle (urb->dev,
+					epnum & 0x0f, !(epnum & 0x10), qh);
+			}
+			qh_update (qh, qtd);
+		}
+		list_splice (qtd_list, qh->qtd_list.prev);
+
+	} else {
+		/* can't sleep here, we have ehci->lock... */
+		qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC);
+		if (likely (qh != 0)) {
+			// dbg_qh ("new qh", ehci, qh);
+			dev->ep [epnum] = qh;
+		} else
+			urb->status = -ENOMEM;
+	}
+
+	/* Control/bulk operations through TTs don't need scheduling,
+	 * the HC and TT handle it when the TT has a buffer ready.
+	 */
+	if (likely (qh != 0)) {
+		urb->hcpriv = qh_put (qh);
+		if (likely (qh->qh_state == QH_STATE_IDLE))
+			qh_link_async (ehci, qh_put (qh));
+	}
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	if (unlikely (!qh))
+		qh_completions (ehci, qtd_list, 1);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* the async qh for the qtds being reclaimed are now unlinked from the HC */
+/* caller must not own ehci->lock */
+
+static void end_unlink_async (struct ehci_hcd *ehci)
+{
+	struct ehci_qh		*qh = ehci->reclaim;
+
+	qh->qh_state = QH_STATE_IDLE;
+	qh->qh_next.qh = 0;
+	qh_unput (ehci, qh);			// refcount from reclaim 
+	ehci->reclaim = 0;
+	ehci->reclaim_ready = 0;
+
+	qh_completions (ehci, &qh->qtd_list, 1);
+
+	// unlink any urb should now unlink all following urbs, so that
+	// relinking only happens for urbs before the unlinked ones.
+	if (!list_empty (&qh->qtd_list)
+			&& HCD_IS_RUNNING (ehci->hcd.state))
+		qh_link_async (ehci, qh);
+	else
+		qh_unput (ehci, qh);		// refcount from async list
+}
+
+
+/* makes sure the async qh will become idle */
+/* caller must own ehci->lock */
+
+static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+	int		cmd = readl (&ehci->regs->command);
+	struct ehci_qh	*prev;
+
+#ifdef DEBUG
+	if (ehci->reclaim
+			|| !ehci->async
+			|| qh->qh_state != QH_STATE_LINKED
+#ifdef CONFIG_SMP
+// this macro lies except on SMP compiles
+			|| !spin_is_locked (&ehci->lock)
+#endif
+			)
+		BUG ();
+#endif
+
+	qh->qh_state = QH_STATE_UNLINK;
+	ehci->reclaim = qh = qh_put (qh);
+
+	// dbg_qh ("start unlink", ehci, qh);
+
+	/* Remove the last QH (qhead)?  Stop async schedule first. */
+	if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) {
+		/* can't get here without STS_ASS set */
+		if (ehci->hcd.state != USB_STATE_HALT) {
+			if (cmd & CMD_PSE)
+				writel (cmd & ~CMD_ASE, &ehci->regs->command);
+			else {
+				ehci_ready (ehci);
+				while (readl (&ehci->regs->status) & STS_ASS)
+					udelay (100);
+			}
+		}
+		qh->qh_next.qh = ehci->async = 0;
+
+		ehci->reclaim_ready = 1;
+		tasklet_schedule (&ehci->tasklet);
+		return;
+	} 
+
+	if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
+		ehci->reclaim_ready = 1;
+		tasklet_schedule (&ehci->tasklet);
+		return;
+	}
+
+	prev = ehci->async;
+	while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async)
+		prev = prev->qh_next.qh;
+#ifdef DEBUG
+	if (prev->qh_next.qh != qh)
+		BUG ();
+#endif
+
+	if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) {
+		ehci->async = prev;
+		prev->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD);
+	}
+	prev->hw_next = qh->hw_next;
+	prev->qh_next = qh->qh_next;
+
+	ehci->reclaim_ready = 0;
+	cmd |= CMD_IAAD;
+	writel (cmd, &ehci->regs->command);
+	/* posted write need not be known to HC yet ... */
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void scan_async (struct ehci_hcd *ehci)
+{
+	struct ehci_qh		*qh;
+	unsigned long		flags;
+
+	spin_lock_irqsave (&ehci->lock, flags);
+rescan:
+	qh = ehci->async;
+	if (likely (qh != 0)) {
+		do {
+			/* clean any finished work for this qh */
+			if (!list_empty (&qh->qtd_list)) {
+				// dbg_qh ("scan_async", ehci, qh);
+				qh = qh_put (qh);
+				spin_unlock_irqrestore (&ehci->lock, flags);
+
+				/* concurrent unlink could happen here */
+				qh_completions (ehci, &qh->qtd_list, 1);
+
+				spin_lock_irqsave (&ehci->lock, flags);
+				qh_unput (ehci, qh);
+			}
+
+			/* unlink idle entries (reduces PCI usage) */
+			if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
+				if (qh->qh_next.qh != qh) {
+					// dbg ("irq/empty");
+					start_unlink_async (ehci, qh);
+				} else {
+					// FIXME:  arrange to stop
+					// after it's been idle a while.
+				}
+			}
+			qh = qh->qh_next.qh;
+			if (!qh)		/* unlinked? */
+				goto rescan;
+		} while (qh != ehci->async);
+	}
+
+	spin_unlock_irqrestore (&ehci->lock, flags);
+}
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci-sched.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,1212 @@
+/*
+ * Copyright (c) 2001-2002 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* this file is part of ehci-hcd.c */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI scheduled transaction support:  interrupt, iso, split iso
+ * These are called "periodic" transactions in the EHCI spec.
+ */
+
+/*
+ * Ceiling microseconds (typical) for that many bytes at high speed
+ * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
+ * to preallocate bandwidth)
+ */
+#define EHCI_HOST_DELAY	5	/* nsec, guess */
+#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
+	+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
+	+ EHCI_HOST_DELAY)
+#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
+	+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
+	+ EHCI_HOST_DELAY)
+	
+static int ehci_get_frame (struct usb_hcd *hcd);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * periodic_next_shadow - return "next" pointer on shadow list
+ * @periodic: host pointer to qh/itd/sitd
+ * @tag: hardware tag for type of this record
+ */
+static union ehci_shadow *
+periodic_next_shadow (union ehci_shadow *periodic, int tag)
+{
+	switch (tag) {
+	case Q_TYPE_QH:
+		return &periodic->qh->qh_next;
+	case Q_TYPE_FSTN:
+		return &periodic->fstn->fstn_next;
+	case Q_TYPE_ITD:
+		return &periodic->itd->itd_next;
+#ifdef have_split_iso
+	case Q_TYPE_SITD:
+		return &periodic->sitd->sitd_next;
+#endif /* have_split_iso */
+	}
+	dbg ("BAD shadow %p tag %d", periodic->ptr, tag);
+	// BUG ();
+	return 0;
+}
+
+/* returns true after successful unlink */
+/* caller must hold ehci->lock */
+static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
+{
+	union ehci_shadow	*prev_p = &ehci->pshadow [frame];
+	u32			*hw_p = &ehci->periodic [frame];
+	union ehci_shadow	here = *prev_p;
+	union ehci_shadow	*next_p;
+
+	/* find predecessor of "ptr"; hw and shadow lists are in sync */
+	while (here.ptr && here.ptr != ptr) {
+		prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
+		hw_p = &here.qh->hw_next;
+		here = *prev_p;
+	}
+	/* an interrupt entry (at list end) could have been shared */
+	if (!here.ptr) {
+		dbg ("entry %p no longer on frame [%d]", ptr, frame);
+		return 0;
+	}
+	// vdbg ("periodic unlink %p from frame %d", ptr, frame);
+
+	/* update hardware list ... HC may still know the old structure, so
+	 * don't change hw_next until it'll have purged its cache
+	 */
+	next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+	*hw_p = here.qh->hw_next;
+
+	/* unlink from shadow list; HCD won't see old structure again */
+	*prev_p = *next_p;
+	next_p->ptr = 0;
+
+	return 1;
+}
+
+/* how many of the uframe's 125 usecs are allocated? */
+static unsigned short
+periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
+{
+	u32			*hw_p = &ehci->periodic [frame];
+	union ehci_shadow	*q = &ehci->pshadow [frame];
+	unsigned		usecs = 0;
+
+	while (q->ptr) {
+		switch (Q_NEXT_TYPE (*hw_p)) {
+		case Q_TYPE_QH:
+			/* is it in the S-mask? */
+			if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
+				usecs += q->qh->usecs;
+			q = &q->qh->qh_next;
+			break;
+		case Q_TYPE_FSTN:
+			/* for "save place" FSTNs, count the relevant INTR
+			 * bandwidth from the previous frame
+			 */
+			if (q->fstn->hw_prev != EHCI_LIST_END) {
+				dbg ("not counting FSTN bandwidth yet ...");
+			}
+			q = &q->fstn->fstn_next;
+			break;
+		case Q_TYPE_ITD:
+			/* NOTE the "one uframe per itd" policy */
+			if (q->itd->hw_transaction [uframe] != 0)
+				usecs += q->itd->usecs;
+			q = &q->itd->itd_next;
+			break;
+#ifdef have_split_iso
+		case Q_TYPE_SITD:
+			temp = q->sitd->hw_fullspeed_ep &
+				__constant_cpu_to_le32 (1 << 31);
+
+			// FIXME:  this doesn't count data bytes right...
+
+			/* is it in the S-mask?  (count SPLIT, DATA) */
+			if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
+				if (temp)
+					usecs += HS_USECS (188);
+				else
+					usecs += HS_USECS (1);
+			}
+
+			/* ... C-mask?  (count CSPLIT, DATA) */
+			if (q->sitd->hw_uframe &
+					cpu_to_le32 (1 << (8 + uframe))) {
+				if (temp)
+					usecs += HS_USECS (0);
+				else
+					usecs += HS_USECS (188);
+			}
+			q = &q->sitd->sitd_next;
+			break;
+#endif /* have_split_iso */
+		default:
+			BUG ();
+		}
+	}
+#ifdef	DEBUG
+	if (usecs > 100)
+		err ("overallocated uframe %d, periodic is %d usecs",
+			frame * 8 + uframe, usecs);
+#endif
+	return usecs;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void enable_periodic (struct ehci_hcd *ehci)
+{
+	u32	cmd;
+
+	/* did clearing PSE did take effect yet?
+	 * takes effect only at frame boundaries...
+	 */
+	while (readl (&ehci->regs->status) & STS_PSS)
+		udelay (20);
+
+	cmd = readl (&ehci->regs->command) | CMD_PSE;
+	writel (cmd, &ehci->regs->command);
+	/* posted write ... PSS happens later */
+	ehci->hcd.state = USB_STATE_RUNNING;
+
+	/* make sure tasklet scans these */
+	ehci->next_uframe = readl (&ehci->regs->frame_index)
+				% (ehci->periodic_size << 3);
+}
+
+static void disable_periodic (struct ehci_hcd *ehci)
+{
+	u32	cmd;
+
+	/* did setting PSE not take effect yet?
+	 * takes effect only at frame boundaries...
+	 */
+	while (!(readl (&ehci->regs->status) & STS_PSS))
+		udelay (20);
+
+	cmd = readl (&ehci->regs->command) & ~CMD_PSE;
+	writel (cmd, &ehci->regs->command);
+	/* posted write ... */
+
+	ehci->next_uframe = -1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void intr_deschedule (
+	struct ehci_hcd	*ehci,
+	unsigned	frame,
+	struct ehci_qh	*qh,
+	unsigned	period
+) {
+	unsigned long	flags;
+
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	do {
+		periodic_unlink (ehci, frame, qh);
+		qh_unput (ehci, qh);
+		frame += period;
+	} while (frame < ehci->periodic_size);
+
+	qh->qh_state = QH_STATE_UNLINK;
+	qh->qh_next.ptr = 0;
+	ehci->periodic_urbs--;
+
+	/* maybe turn off periodic schedule */
+	if (!ehci->periodic_urbs)
+		disable_periodic (ehci);
+	else
+		vdbg ("periodic schedule still enabled");
+
+	spin_unlock_irqrestore (&ehci->lock, flags);
+
+	/*
+	 * If the hc may be looking at this qh, then delay a uframe
+	 * (yeech!) to be sure it's done.
+	 * No other threads may be mucking with this qh.
+	 */
+	if (((ehci_get_frame (&ehci->hcd) - frame) % period) == 0)
+		udelay (125);
+
+	qh->qh_state = QH_STATE_IDLE;
+	qh->hw_next = EHCI_LIST_END;
+
+	vdbg ("descheduled qh %p, per = %d frame = %d count = %d, urbs = %d",
+		qh, period, frame,
+		atomic_read (&qh->refcount), ehci->periodic_urbs);
+}
+
+static int intr_submit (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	struct list_head	*qtd_list,
+	int			mem_flags
+) {
+	unsigned		epnum, period;
+	unsigned		temp;
+	unsigned short		usecs;
+	unsigned long		flags;
+	struct ehci_qh		*qh;
+	struct hcd_dev		*dev;
+	int			status = 0;
+
+	/* get endpoint and transfer data */
+	epnum = usb_pipeendpoint (urb->pipe);
+	if (usb_pipein (urb->pipe)) {
+		temp = urb->dev->epmaxpacketin [epnum];
+		epnum |= 0x10;
+	} else
+		temp = urb->dev->epmaxpacketout [epnum];
+	if (urb->dev->speed != USB_SPEED_HIGH) {
+		dbg ("no intr/tt scheduling yet"); 
+		status = -ENOSYS;
+		goto done;
+	}
+
+	/*
+	 * NOTE: current completion/restart logic doesn't handle more than
+	 * one qtd in a periodic qh ... 16-20 KB/urb is pretty big for this.
+	 * such big requests need many periods to transfer.
+	 */
+	if (unlikely (qtd_list->next != qtd_list->prev)) {
+		dbg ("only one intr qtd per urb allowed"); 
+		status = -EINVAL;
+		goto done;
+	}
+
+	usecs = HS_USECS (urb->transfer_buffer_length);
+
+	/* FIXME handle HS periods of less than 1 frame. */
+	if (urb->interval < 8)
+		period = 1;
+	else
+		period = urb->interval >> 8;
+		
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	/* get the qh (must be empty and idle) */
+	dev = (struct hcd_dev *)urb->dev->hcpriv;
+	qh = (struct ehci_qh *) dev->ep [epnum];
+	if (qh) {
+		/* only allow one queued interrupt urb per EP */
+		if (unlikely (qh->qh_state != QH_STATE_IDLE
+				|| !list_empty (&qh->qtd_list))) {
+			dbg ("interrupt urb already queued");
+			status = -EBUSY;
+		} else {
+			/* maybe reset hardware's data toggle in the qh */
+			if (unlikely (!usb_gettoggle (urb->dev, epnum & 0x0f,
+					!(epnum & 0x10)))) {
+				qh->hw_token |=
+					__constant_cpu_to_le32 (QTD_TOGGLE);
+				usb_settoggle (urb->dev, epnum & 0x0f,
+					!(epnum & 0x10), 1);
+			}
+			/* trust the QH was set up as interrupt ... */
+			list_splice (qtd_list, &qh->qtd_list);
+			qh_update (qh, list_entry (qtd_list->next,
+						struct ehci_qtd, qtd_list));
+		}
+	} else {
+		/* can't sleep here, we have ehci->lock... */
+		qh = ehci_qh_make (ehci, urb, qtd_list, SLAB_ATOMIC);
+		qtd_list = &qh->qtd_list;
+		if (likely (qh != 0)) {
+			// dbg ("new INTR qh %p", qh);
+			dev->ep [epnum] = qh;
+		} else
+			status = -ENOMEM;
+	}
+
+	/* Schedule this periodic QH. */
+	if (likely (status == 0)) {
+		unsigned	frame = urb->interval;
+
+		qh->hw_next = EHCI_LIST_END;
+		qh->usecs = usecs;
+
+		urb->hcpriv = qh_put (qh);
+		status = -ENOSPC;
+
+		/* pick a set of schedule slots, link the QH into them */
+		do {
+			int	uframe;
+
+			/* Select some frame 0..(urb->interval - 1) with a
+			 * microframe that can hold this transaction.
+			 *
+			 * FIXME for TT splits, need uframes for start and end.
+			 * FSTNs can put end into next frame (uframes 0 or 1).
+			 */
+			frame--;
+			for (uframe = 0; uframe < 8; uframe++) {
+				int	claimed;
+				claimed = periodic_usecs (ehci, frame, uframe);
+				/* 80% periodic == 100 usec max committed */
+				if ((claimed + usecs) <= 100) {
+					vdbg ("frame %d.%d: %d usecs, plus %d",
+						frame, uframe, claimed, usecs);
+					break;
+				}
+			}
+			if (uframe == 8)
+				continue;
+// FIXME delete when code below handles non-empty queues
+			if (ehci->pshadow [frame].ptr)
+				continue;
+
+			/* QH will run once each period, starting there  */
+			urb->start_frame = frame;
+			status = 0;
+
+			/* set S-frame mask */
+			qh->hw_info2 |= cpu_to_le32 (1 << uframe);
+			// dbg_qh ("Schedule INTR qh", ehci, qh);
+
+			/* stuff into the periodic schedule */
+			qh->qh_state = QH_STATE_LINKED;
+			vdbg ("qh %p usecs %d period %d starting %d.%d",
+				qh, qh->usecs, period, frame, uframe);
+			do {
+				if (unlikely (ehci->pshadow [frame].ptr != 0)) {
+// FIXME -- just link to the end, before any qh with a shorter period,
+// AND handle it already being (implicitly) linked into this frame
+					BUG ();
+				} else {
+					ehci->pshadow [frame].qh = qh_put (qh);
+					ehci->periodic [frame] =
+						QH_NEXT (qh->qh_dma);
+				}
+				frame += period;
+			} while (frame < ehci->periodic_size);
+
+			/* update bandwidth utilization records (for usbfs) */
+			usb_claim_bandwidth (urb->dev, urb, usecs, 0);
+
+			/* maybe enable periodic schedule processing */
+			if (!ehci->periodic_urbs++)
+				enable_periodic (ehci);
+			break;
+
+		} while (frame);
+	}
+	spin_unlock_irqrestore (&ehci->lock, flags);
+done:
+	if (status) {
+		usb_complete_t	complete = urb->complete;
+
+		urb->complete = 0;
+		urb->status = status;
+		qh_completions (ehci, qtd_list, 1);
+		urb->complete = complete;
+	}
+	return status;
+}
+
+static unsigned long
+intr_complete (
+	struct ehci_hcd	*ehci,
+	unsigned	frame,
+	struct ehci_qh	*qh,
+	unsigned long	flags		/* caller owns ehci->lock ... */
+) {
+	struct ehci_qtd	*qtd;
+	struct urb	*urb;
+	int		unlinking;
+
+	/* nothing to report? */
+	if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
+			!= 0))
+		return flags;
+	
+	qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list);
+	urb = qtd->urb;
+	unlinking = (urb->status == -ENOENT) || (urb->status == -ECONNRESET);
+
+	/* call any completions, after patching for reactivation */
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	/* NOTE:  currently restricted to one qtd per qh! */
+	if (qh_completions (ehci, &qh->qtd_list, 0) == 0)
+		urb = 0;
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	/* never reactivate requests that were unlinked ... */
+	if (likely (urb != 0)) {
+		if (unlinking
+				|| urb->status == -ECONNRESET
+				|| urb->status == -ENOENT
+				// || (urb->dev == null)
+				|| ehci->hcd.state == USB_STATE_HALT)
+			urb = 0;
+		// FIXME look at all those unlink cases ... we always
+		// need exactly one completion that reports unlink.
+		// the one above might not have been it!
+	}
+
+	/* normally reactivate */
+	if (likely (urb != 0)) {
+		if (usb_pipeout (urb->pipe))
+			pci_dma_sync_single (ehci->hcd.pdev,
+				qtd->buf_dma,
+				urb->transfer_buffer_length,
+				PCI_DMA_TODEVICE);
+		urb->status = -EINPROGRESS;
+		urb->actual_length = 0;
+
+		/* patch qh and restart */
+		qh_update (qh, qtd);
+	}
+	return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
+{
+	struct ehci_itd *first_itd = urb->hcpriv;
+
+	pci_unmap_single (ehci->hcd.pdev,
+		first_itd->buf_dma, urb->transfer_buffer_length,
+		usb_pipein (urb->pipe)
+		    ? PCI_DMA_FROMDEVICE
+		    : PCI_DMA_TODEVICE);
+	while (!list_empty (&first_itd->itd_list)) {
+		struct ehci_itd	*itd;
+
+		itd = list_entry (
+			first_itd->itd_list.next,
+			struct ehci_itd, itd_list);
+		list_del (&itd->itd_list);
+		pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
+	}
+	pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma);
+	urb->hcpriv = 0;
+}
+
+static int
+itd_fill (
+	struct ehci_hcd	*ehci,
+	struct ehci_itd	*itd,
+	struct urb	*urb,
+	unsigned	index,		// urb->iso_frame_desc [index]
+	dma_addr_t	dma		// mapped transfer buffer
+) {
+	u64		temp;
+	u32		buf1;
+	unsigned	i, epnum, maxp, multi;
+	unsigned	length;
+
+	itd->hw_next = EHCI_LIST_END;
+	itd->urb = urb;
+	itd->index = index;
+
+	/* tell itd about its transfer buffer, max 2 pages */
+	length = urb->iso_frame_desc [index].length;
+	dma += urb->iso_frame_desc [index].offset;
+	temp = dma & ~0x0fff;
+	for (i = 0; i < 2; i++) {
+		itd->hw_bufp [i] = cpu_to_le32 ((u32) temp);
+		itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32));
+		temp += 0x1000;
+	}
+	itd->buf_dma = dma;
+
+	/*
+	 * this might be a "high bandwidth" highspeed endpoint,
+	 * as encoded in the ep descriptor's maxpacket field
+	 */
+	epnum = usb_pipeendpoint (urb->pipe);
+	if (usb_pipein (urb->pipe)) {
+		maxp = urb->dev->epmaxpacketin [epnum];
+		buf1 = (1 << 11);
+	} else {
+		maxp = urb->dev->epmaxpacketout [epnum];
+		buf1 = 0;
+	}
+	buf1 |= (maxp & 0x03ff);
+	multi = 1;
+	multi += (maxp >> 11) & 0x03;
+	maxp &= 0x03ff;
+	maxp *= multi;
+
+	/* transfer can't fit in any uframe? */ 
+	if (length < 0 || maxp < length) {
+		dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)",
+			length, maxp, urb, index,
+			urb->iso_frame_desc [index].length);
+		return -ENOSPC;
+	}
+	itd->usecs = HS_USECS_ISO (length);
+
+	/* "plus" info in low order bits of buffer pointers */
+	itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum);
+	itd->hw_bufp [1] |= cpu_to_le32 (buf1);
+	itd->hw_bufp [2] |= cpu_to_le32 (multi);
+
+	/* figure hw_transaction[] value (it's scheduled later) */
+	itd->transaction = EHCI_ISOC_ACTIVE;
+	itd->transaction |= dma & 0x0fff;		/* offset; buffer=0 */
+	if ((index + 1) == urb->number_of_packets)
+		itd->transaction |= EHCI_ITD_IOC; 	/* end-of-urb irq */
+	itd->transaction |= length << 16;
+	cpu_to_le32s (&itd->transaction);
+
+	return 0;
+}
+
+static int
+itd_urb_transaction (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	int			mem_flags
+) {
+	int			frame_index;
+	struct ehci_itd		*first_itd, *itd;
+	int			status;
+	dma_addr_t		buf_dma, itd_dma;
+
+	/* set up one dma mapping for this urb */
+	buf_dma = pci_map_single (ehci->hcd.pdev,
+		urb->transfer_buffer, urb->transfer_buffer_length,
+		usb_pipein (urb->pipe)
+		    ? PCI_DMA_FROMDEVICE
+		    : PCI_DMA_TODEVICE);
+	if (buf_dma == 0)
+		return -ENOMEM;
+
+	/* allocate/init ITDs */
+	for (frame_index = 0, first_itd = 0;
+			frame_index < urb->number_of_packets;
+			frame_index++) {
+		itd = pci_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma);
+		if (!itd) {
+			status = -ENOMEM;
+			goto fail;
+		}
+		memset (itd, 0, sizeof *itd);
+		itd->itd_dma = itd_dma;
+
+		status = itd_fill (ehci, itd, urb, frame_index, buf_dma);
+		if (status != 0)
+			goto fail;
+
+		if (first_itd)
+			list_add_tail (&itd->itd_list,
+					&first_itd->itd_list);
+		else {
+			INIT_LIST_HEAD (&itd->itd_list);
+			urb->hcpriv = first_itd = itd;
+		}
+	}
+	urb->error_count = 0;
+	return 0;
+
+fail:
+	if (urb->hcpriv)
+		itd_free_list (ehci, urb);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void
+itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
+{
+	/* always prepend ITD/SITD ... only QH tree is order-sensitive */
+	itd->itd_next = ehci->pshadow [frame];
+	itd->hw_next = ehci->periodic [frame];
+	ehci->pshadow [frame].itd = itd;
+	ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
+}
+
+/*
+ * return zero on success, else -errno
+ * - start holds first uframe to start scheduling into
+ * - max is the first uframe it's NOT (!) OK to start scheduling into
+ * math to be done modulo "mod" (ehci->periodic_size << 3)
+ */
+static int get_iso_range (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	unsigned		*start,
+	unsigned		*max,
+	unsigned		mod
+) {
+	struct list_head	*lh;
+	struct hcd_dev		*dev = urb->dev->hcpriv;
+	int			last = -1;
+	unsigned		now, span, end;
+
+	span = urb->interval * urb->number_of_packets;
+
+	/* first see if we know when the next transfer SHOULD happen */
+	list_for_each (lh, &dev->urb_list) {
+		struct urb	*u;
+		struct ehci_itd	*itd;
+		unsigned	s;
+
+		u = list_entry (lh, struct urb, urb_list);
+		if (u == urb || u->pipe != urb->pipe)
+			continue;
+		if (u->interval != urb->interval) {	/* must not change! */ 
+			dbg ("urb %p interval %d ... != %p interval %d",
+				u, u->interval, urb, urb->interval);
+			return -EINVAL;
+		}
+		
+		/* URB for this endpoint... covers through when?  */
+		itd = urb->hcpriv;
+		s = itd->uframe + u->interval * u->number_of_packets;
+		if (last < 0)
+			last = s;
+		else {
+			/*
+			 * So far we can only queue two ISO URBs...
+			 *
+			 * FIXME do interval math, figure out whether
+			 * this URB is "before" or not ... also, handle
+			 * the case where the URB might have completed,
+			 * but hasn't yet been processed.
+			 */
+			dbg ("NYET: queue >2 URBs per ISO endpoint");
+			return -EDOM;
+		}
+	}
+
+	/* calculate the legal range [start,max) */
+	now = readl (&ehci->regs->frame_index) + 1;	/* next uframe */
+	if (!ehci->periodic_urbs)
+		now += 8;				/* startup delay */
+	now %= mod;
+	end = now + mod;
+	if (last < 0) {
+		*start = now + ehci->i_thresh + /* paranoia */ 1;
+		*max = end - span;
+		if (*max < *start + 1)
+			*max = *start + 1;
+	} else {
+		*start = last % mod;
+		*max = (last + 1) % mod;
+	}
+
+	/* explicit start frame? */
+	if (!(urb->transfer_flags & USB_ISO_ASAP)) {
+		unsigned	temp;
+
+		/* sanity check: must be in range */
+		urb->start_frame %= ehci->periodic_size;
+		temp = urb->start_frame << 3;
+		if (temp < *start)
+			temp += mod;
+		if (temp > *max)
+			return -EDOM;
+
+		/* use that explicit start frame */
+		*start = urb->start_frame << 3;
+		temp += 8;
+		if (temp < *max)
+			*max = temp;
+	}
+
+	// FIXME minimize wraparound to "now" ... insist max+span
+	// (and start+span) remains a few frames short of "end"
+
+	*max %= ehci->periodic_size;
+	if ((*start + span) < end)
+		return 0;
+	return -EFBIG;
+}
+
+static int
+itd_schedule (struct ehci_hcd *ehci, struct urb *urb)
+{
+	unsigned	start, max, i;
+	int		status;
+	unsigned	mod = ehci->periodic_size << 3;
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		urb->iso_frame_desc [i].status = -EINPROGRESS;
+		urb->iso_frame_desc [i].actual_length = 0;
+	}
+
+	if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0)
+		return status;
+
+	do {
+		unsigned	uframe;
+		unsigned	usecs;
+		struct ehci_itd	*itd;
+
+		/* check schedule: enough space? */
+		itd = urb->hcpriv;
+		uframe = start;
+		for (i = 0, uframe = start;
+				i < urb->number_of_packets;
+				i++, uframe += urb->interval) {
+			uframe %= mod;
+
+			/* can't commit more than 80% periodic == 100 usec */
+			if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
+					> (100 - itd->usecs)) {
+				itd = 0;
+				break;
+			}
+			itd = list_entry (itd->itd_list.next,
+				struct ehci_itd, itd_list);
+		}
+		if (!itd)
+			continue;
+		
+		/* that's where we'll schedule this! */
+		itd = urb->hcpriv;
+		urb->start_frame = start >> 3;
+		vdbg ("ISO urb %p (%d packets period %d) starting %d.%d",
+			urb, urb->number_of_packets, urb->interval,
+			urb->start_frame, start & 0x7);
+		for (i = 0, uframe = start, usecs = 0;
+				i < urb->number_of_packets;
+				i++, uframe += urb->interval) {
+			uframe %= mod;
+
+			itd->uframe = uframe;
+			itd->hw_transaction [uframe & 0x07] = itd->transaction;
+			itd_link (ehci, (uframe >> 3) % ehci->periodic_size,
+				itd);
+			usecs += itd->usecs;
+
+			itd = list_entry (itd->itd_list.next,
+				struct ehci_itd, itd_list);
+		}
+
+		/* update bandwidth utilization records (for usbfs) */
+		/* FIXME usbcore expects per-frame average, which isn't
+		 * most accurate model... this provides the total claim,
+		 * and expects the average to be computed only display.
+		 */
+		usb_claim_bandwidth (urb->dev, urb, usecs, 1);
+
+		/* maybe enable periodic schedule processing */
+		if (!ehci->periodic_urbs++)
+			enable_periodic (ehci);
+
+		return 0;
+
+	} while ((start = ++start % mod) != max);
+
+	/* no room in the schedule */
+	dbg ("urb %p, CAN'T SCHEDULE", urb);
+	return -ENOSPC;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define	ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
+
+static unsigned long
+itd_complete (
+	struct ehci_hcd	*ehci,
+	struct ehci_itd	*itd,
+	unsigned	uframe,
+	unsigned long	flags
+) {
+	struct urb				*urb = itd->urb;
+	struct usb_iso_packet_descriptor	*desc;
+	u32					t;
+
+	/* update status for this uframe's transfers */
+	desc = &urb->iso_frame_desc [itd->index];
+
+	t = itd->hw_transaction [uframe];
+	itd->hw_transaction [uframe] = 0;
+	if (t & EHCI_ISOC_ACTIVE)
+		desc->status = -EXDEV;
+	else if (t & ISO_ERRS) {
+		urb->error_count++;
+		if (t & EHCI_ISOC_BUF_ERR)
+			desc->status = usb_pipein (urb->pipe)
+				? -ENOSR  /* couldn't read */
+				: -ECOMM; /* couldn't write */
+		else if (t & EHCI_ISOC_BABBLE)
+			desc->status = -EOVERFLOW;
+		else /* (t & EHCI_ISOC_XACTERR) */
+			desc->status = -EPROTO;
+
+		/* HC need not update length with this error */
+		if (!(t & EHCI_ISOC_BABBLE))
+			desc->actual_length += EHCI_ITD_LENGTH (t);
+	} else {
+		desc->status = 0;
+		desc->actual_length += EHCI_ITD_LENGTH (t);
+	}
+
+	vdbg ("itd %p urb %p packet %d/%d trans %x status %d len %d",
+		itd, urb, itd->index + 1, urb->number_of_packets,
+		t, desc->status, desc->actual_length);
+
+	/* handle completion now? */
+	if ((itd->index + 1) != urb->number_of_packets)
+		return flags;
+
+	/*
+	 * For now, always give the urb back to the driver ... expect it
+	 * to submit a new urb (or resubmit this), and to have another
+	 * already queued when un-interrupted transfers are needed.
+	 * No, that's not what OHCI or UHCI are now doing.
+	 *
+	 * FIXME Revisit the ISO URB model.  It's cleaner not to have all
+	 * the special case magic, but it'd be faster to reuse existing
+	 * ITD/DMA setup and schedule state.  Easy to dma_sync/complete(),
+	 * then either reschedule or, if unlinking, free and giveback().
+	 * But we can't overcommit like the full and low speed HCs do, and
+	 * there's no clean way to report an error when rescheduling...
+	 *
+	 * NOTE that for now we don't accelerate ISO unlinks; they just
+	 * happen according to the current schedule.  Means a delay of
+	 * up to about a second (max).
+	 */
+	itd_free_list (ehci, urb);
+	if (urb->status == -EINPROGRESS)
+		urb->status = 0;
+
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	usb_hcd_giveback_urb (&ehci->hcd, urb);
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	/* defer stopping schedule; completion can submit */
+	ehci->periodic_urbs--;
+	if (!ehci->periodic_urbs)
+		disable_periodic (ehci);
+
+	return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+{
+	int		status;
+	unsigned long	flags;
+
+	dbg ("itd_submit urb %p", urb);
+
+	/* NOTE DMA mapping assumes this ... */
+	if (urb->iso_frame_desc [0].offset != 0)
+		return -EINVAL;
+	
+	/*
+	 * NOTE doing this for now, anticipating periodic URB models
+	 * get updated to be "explicit resubmit".
+	 */
+	if (urb->next) {
+		dbg ("use explicit resubmit for ISO");
+		return -EINVAL;
+	}
+
+	/* allocate ITDs w/o locking anything */
+	status = itd_urb_transaction (ehci, urb, mem_flags);
+	if (status < 0)
+		return status;
+
+	/* schedule ... need to lock */
+	spin_lock_irqsave (&ehci->lock, flags);
+	status = itd_schedule (ehci, urb);
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	if (status < 0)
+		itd_free_list (ehci, urb);
+
+	return status;
+}
+
+#ifdef have_split_iso
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * "Split ISO TDs" ... used for USB 1.1 devices going through
+ * the TTs in USB 2.0 hubs.
+ */
+
+static void
+sitd_free (struct ehci_hcd *ehci, struct ehci_sitd *sitd)
+{
+	pci_pool_free (ehci->sitd_pool, sitd, sitd->sitd_dma);
+}
+
+static struct ehci_sitd *
+sitd_make (
+	struct ehci_hcd	*ehci,
+	struct urb	*urb,
+	unsigned	index,		// urb->iso_frame_desc [index]
+	unsigned	uframe,		// scheduled start
+	dma_addr_t	dma,		// mapped transfer buffer
+	int		mem_flags
+) {
+	struct ehci_sitd	*sitd;
+	unsigned		length;
+
+	sitd = pci_pool_alloc (ehci->sitd_pool, mem_flags, &dma);
+	if (!sitd)
+		return sitd;
+	sitd->urb = urb;
+	length = urb->iso_frame_desc [index].length;
+	dma += urb->iso_frame_desc [index].offset;
+
+#if 0
+	// FIXME:  do the rest!
+#else
+	sitd_free (ehci, sitd);
+	return 0;
+#endif
+
+}
+
+static void
+sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
+{
+	u32		ptr;
+
+	ptr = cpu_to_le32 (sitd->sitd_dma | 2);	// type 2 == sitd
+	if (ehci->pshadow [frame].ptr) {
+		if (!sitd->sitd_next.ptr) {
+			sitd->sitd_next = ehci->pshadow [frame];
+			sitd->hw_next = ehci->periodic [frame];
+		} else if (sitd->sitd_next.ptr != ehci->pshadow [frame].ptr) {
+			dbg ("frame %d sitd link goof", frame);
+			BUG ();
+		}
+	}
+	ehci->pshadow [frame].sitd = sitd;
+	ehci->periodic [frame] = ptr;
+}
+
+static unsigned long
+sitd_complete (
+	struct ehci_hcd *ehci,
+	struct ehci_sitd	*sitd,
+	unsigned long		flags
+) {
+	// FIXME -- implement!
+
+	dbg ("NYI -- sitd_complete");
+	return flags;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+{
+	// struct ehci_sitd	*first_sitd = 0;
+	unsigned		frame_index;
+	dma_addr_t		dma;
+
+	dbg ("NYI -- sitd_submit");
+
+	// FIXME -- implement!
+
+	// FIXME:  setup one big dma mapping
+	dma = 0;
+
+	for (frame_index = 0;
+			frame_index < urb->number_of_packets;
+			frame_index++) {
+		struct ehci_sitd	*sitd;
+		unsigned		uframe;
+
+		// FIXME:  use real arguments, schedule this!
+		uframe = -1;
+
+		sitd = sitd_make (ehci, urb, frame_index,
+				uframe, dma, mem_flags);
+
+		if (sitd) {
+    /*
+			if (first_sitd)
+				list_add_tail (&sitd->sitd_list,
+						&first_sitd->sitd_list);
+			else
+				first_sitd = sitd;
+    */
+		} else {
+			// FIXME:  clean everything up
+		}
+	}
+
+	// if we have a first sitd, then
+		// store them all into the periodic schedule!
+		// urb->hcpriv = first sitd in sitd_list
+
+	return -ENOSYS;
+}
+#endif /* have_split_iso */
+
+/*-------------------------------------------------------------------------*/
+
+static void scan_periodic (struct ehci_hcd *ehci)
+{
+	unsigned	frame, clock, now_uframe, mod;
+	unsigned long	flags;
+
+	mod = ehci->periodic_size << 3;
+	spin_lock_irqsave (&ehci->lock, flags);
+
+	/*
+	 * When running, scan from last scan point up to "now"
+	 * else clean up by scanning everything that's left.
+	 * Touches as few pages as possible:  cache-friendly.
+	 * Don't scan ISO entries more than once, though.
+	 */
+	frame = ehci->next_uframe >> 3;
+	if (HCD_IS_RUNNING (ehci->hcd.state))
+		now_uframe = readl (&ehci->regs->frame_index);
+	else
+		now_uframe = (frame << 3) - 1;
+	now_uframe %= mod;
+	clock = now_uframe >> 3;
+
+	for (;;) {
+		union ehci_shadow	q, *q_p;
+		u32			type, *hw_p;
+		unsigned		uframes;
+
+restart:
+		/* scan schedule to _before_ current frame index */
+		if (frame == clock)
+			uframes = now_uframe & 0x07;
+		else
+			uframes = 8;
+
+		q_p = &ehci->pshadow [frame];
+		hw_p = &ehci->periodic [frame];
+		q.ptr = q_p->ptr;
+		type = Q_NEXT_TYPE (*hw_p);
+
+		/* scan each element in frame's queue for completions */
+		while (q.ptr != 0) {
+			int			last;
+			unsigned		uf;
+			union ehci_shadow	temp;
+
+			switch (type) {
+			case Q_TYPE_QH:
+				last = (q.qh->hw_next == EHCI_LIST_END);
+				temp = q.qh->qh_next;
+				type = Q_NEXT_TYPE (q.qh->hw_next);
+				flags = intr_complete (ehci, frame,
+						qh_put (q.qh), flags);
+				qh_unput (ehci, q.qh);
+				q = temp;
+				break;
+			case Q_TYPE_FSTN:
+				last = (q.fstn->hw_next == EHCI_LIST_END);
+				/* for "save place" FSTNs, look at QH entries
+				 * in the previous frame for completions.
+				 */
+				if (q.fstn->hw_prev != EHCI_LIST_END) {
+					dbg ("ignoring completions from FSTNs");
+				}
+				type = Q_NEXT_TYPE (q.fstn->hw_next);
+				q = q.fstn->fstn_next;
+				break;
+			case Q_TYPE_ITD:
+				last = (q.itd->hw_next == EHCI_LIST_END);
+
+				/* Unlink each (S)ITD we see, since the ISO
+				 * URB model forces constant rescheduling.
+				 * That complicates sharing uframes in ITDs,
+				 * and means we need to skip uframes the HC
+				 * hasn't yet processed.
+				 */
+				for (uf = 0; uf < uframes; uf++) {
+					if (q.itd->hw_transaction [uf] != 0) {
+						temp = q;
+						*q_p = q.itd->itd_next;
+						*hw_p = q.itd->hw_next;
+						type = Q_NEXT_TYPE (*hw_p);
+
+						/* might free q.itd ... */
+						flags = itd_complete (ehci,
+							temp.itd, uf, flags);
+						break;
+					}
+				}
+				/* we might skip this ITD's uframe ... */
+				if (uf == uframes) {
+					q_p = &q.itd->itd_next;
+					hw_p = &q.itd->hw_next;
+					type = Q_NEXT_TYPE (q.itd->hw_next);
+				}
+
+				q = *q_p;
+				break;
+#ifdef have_split_iso
+			case Q_TYPE_SITD:
+				last = (q.sitd->hw_next == EHCI_LIST_END);
+				flags = sitd_complete (ehci, q.sitd, flags);
+				type = Q_NEXT_TYPE (q.sitd->hw_next);
+
+				// FIXME unlink SITD after split completes
+				q = q.sitd->sitd_next;
+				break;
+#endif /* have_split_iso */
+			default:
+				dbg ("corrupt type %d frame %d shadow %p",
+					type, frame, q.ptr);
+				// BUG ();
+				last = 1;
+				q.ptr = 0;
+			}
+
+			/* did completion remove an interior q entry? */
+			if (unlikely (q.ptr == 0 && !last))
+				goto restart;
+		}
+
+		/* stop when we catch up to the HC */
+
+		// FIXME:  this assumes we won't get lapped when
+		// latencies climb; that should be rare, but...
+		// detect it, and just go all the way around.
+		// FLR might help detect this case, so long as latencies
+		// don't exceed periodic_size msec (default 1.024 sec).
+
+		// FIXME:  likewise assumes HC doesn't halt mid-scan
+
+		if (frame == clock) {
+			unsigned	now;
+
+			if (!HCD_IS_RUNNING (ehci->hcd.state))
+				break;
+			ehci->next_uframe = now_uframe;
+			now = readl (&ehci->regs->frame_index) % mod;
+			if (now_uframe == now)
+				break;
+
+			/* rescan the rest of this frame, then ... */
+			now_uframe = now;
+			clock = now_uframe >> 3;
+		} else
+			frame = (frame + 1) % ehci->periodic_size;
+	} 
+	spin_unlock_irqrestore (&ehci->lock, flags);
+}
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ehci.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2001-2002 by David Brownell
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_EHCI_HCD_H
+#define __LINUX_EHCI_HCD_H
+
+/* definitions used for the EHCI driver */
+
+/* ehci_hcd->lock guards shared data against other CPUs:
+ *   ehci_hcd:	async, reclaim, periodic (and shadow), ...
+ *   hcd_dev:	ep[]
+ *   ehci_qh:	qh_next, qtd_list
+ *   ehci_qtd:	qtd_list
+ *
+ * Also, hold this lock when talking to HC registers or
+ * when updating hw_* fields in shared qh/qtd/... structures.
+ */
+
+#define	EHCI_MAX_ROOT_PORTS	15		/* see HCS_N_PORTS */
+
+struct ehci_hcd {			/* one per controller */
+	spinlock_t		lock;
+
+	/* async schedule support */
+	struct ehci_qh		*async;
+	struct ehci_qh		*reclaim;
+	int			reclaim_ready;
+
+	/* periodic schedule support */
+#define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
+	unsigned		periodic_size;
+	u32			*periodic;	/* hw periodic table */
+	dma_addr_t		periodic_dma;
+	unsigned		i_thresh;	/* uframes HC might cache */
+
+	union ehci_shadow	*pshadow;	/* mirror hw periodic table */
+	int			next_uframe;	/* scan periodic, start here */
+	unsigned		periodic_urbs;	/* how many urbs scheduled? */
+
+	/* deferred work from IRQ, etc */
+	struct tasklet_struct	tasklet;
+
+	/* per root hub port */
+	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
+
+	/* glue to PCI and HCD framework */
+	struct usb_hcd		hcd;
+	struct ehci_caps	*caps;
+	struct ehci_regs	*regs;
+	u32			hcs_params;	/* cached register copy */
+
+	/* per-HC memory pools (could be per-PCI-bus, but ...) */
+	struct pci_pool		*qh_pool;	/* qh per active urb */
+	struct pci_pool		*qtd_pool;	/* one or more per qh */
+	struct pci_pool		*itd_pool;	/* itd per iso urb */
+	struct pci_pool		*sitd_pool;	/* sitd per split iso urb */
+};
+
+/* unwrap an HCD pointer to get an EHCI_HCD pointer */ 
+#define hcd_to_ehci(hcd_ptr) list_entry(hcd_ptr, struct ehci_hcd, hcd)
+
+/* NOTE:  urb->transfer_flags expected to not use this bit !!! */
+#define EHCI_STATE_UNLINK	0x8000		/* urb being unlinked */
+
+/*-------------------------------------------------------------------------*/
+
+/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
+
+/* Section 2.2 Host Controller Capability Registers */
+struct ehci_caps {
+	u8		length;		/* CAPLENGTH - size of this struct */
+	u8		reserved;       /* offset 0x1 */
+	u16		hci_version;    /* HCIVERSION - offset 0x2 */
+	u32		hcs_params;     /* HCSPARAMS - offset 0x4 */
+#define HCS_DEBUG_PORT(p)	(((p)>>20)&0xf)	/* bits 23:20, debug port? */
+#define HCS_INDICATOR(p)	((p)&(1 << 16))	/* true: has port indicators */
+#define HCS_N_CC(p)		(((p)>>12)&0xf)	/* bits 15:12, #companion HCs */
+#define HCS_N_PCC(p)		(((p)>>8)&0xf)	/* bits 11:8, ports per CC */
+#define HCS_PORTROUTED(p)	((p)&(1 << 7))	/* true: port routing */ 
+#define HCS_PPC(p)		((p)&(1 << 4))	/* true: port power control */ 
+#define HCS_N_PORTS(p)		(((p)>>0)&0xf)	/* bits 3:0, ports on HC */
+
+	u32		hcc_params;      /* HCCPARAMS - offset 0x8 */
+#define HCC_EXT_CAPS(p)		(((p)>>8)&0xff)	/* for pci extended caps */
+#define HCC_ISOC_CACHE(p)       ((p)&(1 << 7))  /* true: can cache isoc frame */
+#define HCC_ISOC_THRES(p)       (((p)>>4)&0x7)  /* bits 6:4, uframes cached */
+#define HCC_CANPARK(p)		((p)&(1 << 2))  /* true: can park on async qh */
+#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1))  /* true: periodic_size changes*/
+#define HCC_64BIT_ADDR(p)       ((p)&(1))       /* true: can use 64-bit addr */
+	u8		portroute [8];	 /* nibbles for routing - offset 0xC */
+} __attribute__ ((packed));
+
+
+/* Section 2.3 Host Controller Operational Registers */
+struct ehci_regs {
+
+	/* USBCMD: offset 0x00 */
+	u32		command;
+/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
+#define CMD_PARK	(1<<11)		/* enable "park" on async qh */
+#define CMD_PARK_CNT(c)	(((c)>>8)&3)	/* how many transfers to park for */
+#define CMD_LRESET	(1<<7)		/* partial reset (no ports, etc) */
+#define CMD_IAAD	(1<<6)		/* "doorbell" interrupt async advance */
+#define CMD_ASE		(1<<5)		/* async schedule enable */
+#define CMD_PSE  	(1<<4)		/* periodic schedule enable */
+/* 3:2 is periodic frame list size */
+#define CMD_RESET	(1<<1)		/* reset HC not bus */
+#define CMD_RUN		(1<<0)		/* start/stop HC */
+
+	/* USBSTS: offset 0x04 */
+	u32		status;
+#define STS_ASS		(1<<15)		/* Async Schedule Status */
+#define STS_PSS		(1<<14)		/* Periodic Schedule Status */
+#define STS_RECL	(1<<13)		/* Reclamation */
+#define STS_HALT	(1<<12)		/* Not running (any reason) */
+/* some bits reserved */
+	/* these STS_* flags are also intr_enable bits (USBINTR) */
+#define STS_IAA		(1<<5)		/* Interrupted on async advance */
+#define STS_FATAL	(1<<4)		/* such as some PCI access errors */
+#define STS_FLR		(1<<3)		/* frame list rolled over */
+#define STS_PCD		(1<<2)		/* port change detect */
+#define STS_ERR		(1<<1)		/* "error" completion (overflow, ...) */
+#define STS_INT		(1<<0)		/* "normal" completion (short, ...) */
+
+	/* USBINTR: offset 0x08 */
+	u32		intr_enable;
+
+	/* FRINDEX: offset 0x0C */
+	u32		frame_index;	/* current microframe number */
+	/* CTRLDSSEGMENT: offset 0x10 */
+	u32		segment; 	/* address bits 63:32 if needed */
+	/* PERIODICLISTBASE: offset 0x14 */
+	u32		frame_list; 	/* points to periodic list */
+	/* ASYNCICLISTADDR: offset 0x18 */
+	u32		async_next;	/* address of next async queue head */
+
+	u32		reserved [9];
+
+	/* CONFIGFLAG: offset 0x40 */
+	u32		configured_flag;
+#define FLAG_CF		(1<<0)		/* true: we'll support "high speed" */
+
+	/* PORTSC: offset 0x44 */
+	u32		port_status [0];	/* up to N_PORTS */
+/* 31:23 reserved */
+#define PORT_WKOC_E	(1<<22)		/* wake on overcurrent (enable) */
+#define PORT_WKDISC_E	(1<<21)		/* wake on disconnect (enable) */
+#define PORT_WKCONN_E	(1<<20)		/* wake on connect (enable) */
+/* 19:16 for port testing */
+/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */
+#define PORT_OWNER	(1<<13)		/* true: companion hc owns this port */
+#define PORT_POWER	(1<<12)		/* true: has power (see PPC) */
+#define PORT_USB11(x) (((x)&(3<<10))==(1<<10))	/* USB 1.1 device */
+/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
+/* 9 reserved */
+#define PORT_RESET	(1<<8)		/* reset port */
+#define PORT_SUSPEND	(1<<7)		/* suspend port */
+#define PORT_RESUME	(1<<6)		/* resume it */
+#define PORT_OCC	(1<<5)		/* over current change */
+#define PORT_OC		(1<<4)		/* over current active */
+#define PORT_PEC	(1<<3)		/* port enable change */
+#define PORT_PE		(1<<2)		/* port enable */
+#define PORT_CSC	(1<<1)		/* connect status change */
+#define PORT_CONNECT	(1<<0)		/* device connected */
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+#define	QTD_NEXT(dma)	cpu_to_le32((u32)dma)
+
+/*
+ * EHCI Specification 0.95 Section 3.5
+ * QTD: describe data transfer components (buffer, direction, ...) 
+ * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
+ *
+ * These are associated only with "QH" (Queue Head) structures,
+ * used with control, bulk, and interrupt transfers.
+ */
+struct ehci_qtd {
+	/* first part defined by EHCI spec */
+	u32			hw_next;	  /* see EHCI 3.5.1 */
+	u32			hw_alt_next;      /* see EHCI 3.5.2 */
+	u32			hw_token;         /* see EHCI 3.5.3 */       
+#define	QTD_TOGGLE	(1 << 31)	/* data toggle */
+#define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
+#define	QTD_IOC		(1 << 15)	/* interrupt on complete */
+#define	QTD_CERR(tok)	(((tok)>>10) & 0x3)
+#define	QTD_PID(tok)	(((tok)>>8) & 0x3)
+#define	QTD_STS_ACTIVE	(1 << 7)	/* HC may execute this */
+#define	QTD_STS_HALT	(1 << 6)	/* halted on error */
+#define	QTD_STS_DBE	(1 << 5)	/* data buffer error (in HC) */
+#define	QTD_STS_BABBLE	(1 << 4)	/* device was babbling (qtd halted) */
+#define	QTD_STS_XACT	(1 << 3)	/* device gave illegal response */
+#define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
+#define	QTD_STS_STS	(1 << 1)	/* split transaction state */
+#define	QTD_STS_PING	(1 << 0)	/* issue PING? */
+	u32			hw_buf [5];        /* see EHCI 3.5.4 */
+	u32			hw_buf_hi [5];        /* Appendix B */
+
+	/* the rest is HCD-private */
+	dma_addr_t		qtd_dma;		/* qtd address */
+	struct list_head	qtd_list;		/* sw qtd list */
+
+	/* dma same in urb's qtds, except 1st control qtd (setup buffer) */
+	struct urb		*urb;			/* qtd's urb */
+	dma_addr_t		buf_dma;		/* buffer address */
+	size_t			length;			/* length of buffer */
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/* type tag from {qh,itd,sitd,fstn}->hw_next */
+#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+
+/* values for that type tag */
+#define Q_TYPE_ITD	__constant_cpu_to_le32 (0 << 1)
+#define Q_TYPE_QH	__constant_cpu_to_le32 (1 << 1)
+#define Q_TYPE_SITD 	__constant_cpu_to_le32 (2 << 1)
+#define Q_TYPE_FSTN 	__constant_cpu_to_le32 (3 << 1)
+
+/* next async queue entry, or pointer to interrupt/periodic QH */
+#define	QH_NEXT(dma)	(cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
+
+/* for periodic/async schedules and qtd lists, mark end of list */
+#define	EHCI_LIST_END	__constant_cpu_to_le32(1) /* "null pointer" to hw */
+
+/*
+ * Entries in periodic shadow table are pointers to one of four kinds
+ * of data structure.  That's dictated by the hardware; a type tag is
+ * encoded in the low bits of the hardware's periodic schedule.  Use
+ * Q_NEXT_TYPE to get the tag.
+ *
+ * For entries in the async schedule, the type tag always says "qh".
+ */
+union ehci_shadow {
+	struct ehci_qh 		*qh;		/* Q_TYPE_QH */
+	struct ehci_itd		*itd;		/* Q_TYPE_ITD */
+	struct ehci_sitd	*sitd;		/* Q_TYPE_SITD */
+	struct ehci_fstn	*fstn;		/* Q_TYPE_FSTN */
+	void			*ptr;
+};
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.6
+ * QH: describes control/bulk/interrupt endpoints
+ * See Fig 3-7 "Queue Head Structure Layout".
+ *
+ * These appear in both the async and (for interrupt) periodic schedules.
+ */
+
+struct ehci_qh {
+	/* first part defined by EHCI spec */
+	u32			hw_next;	 /* see EHCI 3.6.1 */
+	u32			hw_info1;        /* see EHCI 3.6.2 */
+#define	QH_HEAD		0x00008000
+	u32			hw_info2;        /* see EHCI 3.6.2 */
+	u32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
+	
+	/* qtd overlay (hardware parts of a struct ehci_qtd) */
+	u32			hw_qtd_next;
+	u32			hw_alt_next;
+	u32			hw_token;
+	u32			hw_buf [5];
+	u32			hw_buf_hi [5];
+
+	/* the rest is HCD-private */
+	dma_addr_t		qh_dma;		/* address of qh */
+	union ehci_shadow	qh_next;	/* ptr to qh; or periodic */
+	struct list_head	qtd_list;	/* sw qtd list */
+
+	atomic_t		refcount;
+	unsigned short		usecs;		/* intr bandwidth */
+	short			qh_state;
+#define	QH_STATE_LINKED		1		/* HC sees this */
+#define	QH_STATE_UNLINK		2		/* HC may still see this */
+#define	QH_STATE_IDLE		3		/* HC doesn't see this */
+
+#ifdef EHCI_SOFT_RETRIES
+	int			retries;
+#endif
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.3
+ * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
+ *
+ * Schedule records for high speed iso xfers
+ */
+struct ehci_itd {
+	/* first part defined by EHCI spec */
+	u32			hw_next;           /* see EHCI 3.3.1 */
+	u32			hw_transaction [8]; /* see EHCI 3.3.2 */
+#define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
+#define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
+#define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
+#define EHCI_ISOC_XACTERR       (1<<28)        /* XactErr - transaction error */
+#define	EHCI_ITD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
+#define	EHCI_ITD_IOC		(1 << 15)	/* interrupt on complete */
+
+	u32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
+	u32			hw_bufp_hi [7];	/* Appendix B */
+
+	/* the rest is HCD-private */
+	dma_addr_t		itd_dma;	/* for this itd */
+	union ehci_shadow	itd_next;	/* ptr to periodic q entry */
+
+	struct urb		*urb;
+	struct list_head	itd_list;	/* list of urb frames' itds */
+	dma_addr_t		buf_dma;	/* frame's buffer address */
+
+	/* for now, only one hw_transaction per itd */
+	u32			transaction;
+	u16			index;		/* in urb->iso_frame_desc */
+	u16			uframe;		/* in periodic schedule */
+	u16			usecs;
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.95 Section 3.4 
+ * siTD, aka split-transaction isochronous Transfer Descriptor
+ *       ... describe low/full speed iso xfers through TT in hubs
+ * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
+ */
+struct ehci_sitd {
+	/* first part defined by EHCI spec */
+	u32			hw_next;
+/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
+	u32			hw_fullspeed_ep;  /* see EHCI table 3-9 */
+	u32                     hw_uframe;        /* see EHCI table 3-10 */
+        u32                     hw_tx_results1;   /* see EHCI table 3-11 */
+	u32                     hw_tx_results2;   /* see EHCI table 3-12 */
+	u32                     hw_tx_results3;   /* see EHCI table 3-12 */
+        u32                     hw_backpointer;   /* see EHCI table 3-13 */
+	u32			hw_buf_hi [2];	  /* Appendix B */
+
+	/* the rest is HCD-private */
+	dma_addr_t		sitd_dma;
+	union ehci_shadow	sitd_next;	/* ptr to periodic q entry */
+	struct urb		*urb;
+	dma_addr_t		buf_dma;	/* buffer address */
+} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * EHCI Specification 0.96 Section 3.7
+ * Periodic Frame Span Traversal Node (FSTN)
+ *
+ * Manages split interrupt transactions (using TT) that span frame boundaries
+ * into uframes 0/1; see 4.12.2.2.  In those uframes, a "save place" FSTN
+ * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
+ * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
+ */
+struct ehci_fstn {
+	u32			hw_next;	/* any periodic q entry */
+	u32			hw_prev;	/* qh or EHCI_LIST_END */
+
+	/* the rest is HCD-private */
+	dma_addr_t		fstn_dma;
+	union ehci_shadow	fstn_next;	/* ptr to periodic q entry */
+} __attribute__ ((aligned (32)));
+
+#endif /* __LINUX_EHCI_HCD_H */
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci-dbg.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,246 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ * 
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * This file is licenced under the GPL.
+ * $Id: ohci-dbg.c,v 1.4 2002/03/27 20:40:40 dbrownell Exp $
+ */
+ 
+/*-------------------------------------------------------------------------*/
+ 
+#ifdef DEBUG
+
+#define pipestring(pipe) ({ char *temp; \
+	switch (usb_pipetype (pipe)) { \
+	case PIPE_CONTROL:	temp = "CTRL"; break; \
+	case PIPE_BULK:		temp = "BULK"; break; \
+	case PIPE_INTERRUPT:	temp = "INTR"; break; \
+	default: 		temp = "ISOC"; break; \
+	}; temp;})
+
+/* debug| print the main components of an URB     
+ * small: 0) header + data packets 1) just header
+ */
+static void urb_print (struct urb * urb, char * str, int small)
+{
+	unsigned int pipe= urb->pipe;
+	
+	if (!urb->dev || !urb->dev->bus) {
+		dbg("%s URB: no dev", str);
+		return;
+	}
+	
+#ifndef	OHCI_VERBOSE_DEBUG
+	if (urb->status != 0)
+#endif
+	dbg("%s:[%4x] dev:%d,ep=%d-%c,%s,flags:%4x,len:%d/%d,stat:%d", 
+		    str,
+		    usb_get_current_frame_number (urb->dev), 
+		    usb_pipedevice (pipe),
+		    usb_pipeendpoint (pipe), 
+		    usb_pipeout (pipe)? 'O': 'I',
+		    pipestring (pipe),
+		    urb->transfer_flags, 
+		    urb->actual_length, 
+		    urb->transfer_buffer_length,
+		    urb->status);
+
+#ifdef	OHCI_VERBOSE_DEBUG
+	if (!small) {
+		int i, len;
+
+		if (usb_pipecontrol (pipe)) {
+			printk (KERN_DEBUG __FILE__ ": setup(8):");
+			for (i = 0; i < 8 ; i++) 
+				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
+			printk ("\n");
+		}
+		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
+			printk (KERN_DEBUG __FILE__ ": data(%d/%d):", 
+				urb->actual_length, 
+				urb->transfer_buffer_length);
+			len = usb_pipeout (pipe)? 
+						urb->transfer_buffer_length: urb->actual_length;
+			for (i = 0; i < 16 && i < len; i++) 
+				printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
+			printk ("%s stat:%d\n", i < len? "...": "", urb->status);
+		}
+	} 
+#endif
+}
+
+static inline struct ed *
+dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma);
+
+#ifdef OHCI_VERBOSE_DEBUG
+/* print non-empty branches of the periodic ed tree */
+void ohci_dump_periodic (struct ohci_hcd *ohci, char *label)
+{
+	int i, j;
+	u32 *ed_p;
+	int printed = 0;
+
+	for (i= 0; i < 32; i++) {
+		j = 5;
+		ed_p = &(ohci->hcca->int_table [i]);
+		if (*ed_p == 0)
+			continue;
+		printed = 1;
+		printk (KERN_DEBUG "%s, ohci %s frame %2d:",
+				label, ohci->hcd.bus_name, i);
+		while (*ed_p != 0 && j--) {
+			struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
+			printk (" %p/%08x;", ed, ed->hwINFO);
+			ed_p = &ed->hwNextED;
+		}
+		printk ("\n");
+	}
+	if (!printed)
+		printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n",
+				label, ohci->hcd.bus_name);
+}
+#endif
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+	dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+		label,
+		mask,
+		(mask & OHCI_INTR_MIE) ? " MIE" : "",
+		(mask & OHCI_INTR_OC) ? " OC" : "",
+		(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+		(mask & OHCI_INTR_FNO) ? " FNO" : "",
+		(mask & OHCI_INTR_UE) ? " UE" : "",
+		(mask & OHCI_INTR_RD) ? " RD" : "",
+		(mask & OHCI_INTR_SF) ? " SF" : "",
+		(mask & OHCI_INTR_WDH) ? " WDH" : "",
+		(mask & OHCI_INTR_SO) ? " SO" : ""
+		);
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+	if (value)
+		dbg ("%s %08x", label, value);
+}
+
+static char *hcfs2string (int state)
+{
+	switch (state) {
+		case OHCI_USB_RESET:	return "reset";
+		case OHCI_USB_RESUME:	return "resume";
+		case OHCI_USB_OPER:	return "operational";
+		case OHCI_USB_SUSPEND:	return "suspend";
+	}
+	return "?";
+}
+
+// dump control and status registers
+static void ohci_dump_status (struct ohci_hcd *controller)
+{
+	struct ohci_regs	*regs = controller->regs;
+	__u32			temp;
+
+	temp = readl (&regs->revision) & 0xff;
+	dbg ("OHCI %d.%d, %s legacy support registers",
+		0x03 & (temp >> 4), (temp & 0x0f),
+		(temp & 0x10) ? "with" : "NO");
+
+	temp = readl (&regs->control);
+	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
+		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
+		(temp & OHCI_CTRL_IR) ? " IR" : "",
+		hcfs2string (temp & OHCI_CTRL_HCFS),
+		(temp & OHCI_CTRL_BLE) ? " BLE" : "",
+		(temp & OHCI_CTRL_CLE) ? " CLE" : "",
+		(temp & OHCI_CTRL_IE) ? " IE" : "",
+		(temp & OHCI_CTRL_PLE) ? " PLE" : "",
+		temp & OHCI_CTRL_CBSR
+		);
+
+	temp = readl (&regs->cmdstatus);
+	dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+		(temp & OHCI_SOC) >> 16,
+		(temp & OHCI_OCR) ? " OCR" : "",
+		(temp & OHCI_BLF) ? " BLF" : "",
+		(temp & OHCI_CLF) ? " CLF" : "",
+		(temp & OHCI_HCR) ? " HCR" : ""
+		);
+
+	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+	// intrdisable always same as intrenable
+	// ohci_dump_intr_mask ("intrdisable", readl (&regs->intrdisable));
+
+	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+	maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
+{
+	__u32			temp, ndp, i;
+
+	temp = roothub_a (controller);
+	ndp = (temp & RH_A_NDP);
+
+	if (verbose) {
+		dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+			((temp & RH_A_POTPGT) >> 24) & 0xff,
+			(temp & RH_A_NOCP) ? " NOCP" : "",
+			(temp & RH_A_OCPM) ? " OCPM" : "",
+			(temp & RH_A_DT) ? " DT" : "",
+			(temp & RH_A_NPS) ? " NPS" : "",
+			(temp & RH_A_PSM) ? " PSM" : "",
+			ndp
+			);
+		temp = roothub_b (controller);
+		dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+			temp,
+			(temp & RH_B_PPCM) >> 16,
+			(temp & RH_B_DR)
+			);
+		temp = roothub_status (controller);
+		dbg ("roothub.status: %08x%s%s%s%s%s%s",
+			temp,
+			(temp & RH_HS_CRWE) ? " CRWE" : "",
+			(temp & RH_HS_OCIC) ? " OCIC" : "",
+			(temp & RH_HS_LPSC) ? " LPSC" : "",
+			(temp & RH_HS_DRWE) ? " DRWE" : "",
+			(temp & RH_HS_OCI) ? " OCI" : "",
+			(temp & RH_HS_LPS) ? " LPS" : ""
+			);
+	}
+	
+	for (i = 0; i < ndp; i++) {
+		temp = roothub_portstatus (controller, i);
+		dbg_port (controller, "", i, temp);
+	}
+}
+
+static void ohci_dump (struct ohci_hcd *controller, int verbose)
+{
+	dbg ("OHCI controller %s state", controller->hcd.bus_name);
+
+	// dumps some of the state we know about
+	ohci_dump_status (controller);
+#ifdef OHCI_VERBOSE_DEBUG
+	if (verbose)
+		ohci_dump_periodic (controller, "hcca");
+#endif
+	dbg ("hcca frame #%04x", controller->hcca->frame_no);
+	ohci_dump_roothub (controller, 1);
+}
+
+
+#endif
+
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci-hcd.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,961 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * [ Initialisation is based on Linus'  ]
+ * [ uhci code and gregs ohci fragments ]
+ * [ (C) Copyright 1999 Linus Torvalds  ]
+ * [ (C) Copyright 1999 Gregory P. Smith]
+ * 
+ * 
+ * History:
+ * 
+ * 2002/01/18 package as a patch for 2.5.3; this should match the
+ *	2.4.17 kernel modulo some bugs being fixed.
+ *
+ * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes
+ *	from post-2.4.5 patches.
+ * 2001/09/20 USB_ZERO_PACKET support; hcca_dma portability, OPTi warning
+ * 2001/09/07 match PCI PM changes, errnos from Linus' tree
+ * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify;
+ *	pbook pci quirks gone (please fix pbook pci sw!) (db)
+ *
+ * 2001/04/08 Identify version on module load (gb)
+ * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
+ 	pci_map_single (db)
+ * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
+ * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
+ *
+ * 2000/09/26 fixed races in removing the private portion of the urb
+ * 2000/09/07 disable bulk and control lists when unlinking the last
+ *	endpoint descriptor in order to avoid unrecoverable errors on
+ *	the Lucent chips. (rwc@sgi)
+ * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
+ *	urb unlink probs, indentation fixes
+ * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
+ *	device unplugs.
+ * 2000/06/28 use PCI hotplug framework, for better power management
+ *	and for Cardbus support (David Brownell)
+ * 2000/earlier:  fixes for NEC/Lucent chips; suspend/resume handling
+ *	when the controller loses power; handle UE; cleanup; ...
+ *
+ * v5.2 1999/12/07 URB 3rd preview, 
+ * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
+ * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume 
+ * 	i386: HUB, Keyboard, Mouse, Printer 
+ *
+ * v4.3 1999/10/27 multiple HCs, bulk_request
+ * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
+ * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
+ * v4.0 1999/08/18 
+ * v3.0 1999/06/25 
+ * v2.1 1999/05/09  code clean up
+ * v2.0 1999/05/04 
+ * v1.0 1999/04/27 initial release
+ *
+ * This file is licenced under the GPL.
+ * $Id: ohci-hcd.c,v 1.9 2002/03/27 20:41:57 dbrownell Exp $
+ */
+ 
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>  /* for in_interrupt () */
+
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+
+#include <linux/usb.h>
+#include "../core/hcd.h"
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_PMAC_PBOOK
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/pci-bridge.h>
+#ifndef CONFIG_PM
+#	define CONFIG_PM
+#endif
+#endif
+
+/*
+ * TO DO:
+ *
+ *	- "disabled" should be the hcd state
+ *	- bandwidth alloc to generic code
+ *	- lots more testing!!
+ */
+
+#define DRIVER_VERSION "$Revision: 1.9 $"
+#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
+#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
+
+/*-------------------------------------------------------------------------*/
+
+#define OHCI_USE_NPS		// force NoPowerSwitching mode
+// #define OHCI_VERBOSE_DEBUG	/* not always helpful */
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define	OHCI_CONTROL_INIT \
+	 (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define OHCI_UNLINK_TIMEOUT	 (HZ / 10)
+
+/*-------------------------------------------------------------------------*/
+
+#include "ohci.h"
+
+#include "ohci-hub.c"
+#include "ohci-dbg.c"
+#include "ohci-mem.c"
+#include "ohci-q.c"
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * queue up an urb for anything except the root hub
+ */
+static int ohci_urb_enqueue (
+	struct usb_hcd	*hcd,
+	struct urb	*urb,
+	int		mem_flags
+) {
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	struct ed	*ed;
+	urb_priv_t	*urb_priv;
+	unsigned int	pipe = urb->pipe;
+	int		i, size = 0;
+	unsigned long	flags;
+	int		bustime = 0;
+	
+#ifdef OHCI_VERBOSE_DEBUG
+	urb_print (urb, "SUB", usb_pipein (pipe));
+#endif
+	
+	/* every endpoint has a ed, locate and fill it */
+	if (! (ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags)))
+		return -ENOMEM;
+
+	/* for the private part of the URB we need the number of TDs (size) */
+	switch (usb_pipetype (pipe)) {
+		case PIPE_CONTROL:
+			/* 1 TD for setup, 1 for ACK, plus ... */
+			size = 2;
+			/* FALLTHROUGH */
+		case PIPE_BULK:
+			/* one TD for every 4096 Bytes (can be upto 8K) */
+			size += urb->transfer_buffer_length / 4096;
+			/* ... and for any remaining bytes ... */
+			if ((urb->transfer_buffer_length % 4096) != 0)
+				size++;
+			/* ... and maybe a zero length packet to wrap it up */
+			if (size == 0)
+				size++;
+			else if ((urb->transfer_flags & USB_ZERO_PACKET) != 0
+				&& (urb->transfer_buffer_length
+					% usb_maxpacket (urb->dev, pipe,
+						usb_pipeout (pipe))) != 0)
+				size++;
+			break;
+		case PIPE_ISOCHRONOUS: /* number of packets from URB */
+			size = urb->number_of_packets;
+			if (size <= 0)
+				return -EINVAL;
+			for (i = 0; i < urb->number_of_packets; i++) {
+  				urb->iso_frame_desc [i].actual_length = 0;
+  				urb->iso_frame_desc [i].status = -EXDEV;
+  			}
+			break;
+		case PIPE_INTERRUPT: /* one TD */
+			size = 1;
+			break;
+	}
+
+	/* allocate the private part of the URB */
+	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *),
+			mem_flags);
+	if (!urb_priv)
+		return -ENOMEM;
+	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
+	
+	/* fill the private part of the URB */
+	urb_priv->length = size;
+	urb_priv->ed = ed;	
+
+	/* allocate the TDs (updating hash chains) */
+	spin_lock_irqsave (&ohci->lock, flags);
+	for (i = 0; i < size; i++) { 
+		urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC);
+		if (!urb_priv->td [i]) {
+			urb_priv->length = i;
+			urb_free_priv (ohci, urb_priv);
+			spin_unlock_irqrestore (&ohci->lock, flags);
+			return -ENOMEM;
+		}
+	}	
+
+// FIXME:  much of this switch should be generic, move to hcd code ...
+
+	/* allocate and claim bandwidth if needed; ISO
+	 * needs start frame index if it was't provided.
+	 */
+	switch (usb_pipetype (pipe)) {
+		case PIPE_ISOCHRONOUS:
+			if (urb->transfer_flags & USB_ISO_ASAP) { 
+				urb->start_frame = ( (ed->state == ED_OPER)
+					? (ed->last_iso + 1)
+					: (le16_to_cpu (ohci->hcca->frame_no)
+						+ 10)) & 0xffff;
+			}	
+			/* FALLTHROUGH */
+		case PIPE_INTERRUPT:
+			if (urb->bandwidth == 0) {
+				bustime = usb_check_bandwidth (urb->dev, urb);
+			}
+			if (bustime < 0) {
+				urb_free_priv (ohci, urb_priv);
+				spin_unlock_irqrestore (&ohci->lock, flags);
+				return bustime;
+			}
+			usb_claim_bandwidth (urb->dev, urb,
+				bustime, usb_pipeisoc (urb->pipe));
+	}
+
+	urb->hcpriv = urb_priv;
+
+	/* link the ed into a chain if is not already */
+	if (ed->state != ED_OPER)
+		ep_link (ohci, ed);
+
+	/* fill the TDs and link them to the ed; and
+	 * enable that part of the schedule, if needed
+	 */
+	td_submit_urb (urb);
+
+	spin_unlock_irqrestore (&ohci->lock, flags);
+
+	return 0;	
+}
+
+/*
+ * decouple the URB from the HC queues (TDs, urb_priv); it's
+ * already marked for deletion.  reporting is always done
+ * asynchronously, and we might be dealing with an urb that's
+ * almost completed anyway...
+ */
+static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	unsigned long		flags;
+	
+#ifdef DEBUG
+	urb_print (urb, "UNLINK", 1);
+#endif		  
+
+	if (!ohci->disabled) {
+		urb_priv_t  *urb_priv;
+
+		/* flag the urb's data for deletion in some upcoming
+		 * SF interrupt's delete list processing
+		 */
+		spin_lock_irqsave (&ohci->lock, flags);
+		urb_priv = urb->hcpriv;
+
+		if (!urb_priv || (urb_priv->state == URB_DEL)) {
+			spin_unlock_irqrestore (&ohci->lock, flags);
+			return 0;
+		}
+			
+		urb_priv->state = URB_DEL; 
+		ed_unlink (urb->dev, urb_priv->ed);
+		spin_unlock_irqrestore (&ohci->lock, flags);
+	} else {
+		/*
+		 * with HC dead, we won't respect hc queue pointers
+		 * any more ... just clean up every urb's memory.
+		 */
+		finish_urb (ohci, urb);
+	}	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	struct hcd_dev		*dev = (struct hcd_dev *) udev->hcpriv;
+	int			i;
+	unsigned long		flags;
+
+	/* free any eds, and dummy tds, still hanging around */
+	spin_lock_irqsave (&ohci->lock, flags);
+	for (i = 0; i < 32; i++) {
+		struct ed	*ed = dev->ep [i];
+		struct td	*tdTailP;
+
+		if (!ed)
+			continue;
+
+		ed->state &= ~ED_URB_DEL;
+		if (ohci->disabled && ed->state == ED_OPER)
+			ed->state = ED_UNLINK;
+		switch (ed->state) {
+		case ED_NEW:
+			break;
+		case ED_UNLINK:
+			tdTailP = dma_to_td (ohci,
+				le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
+			td_free (ohci, tdTailP); /* free dummy td */
+			hash_free_ed (ohci, ed);
+			break;
+
+		case ED_OPER:
+		default:
+			err ("illegal ED %d state in free_config, %d",
+				i, ed->state);
+#ifdef DEBUG
+			BUG ();
+#endif
+		}
+		ed_free (ohci, ed);
+	}
+	spin_unlock_irqrestore (&ohci->lock, flags);
+}
+
+static int ohci_get_frame (struct usb_hcd *hcd)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+
+	return le16_to_cpu (ohci->hcca->frame_no);
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (struct ohci_hcd *ohci)
+{
+	int timeout = 30;
+	int smm_timeout = 50; /* 0,5 sec */
+	 	
+	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+		writel (OHCI_INTR_OC, &ohci->regs->intrenable);
+		writel (OHCI_OCR, &ohci->regs->cmdstatus);
+		dbg ("USB HC TakeOver from SMM");
+		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+			wait_ms (10);
+			if (--smm_timeout == 0) {
+				err ("USB HC TakeOver failed!");
+				return -1;
+			}
+		}
+	}	
+		
+	/* Disable HC interrupts */
+	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+	dbg ("USB HC reset_hc %s: ctrl = 0x%x ;",
+		ohci->hcd.bus_name,
+		readl (&ohci->regs->control));
+
+  	/* Reset USB (needed by some controllers) */
+	writel (0, &ohci->regs->control);
+      	
+	/* HC Reset requires max 10 ms delay */
+	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
+	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+		if (--timeout == 0) {
+			err ("USB HC reset timed out!");
+			return -1;
+		}	
+		udelay (1);
+	}	 
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts 
+ * connect the virtual root hub
+ */
+static int hc_start (struct ohci_hcd *ohci)
+{
+  	__u32			mask;
+  	unsigned int		fminterval;
+  	struct usb_device	*udev;
+	
+	spin_lock_init (&ohci->lock);
+	ohci->disabled = 1;
+	ohci->sleeping = 0;
+
+	/* Tell the controller where the control and bulk lists are
+	 * The lists are empty now. */
+	 
+	writel (0, &ohci->regs->ed_controlhead);
+	writel (0, &ohci->regs->ed_bulkhead);
+	
+	/* a reset clears this */
+	writel ((u32) ohci->hcca_dma, &ohci->regs->hcca);
+   
+  	fminterval = 0x2edf;
+	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+	fminterval |= ((((fminterval - 210) * 6) / 7) << 16); 
+	writel (fminterval, &ohci->regs->fminterval);	
+	writel (0x628, &ohci->regs->lsthresh);
+
+ 	/* start controller operations */
+ 	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+	ohci->disabled = 0;
+ 	writel (ohci->hc_control, &ohci->regs->control);
+ 
+	/* Choose the interrupts we care about now, others later on demand */
+	mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH;
+	writel (mask, &ohci->regs->intrstatus);
+	writel (mask, &ohci->regs->intrenable);
+
+#ifdef	OHCI_USE_NPS
+	/* required for AMD-756 and some Mac platforms */
+	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+		&ohci->regs->roothub.a);
+	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif	/* OHCI_USE_NPS */
+
+	// POTPGT delay is bits 24-31, in 2 ms units.
+	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+ 
+	/* connect the virtual root hub */
+	ohci->hcd.bus->root_hub = udev = usb_alloc_dev (NULL, ohci->hcd.bus);
+	ohci->hcd.state = USB_STATE_READY;
+	if (!udev) {
+	    ohci->disabled = 1;
+// FIXME cleanup
+	    return -ENOMEM;
+	}
+
+	usb_connect (udev);
+	udev->speed = USB_SPEED_FULL;
+	if (usb_register_root_hub (udev, &ohci->hcd.pdev->dev) != 0) {
+		usb_free_dev (udev); 
+		ohci->disabled = 1;
+// FIXME cleanup
+		return -ENODEV;
+	}
+	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static void ohci_irq (struct usb_hcd *hcd)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	struct ohci_regs	*regs = ohci->regs;
+ 	int			ints; 
+
+	if ((ohci->hcca->done_head != 0)
+			&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
+		ints =  OHCI_INTR_WDH;
+	} else if ((ints = (readl (&regs->intrstatus)
+			& readl (&regs->intrenable))) == 0) {
+		return;
+	} 
+
+	// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
+
+	if (ints & OHCI_INTR_UE) {
+		ohci->disabled++;
+		err ("OHCI Unrecoverable Error, %s disabled", hcd->bus_name);
+		// e.g. due to PCI Master/Target Abort
+
+#ifdef	DEBUG
+		ohci_dump (ohci, 1);
+#endif
+		hc_reset (ohci);
+	}
+  
+	if (ints & OHCI_INTR_WDH) {
+		writel (OHCI_INTR_WDH, &regs->intrdisable);	
+		dl_done_list (ohci, dl_reverse_done_list (ohci));
+		writel (OHCI_INTR_WDH, &regs->intrenable); 
+	}
+  
+	/* could track INTR_SO to reduce available PCI/... bandwidth */
+
+	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...
+	if (ints & OHCI_INTR_SF) { 
+		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
+		writel (OHCI_INTR_SF, &regs->intrdisable);	
+		if (ohci->ed_rm_list [!frame] != NULL) {
+			dl_del_list (ohci, !frame);
+		}
+		if (ohci->ed_rm_list [frame] != NULL)
+			writel (OHCI_INTR_SF, &regs->intrenable);	
+	}
+
+	writel (ints, &regs->intrstatus);
+	writel (OHCI_INTR_MIE, &regs->intrenable);	
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void ohci_stop (struct usb_hcd *hcd)
+{	
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+
+	dbg ("%s: stop %s controller%s",
+		hcd->bus_name,
+		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
+		ohci->disabled ? " (disabled)" : ""
+		);
+#ifdef	DEBUG
+	ohci_dump (ohci, 1);
+#endif
+
+	if (!ohci->disabled)
+		hc_reset (ohci);
+	
+	ohci_mem_cleanup (ohci);
+
+#ifdef CONFIG_PCI
+	pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca,
+		ohci->hcca, ohci->hcca_dma);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit
+ohci_start (struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	int		ret;
+
+#ifdef CONFIG_PCI
+	if (hcd->pdev) {
+		ohci->hcca = pci_alloc_consistent (hcd->pdev,
+				sizeof *ohci->hcca, &ohci->hcca_dma);
+		if (!ohci->hcca)
+			return -ENOMEM;
+
+		/* AMD 756, for most chips (early revs), corrupts register
+		 * values on read ... so enable the vendor workaround.
+		 */
+		if (hcd->pdev->vendor == 0x1022
+				&& hcd->pdev->device == 0x740c) {
+			ohci->flags = OHCI_QUIRK_AMD756;
+			info ("%s: AMD756 erratum 4 workaround",
+				hcd->bus_name);
+		}
+
+		/* Apple's OHCI driver has a lot of bizarre workarounds
+		 * for this chip.  Evidently control and bulk lists
+		 * can get confused.  (B&W G3 models, and ...)
+		 */
+		else if (hcd->pdev->vendor == 0x1045
+				&& hcd->pdev->device == 0xc861) {
+			info ("%s: WARNING: OPTi workarounds unavailable",
+				hcd->bus_name);
+		}
+	}
+#else
+#	error "where's hcca coming from?"
+#endif /* CONFIG_PCI */
+
+        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
+	if ((ret = ohci_mem_init (ohci)) < 0) {
+		ohci_stop (hcd);
+		return ret;
+	}
+	ohci->regs = hcd->regs;
+
+	if (hc_reset (ohci) < 0) {
+		ohci_stop (hcd);
+		return -ENODEV;
+	}
+
+	if (hc_start (ohci) < 0) {
+		err ("can't start %s", ohci->hcd.bus_name);
+		ohci_stop (hcd);
+		return -EBUSY;
+	}
+
+#ifdef	DEBUG
+	ohci_dump (ohci, 1);
+#endif
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+static int ohci_suspend (struct usb_hcd *hcd, u32 state)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	unsigned long		flags;
+	u16			cmd;
+
+	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
+		dbg ("can't suspend %s (state is %s)", hcd->bus_name,
+			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
+		return -EIO;
+	}
+
+	/* act as if usb suspend can always be used */
+	dbg ("%s: suspend to %d", hcd->bus_name, state);
+	ohci->sleeping = 1;
+
+	/* First stop processing */
+  	spin_lock_irqsave (&ohci->lock, flags);
+	ohci->hc_control &=
+		~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
+	writel (ohci->hc_control, &ohci->regs->control);
+	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
+	(void) readl (&ohci->regs->intrstatus);
+  	spin_unlock_irqrestore (&ohci->lock, flags);
+
+	/* Wait a frame or two */
+	mdelay (1);
+	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
+		mdelay (1);
+		
+ #ifdef CONFIG_PMAC_PBOOK
+	if (_machine == _MACH_Pmac)
+		disable_irq (hcd->pdev->irq);
+ 	/* else, 2.4 assumes shared irqs -- don't disable */
+ #endif
+
+	/* Enable remote wakeup */
+	writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
+		&ohci->regs->intrenable);
+
+	/* Suspend chip and let things settle down a bit */
+ 	ohci->hc_control = OHCI_USB_SUSPEND;
+ 	writel (ohci->hc_control, &ohci->regs->control);
+	(void) readl (&ohci->regs->control);
+	mdelay (500); /* No schedule here ! */
+
+	switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
+		case OHCI_USB_RESET:
+			dbg ("%s suspend->reset ?", hcd->bus_name);
+			break;
+		case OHCI_USB_RESUME:
+			dbg ("%s suspend->resume ?", hcd->bus_name);
+			break;
+		case OHCI_USB_OPER:
+			dbg ("%s suspend->operational ?", hcd->bus_name);
+			break;
+		case OHCI_USB_SUSPEND:
+			dbg ("%s suspended", hcd->bus_name);
+			break;
+	}
+
+	/* In some rare situations, Apple's OHCI have happily trashed
+	 * memory during sleep. We disable its bus master bit during
+	 * suspend
+	 */
+	pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
+	cmd &= ~PCI_COMMAND_MASTER;
+	pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
+#ifdef CONFIG_PMAC_PBOOK
+	{
+	   	struct device_node	*of_node;
+ 
+		/* Disable USB PAD & cell clock */
+		of_node = pci_device_to_OF_node (hcd->pdev);
+		if (of_node)
+			pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
+	}
+#endif
+	return 0;
+}
+
+
+// FIXME:  this restart logic should be generic,
+// and handle full hcd state cleanup
+
+/* controller died; cleanup debris, then restart */
+/* must not be called from interrupt context */
+
+static int hc_restart (struct ohci_hcd *ohci)
+{
+	int temp;
+	int i;
+
+	ohci->disabled = 1;
+	ohci->sleeping = 0;
+	if (ohci->hcd.bus->root_hub)
+		usb_disconnect (&ohci->hcd.bus->root_hub);
+	
+	/* empty the interrupt branches */
+	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0;
+	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
+	
+	/* no EDs to remove */
+	ohci->ed_rm_list [0] = NULL;
+	ohci->ed_rm_list [1] = NULL;
+
+	/* empty control and bulk lists */	 
+	ohci->ed_isotail     = NULL;
+	ohci->ed_controltail = NULL;
+	ohci->ed_bulktail    = NULL;
+
+	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
+		err ("can't restart %s, %d", ohci->hcd.bus_name, temp);
+		return temp;
+	} else
+		dbg ("restart %s completed", ohci->hcd.bus_name);
+	return 0;
+}
+
+static int ohci_resume (struct usb_hcd *hcd)
+{
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	int			temp;
+	int			retval = 0;
+	unsigned long		flags;
+
+#ifdef CONFIG_PMAC_PBOOK
+	{
+		struct device_node *of_node;
+
+		/* Re-enable USB PAD & cell clock */
+		of_node = pci_device_to_OF_node (hcd->pdev);
+		if (of_node)
+			pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
+	}
+#endif
+	/* did we suspend, or were we powered off? */
+	ohci->hc_control = readl (&ohci->regs->control);
+	temp = ohci->hc_control & OHCI_CTRL_HCFS;
+
+#ifdef DEBUG
+	/* the registers may look crazy here */
+	ohci_dump_status (ohci);
+#endif
+
+	/* Re-enable bus mastering */
+	pci_set_master (ohci->hcd.pdev);
+	
+	switch (temp) {
+
+	case OHCI_USB_RESET:	// lost power
+		info ("USB restart: %s", hcd->bus_name);
+		retval = hc_restart (ohci);
+		break;
+
+	case OHCI_USB_SUSPEND:	// host wakeup
+	case OHCI_USB_RESUME:	// remote wakeup
+		info ("USB continue: %s from %s wakeup", hcd->bus_name,
+			 (temp == OHCI_USB_SUSPEND)
+				? "host" : "remote");
+		ohci->hc_control = OHCI_USB_RESUME;
+		writel (ohci->hc_control, &ohci->regs->control);
+		(void) readl (&ohci->regs->control);
+		mdelay (20); /* no schedule here ! */
+		/* Some controllers (lucent) need a longer delay here */
+		mdelay (15);
+
+		temp = readl (&ohci->regs->control);
+		temp = ohci->hc_control & OHCI_CTRL_HCFS;
+		if (temp != OHCI_USB_RESUME) {
+			err ("controller %s won't resume", hcd->bus_name);
+			ohci->disabled = 1;
+			retval = -EIO;
+			break;
+		}
+
+		/* Some chips likes being resumed first */
+		writel (OHCI_USB_OPER, &ohci->regs->control);
+		(void) readl (&ohci->regs->control);
+		mdelay (3);
+
+		/* Then re-enable operations */
+		spin_lock_irqsave (&ohci->lock, flags);
+		ohci->disabled = 0;
+		ohci->sleeping = 0;
+		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+		if (!ohci->ed_rm_list [0] && !ohci->ed_rm_list [1]) {
+			if (ohci->ed_controltail)
+				ohci->hc_control |= OHCI_CTRL_CLE;
+			if (ohci->ed_bulktail)
+				ohci->hc_control |= OHCI_CTRL_BLE;
+		}
+		hcd->state = USB_STATE_READY;
+		writel (ohci->hc_control, &ohci->regs->control);
+
+		/* trigger a start-frame interrupt (why?) */
+		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
+		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
+
+		/* Check for a pending done list */
+		writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);	
+		(void) readl (&ohci->regs->intrdisable);
+		spin_unlock_irqrestore (&ohci->lock, flags);
+
+ #ifdef CONFIG_PMAC_PBOOK
+		if (_machine == _MACH_Pmac)
+			enable_irq (hcd->pdev->irq);
+ #endif
+		if (ohci->hcca->done_head)
+			dl_done_list (ohci, dl_reverse_done_list (ohci));
+		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
+
+		/* assume there are TDs on the bulk and control lists */
+		writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
+
+// ohci_dump_status (ohci);
+dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);
+		break;
+
+	default:
+		warn ("odd PCI resume for %s", hcd->bus_name);
+	}
+	return retval;
+}
+
+#endif	/* CONFIG_PM */
+
+
+/*-------------------------------------------------------------------------*/
+
+static const char	hcd_name [] = "ohci-hcd";
+
+static const struct hc_driver ohci_driver = {
+	description:		hcd_name,
+
+	/*
+	 * generic hardware linkage
+	 */
+	irq:			ohci_irq,
+	flags:			HCD_MEMORY | HCD_USB11,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	start:			ohci_start,
+#ifdef	CONFIG_PM
+	suspend:		ohci_suspend,
+	resume:			ohci_resume,
+#endif
+	stop:			ohci_stop,
+
+	/*
+	 * memory lifecycle (except per-request)
+	 */
+	hcd_alloc:		ohci_hcd_alloc,
+	hcd_free:		ohci_hcd_free,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	urb_enqueue:		ohci_urb_enqueue,
+	urb_dequeue:		ohci_urb_dequeue,
+	free_config:		ohci_free_config,
+
+	/*
+	 * scheduling support
+	 */
+	get_frame_number:	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	hub_status_data:	ohci_hub_status_data,
+	hub_control:		ohci_hub_control,
+};
+
+#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_INFO);
+MODULE_LICENSE ("GPL");
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PCI
+
+/* There do exist non-PCI implementations of OHCI ...
+ * Examples include the SA-1111 (ARM) and some MIPS
+ * and related hardware.
+ */
+
+static const struct pci_device_id __devinitdata pci_ids [] = { {
+
+	/* handle any USB OHCI controller */
+	class:		(PCI_CLASS_SERIAL_USB << 8) | 0x10,
+	class_mask:	~0,
+	driver_data:	(unsigned long) &ohci_driver,
+
+	/* no matter who makes it */
+	vendor:		PCI_ANY_ID,
+	device:		PCI_ANY_ID,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	}, { /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE (pci, pci_ids);
+
+/* pci driver glue; this is a "new style" PCI driver module */
+static struct pci_driver ohci_pci_driver = {
+	name:		(char *) hcd_name,
+	id_table:	pci_ids,
+
+	probe:		usb_hcd_pci_probe,
+	remove:		usb_hcd_pci_remove,
+
+#ifdef	CONFIG_PM
+	suspend:	usb_hcd_pci_suspend,
+	resume:		usb_hcd_pci_resume,
+#endif
+};
+
+ 
+static int __init ohci_hcd_init (void) 
+{
+	dbg (DRIVER_INFO);
+	dbg ("block sizes: ed %d td %d",
+		sizeof (struct ed), sizeof (struct td));
+	return pci_module_init (&ohci_pci_driver);
+}
+module_init (ohci_hcd_init);
+
+/*-------------------------------------------------------------------------*/
+
+static void __exit ohci_hcd_cleanup (void) 
+{	
+	pci_unregister_driver (&ohci_pci_driver);
+}
+module_exit (ohci_hcd_cleanup);
+
+#endif /* CONFIG_PCI */
+
diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci-hub.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,267 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ * 
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * This file is licenced under GPL
+ * $Id: ohci-hub.c,v 1.3 2002/03/22 16:04:54 dbrownell Exp $
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * OHCI Root Hub ... the nonsharable stuff
+ *
+ * Registers don't need cpu_to_le32, that happens transparently
+ */
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect.  AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define read_roothub(hc, register, mask) ({ \
+	u32 temp = readl (&hc->regs->roothub.register); \
+	if (hc->flags & OHCI_QUIRK_AMD756) \
+		while (temp & mask) \
+			temp = readl (&hc->regs->roothub.register); \
+	temp; })
+
+static u32 roothub_a (struct ohci_hcd *hc)
+	{ return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci_hcd *hc)
+	{ return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci_hcd *hc)
+	{ return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
+	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+/*-------------------------------------------------------------------------*/
+
+#define dbg_port(hc,label,num,value) \
+	dbg ("%s: %s roothub.portstatus [%d] " \
+		"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", \
+		hc->hcd.bus_name, label, num, temp, \
+		(temp & RH_PS_PRSC) ? " PRSC" : "", \
+		(temp & RH_PS_OCIC) ? " OCIC" : "", \
+		(temp & RH_PS_PSSC) ? " PSSC" : "", \
+		(temp & RH_PS_PESC) ? " PESC" : "", \
+		(temp & RH_PS_CSC) ? " CSC" : "", \
+ 		\
+		(temp & RH_PS_LSDA) ? " LSDA" : "", \
+		(temp & RH_PS_PPS) ? " PPS" : "", \
+		(temp & RH_PS_PRS) ? " PRS" : "", \
+		(temp & RH_PS_POCI) ? " POCI" : "", \
+		(temp & RH_PS_PSS) ? " PSS" : "", \
+ 		\
+		(temp & RH_PS_PES) ? " PES" : "", \
+		(temp & RH_PS_CCS) ? " CCS" : "" \
+		);
+
+
+/*-------------------------------------------------------------------------*/
+
+/* build "status change" packet (one or two bytes) from HC registers */
+
+static int
+ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	int		ports, i, changed = 0, length = 1;
+
+	ports = roothub_a (ohci) & RH_A_NDP; 
+	if (ports > MAX_ROOT_PORTS) {
+		err ("%s: bogus NDP=%d", hcd->bus_name, ports);
+		err ("rereads as NDP=%d",
+			readl (&ohci->regs->roothub.a) & RH_A_NDP);
+		/* retry later; "should not happen" */
+		return 0;
+	}
+
+	/* init status */
+	if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
+		buf [0] = changed = 1;
+	else
+		buf [0] = 0;
+	if (ports > 7) {
+		buf [1] = 0;
+		length++;
+	}
+
+	/* look at each port */
+	for (i = 0; i < ports; i++) {
+		u32	status = roothub_portstatus (ohci, i);
+
+		status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
+				| RH_PS_OCIC | RH_PS_PRSC;
+		if (status) {
+			changed = 1;
+			set_bit (i + 1, buf);
+		}
+	}
+	return changed ? length : 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+ohci_hub_descriptor (
+	struct ohci_hcd			*ohci,
+	struct usb_hub_descriptor	*desc
+) {
+	u32		rh = roothub_a (ohci);
+	int		ports = rh & RH_A_NDP; 
+	u16		temp;
+
+	desc->bDescriptorType = 0x29;
+	desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
+	desc->bHubContrCurrent = 0;
+
+	desc->bNbrPorts = ports;
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	temp = 0;
+	if (rh & RH_A_PSM) 		/* per-port power switching? */
+	    temp |= 0x0001;
+	if (rh & RH_A_NOCP)		/* no overcurrent reporting? */
+	    temp |= 0x0010;
+	else if (rh & RH_A_OCPM)	/* per-port overcurrent reporting? */
+	    temp |= 0x0008;
+	desc->wHubCharacteristics = cpu_to_le16 (temp);
+
+	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	rh = roothub_b (ohci);
+	desc->bitmap [0] = rh & RH_B_DR;
+	if (ports > 7) {
+		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
+		desc->bitmap [2] = desc->bitmap [3] = 0xff;
+	} else
+		desc->bitmap [1] = 0xff;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hub_control (
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength
+) {
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	int		ports;
+	u32		temp;
+	int		retval = 0;
+
+	// if (port request)
+		ports = roothub_a (ohci) & RH_A_NDP; 
+	switch (typeReq) {
+	case ClearHubFeature:
+		switch (wValue) {
+		case C_HUB_OVER_CURRENT:
+			writel (RH_HS_OCIC, &ohci->regs->roothub.status);
+		case C_HUB_LOCAL_POWER:
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case ClearPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			temp = RH_PS_CCS;
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+			temp = RH_PS_PESC;
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			temp = RH_PS_POCI;
+			break;
+		case USB_PORT_FEAT_C_SUSPEND:
+			temp = RH_PS_PSSC;
+			break;
+		case USB_PORT_FEAT_POWER:
+			temp = RH_PS_LSDA;
+			break;
+		case USB_PORT_FEAT_C_CONNECTION:
+			temp = RH_PS_CSC;
+			break;
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			temp = RH_PS_OCIC;
+			break;
+		case USB_PORT_FEAT_C_RESET:
+			temp = RH_PS_PRSC;
+			break;
+		default:
+			goto error;
+		}
+		writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
+		// readl (&ohci->regs->roothub.portstatus [wIndex]);
+		break;
+	case GetHubDescriptor:
+		ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
+		break;
+	case GetHubStatus:
+		temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
+		*(u32 *) buf = cpu_to_le32 (temp);
+		break;
+	case GetPortStatus:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		temp = roothub_portstatus (ohci, wIndex);
+		*(u32 *) buf = cpu_to_le32 (temp);
+
+#ifndef	OHCI_VERBOSE_DEBUG
+	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
+#endif
+		dbg_port (ohci, "GetStatus", wIndex + 1, temp);
+		break;
+	case SetHubFeature:
+		switch (wValue) {
+		case C_HUB_OVER_CURRENT:
+			// FIXME:  this can be cleared, yes?
+		case C_HUB_LOCAL_POWER:
+			break;
+		default:
+			goto error;
+		}
+		break;
+	case SetPortFeature:
+		if (!wIndex || wIndex > ports)
+			goto error;
+		wIndex--;
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			writel (RH_PS_PSS,
+				&ohci->regs->roothub.portstatus [wIndex]);
+			break;
+		case USB_PORT_FEAT_POWER:
+			writel (RH_PS_PPS,
+				&ohci->regs->roothub.portstatus [wIndex]);
+			break;
+		case USB_PORT_FEAT_RESET:
+			temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
+			if (temp & RH_PS_CCS)
+				writel (RH_PS_PRS,
+				    &ohci->regs->roothub.portstatus [wIndex]);
+			break;
+		default:
+			goto error;
+		}
+		break;
+
+	default:
+error:
+		/* "protocol stall" on error */
+		retval = -EPIPE;
+	}
+	return retval;
+}
+
diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci-mem.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,246 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ * 
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * This file is licenced under the GPL.
+ * $Id: ohci-mem.c,v 1.3 2002/03/22 16:04:54 dbrownell Exp $
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * There's basically three types of memory:
+ *	- data used only by the HCD ... kmalloc is fine
+ *	- async and periodic schedules, shared by HC and HCD ... these
+ *	  need to use pci_pool or pci_alloc_consistent
+ *	- driver buffers, read/written by HC ... single shot DMA mapped 
+ *
+ * There's also PCI "register" data, which is memory mapped.
+ * No memory seen by this driver is pagable.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_hcd *ohci_hcd_alloc (void)
+{
+	struct ohci_hcd *ohci;
+
+	ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL);
+	if (ohci != 0) {
+		memset (ohci, 0, sizeof (struct ohci_hcd));
+		return &ohci->hcd;
+	}
+	return 0;
+}
+
+static void ohci_hcd_free (struct usb_hcd *hcd)
+{
+	kfree (hcd_to_ohci (hcd));
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef CONFIG_PCI
+#	error "usb-ohci currently requires PCI-based controllers"
+	/* to support non-PCI OHCIs, you need custom bus/mem/... glue */
+#endif
+
+
+/* Recover a TD/ED using its collision chain */
+static inline void *
+dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
+{
+	struct hash_t * scan = entry->head;
+	while (scan && scan->dma != dma)
+		scan = scan->next;
+	return scan->virt;
+}
+
+static struct ed *
+dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma)
+{
+	return (struct ed *) dma_to_ed_td(&(hc->ed_hash [ED_HASH_FUNC(ed_dma)]),
+				      ed_dma);
+}
+
+static struct td *
+dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
+{
+	td_dma &= TD_MASK;
+	return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]),
+				      td_dma);
+}
+
+// FIXME:  when updating the hashtables this way, mem_flags is unusable...
+
+/* Add a hash entry for a TD/ED; return true on success */
+static int
+hash_add_ed_td (
+	struct hash_list_t *entry,
+	void *virt,
+	dma_addr_t dma,
+	int mem_flags
+)
+{
+	struct hash_t * scan;
+	
+	scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags);
+	if (!scan)
+		return 0;
+	
+	if (!entry->tail) {
+		entry->head = entry->tail = scan;
+	} else {
+		entry->tail->next = scan;
+		entry->tail = scan;
+	}
+	
+	scan->virt = virt;
+	scan->dma = dma;
+	scan->next = NULL;
+	return 1;
+}
+
+static inline int
+hash_add_ed (struct ohci_hcd *hc, struct ed *ed, int mem_flags)
+{
+	return hash_add_ed_td (&(hc->ed_hash [ED_HASH_FUNC (ed->dma)]),
+			ed, ed->dma, mem_flags);
+}
+
+static inline int
+hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags)
+{
+	return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]),
+			td, td->td_dma, mem_flags);
+}
+
+
+static void
+hash_free_ed_td (struct hash_list_t *entry, void *virt)
+{
+	struct hash_t *scan, *prev;
+	scan = prev = entry->head;
+
+	// Find and unlink hash entry
+	while (scan && scan->virt != virt) {
+		prev = scan;
+		scan = scan->next;
+	}
+	if (scan) {
+		if (scan == entry->head) {
+			if (entry->head == entry->tail)
+				entry->head = entry->tail = NULL;
+			else
+				entry->head = scan->next;
+		} else if (scan == entry->tail) {
+			entry->tail = prev;
+			prev->next = NULL;
+		} else
+			prev->next = scan->next;
+		kfree(scan);
+	}
+}
+
+static inline void
+hash_free_ed (struct ohci_hcd *hc, struct ed * ed)
+{
+	hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed);
+}
+
+static inline void
+hash_free_td (struct ohci_hcd *hc, struct td * td)
+{
+	hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);
+}
+
+
+static int ohci_mem_init (struct ohci_hcd *ohci)
+{
+	ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
+		sizeof (struct td),
+		32 /* byte alignment */,
+		0 /* no page-crossing issues */,
+		GFP_KERNEL);
+	if (!ohci->td_cache)
+		return -ENOMEM;
+	ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev,
+		sizeof (struct ed),
+		16 /* byte alignment */,
+		0 /* no page-crossing issues */,
+		GFP_KERNEL);
+	if (!ohci->ed_cache) {
+		pci_pool_destroy (ohci->td_cache);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void ohci_mem_cleanup (struct ohci_hcd *ohci)
+{
+	if (ohci->td_cache) {
+		pci_pool_destroy (ohci->td_cache);
+		ohci->td_cache = 0;
+	}
+	if (ohci->ed_cache) {
+		pci_pool_destroy (ohci->ed_cache);
+		ohci->ed_cache = 0;
+	}
+}
+
+/* TDs ... */
+static struct td *
+td_alloc (struct ohci_hcd *hc, int mem_flags)
+{
+	dma_addr_t	dma;
+	struct td	*td;
+
+	td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
+	if (td) {
+		td->td_dma = dma;
+		/* hash it for later reverse mapping */
+		if (!hash_add_td (hc, td, mem_flags)) {
+			pci_pool_free (hc->td_cache, td, dma);
+			return NULL;
+		}
+	}
+	return td;
+}
+
+static void
+td_free (struct ohci_hcd *hc, struct td *td)
+{
+	hash_free_td (hc, td);
+	pci_pool_free (hc->td_cache, td, td->td_dma);
+}
+
+
+/* EDs ... */
+static struct ed *
+ed_alloc (struct ohci_hcd *hc, int mem_flags)
+{
+	dma_addr_t	dma;
+	struct ed	*ed;
+
+	ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
+	if (ed) {
+		memset (ed, 0, sizeof (*ed));
+		ed->dma = dma;
+		/* hash it for later reverse mapping */
+		if (!hash_add_ed (hc, ed, mem_flags)) {
+			pci_pool_free (hc->ed_cache, ed, dma);
+			return NULL;
+		}
+	}
+	return ed;
+}
+
+static void
+ed_free (struct ohci_hcd *hc, struct ed *ed)
+{
+	hash_free_ed (hc, ed);
+	pci_pool_free (hc->ed_cache, ed, ed->dma);
+}
+
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci-q.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,979 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ * 
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * This file is licenced under the GPL.
+ * $Id: ohci-q.c,v 1.8 2002/03/27 20:57:01 dbrownell Exp $
+ */
+
+static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
+{
+	int		last = urb_priv->length - 1;
+
+	if (last >= 0) {
+		int		i;
+		struct td	*td = urb_priv->td [0];
+#ifdef CONFIG_PCI
+		int		len = td->urb->transfer_buffer_length;
+		int		dir = usb_pipeout (td->urb->pipe)
+					? PCI_DMA_TODEVICE
+					: PCI_DMA_FROMDEVICE;
+
+		/* unmap CTRL URB setup buffer (always td 0) */
+		if (usb_pipecontrol (td->urb->pipe)) {
+			pci_unmap_single (hc->hcd.pdev, 
+					td->data_dma, 8, PCI_DMA_TODEVICE);
+			
+			/* CTRL data buffer starts at td 1 if len > 0 */
+			if (len && last > 0)
+				td = urb_priv->td [1]; 		
+		}
+		/* else:  ISOC, BULK, INTR data buffer starts at td 0 */
+
+		/* unmap data buffer */
+		if (len && td->data_dma)
+			pci_unmap_single (hc->hcd.pdev,
+					td->data_dma, len, dir);
+#else
+#	warning "assuming no buffer unmapping is needed"
+#endif
+
+		for (i = 0; i <= last; i++) {
+			td = urb_priv->td [i];
+			if (td)
+				td_free (hc, td);
+		}
+	}
+
+	kfree (urb_priv);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * URB goes back to driver, and isn't reissued.
+ * It's completely gone from HC data structures.
+ * PRECONDITION:  no locks held  (Giveback can call into HCD.)
+ */
+static void finish_urb (struct ohci_hcd *ohci, struct urb *urb)
+{
+	unsigned long	flags;
+
+#ifdef DEBUG
+	if (!urb->hcpriv) {
+		err ("already unlinked!");
+		BUG ();
+	}
+#endif
+
+	urb_free_priv (ohci, urb->hcpriv);
+	urb->hcpriv = NULL;
+
+	spin_lock_irqsave (&urb->lock, flags);
+	if (likely (urb->status == -EINPROGRESS))
+		urb->status = 0;
+	spin_unlock_irqrestore (&urb->lock, flags);
+
+#ifdef OHCI_VERBOSE_DEBUG
+	urb_print (urb, "RET", usb_pipeout (urb->pipe));
+#endif
+	usb_hcd_giveback_urb (&ohci->hcd, urb);
+}
+
+static void td_submit_urb (struct urb *urb);
+
+/* Report interrupt transfer completion, maybe reissue */
+static void intr_resub (struct ohci_hcd *hc, struct urb *urb)
+{
+	urb_priv_t	*urb_priv = urb->hcpriv;
+	unsigned long	flags;
+
+#ifdef CONFIG_PCI
+// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
+// and requeue more cheaply, and only if needed.
+// Better yet ... abolish the notion of automagic resubmission.
+	pci_unmap_single (hc->hcd.pdev,
+		urb_priv->td [0]->data_dma,
+		urb->transfer_buffer_length,
+		usb_pipeout (urb->pipe)
+			? PCI_DMA_TODEVICE
+			: PCI_DMA_FROMDEVICE);
+#endif
+	/* FIXME: MP race.  If another CPU partially unlinks
+	 * this URB (urb->status was updated, hasn't yet told
+	 * us to dequeue) before we call complete() here, an
+	 * extra "unlinked" completion will be reported...
+	 */
+
+	spin_lock_irqsave (&urb->lock, flags);
+	if (likely (urb->status == -EINPROGRESS))
+		urb->status = 0;
+	spin_unlock_irqrestore (&urb->lock, flags);
+
+#ifdef OHCI_VERBOSE_DEBUG
+	urb_print (urb, "INTR", usb_pipeout (urb->pipe));
+#endif
+	urb->complete (urb);
+
+	/* always requeued, but ED_SKIP if complete() unlinks.
+	 * EDs are removed from periodic table only at SOF intr.
+	 */
+	urb->actual_length = 0;
+	spin_lock_irqsave (&urb->lock, flags);
+	if (urb_priv->state != URB_DEL)
+		urb->status = -EINPROGRESS;
+	spin_unlock (&urb->lock);
+
+	spin_lock (&hc->lock);
+	td_submit_urb (urb);
+	spin_unlock_irqrestore (&hc->lock, flags);
+}
+
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/  
+
+/* search for the right branch to insert an interrupt ed into the int tree 
+ * do some load balancing;
+ * returns the branch and 
+ * sets the interval to interval = 2^integer (ld (interval))
+ */
+static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load)
+{
+	int	i, branch = 0;
+
+	/* search for the least loaded interrupt endpoint branch */
+	for (i = 0; i < NUM_INTS ; i++) 
+		if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i])
+			branch = i; 
+
+	branch = branch % interval;
+	for (i = branch; i < NUM_INTS; i += interval)
+		ohci->ohci_int_load [i] += load;
+
+	return branch;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*  2^int ( ld (inter)) */
+
+static int ep_2_n_interval (int inter)
+{	
+	int	i;
+
+	for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++)
+		continue;
+	return 1 << i;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* the int tree is a binary tree 
+ * in order to process it sequentially the indexes of the branches have
+ * to be mapped the mapping reverses the bits of a word of num_bits length
+ */
+static int ep_rev (int num_bits, int word)
+{
+	int			i, wout = 0;
+
+	for (i = 0; i < num_bits; i++)
+		wout |= (( (word >> i) & 1) << (num_bits - i - 1));
+	return wout;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (struct ohci_hcd *ohci, struct ed *edi)
+{	 
+	int			int_branch, i;
+	int			inter, interval, load;
+	__u32			*ed_p;
+	volatile struct ed	*ed = edi;
+
+	ed->state = ED_OPER;
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		ed->hwNextED = 0;
+		if (ohci->ed_controltail == NULL) {
+			writel (ed->dma, &ohci->regs->ed_controlhead);
+		} else {
+			ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
+		}
+		ed->ed_prev = ohci->ed_controltail;
+		if (!ohci->ed_controltail
+				&& !ohci->ed_rm_list [0]
+				&& !ohci->ed_rm_list [1]
+				&& !ohci->sleeping
+				) {
+			ohci->hc_control |= OHCI_CTRL_CLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_controltail = edi;	  
+		break;
+
+	case PIPE_BULK:
+		ed->hwNextED = 0;
+		if (ohci->ed_bulktail == NULL) {
+			writel (ed->dma, &ohci->regs->ed_bulkhead);
+		} else {
+			ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
+		}
+		ed->ed_prev = ohci->ed_bulktail;
+		if (!ohci->ed_bulktail
+				&& !ohci->ed_rm_list [0]
+				&& !ohci->ed_rm_list [1]
+				&& !ohci->sleeping
+				) {
+			ohci->hc_control |= OHCI_CTRL_BLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_bulktail = edi;	  
+		break;
+
+	case PIPE_INTERRUPT:
+		load = ed->int_load;
+		interval = ep_2_n_interval (ed->int_period);
+		ed->int_interval = interval;
+		int_branch = ep_int_balance (ohci, interval, load);
+		ed->int_branch = int_branch;
+
+		for (i = 0; i < ep_rev (6, interval); i += inter) {
+			inter = 1;
+			for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i) + int_branch]); 
+				 (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); 
+				ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
+					inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
+			ed->hwNextED = *ed_p; 
+			*ed_p = cpu_to_le32 (ed->dma);
+		}
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "LINK_INT");
+#endif
+		break;
+
+	case PIPE_ISOCHRONOUS:
+		ed->hwNextED = 0;
+		ed->int_interval = 1;
+		if (ohci->ed_isotail != NULL) {
+			ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
+			ed->ed_prev = ohci->ed_isotail;
+		} else {
+			for ( i = 0; i < NUM_INTS; i += inter) {
+				inter = 1;
+				for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); 
+					*ed_p != 0; 
+					ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
+						inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
+				*ed_p = cpu_to_le32 (ed->dma);	
+			}	
+			ed->ed_prev = NULL;
+		}	
+		ohci->ed_isotail = edi;  
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "LINK_ISO");
+#endif
+		break;
+	}	 	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* scan the periodic table to find and unlink this ED */
+static void periodic_unlink (
+	struct ohci_hcd	*ohci,
+	struct ed	*ed,
+	unsigned	index,
+	unsigned	period
+) {
+	for (; index < NUM_INTS; index += period) {
+		__u32	*ed_p = &ohci->hcca->int_table [index];
+
+		while (*ed_p != 0) {
+			if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
+				*ed_p = ed->hwNextED;		
+				break;
+			}
+			ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED);
+		}
+	}	
+}
+
+/* unlink an ed from one of the HC chains. 
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed
+ */
+static int ep_unlink (struct ohci_hcd *ohci, struct ed *ed) 
+{
+	int	i;
+
+	ed->hwINFO |= ED_SKIP;
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_CLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (le32_to_cpup (&ed->hwNextED),
+				&ohci->regs->ed_controlhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_controltail == ed) {
+			ohci->ed_controltail = ed->ed_prev;
+		} else {
+			 (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
+			 	->ed_prev = ed->ed_prev;
+		}
+		break;
+
+	case PIPE_BULK:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_BLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (le32_to_cpup (&ed->hwNextED),
+				&ohci->regs->ed_bulkhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_bulktail == ed) {
+			ohci->ed_bulktail = ed->ed_prev;
+		} else {
+			 (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
+			 	->ed_prev = ed->ed_prev;
+		}
+		break;
+
+	case PIPE_INTERRUPT:
+		periodic_unlink (ohci, ed, ed->int_branch, ed->int_interval);
+		for (i = ed->int_branch; i < NUM_INTS; i += ed->int_interval)
+			ohci->ohci_int_load [i] -= ed->int_load;
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "UNLINK_INT");
+#endif
+		break;
+
+	case PIPE_ISOCHRONOUS:
+		if (ohci->ed_isotail == ed)
+			ohci->ed_isotail = ed->ed_prev;
+		if (ed->hwNextED != 0) 
+			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
+		    		->ed_prev = ed->ed_prev;
+
+		if (ed->ed_prev != NULL)
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		else
+			periodic_unlink (ohci, ed, 0, 1);
+#ifdef OHCI_VERBOSE_DEBUG
+		ohci_dump_periodic (ohci, "UNLINK_ISO");
+#endif
+		break;
+	}
+
+	/* FIXME ED's "unlink" state is indeterminate;
+	 * the HC might still be caching it (till SOF).
+	 */
+	ed->state = ED_UNLINK;
+	return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* (re)init an endpoint; this _should_ be done once at the
+ * usb_set_configuration command, but the USB stack is a bit stateless
+ * so we do it at every transaction.
+ * if the state of the ed is ED_NEW then a dummy td is added and the
+ * state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are set even though most of them should
+ * not change
+ */
+static struct ed *ep_add_ed (
+	struct usb_device	*udev,
+	unsigned int		pipe,
+	int			interval,
+	int			load,
+	int			mem_flags
+) {
+   	struct ohci_hcd		*ohci = hcd_to_ohci (udev->bus->hcpriv);
+	struct hcd_dev		*dev = (struct hcd_dev *) udev->hcpriv;
+	struct td		*td;
+	struct ed		*ed; 
+	unsigned		ep;
+	unsigned long		flags;
+
+	spin_lock_irqsave (&ohci->lock, flags);
+
+	ep = usb_pipeendpoint (pipe) << 1;
+	if (!usb_pipecontrol (pipe) && usb_pipeout (pipe))
+		ep |= 1;
+	if (!(ed = dev->ep [ep])) {
+		ed = ed_alloc (ohci, SLAB_ATOMIC);
+		if (!ed) {
+			/* out of memory */
+			spin_unlock_irqrestore (&ohci->lock, flags);
+			return NULL;
+		}
+		dev->ep [ep] = ed;
+	}
+
+	if (ed->state & ED_URB_DEL) {
+		/* pending unlink request */
+		spin_unlock_irqrestore (&ohci->lock, flags);
+		return NULL;
+	}
+
+	if (ed->state == ED_NEW) {
+		ed->hwINFO = ED_SKIP;
+  		/* dummy td; end of td list for ed */
+		td = td_alloc (ohci, SLAB_ATOMIC);
+ 		if (!td) {
+			/* out of memory */
+			spin_unlock_irqrestore (&ohci->lock, flags);
+			return NULL;
+		}
+		ed->hwTailP = cpu_to_le32 (td->td_dma);
+		ed->hwHeadP = ed->hwTailP;	
+		ed->state = ED_UNLINK;
+		ed->type = usb_pipetype (pipe);
+	}
+
+// FIXME:  don't do this if it's linked to the HC,
+// we might clobber data toggle or other state ...
+
+	ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
+			| usb_pipeendpoint (pipe) << 7
+			| (usb_pipeisoc (pipe)? 0x8000: 0)
+			| (usb_pipecontrol (pipe)
+				? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) 
+			| (udev->speed == USB_SPEED_LOW) << 13
+			| usb_maxpacket (udev, pipe, usb_pipeout (pipe))
+				<< 16);
+
+  	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
+  		ed->int_period = interval;
+  		ed->int_load = load;
+  	}
+
+	spin_unlock_irqrestore (&ohci->lock, flags);
+	return ed; 
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* request unlinking of an endpoint from an operational HC.
+ * put the ep on the rm_list and stop the bulk or ctrl list 
+ * real work is done at the next start frame (SF) hardware interrupt
+ */
+static void ed_unlink (struct usb_device *usb_dev, struct ed *ed)
+{    
+	unsigned int		frame;
+   	struct ohci_hcd		*ohci = hcd_to_ohci (usb_dev->bus->hcpriv);
+
+	/* already pending? */
+	if (ed->state & ED_URB_DEL)
+		return;
+	ed->state |= ED_URB_DEL;
+
+	ed->hwINFO |= ED_SKIP;
+
+	switch (ed->type) {
+		case PIPE_CONTROL: /* stop control list */
+			ohci->hc_control &= ~OHCI_CTRL_CLE;
+			writel (ohci->hc_control,
+				&ohci->regs->control); 
+			break;
+		case PIPE_BULK: /* stop bulk list */
+			ohci->hc_control &= ~OHCI_CTRL_BLE;
+			writel (ohci->hc_control,
+				&ohci->regs->control); 
+			break;
+	}
+
+	frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1;
+	ed->ed_rm_list = ohci->ed_rm_list [frame];
+	ohci->ed_rm_list [frame] = ed;
+
+	/* enable SOF interrupt */
+	if (!ohci->sleeping) {
+		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
+		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
+	}
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void
+td_fill (struct ohci_hcd *ohci, unsigned int info,
+	dma_addr_t data, int len,
+	struct urb *urb, int index)
+{
+	volatile struct td	*td, *td_pt;
+	urb_priv_t		*urb_priv = urb->hcpriv;
+
+	if (index >= urb_priv->length) {
+		err ("internal OHCI error: TD index > length");
+		return;
+	}
+
+#if 0
+	/* no interrupt needed except for URB's last TD */
+	if (index != (urb_priv->length - 1))
+		info |= TD_DI;
+#endif
+
+	/* use this td as the next dummy */
+	td_pt = urb_priv->td [index];
+	td_pt->hwNextTD = 0;
+
+	/* fill the old dummy TD */
+	td = urb_priv->td [index] = dma_to_td (ohci,
+			le32_to_cpup (&urb_priv->ed->hwTailP));
+
+	td->ed = urb_priv->ed;
+	td->next_dl_td = NULL;
+	td->index = index;
+	td->urb = urb; 
+	td->data_dma = data;
+	if (!len)
+		data = 0;
+
+	td->hwINFO = cpu_to_le32 (info);
+	if ((td->ed->type) == PIPE_ISOCHRONOUS) {
+		td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
+		td->ed->last_iso = info & 0xffff;
+	} else {
+		td->hwCBP = cpu_to_le32 (data); 
+	}			
+	if (data)
+		td->hwBE = cpu_to_le32 (data + len - 1);
+	else
+		td->hwBE = 0;
+	td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
+	td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
+
+	/* append to queue */
+	td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+
+static void td_submit_urb (struct urb *urb)
+{ 
+	urb_priv_t	*urb_priv = urb->hcpriv;
+	struct ohci_hcd *ohci = hcd_to_ohci (urb->dev->bus->hcpriv);
+	dma_addr_t	data;
+	int		data_len = urb->transfer_buffer_length;
+	int		cnt = 0; 
+	__u32		info = 0;
+  	unsigned int	toggle = 0;
+
+	/* OHCI handles the DATA-toggles itself, we just use the
+	 * USB-toggle bits for resetting
+	 */
+  	if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+			usb_pipeout (urb->pipe))) {
+  		toggle = TD_T_TOGGLE;
+	} else {
+  		toggle = TD_T_DATA0;
+		usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+			usb_pipeout (urb->pipe), 1);
+	}
+
+	urb_priv->td_cnt = 0;
+
+	if (data_len) {
+#ifdef CONFIG_PCI
+		data = pci_map_single (ohci->hcd.pdev,
+			urb->transfer_buffer, data_len,
+			usb_pipeout (urb->pipe)
+				? PCI_DMA_TODEVICE
+				: PCI_DMA_FROMDEVICE
+			);
+#else
+#	error "what dma addr to use"
+#endif
+	} else
+		data = 0;
+
+	/* NOTE:  TD_CC is set so we can tell which TDs the HC processed by
+	 * using TD_CC_GET, as well as by seeing them on the done list.
+	 */
+	switch (usb_pipetype (urb->pipe)) {
+		case PIPE_BULK:
+			info = usb_pipeout (urb->pipe)
+				? TD_CC | TD_DP_OUT
+				: TD_CC | TD_DP_IN ;
+			while (data_len > 4096) {		
+				td_fill (ohci,
+					info | (cnt? TD_T_TOGGLE:toggle),
+					data, 4096, urb, cnt);
+				data += 4096; data_len -= 4096; cnt++;
+			}
+			info = usb_pipeout (urb->pipe)?
+				TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
+				data, data_len, urb, cnt);
+			cnt++;
+			if ((urb->transfer_flags & USB_ZERO_PACKET)
+					&& cnt < urb_priv->length) {
+				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
+					0, 0, urb, cnt);
+				cnt++;
+			}
+			/* start bulk list */
+			if (!ohci->sleeping)
+				writel (OHCI_BLF, &ohci->regs->cmdstatus);
+			break;
+
+		case PIPE_INTERRUPT:
+			info = TD_CC | toggle;
+			info |= usb_pipeout (urb->pipe) 
+				?  TD_DP_OUT
+				:  TD_R | TD_DP_IN;
+			td_fill (ohci, info, data, data_len, urb, cnt++);
+			break;
+
+		case PIPE_CONTROL:
+			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+			td_fill (ohci, info,
+#ifdef CONFIG_PCI
+				pci_map_single (ohci->hcd.pdev,
+					urb->setup_packet, 8,
+					PCI_DMA_TODEVICE),
+#else
+#	error "what dma addr to use"				
+#endif
+				8, urb, cnt++); 
+			if (data_len > 0) {  
+				info = TD_CC | TD_R | TD_T_DATA1;
+				info |= usb_pipeout (urb->pipe)
+				    ? TD_DP_OUT
+				    : TD_DP_IN;
+				/* NOTE:  mishandles transfers >8K, some >4K */
+				td_fill (ohci, info, data, data_len,
+						urb, cnt++);  
+			} 
+			info = usb_pipeout (urb->pipe)
+				? TD_CC | TD_DP_IN | TD_T_DATA1
+				: TD_CC | TD_DP_OUT | TD_T_DATA1;
+			td_fill (ohci, info, data, 0, urb, cnt++);
+			/* start control list */
+			if (!ohci->sleeping)
+				writel (OHCI_CLF, &ohci->regs->cmdstatus);
+			break;
+
+		case PIPE_ISOCHRONOUS:
+			for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+				int	frame = urb->start_frame;
+
+				// FIXME scheduling should handle frame counter
+				// roll-around ... exotic case (and OHCI has
+				// a 2^16 iso range, vs other HCs max of 2^10)
+				frame += cnt * urb->interval;
+				frame &= 0xffff;
+				td_fill (ohci, TD_CC | TD_ISO | frame,
+				    data + urb->iso_frame_desc [cnt].offset, 
+				    urb->iso_frame_desc [cnt].length, urb, cnt); 
+			}
+			break;
+	} 
+	if (urb_priv->length != cnt) 
+		dbg ("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+/* calculate transfer length/status and update the urb
+ * PRECONDITION:  irqsafe (only for urb->status locking)
+ */
+static void td_done (struct urb *urb, struct td *td)
+{
+	u32	tdINFO = le32_to_cpup (&td->hwINFO);
+	int	cc = 0;
+
+
+	/* ISO ... drivers see per-TD length/status */
+  	if (tdINFO & TD_ISO) {
+ 		u16	tdPSW = le16_to_cpu (td->hwPSW [0]);
+		int	dlen = 0;
+
+ 		cc = (tdPSW >> 12) & 0xF;
+		if (! ((urb->transfer_flags & USB_DISABLE_SPD)
+				&& (cc == TD_DATAUNDERRUN)))
+			cc = TD_CC_NOERROR;
+
+		if (usb_pipeout (urb->pipe))
+			dlen = urb->iso_frame_desc [td->index].length;
+		else
+			dlen = tdPSW & 0x3ff;
+		urb->actual_length += dlen;
+		urb->iso_frame_desc [td->index].actual_length = dlen;
+		urb->iso_frame_desc [td->index].status = cc_to_error [cc];
+
+		if (cc != 0)
+			dbg ("  urb %p iso TD %d len %d CC %d",
+				urb, td->index, dlen, cc);
+
+	/* BULK, INT, CONTROL ... drivers see aggregate length/status,
+	 * except that "setup" bytes aren't counted and "short" transfers
+	 * might not be reported as errors.
+	 */
+	} else {
+		int	type = usb_pipetype (urb->pipe);
+		u32	tdBE = le32_to_cpup (&td->hwBE);
+
+  		cc = TD_CC_GET (tdINFO);
+
+		/* control endpoints only have soft stalls */
+  		if (type != PIPE_CONTROL && cc == TD_CC_STALL)
+			usb_endpoint_halt (urb->dev,
+				usb_pipeendpoint (urb->pipe),
+				usb_pipeout (urb->pipe));
+
+		/* update packet status if needed (short may be ok) */
+		if (((urb->transfer_flags & USB_DISABLE_SPD) != 0
+				&& cc == TD_DATAUNDERRUN))
+			cc = TD_CC_NOERROR;
+		if (cc != TD_CC_NOERROR) {
+			spin_lock (&urb->lock);
+			if (urb->status == -EINPROGRESS)
+				urb->status = cc_to_error [cc];
+			spin_unlock (&urb->lock);
+		}
+
+		/* count all non-empty packets except control SETUP packet */
+		if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) {
+			if (td->hwCBP == 0)
+				urb->actual_length += tdBE - td->data_dma + 1;
+			else
+				urb->actual_length +=
+					  le32_to_cpup (&td->hwCBP)
+					- td->data_dma;
+		}
+
+		if (cc != 0)
+			dbg ("  urb %p TD %d CC %d, len=%d",
+				urb, td->index, cc, urb->actual_length);
+  	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we unreverse the hc-reversed done-list
+ */
+static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
+{
+	__u32		td_list_hc;
+	struct td	*td_rev = NULL;
+	struct td	*td_list = NULL;
+  	urb_priv_t	*urb_priv = NULL;
+  	unsigned long	flags;
+
+  	spin_lock_irqsave (&ohci->lock, flags);
+
+	td_list_hc = le32_to_cpup (&ohci->hcca->done_head);
+	ohci->hcca->done_head = 0;
+
+	while (td_list_hc) {		
+		td_list = dma_to_td (ohci, td_list_hc);
+
+		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
+			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
+			/* typically the endpoint halts on error; un-halt,
+			 * and maybe dequeue other TDs from this urb
+			 */
+			if (td_list->ed->hwHeadP & ED_H) {
+				if (urb_priv && ((td_list->index + 1)
+						< urb_priv->length)) {
+					dbg ("urb %p TD %d of %d, patch ED",
+						td_list->urb,
+						1 + td_list->index,
+						urb_priv->length);
+					td_list->ed->hwHeadP = 
+			    (urb_priv->td [urb_priv->length - 1]->hwNextTD
+				    & __constant_cpu_to_le32 (TD_MASK))
+			    | (td_list->ed->hwHeadP & ED_C);
+					urb_priv->td_cnt += urb_priv->length
+						- td_list->index - 1;
+				} else 
+					td_list->ed->hwHeadP &= ~ED_H;
+			}
+		}
+
+		td_list->next_dl_td = td_rev;	
+		td_rev = td_list;
+		td_list_hc = le32_to_cpup (&td_list->hwNextTD);
+	}	
+	spin_unlock_irqrestore (&ohci->lock, flags);
+	return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* there are some pending requests to unlink 
+ * - some URBs/TDs if urb_priv->state == URB_DEL
+ */
+static void dl_del_list (struct ohci_hcd *ohci, unsigned int frame)
+{
+	unsigned long	flags;
+	struct ed	*ed;
+	__u32		edINFO;
+	__u32		tdINFO;
+	struct td	*td = NULL, *td_next = NULL,
+			*tdHeadP = NULL, *tdTailP;
+	__u32		*td_p;
+	int		ctrl = 0, bulk = 0;
+
+	spin_lock_irqsave (&ohci->lock, flags);
+
+	for (ed = ohci->ed_rm_list [frame]; ed != NULL; ed = ed->ed_rm_list) {
+
+		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP));
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
+		edINFO = le32_to_cpup (&ed->hwINFO);
+		td_p = &ed->hwHeadP;
+
+		for (td = tdHeadP; td != tdTailP; td = td_next) {
+			struct urb *urb = td->urb;
+			urb_priv_t *urb_priv = td->urb->hcpriv;
+
+			td_next = dma_to_td (ohci,
+				le32_to_cpup (&td->hwNextTD));
+			if ((urb_priv->state == URB_DEL)) {
+				tdINFO = le32_to_cpup (&td->hwINFO);
+				/* HC may have partly processed this TD */
+				if (TD_CC_GET (tdINFO) < 0xE)
+					td_done (urb, td);
+				*td_p = td->hwNextTD | (*td_p
+					& __constant_cpu_to_le32 (0x3));
+
+				/* URB is done; clean up */
+				if (++ (urb_priv->td_cnt) == urb_priv->length) {
+     					spin_unlock_irqrestore (&ohci->lock,
+						flags);
+					finish_urb (ohci, urb);
+					spin_lock_irqsave (&ohci->lock, flags);
+				}
+			} else {
+				td_p = &td->hwNextTD;
+			}
+		}
+
+		ed->state &= ~ED_URB_DEL;
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP));
+
+		if (tdHeadP == tdTailP) {
+			if (ed->state == ED_OPER)
+				ep_unlink (ohci, ed);
+			td_free (ohci, tdTailP);
+			ed->hwINFO = ED_SKIP;
+			ed->state = ED_NEW;
+		} else
+			ed->hwINFO &= ~ED_SKIP;
+
+		switch (ed->type) {
+			case PIPE_CONTROL:
+				ctrl = 1;
+				break;
+			case PIPE_BULK:
+				bulk = 1;
+				break;
+		}
+   	}
+
+	/* maybe reenable control and bulk lists */ 
+	if (!ohci->disabled) {
+		if (ctrl) 	/* reset control list */
+			writel (0, &ohci->regs->ed_controlcurrent);
+		if (bulk)	/* reset bulk list */
+			writel (0, &ohci->regs->ed_bulkcurrent);
+		if (!ohci->ed_rm_list [!frame]) {
+			if (ohci->ed_controltail)
+				ohci->hc_control |= OHCI_CTRL_CLE;
+			if (ohci->ed_bulktail)
+				ohci->hc_control |= OHCI_CTRL_BLE;
+			writel (ohci->hc_control, &ohci->regs->control);   
+		}
+	}
+
+   	ohci->ed_rm_list [frame] = NULL;
+   	spin_unlock_irqrestore (&ohci->lock, flags);
+}
+
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Process normal completions (error or success) and clean the schedules.
+ *
+ * This is the main path for handing urbs back to drivers.  The only other
+ * path is dl_del_list(), which unlinks URBs by scanning EDs, instead of
+ * scanning the (re-reversed) donelist as this does.
+ */
+static void dl_done_list (struct ohci_hcd *ohci, struct td *td)
+{
+	unsigned long	flags;
+
+  	spin_lock_irqsave (&ohci->lock, flags);
+  	while (td) {
+		struct td	*td_next = td->next_dl_td;
+		struct urb	*urb = td->urb;
+		urb_priv_t	*urb_priv = urb->hcpriv;
+		struct ed	*ed = td->ed;
+
+		/* update URB's length and status from TD */
+   		td_done (urb, td);
+  		urb_priv->td_cnt++;
+
+		/* If all this urb's TDs are done, call complete().
+		 * Interrupt transfers are the only special case:
+		 * they're reissued, until "deleted" by usb_unlink_urb
+		 * (real work done in a SOF intr, by dl_del_list).
+		 */
+  		if (urb_priv->td_cnt == urb_priv->length) {
+			int	resubmit;
+
+			resubmit = usb_pipeint (urb->pipe)
+					&& (urb_priv->state != URB_DEL);
+
+     			spin_unlock_irqrestore (&ohci->lock, flags);
+			if (resubmit)
+  				intr_resub (ohci, urb);
+  			else
+  				finish_urb (ohci, urb);
+  			spin_lock_irqsave (&ohci->lock, flags);
+  		}
+
+		/* clean schedule:  unlink EDs that are no longer busy */
+		if ((ed->hwHeadP & __constant_cpu_to_le32 (TD_MASK))
+					== ed->hwTailP
+				&& (ed->state == ED_OPER)) 
+			ep_unlink (ohci, ed);
+    		td = td_next;
+  	}  
+	spin_unlock_irqrestore (&ohci->lock, flags);
+}
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/ohci.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,369 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ * 
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * This file is licenced under the GPL.
+ * $Id: ohci.h,v 1.6 2002/03/22 16:04:54 dbrownell Exp $
+ */
+ 
+/*
+ * OHCI Endpoint Descriptor (ED) ... holds TD queue
+ * See OHCI spec, section 4.2
+ */
+struct ed {
+	/* first fields are hardware-specified, le32 */
+	__u32			hwINFO;       	/* endpoint config bitmap */
+#define ED_ISO		__constant_cpu_to_le32(1 << 15)
+#define ED_SKIP		__constant_cpu_to_le32(1 << 14)
+#define ED_LOWSPEED	__constant_cpu_to_le32(1 << 13)
+#define ED_OUT		__constant_cpu_to_le32(0x01 << 11)
+#define ED_IN		__constant_cpu_to_le32(0x10 << 11)
+	__u32			hwTailP;	/* tail of TD list */
+	__u32			hwHeadP;	/* head of TD list */
+#define ED_C		__constant_cpu_to_le32(0x02)	/* toggle carry */
+#define ED_H		__constant_cpu_to_le32(0x01)	/* halted */
+	__u32			hwNextED;	/* next ED in list */
+
+	/* rest are purely for the driver's use */
+	struct ed		*ed_prev;  
+	__u8			int_period;
+	__u8			int_branch;
+	__u8			int_load; 
+	__u8			int_interval;
+	__u8			state;			// ED_{NEW,UNLINK,OPER}
+#define ED_NEW 		0x00		/* unused, no dummy td */
+#define ED_UNLINK 	0x01		/* dummy td, maybe linked to hc */
+#define ED_OPER		0x02		/* dummy td, _is_ linked to hc */
+#define ED_URB_DEL  	0x08		/* for unlinking; masked in */
+
+	__u8			type; 
+	__u16			last_iso;
+	struct ed		*ed_rm_list;
+
+	dma_addr_t		dma;			/* addr of ED */
+} __attribute__ ((aligned(16)));
+
+#define ED_MASK	((u32)~0x0f)		/* strip hw status in low addr bits */
+
+ 
+/*
+ * OHCI Transfer Descriptor (TD) ... one per transfer segment
+ * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
+ * and 4.3.2 (iso)
+ */
+struct td {
+	/* first fields are hardware-specified, le32 */
+	__u32		hwINFO;		/* transfer info bitmask */
+#define TD_CC       0xf0000000			/* condition code */
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC       0x0C000000			/* error count */
+#define TD_T        0x03000000			/* data toggle state */
+#define TD_T_DATA0  0x02000000				/* DATA0 */
+#define TD_T_DATA1  0x03000000				/* DATA1 */
+#define TD_T_TOGGLE 0x00000000				/* uses ED_C */
+#define TD_DI       0x00E00000			/* frames before interrupt */
+//#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP       0x00180000			/* direction/pid */
+#define TD_DP_SETUP 0x00000000			/* SETUP pid */
+#define TD_DP_IN    0x00100000				/* IN pid */
+#define TD_DP_OUT   0x00080000				/* OUT pid */
+							/* 0x00180000 rsvd */
+#define TD_R        0x00040000			/* round: short packets OK? */
+					/* bits 0x1ffff are defined by HCD */
+#define TD_ISO	    0x00010000			/* copy of ED_ISO */
+
+  	__u32		hwCBP;		/* Current Buffer Pointer (or 0) */
+  	__u32		hwNextTD;	/* Next TD Pointer */
+  	__u32		hwBE;		/* Memory Buffer End Pointer */
+
+	/* PSW is only for ISO */
+#define MAXPSW 1		/* hardware allows 8 */
+  	__u16		hwPSW [MAXPSW];
+
+	/* rest are purely for the driver's use */
+  	__u8		index;
+  	struct ed	*ed;
+  	struct td	*next_dl_td;
+  	struct urb	*urb;
+
+	dma_addr_t	td_dma;		/* addr of this TD */
+	dma_addr_t	data_dma;	/* addr of data it points to */
+} __attribute__ ((aligned(32)));	/* c/b/i need 16; only iso needs 32 */
+
+#define TD_MASK	((u32)~0x1f)		/* strip hw status in low addr bits */
+
+/*
+ * Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW
+ */
+#define TD_CC_NOERROR      0x00
+#define TD_CC_CRC          0x01
+#define TD_CC_BITSTUFFING  0x02
+#define TD_CC_DATATOGGLEM  0x03
+#define TD_CC_STALL        0x04
+#define TD_DEVNOTRESP      0x05
+#define TD_PIDCHECKFAIL    0x06
+#define TD_UNEXPECTEDPID   0x07
+#define TD_DATAOVERRUN     0x08
+#define TD_DATAUNDERRUN    0x09
+    /* 0x0A, 0x0B reserved for hardware */
+#define TD_BUFFEROVERRUN   0x0C
+#define TD_BUFFERUNDERRUN  0x0D
+    /* 0x0E, 0x0F reserved for HCD */
+#define TD_NOTACCESSED     0x0F
+
+
+/* map OHCI TD status codes (CC) to errno values */ 
+static const int cc_to_error [16] = { 
+	/* No  Error  */               0,
+	/* CRC Error  */               -EILSEQ,
+	/* Bit Stuff  */               -EPROTO,
+	/* Data Togg  */               -EILSEQ,
+	/* Stall      */               -EPIPE,
+	/* DevNotResp */               -ETIMEDOUT,
+	/* PIDCheck   */               -EPROTO,
+	/* UnExpPID   */               -EPROTO,
+	/* DataOver   */               -EOVERFLOW,
+	/* DataUnder  */               -EREMOTEIO,
+	/* (for hw)   */               -EIO,
+	/* (for hw)   */               -EIO,
+	/* BufferOver */               -ECOMM,
+	/* BuffUnder  */               -ENOSR,
+	/* (for HCD)  */               -EALREADY,
+	/* (for HCD)  */               -EALREADY 
+};
+
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined section 4.4.1 of the OHCI spec. The HC is
+ * told the base address of it.  It must be 256-byte aligned.
+ */
+struct ohci_hcca {
+#define NUM_INTS 32
+	__u32	int_table [NUM_INTS];	/* periodic schedule */
+	__u16	frame_no;		/* current frame number */
+	__u16	pad1;			/* set to 0 on each frame_no change */
+	__u32	done_head;		/* info returned for an interrupt */
+	u8	reserved_for_hc [116];
+	u8	what [4];		/* spec only identifies 252 bytes :) */
+} __attribute__ ((aligned(256)));
+
+  
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O region.
+ * You must use readl() and writel() (in <asm/io.h>) to access these fields!!
+ * Layout is in section 7 (and appendix B) of the spec.
+ */
+struct ohci_regs {
+	/* control and status registers (section 7.1) */
+	__u32	revision;
+	__u32	control;
+	__u32	cmdstatus;
+	__u32	intrstatus;
+	__u32	intrenable;
+	__u32	intrdisable;
+
+	/* memory pointers (section 7.2) */
+	__u32	hcca;
+	__u32	ed_periodcurrent;
+	__u32	ed_controlhead;
+	__u32	ed_controlcurrent;
+	__u32	ed_bulkhead;
+	__u32	ed_bulkcurrent;
+	__u32	donehead;
+
+	/* frame counters (section 7.3) */
+	__u32	fminterval;
+	__u32	fmremaining;
+	__u32	fmnumber;
+	__u32	periodicstart;
+	__u32	lsthresh;
+
+	/* Root hub ports (section 7.4) */
+	struct	ohci_roothub_regs {
+		__u32	a;
+		__u32	b;
+		__u32	status;
+#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports (RH_A_NDP) */
+		__u32	portstatus [MAX_ROOT_PORTS];
+	} roothub;
+
+	/* and optional "legacy support" registers (appendix B) at 0x0100 */
+
+} __attribute__ ((aligned(32)));
+
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR	(3 << 0)	/* control/bulk service ratio */
+#define OHCI_CTRL_PLE	(1 << 2)	/* periodic list enable */
+#define OHCI_CTRL_IE	(1 << 3)	/* isochronous enable */
+#define OHCI_CTRL_CLE	(1 << 4)	/* control list enable */
+#define OHCI_CTRL_BLE	(1 << 5)	/* bulk list enable */
+#define OHCI_CTRL_HCFS	(3 << 6)	/* host controller functional state */
+#define OHCI_CTRL_IR	(1 << 8)	/* interrupt routing */
+#define OHCI_CTRL_RWC	(1 << 9)	/* remote wakeup connected */
+#define OHCI_CTRL_RWE	(1 << 10)	/* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+#	define OHCI_USB_RESET	(0 << 6)
+#	define OHCI_USB_RESUME	(1 << 6)
+#	define OHCI_USB_OPER	(2 << 6)
+#	define OHCI_USB_SUSPEND	(3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR	(1 << 0)	/* host controller reset */
+#define OHCI_CLF  	(1 << 1)	/* control list filled */
+#define OHCI_BLF  	(1 << 2)	/* bulk list filled */
+#define OHCI_OCR  	(1 << 3)	/* ownership change request */
+#define OHCI_SOC  	(3 << 16)	/* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO	(1 << 0)	/* scheduling overrun */
+#define OHCI_INTR_WDH	(1 << 1)	/* writeback of done_head */
+#define OHCI_INTR_SF	(1 << 2)	/* start frame */
+#define OHCI_INTR_RD	(1 << 3)	/* resume detect */
+#define OHCI_INTR_UE	(1 << 4)	/* unrecoverable error */
+#define OHCI_INTR_FNO	(1 << 5)	/* frame number overflow */
+#define OHCI_INTR_RHSC	(1 << 6)	/* root hub status change */
+#define OHCI_INTR_OC	(1 << 30)	/* ownership change */
+#define OHCI_INTR_MIE	(1 << 31)	/* master interrupt enable */
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+ 
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS            0x00000001   	/* current connect status */
+#define RH_PS_PES            0x00000002   	/* port enable status*/
+#define RH_PS_PSS            0x00000004   	/* port suspend status */
+#define RH_PS_POCI           0x00000008   	/* port over current indicator */
+#define RH_PS_PRS            0x00000010  	/* port reset status */
+#define RH_PS_PPS            0x00000100   	/* port power status */
+#define RH_PS_LSDA           0x00000200    	/* low speed device attached */
+#define RH_PS_CSC            0x00010000 	/* connect status change */
+#define RH_PS_PESC           0x00020000   	/* port enable status change */
+#define RH_PS_PSSC           0x00040000    	/* port suspend status change */
+#define RH_PS_OCIC           0x00080000    	/* over current indicator change */
+#define RH_PS_PRSC           0x00100000   	/* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS	     0x00000001		/* local power status */
+#define RH_HS_OCI	     0x00000002		/* over current indicator */
+#define RH_HS_DRWE	     0x00008000		/* device remote wakeup enable */
+#define RH_HS_LPSC	     0x00010000		/* local power status change */
+#define RH_HS_OCIC	     0x00020000		/* over current indicator change */
+#define RH_HS_CRWE	     0x80000000		/* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR		0x0000ffff		/* device removable flags */
+#define RH_B_PPCM	0xffff0000		/* port power control mask */
+
+/* roothub.a masks */
+#define	RH_A_NDP	(0xff << 0)		/* number of downstream ports */
+#define	RH_A_PSM	(1 << 8)		/* power switching mode */
+#define	RH_A_NPS	(1 << 9)		/* no power switching */
+#define	RH_A_DT		(1 << 10)		/* device type (mbz) */
+#define	RH_A_OCPM	(1 << 11)		/* over current protection mode */
+#define	RH_A_NOCP	(1 << 12)		/* no over current protection */
+#define	RH_A_POTPGT	(0xff << 24)		/* power on to power good time */
+
+
+/* hcd-private per-urb state */
+typedef struct urb_priv {
+	struct ed		*ed;
+	__u16			length;		// # tds in this request
+	__u16			td_cnt;		// tds already serviced
+	int   			state;
+	struct td		*td [0];	// all TDs in this request
+
+} urb_priv_t;
+
+#define URB_DEL 1
+
+
+/* Hash struct used for TD/ED hashing */
+struct hash_t {
+	void		*virt;
+	dma_addr_t	dma;
+	struct hash_t	*next; // chaining for collision cases
+};
+
+/* List of TD/ED hash entries */
+struct hash_list_t {
+	struct hash_t	*head;
+	struct hash_t	*tail;
+};
+
+#define TD_HASH_SIZE    64    /* power'o'two */
+#define ED_HASH_SIZE    64    /* power'o'two */
+
+#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)
+#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE)
+
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+struct ohci_hcd {
+	spinlock_t		lock;
+
+	/*
+	 * I/O memory used to communicate with the HC (uncached);
+	 */
+	struct ohci_regs	*regs;
+
+	/*
+	 * main memory used to communicate with the HC (uncached)
+	 */
+	struct ohci_hcca	*hcca;
+	dma_addr_t		hcca_dma;
+
+	struct ed		*ed_rm_list [2];	/* to be removed */
+
+	struct ed		*ed_bulktail;		/* last in bulk list */
+	struct ed		*ed_controltail;	/* last in ctrl list */
+ 	struct ed		*ed_isotail;		/* last in iso list */
+
+#ifdef CONFIG_PCI
+	struct pci_pool		*td_cache;
+	struct pci_pool		*ed_cache;
+	struct hash_list_t	td_hash [TD_HASH_SIZE];
+	struct hash_list_t	ed_hash [ED_HASH_SIZE];
+#endif
+
+	/*
+	 * driver state
+	 */
+	int			disabled;	/* e.g. got a UE, we're hung */
+	int			sleeping;
+	int			ohci_int_load [NUM_INTS];
+	u32 			hc_control;	/* copy of hc control reg */
+
+	unsigned long		flags;		/* for HC bugs */
+#define	OHCI_QUIRK_AMD756	0x01			/* erratum #4 */
+
+	/*
+	 * framework state
+	 */
+	struct usb_hcd		hcd;
+};
+
+#define hcd_to_ohci(hcd_ptr) list_entry(hcd_ptr, struct ohci_hcd, hcd)
+
diff -Nru a/drivers/usb/host/uhci-debug.h b/drivers/usb/host/uhci-debug.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/uhci-debug.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,577 @@
+/*
+ * UHCI-specific debugging code. Invaluable when something
+ * goes wrong, but don't get in my face.
+ *
+ * Kernel visible pointers are surrounded in []'s and bus
+ * visible pointers are surrounded in ()'s
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2001 Johannes Erdfelt
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+
+#include "uhci.h"
+
+/* Handle REALLY large printk's so we don't overflow buffers */
+static void inline lprintk(char *buf)
+{
+	char *p;
+
+	/* Just write one line at a time */
+	while (buf) {
+		p = strchr(buf, '\n');
+		if (p)
+			*p = 0;
+		printk("%s\n", buf);
+		buf = p;
+		if (buf)
+			buf++;
+	}
+}
+
+static int inline uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td)
+{
+	int i;
+
+	for (i = 0; i < UHCI_NUM_SKELTD; i++)
+		if (td == uhci->skeltd[i])
+			return 1;
+
+	return 0;
+}
+
+static int inline uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
+{
+	int i;
+
+	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+		if (qh == uhci->skelqh[i])
+			return 1;
+
+	return 0;
+}
+
+static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
+{
+	char *out = buf;
+	char *spid;
+
+	/* Try to make sure there's enough memory */
+	if (len < 160)
+		return 0;
+
+	out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, td->link);
+	out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
+		((td->status >> 27) & 3),
+		(td->status & TD_CTRL_SPD) ?      "SPD " : "",
+		(td->status & TD_CTRL_LS) ?       "LS " : "",
+		(td->status & TD_CTRL_IOC) ?      "IOC " : "",
+		(td->status & TD_CTRL_ACTIVE) ?   "Active " : "",
+		(td->status & TD_CTRL_STALLED) ?  "Stalled " : "",
+		(td->status & TD_CTRL_DBUFERR) ?  "DataBufErr " : "",
+		(td->status & TD_CTRL_BABBLE) ?   "Babble " : "",
+		(td->status & TD_CTRL_NAK) ?      "NAK " : "",
+		(td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
+		(td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
+		td->status & 0x7ff);
+
+	switch (td->info & 0xff) {
+		case USB_PID_SETUP:
+			spid = "SETUP";
+			break;
+		case USB_PID_OUT:
+			spid = "OUT";
+			break;
+		case USB_PID_IN:
+			spid = "IN";
+			break;
+		default:
+			spid = "?";
+			break;
+	}
+
+	out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
+		td->info >> 21,
+		((td->info >> 19) & 1),
+		(td->info >> 15) & 15,
+		(td->info >> 8) & 127,
+		(td->info & 0xff),
+		spid);
+	out += sprintf(out, "(buf=%08x)\n", td->buffer);
+
+	return out - buf;
+}
+
+static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
+{
+	char *out = buf;
+
+	/* Try to make sure there's enough memory */
+	if (len < 80)
+		return 0;
+
+	out += sprintf(out, "  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
+		port,
+		status,
+		(status & USBPORTSC_SUSP) ? "PortSuspend " : "",
+		(status & USBPORTSC_PR) ?   "PortReset " : "",
+		(status & USBPORTSC_LSDA) ? "LowSpeed " : "",
+		(status & USBPORTSC_RD) ?   "ResumeDetect " : "",
+		(status & USBPORTSC_PEC) ?  "EnableChange " : "",
+		(status & USBPORTSC_PE) ?   "PortEnabled " : "",
+		(status & USBPORTSC_CSC) ?  "ConnectChange " : "",
+		(status & USBPORTSC_CCS) ?  "PortConnected " : "");
+
+	return out - buf;
+}
+
+static int uhci_show_status(struct uhci *uhci, char *buf, int len)
+{
+	char *out = buf;
+	unsigned int io_addr = uhci->io_addr;
+	unsigned short usbcmd, usbstat, usbint, usbfrnum;
+	unsigned int flbaseadd;
+	unsigned char sof;
+	unsigned short portsc1, portsc2;
+
+	/* Try to make sure there's enough memory */
+	if (len < 80 * 6)
+		return 0;
+
+	usbcmd    = inw(io_addr + 0);
+	usbstat   = inw(io_addr + 2);
+	usbint    = inw(io_addr + 4);
+	usbfrnum  = inw(io_addr + 6);
+	flbaseadd = inl(io_addr + 8);
+	sof       = inb(io_addr + 12);
+	portsc1   = inw(io_addr + 16);
+	portsc2   = inw(io_addr + 18);
+
+	out += sprintf(out, "  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
+		usbcmd,
+		(usbcmd & USBCMD_MAXP) ?    "Maxp64 " : "Maxp32 ",
+		(usbcmd & USBCMD_CF) ?      "CF " : "",
+		(usbcmd & USBCMD_SWDBG) ?   "SWDBG " : "",
+		(usbcmd & USBCMD_FGR) ?     "FGR " : "",
+		(usbcmd & USBCMD_EGSM) ?    "EGSM " : "",
+		(usbcmd & USBCMD_GRESET) ?  "GRESET " : "",
+		(usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+		(usbcmd & USBCMD_RS) ?      "RS " : "");
+
+	out += sprintf(out, "  usbstat   =     %04x   %s%s%s%s%s%s\n",
+		usbstat,
+		(usbstat & USBSTS_HCH) ?    "HCHalted " : "",
+		(usbstat & USBSTS_HCPE) ?   "HostControllerProcessError " : "",
+		(usbstat & USBSTS_HSE) ?    "HostSystemError " : "",
+		(usbstat & USBSTS_RD) ?     "ResumeDetect " : "",
+		(usbstat & USBSTS_ERROR) ?  "USBError " : "",
+		(usbstat & USBSTS_USBINT) ? "USBINT " : "");
+
+	out += sprintf(out, "  usbint    =     %04x\n", usbint);
+	out += sprintf(out, "  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,
+		0xfff & (4*(unsigned int)usbfrnum));
+	out += sprintf(out, "  flbaseadd = %08x\n", flbaseadd);
+	out += sprintf(out, "  sof       =       %02x\n", sof);
+	out += uhci_show_sc(1, portsc1, out, len - (out - buf));
+	out += uhci_show_sc(2, portsc2, out, len - (out - buf));
+
+	return out - buf;
+}
+
+static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
+{
+	char *out = buf;
+	struct urb_priv *urbp;
+	struct list_head *head, *tmp;
+	struct uhci_td *td;
+	int i = 0, checked = 0, prevactive = 0;
+
+	/* Try to make sure there's enough memory */
+	if (len < 80 * 6)
+		return 0;
+
+	out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "",
+			qh, qh->link, qh->element);
+
+	if (qh->element & UHCI_PTR_QH)
+		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
+
+	if (qh->element & UHCI_PTR_DEPTH)
+		out += sprintf(out, "%*s  Depth traverse\n", space, "");
+
+	if (qh->element & 8)
+		out += sprintf(out, "%*s  Bit 3 set (bug?)\n", space, "");
+
+	if (!(qh->element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
+		out += sprintf(out, "%*s  Element is NULL (bug?)\n", space, "");
+
+	if (!qh->urbp) {
+		out += sprintf(out, "%*s  urbp == NULL\n", space, "");
+		goto out;
+	}
+
+	urbp = qh->urbp;
+
+	head = &urbp->td_list;
+	tmp = head->next;
+
+	td = list_entry(tmp, struct uhci_td, list);
+
+	if (td->dma_handle != (qh->element & ~UHCI_PTR_BITS))
+		out += sprintf(out, "%*s Element != First TD\n", space, "");
+
+	while (tmp != head) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		out += sprintf(out, "%*s%d: ", space + 2, "", i++);
+		out += uhci_show_td(td, out, len - (out - buf), 0);
+
+		if (i > 10 && !checked && prevactive && tmp != head &&
+		    debug <= 2) {
+			struct list_head *ntmp = tmp;
+			struct uhci_td *ntd = td;
+			int active = 1, ni = i;
+
+			checked = 1;
+
+			while (ntmp != head && ntmp->next != head && active) {
+				ntd = list_entry(ntmp, struct uhci_td, list);
+
+				ntmp = ntmp->next;
+
+				active = ntd->status & TD_CTRL_ACTIVE;
+
+				ni++;
+			}
+
+			if (active && ni > i) {
+				out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
+				tmp = ntmp;
+				td = ntd;
+				i = ni;
+			}
+		}
+
+		prevactive = td->status & TD_CTRL_ACTIVE;
+	}
+
+	if (list_empty(&urbp->queue_list) || urbp->queued)
+		goto out;
+
+	out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
+
+	head = &urbp->queue_list;
+	tmp = head->next;
+
+	while (tmp != head) {
+		struct urb_priv *nurbp = list_entry(tmp, struct urb_priv,
+						queue_list);
+		tmp = tmp->next;
+
+		out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space);
+	}
+
+out:
+	return out - buf;
+}
+
+static const char *td_names[] = {"skel_int1_td", "skel_int2_td",
+				 "skel_int4_td", "skel_int8_td",
+				 "skel_int16_td", "skel_int32_td",
+				 "skel_int64_td", "skel_int128_td",
+				 "skel_int256_td", "skel_term_td" };
+static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh",
+				  "skel_bulk_qh", "skel_term_qh" };
+
+#define show_frame_num()	\
+	if (!shown) {		\
+	  shown = 1;		\
+	  out += sprintf(out, "- Frame %d\n", i); \
+	}
+
+#define show_td_name()		\
+	if (!shown) {		\
+	  shown = 1;		\
+	  out += sprintf(out, "- %s\n", td_names[i]); \
+	}
+
+#define show_qh_name()		\
+	if (!shown) {		\
+	  shown = 1;		\
+	  out += sprintf(out, "- %s\n", qh_names[i]); \
+	}
+
+static int uhci_sprint_schedule(struct uhci *uhci, char *buf, int len)
+{
+	char *out = buf;
+	int i;
+	struct uhci_qh *qh;
+	struct uhci_td *td;
+	struct list_head *tmp, *head;
+
+	out += sprintf(out, "HC status\n");
+	out += uhci_show_status(uhci, out, len - (out - buf));
+
+	out += sprintf(out, "Frame List\n");
+	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+		int shown = 0;
+		td = uhci->fl->frame_cpu[i];
+		if (!td)
+			continue;
+
+		if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+			show_frame_num();
+			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
+		}
+		if (uhci_is_skeleton_td(uhci, td))
+			continue;
+		show_frame_num();
+
+		head = &td->fl_list;
+		tmp = head;
+		do {
+			td = list_entry(tmp, struct uhci_td, fl_list);
+			tmp = tmp->next;
+			out += uhci_show_td(td, out, len - (out - buf), 4);
+		} while (tmp != head);
+	}
+
+	out += sprintf(out, "Skeleton TD's\n");
+	for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) {
+		int shown = 0;
+
+		td = uhci->skeltd[i];
+
+		if (debug > 1) {
+			show_td_name();
+			out += uhci_show_td(td, out, len - (out - buf), 4);
+		}
+
+		if (list_empty(&td->fl_list)) {
+			/* TD 0 is the int1 TD and links to control_ls_qh */
+			if (!i) {
+				if (td->link !=
+				    (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) {
+					show_td_name();
+					out += sprintf(out, "    skeleton TD not linked to ls_control QH!\n");
+				}
+			} else if (i < 9) {
+				if (td->link != uhci->skeltd[i - 1]->dma_handle) {
+					show_td_name();
+					out += sprintf(out, "    skeleton TD not linked to next skeleton TD!\n");
+				}
+			} else {
+				show_td_name();
+
+				if (td->link != td->dma_handle)
+					out += sprintf(out, "    skel_term_td does not link to self\n");
+
+				/* Don't show it twice */
+				if (debug <= 1)
+					out += uhci_show_td(td, out, len - (out - buf), 4);
+			}
+
+			continue;
+		}
+
+		show_td_name();
+
+		head = &td->fl_list;
+		tmp = head->next;
+
+		while (tmp != head) {
+			td = list_entry(tmp, struct uhci_td, fl_list);
+
+			tmp = tmp->next;
+
+			out += uhci_show_td(td, out, len - (out - buf), 4);
+		}
+
+		if (!i) {
+			if (td->link !=
+			    (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH))
+				out += sprintf(out, "    last TD not linked to ls_control QH!\n");
+		} else if (i < 9) {
+			if (td->link != uhci->skeltd[i - 1]->dma_handle)
+				out += sprintf(out, "    last TD not linked to next skeleton!\n");
+		}
+	}
+
+	out += sprintf(out, "Skeleton QH's\n");
+
+	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+		int shown = 0;
+
+		qh = uhci->skelqh[i];
+
+		if (debug > 1) {
+			show_qh_name();
+			out += uhci_show_qh(qh, out, len - (out - buf), 4);
+		}
+
+		/* QH 3 is the Terminating QH, it's different */
+		if (i == 3) {
+			if (qh->link != UHCI_PTR_TERM) {
+				show_qh_name();
+				out += sprintf(out, "    bandwidth reclamation on!\n");
+			}
+
+			if (qh->element != uhci->skel_term_td->dma_handle) {
+				show_qh_name();
+				out += sprintf(out, "    skel_term_qh element is not set to skel_term_td\n");
+			}
+		}
+
+		if (list_empty(&qh->list)) {
+			if (i < 3) {
+				if (qh->link !=
+				    (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH)) {
+					show_qh_name();
+					out += sprintf(out, "    skeleton QH not linked to next skeleton QH!\n");
+				}
+			}
+
+			continue;
+		}
+
+		show_qh_name();
+
+		head = &qh->list;
+		tmp = head->next;
+
+		while (tmp != head) {
+			qh = list_entry(tmp, struct uhci_qh, list);
+
+			tmp = tmp->next;
+
+			out += uhci_show_qh(qh, out, len - (out - buf), 4);
+		}
+
+		if (i < 3) {
+			if (qh->link !=
+			    (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH))
+				out += sprintf(out, "    last QH not linked to next skeleton!\n");
+		}
+	}
+
+	return out - buf;
+}
+
+#ifdef CONFIG_PROC_FS
+#define MAX_OUTPUT	(PAGE_SIZE * 8)
+
+static struct proc_dir_entry *uhci_proc_root = NULL;
+
+struct uhci_proc {
+	int size;
+	char *data;
+	struct uhci *uhci;
+};
+
+static int uhci_proc_open(struct inode *inode, struct file *file)
+{
+	const struct proc_dir_entry *dp = PDE(inode);
+	struct uhci *uhci = dp->data;
+	struct uhci_proc *up;
+	unsigned long flags;
+	int ret = -ENOMEM;
+
+	lock_kernel();
+	up = kmalloc(sizeof(*up), GFP_KERNEL);
+	if (!up)
+		goto out;
+
+	up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
+	if (!up->data) {
+		kfree(up);
+		goto out;
+	}
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+
+	file->private_data = up;
+
+	ret = 0;
+out:
+	unlock_kernel();
+	return ret;
+}
+
+static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence)
+{
+	struct uhci_proc *up;
+	loff_t new = -1;
+
+	lock_kernel();
+	up = file->private_data;
+
+	switch (whence) {
+	case 0:
+		new = off;
+		break;
+	case 1:
+		new = file->f_pos + off;
+		break;
+	}
+	if (new < 0 || new > up->size) {
+		unlock_kernel();
+		return -EINVAL;
+	}
+	unlock_kernel();
+	return (file->f_pos = new);
+}
+
+static ssize_t uhci_proc_read(struct file *file, char *buf, size_t nbytes,
+			loff_t *ppos)
+{
+	struct uhci_proc *up = file->private_data;
+	unsigned int pos;
+	unsigned int size;
+
+	pos = *ppos;
+	size = up->size;
+	if (pos >= size)
+		return 0;
+	if (nbytes >= size)
+		nbytes = size;
+	if (pos + nbytes > size)
+		nbytes = size - pos;
+
+	if (!access_ok(VERIFY_WRITE, buf, nbytes))
+		return -EINVAL;
+
+	copy_to_user(buf, up->data + pos, nbytes);
+
+	*ppos += nbytes;
+
+	return nbytes;
+}
+
+static int uhci_proc_release(struct inode *inode, struct file *file)
+{
+	struct uhci_proc *up = file->private_data;
+
+	kfree(up->data);
+	kfree(up);
+
+	return 0;
+}
+
+static struct file_operations uhci_proc_operations = {
+	open:		uhci_proc_open,
+	llseek:		uhci_proc_lseek,
+	read:		uhci_proc_read,
+//	write:		uhci_proc_write,
+	release:	uhci_proc_release,
+};
+#endif
+
diff -Nru a/drivers/usb/host/uhci.c b/drivers/usb/host/uhci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/uhci.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,3170 @@
+/*
+ * Universal Host Controller Interface driver for USB.
+ *
+ * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
+ * (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Georg Acher, acher@in.tum.de
+ * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
+ * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
+ * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
+ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+ *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+ * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+ *
+ * Intel documents this fairly well, and as far as I know there
+ * are no royalties or anything like that, but even so there are
+ * people who decided that they want to do the same thing in a
+ * completely different way.
+ *
+ * WARNING! The USB documentation is downright evil. Most of it
+ * is just crap, written by a committee. You're better off ignoring
+ * most of it, the important stuff is:
+ *  - the low-level protocol (fairly simple but lots of small details)
+ *  - working around the horridness of the rest
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "../core/hcd.h"
+#include "uhci.h"
+
+#include <linux/pm.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
+/*
+ * debug = 0, no debugging messages
+ * debug = 1, dump failed URB's except for stalls
+ * debug = 2, dump all failed URB's (including stalls)
+ *            show all queues in /proc/uhci/hc*
+ * debug = 3, show all TD's in URB's when dumping
+ */
+#ifdef DEBUG
+static int debug = 1;
+#else
+static int debug = 0;
+#endif
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level");
+static char *errbuf;
+#define ERRBUF_LEN    (PAGE_SIZE * 8)
+
+#include "uhci-debug.h"
+
+static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
+
+static int rh_submit_urb(struct urb *urb);
+static int rh_unlink_urb(struct urb *urb);
+static int uhci_get_current_frame_number(struct usb_device *dev);
+static int uhci_unlink_urb(struct urb *urb);
+static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb);
+static void uhci_call_completion(struct urb *urb);
+
+static int  ports_active(struct uhci *uhci);
+static void suspend_hc(struct uhci *uhci);
+static void wakeup_hc(struct uhci *uhci);
+
+/* If a transfer is still active after this much time, turn off FSBR */
+#define IDLE_TIMEOUT	(HZ / 20)	/* 50 ms */
+#define FSBR_DELAY	(HZ / 20)	/* 50 ms */
+
+#define MAX_URB_LOOP	2048		/* Maximum number of linked URB's */
+
+/*
+ * Only the USB core should call uhci_alloc_dev and uhci_free_dev
+ */
+static int uhci_alloc_dev(struct usb_device *dev)
+{
+	return 0;
+}
+
+static int uhci_free_dev(struct usb_device *dev)
+{
+	return 0;
+}
+
+static inline void uhci_set_next_interrupt(struct uhci *uhci)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	set_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static inline void uhci_clear_next_interrupt(struct uhci *uhci)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	clear_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static inline void uhci_add_complete(struct urb *urb)
+{
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->complete_list_lock, flags);
+	list_add(&urbp->complete_list, &uhci->complete_list);
+	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+}
+
+static struct uhci_td *uhci_alloc_td(struct uhci *uhci, struct usb_device *dev)
+{
+	dma_addr_t dma_handle;
+	struct uhci_td *td;
+
+	td = pci_pool_alloc(uhci->td_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
+	if (!td)
+		return NULL;
+
+	td->dma_handle = dma_handle;
+
+	td->link = UHCI_PTR_TERM;
+	td->buffer = 0;
+
+	td->frame = -1;
+	td->dev = dev;
+
+	INIT_LIST_HEAD(&td->list);
+	INIT_LIST_HEAD(&td->fl_list);
+
+	usb_inc_dev_use(dev);
+
+	return td;
+}
+
+static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
+		__u32 info, __u32 buffer)
+{
+	td->status = status;
+	td->info = info;
+	td->buffer = buffer;
+}
+
+static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td)
+{
+	unsigned long flags;
+	struct uhci_td *ltd;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+	ltd = list_entry(skeltd->fl_list.prev, struct uhci_td, fl_list);
+
+	td->link = ltd->link;
+	mb();
+	ltd->link = td->dma_handle;
+
+	list_add_tail(&td->fl_list, &skeltd->fl_list);
+
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+/*
+ * We insert Isochronous transfers directly into the frame list at the
+ * beginning
+ * The layout looks as follows:
+ * frame list pointer -> iso td's (if any) ->
+ * periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh
+ */
+static void uhci_insert_td_frame_list(struct uhci *uhci, struct uhci_td *td, unsigned framenum)
+{
+	unsigned long flags;
+
+	framenum %= UHCI_NUMFRAMES;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+	td->frame = framenum;
+
+	/* Is there a TD already mapped there? */
+	if (uhci->fl->frame_cpu[framenum]) {
+		struct uhci_td *ftd, *ltd;
+
+		ftd = uhci->fl->frame_cpu[framenum];
+		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
+
+		list_add_tail(&td->fl_list, &ftd->fl_list);
+
+		td->link = ltd->link;
+		mb();
+		ltd->link = td->dma_handle;
+	} else {
+		td->link = uhci->fl->frame[framenum];
+		mb();
+		uhci->fl->frame[framenum] = td->dma_handle;
+		uhci->fl->frame_cpu[framenum] = td;
+	}
+
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static void uhci_remove_td(struct uhci *uhci, struct uhci_td *td)
+{
+	unsigned long flags;
+
+	/* If it's not inserted, don't remove it */
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	if (td->frame == -1 && list_empty(&td->fl_list))
+		goto out;
+
+	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+		if (list_empty(&td->fl_list)) {
+			uhci->fl->frame[td->frame] = td->link;
+			uhci->fl->frame_cpu[td->frame] = NULL;
+		} else {
+			struct uhci_td *ntd;
+
+			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
+			uhci->fl->frame[td->frame] = ntd->dma_handle;
+			uhci->fl->frame_cpu[td->frame] = ntd;
+		}
+	} else {
+		struct uhci_td *ptd;
+
+		ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
+		ptd->link = td->link;
+	}
+
+	mb();
+	td->link = UHCI_PTR_TERM;
+
+	list_del_init(&td->fl_list);
+	td->frame = -1;
+
+out:
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+/*
+ * Inserts a td into qh list at the top.
+ */
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth)
+{
+	struct list_head *tmp, *head;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td, *ptd;
+
+	if (list_empty(&urbp->td_list))
+		return;
+
+	head = &urbp->td_list;
+	tmp = head->next;
+
+	/* Ordering isn't important here yet since the QH hasn't been */
+	/*  inserted into the schedule yet */
+	td = list_entry(tmp, struct uhci_td, list);
+
+	/* Add the first TD to the QH element pointer */
+	qh->element = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH);
+
+	ptd = td;
+
+	/* Then link the rest of the TD's */
+	tmp = tmp->next;
+	while (tmp != head) {
+		td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		ptd->link = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH);
+
+		ptd = td;
+	}
+
+	ptd->link = UHCI_PTR_TERM;
+}
+
+static void uhci_free_td(struct uhci *uhci, struct uhci_td *td)
+{
+	if (!list_empty(&td->list) || !list_empty(&td->fl_list))
+		dbg("td is still in URB list!");
+
+	if (td->dev)
+		usb_dec_dev_use(td->dev);
+
+	pci_pool_free(uhci->td_pool, td, td->dma_handle);
+}
+
+static struct uhci_qh *uhci_alloc_qh(struct uhci *uhci, struct usb_device *dev)
+{
+	dma_addr_t dma_handle;
+	struct uhci_qh *qh;
+
+	qh = pci_pool_alloc(uhci->qh_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
+	if (!qh)
+		return NULL;
+
+	qh->dma_handle = dma_handle;
+
+	qh->element = UHCI_PTR_TERM;
+	qh->link = UHCI_PTR_TERM;
+
+	qh->dev = dev;
+	qh->urbp = NULL;
+
+	INIT_LIST_HEAD(&qh->list);
+	INIT_LIST_HEAD(&qh->remove_list);
+
+	usb_inc_dev_use(dev);
+
+	return qh;
+}
+
+static void uhci_free_qh(struct uhci *uhci, struct uhci_qh *qh)
+{
+	if (!list_empty(&qh->list))
+		dbg("qh list not empty!");
+	if (!list_empty(&qh->remove_list))
+		dbg("qh still in remove_list!");
+
+	if (qh->dev)
+		usb_dec_dev_use(qh->dev);
+
+	pci_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+}
+
+/*
+ * MUST be called with uhci->frame_list_lock acquired
+ */
+static void _uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct list_head *head, *tmp;
+	struct uhci_qh *lqh;
+
+	/* Grab the last QH */
+	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
+
+	if (lqh->urbp) {
+		head = &lqh->urbp->queue_list;
+		tmp = head->next;
+		while (head != tmp) {
+			struct urb_priv *turbp =
+				list_entry(tmp, struct urb_priv, queue_list);
+
+			tmp = tmp->next;
+
+			turbp->qh->link = urbp->qh->dma_handle | UHCI_PTR_QH;
+		}
+	}
+
+	head = &urbp->queue_list;
+	tmp = head->next;
+	while (head != tmp) {
+		struct urb_priv *turbp =
+			list_entry(tmp, struct urb_priv, queue_list);
+
+		tmp = tmp->next;
+
+		turbp->qh->link = lqh->link;
+	}
+
+	urbp->qh->link = lqh->link;
+	mb();				/* Ordering is important */
+	lqh->link = urbp->qh->dma_handle | UHCI_PTR_QH;
+
+	list_add_tail(&urbp->qh->list, &skelqh->list);
+}
+
+static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	_uhci_insert_qh(uhci, skelqh, urb);
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh)
+{
+	unsigned long flags;
+	struct uhci_qh *pqh;
+
+	if (!qh)
+		return;
+
+	qh->urbp = NULL;
+
+	/* Only go through the hoops if it's actually linked in */
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+	if (!list_empty(&qh->list)) {
+		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
+
+		if (pqh->urbp) {
+			struct list_head *head, *tmp;
+
+			head = &pqh->urbp->queue_list;
+			tmp = head->next;
+			while (head != tmp) {
+				struct urb_priv *turbp =
+					list_entry(tmp, struct urb_priv, queue_list);
+
+				tmp = tmp->next;
+
+				turbp->qh->link = qh->link;
+			}
+		}
+
+		pqh->link = qh->link;
+		mb();
+		qh->element = qh->link = UHCI_PTR_TERM;
+
+		list_del_init(&qh->list);
+	}
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+
+	spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
+
+	/* Check to see if the remove list is empty. Set the IOC bit */
+	/* to force an interrupt so we can remove the QH */
+	if (list_empty(&uhci->qh_remove_list))
+		uhci_set_next_interrupt(uhci);
+
+	list_add(&qh->remove_list, &uhci->qh_remove_list);
+
+	spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags);
+}
+
+static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct list_head *head, *tmp;
+
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (head != tmp) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		if (toggle)
+			set_bit(TD_TOKEN_TOGGLE, &td->info);
+		else
+			clear_bit(TD_TOKEN_TOGGLE, &td->info);
+
+		toggle ^= 1;
+	}
+
+	return toggle;
+}
+
+/* This function will append one URB's QH to another URB's QH. This is for */
+/*  USB_QUEUE_BULK support for bulk transfers and soon implicitily for */
+/*  control transfers */
+static void uhci_append_queued_urb(struct uhci *uhci, struct urb *eurb, struct urb *urb)
+{
+	struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
+	struct list_head *tmp;
+	struct uhci_td *lltd;
+	unsigned long flags;
+
+	eurbp = eurb->hcpriv;
+	urbp = urb->hcpriv;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+	/* Find the first URB in the queue */
+	if (eurbp->queued) {
+		struct list_head *head = &eurbp->queue_list;
+
+		tmp = head->next;
+		while (tmp != head) {
+			struct urb_priv *turbp =
+				list_entry(tmp, struct urb_priv, queue_list);
+
+			if (!turbp->queued)
+				break;
+
+			tmp = tmp->next;
+		}
+	} else
+		tmp = &eurbp->queue_list;
+
+	furbp = list_entry(tmp, struct urb_priv, queue_list);
+	lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
+
+	lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
+
+	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe),
+		uhci_fixup_toggle(urb, uhci_toggle(lltd->info) ^ 1));
+
+	/* All qh's in the queue need to link to the next queue */
+	urbp->qh->link = eurbp->qh->link;
+
+	mb();			/* Make sure we flush everything */
+	/* Only support bulk right now, so no depth */
+	lltd->link = urbp->qh->dma_handle | UHCI_PTR_QH;
+
+	list_add_tail(&urbp->queue_list, &furbp->queue_list);
+
+	urbp->queued = 1;
+
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static void uhci_delete_queued_urb(struct uhci *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp, *nurbp;
+	struct list_head *head, *tmp;
+	struct urb_priv *purbp;
+	struct uhci_td *pltd;
+	unsigned int toggle;
+	unsigned long flags;
+
+	urbp = urb->hcpriv;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+	if (list_empty(&urbp->queue_list))
+		goto out;
+
+	nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
+
+	/* Fix up the toggle for the next URB's */
+	if (!urbp->queued)
+		/* We set the toggle when we unlink */
+		toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+	else {
+		/* If we're in the middle of the queue, grab the toggle */
+		/*  from the TD previous to us */
+		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
+				queue_list);
+
+		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
+
+		toggle = uhci_toggle(pltd->info) ^ 1;
+	}
+
+	head = &urbp->queue_list;
+	tmp = head->next;
+	while (head != tmp) {
+		struct urb_priv *turbp;
+
+		turbp = list_entry(tmp, struct urb_priv, queue_list);
+
+		tmp = tmp->next;
+
+		if (!turbp->queued)
+			break;
+
+		toggle = uhci_fixup_toggle(turbp->urb, toggle);
+	}
+
+	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+		usb_pipeout(urb->pipe), toggle);
+
+	if (!urbp->queued) {
+		nurbp->queued = 0;
+
+		_uhci_insert_qh(uhci, uhci->skel_bulk_qh, nurbp->urb);
+	} else {
+		/* We're somewhere in the middle (or end). A bit trickier */
+		/*  than the head scenario */
+		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
+				queue_list);
+
+		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
+		if (nurbp->queued)
+			pltd->link = nurbp->qh->dma_handle | UHCI_PTR_QH;
+		else
+			/* The next URB happens to be the beginning, so */
+			/*  we're the last, end the chain */
+			pltd->link = UHCI_PTR_TERM;
+	}
+
+	list_del_init(&urbp->queue_list);
+
+out:
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static struct urb_priv *uhci_alloc_urb_priv(struct uhci *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp;
+
+	urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
+	if (!urbp) {
+		err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
+		return NULL;
+	}
+
+	memset((void *)urbp, 0, sizeof(*urbp));
+
+	urbp->inserttime = jiffies;
+	urbp->fsbrtime = jiffies;
+	urbp->urb = urb;
+	urbp->dev = urb->dev;
+	
+	INIT_LIST_HEAD(&urbp->td_list);
+	INIT_LIST_HEAD(&urbp->queue_list);
+	INIT_LIST_HEAD(&urbp->complete_list);
+
+	urb->hcpriv = urbp;
+
+	if (urb->dev != uhci->rh.dev) {
+		if (urb->transfer_buffer_length) {
+			urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
+				urb->transfer_buffer, urb->transfer_buffer_length,
+				usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
+				PCI_DMA_TODEVICE);
+			if (!urbp->transfer_buffer_dma_handle)
+				return NULL;
+		}
+
+		if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
+			urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
+				urb->setup_packet, sizeof(struct usb_ctrlrequest),
+				PCI_DMA_TODEVICE);
+			if (!urbp->setup_packet_dma_handle)
+				return NULL;
+		}
+	}
+
+	return urbp;
+}
+
+/*
+ * MUST be called with urb->lock acquired
+ */
+static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	td->urb = urb;
+
+	list_add_tail(&td->list, &urbp->td_list);
+}
+
+/*
+ * MUST be called with urb->lock acquired
+ */
+static void uhci_remove_td_from_urb(struct uhci_td *td)
+{
+	if (list_empty(&td->list))
+		return;
+
+	list_del_init(&td->list);
+
+	td->urb = NULL;
+}
+
+/*
+ * MUST be called with urb->lock acquired
+ */
+static void uhci_destroy_urb_priv(struct urb *urb)
+{
+	struct list_head *head, *tmp;
+	struct urb_priv *urbp;
+	struct uhci *uhci;
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+	if (!urbp)
+		return;
+
+	if (!urbp->dev || !urbp->dev->bus || !urbp->dev->bus->hcpriv) {
+		warn("uhci_destroy_urb_priv: urb %p belongs to disconnected device or bus?", urb);
+		return;
+	}
+
+	if (!list_empty(&urb->urb_list))
+		warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb);
+
+	if (!list_empty(&urbp->complete_list))
+		warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb);
+
+	uhci = urbp->dev->bus->hcpriv;
+
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		uhci_remove_td_from_urb(td);
+		uhci_remove_td(uhci, td);
+		uhci_free_td(uhci, td);
+	}
+
+	if (urbp->setup_packet_dma_handle) {
+		pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
+			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
+		urbp->setup_packet_dma_handle = 0;
+	}
+
+	if (urbp->transfer_buffer_dma_handle) {
+		pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
+			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
+			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+		urbp->transfer_buffer_dma_handle = 0;
+	}
+
+	urb->hcpriv = NULL;
+	kmem_cache_free(uhci_up_cachep, urbp);
+}
+
+static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
+{
+	unsigned long flags;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+	if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) {
+		urbp->fsbr = 1;
+		if (!uhci->fsbr++ && !uhci->fsbrtimeout)
+			uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH;
+	}
+
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
+{
+	unsigned long flags;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+	if ((!(urb->transfer_flags & USB_NO_FSBR)) && urbp->fsbr) {
+		urbp->fsbr = 0;
+		if (!--uhci->fsbr)
+			uhci->fsbrtimeout = jiffies + FSBR_DELAY;
+	}
+
+	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+/*
+ * Map status to standard result codes
+ *
+ * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
+ * <dir_out> is True for output TDs and False for input TDs.
+ */
+static int uhci_map_status(int status, int dir_out)
+{
+	if (!status)
+		return 0;
+	if (status & TD_CTRL_BITSTUFF)			/* Bitstuff error */
+		return -EPROTO;
+	if (status & TD_CTRL_CRCTIMEO) {		/* CRC/Timeout */
+		if (dir_out)
+			return -ETIMEDOUT;
+		else
+			return -EILSEQ;
+	}
+	if (status & TD_CTRL_NAK)			/* NAK */
+		return -ETIMEDOUT;
+	if (status & TD_CTRL_BABBLE)			/* Babble */
+		return -EOVERFLOW;
+	if (status & TD_CTRL_DBUFERR)			/* Buffer error */
+		return -ENOSR;
+	if (status & TD_CTRL_STALLED)			/* Stalled */
+		return -EPIPE;
+	if (status & TD_CTRL_ACTIVE)			/* Active */
+		return 0;
+
+	return -EINVAL;
+}
+
+/*
+ * Control transfers
+ */
+static int uhci_submit_control(struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct uhci_td *td;
+	struct uhci_qh *qh;
+	unsigned long destination, status;
+	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	int len = urb->transfer_buffer_length;
+	dma_addr_t data = urbp->transfer_buffer_dma_handle;
+
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+
+	/* 3 errors */
+	status = TD_CTRL_ACTIVE | (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+
+	/*
+	 * Build the TD for the control request
+	 */
+	td = uhci_alloc_td(uhci, urb->dev);
+	if (!td)
+		return -ENOMEM;
+
+	uhci_add_td_to_urb(urb, td);
+	uhci_fill_td(td, status, destination | (7 << 21),
+		urbp->setup_packet_dma_handle);
+
+	/*
+	 * If direction is "send", change the frame from SETUP (0x2D)
+	 * to OUT (0xE1). Else change it from SETUP to IN (0x69).
+	 */
+	destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe));
+
+	if (!(urb->transfer_flags & USB_DISABLE_SPD))
+		status |= TD_CTRL_SPD;
+
+	/*
+	 * Build the DATA TD's
+	 */
+	while (len > 0) {
+		int pktsze = len;
+
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		/* Alternate Data0/1 (start with Data1) */
+		destination ^= 1 << TD_TOKEN_TOGGLE;
+	
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | ((pktsze - 1) << 21),
+			data);
+
+		data += pktsze;
+		len -= pktsze;
+	}
+
+	/*
+	 * Build the final TD for control status 
+	 */
+	td = uhci_alloc_td(uhci, urb->dev);
+	if (!td)
+		return -ENOMEM;
+
+	/*
+	 * It's IN if the pipe is an output pipe or we're not expecting
+	 * data back.
+	 */
+	destination &= ~TD_TOKEN_PID_MASK;
+	if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
+		destination |= USB_PID_IN;
+	else
+		destination |= USB_PID_OUT;
+
+	destination |= 1 << TD_TOKEN_TOGGLE;		/* End in Data1 */
+
+	status &= ~TD_CTRL_SPD;
+
+	uhci_add_td_to_urb(urb, td);
+	uhci_fill_td(td, status | TD_CTRL_IOC,
+		destination | (UHCI_NULL_DATA_SIZE << 21), 0);
+
+	qh = uhci_alloc_qh(uhci, urb->dev);
+	if (!qh)
+		return -ENOMEM;
+
+	urbp->qh = qh;
+	qh->urbp = urbp;
+
+	/* Low speed or small transfers gets a different queue and treatment */
+	if (urb->dev->speed == USB_SPEED_LOW) {
+		uhci_insert_tds_in_qh(qh, urb, 0);
+		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
+	} else {
+		uhci_insert_tds_in_qh(qh, urb, 1);
+		uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb);
+		uhci_inc_fsbr(uhci, urb);
+	}
+
+	return -EINPROGRESS;
+}
+
+static int usb_control_retrigger_status(struct urb *urb);
+
+static int uhci_result_control(struct urb *urb)
+{
+	struct list_head *tmp, *head;
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci_td *td;
+	unsigned int status;
+	int ret = 0;
+
+	if (list_empty(&urbp->td_list))
+		return -EINVAL;
+
+	head = &urbp->td_list;
+
+	if (urbp->short_control_packet) {
+		tmp = head->prev;
+		goto status_phase;
+	}
+
+	tmp = head->next;
+	td = list_entry(tmp, struct uhci_td, list);
+
+	/* The first TD is the SETUP phase, check the status, but skip */
+	/*  the count */
+	status = uhci_status_bits(td->status);
+	if (status & TD_CTRL_ACTIVE)
+		return -EINPROGRESS;
+
+	if (status)
+		goto td_error;
+
+	urb->actual_length = 0;
+
+	/* The rest of the TD's (but the last) are data */
+	tmp = tmp->next;
+	while (tmp != head && tmp->next != head) {
+		td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		if (urbp->fsbr_timeout && (td->status & TD_CTRL_IOC) &&
+		    !(td->status & TD_CTRL_ACTIVE)) {
+			uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
+			urbp->fsbr_timeout = 0;
+			urbp->fsbrtime = jiffies;
+			clear_bit(TD_CTRL_IOC_BIT, &td->status);
+		}
+
+		status = uhci_status_bits(td->status);
+		if (status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		urb->actual_length += uhci_actual_length(td->status);
+
+		if (status)
+			goto td_error;
+
+		/* Check to see if we received a short packet */
+		if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) {
+			if (urb->transfer_flags & USB_DISABLE_SPD) {
+				ret = -EREMOTEIO;
+				goto err;
+			}
+
+			if (uhci_packetid(td->info) == USB_PID_IN)
+				return usb_control_retrigger_status(urb);
+			else
+				return 0;
+		}
+	}
+
+status_phase:
+	td = list_entry(tmp, struct uhci_td, list);
+
+	/* Control status phase */
+	status = uhci_status_bits(td->status);
+
+#ifdef I_HAVE_BUGGY_APC_BACKUPS
+	/* APC BackUPS Pro kludge */
+	/* It tries to send all of the descriptor instead of the amount */
+	/*  we requested */
+	if (td->status & TD_CTRL_IOC &&	/* IOC is masked out by uhci_status_bits */
+	    status & TD_CTRL_ACTIVE &&
+	    status & TD_CTRL_NAK)
+		return 0;
+#endif
+
+	if (status & TD_CTRL_ACTIVE)
+		return -EINPROGRESS;
+
+	if (status)
+		goto td_error;
+
+	return 0;
+
+td_error:
+	ret = uhci_map_status(status, uhci_packetout(td->info));
+	if (ret == -EPIPE)
+		/* endpoint has stalled - mark it halted */
+		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
+	    			uhci_packetout(td->info));
+
+err:
+	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+		/* Some debugging code */
+		dbg("uhci_result_control() failed with status %x", status);
+
+		if (errbuf) {
+			/* Print the chain for debugging purposes */
+			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+
+			lprintk(errbuf);
+		}
+	}
+
+	return ret;
+}
+
+static int usb_control_retrigger_status(struct urb *urb)
+{
+	struct list_head *tmp, *head;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci *uhci = urb->dev->bus->hcpriv;
+
+	urbp->short_control_packet = 1;
+
+	/* Create a new QH to avoid pointer overwriting problems */
+	uhci_remove_qh(uhci, urbp->qh);
+
+	/* Delete all of the TD's except for the status TD at the end */
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (tmp != head && tmp->next != head) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		uhci_remove_td_from_urb(td);
+		uhci_remove_td(uhci, td);
+		uhci_free_td(uhci, td);
+	}
+
+	urbp->qh = uhci_alloc_qh(uhci, urb->dev);
+	if (!urbp->qh) {
+		err("unable to allocate new QH for control retrigger");
+		return -ENOMEM;
+	}
+
+	urbp->qh->urbp = urbp;
+
+	/* One TD, who cares about Breadth first? */
+	uhci_insert_tds_in_qh(urbp->qh, urb, 0);
+
+	/* Low speed or small transfers gets a different queue and treatment */
+	if (urb->dev->speed == USB_SPEED_LOW)
+		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
+	else
+		uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb);
+
+	return -EINPROGRESS;
+}
+
+/*
+ * Interrupt transfers
+ */
+static int uhci_submit_interrupt(struct urb *urb)
+{
+	struct uhci_td *td;
+	unsigned long destination, status;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
+		return -EINVAL;
+
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOC;
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+
+	td = uhci_alloc_td(uhci, urb->dev);
+	if (!td)
+		return -ENOMEM;
+
+	destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+	destination |= ((urb->transfer_buffer_length - 1) << 21);
+
+	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+
+	uhci_add_td_to_urb(urb, td);
+	uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle);
+
+	uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td);
+
+	return -EINPROGRESS;
+}
+
+static int uhci_result_interrupt(struct urb *urb)
+{
+	struct list_head *tmp, *head;
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci_td *td;
+	unsigned int status;
+	int ret = 0;
+
+	urb->actual_length = 0;
+
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (tmp != head) {
+		td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		if (urbp->fsbr_timeout && (td->status & TD_CTRL_IOC) &&
+		    !(td->status & TD_CTRL_ACTIVE)) {
+			uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
+			urbp->fsbr_timeout = 0;
+			urbp->fsbrtime = jiffies;
+			clear_bit(TD_CTRL_IOC_BIT, &td->status);
+		}
+
+		status = uhci_status_bits(td->status);
+		if (status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		urb->actual_length += uhci_actual_length(td->status);
+
+		if (status)
+			goto td_error;
+
+		if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) {
+			if (urb->transfer_flags & USB_DISABLE_SPD) {
+				ret = -EREMOTEIO;
+				goto err;
+			} else
+				return 0;
+		}
+	}
+
+	return 0;
+
+td_error:
+	ret = uhci_map_status(status, uhci_packetout(td->info));
+	if (ret == -EPIPE)
+		/* endpoint has stalled - mark it halted */
+		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
+	    			uhci_packetout(td->info));
+
+err:
+	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+		/* Some debugging code */
+		dbg("uhci_result_interrupt/bulk() failed with status %x",
+			status);
+
+		if (errbuf) {
+			/* Print the chain for debugging purposes */
+			if (urbp->qh)
+				uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+			else
+				uhci_show_td(td, errbuf, ERRBUF_LEN, 0);
+
+			lprintk(errbuf);
+		}
+	}
+
+	return ret;
+}
+
+static void uhci_reset_interrupt(struct urb *urb)
+{
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td;
+	unsigned long flags;
+
+	spin_lock_irqsave(&urb->lock, flags);
+
+	/* Root hub is special */
+	if (urb->dev == uhci->rh.dev)
+		goto out;
+
+	td = list_entry(urbp->td_list.next, struct uhci_td, list);
+
+	td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
+	td->info &= ~(1 << TD_TOKEN_TOGGLE);
+	td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+
+out:
+	urb->status = -EINPROGRESS;
+
+	spin_unlock_irqrestore(&urb->lock, flags);
+}
+
+/*
+ * Bulk transfers
+ */
+static int uhci_submit_bulk(struct urb *urb, struct urb *eurb)
+{
+	struct uhci_td *td;
+	struct uhci_qh *qh;
+	unsigned long destination, status;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	int len = urb->transfer_buffer_length;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	dma_addr_t data = urbp->transfer_buffer_dma_handle;
+
+	if (len < 0)
+		return -EINVAL;
+
+	/* Can't have low speed bulk transfers */
+	if (urb->dev->speed == USB_SPEED_LOW)
+		return -EINVAL;
+
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+	/* 3 errors */
+	status = TD_CTRL_ACTIVE | (3 << TD_CTRL_C_ERR_SHIFT);
+
+	if (!(urb->transfer_flags & USB_DISABLE_SPD))
+		status |= TD_CTRL_SPD;
+
+	/*
+	 * Build the DATA TD's
+	 */
+	do {	/* Allow zero length packets */
+		int pktsze = len;
+
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination |
+			(((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) |
+			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
+			data);
+
+		data += pktsze;
+		len -= maxsze;
+
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			usb_pipeout(urb->pipe));
+	} while (len > 0);
+
+	/*
+	 * USB_ZERO_PACKET means adding a 0-length packet, if
+	 * direction is OUT and the transfer_length was an
+	 * exact multiple of maxsze, hence
+	 * (len = transfer_length - N * maxsze) == 0
+	 * however, if transfer_length == 0, the zero packet
+	 * was already prepared above.
+	 */
+	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) &&
+	   !len && urb->transfer_buffer_length) {
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination |
+			(UHCI_NULL_DATA_SIZE << 21) |
+			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
+			data);
+
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			usb_pipeout(urb->pipe));
+	}
+
+	/* Set the flag on the last packet */
+	td->status |= TD_CTRL_IOC;
+
+	qh = uhci_alloc_qh(uhci, urb->dev);
+	if (!qh)
+		return -ENOMEM;
+
+	urbp->qh = qh;
+	qh->urbp = urbp;
+
+	/* Always assume breadth first */
+	uhci_insert_tds_in_qh(qh, urb, 1);
+
+	if (urb->transfer_flags & USB_QUEUE_BULK && eurb)
+		uhci_append_queued_urb(uhci, eurb, urb);
+	else
+		uhci_insert_qh(uhci, uhci->skel_bulk_qh, urb);
+
+	uhci_inc_fsbr(uhci, urb);
+
+	return -EINPROGRESS;
+}
+
+/* We can use the result interrupt since they're identical */
+#define uhci_result_bulk uhci_result_interrupt
+
+/*
+ * Isochronous transfers
+ */
+static int isochronous_find_limits(struct urb *urb, unsigned int *start, unsigned int *end)
+{
+	struct urb *last_urb = NULL;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct list_head *tmp, *head;
+	int ret = 0;
+
+	head = &uhci->urb_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *u = list_entry(tmp, struct urb, urb_list);
+
+		tmp = tmp->next;
+
+		/* look for pending URB's with identical pipe handle */
+		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
+		    (u->status == -EINPROGRESS) && (u != urb)) {
+			if (!last_urb)
+				*start = u->start_frame;
+			last_urb = u;
+		}
+	}
+
+	if (last_urb) {
+		*end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
+		ret = 0;
+	} else
+		ret = -1;	/* no previous urb found */
+
+	return ret;
+}
+
+static int isochronous_find_start(struct urb *urb)
+{
+	int limits;
+	unsigned int start = 0, end = 0;
+
+	if (urb->number_of_packets > 900)	/* 900? Why? */
+		return -EFBIG;
+
+	limits = isochronous_find_limits(urb, &start, &end);
+
+	if (urb->transfer_flags & USB_ISO_ASAP) {
+		if (limits) {
+			int curframe;
+
+			curframe = uhci_get_current_frame_number(urb->dev) % UHCI_NUMFRAMES;
+			urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES;
+		} else
+			urb->start_frame = end;
+	} else {
+		urb->start_frame %= UHCI_NUMFRAMES;
+		/* FIXME: Sanity check */
+	}
+
+	return 0;
+}
+
+/*
+ * Isochronous transfers
+ */
+static int uhci_submit_isochronous(struct urb *urb)
+{
+	struct uhci_td *td;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	int i, ret, framenum;
+	int status, destination;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+	ret = isochronous_find_start(urb);
+	if (ret)
+		return ret;
+
+	framenum = urb->start_frame;
+	for (i = 0; i < urb->number_of_packets; i++, framenum++) {
+		if (!urb->iso_frame_desc[i].length)
+			continue;
+
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | ((urb->iso_frame_desc[i].length - 1) << 21),
+			urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset);
+
+		if (i + 1 >= urb->number_of_packets)
+			td->status |= TD_CTRL_IOC;
+
+		uhci_insert_td_frame_list(uhci, td, framenum);
+	}
+
+	return -EINPROGRESS;
+}
+
+static int uhci_result_isochronous(struct urb *urb)
+{
+	struct list_head *tmp, *head;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	int status;
+	int i, ret = 0;
+
+	urb->actual_length = 0;
+
+	i = 0;
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+		int actlength;
+
+		tmp = tmp->next;
+
+		if (td->status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		actlength = uhci_actual_length(td->status);
+		urb->iso_frame_desc[i].actual_length = actlength;
+		urb->actual_length += actlength;
+
+		status = uhci_map_status(uhci_status_bits(td->status), usb_pipeout(urb->pipe));
+		urb->iso_frame_desc[i].status = status;
+		if (status) {
+			urb->error_count++;
+			ret = status;
+		}
+
+		i++;
+	}
+
+	return ret;
+}
+
+/*
+ * MUST be called with uhci->urb_list_lock acquired
+ */
+static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb)
+{
+	struct list_head *tmp, *head;
+
+	/* We don't match Isoc transfers since they are special */
+	if (usb_pipeisoc(urb->pipe))
+		return NULL;
+
+	head = &uhci->urb_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *u = list_entry(tmp, struct urb, urb_list);
+
+		tmp = tmp->next;
+
+		if (u->dev == urb->dev && u->pipe == urb->pipe &&
+		    u->status == -EINPROGRESS)
+			return u;
+	}
+
+	return NULL;
+}
+
+static int uhci_submit_urb(struct urb *urb, int mem_flags)
+{
+	int ret = -EINVAL;
+	struct uhci *uhci;
+	unsigned long flags;
+	struct urb *eurb;
+	int bustime;
+
+	if (!urb)
+		return -EINVAL;
+
+	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
+		warn("uhci_submit_urb: urb %p belongs to disconnected device or bus?", urb);
+		return -ENODEV;
+	}
+
+	/* increment the reference count of the urb, as we now also control it */
+	urb = usb_get_urb(urb);
+
+	uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+	INIT_LIST_HEAD(&urb->urb_list);
+	usb_inc_dev_use(urb->dev);
+
+	spin_lock_irqsave(&uhci->urb_list_lock, flags);
+	spin_lock(&urb->lock);
+
+	if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
+	    urb->status == -ECONNABORTED) {
+		dbg("uhci_submit_urb: urb not available to submit (status = %d)", urb->status);
+		/* Since we can have problems on the out path */
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+		usb_dec_dev_use(urb->dev);
+		usb_put_urb(urb);
+
+		return ret;
+	}
+
+	if (!uhci_alloc_urb_priv(uhci, urb)) {
+		ret = -ENOMEM;
+
+		goto out;
+	}
+
+	eurb = uhci_find_urb_ep(uhci, urb);
+	if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
+		ret = -ENXIO;
+
+		goto out;
+	}
+
+	/* Short circuit the virtual root hub */
+	if (urb->dev == uhci->rh.dev) {
+		ret = rh_submit_urb(urb);
+
+		goto out;
+	}
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		ret = uhci_submit_control(urb);
+		break;
+	case PIPE_INTERRUPT:
+		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
+			bustime = usb_check_bandwidth(urb->dev, urb);
+			if (bustime < 0)
+				ret = bustime;
+			else {
+				ret = uhci_submit_interrupt(urb);
+				if (ret == -EINPROGRESS)
+					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+			}
+		} else		/* bandwidth is already set */
+			ret = uhci_submit_interrupt(urb);
+		break;
+	case PIPE_BULK:
+		ret = uhci_submit_bulk(urb, eurb);
+		break;
+	case PIPE_ISOCHRONOUS:
+		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
+			if (urb->number_of_packets <= 0) {
+				ret = -EINVAL;
+				break;
+			}
+			bustime = usb_check_bandwidth(urb->dev, urb);
+			if (bustime < 0) {
+				ret = bustime;
+				break;
+			}
+
+			ret = uhci_submit_isochronous(urb);
+			if (ret == -EINPROGRESS)
+				usb_claim_bandwidth(urb->dev, urb, bustime, 1);
+		} else		/* bandwidth is already set */
+			ret = uhci_submit_isochronous(urb);
+		break;
+	}
+
+out:
+	urb->status = ret;
+
+	if (ret == -EINPROGRESS) {
+		/* We use _tail to make find_urb_ep more efficient */
+		list_add_tail(&urb->urb_list, &uhci->urb_list);
+
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+		return 0;
+	}
+
+	uhci_unlink_generic(uhci, urb);
+
+	spin_unlock(&urb->lock);
+	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+	/* Only call completion if it was successful */
+	if (!ret)
+		uhci_call_completion(urb);
+
+	return ret;
+}
+
+/*
+ * Return the result of a transfer
+ *
+ * MUST be called with urb_list_lock acquired
+ */
+static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
+{
+	int ret = -EINVAL;
+	unsigned long flags;
+	struct urb_priv *urbp;
+
+	/* The root hub is special */
+	if (urb->dev == uhci->rh.dev)
+		return;
+
+	spin_lock_irqsave(&urb->lock, flags);
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+
+	if (urb->status != -EINPROGRESS) {
+		info("uhci_transfer_result: called for URB %p not in flight?", urb);
+		goto out;
+	}
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		ret = uhci_result_control(urb);
+		break;
+	case PIPE_INTERRUPT:
+		ret = uhci_result_interrupt(urb);
+		break;
+	case PIPE_BULK:
+		ret = uhci_result_bulk(urb);
+		break;
+	case PIPE_ISOCHRONOUS:
+		ret = uhci_result_isochronous(urb);
+		break;
+	}
+
+	urbp->status = ret;
+
+	if (ret == -EINPROGRESS)
+		goto out;
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+	case PIPE_ISOCHRONOUS:
+		/* Release bandwidth for Interrupt or Isoc. transfers */
+		/* Spinlock needed ? */
+		if (urb->bandwidth)
+			usb_release_bandwidth(urb->dev, urb, 1);
+		uhci_unlink_generic(uhci, urb);
+		break;
+	case PIPE_INTERRUPT:
+		/* Interrupts are an exception */
+		if (urb->interval)
+			goto out_complete;
+
+		/* Release bandwidth for Interrupt or Isoc. transfers */
+		/* Spinlock needed ? */
+		if (urb->bandwidth)
+			usb_release_bandwidth(urb->dev, urb, 0);
+		uhci_unlink_generic(uhci, urb);
+		break;
+	default:
+		info("uhci_transfer_result: unknown pipe type %d for urb %p\n",
+			usb_pipetype(urb->pipe), urb);
+	}
+
+	/* Remove it from uhci->urb_list */
+	list_del_init(&urb->urb_list);
+
+out_complete:
+	uhci_add_complete(urb);
+
+out:
+	spin_unlock_irqrestore(&urb->lock, flags);
+}
+
+/*
+ * MUST be called with urb->lock acquired
+ */
+static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
+{
+	struct list_head *head, *tmp;
+	struct urb_priv *urbp = urb->hcpriv;
+	int prevactive = 1;
+
+	/* We can get called when urbp allocation fails, so check */
+	if (!urbp)
+		return;
+
+	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
+
+	/*
+	 * Now we need to find out what the last successful toggle was
+	 * so we can update the local data toggle for the next transfer
+	 *
+	 * There's 3 way's the last successful completed TD is found:
+	 *
+	 * 1) The TD is NOT active and the actual length < expected length
+	 * 2) The TD is NOT active and it's the last TD in the chain
+	 * 3) The TD is active and the previous TD is NOT active
+	 *
+	 * Control and Isochronous ignore the toggle, so this is safe
+	 * for all types
+	 */
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		if (!(td->status & TD_CTRL_ACTIVE) &&
+		    (uhci_actual_length(td->status) < uhci_expected_length(td->info) ||
+		    tmp == head))
+			usb_settoggle(urb->dev, uhci_endpoint(td->info),
+				uhci_packetout(td->info),
+				uhci_toggle(td->info) ^ 1);
+		else if ((td->status & TD_CTRL_ACTIVE) && !prevactive)
+			usb_settoggle(urb->dev, uhci_endpoint(td->info),
+				uhci_packetout(td->info),
+				uhci_toggle(td->info));
+
+		prevactive = td->status & TD_CTRL_ACTIVE;
+	}
+
+	uhci_delete_queued_urb(uhci, urb);
+
+	/* The interrupt loop will reclaim the QH's */
+	uhci_remove_qh(uhci, urbp->qh);
+	urbp->qh = NULL;
+}
+
+static int uhci_unlink_urb(struct urb *urb)
+{
+	struct uhci *uhci;
+	unsigned long flags;
+	struct urb_priv *urbp = urb->hcpriv;
+
+	if (!urb)
+		return -EINVAL;
+
+	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
+		return -ENODEV;
+
+	uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+	spin_lock_irqsave(&uhci->urb_list_lock, flags);
+	spin_lock(&urb->lock);
+
+	/* Release bandwidth for Interrupt or Isoc. transfers */
+	/* Spinlock needed ? */
+	if (urb->bandwidth) {
+		switch (usb_pipetype(urb->pipe)) {
+		case PIPE_INTERRUPT:
+			usb_release_bandwidth(urb->dev, urb, 0);
+			break;
+		case PIPE_ISOCHRONOUS:
+			usb_release_bandwidth(urb->dev, urb, 1);
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (urb->status != -EINPROGRESS) {
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+		return 0;
+	}
+
+	list_del_init(&urb->urb_list);
+
+	uhci_unlink_generic(uhci, urb);
+
+	/* Short circuit the virtual root hub */
+	if (urb->dev == uhci->rh.dev) {
+		rh_unlink_urb(urb);
+
+		spin_unlock(&urb->lock);
+		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+		uhci_call_completion(urb);
+	} else {
+		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+			urbp->status = urb->status = -ECONNABORTED;
+
+			spin_lock(&uhci->urb_remove_list_lock);
+
+			/* If we're the first, set the next interrupt bit */
+			if (list_empty(&uhci->urb_remove_list))
+				uhci_set_next_interrupt(uhci);
+			
+			list_add(&urb->urb_list, &uhci->urb_remove_list);
+
+			spin_unlock(&uhci->urb_remove_list_lock);
+
+			spin_unlock(&urb->lock);
+			spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+		} else {
+			urb->status = -ENOENT;
+
+			spin_unlock(&urb->lock);
+			spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+			if (in_interrupt()) {	/* wait at least 1 frame */
+				static int errorcount = 10;
+
+				if (errorcount--)
+					dbg("uhci_unlink_urb called from interrupt for urb %p", urb);
+				udelay(1000);
+			} else
+				schedule_timeout(1+1*HZ/1000); 
+
+			uhci_call_completion(urb);
+		}
+	}
+
+	return 0;
+}
+
+static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct list_head *head, *tmp;
+
+	uhci_dec_fsbr(uhci, urb);
+
+	urbp->fsbr_timeout = 1;
+
+	head = &urbp->td_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+		tmp = tmp->next;
+
+		if (td->status & TD_CTRL_ACTIVE) {
+			set_bit(TD_CTRL_IOC_BIT, &td->status);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * uhci_get_current_frame_number()
+ *
+ * returns the current frame number for a USB bus/controller.
+ */
+static int uhci_get_current_frame_number(struct usb_device *dev)
+{
+	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
+
+	return inw(uhci->io_addr + USBFRNUM);
+}
+
+struct usb_operations uhci_device_operations = {
+	allocate:		uhci_alloc_dev,
+	deallocate:		uhci_free_dev,
+	get_frame_number:	uhci_get_current_frame_number,
+	submit_urb:		uhci_submit_urb,
+	unlink_urb:		uhci_unlink_urb,
+};
+
+/* Virtual Root Hub */
+
+static __u8 root_hub_dev_des[] =
+{
+ 	0x12,			/*  __u8  bLength; */
+	0x01,			/*  __u8  bDescriptorType; Device */
+	0x00,			/*  __u16 bcdUSB; v1.0 */
+	0x01,
+	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,			/*  __u8  bDeviceSubClass; */
+	0x00,			/*  __u8  bDeviceProtocol; */
+	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x00,			/*  __u16 idVendor; */
+	0x00,
+	0x00,			/*  __u16 idProduct; */
+	0x00,
+	0x00,			/*  __u16 bcdDevice; */
+	0x00,
+	0x00,			/*  __u8  iManufacturer; */
+	0x02,			/*  __u8  iProduct; */
+	0x01,			/*  __u8  iSerialNumber; */
+	0x01			/*  __u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+	0x09,			/*  __u8  bLength; */
+	0x02,			/*  __u8  bDescriptorType; Configuration */
+	0x19,			/*  __u16 wTotalLength; */
+	0x00,
+	0x01,			/*  __u8  bNumInterfaces; */
+	0x01,			/*  __u8  bConfigurationValue; */
+	0x00,			/*  __u8  iConfiguration; */
+	0x40,			/*  __u8  bmAttributes;
+					Bit 7: Bus-powered, 6: Self-powered,
+					Bit 5 Remote-wakeup, 4..0: resvd */
+	0x00,			/*  __u8  MaxPower; */
+
+	/* interface */
+	0x09,			/*  __u8  if_bLength; */
+	0x04,			/*  __u8  if_bDescriptorType; Interface */
+	0x00,			/*  __u8  if_bInterfaceNumber; */
+	0x00,			/*  __u8  if_bAlternateSetting; */
+	0x01,			/*  __u8  if_bNumEndpoints; */
+	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,			/*  __u8  if_bInterfaceSubClass; */
+	0x00,			/*  __u8  if_bInterfaceProtocol; */
+	0x00,			/*  __u8  if_iInterface; */
+
+	/* endpoint */
+	0x07,			/*  __u8  ep_bLength; */
+	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
+	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
+	0x00,
+	0xff			/*  __u8  ep_bInterval; 255 ms */
+};
+
+static __u8 root_hub_hub_des[] =
+{
+	0x09,			/*  __u8  bLength; */
+	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
+	0x02,			/*  __u8  bNbrPorts; */
+	0x00,			/* __u16  wHubCharacteristics; */
+	0x00,
+	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
+	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
+	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
+	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
+static int rh_send_irq(struct urb *urb)
+{
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	unsigned int io_addr = uhci->io_addr;
+	unsigned long flags;
+	int i, len = 1;
+	__u16 data = 0;
+
+	spin_lock_irqsave(&urb->lock, flags);
+	for (i = 0; i < uhci->rh.numports; i++) {
+		data |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
+		len = (i + 1) / 8 + 1;
+	}
+
+	*(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
+	urb->actual_length = len;
+	urbp->status = 0;
+
+	spin_unlock_irqrestore(&urb->lock, flags);
+
+	if ((data > 0) && (uhci->rh.send != 0)) {
+		dbg("root-hub INT complete: port1: %x port2: %x data: %x",
+			inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data);
+		uhci_call_completion(urb);
+	}
+
+	return 0;
+}
+
+/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
+static int rh_init_int_timer(struct urb *urb);
+
+static void rh_int_timer_do(unsigned long ptr)
+{
+	struct urb *urb = (struct urb *)ptr;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct list_head list, *tmp, *head;
+	unsigned long flags;
+
+	if (uhci->rh.send)
+		rh_send_irq(urb);
+
+	INIT_LIST_HEAD(&list);
+
+	spin_lock_irqsave(&uhci->urb_list_lock, flags);
+	head = &uhci->urb_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *u = list_entry(tmp, struct urb, urb_list);
+		struct urb_priv *up = (struct urb_priv *)u->hcpriv;
+
+		tmp = tmp->next;
+
+		spin_lock(&u->lock);
+
+		/* Check if the FSBR timed out */
+		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
+			uhci_fsbr_timeout(uhci, u);
+
+		/* Check if the URB timed out */
+		if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) {
+			list_del(&u->urb_list);
+			list_add_tail(&u->urb_list, &list);
+		}
+
+		spin_unlock(&u->lock);
+	}
+	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
+
+	head = &list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *u = list_entry(tmp, struct urb, urb_list);
+
+		tmp = tmp->next;
+
+		u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
+		uhci_unlink_urb(u);
+	}
+
+	/* Really disable FSBR */
+	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
+		uhci->fsbrtimeout = 0;
+		uhci->skel_term_qh->link = UHCI_PTR_TERM;
+	}
+
+	/* enter global suspend if nothing connected */
+	if (!uhci->is_suspended && !ports_active(uhci))
+		suspend_hc(uhci);
+
+	rh_init_int_timer(urb);
+}
+
+/* Root Hub INTs are polled by this timer */
+static int rh_init_int_timer(struct urb *urb)
+{
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+	uhci->rh.interval = urb->interval;
+	init_timer(&uhci->rh.rh_int_timer);
+	uhci->rh.rh_int_timer.function = rh_int_timer_do;
+	uhci->rh.rh_int_timer.data = (unsigned long)urb;
+	uhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
+	add_timer(&uhci->rh.rh_int_timer);
+
+	return 0;
+}
+
+#define OK(x)			len = (x); break
+
+#define CLR_RH_PORTSTAT(x) \
+	status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
+	status = (status & 0xfff5) & ~(x); \
+	outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
+
+#define SET_RH_PORTSTAT(x) \
+	status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
+	status = (status & 0xfff5) | (x); \
+	outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
+
+
+/* Root Hub Control Pipe */
+static int rh_submit_urb(struct urb *urb)
+{
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	unsigned int pipe = urb->pipe;
+	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet;
+	void *data = urb->transfer_buffer;
+	int leni = urb->transfer_buffer_length;
+	int len = 0;
+	int status = 0;
+	int stat = 0;
+	int i;
+	unsigned int io_addr = uhci->io_addr;
+	__u16 cstatus;
+	__u16 bmRType_bReq;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+
+	if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
+		uhci->rh.urb = urb;
+		uhci->rh.send = 1;
+		uhci->rh.interval = urb->interval;
+		rh_init_int_timer(urb);
+
+		return -EINPROGRESS;
+	}
+
+	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
+	wValue = le16_to_cpu(cmd->wValue);
+	wIndex = le16_to_cpu(cmd->wIndex);
+	wLength = le16_to_cpu(cmd->wLength);
+
+	for (i = 0; i < 8; i++)
+		uhci->rh.c_p_r[i] = 0;
+
+	switch (bmRType_bReq) {
+		/* Request Destination:
+		   without flags: Device,
+		   RH_INTERFACE: interface,
+		   RH_ENDPOINT: endpoint,
+		   RH_CLASS means HUB here,
+		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
+		*/
+
+	case RH_GET_STATUS:
+		*(__u16 *)data = cpu_to_le16(1);
+		OK(2);
+	case RH_GET_STATUS | RH_INTERFACE:
+		*(__u16 *)data = cpu_to_le16(0);
+		OK(2);
+	case RH_GET_STATUS | RH_ENDPOINT:
+		*(__u16 *)data = cpu_to_le16(0);
+		OK(2);
+	case RH_GET_STATUS | RH_CLASS:
+		*(__u32 *)data = cpu_to_le32(0);
+		OK(4);		/* hub power */
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+		status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1));
+		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
+			((status & USBPORTSC_PEC) >> (3 - 1)) |
+			(uhci->rh.c_p_r[wIndex - 1] << (0 + 4));
+			status = (status & USBPORTSC_CCS) |
+			((status & USBPORTSC_PE) >> (2 - 1)) |
+			((status & USBPORTSC_SUSP) >> (12 - 2)) |
+			((status & USBPORTSC_PR) >> (9 - 4)) |
+			(1 << 8) |      /* power on */
+			((status & USBPORTSC_LSDA) << (-8 + 9));
+
+		*(__u16 *)data = cpu_to_le16(status);
+		*(__u16 *)(data + 2) = cpu_to_le16(cstatus);
+		OK(4);
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		switch (wValue) {
+		case RH_ENDPOINT_STALL:
+			OK(0);
+		}
+		break;
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		switch (wValue) {
+		case RH_C_HUB_OVER_CURRENT:
+			OK(0);	/* hub power over current */
+		}
+		break;
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case RH_PORT_ENABLE:
+			CLR_RH_PORTSTAT(USBPORTSC_PE);
+			OK(0);
+		case RH_PORT_SUSPEND:
+			CLR_RH_PORTSTAT(USBPORTSC_SUSP);
+			OK(0);
+		case RH_PORT_POWER:
+			OK(0);	/* port power */
+		case RH_C_PORT_CONNECTION:
+			SET_RH_PORTSTAT(USBPORTSC_CSC);
+			OK(0);
+		case RH_C_PORT_ENABLE:
+			SET_RH_PORTSTAT(USBPORTSC_PEC);
+			OK(0);
+		case RH_C_PORT_SUSPEND:
+			/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+			OK(0);
+		case RH_C_PORT_OVER_CURRENT:
+			OK(0);	/* port power over current */
+		case RH_C_PORT_RESET:
+			uhci->rh.c_p_r[wIndex - 1] = 0;
+			OK(0);
+		}
+		break;
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case RH_PORT_SUSPEND:
+			SET_RH_PORTSTAT(USBPORTSC_SUSP);
+			OK(0);
+		case RH_PORT_RESET:
+			SET_RH_PORTSTAT(USBPORTSC_PR);
+			mdelay(50);	/* USB v1.1 7.1.7.3 */
+			uhci->rh.c_p_r[wIndex - 1] = 1;
+			CLR_RH_PORTSTAT(USBPORTSC_PR);
+			udelay(10);
+			SET_RH_PORTSTAT(USBPORTSC_PE);
+			mdelay(10);
+			SET_RH_PORTSTAT(0xa);
+			OK(0);
+		case RH_PORT_POWER:
+			OK(0); /* port power ** */
+		case RH_PORT_ENABLE:
+			SET_RH_PORTSTAT(USBPORTSC_PE);
+			OK(0);
+		}
+		break;
+	case RH_SET_ADDRESS:
+		uhci->rh.devnum = wValue;
+		OK(0);
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+		case 0x01:	/* device descriptor */
+			len = min_t(unsigned int, leni,
+				  min_t(unsigned int,
+				      sizeof(root_hub_dev_des), wLength));
+			memcpy(data, root_hub_dev_des, len);
+			OK(len);
+		case 0x02:	/* configuration descriptor */
+			len = min_t(unsigned int, leni,
+				  min_t(unsigned int,
+				      sizeof(root_hub_config_des), wLength));
+			memcpy (data, root_hub_config_des, len);
+			OK(len);
+		case 0x03:	/* string descriptors */
+			len = usb_root_hub_string (wValue & 0xff,
+				uhci->io_addr, "UHCI-alt",
+				data, wLength);
+			if (len > 0) {
+				OK(min_t(int, leni, len));
+			} else 
+				stat = -EPIPE;
+		}
+		break;
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+		root_hub_hub_des[2] = uhci->rh.numports;
+		len = min_t(unsigned int, leni,
+			  min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
+		memcpy(data, root_hub_hub_des, len);
+		OK(len);
+	case RH_GET_CONFIGURATION:
+		*(__u8 *)data = 0x01;
+		OK(1);
+	case RH_SET_CONFIGURATION:
+		OK(0);
+	case RH_GET_INTERFACE | RH_INTERFACE:
+		*(__u8 *)data = 0x00;
+		OK(1);
+	case RH_SET_INTERFACE | RH_INTERFACE:
+		OK(0);
+	default:
+		stat = -EPIPE;
+	}
+
+	urb->actual_length = len;
+
+	return stat;
+}
+
+/*
+ * MUST be called with urb->lock acquired
+ */
+static int rh_unlink_urb(struct urb *urb)
+{
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+	if (uhci->rh.urb == urb) {
+		urb->status = -ENOENT;
+		uhci->rh.send = 0;
+		uhci->rh.urb = NULL;
+		del_timer(&uhci->rh.rh_int_timer);
+	}
+	return 0;
+}
+
+static void uhci_free_pending_qhs(struct uhci *uhci)
+{
+	struct list_head *tmp, *head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
+	head = &uhci->qh_remove_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list);
+
+		tmp = tmp->next;
+
+		list_del_init(&qh->remove_list);
+
+		uhci_free_qh(uhci, qh);
+	}
+	spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags);
+}
+
+static void uhci_call_completion(struct urb *urb)
+{
+	struct urb_priv *urbp;
+	struct usb_device *dev = urb->dev;
+	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
+	int is_ring = 0, killed, resubmit_interrupt, status;
+	struct urb *nurb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&urb->lock, flags);
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+	if (!urbp || !urb->dev) {
+		spin_unlock_irqrestore(&urb->lock, flags);
+		return;
+	}
+
+	killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
+			urb->status == -ECONNRESET);
+	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
+			urb->interval);
+
+	nurb = urb->next;
+	if (nurb && !killed) {
+		int count = 0;
+
+		while (nurb && nurb != urb && count < MAX_URB_LOOP) {
+			if (nurb->status == -ENOENT ||
+			    nurb->status == -ECONNABORTED ||
+			    nurb->status == -ECONNRESET) {
+				killed = 1;
+				break;
+			}
+
+			nurb = nurb->next;
+			count++;
+		}
+
+		if (count == MAX_URB_LOOP)
+			err("uhci_call_completion: too many linked URB's, loop? (first loop)");
+
+		/* Check to see if chain is a ring */
+		is_ring = (nurb == urb);
+	}
+
+	if (urbp->transfer_buffer_dma_handle)
+		pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
+			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
+			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+
+	if (urbp->setup_packet_dma_handle)
+		pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
+			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
+
+	status = urbp->status;
+	if (!resubmit_interrupt || killed)
+		/* We don't need urb_priv anymore */
+		uhci_destroy_urb_priv(urb);
+
+	if (!killed)
+		urb->status = status;
+
+	urb->dev = NULL;
+	spin_unlock_irqrestore(&urb->lock, flags);
+
+	if (urb->complete)
+		urb->complete(urb);
+
+	if (resubmit_interrupt)
+		/* Recheck the status. The completion handler may have */
+		/*  unlinked the resubmitting interrupt URB */
+		killed = (urb->status == -ENOENT ||
+			  urb->status == -ECONNABORTED ||
+			  urb->status == -ECONNRESET);
+
+	if (resubmit_interrupt && !killed) {
+		urb->dev = dev;
+		uhci_reset_interrupt(urb);
+	} else {
+		if (is_ring && !killed) {
+			urb->dev = dev;
+			uhci_submit_urb(urb, GFP_ATOMIC);
+		} else {
+			/* We decrement the usage count after we're done */
+			/*  with everything */
+			usb_dec_dev_use(dev);
+			usb_put_urb(urb);
+		}
+	}
+}
+
+static void uhci_finish_completion(struct uhci *uhci)
+{
+	struct list_head *tmp, *head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->complete_list_lock, flags);
+	head = &uhci->complete_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
+		struct urb *urb = urbp->urb;
+
+		list_del_init(&urbp->complete_list);
+		spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+
+		uhci_call_completion(urb);
+
+		spin_lock_irqsave(&uhci->complete_list_lock, flags);
+		head = &uhci->complete_list;
+		tmp = head->next;
+	}
+	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+}
+
+static void uhci_remove_pending_qhs(struct uhci *uhci)
+{
+	struct list_head *tmp, *head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->urb_remove_list_lock, flags);
+	head = &uhci->urb_remove_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *urb = list_entry(tmp, struct urb, urb_list);
+		struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+		tmp = tmp->next;
+
+		list_del_init(&urb->urb_list);
+
+		urbp->status = urb->status = -ECONNRESET;
+
+		uhci_add_complete(urb);
+	}
+	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
+}
+
+static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
+{
+	struct uhci *uhci = __uhci;
+	unsigned int io_addr = uhci->io_addr;
+	unsigned short status;
+	struct list_head *tmp, *head;
+
+	/*
+	 * Read the interrupt status, and write it back to clear the
+	 * interrupt cause
+	 */
+	status = inw(io_addr + USBSTS);
+	if (!status)	/* shared interrupt, not mine */
+		return;
+	outw(status, io_addr + USBSTS);		/* Clear it */
+
+	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
+		if (status & USBSTS_HSE)
+			err("%x: host system error, PCI problems?", io_addr);
+		if (status & USBSTS_HCPE)
+			err("%x: host controller process error. something bad happened", io_addr);
+		if ((status & USBSTS_HCH) && !uhci->is_suspended) {
+			err("%x: host controller halted. very bad", io_addr);
+			/* FIXME: Reset the controller, fix the offending TD */
+		}
+	}
+
+	if (status & USBSTS_RD)
+		wakeup_hc(uhci);
+
+	uhci_free_pending_qhs(uhci);
+
+	uhci_remove_pending_qhs(uhci);
+
+	uhci_clear_next_interrupt(uhci);
+
+	/* Walk the list of pending URB's to see which ones completed */
+	spin_lock(&uhci->urb_list_lock);
+	head = &uhci->urb_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *urb = list_entry(tmp, struct urb, urb_list);
+
+		tmp = tmp->next;
+
+		/* Checks the status and does all of the magic necessary */
+		uhci_transfer_result(uhci, urb);
+	}
+	spin_unlock(&uhci->urb_list_lock);
+
+	uhci_finish_completion(uhci);
+}
+
+static void reset_hc(struct uhci *uhci)
+{
+	unsigned int io_addr = uhci->io_addr;
+
+	/* Global reset for 50ms */
+	outw(USBCMD_GRESET, io_addr + USBCMD);
+	wait_ms(50);
+	outw(0, io_addr + USBCMD);
+	wait_ms(10);
+}
+
+static void suspend_hc(struct uhci *uhci)
+{
+	unsigned int io_addr = uhci->io_addr;
+
+	dbg("%x: suspend_hc", io_addr);
+
+	outw(USBCMD_EGSM, io_addr + USBCMD);
+
+	uhci->is_suspended = 1;
+}
+
+static void wakeup_hc(struct uhci *uhci)
+{
+	unsigned int io_addr = uhci->io_addr;
+	unsigned int status;
+
+	dbg("%x: wakeup_hc", io_addr);
+
+	outw(0, io_addr + USBCMD);
+	
+	/* wait for EOP to be sent */
+	status = inw(io_addr + USBCMD);
+	while (status & USBCMD_FGR)
+		status = inw(io_addr + USBCMD);
+
+	uhci->is_suspended = 0;
+
+	/* Run and mark it configured with a 64-byte max packet */
+	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+}
+
+static int ports_active(struct uhci *uhci)
+{
+	unsigned int io_addr = uhci->io_addr;
+	int connection = 0;
+	int i;
+
+	for (i = 0; i < uhci->rh.numports; i++)
+		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & 0x1);
+
+	return connection;
+}
+
+static void start_hc(struct uhci *uhci)
+{
+	unsigned int io_addr = uhci->io_addr;
+	int timeout = 1000;
+
+	/*
+	 * Reset the HC - this will force us to get a
+	 * new notification of any already connected
+	 * ports due to the virtual disconnect that it
+	 * implies.
+	 */
+	outw(USBCMD_HCRESET, io_addr + USBCMD);
+	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
+		if (!--timeout) {
+			printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n");
+			break;
+		}
+	}
+
+	/* Turn on all interrupts */
+	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
+		io_addr + USBINTR);
+
+	/* Start at frame 0 */
+	outw(0, io_addr + USBFRNUM);
+	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
+
+	/* Run and mark it configured with a 64-byte max packet */
+	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+}
+
+#ifdef CONFIG_PROC_FS
+static int uhci_num = 0;
+#endif
+
+static void free_uhci(struct uhci *uhci)
+{
+	kfree(uhci);
+}
+
+/*
+ * De-allocate all resources..
+ */
+static void release_uhci(struct uhci *uhci)
+{
+	int i;
+#ifdef CONFIG_PROC_FS
+	char buf[8];
+#endif
+
+	if (uhci->irq >= 0) {
+		free_irq(uhci->irq, uhci);
+		uhci->irq = -1;
+	}
+
+	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+		if (uhci->skelqh[i]) {
+			uhci_free_qh(uhci, uhci->skelqh[i]);
+			uhci->skelqh[i] = NULL;
+		}
+
+	for (i = 0; i < UHCI_NUM_SKELTD; i++)
+		if (uhci->skeltd[i]) {
+			uhci_free_td(uhci, uhci->skeltd[i]);
+			uhci->skeltd[i] = NULL;
+		}
+
+	if (uhci->qh_pool) {
+		pci_pool_destroy(uhci->qh_pool);
+		uhci->qh_pool = NULL;
+	}
+
+	if (uhci->td_pool) {
+		pci_pool_destroy(uhci->td_pool);
+		uhci->td_pool = NULL;
+	}
+
+	if (uhci->fl) {
+		pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
+		uhci->fl = NULL;
+	}
+
+	if (uhci->bus) {
+		usb_free_bus(uhci->bus);
+		uhci->bus = NULL;
+	}
+
+#ifdef CONFIG_PROC_FS
+	if (uhci->proc_entry) {
+		sprintf(buf, "hc%d", uhci->num);
+
+		remove_proc_entry(buf, uhci_proc_root);
+		uhci->proc_entry = NULL;
+	}
+#endif
+
+	free_uhci(uhci);
+}
+
+/*
+ * Allocate a frame list, and then setup the skeleton
+ *
+ * The hardware doesn't really know any difference
+ * in the queues, but the order does matter for the
+ * protocols higher up. The order is:
+ *
+ *  - any isochronous events handled before any
+ *    of the queues. We don't do that here, because
+ *    we'll create the actual TD entries on demand.
+ *  - The first queue is the interrupt queue.
+ *  - The second queue is the control queue, split into low and high speed
+ *  - The third queue is bulk queue.
+ *  - The fourth queue is the bandwidth reclamation queue, which loops back
+ *    to the high speed control queue.
+ */
+static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io_size)
+{
+	struct uhci *uhci;
+	int retval;
+	char buf[8], *bufp = buf;
+	int i, port;
+	struct usb_bus *bus;
+	dma_addr_t dma_handle;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *ent;
+#endif
+
+	retval = -ENODEV;
+	if (pci_enable_device(dev) < 0) {
+		err("couldn't enable PCI device");
+		goto err_enable_device;
+	}
+
+	if (!dev->irq) {
+		err("found UHCI device with no IRQ assigned. check BIOS settings!");
+		goto err_invalid_irq;
+	}
+
+	if (!pci_dma_supported(dev, 0xFFFFFFFF)) {
+		err("PCI subsystem doesn't support 32 bit addressing?");
+		goto err_pci_dma_supported;
+	}
+
+	retval = -EBUSY;
+	if (!request_region(io_addr, io_size, "usb-uhci")) {
+		err("couldn't allocate I/O range %x - %x", io_addr,
+			io_addr + io_size - 1);
+		goto err_request_region;
+	}
+
+	pci_set_master(dev);
+
+#ifndef __sparc__
+	sprintf(buf, "%d", dev->irq);
+#else
+	bufp = __irq_itoa(dev->irq);
+#endif
+	printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
+		io_addr, bufp);
+
+	if (pci_set_dma_mask(dev, 0xFFFFFFFF)) {
+		err("couldn't set PCI dma mask");
+		retval = -ENODEV;
+		goto err_pci_set_dma_mask;
+	}
+
+	uhci = kmalloc(sizeof(*uhci), GFP_KERNEL);
+	if (!uhci) {
+		err("couldn't allocate uhci structure");
+		retval = -ENOMEM;
+		goto err_alloc_uhci;
+	}
+
+	uhci->dev = dev;
+	uhci->irq = dev->irq;
+	uhci->io_addr = io_addr;
+	uhci->io_size = io_size;
+	pci_set_drvdata(dev, uhci);
+
+#ifdef CONFIG_PROC_FS
+	uhci->num = uhci_num++;
+
+	sprintf(buf, "hc%d", uhci->num);
+
+	ent = create_proc_entry(buf, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root);
+	if (!ent) {
+		err("couldn't create uhci proc entry");
+		retval = -ENOMEM;
+		goto err_create_proc_entry;
+	}
+
+	ent->data = uhci;
+	ent->proc_fops = &uhci_proc_operations;
+	ent->size = 0;
+	uhci->proc_entry = ent;
+#endif
+
+	/* Reset here so we don't get any interrupts from an old setup */
+	/*  or broken setup */
+	reset_hc(uhci);
+
+	uhci->fsbr = 0;
+	uhci->fsbrtimeout = 0;
+
+	uhci->is_suspended = 0;
+
+	spin_lock_init(&uhci->qh_remove_list_lock);
+	INIT_LIST_HEAD(&uhci->qh_remove_list);
+
+	spin_lock_init(&uhci->urb_remove_list_lock);
+	INIT_LIST_HEAD(&uhci->urb_remove_list);
+
+	spin_lock_init(&uhci->urb_list_lock);
+	INIT_LIST_HEAD(&uhci->urb_list);
+
+	spin_lock_init(&uhci->complete_list_lock);
+	INIT_LIST_HEAD(&uhci->complete_list);
+
+	spin_lock_init(&uhci->frame_list_lock);
+
+	/* We need exactly one page (per UHCI specs), how convenient */
+	/* We assume that one page is atleast 4k (1024 frames * 4 bytes) */
+#if PAGE_SIZE < (4 * 1024)
+#error PAGE_SIZE is not atleast 4k
+#endif
+	uhci->fl = pci_alloc_consistent(uhci->dev, sizeof(*uhci->fl), &dma_handle);
+	if (!uhci->fl) {
+		err("unable to allocate consistent memory for frame list");
+		goto err_alloc_fl;
+	}
+
+	memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
+
+	uhci->fl->dma_handle = dma_handle;
+
+	uhci->td_pool = pci_pool_create("uhci_td", uhci->dev,
+		sizeof(struct uhci_td), 16, 0, GFP_DMA | GFP_ATOMIC);
+	if (!uhci->td_pool) {
+		err("unable to create td pci_pool");
+		goto err_create_td_pool;
+	}
+
+	uhci->qh_pool = pci_pool_create("uhci_qh", uhci->dev,
+		sizeof(struct uhci_qh), 16, 0, GFP_DMA | GFP_ATOMIC);
+	if (!uhci->qh_pool) {
+		err("unable to create qh pci_pool");
+		goto err_create_qh_pool;
+	}
+
+	bus = usb_alloc_bus(&uhci_device_operations);
+	if (!bus) {
+		err("unable to allocate bus");
+		goto err_alloc_bus;
+	}
+
+	uhci->bus = bus;
+	bus->hcpriv = uhci;
+
+	usb_register_bus(uhci->bus);
+
+	/* Initialize the root hub */
+
+	/* UHCI specs says devices must have 2 ports, but goes on to say */
+	/*  they may have more but give no way to determine how many they */
+	/*  have. However, according to the UHCI spec, Bit 7 is always set */
+	/*  to 1. So we try to use this to our advantage */
+	for (port = 0; port < (uhci->io_size - 0x10) / 2; port++) {
+		unsigned int portstatus;
+
+		portstatus = inw(uhci->io_addr + 0x10 + (port * 2));
+		if (!(portstatus & 0x0080))
+			break;
+	}
+	if (debug)
+		info("detected %d ports", port);
+
+	/* This is experimental so anything less than 2 or greater than 8 is */
+	/*  something weird and we'll ignore it */
+	if (port < 2 || port > 8) {
+		info("port count misdetected? forcing to 2 ports");
+		port = 2;
+	}
+
+	uhci->rh.numports = port;
+
+	uhci->bus->root_hub = uhci->rh.dev = usb_alloc_dev(NULL, uhci->bus);
+	if (!uhci->rh.dev) {
+		err("unable to allocate root hub");
+		goto err_alloc_root_hub;
+	}
+
+	uhci->skeltd[0] = uhci_alloc_td(uhci, uhci->rh.dev);
+	if (!uhci->skeltd[0]) {
+		err("unable to allocate TD 0");
+		goto err_alloc_skeltd;
+	}
+
+	/*
+	 * 9 Interrupt queues; link int2 to int1, int4 to int2, etc
+	 * then link int1 to control and control to bulk
+	 */
+	for (i = 1; i < 9; i++) {
+		struct uhci_td *td;
+
+		td = uhci->skeltd[i] = uhci_alloc_td(uhci, uhci->rh.dev);
+		if (!td) {
+			err("unable to allocate TD %d", i);
+			goto err_alloc_skeltd;
+		}
+
+		uhci_fill_td(td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+		td->link = uhci->skeltd[i - 1]->dma_handle;
+	}
+
+	uhci->skel_term_td = uhci_alloc_td(uhci, uhci->rh.dev);
+	if (!uhci->skel_term_td) {
+		err("unable to allocate skel TD term");
+		goto err_alloc_skeltd;
+	}
+
+	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
+		uhci->skelqh[i] = uhci_alloc_qh(uhci, uhci->rh.dev);
+		if (!uhci->skelqh[i]) {
+			err("unable to allocate QH %d", i);
+			goto err_alloc_skelqh;
+		}
+	}
+
+	uhci_fill_td(uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+	uhci->skel_int1_td->link = uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH;
+
+	uhci->skel_ls_control_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH;
+	uhci->skel_ls_control_qh->element = UHCI_PTR_TERM;
+
+	uhci->skel_hs_control_qh->link = uhci->skel_bulk_qh->dma_handle | UHCI_PTR_QH;
+	uhci->skel_hs_control_qh->element = UHCI_PTR_TERM;
+
+	uhci->skel_bulk_qh->link = uhci->skel_term_qh->dma_handle | UHCI_PTR_QH;
+	uhci->skel_bulk_qh->element = UHCI_PTR_TERM;
+
+	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+	uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+	uhci->skel_term_td->link = uhci->skel_term_td->dma_handle;
+
+	uhci->skel_term_qh->link = UHCI_PTR_TERM;
+	uhci->skel_term_qh->element = uhci->skel_term_td->dma_handle;
+
+	/*
+	 * Fill the frame list: make all entries point to
+	 * the proper interrupt queue.
+	 *
+	 * This is probably silly, but it's a simple way to
+	 * scatter the interrupt queues in a way that gives
+	 * us a reasonable dynamic range for irq latencies.
+	 */
+	for (i = 0; i < UHCI_NUMFRAMES; i++) {
+		int irq = 0;
+
+		if (i & 1) {
+			irq++;
+			if (i & 2) {
+				irq++;
+				if (i & 4) { 
+					irq++;
+					if (i & 8) { 
+						irq++;
+						if (i & 16) {
+							irq++;
+							if (i & 32) {
+								irq++;
+								if (i & 64)
+									irq++;
+							}
+						}
+					}
+				}
+			}
+		}
+
+		/* Only place we don't use the frame list routines */
+		uhci->fl->frame[i] =  uhci->skeltd[irq]->dma_handle;
+	}
+
+	start_hc(uhci);
+
+	if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci))
+		goto err_request_irq;
+
+	/* disable legacy emulation */
+	pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
+	usb_connect(uhci->rh.dev);
+
+	if (usb_register_root_hub(uhci->rh.dev, &dev->dev) != 0) {
+		err("unable to start root hub");
+		retval = -ENOMEM;
+		goto err_start_root_hub;
+	}
+
+	return 0;
+
+/*
+ * error exits:
+ */
+err_start_root_hub:
+	free_irq(uhci->irq, uhci);
+	uhci->irq = -1;
+
+err_request_irq:
+	for (i = 0; i < UHCI_NUM_SKELQH; i++)
+		if (uhci->skelqh[i]) {
+			uhci_free_qh(uhci, uhci->skelqh[i]);
+			uhci->skelqh[i] = NULL;
+		}
+
+err_alloc_skelqh:
+	for (i = 0; i < UHCI_NUM_SKELTD; i++)
+		if (uhci->skeltd[i]) {
+			uhci_free_td(uhci, uhci->skeltd[i]);
+			uhci->skeltd[i] = NULL;
+		}
+
+err_alloc_skeltd:
+	usb_free_dev(uhci->rh.dev);
+	uhci->rh.dev = NULL;
+
+err_alloc_root_hub:
+	usb_free_bus(uhci->bus);
+	uhci->bus = NULL;
+
+err_alloc_bus:
+	pci_pool_destroy(uhci->qh_pool);
+	uhci->qh_pool = NULL;
+
+err_create_qh_pool:
+	pci_pool_destroy(uhci->td_pool);
+	uhci->td_pool = NULL;
+
+err_create_td_pool:
+	pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
+	uhci->fl = NULL;
+
+err_alloc_fl:
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(buf, uhci_proc_root);
+	uhci->proc_entry = NULL;
+
+err_create_proc_entry:
+	free_uhci(uhci);
+#endif
+
+err_alloc_uhci:
+
+err_pci_set_dma_mask:
+	release_region(io_addr, io_size);
+
+err_request_region:
+
+err_pci_dma_supported:
+
+err_invalid_irq:
+
+err_enable_device:
+
+	return retval;
+}
+
+static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int i;
+
+	/* Search for the IO base address.. */
+	for (i = 0; i < 6; i++) {
+		unsigned int io_addr = pci_resource_start(dev, i);
+		unsigned int io_size = pci_resource_len(dev, i);
+
+		/* IO address? */
+		if (!(pci_resource_flags(dev, i) & IORESOURCE_IO))
+			continue;
+
+		return alloc_uhci(dev, io_addr, io_size);
+	}
+
+	return -ENODEV;
+}
+
+static void __devexit uhci_pci_remove(struct pci_dev *dev)
+{
+	struct uhci *uhci = pci_get_drvdata(dev);
+
+	if (uhci->bus->root_hub)
+		usb_disconnect(&uhci->bus->root_hub);
+
+	usb_deregister_bus(uhci->bus);
+
+	/*
+	 * At this point, we're guaranteed that no new connects can be made
+	 * to this bus since there are no more parents
+	 */
+	uhci_free_pending_qhs(uhci);
+	uhci_remove_pending_qhs(uhci);
+
+	reset_hc(uhci);
+	release_region(uhci->io_addr, uhci->io_size);
+
+	uhci_free_pending_qhs(uhci);
+
+	release_uhci(uhci);
+}
+
+#ifdef CONFIG_PM
+static int uhci_pci_suspend(struct pci_dev *dev, u32 state)
+{
+	suspend_hc((struct uhci *) pci_get_drvdata(dev));
+	return 0;
+}
+
+static int uhci_pci_resume(struct pci_dev *dev)
+{
+	reset_hc((struct uhci *) pci_get_drvdata(dev));
+	start_hc((struct uhci *) pci_get_drvdata(dev));
+	return 0;
+}
+#endif
+
+static const struct pci_device_id __devinitdata uhci_pci_ids[] = { {
+
+	/* handle any USB UHCI controller */
+	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x00),
+	class_mask: 	~0,
+
+	/* no matter who makes it */
+	vendor:		PCI_ANY_ID,
+	device:		PCI_ANY_ID,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	}, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
+
+static struct pci_driver uhci_pci_driver = {
+	name:		"usb-uhci",
+	id_table:	uhci_pci_ids,
+
+	probe:		uhci_pci_probe,
+	remove:		__devexit_p(uhci_pci_remove),
+
+#ifdef	CONFIG_PM
+	suspend:	uhci_pci_suspend,
+	resume:		uhci_pci_resume,
+#endif	/* PM */
+};
+
+ 
+static int __init uhci_hcd_init(void)
+{
+	int retval = -ENOMEM;
+
+	info(DRIVER_DESC " " DRIVER_VERSION);
+
+	if (debug) {
+		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
+		if (!errbuf)
+			goto errbuf_failed;
+	}
+
+#ifdef CONFIG_PROC_FS
+	uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, 0);
+	if (!uhci_proc_root)
+		goto proc_failed;
+#endif
+
+	uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
+		sizeof(struct urb_priv), 0, 0, NULL, NULL);
+	if (!uhci_up_cachep)
+		goto up_failed;
+
+	retval = pci_module_init(&uhci_pci_driver);
+	if (retval)
+		goto init_failed;
+
+	return 0;
+
+init_failed:
+	if (kmem_cache_destroy(uhci_up_cachep))
+		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
+
+up_failed:
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("uhci", 0);
+
+proc_failed:
+#endif
+	if (errbuf)
+		kfree(errbuf);
+
+errbuf_failed:
+
+	return retval;
+}
+
+static void __exit uhci_hcd_cleanup(void) 
+{
+	pci_unregister_driver(&uhci_pci_driver);
+	
+	if (kmem_cache_destroy(uhci_up_cachep))
+		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("uhci", 0);
+#endif
+
+	if (errbuf)
+		kfree(errbuf);
+}
+
+module_init(uhci_hcd_init);
+module_exit(uhci_hcd_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/host/uhci.h b/drivers/usb/host/uhci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/uhci.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,441 @@
+#ifndef __LINUX_UHCI_H
+#define __LINUX_UHCI_H
+
+#include <linux/list.h>
+#include <linux/usb.h>
+
+/*
+ * Universal Host Controller Interface data structures and defines
+ */
+
+/* Command register */
+#define USBCMD		0
+#define   USBCMD_RS		0x0001	/* Run/Stop */
+#define   USBCMD_HCRESET	0x0002	/* Host reset */
+#define   USBCMD_GRESET		0x0004	/* Global reset */
+#define   USBCMD_EGSM		0x0008	/* Global Suspend Mode */
+#define   USBCMD_FGR		0x0010	/* Force Global Resume */
+#define   USBCMD_SWDBG		0x0020	/* SW Debug mode */
+#define   USBCMD_CF		0x0040	/* Config Flag (sw only) */
+#define   USBCMD_MAXP		0x0080	/* Max Packet (0 = 32, 1 = 64) */
+
+/* Status register */
+#define USBSTS		2
+#define   USBSTS_USBINT		0x0001	/* Interrupt due to IOC */
+#define   USBSTS_ERROR		0x0002	/* Interrupt due to error */
+#define   USBSTS_RD		0x0004	/* Resume Detect */
+#define   USBSTS_HSE		0x0008	/* Host System Error - basically PCI problems */
+#define   USBSTS_HCPE		0x0010	/* Host Controller Process Error - the scripts were buggy */
+#define   USBSTS_HCH		0x0020	/* HC Halted */
+
+/* Interrupt enable register */
+#define USBINTR		4
+#define   USBINTR_TIMEOUT	0x0001	/* Timeout/CRC error enable */
+#define   USBINTR_RESUME	0x0002	/* Resume interrupt enable */
+#define   USBINTR_IOC		0x0004	/* Interrupt On Complete enable */
+#define   USBINTR_SP		0x0008	/* Short packet interrupt enable */
+
+#define USBFRNUM	6
+#define USBFLBASEADD	8
+#define USBSOF		12
+
+/* USB port status and control registers */
+#define USBPORTSC1	16
+#define USBPORTSC2	18
+#define   USBPORTSC_CCS		0x0001	/* Current Connect Status ("device present") */
+#define   USBPORTSC_CSC		0x0002	/* Connect Status Change */
+#define   USBPORTSC_PE		0x0004	/* Port Enable */
+#define   USBPORTSC_PEC		0x0008	/* Port Enable Change */
+#define   USBPORTSC_LS		0x0030	/* Line Status */
+#define   USBPORTSC_RD		0x0040	/* Resume Detect */
+#define   USBPORTSC_LSDA	0x0100	/* Low Speed Device Attached */
+#define   USBPORTSC_PR		0x0200	/* Port Reset */
+#define   USBPORTSC_SUSP	0x1000	/* Suspend */
+
+/* Legacy support register */
+#define USBLEGSUP		0xc0
+#define   USBLEGSUP_DEFAULT	0x2000	/* only PIRQ enable set */
+
+#define UHCI_NULL_DATA_SIZE	0x7FF	/* for UHCI controller TD */
+
+#define UHCI_PTR_BITS		0x000F
+#define UHCI_PTR_TERM		0x0001
+#define UHCI_PTR_QH		0x0002
+#define UHCI_PTR_DEPTH		0x0004
+
+#define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
+#define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
+#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
+
+struct uhci_frame_list {
+	__u32 frame[UHCI_NUMFRAMES];
+
+	void *frame_cpu[UHCI_NUMFRAMES];
+
+	dma_addr_t dma_handle;
+};
+
+struct urb_priv;
+
+struct uhci_qh {
+	/* Hardware fields */
+	__u32 link;			/* Next queue */
+	__u32 element;			/* Queue element pointer */
+
+	/* Software fields */
+	dma_addr_t dma_handle;
+
+	struct usb_device *dev;
+	struct urb_priv *urbp;
+
+	struct list_head list;		/* P: uhci->frame_list_lock */
+	struct list_head remove_list;	/* P: uhci->remove_list_lock */
+} __attribute__((aligned(16)));
+
+/*
+ * for TD <status>:
+ */
+#define TD_CTRL_SPD		(1 << 29)	/* Short Packet Detect */
+#define TD_CTRL_C_ERR_MASK	(3 << 27)	/* Error Counter bits */
+#define TD_CTRL_C_ERR_SHIFT	27
+#define TD_CTRL_LS		(1 << 26)	/* Low Speed Device */
+#define TD_CTRL_IOS		(1 << 25)	/* Isochronous Select */
+#define TD_CTRL_IOC_BIT		24
+#define TD_CTRL_IOC		(1 << 24)	/* Interrupt on Complete */
+#define TD_CTRL_ACTIVE		(1 << 23)	/* TD Active */
+#define TD_CTRL_STALLED		(1 << 22)	/* TD Stalled */
+#define TD_CTRL_DBUFERR		(1 << 21)	/* Data Buffer Error */
+#define TD_CTRL_BABBLE		(1 << 20)	/* Babble Detected */
+#define TD_CTRL_NAK		(1 << 19)	/* NAK Received */
+#define TD_CTRL_CRCTIMEO	(1 << 18)	/* CRC/Time Out Error */
+#define TD_CTRL_BITSTUFF	(1 << 17)	/* Bit Stuff Error */
+#define TD_CTRL_ACTLEN_MASK	0x7FF		/* actual length, encoded as n - 1 */
+
+#define TD_CTRL_ANY_ERROR	(TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
+
+#define uhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
+#define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
+
+/*
+ * for TD <info>: (a.k.a. Token)
+ */
+#define TD_TOKEN_TOGGLE		19
+#define TD_TOKEN_PID_MASK	0xFF
+#define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
+
+#define uhci_maxlen(token)	((token) >> 21)
+#define uhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */
+#define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
+#define uhci_endpoint(token)	(((token) >> 15) & 0xf)
+#define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
+#define uhci_devep(token)	(((token) >> 8) & 0x7ff)
+#define uhci_packetid(token)	((token) & TD_TOKEN_PID_MASK)
+#define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
+#define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
+
+/*
+ * The documentation says "4 words for hardware, 4 words for software".
+ *
+ * That's silly, the hardware doesn't care. The hardware only cares that
+ * the hardware words are 16-byte aligned, and we can have any amount of
+ * sw space after the TD entry as far as I can tell.
+ *
+ * But let's just go with the documentation, at least for 32-bit machines.
+ * On 64-bit machines we probably want to take advantage of the fact that
+ * hw doesn't really care about the size of the sw-only area.
+ *
+ * Alas, not anymore, we have more than 4 words for software, woops.
+ * Everything still works tho, surprise! -jerdfelt
+ */
+struct uhci_td {
+	/* Hardware fields */
+	__u32 link;
+	__u32 status;
+	__u32 info;
+	__u32 buffer;
+
+	/* Software fields */
+	dma_addr_t dma_handle;
+
+	struct usb_device *dev;
+	struct urb *urb;
+
+	struct list_head list;		/* P: urb->lock */
+
+	int frame;
+	struct list_head fl_list;	/* P: uhci->frame_list_lock */
+} __attribute__((aligned(16)));
+
+/*
+ * There are various standard queues. We set up several different
+ * queues for each of the three basic queue types: interrupt,
+ * control, and bulk.
+ *
+ *  - There are various different interrupt latencies: ranging from
+ *    every other USB frame (2 ms apart) to every 256 USB frames (ie
+ *    256 ms apart). Make your choice according to how obnoxious you
+ *    want to be on the wire, vs how critical latency is for you.
+ *  - The control list is done every frame.
+ *  - There are 4 bulk lists, so that up to four devices can have a
+ *    bulk list of their own and when run concurrently all four lists
+ *    will be be serviced.
+ *
+ * This is a bit misleading, there are various interrupt latencies, but they
+ * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the
+ * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor
+ * problem
+ *
+ * In the case of the root hub, these QH's are just head's of qh's. Don't
+ * be scared, it kinda makes sense. Look at this wonderful picture care of
+ * Linus:
+ *
+ *  generic-  ->  dev1-  ->  generic-  ->  dev1-  ->  control-  ->  bulk- -> ...
+ *   iso-QH      iso-QH       irq-QH      irq-QH        QH           QH
+ *      |           |            |           |           |            |
+ *     End     dev1-iso-TD1     End     dev1-irq-TD1    ...          ... 
+ *                  |
+ *             dev1-iso-TD2
+ *                  |
+ *                ....
+ *
+ * This may vary a bit (the UHCI docs don't explicitly say you can put iso
+ * transfers in QH's and all of their pictures don't have that either) but
+ * other than that, that is what we're doing now
+ *
+ * And now we don't put Iso transfers in QH's, so we don't waste one on it
+ * --jerdfelt
+ *
+ * To keep with Linus' nomenclature, this is called the QH skeleton. These
+ * labels (below) are only signficant to the root hub's QH's
+ */
+
+#define UHCI_NUM_SKELTD		10
+#define skel_int1_td		skeltd[0]
+#define skel_int2_td		skeltd[1]
+#define skel_int4_td		skeltd[2]
+#define skel_int8_td		skeltd[3]
+#define skel_int16_td		skeltd[4]
+#define skel_int32_td		skeltd[5]
+#define skel_int64_td		skeltd[6]
+#define skel_int128_td		skeltd[7]
+#define skel_int256_td		skeltd[8]
+#define skel_term_td		skeltd[9]	/* To work around PIIX UHCI bug */
+
+#define UHCI_NUM_SKELQH		4
+#define skel_ls_control_qh	skelqh[0]
+#define skel_hs_control_qh	skelqh[1]
+#define skel_bulk_qh		skelqh[2]
+#define skel_term_qh		skelqh[3]
+
+/*
+ * Search tree for determining where <interval> fits in the
+ * skelqh[] skeleton.
+ *
+ * An interrupt request should be placed into the slowest skelqh[]
+ * which meets the interval/period/frequency requirement.
+ * An interrupt request is allowed to be faster than <interval> but not slower.
+ *
+ * For a given <interval>, this function returns the appropriate/matching
+ * skelqh[] index value.
+ *
+ * NOTE: For UHCI, we don't really need int256_qh since the maximum interval
+ * is 255 ms.  However, we do need an int1_qh since 1 is a valid interval
+ * and we should meet that frequency when requested to do so.
+ * This will require some change(s) to the UHCI skeleton.
+ */
+static inline int __interval_to_skel(int interval)
+{
+	if (interval < 16) {
+		if (interval < 4) {
+			if (interval < 2)
+				return 0;	/* int1 for 0-1 ms */
+			return 1;		/* int2 for 2-3 ms */
+		}
+		if (interval < 8)
+			return 2;		/* int4 for 4-7 ms */
+		return 3;			/* int8 for 8-15 ms */
+	}
+	if (interval < 64) {
+		if (interval < 32)
+			return 4;		/* int16 for 16-31 ms */
+		return 5;			/* int32 for 32-63 ms */
+	}
+	if (interval < 128)
+		return 6;			/* int64 for 64-127 ms */
+	return 7;				/* int128 for 128-255 ms (Max.) */
+}
+
+struct virt_root_hub {
+	struct usb_device *dev;
+	int devnum;		/* Address of Root Hub endpoint */
+	struct urb *urb;
+	void *int_addr;
+	int send;
+	int interval;
+	int numports;
+	int c_p_r[8];
+	struct timer_list rh_int_timer;
+};
+
+/*
+ * This describes the full uhci information.
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs.
+ */
+struct uhci {
+	struct pci_dev *dev;
+
+#ifdef CONFIG_PROC_FS
+	/* procfs */
+	int num;
+	struct proc_dir_entry *proc_entry;
+#endif
+
+	/* Grabbed from PCI */
+	int irq;
+	unsigned int io_addr;
+	unsigned int io_size;
+
+	struct pci_pool *qh_pool;
+	struct pci_pool *td_pool;
+
+	struct usb_bus *bus;
+
+	struct uhci_td *skeltd[UHCI_NUM_SKELTD];	/* Skeleton TD's */
+	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
+
+	spinlock_t frame_list_lock;
+	struct uhci_frame_list *fl;		/* P: uhci->frame_list_lock */
+	int fsbr;				/* Full speed bandwidth reclamation */
+	unsigned long fsbrtimeout;		/* FSBR delay */
+	int is_suspended;
+
+	/* Main list of URB's currently controlled by this HC */
+	spinlock_t urb_list_lock;
+	struct list_head urb_list;		/* P: uhci->urb_list_lock */
+
+	/* List of QH's that are done, but waiting to be unlinked (race) */
+	spinlock_t qh_remove_list_lock;
+	struct list_head qh_remove_list;	/* P: uhci->qh_remove_list_lock */
+
+	/* List of asynchronously unlinked URB's */
+	spinlock_t urb_remove_list_lock;
+	struct list_head urb_remove_list;	/* P: uhci->urb_remove_list_lock */
+
+	/* List of URB's awaiting completion callback */
+	spinlock_t complete_list_lock;
+	struct list_head complete_list;		/* P: uhci->complete_list_lock */
+
+	struct virt_root_hub rh;	/* private data of the virtual root hub */
+};
+
+struct urb_priv {
+	struct urb *urb;
+	struct usb_device *dev;
+
+	dma_addr_t setup_packet_dma_handle;
+	dma_addr_t transfer_buffer_dma_handle;
+
+	struct uhci_qh *qh;		/* QH for this URB */
+	struct list_head td_list;	/* P: urb->lock */
+
+	int fsbr : 1;			/* URB turned on FSBR */
+	int fsbr_timeout : 1;		/* URB timed out on FSBR */
+	int queued : 1;			/* QH was queued (not linked in) */
+	int short_control_packet : 1;	/* If we get a short packet during */
+					/*  a control transfer, retrigger */
+					/*  the status phase */
+
+	int status;			/* Final status */
+
+	unsigned long inserttime;	/* In jiffies */
+	unsigned long fsbrtime;		/* In jiffies */
+
+	struct list_head queue_list;	/* P: uhci->frame_list_lock */
+	struct list_head complete_list;	/* P: uhci->complete_list_lock */
+};
+
+/*
+ * Locking in uhci.c
+ *
+ * spinlocks are used extensively to protect the many lists and data
+ * structures we have. It's not that pretty, but it's necessary. We
+ * need to be done with all of the locks (except complete_list_lock) when
+ * we call urb->complete. I've tried to make it simple enough so I don't
+ * have to spend hours racking my brain trying to figure out if the
+ * locking is safe.
+ *
+ * Here's the safe locking order to prevent deadlocks:
+ *
+ * #1 uhci->urb_list_lock
+ * #2 urb->lock
+ * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock, 
+ *   uhci->qh_remove_list_lock
+ * #4 uhci->complete_list_lock
+ *
+ * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
+ * at the lowest level FIRST and NEVER grab locks at the same level at the
+ * same time.
+ * 
+ * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock
+ */
+
+/* -------------------------------------------------------------------------
+   Virtual Root HUB
+   ------------------------------------------------------------------------- */
+/* destination of request */
+#define RH_DEVICE		0x00
+#define RH_INTERFACE		0x01
+#define RH_ENDPOINT		0x02
+#define RH_OTHER		0x03
+
+#define RH_CLASS		0x20
+#define RH_VENDOR		0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS		0x0080
+#define RH_CLEAR_FEATURE	0x0100
+#define RH_SET_FEATURE		0x0300
+#define RH_SET_ADDRESS		0x0500
+#define RH_GET_DESCRIPTOR	0x0680
+#define RH_SET_DESCRIPTOR	0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE		0x0280
+#define RH_GET_INTERFACE	0x0A80
+#define RH_SET_INTERFACE	0x0B00
+#define RH_SYNC_FRAME		0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP		0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION	0x00
+#define RH_PORT_ENABLE		0x01
+#define RH_PORT_SUSPEND		0x02
+#define RH_PORT_OVER_CURRENT	0x03
+#define RH_PORT_RESET		0x04
+#define RH_PORT_POWER		0x08
+#define RH_PORT_LOW_SPEED	0x09
+#define RH_C_PORT_CONNECTION	0x10
+#define RH_C_PORT_ENABLE	0x11
+#define RH_C_PORT_SUSPEND	0x12
+#define RH_C_PORT_OVER_CURRENT	0x13
+#define RH_C_PORT_RESET		0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER	0x00
+#define RH_C_HUB_OVER_CURRENT	0x01
+#define RH_DEVICE_REMOTE_WAKEUP	0x00
+#define RH_ENDPOINT_STALL	0x01
+
+/* Our Vendor Specific feature */
+#define RH_REMOVE_EP		0x00
+
+#define RH_ACK			0x01
+#define RH_REQ_ERR		-1
+#define RH_NACK			0x00
+
+#endif
+
diff -Nru a/drivers/usb/host/usb-ohci.c b/drivers/usb/host/usb-ohci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-ohci.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,2919 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * [ Initialisation is based on Linus'  ]
+ * [ uhci code and gregs ohci fragments ]
+ * [ (C) Copyright 1999 Linus Torvalds  ]
+ * [ (C) Copyright 1999 Gregory P. Smith]
+ * 
+ * 
+ * History:
+ *
+ * 2002/03/08 interrupt unlink fix (Matt Hughes), better cleanup on
+ *	load failure (Matthew Frederickson)
+ * 2002/01/20 async unlink fixes:  return -EINPROGRESS (per spec) and
+ *	make interrupt unlink-in-completion work (db)
+ * 
+ * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes)
+ * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt)
+ * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
+ 	pci_map_single (db)
+ * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
+ * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
+ *
+ * 2000/09/26 fixed races in removing the private portion of the urb
+ * 2000/09/07 disable bulk and control lists when unlinking the last
+ *	endpoint descriptor in order to avoid unrecoverable errors on
+ *	the Lucent chips. (rwc@sgi)
+ * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
+ *	urb unlink probs, indentation fixes
+ * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
+ *	device unplugs.
+ * 2000/06/28 use PCI hotplug framework, for better power management
+ *	and for Cardbus support (David Brownell)
+ * 2000/earlier:  fixes for NEC/Lucent chips; suspend/resume handling
+ *	when the controller loses power; handle UE; cleanup; ...
+ *
+ * v5.2 1999/12/07 URB 3rd preview, 
+ * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
+ * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume 
+ * 	i386: HUB, Keyboard, Mouse, Printer 
+ *
+ * v4.3 1999/10/27 multiple HCs, bulk_request
+ * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
+ * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
+ * v4.0 1999/08/18 
+ * v3.0 1999/06/25 
+ * v2.1 1999/05/09  code clean up
+ * v2.0 1999/05/04 
+ * v1.0 1999/04/27 initial release
+ */
+ 
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>  /* for in_interrupt() */
+#undef DEBUG
+#include <linux/usb.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+
+#define OHCI_USE_NPS		// force NoPowerSwitching mode
+// #define OHCI_VERBOSE_DEBUG	/* not always helpful */
+
+#include "../core/hcd.h"
+#include "usb-ohci.h"
+
+
+#ifdef CONFIG_PMAC_PBOOK
+#include <asm/feature.h>
+#include <asm/pci-bridge.h>
+#ifndef CONFIG_PM
+#define CONFIG_PM
+#endif
+#endif
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v5.3"
+#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
+#define DRIVER_DESC "USB OHCI Host Controller Driver"
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define	OHCI_CONTROL_INIT \
+	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define OHCI_UNLINK_TIMEOUT	(HZ / 10)
+
+static LIST_HEAD (ohci_hcd_list);
+static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect.  AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define read_roothub(hc, register, mask) ({ \
+	u32 temp = readl (&hc->regs->roothub.register); \
+	if (hc->flags & OHCI_QUIRK_AMD756) \
+		while (temp & mask) \
+			temp = readl (&hc->regs->roothub.register); \
+	temp; })
+
+static u32 roothub_a (struct ohci *hc)
+	{ return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+	{ return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+	{ return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+
+/*-------------------------------------------------------------------------*
+ * URB support functions 
+ *-------------------------------------------------------------------------*/ 
+ 
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (struct ohci *hc, urb_priv_t * urb_priv)
+{
+	int		i;
+	int		last = urb_priv->length - 1;
+	int		len;
+	int		dir;
+	struct td	*td;
+
+	if (last >= 0) {
+
+		/* ISOC, BULK, INTR data buffer starts at td 0 
+		 * CTRL setup starts at td 0 */
+		td = urb_priv->td [0];
+
+		len = td->urb->transfer_buffer_length,
+		dir = usb_pipeout (td->urb->pipe)
+					? PCI_DMA_TODEVICE
+					: PCI_DMA_FROMDEVICE;
+
+		/* unmap CTRL URB setup */
+		if (usb_pipecontrol (td->urb->pipe)) {
+			pci_unmap_single (hc->ohci_dev, 
+					td->data_dma, 8, PCI_DMA_TODEVICE);
+			
+			/* CTRL data buffer starts at td 1 if len > 0 */
+			if (len && last > 0)
+				td = urb_priv->td [1]; 		
+		} 
+
+		/* unmap data buffer */
+		if (len && td->data_dma)
+			pci_unmap_single (hc->ohci_dev, td->data_dma, len, dir);
+		
+		for (i = 0; i <= last; i++) {
+			td = urb_priv->td [i];
+			if (td)
+				td_free (hc, td);
+		}
+	}
+
+	kfree (urb_priv);
+}
+ 
+static void urb_rm_priv_locked (struct urb * urb) 
+{
+	urb_priv_t * urb_priv = urb->hcpriv;
+	
+	if (urb_priv) {
+		urb->hcpriv = NULL;
+
+#ifdef	DO_TIMEOUTS
+		if (urb->timeout) {
+			list_del (&urb->urb_list);
+			urb->timeout -= jiffies;
+		}
+#endif
+
+		/* Release int/iso bandwidth */
+		if (urb->bandwidth) {
+			switch (usb_pipetype(urb->pipe)) {
+			case PIPE_INTERRUPT:
+				usb_release_bandwidth (urb->dev, urb, 0);
+				break;
+			case PIPE_ISOCHRONOUS:
+				usb_release_bandwidth (urb->dev, urb, 1);
+				break;
+			default:
+				break;
+			}
+		}
+
+		urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
+		usb_dec_dev_use (urb->dev);
+		urb->dev = NULL;
+		usb_put_urb (urb);
+	}
+}
+
+static void urb_rm_priv (struct urb * urb)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave (&usb_ed_lock, flags);
+	urb_rm_priv_locked (urb);
+	spin_unlock_irqrestore (&usb_ed_lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+ 
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB     
+ * small: 0) header + data packets 1) just header */
+ 
+static void urb_print (struct urb * urb, char * str, int small)
+{
+	unsigned int pipe= urb->pipe;
+	
+	if (!urb->dev || !urb->dev->bus) {
+		dbg("%s URB: no dev", str);
+		return;
+	}
+	
+#ifndef	OHCI_VERBOSE_DEBUG
+	if (urb->status != 0)
+#endif
+	dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", 
+			str,
+		 	sohci_get_current_frame_number (urb->dev), 
+		 	usb_pipedevice (pipe),
+		 	usb_pipeendpoint (pipe), 
+		 	usb_pipeout (pipe)? 'O': 'I',
+		 	usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+		 		(usb_pipecontrol (pipe)? "CTRL": "BULK"),
+		 	urb->transfer_flags, 
+		 	urb->actual_length, 
+		 	urb->transfer_buffer_length,
+		 	urb->status, urb->status);
+#ifdef	OHCI_VERBOSE_DEBUG
+	if (!small) {
+		int i, len;
+
+		if (usb_pipecontrol (pipe)) {
+			printk (KERN_DEBUG __FILE__ ": cmd(8):");
+			for (i = 0; i < 8 ; i++) 
+				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
+			printk ("\n");
+		}
+		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
+			printk (KERN_DEBUG __FILE__ ": data(%d/%d):", 
+				urb->actual_length, 
+				urb->transfer_buffer_length);
+			len = usb_pipeout (pipe)? 
+						urb->transfer_buffer_length: urb->actual_length;
+			for (i = 0; i < 16 && i < len; i++) 
+				printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
+			printk ("%s stat:%d\n", i < len? "...": "", urb->status);
+		}
+	} 
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t * ohci, char * str) {
+	int i, j;
+	 __u32 * ed_p;
+	for (i= 0; i < 32; i++) {
+		j = 5;
+		ed_p = &(ohci->hcca->int_table [i]);
+		if (*ed_p == 0)
+		    continue;
+		printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i);
+		while (*ed_p != 0 && j--) {
+			ed_t *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
+			printk (" ed: %4x;", ed->hwINFO);
+			ed_p = &ed->hwNextED;
+		}
+		printk ("\n");
+	}
+}
+
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+	dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+		label,
+		mask,
+		(mask & OHCI_INTR_MIE) ? " MIE" : "",
+		(mask & OHCI_INTR_OC) ? " OC" : "",
+		(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+		(mask & OHCI_INTR_FNO) ? " FNO" : "",
+		(mask & OHCI_INTR_UE) ? " UE" : "",
+		(mask & OHCI_INTR_RD) ? " RD" : "",
+		(mask & OHCI_INTR_SF) ? " SF" : "",
+		(mask & OHCI_INTR_WDH) ? " WDH" : "",
+		(mask & OHCI_INTR_SO) ? " SO" : ""
+		);
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+	if (value)
+		dbg ("%s %08x", label, value);
+}
+
+static char *hcfs2string (int state)
+{
+	switch (state) {
+		case OHCI_USB_RESET:	return "reset";
+		case OHCI_USB_RESUME:	return "resume";
+		case OHCI_USB_OPER:	return "operational";
+		case OHCI_USB_SUSPEND:	return "suspend";
+	}
+	return "?";
+}
+
+// dump control and status registers
+static void ohci_dump_status (ohci_t *controller)
+{
+	struct ohci_regs	*regs = controller->regs;
+	__u32			temp;
+
+	temp = readl (&regs->revision) & 0xff;
+	if (temp != 0x10)
+		dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+	temp = readl (&regs->control);
+	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
+		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
+		(temp & OHCI_CTRL_IR) ? " IR" : "",
+		hcfs2string (temp & OHCI_CTRL_HCFS),
+		(temp & OHCI_CTRL_BLE) ? " BLE" : "",
+		(temp & OHCI_CTRL_CLE) ? " CLE" : "",
+		(temp & OHCI_CTRL_IE) ? " IE" : "",
+		(temp & OHCI_CTRL_PLE) ? " PLE" : "",
+		temp & OHCI_CTRL_CBSR
+		);
+
+	temp = readl (&regs->cmdstatus);
+	dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+		(temp & OHCI_SOC) >> 16,
+		(temp & OHCI_OCR) ? " OCR" : "",
+		(temp & OHCI_BLF) ? " BLF" : "",
+		(temp & OHCI_CLF) ? " CLF" : "",
+		(temp & OHCI_HCR) ? " HCR" : ""
+		);
+
+	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+	// intrdisable always same as intrenable
+	// ohci_dump_intr_mask ("intrdisable", readl (&regs->intrdisable));
+
+	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+	maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+	__u32			temp, ndp, i;
+
+	temp = roothub_a (controller);
+	ndp = (temp & RH_A_NDP);
+
+	if (verbose) {
+		dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+			((temp & RH_A_POTPGT) >> 24) & 0xff,
+			(temp & RH_A_NOCP) ? " NOCP" : "",
+			(temp & RH_A_OCPM) ? " OCPM" : "",
+			(temp & RH_A_DT) ? " DT" : "",
+			(temp & RH_A_NPS) ? " NPS" : "",
+			(temp & RH_A_PSM) ? " PSM" : "",
+			ndp
+			);
+		temp = roothub_b (controller);
+		dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+			temp,
+			(temp & RH_B_PPCM) >> 16,
+			(temp & RH_B_DR)
+			);
+		temp = roothub_status (controller);
+		dbg ("roothub.status: %08x%s%s%s%s%s%s",
+			temp,
+			(temp & RH_HS_CRWE) ? " CRWE" : "",
+			(temp & RH_HS_OCIC) ? " OCIC" : "",
+			(temp & RH_HS_LPSC) ? " LPSC" : "",
+			(temp & RH_HS_DRWE) ? " DRWE" : "",
+			(temp & RH_HS_OCI) ? " OCI" : "",
+			(temp & RH_HS_LPS) ? " LPS" : ""
+			);
+	}
+	
+	for (i = 0; i < ndp; i++) {
+		temp = roothub_portstatus (controller, i);
+		dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+			i,
+			temp,
+			(temp & RH_PS_PRSC) ? " PRSC" : "",
+			(temp & RH_PS_OCIC) ? " OCIC" : "",
+			(temp & RH_PS_PSSC) ? " PSSC" : "",
+			(temp & RH_PS_PESC) ? " PESC" : "",
+			(temp & RH_PS_CSC) ? " CSC" : "",
+
+			(temp & RH_PS_LSDA) ? " LSDA" : "",
+			(temp & RH_PS_PPS) ? " PPS" : "",
+			(temp & RH_PS_PRS) ? " PRS" : "",
+			(temp & RH_PS_POCI) ? " POCI" : "",
+			(temp & RH_PS_PSS) ? " PSS" : "",
+
+			(temp & RH_PS_PES) ? " PES" : "",
+			(temp & RH_PS_CCS) ? " CCS" : ""
+			);
+	}
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+	dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
+
+	// dumps some of the state we know about
+	ohci_dump_status (controller);
+	if (verbose)
+		ep_print_int_eds (controller, "hcca");
+	dbg ("hcca frame #%04x", controller->hcca->frame_no);
+	ohci_dump_roothub (controller, 1);
+}
+
+
+#endif
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* return a request to the completion handler */
+ 
+static int sohci_return_urb (struct ohci *hc, struct urb * urb)
+{
+	urb_priv_t * urb_priv = urb->hcpriv;
+	struct urb * urbt;
+	unsigned long flags;
+	int i;
+	
+	if (!urb_priv)
+		return -1; /* urb already unlinked */
+
+	/* just to be sure */
+	if (!urb->complete) {
+		urb_rm_priv (urb);
+		return -1;
+	}
+	
+#ifdef DEBUG
+	urb_print (urb, "RET", usb_pipeout (urb->pipe));
+#endif
+
+	switch (usb_pipetype (urb->pipe)) {
+  		case PIPE_INTERRUPT:
+			pci_unmap_single (hc->ohci_dev,
+				urb_priv->td [0]->data_dma,
+				urb->transfer_buffer_length,
+				usb_pipeout (urb->pipe)
+					? PCI_DMA_TODEVICE
+					: PCI_DMA_FROMDEVICE);
+			urb->complete (urb);
+
+			/* implicitly requeued */
+  			urb->actual_length = 0;
+  			urb->status = -EINPROGRESS;
+ 			td_submit_urb (urb);
+  			break;
+  			
+		case PIPE_ISOCHRONOUS:
+			for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
+			if (urbt) { /* send the reply and requeue URB */	
+				pci_unmap_single (hc->ohci_dev,
+					urb_priv->td [0]->data_dma,
+					urb->transfer_buffer_length,
+					usb_pipeout (urb->pipe)
+						? PCI_DMA_TODEVICE
+						: PCI_DMA_FROMDEVICE);
+				urb->complete (urb);
+				spin_lock_irqsave (&usb_ed_lock, flags);
+				urb->actual_length = 0;
+  				urb->status = -EINPROGRESS;
+  				urb->start_frame = urb_priv->ed->last_iso + 1;
+  				if (urb_priv->state != URB_DEL) {
+  					for (i = 0; i < urb->number_of_packets; i++) {
+  						urb->iso_frame_desc[i].actual_length = 0;
+  						urb->iso_frame_desc[i].status = -EXDEV;
+  					}
+  					td_submit_urb (urb);
+  				}
+  				spin_unlock_irqrestore (&usb_ed_lock, flags);
+  				
+  			} else { /* unlink URB, call complete */
+				urb_rm_priv (urb);
+				urb->complete (urb); 	
+			}		
+			break;
+  				
+		case PIPE_BULK:
+		case PIPE_CONTROL: /* unlink URB, call complete */
+			urb_rm_priv (urb);
+			urb->complete (urb);	
+			break;
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+ 
+static int sohci_submit_urb (struct urb * urb, int mem_flags)
+{
+	ohci_t * ohci;
+	ed_t * ed;
+	urb_priv_t * urb_priv;
+	unsigned int pipe = urb->pipe;
+	int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
+	int i, size = 0;
+	unsigned long flags;
+	int bustime = 0;
+	
+	if (!urb->dev || !urb->dev->bus)
+		return -ENODEV;
+	
+	if (urb->hcpriv)			/* urb already in use */
+		return -EINVAL;
+
+//	if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) 
+//		return -EPIPE;
+	
+	/* increment the reference count of the urb, as we now also control it */
+	urb = usb_get_urb (urb);
+
+	usb_inc_dev_use (urb->dev);
+	ohci = (ohci_t *) urb->dev->bus->hcpriv;
+	
+#ifdef DEBUG
+	urb_print (urb, "SUB", usb_pipein (pipe));
+#endif
+	
+	/* handle a request to the virtual root hub */
+	if (usb_pipedevice (pipe) == ohci->rh.devnum) 
+		return rh_submit_urb (urb);
+	
+	/* when controller's hung, permit only roothub cleanup attempts
+	 * such as powering down ports */
+	if (ohci->disabled) {
+		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
+		return -ESHUTDOWN;
+	}
+
+	/* every endpoint has a ed, locate and fill it */
+	if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
+		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
+		return -ENOMEM;
+	}
+
+	/* for the private part of the URB we need the number of TDs (size) */
+	switch (usb_pipetype (pipe)) {
+		case PIPE_BULK:	/* one TD for every 4096 Byte */
+			size = (urb->transfer_buffer_length - 1) / 4096 + 1;
+
+			/* If the transfer size is multiple of the pipe mtu,
+			 * we may need an extra TD to create a empty frame
+			 * Jean II */
+			if ((urb->transfer_flags & USB_ZERO_PACKET) &&
+			    usb_pipeout (pipe) &&
+			    (urb->transfer_buffer_length != 0) && 
+			    ((urb->transfer_buffer_length % maxps) == 0))
+				size++;
+			break;
+		case PIPE_ISOCHRONOUS: /* number of packets from URB */
+			size = urb->number_of_packets;
+			if (size <= 0) {
+				usb_dec_dev_use (urb->dev);	
+				usb_put_urb (urb);
+				return -EINVAL;
+			}
+			for (i = 0; i < urb->number_of_packets; i++) {
+  				urb->iso_frame_desc[i].actual_length = 0;
+  				urb->iso_frame_desc[i].status = -EXDEV;
+  			}
+			break;
+		case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+			size = (urb->transfer_buffer_length == 0)? 2: 
+						(urb->transfer_buffer_length - 1) / 4096 + 3;
+			break;
+		case PIPE_INTERRUPT: /* one TD */
+			size = 1;
+			break;
+	}
+
+	/* allocate the private part of the URB */
+	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), mem_flags);
+	if (!urb_priv) {
+		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
+		return -ENOMEM;
+	}
+	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *));
+	
+	/* fill the private part of the URB */
+	urb_priv->length = size;
+	urb_priv->ed = ed;	
+
+	/* allocate the TDs (updating hash chains) */
+	spin_lock_irqsave (&usb_ed_lock, flags);
+	for (i = 0; i < size; i++) { 
+		urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
+		if (!urb_priv->td[i]) {
+			urb_priv->length = i;
+			urb_free_priv (ohci, urb_priv);
+			spin_unlock_irqrestore (&usb_ed_lock, flags);
+			usb_dec_dev_use (urb->dev);	
+			usb_put_urb (urb);
+			return -ENOMEM;
+		}
+	}	
+
+	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+		urb_free_priv (ohci, urb_priv);
+		spin_unlock_irqrestore (&usb_ed_lock, flags);
+		usb_dec_dev_use (urb->dev);	
+		usb_put_urb (urb);
+		return -EINVAL;
+	}
+	
+	/* allocate and claim bandwidth if needed; ISO
+	 * needs start frame index if it was't provided.
+	 */
+	switch (usb_pipetype (pipe)) {
+		case PIPE_ISOCHRONOUS:
+			if (urb->transfer_flags & USB_ISO_ASAP) { 
+				urb->start_frame = ((ed->state == ED_OPER)
+					? (ed->last_iso + 1)
+					: (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff;
+			}	
+			/* FALLTHROUGH */
+		case PIPE_INTERRUPT:
+			if (urb->bandwidth == 0) {
+				bustime = usb_check_bandwidth (urb->dev, urb);
+			}
+			if (bustime < 0) {
+				urb_free_priv (ohci, urb_priv);
+				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				usb_dec_dev_use (urb->dev);	
+				usb_put_urb (urb);
+				return bustime;
+			}
+			usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe));
+#ifdef	DO_TIMEOUTS
+			urb->timeout = 0;
+#endif
+	}
+
+	urb->actual_length = 0;
+	urb->hcpriv = urb_priv;
+	urb->status = -EINPROGRESS;
+
+	/* link the ed into a chain if is not already */
+	if (ed->state != ED_OPER)
+		ep_link (ohci, ed);
+
+	/* fill the TDs and link it to the ed */
+	td_submit_urb (urb);
+
+#ifdef	DO_TIMEOUTS
+	/* maybe add to ordered list of timeouts */
+	if (urb->timeout) {
+		struct list_head	*entry;
+
+		// FIXME:  usb-uhci uses relative timeouts (like this),
+		// while uhci uses absolute ones (probably better).
+		// Pick one solution and change the affected drivers.
+		urb->timeout += jiffies;
+
+		list_for_each (entry, &ohci->timeout_list) {
+			struct urb	*next_urb;
+
+			next_urb = list_entry (entry, struct urb, urb_list);
+			if (time_after_eq (urb->timeout, next_urb->timeout))
+				break;
+		}
+		list_add (&urb->urb_list, entry);
+
+		/* drive timeouts by SF (messy, but works) */
+		writel (OHCI_INTR_SF, &ohci->regs->intrenable);	
+	}
+#endif
+
+	spin_unlock_irqrestore (&usb_ed_lock, flags);
+
+	return 0;	
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* deactivate all TDs and remove the private part of the URB */
+/* interrupt callers must use async unlink mode */
+
+static int sohci_unlink_urb (struct urb * urb)
+{
+	unsigned long flags;
+	ohci_t * ohci;
+	
+	if (!urb) /* just to be sure */ 
+		return -EINVAL;
+		
+	if (!urb->dev || !urb->dev->bus)
+		return -ENODEV;
+
+	ohci = (ohci_t *) urb->dev->bus->hcpriv; 
+
+#ifdef DEBUG
+	urb_print (urb, "UNLINK", 1);
+#endif		  
+
+	/* handle a request to the virtual root hub */
+	if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
+		return rh_unlink_urb (urb);
+
+	if (urb->hcpriv && (urb->status == -EINPROGRESS)) { 
+		if (!ohci->disabled) {
+			urb_priv_t  * urb_priv;
+
+			/* interrupt code may not sleep; it must use
+			 * async status return to unlink pending urbs.
+			 */
+			if (!(urb->transfer_flags & USB_ASYNC_UNLINK)
+					&& in_interrupt ()) {
+				err ("bug in call from %p; use async!",
+					__builtin_return_address(0));
+				return -EWOULDBLOCK;
+			}
+
+			/* flag the urb and its TDs for deletion in some
+			 * upcoming SF interrupt delete list processing
+			 */
+			spin_lock_irqsave (&usb_ed_lock, flags);
+			urb_priv = urb->hcpriv;
+
+			if (!urb_priv || (urb_priv->state == URB_DEL)) {
+				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				return 0;
+			}
+				
+			urb_priv->state = URB_DEL; 
+			ep_rm_ed (urb->dev, urb_priv->ed);
+			urb_priv->ed->state |= ED_URB_DEL;
+
+			if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
+				DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
+				DECLARE_WAITQUEUE (wait, current);
+				int timeout = OHCI_UNLINK_TIMEOUT;
+
+				add_wait_queue (&unlink_wakeup, &wait);
+				urb_priv->wait = &unlink_wakeup;
+				spin_unlock_irqrestore (&usb_ed_lock, flags);
+
+				/* wait until all TDs are deleted */
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				while (timeout && (urb->status == -EINPROGRESS))
+					timeout = schedule_timeout (timeout);
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue (&unlink_wakeup, &wait); 
+				if (urb->status == -EINPROGRESS) {
+					err ("unlink URB timeout");
+					return -ETIMEDOUT;
+				}
+			} else {
+				/* usb_dec_dev_use done in dl_del_list() */
+				urb->status = -EINPROGRESS;
+				spin_unlock_irqrestore (&usb_ed_lock, flags);
+				return -EINPROGRESS;
+			}
+		} else {
+			urb_rm_priv (urb);
+			if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+				urb->status = -ECONNRESET;
+				if (urb->complete)
+					urb->complete (urb); 
+			} else 
+				urb->status = -ENOENT;
+		}	
+	}	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* allocate private data space for a usb device */
+
+static int sohci_alloc_dev (struct usb_device *usb_dev)
+{
+	struct ohci_device * dev;
+
+	dev = dev_alloc ((struct ohci *) usb_dev->bus->hcpriv, ALLOC_FLAGS);
+	if (!dev)
+		return -ENOMEM;
+
+	usb_dev->hcpriv = dev;
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* may be called from interrupt context */
+/* frees private data space of usb device */
+  
+static int sohci_free_dev (struct usb_device * usb_dev)
+{
+	unsigned long flags;
+	int i, cnt = 0;
+	ed_t * ed;
+	struct ohci_device * dev = usb_to_ohci (usb_dev);
+	ohci_t * ohci = usb_dev->bus->hcpriv;
+	
+	if (!dev)
+		return 0;
+	
+	if (usb_dev->devnum >= 0) {
+	
+		/* driver disconnects should have unlinked all urbs
+		 * (freeing all the TDs, unlinking EDs) but we need
+		 * to defend against bugs that prevent that.
+		 */
+		spin_lock_irqsave (&usb_ed_lock, flags);	
+		for(i = 0; i < NUM_EDS; i++) {
+  			ed = &(dev->ed[i]);
+  			if (ed->state != ED_NEW) {
+  				if (ed->state == ED_OPER) {
+					/* driver on that interface didn't unlink an urb */
+					dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
+						ohci->ohci_dev->slot_name, usb_dev->devnum, i);
+					ep_unlink (ohci, ed);
+				}
+  				ep_rm_ed (usb_dev, ed);
+  				ed->state = ED_DEL;
+  				cnt++;
+  			}
+  		}
+  		spin_unlock_irqrestore (&usb_ed_lock, flags);
+  		
+		/* if the controller is running, tds for those unlinked
+		 * urbs get freed by dl_del_list at the next SF interrupt
+		 */
+		if (cnt > 0) {
+
+			if (ohci->disabled) {
+				/* FIXME: Something like this should kick in,
+				 * though it's currently an exotic case ...
+				 * the controller won't ever be touching
+				 * these lists again!!
+				dl_del_list (ohci,
+					le16_to_cpu (ohci->hcca->frame_no) & 1);
+				 */
+				warn ("TD leak, %d", cnt);
+
+			} else if (!in_interrupt ()) {
+				DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); 
+				DECLARE_WAITQUEUE (wait, current);
+				int timeout = OHCI_UNLINK_TIMEOUT;
+
+				/* SF interrupt handler calls dl_del_list */
+				add_wait_queue (&freedev_wakeup, &wait);
+				dev->wait = &freedev_wakeup;
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				while (timeout && dev->ed_cnt)
+					timeout = schedule_timeout (timeout);
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue (&freedev_wakeup, &wait);
+				if (dev->ed_cnt) {
+					err ("free device %d timeout", usb_dev->devnum);
+					return -ETIMEDOUT;
+				}
+			} else {
+				/* likely some interface's driver has a refcount bug */
+				err ("bus %s devnum %d deletion in interrupt",
+					ohci->ohci_dev->slot_name, usb_dev->devnum);
+				BUG ();
+			}
+		}
+	}
+
+	/* free device, and associated EDs */
+	dev_free (ohci, dev);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev) 
+{
+	ohci_t * ohci = usb_dev->bus->hcpriv;
+	
+	return le16_to_cpu (ohci->hcca->frame_no);
+}
+
+/*-------------------------------------------------------------------------*/
+
+struct usb_operations sohci_device_operations = {
+	allocate:		sohci_alloc_dev,
+	deallocate:		sohci_free_dev,
+	get_frame_number:	sohci_get_current_frame_number,
+	submit_urb:		sohci_submit_urb,
+	unlink_urb:		sohci_unlink_urb,
+};
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/  
+		
+/* search for the right branch to insert an interrupt ed into the int tree 
+ * do some load ballancing;
+ * returns the branch and 
+ * sets the interval to interval = 2^integer (ld (interval)) */
+
+static int ep_int_ballance (ohci_t * ohci, int interval, int load)
+{
+	int i, branch = 0;
+   
+	/* search for the least loaded interrupt endpoint branch of all 32 branches */
+	for (i = 0; i < 32; i++) 
+		if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; 
+  
+	branch = branch % interval;
+	for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load;
+
+	return branch;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*  2^int( ld (inter)) */
+
+static int ep_2_n_interval (int inter)
+{	
+	int i;
+	for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); 
+	return 1 << i;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* the int tree is a binary tree 
+ * in order to process it sequentially the indexes of the branches have to be mapped 
+ * the mapping reverses the bits of a word of num_bits length */
+ 
+static int ep_rev (int num_bits, int word)
+{
+	int i, wout = 0;
+
+	for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1));
+	return wout;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t * ohci, ed_t * edi)
+{	 
+	int int_branch;
+	int i;
+	int inter;
+	int interval;
+	int load;
+	__u32 * ed_p;
+	volatile ed_t * ed = edi;
+	
+	ed->state = ED_OPER;
+	
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		ed->hwNextED = 0;
+		if (ohci->ed_controltail == NULL) {
+			writel (ed->dma, &ohci->regs->ed_controlhead);
+		} else {
+			ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
+		}
+		ed->ed_prev = ohci->ed_controltail;
+		if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+			!ohci->ed_rm_list[1] && !ohci->sleeping) {
+			ohci->hc_control |= OHCI_CTRL_CLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_controltail = edi;	  
+		break;
+		
+	case PIPE_BULK:
+		ed->hwNextED = 0;
+		if (ohci->ed_bulktail == NULL) {
+			writel (ed->dma, &ohci->regs->ed_bulkhead);
+		} else {
+			ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
+		}
+		ed->ed_prev = ohci->ed_bulktail;
+		if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+			!ohci->ed_rm_list[1] && !ohci->sleeping) {
+			ohci->hc_control |= OHCI_CTRL_BLE;
+			writel (ohci->hc_control, &ohci->regs->control);
+		}
+		ohci->ed_bulktail = edi;	  
+		break;
+		
+	case PIPE_INTERRUPT:
+		load = ed->int_load;
+		interval = ep_2_n_interval (ed->int_period);
+		ed->int_interval = interval;
+		int_branch = ep_int_ballance (ohci, interval, load);
+		ed->int_branch = int_branch;
+		
+		for (i = 0; i < ep_rev (6, interval); i += inter) {
+			inter = 1;
+			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); 
+				(*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); 
+				ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
+					inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
+			ed->hwNextED = *ed_p; 
+			*ed_p = cpu_to_le32 (ed->dma);
+		}
+#ifdef DEBUG
+		ep_print_int_eds (ohci, "LINK_INT");
+#endif
+		break;
+		
+	case PIPE_ISOCHRONOUS:
+		ed->hwNextED = 0;
+		ed->int_interval = 1;
+		if (ohci->ed_isotail != NULL) {
+			ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
+			ed->ed_prev = ohci->ed_isotail;
+		} else {
+			for ( i = 0; i < 32; i += inter) {
+				inter = 1;
+				for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); 
+					*ed_p != 0; 
+					ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
+						inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
+				*ed_p = cpu_to_le32 (ed->dma);	
+			}	
+			ed->ed_prev = NULL;
+		}	
+		ohci->ed_isotail = edi;  
+#ifdef DEBUG
+		ep_print_int_eds (ohci, "LINK_ISO");
+#endif
+		break;
+	}	 	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* scan the periodic table to find and unlink this ED */
+static void periodic_unlink (
+	struct ohci	*ohci,
+	struct ed	*ed,
+	unsigned	index,
+	unsigned	period
+) {
+	for (; index < NUM_INTS; index += period) {
+		__u32	*ed_p = &ohci->hcca->int_table [index];
+
+		/* ED might have been unlinked through another path */
+		while (*ed_p != 0) {
+			if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
+				*ed_p = ed->hwNextED;		
+				break;
+			}
+			ed_p = & ((dma_to_ed (ohci,
+				le32_to_cpup (ed_p)))->hwNextED);
+		}
+	}	
+}
+
+/* unlink an ed from one of the HC chains. 
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t * ohci, ed_t * ed) 
+{
+	int i;
+
+	ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP);
+
+	switch (ed->type) {
+	case PIPE_CONTROL:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_CLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_controltail == ed) {
+			ohci->ed_controltail = ed->ed_prev;
+		} else {
+			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		}
+		break;
+      
+	case PIPE_BULK:
+		if (ed->ed_prev == NULL) {
+			if (!ed->hwNextED) {
+				ohci->hc_control &= ~OHCI_CTRL_BLE;
+				writel (ohci->hc_control, &ohci->regs->control);
+			}
+			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead);
+		} else {
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		}
+		if (ohci->ed_bulktail == ed) {
+			ohci->ed_bulktail = ed->ed_prev;
+		} else {
+			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
+		}
+		break;
+      
+	case PIPE_INTERRUPT:
+		periodic_unlink (ohci, ed, 0, 1);
+		for (i = ed->int_branch; i < 32; i += ed->int_interval)
+		    ohci->ohci_int_load[i] -= ed->int_load;
+#ifdef DEBUG
+		ep_print_int_eds (ohci, "UNLINK_INT");
+#endif
+		break;
+		
+	case PIPE_ISOCHRONOUS:
+		if (ohci->ed_isotail == ed)
+			ohci->ed_isotail = ed->ed_prev;
+		if (ed->hwNextED != 0) 
+		    (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))
+		    	->ed_prev = ed->ed_prev;
+				    
+		if (ed->ed_prev != NULL)
+			ed->ed_prev->hwNextED = ed->hwNextED;
+		else
+			periodic_unlink (ohci, ed, 0, 1);
+#ifdef DEBUG
+		ep_print_int_eds (ohci, "UNLINK_ISO");
+#endif
+		break;
+	}
+	ed->state = ED_UNLINK;
+	return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless  so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though most of them should not change */
+ 
+static ed_t * ep_add_ed (
+	struct usb_device * usb_dev,
+	unsigned int pipe,
+	int interval,
+	int load,
+	int mem_flags
+)
+{
+   	ohci_t * ohci = usb_dev->bus->hcpriv;
+	td_t * td;
+	ed_t * ed_ret;
+	volatile ed_t * ed; 
+	unsigned long flags;
+ 	
+ 	
+	spin_lock_irqsave (&usb_ed_lock, flags);
+
+	ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | 
+			(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]);
+
+	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+		/* pending delete request */
+		spin_unlock_irqrestore (&usb_ed_lock, flags);
+		return NULL;
+	}
+	
+	if (ed->state == ED_NEW) {
+		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
+  		/* dummy td; end of td list for ed */
+		td = td_alloc (ohci, SLAB_ATOMIC);
+		/* hash the ed for later reverse mapping */
+ 		if (!td || !hash_add_ed (ohci, (ed_t *)ed)) {
+			/* out of memory */
+		        if (td)
+		            td_free(ohci, td);
+			spin_unlock_irqrestore (&usb_ed_lock, flags);
+			return NULL;
+		}
+		ed->hwTailP = cpu_to_le32 (td->td_dma);
+		ed->hwHeadP = ed->hwTailP;	
+		ed->state = ED_UNLINK;
+		ed->type = usb_pipetype (pipe);
+		usb_to_ohci (usb_dev)->ed_cnt++;
+	}
+
+	ohci->dev[usb_pipedevice (pipe)] = usb_dev;
+	
+	ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
+			| usb_pipeendpoint (pipe) << 7
+			| (usb_pipeisoc (pipe)? 0x8000: 0)
+			| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) 
+			| (usb_dev->speed == USB_SPEED_LOW) << 13
+			| usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16);
+  
+  	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
+  		ed->int_period = interval;
+  		ed->int_load = load;
+  	}
+  	
+	spin_unlock_irqrestore (&usb_ed_lock, flags);
+	return ed_ret; 
+}
+
+/*-------------------------------------------------------------------------*/
+ 
+/* request the removal of an endpoint
+ * put the ep on the rm_list and request a stop of the bulk or ctrl list 
+ * real removal is done at the next start frame (SF) hardware interrupt */
+ 
+static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed)
+{    
+	unsigned int frame;
+	ohci_t * ohci = usb_dev->bus->hcpriv;
+
+	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL))
+		return;
+	
+	ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP);
+
+	if (!ohci->disabled) {
+		switch (ed->type) {
+			case PIPE_CONTROL: /* stop control list */
+				ohci->hc_control &= ~OHCI_CTRL_CLE;
+				writel (ohci->hc_control, &ohci->regs->control); 
+  				break;
+			case PIPE_BULK: /* stop bulk list */
+				ohci->hc_control &= ~OHCI_CTRL_BLE;
+				writel (ohci->hc_control, &ohci->regs->control); 
+				break;
+		}
+	}
+
+	frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1;
+	ed->ed_rm_list = ohci->ed_rm_list[frame];
+	ohci->ed_rm_list[frame] = ed;
+
+	if (!ohci->disabled && !ohci->sleeping) {
+		/* enable SOF interrupt */
+		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
+		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
+	}
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void
+td_fill (ohci_t * ohci, unsigned int info,
+	dma_addr_t data, int len,
+	struct urb * urb, int index)
+{
+	volatile td_t  * td, * td_pt;
+	urb_priv_t * urb_priv = urb->hcpriv;
+	
+	if (index >= urb_priv->length) {
+		err("internal OHCI error: TD index > length");
+		return;
+	}
+	
+	/* use this td as the next dummy */
+	td_pt = urb_priv->td [index];
+	td_pt->hwNextTD = 0;
+
+	/* fill the old dummy TD */
+	td = urb_priv->td [index] = dma_to_td (ohci,
+			le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf);
+
+	td->ed = urb_priv->ed;
+	td->next_dl_td = NULL;
+	td->index = index;
+	td->urb = urb; 
+	td->data_dma = data;
+	if (!len)
+		data = 0;
+
+	td->hwINFO = cpu_to_le32 (info);
+	if ((td->ed->type) == PIPE_ISOCHRONOUS) {
+		td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
+		td->ed->last_iso = info & 0xffff;
+	} else {
+		td->hwCBP = cpu_to_le32 (data); 
+	}			
+	if (data)
+		td->hwBE = cpu_to_le32 (data + len - 1);
+	else
+		td->hwBE = 0;
+	td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
+	td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
+
+	/* append to queue */
+	td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+ 
+/* prepare all TDs of a transfer */
+
+static void td_submit_urb (struct urb * urb)
+{ 
+	urb_priv_t * urb_priv = urb->hcpriv;
+	ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv;
+	dma_addr_t data;
+	int data_len = urb->transfer_buffer_length;
+	int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
+	int cnt = 0; 
+	__u32 info = 0;
+  	unsigned int toggle = 0;
+
+	/* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+  	if(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) {
+  		toggle = TD_T_TOGGLE;
+	} else {
+  		toggle = TD_T_DATA0;
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1);
+	}
+	
+	urb_priv->td_cnt = 0;
+
+	if (data_len) {
+		data = pci_map_single (ohci->ohci_dev,
+			urb->transfer_buffer, data_len,
+			usb_pipeout (urb->pipe)
+				? PCI_DMA_TODEVICE
+				: PCI_DMA_FROMDEVICE
+			);
+	} else
+		data = 0;
+	
+	switch (usb_pipetype (urb->pipe)) {
+		case PIPE_BULK:
+			info = usb_pipeout (urb->pipe)? 
+				TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+			while(data_len > 4096) {		
+				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt);
+				data += 4096; data_len -= 4096; cnt++;
+			}
+			info = usb_pipeout (urb->pipe)?
+				TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt);
+			cnt++;
+
+			/* If the transfer size is multiple of the pipe mtu,
+			 * we may need an extra TD to create a empty frame
+			 * Note : another way to check this condition is
+			 * to test if(urb_priv->length > cnt) - Jean II */
+			if ((urb->transfer_flags & USB_ZERO_PACKET) &&
+			    usb_pipeout (urb->pipe) &&
+			    (urb->transfer_buffer_length != 0) && 
+			    ((urb->transfer_buffer_length % maxps) == 0)) {
+				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt);
+				cnt++;
+			}
+
+			if (!ohci->sleeping)
+				writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+			break;
+
+		case PIPE_INTERRUPT:
+			info = usb_pipeout (urb->pipe)? 
+				TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle;
+			td_fill (ohci, info, data, data_len, urb, cnt++);
+			break;
+
+		case PIPE_CONTROL:
+			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+			td_fill (ohci, info,
+				pci_map_single (ohci->ohci_dev,
+					urb->setup_packet, 8,
+					PCI_DMA_TODEVICE),
+				8, urb, cnt++); 
+			if (data_len > 0) {  
+				info = usb_pipeout (urb->pipe)? 
+					TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+				/* NOTE:  mishandles transfers >8K, some >4K */
+				td_fill (ohci, info, data, data_len, urb, cnt++);  
+			} 
+			info = usb_pipeout (urb->pipe)? 
+ 				TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+			td_fill (ohci, info, data, 0, urb, cnt++);
+			if (!ohci->sleeping)
+				writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+			break;
+
+		case PIPE_ISOCHRONOUS:
+			for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
+				td_fill (ohci, TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), 
+					data + urb->iso_frame_desc[cnt].offset, 
+					urb->iso_frame_desc[cnt].length, urb, cnt); 
+			}
+			break;
+	} 
+	if (urb_priv->length != cnt) 
+		dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+	__u32 tdINFO, tdBE, tdCBP;
+ 	__u16 tdPSW;
+ 	struct urb * urb = td->urb;
+ 	urb_priv_t * urb_priv = urb->hcpriv;
+	int dlen = 0;
+	int cc = 0;
+	
+	tdINFO = le32_to_cpup (&td->hwINFO);
+  	tdBE   = le32_to_cpup (&td->hwBE);
+  	tdCBP  = le32_to_cpup (&td->hwCBP);
+
+
+  	if (tdINFO & TD_ISO) {
+ 		tdPSW = le16_to_cpu (td->hwPSW[0]);
+ 		cc = (tdPSW >> 12) & 0xF;
+		if (cc < 0xE)  {
+			if (usb_pipeout(urb->pipe)) {
+				dlen = urb->iso_frame_desc[td->index].length;
+			} else {
+				dlen = tdPSW & 0x3ff;
+			}
+			urb->actual_length += dlen;
+			urb->iso_frame_desc[td->index].actual_length = dlen;
+			if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN))
+				cc = TD_CC_NOERROR;
+					 
+			urb->iso_frame_desc[td->index].status = cc_to_error[cc];
+		}
+	} else { /* BULK, INT, CONTROL DATA */
+		if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && 
+				((td->index == 0) || (td->index == urb_priv->length - 1)))) {
+ 			if (tdBE != 0) {
+ 				if (td->hwCBP == 0)
+					urb->actual_length += tdBE - td->data_dma + 1;
+  				else
+					urb->actual_length += tdCBP - td->data_dma;
+			}
+  		}
+  	}
+}
+
+/* handle an urb that is being unlinked */
+
+static void dl_del_urb (struct urb * urb)
+{
+	wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
+
+	urb_rm_priv_locked (urb);
+
+	if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+		urb->status = -ECONNRESET;
+		if (urb->complete)
+			urb->complete (urb);
+	} else {
+		urb->status = -ENOENT;
+
+		/* unblock sohci_unlink_urb */
+		if (wait_head)
+			wake_up (wait_head);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+ 
+static td_t * dl_reverse_done_list (ohci_t * ohci)
+{
+	__u32 td_list_hc;
+	td_t * td_rev = NULL;
+	td_t * td_list = NULL;
+  	urb_priv_t * urb_priv = NULL;
+  	unsigned long flags;
+  	
+  	spin_lock_irqsave (&usb_ed_lock, flags);
+  	
+	td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
+	ohci->hcca->done_head = 0;
+	
+	while (td_list_hc) {		
+		td_list = dma_to_td (ohci, td_list_hc);
+
+		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
+			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
+			dbg(" USB-error/status: %x : %p", 
+					TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list);
+			if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) {
+				if (urb_priv && ((td_list->index + 1) < urb_priv->length)) {
+					td_list->ed->hwHeadP = 
+						(urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) |
+									(td_list->ed->hwHeadP & cpu_to_le32 (0x2));
+					urb_priv->td_cnt += urb_priv->length - td_list->index - 1;
+				} else 
+					td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2);
+			}
+		}
+
+		td_list->next_dl_td = td_rev;	
+		td_rev = td_list;
+		td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;	
+	}	
+	spin_unlock_irqrestore (&usb_ed_lock, flags);
+	return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* there are some pending requests to remove 
+ * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev)
+ * - some URBs/TDs if urb_priv->state == URB_DEL */
+ 
+static void dl_del_list (ohci_t  * ohci, unsigned int frame)
+{
+	unsigned long flags;
+	ed_t * ed;
+	__u32 edINFO;
+	__u32 tdINFO;
+	td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP;
+	__u32 * td_p;
+	int ctrl = 0, bulk = 0;
+
+	spin_lock_irqsave (&usb_ed_lock, flags);
+
+	for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
+
+		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
+		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
+		edINFO = le32_to_cpup (&ed->hwINFO);
+		td_p = &ed->hwHeadP;
+
+		for (td = tdHeadP; td != tdTailP; td = td_next) { 
+			struct urb * urb = td->urb;
+			urb_priv_t * urb_priv = td->urb->hcpriv;
+			
+			td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
+			if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
+				tdINFO = le32_to_cpup (&td->hwINFO);
+				if (TD_CC_GET (tdINFO) < 0xE)
+					dl_transfer_length (td);
+				*td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
+
+				/* URB is done; clean up */
+				if (++(urb_priv->td_cnt) == urb_priv->length)
+					dl_del_urb (urb);
+			} else {
+				td_p = &td->hwNextTD;
+			}
+		}
+
+		if (ed->state & ED_DEL) { /* set by sohci_free_dev */
+			struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]);
+			td_free (ohci, tdTailP); /* free dummy td */
+   	 		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); 
+			ed->state = ED_NEW;
+			hash_free_ed(ohci, ed);
+   	 		/* if all eds are removed wake up sohci_free_dev */
+   	 		if (!--dev->ed_cnt) {
+				wait_queue_head_t *wait_head = dev->wait;
+
+				dev->wait = 0;
+				if (wait_head)
+					wake_up (wait_head);
+			}
+   	 	} else {
+   	 		ed->state &= ~ED_URB_DEL;
+			tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
+
+			if (tdHeadP == tdTailP) {
+				if (ed->state == ED_OPER)
+					ep_unlink(ohci, ed);
+				td_free (ohci, tdTailP);
+				ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP);
+				ed->state = ED_NEW;
+				hash_free_ed(ohci, ed);
+				--(usb_to_ohci (ohci->dev[edINFO & 0x7F]))->ed_cnt;
+			} else
+   	 			ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP);
+   	 	}
+
+		switch (ed->type) {
+			case PIPE_CONTROL:
+				ctrl = 1;
+				break;
+			case PIPE_BULK:
+				bulk = 1;
+				break;
+		}
+   	}
+   	
+	/* maybe reenable control and bulk lists */ 
+	if (!ohci->disabled) {
+		if (ctrl) 	/* reset control list */
+			writel (0, &ohci->regs->ed_controlcurrent);
+		if (bulk)	/* reset bulk list */
+			writel (0, &ohci->regs->ed_bulkcurrent);
+		if (!ohci->ed_rm_list[!frame] && !ohci->sleeping) {
+			if (ohci->ed_controltail)
+				ohci->hc_control |= OHCI_CTRL_CLE;
+			if (ohci->ed_bulktail)
+				ohci->hc_control |= OHCI_CTRL_BLE;
+			writel (ohci->hc_control, &ohci->regs->control);   
+		}
+	}
+
+   	ohci->ed_rm_list[frame] = NULL;
+   	spin_unlock_irqrestore (&usb_ed_lock, flags);
+}
+
+
+  		
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+
+static void dl_done_list (ohci_t * ohci, td_t * td_list)
+{
+  	td_t * td_list_next = NULL;
+	ed_t * ed;
+	int cc = 0;
+	struct urb * urb;
+	urb_priv_t * urb_priv;
+ 	__u32 tdINFO, edHeadP, edTailP;
+ 	
+ 	unsigned long flags;
+ 	
+  	while (td_list) {
+   		td_list_next = td_list->next_dl_td;
+   		
+  		urb = td_list->urb;
+  		urb_priv = urb->hcpriv;
+  		tdINFO = le32_to_cpup (&td_list->hwINFO);
+  		
+   		ed = td_list->ed;
+   		
+   		dl_transfer_length(td_list);
+ 			
+  		/* error code of transfer */
+  		cc = TD_CC_GET (tdINFO);
+  		if (cc == TD_CC_STALL)
+			usb_endpoint_halt(urb->dev,
+				usb_pipeendpoint(urb->pipe),
+				usb_pipeout(urb->pipe));
+  		
+  		if (!(urb->transfer_flags & USB_DISABLE_SPD)
+				&& (cc == TD_DATAUNDERRUN))
+			cc = TD_CC_NOERROR;
+
+  		if (++(urb_priv->td_cnt) == urb_priv->length) {
+			if ((ed->state & (ED_OPER | ED_UNLINK))
+					&& (urb_priv->state != URB_DEL)) {
+  				urb->status = cc_to_error[cc];
+  				sohci_return_urb (ohci, urb);
+  			} else {
+				spin_lock_irqsave (&usb_ed_lock, flags);
+  				dl_del_urb (urb);
+				spin_unlock_irqrestore (&usb_ed_lock, flags);
+			}
+  		}
+  		
+  		spin_lock_irqsave (&usb_ed_lock, flags);
+  		if (ed->state != ED_NEW) { 
+  			edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
+  			edTailP = le32_to_cpup (&ed->hwTailP);
+
+			/* unlink eds if they are not busy */
+     			if ((edHeadP == edTailP) && (ed->state == ED_OPER)) 
+     				ep_unlink (ohci, ed);
+     		}	
+     		spin_unlock_irqrestore (&usb_ed_lock, flags);
+     	
+    		td_list = td_list_next;
+  	}  
+}
+
+
+
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub 
+ *-------------------------------------------------------------------------*/
+ 
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+	0x12,       /*  __u8  bLength; */
+	0x01,       /*  __u8  bDescriptorType; Device */
+	0x10,	    /*  __u16 bcdUSB; v1.1 */
+	0x01,
+	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,	    /*  __u8  bDeviceSubClass; */
+	0x00,       /*  __u8  bDeviceProtocol; */
+	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x00,       /*  __u16 idVendor; */
+	0x00,
+	0x00,       /*  __u16 idProduct; */
+ 	0x00,
+	0x00,       /*  __u16 bcdDevice; */
+ 	0x00,
+	0x00,       /*  __u8  iManufacturer; */
+	0x02,       /*  __u8  iProduct; */
+	0x01,       /*  __u8  iSerialNumber; */
+	0x01        /*  __u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+	0x09,       /*  __u8  bLength; */
+	0x02,       /*  __u8  bDescriptorType; Configuration */
+	0x19,       /*  __u16 wTotalLength; */
+	0x00,
+	0x01,       /*  __u8  bNumInterfaces; */
+	0x01,       /*  __u8  bConfigurationValue; */
+	0x00,       /*  __u8  iConfiguration; */
+	0x40,       /*  __u8  bmAttributes; 
+                 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+	0x00,       /*  __u8  MaxPower; */
+      
+	/* interface */	  
+	0x09,       /*  __u8  if_bLength; */
+	0x04,       /*  __u8  if_bDescriptorType; Interface */
+	0x00,       /*  __u8  if_bInterfaceNumber; */
+	0x00,       /*  __u8  if_bAlternateSetting; */
+	0x01,       /*  __u8  if_bNumEndpoints; */
+	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,       /*  __u8  if_bInterfaceSubClass; */
+	0x00,       /*  __u8  if_bInterfaceProtocol; */
+	0x00,       /*  __u8  if_iInterface; */
+     
+	/* endpoint */
+	0x07,       /*  __u8  ep_bLength; */
+	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+ 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+ 	0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 	0x00,
+	0xff        /*  __u8  ep_bInterval; 255 ms */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ 
+ 
+static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len)
+{
+	int num_ports;
+	int i;
+	int ret;
+	int len;
+
+	__u8 data[8];
+
+	num_ports = roothub_a (ohci) & RH_A_NDP; 
+	if (num_ports > MAX_ROOT_PORTS) {
+		err ("bogus NDP=%d for OHCI usb-%s", num_ports,
+			ohci->ohci_dev->slot_name);
+		err ("rereads as NDP=%d",
+			readl (&ohci->regs->roothub.a) & RH_A_NDP);
+		/* retry later; "should not happen" */
+		return 0;
+	}
+	*(__u8 *) data = (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
+		? 1: 0;
+	ret = *(__u8 *) data;
+
+	for ( i = 0; i < num_ports; i++) {
+		*(__u8 *) (data + (i + 1) / 8) |= 
+			((roothub_portstatus (ohci, i) &
+				(RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC))
+			    ? 1: 0) << ((i + 1) % 8);
+		ret += *(__u8 *) (data + (i + 1) / 8);
+	}
+	len = i/8 + 1;
+  
+	if (ret > 0) { 
+		memcpy(rh_data, data,
+		       min_t(unsigned int, len,
+			   min_t(unsigned int, rh_len, sizeof(data))));
+		return len;
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
+ 
+static void rh_int_timer_do (unsigned long ptr)
+{
+	int len; 
+
+	struct urb * urb = (struct urb *) ptr;
+	ohci_t * ohci = urb->dev->bus->hcpriv;
+
+	if (ohci->disabled)
+		return;
+
+	/* ignore timers firing during PM suspend, etc */
+	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER)
+		goto out;
+
+	if(ohci->rh.send) { 
+		len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length);
+		if (len > 0) {
+			urb->actual_length = len;
+#ifdef DEBUG
+			urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));
+#endif
+			if (urb->complete)
+				urb->complete (urb);
+		}
+	}
+ out:
+	rh_init_int_timer (urb);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Root Hub INTs are polled by this timer */
+
+static int rh_init_int_timer (struct urb * urb) 
+{
+	ohci_t * ohci = urb->dev->bus->hcpriv;
+
+	ohci->rh.interval = urb->interval;
+	init_timer (&ohci->rh.rh_int_timer);
+	ohci->rh.rh_int_timer.function = rh_int_timer_do;
+	ohci->rh.rh_int_timer.data = (unsigned long) urb;
+	ohci->rh.rh_int_timer.expires = 
+			jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;
+	add_timer (&ohci->rh.rh_int_timer);
+	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x) 			len = (x); break
+#define WR_RH_STAT(x) 		writel((x), &ohci->regs->roothub.status)
+#define WR_RH_PORTSTAT(x) 	writel((x), &ohci->regs->roothub.portstatus[wIndex-1])
+#define RD_RH_STAT		roothub_status(ohci)
+#define RD_RH_PORTSTAT		roothub_portstatus(ohci,wIndex-1)
+
+/* request to virtual root hub */
+
+static int rh_submit_urb (struct urb * urb)
+{
+	struct usb_device * usb_dev = urb->dev;
+	ohci_t * ohci = usb_dev->bus->hcpriv;
+	unsigned int pipe = urb->pipe;
+	struct usb_ctrlrequest * cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+	void * data = urb->transfer_buffer;
+	int leni = urb->transfer_buffer_length;
+	int len = 0;
+	int status = TD_CC_NOERROR;
+	
+	__u32 datab[4];
+	__u8  * data_buf = (__u8 *) datab;
+	
+ 	__u16 bmRType_bReq;
+	__u16 wValue; 
+	__u16 wIndex;
+	__u16 wLength;
+
+	if (usb_pipeint(pipe)) {
+		ohci->rh.urb =  urb;
+		ohci->rh.send = 1;
+		ohci->rh.interval = urb->interval;
+		rh_init_int_timer(urb);
+		urb->status = cc_to_error [TD_CC_NOERROR];
+		
+		return 0;
+	}
+
+	bmRType_bReq  = cmd->bRequestType | (cmd->bRequest << 8);
+	wValue        = le16_to_cpu (cmd->wValue);
+	wIndex        = le16_to_cpu (cmd->wIndex);
+	wLength       = le16_to_cpu (cmd->wLength);
+
+	switch (bmRType_bReq) {
+	/* Request Destination:
+	   without flags: Device, 
+	   RH_INTERFACE: interface, 
+	   RH_ENDPOINT: endpoint,
+	   RH_CLASS means HUB here, 
+	   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
+	*/
+  
+		case RH_GET_STATUS: 				 		
+				*(__u16 *) data_buf = cpu_to_le16 (1); OK (2);
+		case RH_GET_STATUS | RH_INTERFACE: 	 		
+				*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);
+		case RH_GET_STATUS | RH_ENDPOINT:	 		
+				*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);   
+		case RH_GET_STATUS | RH_CLASS: 				
+				*(__u32 *) data_buf = cpu_to_le32 (
+					RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+				OK (4);
+		case RH_GET_STATUS | RH_OTHER | RH_CLASS: 	
+				*(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4);
+
+		case RH_CLEAR_FEATURE | RH_ENDPOINT:  
+			switch (wValue) {
+				case (RH_ENDPOINT_STALL): OK (0);
+			}
+			break;
+
+		case RH_CLEAR_FEATURE | RH_CLASS:
+			switch (wValue) {
+				case RH_C_HUB_LOCAL_POWER:
+					OK(0);
+				case (RH_C_HUB_OVER_CURRENT): 
+						WR_RH_STAT(RH_HS_OCIC); OK (0);
+			}
+			break;
+		
+		case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+			switch (wValue) {
+				case (RH_PORT_ENABLE): 			
+						WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+				case (RH_PORT_SUSPEND):			
+						WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+				case (RH_PORT_POWER):			
+						WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+				case (RH_C_PORT_CONNECTION):	
+						WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+				case (RH_C_PORT_ENABLE):		
+						WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+				case (RH_C_PORT_SUSPEND):		
+						WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+				case (RH_C_PORT_OVER_CURRENT):	
+						WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+				case (RH_C_PORT_RESET):			
+						WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); 
+			}
+			break;
+ 
+		case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+			switch (wValue) {
+				case (RH_PORT_SUSPEND):			
+						WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); 
+				case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+						if (RD_RH_PORTSTAT & RH_PS_CCS)
+						    WR_RH_PORTSTAT (RH_PS_PRS);
+						OK (0);
+				case (RH_PORT_POWER):			
+						WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); 
+				case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+						if (RD_RH_PORTSTAT & RH_PS_CCS)
+						    WR_RH_PORTSTAT (RH_PS_PES );
+						OK (0);
+			}
+			break;
+
+		case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0);
+
+		case RH_GET_DESCRIPTOR:
+			switch ((wValue & 0xff00) >> 8) {
+				case (0x01): /* device descriptor */
+					len = min_t(unsigned int,
+						  leni,
+						  min_t(unsigned int,
+						      sizeof (root_hub_dev_des),
+						      wLength));
+					data_buf = root_hub_dev_des; OK(len);
+				case (0x02): /* configuration descriptor */
+					len = min_t(unsigned int,
+						  leni,
+						  min_t(unsigned int,
+						      sizeof (root_hub_config_des),
+						      wLength));
+					data_buf = root_hub_config_des; OK(len);
+				case (0x03): /* string descriptors */
+					len = usb_root_hub_string (wValue & 0xff,
+						(int)(long) ohci->regs, "OHCI",
+						data, wLength);
+					if (len > 0) {
+						data_buf = data;
+						OK(min_t(int, leni, len));
+					}
+					// else fallthrough
+				default: 
+					status = TD_CC_STALL;
+			}
+			break;
+		
+		case RH_GET_DESCRIPTOR | RH_CLASS:
+		    {
+			    __u32 temp = roothub_a (ohci);
+
+			    data_buf [0] = 9;		// min length;
+			    data_buf [1] = 0x29;
+			    data_buf [2] = temp & RH_A_NDP;
+			    data_buf [3] = 0;
+			    if (temp & RH_A_PSM) 	/* per-port power switching? */
+				data_buf [3] |= 0x1;
+			    if (temp & RH_A_NOCP)	/* no overcurrent reporting? */
+				data_buf [3] |= 0x10;
+			    else if (temp & RH_A_OCPM)	/* per-port overcurrent reporting? */
+				data_buf [3] |= 0x8;
+
+			    datab [1] = 0;
+			    data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+			    temp = roothub_b (ohci);
+			    data_buf [7] = temp & RH_B_DR;
+			    if (data_buf [2] < 7) {
+				data_buf [8] = 0xff;
+			    } else {
+				data_buf [0] += 2;
+				data_buf [8] = (temp & RH_B_DR) >> 8;
+				data_buf [10] = data_buf [9] = 0xff;
+			    }
+				
+			    len = min_t(unsigned int, leni,
+				      min_t(unsigned int, data_buf [0], wLength));
+			    OK (len);
+			}
+ 
+		case RH_GET_CONFIGURATION: 	*(__u8 *) data_buf = 0x01; OK (1);
+
+		case RH_SET_CONFIGURATION: 	WR_RH_STAT (0x10000); OK (0);
+
+		default: 
+			dbg ("unsupported root hub command");
+			status = TD_CC_STALL;
+	}
+	
+#ifdef	DEBUG
+	// ohci_dump_roothub (ohci, 0);
+#endif
+
+	len = min_t(int, len, leni);
+	if (data != data_buf)
+	    memcpy (data, data_buf, len);
+  	urb->actual_length = len;
+	urb->status = cc_to_error [status];
+	
+#ifdef DEBUG
+	urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe));
+#endif
+
+	urb->hcpriv = NULL;
+	usb_dec_dev_use (usb_dev);
+	urb->dev = NULL;
+	if (urb->complete)
+	    	urb->complete (urb);
+	usb_put_urb (urb);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int rh_unlink_urb (struct urb * urb)
+{
+	ohci_t * ohci = urb->dev->bus->hcpriv;
+ 
+	if (ohci->rh.urb == urb) {
+		ohci->rh.send = 0;
+		del_timer (&ohci->rh.rh_int_timer);
+		ohci->rh.urb = NULL;
+
+		urb->hcpriv = NULL;
+		usb_dec_dev_use(urb->dev);
+		urb->dev = NULL;
+		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+			urb->status = -ECONNRESET;
+			if (urb->complete)
+				urb->complete (urb);
+		} else
+			urb->status = -ENOENT;
+		usb_put_urb (urb);
+	}
+	return 0;
+}
+ 
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t * ohci)
+{
+	int timeout = 30;
+	int smm_timeout = 50; /* 0,5 sec */
+	 	
+	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+		writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+		dbg("USB HC TakeOver from SMM");
+		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+			wait_ms (10);
+			if (--smm_timeout == 0) {
+				err("USB HC TakeOver failed!");
+				return -1;
+			}
+		}
+	}	
+		
+	/* Disable HC interrupts */
+	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+	dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
+		ohci->ohci_dev->slot_name,
+		readl (&ohci->regs->control));
+
+  	/* Reset USB (needed by some controllers) */
+	writel (0, &ohci->regs->control);
+      	
+	/* HC Reset requires max 10 ms delay */
+	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
+	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+		if (--timeout == 0) {
+			err("USB HC reset timed out!");
+			return -1;
+		}	
+		udelay (1);
+	}	 
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts 
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+  	__u32 mask;
+  	unsigned int fminterval;
+  	struct usb_device  * usb_dev;
+	struct ohci_device * dev;
+	
+	ohci->disabled = 1;
+
+	/* Tell the controller where the control and bulk lists are
+	 * The lists are empty now. */
+	 
+	writel (0, &ohci->regs->ed_controlhead);
+	writel (0, &ohci->regs->ed_bulkhead);
+	
+	writel (ohci->hcca_dma, &ohci->regs->hcca); /* a reset clears this */
+   
+  	fminterval = 0x2edf;
+	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+	fminterval |= ((((fminterval - 210) * 6) / 7) << 16); 
+	writel (fminterval, &ohci->regs->fminterval);	
+	writel (0x628, &ohci->regs->lsthresh);
+
+ 	/* start controller operations */
+ 	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+	ohci->disabled = 0;
+ 	writel (ohci->hc_control, &ohci->regs->control);
+ 
+	/* Choose the interrupts we care about now, others later on demand */
+	mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+	writel (mask, &ohci->regs->intrenable);
+	writel (mask, &ohci->regs->intrstatus);
+
+#ifdef	OHCI_USE_NPS
+	/* required for AMD-756 and some Mac platforms */
+	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+		&ohci->regs->roothub.a);
+	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif	/* OHCI_USE_NPS */
+
+	// POTPGT delay is bits 24-31, in 2 ms units.
+	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+ 
+	/* connect the virtual root hub */
+	ohci->rh.devnum = 0;
+	usb_dev = usb_alloc_dev (NULL, ohci->bus);
+	if (!usb_dev) {
+	    ohci->disabled = 1;
+	    return -ENOMEM;
+	}
+
+	dev = usb_to_ohci (usb_dev);
+	ohci->bus->root_hub = usb_dev;
+	usb_connect (usb_dev);
+	if (usb_register_root_hub (usb_dev, &ohci->ohci_dev->dev) != 0) {
+		usb_free_dev (usb_dev); 
+		ohci->disabled = 1;
+		return -ENODEV;
+	}
+	
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* called only from interrupt handler */
+
+static void check_timeouts (struct ohci *ohci)
+{
+	spin_lock (&usb_ed_lock);
+	while (!list_empty (&ohci->timeout_list)) {
+		struct urb	*urb;
+
+		urb = list_entry (ohci->timeout_list.next, struct urb, urb_list);
+		if (time_after (jiffies, urb->timeout))
+			break;
+
+		list_del_init (&urb->urb_list);
+		if (urb->status != -EINPROGRESS)
+			continue;
+
+		urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
+		spin_unlock (&usb_ed_lock);
+
+		// outside the interrupt handler (in a timer...)
+		// this reference would race interrupts
+		sohci_unlink_urb (urb);
+
+		spin_lock (&usb_ed_lock);
+	}
+	spin_unlock (&usb_ed_lock);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
+{
+	ohci_t * ohci = __ohci;
+	struct ohci_regs * regs = ohci->regs;
+ 	int ints; 
+
+	if ((ohci->hcca->done_head != 0) && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
+		ints =  OHCI_INTR_WDH;
+	} else if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0) {
+		return;
+	} 
+
+	// dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
+
+	if (ints & OHCI_INTR_UE) {
+		ohci->disabled++;
+		err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+			ohci->ohci_dev->slot_name);
+		// e.g. due to PCI Master/Target Abort
+
+#ifdef	DEBUG
+		ohci_dump (ohci, 1);
+#else
+		// FIXME: be optimistic, hope that bug won't repeat often.
+		// Make some non-interrupt context restart the controller.
+		// Count and limit the retries though; either hardware or
+		// software errors can go forever...
+#endif
+		hc_reset (ohci);
+	}
+  
+	if (ints & OHCI_INTR_WDH) {
+		writel (OHCI_INTR_WDH, &regs->intrdisable);	
+		dl_done_list (ohci, dl_reverse_done_list (ohci));
+		writel (OHCI_INTR_WDH, &regs->intrenable); 
+	}
+  
+	if (ints & OHCI_INTR_SO) {
+		dbg("USB Schedule overrun");
+		writel (OHCI_INTR_SO, &regs->intrenable); 	 
+	}
+
+	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...
+	if (ints & OHCI_INTR_SF) { 
+		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
+		writel (OHCI_INTR_SF, &regs->intrdisable);	
+		if (ohci->ed_rm_list[!frame] != NULL) {
+			dl_del_list (ohci, !frame);
+		}
+		if (ohci->ed_rm_list[frame] != NULL)
+			writel (OHCI_INTR_SF, &regs->intrenable);	
+	}
+
+	if (!list_empty (&ohci->timeout_list)) {
+		check_timeouts (ohci);
+// FIXME:  enable SF as needed in a timer;
+// don't make lots of 1ms interrupts
+// On unloaded USB, think 4k ~= 4-5msec
+		if (!list_empty (&ohci->timeout_list))
+			writel (OHCI_INTR_SF, &regs->intrenable);	
+	}
+
+	writel (ints, &regs->intrstatus);
+	writel (OHCI_INTR_MIE, &regs->intrenable);	
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* allocate OHCI */
+
+static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base)
+{
+	ohci_t * ohci;
+
+	ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL);
+	if (!ohci)
+		return NULL;
+		
+	memset (ohci, 0, sizeof (ohci_t));
+
+	ohci->hcca = pci_alloc_consistent (dev, sizeof *ohci->hcca,
+			&ohci->hcca_dma);
+        if (!ohci->hcca) {
+                kfree (ohci);
+                return NULL;
+        }
+        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
+
+	ohci->disabled = 1;
+	ohci->sleeping = 0;
+	ohci->irq = -1;
+	ohci->regs = mem_base;   
+
+	ohci->ohci_dev = dev;
+	pci_set_drvdata(dev, ohci);
+ 
+	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
+	list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
+
+	INIT_LIST_HEAD (&ohci->timeout_list);
+
+	ohci->bus = usb_alloc_bus (&sohci_device_operations);
+	if (!ohci->bus) {
+		pci_set_drvdata (dev, NULL);
+		pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca,
+				ohci->hcca, ohci->hcca_dma);
+		kfree (ohci);
+		return NULL;
+	}
+	ohci->bus->hcpriv = (void *) ohci;
+
+	return ohci;
+} 
+
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t * ohci)
+{	
+	dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
+
+	/* disconnect all devices */    
+	if (ohci->bus->root_hub)
+		usb_disconnect (&ohci->bus->root_hub);
+
+	if (!ohci->disabled)
+		hc_reset (ohci);
+	
+	if (ohci->irq >= 0) {
+		free_irq (ohci->irq, ohci);
+		ohci->irq = -1;
+	}
+	pci_set_drvdata(ohci->ohci_dev, NULL);
+	if (ohci->bus) {
+		if (ohci->bus->busnum)
+			usb_deregister_bus (ohci->bus);
+		usb_free_bus (ohci->bus);
+	}
+
+	list_del (&ohci->ohci_hcd_list);
+	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
+
+	ohci_mem_cleanup (ohci);
+    
+	/* unmap the IO address space */
+	iounmap (ohci->regs);
+
+	pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca,
+		ohci->hcca, ohci->hcca_dma);
+	kfree (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Increment the module usage count, start the control thread and
+ * return success. */
+
+static struct pci_driver ohci_pci_driver;
+ 
+static int __devinit
+hc_found_ohci (struct pci_dev *dev, int irq,
+	void *mem_base, const struct pci_device_id *id)
+{
+	ohci_t * ohci;
+	u8 latency, limit;
+	char buf[8], *bufp = buf;
+	int ret;
+
+#ifndef __sparc__
+	sprintf(buf, "%d", irq);
+#else
+	bufp = __irq_itoa(irq);
+#endif
+	printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
+		(unsigned long)	mem_base, bufp);
+	printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
+    
+	ohci = hc_alloc_ohci (dev, mem_base);
+	if (!ohci) {
+		return -ENOMEM;
+	}
+	if ((ret = ohci_mem_init (ohci)) < 0) {
+		hc_release_ohci (ohci);
+		return ret;
+	}
+	ohci->flags = id->driver_data;
+	if (ohci->flags & OHCI_QUIRK_AMD756)
+		printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
+
+	/* bad pci latencies can contribute to overruns */ 
+	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+	if (latency) {
+		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
+		if (limit && limit < latency) {
+			dbg ("PCI latency reduced to max %d", limit);
+			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
+			ohci->pci_latency = limit;
+		} else {
+			/* it might already have been reduced */
+			ohci->pci_latency = latency;
+		}
+	}
+
+	if (hc_reset (ohci) < 0) {
+		hc_release_ohci (ohci);
+		return -ENODEV;
+	}
+
+	/* FIXME this is a second HC reset; why?? */
+	writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
+	wait_ms (10);
+
+	usb_register_bus (ohci->bus);
+	
+	if (request_irq (irq, hc_interrupt, SA_SHIRQ,
+			ohci_pci_driver.name, ohci) != 0) {
+		err ("request interrupt %s failed", bufp);
+		hc_release_ohci (ohci);
+		return -EBUSY;
+	}
+	ohci->irq = irq;     
+
+	if (hc_start (ohci) < 0) {
+		err ("can't start usb-%s", dev->slot_name);
+		hc_release_ohci (ohci);
+		return -EBUSY;
+	}
+
+#ifdef	DEBUG
+	ohci_dump (ohci, 1);
+#endif
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+/* controller died; cleanup debris, then restart */
+/* must not be called from interrupt context */
+
+static void hc_restart (ohci_t *ohci)
+{
+	int temp;
+	int i;
+
+	if (ohci->pci_latency)
+		pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
+
+	ohci->disabled = 1;
+	ohci->sleeping = 0;
+	if (ohci->bus->root_hub)
+		usb_disconnect (&ohci->bus->root_hub);
+	
+	/* empty the interrupt branches */
+	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
+	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
+	
+	/* no EDs to remove */
+	ohci->ed_rm_list [0] = NULL;
+	ohci->ed_rm_list [1] = NULL;
+
+	/* empty control and bulk lists */	 
+	ohci->ed_isotail     = NULL;
+	ohci->ed_controltail = NULL;
+	ohci->ed_bulktail    = NULL;
+
+	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
+		err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
+	} else
+		dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
+}
+
+#endif	/* CONFIG_PM */
+
+/*-------------------------------------------------------------------------*/
+
+/* configured so that an OHCI device is always provided */
+/* always called with process context; sleeping is OK */
+
+static int __devinit
+ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+	unsigned long mem_resource, mem_len;
+	void *mem_base;
+	int status;
+
+	if (pci_enable_device(dev) < 0)
+		return -ENODEV;
+
+        if (!dev->irq) {
+        	err("found OHCI device with no IRQ assigned. check BIOS settings!");
+		pci_disable_device (dev);
+   	        return -ENODEV;
+        }
+	
+	/* we read its hardware registers as memory */
+	mem_resource = pci_resource_start(dev, 0);
+	mem_len = pci_resource_len(dev, 0);
+	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
+		dbg ("controller already in use");
+		pci_disable_device (dev);
+		return -EBUSY;
+	}
+
+	mem_base = ioremap_nocache (mem_resource, mem_len);
+	if (!mem_base) {
+		err("Error mapping OHCI memory");
+		release_mem_region (mem_resource, mem_len);
+		pci_disable_device (dev);
+		return -EFAULT;
+	}
+
+	/* controller writes into our memory */
+	pci_set_master (dev);
+
+	status = hc_found_ohci (dev, dev->irq, mem_base, id);
+	if (status < 0) {
+		iounmap (mem_base);
+		release_mem_region (mem_resource, mem_len);
+		pci_disable_device (dev);
+	}
+	return status;
+} 
+
+/*-------------------------------------------------------------------------*/
+
+/* may be called from interrupt context [interface spec] */
+/* may be called without controller present */
+/* may be called with controller, bus, and devices active */
+
+static void __devexit
+ohci_pci_remove (struct pci_dev *dev)
+{
+	ohci_t		*ohci = pci_get_drvdata(dev);
+
+	dbg ("remove %s controller usb-%s%s%s",
+		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
+		dev->slot_name,
+		ohci->disabled ? " (disabled)" : "",
+		in_interrupt () ? " in interrupt" : ""
+		);
+#ifdef	DEBUG
+	ohci_dump (ohci, 1);
+#endif
+
+	/* don't wake up sleeping controllers, or block in interrupt context */
+	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || in_interrupt ()) {
+		dbg ("controller being disabled");
+		ohci->disabled = 1;
+	}
+
+	/* on return, USB will always be reset (if present) */
+	if (ohci->disabled)
+		writel (ohci->hc_control = OHCI_USB_RESET,
+			&ohci->regs->control);
+
+	hc_release_ohci (ohci);
+
+	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
+	pci_disable_device (dev);
+}
+
+
+#ifdef	CONFIG_PM
+
+/*-------------------------------------------------------------------------*/
+
+static int
+ohci_pci_suspend (struct pci_dev *dev, u32 state)
+{
+	ohci_t			*ohci = pci_get_drvdata(dev);
+	unsigned long		flags;
+	u16 cmd;
+
+	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
+		dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
+			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
+		return -EIO;
+	}
+
+	/* act as if usb suspend can always be used */
+	info ("USB suspend: usb-%s", dev->slot_name);
+	ohci->sleeping = 1;
+
+	/* First stop processing */
+  	spin_lock_irqsave (&usb_ed_lock, flags);
+	ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
+	writel (ohci->hc_control, &ohci->regs->control);
+	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
+	(void) readl (&ohci->regs->intrstatus);
+  	spin_unlock_irqrestore (&usb_ed_lock, flags);
+
+	/* Wait a frame or two */
+	mdelay(1);
+	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
+		mdelay (1);
+		
+#ifdef CONFIG_PMAC_PBOOK
+	if (_machine == _MACH_Pmac)
+		disable_irq (ohci->irq);
+	/* else, 2.4 assumes shared irqs -- don't disable */
+#endif
+	/* Enable remote wakeup */
+	writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
+
+	/* Suspend chip and let things settle down a bit */
+	ohci->hc_control = OHCI_USB_SUSPEND;
+	writel (ohci->hc_control, &ohci->regs->control);
+	(void) readl (&ohci->regs->control);
+	mdelay (500); /* No schedule here ! */
+	switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
+		case OHCI_USB_RESET:
+			dbg("Bus in reset phase ???");
+			break;
+		case OHCI_USB_RESUME:
+			dbg("Bus in resume phase ???");
+			break;
+		case OHCI_USB_OPER:
+			dbg("Bus in operational phase ???");
+			break;
+		case OHCI_USB_SUSPEND:
+			dbg("Bus suspended");
+			break;
+	}
+	/* In some rare situations, Apple's OHCI have happily trashed
+	 * memory during sleep. We disable it's bus master bit during
+	 * suspend
+	 */
+	pci_read_config_word (dev, PCI_COMMAND, &cmd);
+	cmd &= ~PCI_COMMAND_MASTER;
+	pci_write_config_word (dev, PCI_COMMAND, cmd);
+#ifdef CONFIG_PMAC_PBOOK
+	{
+   	struct device_node	*of_node;
+
+	/* Disable USB PAD & cell clock */
+	of_node = pci_device_to_OF_node (ohci->ohci_dev);
+	if (of_node && _machine == _MACH_Pmac)
+		feature_set_usb_power (of_node, 0);
+	}
+#endif
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+ohci_pci_resume (struct pci_dev *dev)
+{
+	ohci_t		*ohci = pci_get_drvdata(dev);
+	int		temp;
+	unsigned long	flags;
+
+	/* guard against multiple resumes */
+	atomic_inc (&ohci->resume_count);
+	if (atomic_read (&ohci->resume_count) != 1) {
+		err ("concurrent PCI resumes for usb-%s", dev->slot_name);
+		atomic_dec (&ohci->resume_count);
+		return 0;
+	}
+
+#ifdef CONFIG_PMAC_PBOOK
+	{
+	struct device_node *of_node;
+
+	/* Re-enable USB PAD & cell clock */
+	of_node = pci_device_to_OF_node (ohci->ohci_dev);
+	if (of_node && _machine == _MACH_Pmac)
+		feature_set_usb_power (of_node, 1);
+	}
+#endif
+
+	/* did we suspend, or were we powered off? */
+	ohci->hc_control = readl (&ohci->regs->control);
+	temp = ohci->hc_control & OHCI_CTRL_HCFS;
+
+#ifdef DEBUG
+	/* the registers may look crazy here */
+	ohci_dump_status (ohci);
+#endif
+
+	/* Re-enable bus mastering */
+	pci_set_master(ohci->ohci_dev);
+	
+	switch (temp) {
+
+	case OHCI_USB_RESET:	// lost power
+		info ("USB restart: usb-%s", dev->slot_name);
+		hc_restart (ohci);
+		break;
+
+	case OHCI_USB_SUSPEND:	// host wakeup
+	case OHCI_USB_RESUME:	// remote wakeup
+		info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
+			(temp == OHCI_USB_SUSPEND)
+				? "host" : "remote");
+		ohci->hc_control = OHCI_USB_RESUME;
+		writel (ohci->hc_control, &ohci->regs->control);
+		(void) readl (&ohci->regs->control);
+		mdelay (20); /* no schedule here ! */
+		/* Some controllers (lucent) need a longer delay here */
+		mdelay (15);
+		temp = readl (&ohci->regs->control);
+		temp = ohci->hc_control & OHCI_CTRL_HCFS;
+		if (temp != OHCI_USB_RESUME) {
+			err ("controller usb-%s won't resume", dev->slot_name);
+			ohci->disabled = 1;
+			return -EIO;
+		}
+
+		/* Some chips likes being resumed first */
+		writel (OHCI_USB_OPER, &ohci->regs->control);
+		(void) readl (&ohci->regs->control);
+		mdelay (3);
+
+		/* Then re-enable operations */
+		spin_lock_irqsave (&usb_ed_lock, flags);
+		ohci->disabled = 0;
+		ohci->sleeping = 0;
+		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+		if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
+			if (ohci->ed_controltail)
+				ohci->hc_control |= OHCI_CTRL_CLE;
+			if (ohci->ed_bulktail)
+				ohci->hc_control |= OHCI_CTRL_BLE;
+		}
+		writel (ohci->hc_control, &ohci->regs->control);
+		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
+		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
+		/* Check for a pending done list */
+		writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);	
+		(void) readl (&ohci->regs->intrdisable);
+		spin_unlock_irqrestore (&usb_ed_lock, flags);
+#ifdef CONFIG_PMAC_PBOOK
+		if (_machine == _MACH_Pmac)
+			enable_irq (ohci->irq);
+#endif
+		if (ohci->hcca->done_head)
+			dl_done_list (ohci, dl_reverse_done_list (ohci));
+		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
+		writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+		writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+		break;
+
+	default:
+		warn ("odd PCI resume for usb-%s", dev->slot_name);
+	}
+
+	/* controller is operational, extra resumes are harmless */
+	atomic_dec (&ohci->resume_count);
+
+	return 0;
+}
+
+#endif	/* CONFIG_PM */
+
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
+
+	/*
+	 * AMD-756 [Viper] USB has a serious erratum when used with
+	 * lowspeed devices like mice.
+	 */
+	vendor:		0x1022,
+	device:		0x740c,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	driver_data:	OHCI_QUIRK_AMD756,
+
+} , {
+
+	/* handle any USB OHCI controller */
+	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),
+	class_mask: 	~0,
+
+	/* no matter who makes it */
+	vendor:		PCI_ANY_ID,
+	device:		PCI_ANY_ID,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	}, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
+
+static struct pci_driver ohci_pci_driver = {
+	name:		"usb-ohci",
+	id_table:	&ohci_pci_ids [0],
+
+	probe:		ohci_pci_probe,
+	remove:		__devexit_p(ohci_pci_remove),
+
+#ifdef	CONFIG_PM
+	suspend:	ohci_pci_suspend,
+	resume:		ohci_pci_resume,
+#endif	/* PM */
+};
+
+ 
+/*-------------------------------------------------------------------------*/
+
+static int __init ohci_hcd_init (void) 
+{
+	return pci_module_init (&ohci_pci_driver);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void __exit ohci_hcd_cleanup (void) 
+{	
+	pci_unregister_driver (&ohci_pci_driver);
+}
+
+module_init (ohci_hcd_init);
+module_exit (ohci_hcd_cleanup);
+
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/host/usb-ohci.h b/drivers/usb/host/usb-ohci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-ohci.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,643 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ * 
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ * 
+ * usb-ohci.h
+ */
+
+ 
+static int cc_to_error[16] = { 
+
+/* mapping of the OHCI CC status to error codes */ 
+	/* No  Error  */	0,
+	/* CRC Error  */	-EILSEQ,
+	/* Bit Stuff  */	-EPROTO,
+	/* Data Togg  */	-EILSEQ,
+	/* Stall      */	-EPIPE,
+	/* DevNotResp */	-ETIMEDOUT,
+	/* PIDCheck   */	-EPROTO,
+	/* UnExpPID   */	-EPROTO,
+	/* DataOver   */	-EOVERFLOW,
+	/* DataUnder  */	-EREMOTEIO,
+	/* reservd    */	-ETIMEDOUT,
+	/* reservd    */	-ETIMEDOUT,
+	/* BufferOver */	-ECOMM,
+	/* BuffUnder  */	-ENOSR,
+	/* Not Access */	-ETIMEDOUT,
+	/* Not Access */	-ETIMEDOUT 
+};
+
+#include <linux/config.h>
+
+/* ED States */
+
+#define ED_NEW 		0x00
+#define ED_UNLINK 	0x01
+#define ED_OPER		0x02
+#define ED_DEL		0x04
+#define ED_URB_DEL  	0x08
+
+/* usb_ohci_ed */
+struct ed {
+	__u32 hwINFO;       
+	__u32 hwTailP;
+	__u32 hwHeadP;
+	__u32 hwNextED;
+
+	struct ed * ed_prev;  
+	__u8 int_period;
+	__u8 int_branch;
+	__u8 int_load; 
+	__u8 int_interval;
+	__u8 state;
+	__u8 type; 
+	__u16 last_iso;
+	struct ed * ed_rm_list;
+
+	dma_addr_t dma;
+	__u32 unused[3];
+} __attribute((aligned(16)));
+typedef struct ed ed_t;
+
+ 
+/* TD info field */
+#define TD_CC       0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC       0x0C000000
+#define TD_T        0x03000000
+#define TD_T_DATA0  0x02000000
+#define TD_T_DATA1  0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R        0x00040000
+#define TD_DI       0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP       0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN    0x00100000
+#define TD_DP_OUT   0x00080000
+
+#define TD_ISO	    0x00010000
+#define TD_DEL      0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR      0x00
+#define TD_CC_CRC          0x01
+#define TD_CC_BITSTUFFING  0x02
+#define TD_CC_DATATOGGLEM  0x03
+#define TD_CC_STALL        0x04
+#define TD_DEVNOTRESP      0x05
+#define TD_PIDCHECKFAIL    0x06
+#define TD_UNEXPECTEDPID   0x07
+#define TD_DATAOVERRUN     0x08
+#define TD_DATAUNDERRUN    0x09
+#define TD_BUFFEROVERRUN   0x0C
+#define TD_BUFFERUNDERRUN  0x0D
+#define TD_NOTACCESSED     0x0F
+
+
+#define MAXPSW 1
+
+struct td {
+	__u32 hwINFO;
+  	__u32 hwCBP;		/* Current Buffer Pointer */
+  	__u32 hwNextTD;		/* Next TD Pointer */
+  	__u32 hwBE;		/* Memory Buffer End Pointer */
+
+  	__u16 hwPSW[MAXPSW];
+  	__u8 unused;
+  	__u8 index;
+  	struct ed * ed;
+  	struct td * next_dl_td;
+  	struct urb * urb;
+
+	dma_addr_t td_dma;
+	dma_addr_t data_dma;
+	__u32 unused2[2];
+} __attribute((aligned(32)));	/* normally 16, iso needs 32 */
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP	(1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of.  It must be 256-byte aligned.
+ */
+ 
+#define NUM_INTS 32	/* part of the OHCI standard */
+struct ohci_hcca {
+	__u32	int_table[NUM_INTS];	/* Interrupt ED table */
+	__u16	frame_no;		/* current frame number */
+	__u16	pad1;			/* set to 0 on each frame_no change */
+	__u32	done_head;		/* info returned for an interrupt */
+	u8		reserved_for_hc[116];
+} __attribute((aligned(256)));
+
+  
+/*
+ * Maximum number of root hub ports.  
+ */
+#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region.  This is Memory Mapped I/O.  You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+	/* control and status registers */
+	__u32	revision;
+	__u32	control;
+	__u32	cmdstatus;
+	__u32	intrstatus;
+	__u32	intrenable;
+	__u32	intrdisable;
+	/* memory pointers */
+	__u32	hcca;
+	__u32	ed_periodcurrent;
+	__u32	ed_controlhead;
+	__u32	ed_controlcurrent;
+	__u32	ed_bulkhead;
+	__u32	ed_bulkcurrent;
+	__u32	donehead;
+	/* frame counters */
+	__u32	fminterval;
+	__u32	fmremaining;
+	__u32	fmnumber;
+	__u32	periodicstart;
+	__u32	lsthresh;
+	/* Root hub ports */
+	struct	ohci_roothub_regs {
+		__u32	a;
+		__u32	b;
+		__u32	status;
+		__u32	portstatus[MAX_ROOT_PORTS];
+	} roothub;
+} __attribute((aligned(32)));
+
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR	(3 << 0)	/* control/bulk service ratio */
+#define OHCI_CTRL_PLE	(1 << 2)	/* periodic list enable */
+#define OHCI_CTRL_IE	(1 << 3)	/* isochronous enable */
+#define OHCI_CTRL_CLE	(1 << 4)	/* control list enable */
+#define OHCI_CTRL_BLE	(1 << 5)	/* bulk list enable */
+#define OHCI_CTRL_HCFS	(3 << 6)	/* host controller functional state */
+#define OHCI_CTRL_IR	(1 << 8)	/* interrupt routing */
+#define OHCI_CTRL_RWC	(1 << 9)	/* remote wakeup connected */
+#define OHCI_CTRL_RWE	(1 << 10)	/* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+#	define OHCI_USB_RESET	(0 << 6)
+#	define OHCI_USB_RESUME	(1 << 6)
+#	define OHCI_USB_OPER	(2 << 6)
+#	define OHCI_USB_SUSPEND	(3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR	(1 << 0)	/* host controller reset */
+#define OHCI_CLF  	(1 << 1)	/* control list filled */
+#define OHCI_BLF  	(1 << 2)	/* bulk list filled */
+#define OHCI_OCR  	(1 << 3)	/* ownership change request */
+#define OHCI_SOC  	(3 << 16)	/* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO	(1 << 0)	/* scheduling overrun */
+#define OHCI_INTR_WDH	(1 << 1)	/* writeback of done_head */
+#define OHCI_INTR_SF	(1 << 2)	/* start frame */
+#define OHCI_INTR_RD	(1 << 3)	/* resume detect */
+#define OHCI_INTR_UE	(1 << 4)	/* unrecoverable error */
+#define OHCI_INTR_FNO	(1 << 5)	/* frame number overflow */
+#define OHCI_INTR_RHSC	(1 << 6)	/* root hub status change */
+#define OHCI_INTR_OC	(1 << 30)	/* ownership change */
+#define OHCI_INTR_MIE	(1 << 31)	/* master interrupt enable */
+
+
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+	int devnum; /* Address of Root Hub endpoint */ 
+	void * urb;
+	void * int_addr;
+	int send;
+	int interval;
+	struct timer_list rh_int_timer;
+};
+
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+ 
+/* destination of request */
+#define RH_INTERFACE               0x01
+#define RH_ENDPOINT                0x02
+#define RH_OTHER                   0x03
+
+#define RH_CLASS                   0x20
+#define RH_VENDOR                  0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS		0x0500
+#define RH_GET_DESCRIPTOR	0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP               0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION         0x00
+#define RH_PORT_ENABLE             0x01
+#define RH_PORT_SUSPEND            0x02
+#define RH_PORT_OVER_CURRENT       0x03
+#define RH_PORT_RESET              0x04
+#define RH_PORT_POWER              0x08
+#define RH_PORT_LOW_SPEED          0x09
+
+#define RH_C_PORT_CONNECTION       0x10
+#define RH_C_PORT_ENABLE           0x11
+#define RH_C_PORT_SUSPEND          0x12
+#define RH_C_PORT_OVER_CURRENT     0x13
+#define RH_C_PORT_RESET            0x14  
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER       0x00
+#define RH_C_HUB_OVER_CURRENT      0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP    0x00
+#define RH_ENDPOINT_STALL          0x01
+
+#define RH_ACK                     0x01
+#define RH_REQ_ERR                 -1
+#define RH_NACK                    0x00
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+ 
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS            0x00000001   	/* current connect status */
+#define RH_PS_PES            0x00000002   	/* port enable status*/
+#define RH_PS_PSS            0x00000004   	/* port suspend status */
+#define RH_PS_POCI           0x00000008   	/* port over current indicator */
+#define RH_PS_PRS            0x00000010  	/* port reset status */
+#define RH_PS_PPS            0x00000100   	/* port power status */
+#define RH_PS_LSDA           0x00000200    	/* low speed device attached */
+#define RH_PS_CSC            0x00010000 	/* connect status change */
+#define RH_PS_PESC           0x00020000   	/* port enable status change */
+#define RH_PS_PSSC           0x00040000    	/* port suspend status change */
+#define RH_PS_OCIC           0x00080000    	/* over current indicator change */
+#define RH_PS_PRSC           0x00100000   	/* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS	     0x00000001		/* local power status */
+#define RH_HS_OCI	     0x00000002		/* over current indicator */
+#define RH_HS_DRWE	     0x00008000		/* device remote wakeup enable */
+#define RH_HS_LPSC	     0x00010000		/* local power status change */
+#define RH_HS_OCIC	     0x00020000		/* over current indicator change */
+#define RH_HS_CRWE	     0x80000000		/* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR		0x0000ffff		/* device removable flags */
+#define RH_B_PPCM	0xffff0000		/* port power control mask */
+
+/* roothub.a masks */
+#define	RH_A_NDP	(0xff << 0)		/* number of downstream ports */
+#define	RH_A_PSM	(1 << 8)		/* power switching mode */
+#define	RH_A_NPS	(1 << 9)		/* no power switching */
+#define	RH_A_DT		(1 << 10)		/* device type (mbz) */
+#define	RH_A_OCPM	(1 << 11)		/* over current protection mode */
+#define	RH_A_NOCP	(1 << 12)		/* no over current protection */
+#define	RH_A_POTPGT	(0xff << 24)		/* power on to power good time */
+
+/* urb */
+typedef struct 
+{
+	ed_t * ed;
+	__u16 length;	// number of tds associated with this request
+	__u16 td_cnt;	// number of tds already serviced
+	int   state;
+	wait_queue_head_t * wait;
+	td_t * td[0];	// list pointer to all corresponding TDs associated with this request
+
+} urb_priv_t;
+#define URB_DEL 1
+
+
+/* Hash struct used for TD/ED hashing */
+struct hash_t {
+	void		*virt;
+	dma_addr_t	dma;
+	struct hash_t	*next; // chaining for collision cases
+};
+
+/* List of TD/ED hash entries */
+struct hash_list_t {
+	struct hash_t	*head;
+	struct hash_t	*tail;
+};
+
+#define TD_HASH_SIZE    64    /* power'o'two */
+#define ED_HASH_SIZE    64    /* power'o'two */
+
+#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)
+#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE)
+
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+
+typedef struct ohci {
+	struct ohci_hcca *hcca;		/* hcca */
+	dma_addr_t hcca_dma;
+
+	int irq;
+	int disabled;			/* e.g. got a UE, we're hung */
+	int sleeping;
+	atomic_t resume_count;		/* defending against multiple resumes */
+	unsigned long flags;		/* for HC bugs */
+#define	OHCI_QUIRK_AMD756	0x01		/* erratum #4 */
+
+	struct ohci_regs * regs;	/* OHCI controller's memory */
+	struct list_head ohci_hcd_list;	/* list of all ohci_hcd */
+
+	struct ohci * next; 		// chain of ohci device contexts
+	struct list_head timeout_list;
+	// struct list_head urb_list; 	// list of all pending urbs
+	// spinlock_t urb_list_lock; 	// lock to keep consistency 
+  
+	int ohci_int_load[32];		/* load of the 32 Interrupt Chains (for load balancing)*/
+	ed_t * ed_rm_list[2];     /* lists of all endpoints to be removed */
+	ed_t * ed_bulktail;       /* last endpoint of bulk list */
+	ed_t * ed_controltail;    /* last endpoint of control list */
+ 	ed_t * ed_isotail;        /* last endpoint of iso list */
+	int intrstatus;
+	__u32 hc_control;		/* copy of the hc control reg */
+	struct usb_bus * bus;    
+	struct usb_device * dev[128];
+	struct virt_root_hub rh;
+
+	/* PCI device handle, settings, ... */
+	struct pci_dev	*ohci_dev;
+	u8		pci_latency;
+	struct pci_pool	*td_cache;
+	struct pci_pool	*dev_cache;
+	struct hash_list_t	td_hash[TD_HASH_SIZE];
+	struct hash_list_t	ed_hash[ED_HASH_SIZE];
+
+} ohci_t;
+
+#define NUM_EDS 32		/* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+	ed_t 	ed[NUM_EDS];
+	dma_addr_t dma;
+	int ed_cnt;
+	wait_queue_head_t * wait;
+};
+
+// #define ohci_to_usb(ohci)	((ohci)->usb)
+#define usb_to_ohci(usb)	((struct ohci_device *)(usb)->hcpriv)
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags);
+static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed);
+/* td */
+static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, struct urb * urb, int index);
+static void td_submit_urb(struct urb * urb);
+/* root hub */
+static int rh_submit_urb(struct urb * urb);
+static int rh_unlink_urb(struct urb * urb);
+static int rh_init_int_timer(struct urb * urb);
+
+/*-------------------------------------------------------------------------*/
+
+#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)
+
+#ifdef DEBUG
+#	define OHCI_MEM_FLAGS	SLAB_POISON
+#else
+#	define OHCI_MEM_FLAGS	0
+#endif
+ 
+#ifndef CONFIG_PCI
+#	error "usb-ohci currently requires PCI-based controllers"
+	/* to support non-PCI OHCIs, you need custom bus/mem/... glue */
+#endif
+
+
+/* Recover a TD/ED using its collision chain */
+static void *
+dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
+{
+	struct hash_t * scan = entry->head;
+	while (scan && scan->dma != dma)
+		scan = scan->next;
+	if (!scan)
+		BUG();
+	return scan->virt;
+}
+
+static struct ed *
+dma_to_ed (struct ohci * hc, dma_addr_t ed_dma)
+{
+	return (struct ed *) dma_to_ed_td(&(hc->ed_hash[ED_HASH_FUNC(ed_dma)]),
+				      ed_dma);
+}
+
+static struct td *
+dma_to_td (struct ohci * hc, dma_addr_t td_dma)
+{
+	return (struct td *) dma_to_ed_td(&(hc->td_hash[TD_HASH_FUNC(td_dma)]),
+				      td_dma);
+}
+
+/* Add a hash entry for a TD/ED; return true on success */
+static int
+hash_add_ed_td(struct hash_list_t * entry, void * virt, dma_addr_t dma)
+{
+	struct hash_t * scan;
+	
+	scan = (struct hash_t *)kmalloc(sizeof(struct hash_t), ALLOC_FLAGS);
+	if (!scan)
+		return 0;
+	
+	if (!entry->tail) {
+		entry->head = entry->tail = scan;
+	} else {
+		entry->tail->next = scan;
+		entry->tail = scan;
+	}
+	
+	scan->virt = virt;
+	scan->dma = dma;
+	scan->next = NULL;
+	return 1;
+}
+
+static int
+hash_add_ed (struct ohci * hc, struct ed * ed)
+{
+	return hash_add_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]),
+			ed, ed->dma);
+}
+
+static int
+hash_add_td (struct ohci * hc, struct td * td)
+{
+	return hash_add_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]),
+			td, td->td_dma);
+}
+
+
+static void
+hash_free_ed_td (struct hash_list_t * entry, void * virt)
+{
+	struct hash_t *scan, *prev;
+	scan = prev = entry->head;
+
+	// Find and unlink hash entry
+	while (scan && scan->virt != virt) {
+		prev = scan;
+		scan = scan->next;
+	}
+	if (scan) {
+		if (scan == entry->head) {
+			if (entry->head == entry->tail)
+				entry->head = entry->tail = NULL;
+			else
+				entry->head = scan->next;
+		} else if (scan == entry->tail) {
+			entry->tail = prev;
+			prev->next = NULL;
+		} else
+			prev->next = scan->next;
+		kfree(scan);
+	}
+}
+
+static void
+hash_free_ed (struct ohci * hc, struct ed * ed)
+{
+	hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed);
+}
+
+static void
+hash_free_td (struct ohci * hc, struct td * td)
+{
+	hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);
+}
+
+
+static int ohci_mem_init (struct ohci *ohci)
+{
+	ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev,
+		sizeof (struct td),
+		32 /* byte alignment */,
+		0 /* no page-crossing issues */,
+		GFP_KERNEL | OHCI_MEM_FLAGS);
+	if (!ohci->td_cache)
+		return -ENOMEM;
+	ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev,
+		sizeof (struct ohci_device),
+		16 /* byte alignment */,
+		0 /* no page-crossing issues */,
+		GFP_KERNEL | OHCI_MEM_FLAGS);
+	if (!ohci->dev_cache)
+		return -ENOMEM;
+	return 0;
+}
+
+static void ohci_mem_cleanup (struct ohci *ohci)
+{
+	if (ohci->td_cache) {
+		pci_pool_destroy (ohci->td_cache);
+		ohci->td_cache = 0;
+	}
+	if (ohci->dev_cache) {
+		pci_pool_destroy (ohci->dev_cache);
+		ohci->dev_cache = 0;
+	}
+}
+
+/* TDs ... */
+static struct td *
+td_alloc (struct ohci *hc, int mem_flags)
+{
+	dma_addr_t	dma;
+	struct td	*td;
+
+	td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
+	if (td) {
+		td->td_dma = dma;
+
+		/* hash it for later reverse mapping */
+		if (!hash_add_td (hc, td)) {
+			pci_pool_free (hc->td_cache, td, dma);
+			return NULL;
+		}
+	}
+	return td;
+}
+
+static inline void
+td_free (struct ohci *hc, struct td *td)
+{
+	hash_free_td (hc, td);
+	pci_pool_free (hc->td_cache, td, td->td_dma);
+}
+
+
+/* DEV + EDs ... only the EDs need to be consistent */
+static struct ohci_device *
+dev_alloc (struct ohci *hc, int mem_flags)
+{
+	dma_addr_t		dma;
+	struct ohci_device	*dev;
+	int			i, offset;
+
+	dev = pci_pool_alloc (hc->dev_cache, mem_flags, &dma);
+	if (dev) {
+		memset (dev, 0, sizeof (*dev));
+		dev->dma = dma;
+		offset = ((char *)&dev->ed) - ((char *)dev);
+		for (i = 0; i < NUM_EDS; i++, offset += sizeof dev->ed [0])
+			dev->ed [i].dma = dma + offset;
+		/* add to hashtable if used */
+	}
+	return dev;
+}
+
+static inline void
+dev_free (struct ohci *hc, struct ohci_device *dev)
+{
+	pci_pool_free (hc->dev_cache, dev, dev->dma);
+}
+
diff -Nru a/drivers/usb/host/usb-uhci-debug.h b/drivers/usb/host/usb-uhci-debug.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-uhci-debug.h	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,141 @@
+#ifdef DEBUG
+static void __attribute__((__unused__)) uhci_show_qh (puhci_desc_t qh)
+{
+	if (qh->type != QH_TYPE) {
+		dbg("qh has not QH_TYPE");
+		return;
+	}
+	dbg("QH @ %p/%08llX:", qh, (unsigned long long)qh->dma_addr);
+
+	if (qh->hw.qh.head & UHCI_PTR_TERM)
+		dbg("    Head Terminate");
+	else 
+		dbg("    Head: %s @ %08X",
+		    (qh->hw.qh.head & UHCI_PTR_QH?"QH":"TD"),
+		    qh->hw.qh.head & ~UHCI_PTR_BITS);
+
+	if (qh->hw.qh.element & UHCI_PTR_TERM)
+		dbg("    Element Terminate");
+	else 
+		dbg("    Element: %s @ %08X",
+		    (qh->hw.qh.element & UHCI_PTR_QH?"QH":"TD"),
+		    qh->hw.qh.element & ~UHCI_PTR_BITS);
+}
+#endif
+
+#if 0
+static void uhci_show_td (puhci_desc_t td)
+{
+	char *spid;
+	
+	switch (td->hw.td.info & 0xff) {
+	case USB_PID_SETUP:
+		spid = "SETUP";
+		break;
+	case USB_PID_OUT:
+		spid = " OUT ";
+		break;
+	case USB_PID_IN:
+		spid = " IN  ";
+		break;
+	default:
+		spid = "  ?  ";
+		break;
+	}
+
+	warn("  TD @ %p/%08X, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x",
+	     td, td->dma_addr,
+	     td->hw.td.info >> 21,
+	     ((td->hw.td.info >> 19) & 1),
+	     (td->hw.td.info >> 15) & 15,
+	     (td->hw.td.info >> 8) & 127,
+	     spid,
+	     td->hw.td.buffer);
+
+	warn("    Len=%02x e%d %s%s%s%s%s%s%s%s%s%s",
+	     td->hw.td.status & 0x7ff,
+	     ((td->hw.td.status >> 27) & 3),
+	     (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "",
+	     (td->hw.td.status & TD_CTRL_LS) ? "LS " : "",
+	     (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "",
+	     (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "",
+	     (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "",
+	     (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
+	     (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "",
+	     (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "",
+	     (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
+	     (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : ""
+		);
+
+	if (td->hw.td.link & UHCI_PTR_TERM)
+		warn("   TD Link Terminate");
+	else 
+		warn("    Link points to %s @ %08x, %s",
+		     (td->hw.td.link & UHCI_PTR_QH?"QH":"TD"),
+		     td->hw.td.link & ~UHCI_PTR_BITS,
+		     (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first"));
+}
+#endif
+
+#ifdef DEBUG
+static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
+{
+	dbg("  stat%d     =     %04x   %s%s%s%s%s%s%s%s",
+	     port,
+	     status,
+	     (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
+	     (status & USBPORTSC_PR) ? "PortReset " : "",
+	     (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
+	     (status & USBPORTSC_RD) ? "ResumeDetect " : "",
+	     (status & USBPORTSC_PEC) ? "EnableChange " : "",
+	     (status & USBPORTSC_PE) ? "PortEnabled " : "",
+	     (status & USBPORTSC_CSC) ? "ConnectChange " : "",
+	     (status & USBPORTSC_CCS) ? "PortConnected " : "");
+}
+
+void uhci_show_status (puhci_t s)
+{
+	unsigned int io_addr = s->io_addr;
+	unsigned short usbcmd, usbstat, usbint, usbfrnum;
+	unsigned int flbaseadd;
+	unsigned char sof;
+	unsigned short portsc1, portsc2;
+
+	usbcmd = inw (io_addr + 0);
+	usbstat = inw (io_addr + 2);
+	usbint = inw (io_addr + 4);
+	usbfrnum = inw (io_addr + 6);
+	flbaseadd = inl (io_addr + 8);
+	sof = inb (io_addr + 12);
+	portsc1 = inw (io_addr + 16);
+	portsc2 = inw (io_addr + 18);
+
+	dbg("  usbcmd    =     %04x   %s%s%s%s%s%s%s%s",
+	     usbcmd,
+	     (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
+	     (usbcmd & USBCMD_CF) ? "CF " : "",
+	     (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
+	     (usbcmd & USBCMD_FGR) ? "FGR " : "",
+	     (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
+	     (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
+	     (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+	     (usbcmd & USBCMD_RS) ? "RS " : "");
+
+	dbg("  usbstat   =     %04x   %s%s%s%s%s%s",
+	     usbstat,
+	     (usbstat & USBSTS_HCH) ? "HCHalted " : "",
+	     (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
+	     (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
+	     (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
+	     (usbstat & USBSTS_ERROR) ? "USBError " : "",
+	     (usbstat & USBSTS_USBINT) ? "USBINT " : "");
+
+	dbg("  usbint    =     %04x", usbint);
+	dbg("  usbfrnum  =   (%d)%03x", (usbfrnum >> 10) & 1,
+	     0xfff & (4 * (unsigned int) usbfrnum));
+	dbg("  flbaseadd = %08x", flbaseadd);
+	dbg("  sof       =       %02x", sof);
+	uhci_show_sc (1, portsc1);
+	uhci_show_sc (2, portsc2);
+}
+#endif
diff -Nru a/drivers/usb/host/usb-uhci.c b/drivers/usb/host/usb-uhci.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-uhci.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,3163 @@
+/* 
+ * Universal Host Controller Interface driver for USB (take II).
+ *
+ * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar)
+ *               Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
+ *               Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
+ *               Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter)
+ * (c) 2000      Yggdrasil Computing, Inc. (port of new PCI interface support
+ *               from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+ * (C) 2000      David Brownell, david-b@pacbell.net (usb-ohci.c)
+ *          
+ * HW-initalization based on material of
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Gregory P. Smith
+ *
+ * $Id: usb-uhci.c,v 1.275 2002/01/19 20:57:33 acher Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/interrupt.h>	/* for in_interrupt() */
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#include <linux/timer.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+/* This enables more detailed sanity checks in submit_iso */
+//#define ISO_SANITY_CHECK
+
+/* This enables debug printks */
+#define DEBUG
+
+/* This enables all symbols to be exported, to ease debugging oopses */
+//#define DEBUG_SYMBOLS
+
+/* This enables an extra UHCI slab for memory debugging */
+#define DEBUG_SLAB
+
+#define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__
+
+#include <linux/usb.h>
+#include "../core/hcd.h"
+#include "usb-uhci.h"
+#include "usb-uhci-debug.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.275"
+#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
+#undef DEBUG
+#undef dbg
+#define dbg(format, arg...) do {} while (0)
+#define DEBUG_SYMBOLS
+#ifdef DEBUG_SYMBOLS
+	#define _static
+	#ifndef EXPORT_SYMTAB
+		#define EXPORT_SYMTAB
+	#endif
+#else
+	#define _static static
+#endif
+
+#define queue_dbg dbg //err
+#define async_dbg dbg //err
+
+#ifdef DEBUG_SLAB
+	static kmem_cache_t *urb_priv_kmem;
+#endif
+
+#define SLAB_FLAG     (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL)
+
+/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth
+ * Reclamation: feature that puts loop on descriptor loop when
+ * there's some transfer going on. With FSBR, USB performance
+ * is optimal, but PCI can be slowed down up-to 5 times, slowing down
+ * system performance (eg. framebuffer devices).
+ */
+#define CONFIG_USB_UHCI_HIGH_BANDWIDTH 
+
+/* *_DEPTH_FIRST puts descriptor in depth-first mode. This has
+ * somehow similar effect to FSBR (higher speed), but does not
+ * slow PCI down. OTOH USB performace is slightly slower than
+ * in FSBR case and single device could hog whole USB, starving
+ * other devices.
+ */
+#define USE_CTRL_DEPTH_FIRST 0  // 0: Breadth first, 1: Depth first
+#define USE_BULK_DEPTH_FIRST 0  // 0: Breadth first, 1: Depth first
+
+/* Turning off both CONFIG_USB_UHCI_HIGH_BANDWITH and *_DEPTH_FIRST
+ * will lead to <64KB/sec performance over USB for bulk transfers targeting
+ * one device's endpoint. You probably do not want to do that.
+ */
+
+// stop bandwidth reclamation after (roughly) 50ms
+#define IDLE_TIMEOUT  (HZ/20)
+
+// Suppress HC interrupt error messages for 5s
+#define ERROR_SUPPRESSION_TIME (HZ*5)
+
+_static int rh_submit_urb (struct urb *urb);
+_static int rh_unlink_urb (struct urb *urb);
+_static int delete_qh (uhci_t *s, uhci_desc_t *qh);
+_static int process_transfer (uhci_t *s, struct urb *urb, int mode);
+_static int process_interrupt (uhci_t *s, struct urb *urb);
+_static int process_iso (uhci_t *s, struct urb *urb, int force);
+
+// How much URBs with ->next are walked
+#define MAX_NEXT_COUNT 2048
+
+static uhci_t *devs = NULL;
+
+/* used by userspace UHCI data structure dumper */
+uhci_t **uhci_devices = &devs;
+
+/*-------------------------------------------------------------------*/
+// Cleans up collected QHs, but not more than 100 in one go
+void clean_descs(uhci_t *s, int force)
+{
+	struct list_head *q;
+	uhci_desc_t *qh;
+	int now=UHCI_GET_CURRENT_FRAME(s), n=0;
+
+	q=s->free_desc.prev;
+
+	while (q != &s->free_desc && (force || n<100)) {
+		qh = list_entry (q, uhci_desc_t, horizontal);		
+		q=qh->horizontal.prev;
+
+		if ((qh->last_used!=now) || force)
+			delete_qh(s,qh);
+		n++;
+	}
+}
+/*-------------------------------------------------------------------*/
+_static void uhci_switch_timer_int(uhci_t *s)
+{
+
+	if (!list_empty(&s->urb_unlinked))
+		set_td_ioc(s->td1ms);
+	else
+		clr_td_ioc(s->td1ms);
+
+	if (s->timeout_urbs)
+		set_td_ioc(s->td32ms);
+	else
+		clr_td_ioc(s->td32ms);
+	wmb();
+}
+/*-------------------------------------------------------------------*/
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
+_static void enable_desc_loop(uhci_t *s, struct urb *urb)
+{
+	unsigned long flags;
+
+	if (urb->transfer_flags & USB_NO_FSBR)
+		return;
+
+	spin_lock_irqsave (&s->qh_lock, flags);
+	s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM);
+	mb();
+	s->loop_usage++;
+	((urb_priv_t*)urb->hcpriv)->use_loop=1;
+	spin_unlock_irqrestore (&s->qh_lock, flags);
+}
+/*-------------------------------------------------------------------*/
+_static void disable_desc_loop(uhci_t *s, struct urb *urb)
+{
+	unsigned long flags;
+
+	if (urb->transfer_flags & USB_NO_FSBR)
+		return;
+
+	spin_lock_irqsave (&s->qh_lock, flags);
+	if (((urb_priv_t*)urb->hcpriv)->use_loop) {
+		s->loop_usage--;
+
+		if (!s->loop_usage) {
+			s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM);
+			mb();
+		}
+		((urb_priv_t*)urb->hcpriv)->use_loop=0;
+	}
+	spin_unlock_irqrestore (&s->qh_lock, flags);
+}
+#endif
+/*-------------------------------------------------------------------*/
+_static void queue_urb_unlocked (uhci_t *s, struct urb *urb)
+{
+	struct list_head *p=&urb->urb_list;
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
+	{
+		int type;
+		type=usb_pipetype (urb->pipe);
+
+		if ((type == PIPE_BULK) || (type == PIPE_CONTROL))
+			enable_desc_loop(s, urb);
+	}
+#endif
+	urb->status = -EINPROGRESS;
+	((urb_priv_t*)urb->hcpriv)->started=jiffies;
+	list_add (p, &s->urb_list);
+	if (urb->timeout)
+		s->timeout_urbs++;
+	uhci_switch_timer_int(s);
+}
+/*-------------------------------------------------------------------*/
+_static void queue_urb (uhci_t *s, struct urb *urb)
+{
+	unsigned long flags=0;
+
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+	queue_urb_unlocked(s,urb);
+	spin_unlock_irqrestore (&s->urb_list_lock, flags);
+}
+/*-------------------------------------------------------------------*/
+_static void dequeue_urb (uhci_t *s, struct urb *urb)
+{
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
+	int type;
+
+	type=usb_pipetype (urb->pipe);
+
+	if ((type == PIPE_BULK) || (type == PIPE_CONTROL))
+		disable_desc_loop(s, urb);
+#endif
+
+	list_del (&urb->urb_list);
+	if (urb->timeout && s->timeout_urbs)
+		s->timeout_urbs--;
+
+}
+/*-------------------------------------------------------------------*/
+_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags)
+{
+	dma_addr_t dma_handle;
+
+	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
+	if (!*new)
+		return -ENOMEM;
+	memset (*new, 0, sizeof (uhci_desc_t));
+	(*new)->dma_addr = dma_handle;
+	set_td_link((*new), UHCI_PTR_TERM | (flags & UHCI_PTR_BITS));	// last by default
+	(*new)->type = TD_TYPE;
+	mb();
+	INIT_LIST_HEAD (&(*new)->vertical);
+	INIT_LIST_HEAD (&(*new)->horizontal);
+	
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+// append a qh to td.link physically, the SW linkage is not affected
+_static void append_qh(uhci_t *s, uhci_desc_t *td, uhci_desc_t* qh, int  flags)
+{
+	unsigned long xxx;
+	
+	spin_lock_irqsave (&s->td_lock, xxx);
+
+	set_td_link(td, qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH);
+       
+	mb();
+	spin_unlock_irqrestore (&s->td_lock, xxx);
+}
+/*-------------------------------------------------------------------*/
+/* insert td at last position in td-list of qh (vertical) */
+_static int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags)
+{
+	uhci_desc_t *prev;
+	unsigned long xxx;
+	
+	spin_lock_irqsave (&s->td_lock, xxx);
+
+	list_add_tail (&new->vertical, &qh->vertical);
+
+	prev = list_entry (new->vertical.prev, uhci_desc_t, vertical);
+
+	if (qh == prev ) {
+		// virgin qh without any tds
+		set_qh_element(qh, new->dma_addr | UHCI_PTR_TERM);
+	}
+	else {
+		// already tds inserted, implicitely remove TERM bit of prev
+		set_td_link(prev, new->dma_addr | (flags & UHCI_PTR_DEPTH));
+	}
+	mb();
+	spin_unlock_irqrestore (&s->td_lock, xxx);
+	
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+/* insert new_td after td (horizontal) */
+_static int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new)
+{
+	uhci_desc_t *next;
+	unsigned long flags;
+	
+	spin_lock_irqsave (&s->td_lock, flags);
+
+	next = list_entry (td->horizontal.next, uhci_desc_t, horizontal);
+	list_add (&new->horizontal, &td->horizontal);
+	new->hw.td.link = td->hw.td.link;
+	set_td_link(td, new->dma_addr);
+	mb();
+	spin_unlock_irqrestore (&s->td_lock, flags);	
+	
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+_static int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink)
+{
+	uhci_desc_t *next, *prev;
+	int dir = 0;
+	unsigned long flags;
+	
+	spin_lock_irqsave (&s->td_lock, flags);
+	
+	next = list_entry (element->vertical.next, uhci_desc_t, vertical);
+	
+	if (next == element) {
+		dir = 1;
+		prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
+	}
+	else 
+		prev = list_entry (element->vertical.prev, uhci_desc_t, vertical);
+	
+	if (phys_unlink) {
+		// really remove HW linking
+		if (prev->type == TD_TYPE)
+			prev->hw.td.link = element->hw.td.link;
+		else
+			prev->hw.qh.element = element->hw.td.link;
+	}
+
+	mb ();
+
+	if (dir == 0)
+		list_del (&element->vertical);
+	else
+		list_del (&element->horizontal);
+	
+	spin_unlock_irqrestore (&s->td_lock, flags);	
+	
+	return 0;
+}
+
+/*-------------------------------------------------------------------*/
+_static int delete_desc (uhci_t *s, uhci_desc_t *element)
+{
+	pci_pool_free(s->desc_pool, element, element->dma_addr);
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+// Allocates qh element
+_static int alloc_qh (uhci_t *s, uhci_desc_t ** new)
+{
+	dma_addr_t dma_handle;
+
+	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
+	if (!*new)
+		return -ENOMEM;
+	memset (*new, 0, sizeof (uhci_desc_t));
+	(*new)->dma_addr = dma_handle;
+	set_qh_head(*new, UHCI_PTR_TERM);
+	set_qh_element(*new, UHCI_PTR_TERM);
+	(*new)->type = QH_TYPE;
+	
+	mb();
+	INIT_LIST_HEAD (&(*new)->horizontal);
+	INIT_LIST_HEAD (&(*new)->vertical);
+	
+	dbg("Allocated qh @ %p", *new);
+	
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+// inserts new qh before/after the qh at pos
+// flags: 0: insert before pos, 1: insert after pos (for low speed transfers)
+_static int insert_qh (uhci_t *s, uhci_desc_t *pos, uhci_desc_t *new, int order)
+{
+	uhci_desc_t *old;
+	unsigned long flags;
+
+	spin_lock_irqsave (&s->qh_lock, flags);
+
+	if (!order) {
+		// (OLD) (POS) -> (OLD) (NEW) (POS)
+		old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal);
+		list_add_tail (&new->horizontal, &pos->horizontal);
+		set_qh_head(new, MAKE_QH_ADDR (pos)) ;
+		if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM)))
+			set_qh_head(old, MAKE_QH_ADDR (new)) ;
+	}
+	else {
+		// (POS) (OLD) -> (POS) (NEW) (OLD)
+		old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal);
+		list_add (&new->horizontal, &pos->horizontal);
+		set_qh_head(new, MAKE_QH_ADDR (old));
+		set_qh_head(pos, MAKE_QH_ADDR (new)) ;
+	}
+
+	mb ();
+	
+	spin_unlock_irqrestore (&s->qh_lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------*/
+_static int unlink_qh (uhci_t *s, uhci_desc_t *element)
+{
+	uhci_desc_t  *prev;
+	unsigned long flags;
+
+	spin_lock_irqsave (&s->qh_lock, flags);
+	
+	prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
+	prev->hw.qh.head = element->hw.qh.head;
+
+	dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, 
+	    list_entry (element->horizontal.next, uhci_desc_t, horizontal),le32_to_cpu(element->hw.qh.head) &~15);
+	
+	list_del(&element->horizontal);
+
+	mb ();
+	spin_unlock_irqrestore (&s->qh_lock, flags);
+	
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+_static int delete_qh (uhci_t *s, uhci_desc_t *qh)
+{
+	uhci_desc_t *td;
+	struct list_head *p;
+	
+	list_del (&qh->horizontal);
+
+	while ((p = qh->vertical.next) != &qh->vertical) {
+		td = list_entry (p, uhci_desc_t, vertical);
+		dbg("unlink td @ %p",td);
+		unlink_td (s, td, 0); // no physical unlink
+		delete_desc (s, td);
+	}
+
+	delete_desc (s, qh);
+	
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+_static void clean_td_chain (uhci_t *s, uhci_desc_t *td)
+{
+	struct list_head *p;
+	uhci_desc_t *td1;
+
+	if (!td)
+		return;
+	
+	while ((p = td->horizontal.next) != &td->horizontal) {
+		td1 = list_entry (p, uhci_desc_t, horizontal);
+		delete_desc (s, td1);
+	}
+	
+	delete_desc (s, td);
+}
+
+/*-------------------------------------------------------------------*/
+_static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer)
+{
+	td->hw.td.status = cpu_to_le32(status);
+	td->hw.td.info = cpu_to_le32(info);
+	td->hw.td.buffer = cpu_to_le32(buffer);
+}
+/*-------------------------------------------------------------------*/
+// Removes ALL qhs in chain (paranoia!)
+_static void cleanup_skel (uhci_t *s)
+{
+	unsigned int n;
+	uhci_desc_t *td;
+
+	dbg("cleanup_skel");
+
+	clean_descs(s,1);
+
+	
+	if (s->td32ms) {
+	
+		unlink_td(s,s->td32ms,1);
+		delete_desc(s, s->td32ms);
+	}
+
+	for (n = 0; n < 8; n++) {
+		td = s->int_chain[n];
+		clean_td_chain (s, td);
+	}
+
+	if (s->iso_td) {
+		for (n = 0; n < 1024; n++) {
+			td = s->iso_td[n];
+			clean_td_chain (s, td);
+		}
+		kfree (s->iso_td);
+	}
+
+	if (s->framelist)
+		pci_free_consistent(s->uhci_pci, PAGE_SIZE,
+				    s->framelist, s->framelist_dma);
+
+	if (s->control_chain) {
+		// completed init_skel?
+		struct list_head *p;
+		uhci_desc_t *qh, *qh1;
+
+		qh = s->control_chain;
+		while ((p = qh->horizontal.next) != &qh->horizontal) {
+			qh1 = list_entry (p, uhci_desc_t, horizontal);
+			delete_qh (s, qh1);
+		}
+
+		delete_qh (s, qh);
+	}
+	else {
+		if (s->ls_control_chain)
+			delete_desc (s, s->ls_control_chain);
+		if (s->control_chain)
+			delete_desc (s, s->control_chain);
+		if (s->bulk_chain)
+			delete_desc (s, s->bulk_chain);
+		if (s->chain_end)
+			delete_desc (s, s->chain_end);
+	}
+
+	if (s->desc_pool) {
+		pci_pool_destroy(s->desc_pool);
+		s->desc_pool = NULL;
+	}
+
+	dbg("cleanup_skel finished");	
+}
+/*-------------------------------------------------------------------*/
+// allocates framelist and qh-skeletons
+// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT)
+_static int init_skel (uhci_t *s)
+{
+	int n, ret;
+	uhci_desc_t *qh, *td;
+	
+	dbg("init_skel");
+	
+	s->framelist = pci_alloc_consistent(s->uhci_pci, PAGE_SIZE,
+					    &s->framelist_dma);
+
+	if (!s->framelist)
+		return -ENOMEM;
+
+	memset (s->framelist, 0, 4096);
+
+	dbg("creating descriptor pci_pool");
+
+	s->desc_pool = pci_pool_create("uhci_desc", s->uhci_pci,
+				       sizeof(uhci_desc_t), 16, 0,
+				       GFP_DMA | GFP_ATOMIC);	
+	if (!s->desc_pool)
+		goto init_skel_cleanup;
+
+	dbg("allocating iso desc pointer list");
+	s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL);
+	
+	if (!s->iso_td)
+		goto init_skel_cleanup;
+
+	s->ls_control_chain = NULL;
+	s->control_chain = NULL;
+	s->bulk_chain = NULL;
+	s->chain_end = NULL;
+
+	dbg("allocating iso descs");
+	for (n = 0; n < 1024; n++) {
+	 	// allocate skeleton iso/irq-tds
+		if (alloc_td (s, &td, 0))
+			goto init_skel_cleanup;
+
+		s->iso_td[n] = td;
+		s->framelist[n] = cpu_to_le32((__u32) td->dma_addr);
+	}
+
+	dbg("allocating qh: chain_end");
+	if (alloc_qh (s, &qh))	
+		goto init_skel_cleanup;
+				
+	s->chain_end = qh;
+
+	if (alloc_td (s, &td, 0))
+		goto init_skel_cleanup;
+	
+	fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
+	insert_td (s, qh, td, 0);
+	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // remove TERM bit
+	s->td1ms=td;
+
+	dbg("allocating qh: bulk_chain");
+	if (alloc_qh (s, &qh))
+		goto init_skel_cleanup;
+	
+	insert_qh (s, s->chain_end, qh, 0);
+	s->bulk_chain = qh;
+
+	dbg("allocating qh: control_chain");
+	ret = alloc_qh (s, &qh);
+	if (ret)
+		goto init_skel_cleanup;
+	
+	insert_qh (s, s->bulk_chain, qh, 0);
+	s->control_chain = qh;
+
+#ifdef	CONFIG_USB_UHCI_HIGH_BANDWIDTH
+	// disabled reclamation loop
+	set_qh_head(s->chain_end, s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM);
+#endif
+
+	dbg("allocating qh: ls_control_chain");
+	if (alloc_qh (s, &qh))
+		goto init_skel_cleanup;
+	
+	insert_qh (s, s->control_chain, qh, 0);
+	s->ls_control_chain = qh;
+
+	for (n = 0; n < 8; n++)
+		s->int_chain[n] = 0;
+
+	dbg("allocating skeleton INT-TDs");
+	
+	for (n = 0; n < 8; n++) {
+		uhci_desc_t *td;
+
+		if (alloc_td (s, &td, 0))
+			goto init_skel_cleanup;
+
+		s->int_chain[n] = td;
+		if (n == 0) {
+			set_td_link(s->int_chain[0], s->ls_control_chain->dma_addr | UHCI_PTR_QH);
+		}
+		else {
+			set_td_link(s->int_chain[n], s->int_chain[0]->dma_addr);
+		}
+	}
+
+	dbg("Linking skeleton INT-TDs");
+	
+	for (n = 0; n < 1024; n++) {
+		// link all iso-tds to the interrupt chains
+		int m, o;
+		dbg("framelist[%i]=%x",n,le32_to_cpu(s->framelist[n]));
+		if ((n&127)==127) 
+			((uhci_desc_t*) s->iso_td[n])->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr);
+		else 
+			for (o = 1, m = 2; m <= 128; o++, m += m)
+				if ((n & (m - 1)) == ((m - 1) / 2))
+					set_td_link(((uhci_desc_t*) s->iso_td[n]), s->int_chain[o]->dma_addr);
+	}
+
+	if (alloc_td (s, &td, 0))
+		goto init_skel_cleanup;
+	
+	fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt (activated later)
+	s->td32ms=td;
+
+	insert_td_horizontal (s, s->int_chain[5], td);
+
+	mb();
+	dbg("init_skel exit");
+	return 0;
+
+      init_skel_cleanup:
+	cleanup_skel (s);
+	return -ENOMEM;
+}
+
+/*-------------------------------------------------------------------*/
+//                         LOW LEVEL STUFF
+//          assembles QHs und TDs for control, bulk and iso
+/*-------------------------------------------------------------------*/
+_static int uhci_submit_control_urb (struct urb *urb)
+{
+	uhci_desc_t *qh, *td;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	unsigned long destination, status;
+	int maxsze = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
+	unsigned long len;
+	char *data;
+	int depth_first=USE_CTRL_DEPTH_FIRST;  // UHCI descriptor chasing method
+
+	dbg("uhci_submit_control start");
+	if (alloc_qh (s, &qh))		// alloc qh for this request
+		return -ENOMEM;
+
+	if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first))		// get td for setup stage
+	{
+		delete_qh (s, qh);
+		return -ENOMEM;
+	}
+
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+
+	/* 3 errors */
+	status = TD_CTRL_ACTIVE
+		| (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD)
+		| (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+
+	/*  Build the TD for the control request, try forever, 8 bytes of data */
+	fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma);
+
+	insert_td (s, qh, td, 0);	// queue 'setup stage'-td in qh
+#if 0
+	{
+		char *sp=urb->setup_packet;
+		dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", urb->pipe,
+		    sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]);
+	}
+	//uhci_show_td(td);
+#endif
+
+	len = urb->transfer_buffer_length;
+	data = urb->transfer_buffer;
+
+	/* If direction is "send", change the frame from SETUP (0x2D)
+	   to OUT (0xE1). Else change it from SETUP to IN (0x69). */
+
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | (usb_pipeout (urb->pipe)?USB_PID_OUT:USB_PID_IN);
+
+	while (len > 0) {
+		int pktsze = len;
+
+		if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first))
+			goto fail_unmap_enomem;
+
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+
+		destination ^= 1 << TD_TOKEN_TOGGLE;	// toggle DATA0/1
+
+		// Status, pktsze bytes of data
+		fill_td (td, status, destination | ((pktsze - 1) << 21),
+			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
+
+		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue 'data stage'-td in qh
+
+		data += pktsze;
+		len -= pktsze;
+	}
+
+	/* Build the final TD for control status */
+	/* It's only IN if the pipe is out AND we aren't expecting data */
+
+	destination &= ~UHCI_PID;
+
+	if (usb_pipeout (urb->pipe) || (urb->transfer_buffer_length == 0))
+		destination |= USB_PID_IN;
+	else
+		destination |= USB_PID_OUT;
+
+	destination |= 1 << TD_TOKEN_TOGGLE;	/* End in Data1 */
+
+	if (alloc_td (s, &td, UHCI_PTR_DEPTH))
+		goto fail_unmap_enomem;
+
+	status &=~TD_CTRL_SPD;
+
+	/* no limit on errors on final packet , 0 bytes of data */
+	fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),
+		 0);
+
+	insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue status td
+
+	list_add (&qh->desc_list, &urb_priv->desc_list);
+
+	queue_urb (s, urb);	// queue before inserting in desc chain
+
+	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);
+
+	/* Start it up... put low speed first */
+	if (urb->dev->speed == USB_SPEED_LOW)
+		insert_qh (s, s->control_chain, qh, 0);
+	else
+		insert_qh (s, s->bulk_chain, qh, 0);
+
+	dbg("uhci_submit_control end");
+	return 0;
+
+fail_unmap_enomem:
+	delete_qh(s, qh);
+	return -ENOMEM;
+}
+/*-------------------------------------------------------------------*/
+// For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh)
+// Due to the linking with other bulk urbs, it has to be locked with urb_list_lock!
+
+_static int uhci_submit_bulk_urb (struct urb *urb, struct urb *bulk_urb)
+{
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL;
+	uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL;
+	unsigned long destination, status;
+	char *data;
+	unsigned int pipe = urb->pipe;
+	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
+	int info, len, last;
+	int depth_first=USE_BULK_DEPTH_FIRST;  // UHCI descriptor chasing method
+
+	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)))
+		return -EPIPE;
+
+	queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i",
+		  urb,bulk_urb,urb->pipe,urb->transfer_buffer_length);
+
+	upriv = (urb_priv_t*)urb->hcpriv;
+
+	if (!bulk_urb) {
+		if (alloc_qh (s, &qh))		// get qh for this request
+			return -ENOMEM;
+
+		if (urb->transfer_flags & USB_QUEUE_BULK) {
+			if (alloc_qh(s, &nqh)) // placeholder for clean unlink
+			{
+				delete_desc (s, qh);
+				return -ENOMEM;
+			}
+			upriv->next_qh = nqh;
+			queue_dbg("new next qh %p",nqh);
+		}
+	}
+	else { 
+		bpriv = (urb_priv_t*)bulk_urb->hcpriv;
+		qh = bpriv->bottom_qh;  // re-use bottom qh and next qh
+		nqh = bpriv->next_qh;
+		upriv->next_qh=nqh;	
+		upriv->prev_queued_urb=bulk_urb;
+	}
+
+	if (urb->transfer_flags & USB_QUEUE_BULK) {
+		if (alloc_qh (s, &bqh))  // "bottom" QH
+		{
+			if (!bulk_urb) { 
+				delete_desc(s, qh);
+				delete_desc(s, nqh);
+			}
+			return -ENOMEM;
+		}
+		set_qh_element(bqh, UHCI_PTR_TERM);
+		set_qh_head(bqh, nqh->dma_addr | UHCI_PTR_QH); // element
+		upriv->bottom_qh = bqh;
+	}
+	queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh);
+
+	/* The "pipe" thing contains the destination in bits 8--18. */
+	destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
+
+	/* 3 errors */
+	status = TD_CTRL_ACTIVE
+		| ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD)
+		| (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+
+	/* Build the TDs for the bulk request */
+	len = urb->transfer_buffer_length;
+	data = urb->transfer_buffer;
+	
+	do {					// TBD: Really allow zero-length packets?
+		int pktsze = len;
+
+		if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first))
+		{
+			delete_qh (s, qh);
+			return -ENOMEM;
+		}
+
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+
+		// pktsze bytes of data 
+		info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
+			(usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
+
+		fill_td (td, status, info,
+			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
+
+		data += pktsze;
+		len -= pktsze;
+		// Use USB_ZERO_PACKET to finish bulk OUTs always with a zero length packet
+		last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET)));
+
+		if (last)
+			set_td_ioc(td);	// last one generates INT
+
+		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);
+		if (!first_td)
+			first_td=td;
+		usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+
+	} while (!last);
+
+	if (bulk_urb && bpriv)   // everything went OK, link with old bulk URB
+		bpriv->next_queued_urb=urb;
+
+	list_add (&qh->desc_list, &urb_priv->desc_list);
+
+	if (urb->transfer_flags & USB_QUEUE_BULK)
+		append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first);
+
+	queue_urb_unlocked (s, urb);
+	
+	if (urb->transfer_flags & USB_QUEUE_BULK)
+		set_qh_element(qh, first_td->dma_addr);
+	else
+		qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);    // arm QH
+
+	if (!bulk_urb) { 					// new bulk queue	
+		if (urb->transfer_flags & USB_QUEUE_BULK) {
+			spin_lock (&s->td_lock);		// both QHs in one go
+			insert_qh (s, s->chain_end, qh, 0);	// Main QH
+			insert_qh (s, s->chain_end, nqh, 0);	// Helper QH
+			spin_unlock (&s->td_lock);
+		}
+		else
+			insert_qh (s, s->chain_end, qh, 0);
+	}
+	
+	//dbg("uhci_submit_bulk_urb: exit\n");
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+_static void uhci_clean_iso_step1(uhci_t *s, urb_priv_t *urb_priv)
+{
+	struct list_head *p;
+	uhci_desc_t *td;
+
+	for (p = urb_priv->desc_list.next; p != &urb_priv->desc_list; p = p->next) {
+				td = list_entry (p, uhci_desc_t, desc_list);
+				unlink_td (s, td, 1);
+	}
+}
+/*-------------------------------------------------------------------*/
+_static void uhci_clean_iso_step2(uhci_t *s, urb_priv_t *urb_priv)
+{
+	struct list_head *p;
+	uhci_desc_t *td;
+
+	while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
+				td = list_entry (p, uhci_desc_t, desc_list);
+				list_del (p);
+				delete_desc (s, td);
+	}
+}
+/*-------------------------------------------------------------------*/
+/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink)
+         CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark)
+         CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink)
+ looks a bit complicated because of all the bulk queueing goodies
+*/
+
+_static void uhci_clean_transfer (uhci_t *s, struct urb *urb, uhci_desc_t *qh, int mode)
+{
+	uhci_desc_t *bqh, *nqh, *prevqh, *prevtd;
+	int now;
+	urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
+
+	now=UHCI_GET_CURRENT_FRAME(s);
+
+	bqh=priv->bottom_qh;	
+	
+	if (!priv->next_queued_urb)  { // no more appended bulk queues
+
+		queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p", urb, qh, bqh, priv->next_qh);	
+	
+		if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) {  // qh not top of the queue
+				unsigned long flags; 
+				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
+
+				spin_lock_irqsave (&s->qh_lock, flags);
+				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
+				prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical);
+				set_td_link(prevtd, priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh
+				mb();
+				queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd);
+				spin_unlock_irqrestore (&s->qh_lock, flags);
+
+				ppriv->bottom_qh = priv->bottom_qh;
+				ppriv->next_queued_urb = NULL;
+			}
+		else {   // queue is dead, qh is top of the queue
+			
+			if (mode != CLEAN_TRANSFER_DELETION_MARK) 				
+				unlink_qh(s, qh); // remove qh from horizontal chain
+
+			if (bqh) {  // remove remainings of bulk queue
+				nqh=priv->next_qh;
+
+				if (mode != CLEAN_TRANSFER_DELETION_MARK) 
+					unlink_qh(s, nqh);  // remove nqh from horizontal chain
+				
+				if (mode != CLEAN_TRANSFER_NO_DELETION) {  // add helper QHs to free desc list
+					nqh->last_used = bqh->last_used = now;
+					list_add_tail (&nqh->horizontal, &s->free_desc);
+					list_add_tail (&bqh->horizontal, &s->free_desc);
+				}			
+			}
+		}
+	}
+	else { // there are queued urbs following
+	
+	  queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p",
+		       urb, priv->prev_queued_urb,  priv->next_queued_urb, qh, bqh, priv->next_qh);	
+       	
+		if (mode != CLEAN_TRANSFER_DELETION_MARK) {	// no work for cleanup at unlink-completion
+			struct urb *nurb;
+			unsigned long flags;
+
+			nurb = priv->next_queued_urb;
+			spin_lock_irqsave (&s->qh_lock, flags);		
+
+			if (!priv->prev_queued_urb) { // top QH
+				
+				prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal);
+				set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH);
+				list_del (&qh->horizontal);  // remove this qh form horizontal chain
+				list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain
+			}
+			else {		// intermediate QH
+				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
+				urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv;
+				uhci_desc_t * bnqh;
+				
+				bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list);
+				ppriv->bottom_qh = bnqh;
+				ppriv->next_queued_urb = nurb;				
+				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
+				set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH);
+			}
+
+			mb();
+			((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb;
+			spin_unlock_irqrestore (&s->qh_lock, flags);
+		}		
+	}
+
+	if (mode != CLEAN_TRANSFER_NO_DELETION) {
+		qh->last_used = now;	
+		list_add_tail (&qh->horizontal, &s->free_desc); // mark qh for later deletion/kfree
+	}
+}
+/*-------------------------------------------------------------------*/
+// Release bandwidth for Interrupt or Isoc. transfers 
+_static void uhci_release_bandwidth(struct urb *urb)
+{       
+	if (urb->bandwidth) {
+		switch (usb_pipetype(urb->pipe)) {
+		case PIPE_INTERRUPT:
+			usb_release_bandwidth (urb->dev, urb, 0);
+			break;
+		case PIPE_ISOCHRONOUS:
+			usb_release_bandwidth (urb->dev, urb, 1);
+			break;
+		default:
+			break;
+		}
+	}	
+}
+
+_static void uhci_urb_dma_sync(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv)
+{
+	if (urb_priv->setup_packet_dma)
+		pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma,
+				    sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
+
+	if (urb_priv->transfer_buffer_dma)
+		pci_dma_sync_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
+				    urb->transfer_buffer_length,
+				    usb_pipein(urb->pipe) ?
+				    PCI_DMA_FROMDEVICE :
+				    PCI_DMA_TODEVICE);
+}
+
+_static void uhci_urb_dma_unmap(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv)
+{
+	if (urb_priv->setup_packet_dma) {
+		pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma,
+				 sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
+		urb_priv->setup_packet_dma = 0;
+	}
+	if (urb_priv->transfer_buffer_dma) {
+		pci_unmap_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
+				 urb->transfer_buffer_length,
+				 usb_pipein(urb->pipe) ?
+				 PCI_DMA_FROMDEVICE :
+				 PCI_DMA_TODEVICE);
+		urb_priv->transfer_buffer_dma = 0;
+	}
+}
+/*-------------------------------------------------------------------*/
+/* needs urb_list_lock!
+   mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list
+         UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list
+*/
+_static int uhci_unlink_urb_async (uhci_t *s, struct urb *urb, int mode)
+{
+	uhci_desc_t *qh;
+	urb_priv_t *urb_priv;
+	
+	async_dbg("unlink_urb_async called %p",urb);
+
+	if ((urb->status == -EINPROGRESS) ||
+	    ((usb_pipetype (urb->pipe) ==  PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags))
+	{
+		((urb_priv_t*)urb->hcpriv)->started = ~0;  // mark
+		dequeue_urb (s, urb);
+
+		if (mode==UNLINK_ASYNC_STORE_URB)
+			list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb
+
+		uhci_switch_timer_int(s);
+       		s->unlink_urb_done = 1;
+		uhci_release_bandwidth(urb);
+
+		urb->status = -ECONNABORTED;	// mark urb as "waiting to be killed"	
+		urb_priv = (urb_priv_t*)urb->hcpriv;
+
+		switch (usb_pipetype (urb->pipe)) {
+		case PIPE_INTERRUPT:
+			usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+
+		case PIPE_ISOCHRONOUS:
+			uhci_clean_iso_step1 (s, urb_priv);
+			break;
+
+		case PIPE_BULK:
+		case PIPE_CONTROL:
+			qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
+			uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION);
+			break;
+		}
+		((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s);
+		return -EINPROGRESS;  // completion will follow
+	}		
+
+	return 0;    // URB already dead
+}
+/*-------------------------------------------------------------------*/
+// kills an urb by unlinking descriptors and waiting for at least one frame
+_static int uhci_unlink_urb_sync (uhci_t *s, struct urb *urb)
+{
+	uhci_desc_t *qh;
+	urb_priv_t *urb_priv;
+	unsigned long flags=0;
+	struct usb_device *usb_dev;
+
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+
+	if (urb->status == -EINPROGRESS) {
+
+		// move descriptors out the the running chains, dequeue urb
+		uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE);
+
+		urb_priv = urb->hcpriv;
+		urb->status = -ENOENT;	// prevent from double deletion after unlock		
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+		
+		// cleanup the rest
+		switch (usb_pipetype (urb->pipe)) {
+
+		case PIPE_INTERRUPT:
+		case PIPE_ISOCHRONOUS:
+			uhci_wait_ms(1);
+			uhci_clean_iso_step2(s, urb_priv);
+			break;
+
+		case PIPE_BULK:
+		case PIPE_CONTROL:
+			qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
+			uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK);
+			uhci_wait_ms(1);
+		}
+		urb->status = -ENOENT;	// mark urb as killed		
+					
+		uhci_urb_dma_unmap(s, urb, urb->hcpriv);
+
+#ifdef DEBUG_SLAB
+		kmem_cache_free (urb_priv_kmem, urb->hcpriv);
+#else
+		kfree (urb->hcpriv);
+#endif
+		usb_dev = urb->dev;
+		if (urb->complete) {
+			dbg("unlink_urb: calling completion");
+			urb->dev = NULL;
+			urb->complete ((struct urb *) urb);
+		}
+		usb_dec_dev_use (usb_dev);
+		usb_put_urb (urb);
+	}
+	else
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+// async unlink_urb completion/cleanup work
+// has to be protected by urb_list_lock!
+// features: if set in transfer_flags, the resulting status of the killed
+// transaction is not overwritten
+
+_static void uhci_cleanup_unlink(uhci_t *s, int force)
+{
+	struct list_head *q;
+	struct urb *urb;
+	struct usb_device *dev;
+	int now, type;
+	urb_priv_t *urb_priv;
+
+	q=s->urb_unlinked.next;
+	now=UHCI_GET_CURRENT_FRAME(s);
+
+	while (q != &s->urb_unlinked) {
+
+		urb = list_entry (q, struct urb, urb_list);
+
+		urb_priv = (urb_priv_t*)urb->hcpriv;
+		q = urb->urb_list.next;
+		
+		if (!urb_priv) // avoid crash when URB is corrupted
+			break;
+			
+		if (force || ((urb_priv->started != ~0) && (urb_priv->started != now))) {
+			async_dbg("async cleanup %p",urb);
+			type=usb_pipetype (urb->pipe);
+
+			switch (type) { // process descriptors
+			case PIPE_CONTROL:
+				process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK);  // don't unlink (already done)
+				break;
+			case PIPE_BULK:
+				if (!s->avoid_bulk.counter)
+					process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done)
+				else
+					continue;
+				break;
+			case PIPE_ISOCHRONOUS:
+				process_iso (s, urb, PROCESS_ISO_FORCE); // force, don't unlink
+				break;
+			case PIPE_INTERRUPT:
+				process_interrupt (s, urb);
+				break;
+			}
+
+			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
+		  		urb->status = -ECONNRESET; // mark as asynchronously killed
+
+			dev = urb->dev;	// completion may destroy all...
+			urb_priv = urb->hcpriv;
+			list_del (&urb->urb_list);
+			
+			uhci_urb_dma_sync(s, urb, urb_priv);
+			if (urb->complete) {
+				spin_unlock(&s->urb_list_lock);
+				urb->dev = NULL;
+				urb->complete ((struct urb *) urb);
+				spin_lock(&s->urb_list_lock);
+			}
+
+			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
+				urb->status = -ENOENT;  // now the urb is really dead
+
+			switch (type) {
+			case PIPE_ISOCHRONOUS:
+			case PIPE_INTERRUPT:
+				uhci_clean_iso_step2(s, urb_priv);
+				break;
+			}
+	
+			uhci_urb_dma_unmap(s, urb, urb_priv);
+
+			usb_dec_dev_use (dev);
+#ifdef DEBUG_SLAB
+			kmem_cache_free (urb_priv_kmem, urb_priv);
+#else
+			kfree (urb_priv);
+#endif
+			usb_put_urb (urb);
+		}
+	}
+}
+ 
+/*-------------------------------------------------------------------*/
+_static int uhci_unlink_urb (struct urb *urb)
+{
+	uhci_t *s;
+	unsigned long flags=0;
+	dbg("uhci_unlink_urb called for %p",urb);
+	if (!urb || !urb->dev)		// you never know...
+		return -EINVAL;
+	
+	s = (uhci_t*) urb->dev->bus->hcpriv;
+
+	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
+		return rh_unlink_urb (urb);
+
+	if (!urb->hcpriv)
+		return -EINVAL;
+
+	if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+		int ret;
+       		spin_lock_irqsave (&s->urb_list_lock, flags);
+       		
+		uhci_release_bandwidth(urb);
+		ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);	
+		return ret;
+	}
+	else
+		return uhci_unlink_urb_sync(s, urb);
+}
+/*-------------------------------------------------------------------*/
+// In case of ASAP iso transfer, search the URB-list for already queued URBs
+// for this EP and calculate the earliest start frame for the new
+// URB (easy seamless URB continuation!)
+_static int find_iso_limits (struct urb *urb, unsigned int *start, unsigned int *end)
+{
+	struct urb *u, *last_urb = NULL;
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	struct list_head *p;
+	int ret=-1;
+	unsigned long flags;
+	
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+	p=s->urb_list.prev;
+
+	for (; p != &s->urb_list; p = p->prev) {
+		u = list_entry (p, struct urb, urb_list);
+		// look for pending URBs with identical pipe handle
+		// works only because iso doesn't toggle the data bit!
+		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS)) {
+			if (!last_urb)
+				*start = u->start_frame;
+			last_urb = u;
+		}
+	}
+	
+	if (last_urb) {
+		*end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
+		ret=0;
+	}
+	
+	spin_unlock_irqrestore(&s->urb_list_lock, flags);
+	
+	return ret;
+}
+/*-------------------------------------------------------------------*/
+// adjust start_frame according to scheduling constraints (ASAP etc)
+
+_static int iso_find_start (struct urb *urb)
+{
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	unsigned int now;
+	unsigned int start_limit = 0, stop_limit = 0, queued_size;
+	int limits;
+
+	now = UHCI_GET_CURRENT_FRAME (s) & 1023;
+
+	if ((unsigned) urb->number_of_packets > 900)
+		return -EFBIG;
+	
+	limits = find_iso_limits (urb, &start_limit, &stop_limit);
+	queued_size = (stop_limit - start_limit) & 1023;
+
+	if (urb->transfer_flags & USB_ISO_ASAP) {
+		// first iso
+		if (limits) {
+			// 10ms setup should be enough //FIXME!
+			urb->start_frame = (now + 10) & 1023;
+		}
+		else {
+			urb->start_frame = stop_limit;		//seamless linkage
+
+			if (((now - urb->start_frame) & 1023) <= (unsigned) urb->number_of_packets) {
+				info("iso_find_start: gap in seamless isochronous scheduling");
+				dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x",
+					now, urb->start_frame, urb->number_of_packets, urb->pipe);
+				urb->start_frame = (now + 5) & 1023;	// 5ms setup should be enough //FIXME!
+			}
+		}
+	}
+	else {
+		urb->start_frame &= 1023;
+		if (((now - urb->start_frame) & 1023) < (unsigned) urb->number_of_packets) {
+			dbg("iso_find_start: now between start_frame and end");
+			return -EAGAIN;
+		}
+	}
+
+	/* check if either start_frame or start_frame+number_of_packets-1 lies between start_limit and stop_limit */
+	if (limits)
+		return 0;
+
+	if (((urb->start_frame - start_limit) & 1023) < queued_size ||
+	    ((urb->start_frame + urb->number_of_packets - 1 - start_limit) & 1023) < queued_size) {
+		dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u",
+			urb->start_frame, urb->number_of_packets, start_limit, stop_limit);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+// submits USB interrupt (ie. polling ;-) 
+// ASAP-flag set implicitely
+// if period==0, the transfer is only done once
+
+_static int uhci_submit_int_urb (struct urb *urb)
+{
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	int nint, n;
+	uhci_desc_t *td;
+	int status, destination;
+	int info;
+	unsigned int pipe = urb->pipe;
+
+	if (urb->interval < 0 || urb->interval >= 256)
+		return -EINVAL;
+
+	if (urb->interval == 0)
+		nint = 0;
+	else {
+		for (nint = 0, n = 1; nint <= 8; nint++, n += n)	// round interval down to 2^n
+		 {
+			if (urb->interval < n) {
+				urb->interval = n / 2;
+				break;
+			}
+		}
+		nint--;
+	}
+
+	dbg("Rounded interval to %i, chain  %i", urb->interval, nint);
+
+	urb->start_frame = UHCI_GET_CURRENT_FRAME (s) & 1023;	// remember start frame, just in case...
+
+	urb->number_of_packets = 1;
+
+	// INT allows only one packet
+	if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)))
+		return -EINVAL;
+
+	if (alloc_td (s, &td, UHCI_PTR_DEPTH))
+		return -ENOMEM;
+
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOC
+		| (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD)
+		| (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe) |
+		(((urb->transfer_buffer_length - 1) & 0x7ff) << 21);
+
+
+	info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
+
+	fill_td (td, status, info, urb_priv->transfer_buffer_dma);
+	list_add_tail (&td->desc_list, &urb_priv->desc_list);
+
+	queue_urb (s, urb);
+
+	insert_td_horizontal (s, s->int_chain[nint], td);	// store in INT-TDs
+
+	usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+_static int uhci_submit_iso_urb (struct urb *urb, int mem_flags)
+{
+	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
+	urb_priv_t *urb_priv = urb->hcpriv;
+#ifdef ISO_SANITY_CHECK
+	int pipe=urb->pipe;
+	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
+#endif
+	int n, ret, last=0;
+	uhci_desc_t *td, **tdm;
+	int status, destination;
+	unsigned long flags;
+
+	__save_flags(flags);
+	__cli();		      // Disable IRQs to schedule all ISO-TDs in time
+	ret = iso_find_start (urb);	// adjusts urb->start_frame for later use
+	
+	if (ret)
+		goto err;
+
+	tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), mem_flags);
+
+	if (!tdm) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	memset(tdm, 0, urb->number_of_packets * sizeof (uhci_desc_t*));
+
+	// First try to get all TDs. Cause: Removing already inserted TDs can only be done 
+	// racefree in three steps: unlink TDs, wait one frame, delete TDs. 
+	// So, this solutions seems simpler...
+
+	for (n = 0; n < urb->number_of_packets; n++) {
+		dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length);
+		if (!urb->iso_frame_desc[n].length)
+			continue;  // allows ISO striping by setting length to zero in iso_descriptor
+
+
+#ifdef ISO_SANITY_CHECK
+		if(urb->iso_frame_desc[n].length > maxsze) {
+
+			err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze);
+			ret=-EINVAL;		
+		}
+		else
+#endif
+		if (alloc_td (s, &td, UHCI_PTR_DEPTH)) {
+			int i;	// Cleanup allocated TDs
+
+			for (i = 0; i < n; n++)
+				if (tdm[i])
+					 delete_desc(s, tdm[i]);
+			kfree (tdm);
+			goto err;
+		}
+		last=n;
+		tdm[n] = td;
+	}
+
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe);
+
+	// Queue all allocated TDs
+	for (n = 0; n < urb->number_of_packets; n++) {
+		td = tdm[n];
+		if (!td)
+			continue;
+			
+		if (n  == last) {
+			status |= TD_CTRL_IOC;
+			queue_urb (s, urb);
+		}
+
+		fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21),
+			 urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset);
+		list_add_tail (&td->desc_list, &urb_priv->desc_list);
+	
+		insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td);	// store in iso-tds
+	}
+
+	kfree (tdm);
+	dbg("ISO-INT# %i, start %i, now %i", urb->number_of_packets, urb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
+	ret = 0;
+
+      err:
+	__restore_flags(flags);
+	return ret;
+}
+/*-------------------------------------------------------------------*/
+// returns: 0 (no transfer queued), urb* (this urb already queued)
+ 
+_static struct urb* search_dev_ep (uhci_t *s, struct urb *urb)
+{
+	struct list_head *p;
+	struct urb *tmp;
+	unsigned int mask = usb_pipecontrol(urb->pipe) ? (~USB_DIR_IN) : (~0);
+
+	dbg("search_dev_ep:");
+
+	p=s->urb_list.next;
+
+	for (; p != &s->urb_list; p = p->next) {
+		tmp = list_entry (p, struct urb, urb_list);
+		dbg("urb: %p", tmp);
+		// we can accept this urb if it is not queued at this time 
+		// or if non-iso transfer requests should be scheduled for the same device and pipe
+		if ((!usb_pipeisoc(urb->pipe) && (tmp->dev == urb->dev) && !((tmp->pipe ^ urb->pipe) & mask)) ||
+		    (urb == tmp)) {
+			return tmp;	// found another urb already queued for processing
+		}
+	}
+
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+_static int uhci_submit_urb (struct urb *urb, int mem_flags)
+{
+	uhci_t *s;
+	urb_priv_t *urb_priv;
+	int ret = 0, type;
+	unsigned long flags;
+	struct urb *queued_urb=NULL;
+	int bustime;
+		
+	if (!urb->dev || !urb->dev->bus)
+		return -ENODEV;
+
+	s = (uhci_t*) urb->dev->bus->hcpriv;
+	//dbg("submit_urb: %p type %d",urb,usb_pipetype(urb->pipe));
+	
+	if (!s->running)
+		return -ENODEV;
+	
+	type = usb_pipetype (urb->pipe);
+
+	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
+		return rh_submit_urb (urb);	/* virtual root hub */
+
+	// Sanity checks
+	if (usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)) <= 0) {		
+		err("uhci_submit_urb: pipesize for pipe %x is zero", urb->pipe);
+		return -EMSGSIZE;
+	}
+
+	if (urb->transfer_buffer_length < 0 && type != PIPE_ISOCHRONOUS) {
+		err("uhci_submit_urb: Negative transfer length for urb %p", urb);
+		return -EINVAL;
+	}
+
+	/* increment the reference count of the urb, as we now also control it */
+	urb = usb_get_urb (urb);
+
+	usb_inc_dev_use (urb->dev);
+
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+
+	queued_urb = search_dev_ep (s, urb); // returns already queued urb for that pipe
+
+	if (queued_urb) {
+
+		queue_dbg("found bulk urb %p\n", queued_urb);
+
+		if (( type != PIPE_BULK) ||
+		    ((type == PIPE_BULK) &&
+		     (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) {
+			spin_unlock_irqrestore (&s->urb_list_lock, flags);
+			usb_dec_dev_use (urb->dev);
+			usb_put_urb (urb);
+			err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb);
+			return -ENXIO;	// urb already queued
+		}
+	}
+
+#ifdef DEBUG_SLAB
+	urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG);
+#else
+	urb_priv = kmalloc (sizeof (urb_priv_t), mem_flags);
+#endif
+	if (!urb_priv) {
+		usb_dec_dev_use (urb->dev);
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+		usb_put_urb (urb);
+		return -ENOMEM;
+	}
+
+	memset(urb_priv, 0, sizeof(urb_priv_t));
+	urb->hcpriv = urb_priv;
+	INIT_LIST_HEAD (&urb_priv->desc_list);
+
+	dbg("submit_urb: scheduling %p", urb);
+	
+	if (type == PIPE_CONTROL)
+		urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet,
+							    sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
+
+	if (urb->transfer_buffer_length)
+		urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci,
+							       urb->transfer_buffer,
+							       urb->transfer_buffer_length,
+							       usb_pipein(urb->pipe) ?
+							       PCI_DMA_FROMDEVICE :
+							       PCI_DMA_TODEVICE);
+
+	if (type == PIPE_BULK) {
+	
+		if (queued_urb) {
+			while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb)  // find last queued bulk
+				queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb;
+			
+			((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb;
+		}
+		atomic_inc (&s->avoid_bulk);
+		ret = uhci_submit_bulk_urb (urb, queued_urb);
+		atomic_dec (&s->avoid_bulk);
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+	}
+	else {
+		spin_unlock_irqrestore (&s->urb_list_lock, flags);
+		switch (type) {
+		case PIPE_ISOCHRONOUS:			
+			if (urb->bandwidth == 0) {      /* not yet checked/allocated */
+				if (urb->number_of_packets <= 0) {
+					ret = -EINVAL;
+					break;
+				}
+
+				bustime = usb_check_bandwidth (urb->dev, urb);
+				if (bustime < 0) 
+					ret = bustime;
+				else {
+					ret = uhci_submit_iso_urb(urb, mem_flags);
+					if (ret == 0)
+						usb_claim_bandwidth (urb->dev, urb, bustime, 1);
+				}
+			} else {        /* bandwidth is already set */
+				ret = uhci_submit_iso_urb(urb, mem_flags);
+			}
+			break;
+		case PIPE_INTERRUPT:
+			if (urb->bandwidth == 0) {      /* not yet checked/allocated */
+				bustime = usb_check_bandwidth (urb->dev, urb);
+				if (bustime < 0)
+					ret = bustime;
+				else {
+					ret = uhci_submit_int_urb(urb);
+					if (ret == 0)
+						usb_claim_bandwidth (urb->dev, urb, bustime, 0);
+				}
+			} else {        /* bandwidth is already set */
+				ret = uhci_submit_int_urb(urb);
+			}
+			break;
+		case PIPE_CONTROL:
+			ret = uhci_submit_control_urb (urb);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	}
+
+	dbg("submit_urb: scheduled with ret: %d", ret);
+	
+	if (ret != 0) {
+		uhci_urb_dma_unmap(s, urb, urb_priv);
+		usb_dec_dev_use (urb->dev);
+#ifdef DEBUG_SLAB
+		kmem_cache_free(urb_priv_kmem, urb_priv);
+#else
+		kfree (urb_priv);
+#endif
+		usb_put_urb (urb);
+		return ret;
+	}
+
+	return 0;
+}
+
+// Checks for URB timeout and removes bandwidth reclamation if URB idles too long
+_static void uhci_check_timeouts(uhci_t *s)
+{
+	struct list_head *p,*p2;
+	struct urb *urb;
+	int type;	
+
+	p = s->urb_list.prev;	
+
+	while (p != &s->urb_list) {
+		urb_priv_t *hcpriv;
+
+		p2 = p;
+		p = p->prev;
+		urb = list_entry (p2, struct urb, urb_list);
+		type = usb_pipetype (urb->pipe);
+
+		hcpriv = (urb_priv_t*)urb->hcpriv;
+		
+		if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) {
+			urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
+			async_dbg("uhci_check_timeout: timeout for %p",urb);
+			uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+		}
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
+		else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) &&  
+			 (hcpriv->use_loop) && time_after(jiffies, hcpriv->started + IDLE_TIMEOUT))
+			disable_desc_loop(s, urb);
+#endif
+
+	}
+	s->timeout_check=jiffies;
+}
+
+/*-------------------------------------------------------------------
+ Virtual Root Hub
+ -------------------------------------------------------------------*/
+
+_static __u8 root_hub_dev_des[] =
+{
+	0x12,			/*  __u8  bLength; */
+	0x01,			/*  __u8  bDescriptorType; Device */
+	0x00,			/*  __u16 bcdUSB; v1.0 */
+	0x01,
+	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
+	0x00,			/*  __u8  bDeviceSubClass; */
+	0x00,			/*  __u8  bDeviceProtocol; */
+	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
+	0x00,			/*  __u16 idVendor; */
+	0x00,
+	0x00,			/*  __u16 idProduct; */
+	0x00,
+	0x00,			/*  __u16 bcdDevice; */
+	0x00,
+	0x00,			/*  __u8  iManufacturer; */
+	0x02,			/*  __u8  iProduct; */
+	0x01,			/*  __u8  iSerialNumber; */
+	0x01			/*  __u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+_static __u8 root_hub_config_des[] =
+{
+	0x09,			/*  __u8  bLength; */
+	0x02,			/*  __u8  bDescriptorType; Configuration */
+	0x19,			/*  __u16 wTotalLength; */
+	0x00,
+	0x01,			/*  __u8  bNumInterfaces; */
+	0x01,			/*  __u8  bConfigurationValue; */
+	0x00,			/*  __u8  iConfiguration; */
+	0x40,			/*  __u8  bmAttributes; 
+				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+	0x00,			/*  __u8  MaxPower; */
+
+     /* interface */
+	0x09,			/*  __u8  if_bLength; */
+	0x04,			/*  __u8  if_bDescriptorType; Interface */
+	0x00,			/*  __u8  if_bInterfaceNumber; */
+	0x00,			/*  __u8  if_bAlternateSetting; */
+	0x01,			/*  __u8  if_bNumEndpoints; */
+	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,			/*  __u8  if_bInterfaceSubClass; */
+	0x00,			/*  __u8  if_bInterfaceProtocol; */
+	0x00,			/*  __u8  if_iInterface; */
+
+     /* endpoint */
+	0x07,			/*  __u8  ep_bLength; */
+	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
+	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
+	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
+	0x00,
+	0xff			/*  __u8  ep_bInterval; 255 ms */
+};
+
+
+_static __u8 root_hub_hub_des[] =
+{
+	0x09,			/*  __u8  bLength; */
+	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
+	0x02,			/*  __u8  bNbrPorts; */
+	0x00,			/* __u16  wHubCharacteristics; */
+	0x00,
+	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
+	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
+	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
+	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+/*-------------------------------------------------------------------------*/
+/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
+_static int rh_send_irq (struct urb *urb)
+{
+	int len = 1;
+	int i;
+	uhci_t *uhci = urb->dev->bus->hcpriv;
+	unsigned int io_addr = uhci->io_addr;
+	__u16 data = 0;
+
+	for (i = 0; i < uhci->rh.numports; i++) {
+		data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
+		len = (i + 1) / 8 + 1;
+	}
+
+	*(__u16 *) urb->transfer_buffer = cpu_to_le16 (data);
+	urb->actual_length = len;
+	urb->status = 0;
+	
+	if ((data > 0) && (uhci->rh.send != 0)) {
+		dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",
+		     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);
+		urb->complete (urb);
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
+_static int rh_init_int_timer (struct urb *urb);
+
+_static void rh_int_timer_do (unsigned long ptr)
+{
+	int len;
+	struct urb *urb = (struct urb *) ptr;
+	uhci_t *uhci = urb->dev->bus->hcpriv;
+
+	if (uhci->rh.send) {
+		len = rh_send_irq (urb);
+		if (len > 0) {
+			urb->actual_length = len;
+			if (urb->complete)
+				urb->complete (urb);
+		}
+	}
+	rh_init_int_timer (urb);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Root Hub INTs are polled by this timer, polling interval 20ms */
+
+_static int rh_init_int_timer (struct urb *urb)
+{
+	uhci_t *uhci = urb->dev->bus->hcpriv;
+
+	uhci->rh.interval = urb->interval;
+	init_timer (&uhci->rh.rh_int_timer);
+	uhci->rh.rh_int_timer.function = rh_int_timer_do;
+	uhci->rh.rh_int_timer.data = (unsigned long) urb;
+	uhci->rh.rh_int_timer.expires = jiffies + (HZ * 20) / 1000;
+	add_timer (&uhci->rh.rh_int_timer);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+#define OK(x) 			len = (x); break
+
+#define CLR_RH_PORTSTAT(x) \
+		status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \
+		status = (status & 0xfff5) & ~(x); \
+		outw(status, io_addr+USBPORTSC1+2*(wIndex-1))
+
+#define SET_RH_PORTSTAT(x) \
+		status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \
+		status = (status & 0xfff5) | (x); \
+		outw(status, io_addr+USBPORTSC1+2*(wIndex-1))
+
+
+/*-------------------------------------------------------------------------*/
+/****
+ ** Root Hub Control Pipe
+ *************************/
+
+
+_static int rh_submit_urb (struct urb *urb)
+{
+	struct usb_device *usb_dev = urb->dev;
+	uhci_t *uhci = usb_dev->bus->hcpriv;
+	unsigned int pipe = urb->pipe;
+	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
+	void *data = urb->transfer_buffer;
+	int leni = urb->transfer_buffer_length;
+	int len = 0;
+	int status = 0;
+	int stat = 0;
+	int i;
+	unsigned int io_addr = uhci->io_addr;
+	__u16 cstatus;
+
+	__u16 bmRType_bReq;
+	__u16 wValue;
+	__u16 wIndex;
+	__u16 wLength;
+
+	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
+		dbg("Root-Hub submit IRQ: every %d ms", urb->interval);
+		uhci->rh.urb = urb;
+		uhci->rh.send = 1;
+		uhci->rh.interval = urb->interval;
+		rh_init_int_timer (urb);
+
+		return 0;
+	}
+
+
+	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
+	wValue = le16_to_cpu (cmd->wValue);
+	wIndex = le16_to_cpu (cmd->wIndex);
+	wLength = le16_to_cpu (cmd->wLength);
+
+	for (i = 0; i < 8; i++)
+		uhci->rh.c_p_r[i] = 0;
+
+	dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x",
+	     uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+	switch (bmRType_bReq) {
+		/* Request Destination:
+		   without flags: Device, 
+		   RH_INTERFACE: interface, 
+		   RH_ENDPOINT: endpoint,
+		   RH_CLASS means HUB here, 
+		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
+		 */
+
+	case RH_GET_STATUS:
+		*(__u16 *) data = cpu_to_le16 (1);
+		OK (2);
+	case RH_GET_STATUS | RH_INTERFACE:
+		*(__u16 *) data = cpu_to_le16 (0);
+		OK (2);
+	case RH_GET_STATUS | RH_ENDPOINT:
+		*(__u16 *) data = cpu_to_le16 (0);
+		OK (2);
+	case RH_GET_STATUS | RH_CLASS:
+		*(__u32 *) data = cpu_to_le32 (0);
+		OK (4);		/* hub power ** */
+	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+		status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1));
+		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
+			((status & USBPORTSC_PEC) >> (3 - 1)) |
+			(uhci->rh.c_p_r[wIndex - 1] << (0 + 4));
+		status = (status & USBPORTSC_CCS) |
+			((status & USBPORTSC_PE) >> (2 - 1)) |
+			((status & USBPORTSC_SUSP) >> (12 - 2)) |
+			((status & USBPORTSC_PR) >> (9 - 4)) |
+			(1 << 8) |	/* power on ** */
+			((status & USBPORTSC_LSDA) << (-8 + 9));
+
+		*(__u16 *) data = cpu_to_le16 (status);
+		*(__u16 *) (data + 2) = cpu_to_le16 (cstatus);
+		OK (4);
+
+	case RH_CLEAR_FEATURE | RH_ENDPOINT:
+		switch (wValue) {
+		case (RH_ENDPOINT_STALL):
+			OK (0);
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_CLASS:
+		switch (wValue) {
+		case (RH_C_HUB_OVER_CURRENT):
+			OK (0);	/* hub power over current ** */
+		}
+		break;
+
+	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case (RH_PORT_ENABLE):
+			CLR_RH_PORTSTAT (USBPORTSC_PE);
+			OK (0);
+		case (RH_PORT_SUSPEND):
+			CLR_RH_PORTSTAT (USBPORTSC_SUSP);
+			OK (0);
+		case (RH_PORT_POWER):
+			OK (0);	/* port power ** */
+		case (RH_C_PORT_CONNECTION):
+			SET_RH_PORTSTAT (USBPORTSC_CSC);
+			OK (0);
+		case (RH_C_PORT_ENABLE):
+			SET_RH_PORTSTAT (USBPORTSC_PEC);
+			OK (0);
+		case (RH_C_PORT_SUSPEND):
+/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+			OK (0);
+		case (RH_C_PORT_OVER_CURRENT):
+			OK (0);	/* port power over current ** */
+		case (RH_C_PORT_RESET):
+			uhci->rh.c_p_r[wIndex - 1] = 0;
+			OK (0);
+		}
+		break;
+
+	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+		switch (wValue) {
+		case (RH_PORT_SUSPEND):
+			SET_RH_PORTSTAT (USBPORTSC_SUSP);
+			OK (0);
+		case (RH_PORT_RESET):
+			SET_RH_PORTSTAT (USBPORTSC_PR);
+			uhci_wait_ms (10);
+			uhci->rh.c_p_r[wIndex - 1] = 1;
+			CLR_RH_PORTSTAT (USBPORTSC_PR);
+			udelay (10);
+			SET_RH_PORTSTAT (USBPORTSC_PE);
+			uhci_wait_ms (10);
+			SET_RH_PORTSTAT (0xa);
+			OK (0);
+		case (RH_PORT_POWER):
+			OK (0);	/* port power ** */
+		case (RH_PORT_ENABLE):
+			SET_RH_PORTSTAT (USBPORTSC_PE);
+			OK (0);
+		}
+		break;
+
+	case RH_SET_ADDRESS:
+		uhci->rh.devnum = wValue;
+		OK (0);
+
+	case RH_GET_DESCRIPTOR:
+		switch ((wValue & 0xff00) >> 8) {
+		case (0x01):	/* device descriptor */
+			len = min_t(unsigned int, leni,
+				  min_t(unsigned int,
+				      sizeof (root_hub_dev_des), wLength));
+			memcpy (data, root_hub_dev_des, len);
+			OK (len);
+		case (0x02):	/* configuration descriptor */
+			len = min_t(unsigned int, leni,
+				  min_t(unsigned int,
+				      sizeof (root_hub_config_des), wLength));
+			memcpy (data, root_hub_config_des, len);
+			OK (len);
+		case (0x03):	/* string descriptors */
+			len = usb_root_hub_string (wValue & 0xff,
+			        uhci->io_addr, "UHCI",
+				data, wLength);
+			if (len > 0) {
+				OK(min_t(int, leni, len));
+			} else 
+				stat = -EPIPE;
+		}
+		break;
+
+	case RH_GET_DESCRIPTOR | RH_CLASS:
+		root_hub_hub_des[2] = uhci->rh.numports;
+		len = min_t(unsigned int, leni,
+			  min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
+		memcpy (data, root_hub_hub_des, len);
+		OK (len);
+
+	case RH_GET_CONFIGURATION:
+		*(__u8 *) data = 0x01;
+		OK (1);
+
+	case RH_SET_CONFIGURATION:
+		OK (0);
+	default:
+		stat = -EPIPE;
+	}
+
+	dbg("Root-Hub stat port1: %x port2: %x",
+	     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));
+
+	urb->actual_length = len;
+	urb->status = stat;
+	urb->dev=NULL;
+	if (urb->complete)
+		urb->complete (urb);
+	return 0;
+}
+/*-------------------------------------------------------------------------*/
+
+_static int rh_unlink_urb (struct urb *urb)
+{
+	uhci_t *uhci = urb->dev->bus->hcpriv;
+
+	if (uhci->rh.urb==urb) {
+		dbg("Root-Hub unlink IRQ");
+		uhci->rh.send = 0;
+		del_timer (&uhci->rh.rh_int_timer);
+	}
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+
+/*
+ * Map status to standard result codes
+ *
+ * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)
+ * <dir_out> is True for output TDs and False for input TDs.
+ */
+_static int uhci_map_status (int status, int dir_out)
+{
+	if (!status)
+		return 0;
+	if (status & TD_CTRL_BITSTUFF)	/* Bitstuff error */
+		return -EPROTO;
+	if (status & TD_CTRL_CRCTIMEO) {	/* CRC/Timeout */
+		if (dir_out)
+			return -ETIMEDOUT;
+		else
+			return -EILSEQ;
+	}
+	if (status & TD_CTRL_NAK)	/* NAK */
+		return -ETIMEDOUT;
+	if (status & TD_CTRL_BABBLE)	/* Babble */
+		return -EOVERFLOW;
+	if (status & TD_CTRL_DBUFERR)	/* Buffer error */
+		return -ENOSR;
+	if (status & TD_CTRL_STALLED)	/* Stalled */
+		return -EPIPE;
+	if (status & TD_CTRL_ACTIVE)	/* Active */
+		return 0;
+
+	return -EPROTO;
+}
+
+/*
+ * Only the USB core should call uhci_alloc_dev and uhci_free_dev
+ */
+_static int uhci_alloc_dev (struct usb_device *usb_dev)
+{
+	return 0;
+}
+
+_static void uhci_unlink_urbs(uhci_t *s, struct usb_device *usb_dev, int remove_all)
+{
+	unsigned long flags;
+	struct list_head *p;
+	struct list_head *p2;
+	struct urb *urb;
+
+	spin_lock_irqsave (&s->urb_list_lock, flags);
+	p = s->urb_list.prev;	
+	while (p != &s->urb_list) {
+		p2 = p;
+		p = p->prev ;
+		urb = list_entry (p2, struct urb, urb_list);
+		dbg("urb: %p, dev %p, %p", urb, usb_dev,urb->dev);
+		
+		//urb->transfer_flags |=USB_ASYNC_UNLINK; 
+			
+		if (remove_all || (usb_dev == urb->dev)) {
+			spin_unlock_irqrestore (&s->urb_list_lock, flags);
+			warn("forced removing of queued URB %p due to disconnect",urb);
+			uhci_unlink_urb(urb);
+			urb->dev = NULL; // avoid further processing of this URB
+			spin_lock_irqsave (&s->urb_list_lock, flags);
+			p = s->urb_list.prev;	
+		}
+	}
+	spin_unlock_irqrestore (&s->urb_list_lock, flags);
+}
+
+_static int uhci_free_dev (struct usb_device *usb_dev)
+{
+	uhci_t *s;
+	
+
+	if(!usb_dev || !usb_dev->bus || !usb_dev->bus->hcpriv)
+		return -EINVAL;
+	
+	s=(uhci_t*) usb_dev->bus->hcpriv;	
+	uhci_unlink_urbs(s, usb_dev, 0);
+
+	return 0;
+}
+
+/*
+ * uhci_get_current_frame_number()
+ *
+ * returns the current frame number for a USB bus/controller.
+ */
+_static int uhci_get_current_frame_number (struct usb_device *usb_dev)
+{
+	return UHCI_GET_CURRENT_FRAME ((uhci_t*) usb_dev->bus->hcpriv);
+}
+
+struct usb_operations uhci_device_operations =
+{
+	allocate:		uhci_alloc_dev,
+	deallocate:		uhci_free_dev,
+	get_frame_number:	uhci_get_current_frame_number,
+	submit_urb:		uhci_submit_urb,
+	unlink_urb:		uhci_unlink_urb,
+};
+
+_static void correct_data_toggles(struct urb *urb)
+{
+	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), 
+		       !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)));
+
+	while(urb) {
+		urb_priv_t *priv=urb->hcpriv;		
+		uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list);
+		struct list_head *p = qh->vertical.next;
+		uhci_desc_t *td;
+		dbg("URB to correct %p\n", urb);
+	
+		for (; p != &qh->vertical; p = p->next) {
+			td = list_entry (p, uhci_desc_t, vertical);
+			td->hw.td.info^=cpu_to_le32(1<<TD_TOKEN_TOGGLE);
+		}
+		urb=priv->next_queued_urb;
+	}
+}
+
+/* 
+ * For IN-control transfers, process_transfer gets a bit more complicated,
+ * since there are devices that return less data (eg. strings) than they
+ * have announced. This leads to a queue abort due to the short packet,
+ * the status stage is not executed. If this happens, the status stage
+ * is manually re-executed.
+ * mode: PROCESS_TRANSFER_REGULAR: regular (unlink QH)
+ *       PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb)
+ */
+
+_static int process_transfer (uhci_t *s, struct urb *urb, int mode)
+{
+	int ret = 0;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *qhl = urb_priv->desc_list.next;
+	uhci_desc_t *qh = list_entry (qhl, uhci_desc_t, desc_list);
+	struct list_head *p = qh->vertical.next;
+	uhci_desc_t *desc= list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
+	uhci_desc_t *last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical);
+	int data_toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));	// save initial data_toggle
+	int maxlength; 	// extracted and remapped info from TD
+	int actual_length;
+	int status = 0;
+
+	//dbg("process_transfer: urb %p, urb_priv %p, qh %p last_desc %p\n",urb,urb_priv, qh, last_desc);
+
+	/* if the status phase has been retriggered and the
+	   queue is empty or the last status-TD is inactive, the retriggered
+	   status stage is completed
+	 */
+
+	if (urb_priv->flags && 
+	    ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) || !is_td_active(desc)))
+		goto transfer_finished;
+
+	urb->actual_length=0;
+
+	for (; p != &qh->vertical; p = p->next) {
+		desc = list_entry (p, uhci_desc_t, vertical);
+
+		if (is_td_active(desc)) {	// do not process active TDs
+			if (mode == CLEAN_TRANSFER_DELETION_MARK) // if called from async_unlink
+				uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK);
+			return ret;
+		}
+	
+		actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));		// extract transfer parameters from TD
+		maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff;
+		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
+
+		if (status == -EPIPE) { 		// see if EP is stalled
+			// set up stalled condition
+			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+		}
+
+		if (status && (status != -EPIPE)) {	// if any error occurred stop processing of further TDs
+			// only set ret if status returned an error
+  is_error:
+			ret = status;
+			urb->error_count++;
+			break;
+		}
+		else if ((le32_to_cpu(desc->hw.td.info) & 0xff) != USB_PID_SETUP)
+			urb->actual_length += actual_length;
+
+		// got less data than requested
+		if ( (actual_length < maxlength)) {
+			if (urb->transfer_flags & USB_DISABLE_SPD) {
+				status = -EREMOTEIO;	// treat as real error
+				dbg("process_transfer: SPD!!");
+				break;	// exit after this TD because SP was detected
+			}
+
+			// short read during control-IN: re-start status stage
+			if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) {
+				if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) {
+			
+					set_qh_element(qh, last_desc->dma_addr);  // re-trigger status stage
+					dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
+					urb_priv->flags = 1; // mark as short control packet
+					return 0;
+				}
+			}
+			// all other cases: short read is OK
+			data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
+			break;
+		}
+		else if (status)
+			goto is_error;
+
+		data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
+		queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, le32_to_cpu(desc->hw.td.status),status, data_toggle);      
+
+	}
+
+	if (usb_pipetype (urb->pipe) == PIPE_BULK ) {  /* toggle correction for short bulk transfers (nonqueued/queued) */
+
+		urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
+		struct urb *next_queued_urb=priv->next_queued_urb;
+
+		if (next_queued_urb) {
+			urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv;
+			uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list);
+			uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical);
+
+			if (data_toggle == uhci_toggle (le32_to_cpu(first_td->hw.td.info))) {
+				err("process_transfer: fixed toggle");
+				correct_data_toggles(next_queued_urb);
+			}						
+		}
+		else
+			usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle);		
+	}
+
+ transfer_finished:
+	
+	uhci_clean_transfer(s, urb, qh, mode);
+
+	urb->status = status;
+
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH	
+	disable_desc_loop(s,urb);
+#endif	
+
+	queue_dbg("process_transfer: (end) urb %p, wanted len %d, len %d status %x err %d",
+		urb,urb->transfer_buffer_length,urb->actual_length, urb->status, urb->error_count);
+	return ret;
+}
+
+_static int process_interrupt (uhci_t *s, struct urb *urb)
+{
+	int i, ret = -EINPROGRESS;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *p = urb_priv->desc_list.next;
+	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
+
+	int actual_length;
+	int status = 0;
+
+	//dbg("urb contains interrupt request");
+
+	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
+	{
+		desc = list_entry (p, uhci_desc_t, desc_list);
+
+		if (is_td_active(desc)) {
+			// do not process active TDs
+			//dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status));
+			break;
+		}
+
+		if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) {
+			// do not process one-shot TDs, no recycling
+			break;
+		}
+		// extract transfer parameters from TD
+
+		actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));
+		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
+
+		// see if EP is stalled
+		if (status == -EPIPE) {
+			// set up stalled condition
+			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+		}
+
+		// if any error occurred: ignore this td, and continue
+		if (status != 0) {
+			//uhci_show_td (desc);
+			urb->error_count++;
+			goto recycle;
+		}
+		else
+			urb->actual_length = actual_length;
+
+	recycle:
+		uhci_urb_dma_sync(s, urb, urb->hcpriv);
+		if (urb->complete) {
+			//dbg("process_interrupt: calling completion, status %i",status);
+			urb->status = status;
+			((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion
+
+			spin_unlock(&s->urb_list_lock);
+			
+			urb->complete ((struct urb *) urb);
+			
+			spin_lock(&s->urb_list_lock);
+
+			((urb_priv_t*)urb->hcpriv)->flags=0;		       			
+		}
+		
+		if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
+			    (urb->status != -ENOENT)) {
+
+			urb->status = -EINPROGRESS;
+
+			// Recycle INT-TD if interval!=0, else mark TD as one-shot
+			if (urb->interval) {
+				
+				desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
+				if (status==0) {
+					((urb_priv_t*)urb->hcpriv)->started=jiffies;
+					desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
+					usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+				} else {
+					desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
+				}
+				desc->hw.td.status= cpu_to_le32(TD_CTRL_ACTIVE | TD_CTRL_IOC |
+					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
+				if (urb->dev->speed == USB_SPEED_LOW)
+					desc->hw.td.status |=
+					    __constant_cpu_to_le32 (TD_CTRL_LS);
+				mb();
+			}
+			else {
+				uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
+				// correct toggle after unlink
+				usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+				clr_td_ioc(desc); // inactivate TD
+			}
+		}
+	}
+
+	return ret;
+}
+
+// mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs
+// mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked)
+
+_static int process_iso (uhci_t *s, struct urb *urb, int mode)
+{
+	int i;
+	int ret = 0;
+	urb_priv_t *urb_priv = urb->hcpriv;
+	struct list_head *p = urb_priv->desc_list.next, *p_tmp;
+	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
+
+	dbg("urb contains iso request");
+	if (is_td_active(desc) && mode==PROCESS_ISO_REGULAR)
+		return -EXDEV;	// last TD not finished
+
+	urb->error_count = 0;
+	urb->actual_length = 0;
+	urb->status = 0;
+	dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s),
+	    urb->number_of_packets,mode,le32_to_cpu(desc->hw.td.status));
+
+	for (i = 0; p != &urb_priv->desc_list;  i++) {
+		desc = list_entry (p, uhci_desc_t, desc_list);
+		
+		//uhci_show_td(desc);
+		if (is_td_active(desc)) {
+			// means we have completed the last TD, but not the TDs before
+			desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE);
+			dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status));
+			ret = -EXDEV;
+			urb->iso_frame_desc[i].status = ret;
+			unlink_td (s, desc, 1);
+			// FIXME: immediate deletion may be dangerous
+			goto err;
+		}
+
+		if (mode == PROCESS_ISO_REGULAR)
+			unlink_td (s, desc, 1);
+
+		if (urb->number_of_packets <= i) {
+			dbg("urb->number_of_packets (%d)<=(%d)", urb->number_of_packets, i);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		urb->iso_frame_desc[i].actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));
+		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
+		urb->actual_length += urb->iso_frame_desc[i].actual_length;
+
+	      err:
+
+		if (urb->iso_frame_desc[i].status != 0) {
+			urb->error_count++;
+			urb->status = urb->iso_frame_desc[i].status;
+		}
+		dbg("process_iso: %i: len:%d %08x status:%x",
+		     i, urb->iso_frame_desc[i].actual_length, le32_to_cpu(desc->hw.td.status),urb->iso_frame_desc[i].status);
+
+		p_tmp = p;
+		p = p->next;
+		list_del (p_tmp);
+		delete_desc (s, desc);
+	}
+	
+	dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
+	return ret;
+}
+
+
+_static int process_urb (uhci_t *s, struct list_head *p)
+{
+	int ret = 0;
+	struct urb *urb;
+
+	urb=list_entry (p, struct urb, urb_list);
+	//dbg("process_urb: found queued urb: %p", urb);
+
+	switch (usb_pipetype (urb->pipe)) {
+	case PIPE_CONTROL:
+		ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR);
+		break;
+	case PIPE_BULK:
+		if (!s->avoid_bulk.counter)
+			ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR);
+		else
+			return 0;
+		break;
+	case PIPE_ISOCHRONOUS:
+		ret = process_iso (s, urb, PROCESS_ISO_REGULAR);
+		break;
+	case PIPE_INTERRUPT:
+		ret = process_interrupt (s, urb);
+		break;
+	}
+
+	if (urb->status != -EINPROGRESS) {
+		urb_priv_t *urb_priv;
+		struct usb_device *usb_dev;
+		
+		usb_dev=urb->dev;
+
+		/* Release bandwidth for Interrupt or Iso transfers */
+		if (urb->bandwidth) {
+			if (usb_pipetype(urb->pipe)==PIPE_ISOCHRONOUS)
+				usb_release_bandwidth (urb->dev, urb, 1);
+			else if (usb_pipetype(urb->pipe)==PIPE_INTERRUPT && urb->interval)
+				usb_release_bandwidth (urb->dev, urb, 0);
+		}
+
+		dbg("dequeued urb: %p", urb);
+		dequeue_urb (s, urb);
+
+		urb_priv = urb->hcpriv;
+
+		uhci_urb_dma_unmap(s, urb, urb_priv);
+
+#ifdef DEBUG_SLAB
+		kmem_cache_free(urb_priv_kmem, urb_priv);
+#else
+		kfree (urb_priv);
+#endif
+
+		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {  // process_interrupt does completion on its own		
+			struct urb *next_urb = urb->next;
+			int is_ring = 0;
+			int contains_killed = 0;
+			int loop_count=0;
+			
+			if (next_urb) {
+				// Find out if the URBs are linked to a ring
+				while  (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) {
+					if (next_urb->status == -ENOENT) {// killed URBs break ring structure & resubmission
+						contains_killed = 1;
+						break;
+					}	
+					next_urb = next_urb->next;
+					loop_count++;
+				}
+				
+				if (loop_count == MAX_NEXT_COUNT)
+					err("process_urb: Too much linked URBs in ring detection!");
+
+				if (next_urb == urb)
+					is_ring=1;
+			}			
+
+			// Submit idle/non-killed URBs linked with urb->next
+			// Stop before the current URB				
+			
+			next_urb = urb->next;	
+			if (next_urb && !contains_killed) {
+				int ret_submit;
+				next_urb = urb->next;	
+				
+				loop_count=0;
+				while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) {
+					if (next_urb->status != -EINPROGRESS) {
+					
+						if (next_urb->status == -ENOENT) 
+							break;
+
+						spin_unlock(&s->urb_list_lock);
+
+						// FIXME!!!
+						// We need to know the real state, so 
+						// GFP_ATOMIC is probably not correct
+						ret_submit=uhci_submit_urb(next_urb, GFP_ATOMIC);
+						spin_lock(&s->urb_list_lock);
+						
+						if (ret_submit)
+							break;						
+					}
+					loop_count++;
+					next_urb = next_urb->next;
+				}
+				if (loop_count == MAX_NEXT_COUNT)
+					err("process_urb: Too much linked URBs in resubmission!");
+			}
+
+			// Completion
+			if (urb->complete) {
+				int was_unlinked = (urb->status == -ENOENT);
+				urb->dev = NULL;
+				spin_unlock(&s->urb_list_lock);
+
+				urb->complete ((struct urb *) urb);
+
+				// Re-submit the URB if ring-linked
+				if (is_ring && !was_unlinked && !contains_killed) {
+					urb->dev=usb_dev;
+					// FIXME!!!
+					// We need to know the real state, so 
+					// GFP_ATOMIC is probably not correct
+					uhci_submit_urb (urb, GFP_ATOMIC);
+				}
+				spin_lock(&s->urb_list_lock);
+			}
+			
+			usb_dec_dev_use (usb_dev);
+			usb_put_urb (urb);
+		}
+	}
+
+	return ret;
+}
+
+_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
+{
+	uhci_t *s = __uhci;
+	unsigned int io_addr = s->io_addr;
+	unsigned short status;
+	struct list_head *p, *p2;
+	int restarts, work_done;
+	
+	/*
+	 * Read the interrupt status, and write it back to clear the
+	 * interrupt cause
+	 */
+
+	status = inw (io_addr + USBSTS);
+
+	if (!status)		/* shared interrupt, not mine */
+		return;
+
+	dbg("interrupt");
+
+	if (status != 1) {
+		// Avoid too much error messages at a time
+		if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) {
+			warn("interrupt, status %x, frame# %i", status, 
+			     UHCI_GET_CURRENT_FRAME(s));
+			s->last_error_time = jiffies;
+		}
+		
+		// remove host controller halted state
+		if ((status&0x20) && (s->running)) {
+			err("Host controller halted, trying to restart.");
+			outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD);
+		}
+		//uhci_show_status (s);
+	}
+	/*
+	 * traverse the list in *reverse* direction, because new entries
+	 * may be added at the end.
+	 * also, because process_urb may unlink the current urb,
+	 * we need to advance the list before
+	 * New: check for max. workload and restart count
+	 */
+
+	spin_lock (&s->urb_list_lock);
+
+	restarts=0;
+	work_done=0;
+
+restart:
+	s->unlink_urb_done=0;
+	p = s->urb_list.prev;	
+
+	while (p != &s->urb_list && (work_done < 1024)) {
+		p2 = p;
+		p = p->prev;
+
+		process_urb (s, p2);
+		
+		work_done++;
+
+		if (s->unlink_urb_done) {
+			s->unlink_urb_done=0;
+			restarts++;
+			
+			if (restarts<16)	// avoid endless restarts
+				goto restart;
+			else 
+				break;
+		}
+	}
+	if (time_after(jiffies, s->timeout_check + (HZ/30)))
+		uhci_check_timeouts(s);
+
+	clean_descs(s, CLEAN_NOT_FORCED);
+	uhci_cleanup_unlink(s, CLEAN_NOT_FORCED);
+	uhci_switch_timer_int(s);
+							
+	spin_unlock (&s->urb_list_lock);
+	
+	outw (status, io_addr + USBSTS);
+
+	//dbg("uhci_interrupt: done");
+}
+
+_static void reset_hc (uhci_t *s)
+{
+	unsigned int io_addr = s->io_addr;
+
+	s->apm_state = 0;
+	/* Global reset for 50ms */
+	outw (USBCMD_GRESET, io_addr + USBCMD);
+	uhci_wait_ms (50);
+	outw (0, io_addr + USBCMD);
+	uhci_wait_ms (10);
+}
+
+_static void start_hc (uhci_t *s)
+{
+	unsigned int io_addr = s->io_addr;
+	int timeout = 10;
+
+	/*
+	 * Reset the HC - this will force us to get a
+	 * new notification of any already connected
+	 * ports due to the virtual disconnect that it
+	 * implies.
+	 */
+	outw (USBCMD_HCRESET, io_addr + USBCMD);
+
+	while (inw (io_addr + USBCMD) & USBCMD_HCRESET) {
+		if (!--timeout) {
+			err("USBCMD_HCRESET timed out!");
+			break;
+		}
+		udelay(1);
+	}
+
+	/* Turn on all interrupts */
+	outw (USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR);
+
+	/* Start at frame 0 */
+	outw (0, io_addr + USBFRNUM);
+	outl (s->framelist_dma, io_addr + USBFLBASEADD);
+
+	/* Run and mark it configured with a 64-byte max packet */
+	outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+	s->apm_state = 1;
+	s->running = 1;
+}
+
+/* No  __devexit, since it maybe called from alloc_uhci() */
+_static void
+uhci_pci_remove (struct pci_dev *dev)
+{
+	uhci_t *s = pci_get_drvdata(dev);
+	struct usb_device *root_hub = s->bus->root_hub;
+
+	s->running = 0;		    // Don't allow submit_urb
+
+	if (root_hub)
+		usb_disconnect (&root_hub);
+
+	reset_hc (s);
+	wait_ms (1);
+
+	uhci_unlink_urbs (s, 0, CLEAN_FORCED);  // Forced unlink of remaining URBs
+	uhci_cleanup_unlink (s, CLEAN_FORCED);  // force cleanup of async killed URBs
+	
+	usb_deregister_bus (s->bus);
+
+	release_region (s->io_addr, s->io_size);
+	free_irq (s->irq, s);
+	usb_free_bus (s->bus);
+	cleanup_skel (s);
+	kfree (s);
+}
+
+_static int __init uhci_start_usb (uhci_t *s)
+{				/* start it up */
+	/* connect the virtual root hub */
+	struct usb_device *usb_dev;
+
+	usb_dev = usb_alloc_dev (NULL, s->bus);
+	if (!usb_dev)
+		return -1;
+
+	s->bus->root_hub = usb_dev;
+	usb_connect (usb_dev);
+
+	if (usb_register_root_hub (usb_dev, &s->uhci_pci->dev) != 0) {
+		usb_free_dev (usb_dev);
+		return -1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+_static int
+uhci_pci_suspend (struct pci_dev *dev, u32 state)
+{
+	reset_hc((uhci_t *) pci_get_drvdata(dev));
+	return 0;
+}
+
+_static int
+uhci_pci_resume (struct pci_dev *dev)
+{
+	start_hc((uhci_t *) pci_get_drvdata(dev));
+	return 0;
+}
+#endif
+
+_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
+{
+	uhci_t *s;
+	struct usb_bus *bus;
+	char buf[8], *bufp = buf;
+
+#ifndef __sparc__
+	sprintf(buf, "%d", irq);
+#else
+	bufp = __irq_itoa(irq);
+#endif
+	printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
+		io_addr, bufp);
+
+	s = kmalloc (sizeof (uhci_t), GFP_KERNEL);
+	if (!s)
+		return -1;
+
+	memset (s, 0, sizeof (uhci_t));
+	INIT_LIST_HEAD (&s->free_desc);
+	INIT_LIST_HEAD (&s->urb_list);
+	INIT_LIST_HEAD (&s->urb_unlinked);
+	spin_lock_init (&s->urb_list_lock);
+	spin_lock_init (&s->qh_lock);
+	spin_lock_init (&s->td_lock);
+	atomic_set(&s->avoid_bulk, 0);
+	s->irq = -1;
+	s->io_addr = io_addr;
+	s->io_size = io_size;
+	s->uhci_pci=dev;
+
+	bus = usb_alloc_bus (&uhci_device_operations);
+	if (!bus) {
+		kfree (s);
+		return -1;
+	}
+
+	s->bus = bus;
+	bus->hcpriv = s;
+
+	/* UHCI specs says devices must have 2 ports, but goes on to say */
+	/* they may have more but give no way to determine how many they */
+	/* have, so default to 2 */
+	/* According to the UHCI spec, Bit 7 is always set to 1. So we try */
+	/* to use this to our advantage */
+
+	for (s->maxports = 0; s->maxports < (io_size - 0x10) / 2; s->maxports++) {
+		unsigned int portstatus;
+
+		portstatus = inw (io_addr + 0x10 + (s->maxports * 2));
+		dbg("port %i, adr %x status %x", s->maxports,
+			io_addr + 0x10 + (s->maxports * 2), portstatus);
+		if (!(portstatus & 0x0080))
+			break;
+	}
+	warn("Detected %d ports", s->maxports);
+
+	/* This is experimental so anything less than 2 or greater than 8 is */
+	/*  something weird and we'll ignore it */
+	if (s->maxports < 2 || s->maxports > 8) {
+		dbg("Port count misdetected, forcing to 2 ports");
+		s->maxports = 2;
+	}
+
+	s->rh.numports = s->maxports;
+	s->loop_usage=0;
+	if (init_skel (s)) {
+		usb_free_bus (bus);
+		kfree(s);
+		return -1;
+	}
+
+	request_region (s->io_addr, io_size, MODNAME);
+	reset_hc (s);
+	usb_register_bus (s->bus);
+
+	start_hc (s);
+
+	if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) {
+		err("request_irq %d failed!",irq);
+		usb_free_bus (bus);
+		reset_hc (s);
+		release_region (s->io_addr, s->io_size);
+		cleanup_skel(s);
+		kfree(s);
+		return -1;
+	}
+
+	/* Enable PIRQ */
+	pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
+	s->irq = irq;
+
+	if(uhci_start_usb (s) < 0) {
+		uhci_pci_remove(dev);
+		return -1;
+	}
+
+	//chain new uhci device into global list
+	pci_set_drvdata(dev, s);
+	devs=s;
+
+	return 0;
+}
+
+_static int __devinit
+uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int i;
+
+	if (pci_enable_device(dev) < 0)
+		return -ENODEV;
+		
+	if (!dev->irq) {
+		err("found UHCI device with no IRQ assigned. check BIOS settings!");
+		return -ENODEV;
+	}
+	
+	pci_set_master(dev);
+
+	/* Search for the IO base address.. */
+	for (i = 0; i < 6; i++) {
+
+		unsigned int io_addr = pci_resource_start(dev, i);
+		unsigned int io_size = pci_resource_len(dev, i);
+		if (!(pci_resource_flags(dev,i) & IORESOURCE_IO))
+			continue;
+
+		/* Is it already in use? */
+		if (check_region (io_addr, io_size))
+			break;
+		/* disable legacy emulation */
+		pci_write_config_word (dev, USBLEGSUP, 0);
+	
+		return alloc_uhci(dev, dev->irq, io_addr, io_size);
+	}
+	return -ENODEV;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct pci_device_id __devinitdata uhci_pci_ids [] = { {
+
+	/* handle any USB UHCI controller */
+	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x00),
+	class_mask: 	~0,
+
+	/* no matter who makes it */
+	vendor:		PCI_ANY_ID,
+	device:		PCI_ANY_ID,
+	subvendor:	PCI_ANY_ID,
+	subdevice:	PCI_ANY_ID,
+
+	}, { /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE (pci, uhci_pci_ids);
+
+static struct pci_driver uhci_pci_driver = {
+	name:		"usb-uhci",
+	id_table:	&uhci_pci_ids [0],
+
+	probe:		uhci_pci_probe,
+	remove:		uhci_pci_remove,
+
+#ifdef	CONFIG_PM
+	suspend:	uhci_pci_suspend,
+	resume:		uhci_pci_resume,
+#endif	/* PM */
+
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init uhci_hcd_init (void) 
+{
+	int retval;
+
+#ifdef DEBUG_SLAB
+	urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	
+	if(!urb_priv_kmem) {
+		err("kmem_cache_create for urb_priv_t failed (out of memory)");
+		return -ENOMEM;
+	}
+#endif	
+	info(VERSTR);
+
+#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
+	info("High bandwidth mode enabled");	
+#endif
+
+	retval = pci_module_init (&uhci_pci_driver);
+
+#ifdef DEBUG_SLAB
+	if (retval < 0 ) {
+		if (kmem_cache_destroy(urb_priv_kmem))
+			err("urb_priv_kmem remained");
+	}
+#endif
+	
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+
+	return retval;
+}
+
+static void __exit uhci_hcd_cleanup (void) 
+{      
+	pci_unregister_driver (&uhci_pci_driver);
+	
+#ifdef DEBUG_SLAB
+	if(kmem_cache_destroy(urb_priv_kmem))
+		err("urb_priv_kmem remained");
+#endif
+}
+
+module_init (uhci_hcd_init);
+module_exit (uhci_hcd_cleanup);
+
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/host/usb-uhci.h b/drivers/usb/host/usb-uhci.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/host/usb-uhci.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,307 @@
+#ifndef __LINUX_UHCI_H
+#define __LINUX_UHCI_H
+
+/*
+   $Id: usb-uhci.h,v 1.58 2001/08/28 16:45:00 acher Exp $
+ */
+#define MODNAME "usb-uhci"
+#define UHCI_LATENCY_TIMER 0
+
+static __inline__ void uhci_wait_ms(unsigned int ms)
+{
+	if(!in_interrupt())
+	{
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1 + ms * HZ / 1000);
+	}
+	else
+		mdelay(ms);
+}
+
+/* Command register */
+#define USBCMD		0
+#define   USBCMD_RS		0x0001	/* Run/Stop */
+#define   USBCMD_HCRESET	0x0002	/* Host reset */
+#define   USBCMD_GRESET		0x0004	/* Global reset */
+#define   USBCMD_EGSM		0x0008	/* Global Suspend Mode */
+#define   USBCMD_FGR		0x0010	/* Force Global Resume */
+#define   USBCMD_SWDBG		0x0020	/* SW Debug mode */
+#define   USBCMD_CF		0x0040	/* Config Flag (sw only) */
+#define   USBCMD_MAXP		0x0080	/* Max Packet (0 = 32, 1 = 64) */
+
+/* Status register */
+#define USBSTS		2
+#define   USBSTS_USBINT		0x0001	/* Interrupt due to IOC */
+#define   USBSTS_ERROR		0x0002	/* Interrupt due to error */
+#define   USBSTS_RD		0x0004	/* Resume Detect */
+#define   USBSTS_HSE		0x0008	/* Host System Error - basically PCI problems */
+#define   USBSTS_HCPE		0x0010	/* Host Controller Process Error - the scripts were buggy */
+#define   USBSTS_HCH		0x0020	/* HC Halted */
+
+/* Interrupt enable register */
+#define USBINTR		4
+#define   USBINTR_TIMEOUT	0x0001	/* Timeout/CRC error enable */
+#define   USBINTR_RESUME	0x0002	/* Resume interrupt enable */
+#define   USBINTR_IOC		0x0004	/* Interrupt On Complete enable */
+#define   USBINTR_SP		0x0008	/* Short packet interrupt enable */
+
+#define USBFRNUM	6
+#define USBFLBASEADD	8
+#define USBSOF		12
+
+/* USB port status and control registers */
+#define USBPORTSC1	16
+#define USBPORTSC2	18
+#define   USBPORTSC_CCS		0x0001	/* Current Connect Status ("device present") */
+#define   USBPORTSC_CSC		0x0002	/* Connect Status Change */
+#define   USBPORTSC_PE		0x0004	/* Port Enable */
+#define   USBPORTSC_PEC		0x0008	/* Port Enable Change */
+#define   USBPORTSC_LS		0x0030	/* Line Status */
+#define   USBPORTSC_RD		0x0040	/* Resume Detect */
+#define   USBPORTSC_LSDA	0x0100	/* Low Speed Device Attached */
+#define   USBPORTSC_PR		0x0200	/* Port Reset */
+#define   USBPORTSC_SUSP	0x1000	/* Suspend */
+
+/* Legacy support register */
+#define USBLEGSUP 0xc0
+#define USBLEGSUP_DEFAULT 0x2000	/* only PIRQ enable set */
+
+#define UHCI_NULL_DATA_SIZE	0x7ff	/* for UHCI controller TD */
+#define UHCI_PID 		0xff	/* PID MASK */
+
+#define UHCI_PTR_BITS		0x000F
+#define UHCI_PTR_TERM		0x0001
+#define UHCI_PTR_QH		0x0002
+#define UHCI_PTR_DEPTH		0x0004
+
+#define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
+#define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
+#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
+
+/*
+ * for TD <status>:
+ */
+#define TD_CTRL_SPD		(1 << 29)	/* Short Packet Detect */
+#define TD_CTRL_C_ERR_MASK	(3 << 27)	/* Error Counter bits */
+#define TD_CTRL_LS		(1 << 26)	/* Low Speed Device */
+#define TD_CTRL_IOS		(1 << 25)	/* Isochronous Select */
+#define TD_CTRL_IOC		(1 << 24)	/* Interrupt on Complete */
+#define TD_CTRL_ACTIVE		(1 << 23)	/* TD Active */
+#define TD_CTRL_STALLED		(1 << 22)	/* TD Stalled */
+#define TD_CTRL_DBUFERR		(1 << 21)	/* Data Buffer Error */
+#define TD_CTRL_BABBLE		(1 << 20)	/* Babble Detected */
+#define TD_CTRL_NAK		(1 << 19)	/* NAK Received */
+#define TD_CTRL_CRCTIMEO	(1 << 18)	/* CRC/Time Out Error */
+#define TD_CTRL_BITSTUFF	(1 << 17)	/* Bit Stuff Error */
+#define TD_CTRL_ACTLEN_MASK	0x7ff	/* actual length, encoded as n - 1 */
+
+#define TD_CTRL_ANY_ERROR	(TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
+
+#define uhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
+#define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK)	/* 1-based */
+
+/*
+ * for TD <flags>:
+ */
+#define UHCI_TD_REMOVE		0x0001	/* Remove when done */
+
+/*
+ * for TD <info>: (a.k.a. Token)
+ */
+#define TD_TOKEN_TOGGLE		19
+
+#define uhci_maxlen(token)	((token) >> 21)
+#define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
+#define uhci_endpoint(token)	(((token) >> 15) & 0xf)
+#define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
+#define uhci_devep(token)	(((token) >> 8) & 0x7ff)
+#define uhci_packetid(token)	((token) & 0xff)
+#define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
+#define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
+
+/* ------------------------------------------------------------------------------------
+   New TD/QH-structures
+   ------------------------------------------------------------------------------------ */
+typedef enum {
+	TD_TYPE, QH_TYPE
+} uhci_desc_type_t;
+
+typedef struct {
+	__u32 link;
+	__u32 status;
+	__u32 info;
+	__u32 buffer;
+} uhci_td_t, *puhci_td_t;
+
+typedef struct {
+	__u32 head;
+	__u32 element;		/* Queue element pointer */
+} uhci_qh_t, *puhci_qh_t;
+
+typedef struct {
+	union {
+		uhci_td_t td;
+		uhci_qh_t qh;
+	} hw;
+	uhci_desc_type_t type;
+	dma_addr_t dma_addr;
+	struct list_head horizontal;
+	struct list_head vertical;
+	struct list_head desc_list;
+	int last_used;
+} uhci_desc_t, *puhci_desc_t;
+
+typedef struct {
+	struct list_head desc_list;	// list pointer to all corresponding TDs/QHs associated with this request
+	dma_addr_t setup_packet_dma;
+	dma_addr_t transfer_buffer_dma;
+	unsigned long started;
+	struct urb *next_queued_urb;	// next queued urb for this EP
+	struct urb *prev_queued_urb;
+	uhci_desc_t *bottom_qh;
+	uhci_desc_t *next_qh;       	// next helper QH
+	char use_loop;
+	char flags;
+} urb_priv_t, *purb_priv_t;
+
+struct virt_root_hub {
+	int devnum;		/* Address of Root Hub endpoint */
+	void *urb;
+	void *int_addr;
+	int send;
+	int interval;
+	int numports;
+	int c_p_r[8];
+	struct timer_list rh_int_timer;
+};
+
+typedef struct uhci {
+	int irq;
+	unsigned int io_addr;
+	unsigned int io_size;
+	unsigned int maxports;
+	int running;
+
+	int apm_state;
+
+	struct uhci *next;	// chain of uhci device contexts
+
+	struct list_head urb_list;	// list of all pending urbs
+
+	spinlock_t urb_list_lock;	// lock to keep consistency 
+
+	int unlink_urb_done;
+	atomic_t avoid_bulk;
+	
+	struct usb_bus *bus;	// our bus
+
+	__u32 *framelist;
+	dma_addr_t framelist_dma;
+	uhci_desc_t **iso_td;
+	uhci_desc_t *int_chain[8];
+	uhci_desc_t *ls_control_chain;
+	uhci_desc_t *control_chain;
+	uhci_desc_t *bulk_chain;
+	uhci_desc_t *chain_end;
+	uhci_desc_t *td1ms;
+	uhci_desc_t *td32ms;
+	struct list_head free_desc;
+	spinlock_t qh_lock;
+	spinlock_t td_lock;
+	struct virt_root_hub rh;	//private data of the virtual root hub
+	int loop_usage;            // URBs using bandwidth reclamation
+
+	struct list_head urb_unlinked;	// list of all unlinked  urbs
+	long timeout_check;
+	int timeout_urbs;
+	struct pci_dev *uhci_pci;
+	struct pci_pool *desc_pool;
+	long last_error_time;          // last error output in uhci_interrupt()
+} uhci_t, *puhci_t;
+
+
+#define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH)
+#define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH)
+#define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM))
+
+#define CLEAN_TRANSFER_NO_DELETION 0
+#define CLEAN_TRANSFER_REGULAR 1
+#define CLEAN_TRANSFER_DELETION_MARK 2
+
+#define CLEAN_NOT_FORCED 0
+#define CLEAN_FORCED 1
+
+#define PROCESS_ISO_REGULAR 0
+#define PROCESS_ISO_FORCE 1
+
+#define UNLINK_ASYNC_STORE_URB 0
+#define UNLINK_ASYNC_DONT_STORE 1
+
+#define is_td_active(desc) (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE))
+
+#define set_qh_head(desc,val) (desc)->hw.qh.head=cpu_to_le32(val)
+#define set_qh_element(desc,val) (desc)->hw.qh.element=cpu_to_le32(val)
+#define set_td_link(desc,val) (desc)->hw.td.link=cpu_to_le32(val)
+#define set_td_ioc(desc) (desc)->hw.td.status |= cpu_to_le32(TD_CTRL_IOC)
+#define clr_td_ioc(desc) (desc)->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC)
+
+
+/* ------------------------------------------------------------------------------------ 
+   Virtual Root HUB 
+   ------------------------------------------------------------------------------------ */
+/* destination of request */
+#define RH_INTERFACE               0x01
+#define RH_ENDPOINT                0x02
+#define RH_OTHER                   0x03
+
+#define RH_CLASS                   0x20
+#define RH_VENDOR                  0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS			0x0500
+#define RH_GET_DESCRIPTOR		0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION	0x0880
+#define RH_SET_CONFIGURATION	0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP               0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION         0x00
+#define RH_PORT_ENABLE             0x01
+#define RH_PORT_SUSPEND            0x02
+#define RH_PORT_OVER_CURRENT       0x03
+#define RH_PORT_RESET              0x04
+#define RH_PORT_POWER              0x08
+#define RH_PORT_LOW_SPEED          0x09
+#define RH_C_PORT_CONNECTION       0x10
+#define RH_C_PORT_ENABLE           0x11
+#define RH_C_PORT_SUSPEND          0x12
+#define RH_C_PORT_OVER_CURRENT     0x13
+#define RH_C_PORT_RESET            0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER       0x00
+#define RH_C_HUB_OVER_CURRENT      0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP    0x00
+#define RH_ENDPOINT_STALL          0x01
+
+/* Our Vendor Specific feature */
+#define RH_REMOVE_EP               0x00
+
+
+#define RH_ACK                     0x01
+#define RH_REQ_ERR                 -1
+#define RH_NACK                    0x00
+
+#endif
diff -Nru a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c
--- a/drivers/usb/hpusbscsi.c	Sun Apr 14 12:17:00 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,561 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-#include <asm/atomic.h>
-#include <linux/blk.h>
-#include "../scsi/scsi.h"
-#include "../scsi/hosts.h"
-#include "../scsi/sd.h"
-
-#include "hpusbscsi.h"
-
-#define DEBUG(x...) \
-	printk( KERN_DEBUG x )
-
-static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
-
-#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
-
-/* global variables */
-
-struct list_head hpusbscsi_devices;
-//LIST_HEAD(hpusbscsi_devices);
-
-/* USB related parts */
-
-static void *
-hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
-		     const struct usb_device_id *id)
-{
-	struct hpusbscsi *new;
-	struct usb_interface_descriptor *altsetting =
-		&(dev->actconfig->interface[interface].altsetting[0]);
-
-	int i, result;
-
-	/* basic check */
-
-	if (altsetting->bNumEndpoints != 3) {
-		printk (KERN_ERR "Wrong number of endpoints\n");
-		return NULL;
-	}
-
-	/* descriptor allocation */
-
-	new =
-		(struct hpusbscsi *) kmalloc (sizeof (struct hpusbscsi),
-					      GFP_KERNEL);
-	if (new == NULL)
-		return NULL;
-	DEBUG ("Allocated memory\n");
-	memset (new, 0, sizeof (struct hpusbscsi));
-	new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new->dataurb) {
-		kfree (new);
-		return NULL;
-	}
-	new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new->controlurb) {
-		usb_free_urb (new->dataurb);
-		kfree (new);
-		return NULL;
-	}
-	new->dev = dev;
-	init_waitqueue_head (&new->pending);
-	init_waitqueue_head (&new->deathrow);
-	INIT_LIST_HEAD (&new->lh);
-
-
-
-	/* finding endpoints */
-
-	for (i = 0; i < altsetting->bNumEndpoints; i++) {
-		if (
-		    (altsetting->endpoint[i].
-		     bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-		    USB_ENDPOINT_XFER_BULK) {
-			if (altsetting->endpoint[i].
-			    bEndpointAddress & USB_DIR_IN) {
-				new->ep_in =
-					altsetting->endpoint[i].
-					bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK;
-			} else {
-				new->ep_out =
-					altsetting->endpoint[i].
-					bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK;
-			}
-		} else {
-			new->ep_int =
-				altsetting->endpoint[i].
-				bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-			new->interrupt_interval= altsetting->endpoint[i].bInterval;
-		}
-	}
-
-	/* USB initialisation magic for the simple case */
-
-	result = usb_set_interface (dev, altsetting->bInterfaceNumber, 0);
-
-	switch (result) {
-	case 0:		/* no error */
-		break;
-
-	case -EPIPE:
-		usb_clear_halt (dev, usb_sndctrlpipe (dev, 0));
-		break;
-
-	default:
-		printk (KERN_ERR "unknown error %d from usb_set_interface\n",
-			 result);
-		goto err_out;
-	}
-
-	/* making a template for the scsi layer to fake detection of a scsi device */
-
-	memcpy (&(new->ctempl), &hpusbscsi_scsi_host_template,
-		sizeof (hpusbscsi_scsi_host_template));
-	(struct hpusbscsi *) new->ctempl.proc_dir = new;
-	new->ctempl.module = THIS_MODULE;
-
-	if (scsi_register_host(&new->ctempl))
-		goto err_out;
-
-	/* adding to list for module unload */
-	list_add (&hpusbscsi_devices, &new->lh);
-
-	return new;
-
-      err_out:
-	usb_free_urb (new->controlurb);
-	usb_free_urb (new->dataurb);
-	kfree (new);
-	return NULL;
-}
-
-static void
-hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
-{
-                 usb_unlink_urb((((struct hpusbscsi *) ptr)->controlurb));
-	((struct hpusbscsi *) ptr)->dev = NULL;
-}
-
-static struct usb_device_id hpusbscsi_usb_ids[] = {
-	{USB_DEVICE (0x03f0, 0x0701)},	/* HP 53xx */
-	{USB_DEVICE (0x03f0, 0x0801)},	/* HP 7400 */
-	{USB_DEVICE (0x0638, 0x026a)},	/*Scan Dual II */
-	{}			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids);
-MODULE_LICENSE("GPL");
-
-
-static struct usb_driver hpusbscsi_usb_driver = {
-	name:"hpusbscsi",
-	probe:hpusbscsi_usb_probe,
-	disconnect:hpusbscsi_usb_disconnect,
-	id_table:hpusbscsi_usb_ids,
-};
-
-/* module initialisation */
-
-int __init
-hpusbscsi_init (void)
-{
-	int result;
-
-	INIT_LIST_HEAD (&hpusbscsi_devices);
-	DEBUG ("Driver loaded\n");
-
-	if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
-		printk (KERN_ERR "hpusbscsi: driver registration failed\n");
-		return -1;
-	} else {
-		return 0;
-	}
-}
-
-void __exit
-hpusbscsi_exit (void)
-{
-	struct list_head *tmp;
-	struct list_head *old;
-	struct hpusbscsi * o;
-
-	for (tmp = hpusbscsi_devices.next; tmp != &hpusbscsi_devices;/*nothing */) {
-		old = tmp;
-		tmp = tmp->next;
-		o = (struct hpusbscsi *)old;
-		usb_unlink_urb(o->controlurb);
-		scsi_unregister_host(&o->ctempl);
-		usb_free_urb(o->controlurb);
-		usb_free_urb(o->dataurb);
-		kfree(old);
-	}
-
-	usb_deregister (&hpusbscsi_usb_driver);
-}
-
-module_init (hpusbscsi_init);
-module_exit (hpusbscsi_exit);
-
-/* interface to the scsi layer */
-
-static int
-hpusbscsi_scsi_detect (struct SHT *sht)
-{
-	/* Whole function stolen from usb-storage */
-
-	struct hpusbscsi *desc = (struct hpusbscsi *) sht->proc_dir;
-	/* What a hideous hack! */
-
-	char local_name[48];
-
-
-	/* set up the name of our subdirectory under /proc/scsi/ */
-	sprintf (local_name, "hpusbscsi-%d", desc->number);
-	sht->proc_name = kmalloc (strlen (local_name) + 1, GFP_KERNEL);
-	/* FIXME: where is this freed ? */
-
-	if (!sht->proc_name) {
-		return 0;
-	}
-
-	strcpy (sht->proc_name, local_name);
-
-	sht->proc_dir = NULL;
-
-	/* build and submit an interrupt URB for status byte handling */
- 	FILL_INT_URB(desc->controlurb,
-			desc->dev,
-			usb_rcvintpipe(desc->dev,desc->ep_int),
-			&desc->scsi_state_byte,
-			1,
-			control_interrupt_callback,
-			desc,
-			desc->interrupt_interval
-	);
-
-	if ( 0  >  usb_submit_urb(desc->controlurb, GFP_KERNEL)) {
-		kfree(sht->proc_name);
-		return 0;
-	}
-
-	/* In host->hostdata we store a pointer to desc */
-	desc->host = scsi_register (sht, sizeof (desc));
-	if (desc->host == NULL) {
-		kfree (sht->proc_name);
-		usb_unlink_urb(desc->controlurb);
-		return 0;
-	}
-	desc->host->hostdata[0] = (unsigned long) desc;
-
-
-	return 1;
-}
-
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
-{
-	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
-	usb_urb_callback usb_callback;
-	int res;
-
-	hpusbscsi->use_count++;
-
-	/* we don't answer for anything but our single device on any faked host controller */
-	if ( srb->device->lun || srb->device->id || srb->device->channel ) {
-		if (callback) {
-			srb->result = DID_BAD_TARGET;
-			callback(srb);
-		}
-                	goto out;
-	}
-
-	/* Now we need to decide which callback to give to the urb we send the command with */
-
-	if (!srb->bufflen) {
-		if (srb->cmnd[0] == REQUEST_SENSE){
-			hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
-			usb_callback = request_sense_callback;
-		} else {
-			usb_callback = simple_command_callback;
-		}
-	} else {
-        	if (likely(srb->use_sg)) {
-			usb_callback = scatter_gather_callback;
-			hpusbscsi->fragment = 0;
-		} else {
-                	usb_callback = simple_payload_callback;
-		}
-		/* Now we find out which direction data is to be transfered in */
-		hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ?
-			usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in)
-		:
-			usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out)
-		;
-	}
-
-
-	TRACE_STATE;
-
-        /* We zero the sense buffer to avoid confusing user space */
-        memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-
-	hpusbscsi->state = HP_STATE_BEGINNING;
-	TRACE_STATE;
-
-	/* We prepare the urb for writing out the scsi command */
-	FILL_BULK_URB(
-		hpusbscsi->dataurb,
-		hpusbscsi->dev,
-		usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
-		srb->cmnd,
-		srb->cmd_len,
-		usb_callback,
-		hpusbscsi
-	);
-	hpusbscsi->scallback = callback;
-	hpusbscsi->srb = srb;
-
-	res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC);
-	if (unlikely(res)) {
-		hpusbscsi->state = HP_STATE_FREE;
-		TRACE_STATE;
-		if (likely(callback != NULL)) {
-			srb->result = DID_ERROR;
-			callback(srb);
-		}
-	}
-
-out:
-	hpusbscsi->use_count--;
-	return 0;
-}
-
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb)
-{
-	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
-
-	printk(KERN_DEBUG"SCSI reset requested.\n");
-	//usb_reset_device(hpusbscsi->dev);
-	//printk(KERN_DEBUG"SCSI reset completed.\n");
-	hpusbscsi->state = HP_STATE_FREE;
-
-	return 0;
-}
-
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
-{
-	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
-	printk(KERN_DEBUG"Requested is canceled.\n");
-
-	usb_unlink_urb(hpusbscsi->dataurb);
-	usb_unlink_urb(hpusbscsi->controlurb);
-	hpusbscsi->state = HP_STATE_FREE;
-
-	return SCSI_ABORT_PENDING;
-}
-
-/* usb interrupt handlers - they are all running IN INTERRUPT ! */
-
-static void handle_usb_error (struct hpusbscsi *hpusbscsi)
-{
-	if (likely(hpusbscsi->scallback != NULL)) {
-		hpusbscsi->srb->result = DID_ERROR;
-		hpusbscsi->scallback(hpusbscsi->srb);
-	}
-	hpusbscsi->state = HP_STATE_FREE;
-}
-
-static void  control_interrupt_callback (struct urb *u)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
-DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
-	if(unlikely(u->status < 0)) {
-                if (likely(hpusbscsi->state != HP_STATE_FREE))
-                        handle_usb_error(hpusbscsi);
-		return;
-	}
-	hpusbscsi->srb->result &= SCSI_ERR_MASK;
-	hpusbscsi->srb->result |= hpusbscsi->scsi_state_byte;
-
-	if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT)
-		/* we do a callback to the scsi layer if and only if all data has been transfered */
-		hpusbscsi->scallback(hpusbscsi->srb);
-
-	TRACE_STATE;
-	switch (hpusbscsi->state) {
-	case HP_STATE_WAIT:
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-		break;
-	case HP_STATE_WORKING:
-	case HP_STATE_BEGINNING:
-		hpusbscsi->state = HP_STATE_PREMATURE;
-	TRACE_STATE;
-		break;
-	default:
-		printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
-	TRACE_STATE;
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-		break;
-	}
-}
-
-static void simple_command_callback(struct urb *u)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-	if (unlikely(u->status<0)) {
-		handle_usb_error(hpusbscsi);
-		return;
-        }
-	TRACE_STATE;
-	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-	        TRACE_STATE;
-		hpusbscsi->state = HP_STATE_WAIT;
-	} else {
-		if (likely(hpusbscsi->scallback != NULL))
-			hpusbscsi->scallback(hpusbscsi->srb);
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-	}
-}
-
-static void request_sense_callback (struct urb *u)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
-	if (unlikely(u->status<0)) {
-		handle_usb_error(hpusbscsi);
-		return;
-        }
-
-	FILL_BULK_URB(
-		u,
-		hpusbscsi->dev,
-		hpusbscsi->current_data_pipe,
-		hpusbscsi->srb->sense_buffer,
-		SCSI_SENSE_BUFFERSIZE,
-		simple_done,
-		hpusbscsi
-	);
-
-	if (unlikely(0 > usb_submit_urb(u, GFP_ATOMIC))) {
-		handle_usb_error(hpusbscsi);
-		return;
-	}
-	hpusbscsi->state = HP_STATE_WORKING;
-}
-
-static void scatter_gather_callback(struct urb *u)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-        struct scatterlist *sg = hpusbscsi->srb->buffer;
-        usb_urb_callback callback;
-        int res;
-
-        DEBUG("Going through scatter/gather\n");
-        if (unlikely(u->status < 0)) {
-                handle_usb_error(hpusbscsi);
-                return;
-        }
-
-        if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg)
-                callback = scatter_gather_callback;
-        else
-                callback = simple_done;
-
-	TRACE_STATE;
-        if (hpusbscsi->state != HP_STATE_PREMATURE)
-		hpusbscsi->state = HP_STATE_WORKING;
-	TRACE_STATE;
-
-        FILL_BULK_URB(
-                u,
-                hpusbscsi->dev,
-                hpusbscsi->current_data_pipe,
-                page_address(sg[hpusbscsi->fragment].page) +
-		sg[hpusbscsi->fragment].offset,
-                sg[hpusbscsi->fragment++].length,
-                callback,
-                hpusbscsi
-        );
-
-        res = usb_submit_urb(u, GFP_ATOMIC);
-        if (unlikely(res))
-                hpusbscsi->state = HP_STATE_ERROR;
-	TRACE_STATE;
-}
-
-static void simple_done (struct urb *u)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
-        if (unlikely(u->status < 0)) {
-                handle_usb_error(hpusbscsi);
-                return;
-        }
-        DEBUG("Data transfer done\n");
-	TRACE_STATE;
-	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-		if (unlikely(u->status < 0))
-			hpusbscsi->state = HP_STATE_ERROR;
-		else
-			hpusbscsi->state = HP_STATE_WAIT;
-		TRACE_STATE;
-	} else {
-		if (likely(hpusbscsi->scallback != NULL))
-			hpusbscsi->scallback(hpusbscsi->srb);
-		hpusbscsi->state = HP_STATE_FREE;
-	}
-}
-
-static void simple_payload_callback (struct urb *u)
-{
-	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-	int res;
-
-	if (unlikely(u->status<0)) {
-                handle_usb_error(hpusbscsi);
-		return;
-        }
-
-	FILL_BULK_URB(
-		u,
-		hpusbscsi->dev,
-		hpusbscsi->current_data_pipe,
-		hpusbscsi->srb->buffer,
-		hpusbscsi->srb->bufflen,
-		simple_done,
-		hpusbscsi
-	);
-
-	res = usb_submit_urb(u, GFP_ATOMIC);
-	if (unlikely(res)) {
-                handle_usb_error(hpusbscsi);
-		return;
-        }
-	TRACE_STATE;
-	if (hpusbscsi->state != HP_STATE_PREMATURE) {
-		hpusbscsi->state = HP_STATE_WORKING;
-	TRACE_STATE;
-	} else {
-		if (likely(hpusbscsi->scallback != NULL))
-			hpusbscsi->scallback(hpusbscsi->srb);
-		hpusbscsi->state = HP_STATE_FREE;
-	TRACE_STATE;
-	}
-}
-
-
diff -Nru a/drivers/usb/hpusbscsi.h b/drivers/usb/hpusbscsi.h
--- a/drivers/usb/hpusbscsi.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,88 +0,0 @@
-/* Header file for the hpusbscsi driver */
-/* (C) Copyright 2001 Oliver Neukum */
-/* sponsored by the Linux Usb Project */
-/* large parts based on or taken from code by John Fremlin and Matt Dharm */
-/* this file is licensed under the GPL */
-
-typedef void (*usb_urb_callback) (struct urb *);
-typedef void (*scsi_callback)(Scsi_Cmnd *);
-
-struct hpusbscsi
-{
-        struct list_head lh;
-        struct usb_device *dev; /* NULL indicates unplugged device */
-        int ep_out;
-        int ep_in;
-        int ep_int;
-        int interrupt_interval;
-
-        struct Scsi_Host *host;
-        Scsi_Host_Template ctempl;
-        int number;
-       scsi_callback scallback;
-       Scsi_Cmnd *srb;
-
-        int use_count;
-        wait_queue_head_t pending;
-        wait_queue_head_t deathrow;
-
-        struct urb *dataurb;
-        struct urb *controlurb;
-        int fragment;
-
-        int state;
-        int current_data_pipe;
-
-        u8 scsi_state_byte;
-};
-
-#define SCSI_ERR_MASK ~0x3fu
-
-static const unsigned char scsi_command_direction[256/8] = {
-	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
-	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
-
-static int hpusbscsi_scsi_detect (struct SHT * sht);
-static void simple_command_callback(struct urb *u);
-static void scatter_gather_callback(struct urb *u);
-static void simple_payload_callback (struct urb *u);
-static void request_sense_callback (struct urb *u);
-static void control_interrupt_callback (struct urb *u);
-static void simple_done (struct urb *u);
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
-
-static Scsi_Host_Template hpusbscsi_scsi_host_template = {
-	name:           "hpusbscsi",
-	detect:		hpusbscsi_scsi_detect,
-//	release:	hpusbscsi_scsi_release,
-	queuecommand:	hpusbscsi_scsi_queuecommand,
-
-	eh_abort_handler:	hpusbscsi_scsi_abort,
-	eh_host_reset_handler:	hpusbscsi_scsi_host_reset,
-
-	sg_tablesize:		SG_ALL,
-	can_queue:		1,
-	this_id:		-1,
-	cmd_per_lun:		1,
-	present:		0,
-	unchecked_isa_dma:	FALSE,
-	use_clustering:		TRUE,
-	emulated:		TRUE
-};
-
-/* defines for internal driver state */
-#define HP_STATE_FREE                 0  /*ready for next request */
-#define HP_STATE_BEGINNING      1  /*command being transfered */
-#define HP_STATE_WORKING         2  /* data transfer stage */
-#define HP_STATE_ERROR             3  /* error has been reported */
-#define HP_STATE_WAIT                 4  /* waiting for status transfer */
-#define HP_STATE_PREMATURE              5 /* status prematurely reported */
-
-
diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c
--- a/drivers/usb/hub.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1167 +0,0 @@
-/*
- * USB hub driver.
- *
- * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999 Johannes Erdfelt
- * (C) Copyright 1999 Gregory P. Smith
- * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au)
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/completion.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-#include <linux/usb.h>
-#include <linux/usbdevice_fs.h>
-
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-
-#include "hub.h"
-
-/* Wakes up khubd */
-static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
-static DECLARE_MUTEX(usb_address0_sem);
-
-static LIST_HEAD(hub_event_list);	/* List of hubs needing servicing */
-static LIST_HEAD(hub_list);		/* List of all hubs (for cleanup) */
-
-static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
-static int khubd_pid = 0;			/* PID of khubd */
-static DECLARE_COMPLETION(khubd_exited);
-
-#ifdef	DEBUG
-static inline char *portspeed (int portstatus)
-{
-	if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
-    		return "480 Mb/s";
-	else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
-		return "1.5 Mb/s";
-	else
-		return "12 Mb/s";
-}
-#endif
-
-/* USB 2.0 spec Section 11.24.4.5 */
-static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
-		USB_DT_HUB << 8, 0, data, size, HZ);
-}
-
-/*
- * USB 2.0 spec Section 11.24.2.1
- */
-static int usb_clear_hub_feature(struct usb_device *dev, int feature)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
-}
-
-/*
- * USB 2.0 spec Section 11.24.2.2
- * BUG: doesn't handle port indicator selector in high byte of wIndex
- */
-static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
-}
-
-/*
- * USB 2.0 spec Section 11.24.2.13
- * BUG: doesn't handle port indicator selector in high byte of wIndex
- */
-static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
-}
-
-/*
- * USB 2.0 spec Section 11.24.2.6
- */
-static int usb_get_hub_status(struct usb_device *dev, void *data)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
-		data, sizeof(struct usb_hub_status), HZ);
-}
-
-/*
- * USB 2.0 spec Section 11.24.2.7
- */
-static int usb_get_port_status(struct usb_device *dev, int port, void *data)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
-		data, sizeof(struct usb_hub_status), HZ);
-}
-
-/* completion function, fires on port status changes and various faults */
-static void hub_irq(struct urb *urb)
-{
-	struct usb_hub *hub = (struct usb_hub *)urb->context;
-	unsigned long flags;
-
-	switch (urb->status) {
-	case -ENOENT:		/* synchronous unlink */
-	case -ECONNRESET:	/* async unlink */
-	case -ESHUTDOWN:	/* hardware going away */
-		return;
-
-	default:		/* presumably an error */
-		/* Cause a hub reset after 10 consecutive errors */
-		dbg("hub '%s' status %d for interrupt transfer",
-			urb->dev->devpath, urb->status);
-		if ((++hub->nerrors < 10) || hub->error)
-			return;
-		hub->error = urb->status;
-		/* FALL THROUGH */
-	
-	/* let khubd handle things */
-	case 0:			/* we got data:  port status changed */
-		break;
-	}
-
-	hub->nerrors = 0;
-
-	/* Something happened, let khubd figure it out */
-	spin_lock_irqsave(&hub_event_lock, flags);
-	if (list_empty(&hub->event_list)) {
-		list_add(&hub->event_list, &hub_event_list);
-		wake_up(&khubd_wait);
-	}
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-}
-
-static void usb_hub_power_on(struct usb_hub *hub)
-{
-	int i;
-
-	/* Enable power to the ports */
-	dbg("enabling power on all ports");
-	for (i = 0; i < hub->descriptor->bNbrPorts; i++)
-		usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER);
-
-	/* Wait for power to be enabled */
-	wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
-}
-
-static int usb_hub_configure(struct usb_hub *hub,
-	struct usb_endpoint_descriptor *endpoint)
-{
-	struct usb_device *dev = hub->dev;
-	struct usb_hub_status hubstatus;
-	char portstr[USB_MAXCHILDREN + 1];
-	unsigned int pipe;
-	int i, maxp, ret;
-
-	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
-	if (!hub->descriptor) {
-		err("Unable to kmalloc %Zd bytes for hub descriptor",
-			sizeof(*hub->descriptor));
-		return -1;
-	}
-
-	/* Request the entire hub descriptor.
-	 * hub->descriptor can handle USB_MAXCHILDREN ports,
-	 * but the hub can/will return fewer bytes here.
-	 */
-	ret = usb_get_hub_descriptor(dev, hub->descriptor,
-			sizeof(*hub->descriptor));
-	if (ret < 0) {
-		err("Unable to get hub descriptor (err = %d)", ret);
-		kfree(hub->descriptor);
-		return -1;
-	} else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
-		err("Hub is too big! %d children", hub->descriptor->bNbrPorts);
-		kfree(hub->descriptor);
-		return -1;
-	}
-
-	dev->maxchild = hub->descriptor->bNbrPorts;
-	info("%d port%s detected", dev->maxchild,
-		(dev->maxchild == 1) ? "" : "s");
-
-	le16_to_cpus(&hub->descriptor->wHubCharacteristics);
-
-	if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND)
-		dbg("part of a compound device");
-	else
-		dbg("standalone hub");
-
-	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
-		case 0x00:
-			dbg("ganged power switching");
-			break;
-		case 0x01:
-			dbg("individual port power switching");
-			break;
-		case 0x02:
-		case 0x03:
-			dbg("unknown reserved power switching mode");
-			break;
-	}
-
-	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
-		case 0x00:
-			dbg("global over-current protection");
-			break;
-		case 0x08:
-			dbg("individual port over-current protection");
-			break;
-		case 0x10:
-		case 0x18:
-			dbg("no over-current protection");
-                        break;
-	}
-
-	switch (dev->descriptor.bDeviceProtocol) {
-		case 0:
-			break;
-		case 1:
-			dbg("Single TT");
-			hub->tt.hub = dev;
-			break;
-		case 2:
-			dbg("TT per port");
-			hub->tt.hub = dev;
-			hub->tt.multi = 1;
-			break;
-		default:
-			dbg("Unrecognized hub protocol %d",
-				dev->descriptor.bDeviceProtocol);
-			break;
-	}
-
-	switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) {
-		case 0x00:
-			if (dev->descriptor.bDeviceProtocol != 0)
-				dbg("TT requires at most 8 FS bit times");
-			break;
-		case 0x20:
-			dbg("TT requires at most 16 FS bit times");
-			break;
-		case 0x40:
-			dbg("TT requires at most 24 FS bit times");
-			break;
-		case 0x60:
-			dbg("TT requires at most 32 FS bit times");
-			break;
-	}
-
-	dbg("Port indicators are %s supported", 
-	    (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND)
-	    	? "" : "not");
-
-	dbg("power on to power good time: %dms",
-		hub->descriptor->bPwrOn2PwrGood * 2);
-	dbg("hub controller current requirement: %dmA",
-		hub->descriptor->bHubContrCurrent);
-
-	for (i = 0; i < dev->maxchild; i++)
-		portstr[i] = hub->descriptor->DeviceRemovable
-			    [((i + 1) / 8)] & (1 << ((i + 1) % 8))
-			? 'F' : 'R';
-	portstr[dev->maxchild] = 0;
-
-	dbg("port removable status: %s", portstr);
-
-	ret = usb_get_hub_status(dev, &hubstatus);
-	if (ret < 0) {
-		err("Unable to get hub status (err = %d)", ret);
-		kfree(hub->descriptor);
-		return -1;
-	}
-
-	le16_to_cpus(&hubstatus.wHubStatus);
-
-	dbg("local power source is %s",
-		(hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
-		? "lost (inactive)" : "good");
-
-	dbg("%sover-current condition exists",
-		(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
-
-	/* Start the interrupt endpoint */
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	if (maxp > sizeof(hub->buffer))
-		maxp = sizeof(hub->buffer);
-
-	hub->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!hub->urb) {
-		err("couldn't allocate interrupt urb");
-		kfree(hub->descriptor);
-		return -1;
-	}
-
-	FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
-		hub, endpoint->bInterval);
-	ret = usb_submit_urb(hub->urb, GFP_KERNEL);
-	if (ret) {
-		err("usb_submit_urb failed (%d)", ret);
-		kfree(hub->descriptor);
-		return -1;
-	}
-		
-	/* Wake up khubd */
-	wake_up(&khubd_wait);
-
-	usb_hub_power_on(hub);
-
-	return 0;
-}
-
-static void *hub_probe(struct usb_device *dev, unsigned int i,
-		       const struct usb_device_id *id)
-{
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_hub *hub;
-	unsigned long flags;
-
-	interface = &dev->actconfig->interface[i].altsetting[0];
-
-	/* Some hubs have a subclass of 1, which AFAICT according to the */
-	/*  specs is not defined, but it works */
-	if ((interface->bInterfaceSubClass != 0) &&
-	    (interface->bInterfaceSubClass != 1)) {
-		err("invalid subclass (%d) for USB hub device #%d",
-			interface->bInterfaceSubClass, dev->devnum);
-		return NULL;
-	}
-
-	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
-	if (interface->bNumEndpoints != 1) {
-		err("invalid bNumEndpoints (%d) for USB hub device #%d",
-			interface->bNumEndpoints, dev->devnum);
-		return NULL;
-	}
-
-	endpoint = &interface->endpoint[0];
-
-	/* Output endpoint? Curiousier and curiousier.. */
-	if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
-		err("Device #%d is hub class, but has output endpoint?",
-			dev->devnum);
-		return NULL;
-	}
-
-	/* If it's not an interrupt endpoint, we'd better punt! */
-	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-			!= USB_ENDPOINT_XFER_INT) {
-		err("Device #%d is hub class, but endpoint is not interrupt?",
-			dev->devnum);
-		return NULL;
-	}
-
-	/* We found a hub */
-	info("USB hub found at %s", dev->devpath);
-
-	hub = kmalloc(sizeof(*hub), GFP_KERNEL);
-	if (!hub) {
-		err("couldn't kmalloc hub struct");
-		return NULL;
-	}
-
-	memset(hub, 0, sizeof(*hub));
-
-	INIT_LIST_HEAD(&hub->event_list);
-	hub->dev = dev;
-	init_MUTEX(&hub->khubd_sem);
-
-	/* Record the new hub's existence */
-	spin_lock_irqsave(&hub_event_lock, flags);
-	INIT_LIST_HEAD(&hub->hub_list);
-	list_add(&hub->hub_list, &hub_list);
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-
-	if (usb_hub_configure(hub, endpoint) >= 0)
-		return hub;
-
-	err("hub configuration failed for device at %s", dev->devpath);
-
-	/* free hub, but first clean up its list. */
-	spin_lock_irqsave(&hub_event_lock, flags);
-
-	/* Delete it and then reset it */
-	list_del(&hub->event_list);
-	INIT_LIST_HEAD(&hub->event_list);
-	list_del(&hub->hub_list);
-	INIT_LIST_HEAD(&hub->hub_list);
-
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-
-	kfree(hub);
-
-	return NULL;
-}
-
-static void hub_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_hub *hub = (struct usb_hub *)ptr;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hub_event_lock, flags);
-
-	/* Delete it and then reset it */
-	list_del(&hub->event_list);
-	INIT_LIST_HEAD(&hub->event_list);
-	list_del(&hub->hub_list);
-	INIT_LIST_HEAD(&hub->hub_list);
-
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-
-	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
-	up(&hub->khubd_sem);
-
-	if (hub->urb) {
-		usb_unlink_urb(hub->urb);
-		usb_free_urb(hub->urb);
-		hub->urb = NULL;
-	}
-
-	if (hub->descriptor) {
-		kfree(hub->descriptor);
-		hub->descriptor = NULL;
-	}
-
-	/* Free the memory */
-	kfree(hub);
-}
-
-static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
-{
-	/* assert ifno == 0 (part of hub spec) */
-	switch (code) {
-	case USBDEVFS_HUB_PORTINFO: {
-		struct usbdevfs_hub_portinfo *info = user_data;
-		unsigned long flags;
-		int i;
-
-		spin_lock_irqsave(&hub_event_lock, flags);
-		if (hub->devnum <= 0)
-			info->nports = 0;
-		else {
-			info->nports = hub->maxchild;
-			for (i = 0; i < info->nports; i++) {
-				if (hub->children[i] == NULL)
-					info->port[i] = 0;
-				else
-					info->port[i] =
-						hub->children[i]->devnum;
-			}
-		}
-		spin_unlock_irqrestore(&hub_event_lock, flags);
-
-		return info->nports + 1;
-		}
-
-	default:
-		return -ENOSYS;
-	}
-}
-
-static int usb_hub_reset(struct usb_hub *hub)
-{
-	struct usb_device *dev = hub->dev;
-	int i;
-
-	/* Disconnect any attached devices */
-	for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
-		if (dev->children[i])
-			usb_disconnect(&dev->children[i]);
-	}
-
-	/* Attempt to reset the hub */
-	if (hub->urb)
-		usb_unlink_urb(hub->urb);
-	else
-		return -1;
-
-	if (usb_reset_device(dev))
-		return -1;
-
-	hub->urb->dev = dev;                                                    
-	if (usb_submit_urb(hub->urb, GFP_KERNEL))
-		return -1;
-
-	usb_hub_power_on(hub);
-
-	return 0;
-}
-
-static void usb_hub_disconnect(struct usb_device *dev)
-{
-	struct usb_device *parent = dev->parent;
-	int i;
-
-	/* Find the device pointer to disconnect */
-	if (parent) {
-		for (i = 0; i < parent->maxchild; i++) {
-			if (parent->children[i] == dev) {
-				usb_disconnect(&parent->children[i]);
-				return;
-			}
-		}
-	}
-
-	err("cannot disconnect hub %s", dev->devpath);
-}
-
-static int usb_hub_port_status(struct usb_device *hub, int port,
-			       u16 *status, u16 *change)
-{
-	struct usb_port_status *portsts;
-	int ret = -ENOMEM;
-
-	portsts = kmalloc(sizeof(*portsts), GFP_KERNEL);
-	if (portsts) {
-		ret = usb_get_port_status(hub, port + 1, portsts);
-		if (ret < 0)
-			err("%s(%s) failed (err = %d)", __FUNCTION__, hub->devpath, ret);
-		else {
-			*status = le16_to_cpu(portsts->wPortStatus);
-			*change = le16_to_cpu(portsts->wPortChange); 
-			dbg("port %d, portstatus %x, change %x, %s", port + 1,
-				*status, *change, portspeed(*status));
-			ret = 0;
-		}
-		kfree(portsts);
-	}
-	return ret;
-}
-
-#define HUB_RESET_TRIES		5
-#define HUB_PROBE_TRIES		2
-#define HUB_SHORT_RESET_TIME	10
-#define HUB_LONG_RESET_TIME	200
-#define HUB_RESET_TIMEOUT	500
-
-/* return: -1 on error, 0 on success, 1 on disconnect.  */
-static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
-				struct usb_device *dev, unsigned int delay)
-{
-	int delay_time, ret;
-	u16 portstatus;
-	u16 portchange;
-
-	for (delay_time = 0;
-			delay_time < HUB_RESET_TIMEOUT;
-			delay_time += delay) {
-		/* wait to give the device a chance to reset */
-		wait_ms(delay);
-
-		/* read and decode port status */
-		ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
-		if (ret < 0) {
-			return -1;
-		}
-
-		/* Device went away? */
-		if (!(portstatus & USB_PORT_STAT_CONNECTION))
-			return 1;
-
-		/* bomb out completely if something weird happened */
-		if ((portchange & USB_PORT_STAT_C_CONNECTION))
-			return -1;
-
-		/* if we`ve finished resetting, then break out of the loop */
-		if (!(portstatus & USB_PORT_STAT_RESET) &&
-		    (portstatus & USB_PORT_STAT_ENABLE)) {
-			if (portstatus & USB_PORT_STAT_HIGH_SPEED)
-				dev->speed = USB_SPEED_HIGH;
-			else if (portstatus & USB_PORT_STAT_LOW_SPEED)
-				dev->speed = USB_SPEED_LOW;
-			else
-				dev->speed = USB_SPEED_FULL;
-			return 0;
-		}
-
-		/* switch to the long delay after two short delay failures */
-		if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
-			delay = HUB_LONG_RESET_TIME;
-
-		dbg("port %d of hub %s not reset yet, waiting %dms", port + 1,
-			hub->devpath, delay);
-	}
-
-	return -1;
-}
-
-/* return: -1 on error, 0 on success, 1 on disconnect.  */
-static int usb_hub_port_reset(struct usb_device *hub, int port,
-				struct usb_device *dev, unsigned int delay)
-{
-	int i, status;
-
-	/* Reset the port */
-	for (i = 0; i < HUB_RESET_TRIES; i++) {
-		usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
-
-		/* return on disconnect or reset */
-		status = usb_hub_port_wait_reset(hub, port, dev, delay);
-		if (status != -1) {
-			usb_clear_port_feature(hub,
-				port + 1, USB_PORT_FEAT_C_RESET);
-			return status;
-		}
-
-		dbg("port %d of hub %s not enabled, trying reset again...",
-			port + 1, hub->devpath);
-		delay = HUB_LONG_RESET_TIME;
-	}
-
-	err("Cannot enable port %i of hub %s, disabling port.",
-		port + 1, hub->devpath);
-	err("Maybe the USB cable is bad?");
-
-	return -1;
-}
-
-void usb_hub_port_disable(struct usb_device *hub, int port)
-{
-	int ret;
-
-	ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
-	if (ret)
-		err("cannot disable port %d of hub %s (err = %d)",
-			port + 1, hub->devpath, ret);
-}
-
-/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
- *
- * Between connect detection and reset signaling there must be a delay
- * of 100ms at least for debounce and power-settling. The corresponding
- * timer shall restart whenever the downstream port detects a disconnect.
- * 
- * Apparently there are some bluetooth and irda-dongles and a number
- * of low-speed devices which require longer delays of about 200-400ms.
- * Not covered by the spec - but easy to deal with.
- *
- * This implementation uses 400ms minimum debounce timeout and checks
- * every 10ms for transient disconnects to restart the delay.
- */
-
-#define HUB_DEBOUNCE_TIMEOUT	400
-#define HUB_DEBOUNCE_STEP	10
-
-/* return: -1 on error, 0 on success, 1 on disconnect.  */
-static int usb_hub_port_debounce(struct usb_device *hub, int port)
-{
-	int ret;
-	unsigned delay_time;
-	u16 portchange, portstatus;
-
-	for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; /* empty */ ) {
-
-		/* wait debounce step increment */
-		wait_ms(HUB_DEBOUNCE_STEP);
-
-		ret = usb_hub_port_status(hub, port, &portstatus, &portchange);
-		if (ret < 0)
-			return -1;
-
-		if ((portchange & USB_PORT_STAT_C_CONNECTION)) {
-			usb_clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION);
-			delay_time = 0;
-		}
-		else
-			delay_time += HUB_DEBOUNCE_STEP;
-	}
-	return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1;
-}
-
-static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
-					u16 portstatus, u16 portchange)
-{
-	struct usb_device *hub = hubstate->dev;
-	struct usb_device *dev;
-	unsigned int delay = HUB_SHORT_RESET_TIME;
-	int i;
-
-	dbg("hub %s port %d, portstatus %x, change %x, %s",
-		hub->devpath, port + 1,
-		portstatus, portchange, portspeed (portstatus));
-
-	/* Clear the connection change status */
-	usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
-
-	/* Disconnect any existing devices under this port */
-	if (hub->children[port])
-		usb_disconnect(&hub->children[port]);
-
-	/* Return now if nothing is connected */
-	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
-		if (portstatus & USB_PORT_STAT_ENABLE)
-			usb_hub_port_disable(hub, port);
-
-		return;
-	}
-
-	if (usb_hub_port_debounce(hub, port)) {
-		err("connect-debounce failed, port %d disabled", port+1);
-		usb_hub_port_disable(hub, port);
-		return;
-	}
-
-	/* Some low speed devices have problems with the quick delay, so */
-	/*  be a bit pessimistic with those devices. RHbug #23670 */
-	if (portstatus & USB_PORT_STAT_LOW_SPEED)
-		delay = HUB_LONG_RESET_TIME;
-
-	down(&usb_address0_sem);
-
-	for (i = 0; i < HUB_PROBE_TRIES; i++) {
-		struct usb_device *pdev;
-		int	len;
-
-		/* Allocate a new device struct */
-		dev = usb_alloc_dev(hub, hub->bus);
-		if (!dev) {
-			err("couldn't allocate usb_device");
-			break;
-		}
-
-		hub->children[port] = dev;
-
-		/* Reset the device, and detect its speed */
-		if (usb_hub_port_reset(hub, port, dev, delay)) {
-			usb_free_dev(dev);
-			break;
-		}
-
-		/* Find a new address for it */
-		usb_connect(dev);
-
-		/* Set up TT records, if needed  */
-		if (hub->tt) {
-			dev->tt = hub->tt;
-			dev->ttport = hub->ttport;
-		} else if (dev->speed != USB_SPEED_HIGH
-				&& hub->speed == USB_SPEED_HIGH) {
-			dev->tt = &hubstate->tt;
-			dev->ttport = port + 1;
-		}
-
-		/* Save readable and stable topology id, distinguishing
-		 * devices by location for diagnostics, tools, etc.  The
-		 * string is a path along hub ports, from the root.  Each
-		 * device's id will be stable until USB is re-cabled, and
-		 * hubs are often labled with these port numbers.
-		 *
-		 * Initial size: "/NN" times five hubs + NUL = 16 bytes max
-		 * (quite rare, since most hubs have 4-6 ports).
-		 */
-		pdev = dev->parent;
-		if (pdev->devpath [1] != '\0')	/* parent not root */
-			len = snprintf (dev->devpath, sizeof dev->devpath,
-				"%s/%d", pdev->devpath, port + 1);
-		else	/* root == "/", root port 2 == "/2" */
-			len = snprintf (dev->devpath, sizeof dev->devpath,
-				"/%d", port + 1);
-		if (len == sizeof dev->devpath)
-			warn ("devpath size! usb/%03d/%03d path %s",
-				dev->bus->busnum, dev->devnum, dev->devpath);
-		info("new USB device on bus %d path %s, assigned address %d",
-			dev->bus->busnum, dev->devpath, dev->devnum);
-
-		/* put the device in the global device tree */
-		dev->dev.parent = &dev->parent->dev;
-		sprintf (&dev->dev.name[0], "USB device %04x:%04x",
-			 dev->descriptor.idVendor,
-			 dev->descriptor.idProduct);
-		/* find the number of the port this device is connected to */
-		sprintf (&dev->dev.bus_id[0], "unknown_port_%03d", dev->devnum);
-		for (i = 0; i < USB_MAXCHILDREN; ++i) {
-			if (dev->parent->children[i] == dev) {
-				sprintf (&dev->dev.bus_id[0], "%02d", i);
-				break;
-			}
-		}
-
-		/* Run it through the hoops (find a driver, etc) */
-		if (!usb_new_device(dev))
-			goto done;
-
-		/* Free the configuration if there was an error */
-		usb_free_dev(dev);
-
-		/* Switch to a long reset time */
-		delay = HUB_LONG_RESET_TIME;
-	}
-
-	hub->children[port] = NULL;
-	usb_hub_port_disable(hub, port);
-done:
-	up(&usb_address0_sem);
-}
-
-static void usb_hub_events(void)
-{
-	unsigned long flags;
-	struct list_head *tmp;
-	struct usb_device *dev;
-	struct usb_hub *hub;
-	struct usb_hub_status hubsts;
-	u16 hubstatus;
-	u16 hubchange;
-	u16 portstatus;
-	u16 portchange;
-	int i, ret;
-
-	/*
-	 *  We restart the list everytime to avoid a deadlock with
-	 * deleting hubs downstream from this one. This should be
-	 * safe since we delete the hub from the event list.
-	 * Not the most efficient, but avoids deadlocks.
-	 */
-	while (1) {
-		spin_lock_irqsave(&hub_event_lock, flags);
-
-		if (list_empty(&hub_event_list))
-			break;
-
-		/* Grab the next entry from the beginning of the list */
-		tmp = hub_event_list.next;
-
-		hub = list_entry(tmp, struct usb_hub, event_list);
-		dev = hub->dev;
-
-		list_del(tmp);
-		INIT_LIST_HEAD(tmp);
-
-		down(&hub->khubd_sem); /* never blocks, we were on list */
-		spin_unlock_irqrestore(&hub_event_lock, flags);
-
-		if (hub->error) {
-			dbg("resetting hub %s for error %d",
-				dev->devpath, hub->error);
-
-			if (usb_hub_reset(hub)) {
-				err("error resetting hub %s - disconnecting",
-					dev->devpath);
-				up(&hub->khubd_sem);
-				usb_hub_disconnect(dev);
-				continue;
-			}
-
-			hub->nerrors = 0;
-			hub->error = 0;
-		}
-
-		for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
-			ret = usb_hub_port_status(dev, i, &portstatus, &portchange);
-			if (ret < 0) {
-				continue;
-			}
-
-			if (portchange & USB_PORT_STAT_C_CONNECTION) {
-				dbg("hub %s port %d connection change",
-					dev->devpath, i + 1);
-				usb_hub_port_connect_change(hub, i, portstatus, portchange);
-			} else if (portchange & USB_PORT_STAT_C_ENABLE) {
-				dbg("hub %s port %d enable change, status %x",
-					dev->devpath, i + 1, portstatus);
-				usb_clear_port_feature(dev,
-					i + 1, USB_PORT_FEAT_C_ENABLE);
-
-				/*
-				 * EM interference sometimes causes badly
-				 * shielded USB devices to be shutdown by
-				 * the hub, this hack enables them again.
-				 * Works at least with mouse driver. 
-				 */
-				if (!(portstatus & USB_PORT_STAT_ENABLE)
-				    && (portstatus & USB_PORT_STAT_CONNECTION)
-				    && (dev->children[i])) {
-					err("already running hub %s port %i "
-					    "disabled by hub (EMI?), "
-					    "re-enabling...",
-						dev->devpath, i + 1);
-					usb_hub_port_connect_change(hub,
-						i, portstatus, portchange);
-				}
-			}
-
-			if (portchange & USB_PORT_STAT_C_SUSPEND) {
-				dbg("hub %s port %d suspend change",
-					dev->devpath, i + 1);
-				usb_clear_port_feature(dev,
-					i + 1,  USB_PORT_FEAT_C_SUSPEND);
-			}
-			
-			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
-				err("hub %s port %d over-current change",
-					dev->devpath, i + 1);
-				usb_clear_port_feature(dev,
-					i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
-				usb_hub_power_on(hub);
-			}
-
-			if (portchange & USB_PORT_STAT_C_RESET) {
-				dbg("hub %s port %d reset change",
-					dev->devpath, i + 1);
-				usb_clear_port_feature(dev,
-					i + 1, USB_PORT_FEAT_C_RESET);
-			}
-		} /* end for i */
-
-		/* deal with hub status changes */
-		if (usb_get_hub_status(dev, &hubsts) < 0)
-			err("get_hub_status %s failed", dev->devpath);
-		else {
-			hubstatus = le16_to_cpup(&hubsts.wHubStatus);
-			hubchange = le16_to_cpup(&hubsts.wHubChange);
-			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
-				dbg("hub %s power change", dev->devpath);
-				usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
-			}
-			if (hubchange & HUB_CHANGE_OVERCURRENT) {
-				dbg("hub %s overcurrent change", dev->devpath);
-				wait_ms(500);	/* Cool down */
-				usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
-                        	usb_hub_power_on(hub);
-			}
-		}
-		up(&hub->khubd_sem);
-        } /* end while (1) */
-
-	spin_unlock_irqrestore(&hub_event_lock, flags);
-}
-
-static int usb_hub_thread(void *__hub)
-{
-	lock_kernel();
-
-	/*
-	 * This thread doesn't need any user-level access,
-	 * so get rid of all our resources
-	 */
-
-	daemonize();
-
-	/* Setup a nice name */
-	strcpy(current->comm, "khubd");
-
-	/* Send me a signal to get me die (for debugging) */
-	do {
-		usb_hub_events();
-		interruptible_sleep_on(&khubd_wait);
-	} while (!signal_pending(current));
-
-	dbg("usb_hub_thread exiting");
-
-	unlock_kernel();
-	complete_and_exit(&khubd_exited, 0);
-}
-
-static struct usb_device_id hub_id_table [] = {
-    { match_flags: USB_DEVICE_ID_MATCH_DEV_CLASS,
-      bDeviceClass: USB_CLASS_HUB},
-    { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
-      bInterfaceClass: USB_CLASS_HUB},
-    { }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hub_id_table);
-
-static struct usb_driver hub_driver = {
-	name:		"hub",
-	probe:		hub_probe,
-	ioctl:		hub_ioctl,
-	disconnect:	hub_disconnect,
-	id_table:	hub_id_table,
-};
-
-/*
- * This should be a separate module.
- */
-int usb_hub_init(void)
-{
-	int pid;
-
-	if (usb_register(&hub_driver) < 0) {
-		err("Unable to register USB hub driver");
-		return -1;
-	}
-
-	pid = kernel_thread(usb_hub_thread, NULL,
-		CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-	if (pid >= 0) {
-		khubd_pid = pid;
-
-		return 0;
-	}
-
-	/* Fall through if kernel_thread failed */
-	usb_deregister(&hub_driver);
-	err("failed to start usb_hub_thread");
-
-	return -1;
-}
-
-void usb_hub_cleanup(void)
-{
-	int ret;
-
-	/* Kill the thread */
-	ret = kill_proc(khubd_pid, SIGTERM, 1);
-
-	wait_for_completion(&khubd_exited);
-
-	/*
-	 * Hub resources are freed for us by usb_deregister. It calls
-	 * usb_driver_purge on every device which in turn calls that
-	 * devices disconnect function if it is using this driver.
-	 * The hub_disconnect function takes care of releasing the
-	 * individual hub resources. -greg
-	 */
-	usb_deregister(&hub_driver);
-} /* usb_hub_cleanup() */
-
-/*
- * WARNING - If a driver calls usb_reset_device, you should simulate a
- * disconnect() and probe() for other interfaces you doesn't claim. This
- * is left up to the driver writer right now. This insures other drivers
- * have a chance to re-setup their interface.
- *
- * Take a look at proc_resetdevice in devio.c for some sample code to
- * do this.
- */
-int usb_reset_device(struct usb_device *dev)
-{
-	struct usb_device *parent = dev->parent;
-	struct usb_device_descriptor descriptor;
-	int i, ret, port = -1;
-
-	if (!parent) {
-		err("attempting to reset root hub!");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < parent->maxchild; i++)
-		if (parent->children[i] == dev) {
-			port = i;
-			break;
-		}
-
-	if (port < 0)
-		return -ENOENT;
-
-	down(&usb_address0_sem);
-
-	/* Send a reset to the device */
-	if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) {
-		usb_hub_port_disable(parent, port);
-		up(&usb_address0_sem);
-		return(-ENODEV);
-	}
-
-	/* Reprogram the Address */
-	ret = usb_set_address(dev);
-	if (ret < 0) {
-		err("USB device not accepting new address (error=%d)", ret);
-		usb_hub_port_disable(parent, port);
-		up(&usb_address0_sem);
-		return ret;
-	}
-
-	/* Let the SET_ADDRESS settle */
-	wait_ms(10);
-
-	up(&usb_address0_sem);
-
-	/*
-	 * Now we fetch the configuration descriptors for the device and
-	 * see if anything has changed. If it has, we dump the current
-	 * parsed descriptors and reparse from scratch. Then we leave
-	 * the device alone for the caller to finish setting up.
-	 *
-	 * If nothing changed, we reprogram the configuration and then
-	 * the alternate settings.
-	 */
-	ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
-			sizeof(descriptor));
-	if (ret < 0)
-		return ret;
-
-	le16_to_cpus(&descriptor.bcdUSB);
-	le16_to_cpus(&descriptor.idVendor);
-	le16_to_cpus(&descriptor.idProduct);
-	le16_to_cpus(&descriptor.bcdDevice);
-
-	if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) {
-		usb_destroy_configuration(dev);
-
-		ret = usb_get_device_descriptor(dev);
-		if (ret < sizeof(dev->descriptor)) {
-			if (ret < 0)
-				err("unable to get device %s descriptor "
-					"(error=%d)", dev->devpath, ret);
-			else
-				err("USB device %s descriptor short read "
-					"(expected %Zi, got %i)",
-					dev->devpath,
-					sizeof(dev->descriptor), ret);
-        
-			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-			dev->devnum = -1;
-			return -EIO;
-		}
-
-		ret = usb_get_configuration(dev);
-		if (ret < 0) {
-			err("unable to get configuration (error=%d)", ret);
-			usb_destroy_configuration(dev);
-			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-			dev->devnum = -1;
-			return 1;
-		}
-
-		dev->actconfig = dev->config;
-		usb_set_maxpacket(dev);
-
-		return 1;
-	}
-
-	ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
-	if (ret < 0) {
-		err("failed to set dev %s active configuration (error=%d)",
-			dev->devpath, ret);
-		return ret;
-	}
-
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-		struct usb_interface *intf = &dev->actconfig->interface[i];
-		struct usb_interface_descriptor *as;
-
-		as = &intf->altsetting[intf->act_altsetting];
-		ret = usb_set_interface(dev, as->bInterfaceNumber,
-			as->bAlternateSetting);
-		if (ret < 0) {
-			err("failed to set active alternate setting "
-				"for dev %s interface %d (error=%d)",
-				dev->devpath, i, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
diff -Nru a/drivers/usb/hub.h b/drivers/usb/hub.h
--- a/drivers/usb/hub.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,156 +0,0 @@
-#ifndef __LINUX_HUB_H
-#define __LINUX_HUB_H
-
-/*
- * Hub protocol and driver data structures.
- *
- * Some of these are known to the "virtual root hub" code
- * in host controller drivers.
- */
-
-#include <linux/list.h>
-
-/*
- * Hub request types
- */
-
-#define USB_RT_HUB	(USB_TYPE_CLASS | USB_RECIP_DEVICE)
-#define USB_RT_PORT	(USB_TYPE_CLASS | USB_RECIP_OTHER)
-
-/*
- * Hub class requests
- * See USB 2.0 spec Table 11-16
- */
-#define HUB_CLEAR_TT_BUFFER	8
-#define HUB_RESET_TT		9
-#define HUB_GET_TT_STATE	10
-#define HUB_STOP_TT		11
-
-/*
- * Hub Class feature numbers
- * See USB 2.0 spec Table 11-17
- */
-#define C_HUB_LOCAL_POWER	0
-#define C_HUB_OVER_CURRENT	1
-
-/*
- * Port feature numbers
- * See USB 2.0 spec Table 11-17
- */
-#define USB_PORT_FEAT_CONNECTION	0
-#define USB_PORT_FEAT_ENABLE		1
-#define USB_PORT_FEAT_SUSPEND		2
-#define USB_PORT_FEAT_OVER_CURRENT	3
-#define USB_PORT_FEAT_RESET		4
-#define USB_PORT_FEAT_POWER		8
-#define USB_PORT_FEAT_LOWSPEED		9
-#define USB_PORT_FEAT_HIGHSPEED		10
-#define USB_PORT_FEAT_C_CONNECTION	16
-#define USB_PORT_FEAT_C_ENABLE		17
-#define USB_PORT_FEAT_C_SUSPEND		18
-#define USB_PORT_FEAT_C_OVER_CURRENT	19
-#define USB_PORT_FEAT_C_RESET		20
-#define USB_PORT_FEAT_TEST              21
-#define USB_PORT_FEAT_INDICATOR         22
-
-/* 
- * Hub Status and Hub Change results
- * See USB 2.0 spec Table 11-19 and Table 11-20
- */
-struct usb_port_status {
-	__u16 wPortStatus;
-	__u16 wPortChange;	
-} __attribute__ ((packed));
-
-/* 
- * wPortStatus bit field
- * See USB 2.0 spec Table 11-21
- */
-#define USB_PORT_STAT_CONNECTION	0x0001
-#define USB_PORT_STAT_ENABLE		0x0002
-#define USB_PORT_STAT_SUSPEND		0x0004
-#define USB_PORT_STAT_OVERCURRENT	0x0008
-#define USB_PORT_STAT_RESET		0x0010
-/* bits 5 to 7 are reserved */
-#define USB_PORT_STAT_POWER		0x0100
-#define USB_PORT_STAT_LOW_SPEED		0x0200
-#define USB_PORT_STAT_HIGH_SPEED        0x0400
-#define USB_PORT_STAT_TEST              0x0800
-#define USB_PORT_STAT_INDICATOR         0x1000
-/* bits 13 to 15 are reserved */
-
-/* 
- * wPortChange bit field
- * See USB 2.0 spec Table 11-22
- * Bits 0 to 4 shown, bits 5 to 15 are reserved
- */
-#define USB_PORT_STAT_C_CONNECTION	0x0001
-#define USB_PORT_STAT_C_ENABLE		0x0002
-#define USB_PORT_STAT_C_SUSPEND		0x0004
-#define USB_PORT_STAT_C_OVERCURRENT	0x0008
-#define USB_PORT_STAT_C_RESET		0x0010
-
-/*
- * wHubCharacteristics (masks) 
- * See USB 2.0 spec Table 11-13, offset 3
- */
-#define HUB_CHAR_LPSM		0x0003 /* D1 .. D0 */
-#define HUB_CHAR_COMPOUND	0x0004 /* D2       */
-#define HUB_CHAR_OCPM		0x0018 /* D4 .. D3 */
-#define HUB_CHAR_TTTT           0x0060 /* D6 .. D5 */
-#define HUB_CHAR_PORTIND        0x0080 /* D7       */
-
-struct usb_hub_status {
-	__u16 wHubStatus;
-	__u16 wHubChange;
-} __attribute__ ((packed));
-
-/*
- * Hub Status & Hub Change bit masks
- * See USB 2.0 spec Table 11-19 and Table 11-20
- * Bits 0 and 1 for wHubStatus and wHubChange
- * Bits 2 to 15 are reserved for both
- */
-#define HUB_STATUS_LOCAL_POWER	0x0001
-#define HUB_STATUS_OVERCURRENT	0x0002
-#define HUB_CHANGE_LOCAL_POWER	0x0001
-#define HUB_CHANGE_OVERCURRENT	0x0002
-
-
-/* 
- * Hub descriptor 
- * See USB 2.0 spec Table 11-13
- */
-struct usb_hub_descriptor {
-	__u8  bDescLength;
-	__u8  bDescriptorType;
-	__u8  bNbrPorts;
-	__u16 wHubCharacteristics;
-	__u8  bPwrOn2PwrGood;
-	__u8  bHubContrCurrent;
-	    	/* add 1 bit for hub status change; round to bytes */
-	__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
-	__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
-} __attribute__ ((packed));
-
-struct usb_device;
-
-struct usb_hub {
-	struct usb_device	*dev;		/* the "real" device */
-	struct urb		*urb;		/* for interrupt polling pipe */
-
-	/* buffer for urb ... 1 bit each for hub and children, rounded up */
-	char			buffer[(USB_MAXCHILDREN + 1 + 7) / 8];
-
-	int			error;		/* last reported error */
-	int			nerrors;	/* track consecutive errors */
-
-	struct list_head	hub_list;	/* all hubs */
-	struct list_head	event_list;	/* hubs w/data or errs ready */
-
-	struct usb_hub_descriptor *descriptor;	/* class descriptor */
-	struct semaphore	khubd_sem;
-	struct usb_tt		tt;		/* Transaction Translator */
-};
-
-#endif /* __LINUX_HUB_H */
diff -Nru a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c
--- a/drivers/usb/ibmcam.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,3949 +0,0 @@
-/*
- * USB IBM C-It Video Camera driver
- *
- * Supports Xirlink C-It Video Camera, IBM PC Camera,
- * IBM NetCamera and Veo Stingray.
- *
- * This driver is based on earlier work of:
- *
- * (C) Copyright 1999 Johannes Erdfelt
- * (C) Copyright 1999 Randy Dunlap
- *
- * 5/24/00 Removed optional (and unnecessary) locking of the driver while
- * the device remains plugged in. Corrected race conditions in ibmcam_open
- * and ibmcam_probe() routines using this as a guideline:
- *
- * (2) The big kernel lock is automatically released when a process sleeps
- *   in the kernel and is automatically reacquired on reschedule if the
- *   process had the lock originally.  Any code that can be compiled as
- *   a module and is entered with the big kernel lock held *MUST*
- *   increment the use count to activate the indirect module protection
- *   before doing anything that might sleep.
- *
- *   In practice, this means that all routines that live in modules and
- *   are invoked under the big kernel lock should do MOD_INC_USE_COUNT
- *   as their very first action.  And all failure paths from that
- *   routine must do MOD_DEC_USE_COUNT before returning.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/wrapper.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "usbvideo.h"
-
-#define IBMCAM_VENDOR_ID	0x0545
-#define IBMCAM_PRODUCT_ID	0x8080
-#define NETCAM_PRODUCT_ID	0x8002	/* IBM NetCamera, close to model 2 */
-#define VEO_800C_PRODUCT_ID	0x800C	/* Veo Stingray, repackaged Model 2 */
-#define VEO_800D_PRODUCT_ID	0x800D	/* Veo Stingray, repackaged Model 4 */
-
-#define MAX_IBMCAM		4	/* How many devices we allow to connect */
-#define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */
-
-/* Header signatures */
-
-/* Model 1 header: 00 FF 00 xx */
-#define HDRSIG_MODEL1_128x96	0x06	/* U Y V Y ... */
-#define HDRSIG_MODEL1_176x144	0x0e	/* U Y V Y ... */
-#define HDRSIG_MODEL1_352x288	0x00	/* V Y U Y ... */
-
-#define	IBMCAM_MODEL_1	1	/* XVP-501, 3 interfaces, rev. 0.02 */
-#define IBMCAM_MODEL_2	2	/* KSX-X9903, 2 interfaces, rev. 3.0a */
-#define IBMCAM_MODEL_3	3	/* KSX-X9902, 2 interfaces, rev. 3.01 */
-#define	IBMCAM_MODEL_4	4	/* IBM NetCamera, 0545/8002/3.0a */
-
-/* Video sizes supported */
-#define	VIDEOSIZE_128x96	VIDEOSIZE(128, 96)
-#define	VIDEOSIZE_176x144	VIDEOSIZE(176,144)
-#define	VIDEOSIZE_352x288	VIDEOSIZE(352,288)
-#define	VIDEOSIZE_320x240	VIDEOSIZE(320,240)
-#define	VIDEOSIZE_352x240	VIDEOSIZE(352,240)
-#define	VIDEOSIZE_640x480	VIDEOSIZE(640,480)
-#define	VIDEOSIZE_160x120	VIDEOSIZE(160,120)
-
-/* Video sizes supported */
-enum {
-	SIZE_128x96 = 0,
-	SIZE_160x120,
-	SIZE_176x144,
-	SIZE_320x240,
-	SIZE_352x240,
-	SIZE_352x288,
-	SIZE_640x480,
-	/* Add/remove/rearrange items before this line */
-	SIZE_LastItem
-};
-
-/*
- * This structure lives in uvd_t->user field.
- */
-typedef struct {
-	int initialized;	/* Had we already sent init sequence? */
-	int camera_model;	/* What type of IBM camera we got? */
-	int has_hdr;
-} ibmcam_t;
-#define	IBMCAM_T(uvd)	((ibmcam_t *)((uvd)->user_data))
-
-usbvideo_t *cams = NULL;
-
-static int debug = 0;
-
-static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
-
-static const int min_canvasWidth  = 8;
-static const int min_canvasHeight = 4;
-
-static int lighting = 1; /* Medium */
-
-#define SHARPNESS_MIN	0
-#define SHARPNESS_MAX	6
-static int sharpness = 4; /* Low noise, good details */
-
-#define FRAMERATE_MIN	0
-#define FRAMERATE_MAX	6
-static int framerate = -1;
-
-static int size = SIZE_352x288;
-
-/*
- * Here we define several initialization variables. They may
- * be used to automatically set color, hue, brightness and
- * contrast to desired values. This is particularly useful in
- * case of webcams (which have no controls and no on-screen
- * output) and also when a client V4L software is used that
- * does not have some of those controls. In any case it's
- * good to have startup values as options.
- *
- * These values are all in [0..255] range. This simplifies
- * operation. Note that actual values of V4L variables may
- * be scaled up (as much as << 8). User can see that only
- * on overlay output, however, or through a V4L client.
- */
-static int init_brightness = 128;
-static int init_contrast = 192;
-static int init_color = 128;
-static int init_hue = 128;
-static int hue_correction = 128;
-
-/* Settings for camera model 2 */
-static int init_model2_rg2 = -1;
-static int init_model2_sat = -1;
-static int init_model2_yb = -1;
-
-/* 01.01.08 - Added for RCA video in support -LO */
-/* Settings for camera model 3 */
-static int init_model3_input = 0;
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
-MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
-MODULE_PARM(framerate, "i");
-MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-MODULE_PARM(lighting, "i");
-MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
-MODULE_PARM(sharpness, "i");
-MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
-MODULE_PARM(size, "i");
-MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480  (default=5)");
-MODULE_PARM(init_brightness, "i");
-MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
-MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
-MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
-MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
-MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
-
-MODULE_PARM(init_model2_rg2, "i");
-MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
-MODULE_PARM(init_model2_sat, "i");
-MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
-MODULE_PARM(init_model2_yb, "i");
-MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
-
-/* 01.01.08 - Added for RCA video in support -LO */
-MODULE_PARM(init_model3_input, "i");
-MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
-
-MODULE_AUTHOR ("Dmitri");
-MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
-MODULE_LICENSE("GPL");
-
-/* Still mysterious i2c commands */
-static const unsigned short unknown_88 = 0x0088;
-static const unsigned short unknown_89 = 0x0089;
-static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 };
-static const unsigned short contrast_14 = 0x0014;
-static const unsigned short light_27 = 0x0027;
-static const unsigned short sharp_13 = 0x0013;
-
-/* i2c commands for Model 2 cameras */
-static const unsigned short mod2_brightness = 0x001a;		/* $5b .. $ee; default=$5a */
-static const unsigned short mod2_set_framerate = 0x001c;	/* 0 (fast).. $1F (slow) */
-static const unsigned short mod2_color_balance_rg2 = 0x001e;	/* 0 (red) .. $7F (green) */
-static const unsigned short mod2_saturation = 0x0020;		/* 0 (b/w) - $7F (full color) */
-static const unsigned short mod2_color_balance_yb = 0x0022;	/* 0..$7F, $50 is about right */
-static const unsigned short mod2_hue = 0x0024;			/* 0..$7F, $70 is about right */
-static const unsigned short mod2_sensitivity = 0x0028;		/* 0 (min) .. $1F (max) */
-
-struct struct_initData {
-	unsigned char req;
-	unsigned short value;
-	unsigned short index;
-};
-
-/*
- * ibmcam_size_to_videosize()
- *
- * This procedure converts module option 'size' into the actual
- * videosize_t that defines the image size in pixels. We need
- * simplified 'size' because user wants a simple enumerated list
- * of choices, not an infinite set of possibilities.
- */
-static videosize_t ibmcam_size_to_videosize(int size)
-{
-	videosize_t vs = VIDEOSIZE_352x288;
-	RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1));
-	switch (size) {
-	case SIZE_128x96:
-		vs = VIDEOSIZE_128x96;
-		break;
-	case SIZE_160x120:
-		vs = VIDEOSIZE_160x120;
-		break;
-	case SIZE_176x144:
-		vs = VIDEOSIZE_176x144;
-		break;
-	case SIZE_320x240:
-		vs = VIDEOSIZE_320x240;
-		break;
-	case SIZE_352x240:
-		vs = VIDEOSIZE_352x240;
-		break;
-	case SIZE_352x288:
-		vs = VIDEOSIZE_352x288;
-		break;
-	case SIZE_640x480:
-		vs = VIDEOSIZE_640x480;
-		break;
-	default:
-		err("size=%d. is not valid", size);
-		break;
-	}
-	return vs;
-}
-
-/*
- * ibmcam_find_header()
- *
- * Locate one of supported header markers in the queue.
- * Once found, remove all preceding bytes AND the marker (4 bytes)
- * from the data pump queue. Whatever follows must be video lines.
- *
- * History:
- * 1/21/00  Created.
- */
-static ParseState_t ibmcam_find_header(uvd_t *uvd) /* FIXME: Add frame here */
-{
-	usbvideo_frame_t *frame;
-	ibmcam_t *icam;
-
-	if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-		err("ibmcam_find_header: Illegal frame %d.", uvd->curframe);
-		return scan_EndParse;
-	}
-	icam = IBMCAM_T(uvd);
-	assert(icam != NULL);
-	frame = &uvd->frame[uvd->curframe];
-	icam->has_hdr = 0;
-	switch (icam->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		const int marker_len = 4;
-		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
-			{
-#if 0				/* This code helps to detect new frame markers */
-				info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3));
-#endif
-				frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
-				if ((frame->header == HDRSIG_MODEL1_128x96) ||
-				    (frame->header == HDRSIG_MODEL1_176x144) ||
-				    (frame->header == HDRSIG_MODEL1_352x288))
-				{
-#if 0
-					info("Header found.");
-#endif
-					RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
-					icam->has_hdr = 1;
-					break;
-				}
-			}
-			/* If we are still here then this doesn't look like a header */
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_2:
-case IBMCAM_MODEL_4:
-	{
-		int marker_len = 0;
-		switch (uvd->videosize) {
-		case VIDEOSIZE_176x144:
-			marker_len = 10;
-			break;
-		default:
-			marker_len = 2;
-			break;
-		}
-		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
-			{
-#if 0
-				info("Header found.");
-#endif
-				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
-				icam->has_hdr = 1;
-				frame->header = HDRSIG_MODEL1_176x144;
-				break;
-			}
-			/* If we are still here then this doesn't look like a header */
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_3:
-	{	/*
-		 * Headers: (one precedes every frame). nc=no compression,
-		 * bq=best quality bf=best frame rate.
-		 *
-		 * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf }
-		 * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf }
-		 * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf }
-		 *
-		 * Bytes '00 FF' seem to indicate header. Other two bytes
-		 * encode the frame type. This is a set of bit fields that
-		 * encode image size, compression type etc. These fields
-		 * do NOT contain frame number because all frames carry
-		 * the same header.
-		 */
-		const int marker_len = 4;
-		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF))
-			{
-				/*
-				 * Combine 2 bytes of frame type into one
-				 * easy to use value
-				 */
-				unsigned long byte3, byte4;
-
-				byte3 = RING_QUEUE_PEEK(&uvd->dp, 2);
-				byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
-				frame->header = (byte3 << 8) | byte4;
-#if 0
-				info("Header found.");
-#endif
-				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
-				icam->has_hdr = 1;
-				break;
-			}
-			/* If we are still here then this doesn't look like a header */
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-		}
-		break;
-	}
-	default:
-		break;
-	}
-	if (!icam->has_hdr) {
-		if (uvd->debug > 2)
-			info("Skipping frame, no header");
-		return scan_EndParse;
-	}
-
-	/* Header found */
-	icam->has_hdr = 1;
-	uvd->stats.header_count++;
-	frame->scanstate = ScanState_Lines;
-	frame->curline = 0;
-
-	if (flags & FLAGS_FORCE_TESTPATTERN) {
-		usbvideo_TestPattern(uvd, 1, 1);
-		return scan_NextFrame;
-	}
-	return scan_Continue;
-}
-
-/*
- * ibmcam_parse_lines()
- *
- * Parse one line (interlaced) from the buffer, put
- * decoded RGB value into the current frame buffer
- * and add the written number of bytes (RGB) to
- * the *pcopylen.
- *
- * History:
- * 21-Jan-2000 Created.
- * 12-Oct-2000 Reworked to reflect interlaced nature of the data.
- */
-static ParseState_t ibmcam_parse_lines(
-	uvd_t *uvd,
-	usbvideo_frame_t *frame,
-	long *pcopylen)
-{
-	unsigned char *f;
-	ibmcam_t *icam;
-	unsigned int len, scanLength, scanHeight, order_uv, order_yc;
-	int v4l_linesize; /* V4L line offset */
-	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
-	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
-	const int ccm = 128; /* Color correction median - see below */
-	int y, u, v, i, frame_done=0, color_corr;
-	static unsigned char lineBuffer[640*3];
-	unsigned const char *chromaLine, *lumaLine;
-
-	assert(uvd != NULL);
-	assert(frame != NULL);
-	icam = IBMCAM_T(uvd);
-	assert(icam != NULL);
-	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
-
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) {
-		/* Model 4 frame markers do not carry image size identification */
-		switch (uvd->videosize) {
-		case VIDEOSIZE_128x96:
-		case VIDEOSIZE_160x120:
-		case VIDEOSIZE_176x144:
-			scanLength = VIDEOSIZE_X(uvd->videosize);
-			scanHeight = VIDEOSIZE_Y(uvd->videosize);
-			break;
-		default:
-			err("ibmcam_parse_lines: Wrong mode.");
-			return scan_Out;
-		}
-		order_yc = 1;	/* order_yc: true=Yc false=cY ('c'=either U or V) */
-		order_uv = 1;	/* Always true in this algorithm */
-	} else {
-		switch (frame->header) {
-		case HDRSIG_MODEL1_128x96:
-			scanLength = 128;
-			scanHeight = 96;
-			order_uv = 1;	/* U Y V Y ... */
-			break;
-		case HDRSIG_MODEL1_176x144:
-			scanLength = 176;
-			scanHeight = 144;
-			order_uv = 1;	/* U Y V Y ... */
-			break;
-		case HDRSIG_MODEL1_352x288:
-			scanLength = 352;
-			scanHeight = 288;
-			order_uv = 0;	/* Y V Y V ... */
-			break;
-		default:
-			err("Unknown header signature 00 FF 00 %02lX", frame->header);
-			return scan_NextFrame;
-		}
-		/* order_yc: true=Yc false=cY ('c'=either U or V) */
-		order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2);
-	}
-
-	len = scanLength * 3;
-	assert(len <= sizeof(lineBuffer));
-
-	/*
-	 * Lines are organized this way:
-	 *
-	 * I420:
-	 * ~~~~
-	 * <scanLength->
-	 * ___________________________________
-	 * |-----Y-----|---UVUVUV...UVUV-----| \
-	 * |-----------+---------------------|  \
-	 * |<-- 176 -->|<------ 176*2 ------>|  Total 72. lines (interlaced)
-	 * |...	   ... |        ...          |  /
-	 * |<-- 352 -->|<------ 352*2 ------>|  Total 144. lines (interlaced)
-	 * |___________|_____________________| /
-	 *  \           \
-	 *   lumaLine    chromaLine
-	 */
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Mind that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
-		return scan_NextFrame;
-
-	/*
-	 * Now we are sure that entire line (representing all 'scanLength'
-	 * pixels from the camera) is available in the buffer. We
-	 * start copying the line left-aligned to the V4L buffer.
-	 * If the camera line is shorter then we should pad the V4L
-	 * buffer with something (black) to complete the line.
-	 */
-	assert(frame->data != NULL);
-	f = frame->data + (v4l_linesize * frame->curline);
-
-	/*
-	 * To obtain chrominance data from the 'chromaLine' use this:
-	 *   v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]...
-	 *   u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]...
-	 *
-	 * Indices must be calculated this way:
-	 * v_index = (i >> 1) << 2;
-	 * u_index = (i >> 1) << 2 + 2;
-	 *
-	 * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1]
-	 */
-	lumaLine = lineBuffer;
-	chromaLine = lineBuffer + scanLength;
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++)
-	{
-		unsigned char rv, gv, bv;	/* RGB components */
-
-		/* Check for various visual debugging hints (colorized pixels) */
-		if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) {
-			/*
-			 * This is bad and should not happen. This means that
-			 * we somehow overshoot the line and encountered new
-			 * frame! Obviously our camera/V4L frame size is out
-			 * of whack. This cyan dot will help you to figure
-			 * out where exactly the new frame arrived.
-			 */
-			if (icam->has_hdr == 1) {
-				bv = 0; /* Yellow marker */
-				gv = 0xFF;
-				rv = 0xFF;
-			} else {
-				bv = 0xFF; /* Cyan marker */
-				gv = 0xFF;
-				rv = 0;
-			}
-			icam->has_hdr = 0;
-			goto make_pixel;
-		}
-
-		/*
-		 * Check if we are still in range. We may be out of range if our
-		 * V4L canvas is wider or taller than the camera "native" image.
-		 * Then we quickly fill the remainder of the line with zeros to
-		 * make black color and quit the horizontal scanning loop.
-		 */
-		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
-			const int j = i * V4L_BYTES_PER_PIXEL;
-#if USES_IBMCAM_PUTPIXEL
-			/* Refresh 'f' because we don't use it much with PUTPIXEL */
-			f = frame->data + (v4l_linesize * frame->curline) + j;
-#endif
-			memset(f, 0, v4l_linesize - j);
-			break;
-		}
-
-		y = lumaLine[i];
-		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
-			rv = gv = bv = y;
-		else {
-			int off_0, off_2;
-
-			off_0 = (i >> 1) << 2;
-			off_2 = off_0 + 2;
-
-			if (order_yc) {
-				off_0++;
-				off_2++;
-			}
-			if (!order_uv) {
-				off_0 += 2;
-				off_2 -= 2;
-			}
-			u = chromaLine[off_0] + hue_corr;
-			v = chromaLine[off_2] + hue2_corr;
-
-			/* Apply color correction */
-			if (color_corr != 0) {
-				/* Magnify up to 2 times, reduce down to zero saturation */
-				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
-				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
-			}
-			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
-		}
-
-	make_pixel:
-		/*
-		 * The purpose of creating the pixel here, in one,
-		 * dedicated place is that we may need to make the
-		 * pixel wider and taller than it actually is. This
-		 * may be used if camera generates small frames for
-		 * sake of frame rate (or any other reason.)
-		 *
-		 * The output data consists of B, G, R bytes
-		 * (in this order).
-		 */
-#if USES_IBMCAM_PUTPIXEL
-		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
-#else
-		*f++ = bv;
-		*f++ = gv;
-		*f++ = rv;
-#endif
-		/*
-		 * Typically we do not decide within a legitimate frame
-		 * that we want to end the frame. However debugging code
-		 * may detect marker of new frame within the data. Then
-		 * this condition activates. The 'data' pointer is already
-		 * pointing at the new marker, so we'd better leave it as is.
-		 */
-		if (frame_done)
-			break;	/* End scanning of lines */
-	}
-	/*
-	 * Account for number of bytes that we wrote into output V4L frame.
-	 * We do it here, after we are done with the scanline, because we
-	 * may fill more than one output scanline if we do vertical
-	 * enlargement.
-	 */
-	frame->curline += 2;
-	if (pcopylen != NULL)
-		*pcopylen += 2 * v4l_linesize;
-	frame->deinterlace = Deinterlace_FillOddLines;
-
-	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
-		return scan_NextFrame;
-	else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_model2_320x240_parse_lines()
- *
- * This procedure deals with a weird RGB format that is produced by IBM
- * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
- * depending on horizontal size of the picture:
- *
- * <--- 160 or 176 pairs of RA,RB bytes ----->
- * *-----------------------------------------* \
- * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \   This is pair of horizontal lines,
- * |-----+-----+-----+-----+ ... +-----+-----|   *- or one interlaced line, total
- * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   120 or 144 such pairs which yield
- * |=====+=====+=====+=====+ ... +=====+=====| /    240 or 288 lines after deinterlacing.
- *
- * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
- * defines ONE pixel. Therefore this format yields 176x144 "decoded"
- * resolution at best. I do not know why camera sends such format - the
- * previous model (1) just used interlaced I420 and everyone was happy.
- *
- * I do not know what is the difference between RAi and RBi bytes. Both
- * seemingly represent R component, but slightly vary in value (so that
- * the picture looks a bit colored if one or another is used). I use
- * them both as R component in attempt to at least partially recover the
- * lost resolution.
- */
-static ParseState_t ibmcam_model2_320x240_parse_lines(
-	uvd_t *uvd,
-	usbvideo_frame_t *frame,
-	long *pcopylen)
-{
-	unsigned char *f, *la, *lb;
-	unsigned int len;
-	int v4l_linesize; /* V4L line offset */
-	int i, j, frame_done=0, color_corr;
-	int scanLength, scanHeight;
-	static unsigned char lineBuffer[352*2];
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_320x240:
-	case VIDEOSIZE_352x240:
-	case VIDEOSIZE_352x288:
-		scanLength = VIDEOSIZE_X(uvd->videosize);
-		scanHeight = VIDEOSIZE_Y(uvd->videosize);
-		break;
-	default:
-		err("ibmcam_model2_320x240_parse_lines: Wrong mode.");
-		return scan_Out;
-	}
-
-	color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	len = scanLength * 2; /* See explanation above */
-	assert(len <= sizeof(lineBuffer));
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Mind that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
-		return scan_NextFrame;
-
-	la = lineBuffer;
-	lb = lineBuffer + scanLength;
-
-	/*
-	 * Now we are sure that entire line (representing all
-	 *         VIDEOSIZE_X(frame->request)
-	 * pixels from the camera) is available in the scratch buffer. We
-	 * start copying the line left-aligned to the V4L buffer (which
-	 * might be larger - not smaller, hopefully). If the camera
-	 * line is shorter then we should pad the V4L buffer with something
-	 * (black in this case) to complete the line.
-	 */
-	f = frame->data + (v4l_linesize * frame->curline);
-
-	/* Fill the 2-line strip */
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-		int y, rv, gv, bv;	/* RGB components */
-
-		j = i & (~1);
-
-		/* Check for various visual debugging hints (colorized pixels) */
-		if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) {
-			if (IBMCAM_T(uvd)->has_hdr == 1) {
-				bv = 0; /* Yellow marker */
-				gv = 0xFF;
-				rv = 0xFF;
-			} else {
-				bv = 0xFF; /* Cyan marker */
-				gv = 0xFF;
-				rv = 0;
-			}
-			IBMCAM_T(uvd)->has_hdr = 0;
-			goto make_pixel;
-		}
-
-		/*
-		 * Check if we are still in range. We may be out of range if our
-		 * V4L canvas is wider or taller than the camera "native" image.
-		 * Then we quickly fill the remainder of the line with zeros to
-		 * make black color and quit the horizontal scanning loop.
-		 */
-		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
-			const int j = i * V4L_BYTES_PER_PIXEL;
-#if USES_IBMCAM_PUTPIXEL
-			/* Refresh 'f' because we don't use it much with PUTPIXEL */
-			f = frame->data + (v4l_linesize * frame->curline) + j;
-#endif
-			memset(f, 0, v4l_linesize - j);
-			break;
-		}
-
-		/*
-		 * Here I use RA and RB components, one per physical pixel.
-		 * This causes fine vertical grid on the picture but may improve
-		 * horizontal resolution. If you prefer replicating, use this:
-		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];
-		 * then the pixel will be replicated.
-		 */
-		rv = la[i];
-		gv = lb[j + 1];
-		bv = lb[j + 0];
-
-		y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */
-
-		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
-			rv = gv = bv = y;
-		else if (color_corr != 128) {
-
-			/* Calculate difference between color and brightness */
-			rv -= y;
-			gv -= y;
-			bv -= y;
-
-			/* Scale differences */
-			rv = (rv * color_corr) / 128;
-			gv = (gv * color_corr) / 128;
-			bv = (bv * color_corr) / 128;
-
-			/* Reapply brightness */
-			rv += y;
-			gv += y;
-			bv += y;
-
-			/* Watch for overflows */
-			RESTRICT_TO_RANGE(rv, 0, 255);
-			RESTRICT_TO_RANGE(gv, 0, 255);
-			RESTRICT_TO_RANGE(bv, 0, 255);
-		}
-
-	make_pixel:
-		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
-	}
-	/*
-	 * Account for number of bytes that we wrote into output V4L frame.
-	 * We do it here, after we are done with the scanline, because we
-	 * may fill more than one output scanline if we do vertical
-	 * enlargement.
-	 */
-	frame->curline += 2;
-	*pcopylen += v4l_linesize * 2;
-	frame->deinterlace = Deinterlace_FillOddLines;
-
-	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
-		return scan_NextFrame;
-	else
-		return scan_Continue;
-}
-
-static ParseState_t ibmcam_model3_parse_lines(
-	uvd_t *uvd,
-	usbvideo_frame_t *frame,
-	long *pcopylen)
-{
-	unsigned char *data;
-	const unsigned char *color;
-	unsigned int len;
-	int v4l_linesize; /* V4L line offset */
-	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
-	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
-	const int ccm = 128; /* Color correction median - see below */
-	int i, u, v, rw, data_w=0, data_h=0, color_corr;
-	static unsigned char lineBuffer[640*3];
-
-	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
-
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	/* The header tells us what sort of data is in this frame */
-	switch (frame->header) {
-		/*
-		 * Uncompressed modes (that are easy to decode).
-		 */
-	case 0x0308:
-		data_w = 640;
-		data_h = 480;
-		break;
-	case 0x0208:
-		data_w = 320;
-		data_h = 240;
-		break;
-	case 0x020A:
-		data_w = 160;
-		data_h = 120;
-		break;
-		/*
-		 * Compressed modes (ViCE - that I don't know how to decode).
-		 */
-	case 0x0328:	/* 640x480, best quality compression */
-	case 0x0368:	/* 640x480, best frame rate compression */
-	case 0x0228:	/* 320x240, best quality compression */
-	case 0x0268:	/* 320x240, best frame rate compression */
-	case 0x02CA:	/* 160x120, best quality compression */
-	case 0x02EA:	/* 160x120, best frame rate compression */
-		/* Do nothing with this - not supported */
-		err("Unsupported mode $%04lx", frame->header);
-		return scan_NextFrame;
-	default:
-		/* Catch unknown headers, may help in learning new headers */
-		err("Strange frame->header=$%08lx", frame->header);
-		return scan_NextFrame;
-	}
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Note that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 1) >= data_h) {
-		if (uvd->debug >= 3)
-			info("Reached line %d. (frame is done)", frame->curline);
-		return scan_NextFrame;
-	}
-
-	/* Make sure there's enough data for the entire line */
-	len = 3 * data_w; /* <y-data> <uv-data> */
-	assert(len <= sizeof(lineBuffer));
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	data = lineBuffer;
-	color = data + data_w;		/* Point to where color planes begin */
-
-	/* Bottom-to-top scanning */
-	rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
-	RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
-
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-		int y, rv, gv, bv;	/* RGB components */
-
-		if (i < data_w) {
-			y = data[i];	/* Luminosity is the first line */
-
-			/* Apply static color correction */
-			u = color[i*2] + hue_corr;
-			v = color[i*2 + 1] + hue2_corr;
-
-			/* Apply color correction */
-			if (color_corr != 0) {
-				/* Magnify up to 2 times, reduce down to zero saturation */
-				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
-				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
-			}
-		} else
-			y = 0, u = v = 128;
-
-		YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
-		RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
-	}
-	frame->deinterlace = Deinterlace_FillEvenLines;
-
-	/*
-	 * Account for number of bytes that we wrote into output V4L frame.
-	 * We do it here, after we are done with the scanline, because we
-	 * may fill more than one output scanline if we do vertical
-	 * enlargement.
-	 */
-	frame->curline += 2;
-	*pcopylen += 2 * v4l_linesize;
-
-	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
-		if (uvd->debug >= 3) {
-			info("All requested lines (%ld.) done.",
-			     VIDEOSIZE_Y(frame->request));
-		}
-		return scan_NextFrame;
-	} else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_model4_128x96_parse_lines()
- *
- * This decoder is for one strange data format that is produced by Model 4
- * camera only in 128x96 mode. This is RGB format and here is its description.
- * First of all, this is non-interlaced stream, meaning that all scan lines
- * are present in the datastream. There are 96 consecutive blocks of data
- * that describe all 96 lines of the image. Each block is 5*128 bytes long
- * and carries R, G, B components. The format of the block is shown in the
- * code below. First 128*2 bytes are interleaved R and G components. Then
- * we have a gap (junk data) 64 bytes long. Then follow B and something
- * else, also interleaved (this makes another 128*2 bytes). After that
- * probably another 64 bytes of junk follow.
- *
- * History:
- * 10-Feb-2001 Created.
- */
-static ParseState_t ibmcam_model4_128x96_parse_lines(
-	uvd_t *uvd,
-	usbvideo_frame_t *frame,
-	long *pcopylen)
-{
-	const unsigned char *data_rv, *data_gv, *data_bv;
-	unsigned int len;
-	int i, v4l_linesize; /* V4L line offset */
-	const int data_w=128, data_h=96;
-	static unsigned char lineBuffer[128*5];
-
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-
-	/*
-	 * Make sure that our writing into output buffer
-	 * will not exceed the buffer. Note that we may write
-	 * not into current output scanline but in several after
-	 * it as well (if we enlarge image vertically.)
-	 */
-	if ((frame->curline + 1) >= data_h) {
-		if (uvd->debug >= 3)
-			info("Reached line %d. (frame is done)", frame->curline);
-		return scan_NextFrame;
-	}
-
-	/*
-	 * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________
-	 * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 --->
-	 */
-
-	/* Make sure there's enough data for the entire line */
-	len = 5 * data_w;
-	assert(len <= sizeof(lineBuffer));
-
-	/* Make sure there's enough data for the entire line */
-	if (RingQueue_GetLength(&uvd->dp) < len)
-		return scan_Out;
-
-	/* Suck one line out of the ring queue */
-	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
-
-	data_rv = lineBuffer;
-	data_gv = lineBuffer + 1;
-	data_bv = lineBuffer + data_w*2 + data_w/2;
-	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
-		int rv, gv, bv;	/* RGB components */
-		if (i < data_w) {
-			const int j = i * 2;
-			gv = data_rv[j];
-			rv = data_gv[j];
-			bv = data_bv[j];
-			if (flags & FLAGS_MONOCHROME) {
-				unsigned long y;
-				y = rv + gv + bv;
-				y /= 3;
-				if (y > 0xFF)
-					y = 0xFF;
-				rv = gv = bv = (unsigned char) y;
-			}
-		} else {
-			rv = gv = bv = 0;
-		}
-		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
-	}
-	frame->deinterlace = Deinterlace_None;
-	frame->curline++;
-	*pcopylen += v4l_linesize;
-
-	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
-		if (uvd->debug >= 3) {
-			info("All requested lines (%ld.) done.",
-			     VIDEOSIZE_Y(frame->request));
-		}
-		return scan_NextFrame;
-	} else
-		return scan_Continue;
-}
-
-/*
- * ibmcam_ProcessIsocData()
- *
- * Generic routine to parse the ring queue data. It employs either
- * ibmcam_find_header() or ibmcam_parse_lines() to do most
- * of work.
- *
- * History:
- * 1/21/00  Created.
- */
-void ibmcam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
-{
-	ParseState_t newstate;
-	long copylen = 0;
-	int mod = IBMCAM_T(uvd)->camera_model;
-
-	while (1) {
-		newstate = scan_Out;
-		if (RingQueue_GetLength(&uvd->dp) > 0) {
-			if (frame->scanstate == ScanState_Scanning) {
-				newstate = ibmcam_find_header(uvd);
-			} else if (frame->scanstate == ScanState_Lines) {
-				if ((mod == IBMCAM_MODEL_2) &&
-				    ((uvd->videosize == VIDEOSIZE_352x288) ||
-				     (uvd->videosize == VIDEOSIZE_320x240) ||
-				     (uvd->videosize == VIDEOSIZE_352x240)))
-				{
-					newstate = ibmcam_model2_320x240_parse_lines(
-						uvd, frame, &copylen);
-				} else if (mod == IBMCAM_MODEL_4) {
-					/*
-					 * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB)
-					 * for 320x240 and above; 160x120 and 176x144 uses Model 1
-					 * decoder (YUV), and 128x96 mode uses ???
-					 */
-					if ((uvd->videosize == VIDEOSIZE_352x288) ||
-					    (uvd->videosize == VIDEOSIZE_320x240) ||
-					    (uvd->videosize == VIDEOSIZE_352x240))
-					{
-						newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, &copylen);
-					} else if (uvd->videosize == VIDEOSIZE_128x96) {
-						newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, &copylen);
-					} else {
-						newstate = ibmcam_parse_lines(uvd, frame, &copylen);
-					}
-				} else if (mod == IBMCAM_MODEL_3) {
-					newstate = ibmcam_model3_parse_lines(uvd, frame, &copylen);
-				} else {
-					newstate = ibmcam_parse_lines(uvd, frame, &copylen);
-				}
-			}
-		}
-		if (newstate == scan_Continue)
-			continue;
-		else if ((newstate == scan_NextFrame) || (newstate == scan_Out))
-			break;
-		else
-			return; /* scan_EndParse */
-	}
-
-	if (newstate == scan_NextFrame) {
-		frame->frameState = FrameState_Done;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-		if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) {
-			/* Need software contrast adjustment for those cameras */
-			frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST;
-		}
-	}
-
-	/* Update the frame's uncompressed length. */
-	frame->seqRead_Length += copylen;
-
-#if 0
-	{
-		static unsigned char j=0;
-		memset(frame->data, j++, uvd->max_frame_size);
-		frame->frameState = FrameState_Ready;
-	}
-#endif
-}
-
-/*
- * ibmcam_veio()
- *
- * History:
- * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
- */
-static int ibmcam_veio(
-	uvd_t *uvd,
-	unsigned char req,
-	unsigned short value,
-	unsigned short index)
-{
-	static const char proc[] = "ibmcam_veio";
-	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
-	int i;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return 0;
-
-	if (req == 1) {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_rcvctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-			value,
-			index,
-			cp,
-			sizeof(cp),
-			HZ);
-#if 0
-		info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-		       "(req=$%02x val=$%04x ind=$%04x)",
-		       cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-		       req, value, index);
-#endif
-	} else {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_sndctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-			value,
-			index,
-			NULL,
-			0,
-			HZ);
-	}
-	if (i < 0) {
-		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
-		    proc, i);
-		uvd->last_error = i;
-	}
-	return i;
-}
-
-/*
- * ibmcam_calculate_fps()
- *
- * This procedure roughly calculates the real frame rate based
- * on FPS code (framerate=NNN option). Actual FPS differs
- * slightly depending on lighting conditions, so that actual frame
- * rate is determined by the camera. Since I don't know how to ask
- * the camera what FPS is now I have to use the FPS code instead.
- *
- * The FPS code is in range [0..6], 0 is slowest, 6 is fastest.
- * Corresponding real FPS should be in range [3..30] frames per second.
- * The conversion formula is obvious:
- *
- * real_fps = 3 + (fps_code * 4.5)
- *
- * History:
- * 1/18/00  Created.
- */
-static int ibmcam_calculate_fps(uvd_t *uvd)
-{
-	return 3 + framerate*4 + framerate/2;
-}
-
-/*
- * ibmcam_send_FF_04_02()
- *
- * This procedure sends magic 3-command prefix to the camera.
- * The purpose of this prefix is not known.
- *
- * History:
- * 1/2/00   Created.
- */
-static void ibmcam_send_FF_04_02(uvd_t *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x00FF, 0x0127);
-	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-}
-
-static void ibmcam_send_00_04_06(uvd_t *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0006, 0x0124);
-}
-
-static void ibmcam_send_x_00(uvd_t *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-}
-
-static void ibmcam_send_x_00_05(uvd_t *uvd, unsigned short x)
-{
-	ibmcam_send_x_00(uvd, x);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-}
-
-static void ibmcam_send_x_00_05_02(uvd_t *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-}
-
-static void ibmcam_send_x_01_00_05(uvd_t *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-}
-
-static void ibmcam_send_x_00_05_02_01(uvd_t *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
-}
-
-static void ibmcam_send_x_00_05_02_08_01(uvd_t *uvd, unsigned short x)
-{
-	ibmcam_veio(uvd, 0, x,      0x0127);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0008, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
-}
-
-static void ibmcam_Packet_Format1(uvd_t *uvd, unsigned char fkey, unsigned char val)
-{
-	ibmcam_send_x_01_00_05(uvd, unknown_88);
-	ibmcam_send_x_00_05(uvd, fkey);
-	ibmcam_send_x_00_05_02_08_01(uvd, val);
-	ibmcam_send_x_00_05(uvd, unknown_88);
-	ibmcam_send_x_00_05_02_01(uvd, fkey);
-	ibmcam_send_x_00_05(uvd, unknown_89);
-	ibmcam_send_x_00(uvd, fkey);
-	ibmcam_send_00_04_06(uvd);
-	ibmcam_veio(uvd, 1, 0x0000, 0x0126);
-	ibmcam_send_FF_04_02(uvd);
-}
-
-static void ibmcam_PacketFormat2(uvd_t *uvd, unsigned char fkey, unsigned char val)
-{
-	ibmcam_send_x_01_00_05	(uvd, unknown_88);
-	ibmcam_send_x_00_05	(uvd, fkey);
-	ibmcam_send_x_00_05_02	(uvd, val);
-}
-
-static void ibmcam_model2_Packet2(uvd_t *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x00ff, 0x012d);
-	ibmcam_veio(uvd, 0, 0xfea3, 0x0124);
-}
-
-static void ibmcam_model2_Packet1(uvd_t *uvd, unsigned short v1, unsigned short v2)
-{
-	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-	ibmcam_veio(uvd, 0, 0x00ff, 0x012e);
-	ibmcam_veio(uvd, 0, v1,     0x012f);
-	ibmcam_veio(uvd, 0, 0x00ff, 0x0130);
-	ibmcam_veio(uvd, 0, 0xc719, 0x0124);
-	ibmcam_veio(uvd, 0, v2,     0x0127);
-
-	ibmcam_model2_Packet2(uvd);
-}
-
-/*
- * ibmcam_model3_Packet1()
- *
- * 00_0078_012d	
- * 00_0097_012f
- * 00_d141_0124	
- * 00_0096_0127
- * 00_fea8_0124	
-*/
-static void ibmcam_model3_Packet1(uvd_t *uvd, unsigned short v1, unsigned short v2)
-{
-	ibmcam_veio(uvd, 0, 0x0078, 0x012d);
-	ibmcam_veio(uvd, 0, v1,     0x012f);
-	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-	ibmcam_veio(uvd, 0, v2,     0x0127);
-	ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-}
-
-static void ibmcam_model4_BrightnessPacket(uvd_t *uvd, int i)
-{
-	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-	ibmcam_veio(uvd, 0, 0x0026, 0x012f);
-	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-	ibmcam_veio(uvd, 0, i,      0x0127);
-	ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-	ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-	ibmcam_veio(uvd, 0, 0x0038, 0x012d);
-	ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-	ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-	ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-}
-
-/*
- * ibmcam_adjust_contrast()
- *
- * The contrast value changes from 0 (high contrast) to 15 (low contrast).
- * This is in reverse to usual order of things (such as TV controls), so
- * we reverse it again here.
- *
- * TODO: we probably don't need to send the setup 5 times...
- *
- * History:
- * 1/2/00   Created.
- */
-static void ibmcam_adjust_contrast(uvd_t *uvd)
-{
-	unsigned char a_contrast = uvd->vpic.contrast >> 12;
-	unsigned char new_contrast;
-
-	if (a_contrast >= 16)
-		a_contrast = 15;
-	new_contrast = 15 - a_contrast;
-	if (new_contrast == uvd->vpic_old.contrast)
-		return;
-	uvd->vpic_old.contrast = new_contrast;
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		const int ntries = 5;
-		int i;
-		for (i=0; i < ntries; i++) {
-			ibmcam_Packet_Format1(uvd, contrast_14, new_contrast);
-			ibmcam_send_FF_04_02(uvd);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_2:
-	case IBMCAM_MODEL_4:
-		/* Models 2, 4 do not have this control; implemented in software. */
-		break;
-	case IBMCAM_MODEL_3:
-	{	/* Preset hardware values */
-		static const struct {
-			unsigned short cv1;
-			unsigned short cv2;
-			unsigned short cv3;
-		} cv[7] = {
-			{ 0x05, 0x05, 0x0f },	/* Minimum */
-			{ 0x04, 0x04, 0x16 },
-			{ 0x02, 0x03, 0x16 },
-			{ 0x02, 0x08, 0x16 },
-			{ 0x01, 0x0c, 0x16 },
-			{ 0x01, 0x0e, 0x16 },
-			{ 0x01, 0x10, 0x16 }	/* Maximum */
-		};
-		int i = a_contrast / 2;
-		RESTRICT_TO_RANGE(i, 0, 6);
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1);
-		ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2);
-		ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_change_lighting_conditions()
- *
- * Camera model 1:
- * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
- *
- * Camera model 2:
- * We have 16 levels of lighting, 0 for bright light and up to 15 for
- * low light. But values above 5 or so are useless because camera is
- * not really capable to produce anything worth viewing at such light.
- * This setting may be altered only in certain camera state.
- *
- * Low lighting forces slower FPS. Lighting is set as a module parameter.
- *
- * History:
- * 1/5/00   Created.
- * 2/20/00  Added support for Model 2 cameras.
- */
-static void ibmcam_change_lighting_conditions(uvd_t *uvd)
-{
-	static const char proc[] = "ibmcam_change_lighting_conditions";
-
-	if (debug > 0)
-		info("%s: Set lighting to %hu.", proc, lighting);
-
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		const int ntries = 5;
-		int i;
-		for (i=0; i < ntries; i++)
-			ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting);
-		break;
-	}
-	case IBMCAM_MODEL_2:
-#if 0
-		/*
-		 * This command apparently requires camera to be stopped. My
-		 * experiments showed that it -is- possible to alter the lighting
-		 * conditions setting "on the fly", but why bother? This setting does
-		 * not work reliably in all cases, so I decided simply to leave the
-		 * setting where Xirlink put it - in the camera setup phase. This code
-		 * is commented out because it does not work at -any- moment, so its
-		 * presence makes no sense. You may use it for experiments.
-		 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop camera */
-		ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Start camera */
-#endif
-		break;
-	case IBMCAM_MODEL_3:
-	case IBMCAM_MODEL_4:
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_set_sharpness()
- *
- * Cameras model 1 have internal smoothing feature. It is controlled by value in
- * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
- * Recommended value is 4. Cameras model 2 do not have this feature at all.
- */
-static void ibmcam_set_sharpness(uvd_t *uvd)
-{
-	static const char proc[] = "ibmcam_set_sharpness";
-
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
-		unsigned short i, sv;
-
-		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
-		if (debug > 0)
-			info("%s: Set sharpness to %hu.", proc, sharpness);
-
-		sv = sa[sharpness - SHARPNESS_MIN];
-		for (i=0; i < 2; i++) {
-			ibmcam_send_x_01_00_05	(uvd, unknown_88);
-			ibmcam_send_x_00_05		(uvd, sharp_13);
-			ibmcam_send_x_00_05_02	(uvd, sv);
-		}
-		break;
-	}
-	case IBMCAM_MODEL_2:
-	case IBMCAM_MODEL_4:
-		/* Models 2, 4 do not have this control */
-		break;
-	case IBMCAM_MODEL_3:
-	{	/*
-		 * "Use a table of magic numbers.
-		 *  This setting doesn't really change much.
-		 *  But that's how Windows does it."
-		 */
-		static const struct {
-			unsigned short sv1;
-			unsigned short sv2;
-			unsigned short sv3;
-			unsigned short sv4;
-		} sv[7] = {
-			{ 0x00, 0x00, 0x05, 0x14 },	/* Smoothest */
-			{ 0x01, 0x04, 0x05, 0x14 },
-			{ 0x02, 0x04, 0x05, 0x14 },
-			{ 0x03, 0x04, 0x05, 0x14 },
-			{ 0x03, 0x05, 0x05, 0x14 },
-			{ 0x03, 0x06, 0x05, 0x14 },
-			{ 0x03, 0x07, 0x05, 0x14 }	/* Sharpest */
-		};
-		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
-		RESTRICT_TO_RANGE(sharpness, 0, 6);
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1);
-		ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2);
-		ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3);
-		ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_set_brightness()
- *
- * This procedure changes brightness of the picture.
- */
-static void ibmcam_set_brightness(uvd_t *uvd)
-{
-	static const char proc[] = "ibmcam_set_brightness";
-	static const unsigned short n = 1;
-
-	if (debug > 0)
-		info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness);
-
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-	{
-		unsigned short i, j, bv[3];
-		bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10;
-		if (bv[0] == (uvd->vpic_old.brightness >> 10))
-			return;
-		uvd->vpic_old.brightness = bv[0];
-		for (j=0; j < 3; j++)
-			for (i=0; i < n; i++)
-				ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]);
-		break;
-	}
-	case IBMCAM_MODEL_2:
-	{
-		unsigned short i, j;
-		i = uvd->vpic.brightness >> 12;	/* 0 .. 15 */
-		j = 0x60 + i * ((0xee - 0x60) / 16);	/* 0x60 .. 0xee or so */
-		if (uvd->vpic_old.brightness == j)
-			break;
-		uvd->vpic_old.brightness = j;
-		ibmcam_model2_Packet1(uvd, mod2_brightness, j);
-		break;
-	}
-	case IBMCAM_MODEL_3:
-	{
-		/* Model 3: Brightness range 'i' in [0x0C..0x3F] */
-		unsigned short i =
-			0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1)));
-		RESTRICT_TO_RANGE(i, 0x0C, 0x3F);
-		if (uvd->vpic_old.brightness == i)
-			break;
-		uvd->vpic_old.brightness = i;
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x0036, i);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
-		break;
-	}
-	case IBMCAM_MODEL_4:
-	{
-		/* Model 4: Brightness range 'i' in [0x04..0xb4] */
-		unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1)));
-		RESTRICT_TO_RANGE(i, 0x04, 0xb4);
-		if (uvd->vpic_old.brightness == i)
-			break;
-		uvd->vpic_old.brightness = i;
-		ibmcam_model4_BrightnessPacket(uvd, i);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-static void ibmcam_set_hue(uvd_t *uvd)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_2:
-	{
-		unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */
-		if (uvd->vpic_old.hue == hue)
-			return;
-		uvd->vpic_old.hue = hue;
-		ibmcam_model2_Packet1(uvd, mod2_hue, hue);
-		/* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */
-		break;
-	}
-	case IBMCAM_MODEL_3:
-	{
-#if 0 /* This seems not to work. No problem, will fix programmatically */
-		unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1)));
-		RESTRICT_TO_RANGE(hue, 0x05, 0x37);
-		if (uvd->vpic_old.hue == hue)
-			return;
-		uvd->vpic_old.hue = hue;
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
-		ibmcam_model3_Packet1(uvd, 0x007e, hue);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
-#endif
-		break;
-	}
-	case IBMCAM_MODEL_4:
-	{
-		unsigned short r_gain, g_gain, b_gain, hue;
-
-		/*
-		 * I am not sure r/g/b_gain variables exactly control gain
-		 * of those channels. Most likely they subtly change some
-		 * very internal image processing settings in the camera.
-		 * In any case, here is what they do, and feel free to tweak:
-		 *
-		 * r_gain: seriously affects red gain
-		 * g_gain: seriously affects green gain
-		 * b_gain: seriously affects blue gain
-		 * hue: changes average color from violet (0) to red (0xFF)
-		 *
-		 * These settings are preset for a decent white balance in
-		 * 320x240, 352x288 modes. Low-res modes exhibit higher contrast
-		 * and therefore may need different values here.
-		 */
-		hue = 20 + (uvd->vpic.hue >> 9);
-		switch (uvd->videosize) {
-		case VIDEOSIZE_128x96:
-			r_gain = 90;
-			g_gain = 166;
-			b_gain = 175;
-			break;
-		case VIDEOSIZE_160x120:
-			r_gain = 70;
-			g_gain = 166;
-			b_gain = 185;
-			break;
-		case VIDEOSIZE_176x144:
-			r_gain = 160;
-			g_gain = 175;
-			b_gain = 185;
-			break;
-		default:
-			r_gain = 120;
-			g_gain = 166;
-			b_gain = 175;
-			break;
-		}
-		RESTRICT_TO_RANGE(hue, 1, 0x7f);
-
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, g_gain, 0x0127);	/* Green gain */
-		ibmcam_veio(uvd, 0, r_gain, 0x012e);	/* Red gain */
-		ibmcam_veio(uvd, 0, b_gain, 0x0130);	/* Blue gain */
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, hue,    0x012d);	/* Hue */
-		ibmcam_veio(uvd, 0, 0xf545, 0x0124);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-/*
- * ibmcam_adjust_picture()
- *
- * This procedure gets called from V4L interface to update picture settings.
- * Here we change brightness and contrast.
- */
-static void ibmcam_adjust_picture(uvd_t *uvd)
-{
-	ibmcam_adjust_contrast(uvd);
-	ibmcam_set_brightness(uvd);
-	ibmcam_set_hue(uvd);
-}
-
-static int ibmcam_model1_setup(uvd_t *uvd)
-{
-	const int ntries = 5;
-	int i;
-
-	ibmcam_veio(uvd, 1, 0x00, 0x0128);
-	ibmcam_veio(uvd, 1, 0x00, 0x0100);
-	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
-	ibmcam_veio(uvd, 1, 0x00, 0x0100);
-	ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
-	ibmcam_veio(uvd, 1, 0x00, 0x0100);
-	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
-	ibmcam_veio(uvd, 0, 0x01, 0x0108);
-
-	ibmcam_veio(uvd, 0, 0x03, 0x0112);
-	ibmcam_veio(uvd, 1, 0x00, 0x0115);
-	ibmcam_veio(uvd, 0, 0x06, 0x0115);
-	ibmcam_veio(uvd, 1, 0x00, 0x0116);
-	ibmcam_veio(uvd, 0, 0x44, 0x0116);
-	ibmcam_veio(uvd, 1, 0x00, 0x0116);
-	ibmcam_veio(uvd, 0, 0x40, 0x0116);
-	ibmcam_veio(uvd, 1, 0x00, 0x0115);
-	ibmcam_veio(uvd, 0, 0x0e, 0x0115);
-	ibmcam_veio(uvd, 0, 0x19, 0x012c);
-
-	ibmcam_Packet_Format1(uvd, 0x00, 0x1e);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x0d);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x09);
-	ibmcam_Packet_Format1(uvd, 0x3b, 0x00);
-	ibmcam_Packet_Format1(uvd, 0x28, 0x22);
-	ibmcam_Packet_Format1(uvd, light_27, 0);
-	ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
-
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x2c, 0x00);
-
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x30, 0x14);
-
-	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
-	ibmcam_PacketFormat2(uvd, 0x01, 0xe1);
-	ibmcam_PacketFormat2(uvd, 0x02, 0xcd);
-	ibmcam_PacketFormat2(uvd, 0x03, 0xcd);
-	ibmcam_PacketFormat2(uvd, 0x04, 0xfa);
-	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
-	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
-
-	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
-	ibmcam_PacketFormat2(uvd, 0x0a, 0x37);
-	ibmcam_PacketFormat2(uvd, 0x0b, 0xb8);
-	ibmcam_PacketFormat2(uvd, 0x0c, 0xf3);
-	ibmcam_PacketFormat2(uvd, 0x0d, 0xe3);
-	ibmcam_PacketFormat2(uvd, 0x0e, 0x0d);
-	ibmcam_PacketFormat2(uvd, 0x0f, 0xf2);
-	ibmcam_PacketFormat2(uvd, 0x10, 0xd5);
-	ibmcam_PacketFormat2(uvd, 0x11, 0xba);
-	ibmcam_PacketFormat2(uvd, 0x12, 0x53);
-	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
-	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
-
-	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
-	ibmcam_PacketFormat2(uvd, 0x16, 0x00);
-	ibmcam_PacketFormat2(uvd, 0x17, 0x28);
-	ibmcam_PacketFormat2(uvd, 0x18, 0x7d);
-	ibmcam_PacketFormat2(uvd, 0x19, 0xbe);
-	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
-	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
-
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x00, 0x18);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x13, 0x18);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x14, 0x06);
-
-	/* This is default brightness */
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x31, 0x37);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x32, 0x46);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x33, 0x55);
-
-	ibmcam_Packet_Format1(uvd, 0x2e, 0x04);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x2d, 0x04);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x29, 0x80);
-	ibmcam_Packet_Format1(uvd, 0x2c, 0x01);
-	ibmcam_Packet_Format1(uvd, 0x30, 0x17);
-	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x34, 0x00);
-
-	ibmcam_veio(uvd, 0, 0x00, 0x0101);
-	ibmcam_veio(uvd, 0, 0x00, 0x010a);
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_128x96:
-		ibmcam_veio(uvd, 0, 0x80, 0x0103);
-		ibmcam_veio(uvd, 0, 0x60, 0x0105);
-		ibmcam_veio(uvd, 0, 0x0c, 0x010b);
-		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x0b, 0x011d);
-		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x00, 0x0129);
-		break;
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
-		ibmcam_veio(uvd, 0, 0x8f, 0x0105);
-		ibmcam_veio(uvd, 0, 0x06, 0x010b);
-		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x0d, 0x011d);
-		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x03, 0x0129);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
-		ibmcam_veio(uvd, 0, 0x90, 0x0105);
-		ibmcam_veio(uvd, 0, 0x02, 0x010b);
-		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x05, 0x011d);
-		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x00, 0x0129);
-		break;
-	}
-
-	ibmcam_veio(uvd, 0, 0xff, 0x012b);
-
-	/* This is another brightness - don't know why */
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x31, 0xc3);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x32, 0xd2);
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, 0x33, 0xe1);
-
-	/* Default contrast */
-	for (i=0; i < ntries; i++)
-		ibmcam_Packet_Format1(uvd, contrast_14, 0x0a);
-
-	/* Default sharpness */
-	for (i=0; i < 2; i++)
-		ibmcam_PacketFormat2(uvd, sharp_13, 0x1a);	/* Level 4 FIXME */
-
-	/* Default lighting conditions */
-	ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */
-
-	/* Assorted init */
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_128x96:
-		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
-		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x36, 0x0102);
-		ibmcam_veio(uvd, 0, 0x1a, 0x0104);
-		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
-		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
-#if 0
-		ibmcam_veio(uvd, 0, 0x00, 0x0106);
-		ibmcam_veio(uvd, 0, 0x38, 0x0107);
-#else
-		ibmcam_veio(uvd, 0, 0x02, 0x0106);
-		ibmcam_veio(uvd, 0, 0x2a, 0x0107);
-#endif
-		break;
-	case VIDEOSIZE_176x144:
-		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
-		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x04, 0x0102);
-		ibmcam_veio(uvd, 0, 0x02, 0x0104);
-		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
-		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x01, 0x0106);
-		ibmcam_veio(uvd, 0, 0xca, 0x0107);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
-		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x08, 0x0102);
-		ibmcam_veio(uvd, 0, 0x01, 0x0104);
-		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x2f, 0x011c);
-		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
-		ibmcam_veio(uvd, 0, 0x03, 0x0106);
-		ibmcam_veio(uvd, 0, 0xf6, 0x0107);
-		break;
-	}
-	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
-}
-
-static int ibmcam_model2_setup(uvd_t *uvd)
-{
-	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
-	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
-	ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-	ibmcam_veio(uvd, 0, 0x0008, 0x012b);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
-		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);	/* Unique to this mode */
-		ibmcam_veio(uvd, 0, 0x0038, 0x0119);	/* Unique to this mode */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0090, 0x0107);	/* Unique to every mode*/
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);	/* Unique to this mode */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0098, 0x0107);	/* Unique to every mode*/
-		break;
-	case VIDEOSIZE_352x240:
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x00da, 0x0107);	/* Unique to every mode*/
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
-		ibmcam_veio(uvd, 0, 0x00fe, 0x0107);	/* Unique to every mode*/
-		break;
-	}
-	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
-}
-
-/*
- * ibmcam_model1_setup_after_video_if()
- *
- * This code adds finishing touches to the video data interface.
- * Here we configure the frame rate and turn on the LED.
- */
-static void ibmcam_model1_setup_after_video_if(uvd_t *uvd)
-{
-	unsigned short internal_frame_rate;
-
-	RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
-	internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */
-	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
-	ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111);
-	ibmcam_veio(uvd, 0, 0x01, 0x0114);
-	ibmcam_veio(uvd, 0, 0xc0, 0x010c);
-}
-
-static void ibmcam_model2_setup_after_video_if(uvd_t *uvd)
-{
-	unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb;
-
-	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0x0050, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		break;
-	case VIDEOSIZE_320x240:
-	case VIDEOSIZE_352x240:
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0x0040, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		break;
-	}
-	ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-	ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-
-	/*
-	 * Hardware settings, may affect CMOS sensor; not user controls!
-	 * -------------------------------------------------------------
-	 * 0x0004: no effect
-	 * 0x0006: hardware effect
-	 * 0x0008: no effect
-	 * 0x000a: stops video stream, probably important h/w setting
-	 * 0x000c: changes color in hardware manner (not user setting)
-	 * 0x0012: changes number of colors (does not affect speed)
-	 * 0x002a: no effect
-	 * 0x002c: hardware setting (related to scan lines)
-	 * 0x002e: stops video stream, probably important h/w setting
-	 */
-	ibmcam_model2_Packet1(uvd, 0x000a, 0x005c);
-	ibmcam_model2_Packet1(uvd, 0x0004, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb);
-	ibmcam_model2_Packet1(uvd, 0x0008, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x000c, 0x0009);
-	ibmcam_model2_Packet1(uvd, 0x0012, 0x000a);
-	ibmcam_model2_Packet1(uvd, 0x002a, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x002c, 0x0000);
-	ibmcam_model2_Packet1(uvd, 0x002e, 0x0008);
-
-	/*
-	 * Function 0x0030 pops up all over the place. Apparently
-	 * it is a hardware control register, with every bit assigned to
-	 * do something.
-	 */
-	ibmcam_model2_Packet1(uvd, 0x0030, 0x0000);
-
-	/*
-	 * Magic control of CMOS sensor. Only lower values like
-	 * 0-3 work, and picture shifts left or right. Don't change.
-	 */
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0002);
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009);
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */
-		break;
-	case VIDEOSIZE_352x240:
-		/* This mode doesn't work as Windows programs it; changed to work */
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_model2_Packet1(uvd, 0x0014, 0x0003);
-		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
-		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
-		break;
-	}
-
-	ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a);
-
-	/*
-	 * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest).
-	 * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the
-	 * slowest setting. However for all practical reasons high settings make no
-	 * sense because USB is not fast enough to support high FPS. Be aware that
-	 * the picture datastream will be severely disrupted if you ask for
-	 * frame rate faster than allowed for the video size - see below:
-	 *
-	 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
-	 * -----------------------------------------------------------------
-	 * 176x144: [6..31]
-	 * 320x240: [8..31]
-	 * 352x240: [10..31]
-	 * 352x288: [16..31] I have to raise lower threshold for stability...
-	 *
-	 * As usual, slower FPS provides better sensitivity.
-	 */
-	{
-		short hw_fps=31, i_framerate;
-
-		RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
-		i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN;
-		switch (uvd->videosize) {
-		case VIDEOSIZE_176x144:
-			hw_fps = 6 + i_framerate*4;
-			break;
-		case VIDEOSIZE_320x240:
-			hw_fps = 8 + i_framerate*3;
-			break;
-		case VIDEOSIZE_352x240:
-			hw_fps = 10 + i_framerate*2;
-			break;
-		case VIDEOSIZE_352x288:
-			hw_fps = 28 + i_framerate/2;
-			break;
-		}
-		if (uvd->debug > 0)
-			info("Framerate (hardware): %hd.", hw_fps);
-		RESTRICT_TO_RANGE(hw_fps, 0, 31);
-		ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
-	}
-
-	/*
-	 * This setting does not visibly affect pictures; left it here
-	 * because it was present in Windows USB data stream. This function
-	 * does not allow arbitrary values and apparently is a bit mask, to
-	 * be activated only at appropriate time. Don't change it randomly!
-	 */
-	switch (uvd->videosize) {
-	case VIDEOSIZE_176x144:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x0044);
-		break;
-	case VIDEOSIZE_352x240:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x0046);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_model2_Packet1(uvd, 0x0026, 0x0048);
-		break;
-	}
-
-	ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
-
-	if (init_model2_rg2 >= 0) {
-		RESTRICT_TO_RANGE(init_model2_rg2, 0, 255);
-		setup_model2_rg2 = init_model2_rg2;
-	} else
-		setup_model2_rg2 = 0x002f;
-
-	if (init_model2_sat >= 0) {
-		RESTRICT_TO_RANGE(init_model2_sat, 0, 255);
-		setup_model2_sat = init_model2_sat;
-	} else
-		setup_model2_sat = 0x0034;
-
-	if (init_model2_yb >= 0) {
-		RESTRICT_TO_RANGE(init_model2_yb, 0, 255);
-		setup_model2_yb = init_model2_yb;
-	} else
-		setup_model2_yb = 0x00a0;
-
-	ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2);
-	ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat);
-	ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb);
-	ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */;
-
-	/* Hardware control command */
-	ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
-
-	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go camera, go! */
-	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-}
-
-static void ibmcam_model4_setup_after_video_if(uvd_t *uvd)
-{
-	switch (uvd->videosize) {
-	case VIDEOSIZE_128x96:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_160x120:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d8, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000b, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0025, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0048, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0035, 0x012e);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0048, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0090, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_176x144:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d6, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x0018, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0007, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0001, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x002a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
-		ibmcam_veio(uvd, 0, 0x006d, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break;
-	case VIDEOSIZE_352x288:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
-		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
-		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
-		ibmcam_veio(uvd, 0, 0x00f2, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x008c, 0x0107);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
-		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0006, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0002, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
-		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
-		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
-		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00cf, 0x012e);
-		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
-		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
-		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
-		ibmcam_veio(uvd, 0, 0x0025, 0x0130);
-		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0048, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
-		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
-		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
-		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		break; 
-	}
-	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-}
-
-static void ibmcam_model3_setup_after_video_if(uvd_t *uvd)
-{
-	int i;
-	/*
-	 * 01.01.08 - Added for RCA video in support -LO
-	 * This struct is used to init the Model3 cam to use the RCA video in port
-	 * instead of the CCD sensor.
-	 */
-	static const struct struct_initData initData[] = {
-		{0, 0x0000, 0x010c},
-		{0, 0x0006, 0x012c},
-		{0, 0x0078, 0x012d},
-		{0, 0x0046, 0x012f},
-		{0, 0xd141, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfea8, 0x0124},
-		{1, 0x0000, 0x0116},
-		{0, 0x0064, 0x0116},
-		{1, 0x0000, 0x0115},
-		{0, 0x0003, 0x0115},
-		{0, 0x0008, 0x0123},
-		{0, 0x0000, 0x0117},
-		{0, 0x0000, 0x0112},
-		{0, 0x0080, 0x0100},
-		{0, 0x0000, 0x0100},
-		{1, 0x0000, 0x0116},
-		{0, 0x0060, 0x0116},
-		{0, 0x0002, 0x0112},
-		{0, 0x0000, 0x0123},
-		{0, 0x0001, 0x0117},
-		{0, 0x0040, 0x0108},
-		{0, 0x0019, 0x012c},
-		{0, 0x0040, 0x0116},
-		{0, 0x000a, 0x0115},
-		{0, 0x000b, 0x0115},
-		{0, 0x0078, 0x012d},
-		{0, 0x0046, 0x012f},
-		{0, 0xd141, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfea8, 0x0124},
-		{0, 0x0064, 0x0116},
-		{0, 0x0000, 0x0115},
-		{0, 0x0001, 0x0115},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00aa, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f2, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x000f, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f8, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00fc, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f9, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x003c, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xffff, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0027, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0019, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0021, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0006, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0045, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002a, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x000e, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002b, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00f4, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002c, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0004, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002d, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0014, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002e, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0003, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x002f, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0003, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0014, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0053, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0x0000, 0x0101},
-		{0, 0x00a0, 0x0103},
-		{0, 0x0078, 0x0105},
-		{0, 0x0000, 0x010a},
-		{0, 0x0024, 0x010b},
-		{0, 0x0028, 0x0119},
-		{0, 0x0088, 0x011b},
-		{0, 0x0002, 0x011d},
-		{0, 0x0003, 0x011e},
-		{0, 0x0000, 0x0129},
-		{0, 0x00fc, 0x012b},
-		{0, 0x0008, 0x0102},
-		{0, 0x0000, 0x0104},
-		{0, 0x0008, 0x011a},
-		{0, 0x0028, 0x011c},
-		{0, 0x0021, 0x012a},
-		{0, 0x0000, 0x0118},
-		{0, 0x0000, 0x0132},
-		{0, 0x0000, 0x0109},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0031, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x00dc, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0032, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0020, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0001, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0040, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0037, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0030, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0xfff9, 0x0124},
-		{0, 0x0086, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0038, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0008, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0x0000, 0x0127},
-		{0, 0xfff8, 0x0124},
-		{0, 0xfffd, 0x0124},
-		{0, 0xfffa, 0x0124},
-		{0, 0x0003, 0x0106},
-		{0, 0x0062, 0x0107},
-		{0, 0x0003, 0x0111},
-	};
-#define NUM_INIT_DATA 
-
-	unsigned short compression = 0;	/* 0=none, 7=best frame rate  */
-	int f_rate; /* 0=Fastest 7=slowest */
-
-	if (IBMCAM_T(uvd)->initialized)
-		return;
-
-	/* Internal frame rate is controlled by f_rate value */
-	f_rate = 7 - framerate;
-	RESTRICT_TO_RANGE(f_rate, 0, 7);
-
-	ibmcam_veio(uvd, 0, 0x0000, 0x0100);
-	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
-	ibmcam_veio(uvd, 0, 0x0000, 0x0123);
-	ibmcam_veio(uvd, 0, 0x0001, 0x0117);
-	ibmcam_veio(uvd, 0, 0x0040, 0x0108);
-	ibmcam_veio(uvd, 0, 0x0019, 0x012c);
-	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
-	ibmcam_veio(uvd, 0, 0x0002, 0x0115);
-	ibmcam_veio(uvd, 0, 0x0003, 0x0115);
-	ibmcam_veio(uvd, 1, 0x0000, 0x0115);
-	ibmcam_veio(uvd, 0, 0x000b, 0x0115);
-	ibmcam_model3_Packet1(uvd, 0x000a, 0x0040);
-	ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6);
-	ibmcam_model3_Packet1(uvd, 0x000c, 0x0002);
-	ibmcam_model3_Packet1(uvd, 0x000d, 0x0020);
-	ibmcam_model3_Packet1(uvd, 0x000e, 0x0033);
-	ibmcam_model3_Packet1(uvd, 0x000f, 0x0007);
-	ibmcam_model3_Packet1(uvd, 0x0010, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0011, 0x0070);
-	ibmcam_model3_Packet1(uvd, 0x0012, 0x0030);
-	ibmcam_model3_Packet1(uvd, 0x0013, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0014, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0015, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0016, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0017, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x0018, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3);
-	ibmcam_model3_Packet1(uvd, 0x0020, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0028, 0x0010);
-	ibmcam_model3_Packet1(uvd, 0x0029, 0x0054);
-	ibmcam_model3_Packet1(uvd, 0x002a, 0x0013);
-	ibmcam_model3_Packet1(uvd, 0x002b, 0x0007);
-	ibmcam_model3_Packet1(uvd, 0x002d, 0x0028);
-	ibmcam_model3_Packet1(uvd, 0x002e, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0031, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0032, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0033, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0034, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0035, 0x0038);
-	ibmcam_model3_Packet1(uvd, 0x003a, 0x0001);
-	ibmcam_model3_Packet1(uvd, 0x003c, 0x001e);
-	ibmcam_model3_Packet1(uvd, 0x003f, 0x000a);
-	ibmcam_model3_Packet1(uvd, 0x0041, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0046, 0x003f);
-	ibmcam_model3_Packet1(uvd, 0x0047, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0050, 0x0005);
-	ibmcam_model3_Packet1(uvd, 0x0052, 0x001a);
-	ibmcam_model3_Packet1(uvd, 0x0053, 0x0003);
-	ibmcam_model3_Packet1(uvd, 0x005a, 0x006b);
-	ibmcam_model3_Packet1(uvd, 0x005d, 0x001e);
-	ibmcam_model3_Packet1(uvd, 0x005e, 0x0030);
-	ibmcam_model3_Packet1(uvd, 0x005f, 0x0041);
-	ibmcam_model3_Packet1(uvd, 0x0064, 0x0008);
-	ibmcam_model3_Packet1(uvd, 0x0065, 0x0015);
-	ibmcam_model3_Packet1(uvd, 0x0068, 0x000f);
-	ibmcam_model3_Packet1(uvd, 0x0079, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x007a, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x007c, 0x003f);
-	ibmcam_model3_Packet1(uvd, 0x0082, 0x000f);
-	ibmcam_model3_Packet1(uvd, 0x0085, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x0099, 0x0000);
-	ibmcam_model3_Packet1(uvd, 0x009b, 0x0023);
-	ibmcam_model3_Packet1(uvd, 0x009c, 0x0022);
-	ibmcam_model3_Packet1(uvd, 0x009d, 0x0096);
-	ibmcam_model3_Packet1(uvd, 0x009e, 0x0096);
-	ibmcam_model3_Packet1(uvd, 0x009f, 0x000a);
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_160x120:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */
-		ibmcam_veio(uvd, 0, 0x00a9, 0x0119);
-		ibmcam_veio(uvd, 0, 0x0016, 0x011b);
-		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
-		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
-		ibmcam_veio(uvd, 0, 0x0018, 0x0102);
-		ibmcam_veio(uvd, 0, 0x0004, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
-		ibmcam_veio(uvd, 0, 0x0028, 0x011c);
-		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0118);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
-		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
-		ibmcam_veio(uvd, 0, compression, 0x0109);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */
-		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */
-		ibmcam_veio(uvd, 0, 0x0000, 0x011e);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
-		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
-		/* 4 commands from 160x120 skipped */
-		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
-		ibmcam_veio(uvd, 0, compression, 0x0109);
-		ibmcam_veio(uvd, 0, 0x00d9, 0x0119);
-		ibmcam_veio(uvd, 0, 0x0006, 0x011b);
-		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0010, 0x0104);
-		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
-		ibmcam_veio(uvd, 0, 0x003f, 0x011c);
-		ibmcam_veio(uvd, 0, 0x001c, 0x0118);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
-		break;
-	case VIDEOSIZE_640x480:
-		ibmcam_veio(uvd, 0, 0x00f0, 0x0105);
-		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
-		ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */
-		ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */
-		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
-		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
-		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */
-		ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
-		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
-		ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
-		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
-		ibmcam_veio(uvd, 0, compression, 0x0109);
-		ibmcam_veio(uvd, 0, 0x0040, 0x0101);
-		ibmcam_veio(uvd, 0, 0x0040, 0x0103);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
-		break;
-	}
-	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);	/* Hue */
-	ibmcam_model3_Packet1(uvd, 0x0036, 0x0011);	/* Brightness */
-	ibmcam_model3_Packet1(uvd, 0x0060, 0x0002);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0061, 0x0004);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0062, 0x0005);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0063, 0x0014);	/* Sharpness */
-	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
-	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
-	ibmcam_model3_Packet1(uvd, 0x0067, 0x0001);	/* Contrast */
-	ibmcam_model3_Packet1(uvd, 0x005b, 0x000c);	/* Contrast */
-	ibmcam_model3_Packet1(uvd, 0x005c, 0x0016);	/* Contrast */
-	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x002c, 0x0003);	/* Was 1, broke 640x480 */
-	ibmcam_model3_Packet1(uvd, 0x002f, 0x002a);
-	ibmcam_model3_Packet1(uvd, 0x0030, 0x0029);
-	ibmcam_model3_Packet1(uvd, 0x0037, 0x0002);
-	ibmcam_model3_Packet1(uvd, 0x0038, 0x0059);
-	ibmcam_model3_Packet1(uvd, 0x003d, 0x002e);
-	ibmcam_model3_Packet1(uvd, 0x003e, 0x0028);
-	ibmcam_model3_Packet1(uvd, 0x0078, 0x0005);
-	ibmcam_model3_Packet1(uvd, 0x007b, 0x0011);
-	ibmcam_model3_Packet1(uvd, 0x007d, 0x004b);
-	ibmcam_model3_Packet1(uvd, 0x007f, 0x0022);
-	ibmcam_model3_Packet1(uvd, 0x0080, 0x000c);
-	ibmcam_model3_Packet1(uvd, 0x0081, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd);
-	ibmcam_model3_Packet1(uvd, 0x0086, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x0087, 0x000b);
-	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);
-	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
-	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
-	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
-
-	switch (uvd->videosize) {
-	case VIDEOSIZE_160x120:
-		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0107);
-		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
-		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0040, 0x000a);
-		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
-		break;
-	case VIDEOSIZE_320x240:
-		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
-		ibmcam_veio(uvd, 0, 0x0062, 0x0107);
-		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
-		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
-		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
-		ibmcam_model3_Packet1(uvd, 0x0051, 0x000b);
-		break;
-	case VIDEOSIZE_640x480:
-		ibmcam_veio(uvd, 0, 0x0002, 0x0106);	/* Adjustments */
-		ibmcam_veio(uvd, 0, 0x00b4, 0x0107);	/* Adjustments */
-		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
-		ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */
-		ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */
-		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
-		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
-		break;
-	}
-
-	/* 01.01.08 - Added for RCA video in support -LO */
-	if(init_model3_input) {
-		if (debug > 0)
-			info("Setting input to RCA.");
-		for (i=0; i < (sizeof(initData)/sizeof(initData[0])); i++) {
-			ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
-		}
-	}
-
-	ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-}
-
-/*
- * ibmcam_video_stop()
- *
- * This code tells camera to stop streaming. The interface remains
- * configured and bandwidth - claimed.
- */
-static void ibmcam_video_stop(uvd_t *uvd)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-		ibmcam_veio(uvd, 0, 0x00, 0x010c);
-		ibmcam_veio(uvd, 0, 0x00, 0x010c);
-		ibmcam_veio(uvd, 0, 0x01, 0x0114);
-		ibmcam_veio(uvd, 0, 0xc0, 0x010c);
-		ibmcam_veio(uvd, 0, 0x00, 0x010c);
-		ibmcam_send_FF_04_02(uvd);
-		ibmcam_veio(uvd, 1, 0x00, 0x0100);
-		ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
-		break;
-	case IBMCAM_MODEL_2:
-case IBMCAM_MODEL_4:
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop the camera */
-
-		ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
-
-		ibmcam_veio(uvd, 0, 0x0080, 0x0100);	/* LED Off */
-		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
-		ibmcam_veio(uvd, 0, 0x00a0, 0x0111);
-
-		ibmcam_model2_Packet1(uvd, 0x0030, 0x0002);
-
-		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
-		break;
-	case IBMCAM_MODEL_3:
-#if 1
-		ibmcam_veio(uvd, 0, 0x0000, 0x010c);
-
-		/* Here we are supposed to select video interface alt. setting 0 */
-		ibmcam_veio(uvd, 0, 0x0006, 0x012c);
-
-		ibmcam_model3_Packet1(uvd, 0x0046, 0x0000);
-
-		ibmcam_veio(uvd, 1, 0x0000, 0x0116);
-		ibmcam_veio(uvd, 0, 0x0064, 0x0116);
-		ibmcam_veio(uvd, 1, 0x0000, 0x0115);
-		ibmcam_veio(uvd, 0, 0x0003, 0x0115);
-		ibmcam_veio(uvd, 0, 0x0008, 0x0123);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0117);
-		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
-		ibmcam_veio(uvd, 0, 0x0080, 0x0100);
-		IBMCAM_T(uvd)->initialized = 0;
-#endif
-		break;
-	} /* switch */
-}
-
-/*
- * ibmcam_reinit_iso()
- *
- * This procedure sends couple of commands to the camera and then
- * resets the video pipe. This sequence was observed to reinit the
- * camera or, at least, to initiate ISO data stream.
- *
- * History:
- * 1/2/00   Created.
- */
-static void ibmcam_reinit_iso(uvd_t *uvd, int do_stop)
-{
-	switch (IBMCAM_T(uvd)->camera_model) {
-	case IBMCAM_MODEL_1:
-		if (do_stop)
-			ibmcam_video_stop(uvd);
-		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
-		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
-		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
-		ibmcam_model1_setup_after_video_if(uvd);
-		break;
-	case IBMCAM_MODEL_2:
-		ibmcam_model2_setup_after_video_if(uvd);
-		break;
-	case IBMCAM_MODEL_3:
-		ibmcam_video_stop(uvd);
-		ibmcam_model3_setup_after_video_if(uvd);
-		break;
-	case IBMCAM_MODEL_4:
-		ibmcam_model4_setup_after_video_if(uvd);
-		break;
-	}
-}
-
-static void ibmcam_video_start(uvd_t *uvd)
-{
-	ibmcam_change_lighting_conditions(uvd);
-	ibmcam_set_sharpness(uvd);
-	ibmcam_reinit_iso(uvd, 0);
-}
-
-/*
- * Return negative code on failure, 0 on success.
- */
-static int ibmcam_setup_on_open(uvd_t *uvd)
-{
-	int setup_ok = 0; /* Success by default */
-	/* Send init sequence only once, it's large! */
-	if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */
-		switch (IBMCAM_T(uvd)->camera_model) {
-		case IBMCAM_MODEL_1:
-			setup_ok = ibmcam_model1_setup(uvd);
-			break;
-		case IBMCAM_MODEL_2:
-			setup_ok = ibmcam_model2_setup(uvd);
-			break;
-		case IBMCAM_MODEL_3:
-		case IBMCAM_MODEL_4:
-			/* We do all setup when Isoc stream is requested */
-			break;
-		}
-		IBMCAM_T(uvd)->initialized = (setup_ok != 0);
-	}
-	return setup_ok;
-}
-
-static void ibmcam_configure_video(uvd_t *uvd)
-{
-	if (uvd == NULL)
-		return;
-
-	RESTRICT_TO_RANGE(init_brightness, 0, 255);
-	RESTRICT_TO_RANGE(init_contrast, 0, 255);
-	RESTRICT_TO_RANGE(init_color, 0, 255);
-	RESTRICT_TO_RANGE(init_hue, 0, 255);
-	RESTRICT_TO_RANGE(hue_correction, 0, 255);
-
-	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
-	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
-
-	uvd->vpic.colour = init_color << 8;
-	uvd->vpic.hue = init_hue << 8;
-	uvd->vpic.brightness = init_brightness << 8;
-	uvd->vpic.contrast = init_contrast << 8;
-	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
-	uvd->vpic.depth = 24;
-	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
-
-	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
-	strcpy(uvd->vcap.name, "IBM USB Camera");
-	uvd->vcap.type = VID_TYPE_CAPTURE;
-	uvd->vcap.channels = 1;
-	uvd->vcap.audios = 0;
-	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
-	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
-	uvd->vcap.minwidth = min_canvasWidth;
-	uvd->vcap.minheight = min_canvasHeight;
-
-	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
-	uvd->vchan.flags = 0;
-	uvd->vchan.tuners = 0;
-	uvd->vchan.channel = 0;
-	uvd->vchan.type = VIDEO_TYPE_CAMERA;
-	strcpy(uvd->vchan.name, "Camera");
-}
-
-/*
- * ibmcam_probe()
- *
- * This procedure queries device descriptor and accepts the interface
- * if it looks like IBM C-it camera.
- *
- * History:
- * 22-Jan-2000 Moved camera init code to ibmcam_open()
- * 27=Jan-2000 Changed to use static structures, added locking.
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- * 03-Jul-2000 Fixed endianness bug.
- * 12-Nov-2000 Reworked to comply with new probe() signature.
- * 23-Jan-2001 Added compatibility with 2.2.x kernels.
- */
-static void *ibmcam_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid)
-{
-	uvd_t *uvd = NULL;
-	int i, nas, model=0, canvasX=0, canvasY=0;
-	int actInterface=-1, inactInterface=-1, maxPS=0;
-	unsigned char video_ep = 0;
-
-	if (debug >= 1)
-		info("ibmcam_probe(%p,%u.)", dev, ifnum);
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-	/* Is it an IBM camera? */
-	if (dev->descriptor.idVendor != IBMCAM_VENDOR_ID)
-		return NULL;
-	if ((dev->descriptor.idProduct != IBMCAM_PRODUCT_ID) &&
-	    (dev->descriptor.idProduct != VEO_800C_PRODUCT_ID) &&
-	    (dev->descriptor.idProduct != VEO_800D_PRODUCT_ID) &&
-	    (dev->descriptor.idProduct != NETCAM_PRODUCT_ID))
-		return NULL;
-
-	/* Check the version/revision */
-	switch (dev->descriptor.bcdDevice) {
-	case 0x0002:
-		if (ifnum != 2)
-			return NULL;
-		model = IBMCAM_MODEL_1;
-		break;
-	case 0x030A:
-		if (ifnum != 0)
-			return NULL;
-		if ((dev->descriptor.idProduct == NETCAM_PRODUCT_ID) ||
-		    (dev->descriptor.idProduct == VEO_800D_PRODUCT_ID))
-			model = IBMCAM_MODEL_4;
-		else
-			model = IBMCAM_MODEL_2;
-		break;
-	case 0x0301:
-		if (ifnum != 0)
-			return NULL;
-		model = IBMCAM_MODEL_3;
-		break;
-	default:
-		err("IBM camera with revision 0x%04x is not supported.",
-			dev->descriptor.bcdDevice);
-		return NULL;
-	}
-
-	/* Print detailed info on what we found so far */
-	do {
-		char *brand = NULL;
-		switch (dev->descriptor.idProduct) {
-		case NETCAM_PRODUCT_ID:
-			brand = "IBM NetCamera";
-			break;
-		case VEO_800C_PRODUCT_ID:
-			brand = "Veo Stingray [800C]";
-			break;
-		case VEO_800D_PRODUCT_ID:
-			brand = "Veo Stingray [800D]";
-			break;
-		case IBMCAM_PRODUCT_ID:
-		default:
-			brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
-			break;
-		}
-		info("%s USB camera found (model %d, rev. 0x%04x)",
-		     brand, model, dev->descriptor.bcdDevice);
-	} while (0);
-
-	/* Validate found interface: must have one ISO endpoint */
-	nas = dev->actconfig->interface[ifnum].num_altsetting;
-	if (debug > 0)
-		info("Number of alternate settings=%d.", nas);
-	if (nas < 2) {
-		err("Too few alternate settings for this camera!");
-		return NULL;
-	}
-	/* Validate all alternate settings */
-	for (i=0; i < nas; i++) {
-		const struct usb_interface_descriptor *interface;
-		const struct usb_endpoint_descriptor *endpoint;
-
-		interface = &dev->actconfig->interface[ifnum].altsetting[i];
-		if (interface->bNumEndpoints != 1) {
-			err("Interface %d. has %u. endpoints!",
-			    ifnum, (unsigned)(interface->bNumEndpoints));
-			return NULL;
-		}
-		endpoint = &interface->endpoint[0];
-		if (video_ep == 0)
-			video_ep = endpoint->bEndpointAddress;
-		else if (video_ep != endpoint->bEndpointAddress) {
-			err("Alternate settings have different endpoint addresses!");
-			return NULL;
-		}
-		if ((endpoint->bmAttributes & 0x03) != 0x01) {
-			err("Interface %d. has non-ISO endpoint!", ifnum);
-			return NULL;
-		}
-		if ((endpoint->bEndpointAddress & 0x80) == 0) {
-			err("Interface %d. has ISO OUT endpoint!", ifnum);
-			return NULL;
-		}
-		if (endpoint->wMaxPacketSize == 0) {
-			if (inactInterface < 0)
-				inactInterface = i;
-			else {
-				err("More than one inactive alt. setting!");
-				return NULL;
-			}
-		} else {
-			if (actInterface < 0) {
-				actInterface = i;
-				maxPS = endpoint->wMaxPacketSize;
-				if (debug > 0)
-					info("Active setting=%d. maxPS=%d.", i, maxPS);
-			} else
-				err("More than one active alt. setting! Ignoring #%d.", i);
-		}
-	}
-	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
-		err("Failed to recognize the camera!");
-		return NULL;
-	}
-
-	/* Validate options */
-	switch (model) {
-	case IBMCAM_MODEL_1:
-		RESTRICT_TO_RANGE(lighting, 0, 2);
-		RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288);
-		if (framerate < 0)
-			framerate = 2;
-		canvasX = 352;
-		canvasY = 288;
-		break;
-	case IBMCAM_MODEL_2:
-		RESTRICT_TO_RANGE(lighting, 0, 15);
-		RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240);
-		if (framerate < 0)
-			framerate = 2;
-		canvasX = 352;
-		canvasY = 240;
-		break;
-	case IBMCAM_MODEL_3:
-		RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */
-		switch (size) {
-		case SIZE_160x120:
-			canvasX = 160;
-			canvasY = 120;
-			if (framerate < 0)
-				framerate = 2;
-			RESTRICT_TO_RANGE(framerate, 0, 5);
-			break;
-		default:
-			info("IBM camera: using 320x240");
-			size = SIZE_320x240;
-			/* No break here */
-		case SIZE_320x240:
-			canvasX = 320;
-			canvasY = 240;
-			if (framerate < 0)
-				framerate = 3;
-			RESTRICT_TO_RANGE(framerate, 0, 5);
-			break;
-		case SIZE_640x480:
-			canvasX = 640;
-			canvasY = 480;
-			framerate = 0;	/* Slowest, and maybe even that is too fast */
-			break;
-		}
-		break;
-	case IBMCAM_MODEL_4:
-		RESTRICT_TO_RANGE(lighting, 0, 2);
-		switch (size) {
-		case SIZE_128x96:
-			canvasX = 128;
-			canvasY = 96;
-			break;
-		case SIZE_160x120:
-			canvasX = 160;
-			canvasY = 120;
-			break;
-		default:
-			info("IBM NetCamera: using 176x144");
-			size = SIZE_176x144;
-			/* No break here */
-		case SIZE_176x144:
-			canvasX = 176;
-			canvasY = 144;
-			break;
-		case SIZE_320x240:
-			canvasX = 320;
-			canvasY = 240;
-			break;
-		case SIZE_352x288:
-			canvasX = 352;
-			canvasY = 288;
-			break;
-		}
-		break;
-	default:
-		err("IBM camera: Model %d. not supported!", model);
-		return NULL;
-	}
-
-	/* Code below may sleep, need to lock module while we are here */
-	MOD_INC_USE_COUNT;
-	uvd = usbvideo_AllocateDevice(cams);
-	if (uvd != NULL) {
-		/* Here uvd is a fully allocated uvd_t object */
-		uvd->flags = flags;
-		uvd->debug = debug;
-		uvd->dev = dev;
-		uvd->iface = ifnum;
-		uvd->ifaceAltInactive = inactInterface;
-		uvd->ifaceAltActive = actInterface;
-		uvd->video_endp = video_ep;
-		uvd->iso_packet_len = maxPS;
-		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
-		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
-		uvd->canvas = VIDEOSIZE(canvasX, canvasY);
-		uvd->videosize = ibmcam_size_to_videosize(size);
-
-		/* Initialize ibmcam-specific data */
-		assert(IBMCAM_T(uvd) != NULL);
-		IBMCAM_T(uvd)->camera_model = model;
-		IBMCAM_T(uvd)->initialized = 0;
-
-		ibmcam_configure_video(uvd);
-
-		i = usbvideo_RegisterVideoDevice(uvd);
-		if (i != 0) {
-			err("usbvideo_RegisterVideoDevice() failed.");
-			uvd = NULL;
-		}
-	}
-	MOD_DEC_USE_COUNT;
-	return uvd;
-}
-
-/*
- * ibmcam_init()
- *
- * This code is run to initialize the driver.
- *
- * History:
- * 1/27/00  Reworked to use statically allocated ibmcam structures.
- * 21/10/00 Completely redesigned to use usbvideo services.
- */
-static int __init ibmcam_init(void)
-{
-	usbvideo_cb_t cbTbl;
-	memset(&cbTbl, 0, sizeof(cbTbl));
-	cbTbl.probe = ibmcam_probe;
-	cbTbl.setupOnOpen = ibmcam_setup_on_open;
-	cbTbl.videoStart = ibmcam_video_start;
-	cbTbl.videoStop = ibmcam_video_stop;
-	cbTbl.processData = ibmcam_ProcessIsocData;
-	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
-	cbTbl.adjustPicture = ibmcam_adjust_picture;
-	cbTbl.getFPS = ibmcam_calculate_fps;
-	return usbvideo_register(
-		&cams,
-		MAX_IBMCAM,
-		sizeof(ibmcam_t),
-		"ibmcam",
-		&cbTbl,
-		THIS_MODULE);
-}
-
-static void __exit ibmcam_cleanup(void)
-{
-	usbvideo_Deregister(&cams);
-}
-
-static __devinitdata struct usb_device_id id_table[] = {
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
-	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
-	{ }  /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-module_init(ibmcam_init);
-module_exit(ibmcam_cleanup);
diff -Nru a/drivers/usb/image/Config.help b/drivers/usb/image/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,47 @@
+CONFIG_USB_DC2XX
+  Say Y here if you want to connect this type of still camera to your
+  computer's USB port.  See <file:Documentation/usb/dc2xx.txt> for
+  more information; some non-Kodak cameras may also work with this
+  driver, given application support (such as <http://www.gphoto.org/>).
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dc2xx.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_MDC800
+  Say Y here if you want to connect this type of still camera to
+  your computer's USB port. This driver can be used with gphoto 0.4.3
+  and higher (look at <http://www.gphoto.org/>).
+  To use it create a device node with "mknod /dev/mustek c 180 32" and
+  configure it in your software.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called mdc800.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_HPUSBSCSI
+  Say Y here if you want support for the HP 53xx series of scanners
+  and the Minolta Scan Dual. This driver is experimental.
+  The scanner will be accessible as a SCSI device.
+  This can be compiled as a module, called hpusbscsi.o.
+
+CONFIG_USB_MICROTEK
+  Say Y here if you want support for the Microtek X6USB and
+  possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
+  Support for anything but the X6 is experimental.
+  Please report failures and successes.
+  The scanner will appear as a scsi generic device to the rest
+  of the system. Scsi support is required.
+  This driver can be compiled as a module, called microtek.o.
+
+CONFIG_USB_SCANNER
+  Say Y here if you want to connect a USB scanner to your computer's
+  USB port. Please read <file:Documentation/usb/scanner.txt> and
+  <file:Documentation/usb/scanner-hp-sane.txt> for more information.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called scanner.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/image/Config.in b/drivers/usb/image/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,19 @@
+#
+# USB Imageing devices configuration
+#
+comment 'USB Imaging devices'
+dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
+dep_tristate '  USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
+dep_tristate '  Microtek X6USB scanner support' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI
+dep_tristate '  HP53xx USB scanner support (EXPERIMENTAL)' CONFIG_USB_HPUSBSCSI $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL
+
+# Turn on CONFIG_USB_IMAGE if any of the drivers are compiled into the kernel to
+# make our Makefile logic a bit simpler
+if [ "$CONFIG_USB_DC2XX" = "y" -o "$CONFIG_USB_MDC800" = "y" ]; then
+   define_bool CONFIG_USB_IMAGE y
+fi
+if [ "$CONFIG_USB_SCANNER" = "y" -o "$CONFIG_USB_MICROTEK" = "y" -o "$CONFIG_USB_HPUSBSCSI" = "y" ]; then
+   define_bool CONFIG_USB_IMAGE y
+fi
+   
diff -Nru a/drivers/usb/image/Makefile b/drivers/usb/image/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,13 @@
+#
+# Makefile for USB Image drivers
+#
+
+O_TARGET	:= usb-image.o
+
+obj-$(CONFIG_USB_DC2XX)		+= dc2xx.o
+obj-$(CONFIG_USB_MDC800)	+= mdc800.o
+obj-$(CONFIG_USB_HPUSBSCSI)	+= hpusbscsi.o
+obj-$(CONFIG_USB_MICROTEK)	+= microtek.o
+obj-$(CONFIG_USB_SCANNER)	+= scanner.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/image/dc2xx.c b/drivers/usb/image/dc2xx.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/dc2xx.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,538 @@
+/*
+ * Copyright (C) 1999-2000 by David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+ 
+ 
+/*
+ * USB driver for Kodak DC-2XX series digital still cameras
+ *
+ * The protocol here is the same as the one going over a serial line, but
+ * it uses USB for speed.  Set up /dev/kodak, get gphoto (www.gphoto.org),
+ * and have fun!
+ *
+ * This should also work for a number of other digital (non-Kodak) cameras,
+ * by adding the vendor and product IDs to the table below.  They'll need
+ * to be the sort using USB just as a fast bulk data channel.
+ */
+
+/*
+ * HISTORY
+ *
+ * 26 August, 1999 -- first release (0.1), works with my DC-240.
+ * 	The DC-280 (2Mpixel) should also work, but isn't tested.
+ *	If you use gphoto, make sure you have the USB updates.
+ *	Lives in a 2.3.14 or so Linux kernel, in drivers/usb.
+ * 31 August, 1999 -- minor update to recognize DC-260 and handle
+ *	its endpoints being in a different order.  Note that as
+ *	of gPhoto 0.36pre, the USB updates are integrated.
+ * 12 Oct, 1999 -- handle DC-280 interface class (0xff not 0x0);
+ *	added timeouts to bulk_msg calls.  Minor updates, docs.
+ * 03 Nov, 1999 -- update for 2.3.25 kernel API changes.
+ * 08 Jan, 2000 .. multiple camera support
+ * 12 Aug, 2000 .. add some real locking, remove an Oops
+ * 10 Oct, 2000 .. usb_device_id table created. 
+ * 01 Nov, 2000 .. usb_device_id support added by Adam J. Richter
+ * 08 Apr, 2001 .. Identify version on module load. gb
+ *
+ * Thanks to:  the folk who've provided USB product IDs, sent in
+ * patches, and shared their successes!
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/devfs_fs_kernel.h>
+
+#ifdef CONFIG_USB_DEBUG
+	#define DEBUG
+#else
+	#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+
+/* /dev/usb dir. */
+extern devfs_handle_t usb_devfs_handle;			
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0.0"
+#define DRIVER_AUTHOR "David Brownell, <dbrownell@users.sourceforge.net>"
+#define DRIVER_DESC "USB Camera Driver for Kodak DC-2xx series cameras"
+
+
+/* current USB framework handles max of 16 USB devices per driver */
+#define	MAX_CAMERAS		16
+
+/* USB char devs use USB_MAJOR and from USB_CAMERA_MINOR_BASE up */
+#define	USB_CAMERA_MINOR_BASE	80
+
+
+// XXX remove packet size limit, now that bulk transfers seem fixed
+
+/* Application protocol limit is 0x8002; USB has disliked that limit! */
+#define	MAX_PACKET_SIZE		0x2000		/* e.g. image downloading */
+
+#define	MAX_READ_RETRY		5		/* times to retry reads */
+#define	MAX_WRITE_RETRY		5		/* times to retry writes */
+#define	RETRY_TIMEOUT		(HZ)		/* sleep between retries */
+
+
+/* table of cameras that work through this driver */
+static struct usb_device_id camera_table [] = {
+	/* These have the same application level protocol */  
+	{ USB_DEVICE(0x040a, 0x0120) },		// Kodak DC-240
+	{ USB_DEVICE(0x040a, 0x0130) },		// Kodak DC-280
+	{ USB_DEVICE(0x040a, 0x0131) },		// Kodak DC-5000
+	{ USB_DEVICE(0x040a, 0x0132) },		// Kodak DC-3400
+
+	/* These have a different application level protocol which
+	 * is part of the Flashpoint "DigitaOS".  That supports some
+	 * non-camera devices, and some non-Kodak cameras.
+	 * Use this driver to get USB and "OpenDis" to talk.
+	 */  
+	{ USB_DEVICE(0x040a, 0x0100) },		// Kodak DC-220
+	{ USB_DEVICE(0x040a, 0x0110) },		// Kodak DC-260
+	{ USB_DEVICE(0x040a, 0x0111) },		// Kodak DC-265
+	{ USB_DEVICE(0x040a, 0x0112) },		// Kodak DC-290
+	{ USB_DEVICE(0xf003, 0x6002) },		// HP PhotoSmart C500
+	{ USB_DEVICE(0x03f0, 0x4102) },		// HP PhotoSmart C618
+	{ USB_DEVICE(0x0a17, 0x1001) },		// Pentax EI-200
+
+	/* Other USB devices may well work here too, so long as they
+	 * just stick to half duplex bulk packet exchanges.  That
+	 * means, among other things, no iso or interrupt endpoints.
+	 */
+
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, camera_table);
+
+
+struct camera_state {
+	struct usb_device	*dev;		/* USB device handle */
+	int			inEP;		/* read endpoint */
+	int			outEP;		/* write endpoint */
+	const struct usb_device_id	*info;	/* DC-240, etc */
+	int			subminor;	/* which minor dev #? */
+	struct semaphore	sem;		/* locks this struct */
+
+	/* this is non-null iff the device is open */
+	char			*buf;		/* buffer for I/O */
+
+	devfs_handle_t		devfs;		/* devfs device */
+
+	/* always valid */
+	wait_queue_head_t	wait;		/* for timed waits */
+};
+
+/* Support multiple cameras, possibly of different types.  */
+static struct camera_state *minor_data [MAX_CAMERAS];
+
+/* make this an rwlock if contention becomes an issue */
+static DECLARE_MUTEX (state_table_mutex);
+
+static ssize_t camera_read (struct file *file,
+	char *buf, size_t len, loff_t *ppos)
+{
+	struct camera_state	*camera;
+	int			retries;
+	int			retval = 0;
+
+	if (len > MAX_PACKET_SIZE)
+		return -EINVAL;
+
+	camera = (struct camera_state *) file->private_data;
+	down (&camera->sem);
+	if (!camera->dev) {
+		up (&camera->sem);
+		return -ENODEV;
+	}
+
+	/* Big reads are common, for image downloading.  Smaller ones
+	 * are also common (even "directory listing" commands don't
+	 * send very much data).  We preserve packet boundaries here,
+	 * they matter in the application protocol.
+	 */
+	for (retries = 0; retries < MAX_READ_RETRY; retries++) {
+		int			count;
+
+		if (signal_pending (current)) {
+			retval = -EINTR;
+			break;
+		}
+
+		retval = usb_bulk_msg (camera->dev,
+			  usb_rcvbulkpipe (camera->dev, camera->inEP),
+			  camera->buf, len, &count, HZ*10);
+
+		dbg ("read (%Zd) - 0x%x %d", len, retval, count);
+
+		if (!retval) {
+			if (copy_to_user (buf, camera->buf, count))
+				retval = -EFAULT;
+			else
+				retval = count;
+			break;
+		}
+		if (retval != -ETIMEDOUT)
+			break;
+		interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
+
+		dbg ("read (%Zd) - retry", len);
+	}
+	up (&camera->sem);
+	return retval;
+}
+
+static ssize_t camera_write (struct file *file,
+	const char *buf, size_t len, loff_t *ppos)
+{
+	struct camera_state	*camera;
+	ssize_t			bytes_written = 0;
+
+	if (len > MAX_PACKET_SIZE)
+		return -EINVAL;
+
+	camera = (struct camera_state *) file->private_data;
+	down (&camera->sem);
+	if (!camera->dev) {
+		up (&camera->sem);
+		return -ENODEV;
+	}
+	
+	/* most writes will be small: simple commands, sometimes with
+	 * parameters.  putting images (like borders) into the camera
+	 * would be the main use of big writes.
+	 */
+	while (len > 0) {
+		char		*obuf = camera->buf;
+		int		maxretry = MAX_WRITE_RETRY;
+		unsigned long	copy_size, thistime;
+
+		/* it's not clear that retrying can do any good ... or that
+		 * fragmenting application packets into N writes is correct.
+		 */
+		thistime = copy_size = len;
+		if (copy_from_user (obuf, buf, copy_size)) {
+			bytes_written = -EFAULT;
+			break;
+		}
+		while (thistime) {
+			int		result;
+			int		count;
+
+			if (signal_pending (current)) {
+				if (!bytes_written)
+					bytes_written = -EINTR;
+				goto done;
+			}
+
+			result = usb_bulk_msg (camera->dev,
+				 usb_sndbulkpipe (camera->dev, camera->outEP),
+				 obuf, thistime, &count, HZ*10);
+
+			if (result)
+				dbg ("write USB err - %d", result);
+
+			if (count) {
+				obuf += count;
+				thistime -= count;
+				maxretry = MAX_WRITE_RETRY;
+				continue;
+			} else if (!result)
+				break;
+				
+			if (result == -ETIMEDOUT) {	/* NAK - delay a bit */
+				if (!maxretry--) {
+					if (!bytes_written)
+						bytes_written = -ETIME;
+					goto done;
+				}
+                                interruptible_sleep_on_timeout (&camera->wait,
+					RETRY_TIMEOUT);
+				continue;
+			} 
+			if (!bytes_written)
+				bytes_written = -EIO;
+			goto done;
+		}
+		bytes_written += copy_size;
+		len -= copy_size;
+		buf += copy_size;
+	}
+done:
+	up (&camera->sem);
+	dbg ("wrote %Zd", bytes_written); 
+	return bytes_written;
+}
+
+static int camera_open (struct inode *inode, struct file *file)
+{
+	struct camera_state	*camera = NULL;
+	int			subminor;
+	int			value = 0;
+
+	down (&state_table_mutex);
+	subminor = minor (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
+	if (subminor < 0 || subminor >= MAX_CAMERAS
+			|| !(camera = minor_data [subminor])) {
+		up (&state_table_mutex);
+		return -ENODEV;
+	}
+	down (&camera->sem);
+	up (&state_table_mutex);
+
+	if (camera->buf) {
+		value = -EBUSY;
+		goto done;
+	}
+
+	if (!(camera->buf = (char *) kmalloc (MAX_PACKET_SIZE, GFP_KERNEL))) {
+		value = -ENOMEM;
+		goto done;
+	}
+
+	dbg ("open #%d", subminor); 
+
+	file->private_data = camera;
+done:
+	up (&camera->sem);
+	return value;
+}
+
+static int camera_release (struct inode *inode, struct file *file)
+{
+	struct camera_state	*camera;
+	int			subminor;
+
+	camera = (struct camera_state *) file->private_data;
+	down (&state_table_mutex);
+	down (&camera->sem);
+
+	if (camera->buf) {
+		kfree (camera->buf);
+		camera->buf = 0;
+	}
+	subminor = camera->subminor;
+
+	/* If camera was unplugged with open file ... */
+	if (!camera->dev) {
+		minor_data [subminor] = NULL;
+		kfree (camera);
+	} else
+		up (&camera->sem);
+	
+	up (&state_table_mutex);
+
+	dbg ("close #%d", subminor); 
+
+	return 0;
+}
+
+	/* XXX should define some ioctls to expose camera type
+	 * to applications ... what USB exposes should suffice.
+	 * apps should be able to see the camera type.
+	 */
+static /* const */ struct file_operations usb_camera_fops = {
+	    /* Uses GCC initializer extension; simpler to maintain */
+	owner:		THIS_MODULE,
+	read:		camera_read,
+	write:		camera_write,
+	open:		camera_open,
+	release:	camera_release,
+};
+
+
+
+static void *
+camera_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *camera_info)
+{
+	int				i;
+	struct usb_interface_descriptor	*interface;
+	struct usb_endpoint_descriptor	*endpoint;
+	int				direction, ep;
+	char name[8];
+	struct camera_state		*camera = NULL;
+
+
+	/* these have one config, one interface */
+	if (dev->descriptor.bNumConfigurations != 1
+			|| dev->config[0].bNumInterfaces != 1) {
+		dbg ("Bogus camera config info");
+		return NULL;
+	}
+
+	/* models differ in how they report themselves */
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	if ((interface->bInterfaceClass != USB_CLASS_PER_INTERFACE
+		&& interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+			|| interface->bInterfaceSubClass != 0
+			|| interface->bInterfaceProtocol != 0
+			|| interface->bNumEndpoints != 2
+			) {
+		dbg ("Bogus camera interface info");
+		return NULL;
+	}
+
+
+	/* select "subminor" number (part of a minor number) */
+	down (&state_table_mutex);
+	for (i = 0; i < MAX_CAMERAS; i++) {
+		if (!minor_data [i])
+			break;
+	}
+	if (i >= MAX_CAMERAS) {
+		info ("Ignoring additional USB Camera");
+		goto bye;
+	}
+
+	/* allocate & init camera state */
+	camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
+	if (!camera) {
+		err ("no memory!");
+		goto bye;
+	}
+
+	init_MUTEX (&camera->sem);
+	camera->info = camera_info;
+	camera->subminor = i;
+	camera->buf = NULL;
+	init_waitqueue_head (&camera->wait);
+
+
+	/* get input and output endpoints (either order) */
+	endpoint = interface->endpoint;
+	camera->outEP = camera->inEP =  -1;
+
+	ep = endpoint [0].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	direction = endpoint [0].bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+	if (direction == USB_DIR_IN)
+		camera->inEP = ep;
+	else
+		camera->outEP = ep;
+
+	ep = endpoint [1].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	direction = endpoint [1].bEndpointAddress & USB_ENDPOINT_DIR_MASK;
+	if (direction == USB_DIR_IN)
+		camera->inEP = ep;
+	else
+		camera->outEP = ep;
+
+	if (camera->outEP == -1 || camera->inEP == -1
+			|| endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
+			|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
+			) {
+		dbg ("Bogus endpoints");
+		goto error;
+	}
+
+	info ("USB Camera #%d connected, major/minor %d/%d", camera->subminor,
+		USB_MAJOR, USB_CAMERA_MINOR_BASE + camera->subminor);
+
+	camera->dev = dev;
+	usb_inc_dev_use (dev);
+
+	/* If we have devfs, register the device */
+	sprintf(name, "dc2xx%d", camera->subminor);
+	camera->devfs = devfs_register(usb_devfs_handle, name,
+				       DEVFS_FL_DEFAULT, USB_MAJOR,
+				       USB_CAMERA_MINOR_BASE + camera->subminor,
+				       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
+				       S_IWGRP, &usb_camera_fops, NULL);
+
+	goto bye;
+
+error:
+	minor_data [camera->subminor] = NULL;
+	kfree (camera);
+	camera = NULL;
+bye:
+	up (&state_table_mutex);
+	return camera;
+}
+
+static void camera_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct camera_state	*camera = (struct camera_state *) ptr;
+	int			subminor = camera->subminor;
+
+	down (&state_table_mutex);
+	down (&camera->sem);
+
+	devfs_unregister(camera->devfs); 
+
+	/* If camera's not opened, we can clean up right away.
+	 * Else apps see a disconnect on next I/O; the release cleans.
+	 */
+	if (!camera->buf) {
+		minor_data [subminor] = NULL;
+		kfree (camera);
+		camera = NULL;
+	} else
+		camera->dev = NULL;
+
+	info ("USB Camera #%d disconnected", subminor);
+	usb_dec_dev_use (dev);
+
+	if (camera != NULL)
+		up (&camera->sem);
+	up (&state_table_mutex);
+}
+
+static /* const */ struct usb_driver camera_driver = {
+	name:		"dc2xx",
+
+	id_table:	camera_table,
+	probe:		camera_probe,
+	disconnect:	camera_disconnect,
+
+	fops:		&usb_camera_fops,
+	minor:		USB_CAMERA_MINOR_BASE
+};
+
+
+int __init usb_dc2xx_init(void)
+{
+ 	if (usb_register (&camera_driver) < 0)
+ 		return -1;
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+void __exit usb_dc2xx_cleanup(void)
+{
+	usb_deregister (&camera_driver);
+}
+
+module_init (usb_dc2xx_init);
+module_exit (usb_dc2xx_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/hpusbscsi.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,598 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/usb.h>
+#include <asm/atomic.h>
+#include <linux/blk.h>
+#include "../../scsi/scsi.h"
+#include "../../scsi/hosts.h"
+#include "../../scsi/sd.h"
+
+#include "hpusbscsi.h"
+
+#define DEBUG(x...) \
+	printk( KERN_DEBUG x )
+
+static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
+
+#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
+
+/* global variables */
+
+struct list_head hpusbscsi_devices;
+//LIST_HEAD(hpusbscsi_devices);
+
+/* USB related parts */
+
+static void *
+hpusbscsi_usb_probe (struct usb_device *dev, unsigned int interface,
+		     const struct usb_device_id *id)
+{
+	struct hpusbscsi *new;
+	struct usb_interface_descriptor *altsetting =
+		&(dev->actconfig->interface[interface].altsetting[0]);
+
+	int i, result;
+
+	/* basic check */
+
+	if (altsetting->bNumEndpoints != 3) {
+		printk (KERN_ERR "Wrong number of endpoints\n");
+		return NULL;
+	}
+
+	/* descriptor allocation */
+
+	new =
+		(struct hpusbscsi *) kmalloc (sizeof (struct hpusbscsi),
+					      GFP_KERNEL);
+	if (new == NULL)
+		return NULL;
+	DEBUG ("Allocated memory\n");
+	memset (new, 0, sizeof (struct hpusbscsi));
+	new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!new->dataurb) {
+		kfree (new);
+		return NULL;
+	}
+	new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!new->controlurb) {
+		usb_free_urb (new->dataurb);
+		kfree (new);
+		return NULL;
+	}
+	new->dev = dev;
+	init_waitqueue_head (&new->pending);
+	init_waitqueue_head (&new->deathrow);
+	INIT_LIST_HEAD (&new->lh);
+
+
+
+	/* finding endpoints */
+
+	for (i = 0; i < altsetting->bNumEndpoints; i++) {
+		if (
+		    (altsetting->endpoint[i].
+		     bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		    USB_ENDPOINT_XFER_BULK) {
+			if (altsetting->endpoint[i].
+			    bEndpointAddress & USB_DIR_IN) {
+				new->ep_in =
+					altsetting->endpoint[i].
+					bEndpointAddress &
+					USB_ENDPOINT_NUMBER_MASK;
+			} else {
+				new->ep_out =
+					altsetting->endpoint[i].
+					bEndpointAddress &
+					USB_ENDPOINT_NUMBER_MASK;
+			}
+		} else {
+			new->ep_int =
+				altsetting->endpoint[i].
+				bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			new->interrupt_interval= altsetting->endpoint[i].bInterval;
+		}
+	}
+
+	/* USB initialisation magic for the simple case */
+
+	result = usb_set_interface (dev, altsetting->bInterfaceNumber, 0);
+
+	switch (result) {
+	case 0:		/* no error */
+		break;
+
+	case -EPIPE:
+		usb_clear_halt (dev, usb_sndctrlpipe (dev, 0));
+		break;
+
+	default:
+		printk (KERN_ERR "unknown error %d from usb_set_interface\n",
+			 result);
+		goto err_out;
+	}
+
+	/* making a template for the scsi layer to fake detection of a scsi device */
+
+	memcpy (&(new->ctempl), &hpusbscsi_scsi_host_template,
+		sizeof (hpusbscsi_scsi_host_template));
+	(struct hpusbscsi *) new->ctempl.proc_dir = new;
+	new->ctempl.module = THIS_MODULE;
+
+	if (scsi_register_host(&new->ctempl))
+		goto err_out;
+
+	new->sense_command[0] = REQUEST_SENSE;
+	new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
+
+	/* adding to list for module unload */
+	list_add (&hpusbscsi_devices, &new->lh);
+
+	return new;
+
+      err_out:
+	usb_free_urb (new->controlurb);
+	usb_free_urb (new->dataurb);
+	kfree (new);
+	return NULL;
+}
+
+static void
+hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr)
+{
+                 usb_unlink_urb((((struct hpusbscsi *) ptr)->controlurb));
+	((struct hpusbscsi *) ptr)->dev = NULL;
+}
+
+static struct usb_device_id hpusbscsi_usb_ids[] = {
+	{USB_DEVICE (0x03f0, 0x0701)},	/* HP 53xx */
+	{USB_DEVICE (0x03f0, 0x0801)},	/* HP 7400 */
+	{USB_DEVICE (0x0638, 0x026a)},	/*Scan Dual II */
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids);
+MODULE_LICENSE("GPL");
+
+
+static struct usb_driver hpusbscsi_usb_driver = {
+	name:"hpusbscsi",
+	probe:hpusbscsi_usb_probe,
+	disconnect:hpusbscsi_usb_disconnect,
+	id_table:hpusbscsi_usb_ids,
+};
+
+/* module initialisation */
+
+int __init
+hpusbscsi_init (void)
+{
+	int result;
+
+	INIT_LIST_HEAD (&hpusbscsi_devices);
+	DEBUG ("Driver loaded\n");
+
+	if ((result = usb_register (&hpusbscsi_usb_driver)) < 0) {
+		printk (KERN_ERR "hpusbscsi: driver registration failed\n");
+		return -1;
+	} else {
+		return 0;
+	}
+}
+
+void __exit
+hpusbscsi_exit (void)
+{
+	struct list_head *tmp;
+	struct list_head *old;
+	struct hpusbscsi * o;
+
+	for (tmp = hpusbscsi_devices.next; tmp != &hpusbscsi_devices;/*nothing */) {
+		old = tmp;
+		tmp = tmp->next;
+		o = (struct hpusbscsi *)old;
+		usb_unlink_urb(o->controlurb);
+		scsi_unregister_host(&o->ctempl);
+		usb_free_urb(o->controlurb);
+		usb_free_urb(o->dataurb);
+		kfree(old);
+	}
+
+	usb_deregister (&hpusbscsi_usb_driver);
+}
+
+module_init (hpusbscsi_init);
+module_exit (hpusbscsi_exit);
+
+/* interface to the scsi layer */
+
+static int
+hpusbscsi_scsi_detect (struct SHT *sht)
+{
+	/* Whole function stolen from usb-storage */
+
+	struct hpusbscsi *desc = (struct hpusbscsi *) sht->proc_dir;
+	/* What a hideous hack! */
+
+	char local_name[48];
+
+
+	/* set up the name of our subdirectory under /proc/scsi/ */
+	sprintf (local_name, "hpusbscsi-%d", desc->number);
+	sht->proc_name = kmalloc (strlen (local_name) + 1, GFP_KERNEL);
+	/* FIXME: where is this freed ? */
+
+	if (!sht->proc_name) {
+		return 0;
+	}
+
+	strcpy (sht->proc_name, local_name);
+
+	sht->proc_dir = NULL;
+
+	/* build and submit an interrupt URB for status byte handling */
+ 	FILL_INT_URB(desc->controlurb,
+			desc->dev,
+			usb_rcvintpipe(desc->dev,desc->ep_int),
+			&desc->scsi_state_byte,
+			1,
+			control_interrupt_callback,
+			desc,
+			desc->interrupt_interval
+	);
+
+	if ( 0  >  usb_submit_urb(desc->controlurb, GFP_KERNEL)) {
+		kfree(sht->proc_name);
+		return 0;
+	}
+
+	/* In host->hostdata we store a pointer to desc */
+	desc->host = scsi_register (sht, sizeof (desc));
+	if (desc->host == NULL) {
+		kfree (sht->proc_name);
+		usb_unlink_urb(desc->controlurb);
+		return 0;
+	}
+	desc->host->hostdata[0] = (unsigned long) desc;
+
+
+	return 1;
+}
+
+static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
+{
+	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
+	usb_urb_callback usb_callback;
+	int res;
+
+	hpusbscsi->use_count++;
+
+	/* we don't answer for anything but our single device on any faked host controller */
+	if ( srb->device->lun || srb->device->id || srb->device->channel ) {
+		if (callback) {
+			srb->result = DID_BAD_TARGET;
+			callback(srb);
+		}
+                	goto out;
+	}
+
+	/* Now we need to decide which callback to give to the urb we send the command with */
+
+	if (!srb->bufflen) {
+		if (srb->cmnd[0] == REQUEST_SENSE){
+			hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
+			usb_callback = request_sense_callback;
+		} else {
+			usb_callback = simple_command_callback;
+		}
+	} else {
+        	if (likely(srb->use_sg)) {
+			usb_callback = scatter_gather_callback;
+			hpusbscsi->fragment = 0;
+		} else {
+                	usb_callback = simple_payload_callback;
+		}
+		/* Now we find out which direction data is to be transfered in */
+		hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ?
+			usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in)
+		:
+			usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out)
+		;
+	}
+
+
+	TRACE_STATE;
+
+        /* We zero the sense buffer to avoid confusing user space */
+        memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+
+	hpusbscsi->state = HP_STATE_BEGINNING;
+	TRACE_STATE;
+
+	/* We prepare the urb for writing out the scsi command */
+	FILL_BULK_URB(
+		hpusbscsi->dataurb,
+		hpusbscsi->dev,
+		usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
+		srb->cmnd,
+		srb->cmd_len,
+		usb_callback,
+		hpusbscsi
+	);
+	hpusbscsi->scallback = callback;
+	hpusbscsi->srb = srb;
+
+	res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC);
+	if (unlikely(res)) {
+		hpusbscsi->state = HP_STATE_FREE;
+		TRACE_STATE;
+		if (likely(callback != NULL)) {
+			srb->result = DID_ERROR;
+			callback(srb);
+		}
+	}
+
+out:
+	hpusbscsi->use_count--;
+	return 0;
+}
+
+static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb)
+{
+	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
+
+	printk(KERN_DEBUG"SCSI reset requested.\n");
+	//usb_reset_device(hpusbscsi->dev);
+	//printk(KERN_DEBUG"SCSI reset completed.\n");
+	hpusbscsi->state = HP_STATE_FREE;
+
+	return 0;
+}
+
+static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
+{
+	struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->host->hostdata[0]);
+	printk(KERN_DEBUG"Requested is canceled.\n");
+
+	usb_unlink_urb(hpusbscsi->dataurb);
+	usb_unlink_urb(hpusbscsi->controlurb);
+	hpusbscsi->state = HP_STATE_FREE;
+
+	return SCSI_ABORT_PENDING;
+}
+
+/* usb interrupt handlers - they are all running IN INTERRUPT ! */
+
+static void handle_usb_error (struct hpusbscsi *hpusbscsi)
+{
+	if (likely(hpusbscsi->scallback != NULL)) {
+		hpusbscsi->srb->result = DID_ERROR;
+		hpusbscsi->scallback(hpusbscsi->srb);
+	}
+	hpusbscsi->state = HP_STATE_FREE;
+}
+
+static void  control_interrupt_callback (struct urb *u)
+{
+	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
+	u8 scsi_state;
+
+DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
+	if(unlikely(u->status < 0)) {
+                if (likely(hpusbscsi->state != HP_STATE_FREE))
+                        handle_usb_error(hpusbscsi);
+		return;
+	}
+
+	scsi_state = hpusbscsi->scsi_state_byte;
+	if (hpusbscsi->state != HP_STATE_ERROR) {
+		hpusbscsi->srb->result &= SCSI_ERR_MASK;
+		hpusbscsi->srb->result |= scsi_state;
+	}
+
+	if (scsi_state == CHECK_CONDITION << 1) {
+		if (hpusbscsi->state == HP_STATE_WAIT) {
+			issue_request_sense(hpusbscsi);
+		} else {
+			/* we request sense after an eventual data transfer */
+			hpusbscsi->state = HP_STATE_ERROR;
+		}
+	}
+
+	if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 )
+		/* we do a callback to the scsi layer if and only if all data has been transfered */
+		hpusbscsi->scallback(hpusbscsi->srb);
+
+	TRACE_STATE;
+	switch (hpusbscsi->state) {
+	case HP_STATE_WAIT:
+		hpusbscsi->state = HP_STATE_FREE;
+	TRACE_STATE;
+		break;
+	case HP_STATE_WORKING:
+	case HP_STATE_BEGINNING:
+		hpusbscsi->state = HP_STATE_PREMATURE;
+	TRACE_STATE;
+		break;
+	case HP_STATE_ERROR:
+		break;
+	default:
+		printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
+	TRACE_STATE;
+		hpusbscsi->state = HP_STATE_FREE;
+	TRACE_STATE;
+		break;
+	}
+}
+
+static void simple_command_callback(struct urb *u)
+{
+	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
+	if (unlikely(u->status<0)) {
+		handle_usb_error(hpusbscsi);
+		return;
+        }
+	TRACE_STATE;
+	if (hpusbscsi->state != HP_STATE_PREMATURE) {
+	        TRACE_STATE;
+		hpusbscsi->state = HP_STATE_WAIT;
+	} else {
+		if (likely(hpusbscsi->scallback != NULL))
+			hpusbscsi->scallback(hpusbscsi->srb);
+		hpusbscsi->state = HP_STATE_FREE;
+	TRACE_STATE;
+	}
+}
+
+static void scatter_gather_callback(struct urb *u)
+{
+	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
+        struct scatterlist *sg = hpusbscsi->srb->buffer;
+        usb_urb_callback callback;
+        int res;
+
+        DEBUG("Going through scatter/gather\n");
+        if (unlikely(u->status < 0)) {
+                handle_usb_error(hpusbscsi);
+                return;
+        }
+
+        if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg)
+                callback = scatter_gather_callback;
+        else
+                callback = simple_done;
+
+	TRACE_STATE;
+        if (hpusbscsi->state != HP_STATE_PREMATURE)
+		hpusbscsi->state = HP_STATE_WORKING;
+	TRACE_STATE;
+
+        FILL_BULK_URB(
+                u,
+                hpusbscsi->dev,
+                hpusbscsi->current_data_pipe,
+                page_address(sg[hpusbscsi->fragment].page) +
+		sg[hpusbscsi->fragment].offset,
+                sg[hpusbscsi->fragment++].length,
+                callback,
+                hpusbscsi
+        );
+
+        res = usb_submit_urb(u, GFP_ATOMIC);
+        if (unlikely(res))
+                handle_usb_error(hpusbscsi);
+	TRACE_STATE;
+}
+
+static void simple_done (struct urb *u)
+{
+	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
+
+        if (unlikely(u->status < 0)) {
+                handle_usb_error(hpusbscsi);
+                return;
+        }
+        DEBUG("Data transfer done\n");
+	TRACE_STATE;
+	if (hpusbscsi->state != HP_STATE_PREMATURE) {
+		if (unlikely(u->status < 0)) {
+			handle_usb_error(hpusbscsi);
+		} else {
+			if (hpusbscsi->state != HP_STATE_ERROR) {
+				hpusbscsi->state = HP_STATE_WAIT;
+			} else {
+				issue_request_sense(hpusbscsi);
+			}			
+		}
+	} else {
+		if (likely(hpusbscsi->scallback != NULL))
+			hpusbscsi->scallback(hpusbscsi->srb);
+		hpusbscsi->state = HP_STATE_FREE;
+	}
+}
+
+static void simple_payload_callback (struct urb *u)
+{
+	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
+	int res;
+
+	if (unlikely(u->status<0)) {
+                handle_usb_error(hpusbscsi);
+		return;
+        }
+
+	FILL_BULK_URB(
+		u,
+		hpusbscsi->dev,
+		hpusbscsi->current_data_pipe,
+		hpusbscsi->srb->buffer,
+		hpusbscsi->srb->bufflen,
+		simple_done,
+		hpusbscsi
+	);
+
+	res = usb_submit_urb(u, GFP_ATOMIC);
+	if (unlikely(res)) {
+                handle_usb_error(hpusbscsi);
+		return;
+        }
+	TRACE_STATE;
+	if (hpusbscsi->state != HP_STATE_PREMATURE) {
+		hpusbscsi->state = HP_STATE_WORKING;
+	TRACE_STATE;
+	} 
+}
+
+static void request_sense_callback (struct urb *u)
+{
+	struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
+
+	if (u->status<0) {
+                handle_usb_error(hpusbscsi);
+		return;
+        }
+
+	FILL_BULK_URB(
+		u,
+		hpusbscsi->dev,
+		hpusbscsi->current_data_pipe,
+		hpusbscsi->srb->sense_buffer,
+		SCSI_SENSE_BUFFERSIZE,
+		simple_done,
+		hpusbscsi
+	);
+
+	if (0 > usb_submit_urb(u, GFP_ATOMIC)) {
+		handle_usb_error(hpusbscsi);
+		return;
+	}
+	if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR)
+		hpusbscsi->state = HP_STATE_WORKING;
+}
+
+static void issue_request_sense (struct hpusbscsi *hpusbscsi)
+{
+	FILL_BULK_URB(
+		hpusbscsi->dataurb,
+		hpusbscsi->dev,
+		usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out),
+		&hpusbscsi->sense_command,
+		SENSE_COMMAND_SIZE,
+		request_sense_callback,
+		hpusbscsi
+	);
+
+	hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
+
+	if (0 > usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC)) {
+		handle_usb_error(hpusbscsi);
+	}
+}
+
diff -Nru a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/hpusbscsi.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,96 @@
+/* Header file for the hpusbscsi driver */
+/* (C) Copyright 2001 Oliver Neukum */
+/* sponsored by the Linux Usb Project */
+/* large parts based on or taken from code by John Fremlin and Matt Dharm */
+/* this file is licensed under the GPL */
+
+/* A big thanks to Jose for untiring testing */
+
+typedef void (*usb_urb_callback) (struct urb *);
+typedef void (*scsi_callback)(Scsi_Cmnd *);
+
+#define SENSE_COMMAND_SIZE 6
+#define HPUSBSCSI_SENSE_LENGTH 0x16
+
+struct hpusbscsi
+{
+        struct list_head lh;
+        struct usb_device *dev; /* NULL indicates unplugged device */
+        int ep_out;
+        int ep_in;
+        int ep_int;
+        int interrupt_interval;
+
+        struct Scsi_Host *host;
+        Scsi_Host_Template ctempl;
+        int number;
+	scsi_callback scallback;
+	Scsi_Cmnd *srb;
+	u8 sense_command[SENSE_COMMAND_SIZE];
+
+        int use_count;
+        wait_queue_head_t pending;
+        wait_queue_head_t deathrow;
+
+        struct urb *dataurb;
+        struct urb *controlurb;
+        int fragment;
+
+        int state;
+        int current_data_pipe;
+
+        u8 scsi_state_byte;
+};
+
+#define SCSI_ERR_MASK ~0x3fu
+
+static const unsigned char scsi_command_direction[256/8] = {
+	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
+	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
+
+static int hpusbscsi_scsi_detect (struct SHT * sht);
+static void simple_command_callback(struct urb *u);
+static void scatter_gather_callback(struct urb *u);
+static void simple_payload_callback (struct urb *u);
+static void request_sense_callback (struct urb *u);
+static void control_interrupt_callback (struct urb *u);
+static void simple_done (struct urb *u);
+static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
+static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
+static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
+static void issue_request_sense (struct hpusbscsi *hpusbscsi);
+
+static Scsi_Host_Template hpusbscsi_scsi_host_template = {
+	name:           "hpusbscsi",
+	detect:		hpusbscsi_scsi_detect,
+//	release:	hpusbscsi_scsi_release,
+	queuecommand:	hpusbscsi_scsi_queuecommand,
+
+	eh_abort_handler:	hpusbscsi_scsi_abort,
+	eh_host_reset_handler:	hpusbscsi_scsi_host_reset,
+
+	sg_tablesize:		SG_ALL,
+	can_queue:		1,
+	this_id:		-1,
+	cmd_per_lun:		1,
+	present:		0,
+	unchecked_isa_dma:	FALSE,
+	use_clustering:		TRUE,
+	emulated:		TRUE
+};
+
+/* defines for internal driver state */
+#define HP_STATE_FREE                 0  /*ready for next request */
+#define HP_STATE_BEGINNING      1  /*command being transfered */
+#define HP_STATE_WORKING         2  /* data transfer stage */
+#define HP_STATE_ERROR             3  /* error has been reported */
+#define HP_STATE_WAIT                 4  /* waiting for status transfer */
+#define HP_STATE_PREMATURE              5 /* status prematurely reported */
+
+
+
diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/mdc800.c	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,1029 @@
+/*
+ * copyright (C) 1999/2000 by Henning Zabel <henning@uni-paderborn.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ *	USB-Kernel Driver for the Mustek MDC800 Digital Camera
+ *	(c) 1999/2000 Henning Zabel <henning@uni-paderborn.de>
+ *
+ *
+ * The driver brings the USB functions of the MDC800 to Linux.
+ * To use the Camera you must support the USB Protocoll of the camera
+ * to the Kernel Node.
+ * The Driver uses a misc device Node. Create it with :
+ * mknod /dev/mustek c 180 32
+ *
+ * The driver supports only one camera.
+ * 
+ * Fix: mdc800 used sleep_on and slept with io_lock held.
+ * Converted sleep_on to waitqueues with schedule_timeout and made io_lock
+ * a semaphore from a spinlock.
+ * by Oliver Neukum <520047054719-0001@t-online.de>
+ * (02/12/2001)
+ * 
+ * Identify version on module load.
+ * (08/04/2001) gb
+ *
+ * version 0.7.5
+ * Fixed potential SMP races with Spinlocks.
+ * Thanks to Oliver Neukum <oliver.neukum@lrz.uni-muenchen.de> who 
+ * noticed the race conditions.
+ * (30/10/2000)
+ *
+ * Fixed: Setting urb->dev before submitting urb.
+ * by Greg KH <greg@kroah.com>
+ * (13/10/2000)
+ *
+ * version 0.7.3
+ * bugfix : The mdc800->state field gets set to READY after the
+ * the diconnect function sets it to NOT_CONNECTED. This makes the
+ * driver running like the camera is connected and causes some
+ * hang ups.
+ *
+ * version 0.7.1
+ * MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload
+ * problems when compiled as Module.
+ * (04/04/2000)
+ *
+ * The mdc800 driver gets assigned the USB Minor 32-47. The Registration
+ * was updated to use these values.
+ * (26/03/2000)
+ *
+ * The Init und Exit Module Function are updated.
+ * (01/03/2000)
+ *
+ * version 0.7.0
+ * Rewrite of the driver : The driver now uses URB's. The old stuff
+ * has been removed.
+ *
+ * version 0.6.0
+ * Rewrite of this driver: The Emulation of the rs232 protocoll
+ * has been removed from the driver. A special executeCommand function
+ * for this driver is included to gphoto.
+ * The driver supports two kind of communication to bulk endpoints.
+ * Either with the dev->bus->ops->bulk... or with callback function.
+ * (09/11/1999)
+ *
+ * version 0.5.0:
+ * first Version that gets a version number. Most of the needed
+ * functions work.
+ * (20/10/1999)
+ */
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+
+#include <linux/usb.h>
+#include <linux/fs.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.7.5 (30/10/2000)"
+#define DRIVER_AUTHOR "Henning Zabel <henning@uni-paderborn.de>"
+#define DRIVER_DESC "USB Driver for Mustek MDC800 Digital Camera"
+
+/* Vendor and Product Information */
+#define MDC800_VENDOR_ID 	0x055f
+#define MDC800_PRODUCT_ID	0xa800
+
+/* Timeouts (msec) */
+#define TO_DOWNLOAD_GET_READY		1500
+#define TO_DOWNLOAD_GET_BUSY		1500
+#define TO_WRITE_GET_READY		1000
+#define TO_DEFAULT_COMMAND		5000
+#define TO_READ_FROM_IRQ 		TO_DEFAULT_COMMAND
+#define TO_GET_READY			TO_DEFAULT_COMMAND
+
+/* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
+#define MDC800_DEVICE_MINOR_BASE 32
+
+
+/**************************************************************************
+	Data and structs
+***************************************************************************/
+
+
+typedef enum {
+	NOT_CONNECTED, READY, WORKING, DOWNLOAD
+} mdc800_state;
+
+
+/* Data for the driver */
+struct mdc800_data
+{
+	struct usb_device *	dev;			// Device Data
+	mdc800_state 		state;
+
+	unsigned int		endpoint [4];
+
+	struct urb *		irq_urb;
+	wait_queue_head_t	irq_wait;
+	int			irq_woken;
+	char*			irq_urb_buffer;
+
+	int			camera_busy;          // is camera busy ?
+	int 			camera_request_ready; // Status to synchronize with irq
+	char 			camera_response [8];  // last Bytes send after busy
+
+	struct urb *   		write_urb;
+	char*			write_urb_buffer;
+	wait_queue_head_t	write_wait;
+	int			written;
+
+
+	struct urb *   		download_urb;
+	char*			download_urb_buffer;
+	wait_queue_head_t	download_wait;
+	int			downloaded;
+	int			download_left;		// Bytes left to download ?
+
+
+	/* Device Data */
+	char			out [64];	// Answer Buffer
+	int 			out_ptr;	// Index to the first not readen byte
+	int			out_count;	// Bytes in the buffer
+
+	int			open;		// Camera device open ?
+	struct semaphore	io_lock;	// IO -lock
+
+	char 			in [8];		// Command Input Buffer
+	int  			in_count;
+
+	int			pic_index;	// Cache for the Imagesize (-1 for nothing cached )
+	int			pic_len;
+};
+
+
+/* Specification of the Endpoints */
+static struct usb_endpoint_descriptor mdc800_ed [4] =
+{
+	{ 0,0, 0x01, 0x02,  8, 0,0,0 },
+	{ 0,0, 0x82, 0x03,  8, 0,0,0 },
+	{ 0,0, 0x03, 0x02, 64, 0,0,0 },
+	{ 0,0, 0x84, 0x02, 64, 0,0,0 }
+};
+
+
+/* The Variable used by the driver */
+static struct mdc800_data* mdc800=0;
+
+
+/***************************************************************************
+	The USB Part of the driver
+****************************************************************************/
+
+static int mdc800_endpoint_equals (struct usb_endpoint_descriptor *a,struct usb_endpoint_descriptor *b)
+{
+	return (
+		   ( a->bEndpointAddress == b->bEndpointAddress )
+		&& ( a->bmAttributes     == b->bmAttributes     )
+		&& ( a->wMaxPacketSize   == b->wMaxPacketSize   )
+	);
+}
+
+
+/*
+ * Checks wether the camera responds busy
+ */
+static int mdc800_isBusy (char* ch)
+{
+	int i=0;
+	while (i<8)
+	{
+		if (ch [i] != (char)0x99)
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
+
+/*
+ * Checks wether the Camera is ready
+ */
+static int mdc800_isReady (char *ch)
+{
+	int i=0;
+	while (i<8)
+	{
+		if (ch [i] != (char)0xbb)
+			return 0;
+		i++;
+	}
+	return 1;
+}
+
+
+
+/*
+ * USB IRQ Handler for InputLine
+ */
+static void mdc800_usb_irq (struct urb *urb)
+{
+	int data_received=0, wake_up;
+	unsigned char* b=urb->transfer_buffer;
+	struct mdc800_data* mdc800=urb->context;
+
+	if (urb->status >= 0)
+	{
+
+		//dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
+
+		if (mdc800_isBusy (b))
+		{
+			if (!mdc800->camera_busy)
+			{
+				mdc800->camera_busy=1;
+				dbg ("gets busy");
+			}
+		}
+		else
+		{
+			if (mdc800->camera_busy && mdc800_isReady (b))
+			{
+				mdc800->camera_busy=0;
+				dbg ("gets ready");
+			}
+		}
+		if (!(mdc800_isBusy (b) || mdc800_isReady (b)))
+		{
+			/* Store Data in camera_answer field */
+			dbg ("%i %i %i %i %i %i %i %i ",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
+
+			memcpy (mdc800->camera_response,b,8);
+			data_received=1;
+		}
+	}
+	wake_up= ( mdc800->camera_request_ready > 0 )
+		&&
+		(
+			((mdc800->camera_request_ready == 1) && (!mdc800->camera_busy))
+		||
+			((mdc800->camera_request_ready == 2) && data_received)
+		||
+			((mdc800->camera_request_ready == 3) && (mdc800->camera_busy))
+		||
+			(urb->status < 0)
+		);
+
+	if (wake_up)
+	{
+		mdc800->camera_request_ready=0;
+		mdc800->irq_woken=1;
+		wake_up_interruptible (&mdc800->irq_wait);
+	}
+}
+
+
+/*
+ * Waits a while until the irq responds that camera is ready
+ *
+ *  mode : 0: Wait for camera gets ready
+ *         1: Wait for receiving data
+ *         2: Wait for camera gets busy
+ *
+ * msec: Time to wait
+ */
+static int mdc800_usb_waitForIRQ (int mode, int msec)
+{
+        DECLARE_WAITQUEUE(wait, current);
+
+	mdc800->camera_request_ready=1+mode;
+
+	add_wait_queue(&mdc800->irq_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (!mdc800->irq_woken)
+	{
+		schedule_timeout (msec*HZ/1000);
+	}
+        remove_wait_queue(&mdc800->irq_wait, &wait);
+	set_current_state(TASK_RUNNING);
+	mdc800->irq_woken = 0;
+
+	if (mdc800->camera_request_ready>0)
+	{
+		mdc800->camera_request_ready=0;
+		err ("timeout waiting for camera.");
+		return -1;
+	}
+	
+	if (mdc800->state == NOT_CONNECTED)
+	{
+		warn ("Camera gets disconnected during waiting for irq.");
+		mdc800->camera_request_ready=0;
+		return -2;
+	}
+	
+	return 0;
+}
+
+
+/*
+ * The write_urb callback function
+ */
+static void mdc800_usb_write_notify (struct urb *urb)
+{
+	struct mdc800_data* mdc800=urb->context;
+
+	if (urb->status != 0)
+	{
+		err ("writing command fails (status=%i)", urb->status);
+	}
+	else
+	{	
+		mdc800->state=READY;
+	}
+	mdc800->written = 1;
+	wake_up_interruptible (&mdc800->write_wait);
+}
+
+
+/*
+ * The download_urb callback function
+ */
+static void mdc800_usb_download_notify (struct urb *urb)
+{
+	struct mdc800_data* mdc800=urb->context;
+
+	if (urb->status == 0)
+	{
+		/* Fill output buffer with these data */
+		memcpy (mdc800->out,  urb->transfer_buffer, 64);
+		mdc800->out_count=64;
+		mdc800->out_ptr=0;
+		mdc800->download_left-=64;
+		if (mdc800->download_left == 0)
+		{
+			mdc800->state=READY;
+		}
+	}
+	else
+	{
+		err ("request bytes fails (status:%i)", urb->status);
+	}
+	mdc800->downloaded = 1;
+	wake_up_interruptible (&mdc800->download_wait);
+}
+
+
+/***************************************************************************
+	Probing for the Camera
+ ***************************************************************************/
+
+static struct usb_driver mdc800_usb_driver;
+
+/*
+ * Callback to search the Mustek MDC800 on the USB Bus
+ */
+static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum,
+			       const struct usb_device_id *id)
+{
+	int i,j;
+	struct usb_interface_descriptor	*intf_desc;
+	int irq_interval=0;
+
+	dbg ("(mdc800_usb_probe) called.");
+
+
+	if (mdc800->dev != 0)
+	{
+		warn ("only one Mustek MDC800 is supported.");
+		return 0;
+	}
+
+	if (dev->descriptor.bNumConfigurations != 1)
+	{
+		err ("probe fails -> wrong Number of Configuration");
+		return 0;
+	}
+	intf_desc=&dev->actconfig->interface[ifnum].altsetting[0];
+
+	if (
+			( intf_desc->bInterfaceClass != 0xff )
+		||	( intf_desc->bInterfaceSubClass != 0 )
+		|| ( intf_desc->bInterfaceProtocol != 0 )
+		|| ( intf_desc->bNumEndpoints != 4)
+	)
+	{
+		err ("probe fails -> wrong Interface");
+		return 0;
+	}
+
+	/* Check the Endpoints */
+	for (i=0; i<4; i++)
+	{
+		mdc800->endpoint[i]=-1;
+		for (j=0; j<4; j++)
+		{
+			if (mdc800_endpoint_equals (&intf_desc->endpoint [j],&mdc800_ed [i]))
+			{
+				mdc800->endpoint[i]=intf_desc->endpoint [j].bEndpointAddress ;
+				if (i==1)
+				{
+					irq_interval=intf_desc->endpoint [j].bInterval;
+				}
+
+				continue;
+			}
+		}
+		if (mdc800->endpoint[i] == -1)
+		{
+			err ("probe fails -> Wrong Endpoints.");
+			return 0;
+		}
+	}
+
+
+	usb_driver_claim_interface (&mdc800_usb_driver, &dev->actconfig->interface[ifnum], mdc800);
+	if (usb_set_interface (dev, ifnum, 0) < 0)
+	{
+		err ("MDC800 Configuration fails.");
+		return 0;
+	}
+
+	info ("Found Mustek MDC800 on USB.");
+
+	down (&mdc800->io_lock);
+
+	mdc800->dev=dev;
+	mdc800->open=0;
+
+	/* Setup URB Structs */
+	FILL_INT_URB (
+		mdc800->irq_urb,
+		mdc800->dev,
+		usb_rcvintpipe (mdc800->dev,mdc800->endpoint [1]),
+		mdc800->irq_urb_buffer,
+		8,
+		mdc800_usb_irq,
+		mdc800,
+		irq_interval
+	);
+
+	FILL_BULK_URB (
+		mdc800->write_urb,
+		mdc800->dev,
+		usb_sndbulkpipe (mdc800->dev, mdc800->endpoint[0]),
+		mdc800->write_urb_buffer,
+		8,
+		mdc800_usb_write_notify,
+		mdc800
+	);
+
+	FILL_BULK_URB (
+		mdc800->download_urb,
+		mdc800->dev,
+		usb_rcvbulkpipe (mdc800->dev, mdc800->endpoint [3]),
+		mdc800->download_urb_buffer,
+		64,
+		mdc800_usb_download_notify,
+		mdc800
+	);
+
+	mdc800->state=READY;
+
+	up (&mdc800->io_lock);
+	
+	return mdc800;
+}
+
+
+/*
+ * Disconnect USB device (maybe the MDC800)
+ */
+static void mdc800_usb_disconnect (struct usb_device *dev,void* ptr)
+{
+	struct mdc800_data* mdc800=(struct mdc800_data*) ptr;
+
+	dbg ("(mdc800_usb_disconnect) called");
+
+	if (mdc800->state == NOT_CONNECTED)
+		return;
+	
+	mdc800->state=NOT_CONNECTED;
+
+	usb_unlink_urb (mdc800->irq_urb);
+	usb_unlink_urb (mdc800->write_urb);
+	usb_unlink_urb (mdc800->download_urb);
+
+	usb_driver_release_interface (&mdc800_usb_driver, &dev->actconfig->interface[1]);
+
+	mdc800->dev=0;
+	info ("Mustek MDC800 disconnected from USB.");
+}
+
+
+/***************************************************************************
+	The Misc device Part (file_operations)
+****************************************************************************/
+
+/*
+ * This Function calc the Answersize for a command.
+ */
+static int mdc800_getAnswerSize (char command)
+{
+	switch ((unsigned char) command)
+	{
+		case 0x2a:
+		case 0x49:
+		case 0x51:
+		case 0x0d:
+		case 0x20:
+		case 0x07:
+		case 0x01:
+		case 0x25:
+		case 0x00:
+			return 8;
+
+		case 0x05:
+		case 0x3e:
+			return mdc800->pic_len;
+
+		case 0x09:
+			return 4096;
+
+		default:
+			return 0;
+	}
+}
+
+
+/*
+ * Init the device: (1) alloc mem (2) Increase MOD Count ..
+ */
+static int mdc800_device_open (struct inode* inode, struct file *file)
+{
+	int retval=0;
+	int errn=0;
+
+	down (&mdc800->io_lock);
+	
+	if (mdc800->state == NOT_CONNECTED)
+	{
+		errn=-EBUSY;
+		goto error_out;
+	}
+	if (mdc800->open)
+	{
+		errn=-EBUSY;
+		goto error_out;
+	}
+
+	mdc800->in_count=0;
+	mdc800->out_count=0;
+	mdc800->out_ptr=0;
+	mdc800->pic_index=0;
+	mdc800->pic_len=-1;
+	mdc800->download_left=0;
+
+	mdc800->camera_busy=0;
+	mdc800->camera_request_ready=0;
+
+	retval=0;
+	mdc800->irq_urb->dev = mdc800->dev;
+	if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL))
+	{
+		err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
+		errn = -EIO;
+		goto error_out;
+	}
+
+	mdc800->open=1;
+	dbg ("Mustek MDC800 device opened.");
+
+error_out:
+	up (&mdc800->io_lock);
+	return errn;
+}
+
+
+/*
+ * Close the Camera and release Memory
+ */
+static int mdc800_device_release (struct inode* inode, struct file *file)
+{
+	int retval=0;
+	dbg ("Mustek MDC800 device closed.");
+
+	down (&mdc800->io_lock);
+	if (mdc800->open && (mdc800->state != NOT_CONNECTED))
+	{
+		usb_unlink_urb (mdc800->irq_urb);
+		usb_unlink_urb (mdc800->write_urb);
+		usb_unlink_urb (mdc800->download_urb);
+		mdc800->open=0;
+	}
+	else
+	{
+		retval=-EIO;
+	}
+
+	up(&mdc800->io_lock);
+	return retval;
+}
+
+
+/*
+ * The Device read callback Function
+ */
+static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos)
+{
+	int   left=len, sts=len; /* single transfer size */
+	char* ptr=buf;
+	DECLARE_WAITQUEUE(wait, current);
+
+	down (&mdc800->io_lock);
+	if (mdc800->state == NOT_CONNECTED)
+	{
+		up (&mdc800->io_lock);
+		return -EBUSY;
+	}
+	if (mdc800->state == WORKING)
+	{
+		warn ("Illegal State \"working\" reached during read ?!");
+		up (&mdc800->io_lock);
+		return -EBUSY;
+	}
+	if (!mdc800->open)
+	{
+		up (&mdc800->io_lock);
+		return -EBUSY;
+	}
+
+	while (left)
+	{
+		if (signal_pending (current)) 
+		{
+			up (&mdc800->io_lock);
+			return -EINTR;
+		}
+
+		sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left;
+
+		if (sts <= 0)
+		{
+			/* Too less Data in buffer */
+			if (mdc800->state == DOWNLOAD)
+			{
+				mdc800->out_count=0;
+				mdc800->out_ptr=0;
+
+				/* Download -> Request new bytes */
+				mdc800->download_urb->dev = mdc800->dev;
+				if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))
+				{
+					err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
+					up (&mdc800->io_lock);
+					return len-left;
+				}
+				add_wait_queue(&mdc800->download_wait, &wait);
+				set_current_state(TASK_INTERRUPTIBLE);
+				if (!mdc800->downloaded)
+				{
+					schedule_timeout (TO_DOWNLOAD_GET_READY*HZ/1000);
+				}
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&mdc800->download_wait, &wait);
+				mdc800->downloaded = 0;
+				if (mdc800->download_urb->status != 0)
+				{
+					err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
+					up (&mdc800->io_lock);
+					return len-left;
+				}
+			}
+			else
+			{
+				/* No more bytes -> that's an error*/
+				up (&mdc800->io_lock);
+				return -EIO;
+			}
+		}
+		else
+		{
+			/* memcpy Bytes */
+			memcpy (ptr, &mdc800->out [mdc800->out_ptr], sts);
+			ptr+=sts;
+			left-=sts;
+			mdc800->out_ptr+=sts;
+		}
+	}
+
+	up (&mdc800->io_lock);
+	return len-left;
+}
+
+
+/*
+ * The Device write callback Function
+ * If a 8Byte Command is received, it will be send to the camera.
+ * After this the driver initiates the request for the answer or
+ * just waits until the camera becomes ready.
+ */
+static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
+{
+	int i=0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	down (&mdc800->io_lock);
+	if (mdc800->state != READY)
+	{
+		up (&mdc800->io_lock);
+		return -EBUSY;
+	}
+	if (!mdc800->open )
+	{
+		up (&mdc800->io_lock);
+		return -EBUSY;
+	}
+
+	while (i<len)
+	{
+		if (signal_pending (current)) 
+		{
+			up (&mdc800->io_lock);
+			return -EINTR;
+		}
+
+		/* check for command start */
+		if (buf [i] == (char) 0x55)
+		{
+			mdc800->in_count=0;
+			mdc800->out_count=0;
+			mdc800->out_ptr=0;
+			mdc800->download_left=0;
+		}
+
+		/* save command byte */
+		if (mdc800->in_count < 8)
+		{
+			mdc800->in[mdc800->in_count]=buf[i];
+			mdc800->in_count++;
+		}
+		else
+		{
+			err ("Command is to long !\n");
+			up (&mdc800->io_lock);
+			return -EIO;
+		}
+
+		/* Command Buffer full ? -> send it to camera */
+		if (mdc800->in_count == 8)
+		{
+			int answersize;
+
+			if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
+			{
+				err ("Camera didn't get ready.\n");
+				up (&mdc800->io_lock);
+				return -EIO;
+			}
+
+			answersize=mdc800_getAnswerSize (mdc800->in[1]);
+
+			mdc800->state=WORKING;
+			memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);
+			mdc800->write_urb->dev = mdc800->dev;
+			if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))
+			{
+				err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
+				up (&mdc800->io_lock);
+				return -EIO;
+			}
+			add_wait_queue(&mdc800->write_wait, &wait);
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!mdc800->written)
+			{
+				schedule_timeout (TO_WRITE_GET_READY*HZ/1000);
+			}
+                        set_current_state(TASK_RUNNING);
+			remove_wait_queue(&mdc800->write_wait, &wait);
+			mdc800->written = 0;
+			if (mdc800->state == WORKING)
+			{
+				usb_unlink_urb (mdc800->write_urb);
+				up (&mdc800->io_lock);
+				return -EIO;
+			}
+
+			switch ((unsigned char) mdc800->in[1])
+			{
+				case 0x05: /* Download Image */
+				case 0x3e: /* Take shot in Fine Mode (WCam Mode) */
+					if (mdc800->pic_len < 0)
+					{
+						err ("call 0x07 before 0x05,0x3e");
+						mdc800->state=READY;
+						up (&mdc800->io_lock);
+						return -EIO;
+					}
+					mdc800->pic_len=-1;
+
+				case 0x09: /* Download Thumbnail */
+					mdc800->download_left=answersize+64;
+					mdc800->state=DOWNLOAD;
+					mdc800_usb_waitForIRQ (0,TO_DOWNLOAD_GET_BUSY);
+					break;
+
+
+				default:
+					if (answersize)
+					{
+
+						if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
+						{
+							err ("requesting answer from irq fails");
+							up (&mdc800->io_lock);
+							return -EIO;
+						}
+
+						/* Write dummy data, (this is ugly but part of the USB Protokoll */
+						/* if you use endpoint 1 as bulk and not as irq */
+						memcpy (mdc800->out, mdc800->camera_response,8);
+
+						/* This is the interpreted answer */
+						memcpy (&mdc800->out[8], mdc800->camera_response,8);
+
+						mdc800->out_ptr=0;
+						mdc800->out_count=16;
+
+						/* Cache the Imagesize, if command was getImageSize */
+						if (mdc800->in [1] == (char) 0x07)
+						{
+							mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2];
+
+							dbg ("cached imagesize = %i",mdc800->pic_len);
+						}
+
+					}
+					else
+					{
+						if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
+						{
+							err ("Command Timeout.");
+							up (&mdc800->io_lock);
+							return -EIO;
+						}
+					}
+					mdc800->state=READY;
+					break;
+			}
+		}
+		i++;
+	}
+	up (&mdc800->io_lock);
+	return i;
+}
+
+
+/***************************************************************************
+	Init and Cleanup this driver (Structs and types)
+****************************************************************************/
+
+/* File Operations of this drivers */
+static struct file_operations mdc800_device_ops =
+{
+	owner:		THIS_MODULE,
+	read:		mdc800_device_read,
+	write:		mdc800_device_write,
+	open:		mdc800_device_open,
+	release:	mdc800_device_release,
+};
+
+
+
+static struct usb_device_id mdc800_table [] = {
+	{ USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, mdc800_table);
+/*
+ * USB Driver Struct for this device
+ */
+static struct usb_driver mdc800_usb_driver =
+{
+	name:		"mdc800",
+	probe:		mdc800_usb_probe,
+	disconnect:	mdc800_usb_disconnect,
+	fops:		&mdc800_device_ops,
+	minor:		MDC800_DEVICE_MINOR_BASE,
+	id_table:	mdc800_table
+};
+
+
+
+/************************************************************************
+	Init and Cleanup this driver (Main Functions)
+*************************************************************************/
+
+#define try(A)           if ((A) == 0) goto cleanup_on_fail;
+#define try_free_mem(A)  if (A != 0) { kfree (A); A=0; }
+#define try_free_urb(A)  if (A != 0) { usb_free_urb (A); A=0; }
+
+int __init usb_mdc800_init (void)
+{
+	/* Allocate Memory */
+	try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
+
+	memset(mdc800, 0, sizeof(struct mdc800_data));
+	mdc800->dev=0;
+	mdc800->open=0;
+	mdc800->state=NOT_CONNECTED;
+	init_MUTEX (&mdc800->io_lock);
+
+	init_waitqueue_head (&mdc800->irq_wait);
+	init_waitqueue_head (&mdc800->write_wait);
+	init_waitqueue_head (&mdc800->download_wait);
+
+	mdc800->irq_woken = 0;
+	mdc800->downloaded = 0;
+	mdc800->written = 0;
+
+	try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
+	try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
+	try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
+
+	try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
+	try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
+	try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
+
+	/* Register the driver */
+	if (usb_register (&mdc800_usb_driver) < 0)
+		goto cleanup_on_fail;
+
+	info (DRIVER_VERSION ":" DRIVER_DESC);
+
+	return 0;
+
+	/* Clean driver up, when something fails */
+
+cleanup_on_fail:
+
+	if (mdc800 != 0)
+	{
+		err ("can't alloc memory!");
+
+		try_free_mem (mdc800->download_urb_buffer);
+		try_free_mem (mdc800->write_urb_buffer);
+		try_free_mem (mdc800->irq_urb_buffer);
+
+		try_free_urb (mdc800->write_urb);
+		try_free_urb (mdc800->download_urb);
+		try_free_urb (mdc800->irq_urb);
+
+		kfree (mdc800);
+	}
+	mdc800=0;
+	return -1;
+}
+
+
+void __exit usb_mdc800_cleanup (void)
+{
+	usb_deregister (&mdc800_usb_driver);
+
+	usb_free_urb (mdc800->irq_urb);
+	usb_free_urb (mdc800->download_urb);
+	usb_free_urb (mdc800->write_urb);
+
+	kfree (mdc800->irq_urb_buffer);
+	kfree (mdc800->write_urb_buffer);
+	kfree (mdc800->download_urb_buffer);
+
+	kfree (mdc800);
+	mdc800=0;
+}
+
+module_init (usb_mdc800_init);
+module_exit (usb_mdc800_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/microtek.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,1065 @@
+/* Driver for Microtek Scanmaker X6 USB scanner, and possibly others.
+ *
+ * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com>
+ * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
+ *
+ * Parts shamelessly stolen from usb-storage and copyright by their
+ * authors. Thanks to Matt Dharm for giving us permission!
+ *
+ * This driver implements a SCSI host controller driver and a USB
+ * device driver. To avoid confusion, all the USB related stuff is
+ * prefixed by mts_usb_ and all the SCSI stuff by mts_scsi_.
+ *
+ * Microtek (www.microtek.com) did not release the specifications for
+ * their USB protocol to us, so we had to reverse engineer them. We
+ * don't know for which models they are valid.
+ *
+ * The X6 USB has three bulk endpoints, one output (0x1) down which
+ * commands and outgoing data are sent, and two input: 0x82 from which
+ * normal data is read from the scanner (in packets of maximum 32
+ * bytes) and from which the status byte is read, and 0x83 from which
+ * the results of a scan (or preview) are read in up to 64 * 1024 byte
+ * chunks by the Windows driver. We don't know how much it is possible
+ * to read at a time from 0x83.
+ *
+ * It seems possible to read (with URB transfers) everything from 0x82
+ * in one go, without bothering to read in 32 byte chunks.
+ *
+ * There seems to be an optimisation of a further READ implicit if
+ * you simply read from 0x83.
+ *
+ * Guessed protocol:
+ *
+ *	Send raw SCSI command to EP 0x1
+ *
+ *	If there is data to receive:
+ *		If the command was READ datatype=image:
+ *			Read a lot of data from EP 0x83
+ *		Else:
+ *			Read data from EP 0x82
+ *	Else:
+ *		If there is data to transmit:
+ *			Write it to EP 0x1
+ *
+ *	Read status byte from EP 0x82
+ *
+ * References:
+ *
+ * The SCSI command set for the scanner is available from
+ *	ftp://ftp.microtek.com/microtek/devpack/
+ *
+ * Microtek NV sent us a more up to date version of the document. If
+ * you want it, just send mail.
+ *
+ * Status:
+ *
+ *	Untested with multiple scanners.
+ *	Untested on SMP.
+ *	Untested on a bigendian machine.
+ *
+ * History:
+ *
+ *	20000417 starting history
+ *	20000417 fixed load oops
+ *	20000417 fixed unload oops
+ *	20000419 fixed READ IMAGE detection
+ *	20000424 started conversion to use URBs
+ *	20000502 handled short transfers as errors
+ *	20000513 rename and organisation of functions (john)
+ *	20000513 added IDs for all products supported by Windows driver (john)
+ *	20000514 Rewrote mts_scsi_queuecommand to use URBs (john)
+ *	20000514 Version 0.0.8j
+ *      20000514 Fix reporting of non-existant devices to SCSI layer (john)
+ *	20000514 Added MTS_DEBUG_INT (john)
+ *	20000514 Changed "usb-microtek" to "microtek" for consistency (john)
+ *	20000514 Stupid bug fixes (john)
+ *	20000514 Version 0.0.9j
+ *	20000515 Put transfer context and URB in mts_desc (john)
+ *	20000515 Added prelim turn off debugging support (john)
+ *	20000515 Version 0.0.10j
+ *      20000515 Fixed up URB allocation (clear URB on alloc) (john)
+ *      20000515 Version 0.0.11j
+ *	20000516 Removed unnecessary spinlock in mts_transfer_context (john)
+ *	20000516 Removed unnecessary up on instance lock in mts_remove_nolock (john)
+ *	20000516 Implemented (badly) scsi_abort (john)
+ *	20000516 Version 0.0.12j
+ *      20000517 Hopefully removed mts_remove_nolock quasideadlock (john)
+ *      20000517 Added mts_debug_dump to print ll USB info (john)
+ *	20000518 Tweaks and documentation updates (john)
+ *	20000518 Version 0.0.13j
+ *	20000518 Cleaned up abort handling (john)
+ *	20000523 Removed scsi_command and various scsi_..._resets (john)
+ *	20000523 Added unlink URB on scsi_abort, now OHCI supports it (john)
+ *	20000523 Fixed last tiresome compile warning (john)
+ *	20000523 Version 0.0.14j (though version 0.1 has come out?)
+ *	20000602 Added primitive reset
+ *	20000602 Version 0.2.0
+ *	20000603 various cosmetic changes
+ *	20000603 Version 0.2.1
+ *	20000620 minor cosmetic changes
+ *	20000620 Version 0.2.2
+ *	20000822 Hopefully fixed deadlock in mts_remove_nolock()
+ *	20000822 Fixed minor race in mts_transfer_cleanup()
+ *	20000822 Fixed deadlock on submission error in queuecommand
+ *	20000822 Version 0.2.3
+ *	20000913 Reduced module size if debugging is off
+ *	20000913 Version 0.2.4
+ *      20010210 New abort logic
+ *      20010210 Version 0.3.0
+ *	20010217 Merged scatter/gather
+ *	20010218 Version 0.4.0
+ *	20010218 Cosmetic fixes
+ *	20010218 Version 0.4.1
+ *      20010306 Abort while using scatter/gather
+ *      20010306 Version 0.4.2
+ *      20010311 Remove all timeouts and tidy up generally (john)
+ *	20010320 check return value of scsi_register()
+ *	20010320 Version 0.4.3
+ *	20010408 Identify version on module load.
+ *	20011003 Fix multiple requests
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/usb.h>
+#include <linux/proc_fs.h>
+
+#include <asm/atomic.h>
+#include <linux/blk.h>
+#include "../../scsi/scsi.h"
+#include "../../scsi/hosts.h"
+#include "../../scsi/sd.h"
+
+#include "microtek.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.4.3"
+#define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"
+#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
+
+/* Should we do debugging? */
+
+//#define MTS_DO_DEBUG
+
+/* USB layer driver interface */
+
+static void *mts_usb_probe(struct usb_device *dev, unsigned int interface,
+			 const struct usb_device_id *id);
+static void mts_usb_disconnect(struct usb_device *dev, void *ptr);
+
+static struct usb_device_id mts_usb_ids [];
+
+static struct usb_driver mts_usb_driver = {
+	name:		"microtekX6",
+	probe:		mts_usb_probe,
+	disconnect:	mts_usb_disconnect,
+	id_table:	mts_usb_ids,
+};
+
+
+/* Internal driver stuff */
+
+#define MTS_VERSION	"0.4.3"
+#define MTS_NAME	"microtek usb (rev " MTS_VERSION "): "
+
+#define MTS_WARNING(x...) \
+	printk( KERN_WARNING MTS_NAME x )
+#define MTS_ERROR(x...) \
+	printk( KERN_ERR MTS_NAME x )
+#define MTS_INT_ERROR(x...) \
+	MTS_ERROR(x)
+#define MTS_MESSAGE(x...) \
+	printk( KERN_INFO MTS_NAME x )
+
+#if defined MTS_DO_DEBUG
+
+#define MTS_DEBUG(x...) \
+	printk( KERN_DEBUG MTS_NAME x )
+
+#define MTS_DEBUG_GOT_HERE() \
+	MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
+#define MTS_DEBUG_INT() \
+	do { MTS_DEBUG_GOT_HERE(); \
+	     MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
+	     MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
+             mts_debug_dump(context->instance);\
+	   } while(0)
+#else
+
+#define MTS_NUL_STATEMENT do { } while(0)
+
+#define MTS_DEBUG(x...)	MTS_NUL_STATEMENT
+#define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT
+#define MTS_DEBUG_INT() MTS_NUL_STATEMENT
+
+#endif
+
+
+
+#define MTS_INT_INIT()\
+	struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context; \
+	MTS_DEBUG_INT();\
+
+#ifdef MTS_DO_DEBUG
+
+static inline void mts_debug_dump(struct mts_desc* desc) {
+	MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n",
+		  (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
+		  (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
+		);
+	MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
+		  usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
+		  usb_rcvbulkpipe(desc->usb_dev,desc->ep_response),
+		  usb_rcvbulkpipe(desc->usb_dev,desc->ep_image)
+		);
+}
+
+
+static inline void mts_show_command(Scsi_Cmnd *srb)
+{
+	char *what = NULL;
+
+	switch (srb->cmnd[0]) {
+	case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
+	case REZERO_UNIT: what = "REZERO_UNIT"; break;
+	case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
+	case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
+	case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
+	case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
+	case READ_6: what = "READ_6"; break;
+	case WRITE_6: what = "WRITE_6"; break;
+	case SEEK_6: what = "SEEK_6"; break;
+	case READ_REVERSE: what = "READ_REVERSE"; break;
+	case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
+	case SPACE: what = "SPACE"; break;
+	case INQUIRY: what = "INQUIRY"; break;
+	case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
+	case MODE_SELECT: what = "MODE_SELECT"; break;
+	case RESERVE: what = "RESERVE"; break;
+	case RELEASE: what = "RELEASE"; break;
+	case COPY: what = "COPY"; break;
+	case ERASE: what = "ERASE"; break;
+	case MODE_SENSE: what = "MODE_SENSE"; break;
+	case START_STOP: what = "START_STOP"; break;
+	case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
+	case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
+	case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
+	case SET_WINDOW: what = "SET_WINDOW"; break;
+	case READ_CAPACITY: what = "READ_CAPACITY"; break;
+	case READ_10: what = "READ_10"; break;
+	case WRITE_10: what = "WRITE_10"; break;
+	case SEEK_10: what = "SEEK_10"; break;
+	case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
+	case VERIFY: what = "VERIFY"; break;
+	case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
+	case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
+	case SEARCH_LOW: what = "SEARCH_LOW"; break;
+	case SET_LIMITS: what = "SET_LIMITS"; break;
+	case READ_POSITION: what = "READ_POSITION"; break;
+	case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
+	case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
+	case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
+	case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
+	case COMPARE: what = "COMPARE"; break;
+	case COPY_VERIFY: what = "COPY_VERIFY"; break;
+	case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
+	case READ_BUFFER: what = "READ_BUFFER"; break;
+	case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
+	case READ_LONG: what = "READ_LONG"; break;
+	case WRITE_LONG: what = "WRITE_LONG"; break;
+	case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
+	case WRITE_SAME: what = "WRITE_SAME"; break;
+	case READ_TOC: what = "READ_TOC"; break;
+	case LOG_SELECT: what = "LOG_SELECT"; break;
+	case LOG_SENSE: what = "LOG_SENSE"; break;
+	case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
+	case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
+	case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
+	case READ_12: what = "READ_12"; break;
+	case WRITE_12: what = "WRITE_12"; break;
+	case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
+	case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
+	case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
+	case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
+	case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
+	case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
+	case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
+	default:
+		MTS_DEBUG("can't decode command\n");
+		goto out;
+		break;
+	}
+	MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len);
+
+ out:
+	MTS_DEBUG( "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+	       srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
+	       srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
+}
+
+#else
+
+static inline void mts_show_command(Scsi_Cmnd * dummy)
+{
+}
+
+static inline void mts_debug_dump(struct mts_desc* dummy)
+{
+}
+
+#endif
+
+static inline void mts_urb_abort(struct mts_desc* desc) {
+	MTS_DEBUG_GOT_HERE();
+	mts_debug_dump(desc);
+
+	usb_unlink_urb( desc->urb );
+}
+
+static struct mts_desc * mts_list; /* list of active scanners */
+struct semaphore mts_list_semaphore;
+
+/* Internal list operations */
+
+static
+void mts_remove_nolock( struct mts_desc* to_remove )
+{
+	MTS_DEBUG( "removing 0x%x from list\n",
+		   (int)to_remove );
+
+	lock_kernel();
+	mts_urb_abort(to_remove);
+
+	MTS_DEBUG_GOT_HERE();
+
+	if ( to_remove != mts_list ) {
+		MTS_DEBUG_GOT_HERE();
+		if (to_remove->prev && to_remove->next)
+			to_remove->prev->next = to_remove->next;
+	} else {
+		MTS_DEBUG_GOT_HERE();
+		mts_list = to_remove->next;
+		if (mts_list) {
+			MTS_DEBUG_GOT_HERE();
+			mts_list->prev = 0;
+		}
+	}
+
+	if ( to_remove->next ) {
+		MTS_DEBUG_GOT_HERE();
+		to_remove->next->prev = to_remove->prev;
+	}
+
+	MTS_DEBUG_GOT_HERE();
+	scsi_unregister_host(&to_remove->ctempl);
+	unlock_kernel();
+
+	usb_free_urb(to_remove->urb);
+	kfree( to_remove );
+}
+
+static
+void mts_add_nolock( struct mts_desc* to_add )
+{
+	MTS_DEBUG( "adding 0x%x to list\n", (int)to_add );
+
+	to_add->prev = 0;
+	to_add->next = mts_list;
+	if ( mts_list ) {
+		mts_list->prev = to_add;
+	}
+
+	mts_list = to_add;
+}
+
+
+
+
+/* SCSI driver interface */
+
+/* scsi related functions - dummies for now mostly */
+
+static int mts_scsi_release(struct Scsi_Host *psh)
+{
+	MTS_DEBUG_GOT_HERE();
+
+	return 0;
+}
+
+static int mts_scsi_abort (Scsi_Cmnd *srb)
+{
+	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
+
+	MTS_DEBUG_GOT_HERE();
+
+	mts_urb_abort(desc);
+
+	return SCSI_ABORT_PENDING;
+}
+
+static int mts_scsi_host_reset (Scsi_Cmnd *srb)
+{
+	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
+
+	MTS_DEBUG_GOT_HERE();
+	mts_debug_dump(desc);
+
+	usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */
+	return 0;  /* RANT why here 0 and not SUCCESS */
+}
+
+/* the core of the scsi part */
+
+/* faking a detection - which can't fail :-) */
+
+static int mts_scsi_detect (struct SHT * sht)
+{
+	/* Whole function stolen from usb-storage */
+
+	struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
+	/* What a hideous hack! */
+
+	char local_name[48];
+
+	MTS_DEBUG_GOT_HERE();
+
+	/* set up the name of our subdirectory under /proc/scsi/ */
+	sprintf(local_name, "microtek-%d", desc->host_number);
+	sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
+	/* FIXME: where is this freed ? */
+
+	if (!sht->proc_name) {
+		MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
+		return 0;
+	}
+
+	strcpy(sht->proc_name, local_name);
+
+ 	sht->proc_dir = NULL;
+
+	/* In host->hostdata we store a pointer to desc */
+	desc->host = scsi_register(sht, sizeof(desc));
+	if (desc->host == NULL) {
+		MTS_ERROR("Cannot register due to low memory");
+		kfree(sht->proc_name);
+		return 0;
+	}
+	desc->host->hostdata[0] = (unsigned long)desc;
+/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
+
+	return 1;
+}
+
+
+
+/* Main entrypoint: SCSI commands are dispatched to here */
+
+
+
+static
+int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
+
+static void mts_transfer_cleanup( struct urb *transfer );
+static void mts_do_sg(struct urb * transfer);
+
+
+inline static
+void mts_int_submit_urb (struct urb* transfer,
+			int pipe,
+			void* data,
+			unsigned length,
+			mts_usb_urb_callback callback )
+/* Interrupt context! */
+
+/* Holding transfer->context->lock! */
+{
+	int res;
+
+	MTS_INT_INIT();
+
+	FILL_BULK_URB(transfer,
+		      context->instance->usb_dev,
+		      pipe,
+		      data,
+		      length,
+		      callback,
+		      context
+		);
+
+	transfer->status = 0;
+
+	res = usb_submit_urb( transfer, GFP_ATOMIC );
+	if ( unlikely(res) ) {
+		MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
+		context->srb->result = DID_ERROR << 16;
+		mts_transfer_cleanup(transfer);
+	}
+	return;
+}
+
+
+static void mts_transfer_cleanup( struct urb *transfer )
+/* Interrupt context! */
+{
+	MTS_INT_INIT();
+
+	if ( likely(context->final_callback != NULL) )
+		context->final_callback(context->srb);
+
+}
+
+static void mts_transfer_done( struct urb *transfer )
+{
+	MTS_INT_INIT();
+
+	context->srb->result &= MTS_SCSI_ERR_MASK;
+	context->srb->result |= (unsigned)context->status<<1;
+
+	mts_transfer_cleanup(transfer);
+
+	return;
+}
+
+
+static void mts_get_status( struct urb *transfer )
+/* Interrupt context! */
+{
+	MTS_INT_INIT();
+
+	mts_int_submit_urb(transfer,
+			   usb_rcvbulkpipe(context->instance->usb_dev,
+					   context->instance->ep_response),
+			   &context->status,
+			   1,
+			   mts_transfer_done );
+}
+
+static void mts_data_done( struct urb* transfer )
+/* Interrupt context! */
+{
+	MTS_INT_INIT();
+
+	if ( context->data_length != transfer->actual_length ) {
+		context->srb->resid = context->data_length - transfer->actual_length;
+	} else if ( unlikely(transfer->status) ) {
+		context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
+	}
+
+	mts_get_status(transfer);
+
+	return;
+}
+
+
+static void mts_command_done( struct urb *transfer )
+/* Interrupt context! */
+{
+	MTS_INT_INIT();
+
+	if ( unlikely(transfer->status) ) {
+	        if (transfer->status == -ENOENT) {
+		        /* We are being killed */
+			MTS_DEBUG_GOT_HERE();
+			context->srb->result = DID_ABORT<<16;
+                } else {
+		        /* A genuine error has occured */
+			MTS_DEBUG_GOT_HERE();
+
+		        context->srb->result = DID_ERROR<<16;
+                }
+		mts_transfer_cleanup(transfer);
+
+		return;
+	}
+
+	if ( context->data ) {
+		mts_int_submit_urb(transfer,
+				   context->data_pipe,
+				   context->data,
+				   context->data_length,
+				   context->srb->use_sg ? mts_do_sg : mts_data_done);
+	} else mts_get_status(transfer);
+
+	return;
+}
+
+static void mts_do_sg (struct urb* transfer)
+{
+	struct scatterlist * sg;
+	MTS_INT_INIT();
+	
+	MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
+
+	if (unlikely(transfer->status)) {
+                context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
+		mts_transfer_cleanup(transfer);
+        }
+
+	sg = context->srb->buffer;
+	context->fragment++;
+	mts_int_submit_urb(transfer,
+			   context->data_pipe,
+			   page_address(sg[context->fragment].page) +
+			   sg[context->fragment].offset,
+			   sg[context->fragment].length,
+			   context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
+	return;
+}
+
+static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 };
+static const u8 mts_read_image_sig_len = 4;
+static const unsigned char mts_direction[256/8] = {
+	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
+	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+
+#define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
+
+static void
+mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
+{
+	int pipe;
+	struct scatterlist * sg;
+	
+	MTS_DEBUG_GOT_HERE();
+
+	desc->context.instance = desc;
+	desc->context.srb = srb;
+	desc->context.fragment = 0;
+
+	if (!srb->use_sg) {
+		if ( !srb->bufflen ){
+			desc->context.data = 0;
+			desc->context.data_length = 0;
+			return;
+		} else {
+			desc->context.data = srb->buffer;
+			desc->context.data_length = srb->bufflen;
+			MTS_DEBUG("length = %d or %d\n",
+				  srb->request_bufflen, srb->bufflen);
+		}
+	} else {
+		MTS_DEBUG("Using scatter/gather\n");
+		sg = srb->buffer;
+		desc->context.data = page_address(sg[0].page) + sg[0].offset;
+		desc->context.data_length = sg[0].length;
+	}
+
+
+	/* can't rely on srb->sc_data_direction */
+
+	/* Brutally ripped from usb-storage */
+
+	if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len )
+) { 		pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image);
+		MTS_DEBUG( "transfering from desc->ep_image == %d\n",
+			   (int)desc->ep_image );
+	} else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) {
+			pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response);
+			MTS_DEBUG( "transfering from desc->ep_response == %d\n",
+				   (int)desc->ep_response);
+	} else {
+		MTS_DEBUG("transfering to desc->ep_out == %d\n",
+			  (int)desc->ep_out);
+		pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out);
+	}
+	desc->context.data_pipe = pipe;
+}
+
+
+static
+int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
+{
+	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
+	int err = 0;
+	int res;
+
+	MTS_DEBUG_GOT_HERE();
+	mts_show_command(srb);
+	mts_debug_dump(desc);
+
+	if ( srb->device->lun || srb->device->id || srb->device->channel ) {
+
+		MTS_DEBUG("Command to LUN=%d ID=%d CHANNEL=%d from SCSI layer\n",(int)srb->device->lun,(int)srb->device->id, (int)srb->device->channel );
+
+		MTS_DEBUG("this device doesn't exist\n");
+
+		srb->result = DID_BAD_TARGET << 16;
+
+		if(likely(callback != NULL))
+			callback(srb);
+
+		goto out;
+	}
+
+	
+	FILL_BULK_URB(desc->urb,
+		      desc->usb_dev,
+		      usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
+		      srb->cmnd,
+		      srb->cmd_len,
+		      mts_command_done,
+		      &desc->context
+		      );
+
+
+	mts_build_transfer_context( srb, desc );
+	desc->context.final_callback = callback;
+	
+	/* here we need ATOMIC as we are called with the iolock */
+	res=usb_submit_urb(desc->urb, GFP_ATOMIC);
+
+	if(unlikely(res)){
+		MTS_ERROR("error %d submitting URB\n",(int)res);
+		srb->result = DID_ERROR << 16;
+
+		if(likely(callback != NULL))
+			callback(srb);
+
+	}
+
+out:
+	return err;
+}
+/*
+ * this defines our 'host'
+ */
+
+/* NOTE: This is taken from usb-storage, should be right. */
+
+
+static Scsi_Host_Template mts_scsi_host_template = {
+	name:           "microtekX6",
+	detect:		mts_scsi_detect,
+	release:	mts_scsi_release,
+	queuecommand:	mts_scsi_queuecommand,
+
+	eh_abort_handler:	mts_scsi_abort,
+	eh_host_reset_handler:	mts_scsi_host_reset,
+
+	sg_tablesize:		SG_ALL,
+	can_queue:		1,
+	this_id:		-1,
+	cmd_per_lun:		1,
+	present:		0,
+	unchecked_isa_dma:	FALSE,
+	use_clustering:		TRUE,
+	emulated:		TRUE
+};
+
+
+/* USB layer driver interface implementation */
+
+static void mts_usb_disconnect (struct usb_device *dev, void *ptr)
+{
+	struct mts_desc* to_remove = (struct mts_desc*)ptr;
+
+	MTS_DEBUG_GOT_HERE();
+
+	/* leave the list - lock it */
+	down(&mts_list_semaphore);
+
+	mts_remove_nolock(to_remove);
+
+	up(&mts_list_semaphore);
+}
+
+struct vendor_product
+{
+	char* name;
+	enum
+	{
+		mts_sup_unknown=0,
+		mts_sup_alpha,
+		mts_sup_full
+	}
+	support_status;
+} ;
+
+
+/* These are taken from the msmUSB.inf file on the Windows driver CD */
+const static struct vendor_product mts_supported_products[] =
+{
+	{ "Phantom 336CX",	mts_sup_unknown},
+	{ "Phantom 336CX",	mts_sup_unknown},
+	{ "Scanmaker X6",	mts_sup_alpha},
+	{ "Phantom C6",		mts_sup_unknown},
+	{ "Phantom 336CX",	mts_sup_unknown},
+	{ "ScanMaker V6USL",	mts_sup_unknown},
+	{ "ScanMaker V6USL",	mts_sup_unknown},
+	{ "Scanmaker V6UL",	mts_sup_unknown},
+	{ "Scanmaker V6UPL",	mts_sup_alpha},
+};
+
+/* The entries of microtek_table must correspond, line-by-line to
+   the entries of mts_supported_products[]. */
+
+static struct usb_device_id mts_usb_ids [] =
+{
+	{ USB_DEVICE(0x4ce, 0x0300) },
+	{ USB_DEVICE(0x5da, 0x0094) },
+	{ USB_DEVICE(0x5da, 0x0099) },
+	{ USB_DEVICE(0x5da, 0x009a) },
+	{ USB_DEVICE(0x5da, 0x00a0) },
+	{ USB_DEVICE(0x5da, 0x00a3) },
+	{ USB_DEVICE(0x5da, 0x80a3) },
+	{ USB_DEVICE(0x5da, 0x80ac) },
+	{ USB_DEVICE(0x5da, 0x00b6) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, mts_usb_ids);
+
+
+static void * mts_usb_probe (struct usb_device *dev, unsigned int interface,
+			     const struct usb_device_id *id)
+{
+	int i;
+	int result;
+	int ep_out = -1;
+	int ep_in_set[3]; /* this will break if we have more than three endpoints
+			   which is why we check */
+	int *ep_in_current = ep_in_set;
+
+	struct mts_desc * new_desc;
+	struct vendor_product const* p;
+
+	/* the altsettting 0 on the interface we're probing */
+	struct usb_interface_descriptor *altsetting;
+
+	MTS_DEBUG_GOT_HERE();
+	MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev );
+
+	MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n",
+		   (int)dev->descriptor.idProduct,
+		   (int)dev->descriptor.idVendor );
+
+	MTS_DEBUG_GOT_HERE();
+
+	p = &mts_supported_products[id - mts_usb_ids];
+
+	MTS_DEBUG_GOT_HERE();
+
+	MTS_DEBUG( "found model %s\n", p->name );
+	if ( p->support_status != mts_sup_full )
+		MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n",
+			     p->name );
+
+	/* the altsettting 0 on the interface we're probing */
+	altsetting =
+		&(dev->actconfig->interface[interface].altsetting[0]);
+
+
+	/* Check if the config is sane */
+
+	if ( altsetting->bNumEndpoints != MTS_EP_TOTAL ) {
+		MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n",
+			     (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints );
+		return NULL;
+	}
+
+	for( i = 0; i < altsetting->bNumEndpoints; i++ ) {
+		if ((altsetting->endpoint[i].bmAttributes &
+		     USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
+
+			MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n",
+			     (int)altsetting->endpoint[i].bEndpointAddress );
+		} else {
+			if (altsetting->endpoint[i].bEndpointAddress &
+			    USB_DIR_IN)
+				*ep_in_current++
+					= altsetting->endpoint[i].bEndpointAddress &
+					USB_ENDPOINT_NUMBER_MASK;
+			else {
+				if ( ep_out != -1 ) {
+					MTS_WARNING( "can only deal with one output endpoints. Bailing out." );
+					return NULL;
+				}
+
+				ep_out = altsetting->endpoint[i].bEndpointAddress &
+					USB_ENDPOINT_NUMBER_MASK;
+			}
+		}
+
+	}
+
+
+	if ( ep_out == -1 ) {
+		MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
+		return NULL;
+	}
+
+
+	/* I don't understand the following fully (it's from usb-storage) -- John */
+
+	/* set the interface -- STALL is an acceptable response here */
+	result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0);
+
+	MTS_DEBUG("usb_set_interface returned %d.\n",result);
+	switch( result )
+	{
+	case 0: /* no error */
+		break;
+		
+	case -EPIPE:
+		usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
+		MTS_DEBUG( "clearing clearing stall on control interface\n" );
+		break;
+		
+	default:
+		MTS_DEBUG( "unknown error %d from usb_set_interface\n",
+			(int)result );
+ 		return NULL;
+	}
+	
+	
+	/* allocating a new descriptor */
+	new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
+	if (new_desc == NULL)
+	{
+		MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
+		return NULL;
+	}
+
+	memset( new_desc, 0, sizeof(*new_desc) );
+	new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!new_desc->urb) {
+		kfree(new_desc);
+		return NULL;
+	}
+		
+	/* initialising that descriptor */
+	new_desc->usb_dev = dev;
+	new_desc->interface = interface;
+
+	init_MUTEX(&new_desc->lock);
+
+	if(mts_list){
+		new_desc->host_number = mts_list->host_number+1;
+	} else {
+		new_desc->host_number = 0;
+	}
+	
+	/* endpoints */
+	
+	new_desc->ep_out = ep_out;
+	new_desc->ep_response = ep_in_set[0];
+	new_desc->ep_image = ep_in_set[1];
+
+
+	if ( new_desc->ep_out != MTS_EP_OUT )
+		MTS_WARNING( "will this work? Command EP is not usually %d\n",
+			     (int)new_desc->ep_out );
+
+	if ( new_desc->ep_response != MTS_EP_RESPONSE )
+		MTS_WARNING( "will this work? Response EP is not usually %d\n",
+			     (int)new_desc->ep_response );
+
+	if ( new_desc->ep_image != MTS_EP_IMAGE )
+		MTS_WARNING( "will this work? Image data EP is not usually %d\n",
+			     (int)new_desc->ep_image );
+
+
+	/* Initialize the host template based on the default one */
+	memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template));
+	/* HACK from usb-storage - this is needed for scsi detection */
+	(struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */
+
+	MTS_DEBUG("registering SCSI module\n");
+
+	new_desc->ctempl.module = THIS_MODULE;
+	result = scsi_register_host(&new_desc->ctempl);
+	/* Will get hit back in microtek_detect by this func */
+	if ( result )
+	{
+		MTS_ERROR( "error %d from scsi_register_host! Help!\n",
+			   (int)result );
+
+		/* FIXME: need more cleanup? */
+		kfree( new_desc );
+		return NULL;
+	}
+	MTS_DEBUG_GOT_HERE();
+
+	/* FIXME: the bomb is armed, must the host be registered under lock ? */
+	/* join the list - lock it */
+	down(&mts_list_semaphore);
+
+	mts_add_nolock( new_desc );
+
+	up(&mts_list_semaphore);
+
+
+	MTS_DEBUG("completed probe and exiting happily\n");
+
+	return (void *)new_desc;
+}
+
+
+
+/* get us noticed by the rest of the kernel */
+
+int __init microtek_drv_init(void)
+{
+	int result;
+
+	MTS_DEBUG_GOT_HERE();
+	init_MUTEX(&mts_list_semaphore);
+
+	if ((result = usb_register(&mts_usb_driver)) < 0) {
+		MTS_DEBUG("usb_register returned %d\n", result );
+		return -1;
+	} else {
+		MTS_DEBUG("driver registered.\n");
+	}
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+
+	return 0;
+}
+
+void __exit microtek_drv_exit(void)
+{
+	struct mts_desc* next;
+
+	MTS_DEBUG_GOT_HERE();
+
+	usb_deregister(&mts_usb_driver);
+
+	down(&mts_list_semaphore);
+
+	while (mts_list) {
+		/* keep track of where the next one is */
+		next = mts_list->next;
+
+		mts_remove_nolock( mts_list );
+
+		/* advance the list pointer */
+		mts_list = next;
+	}
+
+	up(&mts_list_semaphore);
+}
+
+module_init(microtek_drv_init);
+module_exit(microtek_drv_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+
diff -Nru a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/microtek.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,60 @@
+ /*
+ * Driver for Microtek Scanmaker X6 USB scanner and possibly others.
+ * 
+ * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com>
+ * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
+ *
+ * See microtek.c for history
+ *
+ */
+
+typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *);
+typedef void (*mts_usb_urb_callback) (struct urb *);
+
+
+struct mts_transfer_context
+{
+	struct mts_desc* instance;
+	mts_scsi_cmnd_callback final_callback;
+	Scsi_Cmnd *srb;
+	
+	void* data;
+	unsigned data_length;
+	int data_pipe;
+	int fragment;
+
+	u8 status; /* status returned from ep_response after command completion */
+};
+
+
+struct mts_desc {
+	struct mts_desc *next;
+	struct mts_desc *prev;
+
+	struct usb_device *usb_dev;
+
+	int interface;
+
+	/* Endpoint addresses */
+	u8 ep_out;
+	u8 ep_response;
+	u8 ep_image;
+
+	struct Scsi_Host * host;
+	Scsi_Host_Template ctempl;
+	int host_number;
+
+	struct semaphore lock;
+
+	struct urb *urb;
+	struct mts_transfer_context context;
+};
+
+
+#define MTS_EP_OUT	0x1
+#define MTS_EP_RESPONSE	0x2
+#define MTS_EP_IMAGE	0x3
+#define MTS_EP_TOTAL	0x3
+
+#define MTS_SCSI_ERR_MASK ~0x3fu
+
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/scanner.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,1125 @@
+/* -*- linux-c -*- */
+
+/* 
+ * Driver for USB Scanners (linux-2.4.12)
+ *
+ * Copyright (C) 1999, 2000, 2001 David E. Nelson
+ *
+ * Portions may be copyright Brad Keryan and Michael Gee.
+ *
+ * David E. Nelson (dnelson@jump.net)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Originally based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
+ *
+ * History
+ *
+ *  0.1  8/31/1999
+ *
+ *    Developed/tested using linux-2.3.15 with minor ohci.c changes to
+ *    support short packes during bulk xfer mode.  Some testing was
+ *    done with ohci-hcd but the performace was low.  Very limited
+ *    testing was performed with uhci but I was unable to get it to
+ *    work.  Initial relase to the linux-usb development effort.
+ *
+ *
+ *  0.2  10/16/1999
+ *
+ *    - Device can't be opened unless a scanner is plugged into the USB.
+ *    - Finally settled on a reasonable value for the I/O buffer's.
+ *    - Cleaned up write_scanner()
+ *    - Disabled read/write stats
+ *    - A little more code cleanup
+ *
+ *
+ *  0.3  10/18/1999
+ *
+ *    - Device registration changed to reflect new device
+ *      allocation/registration for linux-2.3.22+.
+ *    - Adopted David Brownell's <david-b@pacbell.net> technique for 
+ *      assigning bulk endpoints.
+ *    - Removed unnessesary #include's
+ *    - Scanner model now reported via syslog INFO after being detected 
+ *      *and* configured.
+ *    - Added user specified vendor:product USB ID's which can be passed 
+ *      as module parameters.
+ *
+ *
+ *  0.3.1
+ *
+ *    - Applied patches for linux-2.3.25.
+ *    - Error number reporting changed to reflect negative return codes.
+ *
+ *
+ *  0.3.2
+ *
+ *    - Applied patches for linux-2.3.26 to scanner_init().
+ *    - Debug read/write stats now report values as signed decimal.
+ *
+ *
+ *  0.3.3
+ *
+ *    - Updated the bulk_msg() calls to usb usb_bulk_msg().
+ *    - Added a small delay in the write_scanner() method to aid in
+ *      avoiding NULL data reads on HP scanners.  We'll see how this works.
+ *    - Return values from usb_bulk_msg() now ignore positive values for
+ *      use with the ohci driver.
+ *    - Added conditional debugging instead of commenting/uncommenting
+ *      all over the place.
+ *    - kfree()'d the pointer after using usb_string() as documented in
+ *      linux-usb-api.txt.
+ *    - Added usb_set_configuration().  It got lost in version 0.3 -- ack!
+ *    - Added the HP 5200C USB Vendor/Product ID's.
+ *
+ *
+ *  0.3.4  1/23/2000
+ *
+ *    - Added Greg K-H's <greg@kroah.com> patch for better handling of 
+ *      Product/Vendor detection.
+ *    - The driver now autoconfigures its endpoints including interrupt
+ *      endpoints if one is detected.  The concept was originally based
+ *      upon David Brownell's method.
+ *    - Added some Seiko/Epson ID's. Thanks to Karl Heinz 
+ *      Kremer <khk@khk.net>.
+ *    - Added some preliminary ioctl() calls for the PV8630 which is used
+ *      by the HP4200. The ioctl()'s still have to be registered. Thanks 
+ *      to Adrian Perez Jorge <adrianpj@easynews.com>.
+ *    - Moved/migrated stuff to scanner.h
+ *    - Removed the usb_set_configuration() since this is handled by
+ *      the usb_new_device() routine in usb.c.
+ *    - Added the HP 3300C.  Thanks to Bruce Tenison.
+ *    - Changed user specified vendor/product id so that root hub doesn't
+ *      get falsely attached to. Thanks to Greg K-H.
+ *    - Added some Mustek ID's. Thanks to Gernot Hoyler 
+ *      <Dr.Hoyler@t-online.de>.
+ *    - Modified the usb_string() reporting.  See kfree() comment above.
+ *    - Added Umax Astra 2000U. Thanks to Doug Alcorn <doug@lathi.net>.
+ *    - Updated the printk()'s to use the info/warn/dbg macros.
+ *    - Updated usb_bulk_msg() argument types to fix gcc warnings.
+ *
+ *
+ *  0.4  2/4/2000
+ *
+ *    - Removed usb_string() from probe_scanner since the core now does a
+ *      good job of reporting what was connnected.  
+ *    - Finally, simultaneous multiple device attachment!
+ *    - Fixed some potential memory freeing issues should memory allocation
+ *      fail in probe_scanner();
+ *    - Some fixes to disconnect_scanner().
+ *    - Added interrupt endpoint support.
+ *    - Added Agfa SnapScan Touch. Thanks to Jan Van den Bergh
+ *      <jan.vandenbergh@cs.kuleuven.ac.be>.
+ *    - Added Umax 1220U ID's. Thanks to Maciek Klimkowski
+ *      <mac@nexus.carleton.ca>.
+ *    - Fixed bug in write_scanner(). The buffer was not being properly
+ *      updated for writes larger than OBUF_SIZE. Thanks to Henrik 
+ *      Johansson <henrikjo@post.utfors.se> for identifying it.
+ *    - Added Microtek X6 ID's. Thanks to Oliver Neukum
+ *      <Oliver.Neukum@lrz.uni-muenchen.de>.
+ *
+ * 
+ *  0.4.1  2/15/2000
+ *  
+ *    - Fixed 'count' bug in read_scanner(). Thanks to Henrik
+ *      Johansson <henrikjo@post.utfors.se> for identifying it.  Amazing
+ *      it has worked this long.
+ *    - Fixed '>=' bug in both read/write_scanner methods.
+ *    - Cleaned up both read/write_scanner() methods so that they are 
+ *      a little more readable.
+ *    - Added a lot of Microtek ID's.  Thanks to Adrian Perez Jorge.
+ *    - Adopted the __initcall().
+ *    - Added #include <linux/init.h> to scanner.h for __initcall().
+ *    - Added one liner in irq_scanner() to keep gcc from complaining 
+ *      about an unused variable (data) if debugging was disabled
+ *      in scanner.c.
+ *    - Increased the timeout parameter in read_scanner() to 120 Secs.
+ *
+ *
+ *  0.4.2  3/23/2000
+ *
+ *    - Added Umax 1236U ID.  Thanks to Philipp Baer <ph_baer@npw.net>.
+ *    - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's.
+ *      Thanks to Adrian Perez Jorge <adrianpj@easynews.com>.
+ *    - Fixed error number reported for non-existant devices.  Thanks to
+ *      Spyridon Papadimitriou <Spyridon_Papadimitriou@gs91.sp.cs.cmu.edu>.
+ *    - Added Acer Prisascan 620U ID's.  Thanks to Joao <joey@knoware.nl>.
+ *    - Replaced __initcall() with module_init()/module_exit(). Updates
+ *      from patch-2.3.48.
+ *    - Replaced file_operations structure with new syntax.  Updates
+ *      from patch-2.3.49.
+ *    - Changed #include "usb.h" to #include <linux/usb.h>
+ *    - Added #define SCN_IOCTL to exclude development areas 
+ *      since 2.4.x is about to be released. This mainly affects the 
+ *      ioctl() stuff.  See scanner.h for more details.
+ *    - Changed the return value for signal_pending() from -ERESTARTSYS to
+ *      -EINTR.
+ *
+ *
+ * 0.4.3  4/30/2000
+ *
+ *    - Added Umax Astra 2200 ID.  Thanks to Flynn Marquardt 
+ *      <flynn@isr.uni-stuttgart.de>.
+ *    - Added iVina 1200U ID. Thanks to Dyson Lin <dyson@avision.com.tw>.
+ *    - Added access time update for the device file courtesy of Paul
+ *      Mackerras <paulus@samba.org>.  This allows a user space daemon
+ *      to turn the lamp off for a Umax 1220U scanner after a prescribed
+ *      time.
+ *    - Fixed HP S20 ID's.  Thanks to Ruud Linders <rlinders@xs4all.nl>.
+ *    - Added Acer ScanPrisa 620U ID. Thanks to Oliver
+ *      Schwartz <Oliver.Schwartz@gmx.de> via sane-devel mail list.
+ *    - Fixed bug in read_scanner for copy_to_user() function.  The returned
+ *      value should be 'partial' not 'this_read'.
+ *    - Fixed bug in read_scanner. 'count' should be decremented 
+ *      by 'this_read' and not by 'partial'.  This resulted in twice as many
+ *      calls to read_scanner() for small amounts of data and possibly
+ *      unexpected returns of '0'.  Thanks to Karl Heinz 
+ *      Kremer <khk@khk.net> and Alain Knaff <Alain.Knaff@ltnb.lu>
+ *      for discovering this.
+ *    - Integrated Randy Dunlap's <randy.dunlap@intel.com> patch for a
+ *      scanner lookup/ident table. Thanks Randy.
+ *    - Documentation updates.
+ *    - Added wait queues to read_scanner().
+ *
+ *
+ * 0.4.3.1
+ *
+ *    - Fixed HP S20 ID's...again..sigh.  Thanks to Ruud
+ *      Linders <rlinders@xs4all.nl>.
+ *
+ * 0.4.4
+ *    - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB,
+ *      and 1200 UB.  Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
+ *    - Added the Vuego Scan Brisa 340U ID's.  Apparently this scanner is
+ *      marketed by Acer Peripherals as a cheap 300 dpi model. Thanks to
+ *      David Gundersen <gundersd@paradise.net.nz>.
+ *    - Added the Epson Expression1600 ID's. Thanks to Karl Heinz
+ *      Kremer <khk@khk.net>.
+ *
+ * 0.4.5  2/28/2001
+ *    - Added Mustek ID's (BearPaw 2400, 1200 CU Plus, BearPaw 1200F).
+ *      Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
+ *    - Added read_timeout module parameter to override RD_NAK_TIMEOUT
+ *      when read()'ing from devices.
+ *    - Stalled pipes are now checked and cleared with
+ *      usb_clear_halt() for the read_scanner() function. This should
+ *      address the "funky result: -32" error messages.
+ *    - Removed Microtek scanner ID's.  Microtek scanners are now
+ *      supported via the drivers/usb/microtek.c driver.
+ *    - Added scanner specific read timeout's.
+ *    - Return status errors are NEGATIVE!!!  This should address the
+ *      "funky result: -110" error messages.
+ *    - Replaced USB_ST_TIMEOUT with ETIMEDOUT.
+ *    - rd_nak was still defined in MODULE_PARM.  It's been updated with
+ *      read_timeout.  Thanks to Mark W. Webb <markwebb@adelphia.net> for
+ *      reporting this bug.
+ *    - Added Epson Perfection 1640SU and 1640SU Photo.  Thanks to
+ *      Jean-Luc <f5ibh@db0bm.ampr.org> and Manuel
+ *      Pelayo <Manuel.Pelayo@sesips.org>. Reported to work fine by Manuel.
+ *
+ * 0.4.6  9/27/2001
+ *    - Added IOCTL's to report back scanner USB ID's.  Thanks to
+ *      Karl Heinz <khk@lynx.phpwebhosting.com>
+ *    - Added Umax Astra 2100U ID's.  Thanks to Ron
+ *      Wellsted <ron@wellsted.org.uk>.
+ *      and Manuel Pelayo <Manuel.Pelayo@sesips.org>.
+ *    - Added HP 3400 ID's. Thanks to Harald Hannelius <harald@iki.fi>
+ *      and Bertrik Sikken <bertrik@zonnet.nl>.  Reported to work at
+ *      htpp://home.zonnet.nl/bertrik/hp3300c/hp3300c.htm.
+ *    - Added Minolta Dimage Scan Dual II ID's.  Thanks to Jose Paulo
+ *      Moitinho de Almeida <moitinho@civil.ist.utl.pt>
+ *    - Confirmed addition for SnapScan E20.  Thanks to Steffen Hübner
+ *      <hueb_s@gmx.de>.
+ *    - Added Lifetec LT9385 ID's.  Thanks to Van Bruwaene Kris
+ *      <krvbr@yahoo.co.uk>
+ *    - Added Agfa SnapScan e26 ID's.  Reported to work with SANE
+ *      1.0.5.  Thanks to Falk Sauer <falk@mgnkatze.franken.de>.
+ *    - Added HP 4300 ID's.  Thanks to Stefan Schlosser
+ *      <castla@grmmbl.org>.
+ *    - Added Relisis Episode ID's.  Thanks to Manfred
+ *      Morgner <odb-devel@gmx.net>.
+ *    - Added many Acer ID's. Thanks to Oliver
+ *      Schwartz <Oliver.Schwartz@gmx.de>.
+ *    - Added Snapscan e40 ID's.  Thanks to Oliver
+ *      Schwartz <Oliver.Schwartz@gmx.de>.
+ *    - Thanks to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
+ *      for helping with races.
+ *    - Added Epson Perfection 1650 ID's. Thanks to Karl Heinz
+ *      Kremer <khk@khk.net>.
+ *    - Added Epson Perfection 2450 ID's (aka GT-9700 for the Japanese
+ *      market).  Thanks to Karl Heinz Kremer <khk@khk.net>.
+ *    - Added Mustek 600 USB ID's.  Thanks to Marcus
+ *      Alanen <maalanen@ra.abo.fi>.
+ *    - Added Acer ScanPrisa 1240UT ID's.  Thanks to Morgan
+ *      Collins <sirmorcant@morcant.org>.
+ *    - Incorporated devfs patches!! Thanks to Tom Rini
+ *      <trini@kernel.crashing.org>, Pavel Roskin <proski@gnu.org>,
+ *      Greg KH <greg@kroah.com>, Yves Duret <yduret@mandrakesoft.com>,
+ *      Flavio Stanchina <flavio.stanchina@tin.it>.
+ *    - Removed Minolta ScanImage II.  This scanner uses USB SCSI.  Thanks
+ *      to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de> for pointing
+ *      this out.
+ *    - Added additional SMP locking.  Thanks to David Brownell and 
+ *      Oliver Neukum for their help.
+ *    - Added version reporting - reports for both module load and modinfo
+ *    - Started path to hopefully straighten/clean out ioctl()'s.
+ *    - Users are now notified to consult the Documentation/usb/scanner.txt
+ *      for common error messages rather than the maintainer.
+ *
+ * 0.4.7  11/28/2001
+ *    - Fixed typo in Documentation/scanner.txt.  Thanks to
+ *      Karel <karel.vervaeke@pandora.be> for pointing it out.
+ *    - Added ID's for a Memorex 6136u. Thanks to Álvaro Gaspar de
+ *      Valenzuela" <agaspard@utsi.edu>.
+ *    - Added ID's for Agfa e25.  Thanks to Heinrich 
+ *      Rust <Heinrich.Rust@gmx.de>.  Also reported to work with
+ *      Linux and SANE (?).
+ *    - Added Canon FB620U, D646U, and 1220U ID's.  Thanks to Paul
+ *      Rensing <Paul_Rensing@StanfordAlumni.org>.  For more info
+ *      on Linux support for these models, contact 
+ *      salvestrini@users.sourceforge.net.
+ *    - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
+ *      ColorPage-HR6 V2 ID's in addition to many "Unknown" models
+ *      under those vendors.  Thanks to
+ *      Jaeger, Gerhard" <g.jaeger@earthling.net>.  These scanner are
+ *      apparently based upon the LM983x IC's.
+ *    - Applied Frank's patch that addressed some locking and module
+ *      referencing counts.  Thanks to both
+ *      Frank Zago <fzago@greshamstorage.com> and
+ *      Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
+ *
+ * TODO
+ *    - Performance
+ *    - Select/poll methods
+ *    - More testing
+ *    - Proper registry/assignment for LM9830 ioctl's
+ *
+ *
+ *  Thanks to:
+ *
+ *    - All the folks on the linux-usb list who put up with me. :)  This 
+ *      has been a great learning experience for me.
+ *    - To Linus Torvalds for this great OS.
+ *    - The GNU folks.
+ *    - The folks that forwarded Vendor:Product ID's to me.
+ *    - Johannes Erdfelt for the loaning of a USB analyzer for tracking an
+ *      issue with HP-4100 and uhci.
+ *    - Adolfo Montero for his assistance.
+ *    - All the folks who chimed in with reports and suggestions.
+ *    - All the developers that are working on USB SANE backends or other
+ *      applications to use USB scanners.
+ *
+ *  Performance:
+ *
+ *    System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner
+ *            300 dpi scan of the entire bed
+ *      24 Bit Color ~ 70 secs - 3.6 Mbit/sec
+ *       8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
+
+#include <asm/byteorder.h>
+
+/* 
+ * Scanner definitions, macros, module info, 
+ * debug/ioctl/data_dump enable, and other constants.
+ */ 
+#include "scanner.h"
+
+static void
+irq_scanner(struct urb *urb)
+{
+
+/*
+ * For the meantime, this is just a placeholder until I figure out what
+ * all I want to do with it -- or somebody else for that matter.
+ */
+
+	struct scn_usb_data *scn;
+	unsigned char *data;
+	scn = urb->context;
+
+	data = &scn->button;
+	data += 0;		/* Keep gcc from complaining about unused var */
+
+	if (urb->status) {
+		return;
+	}
+
+	dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
+
+	return;
+}
+
+static int
+open_scanner(struct inode * inode, struct file * file)
+{
+	struct scn_usb_data *scn;
+	struct usb_device *dev;
+
+	int scn_minor;
+
+	int err=0;
+
+	MOD_INC_USE_COUNT;
+
+	down(&scn_mutex);
+
+	scn_minor = USB_SCN_MINOR(inode);
+
+	dbg("open_scanner: scn_minor:%d", scn_minor);
+
+	if (!p_scn_table[scn_minor]) {
+		up(&scn_mutex);
+		MOD_DEC_USE_COUNT;
+		err("open_scanner(%d): Unable to access minor data", scn_minor);
+		return -ENODEV;
+	}
+
+	scn = p_scn_table[scn_minor];
+
+	dev = scn->scn_dev;
+
+	down(&(scn->sem));	/* Now protect the scn_usb_data structure */ 
+
+	up(&scn_mutex); /* Now handled by the above */
+
+	if (!dev) {
+		err("open_scanner(%d): Scanner device not present", scn_minor);
+		err = -ENODEV;
+		goto out_error;
+	}
+
+	if (!scn->present) {
+		err("open_scanner(%d): Scanner is not present", scn_minor);
+		err = -ENODEV;
+		goto out_error;
+	}
+
+	if (scn->isopen) {
+		err("open_scanner(%d): Scanner device is already open", scn_minor);
+		err = -EBUSY;
+		goto out_error;
+	}
+
+	init_waitqueue_head(&scn->rd_wait_q);
+
+	scn->isopen = 1;
+
+	file->private_data = scn; /* Used by the read and write methods */
+
+
+out_error:
+
+	up(&(scn->sem)); /* Wake up any possible contending processes */
+
+	if (err)
+		MOD_DEC_USE_COUNT;
+
+	return err;
+}
+
+static int
+close_scanner(struct inode * inode, struct file * file)
+{
+	struct scn_usb_data *scn;
+
+	int scn_minor;
+
+	scn_minor = USB_SCN_MINOR (inode);
+
+	dbg("close_scanner: scn_minor:%d", scn_minor);
+
+	if (!p_scn_table[scn_minor]) {
+		err("close_scanner(%d): invalid scn_minor", scn_minor);
+		return -ENODEV;
+	}
+
+	down(&scn_mutex);
+
+	scn = p_scn_table[scn_minor];
+	down(&(scn->sem));
+	scn->isopen = 0;
+
+	file->private_data = NULL;
+
+	up(&scn_mutex);
+	up(&(scn->sem));
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static ssize_t
+write_scanner(struct file * file, const char * buffer,
+              size_t count, loff_t *ppos)
+{
+	struct scn_usb_data *scn;
+	struct usb_device *dev;
+
+	ssize_t bytes_written = 0; /* Overall count of bytes written */
+	ssize_t ret = 0;
+
+	int scn_minor;
+
+	int this_write;		/* Number of bytes to write */
+	int partial;		/* Number of bytes successfully written */
+	int result = 0;
+
+	char *obuf;
+
+	scn = file->private_data;
+
+	down(&(scn->sem));
+
+	scn_minor = scn->scn_minor;
+
+	obuf = scn->obuf;
+
+	dev = scn->scn_dev;
+
+	file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+
+	while (count > 0) {
+
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+
+		this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
+
+		if (copy_from_user(scn->obuf, buffer, this_write)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, this_write, &partial, 60*HZ);
+		dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, result, this_write, partial);
+
+		if (result == -ETIMEDOUT) {	/* NAK -- shouldn't happen */
+			warn("write_scanner: NAK received.");
+			ret = result;
+			break;
+		} else if (result < 0) { /* We should not get any I/O errors */
+			warn("write_scanner(%d): funky result: %d. Consult Documentataion/usb/scanner.txt.", scn_minor, result);
+			ret = -EIO;
+			break;
+		}
+
+#ifdef WR_DATA_DUMP
+		if (partial) {
+			unsigned char cnt, cnt_max;
+			cnt_max = (partial > 24) ? 24 : partial;
+			printk(KERN_DEBUG "dump(%d): ", scn_minor);
+			for (cnt=0; cnt < cnt_max; cnt++) {
+				printk("%X ", obuf[cnt]);
+			}
+			printk("\n");
+		}
+#endif
+		if (partial != this_write) { /* Unable to write all contents of obuf */
+			ret = -EIO;
+			break;
+		}
+
+		if (partial) { /* Data written */
+			buffer += partial;
+			count -= partial;
+			bytes_written += partial;
+		} else { /* No data written */
+			ret = 0;
+			break;
+		}
+	}
+	up(&(scn->sem));
+	mdelay(5);		/* This seems to help with SANE queries */
+	return ret ? ret : bytes_written;
+}
+
+static ssize_t
+read_scanner(struct file * file, char * buffer,
+             size_t count, loff_t *ppos)
+{
+	struct scn_usb_data *scn;
+	struct usb_device *dev;
+
+	ssize_t bytes_read;	/* Overall count of bytes_read */
+	ssize_t ret;
+
+	int scn_minor;
+	int partial;		/* Number of bytes successfully read */
+	int this_read;		/* Max number of bytes to read */
+	int result;
+	int rd_expire = RD_EXPIRE;
+
+	char *ibuf;
+
+	scn = file->private_data;
+
+	down(&(scn->sem));
+
+	scn_minor = scn->scn_minor;
+
+	ibuf = scn->ibuf;
+
+	dev = scn->scn_dev;
+
+	bytes_read = 0;
+	ret = 0;
+
+	file->f_dentry->d_inode->i_atime = CURRENT_TIME; /* Update the
+                                                            atime of
+                                                            the device
+                                                            node */
+	while (count > 0) {
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+
+		this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
+
+		result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, scn->rd_nak_timeout);
+		dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", scn_minor, result, this_read, partial, count);
+
+/*
+ * Scanners are sometimes inheriently slow since they are mechanical
+ * in nature.  USB bulk reads tend to timeout while the scanner is
+ * positioning, resetting, warming up the lamp, etc if the timeout is
+ * set too low.  A very long timeout parameter for bulk reads was used
+ * to overcome this limitation, but this sometimes resulted in folks
+ * having to wait for the timeout to expire after pressing Ctrl-C from
+ * an application. The user was sometimes left with the impression
+ * that something had hung or crashed when in fact the USB read was
+ * just waiting on data.  So, the below code retains the same long
+ * timeout period, but splits it up into smaller parts so that
+ * Ctrl-C's are acted upon in a reasonable amount of time.
+ */
+
+		if (result == -ETIMEDOUT) { /* NAK */
+			if (!partial) { /* No data */
+				if (--rd_expire <= 0) {	/* Give it up */
+					warn("read_scanner(%d): excessive NAK's received", scn_minor);
+					ret = result;
+					break;
+				} else { /* Keep trying to read data */
+					interruptible_sleep_on_timeout(&scn->rd_wait_q, scn->rd_nak_timeout);
+					continue;
+				}
+			} else { /* Timeout w/ some data */
+				goto data_recvd;
+			}
+		}
+		
+		if (result == -EPIPE) { /* No hope */
+			if(usb_clear_halt(dev, scn->bulk_in_ep)) {
+				err("read_scanner(%d): Failure to clear endpoint halt condition (%Zd).", scn_minor, ret);
+			}
+			ret = result;
+			break;
+		} else if ((result < 0) && (result != -EREMOTEIO)) {
+			warn("read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt.", scn_minor, (int)result);
+			ret = -EIO;
+			break;
+		}
+
+	data_recvd:
+
+#ifdef RD_DATA_DUMP
+		if (partial) {
+			unsigned char cnt, cnt_max;
+			cnt_max = (partial > 24) ? 24 : partial;
+			printk(KERN_DEBUG "dump(%d): ", scn_minor);
+			for (cnt=0; cnt < cnt_max; cnt++) {
+				printk("%X ", ibuf[cnt]);
+			}
+			printk("\n");
+		}
+#endif
+
+		if (partial) { /* Data returned */
+			if (copy_to_user(buffer, ibuf, partial)) {
+				ret = -EFAULT;
+				break;
+			}
+			count -= this_read; /* Compensate for short reads */
+			bytes_read += partial; /* Keep tally of what actually was read */
+			buffer += partial;
+		} else {
+			ret = 0;
+			break;
+		}
+	}
+	up(&(scn->sem));
+	return ret ? ret : bytes_read;
+}
+
+static int
+ioctl_scanner(struct inode *inode, struct file *file,
+	      unsigned int cmd, unsigned long arg)
+{
+	struct usb_device *dev;
+
+	int scn_minor;
+
+	scn_minor = USB_SCN_MINOR(inode);
+
+	if (!p_scn_table[scn_minor]) {
+		err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
+		return -ENODEV;
+	}
+
+	dev = p_scn_table[scn_minor]->scn_dev;
+
+	switch (cmd)
+	{
+	case SCANNER_IOCTL_VENDOR :
+		return (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
+	case SCANNER_IOCTL_PRODUCT :
+		return (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
+#ifdef PV8630
+	case PV8630_IOCTL_INREQUEST :
+	{
+		int result;
+
+		struct {
+			__u8  data;
+			__u8  request;
+			__u16 value;
+			__u16 index;
+		} args;
+
+		if (copy_from_user(&args, (void *)arg, sizeof(args)))
+			return -EFAULT;
+
+		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+					 args.request, USB_TYPE_VENDOR|
+					 USB_RECIP_DEVICE|USB_DIR_IN,
+					 args.value, args.index, &args.data,
+					 1, HZ*5);
+
+		dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request);
+
+		if (copy_to_user((void *)arg, &args, sizeof(args)))
+			return -EFAULT;
+
+		dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
+
+		return result;
+	}
+	case PV8630_IOCTL_OUTREQUEST :
+	{
+		int result;
+
+		struct {
+			__u8  request;
+			__u16 value;
+			__u16 index;
+		} args;
+
+		if (copy_from_user(&args, (void *)arg, sizeof(args)))
+			return -EFAULT;
+
+		dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request);
+
+		result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+					 args.request, USB_TYPE_VENDOR|
+					 USB_RECIP_DEVICE|USB_DIR_OUT,
+					 args.value, args.index, NULL,
+					 0, HZ*5);
+
+		dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
+
+		return result;
+	}
+#endif /* PV8630 */
+ 	case SCANNER_IOCTL_CTRLMSG:
+ 	{
+ 		struct ctrlmsg_ioctl {
+ 			struct usb_ctrlrequest	req;
+ 			void			*data;
+ 		} cmsg;
+ 		int pipe, nb, ret;
+ 		unsigned char buf[64];
+ 
+ 		if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
+ 			return -EFAULT;
+
+ 		nb = le16_to_cpup(&cmsg.req.wLength);
+
+ 		if (nb > sizeof(buf))
+ 			return -EINVAL;
+
+ 		if ((cmsg.req.bRequestType & 0x80) == 0) {
+ 			pipe = usb_sndctrlpipe(dev, 0);
+ 			if (nb > 0 && copy_from_user(buf, cmsg.data, nb))
+ 				return -EFAULT;
+ 		} else {
+ 			pipe = usb_rcvctrlpipe(dev, 0);
+		}
+
+ 		ret = usb_control_msg(dev, pipe, cmsg.req.bRequest,
+ 				      cmsg.req.bRequestType,
+ 				      le16_to_cpup(&cmsg.req.wValue),
+ 				      le16_to_cpup(&cmsg.req.wIndex),
+ 				      buf, nb, HZ);
+
+ 		if (ret < 0) {
+ 			err("ioctl_scanner(%d): control_msg returned %d\n", scn_minor, ret);
+ 			return -EIO;
+ 		}
+
+ 		if (nb > 0 && (cmsg.req.bRequestType & 0x80) && copy_to_user(cmsg.data, buf, nb))
+ 			return -EFAULT;
+
+ 		return 0;
+ 	}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static struct
+file_operations usb_scanner_fops = {
+	read:		read_scanner,
+	write:		write_scanner,
+	ioctl:		ioctl_scanner,
+	open:		open_scanner,
+	release:	close_scanner,
+};
+
+static void *
+probe_scanner(struct usb_device *dev, unsigned int ifnum,
+	      const struct usb_device_id *id)
+{
+	struct scn_usb_data *scn;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+
+	int ep_cnt;
+	int ix;
+	int scn_minor;
+
+	char valid_device = 0;
+	char have_bulk_in, have_bulk_out, have_intr;
+	char name[10];
+
+	if (vendor != -1 && product != -1) {
+		info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product);
+	}
+
+	dbg("probe_scanner: USB dev address:%p", dev);
+	dbg("probe_scanner: ifnum:%u", ifnum);
+
+/*
+ * 1. Check Vendor/Product
+ * 2. Determine/Assign Bulk Endpoints
+ * 3. Determine/Assign Intr Endpoint
+ */
+
+/*
+ * There doesn't seem to be an imaging class defined in the USB
+ * Spec. (yet).  If there is, HP isn't following it and it doesn't
+ * look like anybody else is either.  Therefore, we have to test the
+ * Vendor and Product ID's to see what we have.  Also, other scanners
+ * may be able to use this driver by specifying both vendor and
+ * product ID's as options to the scanner module in conf.modules.
+ *
+ * NOTE: Just because a product is supported here does not mean that
+ * applications exist that support the product.  It's in the hopes
+ * that this will allow developers a means to produce applications
+ * that will support USB products.
+ *
+ * Until we detect a device which is pleasing, we silently punt.
+ */
+
+	for (ix = 0; ix < sizeof (scanner_device_ids) / sizeof (struct usb_device_id); ix++) {
+		if ((dev->descriptor.idVendor == scanner_device_ids [ix].idVendor) &&
+		    (dev->descriptor.idProduct == scanner_device_ids [ix].idProduct)) {
+			valid_device = 1;
+			break;
+                }
+	}
+	if (dev->descriptor.idVendor == vendor &&   /* User specified */
+	    dev->descriptor.idProduct == product) { /* User specified */
+		valid_device = 1;
+	}
+
+        if (!valid_device)
+                return NULL;    /* We didn't find anything pleasing */
+
+/*
+ * After this point we can be a little noisy about what we are trying to
+ *  configure.
+ */
+
+	if (dev->descriptor.bNumConfigurations != 1) {
+		info("probe_scanner: Only one device configuration is supported.");
+		return NULL;
+	}
+
+	if (dev->config[0].bNumInterfaces != 1) {
+		info("probe_scanner: Only one device interface is supported.");
+		return NULL;
+	}
+
+	interface = dev->config[0].interface[ifnum].altsetting;
+	endpoint = interface[ifnum].endpoint;
+
+/*
+ * Start checking for two bulk endpoints OR two bulk endpoints *and* one
+ * interrupt endpoint. If we have an interrupt endpoint go ahead and
+ * setup the handler. FIXME: This is a future enhancement...
+ */
+
+	dbg("probe_scanner: Number of Endpoints:%d", (int) interface->bNumEndpoints);
+
+	if ((interface->bNumEndpoints != 2) && (interface->bNumEndpoints != 3)) {
+		info("probe_scanner: Only two or three endpoints supported.");
+		return NULL;
+	}
+
+	ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0;
+
+	while (ep_cnt < interface->bNumEndpoints) {
+
+		if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {
+			ep_cnt++;
+			have_bulk_in = ep_cnt;
+			dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
+			continue;
+		}
+
+		if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
+			ep_cnt++;
+			have_bulk_out = ep_cnt;
+			dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out);
+			continue;
+		}
+
+		if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) {
+			ep_cnt++;
+			have_intr = ep_cnt;
+			dbg("probe_scanner: intr_ep:%d", have_intr);
+			continue;
+		}
+		info("probe_scanner: Undetected endpoint -- consult Documentation/usb/scanner.txt.");
+		return NULL;	/* Shouldn't ever get here unless we have something weird */
+	}
+
+
+/*
+ * Perform a quick check to make sure that everything worked as it
+ * should have.
+ */
+
+	switch(interface->bNumEndpoints) {
+	case 2:
+		if (!have_bulk_in || !have_bulk_out) {
+			info("probe_scanner: Two bulk endpoints required.");
+			return NULL;
+		}
+		break;
+	case 3:
+		if (!have_bulk_in || !have_bulk_out || !have_intr) {
+			info("probe_scanner: Two bulk endpoints and one interrupt endpoint required.");
+			return NULL;
+		}
+		break;
+	default:
+		info("probe_scanner: Endpoint determination failed --  consult Documentation/usb/scanner.txt");
+		return NULL;
+	}
+
+
+/*
+ * Determine a minor number and initialize the structure associated
+ * with it.  The problem with this is that we are counting on the fact
+ * that the user will sequentially add device nodes for the scanner
+ * devices.  */
+	
+	down(&scn_mutex);
+
+	for (scn_minor = 0; scn_minor < SCN_MAX_MNR; scn_minor++) {
+		if (!p_scn_table[scn_minor])
+			break;
+	}
+
+/* Check to make sure that the last slot isn't already taken */
+	if (p_scn_table[scn_minor]) {
+		err("probe_scanner: No more minor devices remaining.");
+		up(&scn_mutex);
+		return NULL;
+	}
+
+	dbg("probe_scanner: Allocated minor:%d", scn_minor);
+
+	if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
+		err("probe_scanner: Out of memory.");
+		up(&scn_mutex);
+		return NULL;
+	}
+	memset (scn, 0, sizeof(struct scn_usb_data));
+
+	scn->scn_irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!scn->scn_irq) {
+		kfree(scn);
+		up(&scn_mutex);
+		return NULL;
+	}
+
+	init_MUTEX(&(scn->sem)); /* Initializes to unlocked */
+
+	dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn);
+
+/* Ok, if we detected an interrupt EP, setup a handler for it */
+	if (have_intr) {
+		dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", scn_minor, have_intr);
+		FILL_INT_URB(scn->scn_irq, dev,
+			     usb_rcvintpipe(dev, have_intr),
+			     &scn->button, 1, irq_scanner, scn,
+			     // endpoint[(int)have_intr].bInterval);
+			     250);
+
+	        if (usb_submit_urb(scn->scn_irq, GFP_KERNEL)) {
+			err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor);
+                	kfree(scn);
+			up(&scn_mutex);
+                	return NULL;
+        	}
+	}
+
+
+/* Ok, now initialize all the relevant values */
+	if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+		err("probe_scanner(%d): Not enough memory for the output buffer.", scn_minor);
+		kfree(scn);
+		up(&scn_mutex);
+		return NULL;
+	}
+	dbg("probe_scanner(%d): obuf address:%p", scn_minor, scn->obuf);
+
+	if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+		err("probe_scanner(%d): Not enough memory for the input buffer.", scn_minor);
+		kfree(scn->obuf);
+		kfree(scn);
+		up(&scn_mutex);
+		return NULL;
+	}
+	dbg("probe_scanner(%d): ibuf address:%p", scn_minor, scn->ibuf);
+	
+
+	switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
+	case 0x04b8:		/* Seiko/Epson */
+		scn->rd_nak_timeout = HZ * 40;
+		break;
+	case 0x055f:		/* Mustek */
+	case 0x0400:		/* Another Mustek */
+	case 0x0ff5:		/* And yet another Mustek */
+		scn->rd_nak_timeout = HZ * 1;
+	default:
+		scn->rd_nak_timeout = RD_NAK_TIMEOUT;
+	}
+
+
+	if (read_timeout > 0) {	/* User specified read timeout overrides everything */
+		info("probe_scanner: User specified USB read timeout - %d", read_timeout);
+		scn->rd_nak_timeout = read_timeout;
+	}
+
+
+	scn->bulk_in_ep = have_bulk_in;
+	scn->bulk_out_ep = have_bulk_out;
+	scn->intr_ep = have_intr;
+	scn->present = 1;
+	scn->scn_dev = dev;
+	scn->scn_minor = scn_minor;
+	scn->isopen = 0;
+
+	sprintf(name, "scanner%d", scn->scn_minor);
+	
+	scn->devfs = devfs_register(usb_devfs_handle, name,
+				    DEVFS_FL_DEFAULT, USB_MAJOR,
+				    SCN_BASE_MNR + scn->scn_minor,
+				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
+				    S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL);
+	if (scn->devfs == NULL)
+		dbg("scanner%d: device node registration failed", scn_minor);
+
+	p_scn_table[scn_minor] = scn;
+
+	up(&scn_mutex);
+
+	return scn;
+}
+
+static void
+disconnect_scanner(struct usb_device *dev, void *ptr)
+{
+	struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
+
+	down (&scn_mutex);
+	down (&(scn->sem));
+
+	if(scn->intr_ep) {
+		dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
+		usb_unlink_urb(scn->scn_irq);
+	}
+        usb_driver_release_interface(&scanner_driver,
+                &scn->scn_dev->actconfig->interface[scn->ifnum]);
+
+	kfree(scn->ibuf);
+	kfree(scn->obuf);
+
+	dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
+	devfs_unregister(scn->devfs);
+	p_scn_table[scn->scn_minor] = NULL;
+	usb_free_urb(scn->scn_irq);
+	up (&(scn->sem));
+	kfree (scn);
+	up (&scn_mutex);
+}
+
+static struct
+usb_driver scanner_driver = {
+	name:		"usbscanner",
+	probe:		probe_scanner,
+	disconnect:	disconnect_scanner,
+	fops:		&usb_scanner_fops,
+	minor:		SCN_BASE_MNR,
+	id_table:	NULL, /* This would be scanner_device_ids, but we
+				 need to check every USB device, in case
+				 we match a user defined vendor/product ID. */
+};
+
+void __exit
+usb_scanner_exit(void)
+{
+	usb_deregister(&scanner_driver);
+}
+
+int __init
+usb_scanner_init (void)
+{
+        if (usb_register(&scanner_driver) < 0)
+                return -1;
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+module_init(usb_scanner_init);
+module_exit(usb_scanner_exit);
diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/image/scanner.h	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,261 @@
+/*
+ * Driver for USB Scanners (linux-2.4.12)
+ *
+ * Copyright (C) 1999, 2000, 2001 David E. Nelson
+ *
+ * David E. Nelson (dnelson@jump.net)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */ 
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+
+// #define DEBUG
+
+/* Enable this to support the older ioctl interfaces scanners that
+ * a PV8630 Scanner-On-Chip.  The prefered method is the
+ * SCANNER_IOCTL_CTRLMSG ioctl.
+ */
+// #define PV8630 
+
+#define DRIVER_VERSION "0.4.6"
+#define DRIVER_DESC "USB Scanner Driver"
+
+#include <linux/usb.h>
+
+static __s32 vendor=-1, product=-1, read_timeout=0;
+
+MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
+MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+MODULE_PARM(read_timeout, "i");
+MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
+
+
+/* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */
+// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
+// #define WR_DATA_DUMP /* DEBUG does not have to be defined. */
+
+static struct usb_device_id scanner_device_ids [] = {
+	/* Acer */
+	{ USB_DEVICE(0x04a5, 0x2060) },	/* Prisa Acerscan 620U & 640U (!)*/
+	{ USB_DEVICE(0x04a5, 0x2040) },	/* Prisa AcerScan 620U (!) */
+	{ USB_DEVICE(0x04a5, 0x20c0) },  /* Prisa AcerScan 1240UT */
+	{ USB_DEVICE(0x04a5, 0x2022) },	/* Vuego Scan Brisa 340U */
+	{ USB_DEVICE(0x04a5, 0x1a20) },	/* Unknown - Oliver Schwartz */
+	{ USB_DEVICE(0x04a5, 0x1a2a) },	/* Unknown - Oliver Schwartz */
+	{ USB_DEVICE(0x04a5, 0x207e) },	/* Prisa 640BU */
+	{ USB_DEVICE(0x04a5, 0x20be) },	/* Unknown - Oliver Schwartz */
+	{ USB_DEVICE(0x04a5, 0x20c0) },	/* Unknown - Oliver Schwartz */
+	{ USB_DEVICE(0x04a5, 0x20de) },	/* S2W 3300U */
+	{ USB_DEVICE(0x04a5, 0x20b0) },	/* Unknown - Oliver Schwartz */
+	{ USB_DEVICE(0x04a5, 0x20fe) },	/* Unknown - Oliver Schwartz */
+	/* Agfa */
+	{ USB_DEVICE(0x06bd, 0x0001) },	/* SnapScan 1212U */
+	{ USB_DEVICE(0x06bd, 0x0002) },	/* SnapScan 1236U */
+	{ USB_DEVICE(0x06bd, 0x2061) },	/* Another SnapScan 1212U (?)*/
+	{ USB_DEVICE(0x06bd, 0x0100) },	/* SnapScan Touch */
+	{ USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */
+	{ USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */
+	{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
+	{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
+	/* Canon */
+	{ USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
+	{ USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
+	{ USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
+	/* Colorado -- See Primax/Colorado below */
+	/* Epson -- See Seiko/Epson below */
+	/* Genius */
+	{ USB_DEVICE(0x0458, 0x2001) },	/* ColorPage-Vivid Pro */
+	{ USB_DEVICE(0x0458, 0x2007) },	/* ColorPage HR6 V2 */
+	{ USB_DEVICE(0x0458, 0x2008) },	/* Unknown */
+	{ USB_DEVICE(0x0458, 0x2009) },	/* Unknown */
+	{ USB_DEVICE(0x0458, 0x2013) },	/* Unknown */
+	{ USB_DEVICE(0x0458, 0x2015) },	/* Unknown  */
+	{ USB_DEVICE(0x0458, 0x2016) },	/* Unknown  */
+	/* Hewlett Packard */
+	{ USB_DEVICE(0x03f0, 0x0205) },	/* 3300C */
+	{ USB_DEVICE(0x03f0, 0x0405) }, /* 3400C */
+	{ USB_DEVICE(0x03f0, 0x0101) },	/* 4100C */
+	{ USB_DEVICE(0x03f0, 0x0105) },	/* 4200C */
+	{ USB_DEVICE(0x03f0, 0x0305) }, /* 4300C */
+	{ USB_DEVICE(0x03f0, 0x0102) },	/* PhotoSmart S20 */
+	{ USB_DEVICE(0x03f0, 0x0401) },	/* 5200C */
+	//	{ USB_DEVICE(0x03f0, 0x0701) },	/* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
+	{ USB_DEVICE(0x03f0, 0x0201) },	/* 6200C */
+	{ USB_DEVICE(0x03f0, 0x0601) },	/* 6300C */
+	{ USB_DEVICE(0x03f0, 0x605) },	/* 2200C */
+	/* iVina */
+	{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
+	/* Lifetec */
+	{ USB_DEVICE(0x05d8, 0x4002) }, /* Lifetec LT9385 */
+	/* Memorex */
+	{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
+	/* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */
+	//	{ USB_DEVICE(0x05da, 0x0099) },	/* ScanMaker X6 - X6U */
+	//	{ USB_DEVICE(0x05da, 0x0094) },	/* Phantom 336CX - C3 */
+	//	{ USB_DEVICE(0x05da, 0x00a0) },	/* Phantom 336CX - C3 #2 */
+	//	{ USB_DEVICE(0x05da, 0x009a) },	/* Phantom C6 */
+	//	{ USB_DEVICE(0x05da, 0x00a3) },	/* ScanMaker V6USL */
+	//	{ USB_DEVICE(0x05da, 0x80a3) },	/* ScanMaker V6USL #2 */
+	//	{ USB_DEVICE(0x05da, 0x80ac) },	/* ScanMaker V6UL - SpicyU */
+	/* Minolta */
+	//	{ USB_DEVICE(0x0638,0x026a) }, /* Minolta Dimage Scan Dual II */
+	/* Mustek */
+	{ USB_DEVICE(0x055f, 0x0001) },	/* 1200 CU */
+	{ USB_DEVICE(0x0400, 0x1000) },	/* BearPaw 1200 */
+	{ USB_DEVICE(0x055f, 0x0002) },	/* 600 CU */
+	{ USB_DEVICE(0x055f, 0x0873) }, /* 600 USB */
+	{ USB_DEVICE(0x055f, 0x0003) },	/* 1200 USB */
+	{ USB_DEVICE(0x055f, 0x0006) },	/* 1200 UB */
+	{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
+	{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
+	{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
+	/* Plustek */
+	{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
+	{ USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */
+	{ USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0010) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0013) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0015) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
+	/* Primax/Colorado */
+	{ USB_DEVICE(0x0461, 0x0300) },	/* G2-300 #1 */
+	{ USB_DEVICE(0x0461, 0x0380) },	/* G2-600 #1 */
+	{ USB_DEVICE(0x0461, 0x0301) },	/* G2E-300 #1 */
+	{ USB_DEVICE(0x0461, 0x0381) },	/* ReadyScan 636i */
+	{ USB_DEVICE(0x0461, 0x0302) },	/* G2-300 #2 */
+	{ USB_DEVICE(0x0461, 0x0382) },	/* G2-600 #2 */
+	{ USB_DEVICE(0x0461, 0x0303) },	/* G2E-300 #2 */
+	{ USB_DEVICE(0x0461, 0x0383) },	/* G2E-600 */
+	{ USB_DEVICE(0x0461, 0x0340) },	/* Colorado USB 9600 */
+	// { USB_DEVICE(0x0461, 0x0360) },	/* Colorado USB 19200 - undetected endpoint */
+	{ USB_DEVICE(0x0461, 0x0341) },	/* Colorado 600u */
+	{ USB_DEVICE(0x0461, 0x0361) },	/* Colorado 1200u */
+	/* Relisis */
+	// { USB_DEVICE(0x0475, 0x0103) },	/* Episode - undetected endpoint */
+	/* Seiko/Epson Corp. */
+	{ USB_DEVICE(0x04b8, 0x0101) },	/* Perfection 636U and 636Photo */
+	{ USB_DEVICE(0x04b8, 0x0103) },	/* Perfection 610 */
+	{ USB_DEVICE(0x04b8, 0x0104) },	/* Perfection 1200U and 1200Photo*/
+	{ USB_DEVICE(0x04b8, 0x0106) },	/* Stylus Scan 2500 */
+	{ USB_DEVICE(0x04b8, 0x0107) },	/* Expression 1600 */
+	{ USB_DEVICE(0x04b8, 0x010a) }, /* Perfection 1640SU and 1640SU Photo */
+	{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
+	{ USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */
+	{ USB_DEVICE(0x04b8, 0x010e) }, /* Expression 1680 */
+	{ USB_DEVICE(0x04b8, 0x0110) }, /* Perfection 1650 */
+	{ USB_DEVICE(0x04b8, 0x0112) }, /* Perfection 2450 - GT-9700 for the Japanese mkt */
+	/* Umax */
+	{ USB_DEVICE(0x1606, 0x0010) },	/* Astra 1220U */
+	{ USB_DEVICE(0x1606, 0x0030) },	/* Astra 2000U */
+	{ USB_DEVICE(0x1606, 0x0130) }, /* Astra 2100U */
+	{ USB_DEVICE(0x1606, 0x0230) },	/* Astra 2200U */
+	/* Visioneer */
+	{ USB_DEVICE(0x04a7, 0x0221) },	/* OneTouch 5300 USB */
+	{ USB_DEVICE(0x04a7, 0x0211) },	/* OneTouch 7600 USB */
+	{ USB_DEVICE(0x04a7, 0x0231) },	/* 6100 USB */
+	{ USB_DEVICE(0x04a7, 0x0311) },	/* 6200 EPP/USB */
+	{ USB_DEVICE(0x04a7, 0x0321) },	/* OneTouch 8100 EPP/USB */
+	{ USB_DEVICE(0x04a7, 0x0331) }, /* OneTouch 8600 EPP/USB */
+	{ }				/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, scanner_device_ids);
+
+#define IS_EP_BULK(ep)  ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
+#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
+
+#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
+
+#ifdef DEBUG
+#define SCN_DEBUG(X) X
+#else
+#define SCN_DEBUG(X)
+#endif
+
+#define IBUF_SIZE 32768
+#define OBUF_SIZE 4096
+
+/* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
+#define RD_NAK_TIMEOUT (10*HZ)	/* Default number of X seconds to wait */
+#define RD_EXPIRE 12		/* Number of attempts to wait X seconds */
+
+
+/* FIXME: These are NOT registered ioctls()'s */
+#ifdef PV8630
+#define PV8630_IOCTL_INREQUEST 69
+#define PV8630_IOCTL_OUTREQUEST 70
+#endif /* PV8630 */
+
+
+/* read vendor and product IDs from the scanner */
+#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
+#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
+/* send/recv a control message to the scanner */
+#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest)
+
+
+#define SCN_MAX_MNR 16		/* We're allocated 16 minors */
+#define SCN_BASE_MNR 48		/* USB Scanners start at minor 48 */
+
+static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
+
+struct scn_usb_data {
+	struct usb_device *scn_dev;
+	devfs_handle_t devfs;	/* devfs device */
+	struct urb *scn_irq;
+	unsigned int ifnum;	/* Interface number of the USB device */
+	int scn_minor;		/* Scanner minor - used in disconnect() */
+	unsigned char button;	/* Front panel buffer */
+	char isopen;		/* Not zero if the device is open */
+	char present;		/* Not zero if device is present */
+	char *obuf, *ibuf;	/* transfer buffers */
+	char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
+	wait_queue_head_t rd_wait_q; /* read timeouts */
+	struct semaphore sem; /* lock to prevent concurrent reads or writes */
+	unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
+};
+
+extern devfs_handle_t usb_devfs_handle;
+
+static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
+
+static struct usb_driver scanner_driver;
diff -Nru a/drivers/usb/inode.c b/drivers/usb/inode.c
--- a/drivers/usb/inode.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,735 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	inode.c  --  Inode/Dentry functions for the USB device file system.
- *
- *	Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
- *	Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:
- *   0.1  04.01.2000  Created
- *   0.2  10.12.2001  converted to use the vfs layer better
- */
-
-/*****************************************************************************/
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/pagemap.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/usb.h>
-#include <linux/usbdevice_fs.h>
-#include <linux/smp_lock.h>
-#include <asm/byteorder.h>
-
-static struct super_operations usbfs_ops;
-static struct file_operations default_file_operations;
-static struct inode_operations usbfs_dir_inode_operations;
-static struct vfsmount *usbfs_mount;
-static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
-static int mount_count;	/* = 0 */
-
-static struct dentry *devices_dentry;
-static struct dentry *drivers_dentry;
-static int num_buses;	/* = 0 */
-
-static uid_t devuid;	/* = 0 */
-static uid_t busuid;	/* = 0 */
-static uid_t listuid;	/* = 0 */
-static gid_t devgid;	/* = 0 */
-static gid_t busgid;	/* = 0 */
-static gid_t listgid;	/* = 0 */
-static umode_t devmode = S_IWUSR | S_IRUGO;
-static umode_t busmode = S_IXUGO | S_IRUGO;
-static umode_t listmode = S_IRUGO;
-
-static int parse_options(struct super_block *s, char *data)
-{
-	char *curopt = NULL, *value;
-
-	if (data)
-		curopt = strtok(data, ",");
-	for (; curopt; curopt = strtok(NULL, ",")) {
-		if ((value = strchr(curopt, '=')) != NULL)
-			*value++ = 0;
-		if (!strcmp(curopt, "devuid")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			devuid = simple_strtoul(value, &value, 0);
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "devgid")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			devgid = simple_strtoul(value, &value, 0);
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "devmode")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "busuid")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			busuid = simple_strtoul(value, &value, 0);
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "busgid")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			busgid = simple_strtoul(value, &value, 0);
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "busmode")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "listuid")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			listuid = simple_strtoul(value, &value, 0);
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "listgid")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			listgid = simple_strtoul(value, &value, 0);
-			if (*value)
-				return -EINVAL;
-		}
-		if (!strcmp(curopt, "listmode")) {
-			if (!value || !value[0])
-				return -EINVAL;
-			listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
-			if (*value)
-				return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-
-/* --------------------------------------------------------------------- */
-
-static struct inode *usbfs_get_inode (struct super_block *sb, int mode, int dev)
-{
-	struct inode *inode = new_inode(sb);
-
-	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = current->fsuid;
-		inode->i_gid = current->fsgid;
-		inode->i_blksize = PAGE_CACHE_SIZE;
-		inode->i_blocks = 0;
-		inode->i_rdev = NODEV;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		switch (mode & S_IFMT) {
-		default:
-			init_special_inode(inode, mode, dev);
-			break;
-		case S_IFREG:
-			inode->i_fop = &default_file_operations;
-			break;
-		case S_IFDIR:
-			inode->i_op = &usbfs_dir_inode_operations;
-			inode->i_fop = &simple_dir_operations;
-			break;
-		}
-	}
-	return inode; 
-}
-
-/* SMP-safe */
-static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
-			int dev)
-{
-	struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev);
-	int error = -ENOSPC;
-
-	if (inode) {
-		d_instantiate(dentry, inode);
-		dget(dentry);
-		error = 0;
-	}
-	return error;
-}
-
-static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
-{
-	return usbfs_mknod (dir, dentry, mode | S_IFDIR, 0);
-}
-
-static int usbfs_create (struct inode *dir, struct dentry *dentry, int mode)
-{
- 	return usbfs_mknod (dir, dentry, mode | S_IFREG, 0);
-}
-
-static inline int usbfs_positive (struct dentry *dentry)
-{
-	return dentry->d_inode && !d_unhashed(dentry);
-}
-
-static int usbfs_empty (struct dentry *dentry)
-{
-	struct list_head *list;
-
-	spin_lock(&dcache_lock);
-
-	list_for_each(list, &dentry->d_subdirs) {
-		struct dentry *de = list_entry(list, struct dentry, d_child);
-		if (usbfs_positive(de)) {
-			spin_unlock(&dcache_lock);
-			return 0;
-		}
-	}
-
-	spin_unlock(&dcache_lock);
-	return 1;
-}
-
-static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
-{
-	int error = -ENOTEMPTY;
-
-	if (usbfs_empty(dentry)) {
-		struct inode *inode = dentry->d_inode;
-
-		lock_kernel();
-		inode->i_nlink--;
-		unlock_kernel();
-		dput(dentry);
-		error = 0;
-	}
-	return error;
-}
-
-#define usbfs_rmdir usbfs_unlink
-
-/* default file operations */
-static ssize_t default_read_file (struct file *file, char *buf,
-				  size_t count, loff_t *ppos)
-{
-	return 0;
-}
-
-static ssize_t default_write_file (struct file *file, const char *buf,
-				   size_t count, loff_t *ppos)
-{
-	return count;
-}
-
-static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
-{
-	loff_t retval = -EINVAL;
-
-	lock_kernel();
-	switch(orig) {
-	case 0:
-		if (offset > 0) {
-			file->f_pos = offset;
-			retval = file->f_pos;
-		} 
-		break;
-	case 1:
-		if ((offset + file->f_pos) > 0) {
-			file->f_pos += offset;
-			retval = file->f_pos;
-		} 
-		break;
-	default:
-		break;
-	}
-	unlock_kernel();
-	return retval;
-}
-
-static int default_open (struct inode *inode, struct file *filp)
-{
-	if (inode->u.generic_ip)
-		filp->private_data = inode->u.generic_ip;
-
-	return 0;
-}
-
-static struct file_operations default_file_operations = {
-	read:		default_read_file,
-	write:		default_write_file,
-	open:		default_open,
-	llseek:		default_file_lseek,
-};
-
-static struct inode_operations usbfs_dir_inode_operations = {
-	create:		usbfs_create,
-	lookup:		simple_lookup,
-	unlink:		usbfs_unlink,
-	mkdir:		usbfs_mkdir,
-	rmdir:		usbfs_rmdir,
-};
-
-static struct super_operations usbfs_ops = {
-	statfs:		simple_statfs,
-	put_inode:	force_delete,
-};
-
-static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
-{
-	struct inode *inode;
-	struct dentry *root;
-
-	if (parse_options(sb, data)) {
-		warn("usbfs: mount parameter error:");
-		return -EINVAL;
-	}
-
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = USBDEVICE_SUPER_MAGIC;
-	sb->s_op = &usbfs_ops;
-	inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
-
-	if (!inode) {
-		dbg("%s: could not get inode!\n",__FUNCTION__);
-		return -ENOMEM;
-	}
-
-	root = d_alloc_root(inode);
-	if (!root) {
-		dbg("%s: could not get root dentry!\n",__FUNCTION__);
-		iput(inode);
-		return -ENOMEM;
-	}
-	sb->s_root = root;
-	return 0;
-}
-
-/**
- * fs_create_by_name - create a file, given a name
- * @name:	name of file
- * @mode:	type of file
- * @parent:	dentry of directory to create it in
- * @dentry:	resulting dentry of file
- *
- * There is a bit of overhead in creating a file - basically, we 
- * have to hash the name of the file, then look it up. This will
- * prevent files of the same name. 
- * We then call the proper vfs_ function to take care of all the 
- * file creation details. 
- * This function handles both regular files and directories.
- */
-static int fs_create_by_name (const char *name, mode_t mode,
-			      struct dentry *parent, struct dentry **dentry)
-{
-	struct dentry *d = NULL;
-	struct qstr qstr;
-	int error;
-
-	/* If the parent is not specified, we create it in the root.
-	 * We need the root dentry to do this, which is in the super 
-	 * block. A pointer to that is in the struct vfsmount that we
-	 * have around.
-	 */
-	if (!parent ) {
-		if (usbfs_mount && usbfs_mount->mnt_sb) {
-			parent = usbfs_mount->mnt_sb->s_root;
-		}
-	}
-
-	if (!parent) {
-		dbg("Ah! can not find a parent!\n");
-		return -EFAULT;
-	}
-
-	*dentry = NULL;
-	qstr.name = name;
-	qstr.len = strlen(name);
- 	qstr.hash = full_name_hash(name,qstr.len);
-
-	parent = dget(parent);
-
-	down(&parent->d_inode->i_sem);
-
-	d = lookup_hash(&qstr,parent);
-
-	error = PTR_ERR(d);
-	if (!IS_ERR(d)) {
-		switch(mode & S_IFMT) {
-			case 0: 
-			case S_IFREG:
-				error = vfs_create(parent->d_inode,d,mode);
-				break;
-			case S_IFDIR:
-				error = vfs_mkdir(parent->d_inode,d,mode);
-				break;
-			default:
-				err("cannot create special files\n");
-		}
-		*dentry = d;
-	}
-	up(&parent->d_inode->i_sem);
-
-	dput(parent);
-	return error;
-}
-
-static struct dentry *fs_create_file (const char *name, mode_t mode,
-				      struct dentry *parent, void *data,
-				      struct file_operations *fops,
-				      uid_t uid, gid_t gid)
-{
-	struct dentry *dentry;
-	int error;
-
-	dbg("creating file '%s'\n",name);
-
-	error = fs_create_by_name(name,mode,parent,&dentry);
-	if (error) {
-		dentry = NULL;
-	} else {
-		if (dentry->d_inode) {
-			if (data)
-				dentry->d_inode->u.generic_ip = data;
-			if (fops)
-				dentry->d_inode->i_fop = fops;
-			dentry->d_inode->i_uid = uid;
-			dentry->d_inode->i_gid = gid;
-		}
-	}
-
-	return dentry;
-}
-
-static void fs_remove_file (struct dentry *dentry)
-{
-	struct dentry *parent = dentry->d_parent;
-	
-	if (!parent || !parent->d_inode)
-		return;
-
-	down(&parent->d_inode->i_sem);
-	if (usbfs_positive(dentry)) {
-		if (dentry->d_inode) {
-			if (S_ISDIR(dentry->d_inode->i_mode))
-				vfs_rmdir(parent->d_inode,dentry);
-			else
-				vfs_unlink(parent->d_inode,dentry);
-		}
-
-		dput(dentry);
-	}
-	up(&parent->d_inode->i_sem);
-}
-
-/* --------------------------------------------------------------------- */
-
-
-
-/*
- * The usbdevfs name is now deprecated (as of 2.5.1).
- * It will be removed when the 2.7.x development cycle is started.
- * You have been warned :)
- */
-
-static struct super_block *usb_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
-{
-	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
-}
-
-static struct file_system_type usbdevice_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"usbdevfs",
-	get_sb:		usb_get_sb,
-	kill_sb:	kill_anon_super,
-};
-
-static struct file_system_type usb_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"usbfs",
-	get_sb:		usb_get_sb,
-	kill_sb:	kill_anon_super,
-};
-
-/* --------------------------------------------------------------------- */
-static int get_mount (void)
-{
-	struct vfsmount *mnt;
-
-	spin_lock (&mount_lock);
-	if (usbfs_mount) {
-		mntget(usbfs_mount);
-		++mount_count;
-		spin_unlock (&mount_lock);
-		goto go_ahead;
-	}
-
-	spin_unlock (&mount_lock);
-	mnt = kern_mount (&usbdevice_fs_type);
-	if (IS_ERR(mnt)) {
-		err ("could not mount the fs...erroring out!\n");
-		return -ENODEV;
-	}
-	spin_lock (&mount_lock);
-	if (!usbfs_mount) {
-		usbfs_mount = mnt;
-		++mount_count;
-		spin_unlock (&mount_lock);
-		goto go_ahead;
-	}
-	mntget(usbfs_mount);
-	++mount_count;
-	spin_unlock (&mount_lock);
-	mntput(mnt);
-
-go_ahead:
-	dbg("mount_count = %d\n", mount_count);
-	return 0;
-}
-
-static void remove_mount (void)
-{
-	struct vfsmount *mnt;
-
-	spin_lock (&mount_lock);
-	mnt = usbfs_mount;
-	--mount_count;
-	if (!mount_count)
-		usbfs_mount = NULL;
-
-	spin_unlock (&mount_lock);
-	mntput(mnt);
-	dbg("mount_count = %d\n", mount_count);
-}
-
-static int create_special_files (void)
-{
-	int retval;
-
-	/* create the devices and drivers special files */
-	retval = get_mount ();
-	if (retval)
-		return retval;
-	devices_dentry = fs_create_file ("devices",
-					 listmode | S_IFREG,
-					 NULL, NULL,
-					 &usbdevfs_devices_fops,
-					 listuid, listgid);
-	if (devices_dentry == NULL) {
-		err ("Unable to create devices usbfs file");
-		return -ENODEV;
-	}
-
-	drivers_dentry = fs_create_file ("drivers",
-					 listmode | S_IFREG,
-					 NULL, NULL,
-					 &usbdevfs_drivers_fops,
-					 listuid, listgid);
-	if (drivers_dentry == NULL) {
-		err ("Unable to create drivers usbfs file");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void remove_special_files (void)
-{
-	if (devices_dentry)
-		fs_remove_file (devices_dentry);
-	if (drivers_dentry)
-		fs_remove_file (drivers_dentry);
-	devices_dentry = NULL;
-	drivers_dentry = NULL;
-	remove_mount();
-}
-
-void usbfs_update_special (void)
-{
-	struct inode *inode;
-
-	if (devices_dentry) {
-		inode = devices_dentry->d_inode;
-		if (inode)
-			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	}
-	if (drivers_dentry) {
-		inode = devices_dentry->d_inode;
-		if (inode)
-			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	}
-}
-
-void usbfs_add_bus(struct usb_bus *bus)
-{
-	char name[8];
-	int retval;
-
-	/* create the special files if this is the first bus added */
-	if (num_buses == 0) {
-		retval = create_special_files();
-		if (retval)
-			return;
-	}
-	++num_buses;
-
-	sprintf (name, "%03d", bus->busnum);
-	bus->dentry = fs_create_file (name,
-				      busmode | S_IFDIR,
-				      NULL, bus, NULL,
-				      busuid, busgid);
-	if (bus->dentry == NULL)
-		return;
-
-	usbfs_update_special();
-	usbdevfs_conn_disc_event();
-}
-
-
-void usbfs_remove_bus(struct usb_bus *bus)
-{
-	if (bus->dentry) {
-		fs_remove_file (bus->dentry);
-		bus->dentry = NULL;
-	}
-
-	--num_buses;
-	if (num_buses <= 0) {
-		remove_special_files();
-		num_buses = 0;
-	}
-
-	usbfs_update_special();
-	usbdevfs_conn_disc_event();
-}
-
-void usbfs_add_device(struct usb_device *dev)
-{
-	char name[8];
-	int i;
-	int i_size;
-
-	sprintf (name, "%03d", dev->devnum);
-	dev->dentry = fs_create_file (name,
-				      devmode | S_IFREG,
-				      dev->bus->dentry, dev,
-				      &usbdevfs_device_file_operations,
-				      devuid, devgid);
-	if (dev->dentry == NULL)
-		return;
-
-	/* Set the size of the device's file to be
-	 * equal to the size of the device descriptors. */
-	i_size = sizeof (struct usb_device_descriptor);
-	for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) {
-		struct usb_config_descriptor *config =
-			(struct usb_config_descriptor *)dev->rawdescriptors[i];
-		i_size += le16_to_cpu (config->wTotalLength);
-	}
-	if (dev->dentry->d_inode)
-		dev->dentry->d_inode->i_size = i_size;
-
-	usbfs_update_special();
-	usbdevfs_conn_disc_event();
-}
-
-void usbfs_remove_device(struct usb_device *dev)
-{
-	struct dev_state *ds;
-	struct siginfo sinfo;
-
-	if (dev->dentry) {
-		fs_remove_file (dev->dentry);
-		dev->dentry = NULL;
-	}
-	while (!list_empty(&dev->filelist)) {
-		ds = list_entry(dev->filelist.next, struct dev_state, list);
-		list_del(&ds->list);
-		INIT_LIST_HEAD(&ds->list);
-		down_write(&ds->devsem);
-		ds->dev = NULL;
-		up_write(&ds->devsem);
-		if (ds->discsignr) {
-			sinfo.si_signo = SIGPIPE;
-			sinfo.si_errno = EPIPE;
-			sinfo.si_code = SI_ASYNCIO;
-			sinfo.si_addr = ds->disccontext;
-			send_sig_info(ds->discsignr, &sinfo, ds->disctask);
-		}
-	}
-	usbfs_update_special();
-	usbdevfs_conn_disc_event();
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef CONFIG_PROC_FS		
-static struct proc_dir_entry *usbdir = NULL;
-#endif	
-
-int __init usbfs_init(void)
-{
-	int retval;
-
-	retval = usb_register(&usbdevfs_driver);
-	if (retval)
-		return retval;
-
-	retval = register_filesystem(&usb_fs_type);
-	if (retval) {
-		usb_deregister(&usbdevfs_driver);
-		return retval;
-	}
-	retval = register_filesystem(&usbdevice_fs_type);
-	if (retval) {
-		unregister_filesystem(&usb_fs_type);
-		usb_deregister(&usbdevfs_driver);
-		return retval;
-	}
-
-#ifdef CONFIG_PROC_FS		
-	/* create mount point for usbdevfs */
-	usbdir = proc_mkdir("usb", proc_bus);
-#endif	
-
-	return 0;
-}
-
-void __exit usbfs_cleanup(void)
-{
-	usb_deregister(&usbdevfs_driver);
-	unregister_filesystem(&usb_fs_type);
-	unregister_filesystem(&usbdevice_fs_type);
-#ifdef CONFIG_PROC_FS	
-	if (usbdir)
-		remove_proc_entry("usb", proc_bus);
-#endif
-}
-
diff -Nru a/drivers/usb/input/Config.help b/drivers/usb/input/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,74 @@
+CONFIG_USB_HID
+  Say Y here if you want full HID support to connect keyboards,
+  mice, joysticks, graphic tablets, or any other HID based devices
+  to your computer via USB. You also need to select HID Input layer
+  support (below) if you want to use keyboards, mice, joysticks and
+  the like.
+
+  You can't use this driver and the HIDBP (Boot Protocol) keyboard
+  and mouse drivers at the same time. More information is available:
+  <file:Documentation/input/input.txt>.
+
+  If unsure, say Y.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called hid.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_HIDINPUT
+  Say Y here if you want to use a USB keyboard, mouse or joystick,
+  or any other HID input device. You also need Input layer support, 
+  (CONFIG_INPUT) which you select under "Input core support".
+
+  If unsure, say Y.
+
+CONFIG_USB_HIDDEV
+  Say Y here if you want to support HID devices (from the USB
+  specification standpoint) that aren't strictly user interface
+  devices, like monitor controls and Uninterruptable Power Supplies.
+
+  This module supports these devices separately using a separate
+  event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
+  This driver requires CONFIG_USB_HID.
+
+  If unsure, say Y.
+
+CONFIG_USB_KBD
+  Say Y here only if you are absolutely sure that you don't want
+  to use the generic HID driver for your USB keyboard and prefer
+  to use the keyboard in its limited Boot Protocol mode instead.
+
+  This is almost certainly not what you want.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbkbd.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+  If even remotely unsure, say N.
+
+CONFIG_USB_MOUSE
+  Say Y here only if you are absolutely sure that you don't want
+  to use the generic HID driver for your USB keyboard and prefer
+  to use the keyboard in its limited Boot Protocol mode instead.
+
+  This is almost certainly not what you want.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbmouse.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+  If even remotely unsure, say N.
+
+CONFIG_USB_WACOM
+  Say Y here if you want to use the USB version of the Wacom Intuos
+  or Graphire tablet.  Make sure to say Y to "Mouse support"
+  (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
+  (CONFIG_INPUT_EVDEV) as well.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called wacom.o.  If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/input/Config.in b/drivers/usb/input/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,27 @@
+#
+# USB Input driver configuration
+#
+comment 'USB Human Interface Devices (HID)'
+dep_tristate '  USB Human Interface Device (full HID) support' CONFIG_USB_HID $CONFIG_USB
+if [ "$CONFIG_INPUT" = "n" ]; then
+   comment '    Input core support is needed for USB HID input layer or HIDBP support'
+fi
+dep_mbool '    HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID
+dep_mbool '    /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
+
+if [ "$CONFIG_USB_HID" != "y" ]; then
+   dep_tristate '  USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
+   dep_tristate '  USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
+fi
+
+dep_tristate '  Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT
+
+# Turn on CONFIG_USB_INPUT if any of the drivers are compiled into the kernel
+# to make our Makefile logic a bit simpler.
+if [ "$CONFIG_USB_HID" = "y" -o "$CONFIG_USB_KBD" = "y" -o "$CONFIG_USB_MOUSE" = "y" ]; then
+   define_bool CONFIG_USB_INPUT y
+fi
+if [ "$CONFIG_USB_WACOM" = "y" ]; then
+   define_bool CONFIG_USB_INPUT y
+fi
+   
diff -Nru a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,24 @@
+#
+# Makefile for the USB input drivers
+#
+
+O_TARGET	:= usb-input.o
+
+# Multipart objects.
+hid-objs	:= hid-core.o
+
+# Optional parts of multipart objects.
+ifeq ($(CONFIG_USB_HIDDEV),y)
+	hid-objs        += hiddev.o
+endif
+ifeq ($(CONFIG_USB_HIDINPUT),y)
+	hid-objs        += hid-input.o
+endif
+
+obj-$(CONFIG_USB_HID)		+= hid.o
+obj-$(CONFIG_USB_KBD)		+= usbkbd.o
+obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o
+obj-$(CONFIG_USB_WACOM)		+= wacom.o
+
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/hid-core.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,1530 @@
+/*
+ * $Id: hid-core.c,v 1.42 2002/01/27 00:22:46 vojtech Exp $
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ *  USB HID support for Linux
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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/slab.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <linux/input.h>
+
+#undef DEBUG
+#undef DEBUG_DATA
+
+#include <linux/usb.h>
+
+#include "hid.h"
+#include <linux/hiddev.h>
+
+/*
+ * Version Information
+ */
+
+#define DRIVER_VERSION "v1.31"
+#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB HID core driver"
+#define DRIVER_LICENSE "GPL"
+
+static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
+				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
+
+/*
+ * Register a new report for a device.
+ */
+
+static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
+{
+	struct hid_report_enum *report_enum = device->report_enum + type;
+	struct hid_report *report;
+
+	if (report_enum->report_id_hash[id])
+		return report_enum->report_id_hash[id];
+
+	if (!(report = kmalloc(sizeof(struct hid_report), GFP_KERNEL)))
+		return NULL;
+	memset(report, 0, sizeof(struct hid_report));
+
+	if (id != 0) report_enum->numbered = 1;
+
+	report->id = id;
+	report->type = type;
+	report->size = 0;
+	report->device = device;
+	report_enum->report_id_hash[id] = report;
+
+	list_add_tail(&report->list, &report_enum->report_list);
+
+	return report;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+{
+	struct hid_field *field;
+
+	if (report->maxfield == HID_MAX_FIELDS) {
+		dbg("too many fields in report");
+		return NULL;
+	}
+
+	if (!(field = kmalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+		+ values * sizeof(unsigned), GFP_KERNEL))) return NULL;
+
+	memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+		+ values * sizeof(unsigned));
+
+	report->field[report->maxfield] = field;
+	field->usage = (struct hid_usage *)(field + 1);
+	field->value = (unsigned *)(field->usage + usages);
+	field->report = report;
+	field->index = report->maxfield++;
+
+	return field;
+}
+
+/*
+ * Open a collection. The type/usage is pushed on the stack.
+ */
+
+static int open_collection(struct hid_parser *parser, unsigned type)
+{
+	struct hid_collection *collection;
+	unsigned usage;
+
+	usage = parser->local.usage[0];
+
+	if (type == HID_COLLECTION_APPLICATION
+		&& parser->device->maxapplication < HID_MAX_APPLICATIONS)
+			parser->device->application[parser->device->maxapplication++] = usage;
+
+	if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
+		dbg("collection stack overflow");
+		return -1;
+	}
+
+	collection = parser->collection_stack + parser->collection_stack_ptr++;
+	collection->type = type;
+	collection->usage = usage;
+
+	return 0;
+}
+
+/*
+ * Close a collection.
+ */
+
+static int close_collection(struct hid_parser *parser)
+{
+	if (!parser->collection_stack_ptr) {
+		dbg("collection stack underflow");
+		return -1;
+	}
+	parser->collection_stack_ptr--;
+	return 0;
+}
+
+/*
+ * Climb up the stack, search for the specified collection type
+ * and return the usage.
+ */
+
+static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
+{
+	int n;
+	for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
+		if (parser->collection_stack[n].type == type)
+			return parser->collection_stack[n].usage;
+	return 0; /* we know nothing about this usage type */
+}
+
+/*
+ * Add a usage to the temporary parser table.
+ */
+
+static int hid_add_usage(struct hid_parser *parser, unsigned usage)
+{
+	if (parser->local.usage_index >= HID_MAX_USAGES) {
+		dbg("usage index exceeded");
+		return -1;
+	}
+	parser->local.usage[parser->local.usage_index++] = usage;
+	return 0;
+}
+
+/*
+ * Register a new field for this report.
+ */
+
+static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
+{
+	struct hid_report *report;
+	struct hid_field *field;
+	int usages;
+	unsigned offset;
+	int i;
+
+	if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
+		dbg("hid_register_report failed");
+		return -1;
+	}
+
+	if (parser->global.logical_maximum <= parser->global.logical_minimum) {
+		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+		return -1;
+	}
+	usages = parser->local.usage_index;
+
+	offset = report->size;
+	report->size += parser->global.report_size * parser->global.report_count;
+
+	if (usages == 0)
+		return 0; /* ignore padding fields */
+
+	if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
+		return 0;
+
+	field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
+	field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
+	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
+
+	for (i = 0; i < usages; i++)
+		field->usage[i].hid = parser->local.usage[i];
+
+	field->maxusage = usages;
+	field->flags = flags;
+	field->report_offset = offset;
+	field->report_type = report_type;
+	field->report_size = parser->global.report_size;
+	field->report_count = parser->global.report_count;
+	field->logical_minimum = parser->global.logical_minimum;
+	field->logical_maximum = parser->global.logical_maximum;
+	field->physical_minimum = parser->global.physical_minimum;
+	field->physical_maximum = parser->global.physical_maximum;
+	field->unit_exponent = parser->global.unit_exponent;
+	field->unit = parser->global.unit;
+
+	return 0;
+}
+
+/*
+ * Read data value from item.
+ */
+
+static __inline__ __u32 item_udata(struct hid_item *item)
+{
+	switch (item->size) {
+		case 1: return item->data.u8;
+		case 2: return item->data.u16;
+		case 4: return item->data.u32;
+	}
+	return 0;
+}
+
+static __inline__ __s32 item_sdata(struct hid_item *item)
+{
+	switch (item->size) {
+		case 1: return item->data.s8;
+		case 2: return item->data.s16;
+		case 4: return item->data.s32;
+	}
+	return 0;
+}
+
+/*
+ * Process a global item.
+ */
+
+static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
+{
+	switch (item->tag) {
+
+		case HID_GLOBAL_ITEM_TAG_PUSH:
+
+			if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
+				dbg("global enviroment stack overflow");
+				return -1;
+			}
+
+			memcpy(parser->global_stack + parser->global_stack_ptr++,
+				&parser->global, sizeof(struct hid_global));
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_POP:
+
+			if (!parser->global_stack_ptr) {
+				dbg("global enviroment stack underflow");
+				return -1;
+			}
+
+			memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
+				sizeof(struct hid_global));
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+			parser->global.usage_page = item_udata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+			parser->global.logical_minimum = item_sdata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+			if (parser->global.logical_minimum < 0)
+				parser->global.logical_maximum = item_sdata(item);
+			else
+				parser->global.logical_maximum = item_udata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+			parser->global.physical_minimum = item_sdata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+			if (parser->global.physical_minimum < 0)
+				parser->global.physical_maximum = item_sdata(item);
+			else
+				parser->global.physical_maximum = item_udata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+			parser->global.unit_exponent = item_sdata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_UNIT:
+			parser->global.unit = item_udata(item);
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+			if ((parser->global.report_size = item_udata(item)) > 32) {
+				dbg("invalid report_size %d", parser->global.report_size);
+				return -1;
+			}
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+			if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
+				dbg("invalid report_count %d", parser->global.report_count);
+				return -1;
+			}
+			return 0;
+
+		case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+			if ((parser->global.report_id = item_udata(item)) == 0) {
+				dbg("report_id 0 is invalid");
+				return -1;
+			}
+			return 0;
+
+		default:
+			dbg("unknown global tag 0x%x", item->tag);
+			return -1;
+	}
+}
+
+/*
+ * Process a local item.
+ */
+
+static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
+{
+	__u32 data;
+	unsigned n;
+
+	if (item->size == 0) {
+		dbg("item data expected for local item");
+		return -1;
+	}
+
+	data = item_udata(item);
+
+	switch (item->tag) {
+
+		case HID_LOCAL_ITEM_TAG_DELIMITER:
+
+			if (data) {
+				/*
+				 * We treat items before the first delimiter
+				 * as global to all usage sets (branch 0).
+				 * In the moment we process only these global
+				 * items and the first delimiter set.
+				 */
+				if (parser->local.delimiter_depth != 0) {
+					dbg("nested delimiters");
+					return -1;
+				}
+				parser->local.delimiter_depth++;
+				parser->local.delimiter_branch++;
+			} else {
+				if (parser->local.delimiter_depth < 1) {
+					dbg("bogus close delimiter");
+					return -1;
+				}
+				parser->local.delimiter_depth--;
+			}
+			return 1;
+
+		case HID_LOCAL_ITEM_TAG_USAGE:
+
+			if (parser->local.delimiter_branch > 1) {
+				dbg("alternative usage ignored");
+				return 0;
+			}
+
+			if (item->size <= 2)
+				data = (parser->global.usage_page << 16) + data;
+
+			return hid_add_usage(parser, data);
+
+		case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+
+			if (parser->local.delimiter_branch > 1) {
+				dbg("alternative usage ignored");
+				return 0;
+			}
+
+			if (item->size <= 2)
+				data = (parser->global.usage_page << 16) + data;
+
+			parser->local.usage_minimum = data;
+			return 0;
+
+		case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+
+			if (parser->local.delimiter_branch > 1) {
+				dbg("alternative usage ignored");
+				return 0;
+			}
+
+			if (item->size <= 2)
+				data = (parser->global.usage_page << 16) + data;
+
+			for (n = parser->local.usage_minimum; n <= data; n++)
+				if (hid_add_usage(parser, n)) {
+					dbg("hid_add_usage failed\n");
+					return -1;
+				}
+			return 0;
+
+		default:
+
+			dbg("unknown local item tag 0x%x", item->tag);
+			return 0;
+	}
+	return 0;
+}
+
+/*
+ * Process a main item.
+ */
+
+static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
+{
+	__u32 data;
+	int ret;
+
+	data = item_udata(item);
+
+	switch (item->tag) {
+		case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+			ret = open_collection(parser, data & 3);
+			break;
+		case HID_MAIN_ITEM_TAG_END_COLLECTION:
+			ret = close_collection(parser);
+			break;
+		case HID_MAIN_ITEM_TAG_INPUT:
+			ret = hid_add_field(parser, HID_INPUT_REPORT, data);
+			break;
+		case HID_MAIN_ITEM_TAG_OUTPUT:
+			ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
+			break;
+		case HID_MAIN_ITEM_TAG_FEATURE:
+			ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
+			break;
+		default:
+			dbg("unknown main item tag 0x%x", item->tag);
+			ret = 0;
+	}
+
+	memset(&parser->local, 0, sizeof(parser->local));	/* Reset the local parser environment */
+
+	return ret;
+}
+
+/*
+ * Process a reserved item.
+ */
+
+static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
+{
+	dbg("reserved item type, tag 0x%x", item->tag);
+	return 0;
+}
+
+/*
+ * Free a report and all registered fields. The field->usage and
+ * field->value table's are allocated behind the field, so we need
+ * only to free(field) itself.
+ */
+
+static void hid_free_report(struct hid_report *report)
+{
+	unsigned n;
+
+	for (n = 0; n < report->maxfield; n++)
+		kfree(report->field[n]);
+	kfree(report);
+}
+
+/*
+ * Free a device structure, all reports, and all fields.
+ */
+
+static void hid_free_device(struct hid_device *device)
+{
+	unsigned i,j;
+
+	for (i = 0; i < HID_REPORT_TYPES; i++) {
+		struct hid_report_enum *report_enum = device->report_enum + i;
+
+		for (j = 0; j < 256; j++) {
+			struct hid_report *report = report_enum->report_id_hash[j];
+			if (report) hid_free_report(report);
+		}
+	}
+
+	if (device->rdesc) kfree(device->rdesc);
+}
+
+/*
+ * Fetch a report description item from the data stream. We support long
+ * items, though they are not used yet.
+ */
+
+static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
+{
+	u8 b;
+
+	if ((end - start) <= 0)
+		return NULL;
+
+	b = *start++;
+
+	item->type = (b >> 2) & 3;
+	item->tag  = (b >> 4) & 15;
+
+	if (item->tag == HID_ITEM_TAG_LONG) {
+
+		item->format = HID_ITEM_FORMAT_LONG;
+
+		if ((end - start) < 2)
+			return NULL;
+
+		item->size = *start++;
+		item->tag  = *start++;
+
+		if ((end - start) < item->size) 
+			return NULL;
+
+		item->data.longdata = start;
+		start += item->size;
+		return start;
+	} 
+
+	item->format = HID_ITEM_FORMAT_SHORT;
+	item->size = b & 3;
+
+	switch (item->size) {
+
+		case 0:
+			return start;
+
+		case 1:
+			if ((end - start) < 1)
+				return NULL;
+			item->data.u8 = *start++;
+			return start;
+
+		case 2:
+			if ((end - start) < 2) 
+				return NULL;
+			item->data.u16 = le16_to_cpu(get_unaligned(((__u16*)start)++));
+			return start;
+
+		case 3:
+			item->size++;
+			if ((end - start) < 4)
+				return NULL;
+			item->data.u32 = le32_to_cpu(get_unaligned(((__u32*)start)++));
+			return start;
+	}
+
+	return NULL;
+}
+
+/*
+ * Parse a report description into a hid_device structure. Reports are
+ * enumerated, fields are attached to these reports.
+ */
+
+static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+{
+	struct hid_device *device;
+	struct hid_parser *parser;
+	struct hid_item item;
+	__u8 *end;
+	unsigned i;
+	static int (*dispatch_type[])(struct hid_parser *parser,
+				      struct hid_item *item) = {
+		hid_parser_main,
+		hid_parser_global,
+		hid_parser_local,
+		hid_parser_reserved
+	};
+
+	if (!(device = kmalloc(sizeof(struct hid_device), GFP_KERNEL)))
+		return NULL;
+	memset(device, 0, sizeof(struct hid_device));
+
+	for (i = 0; i < HID_REPORT_TYPES; i++)
+		INIT_LIST_HEAD(&device->report_enum[i].report_list);
+
+	if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
+		kfree(device);
+		return NULL;
+	}
+	memcpy(device->rdesc, start, size);
+
+	if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
+		kfree(device->rdesc);
+		kfree(device);
+		return NULL;
+	}
+	memset(parser, 0, sizeof(struct hid_parser));
+	parser->device = device;
+
+	end = start + size;
+	while ((start = fetch_item(start, end, &item)) != 0) {
+
+		if (item.format != HID_ITEM_FORMAT_SHORT) {
+			dbg("unexpected long global item");
+			hid_free_device(device);
+			kfree(parser);
+			return NULL;
+		}
+
+		if (dispatch_type[item.type](parser, &item)) {
+			dbg("item %u %u %u %u parsing failed\n",
+				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
+			hid_free_device(device);
+			kfree(parser);
+			return NULL;
+		}
+
+		if (start == end) {
+			if (parser->collection_stack_ptr) {
+				dbg("unbalanced collection at end of report description");
+				hid_free_device(device);
+				kfree(parser);
+				return NULL;
+			}
+			if (parser->local.delimiter_depth) {
+				dbg("unbalanced delimiter at end of report description");
+				hid_free_device(device);
+				kfree(parser);
+				return NULL;
+			}
+			kfree(parser);
+			return device;
+		}
+	}
+
+	dbg("item fetching failed at offset %d\n", (int)(end - start));
+	hid_free_device(device);
+	kfree(parser);
+	return NULL;
+}
+
+/*
+ * Convert a signed n-bit integer to signed 32-bit integer. Common
+ * cases are done through the compiler, the screwed things has to be
+ * done by hand.
+ */
+
+static __inline__ __s32 snto32(__u32 value, unsigned n)
+{
+	switch (n) {
+		case 8:  return ((__s8)value);
+		case 16: return ((__s16)value);
+		case 32: return ((__s32)value);
+	}
+	return value & (1 << (n - 1)) ? value | (-1 << n) : value;
+}
+
+/*
+ * Convert a signed 32-bit integer to a signed n-bit integer.
+ */
+
+static __inline__ __u32 s32ton(__s32 value, unsigned n)
+{
+	__s32 a = value >> (n - 1);
+	if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
+	return value & ((1 << n) - 1);
+}
+
+/*
+ * Extract/implement a data field from/to a report.
+ */
+
+static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+{
+	report += (offset >> 5) << 2; offset &= 31;
+	return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1);
+}
+
+static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
+{
+	report += (offset >> 5) << 2; offset &= 31;
+	put_unaligned((get_unaligned((__u64*)report)
+		& cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
+		| cpu_to_le64((__u64)value << offset), (__u64*)report);
+}
+
+/*
+ * Search an array for a value.
+ */
+
+static __inline__ int search(__s32 *array, __s32 value, unsigned n)
+{
+	while (n--) if (*array++ == value) return 0;
+	return -1;
+}
+
+static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
+{
+	hid_dump_input(usage, value);
+	if (hid->claimed & HID_CLAIMED_INPUT)
+		hidinput_hid_event(hid, field, usage, value);
+#ifdef CONFIG_USB_HIDDEV
+	if (hid->claimed & HID_CLAIMED_HIDDEV) {
+		struct hiddev_usage_ref uref;
+		unsigned type = field->report_type;
+		uref.report_type = 
+		  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
+		  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : 
+		   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+		uref.report_id = field->report->id;
+		uref.field_index = field->index;
+		uref.usage_index = (usage - field->usage);
+		uref.usage_code = usage->hid;
+		uref.value = value;
+		hiddev_hid_event(hid, &uref);
+	}
+#endif
+}
+
+/*
+ * Analyse a received field, and fetch the data from it. The field
+ * content is stored for next report processing (we do differential
+ * reporting to the layer).
+ */
+
+static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data)
+{
+	unsigned n;
+	unsigned count = field->report_count;
+	unsigned offset = field->report_offset;
+	unsigned size = field->report_size;
+	__s32 min = field->logical_minimum;
+	__s32 max = field->logical_maximum;
+	__s32 value[count]; /* WARNING: gcc specific */
+
+	for (n = 0; n < count; n++) {
+
+			value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
+						    extract(data, offset + n * size, size);
+
+			if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
+			    && value[n] >= min && value[n] <= max
+			    && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+				return;
+	}
+
+	for (n = 0; n < count; n++) {
+
+		if (HID_MAIN_ITEM_VARIABLE & field->flags) {
+
+			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+				if (!value[n]) continue;
+			} else {
+				if (value[n] == field->value[n]) continue;
+			}	
+			hid_process_event(hid, field, &field->usage[n], value[n]);
+			continue;
+		}
+
+		if (field->value[n] >= min && field->value[n] <= max
+			&& field->usage[field->value[n] - min].hid
+			&& search(value, field->value[n], count))
+				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0);
+
+		if (value[n] >= min && value[n] <= max
+			&& field->usage[value[n] - min].hid
+			&& search(field->value, value[n], count))
+				hid_process_event(hid, field, &field->usage[value[n] - min], 1);
+	}
+
+	memcpy(field->value, value, count * sizeof(__s32));
+}
+
+static int hid_input_report(int type, struct urb *urb)
+{
+	struct hid_device *hid = urb->context;
+	struct hid_report_enum *report_enum = hid->report_enum + type;
+	u8 *data = urb->transfer_buffer;
+	int len = urb->actual_length;
+	struct hid_report *report;
+	int n, size;
+
+	if (!len) {
+		dbg("empty report");
+		return -1;
+	}
+
+#ifdef DEBUG_DATA
+	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
+#endif
+
+	n = 0;				/* Normally report number is 0 */
+	if (report_enum->numbered) {	/* Device uses numbered reports, data[0] is report number */
+		n = *data++;
+		len--;
+	}
+
+#ifdef DEBUG_DATA
+	{
+		int i;
+		printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len);
+		for (i = 0; i < n; i++)
+			printk(" %02x", data[i]);
+		printk("\n");
+	}
+#endif
+
+	if (!(report = report_enum->report_id_hash[n])) {
+		dbg("undefined report_id %d received", n);
+		return -1;
+	}
+
+#ifdef CONFIG_USB_HIDDEV
+	/* Notify listeners that a report has been received */
+	if (hid->claimed & HID_CLAIMED_HIDDEV) {
+		struct hiddev_usage_ref uref;
+		memset(&uref, 0, sizeof(uref));
+		uref.report_type = 
+		  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
+		  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : 
+		   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+		uref.report_id = report->id;
+		uref.field_index = HID_FIELD_INDEX_NONE;
+		hiddev_hid_event(hid, &uref);
+	}
+#endif
+
+	size = ((report->size - 1) >> 3) + 1;
+
+	if (len < size) {
+		dbg("report %d is too short, (%d < %d)", report->id, len, size);
+		return -1;
+	}
+
+	for (n = 0; n < report->maxfield; n++)
+		hid_input_field(hid, report->field[n], data);
+
+	return 0;
+}
+
+/*
+ * Input interrupt completion handler.
+ */
+
+static void hid_irq_in(struct urb *urb)
+{
+	if (urb->status) {
+		dbg("nonzero status in input irq %d", urb->status);
+		return;
+	}
+
+	hid_input_report(HID_INPUT_REPORT, urb);
+}
+
+/*
+ * Output the field into the report.
+ */
+
+static void hid_output_field(struct hid_field *field, __u8 *data)
+{
+	unsigned count = field->report_count;
+	unsigned offset = field->report_offset;
+	unsigned size = field->report_size;
+	unsigned n;
+
+	for (n = 0; n < count; n++) {
+		if (field->logical_minimum < 0)	/* signed values */
+			implement(data, offset + n * size, size, s32ton(field->value[n], size));
+		 else				/* unsigned values */
+			implement(data, offset + n * size, size, field->value[n]);
+	}
+}
+
+/*
+ * Create a report.
+ */
+
+void hid_output_report(struct hid_report *report, __u8 *data)
+{
+	unsigned n;
+	for (n = 0; n < report->maxfield; n++)
+		hid_output_field(report->field[n], data);
+}
+
+/*
+ * Set a field value. The report this field belongs to has to be
+ * created and transfered to the device, to set this value in the
+ * device.
+ */
+
+int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
+{
+	unsigned size = field->report_size;
+
+	hid_dump_input(field->usage + offset, value);
+
+	if (offset >= field->report_count) {
+		dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+		hid_dump_field(field, 8);
+		return -1;
+	}
+	if (field->logical_minimum < 0) {
+		if (value != snto32(s32ton(value, size), size)) {
+			dbg("value %d is out of range", value);
+			return -1;
+		}
+	}
+	field->value[offset] = value;
+	return 0;
+}
+
+int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+	struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
+	struct list_head *list = report_enum->report_list.next;
+	int i, j;
+
+	while (list != &report_enum->report_list) {
+		struct hid_report *report = (struct hid_report *) list;
+		list = list->next;
+		for (i = 0; i < report->maxfield; i++) {
+			*field = report->field[i];
+			for (j = 0; j < (*field)->maxusage; j++)
+				if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+					return j;
+		}
+	}
+	return -1;
+}
+
+/*
+ * Find a report with a specified HID usage.
+ */
+
+int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type)
+{
+	struct hid_report_enum *report_enum = hid->report_enum + type;
+	struct list_head *list = report_enum->report_list.next;
+	int i, j;
+
+	while (list != &report_enum->report_list) {
+		*report = (struct hid_report *) list;
+		list = list->next;
+		for (i = 0; i < (*report)->maxfield; i++) {
+			struct hid_field *field = (*report)->field[i];
+			for (j = 0; j < field->maxusage; j++)
+				if (field->logical == wanted_usage)
+					return j;
+		}
+	}
+	return -1;
+}
+
+int hid_find_field_in_report(struct hid_report *report, __u32 wanted_usage, struct hid_field **field)
+{
+	int i, j;
+
+	for (i = 0; i < report->maxfield; i++) {
+		*field = report->field[i];
+		for (j = 0; j < (*field)->maxusage; j++)
+			if ((*field)->usage[j].hid == wanted_usage)
+				return j;
+	}
+
+	return -1;
+}
+
+static int hid_submit_out(struct hid_device *hid)
+{
+	struct hid_report *report;
+
+	report = hid->out[hid->outtail];
+
+	hid_output_report(report, hid->outbuf);
+	hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1;
+	hid->urbout->dev = hid->dev;
+
+	dbg("submitting out urb");
+
+	if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
+		err("usb_submit_urb(out) failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int hid_submit_ctrl(struct hid_device *hid)
+{
+	struct hid_report *report;
+	unsigned char dir;
+
+	report = hid->ctrl[hid->ctrltail].report;
+	dir = hid->ctrl[hid->ctrltail].dir;
+
+	if (dir == USB_DIR_OUT)
+		hid_output_report(report, hid->ctrlbuf);
+
+	hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && (dir != USB_DIR_OUT));
+	hid->urbctrl->pipe = (dir == USB_DIR_OUT) ?  usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);
+	hid->urbctrl->dev = hid->dev;
+
+	hid->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
+	hid->cr.bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
+	hid->cr.wValue = ((report->type + 1) << 8) | report->id;
+	hid->cr.wIndex = cpu_to_le16(hid->ifnum);
+	hid->cr.wLength = cpu_to_le16(hid->urbctrl->transfer_buffer_length);
+
+	dbg("submitting ctrl urb");
+
+	if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
+		err("usb_submit_urb(ctrl) failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Output interrupt completion handler.
+ */
+
+static void hid_irq_out(struct urb *urb)
+{
+	struct hid_device *hid = urb->context;
+	unsigned long flags;
+
+	if (urb->status)
+		warn("output irq status %d received", urb->status);
+
+	spin_lock_irqsave(&hid->outlock, flags);
+
+	hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+
+	if (hid->outhead != hid->outtail) {
+		hid_submit_out(hid);
+		spin_unlock_irqrestore(&hid->outlock, flags);
+		return;
+	}
+
+	clear_bit(HID_OUT_RUNNING, &hid->iofl);
+
+	spin_unlock_irqrestore(&hid->outlock, flags);
+
+	wake_up(&hid->wait);
+}
+
+/*
+ * Control pipe completion handler.
+ */
+
+static void hid_ctrl(struct urb *urb)
+{
+	struct hid_device *hid = urb->context;
+	unsigned long flags;
+
+	if (urb->status)
+		warn("ctrl urb status %d received", urb->status);
+
+	spin_lock_irqsave(&hid->ctrllock, flags);
+
+	if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
+		hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb);
+
+	hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+
+	if (hid->ctrlhead != hid->ctrltail) {
+		hid_submit_ctrl(hid);
+		spin_unlock_irqrestore(&hid->ctrllock, flags);
+		return;
+	}
+
+	clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+
+	spin_unlock_irqrestore(&hid->ctrllock, flags);
+
+	wake_up(&hid->wait);
+}
+
+void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+{
+	int head;
+	unsigned long flags;
+
+	if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
+		return;
+
+	if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
+
+		spin_lock_irqsave(&hid->outlock, flags);
+
+		if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
+			spin_unlock_irqrestore(&hid->outlock, flags);
+			warn("output queue full");
+			return;
+		}
+
+		hid->out[hid->outhead] = report;
+		hid->outhead = head;
+
+		if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
+			hid_submit_out(hid);
+
+		spin_unlock_irqrestore(&hid->outlock, flags);
+		return;
+	}
+
+	spin_lock_irqsave(&hid->ctrllock, flags);
+
+	if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
+		spin_unlock_irqrestore(&hid->ctrllock, flags);
+		warn("control queue full");
+		return;
+	}
+
+	hid->ctrl[hid->ctrlhead].report = report;
+	hid->ctrl[hid->ctrlhead].dir = dir;
+	hid->ctrlhead = head;
+
+	if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
+		hid_submit_ctrl(hid);
+
+	spin_unlock_irqrestore(&hid->ctrllock, flags);
+}
+
+int hid_wait_io(struct hid_device *hid)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = 10*HZ;
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	add_wait_queue(&hid->wait, &wait);
+
+	while (timeout && test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
+			  test_bit(HID_OUT_RUNNING, &hid->iofl))
+		timeout = schedule_timeout(timeout);
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&hid->wait, &wait);
+
+	if (!timeout) {
+		dbg("timeout waiting for ctrl or out queue to clear");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
+		unsigned char type, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
+		(type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+int hid_open(struct hid_device *hid)
+{
+	if (hid->open++)
+		return 0;
+
+	hid->urbin->dev = hid->dev;
+
+	if (usb_submit_urb(hid->urbin, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+void hid_close(struct hid_device *hid)
+{
+	if (!--hid->open)
+		usb_unlink_urb(hid->urbin);
+}
+
+/*
+ * Initialize all reports
+ */
+
+void hid_init_reports(struct hid_device *hid)
+{
+	struct hid_report_enum *report_enum;
+	struct hid_report *report;
+	struct list_head *list;
+	int len;
+
+	report_enum = hid->report_enum + HID_INPUT_REPORT;
+	list = report_enum->report_list.next;
+	while (list != &report_enum->report_list) {
+		report = (struct hid_report *) list;
+		hid_submit_report(hid, report, USB_DIR_IN);
+		list = list->next;
+	}
+
+	report_enum = hid->report_enum + HID_FEATURE_REPORT;
+	list = report_enum->report_list.next;
+	while (list != &report_enum->report_list) {
+		report = (struct hid_report *) list;
+		hid_submit_report(hid, report, USB_DIR_IN);
+		list = list->next;
+	}
+
+	if (hid_wait_io(hid)) {
+		warn("timeout initializing reports\n");
+		return;
+	}
+
+	report_enum = hid->report_enum + HID_INPUT_REPORT;
+	list = report_enum->report_list.next;
+	while (list != &report_enum->report_list) {
+		report = (struct hid_report *) list;
+		len = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+		if (len > hid->urbin->transfer_buffer_length)
+			hid->urbin->transfer_buffer_length = len < HID_BUFFER_SIZE ? len : HID_BUFFER_SIZE;
+		usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
+			0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
+			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+		list = list->next;
+	}
+}
+
+#define USB_VENDOR_ID_WACOM		0x056a
+#define USB_DEVICE_ID_WACOM_GRAPHIRE	0x0010
+#define USB_DEVICE_ID_WACOM_INTUOS	0x0020
+
+#define USB_VENDOR_ID_GRIFFIN		0x077d
+#define USB_DEVICE_ID_POWERMATE		0x0410
+#define USB_DEVICE_ID_SOUNDKNOB		0x04AA
+
+#define USB_VENDOR_ID_ATEN             0x0557  
+#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
+#define USB_DEVICE_ID_ATEN_CS124U      0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
+
+struct hid_blacklist {
+	__u16 idVendor;
+	__u16 idProduct;
+	unsigned quirks;
+} hid_blacklist[] = {
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE  },
+	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE  },
+	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
+	{ 0, 0 }
+};
+
+static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
+{
+	struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
+	struct hid_descriptor *hdesc;
+	struct hid_device *hid;
+	unsigned quirks = 0, rsize = 0;
+	char *buf;
+	int n;
+
+	for (n = 0; hid_blacklist[n].idVendor; n++)
+		if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
+			(hid_blacklist[n].idProduct == dev->descriptor.idProduct))
+				quirks = hid_blacklist[n].quirks;
+
+	if (quirks & HID_QUIRK_IGNORE)
+		return NULL;
+
+	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
+		usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
+			dbg("class descriptor not present\n");
+			return NULL;
+	}
+
+	for (n = 0; n < hdesc->bNumDescriptors; n++)
+		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
+			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
+
+	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
+		dbg("weird size of report descriptor (%u)", rsize);
+		return NULL;
+	}
+
+	{
+		__u8 rdesc[rsize];
+
+		if ((n = hid_get_class_descriptor(dev, interface->bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
+			dbg("reading report descriptor failed");
+			return NULL;
+		}
+
+#ifdef DEBUG_DATA
+		printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+		for (n = 0; n < rsize; n++)
+			printk(" %02x", (unsigned) rdesc[n]);
+		printk("\n");
+#endif
+
+		if (!(hid = hid_parse_report(rdesc, rsize))) {
+			dbg("parsing report descriptor failed");
+			return NULL;
+		}
+	}
+
+	hid->quirks = quirks;
+
+	for (n = 0; n < interface->bNumEndpoints; n++) {
+
+		struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
+		int pipe;
+
+		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
+			continue;
+
+		if (endpoint->bEndpointAddress & USB_DIR_IN) {
+			if (hid->urbin)
+				continue;
+			if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
+				goto fail;
+			pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+			FILL_INT_URB(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, endpoint->bInterval);
+		} else {
+			if (hid->urbout)
+				continue;
+			if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
+				goto fail;
+			pipe = usb_sndbulkpipe(dev, endpoint->bEndpointAddress);
+			FILL_BULK_URB(hid->urbout, dev, pipe, hid->outbuf, 0, hid_irq_out, hid);
+		}
+	}
+
+	if (!hid->urbin) {
+		err("couldn't find an input interrupt endpoint");
+		goto fail;
+	}
+
+	init_waitqueue_head(&hid->wait);
+	
+	hid->outlock = SPIN_LOCK_UNLOCKED;
+	hid->ctrllock = SPIN_LOCK_UNLOCKED;
+
+	hid->version = hdesc->bcdHID;
+	hid->country = hdesc->bCountryCode;
+	hid->dev = dev;
+	hid->ifnum = interface->bInterfaceNumber;
+
+	hid->name[0] = 0;
+
+	if (!(buf = kmalloc(64, GFP_KERNEL)))
+		goto fail;
+
+	if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
+		strcat(hid->name, buf);
+		if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
+			sprintf(hid->name, "%s %s", hid->name, buf);
+	} else
+		sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+	usb_make_path(dev, buf, 63);
+	sprintf(hid->phys, "%s/input%d", buf, ifnum);
+
+	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
+		hid->uniq[0] = 0;
+
+	kfree(buf);
+
+	hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+	FILL_CONTROL_URB(hid->urbctrl, dev, 0, (void*) &hid->cr, hid->ctrlbuf, 1, hid_ctrl, hid);
+
+	return hid;
+
+fail:
+
+	hid_free_device(hid);
+	if (hid->urbin) usb_free_urb(hid->urbin);
+	if (hid->urbout) usb_free_urb(hid->urbout);
+	if (hid->urbctrl) usb_free_urb(hid->urbctrl);
+
+	return NULL;
+}
+
+static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
+		       const struct usb_device_id *id)
+{
+	struct hid_device *hid;
+	char path[64];
+	int i;
+	char *c;
+
+	dbg("HID probe called for ifnum %d", ifnum);
+
+	if (!(hid = usb_hid_configure(dev, ifnum)))
+		return NULL;
+
+	hid_init_reports(hid);
+	hid_dump_device(hid);
+
+	if (!hidinput_connect(hid))
+		hid->claimed |= HID_CLAIMED_INPUT;
+	if (!hiddev_connect(hid))
+		hid->claimed |= HID_CLAIMED_HIDDEV;
+
+	if (!hid->claimed) {
+		hid_free_device(hid);
+		return NULL;
+	}
+
+	printk(KERN_INFO);
+
+	if (hid->claimed & HID_CLAIMED_INPUT)
+		printk("input");
+	if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))
+		printk(",");
+	if (hid->claimed & HID_CLAIMED_HIDDEV)
+		printk("hiddev%d", hid->minor);
+
+	c = "Device";
+	for (i = 0; i < hid->maxapplication; i++)
+		if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
+			c = hid_types[hid->application[i] & 0xffff];
+			break;
+		}
+
+	usb_make_path(dev, path, 63);
+
+	printk(": USB HID v%x.%02x %s [%s] on %s\n",
+		hid->version >> 8, hid->version & 0xff, c, hid->name, path);
+
+	return hid;
+}
+
+static void hid_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct hid_device *hid = ptr;
+
+	usb_unlink_urb(hid->urbin);
+	usb_unlink_urb(hid->urbout);
+	usb_unlink_urb(hid->urbctrl);
+
+	if (hid->claimed & HID_CLAIMED_INPUT)
+		hidinput_disconnect(hid);
+	if (hid->claimed & HID_CLAIMED_HIDDEV)
+		hiddev_disconnect(hid);
+
+	usb_free_urb(hid->urbin);
+	usb_free_urb(hid->urbctrl);
+	if (hid->urbout)
+		usb_free_urb(hid->urbout);
+
+	hid_free_device(hid);
+}
+
+static struct usb_device_id hid_usb_ids [] = {
+	{ match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,
+	    bInterfaceClass: USB_INTERFACE_CLASS_HID },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, hid_usb_ids);
+
+static struct usb_driver hid_driver = {
+	name:		"hid",
+	probe:		hid_probe,
+	disconnect:	hid_disconnect,
+	id_table:	hid_usb_ids,
+};
+
+static int __init hid_init(void)
+{
+	hiddev_init();
+	usb_register(&hid_driver);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+
+	return 0;
+}
+
+static void __exit hid_exit(void)
+{
+	hiddev_exit();
+	usb_deregister(&hid_driver);
+}
+
+module_init(hid_init);
+module_exit(hid_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
diff -Nru a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/hid-debug.h	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,386 @@
+/*
+ * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
+ *
+ *  (c) 1999 Andreas Gal		<gal@cs.uni-magdeburg.de>
+ *  (c) 2000-2001 Vojtech Pavlik	<vojtech@ucw.cz>
+ *
+ *  Some debug stuff for the HID parser.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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
+ */
+
+struct hid_usage_entry {
+	unsigned  page;
+	unsigned  usage;
+	char     *description;
+};
+
+static struct hid_usage_entry hid_usage_table[] = {
+  {  0,      0, "Undefined" },
+  {  1,      0, "GenericDesktop" },
+    {0, 0x01, "Pointer"},
+    {0, 0x02, "Mouse"},
+    {0, 0x04, "Joystick"},
+    {0, 0x05, "GamePad"},
+    {0, 0x06, "Keyboard"},
+    {0, 0x07, "Keypad"},
+    {0, 0x08, "MultiAxis"},
+      {0, 0x30, "X"},
+      {0, 0x31, "Y"},
+      {0, 0x32, "Z"},
+      {0, 0x33, "Rx"},
+      {0, 0x34, "Ry"},
+      {0, 0x35, "Rz"},
+      {0, 0x36, "Slider"},
+      {0, 0x37, "Dial"},
+      {0, 0x38, "Wheel"},
+      {0, 0x39, "HatSwitch"},
+    {0, 0x3a, "CountedBuffer"},
+      {0, 0x3b, "ByteCount"},
+      {0, 0x3c, "MotionWakeup"},
+      {0, 0x3d, "Start"},
+      {0, 0x3e, "Select"},
+      {0, 0x40, "Vx"},
+      {0, 0x41, "Vy"},
+      {0, 0x42, "Vz"},
+      {0, 0x43, "Vbrx"},
+      {0, 0x44, "Vbry"},
+      {0, 0x45, "Vbrz"},
+      {0, 0x46, "Vno"},
+    {0, 0x80, "SystemControl"}, 
+      {0, 0x81, "SystemPowerDown"},
+      {0, 0x82, "SystemSleep"},
+      {0, 0x83, "SystemWakeUp"},
+      {0, 0x84, "SystemContextMenu"},
+      {0, 0x85, "SystemMainMenu"},
+      {0, 0x86, "SystemAppMenu"},
+      {0, 0x87, "SystemMenuHelp"},
+      {0, 0x88, "SystemMenuExit"},
+      {0, 0x89, "SystemMenuSelect"},
+      {0, 0x8a, "SystemMenuRight"},
+      {0, 0x8b, "SystemMenuLeft"},
+      {0, 0x8c, "SystemMenuUp"},
+      {0, 0x8d, "SystemMenuDown"},
+    {0, 0x90, "D-padUp"},
+    {0, 0x91, "D-padDown"},
+    {0, 0x92, "D-padRight"},
+    {0, 0x93, "D-padLeft"},
+  {  7, 0, "Keyboard" },
+  {  8, 0, "LED" },
+  {  9, 0, "Button" },
+  { 10, 0, "Ordinal" },
+  { 12, 0, "Hotkey" },
+  { 13, 0, "Digitizers" },
+    {0, 0x01, "Digitizer"},
+    {0, 0x02, "Pen"},
+    {0, 0x03, "LightPen"},
+    {0, 0x04, "TouchScreen"},
+    {0, 0x05, "TouchPad"},
+    {0, 0x20, "Stylus"},
+    {0, 0x21, "Puck"},
+    {0, 0x22, "Finger"},
+    {0, 0x30, "TipPressure"},
+    {0, 0x31, "BarrelPressure"},
+    {0, 0x32, "InRange"},
+    {0, 0x33, "Touch"},
+    {0, 0x34, "UnTouch"},
+    {0, 0x35, "Tap"},
+    {0, 0x39, "TabletFunctionKey"},
+    {0, 0x3a, "ProgramChangeKey"},
+    {0, 0x3c, "Invert"},
+    {0, 0x42, "TipSwitch"},
+    {0, 0x43, "SecondaryTipSwitch"},
+    {0, 0x44, "BarrelSwitch"},
+    {0, 0x45, "Eraser"},
+    {0, 0x46, "TabletPick"},
+  { 15, 0, "PhysicalInterfaceDevice" },
+    {0, 0x00, "Undefined"},
+    {0, 0x01, "Physical_Interface_Device"},
+      {0, 0x20, "Normal"},
+    {0, 0x21, "Set_Effect_Report"},
+      {0, 0x22, "Effect_Block_Index"},
+      {0, 0x23, "Parameter_Block_Offset"},
+      {0, 0x24, "ROM_Flag"},
+      {0, 0x25, "Effect_Type"},
+        {0, 0x26, "ET_Constant_Force"},
+        {0, 0x27, "ET_Ramp"},
+        {0, 0x28, "ET_Custom_Force_Data"},
+        {0, 0x30, "ET_Square"},
+        {0, 0x31, "ET_Sine"},
+        {0, 0x32, "ET_Triangle"},
+        {0, 0x33, "ET_Sawtooth_Up"},
+        {0, 0x34, "ET_Sawtooth_Down"},
+        {0, 0x40, "ET_Spring"},
+        {0, 0x41, "ET_Damper"},
+        {0, 0x42, "ET_Inertia"},
+        {0, 0x43, "ET_Friction"},
+      {0, 0x50, "Duration"},
+      {0, 0x51, "Sample_Period"},
+      {0, 0x52, "Gain"},
+      {0, 0x53, "Trigger_Button"},
+      {0, 0x54, "Trigger_Repeat_Interval"},
+      {0, 0x55, "Axes_Enable"},
+        {0, 0x56, "Direction_Enable"},
+      {0, 0x57, "Direction"},
+      {0, 0x58, "Type_Specific_Block_Offset"},
+        {0, 0x59, "Block_Type"},
+        {0, 0x5A, "Set_Envelope_Report"},
+          {0, 0x5B, "Attack_Level"},
+          {0, 0x5C, "Attack_Time"},
+          {0, 0x5D, "Fade_Level"},
+          {0, 0x5E, "Fade_Time"},
+        {0, 0x5F, "Set_Condition_Report"},
+        {0, 0x60, "CP_Offset"},
+        {0, 0x61, "Positive_Coefficient"},
+        {0, 0x62, "Negative_Coefficient"},
+        {0, 0x63, "Positive_Saturation"},
+        {0, 0x64, "Negative_Saturation"},
+        {0, 0x65, "Dead_Band"},
+      {0, 0x66, "Download_Force_Sample"},
+      {0, 0x67, "Isoch_Custom_Force_Enable"},
+      {0, 0x68, "Custom_Force_Data_Report"},
+        {0, 0x69, "Custom_Force_Data"},
+        {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
+      {0, 0x6B, "Set_Custom_Force_Report"},
+        {0, 0x6C, "Custom_Force_Data_Offset"},
+        {0, 0x6D, "Sample_Count"},
+      {0, 0x6E, "Set_Periodic_Report"},
+        {0, 0x6F, "Offset"},
+        {0, 0x70, "Magnitude"},
+        {0, 0x71, "Phase"},
+        {0, 0x72, "Period"},
+      {0, 0x73, "Set_Constant_Force_Report"},
+        {0, 0x74, "Set_Ramp_Force_Report"},
+        {0, 0x75, "Ramp_Start"},
+        {0, 0x76, "Ramp_End"},
+      {0, 0x77, "Effect_Operation_Report"},
+        {0, 0x78, "Effect_Operation"},
+          {0, 0x79, "Op_Effect_Start"},
+          {0, 0x7A, "Op_Effect_Start_Solo"},
+          {0, 0x7B, "Op_Effect_Stop"},
+          {0, 0x7C, "Loop_Count"},
+      {0, 0x7D, "Device_Gain_Report"},
+        {0, 0x7E, "Device_Gain"},
+    {0, 0x7F, "PID_Pool_Report"},
+      {0, 0x80, "RAM_Pool_Size"},
+      {0, 0x81, "ROM_Pool_Size"},
+      {0, 0x82, "ROM_Effect_Block_Count"},
+      {0, 0x83, "Simultaneous_Effects_Max"},
+      {0, 0x84, "Pool_Alignment"},
+    {0, 0x85, "PID_Pool_Move_Report"},
+      {0, 0x86, "Move_Source"},
+      {0, 0x87, "Move_Destination"},
+      {0, 0x88, "Move_Length"},
+    {0, 0x89, "PID_Block_Load_Report"},
+      {0, 0x8B, "Block_Load_Status"},
+      {0, 0x8C, "Block_Load_Success"},
+      {0, 0x8D, "Block_Load_Full"},
+      {0, 0x8E, "Block_Load_Error"},
+      {0, 0x8F, "Block_Handle"},
+      {0, 0x90, "PID_Block_Free_Report"},
+      {0, 0x91, "Type_Specific_Block_Handle"},
+    {0, 0x92, "PID_State_Report"},
+      {0, 0x94, "Effect_Playing"},
+      {0, 0x95, "PID_Device_Control_Report"},
+        {0, 0x96, "PID_Device_Control"},
+        {0, 0x97, "DC_Enable_Actuators"},
+        {0, 0x98, "DC_Disable_Actuators"},
+        {0, 0x99, "DC_Stop_All_Effects"},
+        {0, 0x9A, "DC_Device_Reset"},
+        {0, 0x9B, "DC_Device_Pause"},
+        {0, 0x9C, "DC_Device_Continue"},
+      {0, 0x9F, "Device_Paused"},
+      {0, 0xA0, "Actuators_Enabled"},
+      {0, 0xA4, "Safety_Switch"},
+      {0, 0xA5, "Actuator_Override_Switch"},
+      {0, 0xA6, "Actuator_Power"},
+    {0, 0xA7, "Start_Delay"},
+    {0, 0xA8, "Parameter_Block_Size"},
+    {0, 0xA9, "Device_Managed_Pool"},
+    {0, 0xAA, "Shared_Parameter_Blocks"},
+    {0, 0xAB, "Create_New_Effect_Report"},
+    {0, 0xAC, "RAM_Pool_Available"},
+  { 0, 0, NULL }
+};
+
+static void resolv_usage_page(unsigned page) {
+	struct hid_usage_entry *p;
+
+	for (p = hid_usage_table; p->description; p++)
+		if (p->page == page) {
+			printk("%s", p->description);
+			return;
+		}
+	printk("%04x", page);
+}
+
+static void resolv_usage(unsigned usage) {
+	struct hid_usage_entry *p;
+
+	resolv_usage_page(usage >> 16);
+	printk(".");
+	for (p = hid_usage_table; p->description; p++)
+		if (p->page == (usage >> 16)) {
+			for(++p; p->description && p->page == 0; p++)
+				if (p->usage == (usage & 0xffff)) {
+					printk("%s", p->description);
+					return;
+				}
+			break;
+		}
+	printk("%04x", usage & 0xffff);
+}
+
+__inline__ static void tab(int n) {
+	while (n--) printk(" ");
+}
+
+static void hid_dump_field(struct hid_field *field, int n) {
+	int j;
+	
+	if (field->physical) {
+		tab(n);
+		printk("Physical(");
+		resolv_usage(field->physical); printk(")\n");
+	}
+	if (field->logical) {
+		tab(n);
+		printk("Logical(");
+		resolv_usage(field->logical); printk(")\n");
+	}
+	tab(n); printk("Usage(%d)\n", field->maxusage);
+	for (j = 0; j < field->maxusage; j++) {
+		tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
+	}
+	if (field->logical_minimum != field->logical_maximum) {
+		tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
+		tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
+	}
+	if (field->physical_minimum != field->physical_maximum) {
+		tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
+		tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
+	}
+	if (field->unit_exponent) {
+		tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
+	}
+	if (field->unit) {
+		char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
+		char *units[5][8] = {
+			{ "None", "None", "None", "None", "None", "None", "None", "None" },
+			{ "None", "Centimeter", "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
+			{ "None", "Radians",    "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
+			{ "None", "Inch",       "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
+			{ "None", "Degrees",    "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
+		};
+
+		int i;
+		int sys;
+                __u32 data = field->unit;
+
+		/* First nibble tells us which system we're in. */
+		sys = data & 0xf;
+		data >>= 4;
+
+		if(sys > 4) {
+			tab(n); printk("Unit(Invalid)\n");
+		}
+		else {
+			int earlier_unit = 0;
+
+			tab(n); printk("Unit(%s : ", systems[sys]);
+
+			for (i=1 ; i<sizeof(__u32)*2 ; i++) {
+				char nibble = data & 0xf;
+				data >>= 4;
+				if (nibble != 0) {
+					if(earlier_unit++ > 0)
+						printk("*");
+					printk("%s", units[sys][i]);
+					if(nibble != 1) {
+						/* This is a _signed_ nibble(!) */
+	
+						int val = nibble & 0x7;
+						if(nibble & 0x08)
+							val = -((0x7 & ~val) +1);
+						printk("^%d", val);
+					}
+				}
+			}
+			printk(")\n");
+		}
+	}
+	tab(n); printk("Report Size(%u)\n", field->report_size);
+	tab(n); printk("Report Count(%u)\n", field->report_count);
+	tab(n); printk("Report Offset(%u)\n", field->report_offset);
+
+	tab(n); printk("Flags( ");
+	j = field->flags;
+	printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
+	printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
+	printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
+	printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
+	printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
+	printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
+	printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
+	printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
+	printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
+	printk(")\n");
+}
+
+static void hid_dump_device(struct hid_device *device) {
+	struct hid_report_enum *report_enum;
+	struct hid_report *report;
+	struct list_head *list;
+	unsigned i,k;
+	static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
+	
+	for (i = 0; i < device->maxapplication; i++) {
+		printk("Application(");
+		resolv_usage(device->application[i]);
+		printk(")\n");
+	}
+
+	for (i = 0; i < HID_REPORT_TYPES; i++) {
+		report_enum = device->report_enum + i;
+		list = report_enum->report_list.next;
+		while (list != &report_enum->report_list) {
+			report = (struct hid_report *) list;
+			tab(2);
+			printk("%s", table[i]);
+			if (report->id)
+				printk("(%d)", report->id);
+			printk("[%s]", table[report->type]);
+			printk("\n");
+			for (k = 0; k < report->maxfield; k++) {
+				tab(4);
+				printk("Field(%d)\n", k);
+				hid_dump_field(report->field[k], 6);
+			}
+			list = list->next;
+		}
+	}
+}
+
+static void hid_dump_input(struct hid_usage *usage, __s32 value) {
+	printk("hid-debug: input ");
+	resolv_usage(usage->hid);
+	printk(" = %d\n", value);
+}
diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/hid-input.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,460 @@
+/*
+ * $Id: hid-input.c,v 1.18 2001/11/07 09:01:18 vojtech Exp $
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *
+ *  USB HID to Linux Input mapping
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include "hid.h"
+
+#define unk	KEY_UNKNOWN
+
+static unsigned char hid_keyboard[256] = {
+	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+	115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189,
+	190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
+	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
+};
+
+static struct {
+	__s32 x;
+	__s32 y;
+}  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage)
+{
+	struct input_dev *input = &device->input;
+	int max;
+	int is_abs = 0;
+	unsigned long *bit;
+
+	switch (usage->hid & HID_USAGE_PAGE) {
+
+		case HID_UP_KEYBOARD:
+
+			set_bit(EV_REP, input->evbit);
+			usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+
+			if ((usage->hid & HID_USAGE) < 256) {
+				if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE]))
+					return;
+				clear_bit(usage->code, bit);
+			} else
+				usage->code = KEY_UNKNOWN;
+
+			break;
+
+		case HID_UP_BUTTON:
+
+			usage->code = ((usage->hid - 1) & 0xf) + 0x100;
+			usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+
+			switch (field->application) {
+				case HID_GD_GAMEPAD:  usage->code += 0x10;
+				case HID_GD_JOYSTICK: usage->code += 0x10;
+				case HID_GD_MOUSE:    usage->code += 0x10; break;
+				default:
+					if (field->physical == HID_GD_POINTER)
+						usage->code += 0x10;
+					break;
+			}
+			break;
+
+		case HID_UP_GENDESK:
+
+			if ((usage->hid & 0xf0) == 0x80) {	/* SystemControl */
+				switch (usage->hid & 0xf) {
+					case 0x1: usage->code = KEY_POWER;  break;
+					case 0x2: usage->code = KEY_SLEEP;  break;
+					case 0x3: usage->code = KEY_WAKEUP; break;
+					default: usage->code = KEY_UNKNOWN; break;
+				}
+				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+				break;
+			}
+
+			usage->code = usage->hid & 0xf;
+
+			if (field->report_size == 1) {
+				usage->code = BTN_MISC;
+				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+				break;
+			}
+
+			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+				usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
+				break;
+			}
+
+			usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+
+			if (usage->hid == HID_GD_HATSWITCH) {
+				usage->code = ABS_HAT0X;
+				usage->hat_min = field->logical_minimum;
+				usage->hat_max = field->logical_maximum;
+			}
+			break;
+
+		case HID_UP_LED:
+
+			usage->code = (usage->hid - 1) & 0xf;
+			usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
+			break;
+
+		case HID_UP_DIGITIZER:
+
+			switch (usage->hid & 0xff) {
+
+				case 0x30: /* TipPressure */
+
+					if (!test_bit(BTN_TOUCH, input->keybit)) {
+						device->quirks |= HID_QUIRK_NOTOUCH;
+						set_bit(EV_KEY, input->evbit);
+						set_bit(BTN_TOUCH, input->keybit);
+					}
+					usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+					usage->code = ABS_PRESSURE;
+					clear_bit(usage->code, bit);
+					break;
+
+				case 0x32: /* InRange */
+
+					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+					switch (field->physical & 0xff) {
+						case 0x21: usage->code = BTN_TOOL_MOUSE; break;
+						case 0x22: usage->code = BTN_TOOL_FINGER; break;
+						default: usage->code = BTN_TOOL_PEN; break;
+					}
+					break;
+
+				case 0x3c: /* Invert */
+
+					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+					usage->code = BTN_TOOL_RUBBER;
+					clear_bit(usage->code, bit);
+					break;
+
+				case 0x33: /* Touch */
+				case 0x42: /* TipSwitch */
+				case 0x43: /* TipSwitch2 */
+
+					device->quirks &= ~HID_QUIRK_NOTOUCH;
+					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+					usage->code = BTN_TOUCH;
+					clear_bit(usage->code, bit);
+					break;
+
+				case 0x44: /* BarrelSwitch */
+
+					usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+					usage->code = BTN_STYLUS;
+					clear_bit(usage->code, bit);
+					break;
+
+				default:  goto unknown;
+			}
+			break;
+
+		case HID_UP_CONSUMER:	/* USB HUT v1.1, pages 56-62 */
+
+			set_bit(EV_REP, input->evbit);
+			switch (usage->hid & HID_USAGE) {
+				case 0x000: usage->code = 0; break;
+				case 0x034: usage->code = KEY_SLEEP;		break;
+				case 0x036: usage->code = BTN_MISC;		break;
+				case 0x08a: usage->code = KEY_WWW;		break;
+				case 0x095: usage->code = KEY_HELP;		break;
+
+				case 0x0b0: usage->code = KEY_PLAY;		break;
+				case 0x0b1: usage->code = KEY_PAUSE;		break;
+				case 0x0b2: usage->code = KEY_RECORD;		break;
+				case 0x0b3: usage->code = KEY_FASTFORWARD;	break;
+				case 0x0b4: usage->code = KEY_REWIND;		break;
+				case 0x0b5: usage->code = KEY_NEXTSONG;		break;
+				case 0x0b6: usage->code = KEY_PREVIOUSSONG;	break;
+				case 0x0b7: usage->code = KEY_STOPCD;		break;
+				case 0x0b8: usage->code = KEY_EJECTCD;		break;
+				case 0x0cd: usage->code = KEY_PLAYPAUSE;	break;
+			        case 0x0e0: is_abs = 1;
+					    usage->code = ABS_VOLUME;
+					    break;
+				case 0x0e2: usage->code = KEY_MUTE;		break;
+				case 0x0e5: usage->code = KEY_BASSBOOST;	break;
+				case 0x0e9: usage->code = KEY_VOLUMEUP;		break;
+				case 0x0ea: usage->code = KEY_VOLUMEDOWN;	break;
+
+				case 0x183: usage->code = KEY_CONFIG;		break;
+				case 0x18a: usage->code = KEY_MAIL;		break;
+				case 0x192: usage->code = KEY_CALC;		break;
+				case 0x194: usage->code = KEY_FILE;		break;
+				case 0x21a: usage->code = KEY_UNDO;		break;
+				case 0x21b: usage->code = KEY_COPY;		break;
+				case 0x21c: usage->code = KEY_CUT;		break;
+				case 0x21d: usage->code = KEY_PASTE;		break;
+
+				case 0x221: usage->code = KEY_FIND;		break;
+				case 0x223: usage->code = KEY_HOMEPAGE;		break;
+				case 0x224: usage->code = KEY_BACK;		break;
+				case 0x225: usage->code = KEY_FORWARD;		break;
+				case 0x226: usage->code = KEY_STOP;		break;
+				case 0x227: usage->code = KEY_REFRESH;		break;
+				case 0x22a: usage->code = KEY_BOOKMARKS;	break;
+
+				default:    usage->code = KEY_UNKNOWN;		break;
+			}
+
+			if (is_abs) {
+			        usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+			} else  {
+				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+			}
+			break;
+
+		case HID_UP_HPVENDOR:	/* Reported on a Dutch layout HP5308 */
+
+			set_bit(EV_REP, input->evbit);
+			switch (usage->hid & HID_USAGE) {
+			        case 0x021: usage->code = KEY_PRINT;            break;
+				case 0x070: usage->code = KEY_HP;		break;
+				case 0x071: usage->code = KEY_CAMERA;		break;
+				case 0x072: usage->code = KEY_SOUND;		break;
+				case 0x073: usage->code = KEY_QUESTION;		break;
+
+				case 0x080: usage->code = KEY_EMAIL;		break;
+				case 0x081: usage->code = KEY_CHAT;		break;
+				case 0x082: usage->code = KEY_SEARCH;		break;
+				case 0x083: usage->code = KEY_CONNECT;	        break;
+				case 0x084: usage->code = KEY_FINANCE;		break;
+				case 0x085: usage->code = KEY_SPORT;		break;
+				case 0x086: usage->code = KEY_SHOP;	        break;
+
+				default:    usage->code = KEY_UNKNOWN;		break;
+
+			}
+
+			usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+			break;
+
+		default:
+		unknown:
+
+			if (field->report_size == 1) {
+
+				if (field->report->type == HID_OUTPUT_REPORT) {
+					usage->code = LED_MISC;
+					usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
+					break;
+				}
+
+				usage->code = BTN_MISC;
+				usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+				break;
+			}
+
+			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
+				usage->code = REL_MISC;
+				usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
+				break;
+			}
+
+			usage->code = ABS_MISC;
+			usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
+			break;
+	}
+
+	set_bit(usage->type, input->evbit);
+
+	while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
+		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
+	}
+
+	if (usage->code > max) return;
+
+	if (usage->type == EV_ABS) {
+		int a = field->logical_minimum;
+		int b = field->logical_maximum;
+
+		input->absmin[usage->code] = a;
+		input->absmax[usage->code] = b;
+		input->absfuzz[usage->code] = (b - a) >> 8;
+		input->absflat[usage->code] = (b - a) >> 4;
+	}
+
+	if (usage->hat_min != usage->hat_max) {
+		int i;
+		for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
+			input->absmax[i] = 1;
+			input->absmin[i] = -1;
+			input->absfuzz[i] = 0;
+			input->absflat[i] = 0;
+		}
+		set_bit(usage->code + 1, input->absbit);
+	}
+}
+
+void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
+{
+	struct input_dev *input = &hid->input;
+	int *quirks = &hid->quirks;
+
+	if (usage->hat_min != usage->hat_max) {
+		value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
+		if (value < 0 || value > 8) value = 0;
+		input_event(input, usage->type, usage->code    , hid_hat_to_axis[value].x);
+		input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y);
+		return;
+	}
+
+	if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
+		*quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
+		return;
+	}
+
+	if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
+		if (value) {
+			input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
+			return;
+		}
+		input_event(input, usage->type, usage->code, 0);
+		input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
+		return;
+	}
+
+	if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
+		int a = field->logical_minimum;
+		int b = field->logical_maximum;
+		input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
+	}
+
+	if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
+		return;
+
+	input_event(input, usage->type, usage->code, value);
+
+	if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
+		input_event(input, usage->type, usage->code, 0);
+}
+
+static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+	struct hid_device *hid = dev->private;
+	struct hid_field *field = NULL;
+	int offset;
+
+	if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+		warn("event field not found");
+		return -1;
+	}
+
+	hid_set_field(field, offset, value);
+	hid_submit_report(hid, field->report, USB_DIR_OUT);
+
+	return 0;
+}
+
+static int hidinput_open(struct input_dev *dev)
+{
+	struct hid_device *hid = dev->private;
+	return hid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+	struct hid_device *hid = dev->private;
+	hid_close(hid);
+}
+
+/*
+ * Register the input device; print a message.
+ * Configure the input layer interface
+ * Read all reports and initalize the absoulte field values.
+ */
+
+int hidinput_connect(struct hid_device *hid)
+{
+	struct usb_device *dev = hid->dev;
+	struct hid_report_enum *report_enum;
+	struct hid_report *report;
+	struct list_head *list;
+	int i, j, k;
+
+	for (i = 0; i < hid->maxapplication; i++)
+		if (IS_INPUT_APPLICATION(hid->application[i]))
+			break;
+
+	if (i == hid->maxapplication)
+		return -1;
+
+	hid->input.private = hid;
+	hid->input.event = hidinput_input_event;
+	hid->input.open = hidinput_open;
+	hid->input.close = hidinput_close;
+
+	hid->input.name = hid->name;
+	hid->input.phys = hid->phys;
+	hid->input.uniq = hid->uniq;
+	hid->input.idbus = BUS_USB;
+	hid->input.idvendor = dev->descriptor.idVendor;
+	hid->input.idproduct = dev->descriptor.idProduct;
+	hid->input.idversion = dev->descriptor.bcdDevice;
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+		report_enum = hid->report_enum + k;
+		list = report_enum->report_list.next;
+		while (list != &report_enum->report_list) {
+			report = (struct hid_report *) list;
+			for (i = 0; i < report->maxfield; i++)
+				for (j = 0; j < report->field[i]->maxusage; j++)
+					hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j);
+			list = list->next;
+		}
+	}
+
+	input_register_device(&hid->input);
+
+	return 0;
+}
+
+void hidinput_disconnect(struct hid_device *hid)
+{
+	input_unregister_device(&hid->input);
+}
diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/hid.h	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,421 @@
+#ifndef __HID_H
+#define __HID_H
+
+/*
+ * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $
+ *
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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/types.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+/*
+ * USB HID (Human Interface Device) interface class code
+ */
+
+#define USB_INTERFACE_CLASS_HID		3
+
+/*
+ * HID class requests
+ */
+
+#define HID_REQ_GET_REPORT		0x01
+#define HID_REQ_GET_IDLE		0x02
+#define HID_REQ_GET_PROTOCOL		0x03
+#define HID_REQ_SET_REPORT		0x09
+#define HID_REQ_SET_IDLE		0x0A
+#define HID_REQ_SET_PROTOCOL		0x0B
+
+/*
+ * HID class descriptor types
+ */
+
+#define HID_DT_HID			(USB_TYPE_CLASS | 0x01)
+#define HID_DT_REPORT			(USB_TYPE_CLASS | 0x02)
+#define HID_DT_PHYSICAL			(USB_TYPE_CLASS | 0x03)
+
+/*
+ * We parse each description item into this structure. Short items data
+ * values are expanded to 32-bit signed int, long items contain a pointer
+ * into the data area.
+ */
+
+struct hid_item {
+	unsigned  format;
+	__u8      size;
+	__u8      type;
+	__u8      tag;
+	union {
+	    __u8   u8;
+	    __s8   s8;
+	    __u16  u16;
+	    __s16  s16;
+	    __u32  u32;
+	    __s32  s32;
+	    __u8  *longdata;
+	} data;
+};
+
+/*
+ * HID report item format
+ */
+
+#define HID_ITEM_FORMAT_SHORT	0
+#define HID_ITEM_FORMAT_LONG	1
+
+/*
+ * Special tag indicating long items
+ */
+
+#define HID_ITEM_TAG_LONG	15
+
+/*
+ * HID report descriptor item type (prefix bit 2,3)
+ */
+
+#define HID_ITEM_TYPE_MAIN		0
+#define HID_ITEM_TYPE_GLOBAL		1
+#define HID_ITEM_TYPE_LOCAL		2
+#define HID_ITEM_TYPE_RESERVED		3
+
+/*
+ * HID report descriptor main item tags
+ */
+
+#define HID_MAIN_ITEM_TAG_INPUT			8
+#define HID_MAIN_ITEM_TAG_OUTPUT		9
+#define HID_MAIN_ITEM_TAG_FEATURE		11
+#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION	10
+#define HID_MAIN_ITEM_TAG_END_COLLECTION	12
+
+/*
+ * HID report descriptor main item contents
+ */
+
+#define HID_MAIN_ITEM_CONSTANT		0x001
+#define HID_MAIN_ITEM_VARIABLE		0x002
+#define HID_MAIN_ITEM_RELATIVE		0x004
+#define HID_MAIN_ITEM_WRAP		0x008	
+#define HID_MAIN_ITEM_NONLINEAR		0x010
+#define HID_MAIN_ITEM_NO_PREFERRED	0x020
+#define HID_MAIN_ITEM_NULL_STATE	0x040
+#define HID_MAIN_ITEM_VOLATILE		0x080
+#define HID_MAIN_ITEM_BUFFERED_BYTE	0x100
+
+/*
+ * HID report descriptor collection item types
+ */
+
+#define HID_COLLECTION_PHYSICAL		0
+#define HID_COLLECTION_APPLICATION	1
+#define HID_COLLECTION_LOGICAL		2
+
+/*
+ * HID report descriptor global item tags
+ */
+
+#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE		0
+#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM	1
+#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM	2
+#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM	3
+#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM	4
+#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT	5
+#define HID_GLOBAL_ITEM_TAG_UNIT		6
+#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE		7
+#define HID_GLOBAL_ITEM_TAG_REPORT_ID		8
+#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT	9
+#define HID_GLOBAL_ITEM_TAG_PUSH		10
+#define HID_GLOBAL_ITEM_TAG_POP			11
+
+/*
+ * HID report descriptor local item tags
+ */
+
+#define HID_LOCAL_ITEM_TAG_USAGE		0
+#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM	1
+#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM	2
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX	3
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM	4
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM	5
+#define HID_LOCAL_ITEM_TAG_STRING_INDEX		7
+#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM	8
+#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM	9
+#define HID_LOCAL_ITEM_TAG_DELIMITER		10
+
+/*
+ * HID usage tables
+ */
+
+#define HID_USAGE_PAGE		0xffff0000
+
+#define HID_UP_GENDESK 		0x00010000
+#define HID_UP_KEYBOARD 	0x00070000
+#define HID_UP_LED 		0x00080000
+#define HID_UP_BUTTON 		0x00090000
+#define HID_UP_ORDINAL 		0x000a0000
+#define HID_UP_CONSUMER		0x000c0000
+#define HID_UP_DIGITIZER 	0x000d0000
+#define HID_UP_PID 		0x000f0000
+#define HID_UP_HPVENDOR         0xff7f0000
+
+#define HID_USAGE		0x0000ffff
+
+#define HID_GD_POINTER		0x00010001
+#define HID_GD_MOUSE		0x00010002
+#define HID_GD_JOYSTICK		0x00010004
+#define HID_GD_GAMEPAD		0x00010005
+#define HID_GD_HATSWITCH	0x00010039
+
+/*
+ * HID report types --- Ouch! HID spec says 1 2 3!
+ */
+
+#define HID_INPUT_REPORT	0
+#define HID_OUTPUT_REPORT	1
+#define HID_FEATURE_REPORT	2
+
+/*
+ * HID device quirks.
+ */
+
+#define HID_QUIRK_INVERT	0x01
+#define HID_QUIRK_NOTOUCH	0x02
+#define HID_QUIRK_IGNORE	0x04
+#define HID_QUIRK_NOGET		0x08
+
+/*
+ * This is the global enviroment of the parser. This information is
+ * persistent for main-items. The global enviroment can be saved and
+ * restored with PUSH/POP statements.
+ */
+
+struct hid_global {
+	unsigned usage_page;
+	__s32    logical_minimum;
+	__s32    logical_maximum;
+	__s32    physical_minimum;
+	__s32    physical_maximum;
+	__s32    unit_exponent;
+	unsigned unit;
+	unsigned report_id;
+	unsigned report_size;
+	unsigned report_count;
+};
+
+/*
+ * This is the local enviroment. It is resistent up the next main-item.
+ */
+
+#define HID_MAX_DESCRIPTOR_SIZE		4096
+#define HID_MAX_USAGES			1024
+#define HID_MAX_APPLICATIONS		16
+
+struct hid_local {
+	unsigned usage[HID_MAX_USAGES]; /* usage array */
+	unsigned usage_index;
+	unsigned usage_minimum;
+	unsigned delimiter_depth;
+	unsigned delimiter_branch;
+};
+
+/*
+ * This is the collection stack. We climb up the stack to determine
+ * application and function of each field.
+ */
+
+struct hid_collection {
+	unsigned type;
+	unsigned usage;
+};
+
+struct hid_usage {
+	unsigned  hid;			/* hid usage code */
+	__u16     code;			/* input driver code */
+	__u8      type;			/* input driver type */
+	__s8	  hat_min;		/* hat switch fun */
+	__s8	  hat_max;		/* ditto */
+};
+
+struct hid_field {
+	unsigned  physical;		/* physical usage for this field */
+	unsigned  logical;		/* logical usage for this field */
+	unsigned  application;		/* application usage for this field */
+	struct hid_usage *usage;	/* usage table for this function */
+	unsigned  maxusage;		/* maximum usage index */
+	unsigned  flags;		/* main-item flags (i.e. volatile,array,constant) */
+	unsigned  report_offset;	/* bit offset in the report */
+	unsigned  report_size;		/* size of this field in the report */
+	unsigned  report_count;		/* number of this field in the report */
+	unsigned  report_type;		/* (input,output,feature) */
+	__s32    *value;		/* last known value(s) */
+	__s32     logical_minimum;
+	__s32     logical_maximum;
+	__s32     physical_minimum;
+	__s32     physical_maximum;
+	__s32     unit_exponent;
+	unsigned  unit;
+	struct hid_report *report;	/* associated report */
+	unsigned index;			/* index into report->field[] */
+};
+
+#define HID_MAX_FIELDS 64
+
+struct hid_report {
+	struct list_head list;
+	unsigned id;					/* id of this report */
+	unsigned type;					/* report type */
+	struct hid_field *field[HID_MAX_FIELDS];	/* fields of the report */
+	unsigned maxfield;				/* maximum valid field index */
+	unsigned size;					/* size of the report (bits) */
+	struct hid_device *device;			/* associated device */
+};
+
+struct hid_report_enum {
+	unsigned numbered;
+	struct list_head report_list;
+	struct hid_report *report_id_hash[256];
+};
+
+#define HID_REPORT_TYPES 3
+
+#define HID_BUFFER_SIZE		32
+#define HID_CONTROL_FIFO_SIZE	64
+#define HID_OUTPUT_FIFO_SIZE	64
+
+struct hid_control_fifo {
+	unsigned char dir;
+	struct hid_report *report;
+};
+
+#define HID_CLAIMED_INPUT	1
+#define HID_CLAIMED_HIDDEV	2
+
+#define HID_CTRL_RUNNING	1
+#define HID_OUT_RUNNING		2
+
+struct hid_device {							/* device report descriptor */
+	 __u8 *rdesc;
+	unsigned rsize;
+	unsigned application[HID_MAX_APPLICATIONS];			/* List of HID applications */
+	unsigned maxapplication;					/* Number of applications */
+	unsigned version;						/* HID version */
+	unsigned country;						/* HID country */
+	struct hid_report_enum report_enum[HID_REPORT_TYPES];
+
+	struct usb_device *dev;						/* USB device */
+	int ifnum;							/* USB interface number */
+
+	unsigned long iofl;						/* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+
+	struct urb *urbin;						/* Input URB */
+	char inbuf[HID_BUFFER_SIZE];					/* Input buffer */
+
+	struct urb *urbctrl;						/* Control URB */
+	struct usb_ctrlrequest cr;					/* Control request struct */
+	struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];		/* Control fifo */
+	unsigned char ctrlhead, ctrltail;				/* Control fifo head & tail */
+	char ctrlbuf[HID_BUFFER_SIZE];					/* Control buffer */
+	spinlock_t ctrllock;						/* Control fifo spinlock */
+
+	struct urb *urbout;						/* Output URB */
+	struct hid_report *out[HID_CONTROL_FIFO_SIZE];			/* Output pipe fifo */
+	unsigned char outhead, outtail;					/* Output pipe fifo head & tail */
+	char outbuf[HID_BUFFER_SIZE];					/* Output buffer */
+	spinlock_t outlock;						/* Output fifo spinlock */
+
+	unsigned claimed;						/* Claimed by hidinput, hiddev? */	
+	unsigned quirks;						/* Various quirks the device can pull on us */
+
+	struct input_dev input;						/* The input structure */
+	void *hiddev;							/* The hiddev structure */
+	int minor;							/* Hiddev minor number */
+
+	wait_queue_head_t wait;						/* For sleeping */
+
+	int open;							/* is the device open by anyone? */
+	char name[128];							/* Device name */
+	char phys[64];							/* Device physical location */
+	char uniq[64];							/* Device unique identifier (serial #) */
+};
+
+#define HID_GLOBAL_STACK_SIZE 4
+#define HID_COLLECTION_STACK_SIZE 4
+
+struct hid_parser {
+	struct hid_global     global;
+	struct hid_global     global_stack[HID_GLOBAL_STACK_SIZE];
+	unsigned              global_stack_ptr;
+	struct hid_local      local;
+	struct hid_collection collection_stack[HID_COLLECTION_STACK_SIZE];
+	unsigned              collection_stack_ptr;
+	struct hid_device    *device;
+};
+
+struct hid_class_descriptor {
+	__u8  bDescriptorType;
+	__u16 wDescriptorLength;
+} __attribute__ ((packed));
+
+struct hid_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 bcdHID;
+	__u8  bCountryCode;
+	__u8  bNumDescriptors;
+
+	struct hid_class_descriptor desc[1];
+} __attribute__ ((packed));
+
+#ifdef DEBUG
+#include "hid-debug.h"
+#else
+#define hid_dump_input(a,b)	do { } while (0)
+#define hid_dump_device(c)	do { } while (0)
+#define hid_dump_field(a,b)	do { } while (0)
+#endif
+
+#endif
+
+#ifdef CONFIG_USB_HIDINPUT
+/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
+/* We ignore a few input applications that are not widely used */
+#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || ( a == 0x00010080) || ( a == 0x000c0001))
+extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
+extern int hidinput_connect(struct hid_device *);
+extern void hidinput_disconnect(struct hid_device *);
+#else
+#define IS_INPUT_APPLICATION(a) (0)
+static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
+static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
+static inline void hidinput_disconnect(struct hid_device *hid) { }
+#endif
+
+int hid_open(struct hid_device *);
+void hid_close(struct hid_device *);
+int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
+int hid_set_field(struct hid_field *, unsigned, __s32);
+void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
+void hid_init_reports(struct hid_device *hid);
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/hiddev.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,699 @@
+/*
+ *  Copyright (c) 2001 Paul Stewart
+ *  Copyright (c) 2001 Vojtech Pavlik
+ *
+ *  HID char devices, giving access to raw HID device events.
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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 Paul Stewart <stewart@wetlogic.net>
+ */
+
+#define HIDDEV_MINOR_BASE	96
+#define HIDDEV_MINORS		16
+#define HIDDEV_BUFFER_SIZE	64
+
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include "hid.h"
+#include <linux/hiddev.h>
+
+struct hiddev {
+	int exist;
+	int open;
+	int minor;
+	wait_queue_head_t wait;
+	devfs_handle_t devfs;
+	struct hid_device *hid;
+	struct hiddev_list *list;
+};
+
+struct hiddev_list {
+	struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
+	int head;
+	int tail;
+	unsigned flags;
+	struct fasync_struct *fasync;
+	struct hiddev *hiddev;
+	struct hiddev_list *next;
+};
+
+static struct hiddev *hiddev_table[HIDDEV_MINORS];
+static devfs_handle_t hiddev_devfs_handle;
+
+/*
+ * Find a report, given the report's type and ID.  The ID can be specified
+ * indirectly by REPORT_ID_FIRST (which returns the first report of the given
+ * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
+ * given type which follows old_id.
+ */
+static struct hid_report *
+hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
+{
+	struct hid_report_enum *report_enum;
+	struct list_head *list;
+
+	if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
+	    rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
+
+	report_enum = hid->report_enum +
+		(rinfo->report_type - HID_REPORT_TYPE_MIN);
+	if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) {
+		switch (rinfo->report_id & ~HID_REPORT_ID_MASK) {
+		case HID_REPORT_ID_FIRST:
+			list = report_enum->report_list.next;
+			if (list == &report_enum->report_list) return NULL;
+			rinfo->report_id = ((struct hid_report *) list)->id;
+			break;
+
+		case HID_REPORT_ID_NEXT:
+			list = (struct list_head *)
+				report_enum->report_id_hash[rinfo->report_id &
+							   HID_REPORT_ID_MASK];
+			if (list == NULL) return NULL;
+			list = list->next;
+			if (list == &report_enum->report_list) return NULL;
+			rinfo->report_id = ((struct hid_report *) list)->id;
+			break;
+
+		default:
+			return NULL;
+		}
+	}
+
+	return report_enum->report_id_hash[rinfo->report_id];
+}
+
+/*
+ * Perform an exhaustive search of the report table for a usage, given its
+ * type and usage id.
+ */
+static struct hid_field *
+hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
+{
+	int i, j;
+	struct hid_report *report;
+	struct hid_report_enum *report_enum;
+	struct list_head *list;
+	struct hid_field *field;
+
+	if (uref->report_type < HID_REPORT_TYPE_MIN ||
+	    uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
+
+	report_enum = hid->report_enum +
+		(uref->report_type - HID_REPORT_TYPE_MIN);
+	list = report_enum->report_list.next;
+	while (list != &report_enum->report_list) {
+		report = (struct hid_report *) list;
+		for (i = 0; i < report->maxfield; i++) {
+			field = report->field[i];
+			for (j = 0; j < field->maxusage; j++) {
+				if (field->usage[j].hid == uref->usage_code) {
+					uref->report_id = report->id;
+					uref->field_index = i;
+					uref->usage_index = j;
+					return field;
+				}
+			}
+		}
+		list = list->next;
+	}
+
+	return NULL;
+}
+
+/*
+ * This is where hid.c calls into hiddev to pass an event that occurred over
+ * the interrupt pipe
+ */
+void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
+{
+	struct hiddev *hiddev = hid->hiddev;
+	struct hiddev_list *list = hiddev->list;
+
+	while (list) {
+		if (uref->field_index != HID_FIELD_INDEX_NONE ||
+		    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
+			list->buffer[list->head] = *uref;
+			list->head = (list->head + 1) & 
+				(HIDDEV_BUFFER_SIZE - 1);
+			kill_fasync(&list->fasync, SIGIO, POLL_IN);
+		}
+
+		list = list->next;
+	}
+
+	wake_up_interruptible(&hiddev->wait);
+}
+
+/*
+ * fasync file op
+ */
+static int hiddev_fasync(int fd, struct file *file, int on)
+{
+	int retval;
+	struct hiddev_list *list = file->private_data;
+	retval = fasync_helper(fd, file, on, &list->fasync);
+	return retval < 0 ? retval : 0;
+}
+
+/*
+ * De-allocate a hiddev structure
+ */
+static void hiddev_cleanup(struct hiddev *hiddev)
+{
+	devfs_unregister(hiddev->devfs);
+	hiddev_table[hiddev->minor] = NULL;
+	kfree(hiddev);
+}
+
+/*
+ * release file op
+ */
+static int hiddev_release(struct inode * inode, struct file * file)
+{
+	struct hiddev_list *list = file->private_data;
+	struct hiddev_list **listptr;
+
+	listptr = &list->hiddev->list;
+	hiddev_fasync(-1, file, 0);
+
+	while (*listptr && (*listptr != list))
+		listptr = &((*listptr)->next);
+	*listptr = (*listptr)->next;
+
+	if (!--list->hiddev->open) {
+		if (list->hiddev->exist) 
+			hid_close(list->hiddev->hid);
+		else
+			hiddev_cleanup(list->hiddev);
+	}
+
+	kfree(list);
+
+	return 0;
+}
+
+/*
+ * open file op
+ */
+static int hiddev_open(struct inode * inode, struct file * file) {
+	struct hiddev_list *list;
+
+	int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
+
+	if (i >= HIDDEV_MINORS || !hiddev_table[i])
+		return -ENODEV;
+
+	if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
+		return -ENOMEM;
+	memset(list, 0, sizeof(struct hiddev_list));
+
+	list->hiddev = hiddev_table[i];
+	list->next = hiddev_table[i]->list;
+	hiddev_table[i]->list = list;
+
+	file->private_data = list;
+
+	if (!list->hiddev->open++)
+		if (list->hiddev->exist)
+			hid_open(hiddev_table[i]->hid);
+
+	return 0;
+}
+
+/*
+ * "write" file op
+ */
+static ssize_t hiddev_write(struct file * file, const char * buffer,
+			    size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+/*
+ * "read" file op
+ */
+static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
+			   loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct hiddev_list *list = file->private_data;
+	int event_size;
+	int retval = 0;
+
+	event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
+		sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
+
+	if (count < event_size) return 0;
+
+	while (retval == 0) {
+		if (list->head == list->tail) {
+			add_wait_queue(&list->hiddev->wait, &wait);
+			set_current_state(TASK_INTERRUPTIBLE);
+			
+			while (list->head == list->tail) {
+				if (file->f_flags & O_NONBLOCK) {
+					retval = -EAGAIN;
+					break;
+				}
+				if (signal_pending(current)) {
+					retval = -ERESTARTSYS;
+					break;
+				}
+				if (!list->hiddev->exist) {
+					retval = -EIO;
+					break;
+				}
+				
+				schedule();
+			}
+
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&list->hiddev->wait, &wait);
+		}
+
+		if (retval)
+			return retval;
+
+
+		while (list->head != list->tail && 
+		       retval + event_size <= count) {
+			if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
+				if (list->buffer[list->tail].field_index !=
+				    HID_FIELD_INDEX_NONE) {
+					struct hiddev_event event;
+					event.hid = list->buffer[list->tail].usage_code;
+					event.value = list->buffer[list->tail].value;
+					if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
+						return -EFAULT;
+					retval += sizeof(struct hiddev_event);
+				}
+			} else {
+				if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
+				    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
+					if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
+						return -EFAULT;
+					retval += sizeof(struct hiddev_usage_ref);
+				}
+			}
+			list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
+		}
+
+	}
+
+	return retval;
+}
+
+/*
+ * "poll" file op
+ * No kernel lock - fine
+ */
+static unsigned int hiddev_poll(struct file *file, poll_table *wait)
+{
+	struct hiddev_list *list = file->private_data;
+	poll_wait(file, &list->hiddev->wait, wait);
+	if (list->head != list->tail)
+		return POLLIN | POLLRDNORM;
+	if (!list->hiddev->exist)
+		return POLLERR | POLLHUP;
+	return 0;
+}
+
+/*
+ * "ioctl" file op
+ */
+static int hiddev_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct hiddev_list *list = file->private_data;
+	struct hiddev *hiddev = list->hiddev;
+	struct hid_device *hid = hiddev->hid;
+	struct usb_device *dev = hid->dev;
+	struct hiddev_report_info rinfo;
+	struct hiddev_usage_ref uref;
+	struct hid_report *report;
+	struct hid_field *field;
+
+	if (!hiddev->exist) return -EIO;
+
+	switch (cmd) {
+
+	case HIDIOCGVERSION:
+		return put_user(HID_VERSION, (int *) arg);
+
+	case HIDIOCAPPLICATION:
+		if (arg < 0 || arg >= hid->maxapplication)
+			return -EINVAL;
+		return hid->application[arg];
+
+	case HIDIOCGDEVINFO:
+	{
+		struct hiddev_devinfo dinfo;
+		dinfo.bustype = BUS_USB;
+		dinfo.busnum = dev->bus->busnum;
+		dinfo.devnum = dev->devnum;
+		dinfo.ifnum = hid->ifnum;
+		dinfo.vendor = dev->descriptor.idVendor;
+		dinfo.product = dev->descriptor.idProduct;
+		dinfo.version = dev->descriptor.bcdDevice;
+		dinfo.num_applications = hid->maxapplication;
+		return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
+	}
+
+	case HIDIOCGFLAG:
+		return put_user(list->flags, (int *) arg);
+
+	case HIDIOCSFLAG:
+		{
+			int newflags;
+			if (get_user(newflags, (int *) arg))
+				return -EFAULT;
+
+			if ((newflags & ~HIDDEV_FLAGS) != 0 ||
+			    ((newflags & HIDDEV_FLAG_REPORT) != 0 &&
+			     (newflags & HIDDEV_FLAG_UREF) == 0))
+				return -EINVAL;
+
+			list->flags = newflags;
+
+			return 0;
+		}
+
+	case HIDIOCGSTRING:
+		{
+			int idx, len;
+			char *buf;
+
+			if (get_user(idx, (int *) arg))
+				return -EFAULT;
+
+			if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
+				return -ENOMEM;
+
+			if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
+				kfree(buf);
+				return -EINVAL;
+			}
+
+			if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) {
+				kfree(buf);
+				return -EFAULT;
+			}
+
+			kfree(buf);
+
+			return len;
+		}
+
+	case HIDIOCINITREPORT:
+
+		hid_init_reports(hid);
+
+		return 0;
+
+	case HIDIOCGREPORT:
+		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+			return -EFAULT;
+
+		if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
+			return -EINVAL;
+
+		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+			return -EINVAL;
+
+		hid_submit_report(hid, report, USB_DIR_IN);
+
+		return 0;
+
+	case HIDIOCSREPORT:
+		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+			return -EFAULT;
+
+		if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
+			return -EINVAL;
+
+		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+			return -EINVAL;
+
+		hid_submit_report(hid, report, USB_DIR_OUT);
+
+		return 0;
+
+	case HIDIOCGREPORTINFO:
+		if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
+			return -EFAULT;
+
+		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+			return -EINVAL;
+
+		rinfo.num_fields = report->maxfield;
+
+		return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
+
+	case HIDIOCGFIELDINFO:
+	{
+		struct hiddev_field_info finfo;
+		if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
+			return -EFAULT;
+		rinfo.report_type = finfo.report_type;
+		rinfo.report_id = finfo.report_id;
+		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+			return -EINVAL;
+
+		if (finfo.field_index >= report->maxfield)
+			return -EINVAL;
+
+		field = report->field[finfo.field_index];
+		memset(&finfo, 0, sizeof(finfo));
+		finfo.report_type = rinfo.report_type;
+		finfo.report_id = rinfo.report_id;
+		finfo.field_index = field->report_count - 1;
+		finfo.maxusage = field->maxusage;
+		finfo.flags = field->flags;
+		finfo.physical = field->physical;
+		finfo.logical = field->logical;
+		finfo.application = field->application;
+		finfo.logical_minimum = field->logical_minimum;
+		finfo.logical_maximum = field->logical_maximum;
+		finfo.physical_minimum = field->physical_minimum;
+		finfo.physical_maximum = field->physical_maximum;
+		finfo.unit_exponent = field->unit_exponent;
+		finfo.unit = field->unit;
+
+		return copy_to_user((void *) arg, &finfo, sizeof(finfo));
+	}
+
+	case HIDIOCGUCODE:
+		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+			return -EFAULT;
+
+		rinfo.report_type = uref.report_type;
+		rinfo.report_id = uref.report_id;
+		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+			return -EINVAL;
+
+		if (uref.field_index >= report->maxfield)
+			return -EINVAL;
+
+		field = report->field[uref.field_index];
+		if (uref.usage_index >= field->maxusage)
+			return -EINVAL;
+
+		uref.usage_code = field->usage[uref.usage_index].hid;
+
+		return copy_to_user((void *) arg, &uref, sizeof(uref));
+
+	case HIDIOCGUSAGE:
+	case HIDIOCSUSAGE:
+		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+			return -EFAULT;
+
+		if (cmd == HIDIOCSUSAGE &&
+		    uref.report_type != HID_REPORT_TYPE_OUTPUT)
+			return -EINVAL;
+
+		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
+			field = hiddev_lookup_usage(hid, &uref);
+			if (field == NULL)
+				return -EINVAL;
+		} else {
+			rinfo.report_type = uref.report_type;
+			rinfo.report_id = uref.report_id;
+			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
+				return -EINVAL;
+
+			if (uref.field_index >= report->maxfield)
+				return -EINVAL;
+
+			field = report->field[uref.field_index];
+			if (uref.usage_index >= field->maxusage)
+				return -EINVAL;
+		}
+
+		if (cmd == HIDIOCGUSAGE) {
+			uref.value = field->value[uref.usage_index];
+			return copy_to_user((void *) arg, &uref, sizeof(uref));
+		} else {
+			field->value[uref.usage_index] = uref.value;
+		}
+
+		return 0;
+
+	default:
+
+		if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
+			return -EINVAL;
+
+		if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
+			int len;
+			if (!hid->name) return 0;
+			len = strlen(hid->name) + 1;
+			if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+			return copy_to_user((char *) arg, hid->name, len) ?
+				-EFAULT : len;
+		}
+	}
+	return -EINVAL;
+}
+
+static struct file_operations hiddev_fops = {
+	owner:		THIS_MODULE,
+	read:		hiddev_read,
+	write:		hiddev_write,
+	poll:		hiddev_poll,
+	open:		hiddev_open,
+	release:	hiddev_release,
+	ioctl:		hiddev_ioctl,
+	fasync:		hiddev_fasync,
+};
+
+/*
+ * This is where hid.c calls us to connect a hid device to the hiddev driver
+ */
+int hiddev_connect(struct hid_device *hid)
+{
+	struct hiddev *hiddev;
+	int minor, i;
+	char devfs_name[16];
+
+	for (i = 0; i < hid->maxapplication; i++)
+		if (!IS_INPUT_APPLICATION(hid->application[i]))
+			break;
+
+	if (i == hid->maxapplication)
+		return -1;
+
+	for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
+	if (minor == HIDDEV_MINORS) {
+		printk(KERN_ERR "hiddev: no more free hiddev devices\n");
+		return -1;
+	}
+
+	if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
+		return -1;
+	memset(hiddev, 0, sizeof(struct hiddev));
+
+	init_waitqueue_head(&hiddev->wait);
+
+	hiddev->minor = minor;
+	hiddev_table[minor] = hiddev;
+
+	hiddev->hid = hid;
+	hiddev->exist = 1;
+
+	sprintf(devfs_name, "hiddev%d", minor);
+	hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
+				       DEVFS_FL_DEFAULT, USB_MAJOR,
+				       minor + HIDDEV_MINOR_BASE,
+				       S_IFCHR | S_IRUGO | S_IWUSR,
+				       &hiddev_fops, NULL);
+	hid->minor = minor;
+	hid->hiddev = hiddev;
+
+	return 0;
+}
+
+/*
+ * This is where hid.c calls us to disconnect a hiddev device from the
+ * corresponding hid device (usually because the usb device has disconnected)
+ */
+void hiddev_disconnect(struct hid_device *hid)
+{
+	struct hiddev *hiddev = hid->hiddev;
+
+	hiddev->exist = 0;
+
+	if (hiddev->open) {
+		hid_close(hiddev->hid);
+		wake_up_interruptible(&hiddev->wait);
+	} else {
+		hiddev_cleanup(hiddev);
+	}
+}
+
+/* Currently this driver is a USB driver.  It's not a conventional one in
+ * the sense that it doesn't probe at the USB level.  Instead it waits to
+ * be connected by HID through the hiddev_connect / hiddev_disconnect
+ * routines.  The reason to register as a USB device is to gain part of the
+ * minor number space from the USB major.
+ *
+ * In theory, should the HID code be generalized to more than one physical
+ * medium (say, IEEE 1384), this driver will probably need to register its
+ * own major number, and in doing so, no longer need to register with USB.
+ * At that point the probe routine and hiddev_driver struct below will no
+ * longer be useful.
+ */
+
+
+/* We never attach in this manner, and rely on HID to connect us.  This
+ * is why there is no disconnect routine defined in the usb_driver either.
+ */
+static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum,
+			  const struct usb_device_id *hiddev_info)
+{
+	return NULL;
+}
+
+
+static /* const */ struct usb_driver hiddev_driver = {
+	name:	"hiddev",
+	probe:	hiddev_usbd_probe,
+	fops:	&hiddev_fops,
+	minor:	HIDDEV_MINOR_BASE
+};
+
+int __init hiddev_init(void)
+{
+	hiddev_devfs_handle =
+		devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL);
+	usb_register(&hiddev_driver);
+	return 0;
+}
+
+void __exit hiddev_exit(void)
+{
+	devfs_unregister(hiddev_devfs_handle);
+	usb_deregister(&hiddev_driver);
+}
diff -Nru a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/usbkbd.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,309 @@
+/*
+ * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *
+ *  USB HIDBP Keyboard support
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * 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/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION ""
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+static unsigned char usb_kbd_keycode[256] = {
+	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
+	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
+	115,114,  0,  0,  0,124,  0,181,182,183,184,185,186,187,188,189,
+	190,191,192,193,194,195,196,197,198,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+	150,158,159,128,136,177,178,176,142,152,173,140
+};
+
+struct usb_kbd {
+	struct input_dev dev;
+	struct usb_device *usbdev;
+	unsigned char new[8];
+	unsigned char old[8];
+	struct urb *irq, *led;
+	struct usb_ctrlrequest cr;
+	unsigned char leds, newleds;
+	char name[128];
+	char phys[64];
+	int open;
+};
+
+static void usb_kbd_irq(struct urb *urb)
+{
+	struct usb_kbd *kbd = urb->context;
+	int i;
+
+	if (urb->status) return;
+
+	for (i = 0; i < 8; i++)
+		input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
+
+	for (i = 2; i < 8; i++) {
+
+		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
+			if (usb_kbd_keycode[kbd->old[i]])
+				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
+			else
+				info("Unknown key (scancode %#x) released.", kbd->old[i]);
+		}
+
+		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
+			if (usb_kbd_keycode[kbd->new[i]])
+				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
+			else
+				info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
+		}
+	}
+
+	memcpy(kbd->old, kbd->new, 8);
+}
+
+int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+	struct usb_kbd *kbd = dev->private;
+
+	if (type != EV_LED) return -1;
+
+
+	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
+		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
+		       (!!test_bit(LED_NUML,    dev->led));
+
+	if (kbd->led->status == -EINPROGRESS)
+		return 0;
+
+	if (kbd->leds == kbd->newleds)
+		return 0;
+
+	kbd->leds = kbd->newleds;
+	kbd->led->dev = kbd->usbdev;
+	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
+		err("usb_submit_urb(leds) failed");
+
+	return 0;
+}
+
+static void usb_kbd_led(struct urb *urb)
+{
+	struct usb_kbd *kbd = urb->context;
+
+	if (urb->status)
+		warn("led urb status %d received", urb->status);
+	
+	if (kbd->leds == kbd->newleds)
+		return;
+
+	kbd->leds = kbd->newleds;
+	kbd->led->dev = kbd->usbdev;
+	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
+		err("usb_submit_urb(leds) failed");
+}
+
+static int usb_kbd_open(struct input_dev *dev)
+{
+	struct usb_kbd *kbd = dev->private;
+
+	if (kbd->open++)
+		return 0;
+
+	kbd->irq->dev = kbd->usbdev;
+	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+static void usb_kbd_close(struct input_dev *dev)
+{
+	struct usb_kbd *kbd = dev->private;
+
+	if (!--kbd->open)
+		usb_unlink_urb(kbd->irq);
+}
+
+static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
+			   const struct usb_device_id *id)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_kbd *kbd;
+	int i, pipe, maxp;
+	char path[64];
+	char *buf;
+
+	iface = &dev->actconfig->interface[ifnum];
+	interface = &iface->altsetting[iface->act_altsetting];
+
+	if (interface->bNumEndpoints != 1) return NULL;
+
+	endpoint = interface->endpoint + 0;
+	if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
+	if ((endpoint->bmAttributes & 3) != 3) return NULL;
+
+	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
+	memset(kbd, 0, sizeof(struct usb_kbd));
+
+	kbd->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!kbd->irq) {
+		kfree(kbd);
+		return NULL;
+	}
+	kbd->led = usb_alloc_urb(0, GFP_KERNEL);
+	if (!kbd->led) {
+		usb_free_urb(kbd->irq);
+		kfree(kbd);
+		return NULL;
+	}
+
+	kbd->usbdev = dev;
+
+	kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+	kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
+
+	for (i = 0; i < 255; i++)
+		set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
+	clear_bit(0, kbd->dev.keybit);
+	
+	kbd->dev.private = kbd;
+	kbd->dev.event = usb_kbd_event;
+	kbd->dev.open = usb_kbd_open;
+	kbd->dev.close = usb_kbd_close;
+
+	FILL_INT_URB(kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
+		usb_kbd_irq, kbd, endpoint->bInterval);
+
+	kbd->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	kbd->cr.bRequest = 0x09;
+	kbd->cr.wValue = 0x200;
+	kbd->cr.wIndex = interface->bInterfaceNumber;
+	kbd->cr.wLength = 1;
+
+	usb_make_path(dev, path, 64);
+	sprintf(kbd->phys, "%s/input0", path);
+
+	kbd->dev.name = kbd->name;
+	kbd->dev.phys = kbd->phys;	
+	kbd->dev.idbus = BUS_USB;
+	kbd->dev.idvendor = dev->descriptor.idVendor;
+	kbd->dev.idproduct = dev->descriptor.idProduct;
+	kbd->dev.idversion = dev->descriptor.bcdDevice;
+
+	if (!(buf = kmalloc(63, GFP_KERNEL))) {
+		kfree(kbd);
+		return NULL;
+	}
+
+	if (dev->descriptor.iManufacturer &&
+		usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
+			strcat(kbd->name, buf);
+	if (dev->descriptor.iProduct &&
+		usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
+			sprintf(kbd->name, "%s %s", kbd->name, buf);
+
+	if (!strlen(kbd->name))
+		sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
+			kbd->dev.idvendor, kbd->dev.idproduct);
+
+	kfree(buf);
+
+	FILL_CONTROL_URB(kbd->led, dev, usb_sndctrlpipe(dev, 0),
+		(void*) &kbd->cr, &kbd->leds, 1, usb_kbd_led, kbd);
+			
+	input_register_device(&kbd->dev);
+
+	printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
+
+	return kbd;
+}
+
+static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_kbd *kbd = ptr;
+	usb_unlink_urb(kbd->irq);
+	input_unregister_device(&kbd->dev);
+	usb_free_urb(kbd->irq);
+	usb_free_urb(kbd->led);
+	kfree(kbd);
+}
+
+static struct usb_device_id usb_kbd_id_table [] = {
+	{ USB_INTERFACE_INFO(3, 1, 1) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
+
+static struct usb_driver usb_kbd_driver = {
+	name:		"keyboard",
+	probe:		usb_kbd_probe,
+	disconnect:	usb_kbd_disconnect,
+	id_table:	usb_kbd_id_table,
+};
+
+static int __init usb_kbd_init(void)
+{
+	usb_register(&usb_kbd_driver);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+static void __exit usb_kbd_exit(void)
+{
+	usb_deregister(&usb_kbd_driver);
+}
+
+module_init(usb_kbd_init);
+module_exit(usb_kbd_exit);
diff -Nru a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/usbmouse.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,217 @@
+/*
+ * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *
+ *  USB HIDBP Mouse support
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * 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/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.6"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+struct usb_mouse {
+	signed char data[8];
+	char name[128];
+	char phys[64];
+	struct usb_device *usbdev;
+	struct input_dev dev;
+	struct urb *irq;
+	int open;
+};
+
+static void usb_mouse_irq(struct urb *urb)
+{
+	struct usb_mouse *mouse = urb->context;
+	signed char *data = mouse->data;
+	struct input_dev *dev = &mouse->dev;
+
+	if (urb->status) return;
+
+	input_report_key(dev, BTN_LEFT,   data[0] & 0x01);
+	input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);
+	input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
+	input_report_key(dev, BTN_SIDE,   data[0] & 0x08);
+	input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);
+
+	input_report_rel(dev, REL_X,     data[1]);
+	input_report_rel(dev, REL_Y,     data[2]);
+	input_report_rel(dev, REL_WHEEL, data[3]);
+}
+
+static int usb_mouse_open(struct input_dev *dev)
+{
+	struct usb_mouse *mouse = dev->private;
+
+	if (mouse->open++)
+		return 0;
+
+	mouse->irq->dev = mouse->usbdev;
+	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+static void usb_mouse_close(struct input_dev *dev)
+{
+	struct usb_mouse *mouse = dev->private;
+
+	if (!--mouse->open)
+		usb_unlink_urb(mouse->irq);
+}
+
+static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
+			     const struct usb_device_id *id)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_mouse *mouse;
+	int pipe, maxp;
+	char path[64];
+	char *buf;
+
+	iface = &dev->actconfig->interface[ifnum];
+	interface = &iface->altsetting[iface->act_altsetting];
+
+	if (interface->bNumEndpoints != 1) return NULL;
+
+	endpoint = interface->endpoint + 0;
+	if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
+	if ((endpoint->bmAttributes & 3) != 3) return NULL;
+
+	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
+	memset(mouse, 0, sizeof(struct usb_mouse));
+
+	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!mouse->irq) {
+		kfree(mouse);
+		return NULL;
+	}
+
+	mouse->usbdev = dev;
+
+	mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+	mouse->dev.relbit[0] |= BIT(REL_WHEEL);
+
+	mouse->dev.private = mouse;
+	mouse->dev.open = usb_mouse_open;
+	mouse->dev.close = usb_mouse_close;
+
+	usb_make_path(dev, path, 64);
+	sprintf(mouse->phys, "%s/input0", path);
+
+	mouse->dev.name = mouse->name;
+	mouse->dev.phys = mouse->phys;
+	mouse->dev.idbus = BUS_USB;
+	mouse->dev.idvendor = dev->descriptor.idVendor;
+	mouse->dev.idproduct = dev->descriptor.idProduct;
+	mouse->dev.idversion = dev->descriptor.bcdDevice;
+
+	if (!(buf = kmalloc(63, GFP_KERNEL))) {
+		kfree(mouse);
+		return NULL;
+	}
+
+	if (dev->descriptor.iManufacturer &&
+		usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
+			strcat(mouse->name, buf);
+	if (dev->descriptor.iProduct &&
+		usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
+			sprintf(mouse->name, "%s %s", mouse->name, buf);
+
+	if (!strlen(mouse->name))
+		sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
+			mouse->dev.idvendor, mouse->dev.idproduct);
+
+	kfree(buf);
+
+	FILL_INT_URB(mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
+		usb_mouse_irq, mouse, endpoint->bInterval);
+
+	input_register_device(&mouse->dev);
+
+	printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
+
+	return mouse;
+}
+
+static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_mouse *mouse = ptr;
+	usb_unlink_urb(mouse->irq);
+	input_unregister_device(&mouse->dev);
+	usb_free_urb(mouse->irq);
+	kfree(mouse);
+}
+
+static struct usb_device_id usb_mouse_id_table [] = {
+	{ USB_INTERFACE_INFO(3, 1, 2) },
+    { }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
+
+static struct usb_driver usb_mouse_driver = {
+	name:		"usb_mouse",
+	probe:		usb_mouse_probe,
+	disconnect:	usb_mouse_disconnect,
+	id_table:	usb_mouse_id_table,
+};
+
+static int __init usb_mouse_init(void)
+{
+	usb_register(&usb_mouse_driver);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+static void __exit usb_mouse_exit(void)
+{
+	usb_deregister(&usb_mouse_driver);
+}
+
+module_init(usb_mouse_init);
+module_exit(usb_mouse_exit);
diff -Nru a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/wacom.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,450 @@
+/*
+ * $Id: wacom.c,v 1.28 2001/09/25 10:12:07 vojtech Exp $
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik	<vojtech@ucw.cz>
+ *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
+ *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
+ *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
+ *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
+ *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
+ *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support
+ *
+ *  ChangeLog:
+ *      v0.1 (vp)  - Initial release
+ *      v0.2 (aba) - Support for all buttons / combinations
+ *      v0.3 (vp)  - Support for Intuos added
+ *	v0.4 (sm)  - Support for more Intuos models, menustrip
+ *			relative mode, proximity.
+ *	v0.5 (vp)  - Big cleanup, nifty features removed,
+ * 			they belong in userspace
+ *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
+ *			use input_report_key instead of report_btn and
+ *			other cleanups
+ *	v1.11 (vp) - Add URB ->dev setting for new kernels
+ *	v1.11 (jb) - Add support for the 4D Mouse & Lens
+ *	v1.12 (de) - Add support for two more inking pen IDs
+ *	v1.14 (vp) - Use new USB device id probing scheme.
+ *		     Fix Wacom Graphire mouse wheel
+ *	v1.18 (vp) - Fix mouse wheel direction
+ *		     Make mouse relative
+ *      v1.20 (fl) - Report tool id for Intuos devices
+ *                 - Multi tools support
+ *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
+ *                 - Add PL models support
+ *		   - Fix Wacom Graphire mouse wheel again
+ *	v1.21 (vp) - Removed protocol descriptions
+ *		   - Added MISC_SERIAL for tool serial numbers
+ *	      (gb) - Identify version on module load.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.21"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_WACOM	0x056a
+
+struct wacom_features {
+	char *name;
+	int pktlen;
+	int x_max;
+	int y_max;
+	int pressure_max;
+	int distance_max;
+	void (*irq)(struct urb *urb);
+	unsigned long evbit;
+	unsigned long absbit;
+	unsigned long relbit;
+	unsigned long btnbit;
+	unsigned long digibit;
+};
+
+struct wacom {
+	signed char data[10];
+	struct input_dev dev;
+	struct usb_device *usbdev;
+	struct urb *irq;
+	struct wacom_features *features;
+	int tool[2];
+	int open;
+	int x, y;
+	__u32 serial[2];
+	char phys[32];
+};
+
+static void wacom_pl_irq(struct urb *urb)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	int prox;
+
+	if (urb->status) return;
+
+	if (data[0] != 2)
+		dbg("received unknown report #%d", data[0]);
+
+	prox = data[1] & 0x20;
+	
+	input_report_key(dev, BTN_TOOL_PEN, prox);
+	
+	if (prox) {
+		int pressure = (data[4] & 0x04) >> 2 | ((__u32)(data[7] & 0x7f) << 1);
+
+		input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 8) | ((__u32)(data[1] & 0x03) << 16));
+		input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 8) | ((__u32)(data[4] & 0x03) << 8));
+		input_report_abs(dev, ABS_PRESSURE, (data[7] & 0x80) ? (255 - pressure) : (pressure + 255));
+		input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
+		input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
+		input_report_key(dev, BTN_STYLUS2, data[4] & 0x20);
+	}
+	
+	input_event(dev, EV_MSC, MSC_SERIAL, 0);
+}
+
+static void wacom_graphire_irq(struct urb *urb)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	int x, y;
+
+	if (urb->status) return;
+
+	if (data[0] != 2)
+		dbg("received unknown report #%d", data[0]);
+
+	x = data[2] | ((__u32)data[3] << 8);
+	y = data[4] | ((__u32)data[5] << 8);
+
+	switch ((data[1] >> 5) & 3) {
+
+		case 0:	/* Pen */
+			input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80);
+			break;
+
+		case 1: /* Rubber */
+			input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
+			break;
+
+		case 2: /* Mouse */
+			input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24);
+			input_report_key(dev, BTN_LEFT, data[1] & 0x01);
+			input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
+			input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
+			input_report_abs(dev, ABS_DISTANCE, data[7]);
+			input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+
+			input_report_abs(dev, ABS_X, x);
+			input_report_abs(dev, ABS_Y, y);
+
+			input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
+			return;
+	}
+
+	if (data[1] & 0x80) {
+		input_report_abs(dev, ABS_X, wacom->x = x);
+		input_report_abs(dev, ABS_Y, wacom->y = y);
+	}
+
+	input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+	input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
+	input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
+
+	input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
+}
+
+static void wacom_intuos_irq(struct urb *urb)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	unsigned int t;
+	int idx;
+
+	if (urb->status) return;
+
+	if (data[0] != 2)
+		dbg("received unknown report #%d", data[0]);
+
+	/* tool number */
+	idx = data[1] & 0x01;
+
+	if ((data[1] & 0xfc) == 0xc0) {						/* Enter report */
+
+		wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 4) +		/* serial number of the tool */
+			((__u32)data[4] << 16) + ((__u32)data[5] << 12) +
+			((__u32)data[6] << 4) + (data[7] >> 4);
+
+		switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
+			case 0x832:
+			case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL;		break;	/* Inking pen */
+			case 0x822:
+			case 0x022: wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Pen */
+			case 0x812:
+			case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH;		break;	/* Stroke pen */
+		        case 0x09c:
+			case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE;		break;	/* Mouse 4D */
+			case 0x096: wacom->tool[idx] = BTN_TOOL_LENS;		break;	/* Lens cursor */
+			case 0x82a:
+		        case 0x91a:
+			case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER;		break;	/* Eraser */
+			case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH;	break;	/* Airbrush */
+			default:    wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Unknown tool */
+		}	
+
+		input_report_key(dev, wacom->tool[idx], 1);
+		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+		return;
+	}
+
+	if ((data[1] & 0xfe) == 0x80) {						/* Exit report */
+		input_report_key(dev, wacom->tool[idx], 0);
+		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+		return;
+	}
+
+	input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
+	input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
+	input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
+
+	if ((data[1] & 0xb8) == 0xa0) {						/* general pen packet */
+		input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+		input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+		input_report_key(dev, BTN_STYLUS, data[1] & 2);
+		input_report_key(dev, BTN_STYLUS2, data[1] & 4);
+		input_report_key(dev, BTN_TOUCH, t > 10);
+	}
+
+	if ((data[1] & 0xbc) == 0xb4) {						/* airbrush second packet */
+		input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+		input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+	}
+	
+	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {		/* 4D mouse or Lens cursor packets */
+
+		if (data[1] & 0x02) {						/* Rotation packet */
+
+			input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
+					 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3):
+					 (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1);
+
+		} else {
+
+			input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
+			input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
+			input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
+
+	 		if ((data[1] & 0x10) == 0) {				/* 4D mouse packets */
+
+				input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
+				input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
+				input_report_abs(dev, ABS_THROTTLE,  (data[8] & 0x08) ?
+						 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
+						 -((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+
+			} else {						/* Lens cursor packets */
+
+				input_report_key(dev, BTN_SIDE,   data[8] & 0x10);
+				input_report_key(dev, BTN_EXTRA,  data[8] & 0x08);
+			}
+		}
+	}
+	
+	input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+}
+
+#define WACOM_INTUOS_TOOLS	(BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS))
+#define WACOM_INTUOS_BUTTONS	(BIT(BTN_SIDE) | BIT(BTN_EXTRA))
+#define WACOM_INTUOS_ABS	(BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE))
+
+struct wacom_features wacom_features[] = {
+	{ "Wacom Graphire",      8, 10206,  7422,  511, 32, wacom_graphire_irq,
+		BIT(EV_REL), 0, BIT(REL_WHEEL), 0 },
+	{ "Wacom Intuos 4x5",   10, 12700, 10360, 1023, 15, wacom_intuos_irq,
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+	{ "Wacom Intuos 6x8",   10, 20320, 15040, 1023, 15, wacom_intuos_irq,
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+	{ "Wacom Intuos 9x12",  10, 30480, 23060, 1023, 15, wacom_intuos_irq,
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+	{ "Wacom Intuos 12x12", 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+	{ "Wacom Intuos 12x18", 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
+		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
+	{ "Wacom PL500",        8,  12328, 9256,   511, 32, wacom_pl_irq,
+		0,  0, 0, 0 },
+	{ NULL , 0 }
+};
+
+struct usb_device_id wacom_ids[] = {
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), driver_info: 0 },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), driver_info: 1 },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), driver_info: 2 },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 3 },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 4 },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 5 },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 6 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, wacom_ids);
+
+static int wacom_open(struct input_dev *dev)
+{
+	struct wacom *wacom = dev->private;
+
+	if (wacom->open++)
+		return 0;
+
+	wacom->irq->dev = wacom->usbdev;
+	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+static void wacom_close(struct input_dev *dev)
+{
+	struct wacom *wacom = dev->private;
+
+	if (!--wacom->open)
+		usb_unlink_urb(wacom->irq);
+}
+
+static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+{
+	struct usb_endpoint_descriptor *endpoint;
+	struct wacom *wacom;
+	char path[64];
+
+	if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
+	memset(wacom, 0, sizeof(struct wacom));
+
+	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!wacom->irq) {
+		kfree(wacom);
+		return NULL;
+	}
+
+	wacom->features = wacom_features + id->driver_info;
+
+	wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) | wacom->features->evbit;
+	wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | wacom->features->absbit;
+	wacom->dev.relbit[0] |= wacom->features->relbit;
+	wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | wacom->features->btnbit;
+	wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) |
+		BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit;
+	wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
+
+	wacom->dev.absmax[ABS_X] = wacom->features->x_max;
+	wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
+	wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
+	wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
+	wacom->dev.absmax[ABS_TILT_X] = 127;
+	wacom->dev.absmax[ABS_TILT_Y] = 127;
+	wacom->dev.absmax[ABS_WHEEL] = 1023;
+
+	wacom->dev.absmin[ABS_RZ] = -900;
+	wacom->dev.absmax[ABS_RZ] = 899;
+	wacom->dev.absmin[ABS_THROTTLE] = -1023;
+	wacom->dev.absmax[ABS_THROTTLE] = 1023;
+
+	wacom->dev.absfuzz[ABS_X] = 4;
+	wacom->dev.absfuzz[ABS_Y] = 4;
+
+	wacom->dev.private = wacom;
+	wacom->dev.open = wacom_open;
+	wacom->dev.close = wacom_close;
+
+	usb_make_path(dev, path, 64);
+	sprintf(wacom->phys, "%s/input0", path);
+
+	wacom->dev.name = wacom->features->name;
+	wacom->dev.phys = wacom->phys;
+	wacom->dev.idbus = BUS_USB;
+	wacom->dev.idvendor = dev->descriptor.idVendor;
+	wacom->dev.idproduct = dev->descriptor.idProduct;
+	wacom->dev.idversion = dev->descriptor.bcdDevice;
+	wacom->usbdev = dev;
+
+	endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
+	FILL_INT_URB(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+		     wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval);
+
+	input_register_device(&wacom->dev);
+
+	printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
+
+	return wacom;
+}
+
+static void wacom_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct wacom *wacom = ptr;
+	usb_unlink_urb(wacom->irq);
+	input_unregister_device(&wacom->dev);
+	usb_free_urb(wacom->irq);
+	kfree(wacom);
+}
+
+static struct usb_driver wacom_driver = {
+	name:		"wacom",
+	probe:		wacom_probe,
+	disconnect:	wacom_disconnect,
+	id_table:	wacom_ids,
+};
+
+static int __init wacom_init(void)
+{
+	usb_register(&wacom_driver);
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+static void __exit wacom_exit(void)
+{
+	usb_deregister(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
diff -Nru a/drivers/usb/kaweth.c b/drivers/usb/kaweth.c
--- a/drivers/usb/kaweth.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1066 +0,0 @@
-/****************************************************************
- *
- *     kaweth.c - driver for KL5KUSB101 based USB->Ethernet
- *
- *     (c) 2000 Interlan Communications
- *     (c) 2000 Stephane Alnet
- *     (C) 2001 Brad Hards
- *
- *     Original author: The Zapman <zapman@interlan.net>
- *     Inspired by, and much credit goes to Michael Rothwell 
- *     <rothwell@interlan.net> for the test equipment, help, and patience
- *     Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
- *     Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki 
- *     for providing the firmware and driver resources.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2, or 
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software Foundation,
- *     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
- *
- ****************************************************************/
-
-/* TODO:
- * Fix in_interrupt() problem
- * Develop test procedures for USB net interfaces
- * Run test procedures
- * Fix bugs from previous two steps
- * Snoop other OSs for any tricks we're not doing
- * SMP locking
- * Reduce arbitrary timeouts 
- * Smart multicast support 
- * Temporary MAC change support
- * Tunable SOFs parameter - ioctl()?
- * Ethernet stats collection
- * Code formatting improvements
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/usb.h>
-#include <linux/types.h>
-#include <asm/semaphore.h>
-#include <asm/byteorder.h>
-
-#define DEBUG
-
-#ifdef DEBUG
-#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
-#else
-#define kaweth_dbg(format, arg...) do {} while (0)
-#endif
-#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg)
-#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg)
-#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg)
-
-
-#include "kawethfw.h"
-
-#define KAWETH_MTU			1514
-#define KAWETH_BUF_SIZE			1664
-#define KAWETH_TX_TIMEOUT		(5 * HZ)
-#define KAWETH_FIRMWARE_BUF_SIZE	4096
-#define KAWETH_CONTROL_TIMEOUT		(30 * HZ)
-
-#define KAWETH_STATUS_BROKEN		0x0000001
-#define KAWETH_STATUS_CLOSING		0x0000002
-
-#define KAWETH_PACKET_FILTER_PROMISCUOUS	0x01
-#define KAWETH_PACKET_FILTER_ALL_MULTICAST	0x02
-#define KAWETH_PACKET_FILTER_DIRECTED		0x04
-#define KAWETH_PACKET_FILTER_BROADCAST		0x08
-#define KAWETH_PACKET_FILTER_MULTICAST		0x10
-
-/* Table 7 */
-#define KAWETH_COMMAND_GET_ETHERNET_DESC	0x00
-#define KAWETH_COMMAND_MULTICAST_FILTERS        0x01
-#define KAWETH_COMMAND_SET_PACKET_FILTER	0x02
-#define KAWETH_COMMAND_STATISTICS               0x03
-#define KAWETH_COMMAND_SET_TEMP_MAC     	0x06
-#define KAWETH_COMMAND_GET_TEMP_MAC             0x07
-#define KAWETH_COMMAND_SET_URB_SIZE		0x08
-#define KAWETH_COMMAND_SET_SOFS_WAIT		0x09
-#define KAWETH_COMMAND_SCAN			0xFF
-
-#define KAWETH_SOFS_TO_WAIT			0x05
-
-
-MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr> and Brad Hards <bhards@bigpond.net.au>");
-MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
-MODULE_LICENSE("GPL");
-
-static void *kaweth_probe(
-            struct usb_device *dev,             /* the device */
-            unsigned ifnum,                     /* what interface */
-            const struct usb_device_id *id      /* from id_table */
-	);
-static void kaweth_disconnect(struct usb_device *dev, void *ptr);
-int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
-				struct usb_ctrlrequest *cmd, void *data,
-				int len, int timeout);
-
-/****************************************************************
- *     usb_device_id
- ****************************************************************/
-static struct usb_device_id usb_klsi_table[] = {
-	{ USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */ 
-	{ USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
-	{ USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */ 
-	{ USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */ 
-	{ USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */ 
-	{ USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
-	{ USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */ 
-	{ USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
-	{ USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
-	{ USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */ 
-	{ USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */ 
-	{ USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */ 
-	{ USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */ 
-	{ USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */ 
-	{ USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
-	{ USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
-	{ USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
-	{ USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */
-	{ USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */
-	{ USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */
-	{ USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */
-	{ USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */
-	{ USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
-	{ USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
-	{ USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
-	{ USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ 
-	{ USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ 
-	{ USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ 
-	{ USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
-	{} /* Null terminator */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_klsi_table);
-
-/****************************************************************
- *     kaweth_driver
- ****************************************************************/
-static struct usb_driver kaweth_driver = {
-	owner:		THIS_MODULE,
-	name:		"kaweth",
-	probe:		kaweth_probe,
-	disconnect:	kaweth_disconnect,
-	id_table:       usb_klsi_table,
-};
-
-typedef __u8 eth_addr_t[6];
-
-/****************************************************************
- *     usb_eth_dev
- ****************************************************************/
-struct usb_eth_dev {
-	char *name;
-	__u16 vendor;
-	__u16 device;
-	void *pdata;
-};
-
-/****************************************************************
- *     kaweth_ethernet_configuration
- *     Refer Table 8
- ****************************************************************/
-struct kaweth_ethernet_configuration
-{
-	__u8 size;
-	__u8 reserved1;
-	__u8 reserved2;
-	eth_addr_t hw_addr;
-	__u32 statistics_mask;
-	__u16 segment_size;
-	__u16 max_multicast_filters;
-	__u8 reserved3;
-} __attribute__ ((packed));
-
-/****************************************************************
- *     kaweth_device
- ****************************************************************/
-struct kaweth_device
-{
-	spinlock_t device_lock;
-
-	__u32 status;
-
-	struct usb_device *dev;
-	struct net_device *net;
-	wait_queue_head_t control_wait;
-
-	struct urb *rx_urb;
-	struct urb *tx_urb;
-	
-	__u8 firmware_buf[KAWETH_FIRMWARE_BUF_SIZE];
-	__u8 tx_buf[KAWETH_BUF_SIZE];
-	__u8 rx_buf[KAWETH_BUF_SIZE];
-	__u16 packet_filter_bitmap;
-
-	struct kaweth_ethernet_configuration configuration;
-
-	struct net_device_stats stats;
-} __attribute__ ((packed));
-
-
-/****************************************************************
- *     kaweth_control
- ****************************************************************/
-static int kaweth_control(struct kaweth_device *kaweth,
-			  unsigned int pipe, 
-			  __u8 request, 
-			  __u8 requesttype, 
-			  __u16 value, 
-			  __u16 index,
-			  void *data, 
-			  __u16 size, 
-			  int timeout)
-{
-	struct usb_ctrlrequest *dr;
-
-	kaweth_dbg("kaweth_control()");
-
-	if(in_interrupt()) {
-		kaweth_dbg("in_interrupt()");
-		return -EBUSY;
-	}
-
-	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-
-	if (!dr) {
-		kaweth_dbg("kmalloc() failed");
-		return -ENOMEM;
-	}
-	
-	dr->bRequestType= requesttype;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16p(&value);
-	dr->wIndex = cpu_to_le16p(&index);
-	dr->wLength = cpu_to_le16p(&size);
-
-	return kaweth_internal_control_msg(kaweth->dev,
-					pipe,
-					dr,
-					data,
-					size,
-					timeout);
-}
-
-/****************************************************************
- *     kaweth_read_configuration
- ****************************************************************/
-static int kaweth_read_configuration(struct kaweth_device *kaweth)
-{
-	int retval;
-
-	kaweth_dbg("Reading kaweth configuration");
-
-	retval = kaweth_control(kaweth,
-				usb_rcvctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_GET_ETHERNET_DESC,
-				USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
-				0,
-				0,
-				(void *)&kaweth->configuration,
-				sizeof(kaweth->configuration),
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
-}
-
-/****************************************************************
- *     kaweth_set_urb_size
- ****************************************************************/
-static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
-{
-	int retval;
-
-	kaweth_dbg("Setting URB size to %d", (unsigned)urb_size);
-
-	retval = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_URB_SIZE,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				urb_size,
-				0,
-				(void *)&kaweth->firmware_buf,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
-}
-
-/****************************************************************
- *     kaweth_set_sofs_wait
- ****************************************************************/
-static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
-{
-	int retval;
-
-	kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
-
-	retval = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_SOFS_WAIT,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				sofs_wait,
-				0,
-				(void *)&kaweth->firmware_buf,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
-}
-
-/****************************************************************
- *     kaweth_set_receive_filter
- ****************************************************************/
-static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
-				     __u16 receive_filter)
-{
-	int retval;
-
-	kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter);
-
-	retval = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_PACKET_FILTER,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				receive_filter,
-				0,
-				(void *)&kaweth->firmware_buf,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	return retval;
-}
-
-/****************************************************************
- *     kaweth_download_firmware
- ****************************************************************/
-static int kaweth_download_firmware(struct kaweth_device *kaweth, 
-				    __u8 *data, 
-				    __u16 data_len,
-				    __u8 interrupt,
-				    __u8 type)
-{	
-	if(data_len > KAWETH_FIRMWARE_BUF_SIZE)	{
-		kaweth_err("Firmware too big: %d", data_len);
-		return -ENOSPC;
-	}
-	
-	memcpy(kaweth->firmware_buf, data, data_len);
-	
-	kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
-	kaweth->firmware_buf[3] = data_len >> 8;
-	kaweth->firmware_buf[4] = type;
-	kaweth->firmware_buf[5] = interrupt;
-
-	kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
-		   kaweth->firmware_buf[2]);
-
-	kaweth_dbg("Downloading firmware at %p to kaweth device at %p", 
-	    data, 
-	    kaweth);
-	kaweth_dbg("Firmware length: %d", data_len);
-
-	return kaweth_control(kaweth,
-		              usb_sndctrlpipe(kaweth->dev, 0),
-			      KAWETH_COMMAND_SCAN,
-			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-			      0,
-			      0,
-			      (void *)&kaweth->firmware_buf,
-			      data_len,
-			      KAWETH_CONTROL_TIMEOUT);
-}
-
-/****************************************************************
- *     kaweth_trigger_firmware
- ****************************************************************/
-static int kaweth_trigger_firmware(struct kaweth_device *kaweth,
-				   __u8 interrupt)
-{
-	kaweth->firmware_buf[0] = 0xB6;
-	kaweth->firmware_buf[1] = 0xC3;
-	kaweth->firmware_buf[2] = 0x01;
-	kaweth->firmware_buf[3] = 0x00;
-	kaweth->firmware_buf[4] = 0x06;
-	kaweth->firmware_buf[5] = interrupt;
-	kaweth->firmware_buf[6] = 0x00;
-	kaweth->firmware_buf[7] = 0x00;
-	
-	kaweth_dbg("Triggering firmware");
-
-	return kaweth_control(kaweth,
-			      usb_sndctrlpipe(kaweth->dev, 0),
-			      KAWETH_COMMAND_SCAN,
-			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-			      0,
-			      0,
-			      (void *)&kaweth->firmware_buf,
-			      8,
-			      KAWETH_CONTROL_TIMEOUT);
-}
-
-/****************************************************************
- *     kaweth_reset
- ****************************************************************/
-static int kaweth_reset(struct kaweth_device *kaweth)
-{
-	int result;
-
-	kaweth_dbg("kaweth_reset(%p)", kaweth);
-	result = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				USB_REQ_SET_CONFIGURATION, 
-				0, 
-				kaweth->dev->config[0].bConfigurationValue,
-				0, 
-				NULL, 
-				0, 
-				KAWETH_CONTROL_TIMEOUT);
-
-	udelay(10000);
-
-	kaweth_dbg("kaweth_reset() returns %d.",result);
-
-	return result;
-}
-
-static void kaweth_usb_receive(struct urb *);
-
-/****************************************************************
- *     kaweth_resubmit_rx_urb
- ****************************************************************/
-static inline void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
-						int mem_flags)
-{
-	int result;
-
-	memset(kaweth->rx_urb, 0, sizeof(*kaweth->rx_urb));
-
-	FILL_BULK_URB(kaweth->rx_urb,
-		      kaweth->dev,
-		      usb_rcvbulkpipe(kaweth->dev, 1),
-		      kaweth->rx_buf,
-		      KAWETH_BUF_SIZE,
-		      kaweth_usb_receive,
-		      kaweth);
-
-	if((result = usb_submit_urb(kaweth->rx_urb, mem_flags))) {
-		kaweth_err("resubmitting rx_urb %d failed", result);
-	}
-}
-
-static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
-
-/****************************************************************
- *     kaweth_usb_receive
- ****************************************************************/
-static void kaweth_usb_receive(struct urb *urb)
-{
-	struct kaweth_device *kaweth = urb->context;
-	struct net_device *net = kaweth->net;
-	
-	int count = urb->actual_length;
-	int count2 = urb->transfer_buffer_length;
-			
-	__u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
-
-	struct sk_buff *skb;
-
-	if(kaweth->status & KAWETH_STATUS_CLOSING) {
-		return;
-	}
-	
-	if(urb->status && urb->status != -EREMOTEIO && count != 1) { 
-		kaweth_err("%s RX status: %d count: %d packet_len: %d",
-                           net->name, 
-			   urb->status,
-			   count, 
-			   (int)pkt_len);
-		kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-                return;
-	}
-
-	if(kaweth->net && (count > 2)) {
-		if(pkt_len > (count - 2)) {
-			kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
-			kaweth_err("Packet len & 2047: %x", pkt_len & 2047);
-			kaweth_err("Count 2: %x", count2);
-		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-                        return;
-                }
-		
-		if(!(skb = dev_alloc_skb(pkt_len+2))) {
-		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-                        return;
-		}
-
-		skb->dev = net;
-
-		eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
-		
-		skb_put(skb, pkt_len);
-
-		skb->protocol = eth_type_trans(skb, net);
-		
-		netif_rx(skb);
-		
-		kaweth->stats.rx_packets++;
-		kaweth->stats.rx_bytes += pkt_len;
-	}
-
-	kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
-}
-
-/****************************************************************
- *     kaweth_open
- ****************************************************************/
-static int kaweth_open(struct net_device *net)
-{
-	struct kaweth_device *kaweth = (struct kaweth_device *)net->priv;
-
-	kaweth_dbg("Dev usage: %d", kaweth->dev->refcnt.counter);
-
-	kaweth_dbg("Opening network device.");
-
-	MOD_INC_USE_COUNT;
-
-	kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
-
-	netif_start_queue(net);
-
-	kaweth_async_set_rx_mode(kaweth);
-	return 0;
-}
-
-/****************************************************************
- *     kaweth_close
- ****************************************************************/
-static int kaweth_close(struct net_device *net)
-{
-	struct kaweth_device *kaweth = net->priv;
-
-	netif_stop_queue(net);
-
-	kaweth->status |= KAWETH_STATUS_CLOSING;
-
-	usb_unlink_urb(kaweth->rx_urb);
-
-	kaweth->status &= ~KAWETH_STATUS_CLOSING;
-
-	MOD_DEC_USE_COUNT;
-
-	printk("Dev usage: %d", kaweth->dev->refcnt.counter);
-
-	return 0;
-}
-
-/****************************************************************
- *     kaweth_ioctl
- ****************************************************************/
-static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
-{
-	return -EOPNOTSUPP;
-}
-
-/****************************************************************
- *     kaweth_usb_transmit_complete
- ****************************************************************/
-static void kaweth_usb_transmit_complete(struct urb *urb)
-{
-	struct kaweth_device *kaweth = urb->context;
-
-	if (unlikely(urb->status != 0))
-		kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
-
-	netif_wake_queue(kaweth->net);
-}
-
-/****************************************************************
- *     kaweth_start_xmit
- ****************************************************************/
-static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
-{
-	struct kaweth_device *kaweth = net->priv;
-	int count = skb->len;
-	
-	int res;
-
-	spin_lock(&kaweth->device_lock);
-
-	kaweth_async_set_rx_mode(kaweth);
-	netif_stop_queue(net);
-
-	*((__u16 *)kaweth->tx_buf) = cpu_to_le16(skb->len);
-
-	memcpy(kaweth->tx_buf + 2, skb->data, skb->len);
-
-	memset(kaweth->tx_urb, 0, sizeof(*kaweth->tx_urb));
-
-	FILL_BULK_URB(kaweth->tx_urb,
-		      kaweth->dev,
-		      usb_sndbulkpipe(kaweth->dev, 2),
-		      kaweth->tx_buf,
-		      count + 2,
-		      kaweth_usb_transmit_complete,
-		      kaweth);
-
-	if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
-	{
-		kaweth_warn("kaweth failed tx_urb %d", res);
-		kaweth->stats.tx_errors++;
-		
-		netif_start_queue(net);
-	} 
-	else 
-	{
-		kaweth->stats.tx_packets++;
-		kaweth->stats.tx_bytes += skb->len;
-		net->trans_start = jiffies;
-	}
-
-	dev_kfree_skb(skb);
-
-	spin_unlock(&kaweth->device_lock);
-
-	return 0;
-}
-
-/****************************************************************
- *     kaweth_set_rx_mode
- ****************************************************************/
-static void kaweth_set_rx_mode(struct net_device *net)
-{
-	struct kaweth_device *kaweth = net->priv;
-	
-	__u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
-                                     KAWETH_PACKET_FILTER_BROADCAST |
-		                     KAWETH_PACKET_FILTER_MULTICAST;
-
-	kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap);
-
-	netif_stop_queue(net);
-
-	if (net->flags & IFF_PROMISC) {
-		packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
-	} 
-	else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) {
-		packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST;
-	}
-
-	kaweth->packet_filter_bitmap = packet_filter_bitmap;
-	netif_wake_queue(net);
-}
-
-/****************************************************************
- *     kaweth_async_set_rx_mode
- ****************************************************************/
-static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
-{
-	__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
-	kaweth->packet_filter_bitmap = 0;	
-	if(packet_filter_bitmap == 0) return;
-
-	{
-	int result;
-	result = kaweth_control(kaweth,
-				usb_sndctrlpipe(kaweth->dev, 0),
-				KAWETH_COMMAND_SET_PACKET_FILTER,
-				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-				packet_filter_bitmap,
-				0,
-				(void *)&kaweth->firmware_buf,
-				0,
-				KAWETH_CONTROL_TIMEOUT);
-
-	if(result < 0) {
-		kaweth_err("Failed to set Rx mode: %d", result);
-	}
-	else {
-		kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap);
-	}
-	}
-}
-
-/****************************************************************
- *     kaweth_netdev_stats
- ****************************************************************/
-static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
-{
-	return &((struct kaweth_device *)dev->priv)->stats;
-}
-
-/****************************************************************
- *     kaweth_tx_timeout
- ****************************************************************/
-static void kaweth_tx_timeout(struct net_device *net)
-{
-	struct kaweth_device *kaweth = net->priv;
-
-	kaweth_warn("%s: Tx timed out. Resetting.", net->name);
-	kaweth->stats.tx_errors++;
-	net->trans_start = jiffies;
-
-	usb_unlink_urb(kaweth->tx_urb);
-}
-
-/****************************************************************
- *     kaweth_probe
- ****************************************************************/
-static void *kaweth_probe(
-            struct usb_device *dev,             /* the device */
-            unsigned ifnum,                      /* what interface */
-            const struct usb_device_id *id      /* from id_table */
-	)
-{
-	struct kaweth_device *kaweth;
-	const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-	int result = 0;
-
-	kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
-		 dev->devnum, 
-		 (int)dev->descriptor.idVendor, 
-		 (int)dev->descriptor.idProduct,
-		 (int)dev->descriptor.bcdDevice);
-
-	kaweth_dbg("Device at %p", dev);
-
-	kaweth_dbg("Descriptor length: %x type: %x", 
-		 (int)dev->descriptor.bLength,
-		 (int)dev->descriptor.bDescriptorType);
-
-	if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) {
-		kaweth_dbg("out of memory allocating device structure\n");
-		return NULL;
-	}
-
-	memset(kaweth, 0, sizeof(struct kaweth_device));
-
-	kaweth->dev = dev;
-	spin_lock_init(&kaweth->device_lock);
-		
-	kaweth_dbg("Resetting.");
-
-	kaweth_reset(kaweth);
-
-	/*
-	 * If high byte of bcdDevice is nonzero, firmware is already
-	 * downloaded. Don't try to do it again, or we'll hang the device.
-	 */
-
-	if (dev->descriptor.bcdDevice >> 8) {
-		kaweth_info("Firmware present in device.");
-	} else {
-		/* Download the firmware */
-		kaweth_info("Downloading firmware...");
-		if ((result = kaweth_download_firmware(kaweth, 
-						      kaweth_new_code, 
-						      len_kaweth_new_code, 
-						      100, 
-						      2)) < 0) {
-			kaweth_err("Error downloading firmware (%d)", result);
-			kfree(kaweth);
-			return NULL;
-		}
-
-		if ((result = kaweth_download_firmware(kaweth, 
-						      kaweth_new_code_fix, 
-						      len_kaweth_new_code_fix, 
-						      100, 
-						      3)) < 0) {
-			kaweth_err("Error downloading firmware fix (%d)", result);
-			kfree(kaweth);
-			return NULL;
-		}
-
-		if ((result = kaweth_download_firmware(kaweth,
-						      kaweth_trigger_code,
-						      len_kaweth_trigger_code,
-						      126,
-						      2)) < 0) {
-			kaweth_err("Error downloading trigger code (%d)", result);
-			kfree(kaweth);
-			return NULL;
-		}
-
-		if ((result = kaweth_download_firmware(kaweth,
-						      kaweth_trigger_code_fix,
-						      len_kaweth_trigger_code_fix,
-						      126,
-						      3)) < 0) {
-			kaweth_err("Error downloading trigger code fix (%d)", result);
-			kfree(kaweth);
-			return NULL;
-		}
-
-
-		if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
-			kaweth_err("Error triggering firmware (%d)", result);
-			kfree(kaweth);
-			return NULL;
-		}
-
-		/* Device will now disappear for a moment...  */
-		kaweth_info("Firmware loaded.  I'll be back...");
-		kfree(kaweth);
-		return NULL;
-	}
-
-	result = kaweth_read_configuration(kaweth);
-
-	if(result < 0) {
-		kaweth_err("Error reading configuration (%d), no net device created", result);
-		kfree(kaweth);
-		return NULL;
-	}
-
-	kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask);
-	kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
-	kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size));
-	kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
-		 (int)kaweth->configuration.hw_addr[0],
-		 (int)kaweth->configuration.hw_addr[1],
-		 (int)kaweth->configuration.hw_addr[2],
-		 (int)kaweth->configuration.hw_addr[3],
-		 (int)kaweth->configuration.hw_addr[4],
-		 (int)kaweth->configuration.hw_addr[5]);
-
-	if(!memcmp(&kaweth->configuration.hw_addr,
-                   &bcast_addr, 
-		   sizeof(bcast_addr))) {
-		kaweth_err("Firmware not functioning properly, no net device created");
-		kfree(kaweth);
-		return NULL;
-	}
-
-	if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
-		kaweth_dbg("Error setting URB size");
-		return kaweth;
-	}
-	
-	if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
-		kaweth_err("Error setting SOFS wait");
-		return kaweth;
-	}
-
-	result = kaweth_set_receive_filter(kaweth, 
-                                           KAWETH_PACKET_FILTER_DIRECTED |
-                                           KAWETH_PACKET_FILTER_BROADCAST |
-                                           KAWETH_PACKET_FILTER_MULTICAST);
-
-	if(result < 0) {
-		kaweth_err("Error setting receive filter");
-		return kaweth;
-	}
-	
-	kaweth_dbg("Initializing net device.");
-
-	kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-
-	kaweth->net = init_etherdev(0, 0);
-	if (!kaweth->net) {
-		kaweth_err("Error calling init_etherdev.");
-		return kaweth;
-	}
-
-	memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
-	memcpy(kaweth->net->dev_addr, 
-               &kaweth->configuration.hw_addr,
-               sizeof(kaweth->configuration.hw_addr));
-	 
-	kaweth->net->priv = kaweth;
-	kaweth->net->open = kaweth_open;
-	kaweth->net->stop = kaweth_close;
-
-	kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
-	kaweth->net->tx_timeout = kaweth_tx_timeout;
-	
-	kaweth->net->do_ioctl = kaweth_ioctl;
-	kaweth->net->hard_start_xmit = kaweth_start_xmit;
-	kaweth->net->set_multicast_list = kaweth_set_rx_mode;
-	kaweth->net->get_stats = kaweth_netdev_stats;
-	kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size);
-
-	memset(&kaweth->stats, 0, sizeof(kaweth->stats));
-
-	kaweth_info("kaweth interface created at %s", kaweth->net->name);
-								
-	kaweth_dbg("Kaweth probe returning.");
-
-	return kaweth;
-}
-
-/****************************************************************
- *     kaweth_disconnect
- ****************************************************************/
-static void kaweth_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct kaweth_device *kaweth = ptr;
-
-	kaweth_info("Unregistering");
-
-	if (!kaweth) {
-		kaweth_warn("unregistering non-existant device");
-		return;
-	}
-	usb_unlink_urb(kaweth->tx_urb);
-	usb_unlink_urb(kaweth->rx_urb);
-
-	if(kaweth->net) {
-		if(kaweth->net->flags & IFF_UP) {
-			kaweth_dbg("Closing net device");
-			dev_close(kaweth->net);
-		}
-
-		kaweth_dbg("Unregistering net device");
-		unregister_netdev(kaweth->net);
-	}
-
-	usb_free_urb(kaweth->rx_urb);
-	usb_free_urb(kaweth->tx_urb);
-
-	kfree(kaweth);
-}
-
-
-// FIXME this completion stuff is a modified clone of
-// an OLD version of some stuff in usb.c ... 
-struct usb_api_data {
-	wait_queue_head_t wqh;
-	int done;
-};
-
-/*-------------------------------------------------------------------*
- * completion handler for compatibility wrappers (sync control/bulk) *
- *-------------------------------------------------------------------*/
-static void usb_api_blocking_completion(struct urb *urb)
-{
-        struct usb_api_data *awd = (struct usb_api_data *)urb->context;
-
-	awd->done=1;
-	wake_up(&awd->wqh);
-}
-
-/*-------------------------------------------------------------------*
- *                         COMPATIBILITY STUFF                       *
- *-------------------------------------------------------------------*/
-
-// Starts urb and waits for completion or timeout
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	struct usb_api_data awd;
-        int status;
-
-        init_waitqueue_head(&awd.wqh);
-        awd.done = 0;
-        
-        set_current_state(TASK_INTERRUPTIBLE);
-        add_wait_queue(&awd.wqh, &wait);
-        urb->context = &awd;
-        status = usb_submit_urb(urb, GFP_ATOMIC);
-        if (status) {
-                // something went wrong
-                usb_free_urb(urb);
-                set_current_state(TASK_RUNNING);
-                remove_wait_queue(&awd.wqh, &wait);
-                return status;
-        }
-
-	while (timeout && !awd.done)
-		timeout = schedule_timeout(timeout);
-
-        set_current_state(TASK_RUNNING);
-        remove_wait_queue(&awd.wqh, &wait);
-
-        if (!timeout) {
-                // timeout
-                kaweth_warn("usb_control/bulk_msg: timeout");
-                usb_unlink_urb(urb);  // remove urb safely
-                status = -ETIMEDOUT;
-        }
-	else {
-                status = urb->status;
-	}
-
-        if (actual_length) {
-                *actual_length = urb->actual_length;
-	}
-
-        usb_free_urb(urb);
-        return status;
-}
-
-/*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
-int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
-                            struct usb_ctrlrequest *cmd, void *data, int len,
-			    int timeout)
-{
-        struct urb *urb;
-        int retv;
-        int length;
-
-        urb = usb_alloc_urb(0, GFP_KERNEL);
-        if (!urb)
-                return -ENOMEM;
-
-        FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data,
-			 len, (usb_complete_t)usb_api_blocking_completion,0);
-
-        retv = usb_start_wait_urb(urb, timeout, &length);
-        if (retv < 0) {
-                return retv;
-	}
-        else {
-                return length;
-	}
-}
-
-
-/****************************************************************
- *     kaweth_init
- ****************************************************************/
-int __init kaweth_init(void)
-{
-	kaweth_dbg("Driver loading");
-	return usb_register(&kaweth_driver);
-}
-
-/****************************************************************
- *     kaweth_exit
- ****************************************************************/
-void __exit kaweth_exit(void)
-{
-	usb_deregister(&kaweth_driver);
-}
-
-module_init(kaweth_init);
-module_exit(kaweth_exit);
-
-
-
-
-
-
-
-
diff -Nru a/drivers/usb/kawethfw.h b/drivers/usb/kawethfw.h
--- a/drivers/usb/kawethfw.h	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,557 +0,0 @@
-/******************************************/
-/* NOTE: B6/C3 is data header signature   */
-/*       0xAA/0xBB is data length = total */
-/*       bytes - 7, 0xCC is type, 0xDD is */
-/*       interrupt to use.                */
-/******************************************/
-
-/****************************************************************
- *     kaweth_trigger_code
- ****************************************************************/
-static __u8 kaweth_trigger_code[] = 
-{
-    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
-    0xc8, 0x07, 0xa0, 0x00, 0xf0, 0x07, 0x5e, 0x00,
-    0x06, 0x00, 0xf0, 0x07, 0x0a, 0x00, 0x08, 0x00,
-    0xf0, 0x09, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x07,
-    0x36, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00,
-    0x04, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x10, 0xc0,
-    0xf0, 0x09, 0x0e, 0xc0, 0x00, 0x00, 0xe7, 0x87,
-    0x01, 0x00, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09,
-    0x00, 0xc0, 0x17, 0x02, 0xc8, 0x07, 0xa0, 0x00,
-    0xe7, 0x17, 0x50, 0xc3, 0x10, 0xc0, 0x30, 0xd8,
-    0x04, 0x00, 0x30, 0x5c, 0x08, 0x00, 0x04, 0x00,
-    0xb0, 0xc0, 0x06, 0x00, 0xc8, 0x05, 0xe7, 0x05,
-    0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0x49, 0xaf,
-    0xc0, 0x07, 0x00, 0x00, 0x60, 0xaf, 0x4a, 0xaf,
-    0x00, 0x0c, 0x0c, 0x00, 0x40, 0xd2, 0x00, 0x1c,
-    0x0c, 0x00, 0x40, 0xd2, 0x30, 0x00, 0x08, 0x00,
-    0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0xf0, 0x07,
-    0x86, 0x00, 0x06, 0x00, 0x67, 0xcf, 0x27, 0x0c,
-    0x02, 0x00, 0x00, 0x00, 0x27, 0x0c, 0x00, 0x00,
-    0x0e, 0xc0, 0x49, 0xaf, 0x64, 0xaf, 0xc0, 0x07,
-    0x00, 0x00, 0x4b, 0xaf, 0x4a, 0xaf, 0x5a, 0xcf,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x94, 0x00, 0x05, 0x00,
-    0x00, 0x00
-};
-/****************************************************************
- *     kaweth_trigger_code_fix
- ****************************************************************/
-static __u8 kaweth_trigger_code_fix[] = 
-{
-    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
-    0x02, 0x00, 0x06, 0x00, 0x18, 0x00, 0x3e, 0x00,
-    0x80, 0x00, 0x98, 0x00, 0xaa, 0x00,
-    0x00, 0x00
-};
-
-/****************************************************************
- *     kaweth_new_code
- ****************************************************************/
-static __u8 kaweth_new_code[] = 
-{
-    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
-    0x9f, 0xcf, 0xde, 0x06, 0xe7, 0x57, 0x00, 0x00,
-    0xc4, 0x06, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f,
-    0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0,
-    0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf,
-    0xd7, 0x09, 0x00, 0xc0, 0xe7, 0x09, 0xa2, 0xc0,
-    0xbe, 0x06, 0x9f, 0xaf, 0x36, 0x00, 0xe7, 0x05,
-    0x00, 0xc0, 0xa7, 0xcf, 0xbc, 0x06, 0x97, 0xcf,
-    0xe7, 0x57, 0x00, 0x00, 0xb8, 0x06, 0xa7, 0xa1,
-    0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
-    0x14, 0x08, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00,
-    0xa4, 0xc0, 0xa7, 0xc0, 0x7a, 0x06, 0x9f, 0xaf,
-    0x92, 0x07, 0xe7, 0x07, 0x00, 0x00, 0x14, 0x08,
-    0xe7, 0x57, 0xff, 0xff, 0xba, 0x06, 0x9f, 0xa0,
-    0x38, 0x00, 0xe7, 0x59, 0xba, 0x06, 0xbe, 0x06,
-    0x9f, 0xa0, 0x38, 0x00, 0xc8, 0x09, 0xca, 0x06,
-    0x08, 0x62, 0x9f, 0xa1, 0x36, 0x08, 0xc0, 0x09,
-    0x76, 0x06, 0x00, 0x60, 0xa7, 0xc0, 0x7a, 0x06,
-    0x9f, 0xaf, 0xcc, 0x02, 0xe7, 0x57, 0x00, 0x00,
-    0xb8, 0x06, 0xa7, 0xc1, 0x7a, 0x06, 0x9f, 0xaf,
-    0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x06,
-    0x0a, 0xc1, 0xe7, 0x09, 0x20, 0xc0, 0x10, 0x08,
-    0xe7, 0xd0, 0x10, 0x08, 0xe7, 0x67, 0x40, 0x00,
-    0x10, 0x08, 0x9f, 0xaf, 0x92, 0x0c, 0xc0, 0x09,
-    0xd0, 0x06, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59,
-    0xbe, 0x06, 0x02, 0xc0, 0x9f, 0xaf, 0xec, 0x00,
-    0x9f, 0xaf, 0x34, 0x02, 0xe7, 0x57, 0x00, 0x00,
-    0xa6, 0x06, 0x9f, 0xa0, 0x7a, 0x02, 0xa7, 0xcf,
-    0x7a, 0x06, 0x48, 0x02, 0xe7, 0x09, 0xbe, 0x06,
-    0xd0, 0x06, 0xc8, 0x37, 0x04, 0x00, 0x9f, 0xaf,
-    0x08, 0x03, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
-    0xce, 0x06, 0x97, 0xc0, 0xd7, 0x09, 0x00, 0xc0,
-    0xc1, 0xdf, 0xc8, 0x09, 0xc6, 0x06, 0x08, 0x62,
-    0x14, 0xc0, 0x27, 0x04, 0xc6, 0x06, 0x10, 0x94,
-    0xf0, 0x07, 0x10, 0x08, 0x02, 0x00, 0xc1, 0x07,
-    0x01, 0x00, 0x70, 0x00, 0x04, 0x00, 0xf0, 0x07,
-    0x30, 0x01, 0x06, 0x00, 0x50, 0xaf, 0xe7, 0x07,
-    0xff, 0xff, 0xd0, 0x06, 0xe7, 0x07, 0x00, 0x00,
-    0xce, 0x06, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf,
-    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x48, 0x02,
-    0xd0, 0x09, 0xc6, 0x06, 0x27, 0x02, 0xc6, 0x06,
-    0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02,
-    0xc8, 0x37, 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00,
-    0x00, 0x60, 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00,
-    0x23, 0xc9, 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8,
-    0xc0, 0x17, 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff,
-    0x30, 0x00, 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00,
-    0x04, 0x00, 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00,
-    0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, 0xa0, 0x01,
-    0x0a, 0x00, 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00,
-    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf,
-    0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf,
-    0x08, 0x03, 0x9f, 0xaf, 0x7a, 0x02, 0x97, 0xcf,
-    0x9f, 0xaf, 0x7a, 0x02, 0xc9, 0x37, 0x04, 0x00,
-    0xc1, 0xdf, 0xc8, 0x09, 0xa2, 0x06, 0x50, 0x02,
-    0x67, 0x02, 0xa2, 0x06, 0xd1, 0x07, 0x00, 0x00,
-    0x27, 0xd8, 0xaa, 0x06, 0xc0, 0xdf, 0x9f, 0xaf,
-    0xc4, 0x01, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
-    0xd2, 0x06, 0x97, 0xc1, 0xe7, 0x57, 0x01, 0x00,
-    0xa8, 0x06, 0x97, 0xc0, 0xc8, 0x09, 0xa0, 0x06,
-    0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, 0xc0, 0x17,
-    0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, 0x27, 0x0c,
-    0x0c, 0x00, 0x36, 0x01, 0xe7, 0x07, 0x50, 0xc3,
-    0x12, 0xc0, 0xe7, 0x07, 0xcc, 0x0b, 0x02, 0x00,
-    0xe7, 0x07, 0x01, 0x00, 0xa8, 0x06, 0xe7, 0x07,
-    0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, 0xc8, 0x09,
-    0xa4, 0x06, 0x08, 0x62, 0x02, 0xc0, 0x10, 0x64,
-    0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, 0x9e, 0x06,
-    0xe7, 0x07, 0x72, 0x04, 0x24, 0x00, 0x97, 0xcf,
-    0x27, 0x04, 0xa4, 0x06, 0xc8, 0x17, 0x0e, 0x00,
-    0x27, 0x02, 0x9e, 0x06, 0xe7, 0x07, 0x80, 0x04,
-    0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0,
-    0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, 0x90, 0x06,
-    0x13, 0xc1, 0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x57,
-    0x00, 0x00, 0x9e, 0x06, 0x13, 0xc0, 0xe7, 0x09,
-    0x9e, 0x06, 0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05,
-    0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0,
-    0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06, 0x04, 0xcf,
-    0xe7, 0x57, 0x00, 0x00, 0x9e, 0x06, 0x02, 0xc1,
-    0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x05, 0x00, 0xc0,
-    0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf,
-    0x08, 0x92, 0xe7, 0x57, 0x02, 0x00, 0xaa, 0x06,
-    0x02, 0xc3, 0xc8, 0x09, 0xa4, 0x06, 0x27, 0x02,
-    0xa6, 0x06, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05,
-    0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0xa4, 0x06,
-    0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00,
-    0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00,
-    0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00,
-    0x06, 0x00, 0xf0, 0x07, 0x46, 0x01, 0x0a, 0x00,
-    0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00,
-    0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
-    0x96, 0x06, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09,
-    0x96, 0x06, 0x27, 0x04, 0x96, 0x06, 0x27, 0x52,
-    0x98, 0x06, 0x03, 0xc1, 0xe7, 0x07, 0x96, 0x06,
-    0x98, 0x06, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17,
-    0x0e, 0x00, 0x9f, 0xaf, 0xba, 0x03, 0xc8, 0x05,
-    0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x24, 0x03,
-    0x97, 0xcf, 0x9f, 0xaf, 0x08, 0x03, 0x97, 0xcf,
-    0x57, 0x02, 0xc9, 0x07, 0xa4, 0x06, 0xd7, 0x09,
-    0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, 0x1b, 0xc0,
-    0x50, 0x04, 0x11, 0x02, 0xe7, 0x05, 0x00, 0xc0,
-    0xc9, 0x05, 0x97, 0xcf, 0x97, 0x02, 0xca, 0x09,
-    0xd6, 0x06, 0xf2, 0x17, 0x01, 0x00, 0x04, 0x00,
-    0xf2, 0x27, 0x00, 0x00, 0x06, 0x00, 0xca, 0x17,
-    0x2c, 0x00, 0xf8, 0x77, 0x01, 0x00, 0x0e, 0x00,
-    0x06, 0xc0, 0xca, 0xd9, 0xf8, 0x57, 0xff, 0x00,
-    0x0e, 0x00, 0x01, 0xc1, 0xca, 0xd9, 0x22, 0x1c,
-    0x0c, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17,
-    0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xca, 0x05,
-    0x00, 0x0c, 0x0c, 0x00, 0xc0, 0x17, 0x41, 0x00,
-    0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, 0x08, 0x00,
-    0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00,
-    0x06, 0x00, 0xf0, 0x07, 0xda, 0x00, 0x0a, 0x00,
-    0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0c,
-    0x08, 0x00, 0x40, 0xd1, 0x01, 0x00, 0xc0, 0x19,
-    0xce, 0x06, 0xc0, 0x59, 0xc2, 0x06, 0x04, 0xc9,
-    0x49, 0xaf, 0x9f, 0xaf, 0xec, 0x00, 0x4a, 0xaf,
-    0x67, 0x10, 0xce, 0x06, 0xc8, 0x17, 0x04, 0x00,
-    0xc1, 0x07, 0x01, 0x00, 0xd7, 0x09, 0x00, 0xc0,
-    0xc1, 0xdf, 0x50, 0xaf, 0xe7, 0x05, 0x00, 0xc0,
-    0x97, 0xcf, 0xc0, 0x07, 0x01, 0x00, 0xc1, 0x09,
-    0xac, 0x06, 0xc1, 0x77, 0x01, 0x00, 0x97, 0xc1,
-    0xd8, 0x77, 0x01, 0x00, 0x12, 0xc0, 0xc9, 0x07,
-    0x6a, 0x06, 0x9f, 0xaf, 0x08, 0x04, 0x04, 0xc1,
-    0xc1, 0x77, 0x08, 0x00, 0x13, 0xc0, 0x97, 0xcf,
-    0xc1, 0x77, 0x02, 0x00, 0x97, 0xc1, 0xc1, 0x77,
-    0x10, 0x00, 0x0c, 0xc0, 0x9f, 0xaf, 0x2c, 0x04,
-    0x97, 0xcf, 0xc1, 0x77, 0x04, 0x00, 0x06, 0xc0,
-    0xc9, 0x07, 0x70, 0x06, 0x9f, 0xaf, 0x08, 0x04,
-    0x97, 0xc0, 0x00, 0xcf, 0x00, 0x90, 0x97, 0xcf,
-    0x50, 0x54, 0x97, 0xc1, 0x70, 0x5c, 0x02, 0x00,
-    0x02, 0x00, 0x97, 0xc1, 0x70, 0x5c, 0x04, 0x00,
-    0x04, 0x00, 0x97, 0xcf, 0x80, 0x01, 0xc0, 0x00,
-    0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00,
-    0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, 0xb2, 0x06,
-    0xcc, 0x09, 0xb4, 0x06, 0x0b, 0x53, 0x11, 0xc0,
-    0xc9, 0x02, 0xca, 0x07, 0x1c, 0x04, 0x9f, 0xaf,
-    0x08, 0x04, 0x97, 0xc0, 0x0a, 0xc8, 0x82, 0x08,
-    0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, 0x08, 0x04,
-    0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, 0x82, 0x60,
-    0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, 0x89, 0x10,
-    0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, 0x82, 0x08,
-    0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, 0xc0, 0xdf,
-    0x97, 0xcf, 0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06,
-    0xe7, 0x09, 0x98, 0xc0, 0x94, 0x06, 0x0f, 0xcf,
-    0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06, 0xe7, 0x09,
-    0x98, 0xc0, 0x94, 0x06, 0xe7, 0x09, 0x9e, 0x06,
-    0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01,
-    0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09,
-    0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0x90, 0x06,
-    0xc8, 0x37, 0x0e, 0x00, 0xe7, 0x77, 0x2a, 0x00,
-    0x92, 0x06, 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09,
-    0xd6, 0x06, 0xe7, 0x77, 0x20, 0x00, 0x92, 0x06,
-    0x0e, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00,
-    0xf2, 0x27, 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77,
-    0x0a, 0x00, 0x92, 0x06, 0xca, 0x05, 0x1e, 0xc0,
-    0x97, 0x02, 0xca, 0x09, 0xd6, 0x06, 0xf2, 0x17,
-    0x01, 0x00, 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00,
-    0x0e, 0x00, 0xe7, 0x77, 0x02, 0x00, 0x92, 0x06,
-    0x07, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00,
-    0xf2, 0x27, 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf,
-    0xf2, 0x17, 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27,
-    0x00, 0x00, 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf,
-    0x08, 0x03, 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02,
-    0xf1, 0x09, 0x94, 0x06, 0x0c, 0x00, 0xf1, 0xda,
-    0x0c, 0x00, 0xc8, 0x09, 0x98, 0x06, 0x50, 0x02,
-    0x67, 0x02, 0x98, 0x06, 0xd1, 0x07, 0x00, 0x00,
-    0xc9, 0x05, 0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06,
-    0xe7, 0x57, 0x00, 0x00, 0x90, 0x06, 0x02, 0xc0,
-    0x9f, 0xaf, 0x06, 0x02, 0xc8, 0x05, 0xe7, 0x05,
-    0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09,
-    0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, 0x97, 0x02,
-    0xc0, 0x09, 0x92, 0xc0, 0xe7, 0x07, 0x04, 0x00,
-    0x90, 0xc0, 0xca, 0x09, 0xd6, 0x06, 0xe7, 0x07,
-    0x00, 0x00, 0xa8, 0x06, 0xe7, 0x07, 0x6a, 0x04,
-    0x02, 0x00, 0xc0, 0x77, 0x02, 0x00, 0x08, 0xc0,
-    0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27,
-    0x00, 0x00, 0x52, 0x00, 0x9f, 0xcf, 0x24, 0x06,
-    0xc0, 0x77, 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17,
-    0x01, 0x00, 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00,
-    0x5a, 0x00, 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0,
-    0xf2, 0x17, 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27,
-    0x00, 0x00, 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00,
-    0x1d, 0xc1, 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00,
-    0xf2, 0x27, 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77,
-    0x00, 0x02, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00,
-    0x64, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00,
-    0xc0, 0x77, 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17,
-    0x01, 0x00, 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00,
-    0x5e, 0x00, 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0,
-    0x1b, 0xcf, 0x1a, 0xcf, 0xf2, 0x17, 0x01, 0x00,
-    0x00, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00,
-    0xc8, 0x09, 0x34, 0x01, 0xca, 0x17, 0x14, 0x00,
-    0xd8, 0x77, 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9,
-    0xd8, 0x57, 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9,
-    0xe2, 0x19, 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00,
-    0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00,
-    0x9f, 0xaf, 0x40, 0x06, 0x9f, 0xaf, 0xc4, 0x01,
-    0xe7, 0x57, 0x00, 0x00, 0xd2, 0x06, 0x9f, 0xa1,
-    0x0e, 0x0a, 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05,
-    0xe7, 0x05, 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf,
-    0xc8, 0x09, 0xa0, 0x06, 0x08, 0x62, 0x97, 0xc0,
-    0x27, 0x04, 0xa0, 0x06, 0x27, 0x52, 0xa2, 0x06,
-    0x03, 0xc1, 0xe7, 0x07, 0xa0, 0x06, 0xa2, 0x06,
-    0x9f, 0xaf, 0x08, 0x03, 0xe7, 0x57, 0x00, 0x00,
-    0xaa, 0x06, 0x02, 0xc0, 0x27, 0xda, 0xaa, 0x06,
-    0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0xff, 0xff, 0xfb, 0x13, 0xe7, 0x57,
-    0x00, 0x80, 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07,
-    0xee, 0x0b, 0x12, 0x00, 0xe7, 0x07, 0x34, 0x0c,
-    0xb2, 0x00, 0xe7, 0x07, 0xc6, 0x07, 0xf2, 0x02,
-    0xc8, 0x09, 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00,
-    0x0d, 0x00, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07,
-    0x00, 0x00, 0x0e, 0xc0, 0xc8, 0x09, 0xde, 0x00,
-    0xc8, 0x17, 0x09, 0x00, 0xc9, 0x07, 0xda, 0x06,
-    0xc0, 0x07, 0x04, 0x00, 0x68, 0x0a, 0x00, 0xda,
-    0x7d, 0xc1, 0xe7, 0x09, 0xc0, 0x00, 0x7c, 0x06,
-    0xe7, 0x09, 0xbe, 0x00, 0x78, 0x06, 0xe7, 0x09,
-    0x10, 0x00, 0xbc, 0x06, 0xc8, 0x07, 0xd6, 0x07,
-    0x9f, 0xaf, 0xae, 0x07, 0x9f, 0xaf, 0x00, 0x0a,
-    0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e, 0x0f, 0x00,
-    0x41, 0x90, 0x9f, 0xde, 0x06, 0x00, 0x44, 0xaf,
-    0x27, 0x00, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06,
-    0x27, 0x00, 0xb6, 0x06, 0xc0, 0x07, 0x74, 0x00,
-    0x44, 0xaf, 0x27, 0x00, 0xd6, 0x06, 0x08, 0x00,
-    0x00, 0x90, 0xc1, 0x07, 0x3a, 0x00, 0x20, 0x00,
-    0x01, 0xda, 0x7d, 0xc1, 0x9f, 0xaf, 0xba, 0x09,
-    0xc0, 0x07, 0x44, 0x00, 0x48, 0xaf, 0x27, 0x00,
-    0x7a, 0x06, 0x9f, 0xaf, 0x96, 0x0a, 0xe7, 0x07,
-    0x01, 0x00, 0xc0, 0x06, 0xe7, 0x05, 0x0e, 0xc0,
-    0x97, 0xcf, 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00,
-    0x0e, 0xc0, 0xe7, 0x07, 0xff, 0xff, 0xbe, 0x06,
-    0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07, 0x01, 0x00,
-    0x60, 0xaf, 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08,
-    0x09, 0x08, 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1,
-    0x97, 0xcf, 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf,
-    0x51, 0x94, 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf,
-    0xc9, 0x09, 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1,
-    0xc0, 0xdf, 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00,
-    0x24, 0x00, 0x80, 0x04, 0x22, 0x00, 0x4e, 0x05,
-    0xd0, 0x00, 0x0e, 0x0a, 0xaa, 0x00, 0x30, 0x08,
-    0xbe, 0x00, 0x4a, 0x0a, 0x10, 0x00, 0x20, 0x00,
-    0x04, 0x00, 0x6e, 0x04, 0x02, 0x00, 0x6a, 0x04,
-    0x06, 0x00, 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04,
-    0x28, 0xc0, 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04,
-    0x22, 0xc0, 0xff, 0xf4, 0xc0, 0x00, 0x90, 0x09,
-    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56, 0x08,
-    0x60, 0x08, 0xd0, 0x08, 0xda, 0x08, 0x00, 0x09,
-    0x04, 0x09, 0x08, 0x09, 0x32, 0x09, 0x42, 0x09,
-    0x50, 0x09, 0x52, 0x09, 0x5a, 0x09, 0x5a, 0x09,
-    0x27, 0x02, 0xca, 0x06, 0x97, 0xcf, 0xe7, 0x07,
-    0x00, 0x00, 0xca, 0x06, 0x0a, 0x0e, 0x01, 0x00,
-    0xca, 0x57, 0x0e, 0x00, 0x9f, 0xc3, 0x5a, 0x09,
-    0xca, 0x37, 0x00, 0x00, 0x9f, 0xc2, 0x5a, 0x09,
-    0x0a, 0xd2, 0xb2, 0xcf, 0x16, 0x08, 0xc8, 0x09,
-    0xde, 0x00, 0x07, 0x06, 0x9f, 0xcf, 0x6c, 0x09,
-    0x17, 0x02, 0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e,
-    0x0f, 0x00, 0x41, 0x90, 0x9f, 0xde, 0x06, 0x00,
-    0xc8, 0x05, 0x30, 0x50, 0x06, 0x00, 0x9f, 0xc8,
-    0x5a, 0x09, 0x27, 0x0c, 0x02, 0x00, 0xb0, 0x06,
-    0xc0, 0x09, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06,
-    0xe7, 0x07, 0x00, 0x00, 0xae, 0x06, 0x27, 0x00,
-    0x80, 0x06, 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00,
-    0xb6, 0x06, 0x41, 0x90, 0x67, 0x50, 0xb0, 0x06,
-    0x0d, 0xc0, 0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c,
-    0x06, 0x00, 0x82, 0x06, 0xe7, 0x07, 0xbc, 0x08,
-    0x84, 0x06, 0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90,
-    0x51, 0xaf, 0x97, 0xcf, 0x9f, 0xaf, 0x48, 0x0c,
-    0xe7, 0x09, 0xb6, 0x06, 0xb4, 0x06, 0xe7, 0x09,
-    0xb0, 0x06, 0xae, 0x06, 0x59, 0xaf, 0x97, 0xcf,
-    0x27, 0x0c, 0x02, 0x00, 0xac, 0x06, 0x59, 0xaf,
-    0x97, 0xcf, 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda,
-    0x49, 0xd2, 0xc9, 0x19, 0xd6, 0x06, 0xc8, 0x07,
-    0x7e, 0x06, 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02,
-    0xe0, 0x07, 0x04, 0x00, 0xd0, 0x07, 0xcc, 0x08,
-    0x48, 0xdb, 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf,
-    0x59, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf,
-    0xf0, 0x57, 0x06, 0x00, 0x06, 0x00, 0x25, 0xc1,
-    0xe7, 0x07, 0x70, 0x06, 0x80, 0x06, 0x41, 0x90,
-    0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c, 0x06, 0x00,
-    0x82, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06,
-    0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90, 0x51, 0xaf,
-    0x97, 0xcf, 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57,
-    0x06, 0x00, 0x0f, 0xc1, 0xc8, 0x07, 0x70, 0x06,
-    0x15, 0xcf, 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda,
-    0x40, 0xd1, 0x27, 0x00, 0xc2, 0x06, 0x1e, 0xcf,
-    0x1d, 0xcf, 0x27, 0x0c, 0x02, 0x00, 0xcc, 0x06,
-    0x19, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07,
-    0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00,
-    0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00,
-    0x7e, 0x06, 0xe7, 0x01, 0x82, 0x06, 0x27, 0x02,
-    0x80, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06,
-    0xc8, 0x07, 0x7e, 0x06, 0xc1, 0x07, 0x00, 0x80,
-    0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf,
-    0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00,
-    0xc4, 0x06, 0xa7, 0xcf, 0x7c, 0x06, 0x9f, 0xaf,
-    0x00, 0x0a, 0xe7, 0x07, 0x01, 0x00, 0xc4, 0x06,
-    0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf,
-    0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf,
-    0x7c, 0x06, 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf,
-    0x40, 0x00, 0xc0, 0x37, 0x00, 0x01, 0x41, 0x90,
-    0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, 0x50, 0x06,
-    0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, 0xc0, 0x07,
-    0x10, 0x00, 0x27, 0x00, 0x9a, 0x06, 0x41, 0x90,
-    0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, 0x27, 0x00,
-    0x9c, 0x06, 0xc0, 0x09, 0x9a, 0x06, 0x41, 0x90,
-    0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, 0x08, 0x00,
-    0x44, 0xaf, 0x27, 0x00, 0xc8, 0x06, 0x97, 0xcf,
-    0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, 0xe7, 0x67,
-    0xff, 0xfb, 0x24, 0xc0, 0x97, 0xcf, 0xe7, 0x87,
-    0x01, 0x00, 0xd2, 0x06, 0xe7, 0x57, 0x00, 0x00,
-    0xa8, 0x06, 0x97, 0xc1, 0x9f, 0xaf, 0x00, 0x0a,
-    0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, 0xe7, 0x07,
-    0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, 0xfe, 0xff,
-    0x3e, 0xc0, 0xe7, 0x07, 0x26, 0x00, 0x0a, 0xc0,
-    0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, 0xe7, 0x07,
-    0xff, 0xff, 0xbe, 0x06, 0x9f, 0xaf, 0x10, 0x0b,
-    0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, 0x78, 0x06,
-    0xc0, 0x05, 0x27, 0x00, 0x76, 0x06, 0xe7, 0x87,
-    0x01, 0x00, 0xd2, 0x06, 0x9f, 0xaf, 0x00, 0x0a,
-    0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, 0x9f, 0xaf,
-    0x10, 0x0b, 0x00, 0x90, 0x27, 0x00, 0xa6, 0x06,
-    0x27, 0x00, 0xaa, 0x06, 0xe7, 0x09, 0xb2, 0x06,
-    0xb4, 0x06, 0x27, 0x00, 0xae, 0x06, 0x27, 0x00,
-    0xac, 0x06, 0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07,
-    0x00, 0x00, 0x27, 0x00, 0xb2, 0x02, 0x27, 0x00,
-    0xb4, 0x02, 0x27, 0x00, 0x8e, 0x06, 0xc0, 0x07,
-    0x06, 0x00, 0xc8, 0x09, 0xde, 0x00, 0xc8, 0x17,
-    0x03, 0x00, 0xc9, 0x07, 0x70, 0x06, 0x29, 0x0a,
-    0x00, 0xda, 0x7d, 0xc1, 0x97, 0xcf, 0xd7, 0x09,
-    0x00, 0xc0, 0xc1, 0xdf, 0x00, 0x90, 0x27, 0x00,
-    0x96, 0x06, 0xe7, 0x07, 0x96, 0x06, 0x98, 0x06,
-    0x27, 0x00, 0xa0, 0x06, 0xe7, 0x07, 0xa0, 0x06,
-    0xa2, 0x06, 0x27, 0x00, 0xa6, 0x06, 0x27, 0x00,
-    0x90, 0x06, 0x27, 0x00, 0x9e, 0x06, 0xc8, 0x09,
-    0x9c, 0x06, 0xc1, 0x09, 0x9a, 0x06, 0xc9, 0x07,
-    0xa4, 0x06, 0x11, 0x02, 0x09, 0x02, 0xc8, 0x17,
-    0x40, 0x06, 0x01, 0xda, 0x7a, 0xc1, 0x51, 0x94,
-    0xc8, 0x09, 0xc8, 0x06, 0xc9, 0x07, 0xc6, 0x06,
-    0xc1, 0x09, 0x9a, 0x06, 0x11, 0x02, 0x09, 0x02,
-    0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1,
-    0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf,
-    0xe7, 0x57, 0x00, 0x00, 0x76, 0x06, 0x97, 0xc0,
-    0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0xbe, 0x06,
-    0xba, 0x06, 0xe7, 0x57, 0xff, 0xff, 0xba, 0x06,
-    0x04, 0xc1, 0xe7, 0x07, 0x10, 0x0b, 0xb8, 0x06,
-    0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0xba, 0x06,
-    0xe7, 0x67, 0xff, 0x07, 0xba, 0x06, 0xe7, 0x07,
-    0x46, 0x0b, 0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57,
-    0x00, 0x00, 0xc0, 0x06, 0x23, 0xc0, 0xe7, 0x07,
-    0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x80,
-    0x80, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0,
-    0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07,
-    0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07,
-    0x00, 0x00, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0,
-    0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07,
-    0x00, 0x80, 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00,
-    0xe7, 0x07, 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07,
-    0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00,
-    0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0,
-    0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07,
-    0x00, 0x00, 0xc0, 0x06, 0xe7, 0x07, 0x00, 0x00,
-    0xb8, 0x06, 0xe7, 0x07, 0x00, 0x00, 0xd2, 0x06,
-    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf,
-    0x34, 0x02, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf,
-    0xc4, 0x01, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0,
-    0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xe7, 0x57,
-    0x00, 0x00, 0xa8, 0x06, 0x06, 0xc0, 0xc0, 0x09,
-    0x92, 0xc0, 0xc0, 0x77, 0x09, 0x02, 0x9f, 0xc1,
-    0x5c, 0x05, 0x9f, 0xcf, 0x32, 0x06, 0xd7, 0x09,
-    0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x0e, 0xc0,
-    0x9f, 0xaf, 0x02, 0x0c, 0xe7, 0x05, 0x0e, 0xc0,
-    0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x02,
-    0xc8, 0x09, 0xb0, 0xc0, 0xe7, 0x67, 0xfe, 0x7f,
-    0xb0, 0xc0, 0xc8, 0x77, 0x00, 0x20, 0x9f, 0xc1,
-    0x64, 0xeb, 0xe7, 0x57, 0x00, 0x00, 0xc8, 0x02,
-    0x9f, 0xc1, 0x80, 0xeb, 0xc8, 0x99, 0xca, 0x02,
-    0xc8, 0x67, 0x04, 0x00, 0x9f, 0xc1, 0x96, 0xeb,
-    0x9f, 0xcf, 0x4c, 0xeb, 0xe7, 0x07, 0x00, 0x00,
-    0xa6, 0xc0, 0xe7, 0x09, 0xb0, 0xc0, 0xc8, 0x02,
-    0xe7, 0x07, 0x03, 0x00, 0xb0, 0xc0, 0x97, 0xcf,
-    0xc0, 0x09, 0xb0, 0x06, 0xc0, 0x37, 0x01, 0x00,
-    0x97, 0xc9, 0xc9, 0x09, 0xb2, 0x06, 0x02, 0x00,
-    0x41, 0x90, 0x48, 0x02, 0xc9, 0x17, 0x06, 0x00,
-    0x9f, 0xaf, 0x08, 0x04, 0x9f, 0xa2, 0x72, 0x0c,
-    0x02, 0xda, 0x77, 0xc1, 0x41, 0x60, 0x71, 0xc1,
-    0x97, 0xcf, 0x17, 0x02, 0x57, 0x02, 0x43, 0x04,
-    0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, 0x21, 0x04,
-    0xe0, 0x00, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00,
-    0xc1, 0x07, 0x01, 0x00, 0xc9, 0x05, 0xc8, 0x05,
-    0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, 0x8e, 0x06,
-    0xc8, 0x07, 0x86, 0x06, 0xe7, 0x07, 0x00, 0x00,
-    0x86, 0x06, 0xe7, 0x07, 0x10, 0x08, 0x88, 0x06,
-    0xe7, 0x07, 0x04, 0x00, 0x8a, 0x06, 0xe7, 0x07,
-    0xbc, 0x0c, 0x8c, 0x06, 0xc1, 0x07, 0x03, 0x80,
-    0x50, 0xaf, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00,
-    0x8e, 0x06, 0x97, 0xcf,
-    0x00, 0x00
-};
-
-/****************************************************************
- *     kaweth_new_code_fix
- ****************************************************************/
-static __u8 kaweth_new_code_fix[] = 
-{
-    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
-    0x02, 0x00, 0x08, 0x00, 0x28, 0x00, 0x2c, 0x00,
-    0x34, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x48, 0x00,
-    0x54, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x64, 0x00,
-    0x68, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x72, 0x00,
-    0x76, 0x00, 0x7c, 0x00, 0x80, 0x00, 0x86, 0x00,
-    0x8a, 0x00, 0x90, 0x00, 0x94, 0x00, 0x98, 0x00,
-    0x9e, 0x00, 0xa6, 0x00, 0xaa, 0x00, 0xb0, 0x00,
-    0xb4, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc6, 0x00,
-    0xca, 0x00, 0xd0, 0x00, 0xd4, 0x00, 0xd8, 0x00,
-    0xe0, 0x00, 0xde, 0x00, 0xe8, 0x00, 0xf0, 0x00,
-    0xfc, 0x00, 0x04, 0x01, 0x0a, 0x01, 0x18, 0x01,
-    0x22, 0x01, 0x28, 0x01, 0x3a, 0x01, 0x3e, 0x01,
-    0x7e, 0x01, 0x98, 0x01, 0x9c, 0x01, 0xa2, 0x01,
-    0xac, 0x01, 0xb2, 0x01, 0xba, 0x01, 0xc0, 0x01,
-    0xc8, 0x01, 0xd0, 0x01, 0xd6, 0x01, 0xf4, 0x01,
-    0xfc, 0x01, 0x08, 0x02, 0x16, 0x02, 0x1a, 0x02,
-    0x22, 0x02, 0x2a, 0x02, 0x2e, 0x02, 0x3e, 0x02,
-    0x44, 0x02, 0x4a, 0x02, 0x50, 0x02, 0x64, 0x02,
-    0x62, 0x02, 0x6c, 0x02, 0x72, 0x02, 0x86, 0x02,
-    0x8c, 0x02, 0x90, 0x02, 0x9e, 0x02, 0xbc, 0x02,
-    0xd0, 0x02, 0xd8, 0x02, 0xdc, 0x02, 0xe0, 0x02,
-    0xe8, 0x02, 0xe6, 0x02, 0xf4, 0x02, 0xfe, 0x02,
-    0x04, 0x03, 0x0c, 0x03, 0x28, 0x03, 0x7c, 0x03,
-    0x90, 0x03, 0x94, 0x03, 0x9c, 0x03, 0xa2, 0x03,
-    0xc0, 0x03, 0xd0, 0x03, 0xd4, 0x03, 0xee, 0x03,
-    0xfa, 0x03, 0xfe, 0x03, 0x2e, 0x04, 0x32, 0x04,
-    0x3c, 0x04, 0x40, 0x04, 0x4e, 0x04, 0x76, 0x04,
-    0x7c, 0x04, 0x84, 0x04, 0x8a, 0x04, 0x8e, 0x04,
-    0xa6, 0x04, 0xb0, 0x04, 0xb8, 0x04, 0xbe, 0x04,
-    0xd2, 0x04, 0xdc, 0x04, 0xee, 0x04, 0x10, 0x05,
-    0x1a, 0x05, 0x24, 0x05, 0x2a, 0x05, 0x36, 0x05,
-    0x34, 0x05, 0x3c, 0x05, 0x42, 0x05, 0x64, 0x05,
-    0x6a, 0x05, 0x6e, 0x05, 0x86, 0x05, 0x22, 0x06,
-    0x26, 0x06, 0x2c, 0x06, 0x30, 0x06, 0x42, 0x06,
-    0x4a, 0x06, 0x4e, 0x06, 0x56, 0x06, 0x54, 0x06,
-    0x5a, 0x06, 0x60, 0x06, 0x66, 0x06, 0xe8, 0x06,
-    0xee, 0x06, 0xf4, 0x06, 0x16, 0x07, 0x26, 0x07,
-    0x2c, 0x07, 0x32, 0x07, 0x36, 0x07, 0x3a, 0x07,
-    0x3e, 0x07, 0x52, 0x07, 0x56, 0x07, 0x5a, 0x07,
-    0x64, 0x07, 0x76, 0x07, 0x7a, 0x07, 0x80, 0x07,
-    0x84, 0x07, 0x8a, 0x07, 0x9e, 0x07, 0xa2, 0x07,
-    0xda, 0x07, 0xde, 0x07, 0xe2, 0x07, 0xe6, 0x07,
-    0xea, 0x07, 0xee, 0x07, 0xf2, 0x07, 0xf6, 0x07,
-    0x0e, 0x08, 0x16, 0x08, 0x18, 0x08, 0x1a, 0x08,
-    0x1c, 0x08, 0x1e, 0x08, 0x20, 0x08, 0x22, 0x08,
-    0x24, 0x08, 0x26, 0x08, 0x28, 0x08, 0x2a, 0x08,
-    0x2c, 0x08, 0x2e, 0x08, 0x32, 0x08, 0x3a, 0x08,
-    0x46, 0x08, 0x4e, 0x08, 0x54, 0x08, 0x5e, 0x08,
-    0x78, 0x08, 0x7e, 0x08, 0x82, 0x08, 0x86, 0x08,
-    0x8c, 0x08, 0x90, 0x08, 0x98, 0x08, 0x9e, 0x08,
-    0xa4, 0x08, 0xaa, 0x08, 0xb0, 0x08, 0xae, 0x08,
-    0xb4, 0x08, 0xbe, 0x08, 0xc4, 0x08, 0xc2, 0x08,
-    0xca, 0x08, 0xc8, 0x08, 0xd4, 0x08, 0xe4, 0x08,
-    0xe8, 0x08, 0xf6, 0x08, 0x14, 0x09, 0x12, 0x09,
-    0x1a, 0x09, 0x20, 0x09, 0x26, 0x09, 0x24, 0x09,
-    0x2a, 0x09, 0x3e, 0x09, 0x4c, 0x09, 0x56, 0x09,
-    0x70, 0x09, 0x74, 0x09, 0x78, 0x09, 0x7e, 0x09,
-    0x7c, 0x09, 0x82, 0x09, 0x98, 0x09, 0x9c, 0x09,
-    0xa0, 0x09, 0xa6, 0x09, 0xb8, 0x09, 0xdc, 0x09,
-    0xe8, 0x09, 0xec, 0x09, 0xfc, 0x09, 0x12, 0x0a,
-    0x18, 0x0a, 0x1e, 0x0a, 0x42, 0x0a, 0x46, 0x0a,
-    0x4e, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a,
-    0x68, 0x0a, 0x6e, 0x0a, 0x72, 0x0a, 0x78, 0x0a,
-    0x76, 0x0a, 0x7c, 0x0a, 0x80, 0x0a, 0x84, 0x0a,
-    0x94, 0x0a, 0xa4, 0x0a, 0xb8, 0x0a, 0xbe, 0x0a,
-    0xbc, 0x0a, 0xc2, 0x0a, 0xc8, 0x0a, 0xc6, 0x0a,
-    0xcc, 0x0a, 0xd0, 0x0a, 0xd4, 0x0a, 0xd8, 0x0a,
-    0xdc, 0x0a, 0xe0, 0x0a, 0xf2, 0x0a, 0xf6, 0x0a,
-    0xfa, 0x0a, 0x14, 0x0b, 0x1a, 0x0b, 0x20, 0x0b,
-    0x1e, 0x0b, 0x26, 0x0b, 0x2e, 0x0b, 0x2c, 0x0b,
-    0x36, 0x0b, 0x3c, 0x0b, 0x42, 0x0b, 0x40, 0x0b,
-    0x4a, 0x0b, 0xaa, 0x0b, 0xb0, 0x0b, 0xb6, 0x0b,
-    0xc0, 0x0b, 0xc8, 0x0b, 0xda, 0x0b, 0xe8, 0x0b,
-    0xec, 0x0b, 0xfa, 0x0b, 0x4a, 0x0c, 0x54, 0x0c,
-    0x62, 0x0c, 0x66, 0x0c, 0x96, 0x0c, 0x9a, 0x0c,
-    0xa0, 0x0c, 0xa6, 0x0c, 0xa4, 0x0c, 0xac, 0x0c,
-    0xb2, 0x0c, 0xb0, 0x0c, 0xc0, 0x0c,
-    0x00, 0x00
-};
-
-
-const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
-const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
-const int len_kaweth_new_code = sizeof(kaweth_new_code);
-const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
diff -Nru a/drivers/usb/konicawc.c b/drivers/usb/konicawc.c
--- a/drivers/usb/konicawc.c	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,737 +0,0 @@
-/*
- * $Id: konicawc.c,v 1.12 2002/02/07 23:18:53 spse Exp $
- *
- * konicawc.c - konica webcam driver
- *
- * Author: Simon Evans <spse@secret.org.uk>
- *
- * Copyright (C) 2002 Simon Evans
- *
- * Licence: GPL
- * 
- * Driver for USB webcams based on Konica chipset. This
- * chipset is used in Intel YC76 camera.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#define DEBUG
-
-#include "usbvideo.h"
-
-#define MAX_BRIGHTNESS	108
-#define MAX_CONTRAST	108
-#define MAX_SATURATION	108
-#define MAX_SHARPNESS	108
-#define MAX_WHITEBAL	363
-
-#define MAX_CAMERAS 1
-
-enum ctrl_req {
-	SetWhitebal	= 0x01,
-	SetBrightness	= 0x02,
-        SetSharpness	= 0x03,
-	SetContrast	= 0x04,
-	SetSaturation	= 0x05,
-};
-
-
-enum frame_sizes {
-	SIZE_160X130	= 0,
-	SIZE_176X144	= 1,
-	SIZE_320X240	= 2,
-};
-
-
-static usbvideo_t *cams;
-
-/* Some default values for inital camera settings,
-   can be set by modprobe */
-
-static int debug;
-static enum frame_sizes size;	
-static int brightness =	MAX_BRIGHTNESS/2;
-static int contrast =	MAX_CONTRAST/2;
-static int saturation =	MAX_SATURATION/2;
-static int sharpness =	MAX_SHARPNESS/2;
-static int whitebal =	3*(MAX_WHITEBAL/4);
-
-
-struct konicawc {
-	u8 brightness;		/* camera uses 0 - 9, x11 for real value */
-	u8 contrast;		/* as above */
-	u8 saturation;		/* as above */
-	u8 sharpness;		/* as above */
-	u8 white_bal;		/* 0 - 33, x11 for real value */
-	u8 fps;			/* Stored as fps * 3 */
-	u8 size;		/* Frame Size */
-	int height;
-	int width;
-	struct urb *sts_urb[USBVIDEO_NUMFRAMES];
-	u8 sts_buf[USBVIDEO_NUMFRAMES][FRAMES_PER_DESC];
-	struct urb *last_data_urb;
-	int lastframe;
-};
-
-
-#define konicawc_set_misc(uvd, req, value, index)		konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)
-#define konicawc_get_misc(uvd, req, value, index, buf, sz)	konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)
-#define konicawc_set_value(uvd, value, index)			konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)
-
-
-static int konicawc_ctrl_msg(uvd_t *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
-{
-        int retval = usb_control_msg(uvd->dev,
-		dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
-		    request, 0x40 | dir, value, index, buf, len, HZ);
-        return retval < 0 ? retval : 0;
-}
-
-
-static int konicawc_setup_on_open(uvd_t *uvd)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	konicawc_set_misc(uvd, 0x2, 0, 0x0b);
-	dbg("setting brightness to %d (%d)", cam->brightness,
-	    cam->brightness*11);
-	konicawc_set_value(uvd, cam->brightness, SetBrightness);
-	dbg("setting white balance to %d (%d)", cam->white_bal,
-	    cam->white_bal*11);
-	konicawc_set_value(uvd, cam->white_bal, SetWhitebal);
-	dbg("setting contrast to %d (%d)", cam->contrast,
-	    cam->contrast*11);
-	konicawc_set_value(uvd, cam->brightness, SetBrightness);
-	dbg("setting saturation to %d (%d)", cam->saturation,
-	    cam->saturation*11);
-	konicawc_set_value(uvd, cam->saturation, SetSaturation);
-	dbg("setting sharpness to %d (%d)", cam->sharpness,
-	    cam->sharpness*11);
-	konicawc_set_value(uvd, cam->sharpness, SetSharpness);
-	dbg("setting size %d", cam->size);
-	switch(cam->size) {
-	case 0:
-		konicawc_set_misc(uvd, 0x2, 0xa, 0x08);
-		break;
-
-	case 1:
-		konicawc_set_misc(uvd, 0x2, 4, 0x08);
-		break;
-
-	case 2:
-		konicawc_set_misc(uvd, 0x2, 5, 0x08);
-		break;
-	}
-	konicawc_set_misc(uvd, 0x2, 1, 0x0b);
-	cam->lastframe = -1;
-	return 0;
-}
-
-
-static int konicawc_compress_iso(uvd_t *uvd, struct urb *dataurb, struct urb *stsurb)
-{
-	char *cdata;
-	int i, totlen = 0;
-	unsigned char *status = stsurb->transfer_buffer;
-	int keep = 0, discard = 0, bad = 0;
-	static int buttonsts = 0;
-	
-	for (i = 0; i < dataurb->number_of_packets; i++) {
-		int button = buttonsts;
-		unsigned char sts;
-		int n = dataurb->iso_frame_desc[i].actual_length;
-		int st = dataurb->iso_frame_desc[i].status;
-		cdata = dataurb->transfer_buffer + 
-			dataurb->iso_frame_desc[i].offset;
-
-		/* Detect and ignore errored packets */
-		if (st < 0) {
-			if (debug >= 1)
-				err("Data error: packet=%d. len=%d. status=%d.",
-				    i, n, st);
-			uvd->stats.iso_err_count++;
-			continue;
-		}
-
-		/* Detect and ignore empty packets */
-		if (n <= 0) {
-			uvd->stats.iso_skip_count++;
-			continue;
-		}
-
-		/* See what the status data said about the packet */
-		sts = *(status+stsurb->iso_frame_desc[i].offset);
-
-		/* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
-		 * otherwise:
-		 * bit 0 0:drop packet (padding data)
-		 *	 1 keep packet
-		 *
-		 * bit 4 0 button not clicked
-		 *       1 button clicked
-		 * button is used to `take a picture' (in software)
-		 */
-
-		if(sts < 0x80) {
-			button = sts & 0x40;
-			sts &= ~0x40;
-		}
-		
-		/* work out the button status, but dont do
-		   anything with it for now */
-		   
-		if(button != buttonsts) {
-			dbg("button: %sclicked", button ? "" : "un");
-			buttonsts = button;
-		}
-
-		if(sts == 0x01) { /* drop frame */
-			discard++;
-			continue;
-		}
-		
-		if((sts > 0x01) && (sts < 0x80)) {
-			info("unknown status %2.2x", sts);
-			bad++;
-			continue;
-		}
-
-		keep++;
-		if(*(status+i) & 0x80) { /* frame start */
-			unsigned char marker[] = { 0, 0xff, 0, 0x00 };
-			if(debug > 1)
-				dbg("Adding Marker packet = %d, frame = %2.2x",
-				    i, *(status+i));
-			marker[3] = *(status+i) - 0x80;
-			RingQueue_Enqueue(&uvd->dp, marker, 4);			
-			totlen += 4;
-		}
-		totlen += n;	/* Little local accounting */
-		if(debug > 5)
-			dbg("Adding packet %d, bytes = %d", i, n);
-		RingQueue_Enqueue(&uvd->dp, cdata, n);
-
-	}
-	if(debug > 8) {
-		dbg("finished: keep = %d discard = %d bad = %d added %d bytes",
-		    keep, discard, bad, totlen);
-	}
-	return totlen;
-}
-
-
-static void konicawc_isoc_irq(struct urb *urb)
-{
-	int i, len = 0;
-	uvd_t *uvd = urb->context;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
- 
-	/* We don't want to do anything if we are about to be removed! */
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return;
-
-	if (urb->actual_length > 32) {
-		cam->last_data_urb = urb;
-		return;
-
-	}
-
-	if (!uvd->streaming) {
-		if (debug >= 1)
-			info("Not streaming, but interrupt!");
-		return;
-	}
-	
-	uvd->stats.urb_count++;
-	if (urb->actual_length <= 0)
-		goto urb_done_with;
-
-	/* Copy the data received into ring queue */
-	if(cam->last_data_urb) {
-		len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
-		for (i = 0; i < FRAMES_PER_DESC; i++) {
-			cam->last_data_urb->iso_frame_desc[i].status = 0;
-			cam->last_data_urb->iso_frame_desc[i].actual_length = 0;
-		}
-		cam->last_data_urb = NULL;
-	}
-	uvd->stats.urb_length = len;
-	if (len <= 0) {
-		goto urb_done_with;
-	}
-
-	/* Here we got some data */
-	uvd->stats.data_count += len;
-	RingQueue_WakeUpInterruptible(&uvd->dp);
-
-urb_done_with:
-
-	for (i = 0; i < FRAMES_PER_DESC; i++) {
-		urb->iso_frame_desc[i].status = 0;
-		urb->iso_frame_desc[i].actual_length = 0;
-	}
-	return;
-}
-
-
-static int konicawc_start_data(uvd_t *uvd)
-{
-	struct usb_device *dev = uvd->dev;
-	int i, errFlag;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd)) {
-		err("Camera is not operational");
-		return -EFAULT;
-	}
-	uvd->curframe = -1;
-
-	/* Alternate interface 1 is is the biggest frame size */
-	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
-	if (i < 0) {
-		err("usb_set_interface error");
-		uvd->last_error = i;
-		return -EBUSY;
-	}
-
-	/* We double buffer the Iso lists */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		int j, k;
-		struct urb *urb = uvd->sbuf[i].urb;
-		urb->dev = dev;
-		urb->context = uvd;
-		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->transfer_buffer = uvd->sbuf[i].data;
-		urb->complete = konicawc_isoc_irq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
-		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
-			urb->iso_frame_desc[j].offset = k;
-			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
-		}
-
-		urb = cam->sts_urb[i];
-		urb->dev = dev;
-		urb->context = uvd;
-		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->transfer_buffer = cam->sts_buf[i];
-		urb->complete = konicawc_isoc_irq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = FRAMES_PER_DESC;
-		for (j=0; j < FRAMES_PER_DESC; j++) {
-			urb->iso_frame_desc[j].offset = j;
-			urb->iso_frame_desc[j].length = 1;
-		}
-	}
-
-
-	/* Link URBs into a ring so that they invoke each other infinitely */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		if ((i+1) < USBVIDEO_NUMSBUF) {
-			cam->sts_urb[i]->next = uvd->sbuf[i].urb;
-			uvd->sbuf[i].urb->next = cam->sts_urb[i+1];
-		} else {
-			cam->sts_urb[i]->next = uvd->sbuf[i].urb;
-			uvd->sbuf[i].urb->next = cam->sts_urb[0];
-		}
-	}
-
-	/* Submit all URBs */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
-		if (errFlag)
-			err ("usb_submit_isoc(%d) ret %d", i, errFlag);
-
-		errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL);
-		if (errFlag)
-			err("usb_submit_isoc(%d) ret %d", i, errFlag);
-	}
-
-	uvd->streaming = 1;
-	if (debug > 1)
-		dbg("streaming=1 video_endp=$%02x", uvd->video_endp);
-	return 0;
-}
-
-
-static void konicawc_stop_data(uvd_t *uvd)
-{
-	int i, j;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-
-	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
-		return;
-
-	/* Unschedule all of the iso td's */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		j = usb_unlink_urb(uvd->sbuf[i].urb);
-		if (j < 0)
-			err("usb_unlink_urb() error %d.", j);
-
-		j = usb_unlink_urb(cam->sts_urb[i]);
-		if (j < 0)
-			err("usb_unlink_urb() error %d.", j);
-	}
-
-	uvd->streaming = 0;
-
-	if (!uvd->remove_pending) {
-		/* Set packet size to 0 */
-		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
-		if (j < 0) {
-			err("usb_set_interface() error %d.", j);
-			uvd->last_error = j;
-		}
-	}
-}
-
-
-static void konicawc_process_isoc(uvd_t *uvd, usbvideo_frame_t *frame)
-{	
-	int n;
-	int maxline, yplanesz;
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	assert(uvd != NULL);
-	assert(frame != NULL);
-
-	maxline = (cam->height * cam->width * 3) / (2 * 384);
-	yplanesz = cam->height * cam->width;
-	if(debug > 5)
-		dbg("maxline = %d yplanesz = %d", maxline, yplanesz);
-	
-	if(debug > 3)
-		dbg("Frame state = %d", frame->scanstate);
-
-	if(frame->scanstate == ScanState_Scanning) {
-		int drop = 0;
-		int curframe;
-		int fdrops = 0;
-		if(debug > 3)
-			dbg("Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp));
-		while(RingQueue_GetLength(&uvd->dp) >= 4) {
-			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
-			    (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) {
-				curframe = RING_QUEUE_PEEK(&uvd->dp, 3);
-				if(cam->lastframe != -1) {
-					if(curframe < cam->lastframe) {
-						fdrops = (curframe + 0x80) - cam->lastframe;
-					} else {
-						fdrops = curframe - cam->lastframe;
-					}
-					fdrops--;
-					if(fdrops)
-						info("Dropped %d frames (%d -> %d)", fdrops,
-						     cam->lastframe, curframe);
-				}
-				cam->lastframe = curframe;
-				frame->curline = 0;
-				frame->scanstate = ScanState_Lines;
-				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
-				break;
-			}
-			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
-			drop++;
-		}
-	}
-
-	if(frame->scanstate == ScanState_Scanning)
-		return;
-		
-	/* Try to move data from queue into frame buffer 
-	 * We get data in blocks of 384 bytes made up of:
-	 * 256 Y, 64 U, 64 V.
-	 * This needs to be written out as a Y plane, a U plane and a V plane.
-	 */
-		
-	while ( frame->curline < maxline && (n = RingQueue_GetLength(&uvd->dp)) >= 384) {
-		/* Y */
-		RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
-		/* U */
-		RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64);
-		/* V */
-		RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64);
-		frame->seqRead_Length += 384;
-		frame->curline++;
-	}
-	/* See if we filled the frame */
-	if (frame->curline == maxline) {
-		if(debug > 5)
-			dbg("got whole frame");
-
-		frame->frameState = FrameState_Done_Hold;
-		frame->curline = 0;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-	}
-}
-
-
-static int konicawc_calculate_fps(uvd_t *uvd)
-{
-	struct konicawc *t = uvd->user_data;
-	dbg("");
-
-	return (t->fps)/3;
-}
-
-
-static void konicawc_configure_video(uvd_t *uvd)
-{
-	struct konicawc *cam = (struct konicawc *)uvd->user_data;
-	u8 buf[2];
-
-	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
-	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
-
-	RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS);
-	RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST);
-	RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION);
-	RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS);
-	RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL);
-
-	cam->brightness = brightness / 11;
-	cam->contrast = contrast / 11;
-	cam->saturation = saturation / 11;
-	cam->sharpness = sharpness / 11;
-	cam->white_bal = whitebal / 11;
-
-	uvd->vpic.colour = 108;
-	uvd->vpic.hue = 108;
-	uvd->vpic.brightness = brightness;
-	uvd->vpic.contrast = contrast;
-	uvd->vpic.whiteness = whitebal;
-	uvd->vpic.depth = 6;
-	uvd->vpic.palette = VIDEO_PALETTE_YUV420P;
-
-	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
-	strcpy(uvd->vcap.name, "Konica Webcam");
-	uvd->vcap.type = VID_TYPE_CAPTURE;
-	uvd->vcap.channels = 1;
-	uvd->vcap.audios = 0;
-	uvd->vcap.maxwidth = cam->width;
-	uvd->vcap.maxheight = cam->height;
-	uvd->vcap.minwidth = cam->width;
-	uvd->vcap.minheight = cam->height;
-
-	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
-	uvd->vchan.flags = 0 ;
-	uvd->vchan.tuners = 0;
-	uvd->vchan.channel = 0;
-	uvd->vchan.type = VIDEO_TYPE_CAMERA;
-	strcpy(uvd->vchan.name, "Camera");
-
-	/* Talk to device */
-	dbg("device init");
-	if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
-		dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]);
-	if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
-		dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]);
-	if(konicawc_set_misc(uvd, 0x2, 0, 0xd))
-		dbg("2,0,d failed");
-	dbg("setting initial values");
-
-}
-
-
-static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid)
-{
-	uvd_t *uvd = NULL;
-	int i, nas;
-	int actInterface=-1, inactInterface=-1, maxPS=0;
-	unsigned char video_ep = 0;
-	
-	if (debug >= 1)
-		dbg("konicawc_probe(%p,%u.)", dev, ifnum);
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-	info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice);
-
-	/* Validate found interface: must have one ISO endpoint */
-	nas = dev->actconfig->interface[ifnum].num_altsetting;
-	if (debug > 0)
-		info("Number of alternate settings=%d.", nas);
-	if (nas < 8) {
-		err("Too few alternate settings for this camera!");
-		return NULL;
-	}
-	/* Validate all alternate settings */
-	for (i=0; i < nas; i++) {
-		const struct usb_interface_descriptor *interface;
-		const struct usb_endpoint_descriptor *endpoint;
-
-		interface = &dev->actconfig->interface[ifnum].altsetting[i];
-		if (interface->bNumEndpoints != 2) {
-			err("Interface %d. has %u. endpoints!",
-			    ifnum, (unsigned)(interface->bNumEndpoints));
-			return NULL;
-		}
-		endpoint = &interface->endpoint[1];
-		dbg("found endpoint: addr: 0x%2.2x maxps = 0x%4.4x",
-		    endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
-		if (video_ep == 0)
-			video_ep = endpoint->bEndpointAddress;
-		else if (video_ep != endpoint->bEndpointAddress) {
-			err("Alternate settings have different endpoint addresses!");
-			return NULL;
-		}
-		if ((endpoint->bmAttributes & 0x03) != 0x01) {
-			err("Interface %d. has non-ISO endpoint!", ifnum);
-			return NULL;
-		}
-		if ((endpoint->bEndpointAddress & 0x80) == 0) {
-			err("Interface %d. has ISO OUT endpoint!", ifnum);
-			return NULL;
-		}
-		if (endpoint->wMaxPacketSize == 0) {
-			if (inactInterface < 0)
-				inactInterface = i;
-			else {
-				err("More than one inactive alt. setting!");
-				return NULL;
-			}
-		} else {
-			if (actInterface < 0) {
-				actInterface = i;
-				maxPS = endpoint->wMaxPacketSize;
-				if (debug > 0)
-					info("Active setting=%d. maxPS=%d.",
-					     i, maxPS);
-			} else {
-				/* Got another active alt. setting */
-				if (maxPS < endpoint->wMaxPacketSize) {
-					/* This one is better! */
-					actInterface = i;
-					maxPS = endpoint->wMaxPacketSize;
-					if (debug > 0) {
-						info("Even better active setting=%d. maxPS=%d.",
-						     i, maxPS);
-					}
-				}
-			}
-		}
-	}
-
-	/* Code below may sleep, need to lock module while we are here */
-	MOD_INC_USE_COUNT;
-	uvd = usbvideo_AllocateDevice(cams);
-	if (uvd != NULL) {
-		struct konicawc *konicawc_data = (struct konicawc *)(uvd->user_data);
-		/* Here uvd is a fully allocated uvd_t object */
-
-		for(i = 0; i < USBVIDEO_NUMSBUF; i++) {
-			konicawc_data->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-		}
-
-		switch(size) {
-		case SIZE_160X130:
-		default:
-			konicawc_data->height = 136;
-			konicawc_data->width = 160;
-			konicawc_data->size = SIZE_160X130;
-			break;
-
-		case SIZE_176X144:
-			konicawc_data->height = 144;
-			konicawc_data->width = 176;
-			konicawc_data->size = SIZE_176X144;
-			break;
-
-		case SIZE_320X240:
-			konicawc_data->height = 240;
-			konicawc_data->width = 320;
-			konicawc_data->size = SIZE_320X240;
-			break;
-		}
-
-		uvd->flags = 0;
-		uvd->debug = debug;
-		uvd->dev = dev;
-		uvd->iface = ifnum;
-		uvd->ifaceAltInactive = inactInterface;
-		uvd->ifaceAltActive = actInterface;
-		uvd->video_endp = video_ep;
-		uvd->iso_packet_len = maxPS;
-		uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P;
-		uvd->defaultPalette = VIDEO_PALETTE_YUV420P;
-		uvd->canvas = VIDEOSIZE(konicawc_data->width, konicawc_data->height);
-		uvd->videosize = uvd->canvas;
-
-		/* Initialize konicawc specific data */
-		konicawc_configure_video(uvd);
-
-		i = usbvideo_RegisterVideoDevice(uvd);
-		uvd->max_frame_size = (konicawc_data->width * konicawc_data->height * 3)/2;
-		if (i != 0) {
-			err("usbvideo_RegisterVideoDevice() failed.");
-			uvd = NULL;
-		}
-	}
-	MOD_DEC_USE_COUNT;
-	return uvd;
-}
-
-
-static int __init konicawc_init(void)
-{
-	usbvideo_cb_t cbTbl;
-	memset(&cbTbl, 0, sizeof(cbTbl));
-	cbTbl.probe = konicawc_probe;
-	cbTbl.setupOnOpen = konicawc_setup_on_open;
-	cbTbl.processData = konicawc_process_isoc;
-	cbTbl.getFPS = konicawc_calculate_fps;
-	cbTbl.startDataPump = konicawc_start_data;
-	cbTbl.stopDataPump = konicawc_stop_data;
-	return usbvideo_register(
-		&cams,
-		MAX_CAMERAS,
-		sizeof(struct konicawc),
-		"konicawc",
-		&cbTbl,
-		THIS_MODULE);
-}
-
-
-static void __exit konicawc_cleanup(void)
-{
-	usbvideo_Deregister(&cams);
-}
-
-#if defined(usb_device_id_ver)
-
-static __devinitdata struct usb_device_id id_table[] = {
-	{ USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
-	{ }  /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-#endif /* defined(usb_device_id_ver) */
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
-MODULE_DESCRIPTION("Konica Webcam driver");
-MODULE_PARM(size, "i");
-MODULE_PARM_DESC(size, "Frame Size 0: 160x136 1: 176x144 2: 320x240");
-MODULE_PARM(brightness, "i");
-MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
-MODULE_PARM(contrast, "i");
-MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
-MODULE_PARM(saturation, "i");
-MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
-MODULE_PARM(sharpness, "i");
-MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
-MODULE_PARM(whitebal, "i");
-MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-module_init(konicawc_init);
-module_exit(konicawc_cleanup);
diff -Nru a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c
--- a/drivers/usb/mdc800.c	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1029 +0,0 @@
-/*
- * copyright (C) 1999/2000 by Henning Zabel <henning@uni-paderborn.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-/*
- *	USB-Kernel Driver for the Mustek MDC800 Digital Camera
- *	(c) 1999/2000 Henning Zabel <henning@uni-paderborn.de>
- *
- *
- * The driver brings the USB functions of the MDC800 to Linux.
- * To use the Camera you must support the USB Protocoll of the camera
- * to the Kernel Node.
- * The Driver uses a misc device Node. Create it with :
- * mknod /dev/mustek c 180 32
- *
- * The driver supports only one camera.
- * 
- * Fix: mdc800 used sleep_on and slept with io_lock held.
- * Converted sleep_on to waitqueues with schedule_timeout and made io_lock
- * a semaphore from a spinlock.
- * by Oliver Neukum <520047054719-0001@t-online.de>
- * (02/12/2001)
- * 
- * Identify version on module load.
- * (08/04/2001) gb
- *
- * version 0.7.5
- * Fixed potential SMP races with Spinlocks.
- * Thanks to Oliver Neukum <oliver.neukum@lrz.uni-muenchen.de> who 
- * noticed the race conditions.
- * (30/10/2000)
- *
- * Fixed: Setting urb->dev before submitting urb.
- * by Greg KH <greg@kroah.com>
- * (13/10/2000)
- *
- * version 0.7.3
- * bugfix : The mdc800->state field gets set to READY after the
- * the diconnect function sets it to NOT_CONNECTED. This makes the
- * driver running like the camera is connected and causes some
- * hang ups.
- *
- * version 0.7.1
- * MOD_INC and MOD_DEC are changed in usb_probe to prevent load/unload
- * problems when compiled as Module.
- * (04/04/2000)
- *
- * The mdc800 driver gets assigned the USB Minor 32-47. The Registration
- * was updated to use these values.
- * (26/03/2000)
- *
- * The Init und Exit Module Function are updated.
- * (01/03/2000)
- *
- * version 0.7.0
- * Rewrite of the driver : The driver now uses URB's. The old stuff
- * has been removed.
- *
- * version 0.6.0
- * Rewrite of this driver: The Emulation of the rs232 protocoll
- * has been removed from the driver. A special executeCommand function
- * for this driver is included to gphoto.
- * The driver supports two kind of communication to bulk endpoints.
- * Either with the dev->bus->ops->bulk... or with callback function.
- * (09/11/1999)
- *
- * version 0.5.0:
- * first Version that gets a version number. Most of the needed
- * functions work.
- * (20/10/1999)
- */
-
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/smp_lock.h>
-
-#include <linux/usb.h>
-#include <linux/fs.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.7.5 (30/10/2000)"
-#define DRIVER_AUTHOR "Henning Zabel <henning@uni-paderborn.de>"
-#define DRIVER_DESC "USB Driver for Mustek MDC800 Digital Camera"
-
-/* Vendor and Product Information */
-#define MDC800_VENDOR_ID 	0x055f
-#define MDC800_PRODUCT_ID	0xa800
-
-/* Timeouts (msec) */
-#define TO_DOWNLOAD_GET_READY		1500
-#define TO_DOWNLOAD_GET_BUSY		1500
-#define TO_WRITE_GET_READY		1000
-#define TO_DEFAULT_COMMAND		5000
-#define TO_READ_FROM_IRQ 		TO_DEFAULT_COMMAND
-#define TO_GET_READY			TO_DEFAULT_COMMAND
-
-/* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
-#define MDC800_DEVICE_MINOR_BASE 32
-
-
-/**************************************************************************
-	Data and structs
-***************************************************************************/
-
-
-typedef enum {
-	NOT_CONNECTED, READY, WORKING, DOWNLOAD
-} mdc800_state;
-
-
-/* Data for the driver */
-struct mdc800_data
-{
-	struct usb_device *	dev;			// Device Data
-	mdc800_state 		state;
-
-	unsigned int		endpoint [4];
-
-	struct urb *		irq_urb;
-	wait_queue_head_t	irq_wait;
-	int			irq_woken;
-	char*			irq_urb_buffer;
-
-	int			camera_busy;          // is camera busy ?
-	int 			camera_request_ready; // Status to synchronize with irq
-	char 			camera_response [8];  // last Bytes send after busy
-
-	struct urb *   		write_urb;
-	char*			write_urb_buffer;
-	wait_queue_head_t	write_wait;
-	int			written;
-
-
-	struct urb *   		download_urb;
-	char*			download_urb_buffer;
-	wait_queue_head_t	download_wait;
-	int			downloaded;
-	int			download_left;		// Bytes left to download ?
-
-
-	/* Device Data */
-	char			out [64];	// Answer Buffer
-	int 			out_ptr;	// Index to the first not readen byte
-	int			out_count;	// Bytes in the buffer
-
-	int			open;		// Camera device open ?
-	struct semaphore	io_lock;	// IO -lock
-
-	char 			in [8];		// Command Input Buffer
-	int  			in_count;
-
-	int			pic_index;	// Cache for the Imagesize (-1 for nothing cached )
-	int			pic_len;
-};
-
-
-/* Specification of the Endpoints */
-static struct usb_endpoint_descriptor mdc800_ed [4] =
-{
-	{ 0,0, 0x01, 0x02,  8, 0,0,0 },
-	{ 0,0, 0x82, 0x03,  8, 0,0,0 },
-	{ 0,0, 0x03, 0x02, 64, 0,0,0 },
-	{ 0,0, 0x84, 0x02, 64, 0,0,0 }
-};
-
-
-/* The Variable used by the driver */
-static struct mdc800_data* mdc800=0;
-
-
-/***************************************************************************
-	The USB Part of the driver
-****************************************************************************/
-
-static int mdc800_endpoint_equals (struct usb_endpoint_descriptor *a,struct usb_endpoint_descriptor *b)
-{
-	return (
-		   ( a->bEndpointAddress == b->bEndpointAddress )
-		&& ( a->bmAttributes     == b->bmAttributes     )
-		&& ( a->wMaxPacketSize   == b->wMaxPacketSize   )
-	);
-}
-
-
-/*
- * Checks wether the camera responds busy
- */
-static int mdc800_isBusy (char* ch)
-{
-	int i=0;
-	while (i<8)
-	{
-		if (ch [i] != (char)0x99)
-			return 0;
-		i++;
-	}
-	return 1;
-}
-
-
-/*
- * Checks wether the Camera is ready
- */
-static int mdc800_isReady (char *ch)
-{
-	int i=0;
-	while (i<8)
-	{
-		if (ch [i] != (char)0xbb)
-			return 0;
-		i++;
-	}
-	return 1;
-}
-
-
-
-/*
- * USB IRQ Handler for InputLine
- */
-static void mdc800_usb_irq (struct urb *urb)
-{
-	int data_received=0, wake_up;
-	unsigned char* b=urb->transfer_buffer;
-	struct mdc800_data* mdc800=urb->context;
-
-	if (urb->status >= 0)
-	{
-
-		//dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
-
-		if (mdc800_isBusy (b))
-		{
-			if (!mdc800->camera_busy)
-			{
-				mdc800->camera_busy=1;
-				dbg ("gets busy");
-			}
-		}
-		else
-		{
-			if (mdc800->camera_busy && mdc800_isReady (b))
-			{
-				mdc800->camera_busy=0;
-				dbg ("gets ready");
-			}
-		}
-		if (!(mdc800_isBusy (b) || mdc800_isReady (b)))
-		{
-			/* Store Data in camera_answer field */
-			dbg ("%i %i %i %i %i %i %i %i ",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
-
-			memcpy (mdc800->camera_response,b,8);
-			data_received=1;
-		}
-	}
-	wake_up= ( mdc800->camera_request_ready > 0 )
-		&&
-		(
-			((mdc800->camera_request_ready == 1) && (!mdc800->camera_busy))
-		||
-			((mdc800->camera_request_ready == 2) && data_received)
-		||
-			((mdc800->camera_request_ready == 3) && (mdc800->camera_busy))
-		||
-			(urb->status < 0)
-		);
-
-	if (wake_up)
-	{
-		mdc800->camera_request_ready=0;
-		mdc800->irq_woken=1;
-		wake_up_interruptible (&mdc800->irq_wait);
-	}
-}
-
-
-/*
- * Waits a while until the irq responds that camera is ready
- *
- *  mode : 0: Wait for camera gets ready
- *         1: Wait for receiving data
- *         2: Wait for camera gets busy
- *
- * msec: Time to wait
- */
-static int mdc800_usb_waitForIRQ (int mode, int msec)
-{
-        DECLARE_WAITQUEUE(wait, current);
-
-	mdc800->camera_request_ready=1+mode;
-
-	add_wait_queue(&mdc800->irq_wait, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (!mdc800->irq_woken)
-	{
-		schedule_timeout (msec*HZ/1000);
-	}
-        remove_wait_queue(&mdc800->irq_wait, &wait);
-	set_current_state(TASK_RUNNING);
-	mdc800->irq_woken = 0;
-
-	if (mdc800->camera_request_ready>0)
-	{
-		mdc800->camera_request_ready=0;
-		err ("timeout waiting for camera.");
-		return -1;
-	}
-	
-	if (mdc800->state == NOT_CONNECTED)
-	{
-		warn ("Camera gets disconnected during waiting for irq.");
-		mdc800->camera_request_ready=0;
-		return -2;
-	}
-	
-	return 0;
-}
-
-
-/*
- * The write_urb callback function
- */
-static void mdc800_usb_write_notify (struct urb *urb)
-{
-	struct mdc800_data* mdc800=urb->context;
-
-	if (urb->status != 0)
-	{
-		err ("writing command fails (status=%i)", urb->status);
-	}
-	else
-	{	
-		mdc800->state=READY;
-	}
-	mdc800->written = 1;
-	wake_up_interruptible (&mdc800->write_wait);
-}
-
-
-/*
- * The download_urb callback function
- */
-static void mdc800_usb_download_notify (struct urb *urb)
-{
-	struct mdc800_data* mdc800=urb->context;
-
-	if (urb->status == 0)
-	{
-		/* Fill output buffer with these data */
-		memcpy (mdc800->out,  urb->transfer_buffer, 64);
-		mdc800->out_count=64;
-		mdc800->out_ptr=0;
-		mdc800->download_left-=64;
-		if (mdc800->download_left == 0)
-		{
-			mdc800->state=READY;
-		}
-	}
-	else
-	{
-		err ("request bytes fails (status:%i)", urb->status);
-	}
-	mdc800->downloaded = 1;
-	wake_up_interruptible (&mdc800->download_wait);
-}
-
-
-/***************************************************************************
-	Probing for the Camera
- ***************************************************************************/
-
-static struct usb_driver mdc800_usb_driver;
-
-/*
- * Callback to search the Mustek MDC800 on the USB Bus
- */
-static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum,
-			       const struct usb_device_id *id)
-{
-	int i,j;
-	struct usb_interface_descriptor	*intf_desc;
-	int irq_interval=0;
-
-	dbg ("(mdc800_usb_probe) called.");
-
-
-	if (mdc800->dev != 0)
-	{
-		warn ("only one Mustek MDC800 is supported.");
-		return 0;
-	}
-
-	if (dev->descriptor.bNumConfigurations != 1)
-	{
-		err ("probe fails -> wrong Number of Configuration");
-		return 0;
-	}
-	intf_desc=&dev->actconfig->interface[ifnum].altsetting[0];
-
-	if (
-			( intf_desc->bInterfaceClass != 0xff )
-		||	( intf_desc->bInterfaceSubClass != 0 )
-		|| ( intf_desc->bInterfaceProtocol != 0 )
-		|| ( intf_desc->bNumEndpoints != 4)
-	)
-	{
-		err ("probe fails -> wrong Interface");
-		return 0;
-	}
-
-	/* Check the Endpoints */
-	for (i=0; i<4; i++)
-	{
-		mdc800->endpoint[i]=-1;
-		for (j=0; j<4; j++)
-		{
-			if (mdc800_endpoint_equals (&intf_desc->endpoint [j],&mdc800_ed [i]))
-			{
-				mdc800->endpoint[i]=intf_desc->endpoint [j].bEndpointAddress ;
-				if (i==1)
-				{
-					irq_interval=intf_desc->endpoint [j].bInterval;
-				}
-
-				continue;
-			}
-		}
-		if (mdc800->endpoint[i] == -1)
-		{
-			err ("probe fails -> Wrong Endpoints.");
-			return 0;
-		}
-	}
-
-
-	usb_driver_claim_interface (&mdc800_usb_driver, &dev->actconfig->interface[ifnum], mdc800);
-	if (usb_set_interface (dev, ifnum, 0) < 0)
-	{
-		err ("MDC800 Configuration fails.");
-		return 0;
-	}
-
-	info ("Found Mustek MDC800 on USB.");
-
-	down (&mdc800->io_lock);
-
-	mdc800->dev=dev;
-	mdc800->open=0;
-
-	/* Setup URB Structs */
-	FILL_INT_URB (
-		mdc800->irq_urb,
-		mdc800->dev,
-		usb_rcvintpipe (mdc800->dev,mdc800->endpoint [1]),
-		mdc800->irq_urb_buffer,
-		8,
-		mdc800_usb_irq,
-		mdc800,
-		irq_interval
-	);
-
-	FILL_BULK_URB (
-		mdc800->write_urb,
-		mdc800->dev,
-		usb_sndbulkpipe (mdc800->dev, mdc800->endpoint[0]),
-		mdc800->write_urb_buffer,
-		8,
-		mdc800_usb_write_notify,
-		mdc800
-	);
-
-	FILL_BULK_URB (
-		mdc800->download_urb,
-		mdc800->dev,
-		usb_rcvbulkpipe (mdc800->dev, mdc800->endpoint [3]),
-		mdc800->download_urb_buffer,
-		64,
-		mdc800_usb_download_notify,
-		mdc800
-	);
-
-	mdc800->state=READY;
-
-	up (&mdc800->io_lock);
-	
-	return mdc800;
-}
-
-
-/*
- * Disconnect USB device (maybe the MDC800)
- */
-static void mdc800_usb_disconnect (struct usb_device *dev,void* ptr)
-{
-	struct mdc800_data* mdc800=(struct mdc800_data*) ptr;
-
-	dbg ("(mdc800_usb_disconnect) called");
-
-	if (mdc800->state == NOT_CONNECTED)
-		return;
-	
-	mdc800->state=NOT_CONNECTED;
-
-	usb_unlink_urb (mdc800->irq_urb);
-	usb_unlink_urb (mdc800->write_urb);
-	usb_unlink_urb (mdc800->download_urb);
-
-	usb_driver_release_interface (&mdc800_usb_driver, &dev->actconfig->interface[1]);
-
-	mdc800->dev=0;
-	info ("Mustek MDC800 disconnected from USB.");
-}
-
-
-/***************************************************************************
-	The Misc device Part (file_operations)
-****************************************************************************/
-
-/*
- * This Function calc the Answersize for a command.
- */
-static int mdc800_getAnswerSize (char command)
-{
-	switch ((unsigned char) command)
-	{
-		case 0x2a:
-		case 0x49:
-		case 0x51:
-		case 0x0d:
-		case 0x20:
-		case 0x07:
-		case 0x01:
-		case 0x25:
-		case 0x00:
-			return 8;
-
-		case 0x05:
-		case 0x3e:
-			return mdc800->pic_len;
-
-		case 0x09:
-			return 4096;
-
-		default:
-			return 0;
-	}
-}
-
-
-/*
- * Init the device: (1) alloc mem (2) Increase MOD Count ..
- */
-static int mdc800_device_open (struct inode* inode, struct file *file)
-{
-	int retval=0;
-	int errn=0;
-
-	down (&mdc800->io_lock);
-	
-	if (mdc800->state == NOT_CONNECTED)
-	{
-		errn=-EBUSY;
-		goto error_out;
-	}
-	if (mdc800->open)
-	{
-		errn=-EBUSY;
-		goto error_out;
-	}
-
-	mdc800->in_count=0;
-	mdc800->out_count=0;
-	mdc800->out_ptr=0;
-	mdc800->pic_index=0;
-	mdc800->pic_len=-1;
-	mdc800->download_left=0;
-
-	mdc800->camera_busy=0;
-	mdc800->camera_request_ready=0;
-
-	retval=0;
-	mdc800->irq_urb->dev = mdc800->dev;
-	if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL))
-	{
-		err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
-		errn = -EIO;
-		goto error_out;
-	}
-
-	mdc800->open=1;
-	dbg ("Mustek MDC800 device opened.");
-
-error_out:
-	up (&mdc800->io_lock);
-	return errn;
-}
-
-
-/*
- * Close the Camera and release Memory
- */
-static int mdc800_device_release (struct inode* inode, struct file *file)
-{
-	int retval=0;
-	dbg ("Mustek MDC800 device closed.");
-
-	down (&mdc800->io_lock);
-	if (mdc800->open && (mdc800->state != NOT_CONNECTED))
-	{
-		usb_unlink_urb (mdc800->irq_urb);
-		usb_unlink_urb (mdc800->write_urb);
-		usb_unlink_urb (mdc800->download_urb);
-		mdc800->open=0;
-	}
-	else
-	{
-		retval=-EIO;
-	}
-
-	up(&mdc800->io_lock);
-	return retval;
-}
-
-
-/*
- * The Device read callback Function
- */
-static ssize_t mdc800_device_read (struct file *file, char *buf, size_t len, loff_t *pos)
-{
-	int   left=len, sts=len; /* single transfer size */
-	char* ptr=buf;
-	DECLARE_WAITQUEUE(wait, current);
-
-	down (&mdc800->io_lock);
-	if (mdc800->state == NOT_CONNECTED)
-	{
-		up (&mdc800->io_lock);
-		return -EBUSY;
-	}
-	if (mdc800->state == WORKING)
-	{
-		warn ("Illegal State \"working\" reached during read ?!");
-		up (&mdc800->io_lock);
-		return -EBUSY;
-	}
-	if (!mdc800->open)
-	{
-		up (&mdc800->io_lock);
-		return -EBUSY;
-	}
-
-	while (left)
-	{
-		if (signal_pending (current)) 
-		{
-			up (&mdc800->io_lock);
-			return -EINTR;
-		}
-
-		sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left;
-
-		if (sts <= 0)
-		{
-			/* Too less Data in buffer */
-			if (mdc800->state == DOWNLOAD)
-			{
-				mdc800->out_count=0;
-				mdc800->out_ptr=0;
-
-				/* Download -> Request new bytes */
-				mdc800->download_urb->dev = mdc800->dev;
-				if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))
-				{
-					err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
-					up (&mdc800->io_lock);
-					return len-left;
-				}
-				add_wait_queue(&mdc800->download_wait, &wait);
-				set_current_state(TASK_INTERRUPTIBLE);
-				if (!mdc800->downloaded)
-				{
-					schedule_timeout (TO_DOWNLOAD_GET_READY*HZ/1000);
-				}
-				set_current_state(TASK_RUNNING);
-				remove_wait_queue(&mdc800->download_wait, &wait);
-				mdc800->downloaded = 0;
-				if (mdc800->download_urb->status != 0)
-				{
-					err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
-					up (&mdc800->io_lock);
-					return len-left;
-				}
-			}
-			else
-			{
-				/* No more bytes -> that's an error*/
-				up (&mdc800->io_lock);
-				return -EIO;
-			}
-		}
-		else
-		{
-			/* memcpy Bytes */
-			memcpy (ptr, &mdc800->out [mdc800->out_ptr], sts);
-			ptr+=sts;
-			left-=sts;
-			mdc800->out_ptr+=sts;
-		}
-	}
-
-	up (&mdc800->io_lock);
-	return len-left;
-}
-
-
-/*
- * The Device write callback Function
- * If a 8Byte Command is received, it will be send to the camera.
- * After this the driver initiates the request for the answer or
- * just waits until the camera becomes ready.
- */
-static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
-{
-	int i=0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	down (&mdc800->io_lock);
-	if (mdc800->state != READY)
-	{
-		up (&mdc800->io_lock);
-		return -EBUSY;
-	}
-	if (!mdc800->open )
-	{
-		up (&mdc800->io_lock);
-		return -EBUSY;
-	}
-
-	while (i<len)
-	{
-		if (signal_pending (current)) 
-		{
-			up (&mdc800->io_lock);
-			return -EINTR;
-		}
-
-		/* check for command start */
-		if (buf [i] == (char) 0x55)
-		{
-			mdc800->in_count=0;
-			mdc800->out_count=0;
-			mdc800->out_ptr=0;
-			mdc800->download_left=0;
-		}
-
-		/* save command byte */
-		if (mdc800->in_count < 8)
-		{
-			mdc800->in[mdc800->in_count]=buf[i];
-			mdc800->in_count++;
-		}
-		else
-		{
-			err ("Command is to long !\n");
-			up (&mdc800->io_lock);
-			return -EIO;
-		}
-
-		/* Command Buffer full ? -> send it to camera */
-		if (mdc800->in_count == 8)
-		{
-			int answersize;
-
-			if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
-			{
-				err ("Camera didn't get ready.\n");
-				up (&mdc800->io_lock);
-				return -EIO;
-			}
-
-			answersize=mdc800_getAnswerSize (mdc800->in[1]);
-
-			mdc800->state=WORKING;
-			memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);
-			mdc800->write_urb->dev = mdc800->dev;
-			if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))
-			{
-				err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
-				up (&mdc800->io_lock);
-				return -EIO;
-			}
-			add_wait_queue(&mdc800->write_wait, &wait);
-			set_current_state(TASK_INTERRUPTIBLE);
-			if (!mdc800->written)
-			{
-				schedule_timeout (TO_WRITE_GET_READY*HZ/1000);
-			}
-                        set_current_state(TASK_RUNNING);
-			remove_wait_queue(&mdc800->write_wait, &wait);
-			mdc800->written = 0;
-			if (mdc800->state == WORKING)
-			{
-				usb_unlink_urb (mdc800->write_urb);
-				up (&mdc800->io_lock);
-				return -EIO;
-			}
-
-			switch ((unsigned char) mdc800->in[1])
-			{
-				case 0x05: /* Download Image */
-				case 0x3e: /* Take shot in Fine Mode (WCam Mode) */
-					if (mdc800->pic_len < 0)
-					{
-						err ("call 0x07 before 0x05,0x3e");
-						mdc800->state=READY;
-						up (&mdc800->io_lock);
-						return -EIO;
-					}
-					mdc800->pic_len=-1;
-
-				case 0x09: /* Download Thumbnail */
-					mdc800->download_left=answersize+64;
-					mdc800->state=DOWNLOAD;
-					mdc800_usb_waitForIRQ (0,TO_DOWNLOAD_GET_BUSY);
-					break;
-
-
-				default:
-					if (answersize)
-					{
-
-						if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
-						{
-							err ("requesting answer from irq fails");
-							up (&mdc800->io_lock);
-							return -EIO;
-						}
-
-						/* Write dummy data, (this is ugly but part of the USB Protokoll */
-						/* if you use endpoint 1 as bulk and not as irq */
-						memcpy (mdc800->out, mdc800->camera_response,8);
-
-						/* This is the interpreted answer */
-						memcpy (&mdc800->out[8], mdc800->camera_response,8);
-
-						mdc800->out_ptr=0;
-						mdc800->out_count=16;
-
-						/* Cache the Imagesize, if command was getImageSize */
-						if (mdc800->in [1] == (char) 0x07)
-						{
-							mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2];
-
-							dbg ("cached imagesize = %i",mdc800->pic_len);
-						}
-
-					}
-					else
-					{
-						if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
-						{
-							err ("Command Timeout.");
-							up (&mdc800->io_lock);
-							return -EIO;
-						}
-					}
-					mdc800->state=READY;
-					break;
-			}
-		}
-		i++;
-	}
-	up (&mdc800->io_lock);
-	return i;
-}
-
-
-/***************************************************************************
-	Init and Cleanup this driver (Structs and types)
-****************************************************************************/
-
-/* File Operations of this drivers */
-static struct file_operations mdc800_device_ops =
-{
-	owner:		THIS_MODULE,
-	read:		mdc800_device_read,
-	write:		mdc800_device_write,
-	open:		mdc800_device_open,
-	release:	mdc800_device_release,
-};
-
-
-
-static struct usb_device_id mdc800_table [] = {
-	{ USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, mdc800_table);
-/*
- * USB Driver Struct for this device
- */
-static struct usb_driver mdc800_usb_driver =
-{
-	name:		"mdc800",
-	probe:		mdc800_usb_probe,
-	disconnect:	mdc800_usb_disconnect,
-	fops:		&mdc800_device_ops,
-	minor:		MDC800_DEVICE_MINOR_BASE,
-	id_table:	mdc800_table
-};
-
-
-
-/************************************************************************
-	Init and Cleanup this driver (Main Functions)
-*************************************************************************/
-
-#define try(A)           if ((A) == 0) goto cleanup_on_fail;
-#define try_free_mem(A)  if (A != 0) { kfree (A); A=0; }
-#define try_free_urb(A)  if (A != 0) { usb_free_urb (A); A=0; }
-
-int __init usb_mdc800_init (void)
-{
-	/* Allocate Memory */
-	try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
-
-	memset(mdc800, 0, sizeof(struct mdc800_data));
-	mdc800->dev=0;
-	mdc800->open=0;
-	mdc800->state=NOT_CONNECTED;
-	init_MUTEX (&mdc800->io_lock);
-
-	init_waitqueue_head (&mdc800->irq_wait);
-	init_waitqueue_head (&mdc800->write_wait);
-	init_waitqueue_head (&mdc800->download_wait);
-
-	mdc800->irq_woken = 0;
-	mdc800->downloaded = 0;
-	mdc800->written = 0;
-
-	try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
-	try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
-	try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
-
-	try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
-	try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
-	try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
-
-	/* Register the driver */
-	if (usb_register (&mdc800_usb_driver) < 0)
-		goto cleanup_on_fail;
-
-	info (DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-
-	/* Clean driver up, when something fails */
-
-cleanup_on_fail:
-
-	if (mdc800 != 0)
-	{
-		err ("can't alloc memory!");
-
-		try_free_mem (mdc800->download_urb_buffer);
-		try_free_mem (mdc800->write_urb_buffer);
-		try_free_mem (mdc800->irq_urb_buffer);
-
-		try_free_urb (mdc800->write_urb);
-		try_free_urb (mdc800->download_urb);
-		try_free_urb (mdc800->irq_urb);
-
-		kfree (mdc800);
-	}
-	mdc800=0;
-	return -1;
-}
-
-
-void __exit usb_mdc800_cleanup (void)
-{
-	usb_deregister (&mdc800_usb_driver);
-
-	usb_free_urb (mdc800->irq_urb);
-	usb_free_urb (mdc800->download_urb);
-	usb_free_urb (mdc800->write_urb);
-
-	kfree (mdc800->irq_urb_buffer);
-	kfree (mdc800->write_urb_buffer);
-	kfree (mdc800->download_urb_buffer);
-
-	kfree (mdc800);
-	mdc800=0;
-}
-
-module_init (usb_mdc800_init);
-module_exit (usb_mdc800_cleanup);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/media/Config.help b/drivers/usb/media/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,148 @@
+CONFIG_USB_DABUSB
+  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+  brought to you by the DAB-Team (<http://dab.in.tum.de/>).  This
+  driver can be taken as an example for URB-based bulk, control, and
+  isochronous transactions. URB's are explained in
+  <file:Documentation/usb/URB.txt>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dabusb.o.  If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_DSBR
+  Say Y here if you want to connect this type of radio to your
+  computer's USB port. Note that the audio is not digital, and
+  you must connect the line out connector to a sound card or a
+  set of speakers.
+
+  This driver uses the Video For Linux API.  You must enable
+  (Y or M in config) Video For Linux (under Character Devices)
+  to use this driver.  Information on this API and pointers to
+  "v4l" programs may be found on the WWW at
+  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dsbr100.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_IBMCAM
+  Say Y here if you want to connect a IBM "C-It" camera, also known as
+  "Xirlink PC Camera" to your computer's USB port.  For more
+  information, read <file:Documentation/usb/ibmcam.txt>.
+
+  This driver uses the Video For Linux API.  You must enable
+  (Y or M in config) Video For Linux (under Character Devices)
+  to use this driver.  Information on this API and pointers to
+  "v4l" programs may be found on the WWW at
+  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ibmcam.o.  If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>. This
+  camera has several configuration options which can be specified when
+  you load the module.  Read <file:Documentation/usb/ibmcam.txt> to
+  learn more.
+
+CONFIG_USB_KONICAWC
+  Say Y here if you want support for webcams based on a Konica
+  chipset. This is known to work with the Intel YC76 webcam.
+
+  This driver uses the Video For Linux API.  You must enable
+  (Y or M in config) Video For Linux (under Character Devices)
+  to use this driver.  Information on this API and pointers to
+  "v4l" programs may be found on the WWW at
+  <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called konicawc.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_OV511
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. See <file:Documentation/usb/ov511.txt> for more
+  information and for a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Character Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ov511.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_PWC
+  Say Y or M here if you want to use one of these Philips USB webcams:
+  PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
+  the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
+  by this driver and never will be.
+
+  This driver has an optional plugin, which is distributed as a binary
+  module only.  It contains code that allow you to use higher
+  resolutions and framerates but may not be distributed as source.
+  But even without this plugin you can these cams for most
+  applications.
+
+  See <file:Documentation/usb/philips.txt> for more information and
+  installation instructions.
+
+  The built-in microphone is enabled by selecting USB Audio support.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Character Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called pwc.o.  If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_SE401
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. See <file:Documentation/usb/se401.txt> for more
+  information and for a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called se401.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_STV680
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. This includes the Pencam line of cameras.
+  See <file:Documentation/usb/stv680.txt> for more information and for
+  a list of supported cameras.
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called stv680.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_VICAM
+  Say Y here if you have 3com homeconnect camera (vicam).
+
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at <http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called vicam.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/media/Config.in b/drivers/usb/media/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,29 @@
+#
+# USB Multimedia device configuration
+#
+comment 'USB Multimedia devices'
+dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
+if [ "$CONFIG_VIDEO_DEV" = "n" ]; then
+   comment '  Video4Linux support is needed for USB Multimedia device support'
+fi
+dep_tristate '  USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
+dep_tristate '  D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
+dep_tristate '  USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV
+dep_tristate '  USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV
+dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV
+dep_tristate '  USB Philips Cameras' CONFIG_USB_PWC $CONFIG_USB $CONFIG_VIDEO_DEV
+dep_tristate '  USB SE401 Camera support' CONFIG_USB_SE401 $CONFIG_USB $CONFIG_VIDEO_DEV
+dep_tristate '  USB STV680 (Pencam) Camera support' CONFIG_USB_STV680 $CONFIG_USB $CONFIG_VIDEO_DEV     
+
+# Turn on CONFIG_USB_MEDIA if any of the drivers are compiled into the kernel
+# to make our Makefile logic a bit simpler
+if [ "$CONFIG_USB_IBMCAM" = "y" -o "$CONFIG_USB_OV511" = "y" -o "$CONFIG_USB_PWC" = "y" ]; then
+   define_bool CONFIG_USB_MEDIA y
+fi
+if [ "$CONFIG_USB_SE401" = "y" -o "$CONFIG_USB_STV680" = "y" -o "$CONFIG_USB_VICAM" = "y" ]; then
+   define_bool CONFIG_USB_MEDIA y
+fi
+if [ "$CONFIG_USB_DSBR" = "y" -o "$CONFIG_USB_KONICAWC" = "y" -o "$CONFIG_USB_DABUSB" = "y" ]; then
+   define_bool CONFIG_USB_MEDIA y
+fi
+
diff -Nru a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,21 @@
+#
+# Makefile for USB Media drivers
+#
+
+O_TARGET	:= usb-media.o
+
+export-objs	:= ov511.o pwc-uncompress.o
+
+pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
+
+obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
+obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
+obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o usbvideo.o ultracam.o
+obj-$(CONFIG_USB_KONICAWC)	+= konicawc.o usbvideo.o
+obj-$(CONFIG_USB_OV511)		+= ov511.o
+obj-$(CONFIG_USB_PWC)		+= pwc.o
+obj-$(CONFIG_USB_SE401)		+= se401.o
+obj-$(CONFIG_USB_STV680)	+= stv680.o
+obj-$(CONFIG_USB_VICAM)		+= vicam.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/media/dabfirmware.h b/drivers/usb/media/dabfirmware.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/dabfirmware.h	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,1408 @@
+/*
+ * dabdata.h - dab usb firmware and bitstream data
+ */
+
+static INTEL_HEX_RECORD firmware[] = {
+
+{  2, 0x0000, 0, {0x21,0x57} },
+{  3, 0x0003, 0, {0x02,0x01,0x66} },
+{  3, 0x000b, 0, {0x02,0x01,0x66} },
+{  3, 0x0013, 0, {0x02,0x01,0x66} },
+{  3, 0x001b, 0, {0x02,0x01,0x66} },
+{  3, 0x0023, 0, {0x02,0x01,0x66} },
+{  3, 0x002b, 0, {0x02,0x01,0x66} },
+{  3, 0x0033, 0, {0x02,0x03,0x0f} },
+{  3, 0x003b, 0, {0x02,0x01,0x66} },
+{  3, 0x0043, 0, {0x02,0x01,0x00} },
+{  3, 0x004b, 0, {0x02,0x01,0x66} },
+{  3, 0x0053, 0, {0x02,0x01,0x66} },
+{  3, 0x005b, 0, {0x02,0x04,0xbd} },
+{  3, 0x0063, 0, {0x02,0x01,0x67} },
+{  3, 0x0100, 0, {0x02,0x0c,0x5a} },
+{  3, 0x0104, 0, {0x02,0x01,0xed} },
+{  3, 0x0108, 0, {0x02,0x02,0x51} },
+{  3, 0x010c, 0, {0x02,0x02,0x7c} },
+{  3, 0x0110, 0, {0x02,0x02,0xe4} },
+{  1, 0x0114, 0, {0x32} },
+{  1, 0x0118, 0, {0x32} },
+{  3, 0x011c, 0, {0x02,0x05,0xfd} },
+{  3, 0x0120, 0, {0x02,0x00,0x00} },
+{  3, 0x0124, 0, {0x02,0x00,0x00} },
+{  3, 0x0128, 0, {0x02,0x04,0x3c} },
+{  3, 0x012c, 0, {0x02,0x04,0x6a} },
+{  3, 0x0130, 0, {0x02,0x00,0x00} },
+{  3, 0x0134, 0, {0x02,0x00,0x00} },
+{  3, 0x0138, 0, {0x02,0x00,0x00} },
+{  3, 0x013c, 0, {0x02,0x00,0x00} },
+{  3, 0x0140, 0, {0x02,0x00,0x00} },
+{  3, 0x0144, 0, {0x02,0x00,0x00} },
+{  3, 0x0148, 0, {0x02,0x00,0x00} },
+{  3, 0x014c, 0, {0x02,0x00,0x00} },
+{  3, 0x0150, 0, {0x02,0x00,0x00} },
+{  3, 0x0154, 0, {0x02,0x00,0x00} },
+{ 10, 0x0157, 0, {0x75,0x81,0x7f,0xe5,0x82,0x60,0x03,0x02,0x01,0x61} },
+{  5, 0x0161, 0, {0x12,0x07,0x6f,0x21,0x64} },
+{  1, 0x0166, 0, {0x32} },
+{ 14, 0x0167, 0, {0xc0,0xd0,0xc0,0x86,0xc0,0x82,0xc0,0x83,0xc0,0xe0,0x90,0x7f,0x97,0xe0} },
+{ 14, 0x0175, 0, {0x44,0x80,0xf0,0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
+{ 14, 0x0183, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
+{ 14, 0x0191, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x90,0x7f,0x97,0xe0} },
+{  3, 0x019f, 0, {0x55,0x7f,0xf0} },
+{ 14, 0x01a2, 0, {0x90,0x7f,0x9a,0xe0,0x30,0xe4,0x23,0x90,0x7f,0x68,0xf0,0xf0,0xf0,0xf0} },
+{ 14, 0x01b0, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
+{ 14, 0x01be, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} },
+{ 14, 0x01cc, 0, {0xe5,0xd8,0xc2,0xe3,0xf5,0xd8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0xd0,0x86} },
+{  3, 0x01da, 0, {0xd0,0xd0,0x32} },
+{  8, 0x01dd, 0, {0x75,0x86,0x00,0x90,0xff,0xc3,0x7c,0x05} },
+{  7, 0x01e5, 0, {0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} },
+{  1, 0x01ec, 0, {0x22} },
+{ 14, 0x01ed, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0xd0} },
+{ 14, 0x01fb, 0, {0x75,0xd0,0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91} },
+{ 13, 0x0209, 0, {0x90,0x88,0x00,0xe0,0xf5,0x41,0x90,0x7f,0xab,0x74,0x02,0xf0,0x90} },
+{  9, 0x0216, 0, {0x7f,0xab,0x74,0x02,0xf0,0xe5,0x32,0x60,0x21} },
+{  4, 0x021f, 0, {0x7a,0x00,0x7b,0x00} },
+{ 11, 0x0223, 0, {0xc3,0xea,0x94,0x18,0xeb,0x64,0x80,0x94,0x80,0x50,0x12} },
+{ 14, 0x022e, 0, {0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0a,0xba,0x00} },
+{  2, 0x023c, 0, {0x01,0x0b} },
+{  2, 0x023e, 0, {0x80,0xe3} },
+{  2, 0x0240, 0, {0xd0,0x86} },
+{ 14, 0x0242, 0, {0xd0,0xd0,0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0} },
+{  1, 0x0250, 0, {0x32} },
+{ 14, 0x0251, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 14, 0x025f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} },
+{  4, 0x026d, 0, {0x04,0xf0,0xd0,0x86} },
+{ 11, 0x0271, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x027c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
+{ 14, 0x028a, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
+{ 13, 0x0298, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} },
+{ 12, 0x02a5, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0x6e,0x00,0x75,0x6f,0x02,0x12} },
+{  6, 0x02b1, 0, {0x11,0x44,0x75,0x70,0x39,0x75} },
+{  6, 0x02b7, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} },
+{ 12, 0x02bd, 0, {0x11,0x75,0x90,0x7f,0xd6,0xe4,0xf0,0x75,0xd8,0x20,0xd0,0x86} },
+{ 14, 0x02c9, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
+{ 13, 0x02d7, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x02e4, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 14, 0x02f2, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} },
+{  4, 0x0300, 0, {0x10,0xf0,0xd0,0x86} },
+{ 11, 0x0304, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x030f, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
+{ 14, 0x031d, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
+{ 12, 0x032b, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0x75,0x6e,0x00,0x75,0x6f,0x02} },
+{  7, 0x0337, 0, {0x12,0x11,0x44,0x75,0x70,0x40,0x75} },
+{  6, 0x033e, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} },
+{ 14, 0x0344, 0, {0x11,0x75,0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0} },
+{  5, 0x0352, 0, {0x75,0xd8,0x10,0xd0,0x86} },
+{ 14, 0x0357, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
+{ 13, 0x0365, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 13, 0x0372, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} },
+{ 12, 0x037f, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x42,0xf0,0x12,0x10,0x1b,0x90} },
+{ 13, 0x038b, 0, {0x7f,0xa6,0xe5,0x43,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40} },
+{  1, 0x0398, 0, {0xf0} },
+{  1, 0x0399, 0, {0x22} },
+{ 13, 0x039a, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} },
+{ 12, 0x03a7, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x44,0xf0,0x12,0x10,0x1b,0x90} },
+{ 12, 0x03b3, 0, {0x7f,0xa6,0xe5,0x45,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0xe5} },
+{ 11, 0x03bf, 0, {0x46,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40,0xf0} },
+{  1, 0x03ca, 0, {0x22} },
+{ 10, 0x03cb, 0, {0x75,0x44,0x02,0x75,0x45,0x00,0x75,0x46,0x00,0x12} },
+{  9, 0x03d5, 0, {0x03,0x9a,0x75,0x42,0x03,0x75,0x43,0x00,0x12} },
+{  2, 0x03de, 0, {0x03,0x72} },
+{  1, 0x03e0, 0, {0x22} },
+{ 12, 0x03e1, 0, {0x90,0x88,0x00,0xe5,0x36,0xf0,0x90,0x88,0x00,0x74,0x10,0x25} },
+{  9, 0x03ed, 0, {0x36,0xf0,0x12,0x01,0xdd,0x75,0x42,0x01,0x75} },
+{  9, 0x03f6, 0, {0x43,0x18,0x12,0x03,0x72,0x75,0x44,0x02,0x75} },
+{  9, 0x03ff, 0,{0x45,0x00,0x75,0x46,0x00,0x12,0x03,0x9a,0x75} },
+{  8, 0x0408, 0,{0x42,0x03,0x75,0x43,0x44,0x12,0x03,0x72} },
+{  1, 0x0410, 0,{0x22} },
+{ 14, 0x0411, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 14, 0x041f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} },
+{  4, 0x042d, 0, {0x02,0xf0,0xd0,0x86} },
+{ 11, 0x0431, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x043c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 14, 0x044a, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xa9,0x74} },
+{  7, 0x0458, 0, {0x04,0xf0,0x75,0x30,0x01,0xd0,0x86} },
+{ 11, 0x045f, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x046a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 14, 0x0478, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} },
+{  7, 0x0486, 0, {0x04,0xf0,0x75,0x31,0x01,0xd0,0x86} },
+{ 11, 0x048d, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x0498, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 12, 0x04a6, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe5,0xf5,0x91,0xd0,0x86} },
+{ 11, 0x04b2, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x04bd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} },
+{ 12, 0x04cb, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe7,0xf5,0x91,0xd0,0x86} },
+{ 11, 0x04d7, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 12, 0x04e2, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x20,0x90,0x7f,0x96,0xe4,0xf0} },
+{  1, 0x04ee, 0, {0x22} },
+{  7, 0x04ef, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x21} },
+{  1, 0x04f6, 0, {0x22} },
+{ 14, 0x04f7, 0, {0x90,0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xe0,0xfb,0x74,0x80,0x2a,0xfa} },
+{ 14, 0x0505, 0, {0x74,0x80,0x2b,0xfb,0xea,0x03,0x03,0x54,0x3f,0xfc,0xea,0xc4,0x23,0x54} },
+{ 14, 0x0513, 0, {0x1f,0xfa,0x2c,0xfa,0xeb,0x03,0x03,0x54,0x3f,0xfc,0xeb,0xc4,0x23,0x54} },
+{ 11, 0x0521, 0, {0x1f,0xfb,0x2c,0xfb,0x90,0x17,0x0a,0xe0,0xfc,0x60,0x02} },
+{  2, 0x052c, 0, {0x7a,0x00} },
+{  7, 0x052e, 0, {0x90,0x17,0x0c,0xe0,0xfc,0x60,0x02} },
+{  2, 0x0535, 0, {0x7b,0x00} },
+{ 11, 0x0537, 0, {0xea,0x2b,0xfc,0xc3,0x13,0xf5,0x3a,0x75,0x44,0x02,0x8b} },
+{  7, 0x0542, 0, {0x45,0x8a,0x46,0x12,0x03,0x9a,0x75} },
+{  9, 0x0549, 0, {0x6e,0x08,0x75,0x6f,0x00,0x12,0x11,0x44,0x75} },
+{  4, 0x0552, 0, {0x70,0x47,0x75,0x71} },
+{  8, 0x0556, 0, {0x0c,0x75,0x72,0x02,0x12,0x11,0x75,0x85} },
+{  5, 0x055e, 0, {0x3a,0x73,0x12,0x11,0xa0} },
+{  1, 0x0563, 0, {0x22} },
+{ 14, 0x0564, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} },
+{ 14, 0x0572, 0, {0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xef,0xe0,0xfc} },
+{ 14, 0x0580, 0, {0x33,0x95,0xe0,0xfd,0x8c,0x05,0x7c,0x00,0x90,0x7f,0xee,0xe0,0xfe,0x33} },
+{ 14, 0x058e, 0, {0x95,0xe0,0xff,0xec,0x2e,0xfc,0xed,0x3f,0xfd,0x90,0x7f,0xe9,0xe0,0xfe} },
+{  5, 0x059c, 0, {0xbe,0x01,0x02,0x80,0x03} },
+{  3, 0x05a1, 0, {0x02,0x05,0xf9} },
+{  6, 0x05a4, 0, {0xbc,0x01,0x21,0xbd,0x00,0x1e} },
+{ 14, 0x05aa, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfc,0xeb,0x25,0xe0,0xfd,0x2c,0x24,0x00,0xfc} },
+{ 14, 0x05b8, 0, {0xe4,0x34,0x17,0xfd,0x90,0x7e,0xc0,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0} },
+{  2, 0x05c6, 0, {0x80,0x31} },
+{ 14, 0x05c8, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfa,0xeb,0x25,0xe0,0xfb,0x2a,0xfa,0x24,0x00} },
+{ 14, 0x05d6, 0, {0xfb,0xe4,0x34,0x17,0xfc,0x90,0x7e,0xc0,0xe0,0xfd,0x8b,0x82,0x8c,0x83} },
+{ 14, 0x05e4, 0, {0xf0,0x74,0x01,0x2a,0x24,0x00,0xfa,0xe4,0x34,0x17,0xfb,0x90,0x7e,0xc1} },
+{  7, 0x05f2, 0, {0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0} },
+{  3, 0x05f9, 0, {0x75,0x38,0x01} },
+{  1, 0x05fc, 0, {0x22} },
+{ 14, 0x05fd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
+{ 14, 0x060b, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
+{ 13, 0x0619, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} },
+{ 13, 0x0626, 0, {0x7f,0xaa,0x74,0x01,0xf0,0x12,0x05,0x64,0x75,0x37,0x00,0xd0,0x86} },
+{ 14, 0x0633, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
+{ 13, 0x0641, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 14, 0x064e, 0, {0x90,0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xee,0xe0} },
+{ 14, 0x065c, 0, {0xfc,0x33,0x95,0xe0,0xfd,0x90,0x7f,0x96,0xe0,0xfe,0x90,0x7f,0x96,0x74} },
+{ 14, 0x066a, 0, {0x80,0x65,0x06,0xf0,0x90,0x7f,0x00,0x74,0x01,0xf0,0xea,0xc4,0x03,0x54} },
+{ 14, 0x0678, 0, {0xf8,0xfe,0xeb,0x25,0xe0,0xfb,0x2e,0xfe,0x24,0x00,0xfb,0xe4,0x34,0x17} },
+{ 14, 0x0686, 0, {0xff,0x8b,0x82,0x8f,0x83,0xe0,0xfb,0x74,0x01,0x2e,0x24,0x00,0xfe,0xe4} },
+{ 14, 0x0694, 0, {0x34,0x17,0xff,0x8e,0x82,0x8f,0x83,0xe0,0xfe,0x90,0x7f,0xe9,0xe0,0xff} },
+{  3, 0x06a2, 0, {0xbf,0x81,0x0a} },
+{ 10, 0x06a5, 0, {0x90,0x7f,0x00,0xeb,0xf0,0x90,0x7f,0x01,0xee,0xf0} },
+{  8, 0x06af, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x82,0x1a} },
+{  3, 0x06b7, 0, {0xba,0x01,0x0c} },
+{ 12, 0x06ba, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} },
+{ 11, 0x06c6, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0xb5,0xf0} },
+{  8, 0x06d1, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x83,0x1b} },
+{  3, 0x06d9, 0, {0xba,0x01,0x0d} },
+{ 13, 0x06dc, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} },
+{ 11, 0x06e9, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0x12,0xf0} },
+{  8, 0x06f4, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x84,0x1c} },
+{  3, 0x06fc, 0, {0xba,0x01,0x0d} },
+{ 13, 0x06ff, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0c} },
+{ 12, 0x070c, 0, {0x90,0x7f,0x00,0x74,0x80,0xf0,0x90,0x7f,0x01,0x74,0x01,0xf0} },
+{  5, 0x0718, 0, {0x90,0x7f,0xb5,0xec,0xf0} },
+{  1, 0x071d, 0, {0x22} },
+{ 12, 0x071e, 0, {0x75,0x36,0x0d,0x90,0x88,0x00,0x74,0x1d,0xf0,0x75,0x6b,0x80} },
+{ 10, 0x072a, 0, {0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} },
+{  9, 0x0734, 0, {0x6c,0x0f,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} },
+{  9, 0x073d, 0, {0x6c,0x06,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} },
+{  7, 0x0746, 0, {0x6c,0x01,0x12,0x10,0xe2,0x7a,0x00} },
+{  3, 0x074d, 0, {0xba,0xff,0x00} },
+{  2, 0x0750, 0, {0x50,0x0a} },
+{ 10, 0x0752, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} },
+{ 10, 0x075c, 0, {0x75,0x6b,0x80,0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75} },
+{  8, 0x0766, 0, {0x6b,0x80,0x75,0x6c,0x0f,0x12,0x10,0xe2} },
+{  1, 0x076e, 0, {0x22} },
+{ 14, 0x076f, 0, {0x90,0x7f,0xa1,0xe4,0xf0,0x90,0x7f,0xaf,0x74,0x01,0xf0,0x90,0x7f,0x92} },
+{ 14, 0x077d, 0, {0x74,0x02,0xf0,0x75,0x8e,0x31,0x75,0x89,0x21,0x75,0x88,0x00,0x75,0xc8} },
+{ 14, 0x078b, 0, {0x00,0x75,0x8d,0x40,0x75,0x98,0x40,0x75,0xc0,0x40,0x75,0x87,0x00,0x75} },
+{  9, 0x0799, 0, {0x20,0x00,0x75,0x21,0x00,0x75,0x22,0x00,0x75} },
+{  5, 0x07a2, 0, {0x23,0x00,0x75,0x47,0x00} },
+{  7, 0x07a7, 0, {0xc3,0xe5,0x47,0x94,0x20,0x50,0x11} },
+{ 13, 0x07ae, 0, {0xe5,0x47,0x24,0x00,0xf5,0x82,0xe4,0x34,0x17,0xf5,0x83,0xe4,0xf0} },
+{  4, 0x07bb, 0, {0x05,0x47,0x80,0xe8} },
+{  9, 0x07bf, 0, {0xe4,0xf5,0x40,0xf5,0x3f,0xe4,0xf5,0x3c,0xf5} },
+{  7, 0x07c8, 0, {0x3b,0xe4,0xf5,0x3e,0xf5,0x3d,0x75} },
+{ 11, 0x07cf, 0, {0x32,0x00,0x75,0x37,0x00,0x75,0x39,0x00,0x90,0x7f,0x93} },
+{ 14, 0x07da, 0, {0x74,0x3c,0xf0,0x90,0x7f,0x9c,0x74,0xff,0xf0,0x90,0x7f,0x96,0x74,0x80} },
+{ 14, 0x07e8, 0, {0xf0,0x90,0x7f,0x94,0x74,0x70,0xf0,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} },
+{ 14, 0x07f6, 0, {0x7f,0x97,0xe4,0xf0,0x90,0x7f,0x95,0x74,0xc2,0xf0,0x90,0x7f,0x98,0x74} },
+{ 14, 0x0804, 0, {0x28,0xf0,0x90,0x7f,0x9e,0x74,0x28,0xf0,0x90,0x7f,0xf0,0xe4,0xf0,0x90} },
+{ 14, 0x0812, 0, {0x7f,0xf1,0xe4,0xf0,0x90,0x7f,0xf2,0xe4,0xf0,0x90,0x7f,0xf3,0xe4,0xf0} },
+{ 14, 0x0820, 0, {0x90,0x7f,0xf4,0xe4,0xf0,0x90,0x7f,0xf5,0xe4,0xf0,0x90,0x7f,0xf6,0xe4} },
+{ 14, 0x082e, 0, {0xf0,0x90,0x7f,0xf7,0xe4,0xf0,0x90,0x7f,0xf8,0xe4,0xf0,0x90,0x7f,0xf9} },
+{ 14, 0x083c, 0, {0x74,0x38,0xf0,0x90,0x7f,0xfa,0x74,0xa0,0xf0,0x90,0x7f,0xfb,0x74,0xa0} },
+{ 14, 0x084a, 0, {0xf0,0x90,0x7f,0xfc,0x74,0xa0,0xf0,0x90,0x7f,0xfd,0x74,0xa0,0xf0,0x90} },
+{ 14, 0x0858, 0, {0x7f,0xfe,0x74,0xa0,0xf0,0x90,0x7f,0xff,0x74,0xa0,0xf0,0x90,0x7f,0xe0} },
+{ 14, 0x0866, 0, {0x74,0x03,0xf0,0x90,0x7f,0xe1,0x74,0x01,0xf0,0x90,0x7f,0xdd,0x74,0x80} },
+{ 11, 0x0874, 0, {0xf0,0x12,0x12,0x43,0x12,0x07,0x1e,0x7a,0x00,0x7b,0x00} },
+{  9, 0x087f, 0, {0xc3,0xea,0x94,0x1e,0xeb,0x94,0x00,0x50,0x17} },
+{ 12, 0x0888, 0, {0x90,0x88,0x00,0xe0,0xf5,0x47,0x90,0x88,0x0b,0xe0,0xf5,0x47} },
+{  9, 0x0894, 0, {0x90,0x7f,0x68,0xf0,0x0a,0xba,0x00,0x01,0x0b} },
+{  2, 0x089d, 0, {0x80,0xe0} },
+{ 12, 0x089f, 0, {0x12,0x03,0xe1,0x90,0x7f,0xd6,0xe4,0xf0,0x7a,0x00,0x7b,0x00} },
+{ 13, 0x08ab, 0, {0x8a,0x04,0x8b,0x05,0xc3,0xea,0x94,0xe0,0xeb,0x94,0x2e,0x50,0x1a} },
+{ 14, 0x08b8, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} },
+{ 10, 0x08c6, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} },
+{  2, 0x08d0, 0, {0x80,0xd9} },
+{ 13, 0x08d2, 0, {0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0,0x90} },
+{ 14, 0x08df, 0, {0x7f,0xde,0x74,0x05,0xf0,0x90,0x7f,0xdf,0x74,0x05,0xf0,0x90,0x7f,0xac} },
+{ 14, 0x08ed, 0, {0xe4,0xf0,0x90,0x7f,0xad,0x74,0x05,0xf0,0x75,0xa8,0x80,0x75,0xf8,0x10} },
+{ 13, 0x08fb, 0, {0x90,0x7f,0xae,0x74,0x0b,0xf0,0x90,0x7f,0xe2,0x74,0x88,0xf0,0x90} },
+{ 12, 0x0908, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0xe8,0x11,0x75,0x32,0x01,0x75} },
+{ 12, 0x0914, 0, {0x31,0x00,0x75,0x30,0x00,0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7} },
+{ 10, 0x0920, 0, {0xd0,0x05,0xd0,0x04,0x75,0x34,0x00,0x75,0x35,0x01} },
+{ 13, 0x092a, 0, {0x90,0x7f,0xae,0x74,0x03,0xf0,0x8c,0x02,0xba,0x00,0x02,0x80,0x03} },
+{  3, 0x0937, 0, {0x02,0x0a,0x3f} },
+{ 12, 0x093a, 0, {0x85,0x33,0x34,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90,0x7f,0x97} },
+{ 14, 0x0946, 0, {0x74,0x08,0xf0,0x90,0x7f,0x9d,0x74,0x88,0xf0,0x90,0x7f,0x9a,0xe0,0xfa} },
+{ 12, 0x0954, 0, {0x74,0x05,0x5a,0xf5,0x33,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} },
+{ 13, 0x0960, 0, {0x7f,0x97,0x74,0x02,0xf0,0x90,0x7f,0x9d,0x74,0x82,0xf0,0xe5,0x33} },
+{ 13, 0x096d, 0, {0x25,0xe0,0xfa,0x90,0x7f,0x9a,0xe0,0x54,0x05,0xfb,0x4a,0xf5,0x33} },
+{  2, 0x097a, 0, {0x60,0x0c} },
+{ 12, 0x097c, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x4a,0xf0} },
+{ 11, 0x0988, 0, {0x75,0x6e,0x00,0x75,0x6f,0x00,0xc0,0x04,0xc0,0x05,0x12} },
+{ 14, 0x0993, 0, {0x11,0x44,0xd0,0x05,0xd0,0x04,0x90,0x17,0x13,0xe0,0xfa,0x74,0x80,0x2a} },
+{  6, 0x09a1, 0, {0xfa,0xe5,0x33,0xb4,0x04,0x29} },
+{  3, 0x09a7, 0, {0xba,0xa0,0x00} },
+{  2, 0x09aa, 0, {0x50,0x24} },
+{ 13, 0x09ac, 0, {0x90,0x17,0x13,0xe0,0x04,0xfb,0x0b,0x90,0x17,0x13,0xeb,0xf0,0x90} },
+{ 14, 0x09b9, 0, {0x17,0x13,0xe0,0xfb,0x90,0x17,0x15,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05} },
+{  9, 0x09c7, 0, {0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02} },
+{  5, 0x09d0, 0, {0xe5,0x33,0xb4,0x02,0x26} },
+{  6, 0x09d5, 0, {0xc3,0x74,0x04,0x9a,0x50,0x20} },
+{ 13, 0x09db, 0, {0x90,0x17,0x13,0xe0,0xfa,0x1a,0x1a,0x90,0x17,0x13,0xea,0xf0,0x90} },
+{ 13, 0x09e8, 0, {0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xf0,0xc0,0x04,0xc0,0x05,0x12} },
+{  6, 0x09f5, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04} },
+{  5, 0x09fb, 0, {0xe5,0x33,0xb4,0x08,0x1d} },
+{  4, 0x0a00, 0, {0xe5,0x34,0x70,0x19} },
+{ 10, 0x0a04, 0, {0x74,0x01,0x25,0x35,0x54,0x0f,0xf5,0x35,0x85,0x35} },
+{ 12, 0x0a0e, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} },
+{  3, 0x0a1a, 0, {0x05,0xd0,0x04} },
+{  5, 0x0a1d, 0, {0xe5,0x33,0xb4,0x01,0x1d} },
+{  4, 0x0a22, 0, {0xe5,0x34,0x70,0x19} },
+{ 10, 0x0a26, 0, {0xe5,0x35,0x24,0xff,0x54,0x0f,0xf5,0x35,0x85,0x35} },
+{ 12, 0x0a30, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} },
+{  3, 0x0a3c, 0, {0x05,0xd0,0x04} },
+{ 14, 0x0a3f, 0, {0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0,0x04,0x90,0x7f,0x96} },
+{ 14, 0x0a4d, 0, {0xe0,0xfa,0x90,0x7f,0x96,0x74,0x7f,0x5a,0xf0,0x90,0x7f,0x97,0x74,0x08} },
+{ 10, 0x0a5b, 0, {0xf0,0xc3,0xec,0x94,0x00,0xed,0x94,0x02,0x40,0x08} },
+{  8, 0x0a65, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x20,0xe6,0x08} },
+{  8, 0x0a6d, 0, {0xc3,0xe4,0x9c,0x74,0x08,0x9d,0x50,0x13} },
+{ 14, 0x0a75, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x40,0x65,0x02,0xf0,0x7c} },
+{  5, 0x0a83, 0, {0x00,0x7d,0x00,0x80,0x05} },
+{  5, 0x0a88, 0, {0x0c,0xbc,0x00,0x01,0x0d} },
+{  5, 0x0a8d, 0, {0xe5,0x38,0xb4,0x01,0x0e} },
+{ 13, 0x0a92, 0, {0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0x75,0x38} },
+{  1, 0x0a9f, 0, {0x00} },
+{  7, 0x0aa0, 0, {0xe5,0x31,0x70,0x03,0x02,0x09,0x2a} },
+{ 10, 0x0aa7, 0, {0x90,0x7f,0xc9,0xe0,0xfa,0x70,0x03,0x02,0x0c,0x2d} },
+{ 14, 0x0ab1, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} },
+{  9, 0x0abf, 0, {0x7d,0xc0,0xe0,0xfa,0xba,0x2c,0x02,0x80,0x03} },
+{  3, 0x0ac8, 0, {0x02,0x0b,0x36} },
+{  5, 0x0acb, 0, {0x75,0x32,0x00,0x7b,0x00} },
+{  3, 0x0ad0, 0, {0xbb,0x64,0x00} },
+{  2, 0x0ad3, 0, {0x50,0x1c} },
+{ 14, 0x0ad5, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} },
+{ 13, 0x0ae3, 0, {0x04,0xd0,0x03,0xd0,0x02,0x90,0x88,0x0f,0xe0,0xf5,0x47,0x0b,0x80} },
+{  1, 0x0af0, 0, {0xdf} },
+{ 13, 0x0af1, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x07,0x1e,0x12,0x03,0xe1,0x12} },
+{ 12, 0x0afe, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x75,0x6e,0x00,0x75} },
+{ 13, 0x0b0a, 0, {0x6f,0x01,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0x44,0xd0,0x05} },
+{  9, 0x0b17, 0, {0xd0,0x04,0xd0,0x02,0x75,0x70,0x4d,0x75,0x71} },
+{ 11, 0x0b20, 0, {0x0c,0x75,0x72,0x02,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} },
+{ 11, 0x0b2b, 0, {0x11,0x75,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x02,0x0c,0x2d} },
+{  3, 0x0b36, 0, {0xba,0x2a,0x3b} },
+{ 13, 0x0b39, 0, {0x90,0x7f,0x98,0x74,0x20,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} },
+{ 14, 0x0b46, 0, {0x01,0xdd,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x90,0x7f,0x98,0x74,0x28,0xf0} },
+{  2, 0x0b54, 0, {0x7b,0x00} },
+{  3, 0x0b56, 0, {0xbb,0x0a,0x00} },
+{  5, 0x0b59, 0, {0x40,0x03,0x02,0x0c,0x2d} },
+{ 14, 0x0b5e, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} },
+{  8, 0x0b6c, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0b,0x80,0xe2} },
+{  3, 0x0b74, 0, {0xba,0x2b,0x1a} },
+{  8, 0x0b77, 0, {0x90,0x7f,0xc9,0xe0,0xfb,0xbb,0x40,0x12} },
+{ 14, 0x0b7f, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x12,0x05,0xd0,0x05,0xd0,0x04,0xd0} },
+{  4, 0x0b8d, 0, {0x02,0x02,0x0c,0x2d} },
+{  3, 0x0b91, 0, {0xba,0x10,0x1f} },
+{ 14, 0x0b94, 0, {0x90,0x7f,0x96,0xe0,0xfb,0x90,0x7f,0x96,0x74,0x80,0x65,0x03,0xf0,0xc0} },
+{ 14, 0x0ba2, 0, {0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x3d,0xd0,0x05,0xd0,0x04,0xd0,0x02} },
+{  3, 0x0bb0, 0, {0x02,0x0c,0x2d} },
+{  3, 0x0bb3, 0, {0xba,0x11,0x12} },
+{ 14, 0x0bb6, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x6a,0xd0,0x05,0xd0,0x04,0xd0} },
+{  4, 0x0bc4, 0, {0x02,0x02,0x0c,0x2d} },
+{  3, 0x0bc8, 0, {0xba,0x12,0x12} },
+{ 14, 0x0bcb, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x8f,0xd0,0x05,0xd0,0x04,0xd0} },
+{  4, 0x0bd9, 0, {0x02,0x02,0x0c,0x2d} },
+{  3, 0x0bdd, 0, {0xba,0x13,0x0b} },
+{ 11, 0x0be0, 0, {0x90,0x7d,0xc1,0xe0,0xfb,0x90,0x88,0x00,0xf0,0x80,0x42} },
+{  3, 0x0beb, 0, {0xba,0x14,0x11} },
+{ 14, 0x0bee, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0xdd,0xd0,0x05,0xd0,0x04,0xd0} },
+{  3, 0x0bfc, 0, {0x02,0x80,0x2e} },
+{  3, 0x0bff, 0, {0xba,0x15,0x1d} },
+{ 12, 0x0c02, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x75,0x90,0x7d,0xc2,0xe0,0xf5,0x76} },
+{ 14, 0x0c0e, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0,0x05,0xd0,0x04,0xd0} },
+{  3, 0x0c1c, 0, {0x02,0x80,0x0e} },
+{  3, 0x0c1f, 0, {0xba,0x16,0x0b} },
+{ 11, 0x0c22, 0, {0xc0,0x04,0xc0,0x05,0x12,0x13,0xa3,0xd0,0x05,0xd0,0x04} },
+{ 11, 0x0c2d, 0, {0x90,0x7f,0xc9,0xe4,0xf0,0x75,0x31,0x00,0x02,0x09,0x2a} },
+{  1, 0x0c38, 0, {0x22} },
+{  7, 0x0c39, 0, {0x53,0x55,0x50,0x45,0x4e,0x44,0x00} },
+{  7, 0x0c40, 0, {0x52,0x45,0x53,0x55,0x4d,0x45,0x00} },
+{  6, 0x0c47, 0, {0x20,0x56,0x6f,0x6c,0x20,0x00} },
+{ 13, 0x0c4d, 0, {0x44,0x41,0x42,0x55,0x53,0x42,0x20,0x76,0x31,0x2e,0x30,0x30,0x00} },
+{ 14, 0x0c5a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} },
+{ 14, 0x0c68, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} },
+{ 13, 0x0c76, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} },
+{ 14, 0x0c83, 0, {0x7f,0xab,0x74,0x01,0xf0,0x90,0x7f,0xe8,0xe0,0xfa,0x90,0x7f,0xe9,0xe0} },
+{  6, 0x0c91, 0, {0xfb,0xbb,0x00,0x02,0x80,0x03} },
+{  3, 0x0c97, 0, {0x02,0x0d,0x38} },
+{  3, 0x0c9a, 0, {0xba,0x80,0x14} },
+{ 14, 0x0c9d, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5} },
+{  6, 0x0cab, 0, {0x74,0x02,0xf0,0x02,0x0e,0xcd} },
+{  5, 0x0cb1, 0, {0xba,0x82,0x02,0x80,0x03} },
+{  3, 0x0cb6, 0, {0x02,0x0d,0x1d} },
+{  8, 0x0cb9, 0, {0x90,0x7f,0xec,0xe0,0xfc,0xbc,0x01,0x00} },
+{  2, 0x0cc1, 0, {0x40,0x21} },
+{  6, 0x0cc3, 0, {0xc3,0x74,0x07,0x9c,0x40,0x1b} },
+{ 14, 0x0cc9, 0, {0xec,0x24,0xff,0x25,0xe0,0xfd,0x24,0xc6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
+{ 13, 0x0cd7, 0, {0x83,0xe0,0xfd,0x53,0x05,0x01,0x90,0x7f,0x00,0xed,0xf0,0x80,0x2b} },
+{  3, 0x0ce4, 0, {0xbc,0x81,0x00} },
+{  2, 0x0ce7, 0, {0x40,0x21} },
+{  6, 0x0ce9, 0, {0xc3,0x74,0x87,0x9c,0x40,0x1b} },
+{ 14, 0x0cef, 0, {0xec,0x24,0x7f,0x25,0xe0,0xfc,0x24,0xb6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
+{ 13, 0x0cfd, 0, {0x83,0xe0,0xfc,0x53,0x04,0x01,0x90,0x7f,0x00,0xec,0xf0,0x80,0x05} },
+{  5, 0x0d0a, 0, {0x90,0x7f,0x00,0xe4,0xf0} },
+{ 14, 0x0d0f, 0, {0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x02,0x0e,0xcd} },
+{  5, 0x0d1d, 0, {0xba,0x81,0x02,0x80,0x03} },
+{  3, 0x0d22, 0, {0x02,0x0e,0xc5} },
+{ 14, 0x0d25, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74} },
+{  5, 0x0d33, 0, {0x02,0xf0,0x02,0x0e,0xcd} },
+{  3, 0x0d38, 0, {0xbb,0x01,0x2d} },
+{  6, 0x0d3b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} },
+{  3, 0x0d41, 0, {0xba,0x02,0x11} },
+{ 13, 0x0d44, 0, {0x75,0x59,0x00,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} },
+{  4, 0x0d51, 0, {0x02,0x02,0x0e,0xcd} },
+{  5, 0x0d55, 0, {0xba,0x21,0x02,0x80,0x03} },
+{  3, 0x0d5a, 0, {0x02,0x0e,0xcd} },
+{ 11, 0x0d5d, 0, {0x75,0x37,0x01,0x90,0x7f,0xc5,0xe4,0xf0,0x02,0x0e,0xcd} },
+{  3, 0x0d68, 0, {0xbb,0x03,0x1f} },
+{  6, 0x0d6b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} },
+{  5, 0x0d71, 0, {0xba,0x02,0x02,0x80,0x03} },
+{  3, 0x0d76, 0, {0x02,0x0e,0xcd} },
+{ 13, 0x0d79, 0, {0x75,0x59,0x01,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} },
+{  4, 0x0d86, 0, {0x02,0x02,0x0e,0xcd} },
+{  3, 0x0d8a, 0, {0xbb,0x06,0x54} },
+{  5, 0x0d8d, 0, {0xba,0x80,0x02,0x80,0x03} },
+{  3, 0x0d92, 0, {0x02,0x0e,0xc5} },
+{  8, 0x0d95, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x01,0x15} },
+{ 12, 0x0d9d, 0, {0x7c,0xfb,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} },
+{  9, 0x0da9, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} },
+{ 10, 0x0db2, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x02,0x02,0x80,0x03} },
+{  3, 0x0dbc, 0, {0x02,0x0e,0xc5} },
+{ 10, 0x0dbf, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x02,0x80,0x03} },
+{  3, 0x0dc9, 0, {0x02,0x0e,0xc5} },
+{ 12, 0x0dcc, 0, {0x7c,0x3b,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} },
+{  9, 0x0dd8, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} },
+{  6, 0x0de1, 0, {0xbb,0x07,0x03,0x02,0x0e,0xc5} },
+{  3, 0x0de7, 0, {0xbb,0x08,0x10} },
+{ 13, 0x0dea, 0, {0xac,0x48,0x90,0x7f,0x00,0xec,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} },
+{  3, 0x0df7, 0, {0x02,0x0e,0xcd} },
+{  3, 0x0dfa, 0, {0xbb,0x09,0x31} },
+{  5, 0x0dfd, 0, {0xba,0x00,0x02,0x80,0x03} },
+{  3, 0x0e02, 0, {0x02,0x0e,0xc5} },
+{ 14, 0x0e05, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xc3,0x74,0x01,0x9c,0x50,0x03,0x02,0x0e,0xc5} },
+{  8, 0x0e13, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x0a} },
+{ 10, 0x0e1b, 0, {0x90,0x17,0x21,0xe4,0xf0,0x90,0x17,0x22,0xe4,0xf0} },
+{  9, 0x0e25, 0, {0x90,0x7f,0xea,0xe0,0xf5,0x48,0x02,0x0e,0xcd} },
+{  3, 0x0e2e, 0, {0xbb,0x0a,0x27} },
+{  5, 0x0e31, 0, {0xba,0x81,0x02,0x80,0x03} },
+{  3, 0x0e36, 0, {0x02,0x0e,0xc5} },
+{ 14, 0x0e39, 0, {0x90,0x7f,0xec,0xe0,0xfa,0x24,0x20,0xfa,0xe4,0x34,0x17,0xfc,0x8a,0x82} },
+{ 14, 0x0e47, 0, {0x8c,0x83,0xe0,0xfa,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} },
+{  3, 0x0e55, 0, {0x02,0x0e,0xcd} },
+{  5, 0x0e58, 0, {0xbb,0x0b,0x02,0x80,0x03} },
+{  3, 0x0e5d, 0, {0x02,0x0e,0xa9} },
+{ 13, 0x0e60, 0, {0x90,0x17,0x20,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0xfa,0xba,0x01,0x1a} },
+{  8, 0x0e6d, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x12} },
+{ 14, 0x0e75, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x90,0x17,0x21,0xf0,0xc0,0x03,0x12,0x04,0xe2} },
+{  4, 0x0e83, 0, {0xd0,0x03,0x80,0x46} },
+{  8, 0x0e87, 0, {0x90,0x7f,0xec,0xe0,0xfa,0xba,0x02,0x3e} },
+{  8, 0x0e8f, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x36} },
+{ 13, 0x0e97, 0, {0xc0,0x03,0x12,0x04,0xef,0xd0,0x03,0x90,0x7f,0xea,0xe0,0xfa,0x90} },
+{  5, 0x0ea4, 0, {0x17,0x22,0xf0,0x80,0x24} },
+{  5, 0x0ea9, 0, {0xbb,0x12,0x02,0x80,0x17} },
+{  5, 0x0eae, 0, {0xbb,0x81,0x02,0x80,0x0d} },
+{  5, 0x0eb3, 0, {0xbb,0x83,0x02,0x80,0x08} },
+{  5, 0x0eb8, 0, {0xbb,0x82,0x02,0x80,0x03} },
+{  3, 0x0ebd, 0, {0xbb,0x84,0x05} },
+{  5, 0x0ec0, 0, {0x12,0x06,0x4e,0x80,0x08} },
+{  8, 0x0ec5, 0, {0x90,0x7f,0xb4,0x74,0x03,0xf0,0x80,0x06} },
+{  6, 0x0ecd, 0, {0x90,0x7f,0xb4,0x74,0x02,0xf0} },
+{  2, 0x0ed3, 0, {0xd0,0x86} },
+{ 14, 0x0ed5, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} },
+{ 13, 0x0ee3, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} },
+{ 11, 0x0ef0, 0, {0x90,0x7f,0xec,0xe0,0xf5,0x5a,0xc3,0x94,0x01,0x40,0x1d} },
+{  7, 0x0efb, 0, {0xc3,0x74,0x07,0x95,0x5a,0x40,0x16} },
+{ 13, 0x0f02, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xc6,0xf5,0x82,0xe4,0x34} },
+{  9, 0x0f0f, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0,0x80,0x22} },
+{  7, 0x0f18, 0, {0xc3,0xe5,0x5a,0x94,0x81,0x40,0x1b} },
+{  7, 0x0f1f, 0, {0xc3,0x74,0x87,0x95,0x5a,0x40,0x14} },
+{ 13, 0x0f26, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xb6,0xf5,0x82,0xe4,0x34} },
+{  7, 0x0f33, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0} },
+{  1, 0x0f3a, 0, {0x22} },
+{ 14, 0x0f3b, 0, {0x09,0x02,0xba,0x00,0x03,0x01,0x00,0x40,0x00,0x09,0x04,0x00,0x00,0x00} },
+{ 14, 0x0f49, 0, {0x01,0x01,0x00,0x00,0x09,0x24,0x01,0x00,0x01,0x3d,0x00,0x01,0x01,0x0c} },
+{ 14, 0x0f57, 0, {0x24,0x02,0x01,0x10,0x07,0x00,0x02,0x03,0x00,0x00,0x00,0x0d,0x24,0x06} },
+{ 14, 0x0f65, 0, {0x03,0x01,0x02,0x15,0x00,0x03,0x00,0x03,0x00,0x00,0x09,0x24,0x03,0x02} },
+{ 14, 0x0f73, 0, {0x01,0x01,0x00,0x01,0x00,0x09,0x24,0x03,0x04,0x02,0x03,0x00,0x03,0x00} },
+{ 14, 0x0f81, 0, {0x09,0x24,0x03,0x05,0x03,0x06,0x00,0x01,0x00,0x09,0x04,0x01,0x00,0x00} },
+{ 14, 0x0f8f, 0, {0x01,0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x07} },
+{ 14, 0x0f9d, 0, {0x24,0x01,0x02,0x01,0x01,0x00,0x0b,0x24,0x02,0x01,0x02,0x02,0x10,0x01} },
+{ 14, 0x0fab, 0, {0x80,0xbb,0x00,0x09,0x05,0x88,0x05,0x00,0x01,0x01,0x00,0x00,0x07,0x25} },
+{ 14, 0x0fb9, 0, {0x01,0x00,0x00,0x00,0x00,0x09,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00} },
+{ 14, 0x0fc7, 0, {0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00} },
+{ 14, 0x0fd5, 0, {0x09,0x04,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x07,0x05,0x82,0x02,0x40} },
+{ 14, 0x0fe3, 0, {0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00,0x09,0x05,0x89,0x05,0xa0} },
+{ 10, 0x0ff1, 0, {0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00} },
+{ 14, 0x0ffb, 0, {0x12,0x01,0x00,0x01,0x00,0x00,0x00,0x40,0x47,0x05,0x99,0x99,0x00,0x01} },
+{ 14, 0x1009, 0, {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x02,0xba} },
+{  4, 0x1017, 0, {0x00,0x03,0x01,0x00} },
+{  2, 0x101b, 0, {0x7a,0x00} },
+{  3, 0x101d, 0, {0xba,0x05,0x00} },
+{  2, 0x1020, 0, {0x50,0x17} },
+{  8, 0x1022, 0, {0x90,0x7f,0xa5,0xe0,0xfb,0x30,0xe0,0x05} },
+{  5, 0x102a, 0, {0x90,0x00,0x01,0x80,0x0d} },
+{ 10, 0x102f, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xe4} },
+{  3, 0x1039, 0, {0x90,0x00,0x01} },
+{  1, 0x103c, 0, {0x22} },
+{ 14, 0x103d, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0x00,0x7d} },
+{  4, 0x104b, 0, {0x7e,0xeb,0x60,0x12} },
+{ 14, 0x104f, 0, {0x89,0x82,0x8a,0x83,0xe0,0xa3,0xa9,0x82,0xaa,0x83,0x8c,0x82,0x8d,0x83} },
+{  4, 0x105d, 0, {0xf0,0x0c,0xdb,0xee} },
+{  8, 0x1061, 0, {0x90,0x7d,0xc3,0xe0,0x90,0x7f,0xb9,0xf0} },
+{  1, 0x1069, 0, {0x22} },
+{ 14, 0x106a, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0xc4,0x7d} },
+{  4, 0x1078, 0, {0x7d,0xeb,0x60,0xe5} },
+{ 14, 0x107c, 0, {0x8c,0x82,0x8d,0x83,0xe0,0x0c,0x89,0x82,0x8a,0x83,0xf0,0xa3,0xa9,0x82} },
+{  4, 0x108a, 0, {0xaa,0x83,0xdb,0xee} },
+{  1, 0x108e, 0, {0x22} },
+{ 14, 0x108f, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x05,0x86,0x90,0x7d,0xc1,0xe0,0x05,0x86} },
+{ 14, 0x109d, 0, {0xa3,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0x05,0x86,0xa3,0xa3,0xe0,0xf9} },
+{  5, 0x10ab, 0, {0x60,0x16,0xa3,0x05,0x86} },
+{ 13, 0x10b0, 0, {0x90,0x7f,0xa6,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xc0,0x01,0x12} },
+{  6, 0x10bd, 0, {0x10,0x1b,0xd0,0x01,0xd9,0xed} },
+{  6, 0x10c3, 0, {0x90,0x7f,0xa5,0x74,0x40,0xf0} },
+{  1, 0x10c9, 0, {0x22} },
+{  8, 0x10ca, 0, {0x90,0x88,0x02,0x74,0x01,0xf0,0x7a,0x00} },
+{  3, 0x10d2, 0, {0xba,0xff,0x00} },
+{  2, 0x10d5, 0, {0x50,0x0a} },
+{ 10, 0x10d7, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} },
+{  1, 0x10e1, 0, {0x22} },
+{  5, 0x10e2, 0, {0xe5,0x6b,0xb4,0xc0,0x08} },
+{  8, 0x10e7, 0, {0x90,0x88,0x03,0xe5,0x6c,0xf0,0x80,0x06} },
+{  6, 0x10ef, 0, {0x90,0x88,0x02,0xe5,0x6c,0xf0} },
+{  4, 0x10f5, 0, {0x7a,0x00,0x7b,0x00} },
+{ 11, 0x10f9, 0, {0xc3,0xea,0x94,0x32,0xeb,0x64,0x80,0x94,0x80,0x50,0x07} },
+{  5, 0x1104, 0, {0x0a,0xba,0x00,0x01,0x0b} },
+{  2, 0x1109, 0, {0x80,0xee} },
+{  1, 0x110b, 0, {0x22} },
+{ 10, 0x110c, 0, {0x90,0x88,0x03,0xe5,0x6d,0xf0,0x05,0x39,0x7a,0x00} },
+{  3, 0x1116, 0, {0xba,0x28,0x00} },
+{  2, 0x1119, 0, {0x50,0x03} },
+{  3, 0x111b, 0, {0x0a,0x80,0xf8} },
+{  5, 0x111e, 0, {0xe5,0x39,0xb4,0x10,0x08} },
+{  8, 0x1123, 0, {0x90,0x88,0x02,0x74,0xc0,0xf0,0x80,0x0e} },
+{  5, 0x112b, 0, {0xe5,0x39,0xb4,0x20,0x09} },
+{  9, 0x1130, 0, {0x90,0x88,0x02,0x74,0x80,0xf0,0x75,0x39,0x00} },
+{  2, 0x1139, 0, {0x7a,0x00} },
+{  3, 0x113b, 0, {0xba,0x28,0x00} },
+{  2, 0x113e, 0, {0x50,0x03} },
+{  3, 0x1140, 0, {0x0a,0x80,0xf8} },
+{  1, 0x1143, 0, {0x22} },
+{  4, 0x1144, 0, {0xe5,0x6f,0x60,0x02} },
+{  2, 0x1148, 0, {0x80,0x07} },
+{  7, 0x114a, 0, {0x7a,0x00,0x75,0x39,0x00,0x80,0x05} },
+{  5, 0x1151, 0, {0x7a,0x40,0x75,0x39,0x10} },
+{  9, 0x1156, 0, {0xe5,0x6e,0x2a,0xfa,0xe5,0x6e,0x25,0x39,0xf5} },
+{ 10, 0x115f, 0, {0x39,0x90,0x88,0x02,0x74,0x80,0x2a,0xf0,0x7a,0x00} },
+{  8, 0x1169, 0, {0xc3,0xea,0x64,0x80,0x94,0xa8,0x50,0x03} },
+{  3, 0x1171, 0, {0x0a,0x80,0xf5} },
+{  1, 0x1174, 0, {0x22} },
+{  6, 0x1175, 0, {0xaa,0x70,0xab,0x71,0xac,0x72} },
+{ 12, 0x117b, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x14,0xee,0xfd,0x60,0x18} },
+{ 13, 0x1187, 0, {0x8d,0x6d,0xc0,0x02,0xc0,0x03,0xc0,0x04,0x12,0x11,0x0c,0xd0,0x04} },
+{  9, 0x1194, 0, {0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} },
+{  2, 0x119d, 0, {0x80,0xdc} },
+{  1, 0x119f, 0, {0x22} },
+{ 13, 0x11a0, 0, {0xe5,0x73,0xc4,0x54,0x0f,0xfa,0x53,0x02,0x0f,0xc3,0x74,0x09,0x9a} },
+{  2, 0x11ad, 0, {0x50,0x06} },
+{  6, 0x11af, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} },
+{  4, 0x11b5, 0, {0x74,0x30,0x2a,0xfb} },
+{ 12, 0x11b9, 0, {0x8b,0x6d,0xc0,0x03,0x12,0x11,0x0c,0xd0,0x03,0xaa,0x73,0x53} },
+{  8, 0x11c5, 0, {0x02,0x0f,0xc3,0x74,0x09,0x9a,0x50,0x06} },
+{  6, 0x11cd, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} },
+{  4, 0x11d3, 0, {0x74,0x30,0x2a,0xfb} },
+{  5, 0x11d7, 0, {0x8b,0x6d,0x12,0x11,0x0c} },
+{  1, 0x11dc, 0, {0x22} },
+{  7, 0x11dd, 0, {0x90,0x7d,0xc3,0xe0,0xfa,0x60,0x0f} },
+{ 12, 0x11e4, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x6e,0x90,0x7d,0xc2,0xe0,0xf5,0x6f} },
+{  3, 0x11f0, 0, {0x12,0x11,0x44} },
+{ 12, 0x11f3, 0, {0x90,0x7d,0xff,0xe4,0xf0,0x75,0x70,0xc4,0x75,0x71,0x7d,0x75} },
+{  5, 0x11ff, 0, {0x72,0x01,0x12,0x11,0x75} },
+{  1, 0x1204, 0, {0x22} },
+{  2, 0x1205, 0, {0x7a,0x04} },
+{  3, 0x1207, 0, {0xba,0x40,0x00} },
+{  2, 0x120a, 0, {0x50,0x36} },
+{ 14, 0x120c, 0, {0xea,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfb,0x7c,0x00} },
+{  3, 0x121a, 0, {0xbc,0x08,0x00} },
+{  2, 0x121d, 0, {0x50,0x20} },
+{  6, 0x121f, 0, {0x8b,0x05,0xed,0x30,0xe7,0x0b} },
+{ 11, 0x1225, 0, {0x90,0x7f,0x96,0x74,0x42,0xf0,0x74,0xc3,0xf0,0x80,0x08} },
+{  8, 0x1230, 0, {0x90,0x7f,0x96,0xe4,0xf0,0x74,0x81,0xf0} },
+{  7, 0x1238, 0, {0xeb,0x25,0xe0,0xfb,0x0c,0x80,0xdb} },
+{  3, 0x123f, 0, {0x0a,0x80,0xc5} },
+{  1, 0x1242, 0, {0x22} },
+{  4, 0x1243, 0, {0x7a,0x00,0x7b,0xef} },
+{  3, 0x1247, 0, {0xba,0x10,0x00} },
+{  2, 0x124a, 0, {0x50,0x20} },
+{ 14, 0x124c, 0, {0x74,0x11,0x2b,0xfb,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0x8c,0x82,0x8d} },
+{ 14, 0x125a, 0, {0x83,0xe4,0xf0,0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe4} },
+{  4, 0x1268, 0, {0xf0,0x0a,0x80,0xdb} },
+{  1, 0x126c, 0, {0x22} },
+{ 14, 0x126d, 0, {0x74,0xf8,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
+{ 14, 0x127b, 0, {0x74,0xf9,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
+{ 14, 0x1289, 0, {0x74,0xfa,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
+{ 14, 0x1297, 0, {0x74,0xfb,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
+{ 14, 0x12a5, 0, {0x74,0xff,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} },
+{  1, 0x12b3, 0, {0x22} },
+{ 14, 0x12b4, 0, {0x12,0x03,0xcb,0x12,0x12,0x6d,0x7a,0xc0,0x7b,0x87,0x7c,0x01,0x74,0x01} },
+{ 14, 0x12c2, 0, {0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74} },
+{ 14, 0x12d0, 0, {0x01,0x12,0x14,0xbf,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e} },
+{ 14, 0x12de, 0, {0x83,0x8f,0xf0,0x74,0x06,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b} },
+{ 14, 0x12ec, 0, {0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74} },
+{ 14, 0x12fa, 0, {0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0} },
+{ 14, 0x1308, 0, {0x74,0x0b,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07} },
+{ 14, 0x1316, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74,0x08,0x12,0x14,0xbf,0x74,0x01,0x2d} },
+{ 14, 0x1324, 0, {0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x01} },
+{ 14, 0x1332, 0, {0x12,0x14,0xbf,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83} },
+{ 14, 0x1340, 0, {0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74,0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f} },
+{ 14, 0x134e, 0, {0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x03,0x12,0x14,0xbf,0x7d,0x00} },
+{  3, 0x135c, 0, {0xbd,0x06,0x00} },
+{  2, 0x135f, 0, {0x50,0x12} },
+{ 11, 0x1361, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x0a,0xba,0x00,0x01,0x0b} },
+{  7, 0x136c, 0, {0xe4,0x12,0x14,0xbf,0x0d,0x80,0xe9} },
+{ 13, 0x1373, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe5,0x74,0x12,0x14,0xbf,0x74,0xf9} },
+{ 14, 0x1380, 0, {0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x0f,0xf0,0x74} },
+{ 14, 0x138e, 0, {0xfe,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x01,0xf0} },
+{  6, 0x139c, 0, {0x12,0x03,0xe1,0x12,0x04,0xf7} },
+{  1, 0x13a2, 0, {0x22} },
+{ 13, 0x13a3, 0, {0x90,0x7d,0xc1,0xe0,0xfa,0x24,0x00,0xfb,0xe4,0x34,0x19,0xfc,0x90} },
+{ 14, 0x13b0, 0, {0x7d,0xc2,0xe0,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x75,0xf0,0x11,0xea,0xa4} },
+{  3, 0x13be, 0, {0xfa,0x7b,0x00} },
+{  3, 0x13c1, 0, {0xbb,0x10,0x00} },
+{  2, 0x13c4, 0, {0x50,0x24} },
+{ 14, 0x13c6, 0, {0xea,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0xeb,0x2c,0xfc,0xe4,0x3d,0xfd} },
+{ 14, 0x13d4, 0, {0x74,0x04,0x2b,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfe} },
+{  8, 0x13e2, 0, {0x8c,0x82,0x8d,0x83,0xf0,0x0b,0x80,0xd7} },
+{ 14, 0x13ea, 0, {0xea,0x24,0x00,0xfa,0xe4,0x34,0x18,0xfb,0x74,0x10,0x2a,0xf5,0x82,0xe4} },
+{  5, 0x13f8, 0, {0x3b,0xf5,0x83,0xe4,0xf0} },
+{  1, 0x13fd, 0, {0x22} },
+{  4, 0x13fe, 0, {0xe5,0x76,0x60,0x02} },
+{  2, 0x1402, 0, {0x80,0x16} },
+{ 12, 0x1404, 0, {0x74,0x0f,0x55,0x75,0xfa,0x8a,0x75,0x24,0x00,0xf5,0x82,0xe4} },
+{ 10, 0x1410, 0, {0x34,0x19,0xf5,0x83,0xe0,0xf5,0x74,0x12,0x12,0xb4} },
+{ 10, 0x141a, 0, {0x12,0x10,0xca,0x75,0x6e,0x00,0x75,0x6f,0x00,0x12} },
+{  6, 0x1424, 0, {0x11,0x44,0x75,0x70,0xb9,0x75} },
+{  6, 0x142a, 0, {0x71,0x14,0x75,0x72,0x02,0x12} },
+{ 11, 0x1430, 0, {0x11,0x75,0xe5,0x76,0xb4,0x02,0x04,0x74,0x01,0x80,0x01} },
+{  1, 0x143b, 0, {0xe4} },
+{  3, 0x143c, 0, {0xfa,0x70,0x0f} },
+{ 12, 0x143f, 0, {0x74,0x01,0x25,0x75,0xf5,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0} },
+{  3, 0x144b, 0, {0x02,0x80,0x0a} },
+{ 10, 0x144e, 0, {0x85,0x75,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0,0x02} },
+{ 12, 0x1458, 0, {0x75,0x6e,0x00,0x75,0x6f,0x01,0xc0,0x02,0x12,0x11,0x44,0xd0} },
+{  4, 0x1464, 0, {0x02,0xea,0x70,0x1a} },
+{ 13, 0x1468, 0, {0x75,0xf0,0x11,0xe5,0x75,0xa4,0xfa,0x24,0x00,0xfa,0xe4,0x34,0x18} },
+{  9, 0x1475, 0, {0xfb,0x8a,0x70,0x8b,0x71,0x75,0x72,0x01,0x12} },
+{  4, 0x147e, 0, {0x11,0x75,0x80,0x36} },
+{  2, 0x1482, 0, {0x7a,0x00} },
+{  3, 0x1484, 0, {0xba,0x10,0x00} },
+{  2, 0x1487, 0, {0x50,0x2f} },
+{ 13, 0x1489, 0, {0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe0,0xfb,0xe5} },
+{  4, 0x1496, 0, {0x75,0xb5,0x03,0x1b} },
+{ 14, 0x149a, 0, {0x75,0xf0,0x11,0xea,0xa4,0xfb,0x24,0x00,0xfb,0xe4,0x34,0x18,0xfc,0x8b} },
+{  9, 0x14a8, 0, {0x70,0x8c,0x71,0x75,0x72,0x01,0xc0,0x02,0x12} },
+{  4, 0x14b1, 0, {0x11,0x75,0xd0,0x02} },
+{  3, 0x14b5, 0, {0x0a,0x80,0xcc} },
+{  1, 0x14b8, 0, {0x22} },
+{  6, 0x14b9, 0, {0x50,0x72,0x6f,0x67,0x20,0x00} },
+{ 14, 0x14bf, 0, {0xc8,0xc0,0xe0,0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0b,0x14,0x60,0x0f,0x14} },
+{  7, 0x14cd, 0, {0x60,0x11,0x14,0x60,0x12,0x80,0x15} },
+{  7, 0x14d4, 0, {0xd0,0xe0,0xa8,0x82,0xf6,0x80,0x0e} },
+{  5, 0x14db, 0, {0xd0,0xe0,0xf0,0x80,0x09} },
+{  4, 0x14e0, 0, {0xd0,0xe0,0x80,0x05} },
+{  5, 0x14e4, 0, {0xd0,0xe0,0xa8,0x82,0xf2} },
+{  4, 0x14e9, 0, {0xc8,0xd0,0xe0,0xc8} },
+{  1, 0x14ed, 0, {0x22} },
+{ 14, 0x14ee, 0, {0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0d,0x14,0x60,0x0f,0x14,0x60,0x0f,0x14} },
+{  6, 0x14fc, 0, {0x60,0x10,0x74,0xff,0x80,0x0f} },
+{  5, 0x1502, 0, {0xa8,0x82,0xe6,0x80,0x0a} },
+{  3, 0x1507, 0, {0xe0,0x80,0x07} },
+{  4, 0x150a, 0, {0xe4,0x93,0x80,0x03} },
+{  3, 0x150e, 0, {0xa8,0x82,0xe2} },
+{  4, 0x1511, 0, {0xf8,0xd0,0xe0,0xc8} },
+{  1, 0x1515, 0, {0x22} },
+{  0, 0x0000, 1, {0} }
+
+};
+
+static unsigned char bitstream[] = {
+
+0x00,0x09,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0, 0x0F,0xF0,0x00,0x00,0x01,0x61,0x00,0x0D,
+0x64,0x61,0x62,0x75,0x73,0x62,0x74,0x72, 0x2E,0x6E,0x63,0x64,0x00,0x62,0x00,0x0B,
+0x73,0x31,0x30,0x78,0x6C,0x76,0x71,0x31, 0x30,0x30,0x00,0x63,0x00,0x0B,0x31,0x39,
+0x39,0x39,0x2F,0x30,0x39,0x2F,0x32,0x34, 0x00,0x64,0x00,0x09,0x31,0x30,0x3A,0x34,
+0x32,0x3A,0x34,0x36,0x00,0x65,0x00,0x00, 0x2E,0xC0,0xFF,0x20,0x17,0x5F,0x9F,0x5B,
+0xFE,0xFB,0xBB,0xB7,0xBB,0xBB,0xFB,0xBF, 0xAF,0xEF,0xFB,0xDF,0xB7,0xFB,0xFB,0x7F,
+0xBF,0xB7,0xEF,0xF2,0xFF,0xFB,0xFE,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xBF,0xFF,0xFF,
+0xFF,0xFF,0xAF,0xFF,0xFA,0xFF,0xFF,0xFF, 0xC9,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xA3,0xFF,0xFB,
+0xFE,0xFF,0xBF,0xEF,0xE3,0xFE,0xFF,0xBF, 0xE3,0xFE,0xFF,0xBF,0x6F,0xFB,0xF6,0xFF,
+0xBF,0xFF,0x47,0xFF,0xFF,0x9F,0xEE,0xF9, 0xFE,0xCF,0x9F,0xEF,0xFB,0xCF,0x9B,0xEE,
+0xF8,0xFE,0xEF,0x8F,0xEE,0xFB,0xFE,0x0B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xBF,0xFF,0xFF,0xFB,0xFF,0xFF, 0xBF,0xFF,0xFF,0xFC,0x17,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xFF,
+0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0xFF, 0xFF,0xFD,0xFF,0xFF,0xDB,0xFF,0xFD,0xFF,
+0x77,0xFF,0xFD,0xFF,0xFF,0xDF,0xFE,0xFD, 0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,
+0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,
+0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0x7F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x2F,0xFF,
+0xF3,0xFD,0xFF,0x7F,0xDE,0xF7,0xFD,0xFF, 0x7F,0xF7,0x7D,0xFF,0x7F,0xDF,0xF7,0xBD,
+0xFF,0x7F,0xFF,0x1F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xEF,0xFB,
+0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, 0x3F,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,
+0x9F,0xE7,0xFA,0x7F,0x9F,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xFF,0xFC,0x7F,0xBF,0xBF,
+0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xB7, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,
+0xFF,0xE0,0xFD,0xF9,0xFE,0x7F,0x9F,0xE7, 0xF9,0xFE,0x7F,0x9D,0xF9,0xFE,0x7D,0x9D,
+0xE7,0xF9,0xFE,0x7F,0x9F,0xED,0xED,0xFF, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,
+0xDF,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF, 0x7F,0xDF,0xFF,0x9B,0xFF,0xEF,0xFB,0xFE,
+0xFB,0xBF,0xEF,0xBB,0xFE,0xFF,0xAF,0xBB, 0xBE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF,
+0xB7,0xBF,0xDB,0xF6,0xBD,0xBF,0x6B,0xDB, 0xF6,0xF9,0xBF,0x5B,0xD6,0xF9,0xBF,0x6F,
+0xDB,0xF6,0xFD,0xBF,0xFF,0x0E,0xFF,0xFF, 0xFF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0x7F,
+0xF7,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xDF,0x9F,0xFF,0xFF,0xFF,0xFE,0xFF,
+0xFF,0xEF,0xFE,0xFE,0xFF,0xFF,0x77,0xFF, 0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F,
+0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xF4,0x7F,0xFF,0xFE,0xFD, 0xBE,0xFF,0xDF,0xFE,0xFF,0xFF,0xEF,0x7F,
+0xFF,0xCF,0xFF,0xCF,0xFF,0xFF,0xFF,0xDF, 0xE6,0xFF,0xFF,0x7F,0xDF,0xF7,0xDD,0x7F,
+0x7F,0xDF,0xF7,0xFF,0x7F,0xDF,0xD7,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFF,0xCD,0xFF,0xF2,
+0xFF,0xFF,0x4F,0x7F,0xF4,0xFF,0xFF,0xFF, 0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xBB,0xFF,0xEF,0xFF,0xFE,0xFF, 0xFF,0xFF,0xEF,0xFF,0xFF,0xEF,0xFF,0xFB,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x65, 0xEF,0xFF,0xFF,0x7F,0xFF,0xFD,0xEF,0xFF,
+0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xCF,0xDF,0xFE,0xFF,
+0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xEF,0xEB,0xFF,0xFE,0xBF,0xFF, 0xEB,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xEE,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xD6,0xFF,0xFD,0xBF,0xFF,0xFB,0xFF,0xFE,
+0xFD,0xFF,0xFF,0xFD,0xEF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0x7F,0xBF, 0xFF,0x5F,0xDF,0xFF,0xFF,0xBF,0x77,0xFF,
+0xFF,0xFF,0x7F,0xD7,0xFF,0xFF,0xFF,0xFF, 0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xDF,0xEF,
+0xFF,0xFF,0xFE,0xFB,0xFF,0xFF,0xDF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xB7,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xAF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xBF,0xDF,0xF3,0xFD,0xFB,0xFF,0x5B,
+0xFD,0xFF,0xBF,0xEF,0xF7,0xFF,0xFF,0x7D, 0xFF,0xFF,0xFF,0xFF,0xF8,0x3B,0xFF,0xBF,
+0x6F,0xFF,0xFE,0xFF,0xBF,0xFF,0xEB,0x7D, 0xFF,0xEF,0xFB,0xFE,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xF2,0x7F,0xFC,0xFF,0x3F,0xDF,0xED, 0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0x5F,0xF7,
+0xB5,0xFF,0xEF,0xFF,0xFF,0xFF,0xE0,0x3F, 0x9F,0x9E,0xFF,0xFF,0xEF,0xFF,0xDF,0xFF,
+0xBF,0x5F,0xBF,0xCF,0xF3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x69,0xAF,0x33,0xFD,0xFF,
+0xFB,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0x7F, 0xD9,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xF5,
+0xA3,0xDF,0x6E,0xDE,0xFF,0xFF,0xBD,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFE,0xE7,0xFD,
+0xFF,0xFF,0xFF,0xF9,0xEF,0xC6,0xFE,0xB7, 0xAD,0xE5,0xF9,0xFF,0xFF,0xFF,0xCF,0xFF,
+0xFF,0xFF,0xCD,0xFB,0x7F,0xFF,0xFF,0xFF, 0xF9,0xF6,0x0F,0xDF,0xEC,0xCF,0x7F,0xFF,
+0xFB,0x7F,0xFF,0xFF,0xFF,0xFD,0xFF,0xFE, 0xF9,0xFD,0x7F,0xFF,0x7F,0xFF,0xF9,0x5B,
+0xFF,0x73,0xDC,0xFD,0x7B,0xDF,0xFF,0xFF, 0xFF,0x7B,0xFF,0xFF,0xF7,0x53,0xD6,0xFF,
+0xFF,0xFF,0xFF,0xD8,0x9F,0xFE,0xFF,0xEF, 0x7F,0xEE,0xFF,0xFF,0xFF,0xFB,0xED,0xED,
+0xFD,0xFF,0xFE,0xFF,0xFF,0xFB,0x7F,0xFF, 0xE2,0x7F,0xFF,0x6F,0xD8,0x57,0xF7,0xFF,
+0xFF,0xFF,0xDF,0xFF,0xE8,0xFF,0xFF,0xFD, 0xFF,0xFF,0xFC,0x7F,0xFF,0xE4,0xFF,0xFB,
+0xEF,0xFB,0xFE,0xDF,0xB7,0xED,0xFF,0xFE, 0xDF,0x7F,0xFF,0xFE,0x7F,0xB7,0xFF,0xFF,
+0xFF,0xFF,0x89,0xFF,0xFF,0xCF,0xF3,0xFE, 0x7F,0xFF,0xEF,0xFF,0xFE,0x7E,0x7F,0xFB,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1, 0xFF,0xEB,0x7A,0xD5,0xBF,0x6F,0xDB,0xBE,
+0xFD,0xB7,0xD8,0xF6,0xE5,0xBF,0x6F,0xFB, 0xFE,0xF5,0xBD,0x7E,0x06,0xFF,0xDF,0xF7,
+0xFB,0xF6,0xFF,0x3F,0xFF,0xDB,0xFF,0xFF, 0x6F,0xFB,0xF7,0xFF,0xFF,0xFF,0xFB,0xFE,
+0xF7,0xAF,0xFF,0xB7,0xED,0xEF,0xF7,0xFE, 0xFF,0xFF,0xDF,0xFF,0xFE,0xFF,0xEF,0xFF,
+0xFF,0xFF,0xFF,0xBF,0xF7,0xFC,0x1F,0xEE, 0xFB,0xFE,0xBD,0xFF,0x7F,0x5F,0xD7,0xFD,
+0xFB,0x43,0xFF,0xFF,0xFD,0xFF,0x5F,0xFF, 0xF7,0xFF,0xF9,0x3F,0xFF,0xCF,0xF3,0xFD,
+0xF7,0x7E,0xEF,0xA7,0xF9,0xFE,0x8F,0xA7, 0xE9,0xF3,0x7E,0x9F,0xFB,0xF8,0xFF,0xFF,
+0x3F,0xFD,0x7F,0x5F,0xDF,0xFD,0xFF,0xFF, 0x5F,0xFF,0xFD,0x5F,0xFF,0xFF,0x7F,0xFD,
+0x7F,0xFD,0x9F,0xFF,0xE0,0xFF,0xFA,0xF8, 0xBE,0x6F,0x9F,0xE6,0xF8,0xBE,0x3F,0x9A,
+0xF9,0xBE,0x6F,0x9F,0xE2,0xF9,0xFE,0x6F, 0x9F,0xF9,0xFF,0xF5,0xFD,0x7F,0xCF,0xDF,
+0xFD,0xFD,0x7F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xF7,0xF5,0xFD,0x0F,0xDB,0xFF,0xD3,0xFF,
+0xEB,0xFA,0xFF,0xFF,0xBF,0xFF,0xFA,0xFF, 0xFF,0xCB,0xFB,0xFE,0xFF,0xFF,0xEB,0xFA,
+0xFE,0xFF,0xFF,0xB7,0xFF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xDF,0xF5,0xFF,0xFF,0xD7,0xFF,
+0xFF,0xFF,0xDF,0xD7,0xF5,0xFF,0x7F,0xFE, 0x4F,0xFF,0xFD,0xFF,0x7F,0x7F,0xFF,0xAD,
+0xEB,0xFB,0xFF,0xAD,0xFF,0xFF,0xFF,0xFF, 0xAF,0xEB,0xFB,0xFF,0xFC,0x0D,0xFF,0xFF,
+0xDF,0xD2,0xFD,0xFF,0xFF,0xFD,0xF6,0xFF, 0xFF,0x7F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,
+0xFF,0xFB,0x3F,0x7D,0xEB,0x32,0xFE,0xBF, 0x2F,0xEB,0xFA,0xAE,0xBD,0xE0,0xFA,0x7E,
+0xBF,0xAD,0xEB,0xFA,0xFE,0xBF,0xF5,0x7F, 0xFF,0xDE,0xFE,0xE3,0xFB,0xFF,0xFF,0xFF,
+0xDF,0xEF,0x4F,0xDF,0xFF,0x7F,0xDF,0xFF, 0xF7,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xEF,
+0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xDF, 0xED,0xFB,0xDF,0xFF,0xBF,0xFF,0xFF,0xFF,
+0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFF,0xFE,0xDD,0xFE,0xEF,0xFD,0xFF,
+0xFF,0xFB,0xFE,0xF7,0xFF,0x93,0xFD,0xFB, 0x7E,0xFF,0xFE,0x87,0xE9,0xFF,0x7F,0xB3,
+0x9F,0xFE,0xFE,0xFF,0xAF,0xFD,0xFE,0x7E, 0x3F,0xFE,0x67,0xFF,0xFF,0xF7,0xFF,0xFF,
+0xFC,0xF7,0xDF,0xFD,0xFF,0x7F,0xFF,0xFF, 0x7F,0x6D,0xFF,0xFF,0xFE,0xFF,0xFF,0x2F,
+0xFF,0xBF,0xFF,0xFF,0xEE,0xFF,0xBE,0xFF, 0xFF,0xFE,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF,
+0xEF,0xFF,0xFF,0xFA,0x5F,0xFF,0xFF,0xFB, 0xFF,0xFF,0xEF,0xFF,0xFB,0xFE,0xFD,0xFF,
+0xFE,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFE,0xBF,0xDF,0xFF,0xFB,0xFF,0xFF,0xF7,
+0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x7F,0xFF,
+0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xF3,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF,
+0xFF,0xDF,0xE2,0xFF,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xE7,0xFF,0xFD,
+0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xED, 0xEF,0xFD,0xFF,0xFF,0xDF,0xD7,0xF5,0xFD,
+0x7F,0x5D,0xFD,0xFF,0x7F,0xDF,0x97,0xF4, 0xFD,0x7B,0x5F,0xFF,0xC9,0xFF,0xFB,0xFE,
+0xFF,0xBF,0xFF,0x5F,0xFF,0xFF,0xF7,0xFF, 0xEF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xF7,0xFF,0xD7,0xFD,0x7D,0x7F,0xFF, 0xFF,0xFF,0xFF,0xEF,0xDF,0xF7,0xFD,0xFF,
+0xBB,0xFF,0xFF,0x7F,0xFF,0xFE,0xE3,0xFF, 0xF9,0xFE,0x7F,0xBF,0xEF,0xFB,0xFE,0xFF,
+0xBF,0xF9,0xFE,0xFF,0x9F,0xEF,0xF9,0xFE, 0xFF,0xBF,0xF3,0xDA,0xFF,0x37,0xCD,0xF3,
+0x7C,0xDF,0x37,0xCD,0xF3,0x7F,0x37,0xCD, 0xF3,0x7C,0xDF,0x37,0xCC,0xF3,0x7F,0x5A,
+0xBD,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFD, 0xBF,0x6F,0xDE,0xFD,0xBF,0x6F,0xDB,0xF6,
+0xFD,0xBF,0x6F,0xFE,0xF1,0x6F,0xEB,0x7A, 0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7,0xAF,
+0x7A,0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7, 0xFF,0x7E,0xFF,0xFE,0xCD,0xB3,0x6C,0xDB,
+0x36,0xCD,0xB3,0x6C,0xDE,0xCD,0xB3,0x6C, 0xDB,0x36,0xCD,0xB3,0x6C,0xDF,0xC9,0xBF,
+0xF7,0xBD,0xEF,0x7A,0x9E,0xA7,0xA9,0xEA, 0x7A,0xB7,0xBD,0xEA,0x7B,0xDE,0xA7,0xBD,
+0xCA,0x72,0x8D,0x91,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xF7,0xEF,0xFB,
+0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFE, 0x87,0xFF,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,
+0xFD,0xBF,0x6F,0xF6,0xFD,0xBF,0x6F,0xDB, 0xF6,0xFD,0xBF,0x6F,0xFE,0x4F,0xFF,0xBF,
+0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,0xEF, 0xBE,0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,
+0xEF,0xFC,0x5F,0xFF,0xFF,0xFF,0x3F,0xCF, 0xF3,0xFC,0xFF,0x3F,0xCF,0xFC,0xFF,0x3F,
+0xCF,0xF3,0xFC,0xFF,0x3F,0xCF,0xFD,0x9F, 0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,
+0xEB,0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFF,0xE1,0x6F,0xFD,0xFF,0x7F,
+0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFD,0xFF, 0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,
+0x7A,0xBF,0xFB,0xFE,0xDF,0xB7,0xED,0xFB, 0x7E,0xDF,0xB7,0xFB,0x7E,0xDF,0xB7,0xED,
+0xFB,0x7E,0xDF,0xB7,0xFF,0xC9,0xFF,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,
+0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEE, 0xFB,0xFE,0xBB,0xFF,0xFE,0xFF,0xBF,0xEF,
+0xFB,0xFE,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0x3F,0xCF,0xFF,0xE7,
+0xFE,0xFF,0xF5,0xFD,0x77,0x5D,0xD7,0x35, 0xDD,0x77,0xD7,0xF5,0xCD,0x7B,0x5D,0xD7,
+0xF5,0xDD,0x77,0xFE,0x27,0xFF,0xFF,0x8B, 0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9,0xAF,
+0x8B,0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9, 0xFE,0x1F,0xFF,0x5F,0xD7,0xF5,0xFD,0x7F,
+0x5F,0xD7,0xF5,0xFF,0x5F,0xD7,0xF5,0xFD, 0x7F,0x5F,0xD7,0xF5,0xFF,0xFA,0x3F,0xFE,
+0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xEB, 0xEC,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,
+0xEB,0xFF,0xFE,0x7F,0xFD,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6, 0xFF,0xFA,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,
+0xF7,0xFC,0xFF,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFD,0xFF,0xF5,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0x02,0xFF,0xFE,0xBF,0xAB,0xEB,0xFA, 0xBE,0xBF,0x23,0xEB,0xDE,0x1F,0xAF,0xEA,
+0xFA,0xFE,0xAF,0xAF,0xEB,0xFD,0x97,0xFF, 0xF3,0xFC,0x7B,0x1F,0xCF,0xF1,0xFC,0x7F,
+0x1F,0xF1,0xFC,0x77,0x1F,0xCD,0xF1,0xFC, 0xFF,0x1F,0xFE,0x87,0xFF,0xAF,0xEF,0xFA,
+0xFE,0xFF,0xAF,0xEF,0xFA,0xFD,0xBF,0x2B, 0xFB,0x7E,0xBF,0xBF,0xEB,0xFB,0xFB,0xFB,
+0xDF,0xFF,0xFB,0xF7,0xFF,0xFF,0x7F,0xF7, 0xF7,0xFF,0xFD,0xDF,0xFE,0xFC,0xDF,0xFF,
+0xDF,0xFF,0xFD,0xFF,0xDA,0xBF,0xFF,0xBB, 0xEF,0xFB,0xF9,0xFF,0xBE,0xEF,0xFB,0xFB,
+0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xF7,0x7F,0xFD,0xD7,0xFF,0xFF,0x7F,
+0xFF,0xFF,0xFF,0xFE,0xF7,0xFF,0xFE,0xFF, 0xF7,0xFF,0xFF,0x7F,0xFF,0xFF,0xEC,0xFF,
+0xFF,0xFE,0xDF,0xBF,0xFF,0xFB,0xFE,0xFF, 0xBB,0x68,0xAE,0x1F,0xAE,0xFB,0xFB,0xFF,
+0xFF,0xBF,0xFF,0xD5,0xFF,0x7F,0xFF,0xFF, 0xF7,0xFE,0xFE,0xFF,0xBF,0xEF,0x9F,0xFD,
+0x7F,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,0xFF, 0xBB,0xF7,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF,
+0xFF,0xBF,0xFB,0xFF,0xFF,0xFF,0xDE,0x3F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0xFF,0xFF,
+0xFF,0xFF,0xEF,0xFF,0x7F,0xFB,0xFD,0xFB, 0x7F,0xFF,0xFF,0xFF,0xFF,0xCF,0xF3,0x7C,
+0xFF,0x7F,0x8D,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFB,0xFF,0xF7,0xFB,0xFE,0xFD,0xFF,0xFF,
+0xFF,0xFF,0xF7,0xFD,0xFF,0x7F,0xFD,0x1F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xBF,0xDF,0xFF,
+0xFF,0xFE,0x5C,0xFF,0x6D,0xFF,0x7F,0xAB, 0xE7,0xF1,0xFF,0xFD,0x9F,0xFF,0xFF,0xAD,
+0xEB,0x7A,0x3F,0x1F,0xFF,0xFF,0xFE,0xBF, 0xAF,0xF3,0xDE,0xF5,0xFF,0x8F,0xFB,0xDF,
+0xE6,0x7F,0xFF,0xDF,0xF3,0xFD,0xFF,0x7E, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF7,0xF3,
+0x7F,0xDF,0xF7,0xEF,0xFF,0xF6,0x3F,0x9F, 0xDF,0xFF,0xFF,0xEE,0xFF,0xFF,0xEF,0xFB,
+0xFF,0xFF,0xF9,0xFB,0xFE,0x4F,0xBF,0xEF, 0xBB,0xFF,0x69,0xAF,0xAF,0xFC,0xFF,0x3F,
+0xDD,0xFF,0xFC,0xBF,0x8F,0xFF,0xFD,0xF3, 0xBF,0xED,0x9E,0xFC,0xBF,0x6F,0xF5,0xD3,
+0xDF,0xFF,0xDB,0xD6,0xF5,0xEF,0xFD,0xFE, 0xFF,0xB9,0xFF,0x1F,0xD2,0xA9,0xAF,0xFF,
+0xDB,0xF7,0xBF,0xEF,0x46,0xFF,0xFF,0xAD, 0xEB,0x7A,0xDF,0xEF,0xF7,0xFF,0x7F,0xF7,
+0x9F,0xED,0xFF,0x7F,0xFF,0xAD,0xEB,0x7F, 0xF5,0x6F,0xFF,0xFD,0xFB,0xD6,0xF4,0xF7,
+0xFB,0xF9,0x7E,0x7F,0xFF,0x5F,0xC2,0xFE, 0xBF,0xFD,0xFB,0x33,0xDF,0xF9,0x5B,0xFF,
+0xFF,0xDD,0x67,0x7D,0xCF,0xEF,0xDB,0xEC, 0xFF,0x77,0xDD,0xF7,0xFD,0xFF,0xFF,0xDE,
+0xA7,0xBF,0xD4,0x9F,0xFF,0xFF,0xBF,0xEF, 0xFE,0xFF,0xDF,0xEF,0xBB,0xFF,0xFF,0xEF,
+0xEB,0xFA,0xFF,0xEF,0xBD,0xFB,0xFF,0xE2, 0x7F,0xFF,0xDF,0xDF,0xF7,0xFD,0xBF,0xBB,
+0x73,0xF7,0xFD,0x7F,0xDF,0xDE,0xF7,0xBF, 0xEA,0xDB,0xF6,0xFF,0xD6,0xFF,0xFF,0x66,
+0xFF,0xBE,0xFF,0xBF,0x6B,0xD9,0xF6,0xDF, 0xFF,0xFB,0x7E,0x7F,0xB7,0x7E,0xFF,0xFE,
+0xFF,0xCD,0xFF,0xFE,0x7F,0xFF,0xFC,0xFD, 0x3F,0xFB,0xFB,0xF7,0xFF,0xFF,0xFB,0xF6,
+0x7D,0xFE,0x7F,0xFF,0xFC,0xFF,0xB9,0xFF, 0xF9,0xFA,0xFE,0xBF,0xAF,0x5B,0xD6,0xED,
+0xAD,0x7B,0xF6,0xF9,0xBF,0xEF,0xF8,0xFA, 0xFE,0xBF,0xFE,0xE6,0xFF,0xFF,0xF7,0xFD,
+0xFF,0x7F,0xBF,0xEF,0xF3,0xFF,0xFF,0x6F, 0xF7,0xFE,0xFF,0xFF,0xF7,0xFD,0xFE,0xF7,
+0xEF,0xFF,0xFB,0xEF,0xFB,0x7E,0xDE,0xFE, 0xFF,0xBF,0xFF,0xFE,0xFF,0xFF,0xFB,0xFF,
+0xFF,0xEF,0xFB,0x6F,0xFC,0x1F,0xFE,0xE7, 0xFF,0xFF,0xFF,0xEF,0xFF,0xD3,0xB4,0xBB,
+0xFF,0xFF,0xFD,0xBF,0x6F,0xE3,0xFE,0xFF, 0xBF,0xFC,0xBF,0xF7,0xCF,0xF7,0xFD,0xFF,
+0x2F,0xDF,0xAB,0xEA,0xFF,0xDF,0xE7,0xEA, 0x9A,0xAF,0xEF,0xFB,0xFE,0xFF,0xF5,0x3F,
+0xFD,0x7E,0xFF,0xD7,0xF5,0xFB,0xFF,0xFD, 0xF7,0xFF,0x7F,0xFE,0xF7,0xFD,0xFF,0xD7,
+0xFF,0xD7,0x7F,0xEE,0x7F,0xFA,0x79,0xFE, 0x2F,0x8B,0xE6,0xF9,0xFE,0x3F,0x9E,0xF9,
+0xBE,0x2F,0x0B,0xE7,0xF9,0xFE,0x2F,0x9F, 0xFD,0xFF,0xFE,0x7D,0x7F,0x5F,0xD7,0xFF,
+0xFF,0x7F,0xFF,0xFD,0xFF,0x7F,0x5F,0x97, 0xFF,0xFD,0x7F,0x5F,0xFF,0xE3,0xFF,0xFF,
+0xFA,0xFE,0xBF,0xAF,0xFB,0xFB,0xFF,0xFF, 0xCF,0xEB,0xFE,0xBF,0xAF,0xFF,0xFA,0xFE,
+0xBF,0xFF,0x87,0xFF,0xFF,0xF5,0xFF,0xFF, 0xFF,0xFF,0xFD,0xFF,0x7F,0xFF,0xFF,0xFF,
+0xFB,0xFF,0xFF,0xF5,0xFF,0xFF,0xFE,0x0F, 0xFF,0xFD,0xEB,0xFF,0xFF,0xF7,0xFF,0xEF,
+0x7B,0xDF,0xFE,0xFF,0xFF,0xDF,0xF7,0xFD, 0xEB,0x7F,0xDF,0xFF,0x5F,0xFF,0xFF,0xFF,
+0xFF,0xFD,0xBF,0xFF,0x7E,0xFA,0xBF,0xC7, 0xDB,0xF7,0xBD,0x3F,0xFB,0xFF,0xF6,0xFF,
+0xFA,0xAF,0xFF,0xEB,0xFA,0xFE,0x3F,0x2F, 0xEA,0xFA,0x3E,0xAD,0xC9,0xBA,0xF6,0xAD,
+0xAF,0xEB,0xFA,0xF6,0xBF,0xFE,0x7F,0xFF, 0xFF,0xFD,0xFF,0xF1,0x7F,0x3F,0xCF,0xF1,
+0xEF,0xFF,0x7F,0xFF,0xBC,0xDF,0xDF,0xF7, 0xDD,0xFF,0xE0,0x7F,0xFF,0xFF,0xFE,0xFF,
+0xFA,0xEC,0xBB,0x7F,0x5F,0xFF,0xFB,0xEC, 0xFF,0xEF,0xB7,0xFF,0xF7,0xFF,0xFF,0xB5,
+0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEE,0xDF, 0x5F,0xDF,0xDE,0xFF,0xAE,0xE7,0x77,0xFF,
+0xFF,0xDF,0xF7,0xFF,0xE3,0xFF,0xFA,0xBB, 0xFE,0xFF,0xAF,0xFD,0xFB,0xFE,0xBF,0xAB,
+0xF9,0xFE,0xFF,0xBF,0x7F,0xBF,0xFE,0xBD, 0xFE,0xD7,0xFF,0x9F,0xFD,0xFF,0xBE,0xEF,
+0xFF,0xEE,0xFD,0xBB,0x5B,0xEF,0xFF,0x7F, 0xEF,0xFF,0xEF,0xFF,0x7F,0xFF,0x4F,0xFF,
+0xEF,0xFB,0xBC,0xFC,0xFF,0xFF,0xFF,0xFE, 0xFE,0xFD,0xFA,0xFE,0xFB,0xFF,0xFD,0xF3,
+0xFB,0xFF,0xF8,0x5F,0xFF,0xFF,0xD7,0xF5, 0xFD,0xDF,0xEF,0xFF,0xF3,0xDC,0x5F,0xCE,
+0xF5,0xBD,0xFF,0xFF,0xD7,0xFF,0xFF,0xF9, 0x3F,0xFF,0xDF,0xF7,0xFF,0xFE,0xFF,0xFD,
+0xFF,0xFB,0xFF,0xF7,0xB9,0x7D,0xFE,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF9,0x7F,0xFF,0xFE,
+0xFF,0xFF,0x7F,0xFF,0xFE,0xFF,0xFF,0xF7, 0xF6,0xFF,0xBF,0xF1,0xF8,0xFF,0xFF,0xFF,
+0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF,
+0x9B,0xFB,0x7F,0xFF,0xFF,0xFF,0xC1,0xFF, 0xDF,0xFF,0x3F,0x5F,0xD7,0xBF,0xEF,0xBB,
+0xDE,0xEE,0xFF,0x7F,0xDF,0xFF,0xFE,0xF5, 0x7F,0xDF,0xFF,0x99,0xFF,0xFF,0xFA,0xFF,
+0xBF,0xFD,0xEB,0x7A,0xFF,0xB7,0xFE,0xFE, 0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xBF,0xFF,
+0x97,0xFF,0xFD,0xF7,0xFF,0x7F,0xF7,0xFF, 0xFF,0xFD,0x5F,0xFE,0xF3,0xF9,0xDF,0xDF,
+0xFF,0xFF,0xFC,0xFF,0xFF,0x83,0xFF,0xFF, 0xFE,0xFF,0x9E,0xEC,0xFB,0xEE,0xFF,0x9F,
+0xBF,0xEF,0xFF,0xFE,0xED,0x7B,0xFF,0xFF, 0xFF,0xF1,0x5A,0xFF,0xFF,0xFD,0xFF,0x7C,
+0x69,0x3B,0xDF,0xFF,0x7F,0x1F,0xDF,0xFF, 0xFD,0xBA,0xFF,0xFF,0xFB,0xFF,0x5B,0xBD,
+0xFF,0xFF,0xFF,0xFF,0xD7,0xB6,0xED,0xE9, 0xFF,0xD6,0xBD,0x6F,0x5F,0xFB,0xFF,0xEF,
+0xFF,0x5F,0xFE,0xF6,0x6F,0xFF,0xFF,0xFF, 0xFF,0xF7,0xEB,0x7A,0xDF,0xFF,0x9F,0x7F,
+0x7F,0xFF,0xB7,0xFF,0xFF,0xFE,0xDF,0xFF, 0x6C,0xFF,0xFB,0xFF,0xBB,0x6F,0xEB,0xFE,
+0xCC,0xF7,0xA5,0xFA,0x5C,0xF5,0x75,0xBB, 0xB7,0xDF,0xFE,0x6F,0x5F,0xC5,0xBF,0xFD,
+0x7B,0xFE,0xFF,0x95,0xE7,0x29,0xCF,0x4F, 0xF5,0x91,0xEE,0x6B,0xDF,0xEF,0xFD,0x54,
+0xF5,0xBD,0xB1,0xFF,0xEF,0xEE,0xFB,0xBE, 0xBF,0xAF,0xFE,0xDE,0xBD,0x6F,0xDA,0xF2,
+0xFF,0xAF,0xBE,0xFF,0xFF,0xFD,0x7E,0xA7, 0xFF,0xF7,0xFF,0xBF,0xEF,0x7B,0xF6,0xFD,
+0xBD,0x4A,0xF2,0x85,0x85,0xBF,0x5B,0xFE, 0xB5,0xFD,0xFA,0xFF,0x4F,0xFF,0xFE,0xDF,
+0xFF,0xED,0xFF,0xBF,0xFF,0xBF,0x7F,0xFE, 0xFF,0xB7,0x6D,0xFF,0xF7,0xBF,0xBF,0xEF,
+0xFD,0x1F,0xFF,0xFE,0x7D,0xFF,0x67,0xFF, 0xFF,0xFF,0x3F,0x7F,0xFE,0xBF,0xFF,0xE7,
+0xDF,0xE7,0xFF,0xEF,0x6B,0xFC,0x1F,0xFF, 0xBF,0xEF,0xFB,0xFE,0xDE,0xBF,0xAF,0xFA,
+0xFF,0xB6,0xEF,0xF9,0xFE,0xFF,0x8F,0xEF, 0xDB,0xEF,0xAB,0x6F,0xFB,0xFE,0xFF,0xFF,
+0xEF,0xFD,0xFF,0x7F,0xFF,0xFF,0xDE,0xFF, 0xFF,0xEF,0xFF,0xFF,0xFF,0x3F,0xFF,0x6C,
+0xFF,0xBF,0xFB,0xFF,0xFE,0xFF,0xFB,0xFE, 0xDF,0xFF,0xFF,0xEF,0xFF,0xFF,0xBF,0xFF,
+0xFF,0xFE,0xFB,0xFF,0xD5,0x7F,0xFF,0xFF, 0xEF,0xFB,0xFF,0xFF,0xBF,0xEF,0x43,0xB5,
+0xFD,0x6F,0xCF,0xD6,0xBE,0x3F,0x7F,0xDB, 0xFE,0xC3,0xFF,0xFD,0xFF,0xAF,0xEB,0xFB,
+0xFC,0xFF,0x3E,0xEF,0xE8,0xFA,0xBD,0xCD, 0xAA,0xFE,0xFE,0x7D,0xCF,0xFF,0xB7,0xFF,
+0xF7,0xFF,0xFF,0xFF,0xFD,0xFF,0x75,0xCD, 0x52,0xD7,0xFD,0xFB,0xF7,0xDD,0xFB,0xEF,
+0xEB,0xFF,0xFF,0x4F,0xFF,0xBF,0x9F,0xE7, 0xF9,0xFC,0x7F,0x8B,0xC3,0xF9,0xAF,0x8F,
+0xE7,0xE9,0xBE,0x7F,0x9F,0xE6,0xF9,0xFC, 0x5F,0xFF,0xFF,0xF7,0xFD,0xFF,0x7A,0x5F,
+0xD7,0xED,0xFF,0xFF,0xD7,0xFF,0xDD,0x7F, 0xE7,0xFF,0xFC,0xFF,0xFC,0x3F,0xFF,0xFF,
+0xFF,0xFB,0xFF,0xFE,0xBF,0xAF,0xFF,0xFD, 0xFF,0xEF,0xFF,0xEB,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xF7,0x7F,0xFF,0x7F,0xDF,0xFF,0xFD, 0xFD,0x7F,0xFE,0xF7,0xFD,0x7F,0xDF,0xFF,
+0xFD,0xFF,0xFF,0xDF,0xFB,0xFF,0xEE,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7A,0xDF,0xF5,
+0xFD,0xFA,0xDF,0xF7,0xFC,0xFF,0x7F,0xDF, 0xBF,0xED,0xFF,0xC9,0xFF,0xDF,0xFF,0xBF,
+0x2F,0xFB,0xFF,0xBC,0xAD,0xFF,0xF7,0xFF, 0xFF,0xEF,0xD3,0xFF,0x7D,0xBF,0x6F,0xFF,
+0xFA,0xFF,0xFE,0xBF,0xAE,0xEA,0xFA,0xBE, 0xAD,0xA5,0xEB,0xCE,0xBF,0xA7,0xEB,0x5A,
+0xDE,0xBD,0xAF,0x6B,0xFD,0x57,0xFF,0xFF, 0xF4,0x7F,0x1F,0x7F,0xFD,0xFF,0x7F,0x36,
+0xF0,0xDF,0x79,0xFF,0xFF,0xFF,0xF7,0xFD, 0xBF,0xFF,0x87,0xFF,0xFB,0xF3,0xFC,0xFF,
+0xFF,0xFF,0xFF,0x7E,0xFF,0xBF,0xDF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xF8,0x9F,
+0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFD, 0xF7,0xFC,0xBD,0xFF,0xFE,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFB,0xF9,0xBF,0xFF,0xFF,0xEB, 0xE2,0xFE,0xFF,0xBF,0xEF,0xA9,0xBA,0x2F,
+0xEB,0xF9,0xFE,0x77,0xDF,0xF7,0xFF,0xFF, 0xF9,0x7F,0xFF,0xFF,0x7F,0xEF,0xD7,0xFF,
+0xFD,0xFF,0xFB,0xF5,0xFF,0xBF,0x6F,0xDF, 0xFF,0xFF,0xFD,0xFF,0xFF,0xF0,0xFF,0xFF,
+0xFF,0x3F,0xCF,0xFF,0xBA,0xEE,0x9B,0xBF, 0xEE,0xD7,0xFE,0xCD,0xEF,0xFF,0xDF,0xBF,
+0xFF,0xFF,0xC5,0xFF,0xFF,0xFD,0x7F,0x4F, 0xFD,0xF6,0xD9,0xFF,0x4F,0xD6,0xFD,0xBF,
+0x6E,0xFF,0xFF,0xF4,0x7F,0xFF,0x7F,0x8B, 0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF9,0xFE,
+0x37,0xFF,0xD9,0xFB,0xF5,0xAF,0xFD,0xFF, 0xFF,0xFB,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,
+0xFB,0xF7,0xFF,0xFD,0xFF,0x7C,0xFA,0x7E, 0x4F,0xFC,0xDF,0x1D,0xC7,0xFF,0xFF,0xFF,
+0xFF,0xAE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFB, 0xFF,0xFF,0xFE,0xFE,0xFC,0xFF,0x7F,0x7F,
+0xBF,0xEF,0xFE,0xFF,0xFF,0xFF,0x5F,0xFD, 0xFF,0xFF,0xFF,0xFD,0x6F,0x5A,0xD7,0x7B,
+0xBE,0x5F,0xFE,0x39,0xFF,0xF7,0xFF,0xF7, 0xFD,0xFE,0xAA,0x1F,0xFF,0xFF,0xFF,0xFF,
+0xFE,0xFE,0xAB,0xAF,0xFD,0xFE,0xBF,0xFF, 0xF7,0xFF,0x7F,0xFE,0x8F,0xE3,0xFB,0xEE,
+0x7F,0xFF,0xFF,0xFF,0xFF,0xEB,0xFB,0xFF, 0xFD,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFB,0xE4,0x3F,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF3,0xEF,0xBB,0xFB,
+0xBF,0xEF,0xBB,0xFF,0xD7,0xBF,0xFF,0xFF, 0xFF,0x29,0xAF,0xF7,0xFF,0xFF,0xFB,0xFF,
+0xFB,0xE6,0xFF,0x0F,0xFB,0x3F,0xDF,0x0F, 0xFF,0xAF,0xFF,0xFF,0xFF,0xF5,0xC3,0xDF,
+0x5F,0xFF,0xFF,0xFF,0xFE,0x6B,0xCA,0xBE, 0xBC,0xFF,0x9F,0xF2,0xBF,0xFF,0xFE,0xFA,
+0xFF,0xFF,0xEF,0x16,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFC,0xDF,0x97,0xFD,0x79,0xFF,0x37,
+0xE7,0x7F,0xFF,0xFF,0xB5,0xFF,0xFF,0xF6, 0x2F,0xFF,0xFD,0xFB,0xFE,0xFF,0xFF,0xFD,
+0x5F,0x57,0x5F,0xFF,0xDB,0x52,0xDF,0xFF, 0xFD,0xBF,0xFF,0xFF,0xFC,0xDB,0xFF,0x7B,
+0xB5,0xFD,0x7F,0xFF,0x71,0x9C,0x6E,0xFF, 0xF6,0x35,0xA5,0x9B,0xFF,0xFF,0xFD,0xFF,
+0xFF,0xDB,0x9E,0x7F,0xFE,0xEF,0xFB,0xFF, 0xFF,0xBD,0xEF,0xFF,0xDE,0xB7,0xF9,0x4B,
+0xFF,0xF5,0xEF,0xFF,0xFF,0xFF,0xE8,0x7E, 0xFF,0xEA,0xDF,0xF7,0xFF,0xFD,0x69,0x5B,
+0xFC,0x9F,0xEF,0x78,0xD6,0xFF,0xEB,0xEF, 0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xED,0xFF,
+0xFF,0xFF,0xFF,0xE3,0xF9,0xF6,0xBF,0xFF, 0xFF,0xFE,0xDF,0xFF,0x7F,0xFF,0xFF,0xFF,
+0xD1,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF, 0xE7,0xF9,0xFF,0xBF,0x7F,0xD9,0xFF,0xFD,
+0xFE,0x7F,0xFF,0xFE,0xFF,0xF9,0xFF,0xFB, 0xD6,0xDF,0xBF,0xEF,0x5B,0xD6,0xFF,0xBF,
+0xFB,0xF6,0xFF,0xBF,0xEF,0xF8,0xF6,0xDD, 0xBE,0xFE,0x16,0xFF,0xBF,0xEF,0xFF,0xFE,
+0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0x6F,0xFB, 0xFF,0xFF,0xFF,0x6F,0xF3,0xFF,0xF7,0xEF,
+0xFB,0xFF,0xBF,0xFF,0xEF,0xFE,0xFF,0xBF, 0xFF,0xFF,0xFF,0xBE,0xBF,0xFF,0xEF,0xFF,
+0x7F,0xEF,0xFF,0xFD,0x17,0xFB,0x7B,0xFF, 0xFF,0xFD,0x7F,0xDB,0xF6,0xF4,0x7F,0xFA,
+0xFE,0xF5,0xBF,0xEB,0xE3,0xF7,0xFF,0xFF, 0xE9,0xBF,0xFF,0xAF,0xF7,0xFD,0xF3,0x7E,
+0x8F,0xA3,0xEA,0xFF,0xCB,0xF3,0xEE,0xFF, 0xBF,0xEF,0xF7,0xF9,0xFF,0xFE,0x7F,0xFF,
+0xFF,0xFF,0xFF,0xF5,0xFB,0xF6,0xFF,0xF5, 0x2F,0xFE,0xFB,0xD7,0xBF,0xFF,0xBE,0xDF,
+0x9F,0xFF,0xF0,0xFF,0xFF,0xF9,0xFE,0x7F, 0x8F,0xA3,0xF8,0xFE,0x6F,0x9F,0xF9,0xF6,
+0x2F,0x9F,0xE7,0xF9,0xFE,0x2F,0x9F,0xE1, 0xFF,0xFF,0xFF,0x7F,0xDF,0xF7,0xF5,0xFD,
+0x7F,0x7F,0xF5,0xFF,0x9F,0x5F,0xFB,0xFE, 0xFF,0x7F,0xFF,0xFF,0xCB,0xFF,0xFF,0xFB,
+0xFE,0xFF,0xBF,0xAF,0xFB,0xFE,0xFF,0xDF, 0xFE,0xFE,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xC7,0xFF,0xFF,0xFD,0xFF,0x7F,0xDD, 0xF7,0xFD,0xFF,0xFF,0xD7,0xFF,0xFD,0x7F,
+0xFF,0xFB,0xFD,0xFF,0xFF,0xFE,0xEF,0x7F, 0xFD,0xEF,0xFB,0xFE,0xFB,0xFD,0xFF,0x7F,
+0xDF,0xFD,0xFF,0x7A,0xDF,0xF7,0xFD,0xFF, 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xD3,0xF7,
+0xFF,0xFF,0x6F,0xDB,0xFF,0xFF,0xEF,0xCB, 0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+0x29,0xFF,0xE8,0xDA,0x76,0x9F,0xAF,0x6A, 0xDA,0xFE,0x35,0xEB,0xDA,0xD6,0xBF,0xAB,
+0xEB,0x7A,0xDE,0xBF,0xD7,0x7F,0xFF,0xFE, 0xFF,0xBF,0xEF,0xFD,0xDF,0x77,0xBF,0xFD,
+0x37,0xEF,0xFF,0xEF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xF7,0x7E,
+0xDF,0xFF,0xFF,0xFF,0xFA,0xB7,0x7F,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x89,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x9F,0xFB,0xFF,0xFF,0xFF,0xE7,0xFF,
+0xFF,0xFF,0xFF,0xAA,0xFF,0xAB,0xFB,0xFA, 0xEF,0xBF,0xFF,0xDF,0xFA,0x7B,0xB9,0xFE,
+0xFE,0xFF,0xFD,0xFF,0xF7,0xFE,0x3F,0xFF, 0xB7,0xFF,0xF7,0xEE,0xFF,0x7F,0xEF,0xFF,
+0xFF,0x7F,0xFF,0x1F,0xFB,0xFF,0xBF,0xFB, 0xFE,0xFF,0xBD,0xFF,0xFF,0x2F,0xFF,0xBF,
+0xFF,0x7F,0xDF,0xFA,0xFF,0xFF,0xFC,0xEE, 0xF5,0xF3,0xBE,0xFB,0x0F,0xEF,0xF3,0xBE,
+0xEF,0xFC,0x5F,0xFF,0x5A,0xFF,0xF7,0xDF, 0xFF,0xFF,0xFE,0xD5,0xFC,0x5F,0xFB,0xF2,
+0xFF,0xFF,0x2F,0xBB,0xF3,0xFF,0xFF,0xBF, 0xFF,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
+0xBF,0xFF,0xFF,0xFD,0x7B,0xFF,0xDF,0xB9, 0xFF,0xFB,0xFF,0xD8,0x7F,0xFF,0xFF,0xFF,
+0xFB,0xFF,0xFC,0x7F,0x1F,0xBF,0xE0,0xDF, 0xF7,0xEF,0xFF,0xFD,0x7F,0xFE,0xDF,0xFF,
+0xE0,0xFF,0xFF,0xFD,0xEF,0xFB,0xFF,0xFE, 0xF7,0xDF,0xFF,0xEB,0x5F,0xFF,0xF7,0xFF,
+0xFF,0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0xFD, 0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,0x3B,0xDC,
+0xFD,0x6D,0x7B,0x5F,0x57,0xF5,0xFD,0x7F, 0x5F,0xFF,0xB1,0xFF,0xEB,0xFF,0xFF,0xFF,
+0xFB,0xFB,0xFE,0xFF,0xBF,0xFB,0xBE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xAF,0xFE,0xF7,
+0xDF,0xDF,0xFF,0xFF,0xFF,0x7F,0xCF,0xF3, 0xF8,0xFF,0xD7,0xFB,0xFF,0x5F,0xBF,0xF7,
+0xFB,0xFF,0x7F,0xFE,0x23,0xFF,0xFF,0xFE, 0x7F,0xF3,0xFF,0xFB,0xFE,0xFF,0xFF,0xF3,
+0xFF,0xFF,0xF5,0xF9,0xFF,0x3F,0xFF,0xFF, 0xF0,0x9A,0xFF,0xBE,0x7F,0xFF,0xFC,0xF9,
+0xFF,0xFD,0xAF,0xEB,0xFE,0xBF,0xFF,0xCF, 0xF3,0xFE,0x7F,0xFF,0xFF,0x5B,0xBD,0xFF,
+0xBC,0xEB,0xFF,0xD7,0xD4,0xAF,0xAF,0xFD, 0xFF,0xCF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,
+0xFD,0xFE,0xFF,0x6F,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFD,0x7F,0x5E,0xFD,0xBF,0xDB,0xF6,
+0xFD,0xBF,0x6F,0xFB,0xEE,0xFD,0xFF,0x7A, 0xFF,0xFA,0xFB,0xFF,0x3F,0xFB,0xB7,0x5F,
+0xD6,0xF7,0x1F,0x71,0xDC,0x77,0x1D,0xC7, 0x31,0xDC,0x77,0xDF,0xF9,0xBF,0xF5,0x5B,
+0xF4,0xD7,0x9D,0xAE,0xFF,0xBF,0xFD,0xBF, 0xDB,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFE,
+0x3D,0x81,0xFF,0xEB,0xFE,0xFE,0xFE,0xFF, 0xEB,0x7A,0xDF,0x7D,0x77,0x7D,0xF5,0x79,
+0xDF,0x57,0xDD,0xF5,0x7D,0x7E,0xE6,0xFF, 0xD6,0x3F,0xBF,0x7F,0xFF,0xD4,0xF5,0x3F,
+0xBF,0xFB,0xBE,0xEF,0xB3,0xEE,0xFB,0x9E, 0xEF,0xBB,0xFE,0x8B,0xFF,0xFE,0xDF,0xB7,
+0xED,0xFF,0xF7,0xFD,0xFE,0xFF,0xEF,0xBB, 0xEE,0xFF,0xBE,0xEF,0xBB,0xEE,0xEB,0xFC,
+0x1F,0xFF,0xFF,0xFD,0xFF,0xE7,0xFF,0xF7, 0xFD,0xFF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB,
+0xFE,0xFF,0xBF,0xEB,0xFA,0x1F,0xFF,0xB7, 0xEF,0x5B,0xFE,0xFF,0xAF,0xEB,0xDD,0xE7,
+0xDE,0x77,0x9D,0xE7,0x79,0xDE,0x77,0x9D, 0xBF,0xE6,0x6F,0xFF,0xFE,0xFF,0xBF,0xEF,
+0xFB,0xFE,0xFD,0xBF,0x6F,0xF6,0xFD,0xBF, 0x6F,0xDB,0xF6,0xFD,0xBF,0xFF,0x7E,0xFF,
+0xFF,0xFB,0xFE,0xFE,0xFF,0xEF,0xFB,0xFD, 0xEF,0x7E,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7,
+0xBD,0xEF,0xFF,0xD5,0xFF,0xBF,0xFF,0xEF, 0xFE,0xFF,0xFC,0x3F,0x0F,0xE7,0xFE,0x7F,
+0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFE, 0xF3,0xFF,0xFE,0xDF,0xAD,0xDF,0x67,0xEE,
+0xFB,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFF,0x23,0xFF,0xFF,
+0xFF,0xFF,0x7F,0xFF,0xF3,0xBC,0xDB,0xFE, 0xFB,0xFF,0xFB,0xBE,0xF7,0xFB,0xFF,0x7F,
+0xDF,0xFF,0xCF,0xFB,0xFF,0x9F,0xE3,0xF9, 0xBE,0x3F,0x8F,0xE7,0x79,0xFF,0x9D,0xE7,
+0xF9,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x5F, 0xFF,0xCF,0xF7,0xFF,0xFF,0xFF,0xDF,0xF7,
+0xFE,0x7F,0xE7,0xF9,0xFE,0x7F,0xFF,0xFF, 0xFB,0xFE,0xFF,0xFF,0xBF,0xFF,0xBF,0xBF,
+0xFF,0xFE,0xFF,0xBF,0xEF,0xFF,0xFD,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,
+0xFF,0x3F,0xFF,0xBF,0xFF,0xF7,0xFF,0xFF, 0x7F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0xEF,0xFF, 0x5F,0xF7,0xBF,0xF9,0xFE,0xDF,0xB7,0xFD,
+0xFF,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xDD,0xFF,0xF2,0xFF,0xBF,0xFF,
+0xFF,0xBF,0xFF,0xFF,0x2F,0xF2,0xFF,0xBF, 0x2F,0x7B,0xD2,0xF7,0xBF,0x2F,0xFF,0xBB,
+0xFF,0xEE,0x8F,0xAF,0xEB,0xFA,0xFE,0x3F, 0xA7,0x69,0xCE,0x8F,0xA4,0xEA,0xFA,0xEE,
+0xB7,0xAE,0xEB,0xFD,0xC7,0xFF,0xF7,0xF7, 0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3E,0xF3,
+0x74,0xFF,0x3F,0x4F,0xFF,0xE7,0xFF,0x3F, 0xFE,0xA7,0xFF,0xFF,0xDF,0xF7,0xB7,0xFF,
+0xF7,0xFF,0xBA,0xEF,0x37,0xEB,0xFB,0xFE, 0xBF,0xFB,0xFE,0xF3,0xFF,0xF9,0xDF,0xFF,
+0xBF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFD,0xDF,0xFF,0xFD,0xFF,0xFF,0xFB,0xFE,
+0xFD,0xFF,0xFB,0xBF,0xFE,0x3F,0xED,0xFF, 0xDF,0xBE,0x3D,0xA7,0xFB,0xFA,0x3F,0xE6,
+0xE1,0xFE,0xFE,0x3F,0xEF,0xE3,0xDF,0xF5, 0x7F,0xFE,0xFF,0x7E,0xFF,0xFF,0xFF,0xFF,
+0xEF,0x6F,0xF6,0xFF,0x7D,0xEF,0xD7,0xDE, 0xFF,0x7D,0xEF,0xFF,0xF2,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0x7B,0xDE,0xFB,0xE6,0xEE, 0xEF,0x37,0x6E,0xF3,0x7E,0xEB,0x37,0xEF,
+0xFF,0xC1,0xFF,0xFE,0xFF,0xF7,0xEF,0xFF, 0xFF,0xFF,0xBF,0x3F,0xD2,0xDF,0xBF,0x2F,
+0x7B,0xE2,0xFF,0xFE,0x3B,0xBD,0xDB,0xFF, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFE,
+0xFF,0xFB,0xFF,0xFF,0xBF,0xFF,0xFB,0xDF, 0xFF,0xBF,0xFF,0xB7,0xFF,0xFF,0xBF,0xEF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, 0x7F,0xFF,0x1F,0xEF,0xF1,0xFD,0xFF,0xF6,
+0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF, 0xFF,0xFF,0xFE,0x9F,0xFF,0xFF,0xFF,0x77,
+0xEF,0xF7,0xFB,0xFF,0xFE,0x5F,0xFF,0xFF, 0xBF,0xCF,0xFB,0xF7,0xDD,0xF7,0xF5,0xFF,
+0x5F,0xD5,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5, 0xFF,0xFB,0x0F,0xFF,0xFF,0xA9,0xEA,0x7A,
+0xFF,0xAF,0x8F,0xFE,0xDF,0xAF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFB,0xDF,0xE5,0x5F,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x57,0xFF, 0xFF,0x6F,0x77,0xBF,0xF7,0xFB,0xFF,0x7F,
+0xBF,0xF7,0xFF,0xFC,0xBF,0xFF,0x9F,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF,0x1F,
+0xCF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFB, 0x65,0xAF,0xF3,0x7C,0xFF,0x3F,0xDF,0xFF,
+0xFD,0xE9,0xFE,0x7F,0xE7,0xFF,0xFE,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFD,0xE3,0xDF,0xFB,
+0xDB,0xF6,0xFD,0xEF,0x5B,0xFB,0xFF,0xDF, 0xFC,0xFF,0x3F,0xDF,0xF3,0xFD,0xFF,0x7F,
+0xDF,0xEF,0x66,0xFF,0xDF,0xAD,0xEB,0x7A, 0xDE,0xF7,0xF7,0xE7,0xD9,0xFD,0x9F,0x67,
+0xD9,0xF6,0x7D,0x9F,0xE7,0xDF,0xF5,0x47, 0xFD,0x65,0x5B,0xD6,0xF4,0xFE,0xFF,0xEF,
+0xFF,0x6D,0xF6,0xDD,0xB7,0x6D,0xDB,0x76, 0xDC,0xB7,0x7D,0xFA,0x9B,0xF6,0x6D,0x9D,
+0x67,0x59,0xDF,0xF7,0xDD,0xFF,0xEB,0xFE, 0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xE3,
+0xD1,0x9F,0xFF,0xBD,0xBF,0xEF,0xFE,0xF7, 0xBF,0xBF,0xF7,0xD7,0x7F,0xDD,0xF7,0x9D,
+0xDF,0x7F,0xDF,0xF7,0xFF,0xE0,0x7F,0xFD, 0xC1,0xDF,0xF7,0xFD,0xC7,0x7F,0x7F,0xFB,
+0xFF,0xBB,0xEC,0xFB,0x3E,0xFF,0xBF,0xEC, 0xFB,0xFF,0xD8,0x7F,0xBF,0x6C,0xFF,0xBE,
+0xFF,0xBF,0xED,0xFF,0xEF,0xFE,0xFB,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEE,0xFF,0xC5,
+0xFF,0xAF,0x6F,0xFF,0xFC,0xFD,0x3F,0xE7, 0xFF,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,
+0xEF,0xFB,0xFE,0xBF,0x89,0xFE,0xFA,0xBA, 0xFE,0xBF,0xAF,0xFB,0xF6,0xF5,0xD9,0x7D,
+0x97,0x65,0xD9,0x74,0x5D,0x97,0x65,0xD3, 0xFE,0xD6,0xFF,0xBF,0xF7,0xFD,0xFF,0x7F,
+0xBF,0xCF,0xFB,0xFE,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFF,0xF6,0x8F,0xFB,
+0xFF,0xEF,0xFB,0x7E,0xDB,0xFE,0xFF,0xBE, 0xEF,0xEE,0xFB,0xBE,0xEF,0xBB,0xEE,0xFB,
+0xBE,0xFF,0xFF,0xDF,0xFF,0x43,0xFF,0xFF, 0xFB,0xEF,0x5F,0xB7,0xFE,0x7F,0xE7,0xF9,
+0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xF9, 0xBF,0xFE,0xAF,0x77,0xFD,0xFF,0x2F,0xAF,
+0xA7,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xF1,0x7F,0xEF,0xDF,
+0xFF,0x97,0xF5,0xEF,0xFF,0xDF,0xFF,0xFF, 0xBF,0xFF,0xBF,0xFF,0xFF,0xFE,0xFF,0xFF,
+0xFF,0xE0,0xFF,0xFF,0xF9,0xFE,0x2F,0x8B, 0xE3,0xF8,0xBE,0x77,0x9F,0xF9,0xDA,0x77,
+0x9D,0xE7,0x79,0xDE,0x77,0x9F,0xDD,0xFF, 0xFD,0xFD,0x7F,0x5F,0xD7,0xFD,0xFF,0x7F,
+0xE7,0xFE,0x7F,0x97,0xE7,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFF,0xAB,0xFF,0xEF,0xFA,0xFE,
+0xBF,0xAF,0xFF,0xFA,0xFF,0xFF,0xDF,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,
+0x67,0xFF,0xF7,0xF5,0xFF,0xFF,0xFF,0xDF, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xBD, 0xEB,0xFF,0xFF,0xF7,0xAD,0xEB,0xFF,0xDF,
+0xFD,0xFF,0x3F,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0xFD,
+0xBF,0xFF,0xCB,0xF4,0xFF,0x7F,0xD3,0xF7, 0xFD,0x3F,0x7F,0xD3,0xF7,0xFF,0xFC,0x3F,
+0xFF,0xEA,0xFA,0xBE,0xAF,0xAB,0xEB,0xBA, 0xF4,0x95,0x6B,0x52,0xD4,0xAD,0x2F,0x4A,
+0xD2,0xF6,0xBF,0xD2,0x7F,0xF7,0x3F,0xFF, 0xFF,0xF3,0x7F,0xFF,0xFF,0xF7,0xFF,0xBA,
+0xDF,0xFB,0xFD,0xFF,0xBF,0xFF,0xFB,0xFF, 0xF8,0x7F,0xEA,0xFF,0xFE,0xFE,0xDF,0xFF,
+0xF7,0xFF,0x7F,0xBB,0xFF,0xFF,0xBF,0xDF, 0xFB,0xFF,0xFF,0xBF,0xFF,0xB1,0x7F,0xFF,
+0xFB,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, 0xCF,0xFE,0xFF,0xFF,0xEF,0xFF,0xF7,0xFF,
+0xFF,0xFF,0xF1,0xFF,0x69,0xBE,0xFA,0xBF, 0xAF,0xE2,0xFF,0xFE,0xFD,0xAF,0xF3,0xFE,
+0xFF,0xBF,0xEF,0xFB,0xFC,0xFF,0xFF,0x07, 0xFD,0x95,0xDB,0xDF,0x7F,0xDF,0xAF,0xFF,
+0xF7,0xAF,0x36,0xFE,0xBF,0x65,0xEB,0xF6, 0xFE,0x9F,0x6F,0xFE,0x07,0xFF,0xCF,0xFF,
+0xF8,0xFE,0xFF,0xCF,0xFF,0xF6,0xFA,0xE7, 0xFB,0xFE,0xFF,0xBB,0xED,0xF9,0xFF,0xFF,
+0xFF,0x5F,0xFF,0xFF,0xFF,0x75,0xFF,0xEF, 0x7E,0xFD,0xE0,0xE8,0x5E,0xD3,0xE5,0xF9,
+0x3E,0x5F,0xD7,0xF7,0xFF,0xFA,0x2F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0x7F,
+0x7F,0xD7,0xF5,0x7D,0x5F,0x57,0xD5,0xF5, 0xEF,0xFF,0xF3,0x7F,0xFC,0x7F,0xFF,0xC7,
+0xF1,0xFF,0xFF,0x1F,0xCF,0xB0,0xFF,0x3F, 0xCF,0xF3,0xFC,0xFF,0x3F,0xCE,0xFF,0xE4,
+0xFF,0xDF,0x7F,0xFE,0xF7,0xBB,0xFF,0xFF, 0xDF,0xEF,0xEE,0xFF,0xBF,0xEF,0xFB,0xFE,
+0xBF,0xBF,0xEF,0xFF,0xD1,0xFF,0xFF,0xFF, 0xFD,0xFB,0xFF,0xFD,0xFF,0xFB,0x9F,0xE9,
+0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xBF, 0xFF,0xB3,0xFF,0xFF,0xF7,0xFF,0xFF,0xAF,
+0xF7,0xFF,0xB6,0x3F,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFA,0xFE,0xBF,0xFE,0xA7,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF, 0xFE,0x9F,0xF7,0xF9,0xFF,0x7F,0x9F,0xE7,
+0xFF,0xFF,0xFE,0xAF,0x6F,0xFF,0xFF,0xFF, 0x9F,0xFF,0xDF,0xFF,0x7D,0x5F,0xDD,0xFF,
+0xFB,0xBF,0xE7,0xBB,0xFF,0xFB,0xDF,0x6D, 0x5F,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xEB,0xF7,0xFF,0xE7,0xEF,0xF7,0xFF,0xFF, 0x7F,0xFF,0xF7,0xFF,0xFC,0x8F,0xFF,0xEF,
+0xFD,0xFE,0xFF,0xBE,0xF4,0xF2,0x7D,0xD7, 0xCF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xCF,0x6B,0xFF,0xBF,0x3F,0xFB,0xF2, 0xFC,0x7F,0xEB,0xFF,0x9F,0xFA,0xFF,0xFF,
+0x3F,0xFF,0xF3,0xFF,0xFF,0xFD,0x70,0xF7, 0xFF,0xFF,0xBF,0xFF,0xFB,0xD7,0xFE,0xF5,
+0x77,0xFF,0x15,0xDD,0x77,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFB,0xCD,0xBF,0xFF,0xFD,0xFF,
+0xFF,0xDF,0x37,0xCD,0xF9,0xEC,0xFE,0xEF, 0xBB,0xF4,0xFB,0x3F,0x4F,0xB3,0xFF,0xFD,
+0xCB,0xFF,0xE9,0x7E,0x54,0x9F,0xE5,0x4B, 0xB7,0xFF,0xDD,0x7D,0xC7,0x71,0xDD,0x77,
+0x5D,0xD7,0x75,0xCD,0x7F,0xD6,0xFF,0xD3, 0xF6,0xF9,0x3F,0x6D,0x95,0xAF,0x7F,0xFE,
+0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xF6,0xC7,0xFF,0xAD,0x7B,0xCA,0xFF,
+0xBF,0xBF,0xEF,0xFD,0xE3,0xDF,0xB7,0xED, 0xFB,0x7E,0xDF,0x37,0xED,0xE3,0xFB,0xDF,
+0xFF,0x52,0x5C,0x15,0xFD,0xCF,0x7F,0xDF, 0xFE,0xEF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEC,
+0x7B,0xFE,0xFF,0xFE,0x3E,0x7F,0xDA,0xF7, 0xFD,0xFF,0x7F,0xFF,0xFF,0xFB,0xEF,0xBB,
+0x6F,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, 0xF7,0x7D,0xFF,0xD8,0xFF,0xFD,0xBF,0x7F,
+0xFB,0xFF,0xFF,0x9F,0xFB,0xFE,0x7F,0x9F, 0xE7,0xF9,0xFE,0x7F,0x9F,0xEA,0x7F,0xF6,
+0xBF,0xBD,0x6A,0x5A,0xF6,0xE5,0xBF,0x77, 0x5F,0x6D,0xDD,0x77,0x5D,0xD7,0x75,0xDD,
+0x77,0xFF,0xA5,0xBF,0xCF,0xFB,0xFF,0xFF, 0xBF,0xCF,0xFB,0xFD,0xFF,0xBF,0xF3,0xFE,
+0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD,0xAB, 0xFF,0xBF,0xBF,0xFF,0xFB,0xFF,0x7F,0xEF,
+0xFF,0xBE,0xFB,0xEE,0xFB,0xBE,0xEF,0xBB, 0xEE,0xFB,0xBF,0xFF,0xB5,0xFF,0xD0,0xBC,
+0xFD,0x2F,0x4B,0xF7,0xFF,0xFF,0x9F,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,
+0xFA,0x8F,0xFD,0xAB,0xFA,0xDA,0xBF,0xAF, 0xB3,0xFD,0xFF,0xBF,0xFB,0xFE,0xFF,0xBF,
+0xEF,0xFB,0xFE,0xF7,0xBF,0xFF,0x9F,0xFF, 0x77,0xF7,0xBD,0xFD,0x77,0xDF,0xFF,0x7E,
+0xDF,0xED,0xBB,0xFE,0xFF,0xBE,0xEF,0xFB, 0xFE,0xFF,0xFA,0x3F,0xFF,0xBE,0x6F,0x8F,
+0xE6,0xF9,0xFE,0x7F,0x9F,0xC7,0xFE,0x7F, 0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFB,
+0x7F,0xFF,0x7F,0xCF,0xFF,0xFD,0xFF,0xFF, 0xDF,0xFB,0xAF,0xBF,0xEF,0xFF,0xFE,0xFF,
+0x9F,0xEF,0xFB,0xFF,0xFC,0xFF,0xFB,0xFE, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF7,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF5,0xFF,0xFF,0xFF,0x3F,0xDF,0xF7,
+0xFF,0xFF,0x7F,0xEF,0xFE,0xFF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xEF,0xFF,0xB3,0x7F,
+0xFF,0x7B,0x5E,0xF7,0xFD,0xFF,0x7B,0x7F, 0xF7,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,
+0xDF,0xF7,0xFF,0x17,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xDD,0xF6,0xFC,0xBF,0xCB,0xF2,
+0xBC,0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xFE, 0x8F,0xFF,0xFA,0x7E,0xBF,0xA7,0xEB,0xDA,
+0xFC,0xBF,0xAF,0x7A,0xFE,0xBF,0xAF,0xEA, 0xFA,0xFE,0xBF,0xAF,0xF4,0xDF,0xFE,0xFF,
+0xF3,0x3C,0x7F,0x3E,0xFF,0xCF,0xF8,0xBF, 0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xE7,0xE8,
+0xFF,0xFC,0x9F,0xFF,0xFF,0xCF,0xEB,0xB3, 0xE7,0xFB,0x7B,0xF3,0xFE,0xFF,0xCF,0xDB,
+0xFB,0xFB,0xBF,0x6F,0x6F,0xDF,0xEC,0x7F, 0xFF,0xFF,0xF7,0xFD,0xFD,0xFF,0xFF,0xFF,
+0xFF,0xB2,0xBF,0xFF,0xDE,0xFD,0xBD,0xEF, 0xFB,0xF6,0xDF,0xEA,0xE7,0xDB,0xFE,0xBB,
+0xFF,0xEB,0xFB,0xBF,0x9F,0x8F,0xE8,0xFE, 0x3F,0x8F,0xA3,0xF8,0xFE,0x3F,0x8F,0xFF,
+0xF8,0x7E,0xFD,0xFD,0x7F,0xFF,0xFB,0xCD, 0xFF,0xFD,0xFF,0x5F,0xEF,0xFD,0xFF,0xFF,
+0xDF,0xF7,0xFD,0xFF,0xBE,0x90,0xFF,0xFF, 0xEE,0xFF,0x3F,0xBF,0xF3,0xBB,0xFE,0xB7,
+0xAB,0xFA,0xFE,0xAF,0xAD,0xEA,0xFA,0xDE, 0xAB,0xFF,0x63,0xFF,0xFE,0xF2,0xFF,0xB3,
+0xFF,0xDF,0xEE,0x7D,0xFF,0x03,0xF1,0xF4, 0x3F,0x1F,0xC3,0xF1,0xEC,0x7F,0xFE,0x6F,
+0xFF,0xFB,0xFB,0xFF,0x9F,0xFF,0xBF,0xFF, 0x7B,0x5F,0xFD,0xFF,0xDF,0xF7,0xFD,0xFD,
+0x7F,0x7F,0xDF,0xFE,0xCF,0xFB,0xFF,0xFF, 0xAF,0xFB,0xFF,0x1F,0xEF,0xA5,0xFD,0xBF,
+0xDF,0xFB,0x7D,0xFF,0xBF,0xDF,0xFB,0xFF, 0xFD,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,
+0xAF,0xF3,0xFF,0xFB,0x7F,0xBF,0xD7,0xFB, 0xBF,0x7F,0xBB,0xF7,0xFF,0xF8,0x7F,0xFF,
+0xFA,0x5F,0xD7,0xFF,0xDF,0x7F,0xEF,0xFF, 0xFF,0x7F,0xDB,0xF7,0xFD,0xFF,0x7F,0xDF,
+0xB7,0xFB,0xEC,0xFF,0xFF,0xF7,0xBF,0xEF, 0xFD,0xFC,0xFB,0xFF,0xEF,0xF0,0xFE,0x3F,
+0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xEF,0x8D, 0xFF,0xFF,0xEF,0x7F,0xBF,0xFF,0xFB,0xFF,
+0xDB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0xD8,0xFF,0x2E,0x7F,
+0xBE,0xEF,0xFE,0x6E,0xFF,0xBF,0xF9,0xFF, 0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFC,0x66,0xBE,0x47,0xF3,0x7F,0xDF,0xFE, 0x87,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x6F,0x7C, 0xFB,0x4F,0xD2,0xFF,0xFD,0x2B,0xFE,0xFF,
+0xFF,0xFD,0x5F,0xD7,0xD5,0xF5,0x7D,0xFF, 0xFF,0xFF,0xBF,0x9B,0xFF,0xFF,0xDF,0xB7,
+0xFF,0xFF,0xDF,0xFF,0x3F,0xCF,0xFE,0x7F, 0xBF,0xEF,0xFB,0xFC,0xFF,0x3F,0xFF,0xD9,
+0xBF,0xFE,0x97,0xEC,0x8F,0xB7,0xFE,0x9B, 0x7D,0xFD,0xB7,0xDD,0x77,0x1D,0xC7,0x71,
+0xDD,0x77,0x5D,0xD7,0xF3,0x6F,0xFD,0x3F, 0x73,0xDD,0xAF,0xFD,0x7A,0xFF,0xFF,0xAF,
+0xFE,0xFD,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0x66,0x7F,0xFF,0xFF,0xBF,0xBF,0xFF,
+0xFB,0xFF,0xF7,0xDF,0xFD,0xFB,0x7D,0xDF, 0xB7,0xCD,0xF3,0x7C,0x5F,0x3F,0x91,0x3F,
+0xFF,0x3D,0xEF,0x7B,0xFF,0xFC,0xFF,0xCA, 0xEF,0xFE,0xFF,0xBD,0xEF,0xFB,0x1E,0xE7,
+0xBB,0xEC,0x7F,0xB3,0xFF,0xFD,0x9F,0xFF, 0xFF,0xFE,0xFF,0xFF,0x7F,0xBF,0xFB,0xFE,
+0xFF,0xBF,0xEF,0xFB,0xEE,0xFB,0xBF,0xDF, 0x67,0xFF,0xFF,0xBF,0xEF,0xDB,0xFF,0xBC,
+0xFE,0x7F,0xFB,0xFF,0x9F,0xEF,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x87,0xFF,0xEE,
+0xFB,0xBE,0xE5,0xBF,0xEF,0xF9,0xD7,0x65, 0xF7,0xDD,0xE7,0x7D,0xDF,0x77,0x5D,0xD7,
+0x7F,0xF8,0x9B,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xBF,0xEF,0xFB,0xFF,0x7F,0xCF,
+0xF3,0xFC,0xFF,0xBF,0xEF,0xFF,0xDB,0x3F, 0xEF,0xFB,0xFE,0xFF,0xDF,0xFF,0xFE,0xFB,
+0xBB,0xEF,0xBF,0xEF,0xBB,0xEE,0xFB,0xBE, 0xEF,0xBB,0xFF,0xFC,0x7F,0xFD,0x3B,0x5B,
+0xD6,0xE5,0xFD,0x4F,0xC3,0xFB,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF,
+0xB4,0xFF,0xFA,0xBC,0x8F,0xB2,0xE9,0xD2, 0x2E,0xCF,0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,
+0xFF,0xBF,0xEF,0xFB,0xFF,0xEC,0xFF,0xFD, 0xFD,0x7F,0xDF,0xF7,0xE4,0xDF,0x5F,0xFF,
+0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xC3,0xFF,0xEF,0xE6,0xF8,0xFE,
+0x3F,0x8B,0x83,0xF9,0xFE,0x7F,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x17,
+0xFD,0xFF,0xFF,0xFF,0x7F,0x5F,0xF7,0x2C, 0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xE7,0xF9,
+0xFE,0x7F,0x9F,0xFE,0x2F,0xFF,0xFF,0xEF, 0xFF,0xFE,0xBF,0xEF,0xAD,0xFF,0xFF,0x7F,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFE,0xDF,0xFF,0xDF,0xFF,0xFD,0xFD,0x7F,
+0xDF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x3F,0xFE,
+0xF7,0xFD,0xEF,0x7A,0xFF,0xB1,0xBD,0xFF, 0x7F,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,
+0xFF,0x7F,0xF3,0x27,0xFF,0xDF,0xFF,0xDD, 0xFF,0xFC,0x9B,0xFF,0xCB,0xFC,0xBF,0x2F,
+0xCB,0xF2,0xFC,0xBF,0x2F,0xC9,0xFF,0xDE, 0xFF,0xDF,0xAF,0xEB,0xDA,0xFE,0xBB,0xAF,
+0xEB,0xF8,0xF7,0xAF,0xE8,0xFA,0xFE,0xBF, 0xAF,0xEB,0xF2,0xFF,0xFD,0xFF,0xFF,0xEF,
+0xBD,0xD7,0xBF,0xFF,0xFF,0xDE,0x8F,0xB8, 0xDE,0x37,0x8D,0xA3,0x78,0xDA,0x3F,0x8F,
+0xFF,0xA1,0xFF,0xFF,0xFB,0xFB,0xFF,0xFF, 0xFF,0xFF,0xA7,0xBD,0xFB,0x76,0xFD,0xBF,
+0xEF,0xDB,0xFE,0xBB,0xBF,0xFE,0x27,0x7F, 0xFF,0xFE,0xFE,0xFD,0xF5,0xFF,0xEF,0xF5,
+0xDF,0x1F,0xE7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xFF,0xCD,0xFD,0xAE,0xFF,0xFA,
+0x3E,0x3F,0xAB,0xFD,0xF8,0x7E,0x8F,0xE3, 0xF8,0xFE,0x3E,0x8F,0xE3,0xF8,0xFF,0xFE,
+0x1F,0xEF,0xDF,0xBF,0xFE,0xDE,0xDF,0xD9, 0xFF,0xDF,0xBC,0xFF,0xFF,0x7F,0xFF,0xEF,
+0xFD,0x7F,0xDF,0xF7,0xF9,0x3F,0xFE,0xFF, 0xFF,0x6F,0xFE,0xDE,0xBF,0xF7,0xED,0xEA,
+0xFD,0x8F,0x83,0xF8,0xEA,0x3F,0x8F,0xEF, 0xFF,0xF4,0x7F,0xFF,0xEF,0xEF,0x7B,0xF3,
+0xF1,0x5F,0xFF,0xFF,0xF1,0x3B,0x7F,0xDF, 0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,
+0xFF,0xFF,0xF7,0xFF,0x6F,0xFF,0x7F,0xFF, 0xFF,0xF7,0xDE,0xF7,0xBF,0xEF,0xFB,0xF7,
+0xFD,0xFF,0xFF,0xF5,0xFA,0xFF,0xFF,0xFB, 0xE7,0xFF,0xF3,0xF8,0x7F,0xF3,0xDF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0xEF, 0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,
+0xFF,0x7F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xCF,0xFF,0x37,0xFF,0xFF,
+0x7F,0xDF,0x77,0x5D,0xE7,0xFC,0xFF,0xBF, 0xF7,0xF5,0xFB,0xFF,0xFF,0xD7,0xF5,0xFB,
+0xFF,0xFF,0x45,0xFD,0x7F,0xEA,0xFD,0xBE, 0xBF,0xDF,0xF7,0xFF,0xFF,0xDB,0xFB,0xFE,
+0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFB,0x5F, 0x7F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFE,0xFF,0xEF,0xFD,0xFF,0x7F,0xDF, 0xFF,0xEF,0xFB,0xF8,0x0F,0xF3,0xFF,0xF9,
+0x2E,0xFB,0xFE,0xFC,0xF3,0xEF,0xFF,0xFF, 0xBF,0xFF,0xFB,0xE7,0xFF,0xFE,0x7E,0xFF,
+0xC0,0x6B,0xCF,0xFF,0x34,0xDF,0xF1,0xFD, 0xFF,0xEF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFD,
+0xCF,0x7F,0x9C,0xFD,0xFD,0x6C,0xF7,0xFF, 0xF6,0xFD,0xEB,0x2B,0x9F,0xFF,0xFC,0xFE,
+0x7E,0xFF,0xFF,0xFF,0xFF,0xD7,0xF3,0xF7, 0xFF,0xFB,0xE1,0xBF,0xFF,0xEB,0x7A,0xDE,
+0xD7,0xFB,0xFF,0xF9,0xFE,0xFF,0xFF,0xF3, 0xDE,0x7F,0xFD,0xE7,0x7F,0xFF,0xFD,0xBB,
+0xFF,0xFF,0x7E,0xCC,0xF6,0xAF,0x5F,0x7F, 0xFE,0xF4,0x7D,0xF7,0xFD,0xBB,0x6E,0xDB,
+0xB7,0xFF,0xF7,0xDF,0x66,0xFF,0xFF,0xF7, 0x3D,0xCF,0xDE,0xBD,0xFF,0xFF,0xDE,0xDB,
+0x8D,0xF7,0x7E,0xDF,0xB7,0xEF,0x7F,0xFF, 0xF6,0x87,0xFF,0xFF,0xEF,0xFE,0xDE,0xBF,
+0xFF,0xFF,0xFF,0xBB,0xEF,0xFD,0xFF,0x7B, 0xDE,0xF7,0x3F,0xFF,0xBF,0xFB,0xDB,0xFF,
+0xF2,0xB6,0xFD,0xBD,0x7F,0xE7,0xFF,0xFF, 0xFF,0x6F,0xF7,0xFF,0xFF,0xFF,0xFE,0x77,
+0xFF,0xBF,0xF8,0xAF,0xFF,0xDF,0xBF,0xFF, 0xBF,0x7F,0xFB,0xFF,0xFF,0xFF,0xDB,0xFE,
+0xFF,0xBF,0xFF,0xFA,0xFF,0xFD,0xFF,0xF6, 0x7F,0xFF,0x9F,0xFF,0xFF,0x3F,0xEF,0xF8,
+0xEE,0x7E,0x9F,0xBA,0xFE,0xBF,0x8F,0xEF, 0xFE,0xFE,0xF9,0xFF,0xFA,0x7F,0xFE,0x7E,
+0xBF,0xAF,0xFB,0x96,0xFD,0x9F,0xEF,0x5E, 0x65,0xBE,0xEF,0x5B,0xB6,0xFF,0xBE,0xE3,
+0xFF,0xB5,0xBF,0xFF,0xFD,0xFF,0x7F,0xFF, 0xEF,0xDF,0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,
+0xBF,0xCF,0xFF,0xFF,0xFF,0xFD,0x9B,0xFF, 0xFE,0xFB,0xFE,0xDF,0xFF,0x7F,0xFF,0xF7,
+0xFE,0xFF,0xDF,0xFB,0xFB,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xB7,0xFE,0xFA,0xFF,0xAB,
+0xEF,0xFF,0xFD,0xB5,0x7B,0x7F,0xFB,0xF7, 0xFD,0xFF,0xFF,0xDD,0xFF,0xEF,0x8F,0xFF,
+0x2F,0xFF,0xFB,0x7C,0xFF,0x3F,0xDF,0x73, 0xEB,0xFE,0x3F,0xFF,0xEF,0xFB,0xFE,0xFF,
+0xEF,0xFD,0xFF,0xBF,0xFD,0x0F,0xFF,0xFF, 0xFF,0xF5,0xF9,0xFF,0x7F,0xD7,0xFD,0xFF,
+0xDF,0xFF,0xF7,0xFB,0xFF,0x7F,0xBF,0xFF, 0xFF,0xF0,0x9F,0xFF,0xFE,0x7F,0x8B,0xE3,
+0xF9,0xDE,0x27,0x9B,0xE6,0xBE,0x7F,0x9B, 0xC3,0xF8,0xDE,0x7F,0x9D,0xE7,0xFE,0x7F,
+0xFF,0xFF,0x5F,0xD7,0xFF,0xFF,0xFF,0x4F, 0xFB,0xFF,0xFF,0x7F,0xFF,0xAF,0xFF,0x9F,
+0x7F,0xFB,0xFF,0xE8,0xFF,0xFF,0xFE,0xBF, 0xAF,0xFF,0xFF,0xFE,0xBF,0xEF,0xF7,0xFF,
+0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFC,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,
+0xFD,0x3F,0xCF,0xFF,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFD,0x7F,0xFF,0xFF,0x93,0xFF,0xFF,
+0x7A,0xDF,0xF7,0xFF,0xFF,0x7B,0x7F,0xB7, 0xEF,0xFF,0xFF,0xFD,0xBF,0xFD,0xFB,0xFF,
+0xF7,0xFF,0xD7,0xFF,0xFF,0xFF,0xFC,0x9F, 0x6F,0xCB,0xFF,0xF4,0xBB,0xDF,0xD6,0xFD,
+0xBF,0x2F,0xD3,0xF7,0xFF,0xDF,0xFF,0xCF, 0xFF,0xFA,0xBE,0xBD,0xAF,0x6A,0xDA,0xBE,
+0xBB,0xAB,0x3A,0xBE,0x2D,0xAE,0xEB,0xDA, 0xF6,0x3F,0xAD,0xF5,0xDD,0xFF,0xCF,0xF1,
+0xFF,0xF9,0x7F,0xFF,0x73,0xFE,0xFF,0xCF, 0xC3,0xF4,0xF7,0x2F,0xF3,0xFF,0xFC,0xFF,
+0x7C,0x1F,0xFF,0x3F,0x4F,0xFF,0x7E,0xFF, 0xEF,0xBD,0xF6,0xFE,0xFF,0x2B,0xEF,0xDC,
+0xFB,0xFD,0xFF,0xFB,0xFF,0xEA,0x7B,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xF7,0xDF,0xFF,
+0xE3,0x7D,0xFF,0xB7,0xFF,0xBF,0xFF,0xFF, 0xDF,0xFF,0xF8,0xFF,0xBF,0xFF,0xBF,0xEB,
+0xE7,0xFA,0xFE,0x3D,0xBF,0xE9,0xFC,0xBF, 0xFF,0xFA,0xFB,0xFE,0xFF,0xFF,0xFF,0xD9,
+0xFF,0xFF,0xFF,0xF6,0x7F,0xFF,0xF6,0x7D, 0xFF,0xDF,0xCF,0xFD,0xBF,0xFB,0xEF,0x7E,
+0xFF,0x7F,0xFF,0xFF,0xD3,0xFF,0xFD,0xFB, 0xFF,0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xBF,
+0xFE,0xFF,0xF7,0xEF,0xFF,0xFF,0xFF,0xFB, 0xFF,0x87,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,
+0x7B,0xFE,0xFF,0xFE,0x3B,0xF7,0xF7,0xFF, 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,
+0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFF,0xAD,0xFF,0xFE,0xF7,0xFF,0xFF,
+0x5F,0xFF,0xFF,0xDF,0xFF,0xFD,0xFF,0xF5, 0xFF,0xDF,0xFF,0xBD,0xFF,0xE9,0xFF,0xC7,
+0xF3,0xFF,0xFF,0xF7,0xFF,0xF3,0xFF,0xF8, 0x3B,0xFF,0xFF,0x7B,0xDF,0xBF,0xFB,0xEF,
+0xFB,0xFF,0xFB,0xF7,0xF7,0xBB,0xFF,0xFF, 0xFF,0xFF,0xFB,0xFF,0xFE,0x7F,0xF3,0x7F,
+0x5E,0xB7,0xBF,0xFD,0x7F,0xFF,0xF9,0x7F, 0xFB,0xFF,0xEB,0xFD,0x7F,0x7F,0xFF,0xEF,
+0xFB,0xE0,0x3F,0xFE,0xBF,0xBF,0xDF,0xFF, 0x7E,0xFF,0xF7,0xFF,0xFF,0xFE,0xBF,0xFF,
+0xDB,0x78,0xFF,0xFF,0xFF,0xEE,0xA1,0xBF, 0xF5,0xDE,0xFB,0xF7,0xFF,0xFB,0xFF,0xFF,
+0xFF,0xFF,0xFB,0xFF,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xEF,0xF0,0xFF,0xFF,0xFF,0xF3,
+0xF7,0xFF,0xEF,0xFF,0xE7,0xCF,0xFF,0xFB, 0xFF,0xEF,0xFF,0xFF,0x9F,0x9F,0xEF,0xFC,
+0x16,0xBF,0xFE,0xF3,0xE4,0xFF,0xFF,0xC6, 0xFF,0xE7,0xFF,0xFF,0xFD,0xFF,0xBF,0xFF,
+0xFF,0x3F,0xFF,0xBF,0xD6,0xAF,0x7F,0xFE, 0x6B,0x7E,0x7F,0xFF,0xAF,0xFF,0xFF,0xBF,
+0xFF,0x5F,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF, 0xFF,0xBD,0xDB,0xFF,0xFE,0x5F,0xF2,0xFF,
+0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xEF,0x7F,0xFF,0xFF,0xFF,0xFF,0xDE,0xBF,
+0xFF,0xFF,0xEF,0xFB,0x77,0xFE,0xBD,0x7F, 0x5F,0xFF,0xFF,0xFF,0xDF,0x6F,0xED,0xFF,
+0xFD,0xFF,0x7F,0xFD,0x6F,0xFF,0xFF,0x77, 0xDA,0xCF,0xFD,0x5F,0xFF,0xBF,0xFF,0xFF,
+0xDF,0x7F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, 0x66,0x7F,0xFF,0xFE,0xBF,0xE7,0xBF,0xFA,
+0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0x59, 0xEF,0xFF,0xEF,0xFB,0x7F,0x89,0xFF,0xFF,
+0xE9,0xFF,0x6F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xFF,0xFF,0x7F,0xF2,0xF7,0xFF,0xFF,0xEF,
+0xF8,0x7F,0xFB,0xFF,0xFD,0xFF,0xFF,0xD9, 0xFF,0xEF,0xBB,0xFF,0xFF,0xFF,0xBF,0xEF,
+0xDE,0xFF,0xFF,0x9F,0x7F,0xDF,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xAF,
+0xFF,0xFF,0xF7,0x3F,0xEB,0x9F,0xFE,0x7F, 0x9E,0x7F,0x9F,0xFE,0x87,0xFF,0xED,0xDB,
+0x56,0xFF,0xBF,0xAF,0x0B,0xD2,0xFF,0xEF, 0xDB,0x6E,0x7D,0xBD,0x6F,0xF8,0xFE,0x3F,
+0xFA,0x5B,0xFF,0xFD,0xBF,0xEF,0xFF,0xBF, 0x6F,0xDB,0xE6,0xFF,0xFF,0x3F,0xFF,0xDF,
+0xFE,0xFF,0xFF,0xFF,0xFF,0xDA,0x3F,0xFF, 0xFB,0xFE,0xFE,0xFF,0xFF,0xDF,0xF7,0xBD,
+0xFF,0xFD,0xFF,0xFE,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xF1,0x5F,0xFD,0x9F,0xDF,0xFD,
+0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,0xFF,0x76, 0xFA,0xFF,0xFF,0x7F,0xE3,0xF8,0xFF,0xAE,
+0xFF,0xFB,0x7E,0x9D,0x73,0xFF,0xFA,0x7F, 0xDF,0xFF,0xFF,0x7F,0xFF,0xFB,0xCD,0xFF,
+0x7F,0xEF,0xFB,0xFF,0xFD,0xFF,0xF7,0x7F, 0x7F,0xEF,0xFF,0xED,0xFF,0xFF,0xFF,0xB5,
+0xFF,0xBF,0xFF,0xBF,0xFD,0xEF,0xDB,0xF7, 0xFF,0x93,0xFF,0xEF,0xE2,0xF9,0xBE,0x7F,
+0x8B,0xE7,0xF9,0xFE,0x6B,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x47,0xFF,
+0xFF,0xFD,0xFF,0x9F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xF5,0xFF,0x9F,0xFF,0xF7,0xFE,
+0xFF,0xBF,0xFE,0x6F,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xAF,0xFF,0xFF,0xFF,0x7F,0xFB,
+0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xDF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xDF,
+0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,0xFF,0xFF, 0x5F,0xFB,0xFE,0xFF,0xF8,0x37,0xFF,0xFF,
+0xEF,0xFF,0x7F,0xFE,0xBF,0xFF,0xFF,0xFE, 0xBF,0xFF,0xFF,0x7F,0xFF,0xBF,0xFD,0xFF,
+0x7F,0xFA,0x7F,0xFF,0xFF,0x6F,0xFF,0xFF, 0x7D,0xFF,0xCF,0xFF,0xFF,0xFF,0x4F,0xFF,
+0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xBF, 0xFF,0xAE,0xEB,0xFA,0xFE,0xBB,0xAD,0xEB,
+0xFA,0xF7,0xAF,0x6B,0xFA,0xF6,0xBF,0x25, 0xE9,0xF2,0x7F,0x45,0xFF,0xFF,0xFD,0xF7,
+0xF7,0xBF,0xFF,0xDF,0xFF,0xFF,0xBF,0xFB, 0xFF,0xDF,0xF3,0xFF,0xF7,0x3F,0xCF,0xFF,
+0xA1,0xFF,0xFF,0xBF,0xE7,0xFF,0xFF,0x7F, 0xFF,0x3D,0xFF,0xFF,0xFF,0xF7,0xFF,0x2F,
+0xFF,0xFB,0xF5,0x7F,0xFE,0x57,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,
+0x3F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,0xFE, 0xF7,0xEE,0xAF,0xFE,0xEE,0xE7,0xFA,0xFF,
+0xFE,0x9D,0xF9,0x5E,0xFE,0xFF,0xEB,0xFF, 0xFF,0xDF,0xA7,0xFF,0xFF,0xFF,0xFC,0xDB,
+0xFF,0xFF,0xFF,0x7E,0xFB,0xFF,0xFF,0xEF, 0xFB,0xFD,0xFF,0xDB,0xFF,0xFF,0xFF,0xEF,
+0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,0xBF,0xFF, 0x6F,0x7F,0xFF,0xF7,0xFF,0xFF,0xF9,0xFF,
+0xF7,0xFF,0xBF,0xDE,0xF7,0xFF,0xFF,0xFF, 0xFA,0x7F,0xFD,0xBF,0x5F,0xFF,0xFF,0xBF,
+0xFF,0xED,0xFF,0xF7,0xBF,0xFF,0xFF,0xEF, 0xFF,0xDF,0xFF,0xFF,0xFF,0xE6,0xFF,0xFB,
+0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,
+0xFD,0xFF,0xF5,0xFF,0xF6,0x7F,0xDF,0xBD, 0xCF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,
+0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3, 0xFF,0xEE,0xBF,0xFF,0x7D,0xEF,0xFE,0xFF,
+0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xB5,0xAE,
+0xFF,0xFF,0xB6,0xFE,0xBF,0xFF,0xFF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0x27,0xFF,0xEF,0xFE,0x7F,0xDF,0xFF, 0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFD,0xFF,0xF7,0xF9,0x9F,0xFF, 0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
+0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x0F,0xFF,0xE7,0xBF,0xFE,
+0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBF, 0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xC4,
+0x6B,0xFF,0x29,0x1F,0xFB,0xAF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0x1B,0xFE,0xFF,0xFC,
+0x6F,0xFF,0xFF,0xFD,0x6A,0xF7,0xD7,0xF5, 0xBF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFE,0xBF,0xFF,0xFF,0xFA,0xFF,0xFF,0xF7, 0xFB,0xDD,0xBF,0xFF,0xE7,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7F,0xFF, 0xFF,0xF5,0xFF,0xFF,0xF7,0xFD,0xB3,0xEF,
+0xFD,0x7E,0x5D,0xFF,0xFD,0xFF,0xFF,0xFF, 0xFD,0x7F,0xD2,0xF5,0xFB,0x7E,0xCB,0xB7,
+0xFF,0xFF,0xFF,0xC6,0xFF,0xFD,0xEE,0x63, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFD,0x65,
+0x5B,0xDF,0xFF,0xD5,0xFF,0xFF,0xFF,0xF6, 0xE7,0xBF,0xF7,0xA9,0xFF,0xFF,0xED,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFF,0xFF, 0xAF,0xFF,0xFF,0xFF,0xF8,0x1B,0xFF,0xE3,
+0xD0,0xBF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF, 0xFF,0xD7,0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,
+0xFF,0xFF,0xAF,0xFF,0xDB,0x76,0xBF,0xFF, 0x7F,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,
+0xFB,0xFE,0xFF,0xFF,0xFF,0xBF,0xF2,0x7F, 0xFF,0x9F,0xFE,0xBD,0xFE,0x7F,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF7,0x3F,0xEC,0x7F,0xF6,0x95,0xBB,
+0xEF,0xF8,0xFE,0xFC,0xBF,0x2F,0xDA,0xFC, 0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xEF,0xFF,
+0xA9,0xBF,0xCF,0xFB,0xFF,0xFF,0xFF,0xFE, 0xDD,0xB7,0x6D,0xF6,0xD9,0xB6,0x6D,0x9B,
+0x76,0xD9,0xBF,0xFB,0xFD,0xA3,0xFF,0xBF, 0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0x7F,0xDF,
+0xFD,0xEF,0x7B,0xDE,0xF7,0xFD,0xEF,0x7F, 0xFF,0xFF,0x05,0xFF,0xFA,0xFE,0x7F,0xEF,
+0xE3,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, 0xFF,0x5F,0xFF,0xFF,0xFD,0x7F,0xFB,0xAF,
+0xFF,0x63,0xC8,0xFF,0xBF,0xEF,0xFF,0xFF, 0xFA,0x7F,0xFF,0xFF,0xFF,0xFE,0x9F,0xF7,
+0xFF,0xFA,0xBF,0xFE,0x9F,0xFB,0x7F,0xFF, 0xFF,0xEF,0xD7,0xFF,0xFF,0xF5,0xFF,0xFF,
+0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xBF,0xFF, 0xF9,0xBF,0xFF,0xBE,0x27,0x9F,0xE7,0xF9,
+0xFE,0x7F,0x8B,0xE7,0xFE,0x7F,0x9F,0xE2, 0xF9,0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,
+0xFF,0xFF,0xFB,0xFE,0xFF,0xFF,0xFF,0xD7, 0xFF,0xFF,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF,
+0xD7,0xFF,0xFA,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF,0xAF,0xF7,0xFF,0xFF,
+0xFF,0xEB,0xFF,0xFF,0xFF,0xAF,0xFF,0xC4, 0xFF,0xF7,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,
+0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xD7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFB,0x7A,
+0xDF,0xF7,0xFD,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0x7F,0xFF,0xAF,0xFF,0xFF,0xFF,0xF7,
+0xEF,0xE3,0xFF,0xDD,0xD2,0xFF,0xDF,0xFF, 0xFF,0xF2,0xFC,0xBF,0xCB,0xF6,0xFD,0xBF,
+0x2F,0xCB,0xFF,0x7F,0xDF,0xDE,0xAF,0xFF, 0xDA,0xEE,0xBF,0xAF,0xE9,0xFA,0xF4,0xBD,
+0xAF,0x5A,0xAE,0xBB,0xAB,0x6B,0xDA,0xDE, 0xBF,0xAD,0xD7,0x5E,0xFF,0xFF,0xBF,0xFC,
+0xFF,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xDF, 0xF7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFA,
+0x1F,0xFF,0xFE,0xFB,0xEF,0xBF,0xFD,0xFF, 0xFD,0xBD,0x77,0xFF,0xFF,0xFF,0xFF,0x9D,
+0xEF,0xFF,0xFF,0xFF,0xEF,0x7D,0xFF,0xFB, 0xFE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE, 0xBF,0xE4,0xFB,0xFF,0xFE,0x3F,0xFE,0xFF,
+0xFF,0xFF,0xFF,0xAF,0xEA,0xFE,0xBF,0xAF, 0xEB,0xFA,0xFE,0xFF,0xFF,0xFF,0x55,0xF6,
+0xFF,0xFE,0xF7,0xFF,0x7F,0xFF,0xEB,0xF7, 0x5F,0xC5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF,
+0x6F,0xFB,0xFF,0x8A,0xFF,0xFF,0xFF,0xFF, 0xEB,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xBF,
+0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0x77,0xDF,0xFB,0xFF,0xFD,0x7F,0xEF,0xFF,
+0xFF,0xFF,0xBF,0x7F,0xFF,0xDF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xFF,0xFE,0xEF,0xDF,0xFF,
+0xFE,0xFF,0x9F,0xEF,0x7D,0xFF,0xF7,0xFF, 0x7F,0xFF,0xFF,0xDF,0xF7,0xFD,0xFF,0xEF,
+0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB,
+0xFD,0xFF,0xBF,0xDF,0xD1,0xFF,0xF8,0x3B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0x7E,0xDB,0xFD,0xFF,0x77,0xDB,0xB7,0x7D, 0xBF,0xFB,0xFF,0xF8,0x7F,0xED,0x7B,0x5E,
+0xFF,0xFE,0xFF,0xFF,0x4F,0xD7,0xFD,0x7F, 0xDF,0xD7,0xF5,0xFF,0x7F,0xFF,0xFF,0xFF,
+0xF2,0x3F,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFF,0xBF,0xEF,0xFE,0xFF,0x3B,0xEE,0xFF,
+0xFC,0xEF,0xFF,0xFF,0xFF,0x85,0xFF,0xFD, 0xFE,0xFF,0xF5,0xFF,0xFF,0xFE,0xFF,0xDF,
+0xFB,0xFF,0x5F,0xBF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xA8,0xFF,0xFF,0x9F,0x9E,0xFF,
+0xFF,0xFF,0x7F,0xF3,0xFF,0xFF,0xCF,0xFF, 0xF7,0xFD,0xFF,0x7F,0xFF,0xFF,0xFC,0x16,
+0xBF,0xCF,0xA3,0xE5,0xEF,0x7F,0xFF,0xF3, 0xE4,0xFF,0xCF,0x93,0xFC,0xFF,0x3F,0xCF,
+0xFF,0xFF,0xFF,0xD6,0x0F,0x7D,0xBF,0x6E, 0xFB,0xF4,0xFC,0xAF,0x6D,0xDB,0x77,0xB7,
+0x6D,0xDB,0xF6,0xFD,0xBF,0xFF,0xFF,0xFF, 0xBF,0x9B,0xFA,0xDE,0xB7,0xB7,0xED,0xF9,
+0x7E,0xB7,0xAC,0xEB,0xD6,0xB3,0xAD,0xEB, 0x7A,0xDF,0xFF,0xFF,0xFF,0xD8,0xBF,0xFF,
+0xB7,0xED,0x9F,0x6F,0xDD,0xF7,0x68,0xDB, 0x37,0xB3,0x6C,0xDB,0x36,0xCD,0xB3,0x7F,
+0xFF,0x7F,0xF5,0x6F,0xFD,0xEF,0x79,0x3D, 0xF7,0x93,0xE4,0x7A,0x9E,0xAD,0xEA,0x7A,
+0x9E,0xF7,0xBD,0xEF,0xFF,0xFF,0xFF,0x76, 0x7F,0xFB,0xC6,0xFF,0xBB,0xEF,0xDA,0xFE,
+0xFD,0xBF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xFB,0xFF,0xA5,0xFF,0xFD,0xAB,
+0x6F,0x78,0xDE,0x17,0x8F,0x79,0xDF,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xFF,0xFB,
+0xFF,0xFB,0xFF,0xEF,0xFB,0xEF,0xFB,0xFE, 0xFF,0xBB,0xDA,0xF3,0xEF,0x3B,0xCE,0xF3,
+0xBC,0xEF,0x3F,0xCF,0xDF,0xFF,0xB7,0xFF, 0xFF,0xFF,0xCF,0x73,0xFF,0xBF,0xEF,0xFF,
+0xF3,0xFF,0x3F,0xCF,0xF3,0xFC,0xFF,0x3D, 0xCF,0x9F,0xFE,0x07,0xFF,0xAF,0xEB,0xFE,
+0xFD,0xBF,0xEF,0xEB,0xFA,0xFF,0xAF,0xEB, 0xFA,0xFE,0xBF,0xAF,0xFB,0xFE,0x3F,0xFB,
+0x9B,0xFF,0x7F,0xDF,0xFF,0xF3,0xFE,0xFF, 0xDE,0xF7,0xBF,0x7B,0xDE,0xF7,0xBD,0xEF,
+0x7B,0xFE,0xFF,0xFF,0xDF,0x3F,0xFE,0xFF, 0xB7,0xFF,0xEF,0xF7,0xFF,0xBF,0xED,0xFE,
+0xDF,0xB7,0xED,0xFB,0x7E,0xDF,0xFF,0xFF, 0xFF,0xFD,0x5F,0xEF,0xEB,0xFA,0xFE,0xF5,
+0xBF,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xF8,0xFF,0xA8,0xFF,
+0xFF,0xBF,0xEF,0xFB,0x6A,0xFB,0xB7,0xEF, 0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,
+0xEF,0xFB,0xFF,0xE0,0xFF,0xFF,0xFD,0x7F, 0x5C,0xD7,0x7D,0xDF,0xF3,0x5C,0xF5,0xCD,
+0x73,0x5E,0xD7,0xB5,0xFD,0x7F,0xEF,0xFF, 0xDB,0xFF,0xFF,0xE2,0xF8,0xBE,0x2F,0x8F,
+0xE7,0xF8,0xBE,0x6B,0xE2,0xF8,0xBE,0x2F, 0x8B,0xE2,0xF9,0xFE,0x7F,0xE7,0xFF,0xD7,
+0xF5,0xFD,0x7F,0xFF,0xF7,0xF5,0xFD,0x7F, 0xD7,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF,
+0xFF,0xFF,0x8F,0xFF,0xAF,0xEB,0xFA,0xFF, 0xFF,0xBF,0xEB,0xFA,0xFF,0x2F,0xEB,0xFA,
+0xFE,0xBF,0xAF,0xEB,0xFF,0xFF,0xFE,0x5F, 0xFF,0x5F,0xFF,0xFF,0xFD,0xFF,0xFF,0xD7,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFE,0xB7,0xFD,
+0xFF,0x7E,0xDF,0xF7,0xAD,0xFF,0x7F,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,
+0xF6,0x7F,0xFF,0xFF,0xFF,0xDB,0xF6,0xFC, 0xAF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xBF,0xFF, 0xAF,0xEB,0xFA,0xF6,0xAB,0x8F,0xEB,0xFA,
+0xF7,0xA5,0xEB,0xFA,0xBE,0xBF,0xAF,0xEB, 0xFA,0xFF,0x6D,0xFF,0xFF,0x7F,0xDF,0x33,
+0xDD,0xFF,0x7F,0xFE,0xF7,0xFC,0x7F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9,
+0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xDF, 0xFF,0xFF,0xEF,0xEF,0xFD,0xFF,0x7F,0xFF,
+0xFF,0xFF,0xFF,0xFE,0xA7,0xFF,0xFF,0xFF, 0x77,0xDF,0xF7,0xFD,0x9F,0x7F,0xFE,0x77,
+0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xAF,0xBF,0xAF,0xFF,0xF9,0xBE,0xBF,
+0x8F,0xFB,0xFE,0xFE,0xEF,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFF,0xFF,0xFD,0xDF,0x6F,
+0xEF,0xFF,0x7F,0xFF,0xBF,0xBF,0xDF,0xFF, 0xFC,0xFF,0xDF,0xF7,0xFD,0xEF,0x7F,0xDF,
+0xFF,0xFF,0xFF,0x3F,0xF6,0xFF,0xCF,0xFF, 0xDB,0xFB,0xF7,0xFF,0xEB,0x7A,0xFF,0xFF,
+0xFF,0xBF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFE, 0x6D,0xFD,0xFF,0x5F,0xFB,0xFF,0xFF,0xF7,
+0xFF,0x5F,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFB,0xFF,
+0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xE7,0xF6, 0xBF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,
+0xFF,0xC9,0xFF,0xFF,0xFF,0xBD,0xFF,0xBF, 0xAF,0xEF,0xEF,0x3F,0xD1,0xFC,0x7F,0xFB,
+0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF, 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x77,0xFF,
+0xDF,0xB7,0xFD,0xF7,0xFD,0xF7,0xFF,0xFF, 0xFF,0xFF,0xFF,0x57,0xFF,0xF7,0xA5,0xFD,
+0x3F,0xDF,0xBF,0xBF,0xFE,0x7F,0xFF,0xFF, 0xFF,0xDF,0xFA,0xFD,0xFF,0xFF,0xFF,0xFE,
+0x87,0xFF,0xE9,0xFF,0xFE,0xEF,0xBF,0xEF, 0xFE,0xFE,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFA,0x9F,0xFF,0x3F, 0xFF,0xFD,0xFD,0x57,0xDF,0xFD,0xF3,0xFF,
+0xDF,0xFD,0xFF,0x5F,0xDF,0xF5,0xFD,0xFF, 0xFF,0xF9,0x8F,0xFF,0xFF,0xFF,0xEE,0x7F,
+0xFF,0xFF,0xBF,0x5E,0xFE,0xEC,0xFB,0x3F, 0x7F,0x9F,0xEF,0xF9,0xFF,0xFF,0xCD,0x6B,
+0xFF,0xFF,0xFF,0xC5,0xF3,0xFC,0xFA,0x38, 0xFF,0xAF,0x3F,0xEE,0x7F,0x9F,0xFF,0xD9,
+0xFF,0xFF,0xFD,0x7A,0xF7,0xFF,0xF3,0xFF, 0xAF,0x6F,0xDB,0xF2,0xB9,0xE9,0xFB,0xFF,
+0xFF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFB, 0xC5,0xBF,0xFF,0xEF,0xFF,0x5E,0xB7,0xAD,
+0xCD,0x79,0x7C,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0x93,0xFF,0xEF,
+0xEA,0xFE,0xBF,0xEF,0x5B,0xD2,0xCD,0xF5, 0x6D,0x77,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,
+0xFF,0xFF,0x66,0xFF,0xD5,0x65,0x7D,0x5F, 0x75,0x9D,0x65,0x7F,0xD6,0xFB,0x4F,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xC7, 0xFF,0xBF,0xEF,0xFA,0xFE,0xFF,0xBF,0xEB,
+0xFF,0xDF,0xFF,0x7E,0xFF,0xFF,0xEF,0xFD, 0x7E,0xD7,0xFF,0x78,0xDF,0xFF,0x5F,0xDF,
+0xF5,0xBF,0x7F,0xDF,0xC5,0xFF,0x3F,0xF6, 0x7E,0xFF,0x0F,0xEF,0xF2,0x3E,0xBF,0xFF,
+0xFB,0x3F,0xFF,0xFB,0x7F,0xFF,0xB3,0xFE, 0xFB,0xF6,0xFD,0xFF,0xDA,0xF7,0xFD,0xFF,
+0x7F,0xDF,0xF7,0xBF,0xFF,0xFA,0x7F,0xFF, 0xFF,0xFF,0xFF,0x9F,0xFF,0xF3,0xDC,0xF9,
+0xBF,0xCE,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7, 0xFF,0xFF,0xE2,0x7F,0xFE,0xFF,0xBF,0xEF,
+0xEB,0xFA,0xFF,0x9F,0x67,0x1E,0xFF,0x8F, 0xE7,0xF8,0xFE,0x7F,0x8F,0xEF,0xFF,0xBD,
+0xBF,0xFF,0xFB,0xFF,0xFF,0xDF,0xF7,0xFF, 0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xEF, 0xFF,0xFF,0xBF,0xED,0xFF,0xFB,0xEE,0xFE,
+0xFF,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFF,0xB5,0xFF,0xB7,0xFD,0xFD,0x6E,0xFF,
+0xFF,0xFE,0xFD,0x2F,0xD8,0xFE,0xBF,0x8F, 0xEB,0xF9,0xFE,0x3F,0xFF,0xFA,0xCF,0xFF,
+0xE7,0xD9,0xFA,0xBF,0xDF,0x77,0xFC,0xFB, 0x3F,0xAB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,
+0xFF,0xFF,0xEE,0x1F,0xFF,0xDF,0xF7,0xFF, 0xFF,0xFF,0x5F,0x97,0x35,0xBF,0x5E,0xFE,
+0xBF,0xEF,0xFF,0xF7,0xFD,0xFF,0xFF,0xFA, 0xBF,0xFF,0xBE,0x6F,0x9F,0xE7,0xF8,0xBE,
+0x2F,0x8B,0x66,0x94,0x7D,0x9D,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,0xFF,
+0xFF,0xF7,0xF5,0xFD,0x7F,0x5F,0xFB,0xFD, 0x9E,0xFF,0xFB,0xFE,0xFF,0xFF,0xEF,0xFF,
+0xFF,0xA0,0xFF,0xFF,0xFF,0xBF,0xEF,0xEB, 0xFA,0xFE,0xBF,0xB7,0xF7,0xF7,0xFF,0xFF,
+0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xFD,0xFF,0xFF,0xFF,0xD7,0xFF,0xFF,0xFF,
+0x7F,0xF5,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xFF,0xAB,0xFE,0xFB,0xFE,0xFF,
+0xF7,0xAF,0xFF,0xFF,0xDE,0xF7,0xEB,0x5F, 0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,0xFF,
+0xB3,0xFF,0xC9,0xFE,0xFF,0xFF,0xFF,0xFF, 0xD6,0xFF,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFC,0x8F,0xFF,0xBA, 0xBE,0xBF,0xAF,0xEB,0x78,0xFE,0xB7,0xAD,
+0x3A,0xFE,0xB7,0xAF,0xEB,0x7A,0xFE,0xBF, 0xAF,0xFF,0x9F,0xFF,0xFF,0xDF,0xFC,0xFF,
+0xFF,0xFE,0xC3,0xFE,0xFF,0xFF,0x33,0xFC, 0xFF,0xBF,0xDF,0xF3,0xFF,0xFF,0xBB,0x9F,
+0xFF,0xFF,0xFF,0xEB,0xDF,0xFF,0xFF,0xAF, 0xF7,0x6F,0xF9,0xBF,0xEF,0xFD,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xFD,0xFB,0xF7,0xFF,
+0xDF,0xF7,0xFF,0xFE,0xEF,0x5F,0xBD,0xFF, 0xFA,0xFF,0xF8,0xFF,0xBF,0xAF,0xFB,0xFE,
+0xFE,0x3F,0xEF,0xE8,0xFF,0xDF,0xF3,0xFD, 0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xFB,
+0xFD,0xFF,0xAF,0xFF,0xFF,0xFE,0xFE,0xBF, 0xDB,0xFF,0xFF,0xFF,0xBF,0xFF,0xDF,0xFF,
+0xFD,0xFF,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF, 0xBF,0x6F,0xFF,0x7F,0xB7,0xB3,0xFF,0xFF,
+0xDF,0xFF,0xFB,0xEF,0xFF,0xFF,0xFF,0x07, 0xFF,0xFB,0xFF,0xFF,0xFF,0xED,0xFF,0xF5,
+0x7C,0xFF,0x7F,0xFE,0xFF,0xFF,0xEF,0xCF, 0xFF,0xFB,0xFF,0xFF,0x2F,0xFF,0xFF,0xFF,
+0xFF,0xF3,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,
+0xFD,0x1B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFE,0x7C,0xFF,0xFF,0xFF,0xFF,
+0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0x7F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,
+0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xEF,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xEF,0xFA,0xB5,0xFF,0xFF,0xFF, 0xF7,0xF7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFB,
+0xFC,0xFF,0xFF,0xFE,0xFF,0x7F,0xDF,0xBF, 0xFF,0xCB,0xBF,0xF9,0xFE,0x7F,0x9F,0xE7,
+0xF9,0xFE,0x7F,0x97,0xE1,0xFE,0x79,0x9F, 0xE7,0xFD,0xFE,0x7F,0xDF,0xFE,0x37,0xFF,
+0xFB,0xDE,0xDE,0xBD,0xEF,0xF3,0xFE,0xFB, 0xAF,0xEB,0xFE,0xFF,0xFF,0xCF,0xFF,0xFE,
+0xFF,0xBF,0xFF,0x8F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xE7,0xF9,0x5E,0x7F,0xEF,0xFB,
+0xDA,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD, 0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,
+0xFF,0xFF,0x7F,0xFF,0xFF,0xF7,0xFB,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xBF,
+0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0x7B,0x7F, 0xBF,0xEF,0xFB,0xFE,0xFF,0xB5,0xEF,0xFB,
+0xBF,0xFA,0x7F,0xFC,0xFF,0x3F,0xCF,0xF3, 0xFC,0xFF,0x3F,0xCF,0xBC,0xFF,0x3F,0xEF,
+0xF3,0xFC,0xFE,0x3F,0xCF,0xFF,0xEE,0xEF, 0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0x6A,0xD7,
+0xB7,0xFB,0xF8,0xFF,0xB7,0xEF,0xBA,0xFE, 0xFF,0xBF,0x7F,0xE9,0xFF,0xF9,0x7E,0x5F,
+0x97,0xE5,0xF9,0xFE,0x7F,0xBF,0xF9,0x7E, 0x5F,0x9F,0xE5,0xFB,0xFE,0x5F,0xB7,0xFF,
+0xA3,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0x5E,0xF7,0x7D,0xFF,0x77,0xDF,
+0xF7,0xFD,0xFF,0x7F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xDF,0xFB,0x7F,
+0xFF,0xFF,0xEF,0xFF,0xFE,0xFB,0xFF,0xFF, 0xBF,0xFE,0x8F,0xFF,0xDF,0xF7,0xFD,0xFD,
+0x7F,0xDF,0xF7,0xFD,0x3E,0xDF,0xF5,0xBD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xF7,0xFF,0x9F,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xBE,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFD,0x3F,0xFF,0xDF,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xCF,
+0x77,0xFC,0xFF,0x5F,0xDF,0xF7,0xFD,0xFF, 0xF4,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xED,0xFB,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFB,0xFF,0xFF,0xFF,0xD3,0xFF,0xFF,
+0xBF,0x3F,0xFB,0xFF,0xFF,0xFF,0xFB,0xF3, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xFF,
+0xDF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xDF,0xFF,0xFD,0xFF,0xFF,0xDF,0xF7,
+0xFF,0x4F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,
+0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x9F,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFF,0xFF,0x7A,0x3F,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,
+0x7F,0xFF,0xFB,0xFE,0xFF,0xBF,0xEF,0xF8, 0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,0x8F,0xEC,
+0xFB,0xFE,0xFF,0xBF,0xF8,0xF7,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFD,0xBF,0xCF,0xEC,
+0xFF,0x3F,0xEF,0xDB,0xF8,0xFF,0xBF,0xCF, 0xFF,0xF9,0xFF,0xFF,0xBF,0xFF,0xFB,0xFF,
+0xFF,0xFF,0xEF,0xFB,0xDF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xBB,0xFF,
+0xEF,0xFB,0xFE,0xEF,0xBF,0xEE,0xEB,0xFB, 0xFE,0xFF,0xEF,0xFE,0xEE,0xBF,0xFE,0xEB,
+0xFF,0xEF,0xFF,0x17,0xFF,0x7E,0xEB,0xBB, 0xFE,0xBF,0xBE,0xFB,0xEF,0x5B,0xF7,0xBD,
+0xFB,0xCF,0xBF,0xBF,0xBB,0xFB,0x7E,0xCC, 0xEF,0xFF
+
+};
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/dabusb.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,857 @@
+/*****************************************************************************/
+
+/*
+ *      dabusb.c  --  dab usb driver.
+ *
+ *      Copyright (C) 1999  Deti Fliegl (deti@fliegl.de)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *
+ *  $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $
+ *
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/miscdevice.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/delay.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+
+#include "dabusb.h"
+#include "dabfirmware.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.54"
+#define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
+#define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999"
+
+/* --------------------------------------------------------------------- */
+
+#define NRDABUSB 4
+
+/*-------------------------------------------------------------------*/
+
+static dabusb_t dabusb[NRDABUSB];
+static int buffers = 256;
+
+/*-------------------------------------------------------------------*/
+
+static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
+{
+	unsigned long flags;
+	struct list_head *tmp;
+	int ret = 0;
+
+	spin_lock_irqsave (&s->lock, flags);
+
+	if (list_empty (src)) {
+		// no elements in source buffer
+		ret = -1;
+		goto err;
+	}
+	tmp = src->next;
+	list_del (tmp);
+	list_add_tail (tmp, dst);
+
+  err:	spin_unlock_irqrestore (&s->lock, flags);
+	return ret;
+}
+/*-------------------------------------------------------------------*/
+#ifdef DEBUG 
+static void dump_urb (struct urb *urb)
+{
+	dbg("urb                   :%p", urb);
+	dbg("next                  :%p", urb->next);
+	dbg("dev                   :%p", urb->dev);
+	dbg("pipe                  :%08X", urb->pipe);
+	dbg("status                :%d", urb->status);
+	dbg("transfer_flags        :%08X", urb->transfer_flags);
+	dbg("transfer_buffer       :%p", urb->transfer_buffer);
+	dbg("transfer_buffer_length:%d", urb->transfer_buffer_length);
+	dbg("actual_length         :%d", urb->actual_length);
+	dbg("setup_packet          :%p", urb->setup_packet);
+	dbg("start_frame           :%d", urb->start_frame);
+	dbg("number_of_packets     :%d", urb->number_of_packets);
+	dbg("interval              :%d", urb->interval);
+	dbg("error_count           :%d", urb->error_count);
+	dbg("context               :%p", urb->context);
+	dbg("complete              :%p", urb->complete);
+}
+#endif
+/*-------------------------------------------------------------------*/
+static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
+{
+	unsigned long flags;
+	struct list_head *p;
+	pbuff_t b;
+
+	dbg("dabusb_cancel_queue");
+
+	spin_lock_irqsave (&s->lock, flags);
+
+	for (p = q->next; p != q; p = p->next) {
+		b = list_entry (p, buff_t, buff_list);
+
+#ifdef DEBUG
+		dump_urb(b->purb);
+#endif
+		usb_unlink_urb (b->purb);
+	}
+	spin_unlock_irqrestore (&s->lock, flags);
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+static int dabusb_free_queue (struct list_head *q)
+{
+	struct list_head *tmp;
+	struct list_head *p;
+	pbuff_t b;
+
+	dbg("dabusb_free_queue");
+	for (p = q->next; p != q;) {
+		b = list_entry (p, buff_t, buff_list);
+
+#ifdef DEBUG 
+		dump_urb(b->purb);
+#endif
+		if (b->purb->transfer_buffer)
+			kfree (b->purb->transfer_buffer);
+		usb_free_urb(b->purb);
+		tmp = p->next;
+		list_del (p);
+		kfree (b);
+		p = tmp;
+	}
+
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+static int dabusb_free_buffers (pdabusb_t s)
+{
+	unsigned long flags;
+	dbg("dabusb_free_buffers");
+
+	spin_lock_irqsave(&s->lock, flags);
+
+	dabusb_free_queue (&s->free_buff_list);
+	dabusb_free_queue (&s->rec_buff_list);
+
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	s->got_mem = 0;
+	return 0;
+}
+/*-------------------------------------------------------------------*/
+static void dabusb_iso_complete (struct urb *purb)
+{
+	pbuff_t b = purb->context;
+	pdabusb_t s = b->s;
+	int i;
+	int len;
+	int dst = 0;
+	void *buf = purb->transfer_buffer;
+
+	dbg("dabusb_iso_complete");
+
+	// process if URB was not killed
+	if (purb->status != -ENOENT) {
+		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
+		int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
+		for (i = 0; i < purb->number_of_packets; i++)
+			if (!purb->iso_frame_desc[i].status) {
+				len = purb->iso_frame_desc[i].actual_length;
+				if (len <= pipesize) {
+					memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
+					dst += len;
+				}
+				else
+					err("dabusb_iso_complete: invalid len %d", len);
+			}
+			else
+				warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status);
+		if (dst != purb->actual_length)
+			err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
+	}
+
+	if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
+		s->overruns++;
+		err("overrun (%d)", s->overruns);
+	}
+	wake_up (&s->wait);
+}
+/*-------------------------------------------------------------------*/
+static int dabusb_alloc_buffers (pdabusb_t s)
+{
+	int buffers = 0;
+	pbuff_t b;
+	unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
+	int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
+	int packets = _ISOPIPESIZE / pipesize;
+	int transfer_buffer_length = packets * pipesize;
+	int i;
+
+	dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d",
+		 pipesize, packets, transfer_buffer_length);
+
+	while (buffers < (s->total_buffer_size << 10)) {
+		b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
+		if (!b) {
+			err("kmalloc(sizeof(buff_t))==NULL");
+			goto err;
+		}
+		memset (b, 0, sizeof (buff_t));
+		b->s = s;
+		b->purb = usb_alloc_urb(packets, GFP_KERNEL);
+		if (!b->purb) {
+			err("usb_alloc_urb == NULL");
+			kfree (b);
+			goto err;
+		}
+
+		b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
+		if (!b->purb->transfer_buffer) {
+			kfree (b->purb);
+			kfree (b);
+			err("kmalloc(%d)==NULL", transfer_buffer_length);
+			goto err;
+		}
+
+		b->purb->transfer_buffer_length = transfer_buffer_length;
+		b->purb->number_of_packets = packets;
+		b->purb->complete = dabusb_iso_complete;
+		b->purb->context = b;
+		b->purb->dev = s->usbdev;
+		b->purb->pipe = pipe;
+		b->purb->transfer_flags = USB_ISO_ASAP;
+
+		for (i = 0; i < packets; i++) {
+			b->purb->iso_frame_desc[i].offset = i * pipesize;
+			b->purb->iso_frame_desc[i].length = pipesize;
+		}
+
+		buffers += transfer_buffer_length;
+		list_add_tail (&b->buff_list, &s->free_buff_list);
+	}
+	s->got_mem = buffers;
+
+	return 0;
+
+	err:
+	dabusb_free_buffers (s);
+	return -ENOMEM;
+}
+/*-------------------------------------------------------------------*/
+static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
+{
+	int ret;
+	unsigned int pipe;
+	int actual_length;
+
+	dbg("dabusb_bulk");
+
+	if (!pb->pipe)
+		pipe = usb_rcvbulkpipe (s->usbdev, 2);
+	else
+		pipe = usb_sndbulkpipe (s->usbdev, 2);
+
+	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
+	if(ret<0) {
+		err("dabusb: usb_bulk_msg failed(%d)",ret);
+
+		if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
+			err("set_interface failed");
+			return -EINVAL;
+		}
+
+	}
+	
+	if( ret == -EPIPE ) {
+		warn("CLEAR_FEATURE request to remove STALL condition.");
+		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
+			err("request failed");
+	}
+
+	pb->size = actual_length;
+	return ret;
+}
+/* --------------------------------------------------------------------- */
+static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len)
+{
+	int ret;
+	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
+
+	if (!transfer_buffer) {
+		err("dabusb_writemem: kmalloc(%d) failed.", len);
+		return -ENOMEM;
+	}
+
+	memcpy (transfer_buffer, data, len);
+
+	ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
+
+	kfree (transfer_buffer);
+	return ret;
+}
+/* --------------------------------------------------------------------- */
+static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
+{
+	dbg("dabusb_8051_reset: %d",reset_bit);
+	return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
+}
+/* --------------------------------------------------------------------- */
+static int dabusb_loadmem (pdabusb_t s, const char *fname)
+{
+	int ret;
+	PINTEL_HEX_RECORD ptr = firmware;
+
+	dbg("Enter dabusb_loadmem (internal)");
+	
+	ret = dabusb_8051_reset (s, 1);
+	while (ptr->Type == 0) {
+
+		dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
+
+		ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
+		if (ret < 0) {
+			err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length);
+			break;
+		}
+		ptr++;
+	}
+	ret = dabusb_8051_reset (s, 0);
+
+	dbg("dabusb_loadmem: exit");
+
+	return ret;
+}
+/* --------------------------------------------------------------------- */
+static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b)
+{
+	b->size = 4;
+	b->data[0] = 0x2a;
+	b->data[1] = 0;
+	b->data[2] = 0;
+	b->data[3] = 0;
+
+	dbg("dabusb_fpga_clear");
+
+	return dabusb_bulk (s, b);
+}
+/* --------------------------------------------------------------------- */
+static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
+{
+	b->size = 4;
+	b->data[0] = 0x2c;
+	b->data[1] = 0;
+	b->data[2] = 0;
+	b->data[3] = 0;
+
+	dbg("dabusb_fpga_init");
+
+	return dabusb_bulk (s, b);
+}
+/* --------------------------------------------------------------------- */
+static int dabusb_fpga_download (pdabusb_t s, const char *fname)
+{
+	pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
+	unsigned int blen, n;
+	int ret;
+	unsigned char *buf = bitstream;
+
+	dbg("Enter dabusb_fpga_download (internal)");
+
+	if (!b) {
+		err("kmalloc(sizeof(bulk_transfer_t))==NULL");
+		return -ENOMEM;
+	}
+
+	b->pipe = 1;
+	ret = dabusb_fpga_clear (s, b);
+	mdelay (10);
+	blen = buf[73] + (buf[72] << 8);
+
+	dbg("Bitstream len: %i", blen);
+
+	b->data[0] = 0x2b;
+	b->data[1] = 0;
+	b->data[2] = 0;
+	b->data[3] = 60;
+
+	for (n = 0; n <= blen + 60; n += 60) {
+		// some cclks for startup
+		b->size = 64;
+		memcpy (b->data + 4, buf + 74 + n, 60);
+		ret = dabusb_bulk (s, b);
+		if (ret < 0) {
+			err("dabusb_bulk failed.");
+			break;
+		}
+		mdelay (1);
+	}
+
+	ret = dabusb_fpga_init (s, b);
+	kfree (b);
+
+	dbg("exit dabusb_fpga_download");
+
+	return ret;
+}
+
+static int dabusb_stop (pdabusb_t s)
+{
+	dbg("dabusb_stop");
+
+	s->state = _stopped;
+	dabusb_cancel_queue (s, &s->rec_buff_list);
+
+	dbg("pending_io: %d", s->pending_io.counter);
+
+	s->pending_io.counter = 0;
+	return 0;
+}
+
+static int dabusb_startrek (pdabusb_t s)
+{
+	if (!s->got_mem && s->state != _started) {
+
+		dbg("dabusb_startrek");
+
+		if (dabusb_alloc_buffers (s) < 0)
+			return -ENOMEM;
+		dabusb_stop (s);
+		s->state = _started;
+		s->readptr = 0;
+	}
+
+	if (!list_empty (&s->free_buff_list)) {
+		pbuff_t end;
+		int ret;
+		
+	while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
+
+			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
+
+			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
+
+			ret = usb_submit_urb (end->purb, GFP_KERNEL);
+			if (ret) {
+				err("usb_submit_urb returned:%d", ret);
+				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
+					err("startrek: dabusb_add_buf_tail failed");
+				break;
+			}
+			else
+				atomic_inc (&s->pending_io);
+		}
+		dbg("pending_io: %d",s->pending_io.counter);
+	}
+
+	return 0;
+}
+
+static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+	pdabusb_t s = (pdabusb_t) file->private_data;
+	unsigned long flags;
+	unsigned ret = 0;
+	int rem;
+	int cnt;
+	pbuff_t b;
+	struct urb *purb = NULL;
+
+	dbg("dabusb_read");
+
+	if (*ppos)
+		return -ESPIPE;
+
+	if (s->remove_pending)
+		return -EIO;
+
+
+	if (!s->usbdev)
+		return -EIO;
+
+	while (count > 0) {
+		dabusb_startrek (s);
+
+		spin_lock_irqsave (&s->lock, flags);
+
+		if (list_empty (&s->rec_buff_list)) {
+
+			spin_unlock_irqrestore(&s->lock, flags);
+
+			err("error: rec_buf_list is empty");
+			goto err;
+		}
+		
+		b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
+		purb = b->purb;
+
+		spin_unlock_irqrestore(&s->lock, flags);
+
+		if (purb->status == -EINPROGRESS) {
+			if (file->f_flags & O_NONBLOCK)		// return nonblocking
+			 {
+				if (!ret)
+					ret = -EAGAIN;
+				goto err;
+			}
+
+			interruptible_sleep_on (&s->wait);
+
+			if (signal_pending (current)) {
+				if (!ret)
+					ret = -ERESTARTSYS;
+				goto err;
+			}
+
+			spin_lock_irqsave (&s->lock, flags);
+
+			if (list_empty (&s->rec_buff_list)) {
+				spin_unlock_irqrestore(&s->lock, flags);
+				err("error: still no buffer available.");
+				goto err;
+			}
+			spin_unlock_irqrestore(&s->lock, flags);
+			s->readptr = 0;
+		}
+		if (s->remove_pending) {
+			ret = -EIO;
+			goto err;
+		}
+
+		rem = purb->actual_length - s->readptr;		// set remaining bytes to copy
+
+		if (count >= rem)
+			cnt = rem;
+		else
+			cnt = count;
+
+		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
+
+		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
+			err("read: copy_to_user failed");
+			if (!ret)
+				ret = -EFAULT;
+			goto err;
+		}
+
+		s->readptr += cnt;
+		count -= cnt;
+		buf += cnt;
+		ret += cnt;
+
+		if (s->readptr == purb->actual_length) {
+			// finished, take next buffer
+			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
+				err("read: dabusb_add_buf_tail failed");
+			s->readptr = 0;
+		}
+	}
+      err:			//up(&s->mutex);
+	return ret;
+}
+
+static int dabusb_open (struct inode *inode, struct file *file)
+{
+	int devnum = minor (inode->i_rdev);
+	pdabusb_t s;
+
+	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
+		return -EIO;
+
+	s = &dabusb[devnum - DABUSB_MINOR];
+
+	dbg("dabusb_open");
+	down (&s->mutex);
+
+	while (!s->usbdev || s->opened) {
+		up (&s->mutex);
+
+		if (file->f_flags & O_NONBLOCK) {
+			return -EBUSY;
+		}
+		schedule_timeout (HZ / 2);
+
+		if (signal_pending (current)) {
+			return -EAGAIN;
+		}
+		down (&s->mutex);
+	}
+	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
+		err("set_interface failed");
+		return -EINVAL;
+	}
+	s->opened = 1;
+	up (&s->mutex);
+
+	file->f_pos = 0;
+	file->private_data = s;
+
+	return 0;
+}
+
+static int dabusb_release (struct inode *inode, struct file *file)
+{
+	pdabusb_t s = (pdabusb_t) file->private_data;
+
+	dbg("dabusb_release");
+
+	down (&s->mutex);
+	dabusb_stop (s);
+	dabusb_free_buffers (s);
+	up (&s->mutex);
+
+	if (!s->remove_pending) {
+		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
+			err("set_interface failed");
+	}
+	else
+		wake_up (&s->remove_ok);
+
+	s->opened = 0;
+	return 0;
+}
+
+static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	pdabusb_t s = (pdabusb_t) file->private_data;
+	pbulk_transfer_t pbulk;
+	int ret = 0;
+	int version = DABUSB_VERSION;
+
+	dbg("dabusb_ioctl");
+
+	if (s->remove_pending)
+		return -EIO;
+
+	down (&s->mutex);
+
+	if (!s->usbdev) {
+		up (&s->mutex);
+		return -EIO;
+	}
+
+	switch (cmd) {
+
+	case IOCTL_DAB_BULK:
+		pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
+
+		if (!pbulk) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		if (copy_from_user (pbulk, (void *) arg, sizeof (bulk_transfer_t))) {
+			ret = -EFAULT;
+			kfree (pbulk);
+			break;
+		}
+
+		ret=dabusb_bulk (s, pbulk);
+		if(ret==0)
+			ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t));
+		kfree (pbulk);
+		break;
+
+	case IOCTL_DAB_OVERRUNS:
+		ret = put_user (s->overruns, (unsigned int *) arg);
+		break;
+
+	case IOCTL_DAB_VERSION:
+		ret = put_user (version, (unsigned int *) arg);
+		break;
+
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	up (&s->mutex);
+	return ret;
+}
+
+static struct file_operations dabusb_fops =
+{
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	read:		dabusb_read,
+	ioctl:		dabusb_ioctl,
+	open:		dabusb_open,
+	release:	dabusb_release,
+};
+
+static int dabusb_find_struct (void)
+{
+	int u;
+
+	for (u = 0; u < NRDABUSB; u++) {
+		pdabusb_t s = &dabusb[u];
+		if (!s->usbdev)
+			return u;
+	}
+	return -1;
+}
+
+/* --------------------------------------------------------------------- */
+static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum,
+			   const struct usb_device_id *id)
+{
+	int devnum;
+	pdabusb_t s;
+
+	dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
+	  usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
+
+	/* We don't handle multiple configurations */
+	if (usbdev->descriptor.bNumConfigurations != 1)
+		return NULL;
+
+	if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
+		return NULL;
+
+	devnum = dabusb_find_struct ();
+	if (devnum == -1)
+		return NULL;
+
+	s = &dabusb[devnum];
+
+	down (&s->mutex);
+	s->remove_pending = 0;
+	s->usbdev = usbdev;
+
+	if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
+		err("set_configuration failed");
+		goto reject;
+	}
+	if (usbdev->descriptor.idProduct == 0x2131) {
+		dabusb_loadmem (s, NULL);
+		goto reject;
+	}
+	else {
+		dabusb_fpga_download (s, NULL);
+
+		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
+			err("set_interface failed");
+			goto reject;
+		}
+	}
+	dbg("bound to interface: %d", ifnum);
+	up (&s->mutex);
+	MOD_INC_USE_COUNT;
+	return s;
+
+      reject:
+	up (&s->mutex);
+	s->usbdev = NULL;
+	return NULL;
+}
+
+static void dabusb_disconnect (struct usb_device *usbdev, void *ptr)
+{
+	pdabusb_t s = (pdabusb_t) ptr;
+
+	dbg("dabusb_disconnect");
+
+	s->remove_pending = 1;
+	wake_up (&s->wait);
+	if (s->state == _started)
+		sleep_on (&s->remove_ok);
+	s->usbdev = NULL;
+	s->overruns = 0;
+	MOD_DEC_USE_COUNT;
+}
+
+static struct usb_device_id dabusb_ids [] = {
+	{ USB_DEVICE(0x0547, 0x2131) },
+	{ USB_DEVICE(0x0547, 0x9999) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, dabusb_ids);
+
+static struct usb_driver dabusb_driver =
+{
+	name:		"dabusb",
+	probe:		dabusb_probe,
+	disconnect:	dabusb_disconnect,
+	fops:		&dabusb_fops,
+	minor:		DABUSB_MINOR,
+	id_table:	dabusb_ids,
+};
+
+/* --------------------------------------------------------------------- */
+
+static int __init dabusb_init (void)
+{
+	unsigned u;
+
+	/* initialize struct */
+	for (u = 0; u < NRDABUSB; u++) {
+		pdabusb_t s = &dabusb[u];
+		memset (s, 0, sizeof (dabusb_t));
+		init_MUTEX (&s->mutex);
+		s->usbdev = NULL;
+		s->total_buffer_size = buffers;
+		init_waitqueue_head (&s->wait);
+		init_waitqueue_head (&s->remove_ok);
+		spin_lock_init (&s->lock);
+		INIT_LIST_HEAD (&s->free_buff_list);
+		INIT_LIST_HEAD (&s->rec_buff_list);
+	}
+
+	/* register misc device */
+	if (usb_register(&dabusb_driver))
+		return -1;
+
+	dbg("dabusb_init: driver registered");
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+
+	return 0;
+}
+
+static void __exit dabusb_cleanup (void)
+{
+	dbg("dabusb_cleanup");
+
+	usb_deregister (&dabusb_driver);
+}
+
+/* --------------------------------------------------------------------- */
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+MODULE_PARM (buffers, "i");
+MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
+
+module_init (dabusb_init);
+module_exit (dabusb_cleanup);
+
+/* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/media/dabusb.h b/drivers/usb/media/dabusb.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/dabusb.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,84 @@
+#define _BULK_DATA_LEN 64
+typedef struct
+{
+	unsigned char data[_BULK_DATA_LEN];
+	unsigned int size;
+	unsigned int pipe;
+}bulk_transfer_t,*pbulk_transfer_t;
+
+#define DABUSB_MINOR 240		/* some unassigned USB minor */
+#define DABUSB_VERSION 0x1000
+#define IOCTL_DAB_BULK              _IOWR('d', 0x30, bulk_transfer_t)
+#define IOCTL_DAB_OVERRUNS	    _IOR('d',  0x15, int)
+#define IOCTL_DAB_VERSION           _IOR('d', 0x3f, int) 
+
+#ifdef __KERNEL__
+
+typedef enum { _stopped=0, _started } driver_state_t;
+
+typedef struct
+{
+	struct semaphore mutex;
+	struct usb_device *usbdev;
+	wait_queue_head_t wait;
+	wait_queue_head_t remove_ok;
+	spinlock_t lock;
+	atomic_t pending_io;
+	driver_state_t state;
+	int remove_pending;
+	int got_mem;
+	int total_buffer_size;
+	unsigned int overruns;
+	int readptr;
+	int opened;
+	struct list_head free_buff_list;
+	struct list_head rec_buff_list;
+} dabusb_t,*pdabusb_t;
+
+typedef struct 
+{
+	pdabusb_t s;
+	struct urb *purb;
+	struct list_head buff_list;
+} buff_t,*pbuff_t;
+
+typedef struct
+{
+	wait_queue_head_t wait;
+} bulk_completion_context_t, *pbulk_completion_context_t;
+
+
+#define _DABUSB_IF 2
+#define _DABUSB_ISOPIPE 0x09
+#define _ISOPIPESIZE	16384
+
+#define _BULK_DATA_LEN 64
+// Vendor specific request code for Anchor Upload/Download
+// This one is implemented in the core
+#define ANCHOR_LOAD_INTERNAL  0xA0
+
+// EZ-USB Control and Status Register.  Bit 0 controls 8051 reset
+#define CPUCS_REG    0x7F92
+#define _TOTAL_BUFFERS 384
+
+#define MAX_INTEL_HEX_RECORD_LENGTH 16
+
+#ifndef _BYTE_DEFINED
+#define _BYTE_DEFINED
+typedef unsigned char BYTE;
+#endif // !_BYTE_DEFINED
+
+#ifndef _WORD_DEFINED
+#define _WORD_DEFINED
+typedef unsigned short WORD;
+#endif // !_WORD_DEFINED
+
+typedef struct _INTEL_HEX_RECORD
+{
+   BYTE  Length;
+   WORD  Address;
+   BYTE  Type;
+   BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
+} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
+
+#endif
diff -Nru a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/dsbr100.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,373 @@
+/* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
+ into both the USB and an analog audio input, so this thing
+ only deals with initialisation and frequency setting, the
+ audio data has to be handled by a sound driver.
+
+ Major issue: I can't find out where the device reports the signal
+ strength, and indeed the windows software appearantly just looks
+ at the stereo indicator as well.  So, scanning will only find
+ stereo stations.  Sad, but I can't help it.
+
+ Also, the windows program sends oodles of messages over to the
+ device, and I couldn't figure out their meaning.  My suspicion
+ is that they don't have any:-)
+
+ You might find some interesting stuff about this module at
+ http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
+
+ Copyright (c) 2000 Markus Demleitner <msdemlei@tucana.harvard.edu>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ History:
+
+ Version 0.24:
+ 	Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
+	right.  Some minor cleanup, improved standalone compilation
+
+ Version 0.23:
+ 	Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
+
+ Version 0.22:
+ 	Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, 
+	thanks to Mike Cox for pointing the problem out.
+
+ Version 0.21:
+ 	Markus: Minor cleanup, warnings if something goes wrong, lame attempt
+	to adhere to Documentation/CodingStyle
+
+ Version 0.2: 
+ 	Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
+	Markus: Copyright clarification
+
+ Version 0.01: Markus: initial release
+
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/videodev.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.24"
+#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
+#define DRIVER_DESC "D-Link DSB-R100 USB radio driver"
+
+#define DSB100_VENDOR 0x04b4
+#define DSB100_PRODUCT 0x1002
+
+#define TB_LEN 16
+
+static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum,
+			 const struct usb_device_id *id);
+static void usb_dsbr100_disconnect(struct usb_device *dev, void *ptr);
+static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg);
+static int usb_dsbr100_open(struct inode *inode, struct file *file);
+static int usb_dsbr100_close(struct inode *inode, struct file *file);
+
+static int radio_nr = -1;
+MODULE_PARM(radio_nr, "i");
+
+typedef struct
+{
+	struct usb_device *dev;
+	unsigned char transfer_buffer[TB_LEN];
+	int curfreq;
+	int stereo;
+	int ifnum;
+} usb_dsbr100;
+
+
+static struct file_operations usb_dsbr100_fops = {
+	owner:		THIS_MODULE,
+	open:		usb_dsbr100_open,
+	release:       	usb_dsbr100_close,
+	ioctl:          usb_dsbr100_ioctl,
+	llseek:         no_llseek,
+};
+static struct video_device usb_dsbr100_radio=
+{
+	owner:		THIS_MODULE,
+	name:		"D-Link DSB R-100 USB radio",
+	type:		VID_TYPE_TUNER,
+	hardware:	VID_HARDWARE_AZTECH,
+	fops:           &usb_dsbr100_fops,
+};
+
+static int users = 0;
+
+static struct usb_device_id usb_dsbr100_table [] = {
+	{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_dsbr100_table);
+
+static struct usb_driver usb_dsbr100_driver = {
+	name:		"dsbr100",
+	probe:		usb_dsbr100_probe,
+	disconnect:	usb_dsbr100_disconnect,
+	fops:		NULL,
+	minor:		0,
+	id_table:	usb_dsbr100_table,
+};
+
+
+static int dsbr100_start(usb_dsbr100 *radio)
+{
+	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x00, 0xC0, 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
+	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x02, 0xC0, 0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
+		return -1;
+	return (radio->transfer_buffer)[0];
+}
+
+
+static int dsbr100_stop(usb_dsbr100 *radio)
+{
+	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x00, 0xC0, 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
+	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x02, 0xC0, 0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
+		return -1;
+	return (radio->transfer_buffer)[0];
+}
+
+
+static int dsbr100_setfreq(usb_dsbr100 *radio, int freq)
+{
+	freq = (freq/16*80)/1000+856;
+	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x01, 0xC0, (freq>>8)&0x00ff, freq&0xff, 
+		radio->transfer_buffer, 8, 300)<0 ||
+	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x00, 0xC0, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
+	    usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x00, 0xC0, 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
+		radio->stereo = -1;
+		return -1;
+	}
+	radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
+	return (radio->transfer_buffer)[0];
+}
+
+static void dsbr100_getstat(usb_dsbr100 *radio)
+{
+	if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+		0x00, 0xC0, 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
+		radio->stereo = -1;
+	else
+		radio->stereo = ! (radio->transfer_buffer[0]&0x01);
+}
+
+
+static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum,
+			 const struct usb_device_id *id)
+{
+	usb_dsbr100 *radio;
+
+	if (!(radio = kmalloc(sizeof(usb_dsbr100),GFP_KERNEL)))
+		return NULL;
+	usb_dsbr100_radio.priv = radio;
+	radio->dev = dev;
+	radio->ifnum = ifnum;
+	radio->curfreq = 1454000;
+	return (void*)radio;
+}
+
+static void usb_dsbr100_disconnect(struct usb_device *dev, void *ptr)
+{
+	usb_dsbr100 *radio=ptr;
+
+	lock_kernel();
+	if (users) {
+		unlock_kernel();
+		return;
+	}
+	kfree(radio);
+	usb_dsbr100_radio.priv = NULL;
+	unlock_kernel();
+}
+
+static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
+				unsigned int cmd, void *arg)
+{
+	struct video_device *dev = video_devdata(file);
+	usb_dsbr100 *radio=dev->priv;
+
+	if (!radio)
+		return -EINVAL;
+
+	switch(cmd)
+	{
+		case VIDIOCGCAP: {
+			struct video_capability *v = arg;
+			memset(v,0,sizeof(*v));
+			v->type=VID_TYPE_TUNER;
+			v->channels=1;
+			v->audios=1;
+			strcpy(v->name, "D-Link R-100 USB Radio");
+			return 0;
+		}
+		case VIDIOCGTUNER: {
+			struct video_tuner *v = arg;
+			dsbr100_getstat(radio);
+			if(v->tuner)	/* Only 1 tuner */ 
+				return -EINVAL;
+			v->rangelow = 87*16000;
+			v->rangehigh = 108*16000;
+			v->flags = VIDEO_TUNER_LOW;
+			v->mode = VIDEO_MODE_AUTO;
+			v->signal = radio->stereo*0x7000;
+				/* Don't know how to get signal strength */
+			v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo;
+			strcpy(v->name, "DSB R-100");
+			return 0;
+		}
+		case VIDIOCSTUNER: {
+			struct video_tuner *v = arg;
+			if(v->tuner!=0)
+				return -EINVAL;
+			/* Only 1 tuner so no setting needed ! */
+			return 0;
+		}
+		case VIDIOCGFREQ:
+		{
+			int *freq = arg;
+			if (radio->curfreq==-1)
+				return -EINVAL;
+			*freq = radio->curfreq;
+			return 0;
+		}
+		case VIDIOCSFREQ:
+		{
+			int *freq = arg;
+			*freq = radio->curfreq;
+			if (dsbr100_setfreq(radio, radio->curfreq)==-1)
+				warn("set frequency failed");
+			return 0;
+		}
+		case VIDIOCGAUDIO: {
+			struct video_audio *v = arg;
+			memset(v,0, sizeof(*v));
+			v->flags|=VIDEO_AUDIO_MUTABLE;
+			v->mode=VIDEO_SOUND_STEREO;
+			v->volume=1;
+			v->step=1;
+			strcpy(v->name, "Radio");
+			return 0;			
+		}
+		case VIDIOCSAUDIO: {
+			struct video_audio *v = arg;
+			if(v->audio) 
+				return -EINVAL;
+
+			if(v->flags&VIDEO_AUDIO_MUTE) {
+				if (dsbr100_stop(radio)==-1)
+					warn("radio did not respond properly");
+			}
+			else
+				if (dsbr100_start(radio)==-1)
+					warn("radio did not respond properly");
+			return 0;
+		}
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
+}
+
+static int usb_dsbr100_open(struct inode *inode, struct file *file)
+{
+	struct video_device *dev = video_devdata(file);
+	usb_dsbr100 *radio=dev->priv;
+
+	if (! radio) {
+		warn("radio not initialised");
+		return -EAGAIN;
+	}
+	if(users)
+	{
+		warn("radio in use");
+		return -EBUSY;
+	}
+	users++;
+	if (dsbr100_start(radio)<0)
+		warn("radio did not start up properly");
+	dsbr100_setfreq(radio,radio->curfreq);
+	return 0;
+}
+
+static int usb_dsbr100_close(struct inode *inode, struct file *file)
+{
+	struct video_device *dev = video_devdata(file);
+	usb_dsbr100 *radio=dev->priv;
+
+	if (!radio)
+		return -ENODEV;
+	users--;
+	dsbr100_stop(radio);
+	return 0;
+}
+
+static int __init dsbr100_init(void)
+{
+	usb_dsbr100_radio.priv = NULL;
+	usb_register(&usb_dsbr100_driver);
+	if (video_register_device(&usb_dsbr100_radio,VFL_TYPE_RADIO,radio_nr)==-1) {	
+		warn("couldn't register video device");
+		return -EINVAL;
+	}
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+static void __exit dsbr100_exit(void)
+{
+	usb_dsbr100 *radio=usb_dsbr100_radio.priv;
+
+	if (radio)
+		dsbr100_stop(radio);
+	video_unregister_device(&usb_dsbr100_radio);
+	usb_deregister(&usb_dsbr100_driver);
+}
+
+module_init (dsbr100_init);
+module_exit (dsbr100_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+/*
+vi: ts=8
+Sigh.  Of course, I am one of the ts=2 heretics, but Linus' wish is
+my command.
+*/
diff -Nru a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/ibmcam.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,3949 @@
+/*
+ * USB IBM C-It Video Camera driver
+ *
+ * Supports Xirlink C-It Video Camera, IBM PC Camera,
+ * IBM NetCamera and Veo Stingray.
+ *
+ * This driver is based on earlier work of:
+ *
+ * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Randy Dunlap
+ *
+ * 5/24/00 Removed optional (and unnecessary) locking of the driver while
+ * the device remains plugged in. Corrected race conditions in ibmcam_open
+ * and ibmcam_probe() routines using this as a guideline:
+ *
+ * (2) The big kernel lock is automatically released when a process sleeps
+ *   in the kernel and is automatically reacquired on reschedule if the
+ *   process had the lock originally.  Any code that can be compiled as
+ *   a module and is entered with the big kernel lock held *MUST*
+ *   increment the use count to activate the indirect module protection
+ *   before doing anything that might sleep.
+ *
+ *   In practice, this means that all routines that live in modules and
+ *   are invoked under the big kernel lock should do MOD_INC_USE_COUNT
+ *   as their very first action.  And all failure paths from that
+ *   routine must do MOD_DEC_USE_COUNT before returning.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wrapper.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "usbvideo.h"
+
+#define IBMCAM_VENDOR_ID	0x0545
+#define IBMCAM_PRODUCT_ID	0x8080
+#define NETCAM_PRODUCT_ID	0x8002	/* IBM NetCamera, close to model 2 */
+#define VEO_800C_PRODUCT_ID	0x800C	/* Veo Stingray, repackaged Model 2 */
+#define VEO_800D_PRODUCT_ID	0x800D	/* Veo Stingray, repackaged Model 4 */
+
+#define MAX_IBMCAM		4	/* How many devices we allow to connect */
+#define USES_IBMCAM_PUTPIXEL    0       /* 0=Fast/oops 1=Slow/secure */
+
+/* Header signatures */
+
+/* Model 1 header: 00 FF 00 xx */
+#define HDRSIG_MODEL1_128x96	0x06	/* U Y V Y ... */
+#define HDRSIG_MODEL1_176x144	0x0e	/* U Y V Y ... */
+#define HDRSIG_MODEL1_352x288	0x00	/* V Y U Y ... */
+
+#define	IBMCAM_MODEL_1	1	/* XVP-501, 3 interfaces, rev. 0.02 */
+#define IBMCAM_MODEL_2	2	/* KSX-X9903, 2 interfaces, rev. 3.0a */
+#define IBMCAM_MODEL_3	3	/* KSX-X9902, 2 interfaces, rev. 3.01 */
+#define	IBMCAM_MODEL_4	4	/* IBM NetCamera, 0545/8002/3.0a */
+
+/* Video sizes supported */
+#define	VIDEOSIZE_128x96	VIDEOSIZE(128, 96)
+#define	VIDEOSIZE_176x144	VIDEOSIZE(176,144)
+#define	VIDEOSIZE_352x288	VIDEOSIZE(352,288)
+#define	VIDEOSIZE_320x240	VIDEOSIZE(320,240)
+#define	VIDEOSIZE_352x240	VIDEOSIZE(352,240)
+#define	VIDEOSIZE_640x480	VIDEOSIZE(640,480)
+#define	VIDEOSIZE_160x120	VIDEOSIZE(160,120)
+
+/* Video sizes supported */
+enum {
+	SIZE_128x96 = 0,
+	SIZE_160x120,
+	SIZE_176x144,
+	SIZE_320x240,
+	SIZE_352x240,
+	SIZE_352x288,
+	SIZE_640x480,
+	/* Add/remove/rearrange items before this line */
+	SIZE_LastItem
+};
+
+/*
+ * This structure lives in uvd_t->user field.
+ */
+typedef struct {
+	int initialized;	/* Had we already sent init sequence? */
+	int camera_model;	/* What type of IBM camera we got? */
+	int has_hdr;
+} ibmcam_t;
+#define	IBMCAM_T(uvd)	((ibmcam_t *)((uvd)->user_data))
+
+usbvideo_t *cams = NULL;
+
+static int debug = 0;
+
+static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
+
+static const int min_canvasWidth  = 8;
+static const int min_canvasHeight = 4;
+
+static int lighting = 1; /* Medium */
+
+#define SHARPNESS_MIN	0
+#define SHARPNESS_MAX	6
+static int sharpness = 4; /* Low noise, good details */
+
+#define FRAMERATE_MIN	0
+#define FRAMERATE_MAX	6
+static int framerate = -1;
+
+static int size = SIZE_352x288;
+
+/*
+ * Here we define several initialization variables. They may
+ * be used to automatically set color, hue, brightness and
+ * contrast to desired values. This is particularly useful in
+ * case of webcams (which have no controls and no on-screen
+ * output) and also when a client V4L software is used that
+ * does not have some of those controls. In any case it's
+ * good to have startup values as options.
+ *
+ * These values are all in [0..255] range. This simplifies
+ * operation. Note that actual values of V4L variables may
+ * be scaled up (as much as << 8). User can see that only
+ * on overlay output, however, or through a V4L client.
+ */
+static int init_brightness = 128;
+static int init_contrast = 192;
+static int init_color = 128;
+static int init_hue = 128;
+static int hue_correction = 128;
+
+/* Settings for camera model 2 */
+static int init_model2_rg2 = -1;
+static int init_model2_sat = -1;
+static int init_model2_yb = -1;
+
+/* 01.01.08 - Added for RCA video in support -LO */
+/* Settings for camera model 3 */
+static int init_model3_input = 0;
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+MODULE_PARM(flags, "i");
+MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
+MODULE_PARM(framerate, "i");
+MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
+MODULE_PARM(lighting, "i");
+MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
+MODULE_PARM(sharpness, "i");
+MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
+MODULE_PARM(size, "i");
+MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480  (default=5)");
+MODULE_PARM(init_brightness, "i");
+MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
+MODULE_PARM(init_contrast, "i");
+MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
+MODULE_PARM(init_color, "i");
+MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
+MODULE_PARM(init_hue, "i");
+MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
+MODULE_PARM(hue_correction, "i");
+MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
+
+MODULE_PARM(init_model2_rg2, "i");
+MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
+MODULE_PARM(init_model2_sat, "i");
+MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
+MODULE_PARM(init_model2_yb, "i");
+MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
+
+/* 01.01.08 - Added for RCA video in support -LO */
+MODULE_PARM(init_model3_input, "i");
+MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
+
+MODULE_AUTHOR ("Dmitri");
+MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
+MODULE_LICENSE("GPL");
+
+/* Still mysterious i2c commands */
+static const unsigned short unknown_88 = 0x0088;
+static const unsigned short unknown_89 = 0x0089;
+static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 };
+static const unsigned short contrast_14 = 0x0014;
+static const unsigned short light_27 = 0x0027;
+static const unsigned short sharp_13 = 0x0013;
+
+/* i2c commands for Model 2 cameras */
+static const unsigned short mod2_brightness = 0x001a;		/* $5b .. $ee; default=$5a */
+static const unsigned short mod2_set_framerate = 0x001c;	/* 0 (fast).. $1F (slow) */
+static const unsigned short mod2_color_balance_rg2 = 0x001e;	/* 0 (red) .. $7F (green) */
+static const unsigned short mod2_saturation = 0x0020;		/* 0 (b/w) - $7F (full color) */
+static const unsigned short mod2_color_balance_yb = 0x0022;	/* 0..$7F, $50 is about right */
+static const unsigned short mod2_hue = 0x0024;			/* 0..$7F, $70 is about right */
+static const unsigned short mod2_sensitivity = 0x0028;		/* 0 (min) .. $1F (max) */
+
+struct struct_initData {
+	unsigned char req;
+	unsigned short value;
+	unsigned short index;
+};
+
+/*
+ * ibmcam_size_to_videosize()
+ *
+ * This procedure converts module option 'size' into the actual
+ * videosize_t that defines the image size in pixels. We need
+ * simplified 'size' because user wants a simple enumerated list
+ * of choices, not an infinite set of possibilities.
+ */
+static videosize_t ibmcam_size_to_videosize(int size)
+{
+	videosize_t vs = VIDEOSIZE_352x288;
+	RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1));
+	switch (size) {
+	case SIZE_128x96:
+		vs = VIDEOSIZE_128x96;
+		break;
+	case SIZE_160x120:
+		vs = VIDEOSIZE_160x120;
+		break;
+	case SIZE_176x144:
+		vs = VIDEOSIZE_176x144;
+		break;
+	case SIZE_320x240:
+		vs = VIDEOSIZE_320x240;
+		break;
+	case SIZE_352x240:
+		vs = VIDEOSIZE_352x240;
+		break;
+	case SIZE_352x288:
+		vs = VIDEOSIZE_352x288;
+		break;
+	case SIZE_640x480:
+		vs = VIDEOSIZE_640x480;
+		break;
+	default:
+		err("size=%d. is not valid", size);
+		break;
+	}
+	return vs;
+}
+
+/*
+ * ibmcam_find_header()
+ *
+ * Locate one of supported header markers in the queue.
+ * Once found, remove all preceding bytes AND the marker (4 bytes)
+ * from the data pump queue. Whatever follows must be video lines.
+ *
+ * History:
+ * 1/21/00  Created.
+ */
+static ParseState_t ibmcam_find_header(uvd_t *uvd) /* FIXME: Add frame here */
+{
+	usbvideo_frame_t *frame;
+	ibmcam_t *icam;
+
+	if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
+		err("ibmcam_find_header: Illegal frame %d.", uvd->curframe);
+		return scan_EndParse;
+	}
+	icam = IBMCAM_T(uvd);
+	assert(icam != NULL);
+	frame = &uvd->frame[uvd->curframe];
+	icam->has_hdr = 0;
+	switch (icam->camera_model) {
+	case IBMCAM_MODEL_1:
+	{
+		const int marker_len = 4;
+		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
+			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
+			{
+#if 0				/* This code helps to detect new frame markers */
+				info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3));
+#endif
+				frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
+				if ((frame->header == HDRSIG_MODEL1_128x96) ||
+				    (frame->header == HDRSIG_MODEL1_176x144) ||
+				    (frame->header == HDRSIG_MODEL1_352x288))
+				{
+#if 0
+					info("Header found.");
+#endif
+					RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
+					icam->has_hdr = 1;
+					break;
+				}
+			}
+			/* If we are still here then this doesn't look like a header */
+			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+		}
+		break;
+	}
+	case IBMCAM_MODEL_2:
+case IBMCAM_MODEL_4:
+	{
+		int marker_len = 0;
+		switch (uvd->videosize) {
+		case VIDEOSIZE_176x144:
+			marker_len = 10;
+			break;
+		default:
+			marker_len = 2;
+			break;
+		}
+		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
+			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
+			{
+#if 0
+				info("Header found.");
+#endif
+				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
+				icam->has_hdr = 1;
+				frame->header = HDRSIG_MODEL1_176x144;
+				break;
+			}
+			/* If we are still here then this doesn't look like a header */
+			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+		}
+		break;
+	}
+	case IBMCAM_MODEL_3:
+	{	/*
+		 * Headers: (one precedes every frame). nc=no compression,
+		 * bq=best quality bf=best frame rate.
+		 *
+		 * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf }
+		 * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf }
+		 * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf }
+		 *
+		 * Bytes '00 FF' seem to indicate header. Other two bytes
+		 * encode the frame type. This is a set of bit fields that
+		 * encode image size, compression type etc. These fields
+		 * do NOT contain frame number because all frames carry
+		 * the same header.
+		 */
+		const int marker_len = 4;
+		while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
+			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF))
+			{
+				/*
+				 * Combine 2 bytes of frame type into one
+				 * easy to use value
+				 */
+				unsigned long byte3, byte4;
+
+				byte3 = RING_QUEUE_PEEK(&uvd->dp, 2);
+				byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
+				frame->header = (byte3 << 8) | byte4;
+#if 0
+				info("Header found.");
+#endif
+				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
+				icam->has_hdr = 1;
+				break;
+			}
+			/* If we are still here then this doesn't look like a header */
+			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+		}
+		break;
+	}
+	default:
+		break;
+	}
+	if (!icam->has_hdr) {
+		if (uvd->debug > 2)
+			info("Skipping frame, no header");
+		return scan_EndParse;
+	}
+
+	/* Header found */
+	icam->has_hdr = 1;
+	uvd->stats.header_count++;
+	frame->scanstate = ScanState_Lines;
+	frame->curline = 0;
+
+	if (flags & FLAGS_FORCE_TESTPATTERN) {
+		usbvideo_TestPattern(uvd, 1, 1);
+		return scan_NextFrame;
+	}
+	return scan_Continue;
+}
+
+/*
+ * ibmcam_parse_lines()
+ *
+ * Parse one line (interlaced) from the buffer, put
+ * decoded RGB value into the current frame buffer
+ * and add the written number of bytes (RGB) to
+ * the *pcopylen.
+ *
+ * History:
+ * 21-Jan-2000 Created.
+ * 12-Oct-2000 Reworked to reflect interlaced nature of the data.
+ */
+static ParseState_t ibmcam_parse_lines(
+	uvd_t *uvd,
+	usbvideo_frame_t *frame,
+	long *pcopylen)
+{
+	unsigned char *f;
+	ibmcam_t *icam;
+	unsigned int len, scanLength, scanHeight, order_uv, order_yc;
+	int v4l_linesize; /* V4L line offset */
+	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
+	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
+	const int ccm = 128; /* Color correction median - see below */
+	int y, u, v, i, frame_done=0, color_corr;
+	static unsigned char lineBuffer[640*3];
+	unsigned const char *chromaLine, *lumaLine;
+
+	assert(uvd != NULL);
+	assert(frame != NULL);
+	icam = IBMCAM_T(uvd);
+	assert(icam != NULL);
+	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
+
+	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
+
+	if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) {
+		/* Model 4 frame markers do not carry image size identification */
+		switch (uvd->videosize) {
+		case VIDEOSIZE_128x96:
+		case VIDEOSIZE_160x120:
+		case VIDEOSIZE_176x144:
+			scanLength = VIDEOSIZE_X(uvd->videosize);
+			scanHeight = VIDEOSIZE_Y(uvd->videosize);
+			break;
+		default:
+			err("ibmcam_parse_lines: Wrong mode.");
+			return scan_Out;
+		}
+		order_yc = 1;	/* order_yc: true=Yc false=cY ('c'=either U or V) */
+		order_uv = 1;	/* Always true in this algorithm */
+	} else {
+		switch (frame->header) {
+		case HDRSIG_MODEL1_128x96:
+			scanLength = 128;
+			scanHeight = 96;
+			order_uv = 1;	/* U Y V Y ... */
+			break;
+		case HDRSIG_MODEL1_176x144:
+			scanLength = 176;
+			scanHeight = 144;
+			order_uv = 1;	/* U Y V Y ... */
+			break;
+		case HDRSIG_MODEL1_352x288:
+			scanLength = 352;
+			scanHeight = 288;
+			order_uv = 0;	/* Y V Y V ... */
+			break;
+		default:
+			err("Unknown header signature 00 FF 00 %02lX", frame->header);
+			return scan_NextFrame;
+		}
+		/* order_yc: true=Yc false=cY ('c'=either U or V) */
+		order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2);
+	}
+
+	len = scanLength * 3;
+	assert(len <= sizeof(lineBuffer));
+
+	/*
+	 * Lines are organized this way:
+	 *
+	 * I420:
+	 * ~~~~
+	 * <scanLength->
+	 * ___________________________________
+	 * |-----Y-----|---UVUVUV...UVUV-----| \
+	 * |-----------+---------------------|  \
+	 * |<-- 176 -->|<------ 176*2 ------>|  Total 72. lines (interlaced)
+	 * |...	   ... |        ...          |  /
+	 * |<-- 352 -->|<------ 352*2 ------>|  Total 144. lines (interlaced)
+	 * |___________|_____________________| /
+	 *  \           \
+	 *   lumaLine    chromaLine
+	 */
+
+	/* Make sure there's enough data for the entire line */
+	if (RingQueue_GetLength(&uvd->dp) < len)
+		return scan_Out;
+
+	/* Suck one line out of the ring queue */
+	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
+
+	/*
+	 * Make sure that our writing into output buffer
+	 * will not exceed the buffer. Mind that we may write
+	 * not into current output scanline but in several after
+	 * it as well (if we enlarge image vertically.)
+	 */
+	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
+		return scan_NextFrame;
+
+	/*
+	 * Now we are sure that entire line (representing all 'scanLength'
+	 * pixels from the camera) is available in the buffer. We
+	 * start copying the line left-aligned to the V4L buffer.
+	 * If the camera line is shorter then we should pad the V4L
+	 * buffer with something (black) to complete the line.
+	 */
+	assert(frame->data != NULL);
+	f = frame->data + (v4l_linesize * frame->curline);
+
+	/*
+	 * To obtain chrominance data from the 'chromaLine' use this:
+	 *   v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]...
+	 *   u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]...
+	 *
+	 * Indices must be calculated this way:
+	 * v_index = (i >> 1) << 2;
+	 * u_index = (i >> 1) << 2 + 2;
+	 *
+	 * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1]
+	 */
+	lumaLine = lineBuffer;
+	chromaLine = lineBuffer + scanLength;
+	for (i = 0; i < VIDEOSIZE_X(frame->request); i++)
+	{
+		unsigned char rv, gv, bv;	/* RGB components */
+
+		/* Check for various visual debugging hints (colorized pixels) */
+		if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) {
+			/*
+			 * This is bad and should not happen. This means that
+			 * we somehow overshoot the line and encountered new
+			 * frame! Obviously our camera/V4L frame size is out
+			 * of whack. This cyan dot will help you to figure
+			 * out where exactly the new frame arrived.
+			 */
+			if (icam->has_hdr == 1) {
+				bv = 0; /* Yellow marker */
+				gv = 0xFF;
+				rv = 0xFF;
+			} else {
+				bv = 0xFF; /* Cyan marker */
+				gv = 0xFF;
+				rv = 0;
+			}
+			icam->has_hdr = 0;
+			goto make_pixel;
+		}
+
+		/*
+		 * Check if we are still in range. We may be out of range if our
+		 * V4L canvas is wider or taller than the camera "native" image.
+		 * Then we quickly fill the remainder of the line with zeros to
+		 * make black color and quit the horizontal scanning loop.
+		 */
+		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
+			const int j = i * V4L_BYTES_PER_PIXEL;
+#if USES_IBMCAM_PUTPIXEL
+			/* Refresh 'f' because we don't use it much with PUTPIXEL */
+			f = frame->data + (v4l_linesize * frame->curline) + j;
+#endif
+			memset(f, 0, v4l_linesize - j);
+			break;
+		}
+
+		y = lumaLine[i];
+		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
+			rv = gv = bv = y;
+		else {
+			int off_0, off_2;
+
+			off_0 = (i >> 1) << 2;
+			off_2 = off_0 + 2;
+
+			if (order_yc) {
+				off_0++;
+				off_2++;
+			}
+			if (!order_uv) {
+				off_0 += 2;
+				off_2 -= 2;
+			}
+			u = chromaLine[off_0] + hue_corr;
+			v = chromaLine[off_2] + hue2_corr;
+
+			/* Apply color correction */
+			if (color_corr != 0) {
+				/* Magnify up to 2 times, reduce down to zero saturation */
+				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
+				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
+			}
+			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+		}
+
+	make_pixel:
+		/*
+		 * The purpose of creating the pixel here, in one,
+		 * dedicated place is that we may need to make the
+		 * pixel wider and taller than it actually is. This
+		 * may be used if camera generates small frames for
+		 * sake of frame rate (or any other reason.)
+		 *
+		 * The output data consists of B, G, R bytes
+		 * (in this order).
+		 */
+#if USES_IBMCAM_PUTPIXEL
+		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
+#else
+		*f++ = bv;
+		*f++ = gv;
+		*f++ = rv;
+#endif
+		/*
+		 * Typically we do not decide within a legitimate frame
+		 * that we want to end the frame. However debugging code
+		 * may detect marker of new frame within the data. Then
+		 * this condition activates. The 'data' pointer is already
+		 * pointing at the new marker, so we'd better leave it as is.
+		 */
+		if (frame_done)
+			break;	/* End scanning of lines */
+	}
+	/*
+	 * Account for number of bytes that we wrote into output V4L frame.
+	 * We do it here, after we are done with the scanline, because we
+	 * may fill more than one output scanline if we do vertical
+	 * enlargement.
+	 */
+	frame->curline += 2;
+	if (pcopylen != NULL)
+		*pcopylen += 2 * v4l_linesize;
+	frame->deinterlace = Deinterlace_FillOddLines;
+
+	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
+		return scan_NextFrame;
+	else
+		return scan_Continue;
+}
+
+/*
+ * ibmcam_model2_320x240_parse_lines()
+ *
+ * This procedure deals with a weird RGB format that is produced by IBM
+ * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
+ * depending on horizontal size of the picture:
+ *
+ * <--- 160 or 176 pairs of RA,RB bytes ----->
+ * *-----------------------------------------* \
+ * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \   This is pair of horizontal lines,
+ * |-----+-----+-----+-----+ ... +-----+-----|   *- or one interlaced line, total
+ * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   120 or 144 such pairs which yield
+ * |=====+=====+=====+=====+ ... +=====+=====| /    240 or 288 lines after deinterlacing.
+ *
+ * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
+ * defines ONE pixel. Therefore this format yields 176x144 "decoded"
+ * resolution at best. I do not know why camera sends such format - the
+ * previous model (1) just used interlaced I420 and everyone was happy.
+ *
+ * I do not know what is the difference between RAi and RBi bytes. Both
+ * seemingly represent R component, but slightly vary in value (so that
+ * the picture looks a bit colored if one or another is used). I use
+ * them both as R component in attempt to at least partially recover the
+ * lost resolution.
+ */
+static ParseState_t ibmcam_model2_320x240_parse_lines(
+	uvd_t *uvd,
+	usbvideo_frame_t *frame,
+	long *pcopylen)
+{
+	unsigned char *f, *la, *lb;
+	unsigned int len;
+	int v4l_linesize; /* V4L line offset */
+	int i, j, frame_done=0, color_corr;
+	int scanLength, scanHeight;
+	static unsigned char lineBuffer[352*2];
+
+	switch (uvd->videosize) {
+	case VIDEOSIZE_320x240:
+	case VIDEOSIZE_352x240:
+	case VIDEOSIZE_352x288:
+		scanLength = VIDEOSIZE_X(uvd->videosize);
+		scanHeight = VIDEOSIZE_Y(uvd->videosize);
+		break;
+	default:
+		err("ibmcam_model2_320x240_parse_lines: Wrong mode.");
+		return scan_Out;
+	}
+
+	color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */
+	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
+
+	len = scanLength * 2; /* See explanation above */
+	assert(len <= sizeof(lineBuffer));
+
+	/* Make sure there's enough data for the entire line */
+	if (RingQueue_GetLength(&uvd->dp) < len)
+		return scan_Out;
+
+	/* Suck one line out of the ring queue */
+	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
+
+	/*
+	 * Make sure that our writing into output buffer
+	 * will not exceed the buffer. Mind that we may write
+	 * not into current output scanline but in several after
+	 * it as well (if we enlarge image vertically.)
+	 */
+	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
+		return scan_NextFrame;
+
+	la = lineBuffer;
+	lb = lineBuffer + scanLength;
+
+	/*
+	 * Now we are sure that entire line (representing all
+	 *         VIDEOSIZE_X(frame->request)
+	 * pixels from the camera) is available in the scratch buffer. We
+	 * start copying the line left-aligned to the V4L buffer (which
+	 * might be larger - not smaller, hopefully). If the camera
+	 * line is shorter then we should pad the V4L buffer with something
+	 * (black in this case) to complete the line.
+	 */
+	f = frame->data + (v4l_linesize * frame->curline);
+
+	/* Fill the 2-line strip */
+	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+		int y, rv, gv, bv;	/* RGB components */
+
+		j = i & (~1);
+
+		/* Check for various visual debugging hints (colorized pixels) */
+		if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) {
+			if (IBMCAM_T(uvd)->has_hdr == 1) {
+				bv = 0; /* Yellow marker */
+				gv = 0xFF;
+				rv = 0xFF;
+			} else {
+				bv = 0xFF; /* Cyan marker */
+				gv = 0xFF;
+				rv = 0;
+			}
+			IBMCAM_T(uvd)->has_hdr = 0;
+			goto make_pixel;
+		}
+
+		/*
+		 * Check if we are still in range. We may be out of range if our
+		 * V4L canvas is wider or taller than the camera "native" image.
+		 * Then we quickly fill the remainder of the line with zeros to
+		 * make black color and quit the horizontal scanning loop.
+		 */
+		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
+			const int j = i * V4L_BYTES_PER_PIXEL;
+#if USES_IBMCAM_PUTPIXEL
+			/* Refresh 'f' because we don't use it much with PUTPIXEL */
+			f = frame->data + (v4l_linesize * frame->curline) + j;
+#endif
+			memset(f, 0, v4l_linesize - j);
+			break;
+		}
+
+		/*
+		 * Here I use RA and RB components, one per physical pixel.
+		 * This causes fine vertical grid on the picture but may improve
+		 * horizontal resolution. If you prefer replicating, use this:
+		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];
+		 * then the pixel will be replicated.
+		 */
+		rv = la[i];
+		gv = lb[j + 1];
+		bv = lb[j + 0];
+
+		y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */
+
+		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
+			rv = gv = bv = y;
+		else if (color_corr != 128) {
+
+			/* Calculate difference between color and brightness */
+			rv -= y;
+			gv -= y;
+			bv -= y;
+
+			/* Scale differences */
+			rv = (rv * color_corr) / 128;
+			gv = (gv * color_corr) / 128;
+			bv = (bv * color_corr) / 128;
+
+			/* Reapply brightness */
+			rv += y;
+			gv += y;
+			bv += y;
+
+			/* Watch for overflows */
+			RESTRICT_TO_RANGE(rv, 0, 255);
+			RESTRICT_TO_RANGE(gv, 0, 255);
+			RESTRICT_TO_RANGE(bv, 0, 255);
+		}
+
+	make_pixel:
+		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
+	}
+	/*
+	 * Account for number of bytes that we wrote into output V4L frame.
+	 * We do it here, after we are done with the scanline, because we
+	 * may fill more than one output scanline if we do vertical
+	 * enlargement.
+	 */
+	frame->curline += 2;
+	*pcopylen += v4l_linesize * 2;
+	frame->deinterlace = Deinterlace_FillOddLines;
+
+	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
+		return scan_NextFrame;
+	else
+		return scan_Continue;
+}
+
+static ParseState_t ibmcam_model3_parse_lines(
+	uvd_t *uvd,
+	usbvideo_frame_t *frame,
+	long *pcopylen)
+{
+	unsigned char *data;
+	const unsigned char *color;
+	unsigned int len;
+	int v4l_linesize; /* V4L line offset */
+	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */
+	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */
+	const int ccm = 128; /* Color correction median - see below */
+	int i, u, v, rw, data_w=0, data_h=0, color_corr;
+	static unsigned char lineBuffer[640*3];
+
+	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
+
+	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
+
+	/* The header tells us what sort of data is in this frame */
+	switch (frame->header) {
+		/*
+		 * Uncompressed modes (that are easy to decode).
+		 */
+	case 0x0308:
+		data_w = 640;
+		data_h = 480;
+		break;
+	case 0x0208:
+		data_w = 320;
+		data_h = 240;
+		break;
+	case 0x020A:
+		data_w = 160;
+		data_h = 120;
+		break;
+		/*
+		 * Compressed modes (ViCE - that I don't know how to decode).
+		 */
+	case 0x0328:	/* 640x480, best quality compression */
+	case 0x0368:	/* 640x480, best frame rate compression */
+	case 0x0228:	/* 320x240, best quality compression */
+	case 0x0268:	/* 320x240, best frame rate compression */
+	case 0x02CA:	/* 160x120, best quality compression */
+	case 0x02EA:	/* 160x120, best frame rate compression */
+		/* Do nothing with this - not supported */
+		err("Unsupported mode $%04lx", frame->header);
+		return scan_NextFrame;
+	default:
+		/* Catch unknown headers, may help in learning new headers */
+		err("Strange frame->header=$%08lx", frame->header);
+		return scan_NextFrame;
+	}
+
+	/*
+	 * Make sure that our writing into output buffer
+	 * will not exceed the buffer. Note that we may write
+	 * not into current output scanline but in several after
+	 * it as well (if we enlarge image vertically.)
+	 */
+	if ((frame->curline + 1) >= data_h) {
+		if (uvd->debug >= 3)
+			info("Reached line %d. (frame is done)", frame->curline);
+		return scan_NextFrame;
+	}
+
+	/* Make sure there's enough data for the entire line */
+	len = 3 * data_w; /* <y-data> <uv-data> */
+	assert(len <= sizeof(lineBuffer));
+
+	/* Make sure there's enough data for the entire line */
+	if (RingQueue_GetLength(&uvd->dp) < len)
+		return scan_Out;
+
+	/* Suck one line out of the ring queue */
+	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
+
+	data = lineBuffer;
+	color = data + data_w;		/* Point to where color planes begin */
+
+	/* Bottom-to-top scanning */
+	rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
+	RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
+
+	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+		int y, rv, gv, bv;	/* RGB components */
+
+		if (i < data_w) {
+			y = data[i];	/* Luminosity is the first line */
+
+			/* Apply static color correction */
+			u = color[i*2] + hue_corr;
+			v = color[i*2 + 1] + hue2_corr;
+
+			/* Apply color correction */
+			if (color_corr != 0) {
+				/* Magnify up to 2 times, reduce down to zero saturation */
+				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
+				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
+			}
+		} else
+			y = 0, u = v = 128;
+
+		YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
+		RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
+	}
+	frame->deinterlace = Deinterlace_FillEvenLines;
+
+	/*
+	 * Account for number of bytes that we wrote into output V4L frame.
+	 * We do it here, after we are done with the scanline, because we
+	 * may fill more than one output scanline if we do vertical
+	 * enlargement.
+	 */
+	frame->curline += 2;
+	*pcopylen += 2 * v4l_linesize;
+
+	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
+		if (uvd->debug >= 3) {
+			info("All requested lines (%ld.) done.",
+			     VIDEOSIZE_Y(frame->request));
+		}
+		return scan_NextFrame;
+	} else
+		return scan_Continue;
+}
+
+/*
+ * ibmcam_model4_128x96_parse_lines()
+ *
+ * This decoder is for one strange data format that is produced by Model 4
+ * camera only in 128x96 mode. This is RGB format and here is its description.
+ * First of all, this is non-interlaced stream, meaning that all scan lines
+ * are present in the datastream. There are 96 consecutive blocks of data
+ * that describe all 96 lines of the image. Each block is 5*128 bytes long
+ * and carries R, G, B components. The format of the block is shown in the
+ * code below. First 128*2 bytes are interleaved R and G components. Then
+ * we have a gap (junk data) 64 bytes long. Then follow B and something
+ * else, also interleaved (this makes another 128*2 bytes). After that
+ * probably another 64 bytes of junk follow.
+ *
+ * History:
+ * 10-Feb-2001 Created.
+ */
+static ParseState_t ibmcam_model4_128x96_parse_lines(
+	uvd_t *uvd,
+	usbvideo_frame_t *frame,
+	long *pcopylen)
+{
+	const unsigned char *data_rv, *data_gv, *data_bv;
+	unsigned int len;
+	int i, v4l_linesize; /* V4L line offset */
+	const int data_w=128, data_h=96;
+	static unsigned char lineBuffer[128*5];
+
+	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
+
+	/*
+	 * Make sure that our writing into output buffer
+	 * will not exceed the buffer. Note that we may write
+	 * not into current output scanline but in several after
+	 * it as well (if we enlarge image vertically.)
+	 */
+	if ((frame->curline + 1) >= data_h) {
+		if (uvd->debug >= 3)
+			info("Reached line %d. (frame is done)", frame->curline);
+		return scan_NextFrame;
+	}
+
+	/*
+	 * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________
+	 * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 --->
+	 */
+
+	/* Make sure there's enough data for the entire line */
+	len = 5 * data_w;
+	assert(len <= sizeof(lineBuffer));
+
+	/* Make sure there's enough data for the entire line */
+	if (RingQueue_GetLength(&uvd->dp) < len)
+		return scan_Out;
+
+	/* Suck one line out of the ring queue */
+	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
+
+	data_rv = lineBuffer;
+	data_gv = lineBuffer + 1;
+	data_bv = lineBuffer + data_w*2 + data_w/2;
+	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+		int rv, gv, bv;	/* RGB components */
+		if (i < data_w) {
+			const int j = i * 2;
+			gv = data_rv[j];
+			rv = data_gv[j];
+			bv = data_bv[j];
+			if (flags & FLAGS_MONOCHROME) {
+				unsigned long y;
+				y = rv + gv + bv;
+				y /= 3;
+				if (y > 0xFF)
+					y = 0xFF;
+				rv = gv = bv = (unsigned char) y;
+			}
+		} else {
+			rv = gv = bv = 0;
+		}
+		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
+	}
+	frame->deinterlace = Deinterlace_None;
+	frame->curline++;
+	*pcopylen += v4l_linesize;
+
+	if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
+		if (uvd->debug >= 3) {
+			info("All requested lines (%ld.) done.",
+			     VIDEOSIZE_Y(frame->request));
+		}
+		return scan_NextFrame;
+	} else
+		return scan_Continue;
+}
+
+/*
+ * ibmcam_ProcessIsocData()
+ *
+ * Generic routine to parse the ring queue data. It employs either
+ * ibmcam_find_header() or ibmcam_parse_lines() to do most
+ * of work.
+ *
+ * History:
+ * 1/21/00  Created.
+ */
+void ibmcam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
+{
+	ParseState_t newstate;
+	long copylen = 0;
+	int mod = IBMCAM_T(uvd)->camera_model;
+
+	while (1) {
+		newstate = scan_Out;
+		if (RingQueue_GetLength(&uvd->dp) > 0) {
+			if (frame->scanstate == ScanState_Scanning) {
+				newstate = ibmcam_find_header(uvd);
+			} else if (frame->scanstate == ScanState_Lines) {
+				if ((mod == IBMCAM_MODEL_2) &&
+				    ((uvd->videosize == VIDEOSIZE_352x288) ||
+				     (uvd->videosize == VIDEOSIZE_320x240) ||
+				     (uvd->videosize == VIDEOSIZE_352x240)))
+				{
+					newstate = ibmcam_model2_320x240_parse_lines(
+						uvd, frame, &copylen);
+				} else if (mod == IBMCAM_MODEL_4) {
+					/*
+					 * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB)
+					 * for 320x240 and above; 160x120 and 176x144 uses Model 1
+					 * decoder (YUV), and 128x96 mode uses ???
+					 */
+					if ((uvd->videosize == VIDEOSIZE_352x288) ||
+					    (uvd->videosize == VIDEOSIZE_320x240) ||
+					    (uvd->videosize == VIDEOSIZE_352x240))
+					{
+						newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, &copylen);
+					} else if (uvd->videosize == VIDEOSIZE_128x96) {
+						newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, &copylen);
+					} else {
+						newstate = ibmcam_parse_lines(uvd, frame, &copylen);
+					}
+				} else if (mod == IBMCAM_MODEL_3) {
+					newstate = ibmcam_model3_parse_lines(uvd, frame, &copylen);
+				} else {
+					newstate = ibmcam_parse_lines(uvd, frame, &copylen);
+				}
+			}
+		}
+		if (newstate == scan_Continue)
+			continue;
+		else if ((newstate == scan_NextFrame) || (newstate == scan_Out))
+			break;
+		else
+			return; /* scan_EndParse */
+	}
+
+	if (newstate == scan_NextFrame) {
+		frame->frameState = FrameState_Done;
+		uvd->curframe = -1;
+		uvd->stats.frame_num++;
+		if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) {
+			/* Need software contrast adjustment for those cameras */
+			frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST;
+		}
+	}
+
+	/* Update the frame's uncompressed length. */
+	frame->seqRead_Length += copylen;
+
+#if 0
+	{
+		static unsigned char j=0;
+		memset(frame->data, j++, uvd->max_frame_size);
+		frame->frameState = FrameState_Ready;
+	}
+#endif
+}
+
+/*
+ * ibmcam_veio()
+ *
+ * History:
+ * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
+ */
+static int ibmcam_veio(
+	uvd_t *uvd,
+	unsigned char req,
+	unsigned short value,
+	unsigned short index)
+{
+	static const char proc[] = "ibmcam_veio";
+	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
+	int i;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return 0;
+
+	if (req == 1) {
+		i = usb_control_msg(
+			uvd->dev,
+			usb_rcvctrlpipe(uvd->dev, 0),
+			req,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+			value,
+			index,
+			cp,
+			sizeof(cp),
+			HZ);
+#if 0
+		info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
+		       "(req=$%02x val=$%04x ind=$%04x)",
+		       cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
+		       req, value, index);
+#endif
+	} else {
+		i = usb_control_msg(
+			uvd->dev,
+			usb_sndctrlpipe(uvd->dev, 0),
+			req,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+			value,
+			index,
+			NULL,
+			0,
+			HZ);
+	}
+	if (i < 0) {
+		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
+		    proc, i);
+		uvd->last_error = i;
+	}
+	return i;
+}
+
+/*
+ * ibmcam_calculate_fps()
+ *
+ * This procedure roughly calculates the real frame rate based
+ * on FPS code (framerate=NNN option). Actual FPS differs
+ * slightly depending on lighting conditions, so that actual frame
+ * rate is determined by the camera. Since I don't know how to ask
+ * the camera what FPS is now I have to use the FPS code instead.
+ *
+ * The FPS code is in range [0..6], 0 is slowest, 6 is fastest.
+ * Corresponding real FPS should be in range [3..30] frames per second.
+ * The conversion formula is obvious:
+ *
+ * real_fps = 3 + (fps_code * 4.5)
+ *
+ * History:
+ * 1/18/00  Created.
+ */
+static int ibmcam_calculate_fps(uvd_t *uvd)
+{
+	return 3 + framerate*4 + framerate/2;
+}
+
+/*
+ * ibmcam_send_FF_04_02()
+ *
+ * This procedure sends magic 3-command prefix to the camera.
+ * The purpose of this prefix is not known.
+ *
+ * History:
+ * 1/2/00   Created.
+ */
+static void ibmcam_send_FF_04_02(uvd_t *uvd)
+{
+	ibmcam_veio(uvd, 0, 0x00FF, 0x0127);
+	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
+}
+
+static void ibmcam_send_00_04_06(uvd_t *uvd)
+{
+	ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+	ibmcam_veio(uvd, 0, 0x0004, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0006, 0x0124);
+}
+
+static void ibmcam_send_x_00(uvd_t *uvd, unsigned short x)
+{
+	ibmcam_veio(uvd, 0, x,      0x0127);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
+}
+
+static void ibmcam_send_x_00_05(uvd_t *uvd, unsigned short x)
+{
+	ibmcam_send_x_00(uvd, x);
+	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
+}
+
+static void ibmcam_send_x_00_05_02(uvd_t *uvd, unsigned short x)
+{
+	ibmcam_veio(uvd, 0, x,      0x0127);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
+}
+
+static void ibmcam_send_x_01_00_05(uvd_t *uvd, unsigned short x)
+{
+	ibmcam_veio(uvd, 0, x,      0x0127);
+	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
+}
+
+static void ibmcam_send_x_00_05_02_01(uvd_t *uvd, unsigned short x)
+{
+	ibmcam_veio(uvd, 0, x,      0x0127);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
+}
+
+static void ibmcam_send_x_00_05_02_08_01(uvd_t *uvd, unsigned short x)
+{
+	ibmcam_veio(uvd, 0, x,      0x0127);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0005, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0008, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0001, 0x0124);
+}
+
+static void ibmcam_Packet_Format1(uvd_t *uvd, unsigned char fkey, unsigned char val)
+{
+	ibmcam_send_x_01_00_05(uvd, unknown_88);
+	ibmcam_send_x_00_05(uvd, fkey);
+	ibmcam_send_x_00_05_02_08_01(uvd, val);
+	ibmcam_send_x_00_05(uvd, unknown_88);
+	ibmcam_send_x_00_05_02_01(uvd, fkey);
+	ibmcam_send_x_00_05(uvd, unknown_89);
+	ibmcam_send_x_00(uvd, fkey);
+	ibmcam_send_00_04_06(uvd);
+	ibmcam_veio(uvd, 1, 0x0000, 0x0126);
+	ibmcam_send_FF_04_02(uvd);
+}
+
+static void ibmcam_PacketFormat2(uvd_t *uvd, unsigned char fkey, unsigned char val)
+{
+	ibmcam_send_x_01_00_05	(uvd, unknown_88);
+	ibmcam_send_x_00_05	(uvd, fkey);
+	ibmcam_send_x_00_05_02	(uvd, val);
+}
+
+static void ibmcam_model2_Packet2(uvd_t *uvd)
+{
+	ibmcam_veio(uvd, 0, 0x00ff, 0x012d);
+	ibmcam_veio(uvd, 0, 0xfea3, 0x0124);
+}
+
+static void ibmcam_model2_Packet1(uvd_t *uvd, unsigned short v1, unsigned short v2)
+{
+	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+	ibmcam_veio(uvd, 0, 0x00ff, 0x012e);
+	ibmcam_veio(uvd, 0, v1,     0x012f);
+	ibmcam_veio(uvd, 0, 0x00ff, 0x0130);
+	ibmcam_veio(uvd, 0, 0xc719, 0x0124);
+	ibmcam_veio(uvd, 0, v2,     0x0127);
+
+	ibmcam_model2_Packet2(uvd);
+}
+
+/*
+ * ibmcam_model3_Packet1()
+ *
+ * 00_0078_012d	
+ * 00_0097_012f
+ * 00_d141_0124	
+ * 00_0096_0127
+ * 00_fea8_0124	
+*/
+static void ibmcam_model3_Packet1(uvd_t *uvd, unsigned short v1, unsigned short v2)
+{
+	ibmcam_veio(uvd, 0, 0x0078, 0x012d);
+	ibmcam_veio(uvd, 0, v1,     0x012f);
+	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+	ibmcam_veio(uvd, 0, v2,     0x0127);
+	ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+}
+
+static void ibmcam_model4_BrightnessPacket(uvd_t *uvd, int i)
+{
+	ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+	ibmcam_veio(uvd, 0, 0x0026, 0x012f);
+	ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+	ibmcam_veio(uvd, 0, i,      0x0127);
+	ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+	ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+	ibmcam_veio(uvd, 0, 0x0038, 0x012d);
+	ibmcam_veio(uvd, 0, 0x0004, 0x012f);
+	ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+	ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+}
+
+/*
+ * ibmcam_adjust_contrast()
+ *
+ * The contrast value changes from 0 (high contrast) to 15 (low contrast).
+ * This is in reverse to usual order of things (such as TV controls), so
+ * we reverse it again here.
+ *
+ * TODO: we probably don't need to send the setup 5 times...
+ *
+ * History:
+ * 1/2/00   Created.
+ */
+static void ibmcam_adjust_contrast(uvd_t *uvd)
+{
+	unsigned char a_contrast = uvd->vpic.contrast >> 12;
+	unsigned char new_contrast;
+
+	if (a_contrast >= 16)
+		a_contrast = 15;
+	new_contrast = 15 - a_contrast;
+	if (new_contrast == uvd->vpic_old.contrast)
+		return;
+	uvd->vpic_old.contrast = new_contrast;
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_1:
+	{
+		const int ntries = 5;
+		int i;
+		for (i=0; i < ntries; i++) {
+			ibmcam_Packet_Format1(uvd, contrast_14, new_contrast);
+			ibmcam_send_FF_04_02(uvd);
+		}
+		break;
+	}
+	case IBMCAM_MODEL_2:
+	case IBMCAM_MODEL_4:
+		/* Models 2, 4 do not have this control; implemented in software. */
+		break;
+	case IBMCAM_MODEL_3:
+	{	/* Preset hardware values */
+		static const struct {
+			unsigned short cv1;
+			unsigned short cv2;
+			unsigned short cv3;
+		} cv[7] = {
+			{ 0x05, 0x05, 0x0f },	/* Minimum */
+			{ 0x04, 0x04, 0x16 },
+			{ 0x02, 0x03, 0x16 },
+			{ 0x02, 0x08, 0x16 },
+			{ 0x01, 0x0c, 0x16 },
+			{ 0x01, 0x0e, 0x16 },
+			{ 0x01, 0x10, 0x16 }	/* Maximum */
+		};
+		int i = a_contrast / 2;
+		RESTRICT_TO_RANGE(i, 0, 6);
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
+		ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1);
+		ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2);
+		ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
+		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+/*
+ * ibmcam_change_lighting_conditions()
+ *
+ * Camera model 1:
+ * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
+ *
+ * Camera model 2:
+ * We have 16 levels of lighting, 0 for bright light and up to 15 for
+ * low light. But values above 5 or so are useless because camera is
+ * not really capable to produce anything worth viewing at such light.
+ * This setting may be altered only in certain camera state.
+ *
+ * Low lighting forces slower FPS. Lighting is set as a module parameter.
+ *
+ * History:
+ * 1/5/00   Created.
+ * 2/20/00  Added support for Model 2 cameras.
+ */
+static void ibmcam_change_lighting_conditions(uvd_t *uvd)
+{
+	static const char proc[] = "ibmcam_change_lighting_conditions";
+
+	if (debug > 0)
+		info("%s: Set lighting to %hu.", proc, lighting);
+
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_1:
+	{
+		const int ntries = 5;
+		int i;
+		for (i=0; i < ntries; i++)
+			ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting);
+		break;
+	}
+	case IBMCAM_MODEL_2:
+#if 0
+		/*
+		 * This command apparently requires camera to be stopped. My
+		 * experiments showed that it -is- possible to alter the lighting
+		 * conditions setting "on the fly", but why bother? This setting does
+		 * not work reliably in all cases, so I decided simply to leave the
+		 * setting where Xirlink put it - in the camera setup phase. This code
+		 * is commented out because it does not work at -any- moment, so its
+		 * presence makes no sense. You may use it for experiments.
+		 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop camera */
+		ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Start camera */
+#endif
+		break;
+	case IBMCAM_MODEL_3:
+	case IBMCAM_MODEL_4:
+	default:
+		break;
+	}
+}
+
+/*
+ * ibmcam_set_sharpness()
+ *
+ * Cameras model 1 have internal smoothing feature. It is controlled by value in
+ * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
+ * Recommended value is 4. Cameras model 2 do not have this feature at all.
+ */
+static void ibmcam_set_sharpness(uvd_t *uvd)
+{
+	static const char proc[] = "ibmcam_set_sharpness";
+
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_1:
+	{
+		static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
+		unsigned short i, sv;
+
+		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
+		if (debug > 0)
+			info("%s: Set sharpness to %hu.", proc, sharpness);
+
+		sv = sa[sharpness - SHARPNESS_MIN];
+		for (i=0; i < 2; i++) {
+			ibmcam_send_x_01_00_05	(uvd, unknown_88);
+			ibmcam_send_x_00_05		(uvd, sharp_13);
+			ibmcam_send_x_00_05_02	(uvd, sv);
+		}
+		break;
+	}
+	case IBMCAM_MODEL_2:
+	case IBMCAM_MODEL_4:
+		/* Models 2, 4 do not have this control */
+		break;
+	case IBMCAM_MODEL_3:
+	{	/*
+		 * "Use a table of magic numbers.
+		 *  This setting doesn't really change much.
+		 *  But that's how Windows does it."
+		 */
+		static const struct {
+			unsigned short sv1;
+			unsigned short sv2;
+			unsigned short sv3;
+			unsigned short sv4;
+		} sv[7] = {
+			{ 0x00, 0x00, 0x05, 0x14 },	/* Smoothest */
+			{ 0x01, 0x04, 0x05, 0x14 },
+			{ 0x02, 0x04, 0x05, 0x14 },
+			{ 0x03, 0x04, 0x05, 0x14 },
+			{ 0x03, 0x05, 0x05, 0x14 },
+			{ 0x03, 0x06, 0x05, 0x14 },
+			{ 0x03, 0x07, 0x05, 0x14 }	/* Sharpest */
+		};
+		RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
+		RESTRICT_TO_RANGE(sharpness, 0, 6);
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
+		ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1);
+		ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2);
+		ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3);
+		ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
+		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+/*
+ * ibmcam_set_brightness()
+ *
+ * This procedure changes brightness of the picture.
+ */
+static void ibmcam_set_brightness(uvd_t *uvd)
+{
+	static const char proc[] = "ibmcam_set_brightness";
+	static const unsigned short n = 1;
+
+	if (debug > 0)
+		info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness);
+
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_1:
+	{
+		unsigned short i, j, bv[3];
+		bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10;
+		if (bv[0] == (uvd->vpic_old.brightness >> 10))
+			return;
+		uvd->vpic_old.brightness = bv[0];
+		for (j=0; j < 3; j++)
+			for (i=0; i < n; i++)
+				ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]);
+		break;
+	}
+	case IBMCAM_MODEL_2:
+	{
+		unsigned short i, j;
+		i = uvd->vpic.brightness >> 12;	/* 0 .. 15 */
+		j = 0x60 + i * ((0xee - 0x60) / 16);	/* 0x60 .. 0xee or so */
+		if (uvd->vpic_old.brightness == j)
+			break;
+		uvd->vpic_old.brightness = j;
+		ibmcam_model2_Packet1(uvd, mod2_brightness, j);
+		break;
+	}
+	case IBMCAM_MODEL_3:
+	{
+		/* Model 3: Brightness range 'i' in [0x0C..0x3F] */
+		unsigned short i =
+			0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1)));
+		RESTRICT_TO_RANGE(i, 0x0C, 0x3F);
+		if (uvd->vpic_old.brightness == i)
+			break;
+		uvd->vpic_old.brightness = i;
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
+		ibmcam_model3_Packet1(uvd, 0x0036, i);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
+		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
+		break;
+	}
+	case IBMCAM_MODEL_4:
+	{
+		/* Model 4: Brightness range 'i' in [0x04..0xb4] */
+		unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1)));
+		RESTRICT_TO_RANGE(i, 0x04, 0xb4);
+		if (uvd->vpic_old.brightness == i)
+			break;
+		uvd->vpic_old.brightness = i;
+		ibmcam_model4_BrightnessPacket(uvd, i);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+static void ibmcam_set_hue(uvd_t *uvd)
+{
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_2:
+	{
+		unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */
+		if (uvd->vpic_old.hue == hue)
+			return;
+		uvd->vpic_old.hue = hue;
+		ibmcam_model2_Packet1(uvd, mod2_hue, hue);
+		/* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */
+		break;
+	}
+	case IBMCAM_MODEL_3:
+	{
+#if 0 /* This seems not to work. No problem, will fix programmatically */
+		unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1)));
+		RESTRICT_TO_RANGE(hue, 0x05, 0x37);
+		if (uvd->vpic_old.hue == hue)
+			return;
+		uvd->vpic_old.hue = hue;
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop */
+		ibmcam_model3_Packet1(uvd, 0x007e, hue);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go! */
+		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+		ibmcam_veio(uvd, 0, 0x0001, 0x0113);
+#endif
+		break;
+	}
+	case IBMCAM_MODEL_4:
+	{
+		unsigned short r_gain, g_gain, b_gain, hue;
+
+		/*
+		 * I am not sure r/g/b_gain variables exactly control gain
+		 * of those channels. Most likely they subtly change some
+		 * very internal image processing settings in the camera.
+		 * In any case, here is what they do, and feel free to tweak:
+		 *
+		 * r_gain: seriously affects red gain
+		 * g_gain: seriously affects green gain
+		 * b_gain: seriously affects blue gain
+		 * hue: changes average color from violet (0) to red (0xFF)
+		 *
+		 * These settings are preset for a decent white balance in
+		 * 320x240, 352x288 modes. Low-res modes exhibit higher contrast
+		 * and therefore may need different values here.
+		 */
+		hue = 20 + (uvd->vpic.hue >> 9);
+		switch (uvd->videosize) {
+		case VIDEOSIZE_128x96:
+			r_gain = 90;
+			g_gain = 166;
+			b_gain = 175;
+			break;
+		case VIDEOSIZE_160x120:
+			r_gain = 70;
+			g_gain = 166;
+			b_gain = 185;
+			break;
+		case VIDEOSIZE_176x144:
+			r_gain = 160;
+			g_gain = 175;
+			b_gain = 185;
+			break;
+		default:
+			r_gain = 120;
+			g_gain = 166;
+			b_gain = 175;
+			break;
+		}
+		RESTRICT_TO_RANGE(hue, 1, 0x7f);
+
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, g_gain, 0x0127);	/* Green gain */
+		ibmcam_veio(uvd, 0, r_gain, 0x012e);	/* Red gain */
+		ibmcam_veio(uvd, 0, b_gain, 0x0130);	/* Blue gain */
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, hue,    0x012d);	/* Hue */
+		ibmcam_veio(uvd, 0, 0xf545, 0x0124);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+/*
+ * ibmcam_adjust_picture()
+ *
+ * This procedure gets called from V4L interface to update picture settings.
+ * Here we change brightness and contrast.
+ */
+static void ibmcam_adjust_picture(uvd_t *uvd)
+{
+	ibmcam_adjust_contrast(uvd);
+	ibmcam_set_brightness(uvd);
+	ibmcam_set_hue(uvd);
+}
+
+static int ibmcam_model1_setup(uvd_t *uvd)
+{
+	const int ntries = 5;
+	int i;
+
+	ibmcam_veio(uvd, 1, 0x00, 0x0128);
+	ibmcam_veio(uvd, 1, 0x00, 0x0100);
+	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
+	ibmcam_veio(uvd, 1, 0x00, 0x0100);
+	ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
+	ibmcam_veio(uvd, 1, 0x00, 0x0100);
+	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
+	ibmcam_veio(uvd, 0, 0x01, 0x0108);
+
+	ibmcam_veio(uvd, 0, 0x03, 0x0112);
+	ibmcam_veio(uvd, 1, 0x00, 0x0115);
+	ibmcam_veio(uvd, 0, 0x06, 0x0115);
+	ibmcam_veio(uvd, 1, 0x00, 0x0116);
+	ibmcam_veio(uvd, 0, 0x44, 0x0116);
+	ibmcam_veio(uvd, 1, 0x00, 0x0116);
+	ibmcam_veio(uvd, 0, 0x40, 0x0116);
+	ibmcam_veio(uvd, 1, 0x00, 0x0115);
+	ibmcam_veio(uvd, 0, 0x0e, 0x0115);
+	ibmcam_veio(uvd, 0, 0x19, 0x012c);
+
+	ibmcam_Packet_Format1(uvd, 0x00, 0x1e);
+	ibmcam_Packet_Format1(uvd, 0x39, 0x0d);
+	ibmcam_Packet_Format1(uvd, 0x39, 0x09);
+	ibmcam_Packet_Format1(uvd, 0x3b, 0x00);
+	ibmcam_Packet_Format1(uvd, 0x28, 0x22);
+	ibmcam_Packet_Format1(uvd, light_27, 0);
+	ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
+	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
+
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x2c, 0x00);
+
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x30, 0x14);
+
+	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
+	ibmcam_PacketFormat2(uvd, 0x01, 0xe1);
+	ibmcam_PacketFormat2(uvd, 0x02, 0xcd);
+	ibmcam_PacketFormat2(uvd, 0x03, 0xcd);
+	ibmcam_PacketFormat2(uvd, 0x04, 0xfa);
+	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
+	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
+
+	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
+	ibmcam_PacketFormat2(uvd, 0x0a, 0x37);
+	ibmcam_PacketFormat2(uvd, 0x0b, 0xb8);
+	ibmcam_PacketFormat2(uvd, 0x0c, 0xf3);
+	ibmcam_PacketFormat2(uvd, 0x0d, 0xe3);
+	ibmcam_PacketFormat2(uvd, 0x0e, 0x0d);
+	ibmcam_PacketFormat2(uvd, 0x0f, 0xf2);
+	ibmcam_PacketFormat2(uvd, 0x10, 0xd5);
+	ibmcam_PacketFormat2(uvd, 0x11, 0xba);
+	ibmcam_PacketFormat2(uvd, 0x12, 0x53);
+	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
+	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
+
+	ibmcam_PacketFormat2(uvd, 0x39, 0x02);
+	ibmcam_PacketFormat2(uvd, 0x16, 0x00);
+	ibmcam_PacketFormat2(uvd, 0x17, 0x28);
+	ibmcam_PacketFormat2(uvd, 0x18, 0x7d);
+	ibmcam_PacketFormat2(uvd, 0x19, 0xbe);
+	ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
+	ibmcam_PacketFormat2(uvd, 0x39, 0x00);
+
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x00, 0x18);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x13, 0x18);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x14, 0x06);
+
+	/* This is default brightness */
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x31, 0x37);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x32, 0x46);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x33, 0x55);
+
+	ibmcam_Packet_Format1(uvd, 0x2e, 0x04);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x2d, 0x04);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x29, 0x80);
+	ibmcam_Packet_Format1(uvd, 0x2c, 0x01);
+	ibmcam_Packet_Format1(uvd, 0x30, 0x17);
+	ibmcam_Packet_Format1(uvd, 0x39, 0x08);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x34, 0x00);
+
+	ibmcam_veio(uvd, 0, 0x00, 0x0101);
+	ibmcam_veio(uvd, 0, 0x00, 0x010a);
+
+	switch (uvd->videosize) {
+	case VIDEOSIZE_128x96:
+		ibmcam_veio(uvd, 0, 0x80, 0x0103);
+		ibmcam_veio(uvd, 0, 0x60, 0x0105);
+		ibmcam_veio(uvd, 0, 0x0c, 0x010b);
+		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x0b, 0x011d);
+		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x00, 0x0129);
+		break;
+	case VIDEOSIZE_176x144:
+		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
+		ibmcam_veio(uvd, 0, 0x8f, 0x0105);
+		ibmcam_veio(uvd, 0, 0x06, 0x010b);
+		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x0d, 0x011d);
+		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x03, 0x0129);
+		break;
+	case VIDEOSIZE_352x288:
+		ibmcam_veio(uvd, 0, 0xb0, 0x0103);
+		ibmcam_veio(uvd, 0, 0x90, 0x0105);
+		ibmcam_veio(uvd, 0, 0x02, 0x010b);
+		ibmcam_veio(uvd, 0, 0x04, 0x011b);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x05, 0x011d);
+		ibmcam_veio(uvd, 0, 0x00, 0x011e);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x00, 0x0129);
+		break;
+	}
+
+	ibmcam_veio(uvd, 0, 0xff, 0x012b);
+
+	/* This is another brightness - don't know why */
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x31, 0xc3);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x32, 0xd2);
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, 0x33, 0xe1);
+
+	/* Default contrast */
+	for (i=0; i < ntries; i++)
+		ibmcam_Packet_Format1(uvd, contrast_14, 0x0a);
+
+	/* Default sharpness */
+	for (i=0; i < 2; i++)
+		ibmcam_PacketFormat2(uvd, sharp_13, 0x1a);	/* Level 4 FIXME */
+
+	/* Default lighting conditions */
+	ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */
+
+	/* Assorted init */
+
+	switch (uvd->videosize) {
+	case VIDEOSIZE_128x96:
+		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
+		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x36, 0x0102);
+		ibmcam_veio(uvd, 0, 0x1a, 0x0104);
+		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
+		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
+#if 0
+		ibmcam_veio(uvd, 0, 0x00, 0x0106);
+		ibmcam_veio(uvd, 0, 0x38, 0x0107);
+#else
+		ibmcam_veio(uvd, 0, 0x02, 0x0106);
+		ibmcam_veio(uvd, 0, 0x2a, 0x0107);
+#endif
+		break;
+	case VIDEOSIZE_176x144:
+		ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
+		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x04, 0x0102);
+		ibmcam_veio(uvd, 0, 0x02, 0x0104);
+		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x2b, 0x011c);
+		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x01, 0x0106);
+		ibmcam_veio(uvd, 0, 0xca, 0x0107);
+		break;
+	case VIDEOSIZE_352x288:
+		ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
+		ibmcam_veio(uvd, 0, 0xc9, 0x0119);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x80, 0x0109);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x08, 0x0102);
+		ibmcam_veio(uvd, 0, 0x01, 0x0104);
+		ibmcam_veio(uvd, 0, 0x04, 0x011a);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x2f, 0x011c);
+		ibmcam_veio(uvd, 0, 0x23, 0x012a);	/* Same everywhere */
+		ibmcam_veio(uvd, 0, 0x03, 0x0106);
+		ibmcam_veio(uvd, 0, 0xf6, 0x0107);
+		break;
+	}
+	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
+}
+
+static int ibmcam_model2_setup(uvd_t *uvd)
+{
+	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
+	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
+	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
+	ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
+	ibmcam_veio(uvd, 0, 0x0008, 0x012b);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0108);
+	ibmcam_veio(uvd, 0, 0x0001, 0x0133);
+	ibmcam_veio(uvd, 0, 0x0001, 0x0102);
+	switch (uvd->videosize) {
+	case VIDEOSIZE_176x144:
+		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
+		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
+		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);	/* Unique to this mode */
+		ibmcam_veio(uvd, 0, 0x0038, 0x0119);	/* Unique to this mode */
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
+		ibmcam_veio(uvd, 0, 0x0090, 0x0107);	/* Unique to every mode*/
+		break;
+	case VIDEOSIZE_320x240:
+		ibmcam_veio(uvd, 0, 0x0028, 0x0103);	/* Unique to this mode */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
+		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
+		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
+		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
+		ibmcam_veio(uvd, 0, 0x0098, 0x0107);	/* Unique to every mode*/
+		break;
+	case VIDEOSIZE_352x240:
+		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
+		ibmcam_veio(uvd, 0, 0x001e, 0x0105);	/* 320x240, 352x240 */
+		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
+		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
+		ibmcam_veio(uvd, 0, 0x00da, 0x0107);	/* Unique to every mode*/
+		break;
+	case VIDEOSIZE_352x288:
+		ibmcam_veio(uvd, 0, 0x002c, 0x0103);	/* All except 320x240 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);	/* Same */
+		ibmcam_veio(uvd, 0, 0x0024, 0x0105);	/* 176x144, 352x288 */
+		ibmcam_veio(uvd, 0, 0x0039, 0x010a);	/* All except 176x144 */
+		ibmcam_veio(uvd, 0, 0x0070, 0x0119);	/* All except 176x144 */
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);	/* Same */
+		ibmcam_veio(uvd, 0, 0x00fe, 0x0107);	/* Unique to every mode*/
+		break;
+	}
+	return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
+}
+
+/*
+ * ibmcam_model1_setup_after_video_if()
+ *
+ * This code adds finishing touches to the video data interface.
+ * Here we configure the frame rate and turn on the LED.
+ */
+static void ibmcam_model1_setup_after_video_if(uvd_t *uvd)
+{
+	unsigned short internal_frame_rate;
+
+	RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
+	internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */
+	ibmcam_veio(uvd, 0, 0x01, 0x0100);	/* LED On  */
+	ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111);
+	ibmcam_veio(uvd, 0, 0x01, 0x0114);
+	ibmcam_veio(uvd, 0, 0xc0, 0x010c);
+}
+
+static void ibmcam_model2_setup_after_video_if(uvd_t *uvd)
+{
+	unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb;
+
+	ibmcam_veio(uvd, 0, 0x0000, 0x0100);	/* LED on */
+
+	switch (uvd->videosize) {
+	case VIDEOSIZE_176x144:
+		ibmcam_veio(uvd, 0, 0x0050, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
+		break;
+	case VIDEOSIZE_320x240:
+	case VIDEOSIZE_352x240:
+	case VIDEOSIZE_352x288:
+		ibmcam_veio(uvd, 0, 0x0040, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		break;
+	}
+	ibmcam_veio(uvd, 0, 0x009b, 0x010f);
+	ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
+
+	/*
+	 * Hardware settings, may affect CMOS sensor; not user controls!
+	 * -------------------------------------------------------------
+	 * 0x0004: no effect
+	 * 0x0006: hardware effect
+	 * 0x0008: no effect
+	 * 0x000a: stops video stream, probably important h/w setting
+	 * 0x000c: changes color in hardware manner (not user setting)
+	 * 0x0012: changes number of colors (does not affect speed)
+	 * 0x002a: no effect
+	 * 0x002c: hardware setting (related to scan lines)
+	 * 0x002e: stops video stream, probably important h/w setting
+	 */
+	ibmcam_model2_Packet1(uvd, 0x000a, 0x005c);
+	ibmcam_model2_Packet1(uvd, 0x0004, 0x0000);
+	ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb);
+	ibmcam_model2_Packet1(uvd, 0x0008, 0x0000);
+	ibmcam_model2_Packet1(uvd, 0x000c, 0x0009);
+	ibmcam_model2_Packet1(uvd, 0x0012, 0x000a);
+	ibmcam_model2_Packet1(uvd, 0x002a, 0x0000);
+	ibmcam_model2_Packet1(uvd, 0x002c, 0x0000);
+	ibmcam_model2_Packet1(uvd, 0x002e, 0x0008);
+
+	/*
+	 * Function 0x0030 pops up all over the place. Apparently
+	 * it is a hardware control register, with every bit assigned to
+	 * do something.
+	 */
+	ibmcam_model2_Packet1(uvd, 0x0030, 0x0000);
+
+	/*
+	 * Magic control of CMOS sensor. Only lower values like
+	 * 0-3 work, and picture shifts left or right. Don't change.
+	 */
+	switch (uvd->videosize) {
+	case VIDEOSIZE_176x144:
+		ibmcam_model2_Packet1(uvd, 0x0014, 0x0002);
+		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
+		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
+		break;
+	case VIDEOSIZE_320x240:
+		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009);
+		ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */
+		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */
+		break;
+	case VIDEOSIZE_352x240:
+		/* This mode doesn't work as Windows programs it; changed to work */
+		ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */
+		ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */
+		ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
+		break;
+	case VIDEOSIZE_352x288:
+		ibmcam_model2_Packet1(uvd, 0x0014, 0x0003);
+		ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
+		ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
+		break;
+	}
+
+	ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a);
+
+	/*
+	 * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest).
+	 * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the
+	 * slowest setting. However for all practical reasons high settings make no
+	 * sense because USB is not fast enough to support high FPS. Be aware that
+	 * the picture datastream will be severely disrupted if you ask for
+	 * frame rate faster than allowed for the video size - see below:
+	 *
+	 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
+	 * -----------------------------------------------------------------
+	 * 176x144: [6..31]
+	 * 320x240: [8..31]
+	 * 352x240: [10..31]
+	 * 352x288: [16..31] I have to raise lower threshold for stability...
+	 *
+	 * As usual, slower FPS provides better sensitivity.
+	 */
+	{
+		short hw_fps=31, i_framerate;
+
+		RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
+		i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN;
+		switch (uvd->videosize) {
+		case VIDEOSIZE_176x144:
+			hw_fps = 6 + i_framerate*4;
+			break;
+		case VIDEOSIZE_320x240:
+			hw_fps = 8 + i_framerate*3;
+			break;
+		case VIDEOSIZE_352x240:
+			hw_fps = 10 + i_framerate*2;
+			break;
+		case VIDEOSIZE_352x288:
+			hw_fps = 28 + i_framerate/2;
+			break;
+		}
+		if (uvd->debug > 0)
+			info("Framerate (hardware): %hd.", hw_fps);
+		RESTRICT_TO_RANGE(hw_fps, 0, 31);
+		ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
+	}
+
+	/*
+	 * This setting does not visibly affect pictures; left it here
+	 * because it was present in Windows USB data stream. This function
+	 * does not allow arbitrary values and apparently is a bit mask, to
+	 * be activated only at appropriate time. Don't change it randomly!
+	 */
+	switch (uvd->videosize) {
+	case VIDEOSIZE_176x144:
+		ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2);
+		break;
+	case VIDEOSIZE_320x240:
+		ibmcam_model2_Packet1(uvd, 0x0026, 0x0044);
+		break;
+	case VIDEOSIZE_352x240:
+		ibmcam_model2_Packet1(uvd, 0x0026, 0x0046);
+		break;
+	case VIDEOSIZE_352x288:
+		ibmcam_model2_Packet1(uvd, 0x0026, 0x0048);
+		break;
+	}
+
+	ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
+
+	if (init_model2_rg2 >= 0) {
+		RESTRICT_TO_RANGE(init_model2_rg2, 0, 255);
+		setup_model2_rg2 = init_model2_rg2;
+	} else
+		setup_model2_rg2 = 0x002f;
+
+	if (init_model2_sat >= 0) {
+		RESTRICT_TO_RANGE(init_model2_sat, 0, 255);
+		setup_model2_sat = init_model2_sat;
+	} else
+		setup_model2_sat = 0x0034;
+
+	if (init_model2_yb >= 0) {
+		RESTRICT_TO_RANGE(init_model2_yb, 0, 255);
+		setup_model2_yb = init_model2_yb;
+	} else
+		setup_model2_yb = 0x00a0;
+
+	ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2);
+	ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat);
+	ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb);
+	ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */;
+
+	/* Hardware control command */
+	ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
+
+	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);	/* Go camera, go! */
+	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+}
+
+static void ibmcam_model4_setup_after_video_if(uvd_t *uvd)
+{
+	switch (uvd->videosize) {
+	case VIDEOSIZE_128x96:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
+		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
+		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
+		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
+		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
+		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
+		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+		break;
+	case VIDEOSIZE_160x120:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
+		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
+		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
+		ibmcam_veio(uvd, 0, 0x00d8, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
+		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
+		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
+		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000b, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
+		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0025, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0048, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0035, 0x012e);
+		ibmcam_veio(uvd, 0, 0x00d0, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0048, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0090, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+		break;
+	case VIDEOSIZE_176x144:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
+		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
+		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0038, 0x0119);
+		ibmcam_veio(uvd, 0, 0x00d6, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x0018, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
+		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
+		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0007, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0001, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
+		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
+		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0028, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
+		ibmcam_veio(uvd, 0, 0x002a, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
+		ibmcam_veio(uvd, 0, 0x006d, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+		break;
+	case VIDEOSIZE_320x240:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
+		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
+		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
+		ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x005e, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
+		ibmcam_veio(uvd, 0, 0x0028, 0x0103);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
+		ibmcam_veio(uvd, 0, 0x001e, 0x0105);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000a, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
+		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0043, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0017, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0031, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0017, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0078, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+		break;
+	case VIDEOSIZE_352x288:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0100);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
+		ibmcam_veio(uvd, 0, 0x0080, 0x012b);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0108);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0133);
+		ibmcam_veio(uvd, 0, 0x009b, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x000a, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005c, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0004, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x000c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0009, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0012, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x002a, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0000, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0034, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0070, 0x0119);
+		ibmcam_veio(uvd, 0, 0x00f2, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x008c, 0x0107);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
+		ibmcam_veio(uvd, 0, 0x0039, 0x010a);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0102);
+		ibmcam_veio(uvd, 0, 0x002c, 0x0103);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0104);
+		ibmcam_veio(uvd, 0, 0x0024, 0x0105);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0016, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0006, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0014, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0002, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
+		ibmcam_veio(uvd, 0, 0x001a, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
+		ibmcam_veio(uvd, 0, 0x005e, 0x012d);
+		ibmcam_veio(uvd, 0, 0x9545, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0018, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0049, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd055, 0x0124);
+		ibmcam_veio(uvd, 0, 0x001c, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00cf, 0x012e);
+		ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0032, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
+		ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0036, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0008, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x001e, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0010, 0x0127);
+		ibmcam_veio(uvd, 0, 0x0013, 0x012e);
+		ibmcam_veio(uvd, 0, 0x0025, 0x0130);
+		ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0010, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0048, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd145, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
+		ibmcam_veio(uvd, 0, 0x0038, 0x012f);
+		ibmcam_veio(uvd, 0, 0xd141, 0x0124);
+		ibmcam_veio(uvd, 0, 0x0004, 0x0127);
+		ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+		break; 
+	}
+	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+}
+
+static void ibmcam_model3_setup_after_video_if(uvd_t *uvd)
+{
+	int i;
+	/*
+	 * 01.01.08 - Added for RCA video in support -LO
+	 * This struct is used to init the Model3 cam to use the RCA video in port
+	 * instead of the CCD sensor.
+	 */
+	static const struct struct_initData initData[] = {
+		{0, 0x0000, 0x010c},
+		{0, 0x0006, 0x012c},
+		{0, 0x0078, 0x012d},
+		{0, 0x0046, 0x012f},
+		{0, 0xd141, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfea8, 0x0124},
+		{1, 0x0000, 0x0116},
+		{0, 0x0064, 0x0116},
+		{1, 0x0000, 0x0115},
+		{0, 0x0003, 0x0115},
+		{0, 0x0008, 0x0123},
+		{0, 0x0000, 0x0117},
+		{0, 0x0000, 0x0112},
+		{0, 0x0080, 0x0100},
+		{0, 0x0000, 0x0100},
+		{1, 0x0000, 0x0116},
+		{0, 0x0060, 0x0116},
+		{0, 0x0002, 0x0112},
+		{0, 0x0000, 0x0123},
+		{0, 0x0001, 0x0117},
+		{0, 0x0040, 0x0108},
+		{0, 0x0019, 0x012c},
+		{0, 0x0040, 0x0116},
+		{0, 0x000a, 0x0115},
+		{0, 0x000b, 0x0115},
+		{0, 0x0078, 0x012d},
+		{0, 0x0046, 0x012f},
+		{0, 0xd141, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfea8, 0x0124},
+		{0, 0x0064, 0x0116},
+		{0, 0x0000, 0x0115},
+		{0, 0x0001, 0x0115},
+		{0, 0xffff, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00aa, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xffff, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00f2, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x000f, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xffff, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00f8, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00fc, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xffff, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00f9, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x003c, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xffff, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0027, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0019, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0021, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0006, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0045, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x002a, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x000e, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x002b, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00f4, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x002c, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0004, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x002d, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0014, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x002e, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0003, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x002f, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0003, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0014, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0040, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0040, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0053, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0x0000, 0x0101},
+		{0, 0x00a0, 0x0103},
+		{0, 0x0078, 0x0105},
+		{0, 0x0000, 0x010a},
+		{0, 0x0024, 0x010b},
+		{0, 0x0028, 0x0119},
+		{0, 0x0088, 0x011b},
+		{0, 0x0002, 0x011d},
+		{0, 0x0003, 0x011e},
+		{0, 0x0000, 0x0129},
+		{0, 0x00fc, 0x012b},
+		{0, 0x0008, 0x0102},
+		{0, 0x0000, 0x0104},
+		{0, 0x0008, 0x011a},
+		{0, 0x0028, 0x011c},
+		{0, 0x0021, 0x012a},
+		{0, 0x0000, 0x0118},
+		{0, 0x0000, 0x0132},
+		{0, 0x0000, 0x0109},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0031, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0040, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0040, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x00dc, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0032, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0020, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0001, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0040, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0040, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0037, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0030, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0xfff9, 0x0124},
+		{0, 0x0086, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0038, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0008, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0x0000, 0x0127},
+		{0, 0xfff8, 0x0124},
+		{0, 0xfffd, 0x0124},
+		{0, 0xfffa, 0x0124},
+		{0, 0x0003, 0x0106},
+		{0, 0x0062, 0x0107},
+		{0, 0x0003, 0x0111},
+	};
+#define NUM_INIT_DATA 
+
+	unsigned short compression = 0;	/* 0=none, 7=best frame rate  */
+	int f_rate; /* 0=Fastest 7=slowest */
+
+	if (IBMCAM_T(uvd)->initialized)
+		return;
+
+	/* Internal frame rate is controlled by f_rate value */
+	f_rate = 7 - framerate;
+	RESTRICT_TO_RANGE(f_rate, 0, 7);
+
+	ibmcam_veio(uvd, 0, 0x0000, 0x0100);
+	ibmcam_veio(uvd, 1, 0x0000, 0x0116);
+	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0112);
+	ibmcam_veio(uvd, 0, 0x0000, 0x0123);
+	ibmcam_veio(uvd, 0, 0x0001, 0x0117);
+	ibmcam_veio(uvd, 0, 0x0040, 0x0108);
+	ibmcam_veio(uvd, 0, 0x0019, 0x012c);
+	ibmcam_veio(uvd, 0, 0x0060, 0x0116);
+	ibmcam_veio(uvd, 0, 0x0002, 0x0115);
+	ibmcam_veio(uvd, 0, 0x0003, 0x0115);
+	ibmcam_veio(uvd, 1, 0x0000, 0x0115);
+	ibmcam_veio(uvd, 0, 0x000b, 0x0115);
+	ibmcam_model3_Packet1(uvd, 0x000a, 0x0040);
+	ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6);
+	ibmcam_model3_Packet1(uvd, 0x000c, 0x0002);
+	ibmcam_model3_Packet1(uvd, 0x000d, 0x0020);
+	ibmcam_model3_Packet1(uvd, 0x000e, 0x0033);
+	ibmcam_model3_Packet1(uvd, 0x000f, 0x0007);
+	ibmcam_model3_Packet1(uvd, 0x0010, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0011, 0x0070);
+	ibmcam_model3_Packet1(uvd, 0x0012, 0x0030);
+	ibmcam_model3_Packet1(uvd, 0x0013, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0014, 0x0001);
+	ibmcam_model3_Packet1(uvd, 0x0015, 0x0001);
+	ibmcam_model3_Packet1(uvd, 0x0016, 0x0001);
+	ibmcam_model3_Packet1(uvd, 0x0017, 0x0001);
+	ibmcam_model3_Packet1(uvd, 0x0018, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3);
+	ibmcam_model3_Packet1(uvd, 0x0020, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0028, 0x0010);
+	ibmcam_model3_Packet1(uvd, 0x0029, 0x0054);
+	ibmcam_model3_Packet1(uvd, 0x002a, 0x0013);
+	ibmcam_model3_Packet1(uvd, 0x002b, 0x0007);
+	ibmcam_model3_Packet1(uvd, 0x002d, 0x0028);
+	ibmcam_model3_Packet1(uvd, 0x002e, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0031, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0032, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0033, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0034, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0035, 0x0038);
+	ibmcam_model3_Packet1(uvd, 0x003a, 0x0001);
+	ibmcam_model3_Packet1(uvd, 0x003c, 0x001e);
+	ibmcam_model3_Packet1(uvd, 0x003f, 0x000a);
+	ibmcam_model3_Packet1(uvd, 0x0041, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0046, 0x003f);
+	ibmcam_model3_Packet1(uvd, 0x0047, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0050, 0x0005);
+	ibmcam_model3_Packet1(uvd, 0x0052, 0x001a);
+	ibmcam_model3_Packet1(uvd, 0x0053, 0x0003);
+	ibmcam_model3_Packet1(uvd, 0x005a, 0x006b);
+	ibmcam_model3_Packet1(uvd, 0x005d, 0x001e);
+	ibmcam_model3_Packet1(uvd, 0x005e, 0x0030);
+	ibmcam_model3_Packet1(uvd, 0x005f, 0x0041);
+	ibmcam_model3_Packet1(uvd, 0x0064, 0x0008);
+	ibmcam_model3_Packet1(uvd, 0x0065, 0x0015);
+	ibmcam_model3_Packet1(uvd, 0x0068, 0x000f);
+	ibmcam_model3_Packet1(uvd, 0x0079, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x007a, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x007c, 0x003f);
+	ibmcam_model3_Packet1(uvd, 0x0082, 0x000f);
+	ibmcam_model3_Packet1(uvd, 0x0085, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x0099, 0x0000);
+	ibmcam_model3_Packet1(uvd, 0x009b, 0x0023);
+	ibmcam_model3_Packet1(uvd, 0x009c, 0x0022);
+	ibmcam_model3_Packet1(uvd, 0x009d, 0x0096);
+	ibmcam_model3_Packet1(uvd, 0x009e, 0x0096);
+	ibmcam_model3_Packet1(uvd, 0x009f, 0x000a);
+
+	switch (uvd->videosize) {
+	case VIDEOSIZE_160x120:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
+		ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */
+		ibmcam_veio(uvd, 0, 0x00a9, 0x0119);
+		ibmcam_veio(uvd, 0, 0x0016, 0x011b);
+		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
+		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
+		ibmcam_veio(uvd, 0, 0x0018, 0x0102);
+		ibmcam_veio(uvd, 0, 0x0004, 0x0104);
+		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
+		ibmcam_veio(uvd, 0, 0x0028, 0x011c);
+		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0118);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
+		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
+		ibmcam_veio(uvd, 0, compression, 0x0109);
+		break;
+	case VIDEOSIZE_320x240:
+		ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
+		ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */
+		ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */
+		ibmcam_veio(uvd, 0, 0x0000, 0x011e);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
+		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
+		/* 4 commands from 160x120 skipped */
+		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
+		ibmcam_veio(uvd, 0, compression, 0x0109);
+		ibmcam_veio(uvd, 0, 0x00d9, 0x0119);
+		ibmcam_veio(uvd, 0, 0x0006, 0x011b);
+		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0010, 0x0104);
+		ibmcam_veio(uvd, 0, 0x0004, 0x011a);
+		ibmcam_veio(uvd, 0, 0x003f, 0x011c);
+		ibmcam_veio(uvd, 0, 0x001c, 0x0118);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0132);
+		break;
+	case VIDEOSIZE_640x480:
+		ibmcam_veio(uvd, 0, 0x00f0, 0x0105);
+		ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
+		ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */
+		ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */
+		ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
+		ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
+		ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */
+		ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
+		ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
+		ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
+		ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
+		ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
+		ibmcam_veio(uvd, 0, compression, 0x0109);
+		ibmcam_veio(uvd, 0, 0x0040, 0x0101);
+		ibmcam_veio(uvd, 0, 0x0040, 0x0103);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
+		break;
+	}
+	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);	/* Hue */
+	ibmcam_model3_Packet1(uvd, 0x0036, 0x0011);	/* Brightness */
+	ibmcam_model3_Packet1(uvd, 0x0060, 0x0002);	/* Sharpness */
+	ibmcam_model3_Packet1(uvd, 0x0061, 0x0004);	/* Sharpness */
+	ibmcam_model3_Packet1(uvd, 0x0062, 0x0005);	/* Sharpness */
+	ibmcam_model3_Packet1(uvd, 0x0063, 0x0014);	/* Sharpness */
+	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
+	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
+	ibmcam_model3_Packet1(uvd, 0x0067, 0x0001);	/* Contrast */
+	ibmcam_model3_Packet1(uvd, 0x005b, 0x000c);	/* Contrast */
+	ibmcam_model3_Packet1(uvd, 0x005c, 0x0016);	/* Contrast */
+	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
+	ibmcam_model3_Packet1(uvd, 0x002c, 0x0003);	/* Was 1, broke 640x480 */
+	ibmcam_model3_Packet1(uvd, 0x002f, 0x002a);
+	ibmcam_model3_Packet1(uvd, 0x0030, 0x0029);
+	ibmcam_model3_Packet1(uvd, 0x0037, 0x0002);
+	ibmcam_model3_Packet1(uvd, 0x0038, 0x0059);
+	ibmcam_model3_Packet1(uvd, 0x003d, 0x002e);
+	ibmcam_model3_Packet1(uvd, 0x003e, 0x0028);
+	ibmcam_model3_Packet1(uvd, 0x0078, 0x0005);
+	ibmcam_model3_Packet1(uvd, 0x007b, 0x0011);
+	ibmcam_model3_Packet1(uvd, 0x007d, 0x004b);
+	ibmcam_model3_Packet1(uvd, 0x007f, 0x0022);
+	ibmcam_model3_Packet1(uvd, 0x0080, 0x000c);
+	ibmcam_model3_Packet1(uvd, 0x0081, 0x000b);
+	ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd);
+	ibmcam_model3_Packet1(uvd, 0x0086, 0x000b);
+	ibmcam_model3_Packet1(uvd, 0x0087, 0x000b);
+	ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);
+	ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0);	/* Red gain */
+	ibmcam_model3_Packet1(uvd, 0x0097, 0x0096);	/* Blue gain */
+	ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
+
+	switch (uvd->videosize) {
+	case VIDEOSIZE_160x120:
+		ibmcam_veio(uvd, 0, 0x0002, 0x0106);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0107);
+		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
+		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x0040, 0x000a);
+		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
+		break;
+	case VIDEOSIZE_320x240:
+		ibmcam_veio(uvd, 0, 0x0003, 0x0106);
+		ibmcam_veio(uvd, 0, 0x0062, 0x0107);
+		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
+		ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
+		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
+		ibmcam_model3_Packet1(uvd, 0x0051, 0x000b);
+		break;
+	case VIDEOSIZE_640x480:
+		ibmcam_veio(uvd, 0, 0x0002, 0x0106);	/* Adjustments */
+		ibmcam_veio(uvd, 0, 0x00b4, 0x0107);	/* Adjustments */
+		ibmcam_veio(uvd, 0, f_rate, 0x0111);	/* Frame rate */
+		ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */
+		ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */
+		ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
+		ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
+		break;
+	}
+
+	/* 01.01.08 - Added for RCA video in support -LO */
+	if(init_model3_input) {
+		if (debug > 0)
+			info("Setting input to RCA.");
+		for (i=0; i < (sizeof(initData)/sizeof(initData[0])); i++) {
+			ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
+		}
+	}
+
+	ibmcam_veio(uvd, 0, 0x0001, 0x0114);
+	ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+	usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+}
+
+/*
+ * ibmcam_video_stop()
+ *
+ * This code tells camera to stop streaming. The interface remains
+ * configured and bandwidth - claimed.
+ */
+static void ibmcam_video_stop(uvd_t *uvd)
+{
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_1:
+		ibmcam_veio(uvd, 0, 0x00, 0x010c);
+		ibmcam_veio(uvd, 0, 0x00, 0x010c);
+		ibmcam_veio(uvd, 0, 0x01, 0x0114);
+		ibmcam_veio(uvd, 0, 0xc0, 0x010c);
+		ibmcam_veio(uvd, 0, 0x00, 0x010c);
+		ibmcam_send_FF_04_02(uvd);
+		ibmcam_veio(uvd, 1, 0x00, 0x0100);
+		ibmcam_veio(uvd, 0, 0x81, 0x0100);	/* LED Off */
+		break;
+	case IBMCAM_MODEL_2:
+case IBMCAM_MODEL_4:
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);	/* Stop the camera */
+
+		ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
+
+		ibmcam_veio(uvd, 0, 0x0080, 0x0100);	/* LED Off */
+		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
+		ibmcam_veio(uvd, 0, 0x00a0, 0x0111);
+
+		ibmcam_model2_Packet1(uvd, 0x0030, 0x0002);
+
+		ibmcam_veio(uvd, 0, 0x0020, 0x0111);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
+		break;
+	case IBMCAM_MODEL_3:
+#if 1
+		ibmcam_veio(uvd, 0, 0x0000, 0x010c);
+
+		/* Here we are supposed to select video interface alt. setting 0 */
+		ibmcam_veio(uvd, 0, 0x0006, 0x012c);
+
+		ibmcam_model3_Packet1(uvd, 0x0046, 0x0000);
+
+		ibmcam_veio(uvd, 1, 0x0000, 0x0116);
+		ibmcam_veio(uvd, 0, 0x0064, 0x0116);
+		ibmcam_veio(uvd, 1, 0x0000, 0x0115);
+		ibmcam_veio(uvd, 0, 0x0003, 0x0115);
+		ibmcam_veio(uvd, 0, 0x0008, 0x0123);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0117);
+		ibmcam_veio(uvd, 0, 0x0000, 0x0112);
+		ibmcam_veio(uvd, 0, 0x0080, 0x0100);
+		IBMCAM_T(uvd)->initialized = 0;
+#endif
+		break;
+	} /* switch */
+}
+
+/*
+ * ibmcam_reinit_iso()
+ *
+ * This procedure sends couple of commands to the camera and then
+ * resets the video pipe. This sequence was observed to reinit the
+ * camera or, at least, to initiate ISO data stream.
+ *
+ * History:
+ * 1/2/00   Created.
+ */
+static void ibmcam_reinit_iso(uvd_t *uvd, int do_stop)
+{
+	switch (IBMCAM_T(uvd)->camera_model) {
+	case IBMCAM_MODEL_1:
+		if (do_stop)
+			ibmcam_video_stop(uvd);
+		ibmcam_veio(uvd, 0, 0x0001, 0x0114);
+		ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
+		usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
+		ibmcam_model1_setup_after_video_if(uvd);
+		break;
+	case IBMCAM_MODEL_2:
+		ibmcam_model2_setup_after_video_if(uvd);
+		break;
+	case IBMCAM_MODEL_3:
+		ibmcam_video_stop(uvd);
+		ibmcam_model3_setup_after_video_if(uvd);
+		break;
+	case IBMCAM_MODEL_4:
+		ibmcam_model4_setup_after_video_if(uvd);
+		break;
+	}
+}
+
+static void ibmcam_video_start(uvd_t *uvd)
+{
+	ibmcam_change_lighting_conditions(uvd);
+	ibmcam_set_sharpness(uvd);
+	ibmcam_reinit_iso(uvd, 0);
+}
+
+/*
+ * Return negative code on failure, 0 on success.
+ */
+static int ibmcam_setup_on_open(uvd_t *uvd)
+{
+	int setup_ok = 0; /* Success by default */
+	/* Send init sequence only once, it's large! */
+	if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */
+		switch (IBMCAM_T(uvd)->camera_model) {
+		case IBMCAM_MODEL_1:
+			setup_ok = ibmcam_model1_setup(uvd);
+			break;
+		case IBMCAM_MODEL_2:
+			setup_ok = ibmcam_model2_setup(uvd);
+			break;
+		case IBMCAM_MODEL_3:
+		case IBMCAM_MODEL_4:
+			/* We do all setup when Isoc stream is requested */
+			break;
+		}
+		IBMCAM_T(uvd)->initialized = (setup_ok != 0);
+	}
+	return setup_ok;
+}
+
+static void ibmcam_configure_video(uvd_t *uvd)
+{
+	if (uvd == NULL)
+		return;
+
+	RESTRICT_TO_RANGE(init_brightness, 0, 255);
+	RESTRICT_TO_RANGE(init_contrast, 0, 255);
+	RESTRICT_TO_RANGE(init_color, 0, 255);
+	RESTRICT_TO_RANGE(init_hue, 0, 255);
+	RESTRICT_TO_RANGE(hue_correction, 0, 255);
+
+	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
+	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
+
+	uvd->vpic.colour = init_color << 8;
+	uvd->vpic.hue = init_hue << 8;
+	uvd->vpic.brightness = init_brightness << 8;
+	uvd->vpic.contrast = init_contrast << 8;
+	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
+	uvd->vpic.depth = 24;
+	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
+
+	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
+	strcpy(uvd->vcap.name, "IBM USB Camera");
+	uvd->vcap.type = VID_TYPE_CAPTURE;
+	uvd->vcap.channels = 1;
+	uvd->vcap.audios = 0;
+	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
+	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
+	uvd->vcap.minwidth = min_canvasWidth;
+	uvd->vcap.minheight = min_canvasHeight;
+
+	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
+	uvd->vchan.flags = 0;
+	uvd->vchan.tuners = 0;
+	uvd->vchan.channel = 0;
+	uvd->vchan.type = VIDEO_TYPE_CAMERA;
+	strcpy(uvd->vchan.name, "Camera");
+}
+
+/*
+ * ibmcam_probe()
+ *
+ * This procedure queries device descriptor and accepts the interface
+ * if it looks like IBM C-it camera.
+ *
+ * History:
+ * 22-Jan-2000 Moved camera init code to ibmcam_open()
+ * 27=Jan-2000 Changed to use static structures, added locking.
+ * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
+ * 03-Jul-2000 Fixed endianness bug.
+ * 12-Nov-2000 Reworked to comply with new probe() signature.
+ * 23-Jan-2001 Added compatibility with 2.2.x kernels.
+ */
+static void *ibmcam_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid)
+{
+	uvd_t *uvd = NULL;
+	int i, nas, model=0, canvasX=0, canvasY=0;
+	int actInterface=-1, inactInterface=-1, maxPS=0;
+	unsigned char video_ep = 0;
+
+	if (debug >= 1)
+		info("ibmcam_probe(%p,%u.)", dev, ifnum);
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1)
+		return NULL;
+
+	/* Is it an IBM camera? */
+	if (dev->descriptor.idVendor != IBMCAM_VENDOR_ID)
+		return NULL;
+	if ((dev->descriptor.idProduct != IBMCAM_PRODUCT_ID) &&
+	    (dev->descriptor.idProduct != VEO_800C_PRODUCT_ID) &&
+	    (dev->descriptor.idProduct != VEO_800D_PRODUCT_ID) &&
+	    (dev->descriptor.idProduct != NETCAM_PRODUCT_ID))
+		return NULL;
+
+	/* Check the version/revision */
+	switch (dev->descriptor.bcdDevice) {
+	case 0x0002:
+		if (ifnum != 2)
+			return NULL;
+		model = IBMCAM_MODEL_1;
+		break;
+	case 0x030A:
+		if (ifnum != 0)
+			return NULL;
+		if ((dev->descriptor.idProduct == NETCAM_PRODUCT_ID) ||
+		    (dev->descriptor.idProduct == VEO_800D_PRODUCT_ID))
+			model = IBMCAM_MODEL_4;
+		else
+			model = IBMCAM_MODEL_2;
+		break;
+	case 0x0301:
+		if (ifnum != 0)
+			return NULL;
+		model = IBMCAM_MODEL_3;
+		break;
+	default:
+		err("IBM camera with revision 0x%04x is not supported.",
+			dev->descriptor.bcdDevice);
+		return NULL;
+	}
+
+	/* Print detailed info on what we found so far */
+	do {
+		char *brand = NULL;
+		switch (dev->descriptor.idProduct) {
+		case NETCAM_PRODUCT_ID:
+			brand = "IBM NetCamera";
+			break;
+		case VEO_800C_PRODUCT_ID:
+			brand = "Veo Stingray [800C]";
+			break;
+		case VEO_800D_PRODUCT_ID:
+			brand = "Veo Stingray [800D]";
+			break;
+		case IBMCAM_PRODUCT_ID:
+		default:
+			brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
+			break;
+		}
+		info("%s USB camera found (model %d, rev. 0x%04x)",
+		     brand, model, dev->descriptor.bcdDevice);
+	} while (0);
+
+	/* Validate found interface: must have one ISO endpoint */
+	nas = dev->actconfig->interface[ifnum].num_altsetting;
+	if (debug > 0)
+		info("Number of alternate settings=%d.", nas);
+	if (nas < 2) {
+		err("Too few alternate settings for this camera!");
+		return NULL;
+	}
+	/* Validate all alternate settings */
+	for (i=0; i < nas; i++) {
+		const struct usb_interface_descriptor *interface;
+		const struct usb_endpoint_descriptor *endpoint;
+
+		interface = &dev->actconfig->interface[ifnum].altsetting[i];
+		if (interface->bNumEndpoints != 1) {
+			err("Interface %d. has %u. endpoints!",
+			    ifnum, (unsigned)(interface->bNumEndpoints));
+			return NULL;
+		}
+		endpoint = &interface->endpoint[0];
+		if (video_ep == 0)
+			video_ep = endpoint->bEndpointAddress;
+		else if (video_ep != endpoint->bEndpointAddress) {
+			err("Alternate settings have different endpoint addresses!");
+			return NULL;
+		}
+		if ((endpoint->bmAttributes & 0x03) != 0x01) {
+			err("Interface %d. has non-ISO endpoint!", ifnum);
+			return NULL;
+		}
+		if ((endpoint->bEndpointAddress & 0x80) == 0) {
+			err("Interface %d. has ISO OUT endpoint!", ifnum);
+			return NULL;
+		}
+		if (endpoint->wMaxPacketSize == 0) {
+			if (inactInterface < 0)
+				inactInterface = i;
+			else {
+				err("More than one inactive alt. setting!");
+				return NULL;
+			}
+		} else {
+			if (actInterface < 0) {
+				actInterface = i;
+				maxPS = endpoint->wMaxPacketSize;
+				if (debug > 0)
+					info("Active setting=%d. maxPS=%d.", i, maxPS);
+			} else
+				err("More than one active alt. setting! Ignoring #%d.", i);
+		}
+	}
+	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
+		err("Failed to recognize the camera!");
+		return NULL;
+	}
+
+	/* Validate options */
+	switch (model) {
+	case IBMCAM_MODEL_1:
+		RESTRICT_TO_RANGE(lighting, 0, 2);
+		RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288);
+		if (framerate < 0)
+			framerate = 2;
+		canvasX = 352;
+		canvasY = 288;
+		break;
+	case IBMCAM_MODEL_2:
+		RESTRICT_TO_RANGE(lighting, 0, 15);
+		RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240);
+		if (framerate < 0)
+			framerate = 2;
+		canvasX = 352;
+		canvasY = 240;
+		break;
+	case IBMCAM_MODEL_3:
+		RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */
+		switch (size) {
+		case SIZE_160x120:
+			canvasX = 160;
+			canvasY = 120;
+			if (framerate < 0)
+				framerate = 2;
+			RESTRICT_TO_RANGE(framerate, 0, 5);
+			break;
+		default:
+			info("IBM camera: using 320x240");
+			size = SIZE_320x240;
+			/* No break here */
+		case SIZE_320x240:
+			canvasX = 320;
+			canvasY = 240;
+			if (framerate < 0)
+				framerate = 3;
+			RESTRICT_TO_RANGE(framerate, 0, 5);
+			break;
+		case SIZE_640x480:
+			canvasX = 640;
+			canvasY = 480;
+			framerate = 0;	/* Slowest, and maybe even that is too fast */
+			break;
+		}
+		break;
+	case IBMCAM_MODEL_4:
+		RESTRICT_TO_RANGE(lighting, 0, 2);
+		switch (size) {
+		case SIZE_128x96:
+			canvasX = 128;
+			canvasY = 96;
+			break;
+		case SIZE_160x120:
+			canvasX = 160;
+			canvasY = 120;
+			break;
+		default:
+			info("IBM NetCamera: using 176x144");
+			size = SIZE_176x144;
+			/* No break here */
+		case SIZE_176x144:
+			canvasX = 176;
+			canvasY = 144;
+			break;
+		case SIZE_320x240:
+			canvasX = 320;
+			canvasY = 240;
+			break;
+		case SIZE_352x288:
+			canvasX = 352;
+			canvasY = 288;
+			break;
+		}
+		break;
+	default:
+		err("IBM camera: Model %d. not supported!", model);
+		return NULL;
+	}
+
+	/* Code below may sleep, need to lock module while we are here */
+	MOD_INC_USE_COUNT;
+	uvd = usbvideo_AllocateDevice(cams);
+	if (uvd != NULL) {
+		/* Here uvd is a fully allocated uvd_t object */
+		uvd->flags = flags;
+		uvd->debug = debug;
+		uvd->dev = dev;
+		uvd->iface = ifnum;
+		uvd->ifaceAltInactive = inactInterface;
+		uvd->ifaceAltActive = actInterface;
+		uvd->video_endp = video_ep;
+		uvd->iso_packet_len = maxPS;
+		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
+		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
+		uvd->canvas = VIDEOSIZE(canvasX, canvasY);
+		uvd->videosize = ibmcam_size_to_videosize(size);
+
+		/* Initialize ibmcam-specific data */
+		assert(IBMCAM_T(uvd) != NULL);
+		IBMCAM_T(uvd)->camera_model = model;
+		IBMCAM_T(uvd)->initialized = 0;
+
+		ibmcam_configure_video(uvd);
+
+		i = usbvideo_RegisterVideoDevice(uvd);
+		if (i != 0) {
+			err("usbvideo_RegisterVideoDevice() failed.");
+			uvd = NULL;
+		}
+	}
+	MOD_DEC_USE_COUNT;
+	return uvd;
+}
+
+/*
+ * ibmcam_init()
+ *
+ * This code is run to initialize the driver.
+ *
+ * History:
+ * 1/27/00  Reworked to use statically allocated ibmcam structures.
+ * 21/10/00 Completely redesigned to use usbvideo services.
+ */
+static int __init ibmcam_init(void)
+{
+	usbvideo_cb_t cbTbl;
+	memset(&cbTbl, 0, sizeof(cbTbl));
+	cbTbl.probe = ibmcam_probe;
+	cbTbl.setupOnOpen = ibmcam_setup_on_open;
+	cbTbl.videoStart = ibmcam_video_start;
+	cbTbl.videoStop = ibmcam_video_stop;
+	cbTbl.processData = ibmcam_ProcessIsocData;
+	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
+	cbTbl.adjustPicture = ibmcam_adjust_picture;
+	cbTbl.getFPS = ibmcam_calculate_fps;
+	return usbvideo_register(
+		&cams,
+		MAX_IBMCAM,
+		sizeof(ibmcam_t),
+		"ibmcam",
+		&cbTbl,
+		THIS_MODULE);
+}
+
+static void __exit ibmcam_cleanup(void)
+{
+	usbvideo_Deregister(&cams);
+}
+
+static __devinitdata struct usb_device_id id_table[] = {
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) },	/* Model 1 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) },	/* Model 3 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 2 */
+	{ USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) },	/* Model 4 */
+	{ }  /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+module_init(ibmcam_init);
+module_exit(ibmcam_cleanup);
diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/konicawc.c	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,802 @@
+/*
+ * $Id$
+ *
+ * konicawc.c - konica webcam driver
+ *
+ * Author: Simon Evans <spse@secret.org.uk>
+ *
+ * Copyright (C) 2002 Simon Evans
+ *
+ * Licence: GPL
+ * 
+ * Driver for USB webcams based on Konica chipset. This
+ * chipset is used in Intel YC76 camera.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "usbvideo.h"
+
+#define MAX_BRIGHTNESS	108
+#define MAX_CONTRAST	108
+#define MAX_SATURATION	108
+#define MAX_SHARPNESS	108
+#define MAX_WHITEBAL	372
+#define MAX_SPEED	6
+#define MAX_CAMERAS	1
+
+#define DRIVER_VERSION	"v1.1"
+#define DRIVER_DESC	"Konica Webcam driver"
+
+enum ctrl_req {
+	SetWhitebal	= 0x01,
+	SetBrightness	= 0x02,
+        SetSharpness	= 0x03,
+	SetContrast	= 0x04,
+	SetSaturation	= 0x05,
+};
+
+
+enum frame_sizes {
+	SIZE_160X136	= 0,
+	SIZE_176X144	= 1,
+	SIZE_320X240	= 2,
+};
+
+
+static usbvideo_t *cams;
+
+/* Some default values for inital camera settings,
+   can be set by modprobe */
+
+static int debug;
+static enum frame_sizes size;	
+static int speed = 6;		/* Speed (fps) 0 (slowest) to 6 (fastest) */
+static int brightness =	MAX_BRIGHTNESS/2;
+static int contrast =	MAX_CONTRAST/2;
+static int saturation =	MAX_SATURATION/2;
+static int sharpness =	MAX_SHARPNESS/2;
+static int whitebal =	3*(MAX_WHITEBAL/4);
+
+static int speed_to_interface[] = { 1, 0, 3, 2, 4, 5, 6 };
+
+/* These FPS speeds are from the windows config box. They are
+ * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
+ * real fps.
+ */
+
+static int speed_to_fps[3][7] = { { 24, 40, 48, 60, 72, 80, 100 },
+				  { 18, 30, 36, 45, 54, 60, 75  },
+				  { 6,  10, 12, 15, 18, 20, 25  } };
+
+
+static int camera_sizes[][2] = { { 160, 136 },
+				 { 176, 144 },
+				 { 320, 240 },
+				 { } /* List terminator */
+};
+
+struct konicawc {
+	u8 brightness;		/* camera uses 0 - 9, x11 for real value */
+	u8 contrast;		/* as above */
+	u8 saturation;		/* as above */
+	u8 sharpness;		/* as above */
+	u8 white_bal;		/* 0 - 33, x11 for real value */
+	u8 speed;		/* Stored as 0 - 6, used as index in speed_to_* (above) */
+	u8 size;		/* Frame Size */
+	int height;
+	int width;
+	struct urb *sts_urb[USBVIDEO_NUMSBUF];
+	u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];
+	struct urb *last_data_urb;
+	int lastframe;
+};
+
+
+#define konicawc_set_misc(uvd, req, value, index)		konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)
+#define konicawc_get_misc(uvd, req, value, index, buf, sz)	konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)
+#define konicawc_set_value(uvd, value, index)			konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)
+
+
+static int konicawc_ctrl_msg(uvd_t *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
+{
+        int retval = usb_control_msg(uvd->dev,
+		dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
+		    request, 0x40 | dir, value, index, buf, len, HZ);
+        return retval < 0 ? retval : 0;
+}
+
+
+static int konicawc_setup_on_open(uvd_t *uvd)
+{
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+	konicawc_set_misc(uvd, 0x2, 0, 0x0b);
+	dbg("setting brightness to %d (%d)", cam->brightness,
+	    cam->brightness * 11);
+	konicawc_set_value(uvd, cam->brightness, SetBrightness);
+	dbg("setting white balance to %d (%d)", cam->white_bal,
+	    cam->white_bal * 11);
+	konicawc_set_value(uvd, cam->white_bal, SetWhitebal);
+	dbg("setting contrast to %d (%d)", cam->contrast,
+	    cam->contrast * 11);
+	konicawc_set_value(uvd, cam->contrast, SetContrast);
+	dbg("setting saturation to %d (%d)", cam->saturation,
+	    cam->saturation * 11);
+	konicawc_set_value(uvd, cam->saturation, SetSaturation);
+	dbg("setting sharpness to %d (%d)", cam->sharpness,
+	    cam->sharpness * 11);
+	konicawc_set_value(uvd, cam->sharpness, SetSharpness);
+	dbg("setting size %d", cam->size);
+	switch(cam->size) {
+	case 0:
+		konicawc_set_misc(uvd, 0x2, 0xa, 0x08);
+		break;
+
+	case 1:
+		konicawc_set_misc(uvd, 0x2, 4, 0x08);
+		break;
+
+	case 2:
+		konicawc_set_misc(uvd, 0x2, 5, 0x08);
+		break;
+	}
+	konicawc_set_misc(uvd, 0x2, 1, 0x0b);
+	cam->lastframe = -1;
+	return 0;
+}
+
+
+static void konicawc_adjust_picture(uvd_t *uvd)
+{
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+	dbg("new brightness: %d", uvd->vpic.brightness);
+	uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness;
+	if(cam->brightness != uvd->vpic.brightness / 11) {
+	   cam->brightness = uvd->vpic.brightness / 11;
+	   dbg("setting brightness to %d (%d)", cam->brightness,
+	       cam->brightness * 11);
+	   konicawc_set_value(uvd, cam->brightness, SetBrightness);
+	}
+
+	dbg("new contrast: %d", uvd->vpic.contrast);
+	uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast;
+	if(cam->contrast != uvd->vpic.contrast / 11) {
+		cam->contrast = uvd->vpic.contrast / 11;
+		dbg("setting contrast to %d (%d)", cam->contrast,
+		    cam->contrast * 11);
+		konicawc_set_value(uvd, cam->contrast, SetContrast);
+	}
+}
+
+
+static int konicawc_compress_iso(uvd_t *uvd, struct urb *dataurb, struct urb *stsurb)
+{
+	char *cdata;
+	int i, totlen = 0;
+	unsigned char *status = stsurb->transfer_buffer;
+	int keep = 0, discard = 0, bad = 0;
+	static int buttonsts = 0;
+
+	for (i = 0; i < dataurb->number_of_packets; i++) {
+		int button = buttonsts;
+		unsigned char sts;
+		int n = dataurb->iso_frame_desc[i].actual_length;
+		int st = dataurb->iso_frame_desc[i].status;
+		cdata = dataurb->transfer_buffer + 
+			dataurb->iso_frame_desc[i].offset;
+
+		/* Detect and ignore errored packets */
+		if (st < 0) {
+			if (debug >= 1)
+				err("Data error: packet=%d. len=%d. status=%d.",
+				    i, n, st);
+			uvd->stats.iso_err_count++;
+			continue;
+		}
+
+		/* Detect and ignore empty packets */
+		if (n <= 0) {
+			uvd->stats.iso_skip_count++;
+			continue;
+		}
+
+		/* See what the status data said about the packet */
+		sts = *(status+stsurb->iso_frame_desc[i].offset);
+
+		/* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
+		 * otherwise:
+		 * bit 0 0:drop packet (padding data)
+		 *	 1 keep packet
+		 *
+		 * bit 4 0 button not clicked
+		 *       1 button clicked
+		 * button is used to `take a picture' (in software)
+		 */
+
+		if(sts < 0x80) {
+			button = sts & 0x40;
+			sts &= ~0x40;
+		}
+		
+		/* work out the button status, but dont do
+		   anything with it for now */
+		   
+		if(button != buttonsts) {
+			dbg("button: %sclicked", button ? "" : "un");
+			buttonsts = button;
+		}
+
+		if(sts == 0x01) { /* drop frame */
+			discard++;
+			continue;
+		}
+		
+		if((sts > 0x01) && (sts < 0x80)) {
+			info("unknown status %2.2x", sts);
+			bad++;
+			continue;
+		}
+
+		keep++;
+		if(*(status+i) & 0x80) { /* frame start */
+			unsigned char marker[] = { 0, 0xff, 0, 0x00 };
+			if(debug > 1)
+				dbg("Adding Marker packet = %d, frame = %2.2x",
+				    i, *(status+i));
+			marker[3] = *(status+i) - 0x80;
+			RingQueue_Enqueue(&uvd->dp, marker, 4);			
+			totlen += 4;
+		}
+		totlen += n;	/* Little local accounting */
+		if(debug > 5)
+			dbg("Adding packet %d, bytes = %d", i, n);
+		RingQueue_Enqueue(&uvd->dp, cdata, n);
+
+	}
+	if(debug > 8) {
+		dbg("finished: keep = %d discard = %d bad = %d added %d bytes",
+		    keep, discard, bad, totlen);
+	}
+	return totlen;
+}
+
+
+static void konicawc_isoc_irq(struct urb *urb)
+{
+	int i, len = 0;
+	uvd_t *uvd = urb->context;
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+	/* We don't want to do anything if we are about to be removed! */
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return;
+
+	if (urb->actual_length > 32) {
+		cam->last_data_urb = urb;
+		return;
+	}
+
+	if (!uvd->streaming) {
+		if (debug >= 1)
+			info("Not streaming, but interrupt!");
+		return;
+	}
+
+	uvd->stats.urb_count++;
+	if (urb->actual_length <= 0)
+		goto urb_done_with;
+
+	/* Copy the data received into ring queue */
+	if(cam->last_data_urb) {
+		len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
+		for (i = 0; i < FRAMES_PER_DESC; i++) {
+			cam->last_data_urb->iso_frame_desc[i].status = 0;
+			cam->last_data_urb->iso_frame_desc[i].actual_length = 0;
+		}
+		cam->last_data_urb = NULL;
+	}
+	uvd->stats.urb_length = len;
+	if (len <= 0) {
+		goto urb_done_with;
+	}
+
+	/* Here we got some data */
+	uvd->stats.data_count += len;
+	RingQueue_WakeUpInterruptible(&uvd->dp);
+
+urb_done_with:
+
+	for (i = 0; i < FRAMES_PER_DESC; i++) {
+		urb->iso_frame_desc[i].status = 0;
+		urb->iso_frame_desc[i].actual_length = 0;
+	}
+	return;
+}
+
+
+static int konicawc_start_data(uvd_t *uvd)
+{
+	struct usb_device *dev = uvd->dev;
+	int i, errFlag;
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd)) {
+		err("Camera is not operational");
+		return -EFAULT;
+	}
+	uvd->curframe = -1;
+
+	/* Alternate interface 1 is is the biggest frame size */
+	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
+	if (i < 0) {
+		err("usb_set_interface error");
+		uvd->last_error = i;
+		return -EBUSY;
+	}
+
+	/* We double buffer the Iso lists */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		int j, k;
+		struct urb *urb = uvd->sbuf[i].urb;
+		urb->dev = dev;
+		urb->context = uvd;
+		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->transfer_buffer = uvd->sbuf[i].data;
+		urb->complete = konicawc_isoc_irq;
+		urb->number_of_packets = FRAMES_PER_DESC;
+		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
+		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
+			urb->iso_frame_desc[j].offset = k;
+			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
+		}
+
+		urb = cam->sts_urb[i];
+		urb->dev = dev;
+		urb->context = uvd;
+		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->transfer_buffer = cam->sts_buf[i];
+		urb->complete = konicawc_isoc_irq;
+		urb->number_of_packets = FRAMES_PER_DESC;
+		urb->transfer_buffer_length = FRAMES_PER_DESC;
+		for (j=0; j < FRAMES_PER_DESC; j++) {
+			urb->iso_frame_desc[j].offset = j;
+			urb->iso_frame_desc[j].length = 1;
+		}
+	}
+
+	cam->last_data_urb = NULL;
+	
+	/* Link URBs into a ring so that they invoke each other infinitely */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		if ((i+1) < USBVIDEO_NUMSBUF) {
+			cam->sts_urb[i]->next = uvd->sbuf[i].urb;
+			uvd->sbuf[i].urb->next = cam->sts_urb[i+1];
+		} else {
+			cam->sts_urb[i]->next = uvd->sbuf[i].urb;
+			uvd->sbuf[i].urb->next = cam->sts_urb[0];
+		}
+	}
+
+	/* Submit all URBs */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+		if (errFlag)
+			err ("usb_submit_isoc(%d) ret %d", i, errFlag);
+
+		errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL);
+		if (errFlag)
+			err("usb_submit_isoc(%d) ret %d", i, errFlag);
+	}
+
+	uvd->streaming = 1;
+	if (debug > 1)
+		dbg("streaming=1 video_endp=$%02x", uvd->video_endp);
+	return 0;
+}
+
+
+static void konicawc_stop_data(uvd_t *uvd)
+{
+	int i, j;
+	struct konicawc *cam;
+
+	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
+		return;
+
+	cam = (struct konicawc *)uvd->user_data;
+	cam->last_data_urb = NULL;
+
+	/* Unschedule all of the iso td's */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		j = usb_unlink_urb(uvd->sbuf[i].urb);
+		if (j < 0)
+			err("usb_unlink_urb() error %d.", j);
+
+		j = usb_unlink_urb(cam->sts_urb[i]);
+		if (j < 0)
+			err("usb_unlink_urb() error %d.", j);
+	}
+
+	uvd->streaming = 0;
+
+	if (!uvd->remove_pending) {
+		/* Set packet size to 0 */
+		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
+		if (j < 0) {
+			err("usb_set_interface() error %d.", j);
+			uvd->last_error = j;
+		}
+	}
+}
+
+
+static void konicawc_process_isoc(uvd_t *uvd, usbvideo_frame_t *frame)
+{	
+	int n;
+	int maxline, yplanesz;
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+	assert(uvd != NULL);
+	assert(frame != NULL);
+
+	maxline = (cam->height * cam->width * 3) / (2 * 384);
+	yplanesz = cam->height * cam->width;
+	if(debug > 5)
+		dbg("maxline = %d yplanesz = %d", maxline, yplanesz);
+	
+	if(debug > 3)
+		dbg("Frame state = %d", frame->scanstate);
+
+	if(frame->scanstate == ScanState_Scanning) {
+		int drop = 0;
+		int curframe;
+		int fdrops = 0;
+		if(debug > 3)
+			dbg("Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp));
+		while(RingQueue_GetLength(&uvd->dp) >= 4) {
+			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) {
+				curframe = RING_QUEUE_PEEK(&uvd->dp, 3);
+				if(cam->lastframe != -1) {
+					if(curframe < cam->lastframe) {
+						fdrops = (curframe + 0x80) - cam->lastframe;
+					} else {
+						fdrops = curframe - cam->lastframe;
+					}
+					fdrops--;
+					if(fdrops)
+						info("Dropped %d frames (%d -> %d)", fdrops,
+						     cam->lastframe, curframe);
+				}
+				cam->lastframe = curframe;
+				frame->curline = 0;
+				frame->scanstate = ScanState_Lines;
+				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
+				break;
+			}
+			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+			drop++;
+		}
+	}
+
+	if(frame->scanstate == ScanState_Scanning)
+		return;
+		
+	/* Try to move data from queue into frame buffer 
+	 * We get data in blocks of 384 bytes made up of:
+	 * 256 Y, 64 U, 64 V.
+	 * This needs to be written out as a Y plane, a U plane and a V plane.
+	 */
+		
+	while ( frame->curline < maxline && (n = RingQueue_GetLength(&uvd->dp)) >= 384) {
+		/* Y */
+		RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
+		/* U */
+		RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64);
+		/* V */
+		RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64);
+		frame->seqRead_Length += 384;
+		frame->curline++;
+	}
+	/* See if we filled the frame */
+	if (frame->curline == maxline) {
+		if(debug > 5)
+			dbg("got whole frame");
+
+		frame->frameState = FrameState_Done_Hold;
+		frame->curline = 0;
+		uvd->curframe = -1;
+		uvd->stats.frame_num++;
+	}
+}
+
+
+static int konicawc_calculate_fps(uvd_t *uvd)
+{
+	struct konicawc *t = uvd->user_data;
+	dbg("fps = %d", speed_to_fps[t->size][t->speed]/3);
+
+	return speed_to_fps[t->size][t->speed]/3;
+}
+
+
+static void konicawc_configure_video(uvd_t *uvd)
+{
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+	u8 buf[2];
+
+	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
+	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
+
+	RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS);
+	RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST);
+	RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION);
+	RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS);
+	RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL);
+
+	cam->brightness = brightness / 11;
+	cam->contrast = contrast / 11;
+	cam->saturation = saturation / 11;
+	cam->sharpness = sharpness / 11;
+	cam->white_bal = whitebal / 11;
+
+	uvd->vpic.colour = 108;
+	uvd->vpic.hue = 108;
+	uvd->vpic.brightness = brightness;
+	uvd->vpic.contrast = contrast;
+	uvd->vpic.whiteness = whitebal;
+	uvd->vpic.depth = 6;
+	uvd->vpic.palette = VIDEO_PALETTE_YUV420P;
+
+	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
+	strcpy(uvd->vcap.name, "Konica Webcam");
+	uvd->vcap.type = VID_TYPE_CAPTURE;
+	uvd->vcap.channels = 1;
+	uvd->vcap.audios = 0;
+	uvd->vcap.minwidth = camera_sizes[cam->size][0];
+	uvd->vcap.minheight = camera_sizes[cam->size][1];
+	uvd->vcap.maxwidth = camera_sizes[cam->size][0];
+	uvd->vcap.maxheight = camera_sizes[cam->size][1];
+
+	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
+	uvd->vchan.flags = 0 ;
+	uvd->vchan.tuners = 0;
+	uvd->vchan.channel = 0;
+	uvd->vchan.type = VIDEO_TYPE_CAMERA;
+	strcpy(uvd->vchan.name, "Camera");
+
+	/* Talk to device */
+	dbg("device init");
+	if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
+		dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]);
+	if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
+		dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]);
+	if(konicawc_set_misc(uvd, 0x2, 0, 0xd))
+		dbg("2,0,d failed");
+	dbg("setting initial values");
+
+}
+
+
+static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid)
+{
+	uvd_t *uvd = NULL;
+	int i, nas;
+	int actInterface=-1, inactInterface=-1, maxPS=0;
+	unsigned char video_ep = 0;
+	
+	if (debug >= 1)
+		dbg("konicawc_probe(%p,%u.)", dev, ifnum);
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1)
+		return NULL;
+
+	info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice);
+	RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
+
+	/* Validate found interface: must have one ISO endpoint */
+	nas = dev->actconfig->interface[ifnum].num_altsetting;
+	if (debug > 0)
+		info("Number of alternate settings=%d.", nas);
+	if (nas < 8) {
+		err("Too few alternate settings for this camera!");
+		return NULL;
+	}
+	/* Validate all alternate settings */
+	for (i=0; i < nas; i++) {
+		const struct usb_interface_descriptor *interface;
+		const struct usb_endpoint_descriptor *endpoint;
+
+		interface = &dev->actconfig->interface[ifnum].altsetting[i];
+		if (interface->bNumEndpoints != 2) {
+			err("Interface %d. has %u. endpoints!",
+			    ifnum, (unsigned)(interface->bNumEndpoints));
+			return NULL;
+		}
+		endpoint = &interface->endpoint[1];
+		dbg("found endpoint: addr: 0x%2.2x maxps = 0x%4.4x",
+		    endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
+		if (video_ep == 0)
+			video_ep = endpoint->bEndpointAddress;
+		else if (video_ep != endpoint->bEndpointAddress) {
+			err("Alternate settings have different endpoint addresses!");
+			return NULL;
+		}
+		if ((endpoint->bmAttributes & 0x03) != 0x01) {
+			err("Interface %d. has non-ISO endpoint!", ifnum);
+			return NULL;
+		}
+		if ((endpoint->bEndpointAddress & 0x80) == 0) {
+			err("Interface %d. has ISO OUT endpoint!", ifnum);
+			return NULL;
+		}
+		if (endpoint->wMaxPacketSize == 0) {
+			if (inactInterface < 0)
+				inactInterface = i;
+			else {
+				err("More than one inactive alt. setting!");
+				return NULL;
+			}
+		} else {
+			if (i == speed_to_interface[speed]) {
+				/* This one is the requested one */
+				actInterface = i;
+				maxPS = endpoint->wMaxPacketSize;
+				if (debug > 0) {
+					info("Selecting requested active setting=%d. maxPS=%d.",
+					     i, maxPS);
+				}
+			}
+		}
+	}
+	if(actInterface == -1) {
+		err("Cant find required endpoint");
+		return NULL;
+	}
+
+
+	/* Code below may sleep, need to lock module while we are here */
+	MOD_INC_USE_COUNT;
+	uvd = usbvideo_AllocateDevice(cams);
+	if (uvd != NULL) {
+		struct konicawc *cam = (struct konicawc *)(uvd->user_data);
+		/* Here uvd is a fully allocated uvd_t object */
+		for(i = 0; i < USBVIDEO_NUMSBUF; i++) {
+			cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
+			if(cam->sts_urb[i] == NULL) {
+				while(i--) {
+					usb_free_urb(cam->sts_urb[i]);
+				}
+				err("cant allocate urbs");
+				return NULL;
+			}
+		}
+		cam->speed = speed;
+		switch(size) {
+		case SIZE_160X136:
+		default:
+			cam->height = 136;
+			cam->width = 160;
+			cam->size = SIZE_160X136;
+			break;
+
+		case SIZE_176X144:
+			cam->height = 144;
+			cam->width = 176;
+			cam->size = SIZE_176X144;
+			break;
+
+		case SIZE_320X240:
+			cam->height = 240;
+			cam->width = 320;
+			cam->size = SIZE_320X240;
+			break;
+		}
+
+		uvd->flags = 0;
+		uvd->debug = debug;
+		uvd->dev = dev;
+		uvd->iface = ifnum;
+		uvd->ifaceAltInactive = inactInterface;
+		uvd->ifaceAltActive = actInterface;
+		uvd->video_endp = video_ep;
+		uvd->iso_packet_len = maxPS;
+		uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P;
+		uvd->defaultPalette = VIDEO_PALETTE_YUV420P;
+		uvd->canvas = VIDEOSIZE(cam->width, cam->height);
+		uvd->videosize = uvd->canvas;
+
+		/* Initialize konicawc specific data */
+		konicawc_configure_video(uvd);
+
+		i = usbvideo_RegisterVideoDevice(uvd);
+		uvd->max_frame_size = (cam->width * cam->height * 3)/2;
+		if (i != 0) {
+			err("usbvideo_RegisterVideoDevice() failed.");
+			uvd = NULL;
+		}
+	}
+	MOD_DEC_USE_COUNT;
+	return uvd;
+}
+
+
+static void konicawc_free_uvd(uvd_t *uvd)
+{
+	int i;
+	struct konicawc *cam = (struct konicawc *)uvd->user_data;
+
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		usb_free_urb(cam->sts_urb[i]);
+		cam->sts_urb[i] = NULL;
+	}
+}
+
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
+	{ }  /* Terminating entry */
+};
+
+
+static int __init konicawc_init(void)
+{
+	usbvideo_cb_t cbTbl;
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	memset(&cbTbl, 0, sizeof(cbTbl));
+	cbTbl.probe = konicawc_probe;
+	cbTbl.setupOnOpen = konicawc_setup_on_open;
+	cbTbl.processData = konicawc_process_isoc;
+	cbTbl.getFPS = konicawc_calculate_fps;
+	cbTbl.startDataPump = konicawc_start_data;
+	cbTbl.stopDataPump = konicawc_stop_data;
+	cbTbl.adjustPicture = konicawc_adjust_picture;
+	cbTbl.userFree = konicawc_free_uvd;
+	return usbvideo_register(
+		&cams,
+		MAX_CAMERAS,
+		sizeof(struct konicawc),
+		"konicawc",
+		&cbTbl,
+		THIS_MODULE);
+}
+
+
+static void __exit konicawc_cleanup(void)
+{
+	usbvideo_Deregister(&cams);
+}
+
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_PARM(speed, "i");
+MODULE_PARM_DESC(speed, "FPS speed: 0 (slowest) - 6 (fastest)");
+MODULE_PARM(size, "i");
+MODULE_PARM_DESC(size, "Frame Size 0: 160x136 1: 176x144 2: 320x240");
+MODULE_PARM(brightness, "i");
+MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
+MODULE_PARM(contrast, "i");
+MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
+MODULE_PARM(saturation, "i");
+MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
+MODULE_PARM(sharpness, "i");
+MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
+MODULE_PARM(whitebal, "i");
+MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+module_init(konicawc_init);
+module_exit(konicawc_cleanup);
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/ov511.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,6714 @@
+/*
+ * OmniVision OV511 Camera-to-USB Bridge Driver
+ *
+ * Copyright (c) 1999-2002 Mark W. McClelland
+ * Original decompression code Copyright 1998-2000 OmniVision Technologies
+ * Many improvements by Bret Wallach <bwallac1@san.rr.com>
+ * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
+ * Snapshot code by Kevin Moore
+ * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
+ * Changes by Claudio Matsuoka <claudio@conectiva.com>
+ * Original SAA7111A code by Dave Perks <dperks@ibm.net>
+ * Kernel I2C interface adapted from nt1003 driver
+ * URB error messages from pwc driver by Nemosoft
+ * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox
+ *
+ * Based on the Linux CPiA driver written by Peter Pregler,
+ * Scott J. Bertin and Johannes Erdfelt.
+ * 
+ * Please see the file: linux/Documentation/usb/ov511.txt 
+ * and the website at:  http://alpha.dyndns.org/ov511
+ * for more info.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/pagemap.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <linux/wrapper.h>
+#include <linux/mm.h>
+
+#if defined (__i386__)
+	#include <asm/cpufeature.h>
+#endif
+
+#include "ov511.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.53 for Linux 2.5"
+#define EMAIL "mmcclell@bigfoot.com"
+#define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \
+	& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
+	<cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
+#define DRIVER_DESC "ov511 USB Camera Driver"
+
+#define OV511_I2C_RETRIES 3
+#define ENABLE_Y_QUANTABLE 1
+#define ENABLE_UV_QUANTABLE 1
+
+/* If you change this, you must also change the MODULE_PARM definition */
+#define OV511_MAX_UNIT_VIDEO 16
+
+/* Pixel count * 3 bytes for RGB */
+#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)
+#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))
+
+/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */
+#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024)
+
+#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
+
+/**********************************************************************
+ * Module Parameters
+ * (See ov511.txt for detailed descriptions of these)
+ **********************************************************************/
+
+/* These variables (and all static globals) default to zero */
+static int autobright		= 1;
+static int autogain		= 1;
+static int autoexp		= 1;
+static int debug;
+static int fix_rgb_offset;
+static int snapshot;
+static int force_rgb;
+static int buf_timeout		= 5;
+static int cams			= 1;
+static int compress;
+static int testpat;
+static int sensor_gbr;
+static int dumppix;
+static int led 			= 1;
+static int dump_bridge;
+static int dump_sensor;
+static int printph;
+static int phy			= 0x1f;
+static int phuv			= 0x05;
+static int pvy			= 0x06;
+static int pvuv			= 0x06;
+static int qhy			= 0x14;
+static int qhuv			= 0x03;
+static int qvy			= 0x04;
+static int qvuv			= 0x04;
+static int lightfreq;
+static int bandingfilter;
+
+/* Pixel clock divisor */
+static int clockdiv		= -1;
+
+/* Isoc packet size */
+static int packetsize		= -1;
+
+/* Frame drop register (16h) */
+static int framedrop		= -1;
+
+static int fastset;
+static int force_palette;
+static int tuner		= -1;
+static int backlight;
+static int unit_video[OV511_MAX_UNIT_VIDEO];
+static int remove_zeros;
+
+MODULE_PARM(autobright, "i");
+MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
+MODULE_PARM(autogain, "i");
+MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
+MODULE_PARM(autoexp, "i");
+MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug,
+  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
+MODULE_PARM(fix_rgb_offset, "i");
+MODULE_PARM_DESC(fix_rgb_offset,
+  "Fix vertical misalignment of red and blue at 640x480");
+MODULE_PARM(snapshot, "i");
+MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
+MODULE_PARM(force_rgb, "i");
+MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
+MODULE_PARM(buf_timeout, "i");
+MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");
+MODULE_PARM(cams, "i");
+MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
+MODULE_PARM(compress, "i");
+MODULE_PARM_DESC(compress, "Turn on compression (not reliable yet)");
+MODULE_PARM(testpat, "i");
+MODULE_PARM_DESC(testpat,
+  "Replace image with vertical bar testpattern (only partially working)");
+
+// Temporarily removed (needs to be rewritten for new format conversion code)
+// MODULE_PARM(sensor_gbr, "i");
+// MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
+
+MODULE_PARM(dumppix, "i");
+MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
+MODULE_PARM(led, "i");
+MODULE_PARM_DESC(led,
+  "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
+MODULE_PARM(dump_bridge, "i");
+MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
+MODULE_PARM(dump_sensor, "i");
+MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
+MODULE_PARM(printph, "i");
+MODULE_PARM_DESC(printph, "Print frame start/end headers");
+MODULE_PARM(phy, "i");
+MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
+MODULE_PARM(phuv, "i");
+MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
+MODULE_PARM(pvy, "i");
+MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
+MODULE_PARM(pvuv, "i");
+MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
+MODULE_PARM(qhy, "i");
+MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
+MODULE_PARM(qhuv, "i");
+MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
+MODULE_PARM(qvy, "i");
+MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
+MODULE_PARM(qvuv, "i");
+MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
+MODULE_PARM(lightfreq, "i");
+MODULE_PARM_DESC(lightfreq,
+  "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
+MODULE_PARM(bandingfilter, "i");
+MODULE_PARM_DESC(bandingfilter,
+  "Enable banding filter (to reduce effects of fluorescent lighting)");
+MODULE_PARM(clockdiv, "i");
+MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
+MODULE_PARM(packetsize, "i");
+MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
+MODULE_PARM(framedrop, "i");
+MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
+MODULE_PARM(fastset, "i");
+MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
+MODULE_PARM(force_palette, "i");
+MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
+MODULE_PARM(tuner, "i");
+MODULE_PARM_DESC(tuner, "Set tuner type, if not autodetected");
+MODULE_PARM(backlight, "i");
+MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
+MODULE_PARM(unit_video, "0-16i");
+MODULE_PARM_DESC(unit_video,
+  "Force use of specific minor number(s). 0 is not allowed.");
+MODULE_PARM(remove_zeros, "i");
+MODULE_PARM_DESC(remove_zeros,
+  "Remove zero-padding from uncompressed incoming data");
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/**********************************************************************
+ * Miscellaneous Globals
+ **********************************************************************/
+
+static struct usb_driver ov511_driver;
+
+static struct ov51x_decomp_ops *ov511_decomp_ops;
+static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;
+static struct ov51x_decomp_ops *ov518_decomp_ops;
+static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
+
+/* Number of times to retry a failed I2C transaction. Increase this if you
+ * are getting "Failed to read sensor ID..." */
+static int i2c_detect_tries = 5;
+
+/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
+static int ov51x_mmx_available;
+
+static __devinitdata struct usb_device_id device_table [] = {
+	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
+	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
+	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
+	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
+	{ USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
+	{ }  /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, device_table);
+
+static unsigned char yQuanTable511[] = OV511_YQUANTABLE;
+static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;
+static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
+static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
+
+/**********************************************************************
+ * Symbolic Names
+ **********************************************************************/
+
+/* Known OV511-based cameras */
+static struct symbolic_list camlist[] = {
+	{   0, "Generic Camera (no ID)" },
+	{   1, "Mustek WCam 3X" },
+	{   3, "D-Link DSB-C300" },
+	{   4, "Generic OV511/OV7610" },
+	{   5, "Puretek PT-6007" },
+	{   6, "Lifeview USB Life TV (NTSC)" },
+	{  21, "Creative Labs WebCam 3" },
+	{  36, "Koala-Cam" },
+	{  38, "Lifeview USB Life TV" },
+	{  41, "Samsung Anycam MPC-M10" },
+	{  43, "Mtekvision Zeca MV402" },
+	{  46, "Suma eON" },
+	{ 100, "Lifeview RoboCam" },
+	{ 102, "AverMedia InterCam Elite" },
+	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */
+	{ 192, "Webeye 2000B" },
+	{  -1, NULL }
+};
+
+/* Video4Linux1 Palettes */
+static struct symbolic_list v4l1_plist[] = {
+	{ VIDEO_PALETTE_GREY,	"GREY" },
+	{ VIDEO_PALETTE_HI240,	"HI240" },
+	{ VIDEO_PALETTE_RGB565,	"RGB565" },
+	{ VIDEO_PALETTE_RGB24,	"RGB24" },
+	{ VIDEO_PALETTE_RGB32,	"RGB32" },
+	{ VIDEO_PALETTE_RGB555,	"RGB555" },
+	{ VIDEO_PALETTE_YUV422,	"YUV422" },
+	{ VIDEO_PALETTE_YUYV,	"YUYV" },
+	{ VIDEO_PALETTE_UYVY,	"UYVY" },
+	{ VIDEO_PALETTE_YUV420,	"YUV420" },
+	{ VIDEO_PALETTE_YUV411,	"YUV411" },
+	{ VIDEO_PALETTE_RAW,	"RAW" },
+	{ VIDEO_PALETTE_YUV422P,"YUV422P" },
+	{ VIDEO_PALETTE_YUV411P,"YUV411P" },
+	{ VIDEO_PALETTE_YUV420P,"YUV420P" },
+	{ VIDEO_PALETTE_YUV410P,"YUV410P" },
+	{ -1, NULL }
+};
+
+static struct symbolic_list brglist[] = {
+	{ BRG_OV511,		"OV511" },
+	{ BRG_OV511PLUS,	"OV511+" },
+	{ BRG_OV518,		"OV518" },
+	{ BRG_OV518PLUS,	"OV518+" },
+	{ -1, NULL }
+};
+
+static struct symbolic_list senlist[] = {
+	{ SEN_OV76BE,	"OV76BE" },
+	{ SEN_OV7610,	"OV7610" },
+	{ SEN_OV7620,	"OV7620" },
+	{ SEN_OV7620AE,	"OV7620AE" },
+	{ SEN_OV6620,	"OV6620" },
+	{ SEN_OV6630,	"OV6630" },
+	{ SEN_OV6630AE,	"OV6630AE" },
+	{ SEN_OV6630AF,	"OV6630AF" },
+	{ SEN_OV8600,	"OV8600" },
+	{ SEN_KS0127,	"KS0127" },
+	{ SEN_KS0127B,	"KS0127B" },
+	{ SEN_SAA7111A,	"SAA7111A" },
+	{ -1, NULL }
+};
+
+/* URB error codes: */
+static struct symbolic_list urb_errlist[] = {
+	{ -ENOSR,	"Buffer error (overrun)" },
+	{ -EPIPE,	"Stalled (device not responding)" },
+	{ -EOVERFLOW,	"Babble (bad cable?)" },
+	{ -EPROTO,	"Bit-stuff error (bad cable?)" },
+	{ -EILSEQ,	"CRC/Timeout" },
+	{ -ETIMEDOUT,	"NAK (device does not respond)" },
+	{ -1, NULL }
+};
+
+/**********************************************************************
+ * Prototypes
+ **********************************************************************/
+
+static void ov51x_clear_snapshot(struct usb_ov511 *);
+static int ov51x_check_snapshot(struct usb_ov511 *);
+static inline int sensor_get_picture(struct usb_ov511 *, 
+				     struct video_picture *);
+static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
+static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
+			       unsigned long);
+
+/**********************************************************************
+ *
+ * Memory management
+ *
+ **********************************************************************/
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long 
+kvirt_to_pa(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+	return ret;
+}
+
+static void *
+rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		mem_map_reserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+static void 
+rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+
+/**********************************************************************
+ * /proc interface
+ * Based on the CPiA driver version 0.7.4 -claudio
+ **********************************************************************/
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+static struct proc_dir_entry *ov511_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
+
+static struct file_operations ov511_control_fops = {
+	ioctl:		ov51x_control_ioctl,
+};
+
+#define YES_NO(x) ((x) ? "yes" : "no")
+
+/* /proc/video/ov511/<minor#>/info */
+static int 
+ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
+		     void *data)
+{
+	char *out = page;
+	int i, len;
+	struct usb_ov511 *ov = data;
+	struct video_picture p;
+	unsigned char exp;
+
+	if (!ov || !ov->dev)
+		return -ENODEV;
+
+	sensor_get_picture(ov, &p);
+	sensor_get_exposure(ov, &exp);
+
+	/* IMPORTANT: This output MUST be kept under PAGE_SIZE
+	 *            or we need to get more sophisticated. */
+
+	out += sprintf(out, "driver_version  : %s\n", DRIVER_VERSION);
+	out += sprintf(out, "custom_id       : %d\n", ov->customid);
+	out += sprintf(out, "model           : %s\n", ov->desc);
+	out += sprintf(out, "streaming       : %s\n", YES_NO(ov->streaming));
+	out += sprintf(out, "grabbing        : %s\n", YES_NO(ov->grabbing));
+	out += sprintf(out, "compress        : %s\n", YES_NO(ov->compress));
+	out += sprintf(out, "subcapture      : %s\n", YES_NO(ov->sub_flag));
+	out += sprintf(out, "sub_size        : %d %d %d %d\n",
+		       ov->subx, ov->suby, ov->subw, ov->subh);
+	out += sprintf(out, "data_format     : %s\n",
+		       force_rgb ? "RGB" : "BGR");
+	out += sprintf(out, "brightness      : %d\n", p.brightness >> 8);
+	out += sprintf(out, "colour          : %d\n", p.colour >> 8);
+	out += sprintf(out, "contrast        : %d\n", p.contrast >> 8);
+	out += sprintf(out, "hue             : %d\n", p.hue >> 8);
+	out += sprintf(out, "exposure        : %d\n", exp);
+	out += sprintf(out, "num_frames      : %d\n", OV511_NUMFRAMES);
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		out += sprintf(out, "frame           : %d\n", i);
+		out += sprintf(out, "  depth         : %d\n",
+			       ov->frame[i].depth);
+		out += sprintf(out, "  size          : %d %d\n",
+			       ov->frame[i].width, ov->frame[i].height);
+		out += sprintf(out, "  format        : %s\n",
+			       symbolic(v4l1_plist, ov->frame[i].format));
+		out += sprintf(out, "  data_buffer   : 0x%p\n",
+			       ov->frame[i].data);
+	}
+	out += sprintf(out, "snap_enabled    : %s\n", YES_NO(ov->snap_enabled));
+	out += sprintf(out, "bridge          : %s\n",
+		       symbolic(brglist, ov->bridge));
+	out += sprintf(out, "sensor          : %s\n",
+		       symbolic(senlist, ov->sensor));
+	out += sprintf(out, "packet_size     : %d\n", ov->packet_size);
+	out += sprintf(out, "framebuffer     : 0x%p\n", ov->fbuf);
+
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else
+		len = count;
+
+	*start = page + off;
+
+	return len;
+}
+
+/* /proc/video/ov511/<minor#>/button
+ *
+ * When the camera's button is pressed, the output of this will change from a
+ * 0 to a 1 (ASCII). It will retain this value until it is read, after which
+ * it will reset to zero.
+ * 
+ * SECURITY NOTE: Since reading this file can change the state of the snapshot
+ * status, it is important for applications that open it to keep it locked
+ * against access by other processes, using flock() or a similar mechanism. No
+ * locking is provided by this driver.
+ */
+static int 
+ov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,
+		       void *data)
+{
+	char *out = page;
+	int len, status;
+	struct usb_ov511 *ov = data;
+
+	if (!ov || !ov->dev)
+		return -ENODEV;
+
+	status = ov51x_check_snapshot(ov);
+	out += sprintf(out, "%d", status);
+
+	if (status)
+		ov51x_clear_snapshot(ov);
+
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else {
+		len = count;
+	}
+
+	*start = page + off;
+
+	return len;
+}
+
+static void 
+create_proc_ov511_cam(struct usb_ov511 *ov)
+{
+	char dirname[10];
+
+	if (!ov511_proc_entry || !ov)
+		return;
+
+	/* Create per-device directory */
+	snprintf(dirname, 10, "%d", ov->vdev.minor);
+	PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);
+	ov->proc_devdir = create_proc_entry(dirname, S_IFDIR, ov511_proc_entry);
+	if (!ov->proc_devdir)
+		return;
+	ov->proc_devdir->owner = THIS_MODULE;
+
+	/* Create "info" entry (human readable device information) */
+	PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);
+	ov->proc_info = create_proc_read_entry("info", S_IFREG|S_IRUGO|S_IWUSR,
+		ov->proc_devdir, ov511_read_proc_info, ov);
+	if (!ov->proc_info)
+		return;
+	ov->proc_info->owner = THIS_MODULE;
+
+	/* Don't create it if old snapshot mode on (would cause race cond.) */
+	if (!snapshot) {
+		/* Create "button" entry (snapshot button status) */
+		PDEBUG(4, "creating /proc/video/ov511/%s/button", dirname);
+		ov->proc_button = create_proc_read_entry("button",
+			S_IFREG|S_IRUGO|S_IWUSR, ov->proc_devdir,
+			ov511_read_proc_button, ov);
+		if (!ov->proc_button)
+			return;
+	}
+	ov->proc_button->owner = THIS_MODULE;
+
+	/* Create "control" entry (ioctl() interface) */
+	PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);
+	lock_kernel();
+	ov->proc_control = create_proc_entry("control",	S_IFREG|S_IRUGO|S_IWUSR,
+		ov->proc_devdir);
+	if (!ov->proc_control) {
+		unlock_kernel();
+		return;
+	}
+	ov->proc_control->owner = THIS_MODULE;
+	ov->proc_control->data = ov;
+	ov->proc_control->proc_fops = &ov511_control_fops;
+	unlock_kernel();
+}
+
+static void 
+destroy_proc_ov511_cam(struct usb_ov511 *ov)
+{
+	char dirname[10];
+	
+	if (!ov || !ov->proc_devdir)
+		return;
+
+	snprintf(dirname, 10, "%d", ov->vdev.minor);
+
+	/* Destroy "control" entry */
+	if (ov->proc_control) {
+		PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);
+		remove_proc_entry("control", ov->proc_devdir);
+		ov->proc_control = NULL;
+	}
+
+	/* Destroy "button" entry */
+	if (ov->proc_button) {
+		PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);
+		remove_proc_entry("button", ov->proc_devdir);
+		ov->proc_button = NULL;
+	}
+
+	/* Destroy "info" entry */
+	if (ov->proc_info) {
+		PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);
+		remove_proc_entry("info", ov->proc_devdir);
+		ov->proc_info = NULL;
+	}
+
+	/* Destroy per-device directory */
+	PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);
+	remove_proc_entry(dirname, ov511_proc_entry);
+	ov->proc_devdir = NULL;
+}
+
+static void 
+proc_ov511_create(void)
+{
+	/* No current standard here. Alan prefers /proc/video/ as it keeps
+	 * /proc "less cluttered than /proc/randomcardifoundintheshed/"
+	 * -claudio
+	 */
+	if (video_proc_entry == NULL) {
+		err("Error: /proc/video/ does not exist");
+		return;
+	}
+
+	ov511_proc_entry = create_proc_entry("ov511", S_IFDIR,
+					     video_proc_entry);
+
+	if (ov511_proc_entry)
+		ov511_proc_entry->owner = THIS_MODULE;
+	else
+		err("Unable to create /proc/video/ov511");
+}
+
+static void 
+proc_ov511_destroy(void)
+{
+	PDEBUG(3, "removing /proc/video/ov511");
+
+	if (ov511_proc_entry == NULL)
+		return;
+
+	remove_proc_entry("ov511", video_proc_entry);
+}
+#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+/**********************************************************************
+ *
+ * Register I/O
+ *
+ **********************************************************************/
+
+/* Write an OV51x register */
+static int 
+reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
+{
+	int rc;
+
+	PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+	down(&ov->cbuf_lock);
+	ov->cbuf[0] = value;
+	rc = usb_control_msg(ov->dev,
+			     usb_sndctrlpipe(ov->dev, 0),
+			     2 /* REG_IO */,
+			     USB_TYPE_CLASS | USB_RECIP_DEVICE,
+			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);	
+	up(&ov->cbuf_lock);
+
+	if (rc < 0)
+		err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));
+
+	return rc;
+}
+
+/* Read from an OV51x register */
+/* returns: negative is error, pos or zero is data */
+static int 
+reg_r(struct usb_ov511 *ov, unsigned char reg)
+{
+	int rc;
+
+	down(&ov->cbuf_lock);
+	rc = usb_control_msg(ov->dev,
+			     usb_rcvctrlpipe(ov->dev, 0),
+			     2 /* REG_IO */,
+			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
+			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);
+                               
+	PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
+	
+	if (rc < 0)
+		err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));
+	else
+		rc = ov->cbuf[0];	
+
+	up(&ov->cbuf_lock);
+
+	return rc;
+}
+
+/*
+ * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless 
+ * of their respective state in "value".
+ */
+static int 
+reg_w_mask(struct usb_ov511 *ov,
+	   unsigned char reg,
+	   unsigned char value,
+	   unsigned char mask)
+{
+	int ret;
+	unsigned char oldval, newval;
+
+	ret = reg_r(ov, reg);
+	if (ret < 0)
+		return ret;
+
+	oldval = (unsigned char) ret;
+	oldval &= (~mask);		/* Clear the masked bits */
+	value &= mask;			/* Enforce mask on value */
+	newval = oldval | value;	/* Set the desired bits */
+
+	return (reg_w(ov, reg, newval));
+}
+
+/* 
+ * Writes multiple (n) byte value to a single register. Only valid with certain
+ * registers (0x30 and 0xc4 - 0xce).
+ */
+static int 
+ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
+{
+	int rc;
+
+	PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);
+
+	down(&ov->cbuf_lock);
+
+	*((u32 *)ov->cbuf) = __cpu_to_le32(val);
+
+	rc = usb_control_msg(ov->dev,
+			     usb_sndctrlpipe(ov->dev, 0),
+			     2 /* REG_IO */,
+			     USB_TYPE_CLASS | USB_RECIP_DEVICE,
+			     0, (__u16)reg, ov->cbuf, n, HZ);
+	up(&ov->cbuf_lock);
+
+	if (rc < 0)
+		err("reg write multiple: error %d: %s", rc,
+		    symbolic(urb_errlist, rc));
+
+	return rc;
+}
+
+static int 
+ov511_upload_quan_tables(struct usb_ov511 *ov)
+{
+	unsigned char *pYTable = yQuanTable511;
+	unsigned char *pUVTable = uvQuanTable511;
+	unsigned char val0, val1;
+	int i, rc, reg = R511_COMP_LUT_BEGIN;
+
+	PDEBUG(4, "Uploading quantization tables");
+
+	for (i = 0; i < OV511_QUANTABLESIZE / 2; i++)
+	{
+		if (ENABLE_Y_QUANTABLE)
+		{
+			val0 = *pYTable++;
+			val1 = *pYTable++;
+			val0 &= 0x0f;
+			val1 &= 0x0f;
+			val0 |= val1 << 4;
+			rc = reg_w(ov, reg, val0);
+			if (rc < 0)
+				return rc;
+		}
+
+		if (ENABLE_UV_QUANTABLE)
+		{
+			val0 = *pUVTable++;
+			val1 = *pUVTable++;
+			val0 &= 0x0f;
+			val1 &= 0x0f;
+			val0 |= val1 << 4;
+			rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0);
+			if (rc < 0)
+				return rc;
+		}
+
+		reg++;
+	}
+
+	return 0;
+}
+
+/* OV518 quantization tables are 8x4 (instead of 8x8) */
+static int 
+ov518_upload_quan_tables(struct usb_ov511 *ov)
+{
+	unsigned char *pYTable = yQuanTable518;
+	unsigned char *pUVTable = uvQuanTable518;
+	unsigned char val0, val1;
+	int i, rc, reg = R511_COMP_LUT_BEGIN;
+
+	PDEBUG(4, "Uploading quantization tables");
+
+	for (i = 0; i < OV518_QUANTABLESIZE / 2; i++)
+	{
+		if (ENABLE_Y_QUANTABLE)
+		{
+			val0 = *pYTable++;
+			val1 = *pYTable++;
+			val0 &= 0x0f;
+			val1 &= 0x0f;
+			val0 |= val1 << 4;
+			rc = reg_w(ov, reg, val0);
+			if (rc < 0)
+				return rc;
+		}
+
+		if (ENABLE_UV_QUANTABLE)
+		{
+			val0 = *pUVTable++;
+			val1 = *pUVTable++;
+			val0 &= 0x0f;
+			val1 &= 0x0f;
+			val0 |= val1 << 4;
+			rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0);
+			if (rc < 0)
+				return rc;
+		}
+
+		reg++;
+	}
+
+	return 0;
+}
+
+static int 
+ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type)
+{
+	int rc;
+		
+	/* Setting bit 0 not allowed on 518/518Plus */
+	if (ov->bclass == BCL_OV518)
+		reset_type &= 0xfe;
+
+	PDEBUG(4, "Reset: type=0x%X", reset_type);
+
+	rc = reg_w(ov, R51x_SYS_RESET, reset_type);
+	rc = reg_w(ov, R51x_SYS_RESET, 0);
+
+	if (rc < 0)
+		err("reset: command failed");
+
+	return rc;
+}
+
+/**********************************************************************
+ *
+ * I2C (sensor) I/O
+ *
+ **********************************************************************/
+
+/* NOTE: Do not call this function directly!
+ * The OV518 I2C I/O procedure is different, hence, this function.
+ * This is normally only called from i2c_w(). Note that this function
+ * always succeeds regardless of whether the sensor is present and working.
+ */
+static int 
+ov518_i2c_write_internal(struct usb_ov511 *ov,
+			 unsigned char reg,
+			 unsigned char value)
+{
+	int rc;
+
+	PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+	/* Select camera register */
+	rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
+	if (rc < 0) return rc;
+
+	/* Write "value" to I2C data port of OV511 */
+	rc = reg_w(ov, R51x_I2C_DATA, value);
+	if (rc < 0) return rc;
+
+	/* Initiate 3-byte write cycle */
+	rc = reg_w(ov, R518_I2C_CTL, 0x01);
+	if (rc < 0) return rc;
+
+	return 0;
+}
+
+/* NOTE: Do not call this function directly! */
+static int 
+ov511_i2c_write_internal(struct usb_ov511 *ov,
+			 unsigned char reg,
+			 unsigned char value)
+{
+	int rc, retries;
+
+	PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+	/* Three byte write cycle */
+	for (retries = OV511_I2C_RETRIES; ; ) {
+		/* Select camera register */
+		rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
+		if (rc < 0) return rc;
+
+		/* Write "value" to I2C data port of OV511 */
+		rc = reg_w(ov, R51x_I2C_DATA, value);	
+		if (rc < 0) return rc;
+
+		/* Initiate 3-byte write cycle */
+		rc = reg_w(ov, R511_I2C_CTL, 0x01);
+		if (rc < 0) return rc;
+
+		do rc = reg_r(ov, R511_I2C_CTL);
+		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+		if (rc < 0) return rc;
+
+		if ((rc&2) == 0) /* Ack? */
+			break;
+#if 0
+		/* I2C abort */	
+		reg_w(ov, R511_I2C_CTL, 0x10);
+#endif
+		if (--retries < 0) {
+			err("i2c write retries exhausted");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/* NOTE: Do not call this function directly!
+ * The OV518 I2C I/O procedure is different, hence, this function.
+ * This is normally only called from i2c_r(). Note that this function
+ * always succeeds regardless of whether the sensor is present and working.
+ */
+static int 
+ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
+{
+	int rc, value;
+
+	/* Select camera register */
+	rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
+	if (rc < 0) return rc;
+
+	/* Initiate 2-byte write cycle */
+	rc = reg_w(ov, R518_I2C_CTL, 0x03);
+	if (rc < 0) return rc;
+
+	/* Initiate 2-byte read cycle */
+	rc = reg_w(ov, R518_I2C_CTL, 0x05);
+	if (rc < 0) return rc;
+
+	value = reg_r(ov, R51x_I2C_DATA);
+
+	PDEBUG(5, "0x%02X:0x%02X", reg, value);
+
+	return value;
+}
+
+/* NOTE: Do not call this function directly!
+ * returns: negative is error, pos or zero is data */
+static int 
+ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
+{
+	int rc, value, retries;
+
+	/* Two byte write cycle */
+	for (retries = OV511_I2C_RETRIES; ; ) {
+		/* Select camera register */
+		rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
+		if (rc < 0) return rc;
+
+		/* Initiate 2-byte write cycle */
+		rc = reg_w(ov, R511_I2C_CTL, 0x03);
+		if (rc < 0) return rc;
+
+		do rc = reg_r(ov, R511_I2C_CTL);
+		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+		if (rc < 0) return rc;
+
+		if ((rc&2) == 0) /* Ack? */
+			break;
+
+		/* I2C abort */	
+		reg_w(ov, R511_I2C_CTL, 0x10);
+
+		if (--retries < 0) {
+			err("i2c write retries exhausted");
+			return -1;
+		}
+	}
+
+	/* Two byte read cycle */
+	for (retries = OV511_I2C_RETRIES; ; ) {
+		/* Initiate 2-byte read cycle */
+		rc = reg_w(ov, R511_I2C_CTL, 0x05);
+		if (rc < 0) return rc;
+
+		do rc = reg_r(ov, R511_I2C_CTL);
+		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+		if (rc < 0) return rc;
+
+		if ((rc&2) == 0) /* Ack? */
+			break;
+
+		/* I2C abort */	
+		rc = reg_w(ov, R511_I2C_CTL, 0x10);
+		if (rc < 0) return rc;
+
+		if (--retries < 0) {
+			err("i2c read retries exhausted");
+			return -1;
+		}
+	}
+
+	value = reg_r(ov, R51x_I2C_DATA);
+
+	PDEBUG(5, "0x%02X:0x%02X", reg, value);
+		
+	/* This is needed to make i2c_w() work */
+	rc = reg_w(ov, R511_I2C_CTL, 0x05);
+	if (rc < 0)
+		return rc;
+	
+	return value;
+}
+
+/* returns: negative is error, pos or zero is data */
+static int 
+i2c_r(struct usb_ov511 *ov, unsigned char reg)
+{
+	int rc;
+
+	down(&ov->i2c_lock);
+
+	if (ov->bclass == BCL_OV518)
+		rc = ov518_i2c_read_internal(ov, reg);
+	else
+		rc = ov511_i2c_read_internal(ov, reg);
+
+	up(&ov->i2c_lock);
+
+	return rc;
+}
+
+static int 
+i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
+{
+	int rc;
+
+	down(&ov->i2c_lock);
+
+	if (ov->bclass == BCL_OV518)
+		rc = ov518_i2c_write_internal(ov, reg, value);
+	else
+		rc = ov511_i2c_write_internal(ov, reg, value);
+
+	up(&ov->i2c_lock);
+
+	return rc;
+}
+
+/* Do not call this function directly! */
+static int 
+ov51x_i2c_write_mask_internal(struct usb_ov511 *ov,
+			      unsigned char reg,
+			      unsigned char value,
+			      unsigned char mask)
+{
+	int rc;
+	unsigned char oldval, newval;
+
+	if (mask == 0xff) {
+		newval = value;
+	} else {
+		if (ov->bclass == BCL_OV518)
+			rc = ov518_i2c_read_internal(ov, reg);
+		else
+			rc = ov511_i2c_read_internal(ov, reg);
+		if (rc < 0)
+			return rc;
+
+		oldval = (unsigned char) rc;
+		oldval &= (~mask);		/* Clear the masked bits */
+		value &= mask;			/* Enforce mask on value */
+		newval = oldval | value;	/* Set the desired bits */
+	}
+
+	if (ov->bclass == BCL_OV518)
+		return (ov518_i2c_write_internal(ov, reg, newval));
+	else
+		return (ov511_i2c_write_internal(ov, reg, newval));
+}
+
+/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless 
+ * of their respective state in "value".
+ */
+static int 
+i2c_w_mask(struct usb_ov511 *ov,
+	   unsigned char reg,
+	   unsigned char value,
+	   unsigned char mask)
+{
+	int rc;
+
+	down(&ov->i2c_lock);
+	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
+	up(&ov->i2c_lock);
+
+	return rc;
+}
+
+/* Write to a specific I2C slave ID and register, using the specified mask */
+static int 
+i2c_w_slave(struct usb_ov511 *ov,
+	    unsigned char slave,
+	    unsigned char reg,
+	    unsigned char value,
+	    unsigned char mask)
+{
+	int rc = 0;
+
+	down(&ov->i2c_lock);
+
+	/* Set new slave IDs */
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
+	/* Don't bail out yet if error; IDs must be restored */
+
+	/* Restore primary IDs */
+	slave = ov->primary_i2c_slave;
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+out:
+	up(&ov->i2c_lock);
+	return rc;
+}
+
+/* Read from a specific I2C slave ID and register */
+static int 
+i2c_r_slave(struct usb_ov511 *ov,
+	    unsigned char slave,
+	    unsigned char reg)
+{
+	int rc;
+
+	down(&ov->i2c_lock);
+
+	/* Set new slave IDs */
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+	if (ov->bclass == BCL_OV518)
+		rc = ov518_i2c_read_internal(ov, reg);
+	else
+		rc = ov511_i2c_read_internal(ov, reg);
+	/* Don't bail out yet if error; IDs must be restored */
+
+	/* Restore primary IDs */
+	slave = ov->primary_i2c_slave;
+	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
+		rc = -EIO;
+		goto out;
+	}
+
+out:
+	up(&ov->i2c_lock);
+	return rc;
+}
+
+/* Sets I2C read and write slave IDs. Returns <0 for error */
+static int 
+ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid)
+{
+	down(&ov->i2c_lock);
+
+	if (reg_w(ov, R51x_I2C_W_SID, sid) < 0)
+		return -EIO;
+
+	if (reg_w(ov, R51x_I2C_R_SID, sid + 1) < 0)
+		return -EIO;
+
+	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
+		return -EIO;
+
+	up(&ov->i2c_lock);
+
+	return 0;
+}
+
+static int 
+write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals)
+{
+	int rc;
+
+	while (pRegvals->bus != OV511_DONE_BUS) {
+		if (pRegvals->bus == OV511_REG_BUS) {
+			if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0)
+				return rc;
+		} else if (pRegvals->bus == OV511_I2C_BUS) {
+			if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)
+				return rc;
+		} else {
+			err("Bad regval array");
+			return -1;
+		}
+		pRegvals++;
+	}
+	return 0;
+}
+
+#ifdef OV511_DEBUG 
+static void 
+dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
+{
+	int i;
+	int rc;
+
+	for (i = reg1; i <= regn; i++) {
+		rc = i2c_r(ov, i);
+		info("OV7610[0x%X] = 0x%X", i, rc);
+	}
+}
+
+static void 
+dump_i2c_regs(struct usb_ov511 *ov)
+{
+	info("I2C REGS");
+	dump_i2c_range(ov, 0x00, 0x7C);
+}
+
+static void 
+dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
+{
+	int i;
+	int rc;
+
+	for (i = reg1; i <= regn; i++) {
+		rc = reg_r(ov, i);
+		info("OV511[0x%X] = 0x%X", i, rc);
+	}
+}
+
+/* FIXME: Should there be an OV518 version of this? */
+static void 
+ov511_dump_regs(struct usb_ov511 *ov)
+{
+	info("CAMERA INTERFACE REGS");
+	dump_reg_range(ov, 0x10, 0x1f);
+	info("DRAM INTERFACE REGS");
+	dump_reg_range(ov, 0x20, 0x23);
+	info("ISO FIFO REGS");
+	dump_reg_range(ov, 0x30, 0x31);
+	info("PIO REGS");
+	dump_reg_range(ov, 0x38, 0x39);
+	dump_reg_range(ov, 0x3e, 0x3e);
+	info("I2C REGS");
+	dump_reg_range(ov, 0x40, 0x49);
+	info("SYSTEM CONTROL REGS");
+	dump_reg_range(ov, 0x50, 0x55);
+	dump_reg_range(ov, 0x5e, 0x5f);
+	info("OmniCE REGS");
+	dump_reg_range(ov, 0x70, 0x79);
+	/* NOTE: Quantization tables are not readable. You will get the value
+	 * in reg. 0x79 for every table register */
+	dump_reg_range(ov, 0x80, 0x9f);
+	dump_reg_range(ov, 0xa0, 0xbf);
+
+}
+#endif
+
+/**********************************************************************
+ *
+ * Kernel I2C Interface
+ *
+ **********************************************************************/
+
+/* For as-yet unimplemented I2C interface */
+static void 
+call_i2c_clients(struct usb_ov511 *ov, unsigned int cmd,
+		 void *arg)
+{
+	/* Do nothing */
+}
+
+/*****************************************************************************/
+
+/* Temporarily stops OV511 from functioning. Must do this before changing
+ * registers while the camera is streaming */
+static inline int 
+ov51x_stop(struct usb_ov511 *ov)
+{
+	PDEBUG(4, "stopping");
+	ov->stopped = 1;	
+	if (ov->bclass == BCL_OV518)
+		return (reg_w(ov, R51x_SYS_RESET, 0x3a));
+	else
+		return (reg_w(ov, R51x_SYS_RESET, 0x3d));
+}
+
+/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
+ * actually stopped (for performance). */
+static inline int 
+ov51x_restart(struct usb_ov511 *ov)
+{
+	if (ov->stopped) {
+		PDEBUG(4, "restarting");
+		ov->stopped = 0;	
+
+		/* Reinitialize the stream */
+		if (ov->bclass == BCL_OV518)
+			reg_w(ov, 0x2f, 0x80);
+
+		return (reg_w(ov, R51x_SYS_RESET, 0x00));
+	}
+
+	return 0;
+}
+
+/* Resets the hardware snapshot button */
+static void 
+ov51x_clear_snapshot(struct usb_ov511 *ov)
+{
+	if (ov->bclass == BCL_OV511) {
+		reg_w(ov, R51x_SYS_SNAP, 0x01);
+		reg_w(ov, R51x_SYS_SNAP, 0x03);
+		reg_w(ov, R51x_SYS_SNAP, 0x01);
+	} else if (ov->bclass == BCL_OV518) {
+		warn("snapshot reset not supported yet on OV518(+)");
+	} else {
+		err("clear snap: invalid bridge type");
+	}
+	
+}
+
+/* Checks the status of the snapshot button. Returns 1 if it was pressed since
+ * it was last cleared, and zero in all other cases (including errors) */
+static int 
+ov51x_check_snapshot(struct usb_ov511 *ov)
+{
+	int ret, status = 0;
+
+	if (ov->bclass == BCL_OV511) {
+		ret = reg_r(ov, R51x_SYS_SNAP);
+		if (ret < 0) {
+			err("Error checking snspshot status (%d)", ret);
+		} else if (ret & 0x08) {
+			status = 1;
+		}
+	} else if (ov->bclass == BCL_OV518) {
+		warn("snapshot check not supported yet on OV518(+)");
+	} else {
+		err("check snap: invalid bridge type");
+	}
+
+	return status;
+}
+
+/* This does an initial reset of an OmniVision sensor and ensures that I2C
+ * is synchronized. Returns <0 for failure.
+ */
+static int 
+init_ov_sensor(struct usb_ov511 *ov)
+{
+	int i, success;
+
+	/* Reset the sensor */ 
+	if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
+
+	/* Wait for it to initialize */ 
+	schedule_timeout (1 + 150 * HZ / 1000);
+
+	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
+		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
+		    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
+			success = 1;
+			continue;
+		}
+
+		/* Reset the sensor */ 
+		if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
+		/* Wait for it to initialize */ 
+		schedule_timeout(1 + 150 * HZ / 1000);
+		/* Dummy read to sync I2C */
+		if (i2c_r(ov, 0x00) < 0) return -EIO;
+	}
+
+	if (!success)
+		return -EIO;
+	
+	PDEBUG(1, "I2C synced in %d attempt(s)", i);
+
+	return 0;
+}
+
+static int 
+ov51x_set_packet_size(struct usb_ov511 *ov, int size)
+{
+	int alt, mult;
+
+	if (ov51x_stop(ov) < 0)
+		return -EIO;
+
+	mult = size >> 5;
+
+	if (ov->bridge == BRG_OV511) {
+		if (size == 0) alt = OV511_ALT_SIZE_0;
+		else if (size == 257) alt = OV511_ALT_SIZE_257;
+		else if (size == 513) alt = OV511_ALT_SIZE_513;
+		else if (size == 769) alt = OV511_ALT_SIZE_769;
+		else if (size == 993) alt = OV511_ALT_SIZE_993;
+		else {
+			err("Set packet size: invalid size (%d)", size);
+			return -EINVAL;
+		}
+	} else if (ov->bridge == BRG_OV511PLUS) {
+		if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
+		else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
+		else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
+		else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;
+		else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;
+		else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;
+		else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;
+		else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;
+		else {
+			err("Set packet size: invalid size (%d)", size);
+			return -EINVAL;
+		}
+	} else if (ov->bclass == BCL_OV518) {
+		if (size == 0) alt = OV518_ALT_SIZE_0;
+		else if (size == 128) alt = OV518_ALT_SIZE_128;
+		else if (size == 256) alt = OV518_ALT_SIZE_256;
+		else if (size == 384) alt = OV518_ALT_SIZE_384;
+		else if (size == 512) alt = OV518_ALT_SIZE_512;
+		else if (size == 640) alt = OV518_ALT_SIZE_640;
+		else if (size == 768) alt = OV518_ALT_SIZE_768;
+		else if (size == 896) alt = OV518_ALT_SIZE_896;
+		else {
+			err("Set packet size: invalid size (%d)", size);
+			return -EINVAL;
+		}
+	} else {
+		err("Set packet size: Invalid bridge type");
+		return -EINVAL;
+	}
+
+	PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
+
+	// FIXME: Don't know how to do this on OV518 yet
+	if (ov->bclass == BCL_OV511) {
+		if (reg_w(ov, R51x_FIFO_PSIZE,
+				    mult) < 0) {
+			return -EIO;
+		}
+	}
+	
+	if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
+		err("Set packet size: set interface error");
+		return -EBUSY;
+	}
+
+	/* Initialize the stream */
+	if (ov->bclass == BCL_OV518)
+		if (reg_w(ov, 0x2f, 0x80) < 0)
+			return -EIO;
+
+	// FIXME - Should we only reset the FIFO?
+	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
+		return -EIO;
+
+	ov->packet_size = size;
+
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+/* Upload compression params and quantization tables. Returns 0 for success. */
+static int
+ov511_init_compression(struct usb_ov511 *ov)
+{
+	int rc = 0;
+
+	if (!ov->compress_inited) {
+
+		reg_w(ov, 0x70, phy);
+		reg_w(ov, 0x71, phuv);
+		reg_w(ov, 0x72, pvy);
+		reg_w(ov, 0x73, pvuv);
+		reg_w(ov, 0x74, qhy);
+		reg_w(ov, 0x75, qhuv);
+		reg_w(ov, 0x76, qvy);
+		reg_w(ov, 0x77, qvuv);
+
+		if (ov511_upload_quan_tables(ov) < 0) {
+			err("Error uploading quantization tables");
+			rc = -EIO;
+			goto out;
+		}
+	}
+
+	ov->compress_inited = 1;
+out:	
+	return rc;
+}
+
+/* Upload compression params and quantization tables. Returns 0 for success. */
+static int
+ov518_init_compression(struct usb_ov511 *ov)
+{
+	int rc = 0;
+
+	if (!ov->compress_inited) {
+
+		if (ov518_upload_quan_tables(ov) < 0) {
+			err("Error uploading quantization tables");
+			rc = -EIO;
+			goto out;
+		}
+	}
+
+	ov->compress_inited = 1;
+out:	
+	return rc;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's contrast setting to "val" */
+static int
+sensor_set_contrast(struct usb_ov511 *ov, unsigned short val)
+{
+	int rc;
+
+	PDEBUG(3, "%d", val);
+
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
+			return -EIO;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV6620:
+	case SEN_OV6630:
+	{
+		rc = i2c_w(ov, OV7610_REG_CNT, val >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	}
+	case SEN_OV7620:
+	{
+		unsigned char ctab[] = {
+			0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
+			0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
+		};
+
+		/* Use Y gamma control instead. Bit 0 enables it. */
+		rc = i2c_w(ov, 0x64, ctab[val>>12]);
+		if (rc < 0)
+			goto out;
+		break;
+	}
+	case SEN_SAA7111A:
+	{
+		rc = i2c_w(ov, 0x0b, val >> 9);
+		if (rc < 0)
+			goto out;
+		break;
+	}
+	default:
+	{
+		PDEBUG(3, "Unsupported with this sensor");
+		rc = -EPERM;
+		goto out;
+	}
+	}
+
+	rc = 0;		/* Success */
+	ov->contrast = val;
+out:
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return rc;
+}
+
+/* Gets sensor's contrast setting */
+static int
+sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val)
+{
+	int rc;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_r(ov, OV7610_REG_CNT);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc << 8;
+		break;
+	case SEN_OV7620:
+		/* Use Y gamma reg instead. Bit 0 is the enable bit. */
+		rc = i2c_r(ov, 0x64);
+		if (rc < 0)
+			return rc;
+		else
+			*val = (rc & 0xfe) << 8;
+		break;
+	case SEN_SAA7111A:
+		*val = ov->contrast;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		return -EPERM;
+	}
+
+	PDEBUG(3, "%d", *val);
+	ov->contrast = *val;
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's brightness setting to "val" */
+static int
+sensor_set_brightness(struct usb_ov511 *ov, unsigned short val)
+{
+	int rc;
+
+	PDEBUG(4, "%d", val);
+
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
+			return -EIO;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	case SEN_OV7620:
+		/* 7620 doesn't like manual changes when in auto mode */
+		if (!ov->auto_brt) {
+			rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
+			if (rc < 0)
+				goto out;
+		}
+		break;
+	case SEN_SAA7111A:
+		rc = i2c_w(ov, 0x0a, val >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		rc = -EPERM;
+		goto out;
+	}
+
+	rc = 0;		/* Success */
+	ov->brightness = val;
+out:
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return rc;
+}
+
+/* Gets sensor's brightness setting */
+static int
+sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val)
+{
+	int rc;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+	case SEN_OV7620:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_r(ov, OV7610_REG_BRT);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc << 8;
+		break;
+	case SEN_SAA7111A:
+		*val = ov->brightness;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		return -EPERM;
+	}
+
+	PDEBUG(3, "%d", *val);
+	ov->brightness = *val;
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's saturation (color intensity) setting to "val" */
+static int
+sensor_set_saturation(struct usb_ov511 *ov, unsigned short val)
+{
+	int rc;
+
+	PDEBUG(3, "%d", val);
+
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
+			return -EIO;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	case SEN_OV7620:
+//		/* Use UV gamma control instead. Bits 0 & 7 are reserved. */
+//		rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e);
+//		if (rc < 0)
+//			goto out;
+		rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	case SEN_SAA7111A:
+		rc = i2c_w(ov, 0x0c, val >> 9);
+		if (rc < 0)
+			goto out;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		rc = -EPERM;
+		goto out;
+	}
+
+	rc = 0;		/* Success */
+	ov->colour = val;
+out:
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return rc;
+}
+
+/* Gets sensor's saturation (color intensity) setting */
+static int
+sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val)
+{
+	int rc;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_r(ov, OV7610_REG_SAT);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc << 8;
+		break;
+	case SEN_OV7620:
+//		/* Use UV gamma reg instead. Bits 0 & 7 are reserved. */
+//		rc = i2c_r(ov, 0x62);
+//		if (rc < 0)
+//			return rc;
+//		else
+//			*val = (rc & 0x7e) << 9;
+		rc = i2c_r(ov, OV7610_REG_SAT);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc << 8;
+		break;
+	case SEN_SAA7111A:
+		*val = ov->colour;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		return -EPERM;
+	}
+
+	PDEBUG(3, "%d", *val);
+	ov->colour = *val;
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Sets sensor's hue (red/blue balance) setting to "val" */
+static int
+sensor_set_hue(struct usb_ov511 *ov, unsigned short val)
+{
+	int rc;
+
+	PDEBUG(3, "%d", val);
+
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
+			return -EIO;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8));
+		if (rc < 0)
+			goto out;
+
+		rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	case SEN_OV7620:
+// Hue control is causing problems. I will enable it once it's fixed.
+#if 0
+		rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb);
+		if (rc < 0)
+			goto out;
+
+		rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb);
+		if (rc < 0)
+			goto out;
+#endif
+		break;
+	case SEN_SAA7111A:
+		rc = i2c_w(ov, 0x0d, (val + 32768) >> 8);
+		if (rc < 0)
+			goto out;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		rc = -EPERM;
+		goto out;
+	}
+
+	rc = 0;		/* Success */
+	ov->hue = val;
+out:
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return rc;
+}
+
+/* Gets sensor's hue (red/blue balance) setting */
+static int
+sensor_get_hue(struct usb_ov511 *ov, unsigned short *val)
+{
+	int rc;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = i2c_r(ov, OV7610_REG_BLUE);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc << 8;
+		break;
+	case SEN_OV7620:
+		rc = i2c_r(ov, 0x7a);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc << 8;
+		break;
+	case SEN_SAA7111A:
+		*val = ov->hue;
+		break;
+	default:
+		PDEBUG(3, "Unsupported with this sensor");
+		return -EPERM;
+	}
+
+	PDEBUG(3, "%d", *val);
+	ov->hue = *val;
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static inline int
+sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
+{
+	int rc;
+
+	PDEBUG(4, "sensor_set_picture");
+
+	ov->whiteness = p->whiteness;
+
+	/* Don't return error if a setting is unsupported, or rest of settings
+         * will not be performed */
+
+	rc = sensor_set_contrast(ov, p->contrast);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_set_brightness(ov, p->brightness);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_set_saturation(ov, p->colour);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_set_hue(ov, p->hue);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	return 0;
+}
+
+static inline int
+sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
+{
+	int rc;
+
+	PDEBUG(4, "sensor_get_picture");
+
+	/* Don't return error if a setting is unsupported, or rest of settings
+         * will not be performed */
+
+	rc = sensor_get_contrast(ov, &(p->contrast));
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_get_brightness(ov, &(p->brightness));
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_get_saturation(ov, &(p->colour));
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_get_hue(ov, &(p->hue));
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	p->whiteness = 105 << 8;
+
+	/* Can we get these from frame[0]? -claudio? */
+	p->depth = ov->frame[0].depth;
+	p->palette = ov->frame[0].format;
+
+	return 0;
+}
+
+// FIXME: Exposure range is only 0x00-0x7f in interlace mode
+/* Sets current exposure for sensor. This only has an effect if auto-exposure
+ * is off */
+static inline int
+sensor_set_exposure(struct usb_ov511 *ov, unsigned char val)
+{
+	int rc;
+
+	PDEBUG(3, "%d", val);
+
+	if (ov->stop_during_set)
+		if (ov51x_stop(ov) < 0)
+			return -EIO;
+
+	switch (ov->sensor) {
+	case SEN_OV6620:
+	case SEN_OV6630:
+	case SEN_OV7610:
+	case SEN_OV7620:
+	case SEN_OV7620AE:
+	case SEN_OV8600:
+		rc = i2c_w(ov, 0x10, val);
+		if (rc < 0)
+			goto out;
+
+		break;
+	case SEN_KS0127:
+	case SEN_KS0127B:
+	case SEN_SAA7111A:
+		PDEBUG(3, "Unsupported with this sensor");
+		return -EPERM;
+	default:
+		err("Sensor not supported for set_exposure");
+		return -EINVAL;
+	}
+
+	rc = 0;		/* Success */
+	ov->exposure = val;
+out:
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return rc;
+}
+
+/* Gets current exposure level from sensor, regardless of whether it is under
+ * manual control. */
+static int
+sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val)
+{
+	int rc;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV6620:
+	case SEN_OV6630:
+	case SEN_OV7620:
+	case SEN_OV7620AE:
+	case SEN_OV8600:
+		rc = i2c_r(ov, 0x10);
+		if (rc < 0)
+			return rc;
+		else
+			*val = rc;
+		break;
+	case SEN_KS0127:
+	case SEN_KS0127B:
+	case SEN_SAA7111A:
+		val = 0;
+		PDEBUG(3, "Unsupported with this sensor");
+		return -EPERM;
+	default:
+		err("Sensor not supported for get_exposure");
+		return -EINVAL;
+	}
+
+	PDEBUG(3, "%d", *val);
+	ov->exposure = *val;
+
+	return 0;
+}
+
+/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
+static inline void 
+ov51x_led_control(struct usb_ov511 *ov, int enable)
+{
+	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+	if (ov->bridge == BRG_OV511PLUS)
+		reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0);
+	else if (ov->bclass == BCL_OV518)
+		reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02);
+
+	return;
+}
+
+/* Matches the sensor's internal frame rate to the lighting frequency.
+ * Valid frequencies are:
+ *	50 - 50Hz, for European and Asian lighting
+ *	60 - 60Hz, for American lighting
+ *
+ * Tested with: OV7610, OV7620, OV7620AE, OV6620
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static int
+sensor_set_light_freq(struct usb_ov511 *ov, int freq)
+{
+	int sixty;
+
+	PDEBUG(4, "%d Hz", freq);
+
+	if (freq == 60)
+		sixty = 1;
+	else if (freq == 50)
+		sixty = 0;
+	else {
+		err("Invalid light freq (%d Hz)", freq);
+		return -EINVAL;
+	}
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+		i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
+		i2c_w(ov, 0x2b, sixty?0x00:0xac);
+		i2c_w_mask(ov, 0x13, 0x10, 0x10);
+		i2c_w_mask(ov, 0x13, 0x00, 0x10);
+		break;
+	case SEN_OV7620:
+	case SEN_OV7620AE:
+	case SEN_OV8600:
+		i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
+		i2c_w(ov, 0x2b, sixty?0x00:0xac);
+		i2c_w_mask(ov, 0x76, 0x01, 0x01);
+		break;		
+	case SEN_OV6620:
+	case SEN_OV6630:
+		i2c_w(ov, 0x2b, sixty?0xa8:0x28);
+		i2c_w(ov, 0x2a, sixty?0x84:0xa4);
+		break;
+	case SEN_KS0127:
+	case SEN_KS0127B:
+	case SEN_SAA7111A:
+		PDEBUG(5, "Unsupported with this sensor");
+		return -EPERM;
+	default:
+		err("Sensor not supported for set_light_freq");
+		return -EINVAL;
+	}
+
+	ov->lightfreq = freq;
+
+	return 0;
+}
+
+/* If enable is true, turn on the sensor's banding filter, otherwise turn it
+ * off. This filter tries to reduce the pattern of horizontal light/dark bands
+ * caused by some (usually fluorescent) lighting. The light frequency must be
+ * set either before or after enabling it with ov51x_set_light_freq().
+ *
+ * Tested with: OV7610, OV7620, OV7620AE, OV6620.
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static inline int
+sensor_set_banding_filter(struct usb_ov511 *ov, int enable)
+{
+	int rc;
+
+	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+	if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
+		|| ov->sensor == SEN_SAA7111A) {
+		PDEBUG(5, "Unsupported with this sensor");
+		return -EPERM;
+	}
+
+	rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04);
+	if (rc < 0)
+		return rc;
+
+	ov->bandfilt = enable;
+
+	return 0;
+}
+
+/* If enable is true, turn on the sensor's auto brightness control, otherwise
+ * turn it off.
+ *
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static inline int
+sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)
+{
+	int rc;
+
+	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+	if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
+		|| ov->sensor == SEN_SAA7111A) {
+		PDEBUG(5, "Unsupported with this sensor");
+		return -EPERM;
+	}
+
+	rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10);
+	if (rc < 0)
+		return rc;
+
+	ov->auto_brt = enable;
+
+	return 0;
+}
+
+/* If enable is true, turn on the sensor's auto exposure control, otherwise
+ * turn it off.
+ *
+ * Unsupported: KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static inline int
+sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)
+{	
+	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+		i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80);
+		break;
+	case SEN_OV6620:
+	case SEN_OV7620:
+	case SEN_OV7620AE:
+	case SEN_OV8600:
+		i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01);
+		break;		
+	case SEN_OV6630:
+		i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10);
+		break;
+	case SEN_KS0127:
+	case SEN_KS0127B:
+	case SEN_SAA7111A:
+		PDEBUG(5, "Unsupported with this sensor");
+		return -EPERM;
+	default:
+		err("Sensor not supported for set_auto_exposure");
+		return -EINVAL;
+	}
+
+	ov->auto_exp = enable;
+
+	return 0;
+}
+
+/* Modifies the sensor's exposure algorithm to allow proper exposure of objects
+ * that are illuminated from behind.
+ *
+ * Tested with: OV6620, OV7620
+ * Unsupported: OV7610, OV7620AE, KS0127, KS0127B, SAA7111A
+ * Returns: 0 for success
+ */
+static int
+sensor_set_backlight(struct usb_ov511 *ov, int enable)
+{
+
+	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
+
+	switch (ov->sensor) {
+	case SEN_OV7620:
+	case SEN_OV8600:
+		i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0);
+		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
+		i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
+		break;		
+	case SEN_OV6620:
+		i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0);
+		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
+		i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80);
+		break;
+	case SEN_OV6630:
+		i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0);
+		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
+		i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
+		break;
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+	case SEN_KS0127:
+	case SEN_KS0127B:
+	case SEN_SAA7111A:
+		PDEBUG(5, "Unsupported with this sensor");
+		return -EPERM;
+	default:
+		err("Sensor not supported for set_backlight");
+		return -EINVAL;
+	}
+
+	ov->backlight = enable;
+
+	return 0;
+}
+
+/* Returns number of bits per pixel (regardless of where they are located;
+ * planar or not), or zero for unsupported format.
+ */
+static inline int 
+get_depth(int palette)
+{
+	switch (palette) {
+	case VIDEO_PALETTE_GREY:    return 8;
+	case VIDEO_PALETTE_YUV420:  return 12;
+	case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
+	case VIDEO_PALETTE_RGB565:  return 16;
+	case VIDEO_PALETTE_RGB24:   return 24;  
+	case VIDEO_PALETTE_YUV422:  return 16;
+	case VIDEO_PALETTE_YUYV:    return 16;
+	case VIDEO_PALETTE_YUV422P: return 16; /* Planar */
+	default:		    return 0;  /* Invalid format */
+	}
+}
+
+/* Bytes per frame. Used by read(). Return of 0 indicates error */
+static inline long int 
+get_frame_length(struct ov511_frame *frame)
+{
+	if (!frame)
+		return 0;
+	else
+		return ((frame->width * frame->height
+			 * get_depth(frame->format)) >> 3);
+}
+
+static int
+mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
+			 int mode, int sub_flag, int qvga)
+{
+	int clock;
+
+	/******** Mode (VGA/QVGA) and sensor specific regs ********/
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+		i2c_w(ov, 0x14, qvga?0x24:0x04);
+// FIXME: Does this improve the image quality or frame rate?
+#if 0
+		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
+		i2c_w(ov, 0x24, 0x10);
+		i2c_w(ov, 0x25, qvga?0x40:0x8a);
+		i2c_w(ov, 0x2f, qvga?0x30:0xb0);
+		i2c_w(ov, 0x35, qvga?0x1c:0x9c);
+#endif
+		break;
+	case SEN_OV7620:
+//		i2c_w(ov, 0x2b, 0x00);
+		i2c_w(ov, 0x14, qvga?0xa4:0x84);
+		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
+		i2c_w(ov, 0x24, qvga?0x20:0x3a);
+		i2c_w(ov, 0x25, qvga?0x30:0x60);
+		i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
+		i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0);
+		i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
+		break;
+	case SEN_OV7620AE:
+//		i2c_w(ov, 0x2b, 0x00);
+		i2c_w(ov, 0x14, qvga?0xa4:0x84);
+// FIXME: Enable this once 7620AE uses 7620 initial settings
+#if 0
+		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
+		i2c_w(ov, 0x24, qvga?0x20:0x3a);
+		i2c_w(ov, 0x25, qvga?0x30:0x60);
+		i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
+		i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0);
+		i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
+#endif
+		break;
+	case SEN_OV6620:
+	case SEN_OV6630:
+		i2c_w(ov, 0x14, qvga?0x24:0x04);
+		/* No special settings yet */
+		break;
+	default:
+		err("Invalid sensor");
+		return -EINVAL;
+	}
+
+	/******** Palette-specific regs ********/
+
+	if (mode == VIDEO_PALETTE_GREY) {
+		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
+			/* these aren't valid on the OV6620/OV7620/6630? */
+			i2c_w_mask(ov, 0x0e, 0x40, 0x40);
+		}
+		i2c_w_mask(ov, 0x13, 0x20, 0x20);
+	} else {
+		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
+			/* not valid on the OV6620/OV7620/6630? */
+			i2c_w_mask(ov, 0x0e, 0x00, 0x40);
+		}
+		i2c_w_mask(ov, 0x13, 0x00, 0x20);
+	}
+
+	/******** Clock programming ********/
+
+	// FIXME: Test this with OV6630
+
+	/* The OV6620 needs special handling. This prevents the 
+	 * severe banding that normally occurs */
+	if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)
+	{
+		/* Clock down */
+
+		i2c_w(ov, 0x2a, 0x04);
+
+		if (ov->compress) {
+//			clock = 0;    /* This ensures the highest frame rate */
+			clock = 3;
+		} else if (clockdiv == -1) {   /* If user didn't override it */
+			clock = 3;    /* Gives better exposure time */
+		} else {
+			clock = clockdiv;
+		}
+
+		PDEBUG(4, "Setting clock divisor to %d", clock);
+
+		i2c_w(ov, 0x11, clock);
+
+		i2c_w(ov, 0x2a, 0x84);
+		/* This next setting is critical. It seems to improve
+		 * the gain or the contrast. The "reserved" bits seem
+		 * to have some effect in this case. */
+		i2c_w(ov, 0x2d, 0x85);
+	}
+	else
+	{
+		if (ov->compress) {
+			clock = 1;    /* This ensures the highest frame rate */
+		} else if (clockdiv == -1) {   /* If user didn't override it */
+			/* Calculate and set the clock divisor */
+			clock = ((sub_flag ? ov->subw * ov->subh
+				  : width * height)
+				 * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2)
+				 / 66000;
+		} else {
+			clock = clockdiv;
+		}
+
+		PDEBUG(4, "Setting clock divisor to %d", clock);
+
+		i2c_w(ov, 0x11, clock);
+	}
+
+	/******** Special Features ********/
+
+	if (framedrop >= 0)
+		i2c_w(ov, 0x16, framedrop);
+
+	/* We only have code to convert GBR -> RGB24 */
+	if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
+		i2c_w_mask(ov, 0x12, 0x08, 0x08);
+	else
+		i2c_w_mask(ov, 0x12, 0x00, 0x08);
+
+	/* Test Pattern */
+	i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02);
+
+	/* Auto white balance */
+//	if (awb)
+		i2c_w_mask(ov, 0x12, 0x04, 0x04);
+//	else
+//		i2c_w_mask(ov, 0x12, 0x00, 0x04);
+
+	// This will go away as soon as ov51x_mode_init_sensor_regs()
+	// is fully tested.
+	/* 7620/6620/6630? don't have register 0x35, so play it safe */
+	if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
+		if (width == 640 && height == 480)
+			i2c_w(ov, 0x35, 0x9e);
+		else
+			i2c_w(ov, 0x35, 0x1e);
+	}
+
+	return 0;
+}
+
+static int
+set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,
+		     int sub_flag)
+{
+	int ret;
+	int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; 
+	int hoffset, voffset, hwscale = 0, vwscale = 0;
+
+	/* The different sensor ICs handle setting up of window differently.
+	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+		hwsbase = 0x38;
+		hwebase = 0x3a;
+		vwsbase = vwebase = 0x05;
+		break;
+	case SEN_OV6620:
+	case SEN_OV6630:	// FIXME: Is this right?
+		hwsbase = 0x38;
+		hwebase = 0x3a;
+		vwsbase = 0x05;
+		vwebase = 0x06;
+		break;
+	case SEN_OV7620:
+		hwsbase = 0x2f;		/* From 7620.SET (spec is wrong) */
+		hwebase = 0x2f;
+		vwsbase = vwebase = 0x05;
+		break;
+	default:
+		err("Invalid sensor");
+		return -EINVAL;
+	}
+
+	if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) {
+		if (width > 176 && height > 144) {  /* CIF */
+			ret = mode_init_ov_sensor_regs(ov, width, height,
+				mode, sub_flag, 0);
+			if (ret < 0)
+				return ret;
+			hwscale = 1;
+			vwscale = 1;  /* The datasheet says 0; it's wrong */
+			hwsize = 352;
+			vwsize = 288;
+		} else if (width > 176 || height > 144) {
+			err("Illegal dimensions");
+			return -EINVAL;
+		} else {			    /* QCIF */
+			ret = mode_init_ov_sensor_regs(ov, width, height,
+				mode, sub_flag, 1);
+			if (ret < 0)
+				return ret;
+			hwsize = 176;
+			vwsize = 144;
+		}
+	} else {
+		if (width > 320 && height > 240) {  /* VGA */
+			ret = mode_init_ov_sensor_regs(ov, width, height,
+				mode, sub_flag, 0);
+			if (ret < 0)
+				return ret;
+			hwscale = 2;
+			vwscale = 1;
+			hwsize = 640;
+			vwsize = 480;
+		} else if (width > 320 || height > 240) {
+			err("Illegal dimensions");
+			return -EINVAL;
+		} else {			    /* QVGA */
+			ret = mode_init_ov_sensor_regs(ov, width, height,
+				mode, sub_flag, 1);
+			if (ret < 0)
+				return ret;
+			hwscale = 1;
+			hwsize = 320;
+			vwsize = 240;
+		}
+	}
+
+	/* Center the window */
+	hoffset = ((hwsize - width) / 2) >> hwscale;
+	voffset = ((vwsize - height) / 2) >> vwscale;
+
+	/* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
+	if (sub_flag) {
+		i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale));
+		i2c_w(ov, 0x18,	hwebase+((ov->subx+ov->subw)>>hwscale));
+		i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale));
+		i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale));
+	} else {
+		i2c_w(ov, 0x17, hwsbase + hoffset);
+		i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale));
+		i2c_w(ov, 0x19, vwsbase + voffset);
+		i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale));
+	}
+
+#ifdef OV511_DEBUG
+	if (dump_sensor)
+		dump_i2c_regs(ov);
+#endif
+
+	return 0;
+}
+
+/* Set up the OV511/OV511+ with the given image parameters.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int
+ov511_mode_init_regs(struct usb_ov511 *ov,
+		     int width, int height, int mode, int sub_flag)
+{
+	int lncnt, pxcnt, rc = 0;
+
+	if (sub_flag) {
+		width = ov->subw;
+		height = ov->subh;
+	}
+
+	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
+	       width, height, mode, sub_flag);
+
+	// FIXME: This should be moved to a 7111a-specific function once
+	// subcapture is dealt with properly
+	if (ov->sensor == SEN_SAA7111A) {
+		if (width == 320 && height == 240) {
+			/* No need to do anything special */
+		} else if (width == 640 && height == 480) {
+			/* Set the OV511 up as 320x480, but keep the V4L
+			 * resolution as 640x480 */
+			width = 320;
+		} else {
+			err("SAA7111A only supports 320x240 or 640x480");
+			return -EINVAL;
+		}
+	}
+
+	/* Make sure width and height are a multiple of 8 */
+	if (width % 8 || height % 8) {
+		err("Invalid size (%d, %d) (mode = %d)", width, height, mode);
+		return -EINVAL;
+	}
+
+	if (width < ov->minwidth || height < ov->minheight) {
+		err("Requested dimensions are too small");
+		return -EINVAL;
+	}
+
+	if (ov51x_stop(ov) < 0)
+		return -EIO;
+
+	if (mode == VIDEO_PALETTE_GREY) {
+		reg_w(ov, R511_CAM_UV_EN, 0x00);
+		reg_w(ov, R511_SNAP_UV_EN, 0x00);
+		reg_w(ov, R511_SNAP_OPTS, 0x01);
+	} else {
+		reg_w(ov, R511_CAM_UV_EN, 0x01);
+		reg_w(ov, R511_SNAP_UV_EN, 0x01);
+		reg_w(ov, R511_SNAP_OPTS, 0x03);
+	}
+
+	/* Here I'm assuming that snapshot size == image size.
+	 * I hope that's always true. --claudio
+	 */
+	pxcnt = (width >> 3) - 1;
+	lncnt = (height >> 3) - 1;
+
+	reg_w(ov, R511_CAM_PXCNT, pxcnt);
+	reg_w(ov, R511_CAM_LNCNT, lncnt);
+	reg_w(ov, R511_CAM_PXDIV, 0x00);
+	reg_w(ov, R511_CAM_LNDIV, 0x00);
+
+	/* YUV420, low pass filer on */
+	reg_w(ov, R511_CAM_OPTS, 0x03);
+
+	/* Snapshot additions */
+	reg_w(ov, R511_SNAP_PXCNT, pxcnt);
+	reg_w(ov, R511_SNAP_LNCNT, lncnt);
+	reg_w(ov, R511_SNAP_PXDIV, 0x00);
+	reg_w(ov, R511_SNAP_LNDIV, 0x00);
+
+	if (ov->compress) {
+		/* Enable Y and UV quantization and compression */
+		reg_w(ov, R511_COMP_EN, 0x07);
+		reg_w(ov, R511_COMP_LUT_EN, 0x03);
+		ov51x_reset(ov, OV511_RESET_OMNICE);
+	}
+//out:
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	return rc;
+}
+
+static struct mode_list_518 mlist518[] = {
+	/* W    H   reg28 reg29 reg2a reg2c reg2e reg24 reg25 */
+	{ 352, 288, 0x00, 0x16, 0x48, 0x00, 0x00, 0x9f, 0x90 },
+	{ 320, 240, 0x00, 0x14, 0x3c, 0x10, 0x18, 0x9f, 0x90 },
+	{ 176, 144, 0x05, 0x0b, 0x24, 0x00, 0x00, 0xff, 0xf0 },
+	{ 160, 120, 0x05, 0x0a, 0x1e, 0x08, 0x0c, 0xff, 0xf0 },
+	{ 0, 0 }
+};
+
+/* Sets up the OV518/OV518+ with the given image parameters
+ *
+ * OV518 needs a completely different approach, until we can figure out what
+ * the individual registers do. Many register ops are commented out until we
+ * can find out if they are still valid. Also, only 15 FPS is supported now.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static int
+ov518_mode_init_regs(struct usb_ov511 *ov,
+		     int width, int height, int mode, int sub_flag)
+{
+	int i;
+
+	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
+	       width, height, mode, sub_flag);
+
+	if (ov51x_stop(ov) < 0)
+		return -EIO;
+
+	for (i = 0; mlist518[i].width; i++) {
+//		int lncnt, pxcnt;
+
+		if (width != mlist518[i].width || height != mlist518[i].height)
+			continue;
+
+// FIXME: Subcapture won't be possible until we know what the registers do
+// FIXME: We can't handle anything but YUV420 so far
+
+//		/* Here I'm assuming that snapshot size == image size.
+//		 * I hope that's always true. --claudio
+//		 */
+//		pxcnt = sub_flag ? (ov->subw >> 3) - 1 : mlist[i].pxcnt;
+//		lncnt = sub_flag ? (ov->subh >> 3) - 1 : mlist[i].lncnt;
+//
+//		reg_w(ov, 0x12, pxcnt);
+//		reg_w(ov, 0x13, lncnt);
+
+		/******** Set the mode ********/		
+
+		/* Mode independent regs */
+		reg_w(ov, 0x2b, 0x00);
+		reg_w(ov, 0x2d, 0x00);
+		reg_w(ov, 0x3b, 0x00);
+		reg_w(ov, 0x3d, 0x00);
+
+		/* Mode dependent regs. Regs 38 - 3e are always the same as
+		 * regs 28 - 2e */
+		reg_w_mask(ov, 0x28, mlist518[i].reg28
+			| (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
+		reg_w(ov, 0x29, mlist518[i].reg29);
+		reg_w(ov, 0x2a, mlist518[i].reg2a);
+		reg_w(ov, 0x2c, mlist518[i].reg2c);
+		reg_w(ov, 0x2e, mlist518[i].reg2e);
+		reg_w_mask(ov, 0x38, mlist518[i].reg28 
+			| (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
+		reg_w(ov, 0x39, mlist518[i].reg29);
+		reg_w(ov, 0x3a, mlist518[i].reg2a);
+		reg_w(ov, 0x3c, mlist518[i].reg2c);
+		reg_w(ov, 0x3e, mlist518[i].reg2e);
+		reg_w(ov, 0x24, mlist518[i].reg24);
+		reg_w(ov, 0x25, mlist518[i].reg25);
+
+		/* Windows driver does this here; who knows why */
+		reg_w(ov, 0x2f, 0x80);
+
+		/******** Set the framerate (to 15 FPS) ********/		
+
+		/* Mode independent, but framerate dependent, regs */
+		/* These are for 15 FPS only */
+		reg_w(ov, 0x51, 0x08);
+		reg_w(ov, 0x22, 0x18);
+		reg_w(ov, 0x23, 0xff);
+		reg_w(ov, 0x71, 0x19);  /* Compression-related? */
+
+		// FIXME: Sensor-specific
+		/* Bit 5 is what matters here. Of course, it is "reserved" */
+		i2c_w(ov, 0x54, 0x23);
+
+		reg_w(ov, 0x2f, 0x80);
+
+		/* Mode dependent regs */
+		if ((width == 352 && height == 288) ||
+		    (width == 320 && height == 240)) {
+			/*  640 (280h) byte iso packets */
+			ov518_reg_w32(ov, 0x30,    640, 2);	/* 280h   */
+			ov518_reg_w32(ov, 0xc4,    400, 2);	/* 190h   */
+			ov518_reg_w32(ov, 0xc6,    500, 2);	/* 1f4h   */
+			ov518_reg_w32(ov, 0xc7,    500, 2);	/* 1f4h   */
+			ov518_reg_w32(ov, 0xc8,    142, 2);	/* 8eh    */
+			ov518_reg_w32(ov, 0xca, 131098, 3);	/* 2001ah */
+			ov518_reg_w32(ov, 0xcb,    532, 2);	/* 214h   */
+			ov518_reg_w32(ov, 0xcc,   2000, 2);	/* 7d0h   */
+			ov518_reg_w32(ov, 0xcd,     32, 2);	/* 20h    */
+			ov518_reg_w32(ov, 0xce,    608, 2);	/* 260h   */
+		} else if ((width == 176 && height == 144) ||
+			   (width == 160 && height == 120)) {
+			/*  384 (180h) byte iso packets */
+			ov518_reg_w32(ov, 0x30,    384, 2);	/* 180h   */
+			ov518_reg_w32(ov, 0xc4,    200, 2);	/* c8h    */
+			ov518_reg_w32(ov, 0xc6,    320, 2);	/* 140h   */
+			ov518_reg_w32(ov, 0xc7,    320, 2);	/* 140h   */
+			ov518_reg_w32(ov, 0xc8,     96, 2);	/* 60h    */
+			ov518_reg_w32(ov, 0xca,  78607, 3);	/* 1330fh */
+			ov518_reg_w32(ov, 0xcb,    320, 2);	/* 140h   */
+			ov518_reg_w32(ov, 0xcc,   1260, 2);	/* 4ech   */
+			ov518_reg_w32(ov, 0xcd,     19, 2);	/* 13h    */
+			ov518_reg_w32(ov, 0xce,    365, 2);	/* 16dh   */
+		} else {
+			/* Can't happen, since we already handled this case */
+			err("ov518_mode_init_regs(): **** logic error ****");
+		}
+
+		reg_w(ov, 0x2f, 0x80);
+
+		break;
+	}
+
+	if (ov51x_restart(ov) < 0)
+		return -EIO;
+
+	/* Reset it just for good measure */
+	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
+		return -EIO;
+
+	if (mlist518[i].width == 0) {
+		err("Unknown mode (%d, %d): %d", width, height, mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* This is a wrapper around the OV511, OV518, and sensor specific functions */
+static int
+mode_init_regs(struct usb_ov511 *ov,
+	       int width, int height, int mode, int sub_flag)
+{
+	int rc = 0;
+
+	if (!ov || !ov->dev)
+		return -EFAULT;
+
+	if (ov->bclass == BCL_OV518) {
+		rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag);
+	} else {
+		rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag);
+	}
+
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	switch (ov->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620:
+	case SEN_OV7620AE:
+	case SEN_OV8600:
+	case SEN_OV6620:
+	case SEN_OV6630:
+		rc = set_ov_sensor_window(ov, width, height, mode, sub_flag);
+		break;
+	case SEN_KS0127:
+	case SEN_KS0127B:
+		err("KS0127-series decoders not supported yet");
+		rc = -EINVAL;
+		break;
+	case SEN_SAA7111A:
+//		rc = mode_init_saa_sensor_regs(ov, width, height, mode, 
+//					       sub_flag);
+
+		PDEBUG(1, "SAA status = 0X%x", i2c_r(ov, 0x1f));
+		break;
+	default:
+		err("Unknown sensor");
+		rc = -EINVAL;
+	}
+
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	/* Sensor-independent settings */
+	rc = sensor_set_auto_brightness(ov, ov->auto_brt);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_set_auto_exposure(ov, ov->auto_exp);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	rc = sensor_set_banding_filter(ov, bandingfilter);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	if (ov->lightfreq) {
+		rc = sensor_set_light_freq(ov, lightfreq);
+		if (FATAL_ERROR(rc))
+			return rc;
+	}
+
+	rc = sensor_set_backlight(ov, ov->backlight);
+	if (FATAL_ERROR(rc))
+		return rc;
+
+	return 0;
+}
+
+/* This sets the default image parameters (Size = max, RGB24). This is
+ * useful for apps that use read() and do not set these.
+ */
+static int 
+ov51x_set_default_params(struct usb_ov511 *ov)
+{
+	int i;
+
+	PDEBUG(3, "%dx%d, RGB24", ov->maxwidth, ov->maxheight);
+
+	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
+	 * (using read() instead). */
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov->frame[i].width = ov->maxwidth;
+		ov->frame[i].height = ov->maxheight;
+		ov->frame[i].bytes_read = 0;
+		if (force_palette)
+			ov->frame[i].format = force_palette;
+		else
+			ov->frame[i].format = VIDEO_PALETTE_RGB24;
+		ov->frame[i].depth = get_depth(ov->frame[i].format);
+	}
+
+	/* Initialize to max width/height, RGB24 */
+	if (mode_init_regs(ov, ov->maxwidth, ov->maxheight,
+			   ov->frame[0].format, 0) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**********************************************************************
+ *
+ * Video decoder stuff
+ *
+ **********************************************************************/
+
+/* Set analog input port of decoder */
+static int 
+decoder_set_input(struct usb_ov511 *ov, int input)
+{
+	PDEBUG(4, "port %d", input);
+
+	switch (ov->sensor) {
+	case SEN_SAA7111A:
+	{
+		/* Select mode */
+		i2c_w_mask(ov, 0x02, input, 0x07);
+		/* Bypass chrominance trap for modes 4..7 */
+		i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80);
+		break;
+	}
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Get ASCII name of video input */
+static int 
+decoder_get_input_name(struct usb_ov511 *ov, int input, char *name)
+{
+	switch (ov->sensor) {
+	case SEN_SAA7111A:
+	{
+		if (input < 0 || input > 7)
+			return -EINVAL;
+		else if (input < 4)
+			sprintf(name, "CVBS-%d", input);
+		else // if (input < 8)
+			sprintf(name, "S-Video-%d", input - 4);
+
+		break;
+	}
+	default:
+		sprintf(name, "%s", "Camera");
+	}
+
+	return 0;
+}
+
+/* Set norm (NTSC, PAL, SECAM, AUTO) */
+static int 
+decoder_set_norm(struct usb_ov511 *ov, int norm)
+{
+	PDEBUG(4, "%d", norm);
+
+	switch (ov->sensor) {
+	case SEN_SAA7111A:
+	{
+		int reg_8, reg_e;
+
+		if (norm == VIDEO_MODE_NTSC) {
+			reg_8 = 0x40;	/* 60 Hz */
+			reg_e = 0x00;	/* NTSC M / PAL BGHI */
+		} else if (norm == VIDEO_MODE_PAL) {
+			reg_8 = 0x00;	/* 50 Hz */
+			reg_e = 0x00;	/* NTSC M / PAL BGHI */	
+		} else if (norm == VIDEO_MODE_AUTO) {
+			reg_8 = 0x80;	/* Auto field detect */
+			reg_e = 0x00;	/* NTSC M / PAL BGHI */
+		} else if (norm == VIDEO_MODE_SECAM) {
+			reg_8 = 0x00;	/* 50 Hz */
+			reg_e = 0x50;	/* SECAM / PAL 4.43 */
+		} else {
+			return -EINVAL;
+		}
+
+		i2c_w_mask(ov, 0x08, reg_8, 0xc0);
+		i2c_w_mask(ov, 0x0e, reg_e, 0x70);
+		break;
+	}
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/**********************************************************************
+ *
+ * Color correction functions
+ *
+ **********************************************************************/
+
+/*
+ * Turn a YUV4:2:0 block into an RGB block
+ *
+ * Video4Linux seems to use the blue, green, red channel
+ * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
+ *
+ * Color space conversion coefficients taken from the excellent
+ * http://www.inforamp.net/~poynton/ColorFAQ.html
+ * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
+ * Y values are given for all 4 pixels, but the U (Pb)
+ * and V (Pr) are assumed constant over the 2x2 block.
+ *
+ * To avoid floating point arithmetic, the color conversion
+ * coefficients are scaled into 16.16 fixed-point integers.
+ * They were determined as follows:
+ *
+ *	double brightness = 1.0;  (0->black; 1->full scale) 
+ *	double saturation = 1.0;  (0->greyscale; 1->full color)
+ *	double fixScale = brightness * 256 * 256;
+ *	int rvScale = (int)(1.402 * saturation * fixScale);
+ *	int guScale = (int)(-0.344136 * saturation * fixScale);
+ *	int gvScale = (int)(-0.714136 * saturation * fixScale);
+ *	int buScale = (int)(1.772 * saturation * fixScale);
+ *	int yScale = (int)(fixScale);	
+ */
+
+/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
+#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
+
+static inline void
+move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
+	       int rowPixels, unsigned char * rgb, int bits)
+{
+	const int rvScale = 91881;
+	const int guScale = -22553;
+	const int gvScale = -46801;
+	const int buScale = 116129;
+	const int yScale  = 65536;
+	int r, g, b;
+
+	g = guScale * u + gvScale * v;
+	if (force_rgb) {
+		r = buScale * u;
+		b = rvScale * v;
+	} else {
+		r = rvScale * v;
+		b = buScale * u;
+	}
+
+	yTL *= yScale; yTR *= yScale;
+	yBL *= yScale; yBR *= yScale;
+
+	if (bits == 24) {
+		/* Write out top two pixels */
+		rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
+		rgb[2] = LIMIT(r+yTL);
+
+		rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
+		rgb[5] = LIMIT(r+yTR);
+
+		/* Skip down to next line to write out bottom two pixels */
+		rgb += 3 * rowPixels;
+		rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
+		rgb[2] = LIMIT(r+yBL);
+
+		rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
+		rgb[5] = LIMIT(r+yBR);
+	} else if (bits == 16) {
+		/* Write out top two pixels */
+		rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) 
+			| ((LIMIT(g+yTL) << 3) & 0xE0);
+		rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07)
+			| (LIMIT(r+yTL) & 0xF8);
+
+		rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) 
+			| ((LIMIT(g+yTR) << 3) & 0xE0);
+		rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) 
+			| (LIMIT(r+yTR) & 0xF8);
+
+		/* Skip down to next line to write out bottom two pixels */
+		rgb += 2 * rowPixels;
+
+		rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F)
+			| ((LIMIT(g+yBL) << 3) & 0xE0);
+		rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07)
+			| (LIMIT(r+yBL) & 0xF8);
+
+		rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F)
+			| ((LIMIT(g+yBR) << 3) & 0xE0);
+		rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07)
+			| (LIMIT(r+yBR) & 0xF8);
+	}
+}
+
+/**********************************************************************
+ *
+ * Raw data parsing
+ *
+ **********************************************************************/
+
+/* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the
+ * image at pOut is specified by w.
+ */
+static inline void 
+make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
+{
+	unsigned char *pOut1 = pOut;
+	int x, y;
+
+	for (y = 0; y < 8; y++) {
+		pOut1 = pOut;
+		for (x = 0; x < 8; x++) {
+			*pOut1++ = *pIn++;
+		}
+		pOut += w;
+	}
+		
+}
+
+/*
+ * For RAW BW (YUV400) images, data shows up in 256 byte segments.
+ * The segments represent 4 squares of 8x8 pixels as follows:
+ *
+ *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+ *      8  9 ... 15    72  73 ...  79        200 201 ... 207
+ *           ...              ...                    ...
+ *     56 57 ... 63   120 121 ... 127        248 249 ... 255
+ *
+ */ 
+static void
+yuv400raw_to_yuv400p(struct ov511_frame *frame,
+		     unsigned char *pIn0, unsigned char *pOut0)
+{
+	int x, y;
+	unsigned char *pIn, *pOut, *pOutLine;
+
+	/* Copy Y */
+	pIn = pIn0;
+	pOutLine = pOut0;
+	for (y = 0; y < frame->rawheight - 1; y += 8) {
+		pOut = pOutLine;
+		for (x = 0; x < frame->rawwidth - 1; x += 8) {
+			make_8x8(pIn, pOut, frame->rawwidth);
+			pIn += 64;
+			pOut += 8;
+		}
+		pOutLine += 8 * frame->rawwidth;
+	}
+}
+
+/*
+ * For YUV4:2:0 images, the data shows up in 384 byte segments.
+ * The first 64 bytes of each segment are U, the next 64 are V.  The U and
+ * V are arranged as follows:
+ *
+ *      0  1 ...  7
+ *      8  9 ... 15
+ *           ...   
+ *     56 57 ... 63
+ *
+ * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
+ *
+ * The next 256 bytes are full resolution Y data and represent 4 squares
+ * of 8x8 pixels as follows:
+ *
+ *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+ *      8  9 ... 15    72  73 ...  79        200 201 ... 207
+ *           ...              ...                    ...
+ *     56 57 ... 63   120 121 ... 127   ...  248 249 ... 255
+ *
+ * Note that the U and V data in one segment represents a 16 x 16 pixel
+ * area, but the Y data represents a 32 x 8 pixel area. If the width is not an
+ * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the
+ * next horizontal stripe.
+ *
+ * If dumppix module param is set, _parse_data just dumps the incoming segments,
+ * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
+ * this puts the data on the standard output and can be analyzed with the
+ * parseppm.c utility I wrote.  That's a much faster way for figuring out how
+ * this data is scrambled.
+ */
+
+/* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0.
+ *
+ * FIXME: Currently only handles width and height that are multiples of 16
+ */
+static void
+yuv420raw_to_yuv420p(struct ov511_frame *frame,
+		     unsigned char *pIn0, unsigned char *pOut0)
+{
+	int k, x, y;
+	unsigned char *pIn, *pOut, *pOutLine;
+	const unsigned int a = frame->rawwidth * frame->rawheight;
+	const unsigned int w = frame->rawwidth / 2;
+
+	/* Copy U and V */
+	pIn = pIn0;
+	pOutLine = pOut0 + a;
+	for (y = 0; y < frame->rawheight - 1; y += 16) {
+		pOut = pOutLine;
+		for (x = 0; x < frame->rawwidth - 1; x += 16) {
+			make_8x8(pIn, pOut, w);
+			make_8x8(pIn + 64, pOut + a/4, w);
+			pIn += 384;
+			pOut += 8;
+		}
+		pOutLine += 8 * w;
+	}
+
+	/* Copy Y */
+	pIn = pIn0 + 128;
+	pOutLine = pOut0;
+	k = 0;
+	for (y = 0; y < frame->rawheight - 1; y += 8) {
+		pOut = pOutLine;
+		for (x = 0; x < frame->rawwidth - 1; x += 8) {
+			make_8x8(pIn, pOut, frame->rawwidth);
+			pIn += 64;
+			pOut += 8;
+			if ((++k) > 3) {
+				k = 0;
+				pIn += 128;
+			}
+		}
+		pOutLine += 8 * frame->rawwidth;
+	}
+}
+
+/*
+ * fixFrameRGBoffset--
+ * My camera seems to return the red channel about 1 pixel
+ * low, and the blue channel about 1 pixel high. After YUV->RGB
+ * conversion, we can correct this easily. OSL 2/24/2000.
+ */
+static void 
+fixFrameRGBoffset(struct ov511_frame *frame)
+{
+	int x, y;
+	int rowBytes = frame->width*3, w = frame->width;
+	unsigned char *rgb = frame->data;
+	const int shift = 1;  /* Distance to shift pixels by, vertically */
+
+	/* Don't bother with little images */
+	if (frame->width < 400) 
+		return;
+
+	/* This only works with RGB24 */
+	if (frame->format != VIDEO_PALETTE_RGB24)
+		return;
+
+	/* Shift red channel up */
+	for (y = shift; y < frame->height; y++)	{
+		int lp = (y-shift)*rowBytes;     /* Previous line offset */
+		int lc = y*rowBytes;             /* Current line offset */
+		for (x = 0; x < w; x++)
+			rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
+	}
+
+	/* Shift blue channel down */
+	for (y = frame->height-shift-1; y >= 0; y--) {
+		int ln = (y + shift) * rowBytes;  /* Next line offset */
+		int lc = y * rowBytes;            /* Current line offset */
+		for (x = 0; x < w; x++)
+			rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
+	}
+}
+
+/**********************************************************************
+ *
+ * Decompression
+ *
+ **********************************************************************/
+
+/* Chooses a decompression module, locks it, and sets ov->decomp_ops
+ * accordingly. Returns -ENXIO if decompressor is not available, otherwise
+ * returns 0 if no other error.
+ */
+static int 
+request_decompressor(struct usb_ov511 *ov)
+{
+	if (!ov)
+		return -ENODEV;
+
+	if (ov->decomp_ops) {
+		err("ERROR: Decompressor already requested!");
+		return -EINVAL;
+	}
+
+	lock_kernel();
+
+	/* Try to get MMX, and fall back on no-MMX if necessary */
+	if (ov->bclass == BCL_OV511) {
+		if (ov511_mmx_decomp_ops) {
+			PDEBUG(3, "Using OV511 MMX decompressor");
+			ov->decomp_ops = ov511_mmx_decomp_ops;
+		} else if (ov511_decomp_ops) {
+			PDEBUG(3, "Using OV511 decompressor");
+			ov->decomp_ops = ov511_decomp_ops;
+		} else {
+			err("No decompressor available");
+		}
+	} else if (ov->bclass == BCL_OV518) {
+		if (ov518_mmx_decomp_ops) {
+			PDEBUG(3, "Using OV518 MMX decompressor");
+			ov->decomp_ops = ov518_mmx_decomp_ops;
+		} else if (ov518_decomp_ops) {
+			PDEBUG(3, "Using OV518 decompressor");
+			ov->decomp_ops = ov518_decomp_ops;
+		} else {
+			err("No decompressor available");
+		}
+	} else {
+		err("Unknown bridge");
+	}
+
+	if (ov->decomp_ops) {
+		if (!ov->decomp_ops->decomp_lock) {
+			ov->decomp_ops = NULL;
+			unlock_kernel();
+			return -ENOSYS;
+		}
+		ov->decomp_ops->decomp_lock();
+		unlock_kernel();
+		return 0;
+	} else {
+		unlock_kernel();
+		return -ENXIO;
+	}
+}
+
+/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
+ * if ov->decomp_ops is NULL.
+ */
+static void 
+release_decompressor(struct usb_ov511 *ov)
+{
+	int released = 0;	/* Did we actually do anything? */
+
+	if (!ov)
+		return;
+
+	lock_kernel();
+
+	if (ov->decomp_ops && ov->decomp_ops->decomp_unlock) {
+		ov->decomp_ops->decomp_unlock();
+		released = 1;
+	}
+
+	ov->decomp_ops = NULL;
+	
+	unlock_kernel();
+
+	if (released)
+		PDEBUG(3, "Decompressor released");
+}
+
+static void 
+decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
+	   unsigned char *pIn0, unsigned char *pOut0)
+{
+	if (!ov->decomp_ops)
+		if (request_decompressor(ov))
+			return;
+
+	PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
+
+	if (frame->format == VIDEO_PALETTE_GREY 
+	    && ov->decomp_ops->decomp_400) {
+		int ret = ov->decomp_ops->decomp_400(
+			pIn0,
+			pOut0,
+			frame->compbuf,
+			frame->rawwidth,
+			frame->rawheight,
+			frame->bytes_recvd);
+		PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
+	} else if (ov->decomp_ops->decomp_420) {
+		int ret = ov->decomp_ops->decomp_420(
+			pIn0,
+			pOut0,
+			frame->compbuf,
+			frame->rawwidth,
+			frame->rawheight,
+			frame->bytes_recvd);
+		PDEBUG(4, "DEBUG: decomp_420 returned %d", ret);
+	} else {
+		err("Decompressor does not support this format");
+	}
+}
+
+/**********************************************************************
+ *
+ * Format conversion
+ *
+ **********************************************************************/
+
+/* Converts from planar YUV420 to RGB24. */
+static void 
+yuv420p_to_rgb(struct ov511_frame *frame,
+	       unsigned char *pIn0, unsigned char *pOut0, int bits)
+{
+	const int numpix = frame->width * frame->height;
+	const int bytes = bits >> 3;
+	int i, j, y00, y01, y10, y11, u, v;
+	unsigned char *pY = pIn0;
+	unsigned char *pU = pY + numpix;
+	unsigned char *pV = pU + numpix / 4;
+	unsigned char *pOut = pOut0;
+
+	for (j = 0; j <= frame->height - 2; j += 2) {
+		for (i = 0; i <= frame->width - 2; i += 2) {
+			y00 = *pY;
+			y01 = *(pY + 1);
+			y10 = *(pY + frame->width);
+			y11 = *(pY + frame->width + 1);
+			u = (*pU++) - 128;
+			v = (*pV++) - 128;
+
+			move_420_block(y00, y01, y10, y11, u, v,
+				       frame->width, pOut, bits);
+	
+			pY += 2;
+			pOut += 2 * bytes;
+
+		}
+		pY += frame->width;
+		pOut += frame->width * bytes;
+	}
+}
+
+/* Converts from planar YUV420 to YUV422 (YUYV). */
+static void
+yuv420p_to_yuv422(struct ov511_frame *frame,
+		  unsigned char *pIn0, unsigned char *pOut0)
+{
+	const int numpix = frame->width * frame->height;
+	int i, j;
+	unsigned char *pY = pIn0;
+	unsigned char *pU = pY + numpix;
+	unsigned char *pV = pU + numpix / 4;
+	unsigned char *pOut = pOut0;
+
+	for (i = 0; i < numpix; i++) {
+		*pOut = *(pY + i);
+		pOut += 2;
+	}
+
+	pOut = pOut0 + 1;
+	for (j = 0; j <= frame->height - 2 ; j += 2) {
+		for (i = 0; i <= frame->width - 2; i += 2) {
+			int u = *pU++;
+			int v = *pV++;
+			
+			*pOut = u;
+			*(pOut+2) = v;
+			*(pOut+frame->width*2) = u;
+			*(pOut+frame->width*2+2) = v;
+			pOut += 4;
+		}
+		pOut += (frame->width * 2);
+	}
+}
+
+/* Converts pData from planar YUV420 to planar YUV422 **in place**. */
+static void
+yuv420p_to_yuv422p(struct ov511_frame *frame, unsigned char *pData)
+{
+	const int numpix = frame->width * frame->height;
+	const int w = frame->width;
+	int j;
+	unsigned char *pIn, *pOut;
+
+	/* Clear U and V */
+	memset(pData + numpix + numpix / 2, 127, numpix / 2);
+
+	/* Convert V starting from beginning and working forward */
+	pIn = pData + numpix + numpix / 4;
+	pOut = pData + numpix +numpix / 2;
+	for (j = 0; j <= frame->height - 2; j += 2) {
+		memmove(pOut, pIn, w/2);
+		memmove(pOut + w/2, pIn, w/2);
+		pIn += w/2;
+		pOut += w;
+	}
+
+	/* Convert U, starting from end and working backward */
+	pIn = pData + numpix + numpix / 4;
+	pOut = pData + numpix + numpix / 2;
+	for (j = 0; j <= frame->height - 2; j += 2) {
+		pIn -= w/2;
+		pOut -= w;
+		memmove(pOut, pIn, w/2);
+		memmove(pOut + w/2, pIn, w/2);
+	}
+}
+
+/* Fuses even and odd fields together, and doubles width.
+ * INPUT: an odd field followed by an even field at pIn0, in YUV planar format
+ * OUTPUT: a normal YUV planar image, with correct aspect ratio
+ */
+static void
+deinterlace(struct ov511_frame *frame, int rawformat,
+            unsigned char *pIn0, unsigned char *pOut0)
+{
+	const int fieldheight = frame->rawheight / 2;
+	const int fieldpix = fieldheight * frame->rawwidth;
+	const int w = frame->width;
+	int x, y;
+	unsigned char *pInEven, *pInOdd, *pOut;
+
+	PDEBUG(5, "fieldheight=%d", fieldheight);
+
+	if (frame->rawheight != frame->height) {
+		err("invalid height");
+		return;
+	}
+
+	if ((frame->rawwidth * 2) != frame->width) {
+		err("invalid width");
+		return;
+	}
+
+	/* Y */
+	pInOdd = pIn0;
+	pInEven = pInOdd + fieldpix;
+	pOut = pOut0;
+	for (y = 0; y < fieldheight; y++) {
+		for (x = 0; x < frame->rawwidth; x++) {
+			*pOut = *pInEven;
+			*(pOut+1) = *pInEven++;
+			*(pOut+w) = *pInOdd;
+			*(pOut+w+1) = *pInOdd++;
+			pOut += 2;
+		}
+		pOut += w;
+	}
+
+	if (rawformat == RAWFMT_YUV420) {
+	/* U */
+		pInOdd = pIn0 + fieldpix * 2;
+		pInEven = pInOdd + fieldpix / 4;
+		for (y = 0; y < fieldheight / 2; y++) {
+			for (x = 0; x < frame->rawwidth / 2; x++) {
+				*pOut = *pInEven;
+				*(pOut+1) = *pInEven++;
+				*(pOut+w/2) = *pInOdd;
+				*(pOut+w/2+1) = *pInOdd++;
+				pOut += 2;
+			}
+			pOut += w/2;
+		}
+	/* V */
+		pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2;
+		pInEven = pInOdd + fieldpix / 4;
+		for (y = 0; y < fieldheight / 2; y++) {
+			for (x = 0; x < frame->rawwidth / 2; x++) {
+				*pOut = *pInEven;
+				*(pOut+1) = *pInEven++;
+				*(pOut+w/2) = *pInOdd;
+				*(pOut+w/2+1) = *pInOdd++;
+				pOut += 2;
+			}
+			pOut += w/2;
+		}
+	}
+}
+
+/* Post-processes the specified frame. This consists of:
+ * 	1. Decompress frame, if necessary
+ *	2. Deinterlace frame and scale to proper size, if necessary
+ * 	3. Convert from YUV planar to destination format, if necessary
+ * 	4. Fix the RGB offset, if necessary
+ */
+static void 
+ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
+{
+	if (dumppix) {
+		memset(frame->data, 0, 
+			MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
+		PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);
+		memcpy(frame->data, frame->rawdata, frame->bytes_recvd);
+		return;
+	}
+
+	/* YUV400 must be handled separately */
+	if (frame->format == VIDEO_PALETTE_GREY) {
+		/* Deinterlace frame, if necessary */
+		if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
+			if (frame->compressed)
+				decompress(ov, frame, frame->rawdata,
+						 frame->tempdata);
+			else
+				yuv400raw_to_yuv400p(frame, frame->rawdata,
+						     frame->tempdata);
+
+			deinterlace(frame, RAWFMT_YUV400, frame->tempdata,
+			            frame->data);
+		} else {
+			if (frame->compressed)
+				decompress(ov, frame, frame->rawdata,
+						 frame->data);
+			else
+				yuv400raw_to_yuv400p(frame, frame->rawdata,
+						     frame->data);
+		}
+
+		return;
+	}
+
+	/* Process frame->data to frame->rawdata */
+	if (frame->compressed)
+		decompress(ov, frame, frame->rawdata, frame->tempdata);
+	else
+		yuv420raw_to_yuv420p(frame, frame->rawdata, frame->tempdata);
+
+	/* Deinterlace frame, if necessary */
+	if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
+		memcpy(frame->rawdata, frame->tempdata,
+			MAX_RAW_DATA_SIZE(frame->width, frame->height));
+		deinterlace(frame, RAWFMT_YUV420, frame->rawdata,
+		            frame->tempdata);
+	}
+
+	/* Frame should be (width x height) and not (rawwidth x rawheight) at
+         * this point. */
+
+#if 0
+	/* Clear output buffer for testing purposes */
+	memset(frame->data, 0, MAX_DATA_SIZE(frame->width, frame->height));
+#endif
+
+	/* Process frame->tempdata to frame->data */
+	switch (frame->format) {
+	case VIDEO_PALETTE_RGB565:
+		yuv420p_to_rgb(frame, frame->tempdata, frame->data, 16);
+		break;
+	case VIDEO_PALETTE_RGB24:
+		yuv420p_to_rgb(frame, frame->tempdata, frame->data, 24);
+		break;
+	case VIDEO_PALETTE_YUV422:
+	case VIDEO_PALETTE_YUYV:
+		yuv420p_to_yuv422(frame, frame->tempdata, frame->data);
+		break;
+	case VIDEO_PALETTE_YUV420:
+	case VIDEO_PALETTE_YUV420P:
+		memcpy(frame->data, frame->tempdata,
+			MAX_RAW_DATA_SIZE(frame->width, frame->height));
+		break;
+	case VIDEO_PALETTE_YUV422P:
+		/* Data is converted in place, so copy it in advance */
+		memcpy(frame->data, frame->tempdata,
+			MAX_RAW_DATA_SIZE(frame->width, frame->height));
+
+		yuv420p_to_yuv422p(frame, frame->data);
+		break;
+	default:
+		err("Cannot convert data to %s",
+		    symbolic(v4l1_plist, frame->format));
+	}
+
+	if (fix_rgb_offset)
+		fixFrameRGBoffset(frame);
+}
+
+/**********************************************************************
+ *
+ * OV51x data transfer, IRQ handler
+ *
+ **********************************************************************/
+
+static inline void 
+ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
+{
+	int num, offset;
+	int pnum = in[ov->packet_size - 1];		/* Get packet number */
+	int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
+	struct ov511_frame *frame = &ov->frame[ov->curframe];
+	struct timeval *ts;
+
+	/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
+	 * byte non-zero. The EOF packet has image width/height in the
+	 * 10th and 11th bytes. The 9th byte is given as follows:
+	 *
+	 * bit 7: EOF
+	 *     6: compression enabled
+	 *     5: 422/420/400 modes
+	 *     4: 422/420/400 modes
+	 *     3: 1
+	 *     2: snapshot button on
+	 *     1: snapshot frame
+	 *     0: even/odd field
+	 */
+
+	if (printph) {
+		info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
+		     pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
+		     in[7], in[8], in[9], in[10], in[11]);
+	}
+
+	/* Check for SOF/EOF packet */
+	if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) ||
+	    (~in[8] & 0x08))
+		goto check_middle;
+
+	/* Frame end */
+	if (in[8] & 0x80) {
+		ts = (struct timeval *)(frame->data 
+		      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
+		do_gettimeofday(ts);
+
+		/* Get the actual frame size from the EOF header */
+		frame->rawwidth = ((int)(in[9]) + 1) * 8;
+		frame->rawheight = ((int)(in[10]) + 1) * 8;
+
+ 		PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
+			ov->curframe, pnum, frame->rawwidth, frame->rawheight,
+			frame->bytes_recvd);
+
+		/* Validate the header data */
+		RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
+		RESTRICT_TO_RANGE(frame->rawheight, ov->minheight,
+				  ov->maxheight);
+
+		/* Don't allow byte count to exceed buffer size */
+		RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
+
+		if (frame->scanstate == STATE_LINES) {
+	    		int nextf;
+
+			frame->grabstate = FRAME_DONE;	// FIXME: Is this right?
+
+			if (waitqueue_active(&frame->wq)) {
+				frame->grabstate = FRAME_DONE;
+				wake_up_interruptible(&frame->wq);
+			}
+
+			/* If next frame is ready or grabbing,
+			 * point to it */
+			nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
+			if (ov->frame[nextf].grabstate == FRAME_READY
+			    || ov->frame[nextf].grabstate == FRAME_GRABBING) {
+				ov->curframe = nextf;
+				ov->frame[nextf].scanstate = STATE_SCANNING;
+			} else {
+				if (frame->grabstate == FRAME_DONE) {
+					PDEBUG(4, "** Frame done **");
+				} else {
+					PDEBUG(4, "Frame not ready? state = %d",
+						ov->frame[nextf].grabstate);
+				}
+
+				ov->curframe = -1;
+			}
+		} else {
+			PDEBUG(5, "Frame done, but not scanning");
+		}
+		/* Image corruption caused by misplaced frame->segment = 0
+		 * fixed by carlosf@conectiva.com.br
+		 */
+	} else {
+		/* Frame start */
+		PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
+
+		/* Check to see if it's a snapshot frame */
+		/* FIXME?? Should the snapshot reset go here? Performance? */
+		if (in[8] & 0x02) {
+			frame->snapshot = 1;
+			PDEBUG(3, "snapshot detected");
+		}
+
+		frame->scanstate = STATE_LINES;
+		frame->bytes_recvd = 0;
+		frame->compressed = in[8] & 0x40;
+	}
+
+check_middle:
+	/* Are we in a frame? */
+	if (frame->scanstate != STATE_LINES) {
+		PDEBUG(5, "Not in a frame; packet skipped");
+		return;
+	}
+
+	/* If frame start, skip header */
+	if (frame->bytes_recvd == 0)
+		offset = 9;
+	else
+		offset = 0;
+
+	num = n - offset - 1;
+
+	/* Dump all data exactly as received */
+	if (dumppix == 2) {
+		frame->bytes_recvd += n - 1;
+		if (frame->bytes_recvd <= max_raw)
+			memcpy(frame->rawdata + frame->bytes_recvd - (n - 1),
+				in, n - 1);
+		else
+			PDEBUG(3, "Raw data buffer overrun!! (%d)",
+				frame->bytes_recvd - max_raw);
+	} else if (!frame->compressed && !remove_zeros) {
+		frame->bytes_recvd += num;
+		if (frame->bytes_recvd <= max_raw)
+			memcpy(frame->rawdata + frame->bytes_recvd - num,
+				in + offset, num);
+		else
+			PDEBUG(3, "Raw data buffer overrun!! (%d)",
+				frame->bytes_recvd - max_raw);
+	} else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */
+		int b, read = 0, allzero, copied = 0;
+		if (offset) {
+			frame->bytes_recvd += 32 - offset;	// Bytes out
+			memcpy(frame->rawdata,	in + offset, 32 - offset);
+			read += 32;
+		}
+
+		while (read < n - 1) {
+			allzero = 1;
+			for (b = 0; b < 32; b++) {
+				if (in[read + b]) {
+					allzero = 0;
+					break;
+				}
+			}
+
+			if (allzero) {
+				/* Don't copy it */
+			} else {
+				if (frame->bytes_recvd + copied + 32 <= max_raw)
+				{
+					memcpy(frame->rawdata
+						+ frame->bytes_recvd + copied,
+						in + read, 32);
+					copied += 32;
+				} else {
+					PDEBUG(3, "Raw data buffer overrun!!");
+				}
+			}
+			read += 32;
+		}
+
+		frame->bytes_recvd += copied;
+	}
+}
+
+static inline void 
+ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
+{
+	int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
+	struct ov511_frame *frame = &ov->frame[ov->curframe];
+	struct timeval *ts;
+
+	if (printph) {
+		info("ph: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
+		     in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7],
+		     in[8], in[9], in[10], in[11]);
+	}
+
+	/* A false positive here is likely, until OVT gives me
+	 * the definitive SOF/EOF format */
+	if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) {
+		if (frame->scanstate == STATE_LINES) {
+			PDEBUG(4, "Detected frame end/start");
+			goto eof;
+		} else { //scanstate == STATE_SCANNING
+			/* Frame start */
+			PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
+			goto sof;
+		}
+	} else {
+		goto check_middle;
+	}
+
+eof:
+	ts = (struct timeval *)(frame->data
+	      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
+	do_gettimeofday(ts);
+
+	PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d",
+		ov->curframe,
+		(int)(in[9]), (int)(in[10]), frame->bytes_recvd);
+
+	// FIXME: Since we don't know the header formats yet,
+	// there is no way to know what the actual image size is
+	frame->rawwidth = frame->width;
+	frame->rawheight = frame->height;
+
+	/* Validate the header data */
+	RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
+	RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
+
+	/* Don't allow byte count to exceed buffer size */
+	RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
+
+	if (frame->scanstate == STATE_LINES) {
+    		int nextf;
+
+		frame->grabstate = FRAME_DONE;	// FIXME: Is this right?
+
+		if (waitqueue_active(&frame->wq)) {
+			frame->grabstate = FRAME_DONE;
+			wake_up_interruptible(&frame->wq);
+		}
+
+		/* If next frame is ready or grabbing,
+		 * point to it */
+		nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
+		if (ov->frame[nextf].grabstate == FRAME_READY
+		    || ov->frame[nextf].grabstate == FRAME_GRABBING) {
+			ov->curframe = nextf;
+			ov->frame[nextf].scanstate = STATE_SCANNING;
+			frame = &ov->frame[nextf];
+		} else {
+			if (frame->grabstate == FRAME_DONE) {
+				PDEBUG(4, "** Frame done **");
+			} else {
+				PDEBUG(4, "Frame not ready? state = %d",
+				       ov->frame[nextf].grabstate);
+			}
+
+			ov->curframe = -1;
+			PDEBUG(4, "SOF dropped (no active frame)");
+			return;  /* Nowhere to store this frame */
+		}
+	}
+sof:
+	PDEBUG(4, "Starting capture on frame %d", frame->framenum);
+
+// Snapshot not reverse-engineered yet.
+#if 0
+	/* Check to see if it's a snapshot frame */
+	/* FIXME?? Should the snapshot reset go here? Performance? */
+	if (in[8] & 0x02) {
+		frame->snapshot = 1;
+		PDEBUG(3, "snapshot detected");
+	}
+#endif
+	frame->scanstate = STATE_LINES;
+	frame->bytes_recvd = 0;
+//		frame->compressed = 1;
+
+check_middle:
+	/* Are we in a frame? */
+	if (frame->scanstate != STATE_LINES) {
+		PDEBUG(4, "scanstate: no SOF yet");
+		return;
+	}
+
+	/* Dump all data exactly as received */
+	if (dumppix == 2) {
+		frame->bytes_recvd += n;
+		if (frame->bytes_recvd <= max_raw)
+			memcpy(frame->rawdata + frame->bytes_recvd - n, in, n);
+		else
+			PDEBUG(3, "Raw data buffer overrun!! (%d)",
+				frame->bytes_recvd - max_raw);
+	} else {
+		/* All incoming data are divided into 8-byte segments. If the
+		 * segment contains all zero bytes, it must be skipped. These
+		 * zero-segments allow the OV518 to mainain a constant data rate
+		 * regardless of the effectiveness of the compression. Segments
+		 * are aligned relative to the beginning of each isochronous
+		 * packet. The first segment is a header (the decompressor
+		 * skips it later).
+		 */
+
+		int b, read = 0, allzero, copied = 0;
+
+		while (read < n) {
+			allzero = 1;
+			for (b = 0; b < 8; b++) {
+				if (in[read + b]) {
+					allzero = 0;
+					break;
+				}
+			}
+
+			if (allzero) {
+			/* Don't copy it */
+			} else {
+				if (frame->bytes_recvd + copied + 8 <= max_raw)
+				{
+					memcpy(frame->rawdata 
+						+ frame->bytes_recvd + copied,
+						in + read, 8);
+					copied += 8;
+				} else {
+					PDEBUG(3, "Raw data buffer overrun!!");
+				}
+			}
+			read += 8;
+		}
+		frame->bytes_recvd += copied;
+	}
+}
+
+static void 
+ov51x_isoc_irq(struct urb *urb)
+{
+	int i;
+	struct usb_ov511 *ov;
+	struct ov511_sbuf *sbuf;
+
+	if (!urb->context) {
+		PDEBUG(4, "no context");
+		return;
+	}
+
+	sbuf = urb->context;
+	ov = sbuf->ov;
+
+	if (!ov || !ov->dev || !ov->user) {
+		PDEBUG(4, "no device, or not open");
+		return;
+	}
+
+	if (!ov->streaming) {
+		PDEBUG(4, "hmmm... not streaming, but got interrupt");
+		return;
+	}
+
+        if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+                PDEBUG(4, "URB unlinked");
+                return;
+        }
+
+	if (urb->status != -EINPROGRESS && urb->status != 0) {
+		err("ERROR: urb->status=%d: %s", urb->status,
+		    symbolic(urb_errlist, urb->status));
+		return;
+	}
+
+	/* Copy the data received into our frame buffer */
+	PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n,
+	       urb->number_of_packets);
+	for (i = 0; i < urb->number_of_packets; i++) {
+		/* Warning: Don't call *_move_data() if no frame active! */
+		if (ov->curframe >= 0) {
+			int n = urb->iso_frame_desc[i].actual_length;
+			int st = urb->iso_frame_desc[i].status;
+			unsigned char *cdata;
+
+			urb->iso_frame_desc[i].actual_length = 0;
+			urb->iso_frame_desc[i].status = 0;
+
+			cdata = urb->transfer_buffer
+				+ urb->iso_frame_desc[i].offset;
+
+			if (!n) {
+				PDEBUG(4, "Zero-length packet");
+				continue;
+			}
+
+			if (st)
+				PDEBUG(2, "data error: [%d] len=%d, status=%d",
+				       i, n, st);
+
+			if (ov->bclass == BCL_OV511)
+				ov511_move_data(ov, cdata, n);
+			else if (ov->bclass == BCL_OV518)
+				ov518_move_data(ov, cdata, n);
+			else
+				err("Unknown bridge device (%d)", ov->bridge);
+
+		} else if (waitqueue_active(&ov->wq)) {
+			wake_up_interruptible(&ov->wq);
+		}
+	}
+
+	urb->dev = ov->dev;
+
+	return;
+}
+
+/****************************************************************************
+ *
+ * Stream initialization and termination
+ *
+ ***************************************************************************/
+
+static int 
+ov51x_init_isoc(struct usb_ov511 *ov)
+{
+	struct urb *urb;
+	int fx, err, n, size;
+
+	PDEBUG(3, "*** Initializing capture ***");
+
+	ov->curframe = -1;
+
+	if (ov->bridge == BRG_OV511) {
+		if (cams == 1)				size = 993;
+		else if (cams == 2)			size = 513;
+		else if (cams == 3 || cams == 4)	size = 257;
+		else {
+			err("\"cams\" parameter too high!");
+			return -1;
+		}
+	} else if (ov->bridge == BRG_OV511PLUS) {
+		if (cams == 1)				size = 961;
+		else if (cams == 2)			size = 513;
+		else if (cams == 3 || cams == 4)	size = 257;
+		else if (cams >= 5 && cams <= 8)	size = 129;
+		else if (cams >= 9 && cams <= 31)	size = 33;
+		else {
+			err("\"cams\" parameter too high!");
+			return -1;
+		}
+	} else if (ov->bclass == BCL_OV518) {
+		if (cams == 1)				size = 896;
+		else if (cams == 2)			size = 512;
+		else if (cams == 3 || cams == 4)	size = 256;
+		else if (cams >= 5 && cams <= 8)	size = 128;
+		else {
+			err("\"cams\" parameter too high!");
+			return -1;
+		}
+	} else {
+		err("invalid bridge type");
+		return -1;
+	}
+
+	if (packetsize == -1) {
+		// FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now
+		if (ov->bclass == BCL_OV518)
+			ov51x_set_packet_size(ov, 640);
+		else
+			ov51x_set_packet_size(ov, size);
+	} else {
+			info("Forcing packet size to %d", packetsize);
+			ov51x_set_packet_size(ov, packetsize);
+	}
+
+	for (n = 0; n < OV511_NUMSBUF; n++) {
+		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
+		if (!urb) {
+			err("init isoc: usb_alloc_urb ret. NULL");
+			return -ENOMEM;
+		}
+		ov->sbuf[n].urb = urb;
+		urb->dev = ov->dev;
+		urb->context = &ov->sbuf[n];
+		urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS);
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->transfer_buffer = ov->sbuf[n].data;
+		urb->complete = ov51x_isoc_irq;
+		urb->number_of_packets = FRAMES_PER_DESC;
+		urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC;
+		for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+			urb->iso_frame_desc[fx].offset = ov->packet_size * fx;
+			urb->iso_frame_desc[fx].length = ov->packet_size;
+		}
+	}
+
+	ov->streaming = 1;
+
+	ov->sbuf[OV511_NUMSBUF - 1].urb->next = ov->sbuf[0].urb;
+	for (n = 0; n < OV511_NUMSBUF - 1; n++)
+		ov->sbuf[n].urb->next = ov->sbuf[n+1].urb;
+
+	for (n = 0; n < OV511_NUMSBUF; n++) {
+		ov->sbuf[n].urb->dev = ov->dev;
+		err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL);
+		if (err)
+			err("init isoc: usb_submit_urb(%d) ret %d", n, err);
+	}
+
+	return 0;
+}
+
+static void 
+ov51x_unlink_isoc(struct usb_ov511 *ov)
+{
+	int n;
+
+	/* Unschedule all of the iso td's */
+	for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
+		if (ov->sbuf[n].urb) {
+			usb_unlink_urb(ov->sbuf[n].urb);
+			usb_free_urb(ov->sbuf[n].urb);
+			ov->sbuf[n].urb = NULL;
+		}
+	}
+}
+
+static void 
+ov51x_stop_isoc(struct usb_ov511 *ov)
+{
+	if (!ov->streaming || !ov->dev)
+		return;
+
+	PDEBUG(3, "*** Stopping capture ***");
+
+	ov51x_set_packet_size(ov, 0);
+
+	ov->streaming = 0;
+
+	ov51x_unlink_isoc(ov);
+}
+
+static int 
+ov51x_new_frame(struct usb_ov511 *ov, int framenum)
+{
+	struct ov511_frame *frame;
+	int newnum;
+
+	PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);
+
+	if (!ov->dev)
+		return -1;
+
+	/* If we're not grabbing a frame right now and the other frame is */
+	/* ready to be grabbed into, then use it instead */
+	if (ov->curframe == -1) {
+		newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
+		if (ov->frame[newnum].grabstate == FRAME_READY)
+			framenum = newnum;
+	} else
+		return 0;
+
+	frame = &ov->frame[framenum];
+
+	PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, 
+	       frame->width, frame->height);
+
+	frame->grabstate = FRAME_GRABBING;
+	frame->scanstate = STATE_SCANNING;
+	frame->snapshot = 0;
+
+	ov->curframe = framenum;
+
+	/* Make sure it's not too big */
+	if (frame->width > ov->maxwidth)
+		frame->width = ov->maxwidth;
+
+	frame->width &= ~7L;		/* Multiple of 8 */
+
+	if (frame->height > ov->maxheight)
+		frame->height = ov->maxheight;
+
+	frame->height &= ~3L;		/* Multiple of 4 */
+
+	return 0;
+}
+
+/****************************************************************************
+ *
+ * Buffer management
+ *
+ ***************************************************************************/
+
+/* 
+ * - You must acquire buf_lock before entering this function.
+ * - Because this code will free any non-null pointer, you must be sure to null
+ *   them if you explicitly free them somewhere else!
+ */
+static void 
+ov51x_do_dealloc(struct usb_ov511 *ov)
+{
+	int i;
+	PDEBUG(4, "entered");
+
+	if (ov->fbuf) {
+		rvfree(ov->fbuf, OV511_NUMFRAMES
+		       * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
+		ov->fbuf = NULL;
+	}
+
+	if (ov->rawfbuf) {
+		vfree(ov->rawfbuf);
+		ov->rawfbuf = NULL;
+	}
+
+	if (ov->tempfbuf) {
+		vfree(ov->tempfbuf);
+		ov->tempfbuf = NULL;
+	}
+
+	for (i = 0; i < OV511_NUMSBUF; i++) {
+		if (ov->sbuf[i].data) {
+			kfree(ov->sbuf[i].data);
+			ov->sbuf[i].data = NULL;
+		}
+	}
+
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov->frame[i].data = NULL;
+		ov->frame[i].rawdata = NULL;
+		ov->frame[i].tempdata = NULL;
+		if (ov->frame[i].compbuf) {
+			free_page((unsigned long) ov->frame[i].compbuf);
+			ov->frame[i].compbuf = NULL;
+		}
+	}
+
+	PDEBUG(4, "buffer memory deallocated");
+	ov->buf_state = BUF_NOT_ALLOCATED;
+	PDEBUG(4, "leaving");
+}
+
+static int 
+ov51x_alloc(struct usb_ov511 *ov)
+{
+	int i;
+	const int w = ov->maxwidth;
+	const int h = ov->maxheight;
+	const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h);
+	const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);
+
+	PDEBUG(4, "entered");
+	down(&ov->buf_lock);
+
+	if (ov->buf_state == BUF_PEND_DEALLOC) {
+		ov->buf_state = BUF_ALLOCATED;
+		del_timer(&ov->buf_timer);
+	}
+
+	if (ov->buf_state == BUF_ALLOCATED)
+		goto out;
+
+	ov->fbuf = rvmalloc(data_bufsize);
+	if (!ov->fbuf)
+		goto error;
+
+	ov->rawfbuf = vmalloc(raw_bufsize);
+	if (!ov->rawfbuf)
+		goto error;
+
+	memset(ov->rawfbuf, 0, raw_bufsize);
+
+	ov->tempfbuf = vmalloc(raw_bufsize);
+	if (!ov->tempfbuf)
+		goto error;
+
+	memset(ov->tempfbuf, 0, raw_bufsize);
+
+	for (i = 0; i < OV511_NUMSBUF; i++) {
+		ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
+			MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
+		if (!ov->sbuf[i].data)
+			goto error;
+
+		PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data);
+	}
+
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h);
+		ov->frame[i].rawdata = ov->rawfbuf 
+		 + i * MAX_RAW_DATA_SIZE(w, h);
+		ov->frame[i].tempdata = ov->tempfbuf 
+		 + i * MAX_RAW_DATA_SIZE(w, h);
+
+		ov->frame[i].compbuf = 
+		 (unsigned char *) __get_free_page(GFP_KERNEL);
+		if (!ov->frame[i].compbuf)
+			goto error;
+
+		PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data);
+	}
+
+	ov->buf_state = BUF_ALLOCATED;
+out:
+	up(&ov->buf_lock);
+	PDEBUG(4, "leaving");
+	return 0;
+error:
+	ov51x_do_dealloc(ov);
+	up(&ov->buf_lock);
+	PDEBUG(4, "errored");
+	return -ENOMEM;
+}
+
+static void 
+ov51x_buf_callback(unsigned long data)
+{
+	struct usb_ov511 *ov = (struct usb_ov511 *)data;
+	PDEBUG(4, "entered");
+	down(&ov->buf_lock);
+
+	if (ov->buf_state == BUF_PEND_DEALLOC)
+		ov51x_do_dealloc(ov);
+
+	up(&ov->buf_lock);
+	PDEBUG(4, "leaving");
+}
+
+static void 
+ov51x_dealloc(struct usb_ov511 *ov, int now)
+{
+	struct timer_list *bt = &(ov->buf_timer);
+	PDEBUG(4, "entered");
+	down(&ov->buf_lock);
+
+	PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later");
+
+	if (ov->buf_state == BUF_PEND_DEALLOC) {
+		ov->buf_state = BUF_ALLOCATED;
+		del_timer(bt);
+	}
+
+	if (now)
+		ov51x_do_dealloc(ov);
+	else {
+		ov->buf_state = BUF_PEND_DEALLOC;
+		init_timer(bt);
+		bt->function = ov51x_buf_callback;
+		bt->data = (unsigned long)ov;
+		bt->expires = jiffies + buf_timeout * HZ;
+		add_timer(bt);
+	}
+	up(&ov->buf_lock);
+	PDEBUG(4, "leaving");
+}
+
+/****************************************************************************
+ *
+ * V4L 1 API
+ *
+ ***************************************************************************/
+
+static int 
+ov51x_v4l1_open(struct inode *inode, struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct usb_ov511 *ov = vdev->priv;
+	int err, i;
+
+	PDEBUG(4, "opening");
+
+	down(&ov->lock);
+
+	err = -EBUSY;
+	if (ov->user) 
+		goto out;
+
+	err = -ENOMEM;
+	if (ov51x_alloc(ov))
+		goto out;
+
+	ov->sub_flag = 0;
+
+	/* In case app doesn't set them... */
+	if (ov51x_set_default_params(ov) < 0)
+		goto out;
+
+	/* Make sure frames are reset */
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov->frame[i].grabstate = FRAME_UNUSED;
+		ov->frame[i].bytes_read = 0;
+	}
+
+	/* If compression is on, make sure now that a 
+	 * decompressor can be loaded */
+	if (ov->compress && !ov->decomp_ops) {
+		err = request_decompressor(ov);
+		if (err && !dumppix)
+			goto out;
+	}
+
+	err = ov51x_init_isoc(ov);
+	if (err) {
+		ov51x_dealloc(ov, 0);
+		goto out;
+	}
+
+	ov->user++;
+	file->private_data = vdev;
+	
+	if (ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 1);
+
+out:
+	up(&ov->lock);
+	return err;
+}
+
+static int 
+ov51x_v4l1_close(struct inode *inode, struct file *file)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_ov511 *ov = vdev->priv;
+
+	PDEBUG(4, "ov511_close");
+	
+	down(&ov->lock);
+
+	ov->user--;
+	ov51x_stop_isoc(ov);
+
+	release_decompressor(ov);
+
+	if (ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 0);
+
+	if (ov->dev)
+		ov51x_dealloc(ov, 0);
+
+	up(&ov->lock);
+
+	/* Device unplugged while open. Only a minimum of unregistration is done
+	 * here; the disconnect callback already did the rest. */
+	if (!ov->dev) {
+		down(&ov->cbuf_lock);
+		kfree(ov->cbuf);
+		ov->cbuf = NULL;
+		up(&ov->cbuf_lock);
+
+		ov51x_dealloc(ov, 1);
+		kfree(ov);
+		ov = NULL;
+	}
+	file->private_data = NULL;
+
+	return 0;
+}
+
+/* Do not call this function directly! */
+static int 
+ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
+			  unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_ov511 *ov = vdev->priv;
+	PDEBUG(5, "IOCtl: 0x%X", cmd);
+
+	if (!ov->dev)
+		return -EIO;	
+
+	switch (cmd) {
+	case VIDIOCGCAP:
+	{
+		struct video_capability *b = arg;
+
+		PDEBUG(4, "VIDIOCGCAP");
+
+		memset(b, 0, sizeof(struct video_capability));
+		sprintf(b->name, "%s USB Camera",
+			symbolic(brglist, ov->bridge));
+		b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
+		if (ov->has_tuner)
+			b->type |= VID_TYPE_TUNER;
+		b->channels = ov->num_inputs;
+		b->audios = ov->has_audio_proc ? 1:0;
+		b->maxwidth = ov->maxwidth;
+		b->maxheight = ov->maxheight;
+		b->minwidth = ov->minwidth;
+		b->minheight = ov->minheight;
+
+		return 0;
+	}
+	case VIDIOCGCHAN:
+	{
+		struct video_channel *v = arg;
+
+		PDEBUG(4, "VIDIOCGCHAN");
+
+		if ((unsigned)(v->channel) >= ov->num_inputs) {
+			err("Invalid channel (%d)", v->channel);
+			return -EINVAL;
+		}
+
+		v->norm = ov->norm;
+		v->type = (ov->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
+		v->flags = (ov->has_tuner) ? VIDEO_VC_TUNER : 0;
+		v->flags |= (ov->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
+//		v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0;
+		v->tuners = (ov->has_tuner) ? 1:0;
+		decoder_get_input_name(ov, v->channel, v->name);
+
+		return 0;
+	}
+	case VIDIOCSCHAN:
+	{
+		struct video_channel *v = arg;
+		int err;
+
+		PDEBUG(4, "VIDIOCSCHAN");
+
+		/* Make sure it's not a camera */
+		if (!ov->has_decoder) {
+			if (v->channel == 0)
+				return 0;
+			else
+				return -EINVAL;
+		}
+
+		if (v->norm != VIDEO_MODE_PAL &&
+		    v->norm != VIDEO_MODE_NTSC &&
+		    v->norm != VIDEO_MODE_SECAM &&
+		    v->norm != VIDEO_MODE_AUTO) {
+			err("Invalid norm (%d)", v->norm);
+			return -EINVAL;
+		}
+
+		if ((unsigned)(v->channel) >= ov->num_inputs) {
+			err("Invalid channel (%d)", v->channel);
+			return -EINVAL;
+		}
+
+		err = decoder_set_input(ov, v->channel);
+		if (err)
+			return err;
+
+		err = decoder_set_norm(ov, v->norm);
+		if (err)
+			return err;
+
+		return 0;
+	}
+	case VIDIOCGPICT:
+	{
+		struct video_picture *p = arg;
+
+		PDEBUG(4, "VIDIOCGPICT");
+
+		memset(p, 0, sizeof(struct video_picture));
+		if (sensor_get_picture(ov, p))
+			return -EIO;
+
+		return 0;
+	}
+	case VIDIOCSPICT:
+	{
+		struct video_picture *p = arg;
+		int i;
+
+		PDEBUG(4, "VIDIOCSPICT");
+
+		if (!get_depth(p->palette))
+			return -EINVAL;
+
+		if (sensor_set_picture(ov, p))
+			return -EIO;
+
+		if (force_palette && p->palette != force_palette) {
+			info("Palette rejected (%s)",
+			     symbolic(v4l1_plist, p->palette));
+			return -EINVAL;
+		}
+
+		// FIXME: Format should be independent of frames
+		if (p->palette != ov->frame[0].format) {
+			PDEBUG(4, "Detected format change");
+
+			/* If we're collecting previous frame wait
+			   before changing modes */
+			interruptible_sleep_on(&ov->wq);
+			if (signal_pending(current)) return -EINTR;
+
+			mode_init_regs(ov, ov->frame[0].width,
+				ov->frame[0].height, p->palette, ov->sub_flag);
+		}
+
+		PDEBUG(4, "Setting depth=%d, palette=%s",
+		       p->depth, symbolic(v4l1_plist, p->palette));
+
+		for (i = 0; i < OV511_NUMFRAMES; i++) {
+			ov->frame[i].depth = p->depth;
+			ov->frame[i].format = p->palette;
+		}
+
+		return 0;
+	}
+	case VIDIOCGCAPTURE:
+	{
+		int *vf = arg;
+
+		PDEBUG(4, "VIDIOCGCAPTURE");
+
+		ov->sub_flag = *vf;
+		return 0;
+	}
+	case VIDIOCSCAPTURE:
+	{
+		struct video_capture *vc = arg;
+
+		PDEBUG(4, "VIDIOCSCAPTURE");
+
+		if (vc->flags)
+			return -EINVAL;
+		if (vc->decimation)
+			return -EINVAL;
+
+		vc->x &= ~3L;
+		vc->y &= ~1L;
+		vc->y &= ~31L;
+
+		if (vc->width == 0)
+			vc->width = 32;
+
+		vc->height /= 16;
+		vc->height *= 16;
+		if (vc->height == 0)
+			vc->height = 16;
+
+		ov->subx = vc->x;
+		ov->suby = vc->y;
+		ov->subw = vc->width;
+		ov->subh = vc->height;
+
+		return 0;
+	}
+	case VIDIOCSWIN:
+	{
+		struct video_window *vw = arg;
+		int i, result;
+
+		PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height);
+
+#if 0
+		if (vw->flags)
+			return -EINVAL;
+		if (vw->clipcount)
+			return -EINVAL;
+		if (vw->height != ov->maxheight)
+			return -EINVAL;
+		if (vw->width != ov->maxwidth)
+			return -EINVAL;
+#endif
+
+		/* If we're collecting previous frame wait
+		   before changing modes */
+		interruptible_sleep_on(&ov->wq);
+		if (signal_pending(current)) return -EINTR;
+
+		result = mode_init_regs(ov, vw->width, vw->height,
+			ov->frame[0].format, ov->sub_flag);
+		if (result < 0)
+			return result;
+
+		for (i = 0; i < OV511_NUMFRAMES; i++) {
+			ov->frame[i].width = vw->width;
+			ov->frame[i].height = vw->height;
+		}
+
+		return 0;
+	}
+	case VIDIOCGWIN:
+	{
+		struct video_window *vw = arg;
+
+		memset(vw, 0, sizeof(struct video_window));
+		vw->x = 0;		/* FIXME */
+		vw->y = 0;
+		vw->width = ov->frame[0].width;
+		vw->height = ov->frame[0].height;
+		vw->flags = 30;
+
+		PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height);
+
+		return 0;
+	}
+	case VIDIOCGMBUF:
+	{
+		struct video_mbuf *vm = arg;
+		int i;
+
+		PDEBUG(4, "VIDIOCGMBUF");
+
+		memset(vm, 0, sizeof(struct video_mbuf));
+		vm->size = OV511_NUMFRAMES
+			   * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
+		vm->frames = OV511_NUMFRAMES;
+
+		vm->offsets[0] = 0;
+		for (i = 1; i < OV511_NUMFRAMES; i++) {
+			vm->offsets[i] = vm->offsets[i-1]
+			   + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
+		}
+
+		return 0;
+	}
+	case VIDIOCMCAPTURE:
+	{
+		struct video_mmap *vm = arg;
+		int ret, depth;
+		unsigned int f = vm->frame;
+
+		PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width,
+			vm->height, symbolic(v4l1_plist, vm->format));
+
+		depth = get_depth(vm->format);
+		if (!depth) {
+			err("VIDIOCMCAPTURE: invalid format (%s)",
+			    symbolic(v4l1_plist, vm->format));
+			return -EINVAL;
+		}
+
+		if (f >= OV511_NUMFRAMES) {
+			err("VIDIOCMCAPTURE: invalid frame (%d)", f);
+			return -EINVAL;
+		}
+
+		if (vm->width > ov->maxwidth 
+		    || vm->height > ov->maxheight) {
+			err("VIDIOCMCAPTURE: requested dimensions too big");
+			return -EINVAL;
+		}
+
+		if (ov->frame[f].grabstate == FRAME_GRABBING) {
+			PDEBUG(4, "VIDIOCMCAPTURE: already grabbing");
+			return -EBUSY;
+		}
+
+		if (force_palette && (vm->format != force_palette)) {
+			info("palette rejected (%s)",
+			     symbolic(v4l1_plist, vm->format));
+			return -EINVAL;
+		}
+
+		if ((ov->frame[f].width != vm->width) ||
+		    (ov->frame[f].height != vm->height) ||
+		    (ov->frame[f].format != vm->format) ||
+		    (ov->frame[f].sub_flag != ov->sub_flag) ||
+		    (ov->frame[f].depth != depth)) {
+			PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters");
+
+			/* If we're collecting previous frame wait
+			   before changing modes */
+			interruptible_sleep_on(&ov->wq);
+			if (signal_pending(current)) return -EINTR;
+			ret = mode_init_regs(ov, vm->width, vm->height,
+				vm->format, ov->sub_flag);
+#if 0
+			if (ret < 0) {
+				PDEBUG(1, "Got error while initializing regs ");
+				return ret;
+			}
+#endif
+			ov->frame[f].width = vm->width;
+			ov->frame[f].height = vm->height;
+			ov->frame[f].format = vm->format;
+			ov->frame[f].sub_flag = ov->sub_flag;
+			ov->frame[f].depth = depth;
+		}
+
+		/* Mark it as ready */
+		ov->frame[f].grabstate = FRAME_READY;
+
+		PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f);
+
+		return ov51x_new_frame(ov, f);
+	}
+	case VIDIOCSYNC:
+	{
+		unsigned int fnum = *((unsigned int *) arg);
+		struct ov511_frame *frame;
+		int rc;
+
+
+		if (fnum >= OV511_NUMFRAMES) {
+			err("VIDIOCSYNC: invalid frame (%d)", fnum);
+			return -EINVAL;
+		}
+
+		frame = &ov->frame[fnum];
+
+		PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum,
+		       frame->grabstate);
+
+		switch (frame->grabstate) {
+		case FRAME_UNUSED:
+			return -EINVAL;
+		case FRAME_READY:
+		case FRAME_GRABBING:
+		case FRAME_ERROR:
+redo:
+			if (!ov->dev)
+				return -EIO;
+
+			rc = wait_event_interruptible(frame->wq,
+			    (frame->grabstate == FRAME_DONE)
+			    || (frame->grabstate == FRAME_ERROR));
+
+			if (rc)
+				return rc;
+
+			if (frame->grabstate == FRAME_ERROR) {
+				int ret;
+
+				if ((ret = ov51x_new_frame(ov, fnum)) < 0)
+					return ret;
+				goto redo;
+			}
+			/* Fall through */			
+		case FRAME_DONE:
+			if (ov->snap_enabled && !frame->snapshot) {
+				int ret;
+				if ((ret = ov51x_new_frame(ov, fnum)) < 0)
+					return ret;
+				goto redo;
+			}
+
+			frame->grabstate = FRAME_UNUSED;
+
+			/* Reset the hardware snapshot button */
+			/* FIXME - Is this the best place for this? */
+			if ((ov->snap_enabled) && (frame->snapshot)) {
+				frame->snapshot = 0;
+				ov51x_clear_snapshot(ov);
+			}
+
+			/* Decompression, format conversion, etc... */
+			ov51x_postprocess(ov, frame);
+
+			break;
+		} /* end switch */
+
+		return 0;
+	}
+	case VIDIOCGFBUF:
+	{
+		struct video_buffer *vb = arg;
+
+		PDEBUG(4, "VIDIOCGFBUF");
+
+		memset(vb, 0, sizeof(struct video_buffer));
+
+		return 0;
+	}
+	case VIDIOCGUNIT:
+	{
+		struct video_unit *vu = arg;
+
+		PDEBUG(4, "VIDIOCGUNIT");
+
+		memset(vu, 0, sizeof(struct video_unit));
+
+		vu->video = ov->vdev.minor;
+		vu->vbi = VIDEO_NO_UNIT;
+		vu->radio = VIDEO_NO_UNIT;
+		vu->audio = VIDEO_NO_UNIT;
+		vu->teletext = VIDEO_NO_UNIT;
+
+		return 0;
+	}
+	case VIDIOCGTUNER:
+	{
+		struct video_tuner *v = arg;
+
+		PDEBUG(4, "VIDIOCGTUNER");
+
+		if (!ov->has_tuner || v->tuner)	// Only tuner 0
+			return -EINVAL;
+
+		strcpy(v->name, "Television");
+
+		// FIXME: Need a way to get the real values
+		v->rangelow = 0;
+		v->rangehigh = ~0;
+
+		v->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC
+			   | VIDEO_TUNER_SECAM;
+		v->mode = 0; 		/* FIXME:  Not sure what this is yet */
+		v->signal = 0xFFFF;	/* unknown */
+
+		call_i2c_clients(ov, cmd, v);
+
+		return 0;
+	}
+	case VIDIOCSTUNER:
+	{
+		struct video_tuner *v = arg;
+		int err;
+
+		PDEBUG(4, "VIDIOCSTUNER");
+
+		/* Only no or one tuner for now */
+		if (!ov->has_tuner || v->tuner)
+			return -EINVAL;
+
+		/* and it only has certain valid modes */
+		if (v->mode != VIDEO_MODE_PAL &&
+		    v->mode != VIDEO_MODE_NTSC &&
+		    v->mode != VIDEO_MODE_SECAM)
+			return -EOPNOTSUPP;
+
+		/* Is this right/necessary? */
+		err = decoder_set_norm(ov, v->mode);
+		if (err)
+			return err;
+
+		call_i2c_clients(ov, cmd, v);
+
+		return 0;
+	}
+	case VIDIOCGFREQ:
+	{
+		unsigned long v = *((unsigned long *) arg);
+
+		PDEBUG(4, "VIDIOCGFREQ");
+
+		if (!ov->has_tuner)
+			return -EINVAL;
+
+		v = ov->freq;
+#if 0
+		/* FIXME: this is necessary for testing */
+		v = 46*16;
+#endif
+		return 0;
+	}
+	case VIDIOCSFREQ:
+	{
+		unsigned long v = *((unsigned long *) arg);
+
+		PDEBUG(4, "VIDIOCSFREQ: %lx", v);
+
+		if (!ov->has_tuner)
+			return -EINVAL;
+
+		ov->freq = v;
+		call_i2c_clients(ov, cmd, &v);
+
+		return 0;
+	}
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+	{
+		/* FIXME: Implement this... */
+		return 0;
+	}
+	default:
+		PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd);
+		return -ENOIOCTLCMD;
+	} /* end switch */
+
+	return 0;
+}
+
+static int 
+ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
+		 unsigned int cmd, unsigned long arg)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_ov511 *ov = vdev->priv;
+	int rc;
+
+	if (down_interruptible(&ov->lock))
+		return -EINTR;
+
+	rc = video_usercopy(inode, file, cmd, arg, ov51x_v4l1_ioctl_internal);
+
+	up(&ov->lock);
+	return rc;
+}
+
+static inline int 
+ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
+{
+	struct video_device *vdev = file->private_data;
+	int noblock = file->f_flags&O_NONBLOCK;
+	unsigned long count = cnt;
+	struct usb_ov511 *ov = vdev->priv;
+	int i, rc = 0, frmx = -1;
+	struct ov511_frame *frame;
+
+	if (down_interruptible(&ov->lock))
+		return -EINTR;
+
+	PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
+
+	if (!vdev || !buf) {
+		rc = -EFAULT;
+		goto error;
+	}
+
+	if (!ov->dev) {
+		rc = -EIO;
+		goto error;
+	}
+
+// FIXME: Only supports two frames
+	/* See if a frame is completed, then use it. */
+	if (ov->frame[0].grabstate >= FRAME_DONE)	/* _DONE or _ERROR */
+		frmx = 0;
+	else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
+		frmx = 1;
+
+	/* If nonblocking we return immediately */
+	if (noblock && (frmx == -1)) {
+		rc = -EAGAIN;
+		goto error;
+	}
+
+	/* If no FRAME_DONE, look for a FRAME_GRABBING state. */
+	/* See if a frame is in process (grabbing), then use it. */
+	if (frmx == -1) {
+		if (ov->frame[0].grabstate == FRAME_GRABBING)
+			frmx = 0;
+		else if (ov->frame[1].grabstate == FRAME_GRABBING)
+			frmx = 1;
+	}
+
+	/* If no frame is active, start one. */
+	if (frmx == -1) {
+		if ((rc = ov51x_new_frame(ov, frmx = 0))) {
+			err("read: ov51x_new_frame error");
+			goto error;
+		}
+	}
+
+	frame = &ov->frame[frmx];
+
+restart:
+	if (!ov->dev) {
+		rc = -EIO;
+		goto error;
+	}
+
+	/* Wait while we're grabbing the image */
+	PDEBUG(4, "Waiting image grabbing");
+	rc = wait_event_interruptible(frame->wq, 
+		(frame->grabstate == FRAME_DONE)
+		|| (frame->grabstate == FRAME_ERROR));
+
+	if (rc)
+		goto error;
+
+	PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
+	PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd);
+
+	if (frame->grabstate == FRAME_ERROR) {
+		frame->bytes_read = 0;
+		err("** ick! ** Errored frame %d", ov->curframe);
+		if (ov51x_new_frame(ov, frmx)) {
+			err("read: ov51x_new_frame error");
+			goto error;
+		}
+		goto restart;
+	}
+
+
+	/* Repeat until we get a snapshot frame */
+	if (ov->snap_enabled)
+		PDEBUG(4, "Waiting snapshot frame");
+	if (ov->snap_enabled && !frame->snapshot) {
+		frame->bytes_read = 0;
+		if ((rc = ov51x_new_frame(ov, frmx))) {
+			err("read: ov51x_new_frame error");
+			goto error;
+		}
+		goto restart;
+	}
+
+	/* Clear the snapshot */
+	if (ov->snap_enabled && frame->snapshot) {
+		frame->snapshot = 0;
+		ov51x_clear_snapshot(ov);
+	}
+
+	/* Decompression, format conversion, etc... */
+	ov51x_postprocess(ov, frame);
+
+	PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx,
+		frame->bytes_read,
+		get_frame_length(frame));
+
+	/* copy bytes to user space; we allow for partials reads */
+//	if ((count + frame->bytes_read) 
+//	    > get_frame_length((struct ov511_frame *)frame))
+//		count = frame->scanlength - frame->bytes_read;
+
+	/* FIXME - count hardwired to be one frame... */
+	count = get_frame_length(frame);
+
+	PDEBUG(4, "Copy to user space: %ld bytes", count);
+	if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
+		PDEBUG(4, "Copy failed! %d bytes not copied", i);
+		rc = -EFAULT;
+		goto error;
+	}
+
+	frame->bytes_read += count;
+	PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
+		count, frame->bytes_read);
+
+	/* If all data has been read... */
+	if (frame->bytes_read
+	    >= get_frame_length(frame)) {
+		frame->bytes_read = 0;
+
+// FIXME: Only supports two frames
+		/* Mark it as available to be used again. */
+		ov->frame[frmx].grabstate = FRAME_UNUSED;
+		if ((rc = ov51x_new_frame(ov, !frmx))) {
+			err("ov51x_new_frame returned error");
+			goto error;
+		}
+	}
+
+	PDEBUG(4, "read finished, returning %ld (sweet)", count);
+
+	up(&ov->lock);
+	return count;
+
+error:
+	up(&ov->lock);
+	return rc;
+}
+
+static int
+ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *vdev = file->private_data;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end - vma->vm_start;
+	struct usb_ov511 *ov = vdev->priv;
+	unsigned long page, pos;
+
+	if (ov->dev == NULL)
+		return -EIO;
+
+	PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
+
+	if (size > (((OV511_NUMFRAMES
+	              * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
+	              + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
+		return -EINVAL;
+
+	if (down_interruptible(&ov->lock))
+		return -EINTR;
+
+	pos = (unsigned long)ov->fbuf;
+	while (size > 0) {
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(vma, start, page, PAGE_SIZE,
+				     PAGE_SHARED)) {
+			up(&ov->lock);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	up(&ov->lock);
+	return 0;
+}
+
+static struct file_operations ov511_fops = {
+	owner:		THIS_MODULE,
+	open:		ov51x_v4l1_open,
+	release:       	ov51x_v4l1_close,
+	read:		ov51x_v4l1_read,
+	mmap:		ov51x_v4l1_mmap,
+	ioctl:          ov51x_v4l1_ioctl,
+	llseek:         no_llseek,
+};
+
+static struct video_device vdev_template = {
+	owner:		THIS_MODULE,
+	name:		"OV511 USB Camera",
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_OV511,
+	fops:           &ov511_fops,
+};
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+static int 
+ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		    unsigned long ularg)
+{
+	struct proc_dir_entry *pde;
+	struct usb_ov511 *ov;
+	void *arg = (void *) ularg;
+	int rc;
+
+	pde = PDE(inode);
+	if (!pde)
+		return -ENOENT;
+
+	ov = pde->data;
+	if (!ov)
+		return -ENODEV;
+
+	if (!ov->dev)
+		return -EIO;
+
+	/* Should we pass through standard V4L IOCTLs? */
+
+	switch (cmd) {
+	case OV511IOC_GINTVER:
+	{
+		int ver = OV511_INTERFACE_VER;
+
+		PDEBUG(4, "Get interface version: %d", ver);
+		if (copy_to_user(arg, &ver, sizeof(ver)))
+			return -EFAULT;
+
+		return 0;
+	}
+	case OV511IOC_GUSHORT:
+	{
+		struct ov511_ushort_opt opt;
+
+		if (copy_from_user(&opt, arg, sizeof(opt)))
+			return -EFAULT;
+
+		switch (opt.optnum) {
+		case OV511_USOPT_BRIGHT:
+			rc = sensor_get_brightness(ov, &(opt.val));
+			if (rc)	return rc;
+			break;
+		case OV511_USOPT_SAT:
+			rc = sensor_get_saturation(ov, &(opt.val));
+			if (rc)	return rc;
+			break;
+		case OV511_USOPT_HUE:
+			rc = sensor_get_hue(ov, &(opt.val));
+			if (rc)	return rc;
+			break;
+		case OV511_USOPT_CONTRAST:
+			rc = sensor_get_contrast(ov, &(opt.val));
+			if (rc)	return rc;
+			break;
+		default:
+			err("Invalid get short option number");
+			return -EINVAL;
+		}
+
+		if (copy_to_user(arg, &opt, sizeof(opt)))
+			return -EFAULT;
+
+		return 0;
+	}
+	case OV511IOC_SUSHORT:
+	{
+		struct ov511_ushort_opt opt;
+
+		if (copy_from_user(&opt, arg, sizeof(opt)))
+			return -EFAULT;
+
+		switch (opt.optnum) {
+		case OV511_USOPT_BRIGHT:
+			rc = sensor_set_brightness(ov, opt.val);
+			if (rc)	return rc;
+			break;
+		case OV511_USOPT_SAT:
+			rc = sensor_set_saturation(ov, opt.val);
+			if (rc)	return rc;
+			break;
+		case OV511_USOPT_HUE:
+			rc = sensor_set_hue(ov, opt.val);
+			if (rc)	return rc;
+			break;
+		case OV511_USOPT_CONTRAST:
+			rc = sensor_set_contrast(ov, opt.val);
+			if (rc)	return rc;
+			break;
+		default:
+			err("Invalid set short option number");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+	case OV511IOC_GUINT:
+	{
+		struct ov511_uint_opt opt;
+
+		if (copy_from_user(&opt, arg, sizeof(opt)))
+			return -EFAULT;
+
+		switch (opt.optnum) {
+		case OV511_UIOPT_POWER_FREQ:
+			opt.val = ov->lightfreq;
+			break;
+		case OV511_UIOPT_BFILTER:
+			opt.val = ov->bandfilt;
+			break;
+		case OV511_UIOPT_LED:
+			opt.val = ov->led_policy;
+			break;
+		case OV511_UIOPT_DEBUG:
+			opt.val = debug;
+			break;
+		case OV511_UIOPT_COMPRESS:
+			opt.val = ov->compress;
+			break;
+		default:
+			err("Invalid get int option number");
+			return -EINVAL;
+		}
+
+		if (copy_to_user(arg, &opt, sizeof(opt)))
+			return -EFAULT;
+
+		return 0;
+	}
+	case OV511IOC_SUINT:
+	{
+		struct ov511_uint_opt opt;
+
+		if (copy_from_user(&opt, arg, sizeof(opt)))
+			return -EFAULT;
+
+		switch (opt.optnum) {
+		case OV511_UIOPT_POWER_FREQ:
+			rc = sensor_set_light_freq(ov, opt.val);
+			if (rc)	return rc;
+			break;
+		case OV511_UIOPT_BFILTER:
+			rc = sensor_set_banding_filter(ov, opt.val);
+			if (rc)	return rc;
+			break;
+		case OV511_UIOPT_LED:
+			if (opt.val <= 2) {
+				ov->led_policy = opt.val;
+				if (ov->led_policy == LED_OFF)
+					ov51x_led_control(ov, 0);
+				else if (ov->led_policy == LED_ON)
+					ov51x_led_control(ov, 1);
+			} else {
+				return -EINVAL;
+			}
+			break;
+		case OV511_UIOPT_DEBUG:
+			if (opt.val <= 5)
+				debug = opt.val;
+			else
+				return -EINVAL;
+			break;
+		case OV511_UIOPT_COMPRESS:
+			ov->compress = opt.val;
+			if (ov->compress) {
+				if (ov->bclass == BCL_OV511)
+					ov511_init_compression(ov);
+				else if (ov->bclass == BCL_OV518)
+					ov518_init_compression(ov);
+			}
+			break;
+		default:
+			err("Invalid get int option number");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+	case OV511IOC_WI2C:
+	{
+		struct ov511_i2c_struct w;
+
+		if (copy_from_user(&w, arg, sizeof(w)))
+			return -EFAULT;
+
+		return i2c_w_slave(ov, w.slave, w.reg, w.value,
+			w.mask);
+	}
+	case OV511IOC_RI2C:
+	{
+		struct ov511_i2c_struct r;
+
+		if (copy_from_user(&r, arg, sizeof(r)))
+			return -EFAULT;
+
+		rc = i2c_r_slave(ov, r.slave, r.reg);
+		if (rc < 0)
+			return rc;
+
+		r.value = rc;
+
+		if (copy_to_user(arg, &r, sizeof(r)))
+			return -EFAULT;
+
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	} /* end switch */
+
+	return 0;
+}
+#endif
+
+/****************************************************************************
+ *
+ * OV511 and sensor configuration
+ *
+ ***************************************************************************/
+
+/* This initializes the OV7610, OV7620, or OV7620AE sensor. The OV7620AE uses
+ * the same register settings as the OV7610, since they are very similar.
+ */
+static int 
+ov7xx0_configure(struct usb_ov511 *ov)
+{
+	int i, success;
+	int rc;
+
+	/* Lawrence Glaister <lg@jfm.bc.ca> reports:
+	 *
+	 * Register 0x0f in the 7610 has the following effects:
+	 *
+	 * 0x85 (AEC method 1): Best overall, good contrast range
+	 * 0x45 (AEC method 2): Very overexposed
+	 * 0xa5 (spec sheet default): Ok, but the black level is
+	 *	shifted resulting in loss of contrast
+	 * 0x05 (old driver setting): very overexposed, too much
+	 *	contrast
+	 */
+	static struct ov511_regvals aRegvalsNorm7610[] = {
+		{ OV511_I2C_BUS, 0x10, 0xff },
+		{ OV511_I2C_BUS, 0x16, 0x06 },
+		{ OV511_I2C_BUS, 0x28, 0x24 },
+		{ OV511_I2C_BUS, 0x2b, 0xac },
+		{ OV511_I2C_BUS, 0x12, 0x00 },
+		{ OV511_I2C_BUS, 0x38, 0x81 },
+		{ OV511_I2C_BUS, 0x28, 0x24 },	/* 0c */
+		{ OV511_I2C_BUS, 0x0f, 0x85 },	/* lg's setting */
+		{ OV511_I2C_BUS, 0x15, 0x01 },
+		{ OV511_I2C_BUS, 0x20, 0x1c },
+		{ OV511_I2C_BUS, 0x23, 0x2a },
+		{ OV511_I2C_BUS, 0x24, 0x10 },
+		{ OV511_I2C_BUS, 0x25, 0x8a },
+		{ OV511_I2C_BUS, 0x26, 0xa2 },
+		{ OV511_I2C_BUS, 0x27, 0xc2 },
+		{ OV511_I2C_BUS, 0x2a, 0x04 },
+		{ OV511_I2C_BUS, 0x2c, 0xfe },
+		{ OV511_I2C_BUS, 0x2d, 0x93 },
+		{ OV511_I2C_BUS, 0x30, 0x71 },
+		{ OV511_I2C_BUS, 0x31, 0x60 },
+		{ OV511_I2C_BUS, 0x32, 0x26 },
+		{ OV511_I2C_BUS, 0x33, 0x20 },
+		{ OV511_I2C_BUS, 0x34, 0x48 },
+		{ OV511_I2C_BUS, 0x12, 0x24 },
+		{ OV511_I2C_BUS, 0x11, 0x01 },
+		{ OV511_I2C_BUS, 0x0c, 0x24 },
+		{ OV511_I2C_BUS, 0x0d, 0x24 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	static struct ov511_regvals aRegvalsNorm7620[] = {
+		{ OV511_I2C_BUS, 0x00, 0x00 },
+		{ OV511_I2C_BUS, 0x01, 0x80 },
+		{ OV511_I2C_BUS, 0x02, 0x80 },
+		{ OV511_I2C_BUS, 0x03, 0xc0 },
+		{ OV511_I2C_BUS, 0x06, 0x60 },
+		{ OV511_I2C_BUS, 0x07, 0x00 },
+		{ OV511_I2C_BUS, 0x0c, 0x24 },
+		{ OV511_I2C_BUS, 0x0c, 0x24 },
+		{ OV511_I2C_BUS, 0x0d, 0x24 },
+		{ OV511_I2C_BUS, 0x11, 0x01 },
+		{ OV511_I2C_BUS, 0x12, 0x24 },
+		{ OV511_I2C_BUS, 0x13, 0x01 },
+		{ OV511_I2C_BUS, 0x14, 0x84 },
+		{ OV511_I2C_BUS, 0x15, 0x01 },
+		{ OV511_I2C_BUS, 0x16, 0x03 },
+		{ OV511_I2C_BUS, 0x17, 0x2f },
+		{ OV511_I2C_BUS, 0x18, 0xcf },
+		{ OV511_I2C_BUS, 0x19, 0x06 },
+		{ OV511_I2C_BUS, 0x1a, 0xf5 },
+		{ OV511_I2C_BUS, 0x1b, 0x00 },
+		{ OV511_I2C_BUS, 0x20, 0x18 },
+		{ OV511_I2C_BUS, 0x21, 0x80 },
+		{ OV511_I2C_BUS, 0x22, 0x80 },
+		{ OV511_I2C_BUS, 0x23, 0x00 },
+		{ OV511_I2C_BUS, 0x26, 0xa2 },
+		{ OV511_I2C_BUS, 0x27, 0xea },
+		{ OV511_I2C_BUS, 0x28, 0x20 },
+		{ OV511_I2C_BUS, 0x29, 0x00 },
+		{ OV511_I2C_BUS, 0x2a, 0x10 },
+		{ OV511_I2C_BUS, 0x2b, 0x00 },
+		{ OV511_I2C_BUS, 0x2c, 0x88 },
+		{ OV511_I2C_BUS, 0x2d, 0x91 },
+		{ OV511_I2C_BUS, 0x2e, 0x80 },
+		{ OV511_I2C_BUS, 0x2f, 0x44 },
+		{ OV511_I2C_BUS, 0x60, 0x27 },
+		{ OV511_I2C_BUS, 0x61, 0x02 },
+		{ OV511_I2C_BUS, 0x62, 0x5f },
+		{ OV511_I2C_BUS, 0x63, 0xd5 },
+		{ OV511_I2C_BUS, 0x64, 0x57 },
+		{ OV511_I2C_BUS, 0x65, 0x83 },
+		{ OV511_I2C_BUS, 0x66, 0x55 },
+		{ OV511_I2C_BUS, 0x67, 0x92 },
+		{ OV511_I2C_BUS, 0x68, 0xcf },
+		{ OV511_I2C_BUS, 0x69, 0x76 },
+		{ OV511_I2C_BUS, 0x6a, 0x22 },
+		{ OV511_I2C_BUS, 0x6b, 0x00 },
+		{ OV511_I2C_BUS, 0x6c, 0x02 },
+		{ OV511_I2C_BUS, 0x6d, 0x44 },
+		{ OV511_I2C_BUS, 0x6e, 0x80 },
+		{ OV511_I2C_BUS, 0x6f, 0x1d },
+		{ OV511_I2C_BUS, 0x70, 0x8b },
+		{ OV511_I2C_BUS, 0x71, 0x00 },
+		{ OV511_I2C_BUS, 0x72, 0x14 },
+		{ OV511_I2C_BUS, 0x73, 0x54 },
+		{ OV511_I2C_BUS, 0x74, 0x00 },
+		{ OV511_I2C_BUS, 0x75, 0x8e },
+		{ OV511_I2C_BUS, 0x76, 0x00 },
+		{ OV511_I2C_BUS, 0x77, 0xff },
+		{ OV511_I2C_BUS, 0x78, 0x80 },
+		{ OV511_I2C_BUS, 0x79, 0x80 },
+		{ OV511_I2C_BUS, 0x7a, 0x80 },
+		{ OV511_I2C_BUS, 0x7b, 0xe2 },
+		{ OV511_I2C_BUS, 0x7c, 0x00 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	PDEBUG(4, "starting configuration");
+
+	/* This looks redundant, but is necessary for WebCam 3 */
+	ov->primary_i2c_slave = OV7xx0_SID;
+	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
+		return -1;
+
+	if (init_ov_sensor(ov) >= 0) {
+		PDEBUG(1, "OV7xx0 sensor initalized (method 1)");
+	} else {
+		/* Reset the 76xx */
+		if (i2c_w(ov, 0x12, 0x80) < 0) return -1;
+
+		/* Wait for it to initialize */
+		schedule_timeout(1 + 150 * HZ / 1000);
+
+		i = 0;
+		success = 0;
+		while (i <= i2c_detect_tries) {
+			if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
+			    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
+				success = 1;
+				break;
+			} else {
+				i++;
+			}
+		}
+
+// Was (i == i2c_detect_tries) previously. This obviously used to always report
+// success. Whether anyone actually depended on that bug is unknown
+		if ((i >= i2c_detect_tries) && (success == 0)) {
+			err("Failed to read sensor ID. You might not have an");
+			err("OV7610/20, or it may be not responding. Report");
+			err("this to " EMAIL);
+			err("This is only a warning. You can attempt to use");
+			err("your camera anyway");
+// Only issue a warning for now  
+//			return -1;
+		} else {
+			PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1);
+		}
+	}
+
+	/* Detect sensor (sub)type */
+	rc = i2c_r(ov, OV7610_REG_COM_I);
+
+	if (rc < 0) {
+		err("Error detecting sensor type");
+		return -1;
+	} else if ((rc & 3) == 3) {
+		info("Sensor is an OV7610");
+		ov->sensor = SEN_OV7610;
+	} else if ((rc & 3) == 1) {
+		/* I don't know what's different about the 76BE yet */
+		if (i2c_r(ov, 0x15) & 1)
+			info("Sensor is an OV7620AE");
+		else
+			info("Sensor is an OV76BE");
+
+		/* OV511+ will return all zero isoc data unless we
+		 * configure the sensor as a 7620. Someone needs to
+		 * find the exact reg. setting that causes this. */
+		if (ov->bridge == BRG_OV511PLUS) {
+			info("Enabling 511+/7620AE workaround");
+			ov->sensor = SEN_OV7620;
+		} else {
+			ov->sensor = SEN_OV7620AE;
+		}
+	} else if ((rc & 3) == 0) {
+		info("Sensor is an OV7620");
+		ov->sensor = SEN_OV7620;
+	} else {
+		err("Unknown image sensor version: %d", rc & 3);
+		return -1;
+	}
+
+	if (ov->sensor == SEN_OV7620) {
+		PDEBUG(4, "Writing 7620 registers");
+		if (write_regvals(ov, aRegvalsNorm7620))
+			return -1;
+	} else {
+		PDEBUG(4, "Writing 7610 registers");
+		if (write_regvals(ov, aRegvalsNorm7610))
+			return -1;
+	}
+
+	/* Set sensor-specific vars */
+	ov->maxwidth = 640;
+	ov->maxheight = 480;
+	ov->minwidth = 64;
+	ov->minheight = 48;
+
+	// FIXME: These do not match the actual settings yet
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x80 << 8;
+	ov->colour = 0x80 << 8;
+	ov->hue = 0x80 << 8;
+
+	return 0;
+}
+
+/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
+static int 
+ov6xx0_configure(struct usb_ov511 *ov)
+{
+	int rc;
+
+	static struct ov511_regvals aRegvalsNorm6x20[] = {
+		{ OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
+		{ OV511_I2C_BUS, 0x11, 0x01 },
+		{ OV511_I2C_BUS, 0x03, 0x60 },
+		{ OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
+		{ OV511_I2C_BUS, 0x07, 0xa8 },
+		/* The ratio of 0x0c and 0x0d  controls the white point */
+		{ OV511_I2C_BUS, 0x0c, 0x24 },
+		{ OV511_I2C_BUS, 0x0d, 0x24 },
+		{ OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
+		{ OV511_I2C_BUS, 0x14, 0x04 },
+		/* 0x16: 0x06 helps frame stability with moving objects */
+		{ OV511_I2C_BUS, 0x16, 0x06 },
+//		{ OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
+		{ OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
+		/* 0x28: 0x05 Selects RGB format if RGB on */
+		{ OV511_I2C_BUS, 0x28, 0x05 },
+		{ OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
+//		{ OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
+		{ OV511_I2C_BUS, 0x2d, 0x99 },
+		{ OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */
+		{ OV511_I2C_BUS, 0x38, 0x8b },
+		{ OV511_I2C_BUS, 0x39, 0x40 },
+		
+		{ OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
+		{ OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
+		{ OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
+
+		{ OV511_I2C_BUS, 0x3d, 0x80 },
+		/* These next two registers (0x4a, 0x4b) are undocumented. They
+		 * control the color balance */
+		{ OV511_I2C_BUS, 0x4a, 0x80 },
+		{ OV511_I2C_BUS, 0x4b, 0x80 },
+		{ OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */
+		{ OV511_I2C_BUS, 0x4e, 0xc1 },
+		{ OV511_I2C_BUS, 0x4f, 0x04 },
+// Do 50-53 have any effect?
+// Toggle 0x12[2] off and on here?
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	/* This chip is undocumented so many of these are guesses. OK=verified,
+	 * A=Added since 6620, U=unknown function (not a 6620 reg) */
+	static struct ov511_regvals aRegvalsNorm6x30[] = {
+	/*OK*/	{ OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
+	/*00?*/	{ OV511_I2C_BUS, 0x11, 0x01 },
+	/*OK*/	{ OV511_I2C_BUS, 0x03, 0x60 },
+	/*0A?*/	{ OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
+		{ OV511_I2C_BUS, 0x07, 0xa8 },
+		/* The ratio of 0x0c and 0x0d  controls the white point */
+	/*OK*/	{ OV511_I2C_BUS, 0x0c, 0x24 },
+	/*OK*/	{ OV511_I2C_BUS, 0x0d, 0x24 },
+	/*A*/	{ OV511_I2C_BUS, 0x0e, 0x20 },
+
+//	/*24?*/	{ OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */
+//		{ OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
+
+//	/*A*/	{ OV511_I2C_BUS, 0x13, 0x21 },
+//	/*A*/	{ OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */
+
+//	/*04?*/	{ OV511_I2C_BUS, 0x14, 0x80 },
+		/* 0x16: 0x06 helps frame stability with moving objects */
+	/*03?*/	{ OV511_I2C_BUS, 0x16, 0x06 },
+//	/*OK*/	{ OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
+		// 21 & 22? The suggested values look wrong. Go with default
+	/*A*/	{ OV511_I2C_BUS, 0x23, 0xc0 },
+	/*A*/	{ OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default
+//	/*OK*/	{ OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
+
+		/* 0x28: 0x05 Selects RGB format if RGB on */
+//	/*04?*/	{ OV511_I2C_BUS, 0x28, 0x05 },
+//	/*04?*/	{ OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus
+
+	/*OK*/	{ OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
+//	/*OK*/	{ OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
+//	/*U*/	{ OV511_I2C_BUS, 0x2c, 0xa0 },
+		{ OV511_I2C_BUS, 0x2d, 0x99 },
+//	/*A*/	{ OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620
+//	/*d2?*/	{ OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */
+//	/*U*/	{ OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary
+//	/*U*/	{ OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary
+//	/*8b?*/	{ OV511_I2C_BUS, 0x38, 0x83 },
+//	/*40?*/	{ OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7
+//		{ OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
+//		{ OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
+//		{ OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
+	/*OK*/	{ OV511_I2C_BUS, 0x3d, 0x80 },
+//	/*A*/	{ OV511_I2C_BUS, 0x3f, 0x0e },
+//	/*U*/	{ OV511_I2C_BUS, 0x40, 0x00 },
+//	/*U*/	{ OV511_I2C_BUS, 0x41, 0x00 },
+//	/*U*/	{ OV511_I2C_BUS, 0x42, 0x80 },
+//	/*U*/	{ OV511_I2C_BUS, 0x43, 0x3f },
+//	/*U*/	{ OV511_I2C_BUS, 0x44, 0x80 },
+//	/*U*/	{ OV511_I2C_BUS, 0x45, 0x20 },
+//	/*U*/	{ OV511_I2C_BUS, 0x46, 0x20 },
+//	/*U*/	{ OV511_I2C_BUS, 0x47, 0x80 },
+//	/*U*/	{ OV511_I2C_BUS, 0x48, 0x7f },
+//	/*U*/	{ OV511_I2C_BUS, 0x49, 0x00 },
+
+		/* These next two registers (0x4a, 0x4b) are undocumented. They
+		 * control the color balance */
+//	/*OK?*/	{ OV511_I2C_BUS, 0x4a, 0x80 }, // Check these
+//	/*OK?*/	{ OV511_I2C_BUS, 0x4b, 0x80 },
+//	/*U*/	{ OV511_I2C_BUS, 0x4c, 0xd0 }, 
+	/*d2?*/	{ OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */
+	/*c1?*/	{ OV511_I2C_BUS, 0x4e, 0x40 },
+	/*04?*/	{ OV511_I2C_BUS, 0x4f, 0x07 },
+//	/*U*/	{ OV511_I2C_BUS, 0x50, 0xff },
+	/*U*/	{ OV511_I2C_BUS, 0x54, 0x23 },
+//	/*U*/	{ OV511_I2C_BUS, 0x55, 0xff },
+//	/*U*/	{ OV511_I2C_BUS, 0x56, 0x12 },
+	/*U*/	{ OV511_I2C_BUS, 0x57, 0x81 },
+//	/*U*/	{ OV511_I2C_BUS, 0x58, 0x75 },
+	/*U*/	{ OV511_I2C_BUS, 0x59, 0x01 },
+	/*U*/	{ OV511_I2C_BUS, 0x5a, 0x2c },
+	/*U*/	{ OV511_I2C_BUS, 0x5b, 0x0f },
+//	/*U*/	{ OV511_I2C_BUS, 0x5c, 0x10 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	PDEBUG(4, "starting sensor configuration");
+	
+	if (init_ov_sensor(ov) < 0) {
+		err("Failed to read sensor ID. You might not have an OV6xx0,");
+		err("or it may be not responding. Report this to " EMAIL);
+		return -1;
+	} else {
+		PDEBUG(1, "OV6xx0 sensor detected");
+	}
+
+	/* Detect sensor (sub)type */
+	rc = i2c_r(ov, OV7610_REG_COM_I);
+
+	if (rc < 0) {
+		err("Error detecting sensor type");
+		return -1;
+	} 
+
+	if ((rc & 3) == 0)
+		ov->sensor = SEN_OV6630;
+	else if ((rc & 3) == 1)
+		ov->sensor = SEN_OV6620;
+	else if ((rc & 3) == 2)
+		ov->sensor = SEN_OV6630;
+	else if ((rc & 3) == 3)
+		ov->sensor = SEN_OV6630;
+
+	info("Sensor is an %s", symbolic(senlist, ov->sensor));
+
+	/* Set sensor-specific vars */
+	ov->maxwidth = 352;
+	ov->maxheight = 288;
+	ov->minwidth = 64;
+	ov->minheight = 48;
+
+	// FIXME: These do not match the actual settings yet
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x80 << 8;
+	ov->colour = 0x80 << 8;
+	ov->hue = 0x80 << 8;
+
+	if (ov->sensor == SEN_OV6620) {
+		PDEBUG(4, "Writing 6x20 registers");
+		if (write_regvals(ov, aRegvalsNorm6x20))
+			return -1;
+	} else {
+		PDEBUG(4, "Writing 6x30 registers");
+		if (write_regvals(ov, aRegvalsNorm6x30))
+			return -1;
+	}
+	
+	return 0;
+}
+
+/* This initializes the KS0127 and KS0127B video decoders. */
+static int 
+ks0127_configure(struct usb_ov511 *ov)
+{
+	int rc;
+
+// FIXME: I don't know how to sync or reset it yet
+#if 0
+	if (ov51x_init_ks_sensor(ov) < 0) {
+		err("Failed to initialize the KS0127");
+		return -1;
+	} else {
+		PDEBUG(1, "KS012x(B) sensor detected");
+	}
+#endif
+
+	/* Detect decoder subtype */
+	rc = i2c_r(ov, 0x00);
+	if (rc < 0) {
+		err("Error detecting sensor type");
+		return -1;
+	} else if (rc & 0x08) {
+		rc = i2c_r(ov, 0x3d);
+		if (rc < 0) {
+			err("Error detecting sensor type");
+			return -1;
+		} else if ((rc & 0x0f) == 0) {
+			info("Sensor is a KS0127");
+			ov->sensor = SEN_KS0127;
+		} else if ((rc & 0x0f) == 9) {
+			info("Sensor is a KS0127B Rev. A");
+			ov->sensor = SEN_KS0127B;
+		}
+	} else {
+		err("Error: Sensor is an unsupported KS0122");
+		return -1;
+	}
+
+	/* Set sensor-specific vars */
+	ov->maxwidth = 640;
+	ov->maxheight = 480;
+	ov->minwidth = 64;
+	ov->minheight = 48;
+
+	// FIXME: These do not match the actual settings yet
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x80 << 8;
+	ov->colour = 0x80 << 8;
+	ov->hue = 0x80 << 8;
+
+	/* This device is not supported yet. Bail out now... */
+	err("This sensor is not supported yet.");
+	return -1;
+
+	return 0;
+}
+
+/* This initializes the SAA7111A video decoder. */
+static int 
+saa7111a_configure(struct usb_ov511 *ov)
+{
+	int rc;
+
+	/* Since there is no register reset command, all registers must be
+	 * written, otherwise gives erratic results */
+	static struct ov511_regvals aRegvalsNormSAA7111A[] = {
+		{ OV511_I2C_BUS, 0x06, 0xce },
+		{ OV511_I2C_BUS, 0x07, 0x00 },
+		{ OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */
+		{ OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */
+		{ OV511_I2C_BUS, 0x00, 0x00 },
+		{ OV511_I2C_BUS, 0x01, 0x00 },
+		{ OV511_I2C_BUS, 0x03, 0x23 },
+		{ OV511_I2C_BUS, 0x04, 0x00 },
+		{ OV511_I2C_BUS, 0x05, 0x00 },
+		{ OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */
+		{ OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */
+		{ OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */
+		{ OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */
+		{ OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */
+		{ OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */
+		{ OV511_I2C_BUS, 0x0f, 0x00 },
+		{ OV511_I2C_BUS, 0x11, 0x0c },
+		{ OV511_I2C_BUS, 0x12, 0x00 },
+		{ OV511_I2C_BUS, 0x13, 0x00 },
+		{ OV511_I2C_BUS, 0x14, 0x00 },
+		{ OV511_I2C_BUS, 0x15, 0x00 },
+		{ OV511_I2C_BUS, 0x16, 0x00 },
+		{ OV511_I2C_BUS, 0x17, 0x00 },
+		{ OV511_I2C_BUS, 0x02, 0xc0 },	/* Composite input 0 */
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+// FIXME: I don't know how to sync or reset it yet
+#if 0
+	if (ov51x_init_saa_sensor(ov) < 0) {
+		err("Failed to initialize the SAA7111A");
+		return -1;
+	} else {
+		PDEBUG(1, "SAA7111A sensor detected");
+	}
+#endif
+
+	/* Set sensor-specific vars */
+	ov->maxwidth = 640;
+	ov->maxheight = 480;		/* Even/Odd fields */
+	ov->minwidth = 320;
+	ov->minheight = 240;		/* Even field only */
+
+	ov->has_decoder = 1;
+	ov->num_inputs = 8;
+	ov->norm = VIDEO_MODE_AUTO;
+	ov->stop_during_set = 0;	/* Decoder guarantees stable image */
+
+	/* Decoder doesn't change these values, so we use these instead of
+	 * acutally reading the registers (which doesn't work) */
+	ov->brightness = 0x80 << 8;
+	ov->contrast = 0x40 << 9;
+	ov->colour = 0x40 << 9;
+	ov->hue = 32768;
+
+	PDEBUG(4, "Writing SAA7111A registers");
+	if (write_regvals(ov, aRegvalsNormSAA7111A))
+		return -1;
+
+	/* Detect version of decoder. This must be done after writing the
+         * initial regs or the decoder will lock up. */
+	rc = i2c_r(ov, 0x00);
+
+	if (rc < 0) {
+		err("Error detecting sensor version");
+		return -1;
+	} else {
+		info("Sensor is an SAA7111A (version 0x%x)", rc);
+		ov->sensor = SEN_SAA7111A;
+	}
+
+	// FIXME: Fix this for OV518(+)
+	/* Latch to negative edge of clock. Otherwise, we get incorrect
+	 * colors and jitter in the digital signal. */
+	if (ov->bclass == BCL_OV511)
+		reg_w(ov, 0x11, 0x00);
+	else
+		warn("SAA7111A not yet supported with OV518/OV518+");
+
+	return 0;
+}
+
+/* This initializes the OV511/OV511+ and the sensor */
+static int 
+ov511_configure(struct usb_ov511 *ov)
+{
+	static struct ov511_regvals aRegvalsInit511[] = {
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x7f },
+	 	{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
+	 	{ OV511_REG_BUS, R51x_SYS_RESET,	0x7f },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x3f },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x3d },
+		{ OV511_DONE_BUS, 0x0, 0x00},
+	};
+
+	static struct ov511_regvals aRegvalsNorm511[] = {
+		{ OV511_REG_BUS, R511_DRAM_FLOW_CTL, 	0x01 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x03 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R511_FIFO_OPTS,	0x1f },
+		{ OV511_REG_BUS, R511_COMP_EN,		0x00 },
+		{ OV511_REG_BUS, R511_COMP_LUT_EN,	0x03 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	static struct ov511_regvals aRegvalsNorm511Plus[] = {
+		{ OV511_REG_BUS, R511_DRAM_FLOW_CTL,	0xff },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x03 },
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
+		{ OV511_REG_BUS, R511_FIFO_OPTS,	0xff },
+		{ OV511_REG_BUS, R511_COMP_EN,		0x00 },
+		{ OV511_REG_BUS, R511_COMP_LUT_EN,	0x03 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	PDEBUG(4, "");
+
+	ov->customid = reg_r(ov, R511_SYS_CUST_ID);
+	if (ov->customid < 0) {
+		err("Unable to read camera bridge registers");
+		goto error;
+	}
+
+	PDEBUG (1, "CustomID = %d", ov->customid);
+	ov->desc = symbolic(camlist, ov->customid);
+	info("model: %s", ov->desc);
+
+	if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) {
+		err("Camera type (%d) not recognized", ov->customid);
+		err("Please notify " EMAIL " of the name,");
+		err("manufacturer, model, and this number of your camera.");
+		err("Also include the output of the detection process.");
+	} 
+
+	if (ov->customid == 6) {	/* USB Life TV (NTSC) */
+		ov->tuner_type = 8;		/* Temic 4036FY5 3X 1981 */
+	}
+
+	if (write_regvals(ov, aRegvalsInit511)) goto error;
+
+	if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 0);
+
+	/* The OV511+ has undocumented bits in the flow control register.
+	 * Setting it to 0xff fixes the corruption with moving objects. */
+	if (ov->bridge == BRG_OV511) {
+		if (write_regvals(ov, aRegvalsNorm511)) goto error;
+	} else if (ov->bridge == BRG_OV511PLUS) {
+		if (write_regvals(ov, aRegvalsNorm511Plus)) goto error;
+	} else {
+		err("Invalid bridge");
+	}
+
+	if (ov511_init_compression(ov)) goto error;
+
+	ov51x_set_packet_size(ov, 0);
+
+	ov->snap_enabled = snapshot;	
+
+	/* Test for 7xx0 */
+	PDEBUG(3, "Testing for 0V7xx0");
+	ov->primary_i2c_slave = OV7xx0_SID;
+	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
+		goto error;
+
+	if (i2c_w(ov, 0x12, 0x80) < 0) {
+		/* Test for 6xx0 */
+		PDEBUG(3, "Testing for 0V6xx0");
+		ov->primary_i2c_slave = OV6xx0_SID;
+		if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
+			goto error;
+
+		if (i2c_w(ov, 0x12, 0x80) < 0) {
+			/* Test for 8xx0 */
+			PDEBUG(3, "Testing for 0V8xx0");
+			ov->primary_i2c_slave = OV8xx0_SID;
+			if (ov51x_set_slave_ids(ov, OV8xx0_SID))
+				goto error;
+
+			if (i2c_w(ov, 0x12, 0x80) < 0) {
+				/* Test for SAA7111A */
+				PDEBUG(3, "Testing for SAA7111A");
+				ov->primary_i2c_slave = SAA7111A_SID;
+				if (ov51x_set_slave_ids(ov, SAA7111A_SID))
+					goto error;
+
+				if (i2c_w(ov, 0x0d, 0x00) < 0) {
+					/* Test for KS0127 */
+					PDEBUG(3, "Testing for KS0127");
+					ov->primary_i2c_slave = KS0127_SID;
+					if (ov51x_set_slave_ids(ov, KS0127_SID))
+						goto error;
+
+					if (i2c_w(ov, 0x10, 0x00) < 0) {
+						err("Can't determine sensor slave IDs");
+		 				goto error;
+					} else {
+						if (ks0127_configure(ov) < 0) {
+							err("Failed to configure KS0127");
+	 						goto error;
+						}
+					}
+				} else {
+					if (saa7111a_configure(ov) < 0) {
+						err("Failed to configure SAA7111A");
+	 					goto error;
+					}
+				}
+			} else {
+				err("Detected unsupported OV8xx0 sensor");
+				goto error;
+			}
+		} else {
+			if (ov6xx0_configure(ov) < 0) {
+				err("Failed to configure OV6xx0");
+ 				goto error;
+			}
+		}
+	} else {
+		if (ov7xx0_configure(ov) < 0) {
+			err("Failed to configure OV7xx0");
+	 		goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	err("OV511 Config failed");
+
+	return -EBUSY;
+}
+
+/* This initializes the OV518/OV518+ and the sensor */
+static int 
+ov518_configure(struct usb_ov511 *ov)
+{
+	static struct ov511_regvals aRegvalsInit518[] = {
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x40 },
+	 	{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
+	 	{ OV511_REG_BUS, R51x_SYS_RESET,	0x3e },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
+		{ OV511_REG_BUS, R51x_SYS_RESET,	0x00 },
+		{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
+		{ OV511_REG_BUS, 0x46,			0x00 }, 
+		{ OV511_REG_BUS, 0x5d,			0x03 },
+		{ OV511_DONE_BUS, 0x0, 0x00},
+	};
+
+	/* New values, based on Windows driver. Since what they do is not
+	 * known yet, this may be incorrect. */
+	static struct ov511_regvals aRegvalsNorm518[] = {
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x02 }, /* Reset */
+		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 }, /* Enable */
+		{ OV511_REG_BUS, 0x31, 			0x0f },
+		{ OV511_REG_BUS, 0x5d,			0x03 },
+		{ OV511_REG_BUS, 0x24,			0x9f },
+		{ OV511_REG_BUS, 0x25,			0x90 },
+		{ OV511_REG_BUS, 0x20,			0x00 }, /* Was 0x08 */
+		{ OV511_REG_BUS, 0x51,			0x04 },
+		{ OV511_REG_BUS, 0x71,			0x19 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
+	};
+
+	PDEBUG(4, "");
+
+	/* First 5 bits of custom ID reg are a revision ID on OV518 */
+	info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID));
+
+	if (write_regvals(ov, aRegvalsInit518)) goto error;
+
+	/* Set LED GPIO pin to output mode */
+	if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) goto error;
+
+	/* LED is off by default with OV518; have to explicitly turn it on */
+	if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
+		ov51x_led_control(ov, 0);
+	else
+		ov51x_led_control(ov, 1);
+
+	/* Don't require compression if dumppix is enabled; otherwise it's
+	 * required. OV518 has no uncompressed mode, to save RAM. */
+	if (!dumppix && !ov->compress) {
+		ov->compress = 1;
+		warn("Compression required with OV518...enabling");
+	}
+
+	if (write_regvals(ov, aRegvalsNorm518)) goto error;
+
+	if (reg_w(ov, 0x2f, 0x80) < 0) goto error;
+
+	if (ov518_init_compression(ov)) goto error;
+
+	ov51x_set_packet_size(ov, 0);
+
+	ov->snap_enabled = snapshot;
+
+	/* Test for 76xx */
+	ov->primary_i2c_slave = OV7xx0_SID;
+	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
+		goto error;
+
+	/* The OV518 must be more aggressive about sensor detection since
+	 * I2C write will never fail if the sensor is not present. We have
+	 * to try to initialize the sensor to detect its presence */
+
+	if (init_ov_sensor(ov) < 0) {
+		/* Test for 6xx0 */
+		ov->primary_i2c_slave = OV6xx0_SID;
+		if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
+			goto error;
+
+		if (init_ov_sensor(ov) < 0) {
+			/* Test for 8xx0 */
+			ov->primary_i2c_slave = OV8xx0_SID;
+			if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0)
+				goto error;
+
+			if (init_ov_sensor(ov) < 0) {
+				err("Can't determine sensor slave IDs");
+ 				goto error;
+			} else {
+				err("Detected unsupported OV8xx0 sensor");
+				goto error;
+			}
+		} else {
+			if (ov6xx0_configure(ov) < 0) {
+				err("Failed to configure OV6xx0");
+ 				goto error;
+			}
+		}
+	} else {
+		if (ov7xx0_configure(ov) < 0) {
+			err("Failed to configure OV7xx0");
+	 		goto error;
+		}
+	}
+
+	// FIXME: Sizes > 320x240 are not working yet
+	ov->maxwidth = 320;
+	ov->maxheight = 240;
+
+	// The OV518 cannot go as low as the sensor can
+	ov->minwidth = 160;
+	ov->minheight = 120;
+
+	return 0;
+
+error:
+	err("OV518 Config failed");
+
+	return -EBUSY;
+}
+
+
+/****************************************************************************
+ *
+ *  USB routines
+ *
+ ***************************************************************************/
+
+static void *
+ov51x_probe(struct usb_device *dev, unsigned int ifnum,
+	    const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor *interface;
+	struct usb_ov511 *ov;
+	int i;
+	int registered = 0;
+
+	PDEBUG(1, "probing for device...");
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1)
+		return NULL;
+
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+
+	/* Checking vendor/product should be enough, but what the hell */
+	if (interface->bInterfaceClass != 0xFF)
+		return NULL;
+	if (interface->bInterfaceSubClass != 0x00)
+		return NULL;
+
+	if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) {
+		err("couldn't kmalloc ov struct");
+		goto error_out;
+	}
+
+	memset(ov, 0, sizeof(*ov));
+
+	ov->dev = dev;
+	ov->iface = interface->bInterfaceNumber;
+	ov->led_policy = led;
+	ov->compress = compress;
+	ov->lightfreq = lightfreq;
+	ov->num_inputs = 1;	   /* Video decoder init functs. change this */
+	ov->stop_during_set = !fastset;
+	ov->tuner_type = tuner;
+	ov->backlight = backlight;
+
+	ov->auto_brt = autobright;
+	ov->auto_gain = autogain;
+	ov->auto_exp = autoexp;
+
+	switch (dev->descriptor.idProduct) {
+	case PROD_OV511:
+		ov->bridge = BRG_OV511;
+		ov->bclass = BCL_OV511;
+		break;
+	case PROD_OV511PLUS:
+		ov->bridge = BRG_OV511PLUS;
+		ov->bclass = BCL_OV511;
+		break;
+	case PROD_OV518:
+		ov->bridge = BRG_OV518;
+		ov->bclass = BCL_OV518;
+		break;
+	case PROD_OV518PLUS:
+		ov->bridge = BRG_OV518PLUS;
+		ov->bclass = BCL_OV518;
+		break;
+	case PROD_ME2CAM:
+		if (dev->descriptor.idVendor != VEND_MATTEL)
+			goto error;
+		ov->bridge = BRG_OV511PLUS;
+		ov->bclass = BCL_OV511;
+		break;
+	default:
+		err("Unknown product ID 0x%x", dev->descriptor.idProduct);
+		goto error_dealloc;
+	}
+
+	info("USB %s video device found", symbolic(brglist, ov->bridge));
+
+	/* Workaround for some applications that want data in RGB
+	 * instead of BGR. */
+	if (force_rgb)
+		info("data format set to RGB");
+
+	init_waitqueue_head(&ov->wq);
+
+	init_MUTEX(&ov->lock);	/* to 1 == available */
+	init_MUTEX(&ov->buf_lock);
+	init_MUTEX(&ov->param_lock);
+	init_MUTEX(&ov->i2c_lock);
+	init_MUTEX(&ov->cbuf_lock);
+
+	ov->buf_state = BUF_NOT_ALLOCATED;
+
+	/* Must be kmalloc()'ed, for DMA accessibility */
+	ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL);
+	if (!ov->cbuf)
+		goto error;
+
+	if (ov->bclass == BCL_OV518) {
+		if (ov518_configure(ov) < 0)
+			goto error;
+	} else {
+		if (ov511_configure(ov) < 0)
+			goto error;
+	}
+
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov->frame[i].framenum = i;
+		init_waitqueue_head(&ov->frame[i].wq);
+	}
+
+	for (i = 0; i < OV511_NUMSBUF; i++) {
+		ov->sbuf[i].ov = ov;
+		spin_lock_init(&ov->sbuf[i].lock);
+		ov->sbuf[i].n = i;
+	}
+
+	/* Unnecessary? (This is done on open(). Need to make sure variables
+	 * are properly initialized without this before removing it, though). */
+	if (ov51x_set_default_params(ov) < 0)
+		goto error;
+
+#ifdef OV511_DEBUG
+	if (dump_bridge)
+		ov511_dump_regs(ov);
+#endif
+
+	memcpy(&ov->vdev, &vdev_template, sizeof(vdev_template));
+	ov->vdev.priv = ov;
+
+	for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
+		/* Minor 0 cannot be specified; assume user wants autodetect */
+		if (unit_video[i] == 0)
+			break;
+
+		if (video_register_device(&ov->vdev, VFL_TYPE_GRABBER,
+			unit_video[i]) >= 0) {
+			registered = 1;
+			break;
+		}
+	}
+
+	/* Use the next available one */
+	if (!registered &&
+	    video_register_device(&ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
+		err("video_register_device failed");
+		goto error;
+	}
+
+	info("Device registered on minor %d", ov->vdev.minor);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	create_proc_ov511_cam(ov);
+#endif
+
+     	return ov;
+
+error:
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	/* Safe to call even if entry doesn't exist */
+	destroy_proc_ov511_cam(ov);
+#endif
+
+	if (ov->cbuf) {
+		down(&ov->cbuf_lock);
+		kfree(ov->cbuf);
+		ov->cbuf = NULL;
+		up(&ov->cbuf_lock);
+	}
+
+error_dealloc:
+	if (ov) {
+		kfree(ov);
+		ov = NULL;
+	}
+
+error_out:
+	err("Camera initialization failed");
+	return NULL;
+}
+
+
+static void
+ov51x_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_ov511 *ov = (struct usb_ov511 *) ptr;
+	int n;
+
+	PDEBUG(3, "");
+
+	/* We don't want people trying to open up the device */
+	video_unregister_device(&ov->vdev);
+	if (ov->user)
+		PDEBUG(3, "Device open...deferring video_unregister_device");
+
+	for (n = 0; n < OV511_NUMFRAMES; n++)
+		ov->frame[n].grabstate = FRAME_ERROR;
+
+	ov->curframe = -1;
+
+	/* This will cause the process to request another frame */
+	for (n = 0; n < OV511_NUMFRAMES; n++)
+		if (waitqueue_active(&ov->frame[n].wq))
+			wake_up_interruptible(&ov->frame[n].wq);
+	if (waitqueue_active(&ov->wq))
+		wake_up_interruptible(&ov->wq);
+
+	ov->streaming = 0;
+
+	ov51x_unlink_isoc(ov);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+        destroy_proc_ov511_cam(ov);
+#endif
+
+	ov->dev = NULL;
+
+	/* Free the memory */
+	if (ov && !ov->user) {
+		down(&ov->cbuf_lock);
+		kfree(ov->cbuf);
+		ov->cbuf = NULL;
+		up(&ov->cbuf_lock);
+
+		ov51x_dealloc(ov, 1);
+		kfree(ov);
+		ov = NULL;
+	}
+}
+
+static struct usb_driver ov511_driver = {
+	owner:		THIS_MODULE,
+	name:		"ov511",
+	id_table:       device_table,
+	probe:		ov51x_probe,
+	disconnect:	ov51x_disconnect
+};
+
+
+/****************************************************************************
+ *
+ *  Module routines
+ *
+ ***************************************************************************/
+
+/* Returns 0 for success */
+int 
+ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518,
+			     int mmx)
+{
+	if (ver != DECOMP_INTERFACE_VER) {
+		err("Decompression module has incompatible");
+		err("interface version %d", ver);
+		err("Interface version %d is required", DECOMP_INTERFACE_VER);
+		return -EINVAL;
+	}
+
+	if (!ops)
+		return -EFAULT;
+
+	if (mmx && !ov51x_mmx_available) {
+		err("MMX not available on this system or kernel");
+		return -EINVAL;
+	}
+
+	lock_kernel();
+
+	if (ov518) {
+		if (mmx) {
+			if (ov518_mmx_decomp_ops)
+				goto err_in_use;
+			else
+				ov518_mmx_decomp_ops = ops;
+		} else {
+			if (ov518_decomp_ops)
+				goto err_in_use;
+			else
+				ov518_decomp_ops = ops;
+		}
+	} else {
+		if (mmx) {
+			if (ov511_mmx_decomp_ops)
+				goto err_in_use;
+			else
+				ov511_mmx_decomp_ops = ops;
+		} else {
+			if (ov511_decomp_ops)
+				goto err_in_use;
+			else
+				ov511_decomp_ops = ops;
+		}
+	}
+
+	MOD_INC_USE_COUNT;
+
+	unlock_kernel();
+	return 0;
+
+err_in_use:
+	unlock_kernel();
+	return -EBUSY;
+}
+
+void 
+ov511_deregister_decomp_module(int ov518, int mmx)
+{
+	lock_kernel();
+
+	if (ov518) {
+		if (mmx)
+			ov518_mmx_decomp_ops = NULL;
+		else
+			ov518_decomp_ops = NULL;
+	} else {
+		if (mmx)
+			ov511_mmx_decomp_ops = NULL;
+		else
+			ov511_decomp_ops = NULL;
+	}
+	
+	MOD_DEC_USE_COUNT;
+
+	unlock_kernel();
+}
+
+static int __init 
+usb_ov511_init(void)
+{
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+        proc_ov511_create();
+#endif
+
+	if (usb_register(&ov511_driver) < 0)
+		return -1;
+
+	// FIXME: Don't know how to determine this yet
+	ov51x_mmx_available = 0;
+
+#if defined (__i386__)
+	if (test_bit(X86_FEATURE_MMX, &boot_cpu_data.x86_capability))
+		ov51x_mmx_available = 1;
+#endif
+
+	info(DRIVER_VERSION " : " DRIVER_DESC);
+
+	return 0;
+}
+
+static void __exit 
+usb_ov511_exit(void)
+{
+	usb_deregister(&ov511_driver);
+	info("driver deregistered");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+        proc_ov511_destroy();
+#endif
+}
+
+module_init(usb_ov511_init);
+module_exit(usb_ov511_exit);
+
+/* No version, for compatibility with binary-only modules */
+EXPORT_SYMBOL_NOVERS(ov511_register_decomp_module);
+EXPORT_SYMBOL_NOVERS(ov511_deregister_decomp_module);
diff -Nru a/drivers/usb/media/ov511.h b/drivers/usb/media/ov511.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/ov511.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,644 @@
+#ifndef __LINUX_OV511_H
+#define __LINUX_OV511_H
+
+#include <asm/uaccess.h>
+#include <linux/videodev.h>
+#include <linux/smp_lock.h>
+#include <linux/usb.h>
+
+#define OV511_DEBUG	/* Turn on debug messages */
+
+#ifdef OV511_DEBUG
+	#define PDEBUG(level, fmt, args...) \
+		if (debug >= (level)) info("[%s:%d] " fmt, \
+		__PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+	#define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+/* This macro restricts an int variable to an inclusive range */
+#define RESTRICT_TO_RANGE(v,mi,ma) { \
+	if ((v) < (mi)) (v) = (mi); \
+	else if ((v) > (ma)) (v) = (ma); \
+}
+
+/* --------------------------------- */
+/* DEFINES FOR OV511 AND OTHER CHIPS */
+/* --------------------------------- */
+
+/* USB IDs */
+#define VEND_OMNIVISION	0x05A9
+#define PROD_OV511	0x0511
+#define PROD_OV511PLUS	0xA511
+#define PROD_OV518	0x0518
+#define PROD_OV518PLUS	0xA518
+
+#define VEND_MATTEL	0x0813
+#define PROD_ME2CAM	0x0002
+
+/* --------------------------------- */
+/*     OV51x REGISTER MNEMONICS      */
+/* --------------------------------- */
+
+/* Camera interface register numbers */
+#define R511_CAM_DELAY		0x10
+#define R511_CAM_EDGE		0x11
+#define R511_CAM_PXCNT		0x12
+#define R511_CAM_LNCNT		0x13
+#define R511_CAM_PXDIV		0x14
+#define R511_CAM_LNDIV		0x15
+#define R511_CAM_UV_EN		0x16
+#define R511_CAM_LINE_MODE	0x17
+#define R511_CAM_OPTS		0x18
+
+/* Snapshot mode camera interface register numbers */
+#define R511_SNAP_FRAME		0x19
+#define R511_SNAP_PXCNT		0x1A
+#define R511_SNAP_LNCNT		0x1B
+#define R511_SNAP_PXDIV		0x1C
+#define R511_SNAP_LNDIV		0x1D
+#define R511_SNAP_UV_EN		0x1E
+#define R511_SNAP_OPTS		0x1F
+
+/* DRAM register numbers */
+#define R511_DRAM_FLOW_CTL	0x20
+#define R511_DRAM_ARCP		0x21
+#define R511_DRAM_MRC		0x22
+#define R511_DRAM_RFC		0x23
+
+/* ISO FIFO register numbers */
+#define R51x_FIFO_PSIZE		0x30	/* 2 bytes wide w/ OV518(+) */
+#define R511_FIFO_OPTS		0x31
+
+/* Parallel IO register numbers */
+#define R511_PIO_OPTS		0x38
+#define R511_PIO_DATA		0x39
+#define R511_PIO_BIST		0x3E
+#define R518_GPIO_IN		0x55	/* OV518(+) only */
+#define R518_GPIO_OUT		0x56	/* OV518(+) only */
+#define R518_GPIO_CTL		0x57	/* OV518(+) only */
+#define R518_GPIO_PULSE_IN	0x58	/* OV518(+) only */
+#define R518_GPIO_PULSE_CLEAR	0x59	/* OV518(+) only */
+#define R518_GPIO_PULSE_POL	0x5a	/* OV518(+) only */
+#define R518_GPIO_PULSE_EN	0x5b	/* OV518(+) only */
+#define R518_GPIO_RESET		0x5c	/* OV518(+) only */
+
+/* I2C registers */
+#define R511_I2C_CTL		0x40
+#define R518_I2C_CTL		0x47	/* OV518(+) only */
+#define R51x_I2C_W_SID		0x41
+#define R51x_I2C_SADDR_3	0x42
+#define R51x_I2C_SADDR_2	0x43
+#define R51x_I2C_R_SID		0x44
+#define R51x_I2C_DATA		0x45
+#define R51x_I2C_CLOCK		0x46
+#define R51x_I2C_TIMEOUT	0x47
+
+/* I2C snapshot registers */
+#define R511_SI2C_SADDR_3	0x48
+#define R511_SI2C_DATA		0x49
+
+/* System control registers */
+#define R51x_SYS_RESET		0x50
+		/* Reset type definitions */
+#define 	OV511_RESET_UDC		0x01
+#define 	OV511_RESET_I2C		0x02
+#define 	OV511_RESET_FIFO	0x04
+#define 	OV511_RESET_OMNICE	0x08
+#define 	OV511_RESET_DRAM	0x10
+#define 	OV511_RESET_CAM_INT	0x20
+#define 	OV511_RESET_OV511	0x40
+#define 	OV511_RESET_NOREGS	0x3F /* All but OV511 & regs */
+#define 	OV511_RESET_ALL		0x7F
+
+#define R511_SYS_CLOCK_DIV	0x51
+#define R51x_SYS_SNAP		0x52
+#define R51x_SYS_INIT         	0x53
+#define R511_SYS_PWR_CLK	0x54 /* OV511+/OV518(+) only */
+#define R511_SYS_LED_CTL	0x55 /* OV511+ only */
+#define R511_SYS_USER		0x5E
+#define R511_SYS_CUST_ID	0x5F
+
+/* OmniCE (compression) registers */
+#define R511_COMP_PHY		0x70
+#define R511_COMP_PHUV		0x71
+#define R511_COMP_PVY		0x72
+#define R511_COMP_PVUV		0x73
+#define R511_COMP_QHY		0x74
+#define R511_COMP_QHUV		0x75
+#define R511_COMP_QVY		0x76
+#define R511_COMP_QVUV		0x77
+#define R511_COMP_EN		0x78
+#define R511_COMP_LUT_EN	0x79		
+#define R511_COMP_LUT_BEGIN	0x80
+
+/* --------------------------------- */
+/*         ALTERNATE NUMBERS         */
+/* --------------------------------- */
+
+/* Alternate numbers for various max packet sizes (OV511 only) */
+#define OV511_ALT_SIZE_992	0
+#define OV511_ALT_SIZE_993	1
+#define OV511_ALT_SIZE_768	2
+#define OV511_ALT_SIZE_769	3
+#define OV511_ALT_SIZE_512	4
+#define OV511_ALT_SIZE_513	5
+#define OV511_ALT_SIZE_257	6
+#define OV511_ALT_SIZE_0	7
+
+/* Alternate numbers for various max packet sizes (OV511+ only) */
+#define OV511PLUS_ALT_SIZE_0	0
+#define OV511PLUS_ALT_SIZE_33	1
+#define OV511PLUS_ALT_SIZE_129	2
+#define OV511PLUS_ALT_SIZE_257	3
+#define OV511PLUS_ALT_SIZE_385	4
+#define OV511PLUS_ALT_SIZE_513	5
+#define OV511PLUS_ALT_SIZE_769	6
+#define OV511PLUS_ALT_SIZE_961	7
+
+/* Alternate numbers for various max packet sizes (OV518(+) only) */
+#define OV518_ALT_SIZE_0	0
+#define OV518_ALT_SIZE_128	1
+#define OV518_ALT_SIZE_256	2
+#define OV518_ALT_SIZE_384	3
+#define OV518_ALT_SIZE_512	4
+#define OV518_ALT_SIZE_640	5
+#define OV518_ALT_SIZE_768	6
+#define OV518_ALT_SIZE_896	7
+
+/* --------------------------------- */
+/*     OV7610 REGISTER MNEMONICS     */
+/* --------------------------------- */
+
+/* OV7610 registers */
+#define OV7610_REG_GAIN          0x00	/* gain setting (5:0) */
+#define OV7610_REG_BLUE          0x01	/* blue channel balance */
+#define OV7610_REG_RED           0x02	/* red channel balance */
+#define OV7610_REG_SAT           0x03	/* saturation */
+					/* 04 reserved */
+#define OV7610_REG_CNT           0x05	/* Y contrast */
+#define OV7610_REG_BRT           0x06	/* Y brightness */
+					/* 08-0b reserved */
+#define OV7610_REG_BLUE_BIAS     0x0C	/* blue channel bias (5:0) */
+#define OV7610_REG_RED_BIAS      0x0D	/* read channel bias (5:0) */
+#define OV7610_REG_GAMMA_COEFF   0x0E	/* gamma settings */
+#define OV7610_REG_WB_RANGE      0x0F	/* AEC/ALC/S-AWB settings */
+#define OV7610_REG_EXP           0x10	/* manual exposure setting */
+#define OV7610_REG_CLOCK         0x11	/* polarity/clock prescaler */
+#define OV7610_REG_COM_A         0x12	/* misc common regs */
+#define OV7610_REG_COM_B         0x13	/* misc common regs */
+#define OV7610_REG_COM_C         0x14	/* misc common regs */
+#define OV7610_REG_COM_D         0x15	/* misc common regs */
+#define OV7610_REG_FIELD_DIVIDE  0x16	/* field interval/mode settings */
+#define OV7610_REG_HWIN_START    0x17	/* horizontal window start */
+#define OV7610_REG_HWIN_END      0x18	/* horizontal window end */
+#define OV7610_REG_VWIN_START    0x19	/* vertical window start */
+#define OV7610_REG_VWIN_END      0x1A	/* vertical window end */
+#define OV7610_REG_PIXEL_SHIFT   0x1B	/* pixel shift */
+#define OV7610_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
+#define OV7610_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
+					/* 0e-0f reserved */
+#define OV7610_REG_COM_E         0x20	/* misc common regs */
+#define OV7610_REG_YOFFSET       0x21	/* Y channel offset */
+#define OV7610_REG_UOFFSET       0x22	/* U channel offset */
+					/* 23 reserved */
+#define OV7610_REG_ECW           0x24	/* Exposure white level for AEC */
+#define OV7610_REG_ECB           0x25	/* Exposure black level for AEC */
+#define OV7610_REG_COM_F         0x26	/* misc settings */
+#define OV7610_REG_COM_G         0x27	/* misc settings */
+#define OV7610_REG_COM_H         0x28	/* misc settings */
+#define OV7610_REG_COM_I         0x29	/* misc settings */
+#define OV7610_REG_FRAMERATE_H   0x2A	/* frame rate MSB + misc */
+#define OV7610_REG_FRAMERATE_L   0x2B	/* frame rate LSB */
+#define OV7610_REG_ALC           0x2C	/* Auto Level Control settings */
+#define OV7610_REG_COM_J         0x2D	/* misc settings */
+#define OV7610_REG_VOFFSET       0x2E	/* V channel offset adjustment */
+#define OV7610_REG_ARRAY_BIAS	 0x2F	/* Array bias -- don't change */
+					/* 30-32 reserved */
+#define OV7610_REG_YGAMMA        0x33	/* misc gamma settings (7:6) */
+#define OV7610_REG_BIAS_ADJUST   0x34	/* misc bias settings */
+#define OV7610_REG_COM_L         0x35	/* misc settings */
+					/* 36-37 reserved */
+#define OV7610_REG_COM_K         0x38	/* misc registers */
+
+/* --------------------------------- */
+/*           I2C ADDRESSES           */
+/* --------------------------------- */
+
+#define OV7xx0_SID   0x42
+#define OV6xx0_SID   0xC0
+#define OV8xx0_SID   0xA0
+#define KS0127_SID   0xD8
+#define SAA7111A_SID 0x48
+
+/* --------------------------------- */
+/*       MISCELLANEOUS DEFINES       */
+/* --------------------------------- */
+
+#define I2C_CLOCK_PRESCALER 	0x03
+
+#define FRAMES_PER_DESC		10	/* FIXME - What should this be? */
+#define MAX_FRAME_SIZE_PER_DESC	993	/* For statically allocated stuff */
+#define PIXELS_PER_SEG		256	/* Pixels per segment */
+
+#define OV511_ENDPOINT_ADDRESS	1	/* Isoc endpoint number */
+
+#define OV511_NUMFRAMES	2
+#if OV511_NUMFRAMES > VIDEO_MAX_FRAME
+	#error "OV511_NUMFRAMES is too high"
+#endif
+
+#define OV511_NUMSBUF		2
+
+/* Control transfers use up to 4 bytes */
+#define OV511_CBUF_SIZE		4
+
+/* Bridge types */
+enum {
+	BRG_UNKNOWN,
+	BRG_OV511,
+	BRG_OV511PLUS,
+	BRG_OV518,
+	BRG_OV518PLUS,
+};
+
+/* Bridge classes */
+enum {
+	BCL_UNKNOWN,
+	BCL_OV511,
+	BCL_OV518,
+};
+
+/* Sensor types */
+enum {
+	SEN_UNKNOWN,
+	SEN_OV76BE,
+	SEN_OV7610,
+	SEN_OV7620,
+	SEN_OV7620AE,
+	SEN_OV6620,
+	SEN_OV6630,
+	SEN_OV6630AE,
+	SEN_OV6630AF,
+	SEN_OV8600,
+	SEN_KS0127,
+	SEN_KS0127B,
+	SEN_SAA7111A,
+};
+
+// Not implemented yet
+#if 0
+/* Sensor classes */
+enum {
+	SCL_UNKNOWN,
+	SCL_OV7610,	/* 7610, 76BE, 7620AE (for now) */
+	SCL_OV7620,
+	SCL_OV6620,	
+	SCL_OV6630,	/* 6630, 6630AE, 6630AF */
+	SCL_OV8600,
+	SCL_KS0127,	/* SEN_KS0127, SEN_KS0127B */
+	SCL_SAA7111A,
+};
+#endif
+
+enum {
+	STATE_SCANNING,		/* Scanning for start */
+	STATE_HEADER,		/* Parsing header */
+	STATE_LINES,		/* Parsing lines */
+};
+
+/* Buffer states */
+enum {
+	BUF_NOT_ALLOCATED,
+	BUF_ALLOCATED,
+	BUF_PEND_DEALLOC,	/* ov511->buf_timer is set */
+};
+
+/* --------- Definition of ioctl interface --------- */
+
+#define OV511_INTERFACE_VER 101
+
+/* LED options */
+enum {
+	LED_OFF,
+	LED_ON,
+	LED_AUTO,
+};
+
+/* Raw frame formats */
+enum {
+	RAWFMT_INVALID,
+	RAWFMT_YUV400,
+	RAWFMT_YUV420,
+	RAWFMT_YUV422,
+	RAWFMT_GBR422,
+};
+
+/* Unsigned short option numbers */
+enum {
+	OV511_USOPT_INVALID,
+	OV511_USOPT_BRIGHT,
+	OV511_USOPT_SAT,
+	OV511_USOPT_HUE,
+	OV511_USOPT_CONTRAST,
+};
+
+/* Unsigned int option numbers */
+enum {
+	OV511_UIOPT_INVALID,
+	OV511_UIOPT_POWER_FREQ,
+	OV511_UIOPT_BFILTER,
+	OV511_UIOPT_LED,
+	OV511_UIOPT_DEBUG,
+	OV511_UIOPT_COMPRESS,
+};
+
+struct ov511_ushort_opt {
+	int optnum;		/* Specific option number */
+	unsigned short val;
+};
+
+struct ov511_uint_opt {
+	int optnum;		/* Specific option number */
+	unsigned int val;
+};
+
+struct ov511_i2c_struct {
+	unsigned char slave; /* Write slave ID (read ID - 1) */
+	unsigned char reg;   /* Index of register */
+	unsigned char value; /* User sets this w/ write, driver does w/ read */
+	unsigned char mask;  /* Bits to be changed. Not used with read ops */
+};
+
+/* ioctls */
+#define OV511IOC_GINTVER  _IOR('v', BASE_VIDIOCPRIVATE + 0, int)
+#define OV511IOC_GUSHORT _IOWR('v', BASE_VIDIOCPRIVATE + 1, \
+			       struct ov511_ushort_opt)
+#define OV511IOC_SUSHORT  _IOW('v', BASE_VIDIOCPRIVATE + 2, \
+			       struct ov511_ushort_opt)
+#define OV511IOC_GUINT   _IOWR('v', BASE_VIDIOCPRIVATE + 3, \
+			       struct ov511_uint_opt)
+#define OV511IOC_SUINT    _IOW('v', BASE_VIDIOCPRIVATE + 4, \
+			       struct ov511_uint_opt)
+#define OV511IOC_WI2C     _IOW('v', BASE_VIDIOCPRIVATE + 5, \
+			       struct ov511_i2c_struct)
+#define OV511IOC_RI2C    _IOWR('v', BASE_VIDIOCPRIVATE + 6, \
+			       struct ov511_i2c_struct)
+/* ------------- End IOCTL interface -------------- */
+
+struct usb_ov511;		/* Forward declaration */
+
+struct ov511_sbuf {
+	struct usb_ov511 *ov;
+	unsigned char *data;
+	struct urb *urb;
+	spinlock_t lock;
+	int n;
+};
+
+enum {
+	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
+	FRAME_READY,		/* Ready to start grabbing */
+	FRAME_GRABBING,		/* In the process of being grabbed into */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
+	FRAME_ERROR,		/* Something bad happened while processing */
+};
+
+struct ov511_regvals {
+	enum {
+		OV511_DONE_BUS,
+		OV511_REG_BUS,
+		OV511_I2C_BUS,
+	} bus;
+	unsigned char reg;
+	unsigned char val;
+};
+
+struct ov511_frame {
+	int framenum;		/* Index of this frame */
+	unsigned char *data;	/* Frame buffer */
+	unsigned char *tempdata; /* Temp buffer for multi-stage conversions */
+	unsigned char *rawdata;	/* Raw camera data buffer */
+	unsigned char *compbuf;	/* Temp buffer for decompressor */
+
+	int depth;		/* Bytes per pixel */
+	int width;		/* Width application is expecting */
+	int height;		/* Height application is expecting */
+
+	int rawwidth;		/* Actual width of frame sent from camera */
+	int rawheight;		/* Actual height of frame sent from camera */
+
+	int sub_flag;		/* Sub-capture mode for this frame? */
+	unsigned int format;	/* Format for this frame */
+	int compressed;		/* Is frame compressed? */
+
+	volatile int grabstate;	/* State of grabbing */
+	int scanstate;		/* State of scanning */
+
+	int bytes_recvd;	/* Number of image bytes received from camera */
+
+	long bytes_read;	/* Amount that has been read() */
+
+	wait_queue_head_t wq;	/* Processes waiting */
+
+	int snapshot;		/* True if frame was a snapshot */
+};
+
+#define DECOMP_INTERFACE_VER 3
+
+/* Compression module operations */
+struct ov51x_decomp_ops {
+	int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *,
+			  int, int, int);
+	int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *,
+			  int, int, int);
+	int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *,
+			  int, int, int);
+	void (*decomp_lock)(void);
+	void (*decomp_unlock)(void);
+};
+
+struct usb_ov511 {
+	struct video_device vdev;
+
+	/* Device structure */
+	struct usb_device *dev;
+
+	int customid;
+	char *desc;
+	unsigned char iface;
+
+	/* Determined by sensor type */
+	int maxwidth;
+	int maxheight;
+	int minwidth;
+	int minheight;
+
+	int brightness;
+	int colour;
+	int contrast;
+	int hue;
+	int whiteness;
+	int exposure;
+	int auto_brt;		/* Auto brightness enabled flag */
+	int auto_gain;		/* Auto gain control enabled flag */
+	int auto_exp;		/* Auto exposure enabled flag */
+	int backlight;		/* Backlight exposure algorithm flag */
+
+	int led_policy;		/* LED: off|on|auto; OV511+ only */
+
+	struct semaphore lock;	/* Serializes user-accessible operations */
+	int user;		/* user count for exclusive use */
+
+	int streaming;		/* Are we streaming Isochronous? */
+	int grabbing;		/* Are we grabbing? */
+
+	int compress;		/* Should the next frame be compressed? */
+	int compress_inited;	/* Are compression params uploaded? */
+
+	int lightfreq;		/* Power (lighting) frequency */
+	int bandfilt;		/* Banding filter enabled flag */
+
+	unsigned char *fbuf;	/* Videodev buffer area */
+	unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */
+	unsigned char *rawfbuf;	/* Raw camera data buffer area */
+
+	int sub_flag;		/* Pix Array subcapture on flag */
+	int subx;		/* Pix Array subcapture x offset */
+	int suby;		/* Pix Array subcapture y offset */
+	int subw;		/* Pix Array subcapture width */
+	int subh;		/* Pix Array subcapture height */
+
+	int curframe;		/* Current receiving sbuf */
+	struct ov511_frame frame[OV511_NUMFRAMES];	
+
+	struct ov511_sbuf sbuf[OV511_NUMSBUF];
+
+	wait_queue_head_t wq;	/* Processes waiting */
+
+	int snap_enabled;	/* Snapshot mode enabled */
+	
+	int bridge;		/* Type of bridge (BRG_*) */
+	int bclass;		/* Class of bridge (BCL_*) */
+	int sensor;		/* Type of image sensor chip (SEN_*) */
+	int sclass;		/* Type of image sensor chip (SCL_*) */
+	int tuner;		/* Type of TV tuner */
+
+	int packet_size;	/* Frame size per isoc desc */
+
+	struct semaphore param_lock;	/* params lock for this camera */
+
+	/* /proc entries, relative to /proc/video/ov511/ */
+	struct proc_dir_entry *proc_devdir;   /* Per-device proc directory */
+	struct proc_dir_entry *proc_info;     /* <minor#>/info entry */
+	struct proc_dir_entry *proc_button;   /* <minor#>/button entry */
+	struct proc_dir_entry *proc_control;  /* <minor#>/control entry */
+
+	/* Framebuffer/sbuf management */
+	int buf_state;
+	struct semaphore buf_lock;
+	struct timer_list buf_timer;
+
+	struct ov51x_decomp_ops *decomp_ops;
+
+	/* Stop streaming while changing picture settings */
+	int stop_during_set;
+
+	int stopped;		/* Streaming is temporarily paused */
+
+	/* Video decoder stuff */
+	int input;		/* Composite, S-VIDEO, etc... */
+	int num_inputs;		/* Number of inputs */
+	int norm; 		/* NTSC / PAL / SECAM */
+	int has_decoder;	/* Device has a video decoder */
+	int has_tuner;		/* Device has a TV tuner */
+	int has_audio_proc;	/* Device has an audio processor */
+	int freq;		/* Current tuner frequency */
+	int tuner_type;		/* Specific tuner model */
+
+	/* I2C interface to kernel */
+	struct semaphore i2c_lock;	  /* Protect I2C controller regs */
+	unsigned char primary_i2c_slave;  /* I2C write id of sensor */
+
+	/* Control transaction stuff */
+	unsigned char *cbuf;		/* Buffer for payload */
+	struct semaphore cbuf_lock;
+};
+
+/* Used to represent a list of values and their respective symbolic names */
+struct symbolic_list {
+	int num;
+	char *name;
+};
+
+#define NOT_DEFINED_STR "Unknown"
+
+/* Returns the name of the matching element in the symbolic_list array. The
+ * end of the list must be marked with an element that has a NULL name.
+ */
+static inline char * 
+symbolic(struct symbolic_list list[], int num)
+{
+	int i;
+
+	for (i = 0; list[i].name != NULL; i++)
+			if (list[i].num == num)
+				return (list[i].name);
+
+	return (NOT_DEFINED_STR);
+}
+
+struct mode_list_518 {
+	int width;
+	int height;
+	u8 reg28;
+	u8 reg29;
+	u8 reg2a;
+	u8 reg2c;
+	u8 reg2e;
+	u8 reg24;
+	u8 reg25;
+};
+
+/* Compression stuff */
+
+#define OV511_QUANTABLESIZE	64
+#define OV518_QUANTABLESIZE	32
+
+#define OV511_YQUANTABLE { \
+	0, 1, 1, 2, 2, 3, 3, 4, \
+	1, 1, 1, 2, 2, 3, 4, 4, \
+	1, 1, 2, 2, 3, 4, 4, 4, \
+	2, 2, 2, 3, 4, 4, 4, 4, \
+	2, 2, 3, 4, 4, 5, 5, 5, \
+	3, 3, 4, 4, 5, 5, 5, 5, \
+	3, 4, 4, 4, 5, 5, 5, 5, \
+	4, 4, 4, 4, 5, 5, 5, 5  \
+}
+
+#define OV511_UVQUANTABLE { \
+	0, 2, 2, 3, 4, 4, 4, 4, \
+	2, 2, 2, 4, 4, 4, 4, 4, \
+	2, 2, 3, 4, 4, 4, 4, 4, \
+	3, 4, 4, 4, 4, 4, 4, 4, \
+	4, 4, 4, 4, 4, 4, 4, 4, \
+	4, 4, 4, 4, 4, 4, 4, 4, \
+	4, 4, 4, 4, 4, 4, 4, 4, \
+	4, 4, 4, 4, 4, 4, 4, 4  \
+}
+
+#define OV518_YQUANTABLE { \
+	5, 4, 5, 6, 6, 7, 7, 7, \
+	5, 5, 5, 5, 6, 7, 7, 7, \
+	6, 6, 6, 6, 7, 7, 7, 8, \
+	7, 7, 6, 7, 7, 7, 8, 8  \
+}
+
+#define OV518_UVQUANTABLE { \
+	6, 6, 6, 7, 7, 7, 7, 7, \
+	6, 6, 6, 7, 7, 7, 7, 7, \
+	6, 6, 6, 7, 7, 7, 7, 8, \
+	7, 7, 7, 7, 7, 7, 8, 8  \
+}
+
+#endif
diff -Nru a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc-ctrl.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,1205 @@
+/* Driver for Philips webcam
+   Functions that send various control messages to the webcam, including
+   video modes.
+   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added methods for changing white balance and 
+                          red/green gains
+ */
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h> 
+#endif
+#include <asm/errno.h>
+ 
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+
+/* Request types: video */
+#define SET_LUM_CTL			0x01
+#define GET_LUM_CTL			0x02
+#define SET_CHROM_CTL			0x03
+#define GET_CHROM_CTL			0x04
+#define SET_STATUS_CTL			0x05
+#define GET_STATUS_CTL			0x06
+#define SET_EP_STREAM_CTL		0x07
+#define GET_EP_STREAM_CTL		0x08
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER			0x2000
+#define PRESET_AGC_FORMATTER			0x2100
+#define SHUTTER_MODE_FORMATTER			0x2200
+#define PRESET_SHUTTER_FORMATTER		0x2300
+#define PRESET_CONTOUR_FORMATTER		0x2400
+#define AUTO_CONTOUR_FORMATTER			0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER	0x2600
+#define CONTRAST_FORMATTER			0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER		0x2800
+#define FLICKERLESS_MODE_FORMATTER		0x2900
+#define AE_CONTROL_SPEED			0x2A00
+#define BRIGHTNESS_FORMATTER			0x2B00
+#define GAMMA_FORMATTER				0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER			0x1000
+#define AWB_CONTROL_SPEED_FORMATTER		0x1100
+#define AWB_CONTROL_DELAY_FORMATTER		0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER	0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER	0x1400
+#define COLOUR_MODE_FORMATTER			0x1500
+#define SATURATION_MODE_FORMATTER1		0x1600
+#define SATURATION_MODE_FORMATTER2		0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER		0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER		0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER	0x0400
+#define READ_AGC_FORMATTER			0x0500
+#define READ_SHUTTER_FORMATTER			0x0600
+#define READ_RED_GAIN_FORMATTER			0x0700
+#define READ_BLUE_GAIN_FORMATTER		0x0800
+#define READ_RAW_Y_MEAN_FORMATTER		0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER		0x3200
+#define MIRROR_IMAGE_FORMATTER			0x3300
+#define LED_FORMATTER				0x3400
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
+
+static char *size2name[PSZ_MAX] =
+{
+	"subQCIF",
+	"QSIF",
+	"QCIF",
+	"SIF",
+	"CIF",
+	"VGA",
+};  
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
+   preferences, so you either get compressed or non-compressed streams.
+   
+   An alternate value of 0 means this mode is not available at all.
+ */
+
+struct Nala_table_entry {
+	char alternate;			/* USB alternate setting */
+	int compressed;			/* Compressed yes/no */
+
+	unsigned char mode[3];		/* precomputed mode table */
+};
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
+{
+#include "pwc_nala.h"
+};
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface 
+   number. An alternate of 0 means that the mode is unavailable.
+   
+   There are 6 * 4 * 4 entries: 
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+     
+   When an uncompressed mode is not available, the next available compressed mode 
+   will be choosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+struct Timon_table_entry 
+{
+	char alternate;			/* USB alternate interface */
+	unsigned short packetsize;	/* Normal packet size */
+	unsigned short bandlength;	/* Bandlength when decompressing */
+	unsigned char mode[13];		/* precomputed mode settings for cam */
+};
+
+static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = 
+{
+#include "pwc_timon.h"
+};
+
+/* Entries for the Kiara (730/740/750) camera */
+
+struct Kiara_table_entry
+{
+	char alternate;			/* USB alternate interface */
+	unsigned short packetsize;	/* Normal packet size */
+	unsigned short bandlength;	/* Bandlength when decompressing */
+	unsigned char mode[12];		/* precomputed mode settings for cam */
+};
+
+static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+#include "pwc_kiara.h"
+};
+
+
+/****************************************************************************/
+
+
+
+
+#if PWC_DEBUG
+void pwc_hexdump(void *p, int len)
+{
+	int i;
+	unsigned char *s;
+	char buf[100], *d;
+	
+	s = (unsigned char *)p;
+	d = buf;
+	*d = '\0';
+	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
+	for (i = 0; i < len; i++) {
+		d += sprintf(d, "%02X ", *s++);
+		if ((i & 0xF) == 0xF) {
+			Debug("%s\n", buf);
+			d = buf;
+			*d = '\0';
+		}
+	}
+	if ((i & 0xF) != 0)
+		Debug("%s\n", buf);
+}
+#endif
+
+static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+{
+	return usb_control_msg(udev,
+		usb_sndctrlpipe(udev, 0),
+		SET_EP_STREAM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		VIDEO_OUTPUT_CONTROL_FORMATTER,
+		index,
+		buf, buflen, HZ);
+}
+
+
+
+static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+{
+	unsigned char buf[3];
+	int ret, fps;
+	struct Nala_table_entry *pEntry;
+	int frames2frames[31] = 
+	{ /* closest match of framerate */
+	   0,  0,  0,  0,  4,  /*  0-4  */
+	   5,  5,  7,  7, 10,  /*  5-9  */
+          10, 10, 12, 12, 15,  /* 10-14 */
+          15, 15, 15, 20, 20,  /* 15-19 */
+          20, 20, 20, 24, 24,  /* 20-24 */
+          24, 24, 24, 24, 24,  /* 25-29 */
+          24                   /* 30    */
+	};
+	int frames2table[31] = 
+	{ 0, 0, 0, 0, 0, /*  0-4  */
+	  1, 1, 1, 2, 2, /*  5-9  */
+	  3, 3, 4, 4, 4, /* 10-14 */
+	  5, 5, 5, 5, 5, /* 15-19 */
+	  6, 6, 6, 6, 7, /* 20-24 */
+	  7, 7, 7, 7, 7, /* 25-29 */
+	  7              /* 30    */
+	};
+	
+	if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+		return -EINVAL;
+	frames = frames2frames[frames];
+	fps = frames2table[frames];
+	pEntry = &Nala_table[size][fps];
+	if (pEntry->alternate == 0)
+		return -EINVAL;
+
+	if (pEntry->compressed && pdev->decompressor == NULL)
+		return -ENOENT; /* Not supported. */
+
+	memcpy(buf, pEntry->mode, 3);	
+	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+	if (ret < 0)
+		return ret;
+	if (pEntry->compressed)
+		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
+		
+	/* Set various parameters */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->valternate = pEntry->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+	if (pEntry->compressed) {
+		if (pdev->release < 5) { /* 4 fold compression */
+			pdev->vbandlength = 528;
+			pdev->frame_size /= 4;
+		}
+		else {
+			pdev->vbandlength = 704;
+			pdev->frame_size /= 3;
+		}
+	}
+	else
+		pdev->vbandlength = 0;
+	return 0;
+}
+
+
+static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+	unsigned char buf[13];
+	struct Timon_table_entry *pChoose;
+	int ret, fps;
+
+	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+		return -EINVAL;
+	if (size == PSZ_VGA && frames > 15)
+		return -EINVAL;
+	fps = (frames / 5) - 1;
+	
+	/* Find a supported framerate with progressively higher compression ratios
+	   if the preferred ratio is not available.
+	*/
+	pChoose = NULL;
+	if (pdev->decompressor == NULL) {
+#if PWC_DEBUG	
+		Debug("Trying to find uncompressed mode.\n");
+#endif
+		pChoose = &Timon_table[size][fps][0];
+	}
+	else {
+		while (compression <= 3) {
+			pChoose = &Timon_table[size][fps][compression];
+			if (pChoose->alternate != 0)
+				break;
+			compression++;	
+		}
+	}
+	if (pChoose == NULL || pChoose->alternate == 0)
+		return -ENOENT; /* Not supported. */
+
+	memcpy(buf, pChoose->mode, 13);
+	if (snapshot)
+		buf[0] |= 0x80;
+	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
+	if (ret < 0)
+		return ret;
+
+	if (pChoose->bandlength > 0)
+		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
+	
+	/* Set various parameters */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->vsnapshot = snapshot;
+	pdev->valternate = pChoose->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->vbandlength = pChoose->bandlength;
+	if (pChoose->bandlength > 0) 
+		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+	else
+		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	return 0;
+}
+
+
+static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+	struct Kiara_table_entry *pChoose;
+	int fps, ret;
+	unsigned char buf[12];
+	
+	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+		return -EINVAL;
+	if (size == PSZ_VGA && frames > 15)
+		return -EINVAL;
+	fps = (frames / 5) - 1;
+	
+	/* Find a supported framerate with progressively higher compression ratios
+	   if the preferred ratio is not available.
+	*/
+	pChoose = NULL;
+	if (pdev->decompressor == NULL) {
+#if PWC_DEBUG	
+		Debug("Trying to find uncompressed mode.\n");
+#endif		
+		pChoose = &Kiara_table[size][fps][0];
+	}
+	else {
+		while (compression <= 3) {
+			pChoose = &Kiara_table[size][fps][compression];
+			if (pChoose->alternate != 0)
+				break;
+			compression++;	
+		}
+	}
+	if (pChoose == NULL || pChoose->alternate == 0)
+		return -ENOENT; /* Not supported. */
+
+	/* usb_control_msg won't take staticly allocated arrays as argument?? */
+	memcpy(buf, pChoose->mode, 12);
+	if (snapshot)
+		buf[0] |= 0x80;
+
+	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+	ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
+	if (ret < 0)
+		return ret;
+
+	if (pChoose->bandlength > 0)
+		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
+		
+	/* All set and go */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->vsnapshot = snapshot;
+	pdev->valternate = pChoose->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->vbandlength = pChoose->bandlength;
+	if (pChoose->bandlength > 0)
+		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+	else 
+		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size);
+	return 0;
+}
+
+
+/**
+   @pdev: device structure
+   @width: viewport width
+   @height: viewport height
+   @frame: framerate, in fps
+   @compression: preferred compression ratio
+   @snapshot: snapshot mode or streaming
+ */
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+{
+	int ret, size;
+	
+	size = pwc_decode_size(pdev, width, height);
+	if (size < 0) {
+		Debug("Could not find suitable size.\n");
+		return -ERANGE;
+	}
+	ret = -EINVAL;	
+	switch(pdev->type) {
+	case 645:
+	case 646:
+		ret = set_video_mode_Nala(pdev, size, frames);
+		break;
+
+	case 675:
+	case 680:
+	case 690:
+		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+		break;
+		
+	case 730:
+	case 740:
+	case 750:
+		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+		break;
+	}
+	if (ret < 0) {
+		if (ret == -ENOENT)
+			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
+		else {
+			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+			return ret;
+		}
+	}
+	pdev->view.x = width;
+	pdev->view.y = height;
+	pwc_set_image_buffer_size(pdev);
+	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d, palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette);
+	return 0;
+}
+
+
+void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+	int factor, i, filler = 0;
+
+	switch(pdev->vpalette) {
+	case VIDEO_PALETTE_RGB32 | 0x80:
+	case VIDEO_PALETTE_RGB32:
+		factor = 16;
+		filler = 0;
+		break;
+	case VIDEO_PALETTE_RGB24 | 0x80:
+	case VIDEO_PALETTE_RGB24:
+		factor = 12;
+		filler = 0;
+		break;
+	case VIDEO_PALETTE_YUYV:
+	case VIDEO_PALETTE_YUV422:
+		factor = 8;
+		filler = 128;
+		break;
+	case VIDEO_PALETTE_YUV420:
+	case VIDEO_PALETTE_YUV420P:
+		factor = 6;
+		filler = 128;
+		break;
+#if PWC_DEBUG		
+	case VIDEO_PALETTE_RAW:
+		pdev->image.size = pdev->frame_size;
+		pdev->view.size = pdev->frame_size;
+		return;
+		break;
+#endif	
+	default:
+		factor = 0;
+		break;
+	}
+
+	/* Set sizes in bytes */
+	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
+
+	/* Align offset, or you'll get some very weird results in
+	   YUV420 mode... x must be multiple of 4 (to get the Y's in 
+	   place), and y even (or you'll mixup U & V). This is less of a
+	   problem for YUV420P.
+	 */
+	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
+	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
+	
+	/* Fill buffers with gray or black */
+	for (i = 0; i < MAX_IMAGES; i++) {
+		if (pdev->image_ptr[i] != NULL)
+			memset(pdev->image_ptr[i], filler, pdev->view.size);
+	}
+}
+
+
+
+/* BRIGHTNESS */
+
+int pwc_get_brightness(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		BRIGHTNESS_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return buf << 9;
+}
+
+int pwc_set_brightness(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 9) & 0x7f;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		BRIGHTNESS_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+/* CONTRAST */
+
+int pwc_get_contrast(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		CONTRAST_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return buf << 10;
+}
+
+int pwc_set_contrast(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 10) & 0x3f;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		CONTRAST_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+/* GAMMA */
+
+int pwc_get_gamma(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		GAMMA_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return buf << 11;
+}
+
+int pwc_set_gamma(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 11) & 0x1f;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		GAMMA_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+
+/* SATURATION */
+
+int pwc_get_saturation(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+
+	if (pdev->type < 675)
+		return -1;
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_CHROM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+	return 32768 + buf * 327;
+}
+
+int pwc_set_saturation(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (pdev->type < 675)
+		return -EINVAL;
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	/* saturation ranges from -100 to +100 */
+	buf = (value - 32768) / 327;
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_CHROM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+/* AGC */
+
+static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+{
+	char buf;
+	int ret;
+	
+	if (mode)
+		buf = 0x0; /* auto */
+	else
+		buf = 0xff; /* fixed */
+
+	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		AGC_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	
+	if (!mode && ret >= 0) {
+		if (value < 0)
+			value = 0;
+		if (value > 0xffff)
+			value = 0xffff;
+		buf = (value >> 10) & 0x3F;
+		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+			SET_LUM_CTL,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			PRESET_AGC_FORMATTER,
+			pdev->vcinterface,
+			&buf, 1, HZ / 2);
+	}
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_LUM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		AGC_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	if (ret < 0)
+		return ret;
+
+	if (buf != 0) { /* fixed */
+		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+			GET_LUM_CTL,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			PRESET_AGC_FORMATTER,
+			pdev->vcinterface,
+			&buf, 1, HZ / 2);
+		if (ret < 0)
+			return ret;
+		if (buf > 0x3F)
+			buf = 0x3F;
+		*value = (buf << 10);		
+	}
+	else { /* auto */
+		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+			GET_STATUS_CTL,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			READ_AGC_FORMATTER,
+			pdev->vcinterface,
+			&buf, 1, HZ / 2);
+		if (ret < 0)
+			return ret;
+		/* Gah... this value ranges from 0x00 ... 0x9F */
+		if (buf > 0x9F)
+			buf = 0x9F;
+		*value = -(48 + buf * 409);
+	}
+
+	return 0;
+}
+
+static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+{
+	char buf[2];
+	int speed, ret;
+
+
+	if (mode)
+		buf[0] = 0x0;	/* auto */
+	else
+		buf[0] = 0xff; /* fixed */
+	
+	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_LUM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SHUTTER_MODE_FORMATTER,
+		pdev->vcinterface,
+		buf, 1, HZ / 2);
+
+	if (!mode && ret >= 0) {
+		if (value < 0)
+			value = 0;
+		if (value > 0xffff)
+			value = 0xffff;
+		switch(pdev->type) {
+		case 675:
+		case 680:
+		case 690:
+			/* speed ranges from 0x0 to 0x290 (656) */
+			speed = (value / 100);
+			buf[1] = speed >> 8;
+			buf[0] = speed & 0xff;
+			break;
+		case 730:
+		case 740:
+		case 750:
+			/* speed seems to range from 0x0 to 0xff */
+			buf[1] = 0;
+			buf[0] = value >> 8;
+			break;
+		}
+
+		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+			SET_LUM_CTL,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			PRESET_SHUTTER_FORMATTER,
+			pdev->vcinterface,
+			&buf, 2, HZ / 2);
+	}
+	return ret;
+}	
+
+
+/* POWER */
+
+int pwc_camera_power(struct pwc_device *pdev, int power)
+{
+	char buf;
+
+	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
+		return 0;	/* Not supported by Nala or Timon < release 6 */
+
+	if (power)
+		buf = 0x00; /* active */
+	else
+		buf = 0xFF; /* power save */
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SET_POWER_SAVE_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+
+
+/* private calls */
+
+static inline int pwc_restore_user(struct pwc_device *pdev)
+{
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		RESTORE_USER_DEFAULTS_FORMATTER,
+		pdev->vcinterface,
+		NULL, 0, HZ / 2);
+}
+
+static inline int pwc_save_user(struct pwc_device *pdev)
+{
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		SAVE_USER_DEFAULTS_FORMATTER,
+		pdev->vcinterface,
+		NULL, 0, HZ / 2);
+}
+
+static inline int pwc_restore_factory(struct pwc_device *pdev)
+{
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		RESTORE_FACTORY_DEFAULTS_FORMATTER,
+		pdev->vcinterface,
+		NULL, 0, HZ / 2);
+}
+
+ /* ************************************************* */
+ /* Patch by Alvarado: (not in the original version   */
+
+ /*
+  * the camera recognizes modes from 0 to 4:
+  *
+  * 00: indoor (incandescant lighting)
+  * 01: outdoor (sunlight)
+  * 02: fluorescent lighting
+  * 03: manual
+  * 04: auto
+  */ 
+static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
+{
+	char buf;
+	int ret;
+	
+	if (mode < 0)
+	    mode = 0;
+	
+	if (mode > 4)
+	    mode = 4;
+	
+	buf = mode & 0x07; /* just the lowest three bits */
+	
+	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_CHROM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		WB_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+	
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int pwc_get_awb(struct pwc_device *pdev)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+		GET_CHROM_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		WB_MODE_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+
+	if (ret < 0) 
+		return ret;
+	return buf;
+}
+
+static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
+{
+        unsigned char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+
+	/* only the msb are considered */
+	buf = value >> 8;
+
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_CHROM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		PRESET_MANUAL_RED_GAIN_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+static inline int pwc_get_red_gain(struct pwc_device *pdev)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ 	        GET_STATUS_CTL, 
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	        PRESET_MANUAL_RED_GAIN_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+
+	if (ret < 0)
+	    return ret;
+	
+	return (buf << 8);
+}
+
+
+static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
+{
+	unsigned char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+
+	/* linear mapping of 0..0xffff to -0x80..0x7f */
+	buf = (value >> 8);
+
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_CHROM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+}
+
+static inline int pwc_get_blue_gain(struct pwc_device *pdev)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+   	        GET_STATUS_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+
+	if (ret < 0)
+	    return ret;
+	
+	return (buf << 8);
+}
+
+/* The following two functions are different, since they only read the
+   internal red/blue gains, which may be different from the manual 
+   gains set or read above.
+ */   
+static inline int pwc_read_red_gain(struct pwc_device *pdev)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+ 	        GET_STATUS_CTL, 
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+	        READ_RED_GAIN_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+
+	if (ret < 0)
+	    return ret;
+	
+	return (buf << 8);
+}
+
+static inline int pwc_read_blue_gain(struct pwc_device *pdev)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+   	        GET_STATUS_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		READ_BLUE_GAIN_FORMATTER,
+		pdev->vcinterface,
+		&buf, 1, HZ / 2);
+
+	if (ret < 0)
+	    return ret;
+	
+	return (buf << 8);
+}
+
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
+{
+	unsigned char buf[2];
+
+	if (pdev->type < 730)
+		return 0;
+	on_value /= 100;
+	off_value /= 100;
+	if (on_value < 0)
+		on_value = 0;
+	if (on_value > 0xff)
+		on_value = 0xff;
+	if (off_value < 0)
+		off_value = 0;
+	if (off_value > 0xff)
+		off_value = 0xff;
+
+	buf[0] = on_value;
+	buf[1] = off_value;
+
+	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+		SET_STATUS_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		LED_FORMATTER,
+		pdev->vcinterface,
+		&buf, 2, HZ / 2);
+}
+
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
+{
+	unsigned char buf[2];
+	int ret;
+	
+	if (pdev->type < 730) {
+		*on_value = -1;
+		*off_value = -1;
+		return 0;
+	}
+
+	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+   	        GET_STATUS_CTL,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		LED_FORMATTER,
+		pdev->vcinterface,
+		&buf, 2, HZ / 2);
+
+	if (ret < 0)
+		return ret;
+	*on_value = buf[0] * 100;
+	*off_value = buf[1] * 100;
+	return 0;
+}
+
+ /* End of Add-Ons                                    */
+ /* ************************************************* */
+
+int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+{
+	switch(cmd) {
+	case VIDIOCPWCRUSER:
+	{
+		if (pwc_restore_user(pdev))
+			return -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSUSER:
+	{
+		if (pwc_save_user(pdev))
+			return -EINVAL;
+		break;
+	}
+		
+	case VIDIOCPWCFACTORY:
+	{
+		if (pwc_restore_factory(pdev))
+			return -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSCQUAL:
+	{	
+		int *qual = arg;
+		int ret;
+
+		if (*qual < 0 || *qual > 3)
+			return -EINVAL;
+		ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
+		if (ret < 0)
+			return ret;
+		pdev->vcompression = *qual;
+		break;
+	}
+	
+	case VIDIOCPWCGCQUAL:
+	{
+		int *qual = arg;
+
+		*qual = pdev->vcompression;
+		break;
+	}
+
+	case VIDIOCPWCSAGC:
+	{
+		int *agc = arg;
+		
+		if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
+			return -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCGAGC:
+	{
+		int *agc = arg;
+		
+		if (pwc_get_agc(pdev, agc))
+			return -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSSHUTTER:
+	{
+		int *shutter_speed = arg;
+		int ret;
+
+		ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+	
+
+ /* ************************************************* */
+ /* Begin of Add-Ons for color compensation           */
+
+        case VIDIOCPWCSAWB:
+	{
+		struct pwc_whitebalance *wb = arg;
+		int ret;
+		
+		ret = pwc_set_awb(pdev, wb->mode);
+		if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
+			pwc_set_red_gain(pdev, wb->manual_red);
+			pwc_set_blue_gain(pdev, wb->manual_blue);
+		}
+		break;
+	}
+
+	case VIDIOCPWCGAWB:
+	{
+		struct pwc_whitebalance *wb = arg;
+		
+		memset(wb, 0, sizeof(*wb));
+		wb->mode = pwc_get_awb(pdev);
+		if (wb->mode < 0)
+			return -EINVAL;
+		wb->manual_red = pwc_get_red_gain(pdev);
+		wb->manual_blue = pwc_get_blue_gain(pdev);
+		if (wb->mode == PWC_WB_AUTO) {
+			wb->read_red = pwc_read_red_gain(pdev);
+			wb->read_blue = pwc_read_blue_gain(pdev);
+		}
+		break;
+	}
+
+        case VIDIOCPWCSLED:
+	{
+		int ret;
+		struct pwc_leds *leds = arg;
+
+		ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
+		if (ret<0)
+		    return ret;
+	    break;
+	}
+
+
+
+	case VIDIOCPWCGLED:
+	{
+		int led;
+		struct pwc_leds *leds = arg;
+		
+		led = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); 
+		if (led < 0)
+			return -EINVAL;
+		break;
+	}
+
+ /* End of Add-Ons                                    */
+ /* ************************************************* */
+
+	default:
+		return -ENOIOCTLCMD;
+		break;
+	}
+	return 0;
+}
+
+
+
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc-if.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,2019 @@
+/* Linux driver for Philips webcam 
+   USB and Video4Linux interface part.
+   (C) 1999-2001 Nemosoft Unv.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/*  
+   This code forms the interface between the USB layers and the Philips
+   specific stuff. Some adanved stuff of the driver falls under an
+   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+   is thus not distributed in source form. The binary pwcx.o module 
+   contains the code that falls under the NDA.
+   
+   In case you're wondering: 'pwc' stands for "Philips WebCam", but 
+   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+   without explanation).
+   
+   Oh yes, convention: to disctinguish between all the various pointers to
+   device-structures, I use these names for the pointer variables:
+   udev: struct usb_device *
+   vdev: struct video_device *
+   pdev: struct pwc_devive *
+*/
+
+/* Contributors:
+   - Alvarado: adding whitebalance code
+   - Alistar Moire: QuickCam 3000 Pro device/product ID
+   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+   - Jk Fang: SOTEC device/product ID
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+
+#if !defined(MAP_NR)
+#define MAP_NR(a) virt_to_page(a)
+#endif
+
+/* Function prototypes and driver templates */
+
+/* hotplug device table support */
+static __devinitdata struct usb_device_id pwc_device_table [] = {
+	{ USB_DEVICE(0x0471, 0x0302) },
+	{ USB_DEVICE(0x0471, 0x0303) },
+	{ USB_DEVICE(0x0471, 0x0304) },
+	{ USB_DEVICE(0x0471, 0x0307) },
+	{ USB_DEVICE(0x0471, 0x0308) },
+	{ USB_DEVICE(0x0471, 0x030C) },
+	{ USB_DEVICE(0x0471, 0x0310) },
+	{ USB_DEVICE(0x0471, 0x0311) },
+	{ USB_DEVICE(0x0471, 0x0312) },
+	{ USB_DEVICE(0x069A, 0x0001) },
+	{ USB_DEVICE(0x046D, 0x08b0) },
+	{ USB_DEVICE(0x055D, 0x9000) },
+	{ USB_DEVICE(0x055D, 0x9001) },
+	{ USB_DEVICE(0x041E, 0x400C) },
+	{ USB_DEVICE(0x04CC, 0x8116) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id);
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
+
+static struct usb_driver pwc_driver =
+{
+	name:			"Philips webcam",	/* name */
+	id_table:		pwc_device_table,
+	probe:			usb_pwc_probe,		/* probe() */
+	disconnect:		usb_pwc_disconnect,	/* disconnect() */
+};
+
+#define MAX_DEV_HINTS 10
+
+static int default_size = PSZ_QCIF;
+static int default_fps = 10;
+static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */
+static int default_fbufs = 3;   /* Default number of frame buffers */
+static int default_mbufs = 2;	/* Default number of mmap() buffers */
+       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
+static int power_save = 0;
+static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
+       int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static struct {
+	int type;
+	char serial_number[30];
+	int device_node;
+	struct pwc_device *pdev;
+} device_hint[MAX_DEV_HINTS];
+
+static struct semaphore mem_lock;
+static void *mem_leak = NULL; /* For delayed kfree()s. See below */
+
+/***/
+
+static int pwc_video_open(struct inode *inode, struct file *file);
+static int pwc_video_close(struct inode *inode, struct file *file);
+static int pwc_video_read(struct file *file, char *buf,
+			  size_t count, loff_t *ppos);
+static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
+static int  pwc_video_ioctl(struct inode *inode, struct file *file,
+			    unsigned int ioctlnr, unsigned long arg);
+static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
+
+static struct file_operations pwc_fops = {
+	owner:		THIS_MODULE,
+	open:		pwc_video_open,
+	release:       	pwc_video_close,
+	read:		pwc_video_read,
+	poll:		pwc_video_poll,
+	mmap:		pwc_video_mmap,
+	ioctl:          pwc_video_ioctl,
+	llseek:         no_llseek,
+};
+static struct video_device pwc_template = {
+	owner:		THIS_MODULE,
+	name:		"Philips Webcam",	/* Filled in later */
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_PWC,
+	fops:           &pwc_fops,
+};
+
+/***************************************************************************/
+
+/* Okay, this is some magic that I worked out and the reasoning behind it...
+
+   The biggest problem with any USB device is of course: "what to do 
+   when the user unplugs the device while it is in use by an application?"
+   We have several options:
+   1) Curse them with the 7 plagues when they do (requires divine intervention)
+   2) Tell them not to (won't work: they'll do it anyway)
+   3) Oops the kernel (this will have a negative effect on a user's uptime)
+   4) Do something sensible.
+   
+   Of course, we go for option 4.
+
+   It happens that this device will be linked to two times, once from
+   usb_device and once from the video_device in their respective 'private'
+   pointers. This is done when the device is probed() and all initialization
+   succeeded. The pwc_device struct links back to both structures.
+
+   When a device is unplugged while in use it will be removed from the 
+   list of known USB devices; I also de-register as a V4L device, but 
+   unfortunately I can't free the memory since the struct is still in use
+   by the file descriptor. This free-ing is then deferend until the first
+   opportunity. Crude, but it works.
+   
+   A small 'advantage' is that if a user unplugs the cam and plugs it back
+   in, it should get assigned the same video device minor, but unfortunately
+   it's non-trivial to re-link the cam back to the video device... (that 
+   would surely be magic! :))
+*/
+
+/***************************************************************************/
+/* Private functions */
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
+{
+        unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+        return ret;
+}
+
+static void * rvmalloc(unsigned long size)
+{
+	void * mem;
+	unsigned long adr;
+
+	size=PAGE_ALIGN(size);
+        mem=vmalloc_32(size);
+	if (mem) 
+	{
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	        adr=(unsigned long) mem;
+		while (size > 0) 
+                {
+			mem_map_reserve(vmalloc_to_page((void *)adr));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+        unsigned long adr;
+
+	if (mem) 
+	{
+	        adr=(unsigned long) mem;
+		while ((long) size > 0) 
+                {
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+
+
+
+static int pwc_allocate_buffers(struct pwc_device *pdev)
+{
+	int i;
+	void *kbuf;
+
+	Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev);
+
+	if (pdev == NULL)
+		return -ENXIO;
+		
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("allocate_buffers(): magic failed.\n");
+		return -ENXIO;
+	}
+#endif	
+	/* Allocate Isochronuous pipe buffers */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		if (pdev->sbuf[i].data == NULL) {
+			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+			if (kbuf == NULL) {
+				Err("Failed to allocate iso buffer %d.\n", i);
+				return -ENOMEM;
+			}
+			Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
+			pdev->sbuf[i].data = kbuf;
+			memset(kbuf, 0, ISO_BUFFER_SIZE);
+		}
+	}
+
+	/* Allocate frame buffer structure */
+	if (pdev->fbuf == NULL) {
+		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+		if (kbuf == NULL) {
+			Err("Failed to allocate frame buffer structure.\n");
+			return -ENOMEM;
+		}
+		Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
+		pdev->fbuf = kbuf;
+		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
+	}
+	/* create frame buffers, and make circular ring */
+	for (i = 0; i < default_fbufs; i++) {
+		if (pdev->fbuf[i].data == NULL) {
+			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
+			if (kbuf == NULL) {
+				Err("Failed to allocate frame buffer %d.\n", i);
+				return -ENOMEM;
+			}
+			Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
+			pdev->fbuf[i].data = kbuf;
+			memset(kbuf, 128, PWC_FRAME_SIZE);
+		}
+	}
+	
+	/* Allocate decompressor table space */
+	kbuf = NULL;
+	if (pdev->decompressor != NULL) {
+		kbuf = kmalloc(pdev->decompressor->table_size, GFP_KERNEL);
+		if (kbuf == NULL) {
+			Err("Failed to allocate decompress table.\n");
+			return -ENOMEM;
+		}
+		Trace(TRACE_MEMORY, "Allocated decompress table %p.\n", kbuf);
+	}
+	pdev->decompress_data = kbuf;
+	
+	/* Allocate image buffer; double buffer for mmap() */
+	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+	if (kbuf == NULL) {
+		Err("Failed to allocate image buffer(s).\n");
+		return -ENOMEM;
+	}
+	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
+	pdev->image_data = kbuf;
+	for (i = 0; i < default_mbufs; i++)
+		pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
+	for (; i < MAX_IMAGES; i++)
+		pdev->image_ptr[i] = NULL;
+
+	Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
+	return 0;
+}
+
+static void pwc_free_buffers(struct pwc_device *pdev)
+{
+	int i;
+
+	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+
+	if (pdev == NULL)
+		return;
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("free_buffers(): magic failed.\n");
+		return;
+	}
+#endif	
+
+	/* Release Iso-pipe buffers */
+	for (i = 0; i < MAX_ISO_BUFS; i++)
+		if (pdev->sbuf[i].data != NULL) {
+			Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
+			kfree(pdev->sbuf[i].data);
+			pdev->sbuf[i].data = NULL;
+		}
+
+	/* The same for frame buffers */
+	if (pdev->fbuf != NULL) {
+		for (i = 0; i < default_fbufs; i++) {
+			if (pdev->fbuf[i].data != NULL) {
+				Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
+				vfree(pdev->fbuf[i].data);
+				pdev->fbuf[i].data = NULL;
+			}
+		}
+		kfree(pdev->fbuf);
+		pdev->fbuf = NULL;
+	}
+
+	/* Intermediate decompression buffer & tables */
+	if (pdev->decompress_data != NULL) {
+		Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
+		kfree(pdev->decompress_data);
+		pdev->decompress_data = NULL;
+	}
+	pdev->decompressor = NULL;
+
+	/* Release image buffers */
+	if (pdev->image_data != NULL) {
+		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
+		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+	}
+	pdev->image_data = NULL;
+	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+}
+
+/* The frame & image buffer mess. 
+
+   Yes, this is a mess. Well, it used to be simple, but alas...  In this
+   module, 3 buffers schemes are used to get the data from the USB bus to
+   the user program. The first scheme involves the ISO buffers (called thus
+   since they transport ISO data from the USB controller), and not really
+   interesting. Suffices to say the data from this buffer is quickly 
+   gathered in an interrupt handler (pwc_isoc_handler) and placed into the 
+   frame buffer.
+   
+   The frame buffer is the second scheme, and is the central element here.
+   It collects the data from a single frame from the camera (hence, the
+   name). Frames are delimited by the USB camera with a short USB packet,
+   so that's easy to detect. The frame buffers form a list that is filled
+   by the camera+USB controller and drained by the user process through 
+   either read() or mmap().
+   
+   The image buffer is the third scheme, in which frames are decompressed
+   and possibly converted into planar format. For mmap() there is more than
+   one image buffer available.
+
+   The frame buffers provide the image buffering, in case the user process
+   is a bit slow. This introduces lag and some undesired side-effects.
+   The problem arises when the frame buffer is full. I used to drop the last 
+   frame, which makes the data in the queue stale very quickly. But dropping 
+   the frame at the head of the queue proved to be a litte bit more difficult.
+   I tried a circular linked scheme, but this introduced more problems than
+   it solved.
+
+   Because filling and draining are completely asynchronous processes, this
+   requires some fiddling with pointers and mutexes.
+   
+   Eventually, I came up with a system with 2 lists: an 'empty' frame list
+   and a 'full' frame list:
+     * Initially, all frame buffers but one are on the 'empty' list; the one
+       remaining buffer is our initial fill frame.
+     * If a frame is needed for filling, we take it from the 'empty' list, 
+       unless that list is empty, in which case we take the buffer at the 
+       head of the 'full' list.
+     * When our fill buffer has been filled, it is appended to the 'full' 
+       list.
+     * If a frame is needed by read() or mmap(), it is taken from the head of 
+       the 'full' list, handled, and then appended to the 'empty' list. If no
+       buffer is present on the 'full' list, we wait.
+   The advantage is that the buffer that is currently being decompressed/
+   converted, is on neither list, and thus not in our way (any other scheme 
+   I tried had the problem of old data lingering in the queue).
+
+   Whatever strategy you choose, it always remains a tradeoff: with more
+   frame buffers the chances of a missed frame are reduced. On the other
+   hand, on slower machines it introduces lag because the queue will 
+   always be full.
+ */
+
+/**
+  \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
+ */
+static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+{
+	int ret;
+	unsigned long flags;
+	
+	ret = 0;
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	if (pdev->fill_frame != NULL) {
+		/* append to 'full' list */
+		if (pdev->full_frames == NULL) {
+			pdev->full_frames = pdev->fill_frame;
+			pdev->full_frames_tail = pdev->full_frames;
+		}
+		else {
+			pdev->full_frames_tail->next = pdev->fill_frame;
+			pdev->full_frames_tail = pdev->fill_frame;
+		}
+	}
+	if (pdev->empty_frames != NULL) {
+		/* We have empty frames available. That's easy */
+		pdev->fill_frame = pdev->empty_frames;
+		pdev->empty_frames = pdev->empty_frames->next;	
+	}
+	else {
+		/* Hmm. Take it from the full list */
+#if PWC_DEBUG		
+		/* sanity check */
+		if (pdev->full_frames == NULL) {
+			Err("Neither empty or full frames available!\n");
+			spin_unlock_irqrestore(&pdev->ptrlock, flags);
+			return -EINVAL;
+		}
+#endif
+		pdev->fill_frame = pdev->full_frames;
+		pdev->full_frames = pdev->full_frames->next;
+		ret = 1;
+	}
+	pdev->fill_frame->next = NULL;
+#if PWC_DEBUG
+	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
+	pdev->fill_frame->sequence = pdev->sequence++;
+#endif
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+	return ret;
+}
+ 
+
+/**
+  \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. 
+  
+  If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
+ */
+static void pwc_reset_buffers(struct pwc_device *pdev)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	pdev->full_frames = NULL;
+	pdev->full_frames_tail = NULL;
+	for (i = 0; i < default_fbufs; i++) {
+		pdev->fbuf[i].filled = 0;
+		if (i > 0)
+			pdev->fbuf[i].next = &pdev->fbuf[i - 1];
+		else
+			pdev->fbuf->next = NULL;
+	}
+	pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
+	pdev->empty_frames_tail = pdev->fbuf;
+	pdev->read_frame = NULL;
+	pdev->fill_frame = pdev->empty_frames;
+	pdev->empty_frames = pdev->empty_frames->next;
+
+	pdev->image_read_pos = 0;
+	pdev->fill_image = 0;
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+}
+
+
+/**
+  \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
+ */
+static int pwc_handle_frame(struct pwc_device *pdev)
+{
+	int ret = 0;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	/* First grab our read_frame; this is removed from all lists, so
+	   we can release the lock after this without problems */
+	if (pdev->read_frame != NULL) {
+		/* This can't theoretically happen */
+		Err("Huh? Read frame still in use?\n");
+	}
+	else {
+		if (pdev->full_frames == NULL) {
+			Err("Woops. No frames ready.\n");
+		}
+		else {
+			pdev->read_frame = pdev->full_frames;
+			pdev->full_frames = pdev->full_frames->next;
+			pdev->read_frame->next = NULL;
+		}
+
+		if (pdev->read_frame != NULL) {
+#if PWC_DEBUG
+			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
+#endif
+			/* Decompression is a lenghty process, so it's outside of the lock.
+			   This gives the isoc_handler the opportunity to fill more frames 
+			   in the mean time.
+			*/
+			spin_unlock_irqrestore(&pdev->ptrlock, flags);
+			ret = pwc_decompress(pdev);
+			spin_lock_irqsave(&pdev->ptrlock, flags);
+
+			/* We're done with read_buffer, tack it to the end of the empty buffer list */
+			if (pdev->empty_frames == NULL) {
+				pdev->empty_frames = pdev->read_frame;
+				pdev->empty_frames_tail = pdev->empty_frames;
+			}
+			else {
+				pdev->empty_frames_tail->next = pdev->read_frame;
+				pdev->empty_frames_tail = pdev->read_frame;
+			}
+			pdev->read_frame = NULL;
+		}
+	}
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+	return ret;
+}
+
+/**
+  \brief Advance pointers of image buffer (after each user request) 
+*/
+static inline void pwc_next_image(struct pwc_device *pdev)
+{
+	pdev->image_used[pdev->fill_image] = 0;
+	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+}
+
+/* 2001-10-14: The YUV420 is still there, but you can only set it from within 
+   a program (YUV420P being the default) */
+static int pwc_set_palette(struct pwc_device *pdev, int pal)
+{
+	if (   pal == VIDEO_PALETTE_YUV420
+            || pal == VIDEO_PALETTE_YUV420P
+#if PWC_DEBUG
+            || pal == VIDEO_PALETTE_RAW
+#endif
+	) {
+		pdev->vpalette = pal;
+		pwc_set_image_buffer_size(pdev);
+		return 0;
+	}
+	Trace(TRACE_READ, "Palette %d not supported.\n", pal);
+	return -1;
+}
+
+
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(struct urb *urb)
+{
+	struct pwc_device *pdev;
+	int i, fst, flen;
+	int awake;
+	struct pwc_frame_buf *fbuf;
+	unsigned char *fillptr, *iso_buf;
+
+	pdev = (struct pwc_device *)urb->context;
+	if (pdev == NULL) {
+		Err("isoc_handler() called with NULL device?!\n");
+		return;
+	}
+#ifdef PWC_MAGIC	
+	if (pdev->magic != PWC_MAGIC) {
+		Err("isoc_handler() called with bad magic!\n");
+		return;
+	}
+#endif
+	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n");
+		return;
+	}
+	if (urb->status != -EINPROGRESS && urb->status != 0) {
+		char *errmsg;
+		
+		errmsg = "Unknown";
+		switch(urb->status) {
+			case -ENOSR:		errmsg = "Buffer error (overrun)"; break;
+			case -EPIPE:		errmsg = "Stalled (device not responding)"; break;
+			case -EOVERFLOW:	errmsg = "Babble (bad cable?)"; break;
+			case -EPROTO:		errmsg = "Bit-stuff error (bad cable?)"; break;
+			case -EILSEQ:		errmsg = "CRC/Timeout"; break;
+			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
+		}
+		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
+		return;
+	}
+
+	fbuf = pdev->fill_frame;
+	if (fbuf == NULL) {
+		Err("pwc_isoc_handler without valid fill frame.\n");
+		wake_up_interruptible(&pdev->frameq);
+		return;
+	}
+	fillptr = fbuf->data + fbuf->filled;
+	awake = 0;
+
+	/* vsync: 0 = don't copy data
+	          1 = sync-hunt
+	          2 = synched 
+	 */
+	/* Compact data */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		fst  = urb->iso_frame_desc[i].status;
+		flen = urb->iso_frame_desc[i].actual_length;
+		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		if (fst == 0) {
+			if (flen > 0) { /* if valid data... */
+				if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
+					pdev->vsync = 2;
+
+					/* ...copy data to frame buffer, if possible */
+					if (flen + fbuf->filled > pdev->frame_size) {
+						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_size = %d).\n", flen, pdev->frame_size);
+						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
+						pdev->vframes_error++;
+					}
+					else {
+						memmove(fillptr, iso_buf, flen);
+						fillptr += flen;
+					}
+				}
+				fbuf->filled += flen;
+			} /* ..flen > 0 */
+
+			if (flen < pdev->vlast_packet_size) {
+				/* Shorter packet... We probably have the end of an image-frame; 
+				   wake up read() process and let select()/poll() do something.
+				   Decompression is done in user time over there. 
+				 */
+				if (pdev->vsync == 2) {
+					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
+					   frames on the USB wire after an exposure change. This conditition is 
+					   however detected  in the cam and a bit is set in the header.
+					 */
+					if (pdev->type == 730) {
+						unsigned char *ptr = (unsigned char *)fbuf->data;
+						
+						if (ptr[1] == 1 && ptr[0] & 0x10) {
+#if PWC_DEBUG
+							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
+#endif
+							pdev->drop_frames = 2;
+							pdev->vframes_error++;
+						}
+						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
+						   after a short frame; this condition is filtered out specifically. A 4 byte
+						   frame doesn't make sense anyway.
+						   So we get either this sequence: 
+						   	drop_bit set -> 4 byte frame -> short frame -> good frame
+						   Or this one:
+						   	drop_bit set -> short frame -> good frame
+						   So we drop either 3 or 2 frames in all!
+						 */
+						if (fbuf->filled == 4)
+							pdev->drop_frames++;
+					}
+
+					/* In case we were instructed to drop the frame, do so silently.
+					   The buffer pointers are not updated either (but the counters are reset below).
+					 */
+					if (pdev->drop_frames)
+						pdev->drop_frames--;
+					else {
+						/* Check for underflow first */
+						if (fbuf->filled < pdev->frame_size) {
+							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
+							pdev->vframes_error++;
+						}
+						else {
+							/* Send only once per EOF */
+							awake = 1; /* delay wake_ups */
+							
+							/* Find our next frame to fill. This will always succeed, since we
+							 * nick a frame from either empty or full list, but if we had to
+							 * take it from the full list, it means a frame got dropped.
+							 */
+							if (pwc_next_fill_frame(pdev)) {
+								pdev->vframes_dumped++;
+								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
+									if (pdev->vframes_dumped < 20)
+										Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
+									if (pdev->vframes_dumped == 20)
+										Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
+								}
+							}
+							fbuf = pdev->fill_frame;
+						}
+					} /* !drop_frames */
+					pdev->vframe_count++;
+				}
+				fbuf->filled = 0;
+				fillptr = fbuf->data;
+				pdev->vsync = 1;
+			} /* .. flen < last_packet_size */
+			pdev->vlast_packet_size = flen;
+		} /* ..status == 0 */
+#ifdef PWC_DEBUG
+		/* This is normally not interesting to the user, unless you are really debugging something */
+		else 
+			Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+#endif			
+	}
+	if (awake)
+		wake_up_interruptible(&pdev->frameq);
+}
+
+
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+	struct usb_device *udev;
+	struct urb *urb;
+	int i, j, ret;
+
+	struct usb_interface_descriptor *idesc;
+	int cur_alt;
+
+	if (pdev == NULL)
+		return -EFAULT;
+	if (pdev->iso_init)
+		return 0;
+	pdev->vsync = 0;
+	udev = pdev->udev;
+	
+	/* Get the current alternate interface, adjust packet size */
+	if (!udev->actconfig)
+		return -EFAULT;
+	cur_alt = udev->actconfig->interface[0].act_altsetting;
+	idesc = &udev->actconfig->interface[0].altsetting[cur_alt];
+	if (!idesc)
+		return -EFAULT;
+
+	/* Search video endpoint */
+	pdev->vmax_packet_size = -1;
+	for (i = 0; i < idesc->bNumEndpoints; i++)
+		if ((idesc->endpoint[i].bEndpointAddress & 0xF) == pdev->vendpoint) {
+			pdev->vmax_packet_size = idesc->endpoint[i].wMaxPacketSize;
+			break;
+		}
+	
+	if (pdev->vmax_packet_size < 0) {
+		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+		return -ENFILE; /* Odd error, that should be noticable */
+	}
+
+	ret = 0;
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+		if (urb == NULL) {
+			Err("Failed to allocate urb %d\n", i);
+			ret = -ENOMEM;
+			break;
+		}
+		pdev->sbuf[i].urb = urb;
+	}
+	if (ret) {
+		/* De-allocate in reverse order */
+		while (i >= 0) {
+			if (pdev->sbuf[i].urb != NULL)
+				usb_free_urb(pdev->sbuf[i].urb);
+			pdev->sbuf[i].urb = NULL;
+			i--;
+		}
+		return ret;
+	}
+	
+	
+	/* init URB structure */	
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = pdev->sbuf[i].urb;
+
+		urb->next = pdev->sbuf[(i + 1) % MAX_ISO_BUFS].urb;
+		urb->dev = udev;
+	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+		urb->transfer_flags = USB_ISO_ASAP;
+	        urb->transfer_buffer = pdev->sbuf[i].data;
+	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+	        urb->complete = pwc_isoc_handler;
+	        urb->context = pdev;
+		urb->start_frame = 0;
+		urb->number_of_packets = ISO_FRAMES_PER_DESC;
+		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+			urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
+		}
+	}
+
+	/* link */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
+		if (ret)
+			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+		else
+			Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n");
+	}
+
+	/* data should stream in now */
+	pdev->iso_init = 1;
+	return 0;
+}
+
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+	int i;
+	
+	if (pdev == NULL)
+		return;
+	if (!pdev->iso_init)
+		return;
+	/* Stop camera, but only if we are sure the camera is still there */
+	if (!pdev->unplugged)
+		usb_set_interface(pdev->udev, 0, 0);
+	/* Unlinking ISOC buffers one by one */
+	for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
+		pdev->sbuf[i].urb->next = NULL;
+		usb_unlink_urb(pdev->sbuf[i].urb);
+		usb_free_urb(pdev->sbuf[i].urb);
+		pdev->sbuf[i].urb = NULL;
+	}
+	pdev->iso_init = 0;
+}
+
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
+{
+	int ret;
+
+	/* Stop isoc stuff */
+	pwc_isoc_cleanup(pdev);
+	/* Reset parameters */
+	pwc_reset_buffers(pdev);
+	/* Try to set video mode... */
+	ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+	if (ret) /* That failed... restore old mode (we know that worked) */
+		ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+	else /* Set (new) alternate interface */
+		ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+	if (!ret)
+		ret = pwc_isoc_init(pdev);
+	pdev->drop_frames = 1; /* try to avoid garbage during switch */
+	return ret;
+}
+
+
+static inline void set_mem_leak(void *ptr)
+{
+	down(&mem_lock);
+	if (mem_leak != NULL)
+		Err("Memleak: overwriting mem_leak pointer!\n");
+	Trace(TRACE_MEMORY, "Setting mem_leak to 0x%p.\n", ptr);
+	mem_leak = ptr;
+	up(&mem_lock);
+}
+
+static inline void free_mem_leak(void)
+{
+	down(&mem_lock);
+	if (mem_leak != NULL) {
+		Trace(TRACE_MEMORY, "Freeing mem_leak ptr 0x%p.\n", mem_leak);
+		kfree(mem_leak);
+		mem_leak = NULL;
+	}
+	up(&mem_lock);
+}
+
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static int pwc_video_open(struct inode *inode, struct file *file)
+{
+	int i;
+	struct video_device *vdev = video_devdata(file);
+	struct pwc_device *pdev;
+
+	Trace(TRACE_OPEN, "video_open called(0x%p).\n", vdev);
+	
+	pdev = (struct pwc_device *)vdev->priv;
+	if (pdev == NULL)
+		BUG();
+	if (pdev->vopen)
+		return -EBUSY;
+	
+	down(&pdev->modlock);
+	if (!pdev->usb_init) {
+		Trace(TRACE_OPEN, "Doing first time initialization.\n");
+		/* Reset camera */
+		if (usb_set_interface(pdev->udev, 0, 0))
+			Info("Failed to set alternate interface to 0.\n");
+		pdev->usb_init = 1;
+	}
+
+	/* Turn on camera */
+	if (power_save) {
+		i = pwc_camera_power(pdev, 1);
+		if (i < 0)
+			Info("Failed to restore power to the camera! (%d)\n", i);
+	}
+	/* Set LED on/off time */
+	if (pwc_set_leds(pdev, led_on, led_off) < 0)
+		Info("Failed to set LED on/off time.\n");
+
+	/* Find our decompressor, if any */
+	pdev->decompressor = pwc_find_decompressor(pdev->type);
+#if PWC_DEBUG	
+	Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor);
+#endif
+
+	/* So far, so good. Allocate memory. */
+	i = pwc_allocate_buffers(pdev);
+	if (i < 0) {
+		Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
+		up(&pdev->modlock);
+		return i;
+	}
+	
+	/* Reset buffers & parameters */
+	pwc_reset_buffers(pdev);
+	for (i = 0; i < default_mbufs; i++)
+		pdev->image_used[i] = 0;
+	pdev->vframe_count = 0;
+	pdev->vframes_dumped = 0;
+	pdev->vframes_error = 0;
+	pdev->vpalette = default_palette;
+#if PWC_DEBUG	
+	pdev->sequence = 0;
+#endif
+
+	/* Set some defaults */
+	pdev->vsnapshot = 0;
+	if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
+		pdev->vsize = PSZ_QSIF;
+	else
+		pdev->vsize = PSZ_QCIF;
+	pdev->vframes = 10;
+
+	/* Start iso pipe for video; first try user-supplied size/fps, if
+	   that fails try QCIF/10 or QSIF/10 (a reasonable default), 
+	   then give up 
+	 */
+	i = pwc_set_video_mode(pdev, pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y, default_fps, pdev->vcompression, 0);
+	if (i)	{
+		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
+		if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
+			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+		else
+			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+	}
+	if (i) {
+		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+		up(&pdev->modlock);
+		return i;
+	}
+	
+	i = usb_set_interface(pdev->udev, 0, pdev->valternate);
+	if (i) {
+		Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
+		up(&pdev->modlock);
+		return -EINVAL;
+	}
+	i = pwc_isoc_init(pdev);
+	if (i) {
+		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+		MOD_DEC_USE_COUNT;
+		up(&pdev->modlock);
+		return i;
+	}
+
+	pdev->vopen++;
+	file->private_data = vdev;
+	/* lock decompressor; this has a small race condition, since we 
+	   could in theory unload pwcx.o between pwc_find_decompressor()
+	   above and this call. I doubt it's ever going to be a problem.
+	 */
+	if (pdev->decompressor != NULL)
+		pdev->decompressor->lock();
+	up(&pdev->modlock);
+	Trace(TRACE_OPEN, "video_open() returning 0.\n");
+	return 0;
+}
+
+/* Note that all cleanup is done in the reverse order as in _open */
+static int pwc_video_close(struct inode *inode, struct file *file)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	int i;
+
+	Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev);
+
+	pdev = (struct pwc_device *)vdev->priv;
+	if (pdev->vopen == 0)
+		Info("video_close() called on closed device?\n");
+
+	/* Free isoc URBs */
+	pwc_isoc_cleanup(pdev);
+
+	/* Dump statistics, but only if a reasonable amount of frames were
+	   processed (to prevent endless log-entries in case of snap-shot
+	   programs) 
+	 */
+	if (pdev->vframe_count > 20)
+		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+
+	if (!pdev->unplugged) {
+		/* Normal close: stop isochronuous and interrupt endpoint */
+		Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
+		usb_set_interface(pdev->udev, 0, 0);
+
+		/* Turn LEDs off */
+		if (pwc_set_leds(pdev, 0, 0) < 0)
+			Info("Failed to set LED on/off time..\n");
+		/* Power down camere to save energy */
+		if (power_save) {
+			i = pwc_camera_power(pdev, 0);
+			if (i < 0) 
+				Err("Failed to power down camera (%d)\n", i);
+		}
+	}
+
+	pdev->vopen = 0;
+	if (pdev->decompressor != NULL) {
+		pdev->decompressor->exit();
+		pdev->decompressor->unlock();
+	}
+	pwc_free_buffers(pdev);
+
+	/* wake up _disconnect() routine */
+	if (pdev->unplugged)
+		wake_up(&pdev->remove_ok);
+	file->private_data = NULL;
+	return 0;
+}
+
+/*
+ *	FIXME: what about two parallel reads ????
+ *      ANSWER: Not supported. You can't open the device more than once,
+                despite what the V4L1 interface says. First, I don't see 
+                the need, second there's no mechanism of alerting the 
+                2nd/3rd/... process of events like changing image size.
+                And I don't see the point of blocking that for the 
+                2nd/3rd/... process.
+                In multi-threaded environments reading parallel from any
+                device is tricky anyhow.
+ */
+ 
+static int pwc_video_read(struct file *file, char *buf,
+			  size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	int noblock = file->f_flags & O_NONBLOCK;
+	DECLARE_WAITQUEUE(wait, current);
+
+	Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count);
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+	if (pdev->unplugged) {
+		Info("pwc_video_read: Device got unplugged (1).\n");
+		return -EPIPE; /* unplugged device! */
+	}
+
+	/* In case we're doing partial reads, we don't have to wait for a frame */
+	if (pdev->image_read_pos == 0) {
+		/* Do wait queueing according to the (doc)book */
+		add_wait_queue(&pdev->frameq, &wait);
+		while (pdev->full_frames == NULL) {
+	                if (noblock) {
+	                	remove_wait_queue(&pdev->frameq, &wait);
+	                	set_current_state(TASK_RUNNING);
+	                	return -EWOULDBLOCK;
+	                }
+	                if (signal_pending(current)) {
+	                	remove_wait_queue(&pdev->frameq, &wait);
+	                	set_current_state(TASK_RUNNING);
+	                	return -ERESTARTSYS;
+	                }
+	                schedule();
+	               	set_current_state(TASK_INTERRUPTIBLE);
+		}
+		remove_wait_queue(&pdev->frameq, &wait);
+		set_current_state(TASK_RUNNING);
+	                                                                                                                                                                                
+		/* Decompress [, convert] and release frame */
+		if (pwc_handle_frame(pdev))
+			return -EFAULT;
+	}
+
+	Trace(TRACE_READ, "Copying data to user space.\n");
+	/* copy bytes to user space; we allow for partial reads */
+	if (count + pdev->image_read_pos > pdev->view.size)
+		count = pdev->view.size - pdev->image_read_pos;
+	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+		return -EFAULT;
+	pdev->image_read_pos += count;
+	if (pdev->image_read_pos >= pdev->view.size) { /* All data has been read */
+		pdev->image_read_pos = 0;
+		pwc_next_image(pdev);
+	}
+	return count;
+}
+
+static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+	
+	poll_wait(file, &pdev->frameq, wait);
+	if (pdev->unplugged) {
+		Info("pwc_video_poll: Device got unplugged.\n");
+		return POLLERR;
+	}		
+	if (pdev->full_frames != NULL) /* we have frames waiting */
+		return (POLLIN | POLLRDNORM);
+
+	return 0;
+}
+        
+static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	DECLARE_WAITQUEUE(wait, current);
+	
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+	switch (cmd) {
+		/* Query cabapilities */
+		case VIDIOCGCAP: 
+		{
+			struct video_capability *caps = arg;
+
+			strcpy(caps->name, vdev->name);
+			caps->type = VID_TYPE_CAPTURE;
+			caps->channels = 1;
+			caps->audios = 1;
+			caps->minwidth  = pdev->view_min.x;
+			caps->minheight = pdev->view_min.y;
+			caps->maxwidth  = pdev->view_max.x;
+			caps->maxheight = pdev->view_max.y;
+			break;
+		}
+
+		/* Channel functions (simulate 1 channel) */
+		case VIDIOCGCHAN:
+		{
+			struct video_channel *v = arg;
+
+			if (v->channel != 0)
+				return -EINVAL;
+			v->flags = 0;
+			v->tuners = 0;
+			v->type = VIDEO_TYPE_CAMERA;
+			strcpy(v->name, "Webcam");
+			return 0;
+		}
+
+		case VIDIOCSCHAN:
+		{	
+			/* The spec says the argument is an integer, but
+			   the bttv driver uses a video_channel arg, which
+			   makes sense becasue it also has the norm flag.
+			 */
+			struct video_channel *v = arg;
+			if (v->channel != 0)
+				return -EINVAL;
+			return 0;
+		}
+
+
+		/* Picture functions; contrast etc. */
+		case VIDIOCGPICT:
+		{
+			struct video_picture *p = arg;
+			int val;
+
+			p->colour = 0x8000;
+			p->hue = 0x8000;
+			val = pwc_get_brightness(pdev);
+			if (val >= 0)
+				p->brightness = val;
+			else
+				p->brightness = 0xffff;
+			val = pwc_get_contrast(pdev);
+			if (val >= 0)
+				p->contrast = val;
+			else
+				p->contrast = 0xffff;
+			/* Gamma, Whiteness, what's the difference? :) */
+			val = pwc_get_gamma(pdev);
+			if (val >= 0)
+				p->whiteness = val;
+			else
+				p->whiteness = 0xffff;
+			val = pwc_get_saturation(pdev);
+			if (val >= 0)
+				p->colour = val;
+			else
+				p->colour = 0xffff;
+			p->depth = 24;
+			p->palette = pdev->vpalette;
+			p->hue = 0xFFFF; /* N/A */
+			break;
+		}
+		
+		case VIDIOCSPICT:
+		{
+			struct video_picture *p = arg;
+			/*
+			 *	FIXME:	Suppose we are mid read
+			        ANSWER: No problem: the firmware of the camera
+			                can handle brightness/contrast/etc
+			                changes at _any_ time, and the palette
+			                is used exactly once in the uncompress
+			                routine.
+			 */
+			if (p->palette && p->palette != pdev->vpalette) {
+				if (pwc_set_palette(pdev, p->palette) < 0)
+					return -EINVAL;
+			}
+			pwc_set_brightness(pdev, p->brightness);
+			pwc_set_contrast(pdev, p->contrast);
+			pwc_set_gamma(pdev, p->whiteness);
+			pwc_set_saturation(pdev, p->colour);
+			break;
+		}
+
+		/* Window/size parameters */		
+		case VIDIOCGWIN:
+		{
+			struct video_window *vw = arg;
+			
+			vw->x = 0;
+			vw->y = 0;
+			vw->width = pdev->view.x;
+			vw->height = pdev->view.y;
+			vw->chromakey = 0;
+			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | 
+			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+			break;
+		}
+		
+		case VIDIOCSWIN:
+		{
+			struct video_window *vw = arg;
+			int fps, snapshot, ret;
+
+			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
+			if (fps == 0)
+				fps = pdev->vframes;
+			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+				return 0;
+			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
+			if (ret)
+				return ret;
+			break;		
+		}
+		
+		/* We don't have overlay support (yet) */
+		case VIDIOCGFBUF:
+		{
+			struct video_buffer *vb = arg;
+
+			memset(vb,0,sizeof(*vb));
+			break;
+		}
+
+		/* mmap() functions */
+		case VIDIOCGMBUF:
+		{
+			/* Tell the user program how much memory is needed for a mmap() */
+			struct video_mbuf *vm = arg;
+			int i;
+
+			memset(vm, 0, sizeof(*vm));
+			vm->size = default_mbufs * pdev->len_per_image;
+			vm->frames = default_mbufs; /* double buffering should be enough for most applications */
+			for (i = 0; i < default_mbufs; i++)
+				vm->offsets[i] = i * pdev->len_per_image;
+			break;
+		}
+
+		case VIDIOCMCAPTURE:
+		{
+			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+			struct video_mmap *vm = arg;
+
+			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
+			if (vm->frame < 0 || vm->frame >= default_mbufs)
+				return -EINVAL;
+
+			/* xawtv is nasty. It probes the available palettes
+			   by setting a very small image size and trying
+			   various palettes... The driver doesn't support
+			   such small images, so I'm working around it.
+			 */
+			if (vm->format && vm->format != pdev->vpalette)
+				if (pwc_set_palette(pdev, vm->format) < 0)
+					return -EINVAL;
+			 
+			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
+			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
+				int ret;
+				
+				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+				if (ret)
+					return ret;
+			} /* ... size mismatch */
+
+			/* FIXME: should we lock here? */
+			if (pdev->image_used[vm->frame])
+				return -EBUSY;	/* buffer wasn't available. Bummer */
+			pdev->image_used[vm->frame] = 1;
+
+			/* Okay, we're done here. In the SYNC call we wait until a 
+			   frame comes available, then expand image into the given 
+			   buffer.
+			   In contrast to the CPiA cam the Philips cams deliver a 
+			   constant stream, almost like a grabber card. Also,
+			   we have separate buffers for the rawdata and the image,
+			   meaning we can nearly always expand into the requested buffer.
+			 */
+			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
+			break;
+		}
+
+		case VIDIOCSYNC:
+		{
+			/* The doc says: "Whenever a buffer is used it should
+			   call VIDIOCSYNC to free this frame up and continue."
+			   
+			   The only odd thing about this whole procedure is 
+			   that MCAPTURE flags the buffer as "in use", and
+			   SYNC immediately unmarks it, while it isn't 
+			   after SYNC that you know that the buffer actually
+			   got filled! So you better not start a CAPTURE in
+			   the same frame immediately (use double buffering). 
+			   This is not a problem for this cam, since it has 
+			   extra intermediate buffers, but a hardware 
+			   grabber card will then overwrite the buffer 
+			   you're working on.
+			 */
+			int *mbuf = arg;
+			int ret;
+
+			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
+
+			/* bounds check */
+			if (*mbuf < 0 || *mbuf >= default_mbufs)
+				return -EINVAL;
+			/* check if this buffer was requested anyway */
+			if (pdev->image_used[*mbuf] == 0)
+				return -EINVAL;
+
+			/* Add ourselves to the frame wait-queue.
+			   
+			   FIXME: needs auditing for safety.
+			   QUSTION: In what respect? I think that using the
+			            frameq is safe now.
+			 */
+			add_wait_queue(&pdev->frameq, &wait);
+			while (pdev->full_frames == NULL) {
+				if (pdev->unplugged) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -ENODEV;
+				}
+			
+	                	if (signal_pending(current)) {
+	                		remove_wait_queue(&pdev->frameq, &wait);
+		                	set_current_state(TASK_RUNNING);
+		                	return -ERESTARTSYS;
+	        	        }
+		                set_current_state(TASK_INTERRUPTIBLE);
+	                	schedule();
+			}
+			remove_wait_queue(&pdev->frameq, &wait);
+			set_current_state(TASK_RUNNING);
+				
+			/* The frame is ready. Expand in the image buffer 
+			   requested by the user. I don't care if you 
+			   mmap() 5 buffers and request data in this order: 
+			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+			   Grabber hardware may not be so forgiving.
+			 */
+			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
+			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
+			/* Decompress, etc */
+			ret = pwc_handle_frame(pdev);
+			pdev->image_used[*mbuf] = 0;
+			if (ret)
+				return -EFAULT;
+			break;
+		}
+		
+		case VIDIOCGAUDIO:
+		{
+			struct video_audio *v = arg;
+			
+			strcpy(v->name, "Microphone");
+			v->audio = -1; /* unknown audio minor */
+			v->flags = 0;
+			v->mode = VIDEO_SOUND_MONO;
+			v->volume = 0;
+			v->bass = 0;
+			v->treble = 0;
+			v->balance = 0x8000;
+			v->step = 1;
+			break;	
+		}
+		
+		case VIDIOCSAUDIO:
+		{
+			/* Dummy: nothing can be set */
+			break;
+		}
+		
+		case VIDIOCGUNIT:
+		{
+			struct video_unit *vu = arg;
+			
+			vu->video = pdev->vdev->minor & 0x3F;
+			vu->audio = -1; /* not known yet */
+			vu->vbi = -1;
+			vu->radio = -1;
+			vu->teletext = -1;
+			break;
+		}
+		default:
+			return pwc_ioctl(pdev, cmd, arg);
+	} /* ..switch */
+	return 0;
+}	
+
+static int pwc_video_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
+}
+
+
+static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long page, pos;
+	
+	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+	pdev = vdev->priv;
+
+	/* FIXME - audit mmap during a read */		
+	pos = (unsigned long)pdev->image_data;
+	while (size > 0) {
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+}
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)
+{
+	struct pwc_device *pdev = NULL;
+	struct video_device *vdev;
+	int vendor_id, product_id, type_id;
+	int i, hint;
+	int video_nr = -1; /* default: use next available device */
+	char serial_number[30];
+
+	free_mem_leak();
+	
+	/* Check if we can handle this device */
+	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum);
+
+	/* the interfaces are probed one by one. We are only interested in the
+	   video interface (0) now.
+	   Interface 1 is the Audio Control, and interface 2 Audio itself.
+	 */
+	if (ifnum > 0) 
+		return NULL;
+
+	vendor_id = udev->descriptor.idVendor;
+	product_id = udev->descriptor.idProduct;
+
+	if (vendor_id == 0x0471) {
+		switch (product_id) {
+		case 0x0302:
+			Info("Philips PCA645VC USB webcam detected.\n");
+			type_id = 645;
+			break;
+		case 0x0303:
+			Info("Philips PCA646VC USB webcam detected.\n");
+			type_id = 646;
+			break;
+		case 0x0304:
+			Info("Askey VC010 type 2 USB webcam detected.\n");
+			type_id = 646;
+			break;
+		case 0x0307:
+			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+			type_id = 675;
+			break;
+		case 0x0308:
+			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+			type_id = 680;
+			break;
+		case 0x030C:
+			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+			type_id = 690;
+			break;
+		case 0x0310:
+			Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
+			type_id = 730;
+			break;
+		case 0x0311:
+			Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
+			type_id = 740;
+			break;
+		case 0x0312:
+			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+			type_id = 750;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else if (vendor_id == 0x069A) {
+		switch(product_id) {
+		case 0x0001:
+			Info("Askey VC010 type 1 USB webcam detected.\n");
+			type_id = 645;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else if (vendor_id == 0x046d) {
+		switch(product_id) {
+		case 0x08b0:
+			Info("Logitech QuickCam 3000 Pro detected.\n");
+			type_id = 730;
+        		break;
+        	default:
+        		return NULL;
+        		break;
+        	}
+        }
+	else if (vendor_id == 0x055d) {
+		/* I don't know the difference between the C10 and the C30;
+		   I suppose the difference is the sensor, but both cameras
+		   work equally well with a type_id of 675
+		 */
+		switch(product_id) {
+		case 0x9000:
+			Info("Samsung MPC-C10 USB webcam detected.\n");
+			type_id = 675;
+			break;
+		case 0x9001:
+			Info("Samsung MPC-C30 USB webcam detected.\n");
+			type_id = 675;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else if (vendor_id == 0x041e) {
+		switch(product_id) {
+		case 0x400c:
+			Info("Creative Labs Webcam 5 detected.\n");
+			type_id = 730;
+			break;
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else if (vendor_id == 0x04cc) { 
+		switch(product_id) {
+		case 0x8116:
+			Info("SOTEC CMS-001 USB webcam detected.\n");
+			type_id = 730;
+			break;  
+		default:
+			return NULL;
+			break;
+		}
+	}
+	else return NULL; /* Not Philips, Askey, Logitech, Samsung, Creative or SOTEC, for sure. */
+
+	memset(serial_number, 0, 30);
+	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+
+	if (udev->descriptor.bNumConfigurations > 1)
+		Info("Warning: more than 1 configuration available.\n");
+
+	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
+	if (pdev == NULL) {
+		Err("Oops, could not allocate memory for pwc_device.\n");
+		return NULL;
+	}
+	memset(pdev, 0, sizeof(struct pwc_device));
+	pdev->type = type_id;
+	pwc_construct(pdev);
+
+	init_MUTEX(&pdev->modlock);
+	pdev->ptrlock = SPIN_LOCK_UNLOCKED;
+
+	pdev->udev = udev;
+	init_waitqueue_head(&pdev->frameq);
+	init_waitqueue_head(&pdev->remove_ok);
+	pdev->vcompression = pwc_preferred_compression;
+
+	/* Now hook it up to the video subsystem */
+	vdev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
+	if (vdev == NULL) {
+		Err("Oops, could not allocate memory for video_device.\n");
+		return NULL;
+	}
+	memcpy(vdev, &pwc_template, sizeof(pwc_template));
+	sprintf(vdev->name, "Philips %d webcam", pdev->type);
+	SET_MODULE_OWNER(vdev);
+	pdev->vdev = vdev;
+	vdev->priv = pdev;
+
+	pdev->release = udev->descriptor.bcdDevice;
+	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
+
+	/* Now search device_hint[] table for a match, so we can hint a node number. */
+	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
+		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
+		     (device_hint[hint].pdev == NULL)) {
+			/* so far, so good... try serial number */
+			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
+			    	/* match! */
+			    	video_nr = device_hint[hint].device_node;
+			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
+			    	break;
+			}
+		}
+	}
+
+	i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr);
+	if (i < 0) {
+		Err("Failed to register as video device (%d).\n", i);
+		return NULL;
+	}
+	else {
+		Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev);
+		Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F);
+	}
+	/* occupy slot */
+	if (hint < MAX_DEV_HINTS) 
+		device_hint[hint].pdev = pdev;
+
+	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+	return pdev;
+}
+
+/* The user janked out the cable... */
+static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
+{
+	struct pwc_device *pdev;
+	int hint;
+	DECLARE_WAITQUEUE(wait, current);
+
+	lock_kernel();
+	free_mem_leak();
+
+	pdev = (struct pwc_device *)ptr;
+	if (pdev == NULL) {
+		Err("pwc_disconnect() Called without private pointer.\n");
+		return;
+	}
+	if (pdev->udev == NULL) {
+		Err("pwc_disconnect() already called for %p\n", pdev);
+		return;
+	}
+	if (pdev->udev != udev) {
+		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
+		return;
+	}
+#ifdef PWC_MAGIC	
+	if (pdev->magic != PWC_MAGIC) {
+		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
+		return;
+	}
+#endif	
+	
+	pdev->unplugged = 1;
+	if (pdev->vdev != NULL) {
+		video_unregister_device(pdev->vdev); 
+		if (pdev->vopen) {
+			Info("Disconnected while device/video is open!\n");
+			
+			/* Wake up any processes that might be waiting for
+			   a frame, let them return an error condition
+			 */
+			wake_up(&pdev->frameq);
+			
+			/* Wait until we get a 'go' from _close(). This used
+			   to have a gigantic race condition, since we kfree()
+			   stuff here, but we have to wait until close() 
+			   is finished. 
+			 */
+			   
+			Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
+			add_wait_queue(&pdev->remove_ok, &wait);
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			/* ... wait ... */
+			schedule();
+			remove_wait_queue(&pdev->remove_ok, &wait);
+			set_current_state(TASK_RUNNING);
+			Trace(TRACE_PROBE, "Done sleeping.\n");
+			set_mem_leak(pdev->vdev);
+			pdev->vdev = NULL;
+		}
+		else {
+			/* Normal disconnect; remove from available devices */
+			Trace(TRACE_PROBE, "Unregistering video device normally.\n");
+			kfree(pdev->vdev);
+			pdev->vdev = NULL;
+		}
+	}
+
+	/* search device_hint[] table if we occupy a slot, by any chance */
+	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+		if (device_hint[hint].pdev == pdev)
+			device_hint[hint].pdev = NULL;
+
+	pdev->udev = NULL;
+	unlock_kernel();
+	kfree(pdev);
+}
+
+
+/* *grunt* We have to do atoi ourselves :-( */
+static int pwc_atoi(char *s)
+{
+	int k = 0;
+	
+	k = 0;
+	while (*s != '\0' && *s >= '0' && *s <= '9') {
+		k = 10 * k + (*s - '0');
+		s++;
+	}
+	return k;
+}
+
+
+/* 
+ * Initialization code & module stuff 
+ */
+
+static char *size = NULL;
+static int fps = 0;
+static int fbufs = 0;
+static int mbufs = 0;
+static int trace = -1;
+static int compression = -1;
+static int leds[2] = { -1, -1 };
+static char *dev_hint[10] = { };
+
+MODULE_PARM(size, "s");
+MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
+MODULE_PARM(fps, "i");
+MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
+MODULE_PARM(fbufs, "i");
+MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
+MODULE_PARM(mbufs, "i");
+MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
+MODULE_PARM(trace, "i");
+MODULE_PARM_DESC(trace, "For debugging purposes");
+MODULE_PARM(power_save, "i");
+MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
+MODULE_PARM(compression, "i");
+MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
+MODULE_PARM(leds, "2i");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+MODULE_PARM(dev_hint, "0-10s");
+MODULE_PARM_DESC(dev_hint, "Device node hints");
+
+MODULE_DESCRIPTION("Philips USB webcam driver");
+MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
+MODULE_LICENSE("GPL");
+
+static int __init usb_pwc_init(void)
+{
+	int i, sz;
+	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+
+	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
+	Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30, the Creative WebCam 5 and the SOTEC CMS-001.\n");
+
+	if (fps) {
+		if (fps < 5 || fps > 30) {
+			Err("Framerate out of bounds (5-30).\n");
+			return -EINVAL;
+		}
+		default_fps = fps;
+		Info("Default framerate set to %d.\n", default_fps);
+	}
+	
+	if (size) {
+		/* string; try matching with array */
+		for (sz = 0; sz < PSZ_MAX; sz++) {
+			if (!strcmp(sizenames[sz], size)) { /* Found! */
+				default_size = sz;
+				break;
+			}
+		}
+		if (sz == PSZ_MAX) {
+			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+			return -EINVAL;
+		}
+		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+	}
+	if (mbufs) {
+		if (mbufs < 1 || mbufs > MAX_IMAGES) {
+			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+			return -EINVAL;
+		}
+		default_mbufs = mbufs;
+		Info("Number of image buffers set to %d.\n", default_mbufs);
+	}
+	if (fbufs) {
+		if (fbufs < 2 || fbufs > MAX_FRAMES) {
+			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+			return -EINVAL;
+		}
+		default_fbufs = fbufs;
+		Info("Number of frame buffers set to %d.\n", default_fbufs);
+	}
+	if (trace >= 0) {
+		Info("Trace options: 0x%04x\n", trace);
+		pwc_trace = trace;
+	}
+	if (compression >= 0) {
+		if (compression > 3) {
+			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+			return -EINVAL;
+		}
+		pwc_preferred_compression = compression;
+		Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+	}
+	if (power_save)
+		Info("Enabling power save on open/close.\n");
+	if (leds[0] >= 0)
+		led_on = leds[0] / 100;
+	if (leds[1] >= 0)
+		led_off = leds[1] / 100;
+
+	/* Big device node whoopla. Basicly, it allows you to assign a 
+	   device node (/dev/videoX) to a camera, based on its type 
+	   & serial number. The format is [type[.serialnumber]:]node.
+
+           Any camera that isn't matched by these rules gets the next 
+           available free device node.
+	 */
+	for (i = 0; i < MAX_DEV_HINTS; i++) {
+		char *s, *colon, *dot;
+
+		/* This loop also initializes the array */
+		device_hint[i].pdev = NULL;
+		s = dev_hint[i];
+		if (s != NULL && *s != '\0') {
+			device_hint[i].type = -1; /* wildcard */
+			strcpy(device_hint[i].serial_number, "*");
+
+			/* parse string: chop at ':' & '/' */
+			colon = dot = s;
+			while (*colon != '\0' && *colon != ':')
+				colon++;
+			while (*dot != '\0' && *dot != '.')
+				dot++;
+			/* Few sanity checks */
+			if (*dot != '\0' && dot > colon) {
+				Err("Malformed camera hint: the colon must be after the dot.\n");
+				return -EINVAL;
+			}
+
+			if (*colon == '\0') {
+				/* No colon */
+				if (*dot != '\0') {
+					Err("Malformed camera hint: no colon + device node given.\n");
+					return -EINVAL;
+				}
+				else {
+					/* No type or serial number specified, just a number. */
+					device_hint[i].device_node = pwc_atoi(s);
+				}
+			}
+			else {
+				/* There's a colon, so we have at least a type and a device node */
+				device_hint[i].type = pwc_atoi(s);
+				device_hint[i].device_node = pwc_atoi(colon + 1);
+				if (*dot != '\0') {
+					/* There's a serial number as well */
+					int k;
+					
+					dot++;
+					k = 0;
+					while (*dot != ':' && k < 29) {
+						device_hint[i].serial_number[k++] = *dot;
+						dot++;
+					}
+					device_hint[i].serial_number[k] = '\0';
+				}
+			}
+#ifdef PWC_DEBUG		
+			Debug("device_hint[%d]:\n", i);
+			Debug("  type    : %d\n", device_hint[i].type);
+			Debug("  serial# : %s\n", device_hint[i].serial_number);
+			Debug("  node    : %d\n", device_hint[i].device_node);
+#endif			
+		}
+		else
+			device_hint[i].type = 0; /* not filled */
+	} /* ..for MAX_DEV_HINTS */
+
+	init_MUTEX(&mem_lock);
+ 	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+	return usb_register(&pwc_driver);
+}
+
+static void __exit usb_pwc_exit(void)
+{
+	free_mem_leak();
+	Trace(TRACE_MODULE, "Deregistering driver.\n");
+	usb_deregister(&pwc_driver);
+	Info("Philips webcam module removed.\n");
+}
+
+module_init(usb_pwc_init);
+module_exit(usb_pwc_exit);
+
diff -Nru a/drivers/usb/media/pwc-ioctl.h b/drivers/usb/media/pwc-ioctl.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc-ioctl.h	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,123 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001 Nemosoft Unv.    webcam@smcc.demon.nl
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for 
+                          changing white balance and red/blue gains
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API. 
+   
+   The #define names are built up like follows:
+   VIDIOC		VIDeo IOCtl prefix
+         PWC		Philps WebCam
+            G           optional: Get
+            S           optional: Set
+             ... 	the function
+ */
+
+
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour 
+   balance controls.
+ */
+#define PWC_FPS_SHIFT		16
+#define PWC_FPS_MASK		0x00FF0000
+#define PWC_FPS_FRMASK		0x003F0000
+#define PWC_FPS_SNAPSHOT	0x00400000
+
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR		0
+#define PWC_WB_OUTDOOR		1
+#define PWC_WB_FL		2
+#define PWC_WB_MANUAL		3
+#define PWC_WB_AUTO		4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). 
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside 
+   the camera; range 0..65535
+   When mode == PWC_WB_MANUAL, manual_red and manual_blue are set or read; 
+   otherwise undefined.
+   read_red and read_blue are read-only.
+*/   
+   
+struct pwc_whitebalance
+{
+	int mode;
+	int manual_red, manual_blue;	/* R/W */
+	int read_red, read_blue;	/* R/O */
+};
+
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+	int led_on;			/* Led on-time; range = 0..25000 */
+	int led_off;			/* Led off-time; range = 0..25000  */
+};
+
+
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER		_IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER		_IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY	_IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC		_IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC		_IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Turn LED on/off ; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+ /* Get state of LED; int range 0..65535 */
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+#endif
diff -Nru a/drivers/usb/media/pwc-misc.c b/drivers/usb/media/pwc-misc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc-misc.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,104 @@
+/* Linux driver for Philips webcam 
+   Various miscellaneous functions and tables.
+   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/  
+
+#include <linux/slab.h>
+
+#include "pwc.h"
+
+struct pwc_coord pwc_image_sizes[PSZ_MAX] = 
+{
+	{ 128,  96, 0 },
+	{ 160, 120, 0 },
+	{ 176, 144, 0 },
+	{ 320, 240, 0 },
+	{ 352, 288, 0 },
+	{ 640, 480, 0 },
+};
+
+/* x,y -> PSZ_ */
+int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+{
+	int i, find;
+
+	/* Make sure we don't go beyond our max size */
+	if (width > pdev->view_max.x || height > pdev->view_max.y)
+		return -1;
+	/* Find the largest size supported by the camera that fits into the
+	   requested size. 
+	 */
+	find = -1;
+	for (i = 0; i < PSZ_MAX; i++) {
+		if (pdev->image_mask & (1 << i)) {
+			if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
+				find = i;
+		}
+	}
+	return find;
+}
+
+/* initialize variables depending on type */
+void pwc_construct(struct pwc_device *pdev)
+{
+	switch(pdev->type) {
+	case 645:
+	case 646:
+		pdev->view_min.x = 128;
+		pdev->view_min.y =  96;
+		pdev->view_max.x = 352;
+		pdev->view_max.y = 288;
+		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+		pdev->vcinterface = 2;
+		pdev->vendpoint = 4;
+		pdev->frame_header_size = 0;
+		pdev->frame_trailer_size = 0;
+		break;
+	case 675:
+	case 680:
+	case 690:
+		pdev->view_min.x = 128;
+		pdev->view_min.y =  96;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 4;
+		pdev->frame_header_size = 0;
+		pdev->frame_trailer_size = 0;
+		break;
+	case 730:
+	case 740:
+	case 750:
+		pdev->view_min.x = 160;
+		pdev->view_min.y = 120;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 5;
+		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+		break;
+	}
+	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
+	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
+	/* length of image, in YUV format */
+	pdev->len_per_image = (pdev->view_max.size * 3) / 2;
+}
+
+
diff -Nru a/drivers/usb/media/pwc-uncompress.c b/drivers/usb/media/pwc-uncompress.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc-uncompress.c	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,190 @@
+/* Linux driver for Philips webcam 
+   Decompression frontend.
+   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+/*
+   This is where the decompression routines register and unregister 
+   themselves. It also has a decompressor wrapper function.
+*/
+
+#include <asm/types.h>
+
+#include "pwc.h"
+#include "pwc-uncompress.h"
+
+
+/* This contains a list of all registered decompressors */
+static LIST_HEAD(pwc_decompressor_list);
+
+/* Should the pwc_decompress structure ever change, we increase the 
+   version number so that we don't get nasty surprises, or can 
+   dynamicly adjust our structure.
+ */
+const int pwc_decompressor_version = PWC_MAJOR;
+
+/* Add decompressor to list, ignoring duplicates */
+void pwc_register_decompressor(struct pwc_decompressor *pwcd)
+{
+	if (pwc_find_decompressor(pwcd->type) == NULL) {
+		Trace(TRACE_PWCX, "Adding decompressor for model %d.\n", pwcd->type);
+		list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list);
+	}
+}
+
+/* Remove decompressor from list */
+void pwc_unregister_decompressor(int type)
+{
+	struct pwc_decompressor *find;
+	
+	find = pwc_find_decompressor(type);
+	if (find != NULL) {
+		Trace(TRACE_PWCX, "Removing decompressor for model %d.\n", type);
+		list_del(&find->pwcd_list);
+	}
+}
+
+/* Find decompressor in list */
+struct pwc_decompressor *pwc_find_decompressor(int type)
+{
+	struct list_head *tmp;
+	struct pwc_decompressor *pwcd;
+
+	list_for_each(tmp, &pwc_decompressor_list) {
+		pwcd  = list_entry(tmp, struct pwc_decompressor, pwcd_list);
+		if (pwcd->type == type)
+			return pwcd;
+	}
+	return NULL;
+}
+
+
+
+int pwc_decompress(struct pwc_device *pdev)
+{
+	struct pwc_frame_buf *fbuf;
+	int n, line, col, stride;
+	void *yuv, *image, *dst;
+	u16 *src;
+	u16 *dsty, *dstu, *dstv;
+
+	
+	if (pdev == NULL)
+		return -EFAULT;
+#if defined(__KERNEL__) && defined(PWC_MAGIC)
+	if (pdev->magic != PWC_MAGIC) {
+		Err("pwc_decompress(): magic failed.\n");
+		return -EFAULT;
+	}
+#endif
+
+	fbuf = pdev->read_frame;
+	if (fbuf == NULL)
+		return -EFAULT;
+	image = pdev->image_ptr[pdev->fill_image];
+	if (!image)
+		return -EFAULT;
+	
+#if PWC_DEBUG
+	/* This is a quickie */
+	if (pdev->vpalette == VIDEO_PALETTE_RAW) {
+		memcpy(image, fbuf->data, pdev->frame_size);
+		return 0;
+	}
+#endif
+
+	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
+	if (pdev->vbandlength == 0) { 
+		/* Uncompressed mode. We copy the data into the output buffer,
+		   using the viewport size (which may be larger than the image
+		   size). Unfortunately we have to do a bit of byte stuffing
+		   to get the desired output format/size.
+		 */
+		switch (pdev->vpalette) {
+		case VIDEO_PALETTE_YUV420:
+			/* Calculate byte offsets per line in image & view */
+			n   = (pdev->image.x * 3) / 2;
+			col = (pdev->view.x  * 3) / 2;
+			/* Offset into image */
+			dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2;
+			for (line = 0; line < pdev->image.y; line++) {
+				memcpy(dst, yuv, n);
+				yuv += n;
+				dst += col;
+			}
+			break;
+
+		case VIDEO_PALETTE_YUV420P:
+			/* 
+			 * We do some byte shuffling here to go from the 
+			 * native format to YUV420P.
+			 */
+			src = (u16 *)yuv;
+			n = pdev->view.x * pdev->view.y;
+
+			/* offset in Y plane */
+			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+			dsty = (u16 *)(image + stride);
+
+			/* offsets in U/V planes */
+			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+			dstu = (u16 *)(image + n +         stride);
+			dstv = (u16 *)(image + n + n / 4 + stride);
+
+			/* increment after each line */
+			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+
+			for (line = 0; line < pdev->image.y; line++) {
+				for (col = 0; col < pdev->image.x; col += 4) {
+					*dsty++ = *src++;
+					*dsty++ = *src++;
+					if (line & 1)
+						*dstv++ = *src++;
+					else
+						*dstu++ = *src++;
+				}
+				dsty += stride;
+				if (line & 1)
+					dstv += (stride >> 1);
+				else
+					dstu += (stride >> 1);
+			}
+			break;
+		}
+	}
+	else { 
+		/* Compressed; the decompressor routines will write the data 
+		   in interlaced or planar format immediately.
+		 */
+		if (pdev->decompressor)
+			pdev->decompressor->decompress(
+				&pdev->image, &pdev->view, &pdev->offset,
+				yuv, image, 
+				pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0,
+				pdev->decompress_data, pdev->vbandlength);
+		else
+			return -ENXIO; /* No such device or address: missing decompressor */
+	}
+	return 0;
+}
+
+/* Make sure these functions are available for the decompressor plugin
+   both when this code is compiled into the kernel or as as module.
+ */
+
+EXPORT_SYMBOL_NOVERS(pwc_decompressor_version);
+EXPORT_SYMBOL(pwc_register_decompressor);
+EXPORT_SYMBOL(pwc_unregister_decompressor);
diff -Nru a/drivers/usb/media/pwc-uncompress.h b/drivers/usb/media/pwc-uncompress.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc-uncompress.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,77 @@
+/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* This file is the bridge between the kernel module and the plugin; it
+   describes the structures and datatypes used in both modules. Any
+   significant change should be reflected by increasing the 
+   pwc_decompressor_version major number.
+ */
+#ifndef PWC_DEC_H
+#define PWC_DEC_H
+
+#include <linux/config.h>
+#include <linux/list.h>
+
+#include "pwc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The decompressor structure. 
+   Every type of decompressor registers itself with the main module. 
+   When a device is opened, it looks up the correct compressor, and
+   uses that when a compressed video mode is requested.
+ */
+struct pwc_decompressor
+{
+	int  type;		/* type of camera (645, 680, etc) */
+	int  table_size;	/* memory needed */
+
+	void (* init)(int release, void *buffer, void *table);	/* Initialization routine; should be called after each set_video_mode */
+	void (* exit)(void);	/* Cleanup routine */
+	void (* decompress)(struct pwc_coord *image, struct pwc_coord *view, struct pwc_coord *offset,
+                            void *src, void *dst, int planar,
+	                    void *table, int bandlength);
+	void (* lock)(void);	/* make sure module cannot be unloaded */
+	void (* unlock)(void);	/* release lock on module */
+
+	struct list_head pwcd_list;
+};
+
+
+/* Our structure version number. Is set to the version number major */
+extern const int pwc_decompressor_version;
+
+/* Adds decompressor to list, based on its 'type' field (which matches the 'type' field in pwc_device; ignores any double requests */
+extern void pwc_register_decompressor(struct pwc_decompressor *pwcd);
+/* Removes decompressor, based on the type number */
+extern void pwc_unregister_decompressor(int type);
+/* Returns pointer to decompressor struct, or NULL if it doesn't exist */
+extern struct pwc_decompressor *pwc_find_decompressor(int type);
+
+#ifdef CONFIG_USB_PWCX
+/* If the decompressor is compiled in, we must call these manually */
+extern int usb_pwcx_init(void);
+extern void usb_pwcx_exit(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,267 @@
+/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_H
+#define PWC_H
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <linux/videodev.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+/* Defines and structures for the Philips webcam */
+/* Used for checking memory corruption/pointer validation */
+#define PWC_MAGIC 0x89DC10ABUL
+#undef PWC_MAGIC
+
+/* Turn some debugging options on/off */
+#define PWC_DEBUG 0
+
+/* Trace certain actions in the driver */
+#define TRACE_MODULE	0x0001
+#define TRACE_PROBE	0x0002
+#define TRACE_OPEN	0x0004
+#define TRACE_READ	0x0008
+#define TRACE_MEMORY	0x0010
+#define TRACE_FLOW	0x0020
+#define TRACE_SIZE	0x0040
+#define TRACE_PWCX	0x0080
+#define TRACE_SEQUENCE	0x1000
+
+#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
+#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
+#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
+#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
+
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE		8
+#define TOUCAM_TRAILER_SIZE		4
+
+/* Version block */
+#define PWC_MAJOR	8
+#define PWC_MINOR	5
+#define PWC_VERSION 	"8.5"
+#define PWC_NAME 	"pwc"
+
+/* Turn certain features on/off */
+#define PWC_INT_PIPE 0
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS		2
+#define ISO_FRAMES_PER_DESC	10
+#define ISO_MAX_FRAME_SIZE	960
+#define ISO_BUFFER_SIZE 	(ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Frame buffers: contains compressed or uncompressed video data. */
+#define MAX_FRAMES		5
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define PWC_FRAME_SIZE 		(460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute maximum number of buffers available for mmap() */
+#define MAX_IMAGES 		4
+
+struct pwc_coord
+{
+	int x, y;		/* guess what */
+	int size;		/* size, or offset */
+};
+
+/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
+struct pwc_iso_buf
+{
+	void *data;
+	int  length;
+	int  read;
+	struct urb *urb;
+};
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+   void *data;
+   volatile int filled;		/* number of bytes filled */
+   struct pwc_frame_buf *next;	/* list */
+#if PWC_DEBUG
+   int sequence;		/* Sequence number */
+#endif
+};
+
+struct pwc_device
+{
+#ifdef PWC_MAGIC
+   int magic;
+#endif
+   /* Pointer to our usb_device */
+   struct usb_device *udev;
+   
+   int type;                    /* type of cam (645, 646, 675, 680, 690) */
+   int release;			/* release number */
+   int unplugged;		/* set when the plug is pulled */
+   int usb_init;		/* set when the cam has been initialized over USB */
+
+   /*** Video data ***/
+   int vopen;			/* flag */
+   struct video_device *vdev;
+   int vendpoint;		/* video isoc endpoint */
+   int vcinterface;		/* video control interface */
+   int valternate;		/* alternate interface needed */
+   int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
+   int vpalette;		/* YUV, RGB24, RGB32, etc */
+   int vframe_count;		/* received frames */
+   int vframes_dumped; 		/* counter for dumped frames */
+   int vframes_error;		/* frames received in error */
+   int vmax_packet_size;	/* USB maxpacket size */
+   int vlast_packet_size;	/* for frame synchronisation */
+   int vcompression;		/* desired compression factor */
+   int vbandlength;		/* compressed band length; 0 is uncompressed */
+   char vsnapshot;		/* snapshot mode */
+   char vsync;			/* used by isoc handler */
+   
+   /* The image acquisition requires 3 to 4 steps:
+      1. data is gathered in short packets from the USB controller
+      2. data is synchronized and packed into a frame buffer
+      3a. in case data is compressed, decompress it directly into image buffer
+      3b. in case data is uncompressed, copy into image buffer with viewport
+      4. data is transfered to the user process
+
+      Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... 
+      We have in effect a back-to-back-double-buffer system.
+    */
+   /* 1: isoc */
+   struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
+   char iso_init;
+   
+   /* 2: frame */
+   struct pwc_frame_buf *fbuf;	/* all frames */
+   struct pwc_frame_buf *empty_frames, *empty_frames_tail;	/* all empty frames */
+   struct pwc_frame_buf *full_frames, *full_frames_tail;	/* all filled frames */
+   struct pwc_frame_buf *fill_frame;	/* frame currently being filled */
+   struct pwc_frame_buf *read_frame;	/* frame currently read by user process */
+   int frame_size;
+   int frame_header_size, frame_trailer_size;
+   int drop_frames;
+#if PWC_DEBUG
+   int sequence;			/* Debugging aid */
+#endif
+   
+   /* 3: decompression */
+   struct pwc_decompressor *decompressor;	/* function block with decompression routines */
+   void *decompress_data;		/* private data for decompression engine */
+
+   /* 4: image */
+   /* We have an 'image' and a 'view', where 'image' is the fixed-size image
+      as delivered by the camera, and 'view' is the size requested by the
+      program. The camera image is centered in this viewport, laced with 
+      a gray or black border. view_min <= image <= view <= view_max;
+    */
+   int image_mask;			/* bitmask of supported sizes */
+   struct pwc_coord view_min, view_max;	/* minimum and maximum sizes */
+   struct pwc_coord image, view;	/* image and viewport size */
+   struct pwc_coord offset;		/* offset within the viewport */
+
+   void *image_data;			/* total buffer, which is subdivided into ... */
+   void *image_ptr[MAX_IMAGES];		/* ...several images... */
+   int fill_image;			/* ...which are rotated. */
+   int len_per_image;			/* length per image */
+   int image_read_pos;			/* In case we read data in pieces, keep track of were we are in the imagebuffer */
+   int image_used[MAX_IMAGES];		/* For MCAPTURE and SYNC */
+
+   struct semaphore modlock;		/* to prevent races in video_open(), etc */
+   spinlock_t ptrlock;			/* for manipulating the buffer pointers */
+
+   /*** Misc. data ***/
+   wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
+   wait_queue_head_t remove_ok;		/* When we got hot unplugged, we have to avoid a few race conditions */
+#if PWC_INT_PIPE
+   void *usb_int_handler;		/* for the interrupt endpoint */
+#endif   
+};
+
+/* Enumeration of image sizes */
+#define PSZ_SQCIF	0x00
+#define PSZ_QSIF	0x01
+#define PSZ_QCIF	0x02
+#define PSZ_SIF		0x03
+#define PSZ_CIF		0x04
+#define PSZ_VGA		0x05
+#define PSZ_MAX		6
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global variables */
+extern int pwc_trace;
+extern int pwc_preferred_compression;
+
+/** functions in pwc-if.c */
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+
+int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
+
+/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
+extern int pwc_get_brightness(struct pwc_device *pdev);
+extern int pwc_set_brightness(struct pwc_device *pdev, int value);
+extern int pwc_get_contrast(struct pwc_device *pdev);
+extern int pwc_set_contrast(struct pwc_device *pdev, int value);
+extern int pwc_get_gamma(struct pwc_device *pdev);
+extern int pwc_set_gamma(struct pwc_device *pdev, int value);
+extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
+
+/* Power down or up the camera; not supported by all models */
+extern int pwc_camera_power(struct pwc_device *pdev, int power);
+
+/* Private ioctl()s; see pwc-ioctl.h */
+extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+extern int pwc_decompress(struct pwc_device *pdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff -Nru a/drivers/usb/media/pwc_kiara.h b/drivers/usb/media/pwc_kiara.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc_kiara.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,270 @@
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+         {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+         {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+         {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+         {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 25 fps */
+      {
+         {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+         {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+         {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+         {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+      },
+      /* 30 fps */
+      {
+         {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+         {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+         {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+         {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+         {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+         {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+         {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+         {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+         {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+         {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+         {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+         {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+         {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+         {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+         {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+         {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+         {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+         {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+         {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+         {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+         {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+         {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+         {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
diff -Nru a/drivers/usb/media/pwc_nala.h b/drivers/usb/media/pwc_nala.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc_nala.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,66 @@
+   /* SQCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x03}},
+      {8, 0, {0x05, 0x01, 0x03}},
+      {7, 0, {0x08, 0x01, 0x03}},
+      {7, 0, {0x0A, 0x01, 0x03}},
+      {6, 0, {0x0C, 0x01, 0x03}},
+      {5, 0, {0x0F, 0x01, 0x03}},
+      {4, 0, {0x14, 0x01, 0x03}},
+      {3, 0, {0x18, 0x01, 0x03}},
+   },
+   /* QSIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* QCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x02}},
+      {8, 0, {0x05, 0x01, 0x02}},
+      {7, 0, {0x08, 0x01, 0x02}},
+      {6, 0, {0x0A, 0x01, 0x02}},
+      {5, 0, {0x0C, 0x01, 0x02}},
+      {4, 0, {0x0F, 0x01, 0x02}},
+      {1, 0, {0x14, 0x01, 0x02}},
+      {1, 0, {0x18, 0x01, 0x02}},
+   },
+   /* SIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* CIF */
+   {
+      {4, 0, {0x04, 0x01, 0x01}},
+      {7, 1, {0x05, 0x03, 0x01}},
+      {6, 1, {0x08, 0x03, 0x01}},
+      {4, 1, {0x0A, 0x03, 0x01}},
+      {3, 1, {0x0C, 0x03, 0x01}},
+      {2, 1, {0x0F, 0x03, 0x01}},
+      {0},
+      {0},
+   },
+   /* VGA */
+   {  
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
diff -Nru a/drivers/usb/media/pwc_timon.h b/drivers/usb/media/pwc_timon.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/pwc_timon.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,270 @@
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+         {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+         {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+         {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+         {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+         {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+         {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+         {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+         {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+         {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+         {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+         {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+         {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+         {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+         {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+         {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+         {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+         {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+         {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+         {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+         {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+         {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+         {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+         {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+         {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+         {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+         {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+         {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+         {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+         {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+         {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+         {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+         {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+         {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+         {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+         {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+         {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+         {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+         {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+         {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+         {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+         {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+         {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+         {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+         {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+         {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/se401.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,1579 @@
+/*
+ * Endpoints (formerly known as AOX) se401 USB Camera Driver
+ *
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * Still somewhat based on the Linux ov511 driver.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on
+ * their chipset available and supporting me while writing this driver.
+ * 	- Jeroen Vreeken
+ */
+
+static const char version[] = "0.23";
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/usb.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <linux/wrapper.h>
+#include <linux/mm.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
+#define virt_to_page(arg)	MAP_NR(arg)
+#define vmalloc_32		vmalloc
+#endif
+
+#include "se401.h"
+
+static int flickerless=0;
+static int video_nr = -1;
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
+static __devinitdata struct usb_device_id device_table [] = {
+	{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
+	{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
+	{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
+	{ USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */
+	{ USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+#endif
+
+MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
+MODULE_DESCRIPTION("SE401 USB Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM(flickerless, "i");
+MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
+MODULE_PARM(video_nr, "i");
+EXPORT_NO_SYMBOLS;
+
+
+static struct usb_driver se401_driver;
+
+
+/**********************************************************************
+ *
+ * Memory management
+ *
+ **********************************************************************/
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+	return ret;
+}
+
+static void *rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		mem_map_reserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+
+
+
+/****************************************************************************
+ *
+ * /proc interface
+ *
+ ***************************************************************************/
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+static struct proc_dir_entry *se401_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
+
+#define YES_NO(x) ((x) ? "yes" : "no")
+
+static int se401_read_proc(char *page, char **start, off_t off, int count,
+			   int *eof, void *data)
+{
+	char *out = page;
+	int i, len;
+	struct usb_se401 *se401 = data;
+	
+	/* Stay under PAGE_SIZE or else bla bla bla.... */
+
+	out+=sprintf(out, "driver_version  : %s\n", version);
+	out+=sprintf(out, "model           : %s\n", se401->camera_name);
+	out+=sprintf(out, "in use          : %s\n", YES_NO (se401->user));
+	out+=sprintf(out, "streaming       : %s\n", YES_NO (se401->streaming));
+	out+=sprintf(out, "button state    : %s\n", YES_NO (se401->button));
+	out+=sprintf(out, "button pressed  : %s\n", YES_NO (se401->buttonpressed));
+	out+=sprintf(out, "num_frames      : %d\n", SE401_NUMFRAMES);
+
+	out+=sprintf(out, "Sizes           :");
+	for (i=0; i<se401->sizes; i++) {
+		out+=sprintf(out, " %dx%d", se401->width[i],
+		    se401->height[i]);
+	}
+	out+=sprintf(out, "\n");
+	
+	out+=sprintf(out, "Frames total    : %d\n", se401->readcount);
+	out+=sprintf(out, "Frames read     : %d\n", se401->framecount);
+	out+=sprintf(out, "Packets dropped : %d\n", se401->dropped);
+	out+=sprintf(out, "Decoding Errors : %d\n", se401->error);
+
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+			if (len <= 0) return 0;
+	} else
+		len = count;
+
+	*start = page + off;
+	
+	return len;	
+}
+
+static int se401_write_proc(struct file *file, const char *buffer, 
+			    unsigned long count, void *data)
+{
+	return -EINVAL;
+}
+
+static void create_proc_se401_cam (struct usb_se401 *se401)
+{
+	char name[7];
+	struct proc_dir_entry *ent;
+
+	if (!se401_proc_entry || !se401)
+		return;
+
+	sprintf (name, "video%d", se401->vdev.minor);
+
+	ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
+				se401_proc_entry);
+
+	if (!ent)
+		return;
+
+	ent->data = se401;
+	ent->read_proc = se401_read_proc;
+	ent->write_proc = se401_write_proc;
+	se401->proc_entry = ent;
+}
+
+static void destroy_proc_se401_cam (struct usb_se401 *se401)
+{
+	/* One to much, just to be sure :) */
+	char name[9];
+
+	if (!se401 || !se401->proc_entry)
+		return;
+	
+	sprintf(name, "video%d", se401->vdev.minor);
+	remove_proc_entry(name, se401_proc_entry);
+	se401->proc_entry = NULL;
+}
+
+static void proc_se401_create (void)
+{
+	if (video_proc_entry == NULL) {
+		err("/proc/video/ doesn't exist");
+		return;
+	}
+
+	se401_proc_entry=create_proc_entry("se401", S_IFDIR, video_proc_entry);
+
+	if (se401_proc_entry)
+		se401_proc_entry->owner = THIS_MODULE;
+	else
+		err("Unable to initialize /proc/video/se401");
+}
+
+static void proc_se401_destroy(void)
+{
+	if (se401_proc_entry == NULL)
+		return;
+
+	remove_proc_entry("se401", video_proc_entry);
+}
+#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+
+/****************************************************************************
+ *
+ * se401 register read/write functions
+ *
+ ***************************************************************************/
+
+static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
+			 unsigned short value, unsigned char *cp, int size)
+{
+	return usb_control_msg (
+                se401->dev,
+                set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
+                req,
+                (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                value,
+                0,
+                cp,
+                size,
+                HZ
+        );
+}
+
+static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
+			     unsigned short param)
+{
+	/* specs say that the selector (address) should go in the value field
+	   and the param in index, but in the logs of the windows driver they do
+	   this the other way around...
+	 */
+	return usb_control_msg (
+		se401->dev,
+		usb_sndctrlpipe(se401->dev, 0),
+		SE401_REQ_SET_EXT_FEATURE,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		param,
+		selector,
+                NULL,
+                0,
+                HZ
+        );
+}
+
+static unsigned short se401_get_feature(struct usb_se401 *se401, 
+				        unsigned short selector)
+{
+	/* For 'set' the selecetor should be in index, not sure if the spec is
+	   wrong here to....
+	 */
+	unsigned char cp[2];
+        usb_control_msg (
+                se401->dev,
+                usb_rcvctrlpipe(se401->dev, 0),
+                SE401_REQ_GET_EXT_FEATURE,
+                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+        	0,
+                selector,
+                cp,
+                2,
+                HZ
+        );
+	return cp[0]+cp[1]*256;
+}
+
+/****************************************************************************
+ *
+ * Camera control
+ *
+ ***************************************************************************/
+
+
+static int se401_send_pict(struct usb_se401 *se401)
+{
+	se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */
+	se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */
+	se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */
+	se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */
+	se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
+	se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
+	se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
+	    	
+	return 0;
+}
+
+static void se401_set_exposure(struct usb_se401 *se401, int brightness)
+{
+	int integration=brightness<<5;
+	
+	if (flickerless==50) {
+		integration=integration-integration%106667;
+	}
+	if (flickerless==60) {
+		integration=integration-integration%88889;
+	}
+	se401->brightness=integration>>5;
+	se401->expose_h=(integration>>16)&0xff;
+	se401->expose_m=(integration>>8)&0xff;
+	se401->expose_l=integration&0xff;
+}
+
+static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
+{
+	p->brightness=se401->brightness;
+	if (se401->enhance) {
+		p->whiteness=32768;
+	} else {
+		p->whiteness=0;
+	}
+	p->colour=65535;
+	p->contrast=65535;
+	p->hue=se401->rgain<<10;
+	p->palette=se401->palette;
+	p->depth=3; /* rgb24 */
+	return 0;
+}
+
+
+static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
+{
+	if (p->palette != VIDEO_PALETTE_RGB24)
+		return 1;
+	se401->palette=p->palette;
+	if (p->hue!=se401->hue) {
+		se401->rgain= p->hue>>10;
+		se401->bgain= 0x40-(p->hue>>10);
+		se401->hue=p->hue;
+	}
+	if (p->brightness!=se401->brightness) {
+		se401_set_exposure(se401, p->brightness);
+	}
+	if (p->whiteness>=32768) {
+		se401->enhance=1;
+	} else {
+		se401->enhance=0;
+	}
+	se401_send_pict(se401);
+	se401_send_pict(se401);
+	return 0;
+}
+
+/*
+	Hyundai have some really nice docs about this and other sensor related
+	stuff on their homepage: www.hei.co.kr
+*/
+static void se401_auto_resetlevel(struct usb_se401 *se401)
+{
+	unsigned int ahrc, alrc;
+	int oldreset=se401->resetlevel;
+
+	/* For some reason this normally read-only register doesn't get reset
+	   to zero after reading them just once...
+	 */
+	se401_get_feature(se401, HV7131_REG_HIREFNOH); 
+	se401_get_feature(se401, HV7131_REG_HIREFNOL);
+	se401_get_feature(se401, HV7131_REG_LOREFNOH);
+	se401_get_feature(se401, HV7131_REG_LOREFNOL);
+	ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + 
+	    se401_get_feature(se401, HV7131_REG_HIREFNOL);
+	alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
+	    se401_get_feature(se401, HV7131_REG_LOREFNOL);
+
+	/* Not an exact science, but it seems to work pretty well... */
+	if (alrc > 10) {
+		while (alrc>=10 && se401->resetlevel < 63) {
+			se401->resetlevel++;
+			alrc /=2;
+		}
+	} else if (ahrc > 20) {
+		while (ahrc>=20 && se401->resetlevel > 0) {
+			se401->resetlevel--;
+			ahrc /=2;
+		}
+	}
+	if (se401->resetlevel!=oldreset)
+		se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
+
+	return;
+}
+
+/* irq handler for snapshot button */
+static void se401_button_irq(struct urb *urb)
+{
+	struct usb_se401 *se401 = urb->context;
+	
+	if (!se401->dev) {
+		info("ohoh: device vapourished");
+		return;
+	}
+	
+	if (urb->actual_length >=2 && !urb->status) {
+		if (se401->button)
+			se401->buttonpressed=1;
+	}
+}
+
+static void se401_video_irq(struct urb *urb)
+{
+	struct usb_se401 *se401 = urb->context;
+	int length = urb->actual_length;
+
+	/* ohoh... */
+	if (!se401->streaming)
+		return;
+
+	if (!se401->dev) {
+		info ("ohoh: device vapourished");
+		return;
+	}
+
+	/* 0 sized packets happen if we are to fast, but sometimes the camera
+	   keeps sending them forever...
+	 */
+	if (length && !urb->status) {
+		se401->nullpackets=0;
+		switch(se401->scratch[se401->scratch_next].state) {
+			case BUFFER_READY:
+			case BUFFER_BUSY: {
+				se401->dropped++;
+				break;
+			}
+			case BUFFER_UNUSED: {
+				memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length);
+				se401->scratch[se401->scratch_next].state=BUFFER_READY;
+				se401->scratch[se401->scratch_next].offset=se401->bayeroffset;
+				se401->scratch[se401->scratch_next].length=length;
+				if (waitqueue_active(&se401->wq)) {
+					wake_up_interruptible(&se401->wq);
+				}
+				se401->scratch_overflow=0;
+				se401->scratch_next++;
+				if (se401->scratch_next>=SE401_NUMSCRATCH)
+					se401->scratch_next=0;;
+				break;
+			}
+		}
+		se401->bayeroffset+=length;
+		if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
+			se401->bayeroffset=0;
+		}
+	} else {
+		se401->nullpackets++;
+		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
+			if (waitqueue_active(&se401->wq)) {
+				wake_up_interruptible(&se401->wq);
+			}		
+		}
+	}
+
+	/* Resubmit urb for new data */
+	urb->status=0;
+	urb->dev=se401->dev;
+	if(usb_submit_urb(urb, GFP_KERNEL))
+		info("urb burned down");
+	return;
+}
+
+static void se401_send_size(struct usb_se401 *se401, int width, int height)
+{
+	int i=0;
+	int mode=0x03; /* No compression */
+	int sendheight=height;
+	int sendwidth=width;
+
+	/* JangGu compression can only be used with the camera supported sizes,
+	   but bayer seems to work with any size that fits on the sensor.
+	   We check if we can use compression with the current size with either
+	   4 or 16 times subcapturing, if not we use uncompressed bayer data
+	   but this will result in cutouts of the maximum size....
+	 */
+	while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
+		i++;
+	while (i<se401->sizes) {
+		if (se401->width[i]==width*2 && se401->height[i]==height*2) {
+			sendheight=se401->height[i];
+			sendwidth=se401->width[i];
+			mode=0x40;
+		}
+		if (se401->width[i]==width*4 && se401->height[i]==height*4) {
+			sendheight=se401->height[i];
+			sendwidth=se401->width[i];
+			mode=0x42;
+		}
+		i++;
+	}
+
+	se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
+	se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
+	se401_set_feature(se401, SE401_OPERATINGMODE, mode);
+
+	if (mode==0x03) {
+		se401->format=FMT_BAYER;
+	} else {
+		se401->format=FMT_JANGGU;
+	}
+
+	return;
+}
+
+/*
+	In this function se401_send_pict is called several times,
+	for some reason (depending on the state of the sensor and the phase of
+	the moon :) doing this only in either place doesn't always work...
+*/
+static int se401_start_stream(struct usb_se401 *se401)
+{
+	struct urb *urb;
+	int err=0, i;
+	se401->streaming=1;
+
+        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
+        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
+
+	/* Set picture settings */
+	se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
+	se401_send_pict(se401);
+
+	se401_send_size(se401, se401->cwidth, se401->cheight);
+
+	se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
+
+	/* Do some memory allocation */
+	for (i=0; i<SE401_NUMFRAMES; i++) {
+		se401->frame[i].data=se401->fbuf + i * se401->maxframesize;
+		se401->frame[i].curpix=0;
+	}
+	for (i=0; i<SE401_NUMSBUF; i++) {
+		se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
+	}
+
+	se401->bayeroffset=0;
+	se401->scratch_next=0;
+	se401->scratch_use=0;
+	se401->scratch_overflow=0;
+	for (i=0; i<SE401_NUMSCRATCH; i++) {
+		se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
+		se401->scratch[i].state=BUFFER_UNUSED;
+	}
+
+	for (i=0; i<SE401_NUMSBUF; i++) {
+		urb=usb_alloc_urb(0, GFP_KERNEL);
+		if(!urb)
+			return ENOMEM;
+
+		FILL_BULK_URB(urb, se401->dev,
+			usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
+			se401->sbuf[i].data, SE401_PACKETSIZE,
+			se401_video_irq,
+			se401);
+		urb->transfer_flags |= USB_QUEUE_BULK;
+
+		se401->urb[i]=urb;
+
+		err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
+		if(err)
+			err("urb burned down");
+	}
+
+	se401->framecount=0;
+
+	return 0;
+}
+
+static int se401_stop_stream(struct usb_se401 *se401)
+{
+	int i;
+
+	if (!se401->streaming || !se401->dev)
+		return 1;
+
+	se401->streaming=0;
+
+	se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
+
+	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
+	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
+
+	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
+		se401->urb[i]->next=NULL;
+		usb_unlink_urb(se401->urb[i]);
+		usb_free_urb(se401->urb[i]);
+		se401->urb[i]=NULL;
+		kfree(se401->sbuf[i].data);
+	}
+	for (i=0; i<SE401_NUMSCRATCH; i++) {
+		kfree(se401->scratch[i].data);
+		se401->scratch[i].data=NULL;
+	}
+
+	return 0;
+}
+
+static int se401_set_size(struct usb_se401 *se401, int width, int height)
+{
+	int wasstreaming=se401->streaming;
+	/* Check to see if we need to change */
+	if (se401->cwidth==width && se401->cheight==height)
+		return 0;
+
+	/* Check for a valid mode */
+	if (!width || !height)
+		return 1;
+	if ((width & 1) || (height & 1))
+		return 1;
+	if (width>se401->width[se401->sizes-1])
+		return 1;
+	if (height>se401->height[se401->sizes-1])
+		return 1;
+
+	/* Stop a current stream and start it again at the new size */
+	if (wasstreaming)
+		se401_stop_stream(se401);
+	se401->cwidth=width;
+	se401->cheight=height;
+	if (wasstreaming)
+		se401_start_stream(se401);
+	return 0;
+}
+
+
+/****************************************************************************
+ *
+ * Video Decoding
+ *
+ ***************************************************************************/
+
+/*
+	This shouldn't really be done in a v4l driver....
+	But it does make the image look a lot more usable.
+	Basicly it lifts the dark pixels more than the light pixels.
+*/
+static inline void enhance_picture(unsigned char *frame, int len)
+{
+	while (len--) {
+		*frame++=(((*frame^255)*(*frame^255))/255)^255;
+	}
+}
+
+static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
+{
+	struct se401_frame *frame=&se401->frame[se401->curframe];
+	int linelength=se401->cwidth*3;
+
+	if (frame->curlinepix >= linelength) {
+		frame->curlinepix=0;
+		frame->curline+=linelength;
+	}
+
+	/* First three are absolute, all others relative.
+	 * Format is rgb from right to left (mirrorred image), 
+	 * we flip it to get bgr from left to right. */
+	if (frame->curlinepix < 3) {
+		*(frame->curline-frame->curlinepix)=1+data*4;
+	} else {
+		*(frame->curline-frame->curlinepix)=
+		    *(frame->curline-frame->curlinepix+3)+data*4;
+	}
+	frame->curlinepix++;
+}
+
+static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
+{
+	int pos=0;
+	int vlc_cod=0;
+	int vlc_size=0;
+	int vlc_data=0;
+	int bit_cur;
+	int bit;
+	data+=4;
+	while (pos < packetlength) {
+		bit_cur=8;
+		while (bit_cur && bit_exp) {
+			bit=((*data)>>(bit_cur-1))&1;
+			if (!vlc_cod) {
+				if (bit) {
+					vlc_size++;
+				} else {
+					if (!vlc_size) {
+						decode_JangGu_integrate(se401, 0);
+					} else {
+						vlc_cod=2;
+						vlc_data=0;
+					}
+				}
+			} else {
+				if (vlc_cod==2) {
+					if (!bit) vlc_data=-(1<<vlc_size)+1;
+					vlc_cod--;
+				}
+				vlc_size--;
+				vlc_data+=bit<<vlc_size;
+				if (!vlc_size) {
+					decode_JangGu_integrate(se401, vlc_data);
+					vlc_cod=0;
+				}
+			}
+			bit_cur--;
+			bit_exp--;
+		}
+		pos++;
+		data++;
+	}
+}
+
+static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
+{
+	unsigned char *data=buffer->data;
+	int len=buffer->length;
+	int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
+	int datapos=0;
+
+	/* New image? */
+	if (!se401->frame[se401->curframe].curpix) {
+		se401->frame[se401->curframe].curlinepix=0;
+		se401->frame[se401->curframe].curline=
+		    se401->frame[se401->curframe].data+
+		    se401->cwidth*3-1;
+		if (se401->frame[se401->curframe].grabstate==FRAME_READY)
+			se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
+		se401->vlcdatapos=0;
+	}
+	while (datapos < len) {
+		size=1024-se401->vlcdatapos;
+		if (size+datapos > len)
+			size=len-datapos;
+		memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
+		se401->vlcdatapos+=size;
+		packetlength=0;
+		if (se401->vlcdatapos >= 4) {
+			bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
+			pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
+			frameinfo=se401->vlcdata[0]&0xc0;
+			packetlength=((bit_exp+47)>>4)<<1;
+			if (packetlength > 1024) {
+				se401->vlcdatapos=0;
+				datapos=len;
+				packetlength=0;
+				se401->error++;
+				se401->frame[se401->curframe].curpix=0;
+			}
+		}
+		if (packetlength && se401->vlcdatapos >= packetlength) {
+			decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
+			se401->frame[se401->curframe].curpix+=pix_exp*3;
+			datapos+=size-(se401->vlcdatapos-packetlength);
+			se401->vlcdatapos=0;
+			if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
+				if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
+					if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
+						se401->frame[se401->curframe].grabstate=FRAME_DONE;
+						se401->framecount++;
+						se401->readcount++;
+					}
+					if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
+						se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
+					}
+				} else {
+					se401->error++;
+				}
+				se401->frame[se401->curframe].curpix=0;
+				datapos=len;
+			}
+		} else {
+			datapos+=size;
+		}
+	}
+}
+
+static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
+{
+	unsigned char *data=buffer->data;
+	int len=buffer->length;
+	int offset=buffer->offset;
+	int datasize=se401->cwidth*se401->cheight;
+	struct se401_frame *frame=&se401->frame[se401->curframe];
+
+	unsigned char *framedata=frame->data, *curline, *nextline;
+	int width=se401->cwidth;
+	int blineoffset=0, bline;
+	int linelength=width*3, i;
+	
+
+	if (frame->curpix==0) {
+		if (frame->grabstate==FRAME_READY) {
+			frame->grabstate=FRAME_GRABBING;
+		}
+		frame->curline=framedata+linelength;
+		frame->curlinepix=0;
+	}
+
+	if (offset!=frame->curpix) {
+		/* Regard frame as lost :( */
+		frame->curpix=0;
+		se401->error++;
+		return;
+	}
+
+	/* Check if we have to much data */
+	if (frame->curpix+len > datasize) {
+		len=datasize-frame->curpix;
+	}
+	if (se401->cheight%4)
+		blineoffset=1;
+	bline=frame->curpix/se401->cwidth+blineoffset;
+
+	curline=frame->curline;
+	nextline=curline+linelength;
+	if (nextline >= framedata+datasize*3)
+		nextline=curline;
+	while (len) {
+		if (frame->curlinepix>=width) {
+			frame->curlinepix-=width;
+			bline=frame->curpix/width+blineoffset;
+			curline+=linelength*2;
+			nextline+=linelength*2;
+			if (curline >= framedata+datasize*3) {
+				frame->curlinepix++;
+				curline-=3;
+				nextline-=3;
+				len--;
+				data++;
+				frame->curpix++;
+			}
+			if (nextline >= framedata+datasize*3)
+				nextline=curline;
+		}
+		if ((bline&1)) {
+			if ((frame->curlinepix&1)) {
+				*(curline+2)=*data;
+				*(curline-1)=*data;
+				*(nextline+2)=*data;
+				*(nextline-1)=*data;
+			} else {
+				*(curline+1)=
+					(*(curline+1)+*data)/2;
+				*(curline-2)=
+					(*(curline-2)+*data)/2;
+				*(nextline+1)=*data;
+				*(nextline-2)=*data;
+			}
+		} else {
+			if ((frame->curlinepix&1)) {
+				*(curline+1)=
+					(*(curline+1)+*data)/2;
+				*(curline-2)=
+					(*(curline-2)+*data)/2;
+				*(nextline+1)=*data;
+				*(nextline-2)=*data;
+			} else {
+				*curline=*data;
+				*(curline-3)=*data;
+				*nextline=*data;
+				*(nextline-3)=*data;
+			}
+		}
+		frame->curlinepix++;
+		curline-=3;
+		nextline-=3;
+		len--;
+		data++;
+		frame->curpix++;
+	}
+	frame->curline=curline;
+
+	if (frame->curpix>=datasize) {
+		/* Fix the top line */
+		framedata+=linelength;
+		for (i=0; i<linelength; i++) {
+			*--framedata=*(framedata+linelength);
+		}
+		/* Fix the left side (green is already present) */
+		for (i=0; i<se401->cheight; i++) {
+			*framedata=*(framedata+3);
+			*(framedata+1)=*(framedata+4);
+			*(framedata+2)=*(framedata+5);
+			framedata+=linelength;
+		}
+		frame->curpix=0;
+		frame->grabstate=FRAME_DONE;
+		se401->framecount++;
+		se401->readcount++;
+		if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
+			se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
+		}
+	}
+}
+
+static int se401_newframe(struct usb_se401 *se401, int framenr)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int errors=0;
+
+	while (se401->streaming &&
+	    (se401->frame[framenr].grabstate==FRAME_READY ||
+	     se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
+		if(!se401->frame[framenr].curpix) {
+			errors++;
+		}
+		wait_interruptible(
+		    se401->scratch[se401->scratch_use].state!=BUFFER_READY,
+		    &se401->wq,
+		    &wait
+		);
+		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
+			se401->nullpackets=0;
+			info("to many null length packets, restarting capture");
+			se401_stop_stream(se401);
+			se401_start_stream(se401);			
+		} else {
+			if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
+				se401->frame[framenr].grabstate=FRAME_ERROR;
+				return -EIO;
+			}
+			se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
+			if (se401->format==FMT_JANGGU) {
+				decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
+			} else {
+				decode_bayer(se401, &se401->scratch[se401->scratch_use]);
+			}
+			se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
+			se401->scratch_use++;
+			if (se401->scratch_use>=SE401_NUMSCRATCH)
+				se401->scratch_use=0;
+			if (errors > SE401_MAX_ERRORS) {
+				errors=0;
+				info("to much errors, restarting capture");
+				se401_stop_stream(se401);
+				se401_start_stream(se401);
+			}
+		}
+	}
+
+	if (se401->frame[framenr].grabstate==FRAME_DONE)
+		if (se401->enhance)
+			enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
+	return 0;
+}
+
+
+/****************************************************************************
+ *
+ * Video4Linux
+ *
+ ***************************************************************************/
+
+
+static int se401_open(struct inode *inode, struct file *file)
+{
+	struct video_device *dev = video_devdata(file);
+	struct usb_se401 *se401 = (struct usb_se401 *)dev;
+	int err = 0;
+
+	if (se401->user)
+		return -EBUSY;
+	se401->user=1;
+	se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
+	if(!se401->fbuf) err=-ENOMEM;
+
+        if (0 != err) {
+		se401->user = 0;
+	} else {
+		file->private_data = dev;
+	}
+
+	return err;
+}
+
+static int se401_close(struct inode *inode, struct file *file)
+{
+	struct video_device *dev = file->private_data;
+        struct usb_se401 *se401 = (struct usb_se401 *)dev;
+	int i;
+
+	for (i=0; i<SE401_NUMFRAMES; i++)
+		se401->frame[i].grabstate=FRAME_UNUSED;
+	if (se401->streaming)
+		se401_stop_stream(se401);
+
+	rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
+	se401->user=0;
+
+        if (se401->removed) {
+		kfree(se401->width);
+		kfree(se401->height);
+                kfree(se401);
+                se401 = NULL;
+		info("device unregistered");
+	}
+	file->private_data = NULL;
+	return 0;
+}
+
+static int se401_do_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = file->private_data;
+        struct usb_se401 *se401 = (struct usb_se401 *)vdev;
+
+        if (!se401->dev)
+                return -EIO;
+
+        switch (cmd) {
+	case VIDIOCGCAP:
+	{
+		struct video_capability *b = arg;
+		strcpy(b->name, se401->camera_name);
+		b->type = VID_TYPE_CAPTURE;
+		b->channels = 1;
+		b->audios = 0;
+		b->maxwidth = se401->width[se401->sizes-1];
+		b->maxheight = se401->height[se401->sizes-1];
+		b->minwidth = se401->width[0];
+		b->minheight = se401->height[0];
+		return 0;
+	}
+	case VIDIOCGCHAN:
+	{
+		struct video_channel *v = arg;
+
+		if (v->channel != 0)
+			return -EINVAL;
+		v->flags = 0;
+		v->tuners = 0;
+		v->type = VIDEO_TYPE_CAMERA;
+		strcpy(v->name, "Camera");
+		return 0;
+	}
+	case VIDIOCSCHAN:
+	{
+		struct video_channel *v = arg;
+
+		if (v->channel != 0)
+			return -EINVAL;
+		return 0;
+	}
+        case VIDIOCGPICT:
+        {
+		struct video_picture *p = arg;
+
+		se401_get_pict(se401, p);
+		return 0;
+	}
+	case VIDIOCSPICT:
+	{
+		struct video_picture *p = arg;
+
+		if (se401_set_pict(se401, p))
+			return -EINVAL;
+		return 0;
+	}
+	case VIDIOCSWIN:
+	{
+		struct video_window *vw = arg;
+
+		if (vw->flags)
+			return -EINVAL;
+		if (vw->clipcount)
+			return -EINVAL;
+		if (se401_set_size(se401, vw->width, vw->height))
+			return -EINVAL;
+		return 0;
+        }
+	case VIDIOCGWIN:
+	{
+		struct video_window *vw = arg;
+
+		vw->x = 0;               /* FIXME */
+		vw->y = 0;
+		vw->chromakey = 0;
+		vw->flags = 0;
+		vw->clipcount = 0;
+		vw->width = se401->cwidth;
+		vw->height = se401->cheight;
+		return 0;
+	}
+	case VIDIOCGMBUF:
+	{
+		struct video_mbuf *vm = arg;
+		int i;
+
+		memset(vm, 0, sizeof(*vm));
+		vm->size = SE401_NUMFRAMES * se401->maxframesize;
+		vm->frames = SE401_NUMFRAMES;
+		for (i=0; i<SE401_NUMFRAMES; i++)
+			vm->offsets[i] = se401->maxframesize * i;
+		return 0;
+	}
+	case VIDIOCMCAPTURE:
+	{
+		struct video_mmap *vm = arg;
+
+		if (vm->format != VIDEO_PALETTE_RGB24)
+			return -EINVAL;
+		if (vm->frame >= SE401_NUMFRAMES)
+			return -EINVAL;
+		if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
+			return -EBUSY;
+
+		/* Is this according to the v4l spec??? */
+		if (se401_set_size(se401, vm->width, vm->height))
+			return -EINVAL;
+		se401->frame[vm->frame].grabstate=FRAME_READY;
+
+		if (!se401->streaming)
+			se401_start_stream(se401);
+
+		/* Set the picture properties */
+		if (se401->framecount==0)
+			se401_send_pict(se401);
+		/* Calibrate the reset level after a few frames. */
+		if (se401->framecount%20==1)
+			se401_auto_resetlevel(se401);
+
+		return 0;
+	}
+	case VIDIOCSYNC:
+	{
+		int *frame = arg;
+		int ret=0;
+
+		if(*frame <0 || *frame >= SE401_NUMFRAMES)
+			return -EINVAL;
+
+		ret=se401_newframe(se401, *frame);
+		se401->frame[*frame].grabstate=FRAME_UNUSED;
+		return ret;
+	}
+	case VIDIOCGFBUF:
+	{
+		struct video_buffer *vb = arg;
+
+		memset(vb, 0, sizeof(*vb));
+		return 0;
+	}
+	case VIDIOCKEY:
+		return 0;
+	case VIDIOCCAPTURE:
+		return -EINVAL;
+	case VIDIOCSFBUF:
+		return -EINVAL;
+	case VIDIOCGTUNER:
+	case VIDIOCSTUNER:
+		return -EINVAL;
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+		return -EINVAL;
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+		return -EINVAL;
+        default:
+                return -ENOIOCTLCMD;
+        } /* end switch */
+
+        return 0;
+}
+
+static int se401_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);
+}
+
+static int se401_read(struct file *file, char *buf,
+		     size_t count, loff_t *ppos)
+{
+	int realcount=count, ret=0;
+	struct video_device *dev = file->private_data;
+	struct usb_se401 *se401 = (struct usb_se401 *)dev;
+
+
+	if (se401->dev == NULL)
+		return -EIO;
+	if (realcount > se401->cwidth*se401->cheight*3)
+		realcount=se401->cwidth*se401->cheight*3;
+
+	/* Shouldn't happen: */
+	if (se401->frame[0].grabstate==FRAME_GRABBING)
+		return -EBUSY;
+	se401->frame[0].grabstate=FRAME_READY;
+	se401->frame[1].grabstate=FRAME_UNUSED;
+	se401->curframe=0;
+
+	if (!se401->streaming)
+		se401_start_stream(se401);
+
+	/* Set the picture properties */
+	if (se401->framecount==0)
+		se401_send_pict(se401);
+	/* Calibrate the reset level after a few frames. */
+	if (se401->framecount%20==1)
+		se401_auto_resetlevel(se401);
+
+	ret=se401_newframe(se401, 0);
+
+	se401->frame[0].grabstate=FRAME_UNUSED;
+	if (ret)
+		return ret;	
+	if (copy_to_user(buf, se401->frame[0].data, realcount))
+		return -EFAULT;
+
+	return realcount;
+}
+
+static int se401_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *dev = file->private_data;
+	struct usb_se401 *se401 = (struct usb_se401 *)dev;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long page, pos;
+
+	down(&se401->lock);
+
+	if (se401->dev == NULL) {
+		up(&se401->lock);
+		return -EIO;
+	}
+	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+		up(&se401->lock);
+		return -EINVAL;
+	}
+	pos = (unsigned long)se401->fbuf;
+	while (size > 0) {
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+			up(&se401->lock);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	up(&se401->lock);
+
+        return 0;
+}
+
+static struct file_operations se401_fops = {
+	owner:		THIS_MODULE,
+        open:           se401_open,
+        release:        se401_close,
+        read:           se401_read,
+        mmap:           se401_mmap,
+	ioctl:          se401_ioctl,
+	llseek:         no_llseek,
+};
+static struct video_device se401_template = {
+	owner:		THIS_MODULE,
+        name:           "se401 USB camera",
+        type:           VID_TYPE_CAPTURE,
+        hardware:       VID_HARDWARE_SE401,
+	fops:           &se401_fops,
+};
+
+
+
+/***************************/
+static int se401_init(struct usb_se401 *se401)
+{
+        int i=0, rc;
+        unsigned char cp[0x40];
+	char temp[200];
+
+	/* led on */
+        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
+
+	/* get camera descriptor */
+	rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
+	if (cp[1]!=0x41) {
+		err("Wrong descriptor type");
+		return 1;
+	}
+	sprintf (temp, "ExtraFeatures: %d", cp[3]);
+
+	se401->sizes=cp[4]+cp[5]*256;
+	se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+	se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
+	for (i=0; i<se401->sizes; i++) {
+		    se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
+		    se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
+	}
+	sprintf (temp, "%s Sizes:", temp);
+	for (i=0; i<se401->sizes; i++) {
+		sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
+	}
+	info("%s", temp);
+	se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
+
+	rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
+	se401->cwidth=cp[0]+cp[1]*256;
+	rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
+	se401->cheight=cp[0]+cp[1]*256;
+
+	if (!cp[2] && SE401_FORMAT_BAYER) {
+		err("Bayer format not supported!");
+		return 1;
+	}
+	/* set output mode (BAYER) */
+        se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
+
+	rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
+	se401->brightness=cp[0]+cp[1]*256;
+	/* some default values */
+	se401->resetlevel=0x2d;
+	se401->rgain=0x20;
+	se401->ggain=0x20;
+	se401->bgain=0x20;
+	se401_set_exposure(se401, 20000);
+	se401->palette=VIDEO_PALETTE_RGB24;
+	se401->enhance=1;
+	se401->dropped=0;
+	se401->error=0;
+	se401->framecount=0;
+	se401->readcount=0;
+
+	/* Start interrupt transfers for snapshot button */
+	se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
+	if (!se401->inturb) {
+		info("Allocation of inturb failed");
+		return 1;
+	}
+	FILL_INT_URB(se401->inturb, se401->dev,
+	    usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
+	    &se401->button, sizeof(se401->button),
+	    se401_button_irq,
+	    se401,
+	    HZ/10
+	);
+	if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
+		info("int urb burned down");
+		return 1;
+	}
+
+        /* Flash the led */
+        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
+        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
+        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
+	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
+
+        return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
+static void* se401_probe(struct usb_device *dev, unsigned int ifnum)
+#else
+static void* __devinit se401_probe(struct usb_device *dev, unsigned int ifnum,
+	const struct usb_device_id *id)
+#endif
+{
+        struct usb_interface_descriptor *interface;
+        struct usb_se401 *se401;
+        char *camera_name=NULL;
+
+        /* We don't handle multi-config cameras */
+        if (dev->descriptor.bNumConfigurations != 1)
+                return NULL;
+
+        interface = &dev->actconfig->interface[ifnum].altsetting[0];
+
+        /* Is it an se401? */
+        if (dev->descriptor.idVendor == 0x03e8 &&
+            dev->descriptor.idProduct == 0x0004) {
+                camera_name="Endpoints/Aox SE401";
+        } else if (dev->descriptor.idVendor == 0x0471 &&
+            dev->descriptor.idProduct == 0x030b) {
+                camera_name="Philips PCVC665K";
+        } else if (dev->descriptor.idVendor == 0x047d &&
+	    dev->descriptor.idProduct == 0x5001) {
+		camera_name="Kensington VideoCAM 67014";
+        } else if (dev->descriptor.idVendor == 0x047d &&
+	    dev->descriptor.idProduct == 0x5002) {
+		camera_name="Kensington VideoCAM 6701(5/7)";
+        } else if (dev->descriptor.idVendor == 0x047d &&
+	    dev->descriptor.idProduct == 0x5003) {
+		camera_name="Kensington VideoCAM 67016";
+	} else
+		return NULL;
+
+        /* Checking vendor/product should be enough, but what the hell */
+        if (interface->bInterfaceClass != 0x00)
+                return NULL;
+        if (interface->bInterfaceSubClass != 0x00)
+                return NULL;
+
+        /* We found one */
+        info("SE401 camera found: %s", camera_name);
+
+        if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
+                err("couldn't kmalloc se401 struct");
+                return NULL;
+        }
+
+        memset(se401, 0, sizeof(*se401));
+
+        se401->dev = dev;
+        se401->iface = interface->bInterfaceNumber;
+        se401->camera_name = camera_name;
+
+	info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
+
+        if (se401_init(se401)) {
+		kfree(se401);
+		return NULL;
+	}
+
+	memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
+	memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
+	init_waitqueue_head(&se401->wq);
+	init_MUTEX(&se401->lock);
+	wmb();
+
+	if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+		kfree(se401);
+		err("video_register_device failed");
+		return NULL;
+	}
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+        create_proc_se401_cam(se401);
+#endif
+	info("registered new video device: video%d", se401->vdev.minor);
+
+        return se401;
+}
+
+static void se401_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_se401 *se401 = (struct usb_se401 *) ptr;
+
+	video_unregister_device(&se401->vdev);
+	if (!se401->user){
+		usb_se401_remove_disconnected(se401);
+	} else {
+		se401->removed = 1;
+	}
+}
+
+static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
+{
+	int i;
+
+        se401->dev = NULL;
+        se401->frame[0].grabstate = FRAME_ERROR;
+        se401->frame[1].grabstate = FRAME_ERROR;
+
+	se401->streaming = 0;
+
+	wake_up_interruptible(&se401->wq);
+
+	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
+		se401->urb[i]->next = NULL;
+		usb_unlink_urb(se401->urb[i]);
+		usb_free_urb(se401->urb[i]);
+		se401->urb[i] = NULL;
+		kfree(se401->sbuf[i].data);
+	}
+	for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
+		kfree(se401->scratch[i].data);
+	}
+	if (se401->inturb) {
+		usb_unlink_urb(se401->inturb);
+		usb_free_urb(se401->inturb);
+	}
+        info("%s disconnected", se401->camera_name);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	destroy_proc_se401_cam(se401);
+#endif
+
+        /* Free the memory */
+	kfree(se401->width);
+	kfree(se401->height);
+	kfree(se401);
+}
+
+static struct usb_driver se401_driver = {
+        name:		"se401",
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
+        id_table:	device_table,
+#endif
+	probe:		se401_probe,
+        disconnect:	se401_disconnect
+};
+
+
+
+/****************************************************************************
+ *
+ *  Module routines
+ *
+ ***************************************************************************/
+
+static int __init usb_se401_init(void)
+{
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	proc_se401_create();
+#endif
+
+	info("SE401 usb camera driver version %s registering", version);
+	if (flickerless)
+		if (flickerless!=50 && flickerless!=60) {
+			info("Invallid flickerless value, use 0, 50 or 60.");
+			return -1;
+	}
+	if (usb_register(&se401_driver) < 0)
+		return -1;
+	return 0;
+}
+
+static void __exit usb_se401_exit(void)
+{
+	usb_deregister(&se401_driver);
+	info("SE401 driver deregistered");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	proc_se401_destroy();
+#endif
+}
+
+module_init(usb_se401_init);
+module_exit(usb_se401_exit);
diff -Nru a/drivers/usb/media/se401.h b/drivers/usb/media/se401.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/se401.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,237 @@
+
+#ifndef __LINUX_se401_H
+#define __LINUX_se401_H
+
+#include <asm/uaccess.h>
+#include <linux/videodev.h>
+#include <linux/smp_lock.h>
+
+#define se401_DEBUG	/* Turn on debug messages */
+
+#ifdef se401_DEBUG
+#  define PDEBUG(level, fmt, args...) \
+if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
+#else
+#  define PDEBUG(level, fmt, args...) do {} while(0)
+#endif
+
+/* An almost drop-in replacement for sleep_on_interruptible */
+#define wait_interruptible(test, queue, wait) \
+{ \
+	add_wait_queue(queue, wait); \
+	set_current_state(TASK_INTERRUPTIBLE); \
+	if (test) \
+		schedule(); \
+	remove_wait_queue(queue, wait); \
+	set_current_state(TASK_RUNNING); \
+	if (signal_pending(current)) \
+		break; \
+}
+
+#define SE401_REQ_GET_CAMERA_DESCRIPTOR		0x06
+#define SE401_REQ_START_CONTINUOUS_CAPTURE	0x41
+#define SE401_REQ_STOP_CONTINUOUS_CAPTURE	0x42
+#define SE401_REQ_CAPTURE_FRAME			0x43
+#define SE401_REQ_GET_BRT			0x44
+#define SE401_REQ_SET_BRT			0x45
+#define SE401_REQ_GET_WIDTH			0x4c
+#define SE401_REQ_SET_WIDTH			0x4d
+#define SE401_REQ_GET_HEIGHT			0x4e
+#define SE401_REQ_SET_HEIGHT			0x4f
+#define SE401_REQ_GET_OUTPUT_MODE		0x50
+#define SE401_REQ_SET_OUTPUT_MODE		0x51
+#define SE401_REQ_GET_EXT_FEATURE		0x52
+#define SE401_REQ_SET_EXT_FEATURE		0x53
+#define SE401_REQ_CAMERA_POWER			0x56
+#define SE401_REQ_LED_CONTROL			0x57
+#define SE401_REQ_BIOS				0xff
+
+#define SE401_BIOS_READ				0x07
+
+#define SE401_FORMAT_BAYER	0x40
+
+/* Hyundai hv7131b registers
+   7121 and 7141 should be the same (haven't really checked...) */
+/* Mode registers: */
+#define HV7131_REG_MODE_A		0x00
+#define HV7131_REG_MODE_B		0x01
+#define HV7131_REG_MODE_C		0x02
+/* Frame registers: */
+#define HV7131_REG_FRSU		0x10
+#define HV7131_REG_FRSL		0x11
+#define HV7131_REG_FCSU		0x12
+#define HV7131_REG_FCSL		0x13
+#define HV7131_REG_FWHU		0x14
+#define HV7131_REG_FWHL		0x15
+#define HV7131_REG_FWWU		0x16
+#define HV7131_REG_FWWL		0x17
+/* Timing registers: */
+#define HV7131_REG_THBU		0x20
+#define HV7131_REG_THBL		0x21
+#define HV7131_REG_TVBU		0x22
+#define HV7131_REG_TVBL		0x23
+#define HV7131_REG_TITU		0x25
+#define HV7131_REG_TITM		0x26
+#define HV7131_REG_TITL		0x27
+#define HV7131_REG_TMCD		0x28
+/* Adjust Registers: */
+#define HV7131_REG_ARLV		0x30
+#define HV7131_REG_ARCG		0x31
+#define HV7131_REG_AGCG		0x32
+#define HV7131_REG_ABCG		0x33
+#define HV7131_REG_APBV		0x34
+#define HV7131_REG_ASLP		0x54
+/* Offset Registers: */
+#define HV7131_REG_OFSR		0x50
+#define HV7131_REG_OFSG		0x51
+#define HV7131_REG_OFSB		0x52
+/* REset level statistics registers: */
+#define HV7131_REG_LOREFNOH	0x57
+#define HV7131_REG_LOREFNOL	0x58
+#define HV7131_REG_HIREFNOH	0x59
+#define HV7131_REG_HIREFNOL	0x5a
+
+/* se401 registers */
+#define SE401_OPERATINGMODE	0x2000
+
+
+/* size of usb transfers */
+#define SE401_PACKETSIZE	4096
+/* number of queued bulk transfers to use, should be about 8 */
+#define SE401_NUMSBUF		1
+/* read the usb specs for this one :) */
+#define SE401_VIDEO_ENDPOINT	1
+#define SE401_BUTTON_ENDPOINT	2
+/* number of frames supported by the v4l part */
+#define SE401_NUMFRAMES		2
+/* scratch buffers for passing data to the decoders */
+#define SE401_NUMSCRATCH	32
+/* maximum amount of data in a JangGu packet */
+#define SE401_VLCDATALEN	1024
+/* number of nul sized packets to receive before kicking the camera */
+#define SE401_MAX_NULLPACKETS	4000
+/* number of decoding errors before kicking the camera */
+#define SE401_MAX_ERRORS	200
+
+struct usb_device;
+
+struct se401_sbuf {
+	unsigned char *data;
+};
+
+enum {
+	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
+	FRAME_READY,		/* Ready to start grabbing */
+	FRAME_GRABBING,		/* In the process of being grabbed into */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
+	FRAME_ERROR,		/* Something bad happened while processing */
+};
+
+enum {
+	FMT_BAYER,
+	FMT_JANGGU,
+};
+
+enum {
+	BUFFER_UNUSED,
+	BUFFER_READY,
+	BUFFER_BUSY,
+	BUFFER_DONE,
+};
+
+struct se401_scratch {
+	unsigned char *data;
+	volatile int state;
+	int offset;
+	int length;
+};
+
+struct se401_frame {
+	unsigned char *data;		/* Frame buffer */
+
+	volatile int grabstate;	/* State of grabbing */
+
+	unsigned char *curline;
+	int curlinepix;
+	int curpix;
+};
+
+struct usb_se401 {
+	struct video_device vdev;
+
+	/* Device structure */
+	struct usb_device *dev;
+
+	unsigned char iface;
+
+	char *camera_name;
+
+	int change;
+	int brightness;
+	int hue;
+	int rgain;
+	int ggain;
+	int bgain;
+	int expose_h;
+	int expose_m;
+	int expose_l;
+	int resetlevel;
+	
+	int enhance;
+
+	int format;
+	int sizes;
+	int *width;
+	int *height;
+	int cwidth;		/* current width */
+	int cheight;		/* current height */
+	int palette;
+	int maxframesize;
+	int cframesize;		/* current framesize */
+
+	struct semaphore lock;
+	int user;		/* user count for exclusive use */
+	int removed;		/* device disconnected */
+
+	int streaming;		/* Are we streaming video? */
+
+	char *fbuf;		/* Videodev buffer area */
+
+	struct urb *urb[SE401_NUMSBUF];
+	struct urb *inturb;
+	
+	int button;
+	int buttonpressed;
+
+	int curframe;		/* Current receiving frame */
+	struct se401_frame frame[SE401_NUMFRAMES];	
+	int readcount;
+	int framecount;
+	int error;
+	int dropped;
+
+	int scratch_next;
+	int scratch_use;
+	int scratch_overflow;
+	struct se401_scratch scratch[SE401_NUMSCRATCH];
+
+	/* Decoder specific data: */
+	unsigned char vlcdata[SE401_VLCDATALEN];
+	int vlcdatapos;
+	int bayeroffset;
+
+	struct se401_sbuf sbuf[SE401_NUMSBUF];
+
+	wait_queue_head_t wq;	/* Processes waiting */
+
+	/* proc interface */
+	struct proc_dir_entry *proc_entry;	/* /proc/se401/videoX */
+
+	int nullpackets;
+};
+
+static inline void usb_se401_remove_disconnected (struct usb_se401 *se401);
+
+
+#endif
+
diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/stv680.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,1589 @@
+/*
+ *  STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
+ *  
+ * Thanks to STMicroelectronics for information on the usb commands, and 
+ * to Steve Miller at STM for his help and encouragement while I was 
+ * writing this driver.
+ *
+ * This driver is based heavily on the 
+ * Endpoints (formerly known as AOX) se401 USB Camera Driver
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * Still somewhat based on the Linux ov511 driver.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * History: 
+ * ver 0.1 October, 2001. Initial attempt. 
+ *
+ * ver 0.2 November, 2001. Fixed asbility to resize, added brightness
+ *                         function, made more stable (?)
+ *
+ * ver 0.21 Nov, 2001.     Added gamma correction and white balance, 
+ *                         due to Alexander Schwartz. Still trying to 
+ *                         improve stablility. Moved stuff into stv680.h
+ *
+ * ver 0.22 Nov, 2001.	   Added sharpen function (by Michael Sweet, 
+ *                         mike@easysw.com) from GIMP, also used in pencam. 
+ *                         Simple, fast, good integer math routine.
+ *
+ * ver 0.23 Dec, 2001 (gkh)
+ * 			   Took out sharpen function, ran code through
+ * 			   Lindent, and did other minor tweaks to get
+ * 			   things to work properly with 2.5.1
+ *
+ * ver 0.24 Jan, 2002 (kjs) 
+ *                         Fixed the problem with webcam crashing after
+ *                         two pictures. Changed the way pic is halved to 
+ *                         improve quality. Got rid of green line around 
+ *                         frame. Fix brightness reset when changing size 
+ *                         bug. Adjusted gamma filters slightly.
+ *
+ * ver 0.25 Jan, 2002 (kjs)
+ *			   Fixed a bug in which the driver sometimes attempted
+ *			   to set to a non-supported size. This allowed
+ *			   gnomemeeting to work.
+ *			   Fixed proc entry removal bug.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/wrapper.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/videodev.h>
+#include <linux/usb.h>
+
+#include "stv680.h"
+
+static int video_nr = -1;
+static int swapRGB = 0;   /* default for auto sleect */
+static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
+
+static unsigned int debug = 0;
+
+#define PDEBUG(level, fmt, args...) \
+	do { \
+	if (debug >= level)	\
+		info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args);	\
+	} while (0)
+
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.25"
+#define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>"
+#define DRIVER_DESC "STV0680 USB Camera Driver"
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_LICENSE ("GPL");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "Debug enabled or not");
+MODULE_PARM (swapRGB_on, "i");
+MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
+MODULE_PARM (video_nr, "i");
+EXPORT_NO_SYMBOLS;
+
+/********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the ov511 driver -claudio
+ *
+ * Same for the se401 driver -Jeroen
+ *
+ * And the STV0680 driver - Kevin
+ ********************************************************************/
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long kvirt_to_pa (unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+	return ret;
+}
+
+static void *rvmalloc (unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32 (size);
+	if (!mem)
+		return NULL;
+
+	memset (mem, 0, size);	/* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		mem_map_reserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	return mem;
+}
+
+static void rvfree (void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree (mem);
+}
+
+
+/*********************************************************************
+ * pencam read/write functions
+ ********************************************************************/
+
+static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size)
+{
+	int ret = -1;
+
+	switch (set) {
+	case 0:		/*  0xc1  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_rcvctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	case 1:		/*  0x41  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_sndctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	case 2:		/*  0x80  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_rcvctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_IN | USB_RECIP_DEVICE),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	case 3:		/*  0x40  */
+		ret = usb_control_msg (stv680->udev,
+				       usb_sndctrlpipe (stv680->udev, 0),
+				       req,
+				       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
+				       value, 0, buffer, size, PENCAM_TIMEOUT);
+		break;
+
+	}
+	if ((ret < 0) && (req != 0x0a)) {
+		PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret);
+	}
+	return ret;
+}
+
+static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate)
+{
+
+	if (usb_set_configuration (dev->udev, configuration) < 0) {
+		PDEBUG (1, "STV(e): FAILED to set configuration %i", configuration);
+		return -1;
+	}
+	if (usb_set_interface (dev->udev, interface, alternate) < 0) {
+		PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate);
+		return -1;
+	}
+	return 0;
+}
+
+static int stv_stop_video (struct usb_stv *dev)
+{
+	int i;
+	unsigned char *buf;
+
+	buf = kmalloc (40, GFP_KERNEL);
+	if (buf == NULL) {
+		PDEBUG (0, "STV(e): Out of (small buf) memory");
+		return -1;
+	}
+
+	/* this is a high priority command; it stops all lower order commands */
+	if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) {
+		i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02);	/* Get Last Error; 2 = busy */
+		PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buf[0], buf[1]);
+	} else {
+		PDEBUG (1, "STV(i): Camera reset to idle mode.");
+	}
+
+	if ((i = stv_set_config (dev, 1, 0, 0)) < 0)
+		PDEBUG (1, "STV(e): Reset config during exit failed");
+
+	/*  get current mode  */
+	buf[0] = 0xf0;
+	if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08)	/* get mode */
+		PDEBUG (0, "STV(e): Stop_video: problem setting original mode");
+	if (dev->origMode != buf[0]) {
+		memset (buf, 0, 8);
+		buf[0] = (unsigned char) dev->origMode;
+		if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) {
+			PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed");
+			i = -1;
+		}
+		buf[0] = 0xf0;
+		i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08);
+		if ((i != 0x08) || (buf[0] != dev->origMode)) {
+			PDEBUG (0, "STV(e): camera NOT set to original resolution.");
+			i = -1;
+		} else
+			PDEBUG (0, "STV(i): Camera set to original resolution");
+	}
+	/* origMode */
+	kfree (buf);
+	return i;
+}
+
+static int stv_set_video_mode (struct usb_stv *dev)
+{
+	int i, stop_video = 1;
+	unsigned char *buf;
+
+	buf = kmalloc (40, GFP_KERNEL);
+	if (buf == NULL) {
+		PDEBUG (0, "STV(e): Out of (small buf) memory");
+		return -1;
+	}
+
+	if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
+		kfree (buf);
+		return i;
+	}
+
+	i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12);
+	if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) {
+		PDEBUG (1, "STV(e): Could not get descriptor 0100.");
+		goto error;
+	}
+
+	/*  set alternate interface 1 */
+	if ((i = stv_set_config (dev, 1, 0, 1)) < 0)
+		goto error;
+
+	if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10)
+		goto error;
+	PDEBUG (1, "STV(i): Setting video mode.");
+	/*  Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240)  */
+	if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) {
+		stop_video = 0;
+		goto error;
+	}
+	goto exit;
+
+error:
+	kfree (buf);
+	if (stop_video == 1)
+		stv_stop_video (dev);
+	return -1;
+
+exit:
+	kfree (buf);
+	return 0;
+}
+
+static int stv_init (struct usb_stv *stv680)
+{
+	int i = 0;
+	unsigned char *buffer;
+	unsigned long int bufsize;
+
+	buffer = kmalloc (40, GFP_KERNEL);
+	if (buffer == NULL) {
+		PDEBUG (0, "STV(e): Out of (small buf) memory");
+		return -1;
+	}
+	memset (buffer, 0, 40);
+	udelay (100);
+
+	/* set config 1, interface 0, alternate 0 */
+	if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
+		kfree (buffer);
+		PDEBUG (0, "STV(e): set config 1,0,0 failed");
+		return -1;
+	}
+	/* ping camera to be sure STV0680 is present */
+	if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02)
+		goto error;
+	if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) {
+		PDEBUG (1, "STV(e): camera ping failed!!");
+		goto error;
+	}
+
+	/* get camera descriptor */
+	if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09)
+		goto error;
+	i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22);
+	if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) {
+		PDEBUG (1, "STV(e): Could not get descriptor 0200.");
+		goto error;
+	}
+	if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02)
+		goto error;
+	if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24)
+		goto error;
+	if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+		goto error;
+
+	stv680->SupportedModes = buffer[7];
+	i = stv680->SupportedModes;
+	stv680->CIF = 0;
+	stv680->VGA = 0;
+	stv680->QVGA = 0;
+	if (i & 1)
+		stv680->CIF = 1;
+	if (i & 2)
+		stv680->VGA = 1;
+	if (i & 8)
+		stv680->QVGA = 1;
+	if (stv680->SupportedModes == 0) {
+		PDEBUG (0, "STV(e): There are NO supported STV680 modes!!");
+		i = -1;
+		goto error;
+	} else {
+		if (stv680->CIF)
+			PDEBUG (0, "STV(i): CIF is supported");
+		if (stv680->QVGA)
+			PDEBUG (0, "STV(i): QVGA is supported");
+	}
+	/* FW rev, ASIC rev, sensor ID  */
+	PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]);
+	PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]);
+	PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4));
+
+	/*  set alternate interface 1 */
+	if ((i = stv_set_config (stv680, 1, 0, 1)) < 0)
+		goto error;
+
+	if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
+		goto error;
+	if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08)
+		goto error;
+	i = buffer[3];
+	PDEBUG (0, "STV(i): Camera has %i pictures.", i);
+
+	/*  get current mode */
+	if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08)
+		goto error;
+	stv680->origMode = buffer[0];	/* 01 = VGA, 03 = QVGA, 00 = CIF */
+
+	/* This will attemp CIF mode, if supported. If not, set to QVGA  */
+	memset (buffer, 0, 8);
+	if (stv680->CIF)
+		buffer[0] = 0x00;
+	else if (stv680->QVGA)
+		buffer[0] = 0x03;
+	if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) {
+		PDEBUG (0, "STV(i): Set_Camera_Mode failed");
+		i = -1;
+		goto error;
+	}
+	buffer[0] = 0xf0;
+	stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08);
+	if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) {
+		PDEBUG (0, "STV(e): Error setting camera video mode!");
+		i = -1;
+		goto error;
+	} else {
+		if (buffer[0] == 0) {
+			stv680->VideoMode = 0x0000;
+			PDEBUG (0, "STV(i): Video Mode set to CIF");
+		}
+		if (buffer[0] == 0x03) {
+			stv680->VideoMode = 0x0300;
+			PDEBUG (0, "STV(i): Video Mode set to QVGA");
+		}
+	}
+	if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10)
+		goto error;
+	bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]);
+	stv680->cwidth = (buffer[4] << 8) | (buffer[5]);	/* ->camera = 322, 356, 644  */
+	stv680->cheight = (buffer[6] << 8) | (buffer[7]);	/* ->camera = 242, 292, 484  */
+	stv680->origGain = buffer[12];
+
+	goto exit;
+
+error:
+	i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02);	/* Get Last Error */
+	PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buffer[0], buffer[1]);
+	kfree (buffer);
+	return -1;
+
+exit:
+	kfree (buffer);
+
+	/* video = 320x240, 352x288 */
+	if (stv680->CIF == 1) {
+		stv680->maxwidth = 352;
+		stv680->maxheight = 288;
+		stv680->vwidth = 352;
+		stv680->vheight = 288;
+	}
+	if (stv680->QVGA == 1) {
+		stv680->maxwidth = 320;
+		stv680->maxheight = 240;
+		stv680->vwidth = 320;
+		stv680->vheight = 240;
+	}
+
+	stv680->rawbufsize = bufsize;	/* must be ./. by 8 */
+	stv680->maxframesize = bufsize * 3;	/* RGB size */
+	PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight);
+	PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize);
+
+	/* some default values */
+	stv680->bulk_in_endpointAddr = 0x82;
+	stv680->dropped = 0;
+	stv680->error = 0;
+	stv680->framecount = 0;
+	stv680->readcount = 0;
+	stv680->streaming = 0;
+	/* bright, white, colour, hue, contrast are set by software, not in stv0680 */
+	stv680->brightness = 32767;
+	stv680->chgbright = 0;
+	stv680->whiteness = 0;	/* only for greyscale */
+	stv680->colour = 32767;
+	stv680->contrast = 32767;
+	stv680->hue = 32767;
+	stv680->palette = STV_VIDEO_PALETTE;
+	stv680->depth = 24;	/* rgb24 bits */
+	swapRGB = 0;
+	if ((swapRGB_on == 0) && (swapRGB == 0))
+		PDEBUG (1, "STV(i): swapRGB is (auto) OFF");
+	else if ((swapRGB_on == 1) && (swapRGB == 1))
+		PDEBUG (1, "STV(i): swapRGB is (auto) ON");
+	else if (swapRGB_on == 1)
+		PDEBUG (1, "STV(i): swapRGB is (forced) ON");
+	else if (swapRGB_on == -1)
+		PDEBUG (1, "STV(i): swapRGB is (forced) OFF");
+	
+	if (stv_set_video_mode (stv680) < 0) {
+		PDEBUG (0, "STV(e): Could not set video mode in stv_init");
+		return -1;
+	}
+
+	return 0;
+}
+
+/***************** last of pencam  routines  *******************/
+
+/********************************************************************
+ * /proc interface
+ *******************************************************************/
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+
+static struct proc_dir_entry *stv680_proc_entry = NULL;
+extern struct proc_dir_entry *video_proc_entry;
+
+#define YES_NO(x) ((x) ? "yes" : "no")
+#define ON_OFF(x) ((x) ? "(auto) on" : "(auto) off")
+
+static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	char *out = page;
+	int len;
+	struct usb_stv *stv680 = data;
+
+	/* Stay under PAGE_SIZE or else bla bla bla.... */
+
+	out += sprintf (out, "driver_version  : %s\n", DRIVER_VERSION);
+	out += sprintf (out, "model           : %s\n", stv680->camera_name);
+	out += sprintf (out, "in use          : %s\n", YES_NO (stv680->user));
+	out += sprintf (out, "streaming       : %s\n", YES_NO (stv680->streaming));
+	out += sprintf (out, "num_frames      : %d\n", STV680_NUMFRAMES);
+
+	out += sprintf (out, "Current size    : %ix%i\n", stv680->vwidth, stv680->vheight);
+	if (swapRGB_on == 0)
+		out += sprintf (out, "swapRGB         : %s\n", ON_OFF (swapRGB));
+	else if (swapRGB_on == 1)
+		out += sprintf (out, "swapRGB         : (forced) on\n");
+	else if (swapRGB_on == -1)
+		out += sprintf (out, "swapRGB         : (forced) off\n");
+
+	out += sprintf (out, "Palette         : %i", stv680->palette);
+
+	out += sprintf (out, "\n");
+
+	out += sprintf (out, "Frames total    : %d\n", stv680->readcount);
+	out += sprintf (out, "Frames read     : %d\n", stv680->framecount);
+	out += sprintf (out, "Packets dropped : %d\n", stv680->dropped);
+	out += sprintf (out, "Decoding Errors : %d\n", stv680->error);
+
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else
+		len = count;
+
+	*start = page + off;
+	return len;
+}
+
+static int create_proc_stv680_cam (struct usb_stv *stv680)
+{
+	char name[9];
+	struct proc_dir_entry *ent;
+
+	if (!stv680_proc_entry || !stv680)
+		return -1;
+
+	sprintf (name, "video%d", stv680->vdev.minor);
+
+	ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, stv680_proc_entry);
+	if (!ent)
+		return -1;
+
+	ent->data = stv680;
+	ent->read_proc = stv680_read_proc;
+	stv680->proc_entry = ent;
+	return 0;
+}
+
+static void destroy_proc_stv680_cam (struct usb_stv *stv680)
+{
+	/* One to much, just to be sure :) */
+	char name[9];
+
+	if (!stv680 || !stv680->proc_entry)
+		return;
+
+	sprintf (name, "video%d", stv680->vdev.minor);
+	remove_proc_entry (name, stv680_proc_entry);
+	stv680->proc_entry = NULL;
+}
+
+static int proc_stv680_create (void)
+{
+	if (video_proc_entry == NULL) {
+		PDEBUG (0, "STV(e): /proc/video/ doesn't exist!");
+		return -1;
+	}
+	stv680_proc_entry = create_proc_entry ("stv680", S_IFDIR, video_proc_entry);
+
+	if (stv680_proc_entry) {
+		stv680_proc_entry->owner = THIS_MODULE;
+	} else {
+		PDEBUG (0, "STV(e): Unable to initialize /proc/video/stv680");
+		return -1;
+	}
+	return 0;
+}
+
+static void proc_stv680_destroy (void)
+{
+	if (stv680_proc_entry == NULL)
+		return;
+
+	remove_proc_entry ("stv680", video_proc_entry);
+}
+#endif				/* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
+
+/********************************************************************
+ * Camera control
+ *******************************************************************/
+
+static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+	/* This sets values for v4l interface. max/min = 65535/0  */
+
+	p->brightness = stv680->brightness;
+	p->whiteness = stv680->whiteness;	/* greyscale */
+	p->colour = stv680->colour;
+	p->contrast = stv680->contrast;
+	p->hue = stv680->hue;
+	p->palette = stv680->palette;
+	p->depth = stv680->depth;
+	return 0;
+}
+
+static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
+{
+	/* See above stv680_get_pict  */
+
+	if (p->palette != STV_VIDEO_PALETTE) {
+		PDEBUG (2, "STV(e): Palette set error in _set_pic");
+		return 1;
+	}
+
+	if (stv680->brightness != p->brightness) {
+		stv680->chgbright = 1;
+		stv680->brightness = p->brightness;
+	} 
+
+	stv680->whiteness = p->whiteness;	/* greyscale */
+	stv680->colour = p->colour;
+	stv680->contrast = p->contrast;
+	stv680->hue = p->hue;
+	stv680->palette = p->palette;
+	stv680->depth = p->depth;
+
+	return 0;
+}
+
+static void stv680_video_irq (struct urb *urb)
+{
+	struct usb_stv *stv680 = urb->context;
+	int length = urb->actual_length;
+
+	if (length < stv680->rawbufsize)
+		PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length);
+
+	/* ohoh... */
+	if (!stv680->streaming)
+		return;
+
+	if (!stv680->udev) {
+		PDEBUG (0, "STV(e): device vapourished in video_irq");
+		return;
+	}
+
+	/* 0 sized packets happen if we are to fast, but sometimes the camera
+	   keeps sending them forever...
+	 */
+	if (length && !urb->status) {
+		stv680->nullpackets = 0;
+		switch (stv680->scratch[stv680->scratch_next].state) {
+		case BUFFER_READY:
+		case BUFFER_BUSY:
+			stv680->dropped++;
+			break;
+
+		case BUFFER_UNUSED:
+			memcpy (stv680->scratch[stv680->scratch_next].data,
+			        (unsigned char *) urb->transfer_buffer, length);
+			stv680->scratch[stv680->scratch_next].state = BUFFER_READY;
+			stv680->scratch[stv680->scratch_next].length = length;
+			if (waitqueue_active (&stv680->wq)) {
+				wake_up_interruptible (&stv680->wq);
+			}
+			stv680->scratch_overflow = 0;
+			stv680->scratch_next++;
+			if (stv680->scratch_next >= STV680_NUMSCRATCH)
+				stv680->scratch_next = 0;;
+			break;
+		}		/* switch  */
+	} else {
+		stv680->nullpackets++;
+		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+			if (waitqueue_active (&stv680->wq)) {
+				wake_up_interruptible (&stv680->wq);
+			}
+		}
+	}			/*  if - else */
+
+	/* Resubmit urb for new data */
+	urb->status = 0;
+	urb->dev = stv680->udev;
+	if (usb_submit_urb (urb, GFP_KERNEL))
+		PDEBUG (0, "STV(e): urb burned down in video irq");
+	return;
+}				/*  _video_irq  */
+
+static int stv680_start_stream (struct usb_stv *stv680)
+{
+	struct urb *urb;
+	int err = 0, i;
+
+	stv680->streaming = 1;
+
+	/* Do some memory allocation */
+	for (i = 0; i < STV680_NUMFRAMES; i++) {
+		stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize;
+		stv680->frame[i].curpix = 0;
+	}
+	/* packet size = 4096  */
+	for (i = 0; i < STV680_NUMSBUF; i++) {
+		stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+		if (stv680->sbuf[i].data == NULL) {
+			PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
+			return -1;
+		}
+	}
+
+	stv680->scratch_next = 0;
+	stv680->scratch_use = 0;
+	stv680->scratch_overflow = 0;
+	for (i = 0; i < STV680_NUMSCRATCH; i++) {
+		stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
+		if (stv680->scratch[i].data == NULL) {
+			PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
+			return -1;
+		}
+		stv680->scratch[i].state = BUFFER_UNUSED;
+	}
+
+	for (i = 0; i < STV680_NUMSBUF; i++) {
+		urb = usb_alloc_urb (0, GFP_KERNEL);
+		if (!urb)
+			return ENOMEM;
+
+		/* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
+		usb_fill_bulk_urb (urb, stv680->udev,
+				   usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
+				   stv680->sbuf[i].data, stv680->rawbufsize,
+				   stv680_video_irq, stv680);
+		urb->timeout = PENCAM_TIMEOUT * 2;
+		urb->transfer_flags |= USB_QUEUE_BULK;
+		stv680->urb[i] = urb;
+		err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
+		if (err)
+			PDEBUG (0, "STV(e): urb burned down in start stream");
+	}			/* i STV680_NUMSBUF */
+
+	stv680->framecount = 0;
+	return 0;
+}
+
+static int stv680_stop_stream (struct usb_stv *stv680)
+{
+	int i;
+
+	if (!stv680->streaming || !stv680->udev)
+		return 1;
+
+	stv680->streaming = 0;
+
+	for (i = 0; i < STV680_NUMSBUF; i++)
+		if (stv680->urb[i]) {
+			stv680->urb[i]->next = NULL;
+			usb_unlink_urb (stv680->urb[i]);
+			usb_free_urb (stv680->urb[i]);
+			stv680->urb[i] = NULL;
+			kfree (stv680->sbuf[i].data);
+		}
+	for (i = 0; i < STV680_NUMSCRATCH; i++) {
+		kfree (stv680->scratch[i].data);
+		stv680->scratch[i].data = NULL;
+	}
+
+	return 0;
+}
+
+static int stv680_set_size (struct usb_stv *stv680, int width, int height)
+{
+	int wasstreaming = stv680->streaming;
+
+	/* Check to see if we need to change */
+	if ((stv680->vwidth == width) && (stv680->vheight == height))
+		return 0;
+
+	PDEBUG (1, "STV(i): size request for %i x %i", width, height);
+	/* Check for a valid mode */
+	if ((!width || !height) || ((width & 1) || (height & 1))) {
+		PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
+		return 1;
+	}
+
+	if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {
+		width = stv680->maxwidth / 2;
+		height = stv680->maxheight / 2;
+	} else if ((width >= 158) && (width <= 166) && (stv680->QVGA == 1)) {
+		width = 160;
+		height = 120;
+	} else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) {
+		width = 176;
+		height = 144;
+	} else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) {
+		width = 320;
+		height = 240;
+	} else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) {
+		width = 352;
+		height = 288;
+	} else {
+		PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
+		return 1;
+	}
+	
+	/* Stop a current stream and start it again at the new size */
+	if (wasstreaming)
+		stv680_stop_stream (stv680);
+	stv680->vwidth = width;
+	stv680->vheight = height;
+	PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight);
+	if (wasstreaming)
+		stv680_start_stream (stv680);
+
+	return 0;
+}
+
+/**********************************************************************
+ * Video Decoding
+ **********************************************************************/
+
+/*******  routines from the pencam program; hey, they work!  ********/
+
+/*
+ * STV0680 Vision Camera Chipset Driver
+ * Copyright (C) 2000 Adam Harrison <adam@antispin.org> 
+*/
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define AD(x, y, w) (((y)*(w)+(x))*3)
+
+static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer)
+{
+	int x, y, i;
+	int w = stv680->cwidth;
+	int vw = stv680->cwidth, vh = stv680->cheight;
+	unsigned int p = 0;
+	int colour = 0, bayer = 0;
+	unsigned char *raw = buffer->data;
+	struct stv680_frame *frame = &stv680->frame[stv680->curframe];
+	unsigned char *output = frame->data;
+	unsigned char *temp = frame->data;
+	int offset = buffer->offset;
+
+	if (frame->curpix == 0) {
+		if (frame->grabstate == FRAME_READY) {
+			frame->grabstate = FRAME_GRABBING;
+		}
+	}
+	if (offset != frame->curpix) {	/* Regard frame as lost :( */
+		frame->curpix = 0;
+		stv680->error++;
+		return;
+	}
+
+	if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) {
+		vw = 320;
+		vh = 240;
+	}
+	if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) {
+		vw = 352;
+		vh = 288;
+	}
+
+	memset (output, 0, 3 * vw * vh);	/* clear output matrix. */
+
+	for (y = 0; y < vh; y++) {
+		for (x = 0; x < vw; x++) {
+			if (x & 1)
+				p = *(raw + y * w + (x >> 1));
+			else
+				p = *(raw + y * w + (x >> 1) + (w >> 1));
+
+			if (y & 1)
+				bayer = 2;
+			else
+				bayer = 0;
+			if (x & 1)
+				bayer++;
+
+			switch (bayer) {
+			case 0:
+			case 3:
+				colour = 1;
+				break;
+			case 1:
+				colour = 0;
+				break;
+			case 2:
+				colour = 2;
+				break;
+			}
+			i = (y * vw + x) * 3;	
+			*(output + i + colour) = (unsigned char) p;
+		}		/* for x */
+
+	}			/* for y */
+
+	/****** gamma correction plus hardcoded white balance */
+	/* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
+	   Correction values red[], green[], blue[], are generated by 
+	   (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255. 
+	   White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and 
+	   converted to unsigned char. Values are in stv680.h  */
+
+	for (y = 0; y < vh; y++) {
+		for (x = 0; x < vw; x++) {
+			i = (y * vw + x) * 3;
+			*(output + i) = red[*(output + i)];
+			*(output + i + 1) = green[*(output + i + 1)];
+			*(output + i + 2) = blue[*(output + i + 2)];
+		}
+	}
+
+	/******  bayer demosaic  ******/
+	for (y = 1; y < (vh - 1); y++) {
+		for (x = 1; x < (vw - 1); x++) {	/* work out pixel type */
+			if (y & 1)
+				bayer = 0;
+			else
+				bayer = 2;
+			if (!(x & 1))
+				bayer++;
+
+			switch (bayer) {
+			case 0:	/* green. blue lr, red tb */
+				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1;
+				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1;
+				break;
+
+			case 1:	/* blue. green lrtb, red diagonals */
+				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2;
+				break;
+
+			case 2:	/* red. green lrtb, blue diagonals */
+				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
+				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2;
+				break;
+
+			case 3:	/* green. red lr, blue tb */
+				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1;
+				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1;
+				break;
+			}	/* switch */
+		}		/* for x */
+	}			/* for y  - end demosaic  */
+
+	/* fix top and bottom row, left and right side */
+	i = vw * 3;
+	memcpy (output, (output + i), i);
+	memcpy ((output + (vh * i)), (output + ((vh - 1) * i)), i);
+	for (y = 0; y < vh; y++) {
+		i = y * vw * 3;
+		memcpy ((output + i), (output + i + 3), 3);
+		memcpy ((output + i + (vw * 3)), (output + i + (vw - 1) * 3), 3);
+	}
+
+	/*  process all raw data, then trim to size if necessary */
+	if ((stv680->vwidth == 160) || (stv680->vwidth == 176))  {
+		i = 0;
+		for (y = 0; y < vh; y++) {
+			if (!(y & 1)) {
+				for (x = 0; x < vw; x++) {
+					p = (y * vw + x) * 3;
+					if (!(x & 1)) {
+						*(output + i) = *(output + p);
+						*(output + i + 1) = *(output + p + 1);
+						*(output + i + 2) = *(output + p + 2);
+						i += 3;
+					}
+				}  /* for x */
+			}
+		}  /* for y */
+	}
+	/* reset to proper width */
+	if ((stv680->vwidth == 160)) {
+		vw = 160;
+		vh = 120;
+	}
+	if ((stv680->vwidth == 176)) {
+		vw = 176;
+		vh = 144;
+	}
+
+	/* output is RGB; some programs want BGR  */
+	/* swapRGB_on=0 -> program decides;  swapRGB_on=1, always swap */
+	/* swapRGB_on=-1, never swap */
+	if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) {
+		for (y = 0; y < vh; y++) {
+			for (x = 0; x < vw; x++) {
+				i = (y * vw + x) * 3;
+				*(temp) = *(output + i);
+				*(output + i) = *(output + i + 2);
+				*(output + i + 2) = *(temp);
+			}
+		}
+	}
+	/* brightness */
+	if (stv680->chgbright == 1) {
+		if (stv680->brightness >= 32767) {
+			p = (stv680->brightness - 32767) / 256;
+			for (x = 0; x < (vw * vh * 3); x++) {
+				if ((*(output + x) + (unsigned char) p) > 255)
+					*(output + x) = 255;
+				else
+					*(output + x) += (unsigned char) p;
+			}	/* for */
+		} else {
+			p = (32767 - stv680->brightness) / 256;
+			for (x = 0; x < (vw * vh * 3); x++) {
+				if ((unsigned char) p > *(output + x))
+					*(output + x) = 0;
+				else
+					*(output + x) -= (unsigned char) p;
+			}	/* for */
+		}		/* else */
+	}
+	/* if */
+	frame->curpix = 0;
+	frame->curlinepix = 0;
+	frame->grabstate = FRAME_DONE;
+	stv680->framecount++;
+	stv680->readcount++;
+	if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) {
+		stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1);
+	}
+
+}				/* bayer_unshuffle */
+
+/*******  end routines from the pencam program  *********/
+
+static int stv680_newframe (struct usb_stv *stv680, int framenr)
+{
+	int errors = 0;
+
+	while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) {
+		if (!stv680->frame[framenr].curpix) {
+			errors++;
+		}
+		wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY));
+
+		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
+			stv680->nullpackets = 0;
+			PDEBUG (2, "STV(i): too many null length packets, restarting capture");
+			stv680_stop_stream (stv680);
+			stv680_start_stream (stv680);
+		} else {
+			if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) {
+				stv680->frame[framenr].grabstate = FRAME_ERROR;
+				PDEBUG (2, "STV(e): FRAME_ERROR in _newframe");
+				return -EIO;
+			}
+			stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY;
+
+			bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]);
+
+			stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;
+			stv680->scratch_use++;
+			if (stv680->scratch_use >= STV680_NUMSCRATCH)
+				stv680->scratch_use = 0;
+			if (errors > STV680_MAX_ERRORS) {
+				errors = 0;
+				PDEBUG (2, "STV(i): too many errors, restarting capture");
+				stv680_stop_stream (stv680);
+				stv680_start_stream (stv680);
+			}
+		}		/* else */
+	}			/* while */
+	return 0;
+}
+
+/*********************************************************************
+ * Video4Linux
+ *********************************************************************/
+
+static int stv_open (struct inode *inode, struct file *file)
+{
+	struct video_device *dev = video_devdata(file);
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	int err = 0;
+
+	/* we are called with the BKL held */
+	stv680->user = 1;
+	err = stv_init (stv680);	/* main initialization routine for camera */
+
+	if (err >= 0) {
+		stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);
+		if (!stv680->fbuf) {
+			PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");
+			err = -ENOMEM;
+		}
+		file->private_data = dev;
+	}
+	if (err)
+		stv680->user = 0;
+
+	return err;
+}
+
+static int stv_close (struct inode *inode, struct file *file)
+{
+	struct video_device *dev = file->private_data;
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	int i;
+
+	for (i = 0; i < STV680_NUMFRAMES; i++)
+		stv680->frame[i].grabstate = FRAME_UNUSED;
+	if (stv680->streaming)
+		stv680_stop_stream (stv680);
+
+	if ((i = stv_stop_video (stv680)) < 0)
+		PDEBUG (1, "STV(e): stop_video failed in stv_close");
+
+	rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);
+	stv680->user = 0;
+
+	if (stv680->removed) {
+		kfree (stv680);
+		stv680 = NULL;
+		PDEBUG (0, "STV(i): device unregistered");
+	}
+	file->private_data = NULL;
+	return 0;
+}
+
+static int stv680_do_ioctl (struct inode *inode, struct file *file,
+			    unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_stv *stv680 = (struct usb_stv *) vdev;
+
+	if (!stv680->udev)
+		return -EIO;
+
+	switch (cmd) {
+	case VIDIOCGCAP:{
+			struct video_capability *b = arg;
+
+			strcpy (b->name, stv680->camera_name);
+			b->type = VID_TYPE_CAPTURE;
+			b->channels = 1;
+			b->audios = 0;
+			b->maxwidth = stv680->maxwidth;
+			b->maxheight = stv680->maxheight;
+			b->minwidth = stv680->maxwidth / 2;
+			b->minheight = stv680->maxheight / 2;
+			return 0;
+		}
+	case VIDIOCGCHAN:{
+			struct video_channel *v = arg;
+
+			if (v->channel != 0)
+				return -EINVAL;
+			v->flags = 0;
+			v->tuners = 0;
+			v->type = VIDEO_TYPE_CAMERA;
+			strcpy (v->name, "STV Camera");
+			return 0;
+		}
+	case VIDIOCSCHAN:{
+			struct video_channel *v = arg;
+			if (v->channel != 0)
+				return -EINVAL;
+			return 0;
+		}
+	case VIDIOCGPICT:{
+			struct video_picture *p = arg;
+
+			stv680_get_pict (stv680, p);
+			return 0;
+		}
+	case VIDIOCSPICT:{
+			struct video_picture *p = arg;
+
+			if (stv680_set_pict (stv680, p))
+				return -EINVAL;
+			return 0;
+		}
+	case VIDIOCSWIN:{
+			struct video_window *vw = arg;
+
+			if (vw->flags)
+				return -EINVAL;
+			if (vw->clipcount)
+				return -EINVAL;
+			if (vw->width != stv680->vwidth) {
+				if (stv680_set_size (stv680, vw->width, vw->height)) {
+					PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN");
+					return -EINVAL;
+				}
+			}
+			return 0;
+		}
+	case VIDIOCGWIN:{
+			struct video_window *vw = arg;
+
+			vw->x = 0;	/* FIXME */
+			vw->y = 0;
+			vw->chromakey = 0;
+			vw->flags = 0;
+			vw->clipcount = 0;
+			vw->width = stv680->vwidth;
+			vw->height = stv680->vheight;
+			return 0;
+		}
+	case VIDIOCGMBUF:{
+			struct video_mbuf *vm = arg;
+			int i;
+
+			memset (vm, 0, sizeof (*vm));
+			vm->size = STV680_NUMFRAMES * stv680->maxframesize;
+			vm->frames = STV680_NUMFRAMES;
+			for (i = 0; i < STV680_NUMFRAMES; i++)
+				vm->offsets[i] = stv680->maxframesize * i;
+			return 0;
+		}
+	case VIDIOCMCAPTURE:{
+			struct video_mmap *vm = arg;
+
+			if (vm->format != STV_VIDEO_PALETTE) {
+				PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",
+					vm->format, STV_VIDEO_PALETTE);
+				if ((vm->format == 3) && (swapRGB_on == 0))  {
+					PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON");
+					/* this may fix those apps (e.g., xawtv) that want BGR */
+					swapRGB = 1;
+				}
+				return -EINVAL;
+			}
+			if (vm->frame >= STV680_NUMFRAMES) {
+				PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");
+				return -EINVAL;
+			}
+			if ((stv680->frame[vm->frame].grabstate == FRAME_ERROR)
+			    || (stv680->frame[vm->frame].grabstate == FRAME_GRABBING)) {
+				PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error",
+					stv680->frame[vm->frame].grabstate);
+				return -EBUSY;
+			}
+			/* Is this according to the v4l spec??? */
+			if (stv680->vwidth != vm->width) {
+				if (stv680_set_size (stv680, vm->width, vm->height)) {
+					PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed");
+					return -EINVAL;
+				}
+			}
+			stv680->frame[vm->frame].grabstate = FRAME_READY;
+
+			if (!stv680->streaming)
+				stv680_start_stream (stv680);
+
+			return 0;
+		}
+	case VIDIOCSYNC:{
+			int *frame = arg;
+			int ret = 0;
+
+			if (*frame < 0 || *frame >= STV680_NUMFRAMES) {
+				PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC");
+				return -EINVAL;
+			}
+			ret = stv680_newframe (stv680, *frame);
+			stv680->frame[*frame].grabstate = FRAME_UNUSED;
+			return ret;
+		}
+	case VIDIOCGFBUF:{
+			struct video_buffer *vb = arg;
+
+			memset (vb, 0, sizeof (*vb));
+			return 0;
+		}
+	case VIDIOCKEY:
+		return 0;
+	case VIDIOCCAPTURE:
+		{
+			PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");
+			return -EINVAL;
+		}
+	case VIDIOCSFBUF:
+		return -EINVAL;
+	case VIDIOCGTUNER:
+	case VIDIOCSTUNER:
+		return -EINVAL;
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+		return -EINVAL;
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+		return -EINVAL;
+	default:
+		return -ENOIOCTLCMD;
+	}			/* end switch */
+
+	return 0;
+}
+
+static int stv680_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, stv680_do_ioctl);
+}
+
+static int stv680_mmap (struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *dev = file->private_data;
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long page, pos;
+
+	down (&stv680->lock);
+
+	if (stv680->udev == NULL) {
+		up (&stv680->lock);
+		return -EIO;
+	}
+	if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
+		    & ~(PAGE_SIZE - 1))) {
+		up (&stv680->lock);
+		return -EINVAL;
+	}
+	pos = (unsigned long) stv680->fbuf;
+	while (size > 0) {
+		page = kvirt_to_pa (pos);
+		if (remap_page_range (vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+			up (&stv680->lock);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	up (&stv680->lock);
+
+	return 0;
+}
+
+static int stv680_read (struct file *file, char *buf,
+			size_t count, loff_t *ppos)
+{
+	struct video_device *dev = file->private_data;
+	unsigned long int realcount = count;
+	int ret = 0;
+	struct usb_stv *stv680 = (struct usb_stv *) dev;
+	unsigned long int i;
+
+	if (STV680_NUMFRAMES != 2) {
+		PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!");
+		return -1;
+	}
+	if (stv680->udev == NULL)
+		return -EIO;
+	if (realcount > (stv680->vwidth * stv680->vheight * 3))
+		realcount = stv680->vwidth * stv680->vheight * 3;
+
+	/* Shouldn't happen: */
+	if (stv680->frame[0].grabstate == FRAME_GRABBING) {
+		PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read");
+		return -EBUSY;
+	}
+	stv680->frame[0].grabstate = FRAME_READY;
+	stv680->frame[1].grabstate = FRAME_UNUSED;
+	stv680->curframe = 0;
+
+	if (!stv680->streaming)
+		stv680_start_stream (stv680);
+
+	if (!stv680->streaming) {
+		ret = stv680_newframe (stv680, 0);	/* ret should = 0 */
+	}
+
+	ret = stv680_newframe (stv680, 0);
+
+	if (!ret) {
+		if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) {
+			PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i);
+			return -EFAULT;
+		}
+	} else {
+		realcount = ret;
+	}
+	stv680->frame[0].grabstate = FRAME_UNUSED;
+	return realcount;
+}				/* stv680_read */
+
+static struct file_operations stv680_fops = {
+	owner:		THIS_MODULE,
+	open:		stv_open,
+	release:       	stv_close,
+	read:		stv680_read,
+	mmap:		stv680_mmap,
+	ioctl:          stv680_ioctl,
+	llseek:         no_llseek,
+};
+static struct video_device stv680_template = {
+	owner:		THIS_MODULE,
+	name:		"STV0680 USB camera",
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_SE401,
+	fops:           &stv680_fops,
+};
+
+static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor *interface;
+	struct usb_stv *stv680;
+	char *camera_name = NULL;
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1) {
+		PDEBUG (0, "STV(e): Number of Configurations != 1");
+		return NULL;
+	}
+
+	interface = &dev->actconfig->interface[ifnum].altsetting[0];
+	/* Is it a STV680? */
+	if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {
+		camera_name = "STV0680";
+		PDEBUG (0, "STV(i): STV0680 camera found.");
+	} else {
+		PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");
+		PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");
+		return NULL;
+	}
+	/* We found one */
+	if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
+		PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");
+		return NULL;
+	}
+
+	memset (stv680, 0, sizeof (*stv680));
+
+	stv680->udev = dev;
+	stv680->camera_name = camera_name;
+
+	memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template));
+	memcpy (stv680->vdev.name, stv680->camera_name, strlen (stv680->camera_name));
+	init_waitqueue_head (&stv680->wq);
+	init_MUTEX (&stv680->lock);
+	wmb ();
+
+	if (video_register_device (&stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+		kfree (stv680);
+		PDEBUG (0, "STV(e): video_register_device failed");
+		return NULL;
+	}
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	create_proc_stv680_cam (stv680);
+#endif
+	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);
+
+	return stv680;
+}
+
+static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
+{
+	int i;
+
+	stv680->udev = NULL;
+	stv680->frame[0].grabstate = FRAME_ERROR;
+	stv680->frame[1].grabstate = FRAME_ERROR;
+	stv680->streaming = 0;
+
+	wake_up_interruptible (&stv680->wq);
+
+	for (i = 0; i < STV680_NUMSBUF; i++)
+		if (stv680->urb[i]) {
+			stv680->urb[i]->next = NULL;
+			usb_unlink_urb (stv680->urb[i]);
+			usb_free_urb (stv680->urb[i]);
+			stv680->urb[i] = NULL;
+			kfree (stv680->sbuf[i].data);
+		}
+	for (i = 0; i < STV680_NUMSCRATCH; i++)
+		if (stv680->scratch[i].data) {
+			kfree (stv680->scratch[i].data);
+		}
+	PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	destroy_proc_stv680_cam (stv680);
+#endif
+	/* Free the memory */
+	kfree (stv680);
+}
+
+static void stv680_disconnect (struct usb_device *dev, void *ptr)
+{
+	struct usb_stv *stv680 = (struct usb_stv *) ptr;
+
+	/* We don't want people trying to open up the device */
+	video_unregister_device (&stv680->vdev);
+	if (!stv680->user) {
+		usb_stv680_remove_disconnected (stv680);
+	} else {
+		stv680->removed = 1;
+	}
+}
+
+static struct usb_driver stv680_driver = {
+	name:		"stv680",
+	probe:		stv680_probe,
+	disconnect:	stv680_disconnect,
+	id_table:	device_table
+};
+
+/********************************************************************
+ *  Module routines
+ ********************************************************************/
+
+static int __init usb_stv680_init (void)
+{
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	if (proc_stv680_create () < 0)
+		return -1;
+#endif
+	if (usb_register (&stv680_driver) < 0) {
+		PDEBUG (0, "STV(e): Could not setup STV0680 driver");
+		return -1;
+	}
+	PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
+
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return 0;
+}
+
+static void __exit usb_stv680_exit (void)
+{
+	usb_deregister (&stv680_driver);
+	PDEBUG (0, "STV(i): driver deregistered");
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+	proc_stv680_destroy ();
+#endif
+}
+
+module_init (usb_stv680_init);
+module_exit (usb_stv680_exit);
diff -Nru a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/stv680.h	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,223 @@
+/****************************************************************************
+ *
+ *  Filename: stv680.h
+ *
+ *  Description:
+ *     This is a USB driver for STV0680 based usb video cameras.
+ *
+ *  This program is free software; you can redistribute it and/or 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.
+ *
+ ****************************************************************************/
+
+/* size of usb transfers */
+#define STV680_PACKETSIZE	4096
+
+/* number of queued bulk transfers to use, may have problems if > 1 */
+#define STV680_NUMSBUF		1
+
+/* number of frames supported by the v4l part */
+#define STV680_NUMFRAMES	2
+
+/* scratch buffers for passing data to the decoders: 2 or 4 are good */
+#define STV680_NUMSCRATCH	2
+
+/* number of nul sized packets to receive before kicking the camera */
+#define STV680_MAX_NULLPACKETS	200
+
+/* number of decoding errors before kicking the camera */
+#define STV680_MAX_ERRORS	100
+
+#define USB_PENCAM_VENDOR_ID	0x0553
+#define USB_PENCAM_PRODUCT_ID	0x0202
+#define PENCAM_TIMEOUT          1000
+/* fmt 4 */
+#define STV_VIDEO_PALETTE       VIDEO_PALETTE_RGB24
+
+static __devinitdata struct usb_device_id device_table[] = {
+	{USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)},
+	{}
+};
+MODULE_DEVICE_TABLE (usb, device_table);
+
+struct stv680_sbuf {
+	unsigned char *data;
+};
+
+enum {
+	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
+	FRAME_READY,		/* Ready to start grabbing */
+	FRAME_GRABBING,		/* In the process of being grabbed into */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
+	FRAME_ERROR,		/* Something bad happened while processing */
+};
+
+enum {
+	BUFFER_UNUSED,
+	BUFFER_READY,
+	BUFFER_BUSY,
+	BUFFER_DONE,
+};
+
+/* raw camera data <- sbuf (urb transfer buf) */
+struct stv680_scratch {
+	unsigned char *data;
+	volatile int state;
+	int offset;
+	int length;
+};
+
+/* processed data for display ends up here, after bayer */
+struct stv680_frame {
+	unsigned char *data;	/* Frame buffer */
+	volatile int grabstate;	/* State of grabbing */
+	unsigned char *curline;
+	int curlinepix;
+	int curpix;
+};
+
+/* this is almost the video structure uvd_t, with extra parameters for stv */
+struct usb_stv {
+	struct video_device vdev;
+
+	struct usb_device *udev;
+
+	unsigned char bulk_in_endpointAddr;	/* __u8  the address of the bulk in endpoint */
+	char *camera_name;
+
+	unsigned int VideoMode;	/* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */
+	int SupportedModes;
+	int CIF;
+	int VGA;
+	int QVGA;
+	int cwidth;		/* camera width */
+	int cheight;		/* camera height */
+	int maxwidth;		/* max video width */
+	int maxheight;		/* max video height */
+	int vwidth;		/* current width for video window */
+	int vheight;		/* current height for video window */
+	unsigned long int rawbufsize;
+	unsigned long int maxframesize;	/* rawbufsize * 3 for RGB */
+
+	int origGain;
+	int origMode;		/* original camera mode */
+
+	struct semaphore lock;	/* to lock the structure */
+	int user;		/* user count for exclusive use */
+	int removed;		/* device disconnected */
+	int streaming;		/* Are we streaming video? */
+	char *fbuf;		/* Videodev buffer area */
+	struct urb *urb[STV680_NUMSBUF];	/* # of queued bulk transfers */
+	int curframe;		/* Current receiving frame */
+	struct stv680_frame frame[STV680_NUMFRAMES];	/* # frames supported by v4l part */
+	int readcount;
+	int framecount;
+	int error;
+	int dropped;
+	int scratch_next;
+	int scratch_use;
+	int scratch_overflow;
+	struct stv680_scratch scratch[STV680_NUMSCRATCH];	/* for decoders */
+	struct stv680_sbuf sbuf[STV680_NUMSBUF];
+
+	unsigned int brightness;
+	unsigned int chgbright;
+	unsigned int whiteness;
+	unsigned int colour;
+	unsigned int contrast;
+	unsigned int hue;
+	unsigned int palette;
+	unsigned int depth;	/* rgb24 in bits */
+
+	wait_queue_head_t wq;	/* Processes waiting */
+
+	struct proc_dir_entry *proc_entry;	/* /proc/stv680/videoX */
+	int nullpackets;
+};
+
+
+unsigned char red[256] = { 
+	0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 
+	18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, 
+	44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, 
+	71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, 
+	88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, 
+	102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 
+	114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, 
+	125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 
+	134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 
+	143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, 
+	152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, 
+	159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, 
+	167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, 
+	173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, 
+	180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, 
+	187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, 
+	192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, 
+	198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, 
+	204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, 
+	209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 
+	215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, 
+	220, 220, 221, 221 
+}; 
+
+unsigned char green[256] = {
+	0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 
+	21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, 
+	50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, 
+	79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, 
+	98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, 
+	114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 
+	127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 
+	139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 
+	150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, 
+	160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, 
+	169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, 
+	177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, 
+	186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 
+	193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 
+	201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 
+	208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 
+	214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 
+	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 
+	227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 
+	233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 
+	239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, 
+	245, 245, 246, 246 
+}; 
+
+unsigned char blue[256] = {
+	0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 
+	23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, 
+	55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, 
+	86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, 
+	107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, 
+	125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, 
+	139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, 
+	152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, 
+	165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 
+	176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, 
+	185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 
+	194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, 
+	204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, 
+	212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, 
+	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 
+	228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, 
+	235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, 
+	243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, 
+	249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, 
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 
+	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 
+	255, 255, 255, 255 
+}; 
diff -Nru a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/ultracam.c	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,706 @@
+/*
+ * USB NB Camera driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wrapper.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "usbvideo.h"
+
+#define	ULTRACAM_VENDOR_ID	0x0461
+#define	ULTRACAM_PRODUCT_ID	0x0813
+
+#define MAX_CAMERAS		4	/* How many devices we allow to connect */
+
+/*
+ * This structure lives in uvd_t->user field.
+ */
+typedef struct {
+	int initialized;	/* Had we already sent init sequence? */
+	int camera_model;	/* What type of IBM camera we got? */
+        int has_hdr;
+} ultracam_t;
+#define	ULTRACAM_T(uvd)	((ultracam_t *)((uvd)->user_data))
+
+static usbvideo_t *cams = NULL;
+
+static int debug = 0;
+
+static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
+
+static const int min_canvasWidth  = 8;
+static const int min_canvasHeight = 4;
+
+//static int lighting = 1; /* Medium */
+
+#define SHARPNESS_MIN	0
+#define SHARPNESS_MAX	6
+//static int sharpness = 4; /* Low noise, good details */
+
+#define FRAMERATE_MIN	0
+#define FRAMERATE_MAX	6
+static int framerate = -1;
+
+/*
+ * Here we define several initialization variables. They may
+ * be used to automatically set color, hue, brightness and
+ * contrast to desired values. This is particularly useful in
+ * case of webcams (which have no controls and no on-screen
+ * output) and also when a client V4L software is used that
+ * does not have some of those controls. In any case it's
+ * good to have startup values as options.
+ *
+ * These values are all in [0..255] range. This simplifies
+ * operation. Note that actual values of V4L variables may
+ * be scaled up (as much as << 8). User can see that only
+ * on overlay output, however, or through a V4L client.
+ */
+static int init_brightness = 128;
+static int init_contrast = 192;
+static int init_color = 128;
+static int init_hue = 128;
+static int hue_correction = 128;
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+MODULE_PARM(flags, "i");
+MODULE_PARM_DESC(flags,
+		"Bitfield: 0=VIDIOCSYNC, "
+		"1=B/W, "
+		"2=show hints, "
+		"3=show stats, "
+		"4=test pattern, "
+		"5=separate frames, "
+		"6=clean frames");
+MODULE_PARM(framerate, "i");
+MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
+MODULE_PARM(lighting, "i");
+MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
+MODULE_PARM(sharpness, "i");
+MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
+
+MODULE_PARM(init_brightness, "i");
+MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
+MODULE_PARM(init_contrast, "i");
+MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
+MODULE_PARM(init_color, "i");
+MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
+MODULE_PARM(init_hue, "i");
+MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
+MODULE_PARM(hue_correction, "i");
+MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
+
+/*
+ * ultracam_ProcessIsocData()
+ *
+ * Generic routine to parse the ring queue data. It employs either
+ * ultracam_find_header() or ultracam_parse_lines() to do most
+ * of work.
+ *
+ * 02-Nov-2000 First (mostly dummy) version.
+ * 06-Nov-2000 Rewrote to dump all data into frame.
+ */
+void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
+{
+	int n;
+
+	assert(uvd != NULL);
+	assert(frame != NULL);
+
+	/* Try to move data from queue into frame buffer */
+	n = RingQueue_GetLength(&uvd->dp);
+	if (n > 0) {
+		int m;
+		/* See how much spare we have left */
+		m = uvd->max_frame_size - frame->seqRead_Length;
+		if (n > m)
+			n = m;
+		/* Now move that much data into frame buffer */
+		RingQueue_Dequeue(
+			&uvd->dp,
+			frame->data + frame->seqRead_Length,
+			m);
+		frame->seqRead_Length += m;
+	}
+	/* See if we filled the frame */
+	if (frame->seqRead_Length >= uvd->max_frame_size) {
+		frame->frameState = FrameState_Done;
+		uvd->curframe = -1;
+		uvd->stats.frame_num++;
+	}
+}
+
+/*
+ * ultracam_veio()
+ *
+ * History:
+ * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
+ */
+static int ultracam_veio(
+	uvd_t *uvd,
+	unsigned char req,
+	unsigned short value,
+	unsigned short index,
+	int is_out)
+{
+	static const char proc[] = "ultracam_veio";
+	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
+	int i;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return 0;
+
+	if (!is_out) {
+		i = usb_control_msg(
+			uvd->dev,
+			usb_rcvctrlpipe(uvd->dev, 0),
+			req,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value,
+			index,
+			cp,
+			sizeof(cp),
+			HZ);
+#if 1
+		info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
+		       "(req=$%02x val=$%04x ind=$%04x)",
+		       cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
+		       req, value, index);
+#endif
+	} else {
+		i = usb_control_msg(
+			uvd->dev,
+			usb_sndctrlpipe(uvd->dev, 0),
+			req,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value,
+			index,
+			NULL,
+			0,
+			HZ);
+	}
+	if (i < 0) {
+		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
+		    proc, i);
+		uvd->last_error = i;
+	}
+	return i;
+}
+
+/*
+ * ultracam_calculate_fps()
+ */
+static int ultracam_calculate_fps(uvd_t *uvd)
+{
+	return 3 + framerate*4 + framerate/2;
+}
+
+/*
+ * ultracam_adjust_contrast()
+ */
+static void ultracam_adjust_contrast(uvd_t *uvd)
+{
+}
+
+/*
+ * ultracam_change_lighting_conditions()
+ */
+static void ultracam_change_lighting_conditions(uvd_t *uvd)
+{
+}
+
+/*
+ * ultracam_set_sharpness()
+ *
+ * Cameras model 1 have internal smoothing feature. It is controlled by value in
+ * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
+ * Recommended value is 4. Cameras model 2 do not have this feature at all.
+ */
+static void ultracam_set_sharpness(uvd_t *uvd)
+{
+}
+
+/*
+ * ultracam_set_brightness()
+ *
+ * This procedure changes brightness of the picture.
+ */
+static void ultracam_set_brightness(uvd_t *uvd)
+{
+}
+
+static void ultracam_set_hue(uvd_t *uvd)
+{
+}
+
+/*
+ * ultracam_adjust_picture()
+ *
+ * This procedure gets called from V4L interface to update picture settings.
+ * Here we change brightness and contrast.
+ */
+static void ultracam_adjust_picture(uvd_t *uvd)
+{
+	ultracam_adjust_contrast(uvd);
+	ultracam_set_brightness(uvd);
+	ultracam_set_hue(uvd);
+}
+
+/*
+ * ultracam_video_stop()
+ *
+ * This code tells camera to stop streaming. The interface remains
+ * configured and bandwidth - claimed.
+ */
+static void ultracam_video_stop(uvd_t *uvd)
+{
+}
+
+/*
+ * ultracam_reinit_iso()
+ *
+ * This procedure sends couple of commands to the camera and then
+ * resets the video pipe. This sequence was observed to reinit the
+ * camera or, at least, to initiate ISO data stream.
+ */
+static void ultracam_reinit_iso(uvd_t *uvd, int do_stop)
+{
+}
+
+static void ultracam_video_start(uvd_t *uvd)
+{
+	ultracam_change_lighting_conditions(uvd);
+	ultracam_set_sharpness(uvd);
+	ultracam_reinit_iso(uvd, 0);
+}
+
+static int ultracam_resetPipe(uvd_t *uvd)
+{
+	usb_clear_halt(uvd->dev, uvd->video_endp);
+	return 0;
+}
+
+static int ultracam_alternateSetting(uvd_t *uvd, int setting)
+{
+	static const char proc[] = "ultracam_alternateSetting";
+	int i;
+	i = usb_set_interface(uvd->dev, uvd->iface, setting);
+	if (i < 0) {
+		err("%s: usb_set_interface error", proc);
+		uvd->last_error = i;
+		return -EBUSY;
+	}
+	return 0;
+}
+
+/*
+ * Return negative code on failure, 0 on success.
+ */
+static int ultracam_setup_on_open(uvd_t *uvd)
+{
+	int setup_ok = 0; /* Success by default */
+	/* Send init sequence only once, it's large! */
+	if (!ULTRACAM_T(uvd)->initialized) {
+		ultracam_alternateSetting(uvd, 0x04);
+		ultracam_alternateSetting(uvd, 0x00);
+		ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1);
+		ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1);
+		ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
+		ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1);
+		ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1);
+		ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1);
+		ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1);
+		ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1);
+		ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1);
+		ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1);
+		ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1);
+		ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1);
+		ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1);
+		ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1);
+		ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1);
+		ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
+		ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
+		ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
+		ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
+		ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
+		ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
+		ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
+		ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
+		ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1);
+		ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1);
+		ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1);
+		ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1);
+		ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1);
+		ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1);
+		ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1);
+		ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1);
+		ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1);
+		ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1);
+		ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1);
+		ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1);
+		ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1);
+		ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1);
+		ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1);
+		ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1);
+		ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1);
+		ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1);
+		ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1);
+		ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1);
+		ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1);
+		ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1);
+		ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
+		ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1);
+		ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1);
+		ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
+		ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
+		ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0);
+		ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
+		ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
+		ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
+		ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
+		ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
+		ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
+		ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
+		ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
+		ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0);
+		ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1);
+		ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1);
+		ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1);
+		ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1);
+		ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1);
+		ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1);
+		ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1);
+		ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
+		ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1);
+		ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1);
+		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
+		ultracam_alternateSetting(uvd, 0x04);
+		ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
+		ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
+		ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1);
+		ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1);
+		ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1);
+		ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0);
+		ultracam_resetPipe(uvd);
+		ULTRACAM_T(uvd)->initialized = (setup_ok != 0);
+	}
+	return setup_ok;
+}
+
+static void ultracam_configure_video(uvd_t *uvd)
+{
+	if (uvd == NULL)
+		return;
+
+	RESTRICT_TO_RANGE(init_brightness, 0, 255);
+	RESTRICT_TO_RANGE(init_contrast, 0, 255);
+	RESTRICT_TO_RANGE(init_color, 0, 255);
+	RESTRICT_TO_RANGE(init_hue, 0, 255);
+	RESTRICT_TO_RANGE(hue_correction, 0, 255);
+
+	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
+	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
+
+	uvd->vpic.colour = init_color << 8;
+	uvd->vpic.hue = init_hue << 8;
+	uvd->vpic.brightness = init_brightness << 8;
+	uvd->vpic.contrast = init_contrast << 8;
+	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
+	uvd->vpic.depth = 24;
+	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
+
+	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
+	strcpy(uvd->vcap.name, "IBM Ultra Camera");
+	uvd->vcap.type = VID_TYPE_CAPTURE;
+	uvd->vcap.channels = 1;
+	uvd->vcap.audios = 0;
+	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
+	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
+	uvd->vcap.minwidth = min_canvasWidth;
+	uvd->vcap.minheight = min_canvasHeight;
+
+	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
+	uvd->vchan.flags = 0;
+	uvd->vchan.tuners = 0;
+	uvd->vchan.channel = 0;
+	uvd->vchan.type = VIDEO_TYPE_CAMERA;
+	strcpy(uvd->vchan.name, "Camera");
+}
+
+/*
+ * ultracam_probe()
+ *
+ * This procedure queries device descriptor and accepts the interface
+ * if it looks like our camera.
+ *
+ * History:
+ * 12-Nov-2000 Reworked to comply with new probe() signature.
+ * 23-Jan-2001 Added compatibility with 2.2.x kernels.
+ */
+static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid)
+{
+	uvd_t *uvd = NULL;
+	int i, nas;
+	int actInterface=-1, inactInterface=-1, maxPS=0;
+	unsigned char video_ep = 0;
+
+	if (debug >= 1)
+		info("ultracam_probe(%p,%u.)", dev, ifnum);
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1)
+		return NULL;
+
+	/* Is it an IBM camera? */
+	if ((dev->descriptor.idVendor != ULTRACAM_VENDOR_ID) ||
+	    (dev->descriptor.idProduct != ULTRACAM_PRODUCT_ID))
+		return NULL;
+
+	info("IBM Ultra camera found (rev. 0x%04x)", dev->descriptor.bcdDevice);
+
+	/* Validate found interface: must have one ISO endpoint */
+	nas = dev->actconfig->interface[ifnum].num_altsetting;
+	if (debug > 0)
+		info("Number of alternate settings=%d.", nas);
+	if (nas < 8) {
+		err("Too few alternate settings for this camera!");
+		return NULL;
+	}
+	/* Validate all alternate settings */
+	for (i=0; i < nas; i++) {
+		const struct usb_interface_descriptor *interface;
+		const struct usb_endpoint_descriptor *endpoint;
+
+		interface = &dev->actconfig->interface[ifnum].altsetting[i];
+		if (interface->bNumEndpoints != 1) {
+			err("Interface %d. has %u. endpoints!",
+			    ifnum, (unsigned)(interface->bNumEndpoints));
+			return NULL;
+		}
+		endpoint = &interface->endpoint[0];
+		if (video_ep == 0)
+			video_ep = endpoint->bEndpointAddress;
+		else if (video_ep != endpoint->bEndpointAddress) {
+			err("Alternate settings have different endpoint addresses!");
+			return NULL;
+		}
+		if ((endpoint->bmAttributes & 0x03) != 0x01) {
+			err("Interface %d. has non-ISO endpoint!", ifnum);
+			return NULL;
+		}
+		if ((endpoint->bEndpointAddress & 0x80) == 0) {
+			err("Interface %d. has ISO OUT endpoint!", ifnum);
+			return NULL;
+		}
+		if (endpoint->wMaxPacketSize == 0) {
+			if (inactInterface < 0)
+				inactInterface = i;
+			else {
+				err("More than one inactive alt. setting!");
+				return NULL;
+			}
+		} else {
+			if (actInterface < 0) {
+				actInterface = i;
+				maxPS = endpoint->wMaxPacketSize;
+				if (debug > 0)
+					info("Active setting=%d. maxPS=%d.", i, maxPS);
+			} else {
+				/* Got another active alt. setting */
+				if (maxPS < endpoint->wMaxPacketSize) {
+					/* This one is better! */
+					actInterface = i;
+					maxPS = endpoint->wMaxPacketSize;
+					if (debug > 0) {
+						info("Even better ctive setting=%d. maxPS=%d.",
+						     i, maxPS);
+					}
+				}
+			}
+		}
+	}
+	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
+		err("Failed to recognize the camera!");
+		return NULL;
+	}
+
+	/* Code below may sleep, need to lock module while we are here */
+	MOD_INC_USE_COUNT;
+	uvd = usbvideo_AllocateDevice(cams);
+	if (uvd != NULL) {
+		/* Here uvd is a fully allocated uvd_t object */
+		uvd->flags = flags;
+		uvd->debug = debug;
+		uvd->dev = dev;
+		uvd->iface = ifnum;
+		uvd->ifaceAltInactive = inactInterface;
+		uvd->ifaceAltActive = actInterface;
+		uvd->video_endp = video_ep;
+		uvd->iso_packet_len = maxPS;
+		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
+		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
+		uvd->canvas = VIDEOSIZE(640, 480);	/* FIXME */
+		uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/
+
+		/* Initialize ibmcam-specific data */
+		assert(ULTRACAM_T(uvd) != NULL);
+		ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */
+		ULTRACAM_T(uvd)->initialized = 0;
+
+		ultracam_configure_video(uvd);
+
+		i = usbvideo_RegisterVideoDevice(uvd);
+		if (i != 0) {
+			err("usbvideo_RegisterVideoDevice() failed.");
+			uvd = NULL;
+		}
+	}
+	MOD_DEC_USE_COUNT;
+	return uvd;
+}
+
+/*
+ * ultracam_init()
+ *
+ * This code is run to initialize the driver.
+ */
+static int __init ultracam_init(void)
+{
+	usbvideo_cb_t cbTbl;
+	memset(&cbTbl, 0, sizeof(cbTbl));
+	cbTbl.probe = ultracam_probe;
+	cbTbl.setupOnOpen = ultracam_setup_on_open;
+	cbTbl.videoStart = ultracam_video_start;
+	cbTbl.videoStop = ultracam_video_stop;
+	cbTbl.processData = ultracam_ProcessIsocData;
+	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
+	cbTbl.adjustPicture = ultracam_adjust_picture;
+	cbTbl.getFPS = ultracam_calculate_fps;
+	return usbvideo_register(
+		&cams,
+		MAX_CAMERAS,
+		sizeof(ultracam_t),
+		"ultracam",
+		&cbTbl,
+		THIS_MODULE);
+}
+
+static void __exit ultracam_cleanup(void)
+{
+	usbvideo_Deregister(&cams);
+}
+
+#if defined(usb_device_id_ver)
+
+static __devinitdata struct usb_device_id id_table[] = {
+	{ USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
+	{ }  /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+
+#endif /* defined(usb_device_id_ver) */
+MODULE_LICENSE("GPL");
+
+module_init(ultracam_init);
+module_exit(ultracam_cleanup);
diff -Nru a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/usbvideo.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,2402 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#define	__NO_VERSION__		/* Temporary: usbvideo is not a module yet */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+
+#include "usbvideo.h"
+
+#if defined(MAP_NR)
+#define	virt_to_page(v)	MAP_NR(v)	/* Kernels 2.2.x */
+#endif
+
+static int video_nr = -1;
+MODULE_PARM(video_nr, "i");
+
+/*
+ * Local prototypes.
+ */
+#if USES_PROC_FS
+static void usbvideo_procfs_level1_create(usbvideo_t *ut);
+static void usbvideo_procfs_level1_destroy(usbvideo_t *ut);
+static void usbvideo_procfs_level2_create(uvd_t *uvd);
+static void usbvideo_procfs_level2_destroy(uvd_t *uvd);
+static int usbvideo_default_procfs_read_proc(
+	char *page, char **start, off_t off, int count,
+	int *eof, void *data);
+static int usbvideo_default_procfs_write_proc(
+	struct file *file, const char *buffer, 
+	unsigned long count, void *data);
+#endif
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+/*
+ * Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+unsigned long usbvideo_kvirt_to_pa(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+	return ret;
+}
+
+void *usbvideo_rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr = (unsigned long) mem;
+	while (size > 0) {
+		mem_map_reserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	return mem;
+}
+
+void usbvideo_rvfree(void *mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (!mem)
+		return;
+
+	adr = (unsigned long) mem;
+	while ((long) size > 0) {
+		mem_map_unreserve(vmalloc_to_page((void *)adr));
+		adr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(mem);
+}
+
+void RingQueue_Initialize(RingQueue_t *rq)
+{
+	assert(rq != NULL);
+	init_waitqueue_head(&rq->wqh);
+}
+
+void RingQueue_Allocate(RingQueue_t *rq, int rqLen)
+{
+	assert(rq != NULL);
+	assert(rqLen > 0);
+	rq->length = rqLen;
+	rq->queue = usbvideo_rvmalloc(rq->length);
+	assert(rq->queue != NULL);
+}
+
+int RingQueue_IsAllocated(const RingQueue_t *rq)
+{
+	if (rq == NULL)
+		return 0;
+	return (rq->queue != NULL) && (rq->length > 0);
+}
+
+void RingQueue_Free(RingQueue_t *rq)
+{
+	assert(rq != NULL);
+	if (RingQueue_IsAllocated(rq)) {
+		usbvideo_rvfree(rq->queue, rq->length);
+		rq->queue = NULL;
+		rq->length = 0;
+	}
+}
+
+int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len)
+{
+	int i;
+	assert(rq != NULL);
+	assert(dst != NULL);
+	for (i=0; i < len; i++) {
+		dst[i] = rq->queue[rq->ri];
+		RING_QUEUE_DEQUEUE_BYTES(rq,1);
+	}
+	return len;
+}
+
+int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n)
+{
+	int enqueued = 0;
+
+	assert(rq != NULL);
+	assert(cdata != NULL);
+	assert(rq->length > 0);
+	while (n > 0) {
+		int m, q_avail;
+
+		/* Calculate the largest chunk that fits the tail of the ring */
+		q_avail = rq->length - rq->wi;
+		if (q_avail <= 0) {
+			rq->wi = 0;
+			q_avail = rq->length;
+		}
+		m = n;
+		assert(q_avail > 0);
+		if (m > q_avail)
+			m = q_avail;
+
+		memmove(rq->queue + rq->wi, cdata, m);
+		RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
+		cdata += m;
+		enqueued += m;
+		n -= m;
+	}
+	return enqueued;
+}
+
+int RingQueue_GetLength(const RingQueue_t *rq)
+{
+	int ri, wi;
+
+	assert(rq != NULL);
+
+	ri = rq->ri;
+	wi = rq->wi;
+	if (ri == wi)
+		return 0;
+	else if (ri < wi)
+		return wi - ri;
+	else
+		return wi + (rq->length - ri);
+}
+
+void RingQueue_InterruptibleSleepOn(RingQueue_t *rq)
+{
+	assert(rq != NULL);
+	interruptible_sleep_on(&rq->wqh);
+}
+
+void RingQueue_WakeUpInterruptible(RingQueue_t *rq)
+{
+	assert(rq != NULL);
+	if (waitqueue_active(&rq->wqh))
+		wake_up_interruptible(&rq->wqh);
+}
+
+/*
+ * usbvideo_VideosizeToString()
+ *
+ * This procedure converts given videosize value to readable string.
+ *
+ * History:
+ * 07-Aug-2000 Created.
+ * 19-Oct-2000 Reworked for usbvideo module.
+ */
+void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs)
+{
+	char tmp[40];
+	int n;
+
+	n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs));
+	assert(n < sizeof(tmp));
+	if ((buf == NULL) || (bufLen < n))
+		err("usbvideo_VideosizeToString: buffer is too small.");
+	else
+		memmove(buf, tmp, n);
+}
+
+/*
+ * usbvideo_OverlayChar()
+ *
+ * History:
+ * 01-Feb-2000 Created.
+ */
+void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame,
+			  int x, int y, int ch)
+{
+	static const unsigned short digits[16] = {
+		0xF6DE, /* 0 */
+		0x2492, /* 1 */
+		0xE7CE, /* 2 */
+		0xE79E, /* 3 */
+		0xB792, /* 4 */
+		0xF39E, /* 5 */
+		0xF3DE, /* 6 */
+		0xF492, /* 7 */
+		0xF7DE, /* 8 */
+		0xF79E, /* 9 */
+		0x77DA, /* a */
+		0xD75C, /* b */
+		0xF24E, /* c */
+		0xD6DC, /* d */
+		0xF34E, /* e */
+		0xF348  /* f */
+	};
+	unsigned short digit;
+	int ix, iy;
+
+	if ((uvd == NULL) || (frame == NULL))
+		return;
+
+	if (ch >= '0' && ch <= '9')
+		ch -= '0';
+	else if (ch >= 'A' && ch <= 'F')
+		ch = 10 + (ch - 'A');
+	else if (ch >= 'a' && ch <= 'f')
+		ch = 10 + (ch - 'a');
+	else
+		return;
+	digit = digits[ch];
+
+	for (iy=0; iy < 5; iy++) {
+		for (ix=0; ix < 3; ix++) {
+			if (digit & 0x8000) {
+				if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {
+/* TODO */				RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);
+				}
+			}
+			digit = digit << 1;
+		}
+	}
+}
+
+/*
+ * usbvideo_OverlayString()
+ *
+ * History:
+ * 01-Feb-2000 Created.
+ */
+void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame,
+			    int x, int y, const char *str)
+{
+	while (*str) {
+		usbvideo_OverlayChar(uvd, frame, x, y, *str);
+		str++;
+		x += 4; /* 3 pixels character + 1 space */
+	}
+}
+
+/*
+ * usbvideo_OverlayStats()
+ *
+ * Overlays important debugging information.
+ *
+ * History:
+ * 01-Feb-2000 Created.
+ */
+void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame)
+{
+	const int y_diff = 8;
+	char tmp[16];
+	int x = 10, y=10;
+	long i, j, barLength;
+	const int qi_x1 = 60, qi_y1 = 10;
+	const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;
+
+	/* Call the user callback, see if we may proceed after that */
+	if (VALID_CALLBACK(uvd, overlayHook)) {
+		if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0)
+			return;
+	}
+
+	/*
+	 * We draw a (mostly) hollow rectangle with qi_xxx coordinates.
+	 * Left edge symbolizes the queue index 0; right edge symbolizes
+	 * the full capacity of the queue.
+	 */
+	barLength = qi_x2 - qi_x1 - 2;
+	if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) {
+/* TODO */	long u_lo, u_hi, q_used;
+		long m_ri, m_wi, m_lo, m_hi;
+
+		/*
+		 * Determine fill zones (used areas of the queue):
+		 * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length
+		 *
+		 * if u_lo < 0 then there is no first filler.
+		 */
+
+		q_used = RingQueue_GetLength(&uvd->dp);
+		if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
+			u_hi = uvd->dp.length;
+			u_lo = (q_used + uvd->dp.ri) % uvd->dp.length;
+		} else {
+			u_hi = (q_used + uvd->dp.ri);
+			u_lo = -1;
+		}
+
+		/* Convert byte indices into screen units */
+		m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length);
+		m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length);
+		m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;
+		m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);
+
+		for (j=qi_y1; j < (qi_y1 + qi_h); j++) {
+			for (i=qi_x1; i < qi_x2; i++) {
+				/* Draw border lines */
+				if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||
+				    (i == qi_x1) || (i == (qi_x2 - 1))) {
+					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF);
+					continue;
+				}
+				/* For all other points the Y coordinate does not matter */
+				if ((i >= m_ri) && (i <= (m_ri + 3))) {
+					RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);
+				} else if ((i >= m_wi) && (i <= (m_wi + 3))) {
+					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);
+				} else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
+					RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);
+			}
+		}
+	}
+
+	sprintf(tmp, "%8lx", uvd->stats.frame_num);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8lx", uvd->stats.urb_count);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8lx", uvd->stats.urb_length);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8lx", uvd->stats.data_count);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8lx", uvd->stats.header_count);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8lx", uvd->stats.iso_skip_count);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8lx", uvd->stats.iso_err_count);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8x", uvd->vpic.colour);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8x", uvd->vpic.hue);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8x", uvd->vpic.brightness >> 8);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8x", uvd->vpic.contrast >> 12);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+
+	sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8);
+	usbvideo_OverlayString(uvd, frame, x, y, tmp);
+	y += y_diff;
+}
+
+/*
+ * usbvideo_ReportStatistics()
+ *
+ * This procedure prints packet and transfer statistics.
+ *
+ * History:
+ * 14-Jan-2000 Corrected default multiplier.
+ */
+void usbvideo_ReportStatistics(const uvd_t *uvd)
+{
+	if ((uvd != NULL) && (uvd->stats.urb_count > 0)) {
+		unsigned long allPackets, badPackets, goodPackets, percent;
+		allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES;
+		badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count;
+		goodPackets = allPackets - badPackets;
+		/* Calculate percentage wisely, remember integer limits */
+		assert(allPackets != 0);
+		if (goodPackets < (((unsigned long)-1)/100))
+			percent = (100 * goodPackets) / allPackets;
+		else
+			percent = goodPackets / (allPackets / 100);
+		info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%",
+		     allPackets, badPackets, percent);
+		if (uvd->iso_packet_len > 0) {
+			unsigned long allBytes, xferBytes;
+			char multiplier = ' ';
+			allBytes = allPackets * uvd->iso_packet_len;
+			xferBytes = uvd->stats.data_count;
+			assert(allBytes != 0);
+			if (xferBytes < (((unsigned long)-1)/100))
+				percent = (100 * xferBytes) / allBytes;
+			else
+				percent = xferBytes / (allBytes / 100);
+			/* Scale xferBytes for easy reading */
+			if (xferBytes > 10*1024) {
+				xferBytes /= 1024;
+				multiplier = 'K';
+				if (xferBytes > 10*1024) {
+					xferBytes /= 1024;
+					multiplier = 'M';
+					if (xferBytes > 10*1024) {
+						xferBytes /= 1024;
+						multiplier = 'G';
+						if (xferBytes > 10*1024) {
+							xferBytes /= 1024;
+							multiplier = 'T';
+						}
+					}
+				}
+			}
+			info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%",
+			     xferBytes, multiplier, percent);
+		}
+	}
+}
+
+/*
+ * usbvideo_DrawLine()
+ *
+ * A standard implementation of Bresenham's line drawing algorithm.
+ * This procedure is provided primarily for debugging or demo
+ * purposes.
+ */
+void usbvideo_DrawLine(
+	usbvideo_frame_t *frame,
+	int x1, int y1,
+	int x2, int y2,
+	unsigned char cr, unsigned char cg, unsigned char cb)
+{
+	int i, dx, dy, np, d;
+	int dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2;
+
+	if ((dx = x2 - x1) < 0)
+		dx = -dx;
+	if ((dy = y2 - y1) < 0)
+		dy = -dy;
+	if (dx >= dy) {
+		np = dx + 1;
+		d = (2 * dy) - dx;
+		dinc1 = dy << 1;
+		dinc2 = (dy - dx) << 1;
+		xinc1 = 1;
+		xinc2 = 1;
+		yinc1 = 0;
+		yinc2 = 1;
+	} else {
+		np = dy + 1;
+		d = (2 * dx) - dy;
+		dinc1 = dx << 1;
+		dinc2 = (dx - dy) << 1;
+		xinc1 = 0;
+		xinc2 = 1;
+		yinc1 = 1;
+		yinc2 = 1;
+	}
+	/* Make sure x and y move in the right directions */
+	if (x1 > x2) {
+		xinc1 = -xinc1;
+		xinc2 = -xinc2;
+	}
+	if (y1 > y2) {
+		yinc1 = -yinc1;
+		yinc2 = -yinc2;
+	}
+	for (i=0, x=x1, y=y1; i < np; i++) {
+		if (frame->palette == VIDEO_PALETTE_RGB24) {
+/* TODO */		RGB24_PUTPIXEL(frame, x, y, cr, cg, cb);
+		}
+		if (d < 0) {
+			d += dinc1;
+			x += xinc1;
+			y += yinc1;
+		} else {
+			d += dinc2;
+			x += xinc2;
+			y += yinc2;
+		}
+	}
+}
+
+/*
+ * usbvideo_TestPattern()
+ *
+ * Procedure forms a test pattern (yellow grid on blue background).
+ *
+ * Parameters:
+ * fullframe: if TRUE then entire frame is filled, otherwise the procedure
+ *	      continues from the current scanline.
+ * pmode      0: fill the frame with solid blue color (like on VCR or TV)
+ *	      1: Draw a colored grid
+ *
+ * History:
+ * 01-Feb-2000 Created.
+ */
+void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode)
+{
+	static const char proc[] = "usbvideo_TestPattern";
+	usbvideo_frame_t *frame;
+	int num_cell = 0;
+	int scan_length = 0;
+	static int num_pass = 0;
+
+	if (uvd == NULL) {
+		err("%s: uvd == NULL", proc);
+		return;
+	}
+	if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
+		err("%s: uvd->curframe=%d.", proc, uvd->curframe);
+		return;
+	}
+
+	/* Grab the current frame */
+	frame = &uvd->frame[uvd->curframe];
+
+	/* Optionally start at the beginning */
+	if (fullframe) {
+		frame->curline = 0;
+		frame->seqRead_Length = 0;
+	}
+#if 0
+	{	/* For debugging purposes only */
+		char tmp[20];
+		usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
+		info("testpattern: frame=%s", tmp);
+	}
+#endif
+	/* Form every scan line */
+	for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) {
+		int i;
+		unsigned char *f = frame->data +
+			(VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);
+		for (i=0; i < VIDEOSIZE_X(frame->request); i++) {
+			unsigned char cb=0x80;
+			unsigned char cg = 0;
+			unsigned char cr = 0;
+
+			if (pmode == 1) {
+				if (frame->curline % 32 == 0)
+					cb = 0, cg = cr = 0xFF;
+				else if (i % 32 == 0) {
+					if (frame->curline % 32 == 1)
+						num_cell++;
+					cb = 0, cg = cr = 0xFF;
+				} else {
+					cb = ((num_cell*7) + num_pass) & 0xFF;
+					cg = ((num_cell*5) + num_pass*2) & 0xFF;
+					cr = ((num_cell*3) + num_pass*3) & 0xFF;
+				}
+			} else {
+				/* Just the blue screen */
+			}
+				
+			*f++ = cb;
+			*f++ = cg;
+			*f++ = cr;
+			scan_length += 3;
+		}
+	}
+
+	frame->frameState = FrameState_Done;
+	frame->seqRead_Length += scan_length;
+	++num_pass;
+
+	/* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */
+	usbvideo_OverlayStats(uvd, frame);
+}
+
+/*
+ * usbvideo_HexDump()
+ *
+ * A debugging tool. Prints hex dumps.
+ *
+ * History:
+ * 29-Jul-2000 Added printing of offsets.
+ */
+void usbvideo_HexDump(const unsigned char *data, int len)
+{
+	const int bytes_per_line = 32;
+	char tmp[128]; /* 32*3 + 5 */
+	int i, k;
+
+	for (i=k=0; len > 0; i++, len--) {
+		if (i > 0 && ((i % bytes_per_line) == 0)) {
+			printk("%s\n", tmp);
+			k=0;
+		}
+		if ((i % bytes_per_line) == 0)
+			k += sprintf(&tmp[k], "%04x: ", i);
+		k += sprintf(&tmp[k], "%02x ", data[i]);
+	}
+	if (k > 0)
+		printk("%s\n", tmp);
+}
+
+/* Debugging aid */
+void usbvideo_SayAndWait(const char *what)
+{
+	wait_queue_head_t wq;
+	init_waitqueue_head(&wq);
+	info("Say: %s", what);
+	interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */
+}
+
+/* ******************************************************************** */
+
+static void usbvideo_ClientIncModCount(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_ClientIncModCount";
+	if (uvd == NULL) {
+		err("%s: uvd == NULL", proc);
+		return;
+	}
+	if (uvd->handle == NULL) {
+		err("%s: uvd->handle == NULL", proc);
+		return;
+	}
+	if (uvd->handle->md_module == NULL) {
+		err("%s: uvd->handle->md_module == NULL", proc);
+		return;
+	}
+	__MOD_INC_USE_COUNT(uvd->handle->md_module);
+}
+
+static void usbvideo_ClientDecModCount(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_ClientDecModCount";
+	if (uvd == NULL) {
+		err("%s: uvd == NULL", proc);
+		return;
+	}
+	if (uvd->handle == NULL) {
+		err("%s: uvd->handle == NULL", proc);
+		return;
+	}
+	if (uvd->handle->md_module == NULL) {
+		err("%s: uvd->handle->md_module == NULL", proc);
+		return;
+	}
+	__MOD_DEC_USE_COUNT(uvd->handle->md_module);
+}
+
+int usbvideo_register(
+	usbvideo_t **pCams,
+	const int num_cams,
+	const int num_extra,
+	const char *driverName,
+	const usbvideo_cb_t *cbTbl,
+	struct module *md )
+{
+	static const char proc[] = "usbvideo_register";
+	usbvideo_t *cams;
+	int i, base_size;
+
+	/* Check parameters for sanity */
+	if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
+		err("%s: Illegal call", proc);
+		return -EINVAL;
+	}
+
+	/* Check registration callback - must be set! */
+	if (cbTbl->probe == NULL) {
+		err("%s: probe() is required!", proc);
+		return -EINVAL;
+	}
+
+	base_size = num_cams * sizeof(uvd_t) + sizeof(usbvideo_t);
+	cams = (usbvideo_t *) kmalloc(base_size, GFP_KERNEL);
+	if (cams == NULL) {
+		err("Failed to allocate %d. bytes for usbvideo_t", base_size);
+		return -ENOMEM;
+	}
+	dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
+	    proc, cams, base_size, num_cams);
+	memset(cams, 0, base_size);
+
+	/* Copy callbacks, apply defaults for those that are not set */
+	memmove(&cams->cb, cbTbl, sizeof(cams->cb));
+	if (cams->cb.getFrame == NULL)
+		cams->cb.getFrame = usbvideo_GetFrame;
+	if (cams->cb.disconnect == NULL)
+		cams->cb.disconnect = usbvideo_Disconnect;
+	if (cams->cb.startDataPump == NULL)
+		cams->cb.startDataPump = usbvideo_StartDataPump;
+	if (cams->cb.stopDataPump == NULL)
+		cams->cb.stopDataPump = usbvideo_StopDataPump;
+#if USES_PROC_FS
+	/*
+	 * If both /proc fs callbacks are NULL then we assume that the driver
+	 * does not need procfs services at all. Leave them NULL.
+	 */
+	cams->uses_procfs = (cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL);
+	if (cams->uses_procfs) {
+		if (cams->cb.procfs_read == NULL)
+			cams->cb.procfs_read = usbvideo_default_procfs_read_proc;
+		if (cams->cb.procfs_write == NULL)
+			cams->cb.procfs_write = usbvideo_default_procfs_write_proc;
+	}
+#else /* !USES_PROC_FS */
+	/* Report a warning so that user knows why there is no /proc entries */
+	if ((cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL)) {
+		dbg("%s: /proc fs support requested but not configured!", proc);
+	}
+#endif
+	cams->num_cameras = num_cams;
+	cams->cam = (uvd_t *) &cams[1];
+	cams->md_module = md;
+	if (cams->md_module == NULL)
+		warn("%s: module == NULL!", proc);
+	init_MUTEX(&cams->lock);	/* to 1 == available */
+
+	for (i = 0; i < num_cams; i++) {
+		uvd_t *up = &cams->cam[i];
+
+		up->handle = cams;
+
+		/* Allocate user_data separately because of kmalloc's limits */
+		if (num_extra > 0) {
+			up->user_size = num_cams * num_extra;
+			up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL);
+			if (up->user_data == NULL) {
+				up->user_size = 0;
+				err("%s: Failed to allocate user_data (%d. bytes)",
+				    proc, up->user_size);
+				return -ENOMEM;
+			}
+			dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
+			     proc, i, up->user_data, up->user_size);
+		}
+	}
+
+	/*
+	 * Register ourselves with USB stack.
+	 */
+	strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown");
+	cams->usbdrv.name = cams->drvName;
+	cams->usbdrv.probe = cams->cb.probe;
+	cams->usbdrv.disconnect = cams->cb.disconnect;
+
+#if USES_PROC_FS
+	if (cams->uses_procfs) {
+		dbg("%s: Creating /proc filesystem entries.", proc);
+		usbvideo_procfs_level1_create(cams);
+	}
+#endif
+
+	/*
+	 * Update global handle to usbvideo. This is very important
+	 * because probe() can be called before usb_register() returns.
+	 * If the handle is not yet updated then the probe() will fail.
+	 */
+	*pCams = cams;
+	usb_register(&cams->usbdrv);
+
+	return 0;
+}
+
+/*
+ * usbvideo_Deregister()
+ *
+ * Procedure frees all usbvideo and user data structures. Be warned that
+ * if you had some dynamically allocated components in ->user field then
+ * you should free them before calling here.
+ */
+void usbvideo_Deregister(usbvideo_t **pCams)
+{
+	static const char proc[] = "usbvideo_deregister";
+	usbvideo_t *cams;
+	int i;
+
+	if (pCams == NULL) {
+		err("%s: pCams == NULL", proc);
+		return;
+	}
+	cams = *pCams;
+	if (cams == NULL) {
+		err("%s: cams == NULL", proc);
+		return;
+	}
+
+#if USES_PROC_FS
+	if (cams->uses_procfs) {
+		dbg("%s: Deregistering filesystem entries.", proc);
+		usbvideo_procfs_level1_destroy(cams);
+	}
+#endif
+
+	dbg("%s: Deregistering %s driver.", proc, cams->drvName);
+	usb_deregister(&cams->usbdrv);
+
+	dbg("%s: Deallocating cams=$%p (%d. cameras)", proc, cams, cams->num_cameras);
+	for (i=0; i < cams->num_cameras; i++) {
+		uvd_t *up = &cams->cam[i];
+		int warning = 0;
+
+		if (up->user_data != NULL) {
+			if (up->user_size <= 0)
+				++warning;
+		} else {
+			if (up->user_size > 0)
+				++warning;
+		}
+		if (warning) {
+			err("%s: Warning: user_data=$%p user_size=%d.",
+			    proc, up->user_data, up->user_size);
+		} else {
+			dbg("%s: Freeing %d. $%p->user_data=$%p",
+			    proc, i, up, up->user_data);
+			kfree(up->user_data);
+		}
+	}
+	/* Whole array was allocated in one chunk */
+	dbg("%s: Freed %d uvd_t structures",
+	    proc, cams->num_cameras);
+	kfree(cams);
+	*pCams = NULL;
+}
+
+/*
+ * usbvideo_Disconnect()
+ *
+ * This procedure stops all driver activity. Deallocation of
+ * the interface-private structure (pointed by 'ptr') is done now
+ * (if we don't have any open files) or later, when those files
+ * are closed. After that driver should be removable.
+ *
+ * This code handles surprise removal. The uvd->user is a counter which
+ * increments on open() and decrements on close(). If we see here that
+ * this counter is not 0 then we have a client who still has us opened.
+ * We set uvd->remove_pending flag as early as possible, and after that
+ * all access to the camera will gracefully fail. These failures should
+ * prompt client to (eventually) close the video device, and then - in
+ * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter.
+ *
+ * History:
+ * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone.
+ * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close()
+ * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
+ * 19-Oct-2000 Moved to usbvideo module.
+ */
+void usbvideo_Disconnect(struct usb_device *dev, void *ptr)
+{
+	static const char proc[] = "usbvideo_Disconnect";
+	uvd_t *uvd = (uvd_t *) ptr;
+	int i;
+
+	if ((dev == NULL) || (uvd == NULL)) {
+		err("%s($%p,$%p): Illegal call.", proc, dev, ptr);
+		return;
+	}
+	usbvideo_ClientIncModCount(uvd);
+	if (uvd->debug > 0)
+		info("%s(%p,%p.)", proc, dev, ptr);
+
+	down(&uvd->lock);
+	uvd->remove_pending = 1; /* Now all ISO data will be ignored */
+
+	/* At this time we ask to cancel outstanding URBs */
+	GET_CALLBACK(uvd, stopDataPump)(uvd);
+
+	for (i=0; i < USBVIDEO_NUMSBUF; i++)
+		usb_free_urb(uvd->sbuf[i].urb);
+
+	usb_dec_dev_use(uvd->dev);
+	uvd->dev = NULL;    	    /* USB device is no more */
+
+	video_unregister_device(&uvd->vdev);
+	if (uvd->debug > 0)
+		info("%s: Video unregistered.", proc);
+
+	if (uvd->user)
+		info("%s: In use, disconnect pending.", proc);
+	else
+		usbvideo_CameraRelease(uvd);
+	up(&uvd->lock);
+	info("USB camera disconnected.");
+
+	usbvideo_ClientDecModCount(uvd);
+}
+
+/*
+ * usbvideo_CameraRelease()
+ *
+ * This code does final release of uvd_t. This happens
+ * after the device is disconnected -and- all clients
+ * closed their files.
+ *
+ * History:
+ * 27-Jan-2000 Created.
+ */
+void usbvideo_CameraRelease(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_CameraRelease";
+	if (uvd == NULL) {
+		err("%s: Illegal call", proc);
+		return;
+	}
+
+#if USES_PROC_FS
+	assert(uvd->handle != NULL);
+	if (uvd->handle->uses_procfs) {
+		dbg("%s: Removing /proc/%s/ filesystem entries.", proc, uvd->handle->drvName);
+		usbvideo_procfs_level2_destroy(uvd);
+	}
+#endif
+
+	RingQueue_Free(&uvd->dp);
+	if (VALID_CALLBACK(uvd, userFree))
+		GET_CALLBACK(uvd, userFree)(uvd);
+	uvd->uvd_used = 0;	/* This is atomic, no need to take mutex */
+}
+
+/*
+ * usbvideo_find_struct()
+ *
+ * This code searches the array of preallocated (static) structures
+ * and returns index of the first one that isn't in use. Returns -1
+ * if there are no free structures.
+ *
+ * History:
+ * 27-Jan-2000 Created.
+ */
+static int usbvideo_find_struct(usbvideo_t *cams)
+{
+	int u, rv = -1;
+
+	if (cams == NULL) {
+		err("No usbvideo_t handle?");
+		return -1;
+	}
+	down(&cams->lock);
+	for (u = 0; u < cams->num_cameras; u++) {
+		uvd_t *uvd = &cams->cam[u];
+		if (!uvd->uvd_used) /* This one is free */
+		{
+			uvd->uvd_used = 1;	/* In use now */
+			init_MUTEX(&uvd->lock);	/* to 1 == available */
+			uvd->dev = NULL;
+			rv = u;
+			break;
+		}
+	}
+	up(&cams->lock);
+	return rv;
+}
+
+static struct file_operations usbvideo_fops = {
+	owner:	  THIS_MODULE,
+	open:     usbvideo_v4l_open,
+	release:  usbvideo_v4l_close,
+	read:     usbvideo_v4l_read,
+	mmap:     usbvideo_v4l_mmap,
+	ioctl:    usbvideo_v4l_ioctl,
+	llseek:   no_llseek,
+};
+static struct video_device usbvideo_template = {
+	owner:	      THIS_MODULE,
+	type:         VID_TYPE_CAPTURE,
+	hardware:     VID_HARDWARE_CPIA,
+	fops:         &usbvideo_fops,
+};
+
+uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams)
+{
+	int i, devnum;
+	uvd_t *uvd = NULL;
+
+	if (cams == NULL) {
+		err("No usbvideo_t handle?");
+		return NULL;
+	}
+
+	devnum = usbvideo_find_struct(cams);
+	if (devnum == -1) {
+		err("IBM USB camera driver: Too many devices!");
+		return NULL;
+	}
+	uvd = &cams->cam[devnum];
+	dbg("Device entry #%d. at $%p", devnum, uvd);
+
+	/* Not relying upon caller we increase module counter ourselves */
+	usbvideo_ClientIncModCount(uvd);
+
+	down(&uvd->lock);
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
+		if (uvd->sbuf[i].urb == NULL) {
+			err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);
+			uvd->uvd_used = 0;
+			uvd = NULL;
+			goto allocate_done;
+		}
+	}
+	uvd->user=0;
+	uvd->remove_pending = 0;
+	uvd->last_error = 0;
+	RingQueue_Initialize(&uvd->dp);
+
+	/* Initialize video device structure */
+	uvd->vdev = usbvideo_template;
+	sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName);
+	/*
+	 * The client is free to overwrite those because we
+	 * return control to the client's probe function right now.
+	 */
+allocate_done:
+	up (&uvd->lock);
+	usbvideo_ClientDecModCount(uvd);
+	return uvd;
+}
+
+int usbvideo_RegisterVideoDevice(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_RegisterVideoDevice";
+	char tmp1[20], tmp2[20];	/* Buffers for printing */
+
+	if (uvd == NULL) {
+		err("%s: Illegal call.", proc);
+		return -EINVAL;
+	}
+	if (uvd->video_endp == 0) {
+		info("%s: No video endpoint specified; data pump disabled.", proc);
+	}
+	if (uvd->paletteBits == 0) {
+		err("%s: No palettes specified!", proc);
+		return -EINVAL;
+	}
+	if (uvd->defaultPalette == 0) {
+		info("%s: No default palette!", proc);
+	}
+
+	uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
+		VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL;
+	usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize);
+	usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
+
+	if (uvd->debug > 0) {
+		info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
+		     proc, uvd->iface, uvd->video_endp, uvd->paletteBits);
+	}
+	if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+		err("%s: video_register_device failed", proc);
+		return -EPIPE;
+	}
+	if (uvd->debug > 1) {
+		info("%s: video_register_device() successful", proc);
+	}
+	if (uvd->dev == NULL) {
+		err("%s: uvd->dev == NULL", proc);
+		return -EINVAL;
+	}
+
+	info("%s on /dev/video%d: canvas=%s videosize=%s",
+	     (uvd->handle != NULL) ? uvd->handle->drvName : "???",
+	     uvd->vdev.minor, tmp2, tmp1);
+
+#if USES_PROC_FS
+	assert(uvd->handle != NULL);
+	if (uvd->handle->uses_procfs) {
+		if (uvd->debug > 0) {
+			info("%s: Creating /proc/video/%s/ filesystem entries.",
+			     proc, uvd->handle->drvName);
+		}
+		usbvideo_procfs_level2_create(uvd);
+	}
+#endif
+
+	usb_inc_dev_use(uvd->dev);
+	return 0;
+}
+
+/* ******************************************************************** */
+
+int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	uvd_t *uvd = file->private_data;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long page, pos;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return -EFAULT;
+
+	if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+		return -EINVAL;
+
+	pos = (unsigned long) uvd->fbuf;
+	while (size > 0) {
+		page = usbvideo_kvirt_to_pa(pos);
+		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * usbvideo_v4l_open()
+ *
+ * This is part of Video 4 Linux API. The driver can be opened by one
+ * client only (checks internal counter 'uvdser'). The procedure
+ * then allocates buffers needed for video processing.
+ *
+ * History:
+ * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the
+ *             camera is also initialized here (once per connect), at
+ *             expense of V4L client (it waits on open() call).
+ * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
+ * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
+ */
+int usbvideo_v4l_open(struct inode *inode, struct file *file)
+{
+	static const char proc[] = "usbvideo_v4l_open";
+	struct video_device *dev = video_devdata(file);
+	uvd_t *uvd = (uvd_t *) dev;
+	const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len;
+	int i, errCode = 0;
+
+	if (uvd->debug > 1)
+		info("%s($%p", proc, dev);
+
+	usbvideo_ClientIncModCount(uvd);
+	down(&uvd->lock);
+
+	if (uvd->user) {
+		err("%s: Someone tried to open an already opened device!", proc);
+		errCode = -EBUSY;
+	} else {
+		/* Clear statistics */
+		memset(&uvd->stats, 0, sizeof(uvd->stats));
+
+		/* Clean pointers so we know if we allocated something */
+		for (i=0; i < USBVIDEO_NUMSBUF; i++)
+			uvd->sbuf[i].data = NULL;
+
+		/* Allocate memory for the frame buffers */
+		uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
+		uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
+		RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */
+		if ((uvd->fbuf == NULL) ||
+		    (!RingQueue_IsAllocated(&uvd->dp))) {
+			err("%s: Failed to allocate fbuf or dp", proc);
+			errCode = -ENOMEM;
+		} else {
+			/* Allocate all buffers */
+			for (i=0; i < USBVIDEO_NUMFRAMES; i++) {
+				uvd->frame[i].frameState = FrameState_Unused;
+				uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);
+				/*
+				 * Set default sizes in case IOCTL (VIDIOCMCAPTURE)
+				 * is not used (using read() instead).
+				 */
+				uvd->frame[i].canvas = uvd->canvas;
+				uvd->frame[i].seqRead_Index = 0;
+			}
+			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+				uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
+				if (uvd->sbuf[i].data == NULL) {
+					errCode = -ENOMEM;
+					break;
+				}
+			}
+		}
+		if (errCode != 0) {
+			/* Have to free all that memory */
+			if (uvd->fbuf != NULL) {
+				usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
+				uvd->fbuf = NULL;
+			}
+			RingQueue_Free(&uvd->dp);
+			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+				if (uvd->sbuf[i].data != NULL) {
+					kfree (uvd->sbuf[i].data);
+					uvd->sbuf[i].data = NULL;
+				}
+			}
+		}
+	}
+
+	/* If so far no errors then we shall start the camera */
+	if (errCode == 0) {
+		/* Start data pump if we have valid endpoint */
+		if (uvd->video_endp != 0)
+			errCode = GET_CALLBACK(uvd, startDataPump)(uvd);
+		if (errCode == 0) {
+			if (VALID_CALLBACK(uvd, setupOnOpen)) {
+				if (uvd->debug > 1)
+					info("%s: setupOnOpen callback", proc);
+				errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
+				if (errCode < 0) {
+					err("%s: setupOnOpen callback failed (%d.).",
+					    proc, errCode);
+				} else if (uvd->debug > 1) {
+					info("%s: setupOnOpen callback successful", proc);
+				}
+			}
+			if (errCode == 0) {
+				uvd->settingsAdjusted = 0;
+				if (uvd->debug > 1)
+					info("%s: Open succeeded.", proc);
+				uvd->user++;
+				file->private_data = uvd;
+			}
+		}
+	}
+	up(&uvd->lock);
+	if (errCode != 0)
+		usbvideo_ClientDecModCount(uvd);
+	if (uvd->debug > 0)
+		info("%s: Returning %d.", proc, errCode);
+	return errCode;
+}
+
+/*
+ * usbvideo_v4l_close()
+ *
+ * This is part of Video 4 Linux API. The procedure
+ * stops streaming and deallocates all buffers that were earlier
+ * allocated in usbvideo_v4l_open().
+ *
+ * History:
+ * 22-Jan-2000 Moved scratch buffer deallocation here.
+ * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
+ * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
+ */
+int usbvideo_v4l_close(struct inode *inode, struct file *file)
+{
+	static const char proc[] = "usbvideo_v4l_close";
+	struct video_device *dev = file->private_data;
+	uvd_t *uvd = (uvd_t *) dev;
+	int i;
+
+	if (uvd->debug > 1)
+		info("%s($%p)", proc, dev);
+
+	down(&uvd->lock);
+	GET_CALLBACK(uvd, stopDataPump)(uvd);
+	usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
+	uvd->fbuf = NULL;
+	RingQueue_Free(&uvd->dp);
+
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		kfree(uvd->sbuf[i].data);
+		uvd->sbuf[i].data = NULL;
+	}
+
+#if USBVIDEO_REPORT_STATS
+	usbvideo_ReportStatistics(uvd);
+#endif    
+
+	uvd->user--;
+	if (uvd->remove_pending) {
+		if (uvd->debug > 0)
+			info("usbvideo_v4l_close: Final disconnect.");
+		usbvideo_CameraRelease(uvd);
+	}
+	up(&uvd->lock);
+	usbvideo_ClientDecModCount(uvd);
+
+	if (uvd->debug > 1)
+		info("%s: Completed.", proc);
+	file->private_data = NULL;
+	return 0;
+}
+
+/*
+ * usbvideo_v4l_ioctl()
+ *
+ * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
+ *
+ * History:
+ * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
+ */
+static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
+				 unsigned int cmd, void *arg)
+{
+	uvd_t *uvd = file->private_data;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return -EIO;
+
+	switch (cmd) {
+		case VIDIOCGCAP:
+		{
+			struct video_capability *b = arg;
+			*b = uvd->vcap;
+			return 0;
+		}
+		case VIDIOCGCHAN:
+		{
+			struct video_channel *v = arg;
+			*v = uvd->vchan;
+			return 0;
+		}
+		case VIDIOCSCHAN:
+		{	
+			struct video_channel *v = arg;
+			if (v->channel != 0)
+				return -EINVAL;
+			return 0;
+		}
+		case VIDIOCGPICT:
+		{
+			struct video_picture *pic = arg;
+			*pic = uvd->vpic;
+			return 0;
+		}
+		case VIDIOCSPICT:
+		{
+			struct video_picture *pic = arg;
+			/*
+			 * Use temporary 'video_picture' structure to preserve our
+			 * own settings (such as color depth, palette) that we
+			 * aren't allowing everyone (V4L client) to change.
+			 */
+			uvd->vpic.brightness = pic->brightness;
+			uvd->vpic.hue = pic->hue;
+			uvd->vpic.colour = pic->colour;
+			uvd->vpic.contrast = pic->contrast;
+			uvd->settingsAdjusted = 0;	/* Will force new settings */
+			return 0;
+		}
+		case VIDIOCSWIN:
+		{
+			struct video_window *vw = arg;
+
+			if (vw->flags)
+				return -EINVAL;
+			if (vw->clipcount)
+				return -EINVAL;
+			if (vw->width != VIDEOSIZE_X(uvd->canvas))
+				return -EINVAL;
+			if (vw->height != VIDEOSIZE_Y(uvd->canvas))
+				return -EINVAL;
+
+			return 0;
+		}
+		case VIDIOCGWIN:
+		{
+			struct video_window *vw = arg;
+
+			vw->x = 0;
+			vw->y = 0;
+			vw->width = VIDEOSIZE_X(uvd->canvas);
+			vw->height = VIDEOSIZE_Y(uvd->canvas);
+			vw->chromakey = 0;
+			if (VALID_CALLBACK(uvd, getFPS))
+				vw->flags = GET_CALLBACK(uvd, getFPS)(uvd);
+			else 
+				vw->flags = 10; /* FIXME: do better! */
+			return 0;
+		}
+		case VIDIOCGMBUF:
+		{
+			struct video_mbuf *vm = arg;
+
+			memset(vm, 0, sizeof(*vm));
+			vm->size = uvd->max_frame_size * 2;
+			vm->frames = 2;
+			vm->offsets[0] = 0;
+			vm->offsets[1] = uvd->max_frame_size;
+			return 0;
+		}
+		case VIDIOCMCAPTURE:
+		{
+			struct video_mmap *vm = arg;
+
+			if (uvd->debug >= 1) {
+				info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.",
+				     vm->frame, vm->width, vm->height, vm->format);
+			}
+			/*
+			 * Check if the requested size is supported. If the requestor
+			 * requests too big a frame then we may be tricked into accessing
+			 * outside of own preallocated frame buffer (in uvd->frame).
+			 * This will cause oops or a security hole. Theoretically, we
+			 * could only clamp the size down to acceptable bounds, but then
+			 * we'd need to figure out how to insert our smaller buffer into
+			 * larger caller's buffer... this is not an easy question. So we
+			 * here just flatly reject too large requests, assuming that the
+			 * caller will resubmit with smaller size. Callers should know
+			 * what size we support (returned by VIDIOCGCAP). However vidcat,
+			 * for one, does not care and allows to ask for any size.
+			 */
+			if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
+			    (vm->height > VIDEOSIZE_Y(uvd->canvas))) {
+				if (uvd->debug > 0) {
+					info("VIDIOCMCAPTURE: Size=%dx%d too large; "
+					     "allowed only up to %ldx%ld", vm->width, vm->height,
+					     VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas));
+				}
+				return -EINVAL;
+			}
+			/* Check if the palette is supported */
+			if (((1L << vm->format) & uvd->paletteBits) == 0) {
+				if (uvd->debug > 0) {
+					info("VIDIOCMCAPTURE: format=%d. not supported"
+					     " (paletteBits=$%08lx)",
+					     vm->format, uvd->paletteBits);
+				}
+				return -EINVAL;
+			}
+			if ((vm->frame != 0) && (vm->frame != 1)) {
+				err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm->frame);
+				return -EINVAL;
+			}
+			if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) {
+				/* Not an error - can happen */
+			}
+			uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height);
+			uvd->frame[vm->frame].palette = vm->format;
+
+			/* Mark it as ready */
+			uvd->frame[vm->frame].frameState = FrameState_Ready;
+
+			return usbvideo_NewFrame(uvd, vm->frame);
+		}
+		case VIDIOCSYNC:
+		{
+			int *frameNum = arg;
+			int ret;
+
+			if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES)
+				return -EINVAL;
+				
+			if (uvd->debug >= 1)
+				info("VIDIOCSYNC: syncing to frame %d.", *frameNum);
+			if (uvd->flags & FLAGS_NO_DECODING)
+				ret = usbvideo_GetFrame(uvd, *frameNum);
+			else if (VALID_CALLBACK(uvd, getFrame)) {
+				ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum);
+				if ((ret < 0) && (uvd->debug >= 1)) {
+					err("VIDIOCSYNC: getFrame() returned %d.", ret);
+				}
+			} else {
+				err("VIDIOCSYNC: getFrame is not set");
+				ret = -EFAULT;
+			}
+
+			/*
+			 * The frame is in FrameState_Done_Hold state. Release it
+			 * right now because its data is already mapped into
+			 * the user space and it's up to the application to
+			 * make use of it until it asks for another frame.
+			 */
+			uvd->frame[*frameNum].frameState = FrameState_Unused;
+			return ret;
+		}
+		case VIDIOCGFBUF:
+		{
+			struct video_buffer *vb = arg;
+
+			memset(vb, 0, sizeof(*vb));
+ 			return 0;
+ 		}
+		case VIDIOCKEY:
+			return 0;
+
+		case VIDIOCCAPTURE:
+			return -EINVAL;
+
+		case VIDIOCSFBUF:
+
+		case VIDIOCGTUNER:
+		case VIDIOCSTUNER:
+
+		case VIDIOCGFREQ:
+		case VIDIOCSFREQ:
+
+		case VIDIOCGAUDIO:
+		case VIDIOCSAUDIO:
+			return -EINVAL;
+
+		default:
+			return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, usbvideo_v4l_do_ioctl);
+}
+
+/*
+ * usbvideo_v4l_read()
+ *
+ * This is mostly boring stuff. We simply ask for a frame and when it
+ * arrives copy all the video data from it into user space. There is
+ * no obvious need to override this method.
+ *
+ * History:
+ * 20-Oct-2000 Created.
+ * 01-Nov-2000 Added mutex (uvd->lock).
+ */
+int usbvideo_v4l_read(struct file *file, char *buf,
+		      size_t count, loff_t *ppos)
+{
+	static const char proc[] = "usbvideo_v4l_read";
+	uvd_t *uvd = file->private_data;
+	int noblock = file->f_flags & O_NONBLOCK;
+	int frmx = -1;
+	usbvideo_frame_t *frame;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
+		return -EFAULT;
+
+	if (uvd->debug >= 1)
+		info("%s: %d. bytes, noblock=%d.", proc, count, noblock);
+
+	down(&uvd->lock);	
+
+	/* See if a frame is completed, then use it. */
+	if ((uvd->frame[0].frameState == FrameState_Done) ||
+	    (uvd->frame[0].frameState == FrameState_Done_Hold) ||
+	    (uvd->frame[0].frameState == FrameState_Error)) {
+		frmx = 0;
+	} else if ((uvd->frame[1].frameState >= FrameState_Done) ||
+		   (uvd->frame[1].frameState == FrameState_Done_Hold) ||
+		   (uvd->frame[1].frameState >= FrameState_Done)) {
+		frmx = 1;
+	}
+
+	/* FIXME: If we don't start a frame here then who ever does? */
+	if (noblock && (frmx == -1)) {
+		count = -EAGAIN;
+		goto read_done;
+	}
+
+	/*
+	 * If no FrameState_Done, look for a FrameState_Grabbing state.
+	 * See if a frame is in process (grabbing), then use it.
+	 * We will need to wait until it becomes cooked, of course.
+	 */
+	if (frmx == -1) {
+		if (uvd->frame[0].frameState == FrameState_Grabbing)
+			frmx = 0;
+		else if (uvd->frame[1].frameState == FrameState_Grabbing)
+			frmx = 1;
+	}
+
+	/*
+	 * If no frame is active, start one. We don't care which one
+	 * it will be, so #0 is as good as any.
+	 * In read access mode we don't have convenience of VIDIOCMCAPTURE
+	 * to specify the requested palette (video format) on per-frame
+	 * basis. This means that we have to return data in -some- format
+	 * and just hope that the client knows what to do with it.
+	 * The default format is configured in uvd->defaultPalette field
+	 * as one of VIDEO_PALETTE_xxx values. We stuff it into the new
+	 * frame and initiate the frame filling process.
+	 */
+	if (frmx == -1) {
+		if (uvd->defaultPalette == 0) {
+			err("%s: No default palette; don't know what to do!", proc);
+			count = -EFAULT;
+			goto read_done;
+		}
+		frmx = 0;
+		/*
+		 * We have no per-frame control over video size.
+		 * Therefore we only can use whatever size was
+		 * specified as default.
+		 */
+		uvd->frame[frmx].request = uvd->videosize;
+		uvd->frame[frmx].palette = uvd->defaultPalette;
+		uvd->frame[frmx].frameState = FrameState_Ready;
+		usbvideo_NewFrame(uvd, frmx);
+		/* Now frame 0 is supposed to start filling... */
+	}
+
+	/*
+	 * Get a pointer to the active frame. It is either previously
+	 * completed frame or frame in progress but not completed yet.
+	 */
+	frame = &uvd->frame[frmx];
+
+	/*
+	 * Sit back & wait until the frame gets filled and postprocessed.
+	 * If we fail to get the picture [in time] then return the error.
+	 * In this call we specify that we want the frame to be waited for,
+	 * postprocessed and switched into FrameState_Done_Hold state. This
+	 * state is used to hold the frame as "fully completed" between
+	 * subsequent partial reads of the same frame.
+	 */
+	if (frame->frameState != FrameState_Done_Hold) {
+		long rv = -EFAULT;
+		if (uvd->flags & FLAGS_NO_DECODING)
+			rv = usbvideo_GetFrame(uvd, frmx);
+		else if (VALID_CALLBACK(uvd, getFrame))
+			rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx);
+		else
+			err("getFrame is not set");
+		if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) {
+			count = rv;
+			goto read_done;
+		}
+	}
+
+	/*
+	 * Copy bytes to user space. We allow for partial reads, which
+	 * means that the user application can request read less than
+	 * the full frame size. It is up to the application to issue
+	 * subsequent calls until entire frame is read.
+	 *
+	 * First things first, make sure we don't copy more than we
+	 * have - even if the application wants more. That would be
+	 * a big security embarassment!
+	 */
+	if ((count + frame->seqRead_Index) > frame->seqRead_Length)
+		count = frame->seqRead_Length - frame->seqRead_Index;
+
+	/*
+	 * Copy requested amount of data to user space. We start
+	 * copying from the position where we last left it, which
+	 * will be zero for a new frame (not read before).
+	 */
+	if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) {
+		count = -EFAULT;
+		goto read_done;
+	}
+
+	/* Update last read position */
+	frame->seqRead_Index += count;
+	if (uvd->debug >= 1) {
+		err("%s: {copy} count used=%d, new seqRead_Index=%ld",
+			proc, count, frame->seqRead_Index);
+	}
+
+	/* Finally check if the frame is done with and "release" it */
+	if (frame->seqRead_Index >= frame->seqRead_Length) {
+		/* All data has been read */
+		frame->seqRead_Index = 0;
+
+		/* Mark it as available to be used again. */
+		uvd->frame[frmx].frameState = FrameState_Unused;
+		if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) {
+			err("%s: usbvideo_NewFrame failed.", proc);
+		}
+	}
+read_done:
+	up(&uvd->lock);	
+	return count;
+}
+
+/*
+ * Make all of the blocks of data contiguous
+ */
+static int usbvideo_CompressIsochronous(uvd_t *uvd, struct urb *urb)
+{
+	char *cdata;
+	int i, totlen = 0;
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		int n = urb->iso_frame_desc[i].actual_length;
+		int st = urb->iso_frame_desc[i].status;
+
+		cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+		/* Detect and ignore errored packets */
+		if (st < 0) {
+			if (uvd->debug >= 1)
+				err("Data error: packet=%d. len=%d. status=%d.", i, n, st);
+			uvd->stats.iso_err_count++;
+			continue;
+		}
+
+		/* Detect and ignore empty packets */
+		if (n <= 0) {
+			uvd->stats.iso_skip_count++;
+			continue;
+		}
+		totlen += n;	/* Little local accounting */
+		RingQueue_Enqueue(&uvd->dp, cdata, n);
+	}
+	return totlen;
+}
+
+static void usbvideo_IsocIrq(struct urb *urb)
+{
+	int i, len;
+	uvd_t *uvd = urb->context;
+
+	/* We don't want to do anything if we are about to be removed! */
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return;
+#if 0
+	if (urb->actual_length > 0) {
+		info("urb=$%p status=%d. errcount=%d. length=%d.",
+		     urb, urb->status, urb->error_count, urb->actual_length);
+	} else {
+		static int c = 0;
+		if (c++ % 100 == 0)
+			info("No Isoc data");
+	}
+#endif
+
+	if (!uvd->streaming) {
+		if (uvd->debug >= 1)
+			info("Not streaming, but interrupt!");
+		return;
+	}
+	
+	uvd->stats.urb_count++;
+	if (urb->actual_length <= 0)
+		goto urb_done_with;
+
+	/* Copy the data received into ring queue */
+	len = usbvideo_CompressIsochronous(uvd, urb);
+	uvd->stats.urb_length = len;
+	if (len <= 0)
+		goto urb_done_with;
+
+	/* Here we got some data */
+	uvd->stats.data_count += len;
+	RingQueue_WakeUpInterruptible(&uvd->dp);
+
+urb_done_with:
+	for (i = 0; i < FRAMES_PER_DESC; i++) {
+		urb->iso_frame_desc[i].status = 0;
+		urb->iso_frame_desc[i].actual_length = 0;
+	}
+	return;
+}
+
+/*
+ * usbvideo_StartDataPump()
+ *
+ * History:
+ * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead
+ *             of hardcoded values. Simplified by using for loop,
+ *             allowed any number of URBs.
+ */
+int usbvideo_StartDataPump(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_StartDataPump";
+	struct usb_device *dev = uvd->dev;
+	int i, errFlag;
+
+	if (uvd->debug > 1)
+		info("%s($%p)", proc, uvd);
+
+	if (!CAMERA_IS_OPERATIONAL(uvd)) {
+		err("%s: Camera is not operational",proc);
+		return -EFAULT;
+	}
+	uvd->curframe = -1;
+
+	/* Alternate interface 1 is is the biggest frame size */
+	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
+	if (i < 0) {
+		err("%s: usb_set_interface error", proc);
+		uvd->last_error = i;
+		return -EBUSY;
+	}
+	if (VALID_CALLBACK(uvd, videoStart))
+		GET_CALLBACK(uvd, videoStart)(uvd);
+	else 
+		err("%s: videoStart not set", proc);
+
+	/* We double buffer the Iso lists */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		int j, k;
+		struct urb *urb = uvd->sbuf[i].urb;
+		urb->dev = dev;
+		urb->context = uvd;
+		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
+		urb->transfer_flags = USB_ISO_ASAP;
+		urb->transfer_buffer = uvd->sbuf[i].data;
+		urb->complete = usbvideo_IsocIrq;
+		urb->number_of_packets = FRAMES_PER_DESC;
+		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
+		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
+			urb->iso_frame_desc[j].offset = k;
+			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
+		}
+	}
+
+	/* Link URBs into a ring so that they invoke each other infinitely */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		if ((i+1) < USBVIDEO_NUMSBUF)
+			uvd->sbuf[i].urb->next = uvd->sbuf[i+1].urb;
+		else
+			uvd->sbuf[i].urb->next = uvd->sbuf[0].urb;
+	}
+
+	/* Submit all URBs */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+		if (errFlag)
+			err("%s: usb_submit_isoc(%d) ret %d", proc, i, errFlag);
+	}
+
+	uvd->streaming = 1;
+	if (uvd->debug > 1)
+		info("%s: streaming=1 video_endp=$%02x", proc, uvd->video_endp);
+	return 0;
+}
+
+/*
+ * usbvideo_StopDataPump()
+ *
+ * This procedure stops streaming and deallocates URBs. Then it
+ * activates zero-bandwidth alt. setting of the video interface.
+ *
+ * History:
+ * 22-Jan-2000 Corrected order of actions to work after surprise removal.
+ * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values.
+ */
+void usbvideo_StopDataPump(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_StopDataPump";
+	int i, j;
+
+	if (uvd->debug > 1)
+		info("%s($%p)", proc, uvd);
+
+	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
+		return;
+
+	/* Unschedule all of the iso td's */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		j = usb_unlink_urb(uvd->sbuf[i].urb);
+		if (j < 0)
+			err("%s: usb_unlink_urb() error %d.", proc, j);
+	}
+	if (uvd->debug > 1)
+		info("%s: streaming=0", proc);
+	uvd->streaming = 0;
+
+	if (!uvd->remove_pending) {
+		/* Invoke minidriver's magic to stop the camera */
+		if (VALID_CALLBACK(uvd, videoStop))
+			GET_CALLBACK(uvd, videoStop)(uvd);
+		else 
+			err("%s: videoStop not set" ,proc);
+
+		/* Set packet size to 0 */
+		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
+		if (j < 0) {
+			err("%s: usb_set_interface() error %d.", proc, j);
+			uvd->last_error = j;
+		}
+	}
+}
+
+/*
+ * usbvideo_NewFrame()
+ *
+ * History:
+ * 29-Mar-00 Added copying of previous frame into the current one.
+ * 6-Aug-00  Added model 3 video sizes, removed redundant width, height.
+ */
+int usbvideo_NewFrame(uvd_t *uvd, int framenum)
+{
+	usbvideo_frame_t *frame;
+	int n;
+
+	if (uvd->debug > 1)
+		info("usbvideo_NewFrame($%p,%d.)", uvd, framenum);
+
+	/* If we're not grabbing a frame right now and the other frame is */
+	/*  ready to be grabbed into, then use it instead */
+	if (uvd->curframe != -1)
+		return 0;
+
+	/* If necessary we adjust picture settings between frames */
+	if (!uvd->settingsAdjusted) {
+		if (VALID_CALLBACK(uvd, adjustPicture))
+			GET_CALLBACK(uvd, adjustPicture)(uvd);
+		uvd->settingsAdjusted = 1;
+	}
+
+	n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
+	if (uvd->frame[n].frameState == FrameState_Ready)
+		framenum = n;
+
+	frame = &uvd->frame[framenum];
+
+	frame->frameState = FrameState_Grabbing;
+	frame->scanstate = ScanState_Scanning;
+	frame->seqRead_Length = 0;	/* Accumulated in xxx_parse_data() */
+	frame->deinterlace = Deinterlace_None;
+	frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */
+	uvd->curframe = framenum;
+
+	/*
+	 * Normally we would want to copy previous frame into the current one
+	 * before we even start filling it with data; this allows us to stop
+	 * filling at any moment; top portion of the frame will be new and
+	 * bottom portion will stay as it was in previous frame. If we don't
+	 * do that then missing chunks of video stream will result in flickering
+	 * portions of old data whatever it was before.
+	 *
+	 * If we choose not to copy previous frame (to, for example, save few
+	 * bus cycles - the frame can be pretty large!) then we have an option
+	 * to clear the frame before using. If we experience losses in this
+	 * mode then missing picture will be black (no flickering).
+	 *
+	 * Finally, if user chooses not to clean the current frame before
+	 * filling it with data then the old data will be visible if we fail
+	 * to refill entire frame with new data.
+	 */
+	if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
+		/* This copies previous frame into this one to mask losses */
+		memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size);
+	} else {
+		if (uvd->flags & FLAGS_CLEAN_FRAMES) {
+			/* This provides a "clean" frame but slows things down */
+			memset(frame->data, 0, uvd->max_frame_size);
+		}
+	}
+	return 0;
+}
+
+/*
+ * usbvideo_CollectRawData()
+ *
+ * This procedure can be used instead of 'processData' callback if you
+ * only want to dump the raw data from the camera into the output
+ * device (frame buffer). You can look at it with V4L client, but the
+ * image will be unwatchable. The main purpose of this code and of the
+ * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from
+ * new, unknown cameras. This procedure will be automatically invoked
+ * instead of the specified callback handler when uvd->flags has bit
+ * FLAGS_NO_DECODING set. Therefore, any regular build of any driver
+ * based on usbvideo can use this feature at any time.
+ */
+void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame)
+{
+	int n;
+
+	assert(uvd != NULL);
+	assert(frame != NULL);
+
+	/* Try to move data from queue into frame buffer */
+	n = RingQueue_GetLength(&uvd->dp);
+	if (n > 0) {
+		int m;
+		/* See how much space we have left */
+		m = uvd->max_frame_size - frame->seqRead_Length;
+		if (n > m)
+			n = m;
+		/* Now move that much data into frame buffer */
+		RingQueue_Dequeue(
+			&uvd->dp,
+			frame->data + frame->seqRead_Length,
+			m);
+		frame->seqRead_Length += m;
+	}
+	/* See if we filled the frame */
+	if (frame->seqRead_Length >= uvd->max_frame_size) {
+		frame->frameState = FrameState_Done;
+		uvd->curframe = -1;
+		uvd->stats.frame_num++;
+	}
+}
+
+int usbvideo_GetFrame(uvd_t *uvd, int frameNum)
+{
+	static const char proc[] = "usbvideo_GetFrame";
+	usbvideo_frame_t *frame = &uvd->frame[frameNum];
+
+	if (uvd->debug >= 2)
+		info("%s($%p,%d.)", proc, uvd, frameNum);
+
+	switch (frame->frameState) {
+        case FrameState_Unused:
+		if (uvd->debug >= 2)
+			info("%s: FrameState_Unused", proc);
+		return -EINVAL;
+        case FrameState_Ready:
+        case FrameState_Grabbing:
+        case FrameState_Error:
+        {
+		int ntries, signalPending;
+	redo:
+		if (!CAMERA_IS_OPERATIONAL(uvd)) {
+			if (uvd->debug >= 2)
+				info("%s: Camera is not operational (1)", proc);
+			return -EIO;
+		}
+		ntries = 0; 
+		do {
+			RingQueue_InterruptibleSleepOn(&uvd->dp);
+			signalPending = signal_pending(current);
+			if (!CAMERA_IS_OPERATIONAL(uvd)) {
+				if (uvd->debug >= 2)
+					info("%s: Camera is not operational (2)", proc);
+				return -EIO;
+			}
+			assert(uvd->fbuf != NULL);
+			if (signalPending) {
+				if (uvd->debug >= 2)
+					info("%s: Signal=$%08x", proc, signalPending);
+				if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
+					usbvideo_TestPattern(uvd, 1, 0);
+					uvd->curframe = -1;
+					uvd->stats.frame_num++;
+					if (uvd->debug >= 2)
+						info("%s: Forced test pattern screen", proc);
+					return 0;
+				} else {
+					/* Standard answer: Interrupted! */
+					if (uvd->debug >= 2)
+						info("%s: Interrupted!", proc);
+					return -EINTR;
+				}
+			} else {
+				/* No signals - we just got new data in dp queue */
+				if (uvd->flags & FLAGS_NO_DECODING)
+					usbvideo_CollectRawData(uvd, frame);
+				else if (VALID_CALLBACK(uvd, processData))
+					GET_CALLBACK(uvd, processData)(uvd, frame);
+				else 
+					err("%s: processData not set", proc);
+			}
+		} while (frame->frameState == FrameState_Grabbing);
+		if (uvd->debug >= 2) {
+			info("%s: Grabbing done; state=%d. (%lu. bytes)",
+			     proc, frame->frameState, frame->seqRead_Length);
+		}
+		if (frame->frameState == FrameState_Error) {
+			int ret = usbvideo_NewFrame(uvd, frameNum);
+			if (ret < 0) {
+				err("%s: usbvideo_NewFrame() failed (%d.)", proc, ret);
+				return ret;
+			}
+			goto redo;
+		}
+		/* Note that we fall through to meet our destiny below */
+        }
+        case FrameState_Done:
+		/*
+		 * Do all necessary postprocessing of data prepared in
+		 * "interrupt" code and the collecting code above. The
+		 * frame gets marked as FrameState_Done by queue parsing code.
+		 * This status means that we collected enough data and
+		 * most likely processed it as we went through. However
+		 * the data may need postprocessing, such as deinterlacing
+		 * or picture adjustments implemented in software (horror!)
+		 *
+		 * As soon as the frame becomes "final" it gets promoted to
+		 * FrameState_Done_Hold status where it will remain until the
+		 * caller consumed all the video data from the frame. Then
+		 * the empty shell of ex-frame is thrown out for dogs to eat.
+		 * But we, worried about pets, will recycle the frame!
+		 */
+		uvd->stats.frame_num++;
+		if ((uvd->flags & FLAGS_NO_DECODING) == 0) {
+			if (VALID_CALLBACK(uvd, postProcess))
+				GET_CALLBACK(uvd, postProcess)(uvd, frame);
+			if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST)
+				usbvideo_SoftwareContrastAdjustment(uvd, frame);
+		}
+		frame->frameState = FrameState_Done_Hold;
+		if (uvd->debug >= 2)
+			info("%s: Entered FrameState_Done_Hold state.", proc);
+		return 0;
+
+	case FrameState_Done_Hold:
+		/*
+		 * We stay in this state indefinitely until someone external,
+		 * like ioctl() or read() call finishes digesting the frame
+		 * data. Then it will mark the frame as FrameState_Unused and
+		 * it will be released back into the wild to roam freely.
+		 */
+		if (uvd->debug >= 2)
+			info("%s: FrameState_Done_Hold state.", proc);
+		return 0;
+	}
+
+	/* Catch-all for other cases. We shall not be here. */
+	err("%s: Invalid state %d.", proc, frame->frameState);
+	frame->frameState = FrameState_Unused;
+	return 0;
+}
+
+/*
+ * usbvideo_DeinterlaceFrame()
+ *
+ * This procedure deinterlaces the given frame. Some cameras produce
+ * only half of scanlines - sometimes only even lines, sometimes only
+ * odd lines. The deinterlacing method is stored in frame->deinterlace
+ * variable.
+ *
+ * Here we scan the frame vertically and replace missing scanlines with
+ * average between surrounding ones - before and after. If we have no
+ * line above then we just copy next line. Similarly, if we need to
+ * create a last line then preceding line is used.
+ */
+void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame)
+{
+	if ((uvd == NULL) || (frame == NULL))
+		return;
+
+	if ((frame->deinterlace == Deinterlace_FillEvenLines) ||
+	    (frame->deinterlace == Deinterlace_FillOddLines))
+	{
+		const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
+		int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1;
+
+		for (; i < VIDEOSIZE_Y(frame->request); i += 2) {
+			const unsigned char *fs1, *fs2;
+			unsigned char *fd;
+			int ip, in, j;	/* Previous and next lines */
+
+			/*
+			 * Need to average lines before and after 'i'.
+			 * If we go out of bounds seeking those lines then
+			 * we point back to existing line.
+			 */
+			ip = i - 1;	/* First, get rough numbers */
+			in = i + 1;
+
+			/* Now validate */
+			if (ip < 0)
+				ip = in;
+			if (in >= VIDEOSIZE_Y(frame->request))
+				in = ip;
+
+			/* Sanity check */
+			if ((ip < 0) || (in < 0) ||
+			    (ip >= VIDEOSIZE_Y(frame->request)) ||
+			    (in >= VIDEOSIZE_Y(frame->request)))
+			{
+				err("Error: ip=%d. in=%d. req.height=%ld.",
+				    ip, in, VIDEOSIZE_Y(frame->request));
+				break;
+			}
+
+			/* Now we need to average lines 'ip' and 'in' to produce line 'i' */
+			fs1 = frame->data + (v4l_linesize * ip);
+			fs2 = frame->data + (v4l_linesize * in);
+			fd = frame->data + (v4l_linesize * i);
+
+			/* Average lines around destination */
+			for (j=0; j < v4l_linesize; j++) {
+				fd[j] = (unsigned char)((((unsigned) fs1[j]) +
+							 ((unsigned)fs2[j])) >> 1);
+			}
+		}
+	}
+
+	/* Optionally display statistics on the screen */
+	if (uvd->flags & FLAGS_OVERLAY_STATS)
+		usbvideo_OverlayStats(uvd, frame);
+}
+
+/*
+ * usbvideo_SoftwareContrastAdjustment()
+ *
+ * This code adjusts the contrast of the frame, assuming RGB24 format.
+ * As most software image processing, this job is CPU-intensive.
+ * Get a camera that supports hardware adjustment!
+ *
+ * History:
+ * 09-Feb-2001  Created.
+ */
+void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame)
+{
+	static const char proc[] = "usbvideo_SoftwareContrastAdjustment";
+	int i, j, v4l_linesize;
+	signed long adj;
+	const int ccm = 128; /* Color correction median - see below */
+
+	if ((uvd == NULL) || (frame == NULL)) {
+		err("%s: Illegal call.", proc);
+		return;
+	}
+	adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
+	RESTRICT_TO_RANGE(adj, -ccm, ccm+1);
+	if (adj == 0) {
+		/* In rare case of no adjustment */
+		return;
+	}
+	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
+	for (i=0; i < VIDEOSIZE_Y(frame->request); i++) {
+		unsigned char *fd = frame->data + (v4l_linesize * i);
+		for (j=0; j < v4l_linesize; j++) {
+			signed long v = (signed long) fd[j];
+			/* Magnify up to 2 times, reduce down to zero */
+			v = 128 + ((ccm + adj) * (v - 128)) / ccm;
+			RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */
+			fd[j] = (unsigned char) v;
+		}
+	}
+}
+
+/*
+ * /proc interface
+ *
+ * We will be creating directories and entries under /proc/video using
+ * external 'video_proc_entry' directory which is exported by videodev.o
+ * module. Within that directory we will create $driver/ directory to
+ * uniquely and uniformly refer to our specific $driver. Within that
+ * directory we will finally create an entry that is named after the
+ * video device node - video3, for example. The format of that file
+ * is determined by callbacks that the minidriver may provide. If no
+ * callbacks are provided (neither read nor write) then we don't create
+ * the entry.
+ *
+ * Here is a sample directory entry: /proc/video/ibmcam/video3
+ *
+ * The "file" video3 (in example above) is readable and writeable, in
+ * theory. If the minidriver provides callbacks to do reading and
+ * writing then both those procedures are supported. However if the
+ * driver leaves callbacks in default (NULL) state the default
+ * read and write handlers are used. The default read handler reports
+ * that the driver does not support /proc fs. The default write handler
+ * returns error code on any write attempt.
+ */
+
+#if USES_PROC_FS
+
+extern struct proc_dir_entry *video_proc_entry;
+
+static void usbvideo_procfs_level1_create(usbvideo_t *ut)
+{
+	static const char proc[] = "usbvideo_procfs_level1_create";
+
+	if (ut == NULL) {
+		err("%s: ut == NULL", proc);
+		return;
+	}
+	if (video_proc_entry == NULL) {
+		err("%s: /proc/video/ doesn't exist.", proc);
+		return;
+	}
+	ut->procfs_dEntry = create_proc_entry(ut->drvName, S_IFDIR, video_proc_entry);
+	if (ut->procfs_dEntry != NULL) {
+		if (ut->md_module != NULL)
+			ut->procfs_dEntry->owner = ut->md_module;
+	} else {
+		err("%s: Unable to initialize /proc/video/%s", proc, ut->drvName);
+	}
+}
+
+static void usbvideo_procfs_level1_destroy(usbvideo_t *ut)
+{
+	static const char proc[] = "usbvideo_procfs_level1_destroy";
+
+	if (ut == NULL) {
+		err("%s: ut == NULL", proc);
+		return;
+	}
+	if (ut->procfs_dEntry != NULL) {
+		remove_proc_entry(ut->drvName, video_proc_entry);
+		ut->procfs_dEntry = NULL;
+	}
+}
+
+static void usbvideo_procfs_level2_create(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_procfs_level2_create";
+
+	if (uvd == NULL) {
+		err("%s: uvd == NULL", proc);
+		return;
+	}
+	assert(uvd->handle != NULL);
+	if (uvd->handle->procfs_dEntry == NULL) {
+		err("%s: uvd->handle->procfs_dEntry == NULL", proc);
+		return;
+	}
+
+	sprintf(uvd->videoName, "video%d", uvd->vdev.minor);
+	uvd->procfs_vEntry = create_proc_entry(
+		uvd->videoName,
+		S_IFREG | S_IRUGO | S_IWUSR,
+		uvd->handle->procfs_dEntry);
+	if (uvd->procfs_vEntry != NULL) {
+		uvd->procfs_vEntry->data = uvd;
+		uvd->procfs_vEntry->read_proc = uvd->handle->cb.procfs_read;
+		uvd->procfs_vEntry->write_proc = uvd->handle->cb.procfs_write;
+	} else {
+		err("%s: Failed to create entry \"%s\"", proc, uvd->videoName);
+	}
+}
+
+static void usbvideo_procfs_level2_destroy(uvd_t *uvd)
+{
+	static const char proc[] = "usbvideo_procfs_level2_destroy";
+
+	if (uvd == NULL) {
+		err("%s: uvd == NULL", proc);
+		return;
+	}
+	if (uvd->procfs_vEntry != NULL) {
+		remove_proc_entry(uvd->videoName, uvd->procfs_vEntry);
+		uvd->procfs_vEntry = NULL;
+	}
+}
+
+static int usbvideo_default_procfs_read_proc(
+	char *page, char **start, off_t off, int count,
+	int *eof, void *data)
+{
+	char *out = page;
+	int len;
+	
+	/* Stay under PAGE_SIZE or else */
+	out += sprintf(out, "This driver does not support /proc services.\n");
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else
+		len = count;
+	*start = page + off;
+	return len;	
+}
+
+static int usbvideo_default_procfs_write_proc(
+	struct file *file, const char *buffer, 
+	unsigned long count, void *data)
+{
+	return -EINVAL;
+}
+
+#endif /* USES_PROC_FS */
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/media/usbvideo.h b/drivers/usb/media/usbvideo.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/usbvideo.h	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,416 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef usbvideo_h
+#define	usbvideo_h
+
+#include <linux/config.h>
+#include <linux/proc_fs.h>
+#include <linux/videodev.h>
+#include <linux/usb.h>
+
+/* Most helpful debugging aid */
+#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
+
+#define USES_PROC_FS	(defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS))
+#define USBVIDEO_REPORT_STATS	1	/* Set to 0 to block statistics on close */
+
+/* Bit flags (options) */
+#define FLAGS_RETRY_VIDIOCSYNC		(1 << 0)
+#define	FLAGS_MONOCHROME		(1 << 1)
+#define FLAGS_DISPLAY_HINTS		(1 << 2)
+#define FLAGS_OVERLAY_STATS		(1 << 3)
+#define FLAGS_FORCE_TESTPATTERN		(1 << 4)
+#define FLAGS_SEPARATE_FRAMES		(1 << 5)
+#define FLAGS_CLEAN_FRAMES		(1 << 6)
+#define	FLAGS_NO_DECODING		(1 << 7)
+
+/* Bit flags for frames (apply to the frame where they are specified) */
+#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST	(1 << 0)
+
+/* Camera capabilities (maximum) */
+#define CAMERA_URB_FRAMES       32
+#define CAMERA_MAX_ISO_PACKET   1023 /* 1022 actually sent by camera */
+#define FRAMES_PER_DESC		(CAMERA_URB_FRAMES)
+#define FRAME_SIZE_PER_DESC	(CAMERA_MAX_ISO_PACKET)
+
+/* This macro restricts an int variable to an inclusive range */
+#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+
+#define V4L_BYTES_PER_PIXEL     3	/* Because we produce RGB24 */
+
+/*
+ * Use this macro to construct constants for different video sizes.
+ * We have to deal with different video sizes that have to be
+ * configured in the device or compared against when we receive
+ * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y
+ * #defines and that's the end of story. However this solution
+ * does not allow to convert between real pixel sizes and the
+ * constant (integer) value that may be used to tag a frame or
+ * whatever. The set of macros below constructs videosize constants
+ * from the pixel size and allows to reconstruct the pixel size
+ * from the combined value later.
+ */
+#define	VIDEOSIZE(x,y)	(((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16))
+#define	VIDEOSIZE_X(vs)	((vs) & 0xFFFFL)
+#define	VIDEOSIZE_Y(vs)	(((vs) >> 16) & 0xFFFFL)
+typedef unsigned long videosize_t;
+
+/*
+ * This macro checks if the camera is still operational. The 'uvd'
+ * pointer must be valid, uvd->dev must be valid, we are not
+ * removing the device and the device has not erred on us.
+ */
+#define CAMERA_IS_OPERATIONAL(uvd) (\
+	(uvd != NULL) && \
+	((uvd)->dev != NULL) && \
+	((uvd)->last_error == 0) && \
+	(!(uvd)->remove_pending))
+
+/*
+ * We use macros to do YUV -> RGB conversion because this is
+ * very important for speed and totally unimportant for size.
+ *
+ * YUV -> RGB Conversion
+ * ---------------------
+ *
+ * B = 1.164*(Y-16)		    + 2.018*(V-128)
+ * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
+ * R = 1.164*(Y-16) + 1.596*(U-128)
+ *
+ * If you fancy integer arithmetics (as you should), hear this:
+ *
+ * 65536*B = 76284*(Y-16)		  + 132252*(V-128)
+ * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
+ * 65536*R = 76284*(Y-16) + 104595*(U-128)
+ *
+ * Make sure the output values are within [0..255] range.
+ */
+#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
+#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
+    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
+    mm_y = (my) - 16;  \
+    mm_u = (mu) - 128; \
+    mm_v = (mv) - 128; \
+    mm_yc= mm_y * 76284; \
+    mm_b = (mm_yc		+ 132252*mm_v	) >> 16; \
+    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v	) >> 16; \
+    mm_r = (mm_yc + 104595*mm_u			) >> 16; \
+    mb = LIMIT_RGB(mm_b); \
+    mg = LIMIT_RGB(mm_g); \
+    mr = LIMIT_RGB(mm_r); \
+}
+
+#define	RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length
+#define	RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
+#define	RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length])
+
+typedef struct {
+	unsigned char *queue;	/* Data from the Isoc data pump */
+	int length;		/* How many bytes allocated for the queue */
+	int wi;			/* That's where we write */
+	int ri;			/* Read from here until you hit write index */
+	wait_queue_head_t wqh;	/* Processes waiting */
+} RingQueue_t;
+
+typedef enum {
+	ScanState_Scanning,	/* Scanning for header */
+	ScanState_Lines		/* Parsing lines */
+} ScanState_t;
+
+/* Completion states of the data parser */
+typedef enum {
+	scan_Continue,		/* Just parse next item */
+	scan_NextFrame,		/* Frame done, send it to V4L */
+	scan_Out,		/* Not enough data for frame */
+	scan_EndParse		/* End parsing */
+} ParseState_t;
+
+typedef enum {
+	FrameState_Unused,	/* Unused (no MCAPTURE) */
+	FrameState_Ready,	/* Ready to start grabbing */
+	FrameState_Grabbing,	/* In the process of being grabbed into */
+	FrameState_Done,	/* Finished grabbing, but not been synced yet */
+	FrameState_Done_Hold,	/* Are syncing or reading */
+	FrameState_Error,	/* Something bad happened while processing */
+} FrameState_t;
+
+/*
+ * Some frames may contain only even or odd lines. This type
+ * specifies what type of deinterlacing is required.
+ */
+typedef enum {
+	Deinterlace_None=0,
+	Deinterlace_FillOddLines,
+	Deinterlace_FillEvenLines
+} Deinterlace_t;
+
+struct usb_device;
+
+#define USBVIDEO_NUMFRAMES	2	/* How many frames we work with */
+#define USBVIDEO_NUMSBUF	2	/* How many URBs linked in a ring */
+
+/* This structure represents one Isoc request - URB and buffer */
+typedef struct {
+	char *data;
+	struct urb *urb;
+} usbvideo_sbuf_t;
+
+typedef struct {
+	char *data;		/* Frame buffer */
+	unsigned long header;	/* Significant bits from the header */
+
+	videosize_t canvas;	/* The canvas (max. image) allocated */
+	videosize_t request;	/* That's what the application asked for */
+	unsigned short palette;	/* The desired format */
+
+	FrameState_t frameState;/* State of grabbing */
+	ScanState_t scanstate;	/* State of scanning */
+	Deinterlace_t deinterlace;
+	int flags;		/* USBVIDEO_FRAME_FLAG_xxx bit flags */
+
+	int curline;		/* Line of frame we're working on */
+
+	long seqRead_Length;	/* Raw data length of frame */
+	long seqRead_Index;	/* Amount of data that has been already read */
+
+	void *user;		/* Additional data that user may need */
+} usbvideo_frame_t;
+
+/* Statistics that can be overlaid on screen */
+typedef struct {
+        unsigned long frame_num;	/* Sequential number of the frame */
+        unsigned long urb_count;        /* How many URBs we received so far */
+        unsigned long urb_length;       /* Length of last URB */
+        unsigned long data_count;       /* How many bytes we received */
+        unsigned long header_count;     /* How many frame headers we found */
+	unsigned long iso_skip_count;	/* How many empty ISO packets received */
+	unsigned long iso_err_count;	/* How many bad ISO packets received */
+} usbvideo_statistics_t;
+
+struct s_usbvideo_t;
+
+typedef struct {
+	struct video_device vdev;	/* Must be the first field! */
+	struct usb_device *dev;
+	struct s_usbvideo_t *handle;	/* Points back to the usbvideo_t */
+	void *user_data;		/* Camera-dependent data */
+	int user_size;			/* Size of that camera-dependent data */
+	int debug;			/* Debug level for usbvideo */
+	unsigned char iface;		/* Video interface number */
+	unsigned char video_endp;
+	unsigned char ifaceAltActive;
+	unsigned char ifaceAltInactive; /* Alt settings */
+	unsigned long flags;		/* FLAGS_USBVIDEO_xxx */
+	unsigned long paletteBits;	/* Which palettes we accept? */
+	unsigned short defaultPalette;	/* What palette to use for read() */
+	struct semaphore lock;
+	int user;		/* user count for exclusive use */
+
+	videosize_t videosize;	/* Current setting */
+	videosize_t canvas;	/* This is the width,height of the V4L canvas */
+	int max_frame_size;	/* Bytes in one video frame */
+
+	int uvd_used;        	/* Is this structure in use? */
+	int streaming;		/* Are we streaming Isochronous? */
+	int grabbing;		/* Are we grabbing? */
+	int settingsAdjusted;	/* Have we adjusted contrast etc.? */
+	int last_error;		/* What calamity struck us? */
+
+	char *fbuf;		/* Videodev buffer area */
+	int fbuf_size;		/* Videodev buffer size */
+
+	int curframe;
+	int iso_packet_len;	/* Videomode-dependent, saves bus bandwidth */
+
+	RingQueue_t dp;		/* Isoc data pump */
+	usbvideo_frame_t frame[USBVIDEO_NUMFRAMES];
+	usbvideo_sbuf_t sbuf[USBVIDEO_NUMSBUF];
+
+	volatile int remove_pending;	/* If set then about to exit */
+
+	struct video_picture vpic, vpic_old;	/* Picture settings */
+	struct video_capability vcap;		/* Video capabilities */
+	struct video_channel vchan;	/* May be used for tuner support */
+	usbvideo_statistics_t stats;
+	struct proc_dir_entry *procfs_vEntry;	/* /proc/video/MYDRIVER/video2 */
+	char videoName[32];		/* Holds name like "video7" */
+} uvd_t;
+
+/*
+ * usbvideo callbacks (virtual methods). They are set when usbvideo
+ * services are registered. All of these default to NULL, except those
+ * that default to usbvideo-provided methods.
+ */
+typedef struct {
+	void *(*probe)(struct usb_device *, unsigned int,const struct usb_device_id *);
+	void (*userFree)(uvd_t *);
+	void (*disconnect)(struct usb_device *, void *);
+	int (*setupOnOpen)(uvd_t *);
+	void (*videoStart)(uvd_t *);
+	void (*videoStop)(uvd_t *);
+	void (*processData)(uvd_t *, usbvideo_frame_t *);
+	void (*postProcess)(uvd_t *, usbvideo_frame_t *);
+	void (*adjustPicture)(uvd_t *);
+	int (*getFPS)(uvd_t *);
+	int (*overlayHook)(uvd_t *, usbvideo_frame_t *);
+	int (*getFrame)(uvd_t *, int);
+	int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data);
+	int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data);
+	int (*startDataPump)(uvd_t *uvd);
+	void (*stopDataPump)(uvd_t *uvd);
+} usbvideo_cb_t;
+
+struct s_usbvideo_t {
+	int num_cameras;		/* As allocated */
+	struct usb_driver usbdrv;	/* Interface to the USB stack */
+	char drvName[80];		/* Driver name */
+	struct semaphore lock;		/* Mutex protecting camera structures */
+	usbvideo_cb_t cb;		/* Table of callbacks (virtual methods) */
+	struct video_device vdt;	/* Video device template */
+	uvd_t *cam;			/* Array of camera structures */
+	int uses_procfs;		/* Non-zero if we create /proc entries */
+	struct proc_dir_entry *procfs_dEntry;	/* /proc/video/MYDRIVER */
+	struct module *md_module;	/* Minidriver module */
+};
+typedef struct s_usbvideo_t usbvideo_t;
+
+/*
+ * This macro retrieves callback address from the uvd_t object.
+ * No validity checks are done here, so be sure to check the
+ * callback beforehand with VALID_CALLBACK.
+ */
+#define	GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName)
+
+/*
+ * This macro returns either callback pointer or NULL. This is safe
+ * macro, meaning that most of components of data structures involved
+ * may be NULL - this only results in NULL being returned. You may
+ * wish to use this macro to make sure that the callback is callable.
+ * However keep in mind that those checks take time.
+ */
+#define	VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
+		((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
+
+void RingQueue_Initialize(RingQueue_t *rq);
+void RingQueue_Allocate(RingQueue_t *rq, int rqLen);
+int  RingQueue_IsAllocated(const RingQueue_t *rq);
+void RingQueue_Free(RingQueue_t *rq);
+int  RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len);
+int  RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n);
+int  RingQueue_GetLength(const RingQueue_t *rq);
+void RingQueue_InterruptibleSleepOn(RingQueue_t *rq);
+void RingQueue_WakeUpInterruptible(RingQueue_t *rq);
+
+void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame);
+void usbvideo_DrawLine(
+	usbvideo_frame_t *frame,
+	int x1, int y1,
+	int x2, int y2,
+	unsigned char cr, unsigned char cg, unsigned char cb);
+void usbvideo_HexDump(const unsigned char *data, int len);
+void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, int ch);
+void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, const char *str);
+void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame);
+void usbvideo_ReportStatistics(const uvd_t *uvd);
+void usbvideo_SayAndWait(const char *what);
+void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode);
+void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs);
+
+/* Memory allocation routines */
+unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
+void *usbvideo_rvmalloc(unsigned long size);
+void usbvideo_rvfree(void *mem, unsigned long size);
+
+int usbvideo_register(
+	usbvideo_t **pCams,
+	const int num_cams,
+	const int num_extra,
+	const char *driverName,
+	const usbvideo_cb_t *cbTable,
+	struct module *md);
+uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams);
+int usbvideo_RegisterVideoDevice(uvd_t *uvd);
+void usbvideo_Deregister(usbvideo_t **uvt);
+void usbvideo_Disconnect(struct usb_device *dev, void *ptr);
+void usbvideo_CameraRelease(uvd_t *uvd);
+
+int usbvideo_v4l_close(struct inode *inode, struct file *file);
+int usbvideo_v4l_initialize(struct video_device *dev);
+int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg);
+int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
+int usbvideo_v4l_open(struct inode *inode, struct file *file);
+int usbvideo_v4l_read(struct file *file, char *buf,
+		      size_t count, loff_t *ppos);
+
+int usbvideo_GetFrame(uvd_t *uvd, int frameNum);
+int usbvideo_NewFrame(uvd_t *uvd, int framenum);
+int usbvideo_StartDataPump(uvd_t *uvd);
+void usbvideo_StopDataPump(uvd_t *uvd);
+void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame);
+void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame);
+
+/*
+ * This code performs bounds checking - use it when working with
+ * new formats, or else you may get oopses all over the place.
+ * If pixel falls out of bounds then it gets shoved back (as close
+ * to place of offence as possible) and is painted bright red.
+ *
+ * There are two important concepts: frame width, height and
+ * V4L canvas width, height. The former is the area requested by
+ * the application -for this very frame-. The latter is the largest
+ * possible frame that we can serve (we advertise that via V4L ioctl).
+ * The frame data is expected to be formatted as lines of length
+ * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines.
+ */
+static inline void RGB24_PUTPIXEL(
+	usbvideo_frame_t *fr,
+	int ix, int iy,
+	unsigned char vr,
+	unsigned char vg,
+	unsigned char vb)
+{
+	register unsigned char *pf;
+	int limiter = 0, mx, my;
+	mx = ix;
+	my = iy;
+	if (mx < 0) {
+		mx=0;
+		limiter++;
+	} else if (mx >= VIDEOSIZE_X((fr)->request)) {
+		mx= VIDEOSIZE_X((fr)->request) - 1;
+		limiter++;
+	}
+	if (my < 0) {
+		my = 0;
+		limiter++;
+	} else if (my >= VIDEOSIZE_Y((fr)->request)) {
+		my = VIDEOSIZE_Y((fr)->request) - 1;
+		limiter++;
+	}
+	pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix));
+	if (limiter) {
+		*pf++ = 0;
+		*pf++ = 0;
+		*pf++ = 0xFF;
+	} else {
+		*pf++ = (vb);
+		*pf++ = (vg);
+		*pf++ = (vr);
+	}
+}
+
+#endif /* usbvideo_h */
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/vicam.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,926 @@
+/* -*- linux-c -*-
+ * USB ViCAM driver
+ *
+ * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
+ * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
+ *
+ * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
+ *
+ * TODO:
+ *	- find out the ids for the Vista Imaging ViCAM
+ *
+ * History:
+ *
+ * 2001_07_07 - 0.1 - christopher: first version
+ * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try 
+ 			while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
+		      yep, moving pictures.
+ * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
+ 			get gqcam-0.9, compile it and run. Better than dd ;-).
+ * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
+ 			kill update_params if it does not seem to work for you.
+ * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
+
+ *
+ * FIXME: It crashes on rmmod with camera plugged.
+ */
+#define DEBUG 1
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
+
+#include <asm/io.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
+#include <linux/videodev.h>
+
+#include "vicam.h"
+#include "vicamurbs.h"
+
+/* Version Information */
+#define DRIVER_VERSION "v0"
+#define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
+#define DRIVER_DESC "USB ViCAM Driver"
+
+/* Define these values to match your device */
+#define USB_VICAM_VENDOR_ID	0x04C1
+#define USB_VICAM_PRODUCT_ID	0x009D
+
+/* table of devices that work with this driver */
+static struct usb_device_id vicam_table [] = {
+	{ USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, vicam_table);
+
+static int video_nr = -1; 		/* next avail video device */
+static struct usb_driver vicam_driver;
+
+static char *buf, *buf2;
+static volatile int change_pending = 0; 
+
+static int vicam_parameters(struct usb_vicam *vicam);
+
+/******************************************************************************
+ *
+ *  Memory management functions
+ *
+ *  Taken from bttv-drivers.c 2.4.7-pre3
+ *
+ ******************************************************************************/
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+	unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+	return ret;
+}
+
+static void * rvmalloc(unsigned long size)
+{
+	void * mem;
+	unsigned long adr;
+
+	size=PAGE_ALIGN(size);
+	mem=vmalloc_32(size);
+	if (mem)
+	{
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+		adr=(unsigned long) mem;
+		while (size > 0)
+		{
+			mem_map_reserve(vmalloc_to_page((void *)adr));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (mem)
+	{
+		adr=(unsigned long) mem;
+		while ((long) size > 0)
+		{
+			mem_map_unreserve(vmalloc_to_page((void *)adr));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+/******************************************************************************
+ *
+ *  Foo Bar
+ *
+ ******************************************************************************/
+
+/**
+ *	usb_vicam_debug_data
+ */
+static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
+{
+	int i;
+
+	if (!debug)
+		return;
+
+	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
+		function, size);
+	for (i = 0; i < size; ++i) {
+		printk ("%.2x ", data[i]);
+	}
+	printk ("\n");
+}
+
+/*****************************************************************************
+ *
+ *  Send command to vicam
+ *
+ *****************************************************************************/
+
+static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
+	unsigned short value, unsigned char *cp, int size)
+{
+	int ret;
+	unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
+
+	/* Needs to return data I think, works for sending though */
+	memcpy(transfer_buffer, cp, size);
+	
+	ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
+
+	kfree(transfer_buffer);
+	if (ret)
+		printk("vicam: error: %d\n", ret);
+	mdelay(100);
+	return ret;
+}
+
+
+/*****************************************************************************
+ *
+ *  Video4Linux Helpers
+ * 
+ *****************************************************************************/
+
+static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
+{
+	dbg("vicam_get_capability");
+
+	strcpy(b->name, vicam->camera_name);
+	b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
+	b->channels = 1;
+	b->audios = 0;
+
+	b->maxwidth = vicam->width[vicam->sizes-1];
+	b->maxheight = vicam->height[vicam->sizes-1];
+	b->minwidth = vicam->width[0];
+	b->minheight = vicam->height[0];
+
+	return 0;
+}
+		
+static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+	dbg("vicam_get_channel");
+
+	if (v->channel != 0)
+		return -EINVAL;
+ 
+	v->flags = 0;
+	v->tuners = 0;
+	v->type = VIDEO_TYPE_CAMERA;
+	strcpy(v->name, "Camera");
+
+	return 0;
+} 
+		
+static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
+{
+	dbg("vicam_set_channel");
+
+	if (v->channel != 0)
+		return -EINVAL;
+	
+	return 0;
+}
+		
+static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
+{
+	int i;
+
+	dbg("vicam_get_mmapbuffer");
+
+	memset(vm, 0, sizeof(vm));
+	vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
+	vm->frames = VICAM_NUMFRAMES;
+
+	for (i=0; i<VICAM_NUMFRAMES; i++)
+		vm->offsets[i] = vicam->maxframesize * i;
+
+	return 0;
+}
+
+static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+	dbg("vicam_get_picture");
+
+	/* This is probably where that weird 0x56 call goes */
+	p->brightness = vicam->win.brightness;
+	p->hue = vicam->win.hue;
+	p->colour = vicam->win.colour;
+	p->contrast = vicam->win.contrast;
+	p->whiteness = vicam->win.whiteness;
+	p->depth = vicam->win.depth;
+	p->palette = vicam->win.palette;
+
+	return 0;
+}
+
+static void synchronize(struct usb_vicam *vicam)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	change_pending = 1;
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&vicam->wait, &wait);
+	if (change_pending)
+		schedule();
+	remove_wait_queue(&vicam->wait, &wait);
+	set_current_state(TASK_RUNNING);
+	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+	mdelay(10);
+	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+	mdelay(10);
+}
+
+static void params_changed(struct usb_vicam *vicam)
+{
+#if 1
+	synchronize(vicam);
+	mdelay(10);
+	vicam_parameters(vicam);
+	printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
+#endif
+}
+
+static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
+{
+	int changed = 0;
+	info("vicam_set_picture (%d)", p->brightness);
+
+
+#define SET(x) \
+	if (vicam->win.x != p->x) \
+		vicam->win.x = p->x, changed = 1;
+	SET(brightness);
+	SET(hue);
+	SET(colour);
+	SET(contrast);
+	SET(whiteness);
+	SET(depth);
+	SET(palette);
+	if (changed)
+		params_changed(vicam);
+
+	return 0;
+	/* Investigate what should be done maybe 0x56 type call */
+	if (p->depth != 8) return 1;
+	if (p->palette != VIDEO_PALETTE_GREY) return 1;
+
+	return 0;
+}
+
+/* FIXME - vicam_sync_frame - important */
+static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
+{
+	dbg("vicam_sync_frame");
+
+	if(frame <0 || frame >= VICAM_NUMFRAMES)
+		return -EINVAL;
+
+	/* Probably need to handle various cases */
+/*	ret=vicam_newframe(vicam, frame);
+	vicam->frame[frame].grabstate=FRAME_UNUSED;
+*/
+	return 0;
+}
+	
+static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+	dbg("vicam_get_window");
+
+	vw->x = 0;
+	vw->y = 0;
+	vw->chromakey = 0;
+	vw->flags = 0;
+	vw->clipcount = 0;
+	vw->width = vicam->win.width;
+	vw->height = vicam->win.height;
+
+	return 0;
+}
+
+static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
+{
+	info("vicam_set_window");
+		
+	if (vw->flags)
+		return -EINVAL;
+	if (vw->clipcount)
+		return -EINVAL;
+
+	if (vicam->win.width == vw->width && vicam->win.height == vw->height)
+		return 0;
+
+	/* Pick largest mode that is smaller than specified res */
+	/* If specified res is too small reject                 */
+
+	/* Add urb send to device... */
+
+	vicam->win.width = vw->width;
+	vicam->win.height = vw->height;
+	params_changed(vicam);
+
+	return 0;
+}
+
+/* FIXME - vicam_mmap_capture - important */
+static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
+{
+	dbg("vicam_mmap_capture");
+
+	/* usbvideo.c looks good for using here */
+
+	/* 
+	if (vm->frame >= VICAM_NUMFRAMES)
+		return -EINVAL;
+	if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
+		return -EBUSY;
+	vicam->frame[vm->frame].grabstate=FRAME_READY;
+	*/
+
+	/* No need to vicam_set_window here according to Alan */
+
+	/*
+	if (!vicam->streaming)
+		vicam_start_stream(vicam);
+	*/
+
+	/* set frame as ready */
+
+	return 0;
+}
+
+/*****************************************************************************
+ *
+ *  Video4Linux
+ * 
+ *****************************************************************************/
+
+static int vicam_v4l_open(struct inode *inode, struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+	int err = 0;
+	
+	dbg("vicam_v4l_open");
+	down(&vicam->sem);
+
+	vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
+	if (vicam->open_count) {
+		err = -EBUSY;
+	} else if (!vicam->fbuf) {
+		err =- ENOMEM;
+	} else {
+#ifdef BLINKING
+		vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+		info ("led on");
+		vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+#endif
+		vicam->open_count++;
+		file->private_data = vdev;
+	}
+
+	up(&vicam->sem);
+	return err;
+}
+
+static int vicam_v4l_close(struct inode *inode, struct file *file)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+	dbg("vicam_v4l_close");
+	
+	down(&vicam->sem);
+
+#ifdef BLINKING
+	info ("led off");
+	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+//	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
+#endif
+
+	rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
+	vicam->fbuf = 0;
+	vicam->open_count=0;
+	file->private_data = NULL;
+
+	up(&vicam->sem);
+	/* Why does se401.c have a usbdevice check here? */
+	/* If device is unplugged while open, I guess we only may unregister now */
+	return 0;
+}
+
+static int vicam_v4l_read(struct file *file, char *user_buf,
+			  size_t buflen, loff_t *ppos)
+{
+	struct video_device *vdev = file->private_data;
+	//struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+
+	dbg("vicam_v4l_read(%d)", buflen);
+
+	if (!vdev || !buf)
+		return -EFAULT;
+
+	if (copy_to_user(user_buf, buf2, buflen))
+		return -EFAULT;
+	return buflen;
+}
+
+static int vicam_v4l_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+	int ret = -EL3RST;
+
+	if (!vicam->udev)
+		return -EIO;
+
+	down(&vicam->sem);
+
+	switch (cmd) {
+	case VIDIOCGCAP:
+	{
+		struct video_capability *b = arg;
+		ret = vicam_get_capability(vicam,b);
+		dbg("name %s",b->name);
+		break;
+	}
+	case VIDIOCGFBUF:
+	{
+		struct video_buffer *vb = arg;
+		info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
+		/* frame buffer not supported, not used */
+		memset(vb, 0, sizeof(*vb));
+		ret = 0;
+		break;
+	}
+	case VIDIOCGWIN:
+	{
+		struct video_window *vw = arg;
+		ret = vicam_get_window(vicam, vw);
+		break;
+	}
+	case VIDIOCSWIN:
+	{
+		struct video_window *vw = arg;
+		ret = vicam_set_window(vicam, vw);
+		break;
+	}
+	case VIDIOCGCHAN:
+	{
+		struct video_channel *v = arg;
+
+		ret = vicam_get_channel(vicam,v);
+		break;
+	}
+	case VIDIOCSCHAN:
+	{
+		struct video_channel *v = arg;
+		ret = vicam_set_channel(vicam,v);
+		break;
+ 	}
+	case VIDIOCGPICT:
+	{
+		struct video_picture *p = arg;
+		ret = vicam_get_picture(vicam,p);
+		break;
+	}
+	case VIDIOCSPICT:
+	{
+		struct video_picture *p = arg;
+		ret = vicam_set_picture(vicam,p);
+		break;
+	}
+	case VIDIOCGMBUF:
+	{
+		struct video_mbuf *vm = arg;
+		ret = vicam_get_mmapbuffer(vicam,vm);
+		break;
+	}
+	case VIDIOCMCAPTURE:
+	{
+		struct video_mmap *vm = arg;
+		ret = vicam_mmap_capture(vicam,vm);
+		break;
+	}
+	case VIDIOCSYNC:
+	{
+		int *frame = arg;
+		ret = vicam_sync_frame(vicam,*frame);
+		break;
+	}
+
+	case VIDIOCKEY:
+		ret = 0;
+ 
+	case VIDIOCCAPTURE:
+	case VIDIOCSFBUF:
+	case VIDIOCGTUNER:
+	case VIDIOCSTUNER:
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+	case VIDIOCGUNIT:
+		ret = -EINVAL;
+
+	default:
+	{
+		info("vicam_v4l_ioctl - %ui",cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	} /* end switch */
+
+	up(&vicam->sem);
+        return ret;
+}
+
+static int vicam_v4l_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, vicam_v4l_do_ioctl);
+}
+
+static int vicam_v4l_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *vdev = file->private_data;
+	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long page, pos;
+
+	down(&vicam->sem);
+	
+	if (vicam->udev == NULL) {
+		up(&vicam->sem);
+		return -EIO;
+	}
+#if 0
+	if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
+		up(&vicam->sem);
+		return -EINVAL;
+	}
+#endif
+	pos = (unsigned long)vicam->fbuf;
+	while (size > 0) {
+		page = kvirt_to_pa(pos);
+		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+			up(&vicam->sem);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+	up(&vicam->sem);
+
+        return 0;
+}
+
+/* FIXME - vicam_template - important */
+static struct file_operations vicam_fops = {
+	owner:		THIS_MODULE,
+	open:		vicam_v4l_open,
+	release:       	vicam_v4l_close,
+	read:		vicam_v4l_read,
+	mmap:		vicam_v4l_mmap,
+	ioctl:		vicam_v4l_ioctl,
+	llseek:         no_llseek,
+};
+static struct video_device vicam_template = {
+	owner:		THIS_MODULE,
+	name:		"vicam USB camera",
+	type:		VID_TYPE_CAPTURE,
+	hardware:	VID_HARDWARE_SE401, /* need to ask for own id */
+	fops:           &vicam_fops,
+};
+
+/******************************************************************************
+ *
+ *  Some Routines
+ *
+ ******************************************************************************/
+
+/*
+Flash the led
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+info ("led on");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+info ("led off");
+vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
+vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
+*/
+
+static void vicam_bulk(struct urb *urb)
+{
+	struct usb_vicam *vicam = urb->context;
+
+	/*	if (!vicam || !vicam->dev || !vicam->used)
+		return;
+	*/
+
+	if (urb->status)
+		printk("vicam%d: nonzero read/write bulk status received: %d",
+			0, urb->status);
+
+	urb->actual_length = 0;
+	urb->dev = vicam->udev;
+
+	memcpy(buf2, buf+64, 0x1e480);
+	if (vicam->fbuf)
+		memcpy(vicam->fbuf, buf+64, 0x1e480);
+
+	if (!change_pending) {
+		if (usb_submit_urb(urb, GFP_ATOMIC))
+			dbg("failed resubmitting read urb");
+	} else {
+		change_pending = 0;
+		wake_up_interruptible(&vicam->wait);
+	}
+}
+
+static int vicam_parameters(struct usb_vicam *vicam)
+{
+	unsigned char req[0x10];
+	unsigned int shutter;
+	shutter = 10;
+
+	switch (vicam->win.width) {
+	case 512:
+	default:
+		memcpy(req, s512x242bw, 0x10);
+		break;
+	case 256:
+		memcpy(req, s256x242bw, 0x10);
+		break;
+	case 128:
+		memcpy(req, s128x122bw, 0x10);
+		break;
+	}
+
+
+	mdelay(10);
+	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
+	info ("led on");
+	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
+
+	mdelay(10);
+
+	shutter = vicam->win.contrast / 256;
+	if (shutter == 0)
+		shutter = 1;
+	printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );
+	req[0] = vicam->win.brightness /256;
+	shutter = 15600/shutter - 1;
+	req[6] = shutter & 0xff;
+	req[7] = (shutter >> 8) & 0xff;
+	vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
+	mdelay(10);
+	vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
+	mdelay(10);
+
+	return 0;
+}
+
+static int vicam_init(struct usb_vicam *vicam)
+{
+	int width[] = {128, 256, 512};
+	int height[] = {122, 242, 242};
+
+	dbg("vicam_init");
+	buf = kmalloc(0x1e480, GFP_KERNEL);
+	buf2 = kmalloc(0x1e480, GFP_KERNEL);
+	if ((!buf) || (!buf2)) {
+		printk("Not enough memory for vicam!\n");
+		goto error;
+	}
+
+	/* do we do aspect correction in kernel or not? */
+	vicam->sizes = 3;
+	vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+	vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
+	memcpy(vicam->width, &width, sizeof(width));
+	memcpy(vicam->height, &height, sizeof(height));
+	vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
+
+	/* Download firmware to camera */
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
+	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
+
+	vicam_parameters(vicam);
+
+	FILL_BULK_URB(vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
+		      buf, 0x1e480, vicam_bulk, vicam);
+	printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
+
+	return 0;
+error:
+	if (buf)
+		kfree(buf);
+	if (buf2)
+		kfree(buf2);
+	return 1;
+}
+
+static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
+	const struct usb_device_id *id)
+{
+	struct usb_vicam *vicam;
+	char *camera_name=NULL;
+
+	dbg("vicam_probe");
+
+	/* See if the device offered us matches what we can accept */
+	if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
+	    (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
+		return NULL;
+	}
+	
+	camera_name="3Com HomeConnect USB";
+	info("ViCAM camera found: %s", camera_name);
+	
+	vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
+	if (vicam == NULL) {
+		err ("couldn't kmalloc vicam struct");
+		return NULL;
+	}
+	memset(vicam, 0, sizeof(*vicam));
+
+	vicam->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!vicam->readurb) {
+		kfree(vicam);
+		return NULL;
+	}
+
+	vicam->udev = udev;
+	vicam->camera_name = camera_name;
+	vicam->win.brightness = 128;
+	vicam->win.contrast = 10;
+
+	/* FIXME */
+	if (vicam_init(vicam)) {
+		usb_free_urb(vicam->readurb);
+		kfree(vicam);
+		return NULL;
+	}
+	memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
+	memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
+	
+	if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
+		err("video_register_device");
+		usb_free_urb(vicam->readurb);
+		kfree(vicam);
+		return NULL;
+	}
+
+	info("registered new video device: video%d", vicam->vdev.minor);
+	
+	init_MUTEX (&vicam->sem);
+	init_waitqueue_head(&vicam->wait);
+	
+	return vicam;
+}
+
+
+/* FIXME - vicam_disconnect - important */
+static void vicam_disconnect(struct usb_device *udev, void *ptr)
+{
+	struct usb_vicam *vicam;
+
+	vicam = (struct usb_vicam *) ptr;
+
+	video_unregister_device(&vicam->vdev);
+	vicam->udev = NULL;
+/*
+	vicam->frame[0].grabstate = FRAME_ERROR;
+	vicam->frame[1].grabstate = FRAME_ERROR;
+*/
+
+	/* Free buffers and shit */
+
+	info("%s disconnected", vicam->camera_name);
+	synchronize(vicam);
+
+	if (!vicam->open_count) {
+		/* Other random junk */
+		usb_free_urb(vicam->readurb);
+		kfree(vicam);
+		vicam = NULL;
+	}
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vicam_driver = {
+	owner:		THIS_MODULE,
+	name:		"vicam",
+	probe:		vicam_probe,
+	disconnect:	vicam_disconnect,
+	id_table:	vicam_table,
+};
+
+/******************************************************************************
+ *
+ *  Module Routines
+ *
+ ******************************************************************************/
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/* Module paramaters */
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+static int __init usb_vicam_init(void)
+{
+	int result;
+
+	printk("VICAM: initializing\n");
+	/* register this driver with the USB subsystem */
+	result = usb_register(&vicam_driver);
+	if (result < 0) {
+		err("usb_register failed for the "__FILE__" driver. Error number %d",
+		    result);
+		return -1;
+	}
+
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+	return 0;
+}
+
+static void __exit usb_vicam_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&vicam_driver);
+}
+
+module_init(usb_vicam_init);
+module_exit(usb_vicam_exit);
+
diff -Nru a/drivers/usb/media/vicam.h b/drivers/usb/media/vicam.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/vicam.h	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,81 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ * 
+ */
+
+#ifndef __LINUX_VICAM_H
+#define __LINUX_VICAM_H
+
+
+#ifdef CONFIG_USB_DEBUG
+	static int debug = 1;
+#else
+	static int debug;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+
+#define VICAM_NUMFRAMES 30
+#define VICAM_NUMSBUF 1
+
+/* USB REQUEST NUMBERS */
+#define VICAM_REQ_VENDOR	0xff
+#define VICAM_REQ_CAMERA_POWER	0x50
+#define VICAM_REQ_CAPTURE	0x51
+#define VICAM_REQ_LED_CONTROL	0x55
+#define VICAM_REQ_GET_SOMETHIN	0x56
+ 
+/* not required but lets you know camera is on */
+/* camera must be on to turn on led */
+/* 0x01 always on  0x03 on when picture taken (flashes) */
+
+struct picture_parm
+{
+	int width;
+	int height;
+	int brightness;
+	int hue;
+	int colour;
+	int contrast;
+	int whiteness;
+	int depth;
+	int palette;
+};
+
+struct vicam_scratch {
+        unsigned char *data;
+        volatile int state;
+        int offset;
+        int length;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct usb_vicam
+{
+	struct video_device vdev;
+	struct usb_device *udev;
+
+	int open_count;	/* number of times this port has been opened */
+	struct semaphore sem;			/* locks this structure */
+	wait_queue_head_t wait;			/* Processes waiting */ 
+
+	int streaming;
+
+	/* v4l stuff */
+	char *camera_name;
+	char *fbuf;
+	struct urb *urb[VICAM_NUMSBUF];
+	int sizes;
+	int *width;
+	int *height;
+	int maxframesize;
+	struct picture_parm win;
+	struct proc_dir_entry *proc_entry;      /* /proc/se401/videoX */
+	struct urb *readurb;
+};
+
+#endif
diff -Nru a/drivers/usb/media/vicamurbs.h b/drivers/usb/media/vicamurbs.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/media/vicamurbs.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,330 @@
+/*
+ *
+ * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
+ * Christopher L Cheney (C) 2001
+ * 
+ */
+
+
+#ifndef __LINUX_VICAMURBS_H
+#define __LINUX_VICAMURBS_H
+
+/* -------------------------------------------------------------------------- */
+
+/* FIXME - Figure out transfers so that this doesn't need to be here
+ *
+ * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */
+
+/* Request 0x51 Image Setup */
+
+/* 128x98 ? 0x3180 size */
+static unsigned char s128x98bw[] = {
+  0,    0x34, 0xC4, 0x00, 0x00, 0x00, 0,    0,
+  0x18, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 128x122 3D80 size */
+static unsigned char s128x122bw[] = {
+  0,    0x34, 0xF4, 0x00, 0x00, 0x00, 0,    0,
+  0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 256x242 ? 0xF280 size */
+static unsigned char s256x242bw[] = {
+  0,    0x03, 0xC8, 0x03, 0x00, 0x00, 0,    0,
+  0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* 512x242 0x1E480 size */
+static unsigned char s512x242bw[] = {
+  0,    0x05, 0x90, 0x07, 0x00, 0x00, 0,    0,
+  0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
+};
+
+/* In s512x242:
+   byte 0: gain -- higher number means brighter image
+   byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000).
+*/
+
+/* -------------------------------------------------------------------------- */
+
+static unsigned char fsetup[] = {
+  0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64,
+
+  0x00, 0x00
+};
+
+static unsigned char firmware1[] = {
+  0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64,
+
+  0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09,
+  0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03,
+  0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07,
+  0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
+};
+
+static unsigned char findex1[] = {
+  0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64,
+
+  0x18, 0x00, 0x00, 0x00
+};
+
+static unsigned char firmware2[] = {
+  0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64,
+
+  0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07,
+  0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01,
+  0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00,
+  0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07,
+  0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00,
+  0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0,
+  0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07,
+  0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00,
+  0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0,
+  0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87,
+  0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09,
+  0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0,
+  0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01,
+  0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07,
+  0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0,
+  0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00,
+  0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77,
+  0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57,
+  0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57,
+  0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF,
+  0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05,
+  0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF,
+  0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00,
+  0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01,
+  0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09,
+  0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06,
+  0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0,
+  0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09,
+  0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06,
+  0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06,
+  0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00,
+  0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF,
+  0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07,
+  0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05,
+  0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17,
+  0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06,
+  0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00,
+  0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57,
+  0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03,
+  0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF,
+  0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07,
+  0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00,
+  0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00,
+  0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02,
+  0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57,
+  0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00,
+  0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02,
+  0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90,
+  0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B,
+  0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF,
+  0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07,
+  0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF,
+  0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E,
+  0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00,
+  0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67,
+  0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD,
+  0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0,
+  0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF,
+  0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0,
+  0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00,
+  0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0,
+  0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00,
+  0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00,
+  0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+  0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02,
+  0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0,
+  0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+  0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1,
+  0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF,
+  0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF,
+  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07,
+  0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF,
+  0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06,
+  0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67,
+  0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00,
+  0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0,
+  0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF,
+  0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+  0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02,
+  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+  0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C,
+  0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00,
+  0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
+  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
+  0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02,
+  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
+  0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF,
+  0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF,
+  0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B,
+  0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+  0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF,
+  0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00,
+  0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06,
+  0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02,
+  0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF,
+  0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05,
+  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07,
+  0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06,
+  0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01,
+  0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07,
+  0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07,
+  0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01,
+  0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0,
+  0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06,
+  0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06,
+  0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06,
+  0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00,
+  0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05,
+  0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05,
+  0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA,
+  0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1,
+  0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00,
+  0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00,
+  0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05,
+  0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF,
+  0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57,
+  0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07,
+  0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
+  0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
+  0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
+  0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67,
+  0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0,
+  0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00,
+  0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00,
+  0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00,
+  0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05,
+  0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8,
+  0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05,
+  0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07,
+  0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05,
+  0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B,
+  0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17,
+  0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07,
+  0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09,
+  0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1,
+  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00,
+  0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05,
+  0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05,
+  0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07,
+  0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
+  0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF,
+  0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9,
+  0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00,
+  0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0,
+  0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67,
+  0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA,
+  0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0,
+  0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87,
+  0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF,
+  0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0,
+  0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF,
+  0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0,
+  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
+  0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+  0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05,
+  0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67,
+  0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87,
+  0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07,
+  0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67,
+  0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
+  0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0,
+  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA,
+  0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00,
+  0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
+  0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1,
+  0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF,
+  0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77,
+  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+  0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77,
+  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
+  0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80,
+  0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char findex2[] = {
+  0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64,
+
+  0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00,
+  0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00,
+  0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00,
+  0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00,
+  0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00,
+  0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00,
+  0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01,
+  0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01,
+  0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01,
+  0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01,
+  0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01,
+  0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01,
+  0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01,
+  0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01,
+  0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02,
+  0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02,
+  0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02,
+  0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02,
+  0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02,
+  0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02,
+  0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02,
+  0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02,
+  0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03,
+  0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03,
+  0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03,
+  0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03,
+  0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03,
+  0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03,
+  0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03,
+  0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04,
+  0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04,
+  0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04,
+  0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04,
+  0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04,
+  0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04,
+  0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04,
+  0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04,
+  0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
+};
+
+#endif
diff -Nru a/drivers/usb/microtek.c b/drivers/usb/microtek.c
--- a/drivers/usb/microtek.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1065 +0,0 @@
-/* Driver for Microtek Scanmaker X6 USB scanner, and possibly others.
- *
- * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com>
- * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
- *
- * Parts shamelessly stolen from usb-storage and copyright by their
- * authors. Thanks to Matt Dharm for giving us permission!
- *
- * This driver implements a SCSI host controller driver and a USB
- * device driver. To avoid confusion, all the USB related stuff is
- * prefixed by mts_usb_ and all the SCSI stuff by mts_scsi_.
- *
- * Microtek (www.microtek.com) did not release the specifications for
- * their USB protocol to us, so we had to reverse engineer them. We
- * don't know for which models they are valid.
- *
- * The X6 USB has three bulk endpoints, one output (0x1) down which
- * commands and outgoing data are sent, and two input: 0x82 from which
- * normal data is read from the scanner (in packets of maximum 32
- * bytes) and from which the status byte is read, and 0x83 from which
- * the results of a scan (or preview) are read in up to 64 * 1024 byte
- * chunks by the Windows driver. We don't know how much it is possible
- * to read at a time from 0x83.
- *
- * It seems possible to read (with URB transfers) everything from 0x82
- * in one go, without bothering to read in 32 byte chunks.
- *
- * There seems to be an optimisation of a further READ implicit if
- * you simply read from 0x83.
- *
- * Guessed protocol:
- *
- *	Send raw SCSI command to EP 0x1
- *
- *	If there is data to receive:
- *		If the command was READ datatype=image:
- *			Read a lot of data from EP 0x83
- *		Else:
- *			Read data from EP 0x82
- *	Else:
- *		If there is data to transmit:
- *			Write it to EP 0x1
- *
- *	Read status byte from EP 0x82
- *
- * References:
- *
- * The SCSI command set for the scanner is available from
- *	ftp://ftp.microtek.com/microtek/devpack/
- *
- * Microtek NV sent us a more up to date version of the document. If
- * you want it, just send mail.
- *
- * Status:
- *
- *	Untested with multiple scanners.
- *	Untested on SMP.
- *	Untested on a bigendian machine.
- *
- * History:
- *
- *	20000417 starting history
- *	20000417 fixed load oops
- *	20000417 fixed unload oops
- *	20000419 fixed READ IMAGE detection
- *	20000424 started conversion to use URBs
- *	20000502 handled short transfers as errors
- *	20000513 rename and organisation of functions (john)
- *	20000513 added IDs for all products supported by Windows driver (john)
- *	20000514 Rewrote mts_scsi_queuecommand to use URBs (john)
- *	20000514 Version 0.0.8j
- *      20000514 Fix reporting of non-existant devices to SCSI layer (john)
- *	20000514 Added MTS_DEBUG_INT (john)
- *	20000514 Changed "usb-microtek" to "microtek" for consistency (john)
- *	20000514 Stupid bug fixes (john)
- *	20000514 Version 0.0.9j
- *	20000515 Put transfer context and URB in mts_desc (john)
- *	20000515 Added prelim turn off debugging support (john)
- *	20000515 Version 0.0.10j
- *      20000515 Fixed up URB allocation (clear URB on alloc) (john)
- *      20000515 Version 0.0.11j
- *	20000516 Removed unnecessary spinlock in mts_transfer_context (john)
- *	20000516 Removed unnecessary up on instance lock in mts_remove_nolock (john)
- *	20000516 Implemented (badly) scsi_abort (john)
- *	20000516 Version 0.0.12j
- *      20000517 Hopefully removed mts_remove_nolock quasideadlock (john)
- *      20000517 Added mts_debug_dump to print ll USB info (john)
- *	20000518 Tweaks and documentation updates (john)
- *	20000518 Version 0.0.13j
- *	20000518 Cleaned up abort handling (john)
- *	20000523 Removed scsi_command and various scsi_..._resets (john)
- *	20000523 Added unlink URB on scsi_abort, now OHCI supports it (john)
- *	20000523 Fixed last tiresome compile warning (john)
- *	20000523 Version 0.0.14j (though version 0.1 has come out?)
- *	20000602 Added primitive reset
- *	20000602 Version 0.2.0
- *	20000603 various cosmetic changes
- *	20000603 Version 0.2.1
- *	20000620 minor cosmetic changes
- *	20000620 Version 0.2.2
- *	20000822 Hopefully fixed deadlock in mts_remove_nolock()
- *	20000822 Fixed minor race in mts_transfer_cleanup()
- *	20000822 Fixed deadlock on submission error in queuecommand
- *	20000822 Version 0.2.3
- *	20000913 Reduced module size if debugging is off
- *	20000913 Version 0.2.4
- *      20010210 New abort logic
- *      20010210 Version 0.3.0
- *	20010217 Merged scatter/gather
- *	20010218 Version 0.4.0
- *	20010218 Cosmetic fixes
- *	20010218 Version 0.4.1
- *      20010306 Abort while using scatter/gather
- *      20010306 Version 0.4.2
- *      20010311 Remove all timeouts and tidy up generally (john)
- *	20010320 check return value of scsi_register()
- *	20010320 Version 0.4.3
- *	20010408 Identify version on module load.
- *	20011003 Fix multiple requests
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-#include <linux/proc_fs.h>
-
-#include <asm/atomic.h>
-#include <linux/blk.h>
-#include "../scsi/scsi.h"
-#include "../scsi/hosts.h"
-#include "../scsi/sd.h"
-
-#include "microtek.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.4.3"
-#define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"
-#define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
-
-/* Should we do debugging? */
-
-//#define MTS_DO_DEBUG
-
-/* USB layer driver interface */
-
-static void *mts_usb_probe(struct usb_device *dev, unsigned int interface,
-			 const struct usb_device_id *id);
-static void mts_usb_disconnect(struct usb_device *dev, void *ptr);
-
-static struct usb_device_id mts_usb_ids [];
-
-static struct usb_driver mts_usb_driver = {
-	name:		"microtekX6",
-	probe:		mts_usb_probe,
-	disconnect:	mts_usb_disconnect,
-	id_table:	mts_usb_ids,
-};
-
-
-/* Internal driver stuff */
-
-#define MTS_VERSION	"0.4.3"
-#define MTS_NAME	"microtek usb (rev " MTS_VERSION "): "
-
-#define MTS_WARNING(x...) \
-	printk( KERN_WARNING MTS_NAME x )
-#define MTS_ERROR(x...) \
-	printk( KERN_ERR MTS_NAME x )
-#define MTS_INT_ERROR(x...) \
-	MTS_ERROR(x)
-#define MTS_MESSAGE(x...) \
-	printk( KERN_INFO MTS_NAME x )
-
-#if defined MTS_DO_DEBUG
-
-#define MTS_DEBUG(x...) \
-	printk( KERN_DEBUG MTS_NAME x )
-
-#define MTS_DEBUG_GOT_HERE() \
-	MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
-#define MTS_DEBUG_INT() \
-	do { MTS_DEBUG_GOT_HERE(); \
-	     MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
-	     MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
-             mts_debug_dump(context->instance);\
-	   } while(0)
-#else
-
-#define MTS_NUL_STATEMENT do { } while(0)
-
-#define MTS_DEBUG(x...)	MTS_NUL_STATEMENT
-#define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT
-#define MTS_DEBUG_INT() MTS_NUL_STATEMENT
-
-#endif
-
-
-
-#define MTS_INT_INIT()\
-	struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context; \
-	MTS_DEBUG_INT();\
-
-#ifdef MTS_DO_DEBUG
-
-static inline void mts_debug_dump(struct mts_desc* desc) {
-	MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n",
-		  (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
-		  (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
-		);
-	MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
-		  usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
-		  usb_rcvbulkpipe(desc->usb_dev,desc->ep_response),
-		  usb_rcvbulkpipe(desc->usb_dev,desc->ep_image)
-		);
-}
-
-
-static inline void mts_show_command(Scsi_Cmnd *srb)
-{
-	char *what = NULL;
-
-	switch (srb->cmnd[0]) {
-	case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
-	case REZERO_UNIT: what = "REZERO_UNIT"; break;
-	case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
-	case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
-	case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
-	case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
-	case READ_6: what = "READ_6"; break;
-	case WRITE_6: what = "WRITE_6"; break;
-	case SEEK_6: what = "SEEK_6"; break;
-	case READ_REVERSE: what = "READ_REVERSE"; break;
-	case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
-	case SPACE: what = "SPACE"; break;
-	case INQUIRY: what = "INQUIRY"; break;
-	case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
-	case MODE_SELECT: what = "MODE_SELECT"; break;
-	case RESERVE: what = "RESERVE"; break;
-	case RELEASE: what = "RELEASE"; break;
-	case COPY: what = "COPY"; break;
-	case ERASE: what = "ERASE"; break;
-	case MODE_SENSE: what = "MODE_SENSE"; break;
-	case START_STOP: what = "START_STOP"; break;
-	case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
-	case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
-	case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
-	case SET_WINDOW: what = "SET_WINDOW"; break;
-	case READ_CAPACITY: what = "READ_CAPACITY"; break;
-	case READ_10: what = "READ_10"; break;
-	case WRITE_10: what = "WRITE_10"; break;
-	case SEEK_10: what = "SEEK_10"; break;
-	case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
-	case VERIFY: what = "VERIFY"; break;
-	case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
-	case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
-	case SEARCH_LOW: what = "SEARCH_LOW"; break;
-	case SET_LIMITS: what = "SET_LIMITS"; break;
-	case READ_POSITION: what = "READ_POSITION"; break;
-	case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
-	case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
-	case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
-	case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
-	case COMPARE: what = "COMPARE"; break;
-	case COPY_VERIFY: what = "COPY_VERIFY"; break;
-	case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
-	case READ_BUFFER: what = "READ_BUFFER"; break;
-	case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
-	case READ_LONG: what = "READ_LONG"; break;
-	case WRITE_LONG: what = "WRITE_LONG"; break;
-	case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
-	case WRITE_SAME: what = "WRITE_SAME"; break;
-	case READ_TOC: what = "READ_TOC"; break;
-	case LOG_SELECT: what = "LOG_SELECT"; break;
-	case LOG_SENSE: what = "LOG_SENSE"; break;
-	case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
-	case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
-	case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
-	case READ_12: what = "READ_12"; break;
-	case WRITE_12: what = "WRITE_12"; break;
-	case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
-	case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
-	case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
-	case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
-	case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
-	case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
-	case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
-	default:
-		MTS_DEBUG("can't decode command\n");
-		goto out;
-		break;
-	}
-	MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len);
-
- out:
-	MTS_DEBUG( "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-	       srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
-	       srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
-}
-
-#else
-
-static inline void mts_show_command(Scsi_Cmnd * dummy)
-{
-}
-
-static inline void mts_debug_dump(struct mts_desc* dummy)
-{
-}
-
-#endif
-
-static inline void mts_urb_abort(struct mts_desc* desc) {
-	MTS_DEBUG_GOT_HERE();
-	mts_debug_dump(desc);
-
-	usb_unlink_urb( desc->urb );
-}
-
-static struct mts_desc * mts_list; /* list of active scanners */
-struct semaphore mts_list_semaphore;
-
-/* Internal list operations */
-
-static
-void mts_remove_nolock( struct mts_desc* to_remove )
-{
-	MTS_DEBUG( "removing 0x%x from list\n",
-		   (int)to_remove );
-
-	lock_kernel();
-	mts_urb_abort(to_remove);
-
-	MTS_DEBUG_GOT_HERE();
-
-	if ( to_remove != mts_list ) {
-		MTS_DEBUG_GOT_HERE();
-		if (to_remove->prev && to_remove->next)
-			to_remove->prev->next = to_remove->next;
-	} else {
-		MTS_DEBUG_GOT_HERE();
-		mts_list = to_remove->next;
-		if (mts_list) {
-			MTS_DEBUG_GOT_HERE();
-			mts_list->prev = 0;
-		}
-	}
-
-	if ( to_remove->next ) {
-		MTS_DEBUG_GOT_HERE();
-		to_remove->next->prev = to_remove->prev;
-	}
-
-	MTS_DEBUG_GOT_HERE();
-	scsi_unregister_host(&to_remove->ctempl);
-	unlock_kernel();
-
-	usb_free_urb(to_remove->urb);
-	kfree( to_remove );
-}
-
-static
-void mts_add_nolock( struct mts_desc* to_add )
-{
-	MTS_DEBUG( "adding 0x%x to list\n", (int)to_add );
-
-	to_add->prev = 0;
-	to_add->next = mts_list;
-	if ( mts_list ) {
-		mts_list->prev = to_add;
-	}
-
-	mts_list = to_add;
-}
-
-
-
-
-/* SCSI driver interface */
-
-/* scsi related functions - dummies for now mostly */
-
-static int mts_scsi_release(struct Scsi_Host *psh)
-{
-	MTS_DEBUG_GOT_HERE();
-
-	return 0;
-}
-
-static int mts_scsi_abort (Scsi_Cmnd *srb)
-{
-	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
-
-	MTS_DEBUG_GOT_HERE();
-
-	mts_urb_abort(desc);
-
-	return SCSI_ABORT_PENDING;
-}
-
-static int mts_scsi_host_reset (Scsi_Cmnd *srb)
-{
-	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
-
-	MTS_DEBUG_GOT_HERE();
-	mts_debug_dump(desc);
-
-	usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */
-	return 0;  /* RANT why here 0 and not SUCCESS */
-}
-
-/* the core of the scsi part */
-
-/* faking a detection - which can't fail :-) */
-
-static int mts_scsi_detect (struct SHT * sht)
-{
-	/* Whole function stolen from usb-storage */
-
-	struct mts_desc * desc = (struct mts_desc *)sht->proc_dir;
-	/* What a hideous hack! */
-
-	char local_name[48];
-
-	MTS_DEBUG_GOT_HERE();
-
-	/* set up the name of our subdirectory under /proc/scsi/ */
-	sprintf(local_name, "microtek-%d", desc->host_number);
-	sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL);
-	/* FIXME: where is this freed ? */
-
-	if (!sht->proc_name) {
-		MTS_ERROR( "unable to allocate memory for proc interface!!\n" );
-		return 0;
-	}
-
-	strcpy(sht->proc_name, local_name);
-
- 	sht->proc_dir = NULL;
-
-	/* In host->hostdata we store a pointer to desc */
-	desc->host = scsi_register(sht, sizeof(desc));
-	if (desc->host == NULL) {
-		MTS_ERROR("Cannot register due to low memory");
-		kfree(sht->proc_name);
-		return 0;
-	}
-	desc->host->hostdata[0] = (unsigned long)desc;
-/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
-
-	return 1;
-}
-
-
-
-/* Main entrypoint: SCSI commands are dispatched to here */
-
-
-
-static
-int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
-
-static void mts_transfer_cleanup( struct urb *transfer );
-static void mts_do_sg(struct urb * transfer);
-
-
-inline static
-void mts_int_submit_urb (struct urb* transfer,
-			int pipe,
-			void* data,
-			unsigned length,
-			mts_usb_urb_callback callback )
-/* Interrupt context! */
-
-/* Holding transfer->context->lock! */
-{
-	int res;
-
-	MTS_INT_INIT();
-
-	FILL_BULK_URB(transfer,
-		      context->instance->usb_dev,
-		      pipe,
-		      data,
-		      length,
-		      callback,
-		      context
-		);
-
-	transfer->status = 0;
-
-	res = usb_submit_urb( transfer, GFP_ATOMIC );
-	if ( unlikely(res) ) {
-		MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
-		context->srb->result = DID_ERROR << 16;
-		mts_transfer_cleanup(transfer);
-	}
-	return;
-}
-
-
-static void mts_transfer_cleanup( struct urb *transfer )
-/* Interrupt context! */
-{
-	MTS_INT_INIT();
-
-	if ( likely(context->final_callback != NULL) )
-		context->final_callback(context->srb);
-
-}
-
-static void mts_transfer_done( struct urb *transfer )
-{
-	MTS_INT_INIT();
-
-	context->srb->result &= MTS_SCSI_ERR_MASK;
-	context->srb->result |= (unsigned)context->status<<1;
-
-	mts_transfer_cleanup(transfer);
-
-	return;
-}
-
-
-static void mts_get_status( struct urb *transfer )
-/* Interrupt context! */
-{
-	MTS_INT_INIT();
-
-	mts_int_submit_urb(transfer,
-			   usb_rcvbulkpipe(context->instance->usb_dev,
-					   context->instance->ep_response),
-			   &context->status,
-			   1,
-			   mts_transfer_done );
-}
-
-static void mts_data_done( struct urb* transfer )
-/* Interrupt context! */
-{
-	MTS_INT_INIT();
-
-	if ( context->data_length != transfer->actual_length ) {
-		context->srb->resid = context->data_length - transfer->actual_length;
-	} else if ( unlikely(transfer->status) ) {
-		context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
-	}
-
-	mts_get_status(transfer);
-
-	return;
-}
-
-
-static void mts_command_done( struct urb *transfer )
-/* Interrupt context! */
-{
-	MTS_INT_INIT();
-
-	if ( unlikely(transfer->status) ) {
-	        if (transfer->status == -ENOENT) {
-		        /* We are being killed */
-			MTS_DEBUG_GOT_HERE();
-			context->srb->result = DID_ABORT<<16;
-                } else {
-		        /* A genuine error has occured */
-			MTS_DEBUG_GOT_HERE();
-
-		        context->srb->result = DID_ERROR<<16;
-                }
-		mts_transfer_cleanup(transfer);
-
-		return;
-	}
-
-	if ( context->data ) {
-		mts_int_submit_urb(transfer,
-				   context->data_pipe,
-				   context->data,
-				   context->data_length,
-				   context->srb->use_sg ? mts_do_sg : mts_data_done);
-	} else mts_get_status(transfer);
-
-	return;
-}
-
-static void mts_do_sg (struct urb* transfer)
-{
-	struct scatterlist * sg;
-	MTS_INT_INIT();
-	
-	MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
-
-	if (unlikely(transfer->status)) {
-                context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
-		mts_transfer_cleanup(transfer);
-        }
-
-	sg = context->srb->buffer;
-	context->fragment++;
-	mts_int_submit_urb(transfer,
-			   context->data_pipe,
-			   page_address(sg[context->fragment].page) +
-			   sg[context->fragment].offset,
-			   sg[context->fragment].length,
-			   context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
-	return;
-}
-
-static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 };
-static const u8 mts_read_image_sig_len = 4;
-static const unsigned char mts_direction[256/8] = {
-	0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
-	0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
-#define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
-
-static void
-mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
-{
-	int pipe;
-	struct scatterlist * sg;
-	
-	MTS_DEBUG_GOT_HERE();
-
-	desc->context.instance = desc;
-	desc->context.srb = srb;
-	desc->context.fragment = 0;
-
-	if (!srb->use_sg) {
-		if ( !srb->bufflen ){
-			desc->context.data = 0;
-			desc->context.data_length = 0;
-			return;
-		} else {
-			desc->context.data = srb->buffer;
-			desc->context.data_length = srb->bufflen;
-			MTS_DEBUG("length = %d or %d\n",
-				  srb->request_bufflen, srb->bufflen);
-		}
-	} else {
-		MTS_DEBUG("Using scatter/gather\n");
-		sg = srb->buffer;
-		desc->context.data = page_address(sg[0].page) + sg[0].offset;
-		desc->context.data_length = sg[0].length;
-	}
-
-
-	/* can't rely on srb->sc_data_direction */
-
-	/* Brutally ripped from usb-storage */
-
-	if ( !memcmp( srb->cmnd, mts_read_image_sig, mts_read_image_sig_len )
-) { 		pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_image);
-		MTS_DEBUG( "transfering from desc->ep_image == %d\n",
-			   (int)desc->ep_image );
-	} else if ( MTS_DIRECTION_IS_IN(srb->cmnd[0]) ) {
-			pipe = usb_rcvbulkpipe(desc->usb_dev,desc->ep_response);
-			MTS_DEBUG( "transfering from desc->ep_response == %d\n",
-				   (int)desc->ep_response);
-	} else {
-		MTS_DEBUG("transfering to desc->ep_out == %d\n",
-			  (int)desc->ep_out);
-		pipe = usb_sndbulkpipe(desc->usb_dev,desc->ep_out);
-	}
-	desc->context.data_pipe = pipe;
-}
-
-
-static
-int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
-{
-	struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
-	int err = 0;
-	int res;
-
-	MTS_DEBUG_GOT_HERE();
-	mts_show_command(srb);
-	mts_debug_dump(desc);
-
-	if ( srb->device->lun || srb->device->id || srb->device->channel ) {
-
-		MTS_DEBUG("Command to LUN=%d ID=%d CHANNEL=%d from SCSI layer\n",(int)srb->device->lun,(int)srb->device->id, (int)srb->device->channel );
-
-		MTS_DEBUG("this device doesn't exist\n");
-
-		srb->result = DID_BAD_TARGET << 16;
-
-		if(likely(callback != NULL))
-			callback(srb);
-
-		goto out;
-	}
-
-	
-	FILL_BULK_URB(desc->urb,
-		      desc->usb_dev,
-		      usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
-		      srb->cmnd,
-		      srb->cmd_len,
-		      mts_command_done,
-		      &desc->context
-		      );
-
-
-	mts_build_transfer_context( srb, desc );
-	desc->context.final_callback = callback;
-	
-	/* here we need ATOMIC as we are called with the iolock */
-	res=usb_submit_urb(desc->urb, GFP_ATOMIC);
-
-	if(unlikely(res)){
-		MTS_ERROR("error %d submitting URB\n",(int)res);
-		srb->result = DID_ERROR << 16;
-
-		if(likely(callback != NULL))
-			callback(srb);
-
-	}
-
-out:
-	return err;
-}
-/*
- * this defines our 'host'
- */
-
-/* NOTE: This is taken from usb-storage, should be right. */
-
-
-static Scsi_Host_Template mts_scsi_host_template = {
-	name:           "microtekX6",
-	detect:		mts_scsi_detect,
-	release:	mts_scsi_release,
-	queuecommand:	mts_scsi_queuecommand,
-
-	eh_abort_handler:	mts_scsi_abort,
-	eh_host_reset_handler:	mts_scsi_host_reset,
-
-	sg_tablesize:		SG_ALL,
-	can_queue:		1,
-	this_id:		-1,
-	cmd_per_lun:		1,
-	present:		0,
-	unchecked_isa_dma:	FALSE,
-	use_clustering:		TRUE,
-	emulated:		TRUE
-};
-
-
-/* USB layer driver interface implementation */
-
-static void mts_usb_disconnect (struct usb_device *dev, void *ptr)
-{
-	struct mts_desc* to_remove = (struct mts_desc*)ptr;
-
-	MTS_DEBUG_GOT_HERE();
-
-	/* leave the list - lock it */
-	down(&mts_list_semaphore);
-
-	mts_remove_nolock(to_remove);
-
-	up(&mts_list_semaphore);
-}
-
-struct vendor_product
-{
-	char* name;
-	enum
-	{
-		mts_sup_unknown=0,
-		mts_sup_alpha,
-		mts_sup_full
-	}
-	support_status;
-} ;
-
-
-/* These are taken from the msmUSB.inf file on the Windows driver CD */
-const static struct vendor_product mts_supported_products[] =
-{
-	{ "Phantom 336CX",	mts_sup_unknown},
-	{ "Phantom 336CX",	mts_sup_unknown},
-	{ "Scanmaker X6",	mts_sup_alpha},
-	{ "Phantom C6",		mts_sup_unknown},
-	{ "Phantom 336CX",	mts_sup_unknown},
-	{ "ScanMaker V6USL",	mts_sup_unknown},
-	{ "ScanMaker V6USL",	mts_sup_unknown},
-	{ "Scanmaker V6UL",	mts_sup_unknown},
-	{ "Scanmaker V6UPL",	mts_sup_alpha},
-};
-
-/* The entries of microtek_table must correspond, line-by-line to
-   the entries of mts_supported_products[]. */
-
-static struct usb_device_id mts_usb_ids [] =
-{
-	{ USB_DEVICE(0x4ce, 0x0300) },
-	{ USB_DEVICE(0x5da, 0x0094) },
-	{ USB_DEVICE(0x5da, 0x0099) },
-	{ USB_DEVICE(0x5da, 0x009a) },
-	{ USB_DEVICE(0x5da, 0x00a0) },
-	{ USB_DEVICE(0x5da, 0x00a3) },
-	{ USB_DEVICE(0x5da, 0x80a3) },
-	{ USB_DEVICE(0x5da, 0x80ac) },
-	{ USB_DEVICE(0x5da, 0x00b6) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, mts_usb_ids);
-
-
-static void * mts_usb_probe (struct usb_device *dev, unsigned int interface,
-			     const struct usb_device_id *id)
-{
-	int i;
-	int result;
-	int ep_out = -1;
-	int ep_in_set[3]; /* this will break if we have more than three endpoints
-			   which is why we check */
-	int *ep_in_current = ep_in_set;
-
-	struct mts_desc * new_desc;
-	struct vendor_product const* p;
-
-	/* the altsettting 0 on the interface we're probing */
-	struct usb_interface_descriptor *altsetting;
-
-	MTS_DEBUG_GOT_HERE();
-	MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev );
-
-	MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n",
-		   (int)dev->descriptor.idProduct,
-		   (int)dev->descriptor.idVendor );
-
-	MTS_DEBUG_GOT_HERE();
-
-	p = &mts_supported_products[id - mts_usb_ids];
-
-	MTS_DEBUG_GOT_HERE();
-
-	MTS_DEBUG( "found model %s\n", p->name );
-	if ( p->support_status != mts_sup_full )
-		MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n",
-			     p->name );
-
-	/* the altsettting 0 on the interface we're probing */
-	altsetting =
-		&(dev->actconfig->interface[interface].altsetting[0]);
-
-
-	/* Check if the config is sane */
-
-	if ( altsetting->bNumEndpoints != MTS_EP_TOTAL ) {
-		MTS_WARNING( "expecting %d got %d endpoints! Bailing out.\n",
-			     (int)MTS_EP_TOTAL, (int)altsetting->bNumEndpoints );
-		return NULL;
-	}
-
-	for( i = 0; i < altsetting->bNumEndpoints; i++ ) {
-		if ((altsetting->endpoint[i].bmAttributes &
-		     USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
-
-			MTS_WARNING( "can only deal with bulk endpoints; endpoint %d is not bulk.\n",
-			     (int)altsetting->endpoint[i].bEndpointAddress );
-		} else {
-			if (altsetting->endpoint[i].bEndpointAddress &
-			    USB_DIR_IN)
-				*ep_in_current++
-					= altsetting->endpoint[i].bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK;
-			else {
-				if ( ep_out != -1 ) {
-					MTS_WARNING( "can only deal with one output endpoints. Bailing out." );
-					return NULL;
-				}
-
-				ep_out = altsetting->endpoint[i].bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK;
-			}
-		}
-
-	}
-
-
-	if ( ep_out == -1 ) {
-		MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
-		return NULL;
-	}
-
-
-	/* I don't understand the following fully (it's from usb-storage) -- John */
-
-	/* set the interface -- STALL is an acceptable response here */
-	result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0);
-
-	MTS_DEBUG("usb_set_interface returned %d.\n",result);
-	switch( result )
-	{
-	case 0: /* no error */
-		break;
-		
-	case -EPIPE:
-		usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
-		MTS_DEBUG( "clearing clearing stall on control interface\n" );
-		break;
-		
-	default:
-		MTS_DEBUG( "unknown error %d from usb_set_interface\n",
-			(int)result );
- 		return NULL;
-	}
-	
-	
-	/* allocating a new descriptor */
-	new_desc = (struct mts_desc *)kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
-	if (new_desc == NULL)
-	{
-		MTS_ERROR("couldn't allocate scanner desc, bailing out!\n");
-		return NULL;
-	}
-
-	memset( new_desc, 0, sizeof(*new_desc) );
-	new_desc->urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!new_desc->urb) {
-		kfree(new_desc);
-		return NULL;
-	}
-		
-	/* initialising that descriptor */
-	new_desc->usb_dev = dev;
-	new_desc->interface = interface;
-
-	init_MUTEX(&new_desc->lock);
-
-	if(mts_list){
-		new_desc->host_number = mts_list->host_number+1;
-	} else {
-		new_desc->host_number = 0;
-	}
-	
-	/* endpoints */
-	
-	new_desc->ep_out = ep_out;
-	new_desc->ep_response = ep_in_set[0];
-	new_desc->ep_image = ep_in_set[1];
-
-
-	if ( new_desc->ep_out != MTS_EP_OUT )
-		MTS_WARNING( "will this work? Command EP is not usually %d\n",
-			     (int)new_desc->ep_out );
-
-	if ( new_desc->ep_response != MTS_EP_RESPONSE )
-		MTS_WARNING( "will this work? Response EP is not usually %d\n",
-			     (int)new_desc->ep_response );
-
-	if ( new_desc->ep_image != MTS_EP_IMAGE )
-		MTS_WARNING( "will this work? Image data EP is not usually %d\n",
-			     (int)new_desc->ep_image );
-
-
-	/* Initialize the host template based on the default one */
-	memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template));
-	/* HACK from usb-storage - this is needed for scsi detection */
-	(struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */
-
-	MTS_DEBUG("registering SCSI module\n");
-
-	new_desc->ctempl.module = THIS_MODULE;
-	result = scsi_register_host(&new_desc->ctempl);
-	/* Will get hit back in microtek_detect by this func */
-	if ( result )
-	{
-		MTS_ERROR( "error %d from scsi_register_host! Help!\n",
-			   (int)result );
-
-		/* FIXME: need more cleanup? */
-		kfree( new_desc );
-		return NULL;
-	}
-	MTS_DEBUG_GOT_HERE();
-
-	/* FIXME: the bomb is armed, must the host be registered under lock ? */
-	/* join the list - lock it */
-	down(&mts_list_semaphore);
-
-	mts_add_nolock( new_desc );
-
-	up(&mts_list_semaphore);
-
-
-	MTS_DEBUG("completed probe and exiting happily\n");
-
-	return (void *)new_desc;
-}
-
-
-
-/* get us noticed by the rest of the kernel */
-
-int __init microtek_drv_init(void)
-{
-	int result;
-
-	MTS_DEBUG_GOT_HERE();
-	init_MUTEX(&mts_list_semaphore);
-
-	if ((result = usb_register(&mts_usb_driver)) < 0) {
-		MTS_DEBUG("usb_register returned %d\n", result );
-		return -1;
-	} else {
-		MTS_DEBUG("driver registered.\n");
-	}
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-}
-
-void __exit microtek_drv_exit(void)
-{
-	struct mts_desc* next;
-
-	MTS_DEBUG_GOT_HERE();
-
-	usb_deregister(&mts_usb_driver);
-
-	down(&mts_list_semaphore);
-
-	while (mts_list) {
-		/* keep track of where the next one is */
-		next = mts_list->next;
-
-		mts_remove_nolock( mts_list );
-
-		/* advance the list pointer */
-		mts_list = next;
-	}
-
-	up(&mts_list_semaphore);
-}
-
-module_init(microtek_drv_init);
-module_exit(microtek_drv_exit);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
-
diff -Nru a/drivers/usb/microtek.h b/drivers/usb/microtek.h
--- a/drivers/usb/microtek.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,60 +0,0 @@
- /*
- * Driver for Microtek Scanmaker X6 USB scanner and possibly others.
- * 
- * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com>
- * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
- *
- * See microtek.c for history
- *
- */
-
-typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *);
-typedef void (*mts_usb_urb_callback) (struct urb *);
-
-
-struct mts_transfer_context
-{
-	struct mts_desc* instance;
-	mts_scsi_cmnd_callback final_callback;
-	Scsi_Cmnd *srb;
-	
-	void* data;
-	unsigned data_length;
-	int data_pipe;
-	int fragment;
-
-	u8 status; /* status returned from ep_response after command completion */
-};
-
-
-struct mts_desc {
-	struct mts_desc *next;
-	struct mts_desc *prev;
-
-	struct usb_device *usb_dev;
-
-	int interface;
-
-	/* Endpoint addresses */
-	u8 ep_out;
-	u8 ep_response;
-	u8 ep_image;
-
-	struct Scsi_Host * host;
-	Scsi_Host_Template ctempl;
-	int host_number;
-
-	struct semaphore lock;
-
-	struct urb *urb;
-	struct mts_transfer_context context;
-};
-
-
-#define MTS_EP_OUT	0x1
-#define MTS_EP_RESPONSE	0x2
-#define MTS_EP_IMAGE	0x3
-#define MTS_EP_TOTAL	0x3
-
-#define MTS_SCSI_ERR_MASK ~0x3fu
-
diff -Nru a/drivers/usb/misc/Config.help b/drivers/usb/misc/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,76 @@
+CONFIG_USB_AUERSWALD
+  Say Y here if you want to connect an Auerswald USB ISDN Device
+  to your computer's USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called auerswald.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_EMI26
+  This driver loads firmware to Emagic EMI 2|6 low latency USB
+  Audio interface.
+
+  After firmware load the device is handled with standard linux
+  USB Audio driver.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called audio.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_RIO500
+  Say Y here if you want to connect a USB Rio500 mp3 player to your
+  computer's USB port. Please read <file:Documentation/usb/rio.txt>
+  for more information.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called rio500.o. If you want to compile it as
+  a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_TIGL
+  If you own a Texas Instruments graphing calculator and use a 
+  TI-GRAPH LINK USB cable (aka SilverLink), then you might be 
+  interested in this driver.
+
+  If you enable this driver, you will be able to communicate with
+  your calculator through a set of device nodes under /dev.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called tiglusb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  If you don't know what the SilverLink cable is or what a Texas
+  Instruments graphing calculator is, then you probably don't need this
+  driver.
+
+  If unsure, say N.
+
+CONFIG_USB_USS720
+  This driver is for USB parallel port adapters that use the Lucent
+  Technologies USS-720 chip. These cables are plugged into your USB
+  port and provide USB compatibility to peripherals designed with
+  parallel port interfaces.
+
+  The chip has two modes: automatic mode and manual mode. In automatic
+  mode, it looks to the computer like a standard USB printer. Only
+  printers may be connected to the USS-720 in this mode. The generic
+  USB printer driver ("USB Printer support", above) may be used in
+  that mode, and you can say N here if you want to use the chip only
+  in this mode.
+
+  Manual mode is not limited to printers, any parallel port
+  device should work. This driver utilizes manual mode.
+  Note however that some operations are three orders of magnitude
+  slower than on a PCI/ISA Parallel Port, so timing critical
+  applications might not work.
+
+  Say Y here if you own an USS-720 USB->Parport cable and intend to
+  connect anything other than a printer to it.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called uss720.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,14 @@
+#
+# Makefile for the rest of the USB drivers
+# (the ones that don't fit into any other categories)
+#
+
+O_TARGET	:= usb-misc.o
+
+obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
+obj-$(CONFIG_USB_EMI26)		+= emi26.o
+obj-$(CONFIG_USB_RIO500)	+= rio500.o
+obj-$(CONFIG_USB_TIGL)		+= tiglusb.o
+obj-$(CONFIG_USB_USS720)	+= uss720.o
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/auerswald.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,2188 @@
+/*****************************************************************************/
+/*
+ *      auerswald.c  --  Auerswald PBX/System Telephone usb driver.
+ *
+ *      Copyright (C) 2001  Wolfgang Mües (wmues@nexgo.de)
+ *
+ *      Very much code of this driver is borrowed from dabusb.c (Deti Fliegl)
+ *      and from the USB Skeleton driver (Greg Kroah-Hartman). Thank you.
+ *
+ *      This program is free software; you can redistribute it and/or 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.
+ */
+ /*****************************************************************************/
+
+/* Standard Linux module include files */
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
+#undef DEBUG   		/* include debug macros until it's done	*/
+#include <linux/usb.h>
+
+/*-------------------------------------------------------------------*/
+/* Debug support 						     */
+#ifdef DEBUG
+#define dump( adr, len) \
+do {			\
+	unsigned int u;	\
+	printk (KERN_DEBUG); \
+	for (u = 0; u < len; u++) \
+		printk (" %02X", adr[u] & 0xFF); \
+	printk ("\n"); \
+} while (0)
+#else
+#define dump( adr, len)
+#endif
+
+/*-------------------------------------------------------------------*/
+/* Version Information */
+#define DRIVER_VERSION "0.9.11"
+#define DRIVER_AUTHOR  "Wolfgang Mües <wmues@nexgo.de>"
+#define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
+
+/*-------------------------------------------------------------------*/
+/* Private declarations for Auerswald USB driver                     */
+
+/* Auerswald Vendor ID */
+#define ID_AUERSWALD  	0x09BF
+
+#ifndef AUER_MINOR_BASE		/* allow external override */
+#define AUER_MINOR_BASE	112	/* auerswald driver minor number */
+#endif
+
+/* we can have up to this number of device plugged in at once */
+#define AUER_MAX_DEVICES 16
+
+/* prefix for the device descriptors in /dev/usb */
+#define AU_PREFIX	"auer"
+
+/* Number of read buffers for each device */
+#define AU_RBUFFERS     10
+
+/* Number of chain elements for each control chain */
+#define AUCH_ELEMENTS   20
+
+/* Number of retries in communication */
+#define AU_RETRIES	10
+
+/*-------------------------------------------------------------------*/
+/* vendor specific protocol                                          */
+/* Header Byte */
+#define AUH_INDIRMASK   0x80    /* mask for direct/indirect bit */
+#define AUH_DIRECT      0x00    /* data is for USB device */
+#define AUH_INDIRECT    0x80    /* USB device is relay */
+
+#define AUH_SPLITMASK   0x40    /* mask for split bit */
+#define AUH_UNSPLIT     0x00    /* data block is full-size */
+#define AUH_SPLIT       0x40    /* data block is part of a larger one,
+                                   split-byte follows */
+
+#define AUH_TYPEMASK    0x3F    /* mask for type of data transfer */
+#define AUH_TYPESIZE    0x40    /* different types */
+#define AUH_DCHANNEL    0x00    /* D channel data */
+#define AUH_B1CHANNEL   0x01    /* B1 channel transparent */
+#define AUH_B2CHANNEL   0x02    /* B2 channel transparent */
+/*                0x03..0x0F       reserved for driver internal use */
+#define AUH_COMMAND     0x10    /* Command channel */
+#define AUH_BPROT       0x11    /* Configuration block protocol */
+#define AUH_DPROTANA    0x12    /* D channel protocol analyzer */
+#define AUH_TAPI        0x13    /* telephone api data (ATD) */
+/*                0x14..0x3F       reserved for other protocols */
+#define AUH_UNASSIGNED  0xFF    /* if char device has no assigned service */
+#define AUH_FIRSTUSERCH 0x11    /* first channel which is available for driver users */
+
+#define AUH_SIZE	1 	/* Size of Header Byte */
+
+/* Split Byte. Only present if split bit in header byte set.*/
+#define AUS_STARTMASK   0x80    /* mask for first block of splitted frame */
+#define AUS_FIRST       0x80    /* first block */
+#define AUS_FOLLOW      0x00    /* following block */
+
+#define AUS_ENDMASK     0x40    /* mask for last block of splitted frame */
+#define AUS_END         0x40    /* last block */
+#define AUS_NOEND       0x00    /* not the last block */
+
+#define AUS_LENMASK     0x3F    /* mask for block length information */
+
+/* Request types */
+#define AUT_RREQ        (USB_DIR_IN  | USB_TYPE_VENDOR | USB_RECIP_OTHER)   /* Read Request */
+#define AUT_WREQ        (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER)   /* Write Request */
+
+/* Vendor Requests */
+#define AUV_GETINFO     0x00    /* GetDeviceInfo */
+#define AUV_WBLOCK      0x01    /* Write Block */
+#define AUV_RBLOCK      0x02    /* Read Block */
+#define AUV_CHANNELCTL  0x03    /* Channel Control */
+#define AUV_DUMMY	0x04	/* Dummy Out for retry */
+
+/* Device Info Types */
+#define AUDI_NUMBCH     0x0000  /* Number of supported B channels */
+#define AUDI_OUTFSIZE   0x0001  /* Size of OUT B channel fifos */
+#define AUDI_MBCTRANS   0x0002  /* max. Blocklength of control transfer */
+
+/* Interrupt endpoint definitions */
+#define AU_IRQENDP      1       /* Endpoint number */
+#define AU_IRQCMDID     16      /* Command-block ID */
+#define AU_BLOCKRDY     0       /* Command: Block data ready on ctl endpoint */
+#define AU_IRQMINSIZE	5	/* Nr. of bytes decoded in this driver */
+
+/* Device String Descriptors */
+#define AUSI_VENDOR   	1	/* "Auerswald GmbH & Co. KG" */
+#define AUSI_DEVICE   	2	/* Name of the Device */
+#define AUSI_SERIALNR 	3	/* Serial Number */
+#define AUSI_MSN      	4	/* "MSN ..." (first) Multiple Subscriber Number */
+
+#define AUSI_DLEN	100	/* Max. Length of Device Description */
+
+#define AUV_RETRY	0x101	/* First Firmware version which can do control retries */
+
+/*-------------------------------------------------------------------*/
+/* External data structures / Interface                              */
+typedef struct
+{
+        char *buf;               /* return buffer for string contents */
+        unsigned int bsize;      /* size of return buffer */
+} audevinfo_t,*paudevinfo_t;
+
+/* IO controls */
+#define IOCTL_AU_SLEN	  _IOR( 'U', 0xF0, int)         /* return the max. string descriptor length */
+#define IOCTL_AU_DEVINFO  _IOWR('U', 0xF1, audevinfo_t) /* get name of a specific device */
+#define IOCTL_AU_SERVREQ  _IOW( 'U', 0xF2, int) 	/* request a service channel */
+#define IOCTL_AU_BUFLEN	  _IOR( 'U', 0xF3, int)         /* return the max. buffer length for the device */
+#define IOCTL_AU_RXAVAIL  _IOR( 'U', 0xF4, int)         /* return != 0 if Receive Data available */
+#define IOCTL_AU_CONNECT  _IOR( 'U', 0xF5, int)         /* return != 0 if connected to a service channel */
+#define IOCTL_AU_TXREADY  _IOR( 'U', 0xF6, int)         /* return != 0 if Transmitt channel ready to send */
+/*                              'U'  0xF7..0xFF reseved */
+
+/*-------------------------------------------------------------------*/
+/* Internal data structures                                          */
+
+/* ..................................................................*/
+/* urb chain element */
+struct  auerchain;                      /* forward for circular reference */
+typedef struct
+{
+        struct auerchain *chain;        /* pointer to the chain to which this element belongs */
+        struct urb * urbp;                   /* pointer to attached urb */
+        void *context;                  /* saved URB context */
+        usb_complete_t complete;        /* saved URB completion function */
+        struct list_head list;          /* to include element into a list */
+} auerchainelement_t,*pauerchainelement_t;
+
+/* urb chain */
+typedef struct auerchain
+{
+        pauerchainelement_t active;     /* element which is submitted to urb */
+	spinlock_t lock;                /* protection agains interrupts */
+        struct list_head waiting_list;  /* list of waiting elements */
+        struct list_head free_list;     /* list of available elements */
+} auerchain_t,*pauerchain_t;
+
+/* urb blocking completion helper struct */
+typedef struct
+{
+	wait_queue_head_t wqh;    	/* wait for completion */
+	unsigned int done;		/* completion flag */
+} auerchain_chs_t,*pauerchain_chs_t;
+
+/* ...................................................................*/
+/* buffer element */
+struct  auerbufctl;                     /* forward */
+typedef struct
+{
+        char *bufp;                     /* reference to allocated data buffer */
+        unsigned int len;               /* number of characters in data buffer */
+	unsigned int retries;		/* for urb retries */
+        struct usb_ctrlrequest *dr;	/* for setup data in control messages */
+        struct urb * urbp;                   /* USB urb */
+        struct auerbufctl *list;        /* pointer to list */
+        struct list_head buff_list;     /* reference to next buffer in list */
+} auerbuf_t,*pauerbuf_t;
+
+/* buffer list control block */
+typedef struct auerbufctl
+{
+        spinlock_t lock;                /* protection in interrupt */
+        struct list_head free_buff_list;/* free buffers */
+        struct list_head rec_buff_list; /* buffers with receive data */
+} auerbufctl_t,*pauerbufctl_t;
+
+/* ...................................................................*/
+/* service context */
+struct  auerscon;                       /* forward */
+typedef void (*auer_dispatch_t)(struct auerscon*, pauerbuf_t);
+typedef void (*auer_disconn_t) (struct auerscon*);
+typedef struct auerscon
+{
+        unsigned int id;                /* protocol service id AUH_xxxx */
+        auer_dispatch_t dispatch;       /* dispatch read buffer */
+	auer_disconn_t disconnect;	/* disconnect from device, wake up all char readers */
+} auerscon_t,*pauerscon_t;
+
+/* ...................................................................*/
+/* USB device context */
+typedef struct
+{
+	struct semaphore 	mutex;         	    /* protection in user context */
+	char 			name[16];	    /* name of the /dev/usb entry */
+	unsigned int		dtindex;	    /* index in the device table */
+	devfs_handle_t 		devfs;	 	    /* devfs device node */
+	struct usb_device *	usbdev;      	    /* USB device handle */
+	int			open_count;	    /* count the number of open character channels */
+        char 			dev_desc[AUSI_DLEN];/* for storing a textual description */
+        unsigned int 		maxControlLength;   /* max. Length of control paket (without header) */
+        struct urb * 		inturbp;            /* interrupt urb */
+        char *			intbufp;            /* data buffer for interrupt urb */
+	unsigned int 		irqsize;	    /* size of interrupt endpoint 1 */
+        struct auerchain 	controlchain;  	    /* for chaining of control messages */
+	auerbufctl_t 		bufctl;             /* Buffer control for control transfers */
+        pauerscon_t 	     	services[AUH_TYPESIZE];/* context pointers for each service */
+	unsigned int		version;	    /* Version of the device */
+	wait_queue_head_t 	bufferwait;         /* wait for a control buffer */
+} auerswald_t,*pauerswald_t;
+
+/* the global usb devfs handle */
+extern devfs_handle_t usb_devfs_handle;
+
+/* array of pointers to our devices that are currently connected */
+static pauerswald_t dev_table[AUER_MAX_DEVICES];
+
+/* lock to protect the dev_table structure */
+static struct semaphore dev_table_mutex;
+
+/* ................................................................... */
+/* character device context */
+typedef struct
+{
+	struct semaphore mutex;         /* protection in user context */
+	pauerswald_t auerdev;           /* context pointer of assigned device */
+        auerbufctl_t bufctl;            /* controls the buffer chain */
+        auerscon_t scontext;            /* service context */
+	wait_queue_head_t readwait;     /* for synchronous reading */
+	struct semaphore readmutex;     /* protection against multiple reads */
+	pauerbuf_t readbuf;		/* buffer held for partial reading */
+	unsigned int readoffset;	/* current offset in readbuf */
+	unsigned int removed;		/* is != 0 if device is removed */
+} auerchar_t,*pauerchar_t;
+
+
+/*-------------------------------------------------------------------*/
+/* Forwards */
+static void auerswald_ctrlread_complete (struct urb * urb);
+static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
+
+
+/*-------------------------------------------------------------------*/
+/* USB chain helper functions                                        */
+/* --------------------------                                        */
+
+/* completion function for chained urbs */
+static void auerchain_complete (struct urb * urb)
+{
+	unsigned long flags;
+        int result;
+
+        /* get pointer to element and to chain */
+        pauerchainelement_t acep = (pauerchainelement_t) urb->context;
+        pauerchain_t         acp = acep->chain;
+
+        /* restore original entries in urb */
+        urb->context  = acep->context;
+        urb->complete = acep->complete;
+
+        dbg ("auerchain_complete called");
+
+        /* call original completion function
+           NOTE: this function may lead to more urbs submitted into the chain.
+                 (no chain lock at calling complete()!)
+                 acp->active != NULL is protecting us against recursion.*/
+        urb->complete (urb);
+
+        /* detach element from chain data structure */
+	spin_lock_irqsave (&acp->lock, flags);
+        if (acp->active != acep) /* paranoia debug check */
+	        dbg ("auerchain_complete: completion on non-active element called!");
+        else
+                acp->active = NULL;
+
+        /* add the used chain element to the list of free elements */
+	list_add_tail (&acep->list, &acp->free_list);
+        acep = NULL;
+
+        /* is there a new element waiting in the chain? */
+        if (!acp->active && !list_empty (&acp->waiting_list)) {
+                /* yes: get the entry */
+                struct list_head *tmp = acp->waiting_list.next;
+                list_del (tmp);
+                acep = list_entry (tmp, auerchainelement_t, list);
+                acp->active = acep;
+        }
+        spin_unlock_irqrestore (&acp->lock, flags);
+
+        /* submit the new urb */
+        if (acep) {
+                urb    = acep->urbp;
+                dbg ("auerchain_complete: submitting next urb from chain");
+		urb->status = 0;	/* needed! */
+		result = usb_submit_urb(urb, GFP_KERNEL);
+
+                /* check for submit errors */
+                if (result) {
+                        urb->status = result;
+                        dbg("auerchain_complete: usb_submit_urb with error code %d", result);
+                        /* and do error handling via *this* completion function (recursive) */
+                        auerchain_complete( urb);
+                }
+        } else {
+                /* simple return without submitting a new urb.
+                   The empty chain is detected with acp->active == NULL. */
+        };
+}
+
+
+/* submit function for chained urbs
+   this function may be called from completion context or from user space!
+   early = 1 -> submit in front of chain
+*/
+static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int early)
+{
+        int result;
+        unsigned long flags;
+        pauerchainelement_t acep = NULL;
+
+        dbg ("auerchain_submit_urb called");
+
+        /* try to get a chain element */
+        spin_lock_irqsave (&acp->lock, flags);
+        if (!list_empty (&acp->free_list)) {
+                /* yes: get the entry */
+                struct list_head *tmp = acp->free_list.next;
+                list_del (tmp);
+                acep = list_entry (tmp, auerchainelement_t, list);
+        }
+        spin_unlock_irqrestore (&acp->lock, flags);
+
+        /* if no chain element available: return with error */
+        if (!acep) {
+                return -ENOMEM;
+        }
+
+        /* fill in the new chain element values */
+        acep->chain    = acp;
+        acep->context  = urb->context;
+        acep->complete = urb->complete;
+        acep->urbp     = urb;
+        INIT_LIST_HEAD (&acep->list);
+
+        /* modify urb */
+        urb->context   = acep;
+        urb->complete  = auerchain_complete;
+        urb->status    = -EINPROGRESS;    /* usb_submit_urb does this, too */
+
+        /* add element to chain - or start it immediately */
+        spin_lock_irqsave (&acp->lock, flags);
+        if (acp->active) {
+                /* there is traffic in the chain, simple add element to chain */
+		if (early) {
+			dbg ("adding new urb to head of chain");
+			list_add (&acep->list, &acp->waiting_list);
+		} else {
+			dbg ("adding new urb to end of chain");
+			list_add_tail (&acep->list, &acp->waiting_list);
+		}
+		acep = NULL;
+        } else {
+                /* the chain is empty. Prepare restart */
+                acp->active = acep;
+        }
+        /* Spin has to be removed before usb_submit_urb! */
+        spin_unlock_irqrestore (&acp->lock, flags);
+
+        /* Submit urb if immediate restart */
+        if (acep) {
+                dbg("submitting urb immediate");
+		urb->status = 0;	/* needed! */
+                result = usb_submit_urb(urb, GFP_KERNEL);
+                /* check for submit errors */
+                if (result) {
+                        urb->status = result;
+                        dbg("auerchain_submit_urb: usb_submit_urb with error code %d", result);
+                        /* and do error handling via completion function */
+                        auerchain_complete( urb);
+                }
+        }
+
+        return 0;
+}
+
+/* submit function for chained urbs
+   this function may be called from completion context or from user space!
+*/
+static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb)
+{
+	return auerchain_submit_urb_list (acp, urb, 0);
+}
+
+/* cancel an urb which is submitted to the chain
+   the result is 0 if the urb is cancelled, or -EINPROGRESS if
+   USB_ASYNC_UNLINK is set and the function is successfully started.
+*/
+static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb)
+{
+	unsigned long flags;
+        struct urb * urbp;
+        pauerchainelement_t acep;
+        struct list_head *tmp;
+
+        dbg ("auerchain_unlink_urb called");
+
+        /* search the chain of waiting elements */
+        spin_lock_irqsave (&acp->lock, flags);
+        list_for_each (tmp, &acp->waiting_list) {
+                acep = list_entry (tmp, auerchainelement_t, list);
+                if (acep->urbp == urb) {
+                        list_del (tmp);
+                        urb->context = acep->context;
+                        urb->complete = acep->complete;
+                        list_add_tail (&acep->list, &acp->free_list);
+                        spin_unlock_irqrestore (&acp->lock, flags);
+                        dbg ("unlink waiting urb");
+                        urb->status = -ENOENT;
+                        urb->complete (urb);
+                        return 0;
+                }
+        }
+        /* not found. */
+        spin_unlock_irqrestore (&acp->lock, flags);
+
+        /* get the active urb */
+        acep = acp->active;
+        if (acep) {
+                urbp = acep->urbp;
+
+                /* check if we have to cancel the active urb */
+                if (urbp == urb) {
+                        /* note that there is a race condition between the check above
+                           and the unlink() call because of no lock. This race is harmless,
+                           because the usb module will detect the unlink() after completion.
+                           We can't use the acp->lock here because the completion function
+                           wants to grab it.
+			*/
+                        dbg ("unlink active urb");
+                        return usb_unlink_urb (urbp);
+                }
+        }
+
+        /* not found anyway
+           ... is some kind of success
+	*/
+        dbg ("urb to unlink not found in chain");
+        return 0;
+}
+
+/* cancel all urbs which are in the chain.
+   this function must not be called from interrupt or completion handler.
+*/
+static void auerchain_unlink_all (pauerchain_t acp)
+{
+	unsigned long flags;
+        struct urb * urbp;
+        pauerchainelement_t acep;
+
+        dbg ("auerchain_unlink_all called");
+
+        /* clear the chain of waiting elements */
+        spin_lock_irqsave (&acp->lock, flags);
+        while (!list_empty (&acp->waiting_list)) {
+                /* get the next entry */
+                struct list_head *tmp = acp->waiting_list.next;
+                list_del (tmp);
+                acep = list_entry (tmp, auerchainelement_t, list);
+                urbp = acep->urbp;
+                urbp->context = acep->context;
+                urbp->complete = acep->complete;
+                list_add_tail (&acep->list, &acp->free_list);
+                spin_unlock_irqrestore (&acp->lock, flags);
+                dbg ("unlink waiting urb");
+                urbp->status = -ENOENT;
+                urbp->complete (urbp);
+                spin_lock_irqsave (&acp->lock, flags);
+        }
+        spin_unlock_irqrestore (&acp->lock, flags);
+
+        /* clear the active urb */
+        acep = acp->active;
+        if (acep) {
+                urbp = acep->urbp;
+                urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
+                dbg ("unlink active urb");
+                usb_unlink_urb (urbp);
+        }
+}
+
+
+/* free the chain.
+   this function must not be called from interrupt or completion handler.
+*/
+static void auerchain_free (pauerchain_t acp)
+{
+	unsigned long flags;
+        pauerchainelement_t acep;
+
+        dbg ("auerchain_free called");
+
+        /* first, cancel all pending urbs */
+        auerchain_unlink_all (acp);
+
+        /* free the elements */
+        spin_lock_irqsave (&acp->lock, flags);
+        while (!list_empty (&acp->free_list)) {
+                /* get the next entry */
+                struct list_head *tmp = acp->free_list.next;
+                list_del (tmp);
+                spin_unlock_irqrestore (&acp->lock, flags);
+		acep = list_entry (tmp, auerchainelement_t, list);
+                kfree (acep);
+	        spin_lock_irqsave (&acp->lock, flags);
+	}
+        spin_unlock_irqrestore (&acp->lock, flags);
+}
+
+
+/* Init the chain control structure */
+static void auerchain_init (pauerchain_t acp)
+{
+        /* init the chain data structure */
+        acp->active = NULL;
+	spin_lock_init (&acp->lock);
+        INIT_LIST_HEAD (&acp->waiting_list);
+        INIT_LIST_HEAD (&acp->free_list);
+}
+
+/* setup a chain.
+   It is assumed that there is no concurrency while setting up the chain
+   requirement: auerchain_init()
+*/
+static int auerchain_setup (pauerchain_t acp, unsigned int numElements)
+{
+        pauerchainelement_t acep;
+
+        dbg ("auerchain_setup called with %d elements", numElements);
+
+        /* fill the list of free elements */
+        for (;numElements; numElements--) {
+                acep = (pauerchainelement_t) kmalloc (sizeof (auerchainelement_t), GFP_KERNEL);
+                if (!acep) goto ac_fail;
+		memset (acep, 0, sizeof (auerchainelement_t));
+                INIT_LIST_HEAD (&acep->list);
+                list_add_tail (&acep->list, &acp->free_list);
+        }
+        return 0;
+
+ac_fail:/* free the elements */
+        while (!list_empty (&acp->free_list)) {
+                /* get the next entry */
+                struct list_head *tmp = acp->free_list.next;
+                list_del (tmp);
+                acep = list_entry (tmp, auerchainelement_t, list);
+                kfree (acep);
+        }
+        return -ENOMEM;
+}
+
+
+/* completion handler for synchronous chained URBs */
+static void auerchain_blocking_completion (struct urb *urb)
+{
+	pauerchain_chs_t pchs = (pauerchain_chs_t)urb->context;
+	pchs->done = 1;
+	wmb();
+	wake_up (&pchs->wqh);
+}
+
+
+/* Starts chained urb and waits for completion or timeout */
+static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
+{
+	DECLARE_WAITQUEUE (wait, current);
+	auerchain_chs_t chs;
+	int status;
+
+	dbg ("auerchain_start_wait_urb called");
+	init_waitqueue_head (&chs.wqh);
+	chs.done = 0;
+
+	set_current_state (TASK_UNINTERRUPTIBLE);
+	add_wait_queue (&chs.wqh, &wait);
+	urb->context = &chs;
+	status = auerchain_submit_urb (acp, urb);
+	if (status) {
+		/* something went wrong */
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&chs.wqh, &wait);
+		return status;
+	}
+
+	while (timeout && !chs.done)
+	{
+		timeout = schedule_timeout (timeout);
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		rmb();
+	}
+
+	set_current_state (TASK_RUNNING);
+	remove_wait_queue (&chs.wqh, &wait);
+
+	if (!timeout && !chs.done) {
+		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
+			dbg ("auerchain_start_wait_urb: raced timeout");
+			status = urb->status;
+		} else {
+			dbg ("auerchain_start_wait_urb: timeout");
+			auerchain_unlink_urb (acp, urb);  /* remove urb safely */
+			status = -ETIMEDOUT;
+		}
+	} else
+		status = urb->status;
+
+	if (actual_length)
+		*actual_length = urb->actual_length;
+
+  	return status;
+}
+
+
+/* auerchain_control_msg - Builds a control urb, sends it off and waits for completion
+   acp: pointer to the auerchain
+   dev: pointer to the usb device to send the message to
+   pipe: endpoint "pipe" to send the message to
+   request: USB message request value
+   requesttype: USB message request type value
+   value: USB message value
+   index: USB message index value
+   data: pointer to the data to send
+   size: length in bytes of the data to send
+   timeout: time to wait for the message to complete before timing out (if 0 the wait is forever)
+
+   This function sends a simple control message to a specified endpoint
+   and waits for the message to complete, or timeout.
+
+   If successful, it returns the transfered length, othwise a negative error number.
+
+   Don't use this function from within an interrupt context, like a
+   bottom half handler.  If you need a asyncronous message, or need to send
+   a message from within interrupt context, use auerchain_submit_urb()
+*/
+static int auerchain_control_msg (pauerchain_t acp, struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
+			          __u16 value, __u16 index, void *data, __u16 size, int timeout)
+{
+	int ret;
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
+        int length;
+
+        dbg ("auerchain_control_msg");
+        dr = kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+	urb = usb_alloc_urb (0, GFP_KERNEL);
+	if (!urb) {
+        	kfree (dr);
+		return -ENOMEM;
+        }
+
+	dr->bRequestType = requesttype;
+	dr->bRequest = request;
+	dr->wValue  = cpu_to_le16 (value);
+	dr->wIndex  = cpu_to_le16 (index);
+	dr->wLength = cpu_to_le16 (size);
+
+	FILL_CONTROL_URB (urb, dev, pipe, (unsigned char*)dr, data, size,    /* build urb */
+		          (usb_complete_t)auerchain_blocking_completion,0);
+	ret = auerchain_start_wait_urb (acp, urb, timeout, &length);
+
+	usb_free_urb (urb);
+	kfree (dr);
+
+        if (ret < 0)
+		return ret;
+	else
+		return length;
+}
+
+
+/*-------------------------------------------------------------------*/
+/* Buffer List helper functions                                      */
+
+/* free a single auerbuf */
+static void auerbuf_free (pauerbuf_t bp)
+{
+	if (bp->bufp) {
+		kfree (bp->bufp);
+	}
+	if (bp->dr) {
+		kfree (bp->dr);
+	}
+	if (bp->urbp) {
+		usb_free_urb (bp->urbp);
+	}
+	kfree (bp);
+}
+
+/* free the buffers from an auerbuf list */
+static void auerbuf_free_list (struct list_head *q)
+{
+        struct list_head *tmp;
+	struct list_head *p;
+	pauerbuf_t bp;
+
+	dbg ("auerbuf_free_list");
+	for (p = q->next; p != q;) {
+		bp = list_entry (p, auerbuf_t, buff_list);
+		tmp = p->next;
+		list_del (p);
+		p = tmp;
+		auerbuf_free (bp);
+	}
+}
+
+/* init the members of a list control block */
+static void auerbuf_init (pauerbufctl_t bcp)
+{
+	dbg ("auerbuf_init");
+	spin_lock_init (&bcp->lock);
+        INIT_LIST_HEAD (&bcp->free_buff_list);
+        INIT_LIST_HEAD (&bcp->rec_buff_list);
+}
+
+/* free all buffers from an auerbuf chain */
+static void auerbuf_free_buffers (pauerbufctl_t bcp)
+{
+	unsigned long flags;
+	dbg ("auerbuf_free_buffers");
+
+        spin_lock_irqsave (&bcp->lock, flags);
+
+	auerbuf_free_list (&bcp->free_buff_list);
+	auerbuf_free_list (&bcp->rec_buff_list);
+
+        spin_unlock_irqrestore (&bcp->lock, flags);
+}
+
+/* setup a list of buffers */
+/* requirement: auerbuf_init() */
+static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned int bufsize)
+{
+        pauerbuf_t bep;
+
+        dbg ("auerbuf_setup called with %d elements of %d bytes", numElements, bufsize);
+
+        /* fill the list of free elements */
+        for (;numElements; numElements--) {
+                bep = (pauerbuf_t) kmalloc (sizeof (auerbuf_t), GFP_KERNEL);
+                if (!bep) goto bl_fail;
+	        memset (bep, 0, sizeof (auerbuf_t));
+                bep->list = bcp;
+                INIT_LIST_HEAD (&bep->buff_list);
+                bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL);
+                if (!bep->bufp) goto bl_fail;
+                bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
+                if (!bep->dr) goto bl_fail;
+                bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
+                if (!bep->urbp) goto bl_fail;
+                list_add_tail (&bep->buff_list, &bcp->free_buff_list);
+        }
+        return 0;
+
+bl_fail:/* not enought memory. Free allocated elements */
+        dbg ("auerbuf_setup: no more memory");
+        auerbuf_free_buffers (bcp);
+        return -ENOMEM;
+}
+
+/* insert a used buffer into the free list */
+static void auerbuf_releasebuf( pauerbuf_t bp)
+{
+        unsigned long flags;
+        pauerbufctl_t bcp = bp->list;
+	bp->retries = 0;
+
+        dbg ("auerbuf_releasebuf called");
+        spin_lock_irqsave (&bcp->lock, flags);
+	list_add_tail (&bp->buff_list, &bcp->free_buff_list);
+        spin_unlock_irqrestore (&bcp->lock, flags);
+}
+
+
+/*-------------------------------------------------------------------*/
+/* Completion handlers */
+
+/* Values of urb->status or results of usb_submit_urb():
+0		Initial, OK
+-EINPROGRESS	during submission until end
+-ENOENT		if urb is unlinked
+-ETIMEDOUT	Transfer timed out, NAK
+-ENOMEM		Memory Overflow
+-ENODEV		Specified USB-device or bus doesn't exist
+-ENXIO		URB already queued
+-EINVAL		a) Invalid transfer type specified (or not supported)
+		b) Invalid interrupt interval (0n256)
+-EAGAIN		a) Specified ISO start frame too early
+		b) (using ISO-ASAP) Too much scheduled for the future wait some time and try again.
+-EFBIG		Too much ISO frames requested (currently uhci900)
+-EPIPE		Specified pipe-handle/Endpoint is already stalled
+-EMSGSIZE	Endpoint message size is zero, do interface/alternate setting
+-EPROTO		a) Bitstuff error
+		b) Unknown USB error
+-EILSEQ		CRC mismatch
+-ENOSR		Buffer error
+-EREMOTEIO	Short packet detected
+-EXDEV		ISO transfer only partially completed look at individual frame status for details
+-EINVAL		ISO madness, if this happens: Log off and go home
+-EOVERFLOW	babble
+*/
+
+/* check if a status code allows a retry */
+static int auerswald_status_retry (int status)
+{
+	switch (status) {
+	case 0:
+	case -ETIMEDOUT:
+	case -EOVERFLOW:
+	case -EAGAIN:
+	case -EPIPE:
+	case -EPROTO:
+	case -EILSEQ:
+	case -ENOSR:
+	case -EREMOTEIO:
+		return 1; /* do a retry */
+	}
+	return 0;	/* no retry possible */
+}
+
+/* Completion of asynchronous write block */
+static void auerchar_ctrlwrite_complete (struct urb * urb)
+{
+	pauerbuf_t bp = (pauerbuf_t) urb->context;
+	pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
+	dbg ("auerchar_ctrlwrite_complete called");
+
+	/* reuse the buffer */
+	auerbuf_releasebuf (bp);
+	/* Wake up all processes waiting for a buffer */
+	wake_up (&cp->bufferwait);
+}
+
+/* Completion handler for dummy retry packet */
+static void auerswald_ctrlread_wretcomplete (struct urb * urb)
+{
+        pauerbuf_t bp = (pauerbuf_t) urb->context;
+        pauerswald_t cp;
+	int ret;
+        dbg ("auerswald_ctrlread_wretcomplete called");
+        dbg ("complete with status: %d", urb->status);
+	cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
+
+	/* check if it is possible to advance */
+	if (!auerswald_status_retry (urb->status) || !cp->usbdev) {
+		/* reuse the buffer */
+		err ("control dummy: transmission error %d, can not retry", urb->status);
+		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&cp->bufferwait);
+		return;
+	}
+
+	/* fill the control message */
+	bp->dr->bRequestType = AUT_RREQ;
+	bp->dr->bRequest     = AUV_RBLOCK;
+	bp->dr->wLength      = bp->dr->wValue;	/* temporary stored */
+	bp->dr->wValue       = cpu_to_le16 (1);	/* Retry Flag */
+	/* bp->dr->index    = channel id;          remains */
+	FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),
+                          (unsigned char*)bp->dr, bp->bufp, le16_to_cpu (bp->dr->wLength),
+		          (usb_complete_t)auerswald_ctrlread_complete,bp);
+
+	/* submit the control msg as next paket */
+	ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);
+        if (ret) {
+        	dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
+        	bp->urbp->status = ret;
+        	auerswald_ctrlread_complete (bp->urbp);
+    	}
+}
+
+/* completion handler for receiving of control messages */
+static void auerswald_ctrlread_complete (struct urb * urb)
+{
+        unsigned int  serviceid;
+        pauerswald_t  cp;
+        pauerscon_t   scp;
+        pauerbuf_t    bp  = (pauerbuf_t) urb->context;
+	int ret;
+        dbg ("auerswald_ctrlread_complete called");
+
+	cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl)));
+
+	/* check if there is valid data in this urb */
+        if (urb->status) {
+		dbg ("complete with non-zero status: %d", urb->status);
+		/* should we do a retry? */
+		if (!auerswald_status_retry (urb->status)
+		 || !cp->usbdev
+		 || (cp->version < AUV_RETRY)
+                 || (bp->retries >= AU_RETRIES)) {
+			/* reuse the buffer */
+			err ("control read: transmission error %d, can not retry", urb->status);
+			auerbuf_releasebuf (bp);
+			/* Wake up all processes waiting for a buffer */
+			wake_up (&cp->bufferwait);
+			return;
+		}
+		bp->retries++;
+		dbg ("Retry count = %d", bp->retries);
+		/* send a long dummy control-write-message to allow device firmware to react */
+		bp->dr->bRequestType = AUT_WREQ;
+		bp->dr->bRequest     = AUV_DUMMY;
+		bp->dr->wValue       = bp->dr->wLength; /* temporary storage */
+		// bp->dr->wIndex    channel ID remains
+		bp->dr->wLength      = cpu_to_le16 (32); /* >= 8 bytes */
+		FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),
+  			(unsigned char*)bp->dr, bp->bufp, 32,
+	   		(usb_complete_t)auerswald_ctrlread_wretcomplete,bp);
+
+		/* submit the control msg as next paket */
+       		ret = auerchain_submit_urb_list (&cp->controlchain, bp->urbp, 1);
+       		if (ret) {
+               		dbg ("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
+               		bp->urbp->status = ret;
+               		auerswald_ctrlread_wretcomplete (bp->urbp);
+		}
+                return;
+        }
+
+        /* get the actual bytecount (incl. headerbyte) */
+        bp->len = urb->actual_length;
+        serviceid = bp->bufp[0] & AUH_TYPEMASK;
+        dbg ("Paket with serviceid %d and %d bytes received", serviceid, bp->len);
+
+        /* dispatch the paket */
+        scp = cp->services[serviceid];
+        if (scp) {
+                /* look, Ma, a listener! */
+                scp->dispatch (scp, bp);
+        }
+
+        /* release the paket */
+        auerbuf_releasebuf (bp);
+	/* Wake up all processes waiting for a buffer */
+	wake_up (&cp->bufferwait);
+}
+
+/*-------------------------------------------------------------------*/
+/* Handling of Interrupt Endpoint                                    */
+/* This interrupt Endpoint is used to inform the host about waiting
+   messages from the USB device.
+*/
+/* int completion handler. */
+static void auerswald_int_complete (struct urb * urb)
+{
+        unsigned long flags;
+        unsigned  int channelid;
+        unsigned  int bytecount;
+        int ret;
+        pauerbuf_t   bp = NULL;
+        pauerswald_t cp = (pauerswald_t) urb->context;
+
+        dbg ("auerswald_int_complete called");
+
+        /* do not respond to an error condition */
+        if (urb->status != 0) {
+                dbg ("nonzero URB status = %d", urb->status);
+                return;
+        }
+
+        /* check if all needed data was received */
+	if (urb->actual_length < AU_IRQMINSIZE) {
+                dbg ("invalid data length received: %d bytes", urb->actual_length);
+                return;
+        }
+
+        /* check the command code */
+        if (cp->intbufp[0] != AU_IRQCMDID) {
+                dbg ("invalid command received: %d", cp->intbufp[0]);
+                return;
+        }
+
+        /* check the command type */
+        if (cp->intbufp[1] != AU_BLOCKRDY) {
+                dbg ("invalid command type received: %d", cp->intbufp[1]);
+                return;
+        }
+
+        /* now extract the information */
+        channelid = cp->intbufp[2];
+        bytecount = le16_to_cpup (&cp->intbufp[3]);
+
+        /* check the channel id */
+        if (channelid >= AUH_TYPESIZE) {
+                dbg ("invalid channel id received: %d", channelid);
+                return;
+        }
+
+        /* check the byte count */
+        if (bytecount > (cp->maxControlLength+AUH_SIZE)) {
+                dbg ("invalid byte count received: %d", bytecount);
+                return;
+        }
+        dbg ("Service Channel = %d", channelid);
+        dbg ("Byte Count = %d", bytecount);
+
+        /* get a buffer for the next data paket */
+        spin_lock_irqsave (&cp->bufctl.lock, flags);
+        if (!list_empty (&cp->bufctl.free_buff_list)) {
+                /* yes: get the entry */
+                struct list_head *tmp = cp->bufctl.free_buff_list.next;
+                list_del (tmp);
+                bp = list_entry (tmp, auerbuf_t, buff_list);
+        }
+        spin_unlock_irqrestore (&cp->bufctl.lock, flags);
+
+        /* if no buffer available: skip it */
+        if (!bp) {
+                dbg ("auerswald_int_complete: no data buffer available");
+                /* can we do something more?
+		   This is a big problem: if this int packet is ignored, the
+		   device will wait forever and not signal any more data.
+		   The only real solution is: having enought buffers!
+		   Or perhaps temporary disabling the int endpoint?
+		*/
+		return;
+        }
+
+	/* fill the control message */
+        bp->dr->bRequestType = AUT_RREQ;
+	bp->dr->bRequest     = AUV_RBLOCK;
+	bp->dr->wValue       = cpu_to_le16 (0);
+	bp->dr->wIndex       = cpu_to_le16 (channelid | AUH_DIRECT | AUH_UNSPLIT);
+	bp->dr->wLength      = cpu_to_le16 (bytecount);
+	FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_rcvctrlpipe (cp->usbdev, 0),
+                          (unsigned char*)bp->dr, bp->bufp, bytecount,
+		          (usb_complete_t)auerswald_ctrlread_complete,bp);
+
+        /* submit the control msg */
+        ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
+        if (ret) {
+                dbg ("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
+                bp->urbp->status = ret;
+                auerswald_ctrlread_complete( bp->urbp);
+		/* here applies the same problem as above: device locking! */
+        }
+}
+
+/* int memory deallocation
+   NOTE: no mutex please!
+*/
+static void auerswald_int_free (pauerswald_t cp)
+{
+        if (cp->inturbp) {
+                usb_free_urb (cp->inturbp);
+                cp->inturbp = NULL;
+        }
+        if (cp->intbufp) {
+                kfree (cp->intbufp);
+                cp->intbufp = NULL;
+        }
+}
+
+/* This function is called to activate the interrupt
+   endpoint. This function returns 0 if successfull or an error code.
+   NOTE: no mutex please!
+*/
+static int auerswald_int_open (pauerswald_t cp)
+{
+        int ret;
+	struct usb_endpoint_descriptor *ep;
+	int irqsize;
+	dbg ("auerswald_int_open");
+
+	ep = usb_epnum_to_ep_desc (cp->usbdev, USB_DIR_IN | AU_IRQENDP);
+	if (!ep) {
+		ret = -EFAULT;
+  		goto intoend;
+    	}
+	irqsize = ep->wMaxPacketSize;
+	cp->irqsize = irqsize;
+
+	/* allocate the urb and data buffer */
+        if (!cp->inturbp) {
+                cp->inturbp = usb_alloc_urb (0, GFP_KERNEL);
+                if (!cp->inturbp) {
+                        ret = -ENOMEM;
+                        goto intoend;
+                }
+        }
+        if (!cp->intbufp) {
+                cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL);
+                if (!cp->intbufp) {
+                        ret = -ENOMEM;
+                        goto intoend;
+                }
+        }
+        /* setup urb */
+        FILL_INT_URB (cp->inturbp, cp->usbdev, usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp, irqsize, auerswald_int_complete, cp, ep->bInterval);
+        /* start the urb */
+	cp->inturbp->status = 0;	/* needed! */
+	ret = usb_submit_urb (cp->inturbp, GFP_KERNEL);
+
+intoend:
+        if (ret < 0) {
+                /* activation of interrupt endpoint has failed. Now clean up. */
+                dbg ("auerswald_int_open: activation of int endpoint failed");
+
+                /* deallocate memory */
+                auerswald_int_free (cp);
+        }
+        return ret;
+}
+
+/* This function is called to deactivate the interrupt
+   endpoint. This function returns 0 if successfull or an error code.
+   NOTE: no mutex please!
+*/
+static int auerswald_int_release (pauerswald_t cp)
+{
+        int ret = 0;
+        dbg ("auerswald_int_release");
+
+        /* stop the int endpoint */
+        if (cp->inturbp) {
+                ret = usb_unlink_urb (cp->inturbp);
+                if (ret)
+	                dbg ("nonzero int unlink result received: %d", ret);
+        }
+
+        /* deallocate memory */
+        auerswald_int_free (cp);
+
+        return ret;
+}
+
+/* --------------------------------------------------------------------- */
+/* Helper functions                                                      */
+
+/* wake up waiting readers */
+static void auerchar_disconnect (pauerscon_t scp)
+{
+        pauerchar_t ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));
+	dbg ("auerchar_disconnect called");
+	ccp->removed = 1;
+	wake_up (&ccp->readwait);
+}
+
+
+/* dispatch a read paket to a waiting character device */
+static void auerchar_ctrlread_dispatch (pauerscon_t scp, pauerbuf_t bp)
+{
+	unsigned long flags;
+        pauerchar_t ccp;
+        pauerbuf_t newbp = NULL;
+        char * charp;
+        dbg ("auerchar_ctrlread_dispatch called");
+        ccp = ((pauerchar_t)((char *)(scp)-(unsigned long)(&((pauerchar_t)0)->scontext)));
+
+        /* get a read buffer from character device context */
+        spin_lock_irqsave (&ccp->bufctl.lock, flags);
+        if (!list_empty (&ccp->bufctl.free_buff_list)) {
+                /* yes: get the entry */
+                struct list_head *tmp = ccp->bufctl.free_buff_list.next;
+                list_del (tmp);
+                newbp = list_entry (tmp, auerbuf_t, buff_list);
+        }
+        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
+
+        if (!newbp) {
+                dbg ("No read buffer available, discard paket!");
+                return;     /* no buffer, no dispatch */
+        }
+
+        /* copy information to new buffer element
+           (all buffers have the same length) */
+        charp = newbp->bufp;
+        newbp->bufp = bp->bufp;
+        bp->bufp = charp;
+        newbp->len = bp->len;
+
+        /* insert new buffer in read list */
+        spin_lock_irqsave (&ccp->bufctl.lock, flags);
+	list_add_tail (&newbp->buff_list, &ccp->bufctl.rec_buff_list);
+        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
+        dbg ("read buffer appended to rec_list");
+
+        /* wake up pending synchronous reads */
+	wake_up (&ccp->readwait);
+}
+
+
+/* Delete an auerswald driver context */
+static void auerswald_delete( pauerswald_t cp)
+{
+	dbg( "auerswald_delete");
+	if (cp == NULL) return;
+
+	/* Wake up all processes waiting for a buffer */
+	wake_up (&cp->bufferwait);
+
+	/* Cleaning up */
+	auerswald_int_release (cp);
+	auerchain_free (&cp->controlchain);
+	auerbuf_free_buffers (&cp->bufctl);
+
+	/* release the memory */
+	kfree( cp);
+}
+
+
+/* Delete an auerswald character context */
+static void auerchar_delete( pauerchar_t ccp)
+{
+	dbg ("auerchar_delete");
+	if (ccp == NULL) return;
+
+        /* wake up pending synchronous reads */
+	ccp->removed = 1;
+	wake_up (&ccp->readwait);
+
+	/* remove the read buffer */
+	if (ccp->readbuf) {
+		auerbuf_releasebuf (ccp->readbuf);
+		ccp->readbuf = NULL;
+	}
+
+	/* remove the character buffers */
+	auerbuf_free_buffers (&ccp->bufctl);
+
+	/* release the memory */
+	kfree( ccp);
+}
+
+
+/* add a new service to the device
+   scp->id must be set!
+   return: 0 if OK, else error code
+*/
+static int auerswald_addservice (pauerswald_t cp, pauerscon_t scp)
+{
+	int ret;
+
+	/* is the device available? */
+	if (!cp->usbdev) {
+		dbg ("usbdev == NULL");
+		return -EIO;	/*no: can not add a service, sorry*/
+	}
+
+	/* is the service available? */
+	if (cp->services[scp->id]) {
+		dbg ("service is busy");
+                return -EBUSY;
+	}
+
+	/* device is available, service is free */
+	cp->services[scp->id] = scp;
+
+	/* register service in device */
+	ret = auerchain_control_msg(
+		&cp->controlchain,                      /* pointer to control chain */
+		cp->usbdev,                             /* pointer to device */
+		usb_sndctrlpipe (cp->usbdev, 0),        /* pipe to control endpoint */
+		AUV_CHANNELCTL,                         /* USB message request value */
+		AUT_WREQ,                               /* USB message request type value */
+		0x01,              /* open                 USB message value */
+		scp->id,            		        /* USB message index value */
+		NULL,                                   /* pointer to the data to send */
+		0,                                      /* length in bytes of the data to send */
+		HZ * 2);                                /* time to wait for the message to complete before timing out */
+	if (ret < 0) {
+		dbg ("auerswald_addservice: auerchain_control_msg returned error code %d", ret);
+		/* undo above actions */
+		cp->services[scp->id] = NULL;
+		return ret;
+	}
+
+	dbg ("auerswald_addservice: channel open OK");
+	return 0;
+}
+
+
+/* remove a service from the the device
+   scp->id must be set! */
+static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp)
+{
+	dbg ("auerswald_removeservice called");
+
+	/* check if we have a service allocated */
+	if (scp->id == AUH_UNASSIGNED) return;
+
+	/* If there is a device: close the channel */
+	if (cp->usbdev) {
+		/* Close the service channel inside the device */
+		int ret = auerchain_control_msg(
+		&cp->controlchain,            		/* pointer to control chain */
+		cp->usbdev,         		        /* pointer to device */
+		usb_sndctrlpipe (cp->usbdev, 0),	/* pipe to control endpoint */
+		AUV_CHANNELCTL,                         /* USB message request value */
+		AUT_WREQ,                               /* USB message request type value */
+		0x00,              // close             /* USB message value */
+		scp->id,            		        /* USB message index value */
+		NULL,                                   /* pointer to the data to send */
+		0,                                      /* length in bytes of the data to send */
+		HZ * 2);                                /* time to wait for the message to complete before timing out */
+		if (ret < 0) {
+			dbg ("auerswald_removeservice: auerchain_control_msg returned error code %d", ret);
+		}
+		else {
+			dbg ("auerswald_removeservice: channel close OK");
+		}
+	}
+
+	/* remove the service from the device */
+	cp->services[scp->id] = NULL;
+	scp->id = AUH_UNASSIGNED;
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Char device functions                                                 */
+
+/* Open a new character device */
+static int auerchar_open (struct inode *inode, struct file *file)
+{
+	int dtindex = minor(inode->i_rdev) - AUER_MINOR_BASE;
+	pauerswald_t cp = NULL;
+	pauerchar_t ccp = NULL;
+        int ret;
+
+        /* minor number in range? */
+	if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) {
+		return -ENODEV;
+        }
+	/* usb device available? */
+	if (down_interruptible (&dev_table_mutex)) {
+		return -ERESTARTSYS;
+	}
+	cp = dev_table[dtindex];
+	if (cp == NULL) {
+		up (&dev_table_mutex);
+		return -ENODEV;
+	}
+	if (down_interruptible (&cp->mutex)) {
+		up (&dev_table_mutex);
+		return -ERESTARTSYS;
+	}
+	up (&dev_table_mutex);
+
+	/* we have access to the device. Now lets allocate memory */
+	ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
+	if (ccp == NULL) {
+		err ("out of memory");
+		ret = -ENOMEM;
+		goto ofail;
+	}
+
+	/* Initialize device descriptor */
+	memset( ccp, 0, sizeof(auerchar_t));
+	init_MUTEX( &ccp->mutex);
+	init_MUTEX( &ccp->readmutex);
+        auerbuf_init (&ccp->bufctl);
+        ccp->scontext.id = AUH_UNASSIGNED;
+        ccp->scontext.dispatch = auerchar_ctrlread_dispatch;
+	ccp->scontext.disconnect = auerchar_disconnect;
+	init_waitqueue_head (&ccp->readwait);
+
+	ret = auerbuf_setup (&ccp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE);
+       	if (ret) {
+		goto ofail;
+	}
+
+	cp->open_count++;
+	ccp->auerdev = cp;
+	dbg("open %s as /dev/usb/%s", cp->dev_desc, cp->name);
+	up (&cp->mutex);
+
+	/* file IO stuff */
+	file->f_pos = 0;
+	file->private_data = ccp;
+	return 0;
+
+	/* Error exit */
+ofail:	up (&cp->mutex);
+	auerchar_delete (ccp);
+	return ret;
+}
+
+
+/* IOCTL functions */
+static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	pauerchar_t ccp = (pauerchar_t) file->private_data;
+	int ret = 0;
+        audevinfo_t devinfo;
+        pauerswald_t cp = NULL;
+	unsigned int u;
+        dbg ("ioctl");
+
+	/* get the mutexes */
+	if (down_interruptible (&ccp->mutex)) {
+		return -ERESTARTSYS;
+	}
+	cp = ccp->auerdev;
+	if (!cp) {
+		up (&ccp->mutex);
+                return -ENODEV;
+	}
+	if (down_interruptible (&cp->mutex)) {
+		up(&ccp->mutex);
+		return -ERESTARTSYS;
+	}
+
+	/* Check for removal */
+	if (!cp->usbdev) {
+		up(&cp->mutex);
+		up(&ccp->mutex);
+                return -ENODEV;
+	}
+
+	switch (cmd) {
+
+	/* return != 0 if Transmitt channel ready to send */
+	case IOCTL_AU_TXREADY:
+		dbg ("IOCTL_AU_TXREADY");
+		u   = ccp->auerdev
+		   && (ccp->scontext.id != AUH_UNASSIGNED)
+		   && !list_empty (&cp->bufctl.free_buff_list);
+	        ret = put_user (u, (unsigned int *) arg);
+		break;
+
+	/* return != 0 if connected to a service channel */
+	case IOCTL_AU_CONNECT:
+		dbg ("IOCTL_AU_CONNECT");
+		u = (ccp->scontext.id != AUH_UNASSIGNED);
+	        ret = put_user (u, (unsigned int *) arg);
+		break;
+
+	/* return != 0 if Receive Data available */
+	case IOCTL_AU_RXAVAIL:
+		dbg ("IOCTL_AU_RXAVAIL");
+		if (ccp->scontext.id == AUH_UNASSIGNED) {
+                        ret = -EIO;
+                        break;
+                }
+		u = 0;	/* no data */
+		if (ccp->readbuf) {
+			int restlen = ccp->readbuf->len - ccp->readoffset;
+			if (restlen > 0) u = 1;
+		}
+		if (!u) {
+        		if (!list_empty (&ccp->bufctl.rec_buff_list)) {
+				u = 1;
+			}
+		}
+	        ret = put_user (u, (unsigned int *) arg);
+		break;
+
+	/* return the max. buffer length for the device */
+	case IOCTL_AU_BUFLEN:
+		dbg ("IOCTL_AU_BUFLEN");
+		u = cp->maxControlLength;
+	        ret = put_user (u, (unsigned int *) arg);
+		break;
+
+	/* requesting a service channel */
+        case IOCTL_AU_SERVREQ:
+		dbg ("IOCTL_AU_SERVREQ");
+                /* requesting a service means: release the previous one first */
+		auerswald_removeservice (cp, &ccp->scontext);
+		/* get the channel number */
+		ret = get_user (u, (unsigned int *) arg);
+		if (ret) {
+			break;
+		}
+		if ((u < AUH_FIRSTUSERCH) || (u >= AUH_TYPESIZE)) {
+                        ret = -EIO;
+                        break;
+                }
+                dbg ("auerchar service request parameters are ok");
+		ccp->scontext.id = u;
+
+		/* request the service now */
+		ret = auerswald_addservice (cp, &ccp->scontext);
+		if (ret) {
+			/* no: revert service entry */
+                	ccp->scontext.id = AUH_UNASSIGNED;
+		}
+		break;
+
+	/* get a string descriptor for the device */
+	case IOCTL_AU_DEVINFO:
+		dbg ("IOCTL_AU_DEVINFO");
+                if (copy_from_user (&devinfo, (void *) arg, sizeof (audevinfo_t))) {
+        		ret = -EFAULT;
+	        	break;
+                }
+		u = strlen(cp->dev_desc)+1;
+		if (u > devinfo.bsize) {
+			u = devinfo.bsize;
+		}
+		ret = copy_to_user(devinfo.buf, cp->dev_desc, u);
+		break;
+
+	/* get the max. string descriptor length */
+        case IOCTL_AU_SLEN:
+		dbg ("IOCTL_AU_SLEN");
+		u = AUSI_DLEN;
+	        ret = put_user (u, (unsigned int *) arg);
+		break;
+
+	default:
+		dbg ("IOCTL_AU_UNKNOWN");
+		ret = -ENOIOCTLCMD;
+		break;
+        }
+	/* release the mutexes */
+	up(&cp->mutex);
+	up(&ccp->mutex);
+	return ret;
+}
+
+/* Read data from the device */
+static ssize_t auerchar_read (struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+        unsigned long flags;
+	pauerchar_t ccp = (pauerchar_t) file->private_data;
+        pauerbuf_t   bp = NULL;
+	wait_queue_t wait;
+
+        dbg ("auerchar_read");
+
+	/* Error checking */
+	if (!ccp)
+		return -EIO;
+	if (*ppos)
+ 		return -ESPIPE;
+        if (count == 0)
+		return 0;
+
+	/* get the mutex */
+	if (down_interruptible (&ccp->mutex))
+		return -ERESTARTSYS;
+
+	/* Can we expect to read something? */
+	if (ccp->scontext.id == AUH_UNASSIGNED) {
+		up (&ccp->mutex);
+                return -EIO;
+	}
+
+	/* only one reader per device allowed */
+	if (down_interruptible (&ccp->readmutex)) {
+		up (&ccp->mutex);
+		return -ERESTARTSYS;
+	}
+
+	/* read data from readbuf, if available */
+doreadbuf:
+	bp = ccp->readbuf;
+	if (bp) {
+		/* read the maximum bytes */
+		int restlen = bp->len - ccp->readoffset;
+		if (restlen < 0)
+			restlen = 0;
+		if (count > restlen)
+			count = restlen;
+		if (count) {
+			if (copy_to_user (buf, bp->bufp+ccp->readoffset, count)) {
+				dbg ("auerswald_read: copy_to_user failed");
+				up (&ccp->readmutex);
+				up (&ccp->mutex);
+				return -EFAULT;
+			}
+		}
+		/* advance the read offset */
+		ccp->readoffset += count;
+		restlen -= count;
+		// reuse the read buffer
+		if (restlen <= 0) {
+			auerbuf_releasebuf (bp);
+			ccp->readbuf = NULL;
+		}
+		/* return with number of bytes read */
+		if (count) {
+			up (&ccp->readmutex);
+			up (&ccp->mutex);
+			return count;
+		}
+	}
+
+	/* a read buffer is not available. Try to get the next data block. */
+doreadlist:
+	/* Preparing for sleep */
+	init_waitqueue_entry (&wait, current);
+	set_current_state (TASK_INTERRUPTIBLE);
+	add_wait_queue (&ccp->readwait, &wait);
+
+	bp = NULL;
+	spin_lock_irqsave (&ccp->bufctl.lock, flags);
+        if (!list_empty (&ccp->bufctl.rec_buff_list)) {
+                /* yes: get the entry */
+                struct list_head *tmp = ccp->bufctl.rec_buff_list.next;
+                list_del (tmp);
+                bp = list_entry (tmp, auerbuf_t, buff_list);
+        }
+        spin_unlock_irqrestore (&ccp->bufctl.lock, flags);
+
+	/* have we got data? */
+	if (bp) {
+		ccp->readbuf = bp;
+		ccp->readoffset = AUH_SIZE; /* for headerbyte */
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&ccp->readwait, &wait);
+		goto doreadbuf;		  /* now we can read! */
+	}
+
+	/* no data available. Should we wait? */
+	if (file->f_flags & O_NONBLOCK) {
+                dbg ("No read buffer available, returning -EAGAIN");
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&ccp->readwait, &wait);
+		up (&ccp->readmutex);
+		up (&ccp->mutex);
+		return -EAGAIN;  /* nonblocking, no data available */
+        }
+
+	/* yes, we should wait! */
+	up (&ccp->mutex); /* allow other operations while we wait */
+	schedule();
+	remove_wait_queue (&ccp->readwait, &wait);
+	if (signal_pending (current)) {
+		/* waked up by a signal */
+		up (&ccp->readmutex);
+		return -ERESTARTSYS;
+	}
+
+	/* Anything left to read? */
+	if ((ccp->scontext.id == AUH_UNASSIGNED) || ccp->removed) {
+		up (&ccp->readmutex);
+		return -EIO;
+	}
+
+	if (down_interruptible (&ccp->mutex)) {
+		up (&ccp->readmutex);
+		return -ERESTARTSYS;
+	}
+
+	/* try to read the incomming data again */
+	goto doreadlist;
+}
+
+
+/* Write a data block into the right service channel of the device */
+static ssize_t auerchar_write (struct file *file, const char *buf, size_t len, loff_t *ppos)
+{
+	pauerchar_t ccp = (pauerchar_t) file->private_data;
+        pauerswald_t cp = NULL;
+        pauerbuf_t bp;
+        unsigned long flags;
+	int ret;
+	wait_queue_t wait;
+
+        dbg ("auerchar_write %d bytes", len);
+
+	/* Error checking */
+	if (!ccp)
+		return -EIO;
+        if (*ppos)
+		return -ESPIPE;
+        if (len == 0)
+                return 0;
+
+write_again:
+	/* get the mutex */
+	if (down_interruptible (&ccp->mutex))
+		return -ERESTARTSYS;
+
+	/* Can we expect to write something? */
+	if (ccp->scontext.id == AUH_UNASSIGNED) {
+		up (&ccp->mutex);
+                return -EIO;
+	}
+
+	cp = ccp->auerdev;
+	if (!cp) {
+		up (&ccp->mutex);
+		return -ERESTARTSYS;
+	}
+	if (down_interruptible (&cp->mutex)) {
+		up (&ccp->mutex);
+		return -ERESTARTSYS;
+	}
+	if (!cp->usbdev) {
+		up (&cp->mutex);
+		up (&ccp->mutex);
+		return -EIO;
+	}
+	/* Prepare for sleep */
+	init_waitqueue_entry (&wait, current);
+	set_current_state (TASK_INTERRUPTIBLE);
+	add_wait_queue (&cp->bufferwait, &wait);
+
+	/* Try to get a buffer from the device pool.
+	   We can't use a buffer from ccp->bufctl because the write
+	   command will last beond a release() */
+	bp = NULL;
+	spin_lock_irqsave (&cp->bufctl.lock, flags);
+        if (!list_empty (&cp->bufctl.free_buff_list)) {
+                /* yes: get the entry */
+                struct list_head *tmp = cp->bufctl.free_buff_list.next;
+                list_del (tmp);
+                bp = list_entry (tmp, auerbuf_t, buff_list);
+        }
+        spin_unlock_irqrestore (&cp->bufctl.lock, flags);
+
+	/* are there any buffers left? */
+	if (!bp) {
+		up (&cp->mutex);
+		up (&ccp->mutex);
+
+		/* NONBLOCK: don't wait */
+		if (file->f_flags & O_NONBLOCK) {
+			set_current_state (TASK_RUNNING);
+			remove_wait_queue (&cp->bufferwait, &wait);
+			return -EAGAIN;
+		}
+
+		/* BLOCKING: wait */
+		schedule();
+		remove_wait_queue (&cp->bufferwait, &wait);
+		if (signal_pending (current)) {
+			/* waked up by a signal */
+			return -ERESTARTSYS;
+		}
+		goto write_again;
+	} else {
+		set_current_state (TASK_RUNNING);
+		remove_wait_queue (&cp->bufferwait, &wait);
+	}
+
+	/* protect against too big write requests */
+	if (len > cp->maxControlLength) len = cp->maxControlLength;
+
+	/* Fill the buffer */
+	if (copy_from_user ( bp->bufp+AUH_SIZE, buf, len)) {
+		dbg ("copy_from_user failed");
+		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&cp->bufferwait);
+		up (&cp->mutex);
+		up (&ccp->mutex);
+		return -EIO;
+	}
+
+	/* set the header byte */
+        *(bp->bufp) = ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT;
+
+	/* Set the transfer Parameters */
+	bp->len = len+AUH_SIZE;
+        bp->dr->bRequestType = AUT_WREQ;
+	bp->dr->bRequest     = AUV_WBLOCK;
+	bp->dr->wValue       = cpu_to_le16 (0);
+	bp->dr->wIndex       = cpu_to_le16 (ccp->scontext.id | AUH_DIRECT | AUH_UNSPLIT);
+	bp->dr->wLength      = cpu_to_le16 (len+AUH_SIZE);
+	FILL_CONTROL_URB (bp->urbp, cp->usbdev, usb_sndctrlpipe (cp->usbdev, 0),
+                   (unsigned char*)bp->dr, bp->bufp, len+AUH_SIZE,
+		    auerchar_ctrlwrite_complete, bp);
+	/* up we go */
+	ret = auerchain_submit_urb (&cp->controlchain, bp->urbp);
+	up (&cp->mutex);
+	if (ret) {
+		dbg ("auerchar_write: nonzero result of auerchain_submit_urb %d", ret);
+		auerbuf_releasebuf (bp);
+		/* Wake up all processes waiting for a buffer */
+		wake_up (&cp->bufferwait);
+		up (&ccp->mutex);
+		return -EIO;
+	}
+	else {
+		dbg ("auerchar_write: Write OK");
+		up (&ccp->mutex);
+		return len;
+	}
+}
+
+
+/* Close a character device */
+static int auerchar_release (struct inode *inode, struct file *file)
+{
+	pauerchar_t ccp = (pauerchar_t) file->private_data;
+	pauerswald_t cp;
+	dbg("release");
+
+	/* get the mutexes */
+	if (down_interruptible (&ccp->mutex)) {
+		return -ERESTARTSYS;
+	}
+	cp = ccp->auerdev;
+	if (cp) {
+		if (down_interruptible (&cp->mutex)) {
+			up (&ccp->mutex);
+			return -ERESTARTSYS;
+		}
+		/* remove an open service */
+		auerswald_removeservice (cp, &ccp->scontext);
+		/* detach from device */
+		if ((--cp->open_count <= 0) && (cp->usbdev == NULL)) {
+			/* usb device waits for removal */
+			up (&cp->mutex);
+			auerswald_delete (cp);
+		} else {
+			up (&cp->mutex);
+		}
+		cp = NULL;
+		ccp->auerdev = NULL;
+	}
+	up (&ccp->mutex);
+	auerchar_delete (ccp);
+
+	return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* File operation structure                                             */
+static struct file_operations auerswald_fops =
+{
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	read:		auerchar_read,
+	write:          auerchar_write,
+	ioctl:		auerchar_ioctl,
+	open:		auerchar_open,
+	release:	auerchar_release,
+};
+
+
+/* --------------------------------------------------------------------- */
+/* Special USB driver functions                                          */
+
+/* Probe if this driver wants to serve an USB device
+
+   This entry point is called whenever a new device is attached to the bus.
+   Then the device driver has to create a new instance of its internal data
+   structures for the new device.
+
+   The  dev argument specifies the device context, which contains pointers
+   to all USB descriptors. The  interface argument specifies the interface
+   number. If a USB driver wants to bind itself to a particular device and
+   interface it has to return a pointer. This pointer normally references
+   the device driver's context structure.
+
+   Probing normally is done by checking the vendor and product identifications
+   or the class and subclass definitions. If they match the interface number
+   is compared with the ones supported by the driver. When probing is done
+   class based it might be necessary to parse some more USB descriptors because
+   the device properties can differ in a wide range.
+*/
+static void *auerswald_probe (struct usb_device *usbdev, unsigned int ifnum,
+			      const struct usb_device_id *id)
+{
+	pauerswald_t cp = NULL;
+	DECLARE_WAIT_QUEUE_HEAD (wqh);
+	unsigned int dtindex;
+	unsigned int u = 0;
+	char *pbuf;
+	int ret;
+
+	dbg ("probe: vendor id 0x%x, device id 0x%x ifnum:%d",
+	     usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
+
+	/* See if the device offered us matches that we can accept */
+	if (usbdev->descriptor.idVendor != ID_AUERSWALD) return NULL;
+
+        /* we use only the first -and only- interface */
+        if (ifnum != 0) return NULL;
+
+	/* prevent module unloading while sleeping */
+	MOD_INC_USE_COUNT;
+
+	/* allocate memory for our device and intialize it */
+	cp = kmalloc (sizeof(auerswald_t), GFP_KERNEL);
+	if (cp == NULL) {
+		err ("out of memory");
+		goto pfail;
+	}
+
+	/* Initialize device descriptor */
+	memset (cp, 0, sizeof(auerswald_t));
+	init_MUTEX (&cp->mutex);
+	cp->usbdev = usbdev;
+	auerchain_init (&cp->controlchain);
+        auerbuf_init (&cp->bufctl);
+	init_waitqueue_head (&cp->bufferwait);
+
+	/* find a free slot in the device table */
+	down (&dev_table_mutex);
+	for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
+		if (dev_table[dtindex] == NULL)
+			break;
+	}
+	if ( dtindex >= AUER_MAX_DEVICES) {
+		err ("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
+		up (&dev_table_mutex);
+		goto pfail;
+	}
+
+	/* Give the device a name */
+	sprintf (cp->name, AU_PREFIX "%d", dtindex);
+
+	/* Store the index */
+	cp->dtindex = dtindex;
+	dev_table[dtindex] = cp;
+	up (&dev_table_mutex);
+
+	/* initialize the devfs node for this device and register it */
+	cp->devfs = devfs_register (usb_devfs_handle, cp->name,
+				    DEVFS_FL_DEFAULT, USB_MAJOR,
+				    AUER_MINOR_BASE + dtindex,
+				    S_IFCHR | S_IRUGO | S_IWUGO,
+				    &auerswald_fops, NULL);
+
+	/* Get the usb version of the device */
+	cp->version = cp->usbdev->descriptor.bcdDevice;
+	dbg ("Version is %X", cp->version);
+
+	/* allow some time to settle the device */
+	sleep_on_timeout (&wqh, HZ / 3 );
+
+	/* Try to get a suitable textual description of the device */
+	/* Device name:*/
+	ret = usb_string( cp->usbdev, AUSI_DEVICE, cp->dev_desc, AUSI_DLEN-1);
+	if (ret >= 0) {
+		u += ret;
+		/* Append Serial Number */
+		memcpy(&cp->dev_desc[u], ",Ser# ", 6);
+		u += 6;
+		ret = usb_string( cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u], AUSI_DLEN-u-1);
+		if (ret >= 0) {
+			u += ret;
+			/* Append subscriber number */
+			memcpy(&cp->dev_desc[u], ", ", 2);
+			u += 2;
+			ret = usb_string( cp->usbdev, AUSI_MSN, &cp->dev_desc[u], AUSI_DLEN-u-1);
+			if (ret >= 0) {
+				u += ret;
+			}
+		}
+	}
+	cp->dev_desc[u] = '\0';
+	info("device is a %s", cp->dev_desc);
+
+        /* get the maximum allowed control transfer length */
+        pbuf = (char *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
+        if (!pbuf) {
+		err( "out of memory");
+		goto pfail;
+	}
+        ret = usb_control_msg(cp->usbdev,           /* pointer to device */
+                usb_rcvctrlpipe( cp->usbdev, 0 ),   /* pipe to control endpoint */
+                AUV_GETINFO,                        /* USB message request value */
+                AUT_RREQ,                           /* USB message request type value */
+                0,                                  /* USB message value */
+                AUDI_MBCTRANS,                      /* USB message index value */
+                pbuf,                               /* pointer to the receive buffer */
+                2,                                  /* length of the buffer */
+                HZ * 2);                            /* time to wait for the message to complete before timing out */
+        if (ret == 2) {
+	        cp->maxControlLength = le16_to_cpup(pbuf);
+                kfree(pbuf);
+                dbg("setup: max. allowed control transfersize is %d bytes", cp->maxControlLength);
+        } else {
+                kfree(pbuf);
+                err("setup: getting max. allowed control transfer length failed with error %d", ret);
+		goto pfail;
+        }
+
+	/* allocate a chain for the control messages */
+        if (auerchain_setup (&cp->controlchain, AUCH_ELEMENTS)) {
+		err ("out of memory");
+		goto pfail;
+	}
+
+        /* allocate buffers for control messages */
+	if (auerbuf_setup (&cp->bufctl, AU_RBUFFERS, cp->maxControlLength+AUH_SIZE)) {
+		err ("out of memory");
+		goto pfail;
+	}
+
+	/* start the interrupt endpoint */
+	if (auerswald_int_open (cp)) {
+		err ("int endpoint failed");
+		goto pfail;
+	}
+
+	/* all OK */
+	return cp;
+
+	/* Error exit: clean up the memory */
+pfail:	auerswald_delete (cp);
+	MOD_DEC_USE_COUNT;
+	return NULL;
+}
+
+
+/* Disconnect driver from a served device
+
+   This function is called whenever a device which was served by this driver
+   is disconnected.
+
+   The argument  dev specifies the device context and the  driver_context
+   returns a pointer to the previously registered  driver_context of the
+   probe function. After returning from the disconnect function the USB
+   framework completly deallocates all data structures associated with
+   this device. So especially the usb_device structure must not be used
+   any longer by the usb driver.
+*/
+static void auerswald_disconnect (struct usb_device *usbdev, void *driver_context)
+{
+	pauerswald_t cp = (pauerswald_t) driver_context;
+	unsigned int u;
+
+	down (&cp->mutex);
+	info ("device /dev/usb/%s now disconnecting", cp->name);
+
+	/* remove from device table */
+	/* Nobody can open() this device any more */
+	down (&dev_table_mutex);
+	dev_table[cp->dtindex] = NULL;
+	up (&dev_table_mutex);
+
+	/* remove our devfs node */
+	/* Nobody can see this device any more */
+	devfs_unregister (cp->devfs);
+
+	/* Stop the interrupt endpoint */
+	auerswald_int_release (cp);
+
+	/* remove the control chain allocated in auerswald_probe
+	   This has the benefit of
+	   a) all pending (a)synchronous urbs are unlinked
+	   b) all buffers dealing with urbs are reclaimed
+	*/
+	auerchain_free (&cp->controlchain);
+
+	if (cp->open_count == 0) {
+		/* nobody is using this device. So we can clean up now */
+		up (&cp->mutex);/* up() is possible here because no other task
+				   can open the device (see above). I don't want
+				   to kfree() a locked mutex. */
+		auerswald_delete (cp);
+	} else {
+		/* device is used. Remove the pointer to the
+		   usb device (it's not valid any more). The last
+		   release() will do the clean up */
+		cp->usbdev = NULL;
+		up (&cp->mutex);
+		/* Terminate waiting writers */
+		wake_up (&cp->bufferwait);
+		/* Inform all waiting readers */
+		for ( u = 0; u < AUH_TYPESIZE; u++) {
+			pauerscon_t scp = cp->services[u];
+			if (scp) scp->disconnect( scp);
+		}
+	}
+
+	/* The device releases this module */
+	MOD_DEC_USE_COUNT;
+}
+
+/* Descriptor for the devices which are served by this driver.
+   NOTE: this struct is parsed by the usbmanager install scripts.
+         Don't change without caution!
+*/
+static struct usb_device_id auerswald_ids [] = {
+	{ USB_DEVICE (ID_AUERSWALD, 0x00C0) },          /* COMpact 2104 USB */
+	{ USB_DEVICE (ID_AUERSWALD, 0x00DB) },          /* COMpact 4410/2206 USB */
+	{ USB_DEVICE (ID_AUERSWALD, 0x00F1) },          /* Comfort 2000 System Telephone */
+	{ USB_DEVICE (ID_AUERSWALD, 0x00F2) },          /* Comfort 1200 System Telephone */
+        { }			                        /* Terminating entry */
+};
+
+/* Standard module device table */
+MODULE_DEVICE_TABLE (usb, auerswald_ids);
+
+/* Standard usb driver struct */
+static struct usb_driver auerswald_driver = {
+	name:		"auerswald",
+	probe:		auerswald_probe,
+	disconnect:	auerswald_disconnect,
+	fops:		&auerswald_fops,
+	minor:		AUER_MINOR_BASE,
+	id_table:	auerswald_ids,
+};
+
+
+/* --------------------------------------------------------------------- */
+/* Module loading/unloading                                              */
+
+/* Driver initialisation. Called after module loading.
+   NOTE: there is no concurrency at _init
+*/
+static int __init auerswald_init (void)
+{
+	int result;
+	dbg ("init");
+
+	/* initialize the device table */
+	memset (&dev_table, 0, sizeof(dev_table));
+	init_MUTEX (&dev_table_mutex);
+
+	/* register driver at the USB subsystem */
+	result = usb_register (&auerswald_driver);
+	if (result < 0) {
+		err ("driver could not be registered");
+		return -1;
+	}
+	return 0;
+}
+
+/* Driver deinit. Called before module removal.
+   NOTE: there is no concurrency at _cleanup
+*/
+static void __exit auerswald_cleanup (void)
+{
+	dbg ("cleanup");
+	usb_deregister (&auerswald_driver);
+}
+
+/* --------------------------------------------------------------------- */
+/* Linux device driver module description                                */
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+
+module_init (auerswald_init);
+module_exit (auerswald_cleanup);
+
+/* --------------------------------------------------------------------- */
+
diff -Nru a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/emi26.c	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,239 @@
+/* 
+ * Emagic EMI 2|6 usb audio interface firmware loader.
+ * Copyright (C) 2002
+ * 	Tapio Laxström (tapio.laxstrom@iptime.fi)
+ *
+ * This program is free software; 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.
+ * 
+ * emi26.c,v 1.13 2002/03/08 13:10:26 tapio Exp
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define MAX_INTEL_HEX_RECORD_LENGTH 16
+typedef struct _INTEL_HEX_RECORD
+{
+	__u32	length;
+	__u32	address;
+	__u32	type;
+	__u8	data[MAX_INTEL_HEX_RECORD_LENGTH];
+} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
+
+/* include firmware (variables) */
+#include "emi26_fw.h"
+
+#define EMI26_VENDOR_ID 		0x086a  /* Emagic Soft-und Hardware GmBH */
+#define EMI26_PRODUCT_ID		0x0100	/* EMI 2|6 without firmware */
+
+#define ANCHOR_LOAD_INTERNAL	0xA0	/* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
+#define ANCHOR_LOAD_EXTERNAL	0xA3	/* This command is not implemented in the core. Requires firmware */
+#define ANCHOR_LOAD_FPGA	0xA5	/* This command is not implemented in the core. Requires firmware. Emagic extension */
+#define MAX_INTERNAL_ADDRESS	0x1B3F	/* This is the highest internal RAM address for the AN2131Q */
+#define CPUCS_REG		0x7F92  /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */ 
+#define INTERNAL_RAM(address)   (address <= MAX_INTERNAL_ADDRESS)
+
+static int emi26_writememory( struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest);
+static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
+static int emi26_load_firmware (struct usb_device *dev);
+static void *emi26_probe(struct usb_device *dev, unsigned int if_num, const struct usb_device_id *id);
+static void emi26_disconnect(struct usb_device *dev, void *drv_context);
+static int __init emi26_init (void);
+static void __exit emi26_exit (void);
+
+
+/* thanks to drivers/usb/serial/keyspan_pda.c code */
+static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
+{
+	int result;
+	unsigned char *buffer =  kmalloc (length, GFP_KERNEL);
+
+	if (!buffer) {
+		printk(KERN_ERR "emi26: kmalloc(%d) failed.", length);
+		return -ENOMEM;
+	}
+	memcpy (buffer, data, length);
+	/* Note: usb_control_msg returns negative value on error or length of the
+	 * 		 data that was written! */
+	result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
+	kfree (buffer);
+	return result;
+}
+
+/* thanks to drivers/usb/serial/keyspan_pda.c code */
+static int emi26_set_reset (struct usb_device *dev, unsigned char reset_bit)
+{
+	int response;
+	printk(KERN_INFO "%s - %d", __FUNCTION__, reset_bit);
+	/* printk(KERN_DEBUG "%s - %d", __FUNCTION__, reset_bit); */
+	response = emi26_writememory (dev, CPUCS_REG, &reset_bit, 1, 0xa0);
+	if (response < 0) {
+		printk(KERN_ERR "emi26: set_reset (%d) failed", reset_bit);
+	}
+	return response;
+}
+
+static int emi26_load_firmware (struct usb_device *dev)
+{
+	int err;
+	int i;
+	int pos = 0;	/* Position in hex record */
+	__u32 addr;	/* Address to write */
+	__u8 buf[1023];
+
+	/* Assert reset (stop the CPU in the EMI) */
+	err = emi26_set_reset(dev,1);
+	if (err < 0) {
+		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+		return err;
+	}
+
+	/* 1. We need to put the loader for the FPGA into the EZ-USB */
+	for (i=0; g_Loader[i].type == 0; i++) {
+		err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
+		if (err < 0) {
+			printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+			return err;
+		}
+	}
+
+	/* De-assert reset (let the CPU run) */
+	err = emi26_set_reset(dev,0);
+
+	/* 2. We upload the FPGA firmware into the EMI
+	 * Note: collect up to 1023 (yes!) bytes and send them with
+	 * a single request. This is _much_ faster! */
+	do {
+		i = 0;
+		addr = g_bitstream[pos].address;
+
+		/* intel hex records are terminated with type 0 element */
+		while ((g_bitstream[pos].type == 0) && (i + g_bitstream[pos].length < sizeof(buf))) {
+			memcpy(buf + i, g_bitstream[pos].data, g_bitstream[pos].length);
+			i += g_bitstream[pos].length;
+			pos++;
+		}
+		err = emi26_writememory(dev, addr, buf, i, ANCHOR_LOAD_FPGA);
+		if (err < 0) {
+			printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+			return err;
+		}
+	} while (i > 0);
+
+	/* Assert reset (stop the CPU in the EMI) */
+	err = emi26_set_reset(dev,1);
+	if (err < 0) {
+		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+		return err;
+	}
+
+	/* 3. We need to put the loader for the firmware into the EZ-USB (again...) */
+	for (i=0; g_Loader[i].type == 0; i++) {
+		err = emi26_writememory(dev, g_Loader[i].address, g_Loader[i].data, g_Loader[i].length, ANCHOR_LOAD_INTERNAL);
+		if (err < 0) {
+			printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+			return err;
+		}
+	}
+
+	/* De-assert reset (let the CPU run) */
+	err = emi26_set_reset(dev,0);
+	if (err < 0) {
+		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+		return err;
+	}
+
+	/* 4. We put the part of the firmware that lies in the external RAM into the EZ-USB */
+	for (i=0; g_Firmware[i].type == 0; i++) {
+		if (!INTERNAL_RAM(g_Firmware[i].address)) {
+			err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_EXTERNAL);
+			if (err < 0) {
+				printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+				return err;
+			}
+		}
+	}
+	
+	/* Assert reset (stop the CPU in the EMI) */
+	err = emi26_set_reset(dev,1);
+	if (err < 0) {
+		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+		return err;
+	}
+
+	for (i=0; g_Firmware[i].type == 0; i++) {
+		if (INTERNAL_RAM(g_Firmware[i].address)) {
+			err = emi26_writememory(dev, g_Firmware[i].address, g_Firmware[i].data, g_Firmware[i].length, ANCHOR_LOAD_INTERNAL);
+			if (err < 0) {
+				printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+				return err;
+			}
+		}
+	}
+
+	/* De-assert reset (let the CPU run) */
+	err = emi26_set_reset(dev,0);
+	if (err < 0) {
+		printk(KERN_ERR "%s - error loading firmware: error = %d", __FUNCTION__, err);
+		return err;
+	}
+
+	/* return 1 to fail the driver inialization
+	 * and give real driver change to load */
+	return 1;
+}
+
+static __devinitdata struct usb_device_id id_table [] = {
+	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
+	{ }                                             /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+static void * emi26_probe(struct usb_device *dev, unsigned int if_num, const struct usb_device_id *id)
+{
+	printk(KERN_INFO "%s start", __FUNCTION__); 
+	
+	if((dev->descriptor.idVendor == EMI26_VENDOR_ID) && (dev->descriptor.idProduct == EMI26_PRODUCT_ID)) {
+		emi26_load_firmware(dev);
+	}
+	
+	/* do not return the driver context, let real audio driver do that */
+	return 0;
+}
+
+static void emi26_disconnect(struct usb_device *dev, void *drv_context)
+{
+}
+
+struct usb_driver emi26_driver = {
+name:			"emi26 - firmware loader",
+probe:			emi26_probe,
+disconnect:		emi26_disconnect,
+id_table:		NULL,
+};
+
+static int __init emi26_init (void)
+{
+	usb_register (&emi26_driver);
+	return 0;
+}
+
+static void __exit emi26_exit (void)
+{
+	usb_deregister (&emi26_driver);
+}
+
+module_init(emi26_init);
+module_exit(emi26_exit);
+
+MODULE_AUTHOR("tapio laxström");
+MODULE_DESCRIPTION("Emagic EMI 2|6 firmware loader.");
+MODULE_LICENSE("GPL");
+
+/* vi:ai:syntax=c:sw=8:ts=8:tw=80
+ */
diff -Nru a/drivers/usb/misc/emi26_fw.h b/drivers/usb/misc/emi26_fw.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/emi26_fw.h	Sun Apr 14 12:16:57 2002
@@ -0,0 +1,5775 @@
+/*
+ * This file is generated from three different files, provided by Emagic.
+ */
+/* generated Fri Mar 8 15:11:35 EET 2002 */
+
+/*
+ * This firmware is for the Emagic EMI 2|6 Audio Interface
+ *
+ * The firmware contained herein is Copyright (c) 1999-2002 Emagic
+ * as an unpublished work. This notice does not imply unrestricted
+ * or public access to this firmware which is a trade secret of Emagic,
+ * and which may not be reproduced, used, sold or transferred to
+ * any third party without Emagic's written consent. All Rights Reserved.
+ *
+ * This firmware may not be modified and may only be used with the
+ * Emagic EMI 2|6 Audio Interface. Distribution and/or Modification of
+ * any driver which includes this firmware, in whole or in part,
+ * requires the inclusion of this statement.
+ */
+INTEL_HEX_RECORD g_bitstream[]={
+{  16, 0x8010, 0, {0xff,0xff,0xff,0xff,0xaa,0x99,0x55,0x66,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x07 } },
+{  16, 0x8020, 0, {0x30,0x01,0x60,0x01,0x00,0x00,0x00,0x0b,0x30,0x01,0x20,0x01,0x00,0x80,0x3f,0x2d } },
+{  16, 0x8030, 0, {0x30,0x00,0xc0,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x09 } },
+{  16, 0x8040, 0, {0x30,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x01 } },
+{  16, 0x8050, 0, {0x30,0x00,0x40,0x00,0x50,0x00,0x3e,0x04,0x08,0x12,0x10,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04 } },
+{  16, 0x8080, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x10,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8090, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x84 } },
+{  16, 0x80b0, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00 } },
+{  16, 0x80e0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8110, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8120, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04 } },
+{  16, 0x8140, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x13,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8150, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8170, 0, {0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8190, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84 } },
+{  16, 0x81a0, 0, {0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf7,0x10,0x01,0x14,0x00,0x25,0x00,0x05 } },
+{  16, 0x81b0, 0, {0x40,0x01,0x50,0x00,0x94,0x00,0x15,0x00,0x07,0x40,0x01,0xd0,0x00,0x94,0x00,0x25 } },
+{  16, 0x81c0, 0, {0x80,0x01,0x60,0x02,0xd8,0x00,0xf6,0x00,0x2f,0x80,0x02,0xe0,0x04,0xd8,0x37,0x44 } },
+{  16, 0x81d0, 0, {0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf2,0x00,0xcc,0x90,0x39,0x20 } },
+{  16, 0x81e0, 0, {0x0d,0x98,0x03,0xd2,0x00,0xe7,0x80,0x37,0x04,0x0e,0xf1,0x83,0x7e,0x00,0xdf,0x90 } },
+{  16, 0x81f0, 0, {0x31,0xe4,0x8f,0x79,0x03,0x7c,0x20,0xdf,0x22,0x33,0xc0,0x0c,0xf0,0x22,0x30,0x00 } },
+{  16, 0x8200, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0x62,0x00,0x80,0x24,0x22,0x20 } },
+{  16, 0x8210, 0, {0x08,0x98,0x12,0xe2,0x00,0x8b,0x81,0x20,0x94,0x08,0x74,0x02,0x2e,0x00,0x8a,0x01 } },
+{  16, 0x8220, 0, {0x22,0xc8,0x08,0x92,0x02,0x3d,0x80,0x8b,0x60,0x22,0x80,0x08,0xb0,0x02,0x20,0x04 } },
+{  16, 0x8230, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc8,0x00,0xa0,0x00,0x20,0x00 } },
+{  16, 0x8240, 0, {0x0b,0x10,0x02,0xc0,0x00,0xa1,0x00,0x24,0x09,0x4a,0x32,0x02,0x48,0x00,0xb1,0x00 } },
+{  16, 0x8250, 0, {0x62,0xc0,0x09,0xa0,0x46,0xcc,0x24,0x93,0x49,0x2a,0x80,0x48,0x30,0x22,0x62,0x01 } },
+{  16, 0x8260, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa8,0x12,0xa8,0x00,0x22,0x00 } },
+{  16, 0x8270, 0, {0x08,0x90,0x02,0xe0,0x00,0x89,0x80,0x22,0x44,0x08,0xb0,0x12,0xa8,0x00,0xa9,0x40 } },
+{  16, 0x8280, 0, {0x22,0xc0,0x08,0x90,0x82,0xac,0x00,0x9b,0x04,0x2a,0xc4,0x08,0xb0,0x02,0x70,0x04 } },
+{  16, 0x8290, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x84,0x00,0xe9,0x80,0xb2,0x64 } },
+{  16, 0x82a0, 0, {0x4d,0xa0,0x03,0xea,0x20,0xe9,0xc0,0x36,0x40,0x0e,0xb0,0x03,0x44,0x00,0xfb,0x90 } },
+{  16, 0x82b0, 0, {0xb2,0x88,0x0d,0xbc,0x03,0xec,0x08,0x5b,0x00,0x38,0x60,0x2c,0xb0,0x63,0x40,0x04 } },
+{  16, 0x82c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x26,0xdd,0x90,0x37,0x40 } },
+{  16, 0x82d0, 0, {0x4f,0xe0,0x13,0xf2,0x80,0xfd,0x00,0x3d,0xa0,0x0d,0x70,0x03,0x75,0x00,0x5e,0x00 } },
+{  16, 0x82e0, 0, {0x3f,0xa4,0x0d,0xf9,0x03,0x5c,0x10,0xeb,0x00,0x37,0x20,0x0f,0x30,0x03,0xb8,0x00 } },
+{  16, 0x82f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xe9,0x80,0x32,0x40 } },
+{  16, 0x8300, 0, {0x0c,0xa1,0x83,0xe8,0x00,0xe9,0x00,0x32,0x42,0x0e,0xb0,0x03,0xac,0x48,0xe9,0x00 } },
+{  16, 0x8310, 0, {0x3a,0x80,0x0e,0xa4,0x03,0xec,0x00,0xeb,0x00,0xb2,0x03,0x0e,0xb0,0x0b,0x10,0x04 } },
+{  16, 0x8320, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2e,0x80,0x89,0xd1,0x20,0x40 } },
+{  16, 0x8330, 0, {0x08,0xa0,0x02,0xc0,0x00,0x81,0x80,0x22,0x58,0x08,0xf5,0x02,0x2f,0x40,0x8b,0x00 } },
+{  16, 0x8340, 0, {0x20,0xc0,0x08,0x30,0x43,0x7c,0x00,0x87,0x00,0x22,0x40,0x08,0xf0,0x02,0x32,0x00 } },
+{  16, 0x8350, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x42,0x01,0x9a,0x44,0x28,0xa2 } },
+{  16, 0x8360, 0, {0x08,0x18,0x02,0xc0,0x80,0xa1,0x80,0xa0,0x00,0x08,0x30,0x02,0x8e,0x00,0xab,0x00 } },
+{  16, 0x8370, 0, {0x2c,0x40,0x0a,0x30,0x02,0x0c,0x00,0xa3,0x00,0x20,0x44,0x0a,0x30,0x02,0x38,0x00 } },
+{  16, 0x8380, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x32,0x00,0x96,0x82,0x2b,0xa2 } },
+{  16, 0x8390, 0, {0x88,0x5a,0x02,0xf2,0x00,0x05,0x80,0x29,0xa0,0x08,0x78,0x42,0xbe,0x00,0x8e,0x84 } },
+{  16, 0x83a0, 0, {0x2f,0x61,0x0a,0xd8,0x02,0x4e,0x10,0xa7,0x80,0x20,0x28,0x08,0x78,0x02,0x18,0x00 } },
+{  16, 0x83b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x00,0xf2,0x24,0x38,0x80 } },
+{  16, 0x83c0, 0, {0x2c,0x1a,0x03,0xc4,0x00,0xe0,0x58,0xa0,0x80,0x2e,0x30,0x03,0x88,0x41,0xe3,0x02 } },
+{  16, 0x83d0, 0, {0x3c,0x40,0x06,0x20,0x03,0x8c,0x00,0xe3,0x00,0x10,0x00,0x0e,0x31,0x43,0x12,0x02 } },
+{  16, 0x83e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x98,0x00,0xee,0x01,0x37,0x84 } },
+{  16, 0x83f0, 0, {0x9f,0xd9,0x03,0xf0,0x48,0xfd,0x10,0x37,0xc0,0x07,0xb0,0x03,0x5c,0x00,0xf6,0x10 } },
+{  16, 0x8400, 0, {0x33,0xc0,0x0d,0xe1,0x03,0xed,0x20,0xdf,0x10,0x3f,0x48,0x0f,0xf0,0x23,0xd0,0x06 } },
+{  16, 0x8410, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x02,0xcb,0x80,0x30,0xc0 } },
+{  16, 0x8420, 0, {0x0c,0xa0,0x03,0xe2,0x02,0xc9,0x00,0x3a,0x40,0x0d,0xb6,0x03,0x64,0x00,0xeb,0x00 } },
+{  16, 0x8430, 0, {0x3e,0xc0,0x0f,0xb0,0x03,0xed,0x00,0xfb,0x01,0x3e,0xe0,0x0c,0xb0,0x02,0xea,0x00 } },
+{  16, 0x8440, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x00,0x87,0x00,0x21,0xc0 } },
+{  16, 0x8450, 0, {0x28,0x60,0x02,0xd0,0x00,0x85,0x00,0x2d,0x80,0x48,0xf0,0x82,0x1c,0x00,0xb7,0x00 } },
+{  16, 0x8460, 0, {0x2d,0x00,0x0b,0x50,0x02,0xdc,0x00,0xb7,0xa0,0x2f,0x80,0x28,0x7a,0x02,0xd2,0x04 } },
+{  16, 0x8470, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc1,0x00,0xbe,0x00,0x87,0x80,0x21,0xe0 } },
+{  16, 0x8480, 0, {0x28,0x68,0x02,0xd7,0x00,0x84,0x80,0x2d,0xe0,0x49,0x79,0x06,0x53,0x09,0xb5,0x80 } },
+{  16, 0x8490, 0, {0x2d,0xe2,0x0b,0x78,0x02,0xde,0x80,0xb7,0x90,0x2d,0xb0,0x08,0x79,0x02,0xf0,0x00 } },
+{  16, 0x84a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x10,0x83,0x01,0x28,0xc8 } },
+{  16, 0x84b0, 0, {0x08,0x20,0x02,0xc2,0x06,0x81,0x00,0x2c,0xc8,0x88,0x30,0x62,0x0e,0x21,0xb3,0xa0 } },
+{  16, 0x84c0, 0, {0x2c,0xc1,0x0b,0xb6,0x02,0xcc,0x00,0xb3,0x00,0x2c,0xe0,0x08,0x30,0x02,0xd2,0x04 } },
+{  16, 0x84d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xca,0x40,0xb0,0x80 } },
+{  16, 0x84e0, 0, {0x0c,0x2c,0x02,0xf8,0x00,0xc6,0x20,0x3f,0x90,0x0d,0xa0,0x03,0x7b,0x01,0xee,0xe0 } },
+{  16, 0x84f0, 0, {0x3f,0xb4,0x0f,0xec,0x03,0xe8,0x00,0xfa,0x00,0x3f,0xa0,0x0c,0xa0,0x03,0xfa,0x04 } },
+{  16, 0x8500, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe3,0x00,0xf8,0x09,0x26,0x00 } },
+{  16, 0x8510, 0, {0x0f,0xc1,0x83,0xe0,0x10,0xf8,0x40,0x3c,0x00,0x0f,0x80,0x03,0xe0,0x01,0xf8,0x00 } },
+{  16, 0x8520, 0, {0x3e,0x00,0x0f,0x81,0x03,0xe0,0x04,0xf8,0x00,0x3e,0x10,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0x8530, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x02,0xc9,0x00,0x3e,0x40 } },
+{  16, 0x8540, 0, {0x4f,0x90,0x63,0x26,0x84,0x39,0x02,0xb2,0x40,0x0c,0x91,0x03,0x24,0x00,0xf9,0x00 } },
+{  16, 0x8550, 0, {0x3e,0x40,0x0f,0x90,0x03,0x24,0x00,0xf1,0x00,0x3a,0x44,0x0f,0x90,0x03,0xc2,0x04 } },
+{  16, 0x8560, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x45,0x00,0x89,0x40,0x2e,0x40 } },
+{  16, 0x8570, 0, {0x08,0x92,0x0a,0x24,0x00,0xb9,0x31,0x22,0x60,0x88,0x94,0x8a,0x24,0x20,0xb9,0x00 } },
+{  16, 0x8580, 0, {0x2e,0x40,0x0b,0x90,0x02,0x24,0x00,0xb9,0x00,0x22,0x68,0x0b,0x90,0x02,0xe0,0x00 } },
+{  16, 0x8590, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0xa0,0x8d,0x84,0x2f,0x40 } },
+{  16, 0x85a0, 0, {0x0b,0xd1,0x02,0x24,0x00,0xb9,0x00,0x22,0x4a,0x08,0x10,0x02,0x2c,0x40,0xb9,0x00 } },
+{  16, 0x85b0, 0, {0x2e,0x40,0x0b,0x90,0x02,0x24,0x00,0xb9,0x00,0x2a,0x40,0x0b,0x90,0x02,0xc6,0x00 } },
+{  16, 0x85c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x14,0x00,0x85,0x80,0x2d,0x40 } },
+{  16, 0x85d0, 0, {0x08,0x50,0x02,0x04,0x0c,0xb9,0x00,0xa0,0x50,0x08,0x14,0x22,0x04,0x00,0xb1,0x00 } },
+{  16, 0x85e0, 0, {0x2c,0x40,0x0b,0x10,0x02,0x04,0x00,0xb1,0x28,0x20,0x4a,0x0b,0x13,0x02,0xc2,0x01 } },
+{  16, 0x85f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xc0,0x50,0x3e,0x80 } },
+{  16, 0x8600, 0, {0x0f,0xc0,0x43,0x20,0x00,0xf8,0x00,0x30,0x00,0x2c,0x80,0x23,0x20,0x00,0xf8,0x51 } },
+{  16, 0x8610, 0, {0x3e,0x14,0x8f,0x85,0x0b,0x21,0x40,0xf8,0x70,0x3a,0x08,0x0f,0x84,0x83,0xee,0x03 } },
+{  16, 0x8620, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xc4,0x00,0xf9,0x04,0x3e,0x40 } },
+{  16, 0x8630, 0, {0x0f,0x90,0x23,0xd4,0x00,0xfd,0x00,0x3f,0x50,0x0f,0x94,0x03,0xf4,0x04,0xfd,0x00 } },
+{  16, 0x8640, 0, {0x3f,0x41,0x8f,0xd0,0x43,0xe5,0x0c,0xf9,0x02,0x3f,0x4a,0x0f,0x92,0x03,0xe6,0x02 } },
+{  16, 0x8650, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xd4,0x01,0xfd,0x00,0x3d,0x40 } },
+{  16, 0x8660, 0, {0x0c,0xd0,0x13,0xf4,0x00,0xd5,0x00,0x33,0x6a,0x1c,0xdc,0x83,0x34,0x00,0xd1,0x04 } },
+{  16, 0x8670, 0, {0x3e,0x50,0x0c,0x91,0x03,0xe6,0xc0,0xdd,0xb0,0x33,0x6a,0x2c,0x9c,0x83,0xe6,0x00 } },
+{  16, 0x8680, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x09,0xf8,0x80,0x2e,0x00 } },
+{  16, 0x8690, 0, {0x88,0x80,0x00,0xe8,0x00,0xba,0x00,0x22,0xb0,0x08,0x8e,0x02,0x28,0x00,0x88,0xa8 } },
+{  16, 0x86a0, 0, {0x26,0x28,0x08,0x8a,0x22,0xe2,0x00,0x88,0xe4,0x22,0x30,0x08,0x8c,0x02,0xce,0x04 } },
+{  16, 0x86b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x28,0x2e,0x40 } },
+{  16, 0x86c0, 0, {0x08,0x10,0x02,0xc4,0x00,0x99,0x00,0x20,0x42,0x48,0x10,0x02,0x64,0x01,0x91,0x80 } },
+{  16, 0x86d0, 0, {0x2c,0x48,0x08,0x10,0x02,0xc4,0xc0,0x81,0x40,0x20,0x4a,0x08,0x12,0x02,0xc2,0x01 } },
+{  16, 0x86e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x94,0xa9,0x02,0x2e,0x40 } },
+{  16, 0x86f0, 0, {0x0a,0x90,0x02,0x64,0x00,0xb9,0x00,0x82,0x60,0x08,0x90,0x02,0x66,0x00,0x89,0x10 } },
+{  16, 0x8700, 0, {0x24,0x62,0x08,0x90,0x02,0xe4,0x00,0x89,0x02,0x22,0x40,0x18,0x90,0x02,0xc6,0x04 } },
+{  16, 0x8710, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe6,0x00,0xb9,0x04,0x3e,0x40 } },
+{  16, 0x8720, 0, {0x0c,0x90,0x13,0xe4,0x00,0xd1,0xc0,0x12,0x50,0x28,0x90,0x03,0x44,0x00,0xd9,0x00 } },
+{  16, 0x8730, 0, {0x3e,0x40,0x28,0x92,0x03,0xe4,0x02,0xd9,0x00,0x32,0x42,0x8c,0x90,0x12,0xe8,0x04 } },
+{  16, 0x8740, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa6,0x20,0xf9,0x00,0x3e,0x41 } },
+{  16, 0x8750, 0, {0x2d,0x90,0x03,0xe4,0x00,0xf9,0x20,0x3e,0x40,0x4f,0x90,0x01,0xa4,0x00,0xf9,0x00 } },
+{  16, 0x8760, 0, {0x36,0x40,0x8f,0x92,0x07,0xe4,0x00,0xf1,0x00,0xbe,0x40,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0x8770, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xc8,0x00,0x3e,0x20 } },
+{  16, 0x8780, 0, {0x0c,0x80,0x03,0xe0,0x40,0xf8,0x00,0x36,0x12,0x2c,0x00,0x03,0xe0,0xc0,0xf8,0x00 } },
+{  16, 0x8790, 0, {0x32,0x10,0x0d,0x84,0x03,0xa0,0x00,0xf8,0x02,0x3e,0x08,0x0f,0x80,0x00,0xca,0x04 } },
+{  16, 0x87a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x3a,0x90,0x8e,0x00,0x2d,0xa0 } },
+{  16, 0x87b0, 0, {0x80,0xe8,0x02,0xfa,0x00,0xbe,0x40,0x23,0x80,0x08,0xe8,0x02,0xfa,0x00,0x8a,0x00 } },
+{  16, 0x87c0, 0, {0x36,0x80,0x08,0xa0,0x02,0xe8,0x00,0xba,0x00,0x2f,0x80,0x0b,0xa0,0x03,0x8a,0x00 } },
+{  16, 0x87d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x46,0x02,0x83,0x00,0x2c,0x80 } },
+{  16, 0x87e0, 0, {0x08,0x22,0x42,0xc6,0x80,0xb1,0x60,0x2e,0xf4,0x08,0x38,0x22,0xce,0x00,0xa3,0x00 } },
+{  16, 0x87f0, 0, {0x20,0xc0,0x08,0x30,0x02,0xac,0x00,0xb1,0x00,0x2e,0x40,0x0b,0x30,0x02,0xca,0x00 } },
+{  16, 0x8800, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x02,0x85,0x01,0x2d,0xc2 } },
+{  16, 0x8810, 0, {0xa8,0x44,0x02,0xd4,0x00,0xbd,0x01,0x29,0x40,0x18,0x68,0xd2,0xdc,0x00,0x8f,0x80 } },
+{  16, 0x8820, 0, {0x25,0xcc,0x28,0x73,0x42,0xdc,0x80,0xb5,0x30,0x2d,0xc0,0x1b,0x72,0x02,0xe8,0x00 } },
+{  16, 0x8830, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x04,0xc6,0x82,0x3d,0xe0 } },
+{  16, 0x8840, 0, {0x0c,0x48,0x12,0xd6,0x10,0xf5,0x80,0x3c,0xa0,0x0c,0x70,0x03,0xde,0x00,0xe7,0x90 } },
+{  16, 0x8850, 0, {0x23,0xea,0x04,0x7a,0x03,0x9e,0x00,0xf5,0x80,0x3d,0xe0,0x0f,0x7a,0x03,0xea,0x02 } },
+{  16, 0x8860, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0d,0xac,0x00,0x9c,0x00,0x3e,0xc0 } },
+{  16, 0x8870, 0, {0x0f,0x80,0x03,0xe4,0x10,0xf9,0x00,0x36,0x01,0x0f,0xa0,0x03,0xc0,0x00,0xeb,0x00 } },
+{  16, 0x8880, 0, {0x3e,0xd8,0x4e,0xb0,0x83,0xec,0x00,0xf9,0x00,0x3e,0xc0,0x0f,0xb4,0x43,0x82,0x06 } },
+{  16, 0x8890, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xde,0x00,0xcf,0x84,0x31,0xe0 } },
+{  16, 0x88a0, 0, {0x0e,0xc8,0x43,0xd6,0x00,0xcd,0x80,0x33,0xe0,0xcd,0xd9,0x03,0x3a,0x00,0xff,0x88 } },
+{  16, 0x88b0, 0, {0x33,0xe0,0x0f,0xf9,0x13,0xfe,0x24,0xfd,0x80,0x3f,0x20,0x0c,0xf6,0x83,0x10,0x00 } },
+{  16, 0x88c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0x85,0x00,0x21,0xc4 } },
+{  16, 0x88d0, 0, {0x28,0x40,0x82,0xd0,0x00,0xd5,0x00,0x23,0x80,0x48,0xc9,0x02,0x1c,0x00,0xb7,0x00 } },
+{  16, 0x88e0, 0, {0x21,0xc0,0x0b,0x71,0x02,0xde,0x80,0xb5,0x10,0x2d,0xc0,0x28,0xf0,0x02,0x2a,0x04 } },
+{  16, 0x88f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x9c,0x00,0x96,0x00,0x21,0xc0 } },
+{  16, 0x8900, 0, {0x0a,0x41,0x02,0xf5,0x40,0x8d,0x00,0x21,0x40,0x09,0x52,0x02,0x98,0x20,0xb7,0x00 } },
+{  16, 0x8910, 0, {0x21,0xc0,0x0b,0x70,0x06,0xdc,0x80,0xb5,0x00,0x2d,0xc0,0x08,0x70,0x02,0x04,0x00 } },
+{  16, 0x8920, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xcc,0x10,0x98,0x00,0x00,0xc0 } },
+{  16, 0x8930, 0, {0x88,0x04,0x82,0xc0,0x00,0x91,0x04,0x20,0x03,0x09,0x00,0x02,0x8a,0x00,0xb3,0x0a } },
+{  16, 0x8940, 0, {0x20,0xc4,0x8b,0x34,0x02,0xcc,0x00,0xb9,0x00,0x2c,0xc0,0x00,0x30,0x02,0x18,0x04 } },
+{  16, 0x8950, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x15,0xac,0x00,0xdb,0x00,0xb0,0xc0 } },
+{  16, 0x8960, 0, {0x0e,0x9c,0x02,0xc5,0x00,0xc1,0x10,0xb2,0xc0,0x0d,0xb0,0x0b,0xa7,0x08,0xff,0x00 } },
+{  16, 0x8970, 0, {0xb3,0xc0,0x0f,0xfa,0x03,0xfc,0x00,0xfd,0x00,0x3e,0xd4,0x0c,0xf0,0x0b,0x2e,0x04 } },
+{  16, 0x8980, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x04,0xed,0x00,0x3e,0x40 } },
+{  16, 0x8990, 0, {0x0f,0x84,0x03,0xe5,0x40,0xf9,0x40,0x3e,0x60,0xce,0xb4,0x43,0x64,0x00,0xfb,0x80 } },
+{  16, 0x89a0, 0, {0x3e,0xc2,0x0f,0xb0,0x13,0xec,0x00,0xf9,0x02,0x3e,0xc0,0x4f,0xb0,0x03,0xe1,0x00 } },
+{  16, 0x89b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x10,0xff,0x00,0xce,0x00,0x33,0xc0 } },
+{  16, 0x89c0, 0, {0x0e,0xc0,0x07,0x74,0x04,0xec,0x00,0x11,0x80,0x0c,0xca,0x03,0xfe,0x60,0xff,0x00 } },
+{  16, 0x89d0, 0, {0x3f,0xc0,0x0f,0xf0,0x83,0x3c,0x00,0xdd,0x00,0xb3,0x50,0x2c,0xf0,0x03,0x20,0x04 } },
+{  16, 0x89e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x4c,0x04,0x8b,0x0b,0x22,0x70 } },
+{  16, 0x89f0, 0, {0x08,0x08,0x03,0x67,0x20,0x8a,0x88,0xa2,0x00,0x28,0x84,0x02,0xe7,0x00,0xbb,0x00 } },
+{  16, 0x8a00, 0, {0x3e,0xc0,0x0b,0xb0,0x02,0x2c,0x00,0xb9,0x00,0x22,0x61,0x08,0xb0,0x03,0x60,0x40 } },
+{  16, 0x8a10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x20,0x22,0xe2 } },
+{  16, 0x8a20, 0, {0x0a,0x8c,0x02,0x26,0x00,0xa9,0x80,0x2a,0xc0,0x08,0xb4,0x42,0xed,0x00,0xbb,0x00 } },
+{  16, 0x8a30, 0, {0x2e,0xc0,0x0b,0x30,0x02,0x2c,0x00,0xb9,0x00,0x20,0x80,0x08,0x30,0x02,0x60,0x00 } },
+{  16, 0x8a40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0e,0x01,0x81,0x00,0xa0,0xc0 } },
+{  16, 0x8a50, 0, {0x08,0x81,0x02,0x44,0x00,0x81,0x00,0x28,0x81,0x08,0x32,0x02,0xcc,0x00,0xb3,0x00 } },
+{  16, 0x8a60, 0, {0x28,0xc0,0x0b,0x30,0x02,0x0c,0x80,0xb1,0x00,0x20,0xc0,0x08,0x30,0x12,0x42,0x01 } },
+{  16, 0x8a70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0d,0x6c,0x00,0xc2,0x01,0x32,0xc0 } },
+{  16, 0x8a80, 0, {0x2e,0x80,0x16,0x2c,0x08,0xe9,0x00,0x3a,0x40,0x0c,0x80,0x03,0xec,0x00,0xf7,0x00 } },
+{  16, 0x8a90, 0, {0x2f,0xc0,0x0f,0xf0,0x0b,0x2c,0x00,0xd9,0x00,0x30,0x40,0x0c,0xf0,0x03,0x60,0x03 } },
+{  16, 0x8aa0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x0d,0xf8,0x08,0xff,0x00,0x3f,0xc0 } },
+{  16, 0x8ab0, 0, {0x0f,0xc2,0x17,0xfc,0x00,0xf7,0x00,0x37,0x00,0x0f,0x84,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0x8ac0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xed,0x00,0xfd,0x00,0x3f,0x40,0x0f,0xf0,0x03,0xe8,0x06 } },
+{  16, 0x8ad0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xcf,0x30,0x17,0x48 } },
+{  16, 0x8ae0, 0, {0x0c,0x59,0x03,0xb9,0x00,0xdf,0x28,0x35,0x24,0x0d,0x82,0xa3,0x7c,0x80,0xff,0x00 } },
+{  16, 0x8af0, 0, {0x3f,0xc8,0x0f,0xf2,0x03,0xe4,0xa0,0xef,0x80,0x3f,0xe1,0x8c,0xd8,0x43,0x30,0x00 } },
+{  16, 0x8b00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xed,0x48,0x89,0x34,0xa3,0x70 } },
+{  16, 0x8b10, 0, {0x28,0xb0,0x23,0x60,0x00,0x8b,0xc0,0x22,0x40,0x08,0xb4,0x82,0x2f,0x40,0xbf,0xd1 } },
+{  16, 0x8b20, 0, {0x6f,0xf4,0x8e,0xbd,0x02,0xe7,0x00,0xbb,0x80,0x3a,0xe0,0x08,0x98,0x0a,0x28,0x04 } },
+{  16, 0x8b30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0xb0,0x91,0x00,0xa8,0x50 } },
+{  16, 0x8b40, 0, {0x08,0xb2,0x02,0xc8,0x84,0x93,0x00,0x24,0x49,0x0b,0x02,0x02,0x4c,0x00,0xb3,0x04 } },
+{  16, 0x8b50, 0, {0x2c,0xc0,0x0b,0x30,0x42,0x84,0x00,0xb3,0x00,0x2e,0x00,0x0a,0xb0,0x12,0x22,0x01 } },
+{  16, 0x8b60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xac,0x02,0x99,0x18,0x2a,0x44 } },
+{  16, 0x8b70, 0, {0x08,0xb8,0x82,0xa2,0x01,0xbb,0x00,0x28,0x60,0x0a,0xa0,0x12,0x6c,0x00,0xbb,0x00 } },
+{  16, 0x8b80, 0, {0x6e,0xc0,0x0a,0xb0,0x02,0xe4,0x00,0xbb,0x00,0x2a,0x00,0x2a,0xb0,0x02,0x38,0x04 } },
+{  16, 0x8b90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0xe4,0x08,0xda,0xc0,0x3a,0x60 } },
+{  16, 0x8ba0, 0, {0x0c,0x18,0x0a,0xeb,0x04,0xdb,0x00,0x36,0xe0,0x07,0x85,0x83,0x6c,0x00,0xfb,0x00 } },
+{  16, 0x8bb0, 0, {0x2e,0xc0,0x0f,0xb0,0x43,0xe4,0x00,0xeb,0x00,0x3e,0x88,0x0e,0x18,0x03,0x10,0x04 } },
+{  16, 0x8bc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x41,0x9c,0x10,0xe9,0x00,0x37,0x60 } },
+{  16, 0x8bd0, 0, {0x87,0xf0,0x17,0x70,0x00,0xcf,0x01,0x37,0xc0,0x4c,0x98,0x03,0xbc,0x00,0xfb,0x00 } },
+{  16, 0x8be0, 0, {0x3f,0xc2,0x0f,0xf0,0x03,0xe4,0x00,0xff,0x40,0x3f,0xe4,0x0d,0xd9,0x03,0xf0,0x00 } },
+{  16, 0x8bf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa4,0x00,0xf4,0x00,0x30,0x40 } },
+{  16, 0x8c00, 0, {0x0f,0xb4,0x03,0x99,0x00,0xfb,0x00,0x3e,0xc0,0x0d,0x04,0x23,0x2c,0x08,0xfb,0x88 } },
+{  16, 0x8c10, 0, {0x32,0xc0,0x0f,0xb0,0x03,0xe6,0x00,0xdb,0x10,0x3e,0x02,0x0f,0xb0,0x83,0xd0,0x04 } },
+{  16, 0x8c20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xb9,0x50,0xa2,0x48 } },
+{  16, 0x8c30, 0, {0x8b,0xb0,0x03,0x20,0x00,0xd7,0x80,0x2e,0xd8,0x00,0x80,0x02,0x3c,0x00,0xbf,0x80 } },
+{  16, 0x8c40, 0, {0x23,0xe8,0x8b,0xf0,0x02,0xf4,0x40,0x8b,0x40,0x0c,0x42,0x03,0xb6,0x02,0xf2,0x00 } },
+{  16, 0x8c50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb2,0x44,0x00,0xc8 } },
+{  16, 0x8c60, 0, {0x0b,0x30,0x12,0x8c,0x00,0xa3,0x80,0x24,0xc8,0x0b,0x00,0x0a,0xcc,0x00,0xb3,0x44 } },
+{  16, 0x8c70, 0, {0x04,0xc0,0x1b,0x36,0x02,0xc5,0x01,0x83,0x0c,0x2c,0xa0,0x0b,0x30,0x02,0xf8,0x00 } },
+{  16, 0x8c80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x08,0xb7,0x90,0x21,0x64 } },
+{  16, 0x8c90, 0, {0x0b,0xf8,0x02,0x4a,0x04,0x97,0x81,0x2f,0xe4,0x0a,0x78,0x02,0x9e,0x00,0xb7,0x80 } },
+{  16, 0x8ca0, 0, {0x21,0xe0,0x8b,0x78,0x82,0xd6,0x86,0x87,0x84,0x2d,0xa0,0x0b,0x78,0x02,0xc0,0x00 } },
+{  16, 0x8cb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x04,0x00,0xf2,0x00,0x30,0xc0 } },
+{  16, 0x8cc0, 0, {0x0f,0x30,0x03,0x8c,0x00,0xe3,0x0a,0x3c,0xc0,0x0f,0x18,0x03,0x8c,0x00,0xf3,0x02 } },
+{  16, 0x8cd0, 0, {0x30,0xc0,0x1f,0x30,0x01,0xc6,0x80,0xc3,0x00,0x3c,0xc0,0x0f,0x12,0x03,0xda,0x02 } },
+{  16, 0x8ce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x0d,0xbc,0x00,0xff,0x00,0x3f,0x41 } },
+{  16, 0x8cf0, 0, {0x0f,0xf0,0x03,0xb8,0x08,0xff,0x08,0x3f,0xc0,0x0d,0xf0,0x03,0x3c,0x20,0xff,0x08 } },
+{  16, 0x8d00, 0, {0x3b,0xd2,0x0f,0xf0,0x03,0xf4,0x40,0xef,0x00,0x3f,0xc4,0x0f,0xd0,0x03,0xd0,0x06 } },
+{  16, 0x8d10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x00,0xfe,0x00,0x32,0xc2 } },
+{  16, 0x8d20, 0, {0x0c,0x30,0x0b,0x26,0x00,0xfb,0x80,0x36,0xc0,0x0d,0xa0,0x03,0xec,0x00,0xfb,0xe0 } },
+{  16, 0x8d30, 0, {0x32,0xd0,0x0f,0xb8,0x43,0x64,0x44,0xdb,0x04,0x3e,0x80,0x0f,0xb0,0x03,0xe2,0x00 } },
+{  16, 0x8d40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb7,0x00,0xa1,0xc0 } },
+{  16, 0x8d50, 0, {0x88,0x70,0x03,0x10,0x00,0xb7,0x20,0x21,0xc0,0x08,0x70,0x02,0xdc,0x80,0xb3,0x30 } },
+{  16, 0x8d60, 0, {0x31,0xc8,0x0b,0x74,0x02,0x14,0x00,0x87,0x40,0x2d,0xc0,0x4b,0x70,0x02,0xd2,0x00 } },
+{  16, 0x8d70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x96,0x20,0xb6,0x80,0x20,0xe0 } },
+{  16, 0x8d80, 0, {0x28,0xf8,0x02,0x94,0x10,0xb7,0x81,0x27,0xe2,0x09,0x78,0x02,0xde,0x00,0xb7,0xa0 } },
+{  16, 0x8d90, 0, {0xa9,0xe8,0x0b,0x38,0x02,0x76,0x00,0x87,0x80,0x2d,0xa0,0x0b,0x58,0x02,0xf0,0x00 } },
+{  16, 0x8da0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xce,0x10,0xb3,0x00,0x20,0xc4 } },
+{  16, 0x8db0, 0, {0x08,0x20,0x02,0x80,0x10,0xb3,0x00,0x22,0xc8,0x08,0xb0,0x02,0xcc,0x11,0xb3,0x02 } },
+{  16, 0x8dc0, 0, {0x28,0xc0,0x0b,0x30,0x02,0x04,0x00,0x93,0x80,0x2c,0xd2,0x0b,0x10,0x02,0xd2,0x04 } },
+{  16, 0x8dd0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfe,0x40,0x32,0xa0 } },
+{  16, 0x8de0, 0, {0x0c,0xe4,0x03,0x98,0x80,0xfa,0x00,0x37,0xa0,0x0d,0xe0,0x83,0xe8,0x00,0xfe,0x00 } },
+{  16, 0x8df0, 0, {0x3a,0x80,0x0b,0xa0,0x03,0x68,0x00,0xd8,0xa0,0x3f,0x90,0x0f,0xa0,0x03,0xfa,0x04 } },
+{  16, 0x8e00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x08,0xf8,0x08,0x3e,0x00 } },
+{  16, 0x8e10, 0, {0x0f,0x80,0x03,0x20,0x00,0xf8,0x40,0x3e,0x00,0x0f,0x80,0x03,0xe0,0x00,0xf8,0x04 } },
+{  16, 0x8e20, 0, {0x30,0x10,0x0f,0x80,0x03,0xe0,0x02,0xe8,0x00,0x3e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0x8e30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf1,0x00,0x32,0x40 } },
+{  16, 0x8e40, 0, {0x0e,0x90,0x83,0xa4,0x00,0xc9,0x80,0x3e,0x40,0x0e,0x90,0x03,0xa4,0x00,0xf9,0x00 } },
+{  16, 0x8e50, 0, {0x3e,0x40,0x0c,0x90,0x03,0xe4,0x00,0xc8,0x00,0x3e,0x40,0x8f,0x90,0x03,0x02,0x04 } },
+{  16, 0x8e60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x40,0xa0,0x62 } },
+{  16, 0x8e70, 0, {0x08,0x10,0x02,0x24,0x10,0x89,0x00,0x2e,0x40,0x08,0x90,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0x8e80, 0, {0x2e,0x52,0x08,0x94,0x02,0xc4,0x00,0x89,0x40,0x2e,0x40,0x0b,0x10,0x03,0x60,0x10 } },
+{  16, 0x8e90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x18,0x22,0x44 } },
+{  16, 0x8ea0, 0, {0x0a,0x90,0x02,0xac,0x00,0x89,0x10,0x2e,0xc0,0x0a,0x90,0x02,0xa4,0x00,0xb9,0x80 } },
+{  16, 0x8eb0, 0, {0x2e,0x60,0x08,0x98,0x02,0xe6,0x02,0x89,0x08,0x2e,0x40,0x0b,0x90,0x02,0x06,0x00 } },
+{  16, 0x8ec0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0xb1,0x20,0xa0,0x48 } },
+{  16, 0x8ed0, 0, {0x08,0x90,0x02,0x24,0x08,0x81,0x23,0x2c,0x50,0x08,0x10,0x02,0x04,0x80,0xb1,0x20 } },
+{  16, 0x8ee0, 0, {0x2c,0x48,0x28,0x12,0x02,0xe4,0x80,0x81,0x20,0x2c,0x40,0x0b,0x98,0x02,0x42,0x05 } },
+{  16, 0x8ef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x50,0x32,0x00 } },
+{  16, 0x8f00, 0, {0x0e,0x85,0x03,0xa1,0xe0,0xca,0x00,0x3e,0x00,0x0e,0x85,0x03,0xa0,0x00,0xf8,0x00 } },
+{  16, 0x8f10, 0, {0x2e,0x00,0x9c,0xa0,0x03,0xe0,0x00,0xc8,0x28,0x3e,0x00,0x0f,0x80,0x03,0x2e,0x01 } },
+{  16, 0x8f20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xf5,0x10,0x3f,0x44 } },
+{  16, 0x8f30, 0, {0x0f,0xd0,0x03,0xf4,0x00,0xf1,0x10,0x3d,0x40,0x8f,0xd4,0x03,0xe4,0x50,0xf9,0x10 } },
+{  16, 0x8f40, 0, {0x3e,0x45,0x0f,0x91,0x03,0xd4,0x40,0xfc,0x00,0x3f,0xc0,0x8f,0xd0,0x23,0xe6,0x04 } },
+{  16, 0x8f50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0x20,0xcd,0xa8,0x33,0x40 } },
+{  16, 0x8f60, 0, {0x8d,0xd0,0x03,0x26,0x80,0xcd,0x00,0x3d,0x50,0x0c,0x9a,0x03,0x64,0x00,0xf9,0xa0 } },
+{  16, 0x8f70, 0, {0x7a,0x6a,0x0f,0x9a,0x63,0xe6,0x80,0xc9,0x80,0x3e,0x40,0x0f,0x90,0x03,0x06,0x00 } },
+{  16, 0x8f80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x00,0x88,0xe0,0x36,0x00 } },
+{  16, 0x8f90, 0, {0x08,0x80,0x0a,0x21,0x42,0xc8,0x00,0x2e,0x29,0x0c,0xa4,0x42,0x20,0x00,0xb8,0x40 } },
+{  16, 0x8fa0, 0, {0x2e,0x00,0x0b,0x81,0x02,0xe1,0x00,0x88,0x02,0x3a,0x01,0x0b,0xc0,0x02,0x0e,0x04 } },
+{  16, 0x8fb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x02,0x81,0x08,0x24,0x40 } },
+{  16, 0x8fc0, 0, {0x09,0x10,0x02,0x04,0x00,0x91,0x00,0x2c,0x40,0x4b,0x14,0x02,0x44,0x00,0xb5,0x10 } },
+{  16, 0x8fd0, 0, {0x29,0x40,0x0b,0x50,0x02,0xf5,0x00,0xb5,0x00,0x2d,0x40,0x0b,0xd0,0x02,0x02,0x01 } },
+{  16, 0x8fe0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa6,0x01,0x89,0x00,0x26,0x40 } },
+{  16, 0x8ff0, 0, {0x08,0x94,0x02,0x24,0x01,0x89,0x00,0x2e,0x40,0x1a,0x90,0x02,0x6c,0x00,0xbf,0x02 } },
+{  16, 0x9000, 0, {0x2f,0x40,0x0b,0xd0,0x02,0xf4,0x02,0xbd,0x80,0x2b,0x40,0x8b,0xd8,0x3a,0x06,0x04 } },
+{  16, 0x9010, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xc9,0x05,0x36,0x41 } },
+{  16, 0x9020, 0, {0x0d,0x1c,0x03,0x24,0x00,0xd9,0x00,0x3e,0x42,0x2f,0x94,0x03,0x64,0x00,0xf9,0x00 } },
+{  16, 0x9030, 0, {0x3a,0x40,0x0f,0x90,0x03,0xc4,0x00,0xf9,0x00,0x3e,0x70,0x0f,0x10,0x03,0x28,0x04 } },
+{  16, 0x9040, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x84,0x08,0xf9,0x24,0x3e,0x40 } },
+{  16, 0x9050, 0, {0x0f,0x91,0x03,0xe4,0x00,0xf9,0x00,0x3e,0x41,0x0d,0x10,0x03,0xa4,0x00,0xf9,0x00 } },
+{  16, 0x9060, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe4,0x00,0xc9,0x00,0x3e,0x64,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0x9070, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x08,0xc8,0x80,0x32,0x02 } },
+{  16, 0x9080, 0, {0x0f,0x80,0x03,0x00,0x00,0xc8,0x08,0x3a,0x10,0xce,0x84,0x03,0xe0,0x00,0xfc,0x00 } },
+{  16, 0x9090, 0, {0x3f,0x00,0x8f,0xc0,0x03,0xf0,0x80,0xfc,0x00,0x3f,0x18,0x0f,0xc0,0x43,0xca,0x04 } },
+{  16, 0x90a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8e,0x00,0xa1,0x80 } },
+{  16, 0x90b0, 0, {0x0b,0xe0,0x02,0x28,0x00,0xde,0xc2,0x23,0x90,0x00,0xa0,0x02,0xe8,0x00,0xba,0x00 } },
+{  16, 0x90c0, 0, {0x2e,0x80,0x0b,0xa0,0x02,0xe8,0x00,0xfa,0x00,0x2e,0x80,0x0b,0xa0,0x02,0xca,0x00 } },
+{  16, 0x90d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x99,0x81,0x60,0xc0 } },
+{  16, 0x90e0, 0, {0x0b,0x10,0x02,0x0c,0x00,0x90,0x10,0x2a,0xfc,0x0b,0x30,0x02,0xcc,0x00,0xb3,0x00 } },
+{  16, 0x90f0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x00,0xb3,0x00,0x2c,0xc0,0x0b,0x30,0x02,0xca,0x00 } },
+{  16, 0x9100, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x82,0x95,0x40,0x21,0xc0 } },
+{  16, 0x9110, 0, {0x0b,0x50,0x02,0x1c,0x80,0x90,0x80,0x23,0x01,0x09,0x72,0x12,0xdc,0x00,0xb6,0x00 } },
+{  16, 0x9120, 0, {0x2d,0x00,0x0b,0x40,0x02,0xd0,0x00,0xb4,0x09,0x2d,0x00,0x4b,0x40,0x82,0xe8,0x00 } },
+{  16, 0x9130, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x80,0xdd,0x80,0xb1,0xe0 } },
+{  16, 0x9140, 0, {0x0f,0xda,0x03,0x0f,0x80,0xd4,0x80,0x39,0xe0,0x0b,0x7a,0x03,0xde,0x00,0xf5,0x80 } },
+{  16, 0x9150, 0, {0x3d,0x20,0x0f,0x48,0x03,0xd6,0x10,0xf6,0x81,0x3d,0xe0,0x8f,0x68,0x03,0xea,0x02 } },
+{  16, 0x9160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xed,0x00,0x3e,0x00 } },
+{  16, 0x9170, 0, {0x0f,0x91,0x0b,0xec,0x10,0xf8,0x00,0x3e,0x00,0x0e,0xb0,0x03,0xec,0x00,0xf8,0x00 } },
+{  16, 0x9180, 0, {0x3e,0xc0,0x4f,0xb0,0x03,0xe8,0x00,0xe9,0x01,0x3e,0x00,0x0f,0x90,0x03,0xc2,0x06 } },
+{  16, 0x9190, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x20,0xbf,0x81,0x33,0xa4 } },
+{  16, 0x91a0, 0, {0x8c,0x19,0x03,0x3e,0x00,0xcd,0x80,0x3f,0xe0,0x0f,0xf8,0x83,0x3e,0x00,0xef,0x80 } },
+{  16, 0x91b0, 0, {0x3f,0xe0,0x0f,0xf9,0x13,0xfa,0x10,0xfd,0x80,0x3f,0xa4,0x0f,0xd8,0x03,0xc0,0x00 } },
+{  16, 0x91c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xbf,0x20,0x31,0xc2 } },
+{  16, 0x91d0, 0, {0x08,0x5a,0x02,0x3c,0x02,0x87,0x00,0x2d,0x94,0x0b,0x70,0x0a,0x1c,0x40,0x86,0x10 } },
+{  16, 0x91e0, 0, {0x2d,0x00,0x0b,0x40,0x02,0xd4,0x00,0xf6,0x00,0x2d,0x40,0x4b,0x60,0x02,0xea,0x04 } },
+{  16, 0x91f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x01,0x23,0x80 } },
+{  16, 0x9200, 0, {0x28,0x50,0x02,0x1c,0x00,0x84,0x00,0x2d,0xc0,0x0b,0x30,0x02,0x1c,0x00,0xb5,0x00 } },
+{  16, 0x9210, 0, {0x2d,0x00,0x0b,0x40,0x06,0xd0,0x40,0xb4,0x08,0x2d,0x80,0x0b,0x48,0x02,0xc0,0x00 } },
+{  16, 0x9220, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0xb3,0x08,0xa0,0x20 } },
+{  16, 0x9230, 0, {0x08,0x11,0x8a,0x0e,0x00,0x80,0x00,0x2c,0x90,0x0b,0x37,0x02,0x0c,0x00,0x90,0x00 } },
+{  16, 0x9240, 0, {0x2c,0xc0,0x0b,0x30,0x42,0xcc,0x04,0xa3,0x80,0x2c,0x50,0x0b,0x30,0x02,0xc8,0x04 } },
+{  16, 0x9250, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xf9,0x80,0x32,0x60 } },
+{  16, 0x9260, 0, {0x0c,0xd4,0x03,0x3c,0x80,0x88,0x00,0x3e,0xd0,0x0f,0xf8,0x03,0x28,0x00,0xfa,0x00 } },
+{  16, 0x9270, 0, {0x3e,0xc0,0x0f,0xb0,0x07,0xec,0x01,0xbb,0x80,0x3e,0x54,0x0f,0xb0,0x06,0xea,0x04 } },
+{  16, 0x9280, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xee,0x08,0xf9,0x80,0x3a,0xc0 } },
+{  16, 0x9290, 0, {0x0f,0x90,0x03,0xec,0x00,0xf8,0x40,0x3e,0x58,0x0f,0xb0,0x43,0xe9,0x00,0xeb,0x44 } },
+{  16, 0x92a0, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x0d,0xf8,0x00,0x3e,0x80,0x0f,0x80,0x03,0xe0,0x00 } },
+{  16, 0x92b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xcf,0x00,0x33,0x40 } },
+{  16, 0x92c0, 0, {0x0c,0xd0,0x03,0x3c,0x30,0xcc,0x00,0x3b,0xc0,0x2d,0xf0,0x03,0xd8,0x02,0xcc,0x00 } },
+{  16, 0x92d0, 0, {0x3d,0x00,0x0c,0xc0,0x03,0xf4,0x00,0xee,0x02,0x37,0x40,0x0c,0xe0,0x03,0xc0,0x44 } },
+{  16, 0x92e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x18,0x83,0x84,0x20,0x00 } },
+{  16, 0x92f0, 0, {0x4a,0x10,0x02,0x0c,0x00,0xa8,0x48,0x2e,0x60,0x08,0xb0,0x02,0xe9,0x00,0x89,0x40 } },
+{  16, 0x9300, 0, {0x2e,0xc0,0x08,0xb0,0x02,0xe8,0x10,0xb1,0x01,0x20,0x80,0x0a,0x90,0x03,0xa0,0x40 } },
+{  16, 0x9310, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x82,0x22,0x08 } },
+{  16, 0x9320, 0, {0x08,0x90,0x02,0x2c,0x14,0x88,0x04,0x2c,0x08,0x08,0xb0,0x12,0xe8,0x00,0x8a,0x00 } },
+{  16, 0x9330, 0, {0x2e,0xc0,0x0a,0xb0,0x02,0xe8,0x01,0xb9,0x00,0x26,0x04,0x08,0x90,0x02,0xe0,0x00 } },
+{  16, 0x9340, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x80,0xa2,0xc0 } },
+{  16, 0x9350, 0, {0x0a,0x92,0x02,0x2c,0x00,0xa2,0x00,0x2c,0x00,0x08,0x34,0x02,0xc8,0x00,0x83,0x00 } },
+{  16, 0x9360, 0, {0x2c,0x00,0x28,0x00,0x02,0xc4,0x01,0xba,0x00,0x22,0xc0,0x02,0x20,0x06,0xc2,0x01 } },
+{  16, 0x9370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xca,0x00,0xb2,0x00 } },
+{  16, 0x9380, 0, {0x0c,0x92,0x0b,0x2c,0x04,0xc8,0x04,0x3a,0x00,0x0c,0xb4,0x03,0xe8,0x00,0xc8,0x00 } },
+{  16, 0x9390, 0, {0x2e,0x00,0x0c,0x80,0x33,0xe1,0x40,0xe8,0x00,0x36,0x00,0x0c,0x80,0x03,0xc0,0x03 } },
+{  16, 0x93a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x3d,0x00 } },
+{  16, 0x93b0, 0, {0x0f,0xd1,0x0b,0xfc,0x01,0xfc,0x00,0x3f,0x00,0x0f,0xf0,0x03,0xd8,0x00,0xfd,0x00 } },
+{  16, 0x93c0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x80,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x07,0xa8,0x06 } },
+{  16, 0x93d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xf3,0x00,0xcf,0x80,0x35,0x60 } },
+{  16, 0x93e0, 0, {0x4e,0x68,0x43,0x5c,0x00,0xe7,0x80,0x39,0xc0,0x0c,0xc1,0x03,0x7e,0x00,0xcf,0x34 } },
+{  16, 0x93f0, 0, {0x35,0xe1,0x4d,0xf2,0x03,0x7c,0x00,0xdf,0x38,0x3f,0xc8,0x0f,0xf8,0x03,0xf0,0x00 } },
+{  16, 0x9400, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x18,0xc8,0x00,0xdb,0x84,0x22,0x60 } },
+{  16, 0x9410, 0, {0x08,0xac,0x0a,0x2c,0x00,0x8b,0x80,0x22,0x30,0x08,0x91,0x22,0x2c,0x90,0x27,0x61 } },
+{  16, 0x9420, 0, {0x22,0xca,0x88,0xfc,0x22,0xbf,0x00,0x8b,0x62,0x2f,0xd0,0x09,0xb8,0x03,0xb0,0x04 } },
+{  16, 0x9430, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xe2,0x80,0xa9,0x02,0x24,0x40 } },
+{  16, 0x9440, 0, {0x82,0x34,0x42,0x04,0x00,0xa9,0x00,0x28,0xc5,0x48,0x32,0x02,0x4c,0x20,0x83,0x30 } },
+{  16, 0x9450, 0, {0x20,0xc0,0x08,0x31,0x02,0x0d,0x00,0xb3,0x20,0x2c,0xc4,0x0b,0x30,0x02,0xf2,0x01 } },
+{  16, 0x9460, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xaa,0x02,0xb9,0x04,0x22,0x60 } },
+{  16, 0x9470, 0, {0x28,0xb2,0x02,0x26,0x00,0x89,0x88,0x02,0xc0,0x08,0x31,0x12,0xec,0x00,0x8b,0x00 } },
+{  16, 0x9480, 0, {0x2a,0xd0,0x08,0xb0,0x02,0xac,0x00,0x2b,0x00,0x2e,0xc0,0x0b,0xb0,0x02,0xb0,0x04 } },
+{  16, 0x9490, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xe2,0x00,0xe3,0x00,0x36,0x20 } },
+{  16, 0x94a0, 0, {0x0e,0xa4,0x63,0x6e,0x00,0xe1,0xc0,0x1a,0xc1,0x0c,0x80,0x03,0x68,0x70,0xcb,0x00 } },
+{  16, 0x94b0, 0, {0x36,0x80,0x0d,0xb0,0x03,0x4c,0x00,0xfb,0x04,0x3e,0xc1,0x0f,0xb0,0x03,0xd0,0x04 } },
+{  16, 0x94c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x04,0xdf,0x00,0x3f,0x00 } },
+{  16, 0x94d0, 0, {0x0f,0xe8,0x03,0xfc,0x00,0xfd,0x00,0x3f,0x00,0x2b,0x98,0x03,0x3a,0x00,0x77,0x00 } },
+{  16, 0x94e0, 0, {0x27,0xe4,0x0f,0xf0,0x03,0xfc,0x00,0xdf,0x00,0x3e,0xc0,0x0d,0xf0,0x43,0xf8,0x00 } },
+{  16, 0x94f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0xa4,0x68,0xcb,0x20,0x3a,0x90 } },
+{  16, 0x9500, 0, {0x0f,0x24,0xa3,0xac,0x00,0xe9,0x50,0x3a,0xc0,0x0e,0xb4,0x83,0x2c,0x08,0xeb,0x00 } },
+{  16, 0x9510, 0, {0x3a,0x90,0x0e,0xb0,0x8b,0xec,0x80,0xfb,0x00,0x3e,0xc0,0x0e,0xb0,0x03,0x90,0x04 } },
+{  16, 0x9520, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x01,0x0a,0x00,0x8b,0xa0,0x20,0x80 } },
+{  16, 0x9530, 0, {0x0d,0xa8,0x02,0x2c,0x04,0x89,0x40,0x28,0xe8,0x08,0xb2,0x02,0x2c,0x00,0xaf,0x00 } },
+{  16, 0x9540, 0, {0x02,0x80,0x08,0x7c,0x03,0x3d,0x80,0x3f,0x00,0x2f,0xc0,0x08,0xb0,0x02,0x36,0x00 } },
+{  16, 0x9550, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x49,0x00,0x03,0x40,0x28,0xc0 } },
+{  16, 0x9560, 0, {0x2b,0x28,0x4a,0x28,0x00,0xa1,0x00,0x68,0xd2,0x0a,0x20,0x42,0xa4,0x01,0xa3,0x00 } },
+{  16, 0x9570, 0, {0x02,0x40,0x0a,0x34,0x02,0x0d,0x00,0x33,0x00,0x2c,0xc0,0x0a,0x30,0x00,0xb8,0x00 } },
+{  16, 0x9580, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x01,0x1a,0x00,0x87,0x90,0x21,0xe4 } },
+{  16, 0x9590, 0, {0x2b,0xc8,0x12,0x3a,0x00,0x85,0xc0,0x2b,0x21,0x28,0x68,0x02,0xb6,0x00,0xa7,0x84 } },
+{  16, 0x95a0, 0, {0x23,0x60,0x08,0x38,0x80,0x1e,0x00,0xb7,0x80,0x2d,0xe0,0x08,0x78,0x02,0x2e,0x00 } },
+{  16, 0x95b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x00,0xc1,0x00,0x38,0x54 } },
+{  16, 0x95c0, 0, {0x0f,0x26,0x83,0x80,0x00,0xe0,0x34,0x28,0xc8,0x0e,0x2c,0x0b,0x8c,0x00,0xe3,0x00 } },
+{  16, 0x95d0, 0, {0x78,0x45,0x0e,0x30,0x03,0x8e,0x80,0xf3,0x00,0x3c,0xc8,0x0e,0x30,0x03,0x92,0x02 } },
+{  16, 0x95e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb8,0x00,0xf5,0x02,0x3f,0x44 } },
+{  16, 0x95f0, 0, {0x0d,0x90,0x03,0xf8,0x00,0xbd,0x14,0x1f,0xc0,0x0f,0xe1,0x23,0x5c,0x44,0x9f,0x42 } },
+{  16, 0x9600, 0, {0x3f,0xc0,0x0f,0xf4,0x82,0x7d,0x40,0xff,0x10,0x3f,0xc0,0x4f,0x70,0x07,0xd0,0x06 } },
+{  16, 0x9610, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x02,0xcb,0x00,0x38,0xc0 } },
+{  16, 0x9620, 0, {0x3c,0xa0,0x03,0xec,0x00,0xe9,0x00,0x3e,0xc0,0x0c,0xb0,0x03,0x20,0x04,0xfb,0x21 } },
+{  16, 0x9630, 0, {0x3e,0x80,0x4f,0xb4,0x03,0xcf,0x00,0xcb,0x00,0x3e,0xcc,0x4f,0xb0,0x43,0xea,0x00 } },
+{  16, 0x9640, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x91,0x98,0x00,0x87,0x00,0x21,0xc0 } },
+{  16, 0x9650, 0, {0x08,0x40,0x02,0xdc,0x04,0xb5,0x00,0x2d,0x00,0x2d,0x70,0x02,0x1c,0x1c,0xb7,0x02 } },
+{  16, 0x9660, 0, {0x2d,0xc0,0x0b,0x72,0x02,0xdc,0x00,0x87,0x40,0x2d,0xca,0x8b,0x70,0x02,0xf2,0x04 } },
+{  16, 0x9670, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xba,0x00,0x87,0x88,0x2b,0xe0 } },
+{  16, 0x9680, 0, {0x18,0x78,0x22,0xd6,0x11,0xa4,0x82,0x2f,0xe0,0x08,0x78,0x02,0x12,0x00,0xb7,0x94 } },
+{  16, 0x9690, 0, {0x6d,0x60,0x4b,0x7a,0x02,0xde,0x40,0xb7,0xa0,0x2d,0xe0,0x0b,0x78,0x06,0xe0,0x00 } },
+{  16, 0x96a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xc9,0x12,0x83,0x82,0x28,0xd4 } },
+{  16, 0x96b0, 0, {0x98,0x00,0x06,0xef,0x05,0xb1,0x90,0x2c,0xc1,0x09,0xb4,0x02,0x0c,0x04,0xb3,0x01 } },
+{  16, 0x96c0, 0, {0x6c,0xf0,0x0b,0x30,0x02,0xcc,0x00,0xbb,0x00,0x2e,0xc0,0x0b,0x30,0x02,0xd2,0x04 } },
+{  16, 0x96d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x40,0xca,0x80,0x3b,0xa0 } },
+{  16, 0x96e0, 0, {0x4c,0xe5,0x02,0xf8,0x80,0xee,0x00,0x3d,0x80,0x2c,0xe0,0x0f,0x38,0x80,0xfa,0x00 } },
+{  16, 0x96f0, 0, {0x3f,0xa9,0x0f,0xa0,0x03,0xe8,0x00,0xba,0x02,0x3e,0x80,0x8b,0xa0,0x03,0xfa,0x04 } },
+{  16, 0x9700, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x10,0xf8,0x00,0x26,0x02 } },
+{  16, 0x9710, 0, {0x0f,0x84,0x03,0xe0,0x24,0xf8,0x00,0x3e,0x00,0x4f,0x80,0xa3,0xe0,0x30,0xf8,0x00 } },
+{  16, 0x9720, 0, {0x36,0x02,0x0f,0x80,0x23,0xe0,0x04,0x08,0x00,0x3e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0x9730, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xd9,0x00,0xb6,0x41 } },
+{  16, 0x9740, 0, {0x4e,0x99,0x0b,0xa4,0x00,0x69,0x10,0x3e,0x40,0x0c,0x90,0x03,0xa4,0x10,0xc9,0x00 } },
+{  16, 0x9750, 0, {0x3e,0x40,0x0d,0x92,0x03,0xe6,0x00,0xf9,0x00,0x3a,0x40,0x0e,0x90,0x03,0xc2,0x04 } },
+{  16, 0x9760, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x81,0x00,0x20,0x42 } },
+{  16, 0x9770, 0, {0x08,0x14,0x9a,0x24,0x00,0x89,0x00,0x6e,0x50,0x00,0x90,0x02,0x24,0x10,0xd9,0x02 } },
+{  16, 0x9780, 0, {0x6e,0x40,0x0b,0x94,0x03,0xa7,0x00,0xb9,0x00,0x22,0x40,0x08,0x90,0x03,0xe0,0x00 } },
+{  16, 0x9790, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x06,0x00,0x99,0x00,0xa6,0x41 } },
+{  16, 0x97a0, 0, {0x0a,0x90,0x06,0x2c,0x00,0xa9,0x09,0x6e,0x50,0x08,0x91,0x02,0x84,0x04,0x89,0x00 } },
+{  16, 0x97b0, 0, {0x0e,0x40,0x0b,0x94,0x02,0xe5,0x49,0xb9,0x00,0x0a,0x40,0x0a,0x90,0x02,0xc6,0x00 } },
+{  16, 0x97c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x06,0x00,0x81,0x00,0x22,0x40 } },
+{  16, 0x97d0, 0, {0x08,0x12,0x22,0x04,0x81,0xa1,0x00,0x2c,0x40,0x08,0x16,0x02,0x04,0x00,0x91,0x20 } },
+{  16, 0x97e0, 0, {0x2c,0x40,0x0b,0x12,0x42,0x84,0x89,0xb1,0x20,0x20,0x48,0x08,0x10,0x02,0xc2,0x01 } },
+{  16, 0x97f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xd8,0x00,0x36,0x00 } },
+{  16, 0x9800, 0, {0x0a,0x80,0x03,0xa1,0x40,0xe8,0x00,0x2e,0x00,0x0c,0x00,0x23,0xa1,0x40,0xc8,0x50 } },
+{  16, 0x9810, 0, {0x2e,0x14,0x0d,0x80,0x03,0xe0,0x00,0xf8,0x50,0x3a,0x00,0x0e,0x80,0x03,0xee,0x03 } },
+{  16, 0x9820, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x1d,0xd4,0x00,0xf5,0x00,0xbf,0x40 } },
+{  16, 0x9830, 0, {0x0f,0xd1,0x03,0xf4,0x44,0xdd,0x02,0x3d,0x50,0x2b,0xd1,0x23,0xf4,0x00,0xf9,0x10 } },
+{  16, 0x9840, 0, {0x3f,0x40,0x0d,0x91,0x03,0xa4,0x48,0xf9,0x12,0x3e,0x4e,0x1f,0x90,0x03,0xa6,0x02 } },
+{  16, 0x9850, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xf4,0x00,0xc5,0x04,0x3b,0x40 } },
+{  16, 0x9860, 0, {0x0f,0xd8,0x03,0xa7,0x80,0xfd,0x00,0xb3,0x68,0x0d,0xd8,0x43,0xa5,0x10,0xc9,0xa0 } },
+{  16, 0x9870, 0, {0x32,0x51,0x4f,0x5a,0x43,0x36,0x00,0xc9,0xa0,0x7a,0x68,0x0b,0xd0,0x03,0xc6,0x01 } },
+{  16, 0x9880, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x18,0xca,0x88,0x88,0x02,0x02,0x00 } },
+{  16, 0x9890, 0, {0x8d,0x84,0x22,0x23,0x42,0xf8,0x00,0x22,0x04,0x28,0x8a,0xa2,0xaa,0x94,0x88,0xe9 } },
+{  16, 0x98a0, 0, {0x20,0xa8,0x0a,0x80,0x0a,0x21,0x40,0x80,0xe2,0x2e,0x28,0x0b,0x80,0x02,0xce,0x04 } },
+{  16, 0x98b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc4,0x20,0xa1,0x04,0xa8,0xc0 } },
+{  16, 0x98c0, 0, {0x0b,0x1c,0x2a,0x24,0x00,0x39,0x04,0x20,0x40,0x2a,0x1e,0x02,0xe4,0x80,0xb1,0x10 } },
+{  16, 0x98d0, 0, {0x2a,0x48,0x09,0x14,0x46,0x04,0x00,0x81,0x38,0x2c,0x5b,0x0b,0x10,0x02,0xd2,0x00 } },
+{  16, 0x98e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xa4,0x12,0xa9,0x24,0x22,0x40 } },
+{  16, 0x98f0, 0, {0x29,0x90,0x02,0x24,0x00,0x39,0x00,0x02,0x58,0x08,0x18,0x10,0xe6,0x01,0xb9,0x00 } },
+{  16, 0x9900, 0, {0xaa,0x44,0x08,0x90,0x02,0x24,0x00,0x89,0x00,0x0e,0x41,0x0b,0x90,0x02,0xc6,0x04 } },
+{  16, 0x9910, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x05,0xe4,0x00,0xe1,0x01,0x2a,0x64 } },
+{  16, 0x9920, 0, {0x2f,0x94,0x13,0x24,0x02,0x71,0x60,0x12,0x60,0x4d,0x90,0x00,0xc5,0x02,0xf9,0x00 } },
+{  16, 0x9930, 0, {0x3a,0x40,0x0f,0x90,0x23,0x24,0x02,0xc9,0x02,0x3a,0x40,0x0f,0x90,0x02,0xe8,0x04 } },
+{  16, 0x9940, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x01,0xa4,0x00,0xd9,0x00,0x3e,0x60 } },
+{  16, 0x9950, 0, {0xaf,0x90,0x83,0x64,0x88,0xf9,0x20,0x3e,0x62,0x03,0x90,0x83,0xa4,0x00,0xc9,0x00 } },
+{  16, 0x9960, 0, {0x36,0x60,0x0f,0x10,0x03,0xc4,0x00,0xf9,0x00,0x7e,0x40,0x0f,0x90,0x03,0xda,0x00 } },
+{  16, 0x9970, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa1,0x00,0xc8,0x82,0x32,0x00 } },
+{  16, 0x9980, 0, {0x6f,0x00,0x03,0xa0,0x00,0xd8,0x40,0x30,0x00,0x0e,0x80,0x03,0x60,0x04,0xf8,0x01 } },
+{  16, 0x9990, 0, {0x3e,0x10,0x4f,0x80,0x8b,0x22,0x00,0xf8,0x00,0x32,0x01,0x0e,0x80,0x03,0xca,0x04 } },
+{  16, 0x99a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x38,0x00,0x0e,0x00,0xa9,0x90 } },
+{  16, 0x99b0, 0, {0x2f,0xe6,0x20,0x88,0x00,0x9e,0x80,0x23,0x80,0x0a,0xe8,0x03,0x28,0x00,0xba,0x00 } },
+{  16, 0x99c0, 0, {0x18,0x80,0x0d,0xec,0x02,0x38,0x80,0xba,0x00,0xa2,0x80,0x08,0xa0,0x03,0x8a,0x00 } },
+{  16, 0x99d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x6c,0x02,0x83,0x80,0x20,0xc8 } },
+{  16, 0x99e0, 0, {0x0b,0x20,0x02,0x0c,0x01,0x92,0x10,0x68,0xc0,0x3a,0x3c,0x02,0xcc,0x10,0x3b,0x02 } },
+{  16, 0x99f0, 0, {0x0c,0xc0,0x28,0x3c,0x02,0x4e,0x00,0xb3,0x00,0x28,0xc0,0x28,0x30,0x02,0xca,0x00 } },
+{  16, 0x9a00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x14,0x00,0x87,0x42,0x2b,0xc0 } },
+{  16, 0x9a10, 0, {0x29,0x70,0x22,0x9c,0x00,0xb6,0x00,0x2b,0xc2,0x0a,0x60,0x86,0x1c,0x00,0xb7,0x21 } },
+{  16, 0x9a20, 0, {0x29,0xc0,0x00,0x74,0x02,0x5c,0x00,0x37,0x91,0x01,0xe0,0x08,0x74,0x02,0xa8,0x00 } },
+{  16, 0x9a30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xc7,0x80,0x21,0xe0 } },
+{  16, 0x9a40, 0, {0x2f,0x78,0x02,0x9e,0x00,0x96,0x80,0x39,0xe0,0x2e,0xf8,0x03,0xde,0x30,0xf7,0xd0 } },
+{  16, 0x9a50, 0, {0x2d,0xf2,0x00,0x78,0x03,0x52,0x00,0xf7,0xa2,0x3b,0xe0,0x0e,0x78,0x07,0xea,0x02 } },
+{  16, 0x9a60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xb4,0x00,0xfb,0x00,0x0c,0xc0 } },
+{  16, 0x9a70, 0, {0x0f,0x30,0x03,0xec,0x10,0xd3,0x00,0xb4,0xc0,0x2f,0x80,0x03,0x6c,0x48,0xfb,0x00 } },
+{  16, 0x9a80, 0, {0x3e,0xc8,0x4d,0x90,0x03,0xa4,0x00,0xfb,0x20,0x1e,0xc0,0x0f,0xb0,0x03,0xc2,0x06 } },
+{  16, 0x9a90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xcc,0x80,0x2b,0x2c } },
+{  16, 0x9aa0, 0, {0x2f,0xf8,0x03,0x7e,0x00,0x6e,0x80,0x3b,0xa1,0x0d,0xd8,0x43,0x3e,0x00,0xff,0x90 } },
+{  16, 0x9ab0, 0, {0x33,0xe0,0x0f,0xe9,0x33,0xfe,0x00,0xcf,0xc0,0x3f,0xe2,0x0f,0xd8,0x03,0xc0,0x00 } },
+{  16, 0x9ac0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0xb4,0x40,0x87,0x00,0x21,0x04 } },
+{  16, 0x9ad0, 0, {0x08,0x78,0x02,0x1c,0x00,0x86,0x00,0x21,0xc0,0x28,0x90,0x02,0xdc,0x00,0xb7,0x10 } },
+{  16, 0x9ae0, 0, {0x21,0xc0,0x0f,0x73,0x02,0xcc,0x00,0x87,0x00,0x2d,0xc0,0x0b,0x50,0x02,0xea,0x00 } },
+{  16, 0x9af0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9d,0x00,0xa4,0x00,0x29,0x48 } },
+{  16, 0x9b00, 0, {0x6a,0xf0,0x82,0x4c,0x00,0xae,0x00,0xa1,0xc4,0x29,0x74,0x02,0x5c,0x40,0xa3,0x10 } },
+{  16, 0x9b10, 0, {0x61,0xc2,0x0b,0x60,0x06,0xc8,0x00,0x87,0x00,0x2d,0xc0,0x0b,0x50,0x02,0xc0,0x04 } },
+{  16, 0x9b20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xe6,0x01,0xa3,0x02,0x20,0x40 } },
+{  16, 0x9b30, 0, {0x28,0x3c,0x02,0x0c,0x00,0x83,0x42,0x20,0xc8,0x08,0x10,0x02,0xcd,0x00,0xb3,0x00 } },
+{  16, 0x9b40, 0, {0x28,0xf0,0x0b,0x30,0x02,0xcc,0x01,0x83,0x04,0x2c,0xc0,0x83,0x10,0x02,0xc8,0x04 } },
+{  16, 0x9b50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xaa,0x80,0xeb,0x00,0x38,0xc0 } },
+{  16, 0x9b60, 0, {0x0a,0x90,0x03,0x7c,0x22,0xa2,0x40,0x32,0x48,0x0d,0xb0,0x0b,0x3e,0x00,0xff,0x00 } },
+{  16, 0x9b70, 0, {0x33,0xf4,0x0f,0x90,0x03,0xec,0x00,0x8f,0x02,0x3f,0xc0,0x0f,0x90,0x03,0xea,0x04 } },
+{  16, 0x9b80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe0,0x00,0xd9,0x02,0x3e,0xc0 } },
+{  16, 0x9b90, 0, {0x0e,0xb6,0x03,0xec,0x00,0xfa,0x20,0x3e,0xc0,0x4f,0x24,0x23,0xac,0x60,0xfb,0x00 } },
+{  16, 0x9ba0, 0, {0xa6,0xc0,0x0e,0x90,0x03,0xe4,0x00,0xfb,0x00,0x3c,0xc1,0x0f,0x90,0x03,0xe0,0x00 } },
+{  16, 0x9bb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xf8,0x02,0xcf,0x00,0x33,0xe0 } },
+{  16, 0x9bc0, 0, {0x2c,0xf0,0x13,0xbc,0x00,0x2e,0x10,0xb1,0x64,0x2e,0xf0,0x02,0x3c,0x00,0xff,0x02 } },
+{  16, 0x9bd0, 0, {0x3f,0xc1,0x4d,0xec,0x63,0xfe,0x00,0xb7,0x00,0x3b,0xc0,0x0c,0xd8,0x03,0xc0,0x44 } },
+{  16, 0x9be0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x6c,0x28,0x81,0x81,0x22,0xe0 } },
+{  16, 0x9bf0, 0, {0x0a,0x38,0x02,0x3c,0x04,0xba,0xc9,0x32,0xe0,0x20,0x84,0x02,0x2c,0x00,0xbb,0x00 } },
+{  16, 0x9c00, 0, {0x2e,0xc0,0x0b,0x9c,0x02,0xe7,0x81,0xbb,0x04,0x22,0xc0,0x0a,0x99,0x02,0xe0,0x00 } },
+{  16, 0x9c10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x28,0x40,0x88,0x80,0x22,0x88 } },
+{  16, 0x9c20, 0, {0x28,0xbc,0x42,0xac,0x00,0xba,0x00,0x2a,0x80,0x08,0x84,0x02,0xac,0x00,0xbb,0x00 } },
+{  16, 0x9c30, 0, {0x2e,0xc0,0x0b,0xb0,0x82,0xe8,0x90,0xab,0x00,0x62,0xc0,0x08,0xb0,0x12,0xe0,0x00 } },
+{  16, 0x9c40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x89,0x00,0x2a,0x80 } },
+{  16, 0x9c50, 0, {0x28,0xb2,0x02,0x0c,0x00,0xba,0x00,0x20,0xc0,0x08,0x00,0x02,0x8c,0x00,0xb3,0x00 } },
+{  16, 0x9c60, 0, {0x2c,0xc0,0x0b,0x30,0x20,0x4c,0x14,0xb3,0x00,0x20,0xc0,0x08,0x30,0x02,0xc2,0x01 } },
+{  16, 0x9c70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x68,0x00,0xc8,0x00,0xb2,0xc0 } },
+{  16, 0x9c80, 0, {0x2c,0xb2,0x03,0xac,0x00,0xfa,0x00,0x3a,0xc0,0x4e,0xa5,0x03,0xbc,0x00,0xff,0x00 } },
+{  16, 0x9c90, 0, {0x3f,0xc0,0x09,0xa0,0x03,0xe9,0x04,0xef,0x00,0xba,0xc0,0x0c,0xb0,0x01,0xc0,0x01 } },
+{  16, 0x9ca0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xf5,0x00,0x35,0xc0 } },
+{  16, 0x9cb0, 0, {0xaf,0x34,0x03,0xfc,0x00,0xf4,0x00,0x39,0xc0,0x0f,0xc2,0x03,0x7c,0x00,0xff,0x01 } },
+{  16, 0x9cc0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0xa0,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x03,0xe8,0x05 } },
+{  16, 0x9cd0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xff,0x29,0x3d,0x20 } },
+{  16, 0x9ce0, 0, {0x8e,0xc1,0x03,0x32,0x48,0xdc,0x80,0x23,0x25,0x0e,0xf2,0x03,0x3c,0xc0,0xdf,0x84 } },
+{  16, 0x9cf0, 0, {0x33,0xc9,0x0f,0xf2,0x03,0xfc,0x00,0xcf,0x80,0x33,0x40,0x0c,0xf2,0x03,0x30,0x00 } },
+{  16, 0x9d00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0xc0,0xbb,0x60,0x2e,0x08 } },
+{  16, 0x9d10, 0, {0x08,0x81,0x02,0x20,0x04,0x88,0x20,0x20,0x48,0x08,0xf1,0x82,0x2d,0xc0,0x83,0x00 } },
+{  16, 0x9d20, 0, {0x22,0xd4,0x09,0xf5,0x02,0xfc,0x08,0x8b,0x01,0x22,0x40,0x28,0xb4,0x02,0x20,0x04 } },
+{  16, 0x9d30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x20,0xb3,0x09,0x2c,0x82 } },
+{  16, 0x9d40, 0, {0x08,0x10,0x16,0xa0,0x10,0x90,0x08,0x28,0x48,0x0a,0x32,0x02,0x0c,0x00,0xbb,0x00 } },
+{  16, 0x9d50, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x02,0x93,0x01,0x20,0x00,0x8a,0x31,0x22,0xe2,0x01 } },
+{  16, 0x9d60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x04,0xbb,0x00,0x2c,0x80 } },
+{  16, 0x9d70, 0, {0x08,0x86,0x02,0xa0,0x20,0xa0,0x00,0x2a,0x60,0x0a,0xb0,0x10,0x2c,0x00,0xab,0x0c } },
+{  16, 0x9d80, 0, {0x6e,0xc0,0x09,0xb0,0x02,0xcc,0x00,0x9b,0x00,0x22,0x60,0x0a,0xb0,0x02,0xf0,0x04 } },
+{  16, 0x9d90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xec,0x00,0xbb,0x00,0x3e,0x34 } },
+{  16, 0x9da0, 0, {0x08,0xa0,0x0b,0x83,0x00,0xd9,0x02,0x3a,0xe0,0x2e,0xb0,0x0b,0x2c,0x00,0xf8,0x80 } },
+{  16, 0x9db0, 0, {0x3e,0xc0,0x4f,0xb0,0x03,0xec,0x00,0xca,0x40,0xb2,0x72,0x0e,0xb0,0x0b,0xc0,0x04 } },
+{  16, 0x9dc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x10,0xfb,0x00,0x3f,0x00 } },
+{  16, 0x9dd0, 0, {0x0d,0xf8,0x13,0x70,0x48,0xdd,0x40,0x37,0xc2,0x8d,0xf0,0x03,0xdc,0x00,0xdd,0xc8 } },
+{  16, 0x9de0, 0, {0x13,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xee,0x40,0x7f,0x40,0x0d,0x70,0x03,0x38,0x00 } },
+{  16, 0x9df0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x01,0x32,0xc0 } },
+{  16, 0x9e00, 0, {0x04,0x10,0x03,0x20,0x40,0xe8,0x10,0x3a,0xc0,0x0d,0xb0,0x03,0xac,0x08,0xf8,0x40 } },
+{  16, 0x9e10, 0, {0xb2,0xc0,0x2c,0xb0,0x33,0xa4,0x82,0xda,0x40,0xba,0x40,0x0f,0xb0,0x03,0xd0,0x04 } },
+{  16, 0x9e20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3c,0x08,0xbf,0x80,0x22,0xc8 } },
+{  16, 0x9e30, 0, {0x08,0xb7,0x00,0x23,0x44,0x88,0xd0,0x22,0xd0,0x08,0x70,0x82,0xfc,0x00,0xb2,0xe0 } },
+{  16, 0x9e40, 0, {0x03,0xf4,0x08,0xf5,0x02,0x37,0x04,0x8b,0xd1,0x22,0x60,0x4b,0xfd,0x02,0xf2,0x00 } },
+{  16, 0x9e50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb3,0x10,0xa4,0x40 } },
+{  16, 0x9e60, 0, {0x08,0x00,0x02,0x48,0x00,0xa0,0x42,0x2a,0xd0,0x01,0x30,0x02,0x8c,0x00,0xb3,0x80 } },
+{  16, 0x9e70, 0, {0x2c,0xc0,0x09,0x31,0x02,0xcc,0x00,0x89,0x00,0x22,0xe8,0x03,0x38,0x02,0xf8,0x00 } },
+{  16, 0x9e80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x1e,0x00,0xb7,0x80,0x27,0x64 } },
+{  16, 0x9e90, 0, {0x68,0x4a,0x02,0x52,0x00,0x8c,0x80,0x21,0xe0,0x08,0x78,0x02,0xde,0x00,0xb7,0x80 } },
+{  16, 0x9ea0, 0, {0x2d,0xe2,0x19,0x39,0x02,0x5e,0x30,0x85,0x98,0x21,0xe4,0x0b,0x79,0x02,0xd8,0x00 } },
+{  16, 0x9eb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xf3,0x20,0x34,0x00 } },
+{  16, 0x9ec0, 0, {0x0c,0xb8,0x03,0x48,0x80,0xe2,0x22,0x38,0xc0,0x0d,0x30,0x03,0x8c,0x00,0xf3,0x00 } },
+{  16, 0x9ed0, 0, {0x3e,0xc0,0x0d,0x31,0x03,0xec,0x00,0xcb,0x00,0x38,0x06,0x0f,0x30,0x83,0xd2,0x02 } },
+{  16, 0x9ee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0xff,0x00,0x3b,0x01 } },
+{  16, 0x9ef0, 0, {0x0f,0xd0,0x03,0x90,0x00,0xf6,0x00,0x3f,0xc0,0x0f,0xf4,0x01,0xfc,0x00,0xff,0x01 } },
+{  16, 0x9f00, 0, {0x33,0xc2,0x0e,0xf5,0x13,0xbc,0x00,0xed,0x00,0x3f,0xc4,0x0f,0xf0,0x03,0xd0,0x06 } },
+{  16, 0x9f10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x00,0xfb,0x00,0x3c,0xc0 } },
+{  16, 0x9f20, 0, {0x0e,0xa0,0x01,0x64,0x01,0xd8,0x00,0x32,0xe0,0x2c,0xb5,0x03,0x2c,0x00,0xf2,0x00 } },
+{  16, 0x9f30, 0, {0x7a,0xc0,0x0d,0xb4,0x03,0x2d,0x80,0xc9,0x02,0x32,0xc0,0x0c,0xb0,0x03,0x2a,0x00 } },
+{  16, 0x9f40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x80,0xb7,0x00,0x2d,0xc0 } },
+{  16, 0x9f50, 0, {0x0d,0x60,0x02,0xd0,0x01,0x84,0x00,0x21,0xc0,0x08,0x30,0x02,0x1d,0x00,0xb7,0x00 } },
+{  16, 0x9f60, 0, {0x21,0xc8,0x0b,0xf4,0x03,0x1e,0xc0,0x86,0x00,0x21,0xc0,0x08,0x7c,0x03,0x52,0x04 } },
+{  16, 0x9f70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0xc0,0xb7,0x90,0x2d,0xe0 } },
+{  16, 0x9f80, 0, {0x08,0x78,0x06,0xd6,0x01,0xb4,0x82,0x21,0xe0,0x08,0x78,0x0a,0x1e,0x00,0xb5,0xc0 } },
+{  16, 0x9f90, 0, {0x29,0xe8,0x09,0x78,0x02,0x36,0xc1,0x97,0x80,0x28,0xb0,0x0a,0x7a,0x02,0x30,0x00 } },
+{  16, 0x9fa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xbb,0x00,0x2c,0xe0 } },
+{  16, 0x9fb0, 0, {0x09,0x35,0x82,0xc0,0xc1,0xa0,0x51,0x20,0xe4,0x08,0x30,0x02,0x8c,0x00,0xbb,0xc4 } },
+{  16, 0x9fc0, 0, {0x20,0xc0,0x0b,0x30,0x02,0x06,0x00,0x93,0x18,0xaa,0xb0,0x2a,0x30,0x0a,0x52,0x04 } },
+{  16, 0x9fd0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfa,0x01,0x3d,0xac } },
+{  16, 0x9fe0, 0, {0x4c,0xec,0x13,0x78,0x10,0xf6,0x80,0xb3,0x90,0x0c,0xa0,0x03,0x28,0x00,0xfe,0x00 } },
+{  16, 0x9ff0, 0, {0x3a,0x81,0x0d,0xa0,0x0f,0x2a,0x80,0xde,0x04,0x3b,0xa0,0x0e,0xa0,0x03,0x3a,0x04 } },
+{  16, 0xa000, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x00,0xf8,0x00,0x3e,0x00 } },
+{  16, 0xa010, 0, {0x0d,0x80,0x02,0xe1,0x00,0xd8,0x48,0x3e,0x12,0x0f,0x80,0x13,0x60,0x00,0xf8,0x60 } },
+{  16, 0xa020, 0, {0x3e,0x00,0x07,0x80,0x03,0xa0,0x02,0xe8,0x04,0x26,0x08,0x05,0x80,0x03,0x92,0x00 } },
+{  16, 0xa030, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf9,0x04,0x3a,0x40 } },
+{  16, 0xa040, 0, {0x0c,0x12,0x03,0x24,0x82,0xc9,0x00,0x36,0x44,0x0f,0x10,0x03,0x24,0x00,0xf9,0x00 } },
+{  16, 0xa050, 0, {0x36,0x40,0x04,0x90,0x03,0x04,0x00,0xc9,0x00,0x12,0x40,0x0c,0x90,0x03,0x02,0x04 } },
+{  16, 0xa060, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x81,0x22,0x40 } },
+{  16, 0xa070, 0, {0x08,0x90,0x1a,0x24,0x00,0x89,0x00,0x22,0x68,0x0b,0x99,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0xa080, 0, {0x22,0x40,0x68,0x90,0x0a,0x24,0x00,0x89,0x00,0xa2,0x40,0x08,0x90,0x0a,0x20,0x00 } },
+{  16, 0xa090, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x10,0x22,0xe0 } },
+{  16, 0xa0a0, 0, {0x08,0x94,0x00,0x04,0x04,0x8b,0x08,0x26,0xc0,0x0b,0x90,0x02,0x24,0x04,0xb9,0x0c } },
+{  16, 0xa0b0, 0, {0x24,0x40,0x0a,0x10,0x02,0x24,0x00,0x23,0x02,0x2a,0x40,0xa8,0x10,0x02,0x06,0x00 } },
+{  16, 0xa0c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x90,0xb1,0x20,0x22,0x40 } },
+{  16, 0xa0d0, 0, {0x08,0x12,0x02,0x0c,0x10,0x81,0x02,0xa0,0x50,0x0b,0x12,0x02,0x04,0x80,0xb1,0x05 } },
+{  16, 0xa0e0, 0, {0x00,0x48,0x0a,0x10,0x02,0x04,0xa0,0xa1,0x00,0x28,0x4a,0x08,0x12,0x00,0x02,0x01 } },
+{  16, 0xa0f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x50,0xba,0x14 } },
+{  16, 0xa100, 0, {0x0c,0x85,0x03,0x01,0x42,0xc8,0x50,0x34,0x00,0x0f,0x85,0x03,0x21,0x40,0xf8,0x00 } },
+{  16, 0xa110, 0, {0x36,0x00,0x0e,0x80,0x13,0x20,0x80,0xe0,0x00,0x1a,0x08,0x0c,0x00,0x03,0x2e,0x03 } },
+{  16, 0xa120, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x44,0xf9,0x10,0x3f,0x40 } },
+{  16, 0xa130, 0, {0x2f,0xd1,0x13,0xf4,0x04,0xf5,0x00,0x3f,0x40,0x0f,0x91,0x0b,0xe4,0x40,0xff,0x28 } },
+{  16, 0xa140, 0, {0xbe,0x4e,0x0d,0x96,0x83,0xd4,0xa2,0xdd,0x28,0x37,0x4a,0x0f,0x93,0x83,0xe6,0x06 } },
+{  16, 0xa150, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x05,0xe4,0x10,0xcd,0x00,0x3f,0x40 } },
+{  16, 0xa160, 0, {0x0f,0xd0,0x03,0x35,0x02,0x5d,0x01,0x31,0x44,0x0f,0xd0,0x03,0x24,0x00,0xf9,0x00 } },
+{  16, 0xa170, 0, {0x32,0x60,0x0c,0x98,0x83,0xe6,0x40,0xd9,0x00,0x36,0x6a,0x0c,0x9e,0x83,0x26,0x01 } },
+{  16, 0xa180, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0x88,0x00,0x2e,0x00 } },
+{  16, 0xa190, 0, {0x0b,0x80,0x42,0x02,0x80,0x8a,0x00,0x22,0x20,0x88,0x80,0x03,0x20,0x08,0xb8,0x82 } },
+{  16, 0xa1a0, 0, {0x22,0x21,0x08,0x88,0x82,0xe2,0x42,0x88,0xa8,0x22,0x20,0x08,0xce,0x02,0x0e,0x04 } },
+{  16, 0xa1b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x02,0x81,0x00,0x68,0x40 } },
+{  16, 0xa1c0, 0, {0x0b,0x10,0x02,0x84,0x01,0xb9,0x00,0x20,0x40,0x49,0x10,0x0a,0x04,0x00,0xb5,0x08 } },
+{  16, 0xa1d0, 0, {0x21,0x46,0x08,0x50,0x02,0xd4,0x00,0x8d,0x20,0x25,0x4a,0x0b,0x50,0x02,0x42,0x01 } },
+{  16, 0xa1e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0x89,0x04,0x6e,0x54 } },
+{  16, 0xa1f0, 0, {0x0b,0x10,0x12,0xa4,0x01,0xa9,0x00,0xa2,0x40,0x18,0x90,0x16,0x24,0x00,0xb9,0x00 } },
+{  16, 0xa200, 0, {0x23,0x40,0x18,0xd0,0x02,0xf4,0x00,0x8d,0x40,0x21,0x4a,0x0b,0xd0,0x02,0x46,0x04 } },
+{  16, 0xa210, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xc9,0x00,0x3a,0x50 } },
+{  16, 0xa220, 0, {0x8f,0x96,0x0b,0x84,0x02,0xf1,0x01,0x30,0x48,0x8d,0x90,0x03,0x24,0x10,0xf9,0x00 } },
+{  16, 0xa230, 0, {0xb2,0x40,0x2c,0x90,0x03,0xe6,0x40,0xd1,0xc0,0x36,0x50,0x2f,0x90,0x0b,0x68,0x04 } },
+{  16, 0xa240, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x00,0x3e,0x60 } },
+{  16, 0xa250, 0, {0x0f,0x99,0xc3,0x64,0x00,0xd9,0x28,0x3e,0x40,0x0d,0x90,0x03,0xa4,0x00,0xf9,0x40 } },
+{  16, 0xa260, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe4,0x20,0xf9,0x40,0x3e,0x40,0x0c,0x90,0x03,0x8a,0x00 } },
+{  16, 0xa270, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x01,0x36,0x00 } },
+{  16, 0xa280, 0, {0x8f,0x80,0x03,0xe0,0x02,0xf8,0x04,0x32,0x00,0x0d,0x80,0x43,0x20,0x02,0xcc,0x00 } },
+{  16, 0xa290, 0, {0x3f,0x00,0x0f,0xc0,0x13,0x90,0x02,0xdc,0x40,0x3f,0x10,0x4c,0xc0,0x23,0x0a,0x04 } },
+{  16, 0xa2a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xba,0x00,0x22,0x80 } },
+{  16, 0xa2b0, 0, {0x0b,0xe8,0x20,0xf8,0x00,0x4e,0xc0,0x23,0xa0,0x08,0xa0,0x03,0x68,0x00,0x8a,0x00 } },
+{  16, 0xa2c0, 0, {0x2e,0x80,0x1f,0xa0,0x02,0x2a,0x06,0x8a,0x00,0x2e,0xa0,0x02,0x60,0x03,0x0a,0x00 } },
+{  16, 0xa2d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x6c,0x00,0xb3,0x00,0x20,0xc0 } },
+{  16, 0xa2e0, 0, {0x0b,0x3d,0x02,0xc0,0x03,0x23,0x00,0x20,0xe0,0x01,0xb0,0x06,0x4c,0x00,0x8b,0x00 } },
+{  16, 0xa2f0, 0, {0x2e,0xc0,0x4b,0x30,0x02,0x8e,0x08,0x83,0x80,0x2c,0xc4,0x00,0x34,0x8e,0x4a,0x00 } },
+{  16, 0xa300, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x80,0xb5,0x80,0x61,0xc0 } },
+{  16, 0xa310, 0, {0x0b,0x40,0x02,0xd4,0x00,0x84,0x08,0x23,0xc2,0x08,0x50,0x02,0x5e,0xc0,0x84,0x01 } },
+{  16, 0xa320, 0, {0x2d,0x00,0x8a,0x08,0x02,0x10,0x24,0x84,0x08,0x6d,0x00,0x0a,0x03,0x12,0x28,0x00 } },
+{  16, 0xa330, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf5,0x82,0x21,0x60 } },
+{  16, 0xa340, 0, {0x0f,0x78,0x03,0xd6,0x04,0xae,0x80,0x31,0xe0,0x0d,0x58,0x23,0x7e,0x00,0xc6,0x80 } },
+{  16, 0xa350, 0, {0x2d,0xe0,0x0b,0x78,0x03,0x8e,0x00,0xd7,0x82,0x3d,0xf0,0x0c,0x7a,0x03,0x6a,0x02 } },
+{  16, 0xa360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf1,0x00,0xba,0xd8 } },
+{  16, 0xa370, 0, {0x0f,0x80,0x03,0xe4,0x12,0xf8,0x00,0xbe,0x80,0x0e,0x10,0x03,0xec,0x00,0xf9,0x00 } },
+{  16, 0xa380, 0, {0x3e,0x00,0x5f,0x80,0x03,0xe0,0x08,0xf8,0x04,0x3c,0x00,0x0f,0x80,0x03,0xc2,0x06 } },
+{  16, 0xa390, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x20,0xff,0x80,0x3f,0xf0 } },
+{  16, 0xa3a0, 0, {0x0f,0xf8,0x03,0xd2,0x00,0xef,0x84,0xb3,0x61,0x0c,0xb9,0x03,0xfe,0x00,0xff,0x80 } },
+{  16, 0xa3b0, 0, {0x33,0xe0,0x0c,0xf8,0x13,0x22,0x11,0xcd,0x90,0x3f,0x60,0x0c,0xe8,0x03,0x10,0x00 } },
+{  16, 0xa3c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xf5,0x00,0x2d,0xc0 } },
+{  16, 0xa3d0, 0, {0x0b,0x00,0x02,0xd4,0x04,0x84,0x20,0x23,0x40,0x08,0x5a,0x02,0xdc,0x00,0xb4,0x00 } },
+{  16, 0xa3e0, 0, {0x21,0x00,0x28,0xc2,0x02,0x1e,0x04,0x86,0x04,0x2d,0x88,0x08,0xd0,0x02,0x2a,0x04 } },
+{  16, 0xa3f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x9c,0x00,0xb5,0x00,0x2d,0x40 } },
+{  16, 0xa400, 0, {0x0b,0x70,0x02,0xf4,0x20,0xa7,0x04,0x21,0xc0,0x0a,0x50,0x02,0xdc,0x00,0xbe,0x00 } },
+{  16, 0xa410, 0, {0x21,0xc0,0x08,0x70,0x12,0x00,0x00,0x85,0x00,0x2d,0x40,0x88,0x68,0x0a,0x04,0x00 } },
+{  16, 0xa420, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xcc,0x00,0xa1,0x00,0x2e,0xc0 } },
+{  16, 0xa430, 0, {0x1b,0x08,0x06,0xc4,0x20,0x80,0x00,0x20,0x98,0x1a,0x10,0x02,0xcc,0x00,0xb1,0x08 } },
+{  16, 0xa440, 0, {0x20,0x00,0x08,0x00,0x02,0x0c,0x01,0x82,0xc0,0x2c,0xac,0x28,0x90,0x22,0x18,0x04 } },
+{  16, 0xa450, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xb3,0x00,0x3e,0x40 } },
+{  16, 0xa460, 0, {0x0f,0xba,0x03,0xe5,0x02,0xe9,0x04,0x32,0x90,0xae,0xb0,0x03,0xfc,0x10,0xfb,0x40 } },
+{  16, 0xa470, 0, {0xb2,0x00,0x0c,0x80,0x0b,0x2c,0x02,0x82,0x18,0x3f,0xa0,0x0c,0xd0,0x03,0x2e,0x04 } },
+{  16, 0xa480, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0xec,0x04,0xfb,0x01,0x3e,0x40 } },
+{  16, 0xa490, 0, {0x0f,0xb6,0x43,0xe4,0x00,0xf8,0x00,0x3e,0x80,0x01,0x90,0x03,0xec,0x00,0xf8,0x81 } },
+{  16, 0xa4a0, 0, {0x3e,0xd0,0x0d,0xb4,0x53,0xe0,0x00,0xf9,0x40,0x3e,0x40,0x0f,0xa0,0x03,0xe0,0x00 } },
+{  16, 0xa4b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xdc,0x02,0xcd,0x80,0x33,0x60 } },
+{  16, 0xa4c0, 0, {0x2c,0xda,0x03,0xfc,0x00,0xec,0x00,0x33,0x40,0x0f,0xf2,0x03,0x7c,0x04,0xfe,0x00 } },
+{  16, 0xa4d0, 0, {0x32,0x00,0x0c,0xc8,0x03,0x3c,0x00,0xce,0x00,0x31,0x80,0x0c,0xd1,0x03,0x24,0x04 } },
+{  16, 0xa4e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x91,0x04,0x6c,0x00,0x09,0x00,0x2a,0x64 } },
+{  16, 0xa4f0, 0, {0x08,0x8e,0x02,0xc2,0x10,0xa0,0x10,0x3e,0x10,0x0b,0x98,0x02,0xec,0x00,0xb9,0x00 } },
+{  16, 0xa500, 0, {0x02,0xd8,0x08,0xbe,0x22,0x20,0x00,0x89,0x00,0x22,0x50,0x08,0xa0,0x02,0x20,0x40 } },
+{  16, 0xa510, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x0b,0x20,0x22,0x40 } },
+{  16, 0xa520, 0, {0x08,0xa0,0x02,0xe5,0x42,0xab,0x04,0x22,0x18,0x0b,0xb0,0x02,0x6c,0x00,0xb3,0x00 } },
+{  16, 0xa530, 0, {0x20,0x04,0x08,0x01,0x02,0x00,0x04,0xa8,0x40,0x22,0x10,0x08,0x80,0x02,0x20,0x00 } },
+{  16, 0xa540, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x08,0x83,0x00,0x28,0x40 } },
+{  16, 0xa550, 0, {0x08,0x04,0x02,0xc4,0x02,0xa8,0x00,0x2c,0x00,0x0b,0x12,0x02,0xcc,0x00,0xb0,0x00 } },
+{  16, 0xa560, 0, {0x20,0xc0,0x40,0x30,0x02,0x0c,0x00,0x8b,0x00,0xa8,0xc0,0x08,0x30,0x02,0x02,0x11 } },
+{  16, 0xa570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0d,0x6c,0x00,0xc9,0x00,0x33,0x40 } },
+{  16, 0xa580, 0, {0x0c,0xb0,0x03,0xec,0x02,0xeb,0x00,0x32,0x40,0x0f,0xb0,0x03,0x6c,0x00,0xfa,0x00 } },
+{  16, 0xa590, 0, {0x32,0x00,0x0c,0x80,0x03,0x20,0x80,0xc8,0x00,0x30,0x00,0x0c,0x80,0x03,0x20,0x03 } },
+{  16, 0xa5a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xfd,0x00,0x3f,0x40 } },
+{  16, 0xa5b0, 0, {0x0f,0xc2,0x13,0xf0,0x00,0xf4,0x00,0x3f,0x00,0x4f,0xd4,0x03,0xfc,0x00,0xf5,0x00 } },
+{  16, 0xa5c0, 0, {0x3f,0xc0,0x8f,0xf0,0x03,0xfc,0x40,0xff,0x00,0x37,0xc0,0x2f,0xf0,0x03,0xe8,0x06 } },
+{  16, 0xa5d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0x00,0xcc,0x00,0x33,0x00 } },
+{  16, 0xa5e0, 0, {0x0e,0xd0,0x0b,0x33,0x00,0xcc,0x00,0x33,0xe0,0x0f,0xc0,0x83,0x7c,0x00,0xcf,0x20 } },
+{  16, 0xa5f0, 0, {0x7b,0x09,0x8c,0xf8,0x03,0xfe,0x50,0xcf,0x38,0x3f,0xe1,0x0d,0xc2,0x03,0xf0,0x00 } },
+{  16, 0xa600, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe2,0x00,0x98,0x08,0x20,0x80 } },
+{  16, 0xa610, 0, {0x08,0x98,0x02,0x20,0x00,0x88,0xd0,0x22,0xe0,0x0e,0xb4,0x22,0x7d,0x19,0x9f,0x69 } },
+{  16, 0xa620, 0, {0x2e,0x90,0x08,0x30,0x92,0x28,0x81,0xdb,0x64,0x2e,0xe1,0x88,0x16,0xa2,0xe0,0x04 } },
+{  16, 0xa630, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc8,0x00,0x90,0x24,0x20,0x01 } },
+{  16, 0xa640, 0, {0x08,0x10,0x16,0x00,0x82,0x83,0x01,0x28,0xc1,0x0b,0x02,0x82,0x0c,0xe0,0xa3,0x10 } },
+{  16, 0xa650, 0, {0x28,0x0e,0x1b,0x92,0x02,0x84,0x84,0x93,0x20,0x2e,0xc0,0x08,0x31,0x02,0xe2,0x01 } },
+{  16, 0xa660, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa8,0x10,0x98,0x00,0x22,0x80 } },
+{  16, 0xa670, 0, {0x08,0x90,0x02,0x00,0x60,0x8a,0x10,0x2a,0xc0,0x0a,0x20,0x02,0x6c,0x18,0xbb,0x00 } },
+{  16, 0xa680, 0, {0x6e,0x60,0x2b,0x90,0x02,0x46,0x20,0x8b,0x00,0x2e,0xc2,0x08,0xb1,0x82,0xf0,0x04 } },
+{  16, 0xa690, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0xe4,0x02,0xcb,0x00,0xb2,0x40 } },
+{  16, 0xa6a0, 0, {0x2c,0x92,0x03,0x27,0x00,0x88,0x00,0xba,0xc0,0x0f,0x88,0x03,0x2c,0x00,0xeb,0x04 } },
+{  16, 0xa6b0, 0, {0x3a,0xa0,0xcf,0x2c,0xa3,0xed,0x00,0x9b,0x00,0x3c,0xf0,0x2d,0x8c,0x33,0xd0,0x04 } },
+{  16, 0xa6c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x04,0xef,0x00,0x3f,0xc0 } },
+{  16, 0xa6d0, 0, {0x0d,0x51,0x03,0xf0,0x00,0xf1,0x81,0x37,0xc0,0x0e,0xf4,0x03,0x9c,0x10,0xcf,0x00 } },
+{  16, 0xa6e0, 0, {0x3d,0x80,0x0c,0xec,0x07,0xb8,0x08,0xff,0x02,0x1f,0xc4,0x0f,0xc8,0x03,0xf8,0x00 } },
+{  16, 0xa6f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x9e,0x00,0xc3,0x00,0x38,0x40 } },
+{  16, 0xa700, 0, {0x0c,0x92,0x03,0xa4,0x80,0xfb,0x20,0x3a,0xc0,0x0d,0x94,0x03,0x2c,0x40,0xfb,0x00 } },
+{  16, 0xa710, 0, {0x3e,0x01,0x0f,0x80,0x03,0xe5,0x00,0xeb,0x00,0x3a,0xc0,0x0d,0x84,0x0b,0x10,0x04 } },
+{  16, 0xa720, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x08,0x8b,0x02,0x22,0xc0 } },
+{  16, 0xa730, 0, {0x08,0x92,0x03,0x21,0x00,0x8b,0x48,0x22,0xc0,0x0b,0xb7,0x02,0x3d,0x40,0x3f,0x01 } },
+{  16, 0xa740, 0, {0x22,0x74,0x0b,0x90,0x02,0x28,0x04,0xbf,0x00,0xb2,0xc0,0x0b,0x85,0x02,0x32,0x00 } },
+{  16, 0xa750, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x40,0x01,0x80,0x00,0x28,0x00 } },
+{  16, 0xa760, 0, {0x08,0x2c,0x12,0x88,0x40,0xb0,0x40,0x08,0xc0,0x0b,0x18,0x02,0x0e,0x00,0xb3,0x00 } },
+{  16, 0xa770, 0, {0x28,0x20,0x11,0x30,0x02,0x0c,0x00,0xb3,0x00,0x24,0x00,0x09,0x00,0x06,0x38,0x00 } },
+{  16, 0xa780, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x12,0x00,0x84,0x80,0x21,0xa0 } },
+{  16, 0xa790, 0, {0x28,0x68,0x12,0x3a,0x00,0x84,0x80,0x25,0xe0,0x8b,0x58,0x02,0x1e,0x40,0xb7,0x82 } },
+{  16, 0xa7a0, 0, {0x21,0xa6,0x0b,0x78,0x02,0x1a,0x00,0xb7,0x80,0x21,0x20,0x0b,0x58,0x02,0x08,0x00 } },
+{  16, 0xa7b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x00,0xc8,0x21,0x38,0x09 } },
+{  16, 0xa7c0, 0, {0x0c,0x28,0x03,0x80,0x01,0xf1,0x00,0x38,0xc0,0x0d,0x85,0x02,0x0c,0x00,0xfb,0x00 } },
+{  16, 0xa7d0, 0, {0x38,0x85,0x0f,0x10,0x03,0x8c,0x00,0xeb,0x10,0x3c,0xc8,0x0d,0x30,0x03,0x12,0x02 } },
+{  16, 0xa7e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x98,0x00,0xfc,0x01,0x3f,0x80 } },
+{  16, 0xa7f0, 0, {0x0f,0x68,0x03,0xd0,0x40,0xfc,0x00,0x3b,0xc0,0x0d,0xc0,0x03,0xfc,0x20,0xff,0x00 } },
+{  16, 0xa800, 0, {0x3b,0xc5,0x0f,0xf0,0x0b,0xb4,0x40,0xff,0x18,0x3f,0x00,0x0f,0xf1,0x03,0xd0,0x06 } },
+{  16, 0xa810, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x00,0xeb,0x00,0xb0,0x41 } },
+{  16, 0xa820, 0, {0x0c,0xa0,0x03,0xe0,0x04,0xca,0x04,0xb0,0xe0,0x0e,0xb0,0x03,0xec,0x80,0xcb,0x20 } },
+{  16, 0xa830, 0, {0x32,0x81,0x0c,0xa0,0x03,0xee,0x00,0xdb,0x00,0x3e,0x00,0x0e,0xb0,0x03,0x2a,0x00 } },
+{  16, 0xa840, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x04,0x87,0x00,0x21,0xc0 } },
+{  16, 0xa850, 0, {0x48,0x60,0x02,0xf0,0x00,0x87,0x00,0x21,0xc0,0x08,0x70,0x02,0xfc,0xa0,0x83,0x28 } },
+{  16, 0xa860, 0, {0xa3,0x80,0x08,0x60,0x02,0xdc,0x00,0x87,0x20,0x2d,0xc0,0x0b,0x70,0x02,0x12,0x04 } },
+{  16, 0xa870, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9c,0x02,0xa3,0x80,0x21,0x60 } },
+{  16, 0xa880, 0, {0x08,0x68,0x02,0xd2,0x00,0x87,0x80,0x21,0xe0,0x29,0x78,0x02,0xde,0x80,0x87,0x90 } },
+{  16, 0xa890, 0, {0x21,0xa0,0x19,0x48,0x02,0xfe,0x00,0x97,0x80,0x2d,0xe0,0x0a,0x38,0x82,0x30,0x00 } },
+{  16, 0xa8a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x01,0x83,0x80,0x20,0xc0 } },
+{  16, 0xa8b0, 0, {0x08,0x20,0x42,0xc0,0x30,0x83,0x70,0xa0,0xc0,0x89,0x34,0x02,0xcc,0x02,0x83,0x00 } },
+{  16, 0xa8c0, 0, {0x60,0xc0,0x29,0x00,0x02,0xce,0x00,0x83,0x00,0x2c,0xc8,0x0b,0xbc,0x02,0x12,0x04 } },
+{  16, 0xa8d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa9,0x00,0xea,0xe2,0x32,0x90 } },
+{  16, 0xa8e0, 0, {0x2c,0xe0,0x03,0xfb,0x02,0xce,0xc0,0x32,0x80,0x0f,0xe4,0x03,0xe8,0x00,0x8a,0x00 } },
+{  16, 0xa8f0, 0, {0x33,0x88,0x0d,0x64,0xc3,0xfa,0x00,0xda,0x00,0x3d,0x90,0x0e,0xe0,0x0b,0x3a,0x04 } },
+{  16, 0xa900, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xc0,0x24,0xf8,0x08,0x3e,0x12 } },
+{  16, 0xa910, 0, {0x0f,0xc0,0x03,0xe0,0x48,0xf0,0x00,0x3e,0x00,0x0e,0x80,0x93,0xc0,0x00,0xf8,0x00 } },
+{  16, 0xa920, 0, {0x7e,0x01,0x0e,0x80,0xc2,0xe0,0x40,0xf8,0x00,0x7e,0x00,0x8f,0x84,0x03,0xd2,0x00 } },
+{  16, 0xa930, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe5,0x00,0xc1,0x01,0x32,0x48 } },
+{  16, 0xa940, 0, {0x0c,0x98,0x03,0xe6,0x40,0xc9,0x00,0x32,0x40,0x0f,0x90,0x03,0x66,0x00,0xc9,0x00 } },
+{  16, 0xa950, 0, {0x18,0x61,0x0c,0x90,0x03,0x64,0x20,0xf9,0x05,0x3e,0x40,0x0c,0x90,0x83,0x02,0x04 } },
+{  16, 0xa960, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x66,0x20,0x89,0x00,0x20,0x52 } },
+{  16, 0xa970, 0, {0x28,0x10,0xc2,0x26,0x02,0xa9,0x00,0x22,0x40,0x0b,0x90,0x0a,0x27,0x00,0xa9,0x00 } },
+{  16, 0xa980, 0, {0x22,0x70,0x08,0x90,0x02,0x24,0x08,0xb9,0x00,0x2e,0x40,0x0a,0x90,0x0a,0x20,0x00 } },
+{  16, 0xa990, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x02,0x8d,0x00,0x23,0x40 } },
+{  16, 0xa9a0, 0, {0x08,0xd1,0x02,0x84,0x20,0x89,0x00,0x22,0x60,0x0b,0x11,0xf2,0x24,0xb0,0x81,0x00 } },
+{  16, 0xa9b0, 0, {0x2a,0x46,0x08,0x90,0x42,0x64,0x08,0xb9,0x00,0x2e,0x40,0x08,0x92,0x02,0x06,0x00 } },
+{  16, 0xa9c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x14,0x80,0x85,0x20,0x23,0x48 } },
+{  16, 0xa9d0, 0, {0x08,0x52,0x02,0x84,0x08,0x81,0x00,0x20,0x40,0x0b,0x12,0x02,0x04,0x80,0xa1,0x20 } },
+{  16, 0xa9e0, 0, {0x28,0x49,0x28,0x90,0x02,0x04,0x00,0x31,0x20,0x2e,0x40,0x08,0x32,0x02,0x02,0x01 } },
+{  16, 0xa9f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xc8,0x50,0xb2,0x14 } },
+{  16, 0xaa00, 0, {0x0c,0xc0,0x03,0xa1,0x40,0xc8,0x00,0xb2,0x00,0x07,0x85,0x03,0x21,0x40,0xc8,0x50 } },
+{  16, 0xaa10, 0, {0x3a,0x15,0x0c,0x85,0x03,0x61,0x40,0xf8,0x51,0x3e,0x00,0x2c,0x85,0x03,0x2e,0x03 } },
+{  16, 0xaa20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xc4,0x48,0xf9,0x10,0x3e,0x44 } },
+{  16, 0xaa30, 0, {0x4f,0x91,0x03,0x74,0x00,0xf5,0x44,0x3e,0x40,0x0f,0xd1,0x03,0xe4,0x40,0xf9,0x10 } },
+{  16, 0xaa40, 0, {0x37,0x44,0x0f,0xd0,0x03,0xd4,0x00,0xf9,0x10,0x3f,0xc0,0x0f,0xd1,0x03,0xe6,0x06 } },
+{  16, 0xaa50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xf6,0xa0,0xdd,0x8c,0x33,0x78 } },
+{  16, 0xaa60, 0, {0x0e,0xda,0x03,0x35,0x00,0xcd,0xa0,0x33,0x40,0x0d,0xf8,0x0b,0x36,0x81,0xe9,0x80 } },
+{  16, 0xaa70, 0, {0x33,0x70,0x0c,0x91,0x03,0xe4,0x40,0xf9,0xc0,0x3e,0xc0,0x0f,0xdc,0x03,0xc6,0x00 } },
+{  16, 0xaa80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x04,0xb8,0x40,0x20,0x3c } },
+{  16, 0xaa90, 0, {0x0c,0x85,0x02,0x02,0x84,0x8a,0x40,0x22,0x00,0x08,0x8f,0x82,0x23,0x00,0xb8,0xe8 } },
+{  16, 0xaaa0, 0, {0x22,0x20,0x08,0x88,0x02,0xe2,0x00,0xb8,0xd0,0x2e,0x00,0x0b,0x8c,0x02,0xce,0x04 } },
+{  16, 0xaab0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0x91,0x00,0x60,0x48 } },
+{  16, 0xaac0, 0, {0x4b,0x10,0x02,0x04,0x8a,0x81,0x40,0x60,0x40,0x49,0x10,0x02,0x8d,0xa0,0xa1,0x41 } },
+{  16, 0xaad0, 0, {0x20,0x50,0x09,0x12,0x22,0xc4,0x80,0xb1,0x20,0x2c,0x40,0x4b,0x3e,0x02,0xc2,0x01 } },
+{  16, 0xaae0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x08,0xb9,0x04,0xa0,0x40 } },
+{  16, 0xaaf0, 0, {0x48,0xb0,0x02,0x24,0x00,0x89,0x00,0x82,0x40,0x08,0x90,0xa6,0xa4,0x00,0xb9,0x04 } },
+{  16, 0xab00, 0, {0x22,0x54,0x29,0x95,0x02,0xe5,0x40,0xb9,0x00,0x6e,0x40,0x0b,0x92,0x02,0xc6,0x04 } },
+{  16, 0xab10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x05,0xe4,0x00,0x91,0x00,0x32,0x40 } },
+{  16, 0xab20, 0, {0x0f,0x90,0x09,0x24,0x00,0x89,0x90,0x32,0x40,0x0d,0x94,0x03,0xa4,0x00,0xe9,0x02 } },
+{  16, 0xab30, 0, {0x72,0x60,0x0d,0x94,0x03,0xe4,0x01,0xf9,0x01,0x3e,0x60,0x0f,0x90,0x03,0xe8,0x04 } },
+{  16, 0xab40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x40,0xf9,0x00,0x3e,0x40 } },
+{  16, 0xab50, 0, {0x4f,0x90,0x03,0xe7,0x10,0xf9,0x80,0x3e,0x40,0x0f,0x10,0x13,0x64,0x00,0xf1,0x00 } },
+{  16, 0xab60, 0, {0xbe,0x40,0x0e,0x90,0x03,0xe6,0x08,0xf9,0x01,0x3e,0x64,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0xab70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa0,0x00,0xf8,0x00,0x32,0x08 } },
+{  16, 0xab80, 0, {0x0c,0x01,0x0b,0x20,0x40,0xc8,0x40,0x32,0x00,0x0e,0x84,0x83,0x20,0x00,0xf8,0x04 } },
+{  16, 0xab90, 0, {0x3e,0x04,0x0f,0x80,0x03,0x21,0x00,0xe8,0x00,0x3e,0x10,0x0f,0x88,0x03,0xca,0x04 } },
+{  16, 0xaba0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x38,0x00,0x3e,0x04,0x23,0x80 } },
+{  16, 0xabb0, 0, {0x08,0xec,0x12,0x39,0x44,0xa6,0x00,0x28,0x81,0x08,0xe0,0x00,0x38,0x08,0xba,0x00 } },
+{  16, 0xabc0, 0, {0x3f,0x80,0x0b,0xa0,0x02,0xa8,0x00,0x8a,0x02,0x2e,0x80,0x0b,0xe0,0x02,0xca,0x00 } },
+{  16, 0xabd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x48,0x00,0x31,0x00,0x24,0xd0 } },
+{  16, 0xabe0, 0, {0x08,0x3e,0x12,0xae,0x08,0x81,0xa0,0x2c,0xc0,0x0a,0x38,0x00,0x4c,0x00,0xb3,0x00 } },
+{  16, 0xabf0, 0, {0x6e,0xc0,0x0a,0x30,0x02,0x0c,0x00,0xa3,0x00,0x6c,0xc0,0x0b,0x30,0x02,0xca,0x00 } },
+{  16, 0xac00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x18,0x00,0xb5,0x10,0x25,0xc0 } },
+{  16, 0xac10, 0, {0x28,0x60,0x12,0x90,0x10,0xa5,0x08,0x2d,0xc2,0x08,0x64,0x22,0x58,0x18,0xb7,0x00 } },
+{  16, 0xac20, 0, {0x2d,0x80,0x0b,0x79,0x02,0xbe,0xc0,0x87,0x01,0x6d,0xc0,0x0b,0x60,0x02,0xe8,0x00 } },
+{  16, 0xac30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf5,0x84,0x35,0x20 } },
+{  16, 0xac40, 0, {0x8c,0x18,0x02,0x92,0x10,0xc5,0x80,0x3d,0x60,0x0e,0xc8,0x0b,0x5a,0x08,0x77,0xf3 } },
+{  16, 0xac50, 0, {0x3d,0xa0,0x0f,0xf8,0x03,0x1e,0xb0,0xe7,0x85,0x3d,0xe0,0x0f,0x78,0x03,0xea,0x02 } },
+{  16, 0xac60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf1,0x04,0xba,0x01 } },
+{  16, 0xac70, 0, {0x0f,0xa0,0x43,0x60,0x09,0xe1,0x00,0x38,0x40,0x0e,0xa0,0x03,0xa8,0x14,0xfb,0x20 } },
+{  16, 0xac80, 0, {0x3a,0x80,0x0f,0xb4,0x1b,0x4c,0x80,0xfb,0x29,0x3e,0xc0,0x0f,0xb0,0x23,0xc2,0x06 } },
+{  16, 0xac90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfa,0x00,0xcd,0x80,0x3b,0xe0 } },
+{  16, 0xaca0, 0, {0x4e,0xf8,0x03,0xf2,0x02,0xd4,0x81,0x3b,0xe0,0x8e,0x98,0x07,0x3e,0x44,0xef,0x91 } },
+{  16, 0xacb0, 0, {0x3f,0xe0,0x4f,0xfc,0x07,0xee,0xd0,0xcf,0x98,0x33,0xe4,0x0f,0xf8,0x03,0xc0,0x00 } },
+{  16, 0xacc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x01,0x98,0x00,0x85,0x10,0x2d,0xc4 } },
+{  16, 0xacd0, 0, {0x0d,0x11,0x02,0xf0,0x00,0x85,0x20,0x31,0xc4,0x0b,0x7b,0x00,0x38,0x40,0xd7,0x10 } },
+{  16, 0xace0, 0, {0x2d,0x80,0x0b,0x70,0x62,0xfe,0xe1,0x87,0x14,0x39,0xc0,0x0b,0x60,0x02,0xea,0x04 } },
+{  16, 0xacf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xbc,0x40,0xa5,0x00,0x29,0x40 } },
+{  16, 0xad00, 0, {0x0b,0x50,0x82,0xdc,0x40,0x84,0x04,0x2d,0xc0,0x0b,0x10,0x06,0x58,0x44,0xa7,0x10 } },
+{  16, 0xad10, 0, {0x2d,0x80,0x0b,0x71,0x02,0xdc,0x00,0x87,0x04,0x21,0xc2,0x0b,0x50,0x02,0xc0,0x10 } },
+{  16, 0xad20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x0a,0xa1,0x01,0x2c,0x40 } },
+{  16, 0xad30, 0, {0x89,0x18,0x02,0xc1,0x00,0xa1,0x08,0x20,0xc0,0x0b,0x34,0x06,0x40,0x00,0x93,0x05 } },
+{  16, 0xad40, 0, {0x2c,0x14,0x0b,0x3c,0x86,0xce,0x10,0x83,0x01,0x28,0xf1,0x0b,0x14,0x02,0xc8,0x04 } },
+{  16, 0xad50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xa0,0x00,0xed,0x00,0x3a,0xc0 } },
+{  16, 0xad60, 0, {0x07,0xbc,0x63,0xed,0x00,0x81,0x40,0x3e,0xc0,0x0e,0x88,0x03,0x64,0x00,0xef,0x00 } },
+{  16, 0xad70, 0, {0x7e,0x50,0x0f,0xf0,0x02,0xfd,0x42,0xcf,0x00,0x72,0xc0,0x1f,0xb4,0x03,0xea,0x04 } },
+{  16, 0xad80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe8,0x00,0x99,0x00,0x3e,0xe0 } },
+{  16, 0xad90, 0, {0x4f,0xb4,0x83,0xed,0x90,0x09,0x40,0x3e,0xc0,0x0f,0xa1,0x83,0xa8,0x01,0xeb,0x01 } },
+{  16, 0xada0, 0, {0x3e,0x00,0x0f,0xb1,0x13,0xec,0x0c,0xfb,0x00,0x3a,0xc0,0x5f,0x20,0x23,0xe0,0x00 } },
+{  16, 0xadb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xf8,0x00,0xfd,0x04,0x3f,0xb0 } },
+{  16, 0xadc0, 0, {0x0d,0x60,0x03,0x3e,0x00,0xcd,0x00,0x33,0xf0,0x0f,0xf2,0x01,0xf0,0x00,0xff,0x03 } },
+{  16, 0xadd0, 0, {0x3f,0x03,0x0f,0xf0,0x01,0xfc,0x00,0xfb,0x02,0x33,0xc2,0x0f,0xf0,0xe3,0x00,0x44 } },
+{  16, 0xade0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6a,0x00,0xb9,0x02,0x2e,0xa0 } },
+{  16, 0xadf0, 0, {0x4a,0xac,0x02,0x0e,0x80,0xf9,0xc0,0x36,0xe1,0x0b,0xa0,0x02,0x2a,0x08,0xbb,0x00 } },
+{  16, 0xae00, 0, {0x2e,0x20,0x0e,0xb0,0x02,0xec,0x00,0xeb,0x00,0x22,0xc0,0x8b,0xb0,0x02,0x20,0x40 } },
+{  16, 0xae10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x23,0x00,0xa9,0x00,0x28,0xc0 } },
+{  16, 0xae20, 0, {0x09,0xb2,0x22,0x6c,0x40,0x89,0x89,0x2a,0xc0,0x0b,0x14,0x06,0x26,0x00,0xab,0x02 } },
+{  16, 0xae30, 0, {0x6e,0xe0,0x09,0xb0,0x06,0x6c,0x00,0xb3,0x02,0x22,0xc0,0x0b,0xb0,0x02,0x20,0x00 } },
+{  16, 0xae40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x08,0x00,0xb1,0x00,0x2c,0xc0 } },
+{  16, 0xae50, 0, {0x0a,0x30,0x02,0x2c,0x00,0xbb,0x00,0x64,0xc0,0x0b,0x32,0x0a,0x08,0x00,0x33,0x00 } },
+{  16, 0xae60, 0, {0x6c,0x80,0x02,0x30,0x46,0xcc,0x18,0xa3,0x00,0x20,0xc0,0x0b,0x28,0x02,0x02,0x11 } },
+{  16, 0xae70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x68,0x00,0xe9,0x00,0x38,0xc1 } },
+{  16, 0xae80, 0, {0x0d,0xb1,0x0b,0x2c,0x00,0x89,0x00,0x3a,0xc0,0x0b,0x90,0x03,0x60,0x00,0xff,0x02 } },
+{  16, 0xae90, 0, {0x3e,0x80,0x0f,0xf0,0x03,0xfc,0x80,0xff,0x00,0x32,0xc0,0x8f,0x80,0x0b,0x00,0x03 } },
+{  16, 0xaea0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x11,0xd8,0x00,0xfd,0x04,0x3f,0xc0 } },
+{  16, 0xaeb0, 0, {0x2f,0xf2,0x03,0xfc,0x11,0xef,0x00,0x3f,0xc0,0x0f,0xf4,0x43,0x70,0x00,0xff,0x00 } },
+{  16, 0xaec0, 0, {0x3f,0x00,0x46,0xf0,0x03,0xfd,0x00,0xef,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xe8,0x06 } },
+{  16, 0xaed0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfe,0x00,0xff,0x80,0x3d,0xe0 } },
+{  16, 0xaee0, 0, {0x0c,0xf9,0x13,0xde,0x00,0x7f,0x80,0xb3,0xe0,0x0f,0xfc,0x03,0xbe,0x40,0xcf,0x80 } },
+{  16, 0xaef0, 0, {0x33,0xf0,0x0f,0xf8,0x03,0x7c,0x04,0xcc,0x80,0x33,0xa0,0x0c,0xf0,0x0b,0x30,0x01 } },
+{  16, 0xaf00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe0,0x20,0x88,0x00,0x2e,0x20 } },
+{  16, 0xaf10, 0, {0x08,0x82,0x12,0xe0,0x80,0xa8,0x81,0x22,0x02,0x0b,0x80,0x02,0x20,0x80,0xa8,0x80 } },
+{  16, 0xaf20, 0, {0x22,0x08,0x0b,0x80,0x02,0x2c,0x02,0x88,0x04,0xaa,0x20,0x08,0xb0,0x02,0x20,0x04 } },
+{  16, 0xaf30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xec,0x00,0xa3,0x08,0x2c,0x80 } },
+{  16, 0xaf40, 0, {0x08,0x32,0x02,0xc4,0x20,0xa3,0x00,0x28,0x40,0x0b,0x92,0x02,0x84,0x00,0xa9,0x01 } },
+{  16, 0xaf50, 0, {0x28,0xc8,0x1b,0x12,0x82,0xcc,0x40,0xa8,0x00,0x24,0xe0,0x0a,0x30,0x42,0x22,0x01 } },
+{  16, 0xaf60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xa8,0x80,0xa8,0x02,0x2e,0x40 } },
+{  16, 0xaf70, 0, {0x68,0x80,0x10,0xc8,0x00,0xb8,0x40,0x2a,0x90,0x0b,0xa0,0x00,0x28,0x00,0xaa,0x08 } },
+{  16, 0xaf80, 0, {0x2a,0x02,0x03,0x20,0x02,0x8c,0x00,0xa8,0x88,0x2e,0x20,0x0a,0xb0,0x02,0x30,0x04 } },
+{  16, 0xaf90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe8,0x04,0xfa,0x00,0x3c,0x40 } },
+{  16, 0xafa0, 0, {0x0c,0xa0,0x03,0xe8,0x00,0xeb,0x00,0x3a,0xc0,0x0f,0x20,0x53,0xa8,0x00,0xe3,0x40 } },
+{  16, 0xafb0, 0, {0x2a,0x40,0x0f,0xa0,0x03,0x6c,0x00,0xa8,0x80,0x34,0x20,0x1e,0xb0,0x03,0x10,0x04 } },
+{  16, 0xafc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x00,0x9d,0x91,0x3f,0x80 } },
+{  16, 0xafd0, 0, {0x0f,0xda,0x23,0xf4,0x00,0xcc,0x20,0x37,0x00,0x07,0xd0,0x13,0x74,0x00,0xbc,0x00 } },
+{  16, 0xafe0, 0, {0xb7,0x80,0x0b,0xd0,0x43,0x7c,0x00,0xdc,0x04,0x3b,0x00,0x6d,0xf0,0x03,0xf8,0x00 } },
+{  16, 0xaff0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa8,0x00,0xfa,0x80,0x3a,0x00 } },
+{  16, 0xb000, 0, {0x2c,0xa0,0x0b,0x20,0x02,0xcb,0x62,0x3e,0x50,0x0e,0x88,0x03,0x20,0x00,0xd9,0x10 } },
+{  16, 0xb010, 0, {0x3e,0x70,0x8c,0x80,0x33,0xec,0x80,0xd8,0x40,0x3a,0x02,0x0d,0xb0,0x03,0x10,0x04 } },
+{  16, 0xb020, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x01,0x0c,0x00,0x39,0x80,0x22,0xc0 } },
+{  16, 0xb030, 0, {0x0c,0x9d,0x82,0x2c,0x10,0xd0,0x40,0x2e,0xa0,0x08,0xb8,0x03,0x4e,0x02,0x8a,0x40 } },
+{  16, 0xb040, 0, {0x0e,0xa0,0x0d,0xb0,0x03,0x3d,0x00,0xd0,0x90,0x36,0x10,0x0b,0xf0,0x02,0xb2,0x00 } },
+{  16, 0xb050, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb1,0x00,0x60,0xc0 } },
+{  16, 0xb060, 0, {0x8a,0x18,0x02,0x8c,0x08,0x80,0x40,0x0c,0xa0,0x02,0x30,0x02,0xce,0x00,0x82,0x48 } },
+{  16, 0xb070, 0, {0x2c,0x80,0x2b,0x30,0x06,0x8c,0x00,0x81,0x02,0x20,0x90,0x09,0xb0,0x02,0x38,0x00 } },
+{  16, 0xb080, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x12,0x00,0xb6,0x90,0xa3,0x30 } },
+{  16, 0xb090, 0, {0x08,0xe8,0x22,0xb2,0x14,0x87,0x80,0x2d,0x60,0x08,0x49,0x12,0x12,0x61,0x95,0x90 } },
+{  16, 0xb0a0, 0, {0x2d,0x61,0x0a,0x48,0x16,0x1e,0x80,0x95,0x80,0x25,0x20,0x0b,0x78,0x02,0x88,0x00 } },
+{  16, 0xb0b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xf1,0x00,0x28,0x8c } },
+{  16, 0xb0c0, 0, {0x8e,0x10,0x03,0x84,0x80,0x80,0x00,0x2c,0x02,0x0a,0x9a,0x02,0xe4,0x00,0xd0,0x00 } },
+{  16, 0xb0d0, 0, {0x3e,0x80,0x0b,0x91,0x03,0x8e,0x80,0xc2,0x08,0x38,0x80,0x0d,0xb0,0x03,0x12,0x02 } },
+{  16, 0xb0e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb0,0x00,0xf6,0x00,0x3f,0x44 } },
+{  16, 0xb0f0, 0, {0x0f,0x21,0x13,0x78,0x00,0xff,0x00,0x3d,0xc0,0x0f,0xe0,0x03,0x78,0x00,0xef,0x04 } },
+{  16, 0xb100, 0, {0x3f,0x40,0x8d,0xe8,0x03,0xdc,0x04,0xf6,0x00,0x3f,0x00,0x0f,0xf0,0x83,0xd0,0x06 } },
+{  16, 0xb110, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x00,0xe8,0x80,0x32,0x40 } },
+{  16, 0xb120, 0, {0x0f,0x88,0x0b,0x28,0x00,0x78,0x02,0x3e,0x80,0x0e,0x28,0x03,0x28,0x00,0xca,0x80 } },
+{  16, 0xb130, 0, {0x32,0x00,0x0f,0xa0,0x03,0xec,0x00,0xc9,0x80,0x32,0x80,0x0f,0xb0,0x03,0x2a,0x00 } },
+{  16, 0xb140, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x8c,0x00,0x8f,0x00,0xa1,0x80 } },
+{  16, 0xb150, 0, {0x0b,0x70,0x42,0x14,0x00,0xb7,0x00,0x2d,0x41,0x0b,0x50,0x42,0x14,0x00,0xa5,0x00 } },
+{  16, 0xb160, 0, {0xa1,0xc0,0x0b,0x50,0x02,0xfc,0x80,0xa5,0x00,0x21,0x00,0x0b,0xf2,0x02,0x12,0x04 } },
+{  16, 0xb170, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0xba,0x00,0xa4,0x80,0x29,0x30 } },
+{  16, 0xb180, 0, {0x4b,0x48,0x06,0x52,0x08,0xb4,0x80,0x2d,0x20,0x0b,0x48,0x42,0x32,0x00,0x84,0x80 } },
+{  16, 0xb190, 0, {0x21,0x20,0x0b,0x48,0x12,0xde,0x40,0x86,0x81,0x29,0xa0,0x0b,0x78,0x0a,0x30,0x00 } },
+{  16, 0xb1a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0x83,0x05,0x20,0xe0 } },
+{  16, 0xb1b0, 0, {0x0b,0x34,0x02,0x6c,0x10,0xb3,0x00,0x2c,0xc0,0x0b,0x36,0x4a,0x0d,0x0d,0xa3,0x00 } },
+{  16, 0xb1c0, 0, {0x20,0xc0,0x0b,0x34,0x82,0xcc,0x02,0xa2,0x00,0x28,0x00,0x0b,0x30,0x02,0x12,0x04 } },
+{  16, 0xb1d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa9,0x20,0xea,0x40,0x30,0xa0 } },
+{  16, 0xb1e0, 0, {0x07,0xa0,0x43,0x69,0x40,0xfa,0x00,0x3c,0x80,0x0f,0xa0,0x03,0x08,0x40,0xca,0x00 } },
+{  16, 0xb1f0, 0, {0x30,0xa0,0x0f,0xa4,0x03,0xe8,0x00,0xce,0x00,0x3b,0x98,0x0f,0xa0,0x03,0x3a,0x04 } },
+{  16, 0xb200, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xd2,0x00,0xfc,0x08,0x3f,0x00 } },
+{  16, 0xb210, 0, {0x0b,0xc2,0x03,0xb0,0x00,0xfc,0x00,0x3f,0x00,0x0f,0xc0,0x03,0xf0,0x00,0xfc,0x00 } },
+{  16, 0xb220, 0, {0x3f,0x04,0x0f,0xc0,0x03,0xe0,0x00,0xf8,0x00,0xb6,0x02,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xb230, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xd9,0x00,0x3e,0x68 } },
+{  16, 0xb240, 0, {0x4c,0x91,0x01,0xe4,0x08,0xc9,0x00,0x3e,0x40,0x2c,0x92,0x03,0xe4,0x02,0xc9,0xa0 } },
+{  16, 0xb250, 0, {0x3e,0x70,0x0e,0x90,0x03,0xc6,0x42,0xc9,0x00,0x3e,0x40,0x0f,0x10,0x03,0x02,0x04 } },
+{  16, 0xb260, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x86,0x0e,0x60 } },
+{  16, 0xb270, 0, {0x08,0x98,0x02,0xe4,0x08,0x89,0x10,0x2e,0x60,0x08,0x90,0x02,0xe4,0x00,0x89,0x0c } },
+{  16, 0xb280, 0, {0x2e,0x60,0x08,0x90,0x02,0xe6,0x88,0x89,0x00,0x2e,0x40,0x0b,0x90,0x02,0xa0,0x00 } },
+{  16, 0xb290, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x9d,0x10,0x2f,0x40 } },
+{  16, 0xb2a0, 0, {0x28,0xd0,0x06,0xf4,0x02,0xad,0x00,0x2f,0x60,0x08,0xd0,0x02,0xf4,0x00,0x8d,0x00 } },
+{  16, 0xb2b0, 0, {0x2f,0x40,0x0a,0xd0,0x02,0xe4,0x00,0x89,0x00,0x2e,0x60,0x0b,0x90,0x02,0x06,0x00 } },
+{  16, 0xb2c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x34,0x00,0x85,0x00,0x2d,0x40 } },
+{  16, 0xb2d0, 0, {0x08,0x58,0x02,0xd4,0x00,0xa5,0x02,0x2d,0x40,0x08,0x50,0x00,0xd4,0x00,0x85,0x00 } },
+{  16, 0xb2e0, 0, {0x2d,0x40,0x08,0x54,0x02,0xc4,0x80,0x81,0x00,0x2c,0x60,0x0b,0x14,0x02,0x82,0x01 } },
+{  16, 0xb2f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xd8,0x52,0x3e,0x00 } },
+{  16, 0xb300, 0, {0x0c,0x05,0x03,0xe1,0x40,0xe8,0x04,0x3e,0x14,0x0c,0x85,0x03,0xe1,0x40,0xc8,0x00 } },
+{  16, 0xb310, 0, {0x3e,0x14,0x0e,0xc0,0x03,0xe0,0x00,0xc0,0x02,0x3e,0x00,0x4f,0x80,0x23,0x2e,0x03 } },
+{  16, 0xb320, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x00,0xf9,0x01,0x3e,0x40 } },
+{  16, 0xb330, 0, {0x4f,0x90,0x13,0xe4,0x00,0xd9,0x00,0x1e,0x40,0x0f,0x90,0x03,0xc4,0x10,0xf1,0x00 } },
+{  16, 0xb340, 0, {0x1e,0x40,0x0f,0x90,0x03,0xe4,0xe0,0xfd,0x28,0x3f,0x40,0x0f,0x94,0x03,0xe6,0x06 } },
+{  16, 0xb350, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xa4,0x00,0xfd,0x00,0x3f,0x40 } },
+{  16, 0xb360, 0, {0x4d,0x50,0x02,0xe4,0x00,0x95,0x04,0x33,0x40,0x28,0xd0,0x03,0xf4,0x00,0xfd,0x00 } },
+{  16, 0xb370, 0, {0x33,0x40,0x0f,0x91,0x03,0x34,0x00,0xcd,0x40,0x33,0x40,0x0f,0x98,0x81,0x06,0x00 } },
+{  16, 0xb380, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x10,0xb8,0x00,0x2e,0x00 } },
+{  16, 0xb390, 0, {0x0b,0x80,0x02,0xe0,0x10,0xb8,0x00,0x22,0x00,0x08,0x80,0x02,0xe0,0x00,0xb8,0x00 } },
+{  16, 0xb3a0, 0, {0x22,0x00,0x0b,0x88,0x03,0xc2,0x80,0x88,0x80,0x22,0x00,0x0b,0x8c,0x02,0x0e,0x04 } },
+{  16, 0xb3b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0xc4,0x00,0xb1,0x00,0x2c,0xc0 } },
+{  16, 0xb3c0, 0, {0x0b,0x10,0x02,0xc4,0x00,0xbb,0x00,0x22,0x40,0x08,0x10,0x02,0xc4,0x01,0xb9,0x00 } },
+{  16, 0xb3d0, 0, {0x20,0x40,0x1b,0x90,0x02,0x04,0x22,0x89,0x00,0x20,0x60,0x0b,0x12,0x82,0x02,0x01 } },
+{  16, 0xb3e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x44,0xb9,0x00,0x2e,0xc0 } },
+{  16, 0xb3f0, 0, {0x4b,0x90,0x02,0xe4,0x10,0xb9,0x02,0x02,0x40,0x08,0x91,0x42,0xe4,0x00,0xb9,0x80 } },
+{  16, 0xb400, 0, {0x22,0x40,0x0b,0x92,0x02,0xc4,0x00,0x99,0x40,0x22,0x40,0x4b,0x90,0x12,0x06,0x04 } },
+{  16, 0xb410, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe6,0x00,0xb9,0x01,0x3e,0x58 } },
+{  16, 0xb420, 0, {0x0d,0x90,0x03,0xe6,0x00,0xd1,0x00,0x32,0x60,0x0c,0x98,0x02,0xe6,0x40,0xf9,0x00 } },
+{  16, 0xb430, 0, {0xb2,0x40,0x0f,0x18,0x03,0x24,0x00,0xc9,0x80,0x32,0x50,0x0f,0x90,0x23,0x28,0x04 } },
+{  16, 0xb440, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x00,0x3e,0x42 } },
+{  16, 0xb450, 0, {0x0b,0x90,0x03,0xe7,0x08,0xf9,0x00,0xbe,0x48,0x0f,0x90,0x03,0xe4,0x00,0xf9,0x00 } },
+{  16, 0xb460, 0, {0x3e,0x40,0x0f,0x98,0x03,0xa4,0x00,0xe9,0xa0,0xbe,0x40,0x0f,0x10,0x0b,0x4a,0x00 } },
+{  16, 0xb470, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xd8,0x01,0x3e,0x00 } },
+{  16, 0xb480, 0, {0x0f,0x80,0x8b,0x20,0x00,0xf8,0x20,0x3e,0x01,0x0f,0x81,0x03,0xe0,0x00,0xf8,0x08 } },
+{  16, 0xb490, 0, {0x3a,0x00,0x0c,0x80,0x03,0xe0,0x00,0xd8,0x40,0x32,0x00,0x0f,0x80,0x13,0x0a,0x04 } },
+{  16, 0xb4a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8a,0x80,0x2f,0x91 } },
+{  16, 0xb4b0, 0, {0x0b,0xee,0x02,0x28,0x01,0xbe,0x00,0x20,0x80,0x0b,0xa0,0x02,0xea,0x80,0xb6,0x48 } },
+{  16, 0xb4c0, 0, {0x22,0x80,0x0d,0xa0,0x02,0xfa,0x02,0x86,0x41,0xa3,0xa6,0x0b,0xa0,0x03,0x0a,0x00 } },
+{  16, 0xb4d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0x80,0x2c,0xc0 } },
+{  16, 0xb4e0, 0, {0x0b,0x30,0x02,0x0c,0x10,0xb3,0x00,0x28,0xc0,0x0b,0x38,0x02,0xcc,0x00,0xb3,0x00 } },
+{  16, 0xb4f0, 0, {0x28,0xc0,0x09,0x30,0x02,0xc6,0x01,0x83,0x60,0x20,0x70,0x0b,0x30,0x0a,0x4a,0x00 } },
+{  16, 0xb500, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x2e,0x88,0x85,0x08,0x2d,0x80 } },
+{  16, 0xb510, 0, {0x4b,0xf8,0x06,0x1c,0x80,0xb7,0x00,0x21,0xc0,0x0b,0x50,0x02,0xd4,0x00,0xb6,0x00 } },
+{  16, 0xb520, 0, {0x29,0x60,0x09,0x70,0x02,0xd0,0xa0,0x8d,0x00,0x21,0x40,0x0b,0x32,0x02,0x28,0x00 } },
+{  16, 0xb530, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xd5,0x80,0x3d,0xe0 } },
+{  16, 0xb540, 0, {0x8f,0x78,0x03,0x1e,0x84,0xb7,0x82,0x3d,0x60,0x0f,0x59,0x03,0xde,0x00,0xf7,0x80 } },
+{  16, 0xb550, 0, {0x29,0x60,0x15,0x78,0x03,0xde,0x00,0xc7,0x80,0x31,0x60,0x0f,0x7c,0x03,0x6a,0x02 } },
+{  16, 0xb560, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x40,0xe9,0x00,0x3e,0x80 } },
+{  16, 0xb570, 0, {0x0f,0xa0,0x03,0xed,0x30,0xfb,0x00,0x36,0xc1,0x0f,0x96,0x03,0xe4,0x00,0xb3,0x00 } },
+{  16, 0xb580, 0, {0x34,0x40,0x0f,0xb7,0x83,0xec,0x40,0x21,0x00,0x3e,0x40,0x0f,0xb0,0x03,0xc2,0x06 } },
+{  16, 0xb590, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xff,0x81,0x33,0xe0 } },
+{  16, 0xb5a0, 0, {0x0f,0xf9,0x03,0xde,0x20,0xcf,0x81,0x3f,0xe0,0x07,0x78,0x03,0x3e,0x00,0xff,0x80 } },
+{  16, 0xb5b0, 0, {0x3f,0xe0,0x04,0xf8,0x13,0xfe,0x02,0xde,0x80,0x33,0x60,0x0f,0xf8,0x03,0x00,0x00 } },
+{  16, 0xb5c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xb7,0x00,0x21,0xc4 } },
+{  16, 0xb5d0, 0, {0x0b,0x5a,0x02,0xdc,0x48,0x86,0x50,0x2d,0xc0,0x0b,0x31,0x02,0x94,0x60,0xb4,0x18 } },
+{  16, 0xb5e0, 0, {0x2d,0x40,0x48,0x70,0x02,0xe8,0x00,0xa5,0x10,0x21,0x40,0x0b,0x71,0x02,0x2a,0x04 } },
+{  16, 0xb5f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xbd,0x00,0x21,0x42 } },
+{  16, 0xb600, 0, {0x0b,0x70,0x02,0xfc,0x02,0x85,0x00,0x25,0x40,0x0b,0x50,0x02,0x9c,0x00,0xb7,0x00 } },
+{  16, 0xb610, 0, {0x2f,0x40,0x28,0x71,0x02,0xdc,0x00,0xa6,0x00,0x21,0xc0,0x0b,0x70,0x02,0x00,0x00 } },
+{  16, 0xb620, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0x6d,0x80,0xb1,0x20,0xa0,0x50 } },
+{  16, 0xb630, 0, {0x0b,0xb2,0x06,0xce,0x00,0xa0,0x34,0x2e,0xf0,0x0b,0x18,0x02,0x85,0x20,0xb3,0x4a } },
+{  16, 0xb640, 0, {0x2c,0x54,0x88,0x38,0x02,0xcc,0x10,0xa1,0x00,0x20,0xb0,0x0b,0x30,0x02,0x08,0x04 } },
+{  16, 0xb650, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbe,0x80,0xf3,0x08,0x10,0x54 } },
+{  16, 0xb660, 0, {0x0b,0x88,0x13,0xff,0x00,0xc0,0x80,0x3e,0x64,0x0f,0xb4,0x83,0x07,0x00,0xf9,0xc0 } },
+{  16, 0xb670, 0, {0x3e,0xf0,0x0c,0xfc,0x13,0xf4,0x00,0xea,0x00,0x32,0x70,0x0f,0xf0,0x0b,0x2a,0x04 } },
+{  16, 0xb680, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xf9,0x00,0x3e,0x10 } },
+{  16, 0xb690, 0, {0x07,0x91,0x03,0xec,0xc0,0x58,0x00,0x3e,0x44,0x0f,0x92,0x03,0xe4,0x00,0xf9,0x00 } },
+{  16, 0xb6a0, 0, {0x3e,0xc0,0x8f,0xb3,0x03,0xe0,0x00,0xbb,0x00,0xbe,0x44,0x0f,0xb0,0x03,0xe0,0x00 } },
+{  16, 0xb6b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x02,0xcd,0x04,0x33,0xe0 } },
+{  16, 0xb6c0, 0, {0x0c,0xc0,0x03,0x3c,0x08,0xfe,0x00,0x33,0x60,0x2c,0xd0,0x02,0xb4,0x80,0xcf,0x00 } },
+{  16, 0xb6d0, 0, {0x3f,0x52,0x07,0xf0,0x13,0xfc,0x00,0xce,0x10,0x33,0x42,0x0c,0xb0,0x03,0xc0,0x44 } },
+{  16, 0xb6e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x00,0x89,0x00,0x2a,0xb0 } },
+{  16, 0xb6f0, 0, {0x08,0x88,0x02,0x2c,0x00,0xba,0x00,0x36,0x44,0x08,0x90,0x00,0x26,0x00,0xdb,0xc0 } },
+{  16, 0xb700, 0, {0x2e,0x40,0x0b,0xb0,0x02,0xec,0x00,0x83,0xc0,0x28,0x40,0x0a,0xb0,0x02,0xe0,0x40 } },
+{  16, 0xb710, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x00,0x22,0x08 } },
+{  16, 0xb720, 0, {0x1a,0xa2,0x02,0x2c,0x10,0xb9,0x20,0x22,0x40,0x08,0x30,0x02,0x2c,0x04,0xaa,0x54 } },
+{  16, 0xb730, 0, {0x2e,0xc0,0x0b,0xb0,0x12,0xcc,0x00,0x8b,0x08,0x22,0x40,0x08,0xb0,0x02,0xe0,0x00 } },
+{  16, 0xb740, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x04,0x2a,0x00 } },
+{  16, 0xb750, 0, {0x0a,0x08,0x82,0x0c,0x00,0xb8,0x00,0x64,0x40,0x08,0x30,0x02,0xa4,0x00,0xb0,0x00 } },
+{  16, 0xb760, 0, {0x2c,0xc0,0x8b,0x30,0x10,0xc8,0x02,0x8b,0x00,0x2a,0x40,0x0a,0x30,0x02,0xc2,0x01 } },
+{  16, 0xb770, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xc9,0x00,0x32,0x00 } },
+{  16, 0xb780, 0, {0x1a,0x82,0x03,0x3c,0x00,0xf9,0x00,0x32,0x40,0x0c,0xd1,0x03,0xac,0x00,0xeb,0x00 } },
+{  16, 0xb790, 0, {0x3e,0x40,0x0f,0xf0,0x03,0xed,0x00,0xc3,0x00,0x32,0xc0,0x8c,0xb0,0x03,0xc0,0x03 } },
+{  16, 0xb7a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xf5,0x00,0x3f,0x00 } },
+{  16, 0xb7b0, 0, {0x0d,0x80,0x4b,0xfc,0x00,0x7c,0x00,0x3f,0x40,0x0f,0xd2,0x0b,0x74,0x00,0xdf,0x00 } },
+{  16, 0xb7c0, 0, {0x1d,0x40,0x8f,0xf0,0x03,0xfc,0xa0,0xff,0x00,0x3f,0x80,0x0f,0xf0,0x03,0xe8,0x06 } },
+{  16, 0xb7d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xdf,0x84,0x3b,0xe0 } },
+{  16, 0xb7e0, 0, {0x0f,0xf8,0x0b,0x3e,0x00,0xec,0x80,0x33,0xe1,0x0c,0x30,0x03,0x3c,0x80,0xcf,0x48 } },
+{  16, 0xb7f0, 0, {0x37,0xc0,0x0e,0x40,0x03,0xe0,0xc0,0xc7,0x91,0xb3,0x04,0x0c,0xf0,0x03,0x30,0x00 } },
+{  16, 0xb800, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xef,0x04,0x8b,0x80,0x22,0x41 } },
+{  16, 0xb810, 0, {0x0b,0xb0,0x82,0x2e,0x00,0x88,0x80,0xa2,0xe0,0x0a,0xa2,0x92,0xad,0x80,0x87,0x42 } },
+{  16, 0xb820, 0, {0x23,0xd8,0x8a,0xad,0x02,0xe0,0xc0,0x8b,0x00,0x20,0x4c,0x48,0xa4,0x02,0x20,0x04 } },
+{  16, 0xb830, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x58,0xbb,0x00,0x28,0x80 } },
+{  16, 0xb840, 0, {0x0b,0xb2,0x42,0x24,0x00,0xa8,0x00,0x2a,0xc0,0x0a,0x10,0x02,0x04,0x60,0xa3,0x20 } },
+{  16, 0xb850, 0, {0x24,0xd2,0x08,0x00,0x42,0x8c,0x83,0x9b,0x01,0x20,0x49,0x08,0x33,0xc2,0x22,0x01 } },
+{  16, 0xb860, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x00,0xab,0x88,0x22,0xa0 } },
+{  16, 0xb870, 0, {0x0b,0xb8,0x02,0x26,0x0c,0xa8,0x00,0x2a,0xc0,0x0a,0x92,0x02,0xa4,0x00,0xab,0x06 } },
+{  16, 0xb880, 0, {0x22,0xc0,0x0a,0xb0,0x02,0xe8,0x00,0x9b,0x00,0x02,0x40,0x08,0xa0,0x42,0x30,0x04 } },
+{  16, 0xb890, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xd3,0x80,0x3a,0xe0 } },
+{  16, 0xb8a0, 0, {0x0f,0x18,0x01,0x06,0x00,0xe8,0x30,0x38,0x66,0x0e,0xb8,0x03,0x2a,0x40,0xeb,0x00 } },
+{  16, 0xb8b0, 0, {0x36,0xc1,0x0e,0x96,0x03,0xe2,0x80,0xda,0x08,0x32,0x80,0x2c,0xbb,0x03,0x10,0x04 } },
+{  16, 0xb8c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x9c,0x00,0xdf,0x00,0x3f,0xc0 } },
+{  16, 0xb8d0, 0, {0x0f,0xd0,0x03,0xf4,0x00,0xdc,0x80,0x37,0x60,0x0f,0xe8,0x03,0xfa,0x00,0xdf,0x01 } },
+{  16, 0xb8e0, 0, {0x3f,0xc0,0x0f,0xc0,0x43,0xe6,0x4c,0xef,0xa0,0x3f,0x44,0x0f,0xa0,0x03,0xf8,0x00 } },
+{  16, 0xb8f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x40,0xdb,0x00,0x36,0x80 } },
+{  16, 0xb900, 0, {0x0c,0x98,0x03,0x26,0x00,0xf8,0x00,0x3e,0xc0,0x0e,0x18,0x03,0x84,0x02,0xe3,0x01 } },
+{  16, 0xb910, 0, {0x38,0xc1,0x0e,0xb4,0x03,0xac,0x80,0xca,0x18,0x3a,0xd0,0x2c,0x30,0x03,0x10,0x04 } },
+{  16, 0xb920, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3f,0x40,0xb9,0x88,0x2e,0x80 } },
+{  16, 0xb930, 0, {0x08,0xbc,0x02,0xa3,0x00,0xb0,0x00,0x0e,0xc0,0x08,0xb0,0x06,0x20,0x00,0x8f,0x04 } },
+{  16, 0xb940, 0, {0x23,0xc1,0x08,0xb9,0x12,0x2f,0x00,0x83,0x80,0x36,0x40,0x08,0xad,0x02,0x32,0x00 } },
+{  16, 0xb950, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb2,0x00,0x2c,0xc0 } },
+{  16, 0xb960, 0, {0x09,0x32,0x02,0x84,0x00,0x33,0x00,0x2c,0xb2,0x0a,0x36,0x12,0x8c,0x08,0x93,0x05 } },
+{  16, 0xb970, 0, {0x20,0xc0,0x0b,0x18,0x02,0xed,0x00,0x91,0x80,0x6a,0x00,0x08,0x10,0x02,0x38,0x00 } },
+{  16, 0xb980, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0xb7,0x80,0x2d,0xe0 } },
+{  16, 0xb990, 0, {0x09,0x78,0x02,0x97,0x40,0xb4,0x80,0x2f,0xa0,0x08,0xe8,0x02,0x0e,0x40,0x97,0x82 } },
+{  16, 0xb9a0, 0, {0x21,0xe0,0x98,0x68,0x82,0x1a,0x18,0x9d,0x90,0x2d,0xa1,0x18,0x58,0x02,0x08,0x00 } },
+{  16, 0xb9b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0xc0,0xf3,0x00,0x3e,0xc0 } },
+{  16, 0xb9c0, 0, {0x0d,0xb0,0x43,0x84,0x40,0xf0,0x00,0x3c,0x82,0x0e,0x38,0x12,0x8c,0x44,0xf3,0x30 } },
+{  16, 0xb9d0, 0, {0xba,0xc1,0x1e,0x10,0x47,0x8e,0x22,0xd1,0x10,0x38,0x18,0x0c,0x30,0x83,0x12,0x02 } },
+{  16, 0xb9e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x40,0xff,0x00,0x3f,0xc0 } },
+{  16, 0xb9f0, 0, {0x0e,0xe0,0x03,0xf4,0x40,0xfc,0x00,0x3d,0xc4,0x0f,0xd0,0x01,0xf4,0x41,0xef,0x18 } },
+{  16, 0xba00, 0, {0x3f,0xc4,0x1f,0xf0,0x03,0xf8,0x48,0xef,0x14,0x33,0x80,0x0f,0xc1,0x03,0xd0,0x06 } },
+{  16, 0xba10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xfc,0x40,0xfb,0x00,0x3e,0xc0 } },
+{  16, 0xba20, 0, {0x0f,0x98,0x03,0x24,0x00,0xcb,0x00,0x3e,0x40,0x0f,0xb0,0x03,0xa8,0x00,0xdb,0x28 } },
+{  16, 0xba30, 0, {0x3e,0xc4,0x1f,0x90,0x23,0xec,0x00,0xca,0x00,0x32,0xe0,0x0c,0x90,0x03,0xea,0x00 } },
+{  16, 0xba40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x80,0xb7,0x00,0x2d,0xc0 } },
+{  16, 0xba50, 0, {0x4b,0x50,0x52,0x14,0x00,0xd4,0x01,0x2d,0x80,0x0b,0x60,0x02,0xd8,0x00,0xa7,0x20 } },
+{  16, 0xba60, 0, {0x2d,0xc5,0x0b,0x40,0x16,0xdc,0x00,0x84,0x00,0x23,0xc0,0x08,0x40,0x02,0xd2,0x04 } },
+{  16, 0xba70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x80,0xb7,0x80,0x2d,0xe0 } },
+{  16, 0xba80, 0, {0x0b,0x78,0x0a,0x96,0x00,0x94,0x80,0x2d,0x60,0x1b,0x78,0x06,0xd2,0x00,0xa7,0x80 } },
+{  16, 0xba90, 0, {0x2d,0xe0,0x0b,0x78,0x22,0xde,0x00,0x87,0x82,0x21,0xe0,0x08,0x58,0x02,0xf0,0x00 } },
+{  16, 0xbaa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0xe4,0x2c,0xc0 } },
+{  16, 0xbab0, 0, {0x1b,0x21,0x02,0x81,0x00,0x90,0x00,0x2c,0xc8,0x0b,0x39,0x02,0xce,0x00,0xa3,0x00 } },
+{  16, 0xbac0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcd,0x00,0x8b,0x20,0x20,0xf0,0x08,0xb2,0x02,0xd2,0x04 } },
+{  16, 0xbad0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfe,0xa0,0x3f,0x82 } },
+{  16, 0xbae0, 0, {0x0f,0xe8,0x03,0x98,0x30,0xd6,0x00,0x3f,0xa0,0x0f,0xe0,0x03,0xba,0xc0,0xfa,0x00 } },
+{  16, 0xbaf0, 0, {0x3e,0x80,0x0f,0xec,0x33,0xf8,0x02,0xce,0x00,0xb3,0xb8,0x2c,0xec,0x83,0xfa,0x04 } },
+{  16, 0xbb00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x18,0xf8,0x40,0x3e,0x00 } },
+{  16, 0xbb10, 0, {0x0f,0x80,0x02,0x60,0x84,0xf8,0x05,0x2e,0x04,0x8f,0x80,0x41,0xe0,0x00,0x78,0x02 } },
+{  16, 0xbb20, 0, {0x3e,0x00,0x0f,0x81,0x83,0xe0,0x20,0xf8,0x00,0xbe,0x02,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xbb30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe6,0x18,0xf9,0x20,0x3e,0x40 } },
+{  16, 0xbb40, 0, {0x0f,0x9c,0x03,0xe4,0x40,0xc9,0x00,0x32,0x61,0x0c,0x90,0x13,0xc4,0x08,0xc9,0x01 } },
+{  16, 0xbb50, 0, {0x3e,0x41,0x0f,0x18,0x03,0x24,0x00,0xc9,0xa0,0x32,0x40,0x0f,0x98,0x43,0x02,0x04 } },
+{  16, 0xbb60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x65,0x00,0xb1,0xc0,0x22,0x40 } },
+{  16, 0xbb70, 0, {0x0b,0x9c,0x02,0xe7,0x10,0x89,0x00,0x28,0x44,0x08,0x94,0x22,0xe4,0x10,0x89,0x00 } },
+{  16, 0xbb80, 0, {0x2e,0x40,0x0b,0x9f,0x22,0x26,0x60,0x89,0x80,0x22,0x40,0x0b,0x91,0x0a,0x20,0x00 } },
+{  16, 0xbb90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x80,0xb9,0x00,0x2e,0xc0 } },
+{  16, 0xbba0, 0, {0x4b,0xb4,0x02,0xe4,0x20,0x89,0x20,0x22,0x40,0x08,0x94,0x02,0xec,0x00,0x89,0x00 } },
+{  16, 0xbbb0, 0, {0x2e,0x41,0x0b,0x90,0x02,0x04,0x00,0x89,0x40,0x22,0x40,0x0b,0x90,0x02,0x06,0x00 } },
+{  16, 0xbbc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb1,0x04,0x20,0x40 } },
+{  16, 0xbbd0, 0, {0x8b,0x10,0x02,0xe4,0x05,0x81,0x00,0x28,0x40,0x28,0x12,0x12,0xc4,0x82,0x81,0x20 } },
+{  16, 0xbbe0, 0, {0x2c,0x48,0x0b,0x12,0x0a,0x04,0x82,0x81,0x00,0x20,0x48,0x0b,0x12,0x02,0x02,0x01 } },
+{  16, 0xbbf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x68,0xa0,0xfa,0x02,0x3e,0x14 } },
+{  16, 0xbc00, 0, {0x0f,0x85,0x03,0xe0,0x00,0xc8,0x00,0x32,0x00,0x0c,0x85,0x03,0xc1,0x40,0xc8,0x53 } },
+{  16, 0xbc10, 0, {0x3e,0x14,0x0f,0x80,0x03,0x01,0x48,0xc0,0x50,0xb2,0x14,0x0f,0x85,0x03,0x2e,0x03 } },
+{  16, 0xbc20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x00,0xfd,0x00,0xbf,0x40 } },
+{  16, 0xbc30, 0, {0x0f,0x50,0x13,0xd4,0x02,0xfd,0x00,0x2f,0xc0,0x0f,0xd1,0x03,0xf4,0x40,0xf9,0x10 } },
+{  16, 0xbc40, 0, {0x3e,0x44,0x0f,0xd1,0x03,0xf4,0x40,0xff,0x00,0xbf,0x44,0x0f,0xd1,0x03,0xe6,0x06 } },
+{  16, 0xbc50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0xa0,0xfd,0x01,0x3e,0x44 } },
+{  16, 0xbc60, 0, {0x0f,0xd1,0x03,0xd4,0x00,0xc5,0x00,0x33,0x41,0x0f,0xdb,0x03,0x27,0x20,0xd9,0xe0 } },
+{  16, 0xbc70, 0, {0xb2,0x70,0x0d,0xda,0x83,0xf6,0x40,0xcf,0x10,0x32,0x78,0x2d,0xda,0x03,0x06,0x00 } },
+{  16, 0xbc80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x00,0xb8,0x00,0x2e,0x28 } },
+{  16, 0xbc90, 0, {0x0b,0x88,0x42,0xe0,0x10,0xd8,0x00,0x22,0x00,0x0b,0x8c,0x0a,0x23,0x00,0x88,0xc0 } },
+{  16, 0xbca0, 0, {0x22,0x28,0x08,0x84,0x02,0xc2,0x80,0x80,0xa0,0x22,0x30,0x48,0xaa,0x82,0x0e,0x04 } },
+{  16, 0xbcb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x2c,0x40 } },
+{  16, 0xbcc0, 0, {0x8b,0x12,0x02,0xc4,0x00,0x99,0x02,0x28,0x40,0x8b,0x16,0x02,0x84,0x81,0x91,0x30 } },
+{  16, 0xbcd0, 0, {0x20,0x58,0x09,0x10,0x02,0xc5,0x00,0x81,0x00,0x64,0x4d,0x08,0x34,0x02,0x02,0x01 } },
+{  16, 0xbce0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xac,0x0c,0xb9,0x04,0x2e,0x48 } },
+{  16, 0xbcf0, 0, {0x0b,0x94,0x06,0xe4,0x00,0x99,0x40,0xaa,0x40,0x0b,0x92,0x22,0xa4,0x00,0x89,0x00 } },
+{  16, 0xbd00, 0, {0x60,0x40,0x08,0x94,0x02,0xe4,0x00,0x89,0x80,0xa6,0x50,0x08,0x92,0x02,0x06,0x04 } },
+{  16, 0xbd10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x98,0x3e,0x48 } },
+{  16, 0xbd20, 0, {0x0f,0x98,0x03,0xe5,0x20,0xd9,0x00,0x3a,0x64,0x0f,0x94,0x83,0xa4,0xc0,0xd9,0x02 } },
+{  16, 0xbd30, 0, {0x72,0x40,0x4d,0x90,0x42,0xe4,0x82,0xc9,0x40,0x36,0x40,0x0c,0x90,0x0b,0x28,0x04 } },
+{  16, 0xbd40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xac,0x28,0xf9,0x88,0x3e,0x40 } },
+{  16, 0xbd50, 0, {0x0f,0x99,0x13,0xe7,0x00,0xf9,0xc0,0x36,0x60,0x0f,0x90,0x03,0x66,0x00,0xf1,0x00 } },
+{  16, 0xbd60, 0, {0x7e,0x40,0x0f,0x99,0x07,0xe4,0x60,0xf9,0x00,0x38,0x40,0x0f,0x98,0x03,0xca,0x00 } },
+{  16, 0xbd70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x10,0x32,0x00 } },
+{  16, 0xbd80, 0, {0x0f,0x82,0x0b,0x21,0x00,0xe8,0x00,0x36,0x04,0x0c,0x86,0x03,0xe1,0x00,0xd8,0x00 } },
+{  16, 0xbd90, 0, {0x32,0x00,0x0f,0x80,0x03,0x61,0x00,0xc8,0x00,0x32,0x00,0x0f,0x00,0x03,0x0a,0x04 } },
+{  16, 0xbda0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x20,0xbe,0x00,0x22,0x80 } },
+{  16, 0xbdb0, 0, {0x28,0xec,0x02,0x19,0x04,0x82,0x00,0x03,0x80,0x0d,0xe4,0x82,0xe8,0x00,0x8a,0x01 } },
+{  16, 0xbdc0, 0, {0xaa,0x80,0x8b,0xed,0x82,0x3b,0x80,0x8e,0x90,0x36,0x80,0x0b,0xe0,0x03,0x4a,0x00 } },
+{  16, 0xbdd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x42,0x00,0xb3,0x80,0x20,0xc0 } },
+{  16, 0xbde0, 0, {0x6b,0x34,0x16,0x40,0xc0,0x83,0x10,0x24,0x72,0x88,0xb0,0x02,0xec,0x00,0x83,0x00 } },
+{  16, 0xbdf0, 0, {0x24,0xc0,0x0b,0x04,0x02,0x6f,0x09,0x9b,0x00,0x24,0xc0,0x0b,0x30,0x02,0x0a,0x00 } },
+{  16, 0xbe00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x14,0x00,0xb7,0x80,0x23,0xe4 } },
+{  16, 0xbe10, 0, {0x28,0x78,0x82,0x74,0x14,0x8f,0x00,0x61,0xe0,0x09,0x50,0x12,0xdc,0x04,0x87,0x22 } },
+{  16, 0xbe20, 0, {0x25,0xc8,0x1b,0x78,0x02,0x14,0x00,0x94,0x40,0xa5,0xc0,0x0b,0x60,0x22,0x68,0x00 } },
+{  16, 0xbe30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x12,0x20,0xb7,0x80,0xb1,0xe0 } },
+{  16, 0xbe40, 0, {0x8f,0xf8,0x03,0x12,0x02,0xe7,0x80,0x35,0xe0,0x0c,0x68,0x06,0xcf,0xc2,0xcf,0xb0 } },
+{  16, 0xbe50, 0, {0x25,0xf4,0x0f,0x58,0x03,0x5a,0x02,0xd5,0x80,0x75,0xfa,0x4f,0xf8,0x03,0x2a,0x02 } },
+{  16, 0xbe60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xa5,0x90,0xf3,0x00,0x3d,0xc0 } },
+{  16, 0xbe70, 0, {0x4f,0xb0,0x13,0xa8,0x04,0xfb,0x00,0x3c,0xc0,0x0f,0x80,0x43,0xec,0x80,0xeb,0x60 } },
+{  16, 0xbe80, 0, {0x3a,0xc9,0x0f,0x30,0x03,0xec,0x00,0xe9,0x00,0x3e,0xc8,0x0f,0xa0,0x03,0xc2,0x06 } },
+{  16, 0xbe90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xf6,0x00,0xee,0x80,0x3f,0xe0 } },
+{  16, 0xbea0, 0, {0x0d,0x89,0x03,0xd2,0x40,0xe5,0x81,0x39,0xe0,0x3c,0xf9,0x07,0xfe,0x00,0xcf,0x88 } },
+{  16, 0xbeb0, 0, {0x3f,0xe0,0x0f,0xe8,0x03,0xf2,0x08,0xce,0x80,0x33,0xe0,0x0c,0xf8,0x03,0x00,0x00 } },
+{  16, 0xbec0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x94,0x44,0xc6,0x00,0x2f,0xc0 } },
+{  16, 0xbed0, 0, {0x08,0x58,0x02,0xd0,0xc4,0x85,0x24,0x21,0x90,0x08,0x54,0x12,0xdc,0x82,0x07,0x00 } },
+{  16, 0xbee0, 0, {0x2d,0xc0,0x0b,0x70,0x06,0xd4,0x00,0x8e,0x48,0x21,0xc0,0x0a,0x60,0x02,0x2a,0x04 } },
+{  16, 0xbef0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xa7,0x40,0x2d,0xc0 } },
+{  16, 0xbf00, 0, {0x08,0x42,0x02,0xd0,0x00,0xad,0x00,0x29,0xc0,0x08,0x70,0x22,0xdc,0x28,0x87,0x00 } },
+{  16, 0xbf10, 0, {0x2d,0xc0,0x0b,0x40,0x02,0x98,0x00,0x97,0x00,0xa0,0xc4,0x08,0x70,0x02,0x00,0x00 } },
+{  16, 0xbf20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x08,0x93,0x00,0x2c,0xe0 } },
+{  16, 0xbf30, 0, {0x08,0x3c,0x22,0xc1,0x00,0x81,0x00,0x20,0x80,0x88,0x15,0x02,0xce,0x30,0x83,0x00 } },
+{  16, 0xbf40, 0, {0x2c,0xc0,0x0b,0x3c,0x02,0xcc,0x04,0x93,0xc0,0x20,0xf4,0x4a,0x0c,0x82,0x08,0x04 } },
+{  16, 0xbf50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xa0,0x00,0xe3,0xc0,0x1f,0xe0 } },
+{  16, 0xbf60, 0, {0x6c,0x10,0x83,0xe0,0x04,0xeb,0x00,0x3a,0x52,0x4c,0xb4,0x03,0xfe,0x02,0xcf,0x00 } },
+{  16, 0xbf70, 0, {0x3f,0xc0,0x0f,0x84,0x43,0xe1,0x02,0xd8,0xc2,0x33,0xc0,0x0c,0x84,0x0b,0x2a,0x04 } },
+{  16, 0xbf80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe9,0x00,0xeb,0x10,0x3e,0xc4 } },
+{  16, 0xbf90, 0, {0x0e,0x94,0x03,0xe4,0x00,0xfb,0x18,0x3e,0xc2,0x0f,0xb6,0x03,0xec,0x00,0xfb,0x01 } },
+{  16, 0xbfa0, 0, {0x3e,0xc0,0x0f,0x35,0x03,0xc4,0x28,0xea,0x42,0x3e,0xc0,0x0f,0x81,0x03,0xe0,0x00 } },
+{  16, 0xbfb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x40,0xff,0x00,0x33,0xc0 } },
+{  16, 0xbfc0, 0, {0x0c,0xc0,0xa3,0x30,0x28,0xcd,0xa0,0x33,0xc0,0x0c,0xe8,0x03,0x0c,0x00,0xef,0x05 } },
+{  16, 0xbfd0, 0, {0x3d,0xc0,0x0c,0xca,0x83,0x3c,0x00,0xcd,0x08,0x3f,0xc2,0x0c,0xa0,0x03,0xc0,0x44 } },
+{  16, 0xbfe0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x67,0x00,0xbb,0x80,0x20,0xc0 } },
+{  16, 0xbff0, 0, {0x08,0xaa,0x02,0x08,0x00,0xa1,0x01,0x34,0xd1,0x08,0xa4,0x12,0x2c,0x00,0x8b,0x00 } },
+{  16, 0xc000, 0, {0x6e,0xc0,0x88,0xb2,0x02,0x2c,0x08,0x89,0x80,0x2e,0xc0,0x0a,0xa8,0x03,0xa0,0x40 } },
+{  16, 0xc010, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0xba,0x80,0xa2,0xc0 } },
+{  16, 0xc020, 0, {0x08,0xa8,0x0a,0xa0,0x00,0x8b,0x00,0xa2,0xc0,0x48,0x11,0x02,0xac,0x04,0x8b,0x00 } },
+{  16, 0xc030, 0, {0x2e,0xc0,0x00,0x80,0x12,0x2a,0x08,0x8b,0x14,0x2c,0xc0,0x08,0x88,0x02,0xe0,0x00 } },
+{  16, 0xc040, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xb2,0x00,0x22,0xc0 } },
+{  16, 0xc050, 0, {0x08,0xb2,0x12,0x80,0x00,0xab,0x01,0x24,0xc0,0x08,0x00,0x02,0x0c,0x04,0x83,0x00 } },
+{  16, 0xc060, 0, {0x2c,0xc0,0x08,0x30,0x02,0x07,0x00,0x82,0x00,0x24,0xc0,0x08,0x08,0x02,0x82,0x01 } },
+{  16, 0xc070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xfb,0x00,0x32,0xc0 } },
+{  16, 0xc080, 0, {0x0c,0xa2,0x03,0xa0,0x00,0xc9,0x00,0x32,0xc0,0x24,0x94,0x03,0x3c,0x02,0xcf,0x00 } },
+{  16, 0xc090, 0, {0x2f,0xc0,0x04,0x80,0x0b,0x09,0x02,0xcb,0x01,0x3f,0xc0,0x2c,0xa0,0x03,0xc0,0x03 } },
+{  16, 0xc0a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xdc,0x00,0xfd,0x02,0x3f,0xc0 } },
+{  16, 0xc0b0, 0, {0x4f,0xe4,0x13,0x70,0x00,0xfd,0x00,0x3f,0xc0,0x0f,0xc2,0x83,0xfc,0x00,0xff,0x00 } },
+{  16, 0xc0c0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xa8,0x06 } },
+{  16, 0xc0d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x20,0xef,0x30,0x3f,0x04 } },
+{  16, 0xc0e0, 0, {0x6c,0x88,0x03,0x3a,0x42,0xe4,0x91,0x3f,0x0d,0x0d,0x48,0x03,0x3c,0xc0,0xff,0x02 } },
+{  16, 0xc0f0, 0, {0x33,0x44,0x0c,0xf4,0x03,0xfc,0x82,0xdf,0x30,0x33,0x60,0x0d,0xf1,0x03,0x30,0x00 } },
+{  16, 0xc100, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0xed,0x00,0x8b,0x70,0x2e,0x18 } },
+{  16, 0xc110, 0, {0x88,0x22,0x4a,0x2c,0x82,0xea,0x26,0x2e,0x0c,0x0b,0xb8,0x42,0x3d,0x80,0xbf,0x90 } },
+{  16, 0xc120, 0, {0x2a,0x54,0x28,0xb4,0x02,0xcd,0x00,0xdb,0x40,0x2a,0x4a,0x48,0x30,0x02,0xa0,0x04 } },
+{  16, 0xc130, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0xb0,0xa3,0x00,0x6c,0x10 } },
+{  16, 0xc140, 0, {0x09,0x00,0x82,0x20,0x82,0xa0,0x20,0x2c,0x88,0x4b,0x80,0x00,0x0c,0x40,0xb3,0x01 } },
+{  16, 0xc150, 0, {0x20,0x48,0x0b,0x36,0x02,0x8c,0xe0,0x83,0x64,0x24,0x40,0x28,0x32,0x02,0x22,0x01 } },
+{  16, 0xc160, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x11,0xac,0x00,0x8b,0x00,0x2e,0x00 } },
+{  16, 0xc170, 0, {0x09,0x80,0x80,0xa6,0x00,0xba,0x11,0x2e,0x88,0x0b,0xb0,0x00,0x2c,0x00,0xbb,0x02 } },
+{  16, 0xc180, 0, {0x02,0x40,0x09,0xb0,0x02,0xec,0x00,0x8b,0x00,0x2c,0xc8,0x08,0xb8,0x82,0xb0,0x04 } },
+{  16, 0xc190, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xeb,0x00,0x3e,0x92 } },
+{  16, 0xc1a0, 0, {0x0d,0x80,0x03,0x0a,0x20,0xe9,0x00,0x3e,0x50,0x45,0x80,0x01,0x2c,0x04,0xf3,0x00 } },
+{  16, 0xc1b0, 0, {0x90,0x60,0x09,0xb0,0x03,0xec,0x00,0x8b,0x02,0x26,0x50,0x8d,0xbc,0x03,0x10,0x04 } },
+{  16, 0xc1c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0xbc,0x00,0xff,0x02,0x3f,0x80 } },
+{  16, 0xc1d0, 0, {0x0e,0xf9,0x02,0x7c,0x22,0xaf,0x00,0x3f,0x60,0x03,0xc0,0x0b,0xfc,0x10,0xff,0x00 } },
+{  16, 0xc1e0, 0, {0x3f,0x4a,0x4e,0xf0,0x03,0xfc,0x00,0xf7,0x00,0x2b,0x60,0x0f,0x70,0x03,0xf8,0x00 } },
+{  16, 0xc1f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x00,0xb0,0x00 } },
+{  16, 0xc200, 0, {0x0f,0x82,0x0b,0xa9,0x00,0xc9,0x00,0x32,0xd2,0x0f,0xa0,0x83,0xac,0x00,0xcb,0x10 } },
+{  16, 0xc210, 0, {0x3e,0x40,0x0c,0xb0,0x03,0xec,0x00,0xdb,0x00,0x32,0x50,0x2c,0x95,0x03,0x10,0x04 } },
+{  16, 0xc220, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3c,0x04,0xbf,0x02,0x22,0x80 } },
+{  16, 0xc230, 0, {0x0b,0x98,0x00,0x29,0x00,0xcb,0x40,0x22,0xc0,0x0b,0x24,0x02,0x3c,0x08,0x8f,0x50 } },
+{  16, 0xc240, 0, {0x2e,0x50,0x0d,0xf0,0x02,0xfd,0x42,0x8f,0x58,0x22,0xe0,0x48,0xb5,0x02,0x32,0x00 } },
+{  16, 0xc250, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x6c,0x00,0xb3,0x00,0x24,0x40 } },
+{  16, 0xc260, 0, {0x4b,0x94,0x00,0x49,0x00,0x90,0x80,0x04,0x30,0x09,0x00,0x0e,0x4c,0x00,0x83,0x80 } },
+{  16, 0xc270, 0, {0x2c,0xc0,0x09,0x30,0x22,0x6e,0x42,0x83,0x80,0x20,0x48,0x08,0x38,0x02,0x38,0x00 } },
+{  16, 0xc280, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0xb7,0x80,0x65,0x20 } },
+{  16, 0xc290, 0, {0x0b,0x78,0x82,0x7a,0x08,0x8c,0xc0,0x25,0xa3,0x4b,0x78,0x02,0x5e,0x04,0x87,0x84 } },
+{  16, 0xc2a0, 0, {0x2d,0x61,0x89,0x78,0x02,0xde,0x04,0x87,0x80,0xe9,0x62,0x08,0x78,0x02,0x08,0x00 } },
+{  16, 0xc2b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xfb,0x00,0x34,0x48 } },
+{  16, 0xc2c0, 0, {0x0f,0x3b,0x03,0x48,0x00,0x93,0x48,0x34,0x50,0x0d,0x00,0x03,0x6c,0x00,0xc3,0x10 } },
+{  16, 0xc2d0, 0, {0x1c,0xc2,0x05,0x30,0x03,0xcc,0x40,0xcb,0x00,0x32,0x40,0x0c,0x20,0x03,0x12,0x02 } },
+{  16, 0xc2e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x20,0xff,0x01,0x03,0x40 } },
+{  16, 0xc2f0, 0, {0x0f,0xf0,0x23,0x1c,0x00,0xff,0x00,0x3b,0x80,0x0f,0xb0,0x23,0x3c,0x02,0xff,0x50 } },
+{  16, 0xc300, 0, {0x3d,0xc4,0x0f,0xf1,0x03,0xec,0x00,0xef,0x00,0xb7,0xc0,0x0f,0xe1,0x03,0xd0,0x06 } },
+{  16, 0xc310, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xec,0x00,0xfb,0x02,0x3e,0xe0 } },
+{  16, 0xc320, 0, {0x0c,0x80,0x03,0x48,0x02,0xc8,0x81,0x32,0x00,0x0f,0x90,0x42,0xec,0xa0,0xfb,0x10 } },
+{  16, 0xc330, 0, {0x3e,0xe0,0x0c,0xb1,0x03,0xec,0x40,0xfb,0x10,0x32,0x40,0x1f,0xf0,0x03,0x2a,0x00 } },
+{  16, 0xc340, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb7,0x24,0x2d,0x80 } },
+{  16, 0xc350, 0, {0x08,0x70,0x42,0xd8,0x10,0x8c,0x02,0x21,0x40,0x0b,0x50,0x02,0xdd,0x00,0xe7,0x20 } },
+{  16, 0xc360, 0, {0x2f,0x40,0x08,0x70,0x02,0xdc,0x05,0xb7,0x00,0x21,0xc0,0x0b,0xf0,0x02,0x12,0x04 } },
+{  16, 0xc370, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x90,0x2f,0x40 } },
+{  16, 0xc380, 0, {0x0a,0x68,0x02,0x7a,0x00,0x97,0x80,0x21,0xe0,0x0b,0x78,0x02,0xde,0x00,0xb7,0x80 } },
+{  16, 0xc390, 0, {0x2d,0xe0,0x08,0x78,0x06,0xde,0x00,0xb7,0xa0,0x21,0x60,0x0b,0x78,0x42,0x30,0x00 } },
+{  16, 0xc3a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0x00,0x2c,0xc0 } },
+{  16, 0xc3b0, 0, {0x0a,0x34,0x02,0xc8,0x00,0x83,0x4a,0x20,0xf8,0x0b,0x31,0x02,0xcc,0x00,0xa3,0x00 } },
+{  16, 0xc3c0, 0, {0x2c,0xc0,0x08,0x30,0x02,0xcc,0x00,0xb3,0x00,0x20,0xb2,0x0b,0x20,0x42,0x12,0x04 } },
+{  16, 0xc3d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xba,0x00,0x3f,0x88 } },
+{  16, 0xc3e0, 0, {0x2e,0xe0,0x43,0x59,0x88,0xde,0x00,0x33,0xb0,0x0f,0x6c,0x03,0xe8,0x00,0xfa,0x00 } },
+{  16, 0xc3f0, 0, {0x3e,0x80,0x2c,0xa0,0x03,0xe8,0x04,0xfa,0x00,0x23,0xb8,0x0f,0xe0,0x8b,0x3a,0x04 } },
+{  16, 0xc400, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x04,0xf8,0x01,0x3e,0x00 } },
+{  16, 0xc410, 0, {0x09,0x82,0x21,0xe0,0x00,0xf8,0x40,0xbe,0x14,0x0f,0x84,0x81,0xe0,0x00,0xe8,0x00 } },
+{  16, 0xc420, 0, {0x3e,0x00,0x1f,0x80,0x03,0xe0,0x00,0xf8,0x00,0xbe,0x00,0x0f,0x88,0x03,0xd2,0x00 } },
+{  16, 0xc430, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xe1,0x00,0x32,0x40 } },
+{  16, 0xc440, 0, {0x0c,0x90,0x43,0xe4,0x20,0xd9,0x00,0x3c,0x44,0x08,0x90,0x03,0x24,0x00,0xf9,0x01 } },
+{  16, 0xc450, 0, {0x3e,0x48,0x0f,0x10,0x43,0x25,0x00,0xc9,0x00,0xb2,0x40,0x0c,0x90,0x03,0x02,0x04 } },
+{  16, 0xc460, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x00,0xa0,0x40 } },
+{  16, 0xc470, 0, {0x08,0x98,0x02,0xe6,0x08,0xa9,0x60,0x2e,0x49,0x08,0x94,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0xc480, 0, {0x2e,0x70,0x0b,0x90,0x02,0x26,0x02,0x89,0x00,0xa0,0x40,0x0a,0x90,0x0a,0x20,0x00 } },
+{  16, 0xc490, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x00,0x22,0x40 } },
+{  16, 0xc4a0, 0, {0x08,0x98,0x04,0xe6,0x00,0x99,0x80,0x2e,0x40,0x0a,0xb1,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0xc4b0, 0, {0x0e,0x40,0x0b,0x90,0x0a,0x04,0x00,0x81,0x01,0x22,0xc0,0x08,0x10,0x02,0x06,0x00 } },
+{  16, 0xc4c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0xb1,0x20,0x22,0x48 } },
+{  16, 0xc4d0, 0, {0x08,0x18,0x06,0xc4,0x00,0xa1,0x00,0x2c,0x48,0x2a,0x30,0x02,0x04,0x80,0xb1,0x22 } },
+{  16, 0xc4e0, 0, {0x2c,0x48,0x0b,0x12,0x02,0x05,0x80,0x81,0x60,0x22,0x50,0x0a,0x14,0x02,0x02,0x01 } },
+{  16, 0xc4f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x50,0x32,0x14 } },
+{  16, 0xc500, 0, {0x0c,0x85,0x03,0xe1,0x40,0xd8,0x50,0x3e,0x14,0x0e,0x80,0x0b,0x21,0x40,0xfa,0x00 } },
+{  16, 0xc510, 0, {0x3e,0x94,0x0f,0x85,0x03,0x20,0x00,0xc0,0x00,0x32,0x00,0x0c,0x80,0x03,0x2e,0x03 } },
+{  16, 0xc520, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x41,0xf9,0x10,0x3d,0x45 } },
+{  16, 0xc530, 0, {0x0f,0xd0,0x03,0xf4,0x00,0xff,0x00,0x3f,0x45,0x0d,0xd0,0x03,0xe4,0x40,0xf9,0x10 } },
+{  16, 0xc540, 0, {0x3f,0x44,0x0f,0x91,0x03,0xe4,0x42,0xf9,0x10,0x3f,0x40,0x0f,0xd4,0x03,0xe6,0x06 } },
+{  16, 0xc550, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe4,0x00,0xf9,0x00,0x3e,0x40 } },
+{  16, 0xc560, 0, {0x0c,0xd0,0x03,0xf4,0x08,0x8d,0x02,0x3f,0x40,0x0f,0xd0,0x03,0xe4,0x00,0xcd,0x00 } },
+{  16, 0xc570, 0, {0x33,0x40,0x0c,0x90,0x03,0x24,0x00,0xf9,0x00,0x32,0x40,0x4c,0x98,0x23,0x06,0x00 } },
+{  16, 0xc580, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0xe8,0x00,0x2e,0x00 } },
+{  16, 0xc590, 0, {0x48,0x80,0x02,0xe8,0x00,0xd0,0x00,0x2e,0x80,0x0b,0x80,0x12,0xe0,0x02,0x88,0x00 } },
+{  16, 0xc5a0, 0, {0xa2,0x00,0x0a,0x80,0x12,0x22,0x00,0xb8,0x81,0x22,0x28,0x08,0xcf,0x02,0x0e,0x04 } },
+{  16, 0xc5b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x2c,0x40 } },
+{  16, 0xc5c0, 0, {0x28,0x10,0x02,0xc4,0x00,0x81,0x00,0x2c,0x40,0x0b,0x10,0x02,0xc4,0x00,0x91,0x00 } },
+{  16, 0xc5d0, 0, {0x26,0x40,0x09,0x10,0x02,0x54,0xa0,0xb5,0x2c,0xa5,0x42,0x08,0x50,0x82,0x02,0x01 } },
+{  16, 0xc5e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0xa9,0x00,0x2e,0x50 } },
+{  16, 0xc5f0, 0, {0x58,0x90,0x02,0xe4,0x80,0x9b,0x00,0x2e,0x45,0x8b,0x92,0x02,0xe4,0x00,0x99,0x00 } },
+{  16, 0xc600, 0, {0x26,0x44,0x0b,0x90,0x02,0x64,0x08,0xb5,0x00,0x25,0x4a,0x08,0x51,0x02,0x06,0x04 } },
+{  16, 0xc610, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x00,0x3e,0x54 } },
+{  16, 0xc620, 0, {0x0c,0x90,0x43,0xc4,0x00,0xc9,0x90,0x3e,0x70,0x0f,0x98,0x03,0xe4,0x00,0xd9,0x00 } },
+{  16, 0xc630, 0, {0x34,0x60,0x4d,0x90,0x0a,0x64,0x00,0xf9,0x00,0x36,0x40,0x2c,0x9e,0x03,0x28,0x04 } },
+{  16, 0xc640, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x00,0x3c,0x40 } },
+{  16, 0xc650, 0, {0x0f,0x9c,0x03,0xe6,0x30,0xf9,0x00,0x3e,0x62,0x0f,0x90,0x03,0xe4,0x00,0xe9,0x00 } },
+{  16, 0xc660, 0, {0x3a,0x40,0x4e,0x90,0x03,0xa4,0x00,0x79,0x0c,0x3a,0x40,0x0f,0x90,0x1b,0xca,0x00 } },
+{  16, 0xc670, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x00,0x3e,0x00 } },
+{  16, 0xc680, 0, {0x0c,0x81,0x13,0xe1,0x08,0xc8,0x48,0x32,0x00,0x3c,0x80,0x03,0xc0,0x00,0xf0,0x10 } },
+{  16, 0xc690, 0, {0x3e,0x06,0x0c,0x80,0x03,0xf0,0x08,0xcc,0x00,0x33,0x04,0x0c,0xc0,0x03,0x0a,0x04 } },
+{  16, 0xc6a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xba,0x00,0x2e,0x80 } },
+{  16, 0xc6b0, 0, {0x08,0xec,0x42,0xfa,0x20,0x8e,0x00,0x23,0xa0,0x08,0xe8,0x42,0xe8,0x00,0xbe,0x80 } },
+{  16, 0xc6c0, 0, {0x2f,0x80,0x08,0xa0,0x02,0xe8,0x00,0xda,0x00,0x22,0x80,0x48,0xe0,0x02,0x0a,0x00 } },
+{  16, 0xc6d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb3,0x00,0x2c,0xc0 } },
+{  16, 0xc6e0, 0, {0x09,0x34,0x82,0xc9,0x00,0x83,0x80,0x20,0xf0,0x08,0x30,0x82,0xcc,0x00,0xb3,0x80 } },
+{  16, 0xc6f0, 0, {0x2c,0xf0,0x08,0xb0,0x02,0xc1,0x20,0x80,0x00,0xa0,0x32,0x08,0x00,0x02,0x0a,0x00 } },
+{  16, 0xc700, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0xc0,0xb7,0x01,0x2f,0xc8 } },
+{  16, 0xc710, 0, {0x89,0x50,0x02,0xd8,0x02,0x87,0xc4,0x21,0xe2,0x48,0x70,0x82,0xdc,0x00,0xb7,0x00 } },
+{  16, 0xc720, 0, {0x2c,0x40,0x08,0x72,0x02,0xce,0x00,0x97,0x08,0x23,0xc0,0x08,0x70,0x02,0x28,0x00 } },
+{  16, 0xc730, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf7,0xe1,0x3d,0xe8 } },
+{  16, 0xc740, 0, {0x2d,0x68,0x03,0xf2,0x00,0xc7,0x80,0xb0,0xe0,0x08,0x68,0x03,0xdf,0x80,0xf6,0x80 } },
+{  16, 0xc750, 0, {0x3d,0xe0,0x8c,0x7e,0x03,0xda,0x00,0xcc,0x80,0x31,0x20,0x0c,0xc8,0x0b,0x2a,0x02 } },
+{  16, 0xc760, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x08,0xfb,0x00,0x3c,0xc0 } },
+{  16, 0xc770, 0, {0x0e,0x80,0x03,0xe0,0x08,0xf9,0x00,0x3e,0x40,0x0f,0xb0,0x02,0xec,0x00,0xfa,0x00 } },
+{  16, 0xc780, 0, {0x3e,0x40,0x2f,0xb0,0x03,0xe4,0x00,0xfb,0x00,0x3c,0xc0,0x2f,0xb0,0x03,0xc2,0x06 } },
+{  16, 0xc790, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xff,0x92,0x7f,0xea } },
+{  16, 0xc7a0, 0, {0x0c,0xf8,0x03,0xfe,0x00,0xcc,0xa0,0x3f,0x20,0x0d,0xf9,0x03,0x3e,0x00,0xcf,0x80 } },
+{  16, 0xc7b0, 0, {0x33,0x60,0x0f,0xf8,0x03,0xf6,0x00,0xef,0x84,0x33,0xe0,0x2c,0xc8,0x03,0x00,0x00 } },
+{  16, 0xc7c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xb7,0x00,0x2f,0xc8 } },
+{  16, 0xc7d0, 0, {0x08,0x54,0x02,0xd8,0x00,0xd6,0x04,0x2d,0x01,0x08,0x69,0x02,0x1c,0x00,0x85,0x00 } },
+{  16, 0xc7e0, 0, {0x21,0x43,0x0b,0x70,0x03,0x9a,0xc0,0x8c,0x00,0xa3,0x02,0x08,0xf1,0x02,0x2a,0x04 } },
+{  16, 0xc7f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x01,0x2d,0xcc } },
+{  16, 0xc800, 0, {0x08,0x70,0x02,0xd4,0x00,0x94,0x28,0x2d,0xc2,0x08,0xc2,0x02,0x5c,0x00,0x86,0x00 } },
+{  16, 0xc810, 0, {0x21,0x80,0x0b,0x71,0x02,0xdc,0x00,0xa7,0x10,0x21,0xc0,0x08,0x48,0x02,0x40,0x00 } },
+{  16, 0xc820, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x08,0xb3,0x00,0x2c,0xf0 } },
+{  16, 0xc830, 0, {0x08,0x05,0x02,0xc0,0x20,0x90,0x80,0x2e,0x00,0x08,0x00,0x82,0x4c,0x02,0x80,0x00 } },
+{  16, 0xc840, 0, {0xa0,0x61,0x0b,0x30,0x02,0xa0,0x00,0x80,0x00,0xa0,0x30,0x88,0xb1,0x0a,0x48,0x04 } },
+{  16, 0xc850, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xff,0x00,0x2d,0xc8 } },
+{  16, 0xc860, 0, {0x0c,0x3d,0x03,0xe4,0x00,0xdb,0x02,0x3e,0xf0,0x2c,0x90,0x4b,0x7c,0x00,0xc1,0x00 } },
+{  16, 0xc870, 0, {0x32,0x20,0x4f,0xf0,0x13,0xe0,0x00,0xe8,0x01,0x32,0x00,0x8c,0xac,0x03,0x6a,0x04 } },
+{  16, 0xc880, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x04,0x3e,0xc2 } },
+{  16, 0xc890, 0, {0x4f,0xb0,0x03,0xe0,0x04,0xfa,0x40,0x3e,0xc2,0x4e,0x98,0x23,0xac,0x10,0xf8,0x00 } },
+{  16, 0xc8a0, 0, {0x3e,0x50,0x07,0xb0,0x13,0xac,0x00,0xfb,0x00,0x3e,0xc2,0x0f,0x92,0x03,0xa0,0x00 } },
+{  16, 0xc8b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xcf,0x00,0x3f,0xc0 } },
+{  16, 0xc8c0, 0, {0x0c,0xc8,0x23,0x36,0x82,0xcf,0x80,0x3f,0x80,0x0c,0xe0,0x03,0xec,0x00,0xf9,0x20 } },
+{  16, 0xc8d0, 0, {0x33,0xc0,0x0e,0xf0,0x03,0xf8,0x10,0xdc,0x00,0x33,0x00,0x4c,0xe8,0x21,0x00,0x44 } },
+{  16, 0xc8e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x00,0xab,0x00,0x2e,0xc0 } },
+{  16, 0xc8f0, 0, {0x4a,0x8d,0x42,0x21,0x00,0x8b,0x42,0x2e,0xd2,0x08,0xb0,0x03,0xec,0x00,0xb8,0x88 } },
+{  16, 0xc900, 0, {0x34,0x62,0x0d,0xb0,0x02,0xe4,0x00,0x8b,0x00,0x22,0xc0,0x08,0x90,0x0a,0x20,0x40 } },
+{  16, 0xc910, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x00,0x2e,0xc0 } },
+{  16, 0xc920, 0, {0x08,0xa0,0x02,0x0d,0x00,0x89,0x10,0x2e,0x08,0x28,0x92,0x02,0xec,0x04,0xbb,0x00 } },
+{  16, 0xc930, 0, {0x22,0xa0,0x08,0xb0,0x02,0x64,0x02,0xb3,0x02,0x20,0xc0,0x08,0xa2,0x02,0xa0,0x00 } },
+{  16, 0xc940, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xa3,0x00,0x2e,0xc0 } },
+{  16, 0xc950, 0, {0x0a,0x90,0x22,0x0c,0x10,0x80,0x00,0x2c,0x00,0x18,0x02,0x82,0xcc,0x00,0xb0,0x00 } },
+{  16, 0xc960, 0, {0x26,0x40,0x09,0x30,0x02,0xc8,0x20,0x80,0x00,0x20,0x00,0x08,0x10,0x06,0x82,0x01 } },
+{  16, 0xc970, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xcb,0x00,0x2e,0xc0 } },
+{  16, 0xc980, 0, {0x0c,0xa1,0x02,0x24,0x00,0x88,0x00,0x3c,0x00,0x0c,0x80,0x03,0xec,0x00,0xfb,0x00 } },
+{  16, 0xc990, 0, {0x32,0x80,0x0e,0xb0,0x03,0xcc,0x80,0xdb,0x00,0x32,0xc0,0x0c,0xa0,0x03,0x80,0x03 } },
+{  16, 0xc9a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x3f,0xc0 } },
+{  16, 0xc9b0, 0, {0x4f,0xc2,0x13,0xd4,0x10,0xfc,0x00,0x3f,0x00,0x0f,0x00,0x03,0xbc,0x00,0xfc,0x00 } },
+{  16, 0xc9c0, 0, {0x3f,0x40,0x0f,0xf0,0x23,0xe0,0x12,0xfc,0x01,0xbf,0x00,0x0f,0xd0,0x03,0x68,0x02 } },
+{  16, 0xc9d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x00,0xc7,0x80,0x33,0xc0 } },
+{  16, 0xc9e0, 0, {0x8b,0xb4,0x03,0xb0,0xc0,0xcf,0x2e,0x1f,0x0c,0x4f,0xc3,0x03,0x30,0x80,0xff,0x01 } },
+{  16, 0xc9f0, 0, {0x3f,0x08,0x0f,0xf0,0x00,0x7c,0x00,0xff,0x21,0x33,0xe4,0x0c,0xe0,0x03,0x30,0x00 } },
+{  16, 0xca00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xee,0x00,0x8b,0x82,0x23,0xf0 } },
+{  16, 0xca10, 0, {0x0b,0xb5,0x12,0x0d,0x88,0x88,0xc0,0x0e,0x98,0x0b,0x86,0x02,0x21,0x00,0xbb,0xc0 } },
+{  16, 0xca20, 0, {0x2e,0xe4,0x4b,0xf7,0x83,0x2f,0x44,0xbf,0x90,0x22,0xc8,0x48,0xa6,0x82,0x20,0x04 } },
+{  16, 0xca30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x09,0x8a,0x00,0x20,0x50 } },
+{  16, 0xca40, 0, {0x4b,0xb2,0x0a,0x80,0xcc,0x83,0x01,0x0c,0x8c,0x0b,0x23,0x0a,0x04,0x60,0xb3,0x14 } },
+{  16, 0xca50, 0, {0x24,0x40,0x4b,0x30,0x02,0xcc,0x10,0xb3,0x00,0x20,0xc8,0xe9,0x11,0x06,0x62,0x01 } },
+{  16, 0xca60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x01,0x8a,0x80,0xa2,0x44 } },
+{  16, 0xca70, 0, {0x0b,0xb0,0x02,0xa1,0x04,0x88,0x40,0x2e,0xa0,0x0b,0x20,0x02,0x28,0x20,0xbb,0x40 } },
+{  16, 0xca80, 0, {0x2e,0x40,0x0b,0xb0,0x02,0x2c,0x08,0xbb,0x00,0x22,0xc0,0x09,0xb0,0x02,0x70,0x04 } },
+{  16, 0xca90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xc3,0x83,0x32,0xe0 } },
+{  16, 0xcaa0, 0, {0x8f,0x00,0x03,0xa0,0x02,0xcb,0xc4,0x3e,0x28,0x07,0x8b,0x03,0x21,0x00,0xf9,0xc0 } },
+{  16, 0xcab0, 0, {0x3e,0x10,0x0f,0xb0,0x03,0xec,0x00,0x7b,0x00,0x32,0xc0,0x0d,0xa0,0x03,0x50,0x04 } },
+{  16, 0xcac0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x9c,0x02,0xff,0x00,0x3f,0xe0 } },
+{  16, 0xcad0, 0, {0x0f,0xf4,0x43,0x5e,0x80,0xfc,0x94,0x3f,0x00,0x0f,0xc0,0x2b,0xf2,0x50,0xfd,0x21 } },
+{  16, 0xcae0, 0, {0x7e,0x84,0x8f,0xf0,0x03,0x6c,0x0c,0xff,0x00,0x3f,0xc0,0x0e,0x62,0x03,0xb8,0x00 } },
+{  16, 0xcaf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xeb,0x00,0x32,0x40 } },
+{  16, 0xcb00, 0, {0x2c,0x80,0x03,0x69,0x00,0xcb,0x30,0xb2,0x00,0x4f,0xb3,0x43,0xe5,0x00,0xcb,0x40 } },
+{  16, 0xcb10, 0, {0x72,0x18,0x2c,0xb0,0x03,0xec,0x28,0xc3,0x21,0x3a,0xc1,0x0f,0x94,0x03,0x10,0x04 } },
+{  16, 0xcb20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3c,0x00,0x8b,0x20,0x22,0x50 } },
+{  16, 0xcb30, 0, {0x08,0xb0,0x02,0x28,0x00,0x88,0xc0,0x2a,0x00,0x8b,0xb4,0x02,0xe8,0x00,0xdb,0x00 } },
+{  16, 0xcb40, 0, {0x62,0x30,0x08,0xf0,0x02,0xfc,0x00,0x8f,0x80,0x22,0xc0,0x0b,0x95,0x47,0x32,0x00 } },
+{  16, 0xcb50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb1,0x00,0x20,0xc2 } },
+{  16, 0xcb60, 0, {0x48,0x30,0x02,0x49,0x80,0x83,0x42,0x60,0x12,0x0b,0x30,0x02,0xc8,0x00,0x82,0x02 } },
+{  16, 0xcb70, 0, {0x2c,0x30,0x09,0xb0,0x02,0xcf,0x01,0x83,0x50,0x2a,0xc0,0x0b,0x20,0x02,0xb8,0x00 } },
+{  16, 0xcb80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0x9d,0x80,0xa0,0xe0 } },
+{  16, 0xcb90, 0, {0x08,0x79,0x22,0x5e,0x60,0x87,0x90,0x29,0xa0,0x0b,0x78,0x02,0xc6,0x00,0x92,0x81 } },
+{  16, 0xcba0, 0, {0x05,0xe0,0x09,0x78,0x02,0xde,0x40,0x87,0x80,0x21,0xe0,0x0b,0x29,0x02,0x08,0x00 } },
+{  16, 0xcbb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x40,0xf2,0x00,0x30,0xc0 } },
+{  16, 0xcbc0, 0, {0x08,0x3a,0x03,0x44,0x04,0xc3,0x14,0x30,0xc0,0x0f,0x22,0x03,0xcc,0x80,0xc2,0x00 } },
+{  16, 0xcbd0, 0, {0xa4,0xd2,0x0d,0x30,0x13,0xcc,0x20,0xc3,0x00,0x38,0xc4,0x4f,0x04,0x43,0x12,0x02 } },
+{  16, 0xcbe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x9c,0x00,0xee,0x00,0x3f,0xe0 } },
+{  16, 0xcbf0, 0, {0x0f,0x70,0x03,0xb4,0x02,0xf4,0x10,0x3f,0xc0,0x8f,0xa0,0x03,0xfc,0x00,0x7e,0x00 } },
+{  16, 0xcc00, 0, {0x3b,0xc0,0x0e,0xf0,0x83,0xec,0x00,0xf7,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xd0,0x06 } },
+{  16, 0xcc10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xfc,0x00,0xf9,0x00,0x3e,0xc0 } },
+{  16, 0xcc20, 0, {0x0f,0xa0,0x03,0xaa,0x12,0xcb,0x01,0x32,0x80,0x0f,0xb0,0x13,0x28,0x14,0xf9,0x80 } },
+{  16, 0xcc30, 0, {0x3a,0x40,0x03,0xb4,0x03,0xec,0x42,0xcb,0x18,0x3e,0xc0,0x0f,0xb0,0x03,0x2a,0x00 } },
+{  16, 0xcc40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9d,0x00,0xb5,0x00,0x2d,0xc4 } },
+{  16, 0xcc50, 0, {0x0b,0x70,0x4b,0x7c,0x00,0x84,0x00,0x21,0x80,0x0b,0x70,0x02,0x94,0x10,0xb2,0x00 } },
+{  16, 0xcc60, 0, {0x29,0xc0,0x0b,0x72,0x82,0xdc,0x00,0x87,0x20,0x2d,0xc1,0x0e,0x70,0x02,0x12,0x04 } },
+{  16, 0xcc70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x80,0x2d,0xe0 } },
+{  16, 0xcc80, 0, {0x0b,0x68,0x02,0x9e,0x00,0x83,0x80,0x21,0xe0,0x5b,0x38,0x02,0x1e,0x00,0xb4,0xc0 } },
+{  16, 0xcc90, 0, {0x25,0xe0,0x09,0x78,0x32,0xce,0x00,0x97,0x80,0x2d,0xe0,0x0b,0x5c,0x4e,0x30,0x00 } },
+{  16, 0xcca0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0x44,0x2c,0xc0 } },
+{  16, 0xccb0, 0, {0x0b,0x3c,0x02,0xcc,0x40,0x93,0x08,0x20,0xe0,0x0b,0x30,0x02,0x8c,0x10,0xb3,0xc0 } },
+{  16, 0xccc0, 0, {0x28,0xd8,0x1b,0x30,0x02,0xcc,0x08,0x93,0x01,0x6c,0xc0,0x0a,0xb8,0x82,0x12,0x04 } },
+{  16, 0xccd0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xf6,0x10,0x3e,0x80 } },
+{  16, 0xcce0, 0, {0x4b,0xed,0x83,0xb8,0x00,0xce,0xe4,0xb3,0xa3,0x0f,0xe0,0x03,0x38,0x00,0xfe,0x00 } },
+{  16, 0xccf0, 0, {0x3b,0x80,0x0d,0xa0,0x02,0xe8,0x00,0xda,0x00,0x3e,0x80,0x0f,0xe8,0x02,0x3a,0x04 } },
+{  16, 0xcd00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x10,0xf8,0x40,0x3e,0x00 } },
+{  16, 0xcd10, 0, {0x0f,0x80,0x13,0x60,0x00,0xe0,0x00,0x3e,0x00,0x43,0x08,0x03,0xe0,0x00,0xf8,0x08 } },
+{  16, 0xcd20, 0, {0x3a,0x00,0x0f,0x80,0x03,0xe0,0x00,0xe8,0x40,0x3e,0x00,0x0e,0x80,0x23,0xd2,0x00 } },
+{  16, 0xcd30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xc4,0x00,0xd9,0xc0,0xbe,0x40 } },
+{  16, 0xcd40, 0, {0x0f,0x90,0x03,0xe6,0x00,0xf9,0x00,0x32,0x40,0x01,0x9a,0x03,0x24,0x00,0xf9,0x00 } },
+{  16, 0xcd50, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc4,0x40,0x09,0x10,0x0e,0x40,0x0f,0x9a,0x03,0x02,0x04 } },
+{  16, 0xcd60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x04,0x89,0x04,0xa2,0x60 } },
+{  16, 0xcd70, 0, {0x8b,0x9d,0x80,0xa6,0x00,0xb9,0x80,0x22,0x40,0x48,0x98,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0xcd80, 0, {0x2e,0x40,0x8b,0x90,0x02,0xe4,0x94,0x89,0x60,0x2e,0x40,0x0b,0x94,0x0b,0x20,0x00 } },
+{  16, 0xcd90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x99,0x08,0xae,0x48 } },
+{  16, 0xcda0, 0, {0x4b,0x10,0x02,0xe5,0x81,0xb9,0x10,0x20,0x44,0x1b,0x94,0x02,0x24,0x10,0xb9,0x00 } },
+{  16, 0xcdb0, 0, {0x6e,0x60,0x0b,0x90,0x02,0xe4,0x00,0x89,0x00,0x2e,0x40,0x0b,0x94,0x02,0x06,0x00 } },
+{  16, 0xcdc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0x89,0x00,0xa0,0x68 } },
+{  16, 0xcdd0, 0, {0x0b,0x12,0x02,0x84,0x89,0xb1,0x20,0x20,0x48,0x1a,0x12,0x12,0x04,0x80,0xb1,0x22 } },
+{  16, 0xcde0, 0, {0x0c,0x48,0x0b,0x12,0x02,0xc4,0x81,0xa1,0x20,0x2c,0x40,0x0b,0x12,0x02,0x02,0x01 } },
+{  16, 0xcdf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xd8,0x00,0xbe,0x00 } },
+{  16, 0xce00, 0, {0x0f,0x05,0x0b,0xe1,0x40,0xf8,0x00,0x32,0x14,0x0f,0x85,0x03,0x21,0x40,0xf8,0x00 } },
+{  16, 0xce10, 0, {0x2e,0x80,0x0f,0x85,0x13,0xe0,0x02,0xc8,0x00,0x3e,0x14,0x0f,0x05,0x01,0x2e,0x03 } },
+{  16, 0xce20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x40,0xfd,0x00,0xbf,0x44 } },
+{  16, 0xce30, 0, {0x0f,0xd1,0x03,0xf4,0x40,0x7d,0x10,0xbf,0x44,0x45,0xf1,0x2b,0xf4,0x40,0xfd,0x10 } },
+{  16, 0xce40, 0, {0x3f,0x44,0x0f,0x91,0x03,0xe4,0x40,0xd9,0x10,0x3e,0x40,0x0f,0xd1,0x03,0xa6,0x06 } },
+{  16, 0xce50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x00,0xfd,0x00,0x1f,0x62 } },
+{  16, 0xce60, 0, {0x0f,0xd8,0x82,0x36,0x00,0xbd,0xa0,0x3b,0x68,0x0c,0xdc,0x83,0x26,0xc8,0xd9,0xa0 } },
+{  16, 0xce70, 0, {0x33,0x60,0x0d,0x99,0x83,0x56,0x20,0xd5,0xa8,0x2e,0x44,0x0c,0xd8,0x83,0x86,0x04 } },
+{  16, 0xce80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x48,0xb8,0x00,0x2e,0x00 } },
+{  16, 0xce90, 0, {0x0b,0x0a,0x82,0x22,0x20,0xb8,0x50,0x22,0xba,0x08,0x8a,0x22,0x22,0x80,0x88,0x00 } },
+{  16, 0xcea0, 0, {0x22,0x01,0x08,0x0c,0x02,0x20,0x00,0x88,0x00,0x2e,0x28,0x88,0x88,0x02,0xce,0x04 } },
+{  16, 0xceb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x2c,0x40 } },
+{  16, 0xcec0, 0, {0x1b,0x10,0x0a,0x84,0x40,0xb1,0x00,0x28,0x58,0x0a,0x32,0x02,0x05,0x00,0x99,0x40 } },
+{  16, 0xced0, 0, {0x20,0x65,0x09,0x10,0x42,0xc4,0x00,0x91,0x00,0x2c,0x40,0x0a,0x30,0x82,0xc2,0x01 } },
+{  16, 0xcee0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0xb9,0x00,0x2e,0x40 } },
+{  16, 0xcef0, 0, {0x1b,0x90,0x02,0xa5,0x80,0xb9,0x10,0x22,0x48,0x08,0x10,0x42,0x04,0x10,0x09,0x00 } },
+{  16, 0xcf00, 0, {0x22,0x40,0x08,0x90,0x02,0xe4,0x00,0x9b,0x00,0x2c,0x40,0x0a,0x94,0x22,0xc6,0x04 } },
+{  16, 0xcf10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x20,0x3e,0x40 } },
+{  16, 0xcf20, 0, {0x0f,0x90,0x13,0xa7,0x10,0xf9,0x60,0xba,0x50,0x2e,0x9c,0x0a,0x25,0x84,0xd1,0xf0 } },
+{  16, 0xcf30, 0, {0xb2,0x60,0x0d,0x90,0x03,0xe4,0x00,0xd9,0x00,0x3e,0x40,0x0e,0x90,0x03,0xa8,0x00 } },
+{  16, 0xcf40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x0c,0xf9,0x90,0x3e,0x6a } },
+{  16, 0xcf50, 0, {0x8f,0x90,0x23,0x66,0x00,0xf1,0x08,0x3c,0x40,0x0f,0x9c,0x43,0xe4,0x40,0xf9,0x80 } },
+{  16, 0xcf60, 0, {0x3a,0x44,0x0f,0x90,0x03,0x24,0x04,0xe9,0x02,0x3e,0x40,0x2d,0x91,0x13,0xca,0x00 } },
+{  16, 0xcf70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xe8,0x20,0x3e,0x01 } },
+{  16, 0xcf80, 0, {0x0c,0x00,0x03,0xa1,0x20,0xe8,0x50,0x32,0x10,0x2c,0x8c,0x03,0x21,0x00,0xe8,0x00 } },
+{  16, 0xcf90, 0, {0x32,0x02,0x0f,0x00,0x13,0x20,0x88,0xc8,0x08,0x32,0x00,0x0f,0x8c,0x03,0xca,0x00 } },
+{  16, 0xcfa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x20,0x8e,0xe3,0x2f,0x90 } },
+{  16, 0xcfb0, 0, {0x0a,0xe0,0x06,0x3b,0x00,0xee,0x04,0x23,0x90,0x08,0xe0,0x02,0x28,0x08,0x8a,0x02 } },
+{  16, 0xcfc0, 0, {0x75,0x90,0x8b,0xa0,0x41,0x58,0x90,0x8e,0x80,0x2a,0x81,0x0b,0xe0,0x03,0x8a,0x10 } },
+{  16, 0xcfd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4e,0x00,0xa3,0x00,0x6c,0x60 } },
+{  16, 0xcfe0, 0, {0x08,0x38,0x1a,0x8e,0x40,0xa0,0x80,0x20,0xcc,0x09,0x30,0x02,0x0c,0x05,0xa3,0x04 } },
+{  16, 0xcff0, 0, {0x28,0xc4,0x0b,0x30,0x02,0x0d,0x01,0x83,0xc0,0x20,0xc0,0x0b,0x30,0x02,0xca,0x00 } },
+{  16, 0xd000, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x08,0x87,0x00,0x2d,0x62 } },
+{  16, 0xd010, 0, {0x0b,0x70,0x92,0x1c,0x08,0xa0,0x00,0x61,0xc0,0x09,0x60,0x06,0x1c,0x80,0xa7,0x00 } },
+{  16, 0xd020, 0, {0x21,0xc0,0x0b,0x72,0x02,0x58,0x01,0x87,0x88,0x29,0xc0,0x0b,0x60,0x12,0xa8,0x00 } },
+{  16, 0xd030, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xe6,0x80,0x3d,0x60 } },
+{  16, 0xd040, 0, {0x0c,0x78,0x42,0x96,0x00,0xe4,0x80,0xa3,0x60,0x0d,0x78,0x03,0x3f,0x00,0xe3,0x80 } },
+{  16, 0xd050, 0, {0x21,0xe0,0x0f,0x7b,0x03,0x16,0x08,0xc7,0x80,0x31,0xe2,0x4f,0x78,0x43,0xea,0x02 } },
+{  16, 0xd060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0x8c,0x01,0xf8,0x00,0x3c,0x40 } },
+{  16, 0xd070, 0, {0x0e,0xb0,0x02,0xec,0x00,0xf8,0x01,0x3e,0x40,0x4e,0x30,0x33,0xed,0x20,0xdb,0x01 } },
+{  16, 0xd080, 0, {0xbe,0xc0,0x0f,0xb4,0x03,0xec,0x00,0xfb,0x00,0x3e,0xd8,0x0f,0xa0,0x03,0xc2,0x06 } },
+{  16, 0xd090, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xc7,0x84,0x23,0x60 } },
+{  16, 0xd0a0, 0, {0x0c,0x78,0x0b,0xbe,0x00,0xfd,0x80,0x3f,0xe0,0x0f,0xeb,0x03,0x3e,0x00,0xcf,0x80 } },
+{  16, 0xd0b0, 0, {0x3b,0x25,0x0c,0xf8,0x83,0x7e,0x40,0xcd,0x80,0x33,0xe2,0x0b,0xf9,0x03,0x00,0x00 } },
+{  16, 0xd0c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x02,0x87,0x00,0x15,0x48 } },
+{  16, 0xd0d0, 0, {0x08,0x70,0x02,0x14,0x20,0xb6,0x00,0x35,0x9a,0x49,0xc8,0x03,0x9c,0x84,0xa7,0x00 } },
+{  16, 0xd0e0, 0, {0x39,0xd0,0x0a,0x70,0x02,0x1a,0x08,0xa4,0x00,0x21,0xc0,0x09,0x61,0x42,0x2a,0x04 } },
+{  16, 0xd0f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x87,0x00,0x21,0x40 } },
+{  16, 0xd100, 0, {0x08,0x71,0x02,0x94,0x00,0xb5,0x00,0x2d,0x40,0x0b,0xf1,0x22,0x5c,0x02,0x07,0x08 } },
+{  16, 0xd110, 0, {0x2c,0x50,0x08,0x70,0x02,0x50,0x00,0x87,0x00,0x2d,0xc4,0x0b,0x50,0x42,0x00,0x00 } },
+{  16, 0xd120, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0x83,0x02,0x24,0x40 } },
+{  16, 0xd130, 0, {0x18,0x3d,0x0a,0x01,0x00,0xb0,0x58,0x24,0x20,0x09,0x30,0x02,0x8f,0x40,0x83,0xe0 } },
+{  16, 0xd140, 0, {0x2c,0xc1,0x0a,0x30,0x42,0x08,0x00,0xb3,0x01,0x6c,0xc0,0x09,0x08,0x16,0x08,0x04 } },
+{  16, 0xd150, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0x8c,0x00,0x8b,0x00,0x32,0x40 } },
+{  16, 0xd160, 0, {0x0c,0x25,0x03,0xa8,0x48,0xf8,0x81,0x3e,0x80,0x0f,0x80,0x63,0x7c,0x00,0xcb,0x80 } },
+{  16, 0xd170, 0, {0x3a,0xc0,0x0c,0xf0,0x03,0x6c,0x00,0xca,0x02,0xbf,0xc0,0x0f,0x98,0x8b,0x2a,0x04 } },
+{  16, 0xd180, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xf9,0x00,0x3e,0x50 } },
+{  16, 0xd190, 0, {0x2f,0xa4,0x0b,0xc8,0x00,0xf0,0x40,0x3e,0xd0,0x0f,0xa0,0x33,0xec,0x20,0xfb,0x04 } },
+{  16, 0xd1a0, 0, {0x7a,0xe0,0x0f,0xb0,0x03,0xed,0x08,0xe9,0x03,0x32,0xc0,0x0d,0x90,0x03,0xe0,0x00 } },
+{  16, 0xd1b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xec,0x40,0xee,0x00,0x3e,0xc0 } },
+{  16, 0xd1c0, 0, {0x0c,0xda,0x03,0x70,0x04,0xcc,0x02,0xb1,0xa0,0x0e,0xf0,0x23,0xec,0x00,0xff,0x00 } },
+{  16, 0xd1d0, 0, {0x37,0x20,0xcd,0xb0,0x73,0xec,0x88,0xfb,0x80,0x3f,0xc0,0x0f,0x30,0x03,0x00,0x44 } },
+{  16, 0xd1e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6e,0x00,0x88,0x80,0x2c,0xe1 } },
+{  16, 0xd1f0, 0, {0x08,0x94,0x0a,0xa9,0x02,0x88,0x40,0x22,0xd0,0x08,0xb9,0x42,0xec,0x04,0xbb,0x00 } },
+{  16, 0xd200, 0, {0x2c,0xd4,0x0d,0xb0,0x02,0xed,0x20,0xbb,0xd0,0x2e,0xc0,0x0b,0xb0,0x02,0xa0,0x40 } },
+{  16, 0xd210, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x24,0x00,0xab,0x80,0x2e,0xf0 } },
+{  16, 0xd220, 0, {0x29,0xa0,0x82,0x6d,0x00,0x88,0x08,0x22,0x04,0x08,0x90,0x42,0xec,0x00,0xbb,0x00 } },
+{  16, 0xd230, 0, {0x2a,0x81,0x08,0xb0,0x02,0xe4,0x09,0xba,0x04,0x2e,0xc1,0x4b,0x98,0x82,0x20,0x00 } },
+{  16, 0xd240, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x83,0x00,0x2c,0xc0 } },
+{  16, 0xd250, 0, {0x0a,0x21,0x02,0x84,0x10,0x82,0x00,0xe0,0x00,0x18,0x0a,0x12,0xcc,0x00,0xb3,0x00 } },
+{  16, 0xd260, 0, {0x0c,0xc0,0x09,0x30,0x02,0xcc,0x90,0xb0,0x00,0x2c,0xc0,0x0b,0x10,0x02,0x82,0x01 } },
+{  16, 0xd270, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x64,0x00,0xeb,0x00,0x3e,0x00 } },
+{  16, 0xd280, 0, {0x2c,0xb4,0x03,0x64,0x08,0x88,0x00,0xb2,0x00,0x0c,0xb2,0x43,0xfc,0x00,0xfb,0x00 } },
+{  16, 0xd290, 0, {0x56,0x00,0x0c,0xf0,0x01,0xe4,0x00,0xfb,0x00,0x3f,0xc0,0x0f,0x80,0x0b,0x00,0x03 } },
+{  16, 0xd2a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf4,0x00,0xff,0x00,0x3f,0x40 } },
+{  16, 0xd2b0, 0, {0x2d,0xf0,0x61,0xf0,0x00,0xf4,0x00,0x27,0x01,0x0d,0xb1,0x11,0xfc,0x00,0xff,0x02 } },
+{  16, 0xd2c0, 0, {0x07,0xc0,0x0f,0xf0,0x03,0xec,0x40,0xff,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0x68,0x06 } },
+{  16, 0xd2d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf6,0x00,0xef,0x90,0x3d,0x4c } },
+{  16, 0xd2e0, 0, {0x2c,0xc0,0x13,0xf4,0x08,0xfd,0x20,0x37,0x4c,0x8e,0x82,0x83,0x74,0x84,0xdc,0xc2 } },
+{  16, 0xd2f0, 0, {0x3f,0xd8,0x0d,0xf2,0x03,0xec,0xc0,0xff,0x81,0x3f,0x00,0x0c,0xf8,0x03,0xf0,0x00 } },
+{  16, 0xd300, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe6,0x00,0x8b,0x24,0x2e,0x5c } },
+{  16, 0xd310, 0, {0x08,0x8d,0x02,0xff,0x48,0xb9,0x90,0x2f,0x54,0x0b,0x84,0x82,0x3e,0x40,0xa0,0x80 } },
+{  16, 0xd320, 0, {0x2e,0xc4,0x0a,0xfc,0x42,0xed,0x80,0xb9,0x80,0x2e,0x60,0x0a,0x98,0x12,0xe0,0x04 } },
+{  16, 0xd330, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xe4,0x01,0xa3,0x00,0x28,0x48 } },
+{  16, 0xd340, 0, {0x0a,0x00,0x42,0xc4,0x00,0xb1,0x00,0x2c,0x49,0x0b,0x0a,0x42,0x04,0xa2,0x91,0x21 } },
+{  16, 0xd350, 0, {0x2c,0xc9,0x08,0x31,0x02,0x8c,0xc1,0xa3,0x00,0x2c,0x40,0x08,0x18,0x02,0xa2,0x01 } },
+{  16, 0xd360, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa0,0x20,0x8b,0x82,0x2e,0x44 } },
+{  16, 0xd370, 0, {0x58,0x80,0x02,0xe4,0x00,0xbb,0x10,0x2e,0x40,0x0b,0xa1,0x12,0x0c,0x01,0x89,0x10 } },
+{  16, 0xd380, 0, {0x2e,0xc0,0x0a,0xb0,0x02,0xec,0x01,0xb8,0x80,0x2e,0xe2,0x0a,0xa1,0x02,0xf0,0x04 } },
+{  16, 0xd390, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xeb,0x40,0xeb,0x40,0x3e,0x60 } },
+{  16, 0xd3a0, 0, {0x0e,0x87,0x33,0xe4,0x00,0xb9,0xa1,0x36,0xc0,0x0e,0xa8,0x0b,0x26,0x00,0xda,0xc0 } },
+{  16, 0xd3b0, 0, {0x3e,0xc0,0x8d,0xb0,0x03,0xec,0x00,0xfb,0x85,0x3e,0xe1,0x08,0xb8,0x03,0x90,0x05 } },
+{  16, 0xd3c0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x00,0xff,0x02,0x2f,0x60 } },
+{  16, 0xd3d0, 0, {0x03,0xe8,0x83,0xfc,0x10,0xfd,0x80,0x1f,0x40,0x1f,0xd0,0x13,0xbe,0x40,0xee,0x04 } },
+{  16, 0xd3e0, 0, {0x3f,0xc0,0x0f,0xf0,0x43,0xfc,0x08,0xfd,0x00,0x3c,0xc0,0x0f,0xd0,0x11,0xf8,0x00 } },
+{  16, 0xd3f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa4,0x00,0xdb,0x00,0xb2,0x40 } },
+{  16, 0xd400, 0, {0x0e,0x94,0x03,0x24,0x00,0xd9,0x00,0xba,0xc0,0x0c,0x20,0x03,0xe4,0x90,0xfb,0x00 } },
+{  16, 0xd410, 0, {0x3a,0xc0,0x0c,0xb0,0x03,0xec,0x01,0xfa,0x00,0x3e,0xd0,0x2c,0x98,0x03,0x90,0x04 } },
+{  16, 0xd420, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x03,0x00,0x8b,0x00,0x22,0x48 } },
+{  16, 0xd430, 0, {0x08,0x84,0x22,0x2c,0x00,0xb9,0x00,0x22,0xc0,0x08,0xa0,0x02,0xed,0x00,0x8b,0xa0 } },
+{  16, 0xd440, 0, {0x21,0xc0,0x08,0xf0,0x02,0xfc,0x00,0xb9,0x80,0x2e,0xc0,0x08,0xa0,0x02,0x32,0x00 } },
+{  16, 0xd450, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x45,0x20,0x93,0x00,0x22,0xf8 } },
+{  16, 0xd460, 0, {0x0b,0x30,0x0a,0x84,0x40,0xb2,0x00,0x20,0x40,0x08,0x10,0x02,0xc4,0x00,0x80,0x80 } },
+{  16, 0xd470, 0, {0x28,0xc0,0x28,0x39,0x02,0x4c,0x00,0xb1,0x00,0x2c,0xc0,0x08,0x30,0x02,0xb8,0x00 } },
+{  16, 0xd480, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x36,0x00,0x9f,0x80,0x21,0x60 } },
+{  16, 0xd490, 0, {0x09,0x38,0x02,0x9e,0x00,0xb2,0xc0,0x20,0x60,0x48,0x48,0x12,0xd6,0xc6,0x86,0xd0 } },
+{  16, 0xd4a0, 0, {0x21,0xe0,0x08,0x78,0x00,0xde,0x80,0xb7,0x82,0x2d,0xe0,0x08,0xf8,0x02,0x08,0x00 } },
+{  16, 0xd4b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x20,0xd3,0x10,0x30,0xc8 } },
+{  16, 0xd4c0, 0, {0x0f,0x30,0x03,0x84,0x00,0xf1,0x00,0x30,0x40,0x24,0x19,0x03,0xe4,0xc0,0xe0,0x40 } },
+{  16, 0xd4d0, 0, {0x3a,0xc0,0x0c,0x32,0x03,0xce,0x80,0xb1,0x28,0x3c,0xc0,0x0c,0x30,0x13,0x92,0x02 } },
+{  16, 0xd4e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0x9c,0x00,0xe6,0x00,0x7f,0xc0 } },
+{  16, 0xd4f0, 0, {0x0e,0xf0,0x23,0x74,0x40,0xff,0x10,0x3f,0x40,0x4f,0xd0,0x03,0xfc,0xd2,0xce,0x04 } },
+{  16, 0xd500, 0, {0x3f,0xc0,0x0f,0xf4,0x03,0xfc,0x00,0xfe,0x00,0x3f,0xc0,0x0f,0x71,0x03,0xd0,0x12 } },
+{  16, 0xd510, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xee,0x00,0xcb,0x00,0x16,0xc0 } },
+{  16, 0xd520, 0, {0x0d,0x80,0x03,0x27,0x20,0xcb,0x00,0x3e,0xc2,0x0a,0xb0,0x53,0xe4,0x28,0xc1,0x81 } },
+{  16, 0xd530, 0, {0x32,0xc1,0x0e,0xb9,0x03,0x2c,0x00,0xf1,0x80,0x35,0xe0,0x0c,0xb8,0x03,0x2a,0x04 } },
+{  16, 0xd540, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x02,0x87,0x10,0x2d,0x40 } },
+{  16, 0xd550, 0, {0x08,0x70,0x03,0x5c,0x00,0xa7,0x00,0x2d,0x40,0x28,0x70,0x02,0xd4,0x04,0x87,0x04 } },
+{  16, 0xd560, 0, {0xa1,0xd0,0x0b,0x72,0x02,0x1d,0x00,0xf7,0x00,0x21,0xc0,0x0d,0x50,0x02,0x12,0x04 } },
+{  16, 0xd570, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0x85,0x80,0x25,0xe0 } },
+{  16, 0xd580, 0, {0x09,0x78,0x02,0x37,0x03,0x87,0x80,0x2f,0xe0,0x08,0x78,0x12,0xc6,0x10,0x8d,0x80 } },
+{  16, 0xd590, 0, {0x25,0xe8,0x0b,0x38,0x02,0x1e,0x80,0xbc,0x84,0x25,0xe0,0x08,0x58,0x02,0x70,0x00 } },
+{  16, 0xd5a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcd,0x80,0x83,0x88,0x2c,0xc0 } },
+{  16, 0xd5b0, 0, {0x08,0x3c,0x02,0x4e,0x01,0xa3,0xd2,0x2e,0xc4,0x08,0xb1,0x02,0xcc,0x00,0x83,0x80 } },
+{  16, 0xd5c0, 0, {0x24,0xc1,0x0b,0x30,0x02,0x0c,0x00,0xb3,0x40,0xa0,0xd2,0x09,0x30,0x12,0x52,0x00 } },
+{  16, 0xd5d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xba,0x00,0xca,0xc0,0x36,0x80 } },
+{  16, 0xd5e0, 0, {0x0d,0x67,0x13,0x28,0x00,0xce,0x00,0x3e,0xa0,0x0c,0xed,0x03,0xe8,0x00,0xce,0xe0 } },
+{  16, 0xd5f0, 0, {0x36,0x80,0x1e,0xa0,0x0b,0x28,0x04,0xfe,0x00,0xb7,0xb2,0x0c,0xe0,0x0b,0x7a,0x00 } },
+{  16, 0xd600, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x40,0xf8,0x10,0x2e,0x10 } },
+{  16, 0xd610, 0, {0x0f,0x80,0x03,0xe0,0x01,0xd8,0x0a,0x3e,0x00,0x0f,0x80,0x03,0xc0,0x02,0xf8,0x08 } },
+{  16, 0xd620, 0, {0x3a,0x00,0x0f,0x80,0x03,0xe0,0x10,0xe8,0x20,0xbe,0x00,0x0f,0x80,0x13,0x92,0x00 } },
+{  16, 0xd630, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe5,0x00,0xfb,0x00,0x3e,0x40 } },
+{  16, 0xd640, 0, {0x0c,0x91,0x03,0x26,0x00,0x61,0x80,0x32,0x40,0x0c,0x90,0x03,0x24,0x00,0xc9,0x00 } },
+{  16, 0xd650, 0, {0x1e,0x40,0x0c,0x9c,0x03,0xe4,0x01,0xf9,0x00,0x3e,0x40,0x0f,0x90,0x03,0xc2,0x00 } },
+{  16, 0xd660, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x67,0x00,0xb9,0x00,0x2c,0x40 } },
+{  16, 0xd670, 0, {0x00,0x9c,0x02,0xa6,0x00,0x79,0x00,0x22,0x40,0x28,0x90,0x02,0x24,0x00,0x89,0x00 } },
+{  16, 0xd680, 0, {0x2c,0x44,0x08,0x98,0x02,0xe4,0x00,0xb9,0x80,0x2e,0x40,0x0b,0x90,0x02,0xe0,0x01 } },
+{  16, 0xd690, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x24,0x00,0xbb,0x00,0x26,0x50 } },
+{  16, 0xd6a0, 0, {0x28,0x90,0x82,0x24,0x84,0x99,0x20,0x22,0x40,0x49,0x90,0x02,0x24,0x00,0x89,0x00 } },
+{  16, 0xd6b0, 0, {0x2e,0x40,0x08,0x90,0x02,0xe4,0x00,0xb9,0x60,0x2e,0x40,0x0b,0x90,0x02,0xc6,0x04 } },
+{  16, 0xd6c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x06,0x00,0xb1,0x00,0x2e,0x48 } },
+{  16, 0xd6d0, 0, {0x08,0x12,0x02,0x84,0x80,0xb1,0x20,0xa0,0x48,0x09,0x12,0x0a,0x04,0x80,0x81,0x00 } },
+{  16, 0xd6e0, 0, {0x2c,0x48,0x28,0x12,0x42,0xc4,0x88,0x31,0x00,0x2c,0x40,0x0b,0x18,0x02,0xc2,0x01 } },
+{  16, 0xd6f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xf8,0x50,0x36,0x14 } },
+{  16, 0xd700, 0, {0x0c,0x80,0x03,0x20,0x00,0xe8,0x00,0x32,0x14,0x0c,0x85,0x03,0x21,0x40,0xc8,0x50 } },
+{  16, 0xd710, 0, {0x3e,0x14,0x0c,0x80,0x03,0xe1,0x40,0x38,0x00,0x3e,0x00,0x8f,0x80,0x03,0xee,0x03 } },
+{  16, 0xd720, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xd4,0x00,0xfb,0x04,0x3d,0x44 } },
+{  16, 0xd730, 0, {0x0f,0x51,0x23,0xd4,0x48,0xed,0x10,0x3d,0x44,0x4e,0xd1,0x23,0xf4,0x42,0xfd,0x00 } },
+{  16, 0xd740, 0, {0x3e,0x44,0x8f,0x91,0x03,0xe4,0x58,0xfd,0x00,0x3f,0x50,0x0f,0x50,0x03,0xe6,0x06 } },
+{  16, 0xd750, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf4,0x00,0xf9,0x00,0x3d,0x40 } },
+{  16, 0xd760, 0, {0x0c,0xd0,0x03,0xf4,0x00,0xdd,0x02,0x3e,0x40,0x0c,0x90,0x03,0xe4,0x40,0xc9,0x10 } },
+{  16, 0xd770, 0, {0x37,0x40,0x07,0xd0,0x07,0x24,0x00,0xe5,0x00,0x2f,0x6a,0x0f,0x70,0x03,0x06,0x00 } },
+{  16, 0xd780, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0xb8,0x00,0x3a,0x00 } },
+{  16, 0xd790, 0, {0x80,0x80,0x02,0xe0,0x00,0x88,0x00,0x2e,0x00,0x0a,0x80,0x53,0xa2,0x80,0x2c,0xa0 } },
+{  16, 0xd7a0, 0, {0x22,0x00,0x0b,0x80,0x0a,0x20,0x00,0xb8,0x00,0x2e,0x10,0x09,0x80,0x03,0x0e,0x04 } },
+{  16, 0xd7b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0x6c,0x40 } },
+{  16, 0xd7c0, 0, {0x2a,0x10,0x02,0x84,0x01,0x81,0x80,0x2e,0x40,0x09,0x10,0x02,0xf4,0x00,0x8d,0x04 } },
+{  16, 0xd7d0, 0, {0x20,0x40,0x0b,0x10,0x02,0x84,0x00,0xb1,0x00,0x2c,0x40,0x0b,0x98,0x02,0x42,0x01 } },
+{  16, 0xd7e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x20,0xb9,0x00,0x2a,0x40 } },
+{  16, 0xd7f0, 0, {0x88,0xb4,0x02,0xe6,0x01,0xa9,0x20,0x2e,0x48,0x0a,0x90,0x00,0xa4,0x40,0xad,0x40 } },
+{  16, 0xd800, 0, {0x22,0x40,0x0b,0x90,0x12,0xa4,0x04,0xb9,0x01,0x2e,0x41,0x0b,0x90,0x02,0x06,0x04 } },
+{  16, 0xd810, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0xc0,0x3e,0x60 } },
+{  16, 0xd820, 0, {0x0c,0x94,0x13,0xa6,0x02,0xd9,0x42,0x1c,0x60,0x0c,0x9e,0x01,0xc6,0x04,0xc1,0x00 } },
+{  16, 0xd830, 0, {0xb2,0x40,0x1f,0x90,0x02,0xa4,0x00,0xe9,0x08,0x3e,0x68,0x4f,0x98,0x0b,0x68,0x04 } },
+{  16, 0xd840, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa6,0x40,0xf9,0x20,0x38,0x70 } },
+{  16, 0xd850, 0, {0x0f,0x91,0x03,0xe4,0x00,0xd9,0x80,0x3e,0x40,0x0f,0x9c,0x13,0xa4,0x00,0xf9,0x00 } },
+{  16, 0xd860, 0, {0x3e,0x40,0x0f,0x10,0x03,0x64,0x10,0xf9,0x0a,0x3e,0x50,0x0d,0x9a,0x03,0xca,0x00 } },
+{  16, 0xd870, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x00,0xd8,0x04,0x3e,0x00 } },
+{  16, 0xd880, 0, {0x0c,0x81,0x13,0xc0,0x02,0xd8,0x20,0x3e,0x00,0x2d,0x84,0x03,0xe0,0x00,0xcc,0x08 } },
+{  16, 0xd890, 0, {0x3a,0x00,0x0f,0x80,0x43,0xe0,0x00,0xf8,0x41,0x32,0x00,0x07,0x81,0x8b,0x0a,0x04 } },
+{  16, 0xd8a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x3a,0x60,0x8a,0x00,0x2f,0xa8 } },
+{  16, 0xd8b0, 0, {0x0a,0xe0,0x22,0xe8,0x02,0x7e,0x48,0x2e,0x80,0x08,0xa0,0x42,0xe8,0x04,0x8e,0x00 } },
+{  16, 0xd8c0, 0, {0x23,0xa8,0x0b,0xa8,0x82,0xe8,0x00,0xee,0x00,0xa2,0x80,0x4b,0x60,0x02,0x0a,0x00 } },
+{  16, 0xd8d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0x00,0x6c,0xc0 } },
+{  16, 0xd8e0, 0, {0x08,0x30,0x02,0xcc,0x00,0x13,0x81,0x2c,0xc0,0x08,0x30,0x02,0xce,0x40,0x82,0x40 } },
+{  16, 0xd8f0, 0, {0x28,0xe0,0x0b,0x38,0x02,0xcc,0x00,0xb3,0x10,0x24,0xc0,0x8b,0x38,0x02,0x0a,0x00 } },
+{  16, 0xd900, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x00,0x87,0x20,0x2f,0xc0 } },
+{  16, 0xd910, 0, {0x0a,0x70,0x02,0xdc,0x0a,0xb6,0x00,0x2c,0xc8,0x88,0x72,0x06,0xd8,0x00,0x86,0x00 } },
+{  16, 0xd920, 0, {0x21,0xc0,0x0b,0x70,0x02,0xdc,0x84,0xaf,0x80,0xa5,0xc0,0x0b,0xd0,0x02,0x28,0x00 } },
+{  16, 0xd930, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xd7,0x80,0x3d,0xa0 } },
+{  16, 0xd940, 0, {0x1c,0x78,0x13,0xd6,0x02,0xd7,0x80,0x3d,0xec,0x08,0x7e,0x23,0xfe,0x00,0xce,0x80 } },
+{  16, 0xd950, 0, {0x39,0x60,0x0f,0x78,0x03,0xdf,0x00,0xf6,0x80,0x75,0xe0,0x0f,0x78,0x03,0x2a,0x02 } },
+{  16, 0xd960, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0x8c,0x00,0xfb,0x10,0x3e,0x80 } },
+{  16, 0xd970, 0, {0x1f,0xa0,0x21,0xcc,0x00,0xfa,0x00,0x3e,0xc0,0x0e,0xb0,0x03,0xe8,0x02,0xfa,0x00 } },
+{  16, 0xd980, 0, {0x3e,0x40,0x0f,0xb0,0x13,0xec,0x00,0xea,0x01,0x3a,0xc0,0x0f,0x90,0x03,0xc2,0x06 } },
+{  16, 0xd990, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfc,0x00,0xff,0x80,0x3f,0x60 } },
+{  16, 0xd9a0, 0, {0x08,0x99,0x07,0x7e,0x00,0xdd,0x80,0x3f,0xe2,0x0c,0xf8,0x03,0xf6,0x02,0xdf,0x80 } },
+{  16, 0xd9b0, 0, {0xb3,0xe0,0x0c,0xf8,0x03,0x3e,0x41,0xcc,0x80,0x33,0xe4,0x0f,0xf8,0x03,0xc0,0x00 } },
+{  16, 0xd9c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x40,0xb7,0x00,0x2d,0xc0 } },
+{  16, 0xd9d0, 0, {0x0d,0x5a,0x22,0xdc,0x80,0x75,0x00,0x2d,0xc0,0x08,0x71,0x02,0xf0,0x20,0x87,0x00 } },
+{  16, 0xd9e0, 0, {0x21,0xc0,0x0a,0x70,0x02,0x1c,0x00,0xd4,0x28,0x21,0xc0,0x0b,0x72,0x02,0xea,0x04 } },
+{  16, 0xd9f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x40,0xb7,0x00,0x2d,0x00 } },
+{  16, 0xda00, 0, {0x08,0x72,0x22,0xf4,0x00,0x87,0x00,0x2d,0xc2,0x08,0x70,0x02,0xd4,0x00,0x87,0x80 } },
+{  16, 0xda10, 0, {0x25,0x40,0x09,0x30,0x02,0x5c,0x01,0xad,0x00,0x29,0xd0,0x4b,0x70,0x02,0xc0,0x00 } },
+{  16, 0xda20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0xbb,0xc8,0x2c,0xa0 } },
+{  16, 0xda30, 0, {0x09,0x20,0x02,0xce,0x00,0xa3,0x00,0x2c,0xe0,0xa8,0x3d,0x42,0xc2,0x00,0x8b,0x80 } },
+{  16, 0xda40, 0, {0x24,0x40,0x0b,0x30,0x0a,0x6c,0x08,0xa3,0x40,0xa8,0xe0,0x0b,0x34,0x02,0xc8,0x04 } },
+{  16, 0xda50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xad,0x00,0xff,0x48,0x3c,0x28 } },
+{  16, 0xda60, 0, {0x0c,0xa9,0x23,0x6c,0x80,0x8b,0x00,0x3f,0xc0,0x0c,0xfc,0x03,0xec,0x00,0xd8,0x80 } },
+{  16, 0xda70, 0, {0x34,0x40,0x0d,0x30,0x03,0x7c,0x02,0xa3,0x40,0x38,0x68,0x0f,0x24,0x03,0xea,0x04 } },
+{  16, 0xda80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xed,0x88,0xfb,0x00,0x3e,0x50 } },
+{  16, 0xda90, 0, {0x0f,0xa1,0x03,0xec,0x04,0x3a,0xc0,0x3e,0xc0,0x0f,0xb0,0x83,0xe8,0x02,0xf8,0x10 } },
+{  16, 0xdaa0, 0, {0x3a,0x41,0x0e,0x90,0x03,0xac,0x00,0x9b,0x08,0xb6,0x40,0x0f,0x81,0x03,0xe0,0x00 } },
+{  16, 0xdab0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xff,0x00,0xb3,0x20 } },
+{  16, 0xdac0, 0, {0x0c,0x50,0x13,0x1c,0x09,0xcd,0x83,0x33,0xc0,0x83,0x70,0x00,0x3c,0x00,0xdc,0x10 } },
+{  16, 0xdad0, 0, {0x32,0x60,0x0e,0xf1,0x43,0x2c,0x00,0xce,0x04,0x3b,0x70,0x0c,0xf0,0x83,0x00,0x44 } },
+{  16, 0xdae0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x67,0x80,0xbb,0x01,0x62,0x21 } },
+{  16, 0xdaf0, 0, {0x8a,0x89,0x20,0x2c,0x00,0x80,0xe0,0x22,0xc0,0x0b,0xb0,0x03,0xd8,0x10,0x8c,0x04 } },
+{  16, 0xdb00, 0, {0x22,0x40,0x05,0x90,0x02,0xac,0x00,0xd8,0x80,0x36,0x40,0x0a,0x90,0x02,0x20,0x40 } },
+{  16, 0xdb10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x26,0x00,0xbb,0x00,0x22,0x06 } },
+{  16, 0xdb20, 0, {0x08,0x80,0x02,0x2e,0x00,0x88,0x20,0x22,0xc0,0x09,0xb0,0x02,0xa4,0x00,0x99,0x00 } },
+{  16, 0xdb30, 0, {0x62,0xc4,0x08,0xb0,0x06,0x2c,0x00,0x88,0x80,0x22,0x41,0x08,0xa0,0x02,0x20,0x00 } },
+{  16, 0xdb40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xb3,0x00,0x20,0x40 } },
+{  16, 0xdb50, 0, {0x0a,0x00,0x82,0x0c,0x00,0x80,0x00,0x20,0xc0,0x0b,0x30,0x22,0xa0,0x00,0x81,0x00 } },
+{  16, 0xdb60, 0, {0xa0,0xc0,0x09,0x30,0x02,0x8c,0x00,0x90,0x00,0x24,0x40,0x0a,0x28,0x02,0x02,0x01 } },
+{  16, 0xdb70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x60,0x00,0xfb,0x02,0x20,0x00 } },
+{  16, 0xdb80, 0, {0x2c,0x92,0x03,0x2c,0x02,0x88,0x00,0x31,0xc0,0x0b,0xb5,0x02,0xa4,0x00,0xd1,0x04 } },
+{  16, 0xdb90, 0, {0x32,0x40,0x0e,0x90,0x03,0x2c,0x40,0xc9,0x00,0x3a,0x40,0x8c,0xa0,0x03,0x00,0x03 } },
+{  16, 0xdba0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf4,0x00,0xff,0x00,0x2f,0x00 } },
+{  16, 0xdbb0, 0, {0x0f,0xc0,0x03,0xdc,0x00,0xfc,0x00,0x3f,0xc1,0x0f,0xf0,0x43,0xf0,0x00,0xfd,0x00 } },
+{  16, 0xdbc0, 0, {0x3f,0x40,0x4f,0xd0,0x03,0xfc,0x00,0xf5,0x00,0x3f,0x40,0x0f,0xe0,0x03,0xe8,0x06 } },
+{  16, 0xdbd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xd8,0x80,0xcc,0x00,0xb7,0x04 } },
+{  16, 0xdbe0, 0, {0x4e,0xe1,0x03,0x3c,0x20,0xdf,0x10,0x31,0x80,0x06,0xf0,0x03,0x7f,0x00,0xff,0xc0 } },
+{  16, 0xdbf0, 0, {0x3b,0xc0,0x0e,0xf2,0x03,0x5e,0x00,0xef,0x10,0x33,0xd0,0x2c,0xf2,0x03,0x30,0x00 } },
+{  16, 0xdc00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x10,0xe9,0x00,0x88,0xc6,0x20,0x5c } },
+{  16, 0xdc10, 0, {0x08,0xa4,0x57,0x65,0x00,0x8f,0x52,0x2a,0xf0,0x09,0xfc,0x02,0x04,0x00,0xbb,0x00 } },
+{  16, 0xdc20, 0, {0x2d,0xd9,0x09,0x74,0x83,0x64,0x28,0x83,0x44,0x22,0x84,0x88,0x06,0x82,0x30,0x04 } },
+{  16, 0xdc30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xc9,0x00,0x80,0x10,0x20,0x08 } },
+{  16, 0xdc40, 0, {0x08,0x31,0x12,0x04,0xb2,0xa3,0x00,0x20,0x84,0x1b,0x34,0x02,0x0c,0x80,0xb3,0x20 } },
+{  16, 0xdc50, 0, {0x2c,0xc7,0x09,0x36,0x02,0x8c,0x80,0x93,0x40,0xac,0xc8,0x08,0x31,0x28,0x32,0x01 } },
+{  16, 0xdc60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa9,0x00,0x88,0x00,0xa2,0x50 } },
+{  16, 0xdc70, 0, {0x08,0x35,0x02,0x24,0x00,0x8b,0x04,0x2e,0xc1,0x09,0xb0,0x02,0x24,0x94,0xbb,0x00 } },
+{  16, 0xdc80, 0, {0x2e,0xc0,0x0b,0xb0,0x02,0xcc,0x60,0x8b,0x00,0x2e,0x80,0x08,0x80,0x00,0x30,0x04 } },
+{  16, 0xdc90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xe7,0x02,0xcb,0x18,0xb2,0x80 } },
+{  16, 0xdca0, 0, {0x2c,0xac,0x0a,0x2e,0x08,0xeb,0x00,0x32,0x12,0x4e,0xb0,0x03,0x2b,0x80,0xfb,0x00 } },
+{  16, 0xdcb0, 0, {0x3a,0xc0,0x0a,0xb0,0x03,0xab,0x08,0xeb,0x04,0x2e,0x48,0x0c,0xb8,0x83,0x00,0x04 } },
+{  16, 0xdcc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb6,0x80,0xff,0x80,0x39,0xca } },
+{  16, 0xdcd0, 0, {0x0d,0xe8,0x03,0xd6,0x40,0xe7,0x04,0x3b,0x66,0x4e,0x70,0x03,0xb8,0x00,0xff,0x01 } },
+{  16, 0xdce0, 0, {0x3f,0xc0,0x6c,0xf0,0x03,0x70,0x06,0xe7,0x00,0x31,0x04,0x0f,0xc1,0x43,0xf8,0x00 } },
+{  16, 0xdcf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x85,0x00,0xcb,0x40,0x32,0x90 } },
+{  16, 0xdd00, 0, {0x2f,0xb0,0x0b,0x64,0x80,0xfb,0x08,0xba,0x10,0x0d,0xb0,0xa7,0x2d,0x00,0xfb,0x04 } },
+{  16, 0xdd10, 0, {0x3e,0xc0,0x8e,0xb0,0x03,0x6d,0x00,0xdb,0x01,0x32,0x40,0x8c,0x33,0x03,0x90,0x04 } },
+{  16, 0xdd20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0x24,0x00,0x83,0xe0,0xa2,0xd0 } },
+{  16, 0xdd30, 0, {0x40,0xb0,0x02,0x25,0x04,0xbf,0x80,0xa0,0x50,0x08,0xf8,0x02,0x20,0x00,0x8b,0x02 } },
+{  16, 0xdd40, 0, {0x2f,0xd0,0x08,0xf0,0x02,0x24,0x00,0x8f,0x80,0x36,0x01,0x08,0x84,0x42,0x36,0x00 } },
+{  16, 0xdd50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x05,0x44,0x00,0x83,0x48,0x20,0xc4 } },
+{  16, 0xdd60, 0, {0x09,0x00,0x02,0x46,0x00,0xb3,0x01,0xa8,0x90,0x19,0x30,0x12,0x8c,0x00,0xa3,0x04 } },
+{  16, 0xdd70, 0, {0x2e,0xe2,0x0a,0xb0,0x02,0x0c,0x00,0x83,0x49,0x28,0xc0,0x09,0x3c,0x02,0x38,0x00 } },
+{  16, 0xdd80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x01,0x36,0x04,0x83,0x80,0x21,0xe1 } },
+{  16, 0xdd90, 0, {0x08,0x38,0x12,0x1e,0x28,0xb3,0x98,0x21,0xa0,0x19,0x38,0x82,0x96,0x00,0x87,0x83 } },
+{  16, 0xdda0, 0, {0x2d,0xe2,0x08,0x78,0x22,0x36,0x8c,0x87,0x80,0x2d,0xe0,0x09,0x79,0x02,0x3e,0x00 } },
+{  16, 0xddb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x04,0x00,0xc3,0x30,0x30,0xc8 } },
+{  16, 0xddc0, 0, {0x4d,0x00,0x0b,0x4c,0x80,0xf3,0x12,0x38,0xc0,0x0d,0x3a,0x02,0x8c,0x80,0xf3,0x00 } },
+{  16, 0xddd0, 0, {0x3c,0xc0,0x0e,0x30,0x0b,0x0e,0x00,0xc3,0x0c,0x3a,0xc0,0x0d,0x30,0x03,0x12,0x02 } },
+{  16, 0xdde0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb4,0x06,0xff,0x10,0x3f,0xc0 } },
+{  16, 0xddf0, 0, {0x0f,0xb0,0x13,0xbc,0x00,0xff,0x10,0x7f,0xc0,0x0e,0xf1,0xa3,0x7c,0x00,0xff,0x12 } },
+{  16, 0xde00, 0, {0x3f,0xc2,0x0f,0xf5,0x23,0xbc,0x41,0xef,0x18,0x37,0x80,0xae,0xc0,0x03,0x50,0x06 } },
+{  16, 0xde10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe4,0x00,0xdb,0x00,0x3e,0xda } },
+{  16, 0xde20, 0, {0x0c,0x80,0x03,0x66,0x10,0x8b,0x00,0x32,0x80,0x8c,0xb6,0x03,0x4a,0x00,0x4b,0x80 } },
+{  16, 0xde30, 0, {0x32,0xc8,0x0c,0xb4,0x03,0x0a,0x10,0xdb,0x00,0x3e,0xc1,0x0c,0xb0,0x43,0x2a,0x00 } },
+{  16, 0xde40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x11,0xb4,0x00,0x87,0x04,0x2c,0xc0 } },
+{  16, 0xde50, 0, {0x0d,0x70,0x03,0x1c,0x08,0x87,0x48,0x20,0x81,0x0d,0x72,0x82,0x5c,0x00,0xd7,0x00 } },
+{  16, 0xde60, 0, {0x21,0xcc,0x28,0xf0,0x02,0x1c,0x10,0x87,0x20,0x2c,0x00,0x08,0x40,0x0a,0x32,0x04 } },
+{  16, 0xde70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x96,0x00,0xb7,0x81,0x2d,0xe0 } },
+{  16, 0xde80, 0, {0x08,0x48,0x02,0x0e,0x04,0x87,0x80,0x21,0xe0,0x08,0x78,0x02,0x3e,0x01,0x87,0x80 } },
+{  16, 0xde90, 0, {0x21,0xe0,0x18,0x79,0x02,0x3a,0x01,0x97,0xa0,0x2d,0x60,0x08,0x38,0x02,0x20,0x00 } },
+{  16, 0xdea0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xc6,0x00,0xa3,0xc6,0x2c,0xc0 } },
+{  16, 0xdeb0, 0, {0x09,0x30,0x02,0x0c,0x01,0x83,0x00,0x20,0xe0,0x09,0x30,0x02,0x4e,0x00,0x93,0x00 } },
+{  16, 0xdec0, 0, {0x20,0xc0,0x49,0x30,0x22,0x0f,0x64,0x83,0x02,0x6c,0xd4,0x28,0x30,0x02,0x12,0x04 } },
+{  16, 0xded0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x11,0xab,0x80,0xfa,0xe0,0x3c,0x88 } },
+{  16, 0xdee0, 0, {0x0c,0xe0,0x02,0x28,0x02,0xca,0x00,0xb3,0xa9,0x0c,0xa0,0x03,0x3b,0x10,0xca,0x00 } },
+{  16, 0xdef0, 0, {0xa2,0x80,0x0c,0xa0,0x0b,0x38,0x00,0xda,0x00,0x3f,0xb0,0x0c,0xe6,0x03,0x3a,0x04 } },
+{  16, 0xdf00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xc0,0x20,0x98,0x08,0x3e,0x00 } },
+{  16, 0xdf10, 0, {0x0f,0x80,0x0b,0xe1,0x00,0xf8,0x01,0x3c,0x10,0x4f,0x00,0x03,0xa0,0x40,0xf8,0x00 } },
+{  16, 0xdf20, 0, {0x3e,0x10,0x0e,0x80,0x03,0xe0,0x00,0xf8,0x00,0x3c,0x02,0x2f,0x04,0x93,0xd2,0x00 } },
+{  16, 0xdf30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xc1,0xc1,0x32,0x40 } },
+{  16, 0xdf40, 0, {0x0c,0x98,0x03,0x26,0x40,0xf9,0x00,0x32,0x40,0x0c,0x98,0x03,0x24,0x24,0xf9,0x00 } },
+{  16, 0xdf50, 0, {0x3c,0x60,0x0c,0x10,0x03,0xa4,0x00,0xf9,0x82,0x32,0x40,0x0c,0x90,0x03,0x02,0x04 } },
+{  16, 0xdf60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x00,0x22,0x50 } },
+{  16, 0xdf70, 0, {0x0d,0x98,0x02,0x25,0x80,0xb9,0x00,0x22,0x52,0x0d,0x9c,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0xdf80, 0, {0x2e,0x60,0x08,0x90,0x42,0x24,0x00,0xb9,0x40,0x36,0x40,0x08,0x90,0x0a,0x20,0x00 } },
+{  16, 0xdf90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x8d,0x00,0x23,0x40 } },
+{  16, 0xdfa0, 0, {0x08,0x12,0x02,0x24,0x00,0xa1,0x10,0xa2,0x60,0x08,0x92,0x8a,0x24,0x00,0xb9,0x01 } },
+{  16, 0xdfb0, 0, {0x2e,0x46,0x08,0x90,0x02,0xa4,0x00,0xb1,0x50,0x22,0x40,0x28,0x90,0x82,0x06,0x00 } },
+{  16, 0xdfc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x84,0x85,0x20,0xa1,0xd8 } },
+{  16, 0xdfd0, 0, {0x09,0x10,0x02,0x04,0x80,0xb3,0x20,0x20,0x40,0x29,0x12,0x06,0x04,0x00,0xb1,0x01 } },
+{  16, 0xdfe0, 0, {0x2c,0x48,0x28,0x12,0x02,0x04,0x00,0xb1,0x20,0x24,0x48,0x08,0x12,0x02,0x02,0x01 } },
+{  16, 0xdff0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x42,0x8a,0x00,0xb3,0x00 } },
+{  16, 0xe000, 0, {0x0c,0x05,0x03,0x21,0x40,0xe0,0x50,0xb2,0x00,0x2c,0x80,0x02,0x21,0x40,0xf0,0x50 } },
+{  16, 0xe010, 0, {0x3c,0x14,0x0c,0x85,0x13,0xa1,0x50,0xf8,0x50,0x32,0x14,0x0c,0x85,0x23,0x2e,0x03 } },
+{  16, 0xe020, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xf9,0x10,0x3e,0x44 } },
+{  16, 0xe030, 0, {0x0f,0xd4,0x0b,0xf4,0x44,0xf9,0x10,0x3f,0x50,0x4f,0x11,0x03,0xf4,0x00,0xf9,0x00 } },
+{  16, 0xe040, 0, {0x3e,0x44,0x0f,0x91,0x53,0xf4,0x14,0xf9,0x10,0x3f,0x44,0x0f,0xd1,0x03,0xe6,0x02 } },
+{  16, 0xe050, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x05,0xe6,0xa0,0xdd,0x88,0xb3,0x66 } },
+{  16, 0xe060, 0, {0x0c,0xdc,0x83,0x36,0x88,0xbd,0xa0,0x37,0x6a,0x0c,0xda,0x0b,0x25,0x02,0xc9,0x40 } },
+{  16, 0xe070, 0, {0x3f,0x78,0x4f,0x98,0xb3,0xe5,0x04,0xcd,0xa0,0x72,0x78,0x0c,0xd8,0x8b,0x26,0x14 } },
+{  16, 0xe080, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe3,0x00,0x88,0x42,0x22,0x31 } },
+{  16, 0xe090, 0, {0x08,0x0a,0x02,0x22,0xa0,0xb8,0xf9,0x22,0x10,0x0d,0x84,0x12,0x6a,0x80,0x88,0x80 } },
+{  16, 0xe0a0, 0, {0x2e,0x20,0x0b,0x08,0x02,0xe2,0x80,0xa8,0xa8,0xa2,0x38,0x48,0xa8,0x02,0x0e,0x00 } },
+{  16, 0xe0b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc4,0xa2,0x81,0x00,0x20,0x48 } },
+{  16, 0xe0c0, 0, {0x08,0x12,0x42,0x45,0x00,0xb1,0x00,0x24,0x40,0x09,0x14,0x02,0x24,0x00,0x81,0x20 } },
+{  16, 0xe0d0, 0, {0x2c,0x58,0x0b,0x10,0x82,0xc4,0x04,0x91,0x40,0x64,0x6c,0x08,0x30,0x82,0x12,0x05 } },
+{  16, 0xe0e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0x89,0x00,0x22,0x41 } },
+{  16, 0xe0f0, 0, {0x08,0x90,0x8a,0x64,0x80,0xb9,0x00,0x22,0x50,0x09,0x90,0x06,0x64,0x08,0x99,0x00 } },
+{  16, 0xe100, 0, {0x2e,0x40,0x0b,0x90,0x06,0xc4,0x01,0xb9,0x02,0x26,0x61,0x88,0x90,0x02,0x06,0x04 } },
+{  16, 0xe110, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xc9,0x00,0x22,0x40 } },
+{  16, 0xe120, 0, {0x2c,0x94,0x23,0x64,0x00,0xb9,0x00,0x36,0x40,0x09,0x90,0x13,0x05,0x00,0xc9,0x00 } },
+{  16, 0xe130, 0, {0x3e,0x40,0x4f,0x90,0x13,0xe5,0xc0,0xd9,0x00,0x26,0x40,0x2c,0x94,0x03,0x28,0x00 } },
+{  16, 0xe140, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x01,0xa4,0x02,0xe9,0x08,0x3c,0x40 } },
+{  16, 0xe150, 0, {0x0f,0x90,0x0b,0xa4,0x00,0xf1,0x00,0x3e,0x41,0x0f,0x90,0x43,0xa4,0x88,0xe9,0x04 } },
+{  16, 0xe160, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe6,0x00,0xe1,0x00,0x3a,0x40,0x9f,0x92,0x63,0xda,0x00 } },
+{  16, 0xe170, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0x80,0x10,0xe0,0x01,0x32,0x00 } },
+{  16, 0xe180, 0, {0x8f,0x80,0x03,0x20,0x00,0xd8,0x08,0x30,0x01,0x8c,0x00,0x03,0xe1,0x02,0xc8,0x04 } },
+{  16, 0xe190, 0, {0x3e,0x00,0x0c,0x80,0x0b,0x21,0x00,0xc8,0x00,0x78,0x00,0x0f,0x86,0x03,0x0a,0x00 } },
+{  16, 0xe1a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8e,0x40,0x2b,0x82 } },
+{  16, 0xe1b0, 0, {0x0b,0xa0,0x02,0x3a,0x00,0x8e,0x80,0x23,0x82,0x08,0xe2,0x02,0x28,0x10,0x8a,0x00 } },
+{  16, 0xe1c0, 0, {0x2f,0x98,0x28,0xa0,0x12,0x28,0x00,0x8e,0x20,0x2e,0x80,0x4b,0xe4,0x02,0x0a,0x00 } },
+{  16, 0xe1d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x02,0xa2,0x40,0x20,0x80 } },
+{  16, 0xe1e0, 0, {0x0b,0xb0,0x02,0x4e,0x40,0x93,0xc0,0xa0,0x20,0x08,0x36,0x02,0x8c,0x00,0x93,0x00 } },
+{  16, 0xe1f0, 0, {0x2c,0xe2,0x08,0x30,0x06,0x4c,0x12,0x93,0x08,0x28,0xc0,0x0b,0xb0,0x02,0x0a,0x00 } },
+{  16, 0xe200, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x08,0x82,0x40,0x29,0x40 } },
+{  16, 0xe210, 0, {0x0b,0x70,0x02,0x5e,0x08,0x84,0x08,0x23,0x40,0x08,0x70,0x06,0x1c,0x80,0x87,0x00 } },
+{  16, 0xe220, 0, {0x2d,0x20,0x08,0x79,0x12,0x5c,0x00,0x94,0x00,0x2d,0xc0,0x0b,0x30,0x42,0x28,0x00 } },
+{  16, 0xe230, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x00,0xe4,0x80,0x31,0xa1 } },
+{  16, 0xe240, 0, {0x0f,0x58,0x13,0x76,0x00,0xd0,0x80,0x31,0xc0,0x0c,0x38,0x03,0xbe,0x80,0xd7,0x81 } },
+{  16, 0xe250, 0, {0x3f,0x20,0x8c,0x79,0x03,0x7f,0x01,0xd6,0x80,0x39,0xe8,0x4f,0x68,0x03,0x2a,0x00 } },
+{  16, 0xe260, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xbe,0x00,0xfa,0x00,0x3e,0x00 } },
+{  16, 0xe270, 0, {0x8f,0x96,0x0b,0xa4,0x00,0xea,0x00,0x3c,0xc0,0x0f,0x90,0x03,0xac,0x20,0xfb,0x40 } },
+{  16, 0xe280, 0, {0x2e,0x00,0x0f,0xb2,0x03,0xad,0xa0,0xea,0x00,0x3e,0xc0,0x0f,0xa0,0x1b,0xc2,0x04 } },
+{  16, 0xe290, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x08,0xde,0x81,0x33,0xa4 } },
+{  16, 0xe2a0, 0, {0x0e,0xfc,0x13,0x3e,0x00,0xfc,0x80,0x13,0x20,0x0c,0x68,0x03,0x3e,0x20,0xff,0xc8 } },
+{  16, 0xe2b0, 0, {0x3f,0x60,0x1d,0xf8,0x03,0x7e,0x00,0xc7,0x80,0x33,0xe2,0x0c,0xd8,0x03,0x10,0x00 } },
+{  16, 0xe2c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0x86,0x41,0x31,0xc4 } },
+{  16, 0xe2d0, 0, {0x08,0x79,0x42,0x9c,0x00,0xbc,0x10,0x21,0x40,0x85,0x35,0x03,0x5c,0x00,0xb7,0x00 } },
+{  16, 0xe2e0, 0, {0x2d,0xc0,0x08,0x72,0x02,0x2c,0x00,0xa7,0x01,0x37,0xc0,0x08,0x51,0x42,0x2a,0x00 } },
+{  16, 0xe2f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x8c,0x40,0x82,0x00,0x24,0x81 } },
+{  16, 0xe300, 0, {0x08,0xd8,0x02,0x14,0x20,0xb5,0x00,0x20,0x40,0x09,0x60,0x02,0x1c,0x40,0xb7,0x00 } },
+{  16, 0xe310, 0, {0x2c,0x40,0x0b,0x30,0x22,0xdc,0x00,0x97,0x00,0x21,0xc4,0x08,0x40,0x02,0x44,0x00 } },
+{  16, 0xe320, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xec,0x00,0x92,0x06,0x20,0x90 } },
+{  16, 0xe330, 0, {0x38,0x15,0x02,0x86,0x00,0xb8,0x00,0x60,0x50,0x09,0x30,0x02,0x4e,0x01,0xbb,0x00 } },
+{  16, 0xe340, 0, {0x2e,0x40,0x0b,0x30,0x02,0xce,0x20,0xb3,0x00,0x24,0xf0,0x48,0x02,0x0a,0x58,0x04 } },
+{  16, 0xe350, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xca,0x00,0xa6,0x94 } },
+{  16, 0xe360, 0, {0x2c,0x90,0x03,0x2e,0x00,0xfb,0x05,0xb2,0x85,0x0d,0x90,0x03,0x3f,0x90,0xff,0x00 } },
+{  16, 0xe370, 0, {0x7e,0x80,0x1f,0xf0,0x43,0xfc,0x21,0x9a,0x00,0x33,0xc8,0x3c,0xb2,0x03,0x6a,0x04 } },
+{  16, 0xe380, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0xec,0x02,0xea,0x40,0x3d,0x80 } },
+{  16, 0xe390, 0, {0x0f,0x10,0x93,0xed,0x00,0xfb,0x40,0x3e,0x90,0x8f,0x30,0x03,0xec,0x80,0xfb,0x00 } },
+{  16, 0xe3a0, 0, {0x3e,0x91,0x1c,0xb0,0x03,0x2c,0x10,0xe8,0x00,0x3e,0xc8,0x1f,0x90,0x03,0xa5,0x10 } },
+{  16, 0xe3b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xfc,0x02,0xe4,0x00,0x73,0xa0 } },
+{  16, 0xe3c0, 0, {0x0c,0xfc,0x03,0x7c,0x02,0xff,0x10,0x13,0xc4,0x1c,0xc0,0x03,0x3c,0x00,0xff,0x00 } },
+{  16, 0xe3d0, 0, {0x37,0xe0,0x0d,0xf0,0x03,0xfc,0x00,0xed,0x80,0x31,0xc0,0x0c,0x32,0x63,0x20,0x04 } },
+{  16, 0xe3e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x6c,0x00,0x8a,0xc0,0x22,0xb1 } },
+{  16, 0xe3f0, 0, {0x8a,0xb8,0x43,0x4a,0x10,0xdb,0x20,0x20,0xf0,0x0a,0x94,0x03,0x6c,0x00,0xbb,0x07 } },
+{  16, 0xe400, 0, {0x22,0xb8,0x08,0xb0,0x02,0xec,0x11,0xe8,0xc0,0xb2,0xc0,0x2a,0x92,0x1a,0x20,0x00 } },
+{  16, 0xe410, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x2c,0x00,0xaa,0x80,0x22,0x98 } },
+{  16, 0xe420, 0, {0x08,0x90,0x02,0x2f,0x03,0xbb,0x01,0x2a,0x83,0x08,0xb2,0x4e,0x2c,0x04,0xab,0x02 } },
+{  16, 0xe430, 0, {0x22,0xc4,0x28,0xb0,0x22,0xec,0x09,0xb3,0x50,0x62,0xc0,0x08,0xb0,0x02,0x20,0x00 } },
+{  16, 0xe440, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x01,0x83,0x00,0x60,0x80 } },
+{  16, 0xe450, 0, {0x08,0x12,0x0a,0x44,0x00,0x93,0x00,0x2a,0x80,0x4a,0x30,0x02,0x0c,0x00,0xb3,0x00 } },
+{  16, 0xe460, 0, {0x60,0xc0,0x08,0x30,0x02,0xcc,0x00,0xb3,0x02,0x60,0xc0,0x08,0x00,0x46,0x02,0x01 } },
+{  16, 0xe470, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0d,0x6c,0x00,0xe8,0x02,0x22,0x80 } },
+{  16, 0xe480, 0, {0x2c,0xf2,0x43,0x2c,0x00,0xfb,0x00,0xba,0xc0,0x08,0xa5,0x02,0x3c,0x00,0xef,0x00 } },
+{  16, 0xe490, 0, {0x36,0xc0,0x4d,0xf0,0x13,0xfd,0x51,0xfb,0x00,0x32,0xc0,0x0c,0xb0,0x03,0x20,0x01 } },
+{  16, 0xe4a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0x7e,0x04,0x3f,0x80 } },
+{  16, 0xe4b0, 0, {0x0f,0x31,0x43,0xf0,0x02,0xff,0x00,0x37,0xc0,0x0f,0xf0,0x03,0xfc,0x08,0xff,0x00 } },
+{  16, 0xe4c0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xef,0x00,0x3b,0xc0,0x0f,0xc0,0x03,0xe8,0x16 } },
+{  16, 0xe4d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf2,0x40,0xfc,0x80,0x3f,0x24 } },
+{  16, 0xe4e0, 0, {0x0d,0xd8,0x53,0xd6,0x04,0xdf,0x32,0x3f,0xcc,0x4c,0xc0,0x43,0xfc,0x00,0xdf,0x60 } },
+{  16, 0xe4f0, 0, {0x37,0xc0,0x0f,0xc4,0x03,0x7c,0xd0,0xdf,0x20,0x33,0xd8,0x0d,0xf8,0x43,0xf0,0x00 } },
+{  16, 0xe500, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x18,0xe8,0x80,0xb0,0x01,0x2e,0x08 } },
+{  16, 0xe510, 0, {0x88,0x90,0x02,0xec,0x20,0x8b,0x70,0x2f,0xcc,0x08,0xb3,0x82,0xfd,0xe0,0xbf,0x40 } },
+{  16, 0xe520, 0, {0x22,0xd8,0x0b,0x93,0x02,0xfd,0xc0,0xaf,0x10,0x28,0xf0,0x08,0xbc,0x12,0xf0,0x04 } },
+{  16, 0xe530, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x00,0xb0,0x00,0x2e,0x01 } },
+{  16, 0xe540, 0, {0x0a,0x12,0x82,0xec,0x80,0xb3,0x00,0x2c,0xc8,0x0a,0x00,0x32,0x8c,0x00,0xa3,0x30 } },
+{  16, 0xe550, 0, {0x20,0xd2,0x09,0x00,0x02,0x8c,0x80,0x83,0x00,0x28,0xd8,0x0b,0x34,0x12,0xf2,0x01 } },
+{  16, 0xe560, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xac,0x01,0xb8,0x02,0x2e,0x00 } },
+{  16, 0xe570, 0, {0x0a,0x90,0x12,0xec,0x10,0x8b,0x00,0x2e,0xc0,0x0a,0xb0,0x00,0xec,0x00,0xb3,0x00 } },
+{  16, 0xe580, 0, {0x22,0xc1,0x0b,0x92,0x02,0xcc,0x01,0xab,0x00,0x2a,0xc0,0x02,0xb0,0x02,0xf0,0x04 } },
+{  16, 0xe590, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe0,0x00,0xfa,0x0c,0x3e,0xc0 } },
+{  16, 0xe5a0, 0, {0x0f,0xa0,0x13,0xee,0x20,0xdb,0x00,0x3e,0xc0,0x2e,0x88,0x53,0xec,0x00,0xfb,0x00 } },
+{  16, 0xe5b0, 0, {0xb2,0xc0,0x8f,0xac,0x83,0xac,0x08,0xdb,0x00,0x1a,0xc0,0x4f,0xb0,0x03,0xc0,0x04 } },
+{  16, 0xe5c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x00,0xfe,0x00,0x3f,0xc0 } },
+{  16, 0xe5d0, 0, {0x2d,0xe0,0x03,0xfe,0x80,0x7f,0x00,0x3f,0xc0,0x0d,0xd2,0x03,0xfc,0x00,0xbf,0x01 } },
+{  16, 0xe5e0, 0, {0x3e,0xc0,0x0d,0xc8,0x03,0xfc,0x0c,0xff,0x00,0x3f,0xc0,0x09,0xf0,0x23,0xf8,0x00 } },
+{  16, 0xe5f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa4,0x00,0xfa,0x40,0x32,0xc1 } },
+{  16, 0xe600, 0, {0x0f,0xa0,0x03,0x29,0x08,0xdb,0x00,0x3e,0xc0,0x0e,0x85,0x03,0xec,0x20,0xcb,0x00 } },
+{  16, 0xe610, 0, {0x3a,0xc0,0x0e,0xa4,0x03,0xec,0x00,0xfb,0x00,0x3a,0xc2,0x0e,0xb0,0x03,0x10,0x04 } },
+{  16, 0xe620, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xba,0x60,0x20,0xc0 } },
+{  16, 0xe630, 0, {0x0b,0xa0,0x02,0x08,0x00,0xaf,0x00,0x2f,0xd0,0x0b,0xb5,0x02,0xfe,0x02,0x8f,0x00 } },
+{  16, 0xe640, 0, {0x2f,0xc0,0x0d,0x80,0x0a,0x3c,0x00,0xb7,0x00,0x23,0xc2,0x05,0xf0,0x22,0x36,0x00 } },
+{  16, 0xe650, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x04,0x40,0x00,0xb1,0x88,0x20,0x00 } },
+{  16, 0xe660, 0, {0x0b,0x10,0x02,0x0c,0x00,0x83,0x00,0x2e,0xc8,0x0b,0x08,0x06,0x4d,0x40,0x83,0x00 } },
+{  16, 0xe670, 0, {0x20,0xc0,0x08,0x30,0x06,0x0c,0x08,0x93,0x20,0x0a,0xe0,0x4a,0x30,0x02,0x38,0x00 } },
+{  16, 0xe680, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x5a,0x00,0xb5,0x90,0x21,0x20 } },
+{  16, 0xe690, 0, {0x0b,0x58,0x42,0x3e,0x00,0xa7,0x80,0x2d,0xe0,0x0b,0x69,0x02,0xde,0x40,0x87,0x92 } },
+{  16, 0xe6a0, 0, {0x2d,0xe0,0x09,0x18,0x02,0x9e,0x01,0xb7,0x80,0x29,0xe0,0x03,0x70,0x02,0x3e,0x00 } },
+{  16, 0xe6b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x44,0x00,0xf1,0x01,0x30,0x00 } },
+{  16, 0xe6c0, 0, {0x5f,0x18,0x03,0x0c,0x10,0x83,0x00,0x3c,0xc4,0x0e,0x04,0x03,0xec,0x00,0x83,0x00 } },
+{  16, 0xe6d0, 0, {0x30,0xc4,0x0c,0x31,0x03,0x8c,0x00,0xf3,0x00,0x38,0xc8,0x0e,0x31,0x03,0x12,0x02 } },
+{  16, 0xe6e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xbc,0x00,0xfd,0x04,0xbf,0x04 } },
+{  16, 0xe6f0, 0, {0x4f,0x58,0x03,0xf8,0x08,0xef,0x08,0x3f,0xc0,0x0f,0xf0,0x01,0xfc,0x00,0xff,0x4c } },
+{  16, 0xe700, 0, {0x3f,0xc1,0x0f,0xd0,0x03,0x3c,0x00,0xf7,0x00,0x37,0xc2,0x0d,0x72,0x03,0xd0,0x06 } },
+{  16, 0xe710, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xe2,0x00,0xdb,0x00,0x32,0xc0 } },
+{  16, 0xe720, 0, {0x4d,0xa8,0x03,0x2c,0x08,0xfb,0x00,0x7e,0xc8,0x8f,0xb0,0x0b,0x6f,0x45,0xeb,0xc2 } },
+{  16, 0xe730, 0, {0x36,0xc0,0x07,0xa0,0x03,0xef,0x20,0xcb,0x50,0xb2,0xc0,0x0c,0x79,0x03,0x2a,0x00 } },
+{  16, 0xe740, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x19,0x98,0x00,0x8f,0x00,0x21,0xc0 } },
+{  16, 0xe750, 0, {0x0b,0x60,0x03,0x5c,0x00,0x37,0x00,0x2d,0xd2,0x0b,0x30,0x02,0x0c,0xa8,0x87,0x24 } },
+{  16, 0xe760, 0, {0x21,0xd0,0x09,0x70,0x02,0xdd,0x88,0x87,0x2a,0x23,0xe8,0x08,0x70,0x02,0x32,0x04 } },
+{  16, 0xe770, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xb6,0x00,0x97,0x80,0x21,0xe0 } },
+{  16, 0xe780, 0, {0x0b,0x68,0x02,0x1e,0x00,0xb7,0x80,0x2d,0xe8,0x8b,0x48,0x82,0x1e,0x80,0xa3,0x84 } },
+{  16, 0xe790, 0, {0x25,0xe8,0x0b,0x68,0x02,0xce,0x02,0x87,0x80,0x21,0xe0,0x08,0x7a,0x02,0x20,0x00 } },
+{  16, 0xe7a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x04,0xcc,0x08,0x83,0x82,0x20,0xe0 } },
+{  16, 0xe7b0, 0, {0x8b,0x2a,0x02,0x48,0x40,0xb3,0x00,0x2c,0xc0,0x0b,0x30,0x82,0x0c,0x00,0x83,0x00 } },
+{  16, 0xe7c0, 0, {0x00,0xc1,0x09,0x31,0x02,0xcc,0x00,0x83,0x00,0x20,0xc0,0x08,0x30,0x0a,0x12,0x04 } },
+{  16, 0xe7d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xe8,0x00,0xda,0xa0,0x32,0xa8 } },
+{  16, 0xe7e0, 0, {0x8d,0xa8,0x03,0x3b,0x00,0xfa,0x00,0x3e,0x80,0x0f,0xe4,0x03,0x68,0x00,0xea,0x02 } },
+{  16, 0xe7f0, 0, {0x36,0x80,0x0f,0xe4,0x03,0xe8,0x00,0xca,0x00,0x32,0x80,0x2c,0xa0,0x03,0x3a,0x04 } },
+{  16, 0xe800, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x01,0xa0,0x10,0xf8,0x00,0xbe,0x20 } },
+{  16, 0xe810, 0, {0x8f,0xc1,0x03,0xe0,0x24,0xf8,0x00,0x3e,0x10,0x0f,0x84,0x03,0xe0,0x00,0xf8,0x01 } },
+{  16, 0xe820, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x00,0xf8,0x01,0xbe,0x10,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xe830, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xa4,0x00,0xf9,0x40,0x32,0x40 } },
+{  16, 0xe840, 0, {0xcf,0x90,0x03,0xe4,0x00,0xc9,0x00,0x0e,0x50,0x0f,0x1a,0x03,0x26,0x00,0xf9,0x00 } },
+{  16, 0xe850, 0, {0x3e,0x40,0x0f,0x90,0x81,0xe4,0x00,0xf9,0x80,0x32,0x40,0x0c,0x90,0x03,0xc2,0x04 } },
+{  16, 0xe860, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x04,0xb1,0x04,0x22,0x40 } },
+{  16, 0xe870, 0, {0x0b,0x90,0x02,0xe4,0x00,0xa9,0x00,0x2e,0x53,0x0b,0x92,0x0a,0x26,0x48,0xb9,0x04 } },
+{  16, 0xe880, 0, {0x2e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb9,0x80,0x02,0x50,0x08,0x90,0x02,0xe0,0x00 } },
+{  16, 0xe890, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x05,0x24,0x00,0xbd,0x00,0x23,0x40 } },
+{  16, 0xe8a0, 0, {0x0b,0xd0,0x12,0xc4,0x00,0x89,0x02,0x2e,0x40,0x0b,0x90,0x22,0x24,0x00,0xb9,0x00 } },
+{  16, 0xe8b0, 0, {0x2e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb1,0x20,0x20,0x40,0x68,0x90,0x22,0xc6,0x00 } },
+{  16, 0xe8c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x14,0x14,0x00,0xbf,0x12,0xa1,0x40 } },
+{  16, 0xe8d0, 0, {0x0b,0x50,0x02,0xc4,0x00,0xa1,0x20,0x2c,0x48,0x0b,0x12,0x02,0x04,0x10,0xb1,0x11 } },
+{  16, 0xe8e0, 0, {0x2c,0x48,0x0b,0x13,0x22,0xc4,0x00,0xb1,0x40,0x20,0x5a,0x08,0x10,0x02,0xc2,0x01 } },
+{  16, 0xe8f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf8,0x40,0x32,0x14 } },
+{  16, 0xe900, 0, {0x0f,0x45,0x03,0xe1,0x40,0xc8,0x50,0x3e,0x15,0x8f,0x85,0x03,0x21,0xe8,0xf8,0x68 } },
+{  16, 0xe910, 0, {0x3e,0x14,0x0f,0x84,0x03,0xe1,0xe0,0xf0,0x28,0x32,0xa8,0xcc,0x80,0x23,0xee,0x03 } },
+{  16, 0xe920, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x15,0xc4,0x10,0xf9,0x20,0x3e,0x40 } },
+{  16, 0xe930, 0, {0x0f,0x90,0x03,0xf4,0x00,0xf9,0x10,0x3e,0x44,0x0f,0xd1,0x03,0xe4,0x00,0xf9,0x20 } },
+{  16, 0xe940, 0, {0x3e,0x44,0x0f,0xd3,0x03,0xe4,0x00,0xf9,0x00,0xbe,0x40,0x0f,0x94,0x03,0xe6,0x06 } },
+{  16, 0xe950, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xe4,0x00,0xfd,0x10,0x33,0x40 } },
+{  16, 0xe960, 0, {0x0c,0xd0,0x03,0x24,0x00,0xd9,0x00,0x3f,0x40,0x4c,0xd0,0x03,0xf6,0x00,0xfd,0x90 } },
+{  16, 0xe970, 0, {0x3a,0x40,0x0c,0x90,0x03,0xe6,0xa0,0xfd,0xa8,0x37,0x68,0x0c,0xd8,0x83,0x26,0x00 } },
+{  16, 0xe980, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x08,0xc8,0xa0,0x22,0x00 } },
+{  16, 0xe990, 0, {0x08,0x80,0x02,0x20,0x00,0x88,0x00,0x2e,0x00,0x0c,0x80,0x12,0xe0,0x00,0xb8,0x80 } },
+{  16, 0xe9a0, 0, {0x22,0x00,0x0d,0x0a,0x02,0xe3,0x80,0xb0,0xc0,0x20,0x34,0x08,0x84,0x03,0x4e,0x04 } },
+{  16, 0xe9b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x84,0x09,0xa1,0x00,0x20,0x41 } },
+{  16, 0xe9c0, 0, {0x08,0x90,0x02,0x24,0x00,0x91,0x00,0x2c,0x40,0x08,0x10,0x02,0xc5,0x00,0xb1,0x60 } },
+{  16, 0xe9d0, 0, {0x20,0x40,0x08,0x10,0xa2,0xc4,0x20,0xb1,0x28,0x24,0x4a,0x08,0x10,0x02,0x52,0x01 } },
+{  16, 0xe9e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x14,0xa4,0x01,0x81,0x00,0xa2,0x40 } },
+{  16, 0xe9f0, 0, {0xa8,0x90,0x00,0x25,0x40,0x89,0x01,0x2c,0x40,0x08,0x94,0x02,0xe4,0x00,0xb9,0x00 } },
+{  16, 0xea00, 0, {0x2a,0x40,0x09,0x90,0x02,0xe4,0x01,0xb9,0x04,0x22,0x41,0x48,0x90,0x02,0x46,0x04 } },
+{  16, 0xea10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x14,0xa5,0x20,0xe9,0x00,0x32,0x40 } },
+{  16, 0xea20, 0, {0x4c,0x10,0x0b,0x26,0x00,0xd9,0x00,0x3e,0x40,0x2c,0x98,0x03,0xe4,0x00,0xf9,0x00 } },
+{  16, 0xea30, 0, {0xb2,0x40,0x0c,0x90,0x03,0xe4,0x00,0xf9,0x00,0x36,0x40,0x2c,0x90,0x03,0x68,0x04 } },
+{  16, 0xea40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x01,0xa4,0x00,0xe9,0x00,0x3e,0x40 } },
+{  16, 0xea50, 0, {0x0f,0x90,0x03,0xe6,0x00,0xf9,0x00,0x3e,0x40,0x0e,0x9a,0x03,0xe4,0x00,0xf9,0x00 } },
+{  16, 0xea60, 0, {0x36,0x40,0x0f,0x90,0x03,0xe4,0x00,0xf9,0x00,0x3c,0x40,0x0f,0x90,0x03,0xda,0x00 } },
+{  16, 0xea70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xa1,0x00,0xf8,0x00,0x32,0x00 } },
+{  16, 0xea80, 0, {0x0f,0x80,0x13,0xa0,0x00,0xc8,0x00,0x32,0x04,0x8c,0x80,0x03,0xa0,0xc0,0xf8,0x00 } },
+{  16, 0xea90, 0, {0x3a,0x00,0x0f,0x80,0x03,0x20,0x00,0xc0,0x09,0x32,0x00,0x4c,0x80,0x01,0x0a,0x04 } },
+{  16, 0xeaa0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xbe,0x00,0x20,0x80 } },
+{  16, 0xeab0, 0, {0x0b,0xe0,0x02,0x88,0x00,0xaa,0x00,0x03,0xa0,0x0a,0xe6,0x02,0xfa,0x00,0x8a,0x00 } },
+{  16, 0xeac0, 0, {0x32,0x80,0x0b,0xa0,0x02,0x28,0x00,0x8e,0x80,0xa3,0x80,0x28,0x20,0x02,0x8a,0x00 } },
+{  16, 0xead0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x6c,0x00,0xb3,0x48,0x20,0x40 } },
+{  16, 0xeae0, 0, {0x0b,0x10,0x02,0x0c,0x00,0x83,0x00,0x20,0xc0,0x08,0x34,0x82,0x8e,0x04,0x99,0x00 } },
+{  16, 0xeaf0, 0, {0x0a,0xc0,0x1b,0x30,0x02,0x0c,0x02,0x90,0x50,0x20,0x60,0x08,0x30,0x02,0x0a,0x00 } },
+{  16, 0xeb00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x11,0x1c,0x80,0xbd,0x0a,0x21,0x48 } },
+{  16, 0xeb10, 0, {0x0b,0x52,0x02,0x9c,0x40,0xa3,0xa0,0x20,0x80,0x0a,0x60,0x02,0xce,0x00,0x85,0x20 } },
+{  16, 0xeb20, 0, {0x21,0xc4,0x0b,0x7a,0x06,0x1e,0x80,0x95,0x20,0x21,0x90,0x08,0x70,0x02,0x28,0x00 } },
+{  16, 0xeb30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x08,0x1e,0x80,0xf7,0x80,0xb1,0x79 } },
+{  16, 0xeb40, 0, {0x0f,0xdb,0x02,0x3e,0x20,0xc7,0xa0,0xb1,0x60,0xcc,0x78,0x13,0x96,0x00,0xf1,0xf0 } },
+{  16, 0xeb50, 0, {0x39,0xe2,0x0f,0x7b,0x13,0x0f,0x00,0xd4,0xa0,0x31,0x60,0x2c,0x70,0x03,0x2a,0x02 } },
+{  16, 0xeb60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x15,0xac,0x00,0xf7,0x00,0x3e,0x40 } },
+{  16, 0xeb70, 0, {0x0f,0x90,0x03,0xed,0x80,0xfb,0x10,0x3e,0x40,0x0b,0xb0,0x23,0xec,0x00,0xf9,0x20 } },
+{  16, 0xeb80, 0, {0x3a,0xd8,0x0f,0xb0,0x0b,0xed,0x81,0xed,0x10,0x3e,0x80,0x0f,0x30,0x03,0xc2,0x06 } },
+{  16, 0xeb90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xbe,0x20,0xee,0x80,0x33,0x60 } },
+{  16, 0xeba0, 0, {0x0c,0xd8,0x83,0x1e,0x00,0x6f,0x80,0x33,0xe0,0x0f,0xb8,0x11,0x32,0x04,0xf5,0x80 } },
+{  16, 0xebb0, 0, {0x33,0xe0,0x0f,0xf8,0x83,0x2f,0x40,0xfe,0x80,0xb3,0xe0,0x0c,0xf8,0x03,0x10,0x00 } },
+{  16, 0xebc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x18,0x9c,0x00,0xbc,0x00,0xa1,0x44 } },
+{  16, 0xebd0, 0, {0x08,0x10,0x03,0x5c,0x00,0x8f,0x00,0x21,0x80,0x0b,0xea,0x22,0x1c,0x80,0xb5,0x01 } },
+{  16, 0xebe0, 0, {0x21,0xc0,0x0b,0xf0,0x02,0x1e,0x80,0xbe,0x00,0x23,0x80,0x2a,0x70,0x02,0x2a,0x04 } },
+{  16, 0xebf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x20,0xa7,0x00,0x23,0x40 } },
+{  16, 0xec00, 0, {0x0b,0x50,0x0a,0x3c,0x00,0xa7,0x00,0x25,0xc0,0x0a,0x43,0x02,0x10,0x00,0xb5,0x00 } },
+{  16, 0xec10, 0, {0x21,0xc0,0x0b,0x70,0x82,0x1c,0x80,0xb4,0x00,0x21,0xc0,0x08,0x70,0x02,0x04,0x00 } },
+{  16, 0xec20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x04,0x8e,0x04,0xb3,0x00,0x22,0x40 } },
+{  16, 0xec30, 0, {0x09,0x14,0x02,0x4c,0x00,0x83,0x00,0x20,0xc0,0x0b,0x24,0x82,0x04,0x00,0xb1,0x00 } },
+{  16, 0xec40, 0, {0x20,0xc0,0x8b,0x3a,0x02,0x2c,0x01,0xb0,0x00,0x20,0x80,0x0a,0x30,0x02,0x1a,0x04 } },
+{  16, 0xec50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0x9e,0x00,0xeb,0x04,0x33,0x40 } },
+{  16, 0xec60, 0, {0x2d,0xdc,0x03,0x1d,0x60,0xef,0x00,0x32,0x00,0xcf,0x9a,0x03,0x28,0x00,0xfd,0x00 } },
+{  16, 0xec70, 0, {0x33,0xc1,0x8b,0xfc,0x0b,0x3c,0x00,0xfc,0x00,0x32,0x80,0x0c,0x90,0x03,0x2a,0x04 } },
+{  16, 0xec80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xac,0x10,0xf8,0x00,0x3e,0x40 } },
+{  16, 0xec90, 0, {0x0e,0x98,0x23,0xac,0x04,0xfb,0x00,0x3c,0x00,0x0f,0x84,0x20,0xed,0x00,0xf9,0x00 } },
+{  16, 0xeca0, 0, {0x3e,0xc0,0x4f,0xb0,0x03,0xec,0x00,0xfd,0x00,0x3e,0x80,0x0f,0x90,0x03,0xe4,0x00 } },
+{  16, 0xecb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x10,0xfc,0x00,0xcf,0x80,0x33,0x40 } },
+{  16, 0xecc0, 0, {0x0c,0xd0,0x83,0xfc,0x00,0xef,0x00,0x3f,0x40,0x0c,0xf1,0x41,0x30,0x10,0xcd,0x00 } },
+{  16, 0xecd0, 0, {0x3f,0xc0,0x00,0x70,0x13,0x3c,0x00,0xe4,0x00,0xb1,0xd0,0x0c,0x10,0x03,0x20,0x04 } },
+{  16, 0xece0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa1,0x04,0x2c,0x00,0x8a,0xe4,0x2a,0x40 } },
+{  16, 0xecf0, 0, {0x28,0x90,0x02,0xec,0x00,0x8b,0x00,0x3e,0x02,0x0a,0x80,0x02,0x2c,0x82,0x89,0x04 } },
+{  16, 0xed00, 0, {0x2e,0xc1,0x0a,0xb0,0x0a,0x2c,0x00,0x89,0x02,0x22,0xf2,0x2a,0x98,0x02,0x20,0x00 } },
+{  16, 0xed10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x02,0x80,0x14,0x2a,0x40 } },
+{  16, 0xed20, 0, {0x08,0x90,0x02,0xec,0x08,0xab,0x04,0x2e,0x84,0x08,0x10,0x82,0x80,0x10,0x89,0x03 } },
+{  16, 0xed30, 0, {0x2c,0xc0,0x4a,0xb0,0x22,0x2c,0x00,0xaa,0x00,0x22,0x80,0x08,0x91,0x02,0x20,0x00 } },
+{  16, 0xed40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x2c,0x00,0x80,0x00,0x28,0x40 } },
+{  16, 0xed50, 0, {0x08,0x11,0x02,0xec,0x00,0x83,0x00,0x2c,0x81,0x0a,0x00,0x5a,0x88,0x00,0x01,0x00 } },
+{  16, 0xed60, 0, {0x2c,0xc0,0x0a,0x30,0x02,0x0c,0x00,0x82,0x00,0x20,0x80,0x0a,0x10,0x02,0x02,0x01 } },
+{  16, 0xed70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xc9,0x00,0x3a,0x40 } },
+{  16, 0xed80, 0, {0x0c,0xd4,0x03,0xfc,0x00,0xeb,0x00,0x3e,0x40,0x0c,0x92,0x03,0xa0,0x00,0x4d,0x00 } },
+{  16, 0xed90, 0, {0x3f,0xc0,0x0e,0xf0,0x33,0x3c,0x80,0xe8,0x00,0x32,0xc0,0x0c,0x90,0x03,0x20,0x03 } },
+{  16, 0xeda0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x11,0xfc,0x00,0xfc,0x00,0x3d,0x40 } },
+{  16, 0xedb0, 0, {0x0f,0x50,0x03,0xfc,0x02,0x3f,0x04,0x3b,0x01,0x4f,0xc4,0x13,0x70,0x00,0xfd,0x00 } },
+{  16, 0xedc0, 0, {0x3f,0xc0,0x1f,0xf0,0x01,0xfc,0x40,0xfc,0x00,0x3f,0xc0,0x0f,0xd0,0x13,0xe8,0x06 } },
+{  16, 0xedd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf8,0xe0,0xff,0x80,0x3d,0xc0 } },
+{  16, 0xede0, 0, {0x0d,0xf3,0x82,0xf0,0x80,0xff,0x40,0x31,0xcb,0x0c,0xf3,0x03,0xfd,0x04,0xef,0xc1 } },
+{  16, 0xedf0, 0, {0x33,0xe0,0x0f,0x79,0x03,0xfe,0x00,0xcf,0x42,0x33,0xf0,0x4c,0xf8,0x03,0x30,0x00 } },
+{  16, 0xee00, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x10,0xe9,0x08,0xb9,0x81,0x2f,0xf0 } },
+{  16, 0xee10, 0, {0x08,0xf4,0x52,0xe9,0x20,0xbf,0x40,0x23,0xf0,0x0a,0xf3,0x02,0xfd,0x08,0x8b,0x00 } },
+{  16, 0xee20, 0, {0x36,0xe0,0x0b,0x80,0x22,0xe8,0x80,0x8f,0x40,0x22,0xc0,0x08,0xb0,0x82,0x30,0x04 } },
+{  16, 0xee30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xcc,0x00,0xb1,0x80,0x2c,0xc5 } },
+{  16, 0xee40, 0, {0x09,0x32,0x42,0xc8,0xc0,0xb3,0x31,0x20,0xc1,0x08,0x32,0x02,0xcc,0xd4,0xbb,0x20 } },
+{  16, 0xee50, 0, {0x68,0xc0,0x0b,0x30,0x02,0xcc,0x20,0x93,0x60,0x20,0x88,0x08,0x32,0x02,0x32,0x01 } },
+{  16, 0xee60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x15,0xa0,0x00,0xbb,0x80,0x2e,0xc0 } },
+{  16, 0xee70, 0, {0x08,0xb0,0x02,0xea,0x00,0xbb,0x00,0x62,0xc1,0x0a,0xb0,0x02,0xcc,0x00,0xab,0x00 } },
+{  16, 0xee80, 0, {0x2e,0xc0,0x0b,0xa0,0x00,0xe8,0x00,0x83,0x00,0x22,0xc1,0x08,0x30,0x02,0x30,0x04 } },
+{  16, 0xee90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xe8,0x90,0xfb,0x80,0x3e,0xc0 } },
+{  16, 0xeea0, 0, {0x0d,0xb0,0x03,0xe2,0x10,0xfb,0x00,0x32,0xc0,0x4c,0xb0,0x13,0xec,0x00,0xe9,0x54 } },
+{  16, 0xeeb0, 0, {0x3a,0xc0,0x0f,0xb0,0x03,0xe6,0x00,0xcb,0x00,0xb2,0x40,0x0c,0xb0,0x03,0x04,0x04 } },
+{  16, 0xeec0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb8,0x00,0xff,0x00,0x3f,0xc0 } },
+{  16, 0xeed0, 0, {0x8f,0xf0,0x03,0xf0,0x00,0xf7,0x02,0xbf,0xc1,0x0f,0xf0,0x23,0xfc,0x00,0xdf,0x06 } },
+{  16, 0xeee0, 0, {0x37,0xc0,0x8f,0xc9,0x07,0xfa,0x92,0xff,0x04,0x3f,0x50,0x2f,0xf0,0x03,0xf8,0x00 } },
+{  16, 0xeef0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x10,0xac,0x00,0xc9,0x00,0x3e,0xc2 } },
+{  16, 0xef00, 0, {0x0e,0xb0,0x23,0xe4,0x00,0xeb,0x00,0x3a,0xc8,0x0e,0xb0,0x03,0xec,0x00,0xf9,0x00 } },
+{  16, 0xef10, 0, {0x3e,0xc0,0x0f,0xb4,0x03,0xa4,0x00,0xfb,0x00,0x3e,0x80,0x0f,0xb0,0x83,0xd0,0x04 } },
+{  16, 0xef20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x28,0x00,0x8b,0x74,0x2d,0xc0 } },
+{  16, 0xef30, 0, {0x08,0xf0,0x02,0xe4,0x00,0x8f,0x00,0x21,0xf0,0x08,0xf0,0x02,0xfc,0x10,0xd3,0x00 } },
+{  16, 0xef40, 0, {0x2e,0xc0,0x0b,0x90,0x12,0x2c,0x00,0xef,0x00,0x2e,0xc0,0x0b,0xb6,0x02,0xf6,0x00 } },
+{  16, 0xef50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x05,0x48,0x00,0xa3,0x00,0x2c,0xc4 } },
+{  16, 0xef60, 0, {0x0a,0x30,0x02,0xc0,0x00,0xa3,0x00,0x68,0xf0,0x0a,0x30,0x12,0xcc,0x04,0xa2,0x00 } },
+{  16, 0xef70, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xec,0x00,0xb3,0x01,0x2e,0xc0,0x0b,0x34,0x02,0xf8,0x00 } },
+{  16, 0xef80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x01,0x0c,0x00,0x87,0x80,0x2d,0xe8 } },
+{  16, 0xef90, 0, {0x08,0x78,0x42,0xda,0x00,0x87,0x80,0x25,0xe0,0x08,0x79,0x02,0xce,0x00,0x96,0x80 } },
+{  16, 0xefa0, 0, {0x2d,0xe0,0x0b,0xd9,0x02,0xde,0x00,0xa7,0x80,0x2d,0xe0,0x0b,0x78,0x02,0xfc,0x00 } },
+{  16, 0xefb0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x40,0xe3,0x10,0x3c,0xc0 } },
+{  16, 0xefc0, 0, {0x0a,0x38,0x03,0xe8,0x00,0xeb,0x00,0x38,0xc2,0x0a,0x30,0x03,0xcc,0x00,0xe3,0x40 } },
+{  16, 0xefd0, 0, {0x3c,0xc0,0x0f,0x34,0x03,0xcd,0x00,0xf3,0x20,0x3c,0x88,0x0f,0x30,0x03,0xd2,0x02 } },
+{  16, 0xefe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb4,0x80,0xff,0x04,0x3f,0xc8 } },
+{  16, 0xeff0, 0, {0x0f,0xf0,0x83,0xf8,0x40,0xff,0x18,0x3b,0xc0,0x0f,0xf4,0x83,0xfc,0x00,0xee,0x02 } },
+{  16, 0xf000, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0x3c,0x00,0xef,0x08,0x3f,0x80,0x0f,0xf0,0x13,0xd0,0x06 } },
+{  16, 0xf010, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xe8,0x00,0xcb,0x00,0x3e,0xf2 } },
+{  16, 0xf020, 0, {0x4d,0xb2,0x13,0xe8,0x04,0xcb,0x01,0x32,0xf8,0x4d,0xb2,0x13,0x6d,0x20,0xf8,0x00 } },
+{  16, 0xf030, 0, {0x3e,0xc0,0x0f,0x30,0x03,0x24,0x00,0xfb,0x00,0x3e,0x40,0x8f,0xb8,0x03,0x2a,0x00 } },
+{  16, 0xf040, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x11,0x8c,0x00,0x86,0x00,0x2c,0xc0 } },
+{  16, 0xf050, 0, {0x08,0x73,0x02,0xd8,0x12,0x87,0x30,0x20,0xcb,0x08,0xf2,0x02,0x1d,0x05,0xb5,0x00 } },
+{  16, 0xf060, 0, {0x2d,0xc0,0x0b,0x60,0x03,0x50,0x10,0xb7,0x09,0x2d,0xc0,0x0b,0xf0,0x02,0x32,0x04 } },
+{  16, 0xf070, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x9e,0x00,0x87,0x80,0x2d,0xe4 } },
+{  16, 0xf080, 0, {0x09,0x7a,0x02,0xce,0x01,0x87,0x80,0x21,0xec,0x09,0x78,0x02,0x5e,0x80,0xb7,0xc0 } },
+{  16, 0xf090, 0, {0x2d,0xe0,0x0b,0xf8,0x02,0x1e,0x00,0xb7,0xa0,0x2d,0x60,0x0b,0x78,0x02,0x20,0x00 } },
+{  16, 0xf0a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xee,0x00,0x82,0x80,0x2c,0xc0 } },
+{  16, 0xf0b0, 0, {0x08,0x30,0x02,0xec,0x00,0x83,0x00,0xa0,0xc0,0x08,0x30,0x02,0x0c,0x00,0xb3,0x80 } },
+{  16, 0xf0c0, 0, {0x2c,0xc1,0x0b,0x30,0x02,0x4e,0x00,0xb3,0x00,0x2c,0xf1,0x0b,0x30,0x0a,0x12,0x04 } },
+{  16, 0xf0d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xba,0x80,0xc6,0x00,0x3e,0x80 } },
+{  16, 0xf0e0, 0, {0x0d,0xa0,0x03,0xf8,0x40,0xca,0x00,0x32,0x80,0x0d,0xa0,0x13,0x68,0x00,0xfe,0x02 } },
+{  16, 0xf0f0, 0, {0x7e,0x80,0x0f,0xed,0x83,0x39,0x10,0xfa,0x00,0x3f,0x8c,0x0f,0xa0,0x03,0x3a,0x04 } },
+{  16, 0xf100, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x12,0xf8,0x90,0x3e,0x00 } },
+{  16, 0xf110, 0, {0x0f,0x80,0x03,0xe0,0x00,0xf8,0x05,0x3e,0x00,0x0e,0x00,0x03,0xe0,0x00,0xf8,0x80 } },
+{  16, 0xf120, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x60,0xf8,0x00,0x7e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xf130, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xc9,0x80,0x32,0x64 } },
+{  16, 0xf140, 0, {0x0f,0x90,0x43,0xe4,0x06,0xc1,0x04,0x3a,0x40,0x0f,0x90,0x03,0xe4,0x00,0xe9,0x00 } },
+{  16, 0xf150, 0, {0x32,0x40,0x0f,0x90,0x03,0x24,0x00,0xc1,0x01,0x32,0x40,0x0c,0x90,0x03,0xc2,0x04 } },
+{  16, 0xf160, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0xc0,0x22,0x40 } },
+{  16, 0xf170, 0, {0x0b,0x90,0x02,0x24,0x00,0x89,0x00,0x22,0x50,0x1b,0x90,0x22,0x24,0x00,0x81,0x00 } },
+{  16, 0xf180, 0, {0x22,0x40,0x0b,0x90,0x22,0x24,0x08,0xc9,0x00,0x20,0x40,0x08,0x94,0x02,0xe0,0x00 } },
+{  16, 0xf190, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x99,0x20,0x22,0x40 } },
+{  16, 0xf1a0, 0, {0x0b,0x10,0x02,0xa4,0x00,0x89,0x00,0x2a,0x58,0x0b,0x90,0x02,0x84,0x00,0xa9,0x00 } },
+{  16, 0xf1b0, 0, {0x22,0x40,0x0b,0x10,0x0a,0x04,0x00,0x99,0x02,0x22,0xc1,0x08,0x90,0x82,0xc6,0x00 } },
+{  16, 0xf1c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x91,0x02,0xa0,0xc8 } },
+{  16, 0xf1d0, 0, {0x0b,0x12,0x02,0x04,0x80,0x81,0x22,0x20,0x48,0x9b,0x12,0x02,0x04,0x90,0x89,0x01 } },
+{  16, 0xf1e0, 0, {0x20,0x40,0x0b,0x10,0x02,0x04,0x02,0x81,0x22,0x22,0x40,0x08,0x10,0x02,0xc2,0x01 } },
+{  16, 0xf1f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x42,0xda,0x01,0x32,0x01 } },
+{  16, 0xf200, 0, {0x0f,0x85,0x03,0xa1,0x40,0xc0,0x50,0x3a,0x01,0x8b,0x85,0x23,0xa1,0x44,0xe8,0x50 } },
+{  16, 0xf210, 0, {0xb2,0x00,0x0f,0x85,0x03,0x21,0x48,0xd8,0x51,0x32,0x14,0x2c,0x85,0x03,0xee,0x03 } },
+{  16, 0xf220, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf5,0x00,0xed,0x02,0x3e,0x44 } },
+{  16, 0xf230, 0, {0x0f,0x91,0x03,0xf4,0x40,0xf9,0x10,0x3e,0x44,0x0f,0x91,0x03,0xe4,0x40,0xfd,0x00 } },
+{  16, 0xf240, 0, {0x3e,0x40,0x0f,0xd0,0x03,0xf4,0x00,0xe9,0x10,0xbf,0x40,0x0f,0x90,0x03,0x66,0x06 } },
+{  16, 0xf250, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0x21,0xc5,0x00,0x33,0x68 } },
+{  16, 0xf260, 0, {0x0f,0x9a,0x03,0x6f,0x88,0xc9,0xc0,0x33,0x68,0x0c,0x9e,0x03,0x27,0x80,0xd9,0x40 } },
+{  16, 0xf270, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc5,0x10,0xd9,0xe8,0x36,0x50,0x0c,0xd0,0x03,0xe6,0x00 } },
+{  16, 0xf280, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x08,0x88,0x00,0x82,0x00 } },
+{  16, 0xf290, 0, {0x0b,0x8e,0x82,0xeb,0xc8,0x88,0xe0,0x22,0x00,0x28,0x88,0x42,0xa2,0x80,0x8a,0x80 } },
+{  16, 0xf2a0, 0, {0x22,0x00,0x0b,0xaa,0x02,0xe2,0x00,0x88,0xc0,0x22,0xa9,0x08,0x8a,0x03,0x8e,0x04 } },
+{  16, 0xf2b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc4,0x00,0x81,0x00,0x20,0xd0 } },
+{  16, 0xf2c0, 0, {0x0b,0x11,0x32,0x84,0x84,0x81,0x60,0x60,0x50,0x08,0x16,0x06,0x05,0x00,0x91,0x20 } },
+{  16, 0xf2d0, 0, {0x20,0x40,0x0b,0x10,0x82,0xe4,0x09,0x91,0x20,0x24,0x40,0x08,0x10,0xc2,0xd2,0x01 } },
+{  16, 0xf2e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x04,0x89,0x04,0x22,0x40 } },
+{  16, 0xf2f0, 0, {0x0b,0x90,0x02,0xc4,0x00,0xa9,0x00,0x22,0x41,0x00,0x90,0x02,0xa4,0x00,0x81,0x00 } },
+{  16, 0xf300, 0, {0x22,0x40,0x0b,0x92,0x22,0xe5,0x80,0x99,0x01,0x22,0x61,0x08,0x90,0x02,0x86,0x04 } },
+{  16, 0xf310, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x14,0xa5,0x82,0x81,0x90,0x32,0x40 } },
+{  16, 0xf320, 0, {0x0f,0x90,0x13,0x67,0x02,0xc9,0x00,0x32,0x40,0x0c,0x90,0x23,0x24,0x04,0xd9,0xc0 } },
+{  16, 0xf330, 0, {0xb2,0x40,0x0f,0x9c,0x03,0xe6,0x00,0xd9,0x00,0x36,0x50,0x0c,0x90,0x03,0xe8,0x04 } },
+{  16, 0xf340, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0xa6,0x80,0xf9,0x00,0x3e,0x40 } },
+{  16, 0xf350, 0, {0x0f,0x90,0x03,0xe7,0x00,0xd9,0x00,0xbc,0x42,0x0f,0x90,0x53,0xe4,0x04,0xf9,0x10 } },
+{  16, 0xf360, 0, {0x3e,0x40,0x0f,0x98,0x03,0xe6,0x04,0xe1,0x00,0x3e,0x40,0x2f,0x90,0x03,0xda,0x00 } },
+{  16, 0xf370, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0x81,0x10,0x48,0x10,0x32,0x08 } },
+{  16, 0xf380, 0, {0x0c,0x80,0x0f,0x21,0x02,0xc8,0x00,0x3a,0x04,0x0f,0x80,0x07,0x60,0x00,0xf8,0x40 } },
+{  16, 0xf390, 0, {0xb2,0x00,0x0f,0x84,0x0b,0x20,0x00,0xd8,0x00,0x36,0x10,0x0c,0x80,0x03,0xca,0x04 } },
+{  16, 0xf3a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x04,0x28,0x04,0x8e,0x80,0x23,0x80 } },
+{  16, 0xf3b0, 0, {0x08,0xa0,0x42,0x28,0x00,0x8a,0x00,0x23,0xa0,0x4b,0xa0,0x02,0xe8,0x00,0xba,0x00 } },
+{  16, 0xf3c0, 0, {0x76,0x80,0x0b,0xa0,0x02,0x08,0x00,0x8a,0x00,0x32,0x80,0x08,0xe0,0x03,0xca,0x00 } },
+{  16, 0xf3d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x82,0x00,0x20,0xd0 } },
+{  16, 0xf3e0, 0, {0x08,0x30,0x02,0x0c,0x00,0x9b,0x00,0x28,0xc0,0x1a,0xb0,0x02,0x6c,0x00,0xb3,0x02 } },
+{  16, 0xf3f0, 0, {0x20,0xc0,0x0b,0x30,0x02,0x0c,0x00,0xa3,0x00,0x22,0xc0,0x28,0x34,0x82,0xca,0x00 } },
+{  16, 0xf400, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1c,0x00,0x87,0x00,0x20,0xe0 } },
+{  16, 0xf410, 0, {0x08,0x78,0x02,0x0c,0x00,0x97,0x20,0x25,0xc0,0x0b,0x71,0x02,0xdc,0x81,0xb7,0x20 } },
+{  16, 0xf420, 0, {0x21,0xc0,0x0b,0x7a,0x42,0x3c,0x80,0x87,0x20,0x21,0xc0,0x08,0x70,0x02,0xe8,0x00 } },
+{  16, 0xf430, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x08,0x0e,0x82,0xc7,0x80,0xb1,0xe0 } },
+{  16, 0xf440, 0, {0x2c,0xfa,0x06,0x1e,0x08,0xd3,0xb1,0x39,0x60,0x4e,0x78,0x12,0x5e,0xa0,0xff,0xf0 } },
+{  16, 0xf450, 0, {0x21,0xe0,0x0f,0xf8,0x03,0x1f,0x08,0xe3,0xa0,0x33,0xe0,0x0c,0x68,0x03,0xea,0x02 } },
+{  16, 0xf460, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x40,0xfb,0x00,0x3e,0xc0 } },
+{  16, 0xf470, 0, {0x0f,0xb2,0x03,0xed,0xa8,0xeb,0x10,0x3a,0x80,0x0f,0xb0,0xc3,0xec,0x40,0xfb,0x00 } },
+{  16, 0xf480, 0, {0x3e,0xc0,0x0f,0xb0,0x83,0xec,0x80,0xeb,0x70,0xbe,0xc4,0x0f,0xb0,0x03,0x82,0x06 } },
+{  16, 0xf490, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x00,0xce,0x80,0xb3,0x60 } },
+{  16, 0xf4a0, 0, {0x0f,0xfc,0x83,0x7e,0x20,0xef,0xb0,0x3b,0xe0,0x0f,0xb8,0x03,0x3e,0x00,0xcf,0x81 } },
+{  16, 0xf4b0, 0, {0x3f,0xe0,0x8f,0xf8,0x83,0xef,0x40,0xff,0xc2,0x33,0xe1,0x0c,0xf8,0x03,0xd0,0x00 } },
+{  16, 0xf4c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x82,0x87,0x18,0x21,0x80 } },
+{  16, 0xf4d0, 0, {0x0b,0x30,0x02,0x1c,0x60,0xd7,0x10,0x21,0xd0,0x0b,0x7b,0x02,0x3c,0x00,0xd7,0x00 } },
+{  16, 0xf4e0, 0, {0x2d,0xc0,0x0b,0x70,0x02,0xde,0x00,0xbf,0x00,0xa3,0xc4,0x08,0x70,0x03,0xaa,0x04 } },
+{  16, 0xf4f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x11,0x87,0x00,0x21,0xc0 } },
+{  16, 0xf500, 0, {0x0b,0x30,0x02,0x1c,0x00,0x93,0x20,0x69,0xc0,0x0b,0x70,0x02,0x1c,0x00,0x87,0x00 } },
+{  16, 0xf510, 0, {0x2d,0xc0,0x0b,0x71,0x02,0xdc,0x20,0xb7,0x10,0x21,0xc0,0x08,0x60,0x02,0x84,0x00 } },
+{  16, 0xf520, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xcd,0x00,0x83,0x40,0x20,0xc0 } },
+{  16, 0xf530, 0, {0x4b,0x30,0x02,0x0c,0x01,0x83,0x00,0x20,0xc0,0x0b,0x30,0x02,0x0c,0x00,0x93,0x80 } },
+{  16, 0xf540, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x01,0xb3,0x00,0x20,0xc0,0x08,0x30,0x22,0x98,0x04 } },
+{  16, 0xf550, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbf,0x20,0xca,0xc0,0x32,0x80 } },
+{  16, 0xf560, 0, {0x0f,0xf0,0x03,0x3e,0x00,0x9f,0x00,0x3a,0x80,0x0f,0xf0,0x0b,0x3c,0x00,0xcf,0x98 } },
+{  16, 0xf570, 0, {0x3e,0xc0,0x0f,0xf6,0x03,0xff,0x00,0xff,0x00,0x31,0xe0,0x2c,0xb0,0x03,0xae,0x04 } },
+{  16, 0xf580, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xcc,0x80,0xfb,0x00,0x3e,0x50 } },
+{  16, 0xf590, 0, {0x0f,0xb0,0x03,0xac,0x02,0xfb,0x00,0x7e,0x50,0x0f,0xb0,0x03,0xec,0x00,0xfb,0x00 } },
+{  16, 0xf5a0, 0, {0x3e,0xc0,0x0f,0xb2,0x03,0xec,0x20,0xf3,0x00,0x3e,0xc6,0x0f,0x90,0x03,0xa0,0x00 } },
+{  16, 0xf5b0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x02,0xcf,0x98,0x73,0xc8 } },
+{  16, 0xf5c0, 0, {0x0f,0x70,0x03,0x3c,0x00,0xff,0x00,0x33,0x28,0x0f,0xb0,0x02,0x1c,0x00,0x4f,0x00 } },
+{  16, 0xf5d0, 0, {0x3f,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x01,0x33,0xc0,0x0c,0xe4,0x03,0xe4,0x04 } },
+{  16, 0xf5e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x6c,0x00,0x83,0x80,0xa2,0xf8 } },
+{  16, 0xf5f0, 0, {0x0b,0xb0,0x42,0x2c,0x00,0xbb,0x00,0x32,0x10,0x0f,0xb0,0x03,0x6c,0x04,0xab,0x00 } },
+{  16, 0xf600, 0, {0x2e,0xc0,0x0b,0xb0,0x12,0xec,0x04,0xeb,0x00,0x22,0xc0,0x4a,0x94,0x82,0xe0,0x00 } },
+{  16, 0xf610, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x6c,0x00,0x8a,0x00,0x22,0x00 } },
+{  16, 0xf620, 0, {0x0b,0xb0,0x02,0x2c,0x00,0xb3,0x00,0xa2,0xc0,0x0b,0x30,0x02,0xac,0x00,0xab,0x04 } },
+{  16, 0xf630, 0, {0x2e,0xc0,0x0b,0xb0,0x42,0xec,0x00,0xbb,0x00,0x22,0xc0,0x08,0xb0,0x22,0xe0,0x00 } },
+{  16, 0xf640, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0c,0x00,0x8b,0x01,0x20,0x00 } },
+{  16, 0xf650, 0, {0x0b,0x30,0x06,0x0c,0x00,0xb3,0x00,0x20,0xc0,0x0a,0x32,0x0a,0xcc,0x00,0xa3,0x00 } },
+{  16, 0xf660, 0, {0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x00,0xa3,0x00,0x22,0xc0,0x4a,0x00,0x12,0xc2,0x01 } },
+{  16, 0xf670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x6c,0x00,0x8b,0x04,0x22,0xc0 } },
+{  16, 0xf680, 0, {0x0f,0xf1,0x03,0x1c,0x00,0xff,0x04,0x32,0xc0,0x0b,0xf2,0x03,0xbc,0x00,0xef,0x00 } },
+{  16, 0xf690, 0, {0x3e,0xc0,0x07,0xf0,0x03,0xfc,0x80,0xff,0x00,0xb2,0xc0,0x0c,0xa0,0x03,0xe0,0x03 } },
+{  16, 0xf6a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xdc,0x00,0xf5,0x00,0x3f,0xc0 } },
+{  16, 0xf6b0, 0, {0x0f,0xf0,0x03,0xfc,0x01,0xff,0x02,0x3b,0xc0,0x0f,0xf1,0x03,0x7c,0x00,0xff,0x00 } },
+{  16, 0xf6c0, 0, {0x3f,0xc0,0x0f,0xf0,0x13,0xfc,0x40,0xef,0x00,0x3f,0xc0,0x0f,0xc0,0x03,0xe8,0x06 } },
+{  16, 0xf6d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xf2,0x40,0xcc,0x80,0x37,0x20 } },
+{  16, 0xf6e0, 0, {0x0c,0xd8,0x03,0xb0,0x44,0xfc,0x08,0x3f,0x0e,0x0f,0xc1,0x03,0xfc,0x00,0xcc,0x94 } },
+{  16, 0xf6f0, 0, {0x3f,0x0a,0x2e,0xc4,0x03,0x7d,0x80,0xcf,0x10,0x3f,0xc0,0x0f,0xc0,0x83,0x30,0x00 } },
+{  16, 0xf700, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0xe0,0x90,0x88,0x02,0x22,0x81 } },
+{  16, 0xf710, 0, {0x08,0x92,0x13,0xa4,0x40,0x3b,0x60,0x22,0x18,0x0b,0x81,0x02,0xfc,0xd4,0x81,0x00 } },
+{  16, 0xf720, 0, {0x3a,0xb0,0x0a,0x94,0x02,0x3d,0x40,0xaf,0x63,0x2f,0xdf,0x0b,0x98,0x00,0x20,0x04 } },
+{  16, 0xf730, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xe0,0x00,0x88,0x00,0x20,0x40 } },
+{  16, 0xf740, 0, {0x88,0x30,0x82,0xc0,0x00,0xb0,0x08,0x28,0x80,0x0a,0x10,0x02,0xcc,0x20,0x80,0x01 } },
+{  16, 0xf750, 0, {0x2c,0x40,0x1b,0x06,0x02,0x8c,0x90,0x93,0x60,0x68,0xc0,0x4a,0x00,0x42,0x22,0x01 } },
+{  16, 0xf760, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xa0,0x02,0x88,0x00,0x22,0xc0 } },
+{  16, 0xf770, 0, {0x08,0xb0,0x02,0xe4,0x20,0xbb,0x88,0x26,0x98,0x0b,0x80,0x42,0xcc,0x18,0x8a,0x00 } },
+{  16, 0xf780, 0, {0x2e,0xc2,0x1b,0x98,0x02,0xac,0x00,0xab,0x00,0x2e,0xc0,0x0b,0x98,0x82,0x30,0x04 } },
+{  16, 0xf790, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0xe3,0xc0,0xcb,0x02,0x32,0x00 } },
+{  16, 0xf7a0, 0, {0x2c,0x80,0x03,0xae,0x08,0xb9,0x00,0x3e,0x70,0x0f,0xb9,0x03,0xec,0x02,0x48,0x48 } },
+{  16, 0xf7b0, 0, {0x3c,0xc0,0x0f,0x8c,0x93,0xec,0x00,0xdb,0x00,0x1a,0xc0,0x0e,0xac,0x03,0x10,0x04 } },
+{  16, 0xf7c0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb2,0x00,0xff,0x00,0xbb,0x80 } },
+{  16, 0xf7d0, 0, {0x0f,0xc0,0x43,0xb6,0x40,0xbd,0x00,0x3b,0x60,0x0f,0xe8,0x03,0xfc,0x00,0xff,0x94 } },
+{  16, 0xf7e0, 0, {0x3b,0xe4,0x0e,0x60,0x0f,0x6c,0x08,0xef,0x01,0x3f,0xc0,0x0f,0x60,0x03,0xf8,0x00 } },
+{  16, 0xf7f0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa1,0x00,0xfb,0x00,0x3e,0x60 } },
+{  16, 0xf800, 0, {0x0f,0xa0,0x03,0xed,0x00,0xf9,0x40,0x3a,0x00,0x0f,0x90,0x03,0xec,0x02,0xc9,0x04 } },
+{  16, 0xf810, 0, {0x32,0xd0,0x0f,0x90,0x03,0x2c,0x08,0xdb,0x00,0xb6,0xc0,0x0d,0xb4,0x03,0xd0,0x04 } },
+{  16, 0xf820, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x00,0x00,0xb3,0x89,0x2e,0xe0 } },
+{  16, 0xf830, 0, {0x0b,0xa4,0x03,0xa4,0x01,0xb9,0x00,0x2e,0x01,0x0b,0x90,0x42,0xfc,0x10,0x89,0x50 } },
+{  16, 0xf840, 0, {0xa2,0xc0,0x8d,0xb4,0x02,0x3c,0x44,0x8f,0x00,0x23,0xc0,0x08,0xb0,0x02,0xf2,0x00 } },
+{  16, 0xf850, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x04,0x0c,0x00,0xb0,0x80,0x2e,0x00 } },
+{  16, 0xf860, 0, {0x0b,0x12,0x02,0xc8,0x00,0xba,0x00,0x2c,0xc0,0x0b,0x20,0x02,0xcc,0x00,0xa2,0x00 } },
+{  16, 0xf870, 0, {0x20,0x00,0x2b,0x2d,0x9a,0x2e,0x42,0x83,0x00,0x28,0xc0,0x08,0x20,0x02,0xf8,0x00 } },
+{  16, 0xf880, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x1e,0x04,0xb4,0x80,0x2d,0xa0 } },
+{  16, 0xf890, 0, {0x0b,0x58,0x02,0x92,0x00,0xb6,0x80,0x2d,0xe0,0x0b,0x68,0x02,0xde,0x40,0xa6,0x80 } },
+{  16, 0xf8a0, 0, {0x21,0x24,0x29,0x48,0x02,0x1e,0x80,0x87,0x80,0x69,0xe0,0x08,0x61,0x02,0xc8,0x00 } },
+{  16, 0xf8b0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x18,0x0c,0x00,0xf0,0x30,0x3c,0x4c } },
+{  16, 0xf8c0, 0, {0x0f,0x32,0x03,0xc8,0x80,0xb2,0x00,0x38,0x80,0x0f,0x1b,0x03,0xec,0x00,0xe0,0x30 } },
+{  16, 0xf8d0, 0, {0x30,0x04,0x0f,0xb1,0x03,0x0e,0x85,0xcb,0x00,0x3a,0xc0,0x0c,0x31,0x03,0xd2,0x02 } },
+{  16, 0xf8e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1c,0xbc,0x00,0xfc,0x11,0x3f,0xc4 } },
+{  16, 0xf8f0, 0, {0x0f,0xb8,0x13,0xb0,0x04,0xfe,0x02,0x3f,0x80,0x0f,0xc0,0x03,0xfd,0x00,0xdf,0x12 } },
+{  16, 0xf900, 0, {0x1d,0x04,0x0f,0xd0,0x43,0xbc,0x01,0xef,0x10,0x33,0xc4,0x0e,0xf3,0x03,0xd0,0x06 } },
+{  16, 0xf910, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xee,0x00,0xcb,0x00,0x3e,0x00 } },
+{  16, 0xf920, 0, {0x0f,0x80,0x03,0x28,0x00,0xf8,0x00,0x3e,0x40,0x3d,0xb0,0x03,0xef,0x08,0xc9,0x00 } },
+{  16, 0xf930, 0, {0x3a,0x00,0x0c,0xa0,0x03,0xec,0x98,0xfb,0x20,0x32,0xd2,0x0c,0xa8,0x03,0x2a,0x02 } },
+{  16, 0xf940, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0x87,0x01,0x2d,0x80 } },
+{  16, 0xf950, 0, {0x0b,0x40,0x42,0x1c,0x04,0x37,0x00,0xa1,0x40,0x08,0x60,0x02,0xcc,0x80,0x87,0x00 } },
+{  16, 0xf960, 0, {0x2d,0x80,0x2e,0x70,0x02,0xdc,0xa9,0xb7,0x28,0x21,0xd0,0x08,0x70,0x02,0x12,0x00 } },
+{  16, 0xf970, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xbe,0x02,0x87,0x80,0x2d,0x60 } },
+{  16, 0xf980, 0, {0x4b,0xe8,0x02,0x5a,0x01,0xb4,0x88,0x28,0xe0,0x88,0x78,0xc2,0xde,0x52,0x86,0xc0 } },
+{  16, 0xf990, 0, {0x29,0x60,0x08,0x68,0x02,0xde,0x40,0xb3,0x92,0xe1,0xe8,0x28,0x28,0x02,0x70,0x00 } },
+{  16, 0xf9a0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x14,0xcc,0x00,0x8b,0x80,0x2e,0xc0 } },
+{  16, 0xf9b0, 0, {0x0b,0x20,0x02,0x4d,0x80,0x9b,0x20,0x20,0xe0,0x08,0x38,0x02,0xcc,0x00,0x83,0x80 } },
+{  16, 0xf9c0, 0, {0x2c,0xc0,0x0a,0xb0,0x02,0xcc,0x08,0xb3,0x00,0x20,0xc0,0x08,0x31,0x02,0x52,0x04 } },
+{  16, 0xf9d0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x05,0xa8,0x00,0xca,0xe0,0x3e,0x80 } },
+{  16, 0xf9e0, 0, {0x1f,0xa4,0x0b,0x79,0x00,0xfe,0x00,0x3f,0x82,0x1d,0xe0,0x03,0xe8,0x00,0xce,0x40 } },
+{  16, 0xf9f0, 0, {0x3b,0x88,0x2c,0xe4,0x03,0xe8,0x01,0xfa,0x00,0x32,0x80,0x0c,0xe8,0x03,0x7a,0x04 } },
+{  16, 0xfa00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0xa0,0x00,0xf8,0x09,0x3e,0x00 } },
+{  16, 0xfa10, 0, {0x8f,0xc0,0x83,0xa0,0x18,0xf8,0x00,0x3c,0x20,0x0f,0x88,0x03,0xe0,0x00,0xf8,0x08 } },
+{  16, 0xfa20, 0, {0x3e,0x20,0x0e,0x80,0x83,0xe1,0x01,0xf0,0x00,0x3c,0x00,0x0f,0x80,0x0b,0x92,0x00 } },
+{  16, 0xfa30, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xa4,0x00,0xf9,0x42,0x32,0x40 } },
+{  16, 0xfa40, 0, {0x4c,0x98,0x03,0x04,0x00,0xc9,0x00,0x3a,0x40,0x0f,0x90,0x23,0x24,0x00,0xb9,0x81 } },
+{  16, 0xfa50, 0, {0x3c,0x40,0x0c,0x92,0x03,0x24,0x00,0xf9,0x05,0x32,0x40,0x6c,0x90,0xc3,0xc2,0x04 } },
+{  16, 0xfa60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x24,0x14,0xb9,0x00,0xa2,0x54 } },
+{  16, 0xfa70, 0, {0x08,0x9b,0x1a,0x24,0x02,0x89,0x00,0x22,0x40,0x28,0x90,0x02,0xa4,0x00,0xb9,0x90 } },
+{  16, 0xfa80, 0, {0x2e,0x40,0x28,0x9c,0x82,0x25,0x04,0xb9,0x00,0x22,0x40,0x08,0x98,0x12,0xe0,0x00 } },
+{  16, 0xfa90, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xad,0x00,0x23,0x40 } },
+{  16, 0xfaa0, 0, {0x08,0x50,0x02,0x64,0x00,0x89,0x00,0x2a,0x40,0x08,0x10,0x02,0x64,0x00,0xb9,0x00 } },
+{  16, 0xfab0, 0, {0x6e,0x40,0x08,0x90,0x02,0x25,0x00,0xa9,0x00,0x22,0x40,0x08,0x91,0x06,0xc6,0x00 } },
+{  16, 0xfac0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x14,0x00,0xb5,0x10,0xa1,0x44 } },
+{  16, 0xfad0, 0, {0x28,0x50,0x02,0x44,0x80,0x81,0x30,0x20,0x48,0x08,0x12,0x02,0x84,0x40,0xb1,0x80 } },
+{  16, 0xfae0, 0, {0x6c,0xc8,0x08,0x12,0x02,0x04,0x80,0xb1,0x34,0x20,0x48,0x08,0x12,0x02,0xc2,0x01 } },
+{  16, 0xfaf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xe8,0x40,0x32,0x90 } },
+{  16, 0xfb00, 0, {0x0c,0xc5,0x03,0x61,0x40,0xc0,0x40,0x3a,0x14,0x0f,0x85,0x03,0x21,0xb0,0xf8,0x50 } },
+{  16, 0xfb10, 0, {0x3e,0x00,0x0c,0x85,0x03,0x21,0x40,0xf8,0x40,0xb0,0x14,0x0c,0x80,0x03,0xee,0x01 } },
+{  16, 0xfb20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x1d,0xc4,0x04,0xf9,0x22,0x0e,0x48 } },
+{  16, 0xfb30, 0, {0x0f,0x10,0x13,0xb4,0x40,0xfd,0x30,0x3f,0x44,0x4f,0xd1,0x00,0xe4,0x84,0xff,0x01 } },
+{  16, 0xfb40, 0, {0x3d,0x44,0x0f,0xd1,0x0b,0xe4,0x40,0xf9,0x30,0x3e,0x44,0x0f,0xd1,0x03,0xe6,0x04 } },
+{  16, 0xfb50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x05,0xe4,0x00,0xdd,0x40,0x3f,0x50 } },
+{  16, 0xfb60, 0, {0x0c,0xd0,0x03,0x2c,0x00,0xc9,0x00,0x36,0x40,0x0f,0x90,0x13,0x27,0x04,0xf5,0x01 } },
+{  16, 0xfb70, 0, {0x37,0x40,0x0c,0xf0,0x03,0xf6,0x20,0xf9,0xa8,0x32,0x68,0x0c,0xd0,0x03,0xc6,0x00 } },
+{  16, 0xfb80, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xe0,0x00,0x88,0xa0,0x2e,0x28 } },
+{  16, 0xfb90, 0, {0x28,0x80,0x02,0x20,0x00,0x88,0xa0,0x22,0x00,0x0b,0x80,0x0a,0x62,0x80,0xb8,0x00 } },
+{  16, 0xfba0, 0, {0x22,0x00,0x08,0x80,0x02,0xe1,0x00,0xb8,0xe0,0x22,0x3a,0x08,0xa0,0x02,0xce,0x04 } },
+{  16, 0xfbb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x84,0x02,0x81,0x00,0x2e,0x40 } },
+{  16, 0xfbc0, 0, {0x08,0x10,0x0a,0x44,0x02,0x81,0x08,0x24,0x40,0x0a,0x10,0x02,0x45,0x80,0xb9,0x00 } },
+{  16, 0xfbd0, 0, {0x24,0x40,0x29,0x10,0x02,0xc4,0x00,0xb1,0x08,0x24,0x44,0x08,0x10,0x02,0xc2,0x01 } },
+{  16, 0xfbe0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x14,0xa4,0x04,0x89,0x01,0x2e,0x50 } },
+{  16, 0xfbf0, 0, {0x48,0xb2,0x02,0x64,0x00,0x91,0x00,0x22,0x46,0x0b,0x90,0x02,0x64,0x00,0xb9,0x01 } },
+{  16, 0xfc00, 0, {0x26,0xc0,0x09,0xb0,0x12,0xe4,0x00,0xb1,0x00,0x26,0x40,0x08,0x90,0x02,0xc6,0x04 } },
+{  16, 0xfc10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x04,0xe4,0x00,0xc9,0x00,0x3c,0x40 } },
+{  16, 0xfc20, 0, {0x0c,0x90,0x03,0x64,0x00,0xc9,0x02,0x36,0x50,0x0e,0x93,0x03,0x24,0x00,0xf9,0x90 } },
+{  16, 0xfc30, 0, {0x36,0x48,0x0d,0x94,0x83,0xe4,0x08,0xf9,0x00,0xb6,0x40,0x0c,0x94,0x03,0xe8,0x04 } },
+{  16, 0xfc40, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x10,0xa4,0x00,0xe9,0x00,0x3e,0x40 } },
+{  16, 0xfc50, 0, {0x0f,0x90,0x13,0xa4,0x00,0xe9,0x02,0x2e,0x61,0x05,0x90,0x03,0xa4,0x00,0xf9,0x00 } },
+{  16, 0xfc60, 0, {0x3a,0x40,0x0e,0x90,0x43,0xe4,0x10,0xf9,0x00,0x38,0x40,0x2f,0x90,0x03,0xca,0x00 } },
+{  16, 0xfc70, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xd8,0x01,0x32,0x04 } },
+{  16, 0xfc80, 0, {0x0f,0x80,0x43,0xc0,0x01,0xc8,0x00,0xb2,0x01,0x0c,0x80,0x03,0x20,0x00,0xc8,0x40 } },
+{  16, 0xfc90, 0, {0x30,0x00,0x8c,0x84,0x83,0xe0,0x00,0xc8,0x00,0x32,0x00,0x6c,0x84,0x03,0xca,0x04 } },
+{  16, 0xfca0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x28,0x00,0xba,0x00,0x23,0x80 } },
+{  16, 0xfcb0, 0, {0x0b,0xea,0x02,0xe8,0x00,0xaa,0x00,0x22,0x80,0x08,0xa0,0x02,0x28,0x00,0x86,0x20 } },
+{  16, 0xfcc0, 0, {0x37,0xa0,0x8d,0xe4,0x02,0xf8,0x00,0xda,0x00,0x22,0x80,0x08,0xa0,0x02,0xca,0x00 } },
+{  16, 0xfcd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x6c,0x00,0xb3,0x00,0x20,0xc0 } },
+{  16, 0xfce0, 0, {0x0b,0xb8,0x02,0x4c,0x04,0x83,0x00,0x20,0xc0,0x08,0xb0,0x02,0x0c,0x02,0x83,0x00 } },
+{  16, 0xfcf0, 0, {0x20,0x40,0x28,0x34,0x02,0xce,0x90,0x83,0x00,0xa0,0xc0,0x08,0x30,0x02,0xca,0x00 } },
+{  16, 0xfd00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1c,0xc0,0xb5,0x88,0x21,0x40 } },
+{  16, 0xfd10, 0, {0x0b,0x70,0x02,0xdc,0x80,0xa3,0x20,0x21,0xe0,0x48,0x32,0x42,0x0e,0x90,0x8e,0x01 } },
+{  16, 0xfd20, 0, {0x65,0x50,0x09,0x70,0x02,0xde,0x20,0x93,0x21,0x21,0xc0,0x08,0x70,0x02,0xe8,0x00 } },
+{  16, 0xfd30, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x18,0x1e,0x00,0xff,0x80,0xb1,0xa0 } },
+{  16, 0xfd40, 0, {0x0f,0x48,0x02,0x7e,0x00,0x87,0xa0,0x33,0xe0,0x28,0x7a,0x0b,0x1f,0x00,0xc4,0x80 } },
+{  16, 0xfd50, 0, {0x31,0x60,0x8c,0x58,0x03,0xfe,0x00,0xc7,0xc8,0x33,0xe8,0x0c,0x58,0x03,0xea,0x02 } },
+{  16, 0xfd60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xff,0x00,0x3e,0x00 } },
+{  16, 0xfd70, 0, {0x0f,0x90,0x23,0xec,0xa0,0xfb,0x40,0x3e,0xc0,0x8f,0xb5,0x03,0xed,0x80,0xf8,0x00 } },
+{  16, 0xfd80, 0, {0x3c,0x40,0x0f,0xb0,0x03,0xe8,0x00,0xfb,0x02,0x3e,0xd0,0x0f,0x90,0x03,0xc2,0x06 } },
+{  16, 0xfd90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x04,0xbe,0x00,0xff,0x80,0x3f,0xe0 } },
+{  16, 0xfda0, 0, {0x0f,0xd9,0x03,0xfe,0x20,0xcf,0xc8,0x33,0xea,0x8f,0xfc,0x03,0x3f,0x00,0xfd,0x80 } },
+{  16, 0xfdb0, 0, {0x3f,0x60,0x0e,0xe8,0x03,0xf2,0x00,0xcf,0x80,0x2f,0xfe,0x0c,0x78,0x03,0x00,0x00 } },
+{  16, 0xfdc0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x00,0x9c,0x00,0xb5,0x02,0x2d,0xc0 } },
+{  16, 0xfdd0, 0, {0x0b,0x58,0x42,0xdc,0x80,0xcf,0x00,0x21,0xc1,0x0b,0x30,0x12,0x1c,0x40,0xb4,0x02 } },
+{  16, 0xfde0, 0, {0x2d,0x46,0x08,0x71,0x12,0xc8,0x00,0xe7,0x00,0x2d,0xc4,0x08,0x70,0x03,0x6a,0x04 } },
+{  16, 0xfdf0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x00,0x2d,0x02 } },
+{  16, 0xfe00, 0, {0x0b,0x46,0x02,0xdc,0x08,0x97,0x00,0x21,0xc9,0x0a,0x30,0x22,0x1c,0x00,0xb4,0x00 } },
+{  16, 0xfe10, 0, {0x2d,0x40,0x0a,0x50,0x82,0xc4,0x00,0xb7,0x00,0x2c,0xc8,0x28,0x50,0x02,0x40,0x10 } },
+{  16, 0xfe20, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x14,0x8c,0x18,0xb3,0x00,0x2e,0x20 } },
+{  16, 0xfe30, 0, {0x0b,0x18,0x02,0xcf,0x4a,0x83,0xc2,0x20,0xc1,0x0b,0x34,0x22,0x0c,0x04,0xb8,0x58 } },
+{  16, 0xfe40, 0, {0x2c,0x40,0x0b,0x28,0x02,0xc8,0x00,0xa3,0x00,0x2c,0xc0,0x08,0x14,0x02,0x48,0x04 } },
+{  16, 0xfe50, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xbc,0x00,0xfb,0x00,0x3e,0x80 } },
+{  16, 0xfe60, 0, {0x0f,0xa0,0x02,0xfc,0x00,0xdf,0xa0,0xb3,0xc0,0x0e,0xf0,0x0b,0x3c,0x00,0xfb,0xc0 } },
+{  16, 0xfe70, 0, {0x3c,0xa0,0x0e,0xbd,0x03,0xec,0x00,0xff,0x00,0x3f,0xc0,0x0c,0x30,0x03,0x6a,0x04 } },
+{  16, 0xfe80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0xec,0x00,0xf9,0x00,0x3e,0x01 } },
+{  16, 0xfe90, 0, {0x8f,0xb1,0x43,0xec,0x00,0xf3,0x00,0x3e,0xc0,0x4f,0xb0,0x13,0xec,0x00,0xfb,0x00 } },
+{  16, 0xfea0, 0, {0x3e,0x80,0x0c,0x84,0x03,0xe1,0x00,0x73,0x00,0x3e,0xc1,0x0f,0xb2,0x43,0xe0,0x00 } },
+{  16, 0xfeb0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x50,0xfc,0x10,0xff,0x80,0x37,0xc0 } },
+{  16, 0xfec0, 0, {0x0c,0xe0,0x03,0xfc,0x20,0xff,0x08,0x33,0xc0,0x0f,0xf0,0x83,0xbc,0x00,0xff,0x00 } },
+{  16, 0xfed0, 0, {0x33,0xc0,0x2e,0x40,0x03,0x1c,0x01,0xcf,0x00,0x11,0xc0,0x4c,0xd0,0x03,0x00,0x44 } },
+{  16, 0xfee0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x04,0xb3,0x02,0x22,0x72 } },
+{  16, 0xfef0, 0, {0x08,0xa1,0x16,0xec,0x00,0xbb,0x04,0x22,0xc0,0x0b,0xb0,0x42,0xec,0x00,0xba,0x19 } },
+{  16, 0xff00, 0, {0xb6,0xd0,0x08,0x9c,0x4a,0x26,0x80,0xdb,0x00,0x22,0xc0,0x08,0x90,0x03,0x60,0x40 } },
+{  16, 0xff10, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0xb9,0x10,0x62,0x20 } },
+{  16, 0xff20, 0, {0x48,0xa0,0x02,0xec,0x00,0xbb,0x00,0x22,0xc0,0x0b,0xb0,0x02,0xec,0x10,0xbb,0x00 } },
+{  16, 0xff30, 0, {0x66,0x08,0x0a,0xa8,0x12,0x26,0x10,0x9b,0x00,0x2a,0xc0,0x28,0xb0,0x26,0x20,0x00 } },
+{  16, 0xff40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0c,0x00,0xb9,0x00,0x20,0x00 } },
+{  16, 0xff50, 0, {0x08,0x32,0x02,0xcc,0x04,0xb3,0x00,0x20,0xc0,0x4b,0x30,0x02,0xcc,0x00,0xb3,0x00 } },
+{  16, 0xff60, 0, {0x20,0x00,0x08,0x00,0x02,0x01,0x00,0x93,0x00,0x28,0xc0,0x08,0x30,0x06,0x42,0x11 } },
+{  16, 0xff70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x6c,0x00,0xf9,0x00,0xb2,0x40 } },
+{  16, 0xff80, 0, {0x0c,0x82,0x02,0xdc,0x01,0xff,0x00,0xb2,0xc0,0x0b,0xf1,0x03,0xbc,0x00,0xf9,0x00 } },
+{  16, 0xff90, 0, {0x26,0x40,0x2e,0x80,0x03,0x21,0x04,0xcf,0x00,0xbb,0xc0,0x0c,0x90,0x03,0x00,0x03 } },
+{  16, 0xffa0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xfd,0x00,0x3f,0x40 } },
+{  16, 0xffb0, 0, {0x0f,0x81,0x03,0xfc,0x00,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x23,0xfc,0x00,0xfc,0x00 } },
+{  16, 0xffc0, 0, {0x2d,0x40,0x2f,0xc0,0x03,0xf0,0x88,0xff,0x00,0x37,0xc0,0x8f,0xd0,0x03,0xe8,0x02 } },
+{  16, 0xffd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfe,0x40,0xff,0x80,0x33,0xc2 } },
+{  16, 0xffe0, 0, {0x0c,0xf8,0x03,0x7c,0xa0,0xff,0x90,0x3f,0xc4,0x2c,0xb4,0x03,0xbc,0x80,0xcf,0x40 } },
+{  16, 0xfff0, 0, {0x37,0xe0,0x0f,0xf1,0x93,0x6e,0x44,0xbf,0x30,0x3f,0x20,0x2c,0xf8,0x63,0xf0,0x04 } },
+{  16, 0x8010, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0x00,0xeb,0x20,0x23,0xf0 } },
+{  16, 0x8020, 0, {0x08,0xb8,0x52,0x3d,0x00,0xb3,0x00,0x2e,0xdc,0x08,0xf4,0x42,0x1c,0x42,0x8b,0x40 } },
+{  16, 0x8030, 0, {0x22,0xc8,0x0b,0xf6,0x03,0x6c,0x88,0xbb,0x30,0x2e,0x00,0x08,0xb2,0x02,0xe0,0x04 } },
+{  16, 0x8040, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x00,0xbb,0x08,0x20,0xc0 } },
+{  16, 0x8050, 0, {0x08,0x30,0x02,0x4c,0xa0,0xb3,0x20,0x26,0x80,0x88,0x36,0x02,0xcc,0xa0,0x93,0x60 } },
+{  16, 0x8060, 0, {0xa4,0xc2,0x0a,0x32,0x42,0x4c,0x90,0xb3,0x20,0x2c,0x0b,0x88,0x30,0x82,0xe2,0x01 } },
+{  16, 0x8070, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x08,0xbb,0x22,0xa2,0xc0 } },
+{  16, 0x8080, 0, {0x08,0xb0,0x02,0x2c,0x00,0xbb,0x00,0x2e,0x90,0x08,0xb0,0x02,0xec,0x00,0x9b,0x00 } },
+{  16, 0x8090, 0, {0x22,0xc0,0x0b,0xb0,0x02,0x6c,0x00,0xbb,0x02,0x2e,0x20,0x08,0xb0,0x02,0xf0,0x00 } },
+{  16, 0x80a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xb1,0x83,0x32,0xc0 } },
+{  16, 0x80b0, 0, {0x0c,0x1a,0x03,0x6c,0x10,0xfb,0x00,0x34,0xc0,0x0c,0xb0,0x03,0xec,0x08,0xda,0x00 } },
+{  16, 0x80c0, 0, {0x36,0xc0,0x0e,0xb0,0x0b,0x6c,0x00,0xfb,0x00,0x3e,0x28,0x0c,0xb0,0x02,0xd0,0x00 } },
+{  16, 0x80d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x00,0xed,0x80,0x3f,0xc0 } },
+{  16, 0x80e0, 0, {0x0f,0xd4,0x03,0xec,0x00,0xff,0x00,0x3f,0xc8,0x0f,0xb0,0x03,0x3c,0x00,0xee,0x40 } },
+{  16, 0x80f0, 0, {0x3f,0xc0,0x0f,0x70,0x03,0xfc,0x00,0xff,0x00,0x3f,0x80,0x0f,0xf0,0x03,0xf8,0x00 } },
+{  16, 0x8100, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x20,0xb0,0xc0 } },
+{  16, 0x8110, 0, {0x0f,0xb4,0x03,0xac,0x02,0xcb,0x00,0x32,0x90,0x0e,0xb0,0x03,0x6c,0x00,0xeb,0x00 } },
+{  16, 0x8120, 0, {0x3a,0xc0,0x0c,0xb0,0x02,0xec,0x00,0xfb,0x00,0x3e,0x91,0x0f,0xb0,0x03,0x90,0x00 } },
+{  16, 0x8130, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xbb,0x80,0x23,0xd7 } },
+{  16, 0x8140, 0, {0x0b,0x90,0x02,0x3c,0x14,0x8b,0x00,0x6a,0x08,0x28,0xf0,0x00,0xbc,0x00,0x83,0x00 } },
+{  16, 0x8150, 0, {0xbe,0xc0,0x88,0xf0,0x13,0x2c,0x00,0xef,0x00,0x2e,0x80,0x0b,0xb0,0x07,0xb2,0x00 } },
+{  16, 0x8160, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xb3,0x40,0x20,0xd0 } },
+{  16, 0x8170, 0, {0x0b,0x28,0x02,0x8c,0x00,0x83,0x01,0x20,0xc0,0x1a,0xb8,0x00,0x6c,0x10,0xa1,0x00 } },
+{  16, 0x8180, 0, {0x68,0xc0,0x2a,0x30,0x02,0x8c,0x00,0xb3,0x02,0x2e,0x00,0x4b,0x30,0x02,0xf8,0x04 } },
+{  16, 0x8190, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x00,0xb7,0xa0,0x21,0xe0 } },
+{  16, 0x81a0, 0, {0x0b,0xec,0xc2,0x1e,0x04,0x87,0x80,0x29,0xe4,0x08,0x79,0x82,0x9e,0x40,0xaf,0x90 } },
+{  16, 0x81b0, 0, {0x29,0xe0,0x0a,0x38,0x00,0x1e,0x00,0xa7,0x90,0x2d,0x24,0x0b,0x78,0x02,0x88,0x00 } },
+{  16, 0x81c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x50,0xfb,0x09,0x30,0xc0 } },
+{  16, 0x81d0, 0, {0x0f,0x20,0x02,0x8c,0x40,0xc3,0x00,0x20,0xc0,0x0a,0x38,0x03,0x4c,0x44,0xe1,0x00 } },
+{  16, 0x81e0, 0, {0xaa,0xc0,0x0e,0x31,0x43,0x8e,0x00,0xf3,0x00,0x3c,0x00,0x0f,0x30,0x03,0xd2,0x02 } },
+{  16, 0x81f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x4d,0xbc,0x00,0xff,0x20,0x3f,0xd0 } },
+{  16, 0x8200, 0, {0x4f,0x70,0x03,0xfc,0x00,0xff,0x00,0x3d,0xc0,0x0f,0xf3,0x43,0xfc,0x40,0xd7,0x00 } },
+{  16, 0x8210, 0, {0xbf,0xc0,0x0d,0xf4,0xc3,0xfc,0x40,0xff,0x00,0x3f,0x40,0x0f,0xf0,0x03,0xd0,0x06 } },
+{  16, 0x8220, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x00,0xfb,0x00,0x32,0xd0 } },
+{  16, 0x8230, 0, {0x0d,0x90,0x01,0xed,0xc0,0xfb,0x00,0x3e,0xc0,0x1f,0xba,0x03,0xac,0xc0,0xc8,0x00 } },
+{  16, 0x8240, 0, {0x32,0xe0,0x8d,0xb4,0x43,0xec,0x00,0xfb,0x00,0x36,0xa0,0x0c,0xb0,0x03,0x6a,0x00 } },
+{  16, 0x8250, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb7,0x00,0x21,0xc8 } },
+{  16, 0x8260, 0, {0x08,0x60,0x02,0xdc,0x20,0xb7,0x00,0x2d,0xc0,0x0f,0x74,0xa2,0x1c,0x28,0xd6,0x00 } },
+{  16, 0x8270, 0, {0x35,0xc0,0x08,0x72,0x02,0x5c,0x08,0xb7,0x44,0xa1,0x80,0x48,0x70,0x02,0x12,0x00 } },
+{  16, 0x8280, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x80,0x20,0xe4 } },
+{  16, 0x8290, 0, {0x09,0x78,0x26,0xde,0x00,0xb7,0x80,0x2d,0xe2,0x0a,0x70,0x12,0x8c,0x88,0x81,0x80 } },
+{  16, 0x82a0, 0, {0x21,0xe0,0x09,0x78,0x02,0xde,0x00,0xb3,0xa0,0x25,0xa0,0x28,0x78,0x02,0x70,0x04 } },
+{  16, 0x82b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x01,0xbb,0x80,0x20,0xc0 } },
+{  16, 0x82c0, 0, {0x08,0x30,0x42,0xec,0x00,0xb3,0x00,0x2c,0xc0,0x0a,0x30,0x22,0x0c,0x00,0x93,0x00 } },
+{  16, 0x82d0, 0, {0x24,0xc1,0x08,0x30,0x02,0xcc,0x00,0xb3,0x00,0x20,0xe0,0x08,0xb0,0x02,0x12,0x04 } },
+{  16, 0x82e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xfa,0x08,0xb2,0x80 } },
+{  16, 0x82f0, 0, {0x0d,0xe2,0x03,0xe8,0x00,0xfa,0x00,0x3f,0x80,0x0a,0xa0,0x03,0xa8,0x00,0xce,0x50 } },
+{  16, 0x8300, 0, {0x32,0x80,0x05,0xa0,0x03,0xe8,0x00,0xfa,0x00,0x37,0xa8,0x0c,0xa0,0x03,0x7a,0x04 } },
+{  16, 0x8310, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x60,0x08,0xf8,0x00,0x3c,0x00 } },
+{  16, 0x8320, 0, {0x0f,0x88,0x01,0xe0,0x00,0xf8,0x04,0x3c,0x00,0x4f,0x00,0x13,0xc0,0x00,0xf8,0x00 } },
+{  16, 0x8330, 0, {0x3e,0x00,0x0f,0x80,0x03,0x60,0x00,0xf8,0x02,0x3e,0x01,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0x8340, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf9,0x90,0x12,0x40 } },
+{  16, 0x8350, 0, {0x0c,0x90,0x03,0xa4,0x00,0xc9,0x00,0x3e,0x70,0x0e,0x94,0x33,0x24,0x08,0xc9,0x00 } },
+{  16, 0x8360, 0, {0x2a,0x40,0x0b,0x90,0x03,0xe4,0x00,0xf9,0x00,0x3a,0x40,0x0f,0x90,0x03,0x02,0x04 } },
+{  16, 0x8370, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x42,0x22,0x60 } },
+{  16, 0x8380, 0, {0x08,0x10,0x02,0x24,0x00,0x89,0x03,0x2e,0x40,0x08,0x90,0x02,0xa4,0x01,0x81,0x04 } },
+{  16, 0x8390, 0, {0x3e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb9,0x02,0x22,0x40,0x0e,0x90,0x02,0x20,0x00 } },
+{  16, 0x83a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x40,0x2a,0x4a } },
+{  16, 0x83b0, 0, {0x08,0x91,0x02,0xa4,0x00,0x89,0x00,0x2e,0x40,0x1a,0x90,0x0a,0x24,0x04,0x89,0x00 } },
+{  16, 0x83c0, 0, {0x2a,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb1,0x00,0x2a,0x40,0x0b,0x90,0x02,0x06,0x00 } },
+{  16, 0x83d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb1,0x01,0xa8,0x48 } },
+{  16, 0x83e0, 0, {0x88,0x90,0x02,0x04,0x80,0x81,0x40,0x2c,0x50,0x18,0x14,0x0a,0x84,0x10,0x89,0x40 } },
+{  16, 0x83f0, 0, {0x2c,0x40,0x0b,0x10,0x02,0xc4,0x00,0x31,0x20,0x20,0x40,0x0a,0x10,0x0a,0x02,0x01 } },
+{  16, 0x8400, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xf0,0x50,0x3a,0x00 } },
+{  16, 0x8410, 0, {0x2c,0xa0,0x02,0xa1,0x42,0xc8,0x00,0x3e,0x00,0xde,0x00,0x23,0x21,0x42,0x88,0x00 } },
+{  16, 0x8420, 0, {0x38,0x14,0x0f,0x85,0x03,0xe1,0x40,0xf8,0x50,0x38,0x14,0x0f,0x05,0x03,0x2e,0x01 } },
+{  16, 0x8430, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xe4,0x08,0xfd,0x00,0x36,0x44 } },
+{  16, 0x8440, 0, {0x0f,0xd0,0x03,0x64,0x40,0xf9,0x00,0x3d,0x50,0x0f,0x94,0x03,0xe5,0x00,0x7d,0x40 } },
+{  16, 0x8450, 0, {0x3e,0x40,0x0f,0x94,0x03,0xe4,0x00,0xf9,0x10,0x3f,0x40,0x0e,0x90,0x03,0xe6,0x04 } },
+{  16, 0x8460, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe4,0x00,0xfd,0x40,0x33,0x68 } },
+{  16, 0x8470, 0, {0x0c,0xd0,0x03,0xe7,0x81,0xf9,0x00,0x33,0x78,0x0d,0xd8,0x13,0x26,0xa0,0xcd,0xa0 } },
+{  16, 0x8480, 0, {0x32,0x40,0x0d,0x9b,0x03,0x24,0x00,0xf9,0xa0,0x3c,0x44,0x2c,0x90,0x07,0x86,0x00 } },
+{  16, 0x8490, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe0,0x00,0xb8,0xa0,0xa2,0x10 } },
+{  16, 0x84a0, 0, {0x18,0x80,0x03,0x82,0x84,0xb8,0x80,0x36,0x2c,0x2e,0x0f,0x02,0xa3,0xa0,0xd8,0xe0 } },
+{  16, 0x84b0, 0, {0x36,0x22,0x8b,0x08,0x03,0x42,0xa0,0xf8,0xe0,0x2e,0x28,0x08,0x88,0x02,0xce,0x04 } },
+{  16, 0x84c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0xb1,0x00,0xa0,0x50 } },
+{  16, 0x84d0, 0, {0x28,0x30,0x02,0xc5,0x80,0xb1,0x08,0x20,0x40,0x09,0x10,0xa2,0x44,0x08,0x81,0x48 } },
+{  16, 0x84e0, 0, {0x20,0x40,0x0b,0x14,0x02,0x04,0x80,0xb1,0x38,0x2c,0x48,0x08,0x12,0x82,0x82,0x01 } },
+{  16, 0x84f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0xb1,0x00,0x22,0x40 } },
+{  16, 0x8500, 0, {0x08,0x92,0x02,0xe4,0x00,0xb9,0x02,0x26,0x58,0x4a,0x90,0x02,0xe4,0x08,0x99,0x40 } },
+{  16, 0x8510, 0, {0x26,0x40,0x0b,0x90,0x02,0x64,0x08,0xb9,0x01,0x2c,0x48,0x08,0x90,0x12,0xc6,0x04 } },
+{  16, 0x8520, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x80,0x32,0x40 } },
+{  16, 0x8530, 0, {0x08,0x98,0x83,0xe4,0x04,0xb9,0x01,0x30,0x40,0x0d,0x90,0x0b,0x64,0x02,0xc9,0x00 } },
+{  16, 0x8540, 0, {0x32,0x40,0x0f,0x90,0x03,0x24,0x00,0xf9,0x00,0x1e,0x58,0x0c,0x90,0x03,0xa8,0x04 } },
+{  16, 0x8550, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x20,0x3c,0x40 } },
+{  16, 0x8560, 0, {0x0f,0x98,0x03,0xa4,0x00,0xb9,0x00,0x3e,0x42,0x8e,0x10,0x4b,0x84,0x04,0xf9,0x00 } },
+{  16, 0x8570, 0, {0x3e,0x40,0x8f,0x90,0x03,0xe4,0x00,0xe9,0x00,0x3e,0x40,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0x8580, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xd8,0x00,0x32,0x08 } },
+{  16, 0x8590, 0, {0x0f,0x84,0x83,0xa0,0x04,0xc8,0x04,0x3e,0x00,0x83,0x80,0x01,0x20,0x00,0xc0,0x00 } },
+{  16, 0x85a0, 0, {0x32,0x00,0x0f,0x00,0x03,0xa0,0x00,0xc8,0x00,0x32,0x10,0x4e,0x80,0x13,0xca,0x04 } },
+{  16, 0x85b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8e,0x90,0xa3,0x80 } },
+{  16, 0x85c0, 0, {0x0b,0xe4,0x02,0x28,0x00,0xca,0x00,0x2f,0x80,0x4a,0xa0,0x13,0xa8,0x00,0xaa,0x00 } },
+{  16, 0x85d0, 0, {0x36,0x81,0x0b,0xa0,0x02,0x28,0x00,0x8a,0x00,0x22,0x80,0x08,0xa0,0x03,0x8a,0x00 } },
+{  16, 0x85e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0xc0,0x20,0xd0 } },
+{  16, 0x85f0, 0, {0x0b,0x34,0x02,0x8c,0x00,0x8b,0x00,0x2c,0xf0,0x8b,0x18,0x02,0x4c,0x00,0x83,0x00 } },
+{  16, 0x8600, 0, {0x60,0xc0,0x0b,0x30,0x02,0x8c,0x02,0x83,0x00,0x28,0xc1,0x0a,0x30,0x02,0xca,0x00 } },
+{  16, 0x8610, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1e,0x00,0xb4,0x0b,0x69,0xc0 } },
+{  16, 0x8620, 0, {0x09,0x58,0x06,0x1e,0x80,0x97,0x10,0x2f,0xc2,0x48,0x70,0x82,0x9c,0x80,0xa7,0x08 } },
+{  16, 0x8630, 0, {0x25,0xcc,0x0b,0x70,0x02,0x1e,0x81,0x87,0xa2,0xab,0xc4,0x08,0x73,0x02,0xe8,0x00 } },
+{  16, 0x8640, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x10,0xdc,0x84,0x21,0xe0 } },
+{  16, 0x8650, 0, {0x0f,0x78,0x42,0x9f,0x02,0xc7,0x88,0x3d,0xe0,0x2f,0x71,0x03,0x4e,0x00,0xcf,0x80 } },
+{  16, 0x8660, 0, {0x21,0xe2,0x0f,0x78,0x83,0x9e,0x49,0xcf,0xd0,0x39,0xe8,0x0e,0x78,0x03,0xea,0x02 } },
+{  16, 0x8670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x4d,0xac,0x40,0xca,0x00,0x36,0x00 } },
+{  16, 0x8680, 0, {0x8f,0x30,0x23,0xec,0xa8,0xeb,0x40,0x3c,0xc0,0x0f,0x96,0x43,0xed,0x80,0xfb,0x00 } },
+{  16, 0x8690, 0, {0x3e,0xd8,0x8f,0xb1,0x43,0xed,0x80,0xfb,0x20,0x36,0xca,0x0f,0xb0,0xa3,0x82,0x06 } },
+{  16, 0x86a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x80,0xfc,0x80,0x31,0xe0 } },
+{  16, 0x86b0, 0, {0x05,0xaa,0x10,0xfe,0x44,0xff,0x90,0x3f,0xe1,0xcf,0xf9,0x17,0x3f,0x20,0xd7,0x80 } },
+{  16, 0x86c0, 0, {0x8b,0xe4,0x0f,0xf8,0x03,0x3e,0x30,0xff,0x80,0x37,0xe0,0x0f,0xf8,0x00,0x40,0x00 } },
+{  16, 0x86d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xbd,0x10,0x21,0xc0 } },
+{  16, 0x86e0, 0, {0x08,0x4a,0x02,0xdc,0xc0,0xb7,0x00,0x2d,0xc2,0x0c,0xd3,0x02,0x1c,0x80,0x87,0x00 } },
+{  16, 0x86f0, 0, {0x29,0xc0,0x4b,0x72,0x02,0x1c,0x00,0xb7,0x01,0x21,0xc0,0x0b,0xf0,0x12,0x2a,0x04 } },
+{  16, 0x8700, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x90,0x34,0x00,0x21,0x80 } },
+{  16, 0x8710, 0, {0x09,0x70,0x00,0x5c,0x0c,0xb7,0x00,0x2d,0xc4,0x08,0x50,0x1a,0x0c,0x00,0x97,0x00 } },
+{  16, 0x8720, 0, {0x21,0xc0,0x4b,0x30,0x02,0x1c,0x00,0xb7,0x00,0x25,0xc0,0x0b,0x70,0x02,0x40,0x00 } },
+{  16, 0x8730, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x00,0xb0,0x00,0x60,0x00 } },
+{  16, 0x8740, 0, {0x08,0x3e,0x02,0xcc,0x00,0xb3,0x02,0x0c,0xe0,0x2b,0xb0,0x02,0x0c,0x00,0x93,0x00 } },
+{  16, 0x8750, 0, {0x28,0xc0,0x0b,0xb0,0x02,0x2c,0x10,0xb3,0x00,0x20,0xd6,0x03,0x30,0x02,0x08,0x04 } },
+{  16, 0x8760, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xfb,0x00,0xb2,0x00 } },
+{  16, 0x8770, 0, {0x05,0xbe,0x03,0x7c,0x00,0xff,0x00,0x3e,0x20,0x0c,0xb0,0x03,0x3c,0x00,0xd9,0x80 } },
+{  16, 0x8780, 0, {0x33,0xc0,0x8b,0xf0,0x03,0x3c,0x00,0xff,0x00,0x37,0xe0,0x0f,0xf0,0x03,0x6a,0x04 } },
+{  16, 0x8790, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x04,0x3e,0x00 } },
+{  16, 0x87a0, 0, {0x0f,0xa4,0x23,0xcc,0x00,0xfb,0x00,0x3e,0x81,0x08,0x90,0x03,0xec,0x00,0xe9,0x14 } },
+{  16, 0x87b0, 0, {0x3e,0xc0,0x0f,0xb0,0x03,0xec,0x10,0xfb,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0xe0,0x00 } },
+{  16, 0x87c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xff,0x00,0x37,0x80 } },
+{  16, 0x87d0, 0, {0x0f,0xfa,0x03,0xfc,0x00,0xcf,0x00,0x3f,0x90,0x06,0xdc,0x23,0x3c,0x00,0xfd,0x10 } },
+{  16, 0x87e0, 0, {0x33,0xc0,0x0f,0xf0,0x0b,0x3c,0x00,0x43,0x00,0x33,0xc0,0x0f,0xf0,0x03,0xc0,0x44 } },
+{  16, 0x87f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x6c,0x09,0xbb,0x19,0x22,0x32 } },
+{  16, 0x8800, 0, {0x0b,0xbe,0x03,0x6c,0x00,0x8b,0x00,0x2c,0x90,0x0d,0xb8,0x02,0xac,0x00,0xb1,0x00 } },
+{  16, 0x8810, 0, {0xf2,0xc0,0x0b,0xb0,0x12,0xac,0x00,0x8b,0x00,0x22,0xc0,0x0b,0xb0,0x03,0xa0,0x40 } },
+{  16, 0x8820, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x10,0xb3,0x00,0x26,0x20 } },
+{  16, 0x8830, 0, {0x0b,0x90,0x12,0xec,0x01,0x8b,0x00,0x2a,0xc2,0x0a,0x90,0x02,0x2c,0x00,0xbb,0x00 } },
+{  16, 0x8840, 0, {0xa2,0xc0,0x0b,0xb0,0x02,0x2c,0x00,0xab,0x00,0x2a,0xc0,0x0b,0xb0,0x02,0xe0,0x00 } },
+{  16, 0x8850, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x01,0xb3,0x00,0x20,0x00 } },
+{  16, 0x8860, 0, {0x0b,0x00,0x02,0x8c,0x00,0x83,0x00,0x2e,0xc0,0x0b,0x34,0x02,0x8c,0x00,0xbb,0x00 } },
+{  16, 0x8870, 0, {0x20,0xc0,0x0b,0x30,0x02,0x0d,0x00,0xa3,0x00,0xa0,0xc0,0x0b,0x30,0x02,0x82,0x01 } },
+{  16, 0x8880, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xbb,0x04,0x36,0x80 } },
+{  16, 0x8890, 0, {0x0f,0xb2,0x02,0xfc,0x02,0xcf,0x02,0x38,0xc0,0x0e,0xf0,0x03,0x3c,0x00,0xfb,0x00 } },
+{  16, 0x88a0, 0, {0x23,0xc0,0x0f,0xf0,0x03,0x3d,0x02,0xef,0x00,0x33,0xc0,0x0f,0xf0,0x43,0xc0,0x03 } },
+{  16, 0x88b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x3f,0x00 } },
+{  16, 0x88c0, 0, {0x0f,0xf4,0x23,0x7c,0x00,0xff,0x00,0x3f,0xc0,0x0d,0xd0,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0x88d0, 0, {0x3b,0xc0,0x0f,0xf0,0x03,0xfc,0x88,0xdf,0x00,0x3f,0xc0,0x0f,0xf0,0x03,0xa8,0x06 } },
+{  16, 0x88e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0x50,0xce,0x12,0x33,0xd0 } },
+{  16, 0x88f0, 0, {0x4c,0x86,0x83,0x30,0x80,0x5f,0x68,0x33,0xc4,0x0f,0xf3,0x83,0x3c,0xc0,0xcc,0x38 } },
+{  16, 0x8900, 0, {0xb3,0x08,0x0c,0xc6,0x03,0xf1,0xa0,0xff,0x00,0x33,0x24,0x0c,0xc2,0x03,0xf0,0x00 } },
+{  16, 0x8910, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0x80,0xd2,0x20,0x23,0xd8 } },
+{  16, 0x8920, 0, {0x0d,0x96,0x02,0x88,0x60,0xaf,0x40,0x23,0xdc,0x0b,0xf6,0x02,0x3c,0xc2,0x88,0x60 } },
+{  16, 0x8930, 0, {0x22,0x52,0x08,0x91,0x22,0xe1,0x00,0xb7,0x24,0xa2,0x48,0x8a,0x84,0x82,0x60,0x04 } },
+{  16, 0x8940, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x00,0x81,0x00,0xe0,0xc4 } },
+{  16, 0x8950, 0, {0x0a,0x00,0x02,0x04,0x80,0xa3,0x20,0xa8,0xc0,0x1b,0x30,0x0a,0x0c,0x00,0xa0,0x00 } },
+{  16, 0x8960, 0, {0x28,0x0c,0x09,0x02,0x02,0xc4,0x80,0xb3,0x1c,0x22,0x08,0x19,0x03,0x02,0xe2,0x11 } },
+{  16, 0x8970, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa4,0x00,0x99,0x80,0x62,0xc0 } },
+{  16, 0x8980, 0, {0x0b,0xa0,0x32,0xa4,0x51,0xab,0x00,0x2a,0xc0,0x8b,0xb0,0x00,0x0c,0x00,0xa9,0xc0 } },
+{  16, 0x8990, 0, {0x2a,0x21,0x08,0xb8,0x22,0xe2,0x00,0xbb,0x00,0x22,0x84,0x1b,0xa8,0x42,0x70,0x04 } },
+{  16, 0x89a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe2,0x00,0xcb,0xc9,0x32,0xc0 } },
+{  16, 0x89b0, 0, {0x0e,0x8b,0x13,0x22,0x10,0xdb,0x01,0x32,0xc0,0x0f,0xb0,0x0b,0x2c,0x00,0x68,0x81 } },
+{  16, 0x89c0, 0, {0x3a,0x22,0x2c,0x88,0x23,0xe3,0x00,0xfb,0x00,0x30,0x30,0x8d,0x9c,0x83,0xd0,0x04 } },
+{  16, 0x89d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xba,0x40,0xf7,0x04,0x3e,0xc2 } },
+{  16, 0x89e0, 0, {0x0d,0xd8,0x23,0xd8,0x00,0x7b,0x00,0x37,0xc0,0x0f,0x70,0x33,0xfc,0x10,0xd2,0x00 } },
+{  16, 0x89f0, 0, {0x35,0xc0,0x8f,0xc0,0x03,0xf4,0x00,0xf7,0x02,0x3f,0xe0,0x0e,0x80,0x03,0xf8,0x00 } },
+{  16, 0x8a00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x81,0x20,0xc8,0x08,0x30,0xc0 } },
+{  16, 0x8a10, 0, {0x0c,0x00,0x83,0x24,0x40,0xc3,0x89,0x3a,0xc0,0x0e,0xb0,0x0b,0x2c,0x08,0xc9,0x48 } },
+{  16, 0x8a20, 0, {0x72,0x54,0x0f,0x91,0x03,0xed,0x02,0xeb,0x8a,0x3a,0x62,0x8c,0x80,0x0b,0x10,0x04 } },
+{  16, 0x8a30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2b,0x04,0x88,0x40,0xa3,0xc2 } },
+{  16, 0x8a40, 0, {0x02,0xae,0x12,0x27,0x42,0x8f,0x44,0x23,0xc2,0x0b,0xf4,0x02,0x3d,0x00,0x0a,0x40 } },
+{  16, 0x8a50, 0, {0x22,0xe0,0x0b,0xb5,0x02,0xec,0x20,0x8f,0x44,0xa2,0x40,0x8d,0xbd,0x23,0x32,0x00 } },
+{  16, 0x8a60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x49,0x40,0x83,0x81,0x24,0xc1 } },
+{  16, 0x8a70, 0, {0x08,0x28,0x02,0x01,0x00,0x93,0x00,0xa0,0xe8,0x0a,0x30,0x82,0x8f,0x60,0xb3,0x90 } },
+{  16, 0x8a80, 0, {0x60,0xb8,0x0b,0x28,0x12,0x4a,0x00,0x93,0x00,0x20,0x90,0x09,0x20,0x02,0x78,0x00 } },
+{  16, 0x8a90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x02,0x87,0xa8,0x25,0xe0 } },
+{  16, 0x8aa0, 0, {0x0a,0x7b,0x02,0x1a,0x04,0x87,0x80,0x21,0xe4,0x0b,0x78,0x82,0x8e,0x02,0x96,0x91 } },
+{  16, 0x8ab0, 0, {0x21,0x21,0x0b,0x69,0x40,0xdb,0x40,0x97,0x92,0x23,0xa0,0x89,0x58,0x82,0x08,0x00 } },
+{  16, 0x8ac0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x25,0x82,0xc3,0x00,0x34,0xc0 } },
+{  16, 0x8ad0, 0, {0x0c,0x9b,0x43,0x08,0xd0,0xd3,0x20,0x38,0xc0,0x0e,0xb0,0x03,0x8c,0x00,0xb3,0x00 } },
+{  16, 0x8ae0, 0, {0x20,0x80,0x07,0x10,0x03,0xe0,0x00,0xd3,0x10,0x38,0x18,0x0d,0x30,0x03,0x52,0x02 } },
+{  16, 0x8af0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xb4,0x00,0x7f,0x20,0x1b,0xd0 } },
+{  16, 0x8b00, 0, {0x0f,0xf1,0x03,0xf8,0x40,0xef,0x00,0x3f,0xc0,0x0f,0xb4,0x03,0x7c,0x20,0xcf,0x04 } },
+{  16, 0x8b10, 0, {0xbf,0x40,0x0f,0xf0,0x03,0xe4,0x10,0xef,0x18,0x3d,0xc0,0x0f,0xe0,0x03,0xd0,0x06 } },
+{  16, 0x8b20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x00,0xe3,0x00,0xb2,0xc4 } },
+{  16, 0x8b30, 0, {0x0c,0xa0,0x03,0x24,0x00,0xdb,0x68,0x32,0xc8,0x0c,0xb4,0x03,0xec,0x80,0xc8,0x80 } },
+{  16, 0x8b40, 0, {0xb6,0xe0,0x0c,0xa0,0x03,0x2e,0x00,0xcb,0xe0,0xb2,0x60,0x0c,0xb8,0x0b,0x2a,0x00 } },
+{  16, 0x8b50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x02,0x87,0x00,0xa1,0xc8 } },
+{  16, 0x8b60, 0, {0x08,0x70,0x02,0x1c,0x08,0x97,0x02,0x21,0xd4,0x08,0x74,0x02,0xdc,0xc0,0x07,0x00 } },
+{  16, 0x8b70, 0, {0x21,0xc0,0x88,0x70,0x02,0x18,0x00,0x83,0x08,0x21,0xc0,0x08,0x50,0x02,0x12,0x04 } },
+{  16, 0x8b80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x20,0xad,0x80,0x29,0xe0 } },
+{  16, 0x8b90, 0, {0x08,0x58,0x02,0x1e,0x00,0x97,0xb0,0x21,0xe8,0x08,0x78,0x02,0xde,0x10,0x15,0x80 } },
+{  16, 0x8ba0, 0, {0x21,0xa1,0x08,0x48,0x02,0x5e,0x00,0x87,0xa4,0x65,0xa0,0x08,0x78,0x02,0x30,0x00 } },
+{  16, 0x8bb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcf,0x10,0x81,0x70,0xa8,0xc0 } },
+{  16, 0x8bc0, 0, {0x38,0x30,0x0a,0x0d,0x00,0x93,0x00,0xa0,0xc1,0x28,0x30,0x02,0xcc,0x02,0x83,0x88 } },
+{  16, 0x8bd0, 0, {0x20,0xe0,0x38,0x34,0x0a,0x4d,0x72,0x83,0x00,0x24,0xe8,0x28,0x34,0x82,0x12,0x04 } },
+{  16, 0x8be0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xba,0x40,0xee,0xc0,0xba,0x80 } },
+{  16, 0x8bf0, 0, {0x0c,0xe0,0x03,0x39,0x10,0xda,0x00,0x32,0x80,0x0c,0xa0,0x03,0xe8,0x00,0xde,0xc8 } },
+{  16, 0x8c00, 0, {0x33,0xa0,0x0c,0xe0,0x03,0x7b,0x00,0xca,0x00,0x37,0xb1,0x0c,0xe4,0x23,0x3a,0x04 } },
+{  16, 0x8c10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xc1,0x00,0xf8,0x00,0x36,0x00 } },
+{  16, 0x8c20, 0, {0x0f,0x80,0x03,0xc0,0x20,0x38,0x00,0x3e,0x00,0x0f,0x00,0x03,0xe0,0x00,0xf8,0x02 } },
+{  16, 0x8c30, 0, {0x3a,0x24,0x0f,0x80,0x83,0xa0,0x01,0xf8,0x04,0x3a,0x04,0x0d,0x80,0x13,0xd2,0x00 } },
+{  16, 0x8c40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x44,0xc1,0x00,0x32,0x40 } },
+{  16, 0x8c50, 0, {0x0c,0x90,0x32,0x24,0x0c,0xc1,0x06,0x38,0x40,0x0d,0x90,0x09,0x04,0x00,0xd9,0x00 } },
+{  16, 0x8c60, 0, {0x3e,0x40,0x0f,0x18,0x03,0x24,0x00,0xf9,0x01,0x3e,0x40,0x0f,0x90,0x03,0xc2,0x04 } },
+{  16, 0x8c70, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x06,0x89,0x00,0x2a,0x50 } },
+{  16, 0x8c80, 0, {0x08,0x94,0x0a,0x24,0x00,0x89,0x42,0x22,0x50,0x0a,0x90,0x12,0x25,0x00,0x89,0x00 } },
+{  16, 0x8c90, 0, {0x2e,0x50,0x0b,0x9c,0x0a,0x25,0x10,0xb9,0x00,0x2e,0x50,0x0b,0x90,0x02,0xe0,0x00 } },
+{  16, 0x8ca0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x20,0x89,0x00,0x20,0x42 } },
+{  16, 0x8cb0, 0, {0x08,0x10,0xc2,0xac,0x10,0x89,0x08,0x2a,0x42,0x09,0x90,0x02,0x24,0x20,0x99,0x00 } },
+{  16, 0x8cc0, 0, {0x2e,0x42,0x0a,0xb1,0x82,0x2c,0x20,0xb9,0x00,0x6e,0x42,0x0b,0x90,0x02,0xc6,0x00 } },
+{  16, 0x8cd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x83,0x00,0x28,0x48 } },
+{  16, 0x8ce0, 0, {0x08,0x12,0x62,0x8c,0x80,0x81,0x00,0x20,0x40,0x02,0x10,0x02,0x84,0x80,0x81,0x20 } },
+{  16, 0x8cf0, 0, {0x2c,0x49,0x0b,0x12,0x06,0x04,0x84,0xb3,0x02,0x6c,0x40,0x0b,0x12,0x02,0xc2,0x01 } },
+{  16, 0x8d00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x41,0xe0,0xc8,0x78,0x30,0x14 } },
+{  16, 0x8d10, 0, {0x4c,0x05,0x13,0xa1,0x42,0xc0,0x78,0x38,0x1e,0x0d,0x87,0x83,0x01,0x40,0xd0,0x50 } },
+{  16, 0x8d20, 0, {0x3c,0x14,0x0e,0x05,0x03,0x01,0x40,0xf8,0x78,0x3c,0x14,0x0f,0x05,0x03,0xee,0x03 } },
+{  16, 0x8d30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xfc,0x00,0xff,0x00,0x0e,0x44 } },
+{  16, 0x8d40, 0, {0x2f,0xf1,0x03,0x74,0x40,0xf9,0x00,0x3e,0x40,0x0d,0x90,0x03,0x64,0x40,0xfd,0x10 } },
+{  16, 0x8d50, 0, {0x3f,0x44,0x0f,0xd1,0x01,0xf4,0x40,0xf9,0x01,0x3f,0xc0,0x0f,0xd1,0x03,0xe6,0x06 } },
+{  16, 0x8d60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xe6,0x22,0xe9,0x88,0xb2,0x40 } },
+{  16, 0x8d70, 0, {0x0f,0x90,0x03,0x24,0x16,0xc9,0x8c,0x36,0x7b,0x8f,0x9c,0x83,0xa7,0x90,0xc9,0x00 } },
+{  16, 0x8d80, 0, {0x3e,0x50,0x04,0x94,0x13,0x24,0x50,0xc9,0xe0,0x3e,0x50,0x0f,0x90,0x03,0x06,0x00 } },
+{  16, 0x8d90, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe2,0x80,0x88,0xa0,0x22,0x28 } },
+{  16, 0x8da0, 0, {0x0b,0x8a,0x02,0x2a,0x80,0x88,0xa4,0x22,0x30,0x08,0x8e,0x0a,0x22,0x02,0x88,0xa0 } },
+{  16, 0x8db0, 0, {0x2e,0x28,0x88,0xaa,0x12,0x22,0x90,0x88,0xf4,0x2e,0x20,0x0b,0xc8,0x02,0x0e,0x04 } },
+{  16, 0x8dc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xd4,0x20,0xa5,0x08,0x21,0x42 } },
+{  16, 0x8dd0, 0, {0x0b,0x50,0x82,0x14,0x31,0x85,0x08,0x25,0x40,0x0a,0x50,0x22,0x94,0x40,0x85,0x08 } },
+{  16, 0x8de0, 0, {0x6d,0x40,0x08,0x50,0x02,0x54,0x02,0x95,0x00,0x2d,0x48,0x0b,0x50,0x82,0x42,0x01 } },
+{  16, 0x8df0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0x84,0x00,0x8d,0x10,0x23,0x40 } },
+{  16, 0x8e00, 0, {0x0b,0xd0,0x00,0x34,0x01,0x8d,0x00,0x23,0x41,0x58,0xd0,0x02,0x34,0x00,0x8d,0x08 } },
+{  16, 0x8e10, 0, {0x2f,0x50,0x08,0xd2,0x02,0x74,0x80,0x9d,0x00,0x2f,0x48,0x0b,0xdc,0x02,0x46,0x04 } },
+{  16, 0x8e20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe7,0x40,0xe9,0xc0,0x32,0x40 } },
+{  16, 0x8e30, 0, {0x0f,0x90,0x09,0x26,0x00,0xc9,0x04,0x36,0x40,0x1f,0x90,0x23,0xa4,0x08,0xc9,0x40 } },
+{  16, 0x8e40, 0, {0x3e,0x40,0x0c,0x94,0x0b,0x64,0x20,0xd9,0x02,0x3e,0x41,0x0f,0x94,0x03,0x68,0x04 } },
+{  16, 0x8e50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x80,0x3e,0x40 } },
+{  16, 0x8e60, 0, {0x0f,0x14,0x03,0xc5,0x08,0xf9,0x00,0x3e,0x40,0x1f,0x90,0x23,0xe4,0x00,0xf9,0x00 } },
+{  16, 0x8e70, 0, {0x3c,0x40,0xaf,0x98,0x03,0x86,0x00,0xe9,0x00,0x3e,0x40,0x0f,0x10,0x0b,0x8a,0x00 } },
+{  16, 0x8e80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xb0,0x00,0xdc,0x40,0xb3,0x00 } },
+{  16, 0x8e90, 0, {0x0f,0xc0,0x03,0x31,0x02,0xc4,0x04,0xb1,0x00,0x3c,0x40,0x03,0x10,0x00,0xfc,0x40 } },
+{  16, 0x8ea0, 0, {0x33,0x00,0x0c,0xc4,0x03,0xb1,0x00,0xcc,0x00,0xb3,0x00,0x0c,0xc4,0x03,0xca,0x04 } },
+{  16, 0x8eb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x8a,0x80,0x22,0xa0 } },
+{  16, 0x8ec0, 0, {0x0b,0xa0,0x02,0x2a,0x00,0x8a,0x84,0x22,0xa1,0x08,0xa0,0x02,0x28,0x08,0xba,0x01 } },
+{  16, 0x8ed0, 0, {0x22,0x80,0x08,0xa0,0x2b,0x28,0x00,0x8a,0x80,0x2a,0x80,0x08,0xe0,0x02,0xca,0x00 } },
+{  16, 0x8ee0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x02,0x9b,0x81,0x20,0xe0 } },
+{  16, 0x8ef0, 0, {0x8b,0x38,0x06,0xce,0x00,0x93,0x80,0x20,0xc0,0x08,0x38,0x02,0x0c,0x00,0xb3,0x80 } },
+{  16, 0x8f00, 0, {0x6c,0xe0,0x0a,0xb0,0x02,0x4c,0x00,0x93,0x00,0x20,0xe0,0x08,0x30,0x02,0xca,0x00 } },
+{  16, 0x8f10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x10,0x04,0x80,0x08,0x21,0x02 } },
+{  16, 0x8f20, 0, {0x4b,0x44,0x06,0xd0,0x20,0x90,0x08,0x21,0x02,0x80,0x44,0x02,0x10,0x00,0xb4,0xc0 } },
+{  16, 0x8f30, 0, {0x2d,0x10,0x48,0x40,0x02,0x00,0x00,0x94,0x89,0x29,0x30,0x08,0x40,0x02,0xe8,0x00 } },
+{  16, 0x8f40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x32,0x00,0xd6,0x80,0x31,0xa0 } },
+{  16, 0x8f50, 0, {0x0f,0xe8,0x0b,0xca,0x00,0xd6,0x80,0x23,0xa0,0x04,0xf8,0x0b,0x1a,0x00,0xff,0x80 } },
+{  16, 0x8f60, 0, {0xbf,0xa0,0x2e,0xc8,0x13,0xda,0x02,0x5e,0x80,0x73,0xa0,0x2c,0x78,0x03,0xea,0x02 } },
+{  16, 0x8f70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf9,0x00,0x3e,0x40 } },
+{  16, 0x8f80, 0, {0x0f,0x90,0x03,0x24,0x00,0xe9,0x00,0x3e,0x40,0x0e,0x80,0x03,0xe4,0x00,0xf8,0x00 } },
+{  16, 0x8f90, 0, {0x32,0x40,0x0f,0xb0,0x03,0xe4,0x01,0xe9,0x04,0x36,0x40,0x0f,0x80,0x03,0xc2,0x06 } },
+{  16, 0x8fa0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xcd,0x80,0x33,0x60 } },
+{  16, 0x8fb0, 0, {0x0c,0xd8,0x43,0x36,0x00,0xcd,0x80,0x33,0x60,0x0c,0xd9,0x23,0xbe,0x00,0x4d,0x80 } },
+{  16, 0x8fc0, 0, {0x33,0x60,0x08,0xf8,0x0b,0x3e,0x00,0xfd,0x84,0x3f,0x60,0x0f,0xf9,0x03,0xc0,0x00 } },
+{  16, 0x8fd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x90,0x04,0xde,0x00,0x23,0x80 } },
+{  16, 0x8fe0, 0, {0x08,0x60,0x02,0xb8,0x20,0x8e,0x04,0x23,0x80,0x08,0x68,0x02,0x10,0x00,0x8e,0x20 } },
+{  16, 0x8ff0, 0, {0x23,0x82,0x08,0x40,0x02,0x12,0x00,0xf6,0x00,0x2d,0x80,0x0b,0x41,0xa0,0xea,0x04 } },
+{  16, 0x9000, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x84,0x00,0x21,0x00 } },
+{  16, 0x9010, 0, {0x08,0x41,0x02,0x50,0x40,0x94,0x00,0x21,0x00,0x0a,0x52,0x02,0xd8,0x00,0x85,0x02 } },
+{  16, 0x9020, 0, {0x25,0x04,0x08,0x40,0x22,0x18,0x08,0xb4,0x00,0x2d,0x10,0x0b,0x78,0x40,0xc0,0x00 } },
+{  16, 0x9030, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xee,0x22,0x93,0x00,0x20,0xc0 } },
+{  16, 0x9040, 0, {0x08,0x38,0x02,0xec,0x00,0x93,0x00,0x20,0xc1,0x2a,0x20,0x02,0x64,0x02,0x82,0x10 } },
+{  16, 0x9050, 0, {0x24,0xf0,0x0a,0x3c,0x42,0x24,0x28,0xb3,0x00,0x2c,0xe0,0x0b,0x88,0x82,0xc8,0x04 } },
+{  16, 0x9060, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xad,0x00,0xcb,0x00,0xb2,0xc0 } },
+{  16, 0x9070, 0, {0xac,0xbe,0x03,0x6e,0x02,0xdb,0x00,0xb2,0xc0,0x1e,0xa0,0x03,0xe4,0x00,0xca,0x11 } },
+{  16, 0x9080, 0, {0xb6,0xd0,0xac,0xbc,0x03,0x24,0x00,0xfb,0x00,0x3e,0xc0,0xcf,0x84,0x03,0xea,0x04 } },
+{  16, 0x9090, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe0,0x40,0xf8,0x00,0x3c,0x00 } },
+{  16, 0x90a0, 0, {0x2f,0x82,0x03,0xa0,0x00,0xe8,0x00,0x3e,0x00,0x1d,0x90,0x13,0xa8,0x00,0xf9,0x00 } },
+{  16, 0x90b0, 0, {0x3a,0x00,0x81,0x83,0x43,0xe8,0x00,0xe8,0x03,0x3e,0x04,0x0f,0xb0,0x03,0xe0,0x00 } },
+{  16, 0x90c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xe0,0x00,0xd6,0x00,0x37,0x80 } },
+{  16, 0x90d0, 0, {0x0c,0xa0,0x03,0xf8,0x00,0xce,0x00,0x33,0x80,0x0d,0xa0,0x13,0x20,0x08,0xce,0x00 } },
+{  16, 0x90e0, 0, {0x33,0x82,0x0c,0x40,0x73,0x30,0x18,0xce,0x00,0x1f,0x80,0x4f,0xc1,0x43,0x00,0x44 } },
+{  16, 0x90f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x7c,0x00,0x8d,0x00,0x23,0x40 } },
+{  16, 0x9100, 0, {0x0a,0xd0,0x02,0xf4,0x00,0x8d,0x00,0x23,0x40,0x08,0xd4,0x80,0x3e,0x42,0x8d,0x40 } },
+{  16, 0x9110, 0, {0x23,0x40,0x08,0xf0,0x02,0x3e,0x40,0x8d,0x00,0x0f,0x40,0x0b,0xf4,0x02,0x20,0x40 } },
+{  16, 0x9120, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x99,0x00,0xa6,0x40 } },
+{  16, 0x9130, 0, {0x08,0x90,0x06,0xe4,0x00,0x91,0x00,0x20,0x40,0x88,0x00,0x02,0x24,0x08,0x80,0x40 } },
+{  16, 0x9140, 0, {0x20,0x40,0x0a,0xb0,0x02,0x24,0x00,0x89,0x00,0x0e,0x40,0x0b,0x84,0x02,0x20,0x00 } },
+{  16, 0x9150, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x82,0x00,0x20,0x80 } },
+{  16, 0x9160, 0, {0x0a,0x21,0x06,0xc8,0x01,0x82,0x00,0x20,0x80,0x08,0x32,0x82,0x08,0x08,0x83,0x00 } },
+{  16, 0x9170, 0, {0x60,0x80,0x0a,0x00,0x12,0x08,0x80,0x82,0x00,0x2c,0x80,0x0b,0x30,0x0a,0x02,0x01 } },
+{  16, 0x9180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x60,0x00,0xd8,0x00,0x36,0x00 } },
+{  16, 0x9190, 0, {0x0c,0x84,0x23,0xe0,0x00,0xc8,0x00,0x32,0x00,0x0d,0x82,0x0b,0x20,0x02,0xc8,0x00 } },
+{  16, 0x91a0, 0, {0x32,0x00,0x0e,0x00,0x03,0x20,0x02,0xc8,0x00,0x3e,0x00,0x0f,0x80,0x03,0x00,0x03 } },
+{  16, 0x91b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xbf,0x00,0x3f,0xc0 } },
+{  16, 0x91c0, 0, {0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00,0xbf,0xc0,0x8f,0xb0,0x03,0xfc,0x08,0xff,0x02 } },
+{  16, 0x91d0, 0, {0x3f,0xc0,0x0d,0xf0,0x03,0xed,0x00,0xff,0x02,0x3f,0xc0,0x0f,0xf0,0x03,0xe8,0x06 } },
+{  16, 0x91e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0xf0,0x8c,0xff,0x00,0x3d,0x60 } },
+{  16, 0x91f0, 0, {0x2c,0xb2,0x83,0x7c,0x90,0xdf,0x38,0x31,0xe0,0x0f,0xf8,0x03,0x3c,0x00,0xff,0x20 } },
+{  16, 0x9200, 0, {0x3f,0xc4,0x0e,0xf4,0x03,0x7c,0x00,0xf4,0x80,0x33,0x00,0x0d,0xf8,0x03,0xf0,0x00 } },
+{  16, 0x9210, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe1,0x20,0xbb,0x62,0x2e,0x42 } },
+{  16, 0x9220, 0, {0x28,0xf4,0x42,0x3e,0x40,0x8f,0x44,0x22,0xe0,0x0b,0xb0,0x83,0x7f,0x44,0xbf,0xc1 } },
+{  16, 0x9230, 0, {0x2d,0xdc,0x2a,0xf6,0x02,0x3f,0x45,0xb8,0x80,0x22,0x61,0x88,0xb8,0x02,0xe0,0x04 } },
+{  16, 0x9240, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc5,0x80,0xb2,0x18,0x2e,0xc8 } },
+{  16, 0x9250, 0, {0x29,0x30,0x32,0x0c,0x08,0xb3,0x20,0x20,0xc0,0x4b,0x92,0x02,0x0c,0x00,0xb3,0x40 } },
+{  16, 0x9260, 0, {0x2c,0xc0,0x89,0x34,0x12,0x4c,0x00,0xb0,0x00,0x24,0xc1,0x49,0x30,0x02,0xe2,0x01 } },
+{  16, 0x9270, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xa4,0x00,0xba,0x0c,0x2e,0xe0 } },
+{  16, 0x9280, 0, {0xa9,0xb0,0x06,0x2c,0x00,0x8b,0x00,0xa2,0xc0,0x0b,0x90,0x00,0x6c,0x00,0xbb,0x00 } },
+{  16, 0x9290, 0, {0x2e,0xc0,0x0b,0x30,0x02,0x6c,0x00,0xba,0x80,0x26,0xf0,0x08,0xb0,0x02,0xf0,0x04 } },
+{  16, 0x92a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x11,0xee,0x00,0xfb,0xc4,0x3e,0x78 } },
+{  16, 0x92b0, 0, {0x2d,0xb0,0x03,0x6c,0x08,0xfb,0x00,0x32,0xc0,0x8b,0x24,0x83,0x2c,0x00,0xfb,0x00 } },
+{  16, 0x92c0, 0, {0x3e,0xc0,0x8f,0xb0,0x0b,0x6c,0x08,0xb2,0xe0,0x16,0x60,0x8d,0xb0,0x23,0xd0,0x04 } },
+{  16, 0x92d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbe,0x98,0xff,0x40,0x3f,0xc0 } },
+{  16, 0x92e0, 0, {0x0e,0x70,0x03,0xdc,0x00,0xff,0x00,0x3f,0xc0,0x0f,0xe0,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0x92f0, 0, {0x3f,0xc0,0x0e,0xf0,0x03,0xac,0x00,0xfe,0x00,0xb9,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
+{  16, 0x9300, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xad,0x00,0xfa,0x40,0x3e,0xd0 } },
+{  16, 0x9310, 0, {0x0e,0xb2,0x03,0xec,0x00,0xc3,0x00,0x3e,0xc0,0x0c,0xa0,0x03,0x2c,0x01,0xfb,0x00 } },
+{  16, 0x9320, 0, {0x3c,0xc0,0x0e,0xb8,0x03,0xec,0x00,0xda,0x00,0x3a,0xd0,0x4f,0xb0,0x23,0xd0,0x04 } },
+{  16, 0x9330, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xba,0x00,0x2c,0xc0 } },
+{  16, 0x9340, 0, {0x08,0xf4,0x07,0xbc,0x14,0xdf,0x00,0x3e,0xc0,0x1a,0xa0,0x52,0xbc,0x00,0xbf,0x04 } },
+{  16, 0x9350, 0, {0x3f,0xc0,0x8a,0xf0,0x03,0xbc,0x00,0xfa,0x00,0x22,0xc8,0x0f,0xb0,0x03,0xf2,0x00 } },
+{  16, 0x9360, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x48,0x01,0xb1,0x00,0x6c,0xc2 } },
+{  16, 0x9370, 0, {0x0a,0x30,0x42,0xcc,0x00,0x83,0x05,0x2c,0xc0,0x08,0x30,0x02,0x8c,0x01,0xb3,0x04 } },
+{  16, 0x9380, 0, {0x2c,0xc0,0x0a,0x30,0x22,0x8c,0x00,0x80,0x80,0x28,0xc0,0x0b,0x30,0x22,0xf8,0x00 } },
+{  16, 0x9390, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x08,0xb7,0x80,0x6f,0xe0 } },
+{  16, 0x93a0, 0, {0x18,0x78,0x02,0x8e,0x40,0xb7,0x80,0x2d,0xe0,0x0a,0x78,0x02,0x9e,0x00,0xb7,0x80 } },
+{  16, 0x93b0, 0, {0x29,0xe1,0x0a,0x78,0x02,0x9e,0x01,0xbc,0x80,0x29,0xe4,0x0b,0x78,0x02,0xc8,0x00 } },
+{  16, 0x93c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x09,0x40,0xf1,0x20,0x3c,0xc4 } },
+{  16, 0x93d0, 0, {0x0e,0x39,0x02,0xcc,0x00,0xc3,0x00,0x2c,0xc4,0x08,0x92,0x03,0x8c,0x88,0xb3,0x10 } },
+{  16, 0x93e0, 0, {0x2c,0xc4,0x0e,0xb0,0x07,0x8c,0x00,0xc2,0x08,0x38,0xc0,0x0f,0x30,0x43,0xd2,0x02 } },
+{  16, 0x93f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x10,0xfc,0x00,0x7f,0xc0 } },
+{  16, 0x9400, 0, {0x0f,0xf0,0x83,0xfc,0x21,0xdf,0x08,0x3b,0xc0,0x8f,0x90,0x01,0xfc,0x21,0xff,0x0c } },
+{  16, 0x9410, 0, {0x3f,0xc2,0x0f,0xf1,0x03,0xec,0x00,0xef,0x00,0x77,0xc0,0x1e,0xf0,0x03,0x90,0x06 } },
+{  16, 0x9420, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe8,0x01,0xf9,0x00,0x32,0xc0 } },
+{  16, 0x9430, 0, {0x0f,0xb2,0x03,0xee,0x90,0xdb,0xe1,0x3a,0xc0,0x4d,0x38,0x13,0x2d,0x30,0xfb,0x00 } },
+{  16, 0x9440, 0, {0x3e,0xe0,0x4f,0xba,0x43,0x2c,0x40,0xfa,0x00,0x3f,0xc0,0x8c,0xb0,0x03,0xea,0x00 } },
+{  16, 0x9450, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0xb1,0x00,0x21,0xc0 } },
+{  16, 0x9460, 0, {0x0b,0x71,0x02,0xcc,0x20,0xa7,0x28,0x21,0xc0,0x0b,0x70,0x13,0x5c,0x08,0xb7,0x10 } },
+{  16, 0x9470, 0, {0x2d,0xc4,0x4b,0x34,0x83,0x1c,0xc1,0xb7,0x02,0x2d,0xc0,0x1a,0x70,0x02,0xd2,0x04 } },
+{  16, 0x9480, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9a,0x20,0xb4,0xc4,0x25,0xa2 } },
+{  16, 0x9490, 0, {0x0b,0x78,0x06,0xde,0x00,0x83,0x80,0x29,0xe0,0x1b,0xf8,0x02,0x5e,0x80,0xa7,0xa0 } },
+{  16, 0x94a0, 0, {0x2d,0xc8,0x0a,0x72,0x02,0x1e,0x00,0xa6,0x80,0x28,0xe0,0x08,0x78,0x02,0xf0,0x00 } },
+{  16, 0x94b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xed,0x00,0xb3,0x40,0x24,0xc3 } },
+{  16, 0x94c0, 0, {0x0b,0x30,0x42,0xcc,0x00,0xa3,0x00,0x20,0xc0,0x1b,0x34,0x02,0x4c,0x00,0xb3,0x00 } },
+{  16, 0x94d0, 0, {0x2c,0xc0,0x4b,0x30,0x02,0x0c,0x00,0xb3,0x88,0x2c,0xd4,0x0a,0x30,0x02,0xd2,0x04 } },
+{  16, 0x94e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x00,0xfe,0x40,0xb7,0xa0 } },
+{  16, 0x94f0, 0, {0x0f,0xa0,0x03,0xe8,0x00,0xda,0x00,0x3a,0x80,0x0f,0xe2,0x03,0x68,0x00,0xfa,0x00 } },
+{  16, 0x9500, 0, {0x3e,0x80,0x0f,0xa0,0x0b,0x28,0x00,0xee,0xe0,0x3f,0xb0,0x04,0xa0,0x03,0xfa,0x04 } },
+{  16, 0x9510, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x04,0xf0,0x08,0x3a,0x10 } },
+{  16, 0x9520, 0, {0x0f,0x84,0x03,0xe0,0x10,0xf8,0x00,0x3e,0x00,0x4f,0x80,0x83,0xe0,0x00,0xf8,0x00 } },
+{  16, 0x9530, 0, {0x3c,0x00,0x0f,0x80,0x03,0x80,0x00,0xf8,0x40,0x3e,0x09,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0x9540, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x20,0xe9,0x00,0x32,0x44 } },
+{  16, 0x9550, 0, {0x0c,0x90,0x03,0x24,0x00,0xf9,0x00,0x3e,0x40,0x0f,0x90,0x13,0xe4,0x00,0xb9,0x00 } },
+{  16, 0x9560, 0, {0x1e,0x40,0x0c,0x10,0x03,0x24,0x00,0xc9,0xa0,0x3c,0x64,0x0c,0x90,0x03,0x82,0x04 } },
+{  16, 0x9570, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x00,0x22,0x68 } },
+{  16, 0x9580, 0, {0x08,0x13,0x02,0x24,0x08,0xf9,0x00,0x2e,0x48,0x1b,0x90,0x02,0xe4,0x00,0xb9,0x00 } },
+{  16, 0x9590, 0, {0x3e,0x40,0x0c,0x90,0x02,0x24,0x08,0xf9,0x40,0x2e,0x60,0x0a,0x90,0x06,0xe0,0x00 } },
+{  16, 0x95a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x24,0x00,0xa9,0x00,0x20,0x40 } },
+{  16, 0x95b0, 0, {0x08,0x90,0x02,0x24,0x00,0xb9,0x01,0x2e,0x40,0x0b,0x90,0x02,0xe4,0x00,0xb9,0x00 } },
+{  16, 0x95c0, 0, {0x2e,0x40,0x08,0x92,0x22,0x24,0x00,0x89,0x00,0x2e,0x40,0x08,0x90,0x02,0xc6,0x00 } },
+{  16, 0x95d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x80,0x81,0x21,0xe0,0x50 } },
+{  16, 0x95e0, 0, {0x28,0x16,0x0a,0x04,0x80,0xa1,0x40,0x2c,0x40,0x4b,0x14,0x22,0xc4,0x00,0xb1,0x00 } },
+{  16, 0x95f0, 0, {0x2c,0x50,0x09,0x14,0x02,0x04,0x04,0xb1,0x00,0x2c,0x40,0x0a,0x10,0x02,0xc2,0x01 } },
+{  16, 0x9600, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xe8,0x50,0x32,0x00 } },
+{  16, 0x9610, 0, {0x8c,0x80,0x02,0x20,0x00,0xb8,0x00,0x3e,0x00,0x0b,0x80,0x33,0xe0,0x10,0xf8,0x00 } },
+{  16, 0x9620, 0, {0x3e,0x00,0x0c,0x80,0x03,0x20,0x08,0xca,0x00,0x3e,0x00,0x0c,0x80,0x03,0xae,0x03 } },
+{  16, 0x9630, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xfc,0x40,0xfd,0x10,0x2f,0x41 } },
+{  16, 0x9640, 0, {0x4f,0x91,0x03,0xe4,0x40,0xf9,0x40,0x3e,0x40,0x4f,0xd0,0x63,0xe5,0x00,0xf9,0x40 } },
+{  16, 0x9650, 0, {0x3a,0x50,0x2e,0x94,0x03,0x65,0x00,0xed,0x00,0x3f,0x50,0x0f,0x90,0x03,0xe6,0x06 } },
+{  16, 0x9660, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xe6,0x00,0xf9,0xe0,0x33,0x50 } },
+{  16, 0x9670, 0, {0x0c,0xda,0x03,0xa6,0x00,0xd9,0x80,0x3f,0x40,0x0f,0x91,0x03,0xa6,0x00,0xf9,0x88 } },
+{  16, 0x9680, 0, {0x3e,0x68,0x0c,0xde,0x03,0x66,0x00,0xed,0x00,0x3b,0x69,0x0c,0x90,0x03,0xc6,0x00 } },
+{  16, 0x9690, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe1,0x08,0xb8,0xe0,0x20,0x20 } },
+{  16, 0x96a0, 0, {0x18,0x8e,0x26,0xe1,0x00,0x80,0xa0,0x2e,0x00,0x4b,0x88,0x42,0xe1,0x50,0xb8,0x40 } },
+{  16, 0x96b0, 0, {0x2e,0x2a,0x0d,0x0a,0x02,0x20,0x08,0xb8,0x00,0x2e,0x14,0x0d,0x80,0x02,0xce,0x04 } },
+{  16, 0x96c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc5,0x00,0xb1,0x60,0x20,0x40 } },
+{  16, 0x96d0, 0, {0x08,0x31,0xa2,0xc5,0x00,0x91,0x48,0x2c,0x40,0x1b,0x12,0x02,0x84,0x00,0xb1,0x00 } },
+{  16, 0x96e0, 0, {0x2c,0x50,0x09,0x16,0x02,0x05,0x00,0xa3,0x04,0x28,0x40,0x08,0x10,0x02,0xc2,0x01 } },
+{  16, 0x96f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xa4,0x00,0xb9,0x08,0x20,0x70 } },
+{  16, 0x9700, 0, {0x28,0x90,0x02,0xe4,0x00,0x89,0x00,0x2e,0x40,0x0b,0x90,0x02,0xe4,0x08,0xb9,0x03 } },
+{  16, 0x9710, 0, {0x2c,0x40,0x29,0x90,0x02,0x64,0x00,0xb9,0x00,0x2e,0x62,0x09,0x90,0x02,0xc6,0x04 } },
+{  16, 0x9720, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x05,0xe5,0x00,0xf9,0xd0,0xb2,0x70 } },
+{  16, 0x9730, 0, {0x08,0x90,0x03,0xe4,0x00,0xd9,0x04,0x3e,0x40,0x0f,0x90,0x03,0xa4,0x10,0xf9,0x02 } },
+{  16, 0x9740, 0, {0x3e,0x40,0x0d,0x90,0x2b,0x64,0x00,0xe9,0x8d,0x3a,0x60,0x0c,0x90,0x03,0xe8,0x04 } },
+{  16, 0x9750, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x80,0x3e,0x42 } },
+{  16, 0x9760, 0, {0x0f,0x90,0x03,0xe4,0x00,0xf9,0x00,0x3e,0x40,0x0f,0x9a,0x03,0xe4,0x00,0xf9,0x00 } },
+{  16, 0x9770, 0, {0x3e,0x40,0x2f,0x10,0x03,0xa4,0x00,0xf9,0x22,0x3c,0x40,0x4f,0x90,0x03,0xca,0x00 } },
+{  16, 0x9780, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa0,0x00,0xf0,0x40,0x32,0x00 } },
+{  16, 0x9790, 0, {0x0c,0x80,0x03,0xc0,0x00,0xf8,0x00,0x32,0x20,0x1f,0x80,0x03,0xe0,0x00,0xc8,0x00 } },
+{  16, 0x97a0, 0, {0x32,0x00,0x0c,0x80,0x02,0x20,0x00,0xc8,0xc0,0x3e,0x00,0x0c,0x80,0x03,0xca,0x04 } },
+{  16, 0x97b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x15,0x28,0x10,0xba,0x00,0x23,0xa0 } },
+{  16, 0x97c0, 0, {0x0a,0xe4,0x02,0xe8,0x00,0xba,0x00,0x2b,0xa1,0x0b,0xa0,0x02,0xe8,0x00,0xaa,0x00 } },
+{  16, 0x97d0, 0, {0x2a,0x81,0x0a,0xa0,0x03,0xe8,0x08,0xde,0x00,0x2e,0x80,0x0a,0xa0,0x02,0xca,0x00 } },
+{  16, 0x97e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb3,0x04,0xa0,0xb1 } },
+{  16, 0x97f0, 0, {0x08,0x36,0x22,0xcc,0x00,0xb3,0x00,0x20,0xe4,0x0b,0x30,0x02,0xcc,0x00,0x83,0x00 } },
+{  16, 0x9800, 0, {0x20,0xc0,0x08,0x18,0x02,0x0c,0x00,0x91,0x01,0x2c,0xc0,0x08,0x30,0x06,0xca,0x00 } },
+{  16, 0x9810, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0xc8,0xb3,0x21,0x21,0xc2 } },
+{  16, 0x9820, 0, {0x2a,0x70,0x02,0xdc,0x00,0xb7,0xa0,0x29,0xc0,0x0b,0x72,0x02,0xce,0x00,0xa7,0x81 } },
+{  16, 0x9830, 0, {0x29,0xc0,0x4a,0x74,0x02,0xfe,0x00,0x97,0x01,0x2c,0xc0,0x0a,0x70,0x12,0xe8,0x00 } },
+{  16, 0x9840, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x80,0xf7,0xc0,0x31,0xe0 } },
+{  16, 0x9850, 0, {0x0c,0x48,0x03,0xde,0x11,0xf7,0x80,0x21,0xe0,0x0b,0x7a,0x03,0xde,0x00,0xc3,0x80 } },
+{  16, 0x9860, 0, {0x33,0xd8,0x6c,0x78,0x03,0x3e,0x00,0xd6,0x80,0x3d,0xe0,0x0c,0x78,0x03,0xea,0x02 } },
+{  16, 0x9870, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0d,0xac,0x08,0xfb,0x80,0x3e,0xc0 } },
+{  16, 0x9880, 0, {0x0f,0xd0,0x03,0xec,0x04,0xfb,0x3c,0x3e,0xc0,0x0f,0xb6,0x07,0x6c,0x01,0xfb,0x00 } },
+{  16, 0x9890, 0, {0x3e,0xd0,0x0f,0x94,0x07,0xec,0x01,0xea,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0xc2,0x06 } },
+{  16, 0x98a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xfe,0x00,0xcf,0xa4,0x3b,0x60 } },
+{  16, 0x98b0, 0, {0x08,0xd9,0x03,0x7e,0x00,0xcf,0x80,0x3f,0x25,0x4f,0xfc,0x87,0xbe,0x00,0xcf,0x80 } },
+{  16, 0x98c0, 0, {0x7f,0xfc,0x0c,0xfc,0x03,0x7c,0x00,0xf6,0x90,0x33,0xe0,0x0f,0xf8,0x03,0xc0,0x00 } },
+{  16, 0x98d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x08,0x8f,0x28,0x21,0x40 } },
+{  16, 0x98e0, 0, {0x08,0xd0,0x02,0x1c,0x40,0xa7,0x20,0x31,0x04,0x1b,0x78,0x02,0xdc,0x80,0xd7,0x00 } },
+{  16, 0x98f0, 0, {0x2f,0xc4,0x1a,0xd0,0x02,0x1e,0x48,0xb6,0x00,0x61,0xc0,0x0b,0x70,0x06,0xea,0x04 } },
+{  16, 0x9900, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x00,0x87,0x30,0x69,0x44 } },
+{  16, 0x9910, 0, {0x08,0x50,0x22,0x0c,0x00,0x87,0x01,0x2d,0x44,0x8b,0x70,0x06,0x8c,0x10,0x87,0x00 } },
+{  16, 0x9920, 0, {0x29,0xc9,0x08,0x50,0x02,0x1c,0x44,0xa6,0x00,0x61,0xc0,0x0b,0x70,0x02,0xc0,0x00 } },
+{  16, 0x9930, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcd,0x00,0x83,0x88,0x60,0x40 } },
+{  16, 0x9940, 0, {0x00,0x10,0x02,0x4c,0x00,0x2b,0x00,0x2c,0x41,0x1b,0x30,0x02,0xcc,0x00,0x93,0x00 } },
+{  16, 0x9950, 0, {0x2c,0xc0,0x0a,0x30,0x42,0x0c,0x00,0xb2,0x40,0x20,0xf1,0x0b,0x30,0x02,0xc8,0x04 } },
+{  16, 0x9960, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbd,0x41,0xcf,0xc0,0xba,0xf0 } },
+{  16, 0x9970, 0, {0x28,0x90,0x1b,0x6c,0x08,0xcf,0x00,0x2c,0xc0,0x0f,0xf0,0x03,0xac,0x00,0x8b,0x00 } },
+{  16, 0x9980, 0, {0x3f,0xc0,0x6c,0xb0,0x4b,0x2c,0x01,0xfb,0x40,0x22,0xc8,0x0f,0xb0,0x03,0xea,0x04 } },
+{  16, 0x9990, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x04,0xfb,0x04,0x3f,0xd4 } },
+{  16, 0x99a0, 0, {0x0f,0x10,0x03,0xac,0x00,0xfb,0x00,0x32,0xc0,0x5f,0xb0,0x03,0xec,0x00,0xfb,0x04 } },
+{  16, 0x99b0, 0, {0x3e,0xc0,0x4f,0x10,0x13,0xec,0x00,0xfb,0x88,0x3e,0xc0,0x4f,0xb0,0x03,0xe0,0x00 } },
+{  16, 0x99c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xc7,0x00,0x33,0x62 } },
+{  16, 0x99d0, 0, {0x0c,0xc0,0x0b,0x3c,0x00,0xef,0x00,0x33,0xe0,0x1c,0xf0,0x13,0x3c,0x08,0xf7,0x00 } },
+{  16, 0x99e0, 0, {0x31,0xc0,0x0e,0xd8,0x03,0xbc,0x00,0xfe,0x00,0x3d,0xc6,0x0c,0xf0,0x03,0xc0,0x44 } },
+{  16, 0x99f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x00,0xcb,0x03,0x22,0x47 } },
+{  16, 0x9a00, 0, {0x08,0x98,0x42,0x2c,0x00,0x9b,0x00,0x2a,0xc0,0x0a,0xb0,0x02,0x2c,0x00,0xbb,0x04 } },
+{  16, 0x9a10, 0, {0x2a,0xc0,0x0a,0xb0,0x02,0xac,0x08,0xfa,0x00,0x2e,0x60,0x08,0xb0,0x02,0xe0,0x40 } },
+{  16, 0x9a20, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x9b,0x00,0x20,0x40 } },
+{  16, 0x9a30, 0, {0x08,0x98,0x02,0x2c,0x00,0xbb,0x00,0x22,0x88,0x08,0x30,0x02,0x2c,0x00,0xbb,0x00 } },
+{  16, 0x9a40, 0, {0x22,0xc0,0x8a,0x92,0x02,0xac,0x00,0xaa,0x80,0x2e,0xc0,0x08,0xb0,0x06,0xe0,0x00 } },
+{  16, 0x9a50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x00,0xa0,0x40 } },
+{  16, 0x9a60, 0, {0x08,0x10,0x02,0x0c,0x00,0xb3,0x00,0x28,0x80,0x0a,0x32,0x12,0x0c,0x00,0xb3,0x04 } },
+{  16, 0x9a70, 0, {0x28,0xc0,0x0a,0x30,0x22,0x8c,0x20,0xb2,0x00,0x2c,0xc0,0x08,0x30,0x02,0xc2,0x01 } },
+{  16, 0x9a80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x02,0xcb,0x00,0x30,0x40 } },
+{  16, 0x9a90, 0, {0x1c,0x94,0x03,0x2c,0x00,0xef,0x00,0x32,0xc0,0x88,0xf0,0x8b,0x2c,0x00,0xfb,0x00 } },
+{  16, 0x9aa0, 0, {0x33,0xc0,0xae,0xf0,0x03,0xac,0x80,0xea,0x01,0x3e,0xc0,0x2c,0xb0,0x03,0xc0,0x03 } },
+{  16, 0x9ab0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xff,0x00,0x2f,0x40 } },
+{  16, 0x9ac0, 0, {0x07,0xd2,0x83,0xfc,0x00,0xdf,0x04,0x3f,0xc0,0x0f,0xb0,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0x9ad0, 0, {0x3f,0xc0,0x0f,0xd0,0x0b,0xec,0x00,0xee,0x00,0x3f,0x40,0x0f,0xf0,0x03,0xe8,0x06 } },
+{  16, 0x9ae0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf5,0x00,0xcf,0x08,0x3f,0x48 } },
+{  16, 0x9af0, 0, {0x0f,0xc3,0x93,0x70,0xd0,0xdc,0x30,0x3f,0xd8,0x0c,0xb2,0x03,0x3c,0xc0,0xff,0x40 } },
+{  16, 0x9b00, 0, {0x33,0xc4,0x2c,0xf1,0x03,0x62,0x50,0xfc,0x34,0x33,0x00,0x0f,0x5c,0x03,0xf0,0x00 } },
+{  16, 0x9b10, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xc4,0x80,0x8b,0x00,0x2f,0x5a } },
+{  16, 0x9b20, 0, {0x0b,0xa6,0x12,0x21,0xc0,0x89,0x70,0x2f,0xdc,0x08,0xf2,0xc2,0x3d,0xd0,0xbf,0x40 } },
+{  16, 0x9b30, 0, {0x37,0xdc,0x88,0xf5,0x0a,0x20,0x80,0xe8,0x10,0x2a,0x16,0x0b,0x90,0x02,0xe0,0x04 } },
+{  16, 0x9b40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc0,0x00,0x83,0x08,0x2c,0x44 } },
+{  16, 0x9b50, 0, {0x0b,0x02,0x02,0x0c,0x00,0x80,0x00,0x2c,0xc8,0x08,0x33,0x42,0x8c,0x90,0xb3,0x30 } },
+{  16, 0x9b60, 0, {0x28,0xc8,0x4a,0x32,0x12,0x80,0x0c,0xb0,0xa0,0x28,0x28,0x0b,0x12,0x02,0xe2,0x01 } },
+{  16, 0x9b70, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa2,0x00,0x8b,0x00,0x2e,0x48 } },
+{  16, 0x9b80, 0, {0x0b,0xa0,0x22,0x20,0x20,0x88,0x80,0x2e,0xc0,0x28,0xb0,0x0a,0xac,0x00,0xbb,0x00 } },
+{  16, 0x9b90, 0, {0x2e,0xc0,0x0a,0xb0,0x02,0xa0,0x00,0xab,0x82,0x2a,0xa0,0x0b,0xb2,0x02,0xf0,0x04 } },
+{  16, 0x9ba0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe7,0x00,0xcb,0x00,0x3e,0xc0 } },
+{  16, 0x9bb0, 0, {0xcf,0x9c,0x0b,0x21,0x00,0xd8,0x88,0x3e,0xc0,0x0c,0xb0,0x03,0xac,0x00,0xfb,0x00 } },
+{  16, 0x9bc0, 0, {0x3a,0xc0,0x0e,0xb0,0x43,0xe8,0x40,0xf8,0x80,0x3a,0x60,0x0f,0x98,0x03,0xd0,0x04 } },
+{  16, 0x9bd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb4,0x00,0xff,0x00,0x0f,0xe0 } },
+{  16, 0x9be0, 0, {0x07,0xa1,0x03,0xe8,0x02,0xfb,0x00,0x3f,0xc0,0x0f,0x70,0x23,0x7c,0x00,0xff,0x02 } },
+{  16, 0x9bf0, 0, {0x35,0xc0,0x4d,0xb0,0x03,0x74,0x20,0xfc,0x01,0x3f,0x00,0x0f,0xf8,0x03,0xf8,0x00 } },
+{  16, 0x9c00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa5,0x00,0xcb,0x00,0xba,0x40 } },
+{  16, 0x9c10, 0, {0x0c,0x14,0x0b,0x2f,0x22,0xc9,0x40,0x32,0xc0,0x8e,0xb0,0x03,0xac,0x00,0xfb,0x00 } },
+{  16, 0x9c20, 0, {0x3e,0xc0,0x0e,0xb0,0x03,0xe4,0x00,0xc9,0x00,0x32,0x00,0x2c,0x90,0x03,0x10,0x04 } },
+{  16, 0x9c30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x01,0x24,0x00,0x8f,0x00,0x22,0x40 } },
+{  16, 0x9c40, 0, {0x2c,0xa5,0x42,0x29,0x00,0x8b,0x04,0xa3,0xc1,0x0d,0xf0,0x0a,0x3c,0x00,0xbf,0x00 } },
+{  16, 0x9c50, 0, {0x3f,0xc0,0x08,0xf0,0x01,0x69,0x00,0xda,0x05,0x22,0xd0,0x08,0x94,0x03,0x72,0x00 } },
+{  16, 0x9c60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x60,0x40,0x83,0x01,0x20,0xc0 } },
+{  16, 0x9c70, 0, {0x09,0x00,0x02,0x20,0x00,0x82,0x60,0x22,0xc0,0x08,0x30,0x42,0x4c,0x10,0xbb,0x02 } },
+{  16, 0x9c80, 0, {0x2c,0xc0,0x08,0xb0,0x12,0x05,0x00,0x9b,0x00,0x20,0x82,0x09,0x32,0x02,0x38,0x00 } },
+{  16, 0x9c90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x90,0x87,0x80,0x20,0xe0 } },
+{  16, 0x9ca0, 0, {0x08,0x58,0x02,0x16,0x14,0x84,0x81,0x21,0xe0,0x29,0x39,0x02,0x5e,0x00,0xb7,0x80 } },
+{  16, 0x9cb0, 0, {0x28,0xe0,0x08,0x78,0x02,0x7a,0x80,0x96,0x81,0x21,0xe0,0x09,0xf8,0x02,0x48,0x00 } },
+{  16, 0x9cc0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x09,0x8b,0x10,0x38,0x44 } },
+{  16, 0x9cd0, 0, {0x4d,0x25,0x12,0x0c,0x00,0xc2,0x10,0x22,0xc8,0x0a,0x38,0x03,0xcc,0x00,0xf3,0x10 } },
+{  16, 0x9ce0, 0, {0x2c,0xc0,0x0c,0x30,0x03,0x8a,0xc0,0xd9,0x10,0x32,0x40,0x2d,0x10,0x03,0x12,0x02 } },
+{  16, 0x9cf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x80,0xff,0x00,0x3f,0x40 } },
+{  16, 0x9d00, 0, {0x0f,0xf0,0x03,0xf4,0x40,0xed,0x00,0x3f,0xc0,0x0e,0xf3,0x03,0xbc,0x04,0xff,0x00 } },
+{  16, 0x9d10, 0, {0x3f,0xc2,0x0f,0xf0,0x0b,0xd4,0x00,0xff,0x10,0xbf,0x80,0x0e,0xf0,0x03,0xd0,0x06 } },
+{  16, 0x9d20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xfa,0x00,0xcb,0x02,0x3e,0xc0 } },
+{  16, 0x9d30, 0, {0x0f,0x90,0x03,0xa0,0x00,0xcb,0x00,0x3a,0xca,0x0c,0xb3,0x13,0xaf,0x24,0xcb,0x48 } },
+{  16, 0x9d40, 0, {0x1e,0xc8,0x0f,0xb6,0x03,0x2c,0x00,0xfa,0x00,0x3e,0xc0,0x0f,0x90,0x03,0xea,0x00 } },
+{  16, 0x9d50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x08,0x87,0x20,0x2d,0xc4 } },
+{  16, 0x9d60, 0, {0x0b,0x50,0x12,0xdc,0x04,0x87,0x00,0x2c,0xc0,0x08,0x70,0xa2,0x1d,0x00,0xa7,0x40 } },
+{  16, 0x9d70, 0, {0x25,0xcb,0x8b,0x74,0x82,0x1c,0x00,0xb7,0x00,0x2d,0xc1,0x0b,0x70,0x02,0xd2,0x04 } },
+{  16, 0x9d80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9a,0x01,0x87,0x90,0x2d,0xe0 } },
+{  16, 0x9d90, 0, {0x0b,0x78,0x02,0xce,0x00,0x86,0x80,0x2d,0xe4,0x29,0x7a,0x02,0x9e,0x80,0x87,0xa0 } },
+{  16, 0x9da0, 0, {0x6d,0xe8,0x0b,0x78,0x02,0x1e,0x00,0xb5,0x80,0x2d,0x60,0x0b,0x78,0x02,0xf0,0x00 } },
+{  16, 0x9db0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcd,0x00,0x83,0x02,0x2c,0xe0 } },
+{  16, 0x9dc0, 0, {0x0b,0x30,0x02,0xcc,0x00,0x83,0xe0,0x2c,0xc0,0x08,0x30,0x02,0x0c,0x00,0xa3,0x00 } },
+{  16, 0x9dd0, 0, {0x24,0xc0,0x0b,0xb0,0x02,0x0e,0x20,0xb3,0x08,0x2c,0xc0,0x0b,0x30,0x02,0xd2,0x04 } },
+{  16, 0x9de0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x82,0xca,0x00,0x3e,0xa8 } },
+{  16, 0x9df0, 0, {0x0f,0xe0,0x03,0xf8,0x02,0x8e,0x80,0x3e,0x80,0x0d,0xa0,0x5b,0xa8,0x00,0xca,0x00 } },
+{  16, 0x9e00, 0, {0x3e,0x80,0x0f,0xa0,0x03,0x3b,0x80,0xfe,0x42,0x2f,0x80,0x0f,0xa8,0x03,0xfa,0x04 } },
+{  16, 0x9e10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x20,0xf8,0x00,0x3e,0x00 } },
+{  16, 0x9e20, 0, {0x0f,0x06,0x03,0xc0,0x00,0xf8,0x11,0x3e,0x00,0x0f,0x00,0x03,0xe0,0x00,0xf8,0x00 } },
+{  16, 0x9e30, 0, {0x36,0x00,0x0f,0x80,0x0b,0xe0,0x00,0xf8,0x04,0x3e,0x20,0x0f,0x81,0x03,0xd2,0x00 } },
+{  16, 0x9e40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x00,0xf9,0x00,0x3e,0x40 } },
+{  16, 0x9e50, 0, {0x0c,0x9a,0x03,0x24,0x40,0xc9,0xc0,0x3e,0x40,0x4c,0x90,0x03,0x24,0x00,0xf9,0x00 } },
+{  16, 0x9e60, 0, {0x36,0x40,0x07,0x90,0x03,0x24,0x00,0xc9,0x04,0x32,0x60,0x0f,0x90,0x03,0xc2,0x04 } },
+{  16, 0x9e70, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x02,0x2e,0x40 } },
+{  16, 0x9e80, 0, {0x0a,0x92,0x02,0x25,0x02,0x89,0xe0,0x2e,0x40,0x98,0x90,0x02,0x24,0x00,0xb9,0x00 } },
+{  16, 0x9e90, 0, {0x22,0x40,0x09,0x90,0x02,0x04,0x00,0xd9,0x00,0x22,0x44,0x0b,0x9c,0x02,0xe0,0x00 } },
+{  16, 0x9ea0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x2c,0x00,0xb9,0x00,0x2c,0x40 } },
+{  16, 0x9eb0, 0, {0x08,0x90,0x02,0x24,0x28,0x89,0x00,0x2c,0x40,0x68,0x90,0x42,0x24,0x0c,0xb1,0x04 } },
+{  16, 0x9ec0, 0, {0x26,0x40,0x0b,0x90,0x0a,0x2c,0x80,0x81,0x00,0x22,0x40,0xcb,0x92,0x82,0xc6,0x00 } },
+{  16, 0x9ed0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb1,0x20,0x2c,0x48 } },
+{  16, 0x9ee0, 0, {0x0a,0x12,0x02,0x04,0x80,0x81,0x21,0x2c,0x4c,0x08,0x11,0x02,0x04,0x08,0xb1,0x10 } },
+{  16, 0x9ef0, 0, {0x20,0x4c,0x09,0x12,0x02,0x24,0x01,0x91,0x20,0xa0,0x48,0x0b,0x10,0x02,0xc2,0x01 } },
+{  16, 0x9f00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x41,0xe0,0xf8,0x50,0x3e,0x14 } },
+{  16, 0x9f10, 0, {0x0c,0x85,0x03,0x21,0x40,0xc8,0x50,0x3e,0x10,0x08,0x06,0x83,0x01,0xf0,0xf8,0x68 } },
+{  16, 0x9f20, 0, {0x36,0x10,0x0f,0x05,0x03,0x29,0x40,0xc8,0x50,0x32,0x94,0x0f,0x85,0x03,0xee,0x03 } },
+{  16, 0x9f30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x00,0xf9,0x10,0x3f,0x44 } },
+{  16, 0x9f40, 0, {0x0f,0xd1,0x0b,0xf4,0x40,0xfd,0x12,0x2e,0x4c,0x03,0x92,0x0b,0xe4,0x00,0xf9,0x20 } },
+{  16, 0x9f50, 0, {0x3e,0x4c,0x0f,0x91,0x03,0xfc,0x00,0xfd,0x10,0x3f,0x44,0x0f,0xd0,0x03,0xe6,0x06 } },
+{  16, 0x9f60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x20,0xc9,0x01,0x3e,0x40 } },
+{  16, 0x9f70, 0, {0x0f,0xd0,0x03,0x3c,0x00,0xbd,0x00,0x32,0x63,0x0c,0x9e,0x43,0x27,0x00,0xe9,0xc0 } },
+{  16, 0x9f80, 0, {0x3e,0x68,0x0c,0x98,0x03,0x34,0x00,0xf9,0x10,0x3f,0x40,0x0f,0xd0,0x03,0xc6,0x00 } },
+{  16, 0x9f90, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xc2,0x20,0xd8,0x00,0x2e,0x00 } },
+{  16, 0x9fa0, 0, {0x0b,0x80,0x52,0x28,0x04,0xb8,0x00,0x22,0x38,0x08,0x88,0x03,0x62,0x00,0x88,0xf0 } },
+{  16, 0x9fb0, 0, {0x2e,0x3a,0x48,0x8f,0x0a,0x20,0x00,0xb0,0x80,0x2e,0x00,0x0b,0x80,0x02,0xce,0x04 } },
+{  16, 0x9fc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x80,0x81,0x00,0x2c,0x40 } },
+{  16, 0x9fd0, 0, {0x0b,0x10,0x02,0x04,0x00,0xb1,0x00,0x20,0x42,0x48,0x14,0x42,0x05,0x80,0xa1,0x20 } },
+{  16, 0x9fe0, 0, {0x2c,0x44,0x08,0x10,0x82,0x04,0x00,0xb1,0x20,0x2c,0x40,0x0b,0x10,0x02,0xc2,0x01 } },
+{  16, 0x9ff0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa5,0x01,0x99,0x00,0x2e,0x40 } },
+{  16, 0xa000, 0, {0x0b,0x90,0x02,0x24,0x40,0xbb,0x01,0x22,0x41,0x08,0x90,0x12,0x24,0x00,0xa9,0x00 } },
+{  16, 0xa010, 0, {0x2c,0x40,0x08,0x10,0x40,0x24,0x08,0xb9,0x40,0x6e,0x50,0x0b,0x92,0x02,0xc6,0x04 } },
+{  16, 0xa020, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe7,0x14,0xc9,0x05,0x3e,0x41 } },
+{  16, 0xa030, 0, {0x0f,0x90,0x0b,0x24,0x04,0xf9,0x08,0xb2,0x40,0x2c,0x90,0x0a,0x24,0x00,0xe9,0x00 } },
+{  16, 0xa040, 0, {0x3e,0x40,0x2c,0x90,0x03,0x27,0x00,0xf9,0x80,0x3e,0x60,0x0f,0x90,0x03,0xe8,0x04 } },
+{  16, 0xa050, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x84,0x88,0xf9,0x00,0x3e,0x48 } },
+{  16, 0xa060, 0, {0x0f,0x99,0x03,0xe6,0x00,0xf9,0x02,0x3c,0x40,0xaf,0x10,0x03,0xe4,0x12,0xd9,0x04 } },
+{  16, 0xa070, 0, {0x3e,0x40,0x0f,0x90,0x03,0xe5,0x00,0xf9,0xc0,0x3e,0x64,0x0f,0x90,0x83,0xca,0x00 } },
+{  16, 0xa080, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x00,0xc8,0x00,0x3e,0x00 } },
+{  16, 0xa090, 0, {0x0f,0x80,0x03,0x21,0x00,0xc8,0x40,0xb2,0x00,0x0c,0x80,0x03,0x20,0x10,0xc8,0x00 } },
+{  16, 0xa0a0, 0, {0x32,0x00,0x0c,0x80,0x03,0xe0,0x80,0xf8,0x04,0x32,0x00,0x2c,0x80,0x0b,0x0a,0x04 } },
+{  16, 0xa0b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0xca,0x00,0x2e,0x80 } },
+{  16, 0xa0c0, 0, {0x0b,0xe8,0x0a,0x38,0x10,0x8e,0xc0,0x22,0x80,0x0d,0xa0,0x02,0x28,0x00,0x0a,0x04 } },
+{  16, 0xa0d0, 0, {0x02,0x80,0x28,0xa0,0x02,0xfb,0x00,0xba,0x00,0x37,0xb0,0x48,0xea,0x02,0x0a,0x00 } },
+{  16, 0xa0e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0x93,0x01,0x2c,0xc0 } },
+{  16, 0xa0f0, 0, {0x8b,0xb0,0x42,0x0c,0x90,0x9b,0x20,0x20,0xc0,0x48,0x30,0x42,0x2c,0x00,0x83,0x00 } },
+{  16, 0xa100, 0, {0x20,0xc0,0x08,0x30,0x02,0xcd,0x40,0xb3,0x00,0x24,0xc8,0x08,0x38,0x02,0x0a,0x00 } },
+{  16, 0xa110, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x14,0x00,0x87,0x00,0x2d,0xc0 } },
+{  16, 0xa120, 0, {0x0b,0x24,0x06,0x16,0x00,0x93,0x08,0x21,0xc8,0x09,0x31,0x02,0x0c,0x80,0x87,0xa0 } },
+{  16, 0xa130, 0, {0x21,0xc0,0x18,0x72,0x02,0xdc,0x00,0xb7,0xb4,0x24,0xe3,0x08,0x78,0x02,0x28,0x00 } },
+{  16, 0xa140, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x02,0x97,0xa0,0x3d,0xf0 } },
+{  16, 0xa150, 0, {0x0f,0x48,0x03,0x3e,0x00,0xd6,0x80,0x30,0xe0,0x2c,0x7a,0x02,0x1e,0x82,0xc3,0xf0 } },
+{  16, 0xa160, 0, {0x33,0xec,0x0c,0x7c,0x03,0xd6,0x00,0xf7,0x80,0x35,0xe0,0x0c,0xd8,0x03,0x2a,0x02 } },
+{  16, 0xa170, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x19,0xa5,0xa0,0xfb,0x00,0x3e,0xca } },
+{  16, 0xa180, 0, {0x0f,0x80,0x03,0xec,0x02,0xea,0x00,0x3e,0xc6,0x0f,0xb4,0x0b,0xed,0x40,0xfb,0x00 } },
+{  16, 0xa190, 0, {0xbe,0xc0,0x0f,0xb6,0x43,0xe0,0x00,0xfb,0x02,0x3e,0x80,0x0f,0x90,0x03,0xc2,0x06 } },
+{  16, 0xa1a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x02,0xcf,0x88,0x3f,0xe0 } },
+{  16, 0xa1b0, 0, {0x0c,0xb9,0x03,0xfe,0x00,0xdd,0x81,0x33,0xe0,0x8c,0xfc,0x03,0x3f,0x04,0xcf,0x80 } },
+{  16, 0xa1c0, 0, {0x33,0xe2,0x4f,0xfc,0x03,0x3e,0x00,0xcf,0xc0,0x33,0x64,0x0c,0xf8,0x03,0xc0,0x00 } },
+{  16, 0xa1d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x94,0x40,0x87,0x00,0x2f,0xc1 } },
+{  16, 0xa1e0, 0, {0x0d,0x69,0xa2,0xd0,0x40,0xbc,0x00,0x23,0xc0,0x08,0xf0,0x02,0x9c,0x00,0x87,0x00 } },
+{  16, 0xa1f0, 0, {0x21,0xc0,0x0b,0x70,0x0a,0x3c,0x04,0x87,0x10,0x21,0x4c,0x08,0x60,0x02,0xea,0x04 } },
+{  16, 0xa200, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9e,0x00,0x87,0x00,0x2d,0xc0 } },
+{  16, 0xa210, 0, {0x09,0x62,0x02,0xd8,0x00,0x97,0x00,0x21,0xc4,0x08,0x70,0x02,0x0c,0x40,0x97,0x00 } },
+{  16, 0xa220, 0, {0x21,0xc4,0x0b,0x30,0x02,0x58,0x00,0xa7,0x08,0x21,0x80,0x08,0x60,0x82,0xc0,0x00 } },
+{  16, 0xa230, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xe4,0x25,0x83,0x00,0x2c,0xc0 } },
+{  16, 0xa240, 0, {0x09,0x22,0x02,0xcc,0x20,0xb2,0x00,0x20,0xc0,0x28,0xb0,0x02,0x8c,0x00,0x93,0x00 } },
+{  16, 0xa250, 0, {0x20,0xc0,0x0b,0x30,0x42,0x6c,0x20,0x83,0x08,0x20,0xe2,0x08,0xb8,0x02,0xc8,0x04 } },
+{  16, 0xa260, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xa4,0x00,0xcf,0x00,0x3f,0xc0 } },
+{  16, 0xa270, 0, {0x0d,0x9c,0x03,0xe8,0x00,0xdb,0x80,0x33,0xc0,0x0c,0xf0,0x0b,0x3c,0x06,0xdf,0x00 } },
+{  16, 0xa280, 0, {0xb3,0xc0,0x0b,0xf0,0x07,0x68,0x00,0xef,0x40,0x32,0xa8,0x0c,0xa8,0x03,0xea,0x04 } },
+{  16, 0xa290, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x00,0x2e,0xc0 } },
+{  16, 0xa2a0, 0, {0x0f,0x94,0x03,0xc5,0x40,0xfa,0x30,0x3e,0xc0,0x0f,0xb0,0x03,0x6c,0x00,0xeb,0x00 } },
+{  16, 0xa2b0, 0, {0x3e,0xc0,0x0f,0x30,0x13,0xad,0x40,0xfb,0x02,0x3e,0xd0,0x0f,0xb4,0x03,0xe0,0x00 } },
+{  16, 0xa2c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xe4,0x00,0xc7,0x00,0x31,0xc1 } },
+{  16, 0xa2d0, 0, {0x8c,0xd0,0x03,0x34,0x00,0xcd,0x00,0x3d,0xc0,0x0c,0xf0,0x01,0x7c,0x00,0xdb,0x01 } },
+{  16, 0xa2e0, 0, {0x3d,0xc0,0x4c,0xf0,0x0b,0x30,0x02,0xc3,0x00,0x32,0x00,0x0f,0xd0,0x03,0x00,0x44 } },
+{  16, 0xa2f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6e,0x40,0x8b,0x00,0x2a,0xc0 } },
+{  16, 0xa300, 0, {0x28,0x84,0x42,0x22,0x80,0x88,0x80,0x3a,0xc0,0x0d,0xb0,0x02,0xac,0x08,0x8b,0x00 } },
+{  16, 0xa310, 0, {0x2e,0xc0,0x08,0xb0,0x02,0x23,0x20,0x8b,0x00,0x22,0x30,0x8b,0x8c,0x02,0x20,0x40 } },
+{  16, 0xa320, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x24,0x00,0x8b,0x00,0x22,0xc0 } },
+{  16, 0xa330, 0, {0x08,0x38,0x86,0x2a,0x00,0x89,0x80,0x2a,0xc0,0x08,0xb0,0x02,0xcc,0x00,0x9b,0x00 } },
+{  16, 0xa340, 0, {0x2e,0xc0,0x08,0xb0,0x42,0x26,0x00,0x8b,0x00,0x22,0x71,0x0b,0x8c,0x02,0x20,0x00 } },
+{  16, 0xa350, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0x83,0x00,0x28,0xc0 } },
+{  16, 0xa360, 0, {0x08,0x32,0x42,0x00,0x00,0x81,0x00,0x28,0xc0,0x09,0x30,0x52,0x8c,0x08,0x83,0x00 } },
+{  16, 0xa370, 0, {0x2c,0xc0,0x18,0x30,0x06,0x00,0x00,0x83,0x00,0xa0,0x00,0x0b,0x00,0x02,0x02,0x01 } },
+{  16, 0xa380, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x74,0x02,0x8b,0x00,0x33,0xc0 } },
+{  16, 0xa390, 0, {0x0c,0x92,0x0b,0x20,0x02,0xc8,0x00,0x3b,0xc0,0x0c,0xf5,0x03,0xfc,0x00,0xdf,0x01 } },
+{  16, 0xa3a0, 0, {0x3f,0xc1,0x04,0xf0,0x33,0x21,0x40,0xcf,0x00,0x32,0x00,0x0f,0x80,0x0b,0x00,0x03 } },
+{  16, 0xa3b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x19,0xfc,0x00,0xff,0x00,0x3f,0xc0 } },
+{  16, 0xa3c0, 0, {0x0f,0xc4,0x03,0xf0,0x00,0x9c,0x00,0x3b,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0xa3d0, 0, {0x2f,0xc0,0x0f,0xf0,0x03,0xf0,0x80,0xff,0x00,0x3f,0x00,0x0f,0xc0,0x03,0xe8,0x06 } },
+{  16, 0xa3e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0xc0,0xff,0xa0,0x31,0x24 } },
+{  16, 0xa3f0, 0, {0x0e,0xf0,0x63,0x10,0x04,0xef,0x64,0x3f,0xc0,0x4c,0xf3,0x03,0x1c,0x80,0xdf,0x08 } },
+{  16, 0xa400, 0, {0x37,0xc0,0x0f,0xf0,0x03,0xf0,0xa0,0xfc,0x00,0x31,0x08,0x2c,0xd2,0x03,0xf0,0x00 } },
+{  16, 0xa410, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe1,0x00,0xbb,0xc1,0x22,0x48 } },
+{  16, 0xa420, 0, {0x08,0xfd,0x02,0x2e,0x00,0x97,0x00,0x2f,0xc2,0x48,0x71,0x23,0x7e,0x40,0xbf,0x00 } },
+{  16, 0xa430, 0, {0x21,0xc5,0x4b,0xf5,0x02,0xef,0x00,0xbb,0x40,0x36,0xe0,0x08,0xa8,0x02,0xe0,0x04 } },
+{  16, 0xa440, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc5,0x84,0xb3,0x11,0xa2,0xc9 } },
+{  16, 0xa450, 0, {0x0a,0x30,0x02,0x00,0x01,0xb3,0x30,0x28,0xc4,0x08,0x32,0x42,0x0c,0x00,0xa3,0x08 } },
+{  16, 0xa460, 0, {0xa0,0xca,0x0a,0x32,0x82,0x80,0x10,0xb0,0x41,0x24,0x11,0x08,0x31,0x02,0xe2,0x01 } },
+{  16, 0xa470, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa5,0x00,0xbb,0x00,0x22,0xe1 } },
+{  16, 0xa480, 0, {0x28,0xb0,0x02,0x2c,0x80,0x9b,0x00,0x2e,0xc0,0x08,0xb0,0x02,0x6c,0x00,0xb3,0x00 } },
+{  16, 0xa490, 0, {0x22,0xc0,0x0b,0xb0,0x00,0xec,0x20,0xbb,0x00,0x26,0xc0,0x08,0x80,0x02,0xf0,0x04 } },
+{  16, 0xa4a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xe3,0x40,0xf7,0x04,0x32,0xc0 } },
+{  16, 0xa4b0, 0, {0x4e,0xb0,0x23,0x2e,0x20,0xeb,0x00,0x1e,0xc0,0x0c,0xb0,0x01,0x2c,0x00,0xfb,0x00 } },
+{  16, 0xa4c0, 0, {0x36,0xc0,0x1f,0xb0,0x03,0xe1,0x40,0xfb,0x00,0x36,0x98,0x0c,0x90,0x03,0xd0,0x04 } },
+{  16, 0xa4d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb6,0x04,0xff,0x02,0x3f,0xc0 } },
+{  16, 0xa4e0, 0, {0x0f,0xf0,0x03,0xfe,0x00,0xef,0x02,0x3d,0xc0,0x0f,0xf0,0x23,0xfc,0x00,0xff,0x00 } },
+{  16, 0xa4f0, 0, {0x3f,0xc0,0x4f,0xf0,0x03,0xfc,0x00,0xf4,0x00,0x3b,0x40,0x0f,0xa0,0x13,0xf8,0x00 } },
+{  16, 0xa500, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xaa,0x20,0xeb,0x10,0x36,0xc0 } },
+{  16, 0xa510, 0, {0x0d,0xb0,0x07,0xec,0x20,0xdb,0x00,0x32,0xc0,0x0c,0xb0,0x02,0x6c,0x20,0xeb,0x00 } },
+{  16, 0xa520, 0, {0x3e,0xc1,0x0d,0xb0,0x03,0xe0,0x20,0xdb,0xa0,0x32,0x90,0x4c,0xb0,0x0b,0x10,0x04 } },
+{  16, 0xa530, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2d,0x00,0x8f,0x80,0x20,0xc1 } },
+{  16, 0xa540, 0, {0x08,0x70,0x12,0xcf,0x00,0x8f,0x00,0xa3,0xc0,0x0d,0xf0,0x02,0x3c,0x00,0x8f,0x00 } },
+{  16, 0xa550, 0, {0x37,0xc0,0x88,0xf0,0x02,0xec,0x00,0x88,0x00,0x20,0x40,0x08,0x80,0x02,0x32,0x00 } },
+{  16, 0xa560, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4c,0x00,0xa3,0x80,0x24,0x81 } },
+{  16, 0xa570, 0, {0x09,0x30,0x06,0xcc,0x40,0x93,0x00,0x28,0xc1,0x08,0xb0,0x02,0xcf,0x40,0xa3,0x00 } },
+{  16, 0xa580, 0, {0x2c,0xc0,0x09,0x30,0x02,0xcd,0x00,0x90,0x40,0x60,0x40,0x28,0x10,0x02,0x38,0x00 } },
+{  16, 0xa590, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x0e,0x00,0x87,0x80,0x23,0xe0 } },
+{  16, 0xa5a0, 0, {0x48,0x79,0x02,0xde,0x41,0x97,0x80,0x29,0xe0,0x19,0x78,0x06,0x9e,0x00,0x87,0x80 } },
+{  16, 0xa5b0, 0, {0x25,0xe0,0x08,0x78,0x02,0xd2,0x03,0x83,0x80,0x21,0xa0,0x08,0x68,0x02,0x08,0x00 } },
+{  16, 0xa5c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xa3,0x00,0x34,0xc0 } },
+{  16, 0xa5d0, 0, {0x0d,0x30,0x42,0xcc,0x01,0xd3,0x10,0x3a,0xc5,0x0c,0x39,0x03,0xcc,0x00,0xe3,0x04 } },
+{  16, 0xa5e0, 0, {0x3c,0xc4,0x0d,0x30,0x03,0xce,0x00,0xd0,0x00,0x30,0x40,0x0c,0x30,0x03,0x12,0x02 } },
+{  16, 0xa5f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0xf7,0x00,0x3f,0xc0 } },
+{  16, 0xa600, 0, {0x1f,0xf0,0x53,0xfc,0x00,0xef,0x08,0x37,0xd1,0x0f,0xf0,0x83,0x7c,0x00,0xf7,0x40 } },
+{  16, 0xa610, 0, {0x3f,0xc1,0x0f,0xf1,0x03,0xd0,0x00,0xff,0x00,0xbf,0x84,0x0f,0xc8,0x03,0xd0,0x06 } },
+{  16, 0xa620, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xe0,0x00,0xfb,0x00,0x3e,0xe0 } },
+{  16, 0xa630, 0, {0x2c,0xbe,0x83,0xec,0x00,0xeb,0x40,0x3e,0xc0,0x0f,0xb4,0x03,0xed,0x20,0xfb,0x10 } },
+{  16, 0xa640, 0, {0xb6,0xd2,0x0f,0xb4,0x83,0xec,0x00,0xdb,0x80,0x36,0xc1,0x0c,0x90,0x21,0x2a,0x00 } },
+{  16, 0xa650, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x00,0xb7,0x00,0x2f,0xc0 } },
+{  16, 0xa660, 0, {0x08,0x36,0x02,0x0c,0x08,0x87,0x30,0x2d,0xd9,0x8b,0x72,0x86,0xdd,0x00,0xb3,0x20 } },
+{  16, 0xa670, 0, {0x21,0xc8,0x0b,0x74,0x02,0xd0,0x02,0x84,0x00,0xa0,0x00,0x28,0x20,0x02,0x12,0x04 } },
+{  16, 0xa680, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9a,0x00,0xb7,0x80,0x2d,0xe0 } },
+{  16, 0xa690, 0, {0x08,0x7a,0x02,0x9d,0x00,0xa7,0xa0,0x2d,0xe0,0x0b,0x78,0x02,0x9e,0x80,0xa7,0x80 } },
+{  16, 0xa6a0, 0, {0x21,0xe4,0x08,0x7a,0x26,0x9e,0x18,0x83,0x04,0x21,0xe0,0x08,0x78,0x0a,0x70,0x00 } },
+{  16, 0xa6b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0xb3,0x00,0x2c,0xe0 } },
+{  16, 0xa6c0, 0, {0x58,0x30,0x12,0x0e,0x82,0x83,0x00,0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x01,0xb3,0x00 } },
+{  16, 0xa6d0, 0, {0x20,0xc1,0x0b,0x30,0x02,0xc0,0x08,0x88,0xd2,0x20,0x20,0x08,0x00,0x02,0x52,0x04 } },
+{  16, 0xa6e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x60,0xfa,0x00,0x3f,0x82 } },
+{  16, 0xa6f0, 0, {0x0c,0xa0,0x03,0xfa,0x00,0xaa,0x00,0x1e,0x80,0x8f,0xa0,0x03,0xe8,0x00,0xf2,0x00 } },
+{  16, 0xa700, 0, {0x32,0x80,0x1f,0xa0,0x03,0xe8,0x00,0xda,0x00,0x36,0x88,0xac,0xe0,0x03,0x7a,0x04 } },
+{  16, 0xa710, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe1,0x00,0xf8,0x00,0x3e,0x20 } },
+{  16, 0xa720, 0, {0x4f,0x80,0x03,0xe1,0x00,0xf0,0x00,0x3c,0x00,0x0b,0x80,0x03,0xe0,0x00,0xf8,0x02 } },
+{  16, 0xa730, 0, {0x3a,0x00,0x0f,0x80,0x43,0xf1,0x00,0xfc,0x0a,0x3d,0x00,0x0f,0xc0,0x03,0x92,0x00 } },
+{  16, 0xa740, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe6,0x00,0xc9,0x90,0x3e,0x40 } },
+{  16, 0xa750, 0, {0x0f,0x92,0x03,0xe4,0x00,0xd9,0x00,0x32,0x40,0x04,0x90,0x07,0xe7,0x00,0xf9,0x10 } },
+{  16, 0xa760, 0, {0x30,0x40,0x0c,0x90,0x43,0xe4,0x09,0xd9,0x80,0x22,0x40,0x2c,0x10,0x0b,0x02,0x04 } },
+{  16, 0xa770, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x60,0x89,0xc0,0x2e,0x40 } },
+{  16, 0xa780, 0, {0x0b,0x98,0x26,0xc5,0x80,0x89,0x00,0x22,0x40,0x28,0x90,0x12,0xe7,0x10,0xb9,0x00 } },
+{  16, 0xa790, 0, {0x36,0x40,0x28,0x90,0x12,0xc5,0x83,0xc9,0x80,0xb6,0x40,0x08,0x90,0x02,0x20,0x00 } },
+{  16, 0xa7a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x04,0x00,0x89,0x40,0x2e,0x41 } },
+{  16, 0xa7b0, 0, {0x4b,0x90,0x02,0xe4,0x00,0x99,0x00,0xa2,0x40,0x0a,0x90,0x02,0xe5,0x00,0xb9,0x00 } },
+{  16, 0xa7c0, 0, {0xe2,0x41,0x08,0x90,0x42,0xe4,0x00,0x9d,0x50,0xab,0x4a,0x08,0xd0,0x26,0x06,0x00 } },
+{  16, 0xa7d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x82,0x81,0x20,0x2c,0x50 } },
+{  16, 0xa7e0, 0, {0x0b,0x10,0x02,0xe4,0x00,0x81,0x40,0x20,0x50,0x4a,0x14,0x32,0xc4,0x00,0xb1,0x40 } },
+{  16, 0xa7f0, 0, {0x24,0x51,0x18,0x14,0x12,0xd4,0x00,0x85,0x40,0x2d,0x40,0x08,0x50,0x06,0x02,0x01 } },
+{  16, 0xa800, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xc8,0x00,0x3e,0x00 } },
+{  16, 0xa810, 0, {0x0f,0x80,0x02,0xe0,0x00,0xd8,0x00,0x32,0x00,0x0a,0x80,0x02,0xe0,0x10,0xf8,0x00 } },
+{  16, 0xa820, 0, {0x32,0x00,0x04,0x80,0x03,0xe0,0x00,0xd8,0x00,0x3a,0x00,0x0c,0xc0,0x03,0x2e,0x03 } },
+{  16, 0xa830, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xf9,0x10,0x3f,0x41 } },
+{  16, 0xa840, 0, {0x0f,0x94,0x03,0xf5,0x00,0xf9,0x40,0x3e,0x50,0x0d,0x94,0x03,0xe5,0x10,0xf9,0x40 } },
+{  16, 0xa850, 0, {0x3e,0x50,0x4f,0x94,0x03,0xc5,0x00,0xe9,0x41,0x36,0x50,0x0f,0x94,0x03,0xe6,0x06 } },
+{  16, 0xa860, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x00,0xfd,0xa8,0x3a,0x40 } },
+{  16, 0xa870, 0, {0x0c,0xd8,0x23,0x36,0x00,0xe9,0xa0,0x3e,0x78,0x0f,0x9e,0x03,0xb6,0x80,0xcd,0xe2 } },
+{  16, 0xa880, 0, {0x32,0x68,0x0c,0x9b,0x03,0x36,0x82,0x4d,0xa0,0x37,0x68,0x8c,0x98,0x03,0x06,0x00 } },
+{  16, 0xa890, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xeb,0xa0,0xb8,0x40,0x20,0x20 } },
+{  16, 0xa8a0, 0, {0x08,0x85,0x02,0x21,0x51,0x88,0xc0,0x2e,0x29,0x0b,0x8e,0x02,0xe1,0x00,0xd8,0xe0 } },
+{  16, 0xa8b0, 0, {0x22,0x32,0x0d,0x8d,0x23,0x61,0x48,0x98,0xd4,0xa2,0x10,0x28,0x84,0x02,0x0e,0x04 } },
+{  16, 0xa8c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc5,0x00,0xb3,0x00,0x2a,0x4a } },
+{  16, 0xa8d0, 0, {0x28,0x10,0x4e,0xa4,0x08,0xa1,0x68,0x28,0x44,0x0b,0x14,0x02,0xc5,0x00,0x81,0x40 } },
+{  16, 0xa8e0, 0, {0xa0,0x50,0x08,0x10,0x02,0x04,0x02,0x91,0x2a,0x20,0x44,0x28,0x14,0x4a,0x02,0x01 } },
+{  16, 0xa8f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xac,0x80,0xb9,0x00,0x22,0x40 } },
+{  16, 0xa900, 0, {0x48,0x90,0x06,0xa4,0x00,0xa9,0x00,0x2e,0x40,0x0b,0x90,0x22,0xe4,0x00,0x99,0x00 } },
+{  16, 0xa910, 0, {0x22,0x40,0x09,0x10,0x02,0x64,0x02,0x99,0x00,0x22,0x40,0x08,0x90,0x02,0x06,0x04 } },
+{  16, 0xa920, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xf9,0x00,0x38,0x58 } },
+{  16, 0xa930, 0, {0x0c,0x90,0x53,0x84,0x14,0xa9,0x04,0x3e,0x40,0x0f,0x90,0x03,0xe4,0x00,0xc9,0x00 } },
+{  16, 0xa940, 0, {0x32,0x40,0x0c,0x90,0x03,0x24,0x04,0xd9,0x00,0xb6,0x40,0x4c,0x90,0x0b,0x28,0x04 } },
+{  16, 0xa950, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x00,0xf9,0x02,0x3e,0x49 } },
+{  16, 0xa960, 0, {0x0f,0x10,0x43,0x64,0x00,0xd9,0x00,0x3e,0x40,0x0f,0x90,0x03,0xc4,0x00,0xf1,0x02 } },
+{  16, 0xa970, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc4,0x02,0xe9,0x04,0x3c,0x40,0x0f,0x1c,0x03,0xca,0x00 } },
+{  16, 0xa980, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x80,0xc8,0x20,0x3e,0x00 } },
+{  16, 0xa990, 0, {0x8c,0x80,0x0b,0x20,0x00,0xe8,0x02,0x3e,0x00,0x0f,0x80,0x03,0xa0,0x82,0xc8,0x00 } },
+{  16, 0xa9a0, 0, {0x6c,0x00,0x0f,0x80,0x03,0x20,0x10,0xc8,0x00,0x32,0x02,0x0c,0x80,0x03,0x0a,0x04 } },
+{  16, 0xa9b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x38,0x00,0x86,0x00,0x2e,0x80 } },
+{  16, 0xa9c0, 0, {0x68,0xa8,0x80,0x3a,0x00,0x8a,0x00,0x2e,0x80,0x0b,0xa0,0x02,0xf8,0x00,0x8a,0x00 } },
+{  16, 0xa9d0, 0, {0x2e,0x80,0x0b,0xa0,0x0a,0x3a,0x00,0x8e,0x10,0x23,0x80,0x08,0xa0,0x03,0x0a,0x00 } },
+{  16, 0xa9e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4d,0x00,0x83,0x00,0x2c,0xc0 } },
+{  16, 0xa9f0, 0, {0x08,0x38,0x00,0x0c,0x60,0x23,0x00,0x2c,0xc0,0x0b,0x30,0x02,0xcc,0x40,0x83,0x00 } },
+{  16, 0xaa00, 0, {0x2c,0xc0,0x0b,0x30,0x02,0x0c,0x02,0x8a,0x80,0xa0,0xe0,0x28,0x30,0x0a,0x4a,0x00 } },
+{  16, 0xaa10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x16,0x20,0x87,0x02,0x2d,0xc1 } },
+{  16, 0xaa20, 0, {0x48,0x70,0x12,0x7c,0x00,0xa7,0x20,0x2d,0xc9,0x0b,0x72,0x00,0xdc,0x00,0x87,0x08 } },
+{  16, 0xaa30, 0, {0x2d,0xc4,0x1b,0x32,0x02,0x1d,0x01,0x87,0x42,0x21,0xc2,0x08,0x70,0x02,0x28,0x00 } },
+{  16, 0xaa40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x3e,0x02,0xc7,0x80,0x3d,0xec } },
+{  16, 0xaa50, 0, {0x0c,0x58,0x03,0x1e,0x00,0xe7,0x80,0x3d,0xec,0x0f,0x7f,0x03,0x96,0x00,0xc7,0x80 } },
+{  16, 0xaa60, 0, {0x2d,0xe2,0x07,0x79,0x03,0x0a,0x06,0xc3,0x80,0x30,0x20,0x8c,0x38,0x03,0x6a,0x02 } },
+{  16, 0xaa70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xfb,0x00,0x3e,0xc0 } },
+{  16, 0xaa80, 0, {0x0f,0x10,0x43,0x8c,0x00,0xdb,0x38,0x3e,0xd8,0x0f,0xb0,0x03,0xcc,0x04,0xfb,0x44 } },
+{  16, 0xaa90, 0, {0x3e,0xc0,0x8f,0xb6,0x13,0xec,0x02,0xff,0x02,0x3e,0x00,0x0f,0xb0,0x03,0xc2,0x06 } },
+{  16, 0xaaa0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfa,0x00,0xff,0x80,0x31,0xe3 } },
+{  16, 0xaab0, 0, {0x0e,0xf8,0x23,0xfe,0x02,0xdf,0x80,0xb7,0xe2,0x0e,0xf8,0x03,0x7e,0x00,0x6d,0xd0 } },
+{  16, 0xaac0, 0, {0x33,0xe0,0x0c,0xf8,0x9b,0x76,0xc0,0xdf,0x84,0xb3,0xe0,0x04,0xf8,0x03,0xc0,0x00 } },
+{  16, 0xaad0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x90,0x40,0xb7,0x02,0x21,0xc4 } },
+{  16, 0xaae0, 0, {0x08,0x7b,0x42,0xdc,0x00,0x87,0x00,0x21,0xc4,0x0b,0x30,0x00,0x10,0x80,0x8d,0x00 } },
+{  16, 0xaaf0, 0, {0x23,0xc0,0x0d,0xf2,0x02,0x04,0x42,0x8f,0x00,0x29,0xc8,0x28,0x70,0x02,0xea,0x04 } },
+{  16, 0xab00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x00,0xb6,0x00,0x23,0xc0 } },
+{  16, 0xab10, 0, {0x0a,0x72,0x02,0x8c,0x00,0x87,0x00,0x21,0xc0,0x0a,0x30,0x02,0x04,0x01,0xa7,0x02 } },
+{  16, 0xab20, 0, {0x21,0xc0,0x08,0x70,0x42,0x00,0x8a,0x87,0x00,0x21,0xc0,0x28,0x70,0x02,0xc0,0x00 } },
+{  16, 0xab30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xc5,0x00,0xb0,0x00,0xa0,0xd0 } },
+{  16, 0xab40, 0, {0x08,0xb0,0x02,0xc9,0x42,0x8b,0x00,0x20,0xc0,0x0b,0x30,0x22,0x04,0x00,0x83,0x00 } },
+{  16, 0xab50, 0, {0xa0,0xc0,0x49,0x30,0x02,0x45,0x40,0x93,0xc0,0xa8,0xd4,0x00,0x35,0x02,0xc8,0x04 } },
+{  16, 0xab60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xbb,0x00,0x31,0xc0 } },
+{  16, 0xab70, 0, {0x0e,0xb0,0x23,0xcd,0x00,0xdf,0x00,0x37,0xc0,0x0e,0xf0,0x01,0x68,0x00,0xe3,0x00 } },
+{  16, 0xab80, 0, {0x33,0xc0,0x1c,0xf0,0x03,0x45,0x00,0xda,0xc8,0x92,0xd4,0x2c,0xb4,0x03,0xea,0x04 } },
+{  16, 0xab90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe5,0x20,0xfb,0x00,0x3e,0xc0 } },
+{  16, 0xaba0, 0, {0x0f,0xb0,0x03,0xec,0x00,0xfb,0x00,0x3e,0xc0,0x4f,0xb0,0x03,0xad,0x00,0xfb,0x00 } },
+{  16, 0xabb0, 0, {0x7e,0xc0,0x1f,0x30,0x03,0xa4,0x80,0xe9,0x20,0x3c,0xc0,0x0f,0x32,0x03,0xe0,0x00 } },
+{  16, 0xabc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xdc,0x00,0xc7,0x00,0x33,0xc2 } },
+{  16, 0xabd0, 0, {0x2c,0xf0,0x03,0x3e,0x20,0xdb,0x00,0x13,0xc0,0x0c,0x70,0x03,0x3c,0x80,0xef,0x04 } },
+{  16, 0xabe0, 0, {0x73,0xc1,0x0f,0xf0,0x22,0x30,0x00,0xc6,0x00,0xb2,0xc0,0x0c,0xf0,0x03,0x00,0x44 } },
+{  16, 0xabf0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x69,0x00,0x8b,0x44,0xa2,0xc1 } },
+{  16, 0xac00, 0, {0x88,0xb0,0x03,0x6c,0x00,0x8b,0x00,0x22,0xc0,0x28,0xb0,0x0a,0x2d,0x00,0xbb,0x00 } },
+{  16, 0xac10, 0, {0x62,0xc0,0x0b,0xb0,0x02,0x26,0x02,0x8b,0x80,0x22,0xc0,0x08,0xb0,0x03,0x20,0x40 } },
+{  16, 0xac20, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x28,0x01,0x8a,0x08,0x22,0xc0 } },
+{  16, 0xac30, 0, {0x08,0xb2,0x02,0x6c,0x40,0x9b,0x00,0x28,0xc0,0x48,0xb0,0x16,0x29,0x04,0xb9,0x01 } },
+{  16, 0xac40, 0, {0x22,0xc0,0x49,0xb0,0x06,0xae,0x09,0x8b,0x80,0x22,0xe0,0x48,0xb0,0x02,0x20,0x00 } },
+{  16, 0xac50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x02,0x82,0x00,0x22,0xc0 } },
+{  16, 0xac60, 0, {0x88,0xb0,0x02,0x44,0x00,0x83,0x00,0x28,0xc0,0x08,0x30,0x02,0x08,0x00,0xb1,0x00 } },
+{  16, 0xac70, 0, {0x20,0xc0,0x0b,0x30,0x02,0x8c,0x00,0x83,0x80,0x20,0xe0,0x08,0x30,0x0a,0x02,0x01 } },
+{  16, 0xac80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x64,0x00,0xca,0x00,0x33,0xc0 } },
+{  16, 0xac90, 0, {0x0c,0xb2,0x03,0x2c,0x00,0xdf,0x00,0x3b,0xc0,0x4c,0xf5,0x13,0x2c,0x04,0xef,0x00 } },
+{  16, 0xaca0, 0, {0xa3,0xc0,0x0d,0xf0,0x03,0xa8,0x40,0xcb,0x00,0xb2,0x00,0x2c,0xb0,0x03,0x00,0x03 } },
+{  16, 0xacb0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf0,0x00,0xf4,0x00,0x3f,0xc0 } },
+{  16, 0xacc0, 0, {0x0f,0xb1,0x03,0xf0,0x00,0xff,0x00,0x37,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0xacd0, 0, {0x3f,0xc0,0x07,0xf0,0x0b,0x7c,0x08,0xff,0x01,0x3f,0x00,0x0f,0xf0,0x03,0xa8,0x06 } },
+{  16, 0xace0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0xc5,0xed,0x33,0x3b,0xcc } },
+{  16, 0xacf0, 0, {0x0c,0xf0,0x03,0x30,0x40,0xff,0x25,0x3f,0xcc,0x0c,0xf3,0x83,0x3c,0xd0,0xdf,0x48 } },
+{  16, 0xad00, 0, {0x37,0x30,0x4c,0xf3,0x03,0xfd,0x80,0xcf,0x28,0x33,0xd8,0x0c,0xf1,0x03,0x30,0x00 } },
+{  16, 0xad10, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0xd0,0xbb,0x31,0x20,0xcc } },
+{  16, 0xad20, 0, {0x88,0xf3,0x42,0x20,0x50,0xbf,0x90,0x2f,0xc4,0x0a,0xf6,0x02,0x7d,0xc0,0x8f,0x40 } },
+{  16, 0xad30, 0, {0x26,0x40,0x8f,0xf6,0x02,0xfd,0x00,0xff,0x08,0x39,0xc8,0x08,0xf6,0x02,0xa0,0x04 } },
+{  16, 0xad40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x80,0xa1,0x20,0x28,0xc9 } },
+{  16, 0xad50, 0, {0x08,0x30,0x9a,0x00,0x09,0xb3,0x00,0x2c,0xc0,0x20,0x30,0x02,0x4c,0x90,0x83,0x20 } },
+{  16, 0xad60, 0, {0x02,0x08,0x0b,0x33,0x12,0xcd,0x80,0x93,0x20,0x24,0xd8,0x08,0x34,0x22,0x22,0x01 } },
+{  16, 0xad70, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x11,0xae,0x00,0xbb,0x10,0x22,0xc0 } },
+{  16, 0xad80, 0, {0x08,0xb0,0x02,0x26,0x01,0x3b,0x01,0x6e,0xc0,0x08,0xb0,0x02,0x4c,0x08,0x8b,0x00 } },
+{  16, 0xad90, 0, {0xa2,0x89,0x0b,0xb0,0x02,0xec,0x00,0xab,0x00,0x6a,0xc1,0x28,0xb0,0x02,0xb0,0x04 } },
+{  16, 0xada0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0x6e,0x00,0xe8,0xc1,0x3a,0xc0 } },
+{  16, 0xadb0, 0, {0x2c,0xb0,0x43,0x26,0x00,0xfb,0x06,0x3e,0xc1,0x0c,0xb0,0x0b,0x2c,0x02,0xcb,0x00 } },
+{  16, 0xadc0, 0, {0x34,0x22,0x9f,0xb0,0x43,0xec,0x00,0x9b,0x02,0x36,0xc1,0x8c,0xb0,0x03,0x10,0x04 } },
+{  16, 0xadd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x00,0xfc,0x80,0x3d,0xd0 } },
+{  16, 0xade0, 0, {0x2f,0xf0,0x03,0xfc,0x00,0xfb,0x00,0x3d,0xc0,0x07,0x30,0x03,0xbc,0x00,0xef,0x04 } },
+{  16, 0xadf0, 0, {0x3f,0xe0,0x5e,0xb0,0x01,0xfc,0x00,0xff,0x00,0x1b,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
+{  16, 0xae00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xcb,0x01,0x3e,0xc9 } },
+{  16, 0xae10, 0, {0x0c,0xb0,0x17,0x20,0x84,0xeb,0x00,0xb2,0xc1,0x0d,0xb0,0x03,0x6c,0x00,0xc3,0x00 } },
+{  16, 0xae20, 0, {0x32,0x50,0x0f,0xb0,0x03,0x0c,0x40,0xc3,0x00,0x7e,0xc0,0x0c,0x30,0x03,0x10,0x04 } },
+{  16, 0xae30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0x8a,0x58,0x2e,0xe0 } },
+{  16, 0xae40, 0, {0x48,0xf0,0x02,0x2d,0x00,0xef,0x01,0x23,0xc0,0x08,0xf0,0x22,0x3c,0x04,0x8f,0x60 } },
+{  16, 0xae50, 0, {0x36,0x54,0x0b,0xf0,0x0a,0x3d,0x40,0x8f,0x00,0x2f,0xc0,0x08,0xf0,0x03,0x72,0x00 } },
+{  16, 0xae60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x40,0x00,0x89,0x80,0x2c,0x10 } },
+{  16, 0xae70, 0, {0x08,0xb0,0x02,0x49,0x00,0xa3,0xa0,0x24,0xc0,0x09,0x30,0x02,0x4c,0x00,0x83,0xc9 } },
+{  16, 0xae80, 0, {0x20,0x90,0x42,0x30,0x12,0x4d,0x00,0x83,0x00,0x6a,0xc0,0x09,0x30,0x02,0x38,0x00 } },
+{  16, 0xae90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x00,0x85,0x80,0x6d,0x62 } },
+{  16, 0xaea0, 0, {0x08,0x7e,0x02,0x56,0x40,0x27,0x80,0x25,0xe0,0x19,0x78,0x06,0x0e,0x00,0x83,0x80 } },
+{  16, 0xaeb0, 0, {0x61,0xa0,0x0b,0x78,0x02,0x4e,0x00,0x87,0x82,0x6d,0xe0,0x09,0x79,0x02,0x48,0x00 } },
+{  16, 0xaec0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x2c,0x02,0xc3,0x61,0x3c,0x88 } },
+{  16, 0xaed0, 0, {0x2c,0xba,0x12,0x49,0x10,0xe3,0x2c,0x36,0xc0,0x0d,0x30,0x53,0x4c,0x44,0xc3,0x00 } },
+{  16, 0xaee0, 0, {0x20,0x01,0x0f,0x31,0x03,0x4c,0x00,0xc3,0x01,0x3c,0xc0,0x2d,0xb1,0x03,0x12,0x02 } },
+{  16, 0xaef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0xff,0x00,0x3f,0x00 } },
+{  16, 0xaf00, 0, {0x4f,0xf1,0x09,0xb0,0x00,0xff,0x00,0x3b,0xc0,0x0e,0xf4,0x01,0xfd,0x24,0xff,0x40 } },
+{  16, 0xaf10, 0, {0xbf,0xc0,0x07,0xf0,0x03,0xbc,0x00,0x6f,0x10,0x3f,0xc4,0x1e,0xf1,0x83,0xd0,0x06 } },
+{  16, 0xaf20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xc4,0x00,0xe8,0x04,0x32,0x00 } },
+{  16, 0xaf30, 0, {0x0c,0xb6,0x03,0xe8,0x02,0xcb,0x00,0x36,0xca,0x0f,0xb5,0x03,0xad,0x00,0xfb,0x20 } },
+{  16, 0xaf40, 0, {0x3e,0x40,0x0f,0xb3,0x03,0xec,0x80,0xfb,0xa8,0x32,0xc6,0x8c,0xb6,0x03,0x2a,0x00 } },
+{  16, 0xaf50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x02,0xe6,0x00,0x20,0x00 } },
+{  16, 0xaf60, 0, {0x08,0x73,0x02,0xdc,0x00,0x87,0x70,0x2d,0xd0,0x0b,0xf0,0x02,0x1c,0x84,0xb7,0x20 } },
+{  16, 0xaf70, 0, {0x2d,0xc0,0x0b,0x70,0x82,0xdd,0x24,0xb7,0x40,0x34,0xc9,0x28,0x72,0x82,0x92,0x04 } },
+{  16, 0xaf80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0xbe,0x02,0xac,0x80,0xa1,0x20 } },
+{  16, 0xaf90, 0, {0x08,0x79,0x00,0xce,0x04,0x87,0x80,0x65,0xe0,0x0b,0x7a,0x02,0x9e,0x00,0xb7,0x90 } },
+{  16, 0xafa0, 0, {0x6d,0xa0,0x0b,0x78,0x02,0xde,0x00,0xb7,0x80,0x21,0xe0,0x08,0x78,0x02,0x30,0x00 } },
+{  16, 0xafb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xed,0x82,0xab,0xe0,0x20,0xe4 } },
+{  16, 0xafc0, 0, {0x08,0x30,0x02,0xee,0x04,0x83,0x00,0x2c,0xc1,0x1b,0x30,0x02,0x0c,0x08,0xb3,0x00 } },
+{  16, 0xafd0, 0, {0x64,0xf6,0x0b,0xb0,0x02,0xcc,0x04,0xb3,0x00,0x26,0xc0,0x08,0x30,0x02,0x92,0x04 } },
+{  16, 0xafe0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xbb,0x80,0xee,0x49,0x31,0xa0 } },
+{  16, 0xaff0, 0, {0x2c,0xa0,0x03,0xfa,0x00,0xca,0x02,0x36,0x80,0x0f,0xa0,0x03,0xa8,0x00,0xfa,0x02 } },
+{  16, 0xb000, 0, {0x3f,0x90,0x0f,0xa0,0x63,0xe8,0x00,0xfa,0x00,0x32,0x80,0x0c,0xa0,0x23,0x3a,0x04 } },
+{  16, 0xb010, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x0a,0xe8,0x00,0x3e,0x08 } },
+{  16, 0xb020, 0, {0x0f,0x80,0x03,0xe3,0x50,0xf0,0x00,0x3e,0x00,0x0f,0x80,0x13,0xe0,0x00,0xf8,0x00 } },
+{  16, 0xb030, 0, {0x3e,0x00,0x0f,0x80,0x03,0xe0,0x01,0xf8,0x01,0x7e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xb040, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x40,0xc9,0xa1,0x32,0x40 } },
+{  16, 0xb050, 0, {0x20,0x11,0x01,0xa6,0x40,0xc9,0x84,0x36,0x40,0x0d,0x90,0x03,0x44,0x00,0x41,0x00 } },
+{  16, 0xb060, 0, {0x32,0x40,0x0f,0x90,0x0b,0x24,0x00,0xf9,0x00,0x3e,0x40,0x4c,0x10,0x03,0x02,0x04 } },
+{  16, 0xb070, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0x89,0x82,0xa2,0x40 } },
+{  16, 0xb080, 0, {0x08,0x9c,0x02,0x25,0x00,0x89,0xc8,0x22,0x40,0x08,0x90,0x42,0x24,0x00,0x89,0x20 } },
+{  16, 0xb090, 0, {0x22,0x60,0x0b,0x90,0x02,0x24,0x10,0xb9,0x00,0x2e,0x40,0x08,0x90,0x03,0x60,0x00 } },
+{  16, 0xb0a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0x89,0x04,0x22,0xca } },
+{  16, 0xb0b0, 0, {0x0a,0x90,0x0a,0x25,0x02,0x89,0x20,0x20,0x40,0x28,0x10,0x02,0x64,0x01,0xa9,0x00 } },
+{  16, 0xb0c0, 0, {0x22,0x4b,0x0b,0x90,0x02,0x24,0x01,0xb9,0x00,0x2e,0x41,0x28,0x90,0x02,0x06,0x00 } },
+{  16, 0xb0d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x90,0x81,0xa0,0x20,0x48 } },
+{  16, 0xb0e0, 0, {0x0a,0x32,0x02,0x04,0x80,0x81,0x00,0x20,0x44,0x08,0x11,0x02,0x04,0xd0,0xa1,0x20 } },
+{  16, 0xb0f0, 0, {0x20,0x40,0x0b,0x11,0x02,0x06,0x00,0xb1,0x31,0x2c,0x48,0x08,0x14,0x02,0x42,0x01 } },
+{  16, 0xb100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x42,0xc8,0x54,0x32,0x14 } },
+{  16, 0xb110, 0, {0x0e,0x85,0x03,0x21,0x44,0xc8,0x28,0xb2,0x1a,0x4c,0x86,0x93,0x61,0x14,0xe8,0x50 } },
+{  16, 0xb120, 0, {0x22,0x14,0x0f,0x86,0x83,0x21,0x40,0xf0,0x40,0x1e,0x14,0x0c,0x00,0x03,0x2e,0x03 } },
+{  16, 0xb130, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0x74,0x44,0xf5,0x10,0x3f,0x44 } },
+{  16, 0xb140, 0, {0x0d,0x91,0x03,0x74,0x40,0xf9,0x00,0x3e,0x48,0x0b,0x92,0x03,0xe4,0xc2,0xd9,0x10 } },
+{  16, 0xb150, 0, {0xbf,0x40,0x0f,0x92,0x03,0xe5,0x04,0xf9,0x30,0x3e,0x44,0x0f,0x94,0x43,0xe6,0x06 } },
+{  16, 0xb160, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x22,0xcd,0xa1,0x33,0x61 } },
+{  16, 0xb170, 0, {0x0c,0xd8,0xd3,0x34,0x10,0xcd,0xa8,0x3e,0x60,0x8e,0x9c,0x93,0xa7,0x08,0xcd,0x80 } },
+{  16, 0xb180, 0, {0x33,0x40,0x0e,0x9a,0xd3,0x36,0xa0,0xc9,0x80,0x32,0x60,0x0c,0x99,0x03,0x06,0x00 } },
+{  16, 0xb190, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe3,0x88,0x8a,0xa0,0x20,0x28 } },
+{  16, 0xb1a0, 0, {0x08,0x80,0x22,0x20,0x12,0x88,0x40,0x2c,0x28,0x08,0x8a,0x02,0x22,0x00,0x88,0x00 } },
+{  16, 0xb1b0, 0, {0x22,0x00,0x0b,0x8c,0x03,0x21,0x00,0x88,0xd0,0xa2,0x3e,0x28,0x8d,0x02,0x0e,0x04 } },
+{  16, 0xb1c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xce,0x20,0xa1,0x48,0x20,0x52 } },
+{  16, 0xb1d0, 0, {0x29,0x10,0x02,0x24,0x03,0x81,0x00,0x2c,0x52,0x0a,0x10,0x12,0x85,0x10,0x91,0x40 } },
+{  16, 0xb1e0, 0, {0xa4,0x40,0x0a,0x12,0x82,0x44,0x00,0x91,0x28,0x24,0x40,0x28,0x12,0x02,0x02,0x01 } },
+{  16, 0xb1f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0xa9,0x14,0x22,0x40 } },
+{  16, 0xb200, 0, {0x09,0x90,0x02,0xa4,0x01,0x89,0x04,0x2c,0x40,0x08,0x90,0x02,0x24,0x00,0x99,0x00 } },
+{  16, 0xb210, 0, {0x22,0x44,0x4b,0x10,0x42,0x24,0x14,0x99,0x00,0x26,0x40,0x08,0x10,0x02,0x06,0x04 } },
+{  16, 0xb220, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x40,0xe9,0x40,0xb2,0x78 } },
+{  16, 0xb230, 0, {0x0d,0x90,0x0b,0x24,0x22,0xc9,0x03,0x3e,0x41,0x0e,0x90,0x03,0xa4,0x02,0xd9,0x00 } },
+{  16, 0xb240, 0, {0x16,0x58,0x06,0x90,0x0b,0x64,0x02,0xd9,0x00,0x36,0x40,0x0c,0x90,0x0b,0x28,0x04 } },
+{  16, 0xb250, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x84,0x00,0xd9,0x80,0x3e,0x4a } },
+{  16, 0xb260, 0, {0x0e,0x90,0x03,0x64,0x20,0xf9,0x08,0x3e,0x41,0x0f,0x90,0x03,0xe4,0x00,0xe1,0x08 } },
+{  16, 0xb270, 0, {0x3e,0x40,0x0f,0x90,0x03,0xc4,0x00,0xe1,0x00,0x38,0x40,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0xb280, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x09,0xf0,0x40,0xb0,0x10 } },
+{  16, 0xb290, 0, {0x4c,0x00,0x0b,0x20,0x00,0xf8,0x00,0x3a,0x00,0x1c,0x00,0x03,0xe0,0x00,0xc8,0x00 } },
+{  16, 0xb2a0, 0, {0x36,0x00,0x0c,0x80,0x03,0x20,0x00,0xc8,0x00,0x32,0x00,0x0f,0x80,0x03,0x0a,0x04 } },
+{  16, 0xb2b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x28,0x00,0x3e,0x88,0x23,0xa2 } },
+{  16, 0xb2c0, 0, {0x48,0xe0,0x00,0x19,0x80,0xbe,0x88,0x2e,0x80,0x0d,0xa0,0x42,0xe8,0x00,0x8e,0x00 } },
+{  16, 0xb2d0, 0, {0x23,0x90,0x08,0xa0,0x0a,0x3a,0x00,0xda,0x00,0x36,0x80,0x0b,0xa0,0x0a,0x0a,0x00 } },
+{  16, 0xb2e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb3,0x80,0x20,0xe0 } },
+{  16, 0xb2f0, 0, {0x28,0x30,0xc2,0x0f,0x10,0xb3,0x40,0x28,0xc0,0x0b,0x30,0x02,0xec,0x11,0x83,0x40 } },
+{  16, 0xb300, 0, {0x28,0xd2,0x0a,0x30,0x02,0x0c,0xc0,0x83,0x00,0x20,0xc0,0x0b,0x30,0x02,0x0a,0x00 } },
+{  16, 0xb310, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x00,0xb6,0x00,0x21,0xc0 } },
+{  16, 0xb320, 0, {0x08,0x20,0xc2,0x1c,0x10,0xb5,0x00,0x2d,0xc8,0x0a,0x72,0x02,0xdc,0x40,0x85,0x08 } },
+{  16, 0xb330, 0, {0x29,0xa2,0x1a,0x72,0x22,0x0c,0x00,0x93,0x30,0x05,0xc4,0x0b,0x32,0x22,0x28,0x00 } },
+{  16, 0xb340, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x16,0x00,0xb2,0x80,0x31,0x20 } },
+{  16, 0xb350, 0, {0x0c,0x58,0x03,0x1e,0x00,0xf7,0x80,0x39,0xf8,0x0b,0x7c,0x22,0xce,0x40,0xcf,0x80 } },
+{  16, 0xb360, 0, {0x9b,0x60,0x2e,0x3b,0x03,0x1a,0x00,0xc7,0xa8,0x11,0xe0,0x0f,0x78,0x03,0x2a,0x02 } },
+{  16, 0xb370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xa4,0x00,0xfa,0x00,0x3e,0xc0 } },
+{  16, 0xb380, 0, {0x0f,0x90,0x23,0xe8,0x00,0xfb,0x00,0x3e,0xd0,0x2d,0xb6,0x03,0xed,0x02,0xf9,0x00 } },
+{  16, 0xb390, 0, {0x32,0x40,0x0d,0xb0,0x07,0xec,0x00,0xfb,0x60,0x3e,0xc8,0x0f,0xb5,0x03,0xc2,0x06 } },
+{  16, 0xb3a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xff,0x80,0x33,0xa0 } },
+{  16, 0xb3b0, 0, {0x0c,0xf8,0x0b,0x32,0x40,0xce,0x81,0x37,0xf0,0x0c,0xbc,0x03,0xfe,0x00,0xff,0x84 } },
+{  16, 0xb3c0, 0, {0x33,0xe0,0x2c,0xf8,0x83,0xe6,0x02,0xcf,0x85,0x33,0xf0,0x0c,0xfc,0x03,0x00,0x14 } },
+{  16, 0xb3d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0xbe,0x00,0x35,0xc6 } },
+{  16, 0xb3e0, 0, {0x28,0x30,0x02,0x30,0x40,0x87,0x00,0x23,0xc0,0x08,0x7a,0x02,0xdc,0x00,0xbe,0x00 } },
+{  16, 0xb3f0, 0, {0x23,0xc0,0x08,0x70,0x12,0xfe,0x00,0x87,0x00,0x21,0xc0,0x08,0xf0,0x02,0x2a,0x04 } },
+{  16, 0xb400, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x20,0xb6,0x00,0x20,0x80 } },
+{  16, 0xb410, 0, {0x08,0x31,0x02,0x5c,0x01,0x87,0x00,0x25,0xc0,0x08,0x72,0x02,0xdc,0x00,0xb6,0x00 } },
+{  16, 0xb420, 0, {0x21,0xd0,0x09,0x70,0x02,0xd4,0x08,0x93,0x00,0x20,0xc0,0x08,0x70,0x02,0x00,0x00 } },
+{  16, 0xb430, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xc4,0x00,0xb0,0xe0,0x24,0x60 } },
+{  16, 0xb440, 0, {0x08,0x20,0x06,0x48,0x01,0x80,0x00,0x20,0xc0,0x08,0x30,0x02,0xcc,0x04,0xb3,0x00 } },
+{  16, 0xb450, 0, {0x20,0x84,0x0b,0x30,0x02,0xe8,0x00,0x9b,0x00,0x20,0xc0,0x08,0x30,0x02,0x08,0x04 } },
+{  16, 0xb460, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xb9,0xe0,0x32,0x80 } },
+{  16, 0xb470, 0, {0x6c,0xb0,0x23,0x6f,0x00,0xc3,0x00,0x37,0xc1,0x3c,0xf0,0x03,0xfc,0x00,0xfa,0x00 } },
+{  16, 0xb480, 0, {0xb0,0xc0,0x09,0xf0,0x03,0xec,0x10,0xdf,0x00,0x73,0xc0,0x0c,0xf0,0x0b,0x2a,0x00 } },
+{  16, 0xb490, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x10,0xf8,0x00,0x3e,0x42 } },
+{  16, 0xb4a0, 0, {0x0f,0x24,0x03,0xa8,0x60,0xf8,0x00,0x3c,0xc1,0x0f,0xb0,0x03,0xec,0x00,0xf9,0x40 } },
+{  16, 0xb4b0, 0, {0x3e,0x80,0x04,0xb0,0x23,0xe1,0x00,0xeb,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0xe0,0x00 } },
+{  16, 0xb4c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xf4,0x00,0xee,0x00,0x3d,0x30 } },
+{  16, 0xb4d0, 0, {0x0c,0xc0,0x03,0x14,0x00,0xcc,0xa0,0xb3,0xc0,0x4c,0x70,0x03,0x5c,0x10,0xdf,0x00 } },
+{  16, 0xb4e0, 0, {0x3f,0x00,0x0c,0xf0,0x03,0xf8,0x00,0xcf,0x00,0x23,0xc0,0x0c,0xf0,0x03,0x00,0x40 } },
+{  16, 0xb4f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x64,0x00,0xba,0x81,0x2e,0x58 } },
+{  16, 0xb500, 0, {0x08,0x88,0x02,0x27,0x80,0x89,0x20,0x22,0xc0,0x28,0xb0,0x02,0x2c,0x00,0x88,0x83 } },
+{  16, 0xb510, 0, {0x2e,0x20,0x05,0xb0,0x62,0xe3,0x00,0x8b,0x00,0x2a,0xc0,0x08,0xb0,0x03,0x60,0x40 } },
+{  16, 0xb520, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x26,0x00,0xb9,0x81,0x2e,0x40 } },
+{  16, 0xb530, 0, {0x08,0x8c,0x06,0x26,0x00,0x88,0x00,0x22,0xc0,0x08,0xb0,0x16,0x6c,0x00,0x98,0x88 } },
+{  16, 0xb540, 0, {0x2e,0x20,0x08,0xb0,0x04,0xe3,0x01,0x0b,0x00,0x28,0xc0,0x08,0x30,0x02,0x20,0x00 } },
+{  16, 0xb550, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0xb0,0x00,0x2c,0xc0 } },
+{  16, 0xb560, 0, {0x28,0x00,0x0e,0x00,0x10,0x80,0x00,0x20,0xc0,0x08,0x32,0x02,0x0c,0x00,0x80,0x04 } },
+{  16, 0xb570, 0, {0x2e,0x20,0x09,0x30,0x02,0xc4,0x12,0x83,0x00,0x28,0xc0,0x08,0x30,0x02,0x42,0x01 } },
+{  16, 0xb580, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xfa,0x00,0x3e,0x00 } },
+{  16, 0xb590, 0, {0x2c,0x91,0x03,0x20,0x00,0x8a,0x00,0x33,0xc0,0x0c,0xf0,0x03,0x7c,0x00,0xd8,0x00 } },
+{  16, 0xb5a0, 0, {0x2e,0x40,0x0c,0xf0,0x03,0xe0,0x80,0xcf,0x00,0x3b,0xc0,0x0c,0xf0,0x03,0x00,0x03 } },
+{  16, 0xb5b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xfc,0x00,0xfc,0x01,0x3f,0x40 } },
+{  16, 0xb5c0, 0, {0x0f,0xc0,0x13,0xf0,0x00,0xf4,0x00,0x3f,0xc1,0x0f,0xf4,0x23,0xfc,0x08,0xfc,0x00 } },
+{  16, 0xb5d0, 0, {0x3f,0x00,0x0f,0xf0,0x03,0xf0,0x40,0xff,0x00,0x3f,0xc0,0x0f,0xf0,0x03,0xe8,0x06 } },
+{  16, 0xb5e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfc,0x20,0xcd,0x10,0x39,0xc8 } },
+{  16, 0xb5f0, 0, {0x0d,0xc1,0x03,0x3c,0x80,0xef,0x90,0x23,0xd8,0x0f,0xf8,0x00,0xfe,0x00,0xcf,0x80 } },
+{  16, 0xb600, 0, {0x1f,0xd0,0x0f,0xf9,0x03,0xff,0x00,0xe7,0xc0,0x33,0xc4,0x0f,0xf0,0x03,0xb0,0x00 } },
+{  16, 0xb610, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x10,0xfe,0x02,0x89,0x40,0x23,0xf0 } },
+{  16, 0xb620, 0, {0x08,0x85,0x10,0x3c,0x00,0x8b,0x00,0xa3,0xdc,0x4b,0xb2,0x82,0xec,0x20,0x8b,0x00 } },
+{  16, 0xb630, 0, {0x26,0xc0,0x4b,0xb0,0x02,0xec,0x10,0xb9,0x04,0x2a,0xc9,0x0b,0xb5,0x80,0xf0,0x04 } },
+{  16, 0xb640, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0xcc,0x00,0x81,0x64,0x28,0xc4 } },
+{  16, 0xb650, 0, {0x09,0xb2,0x0a,0x0c,0xf0,0xa3,0x20,0x20,0xc8,0x0b,0x32,0x02,0xec,0x02,0x83,0x08 } },
+{  16, 0xb660, 0, {0x2c,0xc8,0x09,0x32,0x02,0xcc,0x80,0xab,0xa0,0x20,0xc8,0x0b,0x32,0x00,0xb2,0x01 } },
+{  16, 0xb670, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x10,0x89,0x00,0x22,0xc0 } },
+{  16, 0xb680, 0, {0x08,0xb2,0x12,0x2c,0x02,0x0b,0x00,0x22,0xc0,0x0b,0xb8,0x02,0xec,0x00,0x8b,0x00 } },
+{  16, 0xb690, 0, {0x26,0xc0,0x4b,0xb0,0x46,0xec,0x00,0xb9,0x00,0x0a,0xc0,0x0b,0xb0,0x02,0xf0,0x04 } },
+{  16, 0xb6a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x15,0xec,0x10,0xc9,0xe0,0x3a,0xc0 } },
+{  16, 0xb6b0, 0, {0x0d,0x28,0x03,0x2c,0x00,0xeb,0x10,0x32,0xc0,0x0f,0x82,0x03,0xc4,0x00,0xcb,0x00 } },
+{  16, 0xb6c0, 0, {0x3e,0xc1,0x0f,0xb0,0x06,0xec,0x08,0xe9,0x00,0xb2,0xc0,0x0f,0xb0,0x13,0x90,0x04 } },
+{  16, 0xb6d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x9c,0x00,0xf5,0xa0,0x3f,0xc0 } },
+{  16, 0xb6e0, 0, {0x0f,0xe8,0x03,0xfc,0x08,0xff,0x00,0x3f,0xc0,0x8f,0xc0,0x03,0xfc,0x00,0xff,0x00 } },
+{  16, 0xb6f0, 0, {0x37,0xc0,0x0f,0xf0,0x03,0xfc,0x00,0xff,0x04,0x3e,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
+{  16, 0xb700, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x10,0xac,0x00,0xf9,0x40,0x34,0xc0 } },
+{  16, 0xb710, 0, {0x0d,0xb4,0x03,0x2c,0x00,0xdb,0x40,0x3e,0xc0,0x2c,0x80,0x03,0x64,0x08,0xfb,0x10 } },
+{  16, 0xb720, 0, {0x3e,0xc6,0x8f,0xb0,0x03,0xec,0x00,0xf9,0x80,0x32,0xc0,0x0c,0xb0,0x0b,0x14,0x04 } },
+{  16, 0xb730, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x3e,0x20,0xe9,0xc8,0x37,0xd4 } },
+{  16, 0xb740, 0, {0x48,0xaa,0x22,0x1c,0x00,0x8b,0x00,0x6f,0xe0,0x08,0x85,0x82,0xed,0x40,0xbb,0x84 } },
+{  16, 0xb750, 0, {0x2f,0xc0,0x4b,0xb8,0x03,0xad,0x40,0xb3,0x00,0x23,0xd4,0x08,0xf7,0x02,0x32,0x00 } },
+{  16, 0xb760, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x4c,0x00,0xb1,0x64,0xa4,0xc0 } },
+{  16, 0xb770, 0, {0x09,0x20,0x0a,0x0c,0x04,0xb8,0x00,0x6c,0xc0,0x08,0x38,0x02,0xc8,0x40,0xb3,0x80 } },
+{  16, 0xb780, 0, {0x2c,0xd1,0x0b,0x30,0x02,0xcc,0x04,0xb3,0x00,0x28,0xc0,0x08,0x30,0x02,0x3a,0x00 } },
+{  16, 0xb790, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x01,0x1e,0x00,0xa5,0x80,0x25,0xe0 } },
+{  16, 0xb7a0, 0, {0x88,0x3a,0x12,0x1e,0x00,0xa6,0x90,0x2d,0xe2,0x08,0x79,0x02,0xda,0x00,0xb7,0x82 } },
+{  16, 0xb7b0, 0, {0x2d,0xe0,0x03,0x78,0x82,0x9e,0x00,0xbc,0xc1,0x29,0xe0,0x08,0x78,0x02,0x2c,0x10 } },
+{  16, 0xb7c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x08,0x0c,0x00,0xf3,0x00,0x34,0xc0 } },
+{  16, 0xb7d0, 0, {0x0d,0x3e,0x03,0x0c,0x00,0xf0,0x40,0x2e,0xc0,0x0c,0x30,0x43,0xc8,0x00,0xf3,0x00 } },
+{  16, 0xb7e0, 0, {0x3c,0xc0,0x07,0x30,0x03,0xcc,0x80,0xf2,0x00,0x38,0xc0,0x0c,0x30,0x03,0x12,0x02 } },
+{  16, 0xb7f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x19,0xbd,0x20,0xf7,0x00,0x3f,0xc2 } },
+{  16, 0xb800, 0, {0x0f,0xf1,0x0b,0xdc,0x20,0xde,0x04,0x3f,0xd2,0x07,0xf0,0x13,0xf8,0x40,0xff,0x00 } },
+{  16, 0xb810, 0, {0x3f,0xc0,0x07,0xf0,0x03,0xfc,0x00,0xfd,0x00,0x37,0xc0,0x0f,0x70,0x03,0xd0,0x06 } },
+{  16, 0xb820, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x05,0xcf,0x00,0xdc,0x00,0x3e,0xca } },
+{  16, 0xb830, 0, {0x0f,0xa0,0x00,0xac,0x92,0xc9,0x00,0x32,0xc0,0x0f,0xb0,0x11,0xa4,0x08,0xfb,0x00 } },
+{  16, 0xb840, 0, {0x2e,0xc0,0x4f,0xb0,0x23,0xec,0x00,0xf9,0x00,0x3e,0xc4,0x0f,0xb0,0x03,0xea,0x00 } },
+{  16, 0xb850, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x91,0x9c,0x00,0x84,0x00,0x01,0xc0 } },
+{  16, 0xb860, 0, {0x4b,0x70,0x22,0x1c,0xc0,0x87,0x00,0x21,0xc0,0x4b,0x70,0x02,0x1c,0x00,0xb7,0x01 } },
+{  16, 0xb870, 0, {0x25,0xd8,0x0b,0x70,0x22,0xdc,0x00,0xb6,0x00,0x2d,0xc0,0x0b,0x72,0x22,0xf2,0x04 } },
+{  16, 0xb880, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x9e,0x80,0x97,0x80,0xa9,0xe0 } },
+{  16, 0xb890, 0, {0x0b,0xf8,0x02,0xce,0x08,0x85,0x80,0x29,0xe8,0x0b,0xfc,0x02,0x17,0x00,0xb7,0x80 } },
+{  16, 0xb8a0, 0, {0x2d,0xe0,0x8b,0x78,0x02,0xde,0x00,0xb4,0xc0,0x2d,0xe8,0x0b,0x79,0x02,0xe0,0x00 } },
+{  16, 0xb8b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0x83,0x08,0xa0,0xc0 } },
+{  16, 0xb8c0, 0, {0x8b,0x3c,0x02,0x4c,0x00,0x83,0x00,0xa0,0xc0,0x1b,0x3c,0x0a,0x0f,0x29,0xb3,0x00 } },
+{  16, 0xb8d0, 0, {0x24,0xc0,0x0b,0x30,0x02,0xcc,0x00,0xb3,0x80,0x2c,0xc0,0x0b,0x30,0x02,0xd2,0x04 } },
+{  16, 0xb8e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xde,0x00,0x3a,0x80 } },
+{  16, 0xb8f0, 0, {0x0f,0xea,0x02,0xe8,0x00,0xce,0x00,0x3a,0x80,0x0f,0xe0,0x03,0x38,0x00,0xfa,0x00 } },
+{  16, 0xb900, 0, {0x3e,0x80,0x0f,0xa0,0x03,0xe8,0x00,0xfe,0x00,0x3e,0x80,0x0b,0xa0,0x03,0xfa,0x04 } },
+{  16, 0xb910, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x00,0xf8,0x04,0xba,0x01 } },
+{  16, 0xb920, 0, {0x0f,0x82,0x0b,0x80,0x04,0xf8,0x80,0x3e,0x00,0x0f,0x86,0x03,0x60,0x00,0xf8,0x00 } },
+{  16, 0xb930, 0, {0x36,0x00,0x0f,0x80,0x23,0xe1,0x00,0xf8,0x00,0x3e,0x00,0x0f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xb940, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x01,0xf9,0x00,0x32,0x40 } },
+{  16, 0xb950, 0, {0x0f,0x90,0x03,0xe4,0x00,0x49,0x00,0x32,0x40,0x0b,0x90,0x03,0x24,0x00,0x49,0x00 } },
+{  16, 0xb960, 0, {0x3c,0x40,0x0d,0x90,0x03,0xe4,0x08,0xc9,0x00,0x3e,0x60,0x0c,0x90,0x03,0x02,0x04 } },
+{  16, 0xb970, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x00,0xb9,0x40,0xa2,0x64 } },
+{  16, 0xb980, 0, {0x0b,0x18,0x02,0x25,0x00,0xd1,0x50,0x36,0x50,0x4e,0x90,0x0a,0x24,0x02,0x89,0x40 } },
+{  16, 0xb990, 0, {0x3a,0x51,0x08,0x94,0x02,0xe5,0x22,0x89,0x44,0x2e,0x60,0x28,0x90,0x0a,0x20,0x00 } },
+{  16, 0xb9a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x24,0x00,0xb1,0x08,0x22,0x40 } },
+{  16, 0xb9b0, 0, {0x4b,0x92,0x82,0xa5,0x00,0xa9,0x08,0x22,0x50,0x0a,0x10,0x02,0x0c,0x00,0xa9,0x40 } },
+{  16, 0xb9c0, 0, {0x6e,0x50,0x0b,0x94,0x02,0xc4,0x04,0x89,0x44,0x6c,0x48,0x88,0x10,0x02,0x46,0x00 } },
+{  16, 0xb9d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x00,0xb1,0x40,0xe0,0x40 } },
+{  16, 0xb9e0, 0, {0x1b,0x14,0x0a,0x04,0x00,0xb9,0x00,0x24,0x40,0x1a,0x10,0x22,0x04,0x00,0xa1,0x00 } },
+{  16, 0xb9f0, 0, {0x28,0x40,0x0a,0x10,0x12,0xc4,0x00,0x81,0x02,0x6c,0x40,0x08,0x12,0x02,0x42,0x01 } },
+{  16, 0xba00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x08,0xb0,0x00,0x32,0x00 } },
+{  16, 0xba10, 0, {0x4f,0x80,0x02,0xa1,0x50,0xe0,0x50,0x32,0x14,0x0e,0xa5,0x23,0x21,0x40,0xe8,0x50 } },
+{  16, 0xba20, 0, {0x3e,0x14,0x0f,0x85,0x03,0xe1,0x40,0xc8,0x50,0x1e,0x14,0x0c,0x85,0x43,0x6e,0x03 } },
+{  16, 0xba30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0x19,0xe5,0x00,0xfd,0x40,0x3e,0x50 } },
+{  16, 0xba40, 0, {0x0f,0x74,0x03,0xa5,0x00,0x5d,0x00,0x3e,0x50,0x0a,0x50,0x13,0xf4,0x00,0xd9,0x00 } },
+{  16, 0xba50, 0, {0x3a,0x50,0x0d,0x90,0x13,0xe4,0x00,0xff,0x00,0x3e,0x50,0x0f,0x91,0x03,0xa6,0x06 } },
+{  16, 0xba60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf6,0x90,0xbd,0xe8,0x23,0x6b } },
+{  16, 0xba70, 0, {0x0b,0xda,0x0b,0x36,0x80,0xc9,0x00,0x32,0x68,0x46,0x90,0x43,0xe4,0x00,0x49,0x00 } },
+{  16, 0xba80, 0, {0x32,0x68,0x0c,0x90,0x03,0x24,0x40,0xf9,0x00,0x32,0x60,0x0c,0x9c,0x03,0xc6,0x01 } },
+{  16, 0xba90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x10,0xe1,0x00,0xb8,0xe0,0xa2,0x11 } },
+{  16, 0xbaa0, 0, {0x0b,0x8e,0x0a,0x23,0x22,0x88,0x80,0x2a,0x31,0x28,0x88,0x02,0x62,0x00,0x88,0x80 } },
+{  16, 0xbab0, 0, {0xa2,0x30,0x28,0x88,0x8a,0x22,0x00,0xb8,0xa8,0xa2,0x39,0x08,0xca,0x02,0xce,0x04 } },
+{  16, 0xbac0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x05,0xc5,0x08,0x21,0x00,0x00,0x40 } },
+{  16, 0xbad0, 0, {0x03,0x14,0x82,0x85,0x80,0xad,0x08,0x21,0x52,0x98,0x50,0x82,0x34,0x23,0x85,0x08 } },
+{  16, 0xbae0, 0, {0x21,0x52,0x08,0x50,0x06,0x54,0x00,0xb5,0x20,0x21,0x5a,0x09,0x54,0x02,0xd2,0x01 } },
+{  16, 0xbaf0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x11,0xa4,0x00,0xb9,0x61,0x22,0x40 } },
+{  16, 0xbb00, 0, {0x0b,0x90,0x06,0x04,0x00,0xad,0x00,0x69,0x40,0x08,0xd0,0x02,0x74,0x00,0x85,0x00 } },
+{  16, 0xbb10, 0, {0x01,0x40,0x00,0x70,0x06,0x74,0x04,0xb5,0x00,0x23,0x40,0x09,0xd0,0x02,0xc6,0x04 } },
+{  16, 0xbb20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x14,0xa4,0x00,0xe9,0x00,0x32,0x40 } },
+{  16, 0xbb30, 0, {0x4f,0x95,0x0b,0xa4,0x00,0xe9,0x00,0x32,0x40,0x8c,0x90,0x03,0x24,0x00,0xc9,0x00 } },
+{  16, 0xbb40, 0, {0x32,0x40,0x0c,0x90,0x03,0x64,0x08,0xf9,0x00,0x32,0x40,0x3d,0x90,0x03,0xe8,0x04 } },
+{  16, 0xbb50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x01,0xa4,0x08,0xf9,0x00,0x3e,0x40 } },
+{  16, 0xbb60, 0, {0x4f,0x90,0x8b,0xe4,0x04,0xd9,0x01,0x3e,0x40,0x0d,0x90,0x03,0x64,0x00,0xd9,0x01 } },
+{  16, 0xbb70, 0, {0x3e,0x40,0x0f,0x90,0x03,0xa4,0x00,0xf9,0x00,0x3c,0x40,0x0e,0x90,0x03,0xda,0x00 } },
+{  16, 0xbb80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xf8,0x40,0x36,0x20 } },
+{  16, 0xbb90, 0, {0x17,0x84,0x03,0x20,0x21,0xc8,0x00,0x7e,0x02,0x2c,0x80,0x43,0x20,0x00,0xe8,0x02 } },
+{  16, 0xbba0, 0, {0x3e,0x01,0x0f,0x80,0x03,0xe0,0x00,0xc8,0x40,0x1e,0x00,0x0f,0x80,0x03,0xca,0x04 } },
+{  16, 0xbbb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x2a,0x88,0xb6,0x02,0x23,0xa0 } },
+{  16, 0xbbc0, 0, {0x0b,0xec,0x42,0x2b,0x00,0xd2,0x80,0x6e,0xb1,0x08,0xa0,0x22,0x08,0x00,0xea,0x04 } },
+{  16, 0xbbd0, 0, {0x3a,0x80,0x9f,0xa0,0x03,0xa8,0x00,0x8a,0x04,0x2e,0x80,0x0b,0xa8,0x02,0xca,0x00 } },
+{  16, 0xbbe0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xb2,0x00,0xa4,0xe1 } },
+{  16, 0xbbf0, 0, {0x8b,0xb4,0x32,0x47,0x45,0x83,0x90,0x2c,0xf4,0x4b,0x38,0x12,0x0e,0x44,0xa3,0x01 } },
+{  16, 0xbc00, 0, {0x2c,0xc0,0x4b,0x30,0x02,0xce,0x00,0x93,0x00,0x6c,0xc0,0x0b,0x38,0x02,0xca,0x00 } },
+{  16, 0xbc10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x00,0xb7,0x44,0x21,0xc2 } },
+{  16, 0xbc20, 0, {0x0b,0x54,0x02,0x54,0x05,0x87,0x00,0x2c,0x40,0x9b,0x6c,0x02,0x18,0x10,0xa7,0x04 } },
+{  16, 0xbc30, 0, {0x29,0xc0,0x0a,0x70,0x02,0x9b,0x00,0x97,0x04,0x0d,0x80,0x0b,0x60,0x82,0xe8,0x00 } },
+{  16, 0xbc40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xf3,0x80,0x35,0xe0 } },
+{  16, 0xbc50, 0, {0x0b,0x38,0x02,0x52,0x10,0x84,0x80,0x2d,0xa0,0x0f,0xf8,0x0b,0x1e,0x00,0xe6,0x80 } },
+{  16, 0xbc60, 0, {0x1d,0xa0,0x0b,0x68,0x03,0xfe,0x02,0xd6,0x80,0x3d,0xe0,0x0f,0x78,0x03,0xea,0x02 } },
+{  16, 0xbc70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x1d,0xac,0x00,0xfb,0x00,0x3e,0xc1 } },
+{  16, 0xbc80, 0, {0x8b,0x90,0x0b,0x80,0x0a,0xb8,0x01,0x2e,0x00,0x0c,0xb0,0x03,0xe8,0x00,0xfa,0x00 } },
+{  16, 0xbc90, 0, {0x3e,0xc0,0x0f,0xa0,0x43,0xec,0x00,0xeb,0x00,0x3e,0x80,0x0f,0xa6,0x23,0xc2,0x02 } },
+{  16, 0xbca0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfe,0x00,0xfe,0x80,0x33,0x20 } },
+{  16, 0xbcb0, 0, {0x4e,0xc9,0x12,0xf6,0x50,0xef,0x90,0x3f,0xe0,0x0c,0x19,0x00,0xb6,0x42,0xcf,0x21 } },
+{  16, 0xbcc0, 0, {0x3f,0xe0,0x0e,0xf9,0x02,0xe6,0xc0,0xff,0x80,0x3f,0xe0,0x4c,0xdc,0x03,0x40,0x00 } },
+{  16, 0xbcd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x11,0x94,0x00,0xb7,0x00,0x81,0x40 } },
+{  16, 0xbce0, 0, {0x08,0x03,0x02,0x14,0xc4,0x87,0x01,0x2d,0xc8,0x08,0x6a,0x12,0x38,0x40,0x87,0x02 } },
+{  16, 0xbcf0, 0, {0x2d,0xc0,0x08,0x71,0x12,0xd2,0x80,0xb7,0x00,0x2d,0x80,0x08,0x60,0x02,0x2a,0x04 } },
+{  16, 0xbd00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0xb7,0x10,0x21,0x80 } },
+{  16, 0xbd10, 0, {0x08,0xf4,0x12,0x94,0x04,0xa6,0x00,0x2c,0xc0,0x18,0xd2,0x02,0x14,0x48,0x86,0x10 } },
+{  16, 0xbd20, 0, {0x2d,0x80,0x0a,0x61,0x32,0xd4,0x00,0xb6,0x18,0x2d,0xc4,0x08,0x58,0x02,0x00,0x10 } },
+{  16, 0xbd30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xc4,0x00,0xb3,0x00,0x20,0xc0 } },
+{  16, 0xbd40, 0, {0x40,0xb0,0x22,0x04,0x00,0x82,0x81,0x0c,0xc0,0x08,0x30,0x0a,0x0a,0x00,0x8a,0x00 } },
+{  16, 0xbd50, 0, {0x2e,0xc0,0x08,0xa0,0x02,0xc4,0x00,0xbb,0x00,0x2e,0x80,0x08,0x20,0x02,0x08,0x04 } },
+{  16, 0xbd60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xfb,0x00,0xa0,0xc0 } },
+{  16, 0xbd70, 0, {0x24,0x94,0x23,0xac,0x10,0xeb,0xa0,0x0e,0xc0,0x0c,0xb0,0x02,0x2e,0x20,0xc9,0x00 } },
+{  16, 0xbd80, 0, {0x2e,0x40,0x0e,0x90,0x03,0xec,0x00,0xf9,0x80,0x3e,0x40,0x6c,0xa0,0x0b,0x2a,0x04 } },
+{  16, 0xbd90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xcc,0x00,0xfb,0x00,0x3e,0xc0 } },
+{  16, 0xbda0, 0, {0x89,0x90,0x03,0x2c,0x00,0xfb,0x02,0x3e,0x40,0x4f,0xa0,0x03,0x6d,0x01,0xfb,0x41 } },
+{  16, 0xbdb0, 0, {0x3e,0xc0,0x8f,0xb4,0x03,0xe8,0x00,0xfb,0x20,0x3e,0x50,0x0f,0xa4,0x03,0xe0,0x00 } },
+{  16, 0xbdc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xc3,0x20,0xb2,0xc0 } },
+{  16, 0xbdd0, 0, {0x0d,0xd0,0x03,0x38,0x00,0xcd,0x00,0x3f,0x80,0x0d,0xf0,0x03,0xfc,0x00,0xfd,0x02 } },
+{  16, 0xbde0, 0, {0x36,0x00,0x0c,0xd0,0x03,0x3f,0x08,0xfc,0x04,0x12,0xc0,0x0c,0xa0,0x03,0xc0,0x44 } },
+{  16, 0xbdf0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x6c,0x02,0x8b,0xc8,0x22,0xc0 } },
+{  16, 0xbe00, 0, {0x08,0x98,0x0a,0x2a,0x40,0x89,0x20,0x2e,0x01,0x8e,0xb0,0x12,0xec,0x80,0xbb,0xf0 } },
+{  16, 0xbe10, 0, {0x22,0xe5,0x08,0xbd,0x02,0x2e,0x00,0xbb,0x90,0x22,0xed,0x08,0xa2,0x02,0xe0,0x00 } },
+{  16, 0xbe20, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0x8b,0x01,0x22,0x00 } },
+{  16, 0xbe30, 0, {0x49,0xa8,0x1e,0x04,0x00,0x8b,0x01,0x2e,0xc0,0x49,0x90,0x02,0xe4,0x00,0xb9,0x00 } },
+{  16, 0xbe40, 0, {0x22,0x40,0x0a,0x90,0x02,0x2c,0x00,0xb9,0x00,0x2a,0x40,0x08,0x80,0x02,0xe0,0x00 } },
+{  16, 0xbe50, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x00,0x81,0x00,0x20,0x40 } },
+{  16, 0xbe60, 0, {0x08,0x20,0x02,0x04,0x00,0x83,0x00,0x2c,0xc0,0x0a,0x20,0x42,0xcc,0x00,0xb3,0x00 } },
+{  16, 0xbe70, 0, {0x20,0xc0,0x02,0x30,0x02,0x08,0x84,0xb3,0x04,0x08,0x40,0x08,0x20,0x02,0xc2,0x11 } },
+{  16, 0xbe80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0x8b,0x00,0xb2,0x80 } },
+{  16, 0xbe90, 0, {0x0d,0xb1,0x03,0x24,0x02,0xcb,0x01,0x3e,0xc0,0x4d,0x90,0x43,0xe4,0x00,0xf9,0x00 } },
+{  16, 0xbea0, 0, {0xb2,0x00,0x2e,0x90,0x0b,0x2c,0x80,0xf8,0x00,0xba,0xc0,0x2c,0x80,0x03,0xc0,0x03 } },
+{  16, 0xbeb0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf4,0x00,0x7d,0x00,0x3f,0xc0 } },
+{  16, 0xbec0, 0, {0x0f,0x72,0x03,0xd4,0x00,0xff,0x00,0x3f,0xc0,0x0e,0xf1,0x47,0xfc,0x00,0xff,0x00 } },
+{  16, 0xbed0, 0, {0x3b,0xc0,0x0d,0xf0,0x13,0xfc,0x50,0xff,0x00,0x37,0xc0,0x0f,0xe0,0x03,0xe8,0x06 } },
+{  16, 0xbee0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf0,0xc4,0xcc,0x33,0x3f,0x04 } },
+{  16, 0xbef0, 0, {0x2c,0xf6,0x03,0x38,0x60,0xcc,0x90,0xb3,0x20,0x0f,0xf1,0x23,0xf0,0x60,0xff,0x01 } },
+{  16, 0xbf00, 0, {0x23,0xc8,0x0c,0xf2,0x8a,0x3c,0x81,0xdf,0x30,0x3f,0x64,0x0c,0xd8,0x03,0x30,0x04 } },
+{  16, 0xbf10, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe0,0xc2,0x8a,0x30,0x2e,0x18 } },
+{  16, 0xbf20, 0, {0x08,0xf5,0x30,0xa5,0x94,0x58,0x22,0x22,0x21,0x4b,0xf3,0x02,0xe1,0x00,0x9f,0x70 } },
+{  16, 0xbf30, 0, {0x2b,0xe4,0x0a,0xf4,0x12,0x1d,0x40,0xaf,0x72,0x2c,0x49,0x2f,0x30,0x82,0xa0,0x06 } },
+{  16, 0xbf40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc4,0x80,0x80,0xa0,0x2c,0x98 } },
+{  16, 0xbf50, 0, {0x08,0x32,0x22,0x08,0x00,0x82,0x00,0x28,0x00,0x03,0x32,0x02,0xc0,0x84,0xb3,0x0c } },
+{  16, 0xbf60, 0, {0x20,0xc0,0x58,0x32,0x92,0x8c,0x30,0xa3,0x20,0x2e,0xc0,0x48,0x12,0x42,0x62,0x01 } },
+{  16, 0xbf70, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xa8,0x00,0x8b,0x00,0x2e,0x20 } },
+{  16, 0xbf80, 0, {0x08,0xb0,0x0a,0x20,0x01,0x98,0x00,0x2a,0x22,0x0b,0xb0,0x02,0xe6,0x00,0x9b,0x00 } },
+{  16, 0xbf90, 0, {0x22,0xc0,0x0a,0xb0,0x12,0xac,0x04,0xab,0x00,0x2e,0xc0,0x03,0xb0,0x02,0xf0,0x00 } },
+{  16, 0xbfa0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0xe5,0x00,0xc8,0x00,0x3e,0xb0 } },
+{  16, 0xbfb0, 0, {0x0c,0xb0,0x03,0x29,0x00,0xc8,0x00,0x3a,0x20,0x4f,0xb0,0x03,0xe2,0x20,0xfb,0x01 } },
+{  16, 0xbfc0, 0, {0xb0,0xc0,0x0c,0xb0,0x03,0x2c,0x00,0xfb,0x02,0x3c,0x41,0x0c,0x90,0x43,0x48,0x04 } },
+{  16, 0xbfd0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xa2,0x80,0xfe,0x40,0x3e,0x00 } },
+{  16, 0xbfe0, 0, {0x0f,0xf0,0x63,0xec,0x00,0xbf,0xc4,0x17,0x42,0x0f,0xf0,0x03,0xec,0x00,0xff,0x00 } },
+{  16, 0xbff0, 0, {0x1f,0xc1,0x0f,0xb0,0x03,0x5c,0x00,0xfb,0x00,0x3f,0x40,0x4f,0xf0,0x00,0xb8,0x00 } },
+{  16, 0xc000, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xa5,0x02,0xc8,0x00,0x3e,0x90 } },
+{  16, 0xc010, 0, {0x2c,0xb0,0x0b,0x01,0x06,0xcb,0x01,0x3e,0x50,0x5f,0xb0,0x13,0x21,0x10,0xcb,0x00 } },
+{  16, 0xc020, 0, {0x7e,0xc0,0x0c,0xb0,0x0b,0x2c,0x00,0xcb,0x00,0x32,0xc0,0x0c,0x90,0x03,0x10,0x04 } },
+{  16, 0xc030, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x28,0x01,0x8b,0xd0,0x2c,0x34 } },
+{  16, 0xc040, 0, {0x48,0xff,0x02,0x30,0x00,0xaa,0x04,0x2e,0x69,0x0f,0xf0,0x03,0x68,0x10,0xdf,0x00 } },
+{  16, 0xc050, 0, {0x2f,0xd4,0x0d,0xf0,0x02,0x3e,0x00,0x5f,0x04,0xb6,0xc0,0x08,0xb0,0x03,0x72,0x00 } },
+{  16, 0xc060, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x69,0x90,0x81,0x80,0x2c,0x00 } },
+{  16, 0xc070, 0, {0x48,0xb8,0x02,0x08,0x09,0x99,0x00,0x4c,0xb0,0x0b,0x30,0x02,0x0c,0x00,0x8b,0x00 } },
+{  16, 0xc080, 0, {0x2c,0xc0,0x09,0xb0,0x40,0x0c,0x40,0x83,0x00,0x00,0x40,0x0a,0x90,0x02,0x30,0x00 } },
+{  16, 0xc090, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x00,0x84,0x88,0x2d,0xe4 } },
+{  16, 0xc0a0, 0, {0x48,0x39,0x02,0x16,0x00,0xb4,0x80,0x2d,0xe0,0x0a,0x7b,0x06,0x5e,0x00,0x97,0x80 } },
+{  16, 0xc0b0, 0, {0x2d,0xe2,0x09,0x78,0x02,0x1e,0x90,0x97,0x80,0x25,0x64,0x8a,0x78,0x02,0x48,0x00 } },
+{  16, 0xc0c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0d,0x00,0x81,0x10,0x2c,0x96 } },
+{  16, 0xc0d0, 0, {0x08,0x31,0x23,0x0c,0x00,0x90,0x20,0x3c,0xc4,0x1b,0xb8,0x02,0x08,0x40,0xc3,0x00 } },
+{  16, 0xc0e0, 0, {0x2c,0xc4,0x0d,0x30,0x03,0x0e,0x40,0xc3,0x10,0x30,0xc0,0x4e,0x10,0x07,0x1a,0x12 } },
+{  16, 0xc0f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xbc,0x00,0x7d,0x05,0x3f,0xc5 } },
+{  16, 0xc100, 0, {0x0f,0xb1,0x0b,0xf4,0x00,0xef,0x00,0x1f,0x45,0x0f,0xf0,0x43,0xfc,0x01,0xff,0x40 } },
+{  16, 0xc110, 0, {0x3d,0xc4,0x1f,0xf0,0x06,0xfc,0x10,0xff,0x00,0x3b,0xc1,0x2d,0xf1,0x03,0xd0,0x06 } },
+{  16, 0xc120, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x04,0xcb,0x04,0x3e,0xa0 } },
+{  16, 0xc130, 0, {0x44,0xb6,0x03,0x28,0x04,0xcb,0x80,0x32,0x80,0x0f,0xb3,0x93,0x60,0x08,0xfb,0x20 } },
+{  16, 0xc140, 0, {0x3e,0xd2,0x1f,0xb3,0x03,0x2d,0x80,0xfb,0x61,0x7e,0x40,0x8c,0x98,0x03,0x2a,0x00 } },
+{  16, 0xc150, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x84,0x0c,0x86,0x05,0x2d,0xc0 } },
+{  16, 0xc160, 0, {0x08,0xf4,0x82,0x8c,0x90,0x85,0x00,0xa1,0xc0,0x0b,0xf0,0x02,0x5c,0x00,0x37,0x00 } },
+{  16, 0xc170, 0, {0x2d,0xd0,0x0b,0x71,0x02,0x1c,0xc8,0xb7,0x48,0x2d,0x40,0x0a,0x70,0x02,0x12,0x04 } },
+{  16, 0xc180, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0x87,0x80,0x2d,0xa1 } },
+{  16, 0xc190, 0, {0x60,0x78,0x4a,0x16,0xd0,0xa7,0x80,0x29,0xe0,0x0b,0x78,0x52,0x96,0x01,0xb7,0x90 } },
+{  16, 0xc1a0, 0, {0x2d,0xe8,0x0b,0x7a,0x22,0x5e,0x40,0xb7,0xa0,0x2f,0xe1,0x48,0x50,0x22,0x30,0x00 } },
+{  16, 0xc1b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x10,0x83,0x84,0x2c,0xc0 } },
+{  16, 0xc1c0, 0, {0x08,0x30,0x02,0xa4,0x10,0x83,0xcb,0x28,0xe0,0x0b,0x30,0x2a,0x4f,0x40,0x93,0x00 } },
+{  16, 0xc1d0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0x4c,0x10,0xb3,0x02,0x2c,0xc0,0xaa,0x30,0x02,0x12,0x04 } },
+{  16, 0xc1e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xb8,0x00,0xce,0xa0,0x3f,0x80 } },
+{  16, 0xc1f0, 0, {0x4c,0xa0,0x2b,0x3a,0x00,0xce,0x40,0x3b,0xb8,0x0f,0xa0,0x03,0xb9,0x00,0xba,0x00 } },
+{  16, 0xc200, 0, {0x3e,0x80,0x0f,0xa0,0x03,0x68,0x00,0xfa,0x00,0x7e,0x80,0x1c,0xa0,0x0b,0x3a,0x04 } },
+{  16, 0xc210, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x02,0xf8,0x00,0x3e,0x04 } },
+{  16, 0xc220, 0, {0x8f,0x00,0x03,0xe0,0x4a,0xf8,0x10,0x26,0x18,0x0f,0x80,0x03,0xa0,0x80,0xf8,0x02 } },
+{  16, 0xc230, 0, {0x3e,0x00,0x8f,0x00,0x0b,0xa0,0x00,0xf8,0x02,0x3e,0x00,0x0f,0x80,0x13,0xd2,0x00 } },
+{  16, 0xc240, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x20,0xc9,0x00,0x32,0x40 } },
+{  16, 0xc250, 0, {0x4d,0x99,0x03,0x24,0x00,0xc9,0x02,0x3e,0x68,0x0f,0x90,0x02,0x24,0x00,0xe9,0x00 } },
+{  16, 0xc260, 0, {0x30,0x40,0x8c,0x90,0x03,0x04,0x40,0xc9,0x00,0x3e,0x40,0x0c,0x90,0x03,0x02,0x04 } },
+{  16, 0xc270, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x20,0x89,0x06,0x22,0x50 } },
+{  16, 0xc280, 0, {0x8b,0x9c,0xc2,0x24,0x00,0xd9,0x01,0x2e,0x40,0x0b,0x90,0x42,0x24,0x08,0xb9,0x01 } },
+{  16, 0xc290, 0, {0x22,0x46,0x0d,0x90,0x0a,0x26,0x02,0x89,0x00,0x2c,0x40,0x0a,0x10,0x02,0x20,0x00 } },
+{  16, 0xc2a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0x06,0x00,0x91,0x40,0x42,0x70 } },
+{  16, 0xc2b0, 0, {0x0b,0x90,0x12,0x2c,0x02,0x8b,0x00,0x2e,0x40,0x0b,0x10,0x22,0xe4,0x10,0xb1,0x00 } },
+{  16, 0xc2c0, 0, {0xa2,0x40,0x48,0x90,0x12,0x24,0x08,0x99,0x02,0x2e,0x40,0x08,0x90,0x02,0x06,0x00 } },
+{  16, 0xc2d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x92,0x91,0x20,0xe0,0x48 } },
+{  16, 0xc2e0, 0, {0x0b,0x12,0x02,0x04,0x02,0x91,0x10,0x2c,0xc0,0x0b,0x10,0x06,0x84,0xc0,0xb1,0x10 } },
+{  16, 0xc2f0, 0, {0x20,0x48,0x89,0x11,0x02,0x05,0x80,0x91,0x40,0x2e,0x44,0x2a,0x94,0x02,0x02,0x01 } },
+{  16, 0xc300, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x61,0x40,0xd8,0x50,0x30,0x14 } },
+{  16, 0xc310, 0, {0x0f,0x85,0x0b,0x21,0xe0,0x80,0x40,0x3e,0x00,0x0f,0x87,0x8b,0xe1,0x0c,0xf8,0x6c } },
+{  16, 0xc320, 0, {0x32,0x00,0x84,0x06,0x83,0x20,0x04,0xd8,0x28,0x3e,0x10,0x0c,0x00,0x03,0x2e,0x03 } },
+{  16, 0xc330, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x40,0xad,0x10,0x3f,0x45 } },
+{  16, 0xc340, 0, {0x0f,0x91,0x03,0xfc,0x18,0x7d,0x20,0x1f,0x41,0x0f,0x90,0x03,0x74,0xc0,0xf9,0x21 } },
+{  16, 0xc350, 0, {0x3e,0x44,0x0f,0x92,0x01,0xe4,0x40,0xe9,0x00,0x3d,0x48,0x4f,0xd0,0x03,0xe6,0x06 } },
+{  16, 0xc360, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0xf7,0x80,0xfd,0xe0,0x33,0x70 } },
+{  16, 0xc370, 0, {0x0c,0xda,0x03,0x26,0x20,0xc9,0x40,0x31,0x40,0x0e,0x9a,0x03,0x24,0x00,0xf9,0x80 } },
+{  16, 0xc380, 0, {0x3b,0x60,0x0f,0x9c,0x83,0x36,0xa0,0xf9,0xa1,0xb0,0x40,0x0f,0x91,0x03,0xc6,0x00 } },
+{  16, 0xc390, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe2,0x90,0xb8,0xa0,0x22,0x28 } },
+{  16, 0xc3a0, 0, {0x28,0x88,0x0a,0x22,0x02,0x88,0xa0,0x22,0x00,0x08,0x88,0x02,0xc2,0x80,0xb8,0x88 } },
+{  16, 0xc3b0, 0, {0x22,0x04,0x0b,0x8e,0x03,0x22,0x80,0xb8,0xd0,0x2a,0x20,0x0b,0x88,0x02,0xce,0x04 } },
+{  16, 0xc3c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc5,0x80,0xb1,0x61,0x00,0x58 } },
+{  16, 0xc3d0, 0, {0x48,0x16,0x8a,0x04,0xa0,0x89,0x01,0x22,0x40,0x1a,0x14,0x88,0x04,0x20,0xb1,0x40 } },
+{  16, 0xc3e0, 0, {0x28,0x40,0x0b,0x10,0x0a,0x04,0x20,0xb1,0x2c,0x20,0x4a,0x0b,0x12,0x02,0xc2,0x01 } },
+{  16, 0xc3f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa5,0x90,0xbb,0x40,0x20,0x40 } },
+{  16, 0xc400, 0, {0x08,0x90,0x02,0x24,0x40,0x89,0x42,0x62,0x58,0x08,0x10,0x02,0xe5,0x00,0xb9,0x03 } },
+{  16, 0xc410, 0, {0x22,0xc0,0x0b,0x90,0x02,0xa4,0x14,0x31,0x00,0x2a,0x44,0x0b,0x90,0x02,0xc6,0x04 } },
+{  16, 0xc420, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0xa5,0x00,0xf9,0x01,0x32,0x40 } },
+{  16, 0xc430, 0, {0x8c,0x90,0x03,0x27,0x00,0xc1,0x94,0x30,0x40,0x0e,0x90,0x03,0x24,0x00,0xf9,0x00 } },
+{  16, 0xc440, 0, {0x3a,0x40,0x0f,0x90,0x03,0x24,0x00,0xf9,0x00,0x32,0x60,0x07,0x90,0x27,0xe8,0x05 } },
+{  16, 0xc450, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xa4,0x18,0xf9,0x00,0xbe,0x44 } },
+{  16, 0xc460, 0, {0x0f,0x90,0x03,0xc4,0x00,0xf9,0x00,0xbe,0x61,0x8f,0x90,0x03,0xa4,0x00,0xf1,0x00 } },
+{  16, 0xc470, 0, {0x1e,0x40,0x0f,0x10,0x03,0x24,0x08,0xf9,0x00,0x7e,0x40,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0xc480, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa1,0x81,0xf8,0x00,0x32,0x04 } },
+{  16, 0xc490, 0, {0x0c,0x00,0xd3,0x21,0x00,0xd8,0x04,0x3a,0x14,0x9c,0x80,0x03,0x21,0x01,0xc8,0x00 } },
+{  16, 0xc4a0, 0, {0x36,0x00,0x0c,0x80,0x13,0x20,0x10,0xc8,0x00,0x32,0x00,0x2c,0x80,0x03,0xca,0x04 } },
+{  16, 0xc4b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x04,0x3a,0x00,0xbe,0x84,0x23,0x85 } },
+{  16, 0xc4c0, 0, {0x08,0xec,0x83,0x68,0x04,0x8a,0x00,0x2f,0x90,0x4d,0xa0,0x02,0x28,0x01,0xda,0x00 } },
+{  16, 0xc4d0, 0, {0x23,0xb0,0x0a,0xa0,0x02,0x2a,0x08,0xda,0x01,0x22,0x80,0x0f,0xa0,0x02,0xca,0x00 } },
+{  16, 0xc4e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x00,0xbb,0xf0,0x20,0xc0 } },
+{  16, 0xc4f0, 0, {0x08,0x3c,0x0a,0x0c,0x00,0x93,0x01,0x28,0xc8,0x89,0x30,0x06,0x4c,0x00,0x83,0x02 } },
+{  16, 0xc500, 0, {0x2c,0xf6,0x08,0x30,0x02,0x04,0x00,0xa3,0x00,0x20,0xc0,0x0a,0x30,0x02,0xca,0x00 } },
+{  16, 0xc510, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1d,0x11,0xb3,0x00,0xa0,0xc0 } },
+{  16, 0xc520, 0, {0x08,0x50,0x02,0x5c,0x10,0x87,0x01,0x6d,0x81,0x49,0x32,0x52,0x1e,0xc3,0x87,0x00 } },
+{  16, 0xc530, 0, {0x28,0xe0,0x0a,0x32,0x26,0x1f,0x00,0x37,0x00,0x23,0xe0,0x0b,0x72,0x02,0xc8,0x00 } },
+{  16, 0xc540, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x08,0x12,0x00,0xb7,0x82,0x31,0x20 } },
+{  16, 0xc550, 0, {0x08,0x08,0x37,0x0f,0x08,0xd7,0xe0,0x39,0x60,0x19,0x7a,0x0b,0x5e,0x0c,0x83,0xb2 } },
+{  16, 0xc560, 0, {0x7d,0xe0,0x0c,0x7a,0x0b,0x3e,0x02,0xaf,0xa0,0xb1,0xe0,0x0e,0x7a,0x03,0xca,0x02 } },
+{  16, 0xc570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xa0,0x10,0xfb,0x00,0x3e,0xc0 } },
+{  16, 0xc580, 0, {0x6f,0xb0,0x43,0xec,0x11,0xfb,0x00,0x3e,0x40,0x0f,0xb5,0x03,0xec,0x20,0xfb,0x50 } },
+{  16, 0xc590, 0, {0x36,0x00,0x0f,0xb5,0x43,0xe5,0xa1,0xdb,0x78,0x3e,0xc0,0x0f,0xb4,0x03,0xc2,0x06 } },
+{  16, 0xc5a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0xfe,0x00,0xff,0xa0,0x3f,0xa0 } },
+{  16, 0xc5b0, 0, {0x0d,0xc9,0x13,0x3e,0x00,0xcf,0xd0,0x3d,0xe8,0x02,0xff,0x13,0x3e,0x00,0xcf,0x82 } },
+{  16, 0xc5c0, 0, {0x3f,0x60,0x0c,0xfc,0x23,0x3e,0x10,0xef,0x80,0x33,0xf2,0x0c,0xfc,0x83,0x10,0x00 } },
+{  16, 0xc5d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x40,0xb5,0x01,0x2d,0xd0 } },
+{  16, 0xc5e0, 0, {0x08,0x58,0x02,0x1c,0x40,0x57,0x10,0x2d,0x5a,0x28,0x31,0x02,0xbc,0x01,0x97,0x10 } },
+{  16, 0xc5f0, 0, {0x2d,0x00,0x0a,0x70,0x02,0x84,0x04,0xcf,0x00,0x29,0xc0,0x0a,0xf0,0x02,0x2a,0x04 } },
+{  16, 0xc600, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0xb7,0x2a,0x2d,0x82 } },
+{  16, 0xc610, 0, {0x08,0x42,0x22,0x3c,0x00,0x87,0x11,0x0d,0xcc,0x88,0x32,0x02,0x1d,0x00,0x97,0x00 } },
+{  16, 0xc620, 0, {0x2c,0xc4,0x08,0x30,0x02,0x14,0x00,0xa7,0x00,0x23,0xc0,0x09,0x70,0x82,0x00,0x00 } },
+{  16, 0xc630, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x14,0xc0,0x20,0xb0,0x20,0x2c,0x50 } },
+{  16, 0xc640, 0, {0x08,0x10,0x02,0x2d,0xc0,0x93,0xe2,0x2c,0x21,0x08,0x30,0x02,0x0e,0x08,0x93,0x00 } },
+{  16, 0xc650, 0, {0x2c,0x40,0x0a,0x30,0x02,0x8c,0x00,0x93,0x00,0x2a,0xc0,0x0b,0x30,0x02,0x18,0x04 } },
+{  16, 0xc660, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xac,0x00,0xf8,0xc0,0x3e,0x80 } },
+{  16, 0xc670, 0, {0x2c,0xa0,0x0b,0x3f,0x00,0xc7,0x60,0x3e,0xd0,0x0c,0xf0,0x0b,0x3c,0x00,0xcf,0x00 } },
+{  16, 0xc680, 0, {0x3e,0x80,0x0c,0xf0,0x0b,0x2c,0x00,0xef,0x00,0x33,0xc1,0x0d,0xf0,0x0b,0x2a,0x04 } },
+{  16, 0xc690, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x40,0xf3,0x40,0x3e,0x50 } },
+{  16, 0xc6a0, 0, {0x8e,0xb4,0x03,0xec,0x10,0xfb,0x00,0x3e,0x09,0x0f,0xb0,0x13,0xec,0x42,0xeb,0x00 } },
+{  16, 0xc6b0, 0, {0x3c,0x00,0x8f,0xb0,0x13,0xc4,0x11,0xe3,0x00,0x3e,0xc0,0x0e,0xb0,0x03,0xe0,0x00 } },
+{  16, 0xc6c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xfc,0x80,0x31,0x22 } },
+{  16, 0xc6d0, 0, {0x0c,0xa8,0x03,0x3c,0x00,0xcf,0x00,0x33,0xa0,0x0e,0xf0,0x03,0xdc,0x00,0xcf,0x00 } },
+{  16, 0xc6e0, 0, {0x1f,0xf0,0x0c,0xf0,0x03,0xf4,0x00,0xcf,0x02,0x33,0xc0,0x0c,0xf0,0x02,0x00,0x54 } },
+{  16, 0xc6f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6f,0x00,0xbb,0xc0,0x22,0x70 } },
+{  16, 0xc700, 0, {0x0a,0xb9,0x42,0x2c,0x10,0x8b,0x00,0x76,0x11,0x83,0xb0,0x02,0xec,0x10,0xab,0x00 } },
+{  16, 0xc710, 0, {0x2e,0xb0,0x0a,0xb0,0x03,0xec,0x04,0x8b,0x00,0xa2,0xc0,0x28,0xb0,0x02,0x20,0x40 } },
+{  16, 0xc720, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x65,0x40,0xb8,0x20,0x22,0x44 } },
+{  16, 0xc730, 0, {0x58,0x34,0x0a,0x2c,0x00,0x8b,0x00,0x22,0x84,0x4b,0xb0,0x02,0xec,0x00,0x8b,0x00 } },
+{  16, 0xc740, 0, {0x6e,0xc0,0x08,0xb0,0x42,0xe6,0x04,0x8b,0x00,0x02,0xc0,0x08,0x30,0x02,0xa0,0x01 } },
+{  16, 0xc750, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0xb1,0x00,0x20,0xc0 } },
+{  16, 0xc760, 0, {0x0a,0x30,0x0a,0x0c,0x00,0x8b,0x03,0x24,0x80,0x0b,0x30,0x02,0xcc,0x00,0xa3,0x00 } },
+{  16, 0xc770, 0, {0x6c,0x00,0x0a,0x30,0x02,0x8d,0x00,0x83,0x00,0x20,0xc0,0x18,0x30,0x02,0x82,0x00 } },
+{  16, 0xc780, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x64,0x00,0xf8,0x00,0x30,0x00 } },
+{  16, 0xc790, 0, {0x4c,0xa0,0x0b,0x2c,0x02,0xcf,0x00,0x22,0x40,0x0e,0xf5,0x03,0xfc,0x00,0xcf,0x01 } },
+{  16, 0xc7a0, 0, {0x3e,0x00,0x0c,0xf0,0x12,0xdd,0x02,0xcf,0x02,0x33,0xc0,0x4c,0xf0,0x0b,0x80,0x03 } },
+{  16, 0xc7b0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x19,0xf0,0x00,0xfc,0x00,0x3f,0x40 } },
+{  16, 0xc7c0, 0, {0x0f,0xb1,0x03,0xdc,0x00,0xbf,0x01,0x3f,0x00,0x0f,0xf2,0x23,0xfc,0x10,0xff,0x00 } },
+{  16, 0xc7d0, 0, {0x3f,0x00,0x0f,0xf0,0x01,0xf4,0x84,0xff,0x00,0x3d,0xc0,0x4f,0xf0,0x13,0x68,0x06 } },
+{  16, 0xc7e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xfe,0x40,0xdf,0x80,0x33,0xc8 } },
+{  16, 0xc7f0, 0, {0x0c,0xf8,0x03,0x3c,0x0a,0x9f,0xc0,0x3f,0xf0,0x08,0xb8,0x02,0x3e,0x00,0xff,0x80 } },
+{  16, 0xc800, 0, {0x3f,0xd8,0x0c,0xf9,0x61,0x2e,0x40,0x6f,0x90,0x3f,0xe4,0x8f,0xf1,0x83,0x30,0x00 } },
+{  16, 0xc810, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xec,0x04,0x8b,0x80,0x23,0xf0 } },
+{  16, 0xc820, 0, {0x08,0xb8,0x02,0x3d,0x40,0xab,0x00,0x0e,0x08,0x48,0x22,0x82,0x6c,0x20,0xbb,0x00 } },
+{  16, 0xc830, 0, {0x2f,0xd0,0x48,0xb0,0x02,0x2c,0x00,0xbb,0x00,0x2e,0xc1,0x0b,0xb0,0x02,0x30,0x04 } },
+{  16, 0xc840, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xcc,0x02,0x83,0x01,0xa0,0xc5 } },
+{  16, 0xc850, 0, {0x08,0xb0,0x4a,0x4c,0xa0,0x80,0x24,0x28,0xc8,0x09,0x32,0x02,0x4c,0x00,0xb3,0x08 } },
+{  16, 0xc860, 0, {0x2e,0xd1,0x29,0xb2,0x3a,0x0c,0x84,0xa3,0x21,0x2c,0xc8,0x4b,0xb2,0x0a,0x32,0x01 } },
+{  16, 0xc870, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x08,0x8b,0x00,0x22,0xc0 } },
+{  16, 0xc880, 0, {0x08,0xb0,0x02,0x4c,0x00,0x88,0x21,0x24,0x21,0x09,0xb0,0x46,0x6c,0x00,0xbb,0x06 } },
+{  16, 0xc890, 0, {0x2e,0xc0,0x09,0xb0,0x02,0x2c,0x10,0xbb,0x00,0x2e,0xc0,0x0b,0xb0,0x02,0x30,0x04 } },
+{  16, 0xc8a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xcb,0x00,0x32,0xc0 } },
+{  16, 0xc8b0, 0, {0x0c,0xb9,0x02,0x6c,0x00,0xcb,0xc8,0x3a,0xc0,0x2d,0x90,0x0b,0x2c,0x08,0xfb,0x00 } },
+{  16, 0xc8c0, 0, {0x3e,0xc0,0x0d,0x30,0x42,0x2c,0x00,0xeb,0x00,0x3e,0xc0,0x0f,0xb0,0x13,0x00,0x04 } },
+{  16, 0xc8d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xbc,0x00,0xef,0x00,0x3d,0xc0 } },
+{  16, 0xc8e0, 0, {0x0f,0xf0,0x03,0xbc,0x06,0xef,0x82,0x3f,0x40,0x4e,0xc9,0x83,0xbc,0x00,0xff,0x00 } },
+{  16, 0xc8f0, 0, {0x7f,0xc0,0x1c,0xf0,0x13,0x7c,0x00,0xff,0x04,0x3f,0xc0,0x0f,0xf0,0x03,0xf8,0x00 } },
+{  16, 0xc900, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x02,0x3e,0xc0 } },
+{  16, 0xc910, 0, {0x0e,0xb0,0x03,0xac,0x20,0xd8,0x40,0x3e,0xc0,0x8c,0x90,0x0b,0x2c,0x00,0xfb,0x00 } },
+{  16, 0xc920, 0, {0x3e,0xc9,0x0d,0xb0,0x33,0xec,0x08,0xfb,0x02,0x3e,0xc0,0x0f,0xb0,0x0b,0x54,0x04 } },
+{  16, 0xc930, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2c,0x00,0xb3,0x00,0x2f,0xc0 } },
+{  16, 0xc940, 0, {0x0b,0x30,0x12,0xfc,0x00,0x88,0xa0,0x2e,0x40,0x28,0x94,0x02,0x2c,0x10,0xbb,0x04 } },
+{  16, 0xc950, 0, {0x2d,0xc0,0x28,0xb0,0x02,0xec,0x00,0xbb,0x00,0x2e,0xc0,0x0b,0x72,0x06,0x32,0x00 } },
+{  16, 0xc960, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x6c,0x00,0xb3,0x00,0x2c,0xe0 } },
+{  16, 0xc970, 0, {0x0a,0x10,0x02,0xcd,0x00,0x93,0x00,0x2c,0xc0,0x08,0xb0,0x02,0x4c,0x00,0xb3,0x00 } },
+{  16, 0xc980, 0, {0x28,0xc0,0x08,0x30,0x02,0xcc,0x00,0xb3,0x00,0x2c,0xc0,0x0b,0x30,0x02,0x3a,0x00 } },
+{  16, 0xc990, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x1e,0x40,0xb7,0x80,0x2d,0xe2 } },
+{  16, 0xc9a0, 0, {0x0b,0x58,0x02,0xde,0x02,0x97,0x81,0x2f,0xa0,0x08,0x68,0x02,0x5e,0x00,0xb7,0x81 } },
+{  16, 0xc9b0, 0, {0x2f,0xe0,0x08,0x79,0x02,0xde,0x00,0xb7,0x81,0x2d,0xe0,0x0b,0x78,0x02,0x3c,0x00 } },
+{  16, 0xc9c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x0c,0x00,0xf3,0x00,0x3c,0xc0 } },
+{  16, 0xc9d0, 0, {0x0e,0x32,0x03,0xcc,0x80,0xd3,0x00,0x3c,0xc4,0x0c,0x39,0x03,0x4c,0x08,0xf3,0x1a } },
+{  16, 0xc9e0, 0, {0x3c,0xc6,0x0d,0x30,0x03,0xce,0x20,0xf3,0x08,0x3c,0xc0,0x0f,0x30,0x03,0x52,0x02 } },
+{  16, 0xc9f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x1d,0xac,0x00,0xfb,0x00,0x2e,0xc0 } },
+{  16, 0xca00, 0, {0x0b,0xb0,0x03,0xcc,0x20,0xeb,0x00,0x3c,0x80,0x0f,0xb0,0x41,0xac,0x00,0xfb,0x00 } },
+{  16, 0xca10, 0, {0x3c,0xc2,0x0f,0xb0,0x03,0xec,0x40,0xfb,0x00,0x3e,0xc0,0x0f,0x30,0x03,0xd0,0x06 } },
+{  16, 0xca20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xee,0x02,0xc3,0x80,0x30,0xce } },
+{  16, 0xca30, 0, {0x0d,0x98,0x03,0xac,0xa0,0xc3,0x80,0xb2,0xc0,0x0f,0xb0,0x03,0xec,0x00,0xfb,0x00 } },
+{  16, 0xca40, 0, {0x3e,0xd2,0x4f,0xb0,0x09,0x2e,0x08,0x4b,0x01,0x3e,0xc0,0x24,0xb0,0x03,0xea,0x00 } },
+{  16, 0xca50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x9c,0x00,0x87,0x01,0x21,0xc0 } },
+{  16, 0xca60, 0, {0x48,0x50,0x12,0x4c,0x00,0x87,0x00,0x35,0xc0,0x4b,0x60,0x02,0xdc,0x04,0xb7,0x01 } },
+{  16, 0xca70, 0, {0x2d,0xc0,0x0b,0x70,0x02,0x1c,0x00,0x87,0x00,0x2d,0xc1,0x0c,0x72,0x02,0xf2,0x04 } },
+{  16, 0xca80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0x87,0x80,0x23,0xe0 } },
+{  16, 0xca90, 0, {0x08,0xf8,0x02,0xde,0x80,0x8f,0x81,0x21,0xe0,0x4b,0x78,0x12,0xde,0x04,0x37,0x80 } },
+{  16, 0xcaa0, 0, {0x2d,0xe8,0x0b,0xf8,0x02,0x3e,0x18,0x87,0x80,0x2f,0xe0,0x09,0x79,0x02,0xe0,0x00 } },
+{  16, 0xcab0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x00,0x83,0x00,0xa0,0xc0 } },
+{  16, 0xcac0, 0, {0x28,0x30,0x42,0x4c,0x00,0x83,0x00,0x24,0xc0,0x0b,0x38,0x06,0xcc,0x04,0xb3,0x00 } },
+{  16, 0xcad0, 0, {0x2c,0xc0,0x0b,0x30,0x02,0x0c,0x02,0x83,0x00,0x2c,0xc0,0x08,0x30,0x02,0xd2,0x04 } },
+{  16, 0xcae0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xa8,0x00,0xca,0x00,0x31,0x80 } },
+{  16, 0xcaf0, 0, {0x08,0xe0,0x02,0x98,0x02,0xce,0x00,0x33,0x84,0x0b,0xea,0x03,0xe8,0x00,0xba,0x00 } },
+{  16, 0xcb00, 0, {0x3f,0x81,0x0f,0xa0,0x03,0x28,0x00,0xca,0x00,0x3e,0x80,0x0d,0xe0,0x03,0xfa,0x04 } },
+{  16, 0xcb10, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x00,0xf8,0x00,0x3e,0x00 } },
+{  16, 0xcb20, 0, {0x0e,0x84,0x23,0xa0,0x00,0xf8,0x00,0x3a,0x10,0x0f,0x80,0x03,0xe0,0x00,0xf8,0x00 } },
+{  16, 0xcb30, 0, {0x3e,0x10,0x0f,0x80,0x13,0xe0,0x00,0xf8,0x00,0x3e,0x00,0x0d,0x80,0x03,0xd2,0x00 } },
+{  16, 0xcb40, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0xe4,0x01,0xf9,0x00,0x3e,0x40 } },
+{  16, 0xcb50, 0, {0x0c,0x9a,0x13,0xe4,0x00,0xc9,0x00,0x3e,0x40,0x0c,0x98,0x23,0xe4,0x80,0xf9,0x00 } },
+{  16, 0xcb60, 0, {0x3e,0x40,0x2c,0x98,0x03,0x64,0x00,0xf9,0x00,0x3e,0x40,0x0c,0x90,0x03,0xc2,0x04 } },
+{  16, 0xcb70, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x04,0xb9,0x00,0x2e,0x40 } },
+{  16, 0xcb80, 0, {0x68,0x9c,0x22,0xe4,0x02,0x89,0x01,0x7c,0x50,0x8d,0x98,0x22,0xe4,0x80,0xb9,0x20 } },
+{  16, 0xcb90, 0, {0x2e,0x50,0x48,0x10,0x0b,0x25,0x00,0xb9,0x44,0x2c,0x40,0x28,0x90,0x00,0xe0,0x00 } },
+{  16, 0xcba0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb9,0x00,0x2e,0x50 } },
+{  16, 0xcbb0, 0, {0x08,0x90,0x02,0xe4,0x04,0x89,0x00,0x2e,0x50,0x0a,0x92,0x02,0xe4,0x00,0xb9,0x00 } },
+{  16, 0xcbc0, 0, {0x2c,0x40,0x08,0x91,0x02,0x24,0x00,0xb9,0x00,0x2e,0x40,0x08,0x90,0x02,0xc6,0x00 } },
+{  16, 0xcbd0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x05,0x00,0xb1,0x01,0x2c,0x40 } },
+{  16, 0xcbe0, 0, {0x48,0x30,0x02,0xe4,0x00,0x81,0x00,0x2a,0x40,0x4b,0x10,0x02,0xc4,0x00,0xb1,0x00 } },
+{  16, 0xcbf0, 0, {0x0c,0xc0,0x08,0x90,0x02,0x0c,0x00,0xb3,0x00,0x2e,0x40,0x48,0x12,0x02,0xc2,0x01 } },
+{  16, 0xcc00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x60,0x00,0xb8,0x01,0x3e,0x00 } },
+{  16, 0xcc10, 0, {0x1c,0x80,0x07,0xe1,0x50,0xc8,0x50,0x2e,0x14,0x1e,0x85,0x03,0xe1,0x41,0xf8,0x50 } },
+{  16, 0xcc20, 0, {0x3e,0x14,0x0c,0x85,0x13,0x21,0x48,0xf8,0x50,0x3e,0x14,0x0c,0x85,0x43,0xee,0x03 } },
+{  16, 0xcc30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x19,0xc4,0x00,0xf9,0x00,0x3e,0x51 } },
+{  16, 0xcc40, 0, {0x0f,0x50,0x03,0xe5,0x00,0xfd,0x00,0x3f,0x40,0x1d,0xd0,0x03,0xf4,0x10,0xf9,0x00 } },
+{  16, 0xcc50, 0, {0x3e,0x50,0x0f,0x50,0x00,0x94,0x00,0xf9,0x00,0x3d,0x40,0x0f,0x91,0x03,0xe6,0x06 } },
+{  16, 0xcc60, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0xe4,0x50,0xcd,0x00,0x31,0x60 } },
+{  16, 0xcc70, 0, {0x04,0xd0,0x03,0x36,0x80,0xc1,0x42,0x2e,0x50,0x1f,0x94,0x03,0xe5,0x00,0xe9,0x02 } },
+{  16, 0xcc80, 0, {0x2e,0x72,0x0a,0x90,0x22,0x05,0x08,0xe9,0x40,0x3e,0x50,0x40,0x9c,0x03,0x26,0x00 } },
+{  16, 0xcc90, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xc2,0x82,0x88,0x00,0x22,0x15 } },
+{  16, 0xcca0, 0, {0x08,0x80,0x02,0x23,0x58,0x88,0xa0,0x2e,0x28,0x0b,0xaa,0x42,0xe2,0x82,0x88,0x80 } },
+{  16, 0xccb0, 0, {0x2e,0x38,0x28,0x88,0x02,0x22,0x80,0xb8,0xa0,0x3a,0x28,0x08,0xcd,0x02,0x0e,0x04 } },
+{  16, 0xccc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0x81,0x00,0xa6,0x40 } },
+{  16, 0xccd0, 0, {0x28,0x10,0x0a,0x24,0x26,0x95,0x00,0x0d,0x40,0x0b,0x50,0x02,0x74,0x00,0x85,0x08 } },
+{  16, 0xcce0, 0, {0x2f,0x40,0x79,0xd2,0xaa,0x14,0x00,0xa5,0x01,0x2f,0x40,0x38,0x50,0x02,0x12,0x01 } },
+{  16, 0xccf0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x04,0x89,0x00,0x26,0x40 } },
+{  16, 0xcd00, 0, {0x08,0x91,0x02,0x24,0x10,0x9d,0x08,0x2f,0x40,0x0b,0xd0,0x02,0xf4,0x00,0x8d,0x02 } },
+{  16, 0xcd10, 0, {0x2f,0x40,0x09,0xd0,0x00,0x34,0x00,0xbd,0x00,0x0b,0x40,0x18,0x70,0x02,0x06,0x04 } },
+{  16, 0xcd20, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xc4,0x00,0xc9,0x05,0x36,0x41 } },
+{  16, 0xcd30, 0, {0x4c,0x90,0x63,0x24,0x00,0xd9,0x00,0x3e,0x40,0x0b,0x90,0x03,0x44,0x08,0xc9,0x00 } },
+{  16, 0xcd40, 0, {0x3e,0x40,0x15,0x10,0x03,0x24,0x00,0xe9,0x00,0x3c,0x40,0x0c,0x90,0x03,0x28,0x04 } },
+{  16, 0xcd50, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0xa4,0x04,0xf9,0x00,0x3a,0x40 } },
+{  16, 0xcd60, 0, {0x4f,0x98,0x03,0xe4,0x00,0xe9,0x99,0x3e,0x40,0x4f,0x90,0x03,0xe4,0x20,0xf9,0x0a } },
+{  16, 0xcd70, 0, {0x3e,0x40,0x0e,0x90,0x43,0x64,0x24,0xf9,0x08,0x3a,0x42,0x0f,0x90,0x8b,0xda,0x00 } },
+{  16, 0xcd80, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xc8,0x00,0x12,0x00 } },
+{  16, 0xcd90, 0, {0x0c,0x80,0x43,0xe0,0x00,0xc8,0x40,0x32,0x00,0x0f,0x84,0x53,0xe0,0x10,0xf8,0x00 } },
+{  16, 0xcda0, 0, {0x3e,0x00,0x0d,0x80,0x23,0x20,0x00,0xd8,0x00,0x3e,0x00,0x0f,0x80,0x03,0x0a,0x04 } },
+{  16, 0xcdb0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x38,0x02,0x82,0x00,0xa1,0x88 } },
+{  16, 0xcdc0, 0, {0x08,0x60,0x22,0xc8,0x00,0x8a,0x40,0x36,0xa1,0x0b,0xa0,0x02,0xe9,0x10,0xba,0x44 } },
+{  16, 0xcdd0, 0, {0x2c,0x80,0x0c,0xa4,0x12,0x29,0x02,0x8a,0x44,0x2e,0x98,0x0b,0xa4,0x02,0x0a,0x00 } },
+{  16, 0xcde0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4c,0x10,0x83,0x00,0x20,0xe0 } },
+{  16, 0xcdf0, 0, {0x18,0x30,0x92,0xc4,0x08,0x93,0x40,0x20,0xe0,0x0b,0x30,0x02,0xcd,0x00,0xb3,0x40 } },
+{  16, 0xce00, 0, {0x2c,0xc0,0x0b,0x3a,0x42,0xcd,0x00,0x83,0x40,0x2c,0xd0,0x0b,0x38,0x02,0x4a,0x00 } },
+{  16, 0xce10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x41,0x1c,0x00,0x87,0x00,0x21,0xc0 } },
+{  16, 0xce20, 0, {0x28,0x70,0x02,0xd1,0x00,0x9d,0x80,0x25,0xc2,0x4b,0x60,0x02,0xdc,0x08,0xb7,0x02 } },
+{  16, 0xce30, 0, {0x2c,0xc0,0x0a,0x74,0x02,0xfe,0x00,0x87,0x00,0x2d,0xc0,0x0b,0x34,0x02,0x68,0x00 } },
+{  16, 0xce40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x1e,0x00,0xc7,0x84,0x31,0xe0 } },
+{  16, 0xce50, 0, {0x0c,0x68,0x03,0xd6,0x00,0x97,0x80,0x31,0xa0,0x0f,0x58,0x13,0xde,0x08,0xf7,0x82 } },
+{  16, 0xce60, 0, {0x3d,0xa0,0x0f,0xf8,0x0b,0xde,0x00,0xc7,0x80,0x3d,0xe0,0x0f,0x78,0x8b,0x6a,0x02 } },
+{  16, 0xce70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xad,0x80,0xf3,0x00,0x3e,0xc1 } },
+{  16, 0xce80, 0, {0x0f,0xa0,0x23,0xc0,0x02,0xe9,0x00,0x3e,0x81,0x0f,0x80,0x03,0xec,0x00,0xfb,0x00 } },
+{  16, 0xce90, 0, {0x3e,0xc0,0x0d,0xb0,0x13,0x2c,0x00,0xeb,0x00,0x3e,0xc0,0x0f,0xb0,0x03,0x82,0x02 } },
+{  16, 0xcea0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xff,0x32,0xc7,0x80,0x33,0x60 } },
+{  16, 0xceb0, 0, {0x0f,0x78,0x03,0x3e,0xc8,0x4e,0x80,0x23,0x64,0x0c,0xf8,0x03,0x3a,0x00,0xce,0x80 } },
+{  16, 0xcec0, 0, {0x13,0xec,0x06,0xd8,0x03,0x3a,0x00,0xde,0x80,0x33,0xa4,0x0c,0xc8,0x03,0xd0,0x00 } },
+{  16, 0xced0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0x9c,0x00,0x87,0x10,0x01,0xc0 } },
+{  16, 0xcee0, 0, {0x0b,0x70,0x02,0x18,0x50,0x84,0x00,0x2b,0x44,0x08,0x60,0x12,0x98,0x00,0x86,0x13 } },
+{  16, 0xcef0, 0, {0x21,0xc4,0x88,0x50,0x02,0x18,0x80,0x86,0x00,0x21,0x80,0x08,0x61,0x02,0xea,0x04 } },
+{  16, 0xcf00, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x87,0x00,0x21,0x40 } },
+{  16, 0xcf10, 0, {0x0b,0xf1,0x02,0x5c,0x80,0x06,0x00,0x21,0x00,0x88,0xd0,0x02,0x5c,0x00,0x87,0x00 } },
+{  16, 0xcf20, 0, {0x20,0x89,0x8a,0xf1,0x02,0x1c,0x08,0x87,0x10,0x21,0x81,0x88,0x48,0x02,0xc6,0x00 } },
+{  16, 0xcf30, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x10,0x83,0x04,0xa0,0xc1 } },
+{  16, 0xcf40, 0, {0x0b,0x30,0x0a,0x48,0x0c,0x88,0x06,0x60,0x38,0x08,0x04,0x42,0xec,0x01,0x8b,0x04 } },
+{  16, 0xcf50, 0, {0x22,0xc1,0x08,0x30,0x0a,0x2c,0x00,0x8b,0x00,0x22,0x80,0x00,0x20,0x02,0xd8,0x04 } },
+{  16, 0xcf60, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xbc,0x00,0xc3,0x00,0x22,0x80 } },
+{  16, 0xcf70, 0, {0x8f,0x90,0x03,0x64,0x0a,0xcb,0x02,0xb2,0xf2,0x20,0x35,0x12,0x64,0x0a,0xc9,0x00 } },
+{  16, 0xcf80, 0, {0xb2,0x40,0x0e,0xa0,0x03,0x24,0x0a,0xc9,0x00,0xa2,0x40,0x2c,0xa0,0x03,0xee,0x04 } },
+{  16, 0xcf90, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xec,0x00,0xfb,0x00,0x3c,0x80 } },
+{  16, 0xcfa0, 0, {0x0f,0x90,0x03,0xa5,0x00,0xdb,0x40,0x3e,0xd0,0x4d,0xb4,0x13,0xa4,0x08,0xfb,0x01 } },
+{  16, 0xcfb0, 0, {0x3e,0xc0,0x1c,0xa0,0x03,0x6c,0x00,0xfb,0x04,0x3e,0x50,0x4f,0xa4,0x03,0xe0,0x00 } },
+{  16, 0xcfc0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xff,0x00,0x33,0xc0 } },
+{  16, 0xcfd0, 0, {0x0c,0xe8,0x43,0x26,0x00,0xdf,0x80,0xb3,0xe0,0x0f,0xf8,0x03,0x7c,0x00,0xcd,0x00 } },
+{  16, 0xcfe0, 0, {0x33,0x04,0x0c,0xe0,0x23,0x34,0x40,0xcd,0x00,0x23,0x40,0x0c,0xe0,0x03,0xe0,0x04 } },
+{  16, 0xcff0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x6c,0x10,0xbb,0x00,0xa2,0xd2 } },
+{  16, 0xd000, 0, {0x08,0x28,0x02,0x04,0x60,0x8b,0x19,0x22,0xc6,0x0e,0xb1,0x8a,0x2e,0x40,0x8b,0x90 } },
+{  16, 0xd010, 0, {0x22,0xc1,0x08,0xa4,0x82,0x2c,0x00,0x8b,0x90,0x22,0x64,0x48,0xa4,0x02,0xe0,0x00 } },
+{  16, 0xd020, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x05,0x2c,0x00,0xbb,0x00,0x22,0x00 } },
+{  16, 0xd030, 0, {0x08,0x91,0x2e,0x24,0x00,0x9b,0x00,0x22,0xc0,0x8b,0xb0,0x12,0x20,0x04,0x88,0x00 } },
+{  16, 0xd040, 0, {0x22,0x40,0x08,0x10,0x22,0x20,0x00,0x88,0x01,0x2a,0xd0,0x08,0x80,0x42,0xe0,0x00 } },
+{  16, 0xd050, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x0c,0x00,0xb3,0x04,0x20,0x80 } },
+{  16, 0xd060, 0, {0x08,0x10,0x06,0x04,0x10,0x83,0x00,0x20,0xc0,0x8b,0xb0,0x12,0x00,0x00,0x82,0x00 } },
+{  16, 0xd070, 0, {0x20,0xc0,0x28,0x10,0x42,0x09,0x06,0x82,0x00,0x28,0xc0,0x08,0x20,0x02,0xc2,0x01 } },
+{  16, 0xd080, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x7c,0x00,0xbb,0x00,0x32,0x40 } },
+{  16, 0xd090, 0, {0x2c,0xb0,0x03,0x24,0x00,0xd3,0x00,0x32,0xc0,0x5f,0xb5,0x03,0x0c,0x02,0xc1,0x00 } },
+{  16, 0xd0a0, 0, {0xb2,0x00,0x0c,0xb0,0x0b,0x05,0x00,0xc1,0x00,0xb8,0xc0,0x2c,0x80,0x13,0xe0,0x03 } },
+{  16, 0xd0b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xdc,0x00,0xff,0x00,0x1f,0xc0 } },
+{  16, 0xd0c0, 0, {0x87,0xf0,0x01,0xf4,0x00,0xff,0x00,0x3f,0xc0,0x0e,0x70,0x43,0xfc,0x10,0x7f,0x00 } },
+{  16, 0xd0d0, 0, {0x3f,0xc0,0x0f,0x70,0x03,0xfc,0x00,0xff,0x00,0x37,0xc0,0x0f,0xe0,0x03,0xe8,0x06 } },
+{  16, 0xd0e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x05,0xf1,0x84,0xfe,0x61,0x31,0xd8 } },
+{  16, 0xd0f0, 0, {0x0c,0xb2,0xc3,0xfc,0xe0,0xcc,0x80,0x7b,0xc0,0x0e,0xf1,0x03,0x7c,0xe0,0xcc,0x83 } },
+{  16, 0xd100, 0, {0x3f,0x20,0x0f,0xf0,0xcb,0x32,0x44,0xdc,0x84,0x3f,0x25,0x4c,0xf2,0x43,0x30,0x00 } },
+{  16, 0xd110, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0xe4,0x48,0xb0,0x10,0x22,0xdc } },
+{  16, 0xd120, 0, {0x08,0xb6,0x02,0xfd,0x92,0x88,0x85,0x23,0xf4,0x40,0xf1,0x02,0xed,0x00,0x88,0x2d } },
+{  16, 0xd130, 0, {0x0e,0x60,0x0b,0xbc,0x12,0x2c,0x10,0xa8,0x82,0x2e,0x00,0x0a,0xfc,0x22,0xa0,0x04 } },
+{  16, 0xd140, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x05,0xc0,0x80,0xb3,0x22,0x28,0xc0 } },
+{  16, 0xd150, 0, {0x08,0x30,0x82,0xcc,0x01,0x88,0x00,0x2c,0xc0,0x4a,0x32,0x02,0xcc,0x00,0x01,0x01 } },
+{  16, 0xd160, 0, {0x28,0x00,0x4b,0xb0,0x02,0xa0,0x00,0x80,0x00,0x2c,0x09,0x08,0x34,0x02,0x62,0x01 } },
+{  16, 0xd170, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x15,0xac,0x04,0xb2,0x10,0x2a,0xc1 } },
+{  16, 0xd180, 0, {0x08,0xb0,0x02,0xec,0x10,0x89,0x80,0x22,0xc0,0x08,0xb0,0x02,0xec,0x08,0x88,0x00 } },
+{  16, 0xd190, 0, {0x2e,0x40,0x83,0xb0,0x02,0xa0,0x40,0xb9,0x80,0x2c,0x21,0x0a,0xb0,0x02,0xf0,0x04 } },
+{  16, 0xd1a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x15,0xec,0x00,0xfa,0x00,0xba,0xc0 } },
+{  16, 0xd1b0, 0, {0x2c,0xb0,0x43,0xec,0x00,0xc0,0x80,0x3e,0xc0,0x8e,0xb0,0x03,0x4c,0x0c,0xc8,0x10 } },
+{  16, 0xd1c0, 0, {0x3e,0x80,0x8f,0xb0,0x03,0x82,0x10,0xd8,0x82,0x3e,0x28,0x0c,0xb0,0x0b,0x50,0x04 } },
+{  16, 0xd1d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0xb6,0x80,0xfd,0x02,0x37,0xc1 } },
+{  16, 0xd1e0, 0, {0x0f,0xb0,0x03,0xfc,0x00,0xfd,0x00,0x3e,0xc0,0x0f,0xb0,0x53,0xfc,0x02,0xff,0x01 } },
+{  16, 0xd1f0, 0, {0x2f,0xa4,0x8b,0xf0,0x83,0x7c,0x00,0xad,0x02,0x2f,0x40,0x03,0x70,0x03,0xb8,0x00 } },
+{  16, 0xd200, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0xac,0x00,0xfb,0x04,0x32,0xc0 } },
+{  16, 0xd210, 0, {0x4c,0xb0,0x23,0x2c,0x00,0xf8,0x40,0x3e,0xc2,0x0c,0xb0,0x03,0x2c,0x00,0xfb,0x41 } },
+{  16, 0xd220, 0, {0x32,0xc2,0x0f,0xb0,0x43,0x2d,0x00,0xc8,0x50,0x3e,0x40,0x0c,0xb0,0x0b,0x10,0x04 } },
+{  16, 0xd230, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x05,0x2f,0x90,0xb9,0x50,0x03,0xc0 } },
+{  16, 0xd240, 0, {0x18,0xf0,0x1a,0x3c,0x00,0xb9,0x32,0x2d,0xe0,0x38,0xf0,0x60,0x3c,0x04,0xf9,0x00 } },
+{  16, 0xd250, 0, {0x3e,0xf0,0x0b,0x7c,0x80,0x2c,0x00,0xd9,0xc0,0x2e,0x40,0x0d,0xf0,0x02,0x32,0x00 } },
+{  16, 0xd260, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x05,0x4b,0x24,0xb2,0x10,0x02,0xc1 } },
+{  16, 0xd270, 0, {0x28,0x30,0x02,0x6c,0x04,0xb2,0xc1,0x2c,0xc0,0x08,0x30,0x00,0x0c,0x00,0xb2,0x00 } },
+{  16, 0xd280, 0, {0x28,0x24,0x03,0x3c,0x0a,0x00,0x00,0x82,0xc8,0x2c,0xa0,0x08,0x30,0x02,0x38,0x00 } },
+{  16, 0xd290, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x16,0x00,0xb4,0x80,0x21,0xe4 } },
+{  16, 0xd2a0, 0, {0x48,0x7b,0x02,0x5e,0x00,0xb6,0x80,0x6d,0xe2,0x48,0x79,0x22,0x1e,0x40,0xac,0x84 } },
+{  16, 0xd2b0, 0, {0x2d,0xe0,0x0b,0xfa,0x00,0x52,0x40,0x96,0x80,0x2d,0xe8,0x19,0x38,0x02,0x08,0x00 } },
+{  16, 0xd2c0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x08,0x40,0xf3,0x10,0xb0,0xc4 } },
+{  16, 0xd2d0, 0, {0x08,0x3a,0x02,0x4c,0x90,0xf3,0x10,0x3c,0xcc,0x08,0x31,0x03,0x0c,0x49,0xb0,0x40 } },
+{  16, 0xd2e0, 0, {0x30,0x05,0x0f,0x30,0x07,0x21,0x40,0x43,0x01,0x3e,0xc2,0x1c,0x30,0x43,0x12,0x02 } },
+{  16, 0xd2f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x0d,0xbc,0x10,0xfc,0x10,0x3f,0xc5 } },
+{  16, 0xd300, 0, {0x0f,0xf1,0x01,0xbc,0x04,0xff,0x04,0x3f,0xc4,0x0f,0xb1,0x4b,0xfc,0x64,0xf7,0x00 } },
+{  16, 0xd310, 0, {0x37,0xc0,0x0f,0x72,0x53,0xac,0x44,0xff,0x01,0x3f,0xc9,0x0f,0xf4,0x03,0xd0,0x06 } },
+{  16, 0xd320, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x05,0xec,0x08,0xfa,0x00,0x3e,0xe0 } },
+{  16, 0xd330, 0, {0x0c,0xb0,0x03,0x2c,0x00,0xcb,0x02,0x3e,0xca,0x0f,0xb2,0x07,0x2e,0x00,0xdb,0x02 } },
+{  16, 0xd340, 0, {0x32,0x08,0x0f,0x31,0x03,0x2c,0x00,0xcb,0x04,0x3e,0x80,0x0c,0x35,0x03,0x2a,0x00 } },
+{  16, 0xd350, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x11,0x94,0x00,0xb5,0x00,0x2d,0xc8 } },
+{  16, 0xd360, 0, {0x08,0x70,0x0a,0x1c,0x22,0x87,0x00,0x2d,0xc9,0x0b,0xf2,0x82,0x9c,0x80,0xa6,0x00 } },
+{  16, 0xd370, 0, {0x09,0x8b,0x0b,0x70,0x0a,0x1c,0x02,0x85,0x00,0x2d,0x40,0x08,0x70,0x02,0x92,0x04 } },
+{  16, 0xd380, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x9e,0x00,0xb7,0x80,0x2c,0xec } },
+{  16, 0xd390, 0, {0x08,0x7b,0x02,0x5e,0x40,0x85,0x89,0x2d,0xec,0x8b,0x7b,0x02,0x4e,0x84,0x8f,0x80 } },
+{  16, 0xd3a0, 0, {0x25,0x64,0x0b,0xfa,0x02,0x12,0x08,0x97,0x80,0x6f,0xe1,0x08,0x7a,0x02,0x30,0x00 } },
+{  16, 0xd3b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x14,0xcc,0x20,0xb3,0x64,0x2c,0xc0 } },
+{  16, 0xd3c0, 0, {0x08,0x30,0x06,0x0c,0x10,0x83,0x8a,0x6c,0xc0,0x5b,0x30,0x42,0xcc,0x00,0xab,0x10 } },
+{  16, 0xd3d0, 0, {0x2c,0xf2,0x0b,0x30,0x02,0x0d,0x00,0x93,0x04,0x2c,0xd5,0x08,0x30,0x0a,0x92,0x04 } },
+{  16, 0xd3e0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe8,0x15,0xbb,0x00,0xfe,0xc0,0x3e,0x80 } },
+{  16, 0xd3f0, 0, {0x2c,0xa0,0x03,0x68,0x00,0xc6,0x40,0x3f,0x80,0x0f,0xa0,0x02,0x68,0x00,0xce,0x44 } },
+{  16, 0xd400, 0, {0x36,0x90,0x4f,0x60,0x03,0x1b,0x70,0xde,0xd8,0x3f,0xa0,0x0c,0x20,0x03,0x3a,0x04 } },
+{  16, 0xd410, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0xe0,0x40,0xf8,0x10,0x3e,0x00 } },
+{  16, 0xd420, 0, {0x0f,0x80,0x03,0xa0,0x10,0xf8,0x42,0x3e,0x10,0x1f,0x80,0x03,0xa0,0x00,0xe8,0x0c } },
+{  16, 0xd430, 0, {0x3a,0x04,0x1f,0x80,0x03,0xe0,0x00,0xe8,0x45,0x7e,0x02,0x2f,0x80,0x03,0xd2,0x00 } },
+{  16, 0xd440, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x64,0x00,0xe9,0x80,0x32,0x40 } },
+{  16, 0xd450, 0, {0x0f,0x90,0x0b,0x04,0x08,0xd9,0x80,0x36,0x40,0x0f,0x10,0x13,0x24,0x08,0xf9,0x00 } },
+{  16, 0xd460, 0, {0x72,0x70,0x0f,0x91,0x13,0x24,0x10,0xc9,0x10,0x3e,0x69,0x0c,0x90,0x03,0x02,0x04 } },
+{  16, 0xd470, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x64,0x08,0xb9,0x80,0x22,0x40 } },
+{  16, 0xd480, 0, {0x0b,0x10,0x02,0x24,0x00,0x89,0xc4,0x22,0x52,0x0b,0x90,0x42,0x24,0x00,0xb9,0x00 } },
+{  16, 0xd490, 0, {0x22,0xe0,0x0b,0x90,0x12,0x24,0x04,0xd9,0x4a,0x2e,0x60,0x08,0x90,0x03,0x60,0x00 } },
+{  16, 0xd4a0, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x05,0x24,0x00,0xb1,0x18,0x22,0x40 } },
+{  16, 0xd4b0, 0, {0x0b,0x90,0x02,0x24,0x00,0x8b,0x20,0x26,0x49,0x0b,0x90,0x02,0x64,0x00,0xb9,0x00 } },
+{  16, 0xd4c0, 0, {0xa2,0x40,0x0b,0x90,0x8a,0x24,0x00,0x8b,0x00,0x2c,0x40,0xa8,0x90,0x02,0x06,0x00 } },
+{  16, 0xd4d0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x84,0xb1,0x20,0xa0,0x48 } },
+{  16, 0xd4e0, 0, {0x0b,0x11,0x06,0x04,0x00,0x83,0x00,0x00,0x40,0x4b,0x11,0x02,0x04,0x49,0xb1,0x10 } },
+{  16, 0xd4f0, 0, {0x28,0x40,0x0b,0x10,0x02,0x24,0x41,0x91,0x00,0x2c,0x50,0x08,0x10,0x02,0x42,0x01 } },
+{  16, 0xd500, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x0d,0x69,0x40,0xe8,0x50,0x32,0x14 } },
+{  16, 0xd510, 0, {0x0f,0x86,0x93,0x21,0xe2,0xc8,0x00,0x36,0x0a,0x0b,0x86,0x8b,0x61,0xa8,0xf8,0x40 } },
+{  16, 0xd520, 0, {0x22,0x80,0x0f,0x82,0xa3,0x21,0x08,0xc8,0x02,0x3e,0x00,0x0c,0x80,0x43,0x2e,0x03 } },
+{  16, 0xd530, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x98,0x1d,0xf4,0x48,0xfd,0x12,0x3e,0x44 } },
+{  16, 0xd540, 0, {0x0f,0x12,0x03,0xc4,0x00,0x7d,0x01,0x1e,0x40,0x0b,0x92,0x03,0xe4,0x80,0xf5,0x20 } },
+{  16, 0xd550, 0, {0x36,0x40,0x0f,0x90,0x03,0xd4,0x90,0x7d,0x00,0x3d,0x40,0x0f,0x94,0x03,0xe6,0x06 } },
+{  16, 0xd560, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x01,0xf6,0xc1,0xdd,0x88,0x32,0x72 } },
+{  16, 0xd570, 0, {0x0c,0x98,0x03,0x26,0x22,0xdd,0x00,0x3f,0x62,0x2c,0x99,0x83,0x46,0xa0,0xc9,0x40 } },
+{  16, 0xd580, 0, {0xb2,0x40,0x0f,0xd8,0x03,0x24,0x00,0xfd,0x00,0x33,0x51,0x2c,0xd8,0x83,0x06,0x00 } },
+{  16, 0xd590, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0xe3,0xc2,0x88,0xc0,0x22,0x30 } },
+{  16, 0xd5a0, 0, {0x08,0x8c,0x42,0x22,0x11,0x8a,0x01,0x2e,0x00,0x08,0x88,0x52,0x23,0x00,0x80,0xa3 } },
+{  16, 0xd5b0, 0, {0x2a,0x00,0x4b,0x80,0x42,0x22,0xa0,0xb8,0x00,0x22,0x28,0x08,0x84,0x02,0x8e,0x04 } },
+{  16, 0xd5c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0xc4,0x00,0x81,0x2d,0x20,0x48 } },
+{  16, 0xd5d0, 0, {0x68,0x14,0x80,0x04,0x20,0x81,0x00,0x2e,0x40,0x0b,0x12,0x12,0x04,0x24,0x81,0x20 } },
+{  16, 0xd5e0, 0, {0x20,0x40,0x0b,0x94,0x32,0x04,0x90,0xb9,0x00,0x20,0x40,0x48,0x10,0x4a,0x02,0x01 } },
+{  16, 0xd5f0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x15,0xa4,0x00,0x89,0x20,0x22,0x40 } },
+{  16, 0xd600, 0, {0x08,0x90,0x12,0x24,0x00,0x89,0x00,0x2e,0x40,0x08,0x90,0x02,0x24,0x08,0x89,0x40 } },
+{  16, 0xd610, 0, {0x22,0x50,0x0b,0xb0,0x02,0x24,0x20,0xb9,0x09,0xa2,0x44,0x08,0x90,0x02,0x86,0x04 } },
+{  16, 0xd620, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x15,0xe4,0x00,0xd9,0x08,0xb2,0x40 } },
+{  16, 0xd630, 0, {0x4c,0x10,0x23,0x04,0x04,0xd9,0xc1,0x3e,0x40,0x8f,0x90,0x0b,0x04,0x08,0xc1,0x40 } },
+{  16, 0xd640, 0, {0x12,0x40,0x0f,0x90,0x43,0x24,0x04,0xf1,0x41,0x30,0x78,0x0c,0x90,0x03,0x28,0x04 } },
+{  16, 0xd650, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x01,0x86,0x64,0xf9,0x80,0x3e,0x40 } },
+{  16, 0xd660, 0, {0x0f,0x90,0x0b,0xe4,0x00,0xf9,0x98,0x3e,0x40,0x2f,0x10,0x03,0xa4,0x02,0xf9,0x10 } },
+{  16, 0xd670, 0, {0x3e,0x40,0x0f,0x90,0x0b,0xe6,0x40,0xf9,0x90,0x3e,0x60,0x0f,0x90,0x03,0xca,0x00 } },
+{  16, 0xd680, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x10,0xa0,0x00,0xc8,0x41,0x32,0x00 } },
+{  16, 0xd690, 0, {0x0c,0x80,0x07,0x20,0x10,0xc8,0x10,0x3e,0x0c,0x0e,0x80,0x03,0xe0,0x04,0xc8,0x00 } },
+{  16, 0xd6a0, 0, {0xba,0x00,0x0f,0x81,0x43,0x20,0x00,0xf8,0x70,0x3e,0x00,0x0f,0x00,0x0b,0x0a,0x04 } },
+{  16, 0xd6b0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x39,0x02,0x8e,0x20,0xa3,0x80 } },
+{  16, 0xd6c0, 0, {0x28,0xe0,0x0a,0x38,0x10,0xae,0x04,0x3d,0xa1,0x8e,0xe0,0x02,0xf8,0x00,0x8e,0x00 } },
+{  16, 0xd6d0, 0, {0x76,0x80,0x0b,0x60,0x03,0x78,0x00,0xbe,0x40,0x2f,0x82,0x0b,0xa0,0x03,0xca,0x00 } },
+{  16, 0xd6e0, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x05,0x4d,0x00,0x8b,0x88,0x22,0xc0 } },
+{  16, 0xd6f0, 0, {0x18,0x30,0x02,0x0c,0x00,0x83,0x44,0x2c,0xd0,0x1b,0x30,0x12,0xcc,0x06,0x83,0x00 } },
+{  16, 0xd700, 0, {0x20,0xc1,0x0b,0x30,0x82,0x0c,0x01,0xb3,0x00,0x2c,0x40,0x0b,0x30,0x02,0x0a,0x00 } },
+{  16, 0xd710, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01,0x1c,0x00,0x85,0x00,0x20,0xcc } },
+{  16, 0xd720, 0, {0x08,0x70,0x06,0x1c,0x84,0xa7,0x01,0x29,0xc0,0x0b,0x72,0x22,0xdc,0x80,0x87,0x34 } },
+{  16, 0xd730, 0, {0x61,0x80,0x0b,0x10,0x02,0x5c,0x00,0xb7,0x00,0x2d,0xc0,0x0b,0x70,0x02,0xe8,0x00 } },
+{  16, 0xd740, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x08,0x0e,0x00,0x8c,0x80,0x31,0xe0 } },
+{  16, 0xd750, 0, {0x0c,0xfe,0x02,0x3f,0x00,0xc5,0x80,0x2d,0xe0,0x0e,0x78,0x03,0xdf,0xa0,0xc7,0xa0 } },
+{  16, 0xd760, 0, {0x21,0x60,0x0f,0x78,0x03,0x1e,0x80,0xf7,0x80,0x3d,0xe0,0x0f,0x78,0x03,0x2a,0x02 } },
+{  16, 0xd770, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1d,0xac,0x00,0xf9,0x00,0x3e,0xc0 } },
+{  16, 0xd780, 0, {0x0f,0xb0,0x03,0xec,0x00,0xfa,0x00,0x3e,0xc0,0x06,0xb0,0x03,0xec,0x80,0xfb,0x28 } },
+{  16, 0xd790, 0, {0x36,0xd8,0x4f,0xa0,0x03,0xec,0x10,0xfa,0x00,0x3e,0x50,0x0f,0x30,0x03,0xc2,0x06 } },
+{  16, 0xd7a0, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xfa,0x00,0xcc,0x80,0xb3,0xe0 } },
+{  16, 0xd7b0, 0, {0x0f,0xf8,0x03,0x3e,0x00,0xcf,0x90,0x3f,0x60,0x4f,0xf8,0xc3,0x3e,0x00,0xef,0x80 } },
+{  16, 0xd7c0, 0, {0x33,0xf0,0x0c,0x7a,0x03,0x3e,0x70,0xc5,0x90,0x33,0xf1,0x0c,0x78,0x03,0x00,0x00 } },
+{  16, 0xd7d0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x11,0xb8,0x00,0x87,0x00,0x21,0xc0 } },
+{  16, 0xd7e0, 0, {0x0b,0x70,0x4a,0x1c,0x00,0x87,0x10,0x2d,0xc0,0x4b,0x71,0x0a,0x3c,0x44,0x8f,0x12 } },
+{  16, 0xd7f0, 0, {0x21,0x86,0x0d,0x72,0x02,0x1e,0x00,0x87,0x00,0x23,0x40,0x08,0x70,0x0a,0x2a,0x04 } },
+{  16, 0xd800, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x00,0x84,0x00,0x25,0xc0 } },
+{  16, 0xd810, 0, {0x0b,0x71,0x0a,0x0c,0x00,0xa7,0x12,0x2d,0x84,0x0b,0x70,0x0a,0x1c,0x00,0xb7,0x08 } },
+{  16, 0xd820, 0, {0x23,0x40,0x09,0xf3,0x1a,0x5c,0x86,0x97,0x08,0x25,0x40,0x08,0x70,0x02,0x00,0x00 } },
+{  16, 0xd830, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x14,0xcc,0x20,0x81,0x20,0x26,0xc0 } },
+{  16, 0xd840, 0, {0x0b,0x30,0x02,0x2c,0x00,0x82,0x42,0x2c,0x80,0x0b,0x30,0x22,0x0c,0x08,0x9b,0x80 } },
+{  16, 0xd850, 0, {0x20,0xe0,0x09,0x20,0x02,0x4d,0x08,0x92,0x00,0x24,0xe5,0x08,0x30,0x0a,0x08,0x04 } },
+{  16, 0xd860, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x15,0xae,0x82,0xca,0xe0,0xb7,0xc0 } },
+{  16, 0xd870, 0, {0x0f,0xf0,0x13,0x3c,0x0a,0xc9,0xc8,0x3e,0x40,0x0f,0xf0,0x03,0x3c,0x04,0xff,0x84 } },
+{  16, 0xd880, 0, {0x32,0xc0,0x0d,0x90,0x13,0x7c,0x00,0xd9,0x00,0xf6,0xc0,0x2c,0x10,0x03,0x2a,0x04 } },
+{  16, 0xd890, 0, {0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xe4,0x00,0xf3,0x00,0x3a,0xc1 } },
+{  16, 0xd8a0, 0, {0x4f,0xb0,0x03,0xec,0x00,0xf9,0x08,0x3c,0x00,0x0f,0x30,0x13,0xec,0x00,0xeb,0x04 } },
+{  16, 0xd8b0, 0, {0xbe,0x18,0x0f,0x90,0x23,0xac,0x60,0xe9,0x02,0x3a,0x40,0x4f,0x90,0x03,0xe0,0x00 } },
+{  16, 0xd8c0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0xfc,0x00,0xca,0x00,0x33,0xc0 } },
+{  16, 0xd8d0, 0, {0x0c,0xf0,0x03,0xfc,0x00,0xcd,0x02,0x7f,0x40,0x0c,0xf0,0x42,0x3c,0x00,0xcf,0x08 } },
+{  16, 0xd8e0, 0, {0x37,0x10,0x0f,0xd0,0x03,0xfc,0x10,0xcd,0x08,0x3f,0x66,0x2c,0xd9,0x03,0x00,0x44 } },
+{  16, 0xd8f0, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x04,0x63,0x80,0x8b,0xe0,0x22,0xc0 } },
+{  16, 0xd900, 0, {0x08,0xb0,0x22,0xec,0x00,0xd8,0x80,0x6e,0x20,0x68,0xb0,0x1a,0x2c,0x01,0xfb,0x00 } },
+{  16, 0xd910, 0, {0x22,0x18,0x0b,0x88,0x43,0x4c,0x00,0x88,0xa0,0x2c,0xc0,0x1d,0x90,0x02,0x20,0x40 } },
+{  16, 0xd920, 0, {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x08,0x80,0x8b,0x20,0x22,0xc0 } },
+{  16, 0xd930, 0, {0x08,0xb0,0x22,0xec,0x00,0x88,0x88,0x2e,0x62,0x48,0xb0,0x1a,0xcc,0x00,0x8b,0x00 } },
+{  16, 0xd940, 0, {0x26,0xc0,0x4a,0x88,0x02,0xec,0x00,0x08,0x84,0x2e,0x40,0x09,0x90,0x02,0x20,0x00 } },
+{  16, 0xd950, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x83,0x00,0x60,0xc0 } },
+{  16, 0xd960, 0, {0x08,0x30,0x02,0xcc,0x00,0x90,0x06,0x6c,0x00,0x08,0x30,0x02,0x8c,0x00,0xa3,0x04 } },
+{  16, 0xd970, 0, {0x20,0x00,0x8b,0x00,0x06,0x4c,0x21,0x80,0x00,0x6c,0xc0,0x49,0x10,0x0a,0x02,0x01 } },
+{  16, 0xd980, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x6c,0x00,0xca,0x00,0xb2,0xc1 } },
+{  16, 0xd990, 0, {0x88,0xb4,0x03,0xec,0x10,0xc8,0x00,0x2e,0x00,0x0c,0xb0,0x0b,0xbc,0x08,0x8f,0x00 } },
+{  16, 0xd9a0, 0, {0x36,0x00,0x06,0x80,0x03,0xec,0x80,0xc8,0x02,0x3f,0xc1,0x0c,0x90,0x03,0x00,0x03 } },
+{  16, 0xd9b0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x1d,0xf0,0x00,0xff,0x00,0x3f,0xc0 } },
+{  16, 0xd9c0, 0, {0x0f,0x72,0x83,0xfc,0x18,0xfc,0x03,0x3f,0x00,0x8f,0x70,0x03,0x7c,0x00,0xff,0x00 } },
+{  16, 0xd9d0, 0, {0x3d,0x00,0x0f,0xc0,0x23,0x8c,0x06,0xfc,0x00,0x3f,0x40,0x0e,0xd0,0x03,0xe8,0x06 } },
+{  16, 0xd9e0, 0, {0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x41,0x03,0x70,0x40,0xdc,0x10 } },
+{  16, 0xd9f0, 0, {0x37,0x04,0x0d,0xc1,0x03,0x70,0x40,0xdc,0x10,0x37,0x04,0x0d,0xc1,0x01,0x70,0x40 } },
+{  16, 0xda00, 0, {0x9c,0x10,0x17,0x14,0x05,0xc1,0x03,0x70,0x40,0xdc,0x10,0x17,0x04,0x0d,0xc0,0x31 } },
+{  16, 0xda10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x44,0x05,0x71,0x01,0x5c,0x40 } },
+{  16, 0xda20, 0, {0x57,0x10,0x15,0xc4,0x05,0x21,0x01,0x5c,0x40,0x57,0x10,0x15,0xc4,0x01,0x71,0x01 } },
+{  16, 0xda30, 0, {0x5c,0x40,0x17,0x10,0x05,0xc4,0x05,0x71,0x05,0x5c,0x41,0x57,0x10,0x15,0xc0,0x11 } },
+{  16, 0xda40, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x01,0x20,0x80,0x48,0x20 } },
+{  16, 0xda50, 0, {0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80 } },
+{  16, 0xda60, 0, {0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x80,0x20 } },
+{  16, 0xda70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x60,0x00,0x58,0x00 } },
+{  16, 0xda80, 0, {0x16,0x00,0x05,0x80,0x01,0x60,0x00,0x58,0x00,0x16,0x00,0x05,0x80,0x05,0x60,0x00 } },
+{  16, 0xda90, 0, {0x58,0x00,0x16,0x18,0x01,0x80,0x01,0x60,0x00,0x58,0x00,0x56,0x00,0x05,0x80,0x20 } },
+{  16, 0xdaa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x48,0x05,0x22,0x01,0x1c,0x80 } },
+{  16, 0xdab0, 0, {0x47,0x20,0x11,0xc8,0x04,0x72,0x01,0x5c,0x80,0x57,0x20,0x11,0xc8,0x04,0x72,0x41 } },
+{  16, 0xdac0, 0, {0x5c,0x80,0x57,0x20,0x11,0xc8,0x04,0x72,0x01,0x1c,0x80,0x47,0x20,0x15,0xc0,0x31 } },
+{  16, 0xdad0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x00,0x60,0x00,0x18,0x00 } },
+{  16, 0xdae0, 0, {0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00 } },
+{  16, 0xdaf0, 0, {0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x31 } },
+{  16, 0xdb00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x48,0x04,0x22,0x01,0x08,0x80 } },
+{  16, 0xdb10, 0, {0x42,0x20,0x10,0x88,0x04,0x22,0x01,0x08,0x80,0x42,0x20,0x10,0x80,0x04,0x23,0x01 } },
+{  16, 0xdb20, 0, {0x08,0x80,0x42,0x20,0x10,0x88,0x04,0x22,0x01,0x08,0x00,0x42,0x20,0x10,0x80,0x21 } },
+{  16, 0xdb30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x4a,0x05,0x42,0x81,0x50,0xa0 } },
+{  16, 0xdb40, 0, {0x44,0x2c,0x11,0x0b,0x04,0x42,0x81,0x10,0xe0,0x54,0x28,0x11,0x02,0x00,0x42,0x81 } },
+{  16, 0xdb50, 0, {0x10,0xa0,0x44,0x38,0x11,0x0b,0x05,0x42,0x81,0x10,0x21,0x14,0x28,0x15,0x00,0x31 } },
+{  16, 0xdb60, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0c,0x01,0x57,0x00,0x54,0xc0 } },
+{  16, 0xdb70, 0, {0x15,0x30,0x04,0x4c,0x01,0x13,0x00,0x54,0xc0,0x15,0x70,0x05,0x4c,0x01,0x53,0x00 } },
+{  16, 0xdb80, 0, {0x54,0xc0,0x15,0x30,0x85,0x4c,0x01,0x13,0x00,0x54,0xc0,0x15,0x30,0x05,0x40,0x21 } },
+{  16, 0xdb90, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x40,0x00,0x10,0x00 } },
+{  16, 0xdba0, 0, {0x04,0x00,0x00,0x40,0x00,0x10,0x00,0x10,0x62,0x04,0x00,0x01,0x08,0x04,0x41,0x00 } },
+{  16, 0xdbb0, 0, {0x10,0x00,0x44,0x18,0x11,0x00,0x00,0x10,0x00,0x10,0x80,0x04,0x00,0x01,0x01,0x20 } },
+{  16, 0xdbc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x60,0x02,0x08,0x00,0x82,0x00 } },
+{  16, 0xdbd0, 0, {0x20,0x80,0x08,0x60,0x02,0x18,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x00,0x08,0x20 } },
+{  16, 0xdbe0, 0, {0x82,0x00,0x00,0x80,0x80,0x20,0x02,0x18,0x00,0x82,0x00,0x20,0x80,0x08,0x01,0x31 } },
+{  16, 0xdbf0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x05,0x64,0x01,0x58,0x00 } },
+{  16, 0xdc00, 0, {0x56,0x00,0x15,0x80,0x05,0x60,0x01,0x58,0x00,0x56,0x40,0x15,0x80,0x05,0x60,0x01 } },
+{  16, 0xdc10, 0, {0x58,0x00,0x56,0x00,0x15,0x80,0x05,0x60,0x01,0x58,0x00,0x76,0x00,0x15,0x80,0x31 } },
+{  16, 0xdc20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x03,0x60,0x00,0xd8,0x00 } },
+{  16, 0xdc30, 0, {0x36,0x00,0x0d,0x80,0x03,0x60,0x00,0x98,0x00,0x36,0x00,0x1d,0x88,0x05,0x60,0x00 } },
+{  16, 0xdc40, 0, {0xd8,0x00,0x16,0x00,0x0d,0x80,0x03,0x60,0x00,0xd8,0x80,0x46,0x00,0x0d,0x80,0x31 } },
+{  16, 0xdc50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x04,0x30,0x81,0x0c,0x20 } },
+{  16, 0xdc60, 0, {0x43,0x08,0x10,0xc2,0x04,0x30,0x81,0x0c,0x22,0x41,0x08,0x18,0xc2,0x04,0x30,0x89 } },
+{  16, 0xdc70, 0, {0x0c,0x20,0x03,0x08,0x10,0xc2,0x04,0x30,0x81,0x0c,0x20,0x43,0x08,0x10,0xc0,0x10 } },
+{  16, 0xdc80, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x30,0x00,0x0c,0x00 } },
+{  16, 0xdc90, 0, {0x03,0x00,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0xc0,0x00,0x30,0x00 } },
+{  16, 0xdca0, 0, {0x0c,0x00,0x03,0x00,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0xc0,0x01 } },
+{  16, 0xdcb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x01,0x30,0x80,0x4c,0x20 } },
+{  16, 0xdcc0, 0, {0x13,0x08,0x04,0xc2,0x01,0x30,0x80,0x4c,0x20,0x13,0x08,0x04,0xc3,0x01,0x30,0x80 } },
+{  16, 0xdcd0, 0, {0x4c,0x20,0x13,0x08,0x04,0xc2,0x01,0x30,0x80,0x4c,0x30,0x13,0x08,0x04,0xc0,0x21 } },
+{  16, 0xdce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x05,0x60,0x81,0x58,0x20 } },
+{  16, 0xdcf0, 0, {0x56,0x08,0x11,0x82,0x05,0x60,0x81,0x58,0x20,0x56,0x08,0x11,0x83,0x00,0x60,0x81 } },
+{  16, 0xdd00, 0, {0x58,0x20,0x46,0x08,0x11,0x82,0x04,0x60,0x81,0x18,0x30,0x56,0x08,0x15,0x80,0x30 } },
+{  16, 0xdd10, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x00,0x20,0x80,0x08,0x20 } },
+{  16, 0xdd20, 0, {0x02,0x08,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x02,0x08,0x00,0x82,0x00,0x30,0x80 } },
+{  16, 0xdd30, 0, {0x08,0x20,0x02,0x00,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x03,0x08,0x00,0x80,0x31 } },
+{  16, 0xdd40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x42,0x04,0x60,0x81,0x18,0x20 } },
+{  16, 0xdd50, 0, {0x46,0x48,0x11,0x92,0x04,0x60,0x81,0x19,0x20,0x46,0x28,0x11,0x82,0x00,0x34,0x81 } },
+{  16, 0xdd60, 0, {0x18,0x20,0x46,0x48,0x11,0x92,0x04,0x60,0x81,0x18,0x20,0x43,0x08,0x11,0x80,0x11 } },
+{  16, 0xdd70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x60,0x04,0x58,0x01,0x56,0x00 } },
+{  16, 0xdd80, 0, {0x55,0x80,0x15,0x60,0x04,0x58,0x01,0x16,0x00,0x55,0x80,0x01,0x60,0x04,0x18,0x01 } },
+{  16, 0xdd90, 0, {0x56,0x00,0x45,0x80,0x11,0x60,0x04,0x58,0x01,0x16,0x00,0x41,0x80,0x11,0x40,0x31 } },
+{  16, 0xdda0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x06,0x01,0x41,0x80,0x50,0x60 } },
+{  16, 0xddb0, 0, {0x14,0x18,0x05,0x06,0x01,0x41,0x80,0x50,0x60,0x04,0x18,0x05,0x06,0x00,0x41,0x80 } },
+{  16, 0xddc0, 0, {0x10,0x60,0x14,0x18,0x05,0x06,0x01,0x41,0x80,0x50,0x60,0x14,0x18,0x05,0x00,0x20 } },
+{  16, 0xddd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x00,0x80,0x40,0x20 } },
+{  16, 0xdde0, 0, {0x10,0x48,0x04,0x12,0x01,0x00,0x80,0x41,0x20,0x10,0x08,0x04,0x02,0x01,0x04,0x80 } },
+{  16, 0xddf0, 0, {0x40,0x20,0x50,0x48,0x04,0x12,0x01,0x00,0x84,0x40,0x20,0x10,0x08,0x04,0x00,0x20 } },
+{  16, 0xde00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x46,0x03,0x51,0x80,0xd4,0x60 } },
+{  16, 0xde10, 0, {0x30,0x18,0x0d,0x46,0x03,0x51,0x80,0xd5,0x60,0x35,0x18,0x0d,0x46,0x03,0x05,0x80 } },
+{  16, 0xde20, 0, {0xd4,0x60,0x15,0x18,0x0d,0x46,0x03,0x11,0x80,0xd4,0x60,0x35,0x18,0x0d,0x40,0x31 } },
+{  16, 0xde30, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x46,0x05,0x71,0x80,0x5c,0x60 } },
+{  16, 0xde40, 0, {0x97,0x18,0x15,0xc6,0x05,0x71,0x81,0x5c,0x20,0x57,0x18,0x15,0xc6,0x03,0x70,0x81 } },
+{  16, 0xde50, 0, {0x5c,0x60,0x57,0x18,0x11,0xc6,0x05,0x31,0x81,0x5c,0x60,0x77,0x18,0x15,0xc0,0x31 } },
+{  16, 0xde60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x46,0x03,0x71,0x80,0xdc,0x60 } },
+{  16, 0xde70, 0, {0x37,0x18,0x0d,0xc6,0x03,0x71,0x80,0xdd,0x60,0x37,0x18,0x05,0xc6,0x01,0x75,0x81 } },
+{  16, 0xde80, 0, {0xdc,0x60,0x37,0x18,0x0d,0xc6,0x03,0x71,0x84,0x5c,0x60,0x17,0x18,0x19,0xc0,0x11 } },
+{  16, 0xde90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x46,0x05,0x71,0x81,0x5c,0x60 } },
+{  16, 0xdea0, 0, {0x57,0x18,0x14,0x86,0x05,0x71,0x81,0x5c,0x60,0x57,0x18,0x05,0xc6,0x04,0x31,0x81 } },
+{  16, 0xdeb0, 0, {0x5c,0x60,0x57,0x18,0x15,0xc6,0x05,0x71,0x80,0x5c,0x60,0x43,0x18,0x15,0xc0,0x11 } },
+{  16, 0xdec0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x20,0x80,0x48,0x20 } },
+{  16, 0xded0, 0, {0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x70,0x80 } },
+{  16, 0xdee0, 0, {0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x17,0x08,0x04,0x80,0x00 } },
+{  16, 0xdef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x01,0x61,0x80,0x58,0x60 } },
+{  16, 0xdf00, 0, {0x16,0x18,0x41,0x86,0x01,0x61,0x80,0x18,0x60,0x06,0x3c,0x05,0x86,0x04,0x61,0x80 } },
+{  16, 0xdf10, 0, {0x18,0x60,0x16,0x18,0x01,0x86,0x00,0x61,0x80,0x58,0x60,0x56,0x18,0x15,0x80,0x10 } },
+{  16, 0xdf20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x40,0x05,0x70,0x01,0x5c,0x00 } },
+{  16, 0xdf30, 0, {0x57,0x00,0x15,0xc0,0x04,0x70,0x01,0x5c,0x00,0x57,0x00,0x10,0xc0,0x04,0x70,0x00 } },
+{  16, 0xdf40, 0, {0x1c,0x00,0x47,0x00,0x11,0xc0,0x04,0x70,0x01,0x5c,0x00,0x47,0x00,0x01,0xc0,0x11 } },
+{  16, 0xdf50, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x42,0x00,0x60,0x80,0x18,0x20 } },
+{  16, 0xdf60, 0, {0x06,0x08,0x01,0x82,0x00,0x60,0x80,0x18,0x20,0x06,0x08,0x00,0x82,0x00,0x60,0x80 } },
+{  16, 0xdf70, 0, {0x18,0x20,0x06,0x08,0x01,0x82,0x00,0x60,0x80,0x18,0x20,0x06,0x08,0x01,0x80,0x11 } },
+{  16, 0xdf80, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x42,0x04,0x20,0x81,0x08,0x20 } },
+{  16, 0xdf90, 0, {0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x42,0x08,0x11,0x82,0x04,0x20,0x80 } },
+{  16, 0xdfa0, 0, {0x08,0x20,0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x42,0x08,0x00,0x80,0x11 } },
+{  16, 0xdfb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x42,0x05,0x40,0x81,0x50,0x20 } },
+{  16, 0xdfc0, 0, {0x54,0x08,0x15,0x02,0x05,0x40,0x81,0x10,0x20,0x54,0x0c,0x15,0x42,0x00,0x40,0x81 } },
+{  16, 0xdfd0, 0, {0x50,0x20,0x44,0x08,0x11,0x02,0x05,0x40,0x81,0x10,0x20,0x14,0x08,0x05,0x00,0x11 } },
+{  16, 0xdfe0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x01,0x50,0xc0,0x54,0x30 } },
+{  16, 0xdff0, 0, {0x15,0x08,0x05,0x42,0x01,0x50,0xc0,0x54,0x30,0x15,0x0c,0x05,0x43,0x01,0x50,0xc0 } },
+{  16, 0xe000, 0, {0x54,0x30,0x15,0x0c,0x05,0x42,0x01,0x50,0xc0,0x54,0x30,0x15,0x0c,0x05,0x40,0x10 } },
+{  16, 0xe010, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x00,0x10,0x80 } },
+{  16, 0xe020, 0, {0x04,0x20,0x01,0x88,0x00,0x62,0x00,0x10,0x80,0x04,0x00,0x11,0x08,0x00,0x42,0x00 } },
+{  16, 0xe030, 0, {0x10,0x80,0x04,0x20,0x01,0x08,0x00,0x42,0x01,0x10,0x80,0x04,0x20,0x01,0x00,0x00 } },
+{  16, 0xe040, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x42,0x02,0x00,0x80,0x80,0x20 } },
+{  16, 0xe050, 0, {0x20,0x08,0x08,0x02,0x02,0x20,0x80,0x80,0x20,0x20,0x28,0x00,0x02,0x02,0x00,0x80 } },
+{  16, 0xe060, 0, {0x80,0x20,0x20,0x0a,0x08,0x02,0x02,0x00,0x80,0x00,0x20,0x20,0x08,0x08,0x00,0x11 } },
+{  16, 0xe070, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x40,0x05,0x60,0x01,0x58,0x00 } },
+{  16, 0xe080, 0, {0x56,0x00,0x05,0x80,0x05,0x60,0x01,0x58,0x08,0x56,0x00,0x15,0x80,0x07,0x60,0x02 } },
+{  16, 0xe090, 0, {0x58,0x00,0x56,0x40,0x15,0x80,0x05,0x60,0x03,0x18,0x00,0x76,0x00,0x15,0x80,0x11 } },
+{  16, 0xe0a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x40,0x03,0x60,0x00,0xd8,0x00 } },
+{  16, 0xe0b0, 0, {0x36,0x00,0x0d,0x80,0x01,0x60,0x00,0xd8,0x0a,0x36,0x00,0x0d,0x80,0x05,0x70,0x09 } },
+{  16, 0xe0c0, 0, {0xd8,0x01,0x36,0x00,0x0d,0x80,0x03,0x60,0x00,0xd8,0x00,0x57,0x00,0x0d,0x80,0x00 } },
+{  16, 0xe0d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x30,0x01,0x0c,0x00 } },
+{  16, 0xe0e0, 0, {0x43,0x00,0x10,0xc0,0x00,0x30,0x01,0x0c,0x00,0x43,0x20,0x10,0xc0,0x04,0x60,0x01 } },
+{  16, 0xe0f0, 0, {0x0c,0x00,0x43,0x40,0x50,0xc1,0x04,0x30,0x01,0x0c,0x00,0x46,0x00,0x10,0xc0,0x00 } },
+{  16, 0xe100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0c,0x00 } },
+{  16, 0xe110, 0, {0x01,0x00,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0xd0,0x00,0x20,0x00 } },
+{  16, 0xe120, 0, {0x0c,0x00,0x03,0x40,0x00,0xc0,0x00,0x30,0x00,0x0d,0x00,0x02,0x00,0x00,0xc0,0x00 } },
+{  16, 0xe130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x01,0x31,0x40,0x4c,0x50 } },
+{  16, 0xe140, 0, {0x13,0x10,0x04,0xc4,0x01,0x31,0x40,0x4c,0x50,0x13,0x14,0x04,0xc5,0x11,0x31,0x41 } },
+{  16, 0xe150, 0, {0x4c,0x50,0x13,0x14,0x04,0xc5,0x01,0x31,0x40,0x4c,0x50,0x13,0x14,0x04,0xc0,0x00 } },
+{  16, 0xe160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x05,0x68,0xc1,0x5a,0x30 } },
+{  16, 0xe170, 0, {0x56,0x8c,0x11,0xa3,0x04,0x68,0xc1,0x1a,0x30,0x56,0x8c,0x11,0xa3,0x05,0x68,0xc0 } },
+{  16, 0xe180, 0, {0x5a,0x30,0x46,0x8c,0x11,0xa3,0x04,0x68,0xc1,0x5a,0x30,0x16,0x8c,0x15,0x80,0x00 } },
+{  16, 0xe190, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x00 } },
+{  16, 0xe1a0, 0, {0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x00,0x02,0x20,0x00,0x90,0x00,0x20,0x00 } },
+{  16, 0xe1b0, 0, {0x08,0x00,0x02,0x40,0x00,0x80,0x00,0x20,0x00,0x09,0x00,0x02,0x00,0x00,0x80,0x00 } },
+{  16, 0xe1c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x44,0x62,0x01,0x18,0x84 } },
+{  16, 0xe1d0, 0, {0x46,0x21,0x11,0x88,0x44,0x62,0x11,0x18,0x84,0x46,0x01,0x11,0x88,0x44,0x62,0x10 } },
+{  16, 0xe1e0, 0, {0x18,0x84,0x46,0x21,0x11,0x88,0x44,0x62,0x11,0x18,0x84,0x06,0x21,0x11,0x80,0x00 } },
+{  16, 0xe1f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45,0x50,0x11,0x54,0x04 } },
+{  16, 0xe200, 0, {0x55,0x01,0x11,0x40,0x45,0x50,0x11,0x14,0x00,0x45,0x01,0x11,0x40,0x44,0x50,0x00 } },
+{  16, 0xe210, 0, {0x14,0x04,0x45,0x00,0x15,0x40,0x44,0x50,0x11,0x14,0x04,0x55,0x01,0x11,0x40,0x00 } },
+{  16, 0xe220, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x21,0x42,0x08,0x50,0x82 } },
+{  16, 0xe230, 0, {0x14,0x20,0x85,0x08,0x21,0x42,0x08,0x50,0x82,0x04,0x20,0x85,0x08,0x21,0x42,0x08 } },
+{  16, 0xe240, 0, {0x50,0x82,0x14,0x20,0x05,0x08,0x21,0x42,0x08,0x50,0x82,0x14,0x20,0x85,0x00,0x00 } },
+{  16, 0xe250, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x01,0x02,0x80,0x40,0xa0 } },
+{  16, 0xe260, 0, {0x10,0x28,0x04,0x0a,0x01,0x02,0x80,0x40,0xa0,0x10,0x28,0x40,0x0a,0x01,0x02,0x80 } },
+{  16, 0xe270, 0, {0x40,0xa0,0x10,0x28,0x44,0x0a,0x01,0x02,0x80,0x40,0xa0,0x10,0x28,0x04,0x00,0x00 } },
+{  16, 0xe280, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x03,0x53,0x00,0xd4,0xc0 } },
+{  16, 0xe290, 0, {0x35,0x30,0x0d,0x4c,0x01,0x53,0x00,0xd4,0xc0,0x35,0x10,0x0c,0x4c,0x03,0x53,0x00 } },
+{  16, 0xe2a0, 0, {0xd4,0xc0,0x35,0x30,0x0d,0x4c,0x03,0x53,0x00,0xd4,0xc0,0x35,0x30,0x0d,0x40,0x00 } },
+{  16, 0xe2b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x05,0x72,0x01,0x5c,0x80 } },
+{  16, 0xe2c0, 0, {0x17,0x20,0x05,0xc8,0x06,0x72,0x01,0x5c,0x80,0x57,0x20,0x15,0xc8,0x02,0x72,0x01 } },
+{  16, 0xe2d0, 0, {0x5c,0x80,0x57,0x20,0x15,0xc8,0x05,0x72,0x01,0x5c,0x80,0x37,0x20,0x11,0xc0,0x00 } },
+{  16, 0xe2e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x18,0x40,0xc6,0x12,0x31 } },
+{  16, 0xe2f0, 0, {0x84,0x8c,0x21,0x23,0x08,0x48,0xc6,0x12,0x30,0x84,0x0c,0x61,0x23,0x10,0x48,0xc2 } },
+{  16, 0xe300, 0, {0x12,0x31,0x84,0x8c,0x01,0x23,0x08,0x48,0xc6,0x12,0x31,0x04,0x8c,0x61,0x00,0x00 } },
+{  16, 0xe310, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x4f,0xff,0xd3,0xff } },
+{  16, 0xe320, 0, {0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff } },
+{  16, 0xe330, 0, {0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x00,0x00 } },
+{  16, 0xe340, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xe350, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xe360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xe370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xdb,0x0f,0xb6,0xc2,0xcd } },
+{  16, 0xe380, 0, {0xb0,0xb3,0x6c,0x2c,0xdb,0x0b,0x36,0xc2,0xdf,0xb0,0xb3,0x6c,0x2c,0xdb,0x0b,0x7e } },
+{  16, 0xe390, 0, {0xc2,0xcd,0xb0,0xb7,0xfd,0x2c,0xdb,0x0b,0x36,0xc2,0xcd,0xb0,0xb3,0x6c,0x00,0x00 } },
+{  16, 0xe3a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x3c,0x4f,0xcf,0x13,0x33 } },
+{  16, 0xe3b0, 0, {0xc4,0xcc,0xf1,0x33,0x3c,0x4c,0xcf,0x13,0x3f,0xc4,0xcc,0xf1,0x33,0x3c,0x4c,0xff } },
+{  16, 0xe3c0, 0, {0x13,0x33,0xc4,0xcf,0xfd,0x33,0x3c,0x4c,0xcf,0x13,0x33,0xc4,0xcc,0xf1,0x00,0x00 } },
+{  16, 0xe3d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3b,0x7e,0x4e,0xdf,0x93,0xb7 } },
+{  16, 0xe3e0, 0, {0xe4,0xec,0x79,0x3b,0x1e,0x4e,0xdf,0x93,0xbf,0xe4,0x8d,0xf9,0x3b,0x78,0x4e,0xff } },
+{  16, 0xe3f0, 0, {0x93,0xb7,0xe4,0xed,0xfd,0x3b,0x1e,0x4e,0xdf,0x93,0xb7,0x84,0xed,0xf9,0x00,0x00 } },
+{  16, 0xe400, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x70,0x40,0x9c,0x10 } },
+{  16, 0xe410, 0, {0x27,0x1c,0x09,0xc1,0x01,0x30,0x40,0x1c,0x10,0x67,0x04,0x09,0xc1,0x02,0x70,0x41 } },
+{  16, 0xe420, 0, {0x9c,0x11,0x07,0x14,0x01,0xc1,0x02,0x70,0x40,0x9c,0x50,0x07,0x1c,0x01,0xc0,0x00 } },
+{  16, 0xe430, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x05,0x71,0x01,0x5c,0x40 } },
+{  16, 0xe440, 0, {0x57,0x10,0x55,0xc4,0x01,0x31,0x00,0x5c,0x40,0x57,0x10,0x15,0xc4,0x05,0x71,0x01 } },
+{  16, 0xe450, 0, {0xdc,0x40,0x17,0x18,0x1d,0xc4,0x05,0x71,0x05,0x5c,0x40,0x57,0x10,0x1d,0xc0,0x00 } },
+{  16, 0xe460, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x20,0x80,0x48,0x20 } },
+{  16, 0xe470, 0, {0x12,0x00,0x04,0x82,0x01,0x20,0x80,0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80 } },
+{  16, 0xe480, 0, {0x48,0x20,0x12,0x08,0x04,0x82,0x01,0x20,0x80,0x48,0x60,0x12,0x08,0x04,0x80,0x00 } },
+{  16, 0xe490, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00 } },
+{  16, 0xe4a0, 0, {0x06,0x00,0x41,0x80,0x00,0x60,0x00,0x18,0x00,0x46,0x00,0x01,0x80,0x00,0x60,0x00 } },
+{  16, 0xe4b0, 0, {0x10,0x00,0x06,0x10,0x01,0x80,0x00,0x60,0x00,0x18,0x20,0x46,0x10,0x01,0x80,0x00 } },
+{  16, 0xe4c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x72,0x01,0x1c,0x80 } },
+{  16, 0xe4d0, 0, {0x47,0x20,0x11,0xc8,0x04,0x72,0x01,0x1c,0x80,0x07,0x20,0x11,0xc8,0x04,0x73,0x00 } },
+{  16, 0xe4e0, 0, {0x1c,0x80,0x47,0x20,0x11,0xcc,0x04,0x72,0x01,0x1c,0x80,0x47,0x20,0x11,0xc0,0x00 } },
+{  16, 0xe4f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00 } },
+{  16, 0xe500, 0, {0x06,0x00,0x01,0x84,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x40 } },
+{  16, 0xe510, 0, {0x18,0x00,0x06,0x04,0x01,0x81,0x00,0x60,0x00,0x18,0x00,0x06,0x14,0x01,0x80,0x00 } },
+{  16, 0xe520, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x22,0x01,0x08,0x80 } },
+{  16, 0xe530, 0, {0x42,0x70,0x10,0x8c,0x04,0x22,0x01,0x08,0xc0,0x02,0x20,0x10,0x88,0x04,0x22,0x00 } },
+{  16, 0xe540, 0, {0x08,0x80,0x42,0x50,0x10,0x08,0x04,0x22,0x01,0x09,0x00,0x42,0x40,0x10,0x80,0x00 } },
+{  16, 0xe550, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x04,0x4a,0x81,0x12,0xa0 } },
+{  16, 0xe560, 0, {0x44,0xa8,0x11,0x2a,0x04,0x4a,0x81,0x12,0xa0,0x04,0xa8,0x11,0x2a,0x04,0x4b,0x80 } },
+{  16, 0xe570, 0, {0x12,0xa0,0x44,0x88,0x01,0x2e,0x04,0x4a,0x81,0x12,0x20,0x04,0x98,0x01,0x00,0x00 } },
+{  16, 0xe580, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x0e,0x00,0x53,0x00,0x14,0xc0 } },
+{  16, 0xe590, 0, {0x05,0x30,0x01,0x4c,0x00,0x53,0x00,0x14,0xe0,0x05,0x30,0x01,0x4c,0x00,0x53,0x00 } },
+{  16, 0xe5a0, 0, {0x04,0xc0,0x05,0x30,0x00,0x4c,0x00,0x03,0x00,0x14,0xc0,0x05,0x30,0x00,0x40,0x10 } },
+{  16, 0xe5b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x04,0x00,0x40,0x00,0x10,0x00 } },
+{  16, 0xe5c0, 0, {0x04,0x58,0x01,0x04,0x00,0x40,0x00,0x10,0x00,0x04,0x00,0x01,0x00,0x00,0x41,0x00 } },
+{  16, 0xe5d0, 0, {0x04,0x00,0x44,0x58,0x10,0x44,0x00,0x00,0x00,0x11,0x80,0x04,0x50,0x10,0x40,0x30 } },
+{  16, 0xe5e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x40,0x02,0x00,0x00,0x80,0x00 } },
+{  16, 0xe5f0, 0, {0x20,0x00,0x08,0x00,0x40,0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x00,0x02,0x00,0x00 } },
+{  16, 0xe600, 0, {0x84,0x00,0x00,0x00,0x08,0x40,0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x40,0x30 } },
+{  16, 0xe610, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc0,0x40,0x00,0x60,0x01,0x18,0x00 } },
+{  16, 0xe620, 0, {0x46,0x00,0x01,0x80,0x06,0x60,0x01,0x98,0x00,0x46,0x00,0x11,0x80,0x04,0x60,0x01 } },
+{  16, 0xe630, 0, {0x18,0x00,0x46,0x00,0x11,0x80,0x04,0x20,0x01,0x18,0x00,0x66,0x00,0x11,0x80,0x30 } },
+{  16, 0xe640, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x01,0x40,0x00,0x60,0x00,0x98,0x00 } },
+{  16, 0xe650, 0, {0x26,0x00,0x09,0x80,0x02,0x60,0x01,0x98,0x00,0x06,0x00,0x0c,0x80,0x02,0x60,0x00 } },
+{  16, 0xe660, 0, {0x18,0x00,0x06,0x00,0x01,0x80,0x02,0x60,0x00,0x98,0x80,0x06,0x00,0x01,0x82,0x00 } },
+{  16, 0xe670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x00,0x30,0x81,0x0c,0x20 } },
+{  16, 0xe680, 0, {0x43,0x08,0x10,0xc2,0x24,0x30,0x81,0x8c,0x20,0x03,0x08,0x10,0xc2,0x04,0x20,0x80 } },
+{  16, 0xe690, 0, {0x0c,0x20,0x03,0x08,0x18,0xc2,0x04,0x30,0x81,0x0c,0x20,0x43,0x08,0x18,0xc0,0x11 } },
+{  16, 0xe6a0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x30,0x00,0x0c,0x00 } },
+{  16, 0xe6b0, 0, {0x03,0x00,0x00,0xc0,0x40,0x30,0x00,0x0c,0x00,0x03,0x00,0x00,0x80,0x00,0x30,0x00 } },
+{  16, 0xe6c0, 0, {0x0c,0x00,0x03,0x20,0x00,0xc0,0x00,0x30,0x00,0x0c,0x00,0x03,0x20,0x00,0xc0,0x00 } },
+{  16, 0xe6d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x02,0x10,0x30,0x80,0x0c,0x20 } },
+{  16, 0xe6e0, 0, {0x03,0x08,0x00,0xc2,0x00,0x30,0x80,0x0c,0x20,0x03,0x08,0x00,0xc2,0x01,0x20,0x80 } },
+{  16, 0xe6f0, 0, {0x0c,0x20,0x03,0x2c,0x00,0xc2,0x00,0x30,0x80,0x0c,0x30,0x43,0x2c,0x00,0xc0,0x00 } },
+{  16, 0xe700, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x04,0x60,0x81,0x18,0x20 } },
+{  16, 0xe710, 0, {0x46,0x08,0x11,0x82,0x04,0x60,0x80,0x18,0x20,0x46,0x08,0x11,0x82,0x04,0x60,0x81 } },
+{  16, 0xe720, 0, {0x18,0x20,0x46,0x0c,0x11,0xc2,0x04,0x60,0x81,0x18,0x30,0x46,0x0c,0x11,0xc0,0x11 } },
+{  16, 0xe730, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x42,0x00,0x20,0x80,0x08,0x20 } },
+{  16, 0xe740, 0, {0x02,0x28,0x00,0x82,0x00,0x20,0x80,0x08,0x20,0x02,0x08,0x00,0x82,0x00,0x20,0x80 } },
+{  16, 0xe750, 0, {0x08,0x20,0x02,0x08,0x01,0x82,0x00,0x20,0x80,0x08,0x20,0x03,0x08,0x01,0x80,0x00 } },
+{  16, 0xe760, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x01,0x42,0x04,0x60,0x81,0x18,0x20 } },
+{  16, 0xe770, 0, {0x46,0x28,0x11,0x82,0x04,0x60,0x80,0x18,0x20,0x46,0x08,0x11,0x82,0x04,0x60,0x81 } },
+{  16, 0xe780, 0, {0x18,0x20,0x46,0x08,0x10,0x82,0x04,0x60,0x81,0x18,0x20,0x43,0x08,0x10,0x80,0x00 } },
+{  16, 0xe790, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x40,0x04,0x50,0x01,0x14,0x00 } },
+{  16, 0xe7a0, 0, {0x45,0x00,0x11,0x40,0x25,0x00,0x00,0x14,0x00,0x45,0x00,0x11,0x40,0x04,0x50,0x01 } },
+{  16, 0xe7b0, 0, {0x14,0x00,0x45,0x00,0x00,0x40,0x04,0x50,0x01,0x40,0x00,0x01,0x00,0x00,0x42,0x11 } },
+{  16, 0xe7c0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x06,0x00,0x41,0x80,0x10,0x60 } },
+{  16, 0xe7d0, 0, {0x04,0x18,0x01,0x06,0x00,0x41,0x80,0x10,0x60,0x04,0x18,0x01,0x06,0x00,0x41,0x80 } },
+{  16, 0xe7e0, 0, {0x10,0x60,0x04,0x18,0x01,0x06,0x00,0x41,0x80,0x10,0x60,0x04,0x18,0x01,0x00,0x00 } },
+{  16, 0xe7f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x02,0x05,0x00,0x80,0x40,0x21 } },
+{  16, 0xe800, 0, {0x10,0x08,0x04,0x00,0x01,0x00,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x00,0x80 } },
+{  16, 0xe810, 0, {0x40,0x20,0x50,0x08,0x14,0x02,0x11,0x00,0x84,0x40,0x20,0x10,0x08,0x14,0x00,0x00 } },
+{  16, 0xe820, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x46,0x01,0x51,0x80,0xd4,0x60 } },
+{  16, 0xe830, 0, {0x35,0x18,0x0d,0x46,0x03,0x51,0x80,0xd4,0x60,0x15,0x18,0x0d,0x46,0x03,0x51,0x80 } },
+{  16, 0xe840, 0, {0x54,0x60,0x15,0x18,0x0d,0x46,0x03,0x51,0x80,0xd4,0x60,0x35,0x18,0x0d,0x40,0x11 } },
+{  16, 0xe850, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x46,0x04,0x71,0x81,0x1c,0x60 } },
+{  16, 0xe860, 0, {0x45,0x18,0x11,0xd6,0x04,0x71,0x81,0x1c,0x60,0x67,0x18,0x11,0xc6,0x04,0x71,0x81 } },
+{  16, 0xe870, 0, {0x9c,0x60,0x47,0x18,0x11,0xc6,0x04,0x71,0x81,0x1c,0x60,0x67,0x18,0x11,0xc0,0x00 } },
+{  16, 0xe880, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x46,0x02,0x71,0x80,0x9c,0x60 } },
+{  16, 0xe890, 0, {0x27,0x18,0x09,0xc6,0x00,0x71,0x80,0x9c,0x60,0x67,0x18,0x09,0xc6,0x02,0x71,0x80 } },
+{  16, 0xe8a0, 0, {0x9c,0x61,0x27,0x18,0x01,0xc6,0x02,0x71,0x80,0x9c,0x60,0x07,0x18,0x01,0xc0,0x00 } },
+{  16, 0xe8b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x45,0x46,0x05,0x71,0x81,0x5c,0x60 } },
+{  16, 0xe8c0, 0, {0x57,0x18,0x55,0xd6,0x01,0x71,0x81,0x5c,0x60,0x57,0x18,0x15,0xc6,0x05,0x71,0x81 } },
+{  16, 0xe8d0, 0, {0x5c,0x60,0x57,0x18,0x18,0xc6,0x05,0x71,0x81,0x5c,0x60,0x43,0x18,0x18,0x82,0x11 } },
+{  16, 0xe8e0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x52,0x01,0x20,0x80,0x48,0x20 } },
+{  16, 0xe8f0, 0, {0x12,0x48,0x04,0x90,0x01,0x20,0x80,0x49,0x20,0x12,0x08,0x04,0x82,0x01,0x24,0x80 } },
+{  16, 0xe900, 0, {0x48,0x20,0x12,0x48,0x00,0x92,0x01,0x20,0x80,0x48,0x20,0x17,0x48,0x04,0x80,0x01 } },
+{  16, 0xe910, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x06,0x00,0x61,0x80,0x18,0x60 } },
+{  16, 0xe920, 0, {0x06,0x3c,0x01,0x86,0x00,0x61,0x80,0x18,0x60,0x46,0x18,0x01,0x86,0x00,0x61,0x80 } },
+{  16, 0xe930, 0, {0x18,0x60,0x06,0x18,0x01,0x86,0x00,0x61,0x80,0x18,0x60,0x46,0x18,0x01,0x80,0x01 } },
+{  16, 0xe940, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x60,0x04,0x78,0x01,0x1e,0x00 } },
+{  16, 0xe950, 0, {0x47,0x80,0x11,0xe0,0x24,0x78,0x01,0x1e,0x00,0x07,0x80,0x11,0xe0,0x04,0x78,0x01 } },
+{  16, 0xe960, 0, {0x1e,0x00,0x47,0x80,0x11,0xe0,0x04,0x38,0x01,0x1e,0x00,0x47,0x80,0x11,0xc0,0x11 } },
+{  16, 0xe970, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x12,0x00,0x60,0x80,0x18,0x20 } },
+{  16, 0xe980, 0, {0x06,0x48,0x01,0x92,0x00,0x60,0x80,0x19,0x20,0x06,0x08,0x01,0x82,0x00,0x64,0x80 } },
+{  16, 0xe990, 0, {0x18,0x20,0x06,0x48,0x01,0x93,0x00,0x20,0x80,0x18,0x20,0x06,0x48,0x01,0x80,0x00 } },
+{  16, 0xe9a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x42,0x04,0x20,0x81,0x08,0x20 } },
+{  16, 0xe9b0, 0, {0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x02,0x08,0x10,0x82,0x04,0x20,0x81 } },
+{  16, 0xe9c0, 0, {0x08,0x20,0x42,0x08,0x10,0x8a,0x04,0x60,0x81,0x08,0x20,0x42,0x08,0x10,0x80,0x00 } },
+{  16, 0xe9d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x04,0x40,0x81,0x10,0x20 } },
+{  16, 0xe9e0, 0, {0x44,0x08,0x11,0x02,0x04,0x40,0x81,0x10,0x20,0x04,0x08,0x11,0x02,0x04,0x40,0x81 } },
+{  16, 0xe9f0, 0, {0x10,0x21,0x44,0x08,0x01,0x02,0x04,0x50,0x81,0x10,0x20,0x04,0x08,0x01,0x00,0x11 } },
+{  16, 0xea00, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,0x50,0xc0,0x14,0x30 } },
+{  16, 0xea10, 0, {0x05,0x0c,0x01,0x43,0x00,0x50,0xc0,0x14,0x30,0x05,0x0c,0x01,0x43,0x00,0x50,0x80 } },
+{  16, 0xea20, 0, {0x14,0x30,0x05,0x08,0x01,0x4a,0x00,0x50,0xc0,0x14,0x30,0x05,0x08,0x01,0x40,0x00 } },
+{  16, 0xea30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x00,0x42,0x00,0x10,0x80 } },
+{  16, 0xea40, 0, {0x04,0x20,0x01,0x08,0x00,0x42,0x00,0x10,0x80,0x04,0x20,0x01,0x08,0x00,0x42,0x00 } },
+{  16, 0xea50, 0, {0x10,0x80,0x04,0x20,0x11,0x00,0x00,0x42,0x00,0x10,0x80,0x04,0x20,0x11,0x00,0x10 } },
+{  16, 0xea60, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x42,0x02,0x00,0x80,0x80,0x20 } },
+{  16, 0xea70, 0, {0x20,0x08,0x08,0x02,0x00,0x00,0x80,0x80,0x20,0x20,0x08,0x08,0x02,0x02,0x00,0x80 } },
+{  16, 0xea80, 0, {0x80,0x20,0x20,0x08,0x08,0x02,0x02,0x00,0x80,0x80,0x20,0x20,0x08,0x08,0x00,0x11 } },
+{  16, 0xea90, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x00,0x60,0x01,0x18,0x00 } },
+{  16, 0xeaa0, 0, {0x46,0x00,0x11,0x80,0x06,0x60,0x01,0x18,0x00,0x46,0x00,0x11,0x80,0x04,0x60,0x01 } },
+{  16, 0xeab0, 0, {0x18,0x00,0x46,0x00,0x11,0x80,0x04,0x60,0x01,0x18,0x00,0x66,0x00,0x11,0x80,0x10 } },
+{  16, 0xeac0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x02,0x64,0x00,0x98,0x00 } },
+{  16, 0xead0, 0, {0x26,0x00,0x09,0x90,0x06,0x60,0x01,0x98,0x00,0x26,0x40,0x09,0x80,0x02,0x60,0x00 } },
+{  16, 0xeae0, 0, {0x98,0x00,0x26,0x00,0x00,0x90,0x02,0x60,0x00,0x98,0x00,0x07,0x00,0x01,0x80,0x00 } },
+{  16, 0xeaf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x60,0x04,0x38,0x05,0x0e,0x00 } },
+{  16, 0xeb00, 0, {0x43,0x80,0x10,0xe0,0x44,0x38,0x01,0x0e,0x00,0x43,0x80,0x10,0xe0,0x04,0x38,0x01 } },
+{  16, 0xeb10, 0, {0x0e,0x00,0x43,0x80,0x18,0xa0,0x04,0x38,0x01,0x0e,0x00,0x46,0x80,0x18,0x80,0x11 } },
+{  16, 0xeb20, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,0x30,0x40,0x0c,0x10 } },
+{  16, 0xeb30, 0, {0x03,0x04,0x00,0xc5,0x00,0x30,0x40,0x0c,0x10,0x03,0x14,0x00,0xc1,0x00,0x30,0x40 } },
+{  16, 0xeb40, 0, {0x0c,0x10,0x03,0x04,0x00,0x87,0x40,0x30,0x40,0x0c,0x10,0x02,0x04,0x00,0x80,0x00 } },
+{  16, 0xeb50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x05,0x00,0x35,0x40,0x0c,0x50 } },
+{  16, 0xeb60, 0, {0x03,0x14,0x00,0xd5,0x04,0x31,0x41,0x0c,0x50,0x03,0x5c,0x00,0xc5,0x00,0x31,0x00 } },
+{  16, 0xeb70, 0, {0x0c,0x50,0x03,0x10,0x00,0x94,0x00,0x31,0x40,0x0c,0x50,0x43,0x10,0x00,0xc2,0x00 } },
+{  16, 0xeb80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x43,0x05,0x20,0xc1,0x18,0x30 } },
+{  16, 0xeb90, 0, {0x46,0x0c,0x11,0x97,0x00,0x60,0xc0,0x18,0x30,0x46,0x1c,0x11,0x83,0x04,0x60,0xc1 } },
+{  16, 0xeba0, 0, {0x18,0x30,0x52,0x0c,0x11,0x87,0x04,0x60,0xc1,0x18,0x30,0x46,0x0c,0x11,0x80,0x11 } },
+{  16, 0xebb0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x21,0x40,0x08,0x00 } },
+{  16, 0xebc0, 0, {0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x00,0x02,0x00,0x00,0x80,0x00,0x20,0x00 } },
+{  16, 0xebd0, 0, {0x08,0x00,0x02,0x00,0x00,0x80,0x00,0x20,0x00,0x08,0x00,0x02,0x00,0x00,0x80,0x00 } },
+{  16, 0xebe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x48,0x44,0x22,0x01,0x18,0x84 } },
+{  16, 0xebf0, 0, {0x46,0x21,0x11,0x98,0x00,0x62,0x10,0x18,0x84,0x44,0x20,0x11,0x88,0x44,0x62,0x11 } },
+{  16, 0xec00, 0, {0x18,0x84,0x42,0x21,0x11,0x80,0x44,0x62,0x11,0x18,0x84,0x46,0x21,0x11,0x80,0x00 } },
+{  16, 0xec10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x40,0x04,0x50,0x11,0x14,0x04 } },
+{  16, 0xec20, 0, {0x45,0x00,0x11,0x41,0x00,0x50,0x10,0x14,0x00,0x45,0x01,0x11,0x40,0x44,0x50,0x11 } },
+{  16, 0xec30, 0, {0x14,0x04,0x45,0x01,0x01,0x40,0x44,0x50,0x11,0x14,0x04,0x05,0x01,0x01,0x40,0x11 } },
+{  16, 0xec40, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x20,0x42,0x08,0x10,0x82 } },
+{  16, 0xec50, 0, {0x04,0x20,0x01,0x08,0x20,0x42,0x08,0x10,0x82,0x04,0x20,0x81,0x08,0x20,0x42,0x08 } },
+{  16, 0xec60, 0, {0x10,0x82,0x04,0x22,0x81,0x08,0x20,0x52,0x08,0x10,0x8a,0x04,0x22,0x81,0x00,0x00 } },
+{  16, 0xec70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0a,0x01,0x02,0x84,0x40,0xa1 } },
+{  16, 0xec80, 0, {0x10,0x28,0x00,0x0a,0x01,0x02,0x80,0x40,0xa0,0x10,0x28,0x04,0x0a,0x01,0x02,0x80 } },
+{  16, 0xec90, 0, {0x40,0xa0,0x10,0x2c,0x14,0x0a,0x00,0x02,0x80,0x40,0xb0,0x10,0x2c,0x14,0x00,0x00 } },
+{  16, 0xeca0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x45,0x4d,0x03,0x53,0x40,0xd4,0xd0 } },
+{  16, 0xecb0, 0, {0x35,0x30,0x0c,0x4d,0x03,0x53,0x40,0xd4,0xd0,0x35,0x34,0x0d,0x4d,0x03,0x53,0x40 } },
+{  16, 0xecc0, 0, {0xd4,0xd0,0x35,0x34,0x0d,0x4d,0x02,0x13,0x40,0xd4,0xd0,0x35,0x34,0x0d,0x40,0x11 } },
+{  16, 0xecd0, 0, {0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x08,0x04,0x72,0x01,0x1c,0x80 } },
+{  16, 0xece0, 0, {0x47,0x20,0x15,0xc8,0x04,0x72,0x01,0x1c,0x80,0x47,0x20,0x11,0xc8,0x04,0x72,0x11 } },
+{  16, 0xecf0, 0, {0x1c,0x80,0x47,0x26,0x11,0xc8,0x44,0x72,0x01,0x1c,0x90,0x67,0x26,0x11,0xc0,0x00 } },
+{  16, 0xed00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x08,0x40,0xc6,0x12,0x31 } },
+{  16, 0xed10, 0, {0x84,0x8c,0x01,0x03,0x08,0x48,0xc6,0x12,0x30,0x84,0x0c,0x61,0x23,0x18,0x48,0xc2 } },
+{  16, 0xed20, 0, {0x12,0x31,0x84,0x8c,0x01,0x03,0x08,0x48,0xc6,0x12,0x31,0x04,0x8c,0x01,0x00,0x00 } },
+{  16, 0xed30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x4f,0xff,0xd3,0xff } },
+{  16, 0xed40, 0, {0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff } },
+{  16, 0xed50, 0, {0xd3,0xff,0xf4,0xff,0xfd,0x3f,0xff,0x4f,0xff,0xd3,0xff,0xf4,0xff,0xfd,0x00,0x00 } },
+{  16, 0xed60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xed70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xed80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xed90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2d,0xfb,0x0f,0xb6,0xc2,0xcd } },
+{  16, 0xeda0, 0, {0xb0,0xb7,0xfd,0x3f,0xfb,0x0b,0x36,0xc2,0xdf,0xb0,0xfb,0x6c,0x2c,0xdb,0x0b,0x7e } },
+{  16, 0xedb0, 0, {0xc2,0xcd,0xb0,0xb7,0xfd,0x3f,0xfb,0x0b,0x36,0xc2,0xcd,0xf4,0xb7,0xfd,0x00,0x00 } },
+{  16, 0xedc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0xfc,0x4f,0xcf,0x13,0x33 } },
+{  16, 0xedd0, 0, {0xc4,0xcf,0xfd,0x3f,0xfc,0x4c,0xcf,0x13,0x3f,0xc4,0xfc,0xf1,0x33,0x3c,0x4c,0xff } },
+{  16, 0xede0, 0, {0x13,0x33,0xc4,0xcf,0xfd,0x3f,0xfc,0x4c,0xcf,0x13,0x33,0xf4,0xcf,0xfd,0x00,0x00 } },
+{  16, 0xedf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3b,0x7e,0x4e,0xdf,0x93,0xb7 } },
+{  16, 0xee00, 0, {0xe4,0xed,0xf9,0x3f,0xfe,0x4e,0xdf,0x93,0xb7,0xe4,0xed,0xf9,0x3b,0x7e,0x4e,0xc7 } },
+{  16, 0xee10, 0, {0x93,0xb7,0xe4,0xec,0x61,0x23,0x1e,0x4e,0xdf,0x93,0xb7,0x84,0xec,0x61,0x00,0x00 } },
+{  16, 0xee20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x24,0xa1,0x4a,0x24 } },
+{  16, 0xee30, 0, {0x63,0x01,0x14,0x02,0x44,0x00,0x81,0x0b,0x28,0x71,0x02,0x10,0x82,0x40,0x38,0x11 } },
+{  16, 0xee40, 0, {0x41,0x04,0x50,0x08,0x18,0x82,0x87,0x38,0x31,0xc3,0x2c,0x52,0x0a,0x10,0x00,0x00 } },
+{  16, 0xee50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x45,0x12,0x81,0x44,0x80 } },
+{  16, 0xee60, 0, {0x71,0x21,0x1c,0x0a,0x07,0x1a,0x81,0x02,0xa0,0x52,0x20,0x14,0x48,0x07,0x12,0x81 } },
+{  16, 0xee70, 0, {0xc6,0x80,0x60,0x20,0x08,0x88,0x47,0x02,0x01,0x4a,0x80,0x70,0x20,0x10,0x00,0x00 } },
+{  16, 0xee80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc5,0x2c,0x01,0x4a,0x00 } },
+{  16, 0xee90, 0, {0x52,0x09,0x1c,0x80,0x07,0x24,0x21,0x08,0x08,0x71,0x02,0x10,0x80,0x45,0x20,0xa1 } },
+{  16, 0xeea0, 0, {0x49,0x28,0x52,0x01,0x14,0xc0,0x45,0x00,0x91,0xc4,0x00,0x72,0x02,0x10,0x00,0x00 } },
+{  16, 0xeeb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x07,0x20,0x01,0xc1,0x00 } },
+{  16, 0xeec0, 0, {0x71,0x09,0x10,0x80,0x07,0x00,0x01,0x01,0x00,0x70,0x08,0x18,0x80,0x07,0x00,0x01 } },
+{  16, 0xeed0, 0, {0x89,0x20,0x52,0x01,0x0c,0x80,0x46,0x30,0x81,0x45,0x04,0x60,0x00,0x10,0x00,0x00 } },
+{  16, 0xeee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xc2,0x02,0x20,0x00,0x88 } },
+{  16, 0xeef0, 0, {0x20,0x22,0x00,0x08,0xc2,0x22,0x80,0x40,0x88,0x02,0x22,0x00,0x08,0x82,0x0a,0xa0 } },
+{  16, 0xef00, 0, {0x0c,0xa8,0x02,0x22,0x00,0x08,0x80,0x0a,0x00,0x80,0x8c,0x02,0x22,0x00,0x00,0x00 } },
+{  16, 0xef10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x43,0x00,0x00,0x40,0x20 } },
+{  16, 0xef20, 0, {0x30,0x08,0x04,0x40,0x41,0x30,0x10,0xc8,0x00,0x00,0x00,0x00,0x02,0x03,0x00,0x10 } },
+{  16, 0xef30, 0, {0xc0,0x00,0x11,0x08,0x00,0xc2,0x43,0x10,0x80,0xc0,0x20,0x01,0x08,0x00,0x02,0x00 } },
+{  16, 0xef40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0xc3,0x0a,0x20,0xc1,0x8c } },
+{  16, 0xef50, 0, {0x12,0x22,0x04,0x88,0x01,0x36,0x20,0xc3,0x08,0x12,0x28,0x04,0x08,0x01,0x04,0x00 } },
+{  16, 0xef60, 0, {0x4a,0xa8,0x22,0x01,0x04,0xc8,0x41,0x26,0x30,0xc0,0x88,0x02,0x21,0x00,0x02,0x00 } },
+{  16, 0xef70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x0a,0x10,0xc1,0x80 } },
+{  16, 0xef80, 0, {0x32,0x21,0x0c,0x88,0x43,0x02,0x80,0x44,0x80,0x12,0x29,0x04,0x08,0x42,0x0a,0x90 } },
+{  16, 0xef90, 0, {0x8a,0x80,0x00,0x20,0x04,0x48,0x03,0x0a,0x10,0x82,0x80,0x00,0x20,0x00,0x02,0x00 } },
+{  16, 0xefa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x87,0x02,0xa1,0x80,0xac } },
+{  16, 0xefb0, 0, {0x43,0x29,0x14,0x8a,0x84,0x02,0xa1,0x00,0xac,0x41,0x20,0x10,0x08,0x06,0x26,0x31 } },
+{  16, 0xefc0, 0, {0x80,0xa4,0x60,0x20,0x14,0x4a,0x44,0x32,0x81,0x81,0xac,0x60,0x2a,0x18,0x02,0x00 } },
+{  16, 0xefd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x07,0x22,0x01,0xc5,0x80 } },
+{  16, 0xefe0, 0, {0x73,0x21,0x1c,0xc8,0x07,0x2a,0x01,0x0c,0x80,0x72,0x20,0x10,0x48,0x47,0x26,0x11 } },
+{  16, 0xeff0, 0, {0xc5,0x80,0x73,0x20,0x1c,0x88,0x07,0x2a,0x11,0x49,0x80,0x70,0x20,0x14,0x02,0x00 } },
+{  16, 0xf000, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x45,0x10,0x31,0xc9,0x0c } },
+{  16, 0xf010, 0, {0x73,0x02,0x1c,0xc0,0x47,0x04,0x01,0x0a,0x0c,0x51,0x0a,0x10,0x82,0x47,0x20,0x31 } },
+{  16, 0xf020, 0, {0xc8,0x00,0x72,0x02,0x1c,0x40,0x05,0x30,0x11,0xc4,0x00,0x72,0x01,0x18,0x02,0x00 } },
+{  16, 0xf030, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x10,0x06,0x24,0x01,0x45,0x04 } },
+{  16, 0xf040, 0, {0x51,0x81,0x18,0x90,0x47,0x14,0x01,0x04,0x04,0x71,0x88,0x10,0x12,0x05,0x34,0x01 } },
+{  16, 0xf050, 0, {0x44,0x04,0x51,0x40,0x18,0xd0,0x07,0x38,0x01,0xc4,0x04,0x52,0x01,0x14,0xc2,0x04 } },
+{  16, 0xf060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x00,0x21,0x89,0x0c } },
+{  16, 0xf070, 0, {0x60,0x01,0x1c,0xd0,0x45,0x24,0x01,0xc1,0x0c,0x42,0x01,0x00,0x00,0xc5,0x20,0x31 } },
+{  16, 0xf080, 0, {0x41,0x08,0x40,0x00,0x18,0x80,0x45,0x00,0x21,0x41,0x0c,0x70,0x42,0x1c,0xc2,0x00 } },
+{  16, 0xf090, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01,0x1c,0x80,0xc4,0x20 } },
+{  16, 0xf0a0, 0, {0x31,0x08,0x10,0x42,0x42,0x08,0x80,0xc6,0x20,0x31,0x09,0x00,0x20,0x03,0x1c,0x90 } },
+{  16, 0xf0b0, 0, {0xc4,0x20,0x01,0x49,0x0c,0x42,0x43,0x10,0x80,0x44,0x20,0x31,0x08,0x10,0x00,0x00 } },
+{  16, 0xf0c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x83,0x20,0x30,0x48,0x0c } },
+{  16, 0xf0d0, 0, {0x32,0x40,0x10,0x90,0x81,0x24,0x20,0xc8,0x04,0x32,0x40,0x10,0x20,0xc3,0x20,0x80 } },
+{  16, 0xf0e0, 0, {0xc8,0x00,0x02,0x4a,0x0c,0xa0,0x01,0x24,0x10,0xc8,0x08,0x32,0x41,0x10,0x00,0x00 } },
+{  16, 0xf0f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x90,0x03,0x00,0x00,0xc9,0x04 } },
+{  16, 0xf100, 0, {0x30,0x40,0x00,0x90,0x00,0x20,0x00,0x80,0x00,0x10,0x40,0x10,0x00,0x40,0x20,0x10 } },
+{  16, 0xf110, 0, {0xc2,0x00,0x00,0x80,0x08,0x20,0x43,0x08,0x10,0x81,0x00,0x32,0x40,0x0c,0xc0,0x04 } },
+{  16, 0xf120, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x40,0x00,0x00,0x00 } },
+{  16, 0xf130, 0, {0x10,0x00,0x00,0xf0,0x10,0x20,0x00,0x00,0x00,0x10,0x00,0x00,0xf0,0x10,0x80,0x40 } },
+{  16, 0xf140, 0, {0x00,0x00,0x00,0x40,0x00,0xf0,0x10,0x90,0x80,0x00,0x00,0x00,0x00,0x00,0xc0,0x00 } },
+{  16, 0xf150, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x10,0x80,0x90,0x40,0x00,0x00 } },
+{  16, 0xf160, 0, {0x00,0x80,0x10,0x90,0xa0,0x90,0x00,0x00,0x00,0x00,0x00,0x10,0x90,0x80,0x80,0x00 } },
+{  16, 0xf170, 0, {0x00,0x00,0x00,0x00,0x10,0x90,0x80,0x90,0x00,0x00,0x00,0x00,0x40,0x10,0x8f,0x0f } },
+{  16, 0xf180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xc6,0xba,0x06,0xc0,0x1c } },
+{  16, 0xf190, 0, {0x49,0x28,0x61,0x14,0x2b,0x1c,0x0e,0x40,0x3f,0xd9,0xbf,0xd9,0xaa,0xbc,0x1a,0x5f } },
+{  16, 0xf1a0, 0, {0x00,0x10,0xa6,0x50,0x3b,0x61,0xb3,0x25,0xbc,0x40,0x19,0xbf,0xff,0xe9,0x80,0x00 } },
+{  16, 0xf1b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x92,0x14,0x94,0x80,0x0c } },
+{  16, 0xf1c0, 0, {0x07,0x3f,0x2b,0x94,0x86,0x14,0x84,0x80,0x28,0x00,0x00,0x49,0x14,0x04,0x86,0x12 } },
+{  16, 0xf1d0, 0, {0x80,0x00,0x41,0x27,0x34,0xd0,0x90,0x84,0x92,0x00,0x2d,0x8a,0x21,0x1e,0x80,0x00 } },
+{  16, 0xf1e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xa2 } },
+{  16, 0xf1f0, 0, {0xb1,0x01,0x01,0x00,0x00,0x00,0x00,0x08,0x84,0xb1,0x78,0x28,0x00,0x00,0x00,0x00 } },
+{  16, 0xf200, 0, {0x08,0xb1,0x32,0x14,0x14,0x00,0x00,0x00,0x00,0x08,0xa8,0x23,0x54,0x21,0x40,0x00 } },
+{  16, 0xf210, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf220, 0, {0x00,0x00,0x00,0x2f,0xff,0xfe,0xf7,0xc0,0x00,0x00,0x00,0x00,0x2f,0xd7,0xfe,0xef } },
+{  16, 0xf230, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0x7f,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf240, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf250, 0, {0x00,0x00,0x00,0x0f,0xef,0x77,0xff,0xc0,0x00,0x00,0x00,0x00,0x3e,0xff,0xfe,0xef } },
+{  16, 0xf260, 0, {0x40,0x00,0x00,0x00,0x00,0x3f,0xff,0xbf,0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf270, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf280, 0, {0x00,0x00,0x00,0x3f,0xff,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff } },
+{  16, 0xf290, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0x7f,0x2f,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf2a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf2b0, 0, {0x00,0x00,0x00,0x1f,0xff,0xff,0xef,0xc0,0x00,0x00,0x00,0x00,0x1f,0xef,0xef,0xef } },
+{  16, 0xf2c0, 0, {0xc0,0x00,0x00,0x00,0x00,0x2f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf2d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf2e0, 0, {0x00,0x00,0x00,0x3f,0xff,0xef,0xff,0xc0,0x00,0x00,0x00,0x00,0x2f,0xaf,0xdf,0xff } },
+{  16, 0xf2f0, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xef,0xff,0xf7,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf300, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf310, 0, {0x00,0x00,0x00,0x3f,0xdf,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff } },
+{  16, 0xf320, 0, {0xc0,0x00,0x00,0x00,0x00,0x1f,0xff,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf330, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xc4,0x24,0xa1,0x00,0x2c } },
+{  16, 0xf340, 0, {0x52,0x0b,0x18,0xc2,0x86,0x2c,0xa1,0x80,0x38,0x62,0x0a,0x08,0x40,0xc4,0x2c,0xa1 } },
+{  16, 0xf350, 0, {0x08,0x28,0x42,0x0b,0x14,0x00,0x85,0x14,0xa1,0x08,0x28,0x43,0x0a,0x10,0x00,0x00 } },
+{  16, 0xf360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x12,0x01,0x03,0x80 } },
+{  16, 0xf370, 0, {0x61,0x20,0x10,0x08,0x07,0x12,0x41,0x42,0x80,0x70,0x20,0x1c,0x08,0x04,0x1a,0x01 } },
+{  16, 0xf380, 0, {0x84,0x81,0x40,0x20,0x18,0x08,0x46,0x36,0x81,0x05,0x80,0x63,0x20,0x10,0x00,0x01 } },
+{  16, 0xf390, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x24,0x21,0x00,0x0c } },
+{  16, 0xf3a0, 0, {0x52,0x02,0x14,0x00,0x87,0x28,0x21,0x81,0x08,0x72,0x06,0x1c,0x82,0x84,0x20,0x21 } },
+{  16, 0xf3b0, 0, {0x48,0x18,0x42,0x03,0x54,0x80,0x45,0x30,0x25,0x4a,0x18,0x53,0x02,0x10,0x00,0x01 } },
+{  16, 0xf3c0, 0, {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x22,0x01,0x01,0x80 } },
+{  16, 0xf3d0, 0, {0x42,0x20,0x18,0xc8,0x44,0x22,0x01,0x80,0x84,0x42,0x20,0x1c,0x88,0x04,0x22,0x01 } },
+{  16, 0xf3e0, 0, {0x00,0x80,0x40,0x20,0x10,0x88,0x44,0x36,0x01,0x40,0x80,0x41,0x00,0x10,0x00,0x00 } },
+{  16, 0xf3f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x08,0x20,0x00,0x0c } },
+{  16, 0xf400, 0, {0x22,0x03,0x04,0x40,0x81,0x00,0x20,0x84,0x08,0x03,0x00,0x00,0x80,0xc2,0x00,0x20 } },
+{  16, 0xf410, 0, {0xc4,0x08,0x00,0x03,0x08,0x88,0x82,0x16,0xa0,0x40,0x88,0x32,0x22,0x80,0x00,0x00 } },
+{  16, 0xf420, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x01,0x00,0x80,0x04,0x20 } },
+{  16, 0xf430, 0, {0x10,0x08,0x0c,0xc2,0x12,0x10,0x84,0xc8,0x22,0x12,0x08,0x04,0x02,0x03,0x00,0x88 } },
+{  16, 0xf440, 0, {0x00,0x21,0x00,0x0c,0x0c,0x40,0x41,0x30,0x00,0x84,0x20,0x10,0x08,0x00,0x02,0x00 } },
+{  16, 0xf450, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x82,0x06,0x20,0x08,0x8c } },
+{  16, 0xf460, 0, {0x32,0x22,0x0c,0x88,0x81,0x26,0x20,0x4d,0x88,0x23,0x22,0x80,0x88,0x83,0x06,0x20 } },
+{  16, 0xf470, 0, {0x08,0x88,0x00,0x23,0x04,0x8a,0x81,0x36,0x20,0x4b,0x88,0x32,0x22,0x00,0x00,0x00 } },
+{  16, 0xf480, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x02,0x02,0x00,0x09,0x80 } },
+{  16, 0xf490, 0, {0x32,0x20,0x04,0x88,0x60,0x22,0x00,0x89,0x84,0x00,0x20,0x08,0x98,0x00,0x02,0x00 } },
+{  16, 0xf4a0, 0, {0x00,0x80,0x00,0x20,0x00,0x08,0x02,0x3a,0x80,0x48,0x80,0x30,0x20,0x00,0x02,0x00 } },
+{  16, 0xf4b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0a,0xc4,0x1a,0xa1,0x80,0xa8 } },
+{  16, 0xf4c0, 0, {0x41,0x2a,0x10,0xca,0xc7,0x1a,0xa1,0x04,0xad,0x71,0x2a,0x18,0x4a,0xd4,0x06,0xb1 } },
+{  16, 0xf4d0, 0, {0x00,0xa8,0x71,0x2a,0x10,0x08,0x84,0x26,0x29,0x06,0xac,0x52,0x2a,0x10,0x02,0x00 } },
+{  16, 0xf4e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x04,0x2a,0x01,0x41,0x80 } },
+{  16, 0xf4f0, 0, {0x42,0x20,0x1c,0x00,0x04,0x0a,0x01,0x09,0x84,0x51,0x20,0x1c,0x88,0x44,0x02,0x01 } },
+{  16, 0xf500, 0, {0x08,0x80,0x40,0x20,0x10,0x4a,0x47,0x02,0x01,0x48,0x80,0x63,0x20,0x10,0x02,0x00 } },
+{  16, 0xf510, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0xc4,0x10,0x21,0x81,0x0c } },
+{  16, 0xf520, 0, {0x41,0x02,0x0c,0x00,0xc0,0x20,0x61,0x0d,0x0e,0x72,0x02,0x1c,0x40,0xc4,0x08,0x31 } },
+{  16, 0xf530, 0, {0x04,0x18,0x42,0x02,0x10,0x80,0x87,0x20,0xb1,0xc4,0x0c,0x53,0x02,0x10,0x00,0x00 } },
+{  16, 0xf540, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x20,0x07,0x24,0x01,0xcc,0x00 } },
+{  16, 0xf550, 0, {0x72,0x40,0x14,0x00,0x04,0x24,0x01,0x08,0x00,0x73,0x41,0x10,0xc0,0x07,0x30,0x11 } },
+{  16, 0xf560, 0, {0xcc,0x00,0x71,0x01,0x10,0x02,0x04,0x20,0x81,0x46,0x10,0x42,0x40,0x10,0x02,0x04 } },
+{  16, 0xf570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0xc5,0x10,0x21,0x00,0x08 } },
+{  16, 0xf580, 0, {0x62,0x02,0x1c,0x90,0xc5,0x24,0x21,0x00,0x0c,0x70,0x82,0x1c,0x10,0xc4,0x20,0x31 } },
+{  16, 0xf590, 0, {0x88,0x02,0x40,0x06,0x1c,0x00,0x85,0x00,0xa1,0x00,0x0c,0x40,0x42,0x00,0x02,0x00 } },
+{  16, 0xf5a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x05,0x14,0x80,0x01,0x20 } },
+{  16, 0xf5b0, 0, {0x30,0x08,0x0c,0x42,0x06,0x00,0x80,0x01,0x24,0x51,0x08,0x0c,0x02,0x41,0x00,0x80 } },
+{  16, 0xf5c0, 0, {0x4c,0x20,0x00,0x08,0x0c,0x30,0x42,0x04,0x00,0x04,0x20,0x00,0x08,0x00,0x00,0x00 } },
+{  16, 0xf5d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xc6,0x24,0x20,0x00,0x0c } },
+{  16, 0xf5e0, 0, {0x32,0xc2,0x04,0x80,0xc7,0x30,0x20,0x00,0x0c,0x53,0xc2,0x04,0x10,0xc2,0x28,0x70 } },
+{  16, 0xf5f0, 0, {0x0c,0x09,0x02,0x02,0x4c,0x80,0x81,0x04,0x30,0x09,0x0c,0x02,0x42,0x10,0x00,0x00 } },
+{  16, 0xf600, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x80,0x01,0x38,0x00,0x02,0x00 } },
+{  16, 0xf610, 0, {0x12,0x40,0x0c,0x20,0x07,0x34,0x04,0x02,0x00,0x63,0x01,0x08,0x10,0x00,0x24,0x10 } },
+{  16, 0xf620, 0, {0x04,0x00,0x02,0x01,0x04,0x82,0x01,0x08,0x80,0x09,0x10,0x02,0x40,0x10,0x00,0x04 } },
+{  16, 0xf630, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x20,0x10,0x80,0x00,0x00 } },
+{  16, 0xf640, 0, {0x20,0x80,0x00,0xf0,0x20,0x10,0x80,0x00,0x00,0x20,0x80,0x00,0xd0,0x80,0x00,0x00 } },
+{  16, 0xf650, 0, {0x40,0x00,0x00,0x00,0x00,0x30,0x10,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0xcc,0x40 } },
+{  16, 0xf660, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x10,0x80,0x80,0x00,0x00,0x00 } },
+{  16, 0xf670, 0, {0x00,0x00,0x10,0x90,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x10,0x90,0x80,0x00,0x90 } },
+{  16, 0xf680, 0, {0x80,0x00,0x10,0x00,0x00,0x10,0xa0,0x80,0x00,0x00,0x00,0x20,0x00,0x10,0x8c,0x08 } },
+{  16, 0xf690, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x1a,0xbe,0x17,0x80,0x00 } },
+{  16, 0xf6a0, 0, {0x3e,0x40,0x26,0x6f,0xba,0xe3,0x24,0x80,0x00,0x16,0x59,0xbd,0x82,0x81,0x82,0xd8 } },
+{  16, 0xf6b0, 0, {0x80,0x00,0x00,0x19,0x99,0x86,0x80,0x64,0x80,0xc0,0x3f,0xd9,0x99,0x80,0x00,0x01 } },
+{  16, 0xf6c0, 0, {0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x16,0x02,0x94,0x00,0x16 } },
+{  16, 0xf6d0, 0, {0xc0,0x16,0x94,0x82,0x90,0x16,0x10,0x80,0x21,0x18,0x28,0x28,0x02,0x0a,0x02,0x08 } },
+{  16, 0xf6e0, 0, {0x80,0x00,0x00,0x00,0x00,0x02,0x82,0x80,0x14,0x00,0x01,0x14,0x11,0xa0,0x40,0x00 } },
+{  16, 0xf6f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x84 } },
+{  16, 0xf700, 0, {0x02,0x84,0xa8,0x80,0x00,0x00,0x00,0x08,0x91,0x22,0x84,0x41,0xa2,0x08,0x24,0x01 } },
+{  16, 0xf710, 0, {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x84,0x01,0x44,0x01,0x00,0x00 } },
+{  16, 0xf720, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf730, 0, {0x00,0x00,0x00,0x3e,0xf7,0xff,0xf7,0xc0,0x00,0x00,0x00,0x00,0x2f,0xe7,0xb7,0xff } },
+{  16, 0xf740, 0, {0xc0,0x00,0x00,0x00,0x00,0x2f,0xfe,0x7f,0xf7,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf750, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf760, 0, {0x00,0x00,0x00,0x36,0xbf,0xfe,0xdf,0xc0,0x00,0x00,0x00,0x00,0x0f,0xf7,0xdf,0xff } },
+{  16, 0xf770, 0, {0xc0,0x00,0x00,0x00,0x00,0x3d,0xb7,0xb7,0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf780, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf790, 0, {0x00,0x00,0x00,0x1f,0xdf,0xdf,0xff,0xc0,0x00,0x00,0x00,0x00,0x0f,0xdf,0xdf,0xff } },
+{  16, 0xf7a0, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xef,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf7b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf7c0, 0, {0x00,0x00,0x00,0x3f,0xbf,0x7f,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0x7f,0xf7 } },
+{  16, 0xf7d0, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xdf,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf7e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf7f0, 0, {0x00,0x00,0x00,0x3f,0x7e,0xff,0xff,0x40,0x00,0x00,0x00,0x00,0x3f,0xfe,0xff,0xff } },
+{  16, 0xf800, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf810, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00 } },
+{  16, 0xf820, 0, {0x00,0x00,0x00,0x37,0xff,0x6f,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff } },
+{  16, 0xf830, 0, {0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf840, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf850, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf860, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf870, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x20,0x01,0x02,0x00,0x00,0x00 } },
+{  16, 0xf880, 0, {0x30,0x00,0x43,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf890, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf8a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf8b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf8c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf8d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf8e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf8f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x00,0x00,0x00,0x00,0x30 } },
+{  16, 0xf900, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf910, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf920, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf930, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf940, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf950, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x00 } },
+{  16, 0xf960, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf970, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf980, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf990, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf9a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf9b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x30,0xc0,0x30 } },
+{  16, 0xf9c0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf9d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf9e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xf9f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x0f } },
+{  16, 0xfa20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x00,0x00,0x00,0x00,0x3f } },
+{  16, 0xfa80, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfa90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfaa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfab0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfac0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfad0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x30,0xc0,0x30,0xc0,0x0f } },
+{  16, 0xfae0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfaf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x6b,0x00,0xc0,0x00,0xcf,0x2c } },
+{  16, 0xfb40, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfb90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x00 } },
+{  16, 0xfba0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfbb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfbc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfbd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfbe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfbf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x0f,0x00,0x0f,0x00,0x30 } },
+{  16, 0xfc00, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x3f,0xc0,0x00 } },
+{  16, 0xfc60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfc90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfca0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfcb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x3f,0xc0,0x3f,0xc0,0x30 } },
+{  16, 0xfcc0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfcd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfcf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x0f,0x00,0x0f } },
+{  16, 0xfd20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x0f,0x00,0x0f,0x00,0x3f } },
+{  16, 0xfd80, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfd90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfda0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfdb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfdc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfdd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x3f,0xc0,0x3f,0xc0,0x0f } },
+{  16, 0xfde0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfdf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x33,0x5d,0x80,0xc0,0x00,0xfd,0xac } },
+{  16, 0xfe40, 0, {0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfe90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfea0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfeb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfec0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfed0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x00,0x00,0x00,0x00,0x30 } },
+{  16, 0xff00, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x00 } },
+{  16, 0xff60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xff90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xffa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xffb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x30,0xc0,0x30,0xc0,0x30 } },
+{  16, 0xffc0, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xffd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xffe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0xfff0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8010, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8020, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x0f } },
+{  16, 0x8030, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8040, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8050, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8080, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x00,0x00,0x00,0x00,0x3f } },
+{  16, 0x8090, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x80e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x30,0xc0,0x30,0xc0,0x0f } },
+{  16, 0x80f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8110, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8120, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8140, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x74,0xc0,0xc0,0x00,0xf0,0xec } },
+{  16, 0x8150, 0, {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8160, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8170, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8180, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8190, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x81a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x00 } },
+{  16, 0x81b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x81c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x81d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x81e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x81f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8200, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xc0,0x0f,0x00,0x0f,0x00,0x30 } },
+{  16, 0x8210, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8220, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8230, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8240, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8250, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8260, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x3f,0xc0,0x00 } },
+{  16, 0x8270, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8280, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8290, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x82a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x82b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x82c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x86,0x10,0x80,0x30,0x82,0x3d } },
+{  16, 0x82d0, 0, {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x82e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x82f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8300, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8310, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8320, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x0f,0x00,0x0f,0x00,0x0f } },
+{  16, 0x8330, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8340, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8350, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8360, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8370, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8380, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xc0,0x0f,0x00,0x0f,0x00,0x3f } },
+{  16, 0x8390, 0, {0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x83a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x83b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x83c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x83d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x83e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x3f,0xc0,0x3f,0xc0,0x0f } },
+{  16, 0x83f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8400, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8410, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8420, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8430, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8440, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x65,0x25,0xe4,0x80,0x00,0xb0,0x88 } },
+{  16, 0x8450, 0, {0xab,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8460, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8470, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8480, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8490, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x84a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x84b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x84c0, 0, {0x00,0x00,0x00,0x00,0x30,0x00,0x20,0x01,0x02,0x02,0x00,0x00,0x30,0x00,0x43,0x00 } },
+{  16, 0x84d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x84e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x84f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8500, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8510, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8520, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8530, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8540, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8550, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8560, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8570, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8580, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8590, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x85a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x85b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x85c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x85d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x85e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x85f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8600, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8610, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8620, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8630, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8640, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8650, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8660, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8670, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8680, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8690, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x86a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x86b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x86c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x86d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x86e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x86f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8700, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8710, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8720, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8730, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8740, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8750, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8760, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8770, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8780, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8790, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x87a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x87b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x87c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x87d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x87e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x87f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8800, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8810, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8820, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8830, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8840, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8850, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8860, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8870, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8880, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8890, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x88a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x88b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x88c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x88d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x88e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x88f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8900, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8910, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8920, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8930, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8940, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8950, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8960, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8970, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8980, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8990, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x89a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x89b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x89c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x89d0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x89e0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x89f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8a90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8aa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ab0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ac0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ad0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ae0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8af0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8b90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ba0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8bb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8bc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8bd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8be0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8bf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8c90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ca0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8cb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8cc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8cd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ce0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8cf0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8d90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8da0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8db0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8dc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8dd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8de0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8df0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8e90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ea0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8eb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ec0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ed0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ee0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ef0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f00, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f10, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f20, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f30, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f40, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f50, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f60, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f70, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f80, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8f90, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8fa0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8fb0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8fc0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8fd0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8fe0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x8ff0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9000, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9010, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9020, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9030, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9040, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9050, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9060, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9070, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9080, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9090, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x90a0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x90b0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x90c0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x90d0, 0, {0x30,0x00,0x00,0x01,0x00,0x00,0x44,0x72,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x03 } },
+{  16, 0x90e0, 0, {0x30,0x00,0x40,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x90f0, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9100, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  16, 0x9110, 0, {0x00,0x00,0x00,0x00,0x30,0x00,0x80,0x01,0x00,0x00,0x00,0x05,0x30,0x00,0xa0,0x01 } },
+{  16, 0x9120, 0, {0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x01,0x00,0x00,0xe1,0x5a,0x00,0x00,0x00,0x00 } },
+{  12, 0x9130, 0, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+{  0 , 0x0000, 1, {0 }}
+};
+// VERSION=1.1.1.131
+// DATE=2001dec06
+// PRODUCT=EMI 2|6
+/*
+ * This firmware is for the Emagic EMI 2|6 Audio Interface
+ *
+ * The firmware contained herein is Copyright (c) 1999-2002 Emagic
+ * as an unpublished work. This notice does not imply unrestricted
+ * or public access to this firmware which is a trade secret of Emagic,
+ * and which may not be reproduced, used, sold or transferred to
+ * any third party without Emagic's written consent. All Rights Reserved.
+ *
+ * This firmware may not be modified and may only be used with the
+ * Emagic EMI 2|6 Audio Interface. Distribution and/or Modification of
+ * any driver which includes this firmware, in whole or in part,
+ * requires the inclusion of this statement.
+ */
+INTEL_HEX_RECORD g_Firmware[] = {
+{   3,0x0000,0,{0x02,0x43,0x56} },
+{   3,0x0003,0,{0x02,0x4b,0xcd} },
+{   3,0x000b,0,{0x02,0x4b,0xd2} },
+{   3,0x0013,0,{0x02,0x4b,0x92} },
+{   3,0x001b,0,{0x02,0x4b,0xd5} },
+{   3,0x0023,0,{0x02,0x1b,0x39} },
+{   3,0x002b,0,{0x02,0x43,0xe2} },
+{   3,0x0033,0,{0x02,0x3f,0xf3} },
+{   3,0x003b,0,{0x02,0x4b,0xc0} },
+{   3,0x0043,0,{0x02,0x47,0x00} },
+{   3,0x004b,0,{0x02,0x3f,0xfc} },
+{   3,0x0053,0,{0x02,0x37,0xfa} },
+{   3,0x005b,0,{0x02,0x4b,0xc7} },
+{   3,0x0063,0,{0x02,0x46,0xfc} },
+{  16,0x0500,0,{0x12,0x01,0x10,0x01,0x00,0x00,0x00,0x40,0x6a,0x08,0x01,0x01,0x00,0x01,0x01,0x02} },
+{  16,0x0510,0,{0x00,0x01,0x09,0x02,0xb8,0x01,0x03,0x01,0x00,0x80,0xa0,0x09,0x04,0x00,0x00,0x00} },
+{  16,0x0520,0,{0x01,0x01,0x00,0x00,0x0a,0x24,0x01,0x00,0x01,0x56,0x00,0x02,0x01,0x02,0x0c,0x24} },
+{  16,0x0530,0,{0x02,0x01,0x01,0x01,0x00,0x06,0x00,0x00,0x00,0x00,0x15,0x24,0x06,0x05,0x01,0x02} },
+{  16,0x0540,0,{0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09} },
+{  16,0x0550,0,{0x24,0x03,0x02,0x04,0x03,0x00,0x05,0x00,0x0c,0x24,0x02,0x03,0x01,0x02,0x00,0x02} },
+{  16,0x0560,0,{0x00,0x00,0x00,0x00,0x0d,0x24,0x06,0x06,0x03,0x02,0x03,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x0570,0,{0x00,0x09,0x24,0x03,0x04,0x01,0x01,0x00,0x06,0x00,0x09,0x04,0x01,0x00,0x00,0x01} },
+{  16,0x0580,0,{0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x02,0x01,0x02,0x00,0x00,0x07,0x24,0x01,0x01} },
+{  16,0x0590,0,{0x00,0x01,0x00,0x11,0x24,0x02,0x01,0x02,0x02,0x10,0x03,0x44,0xac,0x00,0x80,0xbb} },
+{  16,0x05a0,0,{0x00,0x00,0x77,0x01,0x09,0x05,0x0a,0x05,0x84,0x01,0x01,0x00,0x8f,0x07,0x25,0x01} },
+{  16,0x05b0,0,{0x01,0x00,0x00,0x00,0x09,0x05,0x8f,0x01,0x03,0x00,0x01,0x06,0x00,0x09,0x04,0x01} },
+{  16,0x05c0,0,{0x02,0x02,0x01,0x02,0x00,0x00,0x07,0x24,0x01,0x01,0x00,0x01,0x00,0x0e,0x24,0x02} },
+{  16,0x05d0,0,{0x01,0x06,0x02,0x10,0x02,0x44,0xac,0x00,0x80,0xbb,0x00,0x09,0x05,0x0a,0x05,0x4c} },
+{  16,0x05e0,0,{0x02,0x01,0x00,0x8f,0x07,0x25,0x01,0x01,0x00,0x00,0x00,0x09,0x05,0x8f,0x01,0x03} },
+{  16,0x05f0,0,{0x00,0x01,0x06,0x00,0x09,0x04,0x01,0x03,0x02,0x01,0x02,0x00,0x00,0x07,0x24,0x01} },
+{  16,0x0600,0,{0x01,0x00,0x01,0x00,0x0e,0x24,0x02,0x01,0x06,0x03,0x18,0x02,0x44,0xac,0x00,0x80} },
+{  16,0x0610,0,{0xbb,0x00,0x09,0x05,0x0a,0x05,0x72,0x03,0x01,0x00,0x8f,0x07,0x25,0x01,0x01,0x00} },
+{  16,0x0620,0,{0x00,0x00,0x09,0x05,0x8f,0x01,0x03,0x00,0x01,0x06,0x00,0x09,0x04,0x01,0x04,0x02} },
+{  16,0x0630,0,{0x01,0x02,0x00,0x00,0x07,0x24,0x01,0x01,0x00,0x01,0x00,0x0b,0x24,0x02,0x01,0x02} },
+{  16,0x0640,0,{0x03,0x18,0x01,0x00,0x77,0x01,0x09,0x05,0x0a,0x05,0x46,0x02,0x01,0x00,0x8f,0x07} },
+{  16,0x0650,0,{0x25,0x01,0x01,0x00,0x00,0x00,0x09,0x05,0x8f,0x01,0x03,0x00,0x01,0x06,0x00,0x09} },
+{  16,0x0660,0,{0x04,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0x09,0x04,0x02,0x01,0x01,0x01,0x02,0x00} },
+{  16,0x0670,0,{0x00,0x07,0x24,0x01,0x04,0x00,0x01,0x00,0x11,0x24,0x02,0x01,0x02,0x02,0x10,0x03} },
+{  16,0x0680,0,{0x44,0xac,0x00,0x80,0xbb,0x00,0x00,0x77,0x01,0x09,0x05,0x8c,0x05,0x84,0x01,0x01} },
+{  16,0x0690,0,{0x00,0x00,0x07,0x25,0x01,0x01,0x02,0x00,0x00,0x09,0x04,0x02,0x02,0x01,0x01,0x02} },
+{  16,0x06a0,0,{0x00,0x00,0x07,0x24,0x01,0x04,0x00,0x01,0x00,0x11,0x24,0x02,0x01,0x02,0x03,0x18} },
+{  16,0x06b0,0,{0x03,0x44,0xac,0x00,0x80,0xbb,0x00,0x00,0x77,0x01,0x09,0x05,0x8c,0x05,0x46,0x02} },
+{  16,0x06c0,0,{0x01,0x00,0x00,0x07,0x25,0x01,0x01,0x02,0x00,0x00,0x05,0x0c,0x09,0x01,0xa1,0x01} },
+{  16,0x06d0,0,{0x05,0x0c,0x09,0xe9,0x05,0x0c,0x09,0xea,0x15,0x00,0x25,0x01,0x95,0x02,0x75,0x01} },
+{  16,0x06e0,0,{0x81,0x42,0x95,0x01,0x75,0x06,0x81,0x01,0x05,0x0c,0x09,0x00,0x05,0x0c,0x09,0x00} },
+{  16,0x06f0,0,{0x15,0x00,0x25,0x01,0x95,0x02,0x75,0x01,0x91,0x06,0x95,0x01,0x75,0x06,0x91,0x03} },
+{  16,0x0700,0,{0xc0,0x04,0x03,0x09,0x04,0x18,0x03,0x45,0x00,0x4d,0x00,0x41,0x00,0x47,0x00,0x49} },
+{  16,0x0710,0,{0x00,0x43,0x00,0x20,0x00,0x47,0x00,0x6d,0x00,0x62,0x00,0x48,0x00,0x1e,0x03,0x45} },
+{  16,0x0720,0,{0x00,0x6d,0x00,0x61,0x00,0x67,0x00,0x69,0x00,0x63,0x00,0x20,0x00,0x45,0x00,0x4d} },
+{  16,0x0730,0,{0x00,0x49,0x00,0x20,0x00,0x32,0x00,0x7c,0x00,0x36,0x00,0x2a,0x03,0x43,0x00,0x6f} },
+{  16,0x0740,0,{0x00,0x6e,0x00,0x66,0x00,0x69,0x00,0x67,0x00,0x75,0x00,0x72,0x00,0x61,0x00,0x74} },
+{  16,0x0750,0,{0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69} },
+{  16,0x0760,0,{0x00,0x6e,0x00,0x67,0x00,0x22,0x03,0x49,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x72} },
+{  16,0x0770,0,{0x00,0x66,0x00,0x61,0x00,0x63,0x00,0x65,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x72} },
+{   9,0x0780,0,{0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x00,0x00} },
+{  16,0x0789,0,{0x74,0x00,0xf5,0x86,0x90,0xfd,0xa5,0x7c,0x05,0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} },
+{   1,0x0799,0,{0x22} },
+{  16,0x079a,0,{0x90,0x7f,0xd6,0xe0,0x44,0x80,0xf0,0x43,0x87,0x01,0x00,0x00,0x00,0x00,0x00,0x22} },
+{  16,0x07aa,0,{0xc0,0xd0,0xc0,0xe0,0x8f,0xe0,0xc0,0xe0,0x8e,0xe0,0xc0,0xe0,0x8d,0xe0,0xc0,0xe0} },
+{  16,0x07ba,0,{0x8c,0xe0,0xc0,0xe0,0xc0,0x82,0xc0,0x83,0x05,0x86,0xc0,0x84,0xc0,0x85,0xe5,0x18} },
+{  16,0x07ca,0,{0xb4,0x02,0x03,0x02,0x07,0xd9,0xb4,0x01,0x03,0x02,0x07,0xde,0x02,0x07,0xfa,0x7d} },
+{  16,0x07da,0,{0x01,0x02,0x08,0x16,0xe5,0x19,0x14,0xf5,0x19,0xc3,0xb5,0x13,0x03,0x02,0x07,0xf5} },
+{  16,0x07ea,0,{0x50,0x09,0xb4,0x00,0xea,0x75,0x19,0x0a,0x02,0x07,0xd9,0x7d,0x00,0x02,0x08,0x16} },
+{  16,0x07fa,0,{0xe5,0x19,0x14,0xf5,0x19,0xc3,0xb5,0x14,0x03,0x02,0x08,0x11,0x50,0x09,0xb4,0x00} },
+{  16,0x080a,0,{0xce,0x75,0x19,0x0a,0x02,0x07,0xd9,0x7d,0x02,0x02,0x08,0x16,0x7c,0x05,0x90,0x7f} },
+{  16,0x081a,0,{0x99,0xe0,0x54,0x40,0xdc,0x03,0x02,0x08,0x43,0xb4,0x00,0x1d,0x90,0x7f,0xe3,0x74} },
+{  16,0x082a,0,{0x7b,0xf0,0xa3,0x74,0x80,0xf0,0x90,0x7f,0xe2,0x74,0x40,0xf0,0x90,0x7f,0xe5,0xf0} },
+{  16,0x083a,0,{0x90,0x7f,0xe2,0x74,0x00,0xf0,0x02,0x08,0x18,0x05,0x86,0x90,0x7f,0xe2,0x74,0x80} },
+{  16,0x084a,0,{0xf0,0x90,0x79,0x65,0xe0,0xb4,0x01,0x03,0x02,0x08,0x9e,0xb4,0x02,0x03,0x02,0x08} },
+{  16,0x085a,0,{0x96,0xb4,0x03,0x03,0x02,0x08,0x8e,0xb4,0x04,0x03,0x02,0x08,0x86,0xb4,0x05,0x03} },
+{  16,0x086a,0,{0x02,0x08,0x7e,0xb4,0x06,0x03,0x02,0x08,0x76,0x02,0x08,0xf4,0x05,0x86,0x90,0x7f} },
+{  16,0x087a,0,{0x6c,0x02,0x08,0xe9,0x05,0x86,0x90,0x7f,0x6c,0x02,0x08,0xdd,0x05,0x86,0x90,0x7f} },
+{  16,0x088a,0,{0x6c,0x02,0x08,0xcf,0x05,0x86,0x90,0x7f,0x6c,0x02,0x08,0xc0,0x05,0x86,0x90,0x7f} },
+{  16,0x089a,0,{0x6c,0x02,0x08,0xb2,0x05,0x86,0x90,0x7f,0x6c,0xf0,0x00,0xf0,0x00,0xf0,0x00,0xf0} },
+{  16,0x08aa,0,{0x0d,0xed,0xb4,0x2d,0xf4,0x02,0x08,0xf4,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0d,0xed} },
+{  16,0x08ba,0,{0xb4,0x2d,0xf5,0x02,0x08,0xf4,0xf0,0x00,0xf0,0x00,0xf0,0x00,0xf0,0x0d,0xed,0xb4} },
+{  16,0x08ca,0,{0x31,0xf4,0x02,0x08,0xf4,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0d,0xed,0xb4,0x31,0xf5} },
+{  16,0x08da,0,{0x02,0x08,0xf4,0xf0,0xf0,0xf0,0xf0,0x0d,0xed,0xb4,0x61,0xf7,0x02,0x08,0xf4,0xf0} },
+{  16,0x08ea,0,{0xf0,0xf0,0xf0,0xf0,0xf0,0x0d,0xed,0xb4,0x61,0xf5,0x90,0x7f,0xe2,0x74,0x00,0xf0} },
+{  16,0x08fa,0,{0xd0,0x85,0xd0,0x84,0x05,0x86,0xd0,0x83,0xd0,0x82,0xd0,0xe0,0xfc,0xd0,0xe0,0xfd} },
+{   5,0x090a,0,{0xd0,0xe0,0xfe,0xd0,0xe0} },
+{   6,0x090f,0,{0xff,0xd0,0xe0,0xd0,0xd0,0x22} },
+{  16,0x0915,0,{0xc0,0xd0,0xc0,0xe0,0xc0,0x82,0xc0,0x83,0x90,0x7f,0x6f,0xe5,0x0c,0xf0,0xe5,0x0d} },
+{  13,0x0925,0,{0xf0,0xe5,0x0e,0xf0,0xd0,0x83,0xd0,0x82,0xd0,0xe0,0xd0,0xd0,0x22} },
+{  16,0x0932,0,{0xc0,0xd0,0xc0,0xe0,0x8f,0xe0,0xc0,0xe0,0x8e,0xe0,0xc0,0xe0,0xc0,0x82,0xc0,0x83} },
+{  16,0x0942,0,{0x05,0x86,0xc0,0x84,0xc0,0x85,0x90,0x79,0x70,0xe0,0xff,0xbf,0x00,0x03,0x02,0x0a} },
+{  16,0x0952,0,{0xb8,0x90,0x7f,0x96,0xe0,0x44,0x80,0xf0,0x90,0x7f,0xe2,0x74,0x80,0xf0,0x90,0x7f} },
+{  16,0x0962,0,{0x62,0xe0,0x05,0x86,0x90,0x7f,0xe2,0x74,0x00,0xf0,0x90,0x7f,0x96,0xe0,0x54,0x7f} },
+{  16,0x0972,0,{0xf0,0x90,0x7f,0xe2,0x74,0x80,0xf0,0x90,0x79,0x88,0xe0,0xb4,0x01,0x03,0x02,0x09} },
+{  16,0x0982,0,{0xbe,0xb4,0x02,0x03,0x02,0x09,0xc3,0xb4,0x03,0x03,0x02,0x09,0xac,0xb4,0x04,0x03} },
+{  16,0x0992,0,{0x02,0x09,0x9a,0x05,0x86,0x02,0x0a,0xb2,0xef,0x54,0x03,0xfe,0xef,0x03,0x03,0x54} },
+{  16,0x09a2,0,{0x3f,0xff,0x90,0x7f,0x63,0x05,0x86,0x02,0x09,0xc9,0xef,0x54,0x03,0xfe,0xef,0x03} },
+{  16,0x09b2,0,{0x03,0x54,0x3f,0xff,0x90,0x7f,0x63,0x05,0x86,0x02,0x0a,0x36,0x05,0x86,0x02,0x0a} },
+{  16,0x09c2,0,{0xa5,0x05,0x86,0x02,0x0a,0x8e,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0} },
+{  16,0x09d2,0,{0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86} },
+{  16,0x09e2,0,{0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0} },
+{  16,0x09f2,0,{0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86,0xdf,0xca,0xee,0xb4,0x00,0x03} },
+{  16,0x0a02,0,{0x02,0x0a,0xb2,0xb4,0x01,0x03,0x02,0x0a,0x25,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05} },
+{  16,0x0a12,0,{0x86,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0} },
+{  16,0x0a22,0,{0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0x05,0x86} },
+{  16,0x0a32,0,{0x02,0x0a,0xb2,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0} },
+{  13,0x0a42,0,{0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86} },
+{  16,0x0a4f,0,{0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xdf,0xd6} },
+{  16,0x0a5f,0,{0xee,0xb4,0x00,0x03,0x02,0x0a,0xb2,0xb4,0x01,0x03,0x02,0x0a,0x80,0xe0,0xe0,0xe0} },
+{  16,0x0a6f,0,{0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05} },
+{  16,0x0a7f,0,{0x86,0xe0,0xe0,0xe0,0xe0,0x05,0x86,0xe0,0xe0,0x05,0x86,0x02,0x0a,0xb2,0xe0,0xe0} },
+{  16,0x0a8f,0,{0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0} },
+{  16,0x0a9f,0,{0xdf,0xec,0x02,0x0a,0xb2,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0} },
+{  16,0x0aaf,0,{0xe0,0xdf,0xf2,0x90,0x7f,0xe2,0x74,0x00,0xf0,0xd0,0x85,0xd0,0x84,0x05,0x86,0xd0} },
+{  14,0x0abf,0,{0x83,0xd0,0x82,0xd0,0xe0,0xfe,0xd0,0xe0,0xff,0xd0,0xe0,0xd0,0xd0,0x22} },
+{  16,0x0acd,0,{0xc0,0x82,0xc0,0x83,0xc0,0xe0,0xe8,0xc0,0xe0,0x78,0xd1,0xe8,0x14,0xf8,0x70,0xfb} },
+{  10,0x0add,0,{0xd0,0xe0,0xf8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0x22} },
+{  16,0x0ae7,0,{0xc0,0xd0,0xc0,0xe0,0x8f,0xe0,0xc0,0xe0,0x8e,0xe0,0xc0,0xe0,0x8d,0xe0,0xc0,0xe0} },
+{  16,0x0af7,0,{0x8c,0xe0,0xc0,0xe0,0x75,0x86,0x00,0xc0,0x82,0xc0,0x83,0x05,0x86,0xc0,0x84,0xc0} },
+{  16,0x0b07,0,{0x85,0x7e,0x00,0x90,0x79,0x8e,0xe0,0xb4,0x00,0x16,0x74,0x01,0xf0,0x90,0x06,0xca} },
+{  16,0x0b17,0,{0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xa3,0xe0,0xff,0x90,0x79,0x8d,0xf0,0x02,0x0b,0x39} },
+{  16,0x0b27,0,{0x90,0x79,0x8d,0xe0,0xff,0x90,0x79,0x8f,0xe0,0xfd,0x90,0x79,0x90,0xe0,0xfc,0x02} },
+{  16,0x0b37,0,{0x0b,0x46,0x90,0x06,0xca,0x05,0x86,0x90,0x7f,0x00,0x05,0x86,0x02,0x0b,0x51,0x8d} },
+{  16,0x0b47,0,{0x84,0x8c,0x85,0x05,0x86,0x90,0x7f,0x00,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xa3} },
+{  16,0x0b57,0,{0x0e,0xee,0xb4,0x40,0x03,0x02,0x0b,0x6c,0x05,0x86,0xdf,0xee,0x90,0x79,0x8e,0x74} },
+{  16,0x0b67,0,{0x00,0xf0,0x02,0x0b,0x82,0x05,0x86,0xad,0x84,0xac,0x85,0x90,0x79,0x8f,0xed,0xf0} },
+{  16,0x0b77,0,{0x90,0x79,0x90,0xec,0xf0,0x90,0x79,0x8d,0x1f,0xef,0xf0,0x90,0x7f,0xb5,0xee,0xf0} },
+{  16,0x0b87,0,{0xd0,0x85,0xd0,0x84,0x05,0x86,0xd0,0x83,0xd0,0x82,0xd0,0xe0,0xfc,0xd0,0xe0,0xfd} },
+{  11,0x0b97,0,{0xd0,0xe0,0xfe,0xd0,0xe0,0xff,0xd0,0xe0,0xd0,0xd0,0x22} },
+{  16,0x0ba2,0,{0xc0,0xd0,0xc0,0xe0,0xc0,0x82,0xc0,0x83,0x90,0x7f,0xae,0xe0,0x54,0xe0,0xf0,0x90} },
+{  16,0x0bb2,0,{0x7f,0x96,0xe0,0x44,0x08,0x54,0xfb,0xf0,0x90,0x7f,0x97,0xe0,0x54,0xbf,0xf0,0x90} },
+{  16,0x0bc2,0,{0x7f,0xe3,0x74,0x7b,0xf0,0x90,0x7f,0xe4,0x74,0x40,0xf0,0x90,0x79,0x78,0xe0,0x90} },
+{  16,0x0bd2,0,{0x7b,0x40,0xf0,0x90,0x7f,0xe2,0x74,0x48,0xf0,0x90,0x7f,0xe5,0xe0,0x90,0x7f,0xe2} },
+{  16,0x0be2,0,{0x74,0x00,0xf0,0x90,0x7f,0x96,0xe0,0x54,0xf7,0x44,0x04,0xf0,0x90,0x7f,0xe3,0x74} },
+{  16,0x0bf2,0,{0x7b,0xf0,0x90,0x7f,0xe4,0x74,0x40,0xf0,0x90,0x79,0x79,0xe0,0x90,0x7b,0x40,0xf0} },
+{  16,0x0c02,0,{0x90,0x7f,0xe2,0x74,0x48,0xf0,0x90,0x7f,0xe5,0xe0,0x90,0x7f,0xe2,0x74,0x00,0xf0} },
+{  16,0x0c12,0,{0x90,0x7f,0x96,0xe0,0x54,0xf3,0xf0,0x90,0x7f,0xae,0xe0,0x44,0x1f,0xf0,0xd0,0x83} },
+{   7,0x0c22,0,{0xd0,0x82,0xd0,0xe0,0xd0,0xd0,0x22} },
+{  16,0x0c29,0,{0xc0,0xd0,0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x90,0x79,0x2f,0xe0,0x64,0xff,0xc3,0x24} },
+{  11,0x0c39,0,{0x01,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0xd0,0xd0,0x22} },
+{  16,0x0c44,0,{0xbb,0x01,0x06,0x89,0x82,0x8a,0x83,0xe0,0x22,0x50,0x02,0xe7,0x22,0xbb,0xfe,0x02} },
+{   9,0x0c54,0,{0xe3,0x22,0x89,0x82,0x8a,0x83,0xe4,0x93,0x22} },
+{  16,0x0c5d,0,{0xbb,0x01,0x0c,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe0,0x22,0x50} },
+{  16,0x0c6d,0,{0x06,0xe9,0x25,0x82,0xf8,0xe6,0x22,0xbb,0xfe,0x06,0xe9,0x25,0x82,0xf8,0xe2,0x22} },
+{  13,0x0c7d,0,{0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe4,0x93,0x22} },
+{  16,0x0c8a,0,{0xbb,0x01,0x06,0x89,0x82,0x8a,0x83,0xf0,0x22,0x50,0x02,0xf7,0x22,0xbb,0xfe,0x01} },
+{   2,0x0c9a,0,{0xf3,0x22} },
+{  16,0x0c9c,0,{0xf8,0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe8,0xf0} },
+{  16,0x0cac,0,{0x22,0x50,0x06,0xe9,0x25,0x82,0xc8,0xf6,0x22,0xbb,0xfe,0x05,0xe9,0x25,0x82,0xc8} },
+{   2,0x0cbc,0,{0xf2,0x22} },
+{  16,0x0cbe,0,{0xc2,0xd5,0xec,0x30,0xe7,0x09,0xb2,0xd5,0xe4,0xc3,0x9d,0xfd,0xe4,0x9c,0xfc,0xee} },
+{  16,0x0cce,0,{0x30,0xe7,0x15,0xb2,0xd5,0xe4,0xc3,0x9f,0xff,0xe4,0x9e,0xfe,0x12,0x0e,0x40,0xc3} },
+{  16,0x0cde,0,{0xe4,0x9d,0xfd,0xe4,0x9c,0xfc,0x80,0x03,0x12,0x0e,0x40,0x30,0xd5,0x07,0xc3,0xe4} },
+{   6,0x0cee,0,{0x9f,0xff,0xe4,0x9e,0xfe,0x22} },
+{  16,0x0cf4,0,{0xc5,0xf0,0xf8,0xa3,0xe0,0x28,0xf0,0xc5,0xf0,0xf8,0xe5,0x82,0x15,0x82,0x70,0x02} },
+{   6,0x0d04,0,{0x15,0x83,0xe0,0x38,0xf0,0x22} },
+{  16,0x0d0a,0,{0xbb,0x01,0x10,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0xe0,0xf5,0xf0} },
+{  16,0x0d1a,0,{0xa3,0xe0,0x22,0x50,0x09,0xe9,0x25,0x82,0xf8,0x86,0xf0,0x08,0xe6,0x22,0xbb,0xfe} },
+{  16,0x0d2a,0,{0x0a,0xe9,0x25,0x82,0xf8,0xe2,0xf5,0xf0,0x08,0xe2,0x22,0xe5,0x83,0x2a,0xf5,0x83} },
+{   8,0x0d3a,0,{0xe9,0x93,0xf5,0xf0,0xa3,0xe9,0x93,0x22} },
+{  16,0x0d42,0,{0xe8,0x8f,0xf0,0xa4,0xcc,0x8b,0xf0,0xa4,0x2c,0xfc,0xe9,0x8e,0xf0,0xa4,0x2c,0xfc} },
+{  16,0x0d52,0,{0x8a,0xf0,0xed,0xa4,0x2c,0xfc,0xea,0x8e,0xf0,0xa4,0xcd,0xa8,0xf0,0x8b,0xf0,0xa4} },
+{  16,0x0d62,0,{0x2d,0xcc,0x38,0x25,0xf0,0xfd,0xe9,0x8f,0xf0,0xa4,0x2c,0xcd,0x35,0xf0,0xfc,0xeb} },
+{  16,0x0d72,0,{0x8e,0xf0,0xa4,0xfe,0xa9,0xf0,0xeb,0x8f,0xf0,0xa4,0xcf,0xc5,0xf0,0x2e,0xcd,0x39} },
+{  15,0x0d82,0,{0xfe,0xe4,0x3c,0xfc,0xea,0xa4,0x2d,0xce,0x35,0xf0,0xfd,0xe4,0x3c,0xfc,0x22} },
+{  16,0x0d91,0,{0xeb,0x9f,0xf5,0xf0,0xea,0x9e,0x42,0xf0,0xe9,0x9d,0x42,0xf0,0xe8,0x9c,0x45,0xf0} },
+{   1,0x0da1,0,{0x22} },
+{  16,0x0da2,0,{0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0e,0xa1} },
+{  16,0x0db2,0,{0x50,0x07,0xe9,0x25,0x82,0xf8,0x02,0x0e,0x95,0xbb,0xfe,0x07,0xe9,0x25,0x82,0xf8} },
+{  16,0x0dc2,0,{0x02,0x0e,0xad,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0e,0xb9} },
+{  16,0x0dd2,0,{0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0e,0xd5} },
+{  16,0x0de2,0,{0x50,0x07,0xe9,0x25,0x82,0xf8,0x02,0x0e,0xc9,0xbb,0xfe,0x07,0xe9,0x25,0x82,0xf8} },
+{   4,0x0df2,0,{0x02,0x0e,0xe1,0x22} },
+{  16,0x0df6,0,{0xbb,0x01,0x0d,0xe5,0x82,0x29,0xf5,0x82,0xe5,0x83,0x3a,0xf5,0x83,0x02,0x0f,0x06} },
+{  16,0x0e06,0,{0x50,0x07,0xe9,0x25,0x82,0xf8,0x02,0x0e,0xed,0xbb,0xfe,0x07,0xe9,0x25,0x82,0xf8} },
+{   4,0x0e16,0,{0x02,0x0f,0x37,0x22} },
+{  16,0x0e1a,0,{0xd0,0x83,0xd0,0x82,0xf8,0xe4,0x93,0x70,0x12,0x74,0x01,0x93,0x70,0x0d,0xa3,0xa3} },
+{  16,0x0e2a,0,{0x93,0xf8,0x74,0x01,0x93,0xf5,0x82,0x88,0x83,0xe4,0x73,0x74,0x02,0x93,0x68,0x60} },
+{   6,0x0e3a,0,{0xef,0xa3,0xa3,0xa3,0x80,0xdf} },
+{  16,0x0e40,0,{0xbc,0x00,0x0b,0xbe,0x00,0x29,0xef,0x8d,0xf0,0x84,0xff,0xad,0xf0,0x22,0xe4,0xcc} },
+{  16,0x0e50,0,{0xf8,0x75,0xf0,0x08,0xef,0x2f,0xff,0xee,0x33,0xfe,0xec,0x33,0xfc,0xee,0x9d,0xec} },
+{  16,0x0e60,0,{0x98,0x40,0x05,0xfc,0xee,0x9d,0xfe,0x0f,0xd5,0xf0,0xe9,0xe4,0xce,0xfd,0x22,0xed} },
+{  16,0x0e70,0,{0xf8,0xf5,0xf0,0xee,0x84,0x20,0xd2,0x1c,0xfe,0xad,0xf0,0x75,0xf0,0x08,0xef,0x2f} },
+{  16,0x0e80,0,{0xff,0xed,0x33,0xfd,0x40,0x07,0x98,0x50,0x06,0xd5,0xf0,0xf2,0x22,0xc3,0x98,0xfd} },
+{   5,0x0e90,0,{0x0f,0xd5,0xf0,0xea,0x22} },
+{  12,0x0e95,0,{0xe6,0xfc,0x08,0xe6,0xfd,0x08,0xe6,0xfe,0x08,0xe6,0xff,0x22} },
+{  12,0x0ea1,0,{0xe0,0xfc,0xa3,0xe0,0xfd,0xa3,0xe0,0xfe,0xa3,0xe0,0xff,0x22} },
+{  12,0x0ead,0,{0xe2,0xfc,0x08,0xe2,0xfd,0x08,0xe2,0xfe,0x08,0xe2,0xff,0x22} },
+{  16,0x0eb9,0,{0xe4,0x93,0xfc,0xa3,0xe4,0x93,0xfd,0xa3,0xe4,0x93,0xfe,0xa3,0xe4,0x93,0xff,0x22} },
+{  12,0x0ec9,0,{0xec,0xf6,0x08,0xed,0xf6,0x08,0xee,0xf6,0x08,0xef,0xf6,0x22} },
+{  12,0x0ed5,0,{0xec,0xf0,0xa3,0xed,0xf0,0xa3,0xee,0xf0,0xa3,0xef,0xf0,0x22} },
+{  12,0x0ee1,0,{0xec,0xf2,0x08,0xed,0xf2,0x08,0xee,0xf2,0x08,0xef,0xf2,0x22} },
+{  16,0x0eed,0,{0xd0,0x83,0xd0,0x82,0xe4,0x93,0xf6,0x08,0x74,0x01,0x93,0xf6,0x08,0x74,0x02,0x93} },
+{   9,0x0efd,0,{0xf6,0x08,0x74,0x03,0x93,0xf6,0x74,0x04,0x73} },
+{  16,0x0f06,0,{0xa8,0x82,0x85,0x83,0xf0,0xd0,0x83,0xd0,0x82,0x12,0x0f,0x1d,0x12,0x0f,0x1d,0x12} },
+{  16,0x0f16,0,{0x0f,0x1d,0x12,0x0f,0x1d,0xe4,0x73,0xe4,0x93,0xa3,0xc5,0x83,0xc5,0xf0,0xc5,0x83} },
+{  16,0x0f26,0,{0xc8,0xc5,0x82,0xc8,0xf0,0xa3,0xc5,0x83,0xc5,0xf0,0xc5,0x83,0xc8,0xc5,0x82,0xc8} },
+{   1,0x0f36,0,{0x22} },
+{  16,0x0f37,0,{0xd0,0x83,0xd0,0x82,0xe4,0x93,0xf2,0x08,0x74,0x01,0x93,0xf2,0x08,0x74,0x02,0x93} },
+{   9,0x0f47,0,{0xf2,0x08,0x74,0x03,0x93,0xf2,0x74,0x04,0x73} },
+{  16,0x0f50,0,{0xc2,0xaf,0xd2,0x2c,0x90,0x7f,0x93,0x74,0x30,0xf0,0x90,0x7f,0x9c,0x74,0xbf,0xf0} },
+{  16,0x0f60,0,{0x90,0x7f,0x96,0xe0,0x54,0x30,0xf0,0x90,0x7f,0x94,0x74,0x30,0xf0,0x90,0x7f,0x9d} },
+{  16,0x0f70,0,{0x74,0xcf,0xf0,0x90,0x7f,0x97,0x74,0xa0,0xf0,0x90,0x7f,0x95,0x74,0xcc,0xf0,0xe4} },
+{  16,0x0f80,0,{0x90,0x7f,0x9e,0xf0,0xc2,0x2d,0xc2,0x2a,0xc2,0x2b,0xc2,0x2e,0x90,0x79,0x74,0x04} },
+{  16,0x0f90,0,{0xf0,0x12,0x2e,0x94,0x12,0x49,0xe2,0x12,0x4b,0xe6,0x12,0x32,0x0d,0x12,0x3b,0x0d} },
+{  16,0x0fa0,0,{0x12,0x41,0xfd,0x12,0x3e,0x99,0xe5,0x1f,0x70,0x18,0x75,0x1f,0x01,0x12,0x17,0xff} },
+{  16,0x0fb0,0,{0x12,0x2f,0xff,0x12,0x49,0xc8,0x12,0x4b,0xd8,0x12,0x4b,0xda,0x12,0x49,0x6f,0x12} },
+{  16,0x0fc0,0,{0x1b,0x40,0x12,0x39,0x8d,0x90,0x7f,0xaf,0xe0,0x44,0x01,0xf0,0x90,0x7f,0xae,0xe0} },
+{  16,0x0fd0,0,{0x44,0x1f,0xf0,0x90,0x7f,0xac,0x74,0xff,0xf0,0x90,0x7f,0xad,0xf0,0x90,0x7f,0xde} },
+{  16,0x0fe0,0,{0xf0,0x90,0x7f,0xdf,0xf0,0x90,0x7f,0xab,0xf0,0x90,0x7f,0xa9,0xf0,0x90,0x7f,0xaa} },
+{  16,0x0ff0,0,{0xf0,0x53,0x91,0xef,0x43,0xd8,0x20,0xd2,0xe8,0x43,0xd8,0x20,0x43,0xa8,0x80,0x22} },
+{  16,0x1000,0,{0x90,0x79,0x63,0xe0,0x14,0x60,0x44,0x14,0x70,0x02,0x21,0xd0,0x14,0x70,0x02,0x41} },
+{  16,0x1010,0,{0xd9,0x14,0x70,0x02,0x61,0xd7,0x24,0x04,0x60,0x02,0x81,0x56,0xe4,0x90,0x79,0x78} },
+{  16,0x1020,0,{0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x54,0xfd,0xf0,0x90} },
+{  16,0x1030,0,{0x79,0x7b,0xf0,0xe4,0x90,0x79,0x88,0xf0,0xa2,0xaf,0x33,0xf5,0x12,0xc2,0xaf,0x12} },
+{  16,0x1040,0,{0x0b,0xa2,0xe5,0x12,0x70,0x02,0x81,0x56,0xd2,0xaf,0x22,0x90,0x79,0x2d,0xe0,0x64} },
+{  16,0x1050,0,{0x01,0x70,0x79,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x30,0xf0,0x90,0x7f,0xff} },
+{  16,0x1060,0,{0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0} },
+{  16,0x1070,0,{0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12} },
+{  16,0x1080,0,{0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90} },
+{  16,0x1090,0,{0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe} },
+{  16,0x10a0,0,{0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd} },
+{  16,0x10b0,0,{0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x04} },
+{  16,0x10c0,0,{0xf0,0x90,0x79,0x88,0x14,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d,0xe0} },
+{  16,0x10d0,0,{0x64,0x02,0x70,0x79,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x34,0xf0,0x90,0x7f} },
+{  16,0x10e0,0,{0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79} },
+{  16,0x10f0,0,{0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5} },
+{  16,0x1100,0,{0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0} },
+{  16,0x1110,0,{0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54} },
+{  16,0x1120,0,{0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44} },
+{  16,0x1130,0,{0x02,0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74} },
+{  16,0x1140,0,{0x04,0xf0,0x90,0x79,0x88,0x14,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d} },
+{  16,0x1150,0,{0xe0,0x64,0x03,0x60,0x02,0x81,0x56,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x64} },
+{  16,0x1160,0,{0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0} },
+{  16,0x1170,0,{0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf} },
+{  16,0x1180,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90} },
+{  16,0x1190,0,{0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79} },
+{  16,0x11a0,0,{0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79} },
+{  16,0x11b0,0,{0x79,0xe0,0x44,0x04,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74} },
+{  16,0x11c0,0,{0x04,0xf0,0x90,0x79,0x88,0x14,0xf0,0xe5,0x12,0x70,0x02,0x81,0x56,0xd2,0xaf,0x22} },
+{  16,0x11d0,0,{0x90,0x79,0x2d,0xe0,0x64,0x01,0x70,0x7a,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74} },
+{  16,0x11e0,0,{0x88,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b} },
+{  16,0x11f0,0,{0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x54,0xfd,0xf0,0x90,0x79,0x7b,0xf0,0xa2} },
+{  16,0x1200,0,{0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0} },
+{  16,0x1210,0,{0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90} },
+{  16,0x1220,0,{0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90} },
+{  16,0x1230,0,{0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2} },
+{  16,0x1240,0,{0x90,0x79,0x82,0x74,0x0c,0xf0,0x90,0x79,0x88,0x74,0x01,0xf0,0xe5,0x12,0x60,0x02} },
+{  16,0x1250,0,{0xd2,0xaf,0x90,0x79,0x2d,0xe0,0x64,0x02,0x60,0x02,0x81,0x56,0x90,0x7f,0xf2,0xf0} },
+{  16,0x1260,0,{0x90,0x7f,0xf3,0x74,0x94,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4,0x90,0x79,0x78} },
+{  16,0x1270,0,{0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x54,0xfd,0xf0,0x90} },
+{  16,0x1280,0,{0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79} },
+{  16,0x1290,0,{0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0} },
+{  16,0x12a0,0,{0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0} },
+{  16,0x12b0,0,{0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0,0x54,0xfb,0xf0,0x90,0x79,0x84} },
+{  16,0x12c0,0,{0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x0c,0xf0,0x90,0x79,0x88,0x74,0x01,0xf0} },
+{  16,0x12d0,0,{0xe5,0x12,0x70,0x02,0x81,0x56,0xd2,0xaf,0x22,0x90,0x79,0x2d,0xe0,0x64,0x01,0x70} },
+{  16,0x12e0,0,{0x77,0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0xcc,0xf0,0x90,0x7f,0xff,0x74,0xfc} },
+{  16,0x12f0,0,{0xf0,0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfc} },
+{  16,0x1300,0,{0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2} },
+{  16,0x1310,0,{0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79} },
+{  16,0x1320,0,{0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79} },
+{  16,0x1330,0,{0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0,0x90} },
+{  16,0x1340,0,{0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x12,0xf0,0x90,0x79,0x88,0x74} },
+{  16,0x1350,0,{0x02,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d,0xe0,0x64,0x02,0x70,0x77} },
+{  16,0x1360,0,{0x90,0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0xe0,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0} },
+{  16,0x1370,0,{0xe4,0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfc,0xf0} },
+{  16,0x1380,0,{0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90} },
+{  16,0x1390,0,{0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f} },
+{  16,0x13a0,0,{0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79} },
+{  16,0x13b0,0,{0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0,0x54,0xfb,0xf0,0x90,0x79} },
+{  16,0x13c0,0,{0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x12,0xf0,0x90,0x79,0x88,0x74,0x02} },
+{  16,0x13d0,0,{0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x2d,0xe0,0x64,0x03,0x70,0x77,0x90} },
+{  16,0x13e0,0,{0x7f,0xf2,0xf0,0x90,0x7f,0xf3,0x74,0x94,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0xe4} },
+{  16,0x13f0,0,{0x90,0x79,0x78,0xf0,0x90,0x79,0x7b,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfe,0xf0,0x44} },
+{  16,0x1400,0,{0x02,0xf0,0x90,0x79,0x7b,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
+{  16,0x1410,0,{0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90} },
+{  16,0x1420,0,{0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90} },
+{  16,0x1430,0,{0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x90,0x79,0x84} },
+{  16,0x1440,0,{0xf0,0x12,0x0b,0xa2,0x90,0x79,0x82,0x74,0x06,0xf0,0x90,0x79,0x88,0x74,0x04,0xf0} },
+{   7,0x1450,0,{0xe5,0x12,0x60,0x02,0xd2,0xaf,0x22} },
+{  16,0x1457,0,{0xc2,0x28,0xc2,0x29,0x90,0x7f,0xe8,0xe0,0x12,0x0e,0x1a,0x14,0x84,0x00,0x14,0xe0} },
+{  16,0x1467,0,{0x01,0x14,0xf6,0x02,0x16,0x7c,0x21,0x16,0xbe,0x22,0x15,0x91,0x80,0x15,0xd1,0x81} },
+{  16,0x1477,0,{0x16,0x2e,0x82,0x16,0xcf,0xa1,0x17,0x05,0xa2,0x00,0x00,0x17,0x0a,0x90,0x7f,0xe9} },
+{  16,0x1487,0,{0xe0,0x14,0x60,0x11,0x24,0xfe,0x60,0x28,0x24,0xfe,0x60,0x3b,0x24,0xfc,0x70,0x40} },
+{  16,0x1497,0,{0x12,0x4a,0x2a,0xe1,0x16,0x12,0x4b,0xe0,0x40,0x02,0xe1,0x16,0x90,0x7f,0xea,0xe0} },
+{  16,0x14a7,0,{0xb4,0x01,0x04,0xc2,0x2a,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16} },
+{  16,0x14b7,0,{0x12,0x4b,0xe2,0x90,0x7f,0xea,0xe0,0xb4,0x01,0x04,0xd2,0x2a,0xe1,0x16,0x90,0x7f} },
+{  16,0x14c7,0,{0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16} },
+{  16,0x14d7,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x24,0xf5,0x70} },
+{  16,0x14e7,0,{0x05,0x12,0x47,0x9c,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90} },
+{  16,0x14f7,0,{0x7f,0xe9,0xe0,0x24,0xfd,0x60,0x54,0x24,0x02,0x60,0x02,0xa1,0x88,0x12,0x4b,0xe0} },
+{  16,0x1507,0,{0x40,0x02,0xe1,0x16,0x90,0x7f,0xea,0xe0,0x70,0x38,0x90,0x7f,0xec,0xe0,0xf4,0x54} },
+{  16,0x1517,0,{0x80,0xff,0xc4,0x54,0x0f,0xff,0xe0,0x54,0x07,0x2f,0x25,0xe0,0x24,0xb4,0xf5,0x82} },
+{  16,0x1527,0,{0xe4,0x34,0x7f,0xf5,0x83,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0x54,0x80,0xff,0x13,0x13} },
+{  16,0x1537,0,{0x13,0x54,0x1f,0xff,0xe0,0x54,0x07,0x2f,0x90,0x7f,0xd7,0xf0,0xe0,0x44,0x20,0xf0} },
+{  16,0x1547,0,{0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x12,0x4b,0xe2,0x40,0x02} },
+{  16,0x1557,0,{0xe1,0x16,0x90,0x7f,0xea,0xe0,0x70,0x20,0x90,0x7f,0xec,0xe0,0xf4,0x54,0x80,0xff} },
+{  16,0x1567,0,{0xc4,0x54,0x0f,0xff,0xe0,0x54,0x07,0x2f,0x25,0xe0,0x24,0xb4,0xf5,0x82,0xe4,0x34} },
+{  16,0x1577,0,{0x7f,0xf5,0x83,0x74,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1} },
+{  16,0x1587,0,{0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x60,0x12} },
+{  16,0x1597,0,{0x24,0xf8,0x60,0x09,0x24,0x02,0x70,0x29,0x12,0x17,0x1e,0xe1,0x16,0x12,0x4b,0xa0} },
+{  16,0x15a7,0,{0xe1,0x16,0x12,0x4b,0xde,0xa2,0x2a,0xe4,0x33,0xff,0x25,0xe0,0xff,0xa2,0x2b,0xe4} },
+{  16,0x15b7,0,{0x33,0x4f,0x90,0x7f,0x00,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0xe1} },
+{  16,0x15c7,0,{0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x60,0x37} },
+{  16,0x15d7,0,{0x24,0xf6,0x60,0x2e,0x24,0x04,0x70,0x41,0x90,0x7f,0xeb,0xe0,0x24,0xde,0x60,0x0e} },
+{  16,0x15e7,0,{0x04,0x70,0x16,0xd2,0x29,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0xd2,0x29} },
+{  16,0x15f7,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{  16,0x1607,0,{0xe1,0x16,0x12,0x44,0x63,0xe1,0x16,0x12,0x4b,0xde,0xe4,0x90,0x7f,0x00,0xf0,0xa3} },
+{  16,0x1617,0,{0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0xe1,0x16,0x20,0x29,0x07,0x90,0x7f,0xb4,0xe0} },
+{  16,0x1627,0,{0x44,0x01,0xf0,0xc2,0x29,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x24,0xf4,0x60,0x34,0x24} },
+{  16,0x1637,0,{0x0c,0x70,0x39,0x12,0x4b,0xde,0x90,0x7f,0xec,0xe0,0xf4,0x54,0x80,0xff,0xc4,0x54} },
+{  16,0x1647,0,{0x0f,0xff,0xe0,0x54,0x07,0x2f,0x25,0xe0,0x24,0xb4,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
+{  16,0x1657,0,{0x83,0xe0,0x54,0xfd,0x90,0x7f,0x00,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x02} },
+{  16,0x1667,0,{0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xb4,0xe0} },
+{  16,0x1677,0,{0x44,0x01,0xf0,0xe1,0x16,0x90,0x7f,0xe9,0xe0,0x24,0xf6,0x60,0x12,0x14,0x60,0x1a} },
+{  16,0x1687,0,{0x24,0x02,0x70,0x1d,0xd2,0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x12,0xd2} },
+{  16,0x1697,0,{0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
+{  16,0x16a7,0,{0xf0,0x20,0x28,0x0f,0x90,0x79,0x85,0x74,0x01,0xf0,0x12,0x49,0x6f,0x90,0x7f,0xc5} },
+{  16,0x16b7,0,{0x74,0x02,0xf0,0xc2,0x28,0x80,0x58,0x90,0x79,0x86,0x74,0x01,0xf0,0x12,0x49,0x6f} },
+{  16,0x16c7,0,{0x90,0x7f,0xc5,0x74,0x02,0xf0,0x80,0x47,0x90,0x7f,0xe9,0xe0,0x24,0xfe,0x60,0x12} },
+{  16,0x16d7,0,{0x14,0x60,0x1a,0x24,0x02,0x70,0x1d,0xd2,0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{  16,0x16e7,0,{0x80,0x12,0xd2,0x28,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x07,0x90,0x7f,0xb4} },
+{  16,0x16f7,0,{0xe0,0x44,0x01,0xf0,0x20,0x28,0x03,0x12,0x1a,0x7b,0xc2,0x28,0x80,0x11,0x12,0x2c} },
+{  16,0x1707,0,{0x2b,0x80,0x0c,0x12,0x4b,0xe4,0x50,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x90} },
+{   7,0x1717,0,{0x7f,0xb4,0xe0,0x44,0x02,0xf0,0x22} },
+{  16,0x171e,0,{0x12,0x4b,0xdc,0x40,0x02,0xe1,0xe3,0x90,0x7f,0xeb,0xe0,0x24,0xfe,0x60,0x1e,0x14} },
+{  16,0x172e,0,{0x60,0x46,0x14,0x60,0x6e,0x14,0x70,0x02,0xe1,0xd4,0x24,0x04,0x60,0x02,0xe1,0xdc} },
+{  16,0x173e,0,{0x74,0x05,0x90,0x7f,0xd4,0xf0,0x74,0x00,0x90,0x7f,0xd5,0xf0,0x22,0x90,0x7f,0xea} },
+{  16,0x174e,0,{0xe0,0xff,0x12,0x3f,0xa2,0x8b,0x33,0x8a,0x34,0x89,0x35,0xea,0x49,0x60,0x11,0xce} },
+{  16,0x175e,0,{0xea,0xce,0xee,0x90,0x7f,0xd4,0xf0,0xcf,0xe9,0xcf,0xef,0x90,0x7f,0xd5,0xf0,0x22} },
+{  16,0x176e,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xea,0xe0,0xff,0x12,0x48,0x00} },
+{  16,0x177e,0,{0x8b,0x33,0x8a,0x34,0x89,0x35,0xea,0x49,0x60,0x11,0xce,0xea,0xce,0xee,0x90,0x7f} },
+{  16,0x178e,0,{0xd4,0xf0,0xcf,0xe9,0xcf,0xef,0x90,0x7f,0xd5,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44} },
+{  16,0x179e,0,{0x01,0xf0,0x22,0x90,0x7f,0xea,0xe0,0xff,0x90,0x7e,0xc0,0xe0,0xfd,0xa3,0xe0,0xfb} },
+{  16,0x17ae,0,{0x12,0x44,0xd2,0x8b,0x33,0x8a,0x34,0x89,0x35,0xea,0x49,0x60,0x11,0xce,0xea,0xce} },
+{  16,0x17be,0,{0xee,0x90,0x7f,0xd4,0xf0,0xcf,0xe9,0xcf,0xef,0x90,0x7f,0xd5,0xf0,0x22,0x90,0x7f} },
+{  16,0x17ce,0,{0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f} },
+{   5,0x17de,0,{0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x17e3,0,{0x22} },
+{  16,0x17e4,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x90,0x7f,0xc4,0xe4,0xf0,0x53,0x91,0xef,0x90,0x7f} },
+{  11,0x17f4,0,{0xab,0x74,0x04,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{   1,0x17ff,0,{0x22} },
+{  16,0x1800,0,{0xe4,0x90,0x78,0x15,0xf0,0x7b,0x01,0x90,0x78,0x12,0x04,0xf0,0xa3,0x74,0x78,0xf0} },
+{  16,0x1810,0,{0xa3,0x74,0x58,0xf0,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
+{  16,0x1820,0,{0x00,0x01,0x12,0x0c,0x5d,0xff,0x90,0x79,0x9a,0xe0,0x6f,0x60,0x18,0x90,0x78,0x15} },
+{  16,0x1830,0,{0xe0,0xc3,0x94,0x06,0x50,0x0f,0xe0,0x04,0xf0,0x90,0x78,0x13,0xe4,0x75,0xf0,0x0f} },
+{  16,0x1840,0,{0x12,0x0c,0xf4,0x80,0xcf,0x90,0x78,0x15,0xe0,0xb4,0x06,0x08,0x90,0x7f,0xb4,0xe0} },
+{  16,0x1850,0,{0x44,0x01,0xf0,0x22,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12} },
+{  16,0x1860,0,{0x0c,0x44,0xff,0x24,0xbf,0x70,0x02,0x41,0x7a,0x24,0xe0,0x70,0x02,0x41,0x4c,0x24} },
+{  16,0x1870,0,{0x21,0x60,0x02,0x41,0x73,0x90,0x79,0x97,0xe0,0x24,0xfe,0x70,0x02,0x21,0x9a,0x14} },
+{  16,0x1880,0,{0x70,0x02,0x21,0xef,0x24,0x02,0x60,0x02,0x41,0x44,0x90,0x79,0x2d,0xe0,0xa3,0xf0} },
+{  16,0x1890,0,{0x90,0x79,0x23,0xe0,0xff,0xe4,0xfc,0xfd,0xfe,0xfb,0xfa,0x79,0x01,0xf8,0x12,0x0d} },
+{  16,0x18a0,0,{0x42,0xc8,0xec,0xc8,0xc9,0xed,0xc9,0xca,0xee,0xca,0xcb,0xef,0xcb,0x90,0x79,0x22} },
+{  16,0x18b0,0,{0xe0,0xfe,0xe4,0xfc,0xfd,0x2b,0xfb,0xea,0x3e,0xfa,0xed,0x39,0xf9,0xec,0x38,0xf8} },
+{  16,0x18c0,0,{0x90,0x79,0x21,0xe0,0xff,0xe4,0xfe,0xeb,0x2f,0xff,0xee,0x3a,0xfe,0xed,0x39,0xfd} },
+{  16,0x18d0,0,{0xec,0x38,0xfc,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
+{  16,0x18e0,0,{0x02,0x12,0x0d,0xd2,0x90,0x00,0x02,0x12,0x0d,0xa2,0x7b,0x44,0x7a,0xac,0x79,0x00} },
+{  16,0x18f0,0,{0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x05,0x90,0x79,0x2d,0x04,0xf0,0x90,0x78,0x12} },
+{  16,0x1900,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12,0x0d,0xa2,0x7b,0x80} },
+{  16,0x1910,0,{0x7a,0xbb,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x06,0x90,0x79,0x2d,0x74} },
+{  16,0x1920,0,{0x02,0xf0,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02} },
+{  16,0x1930,0,{0x12,0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70} },
+{  16,0x1940,0,{0x06,0x90,0x79,0x2d,0x74,0x03,0xf0,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0x75} },
+{  16,0x1950,0,{0x0c,0x67,0x75,0x0d,0x06,0x75,0x0e,0x0b,0xef,0xb4,0x02,0x08,0xe4,0xf5,0x0c,0xf5} },
+{  16,0x1960,0,{0x0d,0x75,0x0e,0x0c,0xef,0xb4,0x03,0x08,0xe4,0xf5,0x0c,0xf5,0x0d,0x75,0x0e,0x18} },
+{  16,0x1970,0,{0xef,0xb4,0x03,0x0d,0x90,0x79,0x2e,0xe0,0x64,0x03,0x60,0x05,0xd2,0x2f,0x12,0x3d} },
+{  16,0x1980,0,{0x79,0x90,0x79,0x2d,0xe0,0x64,0x03,0x60,0x0a,0xa3,0xe0,0xb4,0x03,0x05,0xc2,0x2f} },
+{  16,0x1990,0,{0x12,0x3d,0x79,0x12,0x10,0x00,0x12,0x28,0x01,0x22,0x90,0x79,0x23,0xe0,0xff,0xe4} },
+{  16,0x19a0,0,{0xfc,0xfd,0xfe,0xfb,0xfa,0x79,0x01,0xf8,0x12,0x0d,0x42,0xc8,0xec,0xc8,0xc9,0xed} },
+{  16,0x19b0,0,{0xc9,0xca,0xee,0xca,0xcb,0xef,0xcb,0x90,0x79,0x22,0xe0,0xfe,0xe4,0xfc,0xfd,0x2b} },
+{  16,0x19c0,0,{0xfb,0xea,0x3e,0xfa,0xed,0x39,0xf9,0xec,0x38,0xf8,0x90,0x79,0x21,0xe0,0xff,0xe4} },
+{  16,0x19d0,0,{0xfe,0xeb,0x2f,0xff,0xee,0x3a,0xfe,0xed,0x39,0xfd,0xec,0x38,0xfc,0x90,0x78,0x12} },
+{  16,0x19e0,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x06,0x12,0x0d,0xd2,0x22,0x90} },
+{  16,0x19f0,0,{0x79,0x23,0xe0,0xff,0xe4,0xfc,0xfd,0xfe,0xfb,0xfa,0x79,0x01,0xf8,0x12,0x0d,0x42} },
+{  16,0x1a00,0,{0xc8,0xec,0xc8,0xc9,0xed,0xc9,0xca,0xee,0xca,0xcb,0xef,0xcb,0x90,0x79,0x22,0xe0} },
+{  16,0x1a10,0,{0xfe,0xe4,0xfc,0xfd,0x2b,0xfb,0xea,0x3e,0xfa,0xed,0x39,0xf9,0xec,0x38,0xf8,0x90} },
+{  16,0x1a20,0,{0x79,0x21,0xe0,0xff,0xe4,0xfe,0xeb,0x2f,0xff,0xee,0x3a,0xfe,0xed,0x39,0xfd,0xec} },
+{  16,0x1a30,0,{0x38,0xfc,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a} },
+{  16,0x1a40,0,{0x12,0x0d,0xd2,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0} },
+{  16,0x1a50,0,{0x14,0x70,0x18,0x90,0x79,0x21,0xe0,0xff,0x90,0x78,0x12,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x1a60,0,{0xa3,0xe0,0xf9,0x90,0x00,0x0e,0xef,0x12,0x0c,0x9c,0x22,0x90,0x7f,0xb4,0xe0,0x44} },
+{  10,0x1a70,0,{0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x1a7a,0,{0x22} },
+{  16,0x1a7b,0,{0xe4,0xff,0xfe,0x7b,0x01,0x90,0x78,0x0f,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74} },
+{  16,0x1a8b,0,{0x2b,0xf0,0x90,0x78,0x0f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02} },
+{  16,0x1a9b,0,{0x12,0x0c,0x5d,0xfd,0x90,0x7f,0xec,0xe0,0x6d,0x60,0x13,0xef,0xc3,0x94,0x05,0x50} },
+{  16,0x1aab,0,{0x0d,0x0f,0x90,0x78,0x10,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd4,0x8d,0x33} },
+{  16,0x1abb,0,{0x90,0x78,0x0f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c} },
+{  16,0x1acb,0,{0x5d,0xfd,0x90,0x7f,0xed,0xe0,0x6d,0x60,0x13,0xee,0xc3,0x94,0x0b,0x50,0x0d,0x0e} },
+{  16,0x1adb,0,{0x90,0x78,0x10,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd4,0x90,0x7f,0xed,0xe0} },
+{  16,0x1aeb,0,{0xf5,0x34,0xef,0x64,0x05,0x60,0x03,0xbe,0x0b,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
+{  16,0x1afb,0,{0xf0,0x22,0x90,0x78,0x0f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44} },
+{  16,0x1b0b,0,{0xff,0x24,0xf0,0x60,0x08,0x24,0x0f,0x70,0x0e,0x12,0x49,0x2a,0x22,0x12,0x4b,0x83} },
+{  14,0x1b1b,0,{0x90,0x79,0x20,0xe5,0x34,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x1b29,0,{0x22} },
+{  15,0x1b2a,0,{0x90,0x7f,0xea,0xe0,0xb4,0xff,0x04,0x12,0x34,0x16,0x22,0x12,0x38,0x00,0x22} },
+{   7,0x1b39,0,{0x53,0x98,0xfe,0x53,0x98,0xfd,0x32} },
+{  16,0x1b40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1b50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1b60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1b70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1b80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1b90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ba0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1bb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1bc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1bd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1be0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1bf0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c00,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c10,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c20,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c30,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1c90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ca0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1cb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1cc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1cd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ce0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1cf0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d00,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d10,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d20,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d30,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1d90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1da0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1db0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1dc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1dd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1de0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1df0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e00,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e10,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e20,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e30,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1e90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ea0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  14,0x1eb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ebe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ece,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ede,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1eee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1efe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f0e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f1e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f2e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{   2,0x1f3e,0,{0x00,0x00} },
+{  16,0x1f40,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f50,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f60,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f70,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f80,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1f90,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1fa0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1fb0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1fc0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1fd0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1fe0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x1ff0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2000,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2010,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2020,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2030,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2040,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2050,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2060,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2070,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2080,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2090,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x20a0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x20b0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x20c0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x20d0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x20e0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x20f0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2100,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2110,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2120,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2130,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2140,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2150,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2160,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2170,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2180,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2190,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x21a0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x21b0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x21c0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x21d0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x21e0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x21f0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2200,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2210,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2220,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2230,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2240,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2250,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2260,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2270,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2280,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2290,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x22a0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x22b0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x22c0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x22d0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x22e0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x22f0,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2300,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2310,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2320,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2330,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2340,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2350,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x2360,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  14,0x2370,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x237e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x238e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x239e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x23ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x23be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x23ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x23de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x23ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x23fe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x240e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x241e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x242e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x243e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x244e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x245e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x246e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x247e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x248e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x249e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x24ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x24be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x24ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x24de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x24ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x24fe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x250e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x251e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x252e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x253e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x254e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x255e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x256e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x257e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x258e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x259e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x25ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x25be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x25ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x25de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x25ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x25fe,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x260e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x261e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x262e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x263e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x264e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x265e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x266e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x267e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x268e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x269e,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x26ae,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x26be,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x26ce,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x26de,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  14,0x26ee,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x26fc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x270c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x271c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x272c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x273c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x274c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x275c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x276c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x277c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x278c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x279c,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x27ac,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x27bc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x27cc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x27dc,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{  16,0x27ec,0,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} },
+{   5,0x27fc,0,{0x00,0x00,0x00,0x00,0x22} },
+{  16,0x2801,0,{0x90,0x79,0x64,0xe0,0x14,0x60,0x46,0x14,0x70,0x02,0x41,0x3c,0x24,0x02,0x60,0x02} },
+{  16,0x2811,0,{0x81,0x2a,0x90,0x7f,0xfc,0x74,0xcc,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79} },
+{  16,0x2821,0,{0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfd,0xf0,0x44} },
+{  16,0x2831,0,{0x01,0xf0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
+{  16,0x2841,0,{0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x7a,0xf0,0x22,0x90,0x79,0x2d} },
+{  16,0x2851,0,{0xe0,0x64,0x01,0x60,0x02,0x01,0xf1,0x90,0x7f,0xfc,0x74,0xcc,0xf0,0x90,0x7f,0xff} },
+{  16,0x2861,0,{0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79} },
+{  16,0x2871,0,{0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79} },
+{  16,0x2881,0,{0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79} },
+{  16,0x2891,0,{0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
+{  16,0x28a1,0,{0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90} },
+{  16,0x28b1,0,{0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90} },
+{  16,0x28c1,0,{0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0} },
+{  16,0x28d1,0,{0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0,0x90,0x79,0x65} },
+{  16,0x28e1,0,{0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0} },
+{  16,0x28f1,0,{0x90,0x79,0x2d,0xe0,0x64,0x02,0x60,0x02,0x21,0x96,0x90,0x7f,0xfc,0x74,0xc8,0xf0} },
+{  16,0x2901,0,{0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0} },
+{  16,0x2911,0,{0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01} },
+{  16,0x2921,0,{0x09,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb} },
+{  16,0x2931,0,{0xf0,0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2} },
+{  16,0x2941,0,{0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79} },
+{  16,0x2951,0,{0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0} },
+{  16,0x2961,0,{0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0} },
+{  16,0x2971,0,{0x54,0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0} },
+{  16,0x2981,0,{0x90,0x79,0x65,0x74,0x03,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c} },
+{  16,0x2991,0,{0xf0,0x90,0x79,0x8b,0xf0,0x90,0x79,0x2d,0xe0,0x64,0x03,0x60,0x02,0x81,0x2a,0x90} },
+{  16,0x29a1,0,{0x7f,0xfc,0x74,0x98,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01} },
+{  16,0x29b1,0,{0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x44,0x01,0xf0,0x44,0x02,0xf0,0x90} },
+{  16,0x29c1,0,{0x79,0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90} },
+{  16,0x29d1,0,{0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf} },
+{  16,0x29e1,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90} },
+{  16,0x29f1,0,{0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79} },
+{  16,0x2a01,0,{0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79} },
+{  16,0x2a11,0,{0x79,0xe0,0x54,0xfd,0xf0,0x44,0x04,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90} },
+{  16,0x2a21,0,{0x79,0x7a,0x74,0x01,0xf0,0x90,0x79,0x65,0x74,0x05,0xf0,0xe5,0x12,0x60,0x02,0xd2} },
+{  16,0x2a31,0,{0xaf,0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x22,0x90,0x79,0x2d,0xe0,0x64} },
+{  16,0x2a41,0,{0x01,0x60,0x02,0x41,0xe0,0x90,0x7f,0xfc,0x74,0xb4,0xf0,0x90,0x7f,0xff,0x74,0xfc} },
+{  16,0x2a51,0,{0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x54} },
+{  16,0x2a61,0,{0xfe,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0} },
+{  16,0x2a71,0,{0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79,0x79,0xe0} },
+{  16,0x2a81,0,{0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90} },
+{  16,0x2a91,0,{0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f} },
+{  16,0x2aa1,0,{0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79} },
+{  16,0x2ab1,0,{0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x54,0xfd,0xf0,0x54,0xfb,0xf0,0x90,0x79} },
+{  16,0x2ac1,0,{0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0,0x90,0x79,0x65,0x04,0xf0} },
+{  16,0x2ad1,0,{0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x90} },
+{  16,0x2ae1,0,{0x79,0x2d,0xe0,0x64,0x02,0x60,0x02,0x61,0x85,0x90,0x7f,0xfc,0x74,0xb0,0xf0,0x90} },
+{  16,0x2af1,0,{0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90} },
+{  16,0x2b01,0,{0x79,0x79,0xf0,0x54,0xfe,0xf0,0x44,0x02,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09} },
+{  16,0x2b11,0,{0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0} },
+{  16,0x2b21,0,{0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf} },
+{  16,0x2b31,0,{0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79} },
+{  16,0x2b41,0,{0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80} },
+{  16,0x2b51,0,{0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x44,0x02,0xf0,0x54} },
+{  16,0x2b61,0,{0xfb,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x7a,0x74,0x01,0xf0,0x90} },
+{  16,0x2b71,0,{0x79,0x65,0x74,0x04,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf,0xe4,0x90,0x79,0x8c,0xf0} },
+{  16,0x2b81,0,{0x90,0x79,0x8b,0xf0,0x90,0x79,0x2d,0xe0,0x64,0x03,0x60,0x02,0x81,0x2a,0x90,0x7f} },
+{  16,0x2b91,0,{0xfc,0x74,0x68,0xf0,0x90,0x7f,0xff,0x74,0xfc,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0} },
+{  16,0x2ba1,0,{0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x54,0xfe,0xf0,0x44,0x02,0xf0,0x90,0x79} },
+{  16,0x2bb1,0,{0x7e,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79} },
+{  16,0x2bc1,0,{0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4} },
+{  16,0x2bd1,0,{0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x02,0xf0,0x90,0x79} },
+{  16,0x2be1,0,{0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09,0x90,0x79,0x79} },
+{  16,0x2bf1,0,{0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79} },
+{  16,0x2c01,0,{0xe0,0x54,0xfd,0xf0,0x44,0x04,0xf0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79} },
+{  16,0x2c11,0,{0x7a,0x74,0x01,0xf0,0x90,0x79,0x65,0x74,0x06,0xf0,0xe5,0x12,0x60,0x02,0xd2,0xaf} },
+{  10,0x2c21,0,{0xe4,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x22} },
+{  16,0x2c2b,0,{0xe4,0xff,0x7b,0x01,0x90,0x78,0x16,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0x58} },
+{  16,0x2c3b,0,{0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12} },
+{  16,0x2c4b,0,{0x0c,0x5d,0xfe,0x90,0x7f,0xec,0xe0,0x6e,0x60,0x13,0xef,0xc3,0x94,0x06,0x50,0x0d} },
+{  16,0x2c5b,0,{0x0f,0x90,0x78,0x17,0xe4,0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x80,0xd4,0xbf,0x06,0x08} },
+{  16,0x2c6b,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x2c7b,0,{0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xff,0x24,0x9f,0x70,0x02,0xc1,0x66,0x24,0x21,0x60} },
+{  16,0x2c8b,0,{0x02,0xc1,0x8c,0x90,0x7f,0xe9,0xe0,0x24,0x7e,0x70,0x02,0xa1,0x30,0x14,0x70,0x02} },
+{  16,0x2c9b,0,{0xa1,0xc8,0x24,0x02,0x60,0x02,0xc1,0x5e,0x90,0x00,0x02,0x12,0x0d,0xa2,0x7b,0x44} },
+{  16,0x2cab,0,{0x7a,0xac,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74} },
+{  16,0x2cbb,0,{0x44,0xf0,0xa3,0x74,0xac,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90} },
+{  16,0x2ccb,0,{0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12,0x0d,0xa2} },
+{  16,0x2cdb,0,{0x7b,0x80,0x7a,0xbb,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f} },
+{  16,0x2ceb,0,{0x00,0x74,0x80,0xf0,0xa3,0x74,0xbb,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03} },
+{  16,0x2cfb,0,{0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12} },
+{  16,0x2d0b,0,{0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01,0x78,0x00,0xc3,0x12,0x0d,0x91,0x60,0x02} },
+{  16,0x2d1b,0,{0xc1,0x93,0x90,0x7f,0x00,0xf0,0xa3,0x74,0x77,0xf0,0xa3,0x74,0x01,0xf0,0x90,0x7f} },
+{  16,0x2d2b,0,{0xb5,0x74,0x03,0xf0,0x22,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
+{  16,0x2d3b,0,{0x90,0x00,0x06,0x12,0x0d,0xa2,0x7b,0x44,0x7a,0xac,0x79,0x00,0x78,0x00,0xc3,0x12} },
+{  16,0x2d4b,0,{0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74,0x44,0xf0,0xa3,0x74,0xac,0xf0,0xe4,0xa3} },
+{  16,0x2d5b,0,{0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3} },
+{  16,0x2d6b,0,{0xe0,0xf9,0x90,0x00,0x06,0x12,0x0d,0xa2,0x7b,0x80,0x7a,0xbb,0x79,0x00,0x78,0x00} },
+{  16,0x2d7b,0,{0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74,0x80,0xf0,0xa3,0x74,0xbb,0xf0} },
+{  16,0x2d8b,0,{0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0} },
+{  16,0x2d9b,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x06,0x12,0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01} },
+{  16,0x2dab,0,{0x78,0x00,0xc3,0x12,0x0d,0x91,0x60,0x02,0xc1,0x93,0x90,0x7f,0x00,0xf0,0xa3,0x74} },
+{  16,0x2dbb,0,{0x77,0xf0,0xa3,0x74,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x22,0x90,0x78,0x16} },
+{  16,0x2dcb,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a,0x12,0x0d,0xa2,0x7b,0x44} },
+{  16,0x2ddb,0,{0x7a,0xac,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f,0x00,0x74} },
+{  16,0x2deb,0,{0x44,0xf0,0xa3,0x74,0xac,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03,0xf0,0x90} },
+{  16,0x2dfb,0,{0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a,0x12,0x0d,0xa2} },
+{  16,0x2e0b,0,{0x7b,0x80,0x7a,0xbb,0x79,0x00,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x13,0x90,0x7f} },
+{  16,0x2e1b,0,{0x00,0x74,0x80,0xf0,0xa3,0x74,0xbb,0xf0,0xe4,0xa3,0xf0,0x90,0x7f,0xb5,0x74,0x03} },
+{  16,0x2e2b,0,{0xf0,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x0a,0x12} },
+{  16,0x2e3b,0,{0x0d,0xa2,0x7b,0x00,0x7a,0x77,0x79,0x01,0x78,0x00,0xc3,0x12,0x0d,0x91,0x70,0x48} },
+{  16,0x2e4b,0,{0x90,0x7f,0x00,0xf0,0xa3,0x74,0x77,0xf0,0xa3,0x74,0x01,0xf0,0x90,0x7f,0xb5,0x74} },
+{  16,0x2e5b,0,{0x03,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24} },
+{  16,0x2e6b,0,{0x7f,0x70,0x16,0x90,0x78,0x16,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
+{  16,0x2e7b,0,{0x0e,0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   8,0x2e8b,0,{0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x2e93,0,{0x22} },
+{  16,0x2e94,0,{0x75,0x36,0x25,0x75,0x37,0x24,0x90,0x79,0x74,0xe0,0x64,0x01,0x70,0x54,0xf0,0xf5} },
+{  16,0x2ea4,0,{0x35,0x75,0x22,0x01,0xe5,0x22,0x64,0x01,0x70,0x48,0x90,0x7f,0xa5,0xe0,0x44,0x80} },
+{  16,0x2eb4,0,{0xf0,0x90,0x7f,0xa6,0xe5,0x36,0xf0,0x12,0x46,0xc0,0x74,0x4f,0x25,0x35,0xf5,0x82} },
+{  16,0x2ec4,0,{0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x74,0x35,0x25} },
+{  16,0x2ed4,0,{0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0} },
+{  16,0x2ee4,0,{0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd,0x05,0x35,0xe5,0x35,0xc3,0x94,0x0d} },
+{  16,0x2ef4,0,{0x40,0xb2,0x90,0x79,0x75,0xe0,0x64,0x01,0x60,0x02,0xe1,0xde,0xf0,0x90,0x79,0x20} },
+{  16,0x2f04,0,{0xe0,0x64,0x05,0x60,0x02,0xe1,0x8d,0x7b,0x01,0x90,0x79,0x5c,0x04,0xf0,0xa3,0x74} },
+{  16,0x2f14,0,{0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x75,0x33,0x07,0x90,0x79,0x5c,0xe0,0xfb,0xa3,0xe0} },
+{  16,0x2f24,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c,0x5d,0x70,0x0f,0x90,0x00,0x04,0x12} },
+{  16,0x2f34,0,{0x0c,0x5d,0x90,0x79,0x2f,0xf0,0x12,0x0c,0x29,0x80,0x06,0x90,0x79,0x2f,0x74,0xff} },
+{  16,0x2f44,0,{0xf0,0xe4,0xf5,0x35,0x75,0x22,0x01,0x75,0x34,0x02,0xe5,0x22,0x64,0x01,0x70,0x39} },
+{  16,0x2f54,0,{0x90,0x7f,0xa5,0xe0,0x44,0x80,0xf0,0x90,0x7f,0xa6,0xe5,0x36,0xf0,0x12,0x46,0xc0} },
+{  16,0x2f64,0,{0xaf,0x34,0x05,0x34,0x90,0x7f,0xa6,0xef,0xf0,0x12,0x46,0xc0,0x90,0x79,0x2f,0xe0} },
+{  16,0x2f74,0,{0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd} },
+{  16,0x2f84,0,{0x05,0x35,0xe5,0x35,0xc3,0x94,0x06,0x40,0xc1,0x90,0x79,0x20,0xe0,0x64,0x06,0x70} },
+{  16,0x2f94,0,{0x49,0x7b,0x01,0x90,0x79,0x5f,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0} },
+{  16,0x2fa4,0,{0x75,0x33,0x03,0x90,0x79,0x5f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
+{  16,0x2fb4,0,{0x01,0x12,0x0c,0x5d,0x70,0x1c,0x90,0x00,0x04,0x12,0x0c,0x5d,0x90,0x79,0x33,0xf0} },
+{  16,0x2fc4,0,{0x70,0x03,0x74,0xff,0xf0,0x90,0x79,0x33,0xe0,0x54,0x7f,0xff,0xf0,0x25,0xe0,0xf0} },
+{  10,0x2fd4,0,{0x80,0x05,0xe4,0x90,0x79,0x33,0xf0,0x12,0x47,0xdf} },
+{   1,0x2fde,0,{0x22} },
+{  16,0x2fdf,0,{0x90,0x79,0x78,0x74,0x03,0xf0,0x90,0x79,0x83,0xe0,0x90,0x79,0x79,0xf0,0xa2,0xaf} },
+{  16,0x2fef,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x22} },
+{   1,0x2fff,0,{0x22} },
+{  16,0x3000,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x11,0x90,0x78,0x25,0x74,0x01,0xf0} },
+{  16,0x3010,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x75,0x35,0x07,0xed,0xb4,0x06,0x11,0x90} },
+{  16,0x3020,0,{0x78,0x25,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x75,0x35,0x03} },
+{  16,0x3030,0,{0x90,0x7f,0xeb,0xe0,0x14,0x60,0x11,0x14,0x60,0x5b,0x24,0x02,0x60,0x02,0x41,0x05} },
+{  16,0x3040,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24,0x7f,0x70,0x3d} },
+{  16,0x3050,0,{0xe4,0xff,0xef,0xc3,0x95,0x35,0x50,0x2f,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x3060,0,{0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00} },
+{  16,0x3070,0,{0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0} },
+{  16,0x3080,0,{0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xcb,0x90,0x7f,0xb5,0xee,0xf0,0x22,0x90,0x7f,0xb4} },
+{  16,0x3090,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24,0x7e,0x60,0x64,0x14,0x70,0x02} },
+{  16,0x30a0,0,{0x21,0x55,0x14,0x70,0x02,0x21,0xa9,0x24,0x03,0x60,0x02,0x21,0xfd,0xe4,0xff,0xef} },
+{  16,0x30b0,0,{0xc3,0x95,0x35,0x50,0x46,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
+{  16,0x30c0,0,{0x90,0x00,0x03,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82} },
+{  16,0x30d0,0,{0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x00,0x04,0x12,0x0c,0x5d,0xfd,0xcc,0xee} },
+{  16,0x30e0,0,{0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78} },
+{  16,0x30f0,0,{0x26,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0x90,0x7f,0xb5,0xee,0xf0} },
+{  16,0x3100,0,{0x22,0xe4,0xff,0xef,0xc3,0x95,0x35,0x50,0x46,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0} },
+{  16,0x3110,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x05,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74} },
+{  16,0x3120,0,{0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x00,0x06,0x12,0x0c} },
+{  16,0x3130,0,{0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83} },
+{  16,0x3140,0,{0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0x90} },
+{  16,0x3150,0,{0x7f,0xb5,0xee,0xf0,0x22,0xe4,0xff,0xef,0xc3,0x95,0x35,0x50,0x46,0x90,0x78,0x25} },
+{  16,0x3160,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x07,0x12,0x0c,0x5d,0xfd,0xcc} },
+{  16,0x3170,0,{0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90} },
+{  16,0x3180,0,{0x00,0x08,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4} },
+{  16,0x3190,0,{0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4} },
+{  16,0x31a0,0,{0x0f,0x80,0xb4,0x90,0x7f,0xb5,0xee,0xf0,0x22,0xe4,0xff,0xef,0xc3,0x95,0x35,0x50} },
+{  16,0x31b0,0,{0x46,0x90,0x78,0x25,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x09,0x12} },
+{  16,0x31c0,0,{0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00,0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5} },
+{  16,0x31d0,0,{0x83,0xed,0xf0,0x90,0x00,0x0a,0x12,0x0c,0x5d,0xfd,0xcc,0xee,0xcc,0x0e,0x74,0x00} },
+{  16,0x31e0,0,{0x2c,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xed,0xf0,0x90,0x78,0x26,0xe4,0x75,0xf0} },
+{  16,0x31f0,0,{0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0x90,0x7f,0xb5,0xee,0xf0,0x22,0x90,0x7f,0xb4} },
+{  12,0x3200,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x320c,0,{0x22} },
+{  16,0x320d,0,{0x7b,0x01,0x7a,0x78,0x79,0x2b,0x90,0x78,0x00,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9} },
+{  16,0x321d,0,{0xf0,0x74,0x01,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
+{  16,0x322d,0,{0xf9,0x90,0x00,0x01,0x74,0x01,0x12,0x0c,0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c} },
+{  16,0x323d,0,{0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
+{  16,0x324d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x10,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
+{  16,0x325d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x05,0x12,0x0c,0x9c,0x90,0x00,0x02} },
+{  16,0x326d,0,{0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78} },
+{  16,0x327d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78} },
+{  16,0x328d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x02,0x12,0x0c} },
+{  16,0x329d,0,{0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12} },
+{  16,0x32ad,0,{0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x01,0x12} },
+{  16,0x32bd,0,{0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01} },
+{  16,0x32cd,0,{0x74,0x03,0x12,0x0c,0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4} },
+{  16,0x32dd,0,{0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
+{  16,0x32ed,0,{0xf9,0x74,0x10,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
+{  16,0x32fd,0,{0xf9,0x90,0x00,0x01,0x74,0x06,0x12,0x0c,0x9c,0x90,0x00,0x02,0xe4,0x12,0x0c,0x9c} },
+{  16,0x330d,0,{0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
+{  16,0x331d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3} },
+{  16,0x332d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x04,0x12,0x0c,0x9c,0x90,0x00,0x02} },
+{  16,0x333d,0,{0xe4,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78} },
+{  16,0x334d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78} },
+{  16,0x335d,0,{0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x04,0x12,0x0c} },
+{  16,0x336d,0,{0x9c,0x90,0x00,0x02,0x74,0x04,0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03} },
+{  16,0x337d,0,{0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02} },
+{  16,0x338d,0,{0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
+{  16,0x339d,0,{0x01,0x74,0x03,0x12,0x0c,0x9c,0x90,0x00,0x02,0x74,0x04,0x12,0x0c,0x9c,0x90,0x78} },
+{  16,0x33ad,0,{0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x33bd,0,{0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78,0x00,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x33cd,0,{0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x02,0x12,0x0c,0x9c,0x90,0x00,0x02,0x74,0x04} },
+{  16,0x33dd,0,{0x12,0x0c,0x9c,0x90,0x78,0x01,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x00} },
+{  16,0x33ed,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x02,0x12,0x0c,0x8a,0x90,0x78,0x00} },
+{  16,0x33fd,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x01,0x12,0x0c,0x9c} },
+{   8,0x340d,0,{0x90,0x00,0x02,0x74,0x04,0x12,0x0c,0x9c} },
+{   1,0x3415,0,{0x22} },
+{  16,0x3416,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x11,0x90,0x78,0x1f,0x74,0x01,0xf0} },
+{  16,0x3426,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x75,0x35,0x07,0xed,0xb4,0x06,0x11,0x90} },
+{  16,0x3436,0,{0x78,0x1f,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x75,0x35,0x03} },
+{  16,0x3446,0,{0x90,0x79,0x99,0xe0,0x14,0x60,0x11,0x14,0x60,0x5b,0x24,0x02,0x60,0x02,0xc1,0x06} },
+{  16,0x3456,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0,0x14,0x70,0x3e,0xe4} },
+{  16,0x3466,0,{0xff,0xef,0xc3,0x95,0x35,0x50,0x2f,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82} },
+{  16,0x3476,0,{0xe4,0x34,0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3} },
+{  16,0x3486,0,{0xe0,0xf9,0x90,0x00,0x01,0xed,0x12,0x0c,0x9c,0x90,0x78,0x20,0xe4,0x75,0xf0,0x0b} },
+{  16,0x3496,0,{0x12,0x0c,0xf4,0x0f,0x80,0xcb,0x90,0x79,0x75,0x74,0x01,0xf0,0x22,0x90,0x7f,0xb4} },
+{  16,0x34a6,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0,0x24,0xfe,0x60,0x63,0x14,0x70,0x02} },
+{  16,0x34b6,0,{0xa1,0x64,0x14,0x70,0x02,0xa1,0xb2,0x24,0x03,0x60,0x02,0xa1,0xfe,0xe4,0xff,0xef} },
+{  16,0x34c6,0,{0xc3,0x95,0x35,0x50,0x44,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82,0xe4,0x34} },
+{  16,0x34d6,0,{0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
+{  16,0x34e6,0,{0x90,0x00,0x03,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82} },
+{  16,0x34f6,0,{0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x04,0x12,0x0c,0x9c,0x90,0x78,0x20,0xe4} },
+{  16,0x3506,0,{0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb6,0x90,0x79,0x75,0x74,0x01,0xf0,0x22} },
+{  16,0x3516,0,{0xe4,0xff,0xef,0xc3,0x95,0x35,0x40,0x02,0xc1,0x0d,0xcd,0xee,0xcd,0x0e,0x74,0x21} },
+{  16,0x3526,0,{0x2d,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3} },
+{  16,0x3536,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x05,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e} },
+{  16,0x3546,0,{0x74,0x21,0x2d,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x06,0x12,0x0c} },
+{  16,0x3556,0,{0x9c,0x90,0x78,0x20,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0xe4,0xff} },
+{  16,0x3566,0,{0xef,0xc3,0x95,0x35,0x40,0x02,0xc1,0x0d,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5} },
+{  16,0x3576,0,{0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x3586,0,{0xa3,0xe0,0xf9,0x90,0x00,0x07,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e,0x74,0x21} },
+{  16,0x3596,0,{0x2d,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x08,0x12,0x0c,0x9c,0x90} },
+{  16,0x35a6,0,{0x78,0x20,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb4,0xe4,0xff,0xef,0xc3} },
+{  16,0x35b6,0,{0x95,0x35,0x50,0x53,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82,0xe4,0x34,0x79} },
+{  16,0x35c6,0,{0xf5,0x83,0xe0,0xfd,0x90,0x78,0x1f,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
+{  16,0x35d6,0,{0x00,0x09,0xed,0x12,0x0c,0x9c,0xcd,0xee,0xcd,0x0e,0x74,0x21,0x2d,0xf5,0x82,0xe4} },
+{  16,0x35e6,0,{0x34,0x79,0xf5,0x83,0xe0,0x90,0x00,0x0a,0x12,0x0c,0x9c,0x90,0x78,0x20,0xe4,0x75} },
+{  16,0x35f6,0,{0xf0,0x0b,0x12,0x0c,0xf4,0x0f,0x80,0xb6,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22} },
+{   7,0x3606,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x360d,0,{0x22} },
+{  16,0x360e,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x10,0x90,0x78,0x28,0x74,0x01,0xf0} },
+{  16,0x361e,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x7f,0x07,0xed,0xb4,0x06,0x10,0x90,0x78} },
+{  16,0x362e,0,{0x28,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x7f,0x03,0x90,0x78} },
+{  16,0x363e,0,{0x28,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xfd,0x90,0x7f,0xea} },
+{  16,0x364e,0,{0xe0,0x6d,0x60,0x12,0xee,0xc3,0x9f,0x50,0x0d,0x90,0x78,0x29,0xe4,0x75,0xf0,0x0b} },
+{  16,0x365e,0,{0x12,0x0c,0xf4,0x0e,0x80,0xd8,0x90,0x7f,0xeb,0xe0,0x14,0x60,0x11,0x14,0x60,0x46} },
+{  16,0x366e,0,{0x24,0x02,0x60,0x02,0xe1,0x9a,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f} },
+{  16,0x367e,0,{0xe9,0xe0,0x24,0x7f,0x70,0x28,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
+{  16,0x368e,0,{0xf0,0x22,0x90,0x78,0x28,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01} },
+{  16,0x369e,0,{0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0,0x22,0x90,0x7f} },
+{  16,0x36ae,0,{0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xe9,0xe0,0x24,0x7e,0x60,0x40,0x14,0x60} },
+{  16,0x36be,0,{0x6f,0x14,0x70,0x02,0xe1,0x60,0x24,0x03,0x60,0x02,0xe1,0x92,0xee,0x6f,0x70,0x08} },
+{  16,0x36ce,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x28,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x36de,0,{0xa3,0xe0,0xf9,0x90,0x00,0x03,0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x90,0x00,0x04} },
+{  16,0x36ee,0,{0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x22,0xee,0x6f} },
+{  16,0x36fe,0,{0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x28,0xe0,0xfb,0xa3} },
+{  16,0x370e,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x05,0x12,0x0c,0x5d,0x90,0x7f,0x00,0xf0,0x90} },
+{  16,0x371e,0,{0x00,0x06,0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x22} },
+{  16,0x372e,0,{0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x28,0xe0} },
+{  16,0x373e,0,{0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x07,0x12,0x0c,0x5d,0x90,0x7f,0x00} },
+{  16,0x374e,0,{0xf0,0x90,0x00,0x08,0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5,0x74,0x02} },
+{  16,0x375e,0,{0xf0,0x22,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78} },
+{  16,0x376e,0,{0x28,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x09,0x12,0x0c,0x5d,0x90} },
+{  16,0x377e,0,{0x7f,0x00,0xf0,0x90,0x00,0x0a,0x12,0x0c,0x5d,0x90,0x7f,0x01,0xf0,0x90,0x7f,0xb5} },
+{  16,0x378e,0,{0x74,0x02,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0} },
+{   3,0x379e,0,{0x44,0x01,0xf0} },
+{   1,0x37a1,0,{0x22} },
+{  16,0x37a2,0,{0xc0,0xe0,0xc0,0xf0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0} },
+{  16,0x37b2,0,{0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef} },
+{  16,0x37c2,0,{0xc0,0xe0,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x10,0xf0,0x90,0x79,0x83,0xe0,0x54} },
+{  16,0x37d2,0,{0xfd,0xf0,0x12,0x2f,0xdf,0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0} },
+{  16,0x37e2,0,{0xfc,0xd0,0xe0,0xfb,0xd0,0xe0,0xfa,0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0} },
+{   8,0x37f2,0,{0x82,0xd0,0x83,0xd0,0xf0,0xd0,0xe0,0x32} },
+{   6,0x37fa,0,{0x53,0x91,0xbf,0xd2,0x26,0x32} },
+{  16,0x3800,0,{0xe4,0xfe,0x90,0x79,0x20,0xe0,0xfd,0xb4,0x05,0x10,0x90,0x78,0x22,0x74,0x01,0xf0} },
+{  16,0x3810,0,{0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0x7f,0x07,0xed,0xb4,0x06,0x10,0x90,0x78} },
+{  16,0x3820,0,{0x22,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xff,0xf0,0x7f,0x03,0x90,0x78} },
+{  16,0x3830,0,{0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xfd,0x90,0x79,0x98} },
+{  16,0x3840,0,{0xe0,0x6d,0x60,0x12,0xee,0xc3,0x9f,0x50,0x0d,0x90,0x78,0x23,0xe4,0x75,0xf0,0x0b} },
+{  16,0x3850,0,{0x12,0x0c,0xf4,0x0e,0x80,0xd8,0x90,0x79,0x99,0xe0,0x14,0x60,0x11,0x14,0x60,0x48} },
+{  16,0x3860,0,{0x24,0x02,0x60,0x02,0x21,0x85,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79} },
+{  16,0x3870,0,{0x97,0xe0,0x14,0x70,0x2b,0xee,0x6f,0x70,0x09,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{  16,0x3880,0,{0x80,0x17,0x90,0x79,0x21,0xe0,0xfd,0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3} },
+{  16,0x3890,0,{0xe0,0xf9,0x90,0x00,0x01,0xed,0x12,0x0c,0x9c,0x90,0x79,0x75,0x74,0x01,0xf0,0x22} },
+{  16,0x38a0,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x97,0xe0,0x24,0xfe,0x60,0x43} },
+{  16,0x38b0,0,{0x14,0x60,0x6e,0x14,0x70,0x02,0x21,0x4f,0x24,0x03,0x60,0x02,0x21,0x7d,0xee,0x6f} },
+{  16,0x38c0,0,{0x70,0x09,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x21,0x90,0x79,0x21,0xe0,0xfd} },
+{  16,0x38d0,0,{0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x03,0xed,0x12} },
+{  16,0x38e0,0,{0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x04,0x12,0x0c,0x9c,0x90,0x79,0x75,0x74} },
+{  16,0x38f0,0,{0x01,0xf0,0x22,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90} },
+{  16,0x3900,0,{0x79,0x21,0xe0,0xfd,0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
+{  16,0x3910,0,{0x00,0x05,0xed,0x12,0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x06,0x12,0x0c,0x9c} },
+{  16,0x3920,0,{0x22,0xee,0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x21} },
+{  16,0x3930,0,{0xe0,0xfd,0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x07} },
+{  16,0x3940,0,{0xed,0x12,0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x08,0x12,0x0c,0x9c,0x22,0xee} },
+{  16,0x3950,0,{0x6f,0x70,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x79,0x21,0xe0,0xfe} },
+{  16,0x3960,0,{0x90,0x78,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x09,0xee,0x12} },
+{  16,0x3970,0,{0x0c,0x9c,0x90,0x79,0x22,0xe0,0x90,0x00,0x0a,0x12,0x0c,0x9c,0x22,0x90,0x7f,0xb4} },
+{  12,0x3980,0,{0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x398c,0,{0x22} },
+{  16,0x398d,0,{0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xe4,0x90,0x79,0x83,0xf0,0x12,0x2f,0xdf,0x90,0x7f} },
+{  16,0x399d,0,{0xe0,0x74,0x90,0xf0,0x90,0x7f,0xe1,0x74,0x04,0xf0,0xe4,0x90,0x7f,0xdd,0xf0,0x90} },
+{  16,0x39ad,0,{0x7f,0xa1,0xf0,0x53,0x8e,0xf8,0x75,0x88,0x05,0x75,0xb8,0x20,0x75,0xf8,0x01,0x43} },
+{  16,0x39bd,0,{0x8e,0x30,0xf5,0xc8,0x75,0xca,0x7f,0x75,0xcb,0xf8,0x43,0xa8,0x20,0x90,0x79,0x74} },
+{  16,0x39cd,0,{0x04,0xf0,0xc2,0x22,0xe4,0xf5,0x0f,0x90,0x79,0x78,0xf0,0xa3,0xf0,0x90,0x79,0x62} },
+{  16,0x39dd,0,{0xf0,0xa3,0xf0,0xa3,0xf0,0x90,0x79,0x66,0xf0,0xa3,0xf0,0x90,0x79,0x7b,0xf0,0xa3} },
+{  16,0x39ed,0,{0xf0,0x90,0x79,0x84,0xf0,0x90,0x79,0x7d,0xf0,0x90,0x79,0x75,0xf0,0xa3,0xf0,0xa3} },
+{  16,0x39fd,0,{0xf0,0xc2,0x23,0xc2,0x24,0xc2,0x25,0xc2,0x26,0xc2,0x20,0x90,0x7f,0x9b,0xe0,0xf5} },
+{  16,0x3a0d,0,{0x0a,0x54,0x20,0xf5,0x0a,0x70,0x06,0x90,0x79,0x7e,0xf0,0x80,0x06,0x90,0x79,0x7e} },
+{  16,0x3a1d,0,{0x74,0x01,0xf0,0x90,0x7f,0x9b,0xe0,0xf5,0x0a,0x54,0x02,0xf5,0x0a,0x70,0x06,0x90} },
+{  16,0x3a2d,0,{0x79,0x7f,0xf0,0x80,0x06,0x90,0x79,0x7f,0x74,0x01,0xf0,0x90,0x79,0x78,0x74,0x02} },
+{  16,0x3a3d,0,{0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7f,0xe0,0xb4,0x01,0x09} },
+{  16,0x3a4d,0,{0x90,0x79,0x79,0xe0,0x54,0xfe,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0} },
+{  16,0x3a5d,0,{0x90,0x79,0x79,0xe0,0x90,0x79,0x84,0xf0,0x12,0x0b,0xa2,0x90,0x79,0x78,0x74,0x01} },
+{  16,0x3a6d,0,{0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0x90,0x79,0x7e,0xe0,0xb4,0x01,0x09} },
+{  16,0x3a7d,0,{0x90,0x79,0x79,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0} },
+{  16,0x3a8d,0,{0x90,0x79,0x79,0xe0,0x90,0x79,0x7c,0xf0,0x12,0x0b,0xa2,0xe4,0x90,0x79,0x78,0xf0} },
+{  16,0x3a9d,0,{0xa3,0x04,0xf0,0xe4,0x90,0x79,0x88,0xf0,0x12,0x0b,0xa2,0x90,0x7f,0xfc,0x74,0xdd} },
+{  16,0x3aad,0,{0xf0,0x90,0x7f,0xff,0x74,0xff,0xf0,0x90,0x79,0x78,0x74,0x01,0xf0,0xa3,0xf0,0x12} },
+{  16,0x3abd,0,{0x0b,0xa2,0xe4,0x90,0x79,0x7a,0xf0,0x90,0x79,0x83,0x04,0xf0,0x12,0x2f,0xdf,0xe4} },
+{  16,0x3acd,0,{0x90,0x79,0x30,0xf0,0x90,0x79,0x85,0xf0,0xa3,0xf0,0xa3,0xf0,0x12,0x2e,0x94,0x90} },
+{  16,0x3add,0,{0x79,0x2d,0x74,0x02,0xf0,0x90,0x79,0x88,0x14,0xf0,0xc2,0x2f,0xe4,0x90,0x79,0x68} },
+{  16,0x3aed,0,{0xf0,0x90,0x79,0x8a,0xf0,0x90,0x79,0x6a,0xf0,0xa3,0xf0,0x75,0x13,0x08,0x75,0x14} },
+{  16,0x3afd,0,{0x08,0xf5,0x16,0xf5,0x15,0xf5,0x17,0x90,0x79,0x8c,0xf0,0x90,0x79,0x8b,0xf0,0x22} },
+{  16,0x3b0d,0,{0x7b,0x01,0x7a,0x78,0x79,0x58,0x90,0x78,0x03,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9} },
+{  16,0x3b1d,0,{0xf0,0x74,0x40,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
+{  16,0x3b2d,0,{0xf9,0x90,0x00,0x01,0x74,0x0a,0x12,0x0c,0x9c,0x90,0x00,0x02,0x12,0x0d,0xf6,0x00} },
+{  16,0x3b3d,0,{0x00,0xbb,0x80,0x90,0x00,0x06,0x12,0x0d,0xf6,0x00,0x00,0xac,0x44,0x90,0x00,0x0a} },
+{  16,0x3b4d,0,{0x12,0x0d,0xf6,0x00,0x01,0x77,0x00,0x90,0x78,0x04,0xe4,0x75,0xf0,0x0f,0x12,0x0c} },
+{  16,0x3b5d,0,{0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x40,0x12,0x0c} },
+{  16,0x3b6d,0,{0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74} },
+{  16,0x3b7d,0,{0x8c,0x12,0x0c,0x9c,0x90,0x00,0x02,0x12,0x0d,0xf6,0x00,0x00,0xbb,0x80,0x90,0x00} },
+{  16,0x3b8d,0,{0x06,0x12,0x0d,0xf6,0x00,0x00,0xac,0x44,0x90,0x00,0x0a,0x12,0x0d,0xf6,0x00,0x01} },
+{  16,0x3b9d,0,{0x77,0x00,0x90,0x78,0x04,0xe4,0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0} },
+{  16,0x3bad,0,{0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x40,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0} },
+{  16,0x3bbd,0,{0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x8f,0x12,0x0c,0x9c,0x90} },
+{  16,0x3bcd,0,{0x78,0x04,0xe4,0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0} },
+{  16,0x3bdd,0,{0xfa,0xa3,0xe0,0xf9,0x74,0x41,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0} },
+{  16,0x3bed,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x84,0x12,0x0c,0x9c,0x90,0x78,0x04,0xe4} },
+{  16,0x3bfd,0,{0x75,0xf0,0x0f,0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
+{  16,0x3c0d,0,{0xf9,0x74,0x61,0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0} },
+{  16,0x3c1d,0,{0xf9,0x90,0x00,0x01,0x74,0x81,0x12,0x0c,0x9c,0x90,0x78,0x04,0xe4,0x75,0xf0,0x0f} },
+{  16,0x3c2d,0,{0x12,0x0c,0xf4,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x74,0x61} },
+{  16,0x3c3d,0,{0x12,0x0c,0x8a,0x90,0x78,0x03,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00} },
+{   6,0x3c4d,0,{0x01,0x74,0x01,0x12,0x0c,0x9c} },
+{   1,0x3c53,0,{0x22} },
+{  16,0x3c54,0,{0xc0,0xe0,0xc0,0xf0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0} },
+{  16,0x3c64,0,{0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef} },
+{   2,0x3c74,0,{0xc0,0xe0} },
+{  16,0x3c76,0,{0x90,0x7f,0xa2,0xe0,0xf5,0x0b,0x90,0x7f,0x74,0xe0,0x90,0x79,0x70,0xf0,0x90,0x7f} },
+{  16,0x3c86,0,{0x75,0xe0,0x90,0x79,0x71,0xf0,0x90,0x79,0x83,0xe0,0xff,0xfe,0x54,0x02,0xfe,0x70} },
+{  16,0x3c96,0,{0x0d,0xef,0x44,0x02,0xf0,0x12,0x2f,0xdf,0x90,0x79,0x74,0x74,0x01,0xf0,0xe5,0x0b} },
+{  16,0x3ca6,0,{0x20,0xe2,0x28,0x90,0x79,0x70,0xe0,0xfe,0xa3,0xe0,0x7c,0x00,0x24,0x00,0xf5,0x11} },
+{  16,0x3cb6,0,{0xec,0x3e,0xf5,0x10,0x90,0x79,0x82,0xe0,0xfd,0xae,0x10,0xaf,0x11,0x12,0x0c,0xbe} },
+{  16,0x3cc6,0,{0x90,0x79,0x70,0xef,0xf0,0x90,0x79,0x89,0x74,0x01,0xf0,0x12,0x48,0x43,0x12,0x48} },
+{  16,0x3cd6,0,{0x76,0x90,0x79,0x89,0xe0,0x64,0x01,0x70,0x32,0x12,0x41,0x08,0x90,0x79,0x89,0xe4} },
+{  16,0x3ce6,0,{0xf0,0x90,0x7f,0x98,0xe0,0x44,0x40,0xf0,0x90,0x7f,0x9e,0xe0,0x44,0x40,0xf0,0x90} },
+{  16,0x3cf6,0,{0x7f,0x95,0x74,0x80,0xf0,0x75,0xe8,0x01,0x12,0x09,0x32,0x75,0xe8,0x0d,0x90,0x7f} },
+{  16,0x3d06,0,{0x95,0x74,0xc0,0xf0,0x75,0xe8,0x0d,0xd2,0x20,0x80,0x05,0x75,0xe8,0x01,0xc2,0x20} },
+{  16,0x3d16,0,{0x20,0x20,0x2b,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0x75,0x0c,0x67,0x75,0x0d} },
+{  16,0x3d26,0,{0x06,0x75,0x0e,0x0b,0xef,0xb4,0x02,0x09,0x75,0x0c,0x00,0x75,0x0d,0x00,0x75,0x0e} },
+{  16,0x3d36,0,{0x0c,0xef,0xb4,0x03,0x09,0x75,0x0c,0x00,0x75,0x0d,0x00,0x75,0x0e,0x18,0x75,0xca} },
+{  16,0x3d46,0,{0x6f,0x75,0xcb,0xfe,0xd2,0xca,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x02,0xf0,0xf0} },
+{  16,0x3d56,0,{0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0,0xfc,0xd0,0xe0,0xfb,0xd0} },
+{  16,0x3d66,0,{0xe0,0xfa,0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0,0x82,0xd0,0x83,0xd0,0xf0} },
+{   3,0x3d76,0,{0xd0,0xe0,0x32} },
+{  16,0x3d79,0,{0x75,0x33,0x25,0x75,0x34,0x24,0x90,0x79,0x5c,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0} },
+{  16,0x3d89,0,{0xa3,0x74,0xb2,0xf0,0x20,0x2f,0x02,0xc1,0x17,0xe4,0xf5,0x35,0x75,0x22,0x01,0x90} },
+{  16,0x3d99,0,{0x79,0x5c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x04,0x12,0x0c,0x5d} },
+{  16,0x3da9,0,{0xf5,0x36,0x75,0x35,0x06,0x74,0x42,0x25,0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83} },
+{  16,0x3db9,0,{0xe5,0x36,0xf0,0x05,0x35,0xe5,0x35,0xb4,0x0c,0xeb,0xe5,0x35,0xc3,0x94,0x0d,0x40} },
+{  16,0x3dc9,0,{0x02,0xc1,0x98,0xe5,0x22,0x64,0x01,0x60,0x02,0xc1,0x98,0x90,0x7f,0xa5,0xe0,0x44} },
+{  16,0x3dd9,0,{0x80,0xf0,0x90,0x7f,0xa6,0xe5,0x33,0xf0,0x12,0x46,0xc0,0x74,0x4f,0x25,0x35,0xf5} },
+{  16,0x3de9,0,{0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x74,0x42} },
+{  16,0x3df9,0,{0x25,0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46} },
+{  16,0x3e09,0,{0xc0,0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd,0x05,0x35,0x80,0xac,0xe4,0xf5} },
+{  16,0x3e19,0,{0x35,0x75,0x22,0x01,0x90,0x79,0x5c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
+{  16,0x3e29,0,{0x00,0x04,0x12,0x0c,0x5d,0xf5,0x36,0x75,0x35,0x06,0x74,0x35,0x25,0x35,0xf5,0x82} },
+{  16,0x3e39,0,{0xe4,0x34,0x79,0xf5,0x83,0xe5,0x36,0xf0,0x05,0x35,0xe5,0x35,0xb4,0x0c,0xeb,0xe5} },
+{  16,0x3e49,0,{0x35,0xc3,0x94,0x0d,0x50,0x49,0xe5,0x22,0x64,0x01,0x70,0x43,0x90,0x7f,0xa5,0xe0} },
+{  16,0x3e59,0,{0x44,0x80,0xf0,0x90,0x7f,0xa6,0xe5,0x33,0xf0,0x12,0x46,0xc0,0x74,0x4f,0x25,0x35} },
+{  16,0x3e69,0,{0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12,0x46,0xc0,0x74} },
+{  16,0x3e79,0,{0x35,0x25,0x35,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xe0,0x90,0x7f,0xa6,0xf0,0x12} },
+{  15,0x3e89,0,{0x46,0xc0,0x90,0x7f,0xa5,0x74,0x40,0xf0,0x12,0x0a,0xcd,0x05,0x35,0x80,0xb0} },
+{   1,0x3e98,0,{0x22} },
+{  16,0x3e99,0,{0x90,0x78,0x09,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0xb2,0xf0,0xe4,0xff} },
+{  16,0x3ea9,0,{0xfe,0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xef,0x12,0x0c,0x8a} },
+{  16,0x3eb9,0,{0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0xe4,0x12} },
+{  16,0x3ec9,0,{0x0c,0x9c,0x90,0x00,0x02,0x74,0x15,0x12,0x0c,0x9c,0x90,0x00,0x03,0xe4,0x12,0x0c} },
+{  16,0x3ed9,0,{0x9c,0x90,0x00,0x04,0x74,0xff,0x12,0x0c,0x9c,0x90,0x00,0x05,0xe4,0x12,0x0c,0x9c} },
+{  16,0x3ee9,0,{0x90,0x00,0x06,0x74,0xc3,0x12,0x0c,0x9c,0x90,0x00,0x07,0xe4,0x12,0x0c,0x9c,0x90} },
+{  16,0x3ef9,0,{0x00,0x08,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x09,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x0a} },
+{  16,0x3f09,0,{0x74,0x01,0x12,0x0c,0x9c,0x90,0x78,0x0a,0xe4,0x75,0xf0,0x0b,0x12,0x0c,0xf4,0x0f} },
+{  16,0x3f19,0,{0x0e,0xbe,0x07,0x8d,0x90,0x78,0x09,0x74,0x01,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74} },
+{  16,0x3f29,0,{0xff,0xf0,0xe4,0xff,0xfe,0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
+{  16,0x3f39,0,{0xef,0x12,0x0c,0x8a,0x90,0x78,0x09,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90} },
+{  16,0x3f49,0,{0x00,0x01,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x02,0x74,0x15,0x12,0x0c,0x9c,0x90,0x00} },
+{  16,0x3f59,0,{0x03,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x04,0x74,0x80,0x12,0x0c,0x9c,0x90,0x00,0x05} },
+{  16,0x3f69,0,{0xe4,0x12,0x0c,0x9c,0x90,0x00,0x06,0x74,0xc3,0x12,0x0c,0x9c,0x90,0x00,0x07,0xe4} },
+{  16,0x3f79,0,{0x12,0x0c,0x9c,0x90,0x00,0x08,0xe4,0x12,0x0c,0x9c,0x90,0x00,0x09,0xe4,0x12,0x0c} },
+{  16,0x3f89,0,{0x9c,0x90,0x00,0x0a,0x74,0x01,0x12,0x0c,0x9c,0x90,0x78,0x0a,0xe4,0x75,0xf0,0x0b} },
+{   8,0x3f99,0,{0x12,0x0c,0xf4,0x0f,0x0e,0xbe,0x03,0x8d} },
+{   1,0x3fa1,0,{0x22} },
+{  16,0x3fa2,0,{0xe4,0xfe,0x75,0x3d,0xff,0x75,0x3e,0x05,0x75,0x3f,0x12,0xab,0x3d,0xaa,0x3e,0xa9} },
+{  16,0x3fb2,0,{0x3f,0x90,0x00,0x01,0x12,0x0c,0x5d,0x64,0x02,0x70,0x2f,0xcd,0xee,0xcd,0x0e,0xed} },
+{  16,0x3fc2,0,{0x6f,0x70,0x01,0x22,0x90,0x00,0x02,0x12,0x0d,0x0a,0x85,0xf0,0x3b,0xf5,0x3c,0x62} },
+{  16,0x3fd2,0,{0x3b,0xe5,0x3b,0x62,0x3c,0xe5,0x3c,0x62,0x3b,0x29,0xfd,0xe5,0x3b,0x3a,0xc9,0xed} },
+{  16,0x3fe2,0,{0xc9,0x75,0x3d,0xff,0xf5,0x3e,0x89,0x3f,0x80,0xc1,0x7b,0x00,0x7a,0x00,0x79,0x00} },
+{   1,0x3ff2,0,{0x22} },
+{   9,0x3ff3,0,{0x53,0xd8,0xef,0x43,0xd8,0x20,0xc2,0x2d,0x32} },
+{   4,0x3ffc,0,{0x53,0x91,0xdf,0x32} },
+{  16,0x4000,0,{0x90,0x79,0x87,0xe0,0xb4,0x01,0x1d,0x90,0x79,0x85,0xe0,0xb4,0x01,0x03,0x12,0x42} },
+{  16,0x4010,0,{0xaa,0x90,0x79,0x86,0xe0,0xb4,0x01,0x03,0x12,0x18,0x00,0xe4,0x90,0x79,0x85,0xf0} },
+{  16,0x4020,0,{0xa3,0xf0,0xa3,0xf0,0x12,0x2e,0x94,0x90,0x7f,0x9b,0xe0,0xf5,0x0a,0x54,0x02,0xf5} },
+{  16,0x4030,0,{0x0a,0x70,0x04,0x90,0x79,0x7f,0xf0,0x90,0x7f,0x9b,0xe0,0xf5,0x0a,0x54,0x02,0xff} },
+{  16,0x4040,0,{0xf5,0x0a,0xbf,0x02,0x06,0x90,0x79,0x7f,0x74,0x01,0xf0,0x90,0x7f,0x9b,0xe0,0xf5} },
+{  16,0x4050,0,{0x0a,0x54,0x20,0xf5,0x0a,0x70,0x04,0x90,0x79,0x7e,0xf0,0x90,0x7f,0x9b,0xe0,0xf5} },
+{  16,0x4060,0,{0x0a,0x54,0x20,0xff,0xf5,0x0a,0xbf,0x20,0x06,0x90,0x79,0x7e,0x74,0x01,0xf0,0x90} },
+{  16,0x4070,0,{0x79,0x7f,0xe0,0xff,0x90,0x79,0x81,0xe0,0x6f,0x60,0x38,0x90,0x79,0x78,0x74,0x02} },
+{  16,0x4080,0,{0xf0,0x90,0x79,0x84,0xe0,0x90,0x79,0x79,0xf0,0xef,0xb4,0x01,0x06,0xe0,0x54,0xfe} },
+{  16,0x4090,0,{0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x44,0x01,0xf0,0x90,0x79,0x79,0xe0,0x90,0x79} },
+{  16,0x40a0,0,{0x84,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0xe5,0x12,0x60} },
+{  16,0x40b0,0,{0x02,0xd2,0xaf,0x90,0x79,0x7e,0xe0,0xff,0x90,0x79,0x80,0xe0,0x6f,0x60,0x38,0x90} },
+{  16,0x40c0,0,{0x79,0x78,0x74,0x01,0xf0,0x90,0x79,0x7c,0xe0,0x90,0x79,0x79,0xf0,0xef,0xb4,0x01} },
+{  16,0x40d0,0,{0x06,0xe0,0x44,0x04,0xf0,0x80,0x07,0x90,0x79,0x79,0xe0,0x54,0xfb,0xf0,0x90,0x79} },
+{  16,0x40e0,0,{0x79,0xe0,0x90,0x79,0x7c,0xf0,0xa2,0xaf,0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b} },
+{  16,0x40f0,0,{0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x90,0x79,0x7f,0xe0,0x90,0x79,0x81,0xf0,0x90} },
+{   8,0x4100,0,{0x79,0x7e,0xe0,0x90,0x79,0x80,0xf0,0x22} },
+{  16,0x4108,0,{0x90,0x79,0x2d,0xe0,0x64,0x01,0x70,0x35,0x90,0x79,0x70,0xe0,0xff,0xd3,0x94,0x2d} },
+{  16,0x4118,0,{0x40,0x2b,0x90,0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0,0xe0,0xd3} },
+{  16,0x4128,0,{0x94,0x0f,0x40,0x19,0xe4,0xf0,0xef,0xd3,0x94,0x31,0x40,0x08,0x90,0x79,0x2d,0x74} },
+{  16,0x4138,0,{0x03,0xf0,0x80,0x06,0x90,0x79,0x2d,0x74,0x02,0xf0,0x12,0x10,0x00,0x90,0x79,0x2d} },
+{  16,0x4148,0,{0xe0,0xb4,0x02,0x2c,0x90,0x79,0x70,0xe0,0xff,0xc3,0x94,0x2f,0x50,0x22,0xef,0xd3} },
+{  16,0x4158,0,{0x94,0x2a,0x40,0x1c,0x90,0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0} },
+{  16,0x4168,0,{0xe0,0xd3,0x94,0x0f,0x40,0x0a,0xe4,0xf0,0x90,0x79,0x2d,0x04,0xf0,0x12,0x10,0x00} },
+{  16,0x4178,0,{0x90,0x79,0x2d,0xe0,0xb4,0x02,0x26,0x90,0x79,0x70,0xe0,0xd3,0x94,0x31,0x40,0x1d} },
+{  16,0x4188,0,{0x90,0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0,0xe0,0xd3,0x94,0x0f} },
+{  16,0x4198,0,{0x40,0x0b,0xe4,0xf0,0x90,0x79,0x2d,0x74,0x03,0xf0,0x12,0x10,0x00,0x90,0x79,0x2d} },
+{  16,0x41a8,0,{0xe0,0x64,0x03,0x70,0x3f,0x90,0x79,0x70,0xe0,0xff,0xc3,0x94,0x5f,0x50,0x35,0x90} },
+{  16,0x41b8,0,{0x79,0x69,0x74,0x01,0xf0,0x90,0x79,0x68,0xe0,0x04,0xf0,0xe0,0xd3,0x94,0x0f,0x40} },
+{  16,0x41c8,0,{0x23,0xe4,0xf0,0xef,0xc3,0x94,0x2f,0x50,0x0c,0xef,0xd3,0x94,0x2a,0x40,0x06,0x90} },
+{  16,0x41d8,0,{0x79,0x2d,0x74,0x01,0xf0,0xef,0xd3,0x94,0x2f,0x40,0x06,0x90,0x79,0x2d,0x74,0x02} },
+{  16,0x41e8,0,{0xf0,0x12,0x10,0x00,0x90,0x79,0x69,0xe0,0x70,0x05,0x90,0x79,0x68,0xf0,0x22,0xe4} },
+{   5,0x41f8,0,{0x90,0x79,0x69,0xf0,0x22} },
+{  16,0x41fd,0,{0x7b,0x01,0x7a,0x78,0x79,0x4c,0x90,0x78,0x06,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9} },
+{  16,0x420d,0,{0xf0,0xe4,0x12,0x0c,0x8a,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9} },
+{  16,0x421d,0,{0x90,0x00,0x01,0x74,0x01,0x12,0x0c,0x9c,0x90,0x78,0x07,0xe4,0x75,0xf0,0x03,0x12} },
+{  16,0x422d,0,{0x0c,0xf4,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xe4,0x12,0x0c} },
+{  16,0x423d,0,{0x8a,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74} },
+{  16,0x424d,0,{0x02,0x12,0x0c,0x9c,0x90,0x78,0x07,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78} },
+{  16,0x425d,0,{0x06,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xe4,0x12,0x0c,0x8a,0x90,0x78,0x06} },
+{  16,0x426d,0,{0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x03,0x12,0x0c,0x9c} },
+{  16,0x427d,0,{0x90,0x78,0x07,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x90,0x78,0x06,0xe0,0xfb,0xa3} },
+{  16,0x428d,0,{0xe0,0xfa,0xa3,0xe0,0xf9,0xe4,0x12,0x0c,0x8a,0x90,0x78,0x06,0xe0,0xfb,0xa3,0xe0} },
+{  12,0x429d,0,{0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x74,0x04,0x12,0x0c,0x9c} },
+{   1,0x42a9,0,{0x22} },
+{  16,0x42aa,0,{0xe4,0xff,0xfe,0x7b,0x01,0x90,0x78,0x0c,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74} },
+{  16,0x42ba,0,{0x2b,0xf0,0x90,0x78,0x0c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02} },
+{  16,0x42ca,0,{0x12,0x0c,0x5d,0xfd,0x90,0x79,0x9a,0xe0,0x6d,0x60,0x13,0xef,0xc3,0x94,0x05,0x50} },
+{  16,0x42da,0,{0x0d,0x0f,0x90,0x78,0x0d,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd4,0x8d,0x33} },
+{  16,0x42ea,0,{0x90,0x78,0x0c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x01,0x12,0x0c} },
+{  16,0x42fa,0,{0x5d,0xfd,0x90,0x79,0x9b,0xe0,0xfc,0x6d,0x60,0x13,0xee,0xc3,0x94,0x0b,0x50,0x0d} },
+{  16,0x430a,0,{0x0e,0x90,0x78,0x0d,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x80,0xd3,0x8c,0x34,0xef} },
+{  16,0x431a,0,{0x64,0x05,0x60,0x03,0xbe,0x0b,0x08,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90} },
+{  16,0x432a,0,{0x78,0x0c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x12,0x0c,0x44,0xff,0x24,0xf0} },
+{  16,0x433a,0,{0x60,0x08,0x24,0x0e,0x70,0x0e,0x12,0x49,0x4d,0x22,0x90,0x79,0x20,0xe5,0x34,0xf0} },
+{  11,0x434a,0,{0x12,0x1b,0x2a,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0} },
+{   1,0x4355,0,{0x22} },
+{  12,0x4356,0,{0x78,0x7f,0xe4,0xf6,0xd8,0xfd,0x75,0x81,0x3f,0x02,0x43,0x9d} },
+{  16,0x4362,0,{0x02,0x48,0xa9,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0x40,0x03,0xf6,0x80,0x01,0xf2} },
+{  16,0x4372,0,{0x08,0xdf,0xf4,0x80,0x29,0xe4,0x93,0xa3,0xf8,0x54,0x07,0x24,0x0c,0xc8,0xc3,0x33} },
+{  16,0x4382,0,{0xc4,0x54,0x0f,0x44,0x20,0xc8,0x83,0x40,0x04,0xf4,0x56,0x80,0x01,0x46,0xf6,0xdf} },
+{  16,0x4392,0,{0xe4,0x80,0x0b,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x90,0x46,0x61,0xe4,0x7e} },
+{  16,0x43a2,0,{0x01,0x93,0x60,0xbc,0xa3,0xff,0x54,0x3f,0x30,0xe5,0x09,0x54,0x1f,0xfe,0xe4,0x93} },
+{  16,0x43b2,0,{0xa3,0x60,0x01,0x0e,0xcf,0x54,0xc0,0x25,0xe0,0x60,0xa8,0x40,0xb8,0xe4,0x93,0xa3} },
+{  16,0x43c2,0,{0xfa,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca} },
+{  16,0x43d2,0,{0xf0,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca,0xdf,0xe9,0xde,0xe7,0x80,0xbe} },
+{  16,0x43e2,0,{0xc0,0xe0,0xc0,0xf0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0} },
+{  16,0x43f2,0,{0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef} },
+{  16,0x4402,0,{0xc0,0xe0,0xc2,0xca,0xc2,0xcf,0x90,0x79,0x7a,0xe0,0xb4,0x01,0x1f,0x12,0x4b,0xae} },
+{  16,0x4412,0,{0x12,0x47,0x58,0x53,0xa8,0xa0,0x90,0x7f,0xae,0xe4,0xf0,0x12,0x07,0xaa,0x12,0x4b} },
+{  16,0x4422,0,{0xb7,0x90,0x7f,0xae,0x74,0x1f,0xf0,0x43,0xa8,0x05,0x80,0x03,0x53,0xa8,0xa0,0x53} },
+{  16,0x4432,0,{0xa8,0xfa,0x75,0xe8,0x01,0x12,0x09,0x15,0x75,0xe8,0x0d,0x43,0xa8,0x05,0xd0,0xe0} },
+{  16,0x4442,0,{0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0,0xfc,0xd0,0xe0,0xfb,0xd0,0xe0,0xfa} },
+{  16,0x4452,0,{0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0,0x82,0xd0,0x83,0xd0,0xf0,0xd0,0xe0} },
+{   1,0x4462,0,{0x32} },
+{  16,0x4463,0,{0x90,0x7f,0xec,0xe0,0xf5,0x09,0x14,0x60,0x1d,0x14,0x60,0x2a,0x14,0x60,0x37,0x14} },
+{  16,0x4473,0,{0x60,0x44,0x24,0x04,0x70,0x50,0x90,0x79,0x62,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
+{  16,0x4483,0,{0xb5,0x74,0x01,0xf0,0x80,0x47,0x90,0x79,0x63,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
+{  16,0x4493,0,{0xb5,0x74,0x01,0xf0,0x80,0x37,0x90,0x79,0x64,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
+{  16,0x44a3,0,{0xb5,0x74,0x01,0xf0,0x80,0x27,0x90,0x79,0x66,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
+{  16,0x44b3,0,{0xb5,0x74,0x01,0xf0,0x80,0x17,0x90,0x79,0x67,0xe0,0x90,0x7f,0x00,0xf0,0x90,0x7f} },
+{  15,0x44c3,0,{0xb5,0x74,0x01,0xf0,0x80,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0xd3,0x22} },
+{   4,0x44d2,0,{0x8d,0x36,0x8b,0x37} },
+{  16,0x44d6,0,{0x12,0x3f,0xa2,0xea,0x49,0x60,0x57,0x12,0x0c,0x44,0x7e,0x00,0x29,0xff,0xee,0x3a} },
+{  16,0x44e6,0,{0xc9,0xef,0xc9,0x75,0x38,0xff,0xf5,0x39,0x89,0x3a,0xab,0x38,0xaa,0x39,0xa9,0x3a} },
+{  16,0x44f6,0,{0x90,0x00,0x01,0x12,0x0c,0x5d,0xff,0x64,0x04,0x60,0x05,0xef,0x64,0x05,0x70,0x2e} },
+{  16,0x4506,0,{0xef,0xb4,0x04,0x15,0x90,0x00,0x02,0x12,0x0c,0x5d,0x65,0x36,0x70,0x0b,0x90,0x00} },
+{  16,0x4516,0,{0x03,0x12,0x0c,0x5d,0x65,0x37,0x70,0x01,0x22,0x12,0x0c,0x44,0x7e,0x00,0x29,0xff} },
+{  16,0x4526,0,{0xee,0x3a,0xc9,0xef,0xc9,0x75,0x38,0xff,0xf5,0x39,0x89,0x3a,0x80,0xbc,0x7b,0x00} },
+{   4,0x4536,0,{0x7a,0x00,0x79,0x00} },
+{   1,0x453a,0,{0x22} },
+{  16,0x453b,0,{0xe4,0xff,0x7b,0x01,0x90,0x78,0x1c,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0x4c} },
+{  16,0x454b,0,{0xf0,0x90,0x78,0x1c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12} },
+{  16,0x455b,0,{0x0c,0x5d,0xfe,0x90,0x7f,0xec,0xe0,0x6e,0x60,0x13,0xef,0xc3,0x94,0x04,0x50,0x0d} },
+{  16,0x456b,0,{0x90,0x78,0x1d,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x0f,0x80,0xd4,0xbf,0x04,0x09} },
+{  16,0x457b,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x80,0x14,0x90,0x79,0x21,0xe0,0xff,0x90,0x78} },
+{  16,0x458b,0,{0x1c,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0xef,0x12,0x0c,0x8a,0x90,0x7f,0xc5} },
+{   3,0x459b,0,{0x74,0x01,0xf0} },
+{   1,0x459e,0,{0x22} },
+{  14,0x459f,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xc0,0xd0,0xee,0xc0,0xe0,0xef,0xc0,0xe0} },
+{  16,0x45ad,0,{0x90,0x79,0x85,0xe0,0x64,0x01,0x60,0x05,0xa3,0xe0,0xb4,0x01,0x2d,0x90,0x79,0x87} },
+{  16,0x45bd,0,{0x74,0x01,0xf0,0xe4,0xff,0x90,0x7f,0xc5,0xe0,0xfe,0xef,0xc3,0x9e,0x50,0x1b,0x74} },
+{  16,0x45cd,0,{0xc0,0x2f,0xf5,0x82,0xe4,0x34,0x7e,0xf5,0x83,0xe0,0xfe,0x74,0x21,0x2f,0xf5,0x82} },
+{  16,0x45dd,0,{0xe4,0x34,0x79,0xf5,0x83,0xee,0xf0,0x0f,0x80,0xdb,0x53,0x91,0xef,0x90,0x7f,0xaa} },
+{   4,0x45ed,0,{0xe0,0x44,0x01,0xf0} },
+{  15,0x45f1,0,{0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xd0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4600,0,{0xe4,0xff,0x7b,0x01,0x90,0x78,0x19,0x04,0xf0,0xa3,0x74,0x78,0xf0,0xa3,0x74,0x4c} },
+{  16,0x4610,0,{0xf0,0x90,0x78,0x19,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,0xf9,0x90,0x00,0x02,0x12} },
+{  16,0x4620,0,{0x0c,0x5d,0xfe,0x90,0x7f,0xec,0xe0,0x6e,0x60,0x13,0xef,0xc3,0x94,0x04,0x50,0x0d} },
+{  16,0x4630,0,{0x90,0x78,0x1a,0xe4,0x75,0xf0,0x03,0x12,0x0c,0xf4,0x0f,0x80,0xd4,0xbf,0x04,0x08} },
+{  16,0x4640,0,{0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x78,0x19,0xe0,0xfb,0xa3,0xe0,0xfa} },
+{  16,0x4650,0,{0xa3,0xe0,0xf9,0x12,0x0c,0x44,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} },
+{   1,0x4660,0,{0x22} },
+{  16,0x4661,0,{0x01,0x18,0x02,0x01,0x19,0x0a,0x01,0x1c,0x00,0xc1,0x28,0xc1,0x29,0x01,0x1f,0x01} },
+{  15,0x4671,0,{0x44,0x79,0x9f,0x00,0x00,0x00,0x00,0x41,0x79,0xa3,0x00,0x41,0x79,0xa4,0x00} },
+{   4,0x4680,0,{0x41,0x79,0x89,0x00} },
+{  16,0x4684,0,{0x01,0x22,0x01,0x41,0x79,0x31,0xff,0x41,0x79,0x34,0x00,0x4d,0x79,0x35,0x3f,0x3f} },
+{  16,0x4694,0,{0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x4d,0x79,0x42,0x3f,0x3f} },
+{  16,0x46a4,0,{0x06,0x08,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x4d,0x79,0x4f,0x0a,0x0a} },
+{  11,0x46b4,0,{0x09,0x00,0x01,0x09,0x02,0x03,0x04,0x05,0x06,0x07,0x08} },
+{   1,0x46bf,0,{0x00} },
+{  16,0x46c0,0,{0x12,0x0a,0xcd,0x90,0x7f,0xa5,0xe0,0xf5,0x21,0xe5,0x21,0x54,0x01,0xf5,0x21,0x64} },
+{  16,0x46d0,0,{0x01,0x60,0x28,0xe5,0x22,0x64,0x01,0x70,0x22,0x90,0x7f,0xa5,0xe0,0xf5,0x21,0x54} },
+{  16,0x46e0,0,{0x02,0xf5,0x21,0x70,0x03,0x75,0x22,0x01,0x90,0x7f,0xa5,0xe0,0xf5,0x21,0x54,0x04} },
+{  12,0x46f0,0,{0xff,0xf5,0x21,0xbf,0x04,0xd3,0x75,0x22,0x01,0x80,0xce,0x22} },
+{   4,0x46fc,0,{0x53,0xd8,0xf7,0x32} },
+{  16,0x4700,0,{0x02,0x49,0xfa,0x00,0x02,0x3c,0x54,0x00,0x02,0x17,0xe4,0x00,0x02,0x4a,0x12,0x00} },
+{  16,0x4710,0,{0x02,0x37,0xa2,0x00,0x02,0x47,0xff,0x00,0x02,0x4a,0x41,0x00,0x02,0x45,0x9f,0x00} },
+{  16,0x4720,0,{0x02,0x49,0x8e,0x00,0x02,0x49,0xab,0x00,0x02,0x4a,0x58,0x00,0x02,0x4a,0x6f,0x00} },
+{  16,0x4730,0,{0x02,0x4a,0x86,0x00,0x02,0x4a,0x9d,0x00,0x02,0x4a,0xb4,0x00,0x02,0x4a,0xcb,0x00} },
+{  16,0x4740,0,{0x02,0x4a,0xe2,0x00,0x02,0x4a,0xf9,0x00,0x02,0x4b,0x10,0x00,0x02,0x4b,0x27,0x00} },
+{   8,0x4750,0,{0x02,0x4b,0x3e,0x00,0x02,0x4b,0x55,0x00} },
+{  16,0x4758,0,{0xe5,0x18,0x70,0x14,0x90,0x79,0x8c,0xe0,0x04,0xf0,0x90,0x79,0x8b,0xe0,0xc3,0x94} },
+{  16,0x4768,0,{0x00,0x40,0x15,0xe0,0x14,0xf0,0x80,0x10,0x90,0x79,0x8b,0xe0,0x04,0xf0,0xa3,0xe0} },
+{  16,0x4778,0,{0xc3,0x94,0x00,0x40,0x03,0xe0,0x14,0xf0,0x90,0x79,0x8b,0xe0,0xd3,0x94,0x14,0x40} },
+{  16,0x4788,0,{0x04,0xe4,0xf5,0x18,0xf0,0x90,0x79,0x8c,0xe0,0xd3,0x94,0x14,0x40,0x05,0x75,0x18} },
+{   4,0x4798,0,{0x01,0xe4,0xf0,0x22} },
+{  16,0x479c,0,{0x90,0x7f,0xd7,0xe0,0xf5,0x33,0x90,0x7f,0xec,0xe0,0xf5,0x09,0x14,0x60,0x11,0x14} },
+{  16,0x47ac,0,{0x60,0x1b,0x24,0x02,0x70,0x24,0x90,0x7f,0xea,0xe0,0x90,0x79,0x62,0xf0,0x80,0x21} },
+{  16,0x47bc,0,{0x90,0x7f,0xea,0xe0,0x90,0x79,0x63,0xf0,0x12,0x10,0x00,0x80,0x14,0x90,0x7f,0xea} },
+{  16,0x47cc,0,{0xe0,0x90,0x79,0x64,0xf0,0x12,0x28,0x01,0x80,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
+{   2,0x47dc,0,{0xf0,0xd3} },
+{   1,0x47de,0,{0x22} },
+{  16,0x47df,0,{0x90,0x79,0x78,0x74,0x04,0xf0,0x90,0x79,0x33,0xe0,0x90,0x79,0x79,0xf0,0xa2,0xaf} },
+{  16,0x47ef,0,{0xe4,0x33,0xf5,0x12,0xc2,0xaf,0x12,0x0b,0xa2,0xe5,0x12,0x60,0x02,0xd2,0xaf,0x22} },
+{   1,0x47ff,0,{0x32} },
+{   2,0x4800,0,{0x8f,0x36} },
+{  16,0x4802,0,{0xe4,0xf5,0x37,0x75,0x38,0xff,0x75,0x39,0x07,0x75,0x3a,0x01,0xab,0x38,0xaa,0x39} },
+{  16,0x4812,0,{0xa9,0x3a,0x90,0x00,0x01,0x12,0x0c,0x5d,0xb4,0x03,0x1f,0xaf,0x37,0x05,0x37,0xef} },
+{  16,0x4822,0,{0x65,0x36,0x70,0x01,0x22,0x12,0x0c,0x44,0x7e,0x00,0x29,0xff,0xee,0x3a,0xc9,0xef} },
+{  16,0x4832,0,{0xc9,0x75,0x38,0xff,0xf5,0x39,0x89,0x3a,0x80,0xd2,0x7b,0x00,0x7a,0x00,0x79,0x00} },
+{   1,0x4842,0,{0x22} },
+{  16,0x4843,0,{0x30,0x26,0x2f,0xc2,0x26,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0xe4,0xf5,0x0c} },
+{  16,0x4853,0,{0x75,0x0d,0xf8,0x75,0x0e,0x0a,0xef,0xb4,0x02,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0xf0} },
+{  16,0x4863,0,{0x75,0x0e,0x0b,0xef,0xb4,0x03,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0xf8,0x75,0x0e,0x17} },
+{   3,0x4873,0,{0xd2,0x22,0x22} },
+{  16,0x4876,0,{0x30,0x25,0x2f,0xc2,0x25,0x90,0x79,0x2d,0xe0,0xff,0xb4,0x01,0x09,0x75,0x0c,0xc0} },
+{  16,0x4886,0,{0x75,0x0d,0x14,0x75,0x0e,0x0b,0xef,0xb4,0x02,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0x10} },
+{  16,0x4896,0,{0x75,0x0e,0x0c,0xef,0xb4,0x03,0x09,0xe4,0xf5,0x0c,0x75,0x0d,0x18,0x75,0x0e,0x18} },
+{   3,0x48a6,0,{0xd2,0x22,0x22} },
+{  16,0x48a9,0,{0xe4,0xf5,0x32,0x12,0x0f,0x50,0x20,0x2e,0x10,0xe5,0x32,0xc3,0x94,0x02,0x50,0x09} },
+{  16,0x48b9,0,{0x05,0x32,0xd2,0x30,0x12,0x49,0x05,0x80,0xed,0x30,0x2e,0x05,0x12,0x14,0x57,0xc2} },
+{  15,0x48c9,0,{0x2e,0x30,0x2d,0x06,0x12,0x07,0x9a,0x12,0x48,0xd9,0x12,0x40,0x00,0x80,0xea} },
+{   1,0x48d8,0,{0x22} },
+{  16,0x48d9,0,{0x90,0x7f,0xd6,0xe0,0xf5,0x1d,0x54,0x80,0xf5,0x1d,0x64,0x80,0x70,0x1d,0xc2,0xaf} },
+{  16,0x48e9,0,{0xe0,0x44,0x80,0xf0,0xe0,0x44,0x01,0xf0,0x7f,0x0c,0x7e,0x00,0x12,0x4b,0x6c,0x90} },
+{  12,0x48f9,0,{0x7f,0xd6,0xe0,0x54,0xfe,0xf0,0x53,0x87,0xfe,0xd2,0xaf,0x22} },
+{  16,0x4905,0,{0x90,0x7f,0xd6,0xe0,0x54,0xfb,0xf0,0xe0,0x44,0x08,0xf0,0x30,0x30,0x04,0xe0,0x44} },
+{  16,0x4915,0,{0x02,0xf0,0x7f,0xdc,0x7e,0x05,0x12,0x4b,0x6c,0x90,0x7f,0xd6,0xe0,0x54,0xf7,0xf0} },
+{   5,0x4925,0,{0xe0,0x44,0x04,0xf0,0x22} },
+{  16,0x492a,0,{0x90,0x7f,0xeb,0xe0,0x14,0x70,0x14,0x90,0x7f,0xe9,0xe0,0x24,0x7f,0x70,0x04,0x12} },
+{  16,0x493a,0,{0x46,0x00,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44} },
+{   3,0x494a,0,{0x01,0xf0,0x22} },
+{  16,0x494d,0,{0x90,0x7f,0xeb,0xe0,0x14,0x70,0x13,0x90,0x7f,0xe9,0xe0,0x14,0x70,0x04,0x12,0x45} },
+{  16,0x495d,0,{0x3b,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x22,0x90,0x7f,0xb4,0xe0,0x44,0x01} },
+{   2,0x496d,0,{0xf0,0x22} },
+{  16,0x496f,0,{0xe4,0xff,0x74,0xe8,0x2f,0xf5,0x82,0xe4,0x34,0x7f,0xf5,0x83,0xe0,0xfe,0x74,0x96} },
+{  14,0x497f,0,{0x2f,0xf5,0x82,0xe4,0x34,0x79,0xf5,0x83,0xee,0xf0,0x0f,0xbf,0x08,0xe4} },
+{   1,0x498d,0,{0x22} },
+{  16,0x498e,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x02,0xf0} },
+{  13,0x499e,0,{0x90,0x7f,0xb7,0x74,0x03,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x49ab,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x02,0xf0} },
+{  13,0x49bb,0,{0x90,0x7f,0xc7,0x74,0x03,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x49c8,0,{0x90,0x7f,0xd6,0xe0,0x30,0xe7,0x12,0xe0,0x44,0x01,0xf0,0x7f,0x14,0x7e,0x00,0x12} },
+{  10,0x49d8,0,{0x4b,0x6c,0x90,0x7f,0xd6,0xe0,0x54,0xfe,0xf0,0x22} },
+{  16,0x49e2,0,{0xe4,0xf5,0x1a,0x75,0x1b,0x01,0x90,0x79,0x91,0x04,0xf0,0xa3,0xf0,0xe4,0xa3,0xf0} },
+{   8,0x49f2,0,{0xa3,0x74,0x0a,0xf0,0xe4,0xa3,0xf0,0x22} },
+{  16,0x49fa,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xd2,0x2e,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x01} },
+{   8,0x4a0a,0,{0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4a12,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xd2,0x2d,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x08} },
+{   8,0x4a22,0,{0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4a2a,0,{0x90,0x7f,0xea,0xe0,0xf5,0x08,0xe4,0x90,0x79,0x62,0xf0,0xa3,0xf0,0xa3,0xf0,0x90} },
+{   7,0x4a3a,0,{0x79,0x66,0xf0,0xa3,0xf0,0xd3,0x22} },
+{  16,0x4a41,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x01,0xf0} },
+{   7,0x4a51,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4a58,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x04,0xf0} },
+{   7,0x4a68,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4a6f,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x04,0xf0} },
+{   7,0x4a7f,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4a86,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x08,0xf0} },
+{   7,0x4a96,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4a9d,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x08,0xf0} },
+{   7,0x4aad,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4ab4,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x10,0xf0} },
+{   7,0x4ac4,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4acb,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x10,0xf0} },
+{   7,0x4adb,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4ae2,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x20,0xf0} },
+{   7,0x4af2,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4af9,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x20,0xf0} },
+{   7,0x4b09,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4b10,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x40,0xf0} },
+{   7,0x4b20,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4b27,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x40,0xf0} },
+{   7,0x4b37,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4b3e,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xa9,0xe0,0x44,0x80,0xf0} },
+{   7,0x4b4e,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4b55,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xaa,0xe0,0x44,0x80,0xf0} },
+{   7,0x4b65,0,{0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x4b6c,0,{0x8e,0x33,0x8f,0x34,0xe5,0x34,0x15,0x34,0xae,0x33,0x70,0x02,0x15,0x33,0x4e,0x60} },
+{   7,0x4b7c,0,{0x05,0x12,0x07,0x89,0x80,0xee,0x22} },
+{  15,0x4b83,0,{0x90,0x7f,0xea,0xe0,0xb4,0xff,0x04,0x12,0x30,0x00,0x22,0x12,0x36,0x0e,0x22} },
+{  14,0x4b92,0,{0xc0,0xe0,0xc2,0x8b,0xd2,0x24,0x30,0x23,0x02,0xc2,0x23,0xd0,0xe0,0x32} },
+{  14,0x4ba0,0,{0x90,0x7f,0x00,0xe5,0x08,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0,0xd3,0x22} },
+{   9,0x4bae,0,{0x30,0x24,0x05,0xc2,0x24,0x75,0x18,0x01,0x22} },
+{   9,0x4bb7,0,{0x30,0x23,0x05,0xc2,0x23,0xe4,0xf5,0x18,0x22} },
+{   7,0x4bc0,0,{0x53,0xc0,0xfe,0x53,0xc0,0xfd,0x32} },
+{   6,0x4bc7,0,{0x53,0x91,0x7f,0xd2,0x25,0x32} },
+{   5,0x4bcd,0,{0xc2,0x89,0xd2,0x23,0x32} },
+{   3,0x4bd2,0,{0xc2,0x8d,0x32} },
+{   3,0x4bd5,0,{0xc2,0x8f,0x32} },
+{   2,0x4bd8,0,{0xd3,0x22} },
+{   2,0x4bda,0,{0xd3,0x22} },
+{   2,0x4bdc,0,{0xd3,0x22} },
+{   2,0x4bde,0,{0xd3,0x22} },
+{   2,0x4be0,0,{0xd3,0x22} },
+{   2,0x4be2,0,{0xd3,0x22} },
+{   2,0x4be4,0,{0xc3,0x22} },
+{   1,0x4be6,0,{0x22} },
+{   0,0x0000,1,{0 }}
+};
+/*
+VERSION=1.0.2.916
+DATE=12.02.2002
+*/
+/*
+ * This firmware is for the Emagic EMI 2|6 Audio Interface
+ *
+ * The firmware contained herein is Copyright (c) 1999-2002 Emagic
+ * as an unpublished work. This notice does not imply unrestricted
+ * or public access to this firmware which is a trade secret of Emagic,
+ * and which may not be reproduced, used, sold or transferred to
+ * any third party without Emagic's written consent. All Rights Reserved.
+ *
+ * This firmware may not be modified and may only be used with the
+ * Emagic EMI 2|6 Audio Interface. Distribution and/or Modification of
+ * any driver which includes this firmware, in whole or in part,
+ * requires the inclusion of this statement.
+ */
+INTEL_HEX_RECORD g_Loader[] = {
+{   3,0x0000,0,{0x02,0x03,0x1c} },
+{   3,0x0043,0,{0x02,0x04,0x00} },
+{  16,0x0100,0,{0x90,0x7f,0xe9,0xe0,0x24,0x5b,0x60,0x60,0x24,0x02,0x60,0x03,0x02,0x01,0xbe,0x90} },
+{  16,0x0110,0,{0x7f,0xea,0xe0,0x75,0x0a,0x00,0xf5,0x0b,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x0a,0x90} },
+{  16,0x0120,0,{0x7f,0xee,0xe0,0x75,0x15,0x00,0xf5,0x16,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x15,0xe5} },
+{  16,0x0130,0,{0x16,0x45,0x15,0x70,0x03,0x02,0x01,0xbe,0xe4,0x90,0x7f,0xc5,0xf0,0x90,0x7f,0xb4} },
+{  16,0x0140,0,{0xe0,0x20,0xe3,0xf9,0x90,0x7f,0xc5,0xe0,0xf5,0x0c,0x12,0x02,0x77,0xaf,0x0c,0x7e} },
+{  16,0x0150,0,{0x00,0xef,0x25,0x0b,0xf5,0x0b,0xee,0x35,0x0a,0xf5,0x0a,0xc3,0xe5,0x16,0x9f,0xf5} },
+{  16,0x0160,0,{0x16,0xe5,0x15,0x9e,0xf5,0x15,0x80,0xc7,0x90,0x7f,0xea,0xe0,0x75,0x0a,0x00,0xf5} },
+{  16,0x0170,0,{0x0b,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x0a,0x90,0x7f,0xee,0xe0,0x75,0x15,0x00,0xf5} },
+{  16,0x0180,0,{0x16,0xa3,0xe0,0xfe,0xe4,0xee,0x42,0x15,0xe5,0x16,0x45,0x15,0x60,0x30,0xe4,0x90} },
+{  16,0x0190,0,{0x7f,0xc5,0xf0,0x90,0x7f,0xb4,0xe0,0x20,0xe3,0xf9,0x90,0x7f,0xc5,0xe0,0xf5,0x0c} },
+{  16,0x01a0,0,{0x12,0x02,0x8f,0xaf,0x0c,0x7e,0x00,0xef,0x25,0x0b,0xf5,0x0b,0xee,0x35,0x0a,0xf5} },
+{  15,0x01b0,0,{0x0a,0xc3,0xe5,0x16,0x9f,0xf5,0x16,0xe5,0x15,0x9e,0xf5,0x15,0x80,0xca,0xc3} },
+{   1,0x01bf,0,{0x22} },
+{  16,0x01c0,0,{0xc2,0x20,0xd2,0xe8,0x43,0xd8,0x20,0x90,0x7f,0xab,0x74,0xff,0xf0,0x90,0x7f,0xa9} },
+{  16,0x01d0,0,{0xf0,0x90,0x7f,0xaa,0xf0,0x53,0x91,0xef,0x90,0x7f,0x95,0xe0,0x44,0xc0,0xf0,0x90} },
+{  16,0x01e0,0,{0x7f,0x98,0xe0,0x44,0xc0,0xf0,0x90,0x7f,0x9e,0xe0,0x44,0xc0,0xf0,0xe4,0x90,0x7f} },
+{  16,0x01f0,0,{0x94,0xf0,0x90,0x7f,0x9d,0xe0,0x44,0x0f,0xf0,0x90,0x7f,0x97,0xe0,0x54,0xf0,0xf0} },
+{  16,0x0200,0,{0x90,0x7f,0xaf,0xe0,0x44,0x01,0xf0,0x90,0x7f,0xae,0xe0,0x44,0x0d,0xf0,0xd2,0xaf} },
+{  16,0x0210,0,{0x90,0x7f,0x97,0xe0,0x54,0xf0,0xf0,0x20,0x20,0x42,0x75,0x14,0x00,0x75,0x13,0x00} },
+{  16,0x0220,0,{0x75,0x12,0x00,0x75,0x11,0x00,0x7f,0x48,0x7e,0x92,0x7d,0x00,0x7c,0x00,0xab,0x14} },
+{  16,0x0230,0,{0xaa,0x13,0xa9,0x12,0xa8,0x11,0xc3,0x12,0x04,0x9a,0x50,0xdb,0x20,0x20,0xd8,0x7a} },
+{  16,0x0240,0,{0x00,0x79,0x00,0x78,0x00,0xe5,0x14,0x24,0x01,0xf5,0x14,0xea,0x35,0x13,0xf5,0x13} },
+{  16,0x0250,0,{0xe9,0x35,0x12,0xf5,0x12,0xe8,0x35,0x11,0xf5,0x11,0x80,0xca,0x30,0x20,0xfd,0x12} },
+{  16,0x0260,0,{0x01,0x00,0x50,0x07,0x90,0x7f,0xb4,0xe0,0x44,0x01,0xf0,0x90,0x7f,0xb4,0xe0,0x44} },
+{   6,0x0270,0,{0x02,0xf0,0xc2,0x20,0x80,0xe6} },
+{   1,0x0276,0,{0x22} },
+{  16,0x0277,0,{0xe5,0x0c,0xff,0xe5,0x0b,0xf5,0x82,0xe5,0x0a,0xf5,0x83,0x75,0x92,0x7e,0x74,0xc0} },
+{   8,0x0287,0,{0xf8,0xe2,0x08,0xf0,0xa3,0xdf,0xfa,0x22} },
+{  16,0x028f,0,{0x90,0x7f,0x96,0x85,0x83,0x92,0xa8,0x82,0x79,0x02,0x90,0x00,0x00,0xe0,0xb4,0x00} },
+{  16,0x029f,0,{0x37,0x74,0x01,0xf0,0x90,0x7f,0x93,0xe0,0x54,0xfc,0xf0,0x90,0x7f,0x96,0xe0,0x54} },
+{  16,0x02af,0,{0xfc,0xf0,0x90,0x7f,0x9c,0xe0,0x44,0x03,0xf0,0x90,0x7f,0x94,0xe0,0x54,0x7f,0xf0} },
+{  16,0x02bf,0,{0x90,0x7f,0x97,0xe0,0x44,0x80,0xf0,0x90,0x7f,0x9d,0xe0,0x44,0x80,0xf0,0x90,0x7f} },
+{  16,0x02cf,0,{0x97,0xe0,0x54,0x7f,0xf0,0x44,0x80,0xf0,0xe5,0x0c,0xff,0x90,0x7e,0xc0,0xe0,0xf5} },
+{  16,0x02df,0,{0x28,0xe4,0xa2,0x47,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x46,0x33,0xf2,0x69,0xf2,0xe4} },
+{  16,0x02ef,0,{0xa2,0x45,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x44,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x43} },
+{  16,0x02ff,0,{0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x42,0x33,0xf2,0x69,0xf2,0xe4,0xa2,0x41,0x33,0xf2} },
+{  13,0x030f,0,{0x69,0xf2,0xe4,0xa2,0x40,0x33,0xf2,0x69,0xf2,0xa3,0xdf,0xc2,0x22} },
+{  12,0x031c,0,{0x78,0x7f,0xe4,0xf6,0xd8,0xfd,0x75,0x81,0x29,0x02,0x03,0x63} },
+{  16,0x0328,0,{0x02,0x01,0xc0,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0x40,0x03,0xf6,0x80,0x01,0xf2} },
+{  16,0x0338,0,{0x08,0xdf,0xf4,0x80,0x29,0xe4,0x93,0xa3,0xf8,0x54,0x07,0x24,0x0c,0xc8,0xc3,0x33} },
+{  16,0x0348,0,{0xc4,0x54,0x0f,0x44,0x20,0xc8,0x83,0x40,0x04,0xf4,0x56,0x80,0x01,0x46,0xf6,0xdf} },
+{  16,0x0358,0,{0xe4,0x80,0x0b,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x90,0x04,0x84,0xe4,0x7e} },
+{  16,0x0368,0,{0x01,0x93,0x60,0xbc,0xa3,0xff,0x54,0x3f,0x30,0xe5,0x09,0x54,0x1f,0xfe,0xe4,0x93} },
+{  16,0x0378,0,{0xa3,0x60,0x01,0x0e,0xcf,0x54,0xc0,0x25,0xe0,0x60,0xa8,0x40,0xb8,0xe4,0x93,0xa3} },
+{  16,0x0388,0,{0xfa,0xe4,0x93,0xa3,0xf8,0xe4,0x93,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca} },
+{  16,0x0398,0,{0xf0,0xa3,0xc8,0xc5,0x82,0xc8,0xca,0xc5,0x83,0xca,0xdf,0xe9,0xde,0xe7,0x80,0xbe} },
+{  16,0x03a8,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x90,0x7f,0xc4,0xe4,0xf0,0x53,0x91,0xef,0x90,0x7f} },
+{  11,0x03b8,0,{0xab,0x74,0x04,0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x03c3,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0xd2,0x20,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x01} },
+{   8,0x03d3,0,{0xf0,0xd0,0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x03db,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x02,0xf0,0xd0} },
+{   6,0x03eb,0,{0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{   1,0x03f1,0,{0x32} },
+{   1,0x03f2,0,{0x32} },
+{   1,0x03f3,0,{0x32} },
+{   1,0x03f4,0,{0x32} },
+{   1,0x03f5,0,{0x32} },
+{   1,0x03f6,0,{0x32} },
+{   1,0x03f7,0,{0x32} },
+{   1,0x03f8,0,{0x32} },
+{   1,0x03f9,0,{0x32} },
+{   1,0x03fa,0,{0x32} },
+{   1,0x03fb,0,{0x32} },
+{   1,0x03fc,0,{0x32} },
+{   1,0x03fd,0,{0x32} },
+{   1,0x03fe,0,{0x32} },
+{   1,0x03ff,0,{0x32} },
+{  16,0x0400,0,{0x02,0x03,0xc3,0x00,0x02,0x03,0xdb,0x00,0x02,0x03,0xa8,0x00,0x02,0x04,0x6e,0x00} },
+{  16,0x0410,0,{0x02,0x04,0x58,0x00,0x02,0x03,0xf1,0x00,0x02,0x03,0xf2,0x00,0x02,0x03,0xf3,0x00} },
+{  16,0x0420,0,{0x02,0x03,0xf4,0x00,0x02,0x03,0xf5,0x00,0x02,0x03,0xf6,0x00,0x02,0x03,0xf7,0x00} },
+{  16,0x0430,0,{0x02,0x03,0xf8,0x00,0x02,0x03,0xf9,0x00,0x02,0x03,0xfa,0x00,0x02,0x03,0xfb,0x00} },
+{  16,0x0440,0,{0x02,0x03,0xfc,0x00,0x02,0x03,0xfd,0x00,0x02,0x03,0xfe,0x00,0x02,0x03,0xff,0x00} },
+{   8,0x0450,0,{0x02,0x04,0xab,0x00,0x02,0x04,0xac,0x00} },
+{  16,0x0458,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x10,0xf0,0xd0} },
+{   6,0x0468,0,{0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x046e,0,{0xc0,0xe0,0xc0,0x83,0xc0,0x82,0x53,0x91,0xef,0x90,0x7f,0xab,0x74,0x08,0xf0,0xd0} },
+{   6,0x047e,0,{0x82,0xd0,0x83,0xd0,0xe0,0x32} },
+{  16,0x0484,0,{0x02,0x0a,0x00,0x0f,0x01,0x0c,0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x41,0x00,0x00} },
+{   1,0x0494,0,{0x00} },
+{   4,0x0495,0,{0x02,0x17,0x00,0x00} },
+{   1,0x0499,0,{0x00} },
+{  16,0x049a,0,{0xeb,0x9f,0xf5,0xf0,0xea,0x9e,0x42,0xf0,0xe9,0x9d,0x42,0xf0,0xe8,0x9c,0x45,0xf0} },
+{   1,0x04aa,0,{0x22} },
+{   1,0x04ab,0,{0x32} },
+{   1,0x04ac,0,{0x32} },
+{  16,0x1100,0,{0x12,0x01,0x10,0x01,0x00,0x00,0x00,0x40,0x6a,0x08,0x01,0x01,0x00,0x01,0x01,0x02} },
+{  16,0x1110,0,{0x00,0x01,0x09,0x02,0x20,0x00,0x01,0x01,0x03,0xa0,0x00,0x09,0x04,0x00,0x00,0x02} },
+{  16,0x1120,0,{0xff,0x00,0x00,0x04,0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40} },
+{  16,0x1130,0,{0x00,0x00,0x04,0x03,0x09,0x04,0x26,0x03,0x41,0x00,0x6e,0x00,0x63,0x00,0x68,0x00} },
+{  16,0x1140,0,{0x6f,0x00,0x72,0x00,0x20,0x00,0x43,0x00,0x68,0x00,0x69,0x00,0x70,0x00,0x73,0x00} },
+{  16,0x1150,0,{0x2c,0x00,0x20,0x00,0x49,0x00,0x6e,0x00,0x63,0x00,0x2e,0x00,0x28,0x03,0x46,0x00} },
+{  16,0x1160,0,{0x69,0x00,0x72,0x00,0x6d,0x00,0x77,0x00,0x61,0x00,0x72,0x00,0x65,0x00,0x20,0x00} },
+{  16,0x1170,0,{0x46,0x00,0x72,0x00,0x61,0x00,0x6d,0x00,0x65,0x00,0x57,0x00,0x6f,0x00,0x72,0x00} },
+{  16,0x1180,0,{0x6b,0x00,0x73,0x00,0x2a,0x03,0x43,0x00,0x6f,0x00,0x6e,0x00,0x66,0x00,0x69,0x00} },
+{  16,0x1190,0,{0x67,0x00,0x75,0x00,0x72,0x00,0x61,0x00,0x74,0x00,0x69,0x00,0x6f,0x00,0x6e,0x00} },
+{  16,0x11a0,0,{0x20,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x67,0x00,0x22,0x03} },
+{  16,0x11b0,0,{0x49,0x00,0x6e,0x00,0x74,0x00,0x65,0x00,0x72,0x00,0x66,0x00,0x61,0x00,0x63,0x00} },
+{  16,0x11c0,0,{0x65,0x00,0x20,0x00,0x53,0x00,0x74,0x00,0x72,0x00,0x69,0x00,0x6e,0x00,0x67,0x00} },
+{   2,0x11d0,0,{0x00,0x00} },
+{   0,0x0000,1,{0 }}
+};
diff -Nru a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/rio500.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,550 @@
+/* -*- linux-c -*- */
+
+/* 
+ * Driver for USB Rio 500
+ *
+ * Cesar Miquel (miquel@df.uba.ar)
+ * 
+ * based on hp_scanner.c by David E. Nelson (dnelson@jump.net)
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
+ *
+ * */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+
+#include "rio500_usb.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
+#define DRIVER_DESC "USB Rio 500 driver"
+
+#define RIO_MINOR   64
+
+/* stall/wait timeout for rio */
+#define NAK_TIMEOUT (HZ)
+
+#define IBUF_SIZE 0x1000
+
+/* Size of the rio buffer */
+#define OBUF_SIZE 0x10000
+
+struct rio_usb_data {
+        struct usb_device *rio_dev;     /* init: probe_rio */
+        devfs_handle_t devfs;           /* devfs device */
+        unsigned int ifnum;             /* Interface number of the USB device */
+        int isopen;                     /* nz if open */
+        int present;                    /* Device is present on the bus */
+        char *obuf, *ibuf;              /* transfer buffers */
+        char bulk_in_ep, bulk_out_ep;   /* Endpoint assignments */
+        wait_queue_head_t wait_q;       /* for timeouts */
+	struct semaphore lock;          /* general race avoidance */
+};
+
+extern devfs_handle_t usb_devfs_handle;	/* /dev/usb dir. */
+
+static struct rio_usb_data rio_instance;
+
+static int open_rio(struct inode *inode, struct file *file)
+{
+	struct rio_usb_data *rio = &rio_instance;
+
+	lock_kernel();
+
+	if (rio->isopen || !rio->present) {
+		unlock_kernel();
+		return -EBUSY;
+	}
+	rio->isopen = 1;
+
+	init_waitqueue_head(&rio->wait_q);
+
+	MOD_INC_USE_COUNT;
+
+	unlock_kernel();
+
+	info("Rio opened.");
+
+	return 0;
+}
+
+static int close_rio(struct inode *inode, struct file *file)
+{
+	struct rio_usb_data *rio = &rio_instance;
+
+	rio->isopen = 0;
+
+	MOD_DEC_USE_COUNT;
+
+	info("Rio closed.");
+	return 0;
+}
+
+static int
+ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
+	  unsigned long arg)
+{
+	struct RioCommand rio_cmd;
+	struct rio_usb_data *rio = &rio_instance;
+	void *data;
+	unsigned char *buffer;
+	int result, requesttype;
+	int retries;
+	int retval=0;
+
+	down(&(rio->lock));
+        /* Sanity check to make sure rio is connected, powered, etc */
+        if ( rio == NULL ||
+             rio->present == 0 ||
+             rio->rio_dev == NULL )
+	{
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	switch (cmd) {
+	case RIO_RECV_COMMAND:
+		data = (void *) arg;
+		if (data == NULL)
+			break;
+		if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
+			retval = -EFAULT;
+			goto err_out;
+		}
+		if (rio_cmd.length > PAGE_SIZE) {
+			retval = -EINVAL;
+			goto err_out;
+		}
+		buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
+		if (buffer == NULL) {
+			retval = -ENOMEM;
+			goto err_out;
+		}
+		if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
+			retval = -EFAULT;
+			free_page((unsigned long) buffer);
+			goto err_out;
+		}
+
+		requesttype = rio_cmd.requesttype | USB_DIR_IN |
+		    USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+		dbg
+		    ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
+		     requesttype, rio_cmd.request, rio_cmd.value,
+		     rio_cmd.index, rio_cmd.length);
+		/* Send rio control message */
+		retries = 3;
+		while (retries) {
+			result = usb_control_msg(rio->rio_dev,
+						 usb_rcvctrlpipe(rio-> rio_dev, 0),
+						 rio_cmd.request,
+						 requesttype,
+						 rio_cmd.value,
+						 rio_cmd.index, buffer,
+						 rio_cmd.length,
+						 rio_cmd.timeout);
+			if (result == -ETIMEDOUT)
+				retries--;
+			else if (result < 0) {
+				err("Error executing ioctrl. code = %d",
+				     le32_to_cpu(result));
+				retries = 0;
+			} else {
+				dbg("Executed ioctl. Result = %d (data=%04x)",
+				     le32_to_cpu(result),
+				     le32_to_cpu(*((long *) buffer)));
+				if (copy_to_user(rio_cmd.buffer, buffer,
+						 rio_cmd.length)) {
+					free_page((unsigned long) buffer);
+					retval = -EFAULT;
+					goto err_out;
+				}
+				retries = 0;
+			}
+
+			/* rio_cmd.buffer contains a raw stream of single byte
+			   data which has been returned from rio.  Data is
+			   interpreted at application level.  For data that
+			   will be cast to data types longer than 1 byte, data
+			   will be little_endian and will potentially need to
+			   be swapped at the app level */
+
+		}
+		free_page((unsigned long) buffer);
+		break;
+
+	case RIO_SEND_COMMAND:
+		data = (void *) arg;
+		if (data == NULL)
+			break;
+		if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
+			retval = -EFAULT;
+			goto err_out;
+		}
+		if (rio_cmd.length > PAGE_SIZE) {
+			retval = -EINVAL;
+			goto err_out;
+		}
+		buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
+		if (buffer == NULL) {
+			retval = -ENOMEM;
+			goto err_out;
+		}
+		if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
+			free_page((unsigned long)buffer);
+			retval = -EFAULT;
+			goto err_out;
+		}
+
+		requesttype = rio_cmd.requesttype | USB_DIR_OUT |
+		    USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+		dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
+		     requesttype, rio_cmd.request, rio_cmd.value,
+		     rio_cmd.index, rio_cmd.length);
+		/* Send rio control message */
+		retries = 3;
+		while (retries) {
+			result = usb_control_msg(rio->rio_dev,
+						 usb_sndctrlpipe(rio-> rio_dev, 0),
+						 rio_cmd.request,
+						 requesttype,
+						 rio_cmd.value,
+						 rio_cmd.index, buffer,
+						 rio_cmd.length,
+						 rio_cmd.timeout);
+			if (result == -ETIMEDOUT)
+				retries--;
+			else if (result < 0) {
+				err("Error executing ioctrl. code = %d",
+				     le32_to_cpu(result));
+				retries = 0;
+			} else {
+				dbg("Executed ioctl. Result = %d",
+				       le32_to_cpu(result));
+				retries = 0;
+
+			}
+
+		}
+		free_page((unsigned long) buffer);
+		break;
+
+	default:
+		retval = -ENOTTY;
+		break;
+	}
+
+
+err_out:
+	up(&(rio->lock));
+	return retval;
+}
+
+static ssize_t
+write_rio(struct file *file, const char *buffer,
+	  size_t count, loff_t * ppos)
+{
+	struct rio_usb_data *rio = &rio_instance;
+
+	unsigned long copy_size;
+	unsigned long bytes_written = 0;
+	unsigned int partial;
+
+	int result = 0;
+	int maxretry;
+	int errn = 0;
+
+	down(&(rio->lock));
+        /* Sanity check to make sure rio is connected, powered, etc */
+        if ( rio == NULL ||
+             rio->present == 0 ||
+             rio->rio_dev == NULL )
+	{
+		up(&(rio->lock));
+		return -ENODEV;
+	}
+
+
+
+	do {
+		unsigned long thistime;
+		char *obuf = rio->obuf;
+
+		thistime = copy_size =
+		    (count >= OBUF_SIZE) ? OBUF_SIZE : count;
+		if (copy_from_user(rio->obuf, buffer, copy_size)) {
+			errn = -EFAULT;
+			goto error;
+		}
+		maxretry = 5;
+		while (thistime) {
+			if (!rio->rio_dev) {
+				errn = -ENODEV;
+				goto error;
+			}
+			if (signal_pending(current)) {
+				up(&(rio->lock));
+				return bytes_written ? bytes_written : -EINTR;
+			}
+
+			result = usb_bulk_msg(rio->rio_dev,
+					 usb_sndbulkpipe(rio->rio_dev, 2),
+					 obuf, thistime, &partial, 5 * HZ);
+
+			dbg("write stats: result:%d thistime:%lu partial:%u",
+			     result, thistime, partial);
+
+			if (result == -ETIMEDOUT) {	/* NAK - so hold for a while */
+				if (!maxretry--) {
+					errn = -ETIME;
+					goto error;
+				}
+				interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
+				continue;
+			} else if (!result & partial) {
+				obuf += partial;
+				thistime -= partial;
+			} else
+				break;
+		};
+		if (result) {
+			err("Write Whoops - %x", result);
+			errn = -EIO;
+			goto error;
+		}
+		bytes_written += copy_size;
+		count -= copy_size;
+		buffer += copy_size;
+	} while (count > 0);
+
+	up(&(rio->lock));
+
+	return bytes_written ? bytes_written : -EIO;
+
+error:
+	up(&(rio->lock));
+	return errn;
+}
+
+static ssize_t
+read_rio(struct file *file, char *buffer, size_t count, loff_t * ppos)
+{
+	struct rio_usb_data *rio = &rio_instance;
+	ssize_t read_count;
+	unsigned int partial;
+	int this_read;
+	int result;
+	int maxretry = 10;
+	char *ibuf;
+
+	down(&(rio->lock));
+	/* Sanity check to make sure rio is connected, powered, etc */
+        if ( rio == NULL ||
+             rio->present == 0 ||
+             rio->rio_dev == NULL )
+	{
+		up(&(rio->lock));
+		return -ENODEV;
+	}
+
+	ibuf = rio->ibuf;
+
+	read_count = 0;
+
+
+	while (count > 0) {
+		if (signal_pending(current)) {
+			up(&(rio->lock));
+			return read_count ? read_count : -EINTR;
+		}
+		if (!rio->rio_dev) {
+			up(&(rio->lock));
+			return -ENODEV;
+		}
+		this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
+
+		result = usb_bulk_msg(rio->rio_dev,
+				      usb_rcvbulkpipe(rio->rio_dev, 1),
+				      ibuf, this_read, &partial,
+				      (int) (HZ * 8));
+
+		dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
+		       result, this_read, partial);
+
+		if (partial) {
+			count = this_read = partial;
+		} else if (result == -ETIMEDOUT || result == 15) {	/* FIXME: 15 ??? */
+			if (!maxretry--) {
+				up(&(rio->lock));
+				err("read_rio: maxretry timeout");
+				return -ETIME;
+			}
+			interruptible_sleep_on_timeout(&rio->wait_q,
+						       NAK_TIMEOUT);
+			continue;
+		} else if (result != -EREMOTEIO) {
+			up(&(rio->lock));
+			err("Read Whoops - result:%u partial:%u this_read:%u",
+			     result, partial, this_read);
+			return -EIO;
+		} else {
+			up(&(rio->lock));
+			return (0);
+		}
+
+		if (this_read) {
+			if (copy_to_user(buffer, ibuf, this_read)) {
+				up(&(rio->lock));
+				return -EFAULT;
+			}
+			count -= this_read;
+			read_count += this_read;
+			buffer += this_read;
+		}
+	}
+	up(&(rio->lock));
+	return read_count;
+}
+
+static struct
+file_operations usb_rio_fops = {
+	read:		read_rio,
+	write:		write_rio,
+	ioctl:		ioctl_rio,
+	open:		open_rio,
+	release:	close_rio,
+};
+
+static void *probe_rio(struct usb_device *dev, unsigned int ifnum,
+		       const struct usb_device_id *id)
+{
+	struct rio_usb_data *rio = &rio_instance;
+
+	info("USB Rio found at address %d", dev->devnum);
+
+	rio->present = 1;
+	rio->rio_dev = dev;
+
+	if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+		err("probe_rio: Not enough memory for the output buffer");
+		return NULL;
+	}
+	dbg("probe_rio: obuf address:%p", rio->obuf);
+
+	if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+		err("probe_rio: Not enough memory for the input buffer");
+		kfree(rio->obuf);
+		return NULL;
+	}
+	dbg("probe_rio: ibuf address:%p", rio->ibuf);
+
+	rio->devfs = devfs_register(usb_devfs_handle, "rio500",
+				    DEVFS_FL_DEFAULT, USB_MAJOR,
+				    RIO_MINOR,
+				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
+				    S_IWGRP, &usb_rio_fops, NULL);
+	if (rio->devfs == NULL)
+		dbg("probe_rio: device node registration failed");
+
+	init_MUTEX(&(rio->lock));
+
+	return rio;
+}
+
+static void disconnect_rio(struct usb_device *dev, void *ptr)
+{
+	struct rio_usb_data *rio = (struct rio_usb_data *) ptr;
+
+	devfs_unregister(rio->devfs);
+
+	down(&(rio->lock));
+	if (rio->isopen) {
+		rio->isopen = 0;
+		/* better let it finish - the release will do whats needed */
+		rio->rio_dev = NULL;
+		up(&(rio->lock));
+		return;
+	}
+	kfree(rio->ibuf);
+	kfree(rio->obuf);
+
+	info("USB Rio disconnected.");
+
+	rio->present = 0;
+	up(&(rio->lock));
+}
+
+static struct usb_device_id rio_table [] = {
+	{ USB_DEVICE(0x0841, 1) }, 		/* Rio 500 */
+	{ }					/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, rio_table);
+
+static struct usb_driver rio_driver = {
+	name:		"rio500",
+	probe:		probe_rio,
+	disconnect:	disconnect_rio,
+	fops:		&usb_rio_fops,
+	minor:		RIO_MINOR,
+	id_table:	rio_table,
+};
+
+int usb_rio_init(void)
+{
+	if (usb_register(&rio_driver) < 0)
+		return -1;
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+
+	return 0;
+}
+
+
+void usb_rio_cleanup(void)
+{
+	struct rio_usb_data *rio = &rio_instance;
+
+	rio->present = 0;
+	usb_deregister(&rio_driver);
+
+
+}
+
+module_init(usb_rio_init);
+module_exit(usb_rio_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/misc/rio500_usb.h b/drivers/usb/misc/rio500_usb.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/rio500_usb.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,37 @@
+/*  ----------------------------------------------------------------------
+
+    Copyright (C) 2000  Cesar Miquel  (miquel@df.uba.ar)
+
+    This program is free software; you can redistribute it and/or 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.
+
+    ---------------------------------------------------------------------- */
+
+
+
+#define RIO_SEND_COMMAND			0x1
+#define RIO_RECV_COMMAND			0x2
+
+#define RIO_DIR_OUT               	        0x0
+#define RIO_DIR_IN				0x1
+
+struct RioCommand {
+	short length;
+	int request;
+	int requesttype;
+	int value;
+	int index;
+	void *buffer;
+	int timeout;
+};
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/tiglusb.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,495 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver.
+ * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
+ *      
+ * Copyright (C) 2001-2002: 
+ *   Romain Lievin <roms@lpg.ticalc.org>
+ *   Julien BLACHE <jb@technologeek.org>
+ * under the terms of the GNU General Public License.
+ *
+ * Based on dabusb.c, printer.c & scanner.c
+ *
+ * Please see the file: linux/Documentation/usb/SilverLink.txt 
+ * and the website at:  http://lpg.ticalc.org/prj_usb/
+ * for more info.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
+
+#include <linux/ticable.h>
+#include "tiglusb.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.02"
+#define DRIVER_AUTHOR  "Romain Lievin <roms@lpg.ticalc.org> & Julien Blache <jb@jblache.org>"
+#define DRIVER_DESC    "TI-GRAPH LINK USB (aka SilverLink) driver"
+#define DRIVER_LICENSE "GPL"
+
+
+/* ----- global variables --------------------------------------------- */
+
+static tiglusb_t tiglusb[MAXTIGL];
+static int timeout = TIMAXTIME;	/* timeout in tenth of seconds     */
+
+static devfs_handle_t devfs_handle;
+
+/*---------- misc functions ------------------------------------------- */
+
+/* Unregister device */
+static void usblp_cleanup (tiglusb_t * s)
+{
+	devfs_unregister (s->devfs);
+	//memset(tiglusb[s->minor], 0, sizeof(tiglusb_t));
+	info ("tiglusb%d removed", s->minor);
+}
+
+/* Re-initialize device */
+static int clear_device (struct usb_device *dev)
+{
+	if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) {
+		printk ("tiglusb: clear_device failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/* Clear input & output pipes (endpoints) */
+static int clear_pipes (struct usb_device *dev)
+{
+	unsigned int pipe;
+
+	pipe = usb_sndbulkpipe (dev, 1);
+	if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) {
+		printk ("tiglusb: clear_pipe (r), request failed\n");
+		return -1;
+	}
+
+	pipe = usb_sndbulkpipe (dev, 2);
+	if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) {
+		printk ("tiglusb: clear_pipe (w), request failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/* ----- kernel module functions--------------------------------------- */
+
+static int tiglusb_open (struct inode *inode, struct file *file)
+{
+	int devnum = minor (inode->i_rdev);
+	ptiglusb_t s;
+
+	if (devnum < TIUSB_MINOR || devnum >= (TIUSB_MINOR + MAXTIGL))
+		return -EIO;
+
+	s = &tiglusb[devnum - TIUSB_MINOR];
+
+	down (&s->mutex);
+
+	while (!s->dev || s->opened) {
+		up (&s->mutex);
+
+		if (file->f_flags & O_NONBLOCK) {
+			return -EBUSY;
+		}
+		schedule_timeout (HZ / 2);
+
+		if (signal_pending (current)) {
+			return -EAGAIN;
+		}
+		down (&s->mutex);
+	}
+
+	s->opened = 1;
+	up (&s->mutex);
+
+	file->f_pos = 0;
+	file->private_data = s;
+
+	return 0;
+}
+
+static int tiglusb_release (struct inode *inode, struct file *file)
+{
+	ptiglusb_t s = (ptiglusb_t) file->private_data;
+
+	lock_kernel ();
+	down (&s->mutex);
+	s->state = _stopped;
+	up (&s->mutex);
+
+	if (!s->remove_pending)
+		clear_device (s->dev);
+	else
+		wake_up (&s->remove_ok);
+
+	s->opened = 0;
+	unlock_kernel ();
+
+	return 0;
+}
+
+static ssize_t tiglusb_read (struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+	ptiglusb_t s = (ptiglusb_t) file->private_data;
+	ssize_t ret = 0;
+	int bytes_to_read = 0;
+	int bytes_read = 0;
+	int result = 0;
+	char buffer[BULK_RCV_MAX];
+	unsigned int pipe;
+
+	if (*ppos)
+		return -ESPIPE;
+
+	if (s->remove_pending)
+		return -EIO;
+
+	if (!s->dev)
+		return -EIO;
+
+	bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count;
+
+	pipe = usb_rcvbulkpipe (s->dev, 1);
+	result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
+			       &bytes_read, HZ / (timeout / 10));
+	if (result == -ETIMEDOUT) {	/* NAK */
+		ret = result;
+		if (!bytes_read) {
+			printk ("quirk !\n");
+		}
+		warn ("tiglusb_read, NAK received.");
+		goto out;
+	} else if (result == -EPIPE) {	/* STALL -- shouldn't happen */
+		warn ("CLEAR_FEATURE request to remove STALL condition.\n");
+		if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe)))
+			warn ("send_packet, request failed\n");
+		//clear_device(s->dev);
+		ret = result;
+		goto out;
+	} else if (result < 0) {	/* We should not get any I/O errors */
+		warn ("funky result: %d. Please notify maintainer.", result);
+		ret = -EIO;
+		goto out;
+	}
+
+	if (copy_to_user (buf, buffer, bytes_read)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+      out:
+	return ret ? ret : bytes_read;
+}
+
+static ssize_t tiglusb_write (struct file *file, const char *buf, size_t count, loff_t * ppos)
+{
+	ptiglusb_t s = (ptiglusb_t) file->private_data;
+	ssize_t ret = 0;
+	int bytes_to_write = 0;
+	int bytes_written = 0;
+	int result = 0;
+	char buffer[BULK_SND_MAX];
+	unsigned int pipe;
+
+	if (*ppos)
+		return -ESPIPE;
+
+	if (s->remove_pending)
+		return -EIO;
+
+	if (!s->dev)
+		return -EIO;
+
+	bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count;
+	if (copy_from_user (buffer, buf, bytes_to_write)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	pipe = usb_sndbulkpipe (s->dev, 2);
+	result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
+			       &bytes_written, HZ / (timeout / 10));
+
+	if (result == -ETIMEDOUT) {	/* NAK */
+		warn ("tiglusb_write, NAK received.");
+		ret = result;
+		goto out;
+	} else if (result == -EPIPE) {	/* STALL -- shouldn't happen */
+		warn ("CLEAR_FEATURE request to remove STALL condition.");
+		if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe)))
+			warn ("send_packet, request failed\n");
+		//clear_device(s->dev);
+		ret = result;
+		goto out;
+	} else if (result < 0) {	/* We should not get any I/O errors */
+		warn ("funky result: %d. Please notify maintainer.", result);
+		ret = -EIO;
+		goto out;
+	}
+
+	if (bytes_written != bytes_to_write) {
+		ret = -EIO;
+		goto out;
+	}
+
+      out:
+	return ret ? ret : bytes_written;
+}
+
+static int tiglusb_ioctl (struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg)
+{
+	ptiglusb_t s = (ptiglusb_t) file->private_data;
+	int ret = 0;
+
+	if (s->remove_pending)
+		return -EIO;
+
+	down (&s->mutex);
+
+	if (!s->dev) {
+		up (&s->mutex);
+		return -EIO;
+	}
+
+	switch (cmd) {
+	case IOCTL_TIUSB_TIMEOUT:
+		timeout = arg;	// timeout value in tenth of seconds
+		break;
+	case IOCTL_TIUSB_RESET_DEVICE:
+		printk (KERN_DEBUG "IOCTL_TIGLUSB_RESET_DEVICE\n");
+		if (clear_device (s->dev))
+			ret = -EIO;
+		break;
+	case IOCTL_TIUSB_RESET_PIPES:
+		printk (KERN_DEBUG "IOCTL_TIGLUSB_RESET_PIPES\n");
+		if (clear_pipes (s->dev))
+			ret = -EIO;
+		break;
+	default:
+		ret = -ENOTTY;
+		break;
+	}
+
+	up (&s->mutex);
+
+	return ret;
+}
+
+/* ----- kernel module registering ------------------------------------ */
+
+static struct file_operations tiglusb_fops = {
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	read:		tiglusb_read,
+	write:		tiglusb_write,
+	ioctl:		tiglusb_ioctl,
+	open:		tiglusb_open,
+	release:	tiglusb_release,
+};
+
+static int tiglusb_find_struct (void)
+{
+	int u;
+
+	for (u = 0; u < MAXTIGL; u++) {
+		ptiglusb_t s = &tiglusb[u];
+		if (!s->dev)
+			return u;
+	}
+
+	return -1;
+}
+
+/* --- initialisation code ------------------------------------- */
+
+static void *tiglusb_probe (struct usb_device *dev, unsigned int ifnum,
+			    const struct usb_device_id *id)
+{
+	int minor;
+	ptiglusb_t s;
+	char name[8];
+
+	printk ("tiglusb: probing vendor id 0x%x, device id 0x%x ifnum:%d\n",
+		dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+
+	/* 
+	 * We don't handle multiple configurations. As of version 0x0103 of 
+	 * the TIGL hardware, there's only 1 configuration. 
+	 */
+
+	if (dev->descriptor.bNumConfigurations != 1)
+		return NULL;
+
+	if ((dev->descriptor.idProduct != 0xe001) && (dev->descriptor.idVendor != 0x451))
+		return NULL;
+
+	if (usb_set_configuration (dev, dev->config[0].bConfigurationValue) < 0) {
+		printk ("tiglusb_probe: set_configuration failed\n");
+		return NULL;
+	}
+
+	minor = tiglusb_find_struct ();
+	if (minor == -1)
+		return NULL;
+
+	s = &tiglusb[minor];
+
+	down (&s->mutex);
+	s->remove_pending = 0;
+	s->dev = dev;
+	up (&s->mutex);
+	dbg ("bound to interface: %d", ifnum);
+
+	sprintf (name, "%d", s->minor);
+	printk ("tiglusb: registering to devfs : major = %d, minor = %d, node = %s\n", TIUSB_MAJOR,
+		(TIUSB_MINOR + s->minor), name);
+	s->devfs =
+	    devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, TIUSB_MAJOR,
+			    TIUSB_MINOR + s->minor, S_IFCHR | S_IRUGO | S_IWUGO, &tiglusb_fops,
+			    NULL);
+
+	/* Display firmware version */
+	printk ("tiglusb: link cable version %i.%02x\n",
+		dev->descriptor.bcdDevice >> 8, dev->descriptor.bcdDevice & 0xff);
+
+	return s;
+}
+
+static void tiglusb_disconnect (struct usb_device *dev, void *drv_context)
+{
+	ptiglusb_t s = (ptiglusb_t) drv_context;
+
+	if (!s || !s->dev)
+		printk ("bogus disconnect");
+
+	s->remove_pending = 1;
+	wake_up (&s->wait);
+	if (s->state == _started)
+		sleep_on (&s->remove_ok);
+	s->dev = NULL;
+	s->opened = 0;
+
+	/* cleanup now or later, on close */
+	if (!s->opened)
+		usblp_cleanup (s);
+	else
+		up (&s->mutex);
+
+	/* unregister device */
+	devfs_unregister (s->devfs);
+	s->devfs = NULL;
+	printk ("tiglusb: device disconnected\n");
+}
+
+static struct usb_device_id tiglusb_ids[] = {
+	{USB_DEVICE (0x0451, 0xe001)},
+	{}
+};
+
+MODULE_DEVICE_TABLE (usb, tiglusb_ids);
+
+static struct usb_driver tiglusb_driver = {
+	owner:		THIS_MODULE,
+	name:		"tiglusb",
+	probe:		tiglusb_probe,
+	disconnect:	tiglusb_disconnect,
+	id_table:	tiglusb_ids,
+};
+
+/* --- initialisation code ------------------------------------- */
+
+#ifndef MODULE
+/*      You must set these - there is no sane way to probe for this cable.
+ *      You can use 'tipar=timeout,delay' to set these now. */
+static int __init tiglusb_setup (char *str)
+{
+	int ints[2];
+
+	str = get_options (str, ARRAY_SIZE (ints), ints);
+
+	if (ints[0] > 0) {
+		timeout = ints[1];
+	}
+
+	return 1;
+}
+#endif
+
+static int __init tiglusb_init (void)
+{
+	unsigned u;
+	int result;
+
+	/* initialize struct */
+	for (u = 0; u < MAXTIGL; u++) {
+		ptiglusb_t s = &tiglusb[u];
+		memset (s, 0, sizeof (tiglusb_t));
+		init_MUTEX (&s->mutex);
+		s->dev = NULL;
+		s->minor = u;
+		s->opened = 0;
+		init_waitqueue_head (&s->wait);
+		init_waitqueue_head (&s->remove_ok);
+	}
+
+	/* register device */
+	if (devfs_register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
+		printk ("tiglusb: unable to get major %d\n", TIUSB_MAJOR);
+		return -EIO;
+	}
+
+	/* Use devfs, tree: /dev/ticables/usb/[0..3] */
+	devfs_handle = devfs_mk_dir (NULL, "ticables/usb", NULL);
+
+	/* register USB module */
+	result = usb_register (&tiglusb_driver);
+	if (result < 0) {
+		devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb");
+		return -1;
+	}
+
+	info (DRIVER_DESC ", " DRIVER_VERSION);
+
+	return 0;
+}
+
+static void __exit tiglusb_cleanup (void)
+{
+	usb_deregister (&tiglusb_driver);
+	devfs_unregister (devfs_handle);
+	devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb");
+}
+
+/* --------------------------------------------------------------------- */
+
+__setup ("tipar=", tiglusb_setup);
+module_init (tiglusb_init);
+module_exit (tiglusb_cleanup);
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_LICENSE (DRIVER_LICENSE);
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM (timeout, "i");
+MODULE_PARM_DESC (timeout, "Timeout (default=1.5 seconds)");
+
+/* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/misc/tiglusb.h b/drivers/usb/misc/tiglusb.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/tiglusb.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,55 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tiglusb - low level driver for SilverLink cable
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ * under the terms of the GNU General Public License.
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _TIGLUSB_H
+#define _TIGLUSB_H
+
+/*
+ * Max. number of devices supported
+ */
+#define MAXTIGL		16
+
+/*
+ * Max. packetsize for IN and OUT pipes
+ */
+#define BULK_RCV_MAX	32
+#define BULK_SND_MAX	32
+
+/*
+ * The driver context...
+ */
+
+typedef enum { _stopped=0, _started } driver_state_t;
+
+typedef struct
+{
+	struct usb_device	*dev;		/* USB device handle */
+	struct semaphore	mutex;		/* locks this struct */
+	struct semaphore	sem;
+
+	wait_queue_head_t	wait;		/* for timed waits */
+	wait_queue_head_t	remove_ok;
+
+	int		minor;			/* which minor dev #? */
+	devfs_handle_t	devfs;			/* devfs device */
+
+	driver_state_t	state;			/* started/stopped */
+	int		opened;			/* tru if open */
+	int	remove_pending;
+
+	char	rd_buf[BULK_RCV_MAX];		/* read  buffer */
+	char	wr_buf[BULK_SND_MAX];		/* write buffer */
+
+} tiglusb_t, *ptiglusb_t;
+
+extern devfs_handle_t usb_devfs_handle;		/* /dev/usb dir. */
+
+#endif
diff -Nru a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/misc/uss720.c	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,678 @@
+/*****************************************************************************/
+
+/*
+ *	uss720.c  --  USS720 USB Parport Cable.
+ *
+ *	Copyright (C) 1999
+ *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *	This program is free software; you can redistribute it and/or 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 on parport_pc.c
+ *
+ *  History:
+ *   0.1  04.08.99  Created
+ *   0.2  07.08.99  Some fixes mainly suggested by Tim Waugh
+ *		    Interrupt handling currently disabled because
+ *		    usb_request_irq crashes somewhere within ohci.c
+ *		    for no apparent reason (that is for me, anyway)
+ *		    ECP currently untested
+ *   0.3  10.08.99  fixing merge errors
+ *   0.4  13.08.99  Added Vendor/Product ID of Brad Hard's cable
+ *   0.5  20.09.99  usb_control_msg wrapper used
+ *        Nov01.00  usb_device_table support by Adam J. Richter
+ *        08.04.01  Identify version on module load.  gb
+ *
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/parport.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5"
+#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
+#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
+
+/* --------------------------------------------------------------------- */
+
+struct parport_uss720_private {
+	struct usb_device *usbdev;
+	void *irqhandle;
+	unsigned int irqpipe;
+	unsigned char reg[7];  /* USB registers */
+};
+
+/* --------------------------------------------------------------------- */
+
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
+{
+	struct parport_uss720_private *priv = pp->private_data;
+	struct usb_device *usbdev = priv->usbdev;
+	static const unsigned char regindex[9] = {
+		4, 0, 1, 5, 5, 0, 2, 3, 6
+	};
+	int ret;
+
+	if (!usbdev)
+		return -1;
+	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, HZ);
+	if (ret != 7) {
+		printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
+		       (unsigned int)reg, ret);
+		ret = -1;
+	} else {
+#if 0
+		printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
+		       (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
+		       (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
+		       (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
+#endif
+		/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
+		if (priv->reg[2] & priv->reg[1] & 0x10)
+			parport_generic_irq(0, pp, NULL);
+		ret = 0;
+	}
+	if (val)
+		*val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
+	return ret;
+}
+
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
+{
+	struct parport_uss720_private *priv = pp->private_data;
+	struct usb_device *usbdev = priv->usbdev;
+	int ret;
+
+	if (!usbdev)
+		return -1;
+	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, HZ);
+	if (ret) {
+		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 
+		       (unsigned int)reg, (unsigned int)val, ret);
+	} else {
+#if 0
+		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 
+		       (unsigned int)reg, (unsigned int)val);
+#endif
+	}
+	return ret;
+}
+
+/* --------------------------------------------------------------------- */
+
+/* ECR modes */
+#define ECR_SPP 00
+#define ECR_PS2 01
+#define ECR_PPF 02
+#define ECR_ECP 03
+#define ECR_EPP 04
+
+/* Safely change the mode bits in the ECR */
+static int change_mode(struct parport *pp, int m)
+{
+	struct parport_uss720_private *priv = pp->private_data;
+	int mode;
+
+	if (get_1284_register(pp, 6, NULL))
+		return -EIO;
+	/* Bits <7:5> contain the mode. */
+	mode = (priv->reg[2] >> 5) & 0x7;
+	if (mode == m)
+		return 0;
+	/* We have to go through mode 000 or 001 */
+	if (mode > ECR_PS2 && m > ECR_PS2)
+		if (change_mode(pp, ECR_PS2))
+			return -EIO;
+
+	if (m <= ECR_PS2 && !(priv->reg[1] & 0x20)) {
+		/* This mode resets the FIFO, so we may
+		 * have to wait for it to drain first. */
+		long expire = jiffies + pp->physport->cad->timeout;
+		switch (mode) {
+		case ECR_PPF: /* Parallel Port FIFO mode */
+		case ECR_ECP: /* ECP Parallel Port mode */
+			/* Poll slowly. */
+			for (;;) {
+				if (get_1284_register(pp, 6, NULL))
+					return -EIO;
+				if (priv->reg[2] & 0x01)
+					break;
+				if (time_after_eq (jiffies, expire))
+					/* The FIFO is stuck. */
+					return -EBUSY;
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout((HZ + 99) / 100);
+				if (signal_pending (current))
+					break;
+			}
+		}
+	}
+	/* Set the mode. */
+	if (set_1284_register(pp, 6, m << 5))
+		return -EIO;
+	return 0;
+}
+
+/*
+ * Clear TIMEOUT BIT in EPP MODE
+ */
+static int clear_epp_timeout(struct parport *pp)
+{
+	unsigned char stat;
+
+	if (get_1284_register(pp, 1, &stat))
+		return 1;
+	return stat & 1;
+}
+
+/*
+ * Access functions.
+ */
+#if 0
+static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
+{
+	struct parport *pp = (struct parport *)dev_id;
+	struct parport_uss720_private *priv = pp->private_data;	
+
+	if (usbstatus != 0 || len < 4 || !buffer)
+		return 1;
+	memcpy(priv->reg, buffer, 4);
+	/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
+	if (priv->reg[2] & priv->reg[1] & 0x10)
+		parport_generic_irq(0, pp, NULL);
+	return 1;
+}
+#endif
+
+static void parport_uss720_write_data(struct parport *pp, unsigned char d)
+{
+	set_1284_register(pp, 0, d);
+}
+
+static unsigned char parport_uss720_read_data(struct parport *pp)
+{
+	unsigned char ret;
+
+	if (get_1284_register(pp, 0, &ret))
+		return 0;
+	return ret;
+}
+
+static void parport_uss720_write_control(struct parport *pp, unsigned char d)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+
+	d = (d & 0xf) | (priv->reg[1] & 0xf0);
+	if (set_1284_register(pp, 2, d))
+		return;
+	priv->reg[1] = d;
+}
+
+static unsigned char parport_uss720_read_control(struct parport *pp)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	return priv->reg[1] & 0xf; /* Use soft copy */
+}
+
+static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned char mask, unsigned char val)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	unsigned char d;
+
+	mask &= 0x0f;
+	val &= 0x0f;
+	d = (priv->reg[1] & (~mask)) ^ val;
+	if (set_1284_register(pp, 2, d))
+		return 0;
+	priv->reg[1] = d;
+	return d & 0xf;
+}
+
+static unsigned char parport_uss720_read_status(struct parport *pp)
+{
+	unsigned char ret;
+
+	if (get_1284_register(pp, 1, &ret))
+		return 0;
+	return ret & 0xf8;
+}
+
+static void parport_uss720_disable_irq(struct parport *pp)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	unsigned char d;
+
+	d = priv->reg[1] & ~0x10;
+	if (set_1284_register(pp, 2, d))
+		return;
+	priv->reg[1] = d;
+}
+
+static void parport_uss720_enable_irq(struct parport *pp)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	unsigned char d;
+
+	d = priv->reg[1] | 0x10;
+	if (set_1284_register(pp, 2, d))
+		return;
+	priv->reg[1] = d;
+}
+
+static void parport_uss720_data_forward (struct parport *pp)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	unsigned char d;
+
+	d = priv->reg[1] & ~0x20;
+	if (set_1284_register(pp, 2, d))
+		return;
+	priv->reg[1] = d;
+}
+
+static void parport_uss720_data_reverse (struct parport *pp)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	unsigned char d;
+
+	d = priv->reg[1] | 0x20;
+	if (set_1284_register(pp, 2, d))
+		return;
+	priv->reg[1] = d;
+}
+
+static void parport_uss720_init_state(struct pardevice *dev, struct parport_state *s)
+{
+	s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
+	s->u.pc.ecr = 0x24;
+}
+
+static void parport_uss720_save_state(struct parport *pp, struct parport_state *s)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+
+	if (get_1284_register(pp, 2, NULL))
+		return;
+	s->u.pc.ctr = priv->reg[1];
+	s->u.pc.ecr = priv->reg[2];
+}
+
+static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
+{
+	set_1284_register(pp, 2, s->u.pc.ctr);
+	set_1284_register(pp, 6, s->u.pc.ecr);
+	get_1284_register(pp, 2, NULL);
+}
+
+static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	size_t got = 0;
+
+	if (change_mode(pp, ECR_EPP))
+		return 0;
+	for (; got < length; got++) {
+		if (get_1284_register(pp, 4, (char *)buf))
+			break;
+		((char*)buf)++;
+		if (priv->reg[0] & 0x01) {
+			clear_epp_timeout(pp);
+			break;
+		}
+	}
+	change_mode(pp, ECR_PS2);
+	return got;
+}
+
+static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags)
+{
+#if 0
+	struct parport_uss720_private *priv = pp->private_data;	
+	size_t written = 0;
+
+	if (change_mode(pp, ECR_EPP))
+		return 0;
+	for (; written < length; written++) {
+		if (set_1284_register(pp, 4, (char *)buf))
+			break;
+		((char*)buf)++;
+		if (get_1284_register(pp, 1, NULL))
+			break;
+		if (priv->reg[0] & 0x01) {
+			clear_epp_timeout(pp);
+			break;
+		}
+	}
+	change_mode(pp, ECR_PS2);
+	return written;
+#else
+	struct parport_uss720_private *priv = pp->private_data;
+	struct usb_device *usbdev = priv->usbdev;
+	int rlen;
+	int i;
+
+	if (!usbdev)
+		return 0;
+	if (change_mode(pp, ECR_EPP))
+		return 0;
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20);
+	if (i)
+		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buf, length, rlen);
+	change_mode(pp, ECR_PS2);
+	return rlen;
+#endif
+}
+
+static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	size_t got = 0;
+
+	if (change_mode(pp, ECR_EPP))
+		return 0;
+	for (; got < length; got++) {
+		if (get_1284_register(pp, 3, (char *)buf))
+			break;
+		((char*)buf)++;
+		if (priv->reg[0] & 0x01) {
+			clear_epp_timeout(pp);
+			break;
+		}
+	}
+	change_mode(pp, ECR_PS2);
+	return got;
+}
+
+static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags)
+{
+	struct parport_uss720_private *priv = pp->private_data;	
+	size_t written = 0;
+
+	if (change_mode(pp, ECR_EPP))
+		return 0;
+	for (; written < length; written++) {
+		if (set_1284_register(pp, 3, *(char *)buf))
+			break;
+		((char*)buf)++;
+		if (get_1284_register(pp, 1, NULL))
+			break;
+		if (priv->reg[0] & 0x01) {
+			clear_epp_timeout(pp);
+			break;
+		}
+	}
+	change_mode(pp, ECR_PS2);
+	return written;
+}
+
+static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buffer, size_t len, int flags)
+{
+	struct parport_uss720_private *priv = pp->private_data;
+	struct usb_device *usbdev = priv->usbdev;
+	int rlen;
+	int i;
+
+	if (!usbdev)
+		return 0;
+	if (change_mode(pp, ECR_ECP))
+		return 0;
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
+	if (i)
+		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
+	change_mode(pp, ECR_PS2);
+	return rlen;
+}
+
+static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, size_t len, int flags)
+{
+	struct parport_uss720_private *priv = pp->private_data;
+	struct usb_device *usbdev = priv->usbdev;
+	int rlen;
+	int i;
+
+	if (!usbdev)
+		return 0;
+	if (change_mode(pp, ECR_ECP))
+		return 0;
+	i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, HZ*20);
+	if (i)
+		printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %Zu rlen %u\n", buffer, len, rlen);
+	change_mode(pp, ECR_PS2);
+	return rlen;
+}
+
+static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags)
+{
+	size_t written = 0;
+
+	if (change_mode(pp, ECR_ECP))
+		return 0;
+	for (; written < len; written++) {
+		if (set_1284_register(pp, 5, *(char *)buffer))
+			break;
+		((char*)buffer)++;
+	}
+	change_mode(pp, ECR_PS2);
+	return written;
+}
+
+static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer, size_t len, int flags)
+{
+	struct parport_uss720_private *priv = pp->private_data;
+	struct usb_device *usbdev = priv->usbdev;
+	int rlen;
+	int i;
+
+	if (!usbdev)
+		return 0;
+	if (change_mode(pp, ECR_PPF))
+		return 0;
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
+	if (i)
+		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
+	change_mode(pp, ECR_PS2);
+	return rlen;
+}
+
+void parport_uss720_inc_use_count(void)
+{
+	MOD_INC_USE_COUNT;
+}
+
+void parport_uss720_dec_use_count(void)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+/* --------------------------------------------------------------------- */
+
+static struct parport_operations parport_uss720_ops = 
+{
+	parport_uss720_write_data,
+	parport_uss720_read_data,
+
+	parport_uss720_write_control,
+	parport_uss720_read_control,
+	parport_uss720_frob_control,
+
+	parport_uss720_read_status,
+
+	parport_uss720_enable_irq,
+	parport_uss720_disable_irq,
+
+	parport_uss720_data_forward,
+	parport_uss720_data_reverse,
+
+	parport_uss720_init_state,
+	parport_uss720_save_state,
+	parport_uss720_restore_state,
+
+	parport_uss720_inc_use_count,
+	parport_uss720_dec_use_count,
+
+	parport_uss720_epp_write_data,
+	parport_uss720_epp_read_data,
+	parport_uss720_epp_write_addr,
+	parport_uss720_epp_read_addr,
+
+	parport_uss720_ecp_write_data,
+	parport_uss720_ecp_read_data,
+	parport_uss720_ecp_write_addr,
+
+	parport_uss720_write_compat,
+	parport_ieee1284_read_nibble,
+	parport_ieee1284_read_byte,
+};
+
+/* --------------------------------------------------------------------- */
+
+static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum,
+			   const struct usb_device_id *id)
+{
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct parport_uss720_private *priv;
+	struct parport *pp;
+	int i;
+
+	printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
+	       usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
+
+	/* our known interfaces have 3 alternate settings */
+	if (usbdev->actconfig->interface[ifnum].num_altsetting != 3)
+		return NULL;
+
+	i = usb_set_interface(usbdev, ifnum, 2);
+	printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
+
+	interface = &usbdev->actconfig->interface[ifnum].altsetting[2];
+
+	/*
+	 * Allocate parport interface 
+	 */
+	printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
+
+	if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
+		return NULL;
+	if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
+		printk(KERN_WARNING "usb-uss720: could not register parport\n");
+		goto probe_abort;
+	}
+
+	pp->private_data = priv;
+	priv->usbdev = usbdev;
+	pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
+
+	/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
+	set_1284_register(pp, 7, 0x00);
+	set_1284_register(pp, 6, 0x30);  /* PS/2 mode */
+	set_1284_register(pp, 2, 0x0c);
+	/* debugging */
+	get_1284_register(pp, 0, NULL);
+	printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
+	       priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+
+	endpoint = &interface->endpoint[2];
+	printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->bEndpointAddress, endpoint->bInterval);
+#if 0
+	priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
+	i = usb_request_irq(usbdev, priv->irqpipe,
+				  uss720_irq, endpoint->bInterval,
+				  pp, &priv->irqhandle);
+	if (i) {
+		printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
+		goto probe_abort_port;
+	}
+#endif
+	parport_proc_register(pp);
+	parport_announce_port(pp);
+
+	MOD_INC_USE_COUNT;
+	return pp;
+
+#if 0
+probe_abort_port:
+	parport_unregister_port(pp);
+#endif
+probe_abort:
+	kfree(priv);
+	return NULL;
+}
+
+static void uss720_disconnect(struct usb_device *usbdev, void *ptr)
+{
+	struct parport *pp = (struct parport *)ptr;
+	struct parport_uss720_private *priv = pp->private_data;
+
+#if 0
+	usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
+#endif
+	priv->usbdev = NULL;
+	parport_proc_unregister(pp);
+	parport_unregister_port(pp);
+	kfree(priv);
+	MOD_DEC_USE_COUNT;
+}
+
+/* table of cables that work through this driver */
+static struct usb_device_id uss720_table [] = {
+	{ USB_DEVICE(0x047e, 0x1001) },
+	{ USB_DEVICE(0x0557, 0x2001) },
+	{ USB_DEVICE(0x0729, 0x1284) },
+	{ USB_DEVICE(0x1293, 0x0002) },
+	{ }						/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, uss720_table);
+
+
+static struct usb_driver uss720_driver = {
+	name:		"uss720",
+	probe:		uss720_probe,
+	disconnect:	uss720_disconnect,
+	id_table:	uss720_table,
+};
+
+/* --------------------------------------------------------------------- */
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+static int __init uss720_init(void)
+{
+	if (usb_register(&uss720_driver) < 0)
+		return -1;
+
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return 0;
+}
+
+static void __exit uss720_cleanup(void)
+{
+	usb_deregister(&uss720_driver);
+}
+
+module_init(uss720_init);
+module_exit(uss720_cleanup);
+
+/* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/net/Config.help b/drivers/usb/net/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,118 @@
+CONFIG_USB_CATC
+  Say Y if you want to use one of the following 10Mbps USB Ethernet
+  device based on the EL1210A chip. Supported devices are:
+    Belkin F5U011
+    Belkin F5U111
+    CATC NetMate
+    CATC NetMate II
+    smartBridges smartNIC
+
+  This driver makes the adapter appear as a normal Ethernet interface,
+  typically on eth0, if it is the only ethernet device, or perhaps on
+  eth1, if you have a PCI or ISA ethernet card installed.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called catc.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_CDCETHER
+  This driver supports devices conforming to the Communication Device
+  Class Ethernet Control Model.  This is used in some cable modems.
+  For more details on the specification, get the Communication Device
+  Class specification from <http://www.usb.org/>.
+
+  This driver should work with the following devices:
+        * Ericsson PipeRider (all variants)
+        * Motorola (DM100 and SB4100)
+        * Broadcom Cable Modem (reference design)
+        * Toshiba PCX1100U and possibly other cable modems
+
+  The device creates a network device (ethX, where X depends on what
+  other networking devices you have in use), as for a normal PCI
+  or ISA based ethernet network card.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called cdc-ether.o.  If you want to compile it 
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_KAWETH
+  Say Y here if you want to use one of the following 10Mbps only
+  USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
+       3Com 3C19250
+       ADS USB-10BT
+       ATEN USB Ethernet
+       ASANTE USB To Ethernet Adapter
+       AOX Endpoints USB Ethernet
+       Correga K.K.
+       D-Link DSB-650C and DU-E10
+       Entrega / Portgear E45
+       I-O DATA USB-ET/T
+       Jaton USB Ethernet Device Adapter
+       Kingston Technology USB Ethernet Adapter
+       Linksys USB10T
+       Mobility USB-Ethernet Adapter
+       NetGear EA-101
+       Peracom Enet and Enet2
+       Portsmith Express Ethernet Adapter
+       Shark Pocket Adapter
+       SMC 2202USB
+       Sony Vaio port extender
+
+  This driver is likely to work with most 10Mbps only USB Ethernet
+  adapters, including some "no brand" devices. It does NOT work on
+  SmartBridges smartNIC or on Belkin F5U111 devices - you should use
+  the CATC NetMate driver for those. If you are not sure which one
+  you need, select both, and the correct one should be selected for
+  you.
+
+  This driver makes the adapter appear as a normal Ethernet interface,
+  typically on eth0, if it is the only ethernet device, or perhaps on
+  eth1, if you have a PCI or ISA ethernet card installed.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called kaweth.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_PEGASUS
+  Say Y here if you know you have Pegasus or Pegasus-II based adapter.
+  If in doubt then look at linux/drivers/usb/pegasus.h for the complete
+  list of supported devices.
+  If your particular adapter is not in the list and you are _sure_ it
+  is Pegasus or Pegasus II based then send me (petkan@users.sourceforge.net)
+  vendor and device IDs.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called pegasus.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_RTL8150
+  Say Y here if you have RTL8150 based usb-ethernet adapter.
+  Send me (petkan@users.sourceforge.net) any comments you may have.
+  You can also check for updates at http://pegasus2.sourceforge.net/
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called rtl8150.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_USBNET
+  This driver supports network links over USB with USB "Network"
+  or "data transfer" cables, often used to network laptops to PCs.
+  Such cables have chips from suppliers such as Belkin/eTEK, GeneSys
+  (GeneLink), NetChip and Prolific. Intelligent USB devices could also
+  use this approach to provide Internet access, using standard USB
+  cabling. You can find these chips also on some motherboards with
+  USB PC2PC support.
+
+  These links will have names like "usb0", "usb1", etc.  They act
+  like two-node Ethernets, so you can use 802.1d Ethernet Bridging
+  (CONFIG_BRIDGE) to simplify your network routing.
+
+  This code is also available as a kernel module (code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usbnet.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
diff -Nru a/drivers/usb/net/Config.in b/drivers/usb/net/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,24 @@
+#
+# USB Network devices configuration
+#
+comment 'USB Network adaptors'
+if [ "$CONFIG_NET" = "n" ]; then
+   comment '  Networking support is needed for USB Networking device support'
+else
+   dep_tristate '  USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)' CONFIG_USB_CATC $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB CDC Ethernet support (EXPERIMENTAL)' CONFIG_USB_CDCETHER $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB KLSI KL5USB101-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_KAWETH $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB Pegasus/Pegasus-II based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB RTL8150 based ethernet device support (EXPERIMENTAL)' CONFIG_USB_RTL8150 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+   dep_tristate '  USB-to-USB Networking cable device support (EXPERIMENTAL)' CONFIG_USB_USBNET $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL
+fi
+
+# Turn on CONFIG_USB_NET if any of the drivers are compiled into the kernel to
+# make our Makefile logic a bit simpler
+if [ "$CONFIG_USB_PEGASUS" = "y" -o "$CONFIG_USB_RTL8150" = "y" -o "$CONFIG_USB_KAWETH" = "y" ]; then
+   define_bool CONFIG_USB_NET y
+fi
+if [ "$CONFIG_USB_CATC" = "y" -o "$CONFIG_USB_USBNET" = "y" -o "$CONFIG_USB_CDCETHER" = "y" ]; then
+   define_bool CONFIG_USB_NET y
+fi
+   
diff -Nru a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/Makefile	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,15 @@
+#
+# Makefile for USB Network drivers
+#
+
+O_TARGET	:= usb-net.o
+
+obj-$(CONFIG_USB_CATC)		+= catc.o
+obj-$(CONFIG_USB_CDCETHER)	+= cdc-ether.o
+obj-$(CONFIG_USB_KAWETH)	+= kaweth.o
+obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
+obj-$(CONFIG_USB_RTL8150)	+= rtl8150.o
+obj-$(CONFIG_USB_USBNET)	+= usbnet.o
+
+
+include $(TOPDIR)/Rules.make
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/catc.c	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,965 @@
+/*
+ *  Copyright (c) 2001 Vojtech Pavlik
+ *
+ *  CATC EL1210A NetMate USB Ethernet driver
+ *
+ *  Sponsored by SuSE
+ *
+ *  Based on the work of
+ *		Donald Becker
+ * 
+ *  Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
+ *    - adds support for Belkin F5U011
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or 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@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#undef DEBUG
+
+#include <linux/usb.h>
+
+/*
+ * Version information.
+ */
+
+#define DRIVER_VERSION "v2.8"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
+#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
+#define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Some defines.
+ */ 
+
+#define STATS_UPDATE		(HZ)	/* Time between stats updates */
+#define TX_TIMEOUT		(5*HZ)	/* Max time the queue can be stopped */
+#define PKT_SZ			1536	/* Max Ethernet packet size */
+#define RX_MAX_BURST		15	/* Max packets per rx buffer (> 0, < 16) */
+#define TX_MAX_BURST		15	/* Max full sized packets per tx buffer (> 0) */
+#define CTRL_QUEUE		16	/* Max control requests in flight (power of two) */
+#define RX_PKT_SZ		1600	/* Max size of receive packet for F5U011 */
+
+/*
+ * Control requests.
+ */
+
+enum control_requests {
+	ReadMem =	0xf1,
+	GetMac =	0xf2,
+	Reset =		0xf4,
+	SetMac =	0xf5,
+	SetRxMode =     0xf5,  /* F5U011 only */
+	WriteROM =	0xf8,
+	SetReg =	0xfa,
+	GetReg =	0xfb,
+	WriteMem =	0xfc,
+	ReadROM =	0xfd,
+};
+
+/*
+ * Registers.
+ */
+
+enum register_offsets {
+	TxBufCount =	0x20,
+	RxBufCount =	0x21,
+	OpModes =	0x22,
+	TxQed =		0x23,
+	RxQed =		0x24,
+	MaxBurst =	0x25,
+	RxUnit =	0x60,
+	EthStatus =	0x61,
+	StationAddr0 =	0x67,
+	EthStats =	0x69,
+	LEDCtrl =	0x81,
+};
+
+enum eth_stats {
+	TxSingleColl =	0x00,
+        TxMultiColl =	0x02,
+        TxExcessColl =	0x04,
+        RxFramErr =	0x06,
+};
+
+enum op_mode_bits {
+	Op3MemWaits =	0x03,
+	OpLenInclude =	0x08,
+	OpRxMerge =	0x10,
+	OpTxMerge =	0x20,
+	OpWin95bugfix =	0x40,
+	OpLoopback =	0x80,
+};
+
+enum rx_filter_bits {
+	RxEnable =	0x01,
+	RxPolarity =	0x02,
+	RxForceOK =	0x04,
+	RxMultiCast =	0x08,
+	RxPromisc =	0x10,
+	AltRxPromisc =  0x20, /* F5U011 uses different bit */
+};
+
+enum led_values {
+	LEDFast = 	0x01,
+	LEDSlow =	0x02,
+	LEDFlash =	0x03,
+	LEDPulse =	0x04,
+	LEDLink =	0x08,
+};
+
+enum link_status {
+	LinkNoChange = 0,
+	LinkGood     = 1,
+	LinkBad      = 2
+};
+
+/*
+ * The catc struct.
+ */
+
+#define CTRL_RUNNING	0
+#define RX_RUNNING	1
+#define TX_RUNNING	2
+
+struct catc {
+	struct net_device *netdev;
+	struct usb_device *usbdev;
+
+	struct net_device_stats stats;
+	unsigned long flags;
+
+	unsigned int tx_ptr, tx_idx;
+	unsigned int ctrl_head, ctrl_tail;
+	spinlock_t tx_lock, ctrl_lock;
+
+	u8 tx_buf[2][TX_MAX_BURST * (PKT_SZ + 2)];
+	u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)];
+	u8 irq_buf[2];
+	u8 ctrl_buf[64];
+	struct usb_ctrlrequest ctrl_dr;
+
+	struct timer_list timer;
+	u8 stats_buf[8];
+	u16 stats_vals[4];
+	unsigned long last_stats;
+
+	u8 multicast[64];
+
+	struct ctrl_queue {
+		u8 dir;
+		u8 request;
+		u16 value;
+		u16 index;
+		void *buf;
+		int len;
+		void (*callback)(struct catc *catc, struct ctrl_queue *q);
+	} ctrl_queue[CTRL_QUEUE];
+
+	struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
+
+	u8 is_f5u011;	/* Set if device is an F5U011 */
+	u8 rxmode[2];	/* Used for F5U011 */
+	atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
+};
+
+/*
+ * Useful macros.
+ */
+
+#define catc_get_mac(catc, mac)				catc_ctrl_msg(catc, USB_DIR_IN,  GetMac, 0, 0, mac,  6)
+#define catc_reset(catc)				catc_ctrl_msg(catc, USB_DIR_OUT, Reset, 0, 0, NULL, 0)
+#define catc_set_reg(catc, reg, val)			catc_ctrl_msg(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0)
+#define catc_get_reg(catc, reg, buf)			catc_ctrl_msg(catc, USB_DIR_IN,  GetReg, 0, reg, buf, 1)
+#define catc_write_mem(catc, addr, buf, size)		catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
+#define catc_read_mem(catc, addr, buf, size)		catc_ctrl_msg(catc, USB_DIR_IN,  ReadMem, 0, addr, buf, size)
+
+#define f5u011_rxmode(catc, rxmode)			catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
+#define f5u011_rxmode_async(catc, rxmode)		catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
+#define f5u011_mchash_async(catc, hash)			catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
+
+#define catc_set_reg_async(catc, reg, val)		catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
+#define catc_get_reg_async(catc, reg, cb)		catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
+#define catc_write_mem_async(catc, addr, buf, size)	catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
+
+/*
+ * Receive routines.
+ */
+
+static void catc_rx_done(struct urb *urb)
+{
+	struct catc *catc = urb->context;
+	u8 *pkt_start = urb->transfer_buffer;
+	struct sk_buff *skb;
+	int pkt_len, pkt_offset = 0;
+
+	if (!catc->is_f5u011) {
+		clear_bit(RX_RUNNING, &catc->flags);
+		pkt_offset = 2;
+	}
+
+	if (urb->status) {
+		dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
+		return;
+	}
+
+	do {
+		if(!catc->is_f5u011) {
+			pkt_len = le16_to_cpup((u16*)pkt_start);
+			if (pkt_len > urb->actual_length) {
+				catc->stats.rx_length_errors++;
+				catc->stats.rx_errors++;
+				break;
+			}
+		} else {
+			pkt_len = urb->actual_length;
+		}
+
+		if (!(skb = dev_alloc_skb(pkt_len)))
+			return;
+
+		skb->dev = catc->netdev;
+		eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
+		skb_put(skb, pkt_len);
+
+		skb->protocol = eth_type_trans(skb, catc->netdev);
+		netif_rx(skb);
+
+		catc->stats.rx_packets++;
+		catc->stats.rx_bytes += pkt_len;
+
+		/* F5U011 only does one packet per RX */
+		if (catc->is_f5u011)
+			break;
+		pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
+
+	} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
+
+	catc->netdev->last_rx = jiffies;
+
+	if (catc->is_f5u011) {
+		if (atomic_read(&catc->recq_sz)) {
+			int status;
+			atomic_dec(&catc->recq_sz);
+			dbg("getting extra packet");
+			urb->dev = catc->usbdev;
+			if ((status = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
+				dbg("submit(rx_urb) status %d", status);
+			}
+		} else {
+			clear_bit(RX_RUNNING, &catc->flags);
+		}
+	}
+}
+
+static void catc_irq_done(struct urb *urb)
+{
+	struct catc *catc = urb->context;
+	u8 *data = urb->transfer_buffer;
+	int status;
+	unsigned int hasdata = 0, linksts = LinkNoChange;
+
+	if (!catc->is_f5u011) {
+		hasdata = data[1] & 0x80;
+		if (data[1] & 0x40)
+			linksts = LinkGood;
+		else if (data[1] & 0x20)
+			linksts = LinkBad;
+	} else {
+		hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
+		if (data[0] == 0x90)
+			linksts = LinkGood;
+		else if (data[0] == 0xA0)
+			linksts = LinkBad;
+	}
+
+	if (urb->status) {
+		dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
+		return;
+	}
+
+	if (linksts == LinkGood) {
+		netif_carrier_on(catc->netdev);
+		dbg("link ok");
+	}
+
+	if (linksts == LinkBad) {
+		netif_carrier_off(catc->netdev);
+		dbg("link bad");
+	}
+
+	if (hasdata) {
+		if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
+			if (catc->is_f5u011)
+				atomic_inc(&catc->recq_sz);
+		} else {
+			catc->rx_urb->dev = catc->usbdev;
+			if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
+				err("submit(rx_urb) status %d", status);
+			}
+		} 
+	}
+}
+
+/*
+ * Transmit routines.
+ */
+
+static void catc_tx_run(struct catc *catc)
+{
+	int status;
+
+	if (catc->is_f5u011)
+		catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
+
+	catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
+	catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
+	catc->tx_urb->dev = catc->usbdev;
+
+	if ((status = usb_submit_urb(catc->tx_urb, GFP_KERNEL)) < 0)
+		err("submit(tx_urb), status %d", status);
+
+	catc->tx_idx = !catc->tx_idx;
+	catc->tx_ptr = 0;
+
+	catc->netdev->trans_start = jiffies;
+}
+
+static void catc_tx_done(struct urb *urb)
+{
+	struct catc *catc = urb->context;
+	unsigned long flags;
+
+	if (urb->status == -ECONNRESET) {
+		dbg("Tx Reset.");
+		urb->transfer_flags &= ~USB_ASYNC_UNLINK;
+		urb->status = 0;
+		catc->netdev->trans_start = jiffies;
+		catc->stats.tx_errors++;
+		clear_bit(TX_RUNNING, &catc->flags);
+		netif_wake_queue(catc->netdev);
+		return;
+	}
+
+	if (urb->status) {
+		dbg("tx_done, status %d, length %d", urb->status, urb->actual_length);
+		return;
+	}
+
+	spin_lock_irqsave(&catc->tx_lock, flags);
+
+	if (catc->tx_ptr)
+		catc_tx_run(catc);
+	else
+		clear_bit(TX_RUNNING, &catc->flags);
+
+	netif_wake_queue(catc->netdev);
+
+	spin_unlock_irqrestore(&catc->tx_lock, flags);
+}
+
+static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct catc *catc = netdev->priv;
+	unsigned long flags;
+	char *tx_buf;
+
+	spin_lock_irqsave(&catc->tx_lock, flags);
+
+	catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
+	tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
+	*((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
+	memcpy(tx_buf + 2, skb->data, skb->len);
+	catc->tx_ptr += skb->len + 2;
+
+	if (!test_and_set_bit(TX_RUNNING, &catc->flags))
+		catc_tx_run(catc);
+
+	if ((catc->is_f5u011 && catc->tx_ptr)
+	     || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
+		netif_stop_queue(netdev);
+
+	spin_unlock_irqrestore(&catc->tx_lock, flags);
+
+	catc->stats.tx_bytes += skb->len;
+	catc->stats.tx_packets++;
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static void catc_tx_timeout(struct net_device *netdev)
+{
+	struct catc *catc = netdev->priv;
+
+	warn("Transmit timed out.");
+	catc->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+	usb_unlink_urb(catc->tx_urb);
+}
+
+/*
+ * Control messages.
+ */
+
+static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
+{
+        int retval = usb_control_msg(catc->usbdev,
+		dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0),
+		 request, 0x40 | dir, value, index, buf, len, HZ);
+        return retval < 0 ? retval : 0;
+}
+
+static void catc_ctrl_run(struct catc *catc)
+{
+	struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
+	struct usb_device *usbdev = catc->usbdev;
+	struct urb *urb = catc->ctrl_urb;
+	struct usb_ctrlrequest *dr = &catc->ctrl_dr;
+	int status;
+
+	dr->bRequest = q->request;
+	dr->bRequestType = 0x40 | q->dir;
+	dr->wValue = cpu_to_le16(q->value);
+	dr->wIndex = cpu_to_le16(q->index);
+	dr->wLength = cpu_to_le16(q->len);
+
+        urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);
+	urb->transfer_buffer_length = q->len;
+	urb->transfer_buffer = catc->ctrl_buf;
+	urb->setup_packet = (void *) dr;
+	urb->dev = usbdev;
+
+	if (!q->dir && q->buf && q->len)
+		memcpy(catc->ctrl_buf, q->buf, q->len);
+
+	if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))
+		err("submit(ctrl_urb) status %d", status);
+}
+
+static void catc_ctrl_done(struct urb *urb)
+{
+	struct catc *catc = urb->context;
+	struct ctrl_queue *q;
+	unsigned long flags;
+
+	if (urb->status)
+		dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
+
+	spin_lock_irqsave(&catc->ctrl_lock, flags);
+
+	q = catc->ctrl_queue + catc->ctrl_tail;
+
+	if (q->dir) {
+		if (q->buf && q->len)
+			memcpy(q->buf, catc->ctrl_buf, q->len);
+		else
+			q->buf = catc->ctrl_buf;
+	}
+
+	if (q->callback)
+		q->callback(catc, q);
+
+	catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
+
+	if (catc->ctrl_head != catc->ctrl_tail)
+		catc_ctrl_run(catc);
+	else
+		clear_bit(CTRL_RUNNING, &catc->flags);
+
+	spin_unlock_irqrestore(&catc->ctrl_lock, flags);
+}
+
+static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value,
+	u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q))
+{
+	struct ctrl_queue *q;
+	int retval = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&catc->ctrl_lock, flags);
+	
+	q = catc->ctrl_queue + catc->ctrl_head;
+
+	q->dir = dir;
+	q->request = request;
+	q->value = value;
+	q->index = index;
+	q->buf = buf;
+	q->len = len;
+	q->callback = callback;
+
+	catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1);
+
+	if (catc->ctrl_head == catc->ctrl_tail) {
+		err("ctrl queue full");
+		catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1);
+		retval = -1;
+	}
+
+	if (!test_and_set_bit(CTRL_RUNNING, &catc->flags))
+		catc_ctrl_run(catc);
+
+	spin_unlock_irqrestore(&catc->ctrl_lock, flags);
+
+	return retval;
+}
+
+/*
+ * Statistics.
+ */
+
+static void catc_stats_done(struct catc *catc, struct ctrl_queue *q)
+{
+	int index = q->index - EthStats;
+	u16 data, last;
+
+	catc->stats_buf[index] = *((char *)q->buf);
+
+	if (index & 1)
+		return;
+
+	data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1];
+	last = catc->stats_vals[index >> 1];
+
+	switch (index) {
+		case TxSingleColl:
+		case TxMultiColl:
+			catc->stats.collisions += data - last;
+			break;
+		case TxExcessColl:
+			catc->stats.tx_aborted_errors += data - last;
+			catc->stats.tx_errors += data - last;
+			break;
+		case RxFramErr:
+			catc->stats.rx_frame_errors += data - last;
+			catc->stats.rx_errors += data - last;
+			break;
+	}
+
+	catc->stats_vals[index >> 1] = data;
+}
+
+static void catc_stats_timer(unsigned long data)
+{
+	struct catc *catc = (void *) data;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done);
+
+	mod_timer(&catc->timer, jiffies + STATS_UPDATE);
+}
+
+static struct net_device_stats *catc_get_stats(struct net_device *netdev)
+{
+	struct catc *catc = netdev->priv;
+	return &catc->stats;
+}
+
+/*
+ * Receive modes. Broadcast, Multicast, Promisc.
+ */
+
+static void catc_multicast(unsigned char *addr, u8 *multicast)
+{
+	u32 crc;
+
+	crc = ether_crc_le(6, addr);
+	multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
+}
+
+static void catc_set_multicast_list(struct net_device *netdev)
+{
+	struct catc *catc = netdev->priv;
+	struct dev_mc_list *mc;
+	u8 broadcast[6];
+	u8 rx = RxEnable | RxPolarity | RxMultiCast;
+	int i;
+
+	memset(broadcast, 0xff, 6);
+	memset(catc->multicast, 0, 64);
+
+	catc_multicast(broadcast, catc->multicast);
+	catc_multicast(netdev->dev_addr, catc->multicast);
+
+	if (netdev->flags & IFF_PROMISC) {
+		memset(catc->multicast, 0xff, 64);
+		rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
+	} 
+
+	if (netdev->flags & IFF_ALLMULTI) {
+		memset(catc->multicast, 0xff, 64);
+	} else {
+		for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
+			u32 crc = ether_crc_le(6, mc->dmi_addr);
+			if (!catc->is_f5u011) {
+				catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
+			} else {
+				catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
+			}
+		}
+	}
+	if (!catc->is_f5u011) {
+		catc_set_reg_async(catc, RxUnit, rx);
+		catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
+	} else {
+		f5u011_mchash_async(catc, catc->multicast);
+		if (catc->rxmode[0] != rx) {
+			catc->rxmode[0] = rx;
+			dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
+			f5u011_rxmode_async(catc, catc->rxmode);
+		}
+	}
+}
+
+/*
+ * ioctl's
+ */
+static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+{
+        struct catc *catc = dev->priv;
+        u32 cmd;
+	char tmp[40];
+        
+        if (get_user(cmd, (u32 *)useraddr))
+                return -EFAULT;
+
+        switch (cmd) {
+        /* get driver info */
+        case ETHTOOL_GDRVINFO: {
+                struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+                strncpy(info.driver, SHORT_DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+                strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+		sprintf(tmp, "usb%d:%d", catc->usbdev->bus->busnum, catc->usbdev->devnum);
+                strncpy(info.bus_info, tmp,ETHTOOL_BUSINFO_LEN);
+                if (copy_to_user(useraddr, &info, sizeof(info)))
+                        return -EFAULT;
+                return 0;
+        }
+
+	/* get settings */
+	case ETHTOOL_GSET:
+		if (catc->is_f5u011) {
+			struct ethtool_cmd ecmd = { ETHTOOL_GSET, 
+						    SUPPORTED_10baseT_Half | SUPPORTED_TP, 
+						    ADVERTISED_10baseT_Half | ADVERTISED_TP, 
+						    SPEED_10, 
+						    DUPLEX_HALF, 
+						    PORT_TP, 
+						    0, 
+						    XCVR_INTERNAL, 
+						    AUTONEG_DISABLE, 
+						    1, 
+						    1 
+			};
+			if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+				return -EFAULT;
+			return 0;
+		} else {
+			return -EOPNOTSUPP;
+		}
+
+        /* get link status */
+        case ETHTOOL_GLINK: {
+                struct ethtool_value edata = {ETHTOOL_GLINK};
+                edata.data = netif_carrier_ok(dev);
+                if (copy_to_user(useraddr, &edata, sizeof(edata)))
+                        return -EFAULT;
+                return 0;
+        }
+	}
+        
+        return -EOPNOTSUPP;
+}
+
+static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+        switch(cmd) {
+        case SIOCETHTOOL:
+                return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+        default:
+                return -EOPNOTSUPP;
+        }
+}
+
+
+/*
+ * Open, close.
+ */
+
+static int catc_open(struct net_device *netdev)
+{
+	struct catc *catc = netdev->priv;
+	int status;
+
+	catc->irq_urb->dev = catc->usbdev;
+	if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) {
+		err("submit(irq_urb) status %d", status);
+		return -1;
+	}
+
+	netif_start_queue(netdev);
+
+	if (!catc->is_f5u011)
+		mod_timer(&catc->timer, jiffies + STATS_UPDATE);
+
+	return 0;
+}
+
+static int catc_stop(struct net_device *netdev)
+{
+	struct catc *catc = netdev->priv;
+
+	netif_stop_queue(netdev);
+
+	if (!catc->is_f5u011)
+		del_timer_sync(&catc->timer);
+
+	usb_unlink_urb(catc->rx_urb);
+	usb_unlink_urb(catc->tx_urb);
+	usb_unlink_urb(catc->irq_urb);
+	usb_unlink_urb(catc->ctrl_urb);
+
+	return 0;
+}
+
+/*
+ * USB probe, disconnect.
+ */
+
+static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id)
+{
+	struct net_device *netdev;
+	struct catc *catc;
+	u8 broadcast[6];
+	int i, pktsz;
+
+	if (usb_set_interface(usbdev, ifnum, 1)) {
+                err("Can't set altsetting 1.");
+		return NULL;
+	}
+
+	catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
+	if (!catc)
+		return NULL;
+
+	memset(catc, 0, sizeof(struct catc));
+
+	netdev = init_etherdev(0, 0);
+	if (!netdev) {
+		kfree(catc);
+		return NULL;
+	}
+
+	netdev->open = catc_open;
+	netdev->hard_start_xmit = catc_hard_start_xmit;
+	netdev->stop = catc_stop;
+	netdev->get_stats = catc_get_stats;
+	netdev->tx_timeout = catc_tx_timeout;
+	netdev->watchdog_timeo = TX_TIMEOUT;
+	netdev->set_multicast_list = catc_set_multicast_list;
+	netdev->do_ioctl = catc_ioctl;
+	netdev->priv = catc;
+
+	catc->usbdev = usbdev;
+	catc->netdev = netdev;
+
+	catc->tx_lock = SPIN_LOCK_UNLOCKED;
+	catc->ctrl_lock = SPIN_LOCK_UNLOCKED;
+
+	init_timer(&catc->timer);
+	catc->timer.data = (long) catc;
+	catc->timer.function = catc_stats_timer;
+
+	catc->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
+	catc->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	catc->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	catc->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
+	    (!catc->rx_urb) || (!catc->irq_urb)) {
+		err("No free urbs available.");
+		if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
+		if (catc->tx_urb)   usb_free_urb(catc->tx_urb);
+		if (catc->rx_urb)   usb_free_urb(catc->rx_urb);
+		if (catc->irq_urb)  usb_free_urb(catc->irq_urb);
+		kfree(netdev);
+		kfree(catc);
+		return NULL;
+	}
+
+	/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
+	if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
+	   catc->usbdev->descriptor.bcdDevice == 0x0130	) {
+		dbg("Testing for f5u011");
+		catc->is_f5u011 = 1;		
+		atomic_set(&catc->recq_sz, 0);
+		pktsz = RX_PKT_SZ;
+	} else {
+		pktsz = RX_MAX_BURST * (PKT_SZ + 2);
+	}
+	
+	FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
+		NULL, NULL, 0, catc_ctrl_done, catc);
+
+	FILL_BULK_URB(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1),
+		NULL, 0, catc_tx_done, catc);
+
+	FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
+		catc->rx_buf, pktsz, catc_rx_done, catc);
+
+	FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
+                catc->irq_buf, 2, catc_irq_done, catc, 1);
+
+	if (!catc->is_f5u011) {
+		dbg("Checking memory size\n");
+
+		i = 0x12345678;
+		catc_write_mem(catc, 0x7a80, &i, 4);
+		i = 0x87654321;	
+		catc_write_mem(catc, 0xfa80, &i, 4);
+		catc_read_mem(catc, 0x7a80, &i, 4);
+	  
+		switch (i) {
+		case 0x12345678:
+			catc_set_reg(catc, TxBufCount, 8);
+			catc_set_reg(catc, RxBufCount, 32);
+			dbg("64k Memory\n");
+			break;
+		default:
+			warn("Couldn't detect memory size, assuming 32k");
+		case 0x87654321:
+			catc_set_reg(catc, TxBufCount, 4);
+			catc_set_reg(catc, RxBufCount, 16);
+			dbg("32k Memory\n");
+			break;
+		}
+	  
+		dbg("Getting MAC from SEEROM.");
+	  
+		catc_get_mac(catc, netdev->dev_addr);
+		
+		dbg("Setting MAC into registers.");
+	  
+		for (i = 0; i < 6; i++)
+			catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
+		
+		dbg("Filling the multicast list.");
+	  
+		memset(broadcast, 0xff, 6);
+		catc_multicast(broadcast, catc->multicast);
+		catc_multicast(netdev->dev_addr, catc->multicast);
+		catc_write_mem(catc, 0xfa80, catc->multicast, 64);
+		
+		dbg("Clearing error counters.");
+		
+		for (i = 0; i < 8; i++)
+			catc_set_reg(catc, EthStats + i, 0);
+		catc->last_stats = jiffies;
+		
+		dbg("Enabling.");
+		
+		catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
+		catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
+		catc_set_reg(catc, LEDCtrl, LEDLink);
+		catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
+	} else {
+		dbg("Performing reset\n");
+		catc_reset(catc);
+		catc_get_mac(catc, netdev->dev_addr);
+		
+		dbg("Setting RX Mode");
+		catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
+		catc->rxmode[1] = 0;
+		f5u011_rxmode(catc, catc->rxmode);
+	}
+	dbg("Init done.");
+	printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
+	       netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
+	       usbdev->bus->busnum, usbdev->devnum, ifnum);
+	for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
+	printk("%2.2x.\n", netdev->dev_addr[i]);
+	return catc;
+}
+
+static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
+{
+	struct catc *catc = dev_ptr;
+	unregister_netdev(catc->netdev);
+	usb_free_urb(catc->ctrl_urb);
+	usb_free_urb(catc->tx_urb);
+	usb_free_urb(catc->rx_urb);
+	usb_free_urb(catc->irq_urb);
+	kfree(catc->netdev);
+	kfree(catc);
+}
+
+/*
+ * Module functions and tables.
+ */
+
+static struct usb_device_id catc_id_table [] = {
+	{ USB_DEVICE(0x0423, 0xa) },	/* CATC Netmate, Belkin F5U011 */
+	{ USB_DEVICE(0x0423, 0xc) },	/* CATC Netmate II, Belkin F5U111 */
+	{ USB_DEVICE(0x08d1, 0x1) },	/* smartBridges smartNIC */
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, catc_id_table);
+
+static struct usb_driver catc_driver = {
+	name:		"catc",
+	probe:		catc_probe,
+	disconnect:	catc_disconnect,
+	id_table:	catc_id_table,
+};
+
+static int __init catc_init(void)
+{
+	info(DRIVER_VERSION " " DRIVER_DESC);
+	usb_register(&catc_driver);
+	return 0;
+}
+
+static void __exit catc_exit(void)
+{
+	usb_deregister(&catc_driver);
+}
+
+module_init(catc_init);
+module_exit(catc_exit);
diff -Nru a/drivers/usb/net/cdc-ether.c b/drivers/usb/net/cdc-ether.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/cdc-ether.c	Sun Apr 14 12:16:55 2002
@@ -0,0 +1,1365 @@
+// Portions of this file taken from 
+// Petko Manolov - Petkan (petkan@dce.bg)
+// from his driver pegasus.c
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+#include "cdc-ether.h"
+
+static const char *version = __FILE__ ": v0.98.5 22 Sep 2001 Brad Hards and another";
+
+/* Take any CDC device, and sort it out in probe() */
+static struct usb_device_id CDCEther_ids[] = {
+	{ USB_DEVICE_INFO(USB_CLASS_COMM, 0, 0) },
+	{ } /* Terminating null entry */
+};
+
+/* 
+ * module parameter that provides an alternate upper limit on the 
+ * number of multicast filters we use, with a default to use all
+ * the filters available to us. Note that the actual number used
+ * is the lesser of this parameter and the number returned in the
+ * descriptor for the particular device. See Table 41 of the CDC
+ * spec for more info on the descriptor limit.
+ */
+static int multicast_filter_limit = 32767;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Callback routines from USB device /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static void read_bulk_callback( struct urb *urb )
+{
+	ether_dev_t *ether_dev = urb->context;
+	struct net_device *net;
+	int count = urb->actual_length, res;
+	struct sk_buff	*skb;
+
+	// Sanity check 
+	if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
+		dbg("BULK IN callback but driver is not active!");
+		return;
+	}
+
+	net = ether_dev->net;
+	if ( !netif_device_present(net) ) {
+		// Somebody killed our network interface...
+		return;
+	}
+
+	if ( ether_dev->flags & CDC_ETHER_RX_BUSY ) {
+		// Are we already trying to receive a frame???
+		ether_dev->stats.rx_errors++;
+		dbg("ether_dev Rx busy");
+		return;
+	}
+
+	// We are busy, leave us alone!
+	ether_dev->flags |= CDC_ETHER_RX_BUSY;
+
+	switch ( urb->status ) {
+		case 0:
+			break;
+		case -ETIMEDOUT:
+			dbg( "no repsonse in BULK IN" );
+			ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
+			break;
+		default:
+			dbg( "%s: RX status %d", net->name, urb->status );
+			goto goon;
+	}
+
+	// Check to make sure we got some data...
+	if ( !count ) {
+		// We got no data!!!
+		goto goon;
+	}
+
+	// Tell the kernel we want some memory
+	if ( !(skb = dev_alloc_skb(count)) ) {
+		// We got no receive buffer.
+		goto goon;
+	}
+
+	// Here's where it came from
+	skb->dev = net;
+	
+	// Now we copy it over
+	eth_copy_and_sum(skb, ether_dev->rx_buff, count, 0);
+	
+	// Not sure
+	skb_put(skb, count);
+	// Not sure here either
+	skb->protocol = eth_type_trans(skb, net);
+	
+	// Ship it off to the kernel
+	netif_rx(skb);
+	
+	// update out statistics
+	ether_dev->stats.rx_packets++;
+	ether_dev->stats.rx_bytes += count;
+
+goon:
+	// Prep the USB to wait for another frame
+	FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
+			usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
+			ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
+			read_bulk_callback, ether_dev );
+			
+	// Give this to the USB subsystem so it can tell us 
+	// when more data arrives.
+	if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) ) {
+		warn( __FUNCTION__ " failed submint rx_urb %d", res);
+	}
+	
+	// We are no longer busy, show us the frames!!!
+	ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
+}
+
+static void write_bulk_callback( struct urb *urb )
+{
+	ether_dev_t *ether_dev = urb->context;
+
+	// Sanity check
+	if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
+		// We are insane!!!
+		err( "write_bulk_callback: device not running" );
+		return;
+	}
+
+	// Do we still have a valid kernel network device?
+	if ( !netif_device_present(ether_dev->net) ) {
+		// Someone killed our network interface.
+		err( "write_bulk_callback: net device not present" );
+		return;
+	}
+
+	// Hmm...  What on Earth could have happened???
+	if ( urb->status ) {
+		info("%s: TX status %d", ether_dev->net->name, urb->status);
+	}
+
+	// Update the network interface and tell it we are
+	// ready for another frame
+	ether_dev->net->trans_start = jiffies;
+	netif_wake_queue( ether_dev->net );
+}
+
+//static void intr_callback( struct urb *urb )
+//{
+//	ether_dev_t *ether_dev = urb->context;
+//	struct net_device *net;
+//	__u8	*d;
+//
+//	if ( !ether_dev )
+//		return;
+//		
+//	switch ( urb->status ) {
+//		case 0:
+//			break;
+//		case -ENOENT:
+//			return;
+//		default:
+//			info("intr status %d", urb->status);
+//	}
+//
+//	d = urb->transfer_buffer;
+//	net = ether_dev->net;
+//	if ( d[0] & 0xfc ) {
+//		ether_dev->stats.tx_errors++;
+//		if ( d[0] & TX_UNDERRUN )
+//			ether_dev->stats.tx_fifo_errors++;
+//		if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
+//			ether_dev->stats.tx_aborted_errors++;
+//		if ( d[0] & LATE_COL )
+//			ether_dev->stats.tx_window_errors++;
+//		if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
+//			ether_dev->stats.tx_carrier_errors++;
+//	}
+//}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines for turning net traffic on and off on the USB side ///////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static inline int enable_net_traffic( ether_dev_t *ether_dev )
+{
+	struct usb_device *usb = ether_dev->usb;
+
+	// Here would be the time to set the data interface to the configuration where
+	// it has two endpoints that use a protocol we can understand.
+
+	if (usb_set_interface( usb, 
+	                        ether_dev->data_bInterfaceNumber, 
+	                        ether_dev->data_bAlternateSetting_with_traffic ) )  {
+		err("usb_set_interface() failed" );
+		err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
+		err("To alternate setting       %d", ether_dev->data_bAlternateSetting_with_traffic);
+		return -1;
+	}
+	return 0;
+}
+
+static inline void disable_net_traffic( ether_dev_t *ether_dev )
+{
+	// The thing to do is to set the data interface to the alternate setting that has
+	// no endpoints.  This is what the spec suggests.
+
+	if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
+		if (usb_set_interface( ether_dev->usb, 
+		                        ether_dev->data_bInterfaceNumber, 
+		                        ether_dev->data_bAlternateSetting_without_traffic ) ) 	{
+			err("usb_set_interface() failed");
+		}
+	} else {
+		// Some devices just may not support this...
+		warn("No way to disable net traffic");
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Callback routines for kernel Ethernet Device //////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static void CDCEther_tx_timeout( struct net_device *net )
+{
+	ether_dev_t *ether_dev = net->priv;
+
+	// Sanity check
+	if ( !ether_dev ) {
+		// Seems to be a case of insanity here
+		return;
+	}
+
+	// Tell syslog we are hosed.
+	warn("%s: Tx timed out.", net->name);
+	
+	// Tear the waiting frame off the list
+	ether_dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+	usb_unlink_urb( ether_dev->tx_urb );
+	
+	// Update statistics
+	ether_dev->stats.tx_errors++;
+}
+
+static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net )
+{
+	ether_dev_t	*ether_dev = net->priv;
+	int 	count;
+	int 	res;
+
+	// If we are told to transmit an ethernet frame that fits EXACTLY 
+	// into an integer number of USB packets, we force it to send one 
+	// more byte so the device will get a runt USB packet signalling the 
+	// end of the ethernet frame
+	if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) {
+		// It was not an exact multiple
+		// no need to add anything extra
+		count = skb->len;
+	} else {
+		// Add one to make it NOT an exact multiple
+		count = skb->len + 1;
+	}
+
+	// Tell the kernel, "No more frames 'til we are done
+	// with this one.'
+	netif_stop_queue( net );
+
+	// Copy it from kernel memory to OUR memory
+	memcpy(ether_dev->tx_buff, skb->data, skb->len);
+
+	// Fill in the URB for shipping it out.
+	FILL_BULK_URB( ether_dev->tx_urb, ether_dev->usb,
+			usb_sndbulkpipe(ether_dev->usb, ether_dev->data_ep_out),
+			ether_dev->tx_buff, ether_dev->wMaxSegmentSize, 
+			write_bulk_callback, ether_dev );
+
+	// Tell the URB how much it will be transporting today
+	ether_dev->tx_urb->transfer_buffer_length = count;
+	
+	// Send the URB on its merry way.
+	if ((res = usb_submit_urb(ether_dev->tx_urb, GFP_KERNEL)))  {
+		// Hmm...  It didn't go. Tell someone...
+		warn("failed tx_urb %d", res);
+		// update some stats...
+		ether_dev->stats.tx_errors++;
+		// and tell the kernel to give us another.
+		// Maybe we'll get it right next time.
+		netif_start_queue( net );
+	} else {
+		// Okay, it went out.
+		// Update statistics
+		ether_dev->stats.tx_packets++;
+		ether_dev->stats.tx_bytes += skb->len;
+		// And tell the kernel when the last transmit occurred.
+		net->trans_start = jiffies;
+	}
+
+	// We are done with the kernel's memory
+	dev_kfree_skb(skb);
+
+	// We are done here.
+	return 0;
+}
+
+static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
+{
+	// Easy enough!
+	return &((ether_dev_t *)net->priv)->stats;
+}
+
+static int CDCEther_open(struct net_device *net)
+{
+	ether_dev_t *ether_dev = (ether_dev_t *)net->priv;
+	int	res;
+
+	// Turn on the USB and let the packets flow!!!
+	if ( (res = enable_net_traffic( ether_dev )) ) {
+		err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
+		return -EIO;
+	}
+
+	// Prep a receive URB
+	FILL_BULK_URB( ether_dev->rx_urb, ether_dev->usb,
+			usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
+			ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
+			read_bulk_callback, ether_dev );
+
+	// Put it out there so the device can send us stuff
+	if ( (res = usb_submit_urb(ether_dev->rx_urb, GFP_KERNEL)) )
+	{
+		// Hmm...  Okay...
+		warn( __FUNCTION__ " failed rx_urb %d", res );
+	}
+
+	// Tell the kernel we are ready to start receiving from it
+	netif_start_queue( net );
+	
+	// We are up and running.
+	ether_dev->flags |= CDC_ETHER_RUNNING;
+
+	// Let's get ready to move frames!!!
+	return 0;
+}
+
+static int CDCEther_close( struct net_device *net )
+{
+	ether_dev_t	*ether_dev = net->priv;
+
+	// We are no longer running.
+	ether_dev->flags &= ~CDC_ETHER_RUNNING;
+	
+	// Tell the kernel to stop sending us stuff
+	netif_stop_queue( net );
+	
+	// If we are not already unplugged, turn off USB
+	// traffic
+	if ( !(ether_dev->flags & CDC_ETHER_UNPLUG) ) {
+		disable_net_traffic( ether_dev );
+	}
+
+	// We don't need the URBs anymore.
+	usb_unlink_urb( ether_dev->rx_urb );
+	usb_unlink_urb( ether_dev->tx_urb );
+	usb_unlink_urb( ether_dev->intr_urb );
+	
+	// That's it.  I'm done.
+	return 0;
+}
+
+static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+{
+	//__u16 *data = (__u16 *)&rq->ifr_data;
+	//ether_dev_t	*ether_dev = net->priv;
+
+	// No support here yet.
+	// Do we need support???
+	switch(cmd) {
+		case SIOCDEVPRIVATE:
+			return -EOPNOTSUPP;
+		case SIOCDEVPRIVATE+1:
+			return -EOPNOTSUPP;
+		case SIOCDEVPRIVATE+2:
+			//return 0;
+			return -EOPNOTSUPP;
+		default:
+			return -EOPNOTSUPP;
+	}
+}
+
+static void CDC_SetEthernetPacketFilter (ether_dev_t *ether_dev)
+{
+	usb_control_msg(ether_dev->usb,
+			usb_sndctrlpipe(ether_dev->usb, 0),
+			SET_ETHERNET_PACKET_FILTER, /* request */
+			USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
+			cpu_to_le16(ether_dev->mode_flags), /* value */
+			cpu_to_le16((u16)ether_dev->comm_interface), /* index */
+			NULL,
+			0, /* size */
+			HZ); /* timeout */
+}	
+
+
+static void CDCEther_set_multicast( struct net_device *net )
+{
+	ether_dev_t *ether_dev = net->priv;
+	int i;
+	__u8 *buff;
+	
+
+	// Tell the kernel to stop sending us frames while we get this
+	// all set up.
+	netif_stop_queue(net);
+
+      /* Note: do not reorder, GCC is clever about common statements. */
+        if (net->flags & IFF_PROMISC) {
+                /* Unconditionally log net taps. */
+                info( "%s: Promiscuous mode enabled", net->name);
+		ether_dev->mode_flags = MODE_FLAG_PROMISCUOUS |
+			MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+        } else if (net->mc_count > ether_dev->wNumberMCFilters) {
+                /* Too many to filter perfectly -- accept all multicasts. */
+		info("%s: set too many MC filters, using allmulti", net->name);
+		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+	} else if (net->flags & IFF_ALLMULTI) {
+                /* Filter in software */
+		info("%s: using allmulti", net->name);
+		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+        } else {
+		/* do multicast filtering in hardware */
+                struct dev_mc_list *mclist;
+		info("%s: set multicast filters", net->name);
+		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |
+			MODE_FLAG_DIRECTED |
+			MODE_FLAG_BROADCAST |
+			MODE_FLAG_MULTICAST;
+		buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+                for (i = 0, mclist = net->mc_list;
+		     mclist && i < net->mc_count;
+                     i++, mclist = mclist->next) {
+			memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
+		}
+#if 0
+		usb_control_msg(ether_dev->usb,
+				usb_sndctrlpipe(ether_dev->usb, 0),
+				SET_ETHERNET_MULTICAST_FILTER, /* request */
+				USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */
+				cpu_to_le16(net->mc_count), /* value */
+				cpu_to_le16((u16)ether_dev->comm_interface), /* index */
+				buff,
+				(6* net->mc_count), /* size */
+				HZ); /* timeout */
+#endif
+		kfree(buff);
+	}
+
+#if 0 
+	CDC_SetEthernetPacketFilter(ether_dev);
+#endif	
+        // Tell the kernel to start giving frames to us again.
+	netif_wake_queue(net);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines used to parse out the Functional Descriptors /////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int parse_header_functional_descriptor( int *bFunctionLength, 
+                                               int bDescriptorType, 
+                                               int bDescriptorSubtype,
+                                               unsigned char *data,
+                                               ether_dev_t *ether_dev,
+                                               int *requirements )
+{
+	// Check to make sure we haven't seen one of these already.
+	if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
+		err( "Multiple Header Functional Descriptors found." );
+		return -1;
+	}
+	
+	// Is it the right size???
+	if (*bFunctionLength != 5) {
+		info( "Invalid length in Header Functional Descriptor" );
+		// This is a hack to get around a particular device (NO NAMES)
+		// It has this function length set to the length of the
+		// whole class-specific descriptor
+		*bFunctionLength = 5;
+	}
+	
+	// Nothing extremely useful here.
+	// We'll keep it for posterity
+	ether_dev->bcdCDC = data[0] + (data[1] << 8);
+	dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
+
+	// We've seen one of these
+	*requirements &= ~REQ_HDR_FUNC_DESCR;
+	
+	// It's all good.
+	return 0;
+}
+
+static int parse_union_functional_descriptor( int *bFunctionLength, 
+                                              int bDescriptorType, 
+                                              int bDescriptorSubtype,
+                                              unsigned char *data,
+                                              ether_dev_t *ether_dev,
+                                              int *requirements )
+{
+	// Check to make sure we haven't seen one of these already.
+	if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
+		err( "Multiple Union Functional Descriptors found." );
+		return -1;
+	}
+
+	// Is it the right size?
+	if (*bFunctionLength != 5) {
+		// It is NOT the size we expected.
+		err( "Unsupported length in Union Functional Descriptor" );
+		return -1;
+	}
+	
+	// Sanity check of sorts
+	if (ether_dev->comm_interface != data[0]) {
+		// This tells us that we are chasing the wrong comm
+		// interface or we are crazy or something else weird.
+		if (ether_dev->comm_interface == data[1]) {
+			info( "Probably broken Union descriptor, fudging data interface" );
+			// We'll need this in a few microseconds, 
+			// so guess here, and hope for the best
+			ether_dev->data_interface = data[0];
+		} else {
+			err( "Union Functional Descriptor is broken beyond repair" );
+			return -1;
+		}
+	} else{ // Descriptor is OK
+       		// We'll need this in a few microseconds!
+		ether_dev->data_interface = data[1];
+	}
+
+	// We've seen one of these now.
+	*requirements &= ~REQ_UNION_FUNC_DESCR;
+	
+	// Done
+	return 0;
+}
+
+static int parse_ethernet_functional_descriptor( int *bFunctionLength, 
+                                                 int bDescriptorType, 
+                                                 int bDescriptorSubtype,
+                                                 unsigned char *data,
+                                                 ether_dev_t *ether_dev,
+                                                 int *requirements )
+{
+	// Check to make sure we haven't seen one of these already.
+	if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
+		err( "Multiple Ethernet Functional Descriptors found." );
+		return -1;
+	}
+	
+	// Is it the right size?
+	if (*bFunctionLength != 13) {
+		err( "Invalid length in Ethernet Networking Functional Descriptor" );
+		return -1;
+	}
+	
+	// Lots of goodies from this one.  They are all important.
+	ether_dev->iMACAddress = data[0];
+	ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
+	ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
+	ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
+	if (ether_dev->wNumberMCFilters > multicast_filter_limit) {
+		ether_dev->wNumberMCFilters = multicast_filter_limit;
+		}	
+	ether_dev->bNumberPowerFilters = data[9];
+	
+	// We've seen one of these now.
+	*requirements &= ~REQ_ETH_FUNC_DESCR;
+	
+	// That's all she wrote.
+	return 0;
+}
+
+static int parse_protocol_unit_functional_descriptor( int *bFunctionLength, 
+                                                      int bDescriptorType, 
+                                                      int bDescriptorSubtype,
+                                                      unsigned char *data,
+                                                      ether_dev_t *ether_dev,
+                                                      int *requirements )
+{
+	// There should only be one type if we are sane
+	if (bDescriptorType != CS_INTERFACE) {
+		info( "Invalid bDescriptorType found." );
+		return -1;
+	}
+
+	// The Subtype tells the tale.
+	switch (bDescriptorSubtype){
+		case 0x00:	// Header Functional Descriptor
+			return parse_header_functional_descriptor( bFunctionLength,
+			                                           bDescriptorType,
+			                                           bDescriptorSubtype,
+			                                           data,
+			                                           ether_dev,
+			                                           requirements );
+			break;
+		case 0x06:	// Union Functional Descriptor
+			return parse_union_functional_descriptor( bFunctionLength,
+			                                          bDescriptorType,
+			                                          bDescriptorSubtype,
+			                                          data,
+			                                          ether_dev,
+			                                          requirements );
+			break;
+		case 0x0F:	// Ethernet Networking Functional Descriptor
+			return parse_ethernet_functional_descriptor( bFunctionLength,
+			                                             bDescriptorType,
+			                                             bDescriptorSubtype,
+			                                             data,
+			                                             ether_dev,
+			                                             requirements );
+			break;
+		default:	// We don't support this at this time...
+			// However that doesn't necessarily indicate an error.
+			dbg( "Unexpected header type %x:", bDescriptorSubtype );
+			return 0;
+	}
+	// How did we get here???
+	return -1;
+}
+
+static int parse_ethernet_class_information( unsigned char *data, int length, ether_dev_t *ether_dev )
+{
+	int loc = 0;
+	int rc;
+	int bFunctionLength;
+	int bDescriptorType;
+	int bDescriptorSubtype;
+	int requirements = REQUIREMENTS_TOTAL;
+
+	// As long as there is something here, we will try to parse it
+	while (loc < length) {
+		// Length
+		bFunctionLength = data[loc];
+		loc++;
+		
+		// Type
+		bDescriptorType = data[loc];
+		loc++;
+		
+		// Subtype
+		bDescriptorSubtype = data[loc];
+		loc++;
+		
+		// ship this off to be processed elsewhere.
+		rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, 
+		                                                bDescriptorType, 
+		                                                bDescriptorSubtype, 
+		                                                &data[loc],
+		                                                ether_dev,
+		                                                &requirements );
+		// Did it process okay?
+		if (rc)	{
+			// Something was hosed somewhere.
+			// No need to continue;
+			err("Bad descriptor parsing: %x", rc );
+			return -1;
+		}
+		// We have already taken three bytes.
+		loc += (bFunctionLength - 3);
+	}
+	// Check to see if we got everything we need.
+	if (requirements) {
+		// We missed some of the requirements...
+		err( "Not all required functional descriptors present 0x%08X", requirements );
+		return -1;
+	}
+	// We got everything.
+	return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to check for the existence of the Functional Descriptors //////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int find_and_parse_ethernet_class_information( struct usb_device *device, ether_dev_t *ether_dev )
+{
+	struct usb_config_descriptor *conf = NULL;
+	struct usb_interface *comm_intf_group = NULL;
+	struct usb_interface_descriptor *comm_intf = NULL;
+	int rc = -1;
+	// The assumption here is that find_ethernet_comm_interface
+	// and find_valid_configuration 
+	// have already filled in the information about where to find
+	// the a valid commication interface.
+
+	conf = &( device->config[ether_dev->configuration_num] );
+	comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
+	comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
+	// Let's check and see if it has the extra information we need...
+
+	if (comm_intf->extralen > 0) {
+		// This is where the information is SUPPOSED to be.
+		rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
+	} else if (conf->extralen > 0) {
+		// This is a hack.  The spec says it should be at the interface 
+		// location checked above.  However I have seen it here also.
+		// This is the same device that requires the functional descriptor hack above
+		warn( "Ethernet information found at device configuration.  This is broken." );
+		rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
+	} else 	{
+		// I don't know where else to look.
+		warn( "No ethernet information found." );
+		rc = -1;
+	}
+	return rc;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines to verify the data interface /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int get_data_interface_endpoints( struct usb_device *device, ether_dev_t *ether_dev )
+{
+	struct usb_config_descriptor *conf = NULL;
+	struct usb_interface *data_intf_group = NULL;
+	struct usb_interface_descriptor *data_intf = NULL;
+	
+	// Walk through and get to the data interface we are checking.
+	conf = &( device->config[ether_dev->configuration_num] );
+	data_intf_group = &( conf->interface[ether_dev->data_interface] );
+	data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
+
+	// Start out assuming we won't find anything we can use
+	ether_dev->data_ep_in = 0;
+	ether_dev->data_ep_out = 0;
+	
+	// If these are not BULK endpoints, we don't want them
+	if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
+		return -1;
+	} if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
+		return -1;
+	}
+
+	// Check the first endpoint to see if it is IN or OUT
+	if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
+		// This endpoint is IN
+		ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
+	} else {
+		// This endpoint is OUT
+		ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;
+		ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
+	}
+
+	// Check the second endpoint to see if it is IN or OUT
+	if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
+		// This endpoint is IN
+		ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
+	} else	{
+		// This endpoint is OUT
+		ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;
+		ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
+	}
+	
+	// Now make sure we got both an IN and an OUT
+	if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
+		// We did get both, we are in good shape...
+		info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
+		return 0;
+	}
+	return -1;
+}
+
+static int verify_ethernet_data_interface( struct usb_device *device, ether_dev_t *ether_dev )
+{
+	struct usb_config_descriptor *conf = NULL;
+	struct usb_interface *data_intf_group = NULL;
+	struct usb_interface_descriptor *data_intf = NULL;
+	int rc = -1;
+	int status;
+	int altset_num;
+
+	// The assumption here is that parse_ethernet_class_information()
+	// and find_valid_configuration() 
+	// have already filled in the information about where to find
+	// a data interface
+	conf = &( device->config[ether_dev->configuration_num] );
+	data_intf_group = &( conf->interface[ether_dev->data_interface] );
+
+	// start out assuming we won't find what we are looking for.
+	ether_dev->data_interface_altset_num_with_traffic = -1;
+	ether_dev->data_bAlternateSetting_with_traffic = -1;
+	ether_dev->data_interface_altset_num_without_traffic = -1;
+	ether_dev->data_bAlternateSetting_without_traffic = -1;
+
+	// Walk through every possible setting for this interface until
+	// we find what makes us happy.
+	for ( altset_num = 0; altset_num < data_intf_group->num_altsetting; altset_num++ ) {
+		data_intf = &( data_intf_group->altsetting[altset_num] );
+
+		// Is this a data interface we like?
+		if ( ( data_intf->bInterfaceClass == 0x0A )
+		   && ( data_intf->bInterfaceSubClass == 0x00 )
+		   && ( data_intf->bInterfaceProtocol == 0x00 ) ) {
+			if ( data_intf->bNumEndpoints == 2 ) {
+				// We are required to have one of these.
+				// An interface with 2 endpoints to send Ethernet traffic back and forth
+				// It actually may be possible that the device might only
+				// communicate in a vendor specific manner.
+				// That would not be very nice.
+				// We can add that one later.
+				ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
+				ether_dev->data_interface_altset_num_with_traffic = altset_num;
+				ether_dev->data_bAlternateSetting_with_traffic = data_intf->bAlternateSetting;
+				status = get_data_interface_endpoints( device, ether_dev );
+				if (!status) {
+					rc = 0;
+				}
+			}
+			if ( data_intf->bNumEndpoints == 0 ) {
+				// According to the spec we are SUPPOSED to have one of these
+				// In fact the device is supposed to come up in this state.
+				// However, I have seen a device that did not have such an interface.
+				// So it must be just optional for our driver...
+				ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
+				ether_dev->data_interface_altset_num_without_traffic = altset_num;
+				ether_dev->data_bAlternateSetting_without_traffic = data_intf->bAlternateSetting;
+			}
+		}
+	}
+	return rc;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to find a communication interface /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int find_ethernet_comm_interface( struct usb_device *device, ether_dev_t *ether_dev )
+{
+	struct usb_config_descriptor *conf = NULL;
+	struct usb_interface *comm_intf_group = NULL;
+	struct usb_interface_descriptor *comm_intf = NULL;
+	int intf_num;
+	int altset_num;
+	int rc;
+
+	conf = &( device->config[ether_dev->configuration_num] );
+
+	// We need to check and see if any of these interfaces are something we want.
+	// Walk through each interface one at a time
+	for ( intf_num = 0; intf_num < conf->bNumInterfaces; intf_num++ ) {
+		comm_intf_group = &( conf->interface[intf_num] );
+		// Now for each of those interfaces, check every possible
+		// alternate setting.
+		for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
+			comm_intf = &( comm_intf_group->altsetting[altset_num] );
+
+			// Is this a communication class of interface of the
+			// ethernet subclass variety.
+			if ( ( comm_intf->bInterfaceClass == 0x02 )
+			   && ( comm_intf->bInterfaceSubClass == 0x06 )
+			   && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
+				if ( comm_intf->bNumEndpoints == 1 ) {
+					// Good, we found one, we will try this one
+					// Fill in the structure...
+					ether_dev->comm_interface = intf_num;
+					ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
+					ether_dev->comm_interface_altset_num = altset_num;
+					ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
+
+					// Look for the Ethernet Functional Descriptors
+					rc = find_and_parse_ethernet_class_information( device, ether_dev );
+					if (rc) {
+						// Nope this was no good after all.
+						continue;
+					}
+
+					// Check that we really can talk to the data
+					// interface 
+					// This includes # of endpoints, protocols,
+					// etc.
+					rc = verify_ethernet_data_interface( device, ether_dev );
+					if (rc)	{
+						// We got something we didn't like
+						continue;
+					}
+					// This communication interface seems to give us everything
+					// we require.  We have all the ethernet info we need.
+					// Let's get out of here and go home right now.
+					return 0;
+				} else {
+                                        // bNumEndPoints != 1
+					// We found an interface that had the wrong number of 
+					// endpoints but would have otherwise been okay
+				} // end bNumEndpoints check.
+			} // end interface specifics check.
+		} // end for altset_num
+	} // end for intf_num
+	return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to go through all configurations and find one that ////////////////
+// is an Ethernet Networking Device //////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int find_valid_configuration( struct usb_device *device, ether_dev_t *ether_dev )
+{
+	struct usb_config_descriptor *conf = NULL;
+	int conf_num;
+	int rc;
+
+	// We will try each and every possible configuration
+	for ( conf_num = 0; conf_num < device->descriptor.bNumConfigurations; conf_num++ ) {
+		conf = &( device->config[conf_num] );
+
+		// Our first requirement : 2 interfaces
+		if ( conf->bNumInterfaces != 2 ) {
+			// I currently don't know how to handle devices with any number of interfaces
+			// other than 2.
+			continue;
+		}
+
+		// This one passed our first check, fill in some 
+		// useful data
+		ether_dev->configuration_num = conf_num;
+		ether_dev->bConfigurationValue = conf->bConfigurationValue;
+
+		// Now run it through the ringers and see what comes
+		// out the other side.
+		rc = find_ethernet_comm_interface( device, ether_dev );
+
+		// Check if we found an ethernet Communcation Device
+		if ( !rc ) {
+			// We found one.
+			return 0;
+		}
+	}
+	// None of the configurations suited us.
+	return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine that checks a given configuration to see if any driver ////////////
+// has claimed any of the devices interfaces /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int check_for_claimed_interfaces( struct usb_config_descriptor *config )
+{
+	struct usb_interface *comm_intf_group;
+	int intf_num;
+
+	// Go through all the interfaces and make sure none are 
+	// claimed by anybody else.
+	for ( intf_num = 0; intf_num < config->bNumInterfaces; intf_num++ ) {
+		comm_intf_group = &( config->interface[intf_num] );
+		if ( usb_interface_claimed( comm_intf_group ) )	{
+			// Somebody has beat us to this guy.
+			// We can't change the configuration out from underneath of whoever
+			// is using this device, so we will go ahead and give up.
+			return -1;
+		}
+	}
+	// We made it all the way through.
+	// I guess no one has claimed any of these interfaces.
+	return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines to ask for and set the kernel network interface's MAC address ////
+// Used by driver's probe routine ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static inline unsigned char hex2dec( unsigned char digit )
+{
+	// Is there a standard way to do this???
+	// I have written this code TOO MANY times.
+	if ( (digit >= '0') && (digit <= '9') )	{
+		return (digit - '0');
+	}
+	if ( (digit >= 'a') && (digit <= 'f') )	{
+		return (digit - 'a' + 10);
+	}
+	if ( (digit >= 'A') && (digit <= 'F') )	{
+		return (digit - 'A' + 10);
+	}
+	return 0;
+}
+
+static void set_ethernet_addr( ether_dev_t *ether_dev )
+{
+	unsigned char	mac_addr[6];
+	int		i;
+	int 		len;
+	unsigned char	buffer[13];
+
+	// Let's assume we don't get anything...
+	mac_addr[0] = 0x00;
+	mac_addr[1] = 0x00;
+	mac_addr[2] = 0x00;
+	mac_addr[3] = 0x00;
+	mac_addr[4] = 0x00;
+	mac_addr[5] = 0x00;
+
+	// Let's ask the device...
+	len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
+
+	// Sanity check!
+	if (len != 12)	{
+		// You gotta love failing sanity checks
+		err("Attempting to get MAC address returned %d bytes", len);
+		return;
+	}
+
+	// Fill in the mac_addr
+	for (i = 0; i < 6; i++)	{
+		mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
+	}
+
+	// Now copy it over to the kernel's network driver.
+	memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to print to syslog information about the driver ///////////////////
+// Used by driver's probe routine ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+void log_device_info(ether_dev_t *ether_dev)
+{
+	int len;
+	int string_num;
+	unsigned char manu[256];
+	unsigned char prod[256];
+	unsigned char sern[256];
+	unsigned char *mac_addr;
+
+	// Default empty strings in case we don't find a real one
+	manu[0] = 0x00;
+	prod[0] = 0x00;
+	sern[0] = 0x00;
+
+	// Try to get the device Manufacturer
+	string_num = ether_dev->usb->descriptor.iManufacturer;
+	if (string_num)	{
+		// Put it into its buffer
+		len = usb_string(ether_dev->usb, string_num, manu, 255);
+		// Just to be safe
+		manu[len] = 0x00;
+	}
+
+	// Try to get the device Product Name
+	string_num = ether_dev->usb->descriptor.iProduct;
+	if (string_num)	{
+		// Put it into its buffer
+		len = usb_string(ether_dev->usb, string_num, prod, 255);
+		// Just to be safe
+		prod[len] = 0x00;
+	}
+
+	// Try to get the device Serial Number
+	string_num = ether_dev->usb->descriptor.iSerialNumber;
+	if (string_num)	{
+		// Put it into its buffer
+		len = usb_string(ether_dev->usb, string_num, sern, 255);
+		// Just to be safe
+		sern[len] = 0x00;
+	}
+
+	// This makes it easier for us to print
+	mac_addr = ether_dev->net->dev_addr;
+
+	// Now send everything we found to the syslog
+	info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X", 
+	      ether_dev->net->name, manu, prod, sern, mac_addr[0], 
+	      mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], 
+	      mac_addr[5] );
+}
+
+/* Forward declaration */
+static struct usb_driver CDCEther_driver ;
+
+//////////////////////////////////////////////////////////////////////////////
+// Module's probe routine ////////////////////////////////////////////////////
+// claims interfaces if they are for an Ethernet CDC /////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
+			     const struct usb_device_id *id)
+{
+	struct net_device	*net;
+	ether_dev_t		*ether_dev;
+	int 			rc;
+
+	// First we should check the active configuration to see if 
+	// any other driver has claimed any of the interfaces.
+	if ( check_for_claimed_interfaces( usb->actconfig ) ) {
+		// Someone has already put there grubby paws on this device.
+		// We don't want it now...
+		return NULL;
+	}
+
+	// We might be finding a device we can use.
+	// We all go ahead and allocate our storage space.
+	// We need to because we have to start filling in the data that
+	// we are going to need later.
+	if(!(ether_dev = kmalloc(sizeof(ether_dev_t), GFP_KERNEL))) {
+		err("out of memory allocating device structure");
+		return NULL;
+	}
+
+	// Zero everything out.
+	memset(ether_dev, 0, sizeof(ether_dev_t));
+
+	ether_dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ether_dev->rx_urb) {
+		kfree(ether_dev);
+		return NULL;
+	}
+	ether_dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ether_dev->tx_urb) {
+		usb_free_urb(ether_dev->rx_urb);
+		kfree(ether_dev);
+		return NULL;
+	}
+	ether_dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ether_dev->intr_urb) {
+		usb_free_urb(ether_dev->tx_urb);
+		usb_free_urb(ether_dev->rx_urb);
+		kfree(ether_dev);
+		return NULL;
+	}
+
+	// Let's see if we can find a configuration we can use.
+	rc = find_valid_configuration( usb, ether_dev );
+	if (rc)	{
+		// Nope we couldn't find one we liked.
+		// This device was not meant for us to control.
+		kfree( ether_dev );
+		return	NULL;
+	}
+
+	// Now that we FOUND a configuration. let's try to make the 
+	// device go into it.
+	if ( usb_set_configuration( usb, ether_dev->bConfigurationValue ) ) {
+		err("usb_set_configuration() failed");
+		kfree( ether_dev );
+		return NULL;
+	}
+
+	// Now set the communication interface up as required.
+	if (usb_set_interface(usb, ether_dev->comm_bInterfaceNumber, ether_dev->comm_bAlternateSetting)) {
+		err("usb_set_interface() failed");
+		kfree( ether_dev );
+		return NULL;
+	}
+
+	// Only turn traffic on right now if we must...
+	if (ether_dev->data_interface_altset_num_without_traffic >= 0)	{
+		// We found an alternate setting for the data
+		// interface that allows us to turn off traffic.
+		// We should use it.
+		if (usb_set_interface( usb, 
+		                       ether_dev->data_bInterfaceNumber, 
+		                       ether_dev->data_bAlternateSetting_without_traffic)) {
+			err("usb_set_interface() failed");
+			kfree( ether_dev );
+			return NULL;
+		}
+	} else	{
+		// We didn't find an alternate setting for the data
+		// interface that would let us turn off traffic.
+		// Oh well, let's go ahead and do what we must...
+		if (usb_set_interface( usb, 
+		                       ether_dev->data_bInterfaceNumber, 
+		                       ether_dev->data_bAlternateSetting_with_traffic)) {
+			err("usb_set_interface() failed");
+			kfree( ether_dev );
+			return NULL;
+		}
+	}
+
+	// Now we need to get a kernel Ethernet interface.
+	net = init_etherdev( NULL, 0 );
+	if ( !net ) {
+		// Hmm...  The kernel is not sharing today...
+		// Fine, we didn't want it anyway...
+		err( "Unable to initialize ethernet device" );
+		kfree( ether_dev );
+		return	NULL;
+	}
+
+	// Now that we have an ethernet device, let's set it up
+	// (And I don't mean "set [it] up the bomb".)
+	net->priv = ether_dev;
+	SET_MODULE_OWNER(net);
+	net->open = CDCEther_open;
+	net->stop = CDCEther_close;
+	net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;
+	net->tx_timeout = CDCEther_tx_timeout;   // TX timeout function
+	net->do_ioctl = CDCEther_ioctl;
+	net->hard_start_xmit = CDCEther_start_xmit;
+	net->set_multicast_list = CDCEther_set_multicast;
+	net->get_stats = CDCEther_netdev_stats;
+	net->mtu = ether_dev->wMaxSegmentSize - 14;
+
+	// We'll keep track of this information for later...
+	ether_dev->usb = usb;
+	ether_dev->net = net;
+	
+	// and don't forget the MAC address.
+	set_ethernet_addr( ether_dev );
+
+	// Send a message to syslog about what we are handling
+	log_device_info( ether_dev );
+
+	// I claim this interface to be a CDC Ethernet Networking device
+	usb_driver_claim_interface( &CDCEther_driver, 
+	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), 
+	                            ether_dev );
+	// I claim this interface to be a CDC Ethernet Networking device
+	usb_driver_claim_interface( &CDCEther_driver, 
+	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), 
+	                            ether_dev );
+
+	// Does this REALLY do anything???
+	usb_inc_dev_use( usb );
+
+	// TODO - last minute HACK
+	ether_dev->comm_ep_in = 5;
+
+	// Okay, we are finally done...
+	return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Module's disconnect routine ///////////////////////////////////////////////
+// Called when the driver is unloaded or the device is unplugged /////////////
+// (Whichever happens first assuming the driver suceeded at its probe) ///////
+//////////////////////////////////////////////////////////////////////////////
+
+static void CDCEther_disconnect( struct usb_device *usb, void *ptr )
+{
+	ether_dev_t *ether_dev = ptr;
+
+	// Sanity check!!!
+	if ( !ether_dev || !ether_dev->usb ) {
+		// We failed.  We are insane!!!
+		warn("unregistering non-existant device");
+		return;
+	}
+
+	// Make sure we fail the sanity check if we try this again.
+	ether_dev->usb = NULL;
+	
+	// It is possible that this function is called before
+	// the "close" function.
+	// This tells the close function we are already disconnected
+	ether_dev->flags |= CDC_ETHER_UNPLUG;
+	
+	// We don't need the network device any more
+	unregister_netdev( ether_dev->net );
+	
+	// For sanity checks
+	ether_dev->net = NULL;
+
+	// I ask again, does this do anything???
+	usb_dec_dev_use( usb );
+
+	// We are done with this interface
+	usb_driver_release_interface( &CDCEther_driver, 
+	                              &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]) );
+
+	// We are done with this interface too
+	usb_driver_release_interface( &CDCEther_driver, 
+	                              &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]) );
+
+	// No more tied up kernel memory
+	usb_free_urb(ether_dev->intr_urb);
+	usb_free_urb(ether_dev->rx_urb);
+	usb_free_urb(ether_dev->rx_urb);
+	kfree( ether_dev );
+	
+	// This does no good, but it looks nice!
+	ether_dev = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Driver info ///////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static struct usb_driver CDCEther_driver = {
+	name:		"CDCEther",
+	probe:		CDCEther_probe,
+	disconnect:	CDCEther_disconnect,
+	id_table:	CDCEther_ids,
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// init and exit routines called when driver is installed and uninstalled ////
+//////////////////////////////////////////////////////////////////////////////
+
+int __init CDCEther_init(void)
+{
+	info( "%s", version );
+	return usb_register( &CDCEther_driver );
+}
+
+void __exit CDCEther_exit(void)
+{
+	usb_deregister( &CDCEther_driver );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Module info ///////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+module_init( CDCEther_init );
+module_exit( CDCEther_exit );
+
+MODULE_AUTHOR("Brad Hards and another");
+MODULE_DESCRIPTION("USB CDC Ethernet driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM (multicast_filter_limit, "i");
+MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");
+
+MODULE_DEVICE_TABLE (usb, CDCEther_ids);
+
+//////////////////////////////////////////////////////////////////////////////
+// End of file ///////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
diff -Nru a/drivers/usb/net/cdc-ether.h b/drivers/usb/net/cdc-ether.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/cdc-ether.h	Sun Apr 14 12:16:56 2002
@@ -0,0 +1,98 @@
+// Portions of this file taken from 
+// Petko Manolov - Petkan (petkan@dce.bg)
+// from his driver pegasus.h
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#define CS_INTERFACE			0x24
+
+#define	CDC_ETHER_MAX_MTU		1536
+
+#define	CDC_ETHER_PRESENT		0x00000001
+#define	CDC_ETHER_RUNNING		0x00000002
+#define	CDC_ETHER_TX_BUSY		0x00000004
+#define	CDC_ETHER_RX_BUSY		0x00000008
+#define	CDC_ETHER_UNPLUG		0x00000040
+
+#define	CDC_ETHER_TX_TIMEOUT	(HZ*10)
+
+#define	TX_UNDERRUN				0x80
+#define	EXCESSIVE_COL			0x40
+#define	LATE_COL				0x20
+#define	NO_CARRIER				0x10
+#define	LOSS_CARRIER			0x08
+#define	JABBER_TIMEOUT			0x04
+
+#define	CDC_ETHER_REQT_READ		0xc0
+#define	CDC_ETHER_REQT_WRITE	0x40
+#define	CDC_ETHER_REQ_GET_REGS	0xf0
+#define	CDC_ETHER_REQ_SET_REGS	0xf1
+#define	CDC_ETHER_REQ_SET_REG	PIPERIDER_REQ_SET_REGS
+#define	ALIGN(x)		x __attribute__((aligned(L1_CACHE_BYTES)))
+
+#define MODE_FLAG_PROMISCUOUS   (1<<0)
+#define MODE_FLAG_ALL_MULTICAST (1<<1)
+#define MODE_FLAG_DIRECTED      (1<<2)
+#define MODE_FLAG_BROADCAST     (1<<3)
+#define MODE_FLAG_MULTICAST     (1<<4)
+
+#define SET_ETHERNET_MULTICAST_FILTER    0x40
+#define SET_ETHERNET_PACKET_FILTER       0x43
+
+typedef struct _ether_dev_t {
+	struct usb_device	*usb;
+	struct net_device	*net;
+	struct net_device_stats	stats;
+	unsigned		flags;
+	int			configuration_num;
+	int			bConfigurationValue;
+	int			comm_interface;
+	int			comm_bInterfaceNumber;
+	int			comm_interface_altset_num;
+	int			comm_bAlternateSetting;
+	int			comm_ep_in;
+	int			data_interface;
+	int			data_bInterfaceNumber;
+	int			data_interface_altset_num_with_traffic;
+	int			data_bAlternateSetting_with_traffic;
+	int			data_interface_altset_num_without_traffic;
+	int			data_bAlternateSetting_without_traffic;
+	int			data_ep_in;
+	int			data_ep_out;
+	int			data_ep_out_size;
+	__u16			bcdCDC;
+	__u8			iMACAddress;
+	__u32			bmEthernetStatistics;
+	__u16			wMaxSegmentSize;
+	__u16                   mode_flags;
+	__u16			wNumberMCFilters;
+	__u8			bNumberPowerFilters;
+	int			intr_interval;
+	struct urb		*rx_urb, *tx_urb, *intr_urb;
+	unsigned char		ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
+	unsigned char		ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
+	unsigned char		ALIGN(intr_buff[8]);
+} ether_dev_t;
+
+#define REQ_HDR_FUNC_DESCR	0x0001
+#define REQ_UNION_FUNC_DESCR	0x0002
+#define REQ_ETH_FUNC_DESCR	0x0004
+#define REQUIREMENTS_TOTAL	0x0007
+
+
+
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/kaweth.c	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,1067 @@
+/****************************************************************
+ *
+ *     kaweth.c - driver for KL5KUSB101 based USB->Ethernet
+ *
+ *     (c) 2000 Interlan Communications
+ *     (c) 2000 Stephane Alnet
+ *     (C) 2001 Brad Hards
+ *
+ *     Original author: The Zapman <zapman@interlan.net>
+ *     Inspired by, and much credit goes to Michael Rothwell 
+ *     <rothwell@interlan.net> for the test equipment, help, and patience
+ *     Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
+ *     Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki 
+ *     for providing the firmware and driver resources.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2, or 
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software Foundation,
+ *     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+ *
+ ****************************************************************/
+
+/* TODO:
+ * Fix in_interrupt() problem
+ * Develop test procedures for USB net interfaces
+ * Run test procedures
+ * Fix bugs from previous two steps
+ * Snoop other OSs for any tricks we're not doing
+ * SMP locking
+ * Reduce arbitrary timeouts 
+ * Smart multicast support 
+ * Temporary MAC change support
+ * Tunable SOFs parameter - ioctl()?
+ * Ethernet stats collection
+ * Code formatting improvements
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/usb.h>
+#include <linux/types.h>
+#include <asm/semaphore.h>
+#include <asm/byteorder.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
+#else
+#define kaweth_dbg(format, arg...) do {} while (0)
+#endif
+#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg)
+#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg)
+#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg)
+
+
+#include "kawethfw.h"
+
+#define KAWETH_MTU			1514
+#define KAWETH_BUF_SIZE			1664
+#define KAWETH_TX_TIMEOUT		(5 * HZ)
+#define KAWETH_FIRMWARE_BUF_SIZE	4096
+#define KAWETH_CONTROL_TIMEOUT		(30 * HZ)
+
+#define KAWETH_STATUS_BROKEN		0x0000001
+#define KAWETH_STATUS_CLOSING		0x0000002
+
+#define KAWETH_PACKET_FILTER_PROMISCUOUS	0x01
+#define KAWETH_PACKET_FILTER_ALL_MULTICAST	0x02
+#define KAWETH_PACKET_FILTER_DIRECTED		0x04
+#define KAWETH_PACKET_FILTER_BROADCAST		0x08
+#define KAWETH_PACKET_FILTER_MULTICAST		0x10
+
+/* Table 7 */
+#define KAWETH_COMMAND_GET_ETHERNET_DESC	0x00
+#define KAWETH_COMMAND_MULTICAST_FILTERS        0x01
+#define KAWETH_COMMAND_SET_PACKET_FILTER	0x02
+#define KAWETH_COMMAND_STATISTICS               0x03
+#define KAWETH_COMMAND_SET_TEMP_MAC     	0x06
+#define KAWETH_COMMAND_GET_TEMP_MAC             0x07
+#define KAWETH_COMMAND_SET_URB_SIZE		0x08
+#define KAWETH_COMMAND_SET_SOFS_WAIT		0x09
+#define KAWETH_COMMAND_SCAN			0xFF
+
+#define KAWETH_SOFS_TO_WAIT			0x05
+
+
+MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr> and Brad Hards <bhards@bigpond.net.au>");
+MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static void *kaweth_probe(
+            struct usb_device *dev,             /* the device */
+            unsigned ifnum,                     /* what interface */
+            const struct usb_device_id *id      /* from id_table */
+	);
+static void kaweth_disconnect(struct usb_device *dev, void *ptr);
+int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
+				struct usb_ctrlrequest *cmd, void *data,
+				int len, int timeout);
+
+/****************************************************************
+ *     usb_device_id
+ ****************************************************************/
+static struct usb_device_id usb_klsi_table[] = {
+	{ USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */ 
+	{ USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
+	{ USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */ 
+	{ USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */ 
+	{ USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */ 
+	{ USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
+	{ USB_DEVICE(0x0565, 0x0003) }, /* Optus@Home UEP1045A */
+	{ USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */ 
+	{ USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
+	{ USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
+	{ USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */ 
+	{ USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */ 
+	{ USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */ 
+	{ USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */ 
+	{ USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */ 
+	{ USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
+	{ USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
+	{ USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
+	{ USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */
+	{ USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */
+	{ USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */
+	{ USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */
+	{ USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */
+	{ USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
+	{ USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
+	{ USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
+	{ USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ 
+	{ USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ 
+	{ USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ 
+	{ USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
+	{} /* Null terminator */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_klsi_table);
+
+/****************************************************************
+ *     kaweth_driver
+ ****************************************************************/
+static struct usb_driver kaweth_driver = {
+	owner:		THIS_MODULE,
+	name:		"kaweth",
+	probe:		kaweth_probe,
+	disconnect:	kaweth_disconnect,
+	id_table:       usb_klsi_table,
+};
+
+typedef __u8 eth_addr_t[6];
+
+/****************************************************************
+ *     usb_eth_dev
+ ****************************************************************/
+struct usb_eth_dev {
+	char *name;
+	__u16 vendor;
+	__u16 device;
+	void *pdata;
+};
+
+/****************************************************************
+ *     kaweth_ethernet_configuration
+ *     Refer Table 8
+ ****************************************************************/
+struct kaweth_ethernet_configuration
+{
+	__u8 size;
+	__u8 reserved1;
+	__u8 reserved2;
+	eth_addr_t hw_addr;
+	__u32 statistics_mask;
+	__u16 segment_size;
+	__u16 max_multicast_filters;
+	__u8 reserved3;
+} __attribute__ ((packed));
+
+/****************************************************************
+ *     kaweth_device
+ ****************************************************************/
+struct kaweth_device
+{
+	spinlock_t device_lock;
+
+	__u32 status;
+
+	struct usb_device *dev;
+	struct net_device *net;
+	wait_queue_head_t control_wait;
+
+	struct urb *rx_urb;
+	struct urb *tx_urb;
+	
+	__u8 firmware_buf[KAWETH_FIRMWARE_BUF_SIZE];
+	__u8 tx_buf[KAWETH_BUF_SIZE];
+	__u8 rx_buf[KAWETH_BUF_SIZE];
+	__u16 packet_filter_bitmap;
+
+	struct kaweth_ethernet_configuration configuration;
+
+	struct net_device_stats stats;
+} __attribute__ ((packed));
+
+
+/****************************************************************
+ *     kaweth_control
+ ****************************************************************/
+static int kaweth_control(struct kaweth_device *kaweth,
+			  unsigned int pipe, 
+			  __u8 request, 
+			  __u8 requesttype, 
+			  __u16 value, 
+			  __u16 index,
+			  void *data, 
+			  __u16 size, 
+			  int timeout)
+{
+	struct usb_ctrlrequest *dr;
+
+	kaweth_dbg("kaweth_control()");
+
+	if(in_interrupt()) {
+		kaweth_dbg("in_interrupt()");
+		return -EBUSY;
+	}
+
+	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+
+	if (!dr) {
+		kaweth_dbg("kmalloc() failed");
+		return -ENOMEM;
+	}
+	
+	dr->bRequestType= requesttype;
+	dr->bRequest = request;
+	dr->wValue = cpu_to_le16p(&value);
+	dr->wIndex = cpu_to_le16p(&index);
+	dr->wLength = cpu_to_le16p(&size);
+
+	return kaweth_internal_control_msg(kaweth->dev,
+					pipe,
+					dr,
+					data,
+					size,
+					timeout);
+}
+
+/****************************************************************
+ *     kaweth_read_configuration
+ ****************************************************************/
+static int kaweth_read_configuration(struct kaweth_device *kaweth)
+{
+	int retval;
+
+	kaweth_dbg("Reading kaweth configuration");
+
+	retval = kaweth_control(kaweth,
+				usb_rcvctrlpipe(kaweth->dev, 0),
+				KAWETH_COMMAND_GET_ETHERNET_DESC,
+				USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+				0,
+				0,
+				(void *)&kaweth->configuration,
+				sizeof(kaweth->configuration),
+				KAWETH_CONTROL_TIMEOUT);
+
+	return retval;
+}
+
+/****************************************************************
+ *     kaweth_set_urb_size
+ ****************************************************************/
+static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
+{
+	int retval;
+
+	kaweth_dbg("Setting URB size to %d", (unsigned)urb_size);
+
+	retval = kaweth_control(kaweth,
+				usb_sndctrlpipe(kaweth->dev, 0),
+				KAWETH_COMMAND_SET_URB_SIZE,
+				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+				urb_size,
+				0,
+				(void *)&kaweth->firmware_buf,
+				0,
+				KAWETH_CONTROL_TIMEOUT);
+
+	return retval;
+}
+
+/****************************************************************
+ *     kaweth_set_sofs_wait
+ ****************************************************************/
+static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
+{
+	int retval;
+
+	kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
+
+	retval = kaweth_control(kaweth,
+				usb_sndctrlpipe(kaweth->dev, 0),
+				KAWETH_COMMAND_SET_SOFS_WAIT,
+				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+				sofs_wait,
+				0,
+				(void *)&kaweth->firmware_buf,
+				0,
+				KAWETH_CONTROL_TIMEOUT);
+
+	return retval;
+}
+
+/****************************************************************
+ *     kaweth_set_receive_filter
+ ****************************************************************/
+static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
+				     __u16 receive_filter)
+{
+	int retval;
+
+	kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter);
+
+	retval = kaweth_control(kaweth,
+				usb_sndctrlpipe(kaweth->dev, 0),
+				KAWETH_COMMAND_SET_PACKET_FILTER,
+				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+				receive_filter,
+				0,
+				(void *)&kaweth->firmware_buf,
+				0,
+				KAWETH_CONTROL_TIMEOUT);
+
+	return retval;
+}
+
+/****************************************************************
+ *     kaweth_download_firmware
+ ****************************************************************/
+static int kaweth_download_firmware(struct kaweth_device *kaweth, 
+				    __u8 *data, 
+				    __u16 data_len,
+				    __u8 interrupt,
+				    __u8 type)
+{	
+	if(data_len > KAWETH_FIRMWARE_BUF_SIZE)	{
+		kaweth_err("Firmware too big: %d", data_len);
+		return -ENOSPC;
+	}
+	
+	memcpy(kaweth->firmware_buf, data, data_len);
+	
+	kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
+	kaweth->firmware_buf[3] = data_len >> 8;
+	kaweth->firmware_buf[4] = type;
+	kaweth->firmware_buf[5] = interrupt;
+
+	kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
+		   kaweth->firmware_buf[2]);
+
+	kaweth_dbg("Downloading firmware at %p to kaweth device at %p", 
+	    data, 
+	    kaweth);
+	kaweth_dbg("Firmware length: %d", data_len);
+
+	return kaweth_control(kaweth,
+		              usb_sndctrlpipe(kaweth->dev, 0),
+			      KAWETH_COMMAND_SCAN,
+			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			      0,
+			      0,
+			      (void *)&kaweth->firmware_buf,
+			      data_len,
+			      KAWETH_CONTROL_TIMEOUT);
+}
+
+/****************************************************************
+ *     kaweth_trigger_firmware
+ ****************************************************************/
+static int kaweth_trigger_firmware(struct kaweth_device *kaweth,
+				   __u8 interrupt)
+{
+	kaweth->firmware_buf[0] = 0xB6;
+	kaweth->firmware_buf[1] = 0xC3;
+	kaweth->firmware_buf[2] = 0x01;
+	kaweth->firmware_buf[3] = 0x00;
+	kaweth->firmware_buf[4] = 0x06;
+	kaweth->firmware_buf[5] = interrupt;
+	kaweth->firmware_buf[6] = 0x00;
+	kaweth->firmware_buf[7] = 0x00;
+	
+	kaweth_dbg("Triggering firmware");
+
+	return kaweth_control(kaweth,
+			      usb_sndctrlpipe(kaweth->dev, 0),
+			      KAWETH_COMMAND_SCAN,
+			      USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+			      0,
+			      0,
+			      (void *)&kaweth->firmware_buf,
+			      8,
+			      KAWETH_CONTROL_TIMEOUT);
+}
+
+/****************************************************************
+ *     kaweth_reset
+ ****************************************************************/
+static int kaweth_reset(struct kaweth_device *kaweth)
+{
+	int result;
+
+	kaweth_dbg("kaweth_reset(%p)", kaweth);
+	result = kaweth_control(kaweth,
+				usb_sndctrlpipe(kaweth->dev, 0),
+				USB_REQ_SET_CONFIGURATION, 
+				0, 
+				kaweth->dev->config[0].bConfigurationValue,
+				0, 
+				NULL, 
+				0, 
+				KAWETH_CONTROL_TIMEOUT);
+
+	udelay(10000);
+
+	kaweth_dbg("kaweth_reset() returns %d.",result);
+
+	return result;
+}
+
+static void kaweth_usb_receive(struct urb *);
+
+/****************************************************************
+ *     kaweth_resubmit_rx_urb
+ ****************************************************************/
+static inline void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
+						int mem_flags)
+{
+	int result;
+
+	memset(kaweth->rx_urb, 0, sizeof(*kaweth->rx_urb));
+
+	FILL_BULK_URB(kaweth->rx_urb,
+		      kaweth->dev,
+		      usb_rcvbulkpipe(kaweth->dev, 1),
+		      kaweth->rx_buf,
+		      KAWETH_BUF_SIZE,
+		      kaweth_usb_receive,
+		      kaweth);
+
+	if((result = usb_submit_urb(kaweth->rx_urb, mem_flags))) {
+		kaweth_err("resubmitting rx_urb %d failed", result);
+	}
+}
+
+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
+
+/****************************************************************
+ *     kaweth_usb_receive
+ ****************************************************************/
+static void kaweth_usb_receive(struct urb *urb)
+{
+	struct kaweth_device *kaweth = urb->context;
+	struct net_device *net = kaweth->net;
+	
+	int count = urb->actual_length;
+	int count2 = urb->transfer_buffer_length;
+			
+	__u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
+
+	struct sk_buff *skb;
+
+	if(kaweth->status & KAWETH_STATUS_CLOSING) {
+		return;
+	}
+	
+	if(urb->status && urb->status != -EREMOTEIO && count != 1) { 
+		kaweth_err("%s RX status: %d count: %d packet_len: %d",
+                           net->name, 
+			   urb->status,
+			   count, 
+			   (int)pkt_len);
+		kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
+                return;
+	}
+
+	if(kaweth->net && (count > 2)) {
+		if(pkt_len > (count - 2)) {
+			kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
+			kaweth_err("Packet len & 2047: %x", pkt_len & 2047);
+			kaweth_err("Count 2: %x", count2);
+		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
+                        return;
+                }
+		
+		if(!(skb = dev_alloc_skb(pkt_len+2))) {
+		        kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
+                        return;
+		}
+
+		skb->dev = net;
+
+		eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
+		
+		skb_put(skb, pkt_len);
+
+		skb->protocol = eth_type_trans(skb, net);
+		
+		netif_rx(skb);
+		
+		kaweth->stats.rx_packets++;
+		kaweth->stats.rx_bytes += pkt_len;
+	}
+
+	kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
+}
+
+/****************************************************************
+ *     kaweth_open
+ ****************************************************************/
+static int kaweth_open(struct net_device *net)
+{
+	struct kaweth_device *kaweth = (struct kaweth_device *)net->priv;
+
+	kaweth_dbg("Dev usage: %d", kaweth->dev->refcnt.counter);
+
+	kaweth_dbg("Opening network device.");
+
+	MOD_INC_USE_COUNT;
+
+	kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
+
+	netif_start_queue(net);
+
+	kaweth_async_set_rx_mode(kaweth);
+	return 0;
+}
+
+/****************************************************************
+ *     kaweth_close
+ ****************************************************************/
+static int kaweth_close(struct net_device *net)
+{
+	struct kaweth_device *kaweth = net->priv;
+
+	netif_stop_queue(net);
+
+	kaweth->status |= KAWETH_STATUS_CLOSING;
+
+	usb_unlink_urb(kaweth->rx_urb);
+
+	kaweth->status &= ~KAWETH_STATUS_CLOSING;
+
+	MOD_DEC_USE_COUNT;
+
+	printk("Dev usage: %d", kaweth->dev->refcnt.counter);
+
+	return 0;
+}
+
+/****************************************************************
+ *     kaweth_ioctl
+ ****************************************************************/
+static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+	return -EOPNOTSUPP;
+}
+
+/****************************************************************
+ *     kaweth_usb_transmit_complete
+ ****************************************************************/
+static void kaweth_usb_transmit_complete(struct urb *urb)
+{
+	struct kaweth_device *kaweth = urb->context;
+
+	if (unlikely(urb->status != 0))
+		kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
+
+	netif_wake_queue(kaweth->net);
+}
+
+/****************************************************************
+ *     kaweth_start_xmit
+ ****************************************************************/
+static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+	struct kaweth_device *kaweth = net->priv;
+	int count = skb->len;
+	
+	int res;
+
+	spin_lock(&kaweth->device_lock);
+
+	kaweth_async_set_rx_mode(kaweth);
+	netif_stop_queue(net);
+
+	*((__u16 *)kaweth->tx_buf) = cpu_to_le16(skb->len);
+
+	memcpy(kaweth->tx_buf + 2, skb->data, skb->len);
+
+	memset(kaweth->tx_urb, 0, sizeof(*kaweth->tx_urb));
+
+	FILL_BULK_URB(kaweth->tx_urb,
+		      kaweth->dev,
+		      usb_sndbulkpipe(kaweth->dev, 2),
+		      kaweth->tx_buf,
+		      count + 2,
+		      kaweth_usb_transmit_complete,
+		      kaweth);
+
+	if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
+	{
+		kaweth_warn("kaweth failed tx_urb %d", res);
+		kaweth->stats.tx_errors++;
+		
+		netif_start_queue(net);
+	} 
+	else 
+	{
+		kaweth->stats.tx_packets++;
+		kaweth->stats.tx_bytes += skb->len;
+		net->trans_start = jiffies;
+	}
+
+	dev_kfree_skb(skb);
+
+	spin_unlock(&kaweth->device_lock);
+
+	return 0;
+}
+
+/****************************************************************
+ *     kaweth_set_rx_mode
+ ****************************************************************/
+static void kaweth_set_rx_mode(struct net_device *net)
+{
+	struct kaweth_device *kaweth = net->priv;
+	
+	__u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
+                                     KAWETH_PACKET_FILTER_BROADCAST |
+		                     KAWETH_PACKET_FILTER_MULTICAST;
+
+	kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap);
+
+	netif_stop_queue(net);
+
+	if (net->flags & IFF_PROMISC) {
+		packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
+	} 
+	else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) {
+		packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST;
+	}
+
+	kaweth->packet_filter_bitmap = packet_filter_bitmap;
+	netif_wake_queue(net);
+}
+
+/****************************************************************
+ *     kaweth_async_set_rx_mode
+ ****************************************************************/
+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
+{
+	__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
+	kaweth->packet_filter_bitmap = 0;	
+	if(packet_filter_bitmap == 0) return;
+
+	{
+	int result;
+	result = kaweth_control(kaweth,
+				usb_sndctrlpipe(kaweth->dev, 0),
+				KAWETH_COMMAND_SET_PACKET_FILTER,
+				USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+				packet_filter_bitmap,
+				0,
+				(void *)&kaweth->firmware_buf,
+				0,
+				KAWETH_CONTROL_TIMEOUT);
+
+	if(result < 0) {
+		kaweth_err("Failed to set Rx mode: %d", result);
+	}
+	else {
+		kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap);
+	}
+	}
+}
+
+/****************************************************************
+ *     kaweth_netdev_stats
+ ****************************************************************/
+static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
+{
+	return &((struct kaweth_device *)dev->priv)->stats;
+}
+
+/****************************************************************
+ *     kaweth_tx_timeout
+ ****************************************************************/
+static void kaweth_tx_timeout(struct net_device *net)
+{
+	struct kaweth_device *kaweth = net->priv;
+
+	kaweth_warn("%s: Tx timed out. Resetting.", net->name);
+	kaweth->stats.tx_errors++;
+	net->trans_start = jiffies;
+
+	usb_unlink_urb(kaweth->tx_urb);
+}
+
+/****************************************************************
+ *     kaweth_probe
+ ****************************************************************/
+static void *kaweth_probe(
+            struct usb_device *dev,             /* the device */
+            unsigned ifnum,                      /* what interface */
+            const struct usb_device_id *id      /* from id_table */
+	)
+{
+	struct kaweth_device *kaweth;
+	const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	int result = 0;
+
+	kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
+		 dev->devnum, 
+		 (int)dev->descriptor.idVendor, 
+		 (int)dev->descriptor.idProduct,
+		 (int)dev->descriptor.bcdDevice);
+
+	kaweth_dbg("Device at %p", dev);
+
+	kaweth_dbg("Descriptor length: %x type: %x", 
+		 (int)dev->descriptor.bLength,
+		 (int)dev->descriptor.bDescriptorType);
+
+	if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) {
+		kaweth_dbg("out of memory allocating device structure\n");
+		return NULL;
+	}
+
+	memset(kaweth, 0, sizeof(struct kaweth_device));
+
+	kaweth->dev = dev;
+	spin_lock_init(&kaweth->device_lock);
+		
+	kaweth_dbg("Resetting.");
+
+	kaweth_reset(kaweth);
+
+	/*
+	 * If high byte of bcdDevice is nonzero, firmware is already
+	 * downloaded. Don't try to do it again, or we'll hang the device.
+	 */
+
+	if (dev->descriptor.bcdDevice >> 8) {
+		kaweth_info("Firmware present in device.");
+	} else {
+		/* Download the firmware */
+		kaweth_info("Downloading firmware...");
+		if ((result = kaweth_download_firmware(kaweth, 
+						      kaweth_new_code, 
+						      len_kaweth_new_code, 
+						      100, 
+						      2)) < 0) {
+			kaweth_err("Error downloading firmware (%d)", result);
+			kfree(kaweth);
+			return NULL;
+		}
+
+		if ((result = kaweth_download_firmware(kaweth, 
+						      kaweth_new_code_fix, 
+						      len_kaweth_new_code_fix, 
+						      100, 
+						      3)) < 0) {
+			kaweth_err("Error downloading firmware fix (%d)", result);
+			kfree(kaweth);
+			return NULL;
+		}
+
+		if ((result = kaweth_download_firmware(kaweth,
+						      kaweth_trigger_code,
+						      len_kaweth_trigger_code,
+						      126,
+						      2)) < 0) {
+			kaweth_err("Error downloading trigger code (%d)", result);
+			kfree(kaweth);
+			return NULL;
+		}
+
+		if ((result = kaweth_download_firmware(kaweth,
+						      kaweth_trigger_code_fix,
+						      len_kaweth_trigger_code_fix,
+						      126,
+						      3)) < 0) {
+			kaweth_err("Error downloading trigger code fix (%d)", result);
+			kfree(kaweth);
+			return NULL;
+		}
+
+
+		if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
+			kaweth_err("Error triggering firmware (%d)", result);
+			kfree(kaweth);
+			return NULL;
+		}
+
+		/* Device will now disappear for a moment...  */
+		kaweth_info("Firmware loaded.  I'll be back...");
+		kfree(kaweth);
+		return NULL;
+	}
+
+	result = kaweth_read_configuration(kaweth);
+
+	if(result < 0) {
+		kaweth_err("Error reading configuration (%d), no net device created", result);
+		kfree(kaweth);
+		return NULL;
+	}
+
+	kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask);
+	kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
+	kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size));
+	kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+		 (int)kaweth->configuration.hw_addr[0],
+		 (int)kaweth->configuration.hw_addr[1],
+		 (int)kaweth->configuration.hw_addr[2],
+		 (int)kaweth->configuration.hw_addr[3],
+		 (int)kaweth->configuration.hw_addr[4],
+		 (int)kaweth->configuration.hw_addr[5]);
+
+	if(!memcmp(&kaweth->configuration.hw_addr,
+                   &bcast_addr, 
+		   sizeof(bcast_addr))) {
+		kaweth_err("Firmware not functioning properly, no net device created");
+		kfree(kaweth);
+		return NULL;
+	}
+
+	if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
+		kaweth_dbg("Error setting URB size");
+		return kaweth;
+	}
+	
+	if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
+		kaweth_err("Error setting SOFS wait");
+		return kaweth;
+	}
+
+	result = kaweth_set_receive_filter(kaweth, 
+                                           KAWETH_PACKET_FILTER_DIRECTED |
+                                           KAWETH_PACKET_FILTER_BROADCAST |
+                                           KAWETH_PACKET_FILTER_MULTICAST);
+
+	if(result < 0) {
+		kaweth_err("Error setting receive filter");
+		return kaweth;
+	}
+	
+	kaweth_dbg("Initializing net device.");
+
+	kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	kaweth->net = init_etherdev(0, 0);
+	if (!kaweth->net) {
+		kaweth_err("Error calling init_etherdev.");
+		return kaweth;
+	}
+
+	memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
+	memcpy(kaweth->net->dev_addr, 
+               &kaweth->configuration.hw_addr,
+               sizeof(kaweth->configuration.hw_addr));
+	 
+	kaweth->net->priv = kaweth;
+	kaweth->net->open = kaweth_open;
+	kaweth->net->stop = kaweth_close;
+
+	kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
+	kaweth->net->tx_timeout = kaweth_tx_timeout;
+	
+	kaweth->net->do_ioctl = kaweth_ioctl;
+	kaweth->net->hard_start_xmit = kaweth_start_xmit;
+	kaweth->net->set_multicast_list = kaweth_set_rx_mode;
+	kaweth->net->get_stats = kaweth_netdev_stats;
+	kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size);
+
+	memset(&kaweth->stats, 0, sizeof(kaweth->stats));
+
+	kaweth_info("kaweth interface created at %s", kaweth->net->name);
+								
+	kaweth_dbg("Kaweth probe returning.");
+
+	return kaweth;
+}
+
+/****************************************************************
+ *     kaweth_disconnect
+ ****************************************************************/
+static void kaweth_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct kaweth_device *kaweth = ptr;
+
+	kaweth_info("Unregistering");
+
+	if (!kaweth) {
+		kaweth_warn("unregistering non-existant device");
+		return;
+	}
+	usb_unlink_urb(kaweth->tx_urb);
+	usb_unlink_urb(kaweth->rx_urb);
+
+	if(kaweth->net) {
+		if(kaweth->net->flags & IFF_UP) {
+			kaweth_dbg("Closing net device");
+			dev_close(kaweth->net);
+		}
+
+		kaweth_dbg("Unregistering net device");
+		unregister_netdev(kaweth->net);
+	}
+
+	usb_free_urb(kaweth->rx_urb);
+	usb_free_urb(kaweth->tx_urb);
+
+	kfree(kaweth);
+}
+
+
+// FIXME this completion stuff is a modified clone of
+// an OLD version of some stuff in usb.c ... 
+struct usb_api_data {
+	wait_queue_head_t wqh;
+	int done;
+};
+
+/*-------------------------------------------------------------------*
+ * completion handler for compatibility wrappers (sync control/bulk) *
+ *-------------------------------------------------------------------*/
+static void usb_api_blocking_completion(struct urb *urb)
+{
+        struct usb_api_data *awd = (struct usb_api_data *)urb->context;
+
+	awd->done=1;
+	wake_up(&awd->wqh);
+}
+
+/*-------------------------------------------------------------------*
+ *                         COMPATIBILITY STUFF                       *
+ *-------------------------------------------------------------------*/
+
+// Starts urb and waits for completion or timeout
+static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+{
+        DECLARE_WAITQUEUE(wait, current);
+	struct usb_api_data awd;
+        int status;
+
+        init_waitqueue_head(&awd.wqh);
+        awd.done = 0;
+        
+        set_current_state(TASK_INTERRUPTIBLE);
+        add_wait_queue(&awd.wqh, &wait);
+        urb->context = &awd;
+        status = usb_submit_urb(urb, GFP_ATOMIC);
+        if (status) {
+                // something went wrong
+                usb_free_urb(urb);
+                set_current_state(TASK_RUNNING);
+                remove_wait_queue(&awd.wqh, &wait);
+                return status;
+        }
+
+	while (timeout && !awd.done)
+		timeout = schedule_timeout(timeout);
+
+        set_current_state(TASK_RUNNING);
+        remove_wait_queue(&awd.wqh, &wait);
+
+        if (!timeout) {
+                // timeout
+                kaweth_warn("usb_control/bulk_msg: timeout");
+                usb_unlink_urb(urb);  // remove urb safely
+                status = -ETIMEDOUT;
+        }
+	else {
+                status = urb->status;
+	}
+
+        if (actual_length) {
+                *actual_length = urb->actual_length;
+	}
+
+        usb_free_urb(urb);
+        return status;
+}
+
+/*-------------------------------------------------------------------*/
+// returns status (negative) or length (positive)
+int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
+                            struct usb_ctrlrequest *cmd, void *data, int len,
+			    int timeout)
+{
+        struct urb *urb;
+        int retv;
+        int length;
+
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb)
+                return -ENOMEM;
+
+        FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data,
+			 len, (usb_complete_t)usb_api_blocking_completion,0);
+
+        retv = usb_start_wait_urb(urb, timeout, &length);
+        if (retv < 0) {
+                return retv;
+	}
+        else {
+                return length;
+	}
+}
+
+
+/****************************************************************
+ *     kaweth_init
+ ****************************************************************/
+int __init kaweth_init(void)
+{
+	kaweth_dbg("Driver loading");
+	return usb_register(&kaweth_driver);
+}
+
+/****************************************************************
+ *     kaweth_exit
+ ****************************************************************/
+void __exit kaweth_exit(void)
+{
+	usb_deregister(&kaweth_driver);
+}
+
+module_init(kaweth_init);
+module_exit(kaweth_exit);
+
+
+
+
+
+
+
+
diff -Nru a/drivers/usb/net/kawethfw.h b/drivers/usb/net/kawethfw.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/kawethfw.h	Sun Apr 14 12:16:59 2002
@@ -0,0 +1,557 @@
+/******************************************/
+/* NOTE: B6/C3 is data header signature   */
+/*       0xAA/0xBB is data length = total */
+/*       bytes - 7, 0xCC is type, 0xDD is */
+/*       interrupt to use.                */
+/******************************************/
+
+/****************************************************************
+ *     kaweth_trigger_code
+ ****************************************************************/
+static __u8 kaweth_trigger_code[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0xc8, 0x07, 0xa0, 0x00, 0xf0, 0x07, 0x5e, 0x00,
+    0x06, 0x00, 0xf0, 0x07, 0x0a, 0x00, 0x08, 0x00,
+    0xf0, 0x09, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x07,
+    0x36, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00,
+    0x04, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x10, 0xc0,
+    0xf0, 0x09, 0x0e, 0xc0, 0x00, 0x00, 0xe7, 0x87,
+    0x01, 0x00, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09,
+    0x00, 0xc0, 0x17, 0x02, 0xc8, 0x07, 0xa0, 0x00,
+    0xe7, 0x17, 0x50, 0xc3, 0x10, 0xc0, 0x30, 0xd8,
+    0x04, 0x00, 0x30, 0x5c, 0x08, 0x00, 0x04, 0x00,
+    0xb0, 0xc0, 0x06, 0x00, 0xc8, 0x05, 0xe7, 0x05,
+    0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0x49, 0xaf,
+    0xc0, 0x07, 0x00, 0x00, 0x60, 0xaf, 0x4a, 0xaf,
+    0x00, 0x0c, 0x0c, 0x00, 0x40, 0xd2, 0x00, 0x1c,
+    0x0c, 0x00, 0x40, 0xd2, 0x30, 0x00, 0x08, 0x00,
+    0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0xf0, 0x07,
+    0x86, 0x00, 0x06, 0x00, 0x67, 0xcf, 0x27, 0x0c,
+    0x02, 0x00, 0x00, 0x00, 0x27, 0x0c, 0x00, 0x00,
+    0x0e, 0xc0, 0x49, 0xaf, 0x64, 0xaf, 0xc0, 0x07,
+    0x00, 0x00, 0x4b, 0xaf, 0x4a, 0xaf, 0x5a, 0xcf,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x94, 0x00, 0x05, 0x00,
+    0x00, 0x00
+};
+/****************************************************************
+ *     kaweth_trigger_code_fix
+ ****************************************************************/
+static __u8 kaweth_trigger_code_fix[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0x02, 0x00, 0x06, 0x00, 0x18, 0x00, 0x3e, 0x00,
+    0x80, 0x00, 0x98, 0x00, 0xaa, 0x00,
+    0x00, 0x00
+};
+
+/****************************************************************
+ *     kaweth_new_code
+ ****************************************************************/
+static __u8 kaweth_new_code[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0x9f, 0xcf, 0xde, 0x06, 0xe7, 0x57, 0x00, 0x00,
+    0xc4, 0x06, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f,
+    0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0,
+    0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf,
+    0xd7, 0x09, 0x00, 0xc0, 0xe7, 0x09, 0xa2, 0xc0,
+    0xbe, 0x06, 0x9f, 0xaf, 0x36, 0x00, 0xe7, 0x05,
+    0x00, 0xc0, 0xa7, 0xcf, 0xbc, 0x06, 0x97, 0xcf,
+    0xe7, 0x57, 0x00, 0x00, 0xb8, 0x06, 0xa7, 0xa1,
+    0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0x14, 0x08, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00,
+    0xa4, 0xc0, 0xa7, 0xc0, 0x7a, 0x06, 0x9f, 0xaf,
+    0x92, 0x07, 0xe7, 0x07, 0x00, 0x00, 0x14, 0x08,
+    0xe7, 0x57, 0xff, 0xff, 0xba, 0x06, 0x9f, 0xa0,
+    0x38, 0x00, 0xe7, 0x59, 0xba, 0x06, 0xbe, 0x06,
+    0x9f, 0xa0, 0x38, 0x00, 0xc8, 0x09, 0xca, 0x06,
+    0x08, 0x62, 0x9f, 0xa1, 0x36, 0x08, 0xc0, 0x09,
+    0x76, 0x06, 0x00, 0x60, 0xa7, 0xc0, 0x7a, 0x06,
+    0x9f, 0xaf, 0xcc, 0x02, 0xe7, 0x57, 0x00, 0x00,
+    0xb8, 0x06, 0xa7, 0xc1, 0x7a, 0x06, 0x9f, 0xaf,
+    0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x06,
+    0x0a, 0xc1, 0xe7, 0x09, 0x20, 0xc0, 0x10, 0x08,
+    0xe7, 0xd0, 0x10, 0x08, 0xe7, 0x67, 0x40, 0x00,
+    0x10, 0x08, 0x9f, 0xaf, 0x92, 0x0c, 0xc0, 0x09,
+    0xd0, 0x06, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59,
+    0xbe, 0x06, 0x02, 0xc0, 0x9f, 0xaf, 0xec, 0x00,
+    0x9f, 0xaf, 0x34, 0x02, 0xe7, 0x57, 0x00, 0x00,
+    0xa6, 0x06, 0x9f, 0xa0, 0x7a, 0x02, 0xa7, 0xcf,
+    0x7a, 0x06, 0x48, 0x02, 0xe7, 0x09, 0xbe, 0x06,
+    0xd0, 0x06, 0xc8, 0x37, 0x04, 0x00, 0x9f, 0xaf,
+    0x08, 0x03, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0xce, 0x06, 0x97, 0xc0, 0xd7, 0x09, 0x00, 0xc0,
+    0xc1, 0xdf, 0xc8, 0x09, 0xc6, 0x06, 0x08, 0x62,
+    0x14, 0xc0, 0x27, 0x04, 0xc6, 0x06, 0x10, 0x94,
+    0xf0, 0x07, 0x10, 0x08, 0x02, 0x00, 0xc1, 0x07,
+    0x01, 0x00, 0x70, 0x00, 0x04, 0x00, 0xf0, 0x07,
+    0x30, 0x01, 0x06, 0x00, 0x50, 0xaf, 0xe7, 0x07,
+    0xff, 0xff, 0xd0, 0x06, 0xe7, 0x07, 0x00, 0x00,
+    0xce, 0x06, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf,
+    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x48, 0x02,
+    0xd0, 0x09, 0xc6, 0x06, 0x27, 0x02, 0xc6, 0x06,
+    0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02,
+    0xc8, 0x37, 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00,
+    0x00, 0x60, 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00,
+    0x23, 0xc9, 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8,
+    0xc0, 0x17, 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff,
+    0x30, 0x00, 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00,
+    0x04, 0x00, 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00,
+    0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, 0xa0, 0x01,
+    0x0a, 0x00, 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00,
+    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf,
+    0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf,
+    0x08, 0x03, 0x9f, 0xaf, 0x7a, 0x02, 0x97, 0xcf,
+    0x9f, 0xaf, 0x7a, 0x02, 0xc9, 0x37, 0x04, 0x00,
+    0xc1, 0xdf, 0xc8, 0x09, 0xa2, 0x06, 0x50, 0x02,
+    0x67, 0x02, 0xa2, 0x06, 0xd1, 0x07, 0x00, 0x00,
+    0x27, 0xd8, 0xaa, 0x06, 0xc0, 0xdf, 0x9f, 0xaf,
+    0xc4, 0x01, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0xd2, 0x06, 0x97, 0xc1, 0xe7, 0x57, 0x01, 0x00,
+    0xa8, 0x06, 0x97, 0xc0, 0xc8, 0x09, 0xa0, 0x06,
+    0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, 0xc0, 0x17,
+    0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, 0x27, 0x0c,
+    0x0c, 0x00, 0x36, 0x01, 0xe7, 0x07, 0x50, 0xc3,
+    0x12, 0xc0, 0xe7, 0x07, 0xcc, 0x0b, 0x02, 0x00,
+    0xe7, 0x07, 0x01, 0x00, 0xa8, 0x06, 0xe7, 0x07,
+    0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, 0xc8, 0x09,
+    0xa4, 0x06, 0x08, 0x62, 0x02, 0xc0, 0x10, 0x64,
+    0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, 0x9e, 0x06,
+    0xe7, 0x07, 0x72, 0x04, 0x24, 0x00, 0x97, 0xcf,
+    0x27, 0x04, 0xa4, 0x06, 0xc8, 0x17, 0x0e, 0x00,
+    0x27, 0x02, 0x9e, 0x06, 0xe7, 0x07, 0x80, 0x04,
+    0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0,
+    0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, 0x90, 0x06,
+    0x13, 0xc1, 0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x57,
+    0x00, 0x00, 0x9e, 0x06, 0x13, 0xc0, 0xe7, 0x09,
+    0x9e, 0x06, 0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05,
+    0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0,
+    0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06, 0x04, 0xcf,
+    0xe7, 0x57, 0x00, 0x00, 0x9e, 0x06, 0x02, 0xc1,
+    0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x05, 0x00, 0xc0,
+    0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf,
+    0x08, 0x92, 0xe7, 0x57, 0x02, 0x00, 0xaa, 0x06,
+    0x02, 0xc3, 0xc8, 0x09, 0xa4, 0x06, 0x27, 0x02,
+    0xa6, 0x06, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05,
+    0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0xa4, 0x06,
+    0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00,
+    0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00,
+    0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00,
+    0x06, 0x00, 0xf0, 0x07, 0x46, 0x01, 0x0a, 0x00,
+    0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00,
+    0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0x96, 0x06, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09,
+    0x96, 0x06, 0x27, 0x04, 0x96, 0x06, 0x27, 0x52,
+    0x98, 0x06, 0x03, 0xc1, 0xe7, 0x07, 0x96, 0x06,
+    0x98, 0x06, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17,
+    0x0e, 0x00, 0x9f, 0xaf, 0xba, 0x03, 0xc8, 0x05,
+    0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x24, 0x03,
+    0x97, 0xcf, 0x9f, 0xaf, 0x08, 0x03, 0x97, 0xcf,
+    0x57, 0x02, 0xc9, 0x07, 0xa4, 0x06, 0xd7, 0x09,
+    0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, 0x1b, 0xc0,
+    0x50, 0x04, 0x11, 0x02, 0xe7, 0x05, 0x00, 0xc0,
+    0xc9, 0x05, 0x97, 0xcf, 0x97, 0x02, 0xca, 0x09,
+    0xd6, 0x06, 0xf2, 0x17, 0x01, 0x00, 0x04, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x06, 0x00, 0xca, 0x17,
+    0x2c, 0x00, 0xf8, 0x77, 0x01, 0x00, 0x0e, 0x00,
+    0x06, 0xc0, 0xca, 0xd9, 0xf8, 0x57, 0xff, 0x00,
+    0x0e, 0x00, 0x01, 0xc1, 0xca, 0xd9, 0x22, 0x1c,
+    0x0c, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17,
+    0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xca, 0x05,
+    0x00, 0x0c, 0x0c, 0x00, 0xc0, 0x17, 0x41, 0x00,
+    0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, 0x08, 0x00,
+    0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00,
+    0x06, 0x00, 0xf0, 0x07, 0xda, 0x00, 0x0a, 0x00,
+    0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0c,
+    0x08, 0x00, 0x40, 0xd1, 0x01, 0x00, 0xc0, 0x19,
+    0xce, 0x06, 0xc0, 0x59, 0xc2, 0x06, 0x04, 0xc9,
+    0x49, 0xaf, 0x9f, 0xaf, 0xec, 0x00, 0x4a, 0xaf,
+    0x67, 0x10, 0xce, 0x06, 0xc8, 0x17, 0x04, 0x00,
+    0xc1, 0x07, 0x01, 0x00, 0xd7, 0x09, 0x00, 0xc0,
+    0xc1, 0xdf, 0x50, 0xaf, 0xe7, 0x05, 0x00, 0xc0,
+    0x97, 0xcf, 0xc0, 0x07, 0x01, 0x00, 0xc1, 0x09,
+    0xac, 0x06, 0xc1, 0x77, 0x01, 0x00, 0x97, 0xc1,
+    0xd8, 0x77, 0x01, 0x00, 0x12, 0xc0, 0xc9, 0x07,
+    0x6a, 0x06, 0x9f, 0xaf, 0x08, 0x04, 0x04, 0xc1,
+    0xc1, 0x77, 0x08, 0x00, 0x13, 0xc0, 0x97, 0xcf,
+    0xc1, 0x77, 0x02, 0x00, 0x97, 0xc1, 0xc1, 0x77,
+    0x10, 0x00, 0x0c, 0xc0, 0x9f, 0xaf, 0x2c, 0x04,
+    0x97, 0xcf, 0xc1, 0x77, 0x04, 0x00, 0x06, 0xc0,
+    0xc9, 0x07, 0x70, 0x06, 0x9f, 0xaf, 0x08, 0x04,
+    0x97, 0xc0, 0x00, 0xcf, 0x00, 0x90, 0x97, 0xcf,
+    0x50, 0x54, 0x97, 0xc1, 0x70, 0x5c, 0x02, 0x00,
+    0x02, 0x00, 0x97, 0xc1, 0x70, 0x5c, 0x04, 0x00,
+    0x04, 0x00, 0x97, 0xcf, 0x80, 0x01, 0xc0, 0x00,
+    0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00,
+    0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, 0xb2, 0x06,
+    0xcc, 0x09, 0xb4, 0x06, 0x0b, 0x53, 0x11, 0xc0,
+    0xc9, 0x02, 0xca, 0x07, 0x1c, 0x04, 0x9f, 0xaf,
+    0x08, 0x04, 0x97, 0xc0, 0x0a, 0xc8, 0x82, 0x08,
+    0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, 0x08, 0x04,
+    0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, 0x82, 0x60,
+    0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, 0x89, 0x10,
+    0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, 0x82, 0x08,
+    0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, 0xc0, 0xdf,
+    0x97, 0xcf, 0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06,
+    0xe7, 0x09, 0x98, 0xc0, 0x94, 0x06, 0x0f, 0xcf,
+    0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06, 0xe7, 0x09,
+    0x98, 0xc0, 0x94, 0x06, 0xe7, 0x09, 0x9e, 0x06,
+    0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01,
+    0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09,
+    0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0x90, 0x06,
+    0xc8, 0x37, 0x0e, 0x00, 0xe7, 0x77, 0x2a, 0x00,
+    0x92, 0x06, 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09,
+    0xd6, 0x06, 0xe7, 0x77, 0x20, 0x00, 0x92, 0x06,
+    0x0e, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77,
+    0x0a, 0x00, 0x92, 0x06, 0xca, 0x05, 0x1e, 0xc0,
+    0x97, 0x02, 0xca, 0x09, 0xd6, 0x06, 0xf2, 0x17,
+    0x01, 0x00, 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00,
+    0x0e, 0x00, 0xe7, 0x77, 0x02, 0x00, 0x92, 0x06,
+    0x07, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf,
+    0xf2, 0x17, 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27,
+    0x00, 0x00, 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf,
+    0x08, 0x03, 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02,
+    0xf1, 0x09, 0x94, 0x06, 0x0c, 0x00, 0xf1, 0xda,
+    0x0c, 0x00, 0xc8, 0x09, 0x98, 0x06, 0x50, 0x02,
+    0x67, 0x02, 0x98, 0x06, 0xd1, 0x07, 0x00, 0x00,
+    0xc9, 0x05, 0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06,
+    0xe7, 0x57, 0x00, 0x00, 0x90, 0x06, 0x02, 0xc0,
+    0x9f, 0xaf, 0x06, 0x02, 0xc8, 0x05, 0xe7, 0x05,
+    0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09,
+    0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, 0x97, 0x02,
+    0xc0, 0x09, 0x92, 0xc0, 0xe7, 0x07, 0x04, 0x00,
+    0x90, 0xc0, 0xca, 0x09, 0xd6, 0x06, 0xe7, 0x07,
+    0x00, 0x00, 0xa8, 0x06, 0xe7, 0x07, 0x6a, 0x04,
+    0x02, 0x00, 0xc0, 0x77, 0x02, 0x00, 0x08, 0xc0,
+    0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27,
+    0x00, 0x00, 0x52, 0x00, 0x9f, 0xcf, 0x24, 0x06,
+    0xc0, 0x77, 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17,
+    0x01, 0x00, 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00,
+    0x5a, 0x00, 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0,
+    0xf2, 0x17, 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27,
+    0x00, 0x00, 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00,
+    0x1d, 0xc1, 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77,
+    0x00, 0x02, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00,
+    0x64, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00,
+    0xc0, 0x77, 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17,
+    0x01, 0x00, 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00,
+    0x5e, 0x00, 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0,
+    0x1b, 0xcf, 0x1a, 0xcf, 0xf2, 0x17, 0x01, 0x00,
+    0x00, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00,
+    0xc8, 0x09, 0x34, 0x01, 0xca, 0x17, 0x14, 0x00,
+    0xd8, 0x77, 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9,
+    0xd8, 0x57, 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9,
+    0xe2, 0x19, 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00,
+    0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00,
+    0x9f, 0xaf, 0x40, 0x06, 0x9f, 0xaf, 0xc4, 0x01,
+    0xe7, 0x57, 0x00, 0x00, 0xd2, 0x06, 0x9f, 0xa1,
+    0x0e, 0x0a, 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05,
+    0xe7, 0x05, 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf,
+    0xc8, 0x09, 0xa0, 0x06, 0x08, 0x62, 0x97, 0xc0,
+    0x27, 0x04, 0xa0, 0x06, 0x27, 0x52, 0xa2, 0x06,
+    0x03, 0xc1, 0xe7, 0x07, 0xa0, 0x06, 0xa2, 0x06,
+    0x9f, 0xaf, 0x08, 0x03, 0xe7, 0x57, 0x00, 0x00,
+    0xaa, 0x06, 0x02, 0xc0, 0x27, 0xda, 0xaa, 0x06,
+    0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xff, 0xff, 0xfb, 0x13, 0xe7, 0x57,
+    0x00, 0x80, 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07,
+    0xee, 0x0b, 0x12, 0x00, 0xe7, 0x07, 0x34, 0x0c,
+    0xb2, 0x00, 0xe7, 0x07, 0xc6, 0x07, 0xf2, 0x02,
+    0xc8, 0x09, 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00,
+    0x0d, 0x00, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0x0e, 0xc0, 0xc8, 0x09, 0xde, 0x00,
+    0xc8, 0x17, 0x09, 0x00, 0xc9, 0x07, 0xda, 0x06,
+    0xc0, 0x07, 0x04, 0x00, 0x68, 0x0a, 0x00, 0xda,
+    0x7d, 0xc1, 0xe7, 0x09, 0xc0, 0x00, 0x7c, 0x06,
+    0xe7, 0x09, 0xbe, 0x00, 0x78, 0x06, 0xe7, 0x09,
+    0x10, 0x00, 0xbc, 0x06, 0xc8, 0x07, 0xd6, 0x07,
+    0x9f, 0xaf, 0xae, 0x07, 0x9f, 0xaf, 0x00, 0x0a,
+    0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e, 0x0f, 0x00,
+    0x41, 0x90, 0x9f, 0xde, 0x06, 0x00, 0x44, 0xaf,
+    0x27, 0x00, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06,
+    0x27, 0x00, 0xb6, 0x06, 0xc0, 0x07, 0x74, 0x00,
+    0x44, 0xaf, 0x27, 0x00, 0xd6, 0x06, 0x08, 0x00,
+    0x00, 0x90, 0xc1, 0x07, 0x3a, 0x00, 0x20, 0x00,
+    0x01, 0xda, 0x7d, 0xc1, 0x9f, 0xaf, 0xba, 0x09,
+    0xc0, 0x07, 0x44, 0x00, 0x48, 0xaf, 0x27, 0x00,
+    0x7a, 0x06, 0x9f, 0xaf, 0x96, 0x0a, 0xe7, 0x07,
+    0x01, 0x00, 0xc0, 0x06, 0xe7, 0x05, 0x0e, 0xc0,
+    0x97, 0xcf, 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00,
+    0x0e, 0xc0, 0xe7, 0x07, 0xff, 0xff, 0xbe, 0x06,
+    0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07, 0x01, 0x00,
+    0x60, 0xaf, 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08,
+    0x09, 0x08, 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1,
+    0x97, 0xcf, 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf,
+    0x51, 0x94, 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf,
+    0xc9, 0x09, 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1,
+    0xc0, 0xdf, 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00,
+    0x24, 0x00, 0x80, 0x04, 0x22, 0x00, 0x4e, 0x05,
+    0xd0, 0x00, 0x0e, 0x0a, 0xaa, 0x00, 0x30, 0x08,
+    0xbe, 0x00, 0x4a, 0x0a, 0x10, 0x00, 0x20, 0x00,
+    0x04, 0x00, 0x6e, 0x04, 0x02, 0x00, 0x6a, 0x04,
+    0x06, 0x00, 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04,
+    0x28, 0xc0, 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04,
+    0x22, 0xc0, 0xff, 0xf4, 0xc0, 0x00, 0x90, 0x09,
+    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56, 0x08,
+    0x60, 0x08, 0xd0, 0x08, 0xda, 0x08, 0x00, 0x09,
+    0x04, 0x09, 0x08, 0x09, 0x32, 0x09, 0x42, 0x09,
+    0x50, 0x09, 0x52, 0x09, 0x5a, 0x09, 0x5a, 0x09,
+    0x27, 0x02, 0xca, 0x06, 0x97, 0xcf, 0xe7, 0x07,
+    0x00, 0x00, 0xca, 0x06, 0x0a, 0x0e, 0x01, 0x00,
+    0xca, 0x57, 0x0e, 0x00, 0x9f, 0xc3, 0x5a, 0x09,
+    0xca, 0x37, 0x00, 0x00, 0x9f, 0xc2, 0x5a, 0x09,
+    0x0a, 0xd2, 0xb2, 0xcf, 0x16, 0x08, 0xc8, 0x09,
+    0xde, 0x00, 0x07, 0x06, 0x9f, 0xcf, 0x6c, 0x09,
+    0x17, 0x02, 0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e,
+    0x0f, 0x00, 0x41, 0x90, 0x9f, 0xde, 0x06, 0x00,
+    0xc8, 0x05, 0x30, 0x50, 0x06, 0x00, 0x9f, 0xc8,
+    0x5a, 0x09, 0x27, 0x0c, 0x02, 0x00, 0xb0, 0x06,
+    0xc0, 0x09, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06,
+    0xe7, 0x07, 0x00, 0x00, 0xae, 0x06, 0x27, 0x00,
+    0x80, 0x06, 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00,
+    0xb6, 0x06, 0x41, 0x90, 0x67, 0x50, 0xb0, 0x06,
+    0x0d, 0xc0, 0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c,
+    0x06, 0x00, 0x82, 0x06, 0xe7, 0x07, 0xbc, 0x08,
+    0x84, 0x06, 0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90,
+    0x51, 0xaf, 0x97, 0xcf, 0x9f, 0xaf, 0x48, 0x0c,
+    0xe7, 0x09, 0xb6, 0x06, 0xb4, 0x06, 0xe7, 0x09,
+    0xb0, 0x06, 0xae, 0x06, 0x59, 0xaf, 0x97, 0xcf,
+    0x27, 0x0c, 0x02, 0x00, 0xac, 0x06, 0x59, 0xaf,
+    0x97, 0xcf, 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda,
+    0x49, 0xd2, 0xc9, 0x19, 0xd6, 0x06, 0xc8, 0x07,
+    0x7e, 0x06, 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02,
+    0xe0, 0x07, 0x04, 0x00, 0xd0, 0x07, 0xcc, 0x08,
+    0x48, 0xdb, 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf,
+    0x59, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf,
+    0xf0, 0x57, 0x06, 0x00, 0x06, 0x00, 0x25, 0xc1,
+    0xe7, 0x07, 0x70, 0x06, 0x80, 0x06, 0x41, 0x90,
+    0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c, 0x06, 0x00,
+    0x82, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06,
+    0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90, 0x51, 0xaf,
+    0x97, 0xcf, 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57,
+    0x06, 0x00, 0x0f, 0xc1, 0xc8, 0x07, 0x70, 0x06,
+    0x15, 0xcf, 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda,
+    0x40, 0xd1, 0x27, 0x00, 0xc2, 0x06, 0x1e, 0xcf,
+    0x1d, 0xcf, 0x27, 0x0c, 0x02, 0x00, 0xcc, 0x06,
+    0x19, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07,
+    0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00,
+    0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00,
+    0x7e, 0x06, 0xe7, 0x01, 0x82, 0x06, 0x27, 0x02,
+    0x80, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06,
+    0xc8, 0x07, 0x7e, 0x06, 0xc1, 0x07, 0x00, 0x80,
+    0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf,
+    0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00,
+    0xc4, 0x06, 0xa7, 0xcf, 0x7c, 0x06, 0x9f, 0xaf,
+    0x00, 0x0a, 0xe7, 0x07, 0x01, 0x00, 0xc4, 0x06,
+    0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf,
+    0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf,
+    0x7c, 0x06, 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf,
+    0x40, 0x00, 0xc0, 0x37, 0x00, 0x01, 0x41, 0x90,
+    0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, 0x50, 0x06,
+    0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, 0xc0, 0x07,
+    0x10, 0x00, 0x27, 0x00, 0x9a, 0x06, 0x41, 0x90,
+    0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, 0x27, 0x00,
+    0x9c, 0x06, 0xc0, 0x09, 0x9a, 0x06, 0x41, 0x90,
+    0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, 0x08, 0x00,
+    0x44, 0xaf, 0x27, 0x00, 0xc8, 0x06, 0x97, 0xcf,
+    0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, 0xe7, 0x67,
+    0xff, 0xfb, 0x24, 0xc0, 0x97, 0xcf, 0xe7, 0x87,
+    0x01, 0x00, 0xd2, 0x06, 0xe7, 0x57, 0x00, 0x00,
+    0xa8, 0x06, 0x97, 0xc1, 0x9f, 0xaf, 0x00, 0x0a,
+    0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, 0xfe, 0xff,
+    0x3e, 0xc0, 0xe7, 0x07, 0x26, 0x00, 0x0a, 0xc0,
+    0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, 0xe7, 0x07,
+    0xff, 0xff, 0xbe, 0x06, 0x9f, 0xaf, 0x10, 0x0b,
+    0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, 0x78, 0x06,
+    0xc0, 0x05, 0x27, 0x00, 0x76, 0x06, 0xe7, 0x87,
+    0x01, 0x00, 0xd2, 0x06, 0x9f, 0xaf, 0x00, 0x0a,
+    0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, 0x9f, 0xaf,
+    0x10, 0x0b, 0x00, 0x90, 0x27, 0x00, 0xa6, 0x06,
+    0x27, 0x00, 0xaa, 0x06, 0xe7, 0x09, 0xb2, 0x06,
+    0xb4, 0x06, 0x27, 0x00, 0xae, 0x06, 0x27, 0x00,
+    0xac, 0x06, 0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07,
+    0x00, 0x00, 0x27, 0x00, 0xb2, 0x02, 0x27, 0x00,
+    0xb4, 0x02, 0x27, 0x00, 0x8e, 0x06, 0xc0, 0x07,
+    0x06, 0x00, 0xc8, 0x09, 0xde, 0x00, 0xc8, 0x17,
+    0x03, 0x00, 0xc9, 0x07, 0x70, 0x06, 0x29, 0x0a,
+    0x00, 0xda, 0x7d, 0xc1, 0x97, 0xcf, 0xd7, 0x09,
+    0x00, 0xc0, 0xc1, 0xdf, 0x00, 0x90, 0x27, 0x00,
+    0x96, 0x06, 0xe7, 0x07, 0x96, 0x06, 0x98, 0x06,
+    0x27, 0x00, 0xa0, 0x06, 0xe7, 0x07, 0xa0, 0x06,
+    0xa2, 0x06, 0x27, 0x00, 0xa6, 0x06, 0x27, 0x00,
+    0x90, 0x06, 0x27, 0x00, 0x9e, 0x06, 0xc8, 0x09,
+    0x9c, 0x06, 0xc1, 0x09, 0x9a, 0x06, 0xc9, 0x07,
+    0xa4, 0x06, 0x11, 0x02, 0x09, 0x02, 0xc8, 0x17,
+    0x40, 0x06, 0x01, 0xda, 0x7a, 0xc1, 0x51, 0x94,
+    0xc8, 0x09, 0xc8, 0x06, 0xc9, 0x07, 0xc6, 0x06,
+    0xc1, 0x09, 0x9a, 0x06, 0x11, 0x02, 0x09, 0x02,
+    0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1,
+    0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf,
+    0xe7, 0x57, 0x00, 0x00, 0x76, 0x06, 0x97, 0xc0,
+    0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0xbe, 0x06,
+    0xba, 0x06, 0xe7, 0x57, 0xff, 0xff, 0xba, 0x06,
+    0x04, 0xc1, 0xe7, 0x07, 0x10, 0x0b, 0xb8, 0x06,
+    0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0xba, 0x06,
+    0xe7, 0x67, 0xff, 0x07, 0xba, 0x06, 0xe7, 0x07,
+    0x46, 0x0b, 0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57,
+    0x00, 0x00, 0xc0, 0x06, 0x23, 0xc0, 0xe7, 0x07,
+    0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x80,
+    0x80, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0,
+    0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07,
+    0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07,
+    0x00, 0x00, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0,
+    0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07,
+    0x00, 0x80, 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00,
+    0xe7, 0x07, 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00,
+    0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0,
+    0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0xc0, 0x06, 0xe7, 0x07, 0x00, 0x00,
+    0xb8, 0x06, 0xe7, 0x07, 0x00, 0x00, 0xd2, 0x06,
+    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf,
+    0x34, 0x02, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf,
+    0xc4, 0x01, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0,
+    0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xe7, 0x57,
+    0x00, 0x00, 0xa8, 0x06, 0x06, 0xc0, 0xc0, 0x09,
+    0x92, 0xc0, 0xc0, 0x77, 0x09, 0x02, 0x9f, 0xc1,
+    0x5c, 0x05, 0x9f, 0xcf, 0x32, 0x06, 0xd7, 0x09,
+    0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x0e, 0xc0,
+    0x9f, 0xaf, 0x02, 0x0c, 0xe7, 0x05, 0x0e, 0xc0,
+    0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x02,
+    0xc8, 0x09, 0xb0, 0xc0, 0xe7, 0x67, 0xfe, 0x7f,
+    0xb0, 0xc0, 0xc8, 0x77, 0x00, 0x20, 0x9f, 0xc1,
+    0x64, 0xeb, 0xe7, 0x57, 0x00, 0x00, 0xc8, 0x02,
+    0x9f, 0xc1, 0x80, 0xeb, 0xc8, 0x99, 0xca, 0x02,
+    0xc8, 0x67, 0x04, 0x00, 0x9f, 0xc1, 0x96, 0xeb,
+    0x9f, 0xcf, 0x4c, 0xeb, 0xe7, 0x07, 0x00, 0x00,
+    0xa6, 0xc0, 0xe7, 0x09, 0xb0, 0xc0, 0xc8, 0x02,
+    0xe7, 0x07, 0x03, 0x00, 0xb0, 0xc0, 0x97, 0xcf,
+    0xc0, 0x09, 0xb0, 0x06, 0xc0, 0x37, 0x01, 0x00,
+    0x97, 0xc9, 0xc9, 0x09, 0xb2, 0x06, 0x02, 0x00,
+    0x41, 0x90, 0x48, 0x02, 0xc9, 0x17, 0x06, 0x00,
+    0x9f, 0xaf, 0x08, 0x04, 0x9f, 0xa2, 0x72, 0x0c,
+    0x02, 0xda, 0x77, 0xc1, 0x41, 0x60, 0x71, 0xc1,
+    0x97, 0xcf, 0x17, 0x02, 0x57, 0x02, 0x43, 0x04,
+    0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, 0x21, 0x04,
+    0xe0, 0x00, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00,
+    0xc1, 0x07, 0x01, 0x00, 0xc9, 0x05, 0xc8, 0x05,
+    0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, 0x8e, 0x06,
+    0xc8, 0x07, 0x86, 0x06, 0xe7, 0x07, 0x00, 0x00,
+    0x86, 0x06, 0xe7, 0x07, 0x10, 0x08, 0x88, 0x06,
+    0xe7, 0x07, 0x04, 0x00, 0x8a, 0x06, 0xe7, 0x07,
+    0xbc, 0x0c, 0x8c, 0x06, 0xc1, 0x07, 0x03, 0x80,
+    0x50, 0xaf, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00,
+    0x8e, 0x06, 0x97, 0xcf,
+    0x00, 0x00
+};
+
+/****************************************************************
+ *     kaweth_new_code_fix
+ ****************************************************************/
+static __u8 kaweth_new_code_fix[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0x02, 0x00, 0x08, 0x00, 0x28, 0x00, 0x2c, 0x00,
+    0x34, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x48, 0x00,
+    0x54, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x64, 0x00,
+    0x68, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x72, 0x00,
+    0x76, 0x00, 0x7c, 0x00, 0x80, 0x00, 0x86, 0x00,
+    0x8a, 0x00, 0x90, 0x00, 0x94, 0x00, 0x98, 0x00,
+    0x9e, 0x00, 0xa6, 0x00, 0xaa, 0x00, 0xb0, 0x00,
+    0xb4, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc6, 0x00,
+    0xca, 0x00, 0xd0, 0x00, 0xd4, 0x00, 0xd8, 0x00,
+    0xe0, 0x00, 0xde, 0x00, 0xe8, 0x00, 0xf0, 0x00,
+    0xfc, 0x00, 0x04, 0x01, 0x0a, 0x01, 0x18, 0x01,
+    0x22, 0x01, 0x28, 0x01, 0x3a, 0x01, 0x3e, 0x01,
+    0x7e, 0x01, 0x98, 0x01, 0x9c, 0x01, 0xa2, 0x01,
+    0xac, 0x01, 0xb2, 0x01, 0xba, 0x01, 0xc0, 0x01,
+    0xc8, 0x01, 0xd0, 0x01, 0xd6, 0x01, 0xf4, 0x01,
+    0xfc, 0x01, 0x08, 0x02, 0x16, 0x02, 0x1a, 0x02,
+    0x22, 0x02, 0x2a, 0x02, 0x2e, 0x02, 0x3e, 0x02,
+    0x44, 0x02, 0x4a, 0x02, 0x50, 0x02, 0x64, 0x02,
+    0x62, 0x02, 0x6c, 0x02, 0x72, 0x02, 0x86, 0x02,
+    0x8c, 0x02, 0x90, 0x02, 0x9e, 0x02, 0xbc, 0x02,
+    0xd0, 0x02, 0xd8, 0x02, 0xdc, 0x02, 0xe0, 0x02,
+    0xe8, 0x02, 0xe6, 0x02, 0xf4, 0x02, 0xfe, 0x02,
+    0x04, 0x03, 0x0c, 0x03, 0x28, 0x03, 0x7c, 0x03,
+    0x90, 0x03, 0x94, 0x03, 0x9c, 0x03, 0xa2, 0x03,
+    0xc0, 0x03, 0xd0, 0x03, 0xd4, 0x03, 0xee, 0x03,
+    0xfa, 0x03, 0xfe, 0x03, 0x2e, 0x04, 0x32, 0x04,
+    0x3c, 0x04, 0x40, 0x04, 0x4e, 0x04, 0x76, 0x04,
+    0x7c, 0x04, 0x84, 0x04, 0x8a, 0x04, 0x8e, 0x04,
+    0xa6, 0x04, 0xb0, 0x04, 0xb8, 0x04, 0xbe, 0x04,
+    0xd2, 0x04, 0xdc, 0x04, 0xee, 0x04, 0x10, 0x05,
+    0x1a, 0x05, 0x24, 0x05, 0x2a, 0x05, 0x36, 0x05,
+    0x34, 0x05, 0x3c, 0x05, 0x42, 0x05, 0x64, 0x05,
+    0x6a, 0x05, 0x6e, 0x05, 0x86, 0x05, 0x22, 0x06,
+    0x26, 0x06, 0x2c, 0x06, 0x30, 0x06, 0x42, 0x06,
+    0x4a, 0x06, 0x4e, 0x06, 0x56, 0x06, 0x54, 0x06,
+    0x5a, 0x06, 0x60, 0x06, 0x66, 0x06, 0xe8, 0x06,
+    0xee, 0x06, 0xf4, 0x06, 0x16, 0x07, 0x26, 0x07,
+    0x2c, 0x07, 0x32, 0x07, 0x36, 0x07, 0x3a, 0x07,
+    0x3e, 0x07, 0x52, 0x07, 0x56, 0x07, 0x5a, 0x07,
+    0x64, 0x07, 0x76, 0x07, 0x7a, 0x07, 0x80, 0x07,
+    0x84, 0x07, 0x8a, 0x07, 0x9e, 0x07, 0xa2, 0x07,
+    0xda, 0x07, 0xde, 0x07, 0xe2, 0x07, 0xe6, 0x07,
+    0xea, 0x07, 0xee, 0x07, 0xf2, 0x07, 0xf6, 0x07,
+    0x0e, 0x08, 0x16, 0x08, 0x18, 0x08, 0x1a, 0x08,
+    0x1c, 0x08, 0x1e, 0x08, 0x20, 0x08, 0x22, 0x08,
+    0x24, 0x08, 0x26, 0x08, 0x28, 0x08, 0x2a, 0x08,
+    0x2c, 0x08, 0x2e, 0x08, 0x32, 0x08, 0x3a, 0x08,
+    0x46, 0x08, 0x4e, 0x08, 0x54, 0x08, 0x5e, 0x08,
+    0x78, 0x08, 0x7e, 0x08, 0x82, 0x08, 0x86, 0x08,
+    0x8c, 0x08, 0x90, 0x08, 0x98, 0x08, 0x9e, 0x08,
+    0xa4, 0x08, 0xaa, 0x08, 0xb0, 0x08, 0xae, 0x08,
+    0xb4, 0x08, 0xbe, 0x08, 0xc4, 0x08, 0xc2, 0x08,
+    0xca, 0x08, 0xc8, 0x08, 0xd4, 0x08, 0xe4, 0x08,
+    0xe8, 0x08, 0xf6, 0x08, 0x14, 0x09, 0x12, 0x09,
+    0x1a, 0x09, 0x20, 0x09, 0x26, 0x09, 0x24, 0x09,
+    0x2a, 0x09, 0x3e, 0x09, 0x4c, 0x09, 0x56, 0x09,
+    0x70, 0x09, 0x74, 0x09, 0x78, 0x09, 0x7e, 0x09,
+    0x7c, 0x09, 0x82, 0x09, 0x98, 0x09, 0x9c, 0x09,
+    0xa0, 0x09, 0xa6, 0x09, 0xb8, 0x09, 0xdc, 0x09,
+    0xe8, 0x09, 0xec, 0x09, 0xfc, 0x09, 0x12, 0x0a,
+    0x18, 0x0a, 0x1e, 0x0a, 0x42, 0x0a, 0x46, 0x0a,
+    0x4e, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a,
+    0x68, 0x0a, 0x6e, 0x0a, 0x72, 0x0a, 0x78, 0x0a,
+    0x76, 0x0a, 0x7c, 0x0a, 0x80, 0x0a, 0x84, 0x0a,
+    0x94, 0x0a, 0xa4, 0x0a, 0xb8, 0x0a, 0xbe, 0x0a,
+    0xbc, 0x0a, 0xc2, 0x0a, 0xc8, 0x0a, 0xc6, 0x0a,
+    0xcc, 0x0a, 0xd0, 0x0a, 0xd4, 0x0a, 0xd8, 0x0a,
+    0xdc, 0x0a, 0xe0, 0x0a, 0xf2, 0x0a, 0xf6, 0x0a,
+    0xfa, 0x0a, 0x14, 0x0b, 0x1a, 0x0b, 0x20, 0x0b,
+    0x1e, 0x0b, 0x26, 0x0b, 0x2e, 0x0b, 0x2c, 0x0b,
+    0x36, 0x0b, 0x3c, 0x0b, 0x42, 0x0b, 0x40, 0x0b,
+    0x4a, 0x0b, 0xaa, 0x0b, 0xb0, 0x0b, 0xb6, 0x0b,
+    0xc0, 0x0b, 0xc8, 0x0b, 0xda, 0x0b, 0xe8, 0x0b,
+    0xec, 0x0b, 0xfa, 0x0b, 0x4a, 0x0c, 0x54, 0x0c,
+    0x62, 0x0c, 0x66, 0x0c, 0x96, 0x0c, 0x9a, 0x0c,
+    0xa0, 0x0c, 0xa6, 0x0c, 0xa4, 0x0c, 0xac, 0x0c,
+    0xb2, 0x0c, 0xb0, 0x0c, 0xc0, 0x0c,
+    0x00, 0x00
+};
+
+
+const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
+const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
+const int len_kaweth_new_code = sizeof(kaweth_new_code);
+const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/pegasus.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,1115 @@
+/*
+**	Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
+**
+**	Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
+**	
+**
+**	ChangeLog:
+**		....	Most of the time spend reading sources & docs.
+**		v0.2.x	First official release for the Linux kernel.
+**		v0.3.0	Beutified and structured, some bugs fixed.
+**		v0.3.x	URBifying bulk requests and bugfixing. First relatively
+**			stable release. Still can touch device's registers only
+**			from top-halves.
+**		v0.4.0	Control messages remained unurbified are now URBs.
+**			Now we can touch the HW at any time.
+**		v0.4.9	Control urbs again use process context to wait. Argh...
+**			Some long standing bugs (enable_net_traffic) fixed.
+**			Also nasty trick about resubmiting control urb from
+**			interrupt context used. Please let me know how it
+**			behaves. Pegasus II support added since this version.
+**			TODO: suppressing HCD warnings spewage on disconnect.
+**		v0.4.13	Ethernet address is now set at probe(), not at open()
+**			time as this seems to break dhcpd. 
+**		v0.5.0	branch to 2.5.x kernels
+**		v0.5.1	ethtool support added
+*/
+
+/*
+ * This program is free software; you can redistribute it and/or 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/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include "pegasus.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.5.2 (2002/03/21)"
+#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
+#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
+
+#define	PEGASUS_USE_INTR
+#define	PEGASUS_WRITE_EEPROM
+#define	BMSR_MEDIA	(BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
+			BMSR_100FULL | BMSR_ANEGCAPABLE)
+
+static int loopback = 0;
+static int mii_mode = 0;
+static int multicast_filter_limit = 32;
+
+static struct usb_eth_dev usb_dev_id[] = {
+#define	PEGASUS_DEV(pn, vid, pid, flags)	\
+	{name:pn, vendor:vid, device:pid, private:flags},
+#include "pegasus.h"
+#undef	PEGASUS_DEV
+	{NULL, 0, 0, 0}
+};
+
+static struct usb_device_id pegasus_ids[] = {
+#define	PEGASUS_DEV(pn, vid, pid, flags) \
+	{match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor:vid, idProduct:pid},
+#include "pegasus.h"
+#undef	PEGASUS_DEV
+	{ }
+};
+
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+MODULE_PARM(loopback, "i");
+MODULE_PARM(mii_mode, "i");
+MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
+MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
+
+MODULE_DEVICE_TABLE (usb, pegasus_ids);
+
+
+static int update_eth_regs_async( pegasus_t * );
+/* Aargh!!! I _really_ hate such tweaks */
+static void ctrl_callback( struct urb *urb )
+{
+	pegasus_t	*pegasus = urb->context;
+
+	if ( !pegasus )
+		return;
+
+	switch ( urb->status ) {
+		case 0:
+			if ( pegasus->flags & ETH_REGS_CHANGE ) {
+				pegasus->flags &= ~ETH_REGS_CHANGE;
+				pegasus->flags |= ETH_REGS_CHANGED;
+				update_eth_regs_async( pegasus );
+				return;
+			}
+			break;
+		case -EINPROGRESS:
+			return;
+		case -ENOENT:
+			break;
+		default:
+			warn("%s: status %d", __FUNCTION__, urb->status);
+	}
+	pegasus->flags &= ~ETH_REGS_CHANGED;
+	wake_up(&pegasus->ctrl_wait );
+}
+
+
+static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
+{
+	int	ret;
+	unsigned char *buffer;
+	DECLARE_WAITQUEUE(wait, current);
+
+	buffer = kmalloc(size,GFP_KERNEL);
+	if (!buffer) {
+		err("unable to allocate memory for configuration descriptors");
+		return 0;
+	}
+	memcpy(buffer,data,size);
+
+	add_wait_queue(&pegasus->ctrl_wait, &wait);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	while ( pegasus->flags & ETH_REGS_CHANGED )
+		schedule();
+	remove_wait_queue(&pegasus->ctrl_wait, &wait);
+	set_current_state(TASK_RUNNING);
+
+	pegasus->dr.bRequestType = PEGASUS_REQT_READ;
+	pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS;
+	pegasus->dr.wValue = cpu_to_le16 (0);
+	pegasus->dr.wIndex = cpu_to_le16p(&indx);
+	pegasus->dr.wLength = cpu_to_le16p(&size);
+	pegasus->ctrl_urb->transfer_buffer_length = size;
+
+	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
+			  usb_rcvctrlpipe(pegasus->usb,0),
+			  (char *)&pegasus->dr,
+			  buffer, size, ctrl_callback, pegasus );
+
+	add_wait_queue( &pegasus->ctrl_wait, &wait );
+	set_current_state( TASK_UNINTERRUPTIBLE );
+
+	/* using ATOMIC, we'd never wake up if we slept */
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
+		err("%s: BAD CTRLs %d", __FUNCTION__, ret);
+		goto out;
+	}
+
+	schedule();
+out:
+	remove_wait_queue( &pegasus->ctrl_wait, &wait );
+	memcpy(data,buffer,size);
+	kfree(buffer);
+
+	return ret;
+}
+
+
+static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
+{
+	int	ret;
+	unsigned char *buffer;
+	DECLARE_WAITQUEUE(wait, current);
+
+	buffer = kmalloc(size, GFP_KERNEL);
+	if (!buffer) {
+		err("unable to allocate memory for configuration descriptors");
+		return 0;
+	}
+	memcpy(buffer, data, size);
+
+	add_wait_queue(&pegasus->ctrl_wait, &wait);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	while ( pegasus->flags & ETH_REGS_CHANGED )
+		schedule();
+	remove_wait_queue(&pegasus->ctrl_wait, &wait);
+	set_current_state(TASK_RUNNING);
+
+	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
+	pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
+	pegasus->dr.wValue = cpu_to_le16 (0);
+	pegasus->dr.wIndex = cpu_to_le16p( &indx );
+	pegasus->dr.wLength = cpu_to_le16p( &size );
+	pegasus->ctrl_urb->transfer_buffer_length = size;
+
+	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
+			  usb_sndctrlpipe(pegasus->usb,0),
+			  (char *)&pegasus->dr,
+			  buffer, size, ctrl_callback, pegasus );
+			  
+	add_wait_queue( &pegasus->ctrl_wait, &wait );
+	set_current_state( TASK_UNINTERRUPTIBLE );
+
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
+		err("%s: BAD CTRL %d", __FUNCTION__, ret);
+		goto out;
+	}
+	
+	schedule();
+out:
+	remove_wait_queue( &pegasus->ctrl_wait, &wait );
+	kfree(buffer);
+	
+	return ret;
+}
+
+
+static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data )
+{
+	int	ret;
+	unsigned char *buffer;
+	__u16 dat = data;
+	DECLARE_WAITQUEUE(wait, current);
+	
+	buffer = kmalloc(1, GFP_KERNEL);
+	if (!buffer) {
+		err("unable to allocate memory for configuration descriptors");
+		return 0;
+	}
+	memcpy(buffer, &data, 1);
+
+	add_wait_queue(&pegasus->ctrl_wait, &wait);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	while ( pegasus->flags & ETH_REGS_CHANGED )
+		schedule();
+	remove_wait_queue(&pegasus->ctrl_wait, &wait);
+	set_current_state(TASK_RUNNING);
+
+	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
+	pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
+	pegasus->dr.wValue = cpu_to_le16p( &dat);
+	pegasus->dr.wIndex = cpu_to_le16p( &indx );
+	pegasus->dr.wLength = cpu_to_le16( 1 );
+	pegasus->ctrl_urb->transfer_buffer_length = 1;
+
+	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
+			  usb_sndctrlpipe(pegasus->usb,0),
+			  (char *)&pegasus->dr,
+			  buffer, 1, ctrl_callback, pegasus );
+
+	add_wait_queue( &pegasus->ctrl_wait, &wait );
+	set_current_state( TASK_UNINTERRUPTIBLE );
+
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
+		err("%s: BAD CTRL %d", __FUNCTION__, ret);
+		goto out;
+	}
+
+	schedule();
+out:
+	remove_wait_queue( &pegasus->ctrl_wait, &wait );
+	kfree(buffer);
+
+	return ret;
+}
+
+
+static int update_eth_regs_async( pegasus_t *pegasus )
+{
+	int	ret;
+
+	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
+	pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
+	pegasus->dr.wValue = 0;
+	pegasus->dr.wIndex =  cpu_to_le16(EthCtrl0);
+	pegasus->dr.wLength = cpu_to_le16(3);
+	pegasus->ctrl_urb->transfer_buffer_length = 3;
+
+	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
+			  usb_sndctrlpipe(pegasus->usb,0),
+			  (char *)&pegasus->dr,
+			  pegasus->eth_regs, 3, ctrl_callback, pegasus );
+
+	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) )
+		err("%s: BAD CTRL %d, flgs %x",__FUNCTION__,ret,pegasus->flags);
+
+	return	ret;
+}
+
+
+static int read_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd )
+{
+	int	i;
+	__u8	data[4] = { phy, 0, 0, indx };
+	__u16  regdi;
+	
+	set_register( pegasus, PhyCtrl, 0 );
+	set_registers( pegasus, PhyAddr, sizeof(data), data );
+	set_register( pegasus, PhyCtrl, (indx | PHY_READ) );
+	for (i = 0; i < REG_TIMEOUT; i++) {
+		get_registers(pegasus, PhyCtrl, 1, data);
+		if ( data[0] & PHY_DONE ) 
+			break;
+	}
+	if ( i < REG_TIMEOUT ) {
+		get_registers( pegasus, PhyData, 2, &regdi );
+		*regd = le16_to_cpu(regdi);
+		return	0;
+	}
+	warn("%s: failed", __FUNCTION__);
+	
+	return 1;
+}
+
+
+static int write_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd )
+{
+	int	i;
+	__u8	data[4] = { phy, 0, 0, indx };
+	
+	*(data + 1) = cpu_to_le16p( &regd );
+	set_register( pegasus, PhyCtrl, 0 );
+	set_registers( pegasus, PhyAddr, 4, data );
+	set_register( pegasus, PhyCtrl, (indx | PHY_WRITE) );
+	for (i = 0; i < REG_TIMEOUT; i++) {
+		get_registers(pegasus, PhyCtrl, 1, data);
+		if ( data[0] & PHY_DONE ) 
+			break;
+	}
+	if ( i < REG_TIMEOUT )
+		return	0;
+	warn("%s: failed", __FUNCTION__);
+
+	return 1;
+}
+
+
+static int read_eprom_word( pegasus_t *pegasus, __u8 index, __u16 *retdata )
+{
+	int	i;
+	__u8 tmp;
+	__u16 retdatai;
+	
+	set_register( pegasus, EpromCtrl, 0 );
+	set_register( pegasus, EpromOffset, index );
+	set_register( pegasus, EpromCtrl, EPROM_READ); 
+
+	for ( i=0; i < REG_TIMEOUT; i++ ) {
+		get_registers( pegasus, EpromCtrl, 1, &tmp );
+		if ( tmp & EPROM_DONE )
+			break;
+	}
+	if ( i < REG_TIMEOUT ) {
+		get_registers( pegasus, EpromData, 2, &retdatai );
+		*retdata = le16_to_cpu (retdatai);
+		return	0;
+	}
+	warn("%s: failed", __FUNCTION__);
+
+	return -1;
+}
+
+#ifdef	PEGASUS_WRITE_EEPROM
+static inline void enable_eprom_write( pegasus_t *pegasus )
+{
+	__u8	tmp;
+
+	get_registers( pegasus, EthCtrl2, 1, &tmp );
+	set_register( pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE );
+}
+
+
+static inline void disable_eprom_write( pegasus_t *pegasus )
+{
+	__u8 	tmp;
+
+	get_registers( pegasus, EthCtrl2, 1, &tmp );
+	set_register( pegasus, EpromCtrl, 0 );
+	set_register( pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE );
+}
+
+
+static int write_eprom_word( pegasus_t *pegasus, __u8 index, __u16 data )
+{
+	int	i, tmp;
+	__u8	d[4] = {0x3f, 0, 0, EPROM_WRITE};
+
+	set_registers( pegasus, EpromOffset, 4, d );
+	enable_eprom_write( pegasus );
+	set_register( pegasus, EpromOffset, index );
+	set_registers( pegasus, EpromData, 2, &data );
+	set_register( pegasus, EpromCtrl, EPROM_WRITE );
+
+	for ( i=0; i < REG_TIMEOUT; i++ ) {
+		get_registers( pegasus, EpromCtrl, 1, &tmp );
+		if ( tmp & EPROM_DONE )
+			break;
+	}
+	disable_eprom_write( pegasus );
+	if ( i < REG_TIMEOUT )
+		return	0;
+	warn("%s: failed", __FUNCTION__);
+	return	-1;
+}
+#endif	/* PEGASUS_WRITE_EEPROM */
+
+static inline void get_node_id( pegasus_t *pegasus, __u8 *id )
+{
+	int	i;
+	__u16 w16;
+	
+	for (i = 0; i < 3; i++) {
+		read_eprom_word( pegasus, i, &w16);
+		((__u16 *) id)[i] = cpu_to_le16p (&w16);
+	}
+}
+
+
+static void set_ethernet_addr( pegasus_t *pegasus )
+{
+	__u8	node_id[6];
+
+	get_node_id(pegasus, node_id);
+	set_registers( pegasus, EthID, sizeof(node_id), node_id );
+	memcpy( pegasus->net->dev_addr, node_id, sizeof(node_id) );
+}
+
+
+static inline int reset_mac( pegasus_t *pegasus )
+{
+	__u8	data = 0x8;
+	int	i;
+
+	set_register(pegasus, EthCtrl1, data);
+	for (i = 0; i < REG_TIMEOUT; i++) {
+		get_registers(pegasus, EthCtrl1, 1, &data);
+		if (~data & 0x08) {
+			if (loopback & 1) 
+				break;
+			if ( mii_mode && (pegasus->features & HAS_HOME_PNA) )
+				set_register( pegasus, Gpio1, 0x34 );
+			else
+				set_register( pegasus, Gpio1, 0x26 );
+			set_register( pegasus, Gpio0, pegasus->features );
+			set_register( pegasus, Gpio0, DEFAULT_GPIO_SET );
+			break;
+		}
+	}
+	if ( i == REG_TIMEOUT )
+		return 1;
+
+	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
+	    usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
+		__u16	auxmode;
+		read_mii_word(pegasus, 1, MII_TPISTATUS, &auxmode);
+		write_mii_word(pegasus, 1, MII_TPISTATUS, auxmode | 4);
+	}
+	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
+		__u16   auxmode;
+		read_mii_word(pegasus, 3, 0x1b, &auxmode);
+		write_mii_word(pegasus, 3, 0x1b, auxmode | 4);
+	}
+
+	return	0;
+}
+
+
+static int enable_net_traffic( struct net_device *dev, struct usb_device *usb )
+{
+	__u16	linkpart, bmsr;
+	__u8	data[4];
+	pegasus_t *pegasus = dev->priv;
+
+
+	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr);
+	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr);
+	if ( !(bmsr & 4) && !loopback )
+		warn( "%s: link NOT established (%04x) - check the cable.",
+			dev->name, bmsr );
+	if ( read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart) )
+		return 2;
+	if ( !(linkpart & 1) )
+		warn( "link partner stat %x", linkpart );
+
+	data[0] = 0xc9;
+	data[1] = 0;
+	if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL) )
+		data[1] |= 0x20; /* set full duplex */
+	if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_100HALF) )
+		data[1] |= 0x10; /* set 100 Mbps */
+	if ( mii_mode )
+		data[1] = 0;
+	data[2] = (loopback & 1) ? 0x09 : 0x01;
+
+	memcpy( pegasus->eth_regs, data, sizeof(data) );
+
+	set_registers( pegasus, EthCtrl0, 3, data );
+
+	return 0;
+}
+
+
+static void read_bulk_callback( struct urb *urb )
+{
+	pegasus_t *pegasus = urb->context;
+	struct net_device *net;
+	int count = urb->actual_length, res;
+	int rx_status;
+	struct sk_buff	*skb;
+	__u16 pkt_len;
+
+	if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
+		return;
+
+	net = pegasus->net;
+	if ( !netif_device_present(net) )
+		return;
+
+	if ( pegasus->flags & PEGASUS_RX_BUSY ) {
+		pegasus->stats.rx_errors++;
+		dbg("pegasus Rx busy");
+		return;
+	}
+	pegasus->flags |= PEGASUS_RX_BUSY;
+
+	switch ( urb->status ) {
+		case 0:
+			break;
+		case -ETIMEDOUT:
+			dbg( "reset MAC" );
+			pegasus->flags &= ~PEGASUS_RX_BUSY;
+			break;
+		default:
+			dbg( "%s: RX status %d", net->name, urb->status );
+			goto goon;
+	}
+
+	if ( !count )
+		goto goon;
+
+	rx_status = le32_to_cpu(*(int *)(pegasus->rx_buff + count - 4));
+	if ( rx_status & 0x000e0000 ) {
+		dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
+		pegasus->stats.rx_errors++;
+		if ( rx_status & 0x060000 )
+			pegasus->stats.rx_length_errors++;
+		if ( rx_status & 0x080000 )
+			pegasus->stats.rx_crc_errors++;
+		if ( rx_status & 0x100000 )
+			pegasus->stats.rx_frame_errors++;
+		goto goon;
+	}
+
+	pkt_len = (rx_status & 0xfff) - 8;
+
+	if ( !(skb = dev_alloc_skb(pkt_len+2)) )
+		goto goon;
+
+	skb->dev = net;
+	skb_reserve(skb, 2);
+	eth_copy_and_sum(skb, pegasus->rx_buff, pkt_len, 0);
+	skb_put(skb, pkt_len);
+
+	skb->protocol = eth_type_trans(skb, net);
+	netif_rx(skb);
+	pegasus->stats.rx_packets++;
+	pegasus->stats.rx_bytes += pkt_len;
+
+goon:
+	FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
+			usb_rcvbulkpipe(pegasus->usb, 1),
+			pegasus->rx_buff, PEGASUS_MAX_MTU, 
+			read_bulk_callback, pegasus );
+	if ( (res = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) )
+		warn("%s: failed submint rx_urb %d", __FUNCTION__, res);
+	pegasus->flags &= ~PEGASUS_RX_BUSY;
+}
+
+
+static void write_bulk_callback( struct urb *urb )
+{
+	pegasus_t *pegasus = urb->context;
+
+	if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
+		return;
+
+	if ( !netif_device_present(pegasus->net) )
+		return;
+		
+	if ( urb->status )
+		info("%s: TX status %d", pegasus->net->name, urb->status);
+
+	pegasus->net->trans_start = jiffies;
+	netif_wake_queue( pegasus->net );
+}
+
+#ifdef	PEGASUS_USE_INTR
+static void intr_callback( struct urb *urb )
+{
+	pegasus_t *pegasus = urb->context;
+	struct net_device *net;
+	__u8	*d;
+
+	if ( !pegasus )
+		return;
+		
+	switch ( urb->status ) {
+		case 0:
+			break;
+		case -ENOENT:
+			return;
+		default:
+			info("intr status %d", urb->status);
+	}
+
+	d = urb->transfer_buffer;
+	net = pegasus->net;
+	if ( d[0] & 0xfc ) {
+		pegasus->stats.tx_errors++;
+		if ( d[0] & TX_UNDERRUN )
+			pegasus->stats.tx_fifo_errors++;
+		if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
+			pegasus->stats.tx_aborted_errors++;
+		if ( d[0] & LATE_COL )
+			pegasus->stats.tx_window_errors++;
+		if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
+			pegasus->stats.tx_carrier_errors++;
+	}
+}
+#endif
+
+static void pegasus_tx_timeout( struct net_device *net )
+{
+	pegasus_t *pegasus = net->priv;
+
+	if ( !pegasus )
+		return;
+		
+	warn("%s: Tx timed out.", net->name);
+	pegasus->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+	usb_unlink_urb( pegasus->tx_urb );
+	pegasus->stats.tx_errors++;
+}
+
+
+static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net )
+{
+	pegasus_t	*pegasus = net->priv;
+	int 	count = ((skb->len+2) & 0x3f) ? skb->len+2 : skb->len+3;
+	int 	res;
+	__u16 l16 = skb->len;
+	
+	netif_stop_queue( net );
+		
+	((__u16 *)pegasus->tx_buff)[0] = cpu_to_le16( l16 );
+	memcpy(pegasus->tx_buff+2, skb->data, skb->len);
+	FILL_BULK_URB( pegasus->tx_urb, pegasus->usb,
+			usb_sndbulkpipe(pegasus->usb, 2),
+			pegasus->tx_buff, PEGASUS_MAX_MTU, 
+			write_bulk_callback, pegasus );
+	pegasus->tx_urb->transfer_buffer_length = count;
+	if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
+		warn("failed tx_urb %d", res);
+		pegasus->stats.tx_errors++;
+		netif_start_queue( net );
+	} else {
+		pegasus->stats.tx_packets++;
+		pegasus->stats.tx_bytes += skb->len;
+		net->trans_start = jiffies;
+	}
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+
+static struct net_device_stats *pegasus_netdev_stats( struct net_device *dev )
+{
+	return &((pegasus_t *)dev->priv)->stats;
+}
+
+
+static inline void disable_net_traffic( pegasus_t *pegasus )
+{
+	int 	tmp=0;
+
+	set_registers( pegasus, EthCtrl0, 2, &tmp );
+}
+
+
+static inline void get_interrupt_interval( pegasus_t *pegasus )
+{
+	__u8	data[2];
+
+	read_eprom_word( pegasus, 4, (__u16 *)data );
+	if ( data[1] < 0x80 ) {
+		info( "intr interval will be changed from %ums to %ums",
+		     data[1], 0x80 );
+		data[1] = 0x80;
+#ifdef	PEGASUS_WRITE_EEPROM
+		write_eprom_word( pegasus, 4, *(__u16 *)data );
+#endif
+	}
+	pegasus->intr_interval = data[1];
+}
+
+
+static void set_carrier(struct net_device *net)
+{
+	pegasus_t	*pegasus;
+	short		tmp;
+
+	pegasus = net->priv;
+	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
+	if (tmp & BMSR_LSTATUS)
+		netif_carrier_on(net);
+	else
+		netif_carrier_off(net);
+	
+}
+
+
+static int pegasus_open(struct net_device *net)
+{
+	pegasus_t *pegasus = (pegasus_t *)net->priv;
+	int	res;
+
+	down(&pegasus->sem);
+	FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
+			usb_rcvbulkpipe(pegasus->usb, 1),
+			pegasus->rx_buff, PEGASUS_MAX_MTU, 
+			read_bulk_callback, pegasus );
+	if ( (res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)) )
+		warn("%s: failed rx_urb %d", __FUNCTION__, res);
+#ifdef	PEGASUS_USE_INTR
+	FILL_INT_URB( pegasus->intr_urb, pegasus->usb,
+			usb_rcvintpipe(pegasus->usb, 3),
+			pegasus->intr_buff, sizeof(pegasus->intr_buff),
+			intr_callback, pegasus, pegasus->intr_interval );
+	if ( (res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)) )
+		warn("%s: failed intr_urb %d", __FUNCTION__, res);
+#endif
+	netif_start_queue( net );
+	pegasus->flags |= PEGASUS_RUNNING;
+	if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
+		err("can't enable_net_traffic() - %d", res);
+		res = -EIO;
+		goto exit;
+	}
+	set_carrier(net);
+	res = 0;
+exit:
+	up(&pegasus->sem);
+
+	return res;
+}
+
+
+static int pegasus_close( struct net_device *net )
+{
+	pegasus_t	*pegasus = net->priv;
+
+	down(&pegasus->sem);
+	pegasus->flags &= ~PEGASUS_RUNNING;
+	netif_stop_queue( net );
+	if ( !(pegasus->flags & PEGASUS_UNPLUG) )
+		disable_net_traffic( pegasus );
+
+	usb_unlink_urb( pegasus->rx_urb );
+	usb_unlink_urb( pegasus->tx_urb );
+	usb_unlink_urb( pegasus->ctrl_urb );
+#ifdef	PEGASUS_USE_INTR
+	usb_unlink_urb( pegasus->intr_urb );
+#endif
+	up(&pegasus->sem);
+
+	return 0;
+}
+
+
+static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
+{
+	pegasus_t	*pegasus;
+	int		cmd;
+	char		tmp[128];
+
+	pegasus = net->priv;
+	if (get_user(cmd, (int *)uaddr))
+		return -EFAULT;
+	switch (cmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+		sprintf(tmp, "usb%d:%d", pegasus->usb->bus->busnum,
+		        pegasus->usb->devnum);
+		strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
+		if (copy_to_user(uaddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd;
+		short	lpa, bmcr;
+
+		if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
+			return -EFAULT;
+		ecmd.supported = (SUPPORTED_10baseT_Half |
+		                 SUPPORTED_10baseT_Full |
+		                 SUPPORTED_100baseT_Half |
+		                 SUPPORTED_100baseT_Full |
+		                 SUPPORTED_Autoneg |
+		                 SUPPORTED_TP |
+		                 SUPPORTED_MII);
+		ecmd.port = PORT_TP;
+		ecmd.transceiver = XCVR_INTERNAL;
+		ecmd.phy_address = pegasus->phy;
+		read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
+		read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
+		if (bmcr & BMCR_ANENABLE) {
+			ecmd.autoneg = AUTONEG_ENABLE;
+			ecmd.speed = lpa & (LPA_100HALF|LPA_100FULL) ?
+		                     SPEED_100 : SPEED_10;
+			if (ecmd.speed == SPEED_100)
+				ecmd.duplex = lpa & LPA_100FULL ?
+				              DUPLEX_FULL : DUPLEX_HALF;
+			else
+				ecmd.duplex = lpa & LPA_10FULL ?
+				              DUPLEX_FULL : DUPLEX_HALF;
+		} else {
+			ecmd.autoneg = AUTONEG_DISABLE;
+			ecmd.speed = bmcr & BMCR_SPEED100 ? 
+			             SPEED_100 : SPEED_10;
+			ecmd.duplex = bmcr & BMCR_FULLDPLX ?
+			              DUPLEX_FULL : DUPLEX_HALF;
+		}
+		if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		
+		return 0;
+	}
+	case ETHTOOL_SSET: {
+		return -EOPNOTSUPP;
+	}
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = netif_carrier_ok(net);
+		if (copy_to_user(uaddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int pegasus_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+{
+	__u16 *data = (__u16 *)&rq->ifr_data;
+	pegasus_t	*pegasus = net->priv;
+	int	res;
+
+	down(&pegasus->sem);
+	switch(cmd) {
+	case SIOCETHTOOL:
+		res = pegasus_ethtool_ioctl(net, rq->ifr_data);
+		break;
+	case SIOCDEVPRIVATE:
+		data[0] = pegasus->phy;
+	case SIOCDEVPRIVATE+1:
+		read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]);
+		res = 0;
+		break;
+	case SIOCDEVPRIVATE+2:
+		if ( !capable(CAP_NET_ADMIN) ) {
+			up(&pegasus->sem);
+			return -EPERM;
+		}
+		write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]);
+		res = 0;
+		break;
+	default:
+		res = -EOPNOTSUPP;
+	}
+	up(&pegasus->sem);
+	return res;
+}
+
+
+static void pegasus_set_multicast( struct net_device *net )
+{
+	pegasus_t *pegasus = net->priv;
+
+	netif_stop_queue(net);
+
+	if (net->flags & IFF_PROMISC) {
+		pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
+		info("%s: Promiscuous mode enabled", net->name);
+	} else if ((net->mc_count > multicast_filter_limit) ||
+			(net->flags & IFF_ALLMULTI)) {
+		pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
+		pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
+		info("%s set allmulti", net->name);
+	} else {
+		pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
+		pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
+	}
+
+	pegasus->flags |= ETH_REGS_CHANGE;
+	ctrl_callback( pegasus->ctrl_urb );
+
+	netif_wake_queue(net);
+}
+
+
+static __u8 mii_phy_probe( pegasus_t *pegasus )
+{
+	int	i;
+	__u16	tmp;
+
+	for ( i=0; i < 32; i++ ) {
+		read_mii_word( pegasus, i, MII_BMSR, &tmp );
+		if ( tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0 )
+			continue;
+		else
+			return	i;
+	}
+
+	return	0xff;
+}
+
+
+static inline void setup_pegasus_II( pegasus_t *pegasus )
+{
+	set_register( pegasus, Reg1d, 0 );
+	set_register( pegasus, Reg7b, 2 );
+	if ( pegasus->features & HAS_HOME_PNA  && mii_mode )
+		set_register( pegasus, Reg81, 6 );
+	else
+		set_register( pegasus, Reg81, 2 );
+}
+
+
+static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum,
+			     const struct usb_device_id *id)
+{
+	struct net_device	*net;
+	pegasus_t		*pegasus;
+	int			dev_index = id - pegasus_ids;
+
+	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
+		err("usb_set_configuration() failed");
+		return NULL;
+	}
+	if(!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) {
+		err("out of memory allocating device structure");
+		return NULL;
+	}
+
+	usb_inc_dev_use( dev );
+	memset(pegasus, 0, sizeof(struct pegasus));
+	pegasus->dev_index = dev_index;
+	init_waitqueue_head( &pegasus->ctrl_wait );
+
+	pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pegasus->ctrl_urb) {
+		kfree (pegasus);
+		return NULL;
+	}
+	pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pegasus->rx_urb) {
+		usb_free_urb (pegasus->ctrl_urb);
+		kfree (pegasus);
+		return NULL;
+	}
+	pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pegasus->tx_urb) {
+		usb_free_urb (pegasus->rx_urb);
+		usb_free_urb (pegasus->ctrl_urb);
+		kfree (pegasus);
+		return NULL;
+	}
+	pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pegasus->intr_urb) {
+		usb_free_urb (pegasus->tx_urb);
+		usb_free_urb (pegasus->rx_urb);
+		usb_free_urb (pegasus->ctrl_urb);
+		kfree (pegasus);
+		return NULL;
+	}
+
+	net = init_etherdev( NULL, 0 );
+	if ( !net ) {
+		usb_free_urb (pegasus->tx_urb);
+		usb_free_urb (pegasus->rx_urb);
+		usb_free_urb (pegasus->ctrl_urb);
+		kfree( pegasus );
+		return NULL;
+	}
+
+	init_MUTEX(&pegasus->sem);
+	down(&pegasus->sem);
+	pegasus->usb = dev;
+	pegasus->net = net;
+	SET_MODULE_OWNER(net);
+	net->priv = pegasus;
+	net->open = pegasus_open;
+	net->stop = pegasus_close;
+	net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
+	net->tx_timeout = pegasus_tx_timeout;
+	net->do_ioctl = pegasus_ioctl;
+	net->hard_start_xmit = pegasus_start_xmit;
+	net->set_multicast_list = pegasus_set_multicast;
+	net->get_stats = pegasus_netdev_stats;
+	net->mtu = PEGASUS_MTU;
+
+	pegasus->features = usb_dev_id[dev_index].private;
+#ifdef	PEGASUS_USE_INTR
+	get_interrupt_interval( pegasus );
+#endif
+	if ( reset_mac(pegasus) ) {
+		err("can't reset MAC");
+		unregister_netdev( pegasus->net );
+		usb_free_urb (pegasus->tx_urb);
+		usb_free_urb (pegasus->rx_urb);
+		usb_free_urb (pegasus->ctrl_urb);
+		kfree(pegasus->net);
+		kfree(pegasus);
+		pegasus = NULL;
+		goto exit;
+	}
+
+	info( "%s: %s", net->name, usb_dev_id[dev_index].name );
+
+	set_ethernet_addr( pegasus );
+
+	if ( pegasus->features & PEGASUS_II ) {
+		info( "setup Pegasus II specific registers" );
+		setup_pegasus_II( pegasus );
+	}
+	
+	pegasus->phy = mii_phy_probe( pegasus );
+	if ( pegasus->phy == 0xff ) {
+		warn( "can't locate MII phy, using default" );
+		pegasus->phy = 1;
+	}
+exit:
+	up(&pegasus->sem);
+	return pegasus;
+}
+
+
+static void pegasus_disconnect( struct usb_device *dev, void *ptr )
+{
+	struct pegasus *pegasus = ptr;
+
+	if ( !pegasus ) {
+		warn("unregistering non-existant device");
+		return;
+	}
+
+	pegasus->flags |= PEGASUS_UNPLUG;
+	unregister_netdev( pegasus->net );
+	usb_dec_dev_use( dev );
+	usb_unlink_urb(pegasus->intr_urb);
+	usb_unlink_urb(pegasus->tx_urb);
+	usb_unlink_urb(pegasus->rx_urb);
+	usb_unlink_urb(pegasus->ctrl_urb);
+	usb_free_urb(pegasus->intr_urb);
+	usb_free_urb(pegasus->tx_urb);
+	usb_free_urb(pegasus->rx_urb);
+	usb_free_urb(pegasus->ctrl_urb);
+	kfree( pegasus->net );
+	kfree( pegasus );
+	pegasus = NULL;
+}
+
+
+static struct usb_driver pegasus_driver = {
+	name:		"pegasus",
+	probe:		pegasus_probe,
+	disconnect:	pegasus_disconnect,
+	id_table:	pegasus_ids,
+};
+
+int __init pegasus_init(void)
+{
+	info(DRIVER_VERSION ":" DRIVER_DESC);
+	return usb_register( &pegasus_driver );
+}
+
+void __exit pegasus_exit(void)
+{
+	usb_deregister( &pegasus_driver );
+}
+
+module_init( pegasus_init );
+module_exit( pegasus_exit );
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/pegasus.h	Sun Apr 14 12:16:58 2002
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef	PEGASUS_DEV
+
+#define	PEGASUS_II		0x80000000
+#define	HAS_HOME_PNA		0x40000000
+
+#define	PEGASUS_MTU		1500
+#define	PEGASUS_MAX_MTU		1536
+
+#define	EPROM_WRITE		0x01
+#define	EPROM_READ		0x02
+#define	EPROM_DONE		0x04
+#define	EPROM_WR_ENABLE		0x10
+#define	EPROM_LOAD		0x20
+
+#define	PHY_DONE		0x80
+#define	PHY_READ		0x40
+#define	PHY_WRITE		0x20
+#define	DEFAULT_GPIO_RESET	0x24
+#define	LINKSYS_GPIO_RESET	0x24
+#define	DEFAULT_GPIO_SET	0x26
+
+#define	PEGASUS_PRESENT		0x00000001
+#define	PEGASUS_RUNNING		0x00000002
+#define	PEGASUS_TX_BUSY		0x00000004
+#define	PEGASUS_RX_BUSY		0x00000008
+#define	CTRL_URB_RUNNING	0x00000010
+#define	CTRL_URB_SLEEP		0x00000020
+#define	PEGASUS_UNPLUG		0x00000040
+#define	ETH_REGS_CHANGE		0x40000000
+#define	ETH_REGS_CHANGED	0x80000000
+
+#define	RX_MULTICAST		2
+#define	RX_PROMISCUOUS		4
+
+#define	REG_TIMEOUT		(HZ)
+#define	PEGASUS_TX_TIMEOUT	(HZ*10)
+
+#define	TX_UNDERRUN		0x80
+#define	EXCESSIVE_COL		0x40
+#define	LATE_COL		0x20
+#define	NO_CARRIER		0x10
+#define	LOSS_CARRIER		0x08
+#define	JABBER_TIMEOUT		0x04
+
+#define	PEGASUS_REQT_READ	0xc0
+#define	PEGASUS_REQT_WRITE	0x40
+#define	PEGASUS_REQ_GET_REGS	0xf0
+#define	PEGASUS_REQ_SET_REGS	0xf1
+#define	PEGASUS_REQ_SET_REG	PEGASUS_REQ_SET_REGS
+
+enum pegasus_registers {
+	EthCtrl0 = 0,
+	EthCtrl1 = 1,
+	EthCtrl2 = 2,
+	EthID = 0x10,
+	Reg1d = 0x1d,
+	EpromOffset = 0x20,
+	EpromData = 0x21,	/* 0x21 low, 0x22 high byte */
+	EpromCtrl = 0x23,
+	PhyAddr = 0x25,
+	PhyData = 0x26, 	/* 0x26 low, 0x27 high byte */
+	PhyCtrl = 0x28,
+	UsbStst = 0x2a,
+	EthTxStat0 = 0x2b,
+	EthTxStat1 = 0x2c,
+	EthRxStat = 0x2d,
+	Reg7b = 0x7b,
+	Gpio0 = 0x7e,
+	Gpio1 = 0x7f,
+	Reg81 = 0x81,
+};
+
+
+typedef struct pegasus {
+	struct usb_device	*usb;
+	struct net_device	*net;
+	struct net_device_stats	stats;
+	unsigned		flags;
+	unsigned		features;
+	int			dev_index;
+	int			intr_interval;
+	struct urb		*ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
+	struct usb_ctrlrequest	dr;
+	wait_queue_head_t	ctrl_wait;
+	struct semaphore	sem;
+	unsigned char		rx_buff[PEGASUS_MAX_MTU];
+	unsigned char		tx_buff[PEGASUS_MAX_MTU];
+	unsigned char		intr_buff[8];
+	__u8			eth_regs[4];
+	__u8			phy;
+	__u8			gpio_res;
+} pegasus_t;
+
+
+struct usb_eth_dev {
+	char	*name;
+	__u16	vendor;
+	__u16	device;
+	__u32	private; /* LSB is gpio reset value */
+};
+
+#define	VENDOR_3COM		0x0506
+#define	VENDOR_ABOCOM		0x07b8
+#define	VENDOR_ACCTON		0x083a
+#define	VENDOR_ADMTEK		0x07a6
+#define	VENDOR_ALLIEDTEL	0x07c9
+#define	VENDOR_BELKIN		0x050d
+#define	VENDOR_BILLIONTON	0x08dd
+#define	VENDOR_COMPAQ		0x049f
+#define	VENDOR_COREGA		0x07aa
+#define	VENDOR_DLINK		0x2001
+#define	VENDOR_ELCON		0x0db7
+#define	VENDOR_ELSA		0x05cc
+#define	VENDOR_HAWKING		0x0e66
+#define	VENDOR_IODATA		0x04bb
+#define	VENDOR_KINGSTON		0x0951
+#define	VENDOR_LANEED		0x056e
+#define	VENDOR_LINKSYS		0x066b
+#define	VENDOR_MELCO		0x0411
+#define	VENDOR_SMARTBRIDGES	0x08d1
+#define	VENDOR_SMC		0x0707
+#define	VENDOR_SOHOWARE		0x15e8
+#define	VENDOR_SIEMENS		0x067c
+
+
+#else	/* PEGASUS_DEV */
+
+PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c,
+		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
+PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104,
+		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004,
+		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007,
+		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
+		DEFAULT_GPIO_RESET | PEGASUS_II ) 	
+PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
+		VENDOR_ADMTEK, 0x8511,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
+		VENDOR_ADMTEK, 0x0986,
+		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
+		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
+		LINKSYS_GPIO_RESET )
+PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002,
+		LINKSYS_GPIO_RESET )
+PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102,
+		LINKSYS_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b,
+		LINKSYS_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c,
+		LINKSYS_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003,
+		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "ELCON EPLC10Mi USB to Powerline Adapter", VENDOR_ELCON, 0x0002,
+		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
+PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
+		DEFAULT_GPIO_RESET)
+PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202,
+		LINKSYS_GPIO_RESET )
+PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203,
+		LINKSYS_GPIO_RESET )
+PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204,
+		LINKSYS_GPIO_RESET | HAS_HOME_PNA )
+PEGASUS_DEV( "Linksys USB Ethernet Adapter", VENDOR_LINKSYS, 0x2206,
+		LINKSYS_GPIO_RESET )
+PEGASUS_DEV( "Linksys USB USB10TX", VENDOR_LINKSYS, 0x400b,
+		LINKSYS_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c,
+		LINKSYS_GPIO_RESET | PEGASUS_II )	
+PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
+		DEFAULT_GPIO_RESET | PEGASUS_II)
+PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
+		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
+		DEFAULT_GPIO_RESET )
+
+
+#endif	/* PEGASUS_DEV */
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/rtl8150.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+
+
+/* Version Information */
+#define DRIVER_VERSION "v0.5.0 (2002/03/28)"
+#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
+#define DRIVER_DESC "rtl8150 based usb-ethernet driver"
+
+
+#define	IRD			0x0120
+#define	MAR			0x0126
+#define	CR			0x012e
+#define	TCR			0x012f
+#define	RCR			0x0130
+#define	TSR			0x0132
+#define	RSR			0x0133
+#define	CON0			0x0135
+#define	CON1			0x0136
+#define	MSR			0x0137
+#define	PHYADD			0x0138
+#define	PHYDAT			0x0139
+#define	PHYCNT			0x013b
+#define	GPPC			0x013d
+#define	BMCR			0x0140
+#define	BMSR			0x0142
+#define	ANAR			0x0144
+#define	ANLP			0x0146
+#define	AER			0x0148
+
+#define	PHY_READ		0
+#define	PHY_WRITE		0x20
+#define	PHY_GO			0x40
+
+#define	RTL8150_REQT_READ	0xc0
+#define	RTL8150_REQT_WRITE	0x40
+#define	RTL8150_REQ_GET_REGS	0x05
+#define	RTL8150_REQ_SET_REGS	0x05
+
+#define	RTL8150_MTU		1500
+#define	RTL8150_MAX_MTU		1536
+
+#define	RTL8150_TX_TIMEOUT	(HZ)
+
+/* rtl8150 flags */
+#define	RTL8150_FLAG_HWCRC	0
+#define	RX_REG_SET		1
+#define	RTL8150_UNPLUG		2
+
+
+/* Define these values to match your device */
+#define VENDOR_ID_REALTEK		0x0bda
+#define PRODUCT_ID_RTL8150		0x8150
+
+/* table of devices that work with this driver */
+static struct usb_device_id rtl8150_table [] = {
+	{ USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150) },
+	{ }				
+};
+
+MODULE_DEVICE_TABLE (usb, rtl8150_table);
+
+
+struct rtl8150 {
+	unsigned int		flags;
+	struct usb_device	*udev;
+	struct usb_interface	*interface;
+	struct semaphore	sem;
+	struct net_device_stats	stats;
+	struct net_device	*netdev;
+	struct urb		*rx_urb, *tx_urb, *intr_urb, *ctrl_urb;
+	struct usb_ctrlrequest	dr;
+	int			intr_interval;
+	u16			rx_creg;
+	u8			rx_buff[RTL8150_MAX_MTU];
+	u8			tx_buff[RTL8150_MAX_MTU];
+	u8			intr_buff[8];
+	u8			phy;
+};
+
+typedef	struct rtl8150	rtl8150_t;
+
+
+/* the global usb devfs handle */
+extern devfs_handle_t usb_devfs_handle;
+unsigned long multicast_filter_limit = 32;
+
+
+static void rtl8150_disconnect(struct usb_device *dev, void *ptr);
+static void * rtl8150_probe(struct usb_device *dev, unsigned int ifnum,
+			    const struct usb_device_id *id);
+
+
+static struct usb_driver rtl8150_driver = {
+	name:		"rtl8150",
+	probe:		rtl8150_probe,
+	disconnect:	rtl8150_disconnect,
+	id_table:	rtl8150_table,
+};
+
+
+
+/*
+**
+**	device related part of the code
+**
+*/
+static int get_registers(rtl8150_t *dev, u16 indx, u16 size, void *data)
+{
+	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev,0),
+				RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
+				indx, 0, data, size, HZ/2);
+}
+
+
+static int set_registers(rtl8150_t *dev, u16 indx, u16 size, void *data)
+{
+	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev,0),
+				RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
+				indx, 0, data, size, HZ/2);
+}
+
+
+static void ctrl_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+	
+	switch (urb->status) {
+	case 0:
+		break;
+	case -EINPROGRESS:
+		break;
+	case -ENOENT:
+		break;
+	default:
+		warn("ctrl urb status %d", urb->status);
+	}
+	dev = urb->context;
+	clear_bit(RX_REG_SET, &dev->flags);
+}
+
+
+static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, void *data)
+{
+	int	ret;
+
+	if (test_bit(RX_REG_SET, &dev->flags))
+		return -EAGAIN;
+	
+	dev->dr.bRequestType = RTL8150_REQT_WRITE;
+	dev->dr.bRequest = RTL8150_REQ_SET_REGS;
+	dev->dr.wValue = cpu_to_le16(indx);
+	dev->dr.wIndex = 0;
+	dev->dr.wLength = cpu_to_le16(size);
+	dev->ctrl_urb->transfer_buffer_length = size;
+	FILL_CONTROL_URB(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev,0),
+	                 (char*)&dev->dr, &dev->rx_creg, size,
+	                 ctrl_callback, dev);
+	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))
+		err("control request submission failed: %d", ret);
+	else
+		set_bit(RX_REG_SET, &dev->flags);
+
+	return ret;
+}
+
+
+static int read_mii_word(rtl8150_t *dev, u8 phy, __u8 indx, u16 *reg)
+{
+	int	i;
+	u8	data[3], tmp;
+
+	data[0] = phy;
+	data[1] = data[2] = 0;
+	tmp = indx | PHY_READ | PHY_GO;
+	i = 0;
+
+	set_registers(dev, PHYADD, sizeof(data), data);
+	set_registers(dev, PHYCNT, 1, &tmp);
+	do {
+		get_registers(dev, PHYCNT, 1, data);
+	} while ((data[0] & PHY_GO) && (i++ < HZ));
+
+	if (i < HZ) {
+		get_registers(dev, PHYDAT, 2, data);
+		*reg = le16_to_cpup(data);
+		return 0;
+	} else
+		return 1;
+}
+
+
+static int write_mii_word(rtl8150_t *dev, u8 phy, __u8 indx, u16 reg)
+{
+	int	i;
+	u8	data[3], tmp;
+
+	data[0] = phy;
+	*(data + 1) = cpu_to_le16p(&reg);
+	tmp = indx | PHY_WRITE | PHY_GO;
+	i = 0;
+
+	set_registers(dev, PHYADD, sizeof(data), data);
+	set_registers(dev, PHYCNT, 1, &tmp);
+	do {
+		get_registers(dev, PHYCNT, 1, data);
+	} while((data[0] & PHY_GO) && (i++ < HZ));
+
+	if (i < HZ)
+		return 0;
+	else
+		return 1;
+}
+
+
+static inline void set_ethernet_addr(rtl8150_t *dev)
+{
+	u8	node_id[6];
+
+	get_registers(dev, IRD, sizeof(node_id), node_id);
+	memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));
+}
+
+
+static int rtl8150_reset(rtl8150_t *dev)
+{
+	u8	data=0x10;
+	int	i=HZ;
+
+	set_registers(dev, CR, 1, &data);
+	do {
+		get_registers(dev, CR, 1, &data);
+	} while ((data & 0x10) && --i);
+	
+	return (i > 0) ? 0 : -1;
+}
+
+
+static int alloc_all_urbs(rtl8150_t *dev)
+{
+	dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->rx_urb)
+		return 0;
+	dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->tx_urb) {
+		usb_free_urb(dev->rx_urb);
+		return 0;
+	}
+	dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->intr_urb) {
+		usb_free_urb(dev->rx_urb);
+		usb_free_urb(dev->tx_urb);
+		return 0;
+	}
+	dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->intr_urb) {
+		usb_free_urb(dev->rx_urb);
+		usb_free_urb(dev->tx_urb);
+		usb_free_urb(dev->intr_urb);
+		return 0;
+	}
+
+	return 1;
+}
+
+
+static void free_all_urbs(rtl8150_t *dev)
+{
+	usb_free_urb(dev->rx_urb);
+	usb_free_urb(dev->tx_urb);
+	usb_free_urb(dev->intr_urb);
+	usb_free_urb(dev->ctrl_urb);
+}
+
+
+static void unlink_all_urbs(rtl8150_t *dev)
+{
+	usb_unlink_urb(dev->rx_urb);
+	usb_unlink_urb(dev->tx_urb);
+	usb_unlink_urb(dev->intr_urb);
+	usb_unlink_urb(dev->ctrl_urb);
+}
+
+
+static void read_bulk_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+	unsigned	pkt_len, res;
+	struct sk_buff	*skb;
+	struct net_device *netdev;
+	u16		rx_stat;
+
+	dev = urb->context;
+	if (!dev) {
+		warn("!dev");
+		return;
+	}
+	netdev = dev->netdev;
+	if (!netif_device_present(netdev)) {
+		warn("netdev is not present");
+		return;
+	}
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ENOENT:
+		return;
+	case -ETIMEDOUT:
+		warn("reset needed may be?..");
+		goto goon;
+	default:
+		warn("Rx status %d", urb->status);
+		goto goon;
+	}
+
+	res = urb->actual_length;
+	rx_stat = le16_to_cpu(*(short*)(dev->rx_buff + res - 4));
+	pkt_len = res - 4;
+
+	if (!(skb = dev_alloc_skb(pkt_len + 2))) 
+		goto goon;
+	skb->dev = netdev;
+	skb_reserve(skb, 2);
+	eth_copy_and_sum(skb, dev->rx_buff, pkt_len, 0);
+	skb_put(skb, pkt_len);
+	skb->protocol = eth_type_trans(skb, netdev);
+	netif_rx(skb);
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += pkt_len;
+goon:
+	FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1),
+	              dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);
+	if ((res=usb_submit_urb(dev->rx_urb, GFP_ATOMIC)))
+		warn("%s: Rx urb submission failed %d", netdev->name, res);
+}
+
+
+static void write_bulk_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+
+	dev = urb->context;
+	if (!dev)
+		return;
+	if (!netif_device_present(dev->netdev))
+		return;
+	if (urb->status)
+		info("%s: Tx status %d", dev->netdev->name, urb->status);
+	dev->netdev->trans_start = jiffies;
+	netif_wake_queue(dev->netdev);
+}
+
+
+void intr_callback(struct urb *urb)
+{
+	rtl8150_t	*dev;
+
+	dev = urb->context;
+	if (!dev)
+		return;
+	switch (urb->status) {
+		case 0:
+			break;
+		case -ENOENT:
+			return;
+		default:
+			info("%s: intr status %d", dev->netdev->name,
+			     urb->status);
+	}
+}
+
+
+/*
+**
+**	network related part of the code
+**
+*/
+
+
+static int enable_net_traffic(rtl8150_t *dev)
+{
+	u8	cr, tcr, rcr, msr;
+
+	if (rtl8150_reset(dev)) {
+		warn("%s - device reset failed", __FUNCTION__);
+	}
+	dev->rx_creg = rcr = 0x9e;	/* bit7=1 attach Rx info at the end */
+	tcr = 0xd8;		/* bit0=1 no CRC at the end of the frame */
+	cr = 0x0c;
+	set_registers(dev, RCR, 1, &rcr);
+	set_registers(dev, TCR, 1, &tcr);
+	set_registers(dev, CR, 1, &cr);
+	get_registers(dev, MSR, 1, &msr);
+
+	return 0;
+}
+
+
+static void disable_net_traffic(rtl8150_t *dev)
+{
+	u8	cr;
+
+	get_registers(dev, CR, 1, &cr);
+	cr &= 0xf3;
+	set_registers(dev, CR, 1, &cr);
+}
+
+
+static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev)
+{
+	return &((rtl8150_t *)dev->priv)->stats;
+}
+
+
+static void rtl8150_tx_timeout(struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+
+	dev = netdev->priv;
+	if (!dev)
+		return;
+	warn("%s: Tx timeout.", netdev->name);
+	dev->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
+	usb_unlink_urb(dev->tx_urb);
+	dev->stats.tx_errors++;
+}
+
+
+static void rtl8150_set_multicast(struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+
+	dev = netdev->priv;
+	netif_stop_queue(netdev);
+	if (netdev->flags & IFF_PROMISC) {
+		dev->rx_creg |= 0x0001;
+		info("%s: promiscuous mode", netdev->name);
+	} else if ((netdev->mc_count > multicast_filter_limit) ||
+	           (netdev->flags & IFF_ALLMULTI)) {
+		dev->rx_creg &= 0xfffe;
+		dev->rx_creg |= 0x0002;
+		info("%s: allmulti set", netdev->name);
+	} else {
+		/* ~RX_MULTICAST, ~RX_PROMISCUOUS */
+		dev->rx_creg &= 0x00fc;
+	}
+	async_set_registers(dev, RCR, 2, &dev->rx_creg);
+	netif_wake_queue(netdev);
+}
+
+
+static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+	int		count, res;
+
+	netif_stop_queue(netdev);
+	dev = netdev->priv;
+	count = (skb->len < 60) ? 60 : skb->len;
+	count = (count & 0x3f) ? count : count + 1;
+	memcpy(dev->tx_buff, skb->data, skb->len);
+	FILL_BULK_URB(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev,2),
+		      dev->tx_buff, RTL8150_MAX_MTU, write_bulk_callback, dev);
+	dev->tx_urb->transfer_buffer_length = count;
+
+	if ((res = usb_submit_urb(dev->tx_urb, GFP_KERNEL))) {
+		warn("failed tx_urb %d\n", res);
+		dev->stats.tx_errors++;
+		netif_start_queue(netdev);
+	} else {
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += skb->len;
+		netdev->trans_start = jiffies;
+	}
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+
+static int rtl8150_open(struct net_device *netdev)
+{
+	rtl8150_t	*dev;
+	int		res;
+	
+	dev = netdev->priv;
+	if (dev == NULL) {
+		return -ENODEV;
+	}
+
+	down(&dev->sem);
+	FILL_BULK_URB(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev,1),
+			dev->rx_buff, RTL8150_MAX_MTU, read_bulk_callback, dev);
+	if ((res=usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
+		warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
+	FILL_INT_URB(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev,3),
+			dev->intr_buff, sizeof(dev->intr_buff), intr_callback,
+			dev, dev->intr_interval);
+	if ((res=usb_submit_urb(dev->intr_urb, GFP_KERNEL)))
+		warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
+	netif_start_queue(netdev);
+	enable_net_traffic(dev);
+	up(&dev->sem);
+
+	return res;
+}
+
+
+static int rtl8150_close(struct net_device *netdev)
+{
+	rtl8150_t *dev;
+	int res = 0;
+
+	dev = netdev->priv;
+	if (!dev)
+		return -ENODEV;
+
+	down(&dev->sem);
+	if (!test_bit(RTL8150_UNPLUG, &dev->flags))
+		disable_net_traffic(dev);
+	unlink_all_urbs(dev);
+	netif_stop_queue(netdev);
+	up(&dev->sem);
+
+
+	return res;
+}
+
+
+static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr)
+{
+	rtl8150_t	*dev;
+	int		cmd;
+	char		tmp[128];
+
+	dev = netdev->priv;
+	if (get_user(cmd, (int *)uaddr))
+		return -EFAULT;
+
+	switch (cmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+		
+		strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
+		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+		sprintf(tmp, "usb%d:%d", dev->udev->bus->busnum,
+		        dev->udev->devnum);
+		strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
+		if (copy_to_user(uaddr, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd;
+		short   lpa, bmcr;
+
+		if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
+			return -EFAULT;
+		ecmd.supported = (SUPPORTED_10baseT_Half |
+		                  SUPPORTED_10baseT_Full |
+		                  SUPPORTED_100baseT_Half |
+		                  SUPPORTED_100baseT_Full |
+		                  SUPPORTED_Autoneg |
+		                  SUPPORTED_TP |
+		                  SUPPORTED_MII);
+		ecmd.port = PORT_TP;
+		ecmd.transceiver = XCVR_INTERNAL;
+		ecmd.phy_address = dev->phy;
+		get_registers(dev, BMCR, 2, &bmcr);
+		get_registers(dev, ANLP, 2, &lpa);
+		if (bmcr & BMCR_ANENABLE) {
+			ecmd.autoneg = AUTONEG_ENABLE;
+			ecmd.speed = (lpa & (LPA_100HALF | LPA_100FULL)) ?
+			             SPEED_100 : SPEED_10;
+			if (ecmd.speed == SPEED_100)
+				ecmd.duplex = (lpa & LPA_100FULL) ?
+				              DUPLEX_FULL : DUPLEX_HALF;
+			else
+				ecmd.duplex = (lpa & LPA_10FULL) ?
+				              DUPLEX_FULL : DUPLEX_HALF;
+		} else {
+			ecmd.autoneg = AUTONEG_DISABLE;
+			ecmd.speed = (bmcr & BMCR_SPEED100) ?
+			             SPEED_100 : SPEED_10;
+			ecmd.duplex = (bmcr & BMCR_FULLDPLX) ?
+			              DUPLEX_FULL : DUPLEX_HALF;
+		}
+		if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	case ETHTOOL_SSET:
+		return -ENOTSUPP;
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+
+		edata.data = netif_carrier_ok(netdev);
+		if (copy_to_user(uaddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int rtl8150_ioctl (struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+	rtl8150_t *dev;
+	u16	*data;
+	int	res;
+
+	dev = netdev->priv;
+	data = (u16 *)&rq->ifr_data;
+	res = 0;
+
+	down(&dev->sem);
+	switch (cmd) {
+	case SIOCETHTOOL:
+		res = rtl8150_ethtool_ioctl(netdev, rq->ifr_data);
+		break;
+	case SIOCDEVPRIVATE:
+		data[0] = dev->phy;
+	case SIOCDEVPRIVATE+1:
+		read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]);
+		break;
+	case SIOCDEVPRIVATE+2:
+		if (!capable(CAP_NET_ADMIN)) {
+			up(&dev->sem);
+			return -EPERM;
+		}
+		write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]);
+		break;
+	default:
+		res = -EOPNOTSUPP;
+	}
+	up(&dev->sem);
+	return res;
+}
+
+
+static void * rtl8150_probe(struct usb_device *udev, unsigned int ifnum,
+			    const struct usb_device_id *id)
+{
+	rtl8150_t *dev;
+	struct net_device *netdev;
+
+	udev->config[0].bConfigurationValue = 1;
+	if (usb_set_configuration(udev, udev->config[0].bConfigurationValue)) {
+		err("usb_set_configuration() failed");
+		return NULL;
+	}
+	if ((udev->descriptor.idVendor != VENDOR_ID_REALTEK) ||
+	    (udev->descriptor.idProduct != PRODUCT_ID_RTL8150)) {
+	    	err("Not the one we are interested about");
+		return NULL;
+	}
+	dev = kmalloc(sizeof(rtl8150_t), GFP_KERNEL);
+	if (!dev) {
+		err ("Out of memory");
+		goto exit;
+	} else
+		memset(dev, 0, sizeof(rtl8150_t));
+
+	netdev = init_etherdev(NULL, 0);
+	if (!netdev) {
+		kfree(dev);
+		err("Oh boy, out of memory again?!?");
+		dev = NULL;
+		goto exit;
+	}
+		
+	init_MUTEX(&dev->sem);
+	dev->udev = udev;
+	dev->netdev = netdev;
+	SET_MODULE_OWNER(netdev);
+	netdev->priv = dev;
+	netdev->open = rtl8150_open;
+	netdev->stop = rtl8150_close;
+	netdev->do_ioctl = rtl8150_ioctl;
+	netdev->watchdog_timeo = RTL8150_TX_TIMEOUT;
+	netdev->tx_timeout = rtl8150_tx_timeout;
+	netdev->hard_start_xmit = rtl8150_start_xmit;
+	netdev->set_multicast_list = rtl8150_set_multicast;
+	netdev->get_stats = rtl8150_netdev_stats;
+	netdev->mtu = RTL8150_MTU;
+	dev->intr_interval = 100;	/* 100ms */
+
+	if (rtl8150_reset(dev) || !alloc_all_urbs(dev)) {
+		err("couldn't reset the device");
+		free_all_urbs(dev);
+		unregister_netdev(dev->netdev);
+		kfree(netdev);
+		kfree(dev);
+		dev = NULL;
+		goto exit;
+	}
+
+	set_ethernet_addr(dev);
+	info("%s: rtl8150 is detected", netdev->name);
+exit:
+	return dev;
+}
+
+
+static void rtl8150_disconnect(struct usb_device *udev, void *ptr)
+{
+	rtl8150_t *dev;
+
+	dev = ptr;
+	set_bit(RTL8150_UNPLUG, &dev->flags);
+	unregister_netdev(dev->netdev);
+	unlink_all_urbs(dev);
+	free_all_urbs(dev);
+	kfree(dev->netdev);
+	kfree(dev);
+	dev->netdev = NULL;
+	dev = NULL;
+}
+
+
+
+static int __init usb_rtl8150_init(void)
+{
+	info(DRIVER_DESC " " DRIVER_VERSION);
+	return usb_register(&rtl8150_driver);
+}
+
+
+static void __exit usb_rtl8150_exit(void)
+{
+	usb_deregister(&rtl8150_driver);
+}
+
+
+module_init(usb_rtl8150_init);
+module_exit(usb_rtl8150_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/net/usbnet.c	Sun Apr 14 12:16:54 2002
@@ -0,0 +1,2073 @@
+/*
+ * USB Host-to-Host Links
+ * Copyright (C) 2000-2002 by David Brownell <dbrownell@users.sourceforge.net>
+ */
+
+/*
+ * This is used for "USB networking", connecting USB hosts as peers.
+ *
+ * It can be used with USB "network cables", for IP-over-USB communications;
+ * Ethernet speeds without the Ethernet.  USB devices (including some PDAs)
+ * can support such links directly, replacing device-specific protocols
+ * with Internet standard ones.
+ *
+ * The links can be bridged using the Ethernet bridging (net/bridge)
+ * support as appropriate.  Devices currently supported include:
+ *
+ *	- AnchorChip 2720
+ *	- Belkin, eTEK (interops with Win32 drivers)
+ *	- GeneSys GL620USB-A
+ *	- "Linux Devices" (like iPaq and similar SA-1100 based PDAs)
+ *	- NetChip 1080 (interoperates with NetChip Win32 drivers)
+ *	- Prolific PL-2301/2302 (replaces "plusb" driver)
+ *
+ * USB devices can implement their side of this protocol at the cost
+ * of two bulk endpoints; it's not restricted to "cable" applications.
+ * See the LINUXDEV support.
+ *
+ * 
+ * TODO:
+ *
+ * This needs to be retested for bulk queuing problems ... earlier versions
+ * seemed to find different types of problems in each HCD.  Once they're fixed,
+ * re-enable queues to get higher bandwidth utilization (without needing
+ * to tweak MTU for larger packets).
+ *
+ * Add support for more "network cable" chips; interop with their Win32
+ * drivers may be a good thing.  Test the AnchorChip 2720 support..
+ * Figure out the initialization protocol used by the Prolific chips,
+ * for better robustness ... there's some powerup/reset handshake that's
+ * needed when only one end reboots.
+ *
+ * Use interrupt on PL230x to detect peer connect/disconnect, and call
+ * netif_carrier_{on,off} (?) appropriately.  For Net1080, detect peer
+ * connect/disconnect with async control messages.
+ *
+ * Find some way to report "peer connected" network hotplug events; it'll
+ * likely mean updating the networking layer.  (This has been discussed
+ * on the netdev list...)
+ *
+ * Craft smarter hotplug policy scripts ... ones that know how to arrange
+ * bridging with "brctl", and can handle static and dynamic ("pump") setups.
+ * Use those "peer connected" events.
+ *
+ *
+ * CHANGELOG:
+ *
+ * 13-sep-2000	experimental, new
+ * 10-oct-2000	usb_device_id table created. 
+ * 28-oct-2000	misc fixes; mostly, discard more TTL-mangled rx packets.
+ * 01-nov-2000	usb_device_id table and probing api update by
+ *		Adam J. Richter <adam@yggdrasil.com>.
+ * 18-dec-2000	(db) tx watchdog, "net1080" renaming to "usbnet", device_info
+ *		and prolific support, isolate net1080-specific bits, cleanup.
+ *		fix unlink_urbs oops in D3 PM resume code path.
+ *
+ * 02-feb-2001	(db) fix tx skb sharing, packet length, match_flags, ...
+ * 08-feb-2001	stubbed in "linuxdev", maybe the SA-1100 folk can use it;
+ *		AnchorChips 2720 support (from spec) for testing;
+ *		fix bit-ordering problem with ethernet multicast addr
+ * 19-feb-2001  Support for clearing halt conditions. SA1100 UDC support
+ *		updates. Oleg Drokin (green@iXcelerator.com)
+ * 25-mar-2001	More SA-1100 updates, including workaround for ip problem
+ *		expecting cleared skb->cb and framing change to match latest
+ *		handhelds.org version (Oleg).  Enable device IDs from the
+ *		Win32 Belkin driver; other cleanups (db).
+ * 16-jul-2001	Bugfixes for uhci oops-on-unplug, Belkin support, various
+ *		cleanups for problems not yet seen in the field. (db)
+ * 17-oct-2001	Handle "Advance USBNET" product, like Belkin/eTEK devices,
+ *		from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>;
+ *		rx unlinks somehow weren't async; minor cleanup.
+ * 03-nov-2001	Merged GeneSys driver; original code from Jiun-Jie Huang
+ *		<huangjj@genesyslogic.com.tw>, updated by Stanislav Brabec
+ *		<utx@penguin.cz>.  Made framing options (NetChip/GeneSys)
+ *		tie mostly to (sub)driver info.  Workaround some PL-2302
+ *		chips that seem to reject SET_INTERFACE requests.
+ *
+ * 06-apr-2002	Added ethtool support, based on a patch from Brad Hards.
+ *		Level of diagnostics is more configurable; they use device
+ *		location (usb_device->devpath) instead of address (2.5).
+ *		For tx_fixup, memflags can't be NOIO.
+ *
+ *-------------------------------------------------------------------------*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/random.h>
+#include <linux/ethtool.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+
+// #define	DEBUG			// error path messages, extra info
+// #define	VERBOSE			// more; success messages
+// #define	REALLY_QUEUE
+
+#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
+#   define DEBUG
+#endif
+#include <linux/usb.h>
+
+
+#define	CONFIG_USB_AN2720
+#define	CONFIG_USB_BELKIN
+#define	CONFIG_USB_GENESYS
+#define	CONFIG_USB_LINUXDEV
+#define	CONFIG_USB_NET1080
+#define	CONFIG_USB_PL2301
+
+
+#define DRIVER_VERSION		"06-Apr-2002"
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Nineteen USB 1.1 max size bulk transactions per frame (ms), max.
+ * Several dozen bytes of IPv4 data can fit in two such transactions.
+ * One maximum size Ethernet packet takes twenty four of them.
+ */
+#ifdef REALLY_QUEUE
+#define	RX_QLEN		4
+#define	TX_QLEN		4
+#else
+#define	RX_QLEN		1
+#define	TX_QLEN		1
+#endif
+
+// packets are always ethernet inside
+// ... except they can be bigger (limit of 64K with NetChip framing)
+#define MIN_PACKET	sizeof(struct ethhdr)
+#define MAX_PACKET	32768
+
+// reawaken network queue this soon after stopping; else watchdog barks
+#define TX_TIMEOUT_JIFFIES	(5*HZ)
+
+// for vendor-specific control operations
+#define	CONTROL_TIMEOUT_MS	(500)			/* msec */
+#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
+
+// between wakeups
+#define UNLINK_TIMEOUT_JIFFIES ((3  /*ms*/ * HZ)/1000)
+
+/*-------------------------------------------------------------------------*/
+
+// list of all devices we manage
+static DECLARE_MUTEX (usbnet_mutex);
+static LIST_HEAD (usbnet_list);
+
+// randomly generated ethernet address
+static u8	node_id [ETH_ALEN];
+
+// state we keep for each device we handle
+struct usbnet {
+	// housekeeping
+	struct usb_device	*udev;
+	struct driver_info	*driver_info;
+	struct semaphore	mutex;
+	struct list_head	dev_list;
+	wait_queue_head_t	*wait;
+
+	// protocol/interface state
+	struct net_device	net;
+	struct net_device_stats	stats;
+	int			msg_level;
+
+#ifdef CONFIG_USB_NET1080
+	u16			packet_id;
+#endif
+
+	// various kinds of pending driver work
+	struct sk_buff_head	rxq;
+	struct sk_buff_head	txq;
+	struct sk_buff_head	done;
+	struct tasklet_struct	bh;
+	struct tq_struct	ctrl_task;
+};
+
+// device-specific info used by the driver
+struct driver_info {
+	char		*description;
+
+	int		flags;
+#define FLAG_FRAMING_NC	0x0001		/* guard against device dropouts */ 
+#define FLAG_FRAMING_GL	0x0002		/* genelink batches packets */
+#define FLAG_NO_SETINT	0x0010		/* device can't set_interface() */
+
+	/* reset device ... can sleep */
+	int	(*reset)(struct usbnet *);
+
+	/* see if peer is connected ... can sleep */
+	int	(*check_connect)(struct usbnet *);
+
+	/* fixup rx packet (strip framing) */
+	int	(*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
+
+	/* fixup tx packet (add framing) */
+	struct sk_buff	*(*tx_fixup)(struct usbnet *dev,
+				struct sk_buff *skb, int flags);
+
+	// FIXME -- also an interrupt mechanism
+	// useful for at least PL2301/2302 and GL620USB-A
+
+	/* framework currently "knows" bulk EPs talk packets */
+	int		in;		/* rx endpoint */
+	int		out;		/* tx endpoint */
+	int		epsize;
+};
+
+#define EP_SIZE(usbnet)	((usbnet)->driver_info->epsize)
+
+// we record the state for each of our queued skbs
+enum skb_state {
+	illegal = 0,
+	tx_start, tx_done,
+	rx_start, rx_done, rx_cleanup
+};
+
+struct skb_data {	// skb->cb is one of these
+	struct urb		*urb;
+	struct usbnet		*dev;
+	enum skb_state		state;
+	size_t			length;
+};
+
+static const char driver_name [] = "usbnet";
+
+/* use ethtool to change the level for any given device */
+static int msg_level = 1;
+MODULE_PARM (msg_level, "i");
+MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
+
+
+#define	mutex_lock(x)	down(x)
+#define	mutex_unlock(x)	up(x)
+
+#define	RUN_CONTEXT (in_irq () ? "in_irq" \
+			: (in_interrupt () ? "in_interrupt" : "can sleep"))
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+#define devdbg(usbnet, fmt, arg...) \
+	printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
+#else
+#define devdbg(usbnet, fmt, arg...) do {} while(0)
+#endif
+
+#define devinfo(usbnet, fmt, arg...) \
+	do { if ((usbnet)->msg_level >= 1) \
+	printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg); \
+	} while (0)
+
+
+#ifdef	CONFIG_USB_AN2720
+
+/*-------------------------------------------------------------------------
+ *
+ * AnchorChips 2720 driver ... http://www.cypress.com
+ *
+ * This doesn't seem to have a way to detect whether the peer is
+ * connected, or need any reset handshaking.  It's got pretty big
+ * internal buffers (handles most of a frame's worth of data).
+ * Chip data sheets don't describe any vendor control messages.
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info	an2720_info = {
+	description:	"AnchorChips/Cypress 2720",
+	// no reset available!
+	// no check_connect available!
+
+	in: 2, out: 2,		// direction distinguishes these
+	epsize:	64,
+};
+
+#endif	/* CONFIG_USB_AN2720 */
+
+
+
+#ifdef	CONFIG_USB_BELKIN
+
+/*-------------------------------------------------------------------------
+ *
+ * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller
+ *
+ * ... also two eTEK designs, including one sold as "Advance USBNET"
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info	belkin_info = {
+	description:	"Belkin, eTEK, or compatible",
+
+	in: 1, out: 1,		// direction distinguishes these
+	epsize:	64,
+};
+
+#endif	/* CONFIG_USB_BELKIN */
+
+
+
+#ifdef CONFIG_USB_GENESYS
+
+/*-------------------------------------------------------------------------
+ *
+ * GeneSys GL620USB-A (www.genesyslogic.com.tw)
+ *
+ * ... should partially interop with the Win32 driver for this hardware
+ * The GeneSys docs imply there's some NDIS issue motivating this framing.
+ *
+ *-------------------------------------------------------------------------*/
+
+// control msg write command
+#define GENELINK_CONNECT_WRITE			0xF0
+// interrupt pipe index
+#define GENELINK_INTERRUPT_PIPE			0x03
+// interrupt read buffer size
+#define INTERRUPT_BUFSIZE			0x08
+// interrupt pipe interval value
+#define GENELINK_INTERRUPT_INTERVAL		0x10
+// max transmit packet number per transmit
+#define GL_MAX_TRANSMIT_PACKETS			32
+// max packet length
+#define GL_MAX_PACKET_LEN			1514
+// max receive buffer size 
+#define GL_RCV_BUF_SIZE		\
+	(((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
+
+struct gl_packet {
+	u32		packet_length;
+	char		packet_data [1];
+};
+
+struct gl_header {
+	u32			packet_count;
+	struct gl_packet	packets;
+};
+
+#ifdef	GENLINK_ACK
+
+// FIXME:  this code is incomplete, not debugged; it doesn't
+// handle interrupts correctly.  interrupts should be generic
+// code like all other device I/O, anyway.
+
+struct gl_priv { 
+	struct urb	*irq_urb;
+	char		irq_buf [INTERRUPT_BUFSIZE];
+};
+
+static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
+{
+	int retval;
+
+	retval = usb_control_msg (dev->udev,
+		      usb_sndctrlpipe (dev->udev, 0),
+		      request,
+		      USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		      value, 
+		      0,			// index
+		      0,			// data buffer
+		      0,			// size
+		      CONTROL_TIMEOUT_JIFFIES);
+	return retval;
+}
+
+static void gl_interrupt_complete (struct urb *urb)
+{
+	int status = urb->status;
+	
+	if (status)
+		dbg ("gl_interrupt_complete fail - %X", status);
+	else
+		dbg ("gl_interrupt_complete success...");
+}
+
+static int gl_interrupt_read (struct usbnet *dev)
+{
+	struct gl_priv	*priv = dev->priv_data;
+	int		retval;
+
+	// issue usb interrupt read
+	if (priv && priv->irq_urb) {
+		// submit urb
+		if ((retval = usb_submit_urb (priv->irq_urb, GFP_KERNEL)) != 0)
+			dbg ("gl_interrupt_read: submit fail - %X...", retval);
+		else
+			dbg ("gl_interrupt_read: submit success...");
+	}
+
+	return 0;
+}
+
+// check whether another side is connected
+static int genelink_check_connect (struct usbnet *dev)
+{
+	int			retval;
+
+	dbg ("genelink_check_connect...");
+
+	// detect whether another side is connected
+	if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
+		dbg ("%s: genelink_check_connect write fail - %X",
+			dev->net.name, retval);
+		return retval;
+	}
+
+	// usb interrupt read to ack another side 
+	if ((retval = gl_interrupt_read (dev)) != 0) {
+		dbg ("%s: genelink_check_connect read fail - %X",
+			dev->net.name, retval);
+		return retval;
+	}
+
+	dbg ("%s: genelink_check_connect read success", dev->net.name);
+	return 0;
+}
+
+// allocate and initialize the private data for genelink
+static int genelink_init (struct usbnet *dev)
+{
+	struct gl_priv *priv;
+
+	// allocate the private data structure
+	if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
+		dbg ("%s: cannot allocate private data per device",
+			dev->net.name);
+		return -ENOMEM;
+	}
+
+	// allocate irq urb
+	if ((priv->irq_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
+		dbg ("%s: cannot allocate private irq urb per device",
+			dev->net.name);
+		kfree (priv);
+		return -ENOMEM;
+	}
+
+	// fill irq urb
+	FILL_INT_URB (priv->irq_urb, dev->udev,
+		usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE),
+		priv->irq_buf, INTERRUPT_BUFSIZE,
+		gl_interrupt_complete, 0,
+		GENELINK_INTERRUPT_INTERVAL);
+
+	// set private data pointer
+	dev->priv_data = priv;
+
+	return 0;
+}
+
+// release the private data
+static int genelink_free (struct usbnet *dev)
+{
+	struct gl_priv	*priv = dev->priv_data;
+
+	if (!priv) 
+		return 0;
+
+// FIXME:  can't cancel here; it's synchronous, and
+// should have happened earlier in any case (interrupt
+// handling needs to be generic)
+
+	// cancel irq urb first
+	usb_unlink_urb (priv->irq_urb);
+
+	// free irq urb
+	usb_free_urb (priv->irq_urb);
+
+	// free the private data structure
+	kfree (priv);
+
+	return 0;
+}
+
+#else
+
+static int genelink_check_connect (struct usbnet *dev)
+{
+	dbg ("%s: assuming peer is connected", dev->net.name);
+	return 0;
+}
+
+#endif
+
+// reset the device status
+static int genelink_reset (struct usbnet *dev)
+{
+	// we don't need to reset, just return 0
+	return 0;
+}
+
+static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
+{
+	struct gl_header	*header;
+	struct gl_packet	*packet;
+	struct sk_buff		*gl_skb;
+	int			status;
+	u32			size;
+
+	header = (struct gl_header *) skb->data;
+
+	// get the packet count of the received skb
+	le32_to_cpus (&header->packet_count);
+	if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
+			|| (header->packet_count < 0)) {
+		dbg ("genelink: illegal received packet count %d",
+			header->packet_count);
+		return 0;
+	}
+
+	// set the current packet pointer to the first packet
+	packet = &header->packets;
+
+	// decrement the length for the packet count size 4 bytes
+	skb_pull (skb, 4);
+
+	while (header->packet_count > 1) {
+		// get the packet length
+		size = packet->packet_length;
+
+		// this may be a broken packet
+		if (size > GL_MAX_PACKET_LEN) {
+			dbg ("genelink: illegal rx length %d", size);
+			return 0;
+		}
+
+		// allocate the skb for the individual packet
+		gl_skb = alloc_skb (size, GFP_ATOMIC);
+		if (gl_skb == 0)
+			return 0;
+
+		// copy the packet data to the new skb
+		memcpy (gl_skb->data, packet->packet_data, size);
+
+		// set skb data size
+		gl_skb->len = size;
+		gl_skb->dev = &dev->net;
+
+		// determine the packet's protocol ID
+		gl_skb->protocol = eth_type_trans (gl_skb, &dev->net);
+
+		// update the status
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += size;
+
+		// notify os of the received packet
+		status = netif_rx (gl_skb);
+
+		// advance to the next packet
+		packet = (struct gl_packet *)
+			&packet->packet_data [size];
+		header->packet_count--;
+
+		// shift the data pointer to the next gl_packet
+		skb_pull (skb, size + 4);
+	}
+
+	// skip the packet length field 4 bytes
+	skb_pull (skb, 4);
+
+	if (skb->len > GL_MAX_PACKET_LEN) {
+		dbg ("genelink: illegal rx length %d", skb->len);
+		return 0;
+	}
+	return 1;
+}
+
+static struct sk_buff *
+genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
+{
+	int 	padlen;
+	int	length = skb->len;
+	int	headroom = skb_headroom (skb);
+	int	tailroom = skb_tailroom (skb);
+	u32	*packet_count;
+	u32	*packet_len;
+
+	// FIXME:  magic numbers, bleech
+	padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
+
+	if ((!skb_cloned (skb))
+			&& ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
+		if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
+			skb->data = memmove (skb->head + (4 + 4*1),
+					     skb->data, skb->len);
+			skb->tail = skb->data + skb->len;
+		}
+	} else {
+		struct sk_buff	*skb2;
+		skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags);
+		dev_kfree_skb_any (skb);
+		skb = skb2;
+	}
+
+	// attach the packet count to the header
+	packet_count = (u32 *) skb_push (skb, (4 + 4*1));
+	packet_len = packet_count + 1;
+
+	// FIXME little endian?
+	*packet_count = 1;
+	*packet_len = length;
+
+	// add padding byte
+	if ((skb->len % EP_SIZE (dev)) == 0)
+		skb_put (skb, 1);
+
+	return skb;
+}
+
+static const struct driver_info	genelink_info = {
+	description:	"Genesys GeneLink",
+	flags:		FLAG_FRAMING_GL | FLAG_NO_SETINT,
+	reset:		genelink_reset,
+	check_connect:	genelink_check_connect,
+	rx_fixup:	genelink_rx_fixup,
+	tx_fixup:	genelink_tx_fixup,
+
+	in: 1, out: 2,
+	epsize:	64,
+};
+
+#endif /* CONFIG_USB_GENESYS */
+
+
+
+#ifdef	CONFIG_USB_LINUXDEV
+
+/*-------------------------------------------------------------------------
+ *
+ * This could talk to a device that uses Linux, such as a PDA or
+ * an embedded system, or in fact to any "smart" device using this
+ * particular mapping of USB and Ethernet.
+ *
+ * Such a Linux host would need a "USB Device Controller" hardware
+ * (not "USB Host Controller"), and a network driver talking to that
+ * hardware.
+ *
+ * One example is Intel's SA-1100 chip, which integrates basic USB
+ * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA.
+ *
+ *-------------------------------------------------------------------------*/
+
+
+static const struct driver_info	linuxdev_info = {
+	description:	"Linux Device",
+	// no reset defined (yet?)
+	// no check_connect needed!
+	in: 2, out: 1,
+	epsize:	64,
+};
+
+#endif	/* CONFIG_USB_LINUXDEV */
+
+
+
+#ifdef	CONFIG_USB_NET1080
+
+/*-------------------------------------------------------------------------
+ *
+ * Netchip 1080 driver ... http://www.netchip.com
+ * Used in LapLink cables
+ *
+ *-------------------------------------------------------------------------*/
+
+/*
+ * NetChip framing of ethernet packets, supporting additional error
+ * checks for links that may drop bulk packets from inside messages.
+ * Odd USB length == always short read for last usb packet.
+ *	- nc_header
+ *	- Ethernet header (14 bytes)
+ *	- payload
+ *	- (optional padding byte, if needed so length becomes odd)
+ *	- nc_trailer
+ *
+ * This framing is to be avoided for non-NetChip devices.
+ */
+
+struct nc_header {		// packed:
+	u16	hdr_len;		// sizeof nc_header (LE, all)
+	u16	packet_len;		// payload size (including ethhdr)
+	u16	packet_id;		// detects dropped packets
+#define MIN_HEADER	6
+
+	// all else is optional, and must start with:
+	// u16	vendorId;		// from usb-if
+	// u16	productId;
+} __attribute__((__packed__));
+
+#define	PAD_BYTE	((unsigned char)0xAC)
+
+struct nc_trailer {
+	u16	packet_id;
+} __attribute__((__packed__));
+
+// packets may use FLAG_FRAMING_NC and optional pad
+#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
+				+ sizeof (struct ethhdr) \
+				+ (mtu) \
+				+ 1 \
+				+ sizeof (struct nc_trailer))
+
+#define MIN_FRAMED	FRAMED_SIZE(0)
+
+
+/*
+ * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
+ * before the hardware drops it.  If that's done, the driver will need to
+ * frame network packets to guard against the dropped USB packets.  The win32
+ * driver sets this for both sides of the link.
+ */
+#define	NC_READ_TTL_MS	((u8)255)	// ms
+
+/*
+ * We ignore most registers and EEPROM contents.
+ */
+#define	REG_USBCTL	((u8)0x04)
+#define REG_TTL		((u8)0x10)
+#define REG_STATUS	((u8)0x11)
+
+/*
+ * Vendor specific requests to read/write data
+ */
+#define	REQUEST_REGISTER	((u8)0x10)
+#define	REQUEST_EEPROM		((u8)0x11)
+
+static int
+nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
+{
+	int status = usb_control_msg (dev->udev,
+		usb_rcvctrlpipe (dev->udev, 0),
+		req,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		0, regnum,
+		retval_ptr, sizeof *retval_ptr,
+		CONTROL_TIMEOUT_JIFFIES);
+	if (status > 0)
+		status = 0;
+	if (!status)
+		le16_to_cpus (retval_ptr);
+	return status;
+}
+
+static inline int
+nc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr)
+{
+	return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr);
+}
+
+// no retval ... can become async, usable in_interrupt()
+static void
+nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value)
+{
+	usb_control_msg (dev->udev,
+		usb_sndctrlpipe (dev->udev, 0),
+		req,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		value, regnum,
+		0, 0,			// data is in setup packet
+		CONTROL_TIMEOUT_JIFFIES);
+}
+
+static inline void
+nc_register_write (struct usbnet *dev, u8 regnum, u16 value)
+{
+	nc_vendor_write (dev, REQUEST_REGISTER, regnum, value);
+}
+
+
+#if 0
+static void nc_dump_registers (struct usbnet *dev)
+{
+	u8	reg;
+	u16	*vp = kmalloc (sizeof (u16));
+
+	if (!vp) {
+		dbg ("no memory?");
+		return;
+	}
+
+	dbg ("%s registers:", dev->net.name);
+	for (reg = 0; reg < 0x20; reg++) {
+		int retval;
+
+		// reading some registers is trouble
+		if (reg >= 0x08 && reg <= 0xf)
+			continue;
+		if (reg >= 0x12 && reg <= 0x1e)
+			continue;
+
+		retval = nc_register_read (dev, reg, vp);
+		if (retval < 0)
+			dbg ("%s reg [0x%x] ==> error %d",
+				dev->net.name, reg, retval);
+		else
+			dbg ("%s reg [0x%x] = 0x%x",
+				dev->net.name, reg, *vp);
+	}
+	kfree (vp);
+}
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Control register
+ */
+
+#define	USBCTL_WRITABLE_MASK	0x1f0f
+// bits 15-13 reserved, r/o
+#define	USBCTL_ENABLE_LANG	(1 << 12)
+#define	USBCTL_ENABLE_MFGR	(1 << 11)
+#define	USBCTL_ENABLE_PROD	(1 << 10)
+#define	USBCTL_ENABLE_SERIAL	(1 << 9)
+#define	USBCTL_ENABLE_DEFAULTS	(1 << 8)
+// bits 7-4 reserved, r/o
+#define	USBCTL_FLUSH_OTHER	(1 << 3)
+#define	USBCTL_FLUSH_THIS	(1 << 2)
+#define	USBCTL_DISCONN_OTHER	(1 << 1)
+#define	USBCTL_DISCONN_THIS	(1 << 0)
+
+static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
+{
+#ifdef DEBUG
+	devdbg (dev, "net1080 %03d/%03d usbctl 0x%x:%s%s%s%s%s;"
+			" this%s%s;"
+			" other%s%s; r/o 0x%x",
+		dev->udev->bus->busnum, dev->udev->devnum,
+		usbctl,
+		(usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
+		(usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
+		(usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
+		(usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
+		(usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
+
+		(usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
+		(usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
+		(usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
+		(usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
+		usbctl & ~USBCTL_WRITABLE_MASK
+		);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Status register
+ */
+
+#define	STATUS_PORT_A		(1 << 15)
+
+#define	STATUS_CONN_OTHER	(1 << 14)
+#define	STATUS_SUSPEND_OTHER	(1 << 13)
+#define	STATUS_MAILBOX_OTHER	(1 << 12)
+#define	STATUS_PACKETS_OTHER(n)	(((n) >> 8) && 0x03)
+
+#define	STATUS_CONN_THIS	(1 << 6)
+#define	STATUS_SUSPEND_THIS	(1 << 5)
+#define	STATUS_MAILBOX_THIS	(1 << 4)
+#define	STATUS_PACKETS_THIS(n)	(((n) >> 0) && 0x03)
+
+#define	STATUS_UNSPEC_MASK	0x0c8c
+#define	STATUS_NOISE_MASK 	((u16)~(0x0303|STATUS_UNSPEC_MASK))
+
+
+static inline void nc_dump_status (struct usbnet *dev, u16 status)
+{
+#ifdef DEBUG
+	devdbg (dev, "net1080 %03d/%03d status 0x%x:"
+			" this (%c) PKT=%d%s%s%s;"
+			" other PKT=%d%s%s%s; unspec 0x%x",
+		dev->udev->bus->busnum, dev->udev->devnum,
+		status,
+
+		// XXX the packet counts don't seem right
+		// (1 at reset, not 0); maybe UNSPEC too
+
+		(status & STATUS_PORT_A) ? 'A' : 'B',
+		STATUS_PACKETS_THIS (status),
+		(status & STATUS_CONN_THIS) ? " CON" : "",
+		(status & STATUS_SUSPEND_THIS) ? " SUS" : "",
+		(status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
+
+		STATUS_PACKETS_OTHER (status),
+		(status & STATUS_CONN_OTHER) ? " CON" : "",
+		(status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
+		(status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
+
+		status & STATUS_UNSPEC_MASK
+		);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * TTL register
+ */
+
+#define	TTL_THIS(ttl)	(0x00ff & ttl)
+#define	TTL_OTHER(ttl)	(0x00ff & (ttl >> 8))
+#define MK_TTL(this,other)	((u16)(((other)<<8)|(0x00ff&(this))))
+
+static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
+{
+#ifdef DEBUG
+	devdbg (dev, "net1080 %03d/%03d ttl 0x%x this = %d, other = %d",
+		dev->udev->bus->busnum, dev->udev->devnum,
+		ttl,
+
+		TTL_THIS (ttl),
+		TTL_OTHER (ttl)
+		);
+#endif
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int net1080_reset (struct usbnet *dev)
+{
+	u16		usbctl, status, ttl;
+	u16		*vp = kmalloc (sizeof (u16), GFP_KERNEL);
+	int		retval;
+
+	if (!vp)
+		return -ENOMEM;
+
+	// nc_dump_registers (dev);
+
+	if ((retval = nc_register_read (dev, REG_STATUS, vp)) < 0) {
+		dbg ("can't read dev %d status: %d", dev->udev->devnum, retval);
+		goto done;
+	}
+	status = *vp;
+	// nc_dump_status (dev, status);
+
+	if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
+		dbg ("can't read USBCTL, %d", retval);
+		goto done;
+	}
+	usbctl = *vp;
+	// nc_dump_usbctl (dev, usbctl);
+
+	nc_register_write (dev, REG_USBCTL,
+			USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
+
+	if ((retval = nc_register_read (dev, REG_TTL, vp)) < 0) {
+		dbg ("can't read TTL, %d", retval);
+		goto done;
+	}
+	ttl = *vp;
+	// nc_dump_ttl (dev, ttl);
+
+	nc_register_write (dev, REG_TTL,
+			MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
+	dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS);
+
+	if (dev->msg_level >= 2)
+		devinfo (dev, "port %c, peer %sconnected",
+			(status & STATUS_PORT_A) ? 'A' : 'B',
+			(status & STATUS_CONN_OTHER) ? "" : "dis"
+			);
+	retval = 0;
+
+done:
+	kfree (vp);
+	return retval;
+}
+
+static int net1080_check_connect (struct usbnet *dev)
+{
+	int			retval;
+	u16			status;
+	u16			*vp = kmalloc (sizeof (u16), GFP_KERNEL);
+
+	if (!vp)
+		return -ENOMEM;
+	retval = nc_register_read (dev, REG_STATUS, vp);
+	status = *vp;
+	kfree (vp);
+	if (retval != 0) {
+		dbg ("%s net1080_check_conn read - %d", dev->net.name, retval);
+		return retval;
+	}
+	if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
+		return -ENOLINK;
+	return 0;
+}
+
+static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
+{
+	struct nc_header	*header;
+	struct nc_trailer	*trailer;
+
+	if (!(skb->len & 0x01)
+			|| MIN_FRAMED > skb->len
+			|| skb->len > FRAMED_SIZE (dev->net.mtu)) {
+		dev->stats.rx_frame_errors++;
+		dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
+			(int)MIN_FRAMED, (int)FRAMED_SIZE (dev->net.mtu),
+			dev->net.mtu);
+		return 0;
+	}
+
+	header = (struct nc_header *) skb->data;
+	le16_to_cpus (&header->hdr_len);
+	le16_to_cpus (&header->packet_len);
+	if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
+		dev->stats.rx_frame_errors++;
+		dbg ("packet too big, %d", header->packet_len);
+		return 0;
+	} else if (header->hdr_len < MIN_HEADER) {
+		dev->stats.rx_frame_errors++;
+		dbg ("header too short, %d", header->hdr_len);
+		return 0;
+	} else if (header->hdr_len > MIN_HEADER) {
+		// out of band data for us?
+		dbg ("header OOB, %d bytes",
+			header->hdr_len - MIN_HEADER);
+		// switch (vendor/product ids) { ... }
+	}
+	skb_pull (skb, header->hdr_len);
+
+	trailer = (struct nc_trailer *)
+		(skb->data + skb->len - sizeof *trailer);
+	skb_trim (skb, skb->len - sizeof *trailer);
+
+	if ((header->packet_len & 0x01) == 0) {
+		if (skb->data [header->packet_len] != PAD_BYTE) {
+			dev->stats.rx_frame_errors++;
+			dbg ("bad pad");
+			return 0;
+		}
+		skb_trim (skb, skb->len - 1);
+	}
+	if (skb->len != header->packet_len) {
+		dev->stats.rx_frame_errors++;
+		dbg ("bad packet len %d (expected %d)",
+			skb->len, header->packet_len);
+		return 0;
+	}
+	if (header->packet_id != get_unaligned (&trailer->packet_id)) {
+		dev->stats.rx_fifo_errors++;
+		dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
+			header->packet_id, trailer->packet_id);
+		return 0;
+	}
+#if 0
+	devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
+		header->packet_len, header->packet_id);
+#endif
+	return 1;
+}
+
+static struct sk_buff *
+net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
+{
+	int			padlen;
+	struct sk_buff		*skb2;
+
+	padlen = ((skb->len + sizeof (struct nc_header)
+			+ sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+	if (!skb_cloned (skb)) {
+		int	headroom = skb_headroom (skb);
+		int	tailroom = skb_tailroom (skb);
+
+		if ((padlen + sizeof (struct nc_trailer)) <= tailroom
+			    && sizeof (struct nc_header) <= headroom)
+			return skb;
+
+		if ((sizeof (struct nc_header) + padlen
+					+ sizeof (struct nc_trailer)) <
+				(headroom + tailroom)) {
+			skb->data = memmove (skb->head
+						+ sizeof (struct nc_header),
+					    skb->data, skb->len);
+			skb->tail = skb->data + skb->len;
+			return skb;
+		}
+	}
+	skb2 = skb_copy_expand (skb,
+				sizeof (struct nc_header),
+				sizeof (struct nc_trailer) + padlen,
+				flags);
+	dev_kfree_skb_any (skb);
+	return skb2;
+}
+
+static const struct driver_info	net1080_info = {
+	description:	"NetChip TurboCONNECT",
+	flags:		FLAG_FRAMING_NC,
+	reset:		net1080_reset,
+	check_connect:	net1080_check_connect,
+	rx_fixup:	net1080_rx_fixup,
+	tx_fixup:	net1080_tx_fixup,
+
+	in: 1, out: 1,		// direction distinguishes these
+	epsize:	64,
+};
+
+#endif /* CONFIG_USB_NET1080 */
+
+
+
+#ifdef CONFIG_USB_PL2301
+
+/*-------------------------------------------------------------------------
+ *
+ * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com
+ *
+ *-------------------------------------------------------------------------*/
+
+/*
+ * Bits 0-4 can be used for software handshaking; they're set from
+ * one end, cleared from the other, "read" with the interrupt byte.
+ */
+#define	PL_S_EN		(1<<7)		/* (feature only) suspend enable */
+/* reserved bit -- rx ready (6) ? */
+#define	PL_TX_READY	(1<<5)		/* (interrupt only) transmit ready */
+#define	PL_RESET_OUT	(1<<4)		/* reset output pipe */
+#define	PL_RESET_IN	(1<<3)		/* reset input pipe */
+#define	PL_TX_C		(1<<2)		/* transmission complete */
+#define	PL_TX_REQ	(1<<1)		/* transmission received */
+#define	PL_PEER_E	(1<<0)		/* peer exists */
+
+static inline int
+pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index)
+{
+	return usb_control_msg (dev->udev,
+		usb_rcvctrlpipe (dev->udev, 0),
+		req,
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		val, index,
+		0, 0,
+		CONTROL_TIMEOUT_JIFFIES);
+}
+
+static inline int
+pl_clear_QuickLink_features (struct usbnet *dev, int val)
+{
+	return pl_vendor_req (dev, 1, (u8) val, 0);
+}
+
+static inline int
+pl_set_QuickLink_features (struct usbnet *dev, int val)
+{
+	return pl_vendor_req (dev, 3, (u8) val, 0);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int pl_reset (struct usbnet *dev)
+{
+	return pl_set_QuickLink_features (dev,
+		PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
+}
+
+static int pl_check_connect (struct usbnet *dev)
+{
+	// FIXME test interrupt data PL_PEER_E bit
+	// plus, there's some handshake done by
+	// the prolific win32 driver... 
+	dbg ("%s: assuming peer is connected", dev->net.name);
+	return 0;
+}
+
+static const struct driver_info	prolific_info = {
+	description:	"Prolific PL-2301/PL-2302",
+	flags:		FLAG_NO_SETINT,
+		/* some PL-2302 versions seem to fail usb_set_interface() */
+	reset:		pl_reset,
+	check_connect:	pl_check_connect,
+
+	in: 3, out: 2,
+	epsize:	64,
+};
+
+#endif /* CONFIG_USB_PL2301 */
+
+
+
+/*-------------------------------------------------------------------------
+ *
+ * Network Device Driver (peer link to "Host Device", from USB host)
+ *
+ *-------------------------------------------------------------------------*/
+
+static int usbnet_change_mtu (struct net_device *net, int new_mtu)
+{
+	struct usbnet	*dev = (struct usbnet *) net->priv;
+
+	if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
+		return -EINVAL;
+#ifdef	CONFIG_USB_NET1080
+	if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {
+		if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
+			return -EINVAL;
+	}
+#endif
+#ifdef	CONFIG_USB_GENESYS
+	if (((dev->driver_info->flags) & FLAG_FRAMING_GL)
+			&& new_mtu > GL_MAX_PACKET_LEN)
+		return -EINVAL;
+#endif
+	// no second zero-length packet read wanted after mtu-sized packets
+	if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0)
+		return -EDOM;
+	net->mtu = new_mtu;
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct net_device_stats *usbnet_get_stats (struct net_device *net)
+{
+	return &((struct usbnet *) net->priv)->stats;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* urb completions are currently in_irq; avoid doing real work then. */
+
+static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
+{
+	struct sk_buff_head	*list = skb->list;
+	unsigned long		flags;
+
+	spin_lock_irqsave (&list->lock, flags);
+	__skb_unlink (skb, list);
+	spin_unlock (&list->lock);
+	spin_lock (&dev->done.lock);
+	__skb_queue_tail (&dev->done, skb);
+	if (dev->done.qlen == 1)
+		tasklet_schedule (&dev->bh);
+	spin_unlock_irqrestore (&dev->done.lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rx_complete (struct urb *urb);
+
+static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
+{
+	struct sk_buff		*skb;
+	struct skb_data		*entry;
+	int			retval = 0;
+	unsigned long		lockflags;
+	size_t			size;
+
+#ifdef CONFIG_USB_NET1080
+	if (dev->driver_info->flags & FLAG_FRAMING_NC)
+		size = FRAMED_SIZE (dev->net.mtu);
+	else
+#endif
+#ifdef CONFIG_USB_GENESYS
+	if (dev->driver_info->flags & FLAG_FRAMING_GL)
+		size = GL_RCV_BUF_SIZE;
+	else
+#endif
+		size = (sizeof (struct ethhdr) + dev->net.mtu);
+
+	if ((skb = alloc_skb (size, flags)) == 0) {
+		dbg ("no rx skb");
+		tasklet_schedule (&dev->bh);
+		usb_free_urb (urb);
+		return;
+	}
+
+	entry = (struct skb_data *) skb->cb;
+	entry->urb = urb;
+	entry->dev = dev;
+	entry->state = rx_start;
+	entry->length = 0;
+
+	FILL_BULK_URB (urb, dev->udev,
+		usb_rcvbulkpipe (dev->udev, dev->driver_info->in),
+		skb->data, size, rx_complete, skb);
+	urb->transfer_flags |= USB_ASYNC_UNLINK;
+#ifdef	REALLY_QUEUE
+	urb->transfer_flags |= USB_QUEUE_BULK;
+#endif
+#if 0
+	// Idle-but-posted reads with UHCI really chew up
+	// PCI bandwidth unless FSBR is disabled
+	urb->transfer_flags |= USB_NO_FSBR;
+#endif
+
+	spin_lock_irqsave (&dev->rxq.lock, lockflags);
+
+	if (netif_running (&dev->net)) {
+		if ((retval = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
+			dbg ("%s rx submit, %d", dev->net.name, retval);
+			tasklet_schedule (&dev->bh);
+		} else {
+			__skb_queue_tail (&dev->rxq, skb);
+		}
+	} else {
+		dbg ("rx: stopped");
+		retval = -ENOLINK;
+	}
+	spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
+	if (retval) {
+		dev_kfree_skb_any (skb);
+		usb_free_urb (urb);
+	}
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
+{
+	if (dev->driver_info->rx_fixup
+			&& !dev->driver_info->rx_fixup (dev, skb))
+		goto error;
+	// else network stack removes extra byte if we forced a short packet
+
+	if (skb->len) {
+		int	status;
+
+// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
+
+		skb->dev = &dev->net;
+		skb->protocol = eth_type_trans (skb, &dev->net);
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += skb->len;
+
+#ifdef	VERBOSE
+		devdbg (dev, "< rx, len %d, type 0x%x",
+			skb->len + sizeof (struct ethhdr), skb->protocol);
+#endif
+		memset (skb->cb, 0, sizeof (struct skb_data));
+		status = netif_rx (skb);
+		if (status != NET_RX_SUCCESS)
+			devdbg (dev, "netif_rx status %d", status);
+	} else {
+		dbg ("drop");
+error:
+		dev->stats.rx_errors++;
+		skb_queue_tail (&dev->done, skb);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void rx_complete (struct urb *urb)
+{
+	struct sk_buff		*skb = (struct sk_buff *) urb->context;
+	struct skb_data		*entry = (struct skb_data *) skb->cb;
+	struct usbnet		*dev = entry->dev;
+	int			urb_status = urb->status;
+
+	skb_put (skb, urb->actual_length);
+	entry->state = rx_done;
+	entry->urb = 0;
+
+	switch (urb_status) {
+	    // success
+	    case 0:
+		if (MIN_PACKET > skb->len || skb->len > MAX_PACKET) {
+			entry->state = rx_cleanup;
+			dev->stats.rx_errors++;
+			dev->stats.rx_length_errors++;
+			dbg ("rx length %d", skb->len);
+		}
+		break;
+
+	    // software-driven interface shutdown
+	    case -ECONNRESET:		// usb-ohci, usb-uhci
+	    case -ECONNABORTED:		// uhci ... for usb-uhci, INTR
+		dbg ("%s shutdown, code %d", dev->net.name, urb_status);
+		entry->state = rx_cleanup;
+		// do urb frees only in the tasklet
+		entry->urb = urb;
+		urb = 0;
+		break;
+
+	    // data overrun ... flush fifo?
+	    case -EOVERFLOW:
+		dev->stats.rx_over_errors++;
+		// FALLTHROUGH
+	    
+	    default:
+		// on unplug we'll get a burst of ETIMEDOUT/EILSEQ
+		// till the khubd gets and handles its interrupt.
+		entry->state = rx_cleanup;
+		dev->stats.rx_errors++;
+		dbg ("%s rx: status %d", dev->net.name, urb_status);
+		break;
+	}
+
+	defer_bh (dev, skb);
+
+	if (urb) {
+		if (netif_running (&dev->net)) {
+			rx_submit (dev, urb, GFP_ATOMIC);
+			return;
+		}
+	}
+#ifdef	VERBOSE
+	dbg ("no read resubmitted");
+#endif /* VERBOSE */
+}
+
+/*-------------------------------------------------------------------------*/
+
+// unlink pending rx/tx; completion handlers do all other cleanup
+
+static int unlink_urbs (struct sk_buff_head *q)
+{
+	unsigned long		flags;
+	struct sk_buff		*skb, *skbnext;
+	int			count = 0;
+
+	spin_lock_irqsave (&q->lock, flags);
+	for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) {
+		struct skb_data		*entry;
+		struct urb		*urb;
+		int			retval;
+
+		entry = (struct skb_data *) skb->cb;
+		urb = entry->urb;
+		skbnext = skb->next;
+
+		// during some PM-driven resume scenarios,
+		// these (async) unlinks complete immediately
+		retval = usb_unlink_urb (urb);
+		if (retval < 0)
+			dbg ("unlink urb err, %d", retval);
+		else
+			count++;
+	}
+	spin_unlock_irqrestore (&q->lock, flags);
+	return count;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+// precondition: never called in_interrupt
+
+static int usbnet_stop (struct net_device *net)
+{
+	struct usbnet		*dev = (struct usbnet *) net->priv;
+	int			temp;
+	DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
+	DECLARE_WAITQUEUE (wait, current);
+
+	mutex_lock (&dev->mutex);
+	netif_stop_queue (net);
+
+	if (dev->msg_level >= 2)
+		devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
+			dev->stats.rx_packets, dev->stats.tx_packets, 
+			dev->stats.rx_errors, dev->stats.tx_errors
+			);
+
+	// ensure there are no more active urbs
+	add_wait_queue (&unlink_wakeup, &wait);
+	dev->wait = &unlink_wakeup;
+	temp = unlink_urbs (&dev->txq) + unlink_urbs (&dev->rxq);
+
+	// maybe wait for deletions to finish.
+	while (skb_queue_len (&dev->rxq)
+			&& skb_queue_len (&dev->txq)
+			&& skb_queue_len (&dev->done)) {
+		set_current_state (TASK_UNINTERRUPTIBLE);
+		schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
+		dbg ("waited for %d urb completions", temp);
+	}
+	dev->wait = 0;
+	remove_wait_queue (&unlink_wakeup, &wait); 
+
+	mutex_unlock (&dev->mutex);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+// posts reads, and enables write queing
+
+// precondition: never called in_interrupt
+
+static int usbnet_open (struct net_device *net)
+{
+	struct usbnet		*dev = (struct usbnet *) net->priv;
+	int			retval = 0;
+	struct driver_info	*info = dev->driver_info;
+
+	mutex_lock (&dev->mutex);
+
+	// put into "known safe" state
+	if (info->reset && (retval = info->reset (dev)) < 0) {
+		devinfo (dev, "open reset fail (%d) usbnet bus%d%s, %s",
+			retval,
+			// FIXME busnum is unstable
+			dev->udev->bus->busnum, dev->udev->devpath,
+			info->description);
+		goto done;
+	}
+
+	// insist peer be connected
+	if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
+		devdbg (dev, "can't open; %d", retval);
+		goto done;
+	}
+
+	netif_start_queue (net);
+	if (dev->msg_level >= 2)
+		devinfo (dev, "open: enable queueing "
+				"(rx %d, tx %d) mtu %d %s framing",
+			RX_QLEN, TX_QLEN, dev->net.mtu,
+			(info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL))
+			    ? ((info->flags & FLAG_FRAMING_NC)
+				? "NetChip"
+				: "GeneSys")
+			    : "raw"
+			);
+
+	// delay posting reads until we're fully open
+	tasklet_schedule (&dev->bh);
+done:
+	mutex_unlock (&dev->mutex);
+	return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int usbnet_ethtool_ioctl (struct net_device *net, void *useraddr)
+{
+	struct usbnet	*dev = (struct usbnet *) net->priv;
+	u32		cmd;
+
+	if (get_user (cmd, (u32 *)useraddr))
+		return -EFAULT;
+	switch (cmd) {
+
+	case ETHTOOL_GDRVINFO: {	/* get driver info */
+		struct ethtool_drvinfo		info;
+
+		memset (&info, 0, sizeof info);
+		info.cmd = ETHTOOL_GDRVINFO;
+		strncpy (info.driver, driver_name, sizeof info.driver);
+		strncpy (info.version, DRIVER_VERSION, sizeof info.version);
+		strncpy (info.fw_version, dev->driver_info->description,
+			sizeof info.fw_version);
+		snprintf (info.bus_info, sizeof info.bus_info, "USB bus%d%s",
+			/* FIXME busnums are bogus/unstable IDs */
+			dev->udev->bus->busnum, dev->udev->devpath);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+		}
+
+	case ETHTOOL_GLINK: 		/* get link status */
+		if (dev->driver_info->check_connect) {
+			struct ethtool_value	edata = { ETHTOOL_GLINK };
+
+			edata.data = dev->driver_info->check_connect (dev);
+			if (copy_to_user (useraddr, &edata, sizeof (edata)))
+				return -EFAULT;
+			return 0;
+		}
+		break;
+
+	case ETHTOOL_GMSGLVL: {		/* get message-level */
+		struct ethtool_value	edata = {ETHTOOL_GMSGLVL};
+
+		edata.data = dev->msg_level;
+		if (copy_to_user (useraddr, &edata, sizeof (edata)))
+			return -EFAULT;
+		return 0;
+		}
+
+	case ETHTOOL_SMSGLVL: {		/* set message-level */
+		struct ethtool_value	edata;
+
+		if (copy_from_user (&edata, useraddr, sizeof (edata)))
+			return -EFAULT;
+		dev->msg_level = edata.data;
+		return 0;
+		}
+	
+	/* could also map RINGPARAM to RX/TX QLEN */
+
+	}
+        /* Note that the ethtool user space code requires EOPNOTSUPP */
+	return -EOPNOTSUPP;
+}
+
+static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return usbnet_ethtool_ioctl (net, (void *)rq->ifr_data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* usb_clear_halt cannot be called in interrupt context */
+
+static void
+tx_clear_halt (void *data)
+{
+	struct usbnet		*dev = data;
+
+	usb_clear_halt (dev->udev,
+		usb_sndbulkpipe (dev->udev, dev->driver_info->out));
+	netif_wake_queue (&dev->net);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void tx_complete (struct urb *urb)
+{
+	struct sk_buff		*skb = (struct sk_buff *) urb->context;
+	struct skb_data		*entry = (struct skb_data *) skb->cb;
+	struct usbnet		*dev = entry->dev;
+
+	if (urb->status == -EPIPE) {
+		if (dev->ctrl_task.sync == 0) {
+			dev->ctrl_task.routine = tx_clear_halt;
+			dev->ctrl_task.data = dev;
+			schedule_task (&dev->ctrl_task);
+		} else {
+			dbg ("Cannot clear TX stall");
+		}
+	}
+	urb->dev = 0;
+	entry->state = tx_done;
+	defer_bh (dev, skb);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void usbnet_tx_timeout (struct net_device *net)
+{
+	struct usbnet		*dev = (struct usbnet *) net->priv;
+
+	unlink_urbs (&dev->txq);
+	tasklet_schedule (&dev->bh);
+
+	// FIXME: device recovery -- reset?
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
+{
+	struct usbnet		*dev = (struct usbnet *) net->priv;
+	int			length = skb->len;
+	int			retval = NET_XMIT_SUCCESS;
+	struct urb		*urb = 0;
+	struct skb_data		*entry;
+	struct driver_info	*info = dev->driver_info;
+	unsigned long		flags;
+#ifdef	CONFIG_USB_NET1080
+	struct nc_header	*header = 0;
+	struct nc_trailer	*trailer = 0;
+#endif	/* CONFIG_USB_NET1080 */
+
+	// some devices want funky USB-level framing, for
+	// win32 driver (usually) and/or hardware quirks
+	if (info->tx_fixup) {
+		skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
+		if (!skb) {
+			dbg ("can't tx_fixup skb");
+			goto drop;
+		}
+	}
+
+	if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
+		dbg ("no urb");
+		goto drop;
+	}
+
+	entry = (struct skb_data *) skb->cb;
+	entry->urb = urb;
+	entry->dev = dev;
+	entry->state = tx_start;
+	entry->length = length;
+
+	// FIXME: reorganize a bit, so that fixup() fills out NetChip
+	// framing too. (Packet ID update needs the spinlock...)
+
+#ifdef	CONFIG_USB_NET1080
+	if (info->flags & FLAG_FRAMING_NC) {
+		header = (struct nc_header *) skb_push (skb, sizeof *header);
+		header->hdr_len = cpu_to_le16 (sizeof (*header));
+		header->packet_len = cpu_to_le16 (length);
+		if (!((skb->len + sizeof *trailer) & 0x01))
+			*skb_put (skb, 1) = PAD_BYTE;
+		trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
+	} else
+#endif	/* CONFIG_USB_NET1080 */
+
+	/* don't assume the hardware handles USB_ZERO_PACKET */
+	if ((length % EP_SIZE (dev)) == 0)
+		skb->len++;
+
+	FILL_BULK_URB (urb, dev->udev,
+			usb_sndbulkpipe (dev->udev, info->out),
+			skb->data, skb->len, tx_complete, skb);
+	urb->transfer_flags |= USB_ASYNC_UNLINK;
+#ifdef	REALLY_QUEUE
+	urb->transfer_flags |= USB_QUEUE_BULK;
+#endif
+	// FIXME urb->timeout = ... jiffies ... ;
+
+	spin_lock_irqsave (&dev->txq.lock, flags);
+
+#ifdef	CONFIG_USB_NET1080
+	if (info->flags & FLAG_FRAMING_NC) {
+		header->packet_id = cpu_to_le16 (dev->packet_id++);
+		put_unaligned (header->packet_id, &trailer->packet_id);
+#if 0
+		devdbg (dev, "frame >tx h %d p %d id %d",
+			header->hdr_len, header->packet_len,
+			header->packet_id);
+#endif
+	}
+#endif	/* CONFIG_USB_NET1080 */
+
+	netif_stop_queue (net);
+	if ((retval = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
+		netif_start_queue (net);
+		dbg ("%s tx: submit urb err %d", net->name, retval);
+	} else {
+		net->trans_start = jiffies;
+		__skb_queue_tail (&dev->txq, skb);
+		if (dev->txq.qlen < TX_QLEN)
+			netif_start_queue (net);
+	}
+	spin_unlock_irqrestore (&dev->txq.lock, flags);
+
+	if (retval) {
+		devdbg (dev, "drop, code %d", retval);
+drop:
+		retval = NET_XMIT_DROP;
+		dev->stats.tx_dropped++;
+		if (skb)
+			dev_kfree_skb_any (skb);
+		usb_free_urb (urb);
+#ifdef	VERBOSE
+	} else {
+		devdbg (dev, "> tx, len %d, type 0x%x",
+			length, skb->protocol);
+#endif
+	}
+	return retval;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+// tasklet ... work that avoided running in_irq()
+
+static void usbnet_bh (unsigned long param)
+{
+	struct usbnet		*dev = (struct usbnet *) param;
+	struct sk_buff		*skb;
+	struct skb_data		*entry;
+
+	while ((skb = skb_dequeue (&dev->done))) {
+		entry = (struct skb_data *) skb->cb;
+		switch (entry->state) {
+		    case rx_done:
+			entry->state = rx_cleanup;
+			rx_process (dev, skb);
+			continue;
+		    case tx_done:
+			if (entry->urb->status) {
+				// can this statistic become more specific?
+				dev->stats.tx_errors++;
+				dbg ("%s tx: err %d", dev->net.name,
+					entry->urb->status);
+			} else {
+				dev->stats.tx_packets++;
+				dev->stats.tx_bytes += entry->length;
+			}
+			// FALLTHROUGH:
+		    case rx_cleanup:
+			usb_free_urb (entry->urb);
+			dev_kfree_skb (skb);
+			continue;
+		    default:
+			dbg ("%s: bogus skb state %d",
+				dev->net.name, entry->state);
+		}
+	}
+
+	// waiting for all pending urbs to complete?
+	if (dev->wait) {
+		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
+			wake_up (dev->wait);
+		}
+
+	// or are we maybe short a few urbs?
+	} else if (netif_running (&dev->net)) {
+		int	temp = dev->rxq.qlen;
+
+		if (temp < RX_QLEN) {
+			struct urb	*urb;
+			int		i;
+			for (i = 0; i < 3 && dev->rxq.qlen < RX_QLEN; i++) {
+				if ((urb = usb_alloc_urb (0, GFP_ATOMIC)) != 0)
+					rx_submit (dev, urb, GFP_ATOMIC);
+			}
+			if (temp != dev->rxq.qlen)
+				devdbg (dev, "rxqlen %d --> %d",
+						temp, dev->rxq.qlen);
+			if (dev->rxq.qlen < RX_QLEN)
+				tasklet_schedule (&dev->bh);
+		}
+		if (dev->txq.qlen < TX_QLEN)
+			netif_wake_queue (&dev->net);
+	}
+}
+
+
+
+/*-------------------------------------------------------------------------
+ *
+ * USB Device Driver support
+ *
+ *-------------------------------------------------------------------------*/
+ 
+// precondition: never called in_interrupt
+
+static void usbnet_disconnect (struct usb_device *udev, void *ptr)
+{
+	struct usbnet	*dev = (struct usbnet *) ptr;
+
+	devinfo (dev, "unregister usbnet bus%d%s, %s",
+		// FIXME busnum is unstable
+		udev->bus->busnum, udev->devpath,
+		dev->driver_info->description);
+	
+	unregister_netdev (&dev->net);
+
+	mutex_lock (&usbnet_mutex);
+	mutex_lock (&dev->mutex);
+	list_del (&dev->dev_list);
+	mutex_unlock (&usbnet_mutex);
+
+	kfree (dev);
+	usb_dec_dev_use (udev);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+// precondition: never called in_interrupt
+
+static void *
+usbnet_probe (struct usb_device *udev, unsigned ifnum,
+			const struct usb_device_id *prod)
+{
+	struct usbnet			*dev;
+	struct net_device 		*net;
+	struct usb_interface_descriptor	*interface;
+	struct driver_info		*info;
+	int				altnum = 0;
+
+	info = (struct driver_info *) prod->driver_info;
+
+	// sanity check; expect dedicated interface/devices for now.
+	interface = &udev->actconfig->interface [ifnum].altsetting [altnum];
+	if (udev->descriptor.bNumConfigurations != 1
+			|| udev->config[0].bNumInterfaces != 1
+//			|| interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC
+			) {
+		dbg ("Bogus config info");
+		return 0;
+	}
+
+	// more sanity (unless the device is broken)
+	if (!(info->flags & FLAG_NO_SETINT)) {
+		if (usb_set_interface (udev, ifnum, altnum) < 0) {
+			err ("set_interface failed");
+			return 0;
+		}
+	}
+
+	// set up our own records
+	if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) {
+		dbg ("can't kmalloc dev");
+		return 0;
+	}
+	memset (dev, 0, sizeof *dev);
+
+	init_MUTEX_LOCKED (&dev->mutex);
+	usb_inc_dev_use (udev);
+	dev->udev = udev;
+	dev->driver_info = info;
+	dev->msg_level = msg_level;
+	INIT_LIST_HEAD (&dev->dev_list);
+	skb_queue_head_init (&dev->rxq);
+	skb_queue_head_init (&dev->txq);
+	skb_queue_head_init (&dev->done);
+	dev->bh.func = usbnet_bh;
+	dev->bh.data = (unsigned long) dev;
+
+	// set up network interface records
+	net = &dev->net;
+	SET_MODULE_OWNER (net);
+	net->priv = dev;
+	strcpy (net->name, "usb%d");
+	memcpy (net->dev_addr, node_id, sizeof node_id);
+
+	// point-to-point link ... we always use Ethernet headers 
+	// supports win32 interop and the bridge driver.
+	ether_setup (net);
+
+	net->change_mtu = usbnet_change_mtu;
+	net->get_stats = usbnet_get_stats;
+	net->hard_start_xmit = usbnet_start_xmit;
+	net->open = usbnet_open;
+	net->stop = usbnet_stop;
+	net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
+	net->tx_timeout = usbnet_tx_timeout;
+	net->do_ioctl = usbnet_ioctl;
+
+	register_netdev (&dev->net);
+	devinfo (dev, "register usbnet bus%d%s, %s",
+		// FIXME busnum is unstable
+		udev->bus->busnum, udev->devpath,
+		dev->driver_info->description);
+
+	// ok, it's ready to go.
+	mutex_lock (&usbnet_mutex);
+	list_add (&dev->dev_list, &usbnet_list);
+	mutex_unlock (&dev->mutex);
+
+	// start as if the link is up
+	netif_device_attach (&dev->net);
+
+	mutex_unlock (&usbnet_mutex);
+	return dev;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * chip vendor names won't normally be on the cables, and
+ * may not be on the device.
+ */
+
+static const struct usb_device_id	products [] = {
+
+#ifdef	CONFIG_USB_AN2720
+{
+	USB_DEVICE (0x0547, 0x2720),	// AnchorChips defaults
+	driver_info:	(unsigned long) &an2720_info,
+},
+
+{
+	USB_DEVICE (0x0547, 0x2727),	// Xircom PGUNET
+	driver_info:	(unsigned long) &an2720_info,
+},
+#endif
+
+#ifdef	CONFIG_USB_BELKIN
+{
+	USB_DEVICE (0x050d, 0x0004),	// Belkin
+	driver_info:	(unsigned long) &belkin_info,
+}, {
+	USB_DEVICE (0x056c, 0x8100),	// eTEK
+	driver_info:	(unsigned long) &belkin_info,
+}, {
+	USB_DEVICE (0x0525, 0x9901),	// Advance USBNET (eTEK)
+	driver_info:	(unsigned long) &belkin_info,
+},
+#endif
+
+#ifdef	CONFIG_USB_GENESYS
+{
+	USB_DEVICE (0x05e3, 0x0502),	// GL620USB-A
+	driver_info:	(unsigned long) &genelink_info,
+},
+#endif
+
+#ifdef	CONFIG_USB_LINUXDEV
+/*
+ * for example, this can be a host side talk-to-PDA driver.
+ * this driver is NOT what runs _inside_ a Linux device !!
+ */
+{
+	// 1183 = 0x049F, both used as hex values?
+	USB_DEVICE (0x049F, 0x505A),	// Compaq "Itsy"
+	driver_info:	(unsigned long) &linuxdev_info,
+},
+#endif
+
+#ifdef	CONFIG_USB_NET1080
+{
+	USB_DEVICE (0x0525, 0x1080),	// NetChip ref design
+	driver_info:	(unsigned long) &net1080_info,
+},
+{
+	USB_DEVICE (0x06D0, 0x0622),	// Laplink Gold
+	driver_info:	(unsigned long) &net1080_info,
+},
+#endif
+
+#ifdef CONFIG_USB_PL2301
+{
+	USB_DEVICE (0x067b, 0x0000),	// PL-2301
+	driver_info:	(unsigned long) &prolific_info,
+}, {
+	USB_DEVICE (0x067b, 0x0001),	// PL-2302
+	driver_info:	(unsigned long) &prolific_info,
+},
+#endif
+
+/* KC2190 from www.sepoong.co.kr "InstaNET" */
+
+	{ },		// END
+};
+MODULE_DEVICE_TABLE (usb, products);
+
+static struct usb_driver usbnet_driver = {
+	name:		driver_name,
+	id_table:	products,
+	probe:		usbnet_probe,
+	disconnect:	usbnet_disconnect,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init usbnet_init (void)
+{
+	// compiler should optimize this out
+	if (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data))
+		BUG ();
+
+	get_random_bytes (node_id, sizeof node_id);
+	node_id [0] &= 0xfe;	// clear multicast bit
+
+ 	if (usb_register (&usbnet_driver) < 0)
+ 		return -1;
+
+	return 0;
+}
+module_init (usbnet_init);
+
+static void __exit usbnet_exit (void)
+{
+ 	usb_deregister (&usbnet_driver);
+}
+module_exit (usbnet_exit);
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR ("David Brownell <dbrownell@users.sourceforge.net>");
+MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (numerous vendors)");
+MODULE_LICENSE ("GPL");
diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,6713 +0,0 @@
-/*
- * OmniVision OV511 Camera-to-USB Bridge Driver
- *
- * Copyright (c) 1999-2002 Mark W. McClelland
- * Original decompression code Copyright 1998-2000 OmniVision Technologies
- * Many improvements by Bret Wallach <bwallac1@san.rr.com>
- * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
- * Snapshot code by Kevin Moore
- * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
- * Changes by Claudio Matsuoka <claudio@conectiva.com>
- * Original SAA7111A code by Dave Perks <dperks@ibm.net>
- * Kernel I2C interface adapted from nt1003 driver
- * URB error messages from pwc driver by Nemosoft
- * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox
- *
- * Based on the Linux CPiA driver written by Peter Pregler,
- * Scott J. Bertin and Johannes Erdfelt.
- * 
- * Please see the file: linux/Documentation/usb/ov511.txt 
- * and the website at:  http://alpha.dyndns.org/ov511
- * for more info.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/ctype.h>
-#include <linux/pagemap.h>
-#include <asm/io.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <linux/wrapper.h>
-#include <linux/mm.h>
-
-#if defined (__i386__)
-	#include <asm/cpufeature.h>
-#endif
-
-#include "ov511.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.53 for Linux 2.5"
-#define EMAIL "mmcclell@bigfoot.com"
-#define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \
-	& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
-	<cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
-#define DRIVER_DESC "ov511 USB Camera Driver"
-
-#define OV511_I2C_RETRIES 3
-#define ENABLE_Y_QUANTABLE 1
-#define ENABLE_UV_QUANTABLE 1
-
-/* If you change this, you must also change the MODULE_PARM definition */
-#define OV511_MAX_UNIT_VIDEO 16
-
-/* Pixel count * 3 bytes for RGB */
-#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)
-#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))
-
-/* Max size * bytes per YUV420 pixel (1.5) + one extra isoc frame for safety */
-#define MAX_RAW_DATA_SIZE(w, h) ((w) * (h) * 3 / 2 + 1024)
-
-#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
-
-/**********************************************************************
- * Module Parameters
- * (See ov511.txt for detailed descriptions of these)
- **********************************************************************/
-
-/* These variables (and all static globals) default to zero */
-static int autobright		= 1;
-static int autogain		= 1;
-static int autoexp		= 1;
-static int debug;
-static int fix_rgb_offset;
-static int snapshot;
-static int force_rgb;
-static int buf_timeout		= 5;
-static int cams			= 1;
-static int compress;
-static int testpat;
-static int sensor_gbr;
-static int dumppix;
-static int led 			= 1;
-static int dump_bridge;
-static int dump_sensor;
-static int printph;
-static int phy			= 0x1f;
-static int phuv			= 0x05;
-static int pvy			= 0x06;
-static int pvuv			= 0x06;
-static int qhy			= 0x14;
-static int qhuv			= 0x03;
-static int qvy			= 0x04;
-static int qvuv			= 0x04;
-static int lightfreq;
-static int bandingfilter;
-
-/* Pixel clock divisor */
-static int clockdiv		= -1;
-
-/* Isoc packet size */
-static int packetsize		= -1;
-
-/* Frame drop register (16h) */
-static int framedrop		= -1;
-
-static int fastset;
-static int force_palette;
-static int tuner		= -1;
-static int backlight;
-static int unit_video[OV511_MAX_UNIT_VIDEO];
-static int remove_zeros;
-
-MODULE_PARM(autobright, "i");
-MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
-MODULE_PARM(autogain, "i");
-MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
-MODULE_PARM(autoexp, "i");
-MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug,
-  "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
-MODULE_PARM(fix_rgb_offset, "i");
-MODULE_PARM_DESC(fix_rgb_offset,
-  "Fix vertical misalignment of red and blue at 640x480");
-MODULE_PARM(snapshot, "i");
-MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
-MODULE_PARM(force_rgb, "i");
-MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
-MODULE_PARM(buf_timeout, "i");
-MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");
-MODULE_PARM(cams, "i");
-MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
-MODULE_PARM(compress, "i");
-MODULE_PARM_DESC(compress, "Turn on compression (not reliable yet)");
-MODULE_PARM(testpat, "i");
-MODULE_PARM_DESC(testpat,
-  "Replace image with vertical bar testpattern (only partially working)");
-
-// Temporarily removed (needs to be rewritten for new format conversion code)
-// MODULE_PARM(sensor_gbr, "i");
-// MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
-
-MODULE_PARM(dumppix, "i");
-MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
-MODULE_PARM(led, "i");
-MODULE_PARM_DESC(led,
-  "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
-MODULE_PARM(dump_bridge, "i");
-MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
-MODULE_PARM(dump_sensor, "i");
-MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
-MODULE_PARM(printph, "i");
-MODULE_PARM_DESC(printph, "Print frame start/end headers");
-MODULE_PARM(phy, "i");
-MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
-MODULE_PARM(phuv, "i");
-MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
-MODULE_PARM(pvy, "i");
-MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
-MODULE_PARM(pvuv, "i");
-MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
-MODULE_PARM(qhy, "i");
-MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
-MODULE_PARM(qhuv, "i");
-MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
-MODULE_PARM(qvy, "i");
-MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
-MODULE_PARM(qvuv, "i");
-MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
-MODULE_PARM(lightfreq, "i");
-MODULE_PARM_DESC(lightfreq,
-  "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
-MODULE_PARM(bandingfilter, "i");
-MODULE_PARM_DESC(bandingfilter,
-  "Enable banding filter (to reduce effects of fluorescent lighting)");
-MODULE_PARM(clockdiv, "i");
-MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
-MODULE_PARM(packetsize, "i");
-MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
-MODULE_PARM(framedrop, "i");
-MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
-MODULE_PARM(fastset, "i");
-MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
-MODULE_PARM(force_palette, "i");
-MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
-MODULE_PARM(tuner, "i");
-MODULE_PARM_DESC(tuner, "Set tuner type, if not autodetected");
-MODULE_PARM(backlight, "i");
-MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
-MODULE_PARM(unit_video, "0-16i");
-MODULE_PARM_DESC(unit_video,
-  "Force use of specific minor number(s). 0 is not allowed.");
-MODULE_PARM(remove_zeros, "i");
-MODULE_PARM_DESC(remove_zeros,
-  "Remove zero-padding from uncompressed incoming data");
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-/**********************************************************************
- * Miscellaneous Globals
- **********************************************************************/
-
-static struct usb_driver ov511_driver;
-
-static struct ov51x_decomp_ops *ov511_decomp_ops;
-static struct ov51x_decomp_ops *ov511_mmx_decomp_ops;
-static struct ov51x_decomp_ops *ov518_decomp_ops;
-static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
-
-/* Number of times to retry a failed I2C transaction. Increase this if you
- * are getting "Failed to read sensor ID..." */
-static int i2c_detect_tries = 5;
-
-/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
-static int ov51x_mmx_available;
-
-static __devinitdata struct usb_device_id device_table [] = {
-	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
-	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
-	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
-	{ USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
-	{ USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
-	{ }  /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, device_table);
-
-static unsigned char yQuanTable511[] = OV511_YQUANTABLE;
-static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;
-static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
-static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
-
-/**********************************************************************
- * Symbolic Names
- **********************************************************************/
-
-/* Known OV511-based cameras */
-static struct symbolic_list camlist[] = {
-	{   0, "Generic Camera (no ID)" },
-	{   1, "Mustek WCam 3X" },
-	{   3, "D-Link DSB-C300" },
-	{   4, "Generic OV511/OV7610" },
-	{   5, "Puretek PT-6007" },
-	{   6, "Lifeview USB Life TV (NTSC)" },
-	{  21, "Creative Labs WebCam 3" },
-	{  36, "Koala-Cam" },
-	{  38, "Lifeview USB Life TV" },
-	{  41, "Samsung Anycam MPC-M10" },
-	{  43, "Mtekvision Zeca MV402" },
-	{  46, "Suma eON" },
-	{ 100, "Lifeview RoboCam" },
-	{ 102, "AverMedia InterCam Elite" },
-	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */
-	{ 192, "Webeye 2000B" },
-	{  -1, NULL }
-};
-
-/* Video4Linux1 Palettes */
-static struct symbolic_list v4l1_plist[] = {
-	{ VIDEO_PALETTE_GREY,	"GREY" },
-	{ VIDEO_PALETTE_HI240,	"HI240" },
-	{ VIDEO_PALETTE_RGB565,	"RGB565" },
-	{ VIDEO_PALETTE_RGB24,	"RGB24" },
-	{ VIDEO_PALETTE_RGB32,	"RGB32" },
-	{ VIDEO_PALETTE_RGB555,	"RGB555" },
-	{ VIDEO_PALETTE_YUV422,	"YUV422" },
-	{ VIDEO_PALETTE_YUYV,	"YUYV" },
-	{ VIDEO_PALETTE_UYVY,	"UYVY" },
-	{ VIDEO_PALETTE_YUV420,	"YUV420" },
-	{ VIDEO_PALETTE_YUV411,	"YUV411" },
-	{ VIDEO_PALETTE_RAW,	"RAW" },
-	{ VIDEO_PALETTE_YUV422P,"YUV422P" },
-	{ VIDEO_PALETTE_YUV411P,"YUV411P" },
-	{ VIDEO_PALETTE_YUV420P,"YUV420P" },
-	{ VIDEO_PALETTE_YUV410P,"YUV410P" },
-	{ -1, NULL }
-};
-
-static struct symbolic_list brglist[] = {
-	{ BRG_OV511,		"OV511" },
-	{ BRG_OV511PLUS,	"OV511+" },
-	{ BRG_OV518,		"OV518" },
-	{ BRG_OV518PLUS,	"OV518+" },
-	{ -1, NULL }
-};
-
-static struct symbolic_list senlist[] = {
-	{ SEN_OV76BE,	"OV76BE" },
-	{ SEN_OV7610,	"OV7610" },
-	{ SEN_OV7620,	"OV7620" },
-	{ SEN_OV7620AE,	"OV7620AE" },
-	{ SEN_OV6620,	"OV6620" },
-	{ SEN_OV6630,	"OV6630" },
-	{ SEN_OV6630AE,	"OV6630AE" },
-	{ SEN_OV6630AF,	"OV6630AF" },
-	{ SEN_OV8600,	"OV8600" },
-	{ SEN_KS0127,	"KS0127" },
-	{ SEN_KS0127B,	"KS0127B" },
-	{ SEN_SAA7111A,	"SAA7111A" },
-	{ -1, NULL }
-};
-
-/* URB error codes: */
-static struct symbolic_list urb_errlist[] = {
-	{ -ENOSR,	"Buffer error (overrun)" },
-	{ -EPIPE,	"Stalled (device not responding)" },
-	{ -EOVERFLOW,	"Babble (bad cable?)" },
-	{ -EPROTO,	"Bit-stuff error (bad cable?)" },
-	{ -EILSEQ,	"CRC/Timeout" },
-	{ -ETIMEDOUT,	"NAK (device does not respond)" },
-	{ -1, NULL }
-};
-
-/**********************************************************************
- * Prototypes
- **********************************************************************/
-
-static void ov51x_clear_snapshot(struct usb_ov511 *);
-static int ov51x_check_snapshot(struct usb_ov511 *);
-static inline int sensor_get_picture(struct usb_ov511 *, 
-				     struct video_picture *);
-static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
-static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
-			       unsigned long);
-
-/**********************************************************************
- *
- * Memory management
- *
- **********************************************************************/
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long 
-kvirt_to_pa(unsigned long adr)
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-	return ret;
-}
-
-static void *
-rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		mem_map_reserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void 
-rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		mem_map_unreserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-/**********************************************************************
- * /proc interface
- * Based on the CPiA driver version 0.7.4 -claudio
- **********************************************************************/
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-
-static struct proc_dir_entry *ov511_proc_entry = NULL;
-extern struct proc_dir_entry *video_proc_entry;
-
-static struct file_operations ov511_control_fops = {
-	ioctl:		ov51x_control_ioctl,
-};
-
-#define YES_NO(x) ((x) ? "yes" : "no")
-
-/* /proc/video/ov511/<minor#>/info */
-static int 
-ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
-		     void *data)
-{
-	char *out = page;
-	int i, len;
-	struct usb_ov511 *ov = data;
-	struct video_picture p;
-	unsigned char exp;
-
-	if (!ov || !ov->dev)
-		return -ENODEV;
-
-	sensor_get_picture(ov, &p);
-	sensor_get_exposure(ov, &exp);
-
-	/* IMPORTANT: This output MUST be kept under PAGE_SIZE
-	 *            or we need to get more sophisticated. */
-
-	out += sprintf(out, "driver_version  : %s\n", DRIVER_VERSION);
-	out += sprintf(out, "custom_id       : %d\n", ov->customid);
-	out += sprintf(out, "model           : %s\n", ov->desc);
-	out += sprintf(out, "streaming       : %s\n", YES_NO(ov->streaming));
-	out += sprintf(out, "grabbing        : %s\n", YES_NO(ov->grabbing));
-	out += sprintf(out, "compress        : %s\n", YES_NO(ov->compress));
-	out += sprintf(out, "subcapture      : %s\n", YES_NO(ov->sub_flag));
-	out += sprintf(out, "sub_size        : %d %d %d %d\n",
-		       ov->subx, ov->suby, ov->subw, ov->subh);
-	out += sprintf(out, "data_format     : %s\n",
-		       force_rgb ? "RGB" : "BGR");
-	out += sprintf(out, "brightness      : %d\n", p.brightness >> 8);
-	out += sprintf(out, "colour          : %d\n", p.colour >> 8);
-	out += sprintf(out, "contrast        : %d\n", p.contrast >> 8);
-	out += sprintf(out, "hue             : %d\n", p.hue >> 8);
-	out += sprintf(out, "exposure        : %d\n", exp);
-	out += sprintf(out, "num_frames      : %d\n", OV511_NUMFRAMES);
-	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		out += sprintf(out, "frame           : %d\n", i);
-		out += sprintf(out, "  depth         : %d\n",
-			       ov->frame[i].depth);
-		out += sprintf(out, "  size          : %d %d\n",
-			       ov->frame[i].width, ov->frame[i].height);
-		out += sprintf(out, "  format        : %s\n",
-			       symbolic(v4l1_plist, ov->frame[i].format));
-		out += sprintf(out, "  data_buffer   : 0x%p\n",
-			       ov->frame[i].data);
-	}
-	out += sprintf(out, "snap_enabled    : %s\n", YES_NO(ov->snap_enabled));
-	out += sprintf(out, "bridge          : %s\n",
-		       symbolic(brglist, ov->bridge));
-	out += sprintf(out, "sensor          : %s\n",
-		       symbolic(senlist, ov->sensor));
-	out += sprintf(out, "packet_size     : %d\n", ov->packet_size);
-	out += sprintf(out, "framebuffer     : 0x%p\n", ov->fbuf);
-
-	len = out - page;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else
-		len = count;
-
-	*start = page + off;
-
-	return len;
-}
-
-/* /proc/video/ov511/<minor#>/button
- *
- * When the camera's button is pressed, the output of this will change from a
- * 0 to a 1 (ASCII). It will retain this value until it is read, after which
- * it will reset to zero.
- * 
- * SECURITY NOTE: Since reading this file can change the state of the snapshot
- * status, it is important for applications that open it to keep it locked
- * against access by other processes, using flock() or a similar mechanism. No
- * locking is provided by this driver.
- */
-static int 
-ov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,
-		       void *data)
-{
-	char *out = page;
-	int len, status;
-	struct usb_ov511 *ov = data;
-
-	if (!ov || !ov->dev)
-		return -ENODEV;
-
-	status = ov51x_check_snapshot(ov);
-	out += sprintf(out, "%d", status);
-
-	if (status)
-		ov51x_clear_snapshot(ov);
-
-	len = out - page;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else {
-		len = count;
-	}
-
-	*start = page + off;
-
-	return len;
-}
-
-static void 
-create_proc_ov511_cam(struct usb_ov511 *ov)
-{
-	char dirname[10];
-
-	if (!ov511_proc_entry || !ov)
-		return;
-
-	/* Create per-device directory */
-	snprintf(dirname, 10, "%d", ov->vdev.minor);
-	PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);
-	ov->proc_devdir = create_proc_entry(dirname, S_IFDIR, ov511_proc_entry);
-	if (!ov->proc_devdir)
-		return;
-	ov->proc_devdir->owner = THIS_MODULE;
-
-	/* Create "info" entry (human readable device information) */
-	PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);
-	ov->proc_info = create_proc_read_entry("info", S_IFREG|S_IRUGO|S_IWUSR,
-		ov->proc_devdir, ov511_read_proc_info, ov);
-	if (!ov->proc_info)
-		return;
-	ov->proc_info->owner = THIS_MODULE;
-
-	/* Don't create it if old snapshot mode on (would cause race cond.) */
-	if (!snapshot) {
-		/* Create "button" entry (snapshot button status) */
-		PDEBUG(4, "creating /proc/video/ov511/%s/button", dirname);
-		ov->proc_button = create_proc_read_entry("button",
-			S_IFREG|S_IRUGO|S_IWUSR, ov->proc_devdir,
-			ov511_read_proc_button, ov);
-		if (!ov->proc_button)
-			return;
-	}
-	ov->proc_button->owner = THIS_MODULE;
-
-	/* Create "control" entry (ioctl() interface) */
-	PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);
-	lock_kernel();
-	ov->proc_control = create_proc_entry("control",	S_IFREG|S_IRUGO|S_IWUSR,
-		ov->proc_devdir);
-	if (!ov->proc_control) {
-		unlock_kernel();
-		return;
-	}
-	ov->proc_control->owner = THIS_MODULE;
-	ov->proc_control->data = ov;
-	ov->proc_control->proc_fops = &ov511_control_fops;
-	unlock_kernel();
-}
-
-static void 
-destroy_proc_ov511_cam(struct usb_ov511 *ov)
-{
-	char dirname[10];
-	
-	if (!ov || !ov->proc_devdir)
-		return;
-
-	snprintf(dirname, 10, "%d", ov->vdev.minor);
-
-	/* Destroy "control" entry */
-	if (ov->proc_control) {
-		PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);
-		remove_proc_entry("control", ov->proc_devdir);
-		ov->proc_control = NULL;
-	}
-
-	/* Destroy "button" entry */
-	if (ov->proc_button) {
-		PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);
-		remove_proc_entry("button", ov->proc_devdir);
-		ov->proc_button = NULL;
-	}
-
-	/* Destroy "info" entry */
-	if (ov->proc_info) {
-		PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);
-		remove_proc_entry("info", ov->proc_devdir);
-		ov->proc_info = NULL;
-	}
-
-	/* Destroy per-device directory */
-	PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);
-	remove_proc_entry(dirname, ov511_proc_entry);
-	ov->proc_devdir = NULL;
-}
-
-static void 
-proc_ov511_create(void)
-{
-	/* No current standard here. Alan prefers /proc/video/ as it keeps
-	 * /proc "less cluttered than /proc/randomcardifoundintheshed/"
-	 * -claudio
-	 */
-	if (video_proc_entry == NULL) {
-		err("Error: /proc/video/ does not exist");
-		return;
-	}
-
-	ov511_proc_entry = create_proc_entry("ov511", S_IFDIR,
-					     video_proc_entry);
-
-	if (ov511_proc_entry)
-		ov511_proc_entry->owner = THIS_MODULE;
-	else
-		err("Unable to create /proc/video/ov511");
-}
-
-static void 
-proc_ov511_destroy(void)
-{
-	PDEBUG(3, "removing /proc/video/ov511");
-
-	if (ov511_proc_entry == NULL)
-		return;
-
-	remove_proc_entry("ov511", video_proc_entry);
-}
-#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
-
-/**********************************************************************
- *
- * Register I/O
- *
- **********************************************************************/
-
-/* Write an OV51x register */
-static int 
-reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
-{
-	int rc;
-
-	PDEBUG(5, "0x%02X:0x%02X", reg, value);
-
-	down(&ov->cbuf_lock);
-	ov->cbuf[0] = value;
-	rc = usb_control_msg(ov->dev,
-			     usb_sndctrlpipe(ov->dev, 0),
-			     2 /* REG_IO */,
-			     USB_TYPE_CLASS | USB_RECIP_DEVICE,
-			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);	
-	up(&ov->cbuf_lock);
-
-	if (rc < 0)
-		err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));
-
-	return rc;
-}
-
-/* Read from an OV51x register */
-/* returns: negative is error, pos or zero is data */
-static int 
-reg_r(struct usb_ov511 *ov, unsigned char reg)
-{
-	int rc;
-
-	down(&ov->cbuf_lock);
-	rc = usb_control_msg(ov->dev,
-			     usb_rcvctrlpipe(ov->dev, 0),
-			     2 /* REG_IO */,
-			     USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
-			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);
-                               
-	PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
-	
-	if (rc < 0)
-		err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));
-	else
-		rc = ov->cbuf[0];	
-
-	up(&ov->cbuf_lock);
-
-	return rc;
-}
-
-/*
- * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
- * the same position as 1's in "mask" are cleared and set to "value". Bits
- * that are in the same position as 0's in "mask" are preserved, regardless 
- * of their respective state in "value".
- */
-static int 
-reg_w_mask(struct usb_ov511 *ov,
-	   unsigned char reg,
-	   unsigned char value,
-	   unsigned char mask)
-{
-	int ret;
-	unsigned char oldval, newval;
-
-	ret = reg_r(ov, reg);
-	if (ret < 0)
-		return ret;
-
-	oldval = (unsigned char) ret;
-	oldval &= (~mask);		/* Clear the masked bits */
-	value &= mask;			/* Enforce mask on value */
-	newval = oldval | value;	/* Set the desired bits */
-
-	return (reg_w(ov, reg, newval));
-}
-
-/* 
- * Writes multiple (n) byte value to a single register. Only valid with certain
- * registers (0x30 and 0xc4 - 0xce).
- */
-static int 
-ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
-{
-	int rc;
-
-	PDEBUG(5, "0x%02X:%7d, n=%d", reg, val, n);
-
-	down(&ov->cbuf_lock);
-
-	*((u32 *)ov->cbuf) = __cpu_to_le32(val);
-
-	rc = usb_control_msg(ov->dev,
-			     usb_sndctrlpipe(ov->dev, 0),
-			     2 /* REG_IO */,
-			     USB_TYPE_CLASS | USB_RECIP_DEVICE,
-			     0, (__u16)reg, ov->cbuf, n, HZ);
-	up(&ov->cbuf_lock);
-
-	if (rc < 0)
-		err("reg write multiple: error %d: %s", rc,
-		    symbolic(urb_errlist, rc));
-
-	return rc;
-}
-
-static int 
-ov511_upload_quan_tables(struct usb_ov511 *ov)
-{
-	unsigned char *pYTable = yQuanTable511;
-	unsigned char *pUVTable = uvQuanTable511;
-	unsigned char val0, val1;
-	int i, rc, reg = R511_COMP_LUT_BEGIN;
-
-	PDEBUG(4, "Uploading quantization tables");
-
-	for (i = 0; i < OV511_QUANTABLESIZE / 2; i++)
-	{
-		if (ENABLE_Y_QUANTABLE)
-		{
-			val0 = *pYTable++;
-			val1 = *pYTable++;
-			val0 &= 0x0f;
-			val1 &= 0x0f;
-			val0 |= val1 << 4;
-			rc = reg_w(ov, reg, val0);
-			if (rc < 0)
-				return rc;
-		}
-
-		if (ENABLE_UV_QUANTABLE)
-		{
-			val0 = *pUVTable++;
-			val1 = *pUVTable++;
-			val0 &= 0x0f;
-			val1 &= 0x0f;
-			val0 |= val1 << 4;
-			rc = reg_w(ov, reg + OV511_QUANTABLESIZE/2, val0);
-			if (rc < 0)
-				return rc;
-		}
-
-		reg++;
-	}
-
-	return 0;
-}
-
-/* OV518 quantization tables are 8x4 (instead of 8x8) */
-static int 
-ov518_upload_quan_tables(struct usb_ov511 *ov)
-{
-	unsigned char *pYTable = yQuanTable518;
-	unsigned char *pUVTable = uvQuanTable518;
-	unsigned char val0, val1;
-	int i, rc, reg = R511_COMP_LUT_BEGIN;
-
-	PDEBUG(4, "Uploading quantization tables");
-
-	for (i = 0; i < OV518_QUANTABLESIZE / 2; i++)
-	{
-		if (ENABLE_Y_QUANTABLE)
-		{
-			val0 = *pYTable++;
-			val1 = *pYTable++;
-			val0 &= 0x0f;
-			val1 &= 0x0f;
-			val0 |= val1 << 4;
-			rc = reg_w(ov, reg, val0);
-			if (rc < 0)
-				return rc;
-		}
-
-		if (ENABLE_UV_QUANTABLE)
-		{
-			val0 = *pUVTable++;
-			val1 = *pUVTable++;
-			val0 &= 0x0f;
-			val1 &= 0x0f;
-			val0 |= val1 << 4;
-			rc = reg_w(ov, reg + OV518_QUANTABLESIZE/2, val0);
-			if (rc < 0)
-				return rc;
-		}
-
-		reg++;
-	}
-
-	return 0;
-}
-
-static int 
-ov51x_reset(struct usb_ov511 *ov, unsigned char reset_type)
-{
-	int rc;
-		
-	/* Setting bit 0 not allowed on 518/518Plus */
-	if (ov->bclass == BCL_OV518)
-		reset_type &= 0xfe;
-
-	PDEBUG(4, "Reset: type=0x%X", reset_type);
-
-	rc = reg_w(ov, R51x_SYS_RESET, reset_type);
-	rc = reg_w(ov, R51x_SYS_RESET, 0);
-
-	if (rc < 0)
-		err("reset: command failed");
-
-	return rc;
-}
-
-/**********************************************************************
- *
- * I2C (sensor) I/O
- *
- **********************************************************************/
-
-/* NOTE: Do not call this function directly!
- * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from i2c_w(). Note that this function
- * always succeeds regardless of whether the sensor is present and working.
- */
-static int 
-ov518_i2c_write_internal(struct usb_ov511 *ov,
-			 unsigned char reg,
-			 unsigned char value)
-{
-	int rc;
-
-	PDEBUG(5, "0x%02X:0x%02X", reg, value);
-
-	/* Select camera register */
-	rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
-	if (rc < 0) return rc;
-
-	/* Write "value" to I2C data port of OV511 */
-	rc = reg_w(ov, R51x_I2C_DATA, value);
-	if (rc < 0) return rc;
-
-	/* Initiate 3-byte write cycle */
-	rc = reg_w(ov, R518_I2C_CTL, 0x01);
-	if (rc < 0) return rc;
-
-	return 0;
-}
-
-/* NOTE: Do not call this function directly! */
-static int 
-ov511_i2c_write_internal(struct usb_ov511 *ov,
-			 unsigned char reg,
-			 unsigned char value)
-{
-	int rc, retries;
-
-	PDEBUG(5, "0x%02X:0x%02X", reg, value);
-
-	/* Three byte write cycle */
-	for (retries = OV511_I2C_RETRIES; ; ) {
-		/* Select camera register */
-		rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
-		if (rc < 0) return rc;
-
-		/* Write "value" to I2C data port of OV511 */
-		rc = reg_w(ov, R51x_I2C_DATA, value);	
-		if (rc < 0) return rc;
-
-		/* Initiate 3-byte write cycle */
-		rc = reg_w(ov, R511_I2C_CTL, 0x01);
-		if (rc < 0) return rc;
-
-		do rc = reg_r(ov, R511_I2C_CTL);
-		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
-		if (rc < 0) return rc;
-
-		if ((rc&2) == 0) /* Ack? */
-			break;
-#if 0
-		/* I2C abort */	
-		reg_w(ov, R511_I2C_CTL, 0x10);
-#endif
-		if (--retries < 0) {
-			err("i2c write retries exhausted");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-/* NOTE: Do not call this function directly!
- * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from i2c_r(). Note that this function
- * always succeeds regardless of whether the sensor is present and working.
- */
-static int 
-ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
-{
-	int rc, value;
-
-	/* Select camera register */
-	rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
-	if (rc < 0) return rc;
-
-	/* Initiate 2-byte write cycle */
-	rc = reg_w(ov, R518_I2C_CTL, 0x03);
-	if (rc < 0) return rc;
-
-	/* Initiate 2-byte read cycle */
-	rc = reg_w(ov, R518_I2C_CTL, 0x05);
-	if (rc < 0) return rc;
-
-	value = reg_r(ov, R51x_I2C_DATA);
-
-	PDEBUG(5, "0x%02X:0x%02X", reg, value);
-
-	return value;
-}
-
-/* NOTE: Do not call this function directly!
- * returns: negative is error, pos or zero is data */
-static int 
-ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
-{
-	int rc, value, retries;
-
-	/* Two byte write cycle */
-	for (retries = OV511_I2C_RETRIES; ; ) {
-		/* Select camera register */
-		rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
-		if (rc < 0) return rc;
-
-		/* Initiate 2-byte write cycle */
-		rc = reg_w(ov, R511_I2C_CTL, 0x03);
-		if (rc < 0) return rc;
-
-		do rc = reg_r(ov, R511_I2C_CTL);
-		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
-		if (rc < 0) return rc;
-
-		if ((rc&2) == 0) /* Ack? */
-			break;
-
-		/* I2C abort */	
-		reg_w(ov, R511_I2C_CTL, 0x10);
-
-		if (--retries < 0) {
-			err("i2c write retries exhausted");
-			return -1;
-		}
-	}
-
-	/* Two byte read cycle */
-	for (retries = OV511_I2C_RETRIES; ; ) {
-		/* Initiate 2-byte read cycle */
-		rc = reg_w(ov, R511_I2C_CTL, 0x05);
-		if (rc < 0) return rc;
-
-		do rc = reg_r(ov, R511_I2C_CTL);
-		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
-		if (rc < 0) return rc;
-
-		if ((rc&2) == 0) /* Ack? */
-			break;
-
-		/* I2C abort */	
-		rc = reg_w(ov, R511_I2C_CTL, 0x10);
-		if (rc < 0) return rc;
-
-		if (--retries < 0) {
-			err("i2c read retries exhausted");
-			return -1;
-		}
-	}
-
-	value = reg_r(ov, R51x_I2C_DATA);
-
-	PDEBUG(5, "0x%02X:0x%02X", reg, value);
-		
-	/* This is needed to make i2c_w() work */
-	rc = reg_w(ov, R511_I2C_CTL, 0x05);
-	if (rc < 0)
-		return rc;
-	
-	return value;
-}
-
-/* returns: negative is error, pos or zero is data */
-static int 
-i2c_r(struct usb_ov511 *ov, unsigned char reg)
-{
-	int rc;
-
-	down(&ov->i2c_lock);
-
-	if (ov->bclass == BCL_OV518)
-		rc = ov518_i2c_read_internal(ov, reg);
-	else
-		rc = ov511_i2c_read_internal(ov, reg);
-
-	up(&ov->i2c_lock);
-
-	return rc;
-}
-
-static int 
-i2c_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
-{
-	int rc;
-
-	down(&ov->i2c_lock);
-
-	if (ov->bclass == BCL_OV518)
-		rc = ov518_i2c_write_internal(ov, reg, value);
-	else
-		rc = ov511_i2c_write_internal(ov, reg, value);
-
-	up(&ov->i2c_lock);
-
-	return rc;
-}
-
-/* Do not call this function directly! */
-static int 
-ov51x_i2c_write_mask_internal(struct usb_ov511 *ov,
-			      unsigned char reg,
-			      unsigned char value,
-			      unsigned char mask)
-{
-	int rc;
-	unsigned char oldval, newval;
-
-	if (mask == 0xff) {
-		newval = value;
-	} else {
-		if (ov->bclass == BCL_OV518)
-			rc = ov518_i2c_read_internal(ov, reg);
-		else
-			rc = ov511_i2c_read_internal(ov, reg);
-		if (rc < 0)
-			return rc;
-
-		oldval = (unsigned char) rc;
-		oldval &= (~mask);		/* Clear the masked bits */
-		value &= mask;			/* Enforce mask on value */
-		newval = oldval | value;	/* Set the desired bits */
-	}
-
-	if (ov->bclass == BCL_OV518)
-		return (ov518_i2c_write_internal(ov, reg, newval));
-	else
-		return (ov511_i2c_write_internal(ov, reg, newval));
-}
-
-/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
- * the same position as 1's in "mask" are cleared and set to "value". Bits
- * that are in the same position as 0's in "mask" are preserved, regardless 
- * of their respective state in "value".
- */
-static int 
-i2c_w_mask(struct usb_ov511 *ov,
-	   unsigned char reg,
-	   unsigned char value,
-	   unsigned char mask)
-{
-	int rc;
-
-	down(&ov->i2c_lock);
-	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
-	up(&ov->i2c_lock);
-
-	return rc;
-}
-
-/* Write to a specific I2C slave ID and register, using the specified mask */
-static int 
-i2c_w_slave(struct usb_ov511 *ov,
-	    unsigned char slave,
-	    unsigned char reg,
-	    unsigned char value,
-	    unsigned char mask)
-{
-	int rc = 0;
-
-	down(&ov->i2c_lock);
-
-	/* Set new slave IDs */
-	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-	rc = ov51x_i2c_write_mask_internal(ov, reg, value, mask);
-	/* Don't bail out yet if error; IDs must be restored */
-
-	/* Restore primary IDs */
-	slave = ov->primary_i2c_slave;
-	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-out:
-	up(&ov->i2c_lock);
-	return rc;
-}
-
-/* Read from a specific I2C slave ID and register */
-static int 
-i2c_r_slave(struct usb_ov511 *ov,
-	    unsigned char slave,
-	    unsigned char reg)
-{
-	int rc;
-
-	down(&ov->i2c_lock);
-
-	/* Set new slave IDs */
-	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-	if (ov->bclass == BCL_OV518)
-		rc = ov518_i2c_read_internal(ov, reg);
-	else
-		rc = ov511_i2c_read_internal(ov, reg);
-	/* Don't bail out yet if error; IDs must be restored */
-
-	/* Restore primary IDs */
-	slave = ov->primary_i2c_slave;
-	if (reg_w(ov, R51x_I2C_W_SID, slave) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-	if (reg_w(ov, R51x_I2C_R_SID, slave + 1) < 0) {
-		rc = -EIO;
-		goto out;
-	}
-
-out:
-	up(&ov->i2c_lock);
-	return rc;
-}
-
-/* Sets I2C read and write slave IDs. Returns <0 for error */
-static int 
-ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid)
-{
-	down(&ov->i2c_lock);
-
-	if (reg_w(ov, R51x_I2C_W_SID, sid) < 0)
-		return -EIO;
-
-	if (reg_w(ov, R51x_I2C_R_SID, sid + 1) < 0)
-		return -EIO;
-
-	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
-		return -EIO;
-
-	up(&ov->i2c_lock);
-
-	return 0;
-}
-
-static int 
-write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals)
-{
-	int rc;
-
-	while (pRegvals->bus != OV511_DONE_BUS) {
-		if (pRegvals->bus == OV511_REG_BUS) {
-			if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0)
-				return rc;
-		} else if (pRegvals->bus == OV511_I2C_BUS) {
-			if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)
-				return rc;
-		} else {
-			err("Bad regval array");
-			return -1;
-		}
-		pRegvals++;
-	}
-	return 0;
-}
-
-#ifdef OV511_DEBUG 
-static void 
-dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
-{
-	int i;
-	int rc;
-
-	for (i = reg1; i <= regn; i++) {
-		rc = i2c_r(ov, i);
-		info("OV7610[0x%X] = 0x%X", i, rc);
-	}
-}
-
-static void 
-dump_i2c_regs(struct usb_ov511 *ov)
-{
-	info("I2C REGS");
-	dump_i2c_range(ov, 0x00, 0x7C);
-}
-
-static void 
-dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
-{
-	int i;
-	int rc;
-
-	for (i = reg1; i <= regn; i++) {
-		rc = reg_r(ov, i);
-		info("OV511[0x%X] = 0x%X", i, rc);
-	}
-}
-
-/* FIXME: Should there be an OV518 version of this? */
-static void 
-ov511_dump_regs(struct usb_ov511 *ov)
-{
-	info("CAMERA INTERFACE REGS");
-	dump_reg_range(ov, 0x10, 0x1f);
-	info("DRAM INTERFACE REGS");
-	dump_reg_range(ov, 0x20, 0x23);
-	info("ISO FIFO REGS");
-	dump_reg_range(ov, 0x30, 0x31);
-	info("PIO REGS");
-	dump_reg_range(ov, 0x38, 0x39);
-	dump_reg_range(ov, 0x3e, 0x3e);
-	info("I2C REGS");
-	dump_reg_range(ov, 0x40, 0x49);
-	info("SYSTEM CONTROL REGS");
-	dump_reg_range(ov, 0x50, 0x55);
-	dump_reg_range(ov, 0x5e, 0x5f);
-	info("OmniCE REGS");
-	dump_reg_range(ov, 0x70, 0x79);
-	/* NOTE: Quantization tables are not readable. You will get the value
-	 * in reg. 0x79 for every table register */
-	dump_reg_range(ov, 0x80, 0x9f);
-	dump_reg_range(ov, 0xa0, 0xbf);
-
-}
-#endif
-
-/**********************************************************************
- *
- * Kernel I2C Interface
- *
- **********************************************************************/
-
-/* For as-yet unimplemented I2C interface */
-static void 
-call_i2c_clients(struct usb_ov511 *ov, unsigned int cmd,
-		 void *arg)
-{
-	/* Do nothing */
-}
-
-/*****************************************************************************/
-
-/* Temporarily stops OV511 from functioning. Must do this before changing
- * registers while the camera is streaming */
-static inline int 
-ov51x_stop(struct usb_ov511 *ov)
-{
-	PDEBUG(4, "stopping");
-	ov->stopped = 1;	
-	if (ov->bclass == BCL_OV518)
-		return (reg_w(ov, R51x_SYS_RESET, 0x3a));
-	else
-		return (reg_w(ov, R51x_SYS_RESET, 0x3d));
-}
-
-/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
- * actually stopped (for performance). */
-static inline int 
-ov51x_restart(struct usb_ov511 *ov)
-{
-	if (ov->stopped) {
-		PDEBUG(4, "restarting");
-		ov->stopped = 0;	
-
-		/* Reinitialize the stream */
-		if (ov->bclass == BCL_OV518)
-			reg_w(ov, 0x2f, 0x80);
-
-		return (reg_w(ov, R51x_SYS_RESET, 0x00));
-	}
-
-	return 0;
-}
-
-/* Resets the hardware snapshot button */
-static void 
-ov51x_clear_snapshot(struct usb_ov511 *ov)
-{
-	if (ov->bclass == BCL_OV511) {
-		reg_w(ov, R51x_SYS_SNAP, 0x01);
-		reg_w(ov, R51x_SYS_SNAP, 0x03);
-		reg_w(ov, R51x_SYS_SNAP, 0x01);
-	} else if (ov->bclass == BCL_OV518) {
-		warn("snapshot reset not supported yet on OV518(+)");
-	} else {
-		err("clear snap: invalid bridge type");
-	}
-	
-}
-
-/* Checks the status of the snapshot button. Returns 1 if it was pressed since
- * it was last cleared, and zero in all other cases (including errors) */
-static int 
-ov51x_check_snapshot(struct usb_ov511 *ov)
-{
-	int ret, status = 0;
-
-	if (ov->bclass == BCL_OV511) {
-		ret = reg_r(ov, R51x_SYS_SNAP);
-		if (ret < 0) {
-			err("Error checking snspshot status (%d)", ret);
-		} else if (ret & 0x08) {
-			status = 1;
-		}
-	} else if (ov->bclass == BCL_OV518) {
-		warn("snapshot check not supported yet on OV518(+)");
-	} else {
-		err("check snap: invalid bridge type");
-	}
-
-	return status;
-}
-
-/* This does an initial reset of an OmniVision sensor and ensures that I2C
- * is synchronized. Returns <0 for failure.
- */
-static int 
-init_ov_sensor(struct usb_ov511 *ov)
-{
-	int i, success;
-
-	/* Reset the sensor */ 
-	if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
-
-	/* Wait for it to initialize */ 
-	schedule_timeout (1 + 150 * HZ / 1000);
-
-	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
-		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
-		    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
-			success = 1;
-			continue;
-		}
-
-		/* Reset the sensor */ 
-		if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
-		/* Wait for it to initialize */ 
-		schedule_timeout(1 + 150 * HZ / 1000);
-		/* Dummy read to sync I2C */
-		if (i2c_r(ov, 0x00) < 0) return -EIO;
-	}
-
-	if (!success)
-		return -EIO;
-	
-	PDEBUG(1, "I2C synced in %d attempt(s)", i);
-
-	return 0;
-}
-
-static int 
-ov51x_set_packet_size(struct usb_ov511 *ov, int size)
-{
-	int alt, mult;
-
-	if (ov51x_stop(ov) < 0)
-		return -EIO;
-
-	mult = size >> 5;
-
-	if (ov->bridge == BRG_OV511) {
-		if (size == 0) alt = OV511_ALT_SIZE_0;
-		else if (size == 257) alt = OV511_ALT_SIZE_257;
-		else if (size == 513) alt = OV511_ALT_SIZE_513;
-		else if (size == 769) alt = OV511_ALT_SIZE_769;
-		else if (size == 993) alt = OV511_ALT_SIZE_993;
-		else {
-			err("Set packet size: invalid size (%d)", size);
-			return -EINVAL;
-		}
-	} else if (ov->bridge == BRG_OV511PLUS) {
-		if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
-		else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
-		else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
-		else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;
-		else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;
-		else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;
-		else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;
-		else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;
-		else {
-			err("Set packet size: invalid size (%d)", size);
-			return -EINVAL;
-		}
-	} else if (ov->bclass == BCL_OV518) {
-		if (size == 0) alt = OV518_ALT_SIZE_0;
-		else if (size == 128) alt = OV518_ALT_SIZE_128;
-		else if (size == 256) alt = OV518_ALT_SIZE_256;
-		else if (size == 384) alt = OV518_ALT_SIZE_384;
-		else if (size == 512) alt = OV518_ALT_SIZE_512;
-		else if (size == 640) alt = OV518_ALT_SIZE_640;
-		else if (size == 768) alt = OV518_ALT_SIZE_768;
-		else if (size == 896) alt = OV518_ALT_SIZE_896;
-		else {
-			err("Set packet size: invalid size (%d)", size);
-			return -EINVAL;
-		}
-	} else {
-		err("Set packet size: Invalid bridge type");
-		return -EINVAL;
-	}
-
-	PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
-
-	// FIXME: Don't know how to do this on OV518 yet
-	if (ov->bclass == BCL_OV511) {
-		if (reg_w(ov, R51x_FIFO_PSIZE,
-				    mult) < 0) {
-			return -EIO;
-		}
-	}
-	
-	if (usb_set_interface(ov->dev, ov->iface, alt) < 0) {
-		err("Set packet size: set interface error");
-		return -EBUSY;
-	}
-
-	/* Initialize the stream */
-	if (ov->bclass == BCL_OV518)
-		if (reg_w(ov, 0x2f, 0x80) < 0)
-			return -EIO;
-
-	// FIXME - Should we only reset the FIFO?
-	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
-		return -EIO;
-
-	ov->packet_size = size;
-
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return 0;
-}
-
-/* Upload compression params and quantization tables. Returns 0 for success. */
-static int
-ov511_init_compression(struct usb_ov511 *ov)
-{
-	int rc = 0;
-
-	if (!ov->compress_inited) {
-
-		reg_w(ov, 0x70, phy);
-		reg_w(ov, 0x71, phuv);
-		reg_w(ov, 0x72, pvy);
-		reg_w(ov, 0x73, pvuv);
-		reg_w(ov, 0x74, qhy);
-		reg_w(ov, 0x75, qhuv);
-		reg_w(ov, 0x76, qvy);
-		reg_w(ov, 0x77, qvuv);
-
-		if (ov511_upload_quan_tables(ov) < 0) {
-			err("Error uploading quantization tables");
-			rc = -EIO;
-			goto out;
-		}
-	}
-
-	ov->compress_inited = 1;
-out:	
-	return rc;
-}
-
-/* Upload compression params and quantization tables. Returns 0 for success. */
-static int
-ov518_init_compression(struct usb_ov511 *ov)
-{
-	int rc = 0;
-
-	if (!ov->compress_inited) {
-
-		if (ov518_upload_quan_tables(ov) < 0) {
-			err("Error uploading quantization tables");
-			rc = -EIO;
-			goto out;
-		}
-	}
-
-	ov->compress_inited = 1;
-out:	
-	return rc;
-}
-
-/* -------------------------------------------------------------------------- */
-
-/* Sets sensor's contrast setting to "val" */
-static int
-sensor_set_contrast(struct usb_ov511 *ov, unsigned short val)
-{
-	int rc;
-
-	PDEBUG(3, "%d", val);
-
-	if (ov->stop_during_set)
-		if (ov51x_stop(ov) < 0)
-			return -EIO;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV6620:
-	case SEN_OV6630:
-	{
-		rc = i2c_w(ov, OV7610_REG_CNT, val >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	}
-	case SEN_OV7620:
-	{
-		unsigned char ctab[] = {
-			0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
-			0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
-		};
-
-		/* Use Y gamma control instead. Bit 0 enables it. */
-		rc = i2c_w(ov, 0x64, ctab[val>>12]);
-		if (rc < 0)
-			goto out;
-		break;
-	}
-	case SEN_SAA7111A:
-	{
-		rc = i2c_w(ov, 0x0b, val >> 9);
-		if (rc < 0)
-			goto out;
-		break;
-	}
-	default:
-	{
-		PDEBUG(3, "Unsupported with this sensor");
-		rc = -EPERM;
-		goto out;
-	}
-	}
-
-	rc = 0;		/* Success */
-	ov->contrast = val;
-out:
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return rc;
-}
-
-/* Gets sensor's contrast setting */
-static int
-sensor_get_contrast(struct usb_ov511 *ov, unsigned short *val)
-{
-	int rc;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_r(ov, OV7610_REG_CNT);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc << 8;
-		break;
-	case SEN_OV7620:
-		/* Use Y gamma reg instead. Bit 0 is the enable bit. */
-		rc = i2c_r(ov, 0x64);
-		if (rc < 0)
-			return rc;
-		else
-			*val = (rc & 0xfe) << 8;
-		break;
-	case SEN_SAA7111A:
-		*val = ov->contrast;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		return -EPERM;
-	}
-
-	PDEBUG(3, "%d", *val);
-	ov->contrast = *val;
-
-	return 0;
-}
-
-/* -------------------------------------------------------------------------- */
-
-/* Sets sensor's brightness setting to "val" */
-static int
-sensor_set_brightness(struct usb_ov511 *ov, unsigned short val)
-{
-	int rc;
-
-	PDEBUG(4, "%d", val);
-
-	if (ov->stop_during_set)
-		if (ov51x_stop(ov) < 0)
-			return -EIO;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV7620AE:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	case SEN_OV7620:
-		/* 7620 doesn't like manual changes when in auto mode */
-		if (!ov->auto_brt) {
-			rc = i2c_w(ov, OV7610_REG_BRT, val >> 8);
-			if (rc < 0)
-				goto out;
-		}
-		break;
-	case SEN_SAA7111A:
-		rc = i2c_w(ov, 0x0a, val >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		rc = -EPERM;
-		goto out;
-	}
-
-	rc = 0;		/* Success */
-	ov->brightness = val;
-out:
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return rc;
-}
-
-/* Gets sensor's brightness setting */
-static int
-sensor_get_brightness(struct usb_ov511 *ov, unsigned short *val)
-{
-	int rc;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV7620AE:
-	case SEN_OV7620:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_r(ov, OV7610_REG_BRT);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc << 8;
-		break;
-	case SEN_SAA7111A:
-		*val = ov->brightness;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		return -EPERM;
-	}
-
-	PDEBUG(3, "%d", *val);
-	ov->brightness = *val;
-
-	return 0;
-}
-
-/* -------------------------------------------------------------------------- */
-
-/* Sets sensor's saturation (color intensity) setting to "val" */
-static int
-sensor_set_saturation(struct usb_ov511 *ov, unsigned short val)
-{
-	int rc;
-
-	PDEBUG(3, "%d", val);
-
-	if (ov->stop_during_set)
-		if (ov51x_stop(ov) < 0)
-			return -EIO;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV7620AE:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	case SEN_OV7620:
-//		/* Use UV gamma control instead. Bits 0 & 7 are reserved. */
-//		rc = ov_i2c_write(ov->dev, 0x62, (val >> 9) & 0x7e);
-//		if (rc < 0)
-//			goto out;
-		rc = i2c_w(ov, OV7610_REG_SAT, val >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	case SEN_SAA7111A:
-		rc = i2c_w(ov, 0x0c, val >> 9);
-		if (rc < 0)
-			goto out;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		rc = -EPERM;
-		goto out;
-	}
-
-	rc = 0;		/* Success */
-	ov->colour = val;
-out:
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return rc;
-}
-
-/* Gets sensor's saturation (color intensity) setting */
-static int
-sensor_get_saturation(struct usb_ov511 *ov, unsigned short *val)
-{
-	int rc;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV7620AE:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_r(ov, OV7610_REG_SAT);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc << 8;
-		break;
-	case SEN_OV7620:
-//		/* Use UV gamma reg instead. Bits 0 & 7 are reserved. */
-//		rc = i2c_r(ov, 0x62);
-//		if (rc < 0)
-//			return rc;
-//		else
-//			*val = (rc & 0x7e) << 9;
-		rc = i2c_r(ov, OV7610_REG_SAT);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc << 8;
-		break;
-	case SEN_SAA7111A:
-		*val = ov->colour;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		return -EPERM;
-	}
-
-	PDEBUG(3, "%d", *val);
-	ov->colour = *val;
-
-	return 0;
-}
-
-/* -------------------------------------------------------------------------- */
-
-/* Sets sensor's hue (red/blue balance) setting to "val" */
-static int
-sensor_set_hue(struct usb_ov511 *ov, unsigned short val)
-{
-	int rc;
-
-	PDEBUG(3, "%d", val);
-
-	if (ov->stop_during_set)
-		if (ov51x_stop(ov) < 0)
-			return -EIO;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_w(ov, OV7610_REG_RED, 0xFF - (val >> 8));
-		if (rc < 0)
-			goto out;
-
-		rc = i2c_w(ov, OV7610_REG_BLUE, val >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	case SEN_OV7620:
-// Hue control is causing problems. I will enable it once it's fixed.
-#if 0
-		rc = i2c_w(ov, 0x7a, (unsigned char)(val >> 8) + 0xb);
-		if (rc < 0)
-			goto out;
-
-		rc = i2c_w(ov, 0x79, (unsigned char)(val >> 8) + 0xb);
-		if (rc < 0)
-			goto out;
-#endif
-		break;
-	case SEN_SAA7111A:
-		rc = i2c_w(ov, 0x0d, (val + 32768) >> 8);
-		if (rc < 0)
-			goto out;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		rc = -EPERM;
-		goto out;
-	}
-
-	rc = 0;		/* Success */
-	ov->hue = val;
-out:
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return rc;
-}
-
-/* Gets sensor's hue (red/blue balance) setting */
-static int
-sensor_get_hue(struct usb_ov511 *ov, unsigned short *val)
-{
-	int rc;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = i2c_r(ov, OV7610_REG_BLUE);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc << 8;
-		break;
-	case SEN_OV7620:
-		rc = i2c_r(ov, 0x7a);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc << 8;
-		break;
-	case SEN_SAA7111A:
-		*val = ov->hue;
-		break;
-	default:
-		PDEBUG(3, "Unsupported with this sensor");
-		return -EPERM;
-	}
-
-	PDEBUG(3, "%d", *val);
-	ov->hue = *val;
-
-	return 0;
-}
-
-/* -------------------------------------------------------------------------- */
-
-static inline int
-sensor_set_picture(struct usb_ov511 *ov, struct video_picture *p)
-{
-	int rc;
-
-	PDEBUG(4, "sensor_set_picture");
-
-	ov->whiteness = p->whiteness;
-
-	/* Don't return error if a setting is unsupported, or rest of settings
-         * will not be performed */
-
-	rc = sensor_set_contrast(ov, p->contrast);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_set_brightness(ov, p->brightness);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_set_saturation(ov, p->colour);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_set_hue(ov, p->hue);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	return 0;
-}
-
-static inline int
-sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
-{
-	int rc;
-
-	PDEBUG(4, "sensor_get_picture");
-
-	/* Don't return error if a setting is unsupported, or rest of settings
-         * will not be performed */
-
-	rc = sensor_get_contrast(ov, &(p->contrast));
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_get_brightness(ov, &(p->brightness));
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_get_saturation(ov, &(p->colour));
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_get_hue(ov, &(p->hue));
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	p->whiteness = 105 << 8;
-
-	/* Can we get these from frame[0]? -claudio? */
-	p->depth = ov->frame[0].depth;
-	p->palette = ov->frame[0].format;
-
-	return 0;
-}
-
-// FIXME: Exposure range is only 0x00-0x7f in interlace mode
-/* Sets current exposure for sensor. This only has an effect if auto-exposure
- * is off */
-static inline int
-sensor_set_exposure(struct usb_ov511 *ov, unsigned char val)
-{
-	int rc;
-
-	PDEBUG(3, "%d", val);
-
-	if (ov->stop_during_set)
-		if (ov51x_stop(ov) < 0)
-			return -EIO;
-
-	switch (ov->sensor) {
-	case SEN_OV6620:
-	case SEN_OV6630:
-	case SEN_OV7610:
-	case SEN_OV7620:
-	case SEN_OV7620AE:
-	case SEN_OV8600:
-		rc = i2c_w(ov, 0x10, val);
-		if (rc < 0)
-			goto out;
-
-		break;
-	case SEN_KS0127:
-	case SEN_KS0127B:
-	case SEN_SAA7111A:
-		PDEBUG(3, "Unsupported with this sensor");
-		return -EPERM;
-	default:
-		err("Sensor not supported for set_exposure");
-		return -EINVAL;
-	}
-
-	rc = 0;		/* Success */
-	ov->exposure = val;
-out:
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return rc;
-}
-
-/* Gets current exposure level from sensor, regardless of whether it is under
- * manual control. */
-static int
-sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val)
-{
-	int rc;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV6620:
-	case SEN_OV6630:
-	case SEN_OV7620:
-	case SEN_OV7620AE:
-	case SEN_OV8600:
-		rc = i2c_r(ov, 0x10);
-		if (rc < 0)
-			return rc;
-		else
-			*val = rc;
-		break;
-	case SEN_KS0127:
-	case SEN_KS0127B:
-	case SEN_SAA7111A:
-		val = 0;
-		PDEBUG(3, "Unsupported with this sensor");
-		return -EPERM;
-	default:
-		err("Sensor not supported for get_exposure");
-		return -EINVAL;
-	}
-
-	PDEBUG(3, "%d", *val);
-	ov->exposure = *val;
-
-	return 0;
-}
-
-/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
-static inline void 
-ov51x_led_control(struct usb_ov511 *ov, int enable)
-{
-	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
-
-	if (ov->bridge == BRG_OV511PLUS)
-		reg_w(ov, R511_SYS_LED_CTL, enable ? 1 : 0);
-	else if (ov->bclass == BCL_OV518)
-		reg_w_mask(ov, R518_GPIO_OUT, enable ? 0x02 : 0x00, 0x02);
-
-	return;
-}
-
-/* Matches the sensor's internal frame rate to the lighting frequency.
- * Valid frequencies are:
- *	50 - 50Hz, for European and Asian lighting
- *	60 - 60Hz, for American lighting
- *
- * Tested with: OV7610, OV7620, OV7620AE, OV6620
- * Unsupported: KS0127, KS0127B, SAA7111A
- * Returns: 0 for success
- */
-static int
-sensor_set_light_freq(struct usb_ov511 *ov, int freq)
-{
-	int sixty;
-
-	PDEBUG(4, "%d Hz", freq);
-
-	if (freq == 60)
-		sixty = 1;
-	else if (freq == 50)
-		sixty = 0;
-	else {
-		err("Invalid light freq (%d Hz)", freq);
-		return -EINVAL;
-	}
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-		i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
-		i2c_w(ov, 0x2b, sixty?0x00:0xac);
-		i2c_w_mask(ov, 0x13, 0x10, 0x10);
-		i2c_w_mask(ov, 0x13, 0x00, 0x10);
-		break;
-	case SEN_OV7620:
-	case SEN_OV7620AE:
-	case SEN_OV8600:
-		i2c_w_mask(ov, 0x2a, sixty?0x00:0x80, 0x80);
-		i2c_w(ov, 0x2b, sixty?0x00:0xac);
-		i2c_w_mask(ov, 0x76, 0x01, 0x01);
-		break;		
-	case SEN_OV6620:
-	case SEN_OV6630:
-		i2c_w(ov, 0x2b, sixty?0xa8:0x28);
-		i2c_w(ov, 0x2a, sixty?0x84:0xa4);
-		break;
-	case SEN_KS0127:
-	case SEN_KS0127B:
-	case SEN_SAA7111A:
-		PDEBUG(5, "Unsupported with this sensor");
-		return -EPERM;
-	default:
-		err("Sensor not supported for set_light_freq");
-		return -EINVAL;
-	}
-
-	ov->lightfreq = freq;
-
-	return 0;
-}
-
-/* If enable is true, turn on the sensor's banding filter, otherwise turn it
- * off. This filter tries to reduce the pattern of horizontal light/dark bands
- * caused by some (usually fluorescent) lighting. The light frequency must be
- * set either before or after enabling it with ov51x_set_light_freq().
- *
- * Tested with: OV7610, OV7620, OV7620AE, OV6620.
- * Unsupported: KS0127, KS0127B, SAA7111A
- * Returns: 0 for success
- */
-static inline int
-sensor_set_banding_filter(struct usb_ov511 *ov, int enable)
-{
-	int rc;
-
-	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
-
-	if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
-		|| ov->sensor == SEN_SAA7111A) {
-		PDEBUG(5, "Unsupported with this sensor");
-		return -EPERM;
-	}
-
-	rc = i2c_w_mask(ov, 0x2d, enable?0x04:0x00, 0x04);
-	if (rc < 0)
-		return rc;
-
-	ov->bandfilt = enable;
-
-	return 0;
-}
-
-/* If enable is true, turn on the sensor's auto brightness control, otherwise
- * turn it off.
- *
- * Unsupported: KS0127, KS0127B, SAA7111A
- * Returns: 0 for success
- */
-static inline int
-sensor_set_auto_brightness(struct usb_ov511 *ov, int enable)
-{
-	int rc;
-
-	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
-
-	if (ov->sensor == SEN_KS0127 || ov->sensor == SEN_KS0127B
-		|| ov->sensor == SEN_SAA7111A) {
-		PDEBUG(5, "Unsupported with this sensor");
-		return -EPERM;
-	}
-
-	rc = i2c_w_mask(ov, 0x2d, enable?0x10:0x00, 0x10);
-	if (rc < 0)
-		return rc;
-
-	ov->auto_brt = enable;
-
-	return 0;
-}
-
-/* If enable is true, turn on the sensor's auto exposure control, otherwise
- * turn it off.
- *
- * Unsupported: KS0127, KS0127B, SAA7111A
- * Returns: 0 for success
- */
-static inline int
-sensor_set_auto_exposure(struct usb_ov511 *ov, int enable)
-{	
-	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-		i2c_w_mask(ov, 0x29, enable?0x00:0x80, 0x80);
-		break;
-	case SEN_OV6620:
-	case SEN_OV7620:
-	case SEN_OV7620AE:
-	case SEN_OV8600:
-		i2c_w_mask(ov, 0x13, enable?0x01:0x00, 0x01);
-		break;		
-	case SEN_OV6630:
-		i2c_w_mask(ov, 0x28, enable?0x00:0x10, 0x10);
-		break;
-	case SEN_KS0127:
-	case SEN_KS0127B:
-	case SEN_SAA7111A:
-		PDEBUG(5, "Unsupported with this sensor");
-		return -EPERM;
-	default:
-		err("Sensor not supported for set_auto_exposure");
-		return -EINVAL;
-	}
-
-	ov->auto_exp = enable;
-
-	return 0;
-}
-
-/* Modifies the sensor's exposure algorithm to allow proper exposure of objects
- * that are illuminated from behind.
- *
- * Tested with: OV6620, OV7620
- * Unsupported: OV7610, OV7620AE, KS0127, KS0127B, SAA7111A
- * Returns: 0 for success
- */
-static int
-sensor_set_backlight(struct usb_ov511 *ov, int enable)
-{
-
-	PDEBUG(4, " (%s)", enable ? "turn on" : "turn off");
-
-	switch (ov->sensor) {
-	case SEN_OV7620:
-	case SEN_OV8600:
-		i2c_w_mask(ov, 0x68, enable?0xe0:0xc0, 0xe0);
-		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
-		i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
-		break;		
-	case SEN_OV6620:
-		i2c_w_mask(ov, 0x4e, enable?0xe0:0xc0, 0xe0);
-		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
-		i2c_w_mask(ov, 0x0e, enable?0x80:0x00, 0x80);
-		break;
-	case SEN_OV6630:
-		i2c_w_mask(ov, 0x4e, enable?0x80:0x60, 0xe0);
-		i2c_w_mask(ov, 0x29, enable?0x08:0x00, 0x08);
-		i2c_w_mask(ov, 0x28, enable?0x02:0x00, 0x02);
-		break;
-	case SEN_OV7610:
-	case SEN_OV7620AE:
-	case SEN_KS0127:
-	case SEN_KS0127B:
-	case SEN_SAA7111A:
-		PDEBUG(5, "Unsupported with this sensor");
-		return -EPERM;
-	default:
-		err("Sensor not supported for set_backlight");
-		return -EINVAL;
-	}
-
-	ov->backlight = enable;
-
-	return 0;
-}
-
-/* Returns number of bits per pixel (regardless of where they are located;
- * planar or not), or zero for unsupported format.
- */
-static inline int 
-get_depth(int palette)
-{
-	switch (palette) {
-	case VIDEO_PALETTE_GREY:    return 8;
-	case VIDEO_PALETTE_YUV420:  return 12;
-	case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
-	case VIDEO_PALETTE_RGB565:  return 16;
-	case VIDEO_PALETTE_RGB24:   return 24;  
-	case VIDEO_PALETTE_YUV422:  return 16;
-	case VIDEO_PALETTE_YUYV:    return 16;
-	case VIDEO_PALETTE_YUV422P: return 16; /* Planar */
-	default:		    return 0;  /* Invalid format */
-	}
-}
-
-/* Bytes per frame. Used by read(). Return of 0 indicates error */
-static inline long int 
-get_frame_length(struct ov511_frame *frame)
-{
-	if (!frame)
-		return 0;
-	else
-		return ((frame->width * frame->height
-			 * get_depth(frame->format)) >> 3);
-}
-
-static int
-mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
-			 int mode, int sub_flag, int qvga)
-{
-	int clock;
-
-	/******** Mode (VGA/QVGA) and sensor specific regs ********/
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-		i2c_w(ov, 0x14, qvga?0x24:0x04);
-// FIXME: Does this improve the image quality or frame rate?
-#if 0
-		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
-		i2c_w(ov, 0x24, 0x10);
-		i2c_w(ov, 0x25, qvga?0x40:0x8a);
-		i2c_w(ov, 0x2f, qvga?0x30:0xb0);
-		i2c_w(ov, 0x35, qvga?0x1c:0x9c);
-#endif
-		break;
-	case SEN_OV7620:
-//		i2c_w(ov, 0x2b, 0x00);
-		i2c_w(ov, 0x14, qvga?0xa4:0x84);
-		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
-		i2c_w(ov, 0x24, qvga?0x20:0x3a);
-		i2c_w(ov, 0x25, qvga?0x30:0x60);
-		i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
-		i2c_w_mask(ov, 0x67, qvga?0xf0:0x90, 0xf0);
-		i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
-		break;
-	case SEN_OV7620AE:
-//		i2c_w(ov, 0x2b, 0x00);
-		i2c_w(ov, 0x14, qvga?0xa4:0x84);
-// FIXME: Enable this once 7620AE uses 7620 initial settings
-#if 0
-		i2c_w_mask(ov, 0x28, qvga?0x00:0x20, 0x20);
-		i2c_w(ov, 0x24, qvga?0x20:0x3a);
-		i2c_w(ov, 0x25, qvga?0x30:0x60);
-		i2c_w_mask(ov, 0x2d, qvga?0x40:0x00, 0x40);
-		i2c_w_mask(ov, 0x67, qvga?0xb0:0x90, 0xf0);
-		i2c_w_mask(ov, 0x74, qvga?0x20:0x00, 0x20);
-#endif
-		break;
-	case SEN_OV6620:
-	case SEN_OV6630:
-		i2c_w(ov, 0x14, qvga?0x24:0x04);
-		/* No special settings yet */
-		break;
-	default:
-		err("Invalid sensor");
-		return -EINVAL;
-	}
-
-	/******** Palette-specific regs ********/
-
-	if (mode == VIDEO_PALETTE_GREY) {
-		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
-			/* these aren't valid on the OV6620/OV7620/6630? */
-			i2c_w_mask(ov, 0x0e, 0x40, 0x40);
-		}
-		i2c_w_mask(ov, 0x13, 0x20, 0x20);
-	} else {
-		if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
-			/* not valid on the OV6620/OV7620/6630? */
-			i2c_w_mask(ov, 0x0e, 0x00, 0x40);
-		}
-		i2c_w_mask(ov, 0x13, 0x00, 0x20);
-	}
-
-	/******** Clock programming ********/
-
-	// FIXME: Test this with OV6630
-
-	/* The OV6620 needs special handling. This prevents the 
-	 * severe banding that normally occurs */
-	if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630)
-	{
-		/* Clock down */
-
-		i2c_w(ov, 0x2a, 0x04);
-
-		if (ov->compress) {
-//			clock = 0;    /* This ensures the highest frame rate */
-			clock = 3;
-		} else if (clockdiv == -1) {   /* If user didn't override it */
-			clock = 3;    /* Gives better exposure time */
-		} else {
-			clock = clockdiv;
-		}
-
-		PDEBUG(4, "Setting clock divisor to %d", clock);
-
-		i2c_w(ov, 0x11, clock);
-
-		i2c_w(ov, 0x2a, 0x84);
-		/* This next setting is critical. It seems to improve
-		 * the gain or the contrast. The "reserved" bits seem
-		 * to have some effect in this case. */
-		i2c_w(ov, 0x2d, 0x85);
-	}
-	else
-	{
-		if (ov->compress) {
-			clock = 1;    /* This ensures the highest frame rate */
-		} else if (clockdiv == -1) {   /* If user didn't override it */
-			/* Calculate and set the clock divisor */
-			clock = ((sub_flag ? ov->subw * ov->subh
-				  : width * height)
-				 * (mode == VIDEO_PALETTE_GREY ? 2 : 3) / 2)
-				 / 66000;
-		} else {
-			clock = clockdiv;
-		}
-
-		PDEBUG(4, "Setting clock divisor to %d", clock);
-
-		i2c_w(ov, 0x11, clock);
-	}
-
-	/******** Special Features ********/
-
-	if (framedrop >= 0)
-		i2c_w(ov, 0x16, framedrop);
-
-	/* We only have code to convert GBR -> RGB24 */
-	if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
-		i2c_w_mask(ov, 0x12, 0x08, 0x08);
-	else
-		i2c_w_mask(ov, 0x12, 0x00, 0x08);
-
-	/* Test Pattern */
-	i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02);
-
-	/* Auto white balance */
-//	if (awb)
-		i2c_w_mask(ov, 0x12, 0x04, 0x04);
-//	else
-//		i2c_w_mask(ov, 0x12, 0x00, 0x04);
-
-	// This will go away as soon as ov51x_mode_init_sensor_regs()
-	// is fully tested.
-	/* 7620/6620/6630? don't have register 0x35, so play it safe */
-	if (ov->sensor == SEN_OV7610 || ov->sensor == SEN_OV7620AE) {
-		if (width == 640 && height == 480)
-			i2c_w(ov, 0x35, 0x9e);
-		else
-			i2c_w(ov, 0x35, 0x1e);
-	}
-
-	return 0;
-}
-
-static int
-set_ov_sensor_window(struct usb_ov511 *ov, int width, int height, int mode,
-		     int sub_flag)
-{
-	int ret;
-	int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; 
-	int hoffset, voffset, hwscale = 0, vwscale = 0;
-
-	/* The different sensor ICs handle setting up of window differently.
-	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!!! */
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV7620AE:
-		hwsbase = 0x38;
-		hwebase = 0x3a;
-		vwsbase = vwebase = 0x05;
-		break;
-	case SEN_OV6620:
-	case SEN_OV6630:	// FIXME: Is this right?
-		hwsbase = 0x38;
-		hwebase = 0x3a;
-		vwsbase = 0x05;
-		vwebase = 0x06;
-		break;
-	case SEN_OV7620:
-		hwsbase = 0x2f;		/* From 7620.SET (spec is wrong) */
-		hwebase = 0x2f;
-		vwsbase = vwebase = 0x05;
-		break;
-	default:
-		err("Invalid sensor");
-		return -EINVAL;
-	}
-
-	if (ov->sensor == SEN_OV6620 || ov->sensor == SEN_OV6630) {
-		if (width > 176 && height > 144) {  /* CIF */
-			ret = mode_init_ov_sensor_regs(ov, width, height,
-				mode, sub_flag, 0);
-			if (ret < 0)
-				return ret;
-			hwscale = 1;
-			vwscale = 1;  /* The datasheet says 0; it's wrong */
-			hwsize = 352;
-			vwsize = 288;
-		} else if (width > 176 || height > 144) {
-			err("Illegal dimensions");
-			return -EINVAL;
-		} else {			    /* QCIF */
-			ret = mode_init_ov_sensor_regs(ov, width, height,
-				mode, sub_flag, 1);
-			if (ret < 0)
-				return ret;
-			hwsize = 176;
-			vwsize = 144;
-		}
-	} else {
-		if (width > 320 && height > 240) {  /* VGA */
-			ret = mode_init_ov_sensor_regs(ov, width, height,
-				mode, sub_flag, 0);
-			if (ret < 0)
-				return ret;
-			hwscale = 2;
-			vwscale = 1;
-			hwsize = 640;
-			vwsize = 480;
-		} else if (width > 320 || height > 240) {
-			err("Illegal dimensions");
-			return -EINVAL;
-		} else {			    /* QVGA */
-			ret = mode_init_ov_sensor_regs(ov, width, height,
-				mode, sub_flag, 1);
-			if (ret < 0)
-				return ret;
-			hwscale = 1;
-			hwsize = 320;
-			vwsize = 240;
-		}
-	}
-
-	/* Center the window */
-	hoffset = ((hwsize - width) / 2) >> hwscale;
-	voffset = ((vwsize - height) / 2) >> vwscale;
-
-	/* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
-	if (sub_flag) {
-		i2c_w(ov, 0x17, hwsbase+(ov->subx>>hwscale));
-		i2c_w(ov, 0x18,	hwebase+((ov->subx+ov->subw)>>hwscale));
-		i2c_w(ov, 0x19, vwsbase+(ov->suby>>vwscale));
-		i2c_w(ov, 0x1a, vwebase+((ov->suby+ov->subh)>>vwscale));
-	} else {
-		i2c_w(ov, 0x17, hwsbase + hoffset);
-		i2c_w(ov, 0x18, hwebase + hoffset + (hwsize>>hwscale));
-		i2c_w(ov, 0x19, vwsbase + voffset);
-		i2c_w(ov, 0x1a, vwebase + voffset + (vwsize>>vwscale));
-	}
-
-#ifdef OV511_DEBUG
-	if (dump_sensor)
-		dump_i2c_regs(ov);
-#endif
-
-	return 0;
-}
-
-/* Set up the OV511/OV511+ with the given image parameters.
- *
- * Do not put any sensor-specific code in here (including I2C I/O functions)
- */
-static int
-ov511_mode_init_regs(struct usb_ov511 *ov,
-		     int width, int height, int mode, int sub_flag)
-{
-	int lncnt, pxcnt, rc = 0;
-
-	if (sub_flag) {
-		width = ov->subw;
-		height = ov->subh;
-	}
-
-	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
-	       width, height, mode, sub_flag);
-
-	// FIXME: This should be moved to a 7111a-specific function once
-	// subcapture is dealt with properly
-	if (ov->sensor == SEN_SAA7111A) {
-		if (width == 320 && height == 240) {
-			/* No need to do anything special */
-		} else if (width == 640 && height == 480) {
-			/* Set the OV511 up as 320x480, but keep the V4L
-			 * resolution as 640x480 */
-			width = 320;
-		} else {
-			err("SAA7111A only supports 320x240 or 640x480");
-			return -EINVAL;
-		}
-	}
-
-	/* Make sure width and height are a multiple of 8 */
-	if (width % 8 || height % 8) {
-		err("Invalid size (%d, %d) (mode = %d)", width, height, mode);
-		return -EINVAL;
-	}
-
-	if (width < ov->minwidth || height < ov->minheight) {
-		err("Requested dimensions are too small");
-		return -EINVAL;
-	}
-
-	if (ov51x_stop(ov) < 0)
-		return -EIO;
-
-	if (mode == VIDEO_PALETTE_GREY) {
-		reg_w(ov, R511_CAM_UV_EN, 0x00);
-		reg_w(ov, R511_SNAP_UV_EN, 0x00);
-		reg_w(ov, R511_SNAP_OPTS, 0x01);
-	} else {
-		reg_w(ov, R511_CAM_UV_EN, 0x01);
-		reg_w(ov, R511_SNAP_UV_EN, 0x01);
-		reg_w(ov, R511_SNAP_OPTS, 0x03);
-	}
-
-	/* Here I'm assuming that snapshot size == image size.
-	 * I hope that's always true. --claudio
-	 */
-	pxcnt = (width >> 3) - 1;
-	lncnt = (height >> 3) - 1;
-
-	reg_w(ov, R511_CAM_PXCNT, pxcnt);
-	reg_w(ov, R511_CAM_LNCNT, lncnt);
-	reg_w(ov, R511_CAM_PXDIV, 0x00);
-	reg_w(ov, R511_CAM_LNDIV, 0x00);
-
-	/* YUV420, low pass filer on */
-	reg_w(ov, R511_CAM_OPTS, 0x03);
-
-	/* Snapshot additions */
-	reg_w(ov, R511_SNAP_PXCNT, pxcnt);
-	reg_w(ov, R511_SNAP_LNCNT, lncnt);
-	reg_w(ov, R511_SNAP_PXDIV, 0x00);
-	reg_w(ov, R511_SNAP_LNDIV, 0x00);
-
-	if (ov->compress) {
-		/* Enable Y and UV quantization and compression */
-		reg_w(ov, R511_COMP_EN, 0x07);
-		reg_w(ov, R511_COMP_LUT_EN, 0x03);
-		ov51x_reset(ov, OV511_RESET_OMNICE);
-	}
-//out:
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	return rc;
-}
-
-static struct mode_list_518 mlist518[] = {
-	/* W    H   reg28 reg29 reg2a reg2c reg2e reg24 reg25 */
-	{ 352, 288, 0x00, 0x16, 0x48, 0x00, 0x00, 0x9f, 0x90 },
-	{ 320, 240, 0x00, 0x14, 0x3c, 0x10, 0x18, 0x9f, 0x90 },
-	{ 176, 144, 0x05, 0x0b, 0x24, 0x00, 0x00, 0xff, 0xf0 },
-	{ 160, 120, 0x05, 0x0a, 0x1e, 0x08, 0x0c, 0xff, 0xf0 },
-	{ 0, 0 }
-};
-
-/* Sets up the OV518/OV518+ with the given image parameters
- *
- * OV518 needs a completely different approach, until we can figure out what
- * the individual registers do. Many register ops are commented out until we
- * can find out if they are still valid. Also, only 15 FPS is supported now.
- *
- * Do not put any sensor-specific code in here (including I2C I/O functions)
- */
-static int
-ov518_mode_init_regs(struct usb_ov511 *ov,
-		     int width, int height, int mode, int sub_flag)
-{
-	int i;
-
-	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
-	       width, height, mode, sub_flag);
-
-	if (ov51x_stop(ov) < 0)
-		return -EIO;
-
-	for (i = 0; mlist518[i].width; i++) {
-//		int lncnt, pxcnt;
-
-		if (width != mlist518[i].width || height != mlist518[i].height)
-			continue;
-
-// FIXME: Subcapture won't be possible until we know what the registers do
-// FIXME: We can't handle anything but YUV420 so far
-
-//		/* Here I'm assuming that snapshot size == image size.
-//		 * I hope that's always true. --claudio
-//		 */
-//		pxcnt = sub_flag ? (ov->subw >> 3) - 1 : mlist[i].pxcnt;
-//		lncnt = sub_flag ? (ov->subh >> 3) - 1 : mlist[i].lncnt;
-//
-//		reg_w(ov, 0x12, pxcnt);
-//		reg_w(ov, 0x13, lncnt);
-
-		/******** Set the mode ********/		
-
-		/* Mode independent regs */
-		reg_w(ov, 0x2b, 0x00);
-		reg_w(ov, 0x2d, 0x00);
-		reg_w(ov, 0x3b, 0x00);
-		reg_w(ov, 0x3d, 0x00);
-
-		/* Mode dependent regs. Regs 38 - 3e are always the same as
-		 * regs 28 - 2e */
-		reg_w_mask(ov, 0x28, mlist518[i].reg28
-			| (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
-		reg_w(ov, 0x29, mlist518[i].reg29);
-		reg_w(ov, 0x2a, mlist518[i].reg2a);
-		reg_w(ov, 0x2c, mlist518[i].reg2c);
-		reg_w(ov, 0x2e, mlist518[i].reg2e);
-		reg_w_mask(ov, 0x38, mlist518[i].reg28 
-			| (mode == VIDEO_PALETTE_GREY) ? 0x80:0x00, 0x8f);
-		reg_w(ov, 0x39, mlist518[i].reg29);
-		reg_w(ov, 0x3a, mlist518[i].reg2a);
-		reg_w(ov, 0x3c, mlist518[i].reg2c);
-		reg_w(ov, 0x3e, mlist518[i].reg2e);
-		reg_w(ov, 0x24, mlist518[i].reg24);
-		reg_w(ov, 0x25, mlist518[i].reg25);
-
-		/* Windows driver does this here; who knows why */
-		reg_w(ov, 0x2f, 0x80);
-
-		/******** Set the framerate (to 15 FPS) ********/		
-
-		/* Mode independent, but framerate dependent, regs */
-		/* These are for 15 FPS only */
-		reg_w(ov, 0x51, 0x08);
-		reg_w(ov, 0x22, 0x18);
-		reg_w(ov, 0x23, 0xff);
-		reg_w(ov, 0x71, 0x19);  /* Compression-related? */
-
-		// FIXME: Sensor-specific
-		/* Bit 5 is what matters here. Of course, it is "reserved" */
-		i2c_w(ov, 0x54, 0x23);
-
-		reg_w(ov, 0x2f, 0x80);
-
-		/* Mode dependent regs */
-		if ((width == 352 && height == 288) ||
-		    (width == 320 && height == 240)) {
-			/*  640 (280h) byte iso packets */
-			ov518_reg_w32(ov, 0x30,    640, 2);	/* 280h   */
-			ov518_reg_w32(ov, 0xc4,    400, 2);	/* 190h   */
-			ov518_reg_w32(ov, 0xc6,    500, 2);	/* 1f4h   */
-			ov518_reg_w32(ov, 0xc7,    500, 2);	/* 1f4h   */
-			ov518_reg_w32(ov, 0xc8,    142, 2);	/* 8eh    */
-			ov518_reg_w32(ov, 0xca, 131098, 3);	/* 2001ah */
-			ov518_reg_w32(ov, 0xcb,    532, 2);	/* 214h   */
-			ov518_reg_w32(ov, 0xcc,   2000, 2);	/* 7d0h   */
-			ov518_reg_w32(ov, 0xcd,     32, 2);	/* 20h    */
-			ov518_reg_w32(ov, 0xce,    608, 2);	/* 260h   */
-		} else if ((width == 176 && height == 144) ||
-			   (width == 160 && height == 120)) {
-			/*  384 (180h) byte iso packets */
-			ov518_reg_w32(ov, 0x30,    384, 2);	/* 180h   */
-			ov518_reg_w32(ov, 0xc4,    200, 2);	/* c8h    */
-			ov518_reg_w32(ov, 0xc6,    320, 2);	/* 140h   */
-			ov518_reg_w32(ov, 0xc7,    320, 2);	/* 140h   */
-			ov518_reg_w32(ov, 0xc8,     96, 2);	/* 60h    */
-			ov518_reg_w32(ov, 0xca,  78607, 3);	/* 1330fh */
-			ov518_reg_w32(ov, 0xcb,    320, 2);	/* 140h   */
-			ov518_reg_w32(ov, 0xcc,   1260, 2);	/* 4ech   */
-			ov518_reg_w32(ov, 0xcd,     19, 2);	/* 13h    */
-			ov518_reg_w32(ov, 0xce,    365, 2);	/* 16dh   */
-		} else {
-			/* Can't happen, since we already handled this case */
-			err("ov518_mode_init_regs(): **** logic error ****");
-		}
-
-		reg_w(ov, 0x2f, 0x80);
-
-		break;
-	}
-
-	if (ov51x_restart(ov) < 0)
-		return -EIO;
-
-	/* Reset it just for good measure */
-	if (ov51x_reset(ov, OV511_RESET_NOREGS) < 0)
-		return -EIO;
-
-	if (mlist518[i].width == 0) {
-		err("Unknown mode (%d, %d): %d", width, height, mode);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* This is a wrapper around the OV511, OV518, and sensor specific functions */
-static int
-mode_init_regs(struct usb_ov511 *ov,
-	       int width, int height, int mode, int sub_flag)
-{
-	int rc = 0;
-
-	if (!ov || !ov->dev)
-		return -EFAULT;
-
-	if (ov->bclass == BCL_OV518) {
-		rc = ov518_mode_init_regs(ov, width, height, mode, sub_flag);
-	} else {
-		rc = ov511_mode_init_regs(ov, width, height, mode, sub_flag);
-	}
-
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	switch (ov->sensor) {
-	case SEN_OV7610:
-	case SEN_OV7620:
-	case SEN_OV7620AE:
-	case SEN_OV8600:
-	case SEN_OV6620:
-	case SEN_OV6630:
-		rc = set_ov_sensor_window(ov, width, height, mode, sub_flag);
-		break;
-	case SEN_KS0127:
-	case SEN_KS0127B:
-		err("KS0127-series decoders not supported yet");
-		rc = -EINVAL;
-		break;
-	case SEN_SAA7111A:
-//		rc = mode_init_saa_sensor_regs(ov, width, height, mode, 
-//					       sub_flag);
-
-		PDEBUG(1, "SAA status = 0X%x", i2c_r(ov, 0x1f));
-		break;
-	default:
-		err("Unknown sensor");
-		rc = -EINVAL;
-	}
-
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	/* Sensor-independent settings */
-	rc = sensor_set_auto_brightness(ov, ov->auto_brt);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_set_auto_exposure(ov, ov->auto_exp);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	rc = sensor_set_banding_filter(ov, bandingfilter);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	if (ov->lightfreq) {
-		rc = sensor_set_light_freq(ov, lightfreq);
-		if (FATAL_ERROR(rc))
-			return rc;
-	}
-
-	rc = sensor_set_backlight(ov, ov->backlight);
-	if (FATAL_ERROR(rc))
-		return rc;
-
-	return 0;
-}
-
-/* This sets the default image parameters (Size = max, RGB24). This is
- * useful for apps that use read() and do not set these.
- */
-static int 
-ov51x_set_default_params(struct usb_ov511 *ov)
-{
-	int i;
-
-	PDEBUG(3, "%dx%d, RGB24", ov->maxwidth, ov->maxheight);
-
-	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
-	 * (using read() instead). */
-	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov->frame[i].width = ov->maxwidth;
-		ov->frame[i].height = ov->maxheight;
-		ov->frame[i].bytes_read = 0;
-		if (force_palette)
-			ov->frame[i].format = force_palette;
-		else
-			ov->frame[i].format = VIDEO_PALETTE_RGB24;
-		ov->frame[i].depth = get_depth(ov->frame[i].format);
-	}
-
-	/* Initialize to max width/height, RGB24 */
-	if (mode_init_regs(ov, ov->maxwidth, ov->maxheight,
-			   ov->frame[0].format, 0) < 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**********************************************************************
- *
- * Video decoder stuff
- *
- **********************************************************************/
-
-/* Set analog input port of decoder */
-static int 
-decoder_set_input(struct usb_ov511 *ov, int input)
-{
-	PDEBUG(4, "port %d", input);
-
-	switch (ov->sensor) {
-	case SEN_SAA7111A:
-	{
-		/* Select mode */
-		i2c_w_mask(ov, 0x02, input, 0x07);
-		/* Bypass chrominance trap for modes 4..7 */
-		i2c_w_mask(ov, 0x09, (input > 3) ? 0x80:0x00, 0x80);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* Get ASCII name of video input */
-static int 
-decoder_get_input_name(struct usb_ov511 *ov, int input, char *name)
-{
-	switch (ov->sensor) {
-	case SEN_SAA7111A:
-	{
-		if (input < 0 || input > 7)
-			return -EINVAL;
-		else if (input < 4)
-			sprintf(name, "CVBS-%d", input);
-		else // if (input < 8)
-			sprintf(name, "S-Video-%d", input - 4);
-
-		break;
-	}
-	default:
-		sprintf(name, "%s", "Camera");
-	}
-
-	return 0;
-}
-
-/* Set norm (NTSC, PAL, SECAM, AUTO) */
-static int 
-decoder_set_norm(struct usb_ov511 *ov, int norm)
-{
-	PDEBUG(4, "%d", norm);
-
-	switch (ov->sensor) {
-	case SEN_SAA7111A:
-	{
-		int reg_8, reg_e;
-
-		if (norm == VIDEO_MODE_NTSC) {
-			reg_8 = 0x40;	/* 60 Hz */
-			reg_e = 0x00;	/* NTSC M / PAL BGHI */
-		} else if (norm == VIDEO_MODE_PAL) {
-			reg_8 = 0x00;	/* 50 Hz */
-			reg_e = 0x00;	/* NTSC M / PAL BGHI */	
-		} else if (norm == VIDEO_MODE_AUTO) {
-			reg_8 = 0x80;	/* Auto field detect */
-			reg_e = 0x00;	/* NTSC M / PAL BGHI */
-		} else if (norm == VIDEO_MODE_SECAM) {
-			reg_8 = 0x00;	/* 50 Hz */
-			reg_e = 0x50;	/* SECAM / PAL 4.43 */
-		} else {
-			return -EINVAL;
-		}
-
-		i2c_w_mask(ov, 0x08, reg_8, 0xc0);
-		i2c_w_mask(ov, 0x0e, reg_e, 0x70);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-
-/**********************************************************************
- *
- * Color correction functions
- *
- **********************************************************************/
-
-/*
- * Turn a YUV4:2:0 block into an RGB block
- *
- * Video4Linux seems to use the blue, green, red channel
- * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
- *
- * Color space conversion coefficients taken from the excellent
- * http://www.inforamp.net/~poynton/ColorFAQ.html
- * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
- * Y values are given for all 4 pixels, but the U (Pb)
- * and V (Pr) are assumed constant over the 2x2 block.
- *
- * To avoid floating point arithmetic, the color conversion
- * coefficients are scaled into 16.16 fixed-point integers.
- * They were determined as follows:
- *
- *	double brightness = 1.0;  (0->black; 1->full scale) 
- *	double saturation = 1.0;  (0->greyscale; 1->full color)
- *	double fixScale = brightness * 256 * 256;
- *	int rvScale = (int)(1.402 * saturation * fixScale);
- *	int guScale = (int)(-0.344136 * saturation * fixScale);
- *	int gvScale = (int)(-0.714136 * saturation * fixScale);
- *	int buScale = (int)(1.772 * saturation * fixScale);
- *	int yScale = (int)(fixScale);	
- */
-
-/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
-#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
-
-static inline void
-move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
-	       int rowPixels, unsigned char * rgb, int bits)
-{
-	const int rvScale = 91881;
-	const int guScale = -22553;
-	const int gvScale = -46801;
-	const int buScale = 116129;
-	const int yScale  = 65536;
-	int r, g, b;
-
-	g = guScale * u + gvScale * v;
-	if (force_rgb) {
-		r = buScale * u;
-		b = rvScale * v;
-	} else {
-		r = rvScale * v;
-		b = buScale * u;
-	}
-
-	yTL *= yScale; yTR *= yScale;
-	yBL *= yScale; yBR *= yScale;
-
-	if (bits == 24) {
-		/* Write out top two pixels */
-		rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
-		rgb[2] = LIMIT(r+yTL);
-
-		rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
-		rgb[5] = LIMIT(r+yTR);
-
-		/* Skip down to next line to write out bottom two pixels */
-		rgb += 3 * rowPixels;
-		rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
-		rgb[2] = LIMIT(r+yBL);
-
-		rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
-		rgb[5] = LIMIT(r+yBR);
-	} else if (bits == 16) {
-		/* Write out top two pixels */
-		rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) 
-			| ((LIMIT(g+yTL) << 3) & 0xE0);
-		rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07)
-			| (LIMIT(r+yTL) & 0xF8);
-
-		rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) 
-			| ((LIMIT(g+yTR) << 3) & 0xE0);
-		rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) 
-			| (LIMIT(r+yTR) & 0xF8);
-
-		/* Skip down to next line to write out bottom two pixels */
-		rgb += 2 * rowPixels;
-
-		rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F)
-			| ((LIMIT(g+yBL) << 3) & 0xE0);
-		rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07)
-			| (LIMIT(r+yBL) & 0xF8);
-
-		rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F)
-			| ((LIMIT(g+yBR) << 3) & 0xE0);
-		rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07)
-			| (LIMIT(r+yBR) & 0xF8);
-	}
-}
-
-/**********************************************************************
- *
- * Raw data parsing
- *
- **********************************************************************/
-
-/* Copies a 64-byte segment at pIn to an 8x8 block at pOut. The width of the
- * image at pOut is specified by w.
- */
-static inline void 
-make_8x8(unsigned char *pIn, unsigned char *pOut, int w)
-{
-	unsigned char *pOut1 = pOut;
-	int x, y;
-
-	for (y = 0; y < 8; y++) {
-		pOut1 = pOut;
-		for (x = 0; x < 8; x++) {
-			*pOut1++ = *pIn++;
-		}
-		pOut += w;
-	}
-		
-}
-
-/*
- * For RAW BW (YUV400) images, data shows up in 256 byte segments.
- * The segments represent 4 squares of 8x8 pixels as follows:
- *
- *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
- *      8  9 ... 15    72  73 ...  79        200 201 ... 207
- *           ...              ...                    ...
- *     56 57 ... 63   120 121 ... 127        248 249 ... 255
- *
- */ 
-static void
-yuv400raw_to_yuv400p(struct ov511_frame *frame,
-		     unsigned char *pIn0, unsigned char *pOut0)
-{
-	int x, y;
-	unsigned char *pIn, *pOut, *pOutLine;
-
-	/* Copy Y */
-	pIn = pIn0;
-	pOutLine = pOut0;
-	for (y = 0; y < frame->rawheight - 1; y += 8) {
-		pOut = pOutLine;
-		for (x = 0; x < frame->rawwidth - 1; x += 8) {
-			make_8x8(pIn, pOut, frame->rawwidth);
-			pIn += 64;
-			pOut += 8;
-		}
-		pOutLine += 8 * frame->rawwidth;
-	}
-}
-
-/*
- * For YUV4:2:0 images, the data shows up in 384 byte segments.
- * The first 64 bytes of each segment are U, the next 64 are V.  The U and
- * V are arranged as follows:
- *
- *      0  1 ...  7
- *      8  9 ... 15
- *           ...   
- *     56 57 ... 63
- *
- * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
- *
- * The next 256 bytes are full resolution Y data and represent 4 squares
- * of 8x8 pixels as follows:
- *
- *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
- *      8  9 ... 15    72  73 ...  79        200 201 ... 207
- *           ...              ...                    ...
- *     56 57 ... 63   120 121 ... 127   ...  248 249 ... 255
- *
- * Note that the U and V data in one segment represents a 16 x 16 pixel
- * area, but the Y data represents a 32 x 8 pixel area. If the width is not an
- * even multiple of 32, the extra 8x8 blocks within a 32x8 block belong to the
- * next horizontal stripe.
- *
- * If dumppix module param is set, _parse_data just dumps the incoming segments,
- * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
- * this puts the data on the standard output and can be analyzed with the
- * parseppm.c utility I wrote.  That's a much faster way for figuring out how
- * this data is scrambled.
- */
-
-/* Converts from raw, uncompressed segments at pIn0 to a YUV420P frame at pOut0.
- *
- * FIXME: Currently only handles width and height that are multiples of 16
- */
-static void
-yuv420raw_to_yuv420p(struct ov511_frame *frame,
-		     unsigned char *pIn0, unsigned char *pOut0)
-{
-	int k, x, y;
-	unsigned char *pIn, *pOut, *pOutLine;
-	const unsigned int a = frame->rawwidth * frame->rawheight;
-	const unsigned int w = frame->rawwidth / 2;
-
-	/* Copy U and V */
-	pIn = pIn0;
-	pOutLine = pOut0 + a;
-	for (y = 0; y < frame->rawheight - 1; y += 16) {
-		pOut = pOutLine;
-		for (x = 0; x < frame->rawwidth - 1; x += 16) {
-			make_8x8(pIn, pOut, w);
-			make_8x8(pIn + 64, pOut + a/4, w);
-			pIn += 384;
-			pOut += 8;
-		}
-		pOutLine += 8 * w;
-	}
-
-	/* Copy Y */
-	pIn = pIn0 + 128;
-	pOutLine = pOut0;
-	k = 0;
-	for (y = 0; y < frame->rawheight - 1; y += 8) {
-		pOut = pOutLine;
-		for (x = 0; x < frame->rawwidth - 1; x += 8) {
-			make_8x8(pIn, pOut, frame->rawwidth);
-			pIn += 64;
-			pOut += 8;
-			if ((++k) > 3) {
-				k = 0;
-				pIn += 128;
-			}
-		}
-		pOutLine += 8 * frame->rawwidth;
-	}
-}
-
-/*
- * fixFrameRGBoffset--
- * My camera seems to return the red channel about 1 pixel
- * low, and the blue channel about 1 pixel high. After YUV->RGB
- * conversion, we can correct this easily. OSL 2/24/2000.
- */
-static void 
-fixFrameRGBoffset(struct ov511_frame *frame)
-{
-	int x, y;
-	int rowBytes = frame->width*3, w = frame->width;
-	unsigned char *rgb = frame->data;
-	const int shift = 1;  /* Distance to shift pixels by, vertically */
-
-	/* Don't bother with little images */
-	if (frame->width < 400) 
-		return;
-
-	/* This only works with RGB24 */
-	if (frame->format != VIDEO_PALETTE_RGB24)
-		return;
-
-	/* Shift red channel up */
-	for (y = shift; y < frame->height; y++)	{
-		int lp = (y-shift)*rowBytes;     /* Previous line offset */
-		int lc = y*rowBytes;             /* Current line offset */
-		for (x = 0; x < w; x++)
-			rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
-	}
-
-	/* Shift blue channel down */
-	for (y = frame->height-shift-1; y >= 0; y--) {
-		int ln = (y + shift) * rowBytes;  /* Next line offset */
-		int lc = y * rowBytes;            /* Current line offset */
-		for (x = 0; x < w; x++)
-			rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
-	}
-}
-
-/**********************************************************************
- *
- * Decompression
- *
- **********************************************************************/
-
-/* Chooses a decompression module, locks it, and sets ov->decomp_ops
- * accordingly. Returns -ENXIO if decompressor is not available, otherwise
- * returns 0 if no other error.
- */
-static int 
-request_decompressor(struct usb_ov511 *ov)
-{
-	if (!ov)
-		return -ENODEV;
-
-	if (ov->decomp_ops) {
-		err("ERROR: Decompressor already requested!");
-		return -EINVAL;
-	}
-
-	lock_kernel();
-
-	/* Try to get MMX, and fall back on no-MMX if necessary */
-	if (ov->bclass == BCL_OV511) {
-		if (ov511_mmx_decomp_ops) {
-			PDEBUG(3, "Using OV511 MMX decompressor");
-			ov->decomp_ops = ov511_mmx_decomp_ops;
-		} else if (ov511_decomp_ops) {
-			PDEBUG(3, "Using OV511 decompressor");
-			ov->decomp_ops = ov511_decomp_ops;
-		} else {
-			err("No decompressor available");
-		}
-	} else if (ov->bclass == BCL_OV518) {
-		if (ov518_mmx_decomp_ops) {
-			PDEBUG(3, "Using OV518 MMX decompressor");
-			ov->decomp_ops = ov518_mmx_decomp_ops;
-		} else if (ov518_decomp_ops) {
-			PDEBUG(3, "Using OV518 decompressor");
-			ov->decomp_ops = ov518_decomp_ops;
-		} else {
-			err("No decompressor available");
-		}
-	} else {
-		err("Unknown bridge");
-	}
-
-	if (ov->decomp_ops) {
-		if (!ov->decomp_ops->decomp_lock) {
-			ov->decomp_ops = NULL;
-			unlock_kernel();
-			return -ENOSYS;
-		}
-		ov->decomp_ops->decomp_lock();
-		unlock_kernel();
-		return 0;
-	} else {
-		unlock_kernel();
-		return -ENXIO;
-	}
-}
-
-/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
- * if ov->decomp_ops is NULL.
- */
-static void 
-release_decompressor(struct usb_ov511 *ov)
-{
-	int released = 0;	/* Did we actually do anything? */
-
-	if (!ov)
-		return;
-
-	lock_kernel();
-
-	if (ov->decomp_ops && ov->decomp_ops->decomp_unlock) {
-		ov->decomp_ops->decomp_unlock();
-		released = 1;
-	}
-
-	ov->decomp_ops = NULL;
-	
-	unlock_kernel();
-
-	if (released)
-		PDEBUG(3, "Decompressor released");
-}
-
-static void 
-decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
-	   unsigned char *pIn0, unsigned char *pOut0)
-{
-	if (!ov->decomp_ops)
-		if (request_decompressor(ov))
-			return;
-
-	PDEBUG(4, "Decompressing %d bytes", frame->bytes_recvd);
-
-	if (frame->format == VIDEO_PALETTE_GREY 
-	    && ov->decomp_ops->decomp_400) {
-		int ret = ov->decomp_ops->decomp_400(
-			pIn0,
-			pOut0,
-			frame->compbuf,
-			frame->rawwidth,
-			frame->rawheight,
-			frame->bytes_recvd);
-		PDEBUG(4, "DEBUG: decomp_400 returned %d", ret);
-	} else if (ov->decomp_ops->decomp_420) {
-		int ret = ov->decomp_ops->decomp_420(
-			pIn0,
-			pOut0,
-			frame->compbuf,
-			frame->rawwidth,
-			frame->rawheight,
-			frame->bytes_recvd);
-		PDEBUG(4, "DEBUG: decomp_420 returned %d", ret);
-	} else {
-		err("Decompressor does not support this format");
-	}
-}
-
-/**********************************************************************
- *
- * Format conversion
- *
- **********************************************************************/
-
-/* Converts from planar YUV420 to RGB24. */
-static void 
-yuv420p_to_rgb(struct ov511_frame *frame,
-	       unsigned char *pIn0, unsigned char *pOut0, int bits)
-{
-	const int numpix = frame->width * frame->height;
-	const int bytes = bits >> 3;
-	int i, j, y00, y01, y10, y11, u, v;
-	unsigned char *pY = pIn0;
-	unsigned char *pU = pY + numpix;
-	unsigned char *pV = pU + numpix / 4;
-	unsigned char *pOut = pOut0;
-
-	for (j = 0; j <= frame->height - 2; j += 2) {
-		for (i = 0; i <= frame->width - 2; i += 2) {
-			y00 = *pY;
-			y01 = *(pY + 1);
-			y10 = *(pY + frame->width);
-			y11 = *(pY + frame->width + 1);
-			u = (*pU++) - 128;
-			v = (*pV++) - 128;
-
-			move_420_block(y00, y01, y10, y11, u, v,
-				       frame->width, pOut, bits);
-	
-			pY += 2;
-			pOut += 2 * bytes;
-
-		}
-		pY += frame->width;
-		pOut += frame->width * bytes;
-	}
-}
-
-/* Converts from planar YUV420 to YUV422 (YUYV). */
-static void
-yuv420p_to_yuv422(struct ov511_frame *frame,
-		  unsigned char *pIn0, unsigned char *pOut0)
-{
-	const int numpix = frame->width * frame->height;
-	int i, j;
-	unsigned char *pY = pIn0;
-	unsigned char *pU = pY + numpix;
-	unsigned char *pV = pU + numpix / 4;
-	unsigned char *pOut = pOut0;
-
-	for (i = 0; i < numpix; i++) {
-		*pOut = *(pY + i);
-		pOut += 2;
-	}
-
-	pOut = pOut0 + 1;
-	for (j = 0; j <= frame->height - 2 ; j += 2) {
-		for (i = 0; i <= frame->width - 2; i += 2) {
-			int u = *pU++;
-			int v = *pV++;
-			
-			*pOut = u;
-			*(pOut+2) = v;
-			*(pOut+frame->width*2) = u;
-			*(pOut+frame->width*2+2) = v;
-			pOut += 4;
-		}
-		pOut += (frame->width * 2);
-	}
-}
-
-/* Converts pData from planar YUV420 to planar YUV422 **in place**. */
-static void
-yuv420p_to_yuv422p(struct ov511_frame *frame, unsigned char *pData)
-{
-	const int numpix = frame->width * frame->height;
-	const int w = frame->width;
-	int j;
-	unsigned char *pIn, *pOut;
-
-	/* Clear U and V */
-	memset(pData + numpix + numpix / 2, 127, numpix / 2);
-
-	/* Convert V starting from beginning and working forward */
-	pIn = pData + numpix + numpix / 4;
-	pOut = pData + numpix +numpix / 2;
-	for (j = 0; j <= frame->height - 2; j += 2) {
-		memmove(pOut, pIn, w/2);
-		memmove(pOut + w/2, pIn, w/2);
-		pIn += w/2;
-		pOut += w;
-	}
-
-	/* Convert U, starting from end and working backward */
-	pIn = pData + numpix + numpix / 4;
-	pOut = pData + numpix + numpix / 2;
-	for (j = 0; j <= frame->height - 2; j += 2) {
-		pIn -= w/2;
-		pOut -= w;
-		memmove(pOut, pIn, w/2);
-		memmove(pOut + w/2, pIn, w/2);
-	}
-}
-
-/* Fuses even and odd fields together, and doubles width.
- * INPUT: an odd field followed by an even field at pIn0, in YUV planar format
- * OUTPUT: a normal YUV planar image, with correct aspect ratio
- */
-static void
-deinterlace(struct ov511_frame *frame, int rawformat,
-            unsigned char *pIn0, unsigned char *pOut0)
-{
-	const int fieldheight = frame->rawheight / 2;
-	const int fieldpix = fieldheight * frame->rawwidth;
-	const int w = frame->width;
-	int x, y;
-	unsigned char *pInEven, *pInOdd, *pOut;
-
-	PDEBUG(5, "fieldheight=%d", fieldheight);
-
-	if (frame->rawheight != frame->height) {
-		err("invalid height");
-		return;
-	}
-
-	if ((frame->rawwidth * 2) != frame->width) {
-		err("invalid width");
-		return;
-	}
-
-	/* Y */
-	pInOdd = pIn0;
-	pInEven = pInOdd + fieldpix;
-	pOut = pOut0;
-	for (y = 0; y < fieldheight; y++) {
-		for (x = 0; x < frame->rawwidth; x++) {
-			*pOut = *pInEven;
-			*(pOut+1) = *pInEven++;
-			*(pOut+w) = *pInOdd;
-			*(pOut+w+1) = *pInOdd++;
-			pOut += 2;
-		}
-		pOut += w;
-	}
-
-	if (rawformat == RAWFMT_YUV420) {
-	/* U */
-		pInOdd = pIn0 + fieldpix * 2;
-		pInEven = pInOdd + fieldpix / 4;
-		for (y = 0; y < fieldheight / 2; y++) {
-			for (x = 0; x < frame->rawwidth / 2; x++) {
-				*pOut = *pInEven;
-				*(pOut+1) = *pInEven++;
-				*(pOut+w/2) = *pInOdd;
-				*(pOut+w/2+1) = *pInOdd++;
-				pOut += 2;
-			}
-			pOut += w/2;
-		}
-	/* V */
-		pInOdd = pIn0 + fieldpix * 2 + fieldpix / 2;
-		pInEven = pInOdd + fieldpix / 4;
-		for (y = 0; y < fieldheight / 2; y++) {
-			for (x = 0; x < frame->rawwidth / 2; x++) {
-				*pOut = *pInEven;
-				*(pOut+1) = *pInEven++;
-				*(pOut+w/2) = *pInOdd;
-				*(pOut+w/2+1) = *pInOdd++;
-				pOut += 2;
-			}
-			pOut += w/2;
-		}
-	}
-}
-
-/* Post-processes the specified frame. This consists of:
- * 	1. Decompress frame, if necessary
- *	2. Deinterlace frame and scale to proper size, if necessary
- * 	3. Convert from YUV planar to destination format, if necessary
- * 	4. Fix the RGB offset, if necessary
- */
-static void 
-ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
-{
-	if (dumppix) {
-		memset(frame->data, 0, 
-			MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
-		PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);
-		memcpy(frame->data, frame->rawdata, frame->bytes_recvd);
-		return;
-	}
-
-	/* YUV400 must be handled separately */
-	if (frame->format == VIDEO_PALETTE_GREY) {
-		/* Deinterlace frame, if necessary */
-		if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
-			if (frame->compressed)
-				decompress(ov, frame, frame->rawdata,
-						 frame->tempdata);
-			else
-				yuv400raw_to_yuv400p(frame, frame->rawdata,
-						     frame->tempdata);
-
-			deinterlace(frame, RAWFMT_YUV400, frame->tempdata,
-			            frame->data);
-		} else {
-			if (frame->compressed)
-				decompress(ov, frame, frame->rawdata,
-						 frame->data);
-			else
-				yuv400raw_to_yuv400p(frame, frame->rawdata,
-						     frame->data);
-		}
-
-		return;
-	}
-
-	/* Process frame->data to frame->rawdata */
-	if (frame->compressed)
-		decompress(ov, frame, frame->rawdata, frame->tempdata);
-	else
-		yuv420raw_to_yuv420p(frame, frame->rawdata, frame->tempdata);
-
-	/* Deinterlace frame, if necessary */
-	if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
-		memcpy(frame->rawdata, frame->tempdata,
-			MAX_RAW_DATA_SIZE(frame->width, frame->height));
-		deinterlace(frame, RAWFMT_YUV420, frame->rawdata,
-		            frame->tempdata);
-	}
-
-	/* Frame should be (width x height) and not (rawwidth x rawheight) at
-         * this point. */
-
-#if 0
-	/* Clear output buffer for testing purposes */
-	memset(frame->data, 0, MAX_DATA_SIZE(frame->width, frame->height));
-#endif
-
-	/* Process frame->tempdata to frame->data */
-	switch (frame->format) {
-	case VIDEO_PALETTE_RGB565:
-		yuv420p_to_rgb(frame, frame->tempdata, frame->data, 16);
-		break;
-	case VIDEO_PALETTE_RGB24:
-		yuv420p_to_rgb(frame, frame->tempdata, frame->data, 24);
-		break;
-	case VIDEO_PALETTE_YUV422:
-	case VIDEO_PALETTE_YUYV:
-		yuv420p_to_yuv422(frame, frame->tempdata, frame->data);
-		break;
-	case VIDEO_PALETTE_YUV420:
-	case VIDEO_PALETTE_YUV420P:
-		memcpy(frame->data, frame->tempdata,
-			MAX_RAW_DATA_SIZE(frame->width, frame->height));
-		break;
-	case VIDEO_PALETTE_YUV422P:
-		/* Data is converted in place, so copy it in advance */
-		memcpy(frame->data, frame->tempdata,
-			MAX_RAW_DATA_SIZE(frame->width, frame->height));
-
-		yuv420p_to_yuv422p(frame, frame->data);
-		break;
-	default:
-		err("Cannot convert data to %s",
-		    symbolic(v4l1_plist, frame->format));
-	}
-
-	if (fix_rgb_offset)
-		fixFrameRGBoffset(frame);
-}
-
-/**********************************************************************
- *
- * OV51x data transfer, IRQ handler
- *
- **********************************************************************/
-
-static inline void 
-ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
-{
-	int num, offset;
-	int pnum = in[ov->packet_size - 1];		/* Get packet number */
-	int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
-	struct ov511_frame *frame = &ov->frame[ov->curframe];
-	struct timeval *ts;
-
-	/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
-	 * byte non-zero. The EOF packet has image width/height in the
-	 * 10th and 11th bytes. The 9th byte is given as follows:
-	 *
-	 * bit 7: EOF
-	 *     6: compression enabled
-	 *     5: 422/420/400 modes
-	 *     4: 422/420/400 modes
-	 *     3: 1
-	 *     2: snapshot button on
-	 *     1: snapshot frame
-	 *     0: even/odd field
-	 */
-
-	if (printph) {
-		info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
-		     pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
-		     in[7], in[8], in[9], in[10], in[11]);
-	}
-
-	/* Check for SOF/EOF packet */
-	if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) ||
-	    (~in[8] & 0x08))
-		goto check_middle;
-
-	/* Frame end */
-	if (in[8] & 0x80) {
-		ts = (struct timeval *)(frame->data 
-		      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
-		do_gettimeofday(ts);
-
-		/* Get the actual frame size from the EOF header */
-		frame->rawwidth = ((int)(in[9]) + 1) * 8;
-		frame->rawheight = ((int)(in[10]) + 1) * 8;
-
- 		PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
-			ov->curframe, pnum, frame->rawwidth, frame->rawheight,
-			frame->bytes_recvd);
-
-		/* Validate the header data */
-		RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
-		RESTRICT_TO_RANGE(frame->rawheight, ov->minheight,
-				  ov->maxheight);
-
-		/* Don't allow byte count to exceed buffer size */
-		RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
-
-		if (frame->scanstate == STATE_LINES) {
-	    		int nextf;
-
-			frame->grabstate = FRAME_DONE;	// FIXME: Is this right?
-
-			if (waitqueue_active(&frame->wq)) {
-				frame->grabstate = FRAME_DONE;
-				wake_up_interruptible(&frame->wq);
-			}
-
-			/* If next frame is ready or grabbing,
-			 * point to it */
-			nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
-			if (ov->frame[nextf].grabstate == FRAME_READY
-			    || ov->frame[nextf].grabstate == FRAME_GRABBING) {
-				ov->curframe = nextf;
-				ov->frame[nextf].scanstate = STATE_SCANNING;
-			} else {
-				if (frame->grabstate == FRAME_DONE) {
-					PDEBUG(4, "** Frame done **");
-				} else {
-					PDEBUG(4, "Frame not ready? state = %d",
-						ov->frame[nextf].grabstate);
-				}
-
-				ov->curframe = -1;
-			}
-		} else {
-			PDEBUG(5, "Frame done, but not scanning");
-		}
-		/* Image corruption caused by misplaced frame->segment = 0
-		 * fixed by carlosf@conectiva.com.br
-		 */
-	} else {
-		/* Frame start */
-		PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
-
-		/* Check to see if it's a snapshot frame */
-		/* FIXME?? Should the snapshot reset go here? Performance? */
-		if (in[8] & 0x02) {
-			frame->snapshot = 1;
-			PDEBUG(3, "snapshot detected");
-		}
-
-		frame->scanstate = STATE_LINES;
-		frame->bytes_recvd = 0;
-		frame->compressed = in[8] & 0x40;
-	}
-
-check_middle:
-	/* Are we in a frame? */
-	if (frame->scanstate != STATE_LINES) {
-		PDEBUG(5, "Not in a frame; packet skipped");
-		return;
-	}
-
-	/* If frame start, skip header */
-	if (frame->bytes_recvd == 0)
-		offset = 9;
-	else
-		offset = 0;
-
-	num = n - offset - 1;
-
-	/* Dump all data exactly as received */
-	if (dumppix == 2) {
-		frame->bytes_recvd += n - 1;
-		if (frame->bytes_recvd <= max_raw)
-			memcpy(frame->rawdata + frame->bytes_recvd - (n - 1),
-				in, n - 1);
-		else
-			PDEBUG(3, "Raw data buffer overrun!! (%d)",
-				frame->bytes_recvd - max_raw);
-	} else if (!frame->compressed && !remove_zeros) {
-		frame->bytes_recvd += num;
-		if (frame->bytes_recvd <= max_raw)
-			memcpy(frame->rawdata + frame->bytes_recvd - num,
-				in + offset, num);
-		else
-			PDEBUG(3, "Raw data buffer overrun!! (%d)",
-				frame->bytes_recvd - max_raw);
-	} else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */
-		int b, read = 0, allzero, copied = 0;
-		if (offset) {
-			frame->bytes_recvd += 32 - offset;	// Bytes out
-			memcpy(frame->rawdata,	in + offset, 32 - offset);
-			read += 32;
-		}
-
-		while (read < n - 1) {
-			allzero = 1;
-			for (b = 0; b < 32; b++) {
-				if (in[read + b]) {
-					allzero = 0;
-					break;
-				}
-			}
-
-			if (allzero) {
-				/* Don't copy it */
-			} else {
-				if (frame->bytes_recvd + copied + 32 <= max_raw)
-				{
-					memcpy(frame->rawdata
-						+ frame->bytes_recvd + copied,
-						in + read, 32);
-					copied += 32;
-				} else {
-					PDEBUG(3, "Raw data buffer overrun!!");
-				}
-			}
-			read += 32;
-		}
-
-		frame->bytes_recvd += copied;
-	}
-}
-
-static inline void 
-ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
-{
-	int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
-	struct ov511_frame *frame = &ov->frame[ov->curframe];
-	struct timeval *ts;
-
-	if (printph) {
-		info("ph: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
-		     in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7],
-		     in[8], in[9], in[10], in[11]);
-	}
-
-	/* A false positive here is likely, until OVT gives me
-	 * the definitive SOF/EOF format */
-	if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) {
-		if (frame->scanstate == STATE_LINES) {
-			PDEBUG(4, "Detected frame end/start");
-			goto eof;
-		} else { //scanstate == STATE_SCANNING
-			/* Frame start */
-			PDEBUG(4, "Frame start, framenum = %d", ov->curframe);
-			goto sof;
-		}
-	} else {
-		goto check_middle;
-	}
-
-eof:
-	ts = (struct timeval *)(frame->data
-	      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
-	do_gettimeofday(ts);
-
-	PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d",
-		ov->curframe,
-		(int)(in[9]), (int)(in[10]), frame->bytes_recvd);
-
-	// FIXME: Since we don't know the header formats yet,
-	// there is no way to know what the actual image size is
-	frame->rawwidth = frame->width;
-	frame->rawheight = frame->height;
-
-	/* Validate the header data */
-	RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
-	RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
-
-	/* Don't allow byte count to exceed buffer size */
-	RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
-
-	if (frame->scanstate == STATE_LINES) {
-    		int nextf;
-
-		frame->grabstate = FRAME_DONE;	// FIXME: Is this right?
-
-		if (waitqueue_active(&frame->wq)) {
-			frame->grabstate = FRAME_DONE;
-			wake_up_interruptible(&frame->wq);
-		}
-
-		/* If next frame is ready or grabbing,
-		 * point to it */
-		nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
-		if (ov->frame[nextf].grabstate == FRAME_READY
-		    || ov->frame[nextf].grabstate == FRAME_GRABBING) {
-			ov->curframe = nextf;
-			ov->frame[nextf].scanstate = STATE_SCANNING;
-			frame = &ov->frame[nextf];
-		} else {
-			if (frame->grabstate == FRAME_DONE) {
-				PDEBUG(4, "** Frame done **");
-			} else {
-				PDEBUG(4, "Frame not ready? state = %d",
-				       ov->frame[nextf].grabstate);
-			}
-
-			ov->curframe = -1;
-			PDEBUG(4, "SOF dropped (no active frame)");
-			return;  /* Nowhere to store this frame */
-		}
-	}
-sof:
-	PDEBUG(4, "Starting capture on frame %d", frame->framenum);
-
-// Snapshot not reverse-engineered yet.
-#if 0
-	/* Check to see if it's a snapshot frame */
-	/* FIXME?? Should the snapshot reset go here? Performance? */
-	if (in[8] & 0x02) {
-		frame->snapshot = 1;
-		PDEBUG(3, "snapshot detected");
-	}
-#endif
-	frame->scanstate = STATE_LINES;
-	frame->bytes_recvd = 0;
-//		frame->compressed = 1;
-
-check_middle:
-	/* Are we in a frame? */
-	if (frame->scanstate != STATE_LINES) {
-		PDEBUG(4, "scanstate: no SOF yet");
-		return;
-	}
-
-	/* Dump all data exactly as received */
-	if (dumppix == 2) {
-		frame->bytes_recvd += n;
-		if (frame->bytes_recvd <= max_raw)
-			memcpy(frame->rawdata + frame->bytes_recvd - n, in, n);
-		else
-			PDEBUG(3, "Raw data buffer overrun!! (%d)",
-				frame->bytes_recvd - max_raw);
-	} else {
-		/* All incoming data are divided into 8-byte segments. If the
-		 * segment contains all zero bytes, it must be skipped. These
-		 * zero-segments allow the OV518 to mainain a constant data rate
-		 * regardless of the effectiveness of the compression. Segments
-		 * are aligned relative to the beginning of each isochronous
-		 * packet. The first segment is a header (the decompressor
-		 * skips it later).
-		 */
-
-		int b, read = 0, allzero, copied = 0;
-
-		while (read < n) {
-			allzero = 1;
-			for (b = 0; b < 8; b++) {
-				if (in[read + b]) {
-					allzero = 0;
-					break;
-				}
-			}
-
-			if (allzero) {
-			/* Don't copy it */
-			} else {
-				if (frame->bytes_recvd + copied + 8 <= max_raw)
-				{
-					memcpy(frame->rawdata 
-						+ frame->bytes_recvd + copied,
-						in + read, 8);
-					copied += 8;
-				} else {
-					PDEBUG(3, "Raw data buffer overrun!!");
-				}
-			}
-			read += 8;
-		}
-		frame->bytes_recvd += copied;
-	}
-}
-
-static void 
-ov51x_isoc_irq(struct urb *urb)
-{
-	int i;
-	struct usb_ov511 *ov;
-	struct ov511_sbuf *sbuf;
-
-	if (!urb->context) {
-		PDEBUG(4, "no context");
-		return;
-	}
-
-	sbuf = urb->context;
-	ov = sbuf->ov;
-
-	if (!ov || !ov->dev || !ov->user) {
-		PDEBUG(4, "no device, or not open");
-		return;
-	}
-
-	if (!ov->streaming) {
-		PDEBUG(4, "hmmm... not streaming, but got interrupt");
-		return;
-	}
-
-        if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-                PDEBUG(4, "URB unlinked");
-                return;
-        }
-
-	if (urb->status != -EINPROGRESS && urb->status != 0) {
-		err("ERROR: urb->status=%d: %s", urb->status,
-		    symbolic(urb_errlist, urb->status));
-		return;
-	}
-
-	/* Copy the data received into our frame buffer */
-	PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n,
-	       urb->number_of_packets);
-	for (i = 0; i < urb->number_of_packets; i++) {
-		/* Warning: Don't call *_move_data() if no frame active! */
-		if (ov->curframe >= 0) {
-			int n = urb->iso_frame_desc[i].actual_length;
-			int st = urb->iso_frame_desc[i].status;
-			unsigned char *cdata;
-
-			urb->iso_frame_desc[i].actual_length = 0;
-			urb->iso_frame_desc[i].status = 0;
-
-			cdata = urb->transfer_buffer
-				+ urb->iso_frame_desc[i].offset;
-
-			if (!n) {
-				PDEBUG(4, "Zero-length packet");
-				continue;
-			}
-
-			if (st)
-				PDEBUG(2, "data error: [%d] len=%d, status=%d",
-				       i, n, st);
-
-			if (ov->bclass == BCL_OV511)
-				ov511_move_data(ov, cdata, n);
-			else if (ov->bclass == BCL_OV518)
-				ov518_move_data(ov, cdata, n);
-			else
-				err("Unknown bridge device (%d)", ov->bridge);
-
-		} else if (waitqueue_active(&ov->wq)) {
-			wake_up_interruptible(&ov->wq);
-		}
-	}
-
-	urb->dev = ov->dev;
-
-	return;
-}
-
-/****************************************************************************
- *
- * Stream initialization and termination
- *
- ***************************************************************************/
-
-static int 
-ov51x_init_isoc(struct usb_ov511 *ov)
-{
-	struct urb *urb;
-	int fx, err, n, size;
-
-	PDEBUG(3, "*** Initializing capture ***");
-
-	ov->curframe = -1;
-
-	if (ov->bridge == BRG_OV511) {
-		if (cams == 1)				size = 993;
-		else if (cams == 2)			size = 513;
-		else if (cams == 3 || cams == 4)	size = 257;
-		else {
-			err("\"cams\" parameter too high!");
-			return -1;
-		}
-	} else if (ov->bridge == BRG_OV511PLUS) {
-		if (cams == 1)				size = 961;
-		else if (cams == 2)			size = 513;
-		else if (cams == 3 || cams == 4)	size = 257;
-		else if (cams >= 5 && cams <= 8)	size = 129;
-		else if (cams >= 9 && cams <= 31)	size = 33;
-		else {
-			err("\"cams\" parameter too high!");
-			return -1;
-		}
-	} else if (ov->bclass == BCL_OV518) {
-		if (cams == 1)				size = 896;
-		else if (cams == 2)			size = 512;
-		else if (cams == 3 || cams == 4)	size = 256;
-		else if (cams >= 5 && cams <= 8)	size = 128;
-		else {
-			err("\"cams\" parameter too high!");
-			return -1;
-		}
-	} else {
-		err("invalid bridge type");
-		return -1;
-	}
-
-	if (packetsize == -1) {
-		// FIXME: OV518 is hardcoded to 15 FPS (alternate 5) for now
-		if (ov->bclass == BCL_OV518)
-			ov51x_set_packet_size(ov, 640);
-		else
-			ov51x_set_packet_size(ov, size);
-	} else {
-			info("Forcing packet size to %d", packetsize);
-			ov51x_set_packet_size(ov, packetsize);
-	}
-
-	for (n = 0; n < OV511_NUMSBUF; n++) {
-		urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-		if (!urb) {
-			err("init isoc: usb_alloc_urb ret. NULL");
-			return -ENOMEM;
-		}
-		ov->sbuf[n].urb = urb;
-		urb->dev = ov->dev;
-		urb->context = &ov->sbuf[n];
-		urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS);
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->transfer_buffer = ov->sbuf[n].data;
-		urb->complete = ov51x_isoc_irq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = ov->packet_size * FRAMES_PER_DESC;
-		for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-			urb->iso_frame_desc[fx].offset = ov->packet_size * fx;
-			urb->iso_frame_desc[fx].length = ov->packet_size;
-		}
-	}
-
-	ov->streaming = 1;
-
-	ov->sbuf[OV511_NUMSBUF - 1].urb->next = ov->sbuf[0].urb;
-	for (n = 0; n < OV511_NUMSBUF - 1; n++)
-		ov->sbuf[n].urb->next = ov->sbuf[n+1].urb;
-
-	for (n = 0; n < OV511_NUMSBUF; n++) {
-		ov->sbuf[n].urb->dev = ov->dev;
-		err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL);
-		if (err)
-			err("init isoc: usb_submit_urb(%d) ret %d", n, err);
-	}
-
-	return 0;
-}
-
-static void 
-ov51x_unlink_isoc(struct usb_ov511 *ov)
-{
-	int n;
-
-	/* Unschedule all of the iso td's */
-	for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
-		if (ov->sbuf[n].urb) {
-			usb_unlink_urb(ov->sbuf[n].urb);
-			usb_free_urb(ov->sbuf[n].urb);
-			ov->sbuf[n].urb = NULL;
-		}
-	}
-}
-
-static void 
-ov51x_stop_isoc(struct usb_ov511 *ov)
-{
-	if (!ov->streaming || !ov->dev)
-		return;
-
-	PDEBUG(3, "*** Stopping capture ***");
-
-	ov51x_set_packet_size(ov, 0);
-
-	ov->streaming = 0;
-
-	ov51x_unlink_isoc(ov);
-}
-
-static int 
-ov51x_new_frame(struct usb_ov511 *ov, int framenum)
-{
-	struct ov511_frame *frame;
-	int newnum;
-
-	PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);
-
-	if (!ov->dev)
-		return -1;
-
-	/* If we're not grabbing a frame right now and the other frame is */
-	/* ready to be grabbed into, then use it instead */
-	if (ov->curframe == -1) {
-		newnum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
-		if (ov->frame[newnum].grabstate == FRAME_READY)
-			framenum = newnum;
-	} else
-		return 0;
-
-	frame = &ov->frame[framenum];
-
-	PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum, 
-	       frame->width, frame->height);
-
-	frame->grabstate = FRAME_GRABBING;
-	frame->scanstate = STATE_SCANNING;
-	frame->snapshot = 0;
-
-	ov->curframe = framenum;
-
-	/* Make sure it's not too big */
-	if (frame->width > ov->maxwidth)
-		frame->width = ov->maxwidth;
-
-	frame->width &= ~7L;		/* Multiple of 8 */
-
-	if (frame->height > ov->maxheight)
-		frame->height = ov->maxheight;
-
-	frame->height &= ~3L;		/* Multiple of 4 */
-
-	return 0;
-}
-
-/****************************************************************************
- *
- * Buffer management
- *
- ***************************************************************************/
-
-/* 
- * - You must acquire buf_lock before entering this function.
- * - Because this code will free any non-null pointer, you must be sure to null
- *   them if you explicitly free them somewhere else!
- */
-static void 
-ov51x_do_dealloc(struct usb_ov511 *ov)
-{
-	int i;
-	PDEBUG(4, "entered");
-
-	if (ov->fbuf) {
-		rvfree(ov->fbuf, OV511_NUMFRAMES
-		       * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
-		ov->fbuf = NULL;
-	}
-
-	if (ov->rawfbuf) {
-		vfree(ov->rawfbuf);
-		ov->rawfbuf = NULL;
-	}
-
-	if (ov->tempfbuf) {
-		vfree(ov->tempfbuf);
-		ov->tempfbuf = NULL;
-	}
-
-	for (i = 0; i < OV511_NUMSBUF; i++) {
-		if (ov->sbuf[i].data) {
-			kfree(ov->sbuf[i].data);
-			ov->sbuf[i].data = NULL;
-		}
-	}
-
-	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov->frame[i].data = NULL;
-		ov->frame[i].rawdata = NULL;
-		ov->frame[i].tempdata = NULL;
-		if (ov->frame[i].compbuf) {
-			free_page((unsigned long) ov->frame[i].compbuf);
-			ov->frame[i].compbuf = NULL;
-		}
-	}
-
-	PDEBUG(4, "buffer memory deallocated");
-	ov->buf_state = BUF_NOT_ALLOCATED;
-	PDEBUG(4, "leaving");
-}
-
-static int 
-ov51x_alloc(struct usb_ov511 *ov)
-{
-	int i;
-	const int w = ov->maxwidth;
-	const int h = ov->maxheight;
-	const int data_bufsize = OV511_NUMFRAMES * MAX_DATA_SIZE(w, h);
-	const int raw_bufsize = OV511_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);
-
-	PDEBUG(4, "entered");
-	down(&ov->buf_lock);
-
-	if (ov->buf_state == BUF_PEND_DEALLOC) {
-		ov->buf_state = BUF_ALLOCATED;
-		del_timer(&ov->buf_timer);
-	}
-
-	if (ov->buf_state == BUF_ALLOCATED)
-		goto out;
-
-	ov->fbuf = rvmalloc(data_bufsize);
-	if (!ov->fbuf)
-		goto error;
-
-	ov->rawfbuf = vmalloc(raw_bufsize);
-	if (!ov->rawfbuf)
-		goto error;
-
-	memset(ov->rawfbuf, 0, raw_bufsize);
-
-	ov->tempfbuf = vmalloc(raw_bufsize);
-	if (!ov->tempfbuf)
-		goto error;
-
-	memset(ov->tempfbuf, 0, raw_bufsize);
-
-	for (i = 0; i < OV511_NUMSBUF; i++) {
-		ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
-			MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
-		if (!ov->sbuf[i].data)
-			goto error;
-
-		PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data);
-	}
-
-	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h);
-		ov->frame[i].rawdata = ov->rawfbuf 
-		 + i * MAX_RAW_DATA_SIZE(w, h);
-		ov->frame[i].tempdata = ov->tempfbuf 
-		 + i * MAX_RAW_DATA_SIZE(w, h);
-
-		ov->frame[i].compbuf = 
-		 (unsigned char *) __get_free_page(GFP_KERNEL);
-		if (!ov->frame[i].compbuf)
-			goto error;
-
-		PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data);
-	}
-
-	ov->buf_state = BUF_ALLOCATED;
-out:
-	up(&ov->buf_lock);
-	PDEBUG(4, "leaving");
-	return 0;
-error:
-	ov51x_do_dealloc(ov);
-	up(&ov->buf_lock);
-	PDEBUG(4, "errored");
-	return -ENOMEM;
-}
-
-static void 
-ov51x_buf_callback(unsigned long data)
-{
-	struct usb_ov511 *ov = (struct usb_ov511 *)data;
-	PDEBUG(4, "entered");
-	down(&ov->buf_lock);
-
-	if (ov->buf_state == BUF_PEND_DEALLOC)
-		ov51x_do_dealloc(ov);
-
-	up(&ov->buf_lock);
-	PDEBUG(4, "leaving");
-}
-
-static void 
-ov51x_dealloc(struct usb_ov511 *ov, int now)
-{
-	struct timer_list *bt = &(ov->buf_timer);
-	PDEBUG(4, "entered");
-	down(&ov->buf_lock);
-
-	PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later");
-
-	if (ov->buf_state == BUF_PEND_DEALLOC) {
-		ov->buf_state = BUF_ALLOCATED;
-		del_timer(bt);
-	}
-
-	if (now)
-		ov51x_do_dealloc(ov);
-	else {
-		ov->buf_state = BUF_PEND_DEALLOC;
-		init_timer(bt);
-		bt->function = ov51x_buf_callback;
-		bt->data = (unsigned long)ov;
-		bt->expires = jiffies + buf_timeout * HZ;
-		add_timer(bt);
-	}
-	up(&ov->buf_lock);
-	PDEBUG(4, "leaving");
-}
-
-/****************************************************************************
- *
- * V4L 1 API
- *
- ***************************************************************************/
-
-static int 
-ov51x_v4l1_open(struct inode *inode, struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct usb_ov511 *ov = vdev->priv;
-	int err, i;
-
-	PDEBUG(4, "opening");
-
-	down(&ov->lock);
-
-	err = -EBUSY;
-	if (ov->user) 
-		goto out;
-
-	err = -ENOMEM;
-	if (ov51x_alloc(ov))
-		goto out;
-
-	ov->sub_flag = 0;
-
-	/* In case app doesn't set them... */
-	if (ov51x_set_default_params(ov) < 0)
-		goto out;
-
-	/* Make sure frames are reset */
-	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov->frame[i].grabstate = FRAME_UNUSED;
-		ov->frame[i].bytes_read = 0;
-	}
-
-	/* If compression is on, make sure now that a 
-	 * decompressor can be loaded */
-	if (ov->compress && !ov->decomp_ops) {
-		err = request_decompressor(ov);
-		if (err && !dumppix)
-			goto out;
-	}
-
-	err = ov51x_init_isoc(ov);
-	if (err) {
-		ov51x_dealloc(ov, 0);
-		goto out;
-	}
-
-	ov->user++;
-	file->private_data = vdev;
-	
-	if (ov->led_policy == LED_AUTO)
-		ov51x_led_control(ov, 1);
-
-out:
-	up(&ov->lock);
-	return err;
-}
-
-static int 
-ov51x_v4l1_close(struct inode *inode, struct file *file)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_ov511 *ov = vdev->priv;
-
-	PDEBUG(4, "ov511_close");
-	
-	down(&ov->lock);
-
-	ov->user--;
-	ov51x_stop_isoc(ov);
-
-	release_decompressor(ov);
-
-	if (ov->led_policy == LED_AUTO)
-		ov51x_led_control(ov, 0);
-
-	if (ov->dev)
-		ov51x_dealloc(ov, 0);
-
-	up(&ov->lock);
-
-	/* Device unplugged while open. Only a minimum of unregistration is done
-	 * here; the disconnect callback already did the rest. */
-	if (!ov->dev) {
-		down(&ov->cbuf_lock);
-		kfree(ov->cbuf);
-		ov->cbuf = NULL;
-		up(&ov->cbuf_lock);
-
-		ov51x_dealloc(ov, 1);
-		kfree(ov);
-		ov = NULL;
-	}
-	file->private_data = NULL;
-
-	return 0;
-}
-
-/* Do not call this function directly! */
-static int 
-ov51x_v4l1_ioctl_internal(struct usb_ov511 *ov, unsigned int cmd,
-			  void *arg)
-{
-	PDEBUG(5, "IOCtl: 0x%X", cmd);
-
-	if (!ov->dev)
-		return -EIO;	
-
-	switch (cmd) {
-	case VIDIOCGCAP:
-	{
-		struct video_capability *b = arg;
-
-		PDEBUG(4, "VIDIOCGCAP");
-
-		memset(b, 0, sizeof(struct video_capability));
-		sprintf(b->name, "%s USB Camera",
-			symbolic(brglist, ov->bridge));
-		b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
-		if (ov->has_tuner)
-			b->type |= VID_TYPE_TUNER;
-		b->channels = ov->num_inputs;
-		b->audios = ov->has_audio_proc ? 1:0;
-		b->maxwidth = ov->maxwidth;
-		b->maxheight = ov->maxheight;
-		b->minwidth = ov->minwidth;
-		b->minheight = ov->minheight;
-
-		return 0;
-	}
-	case VIDIOCGCHAN:
-	{
-		struct video_channel *v = arg;
-
-		PDEBUG(4, "VIDIOCGCHAN");
-
-		if ((unsigned)(v->channel) >= ov->num_inputs) {
-			err("Invalid channel (%d)", v->channel);
-			return -EINVAL;
-		}
-
-		v->norm = ov->norm;
-		v->type = (ov->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
-		v->flags = (ov->has_tuner) ? VIDEO_VC_TUNER : 0;
-		v->flags |= (ov->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
-//		v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0;
-		v->tuners = (ov->has_tuner) ? 1:0;
-		decoder_get_input_name(ov, v->channel, v->name);
-
-		return 0;
-	}
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *v = arg;
-		int err;
-
-		PDEBUG(4, "VIDIOCSCHAN");
-
-		/* Make sure it's not a camera */
-		if (!ov->has_decoder) {
-			if (v->channel == 0)
-				return 0;
-			else
-				return -EINVAL;
-		}
-
-		if (v->norm != VIDEO_MODE_PAL &&
-		    v->norm != VIDEO_MODE_NTSC &&
-		    v->norm != VIDEO_MODE_SECAM &&
-		    v->norm != VIDEO_MODE_AUTO) {
-			err("Invalid norm (%d)", v->norm);
-			return -EINVAL;
-		}
-
-		if ((unsigned)(v->channel) >= ov->num_inputs) {
-			err("Invalid channel (%d)", v->channel);
-			return -EINVAL;
-		}
-
-		err = decoder_set_input(ov, v->channel);
-		if (err)
-			return err;
-
-		err = decoder_set_norm(ov, v->norm);
-		if (err)
-			return err;
-
-		return 0;
-	}
-	case VIDIOCGPICT:
-	{
-		struct video_picture *p = arg;
-
-		PDEBUG(4, "VIDIOCGPICT");
-
-		memset(p, 0, sizeof(struct video_picture));
-		if (sensor_get_picture(ov, p))
-			return -EIO;
-
-		return 0;
-	}
-	case VIDIOCSPICT:
-	{
-		struct video_picture *p = arg;
-		int i;
-
-		PDEBUG(4, "VIDIOCSPICT");
-
-		if (!get_depth(p->palette))
-			return -EINVAL;
-
-		if (sensor_set_picture(ov, p))
-			return -EIO;
-
-		if (force_palette && p->palette != force_palette) {
-			info("Palette rejected (%s)",
-			     symbolic(v4l1_plist, p->palette));
-			return -EINVAL;
-		}
-
-		// FIXME: Format should be independent of frames
-		if (p->palette != ov->frame[0].format) {
-			PDEBUG(4, "Detected format change");
-
-			/* If we're collecting previous frame wait
-			   before changing modes */
-			interruptible_sleep_on(&ov->wq);
-			if (signal_pending(current)) return -EINTR;
-
-			mode_init_regs(ov, ov->frame[0].width,
-				ov->frame[0].height, p->palette, ov->sub_flag);
-		}
-
-		PDEBUG(4, "Setting depth=%d, palette=%s",
-		       p->depth, symbolic(v4l1_plist, p->palette));
-
-		for (i = 0; i < OV511_NUMFRAMES; i++) {
-			ov->frame[i].depth = p->depth;
-			ov->frame[i].format = p->palette;
-		}
-
-		return 0;
-	}
-	case VIDIOCGCAPTURE:
-	{
-		int *vf = arg;
-
-		PDEBUG(4, "VIDIOCGCAPTURE");
-
-		ov->sub_flag = *vf;
-		return 0;
-	}
-	case VIDIOCSCAPTURE:
-	{
-		struct video_capture *vc = arg;
-
-		PDEBUG(4, "VIDIOCSCAPTURE");
-
-		if (vc->flags)
-			return -EINVAL;
-		if (vc->decimation)
-			return -EINVAL;
-
-		vc->x &= ~3L;
-		vc->y &= ~1L;
-		vc->y &= ~31L;
-
-		if (vc->width == 0)
-			vc->width = 32;
-
-		vc->height /= 16;
-		vc->height *= 16;
-		if (vc->height == 0)
-			vc->height = 16;
-
-		ov->subx = vc->x;
-		ov->suby = vc->y;
-		ov->subw = vc->width;
-		ov->subh = vc->height;
-
-		return 0;
-	}
-	case VIDIOCSWIN:
-	{
-		struct video_window *vw = arg;
-		int i, result;
-
-		PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height);
-
-#if 0
-		if (vw->flags)
-			return -EINVAL;
-		if (vw->clipcount)
-			return -EINVAL;
-		if (vw->height != ov->maxheight)
-			return -EINVAL;
-		if (vw->width != ov->maxwidth)
-			return -EINVAL;
-#endif
-
-		/* If we're collecting previous frame wait
-		   before changing modes */
-		interruptible_sleep_on(&ov->wq);
-		if (signal_pending(current)) return -EINTR;
-
-		result = mode_init_regs(ov, vw->width, vw->height,
-			ov->frame[0].format, ov->sub_flag);
-		if (result < 0)
-			return result;
-
-		for (i = 0; i < OV511_NUMFRAMES; i++) {
-			ov->frame[i].width = vw->width;
-			ov->frame[i].height = vw->height;
-		}
-
-		return 0;
-	}
-	case VIDIOCGWIN:
-	{
-		struct video_window *vw = arg;
-
-		memset(vw, 0, sizeof(struct video_window));
-		vw->x = 0;		/* FIXME */
-		vw->y = 0;
-		vw->width = ov->frame[0].width;
-		vw->height = ov->frame[0].height;
-		vw->flags = 30;
-
-		PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height);
-
-		return 0;
-	}
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *vm = arg;
-		int i;
-
-		PDEBUG(4, "VIDIOCGMBUF");
-
-		memset(vm, 0, sizeof(struct video_mbuf));
-		vm->size = OV511_NUMFRAMES
-			   * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
-		vm->frames = OV511_NUMFRAMES;
-
-		vm->offsets[0] = 0;
-		for (i = 1; i < OV511_NUMFRAMES; i++) {
-			vm->offsets[i] = vm->offsets[i-1]
-			   + MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
-		}
-
-		return 0;
-	}
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *vm = arg;
-		int ret, depth;
-		unsigned int f = vm->frame;
-
-		PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width,
-			vm->height, symbolic(v4l1_plist, vm->format));
-
-		depth = get_depth(vm->format);
-		if (!depth) {
-			err("VIDIOCMCAPTURE: invalid format (%s)",
-			    symbolic(v4l1_plist, vm->format));
-			return -EINVAL;
-		}
-
-		if (f >= OV511_NUMFRAMES) {
-			err("VIDIOCMCAPTURE: invalid frame (%d)", f);
-			return -EINVAL;
-		}
-
-		if (vm->width > ov->maxwidth 
-		    || vm->height > ov->maxheight) {
-			err("VIDIOCMCAPTURE: requested dimensions too big");
-			return -EINVAL;
-		}
-
-		if (ov->frame[f].grabstate == FRAME_GRABBING) {
-			PDEBUG(4, "VIDIOCMCAPTURE: already grabbing");
-			return -EBUSY;
-		}
-
-		if (force_palette && (vm->format != force_palette)) {
-			info("palette rejected (%s)",
-			     symbolic(v4l1_plist, vm->format));
-			return -EINVAL;
-		}
-
-		if ((ov->frame[f].width != vm->width) ||
-		    (ov->frame[f].height != vm->height) ||
-		    (ov->frame[f].format != vm->format) ||
-		    (ov->frame[f].sub_flag != ov->sub_flag) ||
-		    (ov->frame[f].depth != depth)) {
-			PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters");
-
-			/* If we're collecting previous frame wait
-			   before changing modes */
-			interruptible_sleep_on(&ov->wq);
-			if (signal_pending(current)) return -EINTR;
-			ret = mode_init_regs(ov, vm->width, vm->height,
-				vm->format, ov->sub_flag);
-#if 0
-			if (ret < 0) {
-				PDEBUG(1, "Got error while initializing regs ");
-				return ret;
-			}
-#endif
-			ov->frame[f].width = vm->width;
-			ov->frame[f].height = vm->height;
-			ov->frame[f].format = vm->format;
-			ov->frame[f].sub_flag = ov->sub_flag;
-			ov->frame[f].depth = depth;
-		}
-
-		/* Mark it as ready */
-		ov->frame[f].grabstate = FRAME_READY;
-
-		PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f);
-
-		return ov51x_new_frame(ov, f);
-	}
-	case VIDIOCSYNC:
-	{
-		unsigned int fnum = *((unsigned int *) arg);
-		struct ov511_frame *frame;
-		int rc;
-
-
-		if (fnum >= OV511_NUMFRAMES) {
-			err("VIDIOCSYNC: invalid frame (%d)", fnum);
-			return -EINVAL;
-		}
-
-		frame = &ov->frame[fnum];
-
-		PDEBUG(4, "syncing to frame %d, grabstate = %d", fnum,
-		       frame->grabstate);
-
-		switch (frame->grabstate) {
-		case FRAME_UNUSED:
-			return -EINVAL;
-		case FRAME_READY:
-		case FRAME_GRABBING:
-		case FRAME_ERROR:
-redo:
-			if (!ov->dev)
-				return -EIO;
-
-			rc = wait_event_interruptible(frame->wq,
-			    (frame->grabstate == FRAME_DONE)
-			    || (frame->grabstate == FRAME_ERROR));
-
-			if (rc)
-				return rc;
-
-			if (frame->grabstate == FRAME_ERROR) {
-				int ret;
-
-				if ((ret = ov51x_new_frame(ov, fnum)) < 0)
-					return ret;
-				goto redo;
-			}
-			/* Fall through */			
-		case FRAME_DONE:
-			if (ov->snap_enabled && !frame->snapshot) {
-				int ret;
-				if ((ret = ov51x_new_frame(ov, fnum)) < 0)
-					return ret;
-				goto redo;
-			}
-
-			frame->grabstate = FRAME_UNUSED;
-
-			/* Reset the hardware snapshot button */
-			/* FIXME - Is this the best place for this? */
-			if ((ov->snap_enabled) && (frame->snapshot)) {
-				frame->snapshot = 0;
-				ov51x_clear_snapshot(ov);
-			}
-
-			/* Decompression, format conversion, etc... */
-			ov51x_postprocess(ov, frame);
-
-			break;
-		} /* end switch */
-
-		return 0;
-	}
-	case VIDIOCGFBUF:
-	{
-		struct video_buffer *vb = arg;
-
-		PDEBUG(4, "VIDIOCGFBUF");
-
-		memset(vb, 0, sizeof(struct video_buffer));
-
-		return 0;
-	}
-	case VIDIOCGUNIT:
-	{
-		struct video_unit *vu = arg;
-
-		PDEBUG(4, "VIDIOCGUNIT");
-
-		memset(vu, 0, sizeof(struct video_unit));
-
-		vu->video = ov->vdev.minor;
-		vu->vbi = VIDEO_NO_UNIT;
-		vu->radio = VIDEO_NO_UNIT;
-		vu->audio = VIDEO_NO_UNIT;
-		vu->teletext = VIDEO_NO_UNIT;
-
-		return 0;
-	}
-	case VIDIOCGTUNER:
-	{
-		struct video_tuner *v = arg;
-
-		PDEBUG(4, "VIDIOCGTUNER");
-
-		if (!ov->has_tuner || v->tuner)	// Only tuner 0
-			return -EINVAL;
-
-		strcpy(v->name, "Television");
-
-		// FIXME: Need a way to get the real values
-		v->rangelow = 0;
-		v->rangehigh = ~0;
-
-		v->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC
-			   | VIDEO_TUNER_SECAM;
-		v->mode = 0; 		/* FIXME:  Not sure what this is yet */
-		v->signal = 0xFFFF;	/* unknown */
-
-		call_i2c_clients(ov, cmd, v);
-
-		return 0;
-	}
-	case VIDIOCSTUNER:
-	{
-		struct video_tuner *v = arg;
-		int err;
-
-		PDEBUG(4, "VIDIOCSTUNER");
-
-		/* Only no or one tuner for now */
-		if (!ov->has_tuner || v->tuner)
-			return -EINVAL;
-
-		/* and it only has certain valid modes */
-		if (v->mode != VIDEO_MODE_PAL &&
-		    v->mode != VIDEO_MODE_NTSC &&
-		    v->mode != VIDEO_MODE_SECAM)
-			return -EOPNOTSUPP;
-
-		/* Is this right/necessary? */
-		err = decoder_set_norm(ov, v->mode);
-		if (err)
-			return err;
-
-		call_i2c_clients(ov, cmd, v);
-
-		return 0;
-	}
-	case VIDIOCGFREQ:
-	{
-		unsigned long v = *((unsigned long *) arg);
-
-		PDEBUG(4, "VIDIOCGFREQ");
-
-		if (!ov->has_tuner)
-			return -EINVAL;
-
-		v = ov->freq;
-#if 0
-		/* FIXME: this is necessary for testing */
-		v = 46*16;
-#endif
-		return 0;
-	}
-	case VIDIOCSFREQ:
-	{
-		unsigned long v = *((unsigned long *) arg);
-
-		PDEBUG(4, "VIDIOCSFREQ: %lx", v);
-
-		if (!ov->has_tuner)
-			return -EINVAL;
-
-		ov->freq = v;
-		call_i2c_clients(ov, cmd, &v);
-
-		return 0;
-	}
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-	{
-		/* FIXME: Implement this... */
-		return 0;
-	}
-	default:
-		PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd);
-		return -ENOIOCTLCMD;
-	} /* end switch */
-
-	return 0;
-}
-
-static int 
-ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
-		 unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_ov511 *ov = vdev->priv;
-	int rc;
-
-	if (down_interruptible(&ov->lock))
-		return -EINTR;
-
-	rc = ov51x_v4l1_ioctl_internal(ov, cmd, arg);
-
-	up(&ov->lock);
-	return rc;
-}
-
-static inline int 
-ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
-{
-	struct video_device *vdev = file->private_data;
-	int noblock = file->f_flags&O_NONBLOCK;
-	unsigned long count = cnt;
-	struct usb_ov511 *ov = vdev->priv;
-	int i, rc = 0, frmx = -1;
-	struct ov511_frame *frame;
-
-	if (down_interruptible(&ov->lock))
-		return -EINTR;
-
-	PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
-
-	if (!vdev || !buf) {
-		rc = -EFAULT;
-		goto error;
-	}
-
-	if (!ov->dev) {
-		rc = -EIO;
-		goto error;
-	}
-
-// FIXME: Only supports two frames
-	/* See if a frame is completed, then use it. */
-	if (ov->frame[0].grabstate >= FRAME_DONE)	/* _DONE or _ERROR */
-		frmx = 0;
-	else if (ov->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
-		frmx = 1;
-
-	/* If nonblocking we return immediately */
-	if (noblock && (frmx == -1)) {
-		rc = -EAGAIN;
-		goto error;
-	}
-
-	/* If no FRAME_DONE, look for a FRAME_GRABBING state. */
-	/* See if a frame is in process (grabbing), then use it. */
-	if (frmx == -1) {
-		if (ov->frame[0].grabstate == FRAME_GRABBING)
-			frmx = 0;
-		else if (ov->frame[1].grabstate == FRAME_GRABBING)
-			frmx = 1;
-	}
-
-	/* If no frame is active, start one. */
-	if (frmx == -1) {
-		if ((rc = ov51x_new_frame(ov, frmx = 0))) {
-			err("read: ov51x_new_frame error");
-			goto error;
-		}
-	}
-
-	frame = &ov->frame[frmx];
-
-restart:
-	if (!ov->dev) {
-		rc = -EIO;
-		goto error;
-	}
-
-	/* Wait while we're grabbing the image */
-	PDEBUG(4, "Waiting image grabbing");
-	rc = wait_event_interruptible(frame->wq, 
-		(frame->grabstate == FRAME_DONE)
-		|| (frame->grabstate == FRAME_ERROR));
-
-	if (rc)
-		goto error;
-
-	PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
-	PDEBUG(4, "bytes_recvd = %d", frame->bytes_recvd);
-
-	if (frame->grabstate == FRAME_ERROR) {
-		frame->bytes_read = 0;
-		err("** ick! ** Errored frame %d", ov->curframe);
-		if (ov51x_new_frame(ov, frmx)) {
-			err("read: ov51x_new_frame error");
-			goto error;
-		}
-		goto restart;
-	}
-
-
-	/* Repeat until we get a snapshot frame */
-	if (ov->snap_enabled)
-		PDEBUG(4, "Waiting snapshot frame");
-	if (ov->snap_enabled && !frame->snapshot) {
-		frame->bytes_read = 0;
-		if ((rc = ov51x_new_frame(ov, frmx))) {
-			err("read: ov51x_new_frame error");
-			goto error;
-		}
-		goto restart;
-	}
-
-	/* Clear the snapshot */
-	if (ov->snap_enabled && frame->snapshot) {
-		frame->snapshot = 0;
-		ov51x_clear_snapshot(ov);
-	}
-
-	/* Decompression, format conversion, etc... */
-	ov51x_postprocess(ov, frame);
-
-	PDEBUG(4, "frmx=%d, bytes_read=%ld, length=%ld", frmx,
-		frame->bytes_read,
-		get_frame_length(frame));
-
-	/* copy bytes to user space; we allow for partials reads */
-//	if ((count + frame->bytes_read) 
-//	    > get_frame_length((struct ov511_frame *)frame))
-//		count = frame->scanlength - frame->bytes_read;
-
-	/* FIXME - count hardwired to be one frame... */
-	count = get_frame_length(frame);
-
-	PDEBUG(4, "Copy to user space: %ld bytes", count);
-	if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
-		PDEBUG(4, "Copy failed! %d bytes not copied", i);
-		rc = -EFAULT;
-		goto error;
-	}
-
-	frame->bytes_read += count;
-	PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
-		count, frame->bytes_read);
-
-	/* If all data has been read... */
-	if (frame->bytes_read
-	    >= get_frame_length(frame)) {
-		frame->bytes_read = 0;
-
-// FIXME: Only supports two frames
-		/* Mark it as available to be used again. */
-		ov->frame[frmx].grabstate = FRAME_UNUSED;
-		if ((rc = ov51x_new_frame(ov, !frmx))) {
-			err("ov51x_new_frame returned error");
-			goto error;
-		}
-	}
-
-	PDEBUG(4, "read finished, returning %ld (sweet)", count);
-
-	up(&ov->lock);
-	return count;
-
-error:
-	up(&ov->lock);
-	return rc;
-}
-
-static int
-ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *vdev = file->private_data;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end - vma->vm_start;
-	struct usb_ov511 *ov = vdev->priv;
-	unsigned long page, pos;
-
-	if (ov->dev == NULL)
-		return -EIO;
-
-	PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
-
-	if (size > (((OV511_NUMFRAMES
-	              * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight)
-	              + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))))
-		return -EINVAL;
-
-	if (down_interruptible(&ov->lock))
-		return -EINTR;
-
-	pos = (unsigned long)ov->fbuf;
-	while (size > 0) {
-		page = kvirt_to_pa(pos);
-		if (remap_page_range(vma, start, page, PAGE_SIZE,
-				     PAGE_SHARED)) {
-			up(&ov->lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	up(&ov->lock);
-	return 0;
-}
-
-static struct file_operations ov511_fops = {
-	owner:		THIS_MODULE,
-	open:		ov51x_v4l1_open,
-	release:       	ov51x_v4l1_close,
-	read:		ov51x_v4l1_read,
-	mmap:		ov51x_v4l1_mmap,
-	ioctl:          video_generic_ioctl,
-	llseek:         no_llseek,
-};
-
-static struct video_device vdev_template = {
-	owner:		THIS_MODULE,
-	name:		"OV511 USB Camera",
-	type:		VID_TYPE_CAPTURE,
-	hardware:	VID_HARDWARE_OV511,
-	fops:           &ov511_fops,
-	kernel_ioctl:	ov51x_v4l1_ioctl,
-};
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-static int 
-ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-		    unsigned long ularg)
-{
-	struct proc_dir_entry *pde;
-	struct usb_ov511 *ov;
-	void *arg = (void *) ularg;
-	int rc;
-
-	pde = PDE(inode);
-	if (!pde)
-		return -ENOENT;
-
-	ov = pde->data;
-	if (!ov)
-		return -ENODEV;
-
-	if (!ov->dev)
-		return -EIO;
-
-	/* Should we pass through standard V4L IOCTLs? */
-
-	switch (cmd) {
-	case OV511IOC_GINTVER:
-	{
-		int ver = OV511_INTERFACE_VER;
-
-		PDEBUG(4, "Get interface version: %d", ver);
-		if (copy_to_user(arg, &ver, sizeof(ver)))
-			return -EFAULT;
-
-		return 0;
-	}
-	case OV511IOC_GUSHORT:
-	{
-		struct ov511_ushort_opt opt;
-
-		if (copy_from_user(&opt, arg, sizeof(opt)))
-			return -EFAULT;
-
-		switch (opt.optnum) {
-		case OV511_USOPT_BRIGHT:
-			rc = sensor_get_brightness(ov, &(opt.val));
-			if (rc)	return rc;
-			break;
-		case OV511_USOPT_SAT:
-			rc = sensor_get_saturation(ov, &(opt.val));
-			if (rc)	return rc;
-			break;
-		case OV511_USOPT_HUE:
-			rc = sensor_get_hue(ov, &(opt.val));
-			if (rc)	return rc;
-			break;
-		case OV511_USOPT_CONTRAST:
-			rc = sensor_get_contrast(ov, &(opt.val));
-			if (rc)	return rc;
-			break;
-		default:
-			err("Invalid get short option number");
-			return -EINVAL;
-		}
-
-		if (copy_to_user(arg, &opt, sizeof(opt)))
-			return -EFAULT;
-
-		return 0;
-	}
-	case OV511IOC_SUSHORT:
-	{
-		struct ov511_ushort_opt opt;
-
-		if (copy_from_user(&opt, arg, sizeof(opt)))
-			return -EFAULT;
-
-		switch (opt.optnum) {
-		case OV511_USOPT_BRIGHT:
-			rc = sensor_set_brightness(ov, opt.val);
-			if (rc)	return rc;
-			break;
-		case OV511_USOPT_SAT:
-			rc = sensor_set_saturation(ov, opt.val);
-			if (rc)	return rc;
-			break;
-		case OV511_USOPT_HUE:
-			rc = sensor_set_hue(ov, opt.val);
-			if (rc)	return rc;
-			break;
-		case OV511_USOPT_CONTRAST:
-			rc = sensor_set_contrast(ov, opt.val);
-			if (rc)	return rc;
-			break;
-		default:
-			err("Invalid set short option number");
-			return -EINVAL;
-		}
-
-		return 0;
-	}
-	case OV511IOC_GUINT:
-	{
-		struct ov511_uint_opt opt;
-
-		if (copy_from_user(&opt, arg, sizeof(opt)))
-			return -EFAULT;
-
-		switch (opt.optnum) {
-		case OV511_UIOPT_POWER_FREQ:
-			opt.val = ov->lightfreq;
-			break;
-		case OV511_UIOPT_BFILTER:
-			opt.val = ov->bandfilt;
-			break;
-		case OV511_UIOPT_LED:
-			opt.val = ov->led_policy;
-			break;
-		case OV511_UIOPT_DEBUG:
-			opt.val = debug;
-			break;
-		case OV511_UIOPT_COMPRESS:
-			opt.val = ov->compress;
-			break;
-		default:
-			err("Invalid get int option number");
-			return -EINVAL;
-		}
-
-		if (copy_to_user(arg, &opt, sizeof(opt)))
-			return -EFAULT;
-
-		return 0;
-	}
-	case OV511IOC_SUINT:
-	{
-		struct ov511_uint_opt opt;
-
-		if (copy_from_user(&opt, arg, sizeof(opt)))
-			return -EFAULT;
-
-		switch (opt.optnum) {
-		case OV511_UIOPT_POWER_FREQ:
-			rc = sensor_set_light_freq(ov, opt.val);
-			if (rc)	return rc;
-			break;
-		case OV511_UIOPT_BFILTER:
-			rc = sensor_set_banding_filter(ov, opt.val);
-			if (rc)	return rc;
-			break;
-		case OV511_UIOPT_LED:
-			if (opt.val <= 2) {
-				ov->led_policy = opt.val;
-				if (ov->led_policy == LED_OFF)
-					ov51x_led_control(ov, 0);
-				else if (ov->led_policy == LED_ON)
-					ov51x_led_control(ov, 1);
-			} else {
-				return -EINVAL;
-			}
-			break;
-		case OV511_UIOPT_DEBUG:
-			if (opt.val <= 5)
-				debug = opt.val;
-			else
-				return -EINVAL;
-			break;
-		case OV511_UIOPT_COMPRESS:
-			ov->compress = opt.val;
-			if (ov->compress) {
-				if (ov->bclass == BCL_OV511)
-					ov511_init_compression(ov);
-				else if (ov->bclass == BCL_OV518)
-					ov518_init_compression(ov);
-			}
-			break;
-		default:
-			err("Invalid get int option number");
-			return -EINVAL;
-		}
-
-		return 0;
-	}
-	case OV511IOC_WI2C:
-	{
-		struct ov511_i2c_struct w;
-
-		if (copy_from_user(&w, arg, sizeof(w)))
-			return -EFAULT;
-
-		return i2c_w_slave(ov, w.slave, w.reg, w.value,
-			w.mask);
-	}
-	case OV511IOC_RI2C:
-	{
-		struct ov511_i2c_struct r;
-
-		if (copy_from_user(&r, arg, sizeof(r)))
-			return -EFAULT;
-
-		rc = i2c_r_slave(ov, r.slave, r.reg);
-		if (rc < 0)
-			return rc;
-
-		r.value = rc;
-
-		if (copy_to_user(arg, &r, sizeof(r)))
-			return -EFAULT;
-
-		return 0;
-	}
-	default:
-		return -EINVAL;
-	} /* end switch */
-
-	return 0;
-}
-#endif
-
-/****************************************************************************
- *
- * OV511 and sensor configuration
- *
- ***************************************************************************/
-
-/* This initializes the OV7610, OV7620, or OV7620AE sensor. The OV7620AE uses
- * the same register settings as the OV7610, since they are very similar.
- */
-static int 
-ov7xx0_configure(struct usb_ov511 *ov)
-{
-	int i, success;
-	int rc;
-
-	/* Lawrence Glaister <lg@jfm.bc.ca> reports:
-	 *
-	 * Register 0x0f in the 7610 has the following effects:
-	 *
-	 * 0x85 (AEC method 1): Best overall, good contrast range
-	 * 0x45 (AEC method 2): Very overexposed
-	 * 0xa5 (spec sheet default): Ok, but the black level is
-	 *	shifted resulting in loss of contrast
-	 * 0x05 (old driver setting): very overexposed, too much
-	 *	contrast
-	 */
-	static struct ov511_regvals aRegvalsNorm7610[] = {
-		{ OV511_I2C_BUS, 0x10, 0xff },
-		{ OV511_I2C_BUS, 0x16, 0x06 },
-		{ OV511_I2C_BUS, 0x28, 0x24 },
-		{ OV511_I2C_BUS, 0x2b, 0xac },
-		{ OV511_I2C_BUS, 0x12, 0x00 },
-		{ OV511_I2C_BUS, 0x38, 0x81 },
-		{ OV511_I2C_BUS, 0x28, 0x24 },	/* 0c */
-		{ OV511_I2C_BUS, 0x0f, 0x85 },	/* lg's setting */
-		{ OV511_I2C_BUS, 0x15, 0x01 },
-		{ OV511_I2C_BUS, 0x20, 0x1c },
-		{ OV511_I2C_BUS, 0x23, 0x2a },
-		{ OV511_I2C_BUS, 0x24, 0x10 },
-		{ OV511_I2C_BUS, 0x25, 0x8a },
-		{ OV511_I2C_BUS, 0x26, 0xa2 },
-		{ OV511_I2C_BUS, 0x27, 0xc2 },
-		{ OV511_I2C_BUS, 0x2a, 0x04 },
-		{ OV511_I2C_BUS, 0x2c, 0xfe },
-		{ OV511_I2C_BUS, 0x2d, 0x93 },
-		{ OV511_I2C_BUS, 0x30, 0x71 },
-		{ OV511_I2C_BUS, 0x31, 0x60 },
-		{ OV511_I2C_BUS, 0x32, 0x26 },
-		{ OV511_I2C_BUS, 0x33, 0x20 },
-		{ OV511_I2C_BUS, 0x34, 0x48 },
-		{ OV511_I2C_BUS, 0x12, 0x24 },
-		{ OV511_I2C_BUS, 0x11, 0x01 },
-		{ OV511_I2C_BUS, 0x0c, 0x24 },
-		{ OV511_I2C_BUS, 0x0d, 0x24 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	static struct ov511_regvals aRegvalsNorm7620[] = {
-		{ OV511_I2C_BUS, 0x00, 0x00 },
-		{ OV511_I2C_BUS, 0x01, 0x80 },
-		{ OV511_I2C_BUS, 0x02, 0x80 },
-		{ OV511_I2C_BUS, 0x03, 0xc0 },
-		{ OV511_I2C_BUS, 0x06, 0x60 },
-		{ OV511_I2C_BUS, 0x07, 0x00 },
-		{ OV511_I2C_BUS, 0x0c, 0x24 },
-		{ OV511_I2C_BUS, 0x0c, 0x24 },
-		{ OV511_I2C_BUS, 0x0d, 0x24 },
-		{ OV511_I2C_BUS, 0x11, 0x01 },
-		{ OV511_I2C_BUS, 0x12, 0x24 },
-		{ OV511_I2C_BUS, 0x13, 0x01 },
-		{ OV511_I2C_BUS, 0x14, 0x84 },
-		{ OV511_I2C_BUS, 0x15, 0x01 },
-		{ OV511_I2C_BUS, 0x16, 0x03 },
-		{ OV511_I2C_BUS, 0x17, 0x2f },
-		{ OV511_I2C_BUS, 0x18, 0xcf },
-		{ OV511_I2C_BUS, 0x19, 0x06 },
-		{ OV511_I2C_BUS, 0x1a, 0xf5 },
-		{ OV511_I2C_BUS, 0x1b, 0x00 },
-		{ OV511_I2C_BUS, 0x20, 0x18 },
-		{ OV511_I2C_BUS, 0x21, 0x80 },
-		{ OV511_I2C_BUS, 0x22, 0x80 },
-		{ OV511_I2C_BUS, 0x23, 0x00 },
-		{ OV511_I2C_BUS, 0x26, 0xa2 },
-		{ OV511_I2C_BUS, 0x27, 0xea },
-		{ OV511_I2C_BUS, 0x28, 0x20 },
-		{ OV511_I2C_BUS, 0x29, 0x00 },
-		{ OV511_I2C_BUS, 0x2a, 0x10 },
-		{ OV511_I2C_BUS, 0x2b, 0x00 },
-		{ OV511_I2C_BUS, 0x2c, 0x88 },
-		{ OV511_I2C_BUS, 0x2d, 0x91 },
-		{ OV511_I2C_BUS, 0x2e, 0x80 },
-		{ OV511_I2C_BUS, 0x2f, 0x44 },
-		{ OV511_I2C_BUS, 0x60, 0x27 },
-		{ OV511_I2C_BUS, 0x61, 0x02 },
-		{ OV511_I2C_BUS, 0x62, 0x5f },
-		{ OV511_I2C_BUS, 0x63, 0xd5 },
-		{ OV511_I2C_BUS, 0x64, 0x57 },
-		{ OV511_I2C_BUS, 0x65, 0x83 },
-		{ OV511_I2C_BUS, 0x66, 0x55 },
-		{ OV511_I2C_BUS, 0x67, 0x92 },
-		{ OV511_I2C_BUS, 0x68, 0xcf },
-		{ OV511_I2C_BUS, 0x69, 0x76 },
-		{ OV511_I2C_BUS, 0x6a, 0x22 },
-		{ OV511_I2C_BUS, 0x6b, 0x00 },
-		{ OV511_I2C_BUS, 0x6c, 0x02 },
-		{ OV511_I2C_BUS, 0x6d, 0x44 },
-		{ OV511_I2C_BUS, 0x6e, 0x80 },
-		{ OV511_I2C_BUS, 0x6f, 0x1d },
-		{ OV511_I2C_BUS, 0x70, 0x8b },
-		{ OV511_I2C_BUS, 0x71, 0x00 },
-		{ OV511_I2C_BUS, 0x72, 0x14 },
-		{ OV511_I2C_BUS, 0x73, 0x54 },
-		{ OV511_I2C_BUS, 0x74, 0x00 },
-		{ OV511_I2C_BUS, 0x75, 0x8e },
-		{ OV511_I2C_BUS, 0x76, 0x00 },
-		{ OV511_I2C_BUS, 0x77, 0xff },
-		{ OV511_I2C_BUS, 0x78, 0x80 },
-		{ OV511_I2C_BUS, 0x79, 0x80 },
-		{ OV511_I2C_BUS, 0x7a, 0x80 },
-		{ OV511_I2C_BUS, 0x7b, 0xe2 },
-		{ OV511_I2C_BUS, 0x7c, 0x00 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	PDEBUG(4, "starting configuration");
-
-	/* This looks redundant, but is necessary for WebCam 3 */
-	ov->primary_i2c_slave = OV7xx0_SID;
-	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
-		return -1;
-
-	if (init_ov_sensor(ov) >= 0) {
-		PDEBUG(1, "OV7xx0 sensor initalized (method 1)");
-	} else {
-		/* Reset the 76xx */
-		if (i2c_w(ov, 0x12, 0x80) < 0) return -1;
-
-		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
-
-		i = 0;
-		success = 0;
-		while (i <= i2c_detect_tries) {
-			if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
-			    (i2c_r(ov, OV7610_REG_ID_LOW) == 0xA2)) {
-				success = 1;
-				break;
-			} else {
-				i++;
-			}
-		}
-
-// Was (i == i2c_detect_tries) previously. This obviously used to always report
-// success. Whether anyone actually depended on that bug is unknown
-		if ((i >= i2c_detect_tries) && (success == 0)) {
-			err("Failed to read sensor ID. You might not have an");
-			err("OV7610/20, or it may be not responding. Report");
-			err("this to " EMAIL);
-			err("This is only a warning. You can attempt to use");
-			err("your camera anyway");
-// Only issue a warning for now  
-//			return -1;
-		} else {
-			PDEBUG(1, "OV7xx0 initialized (method 2, %dx)", i+1);
-		}
-	}
-
-	/* Detect sensor (sub)type */
-	rc = i2c_r(ov, OV7610_REG_COM_I);
-
-	if (rc < 0) {
-		err("Error detecting sensor type");
-		return -1;
-	} else if ((rc & 3) == 3) {
-		info("Sensor is an OV7610");
-		ov->sensor = SEN_OV7610;
-	} else if ((rc & 3) == 1) {
-		/* I don't know what's different about the 76BE yet */
-		if (i2c_r(ov, 0x15) & 1)
-			info("Sensor is an OV7620AE");
-		else
-			info("Sensor is an OV76BE");
-
-		/* OV511+ will return all zero isoc data unless we
-		 * configure the sensor as a 7620. Someone needs to
-		 * find the exact reg. setting that causes this. */
-		if (ov->bridge == BRG_OV511PLUS) {
-			info("Enabling 511+/7620AE workaround");
-			ov->sensor = SEN_OV7620;
-		} else {
-			ov->sensor = SEN_OV7620AE;
-		}
-	} else if ((rc & 3) == 0) {
-		info("Sensor is an OV7620");
-		ov->sensor = SEN_OV7620;
-	} else {
-		err("Unknown image sensor version: %d", rc & 3);
-		return -1;
-	}
-
-	if (ov->sensor == SEN_OV7620) {
-		PDEBUG(4, "Writing 7620 registers");
-		if (write_regvals(ov, aRegvalsNorm7620))
-			return -1;
-	} else {
-		PDEBUG(4, "Writing 7610 registers");
-		if (write_regvals(ov, aRegvalsNorm7610))
-			return -1;
-	}
-
-	/* Set sensor-specific vars */
-	ov->maxwidth = 640;
-	ov->maxheight = 480;
-	ov->minwidth = 64;
-	ov->minheight = 48;
-
-	// FIXME: These do not match the actual settings yet
-	ov->brightness = 0x80 << 8;
-	ov->contrast = 0x80 << 8;
-	ov->colour = 0x80 << 8;
-	ov->hue = 0x80 << 8;
-
-	return 0;
-}
-
-/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
-static int 
-ov6xx0_configure(struct usb_ov511 *ov)
-{
-	int rc;
-
-	static struct ov511_regvals aRegvalsNorm6x20[] = {
-		{ OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
-		{ OV511_I2C_BUS, 0x11, 0x01 },
-		{ OV511_I2C_BUS, 0x03, 0x60 },
-		{ OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
-		{ OV511_I2C_BUS, 0x07, 0xa8 },
-		/* The ratio of 0x0c and 0x0d  controls the white point */
-		{ OV511_I2C_BUS, 0x0c, 0x24 },
-		{ OV511_I2C_BUS, 0x0d, 0x24 },
-		{ OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
-		{ OV511_I2C_BUS, 0x14, 0x04 },
-		/* 0x16: 0x06 helps frame stability with moving objects */
-		{ OV511_I2C_BUS, 0x16, 0x06 },
-//		{ OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
-		{ OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
-		/* 0x28: 0x05 Selects RGB format if RGB on */
-		{ OV511_I2C_BUS, 0x28, 0x05 },
-		{ OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
-//		{ OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
-		{ OV511_I2C_BUS, 0x2d, 0x99 },
-		{ OV511_I2C_BUS, 0x34, 0xd2 }, /* Max A/D range */
-		{ OV511_I2C_BUS, 0x38, 0x8b },
-		{ OV511_I2C_BUS, 0x39, 0x40 },
-		
-		{ OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
-		{ OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
-		{ OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
-
-		{ OV511_I2C_BUS, 0x3d, 0x80 },
-		/* These next two registers (0x4a, 0x4b) are undocumented. They
-		 * control the color balance */
-		{ OV511_I2C_BUS, 0x4a, 0x80 },
-		{ OV511_I2C_BUS, 0x4b, 0x80 },
-		{ OV511_I2C_BUS, 0x4d, 0xd2 }, /* This reduces noise a bit */
-		{ OV511_I2C_BUS, 0x4e, 0xc1 },
-		{ OV511_I2C_BUS, 0x4f, 0x04 },
-// Do 50-53 have any effect?
-// Toggle 0x12[2] off and on here?
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	/* This chip is undocumented so many of these are guesses. OK=verified,
-	 * A=Added since 6620, U=unknown function (not a 6620 reg) */
-	static struct ov511_regvals aRegvalsNorm6x30[] = {
-	/*OK*/	{ OV511_I2C_BUS, 0x12, 0x80 }, /* reset */
-	/*00?*/	{ OV511_I2C_BUS, 0x11, 0x01 },
-	/*OK*/	{ OV511_I2C_BUS, 0x03, 0x60 },
-	/*0A?*/	{ OV511_I2C_BUS, 0x05, 0x7f }, /* For when autoadjust is off */
-		{ OV511_I2C_BUS, 0x07, 0xa8 },
-		/* The ratio of 0x0c and 0x0d  controls the white point */
-	/*OK*/	{ OV511_I2C_BUS, 0x0c, 0x24 },
-	/*OK*/	{ OV511_I2C_BUS, 0x0d, 0x24 },
-	/*A*/	{ OV511_I2C_BUS, 0x0e, 0x20 },
-
-//	/*24?*/	{ OV511_I2C_BUS, 0x12, 0x28 }, /* Enable AGC */
-//		{ OV511_I2C_BUS, 0x12, 0x24 }, /* Enable AGC */
-
-//	/*A*/	{ OV511_I2C_BUS, 0x13, 0x21 },
-//	/*A*/	{ OV511_I2C_BUS, 0x13, 0x25 }, /* Tristate Y and UV busses */
-
-//	/*04?*/	{ OV511_I2C_BUS, 0x14, 0x80 },
-		/* 0x16: 0x06 helps frame stability with moving objects */
-	/*03?*/	{ OV511_I2C_BUS, 0x16, 0x06 },
-//	/*OK*/	{ OV511_I2C_BUS, 0x20, 0x30 }, /* Aperture correction enable */
-		// 21 & 22? The suggested values look wrong. Go with default
-	/*A*/	{ OV511_I2C_BUS, 0x23, 0xc0 },
-	/*A*/	{ OV511_I2C_BUS, 0x25, 0x9a }, // Check this against default
-//	/*OK*/	{ OV511_I2C_BUS, 0x26, 0xb2 }, /* BLC enable */
-
-		/* 0x28: 0x05 Selects RGB format if RGB on */
-//	/*04?*/	{ OV511_I2C_BUS, 0x28, 0x05 },
-//	/*04?*/	{ OV511_I2C_BUS, 0x28, 0x45 }, // DEBUG: Tristate UV bus
-
-	/*OK*/	{ OV511_I2C_BUS, 0x2a, 0x04 }, /* Disable framerate adjust */
-//	/*OK*/	{ OV511_I2C_BUS, 0x2b, 0xac }, /* Framerate; Set 2a[7] first */
-//	/*U*/	{ OV511_I2C_BUS, 0x2c, 0xa0 },
-		{ OV511_I2C_BUS, 0x2d, 0x99 },
-//	/*A*/	{ OV511_I2C_BUS, 0x33, 0x26 }, // Reserved bits on 6620
-//	/*d2?*/	{ OV511_I2C_BUS, 0x34, 0x03 }, /* Max A/D range */
-//	/*U*/	{ OV511_I2C_BUS, 0x36, 0x8f }, // May not be necessary
-//	/*U*/	{ OV511_I2C_BUS, 0x37, 0x80 }, // May not be necessary
-//	/*8b?*/	{ OV511_I2C_BUS, 0x38, 0x83 },
-//	/*40?*/	{ OV511_I2C_BUS, 0x39, 0xc0 }, // 6630 adds bit 7
-//		{ OV511_I2C_BUS, 0x3c, 0x39 }, /* Enable AEC mode changing */
-//		{ OV511_I2C_BUS, 0x3c, 0x3c }, /* Change AEC mode */
-//		{ OV511_I2C_BUS, 0x3c, 0x24 }, /* Disable AEC mode changing */
-	/*OK*/	{ OV511_I2C_BUS, 0x3d, 0x80 },
-//	/*A*/	{ OV511_I2C_BUS, 0x3f, 0x0e },
-//	/*U*/	{ OV511_I2C_BUS, 0x40, 0x00 },
-//	/*U*/	{ OV511_I2C_BUS, 0x41, 0x00 },
-//	/*U*/	{ OV511_I2C_BUS, 0x42, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x43, 0x3f },
-//	/*U*/	{ OV511_I2C_BUS, 0x44, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x45, 0x20 },
-//	/*U*/	{ OV511_I2C_BUS, 0x46, 0x20 },
-//	/*U*/	{ OV511_I2C_BUS, 0x47, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x48, 0x7f },
-//	/*U*/	{ OV511_I2C_BUS, 0x49, 0x00 },
-
-		/* These next two registers (0x4a, 0x4b) are undocumented. They
-		 * control the color balance */
-//	/*OK?*/	{ OV511_I2C_BUS, 0x4a, 0x80 }, // Check these
-//	/*OK?*/	{ OV511_I2C_BUS, 0x4b, 0x80 },
-//	/*U*/	{ OV511_I2C_BUS, 0x4c, 0xd0 }, 
-	/*d2?*/	{ OV511_I2C_BUS, 0x4d, 0x10 }, /* This reduces noise a bit */
-	/*c1?*/	{ OV511_I2C_BUS, 0x4e, 0x40 },
-	/*04?*/	{ OV511_I2C_BUS, 0x4f, 0x07 },
-//	/*U*/	{ OV511_I2C_BUS, 0x50, 0xff },
-	/*U*/	{ OV511_I2C_BUS, 0x54, 0x23 },
-//	/*U*/	{ OV511_I2C_BUS, 0x55, 0xff },
-//	/*U*/	{ OV511_I2C_BUS, 0x56, 0x12 },
-	/*U*/	{ OV511_I2C_BUS, 0x57, 0x81 },
-//	/*U*/	{ OV511_I2C_BUS, 0x58, 0x75 },
-	/*U*/	{ OV511_I2C_BUS, 0x59, 0x01 },
-	/*U*/	{ OV511_I2C_BUS, 0x5a, 0x2c },
-	/*U*/	{ OV511_I2C_BUS, 0x5b, 0x0f },
-//	/*U*/	{ OV511_I2C_BUS, 0x5c, 0x10 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	PDEBUG(4, "starting sensor configuration");
-	
-	if (init_ov_sensor(ov) < 0) {
-		err("Failed to read sensor ID. You might not have an OV6xx0,");
-		err("or it may be not responding. Report this to " EMAIL);
-		return -1;
-	} else {
-		PDEBUG(1, "OV6xx0 sensor detected");
-	}
-
-	/* Detect sensor (sub)type */
-	rc = i2c_r(ov, OV7610_REG_COM_I);
-
-	if (rc < 0) {
-		err("Error detecting sensor type");
-		return -1;
-	} 
-
-	if ((rc & 3) == 0)
-		ov->sensor = SEN_OV6630;
-	else if ((rc & 3) == 1)
-		ov->sensor = SEN_OV6620;
-	else if ((rc & 3) == 2)
-		ov->sensor = SEN_OV6630;
-	else if ((rc & 3) == 3)
-		ov->sensor = SEN_OV6630;
-
-	info("Sensor is an %s", symbolic(senlist, ov->sensor));
-
-	/* Set sensor-specific vars */
-	ov->maxwidth = 352;
-	ov->maxheight = 288;
-	ov->minwidth = 64;
-	ov->minheight = 48;
-
-	// FIXME: These do not match the actual settings yet
-	ov->brightness = 0x80 << 8;
-	ov->contrast = 0x80 << 8;
-	ov->colour = 0x80 << 8;
-	ov->hue = 0x80 << 8;
-
-	if (ov->sensor == SEN_OV6620) {
-		PDEBUG(4, "Writing 6x20 registers");
-		if (write_regvals(ov, aRegvalsNorm6x20))
-			return -1;
-	} else {
-		PDEBUG(4, "Writing 6x30 registers");
-		if (write_regvals(ov, aRegvalsNorm6x30))
-			return -1;
-	}
-	
-	return 0;
-}
-
-/* This initializes the KS0127 and KS0127B video decoders. */
-static int 
-ks0127_configure(struct usb_ov511 *ov)
-{
-	int rc;
-
-// FIXME: I don't know how to sync or reset it yet
-#if 0
-	if (ov51x_init_ks_sensor(ov) < 0) {
-		err("Failed to initialize the KS0127");
-		return -1;
-	} else {
-		PDEBUG(1, "KS012x(B) sensor detected");
-	}
-#endif
-
-	/* Detect decoder subtype */
-	rc = i2c_r(ov, 0x00);
-	if (rc < 0) {
-		err("Error detecting sensor type");
-		return -1;
-	} else if (rc & 0x08) {
-		rc = i2c_r(ov, 0x3d);
-		if (rc < 0) {
-			err("Error detecting sensor type");
-			return -1;
-		} else if ((rc & 0x0f) == 0) {
-			info("Sensor is a KS0127");
-			ov->sensor = SEN_KS0127;
-		} else if ((rc & 0x0f) == 9) {
-			info("Sensor is a KS0127B Rev. A");
-			ov->sensor = SEN_KS0127B;
-		}
-	} else {
-		err("Error: Sensor is an unsupported KS0122");
-		return -1;
-	}
-
-	/* Set sensor-specific vars */
-	ov->maxwidth = 640;
-	ov->maxheight = 480;
-	ov->minwidth = 64;
-	ov->minheight = 48;
-
-	// FIXME: These do not match the actual settings yet
-	ov->brightness = 0x80 << 8;
-	ov->contrast = 0x80 << 8;
-	ov->colour = 0x80 << 8;
-	ov->hue = 0x80 << 8;
-
-	/* This device is not supported yet. Bail out now... */
-	err("This sensor is not supported yet.");
-	return -1;
-
-	return 0;
-}
-
-/* This initializes the SAA7111A video decoder. */
-static int 
-saa7111a_configure(struct usb_ov511 *ov)
-{
-	int rc;
-
-	/* Since there is no register reset command, all registers must be
-	 * written, otherwise gives erratic results */
-	static struct ov511_regvals aRegvalsNormSAA7111A[] = {
-		{ OV511_I2C_BUS, 0x06, 0xce },
-		{ OV511_I2C_BUS, 0x07, 0x00 },
-		{ OV511_I2C_BUS, 0x10, 0x44 }, /* YUV422, 240/286 lines */
-		{ OV511_I2C_BUS, 0x0e, 0x01 }, /* NTSC M or PAL BGHI */
-		{ OV511_I2C_BUS, 0x00, 0x00 },
-		{ OV511_I2C_BUS, 0x01, 0x00 },
-		{ OV511_I2C_BUS, 0x03, 0x23 },
-		{ OV511_I2C_BUS, 0x04, 0x00 },
-		{ OV511_I2C_BUS, 0x05, 0x00 },
-		{ OV511_I2C_BUS, 0x08, 0xc8 }, /* Auto field freq */
-		{ OV511_I2C_BUS, 0x09, 0x01 }, /* Chrom. trap off, APER=0.25 */
-		{ OV511_I2C_BUS, 0x0a, 0x80 }, /* BRIG=128 */
-		{ OV511_I2C_BUS, 0x0b, 0x40 }, /* CONT=1.0 */
-		{ OV511_I2C_BUS, 0x0c, 0x40 }, /* SATN=1.0 */
-		{ OV511_I2C_BUS, 0x0d, 0x00 }, /* HUE=0 */
-		{ OV511_I2C_BUS, 0x0f, 0x00 },
-		{ OV511_I2C_BUS, 0x11, 0x0c },
-		{ OV511_I2C_BUS, 0x12, 0x00 },
-		{ OV511_I2C_BUS, 0x13, 0x00 },
-		{ OV511_I2C_BUS, 0x14, 0x00 },
-		{ OV511_I2C_BUS, 0x15, 0x00 },
-		{ OV511_I2C_BUS, 0x16, 0x00 },
-		{ OV511_I2C_BUS, 0x17, 0x00 },
-		{ OV511_I2C_BUS, 0x02, 0xc0 },	/* Composite input 0 */
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-// FIXME: I don't know how to sync or reset it yet
-#if 0
-	if (ov51x_init_saa_sensor(ov) < 0) {
-		err("Failed to initialize the SAA7111A");
-		return -1;
-	} else {
-		PDEBUG(1, "SAA7111A sensor detected");
-	}
-#endif
-
-	/* Set sensor-specific vars */
-	ov->maxwidth = 640;
-	ov->maxheight = 480;		/* Even/Odd fields */
-	ov->minwidth = 320;
-	ov->minheight = 240;		/* Even field only */
-
-	ov->has_decoder = 1;
-	ov->num_inputs = 8;
-	ov->norm = VIDEO_MODE_AUTO;
-	ov->stop_during_set = 0;	/* Decoder guarantees stable image */
-
-	/* Decoder doesn't change these values, so we use these instead of
-	 * acutally reading the registers (which doesn't work) */
-	ov->brightness = 0x80 << 8;
-	ov->contrast = 0x40 << 9;
-	ov->colour = 0x40 << 9;
-	ov->hue = 32768;
-
-	PDEBUG(4, "Writing SAA7111A registers");
-	if (write_regvals(ov, aRegvalsNormSAA7111A))
-		return -1;
-
-	/* Detect version of decoder. This must be done after writing the
-         * initial regs or the decoder will lock up. */
-	rc = i2c_r(ov, 0x00);
-
-	if (rc < 0) {
-		err("Error detecting sensor version");
-		return -1;
-	} else {
-		info("Sensor is an SAA7111A (version 0x%x)", rc);
-		ov->sensor = SEN_SAA7111A;
-	}
-
-	// FIXME: Fix this for OV518(+)
-	/* Latch to negative edge of clock. Otherwise, we get incorrect
-	 * colors and jitter in the digital signal. */
-	if (ov->bclass == BCL_OV511)
-		reg_w(ov, 0x11, 0x00);
-	else
-		warn("SAA7111A not yet supported with OV518/OV518+");
-
-	return 0;
-}
-
-/* This initializes the OV511/OV511+ and the sensor */
-static int 
-ov511_configure(struct usb_ov511 *ov)
-{
-	static struct ov511_regvals aRegvalsInit511[] = {
-		{ OV511_REG_BUS, R51x_SYS_RESET,	0x7f },
-	 	{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
-	 	{ OV511_REG_BUS, R51x_SYS_RESET,	0x7f },
-		{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
-		{ OV511_REG_BUS, R51x_SYS_RESET,	0x3f },
-		{ OV511_REG_BUS, R51x_SYS_INIT,		0x01 },
-		{ OV511_REG_BUS, R51x_SYS_RESET,	0x3d },
-		{ OV511_DONE_BUS, 0x0, 0x00},
-	};
-
-	static struct ov511_regvals aRegvalsNorm511[] = {
-		{ OV511_REG_BUS, R511_DRAM_FLOW_CTL, 	0x01 },
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x03 },
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
-		{ OV511_REG_BUS, R511_FIFO_OPTS,	0x1f },
-		{ OV511_REG_BUS, R511_COMP_EN,		0x00 },
-		{ OV511_REG_BUS, R511_COMP_LUT_EN,	0x03 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	static struct ov511_regvals aRegvalsNorm511Plus[] = {
-		{ OV511_REG_BUS, R511_DRAM_FLOW_CTL,	0xff },
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x03 },
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 },
-		{ OV511_REG_BUS, R511_FIFO_OPTS,	0xff },
-		{ OV511_REG_BUS, R511_COMP_EN,		0x00 },
-		{ OV511_REG_BUS, R511_COMP_LUT_EN,	0x03 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	PDEBUG(4, "");
-
-	ov->customid = reg_r(ov, R511_SYS_CUST_ID);
-	if (ov->customid < 0) {
-		err("Unable to read camera bridge registers");
-		goto error;
-	}
-
-	PDEBUG (1, "CustomID = %d", ov->customid);
-	ov->desc = symbolic(camlist, ov->customid);
-	info("model: %s", ov->desc);
-
-	if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) {
-		err("Camera type (%d) not recognized", ov->customid);
-		err("Please notify " EMAIL " of the name,");
-		err("manufacturer, model, and this number of your camera.");
-		err("Also include the output of the detection process.");
-	} 
-
-	if (ov->customid == 6) {	/* USB Life TV (NTSC) */
-		ov->tuner_type = 8;		/* Temic 4036FY5 3X 1981 */
-	}
-
-	if (write_regvals(ov, aRegvalsInit511)) goto error;
-
-	if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
-		ov51x_led_control(ov, 0);
-
-	/* The OV511+ has undocumented bits in the flow control register.
-	 * Setting it to 0xff fixes the corruption with moving objects. */
-	if (ov->bridge == BRG_OV511) {
-		if (write_regvals(ov, aRegvalsNorm511)) goto error;
-	} else if (ov->bridge == BRG_OV511PLUS) {
-		if (write_regvals(ov, aRegvalsNorm511Plus)) goto error;
-	} else {
-		err("Invalid bridge");
-	}
-
-	if (ov511_init_compression(ov)) goto error;
-
-	ov51x_set_packet_size(ov, 0);
-
-	ov->snap_enabled = snapshot;	
-
-	/* Test for 7xx0 */
-	PDEBUG(3, "Testing for 0V7xx0");
-	ov->primary_i2c_slave = OV7xx0_SID;
-	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
-		goto error;
-
-	if (i2c_w(ov, 0x12, 0x80) < 0) {
-		/* Test for 6xx0 */
-		PDEBUG(3, "Testing for 0V6xx0");
-		ov->primary_i2c_slave = OV6xx0_SID;
-		if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
-			goto error;
-
-		if (i2c_w(ov, 0x12, 0x80) < 0) {
-			/* Test for 8xx0 */
-			PDEBUG(3, "Testing for 0V8xx0");
-			ov->primary_i2c_slave = OV8xx0_SID;
-			if (ov51x_set_slave_ids(ov, OV8xx0_SID))
-				goto error;
-
-			if (i2c_w(ov, 0x12, 0x80) < 0) {
-				/* Test for SAA7111A */
-				PDEBUG(3, "Testing for SAA7111A");
-				ov->primary_i2c_slave = SAA7111A_SID;
-				if (ov51x_set_slave_ids(ov, SAA7111A_SID))
-					goto error;
-
-				if (i2c_w(ov, 0x0d, 0x00) < 0) {
-					/* Test for KS0127 */
-					PDEBUG(3, "Testing for KS0127");
-					ov->primary_i2c_slave = KS0127_SID;
-					if (ov51x_set_slave_ids(ov, KS0127_SID))
-						goto error;
-
-					if (i2c_w(ov, 0x10, 0x00) < 0) {
-						err("Can't determine sensor slave IDs");
-		 				goto error;
-					} else {
-						if (ks0127_configure(ov) < 0) {
-							err("Failed to configure KS0127");
-	 						goto error;
-						}
-					}
-				} else {
-					if (saa7111a_configure(ov) < 0) {
-						err("Failed to configure SAA7111A");
-	 					goto error;
-					}
-				}
-			} else {
-				err("Detected unsupported OV8xx0 sensor");
-				goto error;
-			}
-		} else {
-			if (ov6xx0_configure(ov) < 0) {
-				err("Failed to configure OV6xx0");
- 				goto error;
-			}
-		}
-	} else {
-		if (ov7xx0_configure(ov) < 0) {
-			err("Failed to configure OV7xx0");
-	 		goto error;
-		}
-	}
-
-	return 0;
-
-error:
-	err("OV511 Config failed");
-
-	return -EBUSY;
-}
-
-/* This initializes the OV518/OV518+ and the sensor */
-static int 
-ov518_configure(struct usb_ov511 *ov)
-{
-	static struct ov511_regvals aRegvalsInit518[] = {
-		{ OV511_REG_BUS, R51x_SYS_RESET,	0x40 },
-	 	{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
-	 	{ OV511_REG_BUS, R51x_SYS_RESET,	0x3e },
-		{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
-		{ OV511_REG_BUS, R51x_SYS_RESET,	0x00 },
-		{ OV511_REG_BUS, R51x_SYS_INIT,		0xe1 },
-		{ OV511_REG_BUS, 0x46,			0x00 }, 
-		{ OV511_REG_BUS, 0x5d,			0x03 },
-		{ OV511_DONE_BUS, 0x0, 0x00},
-	};
-
-	/* New values, based on Windows driver. Since what they do is not
-	 * known yet, this may be incorrect. */
-	static struct ov511_regvals aRegvalsNorm518[] = {
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x02 }, /* Reset */
-		{ OV511_REG_BUS, R51x_SYS_SNAP,		0x01 }, /* Enable */
-		{ OV511_REG_BUS, 0x31, 			0x0f },
-		{ OV511_REG_BUS, 0x5d,			0x03 },
-		{ OV511_REG_BUS, 0x24,			0x9f },
-		{ OV511_REG_BUS, 0x25,			0x90 },
-		{ OV511_REG_BUS, 0x20,			0x00 }, /* Was 0x08 */
-		{ OV511_REG_BUS, 0x51,			0x04 },
-		{ OV511_REG_BUS, 0x71,			0x19 },
-		{ OV511_DONE_BUS, 0x0, 0x00 },
-	};
-
-	PDEBUG(4, "");
-
-	/* First 5 bits of custom ID reg are a revision ID on OV518 */
-	info("Device revision %d", 0x1F & reg_r(ov, R511_SYS_CUST_ID));
-
-	if (write_regvals(ov, aRegvalsInit518)) goto error;
-
-	/* Set LED GPIO pin to output mode */
-	if (reg_w_mask(ov, 0x57, 0x00, 0x02) < 0) goto error;
-
-	/* LED is off by default with OV518; have to explicitly turn it on */
-	if (ov->led_policy == LED_OFF || ov->led_policy == LED_AUTO)
-		ov51x_led_control(ov, 0);
-	else
-		ov51x_led_control(ov, 1);
-
-	/* Don't require compression if dumppix is enabled; otherwise it's
-	 * required. OV518 has no uncompressed mode, to save RAM. */
-	if (!dumppix && !ov->compress) {
-		ov->compress = 1;
-		warn("Compression required with OV518...enabling");
-	}
-
-	if (write_regvals(ov, aRegvalsNorm518)) goto error;
-
-	if (reg_w(ov, 0x2f, 0x80) < 0) goto error;
-
-	if (ov518_init_compression(ov)) goto error;
-
-	ov51x_set_packet_size(ov, 0);
-
-	ov->snap_enabled = snapshot;
-
-	/* Test for 76xx */
-	ov->primary_i2c_slave = OV7xx0_SID;
-	if (ov51x_set_slave_ids(ov, OV7xx0_SID) < 0)
-		goto error;
-
-	/* The OV518 must be more aggressive about sensor detection since
-	 * I2C write will never fail if the sensor is not present. We have
-	 * to try to initialize the sensor to detect its presence */
-
-	if (init_ov_sensor(ov) < 0) {
-		/* Test for 6xx0 */
-		ov->primary_i2c_slave = OV6xx0_SID;
-		if (ov51x_set_slave_ids(ov, OV6xx0_SID) < 0)
-			goto error;
-
-		if (init_ov_sensor(ov) < 0) {
-			/* Test for 8xx0 */
-			ov->primary_i2c_slave = OV8xx0_SID;
-			if (ov51x_set_slave_ids(ov, OV8xx0_SID) < 0)
-				goto error;
-
-			if (init_ov_sensor(ov) < 0) {
-				err("Can't determine sensor slave IDs");
- 				goto error;
-			} else {
-				err("Detected unsupported OV8xx0 sensor");
-				goto error;
-			}
-		} else {
-			if (ov6xx0_configure(ov) < 0) {
-				err("Failed to configure OV6xx0");
- 				goto error;
-			}
-		}
-	} else {
-		if (ov7xx0_configure(ov) < 0) {
-			err("Failed to configure OV7xx0");
-	 		goto error;
-		}
-	}
-
-	// FIXME: Sizes > 320x240 are not working yet
-	ov->maxwidth = 320;
-	ov->maxheight = 240;
-
-	// The OV518 cannot go as low as the sensor can
-	ov->minwidth = 160;
-	ov->minheight = 120;
-
-	return 0;
-
-error:
-	err("OV518 Config failed");
-
-	return -EBUSY;
-}
-
-
-/****************************************************************************
- *
- *  USB routines
- *
- ***************************************************************************/
-
-static void *
-ov51x_probe(struct usb_device *dev, unsigned int ifnum,
-	    const struct usb_device_id *id)
-{
-	struct usb_interface_descriptor *interface;
-	struct usb_ov511 *ov;
-	int i;
-	int registered = 0;
-
-	PDEBUG(1, "probing for device...");
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
-
-	/* Checking vendor/product should be enough, but what the hell */
-	if (interface->bInterfaceClass != 0xFF)
-		return NULL;
-	if (interface->bInterfaceSubClass != 0x00)
-		return NULL;
-
-	if ((ov = kmalloc(sizeof(*ov), GFP_KERNEL)) == NULL) {
-		err("couldn't kmalloc ov struct");
-		goto error_out;
-	}
-
-	memset(ov, 0, sizeof(*ov));
-
-	ov->dev = dev;
-	ov->iface = interface->bInterfaceNumber;
-	ov->led_policy = led;
-	ov->compress = compress;
-	ov->lightfreq = lightfreq;
-	ov->num_inputs = 1;	   /* Video decoder init functs. change this */
-	ov->stop_during_set = !fastset;
-	ov->tuner_type = tuner;
-	ov->backlight = backlight;
-
-	ov->auto_brt = autobright;
-	ov->auto_gain = autogain;
-	ov->auto_exp = autoexp;
-
-	switch (dev->descriptor.idProduct) {
-	case PROD_OV511:
-		ov->bridge = BRG_OV511;
-		ov->bclass = BCL_OV511;
-		break;
-	case PROD_OV511PLUS:
-		ov->bridge = BRG_OV511PLUS;
-		ov->bclass = BCL_OV511;
-		break;
-	case PROD_OV518:
-		ov->bridge = BRG_OV518;
-		ov->bclass = BCL_OV518;
-		break;
-	case PROD_OV518PLUS:
-		ov->bridge = BRG_OV518PLUS;
-		ov->bclass = BCL_OV518;
-		break;
-	case PROD_ME2CAM:
-		if (dev->descriptor.idVendor != VEND_MATTEL)
-			goto error;
-		ov->bridge = BRG_OV511PLUS;
-		ov->bclass = BCL_OV511;
-		break;
-	default:
-		err("Unknown product ID 0x%x", dev->descriptor.idProduct);
-		goto error_dealloc;
-	}
-
-	info("USB %s video device found", symbolic(brglist, ov->bridge));
-
-	/* Workaround for some applications that want data in RGB
-	 * instead of BGR. */
-	if (force_rgb)
-		info("data format set to RGB");
-
-	init_waitqueue_head(&ov->wq);
-
-	init_MUTEX(&ov->lock);	/* to 1 == available */
-	init_MUTEX(&ov->buf_lock);
-	init_MUTEX(&ov->param_lock);
-	init_MUTEX(&ov->i2c_lock);
-	init_MUTEX(&ov->cbuf_lock);
-
-	ov->buf_state = BUF_NOT_ALLOCATED;
-
-	/* Must be kmalloc()'ed, for DMA accessibility */
-	ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL);
-	if (!ov->cbuf)
-		goto error;
-
-	if (ov->bclass == BCL_OV518) {
-		if (ov518_configure(ov) < 0)
-			goto error;
-	} else {
-		if (ov511_configure(ov) < 0)
-			goto error;
-	}
-
-	for (i = 0; i < OV511_NUMFRAMES; i++) {
-		ov->frame[i].framenum = i;
-		init_waitqueue_head(&ov->frame[i].wq);
-	}
-
-	for (i = 0; i < OV511_NUMSBUF; i++) {
-		ov->sbuf[i].ov = ov;
-		spin_lock_init(&ov->sbuf[i].lock);
-		ov->sbuf[i].n = i;
-	}
-
-	/* Unnecessary? (This is done on open(). Need to make sure variables
-	 * are properly initialized without this before removing it, though). */
-	if (ov51x_set_default_params(ov) < 0)
-		goto error;
-
-#ifdef OV511_DEBUG
-	if (dump_bridge)
-		ov511_dump_regs(ov);
-#endif
-
-	memcpy(&ov->vdev, &vdev_template, sizeof(vdev_template));
-	ov->vdev.priv = ov;
-
-	for (i = 0; i < OV511_MAX_UNIT_VIDEO; i++) {
-		/* Minor 0 cannot be specified; assume user wants autodetect */
-		if (unit_video[i] == 0)
-			break;
-
-		if (video_register_device(&ov->vdev, VFL_TYPE_GRABBER,
-			unit_video[i]) >= 0) {
-			registered = 1;
-			break;
-		}
-	}
-
-	/* Use the next available one */
-	if (!registered &&
-	    video_register_device(&ov->vdev, VFL_TYPE_GRABBER, -1) < 0) {
-		err("video_register_device failed");
-		goto error;
-	}
-
-	info("Device registered on minor %d", ov->vdev.minor);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	create_proc_ov511_cam(ov);
-#endif
-
-     	return ov;
-
-error:
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	/* Safe to call even if entry doesn't exist */
-	destroy_proc_ov511_cam(ov);
-#endif
-
-	if (ov->cbuf) {
-		down(&ov->cbuf_lock);
-		kfree(ov->cbuf);
-		ov->cbuf = NULL;
-		up(&ov->cbuf_lock);
-	}
-
-error_dealloc:
-	if (ov) {
-		kfree(ov);
-		ov = NULL;
-	}
-
-error_out:
-	err("Camera initialization failed");
-	return NULL;
-}
-
-
-static void
-ov51x_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_ov511 *ov = (struct usb_ov511 *) ptr;
-	int n;
-
-	PDEBUG(3, "");
-
-	/* We don't want people trying to open up the device */
-	video_unregister_device(&ov->vdev);
-	if (ov->user)
-		PDEBUG(3, "Device open...deferring video_unregister_device");
-
-	for (n = 0; n < OV511_NUMFRAMES; n++)
-		ov->frame[n].grabstate = FRAME_ERROR;
-
-	ov->curframe = -1;
-
-	/* This will cause the process to request another frame */
-	for (n = 0; n < OV511_NUMFRAMES; n++)
-		if (waitqueue_active(&ov->frame[n].wq))
-			wake_up_interruptible(&ov->frame[n].wq);
-	if (waitqueue_active(&ov->wq))
-		wake_up_interruptible(&ov->wq);
-
-	ov->streaming = 0;
-
-	ov51x_unlink_isoc(ov);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-        destroy_proc_ov511_cam(ov);
-#endif
-
-	ov->dev = NULL;
-
-	/* Free the memory */
-	if (ov && !ov->user) {
-		down(&ov->cbuf_lock);
-		kfree(ov->cbuf);
-		ov->cbuf = NULL;
-		up(&ov->cbuf_lock);
-
-		ov51x_dealloc(ov, 1);
-		kfree(ov);
-		ov = NULL;
-	}
-}
-
-static struct usb_driver ov511_driver = {
-	owner:		THIS_MODULE,
-	name:		"ov511",
-	id_table:       device_table,
-	probe:		ov51x_probe,
-	disconnect:	ov51x_disconnect
-};
-
-
-/****************************************************************************
- *
- *  Module routines
- *
- ***************************************************************************/
-
-/* Returns 0 for success */
-int 
-ov511_register_decomp_module(int ver, struct ov51x_decomp_ops *ops, int ov518,
-			     int mmx)
-{
-	if (ver != DECOMP_INTERFACE_VER) {
-		err("Decompression module has incompatible");
-		err("interface version %d", ver);
-		err("Interface version %d is required", DECOMP_INTERFACE_VER);
-		return -EINVAL;
-	}
-
-	if (!ops)
-		return -EFAULT;
-
-	if (mmx && !ov51x_mmx_available) {
-		err("MMX not available on this system or kernel");
-		return -EINVAL;
-	}
-
-	lock_kernel();
-
-	if (ov518) {
-		if (mmx) {
-			if (ov518_mmx_decomp_ops)
-				goto err_in_use;
-			else
-				ov518_mmx_decomp_ops = ops;
-		} else {
-			if (ov518_decomp_ops)
-				goto err_in_use;
-			else
-				ov518_decomp_ops = ops;
-		}
-	} else {
-		if (mmx) {
-			if (ov511_mmx_decomp_ops)
-				goto err_in_use;
-			else
-				ov511_mmx_decomp_ops = ops;
-		} else {
-			if (ov511_decomp_ops)
-				goto err_in_use;
-			else
-				ov511_decomp_ops = ops;
-		}
-	}
-
-	MOD_INC_USE_COUNT;
-
-	unlock_kernel();
-	return 0;
-
-err_in_use:
-	unlock_kernel();
-	return -EBUSY;
-}
-
-void 
-ov511_deregister_decomp_module(int ov518, int mmx)
-{
-	lock_kernel();
-
-	if (ov518) {
-		if (mmx)
-			ov518_mmx_decomp_ops = NULL;
-		else
-			ov518_decomp_ops = NULL;
-	} else {
-		if (mmx)
-			ov511_mmx_decomp_ops = NULL;
-		else
-			ov511_decomp_ops = NULL;
-	}
-	
-	MOD_DEC_USE_COUNT;
-
-	unlock_kernel();
-}
-
-static int __init 
-usb_ov511_init(void)
-{
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-        proc_ov511_create();
-#endif
-
-	if (usb_register(&ov511_driver) < 0)
-		return -1;
-
-	// FIXME: Don't know how to determine this yet
-	ov51x_mmx_available = 0;
-
-#if defined (__i386__)
-	if (test_bit(X86_FEATURE_MMX, &boot_cpu_data.x86_capability))
-		ov51x_mmx_available = 1;
-#endif
-
-	info(DRIVER_VERSION " : " DRIVER_DESC);
-
-	return 0;
-}
-
-static void __exit 
-usb_ov511_exit(void)
-{
-	usb_deregister(&ov511_driver);
-	info("driver deregistered");
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-        proc_ov511_destroy();
-#endif
-}
-
-module_init(usb_ov511_init);
-module_exit(usb_ov511_exit);
-
-/* No version, for compatibility with binary-only modules */
-EXPORT_SYMBOL_NOVERS(ov511_register_decomp_module);
-EXPORT_SYMBOL_NOVERS(ov511_deregister_decomp_module);
diff -Nru a/drivers/usb/ov511.h b/drivers/usb/ov511.h
--- a/drivers/usb/ov511.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,644 +0,0 @@
-#ifndef __LINUX_OV511_H
-#define __LINUX_OV511_H
-
-#include <asm/uaccess.h>
-#include <linux/videodev.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-
-#define OV511_DEBUG	/* Turn on debug messages */
-
-#ifdef OV511_DEBUG
-	#define PDEBUG(level, fmt, args...) \
-		if (debug >= (level)) info("[%s:%d] " fmt, \
-		__PRETTY_FUNCTION__, __LINE__ , ## args)
-#else
-	#define PDEBUG(level, fmt, args...) do {} while(0)
-#endif
-
-/* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v,mi,ma) { \
-	if ((v) < (mi)) (v) = (mi); \
-	else if ((v) > (ma)) (v) = (ma); \
-}
-
-/* --------------------------------- */
-/* DEFINES FOR OV511 AND OTHER CHIPS */
-/* --------------------------------- */
-
-/* USB IDs */
-#define VEND_OMNIVISION	0x05A9
-#define PROD_OV511	0x0511
-#define PROD_OV511PLUS	0xA511
-#define PROD_OV518	0x0518
-#define PROD_OV518PLUS	0xA518
-
-#define VEND_MATTEL	0x0813
-#define PROD_ME2CAM	0x0002
-
-/* --------------------------------- */
-/*     OV51x REGISTER MNEMONICS      */
-/* --------------------------------- */
-
-/* Camera interface register numbers */
-#define R511_CAM_DELAY		0x10
-#define R511_CAM_EDGE		0x11
-#define R511_CAM_PXCNT		0x12
-#define R511_CAM_LNCNT		0x13
-#define R511_CAM_PXDIV		0x14
-#define R511_CAM_LNDIV		0x15
-#define R511_CAM_UV_EN		0x16
-#define R511_CAM_LINE_MODE	0x17
-#define R511_CAM_OPTS		0x18
-
-/* Snapshot mode camera interface register numbers */
-#define R511_SNAP_FRAME		0x19
-#define R511_SNAP_PXCNT		0x1A
-#define R511_SNAP_LNCNT		0x1B
-#define R511_SNAP_PXDIV		0x1C
-#define R511_SNAP_LNDIV		0x1D
-#define R511_SNAP_UV_EN		0x1E
-#define R511_SNAP_OPTS		0x1F
-
-/* DRAM register numbers */
-#define R511_DRAM_FLOW_CTL	0x20
-#define R511_DRAM_ARCP		0x21
-#define R511_DRAM_MRC		0x22
-#define R511_DRAM_RFC		0x23
-
-/* ISO FIFO register numbers */
-#define R51x_FIFO_PSIZE		0x30	/* 2 bytes wide w/ OV518(+) */
-#define R511_FIFO_OPTS		0x31
-
-/* Parallel IO register numbers */
-#define R511_PIO_OPTS		0x38
-#define R511_PIO_DATA		0x39
-#define R511_PIO_BIST		0x3E
-#define R518_GPIO_IN		0x55	/* OV518(+) only */
-#define R518_GPIO_OUT		0x56	/* OV518(+) only */
-#define R518_GPIO_CTL		0x57	/* OV518(+) only */
-#define R518_GPIO_PULSE_IN	0x58	/* OV518(+) only */
-#define R518_GPIO_PULSE_CLEAR	0x59	/* OV518(+) only */
-#define R518_GPIO_PULSE_POL	0x5a	/* OV518(+) only */
-#define R518_GPIO_PULSE_EN	0x5b	/* OV518(+) only */
-#define R518_GPIO_RESET		0x5c	/* OV518(+) only */
-
-/* I2C registers */
-#define R511_I2C_CTL		0x40
-#define R518_I2C_CTL		0x47	/* OV518(+) only */
-#define R51x_I2C_W_SID		0x41
-#define R51x_I2C_SADDR_3	0x42
-#define R51x_I2C_SADDR_2	0x43
-#define R51x_I2C_R_SID		0x44
-#define R51x_I2C_DATA		0x45
-#define R51x_I2C_CLOCK		0x46
-#define R51x_I2C_TIMEOUT	0x47
-
-/* I2C snapshot registers */
-#define R511_SI2C_SADDR_3	0x48
-#define R511_SI2C_DATA		0x49
-
-/* System control registers */
-#define R51x_SYS_RESET		0x50
-		/* Reset type definitions */
-#define 	OV511_RESET_UDC		0x01
-#define 	OV511_RESET_I2C		0x02
-#define 	OV511_RESET_FIFO	0x04
-#define 	OV511_RESET_OMNICE	0x08
-#define 	OV511_RESET_DRAM	0x10
-#define 	OV511_RESET_CAM_INT	0x20
-#define 	OV511_RESET_OV511	0x40
-#define 	OV511_RESET_NOREGS	0x3F /* All but OV511 & regs */
-#define 	OV511_RESET_ALL		0x7F
-
-#define R511_SYS_CLOCK_DIV	0x51
-#define R51x_SYS_SNAP		0x52
-#define R51x_SYS_INIT         	0x53
-#define R511_SYS_PWR_CLK	0x54 /* OV511+/OV518(+) only */
-#define R511_SYS_LED_CTL	0x55 /* OV511+ only */
-#define R511_SYS_USER		0x5E
-#define R511_SYS_CUST_ID	0x5F
-
-/* OmniCE (compression) registers */
-#define R511_COMP_PHY		0x70
-#define R511_COMP_PHUV		0x71
-#define R511_COMP_PVY		0x72
-#define R511_COMP_PVUV		0x73
-#define R511_COMP_QHY		0x74
-#define R511_COMP_QHUV		0x75
-#define R511_COMP_QVY		0x76
-#define R511_COMP_QVUV		0x77
-#define R511_COMP_EN		0x78
-#define R511_COMP_LUT_EN	0x79		
-#define R511_COMP_LUT_BEGIN	0x80
-
-/* --------------------------------- */
-/*         ALTERNATE NUMBERS         */
-/* --------------------------------- */
-
-/* Alternate numbers for various max packet sizes (OV511 only) */
-#define OV511_ALT_SIZE_992	0
-#define OV511_ALT_SIZE_993	1
-#define OV511_ALT_SIZE_768	2
-#define OV511_ALT_SIZE_769	3
-#define OV511_ALT_SIZE_512	4
-#define OV511_ALT_SIZE_513	5
-#define OV511_ALT_SIZE_257	6
-#define OV511_ALT_SIZE_0	7
-
-/* Alternate numbers for various max packet sizes (OV511+ only) */
-#define OV511PLUS_ALT_SIZE_0	0
-#define OV511PLUS_ALT_SIZE_33	1
-#define OV511PLUS_ALT_SIZE_129	2
-#define OV511PLUS_ALT_SIZE_257	3
-#define OV511PLUS_ALT_SIZE_385	4
-#define OV511PLUS_ALT_SIZE_513	5
-#define OV511PLUS_ALT_SIZE_769	6
-#define OV511PLUS_ALT_SIZE_961	7
-
-/* Alternate numbers for various max packet sizes (OV518(+) only) */
-#define OV518_ALT_SIZE_0	0
-#define OV518_ALT_SIZE_128	1
-#define OV518_ALT_SIZE_256	2
-#define OV518_ALT_SIZE_384	3
-#define OV518_ALT_SIZE_512	4
-#define OV518_ALT_SIZE_640	5
-#define OV518_ALT_SIZE_768	6
-#define OV518_ALT_SIZE_896	7
-
-/* --------------------------------- */
-/*     OV7610 REGISTER MNEMONICS     */
-/* --------------------------------- */
-
-/* OV7610 registers */
-#define OV7610_REG_GAIN          0x00	/* gain setting (5:0) */
-#define OV7610_REG_BLUE          0x01	/* blue channel balance */
-#define OV7610_REG_RED           0x02	/* red channel balance */
-#define OV7610_REG_SAT           0x03	/* saturation */
-					/* 04 reserved */
-#define OV7610_REG_CNT           0x05	/* Y contrast */
-#define OV7610_REG_BRT           0x06	/* Y brightness */
-					/* 08-0b reserved */
-#define OV7610_REG_BLUE_BIAS     0x0C	/* blue channel bias (5:0) */
-#define OV7610_REG_RED_BIAS      0x0D	/* read channel bias (5:0) */
-#define OV7610_REG_GAMMA_COEFF   0x0E	/* gamma settings */
-#define OV7610_REG_WB_RANGE      0x0F	/* AEC/ALC/S-AWB settings */
-#define OV7610_REG_EXP           0x10	/* manual exposure setting */
-#define OV7610_REG_CLOCK         0x11	/* polarity/clock prescaler */
-#define OV7610_REG_COM_A         0x12	/* misc common regs */
-#define OV7610_REG_COM_B         0x13	/* misc common regs */
-#define OV7610_REG_COM_C         0x14	/* misc common regs */
-#define OV7610_REG_COM_D         0x15	/* misc common regs */
-#define OV7610_REG_FIELD_DIVIDE  0x16	/* field interval/mode settings */
-#define OV7610_REG_HWIN_START    0x17	/* horizontal window start */
-#define OV7610_REG_HWIN_END      0x18	/* horizontal window end */
-#define OV7610_REG_VWIN_START    0x19	/* vertical window start */
-#define OV7610_REG_VWIN_END      0x1A	/* vertical window end */
-#define OV7610_REG_PIXEL_SHIFT   0x1B	/* pixel shift */
-#define OV7610_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
-#define OV7610_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
-					/* 0e-0f reserved */
-#define OV7610_REG_COM_E         0x20	/* misc common regs */
-#define OV7610_REG_YOFFSET       0x21	/* Y channel offset */
-#define OV7610_REG_UOFFSET       0x22	/* U channel offset */
-					/* 23 reserved */
-#define OV7610_REG_ECW           0x24	/* Exposure white level for AEC */
-#define OV7610_REG_ECB           0x25	/* Exposure black level for AEC */
-#define OV7610_REG_COM_F         0x26	/* misc settings */
-#define OV7610_REG_COM_G         0x27	/* misc settings */
-#define OV7610_REG_COM_H         0x28	/* misc settings */
-#define OV7610_REG_COM_I         0x29	/* misc settings */
-#define OV7610_REG_FRAMERATE_H   0x2A	/* frame rate MSB + misc */
-#define OV7610_REG_FRAMERATE_L   0x2B	/* frame rate LSB */
-#define OV7610_REG_ALC           0x2C	/* Auto Level Control settings */
-#define OV7610_REG_COM_J         0x2D	/* misc settings */
-#define OV7610_REG_VOFFSET       0x2E	/* V channel offset adjustment */
-#define OV7610_REG_ARRAY_BIAS	 0x2F	/* Array bias -- don't change */
-					/* 30-32 reserved */
-#define OV7610_REG_YGAMMA        0x33	/* misc gamma settings (7:6) */
-#define OV7610_REG_BIAS_ADJUST   0x34	/* misc bias settings */
-#define OV7610_REG_COM_L         0x35	/* misc settings */
-					/* 36-37 reserved */
-#define OV7610_REG_COM_K         0x38	/* misc registers */
-
-/* --------------------------------- */
-/*           I2C ADDRESSES           */
-/* --------------------------------- */
-
-#define OV7xx0_SID   0x42
-#define OV6xx0_SID   0xC0
-#define OV8xx0_SID   0xA0
-#define KS0127_SID   0xD8
-#define SAA7111A_SID 0x48
-
-/* --------------------------------- */
-/*       MISCELLANEOUS DEFINES       */
-/* --------------------------------- */
-
-#define I2C_CLOCK_PRESCALER 	0x03
-
-#define FRAMES_PER_DESC		10	/* FIXME - What should this be? */
-#define MAX_FRAME_SIZE_PER_DESC	993	/* For statically allocated stuff */
-#define PIXELS_PER_SEG		256	/* Pixels per segment */
-
-#define OV511_ENDPOINT_ADDRESS	1	/* Isoc endpoint number */
-
-#define OV511_NUMFRAMES	2
-#if OV511_NUMFRAMES > VIDEO_MAX_FRAME
-	#error "OV511_NUMFRAMES is too high"
-#endif
-
-#define OV511_NUMSBUF		2
-
-/* Control transfers use up to 4 bytes */
-#define OV511_CBUF_SIZE		4
-
-/* Bridge types */
-enum {
-	BRG_UNKNOWN,
-	BRG_OV511,
-	BRG_OV511PLUS,
-	BRG_OV518,
-	BRG_OV518PLUS,
-};
-
-/* Bridge classes */
-enum {
-	BCL_UNKNOWN,
-	BCL_OV511,
-	BCL_OV518,
-};
-
-/* Sensor types */
-enum {
-	SEN_UNKNOWN,
-	SEN_OV76BE,
-	SEN_OV7610,
-	SEN_OV7620,
-	SEN_OV7620AE,
-	SEN_OV6620,
-	SEN_OV6630,
-	SEN_OV6630AE,
-	SEN_OV6630AF,
-	SEN_OV8600,
-	SEN_KS0127,
-	SEN_KS0127B,
-	SEN_SAA7111A,
-};
-
-// Not implemented yet
-#if 0
-/* Sensor classes */
-enum {
-	SCL_UNKNOWN,
-	SCL_OV7610,	/* 7610, 76BE, 7620AE (for now) */
-	SCL_OV7620,
-	SCL_OV6620,	
-	SCL_OV6630,	/* 6630, 6630AE, 6630AF */
-	SCL_OV8600,
-	SCL_KS0127,	/* SEN_KS0127, SEN_KS0127B */
-	SCL_SAA7111A,
-};
-#endif
-
-enum {
-	STATE_SCANNING,		/* Scanning for start */
-	STATE_HEADER,		/* Parsing header */
-	STATE_LINES,		/* Parsing lines */
-};
-
-/* Buffer states */
-enum {
-	BUF_NOT_ALLOCATED,
-	BUF_ALLOCATED,
-	BUF_PEND_DEALLOC,	/* ov511->buf_timer is set */
-};
-
-/* --------- Definition of ioctl interface --------- */
-
-#define OV511_INTERFACE_VER 101
-
-/* LED options */
-enum {
-	LED_OFF,
-	LED_ON,
-	LED_AUTO,
-};
-
-/* Raw frame formats */
-enum {
-	RAWFMT_INVALID,
-	RAWFMT_YUV400,
-	RAWFMT_YUV420,
-	RAWFMT_YUV422,
-	RAWFMT_GBR422,
-};
-
-/* Unsigned short option numbers */
-enum {
-	OV511_USOPT_INVALID,
-	OV511_USOPT_BRIGHT,
-	OV511_USOPT_SAT,
-	OV511_USOPT_HUE,
-	OV511_USOPT_CONTRAST,
-};
-
-/* Unsigned int option numbers */
-enum {
-	OV511_UIOPT_INVALID,
-	OV511_UIOPT_POWER_FREQ,
-	OV511_UIOPT_BFILTER,
-	OV511_UIOPT_LED,
-	OV511_UIOPT_DEBUG,
-	OV511_UIOPT_COMPRESS,
-};
-
-struct ov511_ushort_opt {
-	int optnum;		/* Specific option number */
-	unsigned short val;
-};
-
-struct ov511_uint_opt {
-	int optnum;		/* Specific option number */
-	unsigned int val;
-};
-
-struct ov511_i2c_struct {
-	unsigned char slave; /* Write slave ID (read ID - 1) */
-	unsigned char reg;   /* Index of register */
-	unsigned char value; /* User sets this w/ write, driver does w/ read */
-	unsigned char mask;  /* Bits to be changed. Not used with read ops */
-};
-
-/* ioctls */
-#define OV511IOC_GINTVER  _IOR('v', BASE_VIDIOCPRIVATE + 0, int)
-#define OV511IOC_GUSHORT _IOWR('v', BASE_VIDIOCPRIVATE + 1, \
-			       struct ov511_ushort_opt)
-#define OV511IOC_SUSHORT  _IOW('v', BASE_VIDIOCPRIVATE + 2, \
-			       struct ov511_ushort_opt)
-#define OV511IOC_GUINT   _IOWR('v', BASE_VIDIOCPRIVATE + 3, \
-			       struct ov511_uint_opt)
-#define OV511IOC_SUINT    _IOW('v', BASE_VIDIOCPRIVATE + 4, \
-			       struct ov511_uint_opt)
-#define OV511IOC_WI2C     _IOW('v', BASE_VIDIOCPRIVATE + 5, \
-			       struct ov511_i2c_struct)
-#define OV511IOC_RI2C    _IOWR('v', BASE_VIDIOCPRIVATE + 6, \
-			       struct ov511_i2c_struct)
-/* ------------- End IOCTL interface -------------- */
-
-struct usb_ov511;		/* Forward declaration */
-
-struct ov511_sbuf {
-	struct usb_ov511 *ov;
-	unsigned char *data;
-	struct urb *urb;
-	spinlock_t lock;
-	int n;
-};
-
-enum {
-	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
-	FRAME_READY,		/* Ready to start grabbing */
-	FRAME_GRABBING,		/* In the process of being grabbed into */
-	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
-	FRAME_ERROR,		/* Something bad happened while processing */
-};
-
-struct ov511_regvals {
-	enum {
-		OV511_DONE_BUS,
-		OV511_REG_BUS,
-		OV511_I2C_BUS,
-	} bus;
-	unsigned char reg;
-	unsigned char val;
-};
-
-struct ov511_frame {
-	int framenum;		/* Index of this frame */
-	unsigned char *data;	/* Frame buffer */
-	unsigned char *tempdata; /* Temp buffer for multi-stage conversions */
-	unsigned char *rawdata;	/* Raw camera data buffer */
-	unsigned char *compbuf;	/* Temp buffer for decompressor */
-
-	int depth;		/* Bytes per pixel */
-	int width;		/* Width application is expecting */
-	int height;		/* Height application is expecting */
-
-	int rawwidth;		/* Actual width of frame sent from camera */
-	int rawheight;		/* Actual height of frame sent from camera */
-
-	int sub_flag;		/* Sub-capture mode for this frame? */
-	unsigned int format;	/* Format for this frame */
-	int compressed;		/* Is frame compressed? */
-
-	volatile int grabstate;	/* State of grabbing */
-	int scanstate;		/* State of scanning */
-
-	int bytes_recvd;	/* Number of image bytes received from camera */
-
-	long bytes_read;	/* Amount that has been read() */
-
-	wait_queue_head_t wq;	/* Processes waiting */
-
-	int snapshot;		/* True if frame was a snapshot */
-};
-
-#define DECOMP_INTERFACE_VER 3
-
-/* Compression module operations */
-struct ov51x_decomp_ops {
-	int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *,
-			  int, int, int);
-	int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *,
-			  int, int, int);
-	int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *,
-			  int, int, int);
-	void (*decomp_lock)(void);
-	void (*decomp_unlock)(void);
-};
-
-struct usb_ov511 {
-	struct video_device vdev;
-
-	/* Device structure */
-	struct usb_device *dev;
-
-	int customid;
-	char *desc;
-	unsigned char iface;
-
-	/* Determined by sensor type */
-	int maxwidth;
-	int maxheight;
-	int minwidth;
-	int minheight;
-
-	int brightness;
-	int colour;
-	int contrast;
-	int hue;
-	int whiteness;
-	int exposure;
-	int auto_brt;		/* Auto brightness enabled flag */
-	int auto_gain;		/* Auto gain control enabled flag */
-	int auto_exp;		/* Auto exposure enabled flag */
-	int backlight;		/* Backlight exposure algorithm flag */
-
-	int led_policy;		/* LED: off|on|auto; OV511+ only */
-
-	struct semaphore lock;	/* Serializes user-accessible operations */
-	int user;		/* user count for exclusive use */
-
-	int streaming;		/* Are we streaming Isochronous? */
-	int grabbing;		/* Are we grabbing? */
-
-	int compress;		/* Should the next frame be compressed? */
-	int compress_inited;	/* Are compression params uploaded? */
-
-	int lightfreq;		/* Power (lighting) frequency */
-	int bandfilt;		/* Banding filter enabled flag */
-
-	unsigned char *fbuf;	/* Videodev buffer area */
-	unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */
-	unsigned char *rawfbuf;	/* Raw camera data buffer area */
-
-	int sub_flag;		/* Pix Array subcapture on flag */
-	int subx;		/* Pix Array subcapture x offset */
-	int suby;		/* Pix Array subcapture y offset */
-	int subw;		/* Pix Array subcapture width */
-	int subh;		/* Pix Array subcapture height */
-
-	int curframe;		/* Current receiving sbuf */
-	struct ov511_frame frame[OV511_NUMFRAMES];	
-
-	struct ov511_sbuf sbuf[OV511_NUMSBUF];
-
-	wait_queue_head_t wq;	/* Processes waiting */
-
-	int snap_enabled;	/* Snapshot mode enabled */
-	
-	int bridge;		/* Type of bridge (BRG_*) */
-	int bclass;		/* Class of bridge (BCL_*) */
-	int sensor;		/* Type of image sensor chip (SEN_*) */
-	int sclass;		/* Type of image sensor chip (SCL_*) */
-	int tuner;		/* Type of TV tuner */
-
-	int packet_size;	/* Frame size per isoc desc */
-
-	struct semaphore param_lock;	/* params lock for this camera */
-
-	/* /proc entries, relative to /proc/video/ov511/ */
-	struct proc_dir_entry *proc_devdir;   /* Per-device proc directory */
-	struct proc_dir_entry *proc_info;     /* <minor#>/info entry */
-	struct proc_dir_entry *proc_button;   /* <minor#>/button entry */
-	struct proc_dir_entry *proc_control;  /* <minor#>/control entry */
-
-	/* Framebuffer/sbuf management */
-	int buf_state;
-	struct semaphore buf_lock;
-	struct timer_list buf_timer;
-
-	struct ov51x_decomp_ops *decomp_ops;
-
-	/* Stop streaming while changing picture settings */
-	int stop_during_set;
-
-	int stopped;		/* Streaming is temporarily paused */
-
-	/* Video decoder stuff */
-	int input;		/* Composite, S-VIDEO, etc... */
-	int num_inputs;		/* Number of inputs */
-	int norm; 		/* NTSC / PAL / SECAM */
-	int has_decoder;	/* Device has a video decoder */
-	int has_tuner;		/* Device has a TV tuner */
-	int has_audio_proc;	/* Device has an audio processor */
-	int freq;		/* Current tuner frequency */
-	int tuner_type;		/* Specific tuner model */
-
-	/* I2C interface to kernel */
-	struct semaphore i2c_lock;	  /* Protect I2C controller regs */
-	unsigned char primary_i2c_slave;  /* I2C write id of sensor */
-
-	/* Control transaction stuff */
-	unsigned char *cbuf;		/* Buffer for payload */
-	struct semaphore cbuf_lock;
-};
-
-/* Used to represent a list of values and their respective symbolic names */
-struct symbolic_list {
-	int num;
-	char *name;
-};
-
-#define NOT_DEFINED_STR "Unknown"
-
-/* Returns the name of the matching element in the symbolic_list array. The
- * end of the list must be marked with an element that has a NULL name.
- */
-static inline char * 
-symbolic(struct symbolic_list list[], int num)
-{
-	int i;
-
-	for (i = 0; list[i].name != NULL; i++)
-			if (list[i].num == num)
-				return (list[i].name);
-
-	return (NOT_DEFINED_STR);
-}
-
-struct mode_list_518 {
-	int width;
-	int height;
-	u8 reg28;
-	u8 reg29;
-	u8 reg2a;
-	u8 reg2c;
-	u8 reg2e;
-	u8 reg24;
-	u8 reg25;
-};
-
-/* Compression stuff */
-
-#define OV511_QUANTABLESIZE	64
-#define OV518_QUANTABLESIZE	32
-
-#define OV511_YQUANTABLE { \
-	0, 1, 1, 2, 2, 3, 3, 4, \
-	1, 1, 1, 2, 2, 3, 4, 4, \
-	1, 1, 2, 2, 3, 4, 4, 4, \
-	2, 2, 2, 3, 4, 4, 4, 4, \
-	2, 2, 3, 4, 4, 5, 5, 5, \
-	3, 3, 4, 4, 5, 5, 5, 5, \
-	3, 4, 4, 4, 5, 5, 5, 5, \
-	4, 4, 4, 4, 5, 5, 5, 5  \
-}
-
-#define OV511_UVQUANTABLE { \
-	0, 2, 2, 3, 4, 4, 4, 4, \
-	2, 2, 2, 4, 4, 4, 4, 4, \
-	2, 2, 3, 4, 4, 4, 4, 4, \
-	3, 4, 4, 4, 4, 4, 4, 4, \
-	4, 4, 4, 4, 4, 4, 4, 4, \
-	4, 4, 4, 4, 4, 4, 4, 4, \
-	4, 4, 4, 4, 4, 4, 4, 4, \
-	4, 4, 4, 4, 4, 4, 4, 4  \
-}
-
-#define OV518_YQUANTABLE { \
-	5, 4, 5, 6, 6, 7, 7, 7, \
-	5, 5, 5, 5, 6, 7, 7, 7, \
-	6, 6, 6, 6, 7, 7, 7, 8, \
-	7, 7, 6, 7, 7, 7, 8, 8  \
-}
-
-#define OV518_UVQUANTABLE { \
-	6, 6, 6, 7, 7, 7, 7, 7, \
-	6, 6, 6, 7, 7, 7, 7, 7, \
-	6, 6, 6, 7, 7, 7, 7, 8, \
-	7, 7, 7, 7, 7, 7, 8, 8  \
-}
-
-#endif
diff -Nru a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c
--- a/drivers/usb/pegasus.c	Sun Apr 14 12:17:00 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1097 +0,0 @@
-/*
-**	Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
-**
-**	Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
-**	
-**
-**	ChangeLog:
-**		....	Most of the time spend reading sources & docs.
-**		v0.2.x	First official release for the Linux kernel.
-**		v0.3.0	Beutified and structured, some bugs fixed.
-**		v0.3.x	URBifying bulk requests and bugfixing. First relatively
-**			stable release. Still can touch device's registers only
-**			from top-halves.
-**		v0.4.0	Control messages remained unurbified are now URBs.
-**			Now we can touch the HW at any time.
-**		v0.4.9	Control urbs again use process context to wait. Argh...
-**			Some long standing bugs (enable_net_traffic) fixed.
-**			Also nasty trick about resubmiting control urb from
-**			interrupt context used. Please let me know how it
-**			behaves. Pegasus II support added since this version.
-**			TODO: suppressing HCD warnings spewage on disconnect.
-**		v0.4.13	Ethernet address is now set at probe(), not at open()
-**			time as this seems to break dhcpd. 
-**		v0.5.0	branch to 2.5.x kernels
-**		v0.5.1	ethtool support added
-*/
-
-/*
- * This program is free software; you can redistribute it and/or 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/sched.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include "pegasus.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.5.1 (2002/03/06)"
-#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
-#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
-
-#define	PEGASUS_USE_INTR
-#define	PEGASUS_WRITE_EEPROM
-#define	BMSR_MEDIA	(BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
-			BMSR_100FULL | BMSR_ANEGCAPABLE)
-
-static int loopback = 0;
-static int mii_mode = 0;
-static int multicast_filter_limit = 32;
-
-static struct usb_eth_dev usb_dev_id[] = {
-#define	PEGASUS_DEV(pn, vid, pid, flags)	\
-	{name:pn, vendor:vid, device:pid, private:flags},
-#include "pegasus.h"
-#undef	PEGASUS_DEV
-	{NULL, 0, 0, 0}
-};
-
-static struct usb_device_id pegasus_ids[] = {
-#define	PEGASUS_DEV(pn, vid, pid, flags) \
-	{match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor:vid, idProduct:pid},
-#include "pegasus.h"
-#undef	PEGASUS_DEV
-	{ }
-};
-
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-MODULE_PARM(loopback, "i");
-MODULE_PARM(mii_mode, "i");
-MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
-MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
-
-MODULE_DEVICE_TABLE (usb, pegasus_ids);
-
-
-static int update_eth_regs_async( pegasus_t * );
-/* Aargh!!! I _really_ hate such tweaks */
-static void ctrl_callback( struct urb *urb )
-{
-	pegasus_t	*pegasus = urb->context;
-
-	if ( !pegasus )
-		return;
-
-	switch ( urb->status ) {
-		case 0:
-			if ( pegasus->flags & ETH_REGS_CHANGE ) {
-				pegasus->flags &= ~ETH_REGS_CHANGE;
-				pegasus->flags |= ETH_REGS_CHANGED;
-				update_eth_regs_async( pegasus );
-				return;
-			}
-			break;
-		case -EINPROGRESS:
-			return;
-		case -ENOENT:
-			break;
-		default:
-			warn("%s: status %d", __FUNCTION__, urb->status);
-	}
-	pegasus->flags &= ~ETH_REGS_CHANGED;
-	wake_up(&pegasus->ctrl_wait );
-}
-
-
-static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
-{
-	int	ret;
-	unsigned char *buffer;
-	DECLARE_WAITQUEUE(wait, current);
-
-	buffer = kmalloc(size,GFP_KERNEL);
-	if (!buffer) {
-		err("unable to allocate memory for configuration descriptors");
-		return 0;
-	}
-	memcpy(buffer,data,size);
-
-	add_wait_queue(&pegasus->ctrl_wait, &wait);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	while ( pegasus->flags & ETH_REGS_CHANGED )
-		schedule();
-	remove_wait_queue(&pegasus->ctrl_wait, &wait);
-	set_current_state(TASK_RUNNING);
-
-	pegasus->dr.bRequestType = PEGASUS_REQT_READ;
-	pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS;
-	pegasus->dr.wValue = cpu_to_le16 (0);
-	pegasus->dr.wIndex = cpu_to_le16p(&indx);
-	pegasus->dr.wLength = cpu_to_le16p(&size);
-	pegasus->ctrl_urb->transfer_buffer_length = size;
-
-	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
-			  usb_rcvctrlpipe(pegasus->usb,0),
-			  (char *)&pegasus->dr,
-			  buffer, size, ctrl_callback, pegasus );
-
-	add_wait_queue( &pegasus->ctrl_wait, &wait );
-	set_current_state( TASK_UNINTERRUPTIBLE );
-
-	/* using ATOMIC, we'd never wake up if we slept */
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
-		err("%s: BAD CTRLs %d", __FUNCTION__, ret);
-		goto out;
-	}
-
-	schedule();
-out:
-	remove_wait_queue( &pegasus->ctrl_wait, &wait );
-	memcpy(data,buffer,size);
-	kfree(buffer);
-
-	return ret;
-}
-
-
-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
-{
-	int	ret;
-	unsigned char *buffer;
-	DECLARE_WAITQUEUE(wait, current);
-
-	buffer = kmalloc(size, GFP_KERNEL);
-	if (!buffer) {
-		err("unable to allocate memory for configuration descriptors");
-		return 0;
-	}
-	memcpy(buffer, data, size);
-
-	add_wait_queue(&pegasus->ctrl_wait, &wait);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	while ( pegasus->flags & ETH_REGS_CHANGED )
-		schedule();
-	remove_wait_queue(&pegasus->ctrl_wait, &wait);
-	set_current_state(TASK_RUNNING);
-
-	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
-	pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
-	pegasus->dr.wValue = cpu_to_le16 (0);
-	pegasus->dr.wIndex = cpu_to_le16p( &indx );
-	pegasus->dr.wLength = cpu_to_le16p( &size );
-	pegasus->ctrl_urb->transfer_buffer_length = size;
-
-	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
-			  usb_sndctrlpipe(pegasus->usb,0),
-			  (char *)&pegasus->dr,
-			  buffer, size, ctrl_callback, pegasus );
-			  
-	add_wait_queue( &pegasus->ctrl_wait, &wait );
-	set_current_state( TASK_UNINTERRUPTIBLE );
-
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
-		err("%s: BAD CTRL %d", __FUNCTION__, ret);
-		goto out;
-	}
-	
-	schedule();
-out:
-	remove_wait_queue( &pegasus->ctrl_wait, &wait );
-	kfree(buffer);
-	
-	return ret;
-}
-
-
-static int set_register( pegasus_t *pegasus, __u16 indx, __u8 data )
-{
-	int	ret;
-	unsigned char *buffer;
-	__u16 dat = data;
-	DECLARE_WAITQUEUE(wait, current);
-	
-	buffer = kmalloc(1, GFP_KERNEL);
-	if (!buffer) {
-		err("unable to allocate memory for configuration descriptors");
-		return 0;
-	}
-	memcpy(buffer, &data, 1);
-
-	add_wait_queue(&pegasus->ctrl_wait, &wait);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	while ( pegasus->flags & ETH_REGS_CHANGED )
-		schedule();
-	remove_wait_queue(&pegasus->ctrl_wait, &wait);
-	set_current_state(TASK_RUNNING);
-
-	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
-	pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
-	pegasus->dr.wValue = cpu_to_le16p( &dat);
-	pegasus->dr.wIndex = cpu_to_le16p( &indx );
-	pegasus->dr.wLength = cpu_to_le16( 1 );
-	pegasus->ctrl_urb->transfer_buffer_length = 1;
-
-	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
-			  usb_sndctrlpipe(pegasus->usb,0),
-			  (char *)&pegasus->dr,
-			  buffer, 1, ctrl_callback, pegasus );
-
-	add_wait_queue( &pegasus->ctrl_wait, &wait );
-	set_current_state( TASK_UNINTERRUPTIBLE );
-
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) ) {
-		err("%s: BAD CTRL %d", __FUNCTION__, ret);
-		goto out;
-	}
-
-	schedule();
-out:
-	remove_wait_queue( &pegasus->ctrl_wait, &wait );
-	kfree(buffer);
-
-	return ret;
-}
-
-
-static int update_eth_regs_async( pegasus_t *pegasus )
-{
-	int	ret;
-
-	pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
-	pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
-	pegasus->dr.wValue = 0;
-	pegasus->dr.wIndex =  cpu_to_le16(EthCtrl0);
-	pegasus->dr.wLength = cpu_to_le16(3);
-	pegasus->ctrl_urb->transfer_buffer_length = 3;
-
-	FILL_CONTROL_URB( pegasus->ctrl_urb, pegasus->usb,
-			  usb_sndctrlpipe(pegasus->usb,0),
-			  (char *)&pegasus->dr,
-			  pegasus->eth_regs, 3, ctrl_callback, pegasus );
-
-	if ( (ret = usb_submit_urb( pegasus->ctrl_urb, GFP_ATOMIC )) )
-		err("%s: BAD CTRL %d, flgs %x",__FUNCTION__,ret,pegasus->flags);
-
-	return	ret;
-}
-
-
-static int read_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd )
-{
-	int	i;
-	__u8	data[4] = { phy, 0, 0, indx };
-	__u16  regdi;
-	
-	set_register( pegasus, PhyCtrl, 0 );
-	set_registers( pegasus, PhyAddr, sizeof(data), data );
-	set_register( pegasus, PhyCtrl, (indx | PHY_READ) );
-	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, PhyCtrl, 1, data);
-		if ( data[0] & PHY_DONE ) 
-			break;
-	}
-	if ( i < REG_TIMEOUT ) {
-		get_registers( pegasus, PhyData, 2, &regdi );
-		*regd = le16_to_cpu(regdi);
-		return	0;
-	}
-	warn("%s: failed", __FUNCTION__);
-	
-	return 1;
-}
-
-
-static int write_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd )
-{
-	int	i;
-	__u8	data[4] = { phy, 0, 0, indx };
-	
-	*(data + 1) = cpu_to_le16p( &regd );
-	set_register( pegasus, PhyCtrl, 0 );
-	set_registers( pegasus, PhyAddr, 4, data );
-	set_register( pegasus, PhyCtrl, (indx | PHY_WRITE) );
-	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, PhyCtrl, 1, data);
-		if ( data[0] & PHY_DONE ) 
-			break;
-	}
-	if ( i < REG_TIMEOUT )
-		return	0;
-	warn("%s: failed", __FUNCTION__);
-
-	return 1;
-}
-
-
-static int read_eprom_word( pegasus_t *pegasus, __u8 index, __u16 *retdata )
-{
-	int	i;
-	__u8 tmp;
-	__u16 retdatai;
-	
-	set_register( pegasus, EpromCtrl, 0 );
-	set_register( pegasus, EpromOffset, index );
-	set_register( pegasus, EpromCtrl, EPROM_READ); 
-
-	for ( i=0; i < REG_TIMEOUT; i++ ) {
-		get_registers( pegasus, EpromCtrl, 1, &tmp );
-		if ( tmp & EPROM_DONE )
-			break;
-	}
-	if ( i < REG_TIMEOUT ) {
-		get_registers( pegasus, EpromData, 2, &retdatai );
-		*retdata = le16_to_cpu (retdatai);
-		return	0;
-	}
-	warn("%s: failed", __FUNCTION__);
-
-	return -1;
-}
-
-#ifdef	PEGASUS_WRITE_EEPROM
-static inline void enable_eprom_write( pegasus_t *pegasus )
-{
-	__u8	tmp;
-
-	get_registers( pegasus, EthCtrl2, 1, &tmp );
-	set_register( pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE );
-}
-
-
-static inline void disable_eprom_write( pegasus_t *pegasus )
-{
-	__u8 	tmp;
-
-	get_registers( pegasus, EthCtrl2, 1, &tmp );
-	set_register( pegasus, EpromCtrl, 0 );
-	set_register( pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE );
-}
-
-
-static int write_eprom_word( pegasus_t *pegasus, __u8 index, __u16 data )
-{
-	int	i, tmp;
-	__u8	d[4] = {0x3f, 0, 0, EPROM_WRITE};
-
-	set_registers( pegasus, EpromOffset, 4, d );
-	enable_eprom_write( pegasus );
-	set_register( pegasus, EpromOffset, index );
-	set_registers( pegasus, EpromData, 2, &data );
-	set_register( pegasus, EpromCtrl, EPROM_WRITE );
-
-	for ( i=0; i < REG_TIMEOUT; i++ ) {
-		get_registers( pegasus, EpromCtrl, 1, &tmp );
-		if ( tmp & EPROM_DONE )
-			break;
-	}
-	disable_eprom_write( pegasus );
-	if ( i < REG_TIMEOUT )
-		return	0;
-	warn("%s: failed", __FUNCTION__);
-	return	-1;
-}
-#endif	/* PEGASUS_WRITE_EEPROM */
-
-static inline void get_node_id( pegasus_t *pegasus, __u8 *id )
-{
-	int	i;
-	__u16 w16;
-	
-	for (i = 0; i < 3; i++) {
-		read_eprom_word( pegasus, i, &w16);
-		((__u16 *) id)[i] = cpu_to_le16p (&w16);
-	}
-}
-
-
-static void set_ethernet_addr( pegasus_t *pegasus )
-{
-	__u8	node_id[6];
-
-	get_node_id(pegasus, node_id);
-	set_registers( pegasus, EthID, sizeof(node_id), node_id );
-	memcpy( pegasus->net->dev_addr, node_id, sizeof(node_id) );
-}
-
-
-static inline int reset_mac( pegasus_t *pegasus )
-{
-	__u8	data = 0x8;
-	int	i;
-
-	set_register(pegasus, EthCtrl1, data);
-	for (i = 0; i < REG_TIMEOUT; i++) {
-		get_registers(pegasus, EthCtrl1, 1, &data);
-		if (~data & 0x08) {
-			if (loopback & 1) 
-				break;
-			if ( mii_mode && (pegasus->features & HAS_HOME_PNA) )
-				set_register( pegasus, Gpio1, 0x34 );
-			else
-				set_register( pegasus, Gpio1, 0x26 );
-			set_register( pegasus, Gpio0, pegasus->features );
-			set_register( pegasus, Gpio0, DEFAULT_GPIO_SET );
-			break;
-		}
-	}
-	if ( i == REG_TIMEOUT )
-		return 1;
-
-	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
-	    usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
-		__u16	auxmode;
-		read_mii_word(pegasus, 1, MII_TPISTATUS, &auxmode);
-		write_mii_word(pegasus, 1, MII_TPISTATUS, auxmode | 4);
-	}
-	if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
-		__u16   auxmode;
-		read_mii_word(pegasus, 3, 0x1b, &auxmode);
-		write_mii_word(pegasus, 3, 0x1b, auxmode | 4);
-	}
-
-	return	0;
-}
-
-
-static int enable_net_traffic( struct net_device *dev, struct usb_device *usb )
-{
-	__u16	linkpart, bmsr;
-	__u8	data[4];
-	pegasus_t *pegasus = dev->priv;
-
-
-	if ( read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr) ) 
-		return 1;
-	if ( !(bmsr & 0x20) && !loopback ) 
-		warn( "%s: link NOT established (0x%x) - check the cable.",
-			dev->name, bmsr );
-	if ( read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart) )
-		return 2;
-	if ( !(linkpart & 1) )
-		warn( "link partner stat %x", linkpart );
-
-	data[0] = 0xc9;
-	data[1] = 0;
-	if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL) )
-		data[1] |= 0x20; /* set full duplex */
-	if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_100HALF) )
-		data[1] |= 0x10; /* set 100 Mbps */
-	if ( mii_mode )
-		data[1] = 0;
-	data[2] = (loopback & 1) ? 0x09 : 0x01;
-
-	memcpy( pegasus->eth_regs, data, sizeof(data) );
-
-	set_registers( pegasus, EthCtrl0, 3, data );
-
-	return 0;
-}
-
-
-static void read_bulk_callback( struct urb *urb )
-{
-	pegasus_t *pegasus = urb->context;
-	struct net_device *net;
-	int count = urb->actual_length, res;
-	int rx_status;
-	struct sk_buff	*skb;
-	__u16 pkt_len;
-
-	if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
-		return;
-
-	net = pegasus->net;
-	if ( !netif_device_present(net) )
-		return;
-
-	if ( pegasus->flags & PEGASUS_RX_BUSY ) {
-		pegasus->stats.rx_errors++;
-		dbg("pegasus Rx busy");
-		return;
-	}
-	pegasus->flags |= PEGASUS_RX_BUSY;
-
-	switch ( urb->status ) {
-		case 0:
-			break;
-		case -ETIMEDOUT:
-			dbg( "reset MAC" );
-			pegasus->flags &= ~PEGASUS_RX_BUSY;
-			break;
-		default:
-			dbg( "%s: RX status %d", net->name, urb->status );
-			goto goon;
-	}
-
-	if ( !count )
-		goto goon;
-
-	rx_status = le32_to_cpu(*(int *)(pegasus->rx_buff + count - 4));
-	if ( rx_status & 0x000e0000 ) {
-		dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
-		pegasus->stats.rx_errors++;
-		if ( rx_status & 0x060000 )
-			pegasus->stats.rx_length_errors++;
-		if ( rx_status & 0x080000 )
-			pegasus->stats.rx_crc_errors++;
-		if ( rx_status & 0x100000 )
-			pegasus->stats.rx_frame_errors++;
-		goto goon;
-	}
-
-	pkt_len = (rx_status & 0xfff) - 8;
-
-	if ( !(skb = dev_alloc_skb(pkt_len+2)) )
-		goto goon;
-
-	skb->dev = net;
-	skb_reserve(skb, 2);
-	eth_copy_and_sum(skb, pegasus->rx_buff, pkt_len, 0);
-	skb_put(skb, pkt_len);
-
-	skb->protocol = eth_type_trans(skb, net);
-	netif_rx(skb);
-	pegasus->stats.rx_packets++;
-	pegasus->stats.rx_bytes += pkt_len;
-
-goon:
-	FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
-			usb_rcvbulkpipe(pegasus->usb, 1),
-			pegasus->rx_buff, PEGASUS_MAX_MTU, 
-			read_bulk_callback, pegasus );
-	if ( (res = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) )
-		warn("%s: failed submint rx_urb %d", __FUNCTION__, res);
-	pegasus->flags &= ~PEGASUS_RX_BUSY;
-}
-
-
-static void write_bulk_callback( struct urb *urb )
-{
-	pegasus_t *pegasus = urb->context;
-
-	if ( !pegasus || !(pegasus->flags & PEGASUS_RUNNING) )
-		return;
-
-	if ( !netif_device_present(pegasus->net) )
-		return;
-		
-	if ( urb->status )
-		info("%s: TX status %d", pegasus->net->name, urb->status);
-
-	pegasus->net->trans_start = jiffies;
-	netif_wake_queue( pegasus->net );
-}
-
-#ifdef	PEGASUS_USE_INTR
-static void intr_callback( struct urb *urb )
-{
-	pegasus_t *pegasus = urb->context;
-	struct net_device *net;
-	__u8	*d;
-
-	if ( !pegasus )
-		return;
-		
-	switch ( urb->status ) {
-		case 0:
-			break;
-		case -ENOENT:
-			return;
-		default:
-			info("intr status %d", urb->status);
-	}
-
-	d = urb->transfer_buffer;
-	net = pegasus->net;
-	if ( d[0] & 0xfc ) {
-		pegasus->stats.tx_errors++;
-		if ( d[0] & TX_UNDERRUN )
-			pegasus->stats.tx_fifo_errors++;
-		if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
-			pegasus->stats.tx_aborted_errors++;
-		if ( d[0] & LATE_COL )
-			pegasus->stats.tx_window_errors++;
-		if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
-			pegasus->stats.tx_carrier_errors++;
-	}
-}
-#endif
-
-static void pegasus_tx_timeout( struct net_device *net )
-{
-	pegasus_t *pegasus = net->priv;
-
-	if ( !pegasus )
-		return;
-		
-	warn("%s: Tx timed out.", net->name);
-	pegasus->tx_urb->transfer_flags |= USB_ASYNC_UNLINK;
-	usb_unlink_urb( pegasus->tx_urb );
-	pegasus->stats.tx_errors++;
-}
-
-
-static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net )
-{
-	pegasus_t	*pegasus = net->priv;
-	int 	count = ((skb->len+2) & 0x3f) ? skb->len+2 : skb->len+3;
-	int 	res;
-	__u16 l16 = skb->len;
-	
-	netif_stop_queue( net );
-		
-	((__u16 *)pegasus->tx_buff)[0] = cpu_to_le16( l16 );
-	memcpy(pegasus->tx_buff+2, skb->data, skb->len);
-	FILL_BULK_URB( pegasus->tx_urb, pegasus->usb,
-			usb_sndbulkpipe(pegasus->usb, 2),
-			pegasus->tx_buff, PEGASUS_MAX_MTU, 
-			write_bulk_callback, pegasus );
-	pegasus->tx_urb->transfer_buffer_length = count;
-	if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
-		warn("failed tx_urb %d", res);
-		pegasus->stats.tx_errors++;
-		netif_start_queue( net );
-	} else {
-		pegasus->stats.tx_packets++;
-		pegasus->stats.tx_bytes += skb->len;
-		net->trans_start = jiffies;
-	}
-
-	dev_kfree_skb(skb);
-
-	return 0;
-}
-
-
-static struct net_device_stats *pegasus_netdev_stats( struct net_device *dev )
-{
-	return &((pegasus_t *)dev->priv)->stats;
-}
-
-
-static inline void disable_net_traffic( pegasus_t *pegasus )
-{
-	int 	tmp=0;
-
-	set_registers( pegasus, EthCtrl0, 2, &tmp );
-}
-
-
-static inline void get_interrupt_interval( pegasus_t *pegasus )
-{
-	__u8	data[2];
-
-	read_eprom_word( pegasus, 4, (__u16 *)data );
-	if ( data[1] < 0x80 ) {
-		info( "intr interval will be changed from %ums to %ums",
-		     data[1], 0x80 );
-		data[1] = 0x80;
-#ifdef	PEGASUS_WRITE_EEPROM
-		write_eprom_word( pegasus, 4, *(__u16 *)data );
-#endif
-	}
-	pegasus->intr_interval = data[1];
-}
-
-
-static void set_carrier(struct net_device *net)
-{
-	pegasus_t	*pegasus;
-	short		tmp;
-
-	pegasus = net->priv;
-	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
-	if (tmp & BMSR_LSTATUS)
-		netif_carrier_on(net);
-	else
-		netif_carrier_off(net);
-	
-}
-
-
-static int pegasus_open(struct net_device *net)
-{
-	pegasus_t *pegasus = (pegasus_t *)net->priv;
-	int	res;
-
-	FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
-			usb_rcvbulkpipe(pegasus->usb, 1),
-			pegasus->rx_buff, PEGASUS_MAX_MTU, 
-			read_bulk_callback, pegasus );
-	if ( (res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)) )
-		warn("%s: failed rx_urb %d", __FUNCTION__, res);
-#ifdef	PEGASUS_USE_INTR
-	FILL_INT_URB( pegasus->intr_urb, pegasus->usb,
-			usb_rcvintpipe(pegasus->usb, 3),
-			pegasus->intr_buff, sizeof(pegasus->intr_buff),
-			intr_callback, pegasus, pegasus->intr_interval );
-	if ( (res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)) )
-		warn("%s: failed intr_urb %d", __FUNCTION__, res);
-#endif
-	netif_start_queue( net );
-	pegasus->flags |= PEGASUS_RUNNING;
-	if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
-		err("can't enable_net_traffic() - %d", res);
-		return -EIO;
-	}
-	set_carrier(net);
-
-	return 0;
-}
-
-
-static int pegasus_close( struct net_device *net )
-{
-	pegasus_t	*pegasus = net->priv;
-
-	pegasus->flags &= ~PEGASUS_RUNNING;
-	netif_stop_queue( net );
-	if ( !(pegasus->flags & PEGASUS_UNPLUG) )
-		disable_net_traffic( pegasus );
-
-	usb_unlink_urb( pegasus->rx_urb );
-	usb_unlink_urb( pegasus->tx_urb );
-	usb_unlink_urb( pegasus->ctrl_urb );
-#ifdef	PEGASUS_USE_INTR
-	usb_unlink_urb( pegasus->intr_urb );
-#endif
-
-	return 0;
-}
-
-
-static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
-{
-	pegasus_t	*pegasus;
-	int		cmd;
-	char		tmp[128];
-
-	pegasus = net->priv;
-	if (get_user(cmd, (int *)uaddr))
-		return -EFAULT;
-	switch (cmd) {
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-		strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
-		strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
-		sprintf(tmp, "usb%d:%d", pegasus->usb->bus->busnum,
-		        pegasus->usb->devnum);
-		strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
-		if (copy_to_user(uaddr, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd;
-		short	lpa, bmcr;
-
-		if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
-			return -EFAULT;
-		ecmd.supported = (SUPPORTED_10baseT_Half |
-		                 SUPPORTED_10baseT_Full |
-		                 SUPPORTED_100baseT_Half |
-		                 SUPPORTED_100baseT_Full |
-		                 SUPPORTED_Autoneg |
-		                 SUPPORTED_TP |
-		                 SUPPORTED_MII);
-		ecmd.port = PORT_TP;
-		ecmd.transceiver = XCVR_INTERNAL;
-		ecmd.phy_address = pegasus->phy;
-		read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
-		read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
-		if (bmcr & BMCR_ANENABLE) {
-			ecmd.autoneg = AUTONEG_ENABLE;
-			ecmd.speed = lpa & (LPA_100HALF|LPA_100FULL) ?
-		                     SPEED_100 : SPEED_10;
-			if (ecmd.speed == SPEED_100)
-				ecmd.duplex = lpa & LPA_100FULL ?
-				              DUPLEX_FULL : DUPLEX_HALF;
-			else
-				ecmd.duplex = lpa & LPA_10FULL ?
-				              DUPLEX_FULL : DUPLEX_HALF;
-		} else {
-			ecmd.autoneg = AUTONEG_DISABLE;
-			ecmd.speed = bmcr & BMCR_SPEED100 ? 
-			             SPEED_100 : SPEED_10;
-			ecmd.duplex = bmcr & BMCR_FULLDPLX ?
-			              DUPLEX_FULL : DUPLEX_HALF;
-		}
-		if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		
-		return 0;
-	}
-	case ETHTOOL_SSET: {
-		return -EOPNOTSUPP;
-	}
-	case ETHTOOL_GLINK: {
-		struct ethtool_value edata = {ETHTOOL_GLINK};
-		edata.data = netif_carrier_ok(net);
-		if (copy_to_user(uaddr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-
-static int pegasus_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
-{
-	__u16 *data = (__u16 *)&rq->ifr_data;
-	pegasus_t	*pegasus = net->priv;
-
-	switch(cmd) {
-	case SIOCETHTOOL:
-		return pegasus_ethtool_ioctl(net, rq->ifr_data);
-	case SIOCDEVPRIVATE:
-		data[0] = pegasus->phy;
-	case SIOCDEVPRIVATE+1:
-		read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]);
-		return 0;
-	case SIOCDEVPRIVATE+2:
-		if ( !capable(CAP_NET_ADMIN) )
-			return -EPERM;
-		write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]);
-		return 0;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-
-static void pegasus_set_multicast( struct net_device *net )
-{
-	pegasus_t *pegasus = net->priv;
-
-	netif_stop_queue(net);
-
-	if (net->flags & IFF_PROMISC) {
-		pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
-		info("%s: Promiscuous mode enabled", net->name);
-	} else if ((net->mc_count > multicast_filter_limit) ||
-			(net->flags & IFF_ALLMULTI)) {
-		pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
-		pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
-		info("%s set allmulti", net->name);
-	} else {
-		pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
-		pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
-	}
-
-	pegasus->flags |= ETH_REGS_CHANGE;
-	ctrl_callback( pegasus->ctrl_urb );
-
-	netif_wake_queue(net);
-}
-
-
-static __u8 mii_phy_probe( pegasus_t *pegasus )
-{
-	int	i;
-	__u16	tmp;
-
-	for ( i=0; i < 32; i++ ) {
-		read_mii_word( pegasus, i, MII_BMSR, &tmp );
-		if ( tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0 )
-			continue;
-		else
-			return	i;
-	}
-
-	return	0xff;
-}
-
-
-static inline void setup_pegasus_II( pegasus_t *pegasus )
-{
-	set_register( pegasus, Reg1d, 0 );
-	set_register( pegasus, Reg7b, 2 );
-	if ( pegasus->features & HAS_HOME_PNA  && mii_mode )
-		set_register( pegasus, Reg81, 6 );
-	else
-		set_register( pegasus, Reg81, 2 );
-}
-
-
-static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum,
-			     const struct usb_device_id *id)
-{
-	struct net_device	*net;
-	pegasus_t		*pegasus;
-	int			dev_index = id - pegasus_ids;
-
-	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-		err("usb_set_configuration() failed");
-		return NULL;
-	}
-
-	if(!(pegasus = kmalloc(sizeof(struct pegasus), GFP_KERNEL))) {
-		err("out of memory allocating device structure");
-		return NULL;
-	}
-
-	usb_inc_dev_use( dev );
-	memset(pegasus, 0, sizeof(struct pegasus));
-	pegasus->dev_index = dev_index;
-	init_waitqueue_head( &pegasus->ctrl_wait );
-
-	pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!pegasus->ctrl_urb) {
-		kfree (pegasus);
-		return NULL;
-	}
-	pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!pegasus->rx_urb) {
-		usb_free_urb (pegasus->ctrl_urb);
-		kfree (pegasus);
-		return NULL;
-	}
-	pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!pegasus->tx_urb) {
-		usb_free_urb (pegasus->rx_urb);
-		usb_free_urb (pegasus->ctrl_urb);
-		kfree (pegasus);
-		return NULL;
-	}
-	pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!pegasus->intr_urb) {
-		usb_free_urb (pegasus->tx_urb);
-		usb_free_urb (pegasus->rx_urb);
-		usb_free_urb (pegasus->ctrl_urb);
-		kfree (pegasus);
-		return NULL;
-	}
-
-	net = init_etherdev( NULL, 0 );
-	if ( !net ) {
-		usb_free_urb (pegasus->tx_urb);
-		usb_free_urb (pegasus->rx_urb);
-		usb_free_urb (pegasus->ctrl_urb);
-		kfree( pegasus );
-		return	NULL;
-	}
-	
-	pegasus->usb = dev;
-	pegasus->net = net;
-	SET_MODULE_OWNER(net);
-	net->priv = pegasus;
-	net->open = pegasus_open;
-	net->stop = pegasus_close;
-	net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
-	net->tx_timeout = pegasus_tx_timeout;
-	net->do_ioctl = pegasus_ioctl;
-	net->hard_start_xmit = pegasus_start_xmit;
-	net->set_multicast_list = pegasus_set_multicast;
-	net->get_stats = pegasus_netdev_stats;
-	net->mtu = PEGASUS_MTU;
-
-	pegasus->features = usb_dev_id[dev_index].private;
-#ifdef	PEGASUS_USE_INTR
-	get_interrupt_interval( pegasus );
-#endif
-	if ( reset_mac(pegasus) ) {
-		err("can't reset MAC");
-		unregister_netdev( pegasus->net );
-		usb_free_urb (pegasus->tx_urb);
-		usb_free_urb (pegasus->rx_urb);
-		usb_free_urb (pegasus->ctrl_urb);
-		kfree(pegasus->net);
-		kfree(pegasus);
-		pegasus = NULL;
-		return NULL;
-	}
-
-	info( "%s: %s", net->name, usb_dev_id[dev_index].name );
-
-	set_ethernet_addr( pegasus );
-
-	if ( pegasus->features & PEGASUS_II ) {
-		info( "setup Pegasus II specific registers" );
-		setup_pegasus_II( pegasus );
-	}
-	
-	pegasus->phy = mii_phy_probe( pegasus );
-	if ( pegasus->phy == 0xff ) {
-		warn( "can't locate MII phy, using default" );
-		pegasus->phy = 1;
-	}
-
-	return pegasus;
-}
-
-
-static void pegasus_disconnect( struct usb_device *dev, void *ptr )
-{
-	struct pegasus *pegasus = ptr;
-
-	if ( !pegasus ) {
-		warn("unregistering non-existant device");
-		return;
-	}
-
-	pegasus->flags |= PEGASUS_UNPLUG;
-	unregister_netdev( pegasus->net );
-	usb_dec_dev_use( dev );
-	usb_unlink_urb(pegasus->intr_urb);
-	usb_unlink_urb(pegasus->tx_urb);
-	usb_unlink_urb(pegasus->rx_urb);
-	usb_unlink_urb(pegasus->ctrl_urb);
-	usb_free_urb(pegasus->intr_urb);
-	usb_free_urb(pegasus->tx_urb);
-	usb_free_urb(pegasus->rx_urb);
-	usb_free_urb(pegasus->ctrl_urb);
-	kfree( pegasus->net );
-	kfree( pegasus );
-	pegasus = NULL;
-}
-
-
-static struct usb_driver pegasus_driver = {
-	name:		"pegasus",
-	probe:		pegasus_probe,
-	disconnect:	pegasus_disconnect,
-	id_table:	pegasus_ids,
-};
-
-int __init pegasus_init(void)
-{
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return usb_register( &pegasus_driver );
-}
-
-void __exit pegasus_exit(void)
-{
-	usb_deregister( &pegasus_driver );
-}
-
-module_init( pegasus_init );
-module_exit( pegasus_exit );
diff -Nru a/drivers/usb/pegasus.h b/drivers/usb/pegasus.h
--- a/drivers/usb/pegasus.h	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#ifndef	PEGASUS_DEV
-
-#define	PEGASUS_II		0x80000000
-#define	HAS_HOME_PNA		0x40000000
-
-#define	PEGASUS_MTU		1500
-#define	PEGASUS_MAX_MTU		1536
-
-#define	EPROM_WRITE		0x01
-#define	EPROM_READ		0x02
-#define	EPROM_DONE		0x04
-#define	EPROM_WR_ENABLE		0x10
-#define	EPROM_LOAD		0x20
-
-#define	PHY_DONE		0x80
-#define	PHY_READ		0x40
-#define	PHY_WRITE		0x20
-#define	DEFAULT_GPIO_RESET	0x24
-#define	LINKSYS_GPIO_RESET	0x24
-#define	DEFAULT_GPIO_SET	0x26
-
-#define	PEGASUS_PRESENT		0x00000001
-#define	PEGASUS_RUNNING		0x00000002
-#define	PEGASUS_TX_BUSY		0x00000004
-#define	PEGASUS_RX_BUSY		0x00000008
-#define	CTRL_URB_RUNNING	0x00000010
-#define	CTRL_URB_SLEEP		0x00000020
-#define	PEGASUS_UNPLUG		0x00000040
-#define	ETH_REGS_CHANGE		0x40000000
-#define	ETH_REGS_CHANGED	0x80000000
-
-#define	RX_MULTICAST		2
-#define	RX_PROMISCUOUS		4
-
-#define	REG_TIMEOUT		(HZ)
-#define	PEGASUS_TX_TIMEOUT	(HZ*10)
-
-#define	TX_UNDERRUN		0x80
-#define	EXCESSIVE_COL		0x40
-#define	LATE_COL		0x20
-#define	NO_CARRIER		0x10
-#define	LOSS_CARRIER		0x08
-#define	JABBER_TIMEOUT		0x04
-
-#define	PEGASUS_REQT_READ	0xc0
-#define	PEGASUS_REQT_WRITE	0x40
-#define	PEGASUS_REQ_GET_REGS	0xf0
-#define	PEGASUS_REQ_SET_REGS	0xf1
-#define	PEGASUS_REQ_SET_REG	PEGASUS_REQ_SET_REGS
-
-enum pegasus_registers {
-	EthCtrl0 = 0,
-	EthCtrl1 = 1,
-	EthCtrl2 = 2,
-	EthID = 0x10,
-	Reg1d = 0x1d,
-	EpromOffset = 0x20,
-	EpromData = 0x21,	/* 0x21 low, 0x22 high byte */
-	EpromCtrl = 0x23,
-	PhyAddr = 0x25,
-	PhyData = 0x26, 	/* 0x26 low, 0x27 high byte */
-	PhyCtrl = 0x28,
-	UsbStst = 0x2a,
-	EthTxStat0 = 0x2b,
-	EthTxStat1 = 0x2c,
-	EthRxStat = 0x2d,
-	Reg7b = 0x7b,
-	Gpio0 = 0x7e,
-	Gpio1 = 0x7f,
-	Reg81 = 0x81,
-};
-
-
-typedef struct pegasus {
-	struct usb_device	*usb;
-	struct net_device	*net;
-	struct net_device_stats	stats;
-	unsigned		flags;
-	unsigned		features;
-	int			dev_index;
-	int			intr_interval;
-	struct urb		*ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
-	struct usb_ctrlrequest	dr;
-	wait_queue_head_t	ctrl_wait;
-	struct semaphore	ctrl_sem;
-	unsigned char		rx_buff[PEGASUS_MAX_MTU];
-	unsigned char		tx_buff[PEGASUS_MAX_MTU];
-	unsigned char		intr_buff[8];
-	__u8			eth_regs[4];
-	__u8			phy;
-	__u8			gpio_res;
-} pegasus_t;
-
-
-struct usb_eth_dev {
-	char	*name;
-	__u16	vendor;
-	__u16	device;
-	__u32	private; /* LSB is gpio reset value */
-};
-
-#define	VENDOR_3COM		0x0506
-#define	VENDOR_ABOCOM		0x07b8
-#define	VENDOR_ACCTON		0x083a
-#define	VENDOR_ADMTEK		0x07a6
-#define	VENDOR_ALLIEDTEL	0x07c9
-#define	VENDOR_BELKIN		0x050d
-#define	VENDOR_BILLIONTON	0x08dd
-#define	VENDOR_COMPAQ		0x049f
-#define	VENDOR_COREGA		0x07aa
-#define	VENDOR_DLINK		0x2001
-#define	VENDOR_ELCON		0x0db7
-#define	VENDOR_ELSA		0x05cc
-#define	VENDOR_HAWKING		0x0e66
-#define	VENDOR_IODATA		0x04bb
-#define	VENDOR_KINGSTON		0x0951
-#define	VENDOR_LANEED		0x056e
-#define	VENDOR_LINKSYS		0x066b
-#define	VENDOR_MELCO		0x0411
-#define	VENDOR_SMARTBRIDGES	0x08d1
-#define	VENDOR_SMC		0x0707
-#define	VENDOR_SOHOWARE		0x15e8
-#define	VENDOR_SIEMENS		0x067c
-
-
-#else	/* PEGASUS_DEV */
-
-PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c,
-		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
-PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104,
-		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004,
-		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007,
-		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
-		DEFAULT_GPIO_RESET | PEGASUS_II ) 	
-PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
-		VENDOR_ADMTEK, 0x8511,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
-		VENDOR_ADMTEK, 0x0986,
-		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987,
-		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001,
-		LINKSYS_GPIO_RESET )
-PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002,
-		LINKSYS_GPIO_RESET )
-PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102,
-		LINKSYS_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b,
-		LINKSYS_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c,
-		LINKSYS_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003,
-		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "ELCON EPLC10Mi USB to Powerline Adapter", VENDOR_ELCON, 0x0002,
-		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
-PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
-		DEFAULT_GPIO_RESET)
-PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202,
-		LINKSYS_GPIO_RESET )
-PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203,
-		LINKSYS_GPIO_RESET )
-PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204,
-		LINKSYS_GPIO_RESET | HAS_HOME_PNA )
-PEGASUS_DEV( "Linksys USB Ethernet Adapter", VENDOR_LINKSYS, 0x2206,
-		LINKSYS_GPIO_RESET )
-PEGASUS_DEV( "Linksys USB USB10TX", VENDOR_LINKSYS, 0x400b,
-		LINKSYS_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c,
-		LINKSYS_GPIO_RESET | PEGASUS_II )	
-PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
-		DEFAULT_GPIO_RESET | PEGASUS_II )
-PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
-		DEFAULT_GPIO_RESET | PEGASUS_II)
-PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
-		DEFAULT_GPIO_RESET )
-PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
-		DEFAULT_GPIO_RESET )
-
-
-#endif	/* PEGASUS_DEV */
diff -Nru a/drivers/usb/printer.c b/drivers/usb/printer.c
--- a/drivers/usb/printer.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1109 +0,0 @@
-/*
- * printer.c  Version 0.12
- *
- * Copyright (c) 1999 Michael Gee	<michael@linuxspecific.com>
- * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
- * Copyright (c) 2000 Randy Dunlap	<randy.dunlap@intel.com>
- * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
- # Copyright (c) 2001 Pete Zaitcev	<zaitcev@redhat.com>
- # Copyright (c) 2001 David Paschal	<paschal@rcsis.com>
- *
- * USB Printer Device Class driver for USB printers and printer cables
- *
- * Sponsored by SuSE
- *
- * ChangeLog:
- *	v0.1 - thorough cleaning, URBification, almost a rewrite
- *	v0.2 - some more cleanups
- *	v0.3 - cleaner again, waitqueue fixes
- *	v0.4 - fixes in unidirectional mode
- *	v0.5 - add DEVICE_ID string support
- *	v0.6 - never time out
- *	v0.7 - fixed bulk-IN read and poll (David Paschal)
- *	v0.8 - add devfs support
- *	v0.9 - fix unplug-while-open paths
- *	v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
- *	v0.11 - add proto_bias option (Pete Zaitcev)
- *	v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/signal.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/lp.h>
-#include <linux/devfs_fs_kernel.h>
-#undef DEBUG
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.12"
-#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
-#define DRIVER_DESC "USB Printer Device Class driver"
-
-#define USBLP_BUF_SIZE		8192
-#define DEVICE_ID_SIZE		1024
-
-/* ioctls: */
-#define LPGETSTATUS		0x060b		/* same as in drivers/char/lp.c */
-#define IOCNR_GET_DEVICE_ID		1
-#define IOCNR_GET_PROTOCOLS		2
-#define IOCNR_SET_PROTOCOL		3
-#define IOCNR_HP_SET_CHANNEL		4
-#define IOCNR_GET_BUS_ADDRESS		5
-#define IOCNR_GET_VID_PID		6
-/* Get device_id string: */
-#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
-/* The following ioctls were added for http://hpoj.sourceforge.net: */
-/* Get two-int array:
- * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
- * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
-#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
-/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
-#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
-/* Set channel number (HP Vendor-specific command): */
-#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
-/* Get two-int array: [0]=bus number, [1]=device address: */
-#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
-/* Get two-int array: [0]=vendor ID, [1]=product ID: */
-#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
-
-/*
- * A DEVICE_ID string may include the printer's serial number.
- * It should end with a semi-colon (';').
- * An example from an HP 970C DeskJet printer is (this is one long string,
- * with the serial number changed):
-MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ:                    ;
- */
-
-/*
- * USB Printer Requests
- */
-
-#define USBLP_REQ_GET_ID			0x00
-#define USBLP_REQ_GET_STATUS			0x01
-#define USBLP_REQ_RESET				0x02
-#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST	0x00	/* HP Vendor-specific */
-
-#define USBLP_MINORS		16
-#define USBLP_MINOR_BASE	0
-
-#define USBLP_WRITE_TIMEOUT	(5*HZ)			/* 5 seconds */
-
-#define USBLP_FIRST_PROTOCOL	1
-#define USBLP_LAST_PROTOCOL	3
-#define USBLP_MAX_PROTOCOLS	(USBLP_LAST_PROTOCOL+1)
-
-struct usblp {
-	struct usb_device 	*dev;			/* USB device */
-	devfs_handle_t		devfs;			/* devfs device */
-	struct semaphore	sem;			/* locks this struct, especially "dev" */
-	char			*buf;		/* writeurb->transfer_buffer */
-	struct urb		*readurb, *writeurb;	/* The urbs */
-	wait_queue_head_t	wait;			/* Zzzzz ... */
-	int			readcount;		/* Counter for reads */
-	int			ifnum;			/* Interface number */
-	/* Alternate-setting numbers and endpoints for each protocol
-	 * (7/1/{index=1,2,3}) that the device supports: */
-	struct {
-		int				alt_setting;
-		struct usb_endpoint_descriptor	*epwrite;
-		struct usb_endpoint_descriptor	*epread;
-	}			protocol[USBLP_MAX_PROTOCOLS];
-	int			current_protocol;
-	int			minor;			/* minor number of device */
-	int			wcomplete;		/* writing is completed */
-	int			rcomplete;		/* reading is completed */
-	unsigned int		quirks;			/* quirks flags */
-	unsigned char		used;			/* True if open */
-	unsigned char		bidir;			/* interface is bidirectional */
-	unsigned char		*device_id_string;	/* IEEE 1284 DEVICE ID string (ptr) */
-							/* first 2 bytes are (big-endian) length */
-};
-
-#ifdef DEBUG
-static void usblp_dump(struct usblp *usblp) {
-	int p;
-
-	dbg("usblp=0x%p", usblp);
-	dbg("dev=0x%p", usblp->dev);
-	dbg("devfs=0x%p", usblp->devfs);
-	dbg("buf=0x%p", usblp->buf);
-	dbg("readcount=%d", usblp->readcount);
-	dbg("ifnum=%d", usblp->ifnum);
-    for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
-	dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
-	dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
-	dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
-    }
-	dbg("current_protocol=%d", usblp->current_protocol);
-	dbg("minor=%d", usblp->minor);
-	dbg("wcomplete=%d", usblp->wcomplete);
-	dbg("rcomplete=%d", usblp->rcomplete);
-	dbg("quirks=%d", usblp->quirks);
-	dbg("used=%d", usblp->used);
-	dbg("bidir=%d", usblp->bidir);
-	dbg("device_id_string=\"%s\"",
-		usblp->device_id_string ?
-			usblp->device_id_string + 2 :
-			(unsigned char *)"(null)");
-}
-#endif
-
-extern devfs_handle_t usb_devfs_handle;			/* /dev/usb dir. */
-
-static struct usblp *usblp_table[USBLP_MINORS];
-
-/* Quirks: various printer quirks are handled by this table & its flags. */
-
-struct quirk_printer_struct {
-	__u16 vendorId;
-	__u16 productId;
-	unsigned int quirks;
-};
-
-#define USBLP_QUIRK_BIDIR	0x1	/* reports bidir but requires unidirectional mode (no INs/reads) */
-#define USBLP_QUIRK_USB_INIT	0x2	/* needs vendor USB init string */
-
-static struct quirk_printer_struct quirk_printers[] = {
-	{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
-	{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
-	{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
-	{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
-	{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
-	{ 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
-	{ 0, 0 }
-};
-
-static int usblp_select_alts(struct usblp *usblp);
-static int usblp_set_protocol(struct usblp *usblp, int protocol);
-static int usblp_cache_device_id_string(struct usblp *usblp);
-
-
-/*
- * Functions for usblp control messages.
- */
-
-static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
-{
-	int retval = usb_control_msg(usblp->dev,
-		dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
-		request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
-	dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
-		request, !!dir, recip, value, len, retval);
-	return retval < 0 ? retval : 0;
-}
-
-#define usblp_read_status(usblp, status)\
-	usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
-#define usblp_get_id(usblp, config, id, maxlen)\
-	usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
-#define usblp_reset(usblp)\
-	usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
-
-#define usblp_hp_channel_change_request(usblp, channel, buffer) \
-	usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
-
-/*
- * See the description for usblp_select_alts() below for the usage
- * explanation.  Look into your /proc/bus/usb/devices and dmesg in
- * case of any trouble.
- */
-static int proto_bias = -1;
-
-/*
- * URB callback.
- */
-
-static void usblp_bulk_read(struct urb *urb)
-{
-	struct usblp *usblp = urb->context;
-
-	if (!usblp || !usblp->dev || !usblp->used)
-		return;
-
-	if (unlikely(urb->status))
-		warn("usblp%d: nonzero read/write bulk status received: %d",
-			usblp->minor, urb->status);
-	usblp->rcomplete = 1;
-	wake_up_interruptible(&usblp->wait);
-}
-
-static void usblp_bulk_write(struct urb *urb)
-{
-	struct usblp *usblp = urb->context;
-
-	if (!usblp || !usblp->dev || !usblp->used)
-		return;
-
-	if (unlikely(urb->status))
-		warn("usblp%d: nonzero read/write bulk status received: %d",
-			usblp->minor, urb->status);
-	usblp->wcomplete = 1;
-	wake_up_interruptible(&usblp->wait);
-}
-
-/*
- * Get and print printer errors.
- */
-
-static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
-
-static int usblp_check_status(struct usblp *usblp, int err)
-{
-	unsigned char status, newerr = 0;
-	int error;
-
-	error = usblp_read_status (usblp, &status);
-	if (error < 0) {
-		err("usblp%d: error %d reading printer status",
-			usblp->minor, error);
-		return 0;
-	}
-
-	if (~status & LP_PERRORP) {
-		newerr = 3;
-		if (status & LP_POUTPA) newerr = 1;
-		if (~status & LP_PSELECD) newerr = 2;
-	}
-
-	if (newerr != err)
-		info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
-
-	return newerr;
-}
-
-/*
- * File op functions.
- */
-
-static int usblp_open(struct inode *inode, struct file *file)
-{
-	int minor = minor(inode->i_rdev) - USBLP_MINOR_BASE;
-	struct usblp *usblp;
-	int retval;
-
-	if (minor < 0 || minor >= USBLP_MINORS)
-		return -ENODEV;
-
-	lock_kernel();
-	usblp  = usblp_table[minor];
-
-	retval = -ENODEV;
-	if (!usblp || !usblp->dev)
-		goto out;
-
-	retval = -EBUSY;
-	if (usblp->used)
-		goto out;
-
-	/*
-	 * TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ???
-	 * This is #if 0-ed because we *don't* want to fail an open
-	 * just because the printer is off-line.
-	 */
-#if 0
-	if ((retval = usblp_check_status(usblp, 0))) {
-		retval = retval > 1 ? -EIO : -ENOSPC;
-		goto out;
-	}
-#else
-	retval = 0;
-#endif
-
-	usblp->used = 1;
-	file->private_data = usblp;
-
-	usblp->writeurb->transfer_buffer_length = 0;
-	usblp->writeurb->status = 0;
-	usblp->wcomplete = 1; /* we begin writeable */
-	usblp->rcomplete = 0;
-
-	if (usblp->bidir) {
-		usblp->readcount = 0;
-		usblp->readurb->dev = usblp->dev;
-		if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
-			retval = -EIO;
-			usblp->used = 0;
-			file->private_data = NULL;
-		}
-	}
-out:
-	unlock_kernel();
-	return retval;
-}
-
-static void usblp_cleanup (struct usblp *usblp)
-{
-	devfs_unregister (usblp->devfs);
-	usblp_table [usblp->minor] = NULL;
-	info("usblp%d: removed", usblp->minor);
-
-	kfree (usblp->writeurb->transfer_buffer);
-	kfree (usblp->device_id_string);
-	usb_free_urb(usblp->writeurb);
-	usb_free_urb(usblp->readurb);
-	kfree (usblp);
-}
-
-static void usblp_unlink_urbs(struct usblp *usblp)
-{
-	usb_unlink_urb(usblp->writeurb);
-	if (usblp->bidir)
-		usb_unlink_urb(usblp->readurb);
-}
-
-static int usblp_release(struct inode *inode, struct file *file)
-{
-	struct usblp *usblp = file->private_data;
-
-	down (&usblp->sem);
-	lock_kernel();
-	usblp->used = 0;
-	if (usblp->dev) {
-		usblp_unlink_urbs(usblp);
-		up(&usblp->sem);
-	} else 		/* finish cleanup from disconnect */
-		usblp_cleanup (usblp);
-	unlock_kernel();
-	return 0;
-}
-
-/* No kernel lock - fine */
-static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct usblp *usblp = file->private_data;
-	poll_wait(file, &usblp->wait, wait);
- 	return ((!usblp->bidir || usblp->readurb->status  == -EINPROGRESS) ? 0 : POLLIN  | POLLRDNORM)
- 			       | (usblp->writeurb->status == -EINPROGRESS  ? 0 : POLLOUT | POLLWRNORM);
-}
-
-static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct usblp *usblp = file->private_data;
-	int length, err, i;
-	unsigned char status, newChannel;
-	int twoints[2];
-	int retval = 0;
-
-	down (&usblp->sem);
-	if (!usblp->dev) {
-		retval = -ENODEV;
-		goto done;
-	}
-
-	if (_IOC_TYPE(cmd) == 'P')	/* new-style ioctl number */
-
-		switch (_IOC_NR(cmd)) {
-
-			case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */
-				if (_IOC_DIR(cmd) != _IOC_READ) {
-					retval = -EINVAL;
-					goto done;
-				}
-
-				length = usblp_cache_device_id_string(usblp);
-				if (length < 0) {
-					retval = length;
-					goto done;
-				}
-				if (length > _IOC_SIZE(cmd))
-					length = _IOC_SIZE(cmd); /* truncate */
-
-				if (copy_to_user((unsigned char *) arg,
-						usblp->device_id_string,
-						(unsigned long) length)) {
-					retval = -EFAULT;
-					goto done;
-				}
-
-				break;
-
-			case IOCNR_GET_PROTOCOLS:
-				if (_IOC_DIR(cmd) != _IOC_READ ||
-				    _IOC_SIZE(cmd) < sizeof(twoints)) {
-					retval = -EINVAL;
-					goto done;
-				}
-
-				twoints[0] = usblp->current_protocol;
-				twoints[1] = 0;
-				for (i = USBLP_FIRST_PROTOCOL;
-				     i <= USBLP_LAST_PROTOCOL; i++) {
-					if (usblp->protocol[i].alt_setting >= 0)
-						twoints[1] |= (1<<i);
-				}
-
-				if (copy_to_user((unsigned char *)arg,
-						(unsigned char *)twoints,
-						sizeof(twoints))) {
-					retval = -EFAULT;
-					goto done;
-				}
-
-				break;
-
-			case IOCNR_SET_PROTOCOL:
-				if (_IOC_DIR(cmd) != _IOC_WRITE) {
-					retval = -EINVAL;
-					goto done;
-				}
-
-#ifdef DEBUG
-				if (arg == -10) {
-					usblp_dump(usblp);
-					break;
-				}
-#endif
-
-				usblp_unlink_urbs(usblp);
-				retval = usblp_set_protocol(usblp, arg);
-				if (retval < 0) {
-					usblp_set_protocol(usblp,
-						usblp->current_protocol);
-				}
-				break;
-
-			case IOCNR_HP_SET_CHANNEL:
-				if (_IOC_DIR(cmd) != _IOC_WRITE ||
-				    usblp->dev->descriptor.idVendor != 0x03F0 ||
-				    usblp->quirks & USBLP_QUIRK_BIDIR) {
-					retval = -EINVAL;
-					goto done;
-				}
-
-				err = usblp_hp_channel_change_request(usblp,
-					arg, &newChannel);
-				if (err < 0) {
-					err("usblp%d: error = %d setting "
-						"HP channel",
-						usblp->minor, err);
-					retval = -EIO;
-					goto done;
-				}
-
-				dbg("usblp%d requested/got HP channel %ld/%d",
-					usblp->minor, arg, newChannel);
-				break;
-
-			case IOCNR_GET_BUS_ADDRESS:
-				if (_IOC_DIR(cmd) != _IOC_READ ||
-				    _IOC_SIZE(cmd) < sizeof(twoints)) {
-					retval = -EINVAL;
-					goto done;
-				}
-
-				twoints[0] = usblp->dev->bus->busnum;
-				twoints[1] = usblp->dev->devnum;
-				if (copy_to_user((unsigned char *)arg,
-						(unsigned char *)twoints,
-						sizeof(twoints))) {
-					retval = -EFAULT;
-					goto done;
-				}
-
-				dbg("usblp%d is bus=%d, device=%d",
-					usblp->minor, twoints[0], twoints[1]);
-				break;
-
-			case IOCNR_GET_VID_PID:
-				if (_IOC_DIR(cmd) != _IOC_READ ||
-				    _IOC_SIZE(cmd) < sizeof(twoints)) {
-					retval = -EINVAL;
-					goto done;
-				}
-
-				twoints[0] = usblp->dev->descriptor.idVendor;
-				twoints[1] = usblp->dev->descriptor.idProduct;
-				if (copy_to_user((unsigned char *)arg,
-						(unsigned char *)twoints,
-						sizeof(twoints))) {
-					retval = -EFAULT;
-					goto done;
-				}
-
-				dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
-					usblp->minor, twoints[0], twoints[1]);
-				break;
-
-			default:
-				retval = -EINVAL;
-		}
-	else	/* old-style ioctl value */
-		switch (cmd) {
-
-			case LPGETSTATUS:
-				if (usblp_read_status(usblp, &status)) {
-					err("usblp%d: failed reading printer status", usblp->minor);
-					retval = -EIO;
-					goto done;
-				}
-				if (copy_to_user ((unsigned char *)arg, &status, 1))
-					retval = -EFAULT;
-				break;
-
-			default:
-				retval = -EINVAL;
-		}
-
-done:
-	up (&usblp->sem);
-	return retval;
-}
-
-static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct usblp *usblp = file->private_data;
-	int timeout, err = 0, writecount = 0;
-
-	while (writecount < count) {
-		if (!usblp->wcomplete) {
-			barrier();
-			if (file->f_flags & O_NONBLOCK)
-				return -EAGAIN;
-
-			timeout = USBLP_WRITE_TIMEOUT;
-			add_wait_queue(&usblp->wait, &wait);
-			while ( 1==1 ) {
-
-				if (signal_pending(current)) {
-					remove_wait_queue(&usblp->wait, &wait);
-					return writecount ? writecount : -EINTR;
-				}
-				set_current_state(TASK_INTERRUPTIBLE);
-				if (timeout && !usblp->wcomplete) {
-					timeout = schedule_timeout(timeout);
-				} else {
-					set_current_state(TASK_RUNNING);
-					break;
-				}
-			}
-			remove_wait_queue(&usblp->wait, &wait);
-		}
-
-		down (&usblp->sem);
-		if (!usblp->dev) {
-			up (&usblp->sem);
-			return -ENODEV;
-		}
-
-		if (usblp->writeurb->status != 0) {
-			if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-				if (!usblp->wcomplete)
-					err("usblp%d: error %d writing to printer",
-						usblp->minor, usblp->writeurb->status);
-				err = usblp->writeurb->status;
-			} else
-				err = usblp_check_status(usblp, err);
-			up (&usblp->sem);
-
-			/* if the fault was due to disconnect, let khubd's
-			 * call to usblp_disconnect() grab usblp->sem ...
-			 */
-			schedule ();
-			continue;
-		}
-
-		writecount += usblp->writeurb->transfer_buffer_length;
-		usblp->writeurb->transfer_buffer_length = 0;
-
-		if (writecount == count) {
-			up (&usblp->sem);
-			break;
-		}
-
-		usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
-							  (count - writecount) : USBLP_BUF_SIZE;
-
-		if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount,
-				usblp->writeurb->transfer_buffer_length)) return -EFAULT;
-
-		usblp->writeurb->dev = usblp->dev;
-		usblp->wcomplete = 0;
-		if (usb_submit_urb(usblp->writeurb, GFP_KERNEL)) {
-			count = -EIO;
-			up (&usblp->sem);
-			break;
-		}
-		up (&usblp->sem);
-	}
-
-	return count;
-}
-
-static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
-{
-	struct usblp *usblp = file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (!usblp->bidir)
-		return -EINVAL;
-
-	down (&usblp->sem);
-	if (!usblp->dev) {
-		count = -ENODEV;
-		goto done;
-	}
-
-	if (!usblp->rcomplete) {
-		barrier();
-
-		if (file->f_flags & O_NONBLOCK) {
-			count = -EAGAIN;
-			goto done;
-		}
-
-		// FIXME:  only use urb->status inside completion
-		// callbacks; this way is racey...
-		add_wait_queue(&usblp->wait, &wait);
-		while (1==1) {
-			if (signal_pending(current)) {
-				count = -EINTR;
-				remove_wait_queue(&usblp->wait, &wait);
-				goto done;
-			}
-			up (&usblp->sem);
-			set_current_state(TASK_INTERRUPTIBLE);
-			if (!usblp->rcomplete) {
-				schedule();
-			} else {
-				set_current_state(TASK_RUNNING);
-				break;
-			}
-			down (&usblp->sem);
-		}
-		remove_wait_queue(&usblp->wait, &wait);
-	}
-
-	if (!usblp->dev) {
-		count = -ENODEV;
-		goto done;
-	}
-
-	if (usblp->readurb->status) {
-		err("usblp%d: error %d reading from printer",
-			usblp->minor, usblp->readurb->status);
-		usblp->readurb->dev = usblp->dev;
- 		usblp->readcount = 0;
-		usb_submit_urb(usblp->readurb, GFP_KERNEL);
-		count = -EIO;
-		goto done;
-	}
-
-	count = count < usblp->readurb->actual_length - usblp->readcount ?
-		count :	usblp->readurb->actual_length - usblp->readcount;
-
-	if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
-		count = -EFAULT;
-		goto done;
-	}
-
-	if ((usblp->readcount += count) == usblp->readurb->actual_length) {
-		usblp->readcount = 0;
-		usblp->readurb->dev = usblp->dev;
-		usblp->rcomplete = 0;
-		if (usb_submit_urb(usblp->readurb, GFP_KERNEL)) {
-			count = -EIO;
-			goto done;
-		}
-	}
-
-done:
-	up (&usblp->sem);
-	return count;
-}
-
-/*
- * Checks for printers that have quirks, such as requiring unidirectional
- * communication but reporting bidirectional; currently some HP printers
- * have this flaw (HP 810, 880, 895, etc.), or needing an init string
- * sent at each open (like some Epsons).
- * Returns 1 if found, 0 if not found.
- *
- * HP recommended that we use the bidirectional interface but
- * don't attempt any bulk IN transfers from the IN endpoint.
- * Here's some more detail on the problem:
- * The problem is not that it isn't bidirectional though. The problem
- * is that if you request a device ID, or status information, while
- * the buffers are full, the return data will end up in the print data
- * buffer. For example if you make sure you never request the device ID
- * while you are sending print data, and you don't try to query the
- * printer status every couple of milliseconds, you will probably be OK.
- */
-static unsigned int usblp_quirks (__u16 vendor, __u16 product)
-{
-	int i;
-
-	for (i = 0; quirk_printers[i].vendorId; i++) {
-		if (vendor == quirk_printers[i].vendorId &&
-		    product == quirk_printers[i].productId)
-			return quirk_printers[i].quirks;
- 	}
-	return 0;
-}
-
-static struct file_operations usblp_fops = {
-	owner:		THIS_MODULE,
-	read:		usblp_read,
-	write:		usblp_write,
-	poll:		usblp_poll,
-	ioctl:		usblp_ioctl,
-	open:		usblp_open,
-	release:	usblp_release,
-};
-
-static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
-			 const struct usb_device_id *id)
-{
-	struct usblp *usblp = 0;
-	int protocol;
-	char name[6];
-
-	/* Malloc and start initializing usblp structure so we can use it
-	 * directly. */
-	if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
-		err("out of memory for usblp");
-		goto abort;
-	}
-	memset(usblp, 0, sizeof(struct usblp));
-	usblp->dev = dev;
-	init_MUTEX (&usblp->sem);
-	init_waitqueue_head(&usblp->wait);
-	usblp->ifnum = ifnum;
-
-	/* Look for a free usblp_table entry. */
-	while (usblp_table[usblp->minor]) {
-		usblp->minor++;
-		if (usblp->minor >= USBLP_MINORS) {
-			err("no more free usblp devices");
-			goto abort;
-		}
-	}
-
-	usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!usblp->writeurb) {
-		err("out of memory");
-		goto abort;
-	}
-	usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!usblp->readurb) {
-		err("out of memory");
-		goto abort;
-	}
-
-	/* Malloc device ID string buffer to the largest expected length,
-	 * since we can re-query it on an ioctl and a dynamic string
-	 * could change in length. */
-	if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
-		err("out of memory for device_id_string");
-		goto abort;
-	}
-
-	/* Malloc write/read buffers in one chunk.  We somewhat wastefully
-	 * malloc both regardless of bidirectionality, because the
-	 * alternate setting can be changed later via an ioctl. */
-	if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
-		err("out of memory for buf");
-		goto abort;
-	}
-
-	/* Lookup quirks for this printer. */
-	usblp->quirks = usblp_quirks(
-		dev->descriptor.idVendor,
-		dev->descriptor.idProduct);
-
-	/* Analyze and pick initial alternate settings and endpoints. */
-	protocol = usblp_select_alts(usblp);
-	if (protocol < 0) {
-		dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
-			dev->descriptor.idVendor,
-			dev->descriptor.idProduct);
-		goto abort;
-	}
-
-	/* Setup the selected alternate setting and endpoints. */
-	if (usblp_set_protocol(usblp, protocol) < 0)
-		goto abort;
-
-	/* Retrieve and store the device ID string. */
-	usblp_cache_device_id_string(usblp);
-
-#ifdef DEBUG
-	usblp_check_status(usblp, 0);
-#endif
-
-	/* If we have devfs, create with perms=660. */
-	sprintf(name, "lp%d", usblp->minor);
-	usblp->devfs = devfs_register(usb_devfs_handle, name,
-				      DEVFS_FL_DEFAULT, USB_MAJOR,
-				      USBLP_MINOR_BASE + usblp->minor,
-				      S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				      S_IWGRP, &usblp_fops, NULL);
-
-	info("usblp%d: USB %sdirectional printer dev %d "
-		"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
-		usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
-		usblp->protocol[usblp->current_protocol].alt_setting,
-		usblp->current_protocol, usblp->dev->descriptor.idVendor,
-		usblp->dev->descriptor.idProduct);
-
-	return usblp_table[usblp->minor] = usblp;
-
-abort:
-	if (usblp) {
-		usb_free_urb(usblp->writeurb);
-		usb_free_urb(usblp->readurb);
-		if (usblp->buf) kfree(usblp->buf);
-		if (usblp->device_id_string) kfree(usblp->device_id_string);
-		kfree(usblp);
-	}
-	return NULL;
-}
-
-/*
- * We are a "new" style driver with usb_device_id table,
- * but our requirements are too intricate for simple match to handle.
- *
- * The "proto_bias" option may be used to specify the preferred protocol
- * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3).  If the device
- * supports the preferred protocol, then we bind to it.
- *
- * The best interface for us is 7/1/2, because it is compatible
- * with a stream of characters. If we find it, we bind to it.
- *
- * Note that the people from hpoj.sourceforge.net need to be able to
- * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
- *
- * Failing 7/1/2, we look for 7/1/3, even though it's probably not
- * stream-compatible, because this matches the behaviour of the old code.
- *
- * If nothing else, we bind to 7/1/1 - the unidirectional interface.
- */
-static int usblp_select_alts(struct usblp *usblp)
-{
-	struct usb_interface *if_alt;
-	struct usb_interface_descriptor *ifd;
-	struct usb_endpoint_descriptor *epd, *epwrite, *epread;
-	int p, i, e;
-
-	if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
-
-	for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
-		usblp->protocol[p].alt_setting = -1;
-
-	/* Find out what we have. */
-	for (i = 0; i < if_alt->num_altsetting; i++) {
-		ifd = &if_alt->altsetting[i];
-
-		if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
-			continue;
-
-		if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
-		    ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
-			continue;
-
-		/* Look for bulk OUT and IN endpoints. */
-		epwrite = epread = 0;
-		for (e = 0; e < ifd->bNumEndpoints; e++) {
-			epd = &ifd->endpoint[e];
-
-			if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
-			    USB_ENDPOINT_XFER_BULK)
-				continue;
-
-			if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
-				if (!epwrite) epwrite=epd;
-
-			} else {
-				if (!epread) epread=epd;
-			}
-		}
-
-		/* Ignore buggy hardware without the right endpoints. */
-		if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
-			continue;
-
-		/* Turn off reads for 7/1/1 (unidirectional) interfaces
-		 * and buggy bidirectional printers. */
-		if (ifd->bInterfaceProtocol == 1) {
-			epread = NULL;
-		} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
-			info("Disabling reads from problem bidirectional "
-				"printer on usblp%d", usblp->minor);
-			epread = NULL;
-		}
-
-		usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
-		usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
-		usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
-	}
-
-	/* If our requested protocol is supported, then use it. */
-	if (proto_bias >= USBLP_FIRST_PROTOCOL &&
-	    proto_bias <= USBLP_LAST_PROTOCOL &&
-	    usblp->protocol[proto_bias].alt_setting != -1)
-		return proto_bias;
-
-	/* Ordering is important here. */
-	if (usblp->protocol[2].alt_setting != -1) return 2;
-	if (usblp->protocol[1].alt_setting != -1) return 1;
-	if (usblp->protocol[3].alt_setting != -1) return 3;
-
-	/* If nothing is available, then don't bind to this device. */
-	return -1;
-}
-
-static int usblp_set_protocol(struct usblp *usblp, int protocol)
-{
-	int r, alts;
-
-	if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
-		return -EINVAL;
-
-	alts = usblp->protocol[protocol].alt_setting;
-	if (alts < 0) return -EINVAL;
-	r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
-	if (r < 0) {
-		err("can't set desired altsetting %d on interface %d",
-			alts, usblp->ifnum);
-		return r;
-	}
-
-	FILL_BULK_URB(usblp->writeurb, usblp->dev,
-		usb_sndbulkpipe(usblp->dev,
-		 usblp->protocol[protocol].epwrite->bEndpointAddress),
-		usblp->buf, 0,
-		usblp_bulk_write, usblp);
-
-	usblp->bidir = (usblp->protocol[protocol].epread != 0);
-	if (usblp->bidir)
-		FILL_BULK_URB(usblp->readurb, usblp->dev,
-			usb_rcvbulkpipe(usblp->dev,
-			 usblp->protocol[protocol].epread->bEndpointAddress),
-			usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
-			usblp_bulk_read, usblp);
-
-	usblp->current_protocol = protocol;
-	dbg("usblp%d set protocol %d", usblp->minor, protocol);
-	return 0;
-}
-
-/* Retrieves and caches device ID string.
- * Returns length, including length bytes but not null terminator.
- * On error, returns a negative errno value. */
-static int usblp_cache_device_id_string(struct usblp *usblp)
-{
-	int err, length;
-
-	err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
-	if (err < 0) {
-		dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
-			usblp->minor, err);
-		usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
-		return -EIO;
-	}
-
-	/* First two bytes are length in big-endian.
-	 * They count themselves, and we copy them into
-	 * the user's buffer. */
-	length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
-	if (length < 2)
-		length = 2;
-	else if (length >= DEVICE_ID_SIZE)
-		length = DEVICE_ID_SIZE - 1;
-	usblp->device_id_string[length] = '\0';
-
-	dbg("usblp%d Device ID string [len=%d]=\"%s\"",
-		usblp->minor, length, &usblp->device_id_string[2]);
-
-	return length;
-}
-
-static void usblp_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usblp *usblp = ptr;
-
-	if (!usblp || !usblp->dev) {
-		err("bogus disconnect");
-		BUG ();
-	}
-
-	down (&usblp->sem);
-	lock_kernel();
-	usblp->dev = NULL;
-
-	usblp_unlink_urbs(usblp);
-
-	if (!usblp->used)
-		usblp_cleanup (usblp);
-	else 	/* cleanup later, on close */
-		up (&usblp->sem);
-	unlock_kernel();
-}
-
-static struct usb_device_id usblp_ids [] = {
-	{ USB_DEVICE_INFO(7, 1, 1) },
-	{ USB_DEVICE_INFO(7, 1, 2) },
-	{ USB_DEVICE_INFO(7, 1, 3) },
-	{ USB_INTERFACE_INFO(7, 1, 1) },
-	{ USB_INTERFACE_INFO(7, 1, 2) },
-	{ USB_INTERFACE_INFO(7, 1, 3) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usblp_ids);
-
-static struct usb_driver usblp_driver = {
-	owner:		THIS_MODULE,
-	name:		"usblp",
-	probe:		usblp_probe,
-	disconnect:	usblp_disconnect,
-	fops:		&usblp_fops,
-	minor:		USBLP_MINOR_BASE,
-	id_table:	usblp_ids,
-};
-
-static int __init usblp_init(void)
-{
-	if (usb_register(&usblp_driver))
-		return -1;
-	info(DRIVER_VERSION ": " DRIVER_DESC);
-	return 0;
-}
-
-static void __exit usblp_exit(void)
-{
-	usb_deregister(&usblp_driver);
-}
-
-module_init(usblp_init);
-module_exit(usblp_exit);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_PARM(proto_bias, "i");
-MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/pwc-ctrl.c b/drivers/usb/pwc-ctrl.c
--- a/drivers/usb/pwc-ctrl.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1205 +0,0 @@
-/* Driver for Philips webcam
-   Functions that send various control messages to the webcam, including
-   video modes.
-   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added methods for changing white balance and 
-                          red/green gains
- */
-
-/* Control functions for the cam; brightness, contrast, video mode, etc. */
-
-#ifdef __KERNEL__
-#include <asm/uaccess.h> 
-#endif
-#include <asm/errno.h>
- 
-#include "pwc.h"
-#include "pwc-ioctl.h"
-#include "pwc-uncompress.h"
-
-/* Request types: video */
-#define SET_LUM_CTL			0x01
-#define GET_LUM_CTL			0x02
-#define SET_CHROM_CTL			0x03
-#define GET_CHROM_CTL			0x04
-#define SET_STATUS_CTL			0x05
-#define GET_STATUS_CTL			0x06
-#define SET_EP_STREAM_CTL		0x07
-#define GET_EP_STREAM_CTL		0x08
-
-/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
-#define AGC_MODE_FORMATTER			0x2000
-#define PRESET_AGC_FORMATTER			0x2100
-#define SHUTTER_MODE_FORMATTER			0x2200
-#define PRESET_SHUTTER_FORMATTER		0x2300
-#define PRESET_CONTOUR_FORMATTER		0x2400
-#define AUTO_CONTOUR_FORMATTER			0x2500
-#define BACK_LIGHT_COMPENSATION_FORMATTER	0x2600
-#define CONTRAST_FORMATTER			0x2700
-#define DYNAMIC_NOISE_CONTROL_FORMATTER		0x2800
-#define FLICKERLESS_MODE_FORMATTER		0x2900
-#define AE_CONTROL_SPEED			0x2A00
-#define BRIGHTNESS_FORMATTER			0x2B00
-#define GAMMA_FORMATTER				0x2C00
-
-/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
-#define WB_MODE_FORMATTER			0x1000
-#define AWB_CONTROL_SPEED_FORMATTER		0x1100
-#define AWB_CONTROL_DELAY_FORMATTER		0x1200
-#define PRESET_MANUAL_RED_GAIN_FORMATTER	0x1300
-#define PRESET_MANUAL_BLUE_GAIN_FORMATTER	0x1400
-#define COLOUR_MODE_FORMATTER			0x1500
-#define SATURATION_MODE_FORMATTER1		0x1600
-#define SATURATION_MODE_FORMATTER2		0x1700
-
-/* Selectors for the Status controls [GS]ET_STATUS_CTL */
-#define SAVE_USER_DEFAULTS_FORMATTER		0x0200
-#define RESTORE_USER_DEFAULTS_FORMATTER		0x0300
-#define RESTORE_FACTORY_DEFAULTS_FORMATTER	0x0400
-#define READ_AGC_FORMATTER			0x0500
-#define READ_SHUTTER_FORMATTER			0x0600
-#define READ_RED_GAIN_FORMATTER			0x0700
-#define READ_BLUE_GAIN_FORMATTER		0x0800
-#define READ_RAW_Y_MEAN_FORMATTER		0x3100
-#define SET_POWER_SAVE_MODE_FORMATTER		0x3200
-#define MIRROR_IMAGE_FORMATTER			0x3300
-#define LED_FORMATTER				0x3400
-
-/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
-#define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
-
-static char *size2name[PSZ_MAX] =
-{
-	"subQCIF",
-	"QSIF",
-	"QCIF",
-	"SIF",
-	"CIF",
-	"VGA",
-};  
-
-/********/
-
-/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
-   preferences, so you either get compressed or non-compressed streams.
-   
-   An alternate value of 0 means this mode is not available at all.
- */
-
-struct Nala_table_entry {
-	char alternate;			/* USB alternate setting */
-	int compressed;			/* Compressed yes/no */
-
-	unsigned char mode[3];		/* precomputed mode table */
-};
-
-static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
-{
-#include "pwc_nala.h"
-};
-
-/* This tables contains entries for the 675/680/690 (Timon) camera, with
-   4 different qualities (no compression, low, medium, high).
-   It lists the bandwidth requirements for said mode by its alternate interface 
-   number. An alternate of 0 means that the mode is unavailable.
-   
-   There are 6 * 4 * 4 entries: 
-     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
-     6 framerates: 5, 10, 15, 20, 25, 30
-     4 compression modi: none, low, medium, high
-     
-   When an uncompressed mode is not available, the next available compressed mode 
-   will be choosen (unless the decompressor is absent). Sometimes there are only
-   1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-struct Timon_table_entry 
-{
-	char alternate;			/* USB alternate interface */
-	unsigned short packetsize;	/* Normal packet size */
-	unsigned short bandlength;	/* Bandlength when decompressing */
-	unsigned char mode[13];		/* precomputed mode settings for cam */
-};
-
-static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = 
-{
-#include "pwc_timon.h"
-};
-
-/* Entries for the Kiara (730/740/750) camera */
-
-struct Kiara_table_entry
-{
-	char alternate;			/* USB alternate interface */
-	unsigned short packetsize;	/* Normal packet size */
-	unsigned short bandlength;	/* Bandlength when decompressing */
-	unsigned char mode[12];		/* precomputed mode settings for cam */
-};
-
-static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
-{
-#include "pwc_kiara.h"
-};
-
-
-/****************************************************************************/
-
-
-
-
-#if PWC_DEBUG
-void pwc_hexdump(void *p, int len)
-{
-	int i;
-	unsigned char *s;
-	char buf[100], *d;
-	
-	s = (unsigned char *)p;
-	d = buf;
-	*d = '\0';
-	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
-	for (i = 0; i < len; i++) {
-		d += sprintf(d, "%02X ", *s++);
-		if ((i & 0xF) == 0xF) {
-			Debug("%s\n", buf);
-			d = buf;
-			*d = '\0';
-		}
-	}
-	if ((i & 0xF) != 0)
-		Debug("%s\n", buf);
-}
-#endif
-
-static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
-{
-	return usb_control_msg(udev,
-		usb_sndctrlpipe(udev, 0),
-		SET_EP_STREAM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		VIDEO_OUTPUT_CONTROL_FORMATTER,
-		index,
-		buf, buflen, HZ);
-}
-
-
-
-static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
-{
-	unsigned char buf[3];
-	int ret, fps;
-	struct Nala_table_entry *pEntry;
-	int frames2frames[31] = 
-	{ /* closest match of framerate */
-	   0,  0,  0,  0,  4,  /*  0-4  */
-	   5,  5,  7,  7, 10,  /*  5-9  */
-          10, 10, 12, 12, 15,  /* 10-14 */
-          15, 15, 15, 20, 20,  /* 15-19 */
-          20, 20, 20, 24, 24,  /* 20-24 */
-          24, 24, 24, 24, 24,  /* 25-29 */
-          24                   /* 30    */
-	};
-	int frames2table[31] = 
-	{ 0, 0, 0, 0, 0, /*  0-4  */
-	  1, 1, 1, 2, 2, /*  5-9  */
-	  3, 3, 4, 4, 4, /* 10-14 */
-	  5, 5, 5, 5, 5, /* 15-19 */
-	  6, 6, 6, 6, 7, /* 20-24 */
-	  7, 7, 7, 7, 7, /* 25-29 */
-	  7              /* 30    */
-	};
-	
-	if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
-		return -EINVAL;
-	frames = frames2frames[frames];
-	fps = frames2table[frames];
-	pEntry = &Nala_table[size][fps];
-	if (pEntry->alternate == 0)
-		return -EINVAL;
-
-	if (pEntry->compressed && pdev->decompressor == NULL)
-		return -ENOENT; /* Not supported. */
-
-	memcpy(buf, pEntry->mode, 3);	
-	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
-	if (ret < 0)
-		return ret;
-	if (pEntry->compressed)
-		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
-		
-	/* Set various parameters */
-	pdev->vframes = frames;
-	pdev->vsize = size;
-	pdev->valternate = pEntry->alternate;
-	pdev->image = pwc_image_sizes[size];
-	pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
-	if (pEntry->compressed) {
-		if (pdev->release < 5) { /* 4 fold compression */
-			pdev->vbandlength = 528;
-			pdev->frame_size /= 4;
-		}
-		else {
-			pdev->vbandlength = 704;
-			pdev->frame_size /= 3;
-		}
-	}
-	else
-		pdev->vbandlength = 0;
-	return 0;
-}
-
-
-static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
-{
-	unsigned char buf[13];
-	struct Timon_table_entry *pChoose;
-	int ret, fps;
-
-	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
-		return -EINVAL;
-	if (size == PSZ_VGA && frames > 15)
-		return -EINVAL;
-	fps = (frames / 5) - 1;
-	
-	/* Find a supported framerate with progressively higher compression ratios
-	   if the preferred ratio is not available.
-	*/
-	pChoose = NULL;
-	if (pdev->decompressor == NULL) {
-#if PWC_DEBUG	
-		Debug("Trying to find uncompressed mode.\n");
-#endif
-		pChoose = &Timon_table[size][fps][0];
-	}
-	else {
-		while (compression <= 3) {
-			pChoose = &Timon_table[size][fps][compression];
-			if (pChoose->alternate != 0)
-				break;
-			compression++;	
-		}
-	}
-	if (pChoose == NULL || pChoose->alternate == 0)
-		return -ENOENT; /* Not supported. */
-
-	memcpy(buf, pChoose->mode, 13);
-	if (snapshot)
-		buf[0] |= 0x80;
-	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
-	if (ret < 0)
-		return ret;
-
-	if (pChoose->bandlength > 0)
-		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
-	
-	/* Set various parameters */
-	pdev->vframes = frames;
-	pdev->vsize = size;
-	pdev->vsnapshot = snapshot;
-	pdev->valternate = pChoose->alternate;
-	pdev->image = pwc_image_sizes[size];
-	pdev->vbandlength = pChoose->bandlength;
-	if (pChoose->bandlength > 0) 
-		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
-	else
-		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
-	return 0;
-}
-
-
-static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
-{
-	struct Kiara_table_entry *pChoose;
-	int fps, ret;
-	unsigned char buf[12];
-	
-	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
-		return -EINVAL;
-	if (size == PSZ_VGA && frames > 15)
-		return -EINVAL;
-	fps = (frames / 5) - 1;
-	
-	/* Find a supported framerate with progressively higher compression ratios
-	   if the preferred ratio is not available.
-	*/
-	pChoose = NULL;
-	if (pdev->decompressor == NULL) {
-#if PWC_DEBUG	
-		Debug("Trying to find uncompressed mode.\n");
-#endif		
-		pChoose = &Kiara_table[size][fps][0];
-	}
-	else {
-		while (compression <= 3) {
-			pChoose = &Kiara_table[size][fps][compression];
-			if (pChoose->alternate != 0)
-				break;
-			compression++;	
-		}
-	}
-	if (pChoose == NULL || pChoose->alternate == 0)
-		return -ENOENT; /* Not supported. */
-
-	/* usb_control_msg won't take staticly allocated arrays as argument?? */
-	memcpy(buf, pChoose->mode, 12);
-	if (snapshot)
-		buf[0] |= 0x80;
-
-	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
-	ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
-	if (ret < 0)
-		return ret;
-
-	if (pChoose->bandlength > 0)
-		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
-		
-	/* All set and go */
-	pdev->vframes = frames;
-	pdev->vsize = size;
-	pdev->vsnapshot = snapshot;
-	pdev->valternate = pChoose->alternate;
-	pdev->image = pwc_image_sizes[size];
-	pdev->vbandlength = pChoose->bandlength;
-	if (pChoose->bandlength > 0)
-		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
-	else 
-		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
-	pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size);
-	return 0;
-}
-
-
-/**
-   @pdev: device structure
-   @width: viewport width
-   @height: viewport height
-   @frame: framerate, in fps
-   @compression: preferred compression ratio
-   @snapshot: snapshot mode or streaming
- */
-int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
-{
-	int ret, size;
-	
-	size = pwc_decode_size(pdev, width, height);
-	if (size < 0) {
-		Debug("Could not find suitable size.\n");
-		return -ERANGE;
-	}
-	ret = -EINVAL;	
-	switch(pdev->type) {
-	case 645:
-	case 646:
-		ret = set_video_mode_Nala(pdev, size, frames);
-		break;
-
-	case 675:
-	case 680:
-	case 690:
-		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
-		break;
-		
-	case 730:
-	case 740:
-	case 750:
-		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
-		break;
-	}
-	if (ret < 0) {
-		if (ret == -ENOENT)
-			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
-		else {
-			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
-			return ret;
-		}
-	}
-	pdev->view.x = width;
-	pdev->view.y = height;
-	pwc_set_image_buffer_size(pdev);
-	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d, palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette);
-	return 0;
-}
-
-
-void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
-	int factor, i, filler = 0;
-
-	switch(pdev->vpalette) {
-	case VIDEO_PALETTE_RGB32 | 0x80:
-	case VIDEO_PALETTE_RGB32:
-		factor = 16;
-		filler = 0;
-		break;
-	case VIDEO_PALETTE_RGB24 | 0x80:
-	case VIDEO_PALETTE_RGB24:
-		factor = 12;
-		filler = 0;
-		break;
-	case VIDEO_PALETTE_YUYV:
-	case VIDEO_PALETTE_YUV422:
-		factor = 8;
-		filler = 128;
-		break;
-	case VIDEO_PALETTE_YUV420:
-	case VIDEO_PALETTE_YUV420P:
-		factor = 6;
-		filler = 128;
-		break;
-#if PWC_DEBUG		
-	case VIDEO_PALETTE_RAW:
-		pdev->image.size = pdev->frame_size;
-		pdev->view.size = pdev->frame_size;
-		return;
-		break;
-#endif	
-	default:
-		factor = 0;
-		break;
-	}
-
-	/* Set sizes in bytes */
-	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
-	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
-
-	/* Align offset, or you'll get some very weird results in
-	   YUV420 mode... x must be multiple of 4 (to get the Y's in 
-	   place), and y even (or you'll mixup U & V). This is less of a
-	   problem for YUV420P.
-	 */
-	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
-	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-	
-	/* Fill buffers with gray or black */
-	for (i = 0; i < MAX_IMAGES; i++) {
-		if (pdev->image_ptr[i] != NULL)
-			memset(pdev->image_ptr[i], filler, pdev->view.size);
-	}
-}
-
-
-
-/* BRIGHTNESS */
-
-int pwc_get_brightness(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-		GET_LUM_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		BRIGHTNESS_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	if (ret < 0)
-		return ret;
-	return buf << 9;
-}
-
-int pwc_set_brightness(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	buf = (value >> 9) & 0x7f;
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_LUM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		BRIGHTNESS_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-/* CONTRAST */
-
-int pwc_get_contrast(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-		GET_LUM_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		CONTRAST_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	if (ret < 0)
-		return ret;
-	return buf << 10;
-}
-
-int pwc_set_contrast(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	buf = (value >> 10) & 0x3f;
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_LUM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		CONTRAST_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-/* GAMMA */
-
-int pwc_get_gamma(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-		GET_LUM_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		GAMMA_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	if (ret < 0)
-		return ret;
-	return buf << 11;
-}
-
-int pwc_set_gamma(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	buf = (value >> 11) & 0x1f;
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_LUM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		GAMMA_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-
-/* SATURATION */
-
-int pwc_get_saturation(struct pwc_device *pdev)
-{
-	char buf;
-	int ret;
-
-	if (pdev->type < 675)
-		return -1;
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-		GET_CHROM_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	if (ret < 0)
-		return ret;
-	return 32768 + buf * 327;
-}
-
-int pwc_set_saturation(struct pwc_device *pdev, int value)
-{
-	char buf;
-
-	if (pdev->type < 675)
-		return -EINVAL;
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	/* saturation ranges from -100 to +100 */
-	buf = (value - 32768) / 327;
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_CHROM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-/* AGC */
-
-static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
-{
-	char buf;
-	int ret;
-	
-	if (mode)
-		buf = 0x0; /* auto */
-	else
-		buf = 0xff; /* fixed */
-
-	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_LUM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		AGC_MODE_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	
-	if (!mode && ret >= 0) {
-		if (value < 0)
-			value = 0;
-		if (value > 0xffff)
-			value = 0xffff;
-		buf = (value >> 10) & 0x3F;
-		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-			SET_LUM_CTL,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			PRESET_AGC_FORMATTER,
-			pdev->vcinterface,
-			&buf, 1, HZ / 2);
-	}
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-		GET_LUM_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		AGC_MODE_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	if (ret < 0)
-		return ret;
-
-	if (buf != 0) { /* fixed */
-		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-			GET_LUM_CTL,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			PRESET_AGC_FORMATTER,
-			pdev->vcinterface,
-			&buf, 1, HZ / 2);
-		if (ret < 0)
-			return ret;
-		if (buf > 0x3F)
-			buf = 0x3F;
-		*value = (buf << 10);		
-	}
-	else { /* auto */
-		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-			GET_STATUS_CTL,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			READ_AGC_FORMATTER,
-			pdev->vcinterface,
-			&buf, 1, HZ / 2);
-		if (ret < 0)
-			return ret;
-		/* Gah... this value ranges from 0x00 ... 0x9F */
-		if (buf > 0x9F)
-			buf = 0x9F;
-		*value = -(48 + buf * 409);
-	}
-
-	return 0;
-}
-
-static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
-{
-	char buf[2];
-	int speed, ret;
-
-
-	if (mode)
-		buf[0] = 0x0;	/* auto */
-	else
-		buf[0] = 0xff; /* fixed */
-	
-	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_LUM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		SHUTTER_MODE_FORMATTER,
-		pdev->vcinterface,
-		buf, 1, HZ / 2);
-
-	if (!mode && ret >= 0) {
-		if (value < 0)
-			value = 0;
-		if (value > 0xffff)
-			value = 0xffff;
-		switch(pdev->type) {
-		case 675:
-		case 680:
-		case 690:
-			/* speed ranges from 0x0 to 0x290 (656) */
-			speed = (value / 100);
-			buf[1] = speed >> 8;
-			buf[0] = speed & 0xff;
-			break;
-		case 730:
-		case 740:
-		case 750:
-			/* speed seems to range from 0x0 to 0xff */
-			buf[1] = 0;
-			buf[0] = value >> 8;
-			break;
-		}
-
-		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-			SET_LUM_CTL,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			PRESET_SHUTTER_FORMATTER,
-			pdev->vcinterface,
-			&buf, 2, HZ / 2);
-	}
-	return ret;
-}	
-
-
-/* POWER */
-
-int pwc_camera_power(struct pwc_device *pdev, int power)
-{
-	char buf;
-
-	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
-		return 0;	/* Not supported by Nala or Timon < release 6 */
-
-	if (power)
-		buf = 0x00; /* active */
-	else
-		buf = 0xFF; /* power save */
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_STATUS_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		SET_POWER_SAVE_MODE_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-
-
-/* private calls */
-
-static inline int pwc_restore_user(struct pwc_device *pdev)
-{
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_STATUS_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		RESTORE_USER_DEFAULTS_FORMATTER,
-		pdev->vcinterface,
-		NULL, 0, HZ / 2);
-}
-
-static inline int pwc_save_user(struct pwc_device *pdev)
-{
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_STATUS_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		SAVE_USER_DEFAULTS_FORMATTER,
-		pdev->vcinterface,
-		NULL, 0, HZ / 2);
-}
-
-static inline int pwc_restore_factory(struct pwc_device *pdev)
-{
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_STATUS_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		RESTORE_FACTORY_DEFAULTS_FORMATTER,
-		pdev->vcinterface,
-		NULL, 0, HZ / 2);
-}
-
- /* ************************************************* */
- /* Patch by Alvarado: (not in the original version   */
-
- /*
-  * the camera recognizes modes from 0 to 4:
-  *
-  * 00: indoor (incandescant lighting)
-  * 01: outdoor (sunlight)
-  * 02: fluorescent lighting
-  * 03: manual
-  * 04: auto
-  */ 
-static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
-{
-	char buf;
-	int ret;
-	
-	if (mode < 0)
-	    mode = 0;
-	
-	if (mode > 4)
-	    mode = 4;
-	
-	buf = mode & 0x07; /* just the lowest three bits */
-	
-	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_CHROM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		WB_MODE_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-	
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static inline int pwc_get_awb(struct pwc_device *pdev)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-		GET_CHROM_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		WB_MODE_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-
-	if (ret < 0) 
-		return ret;
-	return buf;
-}
-
-static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
-{
-        unsigned char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-
-	/* only the msb are considered */
-	buf = value >> 8;
-
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_CHROM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		PRESET_MANUAL_RED_GAIN_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-static inline int pwc_get_red_gain(struct pwc_device *pdev)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- 	        GET_STATUS_CTL, 
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-	        PRESET_MANUAL_RED_GAIN_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-
-	if (ret < 0)
-	    return ret;
-	
-	return (buf << 8);
-}
-
-
-static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
-{
-	unsigned char buf;
-
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-
-	/* linear mapping of 0..0xffff to -0x80..0x7f */
-	buf = (value >> 8);
-
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_CHROM_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		PRESET_MANUAL_BLUE_GAIN_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-}
-
-static inline int pwc_get_blue_gain(struct pwc_device *pdev)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-   	        GET_STATUS_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		PRESET_MANUAL_BLUE_GAIN_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-
-	if (ret < 0)
-	    return ret;
-	
-	return (buf << 8);
-}
-
-/* The following two functions are different, since they only read the
-   internal red/blue gains, which may be different from the manual 
-   gains set or read above.
- */   
-static inline int pwc_read_red_gain(struct pwc_device *pdev)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
- 	        GET_STATUS_CTL, 
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-	        READ_RED_GAIN_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-
-	if (ret < 0)
-	    return ret;
-	
-	return (buf << 8);
-}
-
-static inline int pwc_read_blue_gain(struct pwc_device *pdev)
-{
-	unsigned char buf;
-	int ret;
-	
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-   	        GET_STATUS_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		READ_BLUE_GAIN_FORMATTER,
-		pdev->vcinterface,
-		&buf, 1, HZ / 2);
-
-	if (ret < 0)
-	    return ret;
-	
-	return (buf << 8);
-}
-
-int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
-{
-	unsigned char buf[2];
-
-	if (pdev->type < 730)
-		return 0;
-	on_value /= 100;
-	off_value /= 100;
-	if (on_value < 0)
-		on_value = 0;
-	if (on_value > 0xff)
-		on_value = 0xff;
-	if (off_value < 0)
-		off_value = 0;
-	if (off_value > 0xff)
-		off_value = 0xff;
-
-	buf[0] = on_value;
-	buf[1] = off_value;
-
-	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-		SET_STATUS_CTL,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		LED_FORMATTER,
-		pdev->vcinterface,
-		&buf, 2, HZ / 2);
-}
-
-int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
-{
-	unsigned char buf[2];
-	int ret;
-	
-	if (pdev->type < 730) {
-		*on_value = -1;
-		*off_value = -1;
-		return 0;
-	}
-
-	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-   	        GET_STATUS_CTL,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		LED_FORMATTER,
-		pdev->vcinterface,
-		&buf, 2, HZ / 2);
-
-	if (ret < 0)
-		return ret;
-	*on_value = buf[0] * 100;
-	*off_value = buf[1] * 100;
-	return 0;
-}
-
- /* End of Add-Ons                                    */
- /* ************************************************* */
-
-int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
-{
-	switch(cmd) {
-	case VIDIOCPWCRUSER:
-	{
-		if (pwc_restore_user(pdev))
-			return -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCSUSER:
-	{
-		if (pwc_save_user(pdev))
-			return -EINVAL;
-		break;
-	}
-		
-	case VIDIOCPWCFACTORY:
-	{
-		if (pwc_restore_factory(pdev))
-			return -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCSCQUAL:
-	{	
-		int *qual = arg;
-		int ret;
-
-		if (*qual < 0 || *qual > 3)
-			return -EINVAL;
-		ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
-		if (ret < 0)
-			return ret;
-		pdev->vcompression = *qual;
-		break;
-	}
-	
-	case VIDIOCPWCGCQUAL:
-	{
-		int *qual = arg;
-
-		*qual = pdev->vcompression;
-		break;
-	}
-
-	case VIDIOCPWCSAGC:
-	{
-		int *agc = arg;
-		
-		if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
-			return -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCGAGC:
-	{
-		int *agc = arg;
-		
-		if (pwc_get_agc(pdev, agc))
-			return -EINVAL;
-		break;
-	}
-	
-	case VIDIOCPWCSSHUTTER:
-	{
-		int *shutter_speed = arg;
-		int ret;
-
-		ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
-		if (ret < 0)
-			return ret;
-		break;
-	}
-	
-
- /* ************************************************* */
- /* Begin of Add-Ons for color compensation           */
-
-        case VIDIOCPWCSAWB:
-	{
-		struct pwc_whitebalance *wb = arg;
-		int ret;
-		
-		ret = pwc_set_awb(pdev, wb->mode);
-		if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
-			pwc_set_red_gain(pdev, wb->manual_red);
-			pwc_set_blue_gain(pdev, wb->manual_blue);
-		}
-		break;
-	}
-
-	case VIDIOCPWCGAWB:
-	{
-		struct pwc_whitebalance *wb = arg;
-		
-		memset(wb, 0, sizeof(*wb));
-		wb->mode = pwc_get_awb(pdev);
-		if (wb->mode < 0)
-			return -EINVAL;
-		wb->manual_red = pwc_get_red_gain(pdev);
-		wb->manual_blue = pwc_get_blue_gain(pdev);
-		if (wb->mode == PWC_WB_AUTO) {
-			wb->read_red = pwc_read_red_gain(pdev);
-			wb->read_blue = pwc_read_blue_gain(pdev);
-		}
-		break;
-	}
-
-        case VIDIOCPWCSLED:
-	{
-		int ret;
-		struct pwc_leds *leds = arg;
-
-		ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
-		if (ret<0)
-		    return ret;
-	    break;
-	}
-
-
-
-	case VIDIOCPWCGLED:
-	{
-		int led;
-		struct pwc_leds *leds = arg;
-		
-		led = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); 
-		if (led < 0)
-			return -EINVAL;
-		break;
-	}
-
- /* End of Add-Ons                                    */
- /* ************************************************* */
-
-	default:
-		return -ENOIOCTLCMD;
-		break;
-	}
-	return 0;
-}
-
-
-
diff -Nru a/drivers/usb/pwc-if.c b/drivers/usb/pwc-if.c
--- a/drivers/usb/pwc-if.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2013 +0,0 @@
-/* Linux driver for Philips webcam 
-   USB and Video4Linux interface part.
-   (C) 1999-2001 Nemosoft Unv.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-*/
-
-/*  
-   This code forms the interface between the USB layers and the Philips
-   specific stuff. Some adanved stuff of the driver falls under an
-   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
-   is thus not distributed in source form. The binary pwcx.o module 
-   contains the code that falls under the NDA.
-   
-   In case you're wondering: 'pwc' stands for "Philips WebCam", but 
-   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
-   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
-   without explanation).
-   
-   Oh yes, convention: to disctinguish between all the various pointers to
-   device-structures, I use these names for the pointer variables:
-   udev: struct usb_device *
-   vdev: struct video_device *
-   pdev: struct pwc_devive *
-*/
-
-/* Contributors:
-   - Alvarado: adding whitebalance code
-   - Alistar Moire: QuickCam 3000 Pro device/product ID
-   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
-   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
-   - Jk Fang: SOTEC device/product ID
-*/
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/wrapper.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-
-#include "pwc.h"
-#include "pwc-ioctl.h"
-#include "pwc-uncompress.h"
-
-#if !defined(MAP_NR)
-#define MAP_NR(a) virt_to_page(a)
-#endif
-
-/* Function prototypes and driver templates */
-
-/* hotplug device table support */
-static __devinitdata struct usb_device_id pwc_device_table [] = {
-	{ USB_DEVICE(0x0471, 0x0302) },
-	{ USB_DEVICE(0x0471, 0x0303) },
-	{ USB_DEVICE(0x0471, 0x0304) },
-	{ USB_DEVICE(0x0471, 0x0307) },
-	{ USB_DEVICE(0x0471, 0x0308) },
-	{ USB_DEVICE(0x0471, 0x030C) },
-	{ USB_DEVICE(0x0471, 0x0310) },
-	{ USB_DEVICE(0x0471, 0x0311) },
-	{ USB_DEVICE(0x0471, 0x0312) },
-	{ USB_DEVICE(0x069A, 0x0001) },
-	{ USB_DEVICE(0x046D, 0x08b0) },
-	{ USB_DEVICE(0x055D, 0x9000) },
-	{ USB_DEVICE(0x055D, 0x9001) },
-	{ USB_DEVICE(0x041E, 0x400C) },
-	{ USB_DEVICE(0x04CC, 0x8116) },
-	{ }
-};
-MODULE_DEVICE_TABLE(usb, pwc_device_table);
-
-static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id);
-static void usb_pwc_disconnect(struct usb_device *udev, void *ptr);
-
-static struct usb_driver pwc_driver =
-{
-	name:			"Philips webcam",	/* name */
-	id_table:		pwc_device_table,
-	probe:			usb_pwc_probe,		/* probe() */
-	disconnect:		usb_pwc_disconnect,	/* disconnect() */
-};
-
-#define MAX_DEV_HINTS 10
-
-static int default_size = PSZ_QCIF;
-static int default_fps = 10;
-static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */
-static int default_fbufs = 3;   /* Default number of frame buffers */
-static int default_mbufs = 2;	/* Default number of mmap() buffers */
-       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
-static int power_save = 0;
-static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
-       int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
-static struct {
-	int type;
-	char serial_number[30];
-	int device_node;
-	struct pwc_device *pdev;
-} device_hint[MAX_DEV_HINTS];
-
-static struct semaphore mem_lock;
-static void *mem_leak = NULL; /* For delayed kfree()s. See below */
-
-/***/
-
-static int pwc_video_open(struct inode *inode, struct file *file);
-static int pwc_video_close(struct inode *inode, struct file *file);
-static int pwc_video_read(struct file *file, char *buf,
-			  size_t count, loff_t *ppos);
-static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
-static int  pwc_video_ioctl(struct inode *inode, struct file *file,
-			    unsigned int ioctlnr, void *arg);
-static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
-
-static struct file_operations pwc_fops = {
-	owner:		THIS_MODULE,
-	open:		pwc_video_open,
-	release:       	pwc_video_close,
-	read:		pwc_video_read,
-	poll:		pwc_video_poll,
-	mmap:		pwc_video_mmap,
-	ioctl:          video_generic_ioctl,
-	llseek:         no_llseek,
-};
-static struct video_device pwc_template = {
-	owner:		THIS_MODULE,
-	name:		"Philips Webcam",	/* Filled in later */
-	type:		VID_TYPE_CAPTURE,
-	hardware:	VID_HARDWARE_PWC,
-	fops:           &pwc_fops,
-	kernel_ioctl:	pwc_video_ioctl,
-};
-
-/***************************************************************************/
-
-/* Okay, this is some magic that I worked out and the reasoning behind it...
-
-   The biggest problem with any USB device is of course: "what to do 
-   when the user unplugs the device while it is in use by an application?"
-   We have several options:
-   1) Curse them with the 7 plagues when they do (requires divine intervention)
-   2) Tell them not to (won't work: they'll do it anyway)
-   3) Oops the kernel (this will have a negative effect on a user's uptime)
-   4) Do something sensible.
-   
-   Of course, we go for option 4.
-
-   It happens that this device will be linked to two times, once from
-   usb_device and once from the video_device in their respective 'private'
-   pointers. This is done when the device is probed() and all initialization
-   succeeded. The pwc_device struct links back to both structures.
-
-   When a device is unplugged while in use it will be removed from the 
-   list of known USB devices; I also de-register as a V4L device, but 
-   unfortunately I can't free the memory since the struct is still in use
-   by the file descriptor. This free-ing is then deferend until the first
-   opportunity. Crude, but it works.
-   
-   A small 'advantage' is that if a user unplugs the cam and plugs it back
-   in, it should get assigned the same video device minor, but unfortunately
-   it's non-trivial to re-link the cam back to the video device... (that 
-   would surely be magic! :))
-*/
-
-/***************************************************************************/
-/* Private functions */
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
-{
-        unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-        return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
-        mem=vmalloc_32(size);
-	if (mem) 
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	        adr=(unsigned long) mem;
-		while (size > 0) 
-                {
-			mem_map_reserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-        unsigned long adr;
-
-	if (mem) 
-	{
-	        adr=(unsigned long) mem;
-		while ((long) size > 0) 
-                {
-			mem_map_unreserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-
-
-
-
-static int pwc_allocate_buffers(struct pwc_device *pdev)
-{
-	int i;
-	void *kbuf;
-
-	Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev);
-
-	if (pdev == NULL)
-		return -ENXIO;
-		
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("allocate_buffers(): magic failed.\n");
-		return -ENXIO;
-	}
-#endif	
-	/* Allocate Isochronuous pipe buffers */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		if (pdev->sbuf[i].data == NULL) {
-			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
-			if (kbuf == NULL) {
-				Err("Failed to allocate iso buffer %d.\n", i);
-				return -ENOMEM;
-			}
-			Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
-			pdev->sbuf[i].data = kbuf;
-			memset(kbuf, 0, ISO_BUFFER_SIZE);
-		}
-	}
-
-	/* Allocate frame buffer structure */
-	if (pdev->fbuf == NULL) {
-		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
-		if (kbuf == NULL) {
-			Err("Failed to allocate frame buffer structure.\n");
-			return -ENOMEM;
-		}
-		Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
-		pdev->fbuf = kbuf;
-		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
-	}
-	/* create frame buffers, and make circular ring */
-	for (i = 0; i < default_fbufs; i++) {
-		if (pdev->fbuf[i].data == NULL) {
-			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
-			if (kbuf == NULL) {
-				Err("Failed to allocate frame buffer %d.\n", i);
-				return -ENOMEM;
-			}
-			Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
-			pdev->fbuf[i].data = kbuf;
-			memset(kbuf, 128, PWC_FRAME_SIZE);
-		}
-	}
-	
-	/* Allocate decompressor table space */
-	kbuf = NULL;
-	if (pdev->decompressor != NULL) {
-		kbuf = kmalloc(pdev->decompressor->table_size, GFP_KERNEL);
-		if (kbuf == NULL) {
-			Err("Failed to allocate decompress table.\n");
-			return -ENOMEM;
-		}
-		Trace(TRACE_MEMORY, "Allocated decompress table %p.\n", kbuf);
-	}
-	pdev->decompress_data = kbuf;
-	
-	/* Allocate image buffer; double buffer for mmap() */
-	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
-	if (kbuf == NULL) {
-		Err("Failed to allocate image buffer(s).\n");
-		return -ENOMEM;
-	}
-	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
-	pdev->image_data = kbuf;
-	for (i = 0; i < default_mbufs; i++)
-		pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
-	for (; i < MAX_IMAGES; i++)
-		pdev->image_ptr[i] = NULL;
-
-	Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
-	return 0;
-}
-
-static void pwc_free_buffers(struct pwc_device *pdev)
-{
-	int i;
-
-	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
-
-	if (pdev == NULL)
-		return;
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("free_buffers(): magic failed.\n");
-		return;
-	}
-#endif	
-
-	/* Release Iso-pipe buffers */
-	for (i = 0; i < MAX_ISO_BUFS; i++)
-		if (pdev->sbuf[i].data != NULL) {
-			Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
-			kfree(pdev->sbuf[i].data);
-			pdev->sbuf[i].data = NULL;
-		}
-
-	/* The same for frame buffers */
-	if (pdev->fbuf != NULL) {
-		for (i = 0; i < default_fbufs; i++) {
-			if (pdev->fbuf[i].data != NULL) {
-				Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
-				vfree(pdev->fbuf[i].data);
-				pdev->fbuf[i].data = NULL;
-			}
-		}
-		kfree(pdev->fbuf);
-		pdev->fbuf = NULL;
-	}
-
-	/* Intermediate decompression buffer & tables */
-	if (pdev->decompress_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
-		kfree(pdev->decompress_data);
-		pdev->decompress_data = NULL;
-	}
-	pdev->decompressor = NULL;
-
-	/* Release image buffers */
-	if (pdev->image_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
-		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
-	}
-	pdev->image_data = NULL;
-	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
-}
-
-/* The frame & image buffer mess. 
-
-   Yes, this is a mess. Well, it used to be simple, but alas...  In this
-   module, 3 buffers schemes are used to get the data from the USB bus to
-   the user program. The first scheme involves the ISO buffers (called thus
-   since they transport ISO data from the USB controller), and not really
-   interesting. Suffices to say the data from this buffer is quickly 
-   gathered in an interrupt handler (pwc_isoc_handler) and placed into the 
-   frame buffer.
-   
-   The frame buffer is the second scheme, and is the central element here.
-   It collects the data from a single frame from the camera (hence, the
-   name). Frames are delimited by the USB camera with a short USB packet,
-   so that's easy to detect. The frame buffers form a list that is filled
-   by the camera+USB controller and drained by the user process through 
-   either read() or mmap().
-   
-   The image buffer is the third scheme, in which frames are decompressed
-   and possibly converted into planar format. For mmap() there is more than
-   one image buffer available.
-
-   The frame buffers provide the image buffering, in case the user process
-   is a bit slow. This introduces lag and some undesired side-effects.
-   The problem arises when the frame buffer is full. I used to drop the last 
-   frame, which makes the data in the queue stale very quickly. But dropping 
-   the frame at the head of the queue proved to be a litte bit more difficult.
-   I tried a circular linked scheme, but this introduced more problems than
-   it solved.
-
-   Because filling and draining are completely asynchronous processes, this
-   requires some fiddling with pointers and mutexes.
-   
-   Eventually, I came up with a system with 2 lists: an 'empty' frame list
-   and a 'full' frame list:
-     * Initially, all frame buffers but one are on the 'empty' list; the one
-       remaining buffer is our initial fill frame.
-     * If a frame is needed for filling, we take it from the 'empty' list, 
-       unless that list is empty, in which case we take the buffer at the 
-       head of the 'full' list.
-     * When our fill buffer has been filled, it is appended to the 'full' 
-       list.
-     * If a frame is needed by read() or mmap(), it is taken from the head of 
-       the 'full' list, handled, and then appended to the 'empty' list. If no
-       buffer is present on the 'full' list, we wait.
-   The advantage is that the buffer that is currently being decompressed/
-   converted, is on neither list, and thus not in our way (any other scheme 
-   I tried had the problem of old data lingering in the queue).
-
-   Whatever strategy you choose, it always remains a tradeoff: with more
-   frame buffers the chances of a missed frame are reduced. On the other
-   hand, on slower machines it introduces lag because the queue will 
-   always be full.
- */
-
-/**
-  \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
- */
-static inline int pwc_next_fill_frame(struct pwc_device *pdev)
-{
-	int ret;
-	unsigned long flags;
-	
-	ret = 0;
-	spin_lock_irqsave(&pdev->ptrlock, flags);
-	if (pdev->fill_frame != NULL) {
-		/* append to 'full' list */
-		if (pdev->full_frames == NULL) {
-			pdev->full_frames = pdev->fill_frame;
-			pdev->full_frames_tail = pdev->full_frames;
-		}
-		else {
-			pdev->full_frames_tail->next = pdev->fill_frame;
-			pdev->full_frames_tail = pdev->fill_frame;
-		}
-	}
-	if (pdev->empty_frames != NULL) {
-		/* We have empty frames available. That's easy */
-		pdev->fill_frame = pdev->empty_frames;
-		pdev->empty_frames = pdev->empty_frames->next;	
-	}
-	else {
-		/* Hmm. Take it from the full list */
-#if PWC_DEBUG		
-		/* sanity check */
-		if (pdev->full_frames == NULL) {
-			Err("Neither empty or full frames available!\n");
-			spin_unlock_irqrestore(&pdev->ptrlock, flags);
-			return -EINVAL;
-		}
-#endif
-		pdev->fill_frame = pdev->full_frames;
-		pdev->full_frames = pdev->full_frames->next;
-		ret = 1;
-	}
-	pdev->fill_frame->next = NULL;
-#if PWC_DEBUG
-	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
-	pdev->fill_frame->sequence = pdev->sequence++;
-#endif
-	spin_unlock_irqrestore(&pdev->ptrlock, flags);
-	return ret;
-}
- 
-
-/**
-  \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. 
-  
-  If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
- */
-static void pwc_reset_buffers(struct pwc_device *pdev)
-{
-	int i;
-	unsigned long flags;
-
-	spin_lock_irqsave(&pdev->ptrlock, flags);
-	pdev->full_frames = NULL;
-	pdev->full_frames_tail = NULL;
-	for (i = 0; i < default_fbufs; i++) {
-		pdev->fbuf[i].filled = 0;
-		if (i > 0)
-			pdev->fbuf[i].next = &pdev->fbuf[i - 1];
-		else
-			pdev->fbuf->next = NULL;
-	}
-	pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
-	pdev->empty_frames_tail = pdev->fbuf;
-	pdev->read_frame = NULL;
-	pdev->fill_frame = pdev->empty_frames;
-	pdev->empty_frames = pdev->empty_frames->next;
-
-	pdev->image_read_pos = 0;
-	pdev->fill_image = 0;
-	spin_unlock_irqrestore(&pdev->ptrlock, flags);
-}
-
-
-/**
-  \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
- */
-static int pwc_handle_frame(struct pwc_device *pdev)
-{
-	int ret = 0;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&pdev->ptrlock, flags);
-	/* First grab our read_frame; this is removed from all lists, so
-	   we can release the lock after this without problems */
-	if (pdev->read_frame != NULL) {
-		/* This can't theoretically happen */
-		Err("Huh? Read frame still in use?\n");
-	}
-	else {
-		if (pdev->full_frames == NULL) {
-			Err("Woops. No frames ready.\n");
-		}
-		else {
-			pdev->read_frame = pdev->full_frames;
-			pdev->full_frames = pdev->full_frames->next;
-			pdev->read_frame->next = NULL;
-		}
-
-		if (pdev->read_frame != NULL) {
-#if PWC_DEBUG
-			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
-#endif
-			/* Decompression is a lenghty process, so it's outside of the lock.
-			   This gives the isoc_handler the opportunity to fill more frames 
-			   in the mean time.
-			*/
-			spin_unlock_irqrestore(&pdev->ptrlock, flags);
-			ret = pwc_decompress(pdev);
-			spin_lock_irqsave(&pdev->ptrlock, flags);
-
-			/* We're done with read_buffer, tack it to the end of the empty buffer list */
-			if (pdev->empty_frames == NULL) {
-				pdev->empty_frames = pdev->read_frame;
-				pdev->empty_frames_tail = pdev->empty_frames;
-			}
-			else {
-				pdev->empty_frames_tail->next = pdev->read_frame;
-				pdev->empty_frames_tail = pdev->read_frame;
-			}
-			pdev->read_frame = NULL;
-		}
-	}
-	spin_unlock_irqrestore(&pdev->ptrlock, flags);
-	return ret;
-}
-
-/**
-  \brief Advance pointers of image buffer (after each user request) 
-*/
-static inline void pwc_next_image(struct pwc_device *pdev)
-{
-	pdev->image_used[pdev->fill_image] = 0;
-	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
-}
-
-/* 2001-10-14: The YUV420 is still there, but you can only set it from within 
-   a program (YUV420P being the default) */
-static int pwc_set_palette(struct pwc_device *pdev, int pal)
-{
-	if (   pal == VIDEO_PALETTE_YUV420
-            || pal == VIDEO_PALETTE_YUV420P
-#if PWC_DEBUG
-            || pal == VIDEO_PALETTE_RAW
-#endif
-	) {
-		pdev->vpalette = pal;
-		pwc_set_image_buffer_size(pdev);
-		return 0;
-	}
-	Trace(TRACE_READ, "Palette %d not supported.\n", pal);
-	return -1;
-}
-
-
-
-/* This gets called for the Isochronous pipe (video). This is done in
- * interrupt time, so it has to be fast, not crash, and not stall. Neat.
- */
-static void pwc_isoc_handler(struct urb *urb)
-{
-	struct pwc_device *pdev;
-	int i, fst, flen;
-	int awake;
-	struct pwc_frame_buf *fbuf;
-	unsigned char *fillptr, *iso_buf;
-
-	pdev = (struct pwc_device *)urb->context;
-	if (pdev == NULL) {
-		Err("isoc_handler() called with NULL device?!\n");
-		return;
-	}
-#ifdef PWC_MAGIC	
-	if (pdev->magic != PWC_MAGIC) {
-		Err("isoc_handler() called with bad magic!\n");
-		return;
-	}
-#endif
-	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n");
-		return;
-	}
-	if (urb->status != -EINPROGRESS && urb->status != 0) {
-		char *errmsg;
-		
-		errmsg = "Unknown";
-		switch(urb->status) {
-			case -ENOSR:		errmsg = "Buffer error (overrun)"; break;
-			case -EPIPE:		errmsg = "Stalled (device not responding)"; break;
-			case -EOVERFLOW:	errmsg = "Babble (bad cable?)"; break;
-			case -EPROTO:		errmsg = "Bit-stuff error (bad cable?)"; break;
-			case -EILSEQ:		errmsg = "CRC/Timeout"; break;
-			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
-		}
-		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
-		return;
-	}
-
-	fbuf = pdev->fill_frame;
-	if (fbuf == NULL) {
-		Err("pwc_isoc_handler without valid fill frame.\n");
-		wake_up_interruptible(&pdev->frameq);
-		return;
-	}
-	fillptr = fbuf->data + fbuf->filled;
-	awake = 0;
-
-	/* vsync: 0 = don't copy data
-	          1 = sync-hunt
-	          2 = synched 
-	 */
-	/* Compact data */
-	for (i = 0; i < urb->number_of_packets; i++) {
-		fst  = urb->iso_frame_desc[i].status;
-		flen = urb->iso_frame_desc[i].actual_length;
-		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-		if (fst == 0) {
-			if (flen > 0) { /* if valid data... */
-				if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
-					pdev->vsync = 2;
-
-					/* ...copy data to frame buffer, if possible */
-					if (flen + fbuf->filled > pdev->frame_size) {
-						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_size = %d).\n", flen, pdev->frame_size);
-						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
-						pdev->vframes_error++;
-					}
-					else {
-						memmove(fillptr, iso_buf, flen);
-						fillptr += flen;
-					}
-				}
-				fbuf->filled += flen;
-			} /* ..flen > 0 */
-
-			if (flen < pdev->vlast_packet_size) {
-				/* Shorter packet... We probably have the end of an image-frame; 
-				   wake up read() process and let select()/poll() do something.
-				   Decompression is done in user time over there. 
-				 */
-				if (pdev->vsync == 2) {
-					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
-					   frames on the USB wire after an exposure change. This conditition is 
-					   however detected  in the cam and a bit is set in the header.
-					 */
-					if (pdev->type == 730) {
-						unsigned char *ptr = (unsigned char *)fbuf->data;
-						
-						if (ptr[1] == 1 && ptr[0] & 0x10) {
-#if PWC_DEBUG
-							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
-#endif
-							pdev->drop_frames = 2;
-							pdev->vframes_error++;
-						}
-						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
-						   after a short frame; this condition is filtered out specifically. A 4 byte
-						   frame doesn't make sense anyway.
-						   So we get either this sequence: 
-						   	drop_bit set -> 4 byte frame -> short frame -> good frame
-						   Or this one:
-						   	drop_bit set -> short frame -> good frame
-						   So we drop either 3 or 2 frames in all!
-						 */
-						if (fbuf->filled == 4)
-							pdev->drop_frames++;
-					}
-
-					/* In case we were instructed to drop the frame, do so silently.
-					   The buffer pointers are not updated either (but the counters are reset below).
-					 */
-					if (pdev->drop_frames)
-						pdev->drop_frames--;
-					else {
-						/* Check for underflow first */
-						if (fbuf->filled < pdev->frame_size) {
-							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
-							pdev->vframes_error++;
-						}
-						else {
-							/* Send only once per EOF */
-							awake = 1; /* delay wake_ups */
-							
-							/* Find our next frame to fill. This will always succeed, since we
-							 * nick a frame from either empty or full list, but if we had to
-							 * take it from the full list, it means a frame got dropped.
-							 */
-							if (pwc_next_fill_frame(pdev)) {
-								pdev->vframes_dumped++;
-								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
-									if (pdev->vframes_dumped < 20)
-										Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
-									if (pdev->vframes_dumped == 20)
-										Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
-								}
-							}
-							fbuf = pdev->fill_frame;
-						}
-					} /* !drop_frames */
-					pdev->vframe_count++;
-				}
-				fbuf->filled = 0;
-				fillptr = fbuf->data;
-				pdev->vsync = 1;
-			} /* .. flen < last_packet_size */
-			pdev->vlast_packet_size = flen;
-		} /* ..status == 0 */
-#ifdef PWC_DEBUG
-		/* This is normally not interesting to the user, unless you are really debugging something */
-		else 
-			Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
-#endif			
-	}
-	if (awake)
-		wake_up_interruptible(&pdev->frameq);
-}
-
-
-static int pwc_isoc_init(struct pwc_device *pdev)
-{
-	struct usb_device *udev;
-	struct urb *urb;
-	int i, j, ret;
-
-	struct usb_interface_descriptor *idesc;
-	int cur_alt;
-
-	if (pdev == NULL)
-		return -EFAULT;
-	if (pdev->iso_init)
-		return 0;
-	pdev->vsync = 0;
-	udev = pdev->udev;
-	
-	/* Get the current alternate interface, adjust packet size */
-	if (!udev->actconfig)
-		return -EFAULT;
-	cur_alt = udev->actconfig->interface[0].act_altsetting;
-	idesc = &udev->actconfig->interface[0].altsetting[cur_alt];
-	if (!idesc)
-		return -EFAULT;
-
-	/* Search video endpoint */
-	pdev->vmax_packet_size = -1;
-	for (i = 0; i < idesc->bNumEndpoints; i++)
-		if ((idesc->endpoint[i].bEndpointAddress & 0xF) == pdev->vendpoint) {
-			pdev->vmax_packet_size = idesc->endpoint[i].wMaxPacketSize;
-			break;
-		}
-	
-	if (pdev->vmax_packet_size < 0) {
-		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
-		return -ENFILE; /* Odd error, that should be noticable */
-	}
-
-	ret = 0;
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
-		if (urb == NULL) {
-			Err("Failed to allocate urb %d\n", i);
-			ret = -ENOMEM;
-			break;
-		}
-		pdev->sbuf[i].urb = urb;
-	}
-	if (ret) {
-		/* De-allocate in reverse order */
-		while (i >= 0) {
-			if (pdev->sbuf[i].urb != NULL)
-				usb_free_urb(pdev->sbuf[i].urb);
-			pdev->sbuf[i].urb = NULL;
-			i--;
-		}
-		return ret;
-	}
-	
-	
-	/* init URB structure */	
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		urb = pdev->sbuf[i].urb;
-
-		urb->next = pdev->sbuf[(i + 1) % MAX_ISO_BUFS].urb;
-		urb->dev = udev;
-	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
-		urb->transfer_flags = USB_ISO_ASAP;
-	        urb->transfer_buffer = pdev->sbuf[i].data;
-	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
-	        urb->complete = pwc_isoc_handler;
-	        urb->context = pdev;
-		urb->start_frame = 0;
-		urb->number_of_packets = ISO_FRAMES_PER_DESC;
-		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
-			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
-			urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
-		}
-	}
-
-	/* link */
-	for (i = 0; i < MAX_ISO_BUFS; i++) {
-		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
-		if (ret)
-			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
-		else
-			Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n");
-	}
-
-	/* data should stream in now */
-	pdev->iso_init = 1;
-	return 0;
-}
-
-static void pwc_isoc_cleanup(struct pwc_device *pdev)
-{
-	int i;
-	
-	if (pdev == NULL)
-		return;
-	if (!pdev->iso_init)
-		return;
-	/* Stop camera, but only if we are sure the camera is still there */
-	if (!pdev->unplugged)
-		usb_set_interface(pdev->udev, 0, 0);
-	/* Unlinking ISOC buffers one by one */
-	for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
-		pdev->sbuf[i].urb->next = NULL;
-		usb_unlink_urb(pdev->sbuf[i].urb);
-		usb_free_urb(pdev->sbuf[i].urb);
-		pdev->sbuf[i].urb = NULL;
-	}
-	pdev->iso_init = 0;
-}
-
-int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
-{
-	int ret;
-
-	/* Stop isoc stuff */
-	pwc_isoc_cleanup(pdev);
-	/* Reset parameters */
-	pwc_reset_buffers(pdev);
-	/* Try to set video mode... */
-	ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
-	if (ret) /* That failed... restore old mode (we know that worked) */
-		ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-	else /* Set (new) alternate interface */
-		ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
-	if (!ret)
-		ret = pwc_isoc_init(pdev);
-	pdev->drop_frames = 1; /* try to avoid garbage during switch */
-	return ret;
-}
-
-
-static inline void set_mem_leak(void *ptr)
-{
-	down(&mem_lock);
-	if (mem_leak != NULL)
-		Err("Memleak: overwriting mem_leak pointer!\n");
-	Trace(TRACE_MEMORY, "Setting mem_leak to 0x%p.\n", ptr);
-	mem_leak = ptr;
-	up(&mem_lock);
-}
-
-static inline void free_mem_leak(void)
-{
-	down(&mem_lock);
-	if (mem_leak != NULL) {
-		Trace(TRACE_MEMORY, "Freeing mem_leak ptr 0x%p.\n", mem_leak);
-		kfree(mem_leak);
-		mem_leak = NULL;
-	}
-	up(&mem_lock);
-}
-
-
-/***************************************************************************/
-/* Video4Linux functions */
-
-static int pwc_video_open(struct inode *inode, struct file *file)
-{
-	int i;
-	struct video_device *vdev = video_devdata(file);
-	struct pwc_device *pdev;
-
-	Trace(TRACE_OPEN, "video_open called(0x%p).\n", vdev);
-	
-	pdev = (struct pwc_device *)vdev->priv;
-	if (pdev == NULL)
-		BUG();
-	if (pdev->vopen)
-		return -EBUSY;
-	
-	down(&pdev->modlock);
-	if (!pdev->usb_init) {
-		Trace(TRACE_OPEN, "Doing first time initialization.\n");
-		/* Reset camera */
-		if (usb_set_interface(pdev->udev, 0, 0))
-			Info("Failed to set alternate interface to 0.\n");
-		pdev->usb_init = 1;
-	}
-
-	/* Turn on camera */
-	if (power_save) {
-		i = pwc_camera_power(pdev, 1);
-		if (i < 0)
-			Info("Failed to restore power to the camera! (%d)\n", i);
-	}
-	/* Set LED on/off time */
-	if (pwc_set_leds(pdev, led_on, led_off) < 0)
-		Info("Failed to set LED on/off time.\n");
-
-	/* Find our decompressor, if any */
-	pdev->decompressor = pwc_find_decompressor(pdev->type);
-#if PWC_DEBUG	
-	Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor);
-#endif
-
-	/* So far, so good. Allocate memory. */
-	i = pwc_allocate_buffers(pdev);
-	if (i < 0) {
-		Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
-		up(&pdev->modlock);
-		return i;
-	}
-	
-	/* Reset buffers & parameters */
-	pwc_reset_buffers(pdev);
-	for (i = 0; i < default_mbufs; i++)
-		pdev->image_used[i] = 0;
-	pdev->vframe_count = 0;
-	pdev->vframes_dumped = 0;
-	pdev->vframes_error = 0;
-	pdev->vpalette = default_palette;
-#if PWC_DEBUG	
-	pdev->sequence = 0;
-#endif
-
-	/* Set some defaults */
-	pdev->vsnapshot = 0;
-	if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
-		pdev->vsize = PSZ_QSIF;
-	else
-		pdev->vsize = PSZ_QCIF;
-	pdev->vframes = 10;
-
-	/* Start iso pipe for video; first try user-supplied size/fps, if
-	   that fails try QCIF/10 or QSIF/10 (a reasonable default), 
-	   then give up 
-	 */
-	i = pwc_set_video_mode(pdev, pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y, default_fps, pdev->vcompression, 0);
-	if (i)	{
-		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
-		if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
-		else
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
-	}
-	if (i) {
-		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
-		up(&pdev->modlock);
-		return i;
-	}
-	
-	i = usb_set_interface(pdev->udev, 0, pdev->valternate);
-	if (i) {
-		Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
-		up(&pdev->modlock);
-		return -EINVAL;
-	}
-	i = pwc_isoc_init(pdev);
-	if (i) {
-		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
-		MOD_DEC_USE_COUNT;
-		up(&pdev->modlock);
-		return i;
-	}
-
-	pdev->vopen++;
-	file->private_data = vdev;
-	/* lock decompressor; this has a small race condition, since we 
-	   could in theory unload pwcx.o between pwc_find_decompressor()
-	   above and this call. I doubt it's ever going to be a problem.
-	 */
-	if (pdev->decompressor != NULL)
-		pdev->decompressor->lock();
-	up(&pdev->modlock);
-	Trace(TRACE_OPEN, "video_open() returning 0.\n");
-	return 0;
-}
-
-/* Note that all cleanup is done in the reverse order as in _open */
-static int pwc_video_close(struct inode *inode, struct file *file)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	int i;
-
-	Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev);
-
-	pdev = (struct pwc_device *)vdev->priv;
-	if (pdev->vopen == 0)
-		Info("video_close() called on closed device?\n");
-
-	/* Free isoc URBs */
-	pwc_isoc_cleanup(pdev);
-
-	/* Dump statistics, but only if a reasonable amount of frames were
-	   processed (to prevent endless log-entries in case of snap-shot
-	   programs) 
-	 */
-	if (pdev->vframe_count > 20)
-		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
-
-	if (!pdev->unplugged) {
-		/* Normal close: stop isochronuous and interrupt endpoint */
-		Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
-		usb_set_interface(pdev->udev, 0, 0);
-
-		/* Turn LEDs off */
-		if (pwc_set_leds(pdev, 0, 0) < 0)
-			Info("Failed to set LED on/off time..\n");
-		/* Power down camere to save energy */
-		if (power_save) {
-			i = pwc_camera_power(pdev, 0);
-			if (i < 0) 
-				Err("Failed to power down camera (%d)\n", i);
-		}
-	}
-
-	pdev->vopen = 0;
-	if (pdev->decompressor != NULL) {
-		pdev->decompressor->exit();
-		pdev->decompressor->unlock();
-	}
-	pwc_free_buffers(pdev);
-
-	/* wake up _disconnect() routine */
-	if (pdev->unplugged)
-		wake_up(&pdev->remove_ok);
-	file->private_data = NULL;
-	return 0;
-}
-
-/*
- *	FIXME: what about two parallel reads ????
- *      ANSWER: Not supported. You can't open the device more than once,
-                despite what the V4L1 interface says. First, I don't see 
-                the need, second there's no mechanism of alerting the 
-                2nd/3rd/... process of events like changing image size.
-                And I don't see the point of blocking that for the 
-                2nd/3rd/... process.
-                In multi-threaded environments reading parallel from any
-                device is tricky anyhow.
- */
- 
-static int pwc_video_read(struct file *file, char *buf,
-			  size_t count, loff_t *ppos)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	int noblock = file->f_flags & O_NONBLOCK;
-	DECLARE_WAITQUEUE(wait, current);
-
-	Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count);
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-	if (pdev->unplugged) {
-		Info("pwc_video_read: Device got unplugged (1).\n");
-		return -EPIPE; /* unplugged device! */
-	}
-
-	/* In case we're doing partial reads, we don't have to wait for a frame */
-	if (pdev->image_read_pos == 0) {
-		/* Do wait queueing according to the (doc)book */
-		add_wait_queue(&pdev->frameq, &wait);
-		while (pdev->full_frames == NULL) {
-	                if (noblock) {
-	                	remove_wait_queue(&pdev->frameq, &wait);
-	                	set_current_state(TASK_RUNNING);
-	                	return -EWOULDBLOCK;
-	                }
-	                if (signal_pending(current)) {
-	                	remove_wait_queue(&pdev->frameq, &wait);
-	                	set_current_state(TASK_RUNNING);
-	                	return -ERESTARTSYS;
-	                }
-	                schedule();
-	               	set_current_state(TASK_INTERRUPTIBLE);
-		}
-		remove_wait_queue(&pdev->frameq, &wait);
-		set_current_state(TASK_RUNNING);
-	                                                                                                                                                                                
-		/* Decompress [, convert] and release frame */
-		if (pwc_handle_frame(pdev))
-			return -EFAULT;
-	}
-
-	Trace(TRACE_READ, "Copying data to user space.\n");
-	/* copy bytes to user space; we allow for partial reads */
-	if (count + pdev->image_read_pos > pdev->view.size)
-		count = pdev->view.size - pdev->image_read_pos;
-	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
-		return -EFAULT;
-	pdev->image_read_pos += count;
-	if (pdev->image_read_pos >= pdev->view.size) { /* All data has been read */
-		pdev->image_read_pos = 0;
-		pwc_next_image(pdev);
-	}
-	return count;
-}
-
-static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-	
-	poll_wait(file, &pdev->frameq, wait);
-	if (pdev->unplugged) {
-		Info("pwc_video_poll: Device got unplugged.\n");
-		return POLLERR;
-	}		
-	if (pdev->full_frames != NULL) /* we have frames waiting */
-		return (POLLIN | POLLRDNORM);
-
-	return 0;
-}
-        
-static int pwc_video_ioctl(struct inode *inode, struct file *file,
-			   unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	DECLARE_WAITQUEUE(wait, current);
-	
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-
-	switch (cmd) {
-		/* Query cabapilities */
-		case VIDIOCGCAP: 
-		{
-			struct video_capability *caps = arg;
-
-			strcpy(caps->name, vdev->name);
-			caps->type = VID_TYPE_CAPTURE;
-			caps->channels = 1;
-			caps->audios = 1;
-			caps->minwidth  = pdev->view_min.x;
-			caps->minheight = pdev->view_min.y;
-			caps->maxwidth  = pdev->view_max.x;
-			caps->maxheight = pdev->view_max.y;
-			break;
-		}
-
-		/* Channel functions (simulate 1 channel) */
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-
-			if (v->channel != 0)
-				return -EINVAL;
-			v->flags = 0;
-			v->tuners = 0;
-			v->type = VIDEO_TYPE_CAMERA;
-			strcpy(v->name, "Webcam");
-			return 0;
-		}
-
-		case VIDIOCSCHAN:
-		{	
-			/* The spec says the argument is an integer, but
-			   the bttv driver uses a video_channel arg, which
-			   makes sense becasue it also has the norm flag.
-			 */
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-
-
-		/* Picture functions; contrast etc. */
-		case VIDIOCGPICT:
-		{
-			struct video_picture *p = arg;
-			int val;
-
-			p->colour = 0x8000;
-			p->hue = 0x8000;
-			val = pwc_get_brightness(pdev);
-			if (val >= 0)
-				p->brightness = val;
-			else
-				p->brightness = 0xffff;
-			val = pwc_get_contrast(pdev);
-			if (val >= 0)
-				p->contrast = val;
-			else
-				p->contrast = 0xffff;
-			/* Gamma, Whiteness, what's the difference? :) */
-			val = pwc_get_gamma(pdev);
-			if (val >= 0)
-				p->whiteness = val;
-			else
-				p->whiteness = 0xffff;
-			val = pwc_get_saturation(pdev);
-			if (val >= 0)
-				p->colour = val;
-			else
-				p->colour = 0xffff;
-			p->depth = 24;
-			p->palette = pdev->vpalette;
-			p->hue = 0xFFFF; /* N/A */
-			break;
-		}
-		
-		case VIDIOCSPICT:
-		{
-			struct video_picture *p = arg;
-			/*
-			 *	FIXME:	Suppose we are mid read
-			        ANSWER: No problem: the firmware of the camera
-			                can handle brightness/contrast/etc
-			                changes at _any_ time, and the palette
-			                is used exactly once in the uncompress
-			                routine.
-			 */
-			if (p->palette && p->palette != pdev->vpalette) {
-				if (pwc_set_palette(pdev, p->palette) < 0)
-					return -EINVAL;
-			}
-			pwc_set_brightness(pdev, p->brightness);
-			pwc_set_contrast(pdev, p->contrast);
-			pwc_set_gamma(pdev, p->whiteness);
-			pwc_set_saturation(pdev, p->colour);
-			break;
-		}
-
-		/* Window/size parameters */		
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-			
-			vw->x = 0;
-			vw->y = 0;
-			vw->width = pdev->view.x;
-			vw->height = pdev->view.y;
-			vw->chromakey = 0;
-			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | 
-			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
-			break;
-		}
-		
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-			int fps, snapshot, ret;
-
-			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
-			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
-			if (fps == 0)
-				fps = pdev->vframes;
-			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
-				return 0;
-			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
-			if (ret)
-				return ret;
-			break;		
-		}
-		
-		/* We don't have overlay support (yet) */
-		case VIDIOCGFBUF:
-		{
-			struct video_buffer *vb = arg;
-
-			memset(vb,0,sizeof(*vb));
-			break;
-		}
-
-		/* mmap() functions */
-		case VIDIOCGMBUF:
-		{
-			/* Tell the user program how much memory is needed for a mmap() */
-			struct video_mbuf *vm = arg;
-			int i;
-
-			memset(vm, 0, sizeof(*vm));
-			vm->size = default_mbufs * pdev->len_per_image;
-			vm->frames = default_mbufs; /* double buffering should be enough for most applications */
-			for (i = 0; i < default_mbufs; i++)
-				vm->offsets[i] = i * pdev->len_per_image;
-			break;
-		}
-
-		case VIDIOCMCAPTURE:
-		{
-			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
-			struct video_mmap *vm = arg;
-
-			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
-			if (vm->frame < 0 || vm->frame >= default_mbufs)
-				return -EINVAL;
-
-			/* xawtv is nasty. It probes the available palettes
-			   by setting a very small image size and trying
-			   various palettes... The driver doesn't support
-			   such small images, so I'm working around it.
-			 */
-			if (vm->format && vm->format != pdev->vpalette)
-				if (pwc_set_palette(pdev, vm->format) < 0)
-					return -EINVAL;
-			 
-			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
-			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
-				int ret;
-				
-				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
-				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-				if (ret)
-					return ret;
-			} /* ... size mismatch */
-
-			/* FIXME: should we lock here? */
-			if (pdev->image_used[vm->frame])
-				return -EBUSY;	/* buffer wasn't available. Bummer */
-			pdev->image_used[vm->frame] = 1;
-
-			/* Okay, we're done here. In the SYNC call we wait until a 
-			   frame comes available, then expand image into the given 
-			   buffer.
-			   In contrast to the CPiA cam the Philips cams deliver a 
-			   constant stream, almost like a grabber card. Also,
-			   we have separate buffers for the rawdata and the image,
-			   meaning we can nearly always expand into the requested buffer.
-			 */
-			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
-			break;
-		}
-
-		case VIDIOCSYNC:
-		{
-			/* The doc says: "Whenever a buffer is used it should
-			   call VIDIOCSYNC to free this frame up and continue."
-			   
-			   The only odd thing about this whole procedure is 
-			   that MCAPTURE flags the buffer as "in use", and
-			   SYNC immediately unmarks it, while it isn't 
-			   after SYNC that you know that the buffer actually
-			   got filled! So you better not start a CAPTURE in
-			   the same frame immediately (use double buffering). 
-			   This is not a problem for this cam, since it has 
-			   extra intermediate buffers, but a hardware 
-			   grabber card will then overwrite the buffer 
-			   you're working on.
-			 */
-			int *mbuf = arg;
-			int ret;
-
-			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
-
-			/* bounds check */
-			if (*mbuf < 0 || *mbuf >= default_mbufs)
-				return -EINVAL;
-			/* check if this buffer was requested anyway */
-			if (pdev->image_used[*mbuf] == 0)
-				return -EINVAL;
-
-			/* Add ourselves to the frame wait-queue.
-			   
-			   FIXME: needs auditing for safety.
-			   QUSTION: In what respect? I think that using the
-			            frameq is safe now.
-			 */
-			add_wait_queue(&pdev->frameq, &wait);
-			while (pdev->full_frames == NULL) {
-				if (pdev->unplugged) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -ENODEV;
-				}
-			
-	                	if (signal_pending(current)) {
-	                		remove_wait_queue(&pdev->frameq, &wait);
-		                	set_current_state(TASK_RUNNING);
-		                	return -ERESTARTSYS;
-	        	        }
-		                set_current_state(TASK_INTERRUPTIBLE);
-	                	schedule();
-			}
-			remove_wait_queue(&pdev->frameq, &wait);
-			set_current_state(TASK_RUNNING);
-				
-			/* The frame is ready. Expand in the image buffer 
-			   requested by the user. I don't care if you 
-			   mmap() 5 buffers and request data in this order: 
-			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
-			   Grabber hardware may not be so forgiving.
-			 */
-			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
-			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
-			/* Decompress, etc */
-			ret = pwc_handle_frame(pdev);
-			pdev->image_used[*mbuf] = 0;
-			if (ret)
-				return -EFAULT;
-			break;
-		}
-		
-		case VIDIOCGAUDIO:
-		{
-			struct video_audio *v = arg;
-			
-			strcpy(v->name, "Microphone");
-			v->audio = -1; /* unknown audio minor */
-			v->flags = 0;
-			v->mode = VIDEO_SOUND_MONO;
-			v->volume = 0;
-			v->bass = 0;
-			v->treble = 0;
-			v->balance = 0x8000;
-			v->step = 1;
-			break;	
-		}
-		
-		case VIDIOCSAUDIO:
-		{
-			/* Dummy: nothing can be set */
-			break;
-		}
-		
-		case VIDIOCGUNIT:
-		{
-			struct video_unit *vu = arg;
-			
-			vu->video = pdev->vdev->minor & 0x3F;
-			vu->audio = -1; /* not known yet */
-			vu->vbi = -1;
-			vu->radio = -1;
-			vu->teletext = -1;
-			break;
-		}
-		default:
-			return pwc_ioctl(pdev, cmd, arg);
-	} /* ..switch */
-	return 0;
-}	
-
-static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-	
-	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
-	pdev = vdev->priv;
-
-	/* FIXME - audit mmap during a read */		
-	pos = (unsigned long)pdev->image_data;
-	while (size > 0) {
-		page = kvirt_to_pa(pos);
-		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-/***************************************************************************/
-/* USB functions */
-
-/* This function gets called when a new device is plugged in or the usb core
- * is loaded.
- */
-
-static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)
-{
-	struct pwc_device *pdev = NULL;
-	struct video_device *vdev;
-	int vendor_id, product_id, type_id;
-	int i, hint;
-	int video_nr = -1; /* default: use next available device */
-	char serial_number[30];
-
-	free_mem_leak();
-	
-	/* Check if we can handle this device */
-	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev->descriptor.idVendor, udev->descriptor.idProduct, ifnum);
-
-	/* the interfaces are probed one by one. We are only interested in the
-	   video interface (0) now.
-	   Interface 1 is the Audio Control, and interface 2 Audio itself.
-	 */
-	if (ifnum > 0) 
-		return NULL;
-
-	vendor_id = udev->descriptor.idVendor;
-	product_id = udev->descriptor.idProduct;
-
-	if (vendor_id == 0x0471) {
-		switch (product_id) {
-		case 0x0302:
-			Info("Philips PCA645VC USB webcam detected.\n");
-			type_id = 645;
-			break;
-		case 0x0303:
-			Info("Philips PCA646VC USB webcam detected.\n");
-			type_id = 646;
-			break;
-		case 0x0304:
-			Info("Askey VC010 type 2 USB webcam detected.\n");
-			type_id = 646;
-			break;
-		case 0x0307:
-			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
-			type_id = 675;
-			break;
-		case 0x0308:
-			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
-			type_id = 680;
-			break;
-		case 0x030C:
-			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
-			type_id = 690;
-			break;
-		case 0x0310:
-			Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
-			type_id = 730;
-			break;
-		case 0x0311:
-			Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
-			type_id = 740;
-			break;
-		case 0x0312:
-			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
-			type_id = 750;
-			break;
-		default:
-			return NULL;
-			break;
-		}
-	}
-	else if (vendor_id == 0x069A) {
-		switch(product_id) {
-		case 0x0001:
-			Info("Askey VC010 type 1 USB webcam detected.\n");
-			type_id = 645;
-			break;
-		default:
-			return NULL;
-			break;
-		}
-	}
-	else if (vendor_id == 0x046d) {
-		switch(product_id) {
-		case 0x08b0:
-			Info("Logitech QuickCam 3000 Pro detected.\n");
-			type_id = 730;
-        		break;
-        	default:
-        		return NULL;
-        		break;
-        	}
-        }
-	else if (vendor_id == 0x055d) {
-		/* I don't know the difference between the C10 and the C30;
-		   I suppose the difference is the sensor, but both cameras
-		   work equally well with a type_id of 675
-		 */
-		switch(product_id) {
-		case 0x9000:
-			Info("Samsung MPC-C10 USB webcam detected.\n");
-			type_id = 675;
-			break;
-		case 0x9001:
-			Info("Samsung MPC-C30 USB webcam detected.\n");
-			type_id = 675;
-			break;
-		default:
-			return NULL;
-			break;
-		}
-	}
-	else if (vendor_id == 0x041e) {
-		switch(product_id) {
-		case 0x400c:
-			Info("Creative Labs Webcam 5 detected.\n");
-			type_id = 730;
-			break;
-		default:
-			return NULL;
-			break;
-		}
-	}
-	else if (vendor_id == 0x04cc) { 
-		switch(product_id) {
-		case 0x8116:
-			Info("SOTEC CMS-001 USB webcam detected.\n");
-			type_id = 730;
-			break;  
-		default:
-			return NULL;
-			break;
-		}
-	}
-	else return NULL; /* Not Philips, Askey, Logitech, Samsung, Creative or SOTEC, for sure. */
-
-	memset(serial_number, 0, 30);
-	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
-	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
-
-	if (udev->descriptor.bNumConfigurations > 1)
-		Info("Warning: more than 1 configuration available.\n");
-
-	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
-	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
-	if (pdev == NULL) {
-		Err("Oops, could not allocate memory for pwc_device.\n");
-		return NULL;
-	}
-	memset(pdev, 0, sizeof(struct pwc_device));
-	pdev->type = type_id;
-	pwc_construct(pdev);
-
-	init_MUTEX(&pdev->modlock);
-	pdev->ptrlock = SPIN_LOCK_UNLOCKED;
-
-	pdev->udev = udev;
-	init_waitqueue_head(&pdev->frameq);
-	init_waitqueue_head(&pdev->remove_ok);
-	pdev->vcompression = pwc_preferred_compression;
-
-	/* Now hook it up to the video subsystem */
-	vdev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
-	if (vdev == NULL) {
-		Err("Oops, could not allocate memory for video_device.\n");
-		return NULL;
-	}
-	memcpy(vdev, &pwc_template, sizeof(pwc_template));
-	sprintf(vdev->name, "Philips %d webcam", pdev->type);
-	SET_MODULE_OWNER(vdev);
-	pdev->vdev = vdev;
-	vdev->priv = pdev;
-
-	pdev->release = udev->descriptor.bcdDevice;
-	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
-
-
-	/* Now search device_hint[] table for a match, so we can hint a node number. */
-	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
-		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
-		     (device_hint[hint].pdev == NULL)) {
-			/* so far, so good... try serial number */
-			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
-			    	/* match! */
-			    	video_nr = device_hint[hint].device_node;
-			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
-			    	break;
-			}
-		}
-	}
-
-	i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr);
-	if (i < 0) {
-		Err("Failed to register as video device (%d).\n", i);
-		return NULL;
-	}
-	else {
-		Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev);
-		Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F);
-	}
-	/* occupy slot */
-	if (hint < MAX_DEV_HINTS) 
-		device_hint[hint].pdev = pdev;
-
-	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
-	return pdev;
-}
-
-/* The user janked out the cable... */
-static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
-{
-	struct pwc_device *pdev;
-	int hint;
-	DECLARE_WAITQUEUE(wait, current);
-
-	lock_kernel();
-	free_mem_leak();
-
-	pdev = (struct pwc_device *)ptr;
-	if (pdev == NULL) {
-		Err("pwc_disconnect() Called without private pointer.\n");
-		return;
-	}
-	if (pdev->udev == NULL) {
-		Err("pwc_disconnect() already called for %p\n", pdev);
-		return;
-	}
-	if (pdev->udev != udev) {
-		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
-		return;
-	}
-#ifdef PWC_MAGIC	
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
-		return;
-	}
-#endif	
-	
-	pdev->unplugged = 1;
-	if (pdev->vdev != NULL) {
-		video_unregister_device(pdev->vdev); 
-		if (pdev->vopen) {
-			Info("Disconnected while device/video is open!\n");
-			
-			/* Wake up any processes that might be waiting for
-			   a frame, let them return an error condition
-			 */
-			wake_up(&pdev->frameq);
-			
-			/* Wait until we get a 'go' from _close(). This used
-			   to have a gigantic race condition, since we kfree()
-			   stuff here, but we have to wait until close() 
-			   is finished. 
-			 */
-			   
-			Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
-			add_wait_queue(&pdev->remove_ok, &wait);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			/* ... wait ... */
-			schedule();
-			remove_wait_queue(&pdev->remove_ok, &wait);
-			set_current_state(TASK_RUNNING);
-			Trace(TRACE_PROBE, "Done sleeping.\n");
-			set_mem_leak(pdev->vdev);
-			pdev->vdev = NULL;
-		}
-		else {
-			/* Normal disconnect; remove from available devices */
-			Trace(TRACE_PROBE, "Unregistering video device normally.\n");
-			kfree(pdev->vdev);
-			pdev->vdev = NULL;
-		}
-	}
-
-	/* search device_hint[] table if we occupy a slot, by any chance */
-	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
-		if (device_hint[hint].pdev == pdev)
-			device_hint[hint].pdev = NULL;
-
-	pdev->udev = NULL;
-	unlock_kernel();
-	kfree(pdev);
-}
-
-
-/* *grunt* We have to do atoi ourselves :-( */
-static int pwc_atoi(char *s)
-{
-	int k = 0;
-	
-	k = 0;
-	while (*s != '\0' && *s >= '0' && *s <= '9') {
-		k = 10 * k + (*s - '0');
-		s++;
-	}
-	return k;
-}
-
-
-/* 
- * Initialization code & module stuff 
- */
-
-static char *size = NULL;
-static int fps = 0;
-static int fbufs = 0;
-static int mbufs = 0;
-static int trace = -1;
-static int compression = -1;
-static int leds[2] = { -1, -1 };
-static char *dev_hint[10] = { };
-
-MODULE_PARM(size, "s");
-MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
-MODULE_PARM(fps, "i");
-MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-MODULE_PARM(fbufs, "i");
-MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-MODULE_PARM(mbufs, "i");
-MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-MODULE_PARM(trace, "i");
-MODULE_PARM_DESC(trace, "For debugging purposes");
-MODULE_PARM(power_save, "i");
-MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-MODULE_PARM(compression, "i");
-MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-MODULE_PARM(leds, "2i");
-MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM(dev_hint, "0-10s");
-MODULE_PARM_DESC(dev_hint, "Device node hints");
-
-MODULE_DESCRIPTION("Philips USB webcam driver");
-MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
-MODULE_LICENSE("GPL");
-
-static int __init usb_pwc_init(void)
-{
-	int i, sz;
-	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
-
-	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
-	Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30, the Creative WebCam 5 and the SOTEC CMS-001.\n");
-
-	if (fps) {
-		if (fps < 5 || fps > 30) {
-			Err("Framerate out of bounds (5-30).\n");
-			return -EINVAL;
-		}
-		default_fps = fps;
-		Info("Default framerate set to %d.\n", default_fps);
-	}
-	
-	if (size) {
-		/* string; try matching with array */
-		for (sz = 0; sz < PSZ_MAX; sz++) {
-			if (!strcmp(sizenames[sz], size)) { /* Found! */
-				default_size = sz;
-				break;
-			}
-		}
-		if (sz == PSZ_MAX) {
-			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
-			return -EINVAL;
-		}
-		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
-	}
-	if (mbufs) {
-		if (mbufs < 1 || mbufs > MAX_IMAGES) {
-			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
-			return -EINVAL;
-		}
-		default_mbufs = mbufs;
-		Info("Number of image buffers set to %d.\n", default_mbufs);
-	}
-	if (fbufs) {
-		if (fbufs < 2 || fbufs > MAX_FRAMES) {
-			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
-			return -EINVAL;
-		}
-		default_fbufs = fbufs;
-		Info("Number of frame buffers set to %d.\n", default_fbufs);
-	}
-	if (trace >= 0) {
-		Info("Trace options: 0x%04x\n", trace);
-		pwc_trace = trace;
-	}
-	if (compression >= 0) {
-		if (compression > 3) {
-			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
-			return -EINVAL;
-		}
-		pwc_preferred_compression = compression;
-		Info("Preferred compression set to %d.\n", pwc_preferred_compression);
-	}
-	if (power_save)
-		Info("Enabling power save on open/close.\n");
-	if (leds[0] >= 0)
-		led_on = leds[0] / 100;
-	if (leds[1] >= 0)
-		led_off = leds[1] / 100;
-
-	/* Big device node whoopla. Basicly, it allows you to assign a 
-	   device node (/dev/videoX) to a camera, based on its type 
-	   & serial number. The format is [type[.serialnumber]:]node.
-
-           Any camera that isn't matched by these rules gets the next 
-           available free device node.
-	 */
-	for (i = 0; i < MAX_DEV_HINTS; i++) {
-		char *s, *colon, *dot;
-
-		/* This loop also initializes the array */
-		device_hint[i].pdev = NULL;
-		s = dev_hint[i];
-		if (s != NULL && *s != '\0') {
-			device_hint[i].type = -1; /* wildcard */
-			strcpy(device_hint[i].serial_number, "*");
-
-			/* parse string: chop at ':' & '/' */
-			colon = dot = s;
-			while (*colon != '\0' && *colon != ':')
-				colon++;
-			while (*dot != '\0' && *dot != '.')
-				dot++;
-			/* Few sanity checks */
-			if (*dot != '\0' && dot > colon) {
-				Err("Malformed camera hint: the colon must be after the dot.\n");
-				return -EINVAL;
-			}
-
-			if (*colon == '\0') {
-				/* No colon */
-				if (*dot != '\0') {
-					Err("Malformed camera hint: no colon + device node given.\n");
-					return -EINVAL;
-				}
-				else {
-					/* No type or serial number specified, just a number. */
-					device_hint[i].device_node = pwc_atoi(s);
-				}
-			}
-			else {
-				/* There's a colon, so we have at least a type and a device node */
-				device_hint[i].type = pwc_atoi(s);
-				device_hint[i].device_node = pwc_atoi(colon + 1);
-				if (*dot != '\0') {
-					/* There's a serial number as well */
-					int k;
-					
-					dot++;
-					k = 0;
-					while (*dot != ':' && k < 29) {
-						device_hint[i].serial_number[k++] = *dot;
-						dot++;
-					}
-					device_hint[i].serial_number[k] = '\0';
-				}
-			}
-#ifdef PWC_DEBUG		
-			Debug("device_hint[%d]:\n", i);
-			Debug("  type    : %d\n", device_hint[i].type);
-			Debug("  serial# : %s\n", device_hint[i].serial_number);
-			Debug("  node    : %d\n", device_hint[i].device_node);
-#endif			
-		}
-		else
-			device_hint[i].type = 0; /* not filled */
-	} /* ..for MAX_DEV_HINTS */
-
-	init_MUTEX(&mem_lock);
- 	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
-	return usb_register(&pwc_driver);
-}
-
-static void __exit usb_pwc_exit(void)
-{
-	free_mem_leak();
-	Trace(TRACE_MODULE, "Deregistering driver.\n");
-	usb_deregister(&pwc_driver);
-	Info("Philips webcam module removed.\n");
-}
-
-module_init(usb_pwc_init);
-module_exit(usb_pwc_exit);
-
diff -Nru a/drivers/usb/pwc-ioctl.h b/drivers/usb/pwc-ioctl.h
--- a/drivers/usb/pwc-ioctl.h	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,123 +0,0 @@
-#ifndef PWC_IOCTL_H
-#define PWC_IOCTL_H
-
-/* (C) 2001 Nemosoft Unv.    webcam@smcc.demon.nl
-   
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added ioctl constants to access methods for 
-                          changing white balance and red/blue gains
- */
-
-/* These are private ioctl() commands, specific for the Philips webcams.
-   They contain functions not found in other webcams, and settings not
-   specified in the Video4Linux API. 
-   
-   The #define names are built up like follows:
-   VIDIOC		VIDeo IOCtl prefix
-         PWC		Philps WebCam
-            G           optional: Get
-            S           optional: Set
-             ... 	the function
- */
-
-
-
-
-/* The frame rate is encoded in the video_window.flags parameter using
-   the upper 16 bits, since some flags are defined nowadays. The following
-   defines provide a mask and shift to filter out this value.
-   
-   In 'Snapshot' mode the camera freezes its automatic exposure and colour 
-   balance controls.
- */
-#define PWC_FPS_SHIFT		16
-#define PWC_FPS_MASK		0x00FF0000
-#define PWC_FPS_FRMASK		0x003F0000
-#define PWC_FPS_SNAPSHOT	0x00400000
-
-
-/* pwc_whitebalance.mode values */
-#define PWC_WB_INDOOR		0
-#define PWC_WB_OUTDOOR		1
-#define PWC_WB_FL		2
-#define PWC_WB_MANUAL		3
-#define PWC_WB_AUTO		4
-
-/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). 
-   Set mode to one of the PWC_WB_* values above.
-   *red and *blue are the respective gains of these colour components inside 
-   the camera; range 0..65535
-   When mode == PWC_WB_MANUAL, manual_red and manual_blue are set or read; 
-   otherwise undefined.
-   read_red and read_blue are read-only.
-*/   
-   
-struct pwc_whitebalance
-{
-	int mode;
-	int manual_red, manual_blue;	/* R/W */
-	int read_red, read_blue;	/* R/O */
-};
-
-
-/* Used with VIDIOCPWC[SG]LED */
-struct pwc_leds
-{
-	int led_on;			/* Led on-time; range = 0..25000 */
-	int led_off;			/* Led off-time; range = 0..25000  */
-};
-
-
-
- /* Restore user settings */
-#define VIDIOCPWCRUSER		_IO('v', 192)
- /* Save user settings */
-#define VIDIOCPWCSUSER		_IO('v', 193)
- /* Restore factory settings */
-#define VIDIOCPWCFACTORY	_IO('v', 194)
-
- /* You can manipulate the compression factor. A compression preference of 0
-    means use uncompressed modes when available; 1 is low compression, 2 is
-    medium and 3 is high compression preferred. Of course, the higher the
-    compression, the lower the bandwidth used but more chance of artefacts
-    in the image. The driver automatically chooses a higher compression when
-    the preferred mode is not available.
-  */
- /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
-#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
- /* Get preferred compression quality */
-#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
-
- /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
-#define VIDIOCPWCSAGC		_IOW('v', 200, int)
- /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCGAGC		_IOR('v', 200, int)
- /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
-#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
-
- /* Color compensation (Auto White Balance) */
-#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
-#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
-
- /* Turn LED on/off ; int range 0..65535 */
-#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
- /* Get state of LED; int range 0..65535 */
-#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
-
-#endif
diff -Nru a/drivers/usb/pwc-misc.c b/drivers/usb/pwc-misc.c
--- a/drivers/usb/pwc-misc.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,104 +0,0 @@
-/* Linux driver for Philips webcam 
-   Various miscellaneous functions and tables.
-   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/  
-
-#include <linux/slab.h>
-
-#include "pwc.h"
-
-struct pwc_coord pwc_image_sizes[PSZ_MAX] = 
-{
-	{ 128,  96, 0 },
-	{ 160, 120, 0 },
-	{ 176, 144, 0 },
-	{ 320, 240, 0 },
-	{ 352, 288, 0 },
-	{ 640, 480, 0 },
-};
-
-/* x,y -> PSZ_ */
-int pwc_decode_size(struct pwc_device *pdev, int width, int height)
-{
-	int i, find;
-
-	/* Make sure we don't go beyond our max size */
-	if (width > pdev->view_max.x || height > pdev->view_max.y)
-		return -1;
-	/* Find the largest size supported by the camera that fits into the
-	   requested size. 
-	 */
-	find = -1;
-	for (i = 0; i < PSZ_MAX; i++) {
-		if (pdev->image_mask & (1 << i)) {
-			if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
-				find = i;
-		}
-	}
-	return find;
-}
-
-/* initialize variables depending on type */
-void pwc_construct(struct pwc_device *pdev)
-{
-	switch(pdev->type) {
-	case 645:
-	case 646:
-		pdev->view_min.x = 128;
-		pdev->view_min.y =  96;
-		pdev->view_max.x = 352;
-		pdev->view_max.y = 288;
-		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
-		pdev->vcinterface = 2;
-		pdev->vendpoint = 4;
-		pdev->frame_header_size = 0;
-		pdev->frame_trailer_size = 0;
-		break;
-	case 675:
-	case 680:
-	case 690:
-		pdev->view_min.x = 128;
-		pdev->view_min.y =  96;
-		pdev->view_max.x = 640;
-		pdev->view_max.y = 480;
-		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
-		pdev->vcinterface = 3;
-		pdev->vendpoint = 4;
-		pdev->frame_header_size = 0;
-		pdev->frame_trailer_size = 0;
-		break;
-	case 730:
-	case 740:
-	case 750:
-		pdev->view_min.x = 160;
-		pdev->view_min.y = 120;
-		pdev->view_max.x = 640;
-		pdev->view_max.y = 480;
-		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-		pdev->vcinterface = 3;
-		pdev->vendpoint = 5;
-		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
-		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
-		break;
-	}
-	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
-	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
-	/* length of image, in YUV format */
-	pdev->len_per_image = (pdev->view_max.size * 3) / 2;
-}
-
-
diff -Nru a/drivers/usb/pwc-uncompress.c b/drivers/usb/pwc-uncompress.c
--- a/drivers/usb/pwc-uncompress.c	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,190 +0,0 @@
-/* Linux driver for Philips webcam 
-   Decompression frontend.
-   (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-/*
-   This is where the decompression routines register and unregister 
-   themselves. It also has a decompressor wrapper function.
-*/
-
-#include <asm/types.h>
-
-#include "pwc.h"
-#include "pwc-uncompress.h"
-
-
-/* This contains a list of all registered decompressors */
-static LIST_HEAD(pwc_decompressor_list);
-
-/* Should the pwc_decompress structure ever change, we increase the 
-   version number so that we don't get nasty surprises, or can 
-   dynamicly adjust our structure.
- */
-const int pwc_decompressor_version = PWC_MAJOR;
-
-/* Add decompressor to list, ignoring duplicates */
-void pwc_register_decompressor(struct pwc_decompressor *pwcd)
-{
-	if (pwc_find_decompressor(pwcd->type) == NULL) {
-		Trace(TRACE_PWCX, "Adding decompressor for model %d.\n", pwcd->type);
-		list_add_tail(&pwcd->pwcd_list, &pwc_decompressor_list);
-	}
-}
-
-/* Remove decompressor from list */
-void pwc_unregister_decompressor(int type)
-{
-	struct pwc_decompressor *find;
-	
-	find = pwc_find_decompressor(type);
-	if (find != NULL) {
-		Trace(TRACE_PWCX, "Removing decompressor for model %d.\n", type);
-		list_del(&find->pwcd_list);
-	}
-}
-
-/* Find decompressor in list */
-struct pwc_decompressor *pwc_find_decompressor(int type)
-{
-	struct list_head *tmp;
-	struct pwc_decompressor *pwcd;
-
-	list_for_each(tmp, &pwc_decompressor_list) {
-		pwcd  = list_entry(tmp, struct pwc_decompressor, pwcd_list);
-		if (pwcd->type == type)
-			return pwcd;
-	}
-	return NULL;
-}
-
-
-
-int pwc_decompress(struct pwc_device *pdev)
-{
-	struct pwc_frame_buf *fbuf;
-	int n, line, col, stride;
-	void *yuv, *image, *dst;
-	u16 *src;
-	u16 *dsty, *dstu, *dstv;
-
-	
-	if (pdev == NULL)
-		return -EFAULT;
-#if defined(__KERNEL__) && defined(PWC_MAGIC)
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_decompress(): magic failed.\n");
-		return -EFAULT;
-	}
-#endif
-
-	fbuf = pdev->read_frame;
-	if (fbuf == NULL)
-		return -EFAULT;
-	image = pdev->image_ptr[pdev->fill_image];
-	if (!image)
-		return -EFAULT;
-	
-#if PWC_DEBUG
-	/* This is a quickie */
-	if (pdev->vpalette == VIDEO_PALETTE_RAW) {
-		memcpy(image, fbuf->data, pdev->frame_size);
-		return 0;
-	}
-#endif
-
-	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
-	if (pdev->vbandlength == 0) { 
-		/* Uncompressed mode. We copy the data into the output buffer,
-		   using the viewport size (which may be larger than the image
-		   size). Unfortunately we have to do a bit of byte stuffing
-		   to get the desired output format/size.
-		 */
-		switch (pdev->vpalette) {
-		case VIDEO_PALETTE_YUV420:
-			/* Calculate byte offsets per line in image & view */
-			n   = (pdev->image.x * 3) / 2;
-			col = (pdev->view.x  * 3) / 2;
-			/* Offset into image */
-			dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2;
-			for (line = 0; line < pdev->image.y; line++) {
-				memcpy(dst, yuv, n);
-				yuv += n;
-				dst += col;
-			}
-			break;
-
-		case VIDEO_PALETTE_YUV420P:
-			/* 
-			 * We do some byte shuffling here to go from the 
-			 * native format to YUV420P.
-			 */
-			src = (u16 *)yuv;
-			n = pdev->view.x * pdev->view.y;
-
-			/* offset in Y plane */
-			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-			dsty = (u16 *)(image + stride);
-
-			/* offsets in U/V planes */
-			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-			dstu = (u16 *)(image + n +         stride);
-			dstv = (u16 *)(image + n + n / 4 + stride);
-
-			/* increment after each line */
-			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
-
-			for (line = 0; line < pdev->image.y; line++) {
-				for (col = 0; col < pdev->image.x; col += 4) {
-					*dsty++ = *src++;
-					*dsty++ = *src++;
-					if (line & 1)
-						*dstv++ = *src++;
-					else
-						*dstu++ = *src++;
-				}
-				dsty += stride;
-				if (line & 1)
-					dstv += (stride >> 1);
-				else
-					dstu += (stride >> 1);
-			}
-			break;
-		}
-	}
-	else { 
-		/* Compressed; the decompressor routines will write the data 
-		   in interlaced or planar format immediately.
-		 */
-		if (pdev->decompressor)
-			pdev->decompressor->decompress(
-				&pdev->image, &pdev->view, &pdev->offset,
-				yuv, image, 
-				pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0,
-				pdev->decompress_data, pdev->vbandlength);
-		else
-			return -ENXIO; /* No such device or address: missing decompressor */
-	}
-	return 0;
-}
-
-/* Make sure these functions are available for the decompressor plugin
-   both when this code is compiled into the kernel or as as module.
- */
-
-EXPORT_SYMBOL_NOVERS(pwc_decompressor_version);
-EXPORT_SYMBOL(pwc_register_decompressor);
-EXPORT_SYMBOL(pwc_unregister_decompressor);
diff -Nru a/drivers/usb/pwc-uncompress.h b/drivers/usb/pwc-uncompress.h
--- a/drivers/usb/pwc-uncompress.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,77 +0,0 @@
-/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/* This file is the bridge between the kernel module and the plugin; it
-   describes the structures and datatypes used in both modules. Any
-   significant change should be reflected by increasing the 
-   pwc_decompressor_version major number.
- */
-#ifndef PWC_DEC_H
-#define PWC_DEC_H
-
-#include <linux/config.h>
-#include <linux/list.h>
-
-#include "pwc.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The decompressor structure. 
-   Every type of decompressor registers itself with the main module. 
-   When a device is opened, it looks up the correct compressor, and
-   uses that when a compressed video mode is requested.
- */
-struct pwc_decompressor
-{
-	int  type;		/* type of camera (645, 680, etc) */
-	int  table_size;	/* memory needed */
-
-	void (* init)(int release, void *buffer, void *table);	/* Initialization routine; should be called after each set_video_mode */
-	void (* exit)(void);	/* Cleanup routine */
-	void (* decompress)(struct pwc_coord *image, struct pwc_coord *view, struct pwc_coord *offset,
-                            void *src, void *dst, int planar,
-	                    void *table, int bandlength);
-	void (* lock)(void);	/* make sure module cannot be unloaded */
-	void (* unlock)(void);	/* release lock on module */
-
-	struct list_head pwcd_list;
-};
-
-
-/* Our structure version number. Is set to the version number major */
-extern const int pwc_decompressor_version;
-
-/* Adds decompressor to list, based on its 'type' field (which matches the 'type' field in pwc_device; ignores any double requests */
-extern void pwc_register_decompressor(struct pwc_decompressor *pwcd);
-/* Removes decompressor, based on the type number */
-extern void pwc_unregister_decompressor(int type);
-/* Returns pointer to decompressor struct, or NULL if it doesn't exist */
-extern struct pwc_decompressor *pwc_find_decompressor(int type);
-
-#ifdef CONFIG_USB_PWCX
-/* If the decompressor is compiled in, we must call these manually */
-extern int usb_pwcx_init(void);
-extern void usb_pwcx_exit(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff -Nru a/drivers/usb/pwc.h b/drivers/usb/pwc.h
--- a/drivers/usb/pwc.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,267 +0,0 @@
-/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef PWC_H
-#define PWC_H
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/spinlock.h>
-#include <linux/videodev.h>
-#include <linux/wait.h>
-#include <linux/smp_lock.h>
-
-#include <asm/semaphore.h>
-#include <asm/errno.h>
-
-/* Defines and structures for the Philips webcam */
-/* Used for checking memory corruption/pointer validation */
-#define PWC_MAGIC 0x89DC10ABUL
-#undef PWC_MAGIC
-
-/* Turn some debugging options on/off */
-#define PWC_DEBUG 0
-
-/* Trace certain actions in the driver */
-#define TRACE_MODULE	0x0001
-#define TRACE_PROBE	0x0002
-#define TRACE_OPEN	0x0004
-#define TRACE_READ	0x0008
-#define TRACE_MEMORY	0x0010
-#define TRACE_FLOW	0x0020
-#define TRACE_SIZE	0x0040
-#define TRACE_PWCX	0x0080
-#define TRACE_SEQUENCE	0x1000
-
-#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
-#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
-#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
-#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
-
-
-/* Defines for ToUCam cameras */
-#define TOUCAM_HEADER_SIZE		8
-#define TOUCAM_TRAILER_SIZE		4
-
-/* Version block */
-#define PWC_MAJOR	8
-#define PWC_MINOR	5
-#define PWC_VERSION 	"8.5"
-#define PWC_NAME 	"pwc"
-
-/* Turn certain features on/off */
-#define PWC_INT_PIPE 0
-
-/* Ignore errors in the first N frames, to allow for startup delays */
-#define FRAME_LOWMARK 5
-
-/* Size and number of buffers for the ISO pipe. */
-#define MAX_ISO_BUFS		2
-#define ISO_FRAMES_PER_DESC	10
-#define ISO_MAX_FRAME_SIZE	960
-#define ISO_BUFFER_SIZE 	(ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
-
-/* Frame buffers: contains compressed or uncompressed video data. */
-#define MAX_FRAMES		5
-/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
-#define PWC_FRAME_SIZE 		(460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
-
-/* Absolute maximum number of buffers available for mmap() */
-#define MAX_IMAGES 		4
-
-struct pwc_coord
-{
-	int x, y;		/* guess what */
-	int size;		/* size, or offset */
-};
-
-/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
-struct pwc_iso_buf
-{
-	void *data;
-	int  length;
-	int  read;
-	struct urb *urb;
-};
-
-/* intermediate buffers with raw data from the USB cam */
-struct pwc_frame_buf
-{
-   void *data;
-   volatile int filled;		/* number of bytes filled */
-   struct pwc_frame_buf *next;	/* list */
-#if PWC_DEBUG
-   int sequence;		/* Sequence number */
-#endif
-};
-
-struct pwc_device
-{
-#ifdef PWC_MAGIC
-   int magic;
-#endif
-   /* Pointer to our usb_device */
-   struct usb_device *udev;
-   
-   int type;                    /* type of cam (645, 646, 675, 680, 690) */
-   int release;			/* release number */
-   int unplugged;		/* set when the plug is pulled */
-   int usb_init;		/* set when the cam has been initialized over USB */
-
-   /*** Video data ***/
-   int vopen;			/* flag */
-   struct video_device *vdev;
-   int vendpoint;		/* video isoc endpoint */
-   int vcinterface;		/* video control interface */
-   int valternate;		/* alternate interface needed */
-   int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
-   int vpalette;		/* YUV, RGB24, RGB32, etc */
-   int vframe_count;		/* received frames */
-   int vframes_dumped; 		/* counter for dumped frames */
-   int vframes_error;		/* frames received in error */
-   int vmax_packet_size;	/* USB maxpacket size */
-   int vlast_packet_size;	/* for frame synchronisation */
-   int vcompression;		/* desired compression factor */
-   int vbandlength;		/* compressed band length; 0 is uncompressed */
-   char vsnapshot;		/* snapshot mode */
-   char vsync;			/* used by isoc handler */
-   
-   /* The image acquisition requires 3 to 4 steps:
-      1. data is gathered in short packets from the USB controller
-      2. data is synchronized and packed into a frame buffer
-      3a. in case data is compressed, decompress it directly into image buffer
-      3b. in case data is uncompressed, copy into image buffer with viewport
-      4. data is transfered to the user process
-
-      Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES.... 
-      We have in effect a back-to-back-double-buffer system.
-    */
-   /* 1: isoc */
-   struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
-   char iso_init;
-   
-   /* 2: frame */
-   struct pwc_frame_buf *fbuf;	/* all frames */
-   struct pwc_frame_buf *empty_frames, *empty_frames_tail;	/* all empty frames */
-   struct pwc_frame_buf *full_frames, *full_frames_tail;	/* all filled frames */
-   struct pwc_frame_buf *fill_frame;	/* frame currently being filled */
-   struct pwc_frame_buf *read_frame;	/* frame currently read by user process */
-   int frame_size;
-   int frame_header_size, frame_trailer_size;
-   int drop_frames;
-#if PWC_DEBUG
-   int sequence;			/* Debugging aid */
-#endif
-   
-   /* 3: decompression */
-   struct pwc_decompressor *decompressor;	/* function block with decompression routines */
-   void *decompress_data;		/* private data for decompression engine */
-
-   /* 4: image */
-   /* We have an 'image' and a 'view', where 'image' is the fixed-size image
-      as delivered by the camera, and 'view' is the size requested by the
-      program. The camera image is centered in this viewport, laced with 
-      a gray or black border. view_min <= image <= view <= view_max;
-    */
-   int image_mask;			/* bitmask of supported sizes */
-   struct pwc_coord view_min, view_max;	/* minimum and maximum sizes */
-   struct pwc_coord image, view;	/* image and viewport size */
-   struct pwc_coord offset;		/* offset within the viewport */
-
-   void *image_data;			/* total buffer, which is subdivided into ... */
-   void *image_ptr[MAX_IMAGES];		/* ...several images... */
-   int fill_image;			/* ...which are rotated. */
-   int len_per_image;			/* length per image */
-   int image_read_pos;			/* In case we read data in pieces, keep track of were we are in the imagebuffer */
-   int image_used[MAX_IMAGES];		/* For MCAPTURE and SYNC */
-
-   struct semaphore modlock;		/* to prevent races in video_open(), etc */
-   spinlock_t ptrlock;			/* for manipulating the buffer pointers */
-
-   /*** Misc. data ***/
-   wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
-   wait_queue_head_t remove_ok;		/* When we got hot unplugged, we have to avoid a few race conditions */
-#if PWC_INT_PIPE
-   void *usb_int_handler;		/* for the interrupt endpoint */
-#endif   
-};
-
-/* Enumeration of image sizes */
-#define PSZ_SQCIF	0x00
-#define PSZ_QSIF	0x01
-#define PSZ_QCIF	0x02
-#define PSZ_SIF		0x03
-#define PSZ_CIF		0x04
-#define PSZ_VGA		0x05
-#define PSZ_MAX		6
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Global variables */
-extern int pwc_trace;
-extern int pwc_preferred_compression;
-
-/** functions in pwc-if.c */
-int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
-
-/** Functions in pwc-misc.c */
-/* sizes in pixels */
-extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
-
-int pwc_decode_size(struct pwc_device *pdev, int width, int height);
-void pwc_construct(struct pwc_device *pdev);
-
-/** Functions in pwc-ctrl.c */
-/* Request a certain video mode. Returns < 0 if not possible */
-extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
-/* Calculate the number of bytes per image (not frame) */
-extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
-
-/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
-extern int pwc_get_brightness(struct pwc_device *pdev);
-extern int pwc_set_brightness(struct pwc_device *pdev, int value);
-extern int pwc_get_contrast(struct pwc_device *pdev);
-extern int pwc_set_contrast(struct pwc_device *pdev, int value);
-extern int pwc_get_gamma(struct pwc_device *pdev);
-extern int pwc_set_gamma(struct pwc_device *pdev, int value);
-extern int pwc_get_saturation(struct pwc_device *pdev);
-extern int pwc_set_saturation(struct pwc_device *pdev, int value);
-extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
-extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
-
-/* Power down or up the camera; not supported by all models */
-extern int pwc_camera_power(struct pwc_device *pdev, int power);
-
-/* Private ioctl()s; see pwc-ioctl.h */
-extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
-
-
-/** pwc-uncompress.c */
-/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
-extern int pwc_decompress(struct pwc_device *pdev);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif
diff -Nru a/drivers/usb/pwc_kiara.h b/drivers/usb/pwc_kiara.h
--- a/drivers/usb/pwc_kiara.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,270 +0,0 @@
-   /* SQCIF */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
-   /* QSIF */
-   {
-      /* 5 fps */
-      {
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-      },
-      /* 10 fps */
-      {
-         {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
-         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-      },
-      /* 15 fps */
-      {
-         {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
-         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
-         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
-         {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
-      },
-      /* 20 fps */
-      {
-         {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
-         {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
-         {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
-         {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
-      },
-      /* 25 fps */
-      {
-         {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
-         {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
-         {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
-         {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
-      },
-      /* 30 fps */
-      {
-         {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
-         {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
-         {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
-         {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
-      },
-   },
-   /* QCIF */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
-   /* SIF */
-   {
-      /* 5 fps */
-      {
-         {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
-         {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
-         {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
-         {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
-         {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
-         {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
-         {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
-         {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
-         {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
-         {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
-         {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
-         {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
-         {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
-         {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
-      },
-   },
-   /* CIF */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
-   /* VGA */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
-         {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
-         {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
-         {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
-         {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
-         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
-         {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
diff -Nru a/drivers/usb/pwc_nala.h b/drivers/usb/pwc_nala.h
--- a/drivers/usb/pwc_nala.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,66 +0,0 @@
-   /* SQCIF */
-   {
-      {0, 0, {0x04, 0x01, 0x03}},
-      {8, 0, {0x05, 0x01, 0x03}},
-      {7, 0, {0x08, 0x01, 0x03}},
-      {7, 0, {0x0A, 0x01, 0x03}},
-      {6, 0, {0x0C, 0x01, 0x03}},
-      {5, 0, {0x0F, 0x01, 0x03}},
-      {4, 0, {0x14, 0x01, 0x03}},
-      {3, 0, {0x18, 0x01, 0x03}},
-   },
-   /* QSIF */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
-   /* QCIF */
-   {
-      {0, 0, {0x04, 0x01, 0x02}},
-      {8, 0, {0x05, 0x01, 0x02}},
-      {7, 0, {0x08, 0x01, 0x02}},
-      {6, 0, {0x0A, 0x01, 0x02}},
-      {5, 0, {0x0C, 0x01, 0x02}},
-      {4, 0, {0x0F, 0x01, 0x02}},
-      {1, 0, {0x14, 0x01, 0x02}},
-      {1, 0, {0x18, 0x01, 0x02}},
-   },
-   /* SIF */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
-   /* CIF */
-   {
-      {4, 0, {0x04, 0x01, 0x01}},
-      {7, 1, {0x05, 0x03, 0x01}},
-      {6, 1, {0x08, 0x03, 0x01}},
-      {4, 1, {0x0A, 0x03, 0x01}},
-      {3, 1, {0x0C, 0x03, 0x01}},
-      {2, 1, {0x0F, 0x03, 0x01}},
-      {0},
-      {0},
-   },
-   /* VGA */
-   {  
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
diff -Nru a/drivers/usb/pwc_timon.h b/drivers/usb/pwc_timon.h
--- a/drivers/usb/pwc_timon.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,270 +0,0 @@
-   /* SQCIF */
-   {
-      /* 5 fps */
-      {
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-      },
-   },
-   /* QSIF */
-   {
-      /* 5 fps */
-      {
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
-         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
-         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
-         {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-         {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
-         {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-         {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
-         {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
-         {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
-         {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
-      },
-   },
-   /* QCIF */
-   {
-      /* 5 fps */
-      {
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
-         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-         {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
-         {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
-         {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
-         {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
-         {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
-         {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
-         {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-         {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
-         {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
-         {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
-      },
-   },
-   /* SIF */
-   {
-      /* 5 fps */
-      {
-         {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
-         {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
-         {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
-         {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
-         {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
-         {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
-         {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
-         {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
-         {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
-         {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
-         {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
-         {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
-         {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
-         {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
-      },
-   },
-   /* CIF */
-   {
-      /* 5 fps */
-      {
-         {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
-         {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
-         {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
-         {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
-         {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
-         {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
-         {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
-         {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
-         {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
-         {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
-         {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
-         {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
-         {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
-         {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
-      },
-   },
-   /* VGA */
-   {
-      /* 5 fps */
-      {
-         {0, },
-         {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
-         {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
-         {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
-      },
-      /* 10 fps */
-      {
-         {0, },
-         {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
-         {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
-         {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-         {0, },
-         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
-         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
-         {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
-      },
-      /* 20 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 25 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-      /* 30 fps */
-      {
-         {0, },
-         {0, },
-         {0, },
-         {0, },
-      },
-   },
diff -Nru a/drivers/usb/rio500.c b/drivers/usb/rio500.c
--- a/drivers/usb/rio500.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,550 +0,0 @@
-/* -*- linux-c -*- */
-
-/* 
- * Driver for USB Rio 500
- *
- * Cesar Miquel (miquel@df.uba.ar)
- * 
- * based on hp_scanner.c by David E. Nelson (dnelson@jump.net)
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
- *
- * */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-
-#include "rio500_usb.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
-#define DRIVER_AUTHOR "Cesar Miquel <miquel@df.uba.ar>"
-#define DRIVER_DESC "USB Rio 500 driver"
-
-#define RIO_MINOR   64
-
-/* stall/wait timeout for rio */
-#define NAK_TIMEOUT (HZ)
-
-#define IBUF_SIZE 0x1000
-
-/* Size of the rio buffer */
-#define OBUF_SIZE 0x10000
-
-struct rio_usb_data {
-        struct usb_device *rio_dev;     /* init: probe_rio */
-        devfs_handle_t devfs;           /* devfs device */
-        unsigned int ifnum;             /* Interface number of the USB device */
-        int isopen;                     /* nz if open */
-        int present;                    /* Device is present on the bus */
-        char *obuf, *ibuf;              /* transfer buffers */
-        char bulk_in_ep, bulk_out_ep;   /* Endpoint assignments */
-        wait_queue_head_t wait_q;       /* for timeouts */
-	struct semaphore lock;          /* general race avoidance */
-};
-
-extern devfs_handle_t usb_devfs_handle;	/* /dev/usb dir. */
-
-static struct rio_usb_data rio_instance;
-
-static int open_rio(struct inode *inode, struct file *file)
-{
-	struct rio_usb_data *rio = &rio_instance;
-
-	lock_kernel();
-
-	if (rio->isopen || !rio->present) {
-		unlock_kernel();
-		return -EBUSY;
-	}
-	rio->isopen = 1;
-
-	init_waitqueue_head(&rio->wait_q);
-
-	MOD_INC_USE_COUNT;
-
-	unlock_kernel();
-
-	info("Rio opened.");
-
-	return 0;
-}
-
-static int close_rio(struct inode *inode, struct file *file)
-{
-	struct rio_usb_data *rio = &rio_instance;
-
-	rio->isopen = 0;
-
-	MOD_DEC_USE_COUNT;
-
-	info("Rio closed.");
-	return 0;
-}
-
-static int
-ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
-	  unsigned long arg)
-{
-	struct RioCommand rio_cmd;
-	struct rio_usb_data *rio = &rio_instance;
-	void *data;
-	unsigned char *buffer;
-	int result, requesttype;
-	int retries;
-	int retval=0;
-
-	down(&(rio->lock));
-        /* Sanity check to make sure rio is connected, powered, etc */
-        if ( rio == NULL ||
-             rio->present == 0 ||
-             rio->rio_dev == NULL )
-	{
-		retval = -ENODEV;
-		goto err_out;
-	}
-
-	switch (cmd) {
-	case RIO_RECV_COMMAND:
-		data = (void *) arg;
-		if (data == NULL)
-			break;
-		if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
-			retval = -EFAULT;
-			goto err_out;
-		}
-		if (rio_cmd.length > PAGE_SIZE) {
-			retval = -EINVAL;
-			goto err_out;
-		}
-		buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
-		if (buffer == NULL) {
-			retval = -ENOMEM;
-			goto err_out;
-		}
-		if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
-			retval = -EFAULT;
-			free_page((unsigned long) buffer);
-			goto err_out;
-		}
-
-		requesttype = rio_cmd.requesttype | USB_DIR_IN |
-		    USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-		dbg
-		    ("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
-		     requesttype, rio_cmd.request, rio_cmd.value,
-		     rio_cmd.index, rio_cmd.length);
-		/* Send rio control message */
-		retries = 3;
-		while (retries) {
-			result = usb_control_msg(rio->rio_dev,
-						 usb_rcvctrlpipe(rio-> rio_dev, 0),
-						 rio_cmd.request,
-						 requesttype,
-						 rio_cmd.value,
-						 rio_cmd.index, buffer,
-						 rio_cmd.length,
-						 rio_cmd.timeout);
-			if (result == -ETIMEDOUT)
-				retries--;
-			else if (result < 0) {
-				err("Error executing ioctrl. code = %d",
-				     le32_to_cpu(result));
-				retries = 0;
-			} else {
-				dbg("Executed ioctl. Result = %d (data=%04x)",
-				     le32_to_cpu(result),
-				     le32_to_cpu(*((long *) buffer)));
-				if (copy_to_user(rio_cmd.buffer, buffer,
-						 rio_cmd.length)) {
-					free_page((unsigned long) buffer);
-					retval = -EFAULT;
-					goto err_out;
-				}
-				retries = 0;
-			}
-
-			/* rio_cmd.buffer contains a raw stream of single byte
-			   data which has been returned from rio.  Data is
-			   interpreted at application level.  For data that
-			   will be cast to data types longer than 1 byte, data
-			   will be little_endian and will potentially need to
-			   be swapped at the app level */
-
-		}
-		free_page((unsigned long) buffer);
-		break;
-
-	case RIO_SEND_COMMAND:
-		data = (void *) arg;
-		if (data == NULL)
-			break;
-		if (copy_from_user(&rio_cmd, data, sizeof(struct RioCommand))) {
-			retval = -EFAULT;
-			goto err_out;
-		}
-		if (rio_cmd.length > PAGE_SIZE) {
-			retval = -EINVAL;
-			goto err_out;
-		}
-		buffer = (unsigned char *) __get_free_page(GFP_KERNEL);
-		if (buffer == NULL) {
-			retval = -ENOMEM;
-			goto err_out;
-		}
-		if (copy_from_user(buffer, rio_cmd.buffer, rio_cmd.length)) {
-			free_page((unsigned long)buffer);
-			retval = -EFAULT;
-			goto err_out;
-		}
-
-		requesttype = rio_cmd.requesttype | USB_DIR_OUT |
-		    USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-		dbg("sending command: reqtype=%0x req=%0x value=%0x index=%0x len=%0x",
-		     requesttype, rio_cmd.request, rio_cmd.value,
-		     rio_cmd.index, rio_cmd.length);
-		/* Send rio control message */
-		retries = 3;
-		while (retries) {
-			result = usb_control_msg(rio->rio_dev,
-						 usb_sndctrlpipe(rio-> rio_dev, 0),
-						 rio_cmd.request,
-						 requesttype,
-						 rio_cmd.value,
-						 rio_cmd.index, buffer,
-						 rio_cmd.length,
-						 rio_cmd.timeout);
-			if (result == -ETIMEDOUT)
-				retries--;
-			else if (result < 0) {
-				err("Error executing ioctrl. code = %d",
-				     le32_to_cpu(result));
-				retries = 0;
-			} else {
-				dbg("Executed ioctl. Result = %d",
-				       le32_to_cpu(result));
-				retries = 0;
-
-			}
-
-		}
-		free_page((unsigned long) buffer);
-		break;
-
-	default:
-		retval = -ENOTTY;
-		break;
-	}
-
-
-err_out:
-	up(&(rio->lock));
-	return retval;
-}
-
-static ssize_t
-write_rio(struct file *file, const char *buffer,
-	  size_t count, loff_t * ppos)
-{
-	struct rio_usb_data *rio = &rio_instance;
-
-	unsigned long copy_size;
-	unsigned long bytes_written = 0;
-	unsigned int partial;
-
-	int result = 0;
-	int maxretry;
-	int errn = 0;
-
-	down(&(rio->lock));
-        /* Sanity check to make sure rio is connected, powered, etc */
-        if ( rio == NULL ||
-             rio->present == 0 ||
-             rio->rio_dev == NULL )
-	{
-		up(&(rio->lock));
-		return -ENODEV;
-	}
-
-
-
-	do {
-		unsigned long thistime;
-		char *obuf = rio->obuf;
-
-		thistime = copy_size =
-		    (count >= OBUF_SIZE) ? OBUF_SIZE : count;
-		if (copy_from_user(rio->obuf, buffer, copy_size)) {
-			errn = -EFAULT;
-			goto error;
-		}
-		maxretry = 5;
-		while (thistime) {
-			if (!rio->rio_dev) {
-				errn = -ENODEV;
-				goto error;
-			}
-			if (signal_pending(current)) {
-				up(&(rio->lock));
-				return bytes_written ? bytes_written : -EINTR;
-			}
-
-			result = usb_bulk_msg(rio->rio_dev,
-					 usb_sndbulkpipe(rio->rio_dev, 2),
-					 obuf, thistime, &partial, 5 * HZ);
-
-			dbg("write stats: result:%d thistime:%lu partial:%u",
-			     result, thistime, partial);
-
-			if (result == -ETIMEDOUT) {	/* NAK - so hold for a while */
-				if (!maxretry--) {
-					errn = -ETIME;
-					goto error;
-				}
-				interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
-				continue;
-			} else if (!result & partial) {
-				obuf += partial;
-				thistime -= partial;
-			} else
-				break;
-		};
-		if (result) {
-			err("Write Whoops - %x", result);
-			errn = -EIO;
-			goto error;
-		}
-		bytes_written += copy_size;
-		count -= copy_size;
-		buffer += copy_size;
-	} while (count > 0);
-
-	up(&(rio->lock));
-
-	return bytes_written ? bytes_written : -EIO;
-
-error:
-	up(&(rio->lock));
-	return errn;
-}
-
-static ssize_t
-read_rio(struct file *file, char *buffer, size_t count, loff_t * ppos)
-{
-	struct rio_usb_data *rio = &rio_instance;
-	ssize_t read_count;
-	unsigned int partial;
-	int this_read;
-	int result;
-	int maxretry = 10;
-	char *ibuf;
-
-	down(&(rio->lock));
-	/* Sanity check to make sure rio is connected, powered, etc */
-        if ( rio == NULL ||
-             rio->present == 0 ||
-             rio->rio_dev == NULL )
-	{
-		up(&(rio->lock));
-		return -ENODEV;
-	}
-
-	ibuf = rio->ibuf;
-
-	read_count = 0;
-
-
-	while (count > 0) {
-		if (signal_pending(current)) {
-			up(&(rio->lock));
-			return read_count ? read_count : -EINTR;
-		}
-		if (!rio->rio_dev) {
-			up(&(rio->lock));
-			return -ENODEV;
-		}
-		this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-
-		result = usb_bulk_msg(rio->rio_dev,
-				      usb_rcvbulkpipe(rio->rio_dev, 1),
-				      ibuf, this_read, &partial,
-				      (int) (HZ * 8));
-
-		dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
-		       result, this_read, partial);
-
-		if (partial) {
-			count = this_read = partial;
-		} else if (result == -ETIMEDOUT || result == 15) {	/* FIXME: 15 ??? */
-			if (!maxretry--) {
-				up(&(rio->lock));
-				err("read_rio: maxretry timeout");
-				return -ETIME;
-			}
-			interruptible_sleep_on_timeout(&rio->wait_q,
-						       NAK_TIMEOUT);
-			continue;
-		} else if (result != -EREMOTEIO) {
-			up(&(rio->lock));
-			err("Read Whoops - result:%u partial:%u this_read:%u",
-			     result, partial, this_read);
-			return -EIO;
-		} else {
-			up(&(rio->lock));
-			return (0);
-		}
-
-		if (this_read) {
-			if (copy_to_user(buffer, ibuf, this_read)) {
-				up(&(rio->lock));
-				return -EFAULT;
-			}
-			count -= this_read;
-			read_count += this_read;
-			buffer += this_read;
-		}
-	}
-	up(&(rio->lock));
-	return read_count;
-}
-
-static struct
-file_operations usb_rio_fops = {
-	read:		read_rio,
-	write:		write_rio,
-	ioctl:		ioctl_rio,
-	open:		open_rio,
-	release:	close_rio,
-};
-
-static void *probe_rio(struct usb_device *dev, unsigned int ifnum,
-		       const struct usb_device_id *id)
-{
-	struct rio_usb_data *rio = &rio_instance;
-
-	info("USB Rio found at address %d", dev->devnum);
-
-	rio->present = 1;
-	rio->rio_dev = dev;
-
-	if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-		err("probe_rio: Not enough memory for the output buffer");
-		return NULL;
-	}
-	dbg("probe_rio: obuf address:%p", rio->obuf);
-
-	if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-		err("probe_rio: Not enough memory for the input buffer");
-		kfree(rio->obuf);
-		return NULL;
-	}
-	dbg("probe_rio: ibuf address:%p", rio->ibuf);
-
-	rio->devfs = devfs_register(usb_devfs_handle, "rio500",
-				    DEVFS_FL_DEFAULT, USB_MAJOR,
-				    RIO_MINOR,
-				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				    S_IWGRP, &usb_rio_fops, NULL);
-	if (rio->devfs == NULL)
-		dbg("probe_rio: device node registration failed");
-
-	init_MUTEX(&(rio->lock));
-
-	return rio;
-}
-
-static void disconnect_rio(struct usb_device *dev, void *ptr)
-{
-	struct rio_usb_data *rio = (struct rio_usb_data *) ptr;
-
-	devfs_unregister(rio->devfs);
-
-	down(&(rio->lock));
-	if (rio->isopen) {
-		rio->isopen = 0;
-		/* better let it finish - the release will do whats needed */
-		rio->rio_dev = NULL;
-		up(&(rio->lock));
-		return;
-	}
-	kfree(rio->ibuf);
-	kfree(rio->obuf);
-
-	info("USB Rio disconnected.");
-
-	rio->present = 0;
-	up(&(rio->lock));
-}
-
-static struct usb_device_id rio_table [] = {
-	{ USB_DEVICE(0x0841, 1) }, 		/* Rio 500 */
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, rio_table);
-
-static struct usb_driver rio_driver = {
-	name:		"rio500",
-	probe:		probe_rio,
-	disconnect:	disconnect_rio,
-	fops:		&usb_rio_fops,
-	minor:		RIO_MINOR,
-	id_table:	rio_table,
-};
-
-int usb_rio_init(void)
-{
-	if (usb_register(&rio_driver) < 0)
-		return -1;
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return 0;
-}
-
-
-void usb_rio_cleanup(void)
-{
-	struct rio_usb_data *rio = &rio_instance;
-
-	rio->present = 0;
-	usb_deregister(&rio_driver);
-
-
-}
-
-module_init(usb_rio_init);
-module_exit(usb_rio_cleanup);
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/rio500_usb.h b/drivers/usb/rio500_usb.h
--- a/drivers/usb/rio500_usb.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,37 +0,0 @@
-/*  ----------------------------------------------------------------------
-
-    Copyright (C) 2000  Cesar Miquel  (miquel@df.uba.ar)
-
-    This program is free software; you can redistribute it and/or 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.
-
-    ---------------------------------------------------------------------- */
-
-
-
-#define RIO_SEND_COMMAND			0x1
-#define RIO_RECV_COMMAND			0x2
-
-#define RIO_DIR_OUT               	        0x0
-#define RIO_DIR_IN				0x1
-
-struct RioCommand {
-	short length;
-	int request;
-	int requesttype;
-	int value;
-	int index;
-	void *buffer;
-	int timeout;
-};
diff -Nru a/drivers/usb/scanner.c b/drivers/usb/scanner.c
--- a/drivers/usb/scanner.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1125 +0,0 @@
-/* -*- linux-c -*- */
-
-/* 
- * Driver for USB Scanners (linux-2.4.12)
- *
- * Copyright (C) 1999, 2000, 2001 David E. Nelson
- *
- * Portions may be copyright Brad Keryan and Michael Gee.
- *
- * David E. Nelson (dnelson@jump.net)
- * 
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Originally based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
- *
- * History
- *
- *  0.1  8/31/1999
- *
- *    Developed/tested using linux-2.3.15 with minor ohci.c changes to
- *    support short packes during bulk xfer mode.  Some testing was
- *    done with ohci-hcd but the performace was low.  Very limited
- *    testing was performed with uhci but I was unable to get it to
- *    work.  Initial relase to the linux-usb development effort.
- *
- *
- *  0.2  10/16/1999
- *
- *    - Device can't be opened unless a scanner is plugged into the USB.
- *    - Finally settled on a reasonable value for the I/O buffer's.
- *    - Cleaned up write_scanner()
- *    - Disabled read/write stats
- *    - A little more code cleanup
- *
- *
- *  0.3  10/18/1999
- *
- *    - Device registration changed to reflect new device
- *      allocation/registration for linux-2.3.22+.
- *    - Adopted David Brownell's <david-b@pacbell.net> technique for 
- *      assigning bulk endpoints.
- *    - Removed unnessesary #include's
- *    - Scanner model now reported via syslog INFO after being detected 
- *      *and* configured.
- *    - Added user specified vendor:product USB ID's which can be passed 
- *      as module parameters.
- *
- *
- *  0.3.1
- *
- *    - Applied patches for linux-2.3.25.
- *    - Error number reporting changed to reflect negative return codes.
- *
- *
- *  0.3.2
- *
- *    - Applied patches for linux-2.3.26 to scanner_init().
- *    - Debug read/write stats now report values as signed decimal.
- *
- *
- *  0.3.3
- *
- *    - Updated the bulk_msg() calls to usb usb_bulk_msg().
- *    - Added a small delay in the write_scanner() method to aid in
- *      avoiding NULL data reads on HP scanners.  We'll see how this works.
- *    - Return values from usb_bulk_msg() now ignore positive values for
- *      use with the ohci driver.
- *    - Added conditional debugging instead of commenting/uncommenting
- *      all over the place.
- *    - kfree()'d the pointer after using usb_string() as documented in
- *      linux-usb-api.txt.
- *    - Added usb_set_configuration().  It got lost in version 0.3 -- ack!
- *    - Added the HP 5200C USB Vendor/Product ID's.
- *
- *
- *  0.3.4  1/23/2000
- *
- *    - Added Greg K-H's <greg@kroah.com> patch for better handling of 
- *      Product/Vendor detection.
- *    - The driver now autoconfigures its endpoints including interrupt
- *      endpoints if one is detected.  The concept was originally based
- *      upon David Brownell's method.
- *    - Added some Seiko/Epson ID's. Thanks to Karl Heinz 
- *      Kremer <khk@khk.net>.
- *    - Added some preliminary ioctl() calls for the PV8630 which is used
- *      by the HP4200. The ioctl()'s still have to be registered. Thanks 
- *      to Adrian Perez Jorge <adrianpj@easynews.com>.
- *    - Moved/migrated stuff to scanner.h
- *    - Removed the usb_set_configuration() since this is handled by
- *      the usb_new_device() routine in usb.c.
- *    - Added the HP 3300C.  Thanks to Bruce Tenison.
- *    - Changed user specified vendor/product id so that root hub doesn't
- *      get falsely attached to. Thanks to Greg K-H.
- *    - Added some Mustek ID's. Thanks to Gernot Hoyler 
- *      <Dr.Hoyler@t-online.de>.
- *    - Modified the usb_string() reporting.  See kfree() comment above.
- *    - Added Umax Astra 2000U. Thanks to Doug Alcorn <doug@lathi.net>.
- *    - Updated the printk()'s to use the info/warn/dbg macros.
- *    - Updated usb_bulk_msg() argument types to fix gcc warnings.
- *
- *
- *  0.4  2/4/2000
- *
- *    - Removed usb_string() from probe_scanner since the core now does a
- *      good job of reporting what was connnected.  
- *    - Finally, simultaneous multiple device attachment!
- *    - Fixed some potential memory freeing issues should memory allocation
- *      fail in probe_scanner();
- *    - Some fixes to disconnect_scanner().
- *    - Added interrupt endpoint support.
- *    - Added Agfa SnapScan Touch. Thanks to Jan Van den Bergh
- *      <jan.vandenbergh@cs.kuleuven.ac.be>.
- *    - Added Umax 1220U ID's. Thanks to Maciek Klimkowski
- *      <mac@nexus.carleton.ca>.
- *    - Fixed bug in write_scanner(). The buffer was not being properly
- *      updated for writes larger than OBUF_SIZE. Thanks to Henrik 
- *      Johansson <henrikjo@post.utfors.se> for identifying it.
- *    - Added Microtek X6 ID's. Thanks to Oliver Neukum
- *      <Oliver.Neukum@lrz.uni-muenchen.de>.
- *
- * 
- *  0.4.1  2/15/2000
- *  
- *    - Fixed 'count' bug in read_scanner(). Thanks to Henrik
- *      Johansson <henrikjo@post.utfors.se> for identifying it.  Amazing
- *      it has worked this long.
- *    - Fixed '>=' bug in both read/write_scanner methods.
- *    - Cleaned up both read/write_scanner() methods so that they are 
- *      a little more readable.
- *    - Added a lot of Microtek ID's.  Thanks to Adrian Perez Jorge.
- *    - Adopted the __initcall().
- *    - Added #include <linux/init.h> to scanner.h for __initcall().
- *    - Added one liner in irq_scanner() to keep gcc from complaining 
- *      about an unused variable (data) if debugging was disabled
- *      in scanner.c.
- *    - Increased the timeout parameter in read_scanner() to 120 Secs.
- *
- *
- *  0.4.2  3/23/2000
- *
- *    - Added Umax 1236U ID.  Thanks to Philipp Baer <ph_baer@npw.net>.
- *    - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's.
- *      Thanks to Adrian Perez Jorge <adrianpj@easynews.com>.
- *    - Fixed error number reported for non-existant devices.  Thanks to
- *      Spyridon Papadimitriou <Spyridon_Papadimitriou@gs91.sp.cs.cmu.edu>.
- *    - Added Acer Prisascan 620U ID's.  Thanks to Joao <joey@knoware.nl>.
- *    - Replaced __initcall() with module_init()/module_exit(). Updates
- *      from patch-2.3.48.
- *    - Replaced file_operations structure with new syntax.  Updates
- *      from patch-2.3.49.
- *    - Changed #include "usb.h" to #include <linux/usb.h>
- *    - Added #define SCN_IOCTL to exclude development areas 
- *      since 2.4.x is about to be released. This mainly affects the 
- *      ioctl() stuff.  See scanner.h for more details.
- *    - Changed the return value for signal_pending() from -ERESTARTSYS to
- *      -EINTR.
- *
- *
- * 0.4.3  4/30/2000
- *
- *    - Added Umax Astra 2200 ID.  Thanks to Flynn Marquardt 
- *      <flynn@isr.uni-stuttgart.de>.
- *    - Added iVina 1200U ID. Thanks to Dyson Lin <dyson@avision.com.tw>.
- *    - Added access time update for the device file courtesy of Paul
- *      Mackerras <paulus@samba.org>.  This allows a user space daemon
- *      to turn the lamp off for a Umax 1220U scanner after a prescribed
- *      time.
- *    - Fixed HP S20 ID's.  Thanks to Ruud Linders <rlinders@xs4all.nl>.
- *    - Added Acer ScanPrisa 620U ID. Thanks to Oliver
- *      Schwartz <Oliver.Schwartz@gmx.de> via sane-devel mail list.
- *    - Fixed bug in read_scanner for copy_to_user() function.  The returned
- *      value should be 'partial' not 'this_read'.
- *    - Fixed bug in read_scanner. 'count' should be decremented 
- *      by 'this_read' and not by 'partial'.  This resulted in twice as many
- *      calls to read_scanner() for small amounts of data and possibly
- *      unexpected returns of '0'.  Thanks to Karl Heinz 
- *      Kremer <khk@khk.net> and Alain Knaff <Alain.Knaff@ltnb.lu>
- *      for discovering this.
- *    - Integrated Randy Dunlap's <randy.dunlap@intel.com> patch for a
- *      scanner lookup/ident table. Thanks Randy.
- *    - Documentation updates.
- *    - Added wait queues to read_scanner().
- *
- *
- * 0.4.3.1
- *
- *    - Fixed HP S20 ID's...again..sigh.  Thanks to Ruud
- *      Linders <rlinders@xs4all.nl>.
- *
- * 0.4.4
- *    - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB,
- *      and 1200 UB.  Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
- *    - Added the Vuego Scan Brisa 340U ID's.  Apparently this scanner is
- *      marketed by Acer Peripherals as a cheap 300 dpi model. Thanks to
- *      David Gundersen <gundersd@paradise.net.nz>.
- *    - Added the Epson Expression1600 ID's. Thanks to Karl Heinz
- *      Kremer <khk@khk.net>.
- *
- * 0.4.5  2/28/2001
- *    - Added Mustek ID's (BearPaw 2400, 1200 CU Plus, BearPaw 1200F).
- *      Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
- *    - Added read_timeout module parameter to override RD_NAK_TIMEOUT
- *      when read()'ing from devices.
- *    - Stalled pipes are now checked and cleared with
- *      usb_clear_halt() for the read_scanner() function. This should
- *      address the "funky result: -32" error messages.
- *    - Removed Microtek scanner ID's.  Microtek scanners are now
- *      supported via the drivers/usb/microtek.c driver.
- *    - Added scanner specific read timeout's.
- *    - Return status errors are NEGATIVE!!!  This should address the
- *      "funky result: -110" error messages.
- *    - Replaced USB_ST_TIMEOUT with ETIMEDOUT.
- *    - rd_nak was still defined in MODULE_PARM.  It's been updated with
- *      read_timeout.  Thanks to Mark W. Webb <markwebb@adelphia.net> for
- *      reporting this bug.
- *    - Added Epson Perfection 1640SU and 1640SU Photo.  Thanks to
- *      Jean-Luc <f5ibh@db0bm.ampr.org> and Manuel
- *      Pelayo <Manuel.Pelayo@sesips.org>. Reported to work fine by Manuel.
- *
- * 0.4.6  9/27/2001
- *    - Added IOCTL's to report back scanner USB ID's.  Thanks to
- *      Karl Heinz <khk@lynx.phpwebhosting.com>
- *    - Added Umax Astra 2100U ID's.  Thanks to Ron
- *      Wellsted <ron@wellsted.org.uk>.
- *      and Manuel Pelayo <Manuel.Pelayo@sesips.org>.
- *    - Added HP 3400 ID's. Thanks to Harald Hannelius <harald@iki.fi>
- *      and Bertrik Sikken <bertrik@zonnet.nl>.  Reported to work at
- *      htpp://home.zonnet.nl/bertrik/hp3300c/hp3300c.htm.
- *    - Added Minolta Dimage Scan Dual II ID's.  Thanks to Jose Paulo
- *      Moitinho de Almeida <moitinho@civil.ist.utl.pt>
- *    - Confirmed addition for SnapScan E20.  Thanks to Steffen Hübner
- *      <hueb_s@gmx.de>.
- *    - Added Lifetec LT9385 ID's.  Thanks to Van Bruwaene Kris
- *      <krvbr@yahoo.co.uk>
- *    - Added Agfa SnapScan e26 ID's.  Reported to work with SANE
- *      1.0.5.  Thanks to Falk Sauer <falk@mgnkatze.franken.de>.
- *    - Added HP 4300 ID's.  Thanks to Stefan Schlosser
- *      <castla@grmmbl.org>.
- *    - Added Relisis Episode ID's.  Thanks to Manfred
- *      Morgner <odb-devel@gmx.net>.
- *    - Added many Acer ID's. Thanks to Oliver
- *      Schwartz <Oliver.Schwartz@gmx.de>.
- *    - Added Snapscan e40 ID's.  Thanks to Oliver
- *      Schwartz <Oliver.Schwartz@gmx.de>.
- *    - Thanks to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
- *      for helping with races.
- *    - Added Epson Perfection 1650 ID's. Thanks to Karl Heinz
- *      Kremer <khk@khk.net>.
- *    - Added Epson Perfection 2450 ID's (aka GT-9700 for the Japanese
- *      market).  Thanks to Karl Heinz Kremer <khk@khk.net>.
- *    - Added Mustek 600 USB ID's.  Thanks to Marcus
- *      Alanen <maalanen@ra.abo.fi>.
- *    - Added Acer ScanPrisa 1240UT ID's.  Thanks to Morgan
- *      Collins <sirmorcant@morcant.org>.
- *    - Incorporated devfs patches!! Thanks to Tom Rini
- *      <trini@kernel.crashing.org>, Pavel Roskin <proski@gnu.org>,
- *      Greg KH <greg@kroah.com>, Yves Duret <yduret@mandrakesoft.com>,
- *      Flavio Stanchina <flavio.stanchina@tin.it>.
- *    - Removed Minolta ScanImage II.  This scanner uses USB SCSI.  Thanks
- *      to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de> for pointing
- *      this out.
- *    - Added additional SMP locking.  Thanks to David Brownell and 
- *      Oliver Neukum for their help.
- *    - Added version reporting - reports for both module load and modinfo
- *    - Started path to hopefully straighten/clean out ioctl()'s.
- *    - Users are now notified to consult the Documentation/usb/scanner.txt
- *      for common error messages rather than the maintainer.
- *
- * 0.4.7  11/28/2001
- *    - Fixed typo in Documentation/scanner.txt.  Thanks to
- *      Karel <karel.vervaeke@pandora.be> for pointing it out.
- *    - Added ID's for a Memorex 6136u. Thanks to Álvaro Gaspar de
- *      Valenzuela" <agaspard@utsi.edu>.
- *    - Added ID's for Agfa e25.  Thanks to Heinrich 
- *      Rust <Heinrich.Rust@gmx.de>.  Also reported to work with
- *      Linux and SANE (?).
- *    - Added Canon FB620U, D646U, and 1220U ID's.  Thanks to Paul
- *      Rensing <Paul_Rensing@StanfordAlumni.org>.  For more info
- *      on Linux support for these models, contact 
- *      salvestrini@users.sourceforge.net.
- *    - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
- *      ColorPage-HR6 V2 ID's in addition to many "Unknown" models
- *      under those vendors.  Thanks to
- *      Jaeger, Gerhard" <g.jaeger@earthling.net>.  These scanner are
- *      apparently based upon the LM983x IC's.
- *    - Applied Frank's patch that addressed some locking and module
- *      referencing counts.  Thanks to both
- *      Frank Zago <fzago@greshamstorage.com> and
- *      Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
- *
- * TODO
- *    - Performance
- *    - Select/poll methods
- *    - More testing
- *    - Proper registry/assignment for LM9830 ioctl's
- *
- *
- *  Thanks to:
- *
- *    - All the folks on the linux-usb list who put up with me. :)  This 
- *      has been a great learning experience for me.
- *    - To Linus Torvalds for this great OS.
- *    - The GNU folks.
- *    - The folks that forwarded Vendor:Product ID's to me.
- *    - Johannes Erdfelt for the loaning of a USB analyzer for tracking an
- *      issue with HP-4100 and uhci.
- *    - Adolfo Montero for his assistance.
- *    - All the folks who chimed in with reports and suggestions.
- *    - All the developers that are working on USB SANE backends or other
- *      applications to use USB scanners.
- *
- *  Performance:
- *
- *    System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner
- *            300 dpi scan of the entire bed
- *      24 Bit Color ~ 70 secs - 3.6 Mbit/sec
- *       8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
-
-#include <asm/byteorder.h>
-
-/* 
- * Scanner definitions, macros, module info, 
- * debug/ioctl/data_dump enable, and other constants.
- */ 
-#include "scanner.h"
-
-static void
-irq_scanner(struct urb *urb)
-{
-
-/*
- * For the meantime, this is just a placeholder until I figure out what
- * all I want to do with it -- or somebody else for that matter.
- */
-
-	struct scn_usb_data *scn;
-	unsigned char *data;
-	scn = urb->context;
-
-	data = &scn->button;
-	data += 0;		/* Keep gcc from complaining about unused var */
-
-	if (urb->status) {
-		return;
-	}
-
-	dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
-
-	return;
-}
-
-static int
-open_scanner(struct inode * inode, struct file * file)
-{
-	struct scn_usb_data *scn;
-	struct usb_device *dev;
-
-	int scn_minor;
-
-	int err=0;
-
-	MOD_INC_USE_COUNT;
-
-	down(&scn_mutex);
-
-	scn_minor = USB_SCN_MINOR(inode);
-
-	dbg("open_scanner: scn_minor:%d", scn_minor);
-
-	if (!p_scn_table[scn_minor]) {
-		up(&scn_mutex);
-		MOD_DEC_USE_COUNT;
-		err("open_scanner(%d): Unable to access minor data", scn_minor);
-		return -ENODEV;
-	}
-
-	scn = p_scn_table[scn_minor];
-
-	dev = scn->scn_dev;
-
-	down(&(scn->sem));	/* Now protect the scn_usb_data structure */ 
-
-	up(&scn_mutex); /* Now handled by the above */
-
-	if (!dev) {
-		err("open_scanner(%d): Scanner device not present", scn_minor);
-		err = -ENODEV;
-		goto out_error;
-	}
-
-	if (!scn->present) {
-		err("open_scanner(%d): Scanner is not present", scn_minor);
-		err = -ENODEV;
-		goto out_error;
-	}
-
-	if (scn->isopen) {
-		err("open_scanner(%d): Scanner device is already open", scn_minor);
-		err = -EBUSY;
-		goto out_error;
-	}
-
-	init_waitqueue_head(&scn->rd_wait_q);
-
-	scn->isopen = 1;
-
-	file->private_data = scn; /* Used by the read and write methods */
-
-
-out_error:
-
-	up(&(scn->sem)); /* Wake up any possible contending processes */
-
-	if (err)
-		MOD_DEC_USE_COUNT;
-
-	return err;
-}
-
-static int
-close_scanner(struct inode * inode, struct file * file)
-{
-	struct scn_usb_data *scn;
-
-	int scn_minor;
-
-	scn_minor = USB_SCN_MINOR (inode);
-
-	dbg("close_scanner: scn_minor:%d", scn_minor);
-
-	if (!p_scn_table[scn_minor]) {
-		err("close_scanner(%d): invalid scn_minor", scn_minor);
-		return -ENODEV;
-	}
-
-	down(&scn_mutex);
-
-	scn = p_scn_table[scn_minor];
-	down(&(scn->sem));
-	scn->isopen = 0;
-
-	file->private_data = NULL;
-
-	up(&scn_mutex);
-	up(&(scn->sem));
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-static ssize_t
-write_scanner(struct file * file, const char * buffer,
-              size_t count, loff_t *ppos)
-{
-	struct scn_usb_data *scn;
-	struct usb_device *dev;
-
-	ssize_t bytes_written = 0; /* Overall count of bytes written */
-	ssize_t ret = 0;
-
-	int scn_minor;
-
-	int this_write;		/* Number of bytes to write */
-	int partial;		/* Number of bytes successfully written */
-	int result = 0;
-
-	char *obuf;
-
-	scn = file->private_data;
-
-	down(&(scn->sem));
-
-	scn_minor = scn->scn_minor;
-
-	obuf = scn->obuf;
-
-	dev = scn->scn_dev;
-
-	file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-
-	while (count > 0) {
-
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-
-		this_write = (count >= OBUF_SIZE) ? OBUF_SIZE : count;
-
-		if (copy_from_user(scn->obuf, buffer, this_write)) {
-			ret = -EFAULT;
-			break;
-		}
-
-		result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, scn->bulk_out_ep), obuf, this_write, &partial, 60*HZ);
-		dbg("write stats(%d): result:%d this_write:%d partial:%d", scn_minor, result, this_write, partial);
-
-		if (result == -ETIMEDOUT) {	/* NAK -- shouldn't happen */
-			warn("write_scanner: NAK received.");
-			ret = result;
-			break;
-		} else if (result < 0) { /* We should not get any I/O errors */
-			warn("write_scanner(%d): funky result: %d. Consult Documentataion/usb/scanner.txt.", scn_minor, result);
-			ret = -EIO;
-			break;
-		}
-
-#ifdef WR_DATA_DUMP
-		if (partial) {
-			unsigned char cnt, cnt_max;
-			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump(%d): ", scn_minor);
-			for (cnt=0; cnt < cnt_max; cnt++) {
-				printk("%X ", obuf[cnt]);
-			}
-			printk("\n");
-		}
-#endif
-		if (partial != this_write) { /* Unable to write all contents of obuf */
-			ret = -EIO;
-			break;
-		}
-
-		if (partial) { /* Data written */
-			buffer += partial;
-			count -= partial;
-			bytes_written += partial;
-		} else { /* No data written */
-			ret = 0;
-			break;
-		}
-	}
-	up(&(scn->sem));
-	mdelay(5);		/* This seems to help with SANE queries */
-	return ret ? ret : bytes_written;
-}
-
-static ssize_t
-read_scanner(struct file * file, char * buffer,
-             size_t count, loff_t *ppos)
-{
-	struct scn_usb_data *scn;
-	struct usb_device *dev;
-
-	ssize_t bytes_read;	/* Overall count of bytes_read */
-	ssize_t ret;
-
-	int scn_minor;
-	int partial;		/* Number of bytes successfully read */
-	int this_read;		/* Max number of bytes to read */
-	int result;
-	int rd_expire = RD_EXPIRE;
-
-	char *ibuf;
-
-	scn = file->private_data;
-
-	down(&(scn->sem));
-
-	scn_minor = scn->scn_minor;
-
-	ibuf = scn->ibuf;
-
-	dev = scn->scn_dev;
-
-	bytes_read = 0;
-	ret = 0;
-
-	file->f_dentry->d_inode->i_atime = CURRENT_TIME; /* Update the
-                                                            atime of
-                                                            the device
-                                                            node */
-	while (count > 0) {
-		if (signal_pending(current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-
-		this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-
-		result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, scn->rd_nak_timeout);
-		dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", scn_minor, result, this_read, partial, count);
-
-/*
- * Scanners are sometimes inheriently slow since they are mechanical
- * in nature.  USB bulk reads tend to timeout while the scanner is
- * positioning, resetting, warming up the lamp, etc if the timeout is
- * set too low.  A very long timeout parameter for bulk reads was used
- * to overcome this limitation, but this sometimes resulted in folks
- * having to wait for the timeout to expire after pressing Ctrl-C from
- * an application. The user was sometimes left with the impression
- * that something had hung or crashed when in fact the USB read was
- * just waiting on data.  So, the below code retains the same long
- * timeout period, but splits it up into smaller parts so that
- * Ctrl-C's are acted upon in a reasonable amount of time.
- */
-
-		if (result == -ETIMEDOUT) { /* NAK */
-			if (!partial) { /* No data */
-				if (--rd_expire <= 0) {	/* Give it up */
-					warn("read_scanner(%d): excessive NAK's received", scn_minor);
-					ret = result;
-					break;
-				} else { /* Keep trying to read data */
-					interruptible_sleep_on_timeout(&scn->rd_wait_q, scn->rd_nak_timeout);
-					continue;
-				}
-			} else { /* Timeout w/ some data */
-				goto data_recvd;
-			}
-		}
-		
-		if (result == -EPIPE) { /* No hope */
-			if(usb_clear_halt(dev, scn->bulk_in_ep)) {
-				err("read_scanner(%d): Failure to clear endpoint halt condition (%Zd).", scn_minor, ret);
-			}
-			ret = result;
-			break;
-		} else if ((result < 0) && (result != -EREMOTEIO)) {
-			warn("read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt.", scn_minor, (int)result);
-			ret = -EIO;
-			break;
-		}
-
-	data_recvd:
-
-#ifdef RD_DATA_DUMP
-		if (partial) {
-			unsigned char cnt, cnt_max;
-			cnt_max = (partial > 24) ? 24 : partial;
-			printk(KERN_DEBUG "dump(%d): ", scn_minor);
-			for (cnt=0; cnt < cnt_max; cnt++) {
-				printk("%X ", ibuf[cnt]);
-			}
-			printk("\n");
-		}
-#endif
-
-		if (partial) { /* Data returned */
-			if (copy_to_user(buffer, ibuf, partial)) {
-				ret = -EFAULT;
-				break;
-			}
-			count -= this_read; /* Compensate for short reads */
-			bytes_read += partial; /* Keep tally of what actually was read */
-			buffer += partial;
-		} else {
-			ret = 0;
-			break;
-		}
-	}
-	up(&(scn->sem));
-	return ret ? ret : bytes_read;
-}
-
-static int
-ioctl_scanner(struct inode *inode, struct file *file,
-	      unsigned int cmd, unsigned long arg)
-{
-	struct usb_device *dev;
-
-	int scn_minor;
-
-	scn_minor = USB_SCN_MINOR(inode);
-
-	if (!p_scn_table[scn_minor]) {
-		err("ioctl_scanner(%d): invalid scn_minor", scn_minor);
-		return -ENODEV;
-	}
-
-	dev = p_scn_table[scn_minor]->scn_dev;
-
-	switch (cmd)
-	{
-	case SCANNER_IOCTL_VENDOR :
-		return (put_user(dev->descriptor.idVendor, (unsigned int *) arg));
-	case SCANNER_IOCTL_PRODUCT :
-		return (put_user(dev->descriptor.idProduct, (unsigned int *) arg));
-#ifdef PV8630
-	case PV8630_IOCTL_INREQUEST :
-	{
-		int result;
-
-		struct {
-			__u8  data;
-			__u8  request;
-			__u16 value;
-			__u16 index;
-		} args;
-
-		if (copy_from_user(&args, (void *)arg, sizeof(args)))
-			return -EFAULT;
-
-		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-					 args.request, USB_TYPE_VENDOR|
-					 USB_RECIP_DEVICE|USB_DIR_IN,
-					 args.value, args.index, &args.data,
-					 1, HZ*5);
-
-		dbg("ioctl_scanner(%d): inreq: args.data:%x args.value:%x args.index:%x args.request:%x\n", scn_minor, args.data, args.value, args.index, args.request);
-
-		if (copy_to_user((void *)arg, &args, sizeof(args)))
-			return -EFAULT;
-
-		dbg("ioctl_scanner(%d): inreq: result:%d\n", scn_minor, result);
-
-		return result;
-	}
-	case PV8630_IOCTL_OUTREQUEST :
-	{
-		int result;
-
-		struct {
-			__u8  request;
-			__u16 value;
-			__u16 index;
-		} args;
-
-		if (copy_from_user(&args, (void *)arg, sizeof(args)))
-			return -EFAULT;
-
-		dbg("ioctl_scanner(%d): outreq: args.value:%x args.index:%x args.request:%x\n", scn_minor, args.value, args.index, args.request);
-
-		result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-					 args.request, USB_TYPE_VENDOR|
-					 USB_RECIP_DEVICE|USB_DIR_OUT,
-					 args.value, args.index, NULL,
-					 0, HZ*5);
-
-		dbg("ioctl_scanner(%d): outreq: result:%d\n", scn_minor, result);
-
-		return result;
-	}
-#endif /* PV8630 */
- 	case SCANNER_IOCTL_CTRLMSG:
- 	{
- 		struct ctrlmsg_ioctl {
- 			struct usb_ctrlrequest	req;
- 			void			*data;
- 		} cmsg;
- 		int pipe, nb, ret;
- 		unsigned char buf[64];
- 
- 		if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
- 			return -EFAULT;
-
- 		nb = le16_to_cpup(&cmsg.req.wLength);
-
- 		if (nb > sizeof(buf))
- 			return -EINVAL;
-
- 		if ((cmsg.req.bRequestType & 0x80) == 0) {
- 			pipe = usb_sndctrlpipe(dev, 0);
- 			if (nb > 0 && copy_from_user(buf, cmsg.data, nb))
- 				return -EFAULT;
- 		} else {
- 			pipe = usb_rcvctrlpipe(dev, 0);
-		}
-
- 		ret = usb_control_msg(dev, pipe, cmsg.req.bRequest,
- 				      cmsg.req.bRequestType,
- 				      le16_to_cpup(&cmsg.req.wValue),
- 				      le16_to_cpup(&cmsg.req.wIndex),
- 				      buf, nb, HZ);
-
- 		if (ret < 0) {
- 			err("ioctl_scanner(%d): control_msg returned %d\n", scn_minor, ret);
- 			return -EIO;
- 		}
-
- 		if (nb > 0 && (cmsg.req.bRequestType & 0x80) && copy_to_user(cmsg.data, buf, nb))
- 			return -EFAULT;
-
- 		return 0;
- 	}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static struct
-file_operations usb_scanner_fops = {
-	read:		read_scanner,
-	write:		write_scanner,
-	ioctl:		ioctl_scanner,
-	open:		open_scanner,
-	release:	close_scanner,
-};
-
-static void *
-probe_scanner(struct usb_device *dev, unsigned int ifnum,
-	      const struct usb_device_id *id)
-{
-	struct scn_usb_data *scn;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-
-	int ep_cnt;
-	int ix;
-	int scn_minor;
-
-	char valid_device = 0;
-	char have_bulk_in, have_bulk_out, have_intr;
-	char name[10];
-
-	if (vendor != -1 && product != -1) {
-		info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product);
-	}
-
-	dbg("probe_scanner: USB dev address:%p", dev);
-	dbg("probe_scanner: ifnum:%u", ifnum);
-
-/*
- * 1. Check Vendor/Product
- * 2. Determine/Assign Bulk Endpoints
- * 3. Determine/Assign Intr Endpoint
- */
-
-/*
- * There doesn't seem to be an imaging class defined in the USB
- * Spec. (yet).  If there is, HP isn't following it and it doesn't
- * look like anybody else is either.  Therefore, we have to test the
- * Vendor and Product ID's to see what we have.  Also, other scanners
- * may be able to use this driver by specifying both vendor and
- * product ID's as options to the scanner module in conf.modules.
- *
- * NOTE: Just because a product is supported here does not mean that
- * applications exist that support the product.  It's in the hopes
- * that this will allow developers a means to produce applications
- * that will support USB products.
- *
- * Until we detect a device which is pleasing, we silently punt.
- */
-
-	for (ix = 0; ix < sizeof (scanner_device_ids) / sizeof (struct usb_device_id); ix++) {
-		if ((dev->descriptor.idVendor == scanner_device_ids [ix].idVendor) &&
-		    (dev->descriptor.idProduct == scanner_device_ids [ix].idProduct)) {
-			valid_device = 1;
-			break;
-                }
-	}
-	if (dev->descriptor.idVendor == vendor &&   /* User specified */
-	    dev->descriptor.idProduct == product) { /* User specified */
-		valid_device = 1;
-	}
-
-        if (!valid_device)
-                return NULL;    /* We didn't find anything pleasing */
-
-/*
- * After this point we can be a little noisy about what we are trying to
- *  configure.
- */
-
-	if (dev->descriptor.bNumConfigurations != 1) {
-		info("probe_scanner: Only one device configuration is supported.");
-		return NULL;
-	}
-
-	if (dev->config[0].bNumInterfaces != 1) {
-		info("probe_scanner: Only one device interface is supported.");
-		return NULL;
-	}
-
-	interface = dev->config[0].interface[ifnum].altsetting;
-	endpoint = interface[ifnum].endpoint;
-
-/*
- * Start checking for two bulk endpoints OR two bulk endpoints *and* one
- * interrupt endpoint. If we have an interrupt endpoint go ahead and
- * setup the handler. FIXME: This is a future enhancement...
- */
-
-	dbg("probe_scanner: Number of Endpoints:%d", (int) interface->bNumEndpoints);
-
-	if ((interface->bNumEndpoints != 2) && (interface->bNumEndpoints != 3)) {
-		info("probe_scanner: Only two or three endpoints supported.");
-		return NULL;
-	}
-
-	ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0;
-
-	while (ep_cnt < interface->bNumEndpoints) {
-
-		if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {
-			ep_cnt++;
-			have_bulk_in = ep_cnt;
-			dbg("probe_scanner: bulk_in_ep:%d", have_bulk_in);
-			continue;
-		}
-
-		if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {
-			ep_cnt++;
-			have_bulk_out = ep_cnt;
-			dbg("probe_scanner: bulk_out_ep:%d", have_bulk_out);
-			continue;
-		}
-
-		if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) {
-			ep_cnt++;
-			have_intr = ep_cnt;
-			dbg("probe_scanner: intr_ep:%d", have_intr);
-			continue;
-		}
-		info("probe_scanner: Undetected endpoint -- consult Documentation/usb/scanner.txt.");
-		return NULL;	/* Shouldn't ever get here unless we have something weird */
-	}
-
-
-/*
- * Perform a quick check to make sure that everything worked as it
- * should have.
- */
-
-	switch(interface->bNumEndpoints) {
-	case 2:
-		if (!have_bulk_in || !have_bulk_out) {
-			info("probe_scanner: Two bulk endpoints required.");
-			return NULL;
-		}
-		break;
-	case 3:
-		if (!have_bulk_in || !have_bulk_out || !have_intr) {
-			info("probe_scanner: Two bulk endpoints and one interrupt endpoint required.");
-			return NULL;
-		}
-		break;
-	default:
-		info("probe_scanner: Endpoint determination failed --  consult Documentation/usb/scanner.txt");
-		return NULL;
-	}
-
-
-/*
- * Determine a minor number and initialize the structure associated
- * with it.  The problem with this is that we are counting on the fact
- * that the user will sequentially add device nodes for the scanner
- * devices.  */
-	
-	down(&scn_mutex);
-
-	for (scn_minor = 0; scn_minor < SCN_MAX_MNR; scn_minor++) {
-		if (!p_scn_table[scn_minor])
-			break;
-	}
-
-/* Check to make sure that the last slot isn't already taken */
-	if (p_scn_table[scn_minor]) {
-		err("probe_scanner: No more minor devices remaining.");
-		up(&scn_mutex);
-		return NULL;
-	}
-
-	dbg("probe_scanner: Allocated minor:%d", scn_minor);
-
-	if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
-		err("probe_scanner: Out of memory.");
-		up(&scn_mutex);
-		return NULL;
-	}
-	memset (scn, 0, sizeof(struct scn_usb_data));
-
-	scn->scn_irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!scn->scn_irq) {
-		kfree(scn);
-		up(&scn_mutex);
-		return NULL;
-	}
-
-	init_MUTEX(&(scn->sem)); /* Initializes to unlocked */
-
-	dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn);
-
-/* Ok, if we detected an interrupt EP, setup a handler for it */
-	if (have_intr) {
-		dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", scn_minor, have_intr);
-		FILL_INT_URB(scn->scn_irq, dev,
-			     usb_rcvintpipe(dev, have_intr),
-			     &scn->button, 1, irq_scanner, scn,
-			     // endpoint[(int)have_intr].bInterval);
-			     250);
-
-	        if (usb_submit_urb(scn->scn_irq, GFP_KERNEL)) {
-			err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor);
-                	kfree(scn);
-			up(&scn_mutex);
-                	return NULL;
-        	}
-	}
-
-
-/* Ok, now initialize all the relevant values */
-	if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-		err("probe_scanner(%d): Not enough memory for the output buffer.", scn_minor);
-		kfree(scn);
-		up(&scn_mutex);
-		return NULL;
-	}
-	dbg("probe_scanner(%d): obuf address:%p", scn_minor, scn->obuf);
-
-	if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-		err("probe_scanner(%d): Not enough memory for the input buffer.", scn_minor);
-		kfree(scn->obuf);
-		kfree(scn);
-		up(&scn_mutex);
-		return NULL;
-	}
-	dbg("probe_scanner(%d): ibuf address:%p", scn_minor, scn->ibuf);
-	
-
-	switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */
-	case 0x04b8:		/* Seiko/Epson */
-		scn->rd_nak_timeout = HZ * 40;
-		break;
-	case 0x055f:		/* Mustek */
-	case 0x0400:		/* Another Mustek */
-	case 0x0ff5:		/* And yet another Mustek */
-		scn->rd_nak_timeout = HZ * 1;
-	default:
-		scn->rd_nak_timeout = RD_NAK_TIMEOUT;
-	}
-
-
-	if (read_timeout > 0) {	/* User specified read timeout overrides everything */
-		info("probe_scanner: User specified USB read timeout - %d", read_timeout);
-		scn->rd_nak_timeout = read_timeout;
-	}
-
-
-	scn->bulk_in_ep = have_bulk_in;
-	scn->bulk_out_ep = have_bulk_out;
-	scn->intr_ep = have_intr;
-	scn->present = 1;
-	scn->scn_dev = dev;
-	scn->scn_minor = scn_minor;
-	scn->isopen = 0;
-
-	sprintf(name, "scanner%d", scn->scn_minor);
-	
-	scn->devfs = devfs_register(usb_devfs_handle, name,
-				    DEVFS_FL_DEFAULT, USB_MAJOR,
-				    SCN_BASE_MNR + scn->scn_minor,
-				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
-				    S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL);
-	if (scn->devfs == NULL)
-		dbg("scanner%d: device node registration failed", scn_minor);
-
-	p_scn_table[scn_minor] = scn;
-
-	up(&scn_mutex);
-
-	return scn;
-}
-
-static void
-disconnect_scanner(struct usb_device *dev, void *ptr)
-{
-	struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
-
-	down (&scn_mutex);
-	down (&(scn->sem));
-
-	if(scn->intr_ep) {
-		dbg("disconnect_scanner(%d): Unlinking IRQ URB", scn->scn_minor);
-		usb_unlink_urb(scn->scn_irq);
-	}
-        usb_driver_release_interface(&scanner_driver,
-                &scn->scn_dev->actconfig->interface[scn->ifnum]);
-
-	kfree(scn->ibuf);
-	kfree(scn->obuf);
-
-	dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
-	devfs_unregister(scn->devfs);
-	p_scn_table[scn->scn_minor] = NULL;
-	usb_free_urb(scn->scn_irq);
-	up (&(scn->sem));
-	kfree (scn);
-	up (&scn_mutex);
-}
-
-static struct
-usb_driver scanner_driver = {
-	name:		"usbscanner",
-	probe:		probe_scanner,
-	disconnect:	disconnect_scanner,
-	fops:		&usb_scanner_fops,
-	minor:		SCN_BASE_MNR,
-	id_table:	NULL, /* This would be scanner_device_ids, but we
-				 need to check every USB device, in case
-				 we match a user defined vendor/product ID. */
-};
-
-void __exit
-usb_scanner_exit(void)
-{
-	usb_deregister(&scanner_driver);
-}
-
-int __init
-usb_scanner_init (void)
-{
-        if (usb_register(&scanner_driver) < 0)
-                return -1;
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-module_init(usb_scanner_init);
-module_exit(usb_scanner_exit);
diff -Nru a/drivers/usb/scanner.h b/drivers/usb/scanner.h
--- a/drivers/usb/scanner.h	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,261 +0,0 @@
-/*
- * Driver for USB Scanners (linux-2.4.12)
- *
- * Copyright (C) 1999, 2000, 2001 David E. Nelson
- *
- * David E. Nelson (dnelson@jump.net)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */ 
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-
-// #define DEBUG
-
-/* Enable this to support the older ioctl interfaces scanners that
- * a PV8630 Scanner-On-Chip.  The prefered method is the
- * SCANNER_IOCTL_CTRLMSG ioctl.
- */
-// #define PV8630 
-
-#define DRIVER_VERSION "0.4.6"
-#define DRIVER_DESC "USB Scanner Driver"
-
-#include <linux/usb.h>
-
-static __s32 vendor=-1, product=-1, read_timeout=0;
-
-MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
-MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
-
-MODULE_PARM(read_timeout, "i");
-MODULE_PARM_DESC(read_timeout, "User specified read timeout in seconds");
-
-
-/* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */
-// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
-// #define WR_DATA_DUMP /* DEBUG does not have to be defined. */
-
-static struct usb_device_id scanner_device_ids [] = {
-	/* Acer */
-	{ USB_DEVICE(0x04a5, 0x2060) },	/* Prisa Acerscan 620U & 640U (!)*/
-	{ USB_DEVICE(0x04a5, 0x2040) },	/* Prisa AcerScan 620U (!) */
-	{ USB_DEVICE(0x04a5, 0x20c0) },  /* Prisa AcerScan 1240UT */
-	{ USB_DEVICE(0x04a5, 0x2022) },	/* Vuego Scan Brisa 340U */
-	{ USB_DEVICE(0x04a5, 0x1a20) },	/* Unknown - Oliver Schwartz */
-	{ USB_DEVICE(0x04a5, 0x1a2a) },	/* Unknown - Oliver Schwartz */
-	{ USB_DEVICE(0x04a5, 0x207e) },	/* Prisa 640BU */
-	{ USB_DEVICE(0x04a5, 0x20be) },	/* Unknown - Oliver Schwartz */
-	{ USB_DEVICE(0x04a5, 0x20c0) },	/* Unknown - Oliver Schwartz */
-	{ USB_DEVICE(0x04a5, 0x20de) },	/* S2W 3300U */
-	{ USB_DEVICE(0x04a5, 0x20b0) },	/* Unknown - Oliver Schwartz */
-	{ USB_DEVICE(0x04a5, 0x20fe) },	/* Unknown - Oliver Schwartz */
-	/* Agfa */
-	{ USB_DEVICE(0x06bd, 0x0001) },	/* SnapScan 1212U */
-	{ USB_DEVICE(0x06bd, 0x0002) },	/* SnapScan 1236U */
-	{ USB_DEVICE(0x06bd, 0x2061) },	/* Another SnapScan 1212U (?)*/
-	{ USB_DEVICE(0x06bd, 0x0100) },	/* SnapScan Touch */
-	{ USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */
-	{ USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */
-	{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
-	{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
-	/* Canon */
-	{ USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
-	{ USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
-	{ USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
-	/* Colorado -- See Primax/Colorado below */
-	/* Epson -- See Seiko/Epson below */
-	/* Genius */
-	{ USB_DEVICE(0x0458, 0x2001) },	/* ColorPage-Vivid Pro */
-	{ USB_DEVICE(0x0458, 0x2007) },	/* ColorPage HR6 V2 */
-	{ USB_DEVICE(0x0458, 0x2008) },	/* Unknown */
-	{ USB_DEVICE(0x0458, 0x2009) },	/* Unknown */
-	{ USB_DEVICE(0x0458, 0x2013) },	/* Unknown */
-	{ USB_DEVICE(0x0458, 0x2015) },	/* Unknown  */
-	{ USB_DEVICE(0x0458, 0x2016) },	/* Unknown  */
-	/* Hewlett Packard */
-	{ USB_DEVICE(0x03f0, 0x0205) },	/* 3300C */
-	{ USB_DEVICE(0x03f0, 0x0405) }, /* 3400C */
-	{ USB_DEVICE(0x03f0, 0x0101) },	/* 4100C */
-	{ USB_DEVICE(0x03f0, 0x0105) },	/* 4200C */
-	{ USB_DEVICE(0x03f0, 0x0305) }, /* 4300C */
-	{ USB_DEVICE(0x03f0, 0x0102) },	/* PhotoSmart S20 */
-	{ USB_DEVICE(0x03f0, 0x0401) },	/* 5200C */
-	//	{ USB_DEVICE(0x03f0, 0x0701) },	/* 5300C - NOT SUPPORTED - see http://www.neatech.nl/oss/HP5300C/ */
-	{ USB_DEVICE(0x03f0, 0x0201) },	/* 6200C */
-	{ USB_DEVICE(0x03f0, 0x0601) },	/* 6300C */
-	{ USB_DEVICE(0x03f0, 0x605) },	/* 2200C */
-	/* iVina */
-	{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
-	/* Lifetec */
-	{ USB_DEVICE(0x05d8, 0x4002) }, /* Lifetec LT9385 */
-	/* Memorex */
-	{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
-	/* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */
-	//	{ USB_DEVICE(0x05da, 0x0099) },	/* ScanMaker X6 - X6U */
-	//	{ USB_DEVICE(0x05da, 0x0094) },	/* Phantom 336CX - C3 */
-	//	{ USB_DEVICE(0x05da, 0x00a0) },	/* Phantom 336CX - C3 #2 */
-	//	{ USB_DEVICE(0x05da, 0x009a) },	/* Phantom C6 */
-	//	{ USB_DEVICE(0x05da, 0x00a3) },	/* ScanMaker V6USL */
-	//	{ USB_DEVICE(0x05da, 0x80a3) },	/* ScanMaker V6USL #2 */
-	//	{ USB_DEVICE(0x05da, 0x80ac) },	/* ScanMaker V6UL - SpicyU */
-	/* Minolta */
-	//	{ USB_DEVICE(0x0638,0x026a) }, /* Minolta Dimage Scan Dual II */
-	/* Mustek */
-	{ USB_DEVICE(0x055f, 0x0001) },	/* 1200 CU */
-	{ USB_DEVICE(0x0400, 0x1000) },	/* BearPaw 1200 */
-	{ USB_DEVICE(0x055f, 0x0002) },	/* 600 CU */
-	{ USB_DEVICE(0x055f, 0x0873) }, /* 600 USB */
-	{ USB_DEVICE(0x055f, 0x0003) },	/* 1200 USB */
-	{ USB_DEVICE(0x055f, 0x0006) },	/* 1200 UB */
-	{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
-	{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
-	{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
-	/* Plustek */
-	{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
-	{ USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */
-	{ USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0010) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0013) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0015) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
-	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
-	/* Primax/Colorado */
-	{ USB_DEVICE(0x0461, 0x0300) },	/* G2-300 #1 */
-	{ USB_DEVICE(0x0461, 0x0380) },	/* G2-600 #1 */
-	{ USB_DEVICE(0x0461, 0x0301) },	/* G2E-300 #1 */
-	{ USB_DEVICE(0x0461, 0x0381) },	/* ReadyScan 636i */
-	{ USB_DEVICE(0x0461, 0x0302) },	/* G2-300 #2 */
-	{ USB_DEVICE(0x0461, 0x0382) },	/* G2-600 #2 */
-	{ USB_DEVICE(0x0461, 0x0303) },	/* G2E-300 #2 */
-	{ USB_DEVICE(0x0461, 0x0383) },	/* G2E-600 */
-	{ USB_DEVICE(0x0461, 0x0340) },	/* Colorado USB 9600 */
-	// { USB_DEVICE(0x0461, 0x0360) },	/* Colorado USB 19200 - undetected endpoint */
-	{ USB_DEVICE(0x0461, 0x0341) },	/* Colorado 600u */
-	{ USB_DEVICE(0x0461, 0x0361) },	/* Colorado 1200u */
-	/* Relisis */
-	// { USB_DEVICE(0x0475, 0x0103) },	/* Episode - undetected endpoint */
-	/* Seiko/Epson Corp. */
-	{ USB_DEVICE(0x04b8, 0x0101) },	/* Perfection 636U and 636Photo */
-	{ USB_DEVICE(0x04b8, 0x0103) },	/* Perfection 610 */
-	{ USB_DEVICE(0x04b8, 0x0104) },	/* Perfection 1200U and 1200Photo*/
-	{ USB_DEVICE(0x04b8, 0x0106) },	/* Stylus Scan 2500 */
-	{ USB_DEVICE(0x04b8, 0x0107) },	/* Expression 1600 */
-	{ USB_DEVICE(0x04b8, 0x010a) }, /* Perfection 1640SU and 1640SU Photo */
-	{ USB_DEVICE(0x04b8, 0x010b) }, /* Perfection 1240U */
-	{ USB_DEVICE(0x04b8, 0x010c) }, /* Perfection 640U */
-	{ USB_DEVICE(0x04b8, 0x010e) }, /* Expression 1680 */
-	{ USB_DEVICE(0x04b8, 0x0110) }, /* Perfection 1650 */
-	{ USB_DEVICE(0x04b8, 0x0112) }, /* Perfection 2450 - GT-9700 for the Japanese mkt */
-	/* Umax */
-	{ USB_DEVICE(0x1606, 0x0010) },	/* Astra 1220U */
-	{ USB_DEVICE(0x1606, 0x0030) },	/* Astra 2000U */
-	{ USB_DEVICE(0x1606, 0x0130) }, /* Astra 2100U */
-	{ USB_DEVICE(0x1606, 0x0230) },	/* Astra 2200U */
-	/* Visioneer */
-	{ USB_DEVICE(0x04a7, 0x0221) },	/* OneTouch 5300 USB */
-	{ USB_DEVICE(0x04a7, 0x0211) },	/* OneTouch 7600 USB */
-	{ USB_DEVICE(0x04a7, 0x0231) },	/* 6100 USB */
-	{ USB_DEVICE(0x04a7, 0x0311) },	/* 6200 EPP/USB */
-	{ USB_DEVICE(0x04a7, 0x0321) },	/* OneTouch 8100 EPP/USB */
-	{ USB_DEVICE(0x04a7, 0x0331) }, /* OneTouch 8600 EPP/USB */
-	{ }				/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, scanner_device_ids);
-
-#define IS_EP_BULK(ep)  ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
-#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
-#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
-#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
-
-#define USB_SCN_MINOR(X) minor((X)->i_rdev) - SCN_BASE_MNR
-
-#ifdef DEBUG
-#define SCN_DEBUG(X) X
-#else
-#define SCN_DEBUG(X)
-#endif
-
-#define IBUF_SIZE 32768
-#define OBUF_SIZE 4096
-
-/* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
-#define RD_NAK_TIMEOUT (10*HZ)	/* Default number of X seconds to wait */
-#define RD_EXPIRE 12		/* Number of attempts to wait X seconds */
-
-
-/* FIXME: These are NOT registered ioctls()'s */
-#ifdef PV8630
-#define PV8630_IOCTL_INREQUEST 69
-#define PV8630_IOCTL_OUTREQUEST 70
-#endif /* PV8630 */
-
-
-/* read vendor and product IDs from the scanner */
-#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
-#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
-/* send/recv a control message to the scanner */
-#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest)
-
-
-#define SCN_MAX_MNR 16		/* We're allocated 16 minors */
-#define SCN_BASE_MNR 48		/* USB Scanners start at minor 48 */
-
-static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */
-
-struct scn_usb_data {
-	struct usb_device *scn_dev;
-	devfs_handle_t devfs;	/* devfs device */
-	struct urb *scn_irq;
-	unsigned int ifnum;	/* Interface number of the USB device */
-	int scn_minor;		/* Scanner minor - used in disconnect() */
-	unsigned char button;	/* Front panel buffer */
-	char isopen;		/* Not zero if the device is open */
-	char present;		/* Not zero if device is present */
-	char *obuf, *ibuf;	/* transfer buffers */
-	char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
-	wait_queue_head_t rd_wait_q; /* read timeouts */
-	struct semaphore sem; /* lock to prevent concurrent reads or writes */
-	unsigned int rd_nak_timeout; /* Seconds to wait before read() timeout. */
-};
-
-extern devfs_handle_t usb_devfs_handle;
-
-static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
-
-static struct usb_driver scanner_driver;
diff -Nru a/drivers/usb/se401.c b/drivers/usb/se401.c
--- a/drivers/usb/se401.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1574 +0,0 @@
-/*
- * Endpoints (formerly known as AOX) se401 USB Camera Driver
- *
- * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
- *
- * Still somewhat based on the Linux ov511 driver.
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on
- * their chipset available and supporting me while writing this driver.
- * 	- Jeroen Vreeken
- */
-
-static const char version[] = "0.23";
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/pagemap.h>
-#include <linux/usb.h>
-#include <asm/io.h>
-#include <asm/semaphore.h>
-#include <linux/wrapper.h>
-#include <linux/mm.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
-#define virt_to_page(arg)	MAP_NR(arg)
-#define vmalloc_32		vmalloc
-#endif
-
-#include "se401.h"
-
-static int flickerless=0;
-static int video_nr = -1;
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
-static __devinitdata struct usb_device_id device_table [] = {
-	{ USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
-	{ USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
-	{ USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
-	{ USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */
-	{ USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-#endif
-
-MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
-MODULE_DESCRIPTION("SE401 USB Camera Driver");
-MODULE_LICENSE("GPL");
-MODULE_PARM(flickerless, "i");
-MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
-MODULE_PARM(video_nr, "i");
-EXPORT_NO_SYMBOLS;
-
-
-static struct usb_driver se401_driver;
-
-
-/**********************************************************************
- *
- * Memory management
- *
- **********************************************************************/
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-	return ret;
-}
-
-static void *rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		mem_map_reserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		mem_map_unreserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-
-
-/****************************************************************************
- *
- * /proc interface
- *
- ***************************************************************************/
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-
-static struct proc_dir_entry *se401_proc_entry = NULL;
-extern struct proc_dir_entry *video_proc_entry;
-
-#define YES_NO(x) ((x) ? "yes" : "no")
-
-static int se401_read_proc(char *page, char **start, off_t off, int count,
-			   int *eof, void *data)
-{
-	char *out = page;
-	int i, len;
-	struct usb_se401 *se401 = data;
-	
-	/* Stay under PAGE_SIZE or else bla bla bla.... */
-
-	out+=sprintf(out, "driver_version  : %s\n", version);
-	out+=sprintf(out, "model           : %s\n", se401->camera_name);
-	out+=sprintf(out, "in use          : %s\n", YES_NO (se401->user));
-	out+=sprintf(out, "streaming       : %s\n", YES_NO (se401->streaming));
-	out+=sprintf(out, "button state    : %s\n", YES_NO (se401->button));
-	out+=sprintf(out, "button pressed  : %s\n", YES_NO (se401->buttonpressed));
-	out+=sprintf(out, "num_frames      : %d\n", SE401_NUMFRAMES);
-
-	out+=sprintf(out, "Sizes           :");
-	for (i=0; i<se401->sizes; i++) {
-		out+=sprintf(out, " %dx%d", se401->width[i],
-		    se401->height[i]);
-	}
-	out+=sprintf(out, "\n");
-	
-	out+=sprintf(out, "Frames total    : %d\n", se401->readcount);
-	out+=sprintf(out, "Frames read     : %d\n", se401->framecount);
-	out+=sprintf(out, "Packets dropped : %d\n", se401->dropped);
-	out+=sprintf(out, "Decoding Errors : %d\n", se401->error);
-
-	len = out - page;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-			if (len <= 0) return 0;
-	} else
-		len = count;
-
-	*start = page + off;
-	
-	return len;	
-}
-
-static int se401_write_proc(struct file *file, const char *buffer, 
-			    unsigned long count, void *data)
-{
-	return -EINVAL;
-}
-
-static void create_proc_se401_cam (struct usb_se401 *se401)
-{
-	char name[7];
-	struct proc_dir_entry *ent;
-
-	if (!se401_proc_entry || !se401)
-		return;
-
-	sprintf (name, "video%d", se401->vdev.minor);
-
-	ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
-				se401_proc_entry);
-
-	if (!ent)
-		return;
-
-	ent->data = se401;
-	ent->read_proc = se401_read_proc;
-	ent->write_proc = se401_write_proc;
-	se401->proc_entry = ent;
-}
-
-static void destroy_proc_se401_cam (struct usb_se401 *se401)
-{
-	/* One to much, just to be sure :) */
-	char name[9];
-
-	if (!se401 || !se401->proc_entry)
-		return;
-	
-	sprintf(name, "video%d", se401->vdev.minor);
-	remove_proc_entry(name, se401_proc_entry);
-	se401->proc_entry = NULL;
-}
-
-static void proc_se401_create (void)
-{
-	if (video_proc_entry == NULL) {
-		err("/proc/video/ doesn't exist");
-		return;
-	}
-
-	se401_proc_entry=create_proc_entry("se401", S_IFDIR, video_proc_entry);
-
-	if (se401_proc_entry)
-		se401_proc_entry->owner = THIS_MODULE;
-	else
-		err("Unable to initialize /proc/video/se401");
-}
-
-static void proc_se401_destroy(void)
-{
-	if (se401_proc_entry == NULL)
-		return;
-
-	remove_proc_entry("se401", video_proc_entry);
-}
-#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
-
-
-/****************************************************************************
- *
- * se401 register read/write functions
- *
- ***************************************************************************/
-
-static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
-			 unsigned short value, unsigned char *cp, int size)
-{
-	return usb_control_msg (
-                se401->dev,
-                set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
-                req,
-                (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                value,
-                0,
-                cp,
-                size,
-                HZ
-        );
-}
-
-static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
-			     unsigned short param)
-{
-	/* specs say that the selector (address) should go in the value field
-	   and the param in index, but in the logs of the windows driver they do
-	   this the other way around...
-	 */
-	return usb_control_msg (
-		se401->dev,
-		usb_sndctrlpipe(se401->dev, 0),
-		SE401_REQ_SET_EXT_FEATURE,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		param,
-		selector,
-                NULL,
-                0,
-                HZ
-        );
-}
-
-static unsigned short se401_get_feature(struct usb_se401 *se401, 
-				        unsigned short selector)
-{
-	/* For 'set' the selecetor should be in index, not sure if the spec is
-	   wrong here to....
-	 */
-	unsigned char cp[2];
-        usb_control_msg (
-                se401->dev,
-                usb_rcvctrlpipe(se401->dev, 0),
-                SE401_REQ_GET_EXT_FEATURE,
-                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-        	0,
-                selector,
-                cp,
-                2,
-                HZ
-        );
-	return cp[0]+cp[1]*256;
-}
-
-/****************************************************************************
- *
- * Camera control
- *
- ***************************************************************************/
-
-
-static int se401_send_pict(struct usb_se401 *se401)
-{
-	se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */
-	se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */
-	se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */
-	se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */
-	se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
-	se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
-	se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
-	    	
-	return 0;
-}
-
-static void se401_set_exposure(struct usb_se401 *se401, int brightness)
-{
-	int integration=brightness<<5;
-	
-	if (flickerless==50) {
-		integration=integration-integration%106667;
-	}
-	if (flickerless==60) {
-		integration=integration-integration%88889;
-	}
-	se401->brightness=integration>>5;
-	se401->expose_h=(integration>>16)&0xff;
-	se401->expose_m=(integration>>8)&0xff;
-	se401->expose_l=integration&0xff;
-}
-
-static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
-{
-	p->brightness=se401->brightness;
-	if (se401->enhance) {
-		p->whiteness=32768;
-	} else {
-		p->whiteness=0;
-	}
-	p->colour=65535;
-	p->contrast=65535;
-	p->hue=se401->rgain<<10;
-	p->palette=se401->palette;
-	p->depth=3; /* rgb24 */
-	return 0;
-}
-
-
-static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
-{
-	if (p->palette != VIDEO_PALETTE_RGB24)
-		return 1;
-	se401->palette=p->palette;
-	if (p->hue!=se401->hue) {
-		se401->rgain= p->hue>>10;
-		se401->bgain= 0x40-(p->hue>>10);
-		se401->hue=p->hue;
-	}
-	if (p->brightness!=se401->brightness) {
-		se401_set_exposure(se401, p->brightness);
-	}
-	if (p->whiteness>=32768) {
-		se401->enhance=1;
-	} else {
-		se401->enhance=0;
-	}
-	se401_send_pict(se401);
-	se401_send_pict(se401);
-	return 0;
-}
-
-/*
-	Hyundai have some really nice docs about this and other sensor related
-	stuff on their homepage: www.hei.co.kr
-*/
-static void se401_auto_resetlevel(struct usb_se401 *se401)
-{
-	unsigned int ahrc, alrc;
-	int oldreset=se401->resetlevel;
-
-	/* For some reason this normally read-only register doesn't get reset
-	   to zero after reading them just once...
-	 */
-	se401_get_feature(se401, HV7131_REG_HIREFNOH); 
-	se401_get_feature(se401, HV7131_REG_HIREFNOL);
-	se401_get_feature(se401, HV7131_REG_LOREFNOH);
-	se401_get_feature(se401, HV7131_REG_LOREFNOL);
-	ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) + 
-	    se401_get_feature(se401, HV7131_REG_HIREFNOL);
-	alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
-	    se401_get_feature(se401, HV7131_REG_LOREFNOL);
-
-	/* Not an exact science, but it seems to work pretty well... */
-	if (alrc > 10) {
-		while (alrc>=10 && se401->resetlevel < 63) {
-			se401->resetlevel++;
-			alrc /=2;
-		}
-	} else if (ahrc > 20) {
-		while (ahrc>=20 && se401->resetlevel > 0) {
-			se401->resetlevel--;
-			ahrc /=2;
-		}
-	}
-	if (se401->resetlevel!=oldreset)
-		se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
-
-	return;
-}
-
-/* irq handler for snapshot button */
-static void se401_button_irq(struct urb *urb)
-{
-	struct usb_se401 *se401 = urb->context;
-	
-	if (!se401->dev) {
-		info("ohoh: device vapourished");
-		return;
-	}
-	
-	if (urb->actual_length >=2 && !urb->status) {
-		if (se401->button)
-			se401->buttonpressed=1;
-	}
-}
-
-static void se401_video_irq(struct urb *urb)
-{
-	struct usb_se401 *se401 = urb->context;
-	int length = urb->actual_length;
-
-	/* ohoh... */
-	if (!se401->streaming)
-		return;
-
-	if (!se401->dev) {
-		info ("ohoh: device vapourished");
-		return;
-	}
-
-	/* 0 sized packets happen if we are to fast, but sometimes the camera
-	   keeps sending them forever...
-	 */
-	if (length && !urb->status) {
-		se401->nullpackets=0;
-		switch(se401->scratch[se401->scratch_next].state) {
-			case BUFFER_READY:
-			case BUFFER_BUSY: {
-				se401->dropped++;
-				break;
-			}
-			case BUFFER_UNUSED: {
-				memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length);
-				se401->scratch[se401->scratch_next].state=BUFFER_READY;
-				se401->scratch[se401->scratch_next].offset=se401->bayeroffset;
-				se401->scratch[se401->scratch_next].length=length;
-				if (waitqueue_active(&se401->wq)) {
-					wake_up_interruptible(&se401->wq);
-				}
-				se401->scratch_overflow=0;
-				se401->scratch_next++;
-				if (se401->scratch_next>=SE401_NUMSCRATCH)
-					se401->scratch_next=0;;
-				break;
-			}
-		}
-		se401->bayeroffset+=length;
-		if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
-			se401->bayeroffset=0;
-		}
-	} else {
-		se401->nullpackets++;
-		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
-			if (waitqueue_active(&se401->wq)) {
-				wake_up_interruptible(&se401->wq);
-			}		
-		}
-	}
-
-	/* Resubmit urb for new data */
-	urb->status=0;
-	urb->dev=se401->dev;
-	if(usb_submit_urb(urb, GFP_KERNEL))
-		info("urb burned down");
-	return;
-}
-
-static void se401_send_size(struct usb_se401 *se401, int width, int height)
-{
-	int i=0;
-	int mode=0x03; /* No compression */
-	int sendheight=height;
-	int sendwidth=width;
-
-	/* JangGu compression can only be used with the camera supported sizes,
-	   but bayer seems to work with any size that fits on the sensor.
-	   We check if we can use compression with the current size with either
-	   4 or 16 times subcapturing, if not we use uncompressed bayer data
-	   but this will result in cutouts of the maximum size....
-	 */
-	while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
-		i++;
-	while (i<se401->sizes) {
-		if (se401->width[i]==width*2 && se401->height[i]==height*2) {
-			sendheight=se401->height[i];
-			sendwidth=se401->width[i];
-			mode=0x40;
-		}
-		if (se401->width[i]==width*4 && se401->height[i]==height*4) {
-			sendheight=se401->height[i];
-			sendwidth=se401->width[i];
-			mode=0x42;
-		}
-		i++;
-	}
-
-	se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
-	se401_set_feature(se401, SE401_OPERATINGMODE, mode);
-
-	if (mode==0x03) {
-		se401->format=FMT_BAYER;
-	} else {
-		se401->format=FMT_JANGGU;
-	}
-
-	return;
-}
-
-/*
-	In this function se401_send_pict is called several times,
-	for some reason (depending on the state of the sensor and the phase of
-	the moon :) doing this only in either place doesn't always work...
-*/
-static int se401_start_stream(struct usb_se401 *se401)
-{
-	struct urb *urb;
-	int err=0, i;
-	se401->streaming=1;
-
-        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
-        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
-
-	/* Set picture settings */
-	se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
-	se401_send_pict(se401);
-
-	se401_send_size(se401, se401->cwidth, se401->cheight);
-
-	se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
-
-	/* Do some memory allocation */
-	for (i=0; i<SE401_NUMFRAMES; i++) {
-		se401->frame[i].data=se401->fbuf + i * se401->maxframesize;
-		se401->frame[i].curpix=0;
-	}
-	for (i=0; i<SE401_NUMSBUF; i++) {
-		se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
-	}
-
-	se401->bayeroffset=0;
-	se401->scratch_next=0;
-	se401->scratch_use=0;
-	se401->scratch_overflow=0;
-	for (i=0; i<SE401_NUMSCRATCH; i++) {
-		se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
-		se401->scratch[i].state=BUFFER_UNUSED;
-	}
-
-	for (i=0; i<SE401_NUMSBUF; i++) {
-		urb=usb_alloc_urb(0, GFP_KERNEL);
-		if(!urb)
-			return ENOMEM;
-
-		FILL_BULK_URB(urb, se401->dev,
-			usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
-			se401->sbuf[i].data, SE401_PACKETSIZE,
-			se401_video_irq,
-			se401);
-		urb->transfer_flags |= USB_QUEUE_BULK;
-
-		se401->urb[i]=urb;
-
-		err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
-		if(err)
-			err("urb burned down");
-	}
-
-	se401->framecount=0;
-
-	return 0;
-}
-
-static int se401_stop_stream(struct usb_se401 *se401)
-{
-	int i;
-
-	if (!se401->streaming || !se401->dev)
-		return 1;
-
-	se401->streaming=0;
-
-	se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
-
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
-
-	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
-		se401->urb[i]->next=NULL;
-		usb_unlink_urb(se401->urb[i]);
-		usb_free_urb(se401->urb[i]);
-		se401->urb[i]=NULL;
-		kfree(se401->sbuf[i].data);
-	}
-	for (i=0; i<SE401_NUMSCRATCH; i++) {
-		kfree(se401->scratch[i].data);
-		se401->scratch[i].data=NULL;
-	}
-
-	return 0;
-}
-
-static int se401_set_size(struct usb_se401 *se401, int width, int height)
-{
-	int wasstreaming=se401->streaming;
-	/* Check to see if we need to change */
-	if (se401->cwidth==width && se401->cheight==height)
-		return 0;
-
-	/* Check for a valid mode */
-	if (!width || !height)
-		return 1;
-	if ((width & 1) || (height & 1))
-		return 1;
-	if (width>se401->width[se401->sizes-1])
-		return 1;
-	if (height>se401->height[se401->sizes-1])
-		return 1;
-
-	/* Stop a current stream and start it again at the new size */
-	if (wasstreaming)
-		se401_stop_stream(se401);
-	se401->cwidth=width;
-	se401->cheight=height;
-	if (wasstreaming)
-		se401_start_stream(se401);
-	return 0;
-}
-
-
-/****************************************************************************
- *
- * Video Decoding
- *
- ***************************************************************************/
-
-/*
-	This shouldn't really be done in a v4l driver....
-	But it does make the image look a lot more usable.
-	Basicly it lifts the dark pixels more than the light pixels.
-*/
-static inline void enhance_picture(unsigned char *frame, int len)
-{
-	while (len--) {
-		*frame++=(((*frame^255)*(*frame^255))/255)^255;
-	}
-}
-
-static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
-{
-	struct se401_frame *frame=&se401->frame[se401->curframe];
-	int linelength=se401->cwidth*3;
-
-	if (frame->curlinepix >= linelength) {
-		frame->curlinepix=0;
-		frame->curline+=linelength;
-	}
-
-	/* First three are absolute, all others relative.
-	 * Format is rgb from right to left (mirrorred image), 
-	 * we flip it to get bgr from left to right. */
-	if (frame->curlinepix < 3) {
-		*(frame->curline-frame->curlinepix)=1+data*4;
-	} else {
-		*(frame->curline-frame->curlinepix)=
-		    *(frame->curline-frame->curlinepix+3)+data*4;
-	}
-	frame->curlinepix++;
-}
-
-static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
-{
-	int pos=0;
-	int vlc_cod=0;
-	int vlc_size=0;
-	int vlc_data=0;
-	int bit_cur;
-	int bit;
-	data+=4;
-	while (pos < packetlength) {
-		bit_cur=8;
-		while (bit_cur && bit_exp) {
-			bit=((*data)>>(bit_cur-1))&1;
-			if (!vlc_cod) {
-				if (bit) {
-					vlc_size++;
-				} else {
-					if (!vlc_size) {
-						decode_JangGu_integrate(se401, 0);
-					} else {
-						vlc_cod=2;
-						vlc_data=0;
-					}
-				}
-			} else {
-				if (vlc_cod==2) {
-					if (!bit) vlc_data=-(1<<vlc_size)+1;
-					vlc_cod--;
-				}
-				vlc_size--;
-				vlc_data+=bit<<vlc_size;
-				if (!vlc_size) {
-					decode_JangGu_integrate(se401, vlc_data);
-					vlc_cod=0;
-				}
-			}
-			bit_cur--;
-			bit_exp--;
-		}
-		pos++;
-		data++;
-	}
-}
-
-static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
-{
-	unsigned char *data=buffer->data;
-	int len=buffer->length;
-	int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
-	int datapos=0;
-
-	/* New image? */
-	if (!se401->frame[se401->curframe].curpix) {
-		se401->frame[se401->curframe].curlinepix=0;
-		se401->frame[se401->curframe].curline=
-		    se401->frame[se401->curframe].data+
-		    se401->cwidth*3-1;
-		if (se401->frame[se401->curframe].grabstate==FRAME_READY)
-			se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
-		se401->vlcdatapos=0;
-	}
-	while (datapos < len) {
-		size=1024-se401->vlcdatapos;
-		if (size+datapos > len)
-			size=len-datapos;
-		memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
-		se401->vlcdatapos+=size;
-		packetlength=0;
-		if (se401->vlcdatapos >= 4) {
-			bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
-			pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
-			frameinfo=se401->vlcdata[0]&0xc0;
-			packetlength=((bit_exp+47)>>4)<<1;
-			if (packetlength > 1024) {
-				se401->vlcdatapos=0;
-				datapos=len;
-				packetlength=0;
-				se401->error++;
-				se401->frame[se401->curframe].curpix=0;
-			}
-		}
-		if (packetlength && se401->vlcdatapos >= packetlength) {
-			decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
-			se401->frame[se401->curframe].curpix+=pix_exp*3;
-			datapos+=size-(se401->vlcdatapos-packetlength);
-			se401->vlcdatapos=0;
-			if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
-				if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
-					if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
-						se401->frame[se401->curframe].grabstate=FRAME_DONE;
-						se401->framecount++;
-						se401->readcount++;
-					}
-					if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
-						se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
-					}
-				} else {
-					se401->error++;
-				}
-				se401->frame[se401->curframe].curpix=0;
-				datapos=len;
-			}
-		} else {
-			datapos+=size;
-		}
-	}
-}
-
-static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
-{
-	unsigned char *data=buffer->data;
-	int len=buffer->length;
-	int offset=buffer->offset;
-	int datasize=se401->cwidth*se401->cheight;
-	struct se401_frame *frame=&se401->frame[se401->curframe];
-
-	unsigned char *framedata=frame->data, *curline, *nextline;
-	int width=se401->cwidth;
-	int blineoffset=0, bline;
-	int linelength=width*3, i;
-	
-
-	if (frame->curpix==0) {
-		if (frame->grabstate==FRAME_READY) {
-			frame->grabstate=FRAME_GRABBING;
-		}
-		frame->curline=framedata+linelength;
-		frame->curlinepix=0;
-	}
-
-	if (offset!=frame->curpix) {
-		/* Regard frame as lost :( */
-		frame->curpix=0;
-		se401->error++;
-		return;
-	}
-
-	/* Check if we have to much data */
-	if (frame->curpix+len > datasize) {
-		len=datasize-frame->curpix;
-	}
-	if (se401->cheight%4)
-		blineoffset=1;
-	bline=frame->curpix/se401->cwidth+blineoffset;
-
-	curline=frame->curline;
-	nextline=curline+linelength;
-	if (nextline >= framedata+datasize*3)
-		nextline=curline;
-	while (len) {
-		if (frame->curlinepix>=width) {
-			frame->curlinepix-=width;
-			bline=frame->curpix/width+blineoffset;
-			curline+=linelength*2;
-			nextline+=linelength*2;
-			if (curline >= framedata+datasize*3) {
-				frame->curlinepix++;
-				curline-=3;
-				nextline-=3;
-				len--;
-				data++;
-				frame->curpix++;
-			}
-			if (nextline >= framedata+datasize*3)
-				nextline=curline;
-		}
-		if ((bline&1)) {
-			if ((frame->curlinepix&1)) {
-				*(curline+2)=*data;
-				*(curline-1)=*data;
-				*(nextline+2)=*data;
-				*(nextline-1)=*data;
-			} else {
-				*(curline+1)=
-					(*(curline+1)+*data)/2;
-				*(curline-2)=
-					(*(curline-2)+*data)/2;
-				*(nextline+1)=*data;
-				*(nextline-2)=*data;
-			}
-		} else {
-			if ((frame->curlinepix&1)) {
-				*(curline+1)=
-					(*(curline+1)+*data)/2;
-				*(curline-2)=
-					(*(curline-2)+*data)/2;
-				*(nextline+1)=*data;
-				*(nextline-2)=*data;
-			} else {
-				*curline=*data;
-				*(curline-3)=*data;
-				*nextline=*data;
-				*(nextline-3)=*data;
-			}
-		}
-		frame->curlinepix++;
-		curline-=3;
-		nextline-=3;
-		len--;
-		data++;
-		frame->curpix++;
-	}
-	frame->curline=curline;
-
-	if (frame->curpix>=datasize) {
-		/* Fix the top line */
-		framedata+=linelength;
-		for (i=0; i<linelength; i++) {
-			*--framedata=*(framedata+linelength);
-		}
-		/* Fix the left side (green is already present) */
-		for (i=0; i<se401->cheight; i++) {
-			*framedata=*(framedata+3);
-			*(framedata+1)=*(framedata+4);
-			*(framedata+2)=*(framedata+5);
-			framedata+=linelength;
-		}
-		frame->curpix=0;
-		frame->grabstate=FRAME_DONE;
-		se401->framecount++;
-		se401->readcount++;
-		if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
-			se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
-		}
-	}
-}
-
-static int se401_newframe(struct usb_se401 *se401, int framenr)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int errors=0;
-
-	while (se401->streaming &&
-	    (se401->frame[framenr].grabstate==FRAME_READY ||
-	     se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
-		if(!se401->frame[framenr].curpix) {
-			errors++;
-		}
-		wait_interruptible(
-		    se401->scratch[se401->scratch_use].state!=BUFFER_READY,
-		    &se401->wq,
-		    &wait
-		);
-		if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
-			se401->nullpackets=0;
-			info("to many null length packets, restarting capture");
-			se401_stop_stream(se401);
-			se401_start_stream(se401);			
-		} else {
-			if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
-				se401->frame[framenr].grabstate=FRAME_ERROR;
-				return -EIO;
-			}
-			se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
-			if (se401->format==FMT_JANGGU) {
-				decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
-			} else {
-				decode_bayer(se401, &se401->scratch[se401->scratch_use]);
-			}
-			se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
-			se401->scratch_use++;
-			if (se401->scratch_use>=SE401_NUMSCRATCH)
-				se401->scratch_use=0;
-			if (errors > SE401_MAX_ERRORS) {
-				errors=0;
-				info("to much errors, restarting capture");
-				se401_stop_stream(se401);
-				se401_start_stream(se401);
-			}
-		}
-	}
-
-	if (se401->frame[framenr].grabstate==FRAME_DONE)
-		if (se401->enhance)
-			enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
-	return 0;
-}
-
-
-/****************************************************************************
- *
- * Video4Linux
- *
- ***************************************************************************/
-
-
-static int se401_open(struct inode *inode, struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	int err = 0;
-
-	if (se401->user)
-		return -EBUSY;
-	se401->user=1;
-	se401->fbuf=rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
-	if(!se401->fbuf) err=-ENOMEM;
-
-        if (0 != err) {
-		se401->user = 0;
-	} else {
-		file->private_data = dev;
-	}
-
-	return err;
-}
-
-static int se401_close(struct inode *inode, struct file *file)
-{
-	struct video_device *dev = file->private_data;
-        struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	int i;
-
-	for (i=0; i<SE401_NUMFRAMES; i++)
-		se401->frame[i].grabstate=FRAME_UNUSED;
-	if (se401->streaming)
-		se401_stop_stream(se401);
-
-	rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
-	se401->user=0;
-
-        if (se401->removed) {
-		kfree(se401->width);
-		kfree(se401->height);
-                kfree(se401);
-                se401 = NULL;
-		info("device unregistered");
-	}
-	file->private_data = NULL;
-	return 0;
-}
-
-static int se401_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-        struct usb_se401 *se401 = (struct usb_se401 *)vdev;
-
-        if (!se401->dev)
-                return -EIO;
-
-        switch (cmd) {
-	case VIDIOCGCAP:
-	{
-		struct video_capability *b = arg;
-		strcpy(b->name, se401->camera_name);
-		b->type = VID_TYPE_CAPTURE;
-		b->channels = 1;
-		b->audios = 0;
-		b->maxwidth = se401->width[se401->sizes-1];
-		b->maxheight = se401->height[se401->sizes-1];
-		b->minwidth = se401->width[0];
-		b->minheight = se401->height[0];
-		return 0;
-	}
-	case VIDIOCGCHAN:
-	{
-		struct video_channel *v = arg;
-
-		if (v->channel != 0)
-			return -EINVAL;
-		v->flags = 0;
-		v->tuners = 0;
-		v->type = VIDEO_TYPE_CAMERA;
-		strcpy(v->name, "Camera");
-		return 0;
-	}
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *v = arg;
-
-		if (v->channel != 0)
-			return -EINVAL;
-		return 0;
-	}
-        case VIDIOCGPICT:
-        {
-		struct video_picture *p = arg;
-
-		se401_get_pict(se401, p);
-		return 0;
-	}
-	case VIDIOCSPICT:
-	{
-		struct video_picture *p = arg;
-
-		if (se401_set_pict(se401, p))
-			return -EINVAL;
-		return 0;
-	}
-	case VIDIOCSWIN:
-	{
-		struct video_window *vw = arg;
-
-		if (vw->flags)
-			return -EINVAL;
-		if (vw->clipcount)
-			return -EINVAL;
-		if (se401_set_size(se401, vw->width, vw->height))
-			return -EINVAL;
-		return 0;
-        }
-	case VIDIOCGWIN:
-	{
-		struct video_window *vw = arg;
-
-		vw->x = 0;               /* FIXME */
-		vw->y = 0;
-		vw->chromakey = 0;
-		vw->flags = 0;
-		vw->clipcount = 0;
-		vw->width = se401->cwidth;
-		vw->height = se401->cheight;
-		return 0;
-	}
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *vm = arg;
-		int i;
-
-		memset(vm, 0, sizeof(*vm));
-		vm->size = SE401_NUMFRAMES * se401->maxframesize;
-		vm->frames = SE401_NUMFRAMES;
-		for (i=0; i<SE401_NUMFRAMES; i++)
-			vm->offsets[i] = se401->maxframesize * i;
-		return 0;
-	}
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *vm = arg;
-
-		if (vm->format != VIDEO_PALETTE_RGB24)
-			return -EINVAL;
-		if (vm->frame >= SE401_NUMFRAMES)
-			return -EINVAL;
-		if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
-			return -EBUSY;
-
-		/* Is this according to the v4l spec??? */
-		if (se401_set_size(se401, vm->width, vm->height))
-			return -EINVAL;
-		se401->frame[vm->frame].grabstate=FRAME_READY;
-
-		if (!se401->streaming)
-			se401_start_stream(se401);
-
-		/* Set the picture properties */
-		if (se401->framecount==0)
-			se401_send_pict(se401);
-		/* Calibrate the reset level after a few frames. */
-		if (se401->framecount%20==1)
-			se401_auto_resetlevel(se401);
-
-		return 0;
-	}
-	case VIDIOCSYNC:
-	{
-		int *frame = arg;
-		int ret=0;
-
-		if(*frame <0 || *frame >= SE401_NUMFRAMES)
-			return -EINVAL;
-
-		ret=se401_newframe(se401, *frame);
-		se401->frame[*frame].grabstate=FRAME_UNUSED;
-		return ret;
-	}
-	case VIDIOCGFBUF:
-	{
-		struct video_buffer *vb = arg;
-
-		memset(vb, 0, sizeof(*vb));
-		return 0;
-	}
-	case VIDIOCKEY:
-		return 0;
-	case VIDIOCCAPTURE:
-		return -EINVAL;
-	case VIDIOCSFBUF:
-		return -EINVAL;
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-		return -EINVAL;
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-		return -EINVAL;
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-		return -EINVAL;
-        default:
-                return -ENOIOCTLCMD;
-        } /* end switch */
-
-        return 0;
-}
-
-static int se401_read(struct file *file, char *buf,
-		     size_t count, loff_t *ppos)
-{
-	int realcount=count, ret=0;
-	struct video_device *dev = file->private_data;
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-
-
-	if (se401->dev == NULL)
-		return -EIO;
-	if (realcount > se401->cwidth*se401->cheight*3)
-		realcount=se401->cwidth*se401->cheight*3;
-
-	/* Shouldn't happen: */
-	if (se401->frame[0].grabstate==FRAME_GRABBING)
-		return -EBUSY;
-	se401->frame[0].grabstate=FRAME_READY;
-	se401->frame[1].grabstate=FRAME_UNUSED;
-	se401->curframe=0;
-
-	if (!se401->streaming)
-		se401_start_stream(se401);
-
-	/* Set the picture properties */
-	if (se401->framecount==0)
-		se401_send_pict(se401);
-	/* Calibrate the reset level after a few frames. */
-	if (se401->framecount%20==1)
-		se401_auto_resetlevel(se401);
-
-	ret=se401_newframe(se401, 0);
-
-	se401->frame[0].grabstate=FRAME_UNUSED;
-	if (ret)
-		return ret;	
-	if (copy_to_user(buf, se401->frame[0].data, realcount))
-		return -EFAULT;
-
-	return realcount;
-}
-
-static int se401_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *dev = file->private_data;
-	struct usb_se401 *se401 = (struct usb_se401 *)dev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-
-	down(&se401->lock);
-
-	if (se401->dev == NULL) {
-		up(&se401->lock);
-		return -EIO;
-	}
-	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
-		up(&se401->lock);
-		return -EINVAL;
-	}
-	pos = (unsigned long)se401->fbuf;
-	while (size > 0) {
-		page = kvirt_to_pa(pos);
-		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			up(&se401->lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-	up(&se401->lock);
-
-        return 0;
-}
-
-static struct file_operations se401_fops = {
-	owner:		THIS_MODULE,
-        open:           se401_open,
-        release:        se401_close,
-        read:           se401_read,
-        mmap:           se401_mmap,
-	ioctl:          video_generic_ioctl,
-	llseek:         no_llseek,
-};
-static struct video_device se401_template = {
-	owner:		THIS_MODULE,
-        name:           "se401 USB camera",
-        type:           VID_TYPE_CAPTURE,
-        hardware:       VID_HARDWARE_SE401,
-	fops:           &se401_fops,
-        kernel_ioctl:   se401_ioctl,
-};
-
-
-
-/***************************/
-static int se401_init(struct usb_se401 *se401)
-{
-        int i=0, rc;
-        unsigned char cp[0x40];
-	char temp[200];
-
-	/* led on */
-        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
-
-	/* get camera descriptor */
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
-	if (cp[1]!=0x41) {
-		err("Wrong descriptor type");
-		return 1;
-	}
-	sprintf (temp, "ExtraFeatures: %d", cp[3]);
-
-	se401->sizes=cp[4]+cp[5]*256;
-	se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
-	se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
-	for (i=0; i<se401->sizes; i++) {
-		    se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
-		    se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
-	}
-	sprintf (temp, "%s Sizes:", temp);
-	for (i=0; i<se401->sizes; i++) {
-		sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
-	}
-	info("%s", temp);
-	se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
-
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
-	se401->cwidth=cp[0]+cp[1]*256;
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
-	se401->cheight=cp[0]+cp[1]*256;
-
-	if (!cp[2] && SE401_FORMAT_BAYER) {
-		err("Bayer format not supported!");
-		return 1;
-	}
-	/* set output mode (BAYER) */
-        se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
-
-	rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
-	se401->brightness=cp[0]+cp[1]*256;
-	/* some default values */
-	se401->resetlevel=0x2d;
-	se401->rgain=0x20;
-	se401->ggain=0x20;
-	se401->bgain=0x20;
-	se401_set_exposure(se401, 20000);
-	se401->palette=VIDEO_PALETTE_RGB24;
-	se401->enhance=1;
-	se401->dropped=0;
-	se401->error=0;
-	se401->framecount=0;
-	se401->readcount=0;
-
-	/* Start interrupt transfers for snapshot button */
-	se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
-	if (!se401->inturb) {
-		info("Allocation of inturb failed");
-		return 1;
-	}
-	FILL_INT_URB(se401->inturb, se401->dev,
-	    usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
-	    &se401->button, sizeof(se401->button),
-	    se401_button_irq,
-	    se401,
-	    HZ/10
-	);
-	if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
-		info("int urb burned down");
-		return 1;
-	}
-
-        /* Flash the led */
-        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
-        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
-        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
-	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
-
-        return 0;
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
-static void* se401_probe(struct usb_device *dev, unsigned int ifnum)
-#else
-static void* __devinit se401_probe(struct usb_device *dev, unsigned int ifnum,
-	const struct usb_device_id *id)
-#endif
-{
-        struct usb_interface_descriptor *interface;
-        struct usb_se401 *se401;
-        char *camera_name=NULL;
-
-        /* We don't handle multi-config cameras */
-        if (dev->descriptor.bNumConfigurations != 1)
-                return NULL;
-
-        interface = &dev->actconfig->interface[ifnum].altsetting[0];
-
-        /* Is it an se401? */
-        if (dev->descriptor.idVendor == 0x03e8 &&
-            dev->descriptor.idProduct == 0x0004) {
-                camera_name="Endpoints/Aox SE401";
-        } else if (dev->descriptor.idVendor == 0x0471 &&
-            dev->descriptor.idProduct == 0x030b) {
-                camera_name="Philips PCVC665K";
-        } else if (dev->descriptor.idVendor == 0x047d &&
-	    dev->descriptor.idProduct == 0x5001) {
-		camera_name="Kensington VideoCAM 67014";
-        } else if (dev->descriptor.idVendor == 0x047d &&
-	    dev->descriptor.idProduct == 0x5002) {
-		camera_name="Kensington VideoCAM 6701(5/7)";
-        } else if (dev->descriptor.idVendor == 0x047d &&
-	    dev->descriptor.idProduct == 0x5003) {
-		camera_name="Kensington VideoCAM 67016";
-	} else
-		return NULL;
-
-        /* Checking vendor/product should be enough, but what the hell */
-        if (interface->bInterfaceClass != 0x00)
-                return NULL;
-        if (interface->bInterfaceSubClass != 0x00)
-                return NULL;
-
-        /* We found one */
-        info("SE401 camera found: %s", camera_name);
-
-        if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
-                err("couldn't kmalloc se401 struct");
-                return NULL;
-        }
-
-        memset(se401, 0, sizeof(*se401));
-
-        se401->dev = dev;
-        se401->iface = interface->bInterfaceNumber;
-        se401->camera_name = camera_name;
-
-	info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
-
-        if (se401_init(se401)) {
-		kfree(se401);
-		return NULL;
-	}
-
-	memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
-	memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
-	init_waitqueue_head(&se401->wq);
-	init_MUTEX(&se401->lock);
-	wmb();
-
-	if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
-		kfree(se401);
-		err("video_register_device failed");
-		return NULL;
-	}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-        create_proc_se401_cam(se401);
-#endif
-	info("registered new video device: video%d", se401->vdev.minor);
-
-        return se401;
-}
-
-static void se401_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_se401 *se401 = (struct usb_se401 *) ptr;
-
-	video_unregister_device(&se401->vdev);
-	if (!se401->user){
-		usb_se401_remove_disconnected(se401);
-	} else {
-		se401->removed = 1;
-	}
-}
-
-static inline void usb_se401_remove_disconnected (struct usb_se401 *se401)
-{
-	int i;
-
-        se401->dev = NULL;
-        se401->frame[0].grabstate = FRAME_ERROR;
-        se401->frame[1].grabstate = FRAME_ERROR;
-
-	se401->streaming = 0;
-
-	wake_up_interruptible(&se401->wq);
-
-	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
-		se401->urb[i]->next = NULL;
-		usb_unlink_urb(se401->urb[i]);
-		usb_free_urb(se401->urb[i]);
-		se401->urb[i] = NULL;
-		kfree(se401->sbuf[i].data);
-	}
-	for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
-		kfree(se401->scratch[i].data);
-	}
-	if (se401->inturb) {
-		usb_unlink_urb(se401->inturb);
-		usb_free_urb(se401->inturb);
-	}
-        info("%s disconnected", se401->camera_name);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	destroy_proc_se401_cam(se401);
-#endif
-
-        /* Free the memory */
-	kfree(se401->width);
-	kfree(se401->height);
-	kfree(se401);
-}
-
-static struct usb_driver se401_driver = {
-        name:		"se401",
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)
-        id_table:	device_table,
-#endif
-	probe:		se401_probe,
-        disconnect:	se401_disconnect
-};
-
-
-
-/****************************************************************************
- *
- *  Module routines
- *
- ***************************************************************************/
-
-static int __init usb_se401_init(void)
-{
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	proc_se401_create();
-#endif
-
-	info("SE401 usb camera driver version %s registering", version);
-	if (flickerless)
-		if (flickerless!=50 && flickerless!=60) {
-			info("Invallid flickerless value, use 0, 50 or 60.");
-			return -1;
-	}
-	if (usb_register(&se401_driver) < 0)
-		return -1;
-	return 0;
-}
-
-static void __exit usb_se401_exit(void)
-{
-	usb_deregister(&se401_driver);
-	info("SE401 driver deregistered");
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	proc_se401_destroy();
-#endif
-}
-
-module_init(usb_se401_init);
-module_exit(usb_se401_exit);
diff -Nru a/drivers/usb/se401.h b/drivers/usb/se401.h
--- a/drivers/usb/se401.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,237 +0,0 @@
-
-#ifndef __LINUX_se401_H
-#define __LINUX_se401_H
-
-#include <asm/uaccess.h>
-#include <linux/videodev.h>
-#include <linux/smp_lock.h>
-
-#define se401_DEBUG	/* Turn on debug messages */
-
-#ifdef se401_DEBUG
-#  define PDEBUG(level, fmt, args...) \
-if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
-#else
-#  define PDEBUG(level, fmt, args...) do {} while(0)
-#endif
-
-/* An almost drop-in replacement for sleep_on_interruptible */
-#define wait_interruptible(test, queue, wait) \
-{ \
-	add_wait_queue(queue, wait); \
-	set_current_state(TASK_INTERRUPTIBLE); \
-	if (test) \
-		schedule(); \
-	remove_wait_queue(queue, wait); \
-	set_current_state(TASK_RUNNING); \
-	if (signal_pending(current)) \
-		break; \
-}
-
-#define SE401_REQ_GET_CAMERA_DESCRIPTOR		0x06
-#define SE401_REQ_START_CONTINUOUS_CAPTURE	0x41
-#define SE401_REQ_STOP_CONTINUOUS_CAPTURE	0x42
-#define SE401_REQ_CAPTURE_FRAME			0x43
-#define SE401_REQ_GET_BRT			0x44
-#define SE401_REQ_SET_BRT			0x45
-#define SE401_REQ_GET_WIDTH			0x4c
-#define SE401_REQ_SET_WIDTH			0x4d
-#define SE401_REQ_GET_HEIGHT			0x4e
-#define SE401_REQ_SET_HEIGHT			0x4f
-#define SE401_REQ_GET_OUTPUT_MODE		0x50
-#define SE401_REQ_SET_OUTPUT_MODE		0x51
-#define SE401_REQ_GET_EXT_FEATURE		0x52
-#define SE401_REQ_SET_EXT_FEATURE		0x53
-#define SE401_REQ_CAMERA_POWER			0x56
-#define SE401_REQ_LED_CONTROL			0x57
-#define SE401_REQ_BIOS				0xff
-
-#define SE401_BIOS_READ				0x07
-
-#define SE401_FORMAT_BAYER	0x40
-
-/* Hyundai hv7131b registers
-   7121 and 7141 should be the same (haven't really checked...) */
-/* Mode registers: */
-#define HV7131_REG_MODE_A		0x00
-#define HV7131_REG_MODE_B		0x01
-#define HV7131_REG_MODE_C		0x02
-/* Frame registers: */
-#define HV7131_REG_FRSU		0x10
-#define HV7131_REG_FRSL		0x11
-#define HV7131_REG_FCSU		0x12
-#define HV7131_REG_FCSL		0x13
-#define HV7131_REG_FWHU		0x14
-#define HV7131_REG_FWHL		0x15
-#define HV7131_REG_FWWU		0x16
-#define HV7131_REG_FWWL		0x17
-/* Timing registers: */
-#define HV7131_REG_THBU		0x20
-#define HV7131_REG_THBL		0x21
-#define HV7131_REG_TVBU		0x22
-#define HV7131_REG_TVBL		0x23
-#define HV7131_REG_TITU		0x25
-#define HV7131_REG_TITM		0x26
-#define HV7131_REG_TITL		0x27
-#define HV7131_REG_TMCD		0x28
-/* Adjust Registers: */
-#define HV7131_REG_ARLV		0x30
-#define HV7131_REG_ARCG		0x31
-#define HV7131_REG_AGCG		0x32
-#define HV7131_REG_ABCG		0x33
-#define HV7131_REG_APBV		0x34
-#define HV7131_REG_ASLP		0x54
-/* Offset Registers: */
-#define HV7131_REG_OFSR		0x50
-#define HV7131_REG_OFSG		0x51
-#define HV7131_REG_OFSB		0x52
-/* REset level statistics registers: */
-#define HV7131_REG_LOREFNOH	0x57
-#define HV7131_REG_LOREFNOL	0x58
-#define HV7131_REG_HIREFNOH	0x59
-#define HV7131_REG_HIREFNOL	0x5a
-
-/* se401 registers */
-#define SE401_OPERATINGMODE	0x2000
-
-
-/* size of usb transfers */
-#define SE401_PACKETSIZE	4096
-/* number of queued bulk transfers to use, should be about 8 */
-#define SE401_NUMSBUF		1
-/* read the usb specs for this one :) */
-#define SE401_VIDEO_ENDPOINT	1
-#define SE401_BUTTON_ENDPOINT	2
-/* number of frames supported by the v4l part */
-#define SE401_NUMFRAMES		2
-/* scratch buffers for passing data to the decoders */
-#define SE401_NUMSCRATCH	32
-/* maximum amount of data in a JangGu packet */
-#define SE401_VLCDATALEN	1024
-/* number of nul sized packets to receive before kicking the camera */
-#define SE401_MAX_NULLPACKETS	4000
-/* number of decoding errors before kicking the camera */
-#define SE401_MAX_ERRORS	200
-
-struct usb_device;
-
-struct se401_sbuf {
-	unsigned char *data;
-};
-
-enum {
-	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
-	FRAME_READY,		/* Ready to start grabbing */
-	FRAME_GRABBING,		/* In the process of being grabbed into */
-	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
-	FRAME_ERROR,		/* Something bad happened while processing */
-};
-
-enum {
-	FMT_BAYER,
-	FMT_JANGGU,
-};
-
-enum {
-	BUFFER_UNUSED,
-	BUFFER_READY,
-	BUFFER_BUSY,
-	BUFFER_DONE,
-};
-
-struct se401_scratch {
-	unsigned char *data;
-	volatile int state;
-	int offset;
-	int length;
-};
-
-struct se401_frame {
-	unsigned char *data;		/* Frame buffer */
-
-	volatile int grabstate;	/* State of grabbing */
-
-	unsigned char *curline;
-	int curlinepix;
-	int curpix;
-};
-
-struct usb_se401 {
-	struct video_device vdev;
-
-	/* Device structure */
-	struct usb_device *dev;
-
-	unsigned char iface;
-
-	char *camera_name;
-
-	int change;
-	int brightness;
-	int hue;
-	int rgain;
-	int ggain;
-	int bgain;
-	int expose_h;
-	int expose_m;
-	int expose_l;
-	int resetlevel;
-	
-	int enhance;
-
-	int format;
-	int sizes;
-	int *width;
-	int *height;
-	int cwidth;		/* current width */
-	int cheight;		/* current height */
-	int palette;
-	int maxframesize;
-	int cframesize;		/* current framesize */
-
-	struct semaphore lock;
-	int user;		/* user count for exclusive use */
-	int removed;		/* device disconnected */
-
-	int streaming;		/* Are we streaming video? */
-
-	char *fbuf;		/* Videodev buffer area */
-
-	struct urb *urb[SE401_NUMSBUF];
-	struct urb *inturb;
-	
-	int button;
-	int buttonpressed;
-
-	int curframe;		/* Current receiving frame */
-	struct se401_frame frame[SE401_NUMFRAMES];	
-	int readcount;
-	int framecount;
-	int error;
-	int dropped;
-
-	int scratch_next;
-	int scratch_use;
-	int scratch_overflow;
-	struct se401_scratch scratch[SE401_NUMSCRATCH];
-
-	/* Decoder specific data: */
-	unsigned char vlcdata[SE401_VLCDATALEN];
-	int vlcdatapos;
-	int bayeroffset;
-
-	struct se401_sbuf sbuf[SE401_NUMSBUF];
-
-	wait_queue_head_t wq;	/* Processes waiting */
-
-	/* proc interface */
-	struct proc_dir_entry *proc_entry;	/* /proc/se401/videoX */
-
-	int nullpackets;
-};
-
-static inline void usb_se401_remove_disconnected (struct usb_se401 *se401);
-
-
-#endif
-
diff -Nru a/drivers/usb/serial/Config.help b/drivers/usb/serial/Config.help
--- a/drivers/usb/serial/Config.help	Sun Apr 14 12:16:57 2002
+++ b/drivers/usb/serial/Config.help	Sun Apr 14 12:16:57 2002
@@ -12,6 +12,26 @@
   The module will be called usbserial.o. If you want to compile it
   as a module, say M here and read <file:Documentation/modules.txt>.
 
+CONFIG_USB_SERIAL_CONSOLE
+  If you say Y here, it will be possible to use a USB to serial
+  converter port as the system console (the system console is the
+  device which receives all kernel messages and warnings and which
+  allows logins in single user mode). This could be useful if some
+  terminal or printer is connected to that serial port.
+
+  Even if you say Y here, the currently visible virtual console
+  (/dev/tty0) will still be used as the system console by default, but
+  you can alter that using a kernel command line option such as
+  "console=ttyUSB0". (Try "man bootparam" or see the documentation of
+  your boot loader (lilo or loadlin) about how to pass options to the
+  kernel at boot time.)
+
+  If you don't have a VGA card installed and you say Y here, the
+  kernel will automatically use the first USB to serial converter
+  port, /dev/ttyUSB0, as system console.
+
+  If unsure, say N.
+
 CONFIG_USB_SERIAL_GENERIC
   Say Y here if you want to use the generic USB serial driver.  Please
   read <file:Documentation/usb/usb-serial.txt> for more information on
diff -Nru a/drivers/usb/serial/Config.in b/drivers/usb/serial/Config.in
--- a/drivers/usb/serial/Config.in	Sun Apr 14 12:16:54 2002
+++ b/drivers/usb/serial/Config.in	Sun Apr 14 12:16:54 2002
@@ -7,19 +7,20 @@
 dep_tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
 if [ "$CONFIG_USB_SERIAL" = "y" ]; then
   dep_mbool '  USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
+  dep_mbool '  USB Serial Console device support (EXPERIMENTAL)' CONFIG_USB_SERIAL_CONSOLE $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 fi
 dep_mbool '  USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC $CONFIG_USB_SERIAL
-dep_tristate '  USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-dep_tristate '  USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Belkin and Peracom Single Port Serial Driver' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL
+dep_tristate '  USB ConnectTech WhiteHEAT Serial Driver' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL
 dep_tristate '  USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL
-dep_tristate '  USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Empeg empeg-car Mark I/II Driver' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL
 dep_tristate '  USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL
 dep_tristate '  USB Compaq iPAQ / HP Jornada Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL
 dep_tristate '  USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-dep_tristate '  USB Inside Out Edgeport Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-dep_tristate '  USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-dep_tristate '  USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Inside Out Edgeport Serial Driver' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL
+dep_tristate '  USB Keyspan PDA Single Port Serial Driver' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL
+dep_tristate '  USB Keyspan USA-xxx Serial Driver' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL
    dep_mbool '    USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 $CONFIG_USB_SERIAL_KEYSPAN
    dep_mbool '    USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X $CONFIG_USB_SERIAL_KEYSPAN
    dep_mbool '    USB Keyspan USA-28XA Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28XA $CONFIG_USB_SERIAL_KEYSPAN
@@ -28,11 +29,13 @@
    dep_mbool '    USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X $CONFIG_USB_SERIAL_KEYSPAN
    dep_mbool '    USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W $CONFIG_USB_SERIAL_KEYSPAN
    dep_mbool '    USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W $CONFIG_USB_SERIAL_KEYSPAN
-dep_tristate '  USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 dep_tristate '  USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KLSI $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-dep_tristate '  USB Prolific 2303 Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB MCT Single Port Serial Driver' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL
+dep_tristate '  USB Prolific 2303 Single Port Serial Driver' CONFIG_USB_SERIAL_PL2303 $CONFIG_USB_SERIAL
+dep_tristate '  USB Safe Serial (Encapsulated) Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_SAFE $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+   dep_mbool '  USB Secure Encapsulated Driver - Padded (EXPERIMENTAL)' CONFIG_USB_SERIAL_SAFE_PADDED $CONFIG_USB_SERIAL_SAFE
 dep_tristate '  USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)' CONFIG_USB_SERIAL_CYBERJACK $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
-dep_tristate '  USB Xircom / Entregra Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
+dep_tristate '  USB Xircom / Entregra Single Port Serial Driver' CONFIG_USB_SERIAL_XIRCOM $CONFIG_USB_SERIAL
 dep_tristate '  USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
 
 endmenu
diff -Nru a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
--- a/drivers/usb/serial/Makefile	Sun Apr 14 12:16:56 2002
+++ b/drivers/usb/serial/Makefile	Sun Apr 14 12:16:56 2002
@@ -24,6 +24,7 @@
 obj-$(CONFIG_USB_SERIAL_CYBERJACK)		+= cyberjack.o
 obj-$(CONFIG_USB_SERIAL_IR)			+= ir-usb.o
 obj-$(CONFIG_USB_SERIAL_KLSI)			+= kl5kusb105.o
+obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
 
 # Objects that export symbols.
 export-objs	:= usbserial.o
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/usb/serial/belkin_sa.c	Sun Apr 14 12:16:55 2002
@@ -191,9 +191,6 @@
 
 	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			belkin_sa_close (&serial->port[i], NULL);
-		}
 		/* My special items, the standard routines free my urbs */
 		if (serial->port[i].private)
 			kfree(serial->port[i].private);
@@ -207,26 +204,22 @@
 
 	dbg(__FUNCTION__" port %d", port->number);
 
-	++port->open_count;
-	
-	if (port->open_count == 1) {
-		/*Start reading from the device*/
-		/* TODO: Look at possibility of submitting mulitple URBs to device to
-		 *       enhance buffering.  Win trace shows 16 initial read URBs.
-		 */
-		port->read_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (retval) {
-			err("usb_submit_urb(read bulk) failed");
-			goto exit;
-		}
-
-		port->interrupt_in_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-		if (retval)
-			err(" usb_submit_urb(read int) failed");
+	/*Start reading from the device*/
+	/* TODO: Look at possibility of submitting mulitple URBs to device to
+	 *       enhance buffering.  Win trace shows 16 initial read URBs.
+	 */
+	port->read_urb->dev = port->serial->dev;
+	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (retval) {
+		err("usb_submit_urb(read bulk) failed");
+		goto exit;
 	}
-	
+
+	port->interrupt_in_urb->dev = port->serial->dev;
+	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (retval)
+		err(" usb_submit_urb(read int) failed");
+
 exit:
 	return retval;
 } /* belkin_sa_open */
@@ -245,16 +238,11 @@
 
 	dbg(__FUNCTION__" port %d", port->number);
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			/* shutdown our bulk reads and writes */
-			usb_unlink_urb (port->write_urb);
-			usb_unlink_urb (port->read_urb);
-			usb_unlink_urb (port->interrupt_in_urb);
-		}
-		port->open_count = 0;
+	if (serial->dev) {
+		/* shutdown our bulk reads and writes */
+		usb_unlink_urb (port->write_urb);
+		usb_unlink_urb (port->read_urb);
+		usb_unlink_urb (port->interrupt_in_urb);
 	}
 } /* belkin_sa_close */
 
@@ -336,12 +324,31 @@
 {
 	struct usb_serial *serial = port->serial;
 	struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private;
-	unsigned int iflag = port->tty->termios->c_iflag;
-	unsigned int cflag = port->tty->termios->c_cflag;
-	unsigned int old_iflag = old_termios->c_iflag;
-	unsigned int old_cflag = old_termios->c_cflag;
+	unsigned int iflag;
+	unsigned int cflag;
+	unsigned int old_iflag = 0;
+	unsigned int old_cflag = 0;
 	__u16 urb_value = 0; /* Will hold the new flags */
 	
+	if ((!port->tty) || (!port->tty->termios)) {
+		dbg ("%s - no tty or termios structure", __FUNCTION__);
+		return;
+	}
+
+	iflag = port->tty->termios->c_iflag;
+	cflag = port->tty->termios->c_cflag;
+
+	/* check that they really want us to change something */
+	if (old_termios) {
+		if ((cflag == old_termios->c_cflag) &&
+		    (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+			dbg("%s - nothing to change...", __FUNCTION__);
+			return;
+		}
+		old_iflag = old_termios->c_iflag;
+		old_cflag = old_termios->c_cflag;
+	}
+
 	/* Set the baud rate */
 	if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
 		/* reassert DTR and (maybe) RTS on transition from B0 */
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/usb/serial/cyberjack.c	Sun Apr 14 12:16:59 2002
@@ -130,11 +130,7 @@
 	
 	dbg (__FUNCTION__);
 
-	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			cyberjack_close (&serial->port[i], NULL);
-		}
 		/* My special items, the standard routines free my urbs */
 		if (serial->port[i].private)
 			kfree(serial->port[i].private);
@@ -151,31 +147,27 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-		/* force low_latency on so that our tty_push actually forces
-		 * the data through, otherwise it is scheduled, and with high
-		 * data rates (like with OHCI) data can get lost.
-		 */
-		port->tty->low_latency = 1;
-
-		priv = (struct cyberjack_private *)port->private;
-		priv->rdtodo = 0;
-		priv->wrfilled = 0;
-		priv->wrsent = 0;
-
-		/* shutdown any bulk reads that might be going on */
-		usb_unlink_urb (port->write_urb);
-		usb_unlink_urb (port->read_urb);
-		usb_unlink_urb (port->interrupt_in_urb);
-
-		port->interrupt_in_urb->dev = port->serial->dev;
-		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-		if (result)
-			err(" usb_submit_urb(read int) failed");
-		dbg(__FUNCTION__ " - usb_submit_urb(int urb)");
-	}
+	/* force low_latency on so that our tty_push actually forces
+	 * the data through, otherwise it is scheduled, and with high
+	 * data rates (like with OHCI) data can get lost.
+	 */
+	port->tty->low_latency = 1;
+
+	priv = (struct cyberjack_private *)port->private;
+	priv->rdtodo = 0;
+	priv->wrfilled = 0;
+	priv->wrsent = 0;
+
+	/* shutdown any bulk reads that might be going on */
+	usb_unlink_urb (port->write_urb);
+	usb_unlink_urb (port->read_urb);
+	usb_unlink_urb (port->interrupt_in_urb);
+
+	port->interrupt_in_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (result)
+		err(" usb_submit_urb(read int) failed");
+	dbg(__FUNCTION__ " - usb_submit_urb(int urb)");
 
 	return result;
 }
@@ -184,16 +176,11 @@
 {
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (port->serial->dev) {
-			/* shutdown any bulk reads that might be going on */
-			usb_unlink_urb (port->write_urb);
-			usb_unlink_urb (port->read_urb);
-			usb_unlink_urb (port->interrupt_in_urb);
-		}
-		port->open_count = 0;
+	if (port->serial->dev) {
+		/* shutdown any bulk reads that might be going on */
+		usb_unlink_urb (port->write_urb);
+		usb_unlink_urb (port->read_urb);
+		usb_unlink_urb (port->interrupt_in_urb);
 	}
 }
 
diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
--- a/drivers/usb/serial/digi_acceleport.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/serial/digi_acceleport.c	Sun Apr 14 12:16:58 2002
@@ -1490,28 +1490,17 @@
 		return( -EAGAIN );
 	}
 
-	/* inc module use count before sleeping to wait for closes */
-	++port->open_count;
-
 	/* wait for a close in progress to finish */
 	while( priv->dp_in_close ) {
 		cond_wait_interruptible_timeout_irqrestore(
 			&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
 			&priv->dp_port_lock, flags );
 		if( signal_pending(current) ) {
-			--port->open_count;
 			return( -EINTR );
 		}
 		spin_lock_irqsave( &priv->dp_port_lock, flags );
 	}
 
-	/* if port is already open, just return */
-	/* be sure exactly one open proceeds */
-	if( port->open_count != 1)  {
-		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-		return( 0 );
-	}
-
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
  
 	/* read modem signals automatically whenever they change */
@@ -1557,14 +1546,6 @@
 
 	/* do cleanup only after final close on this port */
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
-	if( port->open_count > 1 ) {
-		--port->open_count;
-		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-		return;
-	} else if( port->open_count <= 0 ) {
-		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-		return;
-	}
 	priv->dp_in_close = 1;
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
@@ -1637,7 +1618,6 @@
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
-	--port->open_count;
 	wake_up_interruptible( &priv->dp_close_wait );
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
@@ -1765,8 +1745,6 @@
 {
 
 	int i;
-	struct digi_port *priv;
-	unsigned long flags;
 
 
 dbg( "digi_shutdown: TOP, in_interrupt()=%d", in_interrupt() );
@@ -1775,16 +1753,6 @@
 	for( i=0; i<serial->type->num_ports+1; i++ ) {
 		usb_unlink_urb( serial->port[i].read_urb );
 		usb_unlink_urb( serial->port[i].write_urb );
-	}
-
-	/* dec module use count */
-	for( i=0; i<serial->type->num_ports; i++ ) {
-		priv = serial->port[i].private;
-		spin_lock_irqsave( &priv->dp_port_lock, flags );
-		while( serial->port[i].open_count > 0 ) {
-			--serial->port[i].open_count;
-		}
-		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 	}
 
 	/* free the private data structures for all ports */
diff -Nru a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
--- a/drivers/usb/serial/empeg.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/serial/empeg.c	Sun Apr 14 12:16:58 2002
@@ -157,35 +157,29 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	++port->open_count;
+	/* Force default termio settings */
+	empeg_set_termios (port, NULL) ;
 
-	if (port->open_count == 1) {
+	bytes_in = 0;
+	bytes_out = 0;
 
-		/* Force default termio settings */
-		empeg_set_termios (port, NULL) ;
-
-		bytes_in = 0;
-		bytes_out = 0;
-
-		/* Start reading from the device */
-		FILL_BULK_URB(
-			port->read_urb,
-			serial->dev, 
-			usb_rcvbulkpipe(serial->dev,
-				port->bulk_in_endpointAddress),
-			port->read_urb->transfer_buffer,
-			port->read_urb->transfer_buffer_length,
-			empeg_read_bulk_callback,
-			port);
-
-		port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+	/* Start reading from the device */
+	FILL_BULK_URB(
+		port->read_urb,
+		serial->dev, 
+		usb_rcvbulkpipe(serial->dev,
+			port->bulk_in_endpointAddress),
+		port->read_urb->transfer_buffer,
+		port->read_urb->transfer_buffer_length,
+		empeg_read_bulk_callback,
+		port);
 
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	port->read_urb->transfer_flags |= USB_QUEUE_BULK;
 
-		if (result)
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
-	}
+	if (result)
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 
 	return result;
 }
@@ -204,16 +198,10 @@
 	if (!serial)
 		return;
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			/* shutdown our bulk read */
-			usb_unlink_urb (port->read_urb);
-		}
-		port->open_count = 0;
+	if (serial->dev) {
+		/* shutdown our bulk read */
+		usb_unlink_urb (port->read_urb);
 	}
-
 	/* Uncomment the following line if you want to see some statistics in your syslog */
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
 }
@@ -491,17 +479,7 @@
 
 static void empeg_shutdown (struct usb_serial *serial)
 {
-	int i;
-
 	dbg (__FUNCTION__);
-
-	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			empeg_close (&serial->port[i], NULL);
-		}
-	}
-
 }
 
 
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/usb/serial/ftdi_sio.c	Sun Apr 14 12:16:56 2002
@@ -294,14 +294,8 @@
 
 static void ftdi_sio_shutdown (struct usb_serial *serial)
 {
-	
 	dbg (__FUNCTION__);
 
-
-	/* stop reads and writes on all ports */
-	while (serial->port[0].open_count > 0) {
-	        ftdi_sio_close (&serial->port[0], NULL);
-	}
 	if (serial->port[0].private){
 		kfree(serial->port[0].private);
 		serial->port[0].private = NULL;
@@ -319,45 +313,41 @@
 
 	dbg(__FUNCTION__);
 
-	++port->open_count;
-
-	if (port->open_count == 1){
-		/* This will push the characters through immediately rather 
-		   than queue a task to deliver them */
-		port->tty->low_latency = 1;
-
-		/* No error checking for this (will get errors later anyway) */
-		/* See ftdi_sio.h for description of what is reset */
-		usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-				FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
-				FTDI_SIO_RESET_SIO, 
-				0, buf, 0, WDR_TIMEOUT);
-
-		/* Setup termios defaults. According to tty_io.c the 
-		   settings are driver specific */
-		port->tty->termios->c_cflag =
-			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-
-		/* ftdi_sio_set_termios  will send usb control messages */
-		ftdi_sio_set_termios(port, &tmp_termios);	
-
-		/* Turn on RTS and DTR since we are not flow controlling by default */
-		if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
-			err(__FUNCTION__ " Error from DTR HIGH urb");
-		}
-		if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
-			err(__FUNCTION__ " Error from RTS HIGH urb");
-		}
-	
-		/* Start reading from the device */
-		FILL_BULK_URB(port->read_urb, serial->dev, 
-			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-			      ftdi_sio_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (result)
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+	/* This will push the characters through immediately rather 
+	   than queue a task to deliver them */
+	port->tty->low_latency = 1;
+
+	/* No error checking for this (will get errors later anyway) */
+	/* See ftdi_sio.h for description of what is reset */
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
+			FTDI_SIO_RESET_SIO, 
+			0, buf, 0, WDR_TIMEOUT);
+
+	/* Setup termios defaults. According to tty_io.c the 
+	   settings are driver specific */
+	port->tty->termios->c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+
+	/* ftdi_sio_set_termios  will send usb control messages */
+	ftdi_sio_set_termios(port, &tmp_termios);	
+
+	/* Turn on RTS and DTR since we are not flow controlling by default */
+	if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
+		err(__FUNCTION__ " Error from DTR HIGH urb");
 	}
+	if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
+		err(__FUNCTION__ " Error from RTS HIGH urb");
+	}
+
+	/* Start reading from the device */
+	FILL_BULK_URB(port->read_urb, serial->dev, 
+		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+		      ftdi_sio_read_bulk_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (result)
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 
 	return result;
 } /* ftdi_sio_open */
@@ -371,41 +361,31 @@
 
 	dbg( __FUNCTION__);
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			if (c_cflag & HUPCL){
-				/* Disable flow control */
-				if (usb_control_msg(serial->dev, 
-						    usb_sndctrlpipe(serial->dev, 0),
-						    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
-						    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-						    0, 0, buf, 0, WDR_TIMEOUT) < 0) {
-					err("error from flowcontrol urb");
-				}	    
-
-				/* drop DTR */
-				if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){
-					err("Error from DTR LOW urb");
-				}
-				/* drop RTS */
-				if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) {
-					err("Error from RTS LOW urb");
-				}	
-			} /* Note change no line is hupcl is off */
-
-			/* shutdown our bulk reads and writes */
-			/* ***CHECK*** behaviour when there is nothing queued */
-			usb_unlink_urb (port->write_urb);
-			usb_unlink_urb (port->read_urb);
-		}
-		port->open_count = 0;
-	} else {  
-		/* Send a HUP if necessary */
-		if (!(port->tty->termios->c_cflag & CLOCAL)){
-			tty_hangup(port->tty);
-		}
+	if (serial->dev) {
+		if (c_cflag & HUPCL){
+			/* Disable flow control */
+			if (usb_control_msg(serial->dev, 
+					    usb_sndctrlpipe(serial->dev, 0),
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+					    0, 0, buf, 0, WDR_TIMEOUT) < 0) {
+				err("error from flowcontrol urb");
+			}	    
+
+			/* drop DTR */
+			if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){
+				err("Error from DTR LOW urb");
+			}
+			/* drop RTS */
+			if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) {
+				err("Error from RTS LOW urb");
+			}	
+		} /* Note change no line is hupcl is off */
+
+		/* shutdown our bulk reads and writes */
+		/* ***CHECK*** behaviour when there is nothing queued */
+		usb_unlink_urb (port->write_urb);
+		usb_unlink_urb (port->read_urb);
 	}
 } /* ftdi_sio_close */
 
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/usb/serial/io_edgeport.c	Sun Apr 14 12:16:55 2002
@@ -274,7 +274,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.2"
+#define DRIVER_VERSION "v2.3"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
@@ -811,7 +811,8 @@
 						dbg(__FUNCTION__" - txcredits for port%d = %d", portNumber, edge_port->txCredits);
 
 						/* tell the tty driver that something has changed */
-						wake_up_interruptible(&edge_port->port->tty->write_wait);
+						if (edge_port->port->tty)
+							wake_up_interruptible(&edge_port->port->tty->write_wait);
 
 						// Since we have more credit, check if more data can be sent
 						send_more_port_data(edge_serial, edge_port);
@@ -898,13 +899,15 @@
 
 	tty = edge_port->port->tty;
 
-	/* let the tty driver wakeup if it has a special write_wakeup function */
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		(tty->ldisc.write_wakeup)(tty);
-	}
+	if (tty) {
+		/* let the tty driver wakeup if it has a special write_wakeup function */
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
+			(tty->ldisc.write_wakeup)(tty);
+		}
 
-	/* tell the tty driver that something has changed */
-	wake_up_interruptible(&tty->write_wait);
+		/* tell the tty driver that something has changed */
+		wake_up_interruptible(&tty->write_wait);
+	}
 
 	// Release the Write URB
 	edge_port->write_in_progress = FALSE;
@@ -953,7 +956,8 @@
 	tty = edge_port->port->tty;
 
 	/* tell the tty driver that something has changed */
-	wake_up_interruptible(&tty->write_wait);
+	if (tty)
+		wake_up_interruptible(&tty->write_wait);
 
 	/* we have completed the command */
 	edge_port->commandPending = FALSE;
@@ -987,124 +991,118 @@
 	if (edge_port == NULL)
 		return -ENODEV;
 
-	++port->open_count;
-	
-	if (port->open_count == 1) {
-		/* force low_latency on so that our tty_push actually forces the data through, 
-		   otherwise it is scheduled, and with high data rates (like with OHCI) data
-		   can get lost. */
+	/* force low_latency on so that our tty_push actually forces the data through, 
+	   otherwise it is scheduled, and with high data rates (like with OHCI) data
+	   can get lost. */
+	if (port->tty)
 		port->tty->low_latency = 1;
+
+	/* see if we've set up our endpoint info yet (can't set it up in edge_startup
+	   as the structures were not set up at that time.) */
+	serial = port->serial;
+	edge_serial = (struct edgeport_serial *)serial->private;
+	if (edge_serial == NULL) {
+		return -ENODEV;
+	}
+	if (edge_serial->interrupt_in_buffer == NULL) {
+		struct usb_serial_port *port0 = &serial->port[0];
+		
+		/* not set up yet, so do it now */
+		edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;
+		edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;
+		edge_serial->interrupt_read_urb = port0->interrupt_in_urb;
+		edge_serial->bulk_in_buffer = port0->bulk_in_buffer;
+		edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;
+		edge_serial->read_urb = port0->read_urb;
+		edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
 	
-		/* see if we've set up our endpoint info yet (can't set it up in edge_startup
-		   as the structures were not set up at that time.) */
-		serial = port->serial;
-		edge_serial = (struct edgeport_serial *)serial->private;
-		if (edge_serial == NULL) {
-			port->open_count = 0;
-			return -ENODEV;
-		}
-		if (edge_serial->interrupt_in_buffer == NULL) {
-			struct usb_serial_port *port0 = &serial->port[0];
-			
-			/* not set up yet, so do it now */
-			edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;
-			edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;
-			edge_serial->interrupt_read_urb = port0->interrupt_in_urb;
-			edge_serial->bulk_in_buffer = port0->bulk_in_buffer;
-			edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;
-			edge_serial->read_urb = port0->read_urb;
-			edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
+		/* set up our interrupt urb */
+		FILL_INT_URB(edge_serial->interrupt_read_urb,
+			     serial->dev,
+			     usb_rcvintpipe(serial->dev,
+					    port0->interrupt_in_endpointAddress),
+			     port0->interrupt_in_buffer,
+			     edge_serial->interrupt_read_urb->transfer_buffer_length,
+			     edge_interrupt_callback, edge_serial,
+			     edge_serial->interrupt_read_urb->interval);
 		
-			/* set up our interrupt urb */
-			FILL_INT_URB(edge_serial->interrupt_read_urb,
-				     serial->dev,
-				     usb_rcvintpipe(serial->dev,
-					            port0->interrupt_in_endpointAddress),
-				     port0->interrupt_in_buffer,
-				     edge_serial->interrupt_read_urb->transfer_buffer_length,
-				     edge_interrupt_callback, edge_serial,
-				     edge_serial->interrupt_read_urb->interval);
-			
-			/* set up our bulk in urb */
-			FILL_BULK_URB(edge_serial->read_urb, serial->dev,
-				      usb_rcvbulkpipe(serial->dev, port0->bulk_in_endpointAddress),
-				      port0->bulk_in_buffer,
-				      edge_serial->read_urb->transfer_buffer_length,
-				      edge_bulk_in_callback, edge_serial);
-
-			/* start interrupt read for this edgeport
-			 * this interrupt will continue as long as the edgeport is connected */
-			response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
-			if (response) {
-				err(__FUNCTION__" - Error %d submitting control urb", response);
-			}
+		/* set up our bulk in urb */
+		FILL_BULK_URB(edge_serial->read_urb, serial->dev,
+			      usb_rcvbulkpipe(serial->dev, port0->bulk_in_endpointAddress),
+			      port0->bulk_in_buffer,
+			      edge_serial->read_urb->transfer_buffer_length,
+			      edge_bulk_in_callback, edge_serial);
+
+		/* start interrupt read for this edgeport
+		 * this interrupt will continue as long as the edgeport is connected */
+		response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
+		if (response) {
+			err(__FUNCTION__" - Error %d submitting control urb", response);
 		}
-		
-		/* initialize our wait queues */
-		init_waitqueue_head(&edge_port->wait_open);
-		init_waitqueue_head(&edge_port->wait_chase);
-		init_waitqueue_head(&edge_port->delta_msr_wait);
-		init_waitqueue_head(&edge_port->wait_command);
-
-		/* initialize our icount structure */
-		memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
-		/* initialize our port settings */
-		edge_port->txCredits            = 0;			/* Can't send any data yet */
-		edge_port->shadowMCR            = MCR_MASTER_IE;	/* Must always set this bit to enable ints! */
-		edge_port->chaseResponsePending = FALSE;
+	}
+	
+	/* initialize our wait queues */
+	init_waitqueue_head(&edge_port->wait_open);
+	init_waitqueue_head(&edge_port->wait_chase);
+	init_waitqueue_head(&edge_port->delta_msr_wait);
+	init_waitqueue_head(&edge_port->wait_command);
+
+	/* initialize our icount structure */
+	memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+
+	/* initialize our port settings */
+	edge_port->txCredits            = 0;			/* Can't send any data yet */
+	edge_port->shadowMCR            = MCR_MASTER_IE;	/* Must always set this bit to enable ints! */
+	edge_port->chaseResponsePending = FALSE;
+
+	/* send a open port command */
+	edge_port->openPending = TRUE;
+	edge_port->open        = FALSE;
+	response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
 
-		/* send a open port command */
-		edge_port->openPending = TRUE;
-		edge_port->open        = FALSE;
-		response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+	if (response < 0) {
+		err(__FUNCTION__" - error sending open port command");
+		edge_port->openPending = FALSE;
+		return -ENODEV;
+	}
 
-		if (response < 0) {
-			err(__FUNCTION__" - error sending open port command");
-			edge_port->openPending = FALSE;
-			port->open_count = 0;
-			return -ENODEV;
-		}
-
-		/* now wait for the port to be completly opened */
-		timeout = OPEN_TIMEOUT;
-		while (timeout && edge_port->openPending == TRUE) {
-			timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout);
-		}
-
-		if (edge_port->open == FALSE) {
-			/* open timed out */
-			dbg(__FUNCTION__" - open timedout");
-			edge_port->openPending = FALSE;
-			port->open_count = 0;
-			return -ENODEV;
-		}
-
-		/* create the txfifo */
-		edge_port->txfifo.head	= 0;
-		edge_port->txfifo.tail	= 0;
-		edge_port->txfifo.count	= 0;
-		edge_port->txfifo.size	= edge_port->maxTxCredits;
-		edge_port->txfifo.fifo	= kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
-
-		if (!edge_port->txfifo.fifo) {
-			dbg(__FUNCTION__" - no memory");
-			edge_close (port, filp);
-			return -ENOMEM;
-		}
+	/* now wait for the port to be completly opened */
+	timeout = OPEN_TIMEOUT;
+	while (timeout && edge_port->openPending == TRUE) {
+		timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout);
+	}
 
-		/* Allocate a URB for the write */
-		edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
+	if (edge_port->open == FALSE) {
+		/* open timed out */
+		dbg(__FUNCTION__" - open timedout");
+		edge_port->openPending = FALSE;
+		return -ENODEV;
+	}
 
-		if (!edge_port->write_urb) {
-			dbg(__FUNCTION__" - no memory");
-			edge_close (port, filp);
-			return -ENOMEM;
-		}
+	/* create the txfifo */
+	edge_port->txfifo.head	= 0;
+	edge_port->txfifo.tail	= 0;
+	edge_port->txfifo.count	= 0;
+	edge_port->txfifo.size	= edge_port->maxTxCredits;
+	edge_port->txfifo.fifo	= kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+
+	if (!edge_port->txfifo.fifo) {
+		dbg(__FUNCTION__" - no memory");
+		edge_close (port, filp);
+		return -ENOMEM;
+	}
 
-		dbg(__FUNCTION__"(%d) - Initialize TX fifo to %d bytes", port->number, edge_port->maxTxCredits);
+	/* Allocate a URB for the write */
+	edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
+
+	if (!edge_port->write_urb) {
+		dbg(__FUNCTION__" - no memory");
+		edge_close (port, filp);
+		return -ENOMEM;
 	}
 
+	dbg(__FUNCTION__"(%d) - Initialize TX fifo to %d bytes", port->number, edge_port->maxTxCredits);
+
 	dbg(__FUNCTION__" exited");
 
 	return 0;
@@ -1234,52 +1232,47 @@
 	if ((edge_serial == NULL) || (edge_port == NULL))
 		return;
 	
-	--port->open_count;
+	if (serial->dev) {
+		// block until tx is empty
+		block_until_tx_empty(edge_port);
+
+		edge_port->closePending = TRUE;
+
+		/* flush and chase */
+		edge_port->chaseResponsePending = TRUE;
+
+		dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
+		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+		if (status == 0) {
+			// block until chase finished
+			block_until_chase_response(edge_port);
+		} else {
+			edge_port->chaseResponsePending = FALSE;
+		}
 
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			// block until tx is empty
-			block_until_tx_empty(edge_port);
-
-			edge_port->closePending = TRUE;
-
-			/* flush and chase */
-			edge_port->chaseResponsePending = TRUE;
-
-			dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");
-			status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
-			if (status == 0) {
-				// block until chase finished
-				block_until_chase_response(edge_port);
-			} else {
-				edge_port->chaseResponsePending = FALSE;
-			}
+		/* close the port */
+		dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
+		send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
 
-			/* close the port */
-			dbg(__FUNCTION__" - Sending IOSP_CMD_CLOSE_PORT");
-			send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
-
-			//port->close = TRUE;
-			edge_port->closePending = FALSE;
-			edge_port->open = FALSE;
-			edge_port->openPending = FALSE;
+		//port->close = TRUE;
+		edge_port->closePending = FALSE;
+		edge_port->open = FALSE;
+		edge_port->openPending = FALSE;
 
-			if (edge_port->write_urb) {
-				usb_unlink_urb (edge_port->write_urb);
-			}
-		}
-	
 		if (edge_port->write_urb) {
-			/* if this urb had a transfer buffer already (old transfer) free it */
-			if (edge_port->write_urb->transfer_buffer != NULL) {
-				kfree(edge_port->write_urb->transfer_buffer);
-			}
-			usb_free_urb   (edge_port->write_urb);
+			usb_unlink_urb (edge_port->write_urb);
 		}
-		if (edge_port->txfifo.fifo) {
-			kfree(edge_port->txfifo.fifo);
+	}
+
+	if (edge_port->write_urb) {
+		/* if this urb had a transfer buffer already (old transfer) free it */
+		if (edge_port->write_urb->transfer_buffer != NULL) {
+			kfree(edge_port->write_urb->transfer_buffer);
 		}
-		port->open_count = 0;
+		usb_free_urb   (edge_port->write_urb);
+	}
+	if (edge_port->txfifo.fifo) {
+		kfree(edge_port->txfifo.fifo);
 	}
 
 	dbg(__FUNCTION__" exited");
@@ -1580,6 +1573,10 @@
 	}
 
 	tty = port->tty;
+	if (!tty) {
+		dbg ("%s - no tty available", __FUNCTION__);
+		return;
+	}
 
 	/* if we are implementing XON/XOFF, send the stop character */
 	if (I_IXOFF(tty)) {
@@ -1625,6 +1622,10 @@
 	}
 
 	tty = port->tty;
+	if (!tty) {
+		dbg ("%s - no tty available", __FUNCTION__);
+		return;
+	}
 
 	/* if we are implementing XON/XOFF, send the start character */
 	if (I_IXOFF(tty)) {
@@ -1656,15 +1657,14 @@
 {
 	struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
 	struct tty_struct *tty = port->tty;
-	unsigned int cflag = tty->termios->c_cflag;
+	unsigned int cflag;
 
-	dbg(__FUNCTION__" - clfag %08x %08x iflag %08x %08x", 
-	    tty->termios->c_cflag,
-	    old_termios->c_cflag,
-	    RELEVANT_IFLAG(tty->termios->c_iflag),
-	    RELEVANT_IFLAG(old_termios->c_iflag)
-	   );
+	if (!port->tty || !port->tty->termios) {
+		dbg ("%s - no tty or termios", __FUNCTION__);
+		return;
+	}
 
+	cflag = tty->termios->c_cflag;
 	/* check that they really want us to change something */
 	if (old_termios) {
 		if ((cflag == old_termios->c_cflag) &&
@@ -1674,6 +1674,15 @@
 		}
 	}
 
+	dbg("%s - clfag %08x iflag %08x", __FUNCTION__, 
+	    tty->termios->c_cflag,
+	    RELEVANT_IFLAG(tty->termios->c_iflag));
+	if (old_termios) {
+		dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+		    old_termios->c_cflag,
+		    RELEVANT_IFLAG(old_termios->c_iflag));
+	}
+
 	dbg(__FUNCTION__" - port %d", port->number);
 
 	if (edge_port == NULL)
@@ -1721,6 +1730,9 @@
 	unsigned int result = 0;
 	struct tty_struct *tty = edge_port->port->tty;
 
+	if (!tty)
+		return -ENOIOCTLCMD;
+
 	result = tty->read_cnt;
 
 	dbg(__FUNCTION__"(%d) = %d",  edge_port->port->number, result);
@@ -2148,7 +2160,8 @@
 		handle_new_msr (edge_port, byte2);
 
 		/* send the current line settings to the port so we are in sync with any further termios calls */
-		change_port_settings (edge_port, edge_port->port->tty->termios);
+		if (edge_port->port->tty)
+			change_port_settings (edge_port, edge_port->port->tty->termios);
 
 		/* we have completed the open */
 		edge_port->openPending = FALSE;
@@ -2259,7 +2272,7 @@
 	}
 
 	/* Place LSR data byte into Rx buffer */
-	if (lsrData) {
+	if (lsrData && edge_port->port->tty) {
 		tty_insert_flip_char(edge_port->port->tty, data, 0);
 		tty_flip_buffer_push(edge_port->port->tty);
 	}
@@ -3027,9 +3040,6 @@
 
 	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			edge_close (&serial->port[i], NULL);
-		}
 		kfree (serial->port[i].private);
 		serial->port[i].private = NULL;
 	}
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/usb/serial/ipaq.c	Sun Apr 14 12:16:56 2002
@@ -9,6 +9,10 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
+ * (19/3/2002) ganesh
+ *	Don't submit urbs while holding spinlocks. Not strictly necessary
+ *	in 2.5.x.
+ *
  * (8/3/2002) ganesh
  * 	The ipaq sometimes emits a '\0' before the CLIENT string. At this
  * 	point of time, the ppp ldisc is not yet attached to the tty, so
@@ -65,7 +69,7 @@
 		       int count);
 static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf,
 			   int count);
-static int ipaq_write_flush(struct usb_serial_port *port);
+static void ipaq_write_gather(struct usb_serial_port *port);
 static void ipaq_read_bulk_callback (struct urb *urb);
 static void ipaq_write_bulk_callback(struct urb *urb);
 static int ipaq_write_room(struct usb_serial_port *port);
@@ -119,93 +123,89 @@
 	
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	++port->open_count;
-	
-	if (port->open_count == 1) {
-		bytes_in = 0;
-		bytes_out = 0;
-		priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
-		if (priv == NULL) {
-			err(__FUNCTION__ " - Out of memory");
-			return -ENOMEM;
-		}
-		port->private = (void *)priv;
-		priv->active = 0;
-		priv->queue_len = 0;
-		INIT_LIST_HEAD(&priv->queue);
-		INIT_LIST_HEAD(&priv->freelist);
-
-		for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
-			pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
-			if (pkt == NULL) {
-				goto enomem;
-			}
-			pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
-			if (pkt->data == NULL) {
-				kfree(pkt);
-				goto enomem;
-			}
-			pkt->len = 0;
-			pkt->written = 0;
-			INIT_LIST_HEAD(&pkt->list);
-			list_add(&pkt->list, &priv->freelist);
-			priv->free_len += PACKET_SIZE;
-		}
-
-		/*
-		 * Force low latency on. This will immediately push data to the line
-		 * discipline instead of queueing.
-		 */
-
-		port->tty->low_latency = 1;
-		port->tty->raw = 1;
-		port->tty->real_raw = 1;
-
-		/*
-		 * Lose the small buffers usbserial provides. Make larger ones.
-		 */
-
-		kfree(port->bulk_in_buffer);
-		kfree(port->bulk_out_buffer);
-		port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
-		if (port->bulk_in_buffer == NULL) {
+	bytes_in = 0;
+	bytes_out = 0;
+	priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+	if (priv == NULL) {
+		err(__FUNCTION__ " - Out of memory");
+		return -ENOMEM;
+	}
+	port->private = (void *)priv;
+	priv->active = 0;
+	priv->queue_len = 0;
+	INIT_LIST_HEAD(&priv->queue);
+	INIT_LIST_HEAD(&priv->freelist);
+
+	for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
+		pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
+		if (pkt == NULL) {
 			goto enomem;
 		}
-		port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
-		if (port->bulk_out_buffer == NULL) {
-			kfree(port->bulk_in_buffer);
+		pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
+		if (pkt->data == NULL) {
+			kfree(pkt);
 			goto enomem;
 		}
-		port->read_urb->transfer_buffer = port->bulk_in_buffer;
-		port->write_urb->transfer_buffer = port->bulk_out_buffer;
-		port->read_urb->transfer_buffer_length = URBDATA_SIZE;
-		port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
-		
-		/* Start reading from the device */
-		FILL_BULK_URB(port->read_urb, serial->dev, 
-			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-			      ipaq_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (result) {
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
-		}
+		pkt->len = 0;
+		pkt->written = 0;
+		INIT_LIST_HEAD(&pkt->list);
+		list_add(&pkt->list, &priv->freelist);
+		priv->free_len += PACKET_SIZE;
+	}
+
+	/*
+	 * Force low latency on. This will immediately push data to the line
+	 * discipline instead of queueing.
+	 */
+
+	port->tty->low_latency = 1;
+	port->tty->raw = 1;
+	port->tty->real_raw = 1;
+
+	/*
+	 * Lose the small buffers usbserial provides. Make larger ones.
+	 */
+
+	kfree(port->bulk_in_buffer);
+	kfree(port->bulk_out_buffer);
+	port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
+	if (port->bulk_in_buffer == NULL) {
+		goto enomem;
+	}
+	port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
+	if (port->bulk_out_buffer == NULL) {
+		kfree(port->bulk_in_buffer);
+		goto enomem;
+	}
+	port->read_urb->transfer_buffer = port->bulk_in_buffer;
+	port->write_urb->transfer_buffer = port->bulk_out_buffer;
+	port->read_urb->transfer_buffer_length = URBDATA_SIZE;
+	port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
+	
+	/* Start reading from the device */
+	FILL_BULK_URB(port->read_urb, serial->dev, 
+		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+		      ipaq_read_bulk_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (result) {
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+	}
 
-		/*
-		 * Send out two control messages observed in win98 sniffs. Not sure what
-		 * they do.
-		 */
-
-		result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
-				0x1, 0, NULL, 0, 5 * HZ);
-		if (result < 0) {
-			err(__FUNCTION__ " - failed doing control urb, error %d", result);
-		}
-		result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
-				0x1, 0, NULL, 0, 5 * HZ);
-		if (result < 0) {
-			err(__FUNCTION__ " - failed doing control urb, error %d", result);
-		}
+	/*
+	 * Send out two control messages observed in win98 sniffs. Not sure what
+	 * they do.
+	 */
+
+	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+			0x1, 0, NULL, 0, 5 * HZ);
+	if (result < 0) {
+		err(__FUNCTION__ " - failed doing control urb, error %d", result);
+	}
+	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+			0x1, 0, NULL, 0, 5 * HZ);
+	if (result < 0) {
+		err(__FUNCTION__ " - failed doing control urb, error %d", result);
 	}
 	
 	return result;
@@ -233,22 +233,16 @@
 	if (!serial)
 		return;
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
+	/*
+	 * shut down bulk read and write
+	 */
 
-		/*
-		 * shut down bulk read and write
-		 */
-
-		usb_unlink_urb(port->write_urb);
-		usb_unlink_urb(port->read_urb);
-		ipaq_destroy_lists(port);
-		kfree(priv);
-		port->private = NULL;
-		port->open_count = 0;
+	usb_unlink_urb(port->write_urb);
+	usb_unlink_urb(port->read_urb);
+	ipaq_destroy_lists(port);
+	kfree(priv);
+	port->private = NULL;
 
-	}
 	/* Uncomment the following line if you want to see some statistics in your syslog */
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
 }
@@ -367,17 +361,23 @@
 	priv->queue_len += count;
 	if (priv->active == 0) {
 		priv->active = 1;
-		result = ipaq_write_flush(port);
+		ipaq_write_gather(port);
+		spin_unlock_irqrestore(&write_list_lock, flags);
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result) {
+			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+		}
+	} else {
+		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
-	spin_unlock_irqrestore(&write_list_lock, flags);
 	return result;
 }
 
-static int ipaq_write_flush(struct usb_serial_port *port)
+static void ipaq_write_gather(struct usb_serial_port *port)
 {
 	struct ipaq_private	*priv = (struct ipaq_private *)port->private;
 	struct usb_serial	*serial = port->serial;
-	int			count, room, result;
+	int			count, room;
 	struct ipaq_packet	*pkt;
 	struct urb		*urb = port->write_urb;
 	struct list_head	*tmp;
@@ -385,7 +385,7 @@
 	if (urb->status == -EINPROGRESS) {
 		/* Should never happen */
 		err(__FUNCTION__ " - flushing while urb is active !");
-		return -EAGAIN;
+		return;
 	}
 	room = URBDATA_SIZE;
 	for (tmp = priv->queue.next; tmp != &priv->queue;) {
@@ -412,11 +412,7 @@
 		      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
 		      port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
 		      port);
-	result = usb_submit_urb(urb, GFP_ATOMIC);
-	if (result) {
-		err(__FUNCTION__ " - failed submitting write urb, error %d", result);
-	}
-	return result;
+	return;
 }
 
 static void ipaq_write_bulk_callback(struct urb *urb)
@@ -424,6 +420,7 @@
 	struct usb_serial_port	*port = (struct usb_serial_port *)urb->context;
 	struct ipaq_private	*priv = (struct ipaq_private *)port->private;
 	unsigned long		flags;
+	int			result;
 
 	if (port_paranoia_check (port, __FUNCTION__)) {
 		return;
@@ -437,11 +434,16 @@
 
 	spin_lock_irqsave(&write_list_lock, flags);
 	if (!list_empty(&priv->queue)) {
-		ipaq_write_flush(port);
+		ipaq_write_gather(port);
+		spin_unlock_irqrestore(&write_list_lock, flags);
+		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (result) {
+			err(__FUNCTION__ " - failed submitting write urb, error %d", result);
+		}
 	} else {
 		priv->active = 0;
+		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
-	spin_unlock_irqrestore(&write_list_lock, flags);
 	queue_task(&port->tqueue, &tq_immediate);
 	mark_bh(IMMEDIATE_BH);
 	
@@ -495,16 +497,7 @@
 
 static void ipaq_shutdown(struct usb_serial *serial)
 {
-	int i;
-
 	dbg (__FUNCTION__);
-
-	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			ipaq_close(&serial->port[i], NULL);
-		}
-	}
 }
 
 static int __init ipaq_init(void)
diff -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/serial/ir-usb.c	Sun Apr 14 12:16:58 2002
@@ -283,45 +283,42 @@
 	
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	++port->open_count;
-	
-	if (port->open_count == 1) {
-		if (buffer_size) {
-			/* override the default buffer sizes */
-			buffer = kmalloc (buffer_size, GFP_KERNEL);
-			if (!buffer) {
-				err ("%s - out of memory.", __FUNCTION__);
-				return -ENOMEM;
-			}
-			kfree (port->read_urb->transfer_buffer);
-			port->read_urb->transfer_buffer = buffer;
-			port->read_urb->transfer_buffer_length = buffer_size;
-
-			buffer = kmalloc (buffer_size, GFP_KERNEL);
-			if (!buffer) {
-				err ("%s - out of memory.", __FUNCTION__);
-				return -ENOMEM;
-			}
-			kfree (port->write_urb->transfer_buffer);
-			port->write_urb->transfer_buffer = buffer;
-			port->write_urb->transfer_buffer_length = buffer_size;
-			port->bulk_out_size = buffer_size;
+	if (buffer_size) {
+		/* override the default buffer sizes */
+		buffer = kmalloc (buffer_size, GFP_KERNEL);
+		if (!buffer) {
+			err ("%s - out of memory.", __FUNCTION__);
+			return -ENOMEM;
 		}
-
-		/* Start reading from the device */
-		usb_fill_bulk_urb (
-			port->read_urb,
-			serial->dev, 
-			usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-			port->read_urb->transfer_buffer,
-			port->read_urb->transfer_buffer_length,
-			ir_read_bulk_callback,
-			port);
-		port->read_urb->transfer_flags = USB_QUEUE_BULK;
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (result)
-			err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+		kfree (port->read_urb->transfer_buffer);
+		port->read_urb->transfer_buffer = buffer;
+		port->read_urb->transfer_buffer_length = buffer_size;
+
+		buffer = kmalloc (buffer_size, GFP_KERNEL);
+		if (!buffer) {
+			err ("%s - out of memory.", __FUNCTION__);
+			return -ENOMEM;
+		}
+		kfree (port->write_urb->transfer_buffer);
+		port->write_urb->transfer_buffer = buffer;
+		port->write_urb->transfer_buffer_length = buffer_size;
+		port->bulk_out_size = buffer_size;
 	}
+
+	/* Start reading from the device */
+	usb_fill_bulk_urb (
+		port->read_urb,
+		serial->dev, 
+		usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		port->read_urb->transfer_buffer,
+		port->read_urb->transfer_buffer_length,
+		ir_read_bulk_callback,
+		port);
+	port->read_urb->transfer_flags = USB_QUEUE_BULK;
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (result)
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+
 	return result;
 }
 
@@ -338,15 +335,9 @@
 	if (!serial)
 		return;
 	
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			/* shutdown our bulk read */
-			usb_unlink_urb (port->read_urb);
-		}
-		port->open_count = 0;
-
+	if (serial->dev) {
+		/* shutdown our bulk read */
+		usb_unlink_urb (port->read_urb);
 	}
 }
 
diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
--- a/drivers/usb/serial/keyspan.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/usb/serial/keyspan.c	Sun Apr 14 12:16:55 2002
@@ -852,7 +852,7 @@
 	struct keyspan_serial_private 	*s_priv;
 	struct usb_serial 		*serial = port->serial;
 	const struct keyspan_device_details	*d_details;
-	int				i, already_active, err;
+	int				i, err;
 	struct urb			*urb;
 
 	s_priv = (struct keyspan_serial_private *)(serial->private);
@@ -861,12 +861,6 @@
 	
 	dbg("keyspan_open called for port%d.\n", port->number); 
 
-	already_active = port->open_count;
-	++port->open_count;
-
-	if (already_active)
-		return 0;
-
 	p_priv = (struct keyspan_port_private *)(port->private);
 	
 	/* Set some sane defaults */
@@ -924,19 +918,16 @@
 	p_priv->out_flip = 0;
 	p_priv->in_flip = 0;
 
-	if (--port->open_count <= 0) {
-		if (serial->dev) {
-			/* Stop reading/writing urbs */
-			stop_urb(p_priv->inack_urb);
-			stop_urb(p_priv->outcont_urb);
-			for (i = 0; i < 2; i++) {
-				stop_urb(p_priv->in_urbs[i]);
-				stop_urb(p_priv->out_urbs[i]);
-			}
+	if (serial->dev) {
+		/* Stop reading/writing urbs */
+		stop_urb(p_priv->inack_urb);
+		stop_urb(p_priv->outcont_urb);
+		for (i = 0; i < 2; i++) {
+			stop_urb(p_priv->in_urbs[i]);
+			stop_urb(p_priv->out_urbs[i]);
 		}
-		port->open_count = 0;
-		port->tty = 0;
 	}
+	port->tty = 0;
 }
 
 
@@ -1762,9 +1753,6 @@
 	/* Now free per port private data */
 	for (i = 0; i < serial->num_ports; i++) {
 		port = &serial->port[i];
-		while (port->open_count > 0) {
-			--port->open_count;
-		}
 		kfree(port->private);
 	}
 }
diff -Nru a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/usb/serial/keyspan_pda.c	Sun Apr 14 12:16:59 2002
@@ -662,52 +662,45 @@
 	int rc = 0;
 	struct keyspan_pda_private *priv;
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-		/* find out how much room is in the Tx ring */
-		rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-				     6, /* write_room */
-				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
-				     | USB_DIR_IN,
-				     0, /* value */
-				     0, /* index */
-				     &room,
-				     1,
-				     2*HZ);
-		if (rc < 0) {
-			dbg(__FUNCTION__" - roomquery failed");
-			goto error;
-		}
-		if (rc == 0) {
-			dbg(__FUNCTION__" - roomquery returned 0 bytes");
-			rc = -EIO;
-			goto error;
-		}
-		priv = (struct keyspan_pda_private *)(port->private);
-		priv->tx_room = room;
-		priv->tx_throttled = room ? 0 : 1;
-
-		/* the normal serial device seems to always turn on DTR and RTS here,
-		   so do the same */
-		if (port->tty->termios->c_cflag & CBAUD)
-			keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
-		else
-			keyspan_pda_set_modem_info(serial, 0);
-
-		/*Start reading from the device*/
-		port->interrupt_in_urb->dev = serial->dev;
-		rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-		if (rc) {
-			dbg(__FUNCTION__" - usb_submit_urb(read int) failed");
-			goto error;
-		}
-
+	/* find out how much room is in the Tx ring */
+	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			     6, /* write_room */
+			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+			     | USB_DIR_IN,
+			     0, /* value */
+			     0, /* index */
+			     &room,
+			     1,
+			     2*HZ);
+	if (rc < 0) {
+		dbg(__FUNCTION__" - roomquery failed");
+		goto error;
+	}
+	if (rc == 0) {
+		dbg(__FUNCTION__" - roomquery returned 0 bytes");
+		rc = -EIO;
+		goto error;
+	}
+	priv = (struct keyspan_pda_private *)(port->private);
+	priv->tx_room = room;
+	priv->tx_throttled = room ? 0 : 1;
+
+	/* the normal serial device seems to always turn on DTR and RTS here,
+	   so do the same */
+	if (port->tty->termios->c_cflag & CBAUD)
+		keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
+	else
+		keyspan_pda_set_modem_info(serial, 0);
+
+	/*Start reading from the device*/
+	port->interrupt_in_urb->dev = serial->dev;
+	rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (rc) {
+		dbg(__FUNCTION__" - usb_submit_urb(read int) failed");
+		goto error;
 	}
 
-	return rc;
 error:
-	--port->open_count;
 	return rc;
 }
 
@@ -716,19 +709,14 @@
 {
 	struct usb_serial *serial = port->serial;
 
-	--port->open_count;
+	if (serial->dev) {
+		/* the normal serial device seems to always shut off DTR and RTS now */
+		if (port->tty->termios->c_cflag & HUPCL)
+			keyspan_pda_set_modem_info(serial, 0);
 
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			/* the normal serial device seems to always shut off DTR and RTS now */
-			if (port->tty->termios->c_cflag & HUPCL)
-				keyspan_pda_set_modem_info(serial, 0);
-
-			/* shutdown our bulk reads and writes */
-			usb_unlink_urb (port->write_urb);
-			usb_unlink_urb (port->interrupt_in_urb);
-		}
-		port->open_count = 0;
+		/* shutdown our bulk reads and writes */
+		usb_unlink_urb (port->write_urb);
+		usb_unlink_urb (port->interrupt_in_urb);
 	}
 }
 
@@ -805,9 +793,6 @@
 {
 	dbg (__FUNCTION__);
 	
-	while (serial->port[0].open_count > 0) {
-		keyspan_pda_close (&serial->port[0], NULL);
-	}
 	kfree(serial->port[0].private);
 }
 
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/usb/serial/kl5kusb105.c	Sun Apr 14 12:16:54 2002
@@ -317,9 +317,6 @@
 		struct klsi_105_private *priv = 
 			(struct klsi_105_private*) serial->port[i].private;
 		unsigned long flags;
-		while (serial->port[i].open_count > 0) {
-			klsi_105_close (&serial->port[i], NULL);
-		}
 
 		if (priv) {
 			/* kill our write urb pool */
@@ -355,85 +352,80 @@
 	struct usb_serial *serial = port->serial;
 	struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
 	int retval = 0;
+	int rc;
+	int i;
+	unsigned long line_state;
 
 	dbg(__FUNCTION__" port %d", port->number);
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-		int rc;
-		int i;
-		unsigned long line_state;
-
-		/* force low_latency on so that our tty_push actually forces
-		 * the data through
-		 * port->tty->low_latency = 1; */
-
-		/* Do a defined restart:
-		 * Set up sane default baud rate and send the 'READ_ON'
-		 * vendor command. 
-		 * FIXME: set modem line control (how?)
-		 * Then read the modem line control and store values in
-		 * priv->line_state.
-		 */
-		priv->cfg.pktlen   = 5;
-		priv->cfg.baudrate = kl5kusb105a_sio_b9600;
-		priv->cfg.databits = kl5kusb105a_dtb_8;
-		priv->cfg.unknown1 = 0;
-		priv->cfg.unknown2 = 1;
-		klsi_105_chg_port_settings(serial, &(priv->cfg));
-		
-		/* set up termios structure */
-		priv->termios.c_iflag = port->tty->termios->c_iflag;
-		priv->termios.c_oflag = port->tty->termios->c_oflag;
-		priv->termios.c_cflag = port->tty->termios->c_cflag;
-		priv->termios.c_lflag = port->tty->termios->c_lflag;
-		for (i=0; i<NCCS; i++)
-			priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
-
-
-		/* READ_ON and urb submission */
-		FILL_BULK_URB(port->read_urb, serial->dev, 
-			      usb_rcvbulkpipe(serial->dev,
-					      port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer,
-			      port->read_urb->transfer_buffer_length,
-			      klsi_105_read_bulk_callback,
-			      port);
-		port->read_urb->transfer_flags |= USB_QUEUE_BULK;
-
-		rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (rc) {
-			err(__FUNCTION__ 
-			    " - failed submitting read urb, error %d", rc);
-			retval = rc;
-			goto exit;
-		}
-
-		rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),
-				     KL5KUSB105A_SIO_CONFIGURE,
-				     USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
-				     KL5KUSB105A_SIO_CONFIGURE_READ_ON,
-				     0, /* index */
-				     NULL,
-				     0,
-				     KLSI_TIMEOUT);
-		if (rc < 0) {
-			err("Enabling read failed (error = %d)", rc);
-			retval = rc;
-		} else 
-			dbg(__FUNCTION__ " - enabled reading");
-
-		rc = klsi_105_get_line_state(serial, &line_state);
-		if (rc >= 0) {
-			priv->line_state = line_state;
-			dbg(__FUNCTION__ 
-			    " - read line state 0x%lx", line_state);
-			retval = 0;
-		} else
-			retval = rc;
+	/* force low_latency on so that our tty_push actually forces
+	 * the data through
+	 * port->tty->low_latency = 1; */
+
+	/* Do a defined restart:
+	 * Set up sane default baud rate and send the 'READ_ON'
+	 * vendor command. 
+	 * FIXME: set modem line control (how?)
+	 * Then read the modem line control and store values in
+	 * priv->line_state.
+	 */
+	priv->cfg.pktlen   = 5;
+	priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+	priv->cfg.databits = kl5kusb105a_dtb_8;
+	priv->cfg.unknown1 = 0;
+	priv->cfg.unknown2 = 1;
+	klsi_105_chg_port_settings(serial, &(priv->cfg));
+	
+	/* set up termios structure */
+	priv->termios.c_iflag = port->tty->termios->c_iflag;
+	priv->termios.c_oflag = port->tty->termios->c_oflag;
+	priv->termios.c_cflag = port->tty->termios->c_cflag;
+	priv->termios.c_lflag = port->tty->termios->c_lflag;
+	for (i=0; i<NCCS; i++)
+		priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
+
+
+	/* READ_ON and urb submission */
+	FILL_BULK_URB(port->read_urb, serial->dev, 
+		      usb_rcvbulkpipe(serial->dev,
+				      port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer,
+		      port->read_urb->transfer_buffer_length,
+		      klsi_105_read_bulk_callback,
+		      port);
+	port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+
+	rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (rc) {
+		err(__FUNCTION__ 
+		    " - failed submitting read urb, error %d", rc);
+		retval = rc;
+		goto exit;
 	}
 
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),
+			     KL5KUSB105A_SIO_CONFIGURE,
+			     USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
+			     KL5KUSB105A_SIO_CONFIGURE_READ_ON,
+			     0, /* index */
+			     NULL,
+			     0,
+			     KLSI_TIMEOUT);
+	if (rc < 0) {
+		err("Enabling read failed (error = %d)", rc);
+		retval = rc;
+	} else 
+		dbg(__FUNCTION__ " - enabled reading");
+
+	rc = klsi_105_get_line_state(serial, &line_state);
+	if (rc >= 0) {
+		priv->line_state = line_state;
+		dbg(__FUNCTION__ 
+		    " - read line state 0x%lx", line_state);
+		retval = 0;
+	} else
+		retval = rc;
+
 exit:
 	return retval;
 } /* klsi_105_open */
@@ -444,6 +436,7 @@
 	struct usb_serial *serial;
 	struct klsi_105_private *priv 
 		= (struct klsi_105_private *)port->private;
+	int rc;
 	dbg(__FUNCTION__" port %d", port->number);
 
 	serial = get_usb_serial (port, __FUNCTION__);
@@ -451,31 +444,26 @@
 	if(!serial)
 		return;
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		/* send READ_OFF */
-		int rc = usb_control_msg(serial->dev,
-					 usb_sndctrlpipe(serial->dev, 0),
-					 KL5KUSB105A_SIO_CONFIGURE,
-					 USB_TYPE_VENDOR | USB_DIR_OUT,
-					 KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
-					 0, /* index */
-					 NULL, 0,
-					 KLSI_TIMEOUT);
-		if (rc < 0)
-			    err("Disabling read failed (error = %d)", rc);
-
-		/* shutdown our bulk reads and writes */
-		usb_unlink_urb (port->write_urb);
-		usb_unlink_urb (port->read_urb);
-		/* unlink our write pool */
-		/* FIXME */
-		/* wgg - do I need this? I think so. */
-		usb_unlink_urb (port->interrupt_in_urb);
-		port->open_count = 0;
-		info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
-	}
+	/* send READ_OFF */
+	rc = usb_control_msg (serial->dev,
+			      usb_sndctrlpipe(serial->dev, 0),
+			      KL5KUSB105A_SIO_CONFIGURE,
+			      USB_TYPE_VENDOR | USB_DIR_OUT,
+			      KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+			      0, /* index */
+			      NULL, 0,
+			      KLSI_TIMEOUT);
+	if (rc < 0)
+		    err("Disabling read failed (error = %d)", rc);
+
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (port->write_urb);
+	usb_unlink_urb (port->read_urb);
+	/* unlink our write pool */
+	/* FIXME */
+	/* wgg - do I need this? I think so. */
+	usb_unlink_urb (port->interrupt_in_urb);
+	info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
 } /* klsi_105_close */
 
 
diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c	Sun Apr 14 12:16:59 2002
+++ b/drivers/usb/serial/mct_u232.c	Sun Apr 14 12:16:59 2002
@@ -324,9 +324,6 @@
 
 	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			mct_u232_close (&serial->port[i], NULL);
-		}
 		/* My special items, the standard routines free my urbs */
 		if (serial->port[i].private)
 			kfree(serial->port[i].private);
@@ -341,60 +338,55 @@
 
 	dbg(__FUNCTION__" port %d", port->number);
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-		/* Compensate for a hardware bug: although the Sitecom U232-P25
-		 * device reports a maximum output packet size of 32 bytes,
-		 * it seems to be able to accept only 16 bytes (and that's what
-		 * SniffUSB says too...)
-		 */
-		if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
-			port->bulk_out_size = 16;
-
-		/* Do a defined restart: the normal serial device seems to 
-		 * always turn on DTR and RTS here, so do the same. I'm not
-		 * sure if this is really necessary. But it should not harm
-		 * either.
-		 */
-		if (port->tty->termios->c_cflag & CBAUD)
-			priv->control_state = TIOCM_DTR | TIOCM_RTS;
-		else
-			priv->control_state = 0;
-		mct_u232_set_modem_ctrl(serial, priv->control_state);
-		
-		priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
-				  MCT_U232_PARITY_NONE |
-				  MCT_U232_STOP_BITS_1);
-		mct_u232_set_line_ctrl(serial, priv->last_lcr);
-
-		/* Read modem status and update control state */
-		mct_u232_get_modem_stat(serial, &priv->last_msr);
-		mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
-
-		{
-			/* Puh, that's dirty */
-			struct usb_serial_port *rport;	
-			rport = &serial->port[1];
-			rport->tty = port->tty;
-			rport->private = port->private;
-			port->read_urb = rport->interrupt_in_urb;
-		}
-
-		port->read_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (retval) {
-			err("usb_submit_urb(read bulk) failed");
-			goto exit;
-		}
-
-		port->interrupt_in_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-		if (retval)
-			err(" usb_submit_urb(read int) failed");
+	/* Compensate for a hardware bug: although the Sitecom U232-P25
+	 * device reports a maximum output packet size of 32 bytes,
+	 * it seems to be able to accept only 16 bytes (and that's what
+	 * SniffUSB says too...)
+	 */
+	if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
+		port->bulk_out_size = 16;
+
+	/* Do a defined restart: the normal serial device seems to 
+	 * always turn on DTR and RTS here, so do the same. I'm not
+	 * sure if this is really necessary. But it should not harm
+	 * either.
+	 */
+	if (port->tty->termios->c_cflag & CBAUD)
+		priv->control_state = TIOCM_DTR | TIOCM_RTS;
+	else
+		priv->control_state = 0;
+	mct_u232_set_modem_ctrl(serial, priv->control_state);
+	
+	priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
+			  MCT_U232_PARITY_NONE |
+			  MCT_U232_STOP_BITS_1);
+	mct_u232_set_line_ctrl(serial, priv->last_lcr);
+
+	/* Read modem status and update control state */
+	mct_u232_get_modem_stat(serial, &priv->last_msr);
+	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
+
+	{
+		/* Puh, that's dirty */
+		struct usb_serial_port *rport;	
+		rport = &serial->port[1];
+		rport->tty = port->tty;
+		rport->private = port->private;
+		port->read_urb = rport->interrupt_in_urb;
+	}
 
+	port->read_urb->dev = port->serial->dev;
+	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (retval) {
+		err("usb_submit_urb(read bulk) failed");
+		goto exit;
 	}
 
+	port->interrupt_in_urb->dev = port->serial->dev;
+	retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+	if (retval)
+		err(" usb_submit_urb(read int) failed");
+
 exit:
 	return 0;
 } /* mct_u232_open */
@@ -404,16 +396,11 @@
 {
 	dbg(__FUNCTION__" port %d", port->number);
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (port->serial->dev) {
-			/* shutdown our urbs */
-			usb_unlink_urb (port->write_urb);
-			usb_unlink_urb (port->read_urb);
-			usb_unlink_urb (port->interrupt_in_urb);
-		}
-		port->open_count = 0;
+	if (port->serial->dev) {
+		/* shutdown our urbs */
+		usb_unlink_urb (port->write_urb);
+		usb_unlink_urb (port->read_urb);
+		usb_unlink_urb (port->interrupt_in_urb);
 	}
 } /* mct_u232_close */
 
diff -Nru a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
--- a/drivers/usb/serial/omninet.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/usb/serial/omninet.c	Sun Apr 14 12:16:57 2002
@@ -157,29 +157,24 @@
 	if (!serial)
 		return -ENODEV;
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-		od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
-		if( !od ) {
-			err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
-			port->open_count = 0;
-			return -ENOMEM;
-		}
+	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+	if( !od ) {
+		err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
+		return -ENOMEM;
+	}
 
-		port->private = od;
-		wport = &serial->port[1];
-		wport->tty = port->tty;
+	port->private = od;
+	wport = &serial->port[1];
+	wport->tty = port->tty;
 
-		/* Start reading from the device */
-		FILL_BULK_URB(port->read_urb, serial->dev, 
-			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-			      omninet_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (result)
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
-	}
+	/* Start reading from the device */
+	FILL_BULK_URB(port->read_urb, serial->dev, 
+		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+		      omninet_read_bulk_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (result)
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 
 	return result;
 }
@@ -199,20 +194,15 @@
 	if (!serial)
 		return;
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			wport = &serial->port[1];
-			usb_unlink_urb (wport->write_urb);
-			usb_unlink_urb (port->read_urb);
-		}
-
-		port->open_count = 0;
-		od = (struct omninet_data *)port->private;
-		if (od)
-			kfree(od);
+	if (serial->dev) {
+		wport = &serial->port[1];
+		usb_unlink_urb (wport->write_urb);
+		usb_unlink_urb (port->read_urb);
 	}
+
+	od = (struct omninet_data *)port->private;
+	if (od)
+		kfree(od);
 }
 
 
@@ -377,10 +367,6 @@
 static void omninet_shutdown (struct usb_serial *serial)
 {
 	dbg (__FUNCTION__);
-
-	while (serial->port[0].open_count > 0) {
-		omninet_close (&serial->port[0], NULL);
-	}
 }
 
 
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/serial/pl2303.c	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,7 @@
 /*
  * Prolific PL2303 USB to serial adaptor driver
  *
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
  *
  * Original driver for 2.2.x by anonymous
  *
@@ -12,6 +12,10 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * 2002_Mar_26 gkh
+ *	allowed driver to work properly if there is no tty assigned to a port
+ *	(this happens for serial console devices.)
+ *
  * 2001_Oct_06 gkh
  *	Added RTS and DTR line control.  Thanks to joe@bndlg.de for parts of it.
  *
@@ -173,11 +177,6 @@
 
 	dbg (__FUNCTION__ " - port %d, %d bytes", port->number, count);
 
-	if (!port->tty) {
-		err (__FUNCTION__ " - no tty???");
-		return 0;
-	}
-
 	if (port->write_urb->status == -EINPROGRESS) {
 		dbg (__FUNCTION__ " - already writing");
 		return 0;
@@ -367,56 +366,54 @@
 		
 	dbg (__FUNCTION__ " -  port %d", port->number);
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-#define FISH(a,b,c,d)									\
-		result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
-				       b, a, c, d, buf, 1, 100);			\
-		dbg("0x%x:0x%x:0x%x:0x%x  %d - %x",a,b,c,d,result,buf[0]);
-
-#define SOUP(a,b,c,d)									\
-		result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),	\
-				       b, a, c, d, NULL, 0, 100);			\
-		dbg("0x%x:0x%x:0x%x:0x%x  %d",a,b,c,d,result);
-
-		FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
-		FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-		FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
-		FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
-		FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
-		FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0xc0);
-		SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 4);
+#define FISH(a,b,c,d)								\
+	result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
+			       b, a, c, d, buf, 1, 100);			\
+	dbg("0x%x:0x%x:0x%x:0x%x  %d - %x",a,b,c,d,result,buf[0]);
+
+#define SOUP(a,b,c,d)								\
+	result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0),	\
+			       b, a, c, d, NULL, 0, 100);			\
+	dbg("0x%x:0x%x:0x%x:0x%x  %d",a,b,c,d,result);
+
+	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
+	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0);
+	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
+	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
+	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
+	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
+	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
+	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
+	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
+	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0xc0);
+	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 4);
 
-		/* Setup termios */
+	/* Setup termios */
+	if (port->tty) {
 		*(port->tty->termios) = tty_std_termios;
 		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 
 		pl2303_set_termios (port, &tmp_termios);
+	}
 
-		//FIXME: need to assert RTS and DTR if CRTSCTS off
-
-		dbg (__FUNCTION__ " - submitting read urb");
-		port->read_urb->dev = serial->dev;
-		result = usb_submit_urb (port->read_urb, GFP_KERNEL);
-		if (result) {
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
-			pl2303_close (port, NULL);
-			return -EPROTO;
-		}
+	//FIXME: need to assert RTS and DTR if CRTSCTS off
 
-		dbg (__FUNCTION__ " - submitting interrupt urb");
-		port->interrupt_in_urb->dev = serial->dev;
-		result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
-		if (result) {
-			err(__FUNCTION__ " - failed submitting interrupt urb, error %d", result);
-			pl2303_close (port, NULL);
-			return -EPROTO;
-		}
+	dbg (__FUNCTION__ " - submitting read urb");
+	port->read_urb->dev = serial->dev;
+	result = usb_submit_urb (port->read_urb, GFP_KERNEL);
+	if (result) {
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+		pl2303_close (port, NULL);
+		return -EPROTO;
+	}
+
+	dbg (__FUNCTION__ " - submitting interrupt urb");
+	port->interrupt_in_urb->dev = serial->dev;
+	result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
+	if (result) {
+		err(__FUNCTION__ " - failed submitting interrupt urb, error %d", result);
+		pl2303_close (port, NULL);
+		return -EPROTO;
 	}
 	return 0;
 }
@@ -437,9 +434,8 @@
 	
 	dbg (__FUNCTION__ " - port %d", port->number);
 
-	--port->open_count;
-	if (port->open_count <= 0) {
-		if (serial->dev) {
+	if (serial->dev) {
+		if (port->tty) {
 			c_cflag = port->tty->termios->c_cflag;
 			if (c_cflag & HUPCL) {
 				/* drop DTR and RTS */
@@ -448,28 +444,27 @@
 				set_control_lines (port->serial->dev,
 						   priv->line_control);
 			}
-
-			/* shutdown our urbs */
-			dbg (__FUNCTION__ " - shutting down urbs");
-			result = usb_unlink_urb (port->write_urb);
-			if (result)
-				dbg (__FUNCTION__ " - usb_unlink_urb "
-				     "(write_urb) failed with reason: %d",
-				     result);
-
-			result = usb_unlink_urb (port->read_urb);
-			if (result)
-				dbg (__FUNCTION__ " - usb_unlink_urb "
-				     "(read_urb) failed with reason: %d",
-				     result);
-
-			result = usb_unlink_urb (port->interrupt_in_urb);
-			if (result)
-				dbg (__FUNCTION__ " - usb_unlink_urb "
-				     "(interrupt_in_urb) failed with reason: %d",
-				     result);
 		}
-		port->open_count = 0;
+
+		/* shutdown our urbs */
+		dbg (__FUNCTION__ " - shutting down urbs");
+		result = usb_unlink_urb (port->write_urb);
+		if (result)
+			dbg (__FUNCTION__ " - usb_unlink_urb "
+			     "(write_urb) failed with reason: %d",
+			     result);
+
+		result = usb_unlink_urb (port->read_urb);
+		if (result)
+			dbg (__FUNCTION__ " - usb_unlink_urb "
+			     "(read_urb) failed with reason: %d",
+			     result);
+
+		result = usb_unlink_urb (port->interrupt_in_urb);
+		if (result)
+			dbg (__FUNCTION__ " - usb_unlink_urb "
+			     "(interrupt_in_urb) failed with reason: %d",
+			     result);
 	}
 }
 
@@ -577,12 +572,8 @@
 
 	dbg (__FUNCTION__);
 
-	/* stop everything on all ports */
 	for (i = 0; i < serial->num_ports; ++i)
-		while (serial->port[i].open_count > 0) {
-			pl2303_close (&serial->port[i], NULL);
-			kfree (serial->port[i].private);
-		}
+		kfree (serial->port[i].private);
 }
 
 
@@ -655,7 +646,7 @@
 	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
 	tty = port->tty;
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 		for (i = 0; i < urb->actual_length; ++i) {
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 				tty_flip_buffer_push(tty);
diff -Nru a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/serial/safe_serial.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,449 @@
+/*
+ * Safe Encapsulated USB Serial Driver
+ *
+ *      Copyright (c) 2001 Lineo
+ *      Copyright (c) 2001 Hewlett-Packard
+ *
+ *	This program is free software; you can redistribute it and/or 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.
+ *
+ * By:
+ *      Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
+ */
+
+/* 
+ * The encapsultaion is designed to overcome difficulties with some USB hardware.
+ *
+ * While the USB protocol has a CRC over the data while in transit, i.e. while
+ * being carried over the bus, there is no end to end protection. If the hardware
+ * has any problems getting the data into or out of the USB transmit and receive
+ * FIFO's then data can be lost. 
+ *
+ * This protocol adds a two byte trailer to each USB packet to specify the number
+ * of bytes of valid data and a 10 bit CRC that will allow the receiver to verify
+ * that the entire USB packet was received without error.
+ *
+ * Because in this case the sender and receiver are the class and function drivers
+ * there is now end to end protection.
+ *
+ * There is an additional option that can be used to force all transmitted packets
+ * to be padded to the maximum packet size. This provides a work around for some
+ * devices which have problems with small USB packets.
+ *
+ * Assuming a packetsize of N:
+ *
+ *      0..N-2  data and optional padding
+ *
+ *      N-2     bits 7-2 - number of bytes of valid data
+ *              bits 1-0 top two bits of 10 bit CRC
+ *      N-1     bottom 8 bits of 10 bit CRC
+ *
+ *
+ *      | Data Length       | 10 bit CRC                                |
+ *      + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
+ *
+ * The 10 bit CRC is computed across the sent data, followed by the trailer with
+ * the length set and the CRC set to zero. The CRC is then OR'd into the trailer.
+ *
+ * When received a 10 bit CRC is computed over the entire frame including the trailer
+ * and should be equal to zero.
+ *
+ * Two module parameters are used to control the encapsulation, if both are
+ * turned of the module works as a simple serial device with NO
+ * encapsulation.
+ *
+ * See linux/drivers/usbd/serial_fd for a device function driver
+ * implementation of this.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+
+
+#ifndef CONFIG_USB_SERIAL_DEBUG
+#define CONFIG_USB_SERIAL_DEBUG 0
+#endif
+#ifndef CONFIG_USB_SAFE_PADDED
+#define CONFIG_USB_SAFE_PADDED 0
+#endif
+
+static int debug = CONFIG_USB_SERIAL_DEBUG;
+#include "usb-serial.h"		// must follow the declaration of debug
+
+static int safe = 1;
+static int padded = CONFIG_USB_SAFE_PADDED;
+
+#define DRIVER_VERSION "v0.0b"
+#define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
+#define DRIVER_DESC "USB Safe Encapsulated Serial"
+
+MODULE_AUTHOR (DRIVER_AUTHOR);
+MODULE_DESCRIPTION (DRIVER_DESC);
+
+#if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT)
+#abort "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT"
+#endif
+
+#if ! defined(CONFIG_USBD_SAFE_SERIAL_VENDOR)
+static __u16 vendor;		// no default
+static __u16 product;		// no default
+MODULE_PARM (vendor, "i");
+MODULE_PARM (product, "i");
+MODULE_PARM_DESC (vendor, "User specified USB idVendor (required)");
+MODULE_PARM_DESC (product, "User specified USB idProduct (required)");
+#endif
+
+MODULE_PARM (debug, "i");
+MODULE_PARM (safe, "i");
+MODULE_PARM (padded, "i");
+
+MODULE_PARM_DESC (debug, "Debug enabled or not");
+MODULE_PARM_DESC (safe, "Turn Safe Encapsulation On/Off");
+MODULE_PARM_DESC (padded, "Pad to full wMaxPacketSize On/Off");
+
+#define CDC_DEVICE_CLASS                        0x02
+
+#define CDC_INTERFACE_CLASS                     0x02
+#define CDC_INTERFACE_SUBCLASS                  0x06
+
+#define LINEO_INTERFACE_CLASS                   0xff
+
+#define LINEO_INTERFACE_SUBCLASS_SAFENET        0x01
+#define LINEO_SAFENET_CRC                       0x01
+#define LINEO_SAFENET_CRC_PADDED                0x02
+
+#define LINEO_INTERFACE_SUBCLASS_SAFESERIAL     0x02
+#define LINEO_SAFESERIAL_CRC                    0x01
+#define LINEO_SAFESERIAL_CRC_PADDED             0x02
+
+
+#define MY_USB_DEVICE(vend,prod,dc,ic,isc) \
+        match_flags: USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS | \
+                USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
+        idVendor: (vend), \
+        idProduct: (prod),\
+        bDeviceClass: (dc),\
+        bInterfaceClass: (ic), \
+        bInterfaceSubClass: (isc),
+
+static __devinitdata struct usb_device_id id_table[] = {
+	{MY_USB_DEVICE (0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Itsy
+	{MY_USB_DEVICE (0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Calypso
+	{MY_USB_DEVICE (0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Iris 
+	{MY_USB_DEVICE (0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Collie 
+	{MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Collie 
+	{MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Collie 
+	{MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Sharp tmp
+#if defined(CONFIG_USB_SAFE_SERIAL_VENDOR)
+	{MY_USB_DEVICE
+	 (CONFIG_USB_SAFE_SERIAL_VENDOR, CONFIG_USB_SAFE_SERIAL_PRODUCT, CDC_DEVICE_CLASS,
+	  LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
+#endif
+	// extra null entry for module 
+	// vendor/produc parameters
+	{MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
+	{}			// terminating entry 
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+static __u16 crc10_table[256] = {
+	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
+	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
+	0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
+	0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
+	0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
+	0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
+	0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
+	0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
+	0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
+	0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
+	0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
+	0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
+	0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
+	0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
+	0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
+	0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
+};
+
+#define CRC10_INITFCS     0x000	// Initial FCS value
+#define CRC10_GOODFCS     0x000	// Good final FCS value
+#define CRC10_FCS(fcs, c) ( (((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
+
+/**     
+ * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
+ * @sp: pointer to buffer
+ * @len: number of bytes
+ * @fcs: starting FCS
+ *
+ * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
+ * new 10 bit FCS.
+ */
+static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
+{
+	for (; len-- > 0; fcs = CRC10_FCS (fcs, *sp++));
+	return fcs;
+}
+
+static void safe_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	unsigned char *data = urb->transfer_buffer;
+	unsigned char length = urb->actual_length;
+	int i;
+	int result;
+
+	dbg ("%s", __FUNCTION__);
+
+	if (!serial) {
+		dbg (__FUNCTION__ " - bad serial pointer, exiting");
+		return;
+	}
+
+	if (urb->status) {
+		dbg (__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+	dbg ("safe_read_bulk_callback length: %d", port->read_urb->actual_length);
+#ifdef ECHO_RCV
+	{
+		int i;
+		unsigned char *cp = port->read_urb->transfer_buffer;
+		for (i = 0; i < port->read_urb->actual_length; i++) {
+			if ((i % 32) == 0) {
+				printk ("\nru[%02x] ", i);
+			}
+			printk ("%02x ", *cp++);
+		}
+		printk ("\n");
+	}
+#endif
+	if (safe) {
+		__u16 fcs;
+		if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
+
+			int actual_length = data[length - 2] >> 2;
+
+			if (actual_length <= (length - 2)) {
+
+				info (__FUNCTION__ " - actual: %d", actual_length);
+
+				for (i = 0; i < actual_length; i++) {
+					tty_insert_flip_char (port->tty, data[i], 0);
+				}
+				tty_flip_buffer_push (port->tty);
+			} else {
+				err (__FUNCTION__ " - inconsistant lengths %d:%d", actual_length,
+				     length);
+			}
+		} else {
+			err (__FUNCTION__ " - bad CRC %x", fcs);
+		}
+	} else {
+		for (i = 0; i < length; i++) {
+			tty_insert_flip_char (port->tty, data[i], 0);
+		}
+		tty_flip_buffer_push (port->tty);
+	}
+
+	/* Continue trying to always read  */
+	FILL_BULK_URB (urb, serial->dev,
+		       usb_rcvbulkpipe (serial->dev, port->bulk_in_endpointAddress),
+		       urb->transfer_buffer, urb->transfer_buffer_length,
+		       safe_read_bulk_callback, port);
+
+	if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
+		err (__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+	}
+}
+
+static int safe_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = port->serial;
+	unsigned char *data;
+	int result;
+	int i;
+	int packet_length;
+
+	dbg ("safe_write port: %p %d urb: %p count: %d", port, port->number, port->write_urb,
+	     count);
+
+	if (!port->write_urb) {
+		dbg (__FUNCTION__ " - write urb NULL");
+		return (0);
+	}
+
+	dbg ("safe_write write_urb: %d transfer_buffer_length",
+	     port->write_urb->transfer_buffer_length);
+
+	if (!port->write_urb->transfer_buffer_length) {
+		dbg (__FUNCTION__ " - write urb transfer_buffer_length zero");
+		return (0);
+	}
+	if (count == 0) {
+		dbg (__FUNCTION__ " - write request of 0 bytes");
+		return (0);
+	}
+	if (port->write_urb->status == -EINPROGRESS) {
+		dbg (__FUNCTION__ " - already writing");
+		return (0);
+	}
+
+	packet_length = port->bulk_out_size;	// get max packetsize
+
+	i = packet_length - (safe ? 2 : 0);	// get bytes to send
+	count = (count > i) ? i : count;
+
+
+	// get the data into the transfer buffer
+	data = port->write_urb->transfer_buffer;
+	memset (data, '0', packet_length);
+
+	if (from_user) {
+		copy_from_user (data, buf, count);
+	} else {
+		memcpy (data, buf, count);
+	}
+
+	if (safe) {
+		__u16 fcs;
+
+		// pad if necessary
+		if (!padded) {
+			packet_length = count + 2;
+		}
+		// set count
+		data[packet_length - 2] = count << 2;
+		data[packet_length - 1] = 0;
+
+		// compute fcs and insert into trailer
+		fcs = fcs_compute10 (data, packet_length, CRC10_INITFCS);
+		data[packet_length - 2] |= fcs >> 8;
+		data[packet_length - 1] |= fcs & 0xff;
+
+		// set length to send
+		port->write_urb->transfer_buffer_length = packet_length;
+	} else {
+		port->write_urb->transfer_buffer_length = count;
+	}
+
+	usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+#ifdef ECHO_TX
+	{
+		int i;
+		unsigned char *cp = port->write_urb->transfer_buffer;
+		for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
+			if ((i % 32) == 0) {
+				printk ("\nsu[%02x] ", i);
+			}
+			printk ("%02x ", *cp++);
+		}
+		printk ("\n");
+	}
+#endif
+	port->write_urb->dev = serial->dev;
+	if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
+		err (__FUNCTION__ " - failed submitting write urb, error %d", result);
+		return 0;
+	}
+	dbg (__FUNCTION__ " urb: %p submitted", port->write_urb);
+
+	return (count);
+}
+
+static int safe_write_room (struct usb_serial_port *port)
+{
+	int room = 0;		// Default: no room
+
+	dbg ("%s", __FUNCTION__);
+
+	if (port->write_urb->status != -EINPROGRESS)
+		room = port->bulk_out_size - (safe ? 2 : 0);
+
+	if (room) {
+		dbg ("safe_write_room returns %d", room);
+	}
+
+	return (room);
+}
+
+static int safe_startup (struct usb_serial *serial)
+{
+	switch (serial->interface->altsetting->bInterfaceProtocol) {
+	case LINEO_SAFESERIAL_CRC:
+		break;
+	case LINEO_SAFESERIAL_CRC_PADDED:
+		padded = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct usb_serial_device_type safe_device = {
+	owner:			THIS_MODULE,
+	name:			"Safe",
+	id_table:		id_table,
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		1,
+	write:			safe_write,
+	write_room:		safe_write_room,
+	read_bulk_callback:	safe_read_bulk_callback,
+	startup:		safe_startup,
+};
+
+static int __init safe_init (void)
+{
+	int i;
+
+	info (DRIVER_VERSION " " DRIVER_AUTHOR);
+	info (DRIVER_DESC);
+	info ("vendor: %x product: %x safe: %d padded: %d\n", vendor, product, safe, padded);
+
+	// if we have vendor / product parameters patch them into id list
+	if (vendor || product) {
+		info ("vendor: %x product: %x\n", vendor, product);
+
+		for (i = 0; i < (sizeof (id_table) / sizeof (struct usb_device_id)); i++) {
+			if (!id_table[i].idVendor && !id_table[i].idProduct) {
+				id_table[i].idVendor = vendor;
+				id_table[i].idProduct = product;
+				break;
+			}
+		}
+	}
+
+	usb_serial_register (&safe_device);
+
+	return 0;
+}
+
+static void __exit safe_exit (void)
+{
+	usb_serial_deregister (&safe_device);
+}
+
+module_init (safe_init);
+module_exit (safe_exit);
diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h	Sun Apr 14 12:16:59 2002
+++ b/drivers/usb/serial/usb-serial.h	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- *	Copyright (C) 1999 - 2001
+ *	Copyright (C) 1999 - 2002
  *	    Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or modify
@@ -11,6 +11,10 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (03/26/2002) gkh
+ *	removed the port->tty check from port_paranoia_check() due to serial
+ *	consoles not having a tty device assigned to them.
+ *
  * (12/03/2001) gkh
  *	removed active from the port structure.
  *	added documentation to the usb_serial_device_type structure
@@ -224,10 +228,6 @@
 	}
 	if (!port->serial) {
 		dbg("%s - port->serial == NULL", function);
-		return -1;
-	}
-	if (!port->tty) {
-		dbg("%s - port->tty == NULL", function);
 		return -1;
 	}
 
diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/serial/usbserial.c	Sun Apr 14 12:16:58 2002
@@ -15,6 +15,19 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (03/27/2002) gkh
+ *	Got USB serial console code working properly and merged into the main
+ *	version of the tree.  Thanks to Randy Dunlap for the initial version
+ *	of this code, and for pushing me to finish it up.
+ *	The USB serial console works with any usb serial driver device.
+ *
+ * (03/21/2002) gkh
+ *	Moved all manipulation of port->open_count into the core.  Now the
+ *	individual driver's open and close functions are called only when the
+ *	first open() and last close() is called.  Making the drivers a bit
+ *	smaller and simpler.
+ *	Fixed a bug if a driver didn't have the owner field set.
+ *
  * (02/26/2002) gkh
  *	Moved all locking into the main serial_* functions, instead of having 
  *	the individual drivers have to grab the port semaphore.  This should
@@ -307,6 +320,14 @@
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 
+#ifdef MODULE
+#undef CONFIG_USB_SERIAL_CONSOLE
+#endif
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+#include <linux/console.h>
+#include <linux/serial.h>
+#endif
+
 #ifdef CONFIG_USB_SERIAL_DEBUG
 	static int debug = 1;
 #else
@@ -395,6 +416,16 @@
 static struct usb_serial	*serial_table[SERIAL_TTY_MINORS];	/* initially all NULL */
 static LIST_HEAD(usb_serial_driver_list);
 
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+struct usbcons_info {
+	int			magic;
+	int			break_flag;
+	struct usb_serial_port	*port;
+};
+
+static struct usbcons_info usbcons_info;
+static struct console usbcons;
+#endif /* CONFIG_USB_SERIAL_CONSOLE */
 
 static struct usb_serial *get_serial_by_minor (unsigned int minor)
 {
@@ -500,7 +531,7 @@
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	unsigned int portNumber;
-	int retval;
+	int retval = 0;
 	
 	dbg(__FUNCTION__);
 
@@ -525,19 +556,48 @@
 	if (serial->type->owner)
 		__MOD_INC_USE_COUNT(serial->type->owner);
 
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->open)
-		retval = serial->type->open(port, filp);
-	else
-		retval = generic_open(port, filp);
+	++port->open_count;
+	if (port->open_count == 1) {
+		/* only call the device specific open if this 
+		 * is the first time the port is opened */
+		if (serial->type->open)
+			retval = serial->type->open(port, filp);
+		else
+			retval = generic_open(port, filp);
+	}
 
-	if (retval)
-		__MOD_DEC_USE_COUNT(serial->type->owner);
+	if (retval) {
+		port->open_count = 0;
+		if (serial->type->owner)
+			__MOD_DEC_USE_COUNT(serial->type->owner);
+	}
 
 	up (&port->sem);
 	return retval;
 }
 
+static void __serial_close(struct usb_serial_port *port, struct file *filp)
+{
+	if (!port->open_count) {
+		dbg (__FUNCTION__ " - port not opened");
+		return;
+	}
+
+	--port->open_count;
+	if (port->open_count <= 0) {
+		/* only call the device specific close if this 
+		 * port is being closed by the last owner */
+		if (port->serial->type->close)
+			port->serial->type->close(port, filp);
+		else
+			generic_close(port, filp);
+		port->open_count = 0;
+	}
+
+	if (port->serial->type->owner)
+		__MOD_DEC_USE_COUNT(port->serial->type->owner);
+}
+
 static void serial_close(struct tty_struct *tty, struct file * filp)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
@@ -550,26 +610,11 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (tty->driver_data == NULL) {
-		/* disconnect beat us to the punch here, so handle it gracefully */
-		goto exit;
-	}
-	if (!port->open_count) {
-		dbg (__FUNCTION__ " - port not opened");
-		goto exit_no_mod_dec;
+	/* if disconnect beat us to the punch here, there's nothing to do */
+	if (tty->driver_data) {
+		__serial_close(port, filp);
 	}
 
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->close)
-		serial->type->close(port, filp);
-	else
-		generic_close(port, filp);
-
-exit:
-	if (serial->type->owner)
-		__MOD_DEC_USE_COUNT(serial->type->owner);
-
-exit_no_mod_dec:
 	up (&port->sem);
 }
 
@@ -791,6 +836,8 @@
 
 static void serial_shutdown (struct usb_serial *serial)
 {
+	dbg(__FUNCTION__);
+
 	if (serial->type->shutdown)
 		serial->type->shutdown(serial);
 	else
@@ -810,54 +857,52 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	++port->open_count;
-
-	if (port->open_count == 1) {
-		/* force low_latency on so that our tty_push actually forces the data through, 
-		   otherwise it is scheduled, and with high data rates (like with OHCI) data
-		   can get lost. */
+	/* force low_latency on so that our tty_push actually forces the data through, 
+	   otherwise it is scheduled, and with high data rates (like with OHCI) data
+	   can get lost. */
+	if (port->tty)
 		port->tty->low_latency = 1;
 
-		/* if we have a bulk interrupt, start reading from it */
-		if (serial->num_bulk_in) {
-			/* Start reading from the device */
-			usb_fill_bulk_urb (port->read_urb, serial->dev,
-					   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-					   port->read_urb->transfer_buffer,
-					   port->read_urb->transfer_buffer_length,
-					   ((serial->type->read_bulk_callback) ?
-					     serial->type->read_bulk_callback :
-					     generic_read_bulk_callback),
-					   port);
-			result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-			if (result)
-				err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
-		}
+	/* if we have a bulk interrupt, start reading from it */
+	if (serial->num_bulk_in) {
+		/* Start reading from the device */
+		usb_fill_bulk_urb (port->read_urb, serial->dev,
+				   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+				   port->read_urb->transfer_buffer,
+				   port->read_urb->transfer_buffer_length,
+				   ((serial->type->read_bulk_callback) ?
+				     serial->type->read_bulk_callback :
+				     generic_read_bulk_callback),
+				   port);
+		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+		if (result)
+			err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
 	}
 
 	return result;
 }
 
-static void generic_close (struct usb_serial_port *port, struct file * filp)
+static void generic_cleanup (struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			/* shutdown any bulk reads that might be going on */
-			if (serial->num_bulk_out)
-				usb_unlink_urb (port->write_urb);
-			if (serial->num_bulk_in)
-				usb_unlink_urb (port->read_urb);
-		}
-		port->open_count = 0;
+	if (serial->dev) {
+		/* shutdown any bulk reads that might be going on */
+		if (serial->num_bulk_out)
+			usb_unlink_urb (port->write_urb);
+		if (serial->num_bulk_in)
+			usb_unlink_urb (port->read_urb);
 	}
 }
 
+static void generic_close (struct usb_serial_port *port, struct file * filp)
+{
+	dbg(__FUNCTION__ " - port %d", port->number);
+	generic_cleanup (port);
+}
+
 static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
@@ -968,7 +1013,7 @@
 	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
 	tty = port->tty;
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
 			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
 			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
@@ -1025,10 +1070,7 @@
 
 	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
-		down (&serial->port[i].sem);
-		while (serial->port[i].open_count > 0)
-			generic_close (&serial->port[i], NULL);
-		up (&serial->port[i].sem);
+		generic_cleanup (&serial->port[i]);
 	}
 }
 
@@ -1040,11 +1082,13 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
-	if (!serial) {
+	if (!serial)
 		return;
-	}
 
 	tty = port->tty;
+	if (!tty)
+		return;
+
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
 		dbg(__FUNCTION__ " - write wakeup call.");
 		(tty->ldisc.write_wakeup)(tty);
@@ -1294,6 +1338,26 @@
 		     type->name, serial->port[i].number, serial->port[i].number);
 	}
 
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+	if (minor == 0) {
+		/* 
+		 * Call register_console() if this is the first device plugged
+		 * in.  If we call it earlier, then the callback to
+		 * console_setup() will fail, as there is not a device seen by
+		 * the USB subsystem yet.
+		 */
+		/*
+		 * Register console.
+		 * NOTES:
+		 * console_setup() is called (back) immediately (from register_console).
+		 * console_write() is called immediately from register_console iff
+		 * CON_PRINTBUFFER is set in flags.
+		 */
+		dbg ("registering the USB serial console.");
+		register_console(&usbcons);
+	}
+#endif
+
 	return serial; /* success */
 
 
@@ -1334,13 +1398,19 @@
 	struct usb_serial_port *port;
 	int i;
 
+	dbg(__FUNCTION__);
 	if (serial) {
 		/* fail all future close/read/write/ioctl/etc calls */
 		for (i = 0; i < serial->num_ports; ++i) {
-			down (&serial->port[i].sem);
-			if (serial->port[i].tty != NULL)
-				serial->port[i].tty->driver_data = NULL;
-			up (&serial->port[i].sem);
+			port = &serial->port[i];
+			down (&port->sem);
+			if (port->tty != NULL) {
+				while (port->open_count > 0) {
+					__serial_close(port, NULL);
+				}
+				port->tty->driver_data = NULL;
+			}
+			up (&port->sem);
 		}
 
 		serial->dev = NULL;
@@ -1466,6 +1536,9 @@
 
 static void __exit usb_serial_exit(void)
 {
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+	unregister_console(&usbcons);
+#endif
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	/* remove our generic driver */
@@ -1515,7 +1588,7 @@
 
 
 
-/* If the usb-serial core is build into the core, the usb-serial drivers
+/* If the usb-serial core is built into the core, the usb-serial drivers
    need these symbols to load properly as modules. */
 EXPORT_SYMBOL(usb_serial_register);
 EXPORT_SYMBOL(usb_serial_deregister);
@@ -1523,6 +1596,241 @@
 	EXPORT_SYMBOL(ezusb_writememory);
 	EXPORT_SYMBOL(ezusb_set_reset);
 #endif
+
+
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+/*
+ * ------------------------------------------------------------
+ * USB Serial console driver
+ *
+ * Much of the code here is copied from drivers/char/serial.c
+ * and implements a phony serial console in the same way that
+ * serial.c does so that in case some software queries it,
+ * it will get the same results.
+ *
+ * Things that are different from the way the serial port code
+ * does things, is that we call the lower level usb-serial
+ * driver code to initialize the device, and we set the initial
+ * console speeds based on the command line arguments.
+ * ------------------------------------------------------------
+ */
+
+#if 0
+static kdev_t usb_console_device(struct console *co)
+{
+	return MKDEV(SERIAL_TTY_MAJOR, co->index);	/* TBD */
+}
+#endif
+
+/*
+ * The parsing of the command line works exactly like the
+ * serial.c code, except that the specifier is "ttyUSB" instead
+ * of "ttyS".
+ */
+static int __init usb_console_setup(struct console *co, char *options)
+{
+	struct usbcons_info *info = &usbcons_info;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int doflow = 0;
+	int cflag = CREAD | HUPCL | CLOCAL;
+	char *s;
+	struct usb_serial *serial;
+	struct usb_serial_port *port;
+	int retval = 0;
+	struct tty_struct *tty;
+	struct termios *termios;
+
+	dbg ("%s", __FUNCTION__);
+
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while (*s >= '0' && *s <= '9')
+			s++;
+		if (*s)	parity = *s++;
+		if (*s)	bits   = *s++ - '0';
+		if (*s)	doflow = (*s++ == 'r');
+	}
+
+	/* build a cflag setting */
+	switch (baud) {
+		case 1200:
+			cflag |= B1200;
+			break;
+		case 2400:
+			cflag |= B2400;
+			break;
+		case 4800:
+			cflag |= B4800;
+			break;
+		case 19200:
+			cflag |= B19200;
+			break;
+		case 38400:
+			cflag |= B38400;
+			break;
+		case 57600:
+			cflag |= B57600;
+			break;
+		case 115200:
+			cflag |= B115200;
+			break;
+		case 9600:
+		default:
+			cflag |= B9600;
+			/*
+			 * Set this to a sane value to prevent a divide error
+			 */
+			baud  = 9600;
+			break;
+	}
+	switch (bits) {
+		case 7:
+			cflag |= CS7;
+			break;
+		default:
+		case 8:
+			cflag |= CS8;
+			break;
+	}
+	switch (parity) {
+		case 'o': case 'O':
+			cflag |= PARODD;
+			break;
+		case 'e': case 'E':
+			cflag |= PARENB;
+			break;
+	}
+	co->cflag = cflag;
+
+	/* grab the first serial port that happens to be connected */
+	serial = get_serial_by_minor (0);
+	if (serial_paranoia_check (serial, __FUNCTION__)) {
+		/* no device is connected yet, sorry :( */
+		err ("No USB device connected to ttyUSB0");
+		return -ENODEV;
+	}
+
+	port = &serial->port[0];
+	down (&port->sem);
+	port->tty = NULL;
+
+	info->port = port;
+	 
+	++port->open_count;
+	if (port->open_count == 1) {
+		/* only call the device specific open if this 
+		 * is the first time the port is opened */
+		if (serial->type->open)
+			retval = serial->type->open(port, NULL);
+		else
+			retval = generic_open(port, NULL);
+		if (retval)
+			port->open_count = 0;
+	}
+
+	up (&port->sem);
+
+	if (retval) {
+		err ("could not open USB console port");
+		return retval;
+	}
+
+	if (serial->type->set_termios) {
+		/* build up a fake tty structure so that the open call has something
+		 * to look at to get the cflag value */
+		tty = kmalloc (sizeof (*tty), GFP_KERNEL);
+		if (!tty) {
+			err ("no more memory");
+			return -ENOMEM;
+		}
+		termios = kmalloc (sizeof (*termios), GFP_KERNEL);
+		if (!termios) {
+			err ("no more memory");
+			kfree (tty);
+			return -ENOMEM;
+		}
+		memset (tty, 0x00, sizeof(*tty));
+		memset (termios, 0x00, sizeof(*termios));
+		termios->c_cflag = cflag;
+		tty->termios = termios;
+		port->tty = tty;
+
+		/* set up the initial termios settings */
+		serial->type->set_termios(port, NULL);
+		port->tty = NULL;
+		kfree (termios);
+		kfree (tty);
+	}
+
+	return retval;
+}
+
+static void usb_console_write(struct console *co, const char *buf, unsigned count)
+{
+	static struct usbcons_info *info = &usbcons_info;
+	struct usb_serial_port *port = info->port;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	int retval = -ENODEV;
+
+	if (!serial || !port)
+		return;
+
+	if (count == 0)
+		return;
+
+	down (&port->sem);
+
+	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
+
+	if (!port->open_count) {
+		dbg (__FUNCTION__ " - port not opened");
+		goto exit;
+	}
+
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->write)
+		retval = serial->type->write(port, 0, buf, count);
+	else
+		retval = generic_write(port, 0, buf, count);
+
+exit:
+	up (&port->sem);
+	dbg("%s - return value (if we had one): %d", __FUNCTION__, retval);
+}
+
+#if 0
+/*
+ * Receive character from the serial port
+ */
+static int usb_console_wait_key(struct console *co)
+{
+	static struct usbcons_info *info = &usbcons_info;
+	int c = 0;
+
+	dbg("%s", __FUNCTION__);
+
+	/* maybe use generic_read_bulk_callback ??? */
+
+	return c;
+}
+#endif
+
+static struct console usbcons = {
+	name:		"ttyUSB",			/* only [8] */
+	write:		usb_console_write,
+#if 0
+	device:		usb_console_device,		/* TBD */
+	wait_key:	usb_console_wait_key,		/* TBD */
+#endif
+	setup:		usb_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
+#endif /* CONFIG_USB_SERIAL_CONSOLE */
 
 
 /* Module information */
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/usb/serial/visor.c	Sun Apr 14 12:16:57 2002
@@ -11,7 +11,23 @@
  *	(at your option) any later version.
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
+ *
+ * (04/03/2002) gkh
+ *	Added support for the Sony OS 4.1 devices.  Thanks to Hiroyuki ARAKI
+ *	<hiro@zob.ne.jp> for the information.
+ *
+ * (03/27/2002) gkh
+ *	Removed assumptions that port->tty was always valid (is not true
+ *	for usb serial console devices.)
+ *
+ * (03/23/2002) gkh
+ *	Added support for the Palm i705 device, thanks to Thomas Riemer
+ *	<tom@netmech.com> for the information.
+ *
+ * (03/21/2002) gkh
+ *	Added support for the Palm m130 device, thanks to Udo Eisenbarth
+ *	<udo.eisenbarth@web.de> for the information.
+ *
  * (02/27/2002) gkh
  *	Reworked the urb handling logic.  We have no more pool, but dynamically
  *	allocate the urb and the transfer buffer on the fly.  In testing this
@@ -169,9 +185,12 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -186,9 +205,12 @@
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
+	{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID) },
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -199,7 +221,7 @@
 /* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
 static struct usb_serial_device_type handspring_device = {
 	owner:			THIS_MODULE,
-	name:			"Handspring Visor / Palm 4.0 / Clié 4.0",
+	name:			"Handspring Visor / Palm 4.0 / Clié 4.x",
 	id_table:		combined_id_table,
 	num_interrupt_in:	0,
 	num_bulk_in:		2,
@@ -262,32 +284,32 @@
 	dbg(__FUNCTION__ " - port %d", port->number);
 
 	if (!port->read_urb) {
+		/* this is needed for some brain dead Sony devices */
 		err ("Device lied about number of ports, please use a lower one.");
 		return -ENODEV;
 	}
 
-	++port->open_count;
-	
-	if (port->open_count == 1) {
-		bytes_in = 0;
-		bytes_out = 0;
-
-		/* force low_latency on so that our tty_push actually forces the data through, 
-		   otherwise it is scheduled, and with high data rates (like with OHCI) data
-		   can get lost. */
+	bytes_in = 0;
+	bytes_out = 0;
+
+	/*
+	 * Force low_latency on so that our tty_push actually forces the data
+	 * through, otherwise it is scheduled, and with high data rates (like
+	 * with OHCI) data can get lost.
+	 */
+	if (port->tty)
 		port->tty->low_latency = 1;
-		
-		/* Start reading from the device */
-		usb_fill_bulk_urb (port->read_urb, serial->dev,
-				   usb_rcvbulkpipe (serial->dev, 
-						    port->bulk_in_endpointAddress),
-				   port->read_urb->transfer_buffer,
-				   port->read_urb->transfer_buffer_length,
-				   visor_read_bulk_callback, port);
-		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-		if (result)
-			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
-	}
+	
+	/* Start reading from the device */
+	usb_fill_bulk_urb (port->read_urb, serial->dev,
+			   usb_rcvbulkpipe (serial->dev, 
+					    port->bulk_in_endpointAddress),
+			   port->read_urb->transfer_buffer,
+			   port->read_urb->transfer_buffer_length,
+			   visor_read_bulk_callback, port);
+	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (result)
+		err(__FUNCTION__ " - failed submitting read urb, error %d", result);
 	
 	return result;
 }
@@ -307,28 +329,23 @@
 	if (!serial)
 		return;
 	
-	--port->open_count;
-
-	if (port->open_count <= 0) {
-		if (serial->dev) {
-			/* only send a shutdown message if the 
-			 * device is still here */
-			transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
-			if (!transfer_buffer) {
-				err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
-			} else {
-				/* send a shutdown message to the device */
-				usb_control_msg (serial->dev,
-						 usb_rcvctrlpipe(serial->dev, 0),
-						 VISOR_CLOSE_NOTIFICATION, 0xc2,
-						 0x0000, 0x0000, 
-						 transfer_buffer, 0x12, 300);
-				kfree (transfer_buffer);
-			}
-			/* shutdown our bulk read */
-			usb_unlink_urb (port->read_urb);
+	if (serial->dev) {
+		/* only send a shutdown message if the 
+		 * device is still here */
+		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+		if (!transfer_buffer) {
+			err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+		} else {
+			/* send a shutdown message to the device */
+			usb_control_msg (serial->dev,
+					 usb_rcvctrlpipe(serial->dev, 0),
+					 VISOR_CLOSE_NOTIFICATION, 0xc2,
+					 0x0000, 0x0000, 
+					 transfer_buffer, 0x12, 300);
+			kfree (transfer_buffer);
 		}
-		port->open_count = 0;
+		/* shutdown our bulk read */
+		usb_unlink_urb (port->read_urb);
 	}
 	/* Uncomment the following line if you want to see some statistics in your syslog */
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
@@ -390,7 +407,7 @@
 	usb_free_urb (urb);
 
 	return count;
-} 
+}
 
 
 static int visor_write_room (struct usb_serial_port *port)
@@ -471,7 +488,7 @@
 	usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 
 	tty = port->tty;
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
 			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
 			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
@@ -481,8 +498,8 @@
 			tty_insert_flip_char(tty, data[i], 0);
 		}
 		tty_flip_buffer_push(tty);
-		bytes_in += urb->actual_length;
 	}
+	bytes_in += urb->actual_length;
 
 	/* Continue trying to always read  */
 	usb_fill_bulk_urb (port->read_urb, serial->dev,
@@ -571,7 +588,8 @@
 	}
 
 	if ((serial->dev->descriptor.idVendor == PALM_VENDOR_ID) ||
-	    (serial->dev->descriptor.idVendor == SONY_VENDOR_ID)) {
+	    ((serial->dev->descriptor.idVendor == SONY_VENDOR_ID) &&
+	     (serial->dev->descriptor.idProduct != SONY_CLIE_4_1_ID))) {
 		/* Palm OS 4.0 Hack */
 		response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), 
 					    PALM_GET_SOME_UNKNOWN_INFORMATION,
@@ -649,15 +667,8 @@
 
 static void visor_shutdown (struct usb_serial *serial)
 {
-	int i;
-
 	dbg (__FUNCTION__);
-
-	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i)
-		serial->port[i].open_count = 0;
 }
-
 
 static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
--- a/drivers/usb/serial/visor.h	Sun Apr 14 12:16:57 2002
+++ b/drivers/usb/serial/visor.h	Sun Apr 14 12:16:57 2002
@@ -24,12 +24,15 @@
 #define PALM_M500_ID			0x0001
 #define PALM_M505_ID			0x0002
 #define PALM_M515_ID			0x0003
+#define PALM_I705_ID			0x0020
 #define PALM_M125_ID			0x0040
+#define PALM_M130_ID			0x0050
 
 #define SONY_VENDOR_ID			0x054C
 #define SONY_CLIE_3_5_ID		0x0038
 #define SONY_CLIE_4_0_ID		0x0066
 #define SONY_CLIE_S360_ID		0x0095
+#define SONY_CLIE_4_1_ID		0x009A
 
 /****************************************************************************
  * Handspring Visor Vendor specific request codes (bRequest values)
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/usb/serial/whiteheat.c	Sun Apr 14 12:16:57 2002
@@ -306,58 +306,49 @@
 
 	dbg(__FUNCTION__" - port %d", port->number);
 
-	++port->open_count;
-	
-	if (port->open_count == 1) {
-		/* set up some stuff for our command port */
-		command_port = &port->serial->port[COMMAND_PORT];
-		if (command_port->private == NULL) {
-			info = (struct whiteheat_private *)kmalloc (sizeof(struct whiteheat_private), GFP_KERNEL);
-			if (info == NULL) {
-				err(__FUNCTION__ " - out of memory");
-				retval = -ENOMEM;
-				goto error_exit;
-			}
-			
-			init_waitqueue_head(&info->wait_command);
-			command_port->private = info;
-			command_port->write_urb->complete = command_port_write_callback;
-			command_port->read_urb->complete = command_port_read_callback;
-			command_port->read_urb->dev = port->serial->dev;
-			command_port->tty = port->tty;		/* need this to "fake" our our sanity check macros */
-			retval = usb_submit_urb (command_port->read_urb, GFP_KERNEL);
-			if (retval) {
-				err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
-				goto error_exit;
-			}
+	/* set up some stuff for our command port */
+	command_port = &port->serial->port[COMMAND_PORT];
+	if (command_port->private == NULL) {
+		info = (struct whiteheat_private *)kmalloc (sizeof(struct whiteheat_private), GFP_KERNEL);
+		if (info == NULL) {
+			err(__FUNCTION__ " - out of memory");
+			retval = -ENOMEM;
+			goto exit;
 		}
 		
-		/* Start reading from the device */
-		port->read_urb->dev = port->serial->dev;
-		retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+		init_waitqueue_head(&info->wait_command);
+		command_port->private = info;
+		command_port->write_urb->complete = command_port_write_callback;
+		command_port->read_urb->complete = command_port_read_callback;
+		command_port->read_urb->dev = port->serial->dev;
+		command_port->tty = port->tty;		/* need this to "fake" our our sanity check macros */
+		retval = usb_submit_urb (command_port->read_urb, GFP_KERNEL);
 		if (retval) {
 			err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
-			goto error_exit;
+			goto exit;
 		}
+	}
 	
-		/* send an open port command */
-		/* firmware uses 1 based port numbering */
-		open_command.port = port->number - port->serial->minor + 1;
-		retval = whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));
-		if (retval)
-			goto error_exit;
-	
-		/* Need to do device specific setup here (control lines, baud rate, etc.) */
-		/* FIXME!!! */
+	/* Start reading from the device */
+	port->read_urb->dev = port->serial->dev;
+	retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+	if (retval) {
+		err(__FUNCTION__ " - failed submitting read urb, error %d", retval);
+		goto exit;
 	}
 
-	dbg(__FUNCTION__ " - exit");
-	return retval;
+	/* send an open port command */
+	/* firmware uses 1 based port numbering */
+	open_command.port = port->number - port->serial->minor + 1;
+	retval = whiteheat_send_cmd (port->serial, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));
+	if (retval)
+		goto exit;
 
-error_exit:
-	--port->open_count;
+	/* Need to do device specific setup here (control lines, baud rate, etc.) */
+	/* FIXME!!! */
 
-	dbg(__FUNCTION__ " - error_exit");
+exit:
+	dbg(__FUNCTION__ " - exit, retval = %d", retval);
 	return retval;
 }
 
@@ -368,22 +359,17 @@
 	
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
-	--port->open_count;
+	/* send a close command to the port */
+	/* firmware uses 1 based port numbering */
+	close_command.port = port->number - port->serial->minor + 1;
+	whiteheat_send_cmd (port->serial, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));
 
-	if (port->open_count <= 0) {
-		/* send a close command to the port */
-		/* firmware uses 1 based port numbering */
-		close_command.port = port->number - port->serial->minor + 1;
-		whiteheat_send_cmd (port->serial, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));
+	/* Need to change the control lines here */
+	/* FIXME */
 	
-		/* Need to change the control lines here */
-		/* FIXME */
-		
-		/* shutdown our bulk reads and writes */
-		usb_unlink_urb (port->write_urb);
-		usb_unlink_urb (port->read_urb);
-		port->open_count = 0;
-	}
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (port->write_urb);
+	usb_unlink_urb (port->read_urb);
 }
 
 
@@ -641,17 +627,9 @@
 
 static void whiteheat_real_shutdown (struct usb_serial *serial)
 {
-	struct usb_serial_port 		*command_port;
-	int i;
+	struct usb_serial_port *command_port;
 
 	dbg(__FUNCTION__);
-
-	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			whiteheat_close (&serial->port[i], NULL);
-		}
-	}
 
 	/* free up our private data for our command port */
 	command_port = &serial->port[COMMAND_PORT];
diff -Nru a/drivers/usb/storage/Config.help b/drivers/usb/storage/Config.help
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/storage/Config.help	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,38 @@
+CONFIG_USB_STORAGE
+  Say Y here if you want to connect USB mass storage devices to your
+  computer's USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-storage.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_USB_STORAGE_DEBUG
+  Say Y here in order to have the USB Mass Storage code generate
+  verbose debugging messages.
+
+CONFIG_USB_STORAGE_ISD200
+  Say Y here if you want to use USB Mass Store devices based
+  on the In-Systems Design ISD-200 USB/ATA bridge.
+
+  Some of the products that use this chip are:
+
+    - Archos Jukebox 6000
+    - ISD SmartCable for Storage
+    - Taiwan Skymaster CD530U/DEL-0241 IDE bridge
+    - Sony CRX10U CD-R/RW drive
+    - CyQ've CQ8060A CDRW drive
+    - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U)
+
+CONFIG_USB_STORAGE_FREECOM
+  Support for the Freecom USB to IDE/ATAPI adaptor.
+  Freecom has a web page at <http://www.freecom.de/>.
+
+CONFIG_USB_STORAGE_DPCM
+  Say Y here to support the Microtech ZiO! CompactFlash/SmartMedia
+  reader, details at <http://www.microtechint.com/zio/index.html>.
+  This driver treats the flash card as a removable storage device.
+
+CONFIG_USB_STORAGE_SDDR09
+  Say Y here to include additional code to support the Sandisk SDDR-09
+  SmartMedia reader in the USB Mass Storage driver.
diff -Nru a/drivers/usb/storage/Config.in b/drivers/usb/storage/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/storage/Config.in	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,15 @@
+#
+# USB Storage driver configuration
+#
+if [ "$CONFIG_SCSI" = "n" ]; then
+   comment '  SCSI support is needed for USB Storage'
+fi
+dep_tristate '  USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
+   dep_mbool '    USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE
+   dep_mbool '    Datafab MDCFE-B Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+   dep_mbool '    Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM  $CONFIG_USB_STORAGE
+   dep_mbool '    ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE
+   dep_mbool '    Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE
+   dep_mbool '    HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+   dep_mbool '    SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
+   dep_mbool '    Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL
diff -Nru a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
--- a/drivers/usb/storage/Makefile	Sun Apr 14 12:16:59 2002
+++ b/drivers/usb/storage/Makefile	Sun Apr 14 12:16:59 2002
@@ -8,25 +8,20 @@
 O_TARGET	:= storage.o
 EXTRA_CFLAGS	:= -I../../scsi/
 
-list-multi	:= usb-storage.o
+obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
 
-obj-$(CONFIG_USB_STORAGE)			+= usb-storage.o
-
-usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e)	+= shuttle_usbat.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SHUTTLE_SMARTMEDIA)   += shuttle_sm.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_SHUTTLE_COMPACTFLASH) += shuttle_cf.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM)	+= dpcm.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)	+= isd200.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)   += datafab.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)  += jumpshot.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)			+= debug.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e)			+= shuttle_usbat.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)			+= sddr09.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)			+= freecom.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_SHUTTLE_SMARTMEDIA)	+= shuttle_sm.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_SHUTTLE_COMPACTFLASH)	+= shuttle_cf.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM)			+= dpcm.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200)			+= isd200.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB)			+= datafab.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT)			+= jumpshot.o
 
 usb-storage-objs :=	scsiglue.o protocol.o transport.o usb.o \
 			initializers.o $(usb-storage-obj-y)
 
 include $(TOPDIR)/Rules.make
-
-usb-storage.o: $(usb-storage-objs)
-	$(LD) -r -o $@ $(usb-storage-objs)
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	Sun Apr 14 12:16:58 2002
+++ b/drivers/usb/storage/transport.h	Sun Apr 14 12:16:58 2002
@@ -112,7 +112,7 @@
 #define US_BULK_GET_MAX_LUN	0xfe
 
 /*
- * us_bulk_transfer() return codes
+ * usb_stor_transfer() return codes
  */
 #define US_BULK_TRANSFER_GOOD		0  /* good transfer                 */
 #define US_BULK_TRANSFER_SHORT		1  /* transfered less than expected */
diff -Nru a/drivers/usb/stv680.c b/drivers/usb/stv680.c
--- a/drivers/usb/stv680.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1584 +0,0 @@
-/*
- *  STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
- *  
- * Thanks to STMicroelectronics for information on the usb commands, and 
- * to Steve Miller at STM for his help and encouragement while I was 
- * writing this driver.
- *
- * This driver is based heavily on the 
- * Endpoints (formerly known as AOX) se401 USB Camera Driver
- * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
- *
- * Still somewhat based on the Linux ov511 driver.
- * 
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History: 
- * ver 0.1 October, 2001. Initial attempt. 
- *
- * ver 0.2 November, 2001. Fixed asbility to resize, added brightness
- *                         function, made more stable (?)
- *
- * ver 0.21 Nov, 2001.     Added gamma correction and white balance, 
- *                         due to Alexander Schwartz. Still trying to 
- *                         improve stablility. Moved stuff into stv680.h
- *
- * ver 0.22 Nov, 2001.	   Added sharpen function (by Michael Sweet, 
- *                         mike@easysw.com) from GIMP, also used in pencam. 
- *                         Simple, fast, good integer math routine.
- *
- * ver 0.23 Dec, 2001 (gkh)
- * 			   Took out sharpen function, ran code through
- * 			   Lindent, and did other minor tweaks to get
- * 			   things to work properly with 2.5.1
- *
- * ver 0.24 Jan, 2002 (kjs) 
- *                         Fixed the problem with webcam crashing after
- *                         two pictures. Changed the way pic is halved to 
- *                         improve quality. Got rid of green line around 
- *                         frame. Fix brightness reset when changing size 
- *                         bug. Adjusted gamma filters slightly.
- *
- * ver 0.25 Jan, 2002 (kjs)
- *			   Fixed a bug in which the driver sometimes attempted
- *			   to set to a non-supported size. This allowed
- *			   gnomemeeting to work.
- *			   Fixed proc entry removal bug.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/pagemap.h>
-#include <linux/wrapper.h>
-#include <linux/smp_lock.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/videodev.h>
-#include <linux/usb.h>
-
-#include "stv680.h"
-
-static int video_nr = -1;
-static int swapRGB = 0;   /* default for auto sleect */
-static int swapRGB_on = 0; /* default to allow auto select; -1=swap never, +1= swap always */
-
-static unsigned int debug = 0;
-
-#define PDEBUG(level, fmt, args...) \
-	do { \
-	if (debug >= level)	\
-		info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args);	\
-	} while (0)
-
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.25"
-#define DRIVER_AUTHOR "Kevin Sisson <kjsisson@bellsouth.net>"
-#define DRIVER_DESC "STV0680 USB Camera Driver"
-
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_LICENSE ("GPL");
-MODULE_PARM (debug, "i");
-MODULE_PARM_DESC (debug, "Debug enabled or not");
-MODULE_PARM (swapRGB_on, "i");
-MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
-MODULE_PARM (video_nr, "i");
-EXPORT_NO_SYMBOLS;
-
-/********************************************************************
- *
- * Memory management
- *
- * This is a shameless copy from the USB-cpia driver (linux kernel
- * version 2.3.29 or so, I have no idea what this code actually does ;).
- * Actually it seems to be a copy of a shameless copy of the bttv-driver.
- * Or that is a copy of a shameless copy of ... (To the powers: is there
- * no generic kernel-function to do this sort of stuff?)
- *
- * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
- * there will be one, but apparentely not yet -jerdfelt
- *
- * So I copied it again for the ov511 driver -claudio
- *
- * Same for the se401 driver -Jeroen
- *
- * And the STV0680 driver - Kevin
- ********************************************************************/
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa (unsigned long adr)
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-	return ret;
-}
-
-static void *rvmalloc (unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32 (size);
-	if (!mem)
-		return NULL;
-
-	memset (mem, 0, size);	/* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		mem_map_reserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	return mem;
-}
-
-static void rvfree (void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		mem_map_unreserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree (mem);
-}
-
-
-/*********************************************************************
- * pencam read/write functions
- ********************************************************************/
-
-static int stv_sndctrl (int set, struct usb_stv *stv680, unsigned short req, unsigned short value, unsigned char *buffer, int size)
-{
-	int ret = -1;
-
-	switch (set) {
-	case 0:		/*  0xc1  */
-		ret = usb_control_msg (stv680->udev,
-				       usb_rcvctrlpipe (stv680->udev, 0),
-				       req,
-				       (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
-				       value, 0, buffer, size, PENCAM_TIMEOUT);
-		break;
-
-	case 1:		/*  0x41  */
-		ret = usb_control_msg (stv680->udev,
-				       usb_sndctrlpipe (stv680->udev, 0),
-				       req,
-				       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT),
-				       value, 0, buffer, size, PENCAM_TIMEOUT);
-		break;
-
-	case 2:		/*  0x80  */
-		ret = usb_control_msg (stv680->udev,
-				       usb_rcvctrlpipe (stv680->udev, 0),
-				       req,
-				       (USB_DIR_IN | USB_RECIP_DEVICE),
-				       value, 0, buffer, size, PENCAM_TIMEOUT);
-		break;
-
-	case 3:		/*  0x40  */
-		ret = usb_control_msg (stv680->udev,
-				       usb_sndctrlpipe (stv680->udev, 0),
-				       req,
-				       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
-				       value, 0, buffer, size, PENCAM_TIMEOUT);
-		break;
-
-	}
-	if ((ret < 0) && (req != 0x0a)) {
-		PDEBUG (1, "STV(e): usb_control_msg error %i, request = 0x%x, error = %i", set, req, ret);
-	}
-	return ret;
-}
-
-static int stv_set_config (struct usb_stv *dev, int configuration, int interface, int alternate)
-{
-
-	if (usb_set_configuration (dev->udev, configuration) < 0) {
-		PDEBUG (1, "STV(e): FAILED to set configuration %i", configuration);
-		return -1;
-	}
-	if (usb_set_interface (dev->udev, interface, alternate) < 0) {
-		PDEBUG (1, "STV(e): FAILED to set alternate interface %i", alternate);
-		return -1;
-	}
-	return 0;
-}
-
-static int stv_stop_video (struct usb_stv *dev)
-{
-	int i;
-	unsigned char *buf;
-
-	buf = kmalloc (40, GFP_KERNEL);
-	if (buf == NULL) {
-		PDEBUG (0, "STV(e): Out of (small buf) memory");
-		return -1;
-	}
-
-	/* this is a high priority command; it stops all lower order commands */
-	if ((i = stv_sndctrl (1, dev, 0x04, 0x0000, buf, 0x0)) < 0) {
-		i = stv_sndctrl (0, dev, 0x80, 0, buf, 0x02);	/* Get Last Error; 2 = busy */
-		PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buf[0], buf[1]);
-	} else {
-		PDEBUG (1, "STV(i): Camera reset to idle mode.");
-	}
-
-	if ((i = stv_set_config (dev, 1, 0, 0)) < 0)
-		PDEBUG (1, "STV(e): Reset config during exit failed");
-
-	/*  get current mode  */
-	buf[0] = 0xf0;
-	if ((i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08)) != 0x08)	/* get mode */
-		PDEBUG (0, "STV(e): Stop_video: problem setting original mode");
-	if (dev->origMode != buf[0]) {
-		memset (buf, 0, 8);
-		buf[0] = (unsigned char) dev->origMode;
-		if ((i = stv_sndctrl (3, dev, 0x07, 0x0100, buf, 0x08)) != 0x08) {
-			PDEBUG (0, "STV(e): Stop_video: Set_Camera_Mode failed");
-			i = -1;
-		}
-		buf[0] = 0xf0;
-		i = stv_sndctrl (0, dev, 0x87, 0, buf, 0x08);
-		if ((i != 0x08) || (buf[0] != dev->origMode)) {
-			PDEBUG (0, "STV(e): camera NOT set to original resolution.");
-			i = -1;
-		} else
-			PDEBUG (0, "STV(i): Camera set to original resolution");
-	}
-	/* origMode */
-	kfree (buf);
-	return i;
-}
-
-static int stv_set_video_mode (struct usb_stv *dev)
-{
-	int i, stop_video = 1;
-	unsigned char *buf;
-
-	buf = kmalloc (40, GFP_KERNEL);
-	if (buf == NULL) {
-		PDEBUG (0, "STV(e): Out of (small buf) memory");
-		return -1;
-	}
-
-	if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
-		kfree (buf);
-		return i;
-	}
-
-	i = stv_sndctrl (2, dev, 0x06, 0x0100, buf, 0x12);
-	if (!(i > 0) && (buf[8] == 0x53) && (buf[9] == 0x05)) {
-		PDEBUG (1, "STV(e): Could not get descriptor 0100.");
-		goto error;
-	}
-
-	/*  set alternate interface 1 */
-	if ((i = stv_set_config (dev, 1, 0, 1)) < 0)
-		goto error;
-
-	if ((i = stv_sndctrl (0, dev, 0x85, 0, buf, 0x10)) != 0x10)
-		goto error;
-	PDEBUG (1, "STV(i): Setting video mode.");
-	/*  Switch to Video mode: 0x0100 = VGA (640x480), 0x0000 = CIF (352x288) 0x0300 = QVGA (320x240)  */
-	if ((i = stv_sndctrl (1, dev, 0x09, dev->VideoMode, buf, 0x0)) < 0) {
-		stop_video = 0;
-		goto error;
-	}
-	goto exit;
-
-error:
-	kfree (buf);
-	if (stop_video == 1)
-		stv_stop_video (dev);
-	return -1;
-
-exit:
-	kfree (buf);
-	return 0;
-}
-
-static int stv_init (struct usb_stv *stv680)
-{
-	int i = 0;
-	unsigned char *buffer;
-	unsigned long int bufsize;
-
-	buffer = kmalloc (40, GFP_KERNEL);
-	if (buffer == NULL) {
-		PDEBUG (0, "STV(e): Out of (small buf) memory");
-		return -1;
-	}
-	memset (buffer, 0, 40);
-	udelay (100);
-
-	/* set config 1, interface 0, alternate 0 */
-	if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
-		kfree (buffer);
-		PDEBUG (0, "STV(e): set config 1,0,0 failed");
-		return -1;
-	}
-	/* ping camera to be sure STV0680 is present */
-	if ((i = stv_sndctrl (0, stv680, 0x88, 0x5678, buffer, 0x02)) != 0x02)
-		goto error;
-	if ((buffer[0] != 0x56) || (buffer[1] != 0x78)) {
-		PDEBUG (1, "STV(e): camera ping failed!!");
-		goto error;
-	}
-
-	/* get camera descriptor */
-	if ((i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x09)) != 0x09)
-		goto error;
-	i = stv_sndctrl (2, stv680, 0x06, 0x0200, buffer, 0x22);
-	if (!(i >= 0) && (buffer[7] == 0xa0) && (buffer[8] == 0x23)) {
-		PDEBUG (1, "STV(e): Could not get descriptor 0200.");
-		goto error;
-	}
-	if ((i = stv_sndctrl (0, stv680, 0x8a, 0, buffer, 0x02)) != 0x02)
-		goto error;
-	if ((i = stv_sndctrl (0, stv680, 0x8b, 0, buffer, 0x24)) != 0x24)
-		goto error;
-	if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
-		goto error;
-
-	stv680->SupportedModes = buffer[7];
-	i = stv680->SupportedModes;
-	stv680->CIF = 0;
-	stv680->VGA = 0;
-	stv680->QVGA = 0;
-	if (i & 1)
-		stv680->CIF = 1;
-	if (i & 2)
-		stv680->VGA = 1;
-	if (i & 8)
-		stv680->QVGA = 1;
-	if (stv680->SupportedModes == 0) {
-		PDEBUG (0, "STV(e): There are NO supported STV680 modes!!");
-		i = -1;
-		goto error;
-	} else {
-		if (stv680->CIF)
-			PDEBUG (0, "STV(i): CIF is supported");
-		if (stv680->QVGA)
-			PDEBUG (0, "STV(i): QVGA is supported");
-	}
-	/* FW rev, ASIC rev, sensor ID  */
-	PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]);
-	PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]);
-	PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4));
-
-	/*  set alternate interface 1 */
-	if ((i = stv_set_config (stv680, 1, 0, 1)) < 0)
-		goto error;
-
-	if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10)
-		goto error;
-	if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08)
-		goto error;
-	i = buffer[3];
-	PDEBUG (0, "STV(i): Camera has %i pictures.", i);
-
-	/*  get current mode */
-	if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08)
-		goto error;
-	stv680->origMode = buffer[0];	/* 01 = VGA, 03 = QVGA, 00 = CIF */
-
-	/* This will attemp CIF mode, if supported. If not, set to QVGA  */
-	memset (buffer, 0, 8);
-	if (stv680->CIF)
-		buffer[0] = 0x00;
-	else if (stv680->QVGA)
-		buffer[0] = 0x03;
-	if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) {
-		PDEBUG (0, "STV(i): Set_Camera_Mode failed");
-		i = -1;
-		goto error;
-	}
-	buffer[0] = 0xf0;
-	stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08);
-	if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) {
-		PDEBUG (0, "STV(e): Error setting camera video mode!");
-		i = -1;
-		goto error;
-	} else {
-		if (buffer[0] == 0) {
-			stv680->VideoMode = 0x0000;
-			PDEBUG (0, "STV(i): Video Mode set to CIF");
-		}
-		if (buffer[0] == 0x03) {
-			stv680->VideoMode = 0x0300;
-			PDEBUG (0, "STV(i): Video Mode set to QVGA");
-		}
-	}
-	if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10)
-		goto error;
-	bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]);
-	stv680->cwidth = (buffer[4] << 8) | (buffer[5]);	/* ->camera = 322, 356, 644  */
-	stv680->cheight = (buffer[6] << 8) | (buffer[7]);	/* ->camera = 242, 292, 484  */
-	stv680->origGain = buffer[12];
-
-	goto exit;
-
-error:
-	i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02);	/* Get Last Error */
-	PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buffer[0], buffer[1]);
-	kfree (buffer);
-	return -1;
-
-exit:
-	kfree (buffer);
-
-	/* video = 320x240, 352x288 */
-	if (stv680->CIF == 1) {
-		stv680->maxwidth = 352;
-		stv680->maxheight = 288;
-		stv680->vwidth = 352;
-		stv680->vheight = 288;
-	}
-	if (stv680->QVGA == 1) {
-		stv680->maxwidth = 320;
-		stv680->maxheight = 240;
-		stv680->vwidth = 320;
-		stv680->vheight = 240;
-	}
-
-	stv680->rawbufsize = bufsize;	/* must be ./. by 8 */
-	stv680->maxframesize = bufsize * 3;	/* RGB size */
-	PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight);
-	PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize);
-
-	/* some default values */
-	stv680->bulk_in_endpointAddr = 0x82;
-	stv680->dropped = 0;
-	stv680->error = 0;
-	stv680->framecount = 0;
-	stv680->readcount = 0;
-	stv680->streaming = 0;
-	/* bright, white, colour, hue, contrast are set by software, not in stv0680 */
-	stv680->brightness = 32767;
-	stv680->chgbright = 0;
-	stv680->whiteness = 0;	/* only for greyscale */
-	stv680->colour = 32767;
-	stv680->contrast = 32767;
-	stv680->hue = 32767;
-	stv680->palette = STV_VIDEO_PALETTE;
-	stv680->depth = 24;	/* rgb24 bits */
-	swapRGB = 0;
-	if ((swapRGB_on == 0) && (swapRGB == 0))
-		PDEBUG (1, "STV(i): swapRGB is (auto) OFF");
-	else if ((swapRGB_on == 1) && (swapRGB == 1))
-		PDEBUG (1, "STV(i): swapRGB is (auto) ON");
-	else if (swapRGB_on == 1)
-		PDEBUG (1, "STV(i): swapRGB is (forced) ON");
-	else if (swapRGB_on == -1)
-		PDEBUG (1, "STV(i): swapRGB is (forced) OFF");
-	
-	if (stv_set_video_mode (stv680) < 0) {
-		PDEBUG (0, "STV(e): Could not set video mode in stv_init");
-		return -1;
-	}
-
-	return 0;
-}
-
-/***************** last of pencam  routines  *******************/
-
-/********************************************************************
- * /proc interface
- *******************************************************************/
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-
-static struct proc_dir_entry *stv680_proc_entry = NULL;
-extern struct proc_dir_entry *video_proc_entry;
-
-#define YES_NO(x) ((x) ? "yes" : "no")
-#define ON_OFF(x) ((x) ? "(auto) on" : "(auto) off")
-
-static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	char *out = page;
-	int len;
-	struct usb_stv *stv680 = data;
-
-	/* Stay under PAGE_SIZE or else bla bla bla.... */
-
-	out += sprintf (out, "driver_version  : %s\n", DRIVER_VERSION);
-	out += sprintf (out, "model           : %s\n", stv680->camera_name);
-	out += sprintf (out, "in use          : %s\n", YES_NO (stv680->user));
-	out += sprintf (out, "streaming       : %s\n", YES_NO (stv680->streaming));
-	out += sprintf (out, "num_frames      : %d\n", STV680_NUMFRAMES);
-
-	out += sprintf (out, "Current size    : %ix%i\n", stv680->vwidth, stv680->vheight);
-	if (swapRGB_on == 0)
-		out += sprintf (out, "swapRGB         : %s\n", ON_OFF (swapRGB));
-	else if (swapRGB_on == 1)
-		out += sprintf (out, "swapRGB         : (forced) on\n");
-	else if (swapRGB_on == -1)
-		out += sprintf (out, "swapRGB         : (forced) off\n");
-
-	out += sprintf (out, "Palette         : %i", stv680->palette);
-
-	out += sprintf (out, "\n");
-
-	out += sprintf (out, "Frames total    : %d\n", stv680->readcount);
-	out += sprintf (out, "Frames read     : %d\n", stv680->framecount);
-	out += sprintf (out, "Packets dropped : %d\n", stv680->dropped);
-	out += sprintf (out, "Decoding Errors : %d\n", stv680->error);
-
-	len = out - page;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else
-		len = count;
-
-	*start = page + off;
-	return len;
-}
-
-static int create_proc_stv680_cam (struct usb_stv *stv680)
-{
-	char name[9];
-	struct proc_dir_entry *ent;
-
-	if (!stv680_proc_entry || !stv680)
-		return -1;
-
-	sprintf (name, "video%d", stv680->vdev.minor);
-
-	ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, stv680_proc_entry);
-	if (!ent)
-		return -1;
-
-	ent->data = stv680;
-	ent->read_proc = stv680_read_proc;
-	stv680->proc_entry = ent;
-	return 0;
-}
-
-static void destroy_proc_stv680_cam (struct usb_stv *stv680)
-{
-	/* One to much, just to be sure :) */
-	char name[9];
-
-	if (!stv680 || !stv680->proc_entry)
-		return;
-
-	sprintf (name, "video%d", stv680->vdev.minor);
-	remove_proc_entry (name, stv680_proc_entry);
-	stv680->proc_entry = NULL;
-}
-
-static int proc_stv680_create (void)
-{
-	if (video_proc_entry == NULL) {
-		PDEBUG (0, "STV(e): /proc/video/ doesn't exist!");
-		return -1;
-	}
-	stv680_proc_entry = create_proc_entry ("stv680", S_IFDIR, video_proc_entry);
-
-	if (stv680_proc_entry) {
-		stv680_proc_entry->owner = THIS_MODULE;
-	} else {
-		PDEBUG (0, "STV(e): Unable to initialize /proc/video/stv680");
-		return -1;
-	}
-	return 0;
-}
-
-static void proc_stv680_destroy (void)
-{
-	if (stv680_proc_entry == NULL)
-		return;
-
-	remove_proc_entry ("stv680", video_proc_entry);
-}
-#endif				/* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
-
-/********************************************************************
- * Camera control
- *******************************************************************/
-
-static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p)
-{
-	/* This sets values for v4l interface. max/min = 65535/0  */
-
-	p->brightness = stv680->brightness;
-	p->whiteness = stv680->whiteness;	/* greyscale */
-	p->colour = stv680->colour;
-	p->contrast = stv680->contrast;
-	p->hue = stv680->hue;
-	p->palette = stv680->palette;
-	p->depth = stv680->depth;
-	return 0;
-}
-
-static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p)
-{
-	/* See above stv680_get_pict  */
-
-	if (p->palette != STV_VIDEO_PALETTE) {
-		PDEBUG (2, "STV(e): Palette set error in _set_pic");
-		return 1;
-	}
-
-	if (stv680->brightness != p->brightness) {
-		stv680->chgbright = 1;
-		stv680->brightness = p->brightness;
-	} 
-
-	stv680->whiteness = p->whiteness;	/* greyscale */
-	stv680->colour = p->colour;
-	stv680->contrast = p->contrast;
-	stv680->hue = p->hue;
-	stv680->palette = p->palette;
-	stv680->depth = p->depth;
-
-	return 0;
-}
-
-static void stv680_video_irq (struct urb *urb)
-{
-	struct usb_stv *stv680 = urb->context;
-	int length = urb->actual_length;
-
-	if (length < stv680->rawbufsize)
-		PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length);
-
-	/* ohoh... */
-	if (!stv680->streaming)
-		return;
-
-	if (!stv680->udev) {
-		PDEBUG (0, "STV(e): device vapourished in video_irq");
-		return;
-	}
-
-	/* 0 sized packets happen if we are to fast, but sometimes the camera
-	   keeps sending them forever...
-	 */
-	if (length && !urb->status) {
-		stv680->nullpackets = 0;
-		switch (stv680->scratch[stv680->scratch_next].state) {
-		case BUFFER_READY:
-		case BUFFER_BUSY:
-			stv680->dropped++;
-			break;
-
-		case BUFFER_UNUSED:
-			memcpy (stv680->scratch[stv680->scratch_next].data,
-			        (unsigned char *) urb->transfer_buffer, length);
-			stv680->scratch[stv680->scratch_next].state = BUFFER_READY;
-			stv680->scratch[stv680->scratch_next].length = length;
-			if (waitqueue_active (&stv680->wq)) {
-				wake_up_interruptible (&stv680->wq);
-			}
-			stv680->scratch_overflow = 0;
-			stv680->scratch_next++;
-			if (stv680->scratch_next >= STV680_NUMSCRATCH)
-				stv680->scratch_next = 0;;
-			break;
-		}		/* switch  */
-	} else {
-		stv680->nullpackets++;
-		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
-			if (waitqueue_active (&stv680->wq)) {
-				wake_up_interruptible (&stv680->wq);
-			}
-		}
-	}			/*  if - else */
-
-	/* Resubmit urb for new data */
-	urb->status = 0;
-	urb->dev = stv680->udev;
-	if (usb_submit_urb (urb, GFP_KERNEL))
-		PDEBUG (0, "STV(e): urb burned down in video irq");
-	return;
-}				/*  _video_irq  */
-
-static int stv680_start_stream (struct usb_stv *stv680)
-{
-	struct urb *urb;
-	int err = 0, i;
-
-	stv680->streaming = 1;
-
-	/* Do some memory allocation */
-	for (i = 0; i < STV680_NUMFRAMES; i++) {
-		stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize;
-		stv680->frame[i].curpix = 0;
-	}
-	/* packet size = 4096  */
-	for (i = 0; i < STV680_NUMSBUF; i++) {
-		stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
-		if (stv680->sbuf[i].data == NULL) {
-			PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
-			return -1;
-		}
-	}
-
-	stv680->scratch_next = 0;
-	stv680->scratch_use = 0;
-	stv680->scratch_overflow = 0;
-	for (i = 0; i < STV680_NUMSCRATCH; i++) {
-		stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
-		if (stv680->scratch[i].data == NULL) {
-			PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
-			return -1;
-		}
-		stv680->scratch[i].state = BUFFER_UNUSED;
-	}
-
-	for (i = 0; i < STV680_NUMSBUF; i++) {
-		urb = usb_alloc_urb (0, GFP_KERNEL);
-		if (!urb)
-			return ENOMEM;
-
-		/* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
-		usb_fill_bulk_urb (urb, stv680->udev,
-				   usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
-				   stv680->sbuf[i].data, stv680->rawbufsize,
-				   stv680_video_irq, stv680);
-		urb->timeout = PENCAM_TIMEOUT * 2;
-		urb->transfer_flags |= USB_QUEUE_BULK;
-		stv680->urb[i] = urb;
-		err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
-		if (err)
-			PDEBUG (0, "STV(e): urb burned down in start stream");
-	}			/* i STV680_NUMSBUF */
-
-	stv680->framecount = 0;
-	return 0;
-}
-
-static int stv680_stop_stream (struct usb_stv *stv680)
-{
-	int i;
-
-	if (!stv680->streaming || !stv680->udev)
-		return 1;
-
-	stv680->streaming = 0;
-
-	for (i = 0; i < STV680_NUMSBUF; i++)
-		if (stv680->urb[i]) {
-			stv680->urb[i]->next = NULL;
-			usb_unlink_urb (stv680->urb[i]);
-			usb_free_urb (stv680->urb[i]);
-			stv680->urb[i] = NULL;
-			kfree (stv680->sbuf[i].data);
-		}
-	for (i = 0; i < STV680_NUMSCRATCH; i++) {
-		kfree (stv680->scratch[i].data);
-		stv680->scratch[i].data = NULL;
-	}
-
-	return 0;
-}
-
-static int stv680_set_size (struct usb_stv *stv680, int width, int height)
-{
-	int wasstreaming = stv680->streaming;
-
-	/* Check to see if we need to change */
-	if ((stv680->vwidth == width) && (stv680->vheight == height))
-		return 0;
-
-	PDEBUG (1, "STV(i): size request for %i x %i", width, height);
-	/* Check for a valid mode */
-	if ((!width || !height) || ((width & 1) || (height & 1))) {
-		PDEBUG (1, "STV(e): set_size error: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
-		return 1;
-	}
-
-	if ((width < (stv680->maxwidth / 2)) || (height < (stv680->maxheight / 2))) {
-		width = stv680->maxwidth / 2;
-		height = stv680->maxheight / 2;
-	} else if ((width >= 158) && (width <= 166) && (stv680->QVGA == 1)) {
-		width = 160;
-		height = 120;
-	} else if ((width >= 172) && (width <= 180) && (stv680->CIF == 1)) {
-		width = 176;
-		height = 144;
-	} else if ((width >= 318) && (width <= 350) && (stv680->QVGA == 1)) {
-		width = 320;
-		height = 240;
-	} else if ((width >= 350) && (width <= 358) && (stv680->CIF == 1)) {
-		width = 352;
-		height = 288;
-	} else {
-		PDEBUG (1, "STV(e): request for non-supported size: request: v.width = %i, v.height = %i  actual: stv.width = %i, stv.height = %i", width, height, stv680->vwidth, stv680->vheight);
-		return 1;
-	}
-	
-	/* Stop a current stream and start it again at the new size */
-	if (wasstreaming)
-		stv680_stop_stream (stv680);
-	stv680->vwidth = width;
-	stv680->vheight = height;
-	PDEBUG (1, "STV(i): size set to %i x %i", stv680->vwidth, stv680->vheight);
-	if (wasstreaming)
-		stv680_start_stream (stv680);
-
-	return 0;
-}
-
-/**********************************************************************
- * Video Decoding
- **********************************************************************/
-
-/*******  routines from the pencam program; hey, they work!  ********/
-
-/*
- * STV0680 Vision Camera Chipset Driver
- * Copyright (C) 2000 Adam Harrison <adam@antispin.org> 
-*/
-
-#define RED 0
-#define GREEN 1
-#define BLUE 2
-#define AD(x, y, w) (((y)*(w)+(x))*3)
-
-static void bayer_unshuffle (struct usb_stv *stv680, struct stv680_scratch *buffer)
-{
-	int x, y, i;
-	int w = stv680->cwidth;
-	int vw = stv680->cwidth, vh = stv680->cheight;
-	unsigned int p = 0;
-	int colour = 0, bayer = 0;
-	unsigned char *raw = buffer->data;
-	struct stv680_frame *frame = &stv680->frame[stv680->curframe];
-	unsigned char *output = frame->data;
-	unsigned char *temp = frame->data;
-	int offset = buffer->offset;
-
-	if (frame->curpix == 0) {
-		if (frame->grabstate == FRAME_READY) {
-			frame->grabstate = FRAME_GRABBING;
-		}
-	}
-	if (offset != frame->curpix) {	/* Regard frame as lost :( */
-		frame->curpix = 0;
-		stv680->error++;
-		return;
-	}
-
-	if ((stv680->vwidth == 320) || (stv680->vwidth == 160)) {
-		vw = 320;
-		vh = 240;
-	}
-	if ((stv680->vwidth == 352) || (stv680->vwidth == 176)) {
-		vw = 352;
-		vh = 288;
-	}
-
-	memset (output, 0, 3 * vw * vh);	/* clear output matrix. */
-
-	for (y = 0; y < vh; y++) {
-		for (x = 0; x < vw; x++) {
-			if (x & 1)
-				p = *(raw + y * w + (x >> 1));
-			else
-				p = *(raw + y * w + (x >> 1) + (w >> 1));
-
-			if (y & 1)
-				bayer = 2;
-			else
-				bayer = 0;
-			if (x & 1)
-				bayer++;
-
-			switch (bayer) {
-			case 0:
-			case 3:
-				colour = 1;
-				break;
-			case 1:
-				colour = 0;
-				break;
-			case 2:
-				colour = 2;
-				break;
-			}
-			i = (y * vw + x) * 3;	
-			*(output + i + colour) = (unsigned char) p;
-		}		/* for x */
-
-	}			/* for y */
-
-	/****** gamma correction plus hardcoded white balance */
-	/* Thanks to Alexander Schwartx <alexander.schwartx@gmx.net> for this code.
-	   Correction values red[], green[], blue[], are generated by 
-	   (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1<i<255. 
-	   White balance (RGB)= 1.0, 1.17, 1.48. Values are calculated as double float and 
-	   converted to unsigned char. Values are in stv680.h  */
-
-	for (y = 0; y < vh; y++) {
-		for (x = 0; x < vw; x++) {
-			i = (y * vw + x) * 3;
-			*(output + i) = red[*(output + i)];
-			*(output + i + 1) = green[*(output + i + 1)];
-			*(output + i + 2) = blue[*(output + i + 2)];
-		}
-	}
-
-	/******  bayer demosaic  ******/
-	for (y = 1; y < (vh - 1); y++) {
-		for (x = 1; x < (vw - 1); x++) {	/* work out pixel type */
-			if (y & 1)
-				bayer = 0;
-			else
-				bayer = 2;
-			if (!(x & 1))
-				bayer++;
-
-			switch (bayer) {
-			case 0:	/* green. blue lr, red tb */
-				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y, vw) + BLUE) + (int) *(output + AD (x + 1, y, vw) + BLUE)) >> 1;
-				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x, y - 1, vw) + RED) + (int) *(output + AD (x, y + 1, vw) + RED)) >> 1;
-				break;
-
-			case 1:	/* blue. green lrtb, red diagonals */
-				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
-				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y - 1, vw) + RED) + (int) *(output + AD (x - 1, y + 1, vw) + RED) + (int) *(output + AD (x + 1, y - 1, vw) + RED) + (int) *(output + AD (x + 1, y + 1, vw) + RED)) >> 2;
-				break;
-
-			case 2:	/* red. green lrtb, blue diagonals */
-				*(output + AD (x, y, vw) + GREEN) = ((int) *(output + AD (x - 1, y, vw) + GREEN) + (int) *(output + AD (x + 1, y, vw) + GREEN) + (int) *(output + AD (x, y - 1, vw) + GREEN) + (int) *(output + AD (x, y + 1, vw) + GREEN)) >> 2;
-				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(output + AD (x + 1, y + 1, vw) + BLUE)) >> 2;
-				break;
-
-			case 3:	/* green. red lr, blue tb */
-				*(output + AD (x, y, vw) + RED) = ((int) *(output + AD (x - 1, y, vw) + RED) + (int) *(output + AD (x + 1, y, vw) + RED)) >> 1;
-				*(output + AD (x, y, vw) + BLUE) = ((int) *(output + AD (x, y - 1, vw) + BLUE) + (int) *(output + AD (x, y + 1, vw) + BLUE)) >> 1;
-				break;
-			}	/* switch */
-		}		/* for x */
-	}			/* for y  - end demosaic  */
-
-	/* fix top and bottom row, left and right side */
-	i = vw * 3;
-	memcpy (output, (output + i), i);
-	memcpy ((output + (vh * i)), (output + ((vh - 1) * i)), i);
-	for (y = 0; y < vh; y++) {
-		i = y * vw * 3;
-		memcpy ((output + i), (output + i + 3), 3);
-		memcpy ((output + i + (vw * 3)), (output + i + (vw - 1) * 3), 3);
-	}
-
-	/*  process all raw data, then trim to size if necessary */
-	if ((stv680->vwidth == 160) || (stv680->vwidth == 176))  {
-		i = 0;
-		for (y = 0; y < vh; y++) {
-			if (!(y & 1)) {
-				for (x = 0; x < vw; x++) {
-					p = (y * vw + x) * 3;
-					if (!(x & 1)) {
-						*(output + i) = *(output + p);
-						*(output + i + 1) = *(output + p + 1);
-						*(output + i + 2) = *(output + p + 2);
-						i += 3;
-					}
-				}  /* for x */
-			}
-		}  /* for y */
-	}
-	/* reset to proper width */
-	if ((stv680->vwidth == 160)) {
-		vw = 160;
-		vh = 120;
-	}
-	if ((stv680->vwidth == 176)) {
-		vw = 176;
-		vh = 144;
-	}
-
-	/* output is RGB; some programs want BGR  */
-	/* swapRGB_on=0 -> program decides;  swapRGB_on=1, always swap */
-	/* swapRGB_on=-1, never swap */
-	if (((swapRGB == 1) && (swapRGB_on != -1)) || (swapRGB_on == 1)) {
-		for (y = 0; y < vh; y++) {
-			for (x = 0; x < vw; x++) {
-				i = (y * vw + x) * 3;
-				*(temp) = *(output + i);
-				*(output + i) = *(output + i + 2);
-				*(output + i + 2) = *(temp);
-			}
-		}
-	}
-	/* brightness */
-	if (stv680->chgbright == 1) {
-		if (stv680->brightness >= 32767) {
-			p = (stv680->brightness - 32767) / 256;
-			for (x = 0; x < (vw * vh * 3); x++) {
-				if ((*(output + x) + (unsigned char) p) > 255)
-					*(output + x) = 255;
-				else
-					*(output + x) += (unsigned char) p;
-			}	/* for */
-		} else {
-			p = (32767 - stv680->brightness) / 256;
-			for (x = 0; x < (vw * vh * 3); x++) {
-				if ((unsigned char) p > *(output + x))
-					*(output + x) = 0;
-				else
-					*(output + x) -= (unsigned char) p;
-			}	/* for */
-		}		/* else */
-	}
-	/* if */
-	frame->curpix = 0;
-	frame->curlinepix = 0;
-	frame->grabstate = FRAME_DONE;
-	stv680->framecount++;
-	stv680->readcount++;
-	if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) {
-		stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1);
-	}
-
-}				/* bayer_unshuffle */
-
-/*******  end routines from the pencam program  *********/
-
-static int stv680_newframe (struct usb_stv *stv680, int framenr)
-{
-	int errors = 0;
-
-	while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) {
-		if (!stv680->frame[framenr].curpix) {
-			errors++;
-		}
-		wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY));
-
-		if (stv680->nullpackets > STV680_MAX_NULLPACKETS) {
-			stv680->nullpackets = 0;
-			PDEBUG (2, "STV(i): too many null length packets, restarting capture");
-			stv680_stop_stream (stv680);
-			stv680_start_stream (stv680);
-		} else {
-			if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) {
-				stv680->frame[framenr].grabstate = FRAME_ERROR;
-				PDEBUG (2, "STV(e): FRAME_ERROR in _newframe");
-				return -EIO;
-			}
-			stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY;
-
-			bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]);
-
-			stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED;
-			stv680->scratch_use++;
-			if (stv680->scratch_use >= STV680_NUMSCRATCH)
-				stv680->scratch_use = 0;
-			if (errors > STV680_MAX_ERRORS) {
-				errors = 0;
-				PDEBUG (2, "STV(i): too many errors, restarting capture");
-				stv680_stop_stream (stv680);
-				stv680_start_stream (stv680);
-			}
-		}		/* else */
-	}			/* while */
-	return 0;
-}
-
-/*********************************************************************
- * Video4Linux
- *********************************************************************/
-
-static int stv_open (struct inode *inode, struct file *file)
-{
-	struct video_device *dev = video_devdata(file);
-	struct usb_stv *stv680 = (struct usb_stv *) dev;
-	int err = 0;
-
-	/* we are called with the BKL held */
-	stv680->user = 1;
-	err = stv_init (stv680);	/* main initialization routine for camera */
-
-	if (err >= 0) {
-		stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES);
-		if (!stv680->fbuf) {
-			PDEBUG (0, "STV(e): Could not rvmalloc frame bufer");
-			err = -ENOMEM;
-		}
-		file->private_data = dev;
-	}
-	if (err)
-		stv680->user = 0;
-
-	return err;
-}
-
-static int stv_close (struct inode *inode, struct file *file)
-{
-	struct video_device *dev = file->private_data;
-	struct usb_stv *stv680 = (struct usb_stv *) dev;
-	int i;
-
-	for (i = 0; i < STV680_NUMFRAMES; i++)
-		stv680->frame[i].grabstate = FRAME_UNUSED;
-	if (stv680->streaming)
-		stv680_stop_stream (stv680);
-
-	if ((i = stv_stop_video (stv680)) < 0)
-		PDEBUG (1, "STV(e): stop_video failed in stv_close");
-
-	rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES);
-	stv680->user = 0;
-
-	if (stv680->removed) {
-		kfree (stv680);
-		stv680 = NULL;
-		PDEBUG (0, "STV(i): device unregistered");
-	}
-	file->private_data = NULL;
-	return 0;
-}
-
-static int stv680_ioctl (struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_stv *stv680 = (struct usb_stv *) vdev;
-
-	if (!stv680->udev)
-		return -EIO;
-
-	switch (cmd) {
-	case VIDIOCGCAP:{
-			struct video_capability *b = arg;
-
-			strcpy (b->name, stv680->camera_name);
-			b->type = VID_TYPE_CAPTURE;
-			b->channels = 1;
-			b->audios = 0;
-			b->maxwidth = stv680->maxwidth;
-			b->maxheight = stv680->maxheight;
-			b->minwidth = stv680->maxwidth / 2;
-			b->minheight = stv680->maxheight / 2;
-			return 0;
-		}
-	case VIDIOCGCHAN:{
-			struct video_channel *v = arg;
-
-			if (v->channel != 0)
-				return -EINVAL;
-			v->flags = 0;
-			v->tuners = 0;
-			v->type = VIDEO_TYPE_CAMERA;
-			strcpy (v->name, "STV Camera");
-			return 0;
-		}
-	case VIDIOCSCHAN:{
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-	case VIDIOCGPICT:{
-			struct video_picture *p = arg;
-
-			stv680_get_pict (stv680, p);
-			return 0;
-		}
-	case VIDIOCSPICT:{
-			struct video_picture *p = arg;
-
-			if (stv680_set_pict (stv680, p))
-				return -EINVAL;
-			return 0;
-		}
-	case VIDIOCSWIN:{
-			struct video_window *vw = arg;
-
-			if (vw->flags)
-				return -EINVAL;
-			if (vw->clipcount)
-				return -EINVAL;
-			if (vw->width != stv680->vwidth) {
-				if (stv680_set_size (stv680, vw->width, vw->height)) {
-					PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN");
-					return -EINVAL;
-				}
-			}
-			return 0;
-		}
-	case VIDIOCGWIN:{
-			struct video_window *vw = arg;
-
-			vw->x = 0;	/* FIXME */
-			vw->y = 0;
-			vw->chromakey = 0;
-			vw->flags = 0;
-			vw->clipcount = 0;
-			vw->width = stv680->vwidth;
-			vw->height = stv680->vheight;
-			return 0;
-		}
-	case VIDIOCGMBUF:{
-			struct video_mbuf *vm = arg;
-			int i;
-
-			memset (vm, 0, sizeof (*vm));
-			vm->size = STV680_NUMFRAMES * stv680->maxframesize;
-			vm->frames = STV680_NUMFRAMES;
-			for (i = 0; i < STV680_NUMFRAMES; i++)
-				vm->offsets[i] = stv680->maxframesize * i;
-			return 0;
-		}
-	case VIDIOCMCAPTURE:{
-			struct video_mmap *vm = arg;
-
-			if (vm->format != STV_VIDEO_PALETTE) {
-				PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)",
-					vm->format, STV_VIDEO_PALETTE);
-				if ((vm->format == 3) && (swapRGB_on == 0))  {
-					PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON");
-					/* this may fix those apps (e.g., xawtv) that want BGR */
-					swapRGB = 1;
-				}
-				return -EINVAL;
-			}
-			if (vm->frame >= STV680_NUMFRAMES) {
-				PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES");
-				return -EINVAL;
-			}
-			if ((stv680->frame[vm->frame].grabstate == FRAME_ERROR)
-			    || (stv680->frame[vm->frame].grabstate == FRAME_GRABBING)) {
-				PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error",
-					stv680->frame[vm->frame].grabstate);
-				return -EBUSY;
-			}
-			/* Is this according to the v4l spec??? */
-			if (stv680->vwidth != vm->width) {
-				if (stv680_set_size (stv680, vm->width, vm->height)) {
-					PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed");
-					return -EINVAL;
-				}
-			}
-			stv680->frame[vm->frame].grabstate = FRAME_READY;
-
-			if (!stv680->streaming)
-				stv680_start_stream (stv680);
-
-			return 0;
-		}
-	case VIDIOCSYNC:{
-			int *frame = arg;
-			int ret = 0;
-
-			if (*frame < 0 || *frame >= STV680_NUMFRAMES) {
-				PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC");
-				return -EINVAL;
-			}
-			ret = stv680_newframe (stv680, *frame);
-			stv680->frame[*frame].grabstate = FRAME_UNUSED;
-			return ret;
-		}
-	case VIDIOCGFBUF:{
-			struct video_buffer *vb = arg;
-
-			memset (vb, 0, sizeof (*vb));
-			return 0;
-		}
-	case VIDIOCKEY:
-		return 0;
-	case VIDIOCCAPTURE:
-		{
-			PDEBUG (2, "STV(e): VIDIOCCAPTURE failed");
-			return -EINVAL;
-		}
-	case VIDIOCSFBUF:
-		return -EINVAL;
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-		return -EINVAL;
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-		return -EINVAL;
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-		return -EINVAL;
-	default:
-		return -ENOIOCTLCMD;
-	}			/* end switch */
-
-	return 0;
-}
-
-static int stv680_mmap (struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *dev = file->private_data;
-	struct usb_stv *stv680 = (struct usb_stv *) dev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-
-	down (&stv680->lock);
-
-	if (stv680->udev == NULL) {
-		up (&stv680->lock);
-		return -EIO;
-	}
-	if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1)
-		    & ~(PAGE_SIZE - 1))) {
-		up (&stv680->lock);
-		return -EINVAL;
-	}
-	pos = (unsigned long) stv680->fbuf;
-	while (size > 0) {
-		page = kvirt_to_pa (pos);
-		if (remap_page_range (vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			up (&stv680->lock);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-	up (&stv680->lock);
-
-	return 0;
-}
-
-static int stv680_read (struct file *file, char *buf,
-			size_t count, loff_t *ppos)
-{
-	struct video_device *dev = file->private_data;
-	unsigned long int realcount = count;
-	int ret = 0;
-	struct usb_stv *stv680 = (struct usb_stv *) dev;
-	unsigned long int i;
-
-	if (STV680_NUMFRAMES != 2) {
-		PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!");
-		return -1;
-	}
-	if (stv680->udev == NULL)
-		return -EIO;
-	if (realcount > (stv680->vwidth * stv680->vheight * 3))
-		realcount = stv680->vwidth * stv680->vheight * 3;
-
-	/* Shouldn't happen: */
-	if (stv680->frame[0].grabstate == FRAME_GRABBING) {
-		PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read");
-		return -EBUSY;
-	}
-	stv680->frame[0].grabstate = FRAME_READY;
-	stv680->frame[1].grabstate = FRAME_UNUSED;
-	stv680->curframe = 0;
-
-	if (!stv680->streaming)
-		stv680_start_stream (stv680);
-
-	if (!stv680->streaming) {
-		ret = stv680_newframe (stv680, 0);	/* ret should = 0 */
-	}
-
-	ret = stv680_newframe (stv680, 0);
-
-	if (!ret) {
-		if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) {
-			PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i);
-			return -EFAULT;
-		}
-	} else {
-		realcount = ret;
-	}
-	stv680->frame[0].grabstate = FRAME_UNUSED;
-	return realcount;
-}				/* stv680_read */
-
-static struct file_operations stv680_fops = {
-	owner:		THIS_MODULE,
-	open:		stv_open,
-	release:       	stv_close,
-	read:		stv680_read,
-	mmap:		stv680_mmap,
-	ioctl:          video_generic_ioctl,
-	llseek:         no_llseek,
-};
-static struct video_device stv680_template = {
-	owner:		THIS_MODULE,
-	name:		"STV0680 USB camera",
-	type:		VID_TYPE_CAPTURE,
-	hardware:	VID_HARDWARE_SE401,
-	fops:           &stv680_fops,
-	kernel_ioctl:	stv680_ioctl,
-};
-
-static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
-{
-	struct usb_interface_descriptor *interface;
-	struct usb_stv *stv680;
-	char *camera_name = NULL;
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1) {
-		PDEBUG (0, "STV(e): Number of Configurations != 1");
-		return NULL;
-	}
-
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
-	/* Is it a STV680? */
-	if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {
-		camera_name = "STV0680";
-		PDEBUG (0, "STV(i): STV0680 camera found.");
-	} else {
-		PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values.");
-		PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer.");
-		return NULL;
-	}
-	/* We found one */
-	if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) {
-		PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct.");
-		return NULL;
-	}
-
-	memset (stv680, 0, sizeof (*stv680));
-
-	stv680->udev = dev;
-	stv680->camera_name = camera_name;
-
-	memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template));
-	memcpy (stv680->vdev.name, stv680->camera_name, strlen (stv680->camera_name));
-	init_waitqueue_head (&stv680->wq);
-	init_MUTEX (&stv680->lock);
-	wmb ();
-
-	if (video_register_device (&stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
-		kfree (stv680);
-		PDEBUG (0, "STV(e): video_register_device failed");
-		return NULL;
-	}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	create_proc_stv680_cam (stv680);
-#endif
-	PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);
-
-	return stv680;
-}
-
-static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
-{
-	int i;
-
-	stv680->udev = NULL;
-	stv680->frame[0].grabstate = FRAME_ERROR;
-	stv680->frame[1].grabstate = FRAME_ERROR;
-	stv680->streaming = 0;
-
-	wake_up_interruptible (&stv680->wq);
-
-	for (i = 0; i < STV680_NUMSBUF; i++)
-		if (stv680->urb[i]) {
-			stv680->urb[i]->next = NULL;
-			usb_unlink_urb (stv680->urb[i]);
-			usb_free_urb (stv680->urb[i]);
-			stv680->urb[i] = NULL;
-			kfree (stv680->sbuf[i].data);
-		}
-	for (i = 0; i < STV680_NUMSCRATCH; i++)
-		if (stv680->scratch[i].data) {
-			kfree (stv680->scratch[i].data);
-		}
-	PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	destroy_proc_stv680_cam (stv680);
-#endif
-	/* Free the memory */
-	kfree (stv680);
-}
-
-static void stv680_disconnect (struct usb_device *dev, void *ptr)
-{
-	struct usb_stv *stv680 = (struct usb_stv *) ptr;
-
-	/* We don't want people trying to open up the device */
-	video_unregister_device (&stv680->vdev);
-	if (!stv680->user) {
-		usb_stv680_remove_disconnected (stv680);
-	} else {
-		stv680->removed = 1;
-	}
-}
-
-static struct usb_driver stv680_driver = {
-	name:		"stv680",
-	probe:		stv680_probe,
-	disconnect:	stv680_disconnect,
-	id_table:	device_table
-};
-
-/********************************************************************
- *  Module routines
- ********************************************************************/
-
-static int __init usb_stv680_init (void)
-{
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	if (proc_stv680_create () < 0)
-		return -1;
-#endif
-	if (usb_register (&stv680_driver) < 0) {
-		PDEBUG (0, "STV(e): Could not setup STV0680 driver");
-		return -1;
-	}
-	PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION);
-
-	info(DRIVER_DESC " " DRIVER_VERSION);
-	return 0;
-}
-
-static void __exit usb_stv680_exit (void)
-{
-	usb_deregister (&stv680_driver);
-	PDEBUG (0, "STV(i): driver deregistered");
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-	proc_stv680_destroy ();
-#endif
-}
-
-module_init (usb_stv680_init);
-module_exit (usb_stv680_exit);
diff -Nru a/drivers/usb/stv680.h b/drivers/usb/stv680.h
--- a/drivers/usb/stv680.h	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,223 +0,0 @@
-/****************************************************************************
- *
- *  Filename: stv680.h
- *
- *  Description:
- *     This is a USB driver for STV0680 based usb video cameras.
- *
- *  This program is free software; you can redistribute it and/or 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.
- *
- ****************************************************************************/
-
-/* size of usb transfers */
-#define STV680_PACKETSIZE	4096
-
-/* number of queued bulk transfers to use, may have problems if > 1 */
-#define STV680_NUMSBUF		1
-
-/* number of frames supported by the v4l part */
-#define STV680_NUMFRAMES	2
-
-/* scratch buffers for passing data to the decoders: 2 or 4 are good */
-#define STV680_NUMSCRATCH	2
-
-/* number of nul sized packets to receive before kicking the camera */
-#define STV680_MAX_NULLPACKETS	200
-
-/* number of decoding errors before kicking the camera */
-#define STV680_MAX_ERRORS	100
-
-#define USB_PENCAM_VENDOR_ID	0x0553
-#define USB_PENCAM_PRODUCT_ID	0x0202
-#define PENCAM_TIMEOUT          1000
-/* fmt 4 */
-#define STV_VIDEO_PALETTE       VIDEO_PALETTE_RGB24
-
-static __devinitdata struct usb_device_id device_table[] = {
-	{USB_DEVICE (USB_PENCAM_VENDOR_ID, USB_PENCAM_PRODUCT_ID)},
-	{}
-};
-MODULE_DEVICE_TABLE (usb, device_table);
-
-struct stv680_sbuf {
-	unsigned char *data;
-};
-
-enum {
-	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
-	FRAME_READY,		/* Ready to start grabbing */
-	FRAME_GRABBING,		/* In the process of being grabbed into */
-	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
-	FRAME_ERROR,		/* Something bad happened while processing */
-};
-
-enum {
-	BUFFER_UNUSED,
-	BUFFER_READY,
-	BUFFER_BUSY,
-	BUFFER_DONE,
-};
-
-/* raw camera data <- sbuf (urb transfer buf) */
-struct stv680_scratch {
-	unsigned char *data;
-	volatile int state;
-	int offset;
-	int length;
-};
-
-/* processed data for display ends up here, after bayer */
-struct stv680_frame {
-	unsigned char *data;	/* Frame buffer */
-	volatile int grabstate;	/* State of grabbing */
-	unsigned char *curline;
-	int curlinepix;
-	int curpix;
-};
-
-/* this is almost the video structure uvd_t, with extra parameters for stv */
-struct usb_stv {
-	struct video_device vdev;
-
-	struct usb_device *udev;
-
-	unsigned char bulk_in_endpointAddr;	/* __u8  the address of the bulk in endpoint */
-	char *camera_name;
-
-	unsigned int VideoMode;	/* 0x0100 = VGA, 0x0000 = CIF, 0x0300 = QVGA */
-	int SupportedModes;
-	int CIF;
-	int VGA;
-	int QVGA;
-	int cwidth;		/* camera width */
-	int cheight;		/* camera height */
-	int maxwidth;		/* max video width */
-	int maxheight;		/* max video height */
-	int vwidth;		/* current width for video window */
-	int vheight;		/* current height for video window */
-	unsigned long int rawbufsize;
-	unsigned long int maxframesize;	/* rawbufsize * 3 for RGB */
-
-	int origGain;
-	int origMode;		/* original camera mode */
-
-	struct semaphore lock;	/* to lock the structure */
-	int user;		/* user count for exclusive use */
-	int removed;		/* device disconnected */
-	int streaming;		/* Are we streaming video? */
-	char *fbuf;		/* Videodev buffer area */
-	struct urb *urb[STV680_NUMSBUF];	/* # of queued bulk transfers */
-	int curframe;		/* Current receiving frame */
-	struct stv680_frame frame[STV680_NUMFRAMES];	/* # frames supported by v4l part */
-	int readcount;
-	int framecount;
-	int error;
-	int dropped;
-	int scratch_next;
-	int scratch_use;
-	int scratch_overflow;
-	struct stv680_scratch scratch[STV680_NUMSCRATCH];	/* for decoders */
-	struct stv680_sbuf sbuf[STV680_NUMSBUF];
-
-	unsigned int brightness;
-	unsigned int chgbright;
-	unsigned int whiteness;
-	unsigned int colour;
-	unsigned int contrast;
-	unsigned int hue;
-	unsigned int palette;
-	unsigned int depth;	/* rgb24 in bits */
-
-	wait_queue_head_t wq;	/* Processes waiting */
-
-	struct proc_dir_entry *proc_entry;	/* /proc/stv680/videoX */
-	int nullpackets;
-};
-
-
-unsigned char red[256] = { 
-	0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 
-	18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, 
-	44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, 
-	71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, 
-	88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, 
-	102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 
-	114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, 
-	125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 
-	134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 
-	143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, 
-	152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, 
-	159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, 
-	167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, 
-	173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, 
-	180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, 
-	187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, 
-	192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, 
-	198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, 
-	204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, 
-	209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 
-	215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, 
-	220, 220, 221, 221 
-}; 
-
-unsigned char green[256] = {
-	0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 
-	21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, 
-	50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, 
-	79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, 
-	98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, 
-	114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 
-	127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 
-	139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 
-	150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, 
-	160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, 
-	169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, 
-	177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, 
-	186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 
-	193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 
-	201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 
-	208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 
-	214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 
-	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 
-	227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 
-	233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 
-	239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, 
-	245, 245, 246, 246 
-}; 
-
-unsigned char blue[256] = {
-	0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 
-	23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, 
-	55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, 
-	86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, 
-	107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, 
-	125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, 
-	139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, 
-	152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, 
-	165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 
-	176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, 
-	185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 
-	194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, 
-	204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, 
-	212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, 
-	221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 
-	228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, 
-	235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, 
-	243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, 
-	249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, 
-	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 
-	255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 
-	255, 255, 255, 255 
-}; 
diff -Nru a/drivers/usb/uhci-debug.h b/drivers/usb/uhci-debug.h
--- a/drivers/usb/uhci-debug.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,577 +0,0 @@
-/*
- * UHCI-specific debugging code. Invaluable when something
- * goes wrong, but don't get in my face.
- *
- * Kernel visible pointers are surrounded in []'s and bus
- * visible pointers are surrounded in ()'s
- *
- * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2001 Johannes Erdfelt
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
-#include <asm/io.h>
-
-#include "uhci.h"
-
-/* Handle REALLY large printk's so we don't overflow buffers */
-static void inline lprintk(char *buf)
-{
-	char *p;
-
-	/* Just write one line at a time */
-	while (buf) {
-		p = strchr(buf, '\n');
-		if (p)
-			*p = 0;
-		printk("%s\n", buf);
-		buf = p;
-		if (buf)
-			buf++;
-	}
-}
-
-static int inline uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td)
-{
-	int i;
-
-	for (i = 0; i < UHCI_NUM_SKELTD; i++)
-		if (td == uhci->skeltd[i])
-			return 1;
-
-	return 0;
-}
-
-static int inline uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
-{
-	int i;
-
-	for (i = 0; i < UHCI_NUM_SKELQH; i++)
-		if (qh == uhci->skelqh[i])
-			return 1;
-
-	return 0;
-}
-
-static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space)
-{
-	char *out = buf;
-	char *spid;
-
-	/* Try to make sure there's enough memory */
-	if (len < 160)
-		return 0;
-
-	out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, td->link);
-	out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
-		((td->status >> 27) & 3),
-		(td->status & TD_CTRL_SPD) ?      "SPD " : "",
-		(td->status & TD_CTRL_LS) ?       "LS " : "",
-		(td->status & TD_CTRL_IOC) ?      "IOC " : "",
-		(td->status & TD_CTRL_ACTIVE) ?   "Active " : "",
-		(td->status & TD_CTRL_STALLED) ?  "Stalled " : "",
-		(td->status & TD_CTRL_DBUFERR) ?  "DataBufErr " : "",
-		(td->status & TD_CTRL_BABBLE) ?   "Babble " : "",
-		(td->status & TD_CTRL_NAK) ?      "NAK " : "",
-		(td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
-		(td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
-		td->status & 0x7ff);
-
-	switch (td->info & 0xff) {
-		case USB_PID_SETUP:
-			spid = "SETUP";
-			break;
-		case USB_PID_OUT:
-			spid = "OUT";
-			break;
-		case USB_PID_IN:
-			spid = "IN";
-			break;
-		default:
-			spid = "?";
-			break;
-	}
-
-	out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
-		td->info >> 21,
-		((td->info >> 19) & 1),
-		(td->info >> 15) & 15,
-		(td->info >> 8) & 127,
-		(td->info & 0xff),
-		spid);
-	out += sprintf(out, "(buf=%08x)\n", td->buffer);
-
-	return out - buf;
-}
-
-static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
-{
-	char *out = buf;
-
-	/* Try to make sure there's enough memory */
-	if (len < 80)
-		return 0;
-
-	out += sprintf(out, "  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
-		port,
-		status,
-		(status & USBPORTSC_SUSP) ? "PortSuspend " : "",
-		(status & USBPORTSC_PR) ?   "PortReset " : "",
-		(status & USBPORTSC_LSDA) ? "LowSpeed " : "",
-		(status & USBPORTSC_RD) ?   "ResumeDetect " : "",
-		(status & USBPORTSC_PEC) ?  "EnableChange " : "",
-		(status & USBPORTSC_PE) ?   "PortEnabled " : "",
-		(status & USBPORTSC_CSC) ?  "ConnectChange " : "",
-		(status & USBPORTSC_CCS) ?  "PortConnected " : "");
-
-	return out - buf;
-}
-
-static int uhci_show_status(struct uhci *uhci, char *buf, int len)
-{
-	char *out = buf;
-	unsigned int io_addr = uhci->io_addr;
-	unsigned short usbcmd, usbstat, usbint, usbfrnum;
-	unsigned int flbaseadd;
-	unsigned char sof;
-	unsigned short portsc1, portsc2;
-
-	/* Try to make sure there's enough memory */
-	if (len < 80 * 6)
-		return 0;
-
-	usbcmd    = inw(io_addr + 0);
-	usbstat   = inw(io_addr + 2);
-	usbint    = inw(io_addr + 4);
-	usbfrnum  = inw(io_addr + 6);
-	flbaseadd = inl(io_addr + 8);
-	sof       = inb(io_addr + 12);
-	portsc1   = inw(io_addr + 16);
-	portsc2   = inw(io_addr + 18);
-
-	out += sprintf(out, "  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
-		usbcmd,
-		(usbcmd & USBCMD_MAXP) ?    "Maxp64 " : "Maxp32 ",
-		(usbcmd & USBCMD_CF) ?      "CF " : "",
-		(usbcmd & USBCMD_SWDBG) ?   "SWDBG " : "",
-		(usbcmd & USBCMD_FGR) ?     "FGR " : "",
-		(usbcmd & USBCMD_EGSM) ?    "EGSM " : "",
-		(usbcmd & USBCMD_GRESET) ?  "GRESET " : "",
-		(usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
-		(usbcmd & USBCMD_RS) ?      "RS " : "");
-
-	out += sprintf(out, "  usbstat   =     %04x   %s%s%s%s%s%s\n",
-		usbstat,
-		(usbstat & USBSTS_HCH) ?    "HCHalted " : "",
-		(usbstat & USBSTS_HCPE) ?   "HostControllerProcessError " : "",
-		(usbstat & USBSTS_HSE) ?    "HostSystemError " : "",
-		(usbstat & USBSTS_RD) ?     "ResumeDetect " : "",
-		(usbstat & USBSTS_ERROR) ?  "USBError " : "",
-		(usbstat & USBSTS_USBINT) ? "USBINT " : "");
-
-	out += sprintf(out, "  usbint    =     %04x\n", usbint);
-	out += sprintf(out, "  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,
-		0xfff & (4*(unsigned int)usbfrnum));
-	out += sprintf(out, "  flbaseadd = %08x\n", flbaseadd);
-	out += sprintf(out, "  sof       =       %02x\n", sof);
-	out += uhci_show_sc(1, portsc1, out, len - (out - buf));
-	out += uhci_show_sc(2, portsc2, out, len - (out - buf));
-
-	return out - buf;
-}
-
-static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
-{
-	char *out = buf;
-	struct urb_priv *urbp;
-	struct list_head *head, *tmp;
-	struct uhci_td *td;
-	int i = 0, checked = 0, prevactive = 0;
-
-	/* Try to make sure there's enough memory */
-	if (len < 80 * 6)
-		return 0;
-
-	out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "",
-			qh, qh->link, qh->element);
-
-	if (qh->element & UHCI_PTR_QH)
-		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
-
-	if (qh->element & UHCI_PTR_DEPTH)
-		out += sprintf(out, "%*s  Depth traverse\n", space, "");
-
-	if (qh->element & 8)
-		out += sprintf(out, "%*s  Bit 3 set (bug?)\n", space, "");
-
-	if (!(qh->element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
-		out += sprintf(out, "%*s  Element is NULL (bug?)\n", space, "");
-
-	if (!qh->urbp) {
-		out += sprintf(out, "%*s  urbp == NULL\n", space, "");
-		goto out;
-	}
-
-	urbp = qh->urbp;
-
-	head = &urbp->td_list;
-	tmp = head->next;
-
-	td = list_entry(tmp, struct uhci_td, list);
-
-	if (td->dma_handle != (qh->element & ~UHCI_PTR_BITS))
-		out += sprintf(out, "%*s Element != First TD\n", space, "");
-
-	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		out += sprintf(out, "%*s%d: ", space + 2, "", i++);
-		out += uhci_show_td(td, out, len - (out - buf), 0);
-
-		if (i > 10 && !checked && prevactive && tmp != head &&
-		    debug <= 2) {
-			struct list_head *ntmp = tmp;
-			struct uhci_td *ntd = td;
-			int active = 1, ni = i;
-
-			checked = 1;
-
-			while (ntmp != head && ntmp->next != head && active) {
-				ntd = list_entry(ntmp, struct uhci_td, list);
-
-				ntmp = ntmp->next;
-
-				active = ntd->status & TD_CTRL_ACTIVE;
-
-				ni++;
-			}
-
-			if (active && ni > i) {
-				out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
-				tmp = ntmp;
-				td = ntd;
-				i = ni;
-			}
-		}
-
-		prevactive = td->status & TD_CTRL_ACTIVE;
-	}
-
-	if (list_empty(&urbp->queue_list) || urbp->queued)
-		goto out;
-
-	out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
-
-	head = &urbp->queue_list;
-	tmp = head->next;
-
-	while (tmp != head) {
-		struct urb_priv *nurbp = list_entry(tmp, struct urb_priv,
-						queue_list);
-		tmp = tmp->next;
-
-		out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space);
-	}
-
-out:
-	return out - buf;
-}
-
-static const char *td_names[] = {"skel_int1_td", "skel_int2_td",
-				 "skel_int4_td", "skel_int8_td",
-				 "skel_int16_td", "skel_int32_td",
-				 "skel_int64_td", "skel_int128_td",
-				 "skel_int256_td", "skel_term_td" };
-static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh",
-				  "skel_bulk_qh", "skel_term_qh" };
-
-#define show_frame_num()	\
-	if (!shown) {		\
-	  shown = 1;		\
-	  out += sprintf(out, "- Frame %d\n", i); \
-	}
-
-#define show_td_name()		\
-	if (!shown) {		\
-	  shown = 1;		\
-	  out += sprintf(out, "- %s\n", td_names[i]); \
-	}
-
-#define show_qh_name()		\
-	if (!shown) {		\
-	  shown = 1;		\
-	  out += sprintf(out, "- %s\n", qh_names[i]); \
-	}
-
-static int uhci_sprint_schedule(struct uhci *uhci, char *buf, int len)
-{
-	char *out = buf;
-	int i;
-	struct uhci_qh *qh;
-	struct uhci_td *td;
-	struct list_head *tmp, *head;
-
-	out += sprintf(out, "HC status\n");
-	out += uhci_show_status(uhci, out, len - (out - buf));
-
-	out += sprintf(out, "Frame List\n");
-	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-		int shown = 0;
-		td = uhci->fl->frame_cpu[i];
-		if (!td)
-			continue;
-
-		if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
-			show_frame_num();
-			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
-		}
-		if (uhci_is_skeleton_td(uhci, td))
-			continue;
-		show_frame_num();
-
-		head = &td->fl_list;
-		tmp = head;
-		do {
-			td = list_entry(tmp, struct uhci_td, fl_list);
-			tmp = tmp->next;
-			out += uhci_show_td(td, out, len - (out - buf), 4);
-		} while (tmp != head);
-	}
-
-	out += sprintf(out, "Skeleton TD's\n");
-	for (i = UHCI_NUM_SKELTD - 1; i >= 0; i--) {
-		int shown = 0;
-
-		td = uhci->skeltd[i];
-
-		if (debug > 1) {
-			show_td_name();
-			out += uhci_show_td(td, out, len - (out - buf), 4);
-		}
-
-		if (list_empty(&td->fl_list)) {
-			/* TD 0 is the int1 TD and links to control_ls_qh */
-			if (!i) {
-				if (td->link !=
-				    (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH)) {
-					show_td_name();
-					out += sprintf(out, "    skeleton TD not linked to ls_control QH!\n");
-				}
-			} else if (i < 9) {
-				if (td->link != uhci->skeltd[i - 1]->dma_handle) {
-					show_td_name();
-					out += sprintf(out, "    skeleton TD not linked to next skeleton TD!\n");
-				}
-			} else {
-				show_td_name();
-
-				if (td->link != td->dma_handle)
-					out += sprintf(out, "    skel_term_td does not link to self\n");
-
-				/* Don't show it twice */
-				if (debug <= 1)
-					out += uhci_show_td(td, out, len - (out - buf), 4);
-			}
-
-			continue;
-		}
-
-		show_td_name();
-
-		head = &td->fl_list;
-		tmp = head->next;
-
-		while (tmp != head) {
-			td = list_entry(tmp, struct uhci_td, fl_list);
-
-			tmp = tmp->next;
-
-			out += uhci_show_td(td, out, len - (out - buf), 4);
-		}
-
-		if (!i) {
-			if (td->link !=
-			    (uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH))
-				out += sprintf(out, "    last TD not linked to ls_control QH!\n");
-		} else if (i < 9) {
-			if (td->link != uhci->skeltd[i - 1]->dma_handle)
-				out += sprintf(out, "    last TD not linked to next skeleton!\n");
-		}
-	}
-
-	out += sprintf(out, "Skeleton QH's\n");
-
-	for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
-		int shown = 0;
-
-		qh = uhci->skelqh[i];
-
-		if (debug > 1) {
-			show_qh_name();
-			out += uhci_show_qh(qh, out, len - (out - buf), 4);
-		}
-
-		/* QH 3 is the Terminating QH, it's different */
-		if (i == 3) {
-			if (qh->link != UHCI_PTR_TERM) {
-				show_qh_name();
-				out += sprintf(out, "    bandwidth reclamation on!\n");
-			}
-
-			if (qh->element != uhci->skel_term_td->dma_handle) {
-				show_qh_name();
-				out += sprintf(out, "    skel_term_qh element is not set to skel_term_td\n");
-			}
-		}
-
-		if (list_empty(&qh->list)) {
-			if (i < 3) {
-				if (qh->link !=
-				    (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH)) {
-					show_qh_name();
-					out += sprintf(out, "    skeleton QH not linked to next skeleton QH!\n");
-				}
-			}
-
-			continue;
-		}
-
-		show_qh_name();
-
-		head = &qh->list;
-		tmp = head->next;
-
-		while (tmp != head) {
-			qh = list_entry(tmp, struct uhci_qh, list);
-
-			tmp = tmp->next;
-
-			out += uhci_show_qh(qh, out, len - (out - buf), 4);
-		}
-
-		if (i < 3) {
-			if (qh->link !=
-			    (uhci->skelqh[i + 1]->dma_handle | UHCI_PTR_QH))
-				out += sprintf(out, "    last QH not linked to next skeleton!\n");
-		}
-	}
-
-	return out - buf;
-}
-
-#ifdef CONFIG_PROC_FS
-#define MAX_OUTPUT	(PAGE_SIZE * 8)
-
-static struct proc_dir_entry *uhci_proc_root = NULL;
-
-struct uhci_proc {
-	int size;
-	char *data;
-	struct uhci *uhci;
-};
-
-static int uhci_proc_open(struct inode *inode, struct file *file)
-{
-	const struct proc_dir_entry *dp = PDE(inode);
-	struct uhci *uhci = dp->data;
-	struct uhci_proc *up;
-	unsigned long flags;
-	int ret = -ENOMEM;
-
-	lock_kernel();
-	up = kmalloc(sizeof(*up), GFP_KERNEL);
-	if (!up)
-		goto out;
-
-	up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
-	if (!up->data) {
-		kfree(up);
-		goto out;
-	}
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-
-	file->private_data = up;
-
-	ret = 0;
-out:
-	unlock_kernel();
-	return ret;
-}
-
-static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence)
-{
-	struct uhci_proc *up;
-	loff_t new = -1;
-
-	lock_kernel();
-	up = file->private_data;
-
-	switch (whence) {
-	case 0:
-		new = off;
-		break;
-	case 1:
-		new = file->f_pos + off;
-		break;
-	}
-	if (new < 0 || new > up->size) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-	unlock_kernel();
-	return (file->f_pos = new);
-}
-
-static ssize_t uhci_proc_read(struct file *file, char *buf, size_t nbytes,
-			loff_t *ppos)
-{
-	struct uhci_proc *up = file->private_data;
-	unsigned int pos;
-	unsigned int size;
-
-	pos = *ppos;
-	size = up->size;
-	if (pos >= size)
-		return 0;
-	if (nbytes >= size)
-		nbytes = size;
-	if (pos + nbytes > size)
-		nbytes = size - pos;
-
-	if (!access_ok(VERIFY_WRITE, buf, nbytes))
-		return -EINVAL;
-
-	copy_to_user(buf, up->data + pos, nbytes);
-
-	*ppos += nbytes;
-
-	return nbytes;
-}
-
-static int uhci_proc_release(struct inode *inode, struct file *file)
-{
-	struct uhci_proc *up = file->private_data;
-
-	kfree(up->data);
-	kfree(up);
-
-	return 0;
-}
-
-static struct file_operations uhci_proc_operations = {
-	open:		uhci_proc_open,
-	llseek:		uhci_proc_lseek,
-	read:		uhci_proc_read,
-//	write:		uhci_proc_write,
-	release:	uhci_proc_release,
-};
-#endif
-
diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c
--- a/drivers/usb/uhci.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,3161 +0,0 @@
-/*
- * Universal Host Controller Interface driver for USB.
- *
- * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
- *
- * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
- * (C) Copyright 1999 Randy Dunlap
- * (C) Copyright 1999 Georg Acher, acher@in.tum.de
- * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
- * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
- * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
- * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
- *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
- * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- *
- * Intel documents this fairly well, and as far as I know there
- * are no royalties or anything like that, but even so there are
- * people who decided that they want to do the same thing in a
- * completely different way.
- *
- * WARNING! The USB documentation is downright evil. Most of it
- * is just crap, written by a committee. You're better off ignoring
- * most of it, the important stuff is:
- *  - the low-level protocol (fairly simple but lots of small details)
- *  - working around the horridness of the rest
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/proc_fs.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include "hcd.h"
-#include "uhci.h"
-
-#include <linux/pm.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.1"
-#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
-#define DRIVER_DESC "USB Universal Host Controller Interface driver"
-
-/*
- * debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
- *            show all queues in /proc/uhci/hc*
- * debug = 3, show all TD's in URB's when dumping
- */
-#ifdef DEBUG
-static int debug = 1;
-#else
-static int debug = 0;
-#endif
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level");
-static char *errbuf;
-#define ERRBUF_LEN    (PAGE_SIZE * 8)
-
-#include "uhci-debug.h"
-
-static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
-
-static int rh_submit_urb(struct urb *urb);
-static int rh_unlink_urb(struct urb *urb);
-static int uhci_get_current_frame_number(struct usb_device *dev);
-static int uhci_unlink_urb(struct urb *urb);
-static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb);
-static void uhci_call_completion(struct urb *urb);
-
-static int  ports_active(struct uhci *uhci);
-static void suspend_hc(struct uhci *uhci);
-static void wakeup_hc(struct uhci *uhci);
-
-/* If a transfer is still active after this much time, turn off FSBR */
-#define IDLE_TIMEOUT	(HZ / 20)	/* 50 ms */
-#define FSBR_DELAY	(HZ / 20)	/* 50 ms */
-
-#define MAX_URB_LOOP	2048		/* Maximum number of linked URB's */
-
-/*
- * Only the USB core should call uhci_alloc_dev and uhci_free_dev
- */
-static int uhci_alloc_dev(struct usb_device *dev)
-{
-	return 0;
-}
-
-static int uhci_free_dev(struct usb_device *dev)
-{
-	return 0;
-}
-
-static inline void uhci_set_next_interrupt(struct uhci *uhci)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	set_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static inline void uhci_clear_next_interrupt(struct uhci *uhci)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	clear_bit(TD_CTRL_IOC_BIT, &uhci->skel_term_td->status);
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static inline void uhci_add_complete(struct urb *urb)
-{
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->complete_list_lock, flags);
-	list_add(&urbp->complete_list, &uhci->complete_list);
-	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
-}
-
-static struct uhci_td *uhci_alloc_td(struct uhci *uhci, struct usb_device *dev)
-{
-	dma_addr_t dma_handle;
-	struct uhci_td *td;
-
-	td = pci_pool_alloc(uhci->td_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
-	if (!td)
-		return NULL;
-
-	td->dma_handle = dma_handle;
-
-	td->link = UHCI_PTR_TERM;
-	td->buffer = 0;
-
-	td->frame = -1;
-	td->dev = dev;
-
-	INIT_LIST_HEAD(&td->list);
-	INIT_LIST_HEAD(&td->fl_list);
-
-	usb_inc_dev_use(dev);
-
-	return td;
-}
-
-static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
-		__u32 info, __u32 buffer)
-{
-	td->status = status;
-	td->info = info;
-	td->buffer = buffer;
-}
-
-static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td)
-{
-	unsigned long flags;
-	struct uhci_td *ltd;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	ltd = list_entry(skeltd->fl_list.prev, struct uhci_td, fl_list);
-
-	td->link = ltd->link;
-	mb();
-	ltd->link = td->dma_handle;
-
-	list_add_tail(&td->fl_list, &skeltd->fl_list);
-
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-/*
- * We insert Isochronous transfers directly into the frame list at the
- * beginning
- * The layout looks as follows:
- * frame list pointer -> iso td's (if any) ->
- * periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh
- */
-static void uhci_insert_td_frame_list(struct uhci *uhci, struct uhci_td *td, unsigned framenum)
-{
-	unsigned long flags;
-
-	framenum %= UHCI_NUMFRAMES;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	td->frame = framenum;
-
-	/* Is there a TD already mapped there? */
-	if (uhci->fl->frame_cpu[framenum]) {
-		struct uhci_td *ftd, *ltd;
-
-		ftd = uhci->fl->frame_cpu[framenum];
-		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
-
-		list_add_tail(&td->fl_list, &ftd->fl_list);
-
-		td->link = ltd->link;
-		mb();
-		ltd->link = td->dma_handle;
-	} else {
-		td->link = uhci->fl->frame[framenum];
-		mb();
-		uhci->fl->frame[framenum] = td->dma_handle;
-		uhci->fl->frame_cpu[framenum] = td;
-	}
-
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static void uhci_remove_td(struct uhci *uhci, struct uhci_td *td)
-{
-	unsigned long flags;
-
-	/* If it's not inserted, don't remove it */
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	if (td->frame == -1 && list_empty(&td->fl_list))
-		goto out;
-
-	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
-		if (list_empty(&td->fl_list)) {
-			uhci->fl->frame[td->frame] = td->link;
-			uhci->fl->frame_cpu[td->frame] = NULL;
-		} else {
-			struct uhci_td *ntd;
-
-			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-			uhci->fl->frame[td->frame] = ntd->dma_handle;
-			uhci->fl->frame_cpu[td->frame] = ntd;
-		}
-	} else {
-		struct uhci_td *ptd;
-
-		ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
-		ptd->link = td->link;
-	}
-
-	mb();
-	td->link = UHCI_PTR_TERM;
-
-	list_del_init(&td->fl_list);
-	td->frame = -1;
-
-out:
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-/*
- * Inserts a td into qh list at the top.
- */
-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td, *ptd;
-
-	if (list_empty(&urbp->td_list))
-		return;
-
-	head = &urbp->td_list;
-	tmp = head->next;
-
-	/* Ordering isn't important here yet since the QH hasn't been */
-	/*  inserted into the schedule yet */
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* Add the first TD to the QH element pointer */
-	qh->element = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH);
-
-	ptd = td;
-
-	/* Then link the rest of the TD's */
-	tmp = tmp->next;
-	while (tmp != head) {
-		td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		ptd->link = td->dma_handle | (breadth ? 0 : UHCI_PTR_DEPTH);
-
-		ptd = td;
-	}
-
-	ptd->link = UHCI_PTR_TERM;
-}
-
-static void uhci_free_td(struct uhci *uhci, struct uhci_td *td)
-{
-	if (!list_empty(&td->list) || !list_empty(&td->fl_list))
-		dbg("td is still in URB list!");
-
-	if (td->dev)
-		usb_dec_dev_use(td->dev);
-
-	pci_pool_free(uhci->td_pool, td, td->dma_handle);
-}
-
-static struct uhci_qh *uhci_alloc_qh(struct uhci *uhci, struct usb_device *dev)
-{
-	dma_addr_t dma_handle;
-	struct uhci_qh *qh;
-
-	qh = pci_pool_alloc(uhci->qh_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
-	if (!qh)
-		return NULL;
-
-	qh->dma_handle = dma_handle;
-
-	qh->element = UHCI_PTR_TERM;
-	qh->link = UHCI_PTR_TERM;
-
-	qh->dev = dev;
-
-	INIT_LIST_HEAD(&qh->list);
-	INIT_LIST_HEAD(&qh->remove_list);
-
-	usb_inc_dev_use(dev);
-
-	return qh;
-}
-
-static void uhci_free_qh(struct uhci *uhci, struct uhci_qh *qh)
-{
-	if (!list_empty(&qh->list))
-		dbg("qh list not empty!");
-	if (!list_empty(&qh->remove_list))
-		dbg("qh still in remove_list!");
-
-	if (qh->dev)
-		usb_dec_dev_use(qh->dev);
-
-	pci_pool_free(uhci->qh_pool, qh, qh->dma_handle);
-}
-
-/*
- * MUST be called with uhci->frame_list_lock acquired
- */
-static void _uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct list_head *head, *tmp;
-	struct uhci_qh *lqh;
-
-	/* Grab the last QH */
-	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
-
-	if (lqh->urbp) {
-		head = &lqh->urbp->queue_list;
-		tmp = head->next;
-		while (head != tmp) {
-			struct urb_priv *turbp =
-				list_entry(tmp, struct urb_priv, queue_list);
-
-			tmp = tmp->next;
-
-			turbp->qh->link = urbp->qh->dma_handle | UHCI_PTR_QH;
-		}
-	}
-
-	head = &urbp->queue_list;
-	tmp = head->next;
-	while (head != tmp) {
-		struct urb_priv *turbp =
-			list_entry(tmp, struct urb_priv, queue_list);
-
-		tmp = tmp->next;
-
-		turbp->qh->link = lqh->link;
-	}
-
-	urbp->qh->link = lqh->link;
-	mb();				/* Ordering is important */
-	lqh->link = urbp->qh->dma_handle | UHCI_PTR_QH;
-
-	list_add_tail(&urbp->qh->list, &skelqh->list);
-}
-
-static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct urb *urb)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	_uhci_insert_qh(uhci, skelqh, urb);
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static void uhci_remove_qh(struct uhci *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	unsigned long flags;
-	struct uhci_qh *qh = urbp->qh, *pqh;
-
-	if (!qh)
-		return;
-
-	/* Only go through the hoops if it's actually linked in */
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-	if (!list_empty(&qh->list)) {
-		qh->urbp = NULL;
-
-		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
-
-		if (pqh->urbp) {
-			struct list_head *head, *tmp;
-
-			head = &pqh->urbp->queue_list;
-			tmp = head->next;
-			while (head != tmp) {
-				struct urb_priv *turbp =
-					list_entry(tmp, struct urb_priv, queue_list);
-
-				tmp = tmp->next;
-
-				turbp->qh->link = qh->link;
-			}
-		}
-
-		pqh->link = qh->link;
-		mb();
-		qh->element = qh->link = UHCI_PTR_TERM;
-
-		list_del_init(&qh->list);
-	}
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-
-	spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
-
-	/* Check to see if the remove list is empty. Set the IOC bit */
-	/* to force an interrupt so we can remove the QH */
-	if (list_empty(&uhci->qh_remove_list))
-		uhci_set_next_interrupt(uhci);
-
-	list_add(&qh->remove_list, &uhci->qh_remove_list);
-
-	spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags);
-}
-
-static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct list_head *head, *tmp;
-
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (head != tmp) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		if (toggle)
-			set_bit(TD_TOKEN_TOGGLE, &td->info);
-		else
-			clear_bit(TD_TOKEN_TOGGLE, &td->info);
-
-		toggle ^= 1;
-	}
-
-	return toggle;
-}
-
-/* This function will append one URB's QH to another URB's QH. This is for */
-/*  USB_QUEUE_BULK support for bulk transfers and soon implicitily for */
-/*  control transfers */
-static void uhci_append_queued_urb(struct uhci *uhci, struct urb *eurb, struct urb *urb)
-{
-	struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
-	struct list_head *tmp;
-	struct uhci_td *lltd;
-	unsigned long flags;
-
-	eurbp = eurb->hcpriv;
-	urbp = urb->hcpriv;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	/* Find the first URB in the queue */
-	if (eurbp->queued) {
-		struct list_head *head = &eurbp->queue_list;
-
-		tmp = head->next;
-		while (tmp != head) {
-			struct urb_priv *turbp =
-				list_entry(tmp, struct urb_priv, queue_list);
-
-			if (!turbp->queued)
-				break;
-
-			tmp = tmp->next;
-		}
-	} else
-		tmp = &eurbp->queue_list;
-
-	furbp = list_entry(tmp, struct urb_priv, queue_list);
-	lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
-
-	lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
-
-	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe),
-		uhci_fixup_toggle(urb, uhci_toggle(lltd->info) ^ 1));
-
-	/* All qh's in the queue need to link to the next queue */
-	urbp->qh->link = eurbp->qh->link;
-
-	mb();			/* Make sure we flush everything */
-	/* Only support bulk right now, so no depth */
-	lltd->link = urbp->qh->dma_handle | UHCI_PTR_QH;
-
-	list_add_tail(&urbp->queue_list, &furbp->queue_list);
-
-	urbp->queued = 1;
-
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static void uhci_delete_queued_urb(struct uhci *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp, *nurbp;
-	struct list_head *head, *tmp;
-	struct urb_priv *purbp;
-	struct uhci_td *pltd;
-	unsigned int toggle;
-	unsigned long flags;
-
-	urbp = urb->hcpriv;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	if (list_empty(&urbp->queue_list))
-		goto out;
-
-	nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
-
-	/* Fix up the toggle for the next URB's */
-	if (!urbp->queued)
-		/* We set the toggle when we unlink */
-		toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-	else {
-		/* If we're in the middle of the queue, grab the toggle */
-		/*  from the TD previous to us */
-		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
-				queue_list);
-
-		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
-
-		toggle = uhci_toggle(pltd->info) ^ 1;
-	}
-
-	head = &urbp->queue_list;
-	tmp = head->next;
-	while (head != tmp) {
-		struct urb_priv *turbp;
-
-		turbp = list_entry(tmp, struct urb_priv, queue_list);
-
-		tmp = tmp->next;
-
-		if (!turbp->queued)
-			break;
-
-		toggle = uhci_fixup_toggle(turbp->urb, toggle);
-	}
-
-	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-		usb_pipeout(urb->pipe), toggle);
-
-	if (!urbp->queued) {
-		nurbp->queued = 0;
-
-		_uhci_insert_qh(uhci, uhci->skel_bulk_qh, nurbp->urb);
-	} else {
-		/* We're somewhere in the middle (or end). A bit trickier */
-		/*  than the head scenario */
-		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
-				queue_list);
-
-		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
-		if (nurbp->queued)
-			pltd->link = nurbp->qh->dma_handle | UHCI_PTR_QH;
-		else
-			/* The next URB happens to be the beginning, so */
-			/*  we're the last, end the chain */
-			pltd->link = UHCI_PTR_TERM;
-	}
-
-	list_del_init(&urbp->queue_list);
-
-out:
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static struct urb_priv *uhci_alloc_urb_priv(struct uhci *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp;
-
-	urbp = kmem_cache_alloc(uhci_up_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
-	if (!urbp) {
-		err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
-		return NULL;
-	}
-
-	memset((void *)urbp, 0, sizeof(*urbp));
-
-	urbp->inserttime = jiffies;
-	urbp->fsbrtime = jiffies;
-	urbp->urb = urb;
-	urbp->dev = urb->dev;
-	
-	INIT_LIST_HEAD(&urbp->td_list);
-	INIT_LIST_HEAD(&urbp->queue_list);
-	INIT_LIST_HEAD(&urbp->complete_list);
-
-	urb->hcpriv = urbp;
-
-	if (urb->dev != uhci->rh.dev) {
-		if (urb->transfer_buffer_length) {
-			urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
-				urb->transfer_buffer, urb->transfer_buffer_length,
-				usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
-				PCI_DMA_TODEVICE);
-			if (!urbp->transfer_buffer_dma_handle)
-				return NULL;
-		}
-
-		if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
-			urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
-				urb->setup_packet, sizeof(struct usb_ctrlrequest),
-				PCI_DMA_TODEVICE);
-			if (!urbp->setup_packet_dma_handle)
-				return NULL;
-		}
-	}
-
-	return urbp;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	td->urb = urb;
-
-	list_add_tail(&td->list, &urbp->td_list);
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static void uhci_remove_td_from_urb(struct uhci_td *td)
-{
-	if (list_empty(&td->list))
-		return;
-
-	list_del_init(&td->list);
-
-	td->urb = NULL;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static void uhci_destroy_urb_priv(struct urb *urb)
-{
-	struct list_head *head, *tmp;
-	struct urb_priv *urbp;
-	struct uhci *uhci;
-
-	urbp = (struct urb_priv *)urb->hcpriv;
-	if (!urbp)
-		return;
-
-	if (!urbp->dev || !urbp->dev->bus || !urbp->dev->bus->hcpriv) {
-		warn("uhci_destroy_urb_priv: urb %p belongs to disconnected device or bus?", urb);
-		return;
-	}
-
-	if (!list_empty(&urb->urb_list))
-		warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb);
-
-	if (!list_empty(&urbp->complete_list))
-		warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb);
-
-	uhci = urbp->dev->bus->hcpriv;
-
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		uhci_remove_td_from_urb(td);
-		uhci_remove_td(uhci, td);
-		uhci_free_td(uhci, td);
-	}
-
-	if (urbp->setup_packet_dma_handle) {
-		pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
-			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-		urbp->setup_packet_dma_handle = 0;
-	}
-
-	if (urbp->transfer_buffer_dma_handle) {
-		pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
-			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
-			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-		urbp->transfer_buffer_dma_handle = 0;
-	}
-
-	urb->hcpriv = NULL;
-	kmem_cache_free(uhci_up_cachep, urbp);
-}
-
-static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
-{
-	unsigned long flags;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	if ((!(urb->transfer_flags & USB_NO_FSBR)) && !urbp->fsbr) {
-		urbp->fsbr = 1;
-		if (!uhci->fsbr++)
-			uhci->skel_term_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH;
-	}
-
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
-{
-	unsigned long flags;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	spin_lock_irqsave(&uhci->frame_list_lock, flags);
-
-	if ((!(urb->transfer_flags & USB_NO_FSBR)) && urbp->fsbr) {
-		urbp->fsbr = 0;
-		if (!--uhci->fsbr)
-			uhci->fsbrtimeout = jiffies + FSBR_DELAY;
-	}
-
-	spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
-}
-
-/*
- * Map status to standard result codes
- *
- * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
- * <dir_out> is True for output TDs and False for input TDs.
- */
-static int uhci_map_status(int status, int dir_out)
-{
-	if (!status)
-		return 0;
-	if (status & TD_CTRL_BITSTUFF)			/* Bitstuff error */
-		return -EPROTO;
-	if (status & TD_CTRL_CRCTIMEO) {		/* CRC/Timeout */
-		if (dir_out)
-			return -ETIMEDOUT;
-		else
-			return -EILSEQ;
-	}
-	if (status & TD_CTRL_NAK)			/* NAK */
-		return -ETIMEDOUT;
-	if (status & TD_CTRL_BABBLE)			/* Babble */
-		return -EOVERFLOW;
-	if (status & TD_CTRL_DBUFERR)			/* Buffer error */
-		return -ENOSR;
-	if (status & TD_CTRL_STALLED)			/* Stalled */
-		return -EPIPE;
-	if (status & TD_CTRL_ACTIVE)			/* Active */
-		return 0;
-
-	return -EINVAL;
-}
-
-/*
- * Control transfers
- */
-static int uhci_submit_control(struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct uhci_td *td;
-	struct uhci_qh *qh;
-	unsigned long destination, status;
-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	int len = urb->transfer_buffer_length;
-	dma_addr_t data = urbp->transfer_buffer_dma_handle;
-
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
-
-	/* 3 errors */
-	status = TD_CTRL_ACTIVE | (3 << 27);
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-
-	/*
-	 * Build the TD for the control request
-	 */
-	td = uhci_alloc_td(uhci, urb->dev);
-	if (!td)
-		return -ENOMEM;
-
-	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination | (7 << 21),
-		urbp->setup_packet_dma_handle);
-
-	/*
-	 * If direction is "send", change the frame from SETUP (0x2D)
-	 * to OUT (0xE1). Else change it from SETUP to IN (0x69).
-	 */
-	destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe));
-
-	if (!(urb->transfer_flags & USB_DISABLE_SPD))
-		status |= TD_CTRL_SPD;
-
-	/*
-	 * Build the DATA TD's
-	 */
-	while (len > 0) {
-		int pktsze = len;
-
-		if (pktsze > maxsze)
-			pktsze = maxsze;
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		/* Alternate Data0/1 (start with Data1) */
-		destination ^= 1 << TD_TOKEN_TOGGLE;
-	
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | ((pktsze - 1) << 21),
-			data);
-
-		data += pktsze;
-		len -= pktsze;
-	}
-
-	/*
-	 * Build the final TD for control status 
-	 */
-	td = uhci_alloc_td(uhci, urb->dev);
-	if (!td)
-		return -ENOMEM;
-
-	/*
-	 * It's IN if the pipe is an output pipe or we're not expecting
-	 * data back.
-	 */
-	destination &= ~TD_TOKEN_PID_MASK;
-	if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
-		destination |= USB_PID_IN;
-	else
-		destination |= USB_PID_OUT;
-
-	destination |= 1 << TD_TOKEN_TOGGLE;		/* End in Data1 */
-
-	status &= ~TD_CTRL_SPD;
-
-	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status | TD_CTRL_IOC,
-		destination | (UHCI_NULL_DATA_SIZE << 21), 0);
-
-	qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!qh)
-		return -ENOMEM;
-
-	urbp->qh = qh;
-	qh->urbp = urbp;
-
-	/* Low speed or small transfers gets a different queue and treatment */
-	if (urb->dev->speed == USB_SPEED_LOW) {
-		uhci_insert_tds_in_qh(qh, urb, 0);
-		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
-	} else {
-		uhci_insert_tds_in_qh(qh, urb, 1);
-		uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb);
-		uhci_inc_fsbr(uhci, urb);
-	}
-
-	return -EINPROGRESS;
-}
-
-static int usb_control_retrigger_status(struct urb *urb);
-
-static int uhci_result_control(struct urb *urb)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status;
-	int ret = 0;
-
-	if (list_empty(&urbp->td_list))
-		return -EINVAL;
-
-	head = &urbp->td_list;
-
-	if (urbp->short_control_packet) {
-		tmp = head->prev;
-		goto status_phase;
-	}
-
-	tmp = head->next;
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* The first TD is the SETUP phase, check the status, but skip */
-	/*  the count */
-	status = uhci_status_bits(td->status);
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
-	if (status)
-		goto td_error;
-
-	urb->actual_length = 0;
-
-	/* The rest of the TD's (but the last) are data */
-	tmp = tmp->next;
-	while (tmp != head && tmp->next != head) {
-		td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		if (urbp->fsbr_timeout && (td->status & TD_CTRL_IOC) &&
-		    !(td->status & TD_CTRL_ACTIVE)) {
-			uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
-			urbp->fsbr_timeout = 0;
-			urbp->fsbrtime = jiffies;
-			clear_bit(TD_CTRL_IOC_BIT, &td->status);
-		}
-
-		status = uhci_status_bits(td->status);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(td->status);
-
-		if (status)
-			goto td_error;
-
-		/* Check to see if we received a short packet */
-		if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) {
-			if (urb->transfer_flags & USB_DISABLE_SPD) {
-				ret = -EREMOTEIO;
-				goto err;
-			}
-
-			if (uhci_packetid(td->info) == USB_PID_IN)
-				return usb_control_retrigger_status(urb);
-			else
-				return 0;
-		}
-	}
-
-status_phase:
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* Control status phase */
-	status = uhci_status_bits(td->status);
-
-#ifdef I_HAVE_BUGGY_APC_BACKUPS
-	/* APC BackUPS Pro kludge */
-	/* It tries to send all of the descriptor instead of the amount */
-	/*  we requested */
-	if (td->status & TD_CTRL_IOC &&	/* IOC is masked out by uhci_status_bits */
-	    status & TD_CTRL_ACTIVE &&
-	    status & TD_CTRL_NAK)
-		return 0;
-#endif
-
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
-	if (status)
-		goto td_error;
-
-	return 0;
-
-td_error:
-	ret = uhci_map_status(status, uhci_packetout(td->info));
-	if (ret == -EPIPE)
-		/* endpoint has stalled - mark it halted */
-		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
-	    			uhci_packetout(td->info));
-
-err:
-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
-		/* Some debugging code */
-		dbg("uhci_result_control() failed with status %x", status);
-
-		if (errbuf) {
-			/* Print the chain for debugging purposes */
-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
-			lprintk(errbuf);
-		}
-	}
-
-	return ret;
-}
-
-static int usb_control_retrigger_status(struct urb *urb)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci *uhci = urb->dev->bus->hcpriv;
-
-	urbp->short_control_packet = 1;
-
-	/* Create a new QH to avoid pointer overwriting problems */
-	uhci_remove_qh(uhci, urb);
-
-	/* Delete all of the TD's except for the status TD at the end */
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (tmp != head && tmp->next != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		uhci_remove_td_from_urb(td);
-		uhci_remove_td(uhci, td);
-		uhci_free_td(uhci, td);
-	}
-
-	urbp->qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!urbp->qh) {
-		err("unable to allocate new QH for control retrigger");
-		return -ENOMEM;
-	}
-
-	urbp->qh->urbp = urbp;
-
-	/* One TD, who cares about Breadth first? */
-	uhci_insert_tds_in_qh(urbp->qh, urb, 0);
-
-	/* Low speed or small transfers gets a different queue and treatment */
-	if (urb->dev->speed == USB_SPEED_LOW)
-		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
-	else
-		uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb);
-
-	return -EINPROGRESS;
-}
-
-/*
- * Interrupt transfers
- */
-static int uhci_submit_interrupt(struct urb *urb)
-{
-	struct uhci_td *td;
-	unsigned long destination, status;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
-		return -EINVAL;
-
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOC;
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-
-	td = uhci_alloc_td(uhci, urb->dev);
-	if (!td)
-		return -ENOMEM;
-
-	destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
-	destination |= ((urb->transfer_buffer_length - 1) << 21);
-
-	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-
-	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle);
-
-	uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td);
-
-	return -EINPROGRESS;
-}
-
-static int uhci_result_interrupt(struct urb *urb)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status;
-	int ret = 0;
-
-	urb->actual_length = 0;
-
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (tmp != head) {
-		td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		if (urbp->fsbr_timeout && (td->status & TD_CTRL_IOC) &&
-		    !(td->status & TD_CTRL_ACTIVE)) {
-			uhci_inc_fsbr(urb->dev->bus->hcpriv, urb);
-			urbp->fsbr_timeout = 0;
-			urbp->fsbrtime = jiffies;
-			clear_bit(TD_CTRL_IOC_BIT, &td->status);
-		}
-
-		status = uhci_status_bits(td->status);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(td->status);
-
-		if (status)
-			goto td_error;
-
-		if (uhci_actual_length(td->status) < uhci_expected_length(td->info)) {
-			if (urb->transfer_flags & USB_DISABLE_SPD) {
-				ret = -EREMOTEIO;
-				goto err;
-			} else
-				return 0;
-		}
-	}
-
-	return 0;
-
-td_error:
-	ret = uhci_map_status(status, uhci_packetout(td->info));
-	if (ret == -EPIPE)
-		/* endpoint has stalled - mark it halted */
-		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
-	    			uhci_packetout(td->info));
-
-err:
-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
-		/* Some debugging code */
-		dbg("uhci_result_interrupt/bulk() failed with status %x",
-			status);
-
-		if (errbuf) {
-			/* Print the chain for debugging purposes */
-			if (urbp->qh)
-				uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-			else
-				uhci_show_td(td, errbuf, ERRBUF_LEN, 0);
-
-			lprintk(errbuf);
-		}
-	}
-
-	return ret;
-}
-
-static void uhci_reset_interrupt(struct urb *urb)
-{
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-	unsigned long flags;
-
-	spin_lock_irqsave(&urb->lock, flags);
-
-	/* Root hub is special */
-	if (urb->dev == uhci->rh.dev)
-		goto out;
-
-	td = list_entry(urbp->td_list.next, struct uhci_td, list);
-
-	td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
-	td->info &= ~(1 << TD_TOKEN_TOGGLE);
-	td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
-	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
-
-out:
-	urb->status = -EINPROGRESS;
-
-	spin_unlock_irqrestore(&urb->lock, flags);
-}
-
-/*
- * Bulk transfers
- */
-static int uhci_submit_bulk(struct urb *urb, struct urb *eurb)
-{
-	struct uhci_td *td;
-	struct uhci_qh *qh;
-	unsigned long destination, status;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	int len = urb->transfer_buffer_length;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	dma_addr_t data = urbp->transfer_buffer_dma_handle;
-
-	if (len < 0)
-		return -EINVAL;
-
-	/* Can't have low speed bulk transfers */
-	if (urb->dev->speed == USB_SPEED_LOW)
-		return -EINVAL;
-
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
-	/* 3 errors */
-	status = TD_CTRL_ACTIVE | (3 << TD_CTRL_C_ERR_SHIFT);
-
-	if (!(urb->transfer_flags & USB_DISABLE_SPD))
-		status |= TD_CTRL_SPD;
-
-	/*
-	 * Build the DATA TD's
-	 */
-	do {	/* Allow zero length packets */
-		int pktsze = len;
-
-		if (pktsze > maxsze)
-			pktsze = maxsze;
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination |
-			(((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) |
-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
-			data);
-
-		data += pktsze;
-		len -= pktsze;
-
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			usb_pipeout(urb->pipe));
-	} while (len > 0);
-
-	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) &&
-	   urb->transfer_buffer_length) {
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | UHCI_NULL_DATA_SIZE |
-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
-			data);
-
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			usb_pipeout(urb->pipe));
-	}
-
-	/* Set the flag on the last packet */
-	td->status |= TD_CTRL_IOC;
-
-	qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!qh)
-		return -ENOMEM;
-
-	urbp->qh = qh;
-	qh->urbp = urbp;
-
-	/* Always assume breadth first */
-	uhci_insert_tds_in_qh(qh, urb, 1);
-
-	if (urb->transfer_flags & USB_QUEUE_BULK && eurb)
-		uhci_append_queued_urb(uhci, eurb, urb);
-	else
-		uhci_insert_qh(uhci, uhci->skel_bulk_qh, urb);
-
-	uhci_inc_fsbr(uhci, urb);
-
-	return -EINPROGRESS;
-}
-
-/* We can use the result interrupt since they're identical */
-#define uhci_result_bulk uhci_result_interrupt
-
-/*
- * Isochronous transfers
- */
-static int isochronous_find_limits(struct urb *urb, unsigned int *start, unsigned int *end)
-{
-	struct urb *last_urb = NULL;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct list_head *tmp, *head;
-	int ret = 0;
-
-	head = &uhci->urb_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb *u = list_entry(tmp, struct urb, urb_list);
-
-		tmp = tmp->next;
-
-		/* look for pending URB's with identical pipe handle */
-		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
-		    (u->status == -EINPROGRESS) && (u != urb)) {
-			if (!last_urb)
-				*start = u->start_frame;
-			last_urb = u;
-		}
-	}
-
-	if (last_urb) {
-		*end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
-		ret = 0;
-	} else
-		ret = -1;	/* no previous urb found */
-
-	return ret;
-}
-
-static int isochronous_find_start(struct urb *urb)
-{
-	int limits;
-	unsigned int start = 0, end = 0;
-
-	if (urb->number_of_packets > 900)	/* 900? Why? */
-		return -EFBIG;
-
-	limits = isochronous_find_limits(urb, &start, &end);
-
-	if (urb->transfer_flags & USB_ISO_ASAP) {
-		if (limits) {
-			int curframe;
-
-			curframe = uhci_get_current_frame_number(urb->dev) % UHCI_NUMFRAMES;
-			urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES;
-		} else
-			urb->start_frame = end;
-	} else {
-		urb->start_frame %= UHCI_NUMFRAMES;
-		/* FIXME: Sanity check */
-	}
-
-	return 0;
-}
-
-/*
- * Isochronous transfers
- */
-static int uhci_submit_isochronous(struct urb *urb)
-{
-	struct uhci_td *td;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	int i, ret, framenum;
-	int status, destination;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
-	ret = isochronous_find_start(urb);
-	if (ret)
-		return ret;
-
-	framenum = urb->start_frame;
-	for (i = 0; i < urb->number_of_packets; i++, framenum++) {
-		if (!urb->iso_frame_desc[i].length)
-			continue;
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | ((urb->iso_frame_desc[i].length - 1) << 21),
-			urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset);
-
-		if (i + 1 >= urb->number_of_packets)
-			td->status |= TD_CTRL_IOC;
-
-		uhci_insert_td_frame_list(uhci, td, framenum);
-	}
-
-	return -EINPROGRESS;
-}
-
-static int uhci_result_isochronous(struct urb *urb)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	int status;
-	int i, ret = 0;
-
-	urb->actual_length = 0;
-
-	i = 0;
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-		int actlength;
-
-		tmp = tmp->next;
-
-		if (td->status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		actlength = uhci_actual_length(td->status);
-		urb->iso_frame_desc[i].actual_length = actlength;
-		urb->actual_length += actlength;
-
-		status = uhci_map_status(uhci_status_bits(td->status), usb_pipeout(urb->pipe));
-		urb->iso_frame_desc[i].status = status;
-		if (status) {
-			urb->error_count++;
-			ret = status;
-		}
-
-		i++;
-	}
-
-	return ret;
-}
-
-/*
- * MUST be called with uhci->urb_list_lock acquired
- */
-static struct urb *uhci_find_urb_ep(struct uhci *uhci, struct urb *urb)
-{
-	struct list_head *tmp, *head;
-
-	/* We don't match Isoc transfers since they are special */
-	if (usb_pipeisoc(urb->pipe))
-		return NULL;
-
-	head = &uhci->urb_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb *u = list_entry(tmp, struct urb, urb_list);
-
-		tmp = tmp->next;
-
-		if (u->dev == urb->dev && u->pipe == urb->pipe &&
-		    u->status == -EINPROGRESS)
-			return u;
-	}
-
-	return NULL;
-}
-
-static int uhci_submit_urb(struct urb *urb, int mem_flags)
-{
-	int ret = -EINVAL;
-	struct uhci *uhci;
-	unsigned long flags;
-	struct urb *eurb;
-	int bustime;
-
-	if (!urb)
-		return -EINVAL;
-
-	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
-		warn("uhci_submit_urb: urb %p belongs to disconnected device or bus?", urb);
-		return -ENODEV;
-	}
-
-	/* increment the reference count of the urb, as we now also control it */
-	urb = usb_get_urb(urb);
-
-	uhci = (struct uhci *)urb->dev->bus->hcpriv;
-
-	INIT_LIST_HEAD(&urb->urb_list);
-	usb_inc_dev_use(urb->dev);
-
-	spin_lock_irqsave(&uhci->urb_list_lock, flags);
-	spin_lock(&urb->lock);
-
-	if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
-	    urb->status == -ECONNABORTED) {
-		dbg("uhci_submit_urb: urb not available to submit (status = %d)", urb->status);
-		/* Since we can have problems on the out path */
-		spin_unlock(&urb->lock);
-		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-		usb_dec_dev_use(urb->dev);
-		usb_put_urb(urb);
-
-		return ret;
-	}
-
-	if (!uhci_alloc_urb_priv(uhci, urb)) {
-		ret = -ENOMEM;
-
-		goto out;
-	}
-
-	eurb = uhci_find_urb_ep(uhci, urb);
-	if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
-		ret = -ENXIO;
-
-		goto out;
-	}
-
-	/* Short circuit the virtual root hub */
-	if (urb->dev == uhci->rh.dev) {
-		ret = rh_submit_urb(urb);
-
-		goto out;
-	}
-
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
-		ret = uhci_submit_control(urb);
-		break;
-	case PIPE_INTERRUPT:
-		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
-			bustime = usb_check_bandwidth(urb->dev, urb);
-			if (bustime < 0)
-				ret = bustime;
-			else {
-				ret = uhci_submit_interrupt(urb);
-				if (ret == -EINPROGRESS)
-					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
-			}
-		} else		/* bandwidth is already set */
-			ret = uhci_submit_interrupt(urb);
-		break;
-	case PIPE_BULK:
-		ret = uhci_submit_bulk(urb, eurb);
-		break;
-	case PIPE_ISOCHRONOUS:
-		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
-			if (urb->number_of_packets <= 0) {
-				ret = -EINVAL;
-				break;
-			}
-			bustime = usb_check_bandwidth(urb->dev, urb);
-			if (bustime < 0) {
-				ret = bustime;
-				break;
-			}
-
-			ret = uhci_submit_isochronous(urb);
-			if (ret == -EINPROGRESS)
-				usb_claim_bandwidth(urb->dev, urb, bustime, 1);
-		} else		/* bandwidth is already set */
-			ret = uhci_submit_isochronous(urb);
-		break;
-	}
-
-out:
-	urb->status = ret;
-
-	if (ret == -EINPROGRESS) {
-		/* We use _tail to make find_urb_ep more efficient */
-		list_add_tail(&urb->urb_list, &uhci->urb_list);
-
-		spin_unlock(&urb->lock);
-		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-		return 0;
-	}
-
-	uhci_unlink_generic(uhci, urb);
-
-	spin_unlock(&urb->lock);
-	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-	uhci_call_completion(urb);
-
-	return ret;
-}
-
-/*
- * Return the result of a transfer
- *
- * MUST be called with urb_list_lock acquired
- */
-static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
-{
-	int ret = -EINVAL;
-	unsigned long flags;
-	struct urb_priv *urbp;
-
-	/* The root hub is special */
-	if (urb->dev == uhci->rh.dev)
-		return;
-
-	spin_lock_irqsave(&urb->lock, flags);
-
-	urbp = (struct urb_priv *)urb->hcpriv;
-
-	if (urb->status != -EINPROGRESS) {
-		info("uhci_transfer_result: called for URB %p not in flight?", urb);
-		spin_unlock_irqrestore(&urb->lock, flags);
-		return;
-	}
-
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
-		ret = uhci_result_control(urb);
-		break;
-	case PIPE_INTERRUPT:
-		ret = uhci_result_interrupt(urb);
-		break;
-	case PIPE_BULK:
-		ret = uhci_result_bulk(urb);
-		break;
-	case PIPE_ISOCHRONOUS:
-		ret = uhci_result_isochronous(urb);
-		break;
-	}
-
-	urbp->status = ret;
-
-	if (ret == -EINPROGRESS) {
-		spin_unlock_irqrestore(&urb->lock, flags);
-		return;
-	}
-
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
-	case PIPE_BULK:
-	case PIPE_ISOCHRONOUS:
-		/* Release bandwidth for Interrupt or Isoc. transfers */
-		/* Spinlock needed ? */
-		if (urb->bandwidth)
-			usb_release_bandwidth(urb->dev, urb, 1);
-		uhci_unlink_generic(uhci, urb);
-		break;
-	case PIPE_INTERRUPT:
-		/* Interrupts are an exception */
-		if (urb->interval) {
-			uhci_add_complete(urb);
-			return;		/* <-- note return */
-		}
-
-		/* Release bandwidth for Interrupt or Isoc. transfers */
-		/* Spinlock needed ? */
-		if (urb->bandwidth)
-			usb_release_bandwidth(urb->dev, urb, 0);
-		uhci_unlink_generic(uhci, urb);
-		break;
-	default:
-		info("uhci_transfer_result: unknown pipe type %d for urb %p\n",
-			usb_pipetype(urb->pipe), urb);
-	}
-
-	/* Remove it from uhci->urb_list */
-	list_del_init(&urb->urb_list);
-
-	uhci_add_complete(urb);
-
-	spin_unlock_irqrestore(&urb->lock, flags);
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
-{
-	struct list_head *head, *tmp;
-	struct urb_priv *urbp = urb->hcpriv;
-	int prevactive = 1;
-
-	/* We can get called when urbp allocation fails, so check */
-	if (!urbp)
-		return;
-
-	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
-
-	/*
-	 * Now we need to find out what the last successful toggle was
-	 * so we can update the local data toggle for the next transfer
-	 *
-	 * There's 3 way's the last successful completed TD is found:
-	 *
-	 * 1) The TD is NOT active and the actual length < expected length
-	 * 2) The TD is NOT active and it's the last TD in the chain
-	 * 3) The TD is active and the previous TD is NOT active
-	 *
-	 * Control and Isochronous ignore the toggle, so this is safe
-	 * for all types
-	 */
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		if (!(td->status & TD_CTRL_ACTIVE) &&
-		    (uhci_actual_length(td->status) < uhci_expected_length(td->info) ||
-		    tmp == head))
-			usb_settoggle(urb->dev, uhci_endpoint(td->info),
-				uhci_packetout(td->info),
-				uhci_toggle(td->info) ^ 1);
-		else if ((td->status & TD_CTRL_ACTIVE) && !prevactive)
-			usb_settoggle(urb->dev, uhci_endpoint(td->info),
-				uhci_packetout(td->info),
-				uhci_toggle(td->info));
-
-		prevactive = td->status & TD_CTRL_ACTIVE;
-	}
-
-	uhci_delete_queued_urb(uhci, urb);
-
-	/* The interrupt loop will reclaim the QH's */
-	uhci_remove_qh(uhci, urb);
-}
-
-static int uhci_unlink_urb(struct urb *urb)
-{
-	struct uhci *uhci;
-	unsigned long flags;
-	struct urb_priv *urbp = urb->hcpriv;
-
-	if (!urb)
-		return -EINVAL;
-
-	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
-		return -ENODEV;
-
-	uhci = (struct uhci *)urb->dev->bus->hcpriv;
-
-	spin_lock_irqsave(&uhci->urb_list_lock, flags);
-	spin_lock(&urb->lock);
-
-	/* Release bandwidth for Interrupt or Isoc. transfers */
-	/* Spinlock needed ? */
-	if (urb->bandwidth) {
-		switch (usb_pipetype(urb->pipe)) {
-		case PIPE_INTERRUPT:
-			usb_release_bandwidth(urb->dev, urb, 0);
-			break;
-		case PIPE_ISOCHRONOUS:
-			usb_release_bandwidth(urb->dev, urb, 1);
-			break;
-		default:
-			break;
-		}
-	}
-
-	if (urb->status != -EINPROGRESS) {
-		spin_unlock(&urb->lock);
-		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-		return 0;
-	}
-
-	list_del_init(&urb->urb_list);
-
-	uhci_unlink_generic(uhci, urb);
-
-	/* Short circuit the virtual root hub */
-	if (urb->dev == uhci->rh.dev) {
-		rh_unlink_urb(urb);
-
-		spin_unlock(&urb->lock);
-		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-		uhci_call_completion(urb);
-	} else {
-		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-			urbp->status = urb->status = -ECONNABORTED;
-
-			spin_lock(&uhci->urb_remove_list_lock);
-
-			/* If we're the first, set the next interrupt bit */
-			if (list_empty(&uhci->urb_remove_list))
-				uhci_set_next_interrupt(uhci);
-			
-			list_add(&urb->urb_list, &uhci->urb_remove_list);
-
-			spin_unlock(&uhci->urb_remove_list_lock);
-
-			spin_unlock(&urb->lock);
-			spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-		} else {
-			urb->status = -ENOENT;
-
-			if (in_interrupt()) {	/* wait at least 1 frame */
-				static int errorcount = 10;
-
-				if (errorcount--)
-					dbg("uhci_unlink_urb called from interrupt for urb %p", urb);
-				udelay(1000);
-			} else
-				schedule_timeout(1+1*HZ/1000); 
-
-			spin_unlock(&urb->lock);
-			spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-			uhci_call_completion(urb);
-		}
-	}
-
-	return 0;
-}
-
-static int uhci_fsbr_timeout(struct uhci *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct list_head *head, *tmp;
-
-	uhci_dec_fsbr(uhci, urb);
-
-	/* There is a race with updating IOC in here, but it's not worth */
-	/*  trying to fix since this is merely an optimization. The only */
-	/*  time we'd lose is if the status of the packet got updated */
-	/*  and we'd be turning on FSBR next frame anyway, so it's a wash */
-	urbp->fsbr_timeout = 1;
-
-	head = &urbp->td_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
-
-		tmp = tmp->next;
-
-		if (td->status & TD_CTRL_ACTIVE) {
-			set_bit(TD_CTRL_IOC_BIT, &td->status);
-			break;
-		}
-	}
-
-	return 0;
-}
-
-/*
- * uhci_get_current_frame_number()
- *
- * returns the current frame number for a USB bus/controller.
- */
-static int uhci_get_current_frame_number(struct usb_device *dev)
-{
-	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
-
-	return inw(uhci->io_addr + USBFRNUM);
-}
-
-struct usb_operations uhci_device_operations = {
-	allocate:		uhci_alloc_dev,
-	deallocate:		uhci_free_dev,
-	get_frame_number:	uhci_get_current_frame_number,
-	submit_urb:		uhci_submit_urb,
-	unlink_urb:		uhci_unlink_urb,
-};
-
-/* Virtual Root Hub */
-
-static __u8 root_hub_dev_des[] =
-{
- 	0x12,			/*  __u8  bLength; */
-	0x01,			/*  __u8  bDescriptorType; Device */
-	0x00,			/*  __u16 bcdUSB; v1.0 */
-	0x01,
-	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,			/*  __u8  bDeviceSubClass; */
-	0x00,			/*  __u8  bDeviceProtocol; */
-	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
-	0x00,			/*  __u16 idVendor; */
-	0x00,
-	0x00,			/*  __u16 idProduct; */
-	0x00,
-	0x00,			/*  __u16 bcdDevice; */
-	0x00,
-	0x00,			/*  __u8  iManufacturer; */
-	0x02,			/*  __u8  iProduct; */
-	0x01,			/*  __u8  iSerialNumber; */
-	0x01			/*  __u8  bNumConfigurations; */
-};
-
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
-	0x09,			/*  __u8  bLength; */
-	0x02,			/*  __u8  bDescriptorType; Configuration */
-	0x19,			/*  __u16 wTotalLength; */
-	0x00,
-	0x01,			/*  __u8  bNumInterfaces; */
-	0x01,			/*  __u8  bConfigurationValue; */
-	0x00,			/*  __u8  iConfiguration; */
-	0x40,			/*  __u8  bmAttributes;
-					Bit 7: Bus-powered, 6: Self-powered,
-					Bit 5 Remote-wakeup, 4..0: resvd */
-	0x00,			/*  __u8  MaxPower; */
-
-	/* interface */
-	0x09,			/*  __u8  if_bLength; */
-	0x04,			/*  __u8  if_bDescriptorType; Interface */
-	0x00,			/*  __u8  if_bInterfaceNumber; */
-	0x00,			/*  __u8  if_bAlternateSetting; */
-	0x01,			/*  __u8  if_bNumEndpoints; */
-	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,			/*  __u8  if_bInterfaceSubClass; */
-	0x00,			/*  __u8  if_bInterfaceProtocol; */
-	0x00,			/*  __u8  if_iInterface; */
-
-	/* endpoint */
-	0x07,			/*  __u8  ep_bLength; */
-	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
-	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
-	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
-	0x00,
-	0xff			/*  __u8  ep_bInterval; 255 ms */
-};
-
-static __u8 root_hub_hub_des[] =
-{
-	0x09,			/*  __u8  bLength; */
-	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
-	0x02,			/*  __u8  bNbrPorts; */
-	0x00,			/* __u16  wHubCharacteristics; */
-	0x00,
-	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
-	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
-	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
-	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-static int rh_send_irq(struct urb *urb)
-{
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	unsigned int io_addr = uhci->io_addr;
-	unsigned long flags;
-	int i, len = 1;
-	__u16 data = 0;
-
-	spin_lock_irqsave(&urb->lock, flags);
-	for (i = 0; i < uhci->rh.numports; i++) {
-		data |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
-		len = (i + 1) / 8 + 1;
-	}
-
-	*(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
-	urb->actual_length = len;
-	urbp->status = 0;
-
-	spin_unlock_irqrestore(&urb->lock, flags);
-
-	if ((data > 0) && (uhci->rh.send != 0)) {
-		dbg("root-hub INT complete: port1: %x port2: %x data: %x",
-			inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data);
-		uhci_call_completion(urb);
-	}
-
-	return 0;
-}
-
-/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
-static int rh_init_int_timer(struct urb *urb);
-
-static void rh_int_timer_do(unsigned long ptr)
-{
-	struct urb *urb = (struct urb *)ptr;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct list_head list, *tmp, *head;
-	unsigned long flags;
-
-	if (uhci->rh.send)
-		rh_send_irq(urb);
-
-	INIT_LIST_HEAD(&list);
-
-	spin_lock_irqsave(&uhci->urb_list_lock, flags);
-	head = &uhci->urb_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb *u = list_entry(tmp, struct urb, urb_list);
-		struct urb_priv *urbp = (struct urb_priv *)u->hcpriv;
-
-		tmp = tmp->next;
-
-		spin_lock(&urb->lock);
-
-		/* Check if the FSBR timed out */
-		if (urbp->fsbr && !urbp->fsbr_timeout && time_after_eq(jiffies, urbp->fsbrtime + IDLE_TIMEOUT))
-			uhci_fsbr_timeout(uhci, u);
-
-		/* Check if the URB timed out */
-		if (u->timeout && time_after_eq(jiffies, urbp->inserttime + u->timeout)) {
-			list_del(&u->urb_list);
-			list_add_tail(&u->urb_list, &list);
-		}
-
-		spin_unlock(&urb->lock);
-	}
-	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-
-	head = &list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb *u = list_entry(tmp, struct urb, urb_list);
-
-		tmp = tmp->next;
-
-		u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
-		uhci_unlink_urb(u);
-	}
-
-	/* Really disable FSBR */
-	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
-		uhci->fsbrtimeout = 0;
-		uhci->skel_term_qh->link = UHCI_PTR_TERM;
-	}
-
-	/* enter global suspend if nothing connected */
-	if (!uhci->is_suspended && !ports_active(uhci))
-		suspend_hc(uhci);
-
-	rh_init_int_timer(urb);
-}
-
-/* Root Hub INTs are polled by this timer */
-static int rh_init_int_timer(struct urb *urb)
-{
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-
-	uhci->rh.interval = urb->interval;
-	init_timer(&uhci->rh.rh_int_timer);
-	uhci->rh.rh_int_timer.function = rh_int_timer_do;
-	uhci->rh.rh_int_timer.data = (unsigned long)urb;
-	uhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
-	add_timer(&uhci->rh.rh_int_timer);
-
-	return 0;
-}
-
-#define OK(x)			len = (x); break
-
-#define CLR_RH_PORTSTAT(x) \
-	status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
-	status = (status & 0xfff5) & ~(x); \
-	outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
-
-#define SET_RH_PORTSTAT(x) \
-	status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
-	status = (status & 0xfff5) | (x); \
-	outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
-
-
-/* Root Hub Control Pipe */
-static int rh_submit_urb(struct urb *urb)
-{
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	unsigned int pipe = urb->pipe;
-	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet;
-	void *data = urb->transfer_buffer;
-	int leni = urb->transfer_buffer_length;
-	int len = 0;
-	int status = 0;
-	int stat = 0;
-	int i;
-	unsigned int io_addr = uhci->io_addr;
-	__u16 cstatus;
-	__u16 bmRType_bReq;
-	__u16 wValue;
-	__u16 wIndex;
-	__u16 wLength;
-
-	if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
-		uhci->rh.urb = urb;
-		uhci->rh.send = 1;
-		uhci->rh.interval = urb->interval;
-		rh_init_int_timer(urb);
-
-		return -EINPROGRESS;
-	}
-
-	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
-	wValue = le16_to_cpu(cmd->wValue);
-	wIndex = le16_to_cpu(cmd->wIndex);
-	wLength = le16_to_cpu(cmd->wLength);
-
-	for (i = 0; i < 8; i++)
-		uhci->rh.c_p_r[i] = 0;
-
-	switch (bmRType_bReq) {
-		/* Request Destination:
-		   without flags: Device,
-		   RH_INTERFACE: interface,
-		   RH_ENDPOINT: endpoint,
-		   RH_CLASS means HUB here,
-		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
-		*/
-
-	case RH_GET_STATUS:
-		*(__u16 *)data = cpu_to_le16(1);
-		OK(2);
-	case RH_GET_STATUS | RH_INTERFACE:
-		*(__u16 *)data = cpu_to_le16(0);
-		OK(2);
-	case RH_GET_STATUS | RH_ENDPOINT:
-		*(__u16 *)data = cpu_to_le16(0);
-		OK(2);
-	case RH_GET_STATUS | RH_CLASS:
-		*(__u32 *)data = cpu_to_le32(0);
-		OK(4);		/* hub power */
-	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-		status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1));
-		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
-			((status & USBPORTSC_PEC) >> (3 - 1)) |
-			(uhci->rh.c_p_r[wIndex - 1] << (0 + 4));
-			status = (status & USBPORTSC_CCS) |
-			((status & USBPORTSC_PE) >> (2 - 1)) |
-			((status & USBPORTSC_SUSP) >> (12 - 2)) |
-			((status & USBPORTSC_PR) >> (9 - 4)) |
-			(1 << 8) |      /* power on */
-			((status & USBPORTSC_LSDA) << (-8 + 9));
-
-		*(__u16 *)data = cpu_to_le16(status);
-		*(__u16 *)(data + 2) = cpu_to_le16(cstatus);
-		OK(4);
-	case RH_CLEAR_FEATURE | RH_ENDPOINT:
-		switch (wValue) {
-		case RH_ENDPOINT_STALL:
-			OK(0);
-		}
-		break;
-	case RH_CLEAR_FEATURE | RH_CLASS:
-		switch (wValue) {
-		case RH_C_HUB_OVER_CURRENT:
-			OK(0);	/* hub power over current */
-		}
-		break;
-	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-		switch (wValue) {
-		case RH_PORT_ENABLE:
-			CLR_RH_PORTSTAT(USBPORTSC_PE);
-			OK(0);
-		case RH_PORT_SUSPEND:
-			CLR_RH_PORTSTAT(USBPORTSC_SUSP);
-			OK(0);
-		case RH_PORT_POWER:
-			OK(0);	/* port power */
-		case RH_C_PORT_CONNECTION:
-			SET_RH_PORTSTAT(USBPORTSC_CSC);
-			OK(0);
-		case RH_C_PORT_ENABLE:
-			SET_RH_PORTSTAT(USBPORTSC_PEC);
-			OK(0);
-		case RH_C_PORT_SUSPEND:
-			/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
-			OK(0);
-		case RH_C_PORT_OVER_CURRENT:
-			OK(0);	/* port power over current */
-		case RH_C_PORT_RESET:
-			uhci->rh.c_p_r[wIndex - 1] = 0;
-			OK(0);
-		}
-		break;
-	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-		switch (wValue) {
-		case RH_PORT_SUSPEND:
-			SET_RH_PORTSTAT(USBPORTSC_SUSP);
-			OK(0);
-		case RH_PORT_RESET:
-			SET_RH_PORTSTAT(USBPORTSC_PR);
-			wait_ms(50);	/* USB v1.1 7.1.7.3 */
-			uhci->rh.c_p_r[wIndex - 1] = 1;
-			CLR_RH_PORTSTAT(USBPORTSC_PR);
-			udelay(10);
-			SET_RH_PORTSTAT(USBPORTSC_PE);
-			wait_ms(10);
-			SET_RH_PORTSTAT(0xa);
-			OK(0);
-		case RH_PORT_POWER:
-			OK(0); /* port power ** */
-		case RH_PORT_ENABLE:
-			SET_RH_PORTSTAT(USBPORTSC_PE);
-			OK(0);
-		}
-		break;
-	case RH_SET_ADDRESS:
-		uhci->rh.devnum = wValue;
-		OK(0);
-	case RH_GET_DESCRIPTOR:
-		switch ((wValue & 0xff00) >> 8) {
-		case 0x01:	/* device descriptor */
-			len = min_t(unsigned int, leni,
-				  min_t(unsigned int,
-				      sizeof(root_hub_dev_des), wLength));
-			memcpy(data, root_hub_dev_des, len);
-			OK(len);
-		case 0x02:	/* configuration descriptor */
-			len = min_t(unsigned int, leni,
-				  min_t(unsigned int,
-				      sizeof(root_hub_config_des), wLength));
-			memcpy (data, root_hub_config_des, len);
-			OK(len);
-		case 0x03:	/* string descriptors */
-			len = usb_root_hub_string (wValue & 0xff,
-				uhci->io_addr, "UHCI-alt",
-				data, wLength);
-			if (len > 0) {
-				OK(min_t(int, leni, len));
-			} else 
-				stat = -EPIPE;
-		}
-		break;
-	case RH_GET_DESCRIPTOR | RH_CLASS:
-		root_hub_hub_des[2] = uhci->rh.numports;
-		len = min_t(unsigned int, leni,
-			  min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
-		memcpy(data, root_hub_hub_des, len);
-		OK(len);
-	case RH_GET_CONFIGURATION:
-		*(__u8 *)data = 0x01;
-		OK(1);
-	case RH_SET_CONFIGURATION:
-		OK(0);
-	case RH_GET_INTERFACE | RH_INTERFACE:
-		*(__u8 *)data = 0x00;
-		OK(1);
-	case RH_SET_INTERFACE | RH_INTERFACE:
-		OK(0);
-	default:
-		stat = -EPIPE;
-	}
-
-	urb->actual_length = len;
-
-	return stat;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static int rh_unlink_urb(struct urb *urb)
-{
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-
-	if (uhci->rh.urb == urb) {
-		urb->status = -ENOENT;
-		uhci->rh.send = 0;
-		uhci->rh.urb = NULL;
-		del_timer(&uhci->rh.rh_int_timer);
-	}
-	return 0;
-}
-
-static void uhci_free_pending_qhs(struct uhci *uhci)
-{
-	struct list_head *tmp, *head;
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->qh_remove_list_lock, flags);
-	head = &uhci->qh_remove_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list);
-
-		tmp = tmp->next;
-
-		list_del_init(&qh->remove_list);
-
-		uhci_free_qh(uhci, qh);
-	}
-	spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags);
-}
-
-static void uhci_call_completion(struct urb *urb)
-{
-	struct urb_priv *urbp;
-	struct usb_device *dev = urb->dev;
-	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
-	int is_ring = 0, killed, resubmit_interrupt, status;
-	struct urb *nurb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&urb->lock, flags);
-
-	urbp = (struct urb_priv *)urb->hcpriv;
-	if (!urbp || !urb->dev) {
-		spin_unlock_irqrestore(&urb->lock, flags);
-		return;
-	}
-
-	killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
-			urb->status == -ECONNRESET);
-	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
-			urb->interval);
-
-	nurb = urb->next;
-	if (nurb && !killed) {
-		int count = 0;
-
-		while (nurb && nurb != urb && count < MAX_URB_LOOP) {
-			if (nurb->status == -ENOENT ||
-			    nurb->status == -ECONNABORTED ||
-			    nurb->status == -ECONNRESET) {
-				killed = 1;
-				break;
-			}
-
-			nurb = nurb->next;
-			count++;
-		}
-
-		if (count == MAX_URB_LOOP)
-			err("uhci_call_completion: too many linked URB's, loop? (first loop)");
-
-		/* Check to see if chain is a ring */
-		is_ring = (nurb == urb);
-	}
-
-	if (urbp->transfer_buffer_dma_handle)
-		pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
-			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
-			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-
-	if (urbp->setup_packet_dma_handle)
-		pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
-			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-
-	status = urbp->status;
-	if (!resubmit_interrupt || killed)
-		/* We don't need urb_priv anymore */
-		uhci_destroy_urb_priv(urb);
-
-	if (!killed)
-		urb->status = status;
-
-	urb->dev = NULL;
-	spin_unlock_irqrestore(&urb->lock, flags);
-
-	if (urb->complete) {
-		urb->complete(urb);
-
-		/* Recheck the status. The completion handler may have */
-		/*  unlinked the resubmitting interrupt URB */
-		killed = (urb->status == -ENOENT ||
-			  urb->status == -ECONNABORTED ||
-			  urb->status == -ECONNRESET);
-	}
-
-	if (resubmit_interrupt && !killed) {
-		urb->dev = dev;
-		uhci_reset_interrupt(urb);
-	} else {
-		if (is_ring && !killed) {
-			urb->dev = dev;
-			uhci_submit_urb(urb, GFP_KERNEL);
-		} else {
-			/* We decrement the usage count after we're done */
-			/*  with everything */
-			usb_dec_dev_use(dev);
-			usb_put_urb(urb);
-		}
-	}
-}
-
-static void uhci_finish_completion(struct uhci *uhci)
-{
-	struct list_head *tmp, *head;
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->complete_list_lock, flags);
-	head = &uhci->complete_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list);
-		struct urb *urb = urbp->urb;
-
-		list_del_init(&urbp->complete_list);
-		spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
-
-		uhci_call_completion(urb);
-
-		spin_lock_irqsave(&uhci->complete_list_lock, flags);
-		head = &uhci->complete_list;
-		tmp = head->next;
-	}
-	spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
-}
-
-static void uhci_remove_pending_qhs(struct uhci *uhci)
-{
-	struct list_head *tmp, *head;
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->urb_remove_list_lock, flags);
-	head = &uhci->urb_remove_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb *urb = list_entry(tmp, struct urb, urb_list);
-		struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-		tmp = tmp->next;
-
-		list_del_init(&urb->urb_list);
-
-		urbp->status = urb->status = -ECONNRESET;
-
-		uhci_add_complete(urb);
-	}
-	spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
-}
-
-static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
-{
-	struct uhci *uhci = __uhci;
-	unsigned int io_addr = uhci->io_addr;
-	unsigned short status;
-	struct list_head *tmp, *head;
-
-	/*
-	 * Read the interrupt status, and write it back to clear the
-	 * interrupt cause
-	 */
-	status = inw(io_addr + USBSTS);
-	if (!status)	/* shared interrupt, not mine */
-		return;
-	outw(status, io_addr + USBSTS);		/* Clear it */
-
-	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
-		if (status & USBSTS_HSE)
-			err("%x: host system error, PCI problems?", io_addr);
-		if (status & USBSTS_HCPE)
-			err("%x: host controller process error. something bad happened", io_addr);
-		if ((status & USBSTS_HCH) && !uhci->is_suspended) {
-			err("%x: host controller halted. very bad", io_addr);
-			/* FIXME: Reset the controller, fix the offending TD */
-		}
-	}
-
-	if (status & USBSTS_RD)
-		wakeup_hc(uhci);
-
-	uhci_free_pending_qhs(uhci);
-
-	uhci_remove_pending_qhs(uhci);
-
-	uhci_clear_next_interrupt(uhci);
-
-	/* Walk the list of pending URB's to see which ones completed */
-	spin_lock(&uhci->urb_list_lock);
-	head = &uhci->urb_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb *urb = list_entry(tmp, struct urb, urb_list);
-
-		tmp = tmp->next;
-
-		/* Checks the status and does all of the magic necessary */
-		uhci_transfer_result(uhci, urb);
-	}
-	spin_unlock(&uhci->urb_list_lock);
-
-	uhci_finish_completion(uhci);
-}
-
-static void reset_hc(struct uhci *uhci)
-{
-	unsigned int io_addr = uhci->io_addr;
-
-	/* Global reset for 50ms */
-	outw(USBCMD_GRESET, io_addr + USBCMD);
-	wait_ms(50);
-	outw(0, io_addr + USBCMD);
-	wait_ms(10);
-}
-
-static void suspend_hc(struct uhci *uhci)
-{
-	unsigned int io_addr = uhci->io_addr;
-
-	dbg("%x: suspend_hc", io_addr);
-
-	outw(USBCMD_EGSM, io_addr + USBCMD);
-
-	uhci->is_suspended = 1;
-}
-
-static void wakeup_hc(struct uhci *uhci)
-{
-	unsigned int io_addr = uhci->io_addr;
-	unsigned int status;
-
-	dbg("%x: wakeup_hc", io_addr);
-
-	outw(0, io_addr + USBCMD);
-	
-	/* wait for EOP to be sent */
-	status = inw(io_addr + USBCMD);
-	while (status & USBCMD_FGR)
-		status = inw(io_addr + USBCMD);
-
-	uhci->is_suspended = 0;
-
-	/* Run and mark it configured with a 64-byte max packet */
-	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
-}
-
-static int ports_active(struct uhci *uhci)
-{
-	unsigned int io_addr = uhci->io_addr;
-	int connection = 0;
-	int i;
-
-	for (i = 0; i < uhci->rh.numports; i++)
-		connection |= (inw(io_addr + USBPORTSC1 + i * 2) & 0x1);
-
-	return connection;
-}
-
-static void start_hc(struct uhci *uhci)
-{
-	unsigned int io_addr = uhci->io_addr;
-	int timeout = 1000;
-
-	/*
-	 * Reset the HC - this will force us to get a
-	 * new notification of any already connected
-	 * ports due to the virtual disconnect that it
-	 * implies.
-	 */
-	outw(USBCMD_HCRESET, io_addr + USBCMD);
-	while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
-		if (!--timeout) {
-			printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n");
-			break;
-		}
-	}
-
-	/* Turn on all interrupts */
-	outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
-		io_addr + USBINTR);
-
-	/* Start at frame 0 */
-	outw(0, io_addr + USBFRNUM);
-	outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
-
-	/* Run and mark it configured with a 64-byte max packet */
-	outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
-}
-
-#ifdef CONFIG_PROC_FS
-static int uhci_num = 0;
-#endif
-
-static void free_uhci(struct uhci *uhci)
-{
-	kfree(uhci);
-}
-
-/*
- * De-allocate all resources..
- */
-static void release_uhci(struct uhci *uhci)
-{
-	int i;
-#ifdef CONFIG_PROC_FS
-	char buf[8];
-#endif
-
-	if (uhci->irq >= 0) {
-		free_irq(uhci->irq, uhci);
-		uhci->irq = -1;
-	}
-
-	for (i = 0; i < UHCI_NUM_SKELQH; i++)
-		if (uhci->skelqh[i]) {
-			uhci_free_qh(uhci, uhci->skelqh[i]);
-			uhci->skelqh[i] = NULL;
-		}
-
-	for (i = 0; i < UHCI_NUM_SKELTD; i++)
-		if (uhci->skeltd[i]) {
-			uhci_free_td(uhci, uhci->skeltd[i]);
-			uhci->skeltd[i] = NULL;
-		}
-
-	if (uhci->qh_pool) {
-		pci_pool_destroy(uhci->qh_pool);
-		uhci->qh_pool = NULL;
-	}
-
-	if (uhci->td_pool) {
-		pci_pool_destroy(uhci->td_pool);
-		uhci->td_pool = NULL;
-	}
-
-	if (uhci->fl) {
-		pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
-		uhci->fl = NULL;
-	}
-
-	if (uhci->bus) {
-		usb_free_bus(uhci->bus);
-		uhci->bus = NULL;
-	}
-
-#ifdef CONFIG_PROC_FS
-	if (uhci->proc_entry) {
-		sprintf(buf, "hc%d", uhci->num);
-
-		remove_proc_entry(buf, uhci_proc_root);
-		uhci->proc_entry = NULL;
-	}
-#endif
-
-	free_uhci(uhci);
-}
-
-/*
- * Allocate a frame list, and then setup the skeleton
- *
- * The hardware doesn't really know any difference
- * in the queues, but the order does matter for the
- * protocols higher up. The order is:
- *
- *  - any isochronous events handled before any
- *    of the queues. We don't do that here, because
- *    we'll create the actual TD entries on demand.
- *  - The first queue is the interrupt queue.
- *  - The second queue is the control queue, split into low and high speed
- *  - The third queue is bulk queue.
- *  - The fourth queue is the bandwidth reclamation queue, which loops back
- *    to the high speed control queue.
- */
-static int alloc_uhci(struct pci_dev *dev, unsigned int io_addr, unsigned int io_size)
-{
-	struct uhci *uhci;
-	int retval;
-	char buf[8], *bufp = buf;
-	int i, port;
-	struct usb_bus *bus;
-	dma_addr_t dma_handle;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *ent;
-#endif
-
-	retval = -ENODEV;
-	if (pci_enable_device(dev) < 0) {
-		err("couldn't enable PCI device");
-		goto err_enable_device;
-	}
-
-	if (!dev->irq) {
-		err("found UHCI device with no IRQ assigned. check BIOS settings!");
-		goto err_invalid_irq;
-	}
-
-	if (!pci_dma_supported(dev, 0xFFFFFFFF)) {
-		err("PCI subsystem doesn't support 32 bit addressing?");
-		goto err_pci_dma_supported;
-	}
-
-	retval = -EBUSY;
-	if (!request_region(io_addr, io_size, "usb-uhci")) {
-		err("couldn't allocate I/O range %x - %x", io_addr,
-			io_addr + io_size - 1);
-		goto err_request_region;
-	}
-
-	pci_set_master(dev);
-
-#ifndef __sparc__
-	sprintf(buf, "%d", dev->irq);
-#else
-	bufp = __irq_itoa(dev->irq);
-#endif
-	printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
-		io_addr, bufp);
-
-	if (pci_set_dma_mask(dev, 0xFFFFFFFF)) {
-		err("couldn't set PCI dma mask");
-		retval = -ENODEV;
-		goto err_pci_set_dma_mask;
-	}
-
-	uhci = kmalloc(sizeof(*uhci), GFP_KERNEL);
-	if (!uhci) {
-		err("couldn't allocate uhci structure");
-		retval = -ENOMEM;
-		goto err_alloc_uhci;
-	}
-
-	uhci->dev = dev;
-	uhci->io_addr = io_addr;
-	uhci->io_size = io_size;
-	pci_set_drvdata(dev, uhci);
-
-#ifdef CONFIG_PROC_FS
-	uhci->num = uhci_num++;
-
-	sprintf(buf, "hc%d", uhci->num);
-
-	ent = create_proc_entry(buf, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root);
-	if (!ent) {
-		err("couldn't create uhci proc entry");
-		retval = -ENOMEM;
-		goto err_create_proc_entry;
-	}
-
-	ent->data = uhci;
-	ent->proc_fops = &uhci_proc_operations;
-	ent->size = 0;
-	uhci->proc_entry = ent;
-#endif
-
-	/* Reset here so we don't get any interrupts from an old setup */
-	/*  or broken setup */
-	reset_hc(uhci);
-
-	spin_lock_init(&uhci->qh_remove_list_lock);
-	INIT_LIST_HEAD(&uhci->qh_remove_list);
-
-	spin_lock_init(&uhci->urb_remove_list_lock);
-	INIT_LIST_HEAD(&uhci->urb_remove_list);
-
-	spin_lock_init(&uhci->urb_list_lock);
-	INIT_LIST_HEAD(&uhci->urb_list);
-
-	spin_lock_init(&uhci->complete_list_lock);
-	INIT_LIST_HEAD(&uhci->complete_list);
-
-	spin_lock_init(&uhci->frame_list_lock);
-
-	/* We need exactly one page (per UHCI specs), how convenient */
-	/* We assume that one page is atleast 4k (1024 frames * 4 bytes) */
-#if PAGE_SIZE < (4 * 1024)
-#error PAGE_SIZE is not atleast 4k
-#endif
-	uhci->fl = pci_alloc_consistent(uhci->dev, sizeof(*uhci->fl), &dma_handle);
-	if (!uhci->fl) {
-		err("unable to allocate consistent memory for frame list");
-		goto err_alloc_fl;
-	}
-
-	memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
-
-	uhci->fl->dma_handle = dma_handle;
-
-	uhci->td_pool = pci_pool_create("uhci_td", uhci->dev,
-		sizeof(struct uhci_td), 16, 0, GFP_DMA | GFP_ATOMIC);
-	if (!uhci->td_pool) {
-		err("unable to create td pci_pool");
-		goto err_create_td_pool;
-	}
-
-	uhci->qh_pool = pci_pool_create("uhci_qh", uhci->dev,
-		sizeof(struct uhci_qh), 16, 0, GFP_DMA | GFP_ATOMIC);
-	if (!uhci->qh_pool) {
-		err("unable to create qh pci_pool");
-		goto err_create_qh_pool;
-	}
-
-	bus = usb_alloc_bus(&uhci_device_operations);
-	if (!bus) {
-		err("unable to allocate bus");
-		goto err_alloc_bus;
-	}
-
-	uhci->bus = bus;
-	bus->hcpriv = uhci;
-
-	usb_register_bus(uhci->bus);
-
-	/* Initialize the root hub */
-
-	/* UHCI specs says devices must have 2 ports, but goes on to say */
-	/*  they may have more but give no way to determine how many they */
-	/*  have. However, according to the UHCI spec, Bit 7 is always set */
-	/*  to 1. So we try to use this to our advantage */
-	for (port = 0; port < (uhci->io_size - 0x10) / 2; port++) {
-		unsigned int portstatus;
-
-		portstatus = inw(uhci->io_addr + 0x10 + (port * 2));
-		if (!(portstatus & 0x0080))
-			break;
-	}
-	if (debug)
-		info("detected %d ports", port);
-
-	/* This is experimental so anything less than 2 or greater than 8 is */
-	/*  something weird and we'll ignore it */
-	if (port < 2 || port > 8) {
-		info("port count misdetected? forcing to 2 ports");
-		port = 2;
-	}
-
-	uhci->rh.numports = port;
-
-	uhci->bus->root_hub = uhci->rh.dev = usb_alloc_dev(NULL, uhci->bus);
-	if (!uhci->rh.dev) {
-		err("unable to allocate root hub");
-		goto err_alloc_root_hub;
-	}
-
-	uhci->skeltd[0] = uhci_alloc_td(uhci, uhci->rh.dev);
-	if (!uhci->skeltd[0]) {
-		err("unable to allocate TD 0");
-		goto err_alloc_skeltd;
-	}
-
-	/*
-	 * 9 Interrupt queues; link int2 to int1, int4 to int2, etc
-	 * then link int1 to control and control to bulk
-	 */
-	for (i = 1; i < 9; i++) {
-		struct uhci_td *td;
-
-		td = uhci->skeltd[i] = uhci_alloc_td(uhci, uhci->rh.dev);
-		if (!td) {
-			err("unable to allocate TD %d", i);
-			goto err_alloc_skeltd;
-		}
-
-		uhci_fill_td(td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
-		td->link = uhci->skeltd[i - 1]->dma_handle;
-	}
-
-	uhci->skel_term_td = uhci_alloc_td(uhci, uhci->rh.dev);
-	if (!uhci->skel_term_td) {
-		err("unable to allocate skel TD term");
-		goto err_alloc_skeltd;
-	}
-
-	for (i = 0; i < UHCI_NUM_SKELQH; i++) {
-		uhci->skelqh[i] = uhci_alloc_qh(uhci, uhci->rh.dev);
-		if (!uhci->skelqh[i]) {
-			err("unable to allocate QH %d", i);
-			goto err_alloc_skelqh;
-		}
-	}
-
-	uhci_fill_td(uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
-	uhci->skel_int1_td->link = uhci->skel_ls_control_qh->dma_handle | UHCI_PTR_QH;
-
-	uhci->skel_ls_control_qh->link = uhci->skel_hs_control_qh->dma_handle | UHCI_PTR_QH;
-	uhci->skel_ls_control_qh->element = UHCI_PTR_TERM;
-
-	uhci->skel_hs_control_qh->link = uhci->skel_bulk_qh->dma_handle | UHCI_PTR_QH;
-	uhci->skel_hs_control_qh->element = UHCI_PTR_TERM;
-
-	uhci->skel_bulk_qh->link = uhci->skel_term_qh->dma_handle | UHCI_PTR_QH;
-	uhci->skel_bulk_qh->element = UHCI_PTR_TERM;
-
-	/* This dummy TD is to work around a bug in Intel PIIX controllers */
-	uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
-	uhci->skel_term_td->link = uhci->skel_term_td->dma_handle;
-
-	uhci->skel_term_qh->link = UHCI_PTR_TERM;
-	uhci->skel_term_qh->element = uhci->skel_term_td->dma_handle;
-
-	/*
-	 * Fill the frame list: make all entries point to
-	 * the proper interrupt queue.
-	 *
-	 * This is probably silly, but it's a simple way to
-	 * scatter the interrupt queues in a way that gives
-	 * us a reasonable dynamic range for irq latencies.
-	 */
-	for (i = 0; i < UHCI_NUMFRAMES; i++) {
-		int irq = 0;
-
-		if (i & 1) {
-			irq++;
-			if (i & 2) {
-				irq++;
-				if (i & 4) { 
-					irq++;
-					if (i & 8) { 
-						irq++;
-						if (i & 16) {
-							irq++;
-							if (i & 32) {
-								irq++;
-								if (i & 64)
-									irq++;
-							}
-						}
-					}
-				}
-			}
-		}
-
-		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] =  uhci->skeltd[irq]->dma_handle;
-	}
-
-	start_hc(uhci);
-
-	if (request_irq(dev->irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci))
-		goto err_request_irq;
-
-	uhci->irq = dev->irq;
-
-	/* disable legacy emulation */
-	pci_write_config_word(uhci->dev, USBLEGSUP, USBLEGSUP_DEFAULT);
-
-	usb_connect(uhci->rh.dev);
-
-	if (usb_register_root_hub(uhci->rh.dev, &dev->dev) != 0) {
-		err("unable to start root hub");
-		retval = -ENOMEM;
-		goto err_start_root_hub;
-	}
-
-	return 0;
-
-/*
- * error exits:
- */
-err_start_root_hub:
-	free_irq(uhci->irq, uhci);
-	uhci->irq = -1;
-
-err_request_irq:
-	for (i = 0; i < UHCI_NUM_SKELQH; i++)
-		if (uhci->skelqh[i]) {
-			uhci_free_qh(uhci, uhci->skelqh[i]);
-			uhci->skelqh[i] = NULL;
-		}
-
-err_alloc_skelqh:
-	for (i = 0; i < UHCI_NUM_SKELTD; i++)
-		if (uhci->skeltd[i]) {
-			uhci_free_td(uhci, uhci->skeltd[i]);
-			uhci->skeltd[i] = NULL;
-		}
-
-err_alloc_skeltd:
-	usb_free_dev(uhci->rh.dev);
-	uhci->rh.dev = NULL;
-
-err_alloc_root_hub:
-	usb_free_bus(uhci->bus);
-	uhci->bus = NULL;
-
-err_alloc_bus:
-	pci_pool_destroy(uhci->qh_pool);
-	uhci->qh_pool = NULL;
-
-err_create_qh_pool:
-	pci_pool_destroy(uhci->td_pool);
-	uhci->td_pool = NULL;
-
-err_create_td_pool:
-	pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle);
-	uhci->fl = NULL;
-
-err_alloc_fl:
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry(buf, uhci_proc_root);
-	uhci->proc_entry = NULL;
-
-err_create_proc_entry:
-	free_uhci(uhci);
-#endif
-
-err_alloc_uhci:
-
-err_pci_set_dma_mask:
-	release_region(io_addr, io_size);
-
-err_request_region:
-
-err_pci_dma_supported:
-
-err_invalid_irq:
-
-err_enable_device:
-
-	return retval;
-}
-
-static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	int i;
-
-	/* Search for the IO base address.. */
-	for (i = 0; i < 6; i++) {
-		unsigned int io_addr = pci_resource_start(dev, i);
-		unsigned int io_size = pci_resource_len(dev, i);
-
-		/* IO address? */
-		if (!(pci_resource_flags(dev, i) & IORESOURCE_IO))
-			continue;
-
-		return alloc_uhci(dev, io_addr, io_size);
-	}
-
-	return -ENODEV;
-}
-
-static void __devexit uhci_pci_remove(struct pci_dev *dev)
-{
-	struct uhci *uhci = pci_get_drvdata(dev);
-
-	if (uhci->bus->root_hub)
-		usb_disconnect(&uhci->bus->root_hub);
-
-	usb_deregister_bus(uhci->bus);
-
-	/*
-	 * At this point, we're guaranteed that no new connects can be made
-	 * to this bus since there are no more parents
-	 */
-	uhci_free_pending_qhs(uhci);
-	uhci_remove_pending_qhs(uhci);
-
-	reset_hc(uhci);
-	release_region(uhci->io_addr, uhci->io_size);
-
-	uhci_free_pending_qhs(uhci);
-
-	release_uhci(uhci);
-}
-
-#ifdef CONFIG_PM
-static int uhci_pci_suspend(struct pci_dev *dev, u32 state)
-{
-	suspend_hc((struct uhci *) pci_get_drvdata(dev));
-	return 0;
-}
-
-static int uhci_pci_resume(struct pci_dev *dev)
-{
-	reset_hc((struct uhci *) pci_get_drvdata(dev));
-	start_hc((struct uhci *) pci_get_drvdata(dev));
-	return 0;
-}
-#endif
-
-static const struct pci_device_id __devinitdata uhci_pci_ids[] = { {
-
-	/* handle any USB UHCI controller */
-	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x00),
-	class_mask: 	~0,
-
-	/* no matter who makes it */
-	vendor:		PCI_ANY_ID,
-	device:		PCI_ANY_ID,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-	}, { /* end: all zeroes */ }
-};
-
-MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
-
-static struct pci_driver uhci_pci_driver = {
-	name:		"usb-uhci",
-	id_table:	uhci_pci_ids,
-
-	probe:		uhci_pci_probe,
-	remove:		__devexit_p(uhci_pci_remove),
-
-#ifdef	CONFIG_PM
-	suspend:	uhci_pci_suspend,
-	resume:		uhci_pci_resume,
-#endif	/* PM */
-};
-
- 
-static int __init uhci_hcd_init(void)
-{
-	int retval = -ENOMEM;
-
-	info(DRIVER_DESC " " DRIVER_VERSION);
-
-	if (debug) {
-		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
-		if (!errbuf)
-			goto errbuf_failed;
-	}
-
-#ifdef CONFIG_PROC_FS
-	uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, 0);
-	if (!uhci_proc_root)
-		goto proc_failed;
-#endif
-
-	uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
-		sizeof(struct urb_priv), 0, 0, NULL, NULL);
-	if (!uhci_up_cachep)
-		goto up_failed;
-
-	retval = pci_module_init(&uhci_pci_driver);
-	if (retval)
-		goto init_failed;
-
-	return 0;
-
-init_failed:
-	if (kmem_cache_destroy(uhci_up_cachep))
-		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
-
-up_failed:
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("uhci", 0);
-
-proc_failed:
-#endif
-	if (errbuf)
-		kfree(errbuf);
-
-errbuf_failed:
-
-	return retval;
-}
-
-static void __exit uhci_hcd_cleanup(void) 
-{
-	pci_unregister_driver(&uhci_pci_driver);
-	
-	if (kmem_cache_destroy(uhci_up_cachep))
-		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("uhci", 0);
-#endif
-
-	if (errbuf)
-		kfree(errbuf);
-}
-
-module_init(uhci_hcd_init);
-module_exit(uhci_hcd_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/usb/uhci.h b/drivers/usb/uhci.h
--- a/drivers/usb/uhci.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,441 +0,0 @@
-#ifndef __LINUX_UHCI_H
-#define __LINUX_UHCI_H
-
-#include <linux/list.h>
-#include <linux/usb.h>
-
-/*
- * Universal Host Controller Interface data structures and defines
- */
-
-/* Command register */
-#define USBCMD		0
-#define   USBCMD_RS		0x0001	/* Run/Stop */
-#define   USBCMD_HCRESET	0x0002	/* Host reset */
-#define   USBCMD_GRESET		0x0004	/* Global reset */
-#define   USBCMD_EGSM		0x0008	/* Global Suspend Mode */
-#define   USBCMD_FGR		0x0010	/* Force Global Resume */
-#define   USBCMD_SWDBG		0x0020	/* SW Debug mode */
-#define   USBCMD_CF		0x0040	/* Config Flag (sw only) */
-#define   USBCMD_MAXP		0x0080	/* Max Packet (0 = 32, 1 = 64) */
-
-/* Status register */
-#define USBSTS		2
-#define   USBSTS_USBINT		0x0001	/* Interrupt due to IOC */
-#define   USBSTS_ERROR		0x0002	/* Interrupt due to error */
-#define   USBSTS_RD		0x0004	/* Resume Detect */
-#define   USBSTS_HSE		0x0008	/* Host System Error - basically PCI problems */
-#define   USBSTS_HCPE		0x0010	/* Host Controller Process Error - the scripts were buggy */
-#define   USBSTS_HCH		0x0020	/* HC Halted */
-
-/* Interrupt enable register */
-#define USBINTR		4
-#define   USBINTR_TIMEOUT	0x0001	/* Timeout/CRC error enable */
-#define   USBINTR_RESUME	0x0002	/* Resume interrupt enable */
-#define   USBINTR_IOC		0x0004	/* Interrupt On Complete enable */
-#define   USBINTR_SP		0x0008	/* Short packet interrupt enable */
-
-#define USBFRNUM	6
-#define USBFLBASEADD	8
-#define USBSOF		12
-
-/* USB port status and control registers */
-#define USBPORTSC1	16
-#define USBPORTSC2	18
-#define   USBPORTSC_CCS		0x0001	/* Current Connect Status ("device present") */
-#define   USBPORTSC_CSC		0x0002	/* Connect Status Change */
-#define   USBPORTSC_PE		0x0004	/* Port Enable */
-#define   USBPORTSC_PEC		0x0008	/* Port Enable Change */
-#define   USBPORTSC_LS		0x0030	/* Line Status */
-#define   USBPORTSC_RD		0x0040	/* Resume Detect */
-#define   USBPORTSC_LSDA	0x0100	/* Low Speed Device Attached */
-#define   USBPORTSC_PR		0x0200	/* Port Reset */
-#define   USBPORTSC_SUSP	0x1000	/* Suspend */
-
-/* Legacy support register */
-#define USBLEGSUP		0xc0
-#define   USBLEGSUP_DEFAULT	0x2000	/* only PIRQ enable set */
-
-#define UHCI_NULL_DATA_SIZE	0x7FF	/* for UHCI controller TD */
-
-#define UHCI_PTR_BITS		0x000F
-#define UHCI_PTR_TERM		0x0001
-#define UHCI_PTR_QH		0x0002
-#define UHCI_PTR_DEPTH		0x0004
-
-#define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
-#define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
-#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
-
-struct uhci_frame_list {
-	__u32 frame[UHCI_NUMFRAMES];
-
-	void *frame_cpu[UHCI_NUMFRAMES];
-
-	dma_addr_t dma_handle;
-};
-
-struct urb_priv;
-
-struct uhci_qh {
-	/* Hardware fields */
-	__u32 link;			/* Next queue */
-	__u32 element;			/* Queue element pointer */
-
-	/* Software fields */
-	dma_addr_t dma_handle;
-
-	struct usb_device *dev;
-	struct urb_priv *urbp;
-
-	struct list_head list;		/* P: uhci->frame_list_lock */
-	struct list_head remove_list;	/* P: uhci->remove_list_lock */
-} __attribute__((aligned(16)));
-
-/*
- * for TD <status>:
- */
-#define TD_CTRL_SPD		(1 << 29)	/* Short Packet Detect */
-#define TD_CTRL_C_ERR_MASK	(3 << 27)	/* Error Counter bits */
-#define TD_CTRL_C_ERR_SHIFT	27
-#define TD_CTRL_LS		(1 << 26)	/* Low Speed Device */
-#define TD_CTRL_IOS		(1 << 25)	/* Isochronous Select */
-#define TD_CTRL_IOC_BIT		24
-#define TD_CTRL_IOC		(1 << 24)	/* Interrupt on Complete */
-#define TD_CTRL_ACTIVE		(1 << 23)	/* TD Active */
-#define TD_CTRL_STALLED		(1 << 22)	/* TD Stalled */
-#define TD_CTRL_DBUFERR		(1 << 21)	/* Data Buffer Error */
-#define TD_CTRL_BABBLE		(1 << 20)	/* Babble Detected */
-#define TD_CTRL_NAK		(1 << 19)	/* NAK Received */
-#define TD_CTRL_CRCTIMEO	(1 << 18)	/* CRC/Time Out Error */
-#define TD_CTRL_BITSTUFF	(1 << 17)	/* Bit Stuff Error */
-#define TD_CTRL_ACTLEN_MASK	0x7FF		/* actual length, encoded as n - 1 */
-
-#define TD_CTRL_ANY_ERROR	(TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
-				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
-
-#define uhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
-#define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
-
-/*
- * for TD <info>: (a.k.a. Token)
- */
-#define TD_TOKEN_TOGGLE		19
-#define TD_TOKEN_PID_MASK	0xFF
-#define TD_TOKEN_EXPLEN_MASK	0x7FF		/* expected length, encoded as n - 1 */
-
-#define uhci_maxlen(token)	((token) >> 21)
-#define uhci_expected_length(info) (((info >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) /* 1-based */
-#define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
-#define uhci_endpoint(token)	(((token) >> 15) & 0xf)
-#define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
-#define uhci_devep(token)	(((token) >> 8) & 0x7ff)
-#define uhci_packetid(token)	((token) & TD_TOKEN_PID_MASK)
-#define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
-#define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
-
-/*
- * The documentation says "4 words for hardware, 4 words for software".
- *
- * That's silly, the hardware doesn't care. The hardware only cares that
- * the hardware words are 16-byte aligned, and we can have any amount of
- * sw space after the TD entry as far as I can tell.
- *
- * But let's just go with the documentation, at least for 32-bit machines.
- * On 64-bit machines we probably want to take advantage of the fact that
- * hw doesn't really care about the size of the sw-only area.
- *
- * Alas, not anymore, we have more than 4 words for software, woops.
- * Everything still works tho, surprise! -jerdfelt
- */
-struct uhci_td {
-	/* Hardware fields */
-	__u32 link;
-	__u32 status;
-	__u32 info;
-	__u32 buffer;
-
-	/* Software fields */
-	dma_addr_t dma_handle;
-
-	struct usb_device *dev;
-	struct urb *urb;
-
-	struct list_head list;		/* P: urb->lock */
-
-	int frame;
-	struct list_head fl_list;	/* P: uhci->frame_list_lock */
-} __attribute__((aligned(16)));
-
-/*
- * There are various standard queues. We set up several different
- * queues for each of the three basic queue types: interrupt,
- * control, and bulk.
- *
- *  - There are various different interrupt latencies: ranging from
- *    every other USB frame (2 ms apart) to every 256 USB frames (ie
- *    256 ms apart). Make your choice according to how obnoxious you
- *    want to be on the wire, vs how critical latency is for you.
- *  - The control list is done every frame.
- *  - There are 4 bulk lists, so that up to four devices can have a
- *    bulk list of their own and when run concurrently all four lists
- *    will be be serviced.
- *
- * This is a bit misleading, there are various interrupt latencies, but they
- * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the
- * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor
- * problem
- *
- * In the case of the root hub, these QH's are just head's of qh's. Don't
- * be scared, it kinda makes sense. Look at this wonderful picture care of
- * Linus:
- *
- *  generic-  ->  dev1-  ->  generic-  ->  dev1-  ->  control-  ->  bulk- -> ...
- *   iso-QH      iso-QH       irq-QH      irq-QH        QH           QH
- *      |           |            |           |           |            |
- *     End     dev1-iso-TD1     End     dev1-irq-TD1    ...          ... 
- *                  |
- *             dev1-iso-TD2
- *                  |
- *                ....
- *
- * This may vary a bit (the UHCI docs don't explicitly say you can put iso
- * transfers in QH's and all of their pictures don't have that either) but
- * other than that, that is what we're doing now
- *
- * And now we don't put Iso transfers in QH's, so we don't waste one on it
- * --jerdfelt
- *
- * To keep with Linus' nomenclature, this is called the QH skeleton. These
- * labels (below) are only signficant to the root hub's QH's
- */
-
-#define UHCI_NUM_SKELTD		10
-#define skel_int1_td		skeltd[0]
-#define skel_int2_td		skeltd[1]
-#define skel_int4_td		skeltd[2]
-#define skel_int8_td		skeltd[3]
-#define skel_int16_td		skeltd[4]
-#define skel_int32_td		skeltd[5]
-#define skel_int64_td		skeltd[6]
-#define skel_int128_td		skeltd[7]
-#define skel_int256_td		skeltd[8]
-#define skel_term_td		skeltd[9]	/* To work around PIIX UHCI bug */
-
-#define UHCI_NUM_SKELQH		4
-#define skel_ls_control_qh	skelqh[0]
-#define skel_hs_control_qh	skelqh[1]
-#define skel_bulk_qh		skelqh[2]
-#define skel_term_qh		skelqh[3]
-
-/*
- * Search tree for determining where <interval> fits in the
- * skelqh[] skeleton.
- *
- * An interrupt request should be placed into the slowest skelqh[]
- * which meets the interval/period/frequency requirement.
- * An interrupt request is allowed to be faster than <interval> but not slower.
- *
- * For a given <interval>, this function returns the appropriate/matching
- * skelqh[] index value.
- *
- * NOTE: For UHCI, we don't really need int256_qh since the maximum interval
- * is 255 ms.  However, we do need an int1_qh since 1 is a valid interval
- * and we should meet that frequency when requested to do so.
- * This will require some change(s) to the UHCI skeleton.
- */
-static inline int __interval_to_skel(int interval)
-{
-	if (interval < 16) {
-		if (interval < 4) {
-			if (interval < 2)
-				return 0;	/* int1 for 0-1 ms */
-			return 1;		/* int2 for 2-3 ms */
-		}
-		if (interval < 8)
-			return 2;		/* int4 for 4-7 ms */
-		return 3;			/* int8 for 8-15 ms */
-	}
-	if (interval < 64) {
-		if (interval < 32)
-			return 4;		/* int16 for 16-31 ms */
-		return 5;			/* int32 for 32-63 ms */
-	}
-	if (interval < 128)
-		return 6;			/* int64 for 64-127 ms */
-	return 7;				/* int128 for 128-255 ms (Max.) */
-}
-
-struct virt_root_hub {
-	struct usb_device *dev;
-	int devnum;		/* Address of Root Hub endpoint */
-	struct urb *urb;
-	void *int_addr;
-	int send;
-	int interval;
-	int numports;
-	int c_p_r[8];
-	struct timer_list rh_int_timer;
-};
-
-/*
- * This describes the full uhci information.
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs.
- */
-struct uhci {
-	struct pci_dev *dev;
-
-	/* procfs */
-	int num;
-	struct proc_dir_entry *proc_entry;
-
-	/* Grabbed from PCI */
-	int irq;
-	unsigned int io_addr;
-	unsigned int io_size;
-
-	struct list_head uhci_list;
-
-	struct pci_pool *qh_pool;
-	struct pci_pool *td_pool;
-
-	struct usb_bus *bus;
-
-	struct uhci_td *skeltd[UHCI_NUM_SKELTD];	/* Skeleton TD's */
-	struct uhci_qh *skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
-
-	spinlock_t frame_list_lock;
-	struct uhci_frame_list *fl;		/* P: uhci->frame_list_lock */
-	int fsbr;				/* Full speed bandwidth reclamation */
-	unsigned long fsbrtimeout;		/* FSBR delay */
-	int is_suspended;
-
-	/* Main list of URB's currently controlled by this HC */
-	spinlock_t urb_list_lock;
-	struct list_head urb_list;		/* P: uhci->urb_list_lock */
-
-	/* List of QH's that are done, but waiting to be unlinked (race) */
-	spinlock_t qh_remove_list_lock;
-	struct list_head qh_remove_list;	/* P: uhci->qh_remove_list_lock */
-
-	/* List of asynchronously unlinked URB's */
-	spinlock_t urb_remove_list_lock;
-	struct list_head urb_remove_list;	/* P: uhci->urb_remove_list_lock */
-
-	/* List of URB's awaiting completion callback */
-	spinlock_t complete_list_lock;
-	struct list_head complete_list;		/* P: uhci->complete_list_lock */
-
-	struct virt_root_hub rh;	/* private data of the virtual root hub */
-};
-
-struct urb_priv {
-	struct urb *urb;
-	struct usb_device *dev;
-
-	dma_addr_t setup_packet_dma_handle;
-	dma_addr_t transfer_buffer_dma_handle;
-
-	struct uhci_qh *qh;		/* QH for this URB */
-	struct list_head td_list;	/* P: urb->lock */
-
-	int fsbr : 1;			/* URB turned on FSBR */
-	int fsbr_timeout : 1;		/* URB timed out on FSBR */
-	int queued : 1;			/* QH was queued (not linked in) */
-	int short_control_packet : 1;	/* If we get a short packet during */
-					/*  a control transfer, retrigger */
-					/*  the status phase */
-
-	int status;			/* Final status */
-
-	unsigned long inserttime;	/* In jiffies */
-	unsigned long fsbrtime;		/* In jiffies */
-
-	struct list_head queue_list;	/* P: uhci->frame_list_lock */
-	struct list_head complete_list;	/* P: uhci->complete_list_lock */
-};
-
-/*
- * Locking in uhci.c
- *
- * spinlocks are used extensively to protect the many lists and data
- * structures we have. It's not that pretty, but it's necessary. We
- * need to be done with all of the locks (except complete_list_lock) when
- * we call urb->complete. I've tried to make it simple enough so I don't
- * have to spend hours racking my brain trying to figure out if the
- * locking is safe.
- *
- * Here's the safe locking order to prevent deadlocks:
- *
- * #1 uhci->urb_list_lock
- * #2 urb->lock
- * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock, 
- *   uhci->qh_remove_list_lock
- * #4 uhci->complete_list_lock
- *
- * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
- * at the lowest level FIRST and NEVER grab locks at the same level at the
- * same time.
- * 
- * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock
- */
-
-/* -------------------------------------------------------------------------
-   Virtual Root HUB
-   ------------------------------------------------------------------------- */
-/* destination of request */
-#define RH_DEVICE		0x00
-#define RH_INTERFACE		0x01
-#define RH_ENDPOINT		0x02
-#define RH_OTHER		0x03
-
-#define RH_CLASS		0x20
-#define RH_VENDOR		0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS		0x0080
-#define RH_CLEAR_FEATURE	0x0100
-#define RH_SET_FEATURE		0x0300
-#define RH_SET_ADDRESS		0x0500
-#define RH_GET_DESCRIPTOR	0x0680
-#define RH_SET_DESCRIPTOR	0x0700
-#define RH_GET_CONFIGURATION	0x0880
-#define RH_SET_CONFIGURATION	0x0900
-#define RH_GET_STATE		0x0280
-#define RH_GET_INTERFACE	0x0A80
-#define RH_SET_INTERFACE	0x0B00
-#define RH_SYNC_FRAME		0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP		0x2000
-
-/* Hub port features */
-#define RH_PORT_CONNECTION	0x00
-#define RH_PORT_ENABLE		0x01
-#define RH_PORT_SUSPEND		0x02
-#define RH_PORT_OVER_CURRENT	0x03
-#define RH_PORT_RESET		0x04
-#define RH_PORT_POWER		0x08
-#define RH_PORT_LOW_SPEED	0x09
-#define RH_C_PORT_CONNECTION	0x10
-#define RH_C_PORT_ENABLE	0x11
-#define RH_C_PORT_SUSPEND	0x12
-#define RH_C_PORT_OVER_CURRENT	0x13
-#define RH_C_PORT_RESET		0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER	0x00
-#define RH_C_HUB_OVER_CURRENT	0x01
-#define RH_DEVICE_REMOTE_WAKEUP	0x00
-#define RH_ENDPOINT_STALL	0x01
-
-/* Our Vendor Specific feature */
-#define RH_REMOVE_EP		0x00
-
-#define RH_ACK			0x01
-#define RH_REQ_ERR		-1
-#define RH_NACK			0x00
-
-#endif
-
diff -Nru a/drivers/usb/ultracam.c b/drivers/usb/ultracam.c
--- a/drivers/usb/ultracam.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,706 +0,0 @@
-/*
- * USB NB Camera driver
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/wrapper.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "usbvideo.h"
-
-#define	ULTRACAM_VENDOR_ID	0x0461
-#define	ULTRACAM_PRODUCT_ID	0x0813
-
-#define MAX_CAMERAS		4	/* How many devices we allow to connect */
-
-/*
- * This structure lives in uvd_t->user field.
- */
-typedef struct {
-	int initialized;	/* Had we already sent init sequence? */
-	int camera_model;	/* What type of IBM camera we got? */
-        int has_hdr;
-} ultracam_t;
-#define	ULTRACAM_T(uvd)	((ultracam_t *)((uvd)->user_data))
-
-static usbvideo_t *cams = NULL;
-
-static int debug = 0;
-
-static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
-
-static const int min_canvasWidth  = 8;
-static const int min_canvasHeight = 4;
-
-//static int lighting = 1; /* Medium */
-
-#define SHARPNESS_MIN	0
-#define SHARPNESS_MAX	6
-//static int sharpness = 4; /* Low noise, good details */
-
-#define FRAMERATE_MIN	0
-#define FRAMERATE_MAX	6
-static int framerate = -1;
-
-/*
- * Here we define several initialization variables. They may
- * be used to automatically set color, hue, brightness and
- * contrast to desired values. This is particularly useful in
- * case of webcams (which have no controls and no on-screen
- * output) and also when a client V4L software is used that
- * does not have some of those controls. In any case it's
- * good to have startup values as options.
- *
- * These values are all in [0..255] range. This simplifies
- * operation. Note that actual values of V4L variables may
- * be scaled up (as much as << 8). User can see that only
- * on overlay output, however, or through a V4L client.
- */
-static int init_brightness = 128;
-static int init_contrast = 192;
-static int init_color = 128;
-static int init_hue = 128;
-static int hue_correction = 128;
-
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
-MODULE_PARM_DESC(flags,
-		"Bitfield: 0=VIDIOCSYNC, "
-		"1=B/W, "
-		"2=show hints, "
-		"3=show stats, "
-		"4=test pattern, "
-		"5=separate frames, "
-		"6=clean frames");
-MODULE_PARM(framerate, "i");
-MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-MODULE_PARM(lighting, "i");
-MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
-MODULE_PARM(sharpness, "i");
-MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
-
-MODULE_PARM(init_brightness, "i");
-MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
-MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
-MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
-MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
-MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
-
-/*
- * ultracam_ProcessIsocData()
- *
- * Generic routine to parse the ring queue data. It employs either
- * ultracam_find_header() or ultracam_parse_lines() to do most
- * of work.
- *
- * 02-Nov-2000 First (mostly dummy) version.
- * 06-Nov-2000 Rewrote to dump all data into frame.
- */
-void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame)
-{
-	int n;
-
-	assert(uvd != NULL);
-	assert(frame != NULL);
-
-	/* Try to move data from queue into frame buffer */
-	n = RingQueue_GetLength(&uvd->dp);
-	if (n > 0) {
-		int m;
-		/* See how much spare we have left */
-		m = uvd->max_frame_size - frame->seqRead_Length;
-		if (n > m)
-			n = m;
-		/* Now move that much data into frame buffer */
-		RingQueue_Dequeue(
-			&uvd->dp,
-			frame->data + frame->seqRead_Length,
-			m);
-		frame->seqRead_Length += m;
-	}
-	/* See if we filled the frame */
-	if (frame->seqRead_Length >= uvd->max_frame_size) {
-		frame->frameState = FrameState_Done;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-	}
-}
-
-/*
- * ultracam_veio()
- *
- * History:
- * 1/27/00  Added check for dev == NULL; this happens if camera is unplugged.
- */
-static int ultracam_veio(
-	uvd_t *uvd,
-	unsigned char req,
-	unsigned short value,
-	unsigned short index,
-	int is_out)
-{
-	static const char proc[] = "ultracam_veio";
-	unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
-	int i;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return 0;
-
-	if (!is_out) {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_rcvctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value,
-			index,
-			cp,
-			sizeof(cp),
-			HZ);
-#if 1
-		info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
-		       "(req=$%02x val=$%04x ind=$%04x)",
-		       cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
-		       req, value, index);
-#endif
-	} else {
-		i = usb_control_msg(
-			uvd->dev,
-			usb_sndctrlpipe(uvd->dev, 0),
-			req,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value,
-			index,
-			NULL,
-			0,
-			HZ);
-	}
-	if (i < 0) {
-		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
-		    proc, i);
-		uvd->last_error = i;
-	}
-	return i;
-}
-
-/*
- * ultracam_calculate_fps()
- */
-static int ultracam_calculate_fps(uvd_t *uvd)
-{
-	return 3 + framerate*4 + framerate/2;
-}
-
-/*
- * ultracam_adjust_contrast()
- */
-static void ultracam_adjust_contrast(uvd_t *uvd)
-{
-}
-
-/*
- * ultracam_change_lighting_conditions()
- */
-static void ultracam_change_lighting_conditions(uvd_t *uvd)
-{
-}
-
-/*
- * ultracam_set_sharpness()
- *
- * Cameras model 1 have internal smoothing feature. It is controlled by value in
- * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
- * Recommended value is 4. Cameras model 2 do not have this feature at all.
- */
-static void ultracam_set_sharpness(uvd_t *uvd)
-{
-}
-
-/*
- * ultracam_set_brightness()
- *
- * This procedure changes brightness of the picture.
- */
-static void ultracam_set_brightness(uvd_t *uvd)
-{
-}
-
-static void ultracam_set_hue(uvd_t *uvd)
-{
-}
-
-/*
- * ultracam_adjust_picture()
- *
- * This procedure gets called from V4L interface to update picture settings.
- * Here we change brightness and contrast.
- */
-static void ultracam_adjust_picture(uvd_t *uvd)
-{
-	ultracam_adjust_contrast(uvd);
-	ultracam_set_brightness(uvd);
-	ultracam_set_hue(uvd);
-}
-
-/*
- * ultracam_video_stop()
- *
- * This code tells camera to stop streaming. The interface remains
- * configured and bandwidth - claimed.
- */
-static void ultracam_video_stop(uvd_t *uvd)
-{
-}
-
-/*
- * ultracam_reinit_iso()
- *
- * This procedure sends couple of commands to the camera and then
- * resets the video pipe. This sequence was observed to reinit the
- * camera or, at least, to initiate ISO data stream.
- */
-static void ultracam_reinit_iso(uvd_t *uvd, int do_stop)
-{
-}
-
-static void ultracam_video_start(uvd_t *uvd)
-{
-	ultracam_change_lighting_conditions(uvd);
-	ultracam_set_sharpness(uvd);
-	ultracam_reinit_iso(uvd, 0);
-}
-
-static int ultracam_resetPipe(uvd_t *uvd)
-{
-	usb_clear_halt(uvd->dev, uvd->video_endp);
-	return 0;
-}
-
-static int ultracam_alternateSetting(uvd_t *uvd, int setting)
-{
-	static const char proc[] = "ultracam_alternateSetting";
-	int i;
-	i = usb_set_interface(uvd->dev, uvd->iface, setting);
-	if (i < 0) {
-		err("%s: usb_set_interface error", proc);
-		uvd->last_error = i;
-		return -EBUSY;
-	}
-	return 0;
-}
-
-/*
- * Return negative code on failure, 0 on success.
- */
-static int ultracam_setup_on_open(uvd_t *uvd)
-{
-	int setup_ok = 0; /* Success by default */
-	/* Send init sequence only once, it's large! */
-	if (!ULTRACAM_T(uvd)->initialized) {
-		ultracam_alternateSetting(uvd, 0x04);
-		ultracam_alternateSetting(uvd, 0x00);
-		ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1);
-		ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1);
-		ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
-		ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1);
-		ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1);
-		ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1);
-		ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1);
-		ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1);
-		ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1);
-		ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1);
-		ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1);
-		ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1);
-		ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1);
-		ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1);
-		ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1);
-		ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
-		ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
-		ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
-		ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
-		ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
-		ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
-		ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
-		ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
-		ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1);
-		ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1);
-		ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1);
-		ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1);
-		ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1);
-		ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1);
-		ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1);
-		ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1);
-		ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1);
-		ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1);
-		ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1);
-		ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1);
-		ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1);
-		ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1);
-		ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1);
-		ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1);
-		ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1);
-		ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1);
-		ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1);
-		ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1);
-		ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1);
-		ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1);
-		ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
-		ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0);
-		ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
-		ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
-		ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
-		ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
-		ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
-		ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
-		ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
-		ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
-		ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0);
-		ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1);
-		ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1);
-		ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1);
-		ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1);
-		ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1);
-		ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1);
-		ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1);
-		ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
-		ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1);
-		ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1);
-		ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
-		ultracam_alternateSetting(uvd, 0x04);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1);
-		ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1);
-		ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1);
-		ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0);
-		ultracam_resetPipe(uvd);
-		ULTRACAM_T(uvd)->initialized = (setup_ok != 0);
-	}
-	return setup_ok;
-}
-
-static void ultracam_configure_video(uvd_t *uvd)
-{
-	if (uvd == NULL)
-		return;
-
-	RESTRICT_TO_RANGE(init_brightness, 0, 255);
-	RESTRICT_TO_RANGE(init_contrast, 0, 255);
-	RESTRICT_TO_RANGE(init_color, 0, 255);
-	RESTRICT_TO_RANGE(init_hue, 0, 255);
-	RESTRICT_TO_RANGE(hue_correction, 0, 255);
-
-	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
-	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
-
-	uvd->vpic.colour = init_color << 8;
-	uvd->vpic.hue = init_hue << 8;
-	uvd->vpic.brightness = init_brightness << 8;
-	uvd->vpic.contrast = init_contrast << 8;
-	uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
-	uvd->vpic.depth = 24;
-	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
-
-	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
-	strcpy(uvd->vcap.name, "IBM Ultra Camera");
-	uvd->vcap.type = VID_TYPE_CAPTURE;
-	uvd->vcap.channels = 1;
-	uvd->vcap.audios = 0;
-	uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
-	uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
-	uvd->vcap.minwidth = min_canvasWidth;
-	uvd->vcap.minheight = min_canvasHeight;
-
-	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
-	uvd->vchan.flags = 0;
-	uvd->vchan.tuners = 0;
-	uvd->vchan.channel = 0;
-	uvd->vchan.type = VIDEO_TYPE_CAMERA;
-	strcpy(uvd->vchan.name, "Camera");
-}
-
-/*
- * ultracam_probe()
- *
- * This procedure queries device descriptor and accepts the interface
- * if it looks like our camera.
- *
- * History:
- * 12-Nov-2000 Reworked to comply with new probe() signature.
- * 23-Jan-2001 Added compatibility with 2.2.x kernels.
- */
-static void *ultracam_probe(struct usb_device *dev, unsigned int ifnum ,const struct usb_device_id *devid)
-{
-	uvd_t *uvd = NULL;
-	int i, nas;
-	int actInterface=-1, inactInterface=-1, maxPS=0;
-	unsigned char video_ep = 0;
-
-	if (debug >= 1)
-		info("ultracam_probe(%p,%u.)", dev, ifnum);
-
-	/* We don't handle multi-config cameras */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-	/* Is it an IBM camera? */
-	if ((dev->descriptor.idVendor != ULTRACAM_VENDOR_ID) ||
-	    (dev->descriptor.idProduct != ULTRACAM_PRODUCT_ID))
-		return NULL;
-
-	info("IBM Ultra camera found (rev. 0x%04x)", dev->descriptor.bcdDevice);
-
-	/* Validate found interface: must have one ISO endpoint */
-	nas = dev->actconfig->interface[ifnum].num_altsetting;
-	if (debug > 0)
-		info("Number of alternate settings=%d.", nas);
-	if (nas < 8) {
-		err("Too few alternate settings for this camera!");
-		return NULL;
-	}
-	/* Validate all alternate settings */
-	for (i=0; i < nas; i++) {
-		const struct usb_interface_descriptor *interface;
-		const struct usb_endpoint_descriptor *endpoint;
-
-		interface = &dev->actconfig->interface[ifnum].altsetting[i];
-		if (interface->bNumEndpoints != 1) {
-			err("Interface %d. has %u. endpoints!",
-			    ifnum, (unsigned)(interface->bNumEndpoints));
-			return NULL;
-		}
-		endpoint = &interface->endpoint[0];
-		if (video_ep == 0)
-			video_ep = endpoint->bEndpointAddress;
-		else if (video_ep != endpoint->bEndpointAddress) {
-			err("Alternate settings have different endpoint addresses!");
-			return NULL;
-		}
-		if ((endpoint->bmAttributes & 0x03) != 0x01) {
-			err("Interface %d. has non-ISO endpoint!", ifnum);
-			return NULL;
-		}
-		if ((endpoint->bEndpointAddress & 0x80) == 0) {
-			err("Interface %d. has ISO OUT endpoint!", ifnum);
-			return NULL;
-		}
-		if (endpoint->wMaxPacketSize == 0) {
-			if (inactInterface < 0)
-				inactInterface = i;
-			else {
-				err("More than one inactive alt. setting!");
-				return NULL;
-			}
-		} else {
-			if (actInterface < 0) {
-				actInterface = i;
-				maxPS = endpoint->wMaxPacketSize;
-				if (debug > 0)
-					info("Active setting=%d. maxPS=%d.", i, maxPS);
-			} else {
-				/* Got another active alt. setting */
-				if (maxPS < endpoint->wMaxPacketSize) {
-					/* This one is better! */
-					actInterface = i;
-					maxPS = endpoint->wMaxPacketSize;
-					if (debug > 0) {
-						info("Even better ctive setting=%d. maxPS=%d.",
-						     i, maxPS);
-					}
-				}
-			}
-		}
-	}
-	if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
-		err("Failed to recognize the camera!");
-		return NULL;
-	}
-
-	/* Code below may sleep, need to lock module while we are here */
-	MOD_INC_USE_COUNT;
-	uvd = usbvideo_AllocateDevice(cams);
-	if (uvd != NULL) {
-		/* Here uvd is a fully allocated uvd_t object */
-		uvd->flags = flags;
-		uvd->debug = debug;
-		uvd->dev = dev;
-		uvd->iface = ifnum;
-		uvd->ifaceAltInactive = inactInterface;
-		uvd->ifaceAltActive = actInterface;
-		uvd->video_endp = video_ep;
-		uvd->iso_packet_len = maxPS;
-		uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
-		uvd->defaultPalette = VIDEO_PALETTE_RGB24;
-		uvd->canvas = VIDEOSIZE(640, 480);	/* FIXME */
-		uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/
-
-		/* Initialize ibmcam-specific data */
-		assert(ULTRACAM_T(uvd) != NULL);
-		ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */
-		ULTRACAM_T(uvd)->initialized = 0;
-
-		ultracam_configure_video(uvd);
-
-		i = usbvideo_RegisterVideoDevice(uvd);
-		if (i != 0) {
-			err("usbvideo_RegisterVideoDevice() failed.");
-			uvd = NULL;
-		}
-	}
-	MOD_DEC_USE_COUNT;
-	return uvd;
-}
-
-/*
- * ultracam_init()
- *
- * This code is run to initialize the driver.
- */
-static int __init ultracam_init(void)
-{
-	usbvideo_cb_t cbTbl;
-	memset(&cbTbl, 0, sizeof(cbTbl));
-	cbTbl.probe = ultracam_probe;
-	cbTbl.setupOnOpen = ultracam_setup_on_open;
-	cbTbl.videoStart = ultracam_video_start;
-	cbTbl.videoStop = ultracam_video_stop;
-	cbTbl.processData = ultracam_ProcessIsocData;
-	cbTbl.postProcess = usbvideo_DeinterlaceFrame;
-	cbTbl.adjustPicture = ultracam_adjust_picture;
-	cbTbl.getFPS = ultracam_calculate_fps;
-	return usbvideo_register(
-		&cams,
-		MAX_CAMERAS,
-		sizeof(ultracam_t),
-		"ultracam",
-		&cbTbl,
-		THIS_MODULE);
-}
-
-static void __exit ultracam_cleanup(void)
-{
-	usbvideo_Deregister(&cams);
-}
-
-#if defined(usb_device_id_ver)
-
-static __devinitdata struct usb_device_id id_table[] = {
-	{ USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
-	{ }  /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-
-#endif /* defined(usb_device_id_ver) */
-MODULE_LICENSE("GPL");
-
-module_init(ultracam_init);
-module_exit(ultracam_cleanup);
diff -Nru a/drivers/usb/usb-debug.c b/drivers/usb/usb-debug.c
--- a/drivers/usb/usb-debug.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,203 +0,0 @@
-/*
- * debug.c - USB debug helper routines.
- *
- * I just want these out of the way where they aren't in your
- * face, but so that you can still use them..
- */
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)
-{
-	usb_show_endpoint_descriptor(endpoint);
-}
-
-static void usb_show_interface(struct usb_interface_descriptor *altsetting)
-{
-	int i;
-
-	usb_show_interface_descriptor(altsetting);
-
-	for (i = 0; i < altsetting->bNumEndpoints; i++)
-		usb_show_endpoint(altsetting->endpoint + i);
-}
-
-static void usb_show_config(struct usb_config_descriptor *config)
-{
-	int i, j;
-	struct usb_interface *ifp;
-
-	usb_show_config_descriptor(config);
-	for (i = 0; i < config->bNumInterfaces; i++) {
-		ifp = config->interface + i;
-
-		if (!ifp)
-			break;
-
-		printk("\n  Interface: %d\n", i);
-		for (j = 0; j < ifp->num_altsetting; j++)
-			usb_show_interface(ifp->altsetting + j);
-	}
-}
-
-void usb_show_device(struct usb_device *dev)
-{
-	int i;
-
-	usb_show_device_descriptor(&dev->descriptor);
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
-		usb_show_config(dev->config + i);
-}
-
-/*
- * Parse and show the different USB descriptors.
- */
-void usb_show_device_descriptor(struct usb_device_descriptor *desc)
-{
-	if (!desc)
-	{
-		printk("Invalid USB device descriptor (NULL POINTER)\n");
-		return;
-	}
-	printk("  Length              = %2d%s\n", desc->bLength,
-		desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
-	printk("  DescriptorType      = %02x\n", desc->bDescriptorType);
-
-	printk("  USB version         = %x.%02x\n",
-		desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
-	printk("  Vendor:Product      = %04x:%04x\n",
-		desc->idVendor, desc->idProduct);
-	printk("  MaxPacketSize0      = %d\n", desc->bMaxPacketSize0);
-	printk("  NumConfigurations   = %d\n", desc->bNumConfigurations);
-	printk("  Device version      = %x.%02x\n",
-		desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
-
-	printk("  Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
-		desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
-	switch (desc->bDeviceClass) {
-	case 0:
-		printk("    Per-interface classes\n");
-		break;
-	case USB_CLASS_AUDIO:
-		printk("    Audio device class\n");
-		break;
-	case USB_CLASS_COMM:
-		printk("    Communications class\n");
-		break;
-	case USB_CLASS_HID:
-		printk("    Human Interface Devices class\n");
-		break;
-	case USB_CLASS_PRINTER:
-		printk("    Printer device class\n");
-		break;
-	case USB_CLASS_MASS_STORAGE:
-		printk("    Mass Storage device class\n");
-		break;
-	case USB_CLASS_HUB:
-		printk("    Hub device class\n");
-		break;
-	case USB_CLASS_VENDOR_SPEC:
-		printk("    Vendor class\n");
-		break;
-	default:
-		printk("    Unknown class\n");
-	}
-}
-
-void usb_show_config_descriptor(struct usb_config_descriptor *desc)
-{
-	printk("Configuration:\n");
-	printk("  bLength             = %4d%s\n", desc->bLength,
-		desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
-	printk("  bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("  wTotalLength        = %04x\n", desc->wTotalLength);
-	printk("  bNumInterfaces      =   %02x\n", desc->bNumInterfaces);
-	printk("  bConfigurationValue =   %02x\n", desc->bConfigurationValue);
-	printk("  iConfiguration      =   %02x\n", desc->iConfiguration);
-	printk("  bmAttributes        =   %02x\n", desc->bmAttributes);
-	printk("  MaxPower            = %4dmA\n", desc->MaxPower * 2);
-}
-
-void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
-{
-	printk("  Alternate Setting: %2d\n", desc->bAlternateSetting);
-	printk("    bLength             = %4d%s\n", desc->bLength,
-		desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
-	printk("    bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("    bInterfaceNumber    =   %02x\n", desc->bInterfaceNumber);
-	printk("    bAlternateSetting   =   %02x\n", desc->bAlternateSetting);
-	printk("    bNumEndpoints       =   %02x\n", desc->bNumEndpoints);
-	printk("    bInterface Class:SubClass:Protocol =   %02x:%02x:%02x\n",
-		desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol);
-	printk("    iInterface          =   %02x\n", desc->iInterface);
-}
-
-void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
-{
-	char *LengthCommentString = (desc->bLength ==
-		USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
-		USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
-	char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
-
-	printk("    Endpoint:\n");
-	printk("      bLength             = %4d%s\n",
-		desc->bLength, LengthCommentString);
-	printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("      bEndpointAddress    =   %02x (%s)\n", desc->bEndpointAddress,
-		(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-			USB_ENDPOINT_XFER_CONTROL ? "i/o" :
-		(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out");
-	printk("      bmAttributes        =   %02x (%s)\n", desc->bmAttributes,
-		EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]);
-	printk("      wMaxPacketSize      = %04x\n", desc->wMaxPacketSize);
-	printk("      bInterval           =   %02x\n", desc->bInterval);
-
-	/* Audio extensions to the endpoint descriptor */
-	if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
-		printk("      bRefresh            =   %02x\n", desc->bRefresh);
-		printk("      bSynchAddress       =   %02x\n", desc->bSynchAddress);
-	}
-}
-
-void usb_show_string(struct usb_device *dev, char *id, int index)
-{
-	char *buf;
-
-	if (!index)
-		return;
-	if (!(buf = kmalloc(256, GFP_KERNEL)))
-		return;
-	if (usb_string(dev, index, buf, 256) > 0)
-		printk(KERN_INFO "%s: %s\n", id, buf);
-	kfree(buf);
-}
-
-void usb_dump_urb (struct urb *urb)
-{
-	printk ("urb                   :%p\n", urb);
-	printk ("next                  :%p\n", urb->next);
-	printk ("dev                   :%p\n", urb->dev);
-	printk ("pipe                  :%08X\n", urb->pipe);
-	printk ("status                :%d\n", urb->status);
-	printk ("transfer_flags        :%08X\n", urb->transfer_flags);
-	printk ("transfer_buffer       :%p\n", urb->transfer_buffer);
-	printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
-	printk ("actual_length         :%d\n", urb->actual_length);
-	printk ("setup_packet          :%p\n", urb->setup_packet);
-	printk ("start_frame           :%d\n", urb->start_frame);
-	printk ("number_of_packets     :%d\n", urb->number_of_packets);
-	printk ("interval              :%d\n", urb->interval);
-	printk ("error_count           :%d\n", urb->error_count);
-	printk ("context               :%p\n", urb->context);
-	printk ("complete              :%p\n", urb->complete);
-}
-
diff -Nru a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c
--- a/drivers/usb/usb-ohci.c	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2905 +0,0 @@
-/*
- * URB OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * [ Initialisation is based on Linus'  ]
- * [ uhci code and gregs ohci fragments ]
- * [ (C) Copyright 1999 Linus Torvalds  ]
- * [ (C) Copyright 1999 Gregory P. Smith]
- * 
- * 
- * History:
- * 
- * 2001/09/19 USB_ZERO_PACKET support (Jean Tourrilhes)
- * 2001/07/17 power management and pmac cleanup (Benjamin Herrenschmidt)
- * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
- 	pci_map_single (db)
- * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
- * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
- *
- * 2000/09/26 fixed races in removing the private portion of the urb
- * 2000/09/07 disable bulk and control lists when unlinking the last
- *	endpoint descriptor in order to avoid unrecoverable errors on
- *	the Lucent chips. (rwc@sgi)
- * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
- *	urb unlink probs, indentation fixes
- * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
- *	device unplugs.
- * 2000/06/28 use PCI hotplug framework, for better power management
- *	and for Cardbus support (David Brownell)
- * 2000/earlier:  fixes for NEC/Lucent chips; suspend/resume handling
- *	when the controller loses power; handle UE; cleanup; ...
- *
- * v5.2 1999/12/07 URB 3rd preview, 
- * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
- * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume 
- * 	i386: HUB, Keyboard, Mouse, Printer 
- *
- * v4.3 1999/10/27 multiple HCs, bulk_request
- * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
- * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
- * v4.0 1999/08/18 
- * v3.0 1999/06/25 
- * v2.1 1999/05/09  code clean up
- * v2.0 1999/05/04 
- * v1.0 1999/04/27 initial release
- */
- 
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>  /* for in_interrupt() */
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-
-#define OHCI_USE_NPS		// force NoPowerSwitching mode
-// #define OHCI_VERBOSE_DEBUG	/* not always helpful */
-
-#include "hcd.h"
-#include "usb-ohci.h"
-
-
-#ifdef CONFIG_PMAC_PBOOK
-#include <asm/feature.h>
-#include <asm/pci-bridge.h>
-#ifndef CONFIG_PM
-#define CONFIG_PM
-#endif
-#endif
-
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v5.3"
-#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
-#define DRIVER_DESC "USB OHCI Host Controller Driver"
-
-/* For initializing controller (mask in an HCFS mode too) */
-#define	OHCI_CONTROL_INIT \
-	(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
-
-#define OHCI_UNLINK_TIMEOUT	(HZ / 10)
-
-static LIST_HEAD (ohci_hcd_list);
-static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
-
-
-/*-------------------------------------------------------------------------*/
-
-/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
- * The erratum (#4) description is incorrect.  AMD's workaround waits
- * till some bits (mostly reserved) are clear; ok for all revs.
- */
-#define read_roothub(hc, register, mask) ({ \
-	u32 temp = readl (&hc->regs->roothub.register); \
-	if (hc->flags & OHCI_QUIRK_AMD756) \
-		while (temp & mask) \
-			temp = readl (&hc->regs->roothub.register); \
-	temp; })
-
-static u32 roothub_a (struct ohci *hc)
-	{ return read_roothub (hc, a, 0xfc0fe000); }
-static inline u32 roothub_b (struct ohci *hc)
-	{ return readl (&hc->regs->roothub.b); }
-static inline u32 roothub_status (struct ohci *hc)
-	{ return readl (&hc->regs->roothub.status); }
-static u32 roothub_portstatus (struct ohci *hc, int i)
-	{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
-
-
-/*-------------------------------------------------------------------------*
- * URB support functions 
- *-------------------------------------------------------------------------*/ 
- 
-/* free HCD-private data associated with this URB */
-
-static void urb_free_priv (struct ohci *hc, urb_priv_t * urb_priv)
-{
-	int		i;
-	int		last = urb_priv->length - 1;
-	int		len;
-	int		dir;
-	struct td	*td;
-
-	if (last >= 0) {
-
-		/* ISOC, BULK, INTR data buffer starts at td 0 
-		 * CTRL setup starts at td 0 */
-		td = urb_priv->td [0];
-
-		len = td->urb->transfer_buffer_length,
-		dir = usb_pipeout (td->urb->pipe)
-					? PCI_DMA_TODEVICE
-					: PCI_DMA_FROMDEVICE;
-
-		/* unmap CTRL URB setup */
-		if (usb_pipecontrol (td->urb->pipe)) {
-			pci_unmap_single (hc->ohci_dev, 
-					td->data_dma, 8, PCI_DMA_TODEVICE);
-			
-			/* CTRL data buffer starts at td 1 if len > 0 */
-			if (len && last > 0)
-				td = urb_priv->td [1]; 		
-		} 
-
-		/* unmap data buffer */
-		if (len && td->data_dma)
-			pci_unmap_single (hc->ohci_dev, td->data_dma, len, dir);
-		
-		for (i = 0; i <= last; i++) {
-			td = urb_priv->td [i];
-			if (td)
-				td_free (hc, td);
-		}
-	}
-
-	kfree (urb_priv);
-}
- 
-static void urb_rm_priv_locked (struct urb * urb) 
-{
-	urb_priv_t * urb_priv = urb->hcpriv;
-	
-	if (urb_priv) {
-		urb->hcpriv = NULL;
-
-#ifdef	DO_TIMEOUTS
-		if (urb->timeout) {
-			list_del (&urb->urb_list);
-			urb->timeout -= jiffies;
-		}
-#endif
-
-		/* Release int/iso bandwidth */
-		if (urb->bandwidth) {
-			switch (usb_pipetype(urb->pipe)) {
-			case PIPE_INTERRUPT:
-				usb_release_bandwidth (urb->dev, urb, 0);
-				break;
-			case PIPE_ISOCHRONOUS:
-				usb_release_bandwidth (urb->dev, urb, 1);
-				break;
-			default:
-				break;
-			}
-		}
-
-		urb_free_priv ((struct ohci *)urb->dev->bus->hcpriv, urb_priv);
-		usb_dec_dev_use (urb->dev);
-		urb->dev = NULL;
-		usb_put_urb (urb);
-	}
-}
-
-static void urb_rm_priv (struct urb * urb)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave (&usb_ed_lock, flags);
-	urb_rm_priv_locked (urb);
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
- 
-#ifdef DEBUG
-static int sohci_get_current_frame_number (struct usb_device * dev);
-
-/* debug| print the main components of an URB     
- * small: 0) header + data packets 1) just header */
- 
-static void urb_print (struct urb * urb, char * str, int small)
-{
-	unsigned int pipe= urb->pipe;
-	
-	if (!urb->dev || !urb->dev->bus) {
-		dbg("%s URB: no dev", str);
-		return;
-	}
-	
-#ifndef	OHCI_VERBOSE_DEBUG
-	if (urb->status != 0)
-#endif
-	dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", 
-			str,
-		 	sohci_get_current_frame_number (urb->dev), 
-		 	usb_pipedevice (pipe),
-		 	usb_pipeendpoint (pipe), 
-		 	usb_pipeout (pipe)? 'O': 'I',
-		 	usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
-		 		(usb_pipecontrol (pipe)? "CTRL": "BULK"),
-		 	urb->transfer_flags, 
-		 	urb->actual_length, 
-		 	urb->transfer_buffer_length,
-		 	urb->status, urb->status);
-#ifdef	OHCI_VERBOSE_DEBUG
-	if (!small) {
-		int i, len;
-
-		if (usb_pipecontrol (pipe)) {
-			printk (KERN_DEBUG __FILE__ ": cmd(8):");
-			for (i = 0; i < 8 ; i++) 
-				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
-			printk ("\n");
-		}
-		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
-			printk (KERN_DEBUG __FILE__ ": data(%d/%d):", 
-				urb->actual_length, 
-				urb->transfer_buffer_length);
-			len = usb_pipeout (pipe)? 
-						urb->transfer_buffer_length: urb->actual_length;
-			for (i = 0; i < 16 && i < len; i++) 
-				printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
-			printk ("%s stat:%d\n", i < len? "...": "", urb->status);
-		}
-	} 
-#endif
-}
-
-/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
-void ep_print_int_eds (ohci_t * ohci, char * str) {
-	int i, j;
-	 __u32 * ed_p;
-	for (i= 0; i < 32; i++) {
-		j = 5;
-		ed_p = &(ohci->hcca->int_table [i]);
-		if (*ed_p == 0)
-		    continue;
-		printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", str, i, i);
-		while (*ed_p != 0 && j--) {
-			ed_t *ed = dma_to_ed (ohci, le32_to_cpup(ed_p));
-			printk (" ed: %4x;", ed->hwINFO);
-			ed_p = &ed->hwNextED;
-		}
-		printk ("\n");
-	}
-}
-
-
-static void ohci_dump_intr_mask (char *label, __u32 mask)
-{
-	dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
-		label,
-		mask,
-		(mask & OHCI_INTR_MIE) ? " MIE" : "",
-		(mask & OHCI_INTR_OC) ? " OC" : "",
-		(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
-		(mask & OHCI_INTR_FNO) ? " FNO" : "",
-		(mask & OHCI_INTR_UE) ? " UE" : "",
-		(mask & OHCI_INTR_RD) ? " RD" : "",
-		(mask & OHCI_INTR_SF) ? " SF" : "",
-		(mask & OHCI_INTR_WDH) ? " WDH" : "",
-		(mask & OHCI_INTR_SO) ? " SO" : ""
-		);
-}
-
-static void maybe_print_eds (char *label, __u32 value)
-{
-	if (value)
-		dbg ("%s %08x", label, value);
-}
-
-static char *hcfs2string (int state)
-{
-	switch (state) {
-		case OHCI_USB_RESET:	return "reset";
-		case OHCI_USB_RESUME:	return "resume";
-		case OHCI_USB_OPER:	return "operational";
-		case OHCI_USB_SUSPEND:	return "suspend";
-	}
-	return "?";
-}
-
-// dump control and status registers
-static void ohci_dump_status (ohci_t *controller)
-{
-	struct ohci_regs	*regs = controller->regs;
-	__u32			temp;
-
-	temp = readl (&regs->revision) & 0xff;
-	if (temp != 0x10)
-		dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
-
-	temp = readl (&regs->control);
-	dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
-		(temp & OHCI_CTRL_RWE) ? " RWE" : "",
-		(temp & OHCI_CTRL_RWC) ? " RWC" : "",
-		(temp & OHCI_CTRL_IR) ? " IR" : "",
-		hcfs2string (temp & OHCI_CTRL_HCFS),
-		(temp & OHCI_CTRL_BLE) ? " BLE" : "",
-		(temp & OHCI_CTRL_CLE) ? " CLE" : "",
-		(temp & OHCI_CTRL_IE) ? " IE" : "",
-		(temp & OHCI_CTRL_PLE) ? " PLE" : "",
-		temp & OHCI_CTRL_CBSR
-		);
-
-	temp = readl (&regs->cmdstatus);
-	dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
-		(temp & OHCI_SOC) >> 16,
-		(temp & OHCI_OCR) ? " OCR" : "",
-		(temp & OHCI_BLF) ? " BLF" : "",
-		(temp & OHCI_CLF) ? " CLF" : "",
-		(temp & OHCI_HCR) ? " HCR" : ""
-		);
-
-	ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
-	ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
-	// intrdisable always same as intrenable
-	// ohci_dump_intr_mask ("intrdisable", readl (&regs->intrdisable));
-
-	maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
-
-	maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
-	maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
-
-	maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
-	maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
-
-	maybe_print_eds ("donehead", readl (&regs->donehead));
-}
-
-static void ohci_dump_roothub (ohci_t *controller, int verbose)
-{
-	__u32			temp, ndp, i;
-
-	temp = roothub_a (controller);
-	ndp = (temp & RH_A_NDP);
-
-	if (verbose) {
-		dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
-			((temp & RH_A_POTPGT) >> 24) & 0xff,
-			(temp & RH_A_NOCP) ? " NOCP" : "",
-			(temp & RH_A_OCPM) ? " OCPM" : "",
-			(temp & RH_A_DT) ? " DT" : "",
-			(temp & RH_A_NPS) ? " NPS" : "",
-			(temp & RH_A_PSM) ? " PSM" : "",
-			ndp
-			);
-		temp = roothub_b (controller);
-		dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
-			temp,
-			(temp & RH_B_PPCM) >> 16,
-			(temp & RH_B_DR)
-			);
-		temp = roothub_status (controller);
-		dbg ("roothub.status: %08x%s%s%s%s%s%s",
-			temp,
-			(temp & RH_HS_CRWE) ? " CRWE" : "",
-			(temp & RH_HS_OCIC) ? " OCIC" : "",
-			(temp & RH_HS_LPSC) ? " LPSC" : "",
-			(temp & RH_HS_DRWE) ? " DRWE" : "",
-			(temp & RH_HS_OCI) ? " OCI" : "",
-			(temp & RH_HS_LPS) ? " LPS" : ""
-			);
-	}
-	
-	for (i = 0; i < ndp; i++) {
-		temp = roothub_portstatus (controller, i);
-		dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
-			i,
-			temp,
-			(temp & RH_PS_PRSC) ? " PRSC" : "",
-			(temp & RH_PS_OCIC) ? " OCIC" : "",
-			(temp & RH_PS_PSSC) ? " PSSC" : "",
-			(temp & RH_PS_PESC) ? " PESC" : "",
-			(temp & RH_PS_CSC) ? " CSC" : "",
-
-			(temp & RH_PS_LSDA) ? " LSDA" : "",
-			(temp & RH_PS_PPS) ? " PPS" : "",
-			(temp & RH_PS_PRS) ? " PRS" : "",
-			(temp & RH_PS_POCI) ? " POCI" : "",
-			(temp & RH_PS_PSS) ? " PSS" : "",
-
-			(temp & RH_PS_PES) ? " PES" : "",
-			(temp & RH_PS_CCS) ? " CCS" : ""
-			);
-	}
-}
-
-static void ohci_dump (ohci_t *controller, int verbose)
-{
-	dbg ("OHCI controller usb-%s state", controller->ohci_dev->slot_name);
-
-	// dumps some of the state we know about
-	ohci_dump_status (controller);
-	if (verbose)
-		ep_print_int_eds (controller, "hcca");
-	dbg ("hcca frame #%04x", controller->hcca->frame_no);
-	ohci_dump_roothub (controller, 1);
-}
-
-
-#endif
-
-/*-------------------------------------------------------------------------*
- * Interface functions (URB)
- *-------------------------------------------------------------------------*/
-
-/* return a request to the completion handler */
- 
-static int sohci_return_urb (struct ohci *hc, struct urb * urb)
-{
-	urb_priv_t * urb_priv = urb->hcpriv;
-	struct urb * urbt;
-	unsigned long flags;
-	int i;
-	
-	if (!urb_priv)
-		return -1; /* urb already unlinked */
-
-	/* just to be sure */
-	if (!urb->complete) {
-		urb_rm_priv (urb);
-		return -1;
-	}
-	
-#ifdef DEBUG
-	urb_print (urb, "RET", usb_pipeout (urb->pipe));
-#endif
-
-	switch (usb_pipetype (urb->pipe)) {
-  		case PIPE_INTERRUPT:
-			pci_unmap_single (hc->ohci_dev,
-				urb_priv->td [0]->data_dma,
-				urb->transfer_buffer_length,
-				usb_pipeout (urb->pipe)
-					? PCI_DMA_TODEVICE
-					: PCI_DMA_FROMDEVICE);
-			urb->complete (urb);
-
-			/* implicitly requeued */
-  			urb->actual_length = 0;
-  			urb->status = -EINPROGRESS;
-  			if (urb_priv->state != URB_DEL)
-  				td_submit_urb (urb);
-  			break;
-  			
-		case PIPE_ISOCHRONOUS:
-			for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next);
-			if (urbt) { /* send the reply and requeue URB */	
-				pci_unmap_single (hc->ohci_dev,
-					urb_priv->td [0]->data_dma,
-					urb->transfer_buffer_length,
-					usb_pipeout (urb->pipe)
-						? PCI_DMA_TODEVICE
-						: PCI_DMA_FROMDEVICE);
-				urb->complete (urb);
-				spin_lock_irqsave (&usb_ed_lock, flags);
-				urb->actual_length = 0;
-  				urb->status = -EINPROGRESS;
-  				urb->start_frame = urb_priv->ed->last_iso + 1;
-  				if (urb_priv->state != URB_DEL) {
-  					for (i = 0; i < urb->number_of_packets; i++) {
-  						urb->iso_frame_desc[i].actual_length = 0;
-  						urb->iso_frame_desc[i].status = -EXDEV;
-  					}
-  					td_submit_urb (urb);
-  				}
-  				spin_unlock_irqrestore (&usb_ed_lock, flags);
-  				
-  			} else { /* unlink URB, call complete */
-				urb_rm_priv (urb);
-				urb->complete (urb); 	
-			}		
-			break;
-  				
-		case PIPE_BULK:
-		case PIPE_CONTROL: /* unlink URB, call complete */
-			urb_rm_priv (urb);
-			urb->complete (urb);	
-			break;
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* get a transfer request */
- 
-static int sohci_submit_urb (struct urb * urb, int mem_flags)
-{
-	ohci_t * ohci;
-	ed_t * ed;
-	urb_priv_t * urb_priv;
-	unsigned int pipe = urb->pipe;
-	int maxps = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
-	int i, size = 0;
-	unsigned long flags;
-	int bustime = 0;
-	
-	if (!urb->dev || !urb->dev->bus)
-		return -ENODEV;
-	
-	if (urb->hcpriv)			/* urb already in use */
-		return -EINVAL;
-
-//	if(usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) 
-//		return -EPIPE;
-	
-	/* increment the reference count of the urb, as we now also control it */
-	urb = usb_get_urb (urb);
-
-	usb_inc_dev_use (urb->dev);
-	ohci = (ohci_t *) urb->dev->bus->hcpriv;
-	
-#ifdef DEBUG
-	urb_print (urb, "SUB", usb_pipein (pipe));
-#endif
-	
-	/* handle a request to the virtual root hub */
-	if (usb_pipedevice (pipe) == ohci->rh.devnum) 
-		return rh_submit_urb (urb);
-	
-	/* when controller's hung, permit only roothub cleanup attempts
-	 * such as powering down ports */
-	if (ohci->disabled) {
-		usb_dec_dev_use (urb->dev);	
-		usb_put_urb (urb);
-		return -ESHUTDOWN;
-	}
-
-	/* every endpoint has a ed, locate and fill it */
-	if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) {
-		usb_dec_dev_use (urb->dev);	
-		usb_put_urb (urb);
-		return -ENOMEM;
-	}
-
-	/* for the private part of the URB we need the number of TDs (size) */
-	switch (usb_pipetype (pipe)) {
-		case PIPE_BULK:	/* one TD for every 4096 Byte */
-			size = (urb->transfer_buffer_length - 1) / 4096 + 1;
-
-			/* If the transfer size is multiple of the pipe mtu,
-			 * we may need an extra TD to create a empty frame
-			 * Jean II */
-			if ((urb->transfer_flags & USB_ZERO_PACKET) &&
-			    usb_pipeout (pipe) &&
-			    (urb->transfer_buffer_length != 0) && 
-			    ((urb->transfer_buffer_length % maxps) == 0))
-				size++;
-			break;
-		case PIPE_ISOCHRONOUS: /* number of packets from URB */
-			size = urb->number_of_packets;
-			if (size <= 0) {
-				usb_dec_dev_use (urb->dev);	
-				usb_put_urb (urb);
-				return -EINVAL;
-			}
-			for (i = 0; i < urb->number_of_packets; i++) {
-  				urb->iso_frame_desc[i].actual_length = 0;
-  				urb->iso_frame_desc[i].status = -EXDEV;
-  			}
-			break;
-		case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
-			size = (urb->transfer_buffer_length == 0)? 2: 
-						(urb->transfer_buffer_length - 1) / 4096 + 3;
-			break;
-		case PIPE_INTERRUPT: /* one TD */
-			size = 1;
-			break;
-	}
-
-	/* allocate the private part of the URB */
-	urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), mem_flags);
-	if (!urb_priv) {
-		usb_dec_dev_use (urb->dev);	
-		usb_put_urb (urb);
-		return -ENOMEM;
-	}
-	memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *));
-	
-	/* fill the private part of the URB */
-	urb_priv->length = size;
-	urb_priv->ed = ed;	
-
-	/* allocate the TDs (updating hash chains) */
-	spin_lock_irqsave (&usb_ed_lock, flags);
-	for (i = 0; i < size; i++) { 
-		urb_priv->td[i] = td_alloc (ohci, SLAB_ATOMIC);
-		if (!urb_priv->td[i]) {
-			urb_priv->length = i;
-			urb_free_priv (ohci, urb_priv);
-			spin_unlock_irqrestore (&usb_ed_lock, flags);
-			usb_dec_dev_use (urb->dev);	
-			usb_put_urb (urb);
-			return -ENOMEM;
-		}
-	}	
-
-	if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
-		urb_free_priv (ohci, urb_priv);
-		spin_unlock_irqrestore (&usb_ed_lock, flags);
-		usb_dec_dev_use (urb->dev);	
-		usb_put_urb (urb);
-		return -EINVAL;
-	}
-	
-	/* allocate and claim bandwidth if needed; ISO
-	 * needs start frame index if it was't provided.
-	 */
-	switch (usb_pipetype (pipe)) {
-		case PIPE_ISOCHRONOUS:
-			if (urb->transfer_flags & USB_ISO_ASAP) { 
-				urb->start_frame = ((ed->state == ED_OPER)
-					? (ed->last_iso + 1)
-					: (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff;
-			}	
-			/* FALLTHROUGH */
-		case PIPE_INTERRUPT:
-			if (urb->bandwidth == 0) {
-				bustime = usb_check_bandwidth (urb->dev, urb);
-			}
-			if (bustime < 0) {
-				urb_free_priv (ohci, urb_priv);
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
-				usb_dec_dev_use (urb->dev);	
-				usb_put_urb (urb);
-				return bustime;
-			}
-			usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe));
-#ifdef	DO_TIMEOUTS
-			urb->timeout = 0;
-#endif
-	}
-
-	urb->actual_length = 0;
-	urb->hcpriv = urb_priv;
-	urb->status = -EINPROGRESS;
-
-	/* link the ed into a chain if is not already */
-	if (ed->state != ED_OPER)
-		ep_link (ohci, ed);
-
-	/* fill the TDs and link it to the ed */
-	td_submit_urb (urb);
-
-#ifdef	DO_TIMEOUTS
-	/* maybe add to ordered list of timeouts */
-	if (urb->timeout) {
-		struct list_head	*entry;
-
-		// FIXME:  usb-uhci uses relative timeouts (like this),
-		// while uhci uses absolute ones (probably better).
-		// Pick one solution and change the affected drivers.
-		urb->timeout += jiffies;
-
-		list_for_each (entry, &ohci->timeout_list) {
-			struct urb	*next_urb;
-
-			next_urb = list_entry (entry, struct urb, urb_list);
-			if (time_after_eq (urb->timeout, next_urb->timeout))
-				break;
-		}
-		list_add (&urb->urb_list, entry);
-
-		/* drive timeouts by SF (messy, but works) */
-		writel (OHCI_INTR_SF, &ohci->regs->intrenable);	
-	}
-#endif
-
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
-
-	return 0;	
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* deactivate all TDs and remove the private part of the URB */
-/* interrupt callers must use async unlink mode */
-
-static int sohci_unlink_urb (struct urb * urb)
-{
-	unsigned long flags;
-	ohci_t * ohci;
-	
-	if (!urb) /* just to be sure */ 
-		return -EINVAL;
-		
-	if (!urb->dev || !urb->dev->bus)
-		return -ENODEV;
-
-	ohci = (ohci_t *) urb->dev->bus->hcpriv; 
-
-#ifdef DEBUG
-	urb_print (urb, "UNLINK", 1);
-#endif		  
-
-	/* handle a request to the virtual root hub */
-	if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
-		return rh_unlink_urb (urb);
-
-	if (urb->hcpriv && (urb->status == -EINPROGRESS)) { 
-		if (!ohci->disabled) {
-			urb_priv_t  * urb_priv;
-
-			/* interrupt code may not sleep; it must use
-			 * async status return to unlink pending urbs.
-			 */
-			if (!(urb->transfer_flags & USB_ASYNC_UNLINK)
-					&& in_interrupt ()) {
-				err ("bug in call from %p; use async!",
-					__builtin_return_address(0));
-				return -EWOULDBLOCK;
-			}
-
-			/* flag the urb and its TDs for deletion in some
-			 * upcoming SF interrupt delete list processing
-			 */
-			spin_lock_irqsave (&usb_ed_lock, flags);
-			urb_priv = urb->hcpriv;
-
-			if (!urb_priv || (urb_priv->state == URB_DEL)) {
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
-				return 0;
-			}
-				
-			urb_priv->state = URB_DEL; 
-			ep_rm_ed (urb->dev, urb_priv->ed);
-			urb_priv->ed->state |= ED_URB_DEL;
-
-			if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
-				DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
-				DECLARE_WAITQUEUE (wait, current);
-				int timeout = OHCI_UNLINK_TIMEOUT;
-
-				add_wait_queue (&unlink_wakeup, &wait);
-				urb_priv->wait = &unlink_wakeup;
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
-
-				/* wait until all TDs are deleted */
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				while (timeout && (urb->status == -EINPROGRESS))
-					timeout = schedule_timeout (timeout);
-				set_current_state(TASK_RUNNING);
-				remove_wait_queue (&unlink_wakeup, &wait); 
-				if (urb->status == -EINPROGRESS) {
-					err ("unlink URB timeout");
-					return -ETIMEDOUT;
-				}
-			} else {
-				/* usb_dec_dev_use done in dl_del_list() */
-				urb->status = -EINPROGRESS;
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
-			}
-		} else {
-			urb_rm_priv (urb);
-			if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-				urb->status = -ECONNRESET;
-				if (urb->complete)
-					urb->complete (urb); 
-			} else 
-				urb->status = -ENOENT;
-		}	
-	}	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* allocate private data space for a usb device */
-
-static int sohci_alloc_dev (struct usb_device *usb_dev)
-{
-	struct ohci_device * dev;
-
-	dev = dev_alloc ((struct ohci *) usb_dev->bus->hcpriv, ALLOC_FLAGS);
-	if (!dev)
-		return -ENOMEM;
-
-	usb_dev->hcpriv = dev;
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* may be called from interrupt context */
-/* frees private data space of usb device */
-  
-static int sohci_free_dev (struct usb_device * usb_dev)
-{
-	unsigned long flags;
-	int i, cnt = 0;
-	ed_t * ed;
-	struct ohci_device * dev = usb_to_ohci (usb_dev);
-	ohci_t * ohci = usb_dev->bus->hcpriv;
-	
-	if (!dev)
-		return 0;
-	
-	if (usb_dev->devnum >= 0) {
-	
-		/* driver disconnects should have unlinked all urbs
-		 * (freeing all the TDs, unlinking EDs) but we need
-		 * to defend against bugs that prevent that.
-		 */
-		spin_lock_irqsave (&usb_ed_lock, flags);	
-		for(i = 0; i < NUM_EDS; i++) {
-  			ed = &(dev->ed[i]);
-  			if (ed->state != ED_NEW) {
-  				if (ed->state == ED_OPER) {
-					/* driver on that interface didn't unlink an urb */
-					dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
-						ohci->ohci_dev->slot_name, usb_dev->devnum, i);
-					ep_unlink (ohci, ed);
-				}
-  				ep_rm_ed (usb_dev, ed);
-  				ed->state = ED_DEL;
-  				cnt++;
-  			}
-  		}
-  		spin_unlock_irqrestore (&usb_ed_lock, flags);
-  		
-		/* if the controller is running, tds for those unlinked
-		 * urbs get freed by dl_del_list at the next SF interrupt
-		 */
-		if (cnt > 0) {
-
-			if (ohci->disabled) {
-				/* FIXME: Something like this should kick in,
-				 * though it's currently an exotic case ...
-				 * the controller won't ever be touching
-				 * these lists again!!
-				dl_del_list (ohci,
-					le16_to_cpu (ohci->hcca->frame_no) & 1);
-				 */
-				warn ("TD leak, %d", cnt);
-
-			} else if (!in_interrupt ()) {
-				DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); 
-				DECLARE_WAITQUEUE (wait, current);
-				int timeout = OHCI_UNLINK_TIMEOUT;
-
-				/* SF interrupt handler calls dl_del_list */
-				add_wait_queue (&freedev_wakeup, &wait);
-				dev->wait = &freedev_wakeup;
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				while (timeout && dev->ed_cnt)
-					timeout = schedule_timeout (timeout);
-				set_current_state(TASK_RUNNING);
-				remove_wait_queue (&freedev_wakeup, &wait);
-				if (dev->ed_cnt) {
-					err ("free device %d timeout", usb_dev->devnum);
-					return -ETIMEDOUT;
-				}
-			} else {
-				/* likely some interface's driver has a refcount bug */
-				err ("bus %s devnum %d deletion in interrupt",
-					ohci->ohci_dev->slot_name, usb_dev->devnum);
-				BUG ();
-			}
-		}
-	}
-
-	/* free device, and associated EDs */
-	dev_free (ohci, dev);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* tell us the current USB frame number */
-
-static int sohci_get_current_frame_number (struct usb_device *usb_dev) 
-{
-	ohci_t * ohci = usb_dev->bus->hcpriv;
-	
-	return le16_to_cpu (ohci->hcca->frame_no);
-}
-
-/*-------------------------------------------------------------------------*/
-
-struct usb_operations sohci_device_operations = {
-	allocate:		sohci_alloc_dev,
-	deallocate:		sohci_free_dev,
-	get_frame_number:	sohci_get_current_frame_number,
-	submit_urb:		sohci_submit_urb,
-	unlink_urb:		sohci_unlink_urb,
-};
-
-/*-------------------------------------------------------------------------*
- * ED handling functions
- *-------------------------------------------------------------------------*/  
-		
-/* search for the right branch to insert an interrupt ed into the int tree 
- * do some load ballancing;
- * returns the branch and 
- * sets the interval to interval = 2^integer (ld (interval)) */
-
-static int ep_int_ballance (ohci_t * ohci, int interval, int load)
-{
-	int i, branch = 0;
-   
-	/* search for the least loaded interrupt endpoint branch of all 32 branches */
-	for (i = 0; i < 32; i++) 
-		if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; 
-  
-	branch = branch % interval;
-	for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load;
-
-	return branch;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*  2^int( ld (inter)) */
-
-static int ep_2_n_interval (int inter)
-{	
-	int i;
-	for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); 
-	return 1 << i;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* the int tree is a binary tree 
- * in order to process it sequentially the indexes of the branches have to be mapped 
- * the mapping reverses the bits of a word of num_bits length */
- 
-static int ep_rev (int num_bits, int word)
-{
-	int i, wout = 0;
-
-	for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1));
-	return wout;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* link an ed into one of the HC chains */
-
-static int ep_link (ohci_t * ohci, ed_t * edi)
-{	 
-	int int_branch;
-	int i;
-	int inter;
-	int interval;
-	int load;
-	__u32 * ed_p;
-	volatile ed_t * ed = edi;
-	
-	ed->state = ED_OPER;
-	
-	switch (ed->type) {
-	case PIPE_CONTROL:
-		ed->hwNextED = 0;
-		if (ohci->ed_controltail == NULL) {
-			writel (ed->dma, &ohci->regs->ed_controlhead);
-		} else {
-			ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma);
-		}
-		ed->ed_prev = ohci->ed_controltail;
-		if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
-			!ohci->ed_rm_list[1] && !ohci->sleeping) {
-			ohci->hc_control |= OHCI_CTRL_CLE;
-			writel (ohci->hc_control, &ohci->regs->control);
-		}
-		ohci->ed_controltail = edi;	  
-		break;
-		
-	case PIPE_BULK:
-		ed->hwNextED = 0;
-		if (ohci->ed_bulktail == NULL) {
-			writel (ed->dma, &ohci->regs->ed_bulkhead);
-		} else {
-			ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma);
-		}
-		ed->ed_prev = ohci->ed_bulktail;
-		if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
-			!ohci->ed_rm_list[1] && !ohci->sleeping) {
-			ohci->hc_control |= OHCI_CTRL_BLE;
-			writel (ohci->hc_control, &ohci->regs->control);
-		}
-		ohci->ed_bulktail = edi;	  
-		break;
-		
-	case PIPE_INTERRUPT:
-		load = ed->int_load;
-		interval = ep_2_n_interval (ed->int_period);
-		ed->int_interval = interval;
-		int_branch = ep_int_ballance (ohci, interval, load);
-		ed->int_branch = int_branch;
-		
-		for (i = 0; i < ep_rev (6, interval); i += inter) {
-			inter = 1;
-			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]); 
-				(*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); 
-				ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
-					inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-			ed->hwNextED = *ed_p; 
-			*ed_p = cpu_to_le32 (ed->dma);
-		}
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "LINK_INT");
-#endif
-		break;
-		
-	case PIPE_ISOCHRONOUS:
-		ed->hwNextED = 0;
-		ed->int_interval = 1;
-		if (ohci->ed_isotail != NULL) {
-			ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma);
-			ed->ed_prev = ohci->ed_isotail;
-		} else {
-			for ( i = 0; i < 32; i += inter) {
-				inter = 1;
-				for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); 
-					*ed_p != 0; 
-					ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) 
-						inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-				*ed_p = cpu_to_le32 (ed->dma);	
-			}	
-			ed->ed_prev = NULL;
-		}	
-		ohci->ed_isotail = edi;  
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "LINK_ISO");
-#endif
-		break;
-	}	 	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* unlink an ed from one of the HC chains. 
- * just the link to the ed is unlinked.
- * the link from the ed still points to another operational ed or 0
- * so the HC can eventually finish the processing of the unlinked ed */
-
-static int ep_unlink (ohci_t * ohci, ed_t * ed) 
-{
-	int int_branch;
-	int i;
-	int inter;
-	int interval;
-	__u32 * ed_p;
-
-	ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP);
-
-	switch (ed->type) {
-	case PIPE_CONTROL:
-		if (ed->ed_prev == NULL) {
-			if (!ed->hwNextED) {
-				ohci->hc_control &= ~OHCI_CTRL_CLE;
-				writel (ohci->hc_control, &ohci->regs->control);
-			}
-			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead);
-		} else {
-			ed->ed_prev->hwNextED = ed->hwNextED;
-		}
-		if (ohci->ed_controltail == ed) {
-			ohci->ed_controltail = ed->ed_prev;
-		} else {
-			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
-		}
-		break;
-      
-	case PIPE_BULK:
-		if (ed->ed_prev == NULL) {
-			if (!ed->hwNextED) {
-				ohci->hc_control &= ~OHCI_CTRL_BLE;
-				writel (ohci->hc_control, &ohci->regs->control);
-			}
-			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead);
-		} else {
-			ed->ed_prev->hwNextED = ed->hwNextED;
-		}
-		if (ohci->ed_bulktail == ed) {
-			ohci->ed_bulktail = ed->ed_prev;
-		} else {
-			(dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
-		}
-		break;
-      
-	case PIPE_INTERRUPT:
-		int_branch = ed->int_branch;
-		interval = ed->int_interval;
-
-		for (i = 0; i < ep_rev (6, interval); i += inter) {
-			for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i) + int_branch]), inter = 1; 
-				(*ed_p != 0) && (*ed_p != ed->hwNextED); 
-				ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED), 
-				inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval)) {				
-					if((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
-			  			*ed_p = ed->hwNextED;		
-			  			break;
-			  		}
-			  }
-		}
-		for (i = int_branch; i < 32; i += interval)
-		    ohci->ohci_int_load[i] -= ed->int_load;
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "UNLINK_INT");
-#endif
-		break;
-		
-	case PIPE_ISOCHRONOUS:
-		if (ohci->ed_isotail == ed)
-			ohci->ed_isotail = ed->ed_prev;
-		if (ed->hwNextED != 0) 
-		    (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
-				    
-		if (ed->ed_prev != NULL) {
-			ed->ed_prev->hwNextED = ed->hwNextED;
-		} else {
-			for (i = 0; i < 32; i++) {
-				for (ed_p = &(ohci->hcca->int_table[ep_rev (5, i)]); 
-						*ed_p != 0; 
-						ed_p = &((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) {
-					// inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval);
-					if((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) {
-						*ed_p = ed->hwNextED;		
-						break;
-					}
-				}
-			}	
-		}	
-#ifdef DEBUG
-		ep_print_int_eds (ohci, "UNLINK_ISO");
-#endif
-		break;
-	}
-	ed->state = ED_UNLINK;
-	return 0;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
- * but the USB stack is a little bit stateless  so we do it at every transaction
- * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
- * in all other cases the state is left unchanged
- * the ed info fields are setted anyway even though most of them should not change */
- 
-static ed_t * ep_add_ed (
-	struct usb_device * usb_dev,
-	unsigned int pipe,
-	int interval,
-	int load,
-	int mem_flags
-)
-{
-   	ohci_t * ohci = usb_dev->bus->hcpriv;
-	td_t * td;
-	ed_t * ed_ret;
-	volatile ed_t * ed; 
-	unsigned long flags;
- 	
- 	
-	spin_lock_irqsave (&usb_ed_lock, flags);
-
-	ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | 
-			(usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]);
-
-	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
-		/* pending delete request */
-		spin_unlock_irqrestore (&usb_ed_lock, flags);
-		return NULL;
-	}
-	
-	if (ed->state == ED_NEW) {
-		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
-  		/* dummy td; end of td list for ed */
-		td = td_alloc (ohci, SLAB_ATOMIC);
-		/* hash the ed for later reverse mapping */
- 		if (!td || !hash_add_ed (ohci, (ed_t *)ed)) {
-			/* out of memory */
-		        if (td)
-		            td_free(ohci, td);
-			spin_unlock_irqrestore (&usb_ed_lock, flags);
-			return NULL;
-		}
-		ed->hwTailP = cpu_to_le32 (td->td_dma);
-		ed->hwHeadP = ed->hwTailP;	
-		ed->state = ED_UNLINK;
-		ed->type = usb_pipetype (pipe);
-		usb_to_ohci (usb_dev)->ed_cnt++;
-	}
-
-	ohci->dev[usb_pipedevice (pipe)] = usb_dev;
-	
-	ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe)
-			| usb_pipeendpoint (pipe) << 7
-			| (usb_pipeisoc (pipe)? 0x8000: 0)
-			| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) 
-			| (usb_dev->speed == USB_SPEED_LOW) << 13
-			| usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16);
-  
-  	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
-  		ed->int_period = interval;
-  		ed->int_load = load;
-  	}
-  	
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
-	return ed_ret; 
-}
-
-/*-------------------------------------------------------------------------*/
- 
-/* request the removal of an endpoint
- * put the ep on the rm_list and request a stop of the bulk or ctrl list 
- * real removal is done at the next start frame (SF) hardware interrupt */
- 
-static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed)
-{    
-	unsigned int frame;
-	ohci_t * ohci = usb_dev->bus->hcpriv;
-
-	if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL))
-		return;
-	
-	ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP);
-
-	if (!ohci->disabled) {
-		switch (ed->type) {
-			case PIPE_CONTROL: /* stop control list */
-				ohci->hc_control &= ~OHCI_CTRL_CLE;
-				writel (ohci->hc_control, &ohci->regs->control); 
-  				break;
-			case PIPE_BULK: /* stop bulk list */
-				ohci->hc_control &= ~OHCI_CTRL_BLE;
-				writel (ohci->hc_control, &ohci->regs->control); 
-				break;
-		}
-	}
-
-	frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1;
-	ed->ed_rm_list = ohci->ed_rm_list[frame];
-	ohci->ed_rm_list[frame] = ed;
-
-	if (!ohci->disabled && !ohci->sleeping) {
-		/* enable SOF interrupt */
-		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-	}
-}
-
-/*-------------------------------------------------------------------------*
- * TD handling functions
- *-------------------------------------------------------------------------*/
-
-/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
-
-static void
-td_fill (ohci_t * ohci, unsigned int info,
-	dma_addr_t data, int len,
-	struct urb * urb, int index)
-{
-	volatile td_t  * td, * td_pt;
-	urb_priv_t * urb_priv = urb->hcpriv;
-	
-	if (index >= urb_priv->length) {
-		err("internal OHCI error: TD index > length");
-		return;
-	}
-	
-	/* use this td as the next dummy */
-	td_pt = urb_priv->td [index];
-	td_pt->hwNextTD = 0;
-
-	/* fill the old dummy TD */
-	td = urb_priv->td [index] = dma_to_td (ohci,
-			le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf);
-
-	td->ed = urb_priv->ed;
-	td->next_dl_td = NULL;
-	td->index = index;
-	td->urb = urb; 
-	td->data_dma = data;
-	if (!len)
-		data = 0;
-
-	td->hwINFO = cpu_to_le32 (info);
-	if ((td->ed->type) == PIPE_ISOCHRONOUS) {
-		td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
-		td->ed->last_iso = info & 0xffff;
-	} else {
-		td->hwCBP = cpu_to_le32 (data); 
-	}			
-	if (data)
-		td->hwBE = cpu_to_le32 (data + len - 1);
-	else
-		td->hwBE = 0;
-	td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
-	td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
-
-	/* append to queue */
-	td->ed->hwTailP = td->hwNextTD;
-}
-
-/*-------------------------------------------------------------------------*/
- 
-/* prepare all TDs of a transfer */
-
-static void td_submit_urb (struct urb * urb)
-{ 
-	urb_priv_t * urb_priv = urb->hcpriv;
-	ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv;
-	dma_addr_t data;
-	int data_len = urb->transfer_buffer_length;
-	int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
-	int cnt = 0; 
-	__u32 info = 0;
-  	unsigned int toggle = 0;
-
-	/* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
-  	if(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe))) {
-  		toggle = TD_T_TOGGLE;
-	} else {
-  		toggle = TD_T_DATA0;
-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 1);
-	}
-	
-	urb_priv->td_cnt = 0;
-
-	if (data_len) {
-		data = pci_map_single (ohci->ohci_dev,
-			urb->transfer_buffer, data_len,
-			usb_pipeout (urb->pipe)
-				? PCI_DMA_TODEVICE
-				: PCI_DMA_FROMDEVICE
-			);
-	} else
-		data = 0;
-	
-	switch (usb_pipetype (urb->pipe)) {
-		case PIPE_BULK:
-			info = usb_pipeout (urb->pipe)? 
-				TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
-			while(data_len > 4096) {		
-				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt);
-				data += 4096; data_len -= 4096; cnt++;
-			}
-			info = usb_pipeout (urb->pipe)?
-				TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
-			td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt);
-			cnt++;
-
-			/* If the transfer size is multiple of the pipe mtu,
-			 * we may need an extra TD to create a empty frame
-			 * Note : another way to check this condition is
-			 * to test if(urb_priv->length > cnt) - Jean II */
-			if ((urb->transfer_flags & USB_ZERO_PACKET) &&
-			    usb_pipeout (urb->pipe) &&
-			    (urb->transfer_buffer_length != 0) && 
-			    ((urb->transfer_buffer_length % maxps) == 0)) {
-				td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), 0, 0, urb, cnt);
-				cnt++;
-			}
-
-			if (!ohci->sleeping)
-				writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-			break;
-
-		case PIPE_INTERRUPT:
-			info = usb_pipeout (urb->pipe)? 
-				TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle;
-			td_fill (ohci, info, data, data_len, urb, cnt++);
-			break;
-
-		case PIPE_CONTROL:
-			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
-			td_fill (ohci, info,
-				pci_map_single (ohci->ohci_dev,
-					urb->setup_packet, 8,
-					PCI_DMA_TODEVICE),
-				8, urb, cnt++); 
-			if (data_len > 0) {  
-				info = usb_pipeout (urb->pipe)? 
-					TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
-				/* NOTE:  mishandles transfers >8K, some >4K */
-				td_fill (ohci, info, data, data_len, urb, cnt++);  
-			} 
-			info = usb_pipeout (urb->pipe)? 
- 				TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
-			td_fill (ohci, info, data, 0, urb, cnt++);
-			if (!ohci->sleeping)
-				writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-			break;
-
-		case PIPE_ISOCHRONOUS:
-			for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
-				td_fill (ohci, TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), 
-					data + urb->iso_frame_desc[cnt].offset, 
-					urb->iso_frame_desc[cnt].length, urb, cnt); 
-			}
-			break;
-	} 
-	if (urb_priv->length != cnt) 
-		dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt);
-}
-
-/*-------------------------------------------------------------------------*
- * Done List handling functions
- *-------------------------------------------------------------------------*/
-
-
-/* calculate the transfer length and update the urb */
-
-static void dl_transfer_length(td_t * td)
-{
-	__u32 tdINFO, tdBE, tdCBP;
- 	__u16 tdPSW;
- 	struct urb * urb = td->urb;
- 	urb_priv_t * urb_priv = urb->hcpriv;
-	int dlen = 0;
-	int cc = 0;
-	
-	tdINFO = le32_to_cpup (&td->hwINFO);
-  	tdBE   = le32_to_cpup (&td->hwBE);
-  	tdCBP  = le32_to_cpup (&td->hwCBP);
-
-
-  	if (tdINFO & TD_ISO) {
- 		tdPSW = le16_to_cpu (td->hwPSW[0]);
- 		cc = (tdPSW >> 12) & 0xF;
-		if (cc < 0xE)  {
-			if (usb_pipeout(urb->pipe)) {
-				dlen = urb->iso_frame_desc[td->index].length;
-			} else {
-				dlen = tdPSW & 0x3ff;
-			}
-			urb->actual_length += dlen;
-			urb->iso_frame_desc[td->index].actual_length = dlen;
-			if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN))
-				cc = TD_CC_NOERROR;
-					 
-			urb->iso_frame_desc[td->index].status = cc_to_error[cc];
-		}
-	} else { /* BULK, INT, CONTROL DATA */
-		if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && 
-				((td->index == 0) || (td->index == urb_priv->length - 1)))) {
- 			if (tdBE != 0) {
- 				if (td->hwCBP == 0)
-					urb->actual_length += tdBE - td->data_dma + 1;
-  				else
-					urb->actual_length += tdCBP - td->data_dma;
-			}
-  		}
-  	}
-}
-
-/* handle an urb that is being unlinked */
-
-static void dl_del_urb (struct urb * urb)
-{
-	wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait;
-
-	urb_rm_priv_locked (urb);
-
-	if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-		urb->status = -ECONNRESET;
-		if (urb->complete)
-			urb->complete (urb);
-	} else {
-		urb->status = -ENOENT;
-
-		/* unblock sohci_unlink_urb */
-		if (wait_head)
-			wake_up (wait_head);
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* replies to the request have to be on a FIFO basis so
- * we reverse the reversed done-list */
- 
-static td_t * dl_reverse_done_list (ohci_t * ohci)
-{
-	__u32 td_list_hc;
-	td_t * td_rev = NULL;
-	td_t * td_list = NULL;
-  	urb_priv_t * urb_priv = NULL;
-  	unsigned long flags;
-  	
-  	spin_lock_irqsave (&usb_ed_lock, flags);
-  	
-	td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0;
-	ohci->hcca->done_head = 0;
-	
-	while (td_list_hc) {		
-		td_list = dma_to_td (ohci, td_list_hc);
-
-		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
-			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
-			dbg(" USB-error/status: %x : %p", 
-					TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list);
-			if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) {
-				if (urb_priv && ((td_list->index + 1) < urb_priv->length)) {
-					td_list->ed->hwHeadP = 
-						(urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) |
-									(td_list->ed->hwHeadP & cpu_to_le32 (0x2));
-					urb_priv->td_cnt += urb_priv->length - td_list->index - 1;
-				} else 
-					td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2);
-			}
-		}
-
-		td_list->next_dl_td = td_rev;	
-		td_rev = td_list;
-		td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;	
-	}	
-	spin_unlock_irqrestore (&usb_ed_lock, flags);
-	return td_list;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* there are some pending requests to remove 
- * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev)
- * - some URBs/TDs if urb_priv->state == URB_DEL */
- 
-static void dl_del_list (ohci_t  * ohci, unsigned int frame)
-{
-	unsigned long flags;
-	ed_t * ed;
-	__u32 edINFO;
-	__u32 tdINFO;
-	td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP;
-	__u32 * td_p;
-	int ctrl = 0, bulk = 0;
-
-	spin_lock_irqsave (&usb_ed_lock, flags);
-
-	for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
-
-		tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
-		tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
-		edINFO = le32_to_cpup (&ed->hwINFO);
-		td_p = &ed->hwHeadP;
-
-		for (td = tdHeadP; td != tdTailP; td = td_next) { 
-			struct urb * urb = td->urb;
-			urb_priv_t * urb_priv = td->urb->hcpriv;
-			
-			td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
-			if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
-				tdINFO = le32_to_cpup (&td->hwINFO);
-				if (TD_CC_GET (tdINFO) < 0xE)
-					dl_transfer_length (td);
-				*td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
-
-				/* URB is done; clean up */
-				if (++(urb_priv->td_cnt) == urb_priv->length)
-					dl_del_urb (urb);
-			} else {
-				td_p = &td->hwNextTD;
-			}
-		}
-
-		if (ed->state & ED_DEL) { /* set by sohci_free_dev */
-			struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]);
-			td_free (ohci, tdTailP); /* free dummy td */
-   	 		ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); 
-			ed->state = ED_NEW;
-			hash_free_ed(ohci, ed);
-   	 		/* if all eds are removed wake up sohci_free_dev */
-   	 		if (!--dev->ed_cnt) {
-				wait_queue_head_t *wait_head = dev->wait;
-
-				dev->wait = 0;
-				if (wait_head)
-					wake_up (wait_head);
-			}
-   	 	} else {
-   	 		ed->state &= ~ED_URB_DEL;
-			tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
-
-			if (tdHeadP == tdTailP) {
-				if (ed->state == ED_OPER)
-					ep_unlink(ohci, ed);
-				td_free (ohci, tdTailP);
-				ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP);
-				ed->state = ED_NEW;
-				hash_free_ed(ohci, ed);
-				--(usb_to_ohci (ohci->dev[edINFO & 0x7F]))->ed_cnt;
-			} else
-   	 			ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP);
-   	 	}
-
-		switch (ed->type) {
-			case PIPE_CONTROL:
-				ctrl = 1;
-				break;
-			case PIPE_BULK:
-				bulk = 1;
-				break;
-		}
-   	}
-   	
-	/* maybe reenable control and bulk lists */ 
-	if (!ohci->disabled) {
-		if (ctrl) 	/* reset control list */
-			writel (0, &ohci->regs->ed_controlcurrent);
-		if (bulk)	/* reset bulk list */
-			writel (0, &ohci->regs->ed_bulkcurrent);
-		if (!ohci->ed_rm_list[!frame] && !ohci->sleeping) {
-			if (ohci->ed_controltail)
-				ohci->hc_control |= OHCI_CTRL_CLE;
-			if (ohci->ed_bulktail)
-				ohci->hc_control |= OHCI_CTRL_BLE;
-			writel (ohci->hc_control, &ohci->regs->control);   
-		}
-	}
-
-   	ohci->ed_rm_list[frame] = NULL;
-   	spin_unlock_irqrestore (&usb_ed_lock, flags);
-}
-
-
-  		
-/*-------------------------------------------------------------------------*/
-
-/* td done list */
-
-static void dl_done_list (ohci_t * ohci, td_t * td_list)
-{
-  	td_t * td_list_next = NULL;
-	ed_t * ed;
-	int cc = 0;
-	struct urb * urb;
-	urb_priv_t * urb_priv;
- 	__u32 tdINFO, edHeadP, edTailP;
- 	
- 	unsigned long flags;
- 	
-  	while (td_list) {
-   		td_list_next = td_list->next_dl_td;
-   		
-  		urb = td_list->urb;
-  		urb_priv = urb->hcpriv;
-  		tdINFO = le32_to_cpup (&td_list->hwINFO);
-  		
-   		ed = td_list->ed;
-   		
-   		dl_transfer_length(td_list);
- 			
-  		/* error code of transfer */
-  		cc = TD_CC_GET (tdINFO);
-  		if (cc == TD_CC_STALL)
-			usb_endpoint_halt(urb->dev,
-				usb_pipeendpoint(urb->pipe),
-				usb_pipeout(urb->pipe));
-  		
-  		if (!(urb->transfer_flags & USB_DISABLE_SPD)
-				&& (cc == TD_DATAUNDERRUN))
-			cc = TD_CC_NOERROR;
-
-  		if (++(urb_priv->td_cnt) == urb_priv->length) {
-			if ((ed->state & (ED_OPER | ED_UNLINK))
-					&& (urb_priv->state != URB_DEL)) {
-  				urb->status = cc_to_error[cc];
-  				sohci_return_urb (ohci, urb);
-  			} else {
-				spin_lock_irqsave (&usb_ed_lock, flags);
-  				dl_del_urb (urb);
-				spin_unlock_irqrestore (&usb_ed_lock, flags);
-			}
-  		}
-  		
-  		spin_lock_irqsave (&usb_ed_lock, flags);
-  		if (ed->state != ED_NEW) { 
-  			edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
-  			edTailP = le32_to_cpup (&ed->hwTailP);
-
-			/* unlink eds if they are not busy */
-     			if ((edHeadP == edTailP) && (ed->state == ED_OPER)) 
-     				ep_unlink (ohci, ed);
-     		}	
-     		spin_unlock_irqrestore (&usb_ed_lock, flags);
-     	
-    		td_list = td_list_next;
-  	}  
-}
-
-
-
-
-/*-------------------------------------------------------------------------*
- * Virtual Root Hub 
- *-------------------------------------------------------------------------*/
- 
-/* Device descriptor */
-static __u8 root_hub_dev_des[] =
-{
-	0x12,       /*  __u8  bLength; */
-	0x01,       /*  __u8  bDescriptorType; Device */
-	0x10,	    /*  __u16 bcdUSB; v1.1 */
-	0x01,
-	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,	    /*  __u8  bDeviceSubClass; */
-	0x00,       /*  __u8  bDeviceProtocol; */
-	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
-	0x00,       /*  __u16 idVendor; */
-	0x00,
-	0x00,       /*  __u16 idProduct; */
- 	0x00,
-	0x00,       /*  __u16 bcdDevice; */
- 	0x00,
-	0x00,       /*  __u8  iManufacturer; */
-	0x02,       /*  __u8  iProduct; */
-	0x01,       /*  __u8  iSerialNumber; */
-	0x01        /*  __u8  bNumConfigurations; */
-};
-
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
-	0x09,       /*  __u8  bLength; */
-	0x02,       /*  __u8  bDescriptorType; Configuration */
-	0x19,       /*  __u16 wTotalLength; */
-	0x00,
-	0x01,       /*  __u8  bNumInterfaces; */
-	0x01,       /*  __u8  bConfigurationValue; */
-	0x00,       /*  __u8  iConfiguration; */
-	0x40,       /*  __u8  bmAttributes; 
-                 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
-	0x00,       /*  __u8  MaxPower; */
-      
-	/* interface */	  
-	0x09,       /*  __u8  if_bLength; */
-	0x04,       /*  __u8  if_bDescriptorType; Interface */
-	0x00,       /*  __u8  if_bInterfaceNumber; */
-	0x00,       /*  __u8  if_bAlternateSetting; */
-	0x01,       /*  __u8  if_bNumEndpoints; */
-	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,       /*  __u8  if_bInterfaceSubClass; */
-	0x00,       /*  __u8  if_bInterfaceProtocol; */
-	0x00,       /*  __u8  if_iInterface; */
-     
-	/* endpoint */
-	0x07,       /*  __u8  ep_bLength; */
-	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
-	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
- 	0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
- 	0x00,
-	0xff        /*  __u8  ep_bInterval; 255 ms */
-};
-
-/* Hub class-specific descriptor is constructed dynamically */
-
-
-/*-------------------------------------------------------------------------*/
-
-/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ 
- 
-static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len)
-{
-	int num_ports;
-	int i;
-	int ret;
-	int len;
-
-	__u8 data[8];
-
-	num_ports = roothub_a (ohci) & RH_A_NDP; 
-	if (num_ports > MAX_ROOT_PORTS) {
-		err ("bogus NDP=%d for OHCI usb-%s", num_ports,
-			ohci->ohci_dev->slot_name);
-		err ("rereads as NDP=%d",
-			readl (&ohci->regs->roothub.a) & RH_A_NDP);
-		/* retry later; "should not happen" */
-		return 0;
-	}
-	*(__u8 *) data = (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
-		? 1: 0;
-	ret = *(__u8 *) data;
-
-	for ( i = 0; i < num_ports; i++) {
-		*(__u8 *) (data + (i + 1) / 8) |= 
-			((roothub_portstatus (ohci, i) &
-				(RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC | RH_PS_PRSC))
-			    ? 1: 0) << ((i + 1) % 8);
-		ret += *(__u8 *) (data + (i + 1) / 8);
-	}
-	len = i/8 + 1;
-  
-	if (ret > 0) { 
-		memcpy(rh_data, data,
-		       min_t(unsigned int, len,
-			   min_t(unsigned int, rh_len, sizeof(data))));
-		return len;
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
- 
-static void rh_int_timer_do (unsigned long ptr)
-{
-	int len; 
-
-	struct urb * urb = (struct urb *) ptr;
-	ohci_t * ohci = urb->dev->bus->hcpriv;
-
-	if (ohci->disabled)
-		return;
-
-	/* ignore timers firing during PM suspend, etc */
-	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER)
-		goto out;
-
-	if(ohci->rh.send) { 
-		len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length);
-		if (len > 0) {
-			urb->actual_length = len;
-#ifdef DEBUG
-			urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));
-#endif
-			if (urb->complete)
-				urb->complete (urb);
-		}
-	}
- out:
-	rh_init_int_timer (urb);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Root Hub INTs are polled by this timer */
-
-static int rh_init_int_timer (struct urb * urb) 
-{
-	ohci_t * ohci = urb->dev->bus->hcpriv;
-
-	ohci->rh.interval = urb->interval;
-	init_timer (&ohci->rh.rh_int_timer);
-	ohci->rh.rh_int_timer.function = rh_int_timer_do;
-	ohci->rh.rh_int_timer.data = (unsigned long) urb;
-	ohci->rh.rh_int_timer.expires = 
-			jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;
-	add_timer (&ohci->rh.rh_int_timer);
-	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define OK(x) 			len = (x); break
-#define WR_RH_STAT(x) 		writel((x), &ohci->regs->roothub.status)
-#define WR_RH_PORTSTAT(x) 	writel((x), &ohci->regs->roothub.portstatus[wIndex-1])
-#define RD_RH_STAT		roothub_status(ohci)
-#define RD_RH_PORTSTAT		roothub_portstatus(ohci,wIndex-1)
-
-/* request to virtual root hub */
-
-static int rh_submit_urb (struct urb * urb)
-{
-	struct usb_device * usb_dev = urb->dev;
-	ohci_t * ohci = usb_dev->bus->hcpriv;
-	unsigned int pipe = urb->pipe;
-	struct usb_ctrlrequest * cmd = (struct usb_ctrlrequest *) urb->setup_packet;
-	void * data = urb->transfer_buffer;
-	int leni = urb->transfer_buffer_length;
-	int len = 0;
-	int status = TD_CC_NOERROR;
-	
-	__u32 datab[4];
-	__u8  * data_buf = (__u8 *) datab;
-	
- 	__u16 bmRType_bReq;
-	__u16 wValue; 
-	__u16 wIndex;
-	__u16 wLength;
-
-	if (usb_pipeint(pipe)) {
-		ohci->rh.urb =  urb;
-		ohci->rh.send = 1;
-		ohci->rh.interval = urb->interval;
-		rh_init_int_timer(urb);
-		urb->status = cc_to_error [TD_CC_NOERROR];
-		
-		return 0;
-	}
-
-	bmRType_bReq  = cmd->bRequestType | (cmd->bRequest << 8);
-	wValue        = le16_to_cpu (cmd->wValue);
-	wIndex        = le16_to_cpu (cmd->wIndex);
-	wLength       = le16_to_cpu (cmd->wLength);
-
-	switch (bmRType_bReq) {
-	/* Request Destination:
-	   without flags: Device, 
-	   RH_INTERFACE: interface, 
-	   RH_ENDPOINT: endpoint,
-	   RH_CLASS means HUB here, 
-	   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
-	*/
-  
-		case RH_GET_STATUS: 				 		
-				*(__u16 *) data_buf = cpu_to_le16 (1); OK (2);
-		case RH_GET_STATUS | RH_INTERFACE: 	 		
-				*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);
-		case RH_GET_STATUS | RH_ENDPOINT:	 		
-				*(__u16 *) data_buf = cpu_to_le16 (0); OK (2);   
-		case RH_GET_STATUS | RH_CLASS: 				
-				*(__u32 *) data_buf = cpu_to_le32 (
-					RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
-				OK (4);
-		case RH_GET_STATUS | RH_OTHER | RH_CLASS: 	
-				*(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4);
-
-		case RH_CLEAR_FEATURE | RH_ENDPOINT:  
-			switch (wValue) {
-				case (RH_ENDPOINT_STALL): OK (0);
-			}
-			break;
-
-		case RH_CLEAR_FEATURE | RH_CLASS:
-			switch (wValue) {
-				case RH_C_HUB_LOCAL_POWER:
-					OK(0);
-				case (RH_C_HUB_OVER_CURRENT): 
-						WR_RH_STAT(RH_HS_OCIC); OK (0);
-			}
-			break;
-		
-		case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-			switch (wValue) {
-				case (RH_PORT_ENABLE): 			
-						WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
-				case (RH_PORT_SUSPEND):			
-						WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
-				case (RH_PORT_POWER):			
-						WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
-				case (RH_C_PORT_CONNECTION):	
-						WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
-				case (RH_C_PORT_ENABLE):		
-						WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
-				case (RH_C_PORT_SUSPEND):		
-						WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
-				case (RH_C_PORT_OVER_CURRENT):	
-						WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
-				case (RH_C_PORT_RESET):			
-						WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); 
-			}
-			break;
- 
-		case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-			switch (wValue) {
-				case (RH_PORT_SUSPEND):			
-						WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); 
-				case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
-						if (RD_RH_PORTSTAT & RH_PS_CCS)
-						    WR_RH_PORTSTAT (RH_PS_PRS);
-						OK (0);
-				case (RH_PORT_POWER):			
-						WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); 
-				case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
-						if (RD_RH_PORTSTAT & RH_PS_CCS)
-						    WR_RH_PORTSTAT (RH_PS_PES );
-						OK (0);
-			}
-			break;
-
-		case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0);
-
-		case RH_GET_DESCRIPTOR:
-			switch ((wValue & 0xff00) >> 8) {
-				case (0x01): /* device descriptor */
-					len = min_t(unsigned int,
-						  leni,
-						  min_t(unsigned int,
-						      sizeof (root_hub_dev_des),
-						      wLength));
-					data_buf = root_hub_dev_des; OK(len);
-				case (0x02): /* configuration descriptor */
-					len = min_t(unsigned int,
-						  leni,
-						  min_t(unsigned int,
-						      sizeof (root_hub_config_des),
-						      wLength));
-					data_buf = root_hub_config_des; OK(len);
-				case (0x03): /* string descriptors */
-					len = usb_root_hub_string (wValue & 0xff,
-						(int)(long) ohci->regs, "OHCI",
-						data, wLength);
-					if (len > 0) {
-						data_buf = data;
-						OK(min_t(int, leni, len));
-					}
-					// else fallthrough
-				default: 
-					status = TD_CC_STALL;
-			}
-			break;
-		
-		case RH_GET_DESCRIPTOR | RH_CLASS:
-		    {
-			    __u32 temp = roothub_a (ohci);
-
-			    data_buf [0] = 9;		// min length;
-			    data_buf [1] = 0x29;
-			    data_buf [2] = temp & RH_A_NDP;
-			    data_buf [3] = 0;
-			    if (temp & RH_A_PSM) 	/* per-port power switching? */
-				data_buf [3] |= 0x1;
-			    if (temp & RH_A_NOCP)	/* no overcurrent reporting? */
-				data_buf [3] |= 0x10;
-			    else if (temp & RH_A_OCPM)	/* per-port overcurrent reporting? */
-				data_buf [3] |= 0x8;
-
-			    datab [1] = 0;
-			    data_buf [5] = (temp & RH_A_POTPGT) >> 24;
-			    temp = roothub_b (ohci);
-			    data_buf [7] = temp & RH_B_DR;
-			    if (data_buf [2] < 7) {
-				data_buf [8] = 0xff;
-			    } else {
-				data_buf [0] += 2;
-				data_buf [8] = (temp & RH_B_DR) >> 8;
-				data_buf [10] = data_buf [9] = 0xff;
-			    }
-				
-			    len = min_t(unsigned int, leni,
-				      min_t(unsigned int, data_buf [0], wLength));
-			    OK (len);
-			}
- 
-		case RH_GET_CONFIGURATION: 	*(__u8 *) data_buf = 0x01; OK (1);
-
-		case RH_SET_CONFIGURATION: 	WR_RH_STAT (0x10000); OK (0);
-
-		default: 
-			dbg ("unsupported root hub command");
-			status = TD_CC_STALL;
-	}
-	
-#ifdef	DEBUG
-	// ohci_dump_roothub (ohci, 0);
-#endif
-
-	len = min_t(int, len, leni);
-	if (data != data_buf)
-	    memcpy (data, data_buf, len);
-  	urb->actual_length = len;
-	urb->status = cc_to_error [status];
-	
-#ifdef DEBUG
-	urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe));
-#endif
-
-	urb->hcpriv = NULL;
-	usb_dec_dev_use (usb_dev);
-	urb->dev = NULL;
-	if (urb->complete)
-	    	urb->complete (urb);
-	usb_put_urb (urb);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int rh_unlink_urb (struct urb * urb)
-{
-	ohci_t * ohci = urb->dev->bus->hcpriv;
- 
-	if (ohci->rh.urb == urb) {
-		ohci->rh.send = 0;
-		del_timer (&ohci->rh.rh_int_timer);
-		ohci->rh.urb = NULL;
-
-		urb->hcpriv = NULL;
-		usb_dec_dev_use(urb->dev);
-		urb->dev = NULL;
-		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-			urb->status = -ECONNRESET;
-			if (urb->complete)
-				urb->complete (urb);
-		} else
-			urb->status = -ENOENT;
-		usb_put_urb (urb);
-	}
-	return 0;
-}
- 
-/*-------------------------------------------------------------------------*
- * HC functions
- *-------------------------------------------------------------------------*/
-
-/* reset the HC and BUS */
-
-static int hc_reset (ohci_t * ohci)
-{
-	int timeout = 30;
-	int smm_timeout = 50; /* 0,5 sec */
-	 	
-	if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
-		writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
-		dbg("USB HC TakeOver from SMM");
-		while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
-			wait_ms (10);
-			if (--smm_timeout == 0) {
-				err("USB HC TakeOver failed!");
-				return -1;
-			}
-		}
-	}	
-		
-	/* Disable HC interrupts */
-	writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
-
-	dbg("USB HC reset_hc usb-%s: ctrl = 0x%x ;",
-		ohci->ohci_dev->slot_name,
-		readl (&ohci->regs->control));
-
-  	/* Reset USB (needed by some controllers) */
-	writel (0, &ohci->regs->control);
-      	
-	/* HC Reset requires max 10 ms delay */
-	writel (OHCI_HCR,  &ohci->regs->cmdstatus);
-	while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
-		if (--timeout == 0) {
-			err("USB HC reset timed out!");
-			return -1;
-		}	
-		udelay (1);
-	}	 
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Start an OHCI controller, set the BUS operational
- * enable interrupts 
- * connect the virtual root hub */
-
-static int hc_start (ohci_t * ohci)
-{
-  	__u32 mask;
-  	unsigned int fminterval;
-  	struct usb_device  * usb_dev;
-	struct ohci_device * dev;
-	
-	ohci->disabled = 1;
-
-	/* Tell the controller where the control and bulk lists are
-	 * The lists are empty now. */
-	 
-	writel (0, &ohci->regs->ed_controlhead);
-	writel (0, &ohci->regs->ed_bulkhead);
-	
-	writel (ohci->hcca_dma, &ohci->regs->hcca); /* a reset clears this */
-   
-  	fminterval = 0x2edf;
-	writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
-	fminterval |= ((((fminterval - 210) * 6) / 7) << 16); 
-	writel (fminterval, &ohci->regs->fminterval);	
-	writel (0x628, &ohci->regs->lsthresh);
-
- 	/* start controller operations */
- 	ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-	ohci->disabled = 0;
- 	writel (ohci->hc_control, &ohci->regs->control);
- 
-	/* Choose the interrupts we care about now, others later on demand */
-	mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
-	writel (mask, &ohci->regs->intrenable);
-	writel (mask, &ohci->regs->intrstatus);
-
-#ifdef	OHCI_USE_NPS
-	/* required for AMD-756 and some Mac platforms */
-	writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
-		&ohci->regs->roothub.a);
-	writel (RH_HS_LPSC, &ohci->regs->roothub.status);
-#endif	/* OHCI_USE_NPS */
-
-	// POTPGT delay is bits 24-31, in 2 ms units.
-	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
- 
-	/* connect the virtual root hub */
-	ohci->rh.devnum = 0;
-	usb_dev = usb_alloc_dev (NULL, ohci->bus);
-	if (!usb_dev) {
-	    ohci->disabled = 1;
-	    return -ENOMEM;
-	}
-
-	dev = usb_to_ohci (usb_dev);
-	ohci->bus->root_hub = usb_dev;
-	usb_connect (usb_dev);
-	if (usb_register_root_hub (usb_dev, &ohci->ohci_dev->dev) != 0) {
-		usb_free_dev (usb_dev); 
-		ohci->disabled = 1;
-		return -ENODEV;
-	}
-	
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* called only from interrupt handler */
-
-static void check_timeouts (struct ohci *ohci)
-{
-	spin_lock (&usb_ed_lock);
-	while (!list_empty (&ohci->timeout_list)) {
-		struct urb	*urb;
-
-		urb = list_entry (ohci->timeout_list.next, struct urb, urb_list);
-		if (time_after (jiffies, urb->timeout))
-			break;
-
-		list_del_init (&urb->urb_list);
-		if (urb->status != -EINPROGRESS)
-			continue;
-
-		urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
-		spin_unlock (&usb_ed_lock);
-
-		// outside the interrupt handler (in a timer...)
-		// this reference would race interrupts
-		sohci_unlink_urb (urb);
-
-		spin_lock (&usb_ed_lock);
-	}
-	spin_unlock (&usb_ed_lock);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* an interrupt happens */
-
-static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
-{
-	ohci_t * ohci = __ohci;
-	struct ohci_regs * regs = ohci->regs;
- 	int ints; 
-
-	if ((ohci->hcca->done_head != 0) && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
-		ints =  OHCI_INTR_WDH;
-	} else if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0) {
-		return;
-	} 
-
-	// dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
-
-	if (ints & OHCI_INTR_UE) {
-		ohci->disabled++;
-		err ("OHCI Unrecoverable Error, controller usb-%s disabled",
-			ohci->ohci_dev->slot_name);
-		// e.g. due to PCI Master/Target Abort
-
-#ifdef	DEBUG
-		ohci_dump (ohci, 1);
-#else
-		// FIXME: be optimistic, hope that bug won't repeat often.
-		// Make some non-interrupt context restart the controller.
-		// Count and limit the retries though; either hardware or
-		// software errors can go forever...
-#endif
-		hc_reset (ohci);
-	}
-  
-	if (ints & OHCI_INTR_WDH) {
-		writel (OHCI_INTR_WDH, &regs->intrdisable);	
-		dl_done_list (ohci, dl_reverse_done_list (ohci));
-		writel (OHCI_INTR_WDH, &regs->intrenable); 
-	}
-  
-	if (ints & OHCI_INTR_SO) {
-		dbg("USB Schedule overrun");
-		writel (OHCI_INTR_SO, &regs->intrenable); 	 
-	}
-
-	// FIXME:  this assumes SOF (1/ms) interrupts don't get lost...
-	if (ints & OHCI_INTR_SF) { 
-		unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1;
-		writel (OHCI_INTR_SF, &regs->intrdisable);	
-		if (ohci->ed_rm_list[!frame] != NULL) {
-			dl_del_list (ohci, !frame);
-		}
-		if (ohci->ed_rm_list[frame] != NULL)
-			writel (OHCI_INTR_SF, &regs->intrenable);	
-	}
-
-	if (!list_empty (&ohci->timeout_list)) {
-		check_timeouts (ohci);
-// FIXME:  enable SF as needed in a timer;
-// don't make lots of 1ms interrupts
-// On unloaded USB, think 4k ~= 4-5msec
-		if (!list_empty (&ohci->timeout_list))
-			writel (OHCI_INTR_SF, &regs->intrenable);	
-	}
-
-	writel (ints, &regs->intrstatus);
-	writel (OHCI_INTR_MIE, &regs->intrenable);	
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* allocate OHCI */
-
-static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base)
-{
-	ohci_t * ohci;
-	struct usb_bus * bus;
-
-	ohci = (ohci_t *) kmalloc (sizeof *ohci, GFP_KERNEL);
-	if (!ohci)
-		return NULL;
-		
-	memset (ohci, 0, sizeof (ohci_t));
-
-	ohci->hcca = pci_alloc_consistent (dev, sizeof *ohci->hcca,
-			&ohci->hcca_dma);
-        if (!ohci->hcca) {
-                kfree (ohci);
-                return NULL;
-        }
-        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
-
-	ohci->disabled = 1;
-	ohci->sleeping = 0;
-	ohci->irq = -1;
-	ohci->regs = mem_base;   
-
-	ohci->ohci_dev = dev;
-	pci_set_drvdata(dev, ohci);
- 
-	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-	list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
-
-	INIT_LIST_HEAD (&ohci->timeout_list);
-
-	bus = usb_alloc_bus (&sohci_device_operations);
-	if (!bus) {
-		kfree (ohci);
-		return NULL;
-	}
-
-	ohci->bus = bus;
-	bus->hcpriv = (void *) ohci;
-
-	return ohci;
-} 
-
-
-/*-------------------------------------------------------------------------*/
-
-/* De-allocate all resources.. */
-
-static void hc_release_ohci (ohci_t * ohci)
-{	
-	dbg ("USB HC release ohci usb-%s", ohci->ohci_dev->slot_name);
-
-	/* disconnect all devices */    
-	if (ohci->bus->root_hub)
-		usb_disconnect (&ohci->bus->root_hub);
-
-	if (!ohci->disabled)
-		hc_reset (ohci);
-	
-	if (ohci->irq >= 0) {
-		free_irq (ohci->irq, ohci);
-		ohci->irq = -1;
-	}
-	pci_set_drvdata(ohci->ohci_dev, NULL);
-
-	usb_deregister_bus (ohci->bus);
-	usb_free_bus (ohci->bus);
-
-	list_del (&ohci->ohci_hcd_list);
-	INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-
-	ohci_mem_cleanup (ohci);
-    
-	/* unmap the IO address space */
-	iounmap (ohci->regs);
-
-	pci_free_consistent (ohci->ohci_dev, sizeof *ohci->hcca,
-		ohci->hcca, ohci->hcca_dma);
-	kfree (ohci);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Increment the module usage count, start the control thread and
- * return success. */
-
-static struct pci_driver ohci_pci_driver;
- 
-static int __devinit
-hc_found_ohci (struct pci_dev *dev, int irq,
-	void *mem_base, const struct pci_device_id *id)
-{
-	ohci_t * ohci;
-	u8 latency, limit;
-	char buf[8], *bufp = buf;
-	int ret;
-
-#ifndef __sparc__
-	sprintf(buf, "%d", irq);
-#else
-	bufp = __irq_itoa(irq);
-#endif
-	printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
-		(unsigned long)	mem_base, bufp);
-	printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
-    
-	ohci = hc_alloc_ohci (dev, mem_base);
-	if (!ohci) {
-		return -ENOMEM;
-	}
-	if ((ret = ohci_mem_init (ohci)) < 0) {
-		hc_release_ohci (ohci);
-		return ret;
-	}
-	ohci->flags = id->driver_data;
-	if (ohci->flags & OHCI_QUIRK_AMD756)
-		printk (KERN_INFO __FILE__ ": AMD756 erratum 4 workaround\n");
-
-	/* bad pci latencies can contribute to overruns */ 
-	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-	if (latency) {
-		pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
-		if (limit && limit < latency) {
-			dbg ("PCI latency reduced to max %d", limit);
-			pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
-			ohci->pci_latency = limit;
-		} else {
-			/* it might already have been reduced */
-			ohci->pci_latency = latency;
-		}
-	}
-
-	if (hc_reset (ohci) < 0) {
-		hc_release_ohci (ohci);
-		return -ENODEV;
-	}
-
-	/* FIXME this is a second HC reset; why?? */
-	writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
-	wait_ms (10);
-
-	usb_register_bus (ohci->bus);
-	
-	if (request_irq (irq, hc_interrupt, SA_SHIRQ,
-			ohci_pci_driver.name, ohci) != 0) {
-		err ("request interrupt %s failed", bufp);
-		hc_release_ohci (ohci);
-		return -EBUSY;
-	}
-	ohci->irq = irq;     
-
-	if (hc_start (ohci) < 0) {
-		err ("can't start usb-%s", dev->slot_name);
-		hc_release_ohci (ohci);
-		return -EBUSY;
-	}
-
-#ifdef	DEBUG
-	ohci_dump (ohci, 1);
-#endif
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef	CONFIG_PM
-
-/* controller died; cleanup debris, then restart */
-/* must not be called from interrupt context */
-
-static void hc_restart (ohci_t *ohci)
-{
-	int temp;
-	int i;
-
-	if (ohci->pci_latency)
-		pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
-
-	ohci->disabled = 1;
-	ohci->sleeping = 0;
-	if (ohci->bus->root_hub)
-		usb_disconnect (&ohci->bus->root_hub);
-	
-	/* empty the interrupt branches */
-	for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
-	for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table[i] = 0;
-	
-	/* no EDs to remove */
-	ohci->ed_rm_list [0] = NULL;
-	ohci->ed_rm_list [1] = NULL;
-
-	/* empty control and bulk lists */	 
-	ohci->ed_isotail     = NULL;
-	ohci->ed_controltail = NULL;
-	ohci->ed_bulktail    = NULL;
-
-	if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
-		err ("can't restart usb-%s, %d", ohci->ohci_dev->slot_name, temp);
-	} else
-		dbg ("restart usb-%s completed", ohci->ohci_dev->slot_name);
-}
-
-#endif	/* CONFIG_PM */
-
-/*-------------------------------------------------------------------------*/
-
-/* configured so that an OHCI device is always provided */
-/* always called with process context; sleeping is OK */
-
-static int __devinit
-ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-	unsigned long mem_resource, mem_len;
-	void *mem_base;
-
-	if (pci_enable_device(dev) < 0)
-		return -ENODEV;
-
-        if (!dev->irq) {
-        	err("found OHCI device with no IRQ assigned. check BIOS settings!");
-   	        return -ENODEV;
-        }
-	
-	/* we read its hardware registers as memory */
-	mem_resource = pci_resource_start(dev, 0);
-	mem_len = pci_resource_len(dev, 0);
-	if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
-		dbg ("controller already in use");
-		return -EBUSY;
-	}
-
-	mem_base = ioremap_nocache (mem_resource, mem_len);
-	if (!mem_base) {
-		err("Error mapping OHCI memory");
-		return -EFAULT;
-	}
-
-	/* controller writes into our memory */
-	pci_set_master (dev);
-
-	return hc_found_ohci (dev, dev->irq, mem_base, id);
-} 
-
-/*-------------------------------------------------------------------------*/
-
-/* may be called from interrupt context [interface spec] */
-/* may be called without controller present */
-/* may be called with controller, bus, and devices active */
-
-static void __devexit
-ohci_pci_remove (struct pci_dev *dev)
-{
-	ohci_t		*ohci = pci_get_drvdata(dev);
-
-	dbg ("remove %s controller usb-%s%s%s",
-		hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
-		dev->slot_name,
-		ohci->disabled ? " (disabled)" : "",
-		in_interrupt () ? " in interrupt" : ""
-		);
-#ifdef	DEBUG
-	ohci_dump (ohci, 1);
-#endif
-
-	/* don't wake up sleeping controllers, or block in interrupt context */
-	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || in_interrupt ()) {
-		dbg ("controller being disabled");
-		ohci->disabled = 1;
-	}
-
-	/* on return, USB will always be reset (if present) */
-	if (ohci->disabled)
-		writel (ohci->hc_control = OHCI_USB_RESET,
-			&ohci->regs->control);
-
-	hc_release_ohci (ohci);
-
-	release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
-}
-
-
-#ifdef	CONFIG_PM
-
-/*-------------------------------------------------------------------------*/
-
-static int
-ohci_pci_suspend (struct pci_dev *dev, u32 state)
-{
-	ohci_t			*ohci = pci_get_drvdata(dev);
-	unsigned long		flags;
-	u16 cmd;
-
-	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
-		dbg ("can't suspend usb-%s (state is %s)", dev->slot_name,
-			hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
-		return -EIO;
-	}
-
-	/* act as if usb suspend can always be used */
-	info ("USB suspend: usb-%s", dev->slot_name);
-	ohci->sleeping = 1;
-
-	/* First stop processing */
-  	spin_lock_irqsave (&usb_ed_lock, flags);
-	ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
-	writel (ohci->hc_control, &ohci->regs->control);
-	writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-	(void) readl (&ohci->regs->intrstatus);
-  	spin_unlock_irqrestore (&usb_ed_lock, flags);
-
-	/* Wait a frame or two */
-	mdelay(1);
-	if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
-		mdelay (1);
-		
-#ifdef CONFIG_PMAC_PBOOK
-	if (_machine == _MACH_Pmac)
-		disable_irq (ohci->irq);
-	/* else, 2.4 assumes shared irqs -- don't disable */
-#endif
-	/* Enable remote wakeup */
-	writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable);
-
-	/* Suspend chip and let things settle down a bit */
-	ohci->hc_control = OHCI_USB_SUSPEND;
-	writel (ohci->hc_control, &ohci->regs->control);
-	(void) readl (&ohci->regs->control);
-	mdelay (500); /* No schedule here ! */
-	switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
-		case OHCI_USB_RESET:
-			dbg("Bus in reset phase ???");
-			break;
-		case OHCI_USB_RESUME:
-			dbg("Bus in resume phase ???");
-			break;
-		case OHCI_USB_OPER:
-			dbg("Bus in operational phase ???");
-			break;
-		case OHCI_USB_SUSPEND:
-			dbg("Bus suspended");
-			break;
-	}
-	/* In some rare situations, Apple's OHCI have happily trashed
-	 * memory during sleep. We disable it's bus master bit during
-	 * suspend
-	 */
-	pci_read_config_word (dev, PCI_COMMAND, &cmd);
-	cmd &= ~PCI_COMMAND_MASTER;
-	pci_write_config_word (dev, PCI_COMMAND, cmd);
-#ifdef CONFIG_PMAC_PBOOK
-	{
-   	struct device_node	*of_node;
-
-	/* Disable USB PAD & cell clock */
-	of_node = pci_device_to_OF_node (ohci->ohci_dev);
-	if (of_node && _machine == _MACH_Pmac)
-		feature_set_usb_power (of_node, 0);
-	}
-#endif
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-ohci_pci_resume (struct pci_dev *dev)
-{
-	ohci_t		*ohci = pci_get_drvdata(dev);
-	int		temp;
-	unsigned long	flags;
-
-	/* guard against multiple resumes */
-	atomic_inc (&ohci->resume_count);
-	if (atomic_read (&ohci->resume_count) != 1) {
-		err ("concurrent PCI resumes for usb-%s", dev->slot_name);
-		atomic_dec (&ohci->resume_count);
-		return 0;
-	}
-
-#ifdef CONFIG_PMAC_PBOOK
-	{
-	struct device_node *of_node;
-
-	/* Re-enable USB PAD & cell clock */
-	of_node = pci_device_to_OF_node (ohci->ohci_dev);
-	if (of_node && _machine == _MACH_Pmac)
-		feature_set_usb_power (of_node, 1);
-	}
-#endif
-
-	/* did we suspend, or were we powered off? */
-	ohci->hc_control = readl (&ohci->regs->control);
-	temp = ohci->hc_control & OHCI_CTRL_HCFS;
-
-#ifdef DEBUG
-	/* the registers may look crazy here */
-	ohci_dump_status (ohci);
-#endif
-
-	/* Re-enable bus mastering */
-	pci_set_master(ohci->ohci_dev);
-	
-	switch (temp) {
-
-	case OHCI_USB_RESET:	// lost power
-		info ("USB restart: usb-%s", dev->slot_name);
-		hc_restart (ohci);
-		break;
-
-	case OHCI_USB_SUSPEND:	// host wakeup
-	case OHCI_USB_RESUME:	// remote wakeup
-		info ("USB continue: usb-%s from %s wakeup", dev->slot_name,
-			(temp == OHCI_USB_SUSPEND)
-				? "host" : "remote");
-		ohci->hc_control = OHCI_USB_RESUME;
-		writel (ohci->hc_control, &ohci->regs->control);
-		(void) readl (&ohci->regs->control);
-		mdelay (20); /* no schedule here ! */
-		/* Some controllers (lucent) need a longer delay here */
-		mdelay (15);
-		temp = readl (&ohci->regs->control);
-		temp = ohci->hc_control & OHCI_CTRL_HCFS;
-		if (temp != OHCI_USB_RESUME) {
-			err ("controller usb-%s won't resume", dev->slot_name);
-			ohci->disabled = 1;
-			return -EIO;
-		}
-
-		/* Some chips likes being resumed first */
-		writel (OHCI_USB_OPER, &ohci->regs->control);
-		(void) readl (&ohci->regs->control);
-		mdelay (3);
-
-		/* Then re-enable operations */
-		spin_lock_irqsave (&usb_ed_lock, flags);
-		ohci->disabled = 0;
-		ohci->sleeping = 0;
-		ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
-		if (!ohci->ed_rm_list[0] && !ohci->ed_rm_list[1]) {
-			if (ohci->ed_controltail)
-				ohci->hc_control |= OHCI_CTRL_CLE;
-			if (ohci->ed_bulktail)
-				ohci->hc_control |= OHCI_CTRL_BLE;
-		}
-		writel (ohci->hc_control, &ohci->regs->control);
-		writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
-		writel (OHCI_INTR_SF, &ohci->regs->intrenable);
-		/* Check for a pending done list */
-		writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);	
-		(void) readl (&ohci->regs->intrdisable);
-		spin_unlock_irqrestore (&usb_ed_lock, flags);
-#ifdef CONFIG_PMAC_PBOOK
-		if (_machine == _MACH_Pmac)
-			enable_irq (ohci->irq);
-#endif
-		if (ohci->hcca->done_head)
-			dl_done_list (ohci, dl_reverse_done_list (ohci));
-		writel (OHCI_INTR_WDH, &ohci->regs->intrenable); 
-		writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
-		writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
-		break;
-
-	default:
-		warn ("odd PCI resume for usb-%s", dev->slot_name);
-	}
-
-	/* controller is operational, extra resumes are harmless */
-	atomic_dec (&ohci->resume_count);
-
-	return 0;
-}
-
-#endif	/* CONFIG_PM */
-
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id __devinitdata ohci_pci_ids [] = { {
-
-	/*
-	 * AMD-756 [Viper] USB has a serious erratum when used with
-	 * lowspeed devices like mice.
-	 */
-	vendor:		0x1022,
-	device:		0x740c,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-	driver_data:	OHCI_QUIRK_AMD756,
-
-} , {
-
-	/* handle any USB OHCI controller */
-	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x10),
-	class_mask: 	~0,
-
-	/* no matter who makes it */
-	vendor:		PCI_ANY_ID,
-	device:		PCI_ANY_ID,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-	}, { /* end: all zeroes */ }
-};
-
-MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
-
-static struct pci_driver ohci_pci_driver = {
-	name:		"usb-ohci",
-	id_table:	&ohci_pci_ids [0],
-
-	probe:		ohci_pci_probe,
-	remove:		__devexit_p(ohci_pci_remove),
-
-#ifdef	CONFIG_PM
-	suspend:	ohci_pci_suspend,
-	resume:		ohci_pci_resume,
-#endif	/* PM */
-};
-
- 
-/*-------------------------------------------------------------------------*/
-
-static int __init ohci_hcd_init (void) 
-{
-	return pci_module_init (&ohci_pci_driver);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void __exit ohci_hcd_cleanup (void) 
-{	
-	pci_unregister_driver (&ohci_pci_driver);
-}
-
-module_init (ohci_hcd_init);
-module_exit (ohci_hcd_cleanup);
-
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/usb-ohci.h b/drivers/usb/usb-ohci.h
--- a/drivers/usb/usb-ohci.h	Sun Apr 14 12:16:56 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,643 +0,0 @@
-/*
- * URB OHCI HCD (Host Controller Driver) for USB.
- * 
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
- * 
- * usb-ohci.h
- */
-
- 
-static int cc_to_error[16] = { 
-
-/* mapping of the OHCI CC status to error codes */ 
-	/* No  Error  */	0,
-	/* CRC Error  */	-EILSEQ,
-	/* Bit Stuff  */	-EPROTO,
-	/* Data Togg  */	-EILSEQ,
-	/* Stall      */	-EPIPE,
-	/* DevNotResp */	-ETIMEDOUT,
-	/* PIDCheck   */	-EPROTO,
-	/* UnExpPID   */	-EPROTO,
-	/* DataOver   */	-EOVERFLOW,
-	/* DataUnder  */	-EREMOTEIO,
-	/* reservd    */	-ETIMEDOUT,
-	/* reservd    */	-ETIMEDOUT,
-	/* BufferOver */	-ECOMM,
-	/* BuffUnder  */	-ENOSR,
-	/* Not Access */	-ETIMEDOUT,
-	/* Not Access */	-ETIMEDOUT 
-};
-
-#include <linux/config.h>
-
-/* ED States */
-
-#define ED_NEW 		0x00
-#define ED_UNLINK 	0x01
-#define ED_OPER		0x02
-#define ED_DEL		0x04
-#define ED_URB_DEL  	0x08
-
-/* usb_ohci_ed */
-struct ed {
-	__u32 hwINFO;       
-	__u32 hwTailP;
-	__u32 hwHeadP;
-	__u32 hwNextED;
-
-	struct ed * ed_prev;  
-	__u8 int_period;
-	__u8 int_branch;
-	__u8 int_load; 
-	__u8 int_interval;
-	__u8 state;
-	__u8 type; 
-	__u16 last_iso;
-	struct ed * ed_rm_list;
-
-	dma_addr_t dma;
-	__u32 unused[3];
-} __attribute((aligned(16)));
-typedef struct ed ed_t;
-
- 
-/* TD info field */
-#define TD_CC       0xf0000000
-#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
-#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
-#define TD_EC       0x0C000000
-#define TD_T        0x03000000
-#define TD_T_DATA0  0x02000000
-#define TD_T_DATA1  0x03000000
-#define TD_T_TOGGLE 0x00000000
-#define TD_R        0x00040000
-#define TD_DI       0x00E00000
-#define TD_DI_SET(X) (((X) & 0x07)<< 21)
-#define TD_DP       0x00180000
-#define TD_DP_SETUP 0x00000000
-#define TD_DP_IN    0x00100000
-#define TD_DP_OUT   0x00080000
-
-#define TD_ISO	    0x00010000
-#define TD_DEL      0x00020000
-
-/* CC Codes */
-#define TD_CC_NOERROR      0x00
-#define TD_CC_CRC          0x01
-#define TD_CC_BITSTUFFING  0x02
-#define TD_CC_DATATOGGLEM  0x03
-#define TD_CC_STALL        0x04
-#define TD_DEVNOTRESP      0x05
-#define TD_PIDCHECKFAIL    0x06
-#define TD_UNEXPECTEDPID   0x07
-#define TD_DATAOVERRUN     0x08
-#define TD_DATAUNDERRUN    0x09
-#define TD_BUFFEROVERRUN   0x0C
-#define TD_BUFFERUNDERRUN  0x0D
-#define TD_NOTACCESSED     0x0F
-
-
-#define MAXPSW 1
-
-struct td {
-	__u32 hwINFO;
-  	__u32 hwCBP;		/* Current Buffer Pointer */
-  	__u32 hwNextTD;		/* Next TD Pointer */
-  	__u32 hwBE;		/* Memory Buffer End Pointer */
-
-  	__u16 hwPSW[MAXPSW];
-  	__u8 unused;
-  	__u8 index;
-  	struct ed * ed;
-  	struct td * next_dl_td;
-  	struct urb * urb;
-
-	dma_addr_t td_dma;
-	dma_addr_t data_dma;
-	__u32 unused2[2];
-} __attribute((aligned(32)));	/* normally 16, iso needs 32 */
-typedef struct td td_t;
-
-#define OHCI_ED_SKIP	(1 << 14)
-
-/*
- * The HCCA (Host Controller Communications Area) is a 256 byte
- * structure defined in the OHCI spec. that the host controller is
- * told the base address of.  It must be 256-byte aligned.
- */
- 
-#define NUM_INTS 32	/* part of the OHCI standard */
-struct ohci_hcca {
-	__u32	int_table[NUM_INTS];	/* Interrupt ED table */
-	__u16	frame_no;		/* current frame number */
-	__u16	pad1;			/* set to 0 on each frame_no change */
-	__u32	done_head;		/* info returned for an interrupt */
-	u8		reserved_for_hc[116];
-} __attribute((aligned(256)));
-
-  
-/*
- * Maximum number of root hub ports.  
- */
-#define MAX_ROOT_PORTS	15	/* maximum OHCI root hub ports */
-
-/*
- * This is the structure of the OHCI controller's memory mapped I/O
- * region.  This is Memory Mapped I/O.  You must use the readl() and
- * writel() macros defined in asm/io.h to access these!!
- */
-struct ohci_regs {
-	/* control and status registers */
-	__u32	revision;
-	__u32	control;
-	__u32	cmdstatus;
-	__u32	intrstatus;
-	__u32	intrenable;
-	__u32	intrdisable;
-	/* memory pointers */
-	__u32	hcca;
-	__u32	ed_periodcurrent;
-	__u32	ed_controlhead;
-	__u32	ed_controlcurrent;
-	__u32	ed_bulkhead;
-	__u32	ed_bulkcurrent;
-	__u32	donehead;
-	/* frame counters */
-	__u32	fminterval;
-	__u32	fmremaining;
-	__u32	fmnumber;
-	__u32	periodicstart;
-	__u32	lsthresh;
-	/* Root hub ports */
-	struct	ohci_roothub_regs {
-		__u32	a;
-		__u32	b;
-		__u32	status;
-		__u32	portstatus[MAX_ROOT_PORTS];
-	} roothub;
-} __attribute((aligned(32)));
-
-
-/* OHCI CONTROL AND STATUS REGISTER MASKS */
-
-/*
- * HcControl (control) register masks
- */
-#define OHCI_CTRL_CBSR	(3 << 0)	/* control/bulk service ratio */
-#define OHCI_CTRL_PLE	(1 << 2)	/* periodic list enable */
-#define OHCI_CTRL_IE	(1 << 3)	/* isochronous enable */
-#define OHCI_CTRL_CLE	(1 << 4)	/* control list enable */
-#define OHCI_CTRL_BLE	(1 << 5)	/* bulk list enable */
-#define OHCI_CTRL_HCFS	(3 << 6)	/* host controller functional state */
-#define OHCI_CTRL_IR	(1 << 8)	/* interrupt routing */
-#define OHCI_CTRL_RWC	(1 << 9)	/* remote wakeup connected */
-#define OHCI_CTRL_RWE	(1 << 10)	/* remote wakeup enable */
-
-/* pre-shifted values for HCFS */
-#	define OHCI_USB_RESET	(0 << 6)
-#	define OHCI_USB_RESUME	(1 << 6)
-#	define OHCI_USB_OPER	(2 << 6)
-#	define OHCI_USB_SUSPEND	(3 << 6)
-
-/*
- * HcCommandStatus (cmdstatus) register masks
- */
-#define OHCI_HCR	(1 << 0)	/* host controller reset */
-#define OHCI_CLF  	(1 << 1)	/* control list filled */
-#define OHCI_BLF  	(1 << 2)	/* bulk list filled */
-#define OHCI_OCR  	(1 << 3)	/* ownership change request */
-#define OHCI_SOC  	(3 << 16)	/* scheduling overrun count */
-
-/*
- * masks used with interrupt registers:
- * HcInterruptStatus (intrstatus)
- * HcInterruptEnable (intrenable)
- * HcInterruptDisable (intrdisable)
- */
-#define OHCI_INTR_SO	(1 << 0)	/* scheduling overrun */
-#define OHCI_INTR_WDH	(1 << 1)	/* writeback of done_head */
-#define OHCI_INTR_SF	(1 << 2)	/* start frame */
-#define OHCI_INTR_RD	(1 << 3)	/* resume detect */
-#define OHCI_INTR_UE	(1 << 4)	/* unrecoverable error */
-#define OHCI_INTR_FNO	(1 << 5)	/* frame number overflow */
-#define OHCI_INTR_RHSC	(1 << 6)	/* root hub status change */
-#define OHCI_INTR_OC	(1 << 30)	/* ownership change */
-#define OHCI_INTR_MIE	(1 << 31)	/* master interrupt enable */
-
-
-
-/* Virtual Root HUB */
-struct virt_root_hub {
-	int devnum; /* Address of Root Hub endpoint */ 
-	void * urb;
-	void * int_addr;
-	int send;
-	int interval;
-	struct timer_list rh_int_timer;
-};
-
-
-/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
- 
-/* destination of request */
-#define RH_INTERFACE               0x01
-#define RH_ENDPOINT                0x02
-#define RH_OTHER                   0x03
-
-#define RH_CLASS                   0x20
-#define RH_VENDOR                  0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS           0x0080
-#define RH_CLEAR_FEATURE        0x0100
-#define RH_SET_FEATURE          0x0300
-#define RH_SET_ADDRESS		0x0500
-#define RH_GET_DESCRIPTOR	0x0680
-#define RH_SET_DESCRIPTOR       0x0700
-#define RH_GET_CONFIGURATION	0x0880
-#define RH_SET_CONFIGURATION	0x0900
-#define RH_GET_STATE            0x0280
-#define RH_GET_INTERFACE        0x0A80
-#define RH_SET_INTERFACE        0x0B00
-#define RH_SYNC_FRAME           0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP               0x2000
-
-
-/* Hub port features */
-#define RH_PORT_CONNECTION         0x00
-#define RH_PORT_ENABLE             0x01
-#define RH_PORT_SUSPEND            0x02
-#define RH_PORT_OVER_CURRENT       0x03
-#define RH_PORT_RESET              0x04
-#define RH_PORT_POWER              0x08
-#define RH_PORT_LOW_SPEED          0x09
-
-#define RH_C_PORT_CONNECTION       0x10
-#define RH_C_PORT_ENABLE           0x11
-#define RH_C_PORT_SUSPEND          0x12
-#define RH_C_PORT_OVER_CURRENT     0x13
-#define RH_C_PORT_RESET            0x14  
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER       0x00
-#define RH_C_HUB_OVER_CURRENT      0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP    0x00
-#define RH_ENDPOINT_STALL          0x01
-
-#define RH_ACK                     0x01
-#define RH_REQ_ERR                 -1
-#define RH_NACK                    0x00
-
-
-/* OHCI ROOT HUB REGISTER MASKS */
- 
-/* roothub.portstatus [i] bits */
-#define RH_PS_CCS            0x00000001   	/* current connect status */
-#define RH_PS_PES            0x00000002   	/* port enable status*/
-#define RH_PS_PSS            0x00000004   	/* port suspend status */
-#define RH_PS_POCI           0x00000008   	/* port over current indicator */
-#define RH_PS_PRS            0x00000010  	/* port reset status */
-#define RH_PS_PPS            0x00000100   	/* port power status */
-#define RH_PS_LSDA           0x00000200    	/* low speed device attached */
-#define RH_PS_CSC            0x00010000 	/* connect status change */
-#define RH_PS_PESC           0x00020000   	/* port enable status change */
-#define RH_PS_PSSC           0x00040000    	/* port suspend status change */
-#define RH_PS_OCIC           0x00080000    	/* over current indicator change */
-#define RH_PS_PRSC           0x00100000   	/* port reset status change */
-
-/* roothub.status bits */
-#define RH_HS_LPS	     0x00000001		/* local power status */
-#define RH_HS_OCI	     0x00000002		/* over current indicator */
-#define RH_HS_DRWE	     0x00008000		/* device remote wakeup enable */
-#define RH_HS_LPSC	     0x00010000		/* local power status change */
-#define RH_HS_OCIC	     0x00020000		/* over current indicator change */
-#define RH_HS_CRWE	     0x80000000		/* clear remote wakeup enable */
-
-/* roothub.b masks */
-#define RH_B_DR		0x0000ffff		/* device removable flags */
-#define RH_B_PPCM	0xffff0000		/* port power control mask */
-
-/* roothub.a masks */
-#define	RH_A_NDP	(0xff << 0)		/* number of downstream ports */
-#define	RH_A_PSM	(1 << 8)		/* power switching mode */
-#define	RH_A_NPS	(1 << 9)		/* no power switching */
-#define	RH_A_DT		(1 << 10)		/* device type (mbz) */
-#define	RH_A_OCPM	(1 << 11)		/* over current protection mode */
-#define	RH_A_NOCP	(1 << 12)		/* no over current protection */
-#define	RH_A_POTPGT	(0xff << 24)		/* power on to power good time */
-
-/* urb */
-typedef struct 
-{
-	ed_t * ed;
-	__u16 length;	// number of tds associated with this request
-	__u16 td_cnt;	// number of tds already serviced
-	int   state;
-	wait_queue_head_t * wait;
-	td_t * td[0];	// list pointer to all corresponding TDs associated with this request
-
-} urb_priv_t;
-#define URB_DEL 1
-
-
-/* Hash struct used for TD/ED hashing */
-struct hash_t {
-	void		*virt;
-	dma_addr_t	dma;
-	struct hash_t	*next; // chaining for collision cases
-};
-
-/* List of TD/ED hash entries */
-struct hash_list_t {
-	struct hash_t	*head;
-	struct hash_t	*tail;
-};
-
-#define TD_HASH_SIZE    64    /* power'o'two */
-#define ED_HASH_SIZE    64    /* power'o'two */
-
-#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)
-#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE)
-
-
-/*
- * This is the full ohci controller description
- *
- * Note how the "proper" USB information is just
- * a subset of what the full implementation needs. (Linus)
- */
-
-
-typedef struct ohci {
-	struct ohci_hcca *hcca;		/* hcca */
-	dma_addr_t hcca_dma;
-
-	int irq;
-	int disabled;			/* e.g. got a UE, we're hung */
-	int sleeping;
-	atomic_t resume_count;		/* defending against multiple resumes */
-	unsigned long flags;		/* for HC bugs */
-#define	OHCI_QUIRK_AMD756	0x01		/* erratum #4 */
-
-	struct ohci_regs * regs;	/* OHCI controller's memory */
-	struct list_head ohci_hcd_list;	/* list of all ohci_hcd */
-
-	struct ohci * next; 		// chain of ohci device contexts
-	struct list_head timeout_list;
-	// struct list_head urb_list; 	// list of all pending urbs
-	// spinlock_t urb_list_lock; 	// lock to keep consistency 
-  
-	int ohci_int_load[32];		/* load of the 32 Interrupt Chains (for load balancing)*/
-	ed_t * ed_rm_list[2];     /* lists of all endpoints to be removed */
-	ed_t * ed_bulktail;       /* last endpoint of bulk list */
-	ed_t * ed_controltail;    /* last endpoint of control list */
- 	ed_t * ed_isotail;        /* last endpoint of iso list */
-	int intrstatus;
-	__u32 hc_control;		/* copy of the hc control reg */
-	struct usb_bus * bus;    
-	struct usb_device * dev[128];
-	struct virt_root_hub rh;
-
-	/* PCI device handle, settings, ... */
-	struct pci_dev	*ohci_dev;
-	u8		pci_latency;
-	struct pci_pool	*td_cache;
-	struct pci_pool	*dev_cache;
-	struct hash_list_t	td_hash[TD_HASH_SIZE];
-	struct hash_list_t	ed_hash[ED_HASH_SIZE];
-
-} ohci_t;
-
-#define NUM_EDS 32		/* num of preallocated endpoint descriptors */
-
-struct ohci_device {
-	ed_t 	ed[NUM_EDS];
-	dma_addr_t dma;
-	int ed_cnt;
-	wait_queue_head_t * wait;
-};
-
-// #define ohci_to_usb(ohci)	((ohci)->usb)
-#define usb_to_ohci(usb)	((struct ohci_device *)(usb)->hcpriv)
-
-/* hcd */
-/* endpoint */
-static int ep_link(ohci_t * ohci, ed_t * ed);
-static int ep_unlink(ohci_t * ohci, ed_t * ed);
-static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags);
-static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed);
-/* td */
-static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, struct urb * urb, int index);
-static void td_submit_urb(struct urb * urb);
-/* root hub */
-static int rh_submit_urb(struct urb * urb);
-static int rh_unlink_urb(struct urb * urb);
-static int rh_init_int_timer(struct urb * urb);
-
-/*-------------------------------------------------------------------------*/
-
-#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL)
-
-#ifdef DEBUG
-#	define OHCI_MEM_FLAGS	SLAB_POISON
-#else
-#	define OHCI_MEM_FLAGS	0
-#endif
- 
-#ifndef CONFIG_PCI
-#	error "usb-ohci currently requires PCI-based controllers"
-	/* to support non-PCI OHCIs, you need custom bus/mem/... glue */
-#endif
-
-
-/* Recover a TD/ED using its collision chain */
-static inline void *
-dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
-{
-	struct hash_t * scan = entry->head;
-	while (scan && scan->dma != dma)
-		scan = scan->next;
-	if (!scan)
-		BUG();
-	return scan->virt;
-}
-
-static inline struct ed *
-dma_to_ed (struct ohci * hc, dma_addr_t ed_dma)
-{
-	return (struct ed *) dma_to_ed_td(&(hc->ed_hash[ED_HASH_FUNC(ed_dma)]),
-				      ed_dma);
-}
-
-static inline struct td *
-dma_to_td (struct ohci * hc, dma_addr_t td_dma)
-{
-	return (struct td *) dma_to_ed_td(&(hc->td_hash[TD_HASH_FUNC(td_dma)]),
-				      td_dma);
-}
-
-/* Add a hash entry for a TD/ED; return true on success */
-static inline int
-hash_add_ed_td(struct hash_list_t * entry, void * virt, dma_addr_t dma)
-{
-	struct hash_t * scan;
-	
-	scan = (struct hash_t *)kmalloc(sizeof(struct hash_t), ALLOC_FLAGS);
-	if (!scan)
-		return 0;
-	
-	if (!entry->tail) {
-		entry->head = entry->tail = scan;
-	} else {
-		entry->tail->next = scan;
-		entry->tail = scan;
-	}
-	
-	scan->virt = virt;
-	scan->dma = dma;
-	scan->next = NULL;
-	return 1;
-}
-
-static inline int
-hash_add_ed (struct ohci * hc, struct ed * ed)
-{
-	return hash_add_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]),
-			ed, ed->dma);
-}
-
-static inline int
-hash_add_td (struct ohci * hc, struct td * td)
-{
-	return hash_add_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]),
-			td, td->td_dma);
-}
-
-
-static inline void
-hash_free_ed_td (struct hash_list_t * entry, void * virt)
-{
-	struct hash_t *scan, *prev;
-	scan = prev = entry->head;
-
-	// Find and unlink hash entry
-	while (scan && scan->virt != virt) {
-		prev = scan;
-		scan = scan->next;
-	}
-	if (scan) {
-		if (scan == entry->head) {
-			if (entry->head == entry->tail)
-				entry->head = entry->tail = NULL;
-			else
-				entry->head = scan->next;
-		} else if (scan == entry->tail) {
-			entry->tail = prev;
-			prev->next = NULL;
-		} else
-			prev->next = scan->next;
-		kfree(scan);
-	}
-}
-
-static inline void
-hash_free_ed (struct ohci * hc, struct ed * ed)
-{
-	hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed);
-}
-
-static inline void
-hash_free_td (struct ohci * hc, struct td * td)
-{
-	hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);
-}
-
-
-static int ohci_mem_init (struct ohci *ohci)
-{
-	ohci->td_cache = pci_pool_create ("ohci_td", ohci->ohci_dev,
-		sizeof (struct td),
-		32 /* byte alignment */,
-		0 /* no page-crossing issues */,
-		GFP_KERNEL | OHCI_MEM_FLAGS);
-	if (!ohci->td_cache)
-		return -ENOMEM;
-	ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev,
-		sizeof (struct ohci_device),
-		16 /* byte alignment */,
-		0 /* no page-crossing issues */,
-		GFP_KERNEL | OHCI_MEM_FLAGS);
-	if (!ohci->dev_cache)
-		return -ENOMEM;
-	return 0;
-}
-
-static void ohci_mem_cleanup (struct ohci *ohci)
-{
-	if (ohci->td_cache) {
-		pci_pool_destroy (ohci->td_cache);
-		ohci->td_cache = 0;
-	}
-	if (ohci->dev_cache) {
-		pci_pool_destroy (ohci->dev_cache);
-		ohci->dev_cache = 0;
-	}
-}
-
-/* TDs ... */
-static inline struct td *
-td_alloc (struct ohci *hc, int mem_flags)
-{
-	dma_addr_t	dma;
-	struct td	*td;
-
-	td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
-	if (td) {
-		td->td_dma = dma;
-
-		/* hash it for later reverse mapping */
-		if (!hash_add_td (hc, td)) {
-			pci_pool_free (hc->td_cache, td, dma);
-			return NULL;
-		}
-	}
-	return td;
-}
-
-static inline void
-td_free (struct ohci *hc, struct td *td)
-{
-	hash_free_td (hc, td);
-	pci_pool_free (hc->td_cache, td, td->td_dma);
-}
-
-
-/* DEV + EDs ... only the EDs need to be consistent */
-static inline struct ohci_device *
-dev_alloc (struct ohci *hc, int mem_flags)
-{
-	dma_addr_t		dma;
-	struct ohci_device	*dev;
-	int			i, offset;
-
-	dev = pci_pool_alloc (hc->dev_cache, mem_flags, &dma);
-	if (dev) {
-		memset (dev, 0, sizeof (*dev));
-		dev->dma = dma;
-		offset = ((char *)&dev->ed) - ((char *)dev);
-		for (i = 0; i < NUM_EDS; i++, offset += sizeof dev->ed [0])
-			dev->ed [i].dma = dma + offset;
-		/* add to hashtable if used */
-	}
-	return dev;
-}
-
-static inline void
-dev_free (struct ohci *hc, struct ohci_device *dev)
-{
-	pci_pool_free (hc->dev_cache, dev, dev->dma);
-}
-
diff -Nru a/drivers/usb/usb-uhci-debug.h b/drivers/usb/usb-uhci-debug.h
--- a/drivers/usb/usb-uhci-debug.h	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,141 +0,0 @@
-#ifdef DEBUG
-static void __attribute__((__unused__)) uhci_show_qh (puhci_desc_t qh)
-{
-	if (qh->type != QH_TYPE) {
-		dbg("qh has not QH_TYPE");
-		return;
-	}
-	dbg("QH @ %p/%08llX:", qh, (unsigned long long)qh->dma_addr);
-
-	if (qh->hw.qh.head & UHCI_PTR_TERM)
-		dbg("    Head Terminate");
-	else 
-		dbg("    Head: %s @ %08X",
-		    (qh->hw.qh.head & UHCI_PTR_QH?"QH":"TD"),
-		    qh->hw.qh.head & ~UHCI_PTR_BITS);
-
-	if (qh->hw.qh.element & UHCI_PTR_TERM)
-		dbg("    Element Terminate");
-	else 
-		dbg("    Element: %s @ %08X",
-		    (qh->hw.qh.element & UHCI_PTR_QH?"QH":"TD"),
-		    qh->hw.qh.element & ~UHCI_PTR_BITS);
-}
-#endif
-
-#if 0
-static void uhci_show_td (puhci_desc_t td)
-{
-	char *spid;
-	
-	switch (td->hw.td.info & 0xff) {
-	case USB_PID_SETUP:
-		spid = "SETUP";
-		break;
-	case USB_PID_OUT:
-		spid = " OUT ";
-		break;
-	case USB_PID_IN:
-		spid = " IN  ";
-		break;
-	default:
-		spid = "  ?  ";
-		break;
-	}
-
-	warn("  TD @ %p/%08X, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x",
-	     td, td->dma_addr,
-	     td->hw.td.info >> 21,
-	     ((td->hw.td.info >> 19) & 1),
-	     (td->hw.td.info >> 15) & 15,
-	     (td->hw.td.info >> 8) & 127,
-	     spid,
-	     td->hw.td.buffer);
-
-	warn("    Len=%02x e%d %s%s%s%s%s%s%s%s%s%s",
-	     td->hw.td.status & 0x7ff,
-	     ((td->hw.td.status >> 27) & 3),
-	     (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "",
-	     (td->hw.td.status & TD_CTRL_LS) ? "LS " : "",
-	     (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "",
-	     (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "",
-	     (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "",
-	     (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
-	     (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "",
-	     (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "",
-	     (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
-	     (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : ""
-		);
-
-	if (td->hw.td.link & UHCI_PTR_TERM)
-		warn("   TD Link Terminate");
-	else 
-		warn("    Link points to %s @ %08x, %s",
-		     (td->hw.td.link & UHCI_PTR_QH?"QH":"TD"),
-		     td->hw.td.link & ~UHCI_PTR_BITS,
-		     (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first"));
-}
-#endif
-
-#ifdef DEBUG
-static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
-{
-	dbg("  stat%d     =     %04x   %s%s%s%s%s%s%s%s",
-	     port,
-	     status,
-	     (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
-	     (status & USBPORTSC_PR) ? "PortReset " : "",
-	     (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
-	     (status & USBPORTSC_RD) ? "ResumeDetect " : "",
-	     (status & USBPORTSC_PEC) ? "EnableChange " : "",
-	     (status & USBPORTSC_PE) ? "PortEnabled " : "",
-	     (status & USBPORTSC_CSC) ? "ConnectChange " : "",
-	     (status & USBPORTSC_CCS) ? "PortConnected " : "");
-}
-
-void uhci_show_status (puhci_t s)
-{
-	unsigned int io_addr = s->io_addr;
-	unsigned short usbcmd, usbstat, usbint, usbfrnum;
-	unsigned int flbaseadd;
-	unsigned char sof;
-	unsigned short portsc1, portsc2;
-
-	usbcmd = inw (io_addr + 0);
-	usbstat = inw (io_addr + 2);
-	usbint = inw (io_addr + 4);
-	usbfrnum = inw (io_addr + 6);
-	flbaseadd = inl (io_addr + 8);
-	sof = inb (io_addr + 12);
-	portsc1 = inw (io_addr + 16);
-	portsc2 = inw (io_addr + 18);
-
-	dbg("  usbcmd    =     %04x   %s%s%s%s%s%s%s%s",
-	     usbcmd,
-	     (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
-	     (usbcmd & USBCMD_CF) ? "CF " : "",
-	     (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
-	     (usbcmd & USBCMD_FGR) ? "FGR " : "",
-	     (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
-	     (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
-	     (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
-	     (usbcmd & USBCMD_RS) ? "RS " : "");
-
-	dbg("  usbstat   =     %04x   %s%s%s%s%s%s",
-	     usbstat,
-	     (usbstat & USBSTS_HCH) ? "HCHalted " : "",
-	     (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
-	     (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
-	     (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
-	     (usbstat & USBSTS_ERROR) ? "USBError " : "",
-	     (usbstat & USBSTS_USBINT) ? "USBINT " : "");
-
-	dbg("  usbint    =     %04x", usbint);
-	dbg("  usbfrnum  =   (%d)%03x", (usbfrnum >> 10) & 1,
-	     0xfff & (4 * (unsigned int) usbfrnum));
-	dbg("  flbaseadd = %08x", flbaseadd);
-	dbg("  sof       =       %02x", sof);
-	uhci_show_sc (1, portsc1);
-	uhci_show_sc (2, portsc2);
-}
-#endif
diff -Nru a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
--- a/drivers/usb/usb-uhci.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,3163 +0,0 @@
-/* 
- * Universal Host Controller Interface driver for USB (take II).
- *
- * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar)
- *               Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
- *               Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
- *               Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter)
- * (c) 2000      Yggdrasil Computing, Inc. (port of new PCI interface support
- *               from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
- * (C) 2000      David Brownell, david-b@pacbell.net (usb-ohci.c)
- *          
- * HW-initalization based on material of
- *
- * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999 Johannes Erdfelt
- * (C) Copyright 1999 Randy Dunlap
- * (C) Copyright 1999 Gregory P. Smith
- *
- * $Id: usb-uhci.c,v 1.275 2002/01/19 20:57:33 acher Exp $
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/interrupt.h>	/* for in_interrupt() */
-#include <linux/init.h>
-#include <linux/version.h>
-#include <linux/pm.h>
-#include <linux/timer.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-/* This enables more detailed sanity checks in submit_iso */
-//#define ISO_SANITY_CHECK
-
-/* This enables debug printks */
-#define DEBUG
-
-/* This enables all symbols to be exported, to ease debugging oopses */
-//#define DEBUG_SYMBOLS
-
-/* This enables an extra UHCI slab for memory debugging */
-#define DEBUG_SLAB
-
-#define VERSTR "$Revision: 1.275 $ time " __TIME__ " " __DATE__
-
-#include <linux/usb.h>
-#include "hcd.h"
-#include "usb-uhci.h"
-#include "usb-uhci-debug.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.275"
-#define DRIVER_AUTHOR "Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
-#define DRIVER_DESC "USB Universal Host Controller Interface driver"
-
-#undef DEBUG
-#undef dbg
-#define dbg(format, arg...) do {} while (0)
-#define DEBUG_SYMBOLS
-#ifdef DEBUG_SYMBOLS
-	#define _static
-	#ifndef EXPORT_SYMTAB
-		#define EXPORT_SYMTAB
-	#endif
-#else
-	#define _static static
-#endif
-
-#define queue_dbg dbg //err
-#define async_dbg dbg //err
-
-#ifdef DEBUG_SLAB
-	static kmem_cache_t *urb_priv_kmem;
-#endif
-
-#define SLAB_FLAG     (in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL)
-
-/* CONFIG_USB_UHCI_HIGH_BANDWITH turns on Full Speed Bandwidth
- * Reclamation: feature that puts loop on descriptor loop when
- * there's some transfer going on. With FSBR, USB performance
- * is optimal, but PCI can be slowed down up-to 5 times, slowing down
- * system performance (eg. framebuffer devices).
- */
-#define CONFIG_USB_UHCI_HIGH_BANDWIDTH 
-
-/* *_DEPTH_FIRST puts descriptor in depth-first mode. This has
- * somehow similar effect to FSBR (higher speed), but does not
- * slow PCI down. OTOH USB performace is slightly slower than
- * in FSBR case and single device could hog whole USB, starving
- * other devices.
- */
-#define USE_CTRL_DEPTH_FIRST 0  // 0: Breadth first, 1: Depth first
-#define USE_BULK_DEPTH_FIRST 0  // 0: Breadth first, 1: Depth first
-
-/* Turning off both CONFIG_USB_UHCI_HIGH_BANDWITH and *_DEPTH_FIRST
- * will lead to <64KB/sec performance over USB for bulk transfers targeting
- * one device's endpoint. You probably do not want to do that.
- */
-
-// stop bandwidth reclamation after (roughly) 50ms
-#define IDLE_TIMEOUT  (HZ/20)
-
-// Suppress HC interrupt error messages for 5s
-#define ERROR_SUPPRESSION_TIME (HZ*5)
-
-_static int rh_submit_urb (struct urb *urb);
-_static int rh_unlink_urb (struct urb *urb);
-_static int delete_qh (uhci_t *s, uhci_desc_t *qh);
-_static int process_transfer (uhci_t *s, struct urb *urb, int mode);
-_static int process_interrupt (uhci_t *s, struct urb *urb);
-_static int process_iso (uhci_t *s, struct urb *urb, int force);
-
-// How much URBs with ->next are walked
-#define MAX_NEXT_COUNT 2048
-
-static uhci_t *devs = NULL;
-
-/* used by userspace UHCI data structure dumper */
-uhci_t **uhci_devices = &devs;
-
-/*-------------------------------------------------------------------*/
-// Cleans up collected QHs, but not more than 100 in one go
-void clean_descs(uhci_t *s, int force)
-{
-	struct list_head *q;
-	uhci_desc_t *qh;
-	int now=UHCI_GET_CURRENT_FRAME(s), n=0;
-
-	q=s->free_desc.prev;
-
-	while (q != &s->free_desc && (force || n<100)) {
-		qh = list_entry (q, uhci_desc_t, horizontal);		
-		q=qh->horizontal.prev;
-
-		if ((qh->last_used!=now) || force)
-			delete_qh(s,qh);
-		n++;
-	}
-}
-/*-------------------------------------------------------------------*/
-_static void uhci_switch_timer_int(uhci_t *s)
-{
-
-	if (!list_empty(&s->urb_unlinked))
-		set_td_ioc(s->td1ms);
-	else
-		clr_td_ioc(s->td1ms);
-
-	if (s->timeout_urbs)
-		set_td_ioc(s->td32ms);
-	else
-		clr_td_ioc(s->td32ms);
-	wmb();
-}
-/*-------------------------------------------------------------------*/
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
-_static void enable_desc_loop(uhci_t *s, struct urb *urb)
-{
-	int flags;
-
-	if (urb->transfer_flags & USB_NO_FSBR)
-		return;
-
-	spin_lock_irqsave (&s->qh_lock, flags);
-	s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM);
-	mb();
-	s->loop_usage++;
-	((urb_priv_t*)urb->hcpriv)->use_loop=1;
-	spin_unlock_irqrestore (&s->qh_lock, flags);
-}
-/*-------------------------------------------------------------------*/
-_static void disable_desc_loop(uhci_t *s, struct urb *urb)
-{
-	int flags;
-
-	if (urb->transfer_flags & USB_NO_FSBR)
-		return;
-
-	spin_lock_irqsave (&s->qh_lock, flags);
-	if (((urb_priv_t*)urb->hcpriv)->use_loop) {
-		s->loop_usage--;
-
-		if (!s->loop_usage) {
-			s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM);
-			mb();
-		}
-		((urb_priv_t*)urb->hcpriv)->use_loop=0;
-	}
-	spin_unlock_irqrestore (&s->qh_lock, flags);
-}
-#endif
-/*-------------------------------------------------------------------*/
-_static void queue_urb_unlocked (uhci_t *s, struct urb *urb)
-{
-	struct list_head *p=&urb->urb_list;
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
-	{
-		int type;
-		type=usb_pipetype (urb->pipe);
-
-		if ((type == PIPE_BULK) || (type == PIPE_CONTROL))
-			enable_desc_loop(s, urb);
-	}
-#endif
-	urb->status = -EINPROGRESS;
-	((urb_priv_t*)urb->hcpriv)->started=jiffies;
-	list_add (p, &s->urb_list);
-	if (urb->timeout)
-		s->timeout_urbs++;
-	uhci_switch_timer_int(s);
-}
-/*-------------------------------------------------------------------*/
-_static void queue_urb (uhci_t *s, struct urb *urb)
-{
-	unsigned long flags=0;
-
-	spin_lock_irqsave (&s->urb_list_lock, flags);
-	queue_urb_unlocked(s,urb);
-	spin_unlock_irqrestore (&s->urb_list_lock, flags);
-}
-/*-------------------------------------------------------------------*/
-_static void dequeue_urb (uhci_t *s, struct urb *urb)
-{
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
-	int type;
-
-	type=usb_pipetype (urb->pipe);
-
-	if ((type == PIPE_BULK) || (type == PIPE_CONTROL))
-		disable_desc_loop(s, urb);
-#endif
-
-	list_del (&urb->urb_list);
-	if (urb->timeout && s->timeout_urbs)
-		s->timeout_urbs--;
-
-}
-/*-------------------------------------------------------------------*/
-_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags)
-{
-	dma_addr_t dma_handle;
-
-	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
-	if (!*new)
-		return -ENOMEM;
-	memset (*new, 0, sizeof (uhci_desc_t));
-	(*new)->dma_addr = dma_handle;
-	set_td_link((*new), UHCI_PTR_TERM | (flags & UHCI_PTR_BITS));	// last by default
-	(*new)->type = TD_TYPE;
-	mb();
-	INIT_LIST_HEAD (&(*new)->vertical);
-	INIT_LIST_HEAD (&(*new)->horizontal);
-	
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-// append a qh to td.link physically, the SW linkage is not affected
-_static void append_qh(uhci_t *s, uhci_desc_t *td, uhci_desc_t* qh, int  flags)
-{
-	unsigned long xxx;
-	
-	spin_lock_irqsave (&s->td_lock, xxx);
-
-	set_td_link(td, qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH);
-       
-	mb();
-	spin_unlock_irqrestore (&s->td_lock, xxx);
-}
-/*-------------------------------------------------------------------*/
-/* insert td at last position in td-list of qh (vertical) */
-_static int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags)
-{
-	uhci_desc_t *prev;
-	unsigned long xxx;
-	
-	spin_lock_irqsave (&s->td_lock, xxx);
-
-	list_add_tail (&new->vertical, &qh->vertical);
-
-	prev = list_entry (new->vertical.prev, uhci_desc_t, vertical);
-
-	if (qh == prev ) {
-		// virgin qh without any tds
-		set_qh_element(qh, new->dma_addr | UHCI_PTR_TERM);
-	}
-	else {
-		// already tds inserted, implicitely remove TERM bit of prev
-		set_td_link(prev, new->dma_addr | (flags & UHCI_PTR_DEPTH));
-	}
-	mb();
-	spin_unlock_irqrestore (&s->td_lock, xxx);
-	
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-/* insert new_td after td (horizontal) */
-_static int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new)
-{
-	uhci_desc_t *next;
-	unsigned long flags;
-	
-	spin_lock_irqsave (&s->td_lock, flags);
-
-	next = list_entry (td->horizontal.next, uhci_desc_t, horizontal);
-	list_add (&new->horizontal, &td->horizontal);
-	new->hw.td.link = td->hw.td.link;
-	set_td_link(td, new->dma_addr);
-	mb();
-	spin_unlock_irqrestore (&s->td_lock, flags);	
-	
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-_static int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink)
-{
-	uhci_desc_t *next, *prev;
-	int dir = 0;
-	unsigned long flags;
-	
-	spin_lock_irqsave (&s->td_lock, flags);
-	
-	next = list_entry (element->vertical.next, uhci_desc_t, vertical);
-	
-	if (next == element) {
-		dir = 1;
-		prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
-	}
-	else 
-		prev = list_entry (element->vertical.prev, uhci_desc_t, vertical);
-	
-	if (phys_unlink) {
-		// really remove HW linking
-		if (prev->type == TD_TYPE)
-			prev->hw.td.link = element->hw.td.link;
-		else
-			prev->hw.qh.element = element->hw.td.link;
-	}
-
-	mb ();
-
-	if (dir == 0)
-		list_del (&element->vertical);
-	else
-		list_del (&element->horizontal);
-	
-	spin_unlock_irqrestore (&s->td_lock, flags);	
-	
-	return 0;
-}
-
-/*-------------------------------------------------------------------*/
-_static int delete_desc (uhci_t *s, uhci_desc_t *element)
-{
-	pci_pool_free(s->desc_pool, element, element->dma_addr);
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-// Allocates qh element
-_static int alloc_qh (uhci_t *s, uhci_desc_t ** new)
-{
-	dma_addr_t dma_handle;
-
-	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
-	if (!*new)
-		return -ENOMEM;
-	memset (*new, 0, sizeof (uhci_desc_t));
-	(*new)->dma_addr = dma_handle;
-	set_qh_head(*new, UHCI_PTR_TERM);
-	set_qh_element(*new, UHCI_PTR_TERM);
-	(*new)->type = QH_TYPE;
-	
-	mb();
-	INIT_LIST_HEAD (&(*new)->horizontal);
-	INIT_LIST_HEAD (&(*new)->vertical);
-	
-	dbg("Allocated qh @ %p", *new);
-	
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-// inserts new qh before/after the qh at pos
-// flags: 0: insert before pos, 1: insert after pos (for low speed transfers)
-_static int insert_qh (uhci_t *s, uhci_desc_t *pos, uhci_desc_t *new, int order)
-{
-	uhci_desc_t *old;
-	unsigned long flags;
-
-	spin_lock_irqsave (&s->qh_lock, flags);
-
-	if (!order) {
-		// (OLD) (POS) -> (OLD) (NEW) (POS)
-		old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal);
-		list_add_tail (&new->horizontal, &pos->horizontal);
-		set_qh_head(new, MAKE_QH_ADDR (pos)) ;
-		if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM)))
-			set_qh_head(old, MAKE_QH_ADDR (new)) ;
-	}
-	else {
-		// (POS) (OLD) -> (POS) (NEW) (OLD)
-		old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal);
-		list_add (&new->horizontal, &pos->horizontal);
-		set_qh_head(new, MAKE_QH_ADDR (old));
-		set_qh_head(pos, MAKE_QH_ADDR (new)) ;
-	}
-
-	mb ();
-	
-	spin_unlock_irqrestore (&s->qh_lock, flags);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------*/
-_static int unlink_qh (uhci_t *s, uhci_desc_t *element)
-{
-	uhci_desc_t  *prev;
-	unsigned long flags;
-
-	spin_lock_irqsave (&s->qh_lock, flags);
-	
-	prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal);
-	prev->hw.qh.head = element->hw.qh.head;
-
-	dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, 
-	    list_entry (element->horizontal.next, uhci_desc_t, horizontal),le32_to_cpu(element->hw.qh.head) &~15);
-	
-	list_del(&element->horizontal);
-
-	mb ();
-	spin_unlock_irqrestore (&s->qh_lock, flags);
-	
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-_static int delete_qh (uhci_t *s, uhci_desc_t *qh)
-{
-	uhci_desc_t *td;
-	struct list_head *p;
-	
-	list_del (&qh->horizontal);
-
-	while ((p = qh->vertical.next) != &qh->vertical) {
-		td = list_entry (p, uhci_desc_t, vertical);
-		dbg("unlink td @ %p",td);
-		unlink_td (s, td, 0); // no physical unlink
-		delete_desc (s, td);
-	}
-
-	delete_desc (s, qh);
-	
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-_static void clean_td_chain (uhci_t *s, uhci_desc_t *td)
-{
-	struct list_head *p;
-	uhci_desc_t *td1;
-
-	if (!td)
-		return;
-	
-	while ((p = td->horizontal.next) != &td->horizontal) {
-		td1 = list_entry (p, uhci_desc_t, horizontal);
-		delete_desc (s, td1);
-	}
-	
-	delete_desc (s, td);
-}
-
-/*-------------------------------------------------------------------*/
-_static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer)
-{
-	td->hw.td.status = cpu_to_le32(status);
-	td->hw.td.info = cpu_to_le32(info);
-	td->hw.td.buffer = cpu_to_le32(buffer);
-}
-/*-------------------------------------------------------------------*/
-// Removes ALL qhs in chain (paranoia!)
-_static void cleanup_skel (uhci_t *s)
-{
-	unsigned int n;
-	uhci_desc_t *td;
-
-	dbg("cleanup_skel");
-
-	clean_descs(s,1);
-
-	
-	if (s->td32ms) {
-	
-		unlink_td(s,s->td32ms,1);
-		delete_desc(s, s->td32ms);
-	}
-
-	for (n = 0; n < 8; n++) {
-		td = s->int_chain[n];
-		clean_td_chain (s, td);
-	}
-
-	if (s->iso_td) {
-		for (n = 0; n < 1024; n++) {
-			td = s->iso_td[n];
-			clean_td_chain (s, td);
-		}
-		kfree (s->iso_td);
-	}
-
-	if (s->framelist)
-		pci_free_consistent(s->uhci_pci, PAGE_SIZE,
-				    s->framelist, s->framelist_dma);
-
-	if (s->control_chain) {
-		// completed init_skel?
-		struct list_head *p;
-		uhci_desc_t *qh, *qh1;
-
-		qh = s->control_chain;
-		while ((p = qh->horizontal.next) != &qh->horizontal) {
-			qh1 = list_entry (p, uhci_desc_t, horizontal);
-			delete_qh (s, qh1);
-		}
-
-		delete_qh (s, qh);
-	}
-	else {
-		if (s->ls_control_chain)
-			delete_desc (s, s->ls_control_chain);
-		if (s->control_chain)
-			delete_desc (s, s->control_chain);
-		if (s->bulk_chain)
-			delete_desc (s, s->bulk_chain);
-		if (s->chain_end)
-			delete_desc (s, s->chain_end);
-	}
-
-	if (s->desc_pool) {
-		pci_pool_destroy(s->desc_pool);
-		s->desc_pool = NULL;
-	}
-
-	dbg("cleanup_skel finished");	
-}
-/*-------------------------------------------------------------------*/
-// allocates framelist and qh-skeletons
-// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT)
-_static int init_skel (uhci_t *s)
-{
-	int n, ret;
-	uhci_desc_t *qh, *td;
-	
-	dbg("init_skel");
-	
-	s->framelist = pci_alloc_consistent(s->uhci_pci, PAGE_SIZE,
-					    &s->framelist_dma);
-
-	if (!s->framelist)
-		return -ENOMEM;
-
-	memset (s->framelist, 0, 4096);
-
-	dbg("creating descriptor pci_pool");
-
-	s->desc_pool = pci_pool_create("uhci_desc", s->uhci_pci,
-				       sizeof(uhci_desc_t), 16, 0,
-				       GFP_DMA | GFP_ATOMIC);	
-	if (!s->desc_pool)
-		goto init_skel_cleanup;
-
-	dbg("allocating iso desc pointer list");
-	s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL);
-	
-	if (!s->iso_td)
-		goto init_skel_cleanup;
-
-	s->ls_control_chain = NULL;
-	s->control_chain = NULL;
-	s->bulk_chain = NULL;
-	s->chain_end = NULL;
-
-	dbg("allocating iso descs");
-	for (n = 0; n < 1024; n++) {
-	 	// allocate skeleton iso/irq-tds
-		if (alloc_td (s, &td, 0))
-			goto init_skel_cleanup;
-
-		s->iso_td[n] = td;
-		s->framelist[n] = cpu_to_le32((__u32) td->dma_addr);
-	}
-
-	dbg("allocating qh: chain_end");
-	if (alloc_qh (s, &qh))	
-		goto init_skel_cleanup;
-				
-	s->chain_end = qh;
-
-	if (alloc_td (s, &td, 0))
-		goto init_skel_cleanup;
-	
-	fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
-	insert_td (s, qh, td, 0);
-	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // remove TERM bit
-	s->td1ms=td;
-
-	dbg("allocating qh: bulk_chain");
-	if (alloc_qh (s, &qh))
-		goto init_skel_cleanup;
-	
-	insert_qh (s, s->chain_end, qh, 0);
-	s->bulk_chain = qh;
-
-	dbg("allocating qh: control_chain");
-	ret = alloc_qh (s, &qh);
-	if (ret)
-		goto init_skel_cleanup;
-	
-	insert_qh (s, s->bulk_chain, qh, 0);
-	s->control_chain = qh;
-
-#ifdef	CONFIG_USB_UHCI_HIGH_BANDWIDTH
-	// disabled reclamation loop
-	set_qh_head(s->chain_end, s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM);
-#endif
-
-	dbg("allocating qh: ls_control_chain");
-	if (alloc_qh (s, &qh))
-		goto init_skel_cleanup;
-	
-	insert_qh (s, s->control_chain, qh, 0);
-	s->ls_control_chain = qh;
-
-	for (n = 0; n < 8; n++)
-		s->int_chain[n] = 0;
-
-	dbg("allocating skeleton INT-TDs");
-	
-	for (n = 0; n < 8; n++) {
-		uhci_desc_t *td;
-
-		if (alloc_td (s, &td, 0))
-			goto init_skel_cleanup;
-
-		s->int_chain[n] = td;
-		if (n == 0) {
-			set_td_link(s->int_chain[0], s->ls_control_chain->dma_addr | UHCI_PTR_QH);
-		}
-		else {
-			set_td_link(s->int_chain[n], s->int_chain[0]->dma_addr);
-		}
-	}
-
-	dbg("Linking skeleton INT-TDs");
-	
-	for (n = 0; n < 1024; n++) {
-		// link all iso-tds to the interrupt chains
-		int m, o;
-		dbg("framelist[%i]=%x",n,le32_to_cpu(s->framelist[n]));
-		if ((n&127)==127) 
-			((uhci_desc_t*) s->iso_td[n])->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr);
-		else 
-			for (o = 1, m = 2; m <= 128; o++, m += m)
-				if ((n & (m - 1)) == ((m - 1) / 2))
-					set_td_link(((uhci_desc_t*) s->iso_td[n]), s->int_chain[o]->dma_addr);
-	}
-
-	if (alloc_td (s, &td, 0))
-		goto init_skel_cleanup;
-	
-	fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 32ms interrupt (activated later)
-	s->td32ms=td;
-
-	insert_td_horizontal (s, s->int_chain[5], td);
-
-	mb();
-	dbg("init_skel exit");
-	return 0;
-
-      init_skel_cleanup:
-	cleanup_skel (s);
-	return -ENOMEM;
-}
-
-/*-------------------------------------------------------------------*/
-//                         LOW LEVEL STUFF
-//          assembles QHs und TDs for control, bulk and iso
-/*-------------------------------------------------------------------*/
-_static int uhci_submit_control_urb (struct urb *urb)
-{
-	uhci_desc_t *qh, *td;
-	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv;
-	unsigned long destination, status;
-	int maxsze = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));
-	unsigned long len;
-	char *data;
-	int depth_first=USE_CTRL_DEPTH_FIRST;  // UHCI descriptor chasing method
-
-	dbg("uhci_submit_control start");
-	if (alloc_qh (s, &qh))		// alloc qh for this request
-		return -ENOMEM;
-
-	if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first))		// get td for setup stage
-	{
-		delete_qh (s, qh);
-		return -ENOMEM;
-	}
-
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
-
-	/* 3 errors */
-	status = TD_CTRL_ACTIVE
-		| (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD)
-		| (3 << 27);
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-
-	/*  Build the TD for the control request, try forever, 8 bytes of data */
-	fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma);
-
-	insert_td (s, qh, td, 0);	// queue 'setup stage'-td in qh
-#if 0
-	{
-		char *sp=urb->setup_packet;
-		dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", urb->pipe,
-		    sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]);
-	}
-	//uhci_show_td(td);
-#endif
-
-	len = urb->transfer_buffer_length;
-	data = urb->transfer_buffer;
-
-	/* If direction is "send", change the frame from SETUP (0x2D)
-	   to OUT (0xE1). Else change it from SETUP to IN (0x69). */
-
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | (usb_pipeout (urb->pipe)?USB_PID_OUT:USB_PID_IN);
-
-	while (len > 0) {
-		int pktsze = len;
-
-		if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first))
-			goto fail_unmap_enomem;
-
-		if (pktsze > maxsze)
-			pktsze = maxsze;
-
-		destination ^= 1 << TD_TOKEN_TOGGLE;	// toggle DATA0/1
-
-		// Status, pktsze bytes of data
-		fill_td (td, status, destination | ((pktsze - 1) << 21),
-			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
-
-		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue 'data stage'-td in qh
-
-		data += pktsze;
-		len -= pktsze;
-	}
-
-	/* Build the final TD for control status */
-	/* It's only IN if the pipe is out AND we aren't expecting data */
-
-	destination &= ~UHCI_PID;
-
-	if (usb_pipeout (urb->pipe) || (urb->transfer_buffer_length == 0))
-		destination |= USB_PID_IN;
-	else
-		destination |= USB_PID_OUT;
-
-	destination |= 1 << TD_TOKEN_TOGGLE;	/* End in Data1 */
-
-	if (alloc_td (s, &td, UHCI_PTR_DEPTH))
-		goto fail_unmap_enomem;
-
-	status &=~TD_CTRL_SPD;
-
-	/* no limit on errors on final packet , 0 bytes of data */
-	fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),
-		 0);
-
-	insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue status td
-
-	list_add (&qh->desc_list, &urb_priv->desc_list);
-
-	queue_urb (s, urb);	// queue before inserting in desc chain
-
-	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);
-
-	/* Start it up... put low speed first */
-	if (urb->dev->speed == USB_SPEED_LOW)
-		insert_qh (s, s->control_chain, qh, 0);
-	else
-		insert_qh (s, s->bulk_chain, qh, 0);
-
-	dbg("uhci_submit_control end");
-	return 0;
-
-fail_unmap_enomem:
-	delete_qh(s, qh);
-	return -ENOMEM;
-}
-/*-------------------------------------------------------------------*/
-// For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh)
-// Due to the linking with other bulk urbs, it has to be locked with urb_list_lock!
-
-_static int uhci_submit_bulk_urb (struct urb *urb, struct urb *bulk_urb)
-{
-	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL;
-	uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL;
-	unsigned long destination, status;
-	char *data;
-	unsigned int pipe = urb->pipe;
-	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
-	int info, len, last;
-	int depth_first=USE_BULK_DEPTH_FIRST;  // UHCI descriptor chasing method
-
-	if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)))
-		return -EPIPE;
-
-	queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i",
-		  urb,bulk_urb,urb->pipe,urb->transfer_buffer_length);
-
-	upriv = (urb_priv_t*)urb->hcpriv;
-
-	if (!bulk_urb) {
-		if (alloc_qh (s, &qh))		// get qh for this request
-			return -ENOMEM;
-
-		if (urb->transfer_flags & USB_QUEUE_BULK) {
-			if (alloc_qh(s, &nqh)) // placeholder for clean unlink
-			{
-				delete_desc (s, qh);
-				return -ENOMEM;
-			}
-			upriv->next_qh = nqh;
-			queue_dbg("new next qh %p",nqh);
-		}
-	}
-	else { 
-		bpriv = (urb_priv_t*)bulk_urb->hcpriv;
-		qh = bpriv->bottom_qh;  // re-use bottom qh and next qh
-		nqh = bpriv->next_qh;
-		upriv->next_qh=nqh;	
-		upriv->prev_queued_urb=bulk_urb;
-	}
-
-	if (urb->transfer_flags & USB_QUEUE_BULK) {
-		if (alloc_qh (s, &bqh))  // "bottom" QH
-		{
-			if (!bulk_urb) { 
-				delete_desc(s, qh);
-				delete_desc(s, nqh);
-			}
-			return -ENOMEM;
-		}
-		set_qh_element(bqh, UHCI_PTR_TERM);
-		set_qh_head(bqh, nqh->dma_addr | UHCI_PTR_QH); // element
-		upriv->bottom_qh = bqh;
-	}
-	queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh);
-
-	/* The "pipe" thing contains the destination in bits 8--18. */
-	destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
-
-	/* 3 errors */
-	status = TD_CTRL_ACTIVE
-		| ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD)
-		| (3 << 27);
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-
-	/* Build the TDs for the bulk request */
-	len = urb->transfer_buffer_length;
-	data = urb->transfer_buffer;
-	
-	do {					// TBD: Really allow zero-length packets?
-		int pktsze = len;
-
-		if (alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first))
-		{
-			delete_qh (s, qh);
-			return -ENOMEM;
-		}
-
-		if (pktsze > maxsze)
-			pktsze = maxsze;
-
-		// pktsze bytes of data 
-		info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
-			(usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
-
-		fill_td (td, status, info,
-			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
-
-		data += pktsze;
-		len -= pktsze;
-		// Use USB_ZERO_PACKET to finish bulk OUTs always with a zero length packet
-		last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET)));
-
-		if (last)
-			set_td_ioc(td);	// last one generates INT
-
-		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);
-		if (!first_td)
-			first_td=td;
-		usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
-
-	} while (!last);
-
-	if (bulk_urb && bpriv)   // everything went OK, link with old bulk URB
-		bpriv->next_queued_urb=urb;
-
-	list_add (&qh->desc_list, &urb_priv->desc_list);
-
-	if (urb->transfer_flags & USB_QUEUE_BULK)
-		append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first);
-
-	queue_urb_unlocked (s, urb);
-	
-	if (urb->transfer_flags & USB_QUEUE_BULK)
-		set_qh_element(qh, first_td->dma_addr);
-	else
-		qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);    // arm QH
-
-	if (!bulk_urb) { 					// new bulk queue	
-		if (urb->transfer_flags & USB_QUEUE_BULK) {
-			spin_lock (&s->td_lock);		// both QHs in one go
-			insert_qh (s, s->chain_end, qh, 0);	// Main QH
-			insert_qh (s, s->chain_end, nqh, 0);	// Helper QH
-			spin_unlock (&s->td_lock);
-		}
-		else
-			insert_qh (s, s->chain_end, qh, 0);
-	}
-	
-	//dbg("uhci_submit_bulk_urb: exit\n");
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-_static void uhci_clean_iso_step1(uhci_t *s, urb_priv_t *urb_priv)
-{
-	struct list_head *p;
-	uhci_desc_t *td;
-
-	for (p = urb_priv->desc_list.next; p != &urb_priv->desc_list; p = p->next) {
-				td = list_entry (p, uhci_desc_t, desc_list);
-				unlink_td (s, td, 1);
-	}
-}
-/*-------------------------------------------------------------------*/
-_static void uhci_clean_iso_step2(uhci_t *s, urb_priv_t *urb_priv)
-{
-	struct list_head *p;
-	uhci_desc_t *td;
-
-	while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
-				td = list_entry (p, uhci_desc_t, desc_list);
-				list_del (p);
-				delete_desc (s, td);
-	}
-}
-/*-------------------------------------------------------------------*/
-/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink)
-         CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark)
-         CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink)
- looks a bit complicated because of all the bulk queueing goodies
-*/
-
-_static void uhci_clean_transfer (uhci_t *s, struct urb *urb, uhci_desc_t *qh, int mode)
-{
-	uhci_desc_t *bqh, *nqh, *prevqh, *prevtd;
-	int now;
-	urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
-
-	now=UHCI_GET_CURRENT_FRAME(s);
-
-	bqh=priv->bottom_qh;	
-	
-	if (!priv->next_queued_urb)  { // no more appended bulk queues
-
-		queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p", urb, qh, bqh, priv->next_qh);	
-	
-		if (priv->prev_queued_urb && mode != CLEAN_TRANSFER_DELETION_MARK) {  // qh not top of the queue
-				unsigned long flags; 
-				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
-
-				spin_lock_irqsave (&s->qh_lock, flags);
-				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
-				prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical);
-				set_td_link(prevtd, priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh
-				mb();
-				queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd);
-				spin_unlock_irqrestore (&s->qh_lock, flags);
-
-				ppriv->bottom_qh = priv->bottom_qh;
-				ppriv->next_queued_urb = NULL;
-			}
-		else {   // queue is dead, qh is top of the queue
-			
-			if (mode != CLEAN_TRANSFER_DELETION_MARK) 				
-				unlink_qh(s, qh); // remove qh from horizontal chain
-
-			if (bqh) {  // remove remainings of bulk queue
-				nqh=priv->next_qh;
-
-				if (mode != CLEAN_TRANSFER_DELETION_MARK) 
-					unlink_qh(s, nqh);  // remove nqh from horizontal chain
-				
-				if (mode != CLEAN_TRANSFER_NO_DELETION) {  // add helper QHs to free desc list
-					nqh->last_used = bqh->last_used = now;
-					list_add_tail (&nqh->horizontal, &s->free_desc);
-					list_add_tail (&bqh->horizontal, &s->free_desc);
-				}			
-			}
-		}
-	}
-	else { // there are queued urbs following
-	
-	  queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p",
-		       urb, priv->prev_queued_urb,  priv->next_queued_urb, qh, bqh, priv->next_qh);	
-       	
-		if (mode != CLEAN_TRANSFER_DELETION_MARK) {	// no work for cleanup at unlink-completion
-			struct urb *nurb;
-			unsigned long flags;
-
-			nurb = priv->next_queued_urb;
-			spin_lock_irqsave (&s->qh_lock, flags);		
-
-			if (!priv->prev_queued_urb) { // top QH
-				
-				prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal);
-				set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH);
-				list_del (&qh->horizontal);  // remove this qh form horizontal chain
-				list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain
-			}
-			else {		// intermediate QH
-				urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv;
-				urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv;
-				uhci_desc_t * bnqh;
-				
-				bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list);
-				ppriv->bottom_qh = bnqh;
-				ppriv->next_queued_urb = nurb;				
-				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
-				set_qh_head(prevqh, bqh->dma_addr | UHCI_PTR_QH);
-			}
-
-			mb();
-			((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb;
-			spin_unlock_irqrestore (&s->qh_lock, flags);
-		}		
-	}
-
-	if (mode != CLEAN_TRANSFER_NO_DELETION) {
-		qh->last_used = now;	
-		list_add_tail (&qh->horizontal, &s->free_desc); // mark qh for later deletion/kfree
-	}
-}
-/*-------------------------------------------------------------------*/
-// Release bandwidth for Interrupt or Isoc. transfers 
-_static void uhci_release_bandwidth(struct urb *urb)
-{       
-	if (urb->bandwidth) {
-		switch (usb_pipetype(urb->pipe)) {
-		case PIPE_INTERRUPT:
-			usb_release_bandwidth (urb->dev, urb, 0);
-			break;
-		case PIPE_ISOCHRONOUS:
-			usb_release_bandwidth (urb->dev, urb, 1);
-			break;
-		default:
-			break;
-		}
-	}	
-}
-
-_static void uhci_urb_dma_sync(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv)
-{
-	if (urb_priv->setup_packet_dma)
-		pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma,
-				    sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-
-	if (urb_priv->transfer_buffer_dma)
-		pci_dma_sync_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
-				    urb->transfer_buffer_length,
-				    usb_pipein(urb->pipe) ?
-				    PCI_DMA_FROMDEVICE :
-				    PCI_DMA_TODEVICE);
-}
-
-_static void uhci_urb_dma_unmap(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv)
-{
-	if (urb_priv->setup_packet_dma) {
-		pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma,
-				 sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-		urb_priv->setup_packet_dma = 0;
-	}
-	if (urb_priv->transfer_buffer_dma) {
-		pci_unmap_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
-				 urb->transfer_buffer_length,
-				 usb_pipein(urb->pipe) ?
-				 PCI_DMA_FROMDEVICE :
-				 PCI_DMA_TODEVICE);
-		urb_priv->transfer_buffer_dma = 0;
-	}
-}
-/*-------------------------------------------------------------------*/
-/* needs urb_list_lock!
-   mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list
-         UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list
-*/
-_static int uhci_unlink_urb_async (uhci_t *s, struct urb *urb, int mode)
-{
-	uhci_desc_t *qh;
-	urb_priv_t *urb_priv;
-	
-	async_dbg("unlink_urb_async called %p",urb);
-
-	if ((urb->status == -EINPROGRESS) ||
-	    ((usb_pipetype (urb->pipe) ==  PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags))
-	{
-		((urb_priv_t*)urb->hcpriv)->started = ~0;  // mark
-		dequeue_urb (s, urb);
-
-		if (mode==UNLINK_ASYNC_STORE_URB)
-			list_add_tail (&urb->urb_list, &s->urb_unlinked); // store urb
-
-		uhci_switch_timer_int(s);
-       		s->unlink_urb_done = 1;
-		uhci_release_bandwidth(urb);
-
-		urb->status = -ECONNABORTED;	// mark urb as "waiting to be killed"	
-		urb_priv = (urb_priv_t*)urb->hcpriv;
-
-		switch (usb_pipetype (urb->pipe)) {
-		case PIPE_INTERRUPT:
-			usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
-
-		case PIPE_ISOCHRONOUS:
-			uhci_clean_iso_step1 (s, urb_priv);
-			break;
-
-		case PIPE_BULK:
-		case PIPE_CONTROL:
-			qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
-			uhci_clean_transfer (s, urb, qh, CLEAN_TRANSFER_NO_DELETION);
-			break;
-		}
-		((urb_priv_t*)urb->hcpriv)->started = UHCI_GET_CURRENT_FRAME(s);
-		return -EINPROGRESS;  // completion will follow
-	}		
-
-	return 0;    // URB already dead
-}
-/*-------------------------------------------------------------------*/
-// kills an urb by unlinking descriptors and waiting for at least one frame
-_static int uhci_unlink_urb_sync (uhci_t *s, struct urb *urb)
-{
-	uhci_desc_t *qh;
-	urb_priv_t *urb_priv;
-	unsigned long flags=0;
-	struct usb_device *usb_dev;
-
-	spin_lock_irqsave (&s->urb_list_lock, flags);
-
-	if (urb->status == -EINPROGRESS) {
-
-		// move descriptors out the the running chains, dequeue urb
-		uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_DONT_STORE);
-
-		urb_priv = urb->hcpriv;
-		urb->status = -ENOENT;	// prevent from double deletion after unlock		
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
-		
-		// cleanup the rest
-		switch (usb_pipetype (urb->pipe)) {
-
-		case PIPE_INTERRUPT:
-		case PIPE_ISOCHRONOUS:
-			uhci_wait_ms(1);
-			uhci_clean_iso_step2(s, urb_priv);
-			break;
-
-		case PIPE_BULK:
-		case PIPE_CONTROL:
-			qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list);
-			uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK);
-			uhci_wait_ms(1);
-		}
-		urb->status = -ENOENT;	// mark urb as killed		
-					
-		uhci_urb_dma_unmap(s, urb, urb->hcpriv);
-
-#ifdef DEBUG_SLAB
-		kmem_cache_free (urb_priv_kmem, urb->hcpriv);
-#else
-		kfree (urb->hcpriv);
-#endif
-		usb_dev = urb->dev;
-		if (urb->complete) {
-			dbg("unlink_urb: calling completion");
-			urb->dev = NULL;
-			urb->complete ((struct urb *) urb);
-		}
-		usb_dec_dev_use (usb_dev);
-		usb_put_urb (urb);
-	}
-	else
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
-
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-// async unlink_urb completion/cleanup work
-// has to be protected by urb_list_lock!
-// features: if set in transfer_flags, the resulting status of the killed
-// transaction is not overwritten
-
-_static void uhci_cleanup_unlink(uhci_t *s, int force)
-{
-	struct list_head *q;
-	struct urb *urb;
-	struct usb_device *dev;
-	int now, type;
-	urb_priv_t *urb_priv;
-
-	q=s->urb_unlinked.next;
-	now=UHCI_GET_CURRENT_FRAME(s);
-
-	while (q != &s->urb_unlinked) {
-
-		urb = list_entry (q, struct urb, urb_list);
-
-		urb_priv = (urb_priv_t*)urb->hcpriv;
-		q = urb->urb_list.next;
-		
-		if (!urb_priv) // avoid crash when URB is corrupted
-			break;
-			
-		if (force || ((urb_priv->started != ~0) && (urb_priv->started != now))) {
-			async_dbg("async cleanup %p",urb);
-			type=usb_pipetype (urb->pipe);
-
-			switch (type) { // process descriptors
-			case PIPE_CONTROL:
-				process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK);  // don't unlink (already done)
-				break;
-			case PIPE_BULK:
-				if (!s->avoid_bulk.counter)
-					process_transfer (s, urb, CLEAN_TRANSFER_DELETION_MARK); // don't unlink (already done)
-				else
-					continue;
-				break;
-			case PIPE_ISOCHRONOUS:
-				process_iso (s, urb, PROCESS_ISO_FORCE); // force, don't unlink
-				break;
-			case PIPE_INTERRUPT:
-				process_interrupt (s, urb);
-				break;
-			}
-
-			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
-		  		urb->status = -ECONNRESET; // mark as asynchronously killed
-
-			dev = urb->dev;	// completion may destroy all...
-			urb_priv = urb->hcpriv;
-			list_del (&urb->urb_list);
-			
-			uhci_urb_dma_sync(s, urb, urb_priv);
-			if (urb->complete) {
-				spin_unlock(&s->urb_list_lock);
-				urb->dev = NULL;
-				urb->complete ((struct urb *) urb);
-				spin_lock(&s->urb_list_lock);
-			}
-
-			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
-				urb->status = -ENOENT;  // now the urb is really dead
-
-			switch (type) {
-			case PIPE_ISOCHRONOUS:
-			case PIPE_INTERRUPT:
-				uhci_clean_iso_step2(s, urb_priv);
-				break;
-			}
-	
-			uhci_urb_dma_unmap(s, urb, urb_priv);
-
-			usb_dec_dev_use (dev);
-#ifdef DEBUG_SLAB
-			kmem_cache_free (urb_priv_kmem, urb_priv);
-#else
-			kfree (urb_priv);
-#endif
-			usb_put_urb (urb);
-		}
-	}
-}
- 
-/*-------------------------------------------------------------------*/
-_static int uhci_unlink_urb (struct urb *urb)
-{
-	uhci_t *s;
-	unsigned long flags=0;
-	dbg("uhci_unlink_urb called for %p",urb);
-	if (!urb || !urb->dev)		// you never know...
-		return -EINVAL;
-	
-	s = (uhci_t*) urb->dev->bus->hcpriv;
-
-	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
-		return rh_unlink_urb (urb);
-
-	if (!urb->hcpriv)
-		return -EINVAL;
-
-	if (urb->transfer_flags & USB_ASYNC_UNLINK) {
-		int ret;
-       		spin_lock_irqsave (&s->urb_list_lock, flags);
-       		
-		uhci_release_bandwidth(urb);
-		ret = uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
-
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);	
-		return ret;
-	}
-	else
-		return uhci_unlink_urb_sync(s, urb);
-}
-/*-------------------------------------------------------------------*/
-// In case of ASAP iso transfer, search the URB-list for already queued URBs
-// for this EP and calculate the earliest start frame for the new
-// URB (easy seamless URB continuation!)
-_static int find_iso_limits (struct urb *urb, unsigned int *start, unsigned int *end)
-{
-	struct urb *u, *last_urb = NULL;
-	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	struct list_head *p;
-	int ret=-1;
-	unsigned long flags;
-	
-	spin_lock_irqsave (&s->urb_list_lock, flags);
-	p=s->urb_list.prev;
-
-	for (; p != &s->urb_list; p = p->prev) {
-		u = list_entry (p, struct urb, urb_list);
-		// look for pending URBs with identical pipe handle
-		// works only because iso doesn't toggle the data bit!
-		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS)) {
-			if (!last_urb)
-				*start = u->start_frame;
-			last_urb = u;
-		}
-	}
-	
-	if (last_urb) {
-		*end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
-		ret=0;
-	}
-	
-	spin_unlock_irqrestore(&s->urb_list_lock, flags);
-	
-	return ret;
-}
-/*-------------------------------------------------------------------*/
-// adjust start_frame according to scheduling constraints (ASAP etc)
-
-_static int iso_find_start (struct urb *urb)
-{
-	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	unsigned int now;
-	unsigned int start_limit = 0, stop_limit = 0, queued_size;
-	int limits;
-
-	now = UHCI_GET_CURRENT_FRAME (s) & 1023;
-
-	if ((unsigned) urb->number_of_packets > 900)
-		return -EFBIG;
-	
-	limits = find_iso_limits (urb, &start_limit, &stop_limit);
-	queued_size = (stop_limit - start_limit) & 1023;
-
-	if (urb->transfer_flags & USB_ISO_ASAP) {
-		// first iso
-		if (limits) {
-			// 10ms setup should be enough //FIXME!
-			urb->start_frame = (now + 10) & 1023;
-		}
-		else {
-			urb->start_frame = stop_limit;		//seamless linkage
-
-			if (((now - urb->start_frame) & 1023) <= (unsigned) urb->number_of_packets) {
-				info("iso_find_start: gap in seamless isochronous scheduling");
-				dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x",
-					now, urb->start_frame, urb->number_of_packets, urb->pipe);
-				urb->start_frame = (now + 5) & 1023;	// 5ms setup should be enough //FIXME!
-			}
-		}
-	}
-	else {
-		urb->start_frame &= 1023;
-		if (((now - urb->start_frame) & 1023) < (unsigned) urb->number_of_packets) {
-			dbg("iso_find_start: now between start_frame and end");
-			return -EAGAIN;
-		}
-	}
-
-	/* check if either start_frame or start_frame+number_of_packets-1 lies between start_limit and stop_limit */
-	if (limits)
-		return 0;
-
-	if (((urb->start_frame - start_limit) & 1023) < queued_size ||
-	    ((urb->start_frame + urb->number_of_packets - 1 - start_limit) & 1023) < queued_size) {
-		dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u",
-			urb->start_frame, urb->number_of_packets, start_limit, stop_limit);
-		return -EAGAIN;
-	}
-
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-// submits USB interrupt (ie. polling ;-) 
-// ASAP-flag set implicitely
-// if period==0, the transfer is only done once
-
-_static int uhci_submit_int_urb (struct urb *urb)
-{
-	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv;
-	int nint, n;
-	uhci_desc_t *td;
-	int status, destination;
-	int info;
-	unsigned int pipe = urb->pipe;
-
-	if (urb->interval < 0 || urb->interval >= 256)
-		return -EINVAL;
-
-	if (urb->interval == 0)
-		nint = 0;
-	else {
-		for (nint = 0, n = 1; nint <= 8; nint++, n += n)	// round interval down to 2^n
-		 {
-			if (urb->interval < n) {
-				urb->interval = n / 2;
-				break;
-			}
-		}
-		nint--;
-	}
-
-	dbg("Rounded interval to %i, chain  %i", urb->interval, nint);
-
-	urb->start_frame = UHCI_GET_CURRENT_FRAME (s) & 1023;	// remember start frame, just in case...
-
-	urb->number_of_packets = 1;
-
-	// INT allows only one packet
-	if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)))
-		return -EINVAL;
-
-	if (alloc_td (s, &td, UHCI_PTR_DEPTH))
-		return -ENOMEM;
-
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOC
-		| (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD)
-		| (3 << 27);
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe) |
-		(((urb->transfer_buffer_length - 1) & 0x7ff) << 21);
-
-
-	info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
-
-	fill_td (td, status, info, urb_priv->transfer_buffer_dma);
-	list_add_tail (&td->desc_list, &urb_priv->desc_list);
-
-	queue_urb (s, urb);
-
-	insert_td_horizontal (s, s->int_chain[nint], td);	// store in INT-TDs
-
-	usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
-
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-_static int uhci_submit_iso_urb (struct urb *urb, int mem_flags)
-{
-	uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
-	urb_priv_t *urb_priv = urb->hcpriv;
-#ifdef ISO_SANITY_CHECK
-	int pipe=urb->pipe;
-	int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe));
-#endif
-	int n, ret, last=0;
-	uhci_desc_t *td, **tdm;
-	int status, destination;
-	unsigned long flags;
-
-	__save_flags(flags);
-	__cli();		      // Disable IRQs to schedule all ISO-TDs in time
-	ret = iso_find_start (urb);	// adjusts urb->start_frame for later use
-	
-	if (ret)
-		goto err;
-
-	tdm = (uhci_desc_t **) kmalloc (urb->number_of_packets * sizeof (uhci_desc_t*), mem_flags);
-
-	if (!tdm) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	memset(tdm, 0, urb->number_of_packets * sizeof (uhci_desc_t*));
-
-	// First try to get all TDs. Cause: Removing already inserted TDs can only be done 
-	// racefree in three steps: unlink TDs, wait one frame, delete TDs. 
-	// So, this solutions seems simpler...
-
-	for (n = 0; n < urb->number_of_packets; n++) {
-		dbg("n:%d urb->iso_frame_desc[n].length:%d", n, urb->iso_frame_desc[n].length);
-		if (!urb->iso_frame_desc[n].length)
-			continue;  // allows ISO striping by setting length to zero in iso_descriptor
-
-
-#ifdef ISO_SANITY_CHECK
-		if(urb->iso_frame_desc[n].length > maxsze) {
-
-			err("submit_iso: urb->iso_frame_desc[%d].length(%d)>%d",n , urb->iso_frame_desc[n].length, maxsze);
-			ret=-EINVAL;		
-		}
-		else
-#endif
-		if (alloc_td (s, &td, UHCI_PTR_DEPTH)) {
-			int i;	// Cleanup allocated TDs
-
-			for (i = 0; i < n; n++)
-				if (tdm[i])
-					 delete_desc(s, tdm[i]);
-			kfree (tdm);
-			goto err;
-		}
-		last=n;
-		tdm[n] = td;
-	}
-
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
-
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe);
-
-	// Queue all allocated TDs
-	for (n = 0; n < urb->number_of_packets; n++) {
-		td = tdm[n];
-		if (!td)
-			continue;
-			
-		if (n  == last) {
-			status |= TD_CTRL_IOC;
-			queue_urb (s, urb);
-		}
-
-		fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21),
-			 urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset);
-		list_add_tail (&td->desc_list, &urb_priv->desc_list);
-	
-		insert_td_horizontal (s, s->iso_td[(urb->start_frame + n) & 1023], td);	// store in iso-tds
-	}
-
-	kfree (tdm);
-	dbg("ISO-INT# %i, start %i, now %i", urb->number_of_packets, urb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
-	ret = 0;
-
-      err:
-	__restore_flags(flags);
-	return ret;
-}
-/*-------------------------------------------------------------------*/
-// returns: 0 (no transfer queued), urb* (this urb already queued)
- 
-_static struct urb* search_dev_ep (uhci_t *s, struct urb *urb)
-{
-	struct list_head *p;
-	struct urb *tmp;
-	unsigned int mask = usb_pipecontrol(urb->pipe) ? (~USB_DIR_IN) : (~0);
-
-	dbg("search_dev_ep:");
-
-	p=s->urb_list.next;
-
-	for (; p != &s->urb_list; p = p->next) {
-		tmp = list_entry (p, struct urb, urb_list);
-		dbg("urb: %p", tmp);
-		// we can accept this urb if it is not queued at this time 
-		// or if non-iso transfer requests should be scheduled for the same device and pipe
-		if ((!usb_pipeisoc(urb->pipe) && (tmp->dev == urb->dev) && !((tmp->pipe ^ urb->pipe) & mask)) ||
-		    (urb == tmp)) {
-			return tmp;	// found another urb already queued for processing
-		}
-	}
-
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-_static int uhci_submit_urb (struct urb *urb, int mem_flags)
-{
-	uhci_t *s;
-	urb_priv_t *urb_priv;
-	int ret = 0, type;
-	unsigned long flags;
-	struct urb *queued_urb=NULL;
-	int bustime;
-		
-	if (!urb->dev || !urb->dev->bus)
-		return -ENODEV;
-
-	s = (uhci_t*) urb->dev->bus->hcpriv;
-	//dbg("submit_urb: %p type %d",urb,usb_pipetype(urb->pipe));
-	
-	if (!s->running)
-		return -ENODEV;
-	
-	type = usb_pipetype (urb->pipe);
-
-	if (usb_pipedevice (urb->pipe) == s->rh.devnum)
-		return rh_submit_urb (urb);	/* virtual root hub */
-
-	// Sanity checks
-	if (usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe)) <= 0) {		
-		err("uhci_submit_urb: pipesize for pipe %x is zero", urb->pipe);
-		return -EMSGSIZE;
-	}
-
-	if (urb->transfer_buffer_length < 0 && type != PIPE_ISOCHRONOUS) {
-		err("uhci_submit_urb: Negative transfer length for urb %p", urb);
-		return -EINVAL;
-	}
-
-	/* increment the reference count of the urb, as we now also control it */
-	urb = usb_get_urb (urb);
-
-	usb_inc_dev_use (urb->dev);
-
-	spin_lock_irqsave (&s->urb_list_lock, flags);
-
-	queued_urb = search_dev_ep (s, urb); // returns already queued urb for that pipe
-
-	if (queued_urb) {
-
-		queue_dbg("found bulk urb %p\n", queued_urb);
-
-		if (( type != PIPE_BULK) ||
-		    ((type == PIPE_BULK) &&
-		     (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) {
-			spin_unlock_irqrestore (&s->urb_list_lock, flags);
-			usb_dec_dev_use (urb->dev);
-			usb_put_urb (urb);
-			err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb);
-			return -ENXIO;	// urb already queued
-		}
-	}
-
-#ifdef DEBUG_SLAB
-	urb_priv = kmem_cache_alloc(urb_priv_kmem, SLAB_FLAG);
-#else
-	urb_priv = kmalloc (sizeof (urb_priv_t), mem_flags);
-#endif
-	if (!urb_priv) {
-		usb_dec_dev_use (urb->dev);
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
-		usb_put_urb (urb);
-		return -ENOMEM;
-	}
-
-	memset(urb_priv, 0, sizeof(urb_priv_t));
-	urb->hcpriv = urb_priv;
-	INIT_LIST_HEAD (&urb_priv->desc_list);
-
-	dbg("submit_urb: scheduling %p", urb);
-	
-	if (type == PIPE_CONTROL)
-		urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet,
-							    sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-
-	if (urb->transfer_buffer_length)
-		urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci,
-							       urb->transfer_buffer,
-							       urb->transfer_buffer_length,
-							       usb_pipein(urb->pipe) ?
-							       PCI_DMA_FROMDEVICE :
-							       PCI_DMA_TODEVICE);
-
-	if (type == PIPE_BULK) {
-	
-		if (queued_urb) {
-			while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb)  // find last queued bulk
-				queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb;
-			
-			((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb;
-		}
-		atomic_inc (&s->avoid_bulk);
-		ret = uhci_submit_bulk_urb (urb, queued_urb);
-		atomic_dec (&s->avoid_bulk);
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
-	}
-	else {
-		spin_unlock_irqrestore (&s->urb_list_lock, flags);
-		switch (type) {
-		case PIPE_ISOCHRONOUS:			
-			if (urb->bandwidth == 0) {      /* not yet checked/allocated */
-				if (urb->number_of_packets <= 0) {
-					ret = -EINVAL;
-					break;
-				}
-
-				bustime = usb_check_bandwidth (urb->dev, urb);
-				if (bustime < 0) 
-					ret = bustime;
-				else {
-					ret = uhci_submit_iso_urb(urb, mem_flags);
-					if (ret == 0)
-						usb_claim_bandwidth (urb->dev, urb, bustime, 1);
-				}
-			} else {        /* bandwidth is already set */
-				ret = uhci_submit_iso_urb(urb, mem_flags);
-			}
-			break;
-		case PIPE_INTERRUPT:
-			if (urb->bandwidth == 0) {      /* not yet checked/allocated */
-				bustime = usb_check_bandwidth (urb->dev, urb);
-				if (bustime < 0)
-					ret = bustime;
-				else {
-					ret = uhci_submit_int_urb(urb);
-					if (ret == 0)
-						usb_claim_bandwidth (urb->dev, urb, bustime, 0);
-				}
-			} else {        /* bandwidth is already set */
-				ret = uhci_submit_int_urb(urb);
-			}
-			break;
-		case PIPE_CONTROL:
-			ret = uhci_submit_control_urb (urb);
-			break;
-		default:
-			ret = -EINVAL;
-		}
-	}
-
-	dbg("submit_urb: scheduled with ret: %d", ret);
-	
-	if (ret != 0) {
-		uhci_urb_dma_unmap(s, urb, urb_priv);
-		usb_dec_dev_use (urb->dev);
-#ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, urb_priv);
-#else
-		kfree (urb_priv);
-#endif
-		usb_put_urb (urb);
-		return ret;
-	}
-
-	return 0;
-}
-
-// Checks for URB timeout and removes bandwidth reclamation if URB idles too long
-_static void uhci_check_timeouts(uhci_t *s)
-{
-	struct list_head *p,*p2;
-	struct urb *urb;
-	int type;	
-
-	p = s->urb_list.prev;	
-
-	while (p != &s->urb_list) {
-		urb_priv_t *hcpriv;
-
-		p2 = p;
-		p = p->prev;
-		urb = list_entry (p2, struct urb, urb_list);
-		type = usb_pipetype (urb->pipe);
-
-		hcpriv = (urb_priv_t*)urb->hcpriv;
-		
-		if ( urb->timeout && time_after(jiffies, hcpriv->started + urb->timeout)) {
-			urb->transfer_flags |= USB_TIMEOUT_KILLED | USB_ASYNC_UNLINK;
-			async_dbg("uhci_check_timeout: timeout for %p",urb);
-			uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
-		}
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
-		else if (((type == PIPE_BULK) || (type == PIPE_CONTROL)) &&  
-			 (hcpriv->use_loop) && time_after(jiffies, hcpriv->started + IDLE_TIMEOUT))
-			disable_desc_loop(s, urb);
-#endif
-
-	}
-	s->timeout_check=jiffies;
-}
-
-/*-------------------------------------------------------------------
- Virtual Root Hub
- -------------------------------------------------------------------*/
-
-_static __u8 root_hub_dev_des[] =
-{
-	0x12,			/*  __u8  bLength; */
-	0x01,			/*  __u8  bDescriptorType; Device */
-	0x00,			/*  __u16 bcdUSB; v1.0 */
-	0x01,
-	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
-	0x00,			/*  __u8  bDeviceSubClass; */
-	0x00,			/*  __u8  bDeviceProtocol; */
-	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
-	0x00,			/*  __u16 idVendor; */
-	0x00,
-	0x00,			/*  __u16 idProduct; */
-	0x00,
-	0x00,			/*  __u16 bcdDevice; */
-	0x00,
-	0x00,			/*  __u8  iManufacturer; */
-	0x02,			/*  __u8  iProduct; */
-	0x01,			/*  __u8  iSerialNumber; */
-	0x01			/*  __u8  bNumConfigurations; */
-};
-
-
-/* Configuration descriptor */
-_static __u8 root_hub_config_des[] =
-{
-	0x09,			/*  __u8  bLength; */
-	0x02,			/*  __u8  bDescriptorType; Configuration */
-	0x19,			/*  __u16 wTotalLength; */
-	0x00,
-	0x01,			/*  __u8  bNumInterfaces; */
-	0x01,			/*  __u8  bConfigurationValue; */
-	0x00,			/*  __u8  iConfiguration; */
-	0x40,			/*  __u8  bmAttributes; 
-				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
-	0x00,			/*  __u8  MaxPower; */
-
-     /* interface */
-	0x09,			/*  __u8  if_bLength; */
-	0x04,			/*  __u8  if_bDescriptorType; Interface */
-	0x00,			/*  __u8  if_bInterfaceNumber; */
-	0x00,			/*  __u8  if_bAlternateSetting; */
-	0x01,			/*  __u8  if_bNumEndpoints; */
-	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
-	0x00,			/*  __u8  if_bInterfaceSubClass; */
-	0x00,			/*  __u8  if_bInterfaceProtocol; */
-	0x00,			/*  __u8  if_iInterface; */
-
-     /* endpoint */
-	0x07,			/*  __u8  ep_bLength; */
-	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
-	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
-	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
-	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
-	0x00,
-	0xff			/*  __u8  ep_bInterval; 255 ms */
-};
-
-
-_static __u8 root_hub_hub_des[] =
-{
-	0x09,			/*  __u8  bLength; */
-	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
-	0x02,			/*  __u8  bNbrPorts; */
-	0x00,			/* __u16  wHubCharacteristics; */
-	0x00,
-	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
-	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
-	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
-	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-/*-------------------------------------------------------------------------*/
-/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-_static int rh_send_irq (struct urb *urb)
-{
-	int len = 1;
-	int i;
-	uhci_t *uhci = urb->dev->bus->hcpriv;
-	unsigned int io_addr = uhci->io_addr;
-	__u16 data = 0;
-
-	for (i = 0; i < uhci->rh.numports; i++) {
-		data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
-		len = (i + 1) / 8 + 1;
-	}
-
-	*(__u16 *) urb->transfer_buffer = cpu_to_le16 (data);
-	urb->actual_length = len;
-	urb->status = 0;
-	
-	if ((data > 0) && (uhci->rh.send != 0)) {
-		dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",
-		     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);
-		urb->complete (urb);
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
-_static int rh_init_int_timer (struct urb *urb);
-
-_static void rh_int_timer_do (unsigned long ptr)
-{
-	int len;
-	struct urb *urb = (struct urb *) ptr;
-	uhci_t *uhci = urb->dev->bus->hcpriv;
-
-	if (uhci->rh.send) {
-		len = rh_send_irq (urb);
-		if (len > 0) {
-			urb->actual_length = len;
-			if (urb->complete)
-				urb->complete (urb);
-		}
-	}
-	rh_init_int_timer (urb);
-}
-
-/*-------------------------------------------------------------------------*/
-/* Root Hub INTs are polled by this timer, polling interval 20ms */
-
-_static int rh_init_int_timer (struct urb *urb)
-{
-	uhci_t *uhci = urb->dev->bus->hcpriv;
-
-	uhci->rh.interval = urb->interval;
-	init_timer (&uhci->rh.rh_int_timer);
-	uhci->rh.rh_int_timer.function = rh_int_timer_do;
-	uhci->rh.rh_int_timer.data = (unsigned long) urb;
-	uhci->rh.rh_int_timer.expires = jiffies + (HZ * 20) / 1000;
-	add_timer (&uhci->rh.rh_int_timer);
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-#define OK(x) 			len = (x); break
-
-#define CLR_RH_PORTSTAT(x) \
-		status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \
-		status = (status & 0xfff5) & ~(x); \
-		outw(status, io_addr+USBPORTSC1+2*(wIndex-1))
-
-#define SET_RH_PORTSTAT(x) \
-		status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \
-		status = (status & 0xfff5) | (x); \
-		outw(status, io_addr+USBPORTSC1+2*(wIndex-1))
-
-
-/*-------------------------------------------------------------------------*/
-/****
- ** Root Hub Control Pipe
- *************************/
-
-
-_static int rh_submit_urb (struct urb *urb)
-{
-	struct usb_device *usb_dev = urb->dev;
-	uhci_t *uhci = usb_dev->bus->hcpriv;
-	unsigned int pipe = urb->pipe;
-	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
-	void *data = urb->transfer_buffer;
-	int leni = urb->transfer_buffer_length;
-	int len = 0;
-	int status = 0;
-	int stat = 0;
-	int i;
-	unsigned int io_addr = uhci->io_addr;
-	__u16 cstatus;
-
-	__u16 bmRType_bReq;
-	__u16 wValue;
-	__u16 wIndex;
-	__u16 wLength;
-
-	if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
-		dbg("Root-Hub submit IRQ: every %d ms", urb->interval);
-		uhci->rh.urb = urb;
-		uhci->rh.send = 1;
-		uhci->rh.interval = urb->interval;
-		rh_init_int_timer (urb);
-
-		return 0;
-	}
-
-
-	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
-	wValue = le16_to_cpu (cmd->wValue);
-	wIndex = le16_to_cpu (cmd->wIndex);
-	wLength = le16_to_cpu (cmd->wLength);
-
-	for (i = 0; i < 8; i++)
-		uhci->rh.c_p_r[i] = 0;
-
-	dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x",
-	     uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
-
-	switch (bmRType_bReq) {
-		/* Request Destination:
-		   without flags: Device, 
-		   RH_INTERFACE: interface, 
-		   RH_ENDPOINT: endpoint,
-		   RH_CLASS means HUB here, 
-		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
-		 */
-
-	case RH_GET_STATUS:
-		*(__u16 *) data = cpu_to_le16 (1);
-		OK (2);
-	case RH_GET_STATUS | RH_INTERFACE:
-		*(__u16 *) data = cpu_to_le16 (0);
-		OK (2);
-	case RH_GET_STATUS | RH_ENDPOINT:
-		*(__u16 *) data = cpu_to_le16 (0);
-		OK (2);
-	case RH_GET_STATUS | RH_CLASS:
-		*(__u32 *) data = cpu_to_le32 (0);
-		OK (4);		/* hub power ** */
-	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
-		status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1));
-		cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
-			((status & USBPORTSC_PEC) >> (3 - 1)) |
-			(uhci->rh.c_p_r[wIndex - 1] << (0 + 4));
-		status = (status & USBPORTSC_CCS) |
-			((status & USBPORTSC_PE) >> (2 - 1)) |
-			((status & USBPORTSC_SUSP) >> (12 - 2)) |
-			((status & USBPORTSC_PR) >> (9 - 4)) |
-			(1 << 8) |	/* power on ** */
-			((status & USBPORTSC_LSDA) << (-8 + 9));
-
-		*(__u16 *) data = cpu_to_le16 (status);
-		*(__u16 *) (data + 2) = cpu_to_le16 (cstatus);
-		OK (4);
-
-	case RH_CLEAR_FEATURE | RH_ENDPOINT:
-		switch (wValue) {
-		case (RH_ENDPOINT_STALL):
-			OK (0);
-		}
-		break;
-
-	case RH_CLEAR_FEATURE | RH_CLASS:
-		switch (wValue) {
-		case (RH_C_HUB_OVER_CURRENT):
-			OK (0);	/* hub power over current ** */
-		}
-		break;
-
-	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
-		switch (wValue) {
-		case (RH_PORT_ENABLE):
-			CLR_RH_PORTSTAT (USBPORTSC_PE);
-			OK (0);
-		case (RH_PORT_SUSPEND):
-			CLR_RH_PORTSTAT (USBPORTSC_SUSP);
-			OK (0);
-		case (RH_PORT_POWER):
-			OK (0);	/* port power ** */
-		case (RH_C_PORT_CONNECTION):
-			SET_RH_PORTSTAT (USBPORTSC_CSC);
-			OK (0);
-		case (RH_C_PORT_ENABLE):
-			SET_RH_PORTSTAT (USBPORTSC_PEC);
-			OK (0);
-		case (RH_C_PORT_SUSPEND):
-/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
-			OK (0);
-		case (RH_C_PORT_OVER_CURRENT):
-			OK (0);	/* port power over current ** */
-		case (RH_C_PORT_RESET):
-			uhci->rh.c_p_r[wIndex - 1] = 0;
-			OK (0);
-		}
-		break;
-
-	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
-		switch (wValue) {
-		case (RH_PORT_SUSPEND):
-			SET_RH_PORTSTAT (USBPORTSC_SUSP);
-			OK (0);
-		case (RH_PORT_RESET):
-			SET_RH_PORTSTAT (USBPORTSC_PR);
-			uhci_wait_ms (10);
-			uhci->rh.c_p_r[wIndex - 1] = 1;
-			CLR_RH_PORTSTAT (USBPORTSC_PR);
-			udelay (10);
-			SET_RH_PORTSTAT (USBPORTSC_PE);
-			uhci_wait_ms (10);
-			SET_RH_PORTSTAT (0xa);
-			OK (0);
-		case (RH_PORT_POWER):
-			OK (0);	/* port power ** */
-		case (RH_PORT_ENABLE):
-			SET_RH_PORTSTAT (USBPORTSC_PE);
-			OK (0);
-		}
-		break;
-
-	case RH_SET_ADDRESS:
-		uhci->rh.devnum = wValue;
-		OK (0);
-
-	case RH_GET_DESCRIPTOR:
-		switch ((wValue & 0xff00) >> 8) {
-		case (0x01):	/* device descriptor */
-			len = min_t(unsigned int, leni,
-				  min_t(unsigned int,
-				      sizeof (root_hub_dev_des), wLength));
-			memcpy (data, root_hub_dev_des, len);
-			OK (len);
-		case (0x02):	/* configuration descriptor */
-			len = min_t(unsigned int, leni,
-				  min_t(unsigned int,
-				      sizeof (root_hub_config_des), wLength));
-			memcpy (data, root_hub_config_des, len);
-			OK (len);
-		case (0x03):	/* string descriptors */
-			len = usb_root_hub_string (wValue & 0xff,
-			        uhci->io_addr, "UHCI",
-				data, wLength);
-			if (len > 0) {
-				OK(min_t(int, leni, len));
-			} else 
-				stat = -EPIPE;
-		}
-		break;
-
-	case RH_GET_DESCRIPTOR | RH_CLASS:
-		root_hub_hub_des[2] = uhci->rh.numports;
-		len = min_t(unsigned int, leni,
-			  min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
-		memcpy (data, root_hub_hub_des, len);
-		OK (len);
-
-	case RH_GET_CONFIGURATION:
-		*(__u8 *) data = 0x01;
-		OK (1);
-
-	case RH_SET_CONFIGURATION:
-		OK (0);
-	default:
-		stat = -EPIPE;
-	}
-
-	dbg("Root-Hub stat port1: %x port2: %x",
-	     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));
-
-	urb->actual_length = len;
-	urb->status = stat;
-	urb->dev=NULL;
-	if (urb->complete)
-		urb->complete (urb);
-	return 0;
-}
-/*-------------------------------------------------------------------------*/
-
-_static int rh_unlink_urb (struct urb *urb)
-{
-	uhci_t *uhci = urb->dev->bus->hcpriv;
-
-	if (uhci->rh.urb==urb) {
-		dbg("Root-Hub unlink IRQ");
-		uhci->rh.send = 0;
-		del_timer (&uhci->rh.rh_int_timer);
-	}
-	return 0;
-}
-/*-------------------------------------------------------------------*/
-
-/*
- * Map status to standard result codes
- *
- * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)
- * <dir_out> is True for output TDs and False for input TDs.
- */
-_static int uhci_map_status (int status, int dir_out)
-{
-	if (!status)
-		return 0;
-	if (status & TD_CTRL_BITSTUFF)	/* Bitstuff error */
-		return -EPROTO;
-	if (status & TD_CTRL_CRCTIMEO) {	/* CRC/Timeout */
-		if (dir_out)
-			return -ETIMEDOUT;
-		else
-			return -EILSEQ;
-	}
-	if (status & TD_CTRL_NAK)	/* NAK */
-		return -ETIMEDOUT;
-	if (status & TD_CTRL_BABBLE)	/* Babble */
-		return -EOVERFLOW;
-	if (status & TD_CTRL_DBUFERR)	/* Buffer error */
-		return -ENOSR;
-	if (status & TD_CTRL_STALLED)	/* Stalled */
-		return -EPIPE;
-	if (status & TD_CTRL_ACTIVE)	/* Active */
-		return 0;
-
-	return -EPROTO;
-}
-
-/*
- * Only the USB core should call uhci_alloc_dev and uhci_free_dev
- */
-_static int uhci_alloc_dev (struct usb_device *usb_dev)
-{
-	return 0;
-}
-
-_static void uhci_unlink_urbs(uhci_t *s, struct usb_device *usb_dev, int remove_all)
-{
-	unsigned long flags;
-	struct list_head *p;
-	struct list_head *p2;
-	struct urb *urb;
-
-	spin_lock_irqsave (&s->urb_list_lock, flags);
-	p = s->urb_list.prev;	
-	while (p != &s->urb_list) {
-		p2 = p;
-		p = p->prev ;
-		urb = list_entry (p2, struct urb, urb_list);
-		dbg("urb: %p, dev %p, %p", urb, usb_dev,urb->dev);
-		
-		//urb->transfer_flags |=USB_ASYNC_UNLINK; 
-			
-		if (remove_all || (usb_dev == urb->dev)) {
-			spin_unlock_irqrestore (&s->urb_list_lock, flags);
-			warn("forced removing of queued URB %p due to disconnect",urb);
-			uhci_unlink_urb(urb);
-			urb->dev = NULL; // avoid further processing of this URB
-			spin_lock_irqsave (&s->urb_list_lock, flags);
-			p = s->urb_list.prev;	
-		}
-	}
-	spin_unlock_irqrestore (&s->urb_list_lock, flags);
-}
-
-_static int uhci_free_dev (struct usb_device *usb_dev)
-{
-	uhci_t *s;
-	
-
-	if(!usb_dev || !usb_dev->bus || !usb_dev->bus->hcpriv)
-		return -EINVAL;
-	
-	s=(uhci_t*) usb_dev->bus->hcpriv;	
-	uhci_unlink_urbs(s, usb_dev, 0);
-
-	return 0;
-}
-
-/*
- * uhci_get_current_frame_number()
- *
- * returns the current frame number for a USB bus/controller.
- */
-_static int uhci_get_current_frame_number (struct usb_device *usb_dev)
-{
-	return UHCI_GET_CURRENT_FRAME ((uhci_t*) usb_dev->bus->hcpriv);
-}
-
-struct usb_operations uhci_device_operations =
-{
-	allocate:		uhci_alloc_dev,
-	deallocate:		uhci_free_dev,
-	get_frame_number:	uhci_get_current_frame_number,
-	submit_urb:		uhci_submit_urb,
-	unlink_urb:		uhci_unlink_urb,
-};
-
-_static void correct_data_toggles(struct urb *urb)
-{
-	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), 
-		       !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)));
-
-	while(urb) {
-		urb_priv_t *priv=urb->hcpriv;		
-		uhci_desc_t *qh = list_entry (priv->desc_list.next, uhci_desc_t, desc_list);
-		struct list_head *p = qh->vertical.next;
-		uhci_desc_t *td;
-		dbg("URB to correct %p\n", urb);
-	
-		for (; p != &qh->vertical; p = p->next) {
-			td = list_entry (p, uhci_desc_t, vertical);
-			td->hw.td.info^=cpu_to_le32(1<<TD_TOKEN_TOGGLE);
-		}
-		urb=priv->next_queued_urb;
-	}
-}
-
-/* 
- * For IN-control transfers, process_transfer gets a bit more complicated,
- * since there are devices that return less data (eg. strings) than they
- * have announced. This leads to a queue abort due to the short packet,
- * the status stage is not executed. If this happens, the status stage
- * is manually re-executed.
- * mode: PROCESS_TRANSFER_REGULAR: regular (unlink QH)
- *       PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb)
- */
-
-_static int process_transfer (uhci_t *s, struct urb *urb, int mode)
-{
-	int ret = 0;
-	urb_priv_t *urb_priv = urb->hcpriv;
-	struct list_head *qhl = urb_priv->desc_list.next;
-	uhci_desc_t *qh = list_entry (qhl, uhci_desc_t, desc_list);
-	struct list_head *p = qh->vertical.next;
-	uhci_desc_t *desc= list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
-	uhci_desc_t *last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical);
-	int data_toggle = usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));	// save initial data_toggle
-	int maxlength; 	// extracted and remapped info from TD
-	int actual_length;
-	int status = 0;
-
-	//dbg("process_transfer: urb %p, urb_priv %p, qh %p last_desc %p\n",urb,urb_priv, qh, last_desc);
-
-	/* if the status phase has been retriggered and the
-	   queue is empty or the last status-TD is inactive, the retriggered
-	   status stage is completed
-	 */
-
-	if (urb_priv->flags && 
-	    ((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) || !is_td_active(desc)))
-		goto transfer_finished;
-
-	urb->actual_length=0;
-
-	for (; p != &qh->vertical; p = p->next) {
-		desc = list_entry (p, uhci_desc_t, vertical);
-
-		if (is_td_active(desc)) {	// do not process active TDs
-			if (mode == CLEAN_TRANSFER_DELETION_MARK) // if called from async_unlink
-				uhci_clean_transfer(s, urb, qh, CLEAN_TRANSFER_DELETION_MARK);
-			return ret;
-		}
-	
-		actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));		// extract transfer parameters from TD
-		maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
-
-		if (status == -EPIPE) { 		// see if EP is stalled
-			// set up stalled condition
-			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
-		}
-
-		if (status && (status != -EPIPE)) {	// if any error occurred stop processing of further TDs
-			// only set ret if status returned an error
-  is_error:
-			ret = status;
-			urb->error_count++;
-			break;
-		}
-		else if ((le32_to_cpu(desc->hw.td.info) & 0xff) != USB_PID_SETUP)
-			urb->actual_length += actual_length;
-
-		// got less data than requested
-		if ( (actual_length < maxlength)) {
-			if (urb->transfer_flags & USB_DISABLE_SPD) {
-				status = -EREMOTEIO;	// treat as real error
-				dbg("process_transfer: SPD!!");
-				break;	// exit after this TD because SP was detected
-			}
-
-			// short read during control-IN: re-start status stage
-			if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) {
-				if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) {
-			
-					set_qh_element(qh, last_desc->dma_addr);  // re-trigger status stage
-					dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
-					urb_priv->flags = 1; // mark as short control packet
-					return 0;
-				}
-			}
-			// all other cases: short read is OK
-			data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
-			break;
-		}
-		else if (status)
-			goto is_error;
-
-		data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
-		queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, le32_to_cpu(desc->hw.td.status),status, data_toggle);      
-
-	}
-
-	if (usb_pipetype (urb->pipe) == PIPE_BULK ) {  /* toggle correction for short bulk transfers (nonqueued/queued) */
-
-		urb_priv_t *priv=(urb_priv_t*)urb->hcpriv;
-		struct urb *next_queued_urb=priv->next_queued_urb;
-
-		if (next_queued_urb) {
-			urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv;
-			uhci_desc_t *qh = list_entry (next_priv->desc_list.next, uhci_desc_t, desc_list);
-			uhci_desc_t *first_td=list_entry (qh->vertical.next, uhci_desc_t, vertical);
-
-			if (data_toggle == uhci_toggle (le32_to_cpu(first_td->hw.td.info))) {
-				err("process_transfer: fixed toggle");
-				correct_data_toggles(next_queued_urb);
-			}						
-		}
-		else
-			usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !data_toggle);		
-	}
-
- transfer_finished:
-	
-	uhci_clean_transfer(s, urb, qh, mode);
-
-	urb->status = status;
-
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH	
-	disable_desc_loop(s,urb);
-#endif	
-
-	queue_dbg("process_transfer: (end) urb %p, wanted len %d, len %d status %x err %d",
-		urb,urb->transfer_buffer_length,urb->actual_length, urb->status, urb->error_count);
-	return ret;
-}
-
-_static int process_interrupt (uhci_t *s, struct urb *urb)
-{
-	int i, ret = -EINPROGRESS;
-	urb_priv_t *urb_priv = urb->hcpriv;
-	struct list_head *p = urb_priv->desc_list.next;
-	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
-
-	int actual_length;
-	int status = 0;
-
-	//dbg("urb contains interrupt request");
-
-	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++)	// Maybe we allow more than one TD later ;-)
-	{
-		desc = list_entry (p, uhci_desc_t, desc_list);
-
-		if (is_td_active(desc)) {
-			// do not process active TDs
-			//dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status));
-			break;
-		}
-
-		if (!(desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC))) {
-			// do not process one-shot TDs, no recycling
-			break;
-		}
-		// extract transfer parameters from TD
-
-		actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));
-		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
-
-		// see if EP is stalled
-		if (status == -EPIPE) {
-			// set up stalled condition
-			usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
-		}
-
-		// if any error occurred: ignore this td, and continue
-		if (status != 0) {
-			//uhci_show_td (desc);
-			urb->error_count++;
-			goto recycle;
-		}
-		else
-			urb->actual_length = actual_length;
-
-	recycle:
-		uhci_urb_dma_sync(s, urb, urb->hcpriv);
-		if (urb->complete) {
-			//dbg("process_interrupt: calling completion, status %i",status);
-			urb->status = status;
-			((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion
-
-			spin_unlock(&s->urb_list_lock);
-			
-			urb->complete ((struct urb *) urb);
-			
-			spin_lock(&s->urb_list_lock);
-
-			((urb_priv_t*)urb->hcpriv)->flags=0;		       			
-		}
-		
-		if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
-			    (urb->status != -ENOENT)) {
-
-			urb->status = -EINPROGRESS;
-
-			// Recycle INT-TD if interval!=0, else mark TD as one-shot
-			if (urb->interval) {
-				
-				desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
-				if (status==0) {
-					((urb_priv_t*)urb->hcpriv)->started=jiffies;
-					desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
-					usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
-				} else {
-					desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
-				}
-				desc->hw.td.status= cpu_to_le32(TD_CTRL_ACTIVE | TD_CTRL_IOC |
-					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
-				if (urb->dev->speed == USB_SPEED_LOW)
-					desc->hw.td.status |=
-					    __constant_cpu_to_le32 (TD_CTRL_LS);
-				mb();
-			}
-			else {
-				uhci_unlink_urb_async(s, urb, UNLINK_ASYNC_STORE_URB);
-				// correct toggle after unlink
-				usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
-				clr_td_ioc(desc); // inactivate TD
-			}
-		}
-	}
-
-	return ret;
-}
-
-// mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs
-// mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked)
-
-_static int process_iso (uhci_t *s, struct urb *urb, int mode)
-{
-	int i;
-	int ret = 0;
-	urb_priv_t *urb_priv = urb->hcpriv;
-	struct list_head *p = urb_priv->desc_list.next, *p_tmp;
-	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
-
-	dbg("urb contains iso request");
-	if (is_td_active(desc) && mode==PROCESS_ISO_REGULAR)
-		return -EXDEV;	// last TD not finished
-
-	urb->error_count = 0;
-	urb->actual_length = 0;
-	urb->status = 0;
-	dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s),
-	    urb->number_of_packets,mode,le32_to_cpu(desc->hw.td.status));
-
-	for (i = 0; p != &urb_priv->desc_list;  i++) {
-		desc = list_entry (p, uhci_desc_t, desc_list);
-		
-		//uhci_show_td(desc);
-		if (is_td_active(desc)) {
-			// means we have completed the last TD, but not the TDs before
-			desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE);
-			dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status));
-			ret = -EXDEV;
-			urb->iso_frame_desc[i].status = ret;
-			unlink_td (s, desc, 1);
-			// FIXME: immediate deletion may be dangerous
-			goto err;
-		}
-
-		if (mode == PROCESS_ISO_REGULAR)
-			unlink_td (s, desc, 1);
-
-		if (urb->number_of_packets <= i) {
-			dbg("urb->number_of_packets (%d)<=(%d)", urb->number_of_packets, i);
-			ret = -EINVAL;
-			goto err;
-		}
-
-		urb->iso_frame_desc[i].actual_length = uhci_actual_length(le32_to_cpu(desc->hw.td.status));
-		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
-		urb->actual_length += urb->iso_frame_desc[i].actual_length;
-
-	      err:
-
-		if (urb->iso_frame_desc[i].status != 0) {
-			urb->error_count++;
-			urb->status = urb->iso_frame_desc[i].status;
-		}
-		dbg("process_iso: %i: len:%d %08x status:%x",
-		     i, urb->iso_frame_desc[i].actual_length, le32_to_cpu(desc->hw.td.status),urb->iso_frame_desc[i].status);
-
-		p_tmp = p;
-		p = p->next;
-		list_del (p_tmp);
-		delete_desc (s, desc);
-	}
-	
-	dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
-	return ret;
-}
-
-
-_static int process_urb (uhci_t *s, struct list_head *p)
-{
-	int ret = 0;
-	struct urb *urb;
-
-	urb=list_entry (p, struct urb, urb_list);
-	//dbg("process_urb: found queued urb: %p", urb);
-
-	switch (usb_pipetype (urb->pipe)) {
-	case PIPE_CONTROL:
-		ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR);
-		break;
-	case PIPE_BULK:
-		if (!s->avoid_bulk.counter)
-			ret = process_transfer (s, urb, CLEAN_TRANSFER_REGULAR);
-		else
-			return 0;
-		break;
-	case PIPE_ISOCHRONOUS:
-		ret = process_iso (s, urb, PROCESS_ISO_REGULAR);
-		break;
-	case PIPE_INTERRUPT:
-		ret = process_interrupt (s, urb);
-		break;
-	}
-
-	if (urb->status != -EINPROGRESS) {
-		urb_priv_t *urb_priv;
-		struct usb_device *usb_dev;
-		
-		usb_dev=urb->dev;
-
-		/* Release bandwidth for Interrupt or Iso transfers */
-		if (urb->bandwidth) {
-			if (usb_pipetype(urb->pipe)==PIPE_ISOCHRONOUS)
-				usb_release_bandwidth (urb->dev, urb, 1);
-			else if (usb_pipetype(urb->pipe)==PIPE_INTERRUPT && urb->interval)
-				usb_release_bandwidth (urb->dev, urb, 0);
-		}
-
-		dbg("dequeued urb: %p", urb);
-		dequeue_urb (s, urb);
-
-		urb_priv = urb->hcpriv;
-
-		uhci_urb_dma_unmap(s, urb, urb_priv);
-
-#ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, urb_priv);
-#else
-		kfree (urb_priv);
-#endif
-
-		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {  // process_interrupt does completion on its own		
-			struct urb *next_urb = urb->next;
-			int is_ring = 0;
-			int contains_killed = 0;
-			int loop_count=0;
-			
-			if (next_urb) {
-				// Find out if the URBs are linked to a ring
-				while  (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) {
-					if (next_urb->status == -ENOENT) {// killed URBs break ring structure & resubmission
-						contains_killed = 1;
-						break;
-					}	
-					next_urb = next_urb->next;
-					loop_count++;
-				}
-				
-				if (loop_count == MAX_NEXT_COUNT)
-					err("process_urb: Too much linked URBs in ring detection!");
-
-				if (next_urb == urb)
-					is_ring=1;
-			}			
-
-			// Submit idle/non-killed URBs linked with urb->next
-			// Stop before the current URB				
-			
-			next_urb = urb->next;	
-			if (next_urb && !contains_killed) {
-				int ret_submit;
-				next_urb = urb->next;	
-				
-				loop_count=0;
-				while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) {
-					if (next_urb->status != -EINPROGRESS) {
-					
-						if (next_urb->status == -ENOENT) 
-							break;
-
-						spin_unlock(&s->urb_list_lock);
-
-						// FIXME!!!
-						// We need to know the real state, so 
-						// GFP_ATOMIC is probably not correct
-						ret_submit=uhci_submit_urb(next_urb, GFP_ATOMIC);
-						spin_lock(&s->urb_list_lock);
-						
-						if (ret_submit)
-							break;						
-					}
-					loop_count++;
-					next_urb = next_urb->next;
-				}
-				if (loop_count == MAX_NEXT_COUNT)
-					err("process_urb: Too much linked URBs in resubmission!");
-			}
-
-			// Completion
-			if (urb->complete) {
-				int was_unlinked = (urb->status == -ENOENT);
-				urb->dev = NULL;
-				spin_unlock(&s->urb_list_lock);
-
-				urb->complete ((struct urb *) urb);
-
-				// Re-submit the URB if ring-linked
-				if (is_ring && !was_unlinked && !contains_killed) {
-					urb->dev=usb_dev;
-					// FIXME!!!
-					// We need to know the real state, so 
-					// GFP_ATOMIC is probably not correct
-					uhci_submit_urb (urb, GFP_ATOMIC);
-				}
-				spin_lock(&s->urb_list_lock);
-			}
-			
-			usb_dec_dev_use (usb_dev);
-			usb_put_urb (urb);
-		}
-	}
-
-	return ret;
-}
-
-_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
-{
-	uhci_t *s = __uhci;
-	unsigned int io_addr = s->io_addr;
-	unsigned short status;
-	struct list_head *p, *p2;
-	int restarts, work_done;
-	
-	/*
-	 * Read the interrupt status, and write it back to clear the
-	 * interrupt cause
-	 */
-
-	status = inw (io_addr + USBSTS);
-
-	if (!status)		/* shared interrupt, not mine */
-		return;
-
-	dbg("interrupt");
-
-	if (status != 1) {
-		// Avoid too much error messages at a time
-		if (time_after(jiffies, s->last_error_time + ERROR_SUPPRESSION_TIME)) {
-			warn("interrupt, status %x, frame# %i", status, 
-			     UHCI_GET_CURRENT_FRAME(s));
-			s->last_error_time = jiffies;
-		}
-		
-		// remove host controller halted state
-		if ((status&0x20) && (s->running)) {
-			err("Host controller halted, trying to restart.");
-			outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD);
-		}
-		//uhci_show_status (s);
-	}
-	/*
-	 * traverse the list in *reverse* direction, because new entries
-	 * may be added at the end.
-	 * also, because process_urb may unlink the current urb,
-	 * we need to advance the list before
-	 * New: check for max. workload and restart count
-	 */
-
-	spin_lock (&s->urb_list_lock);
-
-	restarts=0;
-	work_done=0;
-
-restart:
-	s->unlink_urb_done=0;
-	p = s->urb_list.prev;	
-
-	while (p != &s->urb_list && (work_done < 1024)) {
-		p2 = p;
-		p = p->prev;
-
-		process_urb (s, p2);
-		
-		work_done++;
-
-		if (s->unlink_urb_done) {
-			s->unlink_urb_done=0;
-			restarts++;
-			
-			if (restarts<16)	// avoid endless restarts
-				goto restart;
-			else 
-				break;
-		}
-	}
-	if (time_after(jiffies, s->timeout_check + (HZ/30)))
-		uhci_check_timeouts(s);
-
-	clean_descs(s, CLEAN_NOT_FORCED);
-	uhci_cleanup_unlink(s, CLEAN_NOT_FORCED);
-	uhci_switch_timer_int(s);
-							
-	spin_unlock (&s->urb_list_lock);
-	
-	outw (status, io_addr + USBSTS);
-
-	//dbg("uhci_interrupt: done");
-}
-
-_static void reset_hc (uhci_t *s)
-{
-	unsigned int io_addr = s->io_addr;
-
-	s->apm_state = 0;
-	/* Global reset for 50ms */
-	outw (USBCMD_GRESET, io_addr + USBCMD);
-	uhci_wait_ms (50);
-	outw (0, io_addr + USBCMD);
-	uhci_wait_ms (10);
-}
-
-_static void start_hc (uhci_t *s)
-{
-	unsigned int io_addr = s->io_addr;
-	int timeout = 10;
-
-	/*
-	 * Reset the HC - this will force us to get a
-	 * new notification of any already connected
-	 * ports due to the virtual disconnect that it
-	 * implies.
-	 */
-	outw (USBCMD_HCRESET, io_addr + USBCMD);
-
-	while (inw (io_addr + USBCMD) & USBCMD_HCRESET) {
-		if (!--timeout) {
-			err("USBCMD_HCRESET timed out!");
-			break;
-		}
-		udelay(1);
-	}
-
-	/* Turn on all interrupts */
-	outw (USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR);
-
-	/* Start at frame 0 */
-	outw (0, io_addr + USBFRNUM);
-	outl (s->framelist_dma, io_addr + USBFLBASEADD);
-
-	/* Run and mark it configured with a 64-byte max packet */
-	outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
-	s->apm_state = 1;
-	s->running = 1;
-}
-
-/* No  __devexit, since it maybe called from alloc_uhci() */
-_static void
-uhci_pci_remove (struct pci_dev *dev)
-{
-	uhci_t *s = pci_get_drvdata(dev);
-	struct usb_device *root_hub = s->bus->root_hub;
-
-	s->running = 0;		    // Don't allow submit_urb
-
-	if (root_hub)
-		usb_disconnect (&root_hub);
-
-	reset_hc (s);
-	wait_ms (1);
-
-	uhci_unlink_urbs (s, 0, CLEAN_FORCED);  // Forced unlink of remaining URBs
-	uhci_cleanup_unlink (s, CLEAN_FORCED);  // force cleanup of async killed URBs
-	
-	usb_deregister_bus (s->bus);
-
-	release_region (s->io_addr, s->io_size);
-	free_irq (s->irq, s);
-	usb_free_bus (s->bus);
-	cleanup_skel (s);
-	kfree (s);
-}
-
-_static int __init uhci_start_usb (uhci_t *s)
-{				/* start it up */
-	/* connect the virtual root hub */
-	struct usb_device *usb_dev;
-
-	usb_dev = usb_alloc_dev (NULL, s->bus);
-	if (!usb_dev)
-		return -1;
-
-	s->bus->root_hub = usb_dev;
-	usb_connect (usb_dev);
-
-	if (usb_register_root_hub (usb_dev, &s->uhci_pci->dev) != 0) {
-		usb_free_dev (usb_dev);
-		return -1;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-_static int
-uhci_pci_suspend (struct pci_dev *dev, u32 state)
-{
-	reset_hc((uhci_t *) pci_get_drvdata(dev));
-	return 0;
-}
-
-_static int
-uhci_pci_resume (struct pci_dev *dev)
-{
-	start_hc((uhci_t *) pci_get_drvdata(dev));
-	return 0;
-}
-#endif
-
-_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size)
-{
-	uhci_t *s;
-	struct usb_bus *bus;
-	char buf[8], *bufp = buf;
-
-#ifndef __sparc__
-	sprintf(buf, "%d", irq);
-#else
-	bufp = __irq_itoa(irq);
-#endif
-	printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
-		io_addr, bufp);
-
-	s = kmalloc (sizeof (uhci_t), GFP_KERNEL);
-	if (!s)
-		return -1;
-
-	memset (s, 0, sizeof (uhci_t));
-	INIT_LIST_HEAD (&s->free_desc);
-	INIT_LIST_HEAD (&s->urb_list);
-	INIT_LIST_HEAD (&s->urb_unlinked);
-	spin_lock_init (&s->urb_list_lock);
-	spin_lock_init (&s->qh_lock);
-	spin_lock_init (&s->td_lock);
-	atomic_set(&s->avoid_bulk, 0);
-	s->irq = -1;
-	s->io_addr = io_addr;
-	s->io_size = io_size;
-	s->uhci_pci=dev;
-
-	bus = usb_alloc_bus (&uhci_device_operations);
-	if (!bus) {
-		kfree (s);
-		return -1;
-	}
-
-	s->bus = bus;
-	bus->hcpriv = s;
-
-	/* UHCI specs says devices must have 2 ports, but goes on to say */
-	/* they may have more but give no way to determine how many they */
-	/* have, so default to 2 */
-	/* According to the UHCI spec, Bit 7 is always set to 1. So we try */
-	/* to use this to our advantage */
-
-	for (s->maxports = 0; s->maxports < (io_size - 0x10) / 2; s->maxports++) {
-		unsigned int portstatus;
-
-		portstatus = inw (io_addr + 0x10 + (s->maxports * 2));
-		dbg("port %i, adr %x status %x", s->maxports,
-			io_addr + 0x10 + (s->maxports * 2), portstatus);
-		if (!(portstatus & 0x0080))
-			break;
-	}
-	warn("Detected %d ports", s->maxports);
-
-	/* This is experimental so anything less than 2 or greater than 8 is */
-	/*  something weird and we'll ignore it */
-	if (s->maxports < 2 || s->maxports > 8) {
-		dbg("Port count misdetected, forcing to 2 ports");
-		s->maxports = 2;
-	}
-
-	s->rh.numports = s->maxports;
-	s->loop_usage=0;
-	if (init_skel (s)) {
-		usb_free_bus (bus);
-		kfree(s);
-		return -1;
-	}
-
-	request_region (s->io_addr, io_size, MODNAME);
-	reset_hc (s);
-	usb_register_bus (s->bus);
-
-	start_hc (s);
-
-	if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) {
-		err("request_irq %d failed!",irq);
-		usb_free_bus (bus);
-		reset_hc (s);
-		release_region (s->io_addr, s->io_size);
-		cleanup_skel(s);
-		kfree(s);
-		return -1;
-	}
-
-	/* Enable PIRQ */
-	pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
-
-	s->irq = irq;
-
-	if(uhci_start_usb (s) < 0) {
-		uhci_pci_remove(dev);
-		return -1;
-	}
-
-	//chain new uhci device into global list
-	pci_set_drvdata(dev, s);
-	devs=s;
-
-	return 0;
-}
-
-_static int __devinit
-uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
-{
-	int i;
-
-	if (pci_enable_device(dev) < 0)
-		return -ENODEV;
-		
-	if (!dev->irq) {
-		err("found UHCI device with no IRQ assigned. check BIOS settings!");
-		return -ENODEV;
-	}
-	
-	pci_set_master(dev);
-
-	/* Search for the IO base address.. */
-	for (i = 0; i < 6; i++) {
-
-		unsigned int io_addr = pci_resource_start(dev, i);
-		unsigned int io_size = pci_resource_len(dev, i);
-		if (!(pci_resource_flags(dev,i) & IORESOURCE_IO))
-			continue;
-
-		/* Is it already in use? */
-		if (check_region (io_addr, io_size))
-			break;
-		/* disable legacy emulation */
-		pci_write_config_word (dev, USBLEGSUP, 0);
-	
-		return alloc_uhci(dev, dev->irq, io_addr, io_size);
-	}
-	return -ENODEV;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct pci_device_id __devinitdata uhci_pci_ids [] = { {
-
-	/* handle any USB UHCI controller */
-	class: 		((PCI_CLASS_SERIAL_USB << 8) | 0x00),
-	class_mask: 	~0,
-
-	/* no matter who makes it */
-	vendor:		PCI_ANY_ID,
-	device:		PCI_ANY_ID,
-	subvendor:	PCI_ANY_ID,
-	subdevice:	PCI_ANY_ID,
-
-	}, { /* end: all zeroes */ }
-};
-
-MODULE_DEVICE_TABLE (pci, uhci_pci_ids);
-
-static struct pci_driver uhci_pci_driver = {
-	name:		"usb-uhci",
-	id_table:	&uhci_pci_ids [0],
-
-	probe:		uhci_pci_probe,
-	remove:		uhci_pci_remove,
-
-#ifdef	CONFIG_PM
-	suspend:	uhci_pci_suspend,
-	resume:		uhci_pci_resume,
-#endif	/* PM */
-
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init uhci_hcd_init (void) 
-{
-	int retval;
-
-#ifdef DEBUG_SLAB
-	urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	
-	if(!urb_priv_kmem) {
-		err("kmem_cache_create for urb_priv_t failed (out of memory)");
-		return -ENOMEM;
-	}
-#endif	
-	info(VERSTR);
-
-#ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH
-	info("High bandwidth mode enabled");	
-#endif
-
-	retval = pci_module_init (&uhci_pci_driver);
-
-#ifdef DEBUG_SLAB
-	if (retval < 0 ) {
-		if (kmem_cache_destroy(urb_priv_kmem))
-			err("urb_priv_kmem remained");
-	}
-#endif
-	
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-
-	return retval;
-}
-
-static void __exit uhci_hcd_cleanup (void) 
-{      
-	pci_unregister_driver (&uhci_pci_driver);
-	
-#ifdef DEBUG_SLAB
-	if(kmem_cache_destroy(urb_priv_kmem))
-		err("urb_priv_kmem remained");
-#endif
-}
-
-module_init (uhci_hcd_init);
-module_exit (uhci_hcd_cleanup);
-
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/usb-uhci.h b/drivers/usb/usb-uhci.h
--- a/drivers/usb/usb-uhci.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,307 +0,0 @@
-#ifndef __LINUX_UHCI_H
-#define __LINUX_UHCI_H
-
-/*
-   $Id: usb-uhci.h,v 1.58 2001/08/28 16:45:00 acher Exp $
- */
-#define MODNAME "usb-uhci"
-#define UHCI_LATENCY_TIMER 0
-
-static __inline__ void uhci_wait_ms(unsigned int ms)
-{
-	if(!in_interrupt())
-	{
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(1 + ms * HZ / 1000);
-	}
-	else
-		mdelay(ms);
-}
-
-/* Command register */
-#define USBCMD		0
-#define   USBCMD_RS		0x0001	/* Run/Stop */
-#define   USBCMD_HCRESET	0x0002	/* Host reset */
-#define   USBCMD_GRESET		0x0004	/* Global reset */
-#define   USBCMD_EGSM		0x0008	/* Global Suspend Mode */
-#define   USBCMD_FGR		0x0010	/* Force Global Resume */
-#define   USBCMD_SWDBG		0x0020	/* SW Debug mode */
-#define   USBCMD_CF		0x0040	/* Config Flag (sw only) */
-#define   USBCMD_MAXP		0x0080	/* Max Packet (0 = 32, 1 = 64) */
-
-/* Status register */
-#define USBSTS		2
-#define   USBSTS_USBINT		0x0001	/* Interrupt due to IOC */
-#define   USBSTS_ERROR		0x0002	/* Interrupt due to error */
-#define   USBSTS_RD		0x0004	/* Resume Detect */
-#define   USBSTS_HSE		0x0008	/* Host System Error - basically PCI problems */
-#define   USBSTS_HCPE		0x0010	/* Host Controller Process Error - the scripts were buggy */
-#define   USBSTS_HCH		0x0020	/* HC Halted */
-
-/* Interrupt enable register */
-#define USBINTR		4
-#define   USBINTR_TIMEOUT	0x0001	/* Timeout/CRC error enable */
-#define   USBINTR_RESUME	0x0002	/* Resume interrupt enable */
-#define   USBINTR_IOC		0x0004	/* Interrupt On Complete enable */
-#define   USBINTR_SP		0x0008	/* Short packet interrupt enable */
-
-#define USBFRNUM	6
-#define USBFLBASEADD	8
-#define USBSOF		12
-
-/* USB port status and control registers */
-#define USBPORTSC1	16
-#define USBPORTSC2	18
-#define   USBPORTSC_CCS		0x0001	/* Current Connect Status ("device present") */
-#define   USBPORTSC_CSC		0x0002	/* Connect Status Change */
-#define   USBPORTSC_PE		0x0004	/* Port Enable */
-#define   USBPORTSC_PEC		0x0008	/* Port Enable Change */
-#define   USBPORTSC_LS		0x0030	/* Line Status */
-#define   USBPORTSC_RD		0x0040	/* Resume Detect */
-#define   USBPORTSC_LSDA	0x0100	/* Low Speed Device Attached */
-#define   USBPORTSC_PR		0x0200	/* Port Reset */
-#define   USBPORTSC_SUSP	0x1000	/* Suspend */
-
-/* Legacy support register */
-#define USBLEGSUP 0xc0
-#define USBLEGSUP_DEFAULT 0x2000	/* only PIRQ enable set */
-
-#define UHCI_NULL_DATA_SIZE	0x7ff	/* for UHCI controller TD */
-#define UHCI_PID 		0xff	/* PID MASK */
-
-#define UHCI_PTR_BITS		0x000F
-#define UHCI_PTR_TERM		0x0001
-#define UHCI_PTR_QH		0x0002
-#define UHCI_PTR_DEPTH		0x0004
-
-#define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
-#define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
-#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
-
-/*
- * for TD <status>:
- */
-#define TD_CTRL_SPD		(1 << 29)	/* Short Packet Detect */
-#define TD_CTRL_C_ERR_MASK	(3 << 27)	/* Error Counter bits */
-#define TD_CTRL_LS		(1 << 26)	/* Low Speed Device */
-#define TD_CTRL_IOS		(1 << 25)	/* Isochronous Select */
-#define TD_CTRL_IOC		(1 << 24)	/* Interrupt on Complete */
-#define TD_CTRL_ACTIVE		(1 << 23)	/* TD Active */
-#define TD_CTRL_STALLED		(1 << 22)	/* TD Stalled */
-#define TD_CTRL_DBUFERR		(1 << 21)	/* Data Buffer Error */
-#define TD_CTRL_BABBLE		(1 << 20)	/* Babble Detected */
-#define TD_CTRL_NAK		(1 << 19)	/* NAK Received */
-#define TD_CTRL_CRCTIMEO	(1 << 18)	/* CRC/Time Out Error */
-#define TD_CTRL_BITSTUFF	(1 << 17)	/* Bit Stuff Error */
-#define TD_CTRL_ACTLEN_MASK	0x7ff	/* actual length, encoded as n - 1 */
-
-#define TD_CTRL_ANY_ERROR	(TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
-				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
-
-#define uhci_status_bits(ctrl_sts)	(ctrl_sts & 0xFE0000)
-#define uhci_actual_length(ctrl_sts)	((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK)	/* 1-based */
-
-/*
- * for TD <flags>:
- */
-#define UHCI_TD_REMOVE		0x0001	/* Remove when done */
-
-/*
- * for TD <info>: (a.k.a. Token)
- */
-#define TD_TOKEN_TOGGLE		19
-
-#define uhci_maxlen(token)	((token) >> 21)
-#define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
-#define uhci_endpoint(token)	(((token) >> 15) & 0xf)
-#define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
-#define uhci_devep(token)	(((token) >> 8) & 0x7ff)
-#define uhci_packetid(token)	((token) & 0xff)
-#define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
-#define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
-
-/* ------------------------------------------------------------------------------------
-   New TD/QH-structures
-   ------------------------------------------------------------------------------------ */
-typedef enum {
-	TD_TYPE, QH_TYPE
-} uhci_desc_type_t;
-
-typedef struct {
-	__u32 link;
-	__u32 status;
-	__u32 info;
-	__u32 buffer;
-} uhci_td_t, *puhci_td_t;
-
-typedef struct {
-	__u32 head;
-	__u32 element;		/* Queue element pointer */
-} uhci_qh_t, *puhci_qh_t;
-
-typedef struct {
-	union {
-		uhci_td_t td;
-		uhci_qh_t qh;
-	} hw;
-	uhci_desc_type_t type;
-	dma_addr_t dma_addr;
-	struct list_head horizontal;
-	struct list_head vertical;
-	struct list_head desc_list;
-	int last_used;
-} uhci_desc_t, *puhci_desc_t;
-
-typedef struct {
-	struct list_head desc_list;	// list pointer to all corresponding TDs/QHs associated with this request
-	dma_addr_t setup_packet_dma;
-	dma_addr_t transfer_buffer_dma;
-	unsigned long started;
-	struct urb *next_queued_urb;	// next queued urb for this EP
-	struct urb *prev_queued_urb;
-	uhci_desc_t *bottom_qh;
-	uhci_desc_t *next_qh;       	// next helper QH
-	char use_loop;
-	char flags;
-} urb_priv_t, *purb_priv_t;
-
-struct virt_root_hub {
-	int devnum;		/* Address of Root Hub endpoint */
-	void *urb;
-	void *int_addr;
-	int send;
-	int interval;
-	int numports;
-	int c_p_r[8];
-	struct timer_list rh_int_timer;
-};
-
-typedef struct uhci {
-	int irq;
-	unsigned int io_addr;
-	unsigned int io_size;
-	unsigned int maxports;
-	int running;
-
-	int apm_state;
-
-	struct uhci *next;	// chain of uhci device contexts
-
-	struct list_head urb_list;	// list of all pending urbs
-
-	spinlock_t urb_list_lock;	// lock to keep consistency 
-
-	int unlink_urb_done;
-	atomic_t avoid_bulk;
-	
-	struct usb_bus *bus;	// our bus
-
-	__u32 *framelist;
-	dma_addr_t framelist_dma;
-	uhci_desc_t **iso_td;
-	uhci_desc_t *int_chain[8];
-	uhci_desc_t *ls_control_chain;
-	uhci_desc_t *control_chain;
-	uhci_desc_t *bulk_chain;
-	uhci_desc_t *chain_end;
-	uhci_desc_t *td1ms;
-	uhci_desc_t *td32ms;
-	struct list_head free_desc;
-	spinlock_t qh_lock;
-	spinlock_t td_lock;
-	struct virt_root_hub rh;	//private data of the virtual root hub
-	int loop_usage;            // URBs using bandwidth reclamation
-
-	struct list_head urb_unlinked;	// list of all unlinked  urbs
-	long timeout_check;
-	int timeout_urbs;
-	struct pci_dev *uhci_pci;
-	struct pci_pool *desc_pool;
-	long last_error_time;          // last error output in uhci_interrupt()
-} uhci_t, *puhci_t;
-
-
-#define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH)
-#define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH)
-#define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM))
-
-#define CLEAN_TRANSFER_NO_DELETION 0
-#define CLEAN_TRANSFER_REGULAR 1
-#define CLEAN_TRANSFER_DELETION_MARK 2
-
-#define CLEAN_NOT_FORCED 0
-#define CLEAN_FORCED 1
-
-#define PROCESS_ISO_REGULAR 0
-#define PROCESS_ISO_FORCE 1
-
-#define UNLINK_ASYNC_STORE_URB 0
-#define UNLINK_ASYNC_DONT_STORE 1
-
-#define is_td_active(desc) (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE))
-
-#define set_qh_head(desc,val) (desc)->hw.qh.head=cpu_to_le32(val)
-#define set_qh_element(desc,val) (desc)->hw.qh.element=cpu_to_le32(val)
-#define set_td_link(desc,val) (desc)->hw.td.link=cpu_to_le32(val)
-#define set_td_ioc(desc) (desc)->hw.td.status |= cpu_to_le32(TD_CTRL_IOC)
-#define clr_td_ioc(desc) (desc)->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC)
-
-
-/* ------------------------------------------------------------------------------------ 
-   Virtual Root HUB 
-   ------------------------------------------------------------------------------------ */
-/* destination of request */
-#define RH_INTERFACE               0x01
-#define RH_ENDPOINT                0x02
-#define RH_OTHER                   0x03
-
-#define RH_CLASS                   0x20
-#define RH_VENDOR                  0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS           0x0080
-#define RH_CLEAR_FEATURE        0x0100
-#define RH_SET_FEATURE          0x0300
-#define RH_SET_ADDRESS			0x0500
-#define RH_GET_DESCRIPTOR		0x0680
-#define RH_SET_DESCRIPTOR       0x0700
-#define RH_GET_CONFIGURATION	0x0880
-#define RH_SET_CONFIGURATION	0x0900
-#define RH_GET_STATE            0x0280
-#define RH_GET_INTERFACE        0x0A80
-#define RH_SET_INTERFACE        0x0B00
-#define RH_SYNC_FRAME           0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP               0x2000
-
-
-/* Hub port features */
-#define RH_PORT_CONNECTION         0x00
-#define RH_PORT_ENABLE             0x01
-#define RH_PORT_SUSPEND            0x02
-#define RH_PORT_OVER_CURRENT       0x03
-#define RH_PORT_RESET              0x04
-#define RH_PORT_POWER              0x08
-#define RH_PORT_LOW_SPEED          0x09
-#define RH_C_PORT_CONNECTION       0x10
-#define RH_C_PORT_ENABLE           0x11
-#define RH_C_PORT_SUSPEND          0x12
-#define RH_C_PORT_OVER_CURRENT     0x13
-#define RH_C_PORT_RESET            0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER       0x00
-#define RH_C_HUB_OVER_CURRENT      0x01
-
-#define RH_DEVICE_REMOTE_WAKEUP    0x00
-#define RH_ENDPOINT_STALL          0x01
-
-/* Our Vendor Specific feature */
-#define RH_REMOVE_EP               0x00
-
-
-#define RH_ACK                     0x01
-#define RH_REQ_ERR                 -1
-#define RH_NACK                    0x00
-
-#endif
diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c
--- a/drivers/usb/usb.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2674 +0,0 @@
-/*
- * drivers/usb/usb.c
- *
- * (C) Copyright Linus Torvalds 1999
- * (C) Copyright Johannes Erdfelt 1999-2001
- * (C) Copyright Andreas Gal 1999
- * (C) Copyright Gregory P. Smith 1999
- * (C) Copyright Deti Fliegl 1999 (new USB architecture)
- * (C) Copyright Randy Dunlap 2000
- * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
- 	more docs, etc)
- * (C) Copyright Yggdrasil Computing, Inc. 2000
- *     (usb_device_id matching changes by Adam J. Richter)
- *
- * NOTE! This is not actually a driver at all, rather this is
- * just a collection of helper routines that implement the
- * generic USB things that the real drivers can use..
- *
- * Think of this as a "USB library" rather than anything else.
- * It should be considered a slave, with no callbacks. Callbacks
- * are evil.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>  /* for in_interrupt() */
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/spinlock.h>
-#include <asm/byteorder.h>
-
-#ifdef CONFIG_USB_DEBUG
-	#define DEBUG
-#else
-	#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-#include "hcd.h"
-
-extern int  usb_hub_init(void);
-extern void usb_hub_cleanup(void);
-
-/*
- * Prototypes for the device driver probing/loading functions
- */
-static void usb_find_drivers(struct usb_device *);
-static int  usb_find_interface_driver(struct usb_device *, unsigned int);
-static void usb_check_support(struct usb_device *);
-
-/*
- * We have a per-interface "registered driver" list.
- */
-LIST_HEAD(usb_driver_list);
-
-devfs_handle_t usb_devfs_handle;	/* /dev/usb dir. */
-
-static struct usb_driver *usb_minors[16];
-
-/**
- *	usb_register - register a USB driver
- *	@new_driver: USB operations for the driver
- *
- *	Registers a USB driver with the USB core.  The list of unattached
- *	interfaces will be rescanned whenever a new driver is added, allowing
- *	the new driver to attach to any recognized devices.
- *	Returns a negative error code on failure and 0 on success.
- */
-int usb_register(struct usb_driver *new_driver)
-{
-	if (new_driver->fops != NULL) {
-		if (usb_minors[new_driver->minor/16]) {
-			 err("error registering %s driver", new_driver->name);
-			return -EINVAL;
-		}
-		usb_minors[new_driver->minor/16] = new_driver;
-	}
-
-	info("registered new driver %s", new_driver->name);
-
-	init_MUTEX(&new_driver->serialize);
-
-	/* Add it to the list of known drivers */
-	list_add_tail(&new_driver->driver_list, &usb_driver_list);
-
-	usb_scan_devices();
-
-	usbfs_update_special();
-
-	return 0;
-}
-
-/**
- *	usb_scan_devices - scans all unclaimed USB interfaces
- *	Context: !in_interrupt ()
- *
- *	Goes through all unclaimed USB interfaces, and offers them to all
- *	registered USB drivers through the 'probe' function.
- *	This will automatically be called after usb_register is called.
- *	It is called by some of the subsystems layered over USB
- *	after one of their subdrivers are registered.
- */
-void usb_scan_devices(void)
-{
-	struct list_head *tmp;
-
-	down (&usb_bus_list_lock);
-	tmp = usb_bus_list.next;
-	while (tmp != &usb_bus_list) {
-		struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
-
-		tmp = tmp->next;
-		usb_check_support(bus->root_hub);
-	}
-	up (&usb_bus_list_lock);
-}
-
-/*
- * This function is part of a depth-first search down the device tree,
- * removing any instances of a device driver.
- */
-static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
-{
-	int i;
-
-	if (!dev) {
-		err("null device being purged!!!");
-		return;
-	}
-
-	for (i=0; i<USB_MAXCHILDREN; i++)
-		if (dev->children[i])
-			usb_drivers_purge(driver, dev->children[i]);
-
-	if (!dev->actconfig)
-		return;
-			
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-		struct usb_interface *interface = &dev->actconfig->interface[i];
-		
-		if (interface->driver == driver) {
-			if (driver->owner)
-				__MOD_INC_USE_COUNT(driver->owner);
-			down(&driver->serialize);
-			driver->disconnect(dev, interface->private_data);
-			up(&driver->serialize);
-			if (driver->owner)
-				__MOD_DEC_USE_COUNT(driver->owner);
-			/* if driver->disconnect didn't release the interface */
-			if (interface->driver)
-				usb_driver_release_interface(driver, interface);
-			/*
-			 * This will go through the list looking for another
-			 * driver that can handle the device
-			 */
-			usb_find_interface_driver(dev, i);
-		}
-	}
-}
-
-/**
- *	usb_deregister - unregister a USB driver
- *	@driver: USB operations of the driver to unregister
- *	Context: !in_interrupt ()
- *
- *	Unlinks the specified driver from the internal USB driver list.
- */
-void usb_deregister(struct usb_driver *driver)
-{
-	struct list_head *tmp;
-
-	info("deregistering driver %s", driver->name);
-	if (driver->fops != NULL)
-		usb_minors[driver->minor/16] = NULL;
-
-	/*
-	 * first we remove the driver, to be sure it doesn't get used by
-	 * another thread while we are stepping through removing entries
-	 */
-	list_del(&driver->driver_list);
-
-	down (&usb_bus_list_lock);
-	tmp = usb_bus_list.next;
-	while (tmp != &usb_bus_list) {
-		struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
-
-		tmp = tmp->next;
-		usb_drivers_purge(driver, bus->root_hub);
-	}
-	up (&usb_bus_list_lock);
-
-	usbfs_update_special();
-}
-
-/**
- * usb_ifnum_to_if - get the interface object with a given interface number
- * @dev: the device whose current configuration is considered
- * @ifnum: the desired interface
- *
- * This walks the device descriptor for the currently active configuration
- * and returns a pointer to the interface with that particular interface
- * number, or null.
- *
- * Note that configuration descriptors are not required to assign interface
- * numbers sequentially, so that it would be incorrect to assume that
- * the first interface in that descriptor corresponds to interface zero.
- * This routine helps device drivers avoid such mistakes.
- * However, you should make sure that you do the right thing with any
- * alternate settings available for this interfaces.
- */
-struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
-{
-	int i;
-
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
-		if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum)
-			return &dev->actconfig->interface[i];
-
-	return NULL;
-}
-
-/**
- * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
- * @dev: the device whose current configuration is considered
- * @epnum: the desired endpoint
- *
- * This walks the device descriptor for the currently active configuration,
- * and returns a pointer to the endpoint with that particular endpoint
- * number, or null.
- *
- * Note that interface descriptors are not required to assign endpont
- * numbers sequentially, so that it would be incorrect to assume that
- * the first endpoint in that descriptor corresponds to interface zero.
- * This routine helps device drivers avoid such mistakes.
- */
-struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
-{
-	int i, j, k;
-
-	for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
-		for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++)
-			for (k = 0; k < dev->actconfig->interface[i].altsetting[j].bNumEndpoints; k++)
-				if (epnum == dev->actconfig->interface[i].altsetting[j].endpoint[k].bEndpointAddress)
-					return &dev->actconfig->interface[i].altsetting[j].endpoint[k];
-
-	return NULL;
-}
-
-/*
- * This function is for doing a depth-first search for devices which
- * have support, for dynamic loading of driver modules.
- */
-static void usb_check_support(struct usb_device *dev)
-{
-	int i;
-
-	if (!dev) {
-		err("null device being checked!!!");
-		return;
-	}
-
-	for (i=0; i<USB_MAXCHILDREN; i++)
-		if (dev->children[i])
-			usb_check_support(dev->children[i]);
-
-	if (!dev->actconfig)
-		return;
-
-	/* now we check this device */
-	if (dev->devnum > 0)
-		for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
-			usb_find_interface_driver(dev, i);
-}
-
-
-/**
- * usb_driver_claim_interface - bind a driver to an interface
- * @driver: the driver to be bound
- * @iface: the interface to which it will be bound
- * @priv: driver data associated with that interface
- *
- * This is used by usb device drivers that need to claim more than one
- * interface on a device when probing (audio and acm are current examples).
- * No device driver should directly modify internal usb_interface or
- * usb_device structure members.
- *
- * Few drivers should need to use this routine, since the most natural
- * way to bind to an interface is to return the private data from
- * the driver's probe() method.  Any driver that does use this must
- * first be sure that no other driver has claimed the interface, by
- * checking with usb_interface_claimed().
- */
-void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
-{
-	if (!iface || !driver)
-		return;
-
-	// FIXME change API to report an error in this case
-	if (iface->driver)
-	    err ("%s driver booted %s off interface %p",
-	    	driver->name, iface->driver->name, iface);
-	else
-	    dbg("%s driver claimed interface %p", driver->name, iface);
-
-	iface->driver = driver;
-	iface->private_data = priv;
-} /* usb_driver_claim_interface() */
-
-/**
- * usb_interface_claimed - returns true iff an interface is claimed
- * @iface: the interface being checked
- *
- * This should be used by drivers to check other interfaces to see if
- * they are available or not.  If another driver has claimed the interface,
- * they may not claim it.  Otherwise it's OK to claim it using
- * usb_driver_claim_interface().
- *
- * Returns true (nonzero) iff the interface is claimed, else false (zero).
- */
-int usb_interface_claimed(struct usb_interface *iface)
-{
-	if (!iface)
-		return 0;
-
-	return (iface->driver != NULL);
-} /* usb_interface_claimed() */
-
-/**
- * usb_driver_release_interface - unbind a driver from an interface
- * @driver: the driver to be unbound
- * @iface: the interface from which it will be unbound
- * 
- * This should be used by drivers to release their claimed interfaces.
- * It is normally called in their disconnect() methods, and only for
- * drivers that bound to more than one interface in their probe().
- *
- * When the USB subsystem disconnect()s a driver from some interface,
- * it automatically invokes this method for that interface.  That
- * means that even drivers that used usb_driver_claim_interface()
- * usually won't need to call this.
- */
-void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
-{
-	/* this should never happen, don't release something that's not ours */
-	if (!iface || iface->driver != driver)
-		return;
-
-	iface->driver = NULL;
-	iface->private_data = NULL;
-}
-
-
-/**
- * usb_match_id - find first usb_device_id matching device or interface
- * @dev: the device whose descriptors are considered when matching
- * @interface: the interface of interest
- * @id: array of usb_device_id structures, terminated by zero entry
- *
- * usb_match_id searches an array of usb_device_id's and returns
- * the first one matching the device or interface, or null.
- * This is used when binding (or rebinding) a driver to an interface.
- * Most USB device drivers will use this indirectly, through the usb core,
- * but some layered driver frameworks use it directly.
- * These device tables are exported with MODULE_DEVICE_TABLE, through
- * modutils and "modules.usbmap", to support the driver loading
- * functionality of USB hotplugging.
- *
- * What Matches:
- *
- * The "match_flags" element in a usb_device_id controls which
- * members are used.  If the corresponding bit is set, the
- * value in the device_id must match its corresponding member
- * in the device or interface descriptor, or else the device_id
- * does not match.
- *
- * "driver_info" is normally used only by device drivers,
- * but you can create a wildcard "matches anything" usb_device_id
- * as a driver's "modules.usbmap" entry if you provide an id with
- * only a nonzero "driver_info" field.  If you do this, the USB device
- * driver's probe() routine should use additional intelligence to
- * decide whether to bind to the specified interface.
- * 
- * What Makes Good usb_device_id Tables:
- *
- * The match algorithm is very simple, so that intelligence in
- * driver selection must come from smart driver id records.
- * Unless you have good reasons to use another selection policy,
- * provide match elements only in related groups, and order match
- * specifiers from specific to general.  Use the macros provided
- * for that purpose if you can.
- *
- * The most specific match specifiers use device descriptor
- * data.  These are commonly used with product-specific matches;
- * the USB_DEVICE macro lets you provide vendor and product IDs,
- * and you can also match against ranges of product revisions.
- * These are widely used for devices with application or vendor
- * specific bDeviceClass values.
- *
- * Matches based on device class/subclass/protocol specifications
- * are slightly more general; use the USB_DEVICE_INFO macro, or
- * its siblings.  These are used with single-function devices
- * where bDeviceClass doesn't specify that each interface has
- * its own class. 
- *
- * Matches based on interface class/subclass/protocol are the
- * most general; they let drivers bind to any interface on a
- * multiple-function device.  Use the USB_INTERFACE_INFO
- * macro, or its siblings, to match class-per-interface style 
- * devices (as recorded in bDeviceClass).
- *  
- * Within those groups, remember that not all combinations are
- * meaningful.  For example, don't give a product version range
- * without vendor and product IDs; or specify a protocol without
- * its associated class and subclass.
- */   
-const struct usb_device_id *
-usb_match_id(struct usb_device *dev, struct usb_interface *interface,
-	     const struct usb_device_id *id)
-{
-	struct usb_interface_descriptor	*intf = 0;
-
-	/* proc_connectinfo in devio.c may call us with id == NULL. */
-	if (id == NULL)
-		return NULL;
-
-	/* It is important to check that id->driver_info is nonzero,
-	   since an entry that is all zeroes except for a nonzero
-	   id->driver_info is the way to create an entry that
-	   indicates that the driver want to examine every
-	   device and interface. */
-	for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
-	       id->driver_info; id++) {
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
-		    id->idVendor != dev->descriptor.idVendor)
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
-		    id->idProduct != dev->descriptor.idProduct)
-			continue;
-
-		/* No need to test id->bcdDevice_lo != 0, since 0 is never
-		   greater than any unsigned number. */
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
-		    (id->bcdDevice_lo > dev->descriptor.bcdDevice))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
-		    (id->bcdDevice_hi < dev->descriptor.bcdDevice))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
-		    (id->bDeviceClass != dev->descriptor.bDeviceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
-		    (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
-		    (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
-			continue;
-
-		intf = &interface->altsetting [interface->act_altsetting];
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
-		    (id->bInterfaceClass != intf->bInterfaceClass))
-			continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
-		    (id->bInterfaceSubClass != intf->bInterfaceSubClass))
-		    continue;
-
-		if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
-		    (id->bInterfaceProtocol != intf->bInterfaceProtocol))
-		    continue;
-
-		return id;
-	}
-
-	return NULL;
-}
-
-/*
- * This entrypoint gets called for each new device.
- *
- * We now walk the list of registered USB drivers,
- * looking for one that will accept this interface.
- *
- * "New Style" drivers use a table describing the devices and interfaces
- * they handle.  Those tables are available to user mode tools deciding
- * whether to load driver modules for a new device.
- *
- * The probe return value is changed to be a private pointer.  This way
- * the drivers don't have to dig around in our structures to set the
- * private pointer if they only need one interface. 
- *
- * Returns: 0 if a driver accepted the interface, -1 otherwise
- */
-static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
-{
-	struct list_head *tmp;
-	struct usb_interface *interface;
-	void *private;
-	const struct usb_device_id *id;
-	struct usb_driver *driver;
-	int i;
-	
-	if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
-		err("bad find_interface_driver params");
-		return -1;
-	}
-
-	down(&dev->serialize);
-
-	interface = dev->actconfig->interface + ifnum;
-
-	if (usb_interface_claimed(interface))
-		goto out_err;
-
-	private = NULL;
-	for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {
-		driver = list_entry(tmp, struct usb_driver, driver_list);
-		tmp = tmp->next;
-
-		if (driver->owner)
-			__MOD_INC_USE_COUNT(driver->owner);
-		id = driver->id_table;
-		/* new style driver? */
-		if (id) {
-			for (i = 0; i < interface->num_altsetting; i++) {
-			  	interface->act_altsetting = i;
-				id = usb_match_id(dev, interface, id);
-				if (id) {
-					down(&driver->serialize);
-					private = driver->probe(dev,ifnum,id);
-					up(&driver->serialize);
-					if (private != NULL)
-						break;
-				}
-			}
-
-			/* if driver not bound, leave defaults unchanged */
-			if (private == NULL)
-				interface->act_altsetting = 0;
-		} else { /* "old style" driver */
-			down(&driver->serialize);
-			private = driver->probe(dev, ifnum, NULL);
-			up(&driver->serialize);
-		}
-		if (driver->owner)
-			__MOD_DEC_USE_COUNT(driver->owner);
-
-		/* probe() may have changed the config on us */
-		interface = dev->actconfig->interface + ifnum;
-
-		if (private) {
-			usb_driver_claim_interface(driver, interface, private);
-			up(&dev->serialize);
-			return 0;
-		}
-	}
-
-out_err:
-	up(&dev->serialize);
-	return -1;
-}
-
-
-#ifdef	CONFIG_HOTPLUG
-
-/*
- * USB hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when USB devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
- * or other modules, configure the device, and more.  Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- * Some synchronization is important: removes can't start processing
- * before the add-device processing completes, and vice versa.  That keeps
- * a stack of USB-related identifiers stable while they're in use.  If we
- * know that agents won't complete after they return (such as by forking
- * a process that completes later), it's enough to just waitpid() for the
- * agent -- as is currently done.
- *
- * The reason: we know we're called either from khubd (the typical case)
- * or from root hub initialization (init, kapmd, modprobe, etc).  In both
- * cases, we know no other thread can recycle our address, since we must
- * already have been serialized enough to prevent that.
- */
-static void call_policy (char *verb, struct usb_device *dev)
-{
-	char *argv [3], **envp, *buf, *scratch;
-	int i = 0, value;
-
-	if (!hotplug_path [0])
-		return;
-	if (in_interrupt ()) {
-		dbg ("In_interrupt");
-		return;
-	}
-	if (!current->fs->root) {
-		/* statically linked USB is initted rather early */
-		dbg ("call_policy %s, num %d -- no FS yet", verb, dev->devnum);
-		return;
-	}
-	if (dev->devnum < 0) {
-		dbg ("device already deleted ??");
-		return;
-	}
-	if (!(envp = (char **) kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
-		dbg ("enomem");
-		return;
-	}
-	if (!(buf = kmalloc (256, GFP_KERNEL))) {
-		kfree (envp);
-		dbg ("enomem2");
-		return;
-	}
-
-	/* only one standardized param to hotplug command: type */
-	argv [0] = hotplug_path;
-	argv [1] = "usb";
-	argv [2] = 0;
-
-	/* minimal command environment */
-	envp [i++] = "HOME=/";
-	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
-#ifdef	DEBUG
-	/* hint that policy agent should enter no-stdout debug mode */
-	envp [i++] = "DEBUG=kernel";
-#endif
-	/* extensible set of named bus-specific parameters,
-	 * supporting multiple driver selection algorithms.
-	 */
-	scratch = buf;
-
-	/* action:  add, remove */
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "ACTION=%s", verb) + 1;
-
-#ifdef	CONFIG_USB_DEVICEFS
-	/* If this is available, userspace programs can directly read
-	 * all the device descriptors we don't tell them about.  Or
-	 * even act as usermode drivers.
-	 *
-	 * FIXME reduce hardwired intelligence here
-	 */
-	envp [i++] = "DEVFS=/proc/bus/usb";
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "DEVICE=/proc/bus/usb/%03d/%03d",
-		dev->bus->busnum, dev->devnum) + 1;
-#endif
-
-	/* per-device configuration hacks are common */
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "PRODUCT=%x/%x/%x",
-		dev->descriptor.idVendor,
-		dev->descriptor.idProduct,
-		dev->descriptor.bcdDevice) + 1;
-
-	/* class-based driver binding models */
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "TYPE=%d/%d/%d",
-			    dev->descriptor.bDeviceClass,
-			    dev->descriptor.bDeviceSubClass,
-			    dev->descriptor.bDeviceProtocol) + 1;
-	if (dev->descriptor.bDeviceClass == 0) {
-		int alt = dev->actconfig->interface [0].act_altsetting;
-
-		/* a simple/common case: one config, one interface, one driver
-		 * with current altsetting being a reasonable setting.
-		 * everything needs a smart agent and usbfs; or can rely on
-		 * device-specific binding policies.
-		 */
-		envp [i++] = scratch;
-		scratch += sprintf (scratch, "INTERFACE=%d/%d/%d",
-			dev->actconfig->interface [0].altsetting [alt].bInterfaceClass,
-			dev->actconfig->interface [0].altsetting [alt].bInterfaceSubClass,
-			dev->actconfig->interface [0].altsetting [alt].bInterfaceProtocol)
-			+ 1;
-		/* INTERFACE-0, INTERFACE-1, ... ? */
-	}
-	envp [i++] = 0;
-	/* assert: (scratch - buf) < sizeof buf */
-
-	/* NOTE: user mode daemons can call the agents too */
-
-	dbg ("kusbd: %s %s %d", argv [0], verb, dev->devnum);
-	value = call_usermodehelper (argv [0], argv, envp);
-	kfree (buf);
-	kfree (envp);
-	if (value != 0)
-		dbg ("kusbd policy returned 0x%x", value);
-}
-
-#else
-
-static inline void
-call_policy (char *verb, struct usb_device *dev)
-{ } 
-
-#endif	/* CONFIG_HOTPLUG */
-
-
-/*
- * This entrypoint gets called for each new device.
- *
- * All interfaces are scanned for matching drivers.
- */
-static void usb_find_drivers(struct usb_device *dev)
-{
-	unsigned ifnum;
-	unsigned rejected = 0;
-	unsigned claimed = 0;
-
-	for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
-		struct usb_interface *interface = &dev->actconfig->interface[ifnum];
-		
-		/* register this interface with driverfs */
-		interface->dev.parent = &dev->dev;
-		sprintf (&interface->dev.bus_id[0], "%03d", ifnum);
-		sprintf (&interface->dev.name[0], "figure out some name...");
-		device_register (&interface->dev);
-
-		/* if this interface hasn't already been claimed */
-		if (!usb_interface_claimed(interface)) {
-			if (usb_find_interface_driver(dev, ifnum))
-				rejected++;
-			else
-				claimed++;
-		}
-	}
- 
-	if (rejected)
-		dbg("unhandled interfaces on device");
-
-	if (!claimed) {
-		warn("USB device %d (vend/prod 0x%x/0x%x) is not claimed by any active driver.",
-			dev->devnum,
-			dev->descriptor.idVendor,
-			dev->descriptor.idProduct);
-#ifdef DEBUG
-		usb_show_device(dev);
-#endif
-	}
-}
-
-/**
- * usb_alloc_dev - allocate a usb device structure (usbcore-internal)
- * @parent: hub to which device is connected
- * @bus: bus used to access the device
- * Context: !in_interrupt ()
- *
- * Only hub drivers (including virtual root hub drivers for host
- * controllers) should ever call this.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- */
-struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
-{
-	struct usb_device *dev;
-
-	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
-	memset(dev, 0, sizeof(*dev));
-
-	usb_bus_get(bus);
-
-	if (!parent)
-		dev->devpath [0] = '/';
-	dev->bus = bus;
-	dev->parent = parent;
-	atomic_set(&dev->refcnt, 1);
-	INIT_LIST_HEAD(&dev->filelist);
-
-	init_MUTEX(&dev->serialize);
-
-	dev->bus->op->allocate(dev);
-
-	return dev;
-}
-
-// usbcore-internal ...
-// but usb_dec_dev_use() is #defined to this, and that's public!!
-void usb_free_dev(struct usb_device *dev)
-{
-	if (atomic_dec_and_test(&dev->refcnt)) {
-		dev->bus->op->deallocate(dev);
-		usb_destroy_configuration(dev);
-
-		usb_bus_put(dev->bus);
-
-		kfree(dev);
-	}
-}
-
-/**
- * usb_inc_dev_use - record another reference to a device
- * @dev: the device being referenced
- *
- * Each live reference to a device should be refcounted.
- *
- * Device drivers should normally record such references in their
- * open() methods.
- * Drivers should then release them, using usb_dec_dev_use(), in their
- * close() methods.
- */
-void usb_inc_dev_use(struct usb_device *dev)
-{
-	atomic_inc(&dev->refcnt);
-}
-
-
-/**
- * usb_alloc_urb - creates a new urb for a USB driver to use
- * @iso_packets: number of iso packets for this urb
- * @mem_flags: the type of memory to allocate, see kmalloc() for a list of
- *	valid options for this.
- *
- * Creates an urb for the USB driver to use, initializes a few internal
- * structures, incrementes the usage counter, and returns a pointer to it.
- *
- * If no memory is available, NULL is returned.
- *
- * If the driver want to use this urb for interrupt, control, or bulk
- * endpoints, pass '0' as the number of iso packets.
- *
- * The driver must call usb_free_urb() when it is finished with the urb.
- */
-struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
-{
-	struct urb *urb;
-
-	urb = (struct urb *)kmalloc(sizeof(struct urb) + 
-		iso_packets * sizeof(struct usb_iso_packet_descriptor),
-		mem_flags);
-	if (!urb) {
-		err("alloc_urb: kmalloc failed");
-		return NULL;
-	}
-
-	memset(urb, 0, sizeof(*urb));
-	urb->count = (atomic_t)ATOMIC_INIT(1);
-	spin_lock_init(&urb->lock);
-
-	return urb;
-}
-
-/**
- * usb_free_urb - frees the memory used by a urb when all users of it are finished
- * @urb: pointer to the urb to free
- *
- * Must be called when a user of a urb is finished with it.  When the last user
- * of the urb calls this function, the memory of the urb is freed.
- *
- * Note: The transfer buffer associated with the urb is not freed, that must be
- * done elsewhere.
- */
-void usb_free_urb(struct urb *urb)
-{
-	if (urb)
-		if (atomic_dec_and_test(&urb->count))
-			kfree(urb);
-}
-
-/**
- * usb_get_urb - incrementes the reference count of the urb
- * @urb: pointer to the urb to modify
- *
- * This must be  called whenever a urb is transfered from a device driver to a
- * host controller driver.  This allows proper reference counting to happen
- * for urbs.
- *
- * A pointer to the urb with the incremented reference counter is returned.
- */
-struct urb * usb_get_urb(struct urb *urb)
-{
-	if (urb) {
-		atomic_inc(&urb->count);
-		return urb;
-	} else
-		return NULL;
-}
-		
-		
-/*-------------------------------------------------------------------*/
-
-/**
- * usb_submit_urb - asynchronously issue a transfer request for an endpoint
- * @urb: pointer to the urb describing the request
- * @mem_flags: the type of memory to allocate, see kmalloc() for a list
- *	of valid options for this.
- *
- * This submits a transfer request, and transfers control of the URB
- * describing that request to the USB subsystem.  Request completion will
- * indicated later, asynchronously, by calling the completion handler.
- * This call may be issued in interrupt context.
- *
- * The caller must have correctly initialized the URB before submitting
- * it.  Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
- * available to ensure that most fields are correctly initialized, for
- * the particular kind of transfer, although they will not initialize
- * any transfer flags.
- *
- * Successful submissions return 0; otherwise this routine returns a
- * negative error number.  If the submission is successful, the complete
- * fuction of the urb will be called when the USB host driver is
- * finished with the urb (either a successful transmission, or some
- * error case.)
- *
- * Unreserved Bandwidth Transfers:
- *
- * Bulk or control requests complete only once.  When the completion
- * function is called, control of the URB is returned to the device
- * driver which issued the request.  The completion handler may then
- * immediately free or reuse that URB.
- *
- * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set
- * in the URB.  This can be used to maximize bandwidth utilization by
- * letting the USB controller start work on the next URB without any
- * delay to report completion (scheduling and processing an interrupt)
- * and then submit that next request.
- *
- * For control endpoints, the synchronous usb_control_msg() call is
- * often used (in non-interrupt context) instead of this call.
- *
- * Reserved Bandwidth Transfers:
- *
- * Periodic URBs (interrupt or isochronous) are completed repeatedly,
- * until the original request is aborted.  When the completion callback
- * indicates the URB has been unlinked (with a special status code),
- * control of that URB returns to the device driver.  Otherwise, the
- * completion handler does not control the URB, and should not change
- * any of its fields.
- *
- * Note that isochronous URBs should be submitted in a "ring" data
- * structure (using urb->next) to ensure that they are resubmitted
- * appropriately.
- *
- * If the USB subsystem can't reserve sufficient bandwidth to perform
- * the periodic request, and bandwidth reservation is being done for
- * this controller, submitting such a periodic request will fail.
- *
- * Memory Flags:
- *
- * General rules for how to decide which mem_flags to use:
- * 
- * Basically the rules are the same as for kmalloc.  There are four
- * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
- * GFP_ATOMIC.
- *
- * GFP_NOFS is not ever used, as it has not been implemented yet.
- *
- * There are three situations you must use GFP_ATOMIC.
- *    a) you are inside a completion handler, an interrupt, bottom half,
- *       tasklet or timer.
- *    b) you are holding a spinlock or rwlock (does not apply to
- *       semaphores)
- *    c) current->state != TASK_RUNNING, this is the case only after
- *       you've changed it.
- * 
- * GFP_NOIO is used in the block io path and error handling of storage
- * devices.
- *
- * All other situations use GFP_KERNEL.
- *
- * Specfic rules for how to decide which mem_flags to use:
- *
- *    - start_xmit, timeout, and receive methods of network drivers must
- *      use GFP_ATOMIC (spinlock)
- *    - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock)
- *    - If you use a kernel thread with a network driver you must use
- *      GFP_NOIO, unless b) or c) apply
- *    - After you have done a down() you use GFP_KERNEL, unless b) or c)
- *      apply or your are in a storage driver's block io path
- *    - probe and disconnect use GFP_KERNEL unless b) or c) apply
- *    - Changing firmware on a running storage or net device uses
- *      GFP_NOIO, unless b) or c) apply
- *
- */
-int usb_submit_urb(struct urb *urb, int mem_flags)
-{
-	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
-		return urb->dev->bus->op->submit_urb(urb, mem_flags);
-	else
-		return -ENODEV;
-}
-
-/*-------------------------------------------------------------------*/
-
-/**
- * usb_unlink_urb - abort/cancel a transfer request for an endpoint
- * @urb: pointer to urb describing a previously submitted request
- *
- * This routine cancels an in-progress request.  The requests's
- * completion handler will be called with a status code indicating
- * that the request has been canceled, and that control of the URB
- * has been returned to that device driver.  This is the only way
- * to stop an interrupt transfer, so long as the device is connected.
- *
- * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this
- * request is synchronous.  Success is indicated by returning zero,
- * at which time the urb will have been unlinked,
- * and the completion function will see status -ENOENT.  Failure is
- * indicated by any other return value.  This mode may not be used
- * when unlinking an urb from an interrupt context, such as a bottom
- * half or a completion handler,
- *
- * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this
- * request is asynchronous.  Success is indicated by returning -EINPROGRESS,
- * at which time the urb will normally not have been unlinked,
- * and the completion function will see status -ECONNRESET.  Failure is
- * indicated by any other return value.
- */
-int usb_unlink_urb(struct urb *urb)
-{
-	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
-		return urb->dev->bus->op->unlink_urb(urb);
-	else
-		return -ENODEV;
-}
-/*-------------------------------------------------------------------*
- *                         SYNCHRONOUS CALLS                         *
- *-------------------------------------------------------------------*/
-
-struct usb_api_data {
-	wait_queue_head_t wqh;
-	int done;
-};
-
-static void usb_api_blocking_completion(struct urb *urb)
-{
-	struct usb_api_data *awd = (struct usb_api_data *)urb->context;
-
-	awd->done = 1;
-	wmb();
-	wake_up(&awd->wqh);
-}
-
-// Starts urb and waits for completion or timeout
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
-{ 
-	DECLARE_WAITQUEUE(wait, current);
-	struct usb_api_data awd;
-	int status;
-
-	init_waitqueue_head(&awd.wqh); 	
-	awd.done = 0;
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&awd.wqh, &wait);
-
-	urb->context = &awd;
-	status = usb_submit_urb(urb, GFP_KERNEL);
-	if (status) {
-		// something went wrong
-		usb_free_urb(urb);
-		set_current_state(TASK_RUNNING);
-		remove_wait_queue(&awd.wqh, &wait);
-		return status;
-	}
-
-	while (timeout && !awd.done)
-	{
-		timeout = schedule_timeout(timeout);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		rmb();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&awd.wqh, &wait);
-
-	if (!timeout && !awd.done) {
-		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
-			printk(KERN_ERR "usb: raced timeout, "
-			    "pipe 0x%x status %d time left %d\n",
-			    urb->pipe, urb->status, timeout);
-			status = urb->status;
-		} else {
-			printk("usb_control/bulk_msg: timeout\n");
-			usb_unlink_urb(urb);  // remove urb safely
-			status = -ETIMEDOUT;
-		}
-	} else
-		status = urb->status;
-
-	if (actual_length)
-		*actual_length = urb->actual_length;
-
-	usb_free_urb(urb);
-  	return status;
-}
-
-/*-------------------------------------------------------------------*/
-// returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, 
-			    struct usb_ctrlrequest *cmd,  void *data, int len, int timeout)
-{
-	struct urb *urb;
-	int retv;
-	int length;
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
-  
-	FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,
-		   usb_api_blocking_completion, 0);
-
-	retv = usb_start_wait_urb(urb, timeout, &length);
-	if (retv < 0)
-		return retv;
-	else
-		return length;
-}
-
-/**
- *	usb_control_msg - Builds a control urb, sends it off and waits for completion
- *	@dev: pointer to the usb device to send the message to
- *	@pipe: endpoint "pipe" to send the message to
- *	@request: USB message request value
- *	@requesttype: USB message request type value
- *	@value: USB message value
- *	@index: USB message index value
- *	@data: pointer to the data to send
- *	@size: length in bytes of the data to send
- *	@timeout: time in jiffies to wait for the message to complete before
- *		timing out (if 0 the wait is forever)
- *	Context: !in_interrupt ()
- *
- *	This function sends a simple control message to a specified endpoint
- *	and waits for the message to complete, or timeout.
- *	
- *	If successful, it returns 0, otherwise a negative error number.
- *
- *	Don't use this function from within an interrupt context, like a
- *	bottom half handler.  If you need an asynchronous message, or need to send
- *	a message from within interrupt context, use usb_submit_urb()
- */
-int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
-			 __u16 value, __u16 index, void *data, __u16 size, int timeout)
-{
-	struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
-	int ret;
-	
-	if (!dr)
-		return -ENOMEM;
-
-	dr->bRequestType= requesttype;
-	dr->bRequest = request;
-	dr->wValue = cpu_to_le16p(&value);
-	dr->wIndex = cpu_to_le16p(&index);
-	dr->wLength = cpu_to_le16p(&size);
-
-	//dbg("usb_control_msg");	
-
-	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
-
-	kfree(dr);
-
-	return ret;
-}
-
-
-/**
- *	usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
- *	@usb_dev: pointer to the usb device to send the message to
- *	@pipe: endpoint "pipe" to send the message to
- *	@data: pointer to the data to send
- *	@len: length in bytes of the data to send
- *	@actual_length: pointer to a location to put the actual length transferred in bytes
- *	@timeout: time in jiffies to wait for the message to complete before
- *		timing out (if 0 the wait is forever)
- *	Context: !in_interrupt ()
- *
- *	This function sends a simple bulk message to a specified endpoint
- *	and waits for the message to complete, or timeout.
- *	
- *	If successful, it returns 0, otherwise a negative error number.
- *	The number of actual bytes transferred will be stored in the 
- *	actual_length paramater.
- *
- *	Don't use this function from within an interrupt context, like a
- *	bottom half handler.  If you need an asynchronous message, or need to
- *	send a message from within interrupt context, use usb_submit_urb()
- */
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 
-			void *data, int len, int *actual_length, int timeout)
-{
-	struct urb *urb;
-
-	if (len < 0)
-		return -EINVAL;
-
-	urb=usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb)
-		return -ENOMEM;
-
-	FILL_BULK_URB(urb, usb_dev, pipe, data, len,
-		    usb_api_blocking_completion, 0);
-
-	return usb_start_wait_urb(urb,timeout,actual_length);
-}
-
-/**
- * usb_get_current_frame_number - return current bus frame number
- * @dev: the device whose bus is being queried
- *
- * Returns the current frame number for the USB host controller
- * used with the given USB device.  This can be used when scheduling
- * isochronous requests.
- *
- * Note that different kinds of host controller have different
- * "scheduling horizons".  While one type might support scheduling only
- * 32 frames into the future, others could support scheduling up to
- * 1024 frames into the future.
- */
-int usb_get_current_frame_number(struct usb_device *dev)
-{
-	return dev->bus->op->get_frame_number (dev);
-}
-
-/*-------------------------------------------------------------------*/
-
-static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
-{
-	struct usb_descriptor_header *header;
-	unsigned char *begin;
-	int parsed = 0, len, numskipped;
-
-	header = (struct usb_descriptor_header *)buffer;
-
-	/* Everything should be fine being passed into here, but we sanity */
-	/*  check JIC */
-	if (header->bLength > size) {
-		err("ran out of descriptors parsing");
-		return -1;
-	}
-		
-	if (header->bDescriptorType != USB_DT_ENDPOINT) {
-		warn("unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
-			endpoint->bDescriptorType, USB_DT_ENDPOINT);
-		return parsed;
-	}
-
-	if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
-		memcpy(endpoint, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
-	else
-		memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
-	
-	le16_to_cpus(&endpoint->wMaxPacketSize);
-
-	buffer += header->bLength;
-	size -= header->bLength;
-	parsed += header->bLength;
-
-	/* Skip over the rest of the Class Specific or Vendor Specific */
-	/*  descriptors */
-	begin = buffer;
-	numskipped = 0;
-	while (size >= sizeof(struct usb_descriptor_header)) {
-		header = (struct usb_descriptor_header *)buffer;
-
-		if (header->bLength < 2) {
-			err("invalid descriptor length of %d", header->bLength);
-			return -1;
-		}
-
-		/* If we find another "proper" descriptor then we're done  */
-		if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
-		    (header->bDescriptorType == USB_DT_INTERFACE) ||
-		    (header->bDescriptorType == USB_DT_CONFIG) ||
-		    (header->bDescriptorType == USB_DT_DEVICE))
-			break;
-
-		dbg("skipping descriptor 0x%X",
-			header->bDescriptorType);
-		numskipped++;
-
-		buffer += header->bLength;
-		size -= header->bLength;
-		parsed += header->bLength;
-	}
-	if (numskipped)
-		dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
-
-	/* Copy any unknown descriptors into a storage area for drivers */
-	/*  to later parse */
-	len = (int)(buffer - begin);
-	if (!len) {
-		endpoint->extra = NULL;
-		endpoint->extralen = 0;
-		return parsed;
-	}
-
-	endpoint->extra = kmalloc(len, GFP_KERNEL);
-
-	if (!endpoint->extra) {
-		err("couldn't allocate memory for endpoint extra descriptors");
-		endpoint->extralen = 0;
-		return parsed;
-	}
-
-	memcpy(endpoint->extra, begin, len);
-	endpoint->extralen = len;
-
-	return parsed;
-}
-
-static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size)
-{
-	int i, len, numskipped, retval, parsed = 0;
-	struct usb_descriptor_header *header;
-	struct usb_interface_descriptor *ifp;
-	unsigned char *begin;
-
-	interface->act_altsetting = 0;
-	interface->num_altsetting = 0;
-	interface->max_altsetting = USB_ALTSETTINGALLOC;
-
-	interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
-	
-	if (!interface->altsetting) {
-		err("couldn't kmalloc interface->altsetting");
-		return -1;
-	}
-
-	while (size > 0) {
-		if (interface->num_altsetting >= interface->max_altsetting) {
-			void *ptr;
-			int oldmas;
-
-			oldmas = interface->max_altsetting;
-			interface->max_altsetting += USB_ALTSETTINGALLOC;
-			if (interface->max_altsetting > USB_MAXALTSETTING) {
-				warn("too many alternate settings (max %d)",
-					USB_MAXALTSETTING);
-				return -1;
-			}
-
-			ptr = interface->altsetting;
-			interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * interface->max_altsetting, GFP_KERNEL);
-			if (!interface->altsetting) {
-				err("couldn't kmalloc interface->altsetting");
-				interface->altsetting = ptr;
-				return -1;
-			}
-			memcpy(interface->altsetting, ptr, sizeof(struct usb_interface_descriptor) * oldmas);
-
-			kfree(ptr);
-		}
-
-		ifp = interface->altsetting + interface->num_altsetting;
-		ifp->endpoint = NULL;
-		ifp->extra = NULL;
-		ifp->extralen = 0;
-		interface->num_altsetting++;
-
-		memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
-
-		/* Skip over the interface */
-		buffer += ifp->bLength;
-		parsed += ifp->bLength;
-		size -= ifp->bLength;
-
-		begin = buffer;
-		numskipped = 0;
-
-		/* Skip over any interface, class or vendor descriptors */
-		while (size >= sizeof(struct usb_descriptor_header)) {
-			header = (struct usb_descriptor_header *)buffer;
-
-			if (header->bLength < 2) {
-				err("invalid descriptor length of %d", header->bLength);
-				return -1;
-			}
-
-			/* If we find another "proper" descriptor then we're done  */
-			if ((header->bDescriptorType == USB_DT_INTERFACE) ||
-			    (header->bDescriptorType == USB_DT_ENDPOINT) ||
-			    (header->bDescriptorType == USB_DT_CONFIG) ||
-			    (header->bDescriptorType == USB_DT_DEVICE))
-				break;
-
-			numskipped++;
-
-			buffer += header->bLength;
-			parsed += header->bLength;
-			size -= header->bLength;
-		}
-
-		if (numskipped)
-			dbg("skipped %d class/vendor specific interface descriptors", numskipped);
-
-		/* Copy any unknown descriptors into a storage area for */
-		/*  drivers to later parse */
-		len = (int)(buffer - begin);
-		if (len) {
-			ifp->extra = kmalloc(len, GFP_KERNEL);
-
-			if (!ifp->extra) {
-				err("couldn't allocate memory for interface extra descriptors");
-				ifp->extralen = 0;
-				return -1;
-			}
-			memcpy(ifp->extra, begin, len);
-			ifp->extralen = len;
-		}
-
-		/* Did we hit an unexpected descriptor? */
-		header = (struct usb_descriptor_header *)buffer;
-		if ((size >= sizeof(struct usb_descriptor_header)) &&
-		    ((header->bDescriptorType == USB_DT_CONFIG) ||
-		     (header->bDescriptorType == USB_DT_DEVICE)))
-			return parsed;
-
-		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
-			warn("too many endpoints");
-			return -1;
-		}
-
-		ifp->endpoint = (struct usb_endpoint_descriptor *)
-			kmalloc(ifp->bNumEndpoints *
-			sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
-		if (!ifp->endpoint) {
-			err("out of memory");
-			return -1;	
-		}
-
-		memset(ifp->endpoint, 0, ifp->bNumEndpoints *
-			sizeof(struct usb_endpoint_descriptor));
-	
-		for (i = 0; i < ifp->bNumEndpoints; i++) {
-			header = (struct usb_descriptor_header *)buffer;
-
-			if (header->bLength > size) {
-				err("ran out of descriptors parsing");
-				return -1;
-			}
-		
-			retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size);
-			if (retval < 0)
-				return retval;
-
-			buffer += retval;
-			parsed += retval;
-			size -= retval;
-		}
-
-		/* We check to see if it's an alternate to this one */
-		ifp = (struct usb_interface_descriptor *)buffer;
-		if (size < USB_DT_INTERFACE_SIZE ||
-		    ifp->bDescriptorType != USB_DT_INTERFACE ||
-		    !ifp->bAlternateSetting)
-			return parsed;
-	}
-
-	return parsed;
-}
-
-int usb_parse_configuration(struct usb_config_descriptor *config, char *buffer)
-{
-	int i, retval, size;
-	struct usb_descriptor_header *header;
-
-	memcpy(config, buffer, USB_DT_CONFIG_SIZE);
-	le16_to_cpus(&config->wTotalLength);
-	size = config->wTotalLength;
-
-	if (config->bNumInterfaces > USB_MAXINTERFACES) {
-		warn("too many interfaces");
-		return -1;
-	}
-
-	config->interface = (struct usb_interface *)
-		kmalloc(config->bNumInterfaces *
-		sizeof(struct usb_interface), GFP_KERNEL);
-	dbg("kmalloc IF %p, numif %i", config->interface, config->bNumInterfaces);
-	if (!config->interface) {
-		err("out of memory");
-		return -1;	
-	}
-
-	memset(config->interface, 0,
-	       config->bNumInterfaces * sizeof(struct usb_interface));
-
-	buffer += config->bLength;
-	size -= config->bLength;
-	
-	config->extra = NULL;
-	config->extralen = 0;
-
-	for (i = 0; i < config->bNumInterfaces; i++) {
-		int numskipped, len;
-		char *begin;
-
-		/* Skip over the rest of the Class Specific or Vendor */
-		/*  Specific descriptors */
-		begin = buffer;
-		numskipped = 0;
-		while (size >= sizeof(struct usb_descriptor_header)) {
-			header = (struct usb_descriptor_header *)buffer;
-
-			if ((header->bLength > size) || (header->bLength < 2)) {
-				err("invalid descriptor length of %d", header->bLength);
-				return -1;
-			}
-
-			/* If we find another "proper" descriptor then we're done  */
-			if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
-			    (header->bDescriptorType == USB_DT_INTERFACE) ||
-			    (header->bDescriptorType == USB_DT_CONFIG) ||
-			    (header->bDescriptorType == USB_DT_DEVICE))
-				break;
-
-			dbg("skipping descriptor 0x%X", header->bDescriptorType);
-			numskipped++;
-
-			buffer += header->bLength;
-			size -= header->bLength;
-		}
-		if (numskipped)
-			dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
-
-		/* Copy any unknown descriptors into a storage area for */
-		/*  drivers to later parse */
-		len = (int)(buffer - begin);
-		if (len) {
-			if (config->extralen) {
-				warn("extra config descriptor");
-			} else {
-				config->extra = kmalloc(len, GFP_KERNEL);
-				if (!config->extra) {
-					err("couldn't allocate memory for config extra descriptors");
-					config->extralen = 0;
-					return -1;
-				}
-
-				memcpy(config->extra, begin, len);
-				config->extralen = len;
-			}
-		}
-
-		retval = usb_parse_interface(config->interface + i, buffer, size);
-		if (retval < 0)
-			return retval;
-
-		buffer += retval;
-		size -= retval;
-	}
-
-	return size;
-}
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally on disconnect/destroy path
-void usb_destroy_configuration(struct usb_device *dev)
-{
-	int c, i, j, k;
-	
-	if (!dev->config)
-		return;
-
-	if (dev->rawdescriptors) {
-		for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
-			kfree(dev->rawdescriptors[i]);
-
-		kfree(dev->rawdescriptors);
-	}
-
-	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
-		struct usb_config_descriptor *cf = &dev->config[c];
-
-		if (!cf->interface)
-			break;
-
-		for (i = 0; i < cf->bNumInterfaces; i++) {
-			struct usb_interface *ifp =
-				&cf->interface[i];
-				
-			if (!ifp->altsetting)
-				break;
-
-			for (j = 0; j < ifp->num_altsetting; j++) {
-				struct usb_interface_descriptor *as =
-					&ifp->altsetting[j];
-					
-				if(as->extra) {
-					kfree(as->extra);
-				}
-
-				if (!as->endpoint)
-					break;
-					
-				for(k = 0; k < as->bNumEndpoints; k++) {
-					if(as->endpoint[k].extra) {
-						kfree(as->endpoint[k].extra);
-					}
-				}	
-				kfree(as->endpoint);
-			}
-
-			kfree(ifp->altsetting);
-		}
-		kfree(cf->interface);
-	}
-	kfree(dev->config);
-}
-
-/* for returning string descriptors in UTF-16LE */
-static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
-{
-	int retval;
-
-	for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
-		*utf++ = *ascii++ & 0x7f;
-		*utf++ = 0;
-	}
-	return retval;
-}
-
-/*
- * root_hub_string is used by each host controller's root hub code,
- * so that they're identified consistently throughout the system.
- */
-int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
-{
-	char buf [30];
-
-	// assert (len > (2 * (sizeof (buf) + 1)));
-	// assert (strlen (type) <= 8);
-
-	// language ids
-	if (id == 0) {
-		*data++ = 4; *data++ = 3;	/* 4 bytes data */
-		*data++ = 0; *data++ = 0;	/* some language id */
-		return 4;
-
-	// serial number
-	} else if (id == 1) {
-		sprintf (buf, "%x", serial);
-
-	// product description
-	} else if (id == 2) {
-		sprintf (buf, "USB %s Root Hub", type);
-
-	// id 3 == vendor description
-
-	// unsupported IDs --> "stall"
-	} else
-	    return 0;
-
-	data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
-	data [1] = 3;
-	return data [0];
-}
-
-/*
- * __usb_get_extra_descriptor() finds a descriptor of specific type in the
- * extra field of the interface and endpoint descriptor structs.
- */
-
-int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr)
-{
-	struct usb_descriptor_header *header;
-
-	while (size >= sizeof(struct usb_descriptor_header)) {
-		header = (struct usb_descriptor_header *)buffer;
-
-		if (header->bLength < 2) {
-			err("invalid descriptor length of %d", header->bLength);
-			return -1;
-		}
-
-		if (header->bDescriptorType == type) {
-			*ptr = header;
-			return 0;
-		}
-
-		buffer += header->bLength;
-		size -= header->bLength;
-	}
-	return -1;
-}
-
-/**
- * usb_disconnect - disconnect a device (usbcore-internal)
- * @pdev: pointer to device being disconnected
- * Context: !in_interrupt ()
- *
- * Something got disconnected. Get rid of it, and all of its children.
- *
- * Only hub drivers (including virtual root hub drivers for host
- * controllers) should ever call this.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- */
-void usb_disconnect(struct usb_device **pdev)
-{
-	struct usb_device * dev = *pdev;
-	int i;
-
-	if (!dev)
-		return;
-
-	*pdev = NULL;
-
-	info("USB disconnect on device %d", dev->devnum);
-
-	if (dev->actconfig) {
-		for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
-			struct usb_interface *interface = &dev->actconfig->interface[i];
-			struct usb_driver *driver = interface->driver;
-			if (driver) {
-				if (driver->owner)
-					__MOD_INC_USE_COUNT(driver->owner);
-				down(&driver->serialize);
-				driver->disconnect(dev, interface->private_data);
-				up(&driver->serialize);
-				if (driver->owner)
-					__MOD_DEC_USE_COUNT(driver->owner);
-				/* if driver->disconnect didn't release the interface */
-				if (interface->driver)
-					usb_driver_release_interface(driver, interface);
-			}
-			/* remove our device node for this interface */
-			put_device(&interface->dev);
-		}
-	}
-
-	/* Free up all the children.. */
-	for (i = 0; i < USB_MAXCHILDREN; i++) {
-		struct usb_device **child = dev->children + i;
-		if (*child)
-			usb_disconnect(child);
-	}
-
-	/* Let policy agent unload modules etc */
-	call_policy ("remove", dev);
-
-	/* Free the device number and remove the /proc/bus/usb entry */
-	if (dev->devnum > 0) {
-		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-		usbfs_remove_device(dev);
-		put_device(&dev->dev);
-	}
-
-	/* Free up the device itself */
-	usb_free_dev(dev);
-}
-
-/**
- * usb_connect - connects a new device during enumeration (usbcore-internal)
- * @dev: partially enumerated device
- *
- * Connect a new USB device. This basically just initializes
- * the USB device information and sets up the topology - it's
- * up to the low-level driver to reset the port and actually
- * do the setup (the upper levels don't know how to do that).
- *
- * Only hub drivers (including virtual root hub drivers for host
- * controllers) should ever call this.
- */
-void usb_connect(struct usb_device *dev)
-{
-	int devnum;
-	// FIXME needs locking for SMP!!
-	/* why? this is called only from the hub thread, 
-	 * which hopefully doesn't run on multiple CPU's simultaneously 8-)
-	 * ... it's also called from modprobe/rmmod/apmd threads as part
-	 * of virtual root hub init/reinit.  In the init case, the hub code 
-	 * won't have seen this, but not so for reinit ... 
-	 */
-	dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */
-#ifndef DEVNUM_ROUND_ROBIN
-	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
-#else	/* round_robin alloc of devnums */
-	/* Try to allocate the next devnum beginning at bus->devnum_next. */
-	devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);
-	if (devnum >= 128)
-		devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
-
-	dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
-#endif	/* round_robin alloc of devnums */
-
-	if (devnum < 128) {
-		set_bit(devnum, dev->bus->devmap.devicemap);
-		dev->devnum = devnum;
-	}
-}
-
-/*
- * These are the actual routines to send
- * and receive control messages.
- */
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally, for usb_new_device()
-int usb_set_address(struct usb_device *dev)
-{
-	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
-		// FIXME USB_CTRL_SET_TIMEOUT
-		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-/**
- * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
- * @dev: the device whose descriptor is being retrieved
- * @type: the descriptor type (USB_DT_*)
- * @index: the number of the descriptor
- * @buf: where to put the descriptor
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Gets a USB descriptor.  Convenience functions exist to simplify
- * getting some types of descriptors.  Use
- * usb_get_device_descriptor() for USB_DT_DEVICE,
- * and usb_get_string() or usb_string() for USB_DT_STRING.
- * Configuration descriptors (USB_DT_CONFIG) are part of the device
- * structure, at least for the current configuration.
- * In addition to a number of USB-standard descriptors, some
- * devices also use class-specific or vendor-specific descriptors.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
-{
-	int i = 5;
-	int result;
-	
-	memset(buf,0,size);	// Make sure we parse really received data
-
-	while (i--) {
-		/* retries if the returned length was 0; flakey device */
-		if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-				    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-				    (type << 8) + index, 0, buf, size,
-				    HZ * USB_CTRL_GET_TIMEOUT)) > 0
-				|| result == -EPIPE)
-			break;
-	}
-	return result;
-}
-
-/**
- * usb_get_string - gets a string descriptor
- * @dev: the device whose string descriptor is being retrieved
- * @langid: code for language chosen (from string descriptor zero)
- * @index: the number of the descriptor
- * @buf: where to put the string
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
- * in little-endian byte order).
- * The usb_string() function will often be a convenient way to turn
- * these strings into kernel-printable form.
- *
- * Strings may be referenced in device, configuration, interface, or other
- * descriptors, and could also be used in vendor-specific ways.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-		(USB_DT_STRING << 8) + index, langid, buf, size,
-		HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-/**
- * usb_get_device_descriptor - (re)reads the device descriptor
- * @dev: the device whose device descriptor is being updated
- * Context: !in_interrupt ()
- *
- * Updates the copy of the device descriptor stored in the device structure,
- * which dedicates space for this purpose.  Note that several fields are
- * converted to the host CPU's byte order:  the USB version (bcdUSB), and
- * vendors product and version fields (idVendor, idProduct, and bcdDevice).
- * That lets device drivers compare against non-byteswapped constants.
- *
- * There's normally no need to use this call, although some devices
- * will change their descriptors after events like updating firmware.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_get_device_descriptor(struct usb_device *dev)
-{
-	int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
-				     sizeof(dev->descriptor));
-	if (ret >= 0) {
-		le16_to_cpus(&dev->descriptor.bcdUSB);
-		le16_to_cpus(&dev->descriptor.idVendor);
-		le16_to_cpus(&dev->descriptor.idProduct);
-		le16_to_cpus(&dev->descriptor.bcdDevice);
-	}
-	return ret;
-}
-
-/**
- * usb_get_status - issues a GET_STATUS call
- * @dev: the device whose status is being checked
- * @type: USB_RECIP_*; for device, interface, or endpoint
- * @target: zero (for device), else interface or endpoint number
- * @data: pointer to two bytes of bitmap data
- * Context: !in_interrupt ()
- *
- * Returns device, interface, or endpoint status.  Normally only of
- * interest to see if the device is self powered, or has enabled the
- * remote wakeup facility; or whether a bulk or interrupt endpoint
- * is halted ("stalled").
- *
- * Bits in these status bitmaps are set using the SET_FEATURE request,
- * and cleared using the CLEAR_FEATURE request.  The usb_clear_halt()
- * function should be used to clear halt ("stall") status.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_get_status(struct usb_device *dev, int type, int target, void *data)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
-		HZ * USB_CTRL_GET_TIMEOUT);
-}
-
-
-// hub-only!! ... and only exported for reset/reinit path.
-// otherwise used internally, for config/altsetting reconfig.
-void usb_set_maxpacket(struct usb_device *dev)
-{
-	int i, b;
-
-	for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
-		struct usb_interface *ifp = dev->actconfig->interface + i;
-		struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;
-		struct usb_endpoint_descriptor *ep = as->endpoint;
-		int e;
-
-		for (e=0; e<as->bNumEndpoints; e++) {
-			b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-			if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-				USB_ENDPOINT_XFER_CONTROL) {	/* Control => bidirectional */
-				dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
-				dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
-				}
-			else if (usb_endpoint_out(ep[e].bEndpointAddress)) {
-				if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
-					dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
-			}
-			else {
-				if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
-					dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
-			}
-		}
-	}
-}
-
-/**
- * usb_clear_halt - tells device to clear endpoint halt/stall condition
- * @dev: device whose endpoint is halted
- * @pipe: endpoint "pipe" being cleared
- * Context: !in_interrupt ()
- *
- * This is used to clear halt conditions for bulk and interrupt endpoints,
- * as reported by URB completion status.  Endpoints that are halted are
- * sometimes referred to as being "stalled".  Such endpoints are unable
- * to transmit or receive data until the halt status is cleared.  Any URBs
- * queued queued for such an endpoint should normally be unlinked before
- * clearing the halt condition.
- *
- * Note that control and isochronous endpoints don't halt, although control
- * endpoints report "protocol stall" (for unsupported requests) using the
- * same status code used to report a true stall.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_clear_halt(struct usb_device *dev, int pipe)
-{
-	int result;
-	__u16 status;
-	unsigned char *buffer;
-	int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
-
-/*
-	if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
-		return 0;
-*/
-
-	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
-		HZ * USB_CTRL_SET_TIMEOUT);
-
-	/* don't clear if failed */
-	if (result < 0)
-		return result;
-
-	buffer = kmalloc(sizeof(status), GFP_KERNEL);
-	if (!buffer) {
-		err("unable to allocate memory for configuration descriptors");
-		return -ENOMEM;
-	}
-
-	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
-		// FIXME USB_CTRL_GET_TIMEOUT, yes?  why not usb_get_status() ?
-		buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
-
-	memcpy(&status, buffer, sizeof(status));
-	kfree(buffer);
-
-	if (result < 0)
-		return result;
-
-	if (le16_to_cpu(status) & 1)
-		return -EPIPE;		/* still halted */
-
-	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
-
-	/* toggle is reset on clear */
-
-	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-
-	return 0;
-}
-
-/**
- * usb_set_interface - Makes a particular alternate setting be current
- * @dev: the device whose interface is being updated
- * @interface: the interface being updated
- * @alternate: the setting being chosen.
- * Context: !in_interrupt ()
- *
- * This is used to enable data transfers on interfaces that may not
- * be enabled by default.  Not all devices support such configurability.
- *
- * Within any given configuration, each interface may have several
- * alternative settings.  These are often used to control levels of
- * bandwidth consumption.  For example, the default setting for a high
- * speed interrupt endpoint may not send more than about 4KBytes per
- * microframe, and isochronous endpoints may never be part of a an
- * interface's default setting.  To access such bandwidth, alternate
- * interface setting must be made current.
- *
- * Note that in the Linux USB subsystem, bandwidth associated with
- * an endpoint in a given alternate setting is not reserved until an
- * is submitted that needs that bandwidth.  Some other operating systems
- * allocate bandwidth early, when a configuration is chosen.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_set_interface(struct usb_device *dev, int interface, int alternate)
-{
-	struct usb_interface *iface;
-	struct usb_interface_descriptor *iface_as;
-	int i, ret;
-
-	iface = usb_ifnum_to_if(dev, interface);
-	if (!iface) {
-		warn("selecting invalid interface %d", interface);
-		return -EINVAL;
-	}
-
-	/* 9.4.10 says devices don't need this, if the interface
-	   only has one alternate setting */
-	if (iface->num_altsetting == 1) {
-		dbg("ignoring set_interface for dev %d, iface %d, alt %d",
-			dev->devnum, interface, alternate);
-		return 0;
-	}
-
-	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-	    USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
-	    interface, NULL, 0, HZ * 5)) < 0)
-		return ret;
-
-	iface->act_altsetting = alternate;
-
-	/* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
-	 *
-	 * Note:
-	 * Despite EP0 is always present in all interfaces/AS, the list of
-	 * endpoints from the descriptor does not contain EP0. Due to its
-	 * omnipresence one might expect EP0 being considered "affected" by
-	 * any SetInterface request and hence assume toggles need to be reset.
-	 * However, EP0 toggles are re-synced for every individual transfer
-	 * during the SETUP stage - hence EP0 toggles are "don't care" here.
-	 */
-
-	iface_as = &iface->altsetting[alternate];
-	for (i = 0; i < iface_as->bNumEndpoints; i++) {
-		u8	ep = iface_as->endpoint[i].bEndpointAddress;
-
-		usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
-	}
-
-	/* usb_set_maxpacket() sets the maxpacket size for all EP in all
-	 * interfaces but it shouldn't do any harm here: we have changed
-	 * the AS for the requested interface only, hence for unaffected
-	 * interfaces it's just re-application of still-valid values.
-	 */
-	usb_set_maxpacket(dev);
-	return 0;
-}
-
-/**
- * usb_set_configuration - Makes a particular device setting be current
- * @dev: the device whose configuration is being updated
- * @configuration: the configuration being chosen.
- * Context: !in_interrupt ()
- *
- * This is used to enable non-default device modes.  Not all devices
- * support this kind of configurability.  By default, configuration
- * zero is selected after enumeration; many devices only have a single
- * configuration.
- *
- * USB devices may support one or more configurations, which affect
- * power consumption and the functionality available.  For example,
- * the default configuration is limited to using 100mA of bus power,
- * so that when certain device functionality requires more power,
- * and the device is bus powered, that functionality will be in some
- * non-default device configuration.  Other device modes may also be
- * reflected as configuration options, such as whether two ISDN
- * channels are presented as independent 64Kb/s interfaces or as one
- * bonded 128Kb/s interface.
- *
- * Note that USB has an additional level of device configurability,
- * associated with interfaces.  That configurability is accessed using
- * usb_set_interface().
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns zero on success, or else the status code returned by the
- * underlying usb_control_msg() call.
- */
-int usb_set_configuration(struct usb_device *dev, int configuration)
-{
-	int i, ret;
-	struct usb_config_descriptor *cp = NULL;
-	
-	for (i=0; i<dev->descriptor.bNumConfigurations; i++) {
-		if (dev->config[i].bConfigurationValue == configuration) {
-			cp = &dev->config[i];
-			break;
-		}
-	}
-	if (!cp) {
-		warn("selecting invalid configuration %d", configuration);
-		return -EINVAL;
-	}
-
-	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
-		return ret;
-
-	dev->actconfig = cp;
-	dev->toggle[0] = 0;
-	dev->toggle[1] = 0;
-	usb_set_maxpacket(dev);
-
-	return 0;
-}
-
-// hub-only!! ... and only in reset path, or usb_new_device()
-// (used by real hubs and virtual root hubs)
-int usb_get_configuration(struct usb_device *dev)
-{
-	int result;
-	unsigned int cfgno, length;
-	unsigned char *buffer;
-	unsigned char *bigbuffer;
- 	struct usb_config_descriptor *desc;
-
-	if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
-		warn("too many configurations");
-		return -EINVAL;
-	}
-
-	if (dev->descriptor.bNumConfigurations < 1) {
-		warn("not enough configurations");
-		return -EINVAL;
-	}
-
-	dev->config = (struct usb_config_descriptor *)
-		kmalloc(dev->descriptor.bNumConfigurations *
-		sizeof(struct usb_config_descriptor), GFP_KERNEL);
-	if (!dev->config) {
-		err("out of memory");
-		return -ENOMEM;	
-	}
-	memset(dev->config, 0, dev->descriptor.bNumConfigurations *
-		sizeof(struct usb_config_descriptor));
-
-	dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
-		dev->descriptor.bNumConfigurations, GFP_KERNEL);
-	if (!dev->rawdescriptors) {
-		err("out of memory");
-		return -ENOMEM;
-	}
-
-	buffer = kmalloc(8, GFP_KERNEL);
-	if (!buffer) {
-		err("unable to allocate memory for configuration descriptors");
-		return -ENOMEM;
-	}
-	desc = (struct usb_config_descriptor *)buffer;
-
-	for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
-		/* We grab the first 8 bytes so we know how long the whole */
-		/*  configuration is */
-		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
-		if (result < 8) {
-			if (result < 0)
-				err("unable to get descriptor");
-			else {
-				err("config descriptor too short (expected %i, got %i)", 8, result);
-				result = -EINVAL;
-			}
-			goto err;
-		}
-
-  	  	/* Get the full buffer */
-		length = le16_to_cpu(desc->wTotalLength);
-
-		bigbuffer = kmalloc(length, GFP_KERNEL);
-		if (!bigbuffer) {
-			err("unable to allocate memory for configuration descriptors");
-			result = -ENOMEM;
-			goto err;
-		}
-
-		/* Now that we know the length, get the whole thing */
-		result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
-		if (result < 0) {
-			err("couldn't get all of config descriptors");
-			kfree(bigbuffer);
-			goto err;
-		}	
-	
-		if (result < length) {
-			err("config descriptor too short (expected %i, got %i)", length, result);
-			result = -EINVAL;
-			kfree(bigbuffer);
-			goto err;
-		}
-
-		dev->rawdescriptors[cfgno] = bigbuffer;
-
-		result = usb_parse_configuration(&dev->config[cfgno], bigbuffer);
-		if (result > 0)
-			dbg("descriptor data left");
-		else if (result < 0) {
-			result = -EINVAL;
-			goto err;
-		}
-	}
-
-	kfree(buffer);
-	return 0;
-err:
-	kfree(buffer);
-	dev->descriptor.bNumConfigurations = cfgno;
-	return result;
-}
-
-/**
- * usb_string - returns ISO 8859-1 version of a string descriptor
- * @dev: the device whose string descriptor is being retrieved
- * @index: the number of the descriptor
- * @buf: where to put the string
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- * 
- * This converts the UTF-16LE encoded strings returned by devices, from
- * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
- * that are more usable in most kernel contexts.  Note that all characters
- * in the chosen descriptor that can't be encoded using ISO-8859-1
- * are converted to the question mark ("?") character, and this function
- * chooses strings in the first language supported by the device.
- *
- * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
- * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
- * and is appropriate for use many uses of English and several other
- * Western European languages.  (But it doesn't include the "Euro" symbol.)
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Returns length of the string (>= 0) or usb_control_msg status (< 0).
- */
-int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
-{
-	unsigned char *tbuf;
-	int err;
-	unsigned int u, idx;
-
-	if (size <= 0 || !buf || !index)
-		return -EINVAL;
-	buf[0] = 0;
-	tbuf = kmalloc(256, GFP_KERNEL);
-	if (!tbuf)
-		return -ENOMEM;
-
-	/* get langid for strings if it's not yet known */
-	if (!dev->have_langid) {
-		err = usb_get_string(dev, 0, 0, tbuf, 4);
-		if (err < 0) {
-			err("error getting string descriptor 0 (error=%d)", err);
-			goto errout;
-		} else if (tbuf[0] < 4) {
-			err("string descriptor 0 too short");
-			err = -EINVAL;
-			goto errout;
-		} else {
-			dev->have_langid = -1;
-			dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
-				/* always use the first langid listed */
-			dbg("USB device number %d default language ID 0x%x",
-				dev->devnum, dev->string_langid);
-		}
-	}
-
-	/*
-	 * Just ask for a maximum length string and then take the length
-	 * that was returned.
-	 */
-	err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
-	if (err < 0)
-		goto errout;
-
-	size--;		/* leave room for trailing NULL char in output buffer */
-	for (idx = 0, u = 2; u < err; u += 2) {
-		if (idx >= size)
-			break;
-		if (tbuf[u+1])			/* high byte */
-			buf[idx++] = '?';  /* non ISO-8859-1 character */
-		else
-			buf[idx++] = tbuf[u];
-	}
-	buf[idx] = 0;
-	err = idx;
-
- errout:
-	kfree(tbuf);
-	return err;
-}
-
-/**
- * usb_make_path - returns device path in the hub tree
- * @dev: the device whose path is being constructed
- * @buf: where to put the string
- * @size: how big is "buf"?
- * Context: !in_interrupt ()
- *
- * Returns length of the string (>= 0) or out of memory status (< 0).
- *
- * NOTE:  prefer to use use dev->devpath directly.
- */
-int usb_make_path(struct usb_device *dev, char *buf, size_t size)
-{
-	struct usb_device *pdev = dev->parent;
-	char *tmp;
-	char *port;
-	int i;
-
-	if (!(port = kmalloc(size, GFP_KERNEL)))
-		return -ENOMEM;
-	if (!(tmp = kmalloc(size, GFP_KERNEL))) {
-		kfree(port);
-		return -ENOMEM;
-	}
-
-	*port = 0;
-	while (pdev) {
-		for (i = 0; i < pdev->maxchild; i++)
-			if (pdev->children[i] == dev)
-				break;
-
-		if (pdev->children[i] != dev) {
-			kfree(port);
-			kfree(tmp);
-			return -ENODEV;
-		}
-
-		strcpy(tmp, port);
-		snprintf(port, size, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
-
-		dev = pdev;
-		pdev = dev->parent;
-	}
-
-	snprintf(buf, size, "usb%d:%s", dev->bus->busnum, port);
-	kfree(port);
-	kfree(tmp);
-	return strlen(buf);
-}
-
-/*
- * By the time we get here, the device has gotten a new device ID
- * and is in the default state. We need to identify the thing and
- * get the ball rolling..
- *
- * Returns 0 for success, != 0 for error.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Only hub drivers (including virtual root hub drivers for host
- * controllers) should ever call this.
- */
-int usb_new_device(struct usb_device *dev)
-{
-	int err;
-
-	/* USB v1.1 5.5.3 */
-	/* We read the first 8 bytes from the device descriptor to get to */
-	/*  the bMaxPacketSize0 field. Then we set the maximum packet size */
-	/*  for the control pipe, and retrieve the rest */
-	dev->epmaxpacketin [0] = 8;
-	dev->epmaxpacketout[0] = 8;
-
-	err = usb_set_address(dev);
-	if (err < 0) {
-		err("USB device not accepting new address=%d (error=%d)",
-			dev->devnum, err);
-		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-		dev->devnum = -1;
-		return 1;
-	}
-
-	wait_ms(10);	/* Let the SET_ADDRESS settle */
-
-	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
-	if (err < 8) {
-		if (err < 0)
-			err("USB device not responding, giving up (error=%d)", err);
-		else
-			err("USB device descriptor short read (expected %i, got %i)", 8, err);
-		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-		dev->devnum = -1;
-		return 1;
-	}
-	dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
-	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
-
-	err = usb_get_device_descriptor(dev);
-	if (err < (signed)sizeof(dev->descriptor)) {
-		if (err < 0)
-			err("unable to get device descriptor (error=%d)", err);
-		else
-			err("USB device descriptor short read (expected %Zi, got %i)",
-				sizeof(dev->descriptor), err);
-	
-		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-		dev->devnum = -1;
-		return 1;
-	}
-
-	err = usb_get_configuration(dev);
-	if (err < 0) {
-		err("unable to get device %d configuration (error=%d)",
-			dev->devnum, err);
-		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-		dev->devnum = -1;
-		return 1;
-	}
-
-	/* we set the default configuration here */
-	err = usb_set_configuration(dev, dev->config[0].bConfigurationValue);
-	if (err) {
-		err("failed to set device %d default configuration (error=%d)",
-			dev->devnum, err);
-		clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-		dev->devnum = -1;
-		return 1;
-	}
-
-	dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d",
-		dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
-#ifdef DEBUG
-	if (dev->descriptor.iManufacturer)
-		usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
-	if (dev->descriptor.iProduct)
-		usb_show_string(dev, "Product", dev->descriptor.iProduct);
-	if (dev->descriptor.iSerialNumber)
-		usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
-#endif
-
-	/* register this device in the driverfs tree */
-	err = device_register (&dev->dev);
-	if (err)
-		return err;
-
-	/* now that the basic setup is over, add a /proc/bus/usb entry */
-	usbfs_add_device(dev);
-
-	/* find drivers willing to handle this device */
-	usb_find_drivers(dev);
-
-	/* userspace may load modules and/or configure further */
-	call_policy ("add", dev);
-
-	return 0;
-}
-
-static int usb_open(struct inode * inode, struct file * file)
-{
-	int minor = minor(inode->i_rdev);
-	struct usb_driver *c = usb_minors[minor/16];
-	int err = -ENODEV;
-	struct file_operations *old_fops, *new_fops = NULL;
-
-	/*
-	 * No load-on-demand? Randy, could you ACK that it's really not
-	 * supposed to be done?					-- AV
-	 */
-	if (!c || !(new_fops = fops_get(c->fops)))
-		return err;
-	old_fops = file->f_op;
-	file->f_op = new_fops;
-	/* Curiouser and curiouser... NULL ->open() as "no device" ? */
-	if (file->f_op->open)
-		err = file->f_op->open(inode,file);
-	if (err) {
-		fops_put(file->f_op);
-		file->f_op = fops_get(old_fops);
-	}
-	fops_put(old_fops);
-	return err;
-}
-
-static struct file_operations usb_fops = {
-	owner:		THIS_MODULE,
-	open:		usb_open,
-};
-
-int usb_major_init(void)
-{
-	if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
-		err("unable to get major %d for usb devices", USB_MAJOR);
-		return -EBUSY;
-	}
-
-	usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL);
-
-	return 0;
-}
-
-void usb_major_cleanup(void)
-{
-	devfs_unregister(usb_devfs_handle);
-	devfs_unregister_chrdev(USB_MAJOR, "usb");
-}
-
-
-#ifdef CONFIG_PROC_FS
-struct list_head *usb_driver_get_list(void)
-{
-	return &usb_driver_list;
-}
-
-struct list_head *usb_bus_get_list(void)
-{
-	return &usb_bus_list;
-}
-#endif
-
-
-/*
- * Init
- */
-static int __init usb_init(void)
-{
-	usb_major_init();
-	usbfs_init();
-	usb_hub_init();
-
-	return 0;
-}
-
-/*
- * Cleanup
- */
-static void __exit usb_exit(void)
-{
-	usb_major_cleanup();
-	usbfs_cleanup();
-	usb_hub_cleanup();
-}
-
-subsys_initcall(usb_init);
-module_exit(usb_exit);
-
-/*
- * USB may be built into the kernel or be built as modules.
- * If the USB core [and maybe a host controller driver] is built
- * into the kernel, and other device drivers are built as modules,
- * then these symbols need to be exported for the modules to use.
- */
-EXPORT_SYMBOL(usb_ifnum_to_if);
-EXPORT_SYMBOL(usb_epnum_to_ep_desc);
-
-EXPORT_SYMBOL(usb_register);
-EXPORT_SYMBOL(usb_deregister);
-EXPORT_SYMBOL(usb_scan_devices);
-
-EXPORT_SYMBOL(usb_alloc_dev);
-EXPORT_SYMBOL(usb_free_dev);
-EXPORT_SYMBOL(usb_inc_dev_use);
-
-EXPORT_SYMBOL(usb_driver_claim_interface);
-EXPORT_SYMBOL(usb_interface_claimed);
-EXPORT_SYMBOL(usb_driver_release_interface);
-EXPORT_SYMBOL(usb_match_id);
-
-EXPORT_SYMBOL(usb_root_hub_string);
-EXPORT_SYMBOL(usb_new_device);
-EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_connect);
-EXPORT_SYMBOL(usb_disconnect);
-
-EXPORT_SYMBOL(__usb_get_extra_descriptor);
-
-EXPORT_SYMBOL(usb_get_current_frame_number);
-
-// asynchronous request completion model
-EXPORT_SYMBOL(usb_alloc_urb);
-EXPORT_SYMBOL(usb_free_urb);
-EXPORT_SYMBOL(usb_get_urb);
-EXPORT_SYMBOL(usb_submit_urb);
-EXPORT_SYMBOL(usb_unlink_urb);
-
-// synchronous request completion model
-EXPORT_SYMBOL(usb_control_msg);
-EXPORT_SYMBOL(usb_bulk_msg);
-// synchronous control message convenience routines
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_device_descriptor);
-EXPORT_SYMBOL(usb_get_status);
-EXPORT_SYMBOL(usb_get_string);
-EXPORT_SYMBOL(usb_string);
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_set_configuration);
-EXPORT_SYMBOL(usb_set_interface);
-
-EXPORT_SYMBOL(usb_make_path);
-EXPORT_SYMBOL(usb_devfs_handle);
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c
--- a/drivers/usb/usbkbd.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,309 +0,0 @@
-/*
- * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  USB HIDBP Keyboard support
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * 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/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION ""
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-static unsigned char usb_kbd_keycode[256] = {
-	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
-	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
-	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
-	 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
-	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
-	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
-	 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
-	120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
-	115,114,  0,  0,  0,124,  0,181,182,183,184,185,186,187,188,189,
-	190,191,192,193,194,195,196,197,198,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
-	150,158,159,128,136,177,178,176,142,152,173,140
-};
-
-struct usb_kbd {
-	struct input_dev dev;
-	struct usb_device *usbdev;
-	unsigned char new[8];
-	unsigned char old[8];
-	struct urb *irq, *led;
-	struct usb_ctrlrequest cr;
-	unsigned char leds, newleds;
-	char name[128];
-	char phys[64];
-	int open;
-};
-
-static void usb_kbd_irq(struct urb *urb)
-{
-	struct usb_kbd *kbd = urb->context;
-	int i;
-
-	if (urb->status) return;
-
-	for (i = 0; i < 8; i++)
-		input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
-
-	for (i = 2; i < 8; i++) {
-
-		if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
-			if (usb_kbd_keycode[kbd->old[i]])
-				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
-			else
-				info("Unknown key (scancode %#x) released.", kbd->old[i]);
-		}
-
-		if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
-			if (usb_kbd_keycode[kbd->new[i]])
-				input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
-			else
-				info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
-		}
-	}
-
-	memcpy(kbd->old, kbd->new, 8);
-}
-
-int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	struct usb_kbd *kbd = dev->private;
-
-	if (type != EV_LED) return -1;
-
-
-	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
-		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
-		       (!!test_bit(LED_NUML,    dev->led));
-
-	if (kbd->led->status == -EINPROGRESS)
-		return 0;
-
-	if (kbd->leds == kbd->newleds)
-		return 0;
-
-	kbd->leds = kbd->newleds;
-	kbd->led->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
-
-	return 0;
-}
-
-static void usb_kbd_led(struct urb *urb)
-{
-	struct usb_kbd *kbd = urb->context;
-
-	if (urb->status)
-		warn("led urb status %d received", urb->status);
-	
-	if (kbd->leds == kbd->newleds)
-		return;
-
-	kbd->leds = kbd->newleds;
-	kbd->led->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->led, GFP_ATOMIC))
-		err("usb_submit_urb(leds) failed");
-}
-
-static int usb_kbd_open(struct input_dev *dev)
-{
-	struct usb_kbd *kbd = dev->private;
-
-	if (kbd->open++)
-		return 0;
-
-	kbd->irq->dev = kbd->usbdev;
-	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void usb_kbd_close(struct input_dev *dev)
-{
-	struct usb_kbd *kbd = dev->private;
-
-	if (!--kbd->open)
-		usb_unlink_urb(kbd->irq);
-}
-
-static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
-			   const struct usb_device_id *id)
-{
-	struct usb_interface *iface;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_kbd *kbd;
-	int i, pipe, maxp;
-	char path[64];
-	char *buf;
-
-	iface = &dev->actconfig->interface[ifnum];
-	interface = &iface->altsetting[iface->act_altsetting];
-
-	if (interface->bNumEndpoints != 1) return NULL;
-
-	endpoint = interface->endpoint + 0;
-	if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
-	if ((endpoint->bmAttributes & 3) != 3) return NULL;
-
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
-	memset(kbd, 0, sizeof(struct usb_kbd));
-
-	kbd->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!kbd->irq) {
-		kfree(kbd);
-		return NULL;
-	}
-	kbd->led = usb_alloc_urb(0, GFP_KERNEL);
-	if (!kbd->led) {
-		usb_free_urb(kbd->irq);
-		kfree(kbd);
-		return NULL;
-	}
-
-	kbd->usbdev = dev;
-
-	kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-	kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
-
-	for (i = 0; i < 255; i++)
-		set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
-	clear_bit(0, kbd->dev.keybit);
-	
-	kbd->dev.private = kbd;
-	kbd->dev.event = usb_kbd_event;
-	kbd->dev.open = usb_kbd_open;
-	kbd->dev.close = usb_kbd_close;
-
-	FILL_INT_URB(kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
-		usb_kbd_irq, kbd, endpoint->bInterval);
-
-	kbd->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	kbd->cr.bRequest = 0x09;
-	kbd->cr.wValue = 0x200;
-	kbd->cr.wIndex = interface->bInterfaceNumber;
-	kbd->cr.wLength = 1;
-
-	usb_make_path(dev, path, 64);
-	sprintf(kbd->phys, "%s/input0", path);
-
-	kbd->dev.name = kbd->name;
-	kbd->dev.phys = kbd->phys;	
-	kbd->dev.idbus = BUS_USB;
-	kbd->dev.idvendor = dev->descriptor.idVendor;
-	kbd->dev.idproduct = dev->descriptor.idProduct;
-	kbd->dev.idversion = dev->descriptor.bcdDevice;
-
-	if (!(buf = kmalloc(63, GFP_KERNEL))) {
-		kfree(kbd);
-		return NULL;
-	}
-
-	if (dev->descriptor.iManufacturer &&
-		usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
-			strcat(kbd->name, buf);
-	if (dev->descriptor.iProduct &&
-		usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
-			sprintf(kbd->name, "%s %s", kbd->name, buf);
-
-	if (!strlen(kbd->name))
-		sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
-			kbd->dev.idvendor, kbd->dev.idproduct);
-
-	kfree(buf);
-
-	FILL_CONTROL_URB(kbd->led, dev, usb_sndctrlpipe(dev, 0),
-		(void*) &kbd->cr, &kbd->leds, 1, usb_kbd_led, kbd);
-			
-	input_register_device(&kbd->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
-
-	return kbd;
-}
-
-static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_kbd *kbd = ptr;
-	usb_unlink_urb(kbd->irq);
-	input_unregister_device(&kbd->dev);
-	usb_free_urb(kbd->irq);
-	usb_free_urb(kbd->led);
-	kfree(kbd);
-}
-
-static struct usb_device_id usb_kbd_id_table [] = {
-	{ USB_INTERFACE_INFO(3, 1, 1) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
-
-static struct usb_driver usb_kbd_driver = {
-	name:		"keyboard",
-	probe:		usb_kbd_probe,
-	disconnect:	usb_kbd_disconnect,
-	id_table:	usb_kbd_id_table,
-};
-
-static int __init usb_kbd_init(void)
-{
-	usb_register(&usb_kbd_driver);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-static void __exit usb_kbd_exit(void)
-{
-	usb_deregister(&usb_kbd_driver);
-}
-
-module_init(usb_kbd_init);
-module_exit(usb_kbd_exit);
diff -Nru a/drivers/usb/usbmouse.c b/drivers/usb/usbmouse.c
--- a/drivers/usb/usbmouse.c	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,217 +0,0 @@
-/*
- * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- *
- *  USB HIDBP Mouse support
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or 
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
- * 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/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.6"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-struct usb_mouse {
-	signed char data[8];
-	char name[128];
-	char phys[64];
-	struct usb_device *usbdev;
-	struct input_dev dev;
-	struct urb *irq;
-	int open;
-};
-
-static void usb_mouse_irq(struct urb *urb)
-{
-	struct usb_mouse *mouse = urb->context;
-	signed char *data = mouse->data;
-	struct input_dev *dev = &mouse->dev;
-
-	if (urb->status) return;
-
-	input_report_key(dev, BTN_LEFT,   data[0] & 0x01);
-	input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);
-	input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
-	input_report_key(dev, BTN_SIDE,   data[0] & 0x08);
-	input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);
-
-	input_report_rel(dev, REL_X,     data[1]);
-	input_report_rel(dev, REL_Y,     data[2]);
-	input_report_rel(dev, REL_WHEEL, data[3]);
-}
-
-static int usb_mouse_open(struct input_dev *dev)
-{
-	struct usb_mouse *mouse = dev->private;
-
-	if (mouse->open++)
-		return 0;
-
-	mouse->irq->dev = mouse->usbdev;
-	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void usb_mouse_close(struct input_dev *dev)
-{
-	struct usb_mouse *mouse = dev->private;
-
-	if (!--mouse->open)
-		usb_unlink_urb(mouse->irq);
-}
-
-static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
-			     const struct usb_device_id *id)
-{
-	struct usb_interface *iface;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_mouse *mouse;
-	int pipe, maxp;
-	char path[64];
-	char *buf;
-
-	iface = &dev->actconfig->interface[ifnum];
-	interface = &iface->altsetting[iface->act_altsetting];
-
-	if (interface->bNumEndpoints != 1) return NULL;
-
-	endpoint = interface->endpoint + 0;
-	if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
-	if ((endpoint->bmAttributes & 3) != 3) return NULL;
-
-	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-
-	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
-	memset(mouse, 0, sizeof(struct usb_mouse));
-
-	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!mouse->irq) {
-		kfree(mouse);
-		return NULL;
-	}
-
-	mouse->usbdev = dev;
-
-	mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-	mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-	mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-	mouse->dev.relbit[0] |= BIT(REL_WHEEL);
-
-	mouse->dev.private = mouse;
-	mouse->dev.open = usb_mouse_open;
-	mouse->dev.close = usb_mouse_close;
-
-	usb_make_path(dev, path, 64);
-	sprintf(mouse->phys, "%s/input0", path);
-
-	mouse->dev.name = mouse->name;
-	mouse->dev.phys = mouse->phys;
-	mouse->dev.idbus = BUS_USB;
-	mouse->dev.idvendor = dev->descriptor.idVendor;
-	mouse->dev.idproduct = dev->descriptor.idProduct;
-	mouse->dev.idversion = dev->descriptor.bcdDevice;
-
-	if (!(buf = kmalloc(63, GFP_KERNEL))) {
-		kfree(mouse);
-		return NULL;
-	}
-
-	if (dev->descriptor.iManufacturer &&
-		usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
-			strcat(mouse->name, buf);
-	if (dev->descriptor.iProduct &&
-		usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
-			sprintf(mouse->name, "%s %s", mouse->name, buf);
-
-	if (!strlen(mouse->name))
-		sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
-			mouse->dev.idvendor, mouse->dev.idproduct);
-
-	kfree(buf);
-
-	FILL_INT_URB(mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
-		usb_mouse_irq, mouse, endpoint->bInterval);
-
-	input_register_device(&mouse->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
-
-	return mouse;
-}
-
-static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_mouse *mouse = ptr;
-	usb_unlink_urb(mouse->irq);
-	input_unregister_device(&mouse->dev);
-	usb_free_urb(mouse->irq);
-	kfree(mouse);
-}
-
-static struct usb_device_id usb_mouse_id_table [] = {
-	{ USB_INTERFACE_INFO(3, 1, 2) },
-    { }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
-
-static struct usb_driver usb_mouse_driver = {
-	name:		"usb_mouse",
-	probe:		usb_mouse_probe,
-	disconnect:	usb_mouse_disconnect,
-	id_table:	usb_mouse_id_table,
-};
-
-static int __init usb_mouse_init(void)
-{
-	usb_register(&usb_mouse_driver);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-static void __exit usb_mouse_exit(void)
-{
-	usb_deregister(&usb_mouse_driver);
-}
-
-module_init(usb_mouse_init);
-module_exit(usb_mouse_exit);
diff -Nru a/drivers/usb/usbnet.c b/drivers/usb/usbnet.c
--- a/drivers/usb/usbnet.c	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1973 +0,0 @@
-/*
- * USB Host-to-Host Links
- * Copyright (C) 2000-2001 by David Brownell <dbrownell@users.sourceforge.net>
- */
-
-/*
- * This is used for "USB networking", connecting USB hosts as peers.
- *
- * It can be used with USB "network cables", for IP-over-USB communications;
- * Ethernet speeds without the Ethernet.  USB devices (including some PDAs)
- * can support such links directly, replacing device-specific protocols
- * with Internet standard ones.
- *
- * The links can be bridged using the Ethernet bridging (net/bridge)
- * support as appropriate.  Devices currently supported include:
- *
- *	- AnchorChip 2720
- *	- Belkin, eTEK (interops with Win32 drivers)
- *	- GeneSys GL620USB-A
- *	- "Linux Devices" (like iPaq and similar SA-1100 based PDAs)
- *	- NetChip 1080 (interoperates with NetChip Win32 drivers)
- *	- Prolific PL-2301/2302 (replaces "plusb" driver)
- *
- * USB devices can implement their side of this protocol at the cost
- * of two bulk endpoints; it's not restricted to "cable" applications.
- * See the LINUXDEV support.
- *
- * 
- * TODO:
- *
- * This needs to be retested for bulk queuing problems ... earlier versions
- * seemed to find different types of problems in each HCD.  Once they're fixed,
- * re-enable queues to get higher bandwidth utilization (without needing
- * to tweak MTU for larger packets).
- *
- * Add support for more "network cable" chips; interop with their Win32
- * drivers may be a good thing.  Test the AnchorChip 2720 support..
- * Figure out the initialization protocol used by the Prolific chips,
- * for better robustness ... there's some powerup/reset handshake that's
- * needed when only one end reboots.
- *
- * Use interrupt on PL230x to detect peer connect/disconnect, and call
- * netif_carrier_{on,off} (?) appropriately.  For Net1080, detect peer
- * connect/disconnect with async control messages.
- *
- * Find some way to report "peer connected" network hotplug events; it'll
- * likely mean updating the networking layer.  (This has been discussed
- * on the netdev list...)
- *
- * Craft smarter hotplug policy scripts ... ones that know how to arrange
- * bridging with "brctl", and can handle static and dynamic ("pump") setups.
- * Use those "peer connected" events.
- *
- *
- * CHANGELOG:
- *
- * 13-sep-2000	experimental, new
- * 10-oct-2000	usb_device_id table created. 
- * 28-oct-2000	misc fixes; mostly, discard more TTL-mangled rx packets.
- * 01-nov-2000	usb_device_id table and probing api update by
- *		Adam J. Richter <adam@yggdrasil.com>.
- * 18-dec-2000	(db) tx watchdog, "net1080" renaming to "usbnet", device_info
- *		and prolific support, isolate net1080-specific bits, cleanup.
- *		fix unlink_urbs oops in D3 PM resume code path.
- * 02-feb-2001	(db) fix tx skb sharing, packet length, match_flags, ...
- * 08-feb-2001	stubbed in "linuxdev", maybe the SA-1100 folk can use it;
- *		AnchorChips 2720 support (from spec) for testing;
- *		fix bit-ordering problem with ethernet multicast addr
- * 19-feb-2001  Support for clearing halt conditions. SA1100 UDC support
- *		updates. Oleg Drokin (green@iXcelerator.com)
- * 25-mar-2001	More SA-1100 updates, including workaround for ip problem
- *		expecting cleared skb->cb and framing change to match latest
- *		handhelds.org version (Oleg).  Enable device IDs from the
- *		Win32 Belkin driver; other cleanups (db).
- * 16-jul-2001	Bugfixes for uhci oops-on-unplug, Belkin support, various
- *		cleanups for problems not yet seen in the field. (db)
- * 17-oct-2001	Handle "Advance USBNET" product, like Belkin/eTEK devices,
- *		from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>;
- *		rx unlinks somehow weren't async; minor cleanup.
- * 03-nov-2001	Merged GeneSys driver; original code from Jiun-Jie Huang
- *		<huangjj@genesyslogic.com.tw>, updated by Stanislav Brabec
- *		<utx@penguin.cz>.  Made framing options (NetChip/GeneSys)
- *		tie mostly to (sub)driver info.  Workaround some PL-2302
- *		chips that seem to reject SET_INTERFACE requests.
- *
- *-------------------------------------------------------------------------*/
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/random.h>
-#include <asm/unaligned.h>
-
-// #define	DEBUG			// error path messages, extra info
-// #define	VERBOSE			// more; success messages
-// #define	REALLY_QUEUE
-
-#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
-#   define DEBUG
-#endif
-#include <linux/usb.h>
-
-
-#define	CONFIG_USB_AN2720
-#define	CONFIG_USB_BELKIN
-#define	CONFIG_USB_GENESYS
-#define	CONFIG_USB_LINUXDEV
-#define	CONFIG_USB_NET1080
-#define	CONFIG_USB_PL2301
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Nineteen USB 1.1 max size bulk transactions per frame (ms), max.
- * Several dozen bytes of IPv4 data can fit in two such transactions.
- * One maximum size Ethernet packet takes twenty four of them.
- */
-#ifdef REALLY_QUEUE
-#define	RX_QLEN		4
-#define	TX_QLEN		4
-#else
-#define	RX_QLEN		1
-#define	TX_QLEN		1
-#endif
-
-// packets are always ethernet inside
-// ... except they can be bigger (limit of 64K with NetChip framing)
-#define MIN_PACKET	sizeof(struct ethhdr)
-#define MAX_PACKET	32768
-
-// reawaken network queue this soon after stopping; else watchdog barks
-#define TX_TIMEOUT_JIFFIES	(5*HZ)
-
-// for vendor-specific control operations
-#define	CONTROL_TIMEOUT_MS	(500)			/* msec */
-#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
-
-// between wakeups
-#define UNLINK_TIMEOUT_JIFFIES ((3  /*ms*/ * HZ)/1000)
-
-/*-------------------------------------------------------------------------*/
-
-// list of all devices we manage
-static DECLARE_MUTEX (usbnet_mutex);
-static LIST_HEAD (usbnet_list);
-
-// randomly generated ethernet address
-static u8	node_id [ETH_ALEN];
-
-// state we keep for each device we handle
-struct usbnet {
-	// housekeeping
-	struct usb_device	*udev;
-	struct driver_info	*driver_info;
-	struct semaphore	mutex;
-	struct list_head	dev_list;
-	wait_queue_head_t	*wait;
-
-	// protocol/interface state
-	struct net_device	net;
-	struct net_device_stats	stats;
-
-#ifdef CONFIG_USB_NET1080
-	u16			packet_id;
-#endif
-
-	// various kinds of pending driver work
-	struct sk_buff_head	rxq;
-	struct sk_buff_head	txq;
-	struct sk_buff_head	done;
-	struct tasklet_struct	bh;
-	struct tq_struct	ctrl_task;
-};
-
-// device-specific info used by the driver
-struct driver_info {
-	char		*description;
-
-	int		flags;
-#define FLAG_FRAMING_NC	0x0001		/* guard against device dropouts */ 
-#define FLAG_FRAMING_GL	0x0002		/* genelink batches packets */
-#define FLAG_NO_SETINT	0x0010		/* device can't set_interface() */
-
-	/* reset device ... can sleep */
-	int	(*reset)(struct usbnet *);
-
-	/* see if peer is connected ... can sleep */
-	int	(*check_connect)(struct usbnet *);
-
-	/* fixup rx packet (strip framing) */
-	int	(*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
-
-	/* fixup tx packet (add framing) */
-	struct sk_buff	*(*tx_fixup)(struct usbnet *dev,
-				struct sk_buff *skb, int flags);
-
-	// FIXME -- also an interrupt mechanism
-	// useful for at least PL2301/2302 and GL620USB-A
-
-	/* framework currently "knows" bulk EPs talk packets */
-	int		in;		/* rx endpoint */
-	int		out;		/* tx endpoint */
-	int		epsize;
-};
-
-#define EP_SIZE(usbnet)	((usbnet)->driver_info->epsize)
-
-// we record the state for each of our queued skbs
-enum skb_state {
-	illegal = 0,
-	tx_start, tx_done,
-	rx_start, rx_done, rx_cleanup
-};
-
-struct skb_data {	// skb->cb is one of these
-	struct urb		*urb;
-	struct usbnet		*dev;
-	enum skb_state		state;
-	size_t			length;
-};
-
-
-#define	mutex_lock(x)	down(x)
-#define	mutex_unlock(x)	up(x)
-
-#define	RUN_CONTEXT (in_irq () ? "in_irq" \
-			: (in_interrupt () ? "in_interrupt" : "can sleep"))
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef DEBUG
-#define devdbg(usbnet, fmt, arg...) \
-	printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
-#else
-#define devdbg(usbnet, fmt, arg...) do {} while(0)
-#endif
-
-#define devinfo(usbnet, fmt, arg...) \
-	printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net.name, ## arg)
-
-
-#ifdef	CONFIG_USB_AN2720
-
-/*-------------------------------------------------------------------------
- *
- * AnchorChips 2720 driver ... http://www.cypress.com
- *
- * This doesn't seem to have a way to detect whether the peer is
- * connected, or need any reset handshaking.  It's got pretty big
- * internal buffers (handles most of a frame's worth of data).
- * Chip data sheets don't describe any vendor control messages.
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info	an2720_info = {
-	description:	"AnchorChips/Cypress 2720",
-	// no reset available!
-	// no check_connect available!
-
-	in: 2, out: 2,		// direction distinguishes these
-	epsize:	64,
-};
-
-#endif	/* CONFIG_USB_AN2720 */
-
-
-
-#ifdef	CONFIG_USB_BELKIN
-
-/*-------------------------------------------------------------------------
- *
- * Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller
- *
- * ... also two eTEK designs, including one sold as "Advance USBNET"
- *
- *-------------------------------------------------------------------------*/
-
-static const struct driver_info	belkin_info = {
-	description:	"Belkin, eTEK, or compatible",
-
-	in: 1, out: 1,		// direction distinguishes these
-	epsize:	64,
-};
-
-#endif	/* CONFIG_USB_BELKIN */
-
-
-
-#ifdef CONFIG_USB_GENESYS
-
-/*-------------------------------------------------------------------------
- *
- * GeneSys GL620USB-A (www.genesyslogic.com.tw)
- *
- * ... should partially interop with the Win32 driver for this hardware
- * The GeneSys docs imply there's some NDIS issue motivating this framing.
- *
- *-------------------------------------------------------------------------*/
-
-// control msg write command
-#define GENELINK_CONNECT_WRITE			0xF0
-// interrupt pipe index
-#define GENELINK_INTERRUPT_PIPE			0x03
-// interrupt read buffer size
-#define INTERRUPT_BUFSIZE			0x08
-// interrupt pipe interval value
-#define GENELINK_INTERRUPT_INTERVAL		0x10
-// max transmit packet number per transmit
-#define GL_MAX_TRANSMIT_PACKETS			32
-// max packet length
-#define GL_MAX_PACKET_LEN			1514
-// max receive buffer size 
-#define GL_RCV_BUF_SIZE		\
-	(((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4)
-
-struct gl_packet {
-	u32		packet_length;
-	char		packet_data [1];
-};
-
-struct gl_header {
-	u32			packet_count;
-	struct gl_packet	packets;
-};
-
-#ifdef	GENLINK_ACK
-
-// FIXME:  this code is incomplete, not debugged; it doesn't
-// handle interrupts correctly.  interrupts should be generic
-// code like all other device I/O, anyway.
-
-struct gl_priv { 
-	struct urb	*irq_urb;
-	char		irq_buf [INTERRUPT_BUFSIZE];
-};
-
-static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
-{
-	int retval;
-
-	retval = usb_control_msg (dev->udev,
-		      usb_sndctrlpipe (dev->udev, 0),
-		      request,
-		      USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		      value, 
-		      0,			// index
-		      0,			// data buffer
-		      0,			// size
-		      CONTROL_TIMEOUT_JIFFIES);
-	return retval;
-}
-
-static void gl_interrupt_complete (struct urb *urb)
-{
-	int status = urb->status;
-	
-	if (status)
-		dbg ("gl_interrupt_complete fail - %X", status);
-	else
-		dbg ("gl_interrupt_complete success...");
-}
-
-static int gl_interrupt_read (struct usbnet *dev)
-{
-	struct gl_priv	*priv = dev->priv_data;
-	int		retval;
-
-	// issue usb interrupt read
-	if (priv && priv->irq_urb) {
-		// submit urb
-		if ((retval = usb_submit_urb (priv->irq_urb, GFP_KERNEL)) != 0)
-			dbg ("gl_interrupt_read: submit fail - %X...", retval);
-		else
-			dbg ("gl_interrupt_read: submit success...");
-	}
-
-	return 0;
-}
-
-// check whether another side is connected
-static int genelink_check_connect (struct usbnet *dev)
-{
-	int			retval;
-
-	dbg ("genelink_check_connect...");
-
-	// detect whether another side is connected
-	if ((retval = gl_control_write (dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
-		dbg ("%s: genelink_check_connect write fail - %X",
-			dev->net.name, retval);
-		return retval;
-	}
-
-	// usb interrupt read to ack another side 
-	if ((retval = gl_interrupt_read (dev)) != 0) {
-		dbg ("%s: genelink_check_connect read fail - %X",
-			dev->net.name, retval);
-		return retval;
-	}
-
-	dbg ("%s: genelink_check_connect read success", dev->net.name);
-	return 0;
-}
-
-// allocate and initialize the private data for genelink
-static int genelink_init (struct usbnet *dev)
-{
-	struct gl_priv *priv;
-
-	// allocate the private data structure
-	if ((priv = kmalloc (sizeof *priv, GFP_KERNEL)) == 0) {
-		dbg ("%s: cannot allocate private data per device",
-			dev->net.name);
-		return -ENOMEM;
-	}
-
-	// allocate irq urb
-	if ((priv->irq_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
-		dbg ("%s: cannot allocate private irq urb per device",
-			dev->net.name);
-		kfree (priv);
-		return -ENOMEM;
-	}
-
-	// fill irq urb
-	FILL_INT_URB (priv->irq_urb, dev->udev,
-		usb_rcvintpipe (dev->udev, GENELINK_INTERRUPT_PIPE),
-		priv->irq_buf, INTERRUPT_BUFSIZE,
-		gl_interrupt_complete, 0,
-		GENELINK_INTERRUPT_INTERVAL);
-
-	// set private data pointer
-	dev->priv_data = priv;
-
-	return 0;
-}
-
-// release the private data
-static int genelink_free (struct usbnet *dev)
-{
-	struct gl_priv	*priv = dev->priv_data;
-
-	if (!priv) 
-		return 0;
-
-// FIXME:  can't cancel here; it's synchronous, and
-// should have happened earlier in any case (interrupt
-// handling needs to be generic)
-
-	// cancel irq urb first
-	usb_unlink_urb (priv->irq_urb);
-
-	// free irq urb
-	usb_free_urb (priv->irq_urb);
-
-	// free the private data structure
-	kfree (priv);
-
-	return 0;
-}
-
-#else
-
-static int genelink_check_connect (struct usbnet *dev)
-{
-	dbg ("%s: assuming peer is connected", dev->net.name);
-	return 0;
-}
-
-#endif
-
-// reset the device status
-static int genelink_reset (struct usbnet *dev)
-{
-	// we don't need to reset, just return 0
-	return 0;
-}
-
-static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
-{
-	struct gl_header	*header;
-	struct gl_packet	*packet;
-	struct sk_buff		*gl_skb;
-	int			status;
-	u32			size;
-
-	header = (struct gl_header *) skb->data;
-
-	// get the packet count of the received skb
-	le32_to_cpus (&header->packet_count);
-	if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS)
-			|| (header->packet_count < 0)) {
-		dbg ("genelink: illegal received packet count %d",
-			header->packet_count);
-		return 0;
-	}
-
-	// set the current packet pointer to the first packet
-	packet = &header->packets;
-
-	// decrement the length for the packet count size 4 bytes
-	skb_pull (skb, 4);
-
-	while (header->packet_count > 1) {
-		// get the packet length
-		size = packet->packet_length;
-
-		// this may be a broken packet
-		if (size > GL_MAX_PACKET_LEN) {
-			dbg ("genelink: illegal rx length %d", size);
-			return 0;
-		}
-
-		// allocate the skb for the individual packet
-		gl_skb = alloc_skb (size, GFP_ATOMIC);
-		if (gl_skb == 0)
-			return 0;
-
-		// copy the packet data to the new skb
-		memcpy (gl_skb->data, packet->packet_data, size);
-
-		// set skb data size
-		gl_skb->len = size;
-		gl_skb->dev = &dev->net;
-
-		// determine the packet's protocol ID
-		gl_skb->protocol = eth_type_trans (gl_skb, &dev->net);
-
-		// update the status
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += size;
-
-		// notify os of the received packet
-		status = netif_rx (gl_skb);
-
-		// advance to the next packet
-		packet = (struct gl_packet *)
-			&packet->packet_data [size];
-		header->packet_count--;
-
-		// shift the data pointer to the next gl_packet
-		skb_pull (skb, size + 4);
-	}
-
-	// skip the packet length field 4 bytes
-	skb_pull (skb, 4);
-
-	if (skb->len > GL_MAX_PACKET_LEN) {
-		dbg ("genelink: illegal rx length %d", skb->len);
-		return 0;
-	}
-	return 1;
-}
-
-static struct sk_buff *
-genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
-	int 	padlen;
-	int	length = skb->len;
-	int	headroom = skb_headroom (skb);
-	int	tailroom = skb_tailroom (skb);
-	u32	*packet_count;
-	u32	*packet_len;
-
-	// FIXME:  magic numbers, bleech
-	padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1;
-
-	if ((!skb_cloned (skb))
-			&& ((headroom + tailroom) >= (padlen + (4 + 4*1)))) {
-		if ((headroom < (4 + 4*1)) || (tailroom < padlen)) {
-			skb->data = memmove (skb->head + (4 + 4*1),
-					     skb->data, skb->len);
-			skb->tail = skb->data + skb->len;
-		}
-	} else {
-		struct sk_buff	*skb2;
-		skb2 = skb_copy_expand (skb, (4 + 4*1) , padlen, flags);
-		dev_kfree_skb_any (skb);
-		skb = skb2;
-	}
-
-	// attach the packet count to the header
-	packet_count = (u32 *) skb_push (skb, (4 + 4*1));
-	packet_len = packet_count + 1;
-
-	// FIXME little endian?
-	*packet_count = 1;
-	*packet_len = length;
-
-	// add padding byte
-	if ((skb->len % EP_SIZE (dev)) == 0)
-		skb_put (skb, 1);
-
-	return skb;
-}
-
-static const struct driver_info	genelink_info = {
-	description:	"Genesys GeneLink",
-	flags:		FLAG_FRAMING_GL | FLAG_NO_SETINT,
-	reset:		genelink_reset,
-	check_connect:	genelink_check_connect,
-	rx_fixup:	genelink_rx_fixup,
-	tx_fixup:	genelink_tx_fixup,
-
-	in: 1, out: 2,
-	epsize:	64,
-};
-
-#endif /* CONFIG_USB_GENESYS */
-
-
-
-#ifdef	CONFIG_USB_LINUXDEV
-
-/*-------------------------------------------------------------------------
- *
- * This could talk to a device that uses Linux, such as a PDA or
- * an embedded system, or in fact to any "smart" device using this
- * particular mapping of USB and Ethernet.
- *
- * Such a Linux host would need a "USB Device Controller" hardware
- * (not "USB Host Controller"), and a network driver talking to that
- * hardware.
- *
- * One example is Intel's SA-1100 chip, which integrates basic USB
- * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA.
- *
- *-------------------------------------------------------------------------*/
-
-
-static const struct driver_info	linuxdev_info = {
-	description:	"Linux Device",
-	// no reset defined (yet?)
-	// no check_connect needed!
-	in: 2, out: 1,
-	epsize:	64,
-};
-
-#endif	/* CONFIG_USB_LINUXDEV */
-
-
-
-#ifdef	CONFIG_USB_NET1080
-
-/*-------------------------------------------------------------------------
- *
- * Netchip 1080 driver ... http://www.netchip.com
- * Used in LapLink cables
- *
- *-------------------------------------------------------------------------*/
-
-/*
- * NetChip framing of ethernet packets, supporting additional error
- * checks for links that may drop bulk packets from inside messages.
- * Odd USB length == always short read for last usb packet.
- *	- nc_header
- *	- Ethernet header (14 bytes)
- *	- payload
- *	- (optional padding byte, if needed so length becomes odd)
- *	- nc_trailer
- *
- * This framing is to be avoided for non-NetChip devices.
- */
-
-struct nc_header {		// packed:
-	u16	hdr_len;		// sizeof nc_header (LE, all)
-	u16	packet_len;		// payload size (including ethhdr)
-	u16	packet_id;		// detects dropped packets
-#define MIN_HEADER	6
-
-	// all else is optional, and must start with:
-	// u16	vendorId;		// from usb-if
-	// u16	productId;
-} __attribute__((__packed__));
-
-#define	PAD_BYTE	((unsigned char)0xAC)
-
-struct nc_trailer {
-	u16	packet_id;
-} __attribute__((__packed__));
-
-// packets may use FLAG_FRAMING_NC and optional pad
-#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
-				+ sizeof (struct ethhdr) \
-				+ (mtu) \
-				+ 1 \
-				+ sizeof (struct nc_trailer))
-
-#define MIN_FRAMED	FRAMED_SIZE(0)
-
-
-/*
- * Zero means no timeout; else, how long a 64 byte bulk packet may be queued
- * before the hardware drops it.  If that's done, the driver will need to
- * frame network packets to guard against the dropped USB packets.  The win32
- * driver sets this for both sides of the link.
- */
-#define	NC_READ_TTL_MS	((u8)255)	// ms
-
-/*
- * We ignore most registers and EEPROM contents.
- */
-#define	REG_USBCTL	((u8)0x04)
-#define REG_TTL		((u8)0x10)
-#define REG_STATUS	((u8)0x11)
-
-/*
- * Vendor specific requests to read/write data
- */
-#define	REQUEST_REGISTER	((u8)0x10)
-#define	REQUEST_EEPROM		((u8)0x11)
-
-static int
-nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
-{
-	int status = usb_control_msg (dev->udev,
-		usb_rcvctrlpipe (dev->udev, 0),
-		req,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		0, regnum,
-		retval_ptr, sizeof *retval_ptr,
-		CONTROL_TIMEOUT_JIFFIES);
-	if (status > 0)
-		status = 0;
-	if (!status)
-		le16_to_cpus (retval_ptr);
-	return status;
-}
-
-static inline int
-nc_register_read (struct usbnet *dev, u8 regnum, u16 *retval_ptr)
-{
-	return nc_vendor_read (dev, REQUEST_REGISTER, regnum, retval_ptr);
-}
-
-// no retval ... can become async, usable in_interrupt()
-static void
-nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value)
-{
-	usb_control_msg (dev->udev,
-		usb_sndctrlpipe (dev->udev, 0),
-		req,
-		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		value, regnum,
-		0, 0,			// data is in setup packet
-		CONTROL_TIMEOUT_JIFFIES);
-}
-
-static inline void
-nc_register_write (struct usbnet *dev, u8 regnum, u16 value)
-{
-	nc_vendor_write (dev, REQUEST_REGISTER, regnum, value);
-}
-
-
-#if 0
-static void nc_dump_registers (struct usbnet *dev)
-{
-	u8	reg;
-	u16	*vp = kmalloc (sizeof (u16));
-
-	if (!vp) {
-		dbg ("no memory?");
-		return;
-	}
-
-	dbg ("%s registers:", dev->net.name);
-	for (reg = 0; reg < 0x20; reg++) {
-		int retval;
-
-		// reading some registers is trouble
-		if (reg >= 0x08 && reg <= 0xf)
-			continue;
-		if (reg >= 0x12 && reg <= 0x1e)
-			continue;
-
-		retval = nc_register_read (dev, reg, vp);
-		if (retval < 0)
-			dbg ("%s reg [0x%x] ==> error %d",
-				dev->net.name, reg, retval);
-		else
-			dbg ("%s reg [0x%x] = 0x%x",
-				dev->net.name, reg, *vp);
-	}
-	kfree (vp);
-}
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Control register
- */
-
-#define	USBCTL_WRITABLE_MASK	0x1f0f
-// bits 15-13 reserved, r/o
-#define	USBCTL_ENABLE_LANG	(1 << 12)
-#define	USBCTL_ENABLE_MFGR	(1 << 11)
-#define	USBCTL_ENABLE_PROD	(1 << 10)
-#define	USBCTL_ENABLE_SERIAL	(1 << 9)
-#define	USBCTL_ENABLE_DEFAULTS	(1 << 8)
-// bits 7-4 reserved, r/o
-#define	USBCTL_FLUSH_OTHER	(1 << 3)
-#define	USBCTL_FLUSH_THIS	(1 << 2)
-#define	USBCTL_DISCONN_OTHER	(1 << 1)
-#define	USBCTL_DISCONN_THIS	(1 << 0)
-
-static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
-{
-#ifdef DEBUG
-	devdbg (dev, "net1080 %03d/%03d usbctl 0x%x:%s%s%s%s%s;"
-			" this%s%s;"
-			" other%s%s; r/o 0x%x",
-		dev->udev->bus->busnum, dev->udev->devnum,
-		usbctl,
-		(usbctl & USBCTL_ENABLE_LANG) ? " lang" : "",
-		(usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "",
-		(usbctl & USBCTL_ENABLE_PROD) ? " prod" : "",
-		(usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "",
-		(usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "",
-
-		(usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "",
-		(usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "",
-		(usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "",
-		(usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
-		usbctl & ~USBCTL_WRITABLE_MASK
-		);
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Status register
- */
-
-#define	STATUS_PORT_A		(1 << 15)
-
-#define	STATUS_CONN_OTHER	(1 << 14)
-#define	STATUS_SUSPEND_OTHER	(1 << 13)
-#define	STATUS_MAILBOX_OTHER	(1 << 12)
-#define	STATUS_PACKETS_OTHER(n)	(((n) >> 8) && 0x03)
-
-#define	STATUS_CONN_THIS	(1 << 6)
-#define	STATUS_SUSPEND_THIS	(1 << 5)
-#define	STATUS_MAILBOX_THIS	(1 << 4)
-#define	STATUS_PACKETS_THIS(n)	(((n) >> 0) && 0x03)
-
-#define	STATUS_UNSPEC_MASK	0x0c8c
-#define	STATUS_NOISE_MASK 	((u16)~(0x0303|STATUS_UNSPEC_MASK))
-
-
-static inline void nc_dump_status (struct usbnet *dev, u16 status)
-{
-#ifdef DEBUG
-	devdbg (dev, "net1080 %03d/%03d status 0x%x:"
-			" this (%c) PKT=%d%s%s%s;"
-			" other PKT=%d%s%s%s; unspec 0x%x",
-		dev->udev->bus->busnum, dev->udev->devnum,
-		status,
-
-		// XXX the packet counts don't seem right
-		// (1 at reset, not 0); maybe UNSPEC too
-
-		(status & STATUS_PORT_A) ? 'A' : 'B',
-		STATUS_PACKETS_THIS (status),
-		(status & STATUS_CONN_THIS) ? " CON" : "",
-		(status & STATUS_SUSPEND_THIS) ? " SUS" : "",
-		(status & STATUS_MAILBOX_THIS) ? " MBOX" : "",
-
-		STATUS_PACKETS_OTHER (status),
-		(status & STATUS_CONN_OTHER) ? " CON" : "",
-		(status & STATUS_SUSPEND_OTHER) ? " SUS" : "",
-		(status & STATUS_MAILBOX_OTHER) ? " MBOX" : "",
-
-		status & STATUS_UNSPEC_MASK
-		);
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * TTL register
- */
-
-#define	TTL_THIS(ttl)	(0x00ff & ttl)
-#define	TTL_OTHER(ttl)	(0x00ff & (ttl >> 8))
-#define MK_TTL(this,other)	((u16)(((other)<<8)|(0x00ff&(this))))
-
-static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
-{
-#ifdef DEBUG
-	devdbg (dev, "net1080 %03d/%03d ttl 0x%x this = %d, other = %d",
-		dev->udev->bus->busnum, dev->udev->devnum,
-		ttl,
-
-		TTL_THIS (ttl),
-		TTL_OTHER (ttl)
-		);
-#endif
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int net1080_reset (struct usbnet *dev)
-{
-	u16		usbctl, status, ttl;
-	u16		*vp = kmalloc (sizeof (u16), GFP_KERNEL);
-	int		retval;
-
-	if (!vp)
-		return -ENOMEM;
-
-	// nc_dump_registers (dev);
-
-	if ((retval = nc_register_read (dev, REG_STATUS, vp)) < 0) {
-		dbg ("can't read dev %d status: %d", dev->udev->devnum, retval);
-		goto done;
-	}
-	status = *vp;
-	// nc_dump_status (dev, status);
-
-	if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
-		dbg ("can't read USBCTL, %d", retval);
-		goto done;
-	}
-	usbctl = *vp;
-	// nc_dump_usbctl (dev, usbctl);
-
-	nc_register_write (dev, REG_USBCTL,
-			USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
-
-	if ((retval = nc_register_read (dev, REG_TTL, vp)) < 0) {
-		dbg ("can't read TTL, %d", retval);
-		goto done;
-	}
-	ttl = *vp;
-	// nc_dump_ttl (dev, ttl);
-
-	nc_register_write (dev, REG_TTL,
-			MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
-	dbg ("%s: assigned TTL, %d ms", dev->net.name, NC_READ_TTL_MS);
-
-	devdbg (dev, "port %c, peer %sconnected",
-		(status & STATUS_PORT_A) ? 'A' : 'B',
-		(status & STATUS_CONN_OTHER) ? "" : "dis"
-		);
-	retval = 0;
-
-done:
-	kfree (vp);
-	return retval;
-}
-
-static int net1080_check_connect (struct usbnet *dev)
-{
-	int			retval;
-	u16			status;
-	u16			*vp = kmalloc (sizeof (u16), GFP_KERNEL);
-
-	if (!vp)
-		return -ENOMEM;
-	retval = nc_register_read (dev, REG_STATUS, vp);
-	status = *vp;
-	kfree (vp);
-	if (retval != 0) {
-		dbg ("%s net1080_check_conn read - %d", dev->net.name, retval);
-		return retval;
-	}
-	if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER)
-		return -ENOLINK;
-	return 0;
-}
-
-static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
-{
-	struct nc_header	*header;
-	struct nc_trailer	*trailer;
-
-	if (!(skb->len & 0x01)
-			|| MIN_FRAMED > skb->len
-			|| skb->len > FRAMED_SIZE (dev->net.mtu)) {
-		dev->stats.rx_frame_errors++;
-		dbg ("rx framesize %d range %d..%d mtu %d", skb->len,
-			MIN_FRAMED, FRAMED_SIZE (dev->net.mtu),
-			dev->net.mtu
-			);
-		return 0;
-	}
-
-	header = (struct nc_header *) skb->data;
-	le16_to_cpus (&header->hdr_len);
-	le16_to_cpus (&header->packet_len);
-	if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
-		dev->stats.rx_frame_errors++;
-		dbg ("packet too big, %d", header->packet_len);
-		return 0;
-	} else if (header->hdr_len < MIN_HEADER) {
-		dev->stats.rx_frame_errors++;
-		dbg ("header too short, %d", header->hdr_len);
-		return 0;
-	} else if (header->hdr_len > MIN_HEADER) {
-		// out of band data for us?
-		dbg ("header OOB, %d bytes",
-			header->hdr_len - MIN_HEADER);
-		// switch (vendor/product ids) { ... }
-	}
-	skb_pull (skb, header->hdr_len);
-
-	trailer = (struct nc_trailer *)
-		(skb->data + skb->len - sizeof *trailer);
-	skb_trim (skb, skb->len - sizeof *trailer);
-
-	if ((header->packet_len & 0x01) == 0) {
-		if (skb->data [header->packet_len] != PAD_BYTE) {
-			dev->stats.rx_frame_errors++;
-			dbg ("bad pad");
-			return 0;
-		}
-		skb_trim (skb, skb->len - 1);
-	}
-	if (skb->len != header->packet_len) {
-		dev->stats.rx_frame_errors++;
-		dbg ("bad packet len %d (expected %d)",
-			skb->len, header->packet_len);
-		return 0;
-	}
-	if (header->packet_id != get_unaligned (&trailer->packet_id)) {
-		dev->stats.rx_fifo_errors++;
-		dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
-			header->packet_id, trailer->packet_id);
-		return 0;
-	}
-#if 0
-	devdbg (dev, "frame <rx h %d p %d id %d", header->hdr_len,
-		header->packet_len, header->packet_id);
-#endif
-	return 1;
-}
-
-static struct sk_buff *
-net1080_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags)
-{
-	int			padlen;
-	struct sk_buff		*skb2;
-
-	padlen = ((skb->len + sizeof (struct nc_header)
-			+ sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
-	if (!skb_cloned (skb)) {
-		int	headroom = skb_headroom (skb);
-		int	tailroom = skb_tailroom (skb);
-
-		if ((padlen + sizeof (struct nc_trailer)) <= tailroom
-			    && sizeof (struct nc_header) <= headroom)
-			return skb;
-
-		if ((sizeof (struct nc_header) + padlen
-					+ sizeof (struct nc_trailer)) <
-				(headroom + tailroom)) {
-			skb->data = memmove (skb->head
-						+ sizeof (struct nc_header),
-					    skb->data, skb->len);
-			skb->tail = skb->data + skb->len;
-			return skb;
-		}
-	}
-	skb2 = skb_copy_expand (skb,
-				sizeof (struct nc_header),
-				sizeof (struct nc_trailer) + padlen,
-				flags);
-	dev_kfree_skb_any (skb);
-	return skb2;
-}
-
-static const struct driver_info	net1080_info = {
-	description:	"NetChip TurboCONNECT",
-	flags:		FLAG_FRAMING_NC,
-	reset:		net1080_reset,
-	check_connect:	net1080_check_connect,
-	rx_fixup:	net1080_rx_fixup,
-	tx_fixup:	net1080_tx_fixup,
-
-	in: 1, out: 1,		// direction distinguishes these
-	epsize:	64,
-};
-
-#endif /* CONFIG_USB_NET1080 */
-
-
-
-#ifdef CONFIG_USB_PL2301
-
-/*-------------------------------------------------------------------------
- *
- * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com
- *
- *-------------------------------------------------------------------------*/
-
-/*
- * Bits 0-4 can be used for software handshaking; they're set from
- * one end, cleared from the other, "read" with the interrupt byte.
- */
-#define	PL_S_EN		(1<<7)		/* (feature only) suspend enable */
-/* reserved bit -- rx ready (6) ? */
-#define	PL_TX_READY	(1<<5)		/* (interrupt only) transmit ready */
-#define	PL_RESET_OUT	(1<<4)		/* reset output pipe */
-#define	PL_RESET_IN	(1<<3)		/* reset input pipe */
-#define	PL_TX_C		(1<<2)		/* transmission complete */
-#define	PL_TX_REQ	(1<<1)		/* transmission received */
-#define	PL_PEER_E	(1<<0)		/* peer exists */
-
-static inline int
-pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index)
-{
-	return usb_control_msg (dev->udev,
-		usb_rcvctrlpipe (dev->udev, 0),
-		req,
-		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-		val, index,
-		0, 0,
-		CONTROL_TIMEOUT_JIFFIES);
-}
-
-static inline int
-pl_clear_QuickLink_features (struct usbnet *dev, int val)
-{
-	return pl_vendor_req (dev, 1, (u8) val, 0);
-}
-
-static inline int
-pl_set_QuickLink_features (struct usbnet *dev, int val)
-{
-	return pl_vendor_req (dev, 3, (u8) val, 0);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int pl_reset (struct usbnet *dev)
-{
-	return pl_set_QuickLink_features (dev,
-		PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
-}
-
-static int pl_check_connect (struct usbnet *dev)
-{
-	// FIXME test interrupt data PL_PEER_E bit
-	// plus, there's some handshake done by
-	// the prolific win32 driver... 
-	dbg ("%s: assuming peer is connected", dev->net.name);
-	return 0;
-}
-
-static const struct driver_info	prolific_info = {
-	description:	"Prolific PL-2301/PL-2302",
-	flags:		FLAG_NO_SETINT,
-		/* some PL-2302 versions seem to fail usb_set_interface() */
-	reset:		pl_reset,
-	check_connect:	pl_check_connect,
-
-	in: 3, out: 2,
-	epsize:	64,
-};
-
-#endif /* CONFIG_USB_PL2301 */
-
-
-
-/*-------------------------------------------------------------------------
- *
- * Network Device Driver (peer link to "Host Device", from USB host)
- *
- *-------------------------------------------------------------------------*/
-
-static int usbnet_change_mtu (struct net_device *net, int new_mtu)
-{
-	struct usbnet	*dev = (struct usbnet *) net->priv;
-
-	if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
-		return -EINVAL;
-#ifdef	CONFIG_USB_NET1080
-	if (((dev->driver_info->flags) & FLAG_FRAMING_NC)) {
-		if (FRAMED_SIZE (new_mtu) > MAX_PACKET)
-			return -EINVAL;
-	}
-#endif
-#ifdef	CONFIG_USB_GENESYS
-	if (((dev->driver_info->flags) & FLAG_FRAMING_GL)
-			&& new_mtu > GL_MAX_PACKET_LEN)
-		return -EINVAL;
-#endif
-	// no second zero-length packet read wanted after mtu-sized packets
-	if (((new_mtu + sizeof (struct ethhdr)) % EP_SIZE (dev)) == 0)
-		return -EDOM;
-	net->mtu = new_mtu;
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct net_device_stats *usbnet_get_stats (struct net_device *net)
-{
-	return &((struct usbnet *) net->priv)->stats;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* urb completions are currently in_irq; avoid doing real work then. */
-
-static void defer_bh (struct usbnet *dev, struct sk_buff *skb)
-{
-	struct sk_buff_head	*list = skb->list;
-	unsigned long		flags;
-
-	spin_lock_irqsave (&list->lock, flags);
-	__skb_unlink (skb, list);
-	spin_unlock (&list->lock);
-	spin_lock (&dev->done.lock);
-	__skb_queue_tail (&dev->done, skb);
-	if (dev->done.qlen == 1)
-		tasklet_schedule (&dev->bh);
-	spin_unlock_irqrestore (&dev->done.lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void rx_complete (struct urb *urb);
-
-static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
-{
-	struct sk_buff		*skb;
-	struct skb_data		*entry;
-	int			retval = 0;
-	unsigned long		lockflags;
-	size_t			size;
-
-#ifdef CONFIG_USB_NET1080
-	if (dev->driver_info->flags & FLAG_FRAMING_NC)
-		size = FRAMED_SIZE (dev->net.mtu);
-	else
-#endif
-#ifdef CONFIG_USB_GENESYS
-	if (dev->driver_info->flags & FLAG_FRAMING_GL)
-		size = GL_RCV_BUF_SIZE;
-	else
-#endif
-		size = (sizeof (struct ethhdr) + dev->net.mtu);
-
-	if ((skb = alloc_skb (size, flags)) == 0) {
-		dbg ("no rx skb");
-		tasklet_schedule (&dev->bh);
-		usb_free_urb (urb);
-		return;
-	}
-
-	entry = (struct skb_data *) skb->cb;
-	entry->urb = urb;
-	entry->dev = dev;
-	entry->state = rx_start;
-	entry->length = 0;
-
-	FILL_BULK_URB (urb, dev->udev,
-		usb_rcvbulkpipe (dev->udev, dev->driver_info->in),
-		skb->data, size, rx_complete, skb);
-	urb->transfer_flags |= USB_ASYNC_UNLINK;
-#ifdef	REALLY_QUEUE
-	urb->transfer_flags |= USB_QUEUE_BULK;
-#endif
-#if 0
-	// Idle-but-posted reads with UHCI really chew up
-	// PCI bandwidth unless FSBR is disabled
-	urb->transfer_flags |= USB_NO_FSBR;
-#endif
-
-	spin_lock_irqsave (&dev->rxq.lock, lockflags);
-
-	if (netif_running (&dev->net)) {
-		if ((retval = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
-			dbg ("%s rx submit, %d", dev->net.name, retval);
-			tasklet_schedule (&dev->bh);
-		} else {
-			__skb_queue_tail (&dev->rxq, skb);
-		}
-	} else {
-		dbg ("rx: stopped");
-		retval = -ENOLINK;
-	}
-	spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
-	if (retval) {
-		dev_kfree_skb_any (skb);
-		usb_free_urb (urb);
-	}
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
-{
-	if (dev->driver_info->rx_fixup
-			&& !dev->driver_info->rx_fixup (dev, skb))
-		goto error;
-	// else network stack removes extra byte if we forced a short packet
-
-	if (skb->len) {
-		int	status;
-
-// FIXME: eth_copy_and_csum "small" packets to new SKB (small < ~200 bytes) ?
-
-		skb->dev = &dev->net;
-		skb->protocol = eth_type_trans (skb, &dev->net);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
-
-#ifdef	VERBOSE
-		devdbg (dev, "< rx, len %d, type 0x%x",
-			skb->len + sizeof (struct ethhdr), skb->protocol);
-#endif
-		memset (skb->cb, 0, sizeof (struct skb_data));
-		status = netif_rx (skb);
-		if (status != NET_RX_SUCCESS)
-			devdbg (dev, "netif_rx status %d", status);
-	} else {
-		dbg ("drop");
-error:
-		dev->stats.rx_errors++;
-		skb_queue_tail (&dev->done, skb);
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void rx_complete (struct urb *urb)
-{
-	struct sk_buff		*skb = (struct sk_buff *) urb->context;
-	struct skb_data		*entry = (struct skb_data *) skb->cb;
-	struct usbnet		*dev = entry->dev;
-	int			urb_status = urb->status;
-
-	skb_put (skb, urb->actual_length);
-	entry->state = rx_done;
-	entry->urb = 0;
-
-	switch (urb_status) {
-	    // success
-	    case 0:
-		if (MIN_PACKET > skb->len || skb->len > MAX_PACKET) {
-			entry->state = rx_cleanup;
-			dev->stats.rx_errors++;
-			dev->stats.rx_length_errors++;
-			dbg ("rx length %d", skb->len);
-		}
-		break;
-
-	    // software-driven interface shutdown
-	    case -ECONNRESET:		// usb-ohci, usb-uhci
-	    case -ECONNABORTED:		// uhci ... for usb-uhci, INTR
-		dbg ("%s shutdown, code %d", dev->net.name, urb_status);
-		entry->state = rx_cleanup;
-		// do urb frees only in the tasklet
-		entry->urb = urb;
-		urb = 0;
-		break;
-
-	    // data overrun ... flush fifo?
-	    case -EOVERFLOW:
-		dev->stats.rx_over_errors++;
-		// FALLTHROUGH
-	    
-	    default:
-		// on unplug we'll get a burst of ETIMEDOUT/EILSEQ
-		// till the khubd gets and handles its interrupt.
-		entry->state = rx_cleanup;
-		dev->stats.rx_errors++;
-		dbg ("%s rx: status %d", dev->net.name, urb_status);
-		break;
-	}
-
-	defer_bh (dev, skb);
-
-	if (urb) {
-		if (netif_running (&dev->net)) {
-			rx_submit (dev, urb, GFP_ATOMIC);
-			return;
-		}
-	}
-#ifdef	VERBOSE
-	dbg ("no read resubmitted");
-#endif /* VERBOSE */
-}
-
-/*-------------------------------------------------------------------------*/
-
-// unlink pending rx/tx; completion handlers do all other cleanup
-
-static int unlink_urbs (struct sk_buff_head *q)
-{
-	unsigned long		flags;
-	struct sk_buff		*skb, *skbnext;
-	int			count = 0;
-
-	spin_lock_irqsave (&q->lock, flags);
-	for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) {
-		struct skb_data		*entry;
-		struct urb		*urb;
-		int			retval;
-
-		entry = (struct skb_data *) skb->cb;
-		urb = entry->urb;
-		skbnext = skb->next;
-
-		// during some PM-driven resume scenarios,
-		// these (async) unlinks complete immediately
-		retval = usb_unlink_urb (urb);
-		if (retval < 0)
-			dbg ("unlink urb err, %d", retval);
-		else
-			count++;
-	}
-	spin_unlock_irqrestore (&q->lock, flags);
-	return count;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-// precondition: never called in_interrupt
-
-static int usbnet_stop (struct net_device *net)
-{
-	struct usbnet		*dev = (struct usbnet *) net->priv;
-	int			temp;
-	DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
-	DECLARE_WAITQUEUE (wait, current);
-
-	mutex_lock (&dev->mutex);
-	netif_stop_queue (net);
-
-	devdbg (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
-		dev->stats.rx_packets, dev->stats.tx_packets, 
-		dev->stats.rx_errors, dev->stats.tx_errors
-		);
-
-	// ensure there are no more active urbs
-	add_wait_queue (&unlink_wakeup, &wait);
-	dev->wait = &unlink_wakeup;
-	temp = unlink_urbs (&dev->txq) + unlink_urbs (&dev->rxq);
-
-	// maybe wait for deletions to finish.
-	while (skb_queue_len (&dev->rxq)
-			&& skb_queue_len (&dev->txq)
-			&& skb_queue_len (&dev->done)) {
-		set_current_state (TASK_UNINTERRUPTIBLE);
-		schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
-		dbg ("waited for %d urb completions", temp);
-	}
-	dev->wait = 0;
-	remove_wait_queue (&unlink_wakeup, &wait); 
-
-	mutex_unlock (&dev->mutex);
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// posts reads, and enables write queing
-
-// precondition: never called in_interrupt
-
-static int usbnet_open (struct net_device *net)
-{
-	struct usbnet		*dev = (struct usbnet *) net->priv;
-	int			retval = 0;
-	struct driver_info	*info = dev->driver_info;
-
-	mutex_lock (&dev->mutex);
-
-	// put into "known safe" state
-	if (info->reset && (retval = info->reset (dev)) < 0) {
-		devinfo (dev, "open reset fail (%d) usbnet %03d/%03d, %s",
-			retval,
-			dev->udev->bus->busnum, dev->udev->devnum,
-			info->description);
-		goto done;
-	}
-
-	// insist peer be connected
-	if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
-		devdbg (dev, "can't open; %d", retval);
-		goto done;
-	}
-
-	netif_start_queue (net);
-	devdbg (dev, "open: enable queueing (rx %d, tx %d) mtu %d %s framing",
-		RX_QLEN, TX_QLEN, dev->net.mtu,
-		(info->flags & (FLAG_FRAMING_NC | FLAG_FRAMING_GL))
-		    ? ((info->flags & FLAG_FRAMING_NC)
-			? "NetChip"
-			: "GeneSys")
-		    : "raw"
-		);
-
-	// delay posting reads until we're fully open
-	tasklet_schedule (&dev->bh);
-done:
-	mutex_unlock (&dev->mutex);
-	return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* usb_clear_halt cannot be called in interrupt context */
-
-static void
-tx_clear_halt (void *data)
-{
-	struct usbnet		*dev = data;
-
-	usb_clear_halt (dev->udev,
-		usb_sndbulkpipe (dev->udev, dev->driver_info->out));
-	netif_wake_queue (&dev->net);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void tx_complete (struct urb *urb)
-{
-	struct sk_buff		*skb = (struct sk_buff *) urb->context;
-	struct skb_data		*entry = (struct skb_data *) skb->cb;
-	struct usbnet		*dev = entry->dev;
-
-	if (urb->status == -EPIPE) {
-		if (dev->ctrl_task.sync == 0) {
-			dev->ctrl_task.routine = tx_clear_halt;
-			dev->ctrl_task.data = dev;
-			schedule_task (&dev->ctrl_task);
-		} else {
-			dbg ("Cannot clear TX stall");
-		}
-	}
-	urb->dev = 0;
-	entry->state = tx_done;
-	defer_bh (dev, skb);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void usbnet_tx_timeout (struct net_device *net)
-{
-	struct usbnet		*dev = (struct usbnet *) net->priv;
-
-	unlink_urbs (&dev->txq);
-	tasklet_schedule (&dev->bh);
-
-	// FIXME: device recovery -- reset?
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
-{
-	struct usbnet		*dev = (struct usbnet *) net->priv;
-	int			length = skb->len;
-	int			retval = NET_XMIT_SUCCESS;
-	struct urb		*urb = 0;
-	struct skb_data		*entry;
-	struct driver_info	*info = dev->driver_info;
-	unsigned long		flags;
-#ifdef	CONFIG_USB_NET1080
-	struct nc_header	*header = 0;
-	struct nc_trailer	*trailer = 0;
-#endif	/* CONFIG_USB_NET1080 */
-
-	flags = in_interrupt () ? GFP_ATOMIC : GFP_NOIO; /* might be used for nfs */
-
-	// some devices want funky USB-level framing, for
-	// win32 driver (usually) and/or hardware quirks
-	if (info->tx_fixup) {
-		skb = info->tx_fixup (dev, skb, flags);
-		if (!skb) {
-			dbg ("can't tx_fixup skb");
-			goto drop;
-		}
-	}
-
-	if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
-		dbg ("no urb");
-		goto drop;
-	}
-
-	entry = (struct skb_data *) skb->cb;
-	entry->urb = urb;
-	entry->dev = dev;
-	entry->state = tx_start;
-	entry->length = length;
-
-	// FIXME: reorganize a bit, so that fixup() fills out NetChip
-	// framing too. (Packet ID update needs the spinlock...)
-
-#ifdef	CONFIG_USB_NET1080
-	if (info->flags & FLAG_FRAMING_NC) {
-		header = (struct nc_header *) skb_push (skb, sizeof *header);
-		header->hdr_len = cpu_to_le16 (sizeof (*header));
-		header->packet_len = cpu_to_le16 (length);
-		if (!((skb->len + sizeof *trailer) & 0x01))
-			*skb_put (skb, 1) = PAD_BYTE;
-		trailer = (struct nc_trailer *) skb_put (skb, sizeof *trailer);
-	} else
-#endif	/* CONFIG_USB_NET1080 */
-
-	/* don't assume the hardware handles USB_ZERO_PACKET */
-	if ((length % EP_SIZE (dev)) == 0)
-		skb->len++;
-
-	FILL_BULK_URB (urb, dev->udev,
-			usb_sndbulkpipe (dev->udev, info->out),
-			skb->data, skb->len, tx_complete, skb);
-	urb->transfer_flags |= USB_ASYNC_UNLINK;
-#ifdef	REALLY_QUEUE
-	urb->transfer_flags |= USB_QUEUE_BULK;
-#endif
-	// FIXME urb->timeout = ... jiffies ... ;
-
-	spin_lock_irqsave (&dev->txq.lock, flags);
-
-#ifdef	CONFIG_USB_NET1080
-	if (info->flags & FLAG_FRAMING_NC) {
-		header->packet_id = cpu_to_le16 (dev->packet_id++);
-		put_unaligned (header->packet_id, &trailer->packet_id);
-#if 0
-		devdbg (dev, "frame >tx h %d p %d id %d",
-			header->hdr_len, header->packet_len,
-			header->packet_id);
-#endif
-	}
-#endif	/* CONFIG_USB_NET1080 */
-
-	netif_stop_queue (net);
-	if ((retval = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
-		netif_start_queue (net);
-		dbg ("%s tx: submit urb err %d", net->name, retval);
-	} else {
-		net->trans_start = jiffies;
-		__skb_queue_tail (&dev->txq, skb);
-		if (dev->txq.qlen < TX_QLEN)
-			netif_start_queue (net);
-	}
-	spin_unlock_irqrestore (&dev->txq.lock, flags);
-
-	if (retval) {
-		devdbg (dev, "drop, code %d", retval);
-drop:
-		retval = NET_XMIT_DROP;
-		dev->stats.tx_dropped++;
-		if (skb)
-			dev_kfree_skb_any (skb);
-		usb_free_urb (urb);
-#ifdef	VERBOSE
-	} else {
-		devdbg (dev, "> tx, len %d, type 0x%x",
-			length, skb->protocol);
-#endif
-	}
-	return retval;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-// tasklet ... work that avoided running in_irq()
-
-static void usbnet_bh (unsigned long param)
-{
-	struct usbnet		*dev = (struct usbnet *) param;
-	struct sk_buff		*skb;
-	struct skb_data		*entry;
-
-	while ((skb = skb_dequeue (&dev->done))) {
-		entry = (struct skb_data *) skb->cb;
-		switch (entry->state) {
-		    case rx_done:
-			entry->state = rx_cleanup;
-			rx_process (dev, skb);
-			continue;
-		    case tx_done:
-			if (entry->urb->status) {
-				// can this statistic become more specific?
-				dev->stats.tx_errors++;
-				dbg ("%s tx: err %d", dev->net.name,
-					entry->urb->status);
-			} else {
-				dev->stats.tx_packets++;
-				dev->stats.tx_bytes += entry->length;
-			}
-			// FALLTHROUGH:
-		    case rx_cleanup:
-			usb_free_urb (entry->urb);
-			dev_kfree_skb (skb);
-			continue;
-		    default:
-			dbg ("%s: bogus skb state %d",
-				dev->net.name, entry->state);
-		}
-	}
-
-	// waiting for all pending urbs to complete?
-	if (dev->wait) {
-		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
-			wake_up (dev->wait);
-		}
-
-	// or are we maybe short a few urbs?
-	} else if (netif_running (&dev->net)) {
-		int	temp = dev->rxq.qlen;
-
-		if (temp < RX_QLEN) {
-			struct urb	*urb;
-			int		i;
-			for (i = 0; i < 3 && dev->rxq.qlen < RX_QLEN; i++) {
-				if ((urb = usb_alloc_urb (0, GFP_ATOMIC)) != 0)
-					rx_submit (dev, urb, GFP_ATOMIC);
-			}
-			if (temp != dev->rxq.qlen)
-				devdbg (dev, "rxqlen %d --> %d",
-						temp, dev->rxq.qlen);
-			if (dev->rxq.qlen < RX_QLEN)
-				tasklet_schedule (&dev->bh);
-		}
-		if (dev->txq.qlen < TX_QLEN)
-			netif_wake_queue (&dev->net);
-	}
-}
-
-
-
-/*-------------------------------------------------------------------------
- *
- * USB Device Driver support
- *
- *-------------------------------------------------------------------------*/
- 
-// precondition: never called in_interrupt
-
-static void usbnet_disconnect (struct usb_device *udev, void *ptr)
-{
-	struct usbnet	*dev = (struct usbnet *) ptr;
-
-	devinfo (dev, "unregister usbnet %03d/%03d, %s",
-		udev->bus->busnum, udev->devnum,
-		dev->driver_info->description);
-	
-	unregister_netdev (&dev->net);
-
-	mutex_lock (&usbnet_mutex);
-	mutex_lock (&dev->mutex);
-	list_del (&dev->dev_list);
-	mutex_unlock (&usbnet_mutex);
-
-	kfree (dev);
-	usb_dec_dev_use (udev);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-// precondition: never called in_interrupt
-
-static void *
-usbnet_probe (struct usb_device *udev, unsigned ifnum,
-			const struct usb_device_id *prod)
-{
-	struct usbnet			*dev;
-	struct net_device 		*net;
-	struct usb_interface_descriptor	*interface;
-	struct driver_info		*info;
-	int				altnum = 0;
-
-	info = (struct driver_info *) prod->driver_info;
-
-	// sanity check; expect dedicated interface/devices for now.
-	interface = &udev->actconfig->interface [ifnum].altsetting [altnum];
-	if (udev->descriptor.bNumConfigurations != 1
-			|| udev->config[0].bNumInterfaces != 1
-//			|| interface->bInterfaceClass != USB_CLASS_VENDOR_SPEC
-			) {
-		dbg ("Bogus config info");
-		return 0;
-	}
-
-	// more sanity (unless the device is broken)
-	if (!(info->flags & FLAG_NO_SETINT)) {
-		if (usb_set_interface (udev, ifnum, altnum) < 0) {
-			err ("set_interface failed");
-			return 0;
-		}
-	}
-
-	// set up our own records
-	if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) {
-		dbg ("can't kmalloc dev");
-		return 0;
-	}
-	memset (dev, 0, sizeof *dev);
-
-	init_MUTEX_LOCKED (&dev->mutex);
-	usb_inc_dev_use (udev);
-	dev->udev = udev;
-	dev->driver_info = info;
-	INIT_LIST_HEAD (&dev->dev_list);
-	skb_queue_head_init (&dev->rxq);
-	skb_queue_head_init (&dev->txq);
-	skb_queue_head_init (&dev->done);
-	dev->bh.func = usbnet_bh;
-	dev->bh.data = (unsigned long) dev;
-
-	// set up network interface records
-	net = &dev->net;
-	SET_MODULE_OWNER (net);
-	net->priv = dev;
-	strcpy (net->name, "usb%d");
-	memcpy (net->dev_addr, node_id, sizeof node_id);
-
-	// point-to-point link ... we always use Ethernet headers 
-	// supports win32 interop and the bridge driver.
-	ether_setup (net);
-
-	net->change_mtu = usbnet_change_mtu;
-	net->get_stats = usbnet_get_stats;
-	net->hard_start_xmit = usbnet_start_xmit;
-	net->open = usbnet_open;
-	net->stop = usbnet_stop;
-	net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
-	net->tx_timeout = usbnet_tx_timeout;
-
-	register_netdev (&dev->net);
-	devinfo (dev, "register usbnet %03d/%03d, %s",
-		udev->bus->busnum, udev->devnum,
-		dev->driver_info->description);
-
-	// ok, it's ready to go.
-	mutex_lock (&usbnet_mutex);
-	list_add (&dev->dev_list, &usbnet_list);
-	mutex_unlock (&dev->mutex);
-
-	// start as if the link is up
-	netif_device_attach (&dev->net);
-
-	mutex_unlock (&usbnet_mutex);
-	return dev;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * chip vendor names won't normally be on the cables, and
- * may not be on the device.
- */
-
-static const struct usb_device_id	products [] = {
-
-#ifdef	CONFIG_USB_AN2720
-{
-	USB_DEVICE (0x0547, 0x2720),	// AnchorChips defaults
-	driver_info:	(unsigned long) &an2720_info,
-},
-
-{
-	USB_DEVICE (0x0547, 0x2727),	// Xircom PGUNET
-	driver_info:	(unsigned long) &an2720_info,
-},
-#endif
-
-#ifdef	CONFIG_USB_BELKIN
-{
-	USB_DEVICE (0x050d, 0x0004),	// Belkin
-	driver_info:	(unsigned long) &belkin_info,
-}, {
-	USB_DEVICE (0x056c, 0x8100),	// eTEK
-	driver_info:	(unsigned long) &belkin_info,
-}, {
-	USB_DEVICE (0x0525, 0x9901),	// Advance USBNET (eTEK)
-	driver_info:	(unsigned long) &belkin_info,
-},
-#endif
-
-#ifdef	CONFIG_USB_GENESYS
-{
-	USB_DEVICE (0x05e3, 0x0502),	// GL620USB-A
-	driver_info:	(unsigned long) &genelink_info,
-},
-#endif
-
-#ifdef	CONFIG_USB_LINUXDEV
-/*
- * for example, this can be a host side talk-to-PDA driver.
- * this driver is NOT what runs _inside_ a Linux device !!
- */
-{
-	// 1183 = 0x049F, both used as hex values?
-	USB_DEVICE (0x049F, 0x505A),	// Compaq "Itsy"
-	driver_info:	(unsigned long) &linuxdev_info,
-},
-#endif
-
-#ifdef	CONFIG_USB_NET1080
-{
-	USB_DEVICE (0x0525, 0x1080),	// NetChip ref design
-	driver_info:	(unsigned long) &net1080_info,
-},
-{
-	USB_DEVICE (0x06D0, 0x0622),	// Laplink Gold
-	driver_info:	(unsigned long) &net1080_info,
-},
-#endif
-
-#ifdef CONFIG_USB_PL2301
-{
-	USB_DEVICE (0x067b, 0x0000),	// PL-2301
-	driver_info:	(unsigned long) &prolific_info,
-}, {
-	USB_DEVICE (0x067b, 0x0001),	// PL-2302
-	driver_info:	(unsigned long) &prolific_info,
-},
-#endif
-
-/* KC2190 from www.sepoong.co.kr "InstaNET" */
-
-	{ },		// END
-};
-MODULE_DEVICE_TABLE (usb, products);
-
-static struct usb_driver usbnet_driver = {
-	name:		"usbnet",
-	id_table:	products,
-	probe:		usbnet_probe,
-	disconnect:	usbnet_disconnect,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init usbnet_init (void)
-{
-	// compiler should optimize this out
-	if (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data))
-		BUG ();
-
-	get_random_bytes (node_id, sizeof node_id);
-	node_id [0] &= 0xfe;	// clear multicast bit
-
- 	if (usb_register (&usbnet_driver) < 0)
- 		return -1;
-
-	return 0;
-}
-module_init (usbnet_init);
-
-static void __exit usbnet_exit (void)
-{
- 	usb_deregister (&usbnet_driver);
-}
-module_exit (usbnet_exit);
-
-EXPORT_NO_SYMBOLS;
-MODULE_AUTHOR ("David Brownell <dbrownell@users.sourceforge.net>");
-MODULE_DESCRIPTION ("USB Host-to-Host Link Drivers (numerous vendors)");
-MODULE_LICENSE ("GPL");
diff -Nru a/drivers/usb/usbvideo.c b/drivers/usb/usbvideo.c
--- a/drivers/usb/usbvideo.c	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,2397 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#define	__NO_VERSION__		/* Temporary: usbvideo is not a module yet */
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/vmalloc.h>
-#include <linux/wrapper.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-
-#include "usbvideo.h"
-
-#if defined(MAP_NR)
-#define	virt_to_page(v)	MAP_NR(v)	/* Kernels 2.2.x */
-#endif
-
-static int video_nr = -1;
-MODULE_PARM(video_nr, "i");
-
-/*
- * Local prototypes.
- */
-#if USES_PROC_FS
-static void usbvideo_procfs_level1_create(usbvideo_t *ut);
-static void usbvideo_procfs_level1_destroy(usbvideo_t *ut);
-static void usbvideo_procfs_level2_create(uvd_t *uvd);
-static void usbvideo_procfs_level2_destroy(uvd_t *uvd);
-static int usbvideo_default_procfs_read_proc(
-	char *page, char **start, off_t off, int count,
-	int *eof, void *data);
-static int usbvideo_default_procfs_write_proc(
-	struct file *file, const char *buffer, 
-	unsigned long count, void *data);
-#endif
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-/*
- * Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-unsigned long usbvideo_kvirt_to_pa(unsigned long adr)
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-	return ret;
-}
-
-void *usbvideo_rvmalloc(unsigned long size)
-{
-	void *mem;
-	unsigned long adr;
-
-	size = PAGE_ALIGN(size);
-	mem = vmalloc_32(size);
-	if (!mem)
-		return NULL;
-
-	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-	adr = (unsigned long) mem;
-	while (size > 0) {
-		mem_map_reserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	return mem;
-}
-
-void usbvideo_rvfree(void *mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (!mem)
-		return;
-
-	adr = (unsigned long) mem;
-	while ((long) size > 0) {
-		mem_map_unreserve(vmalloc_to_page((void *)adr));
-		adr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-	vfree(mem);
-}
-
-void RingQueue_Initialize(RingQueue_t *rq)
-{
-	assert(rq != NULL);
-	init_waitqueue_head(&rq->wqh);
-}
-
-void RingQueue_Allocate(RingQueue_t *rq, int rqLen)
-{
-	assert(rq != NULL);
-	assert(rqLen > 0);
-	rq->length = rqLen;
-	rq->queue = usbvideo_rvmalloc(rq->length);
-	assert(rq->queue != NULL);
-}
-
-int RingQueue_IsAllocated(const RingQueue_t *rq)
-{
-	if (rq == NULL)
-		return 0;
-	return (rq->queue != NULL) && (rq->length > 0);
-}
-
-void RingQueue_Free(RingQueue_t *rq)
-{
-	assert(rq != NULL);
-	if (RingQueue_IsAllocated(rq)) {
-		usbvideo_rvfree(rq->queue, rq->length);
-		rq->queue = NULL;
-		rq->length = 0;
-	}
-}
-
-int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len)
-{
-	int i;
-	assert(rq != NULL);
-	assert(dst != NULL);
-	for (i=0; i < len; i++) {
-		dst[i] = rq->queue[rq->ri];
-		RING_QUEUE_DEQUEUE_BYTES(rq,1);
-	}
-	return len;
-}
-
-int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n)
-{
-	int enqueued = 0;
-
-	assert(rq != NULL);
-	assert(cdata != NULL);
-	assert(rq->length > 0);
-	while (n > 0) {
-		int m, q_avail;
-
-		/* Calculate the largest chunk that fits the tail of the ring */
-		q_avail = rq->length - rq->wi;
-		if (q_avail <= 0) {
-			rq->wi = 0;
-			q_avail = rq->length;
-		}
-		m = n;
-		assert(q_avail > 0);
-		if (m > q_avail)
-			m = q_avail;
-
-		memmove(rq->queue + rq->wi, cdata, m);
-		RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
-		cdata += m;
-		enqueued += m;
-		n -= m;
-	}
-	return enqueued;
-}
-
-int RingQueue_GetLength(const RingQueue_t *rq)
-{
-	int ri, wi;
-
-	assert(rq != NULL);
-
-	ri = rq->ri;
-	wi = rq->wi;
-	if (ri == wi)
-		return 0;
-	else if (ri < wi)
-		return wi - ri;
-	else
-		return wi + (rq->length - ri);
-}
-
-void RingQueue_InterruptibleSleepOn(RingQueue_t *rq)
-{
-	assert(rq != NULL);
-	interruptible_sleep_on(&rq->wqh);
-}
-
-void RingQueue_WakeUpInterruptible(RingQueue_t *rq)
-{
-	assert(rq != NULL);
-	if (waitqueue_active(&rq->wqh))
-		wake_up_interruptible(&rq->wqh);
-}
-
-/*
- * usbvideo_VideosizeToString()
- *
- * This procedure converts given videosize value to readable string.
- *
- * History:
- * 07-Aug-2000 Created.
- * 19-Oct-2000 Reworked for usbvideo module.
- */
-void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs)
-{
-	char tmp[40];
-	int n;
-
-	n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs));
-	assert(n < sizeof(tmp));
-	if ((buf == NULL) || (bufLen < n))
-		err("usbvideo_VideosizeToString: buffer is too small.");
-	else
-		memmove(buf, tmp, n);
-}
-
-/*
- * usbvideo_OverlayChar()
- *
- * History:
- * 01-Feb-2000 Created.
- */
-void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame,
-			  int x, int y, int ch)
-{
-	static const unsigned short digits[16] = {
-		0xF6DE, /* 0 */
-		0x2492, /* 1 */
-		0xE7CE, /* 2 */
-		0xE79E, /* 3 */
-		0xB792, /* 4 */
-		0xF39E, /* 5 */
-		0xF3DE, /* 6 */
-		0xF492, /* 7 */
-		0xF7DE, /* 8 */
-		0xF79E, /* 9 */
-		0x77DA, /* a */
-		0xD75C, /* b */
-		0xF24E, /* c */
-		0xD6DC, /* d */
-		0xF34E, /* e */
-		0xF348  /* f */
-	};
-	unsigned short digit;
-	int ix, iy;
-
-	if ((uvd == NULL) || (frame == NULL))
-		return;
-
-	if (ch >= '0' && ch <= '9')
-		ch -= '0';
-	else if (ch >= 'A' && ch <= 'F')
-		ch = 10 + (ch - 'A');
-	else if (ch >= 'a' && ch <= 'f')
-		ch = 10 + (ch - 'a');
-	else
-		return;
-	digit = digits[ch];
-
-	for (iy=0; iy < 5; iy++) {
-		for (ix=0; ix < 3; ix++) {
-			if (digit & 0x8000) {
-				if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {
-/* TODO */				RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);
-				}
-			}
-			digit = digit << 1;
-		}
-	}
-}
-
-/*
- * usbvideo_OverlayString()
- *
- * History:
- * 01-Feb-2000 Created.
- */
-void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame,
-			    int x, int y, const char *str)
-{
-	while (*str) {
-		usbvideo_OverlayChar(uvd, frame, x, y, *str);
-		str++;
-		x += 4; /* 3 pixels character + 1 space */
-	}
-}
-
-/*
- * usbvideo_OverlayStats()
- *
- * Overlays important debugging information.
- *
- * History:
- * 01-Feb-2000 Created.
- */
-void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame)
-{
-	const int y_diff = 8;
-	char tmp[16];
-	int x = 10, y=10;
-	long i, j, barLength;
-	const int qi_x1 = 60, qi_y1 = 10;
-	const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;
-
-	/* Call the user callback, see if we may proceed after that */
-	if (VALID_CALLBACK(uvd, overlayHook)) {
-		if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0)
-			return;
-	}
-
-	/*
-	 * We draw a (mostly) hollow rectangle with qi_xxx coordinates.
-	 * Left edge symbolizes the queue index 0; right edge symbolizes
-	 * the full capacity of the queue.
-	 */
-	barLength = qi_x2 - qi_x1 - 2;
-	if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) {
-/* TODO */	long u_lo, u_hi, q_used;
-		long m_ri, m_wi, m_lo, m_hi;
-
-		/*
-		 * Determine fill zones (used areas of the queue):
-		 * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length
-		 *
-		 * if u_lo < 0 then there is no first filler.
-		 */
-
-		q_used = RingQueue_GetLength(&uvd->dp);
-		if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
-			u_hi = uvd->dp.length;
-			u_lo = (q_used + uvd->dp.ri) % uvd->dp.length;
-		} else {
-			u_hi = (q_used + uvd->dp.ri);
-			u_lo = -1;
-		}
-
-		/* Convert byte indices into screen units */
-		m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length);
-		m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length);
-		m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;
-		m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);
-
-		for (j=qi_y1; j < (qi_y1 + qi_h); j++) {
-			for (i=qi_x1; i < qi_x2; i++) {
-				/* Draw border lines */
-				if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||
-				    (i == qi_x1) || (i == (qi_x2 - 1))) {
-					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF);
-					continue;
-				}
-				/* For all other points the Y coordinate does not matter */
-				if ((i >= m_ri) && (i <= (m_ri + 3))) {
-					RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);
-				} else if ((i >= m_wi) && (i <= (m_wi + 3))) {
-					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);
-				} else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
-					RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);
-			}
-		}
-	}
-
-	sprintf(tmp, "%8lx", uvd->stats.frame_num);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.urb_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.urb_length);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.data_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.header_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.iso_skip_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8lx", uvd->stats.iso_err_count);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.colour);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.hue);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.brightness >> 8);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8x", uvd->vpic.contrast >> 12);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-
-	sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8);
-	usbvideo_OverlayString(uvd, frame, x, y, tmp);
-	y += y_diff;
-}
-
-/*
- * usbvideo_ReportStatistics()
- *
- * This procedure prints packet and transfer statistics.
- *
- * History:
- * 14-Jan-2000 Corrected default multiplier.
- */
-void usbvideo_ReportStatistics(const uvd_t *uvd)
-{
-	if ((uvd != NULL) && (uvd->stats.urb_count > 0)) {
-		unsigned long allPackets, badPackets, goodPackets, percent;
-		allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES;
-		badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count;
-		goodPackets = allPackets - badPackets;
-		/* Calculate percentage wisely, remember integer limits */
-		assert(allPackets != 0);
-		if (goodPackets < (((unsigned long)-1)/100))
-			percent = (100 * goodPackets) / allPackets;
-		else
-			percent = goodPackets / (allPackets / 100);
-		info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%",
-		     allPackets, badPackets, percent);
-		if (uvd->iso_packet_len > 0) {
-			unsigned long allBytes, xferBytes;
-			char multiplier = ' ';
-			allBytes = allPackets * uvd->iso_packet_len;
-			xferBytes = uvd->stats.data_count;
-			assert(allBytes != 0);
-			if (xferBytes < (((unsigned long)-1)/100))
-				percent = (100 * xferBytes) / allBytes;
-			else
-				percent = xferBytes / (allBytes / 100);
-			/* Scale xferBytes for easy reading */
-			if (xferBytes > 10*1024) {
-				xferBytes /= 1024;
-				multiplier = 'K';
-				if (xferBytes > 10*1024) {
-					xferBytes /= 1024;
-					multiplier = 'M';
-					if (xferBytes > 10*1024) {
-						xferBytes /= 1024;
-						multiplier = 'G';
-						if (xferBytes > 10*1024) {
-							xferBytes /= 1024;
-							multiplier = 'T';
-						}
-					}
-				}
-			}
-			info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%",
-			     xferBytes, multiplier, percent);
-		}
-	}
-}
-
-/*
- * usbvideo_DrawLine()
- *
- * A standard implementation of Bresenham's line drawing algorithm.
- * This procedure is provided primarily for debugging or demo
- * purposes.
- */
-void usbvideo_DrawLine(
-	usbvideo_frame_t *frame,
-	int x1, int y1,
-	int x2, int y2,
-	unsigned char cr, unsigned char cg, unsigned char cb)
-{
-	int i, dx, dy, np, d;
-	int dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2;
-
-	if ((dx = x2 - x1) < 0)
-		dx = -dx;
-	if ((dy = y2 - y1) < 0)
-		dy = -dy;
-	if (dx >= dy) {
-		np = dx + 1;
-		d = (2 * dy) - dx;
-		dinc1 = dy << 1;
-		dinc2 = (dy - dx) << 1;
-		xinc1 = 1;
-		xinc2 = 1;
-		yinc1 = 0;
-		yinc2 = 1;
-	} else {
-		np = dy + 1;
-		d = (2 * dx) - dy;
-		dinc1 = dx << 1;
-		dinc2 = (dx - dy) << 1;
-		xinc1 = 0;
-		xinc2 = 1;
-		yinc1 = 1;
-		yinc2 = 1;
-	}
-	/* Make sure x and y move in the right directions */
-	if (x1 > x2) {
-		xinc1 = -xinc1;
-		xinc2 = -xinc2;
-	}
-	if (y1 > y2) {
-		yinc1 = -yinc1;
-		yinc2 = -yinc2;
-	}
-	for (i=0, x=x1, y=y1; i < np; i++) {
-		if (frame->palette == VIDEO_PALETTE_RGB24) {
-/* TODO */		RGB24_PUTPIXEL(frame, x, y, cr, cg, cb);
-		}
-		if (d < 0) {
-			d += dinc1;
-			x += xinc1;
-			y += yinc1;
-		} else {
-			d += dinc2;
-			x += xinc2;
-			y += yinc2;
-		}
-	}
-}
-
-/*
- * usbvideo_TestPattern()
- *
- * Procedure forms a test pattern (yellow grid on blue background).
- *
- * Parameters:
- * fullframe: if TRUE then entire frame is filled, otherwise the procedure
- *	      continues from the current scanline.
- * pmode      0: fill the frame with solid blue color (like on VCR or TV)
- *	      1: Draw a colored grid
- *
- * History:
- * 01-Feb-2000 Created.
- */
-void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode)
-{
-	static const char proc[] = "usbvideo_TestPattern";
-	usbvideo_frame_t *frame;
-	int num_cell = 0;
-	int scan_length = 0;
-	static int num_pass = 0;
-
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", proc);
-		return;
-	}
-	if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
-		err("%s: uvd->curframe=%d.", proc, uvd->curframe);
-		return;
-	}
-
-	/* Grab the current frame */
-	frame = &uvd->frame[uvd->curframe];
-
-	/* Optionally start at the beginning */
-	if (fullframe) {
-		frame->curline = 0;
-		frame->seqRead_Length = 0;
-	}
-#if 0
-	{	/* For debugging purposes only */
-		char tmp[20];
-		usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
-		info("testpattern: frame=%s", tmp);
-	}
-#endif
-	/* Form every scan line */
-	for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) {
-		int i;
-		unsigned char *f = frame->data +
-			(VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);
-		for (i=0; i < VIDEOSIZE_X(frame->request); i++) {
-			unsigned char cb=0x80;
-			unsigned char cg = 0;
-			unsigned char cr = 0;
-
-			if (pmode == 1) {
-				if (frame->curline % 32 == 0)
-					cb = 0, cg = cr = 0xFF;
-				else if (i % 32 == 0) {
-					if (frame->curline % 32 == 1)
-						num_cell++;
-					cb = 0, cg = cr = 0xFF;
-				} else {
-					cb = ((num_cell*7) + num_pass) & 0xFF;
-					cg = ((num_cell*5) + num_pass*2) & 0xFF;
-					cr = ((num_cell*3) + num_pass*3) & 0xFF;
-				}
-			} else {
-				/* Just the blue screen */
-			}
-				
-			*f++ = cb;
-			*f++ = cg;
-			*f++ = cr;
-			scan_length += 3;
-		}
-	}
-
-	frame->frameState = FrameState_Done;
-	frame->seqRead_Length += scan_length;
-	++num_pass;
-
-	/* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */
-	usbvideo_OverlayStats(uvd, frame);
-}
-
-/*
- * usbvideo_HexDump()
- *
- * A debugging tool. Prints hex dumps.
- *
- * History:
- * 29-Jul-2000 Added printing of offsets.
- */
-void usbvideo_HexDump(const unsigned char *data, int len)
-{
-	const int bytes_per_line = 32;
-	char tmp[128]; /* 32*3 + 5 */
-	int i, k;
-
-	for (i=k=0; len > 0; i++, len--) {
-		if (i > 0 && ((i % bytes_per_line) == 0)) {
-			printk("%s\n", tmp);
-			k=0;
-		}
-		if ((i % bytes_per_line) == 0)
-			k += sprintf(&tmp[k], "%04x: ", i);
-		k += sprintf(&tmp[k], "%02x ", data[i]);
-	}
-	if (k > 0)
-		printk("%s\n", tmp);
-}
-
-/* Debugging aid */
-void usbvideo_SayAndWait(const char *what)
-{
-	wait_queue_head_t wq;
-	init_waitqueue_head(&wq);
-	info("Say: %s", what);
-	interruptible_sleep_on_timeout (&wq, HZ*3); /* Timeout */
-}
-
-/* ******************************************************************** */
-
-static void usbvideo_ClientIncModCount(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_ClientIncModCount";
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", proc);
-		return;
-	}
-	if (uvd->handle == NULL) {
-		err("%s: uvd->handle == NULL", proc);
-		return;
-	}
-	if (uvd->handle->md_module == NULL) {
-		err("%s: uvd->handle->md_module == NULL", proc);
-		return;
-	}
-	__MOD_INC_USE_COUNT(uvd->handle->md_module);
-}
-
-static void usbvideo_ClientDecModCount(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_ClientDecModCount";
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", proc);
-		return;
-	}
-	if (uvd->handle == NULL) {
-		err("%s: uvd->handle == NULL", proc);
-		return;
-	}
-	if (uvd->handle->md_module == NULL) {
-		err("%s: uvd->handle->md_module == NULL", proc);
-		return;
-	}
-	__MOD_DEC_USE_COUNT(uvd->handle->md_module);
-}
-
-int usbvideo_register(
-	usbvideo_t **pCams,
-	const int num_cams,
-	const int num_extra,
-	const char *driverName,
-	const usbvideo_cb_t *cbTbl,
-	struct module *md )
-{
-	static const char proc[] = "usbvideo_register";
-	usbvideo_t *cams;
-	int i, base_size;
-
-	/* Check parameters for sanity */
-	if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
-		err("%s: Illegal call", proc);
-		return -EINVAL;
-	}
-
-	/* Check registration callback - must be set! */
-	if (cbTbl->probe == NULL) {
-		err("%s: probe() is required!", proc);
-		return -EINVAL;
-	}
-
-	base_size = num_cams * sizeof(uvd_t) + sizeof(usbvideo_t);
-	cams = (usbvideo_t *) kmalloc(base_size, GFP_KERNEL);
-	if (cams == NULL) {
-		err("Failed to allocate %d. bytes for usbvideo_t", base_size);
-		return -ENOMEM;
-	}
-	dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
-	    proc, cams, base_size, num_cams);
-	memset(cams, 0, base_size);
-
-	/* Copy callbacks, apply defaults for those that are not set */
-	memmove(&cams->cb, cbTbl, sizeof(cams->cb));
-	if (cams->cb.getFrame == NULL)
-		cams->cb.getFrame = usbvideo_GetFrame;
-	if (cams->cb.disconnect == NULL)
-		cams->cb.disconnect = usbvideo_Disconnect;
-	if (cams->cb.startDataPump == NULL)
-		cams->cb.startDataPump = usbvideo_StartDataPump;
-	if (cams->cb.stopDataPump == NULL)
-		cams->cb.stopDataPump = usbvideo_StopDataPump;
-#if USES_PROC_FS
-	/*
-	 * If both /proc fs callbacks are NULL then we assume that the driver
-	 * does not need procfs services at all. Leave them NULL.
-	 */
-	cams->uses_procfs = (cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL);
-	if (cams->uses_procfs) {
-		if (cams->cb.procfs_read == NULL)
-			cams->cb.procfs_read = usbvideo_default_procfs_read_proc;
-		if (cams->cb.procfs_write == NULL)
-			cams->cb.procfs_write = usbvideo_default_procfs_write_proc;
-	}
-#else /* !USES_PROC_FS */
-	/* Report a warning so that user knows why there is no /proc entries */
-	if ((cams->cb.procfs_read != NULL) || (cams->cb.procfs_write == NULL)) {
-		dbg("%s: /proc fs support requested but not configured!", proc);
-	}
-#endif
-	cams->num_cameras = num_cams;
-	cams->cam = (uvd_t *) &cams[1];
-	cams->md_module = md;
-	if (cams->md_module == NULL)
-		warn("%s: module == NULL!", proc);
-	init_MUTEX(&cams->lock);	/* to 1 == available */
-
-	for (i = 0; i < num_cams; i++) {
-		uvd_t *up = &cams->cam[i];
-
-		up->handle = cams;
-
-		/* Allocate user_data separately because of kmalloc's limits */
-		if (num_extra > 0) {
-			up->user_size = num_cams * num_extra;
-			up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL);
-			if (up->user_data == NULL) {
-				up->user_size = 0;
-				err("%s: Failed to allocate user_data (%d. bytes)",
-				    proc, up->user_size);
-				return -ENOMEM;
-			}
-			dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
-			     proc, i, up->user_data, up->user_size);
-		}
-	}
-
-	/*
-	 * Register ourselves with USB stack.
-	 */
-	strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown");
-	cams->usbdrv.name = cams->drvName;
-	cams->usbdrv.probe = cams->cb.probe;
-	cams->usbdrv.disconnect = cams->cb.disconnect;
-
-#if USES_PROC_FS
-	if (cams->uses_procfs) {
-		dbg("%s: Creating /proc filesystem entries.", proc);
-		usbvideo_procfs_level1_create(cams);
-	}
-#endif
-
-	/*
-	 * Update global handle to usbvideo. This is very important
-	 * because probe() can be called before usb_register() returns.
-	 * If the handle is not yet updated then the probe() will fail.
-	 */
-	*pCams = cams;
-	usb_register(&cams->usbdrv);
-
-	return 0;
-}
-
-/*
- * usbvideo_Deregister()
- *
- * Procedure frees all usbvideo and user data structures. Be warned that
- * if you had some dynamically allocated components in ->user field then
- * you should free them before calling here.
- */
-void usbvideo_Deregister(usbvideo_t **pCams)
-{
-	static const char proc[] = "usbvideo_deregister";
-	usbvideo_t *cams;
-	int i;
-
-	if (pCams == NULL) {
-		err("%s: pCams == NULL", proc);
-		return;
-	}
-	cams = *pCams;
-	if (cams == NULL) {
-		err("%s: cams == NULL", proc);
-		return;
-	}
-
-#if USES_PROC_FS
-	if (cams->uses_procfs) {
-		dbg("%s: Deregistering filesystem entries.", proc);
-		usbvideo_procfs_level1_destroy(cams);
-	}
-#endif
-
-	dbg("%s: Deregistering %s driver.", proc, cams->drvName);
-	usb_deregister(&cams->usbdrv);
-
-	dbg("%s: Deallocating cams=$%p (%d. cameras)", proc, cams, cams->num_cameras);
-	for (i=0; i < cams->num_cameras; i++) {
-		uvd_t *up = &cams->cam[i];
-		int warning = 0;
-
-		if (up->user_data != NULL) {
-			if (up->user_size <= 0)
-				++warning;
-		} else {
-			if (up->user_size > 0)
-				++warning;
-		}
-		if (warning) {
-			err("%s: Warning: user_data=$%p user_size=%d.",
-			    proc, up->user_data, up->user_size);
-		} else {
-			dbg("%s: Freeing %d. $%p->user_data=$%p",
-			    proc, i, up, up->user_data);
-			kfree(up->user_data);
-		}
-	}
-	/* Whole array was allocated in one chunk */
-	dbg("%s: Freed %d uvd_t structures",
-	    proc, cams->num_cameras);
-	kfree(cams);
-	*pCams = NULL;
-}
-
-/*
- * usbvideo_Disconnect()
- *
- * This procedure stops all driver activity. Deallocation of
- * the interface-private structure (pointed by 'ptr') is done now
- * (if we don't have any open files) or later, when those files
- * are closed. After that driver should be removable.
- *
- * This code handles surprise removal. The uvd->user is a counter which
- * increments on open() and decrements on close(). If we see here that
- * this counter is not 0 then we have a client who still has us opened.
- * We set uvd->remove_pending flag as early as possible, and after that
- * all access to the camera will gracefully fail. These failures should
- * prompt client to (eventually) close the video device, and then - in
- * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter.
- *
- * History:
- * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone.
- * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close()
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- * 19-Oct-2000 Moved to usbvideo module.
- */
-void usbvideo_Disconnect(struct usb_device *dev, void *ptr)
-{
-	static const char proc[] = "usbvideo_Disconnect";
-	uvd_t *uvd = (uvd_t *) ptr;
-	int i;
-
-	if ((dev == NULL) || (uvd == NULL)) {
-		err("%s($%p,$%p): Illegal call.", proc, dev, ptr);
-		return;
-	}
-	usbvideo_ClientIncModCount(uvd);
-	if (uvd->debug > 0)
-		info("%s(%p,%p.)", proc, dev, ptr);
-
-	down(&uvd->lock);
-	uvd->remove_pending = 1; /* Now all ISO data will be ignored */
-
-	/* At this time we ask to cancel outstanding URBs */
-	GET_CALLBACK(uvd, stopDataPump)(uvd);
-
-	for (i=0; i < USBVIDEO_NUMSBUF; i++)
-		usb_free_urb(uvd->sbuf[i].urb);
-
-	usb_dec_dev_use(uvd->dev);
-	uvd->dev = NULL;    	    /* USB device is no more */
-
-	video_unregister_device(&uvd->vdev);
-	if (uvd->debug > 0)
-		info("%s: Video unregistered.", proc);
-
-	if (uvd->user)
-		info("%s: In use, disconnect pending.", proc);
-	else
-		usbvideo_CameraRelease(uvd);
-	up(&uvd->lock);
-	info("USB camera disconnected.");
-
-	usbvideo_ClientDecModCount(uvd);
-}
-
-/*
- * usbvideo_CameraRelease()
- *
- * This code does final release of uvd_t. This happens
- * after the device is disconnected -and- all clients
- * closed their files.
- *
- * History:
- * 27-Jan-2000 Created.
- */
-void usbvideo_CameraRelease(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_CameraRelease";
-	if (uvd == NULL) {
-		err("%s: Illegal call", proc);
-		return;
-	}
-
-#if USES_PROC_FS
-	assert(uvd->handle != NULL);
-	if (uvd->handle->uses_procfs) {
-		dbg("%s: Removing /proc/%s/ filesystem entries.", proc, uvd->handle->drvName);
-		usbvideo_procfs_level2_destroy(uvd);
-	}
-#endif
-
-	RingQueue_Free(&uvd->dp);
-	if (VALID_CALLBACK(uvd, userFree))
-		GET_CALLBACK(uvd, userFree)(uvd);
-	uvd->uvd_used = 0;	/* This is atomic, no need to take mutex */
-}
-
-/*
- * usbvideo_find_struct()
- *
- * This code searches the array of preallocated (static) structures
- * and returns index of the first one that isn't in use. Returns -1
- * if there are no free structures.
- *
- * History:
- * 27-Jan-2000 Created.
- */
-static int usbvideo_find_struct(usbvideo_t *cams)
-{
-	int u, rv = -1;
-
-	if (cams == NULL) {
-		err("No usbvideo_t handle?");
-		return -1;
-	}
-	down(&cams->lock);
-	for (u = 0; u < cams->num_cameras; u++) {
-		uvd_t *uvd = &cams->cam[u];
-		if (!uvd->uvd_used) /* This one is free */
-		{
-			uvd->uvd_used = 1;	/* In use now */
-			init_MUTEX(&uvd->lock);	/* to 1 == available */
-			uvd->dev = NULL;
-			rv = u;
-			break;
-		}
-	}
-	up(&cams->lock);
-	return rv;
-}
-
-static struct file_operations usbvideo_fops = {
-	owner:	  THIS_MODULE,
-	open:     usbvideo_v4l_open,
-	release:  usbvideo_v4l_close,
-	read:     usbvideo_v4l_read,
-	mmap:     usbvideo_v4l_mmap,
-	ioctl:    video_generic_ioctl,
-	llseek:   no_llseek,
-};
-static struct video_device usbvideo_template = {
-	owner:	      THIS_MODULE,
-	type:         VID_TYPE_CAPTURE,
-	hardware:     VID_HARDWARE_CPIA,
-	fops:         &usbvideo_fops,
-	kernel_ioctl: usbvideo_v4l_ioctl,
-};
-
-uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams)
-{
-	int i, devnum;
-	uvd_t *uvd = NULL;
-
-	if (cams == NULL) {
-		err("No usbvideo_t handle?");
-		return NULL;
-	}
-
-	devnum = usbvideo_find_struct(cams);
-	if (devnum == -1) {
-		err("IBM USB camera driver: Too many devices!");
-		return NULL;
-	}
-	uvd = &cams->cam[devnum];
-	dbg("Device entry #%d. at $%p", devnum, uvd);
-
-	/* Not relying upon caller we increase module counter ourselves */
-	usbvideo_ClientIncModCount(uvd);
-
-	down(&uvd->lock);
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-		if (uvd->sbuf[i].urb == NULL) {
-			err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);
-			uvd->uvd_used = 0;
-			uvd = NULL;
-			goto allocate_done;
-		}
-	}
-	uvd->user=0;
-	uvd->remove_pending = 0;
-	uvd->last_error = 0;
-	RingQueue_Initialize(&uvd->dp);
-
-	/* Initialize video device structure */
-	uvd->vdev = usbvideo_template;
-	sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName);
-	/*
-	 * The client is free to overwrite those because we
-	 * return control to the client's probe function right now.
-	 */
-allocate_done:
-	up (&uvd->lock);
-	usbvideo_ClientDecModCount(uvd);
-	return uvd;
-}
-
-int usbvideo_RegisterVideoDevice(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_RegisterVideoDevice";
-	char tmp1[20], tmp2[20];	/* Buffers for printing */
-
-	if (uvd == NULL) {
-		err("%s: Illegal call.", proc);
-		return -EINVAL;
-	}
-	if (uvd->video_endp == 0) {
-		info("%s: No video endpoint specified; data pump disabled.", proc);
-	}
-	if (uvd->paletteBits == 0) {
-		err("%s: No palettes specified!", proc);
-		return -EINVAL;
-	}
-	if (uvd->defaultPalette == 0) {
-		info("%s: No default palette!", proc);
-	}
-
-	uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
-		VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL;
-	usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize);
-	usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
-
-	if (uvd->debug > 0) {
-		info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
-		     proc, uvd->iface, uvd->video_endp, uvd->paletteBits);
-	}
-	if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
-		err("%s: video_register_device failed", proc);
-		return -EPIPE;
-	}
-	if (uvd->debug > 1) {
-		info("%s: video_register_device() successful", proc);
-	}
-	if (uvd->dev == NULL) {
-		err("%s: uvd->dev == NULL", proc);
-		return -EINVAL;
-	}
-
-	info("%s on /dev/video%d: canvas=%s videosize=%s",
-	     (uvd->handle != NULL) ? uvd->handle->drvName : "???",
-	     uvd->vdev.minor, tmp2, tmp1);
-
-#if USES_PROC_FS
-	assert(uvd->handle != NULL);
-	if (uvd->handle->uses_procfs) {
-		if (uvd->debug > 0) {
-			info("%s: Creating /proc/video/%s/ filesystem entries.",
-			     proc, uvd->handle->drvName);
-		}
-		usbvideo_procfs_level2_create(uvd);
-	}
-#endif
-
-	usb_inc_dev_use(uvd->dev);
-	return 0;
-}
-
-/* ******************************************************************** */
-
-int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	uvd_t *uvd = file->private_data;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return -EFAULT;
-
-	if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
-		return -EINVAL;
-
-	pos = (unsigned long) uvd->fbuf;
-	while (size > 0) {
-		page = usbvideo_kvirt_to_pa(pos);
-		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
-			return -EAGAIN;
-
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-
-	return 0;
-}
-
-/*
- * usbvideo_v4l_open()
- *
- * This is part of Video 4 Linux API. The driver can be opened by one
- * client only (checks internal counter 'uvdser'). The procedure
- * then allocates buffers needed for video processing.
- *
- * History:
- * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the
- *             camera is also initialized here (once per connect), at
- *             expense of V4L client (it waits on open() call).
- * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
- * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
- */
-int usbvideo_v4l_open(struct inode *inode, struct file *file)
-{
-	static const char proc[] = "usbvideo_v4l_open";
-	struct video_device *dev = video_devdata(file);
-	uvd_t *uvd = (uvd_t *) dev;
-	const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len;
-	int i, errCode = 0;
-
-	if (uvd->debug > 1)
-		info("%s($%p", proc, dev);
-
-	usbvideo_ClientIncModCount(uvd);
-	down(&uvd->lock);
-
-	if (uvd->user) {
-		err("%s: Someone tried to open an already opened device!", proc);
-		errCode = -EBUSY;
-	} else {
-		/* Clear statistics */
-		memset(&uvd->stats, 0, sizeof(uvd->stats));
-
-		/* Clean pointers so we know if we allocated something */
-		for (i=0; i < USBVIDEO_NUMSBUF; i++)
-			uvd->sbuf[i].data = NULL;
-
-		/* Allocate memory for the frame buffers */
-		uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
-		uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
-		RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */
-		if ((uvd->fbuf == NULL) ||
-		    (!RingQueue_IsAllocated(&uvd->dp))) {
-			err("%s: Failed to allocate fbuf or dp", proc);
-			errCode = -ENOMEM;
-		} else {
-			/* Allocate all buffers */
-			for (i=0; i < USBVIDEO_NUMFRAMES; i++) {
-				uvd->frame[i].frameState = FrameState_Unused;
-				uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);
-				/*
-				 * Set default sizes in case IOCTL (VIDIOCMCAPTURE)
-				 * is not used (using read() instead).
-				 */
-				uvd->frame[i].canvas = uvd->canvas;
-				uvd->frame[i].seqRead_Index = 0;
-			}
-			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-				uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
-				if (uvd->sbuf[i].data == NULL) {
-					errCode = -ENOMEM;
-					break;
-				}
-			}
-		}
-		if (errCode != 0) {
-			/* Have to free all that memory */
-			if (uvd->fbuf != NULL) {
-				usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
-				uvd->fbuf = NULL;
-			}
-			RingQueue_Free(&uvd->dp);
-			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-				if (uvd->sbuf[i].data != NULL) {
-					kfree (uvd->sbuf[i].data);
-					uvd->sbuf[i].data = NULL;
-				}
-			}
-		}
-	}
-
-	/* If so far no errors then we shall start the camera */
-	if (errCode == 0) {
-		/* Start data pump if we have valid endpoint */
-		if (uvd->video_endp != 0)
-			errCode = GET_CALLBACK(uvd, startDataPump)(uvd);
-		if (errCode == 0) {
-			if (VALID_CALLBACK(uvd, setupOnOpen)) {
-				if (uvd->debug > 1)
-					info("%s: setupOnOpen callback", proc);
-				errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
-				if (errCode < 0) {
-					err("%s: setupOnOpen callback failed (%d.).",
-					    proc, errCode);
-				} else if (uvd->debug > 1) {
-					info("%s: setupOnOpen callback successful", proc);
-				}
-			}
-			if (errCode == 0) {
-				uvd->settingsAdjusted = 0;
-				if (uvd->debug > 1)
-					info("%s: Open succeeded.", proc);
-				uvd->user++;
-				file->private_data = uvd;
-			}
-		}
-	}
-	up(&uvd->lock);
-	if (errCode != 0)
-		usbvideo_ClientDecModCount(uvd);
-	if (uvd->debug > 0)
-		info("%s: Returning %d.", proc, errCode);
-	return errCode;
-}
-
-/*
- * usbvideo_v4l_close()
- *
- * This is part of Video 4 Linux API. The procedure
- * stops streaming and deallocates all buffers that were earlier
- * allocated in usbvideo_v4l_open().
- *
- * History:
- * 22-Jan-2000 Moved scratch buffer deallocation here.
- * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
- * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
- */
-int usbvideo_v4l_close(struct inode *inode, struct file *file)
-{
-	static const char proc[] = "usbvideo_v4l_close";
-	struct video_device *dev = file->private_data;
-	uvd_t *uvd = (uvd_t *) dev;
-	int i;
-
-	if (uvd->debug > 1)
-		info("%s($%p)", proc, dev);
-
-	down(&uvd->lock);
-	GET_CALLBACK(uvd, stopDataPump)(uvd);
-	usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
-	uvd->fbuf = NULL;
-	RingQueue_Free(&uvd->dp);
-
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		kfree(uvd->sbuf[i].data);
-		uvd->sbuf[i].data = NULL;
-	}
-
-#if USBVIDEO_REPORT_STATS
-	usbvideo_ReportStatistics(uvd);
-#endif    
-
-	uvd->user--;
-	if (uvd->remove_pending) {
-		if (uvd->debug > 0)
-			info("usbvideo_v4l_close: Final disconnect.");
-		usbvideo_CameraRelease(uvd);
-	}
-	up(&uvd->lock);
-	usbvideo_ClientDecModCount(uvd);
-
-	if (uvd->debug > 1)
-		info("%s: Completed.", proc);
-	file->private_data = NULL;
-	return 0;
-}
-
-/*
- * usbvideo_v4l_ioctl()
- *
- * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
- *
- * History:
- * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
- */
-int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
-{
-	uvd_t *uvd = file->private_data;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return -EIO;
-
-	switch (cmd) {
-		case VIDIOCGCAP:
-		{
-			struct video_capability *b = arg;
-			*b = uvd->vcap;
-			return 0;
-		}
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-			*v = uvd->vchan;
-			return 0;
-		}
-		case VIDIOCSCHAN:
-		{	
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-		case VIDIOCGPICT:
-		{
-			struct video_picture *pic = arg;
-			*pic = uvd->vpic;
-			return 0;
-		}
-		case VIDIOCSPICT:
-		{
-			struct video_picture *pic = arg;
-			/*
-			 * Use temporary 'video_picture' structure to preserve our
-			 * own settings (such as color depth, palette) that we
-			 * aren't allowing everyone (V4L client) to change.
-			 */
-			uvd->vpic.brightness = pic->brightness;
-			uvd->vpic.hue = pic->hue;
-			uvd->vpic.colour = pic->colour;
-			uvd->vpic.contrast = pic->contrast;
-			uvd->settingsAdjusted = 0;	/* Will force new settings */
-			return 0;
-		}
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-
-			if (vw->flags)
-				return -EINVAL;
-			if (vw->clipcount)
-				return -EINVAL;
-			if (vw->width != VIDEOSIZE_X(uvd->canvas))
-				return -EINVAL;
-			if (vw->height != VIDEOSIZE_Y(uvd->canvas))
-				return -EINVAL;
-
-			return 0;
-		}
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-
-			vw->x = 0;
-			vw->y = 0;
-			vw->width = VIDEOSIZE_X(uvd->canvas);
-			vw->height = VIDEOSIZE_Y(uvd->canvas);
-			vw->chromakey = 0;
-			if (VALID_CALLBACK(uvd, getFPS))
-				vw->flags = GET_CALLBACK(uvd, getFPS)(uvd);
-			else 
-				vw->flags = 10; /* FIXME: do better! */
-			return 0;
-		}
-		case VIDIOCGMBUF:
-		{
-			struct video_mbuf *vm = arg;
-
-			memset(vm, 0, sizeof(*vm));
-			vm->size = uvd->max_frame_size * 2;
-			vm->frames = 2;
-			vm->offsets[0] = 0;
-			vm->offsets[1] = uvd->max_frame_size;
-			return 0;
-		}
-		case VIDIOCMCAPTURE:
-		{
-			struct video_mmap *vm = arg;
-
-			if (uvd->debug >= 1) {
-				info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.",
-				     vm->frame, vm->width, vm->height, vm->format);
-			}
-			/*
-			 * Check if the requested size is supported. If the requestor
-			 * requests too big a frame then we may be tricked into accessing
-			 * outside of own preallocated frame buffer (in uvd->frame).
-			 * This will cause oops or a security hole. Theoretically, we
-			 * could only clamp the size down to acceptable bounds, but then
-			 * we'd need to figure out how to insert our smaller buffer into
-			 * larger caller's buffer... this is not an easy question. So we
-			 * here just flatly reject too large requests, assuming that the
-			 * caller will resubmit with smaller size. Callers should know
-			 * what size we support (returned by VIDIOCGCAP). However vidcat,
-			 * for one, does not care and allows to ask for any size.
-			 */
-			if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
-			    (vm->height > VIDEOSIZE_Y(uvd->canvas))) {
-				if (uvd->debug > 0) {
-					info("VIDIOCMCAPTURE: Size=%dx%d too large; "
-					     "allowed only up to %ldx%ld", vm->width, vm->height,
-					     VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas));
-				}
-				return -EINVAL;
-			}
-			/* Check if the palette is supported */
-			if (((1L << vm->format) & uvd->paletteBits) == 0) {
-				if (uvd->debug > 0) {
-					info("VIDIOCMCAPTURE: format=%d. not supported"
-					     " (paletteBits=$%08lx)",
-					     vm->format, uvd->paletteBits);
-				}
-				return -EINVAL;
-			}
-			if ((vm->frame != 0) && (vm->frame != 1)) {
-				err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm->frame);
-				return -EINVAL;
-			}
-			if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) {
-				/* Not an error - can happen */
-			}
-			uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height);
-			uvd->frame[vm->frame].palette = vm->format;
-
-			/* Mark it as ready */
-			uvd->frame[vm->frame].frameState = FrameState_Ready;
-
-			return usbvideo_NewFrame(uvd, vm->frame);
-		}
-		case VIDIOCSYNC:
-		{
-			int *frameNum = arg;
-			int ret;
-
-			if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES)
-				return -EINVAL;
-				
-			if (uvd->debug >= 1)
-				info("VIDIOCSYNC: syncing to frame %d.", *frameNum);
-			if (uvd->flags & FLAGS_NO_DECODING)
-				ret = usbvideo_GetFrame(uvd, *frameNum);
-			else if (VALID_CALLBACK(uvd, getFrame)) {
-				ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum);
-				if ((ret < 0) && (uvd->debug >= 1)) {
-					err("VIDIOCSYNC: getFrame() returned %d.", ret);
-				}
-			} else {
-				err("VIDIOCSYNC: getFrame is not set");
-				ret = -EFAULT;
-			}
-
-			/*
-			 * The frame is in FrameState_Done_Hold state. Release it
-			 * right now because its data is already mapped into
-			 * the user space and it's up to the application to
-			 * make use of it until it asks for another frame.
-			 */
-			uvd->frame[*frameNum].frameState = FrameState_Unused;
-			return ret;
-		}
-		case VIDIOCGFBUF:
-		{
-			struct video_buffer *vb = arg;
-
-			memset(vb, 0, sizeof(*vb));
- 			return 0;
- 		}
-		case VIDIOCKEY:
-			return 0;
-
-		case VIDIOCCAPTURE:
-			return -EINVAL;
-
-		case VIDIOCSFBUF:
-
-		case VIDIOCGTUNER:
-		case VIDIOCSTUNER:
-
-		case VIDIOCGFREQ:
-		case VIDIOCSFREQ:
-
-		case VIDIOCGAUDIO:
-		case VIDIOCSAUDIO:
-			return -EINVAL;
-
-		default:
-			return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-/*
- * usbvideo_v4l_read()
- *
- * This is mostly boring stuff. We simply ask for a frame and when it
- * arrives copy all the video data from it into user space. There is
- * no obvious need to override this method.
- *
- * History:
- * 20-Oct-2000 Created.
- * 01-Nov-2000 Added mutex (uvd->lock).
- */
-int usbvideo_v4l_read(struct file *file, char *buf,
-		      size_t count, loff_t *ppos)
-{
-	static const char proc[] = "usbvideo_v4l_read";
-	uvd_t *uvd = file->private_data;
-	int noblock = file->f_flags & O_NONBLOCK;
-	int frmx = -1;
-	usbvideo_frame_t *frame;
-
-	if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
-		return -EFAULT;
-
-	if (uvd->debug >= 1)
-		info("%s: %d. bytes, noblock=%d.", proc, count, noblock);
-
-	down(&uvd->lock);	
-
-	/* See if a frame is completed, then use it. */
-	if ((uvd->frame[0].frameState == FrameState_Done) ||
-	    (uvd->frame[0].frameState == FrameState_Done_Hold) ||
-	    (uvd->frame[0].frameState == FrameState_Error)) {
-		frmx = 0;
-	} else if ((uvd->frame[1].frameState >= FrameState_Done) ||
-		   (uvd->frame[1].frameState == FrameState_Done_Hold) ||
-		   (uvd->frame[1].frameState >= FrameState_Done)) {
-		frmx = 1;
-	}
-
-	/* FIXME: If we don't start a frame here then who ever does? */
-	if (noblock && (frmx == -1)) {
-		count = -EAGAIN;
-		goto read_done;
-	}
-
-	/*
-	 * If no FrameState_Done, look for a FrameState_Grabbing state.
-	 * See if a frame is in process (grabbing), then use it.
-	 * We will need to wait until it becomes cooked, of course.
-	 */
-	if (frmx == -1) {
-		if (uvd->frame[0].frameState == FrameState_Grabbing)
-			frmx = 0;
-		else if (uvd->frame[1].frameState == FrameState_Grabbing)
-			frmx = 1;
-	}
-
-	/*
-	 * If no frame is active, start one. We don't care which one
-	 * it will be, so #0 is as good as any.
-	 * In read access mode we don't have convenience of VIDIOCMCAPTURE
-	 * to specify the requested palette (video format) on per-frame
-	 * basis. This means that we have to return data in -some- format
-	 * and just hope that the client knows what to do with it.
-	 * The default format is configured in uvd->defaultPalette field
-	 * as one of VIDEO_PALETTE_xxx values. We stuff it into the new
-	 * frame and initiate the frame filling process.
-	 */
-	if (frmx == -1) {
-		if (uvd->defaultPalette == 0) {
-			err("%s: No default palette; don't know what to do!", proc);
-			count = -EFAULT;
-			goto read_done;
-		}
-		frmx = 0;
-		/*
-		 * We have no per-frame control over video size.
-		 * Therefore we only can use whatever size was
-		 * specified as default.
-		 */
-		uvd->frame[frmx].request = uvd->videosize;
-		uvd->frame[frmx].palette = uvd->defaultPalette;
-		uvd->frame[frmx].frameState = FrameState_Ready;
-		usbvideo_NewFrame(uvd, frmx);
-		/* Now frame 0 is supposed to start filling... */
-	}
-
-	/*
-	 * Get a pointer to the active frame. It is either previously
-	 * completed frame or frame in progress but not completed yet.
-	 */
-	frame = &uvd->frame[frmx];
-
-	/*
-	 * Sit back & wait until the frame gets filled and postprocessed.
-	 * If we fail to get the picture [in time] then return the error.
-	 * In this call we specify that we want the frame to be waited for,
-	 * postprocessed and switched into FrameState_Done_Hold state. This
-	 * state is used to hold the frame as "fully completed" between
-	 * subsequent partial reads of the same frame.
-	 */
-	if (frame->frameState != FrameState_Done_Hold) {
-		long rv = -EFAULT;
-		if (uvd->flags & FLAGS_NO_DECODING)
-			rv = usbvideo_GetFrame(uvd, frmx);
-		else if (VALID_CALLBACK(uvd, getFrame))
-			rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx);
-		else
-			err("getFrame is not set");
-		if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) {
-			count = rv;
-			goto read_done;
-		}
-	}
-
-	/*
-	 * Copy bytes to user space. We allow for partial reads, which
-	 * means that the user application can request read less than
-	 * the full frame size. It is up to the application to issue
-	 * subsequent calls until entire frame is read.
-	 *
-	 * First things first, make sure we don't copy more than we
-	 * have - even if the application wants more. That would be
-	 * a big security embarassment!
-	 */
-	if ((count + frame->seqRead_Index) > frame->seqRead_Length)
-		count = frame->seqRead_Length - frame->seqRead_Index;
-
-	/*
-	 * Copy requested amount of data to user space. We start
-	 * copying from the position where we last left it, which
-	 * will be zero for a new frame (not read before).
-	 */
-	if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) {
-		count = -EFAULT;
-		goto read_done;
-	}
-
-	/* Update last read position */
-	frame->seqRead_Index += count;
-	if (uvd->debug >= 1) {
-		err("%s: {copy} count used=%d, new seqRead_Index=%ld",
-			proc, count, frame->seqRead_Index);
-	}
-
-	/* Finally check if the frame is done with and "release" it */
-	if (frame->seqRead_Index >= frame->seqRead_Length) {
-		/* All data has been read */
-		frame->seqRead_Index = 0;
-
-		/* Mark it as available to be used again. */
-		uvd->frame[frmx].frameState = FrameState_Unused;
-		if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) {
-			err("%s: usbvideo_NewFrame failed.", proc);
-		}
-	}
-read_done:
-	up(&uvd->lock);	
-	return count;
-}
-
-/*
- * Make all of the blocks of data contiguous
- */
-static int usbvideo_CompressIsochronous(uvd_t *uvd, struct urb *urb)
-{
-	char *cdata;
-	int i, totlen = 0;
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		int n = urb->iso_frame_desc[i].actual_length;
-		int st = urb->iso_frame_desc[i].status;
-
-		cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-		/* Detect and ignore errored packets */
-		if (st < 0) {
-			if (uvd->debug >= 1)
-				err("Data error: packet=%d. len=%d. status=%d.", i, n, st);
-			uvd->stats.iso_err_count++;
-			continue;
-		}
-
-		/* Detect and ignore empty packets */
-		if (n <= 0) {
-			uvd->stats.iso_skip_count++;
-			continue;
-		}
-		totlen += n;	/* Little local accounting */
-		RingQueue_Enqueue(&uvd->dp, cdata, n);
-	}
-	return totlen;
-}
-
-static void usbvideo_IsocIrq(struct urb *urb)
-{
-	int i, len;
-	uvd_t *uvd = urb->context;
-
-	/* We don't want to do anything if we are about to be removed! */
-	if (!CAMERA_IS_OPERATIONAL(uvd))
-		return;
-#if 0
-	if (urb->actual_length > 0) {
-		info("urb=$%p status=%d. errcount=%d. length=%d.",
-		     urb, urb->status, urb->error_count, urb->actual_length);
-	} else {
-		static int c = 0;
-		if (c++ % 100 == 0)
-			info("No Isoc data");
-	}
-#endif
-
-	if (!uvd->streaming) {
-		if (uvd->debug >= 1)
-			info("Not streaming, but interrupt!");
-		return;
-	}
-	
-	uvd->stats.urb_count++;
-	if (urb->actual_length <= 0)
-		goto urb_done_with;
-
-	/* Copy the data received into ring queue */
-	len = usbvideo_CompressIsochronous(uvd, urb);
-	uvd->stats.urb_length = len;
-	if (len <= 0)
-		goto urb_done_with;
-
-	/* Here we got some data */
-	uvd->stats.data_count += len;
-	RingQueue_WakeUpInterruptible(&uvd->dp);
-
-urb_done_with:
-	for (i = 0; i < FRAMES_PER_DESC; i++) {
-		urb->iso_frame_desc[i].status = 0;
-		urb->iso_frame_desc[i].actual_length = 0;
-	}
-	return;
-}
-
-/*
- * usbvideo_StartDataPump()
- *
- * History:
- * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead
- *             of hardcoded values. Simplified by using for loop,
- *             allowed any number of URBs.
- */
-int usbvideo_StartDataPump(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_StartDataPump";
-	struct usb_device *dev = uvd->dev;
-	int i, errFlag;
-
-	if (uvd->debug > 1)
-		info("%s($%p)", proc, uvd);
-
-	if (!CAMERA_IS_OPERATIONAL(uvd)) {
-		err("%s: Camera is not operational",proc);
-		return -EFAULT;
-	}
-	uvd->curframe = -1;
-
-	/* Alternate interface 1 is is the biggest frame size */
-	i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
-	if (i < 0) {
-		err("%s: usb_set_interface error", proc);
-		uvd->last_error = i;
-		return -EBUSY;
-	}
-	if (VALID_CALLBACK(uvd, videoStart))
-		GET_CALLBACK(uvd, videoStart)(uvd);
-	else 
-		err("%s: videoStart not set", proc);
-
-	/* We double buffer the Iso lists */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		int j, k;
-		struct urb *urb = uvd->sbuf[i].urb;
-		urb->dev = dev;
-		urb->context = uvd;
-		urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
-		urb->transfer_flags = USB_ISO_ASAP;
-		urb->transfer_buffer = uvd->sbuf[i].data;
-		urb->complete = usbvideo_IsocIrq;
-		urb->number_of_packets = FRAMES_PER_DESC;
-		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
-		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
-			urb->iso_frame_desc[j].offset = k;
-			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
-		}
-	}
-
-	/* Link URBs into a ring so that they invoke each other infinitely */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		if ((i+1) < USBVIDEO_NUMSBUF)
-			uvd->sbuf[i].urb->next = uvd->sbuf[i+1].urb;
-		else
-			uvd->sbuf[i].urb->next = uvd->sbuf[0].urb;
-	}
-
-	/* Submit all URBs */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
-		if (errFlag)
-			err("%s: usb_submit_isoc(%d) ret %d", proc, i, errFlag);
-	}
-
-	uvd->streaming = 1;
-	if (uvd->debug > 1)
-		info("%s: streaming=1 video_endp=$%02x", proc, uvd->video_endp);
-	return 0;
-}
-
-/*
- * usbvideo_StopDataPump()
- *
- * This procedure stops streaming and deallocates URBs. Then it
- * activates zero-bandwidth alt. setting of the video interface.
- *
- * History:
- * 22-Jan-2000 Corrected order of actions to work after surprise removal.
- * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values.
- */
-void usbvideo_StopDataPump(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_StopDataPump";
-	int i, j;
-
-	if (uvd->debug > 1)
-		info("%s($%p)", proc, uvd);
-
-	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
-		return;
-
-	/* Unschedule all of the iso td's */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
-		j = usb_unlink_urb(uvd->sbuf[i].urb);
-		if (j < 0)
-			err("%s: usb_unlink_urb() error %d.", proc, j);
-	}
-	if (uvd->debug > 1)
-		info("%s: streaming=0", proc);
-	uvd->streaming = 0;
-
-	if (!uvd->remove_pending) {
-		/* Invoke minidriver's magic to stop the camera */
-		if (VALID_CALLBACK(uvd, videoStop))
-			GET_CALLBACK(uvd, videoStop)(uvd);
-		else 
-			err("%s: videoStop not set" ,proc);
-
-		/* Set packet size to 0 */
-		j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
-		if (j < 0) {
-			err("%s: usb_set_interface() error %d.", proc, j);
-			uvd->last_error = j;
-		}
-	}
-}
-
-/*
- * usbvideo_NewFrame()
- *
- * History:
- * 29-Mar-00 Added copying of previous frame into the current one.
- * 6-Aug-00  Added model 3 video sizes, removed redundant width, height.
- */
-int usbvideo_NewFrame(uvd_t *uvd, int framenum)
-{
-	usbvideo_frame_t *frame;
-	int n;
-
-	if (uvd->debug > 1)
-		info("usbvideo_NewFrame($%p,%d.)", uvd, framenum);
-
-	/* If we're not grabbing a frame right now and the other frame is */
-	/*  ready to be grabbed into, then use it instead */
-	if (uvd->curframe != -1)
-		return 0;
-
-	/* If necessary we adjust picture settings between frames */
-	if (!uvd->settingsAdjusted) {
-		if (VALID_CALLBACK(uvd, adjustPicture))
-			GET_CALLBACK(uvd, adjustPicture)(uvd);
-		uvd->settingsAdjusted = 1;
-	}
-
-	n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
-	if (uvd->frame[n].frameState == FrameState_Ready)
-		framenum = n;
-
-	frame = &uvd->frame[framenum];
-
-	frame->frameState = FrameState_Grabbing;
-	frame->scanstate = ScanState_Scanning;
-	frame->seqRead_Length = 0;	/* Accumulated in xxx_parse_data() */
-	frame->deinterlace = Deinterlace_None;
-	frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */
-	uvd->curframe = framenum;
-
-	/*
-	 * Normally we would want to copy previous frame into the current one
-	 * before we even start filling it with data; this allows us to stop
-	 * filling at any moment; top portion of the frame will be new and
-	 * bottom portion will stay as it was in previous frame. If we don't
-	 * do that then missing chunks of video stream will result in flickering
-	 * portions of old data whatever it was before.
-	 *
-	 * If we choose not to copy previous frame (to, for example, save few
-	 * bus cycles - the frame can be pretty large!) then we have an option
-	 * to clear the frame before using. If we experience losses in this
-	 * mode then missing picture will be black (no flickering).
-	 *
-	 * Finally, if user chooses not to clean the current frame before
-	 * filling it with data then the old data will be visible if we fail
-	 * to refill entire frame with new data.
-	 */
-	if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
-		/* This copies previous frame into this one to mask losses */
-		memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size);
-	} else {
-		if (uvd->flags & FLAGS_CLEAN_FRAMES) {
-			/* This provides a "clean" frame but slows things down */
-			memset(frame->data, 0, uvd->max_frame_size);
-		}
-	}
-	return 0;
-}
-
-/*
- * usbvideo_CollectRawData()
- *
- * This procedure can be used instead of 'processData' callback if you
- * only want to dump the raw data from the camera into the output
- * device (frame buffer). You can look at it with V4L client, but the
- * image will be unwatchable. The main purpose of this code and of the
- * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from
- * new, unknown cameras. This procedure will be automatically invoked
- * instead of the specified callback handler when uvd->flags has bit
- * FLAGS_NO_DECODING set. Therefore, any regular build of any driver
- * based on usbvideo can use this feature at any time.
- */
-void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame)
-{
-	int n;
-
-	assert(uvd != NULL);
-	assert(frame != NULL);
-
-	/* Try to move data from queue into frame buffer */
-	n = RingQueue_GetLength(&uvd->dp);
-	if (n > 0) {
-		int m;
-		/* See how much space we have left */
-		m = uvd->max_frame_size - frame->seqRead_Length;
-		if (n > m)
-			n = m;
-		/* Now move that much data into frame buffer */
-		RingQueue_Dequeue(
-			&uvd->dp,
-			frame->data + frame->seqRead_Length,
-			m);
-		frame->seqRead_Length += m;
-	}
-	/* See if we filled the frame */
-	if (frame->seqRead_Length >= uvd->max_frame_size) {
-		frame->frameState = FrameState_Done;
-		uvd->curframe = -1;
-		uvd->stats.frame_num++;
-	}
-}
-
-int usbvideo_GetFrame(uvd_t *uvd, int frameNum)
-{
-	static const char proc[] = "usbvideo_GetFrame";
-	usbvideo_frame_t *frame = &uvd->frame[frameNum];
-
-	if (uvd->debug >= 2)
-		info("%s($%p,%d.)", proc, uvd, frameNum);
-
-	switch (frame->frameState) {
-        case FrameState_Unused:
-		if (uvd->debug >= 2)
-			info("%s: FrameState_Unused", proc);
-		return -EINVAL;
-        case FrameState_Ready:
-        case FrameState_Grabbing:
-        case FrameState_Error:
-        {
-		int ntries, signalPending;
-	redo:
-		if (!CAMERA_IS_OPERATIONAL(uvd)) {
-			if (uvd->debug >= 2)
-				info("%s: Camera is not operational (1)", proc);
-			return -EIO;
-		}
-		ntries = 0; 
-		do {
-			RingQueue_InterruptibleSleepOn(&uvd->dp);
-			signalPending = signal_pending(current);
-			if (!CAMERA_IS_OPERATIONAL(uvd)) {
-				if (uvd->debug >= 2)
-					info("%s: Camera is not operational (2)", proc);
-				return -EIO;
-			}
-			assert(uvd->fbuf != NULL);
-			if (signalPending) {
-				if (uvd->debug >= 2)
-					info("%s: Signal=$%08x", proc, signalPending);
-				if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
-					usbvideo_TestPattern(uvd, 1, 0);
-					uvd->curframe = -1;
-					uvd->stats.frame_num++;
-					if (uvd->debug >= 2)
-						info("%s: Forced test pattern screen", proc);
-					return 0;
-				} else {
-					/* Standard answer: Interrupted! */
-					if (uvd->debug >= 2)
-						info("%s: Interrupted!", proc);
-					return -EINTR;
-				}
-			} else {
-				/* No signals - we just got new data in dp queue */
-				if (uvd->flags & FLAGS_NO_DECODING)
-					usbvideo_CollectRawData(uvd, frame);
-				else if (VALID_CALLBACK(uvd, processData))
-					GET_CALLBACK(uvd, processData)(uvd, frame);
-				else 
-					err("%s: processData not set", proc);
-			}
-		} while (frame->frameState == FrameState_Grabbing);
-		if (uvd->debug >= 2) {
-			info("%s: Grabbing done; state=%d. (%lu. bytes)",
-			     proc, frame->frameState, frame->seqRead_Length);
-		}
-		if (frame->frameState == FrameState_Error) {
-			int ret = usbvideo_NewFrame(uvd, frameNum);
-			if (ret < 0) {
-				err("%s: usbvideo_NewFrame() failed (%d.)", proc, ret);
-				return ret;
-			}
-			goto redo;
-		}
-		/* Note that we fall through to meet our destiny below */
-        }
-        case FrameState_Done:
-		/*
-		 * Do all necessary postprocessing of data prepared in
-		 * "interrupt" code and the collecting code above. The
-		 * frame gets marked as FrameState_Done by queue parsing code.
-		 * This status means that we collected enough data and
-		 * most likely processed it as we went through. However
-		 * the data may need postprocessing, such as deinterlacing
-		 * or picture adjustments implemented in software (horror!)
-		 *
-		 * As soon as the frame becomes "final" it gets promoted to
-		 * FrameState_Done_Hold status where it will remain until the
-		 * caller consumed all the video data from the frame. Then
-		 * the empty shell of ex-frame is thrown out for dogs to eat.
-		 * But we, worried about pets, will recycle the frame!
-		 */
-		uvd->stats.frame_num++;
-		if ((uvd->flags & FLAGS_NO_DECODING) == 0) {
-			if (VALID_CALLBACK(uvd, postProcess))
-				GET_CALLBACK(uvd, postProcess)(uvd, frame);
-			if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST)
-				usbvideo_SoftwareContrastAdjustment(uvd, frame);
-		}
-		frame->frameState = FrameState_Done_Hold;
-		if (uvd->debug >= 2)
-			info("%s: Entered FrameState_Done_Hold state.", proc);
-		return 0;
-
-	case FrameState_Done_Hold:
-		/*
-		 * We stay in this state indefinitely until someone external,
-		 * like ioctl() or read() call finishes digesting the frame
-		 * data. Then it will mark the frame as FrameState_Unused and
-		 * it will be released back into the wild to roam freely.
-		 */
-		if (uvd->debug >= 2)
-			info("%s: FrameState_Done_Hold state.", proc);
-		return 0;
-	}
-
-	/* Catch-all for other cases. We shall not be here. */
-	err("%s: Invalid state %d.", proc, frame->frameState);
-	frame->frameState = FrameState_Unused;
-	return 0;
-}
-
-/*
- * usbvideo_DeinterlaceFrame()
- *
- * This procedure deinterlaces the given frame. Some cameras produce
- * only half of scanlines - sometimes only even lines, sometimes only
- * odd lines. The deinterlacing method is stored in frame->deinterlace
- * variable.
- *
- * Here we scan the frame vertically and replace missing scanlines with
- * average between surrounding ones - before and after. If we have no
- * line above then we just copy next line. Similarly, if we need to
- * create a last line then preceding line is used.
- */
-void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame)
-{
-	if ((uvd == NULL) || (frame == NULL))
-		return;
-
-	if ((frame->deinterlace == Deinterlace_FillEvenLines) ||
-	    (frame->deinterlace == Deinterlace_FillOddLines))
-	{
-		const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-		int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1;
-
-		for (; i < VIDEOSIZE_Y(frame->request); i += 2) {
-			const unsigned char *fs1, *fs2;
-			unsigned char *fd;
-			int ip, in, j;	/* Previous and next lines */
-
-			/*
-			 * Need to average lines before and after 'i'.
-			 * If we go out of bounds seeking those lines then
-			 * we point back to existing line.
-			 */
-			ip = i - 1;	/* First, get rough numbers */
-			in = i + 1;
-
-			/* Now validate */
-			if (ip < 0)
-				ip = in;
-			if (in >= VIDEOSIZE_Y(frame->request))
-				in = ip;
-
-			/* Sanity check */
-			if ((ip < 0) || (in < 0) ||
-			    (ip >= VIDEOSIZE_Y(frame->request)) ||
-			    (in >= VIDEOSIZE_Y(frame->request)))
-			{
-				err("Error: ip=%d. in=%d. req.height=%ld.",
-				    ip, in, VIDEOSIZE_Y(frame->request));
-				break;
-			}
-
-			/* Now we need to average lines 'ip' and 'in' to produce line 'i' */
-			fs1 = frame->data + (v4l_linesize * ip);
-			fs2 = frame->data + (v4l_linesize * in);
-			fd = frame->data + (v4l_linesize * i);
-
-			/* Average lines around destination */
-			for (j=0; j < v4l_linesize; j++) {
-				fd[j] = (unsigned char)((((unsigned) fs1[j]) +
-							 ((unsigned)fs2[j])) >> 1);
-			}
-		}
-	}
-
-	/* Optionally display statistics on the screen */
-	if (uvd->flags & FLAGS_OVERLAY_STATS)
-		usbvideo_OverlayStats(uvd, frame);
-}
-
-/*
- * usbvideo_SoftwareContrastAdjustment()
- *
- * This code adjusts the contrast of the frame, assuming RGB24 format.
- * As most software image processing, this job is CPU-intensive.
- * Get a camera that supports hardware adjustment!
- *
- * History:
- * 09-Feb-2001  Created.
- */
-void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame)
-{
-	static const char proc[] = "usbvideo_SoftwareContrastAdjustment";
-	int i, j, v4l_linesize;
-	signed long adj;
-	const int ccm = 128; /* Color correction median - see below */
-
-	if ((uvd == NULL) || (frame == NULL)) {
-		err("%s: Illegal call.", proc);
-		return;
-	}
-	adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
-	RESTRICT_TO_RANGE(adj, -ccm, ccm+1);
-	if (adj == 0) {
-		/* In rare case of no adjustment */
-		return;
-	}
-	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-	for (i=0; i < VIDEOSIZE_Y(frame->request); i++) {
-		unsigned char *fd = frame->data + (v4l_linesize * i);
-		for (j=0; j < v4l_linesize; j++) {
-			signed long v = (signed long) fd[j];
-			/* Magnify up to 2 times, reduce down to zero */
-			v = 128 + ((ccm + adj) * (v - 128)) / ccm;
-			RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */
-			fd[j] = (unsigned char) v;
-		}
-	}
-}
-
-/*
- * /proc interface
- *
- * We will be creating directories and entries under /proc/video using
- * external 'video_proc_entry' directory which is exported by videodev.o
- * module. Within that directory we will create $driver/ directory to
- * uniquely and uniformly refer to our specific $driver. Within that
- * directory we will finally create an entry that is named after the
- * video device node - video3, for example. The format of that file
- * is determined by callbacks that the minidriver may provide. If no
- * callbacks are provided (neither read nor write) then we don't create
- * the entry.
- *
- * Here is a sample directory entry: /proc/video/ibmcam/video3
- *
- * The "file" video3 (in example above) is readable and writeable, in
- * theory. If the minidriver provides callbacks to do reading and
- * writing then both those procedures are supported. However if the
- * driver leaves callbacks in default (NULL) state the default
- * read and write handlers are used. The default read handler reports
- * that the driver does not support /proc fs. The default write handler
- * returns error code on any write attempt.
- */
-
-#if USES_PROC_FS
-
-extern struct proc_dir_entry *video_proc_entry;
-
-static void usbvideo_procfs_level1_create(usbvideo_t *ut)
-{
-	static const char proc[] = "usbvideo_procfs_level1_create";
-
-	if (ut == NULL) {
-		err("%s: ut == NULL", proc);
-		return;
-	}
-	if (video_proc_entry == NULL) {
-		err("%s: /proc/video/ doesn't exist.", proc);
-		return;
-	}
-	ut->procfs_dEntry = create_proc_entry(ut->drvName, S_IFDIR, video_proc_entry);
-	if (ut->procfs_dEntry != NULL) {
-		if (ut->md_module != NULL)
-			ut->procfs_dEntry->owner = ut->md_module;
-	} else {
-		err("%s: Unable to initialize /proc/video/%s", proc, ut->drvName);
-	}
-}
-
-static void usbvideo_procfs_level1_destroy(usbvideo_t *ut)
-{
-	static const char proc[] = "usbvideo_procfs_level1_destroy";
-
-	if (ut == NULL) {
-		err("%s: ut == NULL", proc);
-		return;
-	}
-	if (ut->procfs_dEntry != NULL) {
-		remove_proc_entry(ut->drvName, video_proc_entry);
-		ut->procfs_dEntry = NULL;
-	}
-}
-
-static void usbvideo_procfs_level2_create(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_procfs_level2_create";
-
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", proc);
-		return;
-	}
-	assert(uvd->handle != NULL);
-	if (uvd->handle->procfs_dEntry == NULL) {
-		err("%s: uvd->handle->procfs_dEntry == NULL", proc);
-		return;
-	}
-
-	sprintf(uvd->videoName, "video%d", uvd->vdev.minor);
-	uvd->procfs_vEntry = create_proc_entry(
-		uvd->videoName,
-		S_IFREG | S_IRUGO | S_IWUSR,
-		uvd->handle->procfs_dEntry);
-	if (uvd->procfs_vEntry != NULL) {
-		uvd->procfs_vEntry->data = uvd;
-		uvd->procfs_vEntry->read_proc = uvd->handle->cb.procfs_read;
-		uvd->procfs_vEntry->write_proc = uvd->handle->cb.procfs_write;
-	} else {
-		err("%s: Failed to create entry \"%s\"", proc, uvd->videoName);
-	}
-}
-
-static void usbvideo_procfs_level2_destroy(uvd_t *uvd)
-{
-	static const char proc[] = "usbvideo_procfs_level2_destroy";
-
-	if (uvd == NULL) {
-		err("%s: uvd == NULL", proc);
-		return;
-	}
-	if (uvd->procfs_vEntry != NULL) {
-		remove_proc_entry(uvd->videoName, uvd->procfs_vEntry);
-		uvd->procfs_vEntry = NULL;
-	}
-}
-
-static int usbvideo_default_procfs_read_proc(
-	char *page, char **start, off_t off, int count,
-	int *eof, void *data)
-{
-	char *out = page;
-	int len;
-	
-	/* Stay under PAGE_SIZE or else */
-	out += sprintf(out, "This driver does not support /proc services.\n");
-	len = out - page;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else
-		len = count;
-	*start = page + off;
-	return len;	
-}
-
-static int usbvideo_default_procfs_write_proc(
-	struct file *file, const char *buffer, 
-	unsigned long count, void *data)
-{
-	return -EINVAL;
-}
-
-#endif /* USES_PROC_FS */
-MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/usbvideo.h b/drivers/usb/usbvideo.h
--- a/drivers/usb/usbvideo.h	Sun Apr 14 12:16:58 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,416 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef usbvideo_h
-#define	usbvideo_h
-
-#include <linux/config.h>
-#include <linux/proc_fs.h>
-#include <linux/videodev.h>
-#include <linux/usb.h>
-
-/* Most helpful debugging aid */
-#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
-
-#define USES_PROC_FS	(defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS))
-#define USBVIDEO_REPORT_STATS	1	/* Set to 0 to block statistics on close */
-
-/* Bit flags (options) */
-#define FLAGS_RETRY_VIDIOCSYNC		(1 << 0)
-#define	FLAGS_MONOCHROME		(1 << 1)
-#define FLAGS_DISPLAY_HINTS		(1 << 2)
-#define FLAGS_OVERLAY_STATS		(1 << 3)
-#define FLAGS_FORCE_TESTPATTERN		(1 << 4)
-#define FLAGS_SEPARATE_FRAMES		(1 << 5)
-#define FLAGS_CLEAN_FRAMES		(1 << 6)
-#define	FLAGS_NO_DECODING		(1 << 7)
-
-/* Bit flags for frames (apply to the frame where they are specified) */
-#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST	(1 << 0)
-
-/* Camera capabilities (maximum) */
-#define CAMERA_URB_FRAMES       32
-#define CAMERA_MAX_ISO_PACKET   1023 /* 1022 actually sent by camera */
-#define FRAMES_PER_DESC		(CAMERA_URB_FRAMES)
-#define FRAME_SIZE_PER_DESC	(CAMERA_MAX_ISO_PACKET)
-
-/* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
-
-#define V4L_BYTES_PER_PIXEL     3	/* Because we produce RGB24 */
-
-/*
- * Use this macro to construct constants for different video sizes.
- * We have to deal with different video sizes that have to be
- * configured in the device or compared against when we receive
- * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y
- * #defines and that's the end of story. However this solution
- * does not allow to convert between real pixel sizes and the
- * constant (integer) value that may be used to tag a frame or
- * whatever. The set of macros below constructs videosize constants
- * from the pixel size and allows to reconstruct the pixel size
- * from the combined value later.
- */
-#define	VIDEOSIZE(x,y)	(((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16))
-#define	VIDEOSIZE_X(vs)	((vs) & 0xFFFFL)
-#define	VIDEOSIZE_Y(vs)	(((vs) >> 16) & 0xFFFFL)
-typedef unsigned long videosize_t;
-
-/*
- * This macro checks if the camera is still operational. The 'uvd'
- * pointer must be valid, uvd->dev must be valid, we are not
- * removing the device and the device has not erred on us.
- */
-#define CAMERA_IS_OPERATIONAL(uvd) (\
-	(uvd != NULL) && \
-	((uvd)->dev != NULL) && \
-	((uvd)->last_error == 0) && \
-	(!(uvd)->remove_pending))
-
-/*
- * We use macros to do YUV -> RGB conversion because this is
- * very important for speed and totally unimportant for size.
- *
- * YUV -> RGB Conversion
- * ---------------------
- *
- * B = 1.164*(Y-16)		    + 2.018*(V-128)
- * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
- * R = 1.164*(Y-16) + 1.596*(U-128)
- *
- * If you fancy integer arithmetics (as you should), hear this:
- *
- * 65536*B = 76284*(Y-16)		  + 132252*(V-128)
- * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
- * 65536*R = 76284*(Y-16) + 104595*(U-128)
- *
- * Make sure the output values are within [0..255] range.
- */
-#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
-#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
-    int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
-    mm_y = (my) - 16;  \
-    mm_u = (mu) - 128; \
-    mm_v = (mv) - 128; \
-    mm_yc= mm_y * 76284; \
-    mm_b = (mm_yc		+ 132252*mm_v	) >> 16; \
-    mm_g = (mm_yc -  53281*mm_u -  25625*mm_v	) >> 16; \
-    mm_r = (mm_yc + 104595*mm_u			) >> 16; \
-    mb = LIMIT_RGB(mm_b); \
-    mg = LIMIT_RGB(mm_g); \
-    mr = LIMIT_RGB(mm_r); \
-}
-
-#define	RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length
-#define	RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
-#define	RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length])
-
-typedef struct {
-	unsigned char *queue;	/* Data from the Isoc data pump */
-	int length;		/* How many bytes allocated for the queue */
-	int wi;			/* That's where we write */
-	int ri;			/* Read from here until you hit write index */
-	wait_queue_head_t wqh;	/* Processes waiting */
-} RingQueue_t;
-
-typedef enum {
-	ScanState_Scanning,	/* Scanning for header */
-	ScanState_Lines		/* Parsing lines */
-} ScanState_t;
-
-/* Completion states of the data parser */
-typedef enum {
-	scan_Continue,		/* Just parse next item */
-	scan_NextFrame,		/* Frame done, send it to V4L */
-	scan_Out,		/* Not enough data for frame */
-	scan_EndParse		/* End parsing */
-} ParseState_t;
-
-typedef enum {
-	FrameState_Unused,	/* Unused (no MCAPTURE) */
-	FrameState_Ready,	/* Ready to start grabbing */
-	FrameState_Grabbing,	/* In the process of being grabbed into */
-	FrameState_Done,	/* Finished grabbing, but not been synced yet */
-	FrameState_Done_Hold,	/* Are syncing or reading */
-	FrameState_Error,	/* Something bad happened while processing */
-} FrameState_t;
-
-/*
- * Some frames may contain only even or odd lines. This type
- * specifies what type of deinterlacing is required.
- */
-typedef enum {
-	Deinterlace_None=0,
-	Deinterlace_FillOddLines,
-	Deinterlace_FillEvenLines
-} Deinterlace_t;
-
-struct usb_device;
-
-#define USBVIDEO_NUMFRAMES	2	/* How many frames we work with */
-#define USBVIDEO_NUMSBUF	2	/* How many URBs linked in a ring */
-
-/* This structure represents one Isoc request - URB and buffer */
-typedef struct {
-	char *data;
-	struct urb *urb;
-} usbvideo_sbuf_t;
-
-typedef struct {
-	char *data;		/* Frame buffer */
-	unsigned long header;	/* Significant bits from the header */
-
-	videosize_t canvas;	/* The canvas (max. image) allocated */
-	videosize_t request;	/* That's what the application asked for */
-	unsigned short palette;	/* The desired format */
-
-	FrameState_t frameState;/* State of grabbing */
-	ScanState_t scanstate;	/* State of scanning */
-	Deinterlace_t deinterlace;
-	int flags;		/* USBVIDEO_FRAME_FLAG_xxx bit flags */
-
-	int curline;		/* Line of frame we're working on */
-
-	long seqRead_Length;	/* Raw data length of frame */
-	long seqRead_Index;	/* Amount of data that has been already read */
-
-	void *user;		/* Additional data that user may need */
-} usbvideo_frame_t;
-
-/* Statistics that can be overlaid on screen */
-typedef struct {
-        unsigned long frame_num;	/* Sequential number of the frame */
-        unsigned long urb_count;        /* How many URBs we received so far */
-        unsigned long urb_length;       /* Length of last URB */
-        unsigned long data_count;       /* How many bytes we received */
-        unsigned long header_count;     /* How many frame headers we found */
-	unsigned long iso_skip_count;	/* How many empty ISO packets received */
-	unsigned long iso_err_count;	/* How many bad ISO packets received */
-} usbvideo_statistics_t;
-
-struct s_usbvideo_t;
-
-typedef struct {
-	struct video_device vdev;	/* Must be the first field! */
-	struct usb_device *dev;
-	struct s_usbvideo_t *handle;	/* Points back to the usbvideo_t */
-	void *user_data;		/* Camera-dependent data */
-	int user_size;			/* Size of that camera-dependent data */
-	int debug;			/* Debug level for usbvideo */
-	unsigned char iface;		/* Video interface number */
-	unsigned char video_endp;
-	unsigned char ifaceAltActive;
-	unsigned char ifaceAltInactive; /* Alt settings */
-	unsigned long flags;		/* FLAGS_USBVIDEO_xxx */
-	unsigned long paletteBits;	/* Which palettes we accept? */
-	unsigned short defaultPalette;	/* What palette to use for read() */
-	struct semaphore lock;
-	int user;		/* user count for exclusive use */
-
-	videosize_t videosize;	/* Current setting */
-	videosize_t canvas;	/* This is the width,height of the V4L canvas */
-	int max_frame_size;	/* Bytes in one video frame */
-
-	int uvd_used;        	/* Is this structure in use? */
-	int streaming;		/* Are we streaming Isochronous? */
-	int grabbing;		/* Are we grabbing? */
-	int settingsAdjusted;	/* Have we adjusted contrast etc.? */
-	int last_error;		/* What calamity struck us? */
-
-	char *fbuf;		/* Videodev buffer area */
-	int fbuf_size;		/* Videodev buffer size */
-
-	int curframe;
-	int iso_packet_len;	/* Videomode-dependent, saves bus bandwidth */
-
-	RingQueue_t dp;		/* Isoc data pump */
-	usbvideo_frame_t frame[USBVIDEO_NUMFRAMES];
-	usbvideo_sbuf_t sbuf[USBVIDEO_NUMSBUF];
-
-	volatile int remove_pending;	/* If set then about to exit */
-
-	struct video_picture vpic, vpic_old;	/* Picture settings */
-	struct video_capability vcap;		/* Video capabilities */
-	struct video_channel vchan;	/* May be used for tuner support */
-	usbvideo_statistics_t stats;
-	struct proc_dir_entry *procfs_vEntry;	/* /proc/video/MYDRIVER/video2 */
-	char videoName[32];		/* Holds name like "video7" */
-} uvd_t;
-
-/*
- * usbvideo callbacks (virtual methods). They are set when usbvideo
- * services are registered. All of these default to NULL, except those
- * that default to usbvideo-provided methods.
- */
-typedef struct {
-	void *(*probe)(struct usb_device *, unsigned int,const struct usb_device_id *);
-	void (*userFree)(uvd_t *);
-	void (*disconnect)(struct usb_device *, void *);
-	int (*setupOnOpen)(uvd_t *);
-	void (*videoStart)(uvd_t *);
-	void (*videoStop)(uvd_t *);
-	void (*processData)(uvd_t *, usbvideo_frame_t *);
-	void (*postProcess)(uvd_t *, usbvideo_frame_t *);
-	void (*adjustPicture)(uvd_t *);
-	int (*getFPS)(uvd_t *);
-	int (*overlayHook)(uvd_t *, usbvideo_frame_t *);
-	int (*getFrame)(uvd_t *, int);
-	int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data);
-	int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data);
-	int (*startDataPump)(uvd_t *uvd);
-	void (*stopDataPump)(uvd_t *uvd);
-} usbvideo_cb_t;
-
-struct s_usbvideo_t {
-	int num_cameras;		/* As allocated */
-	struct usb_driver usbdrv;	/* Interface to the USB stack */
-	char drvName[80];		/* Driver name */
-	struct semaphore lock;		/* Mutex protecting camera structures */
-	usbvideo_cb_t cb;		/* Table of callbacks (virtual methods) */
-	struct video_device vdt;	/* Video device template */
-	uvd_t *cam;			/* Array of camera structures */
-	int uses_procfs;		/* Non-zero if we create /proc entries */
-	struct proc_dir_entry *procfs_dEntry;	/* /proc/video/MYDRIVER */
-	struct module *md_module;	/* Minidriver module */
-};
-typedef struct s_usbvideo_t usbvideo_t;
-
-/*
- * This macro retrieves callback address from the uvd_t object.
- * No validity checks are done here, so be sure to check the
- * callback beforehand with VALID_CALLBACK.
- */
-#define	GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName)
-
-/*
- * This macro returns either callback pointer or NULL. This is safe
- * macro, meaning that most of components of data structures involved
- * may be NULL - this only results in NULL being returned. You may
- * wish to use this macro to make sure that the callback is callable.
- * However keep in mind that those checks take time.
- */
-#define	VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
-		((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
-
-void RingQueue_Initialize(RingQueue_t *rq);
-void RingQueue_Allocate(RingQueue_t *rq, int rqLen);
-int  RingQueue_IsAllocated(const RingQueue_t *rq);
-void RingQueue_Free(RingQueue_t *rq);
-int  RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len);
-int  RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n);
-int  RingQueue_GetLength(const RingQueue_t *rq);
-void RingQueue_InterruptibleSleepOn(RingQueue_t *rq);
-void RingQueue_WakeUpInterruptible(RingQueue_t *rq);
-
-void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame);
-void usbvideo_DrawLine(
-	usbvideo_frame_t *frame,
-	int x1, int y1,
-	int x2, int y2,
-	unsigned char cr, unsigned char cg, unsigned char cb);
-void usbvideo_HexDump(const unsigned char *data, int len);
-void usbvideo_OverlayChar(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, int ch);
-void usbvideo_OverlayString(uvd_t *uvd, usbvideo_frame_t *frame, int x, int y, const char *str);
-void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame);
-void usbvideo_ReportStatistics(const uvd_t *uvd);
-void usbvideo_SayAndWait(const char *what);
-void usbvideo_TestPattern(uvd_t *uvd, int fullframe, int pmode);
-void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs);
-
-/* Memory allocation routines */
-unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
-void *usbvideo_rvmalloc(unsigned long size);
-void usbvideo_rvfree(void *mem, unsigned long size);
-
-int usbvideo_register(
-	usbvideo_t **pCams,
-	const int num_cams,
-	const int num_extra,
-	const char *driverName,
-	const usbvideo_cb_t *cbTable,
-	struct module *md);
-uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams);
-int usbvideo_RegisterVideoDevice(uvd_t *uvd);
-void usbvideo_Deregister(usbvideo_t **uvt);
-void usbvideo_Disconnect(struct usb_device *dev, void *ptr);
-void usbvideo_CameraRelease(uvd_t *uvd);
-
-int usbvideo_v4l_close(struct inode *inode, struct file *file);
-int usbvideo_v4l_initialize(struct video_device *dev);
-int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
-		       unsigned int ioctlnr, void *arg);
-int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
-int usbvideo_v4l_open(struct inode *inode, struct file *file);
-int usbvideo_v4l_read(struct file *file, char *buf,
-		      size_t count, loff_t *ppos);
-
-int usbvideo_GetFrame(uvd_t *uvd, int frameNum);
-int usbvideo_NewFrame(uvd_t *uvd, int framenum);
-int usbvideo_StartDataPump(uvd_t *uvd);
-void usbvideo_StopDataPump(uvd_t *uvd);
-void usbvideo_DeinterlaceFrame(uvd_t *uvd, usbvideo_frame_t *frame);
-void usbvideo_SoftwareContrastAdjustment(uvd_t *uvd, usbvideo_frame_t *frame);
-
-/*
- * This code performs bounds checking - use it when working with
- * new formats, or else you may get oopses all over the place.
- * If pixel falls out of bounds then it gets shoved back (as close
- * to place of offence as possible) and is painted bright red.
- *
- * There are two important concepts: frame width, height and
- * V4L canvas width, height. The former is the area requested by
- * the application -for this very frame-. The latter is the largest
- * possible frame that we can serve (we advertise that via V4L ioctl).
- * The frame data is expected to be formatted as lines of length
- * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines.
- */
-static inline void RGB24_PUTPIXEL(
-	usbvideo_frame_t *fr,
-	int ix, int iy,
-	unsigned char vr,
-	unsigned char vg,
-	unsigned char vb)
-{
-	register unsigned char *pf;
-	int limiter = 0, mx, my;
-	mx = ix;
-	my = iy;
-	if (mx < 0) {
-		mx=0;
-		limiter++;
-	} else if (mx >= VIDEOSIZE_X((fr)->request)) {
-		mx= VIDEOSIZE_X((fr)->request) - 1;
-		limiter++;
-	}
-	if (my < 0) {
-		my = 0;
-		limiter++;
-	} else if (my >= VIDEOSIZE_Y((fr)->request)) {
-		my = VIDEOSIZE_Y((fr)->request) - 1;
-		limiter++;
-	}
-	pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix));
-	if (limiter) {
-		*pf++ = 0;
-		*pf++ = 0;
-		*pf++ = 0xFF;
-	} else {
-		*pf++ = (vb);
-		*pf++ = (vg);
-		*pf++ = (vr);
-	}
-}
-
-#endif /* usbvideo_h */
diff -Nru a/drivers/usb/uss720.c b/drivers/usb/uss720.c
--- a/drivers/usb/uss720.c	Sun Apr 14 12:16:54 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,678 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	uss720.c  --  USS720 USB Parport Cable.
- *
- *	Copyright (C) 1999
- *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	This program is free software; you can redistribute it and/or 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 on parport_pc.c
- *
- *  History:
- *   0.1  04.08.99  Created
- *   0.2  07.08.99  Some fixes mainly suggested by Tim Waugh
- *		    Interrupt handling currently disabled because
- *		    usb_request_irq crashes somewhere within ohci.c
- *		    for no apparent reason (that is for me, anyway)
- *		    ECP currently untested
- *   0.3  10.08.99  fixing merge errors
- *   0.4  13.08.99  Added Vendor/Product ID of Brad Hard's cable
- *   0.5  20.09.99  usb_control_msg wrapper used
- *        Nov01.00  usb_device_table support by Adam J. Richter
- *        08.04.01  Identify version on module load.  gb
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/parport.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v0.5"
-#define DRIVER_AUTHOR "Thomas M. Sailer, sailer@ife.ee.ethz.ch"
-#define DRIVER_DESC "USB Parport Cable driver for Cables using the Lucent Technologies USS720 Chip"
-
-/* --------------------------------------------------------------------- */
-
-struct parport_uss720_private {
-	struct usb_device *usbdev;
-	void *irqhandle;
-	unsigned int irqpipe;
-	unsigned char reg[7];  /* USB registers */
-};
-
-/* --------------------------------------------------------------------- */
-
-static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
-{
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	static const unsigned char regindex[9] = {
-		4, 0, 1, 5, 5, 0, 2, 3, 6
-	};
-	int ret;
-
-	if (!usbdev)
-		return -1;
-	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, HZ);
-	if (ret != 7) {
-		printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
-		       (unsigned int)reg, ret);
-		ret = -1;
-	} else {
-#if 0
-		printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
-		       (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
-		       (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
-		       (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
-#endif
-		/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
-		if (priv->reg[2] & priv->reg[1] & 0x10)
-			parport_generic_irq(0, pp, NULL);
-		ret = 0;
-	}
-	if (val)
-		*val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
-	return ret;
-}
-
-static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
-{
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	int ret;
-
-	if (!usbdev)
-		return -1;
-	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, HZ);
-	if (ret) {
-		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 
-		       (unsigned int)reg, (unsigned int)val, ret);
-	} else {
-#if 0
-		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 
-		       (unsigned int)reg, (unsigned int)val);
-#endif
-	}
-	return ret;
-}
-
-/* --------------------------------------------------------------------- */
-
-/* ECR modes */
-#define ECR_SPP 00
-#define ECR_PS2 01
-#define ECR_PPF 02
-#define ECR_ECP 03
-#define ECR_EPP 04
-
-/* Safely change the mode bits in the ECR */
-static int change_mode(struct parport *pp, int m)
-{
-	struct parport_uss720_private *priv = pp->private_data;
-	int mode;
-
-	if (get_1284_register(pp, 6, NULL))
-		return -EIO;
-	/* Bits <7:5> contain the mode. */
-	mode = (priv->reg[2] >> 5) & 0x7;
-	if (mode == m)
-		return 0;
-	/* We have to go through mode 000 or 001 */
-	if (mode > ECR_PS2 && m > ECR_PS2)
-		if (change_mode(pp, ECR_PS2))
-			return -EIO;
-
-	if (m <= ECR_PS2 && !(priv->reg[1] & 0x20)) {
-		/* This mode resets the FIFO, so we may
-		 * have to wait for it to drain first. */
-		long expire = jiffies + pp->physport->cad->timeout;
-		switch (mode) {
-		case ECR_PPF: /* Parallel Port FIFO mode */
-		case ECR_ECP: /* ECP Parallel Port mode */
-			/* Poll slowly. */
-			for (;;) {
-				if (get_1284_register(pp, 6, NULL))
-					return -EIO;
-				if (priv->reg[2] & 0x01)
-					break;
-				if (time_after_eq (jiffies, expire))
-					/* The FIFO is stuck. */
-					return -EBUSY;
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout((HZ + 99) / 100);
-				if (signal_pending (current))
-					break;
-			}
-		}
-	}
-	/* Set the mode. */
-	if (set_1284_register(pp, 6, m << 5))
-		return -EIO;
-	return 0;
-}
-
-/*
- * Clear TIMEOUT BIT in EPP MODE
- */
-static int clear_epp_timeout(struct parport *pp)
-{
-	unsigned char stat;
-
-	if (get_1284_register(pp, 1, &stat))
-		return 1;
-	return stat & 1;
-}
-
-/*
- * Access functions.
- */
-#if 0
-static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
-{
-	struct parport *pp = (struct parport *)dev_id;
-	struct parport_uss720_private *priv = pp->private_data;	
-
-	if (usbstatus != 0 || len < 4 || !buffer)
-		return 1;
-	memcpy(priv->reg, buffer, 4);
-	/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
-	if (priv->reg[2] & priv->reg[1] & 0x10)
-		parport_generic_irq(0, pp, NULL);
-	return 1;
-}
-#endif
-
-static void parport_uss720_write_data(struct parport *pp, unsigned char d)
-{
-	set_1284_register(pp, 0, d);
-}
-
-static unsigned char parport_uss720_read_data(struct parport *pp)
-{
-	unsigned char ret;
-
-	if (get_1284_register(pp, 0, &ret))
-		return 0;
-	return ret;
-}
-
-static void parport_uss720_write_control(struct parport *pp, unsigned char d)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-
-	d = (d & 0xf) | (priv->reg[1] & 0xf0);
-	if (set_1284_register(pp, 2, d))
-		return;
-	priv->reg[1] = d;
-}
-
-static unsigned char parport_uss720_read_control(struct parport *pp)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	return priv->reg[1] & 0xf; /* Use soft copy */
-}
-
-static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned char mask, unsigned char val)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	unsigned char d;
-
-	mask &= 0x0f;
-	val &= 0x0f;
-	d = (priv->reg[1] & (~mask)) ^ val;
-	if (set_1284_register(pp, 2, d))
-		return 0;
-	priv->reg[1] = d;
-	return d & 0xf;
-}
-
-static unsigned char parport_uss720_read_status(struct parport *pp)
-{
-	unsigned char ret;
-
-	if (get_1284_register(pp, 1, &ret))
-		return 0;
-	return ret & 0xf8;
-}
-
-static void parport_uss720_disable_irq(struct parport *pp)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	unsigned char d;
-
-	d = priv->reg[1] & ~0x10;
-	if (set_1284_register(pp, 2, d))
-		return;
-	priv->reg[1] = d;
-}
-
-static void parport_uss720_enable_irq(struct parport *pp)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	unsigned char d;
-
-	d = priv->reg[1] | 0x10;
-	if (set_1284_register(pp, 2, d))
-		return;
-	priv->reg[1] = d;
-}
-
-static void parport_uss720_data_forward (struct parport *pp)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	unsigned char d;
-
-	d = priv->reg[1] & ~0x20;
-	if (set_1284_register(pp, 2, d))
-		return;
-	priv->reg[1] = d;
-}
-
-static void parport_uss720_data_reverse (struct parport *pp)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	unsigned char d;
-
-	d = priv->reg[1] | 0x20;
-	if (set_1284_register(pp, 2, d))
-		return;
-	priv->reg[1] = d;
-}
-
-static void parport_uss720_init_state(struct pardevice *dev, struct parport_state *s)
-{
-	s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
-	s->u.pc.ecr = 0x24;
-}
-
-static void parport_uss720_save_state(struct parport *pp, struct parport_state *s)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-
-	if (get_1284_register(pp, 2, NULL))
-		return;
-	s->u.pc.ctr = priv->reg[1];
-	s->u.pc.ecr = priv->reg[2];
-}
-
-static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
-{
-	set_1284_register(pp, 2, s->u.pc.ctr);
-	set_1284_register(pp, 6, s->u.pc.ecr);
-	get_1284_register(pp, 2, NULL);
-}
-
-static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	size_t got = 0;
-
-	if (change_mode(pp, ECR_EPP))
-		return 0;
-	for (; got < length; got++) {
-		if (get_1284_register(pp, 4, (char *)buf))
-			break;
-		((char*)buf)++;
-		if (priv->reg[0] & 0x01) {
-			clear_epp_timeout(pp);
-			break;
-		}
-	}
-	change_mode(pp, ECR_PS2);
-	return got;
-}
-
-static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags)
-{
-#if 0
-	struct parport_uss720_private *priv = pp->private_data;	
-	size_t written = 0;
-
-	if (change_mode(pp, ECR_EPP))
-		return 0;
-	for (; written < length; written++) {
-		if (set_1284_register(pp, 4, (char *)buf))
-			break;
-		((char*)buf)++;
-		if (get_1284_register(pp, 1, NULL))
-			break;
-		if (priv->reg[0] & 0x01) {
-			clear_epp_timeout(pp);
-			break;
-		}
-	}
-	change_mode(pp, ECR_PS2);
-	return written;
-#else
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	int rlen;
-	int i;
-
-	if (!usbdev)
-		return 0;
-	if (change_mode(pp, ECR_EPP))
-		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20);
-	if (i)
-		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buf, length, rlen);
-	change_mode(pp, ECR_PS2);
-	return rlen;
-#endif
-}
-
-static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	size_t got = 0;
-
-	if (change_mode(pp, ECR_EPP))
-		return 0;
-	for (; got < length; got++) {
-		if (get_1284_register(pp, 3, (char *)buf))
-			break;
-		((char*)buf)++;
-		if (priv->reg[0] & 0x01) {
-			clear_epp_timeout(pp);
-			break;
-		}
-	}
-	change_mode(pp, ECR_PS2);
-	return got;
-}
-
-static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags)
-{
-	struct parport_uss720_private *priv = pp->private_data;	
-	size_t written = 0;
-
-	if (change_mode(pp, ECR_EPP))
-		return 0;
-	for (; written < length; written++) {
-		if (set_1284_register(pp, 3, *(char *)buf))
-			break;
-		((char*)buf)++;
-		if (get_1284_register(pp, 1, NULL))
-			break;
-		if (priv->reg[0] & 0x01) {
-			clear_epp_timeout(pp);
-			break;
-		}
-	}
-	change_mode(pp, ECR_PS2);
-	return written;
-}
-
-static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buffer, size_t len, int flags)
-{
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	int rlen;
-	int i;
-
-	if (!usbdev)
-		return 0;
-	if (change_mode(pp, ECR_ECP))
-		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
-	if (i)
-		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
-	change_mode(pp, ECR_PS2);
-	return rlen;
-}
-
-static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, size_t len, int flags)
-{
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	int rlen;
-	int i;
-
-	if (!usbdev)
-		return 0;
-	if (change_mode(pp, ECR_ECP))
-		return 0;
-	i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, HZ*20);
-	if (i)
-		printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %Zu rlen %u\n", buffer, len, rlen);
-	change_mode(pp, ECR_PS2);
-	return rlen;
-}
-
-static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags)
-{
-	size_t written = 0;
-
-	if (change_mode(pp, ECR_ECP))
-		return 0;
-	for (; written < len; written++) {
-		if (set_1284_register(pp, 5, *(char *)buffer))
-			break;
-		((char*)buffer)++;
-	}
-	change_mode(pp, ECR_PS2);
-	return written;
-}
-
-static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer, size_t len, int flags)
-{
-	struct parport_uss720_private *priv = pp->private_data;
-	struct usb_device *usbdev = priv->usbdev;
-	int rlen;
-	int i;
-
-	if (!usbdev)
-		return 0;
-	if (change_mode(pp, ECR_PPF))
-		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
-	if (i)
-		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
-	change_mode(pp, ECR_PS2);
-	return rlen;
-}
-
-void parport_uss720_inc_use_count(void)
-{
-	MOD_INC_USE_COUNT;
-}
-
-void parport_uss720_dec_use_count(void)
-{
-	MOD_DEC_USE_COUNT;
-}
-
-/* --------------------------------------------------------------------- */
-
-static struct parport_operations parport_uss720_ops = 
-{
-	parport_uss720_write_data,
-	parport_uss720_read_data,
-
-	parport_uss720_write_control,
-	parport_uss720_read_control,
-	parport_uss720_frob_control,
-
-	parport_uss720_read_status,
-
-	parport_uss720_enable_irq,
-	parport_uss720_disable_irq,
-
-	parport_uss720_data_forward,
-	parport_uss720_data_reverse,
-
-	parport_uss720_init_state,
-	parport_uss720_save_state,
-	parport_uss720_restore_state,
-
-	parport_uss720_inc_use_count,
-	parport_uss720_dec_use_count,
-
-	parport_uss720_epp_write_data,
-	parport_uss720_epp_read_data,
-	parport_uss720_epp_write_addr,
-	parport_uss720_epp_read_addr,
-
-	parport_uss720_ecp_write_data,
-	parport_uss720_ecp_read_data,
-	parport_uss720_ecp_write_addr,
-
-	parport_uss720_write_compat,
-	parport_ieee1284_read_nibble,
-	parport_ieee1284_read_byte,
-};
-
-/* --------------------------------------------------------------------- */
-
-static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum,
-			   const struct usb_device_id *id)
-{
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	struct parport_uss720_private *priv;
-	struct parport *pp;
-	int i;
-
-	printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
-	       usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
-
-	/* our known interfaces have 3 alternate settings */
-	if (usbdev->actconfig->interface[ifnum].num_altsetting != 3)
-		return NULL;
-
-	i = usb_set_interface(usbdev, ifnum, 2);
-	printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
-
-	interface = &usbdev->actconfig->interface[ifnum].altsetting[2];
-
-	/*
-	 * Allocate parport interface 
-	 */
-	printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
-
-	if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
-		return NULL;
-	if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
-		printk(KERN_WARNING "usb-uss720: could not register parport\n");
-		goto probe_abort;
-	}
-
-	pp->private_data = priv;
-	priv->usbdev = usbdev;
-	pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
-
-	/* set the USS720 control register to manual mode, no ECP compression, enable all ints */
-	set_1284_register(pp, 7, 0x00);
-	set_1284_register(pp, 6, 0x30);  /* PS/2 mode */
-	set_1284_register(pp, 2, 0x0c);
-	/* debugging */
-	get_1284_register(pp, 0, NULL);
-	printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
-	       priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
-
-	endpoint = &interface->endpoint[2];
-	printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->bEndpointAddress, endpoint->bInterval);
-#if 0
-	priv->irqpipe = usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress);
-	i = usb_request_irq(usbdev, priv->irqpipe,
-				  uss720_irq, endpoint->bInterval,
-				  pp, &priv->irqhandle);
-	if (i) {
-		printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
-		goto probe_abort_port;
-	}
-#endif
-	parport_proc_register(pp);
-	parport_announce_port(pp);
-
-	MOD_INC_USE_COUNT;
-	return pp;
-
-#if 0
-probe_abort_port:
-	parport_unregister_port(pp);
-#endif
-probe_abort:
-	kfree(priv);
-	return NULL;
-}
-
-static void uss720_disconnect(struct usb_device *usbdev, void *ptr)
-{
-	struct parport *pp = (struct parport *)ptr;
-	struct parport_uss720_private *priv = pp->private_data;
-
-#if 0
-	usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
-	priv->usbdev = NULL;
-	parport_proc_unregister(pp);
-	parport_unregister_port(pp);
-	kfree(priv);
-	MOD_DEC_USE_COUNT;
-}
-
-/* table of cables that work through this driver */
-static struct usb_device_id uss720_table [] = {
-	{ USB_DEVICE(0x047e, 0x1001) },
-	{ USB_DEVICE(0x0557, 0x2001) },
-	{ USB_DEVICE(0x0729, 0x1284) },
-	{ USB_DEVICE(0x1293, 0x0002) },
-	{ }						/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, uss720_table);
-
-
-static struct usb_driver uss720_driver = {
-	name:		"uss720",
-	probe:		uss720_probe,
-	disconnect:	uss720_disconnect,
-	id_table:	uss720_table,
-};
-
-/* --------------------------------------------------------------------- */
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
-static int __init uss720_init(void)
-{
-	if (usb_register(&uss720_driver) < 0)
-		return -1;
-
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-static void __exit uss720_cleanup(void)
-{
-	usb_deregister(&uss720_driver);
-}
-
-module_init(uss720_init);
-module_exit(uss720_cleanup);
-
-/* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/vicam.c b/drivers/usb/vicam.c
--- a/drivers/usb/vicam.c	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,921 +0,0 @@
-/* -*- linux-c -*-
- * USB ViCAM driver
- *
- * Copyright (c) 2001 Christopher L Cheney (ccheney@cheney.cx)
- * Copyright (c) 2001 Pavel Machek (pavel@suse.cz) sponsored by SuSE
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- * This driver is for the Vista Imaging ViCAM and 3Com HomeConnect USB
- *
- * Thanks to Greg Kroah-Hartman for the USB Skeleton driver
- *
- * TODO:
- *	- find out the ids for the Vista Imaging ViCAM
- *
- * History:
- *
- * 2001_07_07 - 0.1 - christopher: first version
- * 2001_08_28 - 0.2 - pavel: messed it up, but for some fun, try 
- 			while true; do dd if=/dev/video of=/dev/fb0 bs=$[0x1e480] count=1 2> /dev/null; done
-		      yep, moving pictures.
- * 2001_08_29 - 0.3 - pavel: played a little bit more. Experimental mmap support. For some fun,
- 			get gqcam-0.9, compile it and run. Better than dd ;-).
- * 2001_08_29 - 0.4 - pavel: added shutter speed control (not much functional)
- 			kill update_params if it does not seem to work for you.
- * 2001_08_30 - 0.5 - pavel: fixed stupid bug with update_params & vicam_bulk
-
- *
- * FIXME: It crashes on rmmod with camera plugged.
- */
-#define DEBUG 1
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/usb.h>
-
-#include <asm/io.h>
-#include <linux/wrapper.h>
-#include <linux/vmalloc.h>
-
-#include <linux/videodev.h>
-
-#include "vicam.h"
-#include "vicamurbs.h"
-
-/* Version Information */
-#define DRIVER_VERSION "v0"
-#define DRIVER_AUTHOR "Christopher L Cheney <ccheney@cheney.cx>, Pavel Machek <pavel@suse.cz>"
-#define DRIVER_DESC "USB ViCAM Driver"
-
-/* Define these values to match your device */
-#define USB_VICAM_VENDOR_ID	0x04C1
-#define USB_VICAM_PRODUCT_ID	0x009D
-
-/* table of devices that work with this driver */
-static struct usb_device_id vicam_table [] = {
-	{ USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID) },
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, vicam_table);
-
-static int video_nr = -1; 		/* next avail video device */
-static struct usb_driver vicam_driver;
-
-static char *buf, *buf2;
-static volatile int change_pending = 0; 
-
-static int vicam_parameters(struct usb_vicam *vicam);
-
-/******************************************************************************
- *
- *  Memory management functions
- *
- *  Taken from bttv-drivers.c 2.4.7-pre3
- *
- ******************************************************************************/
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-	return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
-	mem=vmalloc_32(size);
-	if (mem)
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-		adr=(unsigned long) mem;
-		while (size > 0)
-		{
-			mem_map_reserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-	unsigned long adr;
-
-	if (mem)
-	{
-		adr=(unsigned long) mem;
-		while ((long) size > 0)
-		{
-			mem_map_unreserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-
-/******************************************************************************
- *
- *  Foo Bar
- *
- ******************************************************************************/
-
-/**
- *	usb_vicam_debug_data
- */
-static inline void usb_vicam_debug_data (const char *function, int size, const unsigned char *data)
-{
-	int i;
-
-	if (!debug)
-		return;
-
-	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
-		function, size);
-	for (i = 0; i < size; ++i) {
-		printk ("%.2x ", data[i]);
-	}
-	printk ("\n");
-}
-
-/*****************************************************************************
- *
- *  Send command to vicam
- *
- *****************************************************************************/
-
-static int vicam_sndctrl(int set, struct usb_vicam *vicam, unsigned short req,
-	unsigned short value, unsigned char *cp, int size)
-{
-	int ret;
-	unsigned char *transfer_buffer = kmalloc (size, GFP_KERNEL);
-
-	/* Needs to return data I think, works for sending though */
-	memcpy(transfer_buffer, cp, size);
-	
-	ret = usb_control_msg ( vicam->udev, set ? usb_sndctrlpipe(vicam->udev, 0) : usb_rcvctrlpipe(vicam->udev, 0), req, (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, 0, transfer_buffer, size, HZ);
-
-	kfree(transfer_buffer);
-	if (ret)
-		printk("vicam: error: %d\n", ret);
-	mdelay(100);
-	return ret;
-}
-
-
-/*****************************************************************************
- *
- *  Video4Linux Helpers
- * 
- *****************************************************************************/
-
-static int vicam_get_capability(struct usb_vicam *vicam, struct video_capability *b)
-{
-	dbg("vicam_get_capability");
-
-	strcpy(b->name, vicam->camera_name);
-	b->type = VID_TYPE_CAPTURE | VID_TYPE_MONOCHROME;
-	b->channels = 1;
-	b->audios = 0;
-
-	b->maxwidth = vicam->width[vicam->sizes-1];
-	b->maxheight = vicam->height[vicam->sizes-1];
-	b->minwidth = vicam->width[0];
-	b->minheight = vicam->height[0];
-
-	return 0;
-}
-		
-static int vicam_get_channel(struct usb_vicam *vicam, struct video_channel *v)
-{
-	dbg("vicam_get_channel");
-
-	if (v->channel != 0)
-		return -EINVAL;
- 
-	v->flags = 0;
-	v->tuners = 0;
-	v->type = VIDEO_TYPE_CAMERA;
-	strcpy(v->name, "Camera");
-
-	return 0;
-} 
-		
-static int vicam_set_channel(struct usb_vicam *vicam, struct video_channel *v)
-{
-	dbg("vicam_set_channel");
-
-	if (v->channel != 0)
-		return -EINVAL;
-	
-	return 0;
-}
-		
-static int vicam_get_mmapbuffer(struct usb_vicam *vicam, struct video_mbuf *vm)
-{
-	int i;
-
-	dbg("vicam_get_mmapbuffer");
-
-	memset(vm, 0, sizeof(vm));
-	vm->size = VICAM_NUMFRAMES * vicam->maxframesize;
-	vm->frames = VICAM_NUMFRAMES;
-
-	for (i=0; i<VICAM_NUMFRAMES; i++)
-		vm->offsets[i] = vicam->maxframesize * i;
-
-	return 0;
-}
-
-static int vicam_get_picture(struct usb_vicam *vicam, struct video_picture *p)
-{
-	dbg("vicam_get_picture");
-
-	/* This is probably where that weird 0x56 call goes */
-	p->brightness = vicam->win.brightness;
-	p->hue = vicam->win.hue;
-	p->colour = vicam->win.colour;
-	p->contrast = vicam->win.contrast;
-	p->whiteness = vicam->win.whiteness;
-	p->depth = vicam->win.depth;
-	p->palette = vicam->win.palette;
-
-	return 0;
-}
-
-static void synchronize(struct usb_vicam *vicam)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	change_pending = 1;
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&vicam->wait, &wait);
-	if (change_pending)
-		schedule();
-	remove_wait_queue(&vicam->wait, &wait);
-	set_current_state(TASK_RUNNING);
-	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
-	mdelay(10);
-	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
-	mdelay(10);
-}
-
-static void params_changed(struct usb_vicam *vicam)
-{
-#if 1
-	synchronize(vicam);
-	mdelay(10);
-	vicam_parameters(vicam);
-	printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
-#endif
-}
-
-static int vicam_set_picture(struct usb_vicam *vicam, struct video_picture *p)
-{
-	int changed = 0;
-	info("vicam_set_picture (%d)", p->brightness);
-
-
-#define SET(x) \
-	if (vicam->win.x != p->x) \
-		vicam->win.x = p->x, changed = 1;
-	SET(brightness);
-	SET(hue);
-	SET(colour);
-	SET(contrast);
-	SET(whiteness);
-	SET(depth);
-	SET(palette);
-	if (changed)
-		params_changed(vicam);
-
-	return 0;
-	/* Investigate what should be done maybe 0x56 type call */
-	if (p->depth != 8) return 1;
-	if (p->palette != VIDEO_PALETTE_GREY) return 1;
-
-	return 0;
-}
-
-/* FIXME - vicam_sync_frame - important */
-static int vicam_sync_frame(struct usb_vicam *vicam, int frame)
-{
-	dbg("vicam_sync_frame");
-
-	if(frame <0 || frame >= VICAM_NUMFRAMES)
-		return -EINVAL;
-
-	/* Probably need to handle various cases */
-/*	ret=vicam_newframe(vicam, frame);
-	vicam->frame[frame].grabstate=FRAME_UNUSED;
-*/
-	return 0;
-}
-	
-static int vicam_get_window(struct usb_vicam *vicam, struct video_window *vw)
-{
-	dbg("vicam_get_window");
-
-	vw->x = 0;
-	vw->y = 0;
-	vw->chromakey = 0;
-	vw->flags = 0;
-	vw->clipcount = 0;
-	vw->width = vicam->win.width;
-	vw->height = vicam->win.height;
-
-	return 0;
-}
-
-static int vicam_set_window(struct usb_vicam *vicam, struct video_window *vw)
-{
-	info("vicam_set_window");
-		
-	if (vw->flags)
-		return -EINVAL;
-	if (vw->clipcount)
-		return -EINVAL;
-
-	if (vicam->win.width == vw->width && vicam->win.height == vw->height)
-		return 0;
-
-	/* Pick largest mode that is smaller than specified res */
-	/* If specified res is too small reject                 */
-
-	/* Add urb send to device... */
-
-	vicam->win.width = vw->width;
-	vicam->win.height = vw->height;
-	params_changed(vicam);
-
-	return 0;
-}
-
-/* FIXME - vicam_mmap_capture - important */
-static int vicam_mmap_capture(struct usb_vicam *vicam, struct video_mmap *vm)
-{
-	dbg("vicam_mmap_capture");
-
-	/* usbvideo.c looks good for using here */
-
-	/* 
-	if (vm->frame >= VICAM_NUMFRAMES)
-		return -EINVAL;
-	if (vicam->frame[vm->frame].grabstate != FRAME_UNUSED)
-		return -EBUSY;
-	vicam->frame[vm->frame].grabstate=FRAME_READY;
-	*/
-
-	/* No need to vicam_set_window here according to Alan */
-
-	/*
-	if (!vicam->streaming)
-		vicam_start_stream(vicam);
-	*/
-
-	/* set frame as ready */
-
-	return 0;
-}
-
-/*****************************************************************************
- *
- *  Video4Linux
- * 
- *****************************************************************************/
-
-static int vicam_v4l_open(struct inode *inode, struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
-	int err = 0;
-	
-	dbg("vicam_v4l_open");
-	down(&vicam->sem);
-
-	vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES);
-	if (vicam->open_count) {
-		err = -EBUSY;
-	} else if (!vicam->fbuf) {
-		err =- ENOMEM;
-	} else {
-#ifdef BLINKING
-		vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
-		info ("led on");
-		vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
-#endif
-		vicam->open_count++;
-		file->private_data = vdev;
-	}
-
-	up(&vicam->sem);
-	return err;
-}
-
-static int vicam_v4l_close(struct inode *inode, struct file *file)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
-
-	dbg("vicam_v4l_close");
-	
-	down(&vicam->sem);
-
-#ifdef BLINKING
-	info ("led off");
-	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
-//	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on
-#endif
-
-	rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);
-	vicam->fbuf = 0;
-	vicam->open_count=0;
-	file->private_data = NULL;
-
-	up(&vicam->sem);
-	/* Why does se401.c have a usbdevice check here? */
-	/* If device is unplugged while open, I guess we only may unregister now */
-	return 0;
-}
-
-static int vicam_v4l_read(struct file *file, char *user_buf,
-			  size_t buflen, loff_t *ppos)
-{
-	struct video_device *vdev = file->private_data;
-	//struct usb_vicam *vicam = (struct usb_vicam *)vdev;
-
-	dbg("vicam_v4l_read(%d)", buflen);
-
-	if (!vdev || !buf)
-		return -EFAULT;
-
-	if (copy_to_user(user_buf, buf2, buflen))
-		return -EFAULT;
-	return buflen;
-}
-
-static int vicam_v4l_ioctl(struct inode *inode, struct file *file,
-			   unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
-	int ret = -EL3RST;
-
-	if (!vicam->udev)
-		return -EIO;
-
-	down(&vicam->sem);
-
-	switch (cmd) {
-	case VIDIOCGCAP:
-	{
-		struct video_capability *b = arg;
-		ret = vicam_get_capability(vicam,b);
-		dbg("name %s",b->name);
-		break;
-	}
-	case VIDIOCGFBUF:
-	{
-		struct video_buffer *vb = arg;
-		info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");
-		/* frame buffer not supported, not used */
-		memset(vb, 0, sizeof(*vb));
-		ret = 0;
-		break;
-	}
-	case VIDIOCGWIN:
-	{
-		struct video_window *vw = arg;
-		ret = vicam_get_window(vicam, vw);
-		break;
-	}
-	case VIDIOCSWIN:
-	{
-		struct video_window *vw = arg;
-		ret = vicam_set_window(vicam, vw);
-		break;
-	}
-	case VIDIOCGCHAN:
-	{
-		struct video_channel *v = arg;
-
-		ret = vicam_get_channel(vicam,v);
-		break;
-	}
-	case VIDIOCSCHAN:
-	{
-		struct video_channel *v = arg;
-		ret = vicam_set_channel(vicam,v);
-		break;
- 	}
-	case VIDIOCGPICT:
-	{
-		struct video_picture *p = arg;
-		ret = vicam_get_picture(vicam,p);
-		break;
-	}
-	case VIDIOCSPICT:
-	{
-		struct video_picture *p = arg;
-		ret = vicam_set_picture(vicam,p);
-		break;
-	}
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *vm = arg;
-		ret = vicam_get_mmapbuffer(vicam,vm);
-		break;
-	}
-	case VIDIOCMCAPTURE:
-	{
-		struct video_mmap *vm = arg;
-		ret = vicam_mmap_capture(vicam,vm);
-		break;
-	}
-	case VIDIOCSYNC:
-	{
-		int *frame = arg;
-		ret = vicam_sync_frame(vicam,*frame);
-		break;
-	}
-
-	case VIDIOCKEY:
-		ret = 0;
- 
-	case VIDIOCCAPTURE:
-	case VIDIOCSFBUF:
-	case VIDIOCGTUNER:
-	case VIDIOCSTUNER:
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-	case VIDIOCGAUDIO:
-	case VIDIOCSAUDIO:
-	case VIDIOCGUNIT:
-		ret = -EINVAL;
-
-	default:
-	{
-		info("vicam_v4l_ioctl - %ui",cmd);
-		ret = -ENOIOCTLCMD;
-	}
-	} /* end switch */
-
-	up(&vicam->sem);
-        return ret;
-}
-
-static int vicam_v4l_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *vdev = file->private_data;
-	struct usb_vicam *vicam = (struct usb_vicam *)vdev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
-
-	down(&vicam->sem);
-	
-	if (vicam->udev == NULL) {
-		up(&vicam->sem);
-		return -EIO;
-	}
-#if 0
-	if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
-		up(&vicam->sem);
-		return -EINVAL;
-	}
-#endif
-	pos = (unsigned long)vicam->fbuf;
-	while (size > 0) {
-		page = kvirt_to_pa(pos);
-		if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
-			up(&vicam->sem);
-			return -EAGAIN;
-		}
-		start += PAGE_SIZE;
-		pos += PAGE_SIZE;
-		if (size > PAGE_SIZE)
-			size -= PAGE_SIZE;
-		else
-			size = 0;
-	}
-	up(&vicam->sem);
-
-        return 0;
-}
-
-/* FIXME - vicam_template - important */
-static struct file_operations vicam_fops = {
-	owner:		THIS_MODULE,
-	open:		vicam_v4l_open,
-	release:       	vicam_v4l_close,
-	read:		vicam_v4l_read,
-	mmap:		vicam_v4l_mmap,
-	ioctl:		video_generic_ioctl,
-	llseek:         no_llseek,
-};
-static struct video_device vicam_template = {
-	owner:		THIS_MODULE,
-	name:		"vicam USB camera",
-	type:		VID_TYPE_CAPTURE,
-	hardware:	VID_HARDWARE_SE401, /* need to ask for own id */
-	fops:           &vicam_fops,
-	kernel_ioctl:	vicam_v4l_ioctl,
-};
-
-/******************************************************************************
- *
- *  Some Routines
- *
- ******************************************************************************/
-
-/*
-Flash the led
-vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
-info ("led on");
-vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
-info ("led off");
-vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);
-vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);
-*/
-
-static void vicam_bulk(struct urb *urb)
-{
-	struct usb_vicam *vicam = urb->context;
-
-	/*	if (!vicam || !vicam->dev || !vicam->used)
-		return;
-	*/
-
-	if (urb->status)
-		printk("vicam%d: nonzero read/write bulk status received: %d",
-			0, urb->status);
-
-	urb->actual_length = 0;
-	urb->dev = vicam->udev;
-
-	memcpy(buf2, buf+64, 0x1e480);
-	if (vicam->fbuf)
-		memcpy(vicam->fbuf, buf+64, 0x1e480);
-
-	if (!change_pending) {
-		if (usb_submit_urb(urb, GFP_ATOMIC))
-			dbg("failed resubmitting read urb");
-	} else {
-		change_pending = 0;
-		wake_up_interruptible(&vicam->wait);
-	}
-}
-
-static int vicam_parameters(struct usb_vicam *vicam)
-{
-	unsigned char req[0x10];
-	unsigned int shutter;
-	shutter = 10;
-
-	switch (vicam->win.width) {
-	case 512:
-	default:
-		memcpy(req, s512x242bw, 0x10);
-		break;
-	case 256:
-		memcpy(req, s256x242bw, 0x10);
-		break;
-	case 128:
-		memcpy(req, s128x122bw, 0x10);
-		break;
-	}
-
-
-	mdelay(10);
-	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);
-	info ("led on");
-	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);
-
-	mdelay(10);
-
-	shutter = vicam->win.contrast / 256;
-	if (shutter == 0)
-		shutter = 1;
-	printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );
-	req[0] = vicam->win.brightness /256;
-	shutter = 15600/shutter - 1;
-	req[6] = shutter & 0xff;
-	req[7] = (shutter >> 8) & 0xff;
-	vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);
-	mdelay(10);
-	vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);
-	mdelay(10);
-
-	return 0;
-}
-
-static int vicam_init(struct usb_vicam *vicam)
-{
-	int width[] = {128, 256, 512};
-	int height[] = {122, 242, 242};
-
-	dbg("vicam_init");
-	buf = kmalloc(0x1e480, GFP_KERNEL);
-	buf2 = kmalloc(0x1e480, GFP_KERNEL);
-	if ((!buf) || (!buf2)) {
-		printk("Not enough memory for vicam!\n");
-		goto error;
-	}
-
-	/* do we do aspect correction in kernel or not? */
-	vicam->sizes = 3;
-	vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
-	vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);
-	memcpy(vicam->width, &width, sizeof(width));
-	memcpy(vicam->height, &height, sizeof(height));
-	vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];
-
-	/* Download firmware to camera */
-	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));
-	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));
-	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
-	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));
-	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));
-	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));
-
-	vicam_parameters(vicam);
-
-	FILL_BULK_URB(vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),
-		      buf, 0x1e480, vicam_bulk, vicam);
-	printk(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));
-
-	return 0;
-error:
-	if (buf)
-		kfree(buf);
-	if (buf2)
-		kfree(buf2);
-	return 1;
-}
-
-static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,
-	const struct usb_device_id *id)
-{
-	struct usb_vicam *vicam;
-	char *camera_name=NULL;
-
-	dbg("vicam_probe");
-
-	/* See if the device offered us matches what we can accept */
-	if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
-	    (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
-		return NULL;
-	}
-	
-	camera_name="3Com HomeConnect USB";
-	info("ViCAM camera found: %s", camera_name);
-	
-	vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);
-	if (vicam == NULL) {
-		err ("couldn't kmalloc vicam struct");
-		return NULL;
-	}
-	memset(vicam, 0, sizeof(*vicam));
-
-	vicam->readurb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!vicam->readurb) {
-		kfree(vicam);
-		return NULL;
-	}
-
-	vicam->udev = udev;
-	vicam->camera_name = camera_name;
-	vicam->win.brightness = 128;
-	vicam->win.contrast = 10;
-
-	/* FIXME */
-	if (vicam_init(vicam)) {
-		usb_free_urb(vicam->readurb);
-		kfree(vicam);
-		return NULL;
-	}
-	memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));
-	memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));
-	
-	if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
-		err("video_register_device");
-		usb_free_urb(vicam->readurb);
-		kfree(vicam);
-		return NULL;
-	}
-
-	info("registered new video device: video%d", vicam->vdev.minor);
-	
-	init_MUTEX (&vicam->sem);
-	init_waitqueue_head(&vicam->wait);
-	
-	return vicam;
-}
-
-
-/* FIXME - vicam_disconnect - important */
-static void vicam_disconnect(struct usb_device *udev, void *ptr)
-{
-	struct usb_vicam *vicam;
-
-	vicam = (struct usb_vicam *) ptr;
-
-	video_unregister_device(&vicam->vdev);
-	vicam->udev = NULL;
-/*
-	vicam->frame[0].grabstate = FRAME_ERROR;
-	vicam->frame[1].grabstate = FRAME_ERROR;
-*/
-
-	/* Free buffers and shit */
-
-	info("%s disconnected", vicam->camera_name);
-	synchronize(vicam);
-
-	if (!vicam->open_count) {
-		/* Other random junk */
-		usb_free_urb(vicam->readurb);
-		kfree(vicam);
-		vicam = NULL;
-	}
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver vicam_driver = {
-	owner:		THIS_MODULE,
-	name:		"vicam",
-	probe:		vicam_probe,
-	disconnect:	vicam_disconnect,
-	id_table:	vicam_table,
-};
-
-/******************************************************************************
- *
- *  Module Routines
- *
- ******************************************************************************/
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-/* Module paramaters */
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-static int __init usb_vicam_init(void)
-{
-	int result;
-
-	printk("VICAM: initializing\n");
-	/* register this driver with the USB subsystem */
-	result = usb_register(&vicam_driver);
-	if (result < 0) {
-		err("usb_register failed for the "__FILE__" driver. Error number %d",
-		    result);
-		return -1;
-	}
-
-	info(DRIVER_VERSION " " DRIVER_AUTHOR);
-	info(DRIVER_DESC);
-	return 0;
-}
-
-static void __exit usb_vicam_exit(void)
-{
-	/* deregister this driver with the USB subsystem */
-	usb_deregister(&vicam_driver);
-}
-
-module_init(usb_vicam_init);
-module_exit(usb_vicam_exit);
-
diff -Nru a/drivers/usb/vicam.h b/drivers/usb/vicam.h
--- a/drivers/usb/vicam.h	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,81 +0,0 @@
-/*
- *
- * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
- * Christopher L Cheney (C) 2001
- * 
- */
-
-#ifndef __LINUX_VICAM_H
-#define __LINUX_VICAM_H
-
-
-#ifdef CONFIG_USB_DEBUG
-	static int debug = 1;
-#else
-	static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
-
-#define VICAM_NUMFRAMES 30
-#define VICAM_NUMSBUF 1
-
-/* USB REQUEST NUMBERS */
-#define VICAM_REQ_VENDOR	0xff
-#define VICAM_REQ_CAMERA_POWER	0x50
-#define VICAM_REQ_CAPTURE	0x51
-#define VICAM_REQ_LED_CONTROL	0x55
-#define VICAM_REQ_GET_SOMETHIN	0x56
- 
-/* not required but lets you know camera is on */
-/* camera must be on to turn on led */
-/* 0x01 always on  0x03 on when picture taken (flashes) */
-
-struct picture_parm
-{
-	int width;
-	int height;
-	int brightness;
-	int hue;
-	int colour;
-	int contrast;
-	int whiteness;
-	int depth;
-	int palette;
-};
-
-struct vicam_scratch {
-        unsigned char *data;
-        volatile int state;
-        int offset;
-        int length;
-};
-
-/* Structure to hold all of our device specific stuff */
-struct usb_vicam
-{
-	struct video_device vdev;
-	struct usb_device *udev;
-
-	int open_count;	/* number of times this port has been opened */
-	struct semaphore sem;			/* locks this structure */
-	wait_queue_head_t wait;			/* Processes waiting */ 
-
-	int streaming;
-
-	/* v4l stuff */
-	char *camera_name;
-	char *fbuf;
-	struct urb *urb[VICAM_NUMSBUF];
-	int sizes;
-	int *width;
-	int *height;
-	int maxframesize;
-	struct picture_parm win;
-	struct proc_dir_entry *proc_entry;      /* /proc/se401/videoX */
-	struct urb *readurb;
-};
-
-#endif
diff -Nru a/drivers/usb/vicamurbs.h b/drivers/usb/vicamurbs.h
--- a/drivers/usb/vicamurbs.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,330 +0,0 @@
-/*
- *
- * Vista Imaging ViCAM / 3Com HomeConnect Usermode Driver
- * Christopher L Cheney (C) 2001
- * 
- */
-
-
-#ifndef __LINUX_VICAMURBS_H
-#define __LINUX_VICAMURBS_H
-
-/* -------------------------------------------------------------------------- */
-
-/* FIXME - Figure out transfers so that this doesn't need to be here
- *
- * Notice: in pieces below, "0" means other code will fill it while "0x00" means this is zero */
-
-/* Request 0x51 Image Setup */
-
-/* 128x98 ? 0x3180 size */
-static unsigned char s128x98bw[] = {
-  0,    0x34, 0xC4, 0x00, 0x00, 0x00, 0,    0,
-  0x18, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* 128x122 3D80 size */
-static unsigned char s128x122bw[] = {
-  0,    0x34, 0xF4, 0x00, 0x00, 0x00, 0,    0,
-  0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* 256x242 ? 0xF280 size */
-static unsigned char s256x242bw[] = {
-  0,    0x03, 0xC8, 0x03, 0x00, 0x00, 0,    0,
-  0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* 512x242 0x1E480 size */
-static unsigned char s512x242bw[] = {
-  0,    0x05, 0x90, 0x07, 0x00, 0x00, 0,    0,
-  0x00, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00
-};
-
-/* In s512x242:
-   byte 0: gain -- higher number means brighter image
-   byte 6, 7: shutter speed, little-endian; set this to 15600 * (shutter speed) - 1. (Where shutter speed is something like 1/1000).
-*/
-
-/* -------------------------------------------------------------------------- */
-
-static unsigned char fsetup[] = {
-  0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64,
-
-  0x00, 0x00
-};
-
-static unsigned char firmware1[] = {
-  0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64,
-
-  0xE7, 0x67, 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09,
-  0xDE, 0x00, 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03,
-  0xC0, 0x17, 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07,
-  0x00, 0x00, 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
-};
-
-static unsigned char findex1[] = {
-  0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64,
-
-  0x18, 0x00, 0x00, 0x00
-};
-
-static unsigned char firmware2[] = {
-  0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64,
-
-  0xE7, 0x07, 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07,
-  0x00, 0x00, 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01,
-  0xAA, 0x00, 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00,
-  0xE7, 0x07, 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07,
-  0x7C, 0x00, 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00,
-  0x18, 0x00, 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0,
-  0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07,
-  0xFF, 0xFF, 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00,
-  0x24, 0xC0, 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0,
-  0xE7, 0x07, 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87,
-  0x01, 0x00, 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09,
-  0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0,
-  0x09, 0xC1, 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01,
-  0xE7, 0x09, 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07,
-  0x07, 0x00, 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0,
-  0xC0, 0xDF, 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00,
-  0x17, 0x02, 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77,
-  0x01, 0x00, 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57,
-  0xFF, 0xFF, 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57,
-  0x00, 0x00, 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF,
-  0xC6, 0x00, 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05,
-  0xC1, 0x05, 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF,
-  0x27, 0xDA, 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00,
-  0x0B, 0x06, 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01,
-  0x9F, 0xAF, 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09,
-  0xFC, 0x05, 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06,
-  0x26, 0x01, 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0,
-  0xE7, 0x09, 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09,
-  0x02, 0x06, 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06,
-  0xFC, 0x05, 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06,
-  0x27, 0xDA, 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00,
-  0xFA, 0x05, 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF,
-  0x9F, 0xAF, 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07,
-  0x40, 0x00, 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05,
-  0x9F, 0xAF, 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17,
-  0x02, 0x00, 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06,
-  0x9F, 0xA0, 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00,
-  0x09, 0x06, 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57,
-  0x01, 0x00, 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03,
-  0xE7, 0x07, 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF,
-  0x47, 0xAF, 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07,
-  0x2E, 0x00, 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00,
-  0x09, 0x06, 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00,
-  0xC0, 0x57, 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02,
-  0xC0, 0x57, 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57,
-  0x55, 0x00, 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00,
-  0x9F, 0xC0, 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02,
-  0xC1, 0x0B, 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90,
-  0x08, 0x06, 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B,
-  0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF,
-  0x2F, 0x0E, 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07,
-  0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF,
-  0x28, 0x05, 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E,
-  0x02, 0x00, 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00,
-  0x09, 0x06, 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67,
-  0x7F, 0xFF, 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD,
-  0x22, 0xC0, 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0,
-  0xE7, 0x87, 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF,
-  0xB8, 0x05, 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0,
-  0x9F, 0xAF, 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00,
-  0x24, 0xC0, 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0,
-  0xC8, 0x07, 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00,
-  0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
-  0x9F, 0xAF, 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00,
-  0x9F, 0xAF, 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE,
-  0x24, 0xC0, 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87,
-  0x00, 0x01, 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02,
-  0x0F, 0xC1, 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0,
-  0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
-  0x08, 0x00, 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1,
-  0xEF, 0x07, 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF,
-  0xEF, 0x07, 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF,
-  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07,
-  0x00, 0x00, 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF,
-  0x09, 0x06, 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06,
-  0xE7, 0x67, 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67,
-  0x17, 0xD8, 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00,
-  0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0,
-  0x97, 0xCF, 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF,
-  0xDA, 0x02, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
-  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
-  0x0E, 0x06, 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02,
-  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
-  0x00, 0x80, 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C,
-  0x02, 0x00, 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00,
-  0x06, 0x06, 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05,
-  0xE7, 0x07, 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07,
-  0xE2, 0x05, 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02,
-  0xF8, 0x05, 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07,
-  0x00, 0x80, 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF,
-  0x66, 0x04, 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF,
-  0x97, 0xCF, 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B,
-  0x0C, 0x06, 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05,
-  0xC0, 0x07, 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05,
-  0x68, 0x00, 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF,
-  0x44, 0x05, 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00,
-  0xE0, 0x07, 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06,
-  0xE8, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02,
-  0xE0, 0x07, 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF,
-  0x97, 0xCF, 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05,
-  0xEF, 0x07, 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07,
-  0x0E, 0x06, 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06,
-  0xFE, 0x05, 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01,
-  0xE7, 0x07, 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07,
-  0x07, 0x00, 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07,
-  0x02, 0x00, 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01,
-  0xEF, 0x77, 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0,
-  0x14, 0x04, 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06,
-  0x37, 0xC0, 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06,
-  0x0F, 0xC1, 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06,
-  0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
-  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00,
-  0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05,
-  0xC8, 0x07, 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05,
-  0xC0, 0x07, 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05,
-  0xC1, 0x77, 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA,
-  0x75, 0xC1, 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1,
-  0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00,
-  0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00,
-  0x06, 0x06, 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00,
-  0xC1, 0x07, 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05,
-  0xEF, 0x07, 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF,
-  0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57,
-  0x01, 0x00, 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07,
-  0x01, 0x00, 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF,
-  0x28, 0x05, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
-  0x30, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
-  0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
-  0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67,
-  0x03, 0x00, 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0,
-  0x08, 0xDA, 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00,
-  0xC1, 0x07, 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00,
-  0x06, 0x06, 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00,
-  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00,
-  0xC1, 0x0B, 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05,
-  0xC0, 0x07, 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05,
-  0xE7, 0x09, 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8,
-  0xFA, 0x05, 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05,
-  0xE7, 0x07, 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07,
-  0x40, 0x00, 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05,
-  0x9F, 0xAF, 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B,
-  0xE2, 0x05, 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17,
-  0x23, 0x00, 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07,
-  0x04, 0x00, 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF,
-  0x28, 0x05, 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09,
-  0xE6, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
-  0x07, 0x00, 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1,
-  0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00,
-  0xC1, 0x09, 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05,
-  0xC0, 0x07, 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05,
-  0xC1, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
-  0x0D, 0x00, 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF,
-  0x28, 0x05, 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07,
-  0x32, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
-  0x0F, 0x00, 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF,
-  0x28, 0x05, 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9,
-  0x24, 0xC0, 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00,
-  0xC0, 0x67, 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0,
-  0xE7, 0x87, 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67,
-  0xFF, 0xF9, 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA,
-  0x72, 0xC1, 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0,
-  0x97, 0xCF, 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87,
-  0xFF, 0x00, 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF,
-  0x24, 0xC0, 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0,
-  0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF,
-  0x9F, 0xAF, 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0,
-  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
-  0x40, 0x00, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
-  0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05,
-  0xE7, 0x67, 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67,
-  0xFF, 0xFE, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
-  0x24, 0xC0, 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87,
-  0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07,
-  0x40, 0x00, 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67,
-  0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
-  0x24, 0xC0, 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0,
-  0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA,
-  0xE8, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00,
-  0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
-  0x00, 0xDA, 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1,
-  0xE7, 0x87, 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF,
-  0xE7, 0x07, 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77,
-  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
-  0xE7, 0x07, 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77,
-  0x00, 0x80, 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF,
-  0x09, 0x02, 0x19, 0x00, 0x01, 0x01, 0x00, 0x80,
-  0x96, 0x09, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char findex2[] = {
-  0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64,
-
-  0x0E, 0x00, 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00,
-  0x26, 0x00, 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00,
-  0x92, 0x00, 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00,
-  0xB8, 0x00, 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00,
-  0xCE, 0x00, 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00,
-  0xE0, 0x00, 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00,
-  0xEC, 0x00, 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01,
-  0x0A, 0x01, 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01,
-  0x22, 0x01, 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01,
-  0x36, 0x01, 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01,
-  0x72, 0x01, 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01,
-  0x88, 0x01, 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01,
-  0xA0, 0x01, 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01,
-  0xB4, 0x01, 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01,
-  0xF6, 0x01, 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02,
-  0x3C, 0x02, 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02,
-  0x56, 0x02, 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02,
-  0x84, 0x02, 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02,
-  0x8E, 0x02, 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02,
-  0xAE, 0x02, 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02,
-  0xC0, 0x02, 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02,
-  0xD4, 0x02, 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02,
-  0xF8, 0x02, 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03,
-  0x24, 0x03, 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03,
-  0x3C, 0x03, 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03,
-  0x58, 0x03, 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03,
-  0x7A, 0x03, 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03,
-  0xB2, 0x03, 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03,
-  0xD4, 0x03, 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03,
-  0xFC, 0x03, 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04,
-  0x32, 0x04, 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04,
-  0x42, 0x04, 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04,
-  0x54, 0x04, 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04,
-  0x62, 0x04, 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04,
-  0x80, 0x04, 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04,
-  0x9A, 0x04, 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04,
-  0xB4, 0x04, 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04,
-  0x2A, 0x05, 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
-};
-
-#endif
diff -Nru a/drivers/usb/wacom.c b/drivers/usb/wacom.c
--- a/drivers/usb/wacom.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,450 +0,0 @@
-/*
- * $Id: wacom.c,v 1.28 2001/09/25 10:12:07 vojtech Exp $
- *
- *  Copyright (c) 2000-2001 Vojtech Pavlik	<vojtech@ucw.cz>
- *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
- *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
- *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
- *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
- *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
- *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
- *
- *  USB Wacom Graphire and Wacom Intuos tablet support
- *
- *  ChangeLog:
- *      v0.1 (vp)  - Initial release
- *      v0.2 (aba) - Support for all buttons / combinations
- *      v0.3 (vp)  - Support for Intuos added
- *	v0.4 (sm)  - Support for more Intuos models, menustrip
- *			relative mode, proximity.
- *	v0.5 (vp)  - Big cleanup, nifty features removed,
- * 			they belong in userspace
- *	v1.8 (vp)  - Submit URB only when operating, moved to CVS,
- *			use input_report_key instead of report_btn and
- *			other cleanups
- *	v1.11 (vp) - Add URB ->dev setting for new kernels
- *	v1.11 (jb) - Add support for the 4D Mouse & Lens
- *	v1.12 (de) - Add support for two more inking pen IDs
- *	v1.14 (vp) - Use new USB device id probing scheme.
- *		     Fix Wacom Graphire mouse wheel
- *	v1.18 (vp) - Fix mouse wheel direction
- *		     Make mouse relative
- *      v1.20 (fl) - Report tool id for Intuos devices
- *                 - Multi tools support
- *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
- *                 - Add PL models support
- *		   - Fix Wacom Graphire mouse wheel again
- *	v1.21 (vp) - Removed protocol descriptions
- *		   - Added MISC_SERIAL for tool serial numbers
- *	      (gb) - Identify version on module load.
- */
-
-/*
- * This program is free software; you can redistribute it and/or 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/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.21"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-#define USB_VENDOR_ID_WACOM	0x056a
-
-struct wacom_features {
-	char *name;
-	int pktlen;
-	int x_max;
-	int y_max;
-	int pressure_max;
-	int distance_max;
-	void (*irq)(struct urb *urb);
-	unsigned long evbit;
-	unsigned long absbit;
-	unsigned long relbit;
-	unsigned long btnbit;
-	unsigned long digibit;
-};
-
-struct wacom {
-	signed char data[10];
-	struct input_dev dev;
-	struct usb_device *usbdev;
-	struct urb *irq;
-	struct wacom_features *features;
-	int tool[2];
-	int open;
-	int x, y;
-	__u32 serial[2];
-	char phys[32];
-};
-
-static void wacom_pl_irq(struct urb *urb)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
-	int prox;
-
-	if (urb->status) return;
-
-	if (data[0] != 2)
-		dbg("received unknown report #%d", data[0]);
-
-	prox = data[1] & 0x20;
-	
-	input_report_key(dev, BTN_TOOL_PEN, prox);
-	
-	if (prox) {
-		int pressure = (data[4] & 0x04) >> 2 | ((__u32)(data[7] & 0x7f) << 1);
-
-		input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 8) | ((__u32)(data[1] & 0x03) << 16));
-		input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 8) | ((__u32)(data[4] & 0x03) << 8));
-		input_report_abs(dev, ABS_PRESSURE, (data[7] & 0x80) ? (255 - pressure) : (pressure + 255));
-		input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
-		input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
-		input_report_key(dev, BTN_STYLUS2, data[4] & 0x20);
-	}
-	
-	input_event(dev, EV_MSC, MSC_SERIAL, 0);
-}
-
-static void wacom_graphire_irq(struct urb *urb)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
-	int x, y;
-
-	if (urb->status) return;
-
-	if (data[0] != 2)
-		dbg("received unknown report #%d", data[0]);
-
-	x = data[2] | ((__u32)data[3] << 8);
-	y = data[4] | ((__u32)data[5] << 8);
-
-	switch ((data[1] >> 5) & 3) {
-
-		case 0:	/* Pen */
-			input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80);
-			break;
-
-		case 1: /* Rubber */
-			input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
-			break;
-
-		case 2: /* Mouse */
-			input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24);
-			input_report_key(dev, BTN_LEFT, data[1] & 0x01);
-			input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
-			input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
-			input_report_abs(dev, ABS_DISTANCE, data[7]);
-			input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
-
-			input_report_abs(dev, ABS_X, x);
-			input_report_abs(dev, ABS_Y, y);
-
-			input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
-			return;
-	}
-
-	if (data[1] & 0x80) {
-		input_report_abs(dev, ABS_X, wacom->x = x);
-		input_report_abs(dev, ABS_Y, wacom->y = y);
-	}
-
-	input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
-	input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-	input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
-
-	input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
-}
-
-static void wacom_intuos_irq(struct urb *urb)
-{
-	struct wacom *wacom = urb->context;
-	unsigned char *data = wacom->data;
-	struct input_dev *dev = &wacom->dev;
-	unsigned int t;
-	int idx;
-
-	if (urb->status) return;
-
-	if (data[0] != 2)
-		dbg("received unknown report #%d", data[0]);
-
-	/* tool number */
-	idx = data[1] & 0x01;
-
-	if ((data[1] & 0xfc) == 0xc0) {						/* Enter report */
-
-		wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 4) +		/* serial number of the tool */
-			((__u32)data[4] << 16) + ((__u32)data[5] << 12) +
-			((__u32)data[6] << 4) + (data[7] >> 4);
-
-		switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
-			case 0x832:
-			case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL;		break;	/* Inking pen */
-			case 0x822:
-			case 0x022: wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Pen */
-			case 0x812:
-			case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH;		break;	/* Stroke pen */
-		        case 0x09c:
-			case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE;		break;	/* Mouse 4D */
-			case 0x096: wacom->tool[idx] = BTN_TOOL_LENS;		break;	/* Lens cursor */
-			case 0x82a:
-		        case 0x91a:
-			case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER;		break;	/* Eraser */
-			case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH;	break;	/* Airbrush */
-			default:    wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Unknown tool */
-		}	
-
-		input_report_key(dev, wacom->tool[idx], 1);
-		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-		return;
-	}
-
-	if ((data[1] & 0xfe) == 0x80) {						/* Exit report */
-		input_report_key(dev, wacom->tool[idx], 0);
-		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-		return;
-	}
-
-	input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
-	input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
-	input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
-
-	if ((data[1] & 0xb8) == 0xa0) {						/* general pen packet */
-		input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
-		input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-		input_report_key(dev, BTN_STYLUS, data[1] & 2);
-		input_report_key(dev, BTN_STYLUS2, data[1] & 4);
-		input_report_key(dev, BTN_TOUCH, t > 10);
-	}
-
-	if ((data[1] & 0xbc) == 0xb4) {						/* airbrush second packet */
-		input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
-		input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-	}
-	
-	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {		/* 4D mouse or Lens cursor packets */
-
-		if (data[1] & 0x02) {						/* Rotation packet */
-
-			input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
-					 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3):
-					 (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1);
-
-		} else {
-
-			input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-			input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-			input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-
-	 		if ((data[1] & 0x10) == 0) {				/* 4D mouse packets */
-
-				input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
-				input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
-				input_report_abs(dev, ABS_THROTTLE,  (data[8] & 0x08) ?
-						 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
-						 -((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
-
-			} else {						/* Lens cursor packets */
-
-				input_report_key(dev, BTN_SIDE,   data[8] & 0x10);
-				input_report_key(dev, BTN_EXTRA,  data[8] & 0x08);
-			}
-		}
-	}
-	
-	input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-}
-
-#define WACOM_INTUOS_TOOLS	(BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS))
-#define WACOM_INTUOS_BUTTONS	(BIT(BTN_SIDE) | BIT(BTN_EXTRA))
-#define WACOM_INTUOS_ABS	(BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE))
-
-struct wacom_features wacom_features[] = {
-	{ "Wacom Graphire",      8, 10206,  7422,  511, 32, wacom_graphire_irq,
-		BIT(EV_REL), 0, BIT(REL_WHEEL), 0 },
-	{ "Wacom Intuos 4x5",   10, 12700, 10360, 1023, 15, wacom_intuos_irq,
-		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
-	{ "Wacom Intuos 6x8",   10, 20320, 15040, 1023, 15, wacom_intuos_irq,
-		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
-	{ "Wacom Intuos 9x12",  10, 30480, 23060, 1023, 15, wacom_intuos_irq,
-		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
-	{ "Wacom Intuos 12x12", 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
-		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
-	{ "Wacom Intuos 12x18", 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
-		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
-	{ "Wacom PL500",        8,  12328, 9256,   511, 32, wacom_pl_irq,
-		0,  0, 0, 0 },
-	{ NULL , 0 }
-};
-
-struct usb_device_id wacom_ids[] = {
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), driver_info: 0 },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), driver_info: 1 },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), driver_info: 2 },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 3 },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 4 },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 5 },
-	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 6 },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, wacom_ids);
-
-static int wacom_open(struct input_dev *dev)
-{
-	struct wacom *wacom = dev->private;
-
-	if (wacom->open++)
-		return 0;
-
-	wacom->irq->dev = wacom->usbdev;
-	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
-		return -EIO;
-
-	return 0;
-}
-
-static void wacom_close(struct input_dev *dev)
-{
-	struct wacom *wacom = dev->private;
-
-	if (!--wacom->open)
-		usb_unlink_urb(wacom->irq);
-}
-
-static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
-{
-	struct usb_endpoint_descriptor *endpoint;
-	struct wacom *wacom;
-	char path[64];
-
-	if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
-	memset(wacom, 0, sizeof(struct wacom));
-
-	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!wacom->irq) {
-		kfree(wacom);
-		return NULL;
-	}
-
-	wacom->features = wacom_features + id->driver_info;
-
-	wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) | wacom->features->evbit;
-	wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | wacom->features->absbit;
-	wacom->dev.relbit[0] |= wacom->features->relbit;
-	wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | wacom->features->btnbit;
-	wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) |
-		BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit;
-	wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
-
-	wacom->dev.absmax[ABS_X] = wacom->features->x_max;
-	wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
-	wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
-	wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
-	wacom->dev.absmax[ABS_TILT_X] = 127;
-	wacom->dev.absmax[ABS_TILT_Y] = 127;
-	wacom->dev.absmax[ABS_WHEEL] = 1023;
-
-	wacom->dev.absmin[ABS_RZ] = -900;
-	wacom->dev.absmax[ABS_RZ] = 899;
-	wacom->dev.absmin[ABS_THROTTLE] = -1023;
-	wacom->dev.absmax[ABS_THROTTLE] = 1023;
-
-	wacom->dev.absfuzz[ABS_X] = 4;
-	wacom->dev.absfuzz[ABS_Y] = 4;
-
-	wacom->dev.private = wacom;
-	wacom->dev.open = wacom_open;
-	wacom->dev.close = wacom_close;
-
-	usb_make_path(dev, path, 64);
-	sprintf(wacom->phys, "%s/input0", path);
-
-	wacom->dev.name = wacom->features->name;
-	wacom->dev.phys = wacom->phys;
-	wacom->dev.idbus = BUS_USB;
-	wacom->dev.idvendor = dev->descriptor.idVendor;
-	wacom->dev.idproduct = dev->descriptor.idProduct;
-	wacom->dev.idversion = dev->descriptor.bcdDevice;
-	wacom->usbdev = dev;
-
-	endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
-
-	FILL_INT_URB(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-		     wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval);
-
-	input_register_device(&wacom->dev);
-
-	printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
-
-	return wacom;
-}
-
-static void wacom_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct wacom *wacom = ptr;
-	usb_unlink_urb(wacom->irq);
-	input_unregister_device(&wacom->dev);
-	usb_free_urb(wacom->irq);
-	kfree(wacom);
-}
-
-static struct usb_driver wacom_driver = {
-	name:		"wacom",
-	probe:		wacom_probe,
-	disconnect:	wacom_disconnect,
-	id_table:	wacom_ids,
-};
-
-static int __init wacom_init(void)
-{
-	usb_register(&wacom_driver);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
-	return 0;
-}
-
-static void __exit wacom_exit(void)
-{
-	usb_deregister(&wacom_driver);
-}
-
-module_init(wacom_init);
-module_exit(wacom_exit);
diff -Nru a/drivers/video/Config.in b/drivers/video/Config.in
--- a/drivers/video/Config.in	Sun Apr 14 12:16:59 2002
+++ b/drivers/video/Config.in	Sun Apr 14 12:16:59 2002
@@ -27,13 +27,23 @@
 	 fi
       fi
    fi
-   if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-      bool '  Acorn VIDC support' CONFIG_FB_ACORN
-   fi
-   dep_tristate '  Cyber2000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
-   if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-      bool '  SA-1100 LCD support' CONFIG_FB_SA1100
+   if [ "$CONFIG_ARM" = "y" ]; then
+      dep_bool '  Acorn VIDC support' CONFIG_FB_ACORN $CONFIG_ARCH_ACORN
+      dep_bool '  Anakin LCD support' CONFIG_FB_ANAKIN $CONFIG_ARCH_ANAKIN
+      dep_bool '  CLPS711X LCD support' CONFIG_FB_CLPS711X $CONFIG_ARCH_CLPS711X
+      dep_bool '  SA-1100 LCD support' CONFIG_FB_SA1100 $CONFIG_ARCH_SA1100
+      if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF" = "y" ]; then
+         choice 'CerfBoard LCD Display Size' \
+		"3.8_Color		CONFIG_CERF_LCD_38_A \
+		 3.8_Mono		CONFIG_CERF_LCD_38_B \
+		 5.7		CONFIG_CERF_LCD_57_A \
+		 7.2		CONFIG_CERF_LCD_72_A" 5.7
+      fi
+      if [ "$CONFIG_FB_SA1100" = "y" -a "$CONFIG_SA1100_CERF_CPLD" = "y" ]; then
+         bool 'Cerfboard Backlight (CerfPDA)' CONFIG_SA1100_CERF_LCD_BACKLIGHT
+      fi
    fi
+   dep_tristate '  CyberPro 2000/2010/5000 support' CONFIG_FB_CYBER2000 $CONFIG_PCI
    if [ "$CONFIG_APOLLO" = "y" ]; then
       define_bool CONFIG_FB_APOLLO y
    fi
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	Sun Apr 14 12:16:55 2002
+++ b/drivers/video/Makefile	Sun Apr 14 12:16:55 2002
@@ -55,6 +55,8 @@
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
 obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
 obj-$(CONFIG_FB_CT65550)          += chipsfb.o
+obj-$(CONFIG_FB_ANAKIN)           += anakinfb.o
+obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER)            += cyberfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
 obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
diff -Nru a/drivers/video/amifb.c b/drivers/video/amifb.c
--- a/drivers/video/amifb.c	Sun Apr 14 12:16:57 2002
+++ b/drivers/video/amifb.c	Sun Apr 14 12:16:57 2002
@@ -1132,7 +1132,6 @@
 static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
 static u_long chipalloc(u_long size);
 static void chipfree(void);
-static char *strtoke(char *s,const char *ct);
 
 	/*
 	 * Hardware routines
@@ -1224,22 +1223,22 @@
 	 * <H*> horizontal freq. in kHz
 	 */
 
-		if (!(p = strtoke(mcap_spec, ";")) || !*p)
+		if (!(p = strsep(&mcap_spec, ";")) || !*p)
 			goto cap_invalid;
 		vmin = simple_strtoul(p, NULL, 10);
 		if (vmin <= 0)
 			goto cap_invalid;
-		if (!(p = strtoke(NULL, ";")) || !*p)
+		if (!(p = strsep(&mcap_spec, ";")) || !*p)
 			goto cap_invalid;
 		vmax = simple_strtoul(p, NULL, 10);
 		if (vmax <= 0 || vmax <= vmin)
 			goto cap_invalid;
-		if (!(p = strtoke(NULL, ";")) || !*p)
+		if (!(p = strsep(&mcap_spec, ";")) || !*p)
 			goto cap_invalid;
 		hmin = 1000 * simple_strtoul(p, NULL, 10);
 		if (hmin <= 0)
 			goto cap_invalid;
-		if (!(p = strtoke(NULL, "")) || !*p)
+		if (!(p = strsep(&mcap_spec, "")) || !*p)
 			goto cap_invalid;
 		hmax = 1000 * simple_strtoul(p, NULL, 10);
 		if (hmax <= 0 || hmax <= hmin)
@@ -1913,29 +1912,6 @@
 		ami_reinit_copper();
 		do_vmode_full = 0;
 	}
-}
-
-	/*
-	 * A strtok which returns empty strings, too
-	 */
-
-static char __init *strtoke(char *s,const char *ct)
-{
-	char *sbegin, *send;
-	static char *ssave = NULL;
-
-	sbegin  = s ? s : ssave;
-	if (!sbegin)
-		return NULL;
-	if (*sbegin == '\0') {
-		ssave = NULL;
-		return NULL;
-	}
-	send = strpbrk(sbegin, ct);
-	if (send && *send != '\0')
-		*send++ = '\0';
-	ssave = send;
-	return sbegin;
 }
 
 /* --------------------------- Hardware routines --------------------------- */
diff -Nru a/drivers/video/anakinfb.c b/drivers/video/anakinfb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/video/anakinfb.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,221 @@
+/*
+ *  linux/drivers/video/anakinfb.c
+ *
+ *  Copyright (C) 2001 Aleph One Ltd. for Acunia N.V.
+ *
+ * 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.
+ *
+ *  Changelog:
+ *   23-Apr-2001 TTC	Created
+ */
+
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb16.h>
+
+static u16 colreg[16];
+static int currcon = 0;
+static struct fb_info fb_info;
+static struct display display;
+
+static int
+anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+			u_int *transp, struct fb_info *info)
+{
+	if (regno > 15)
+		return 1;
+
+	*red = colreg[regno] & 0xf800;
+	*green = colreg[regno] & 0x7e0 << 5;
+	*blue = colreg[regno] & 0x1f << 11;
+	*transp = 0;
+	return 0;
+}
+
+static int
+anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			u_int transp, struct fb_info *info)
+{
+	if (regno > 15)
+		return 1;
+
+	colreg[regno] = (red & 0xf800) | (green & 0xfc00 >> 5) |
+			(blue & 0xf800 >> 11);
+	return 0;
+}
+
+static int
+anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id, "AnakinFB");
+	fix->smem_start = VGA_START;
+	fix->smem_len = VGA_SIZE;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->ywrapstep = 0;
+        fix->line_length = 400 * 2;
+	fix->accel = FB_ACCEL_NONE;
+	return 0;
+}
+        
+static int
+anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	memset(var, 0, sizeof(struct fb_var_screeninfo));
+	var->xres = 400;
+	var->yres = 234;
+	var->xres_virtual = 400;
+	var->yres_virtual = 234;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	var->bits_per_pixel = 16;
+	var->grayscale = 0;
+	var->red.offset = 11;
+	var->red.length = 5;
+	var->green.offset = 5;
+	var->green.length = 6;
+	var->blue.offset = 0;
+	var->blue.length = 5;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->nonstd = 0;
+	var->activate = FB_ACTIVATE_NOW;
+	var->height = -1;
+	var->width = -1;
+	var->pixclock = 0;
+	var->left_margin = 0;
+	var->right_margin = 0;
+	var->upper_margin = 0;
+	var->lower_margin = 0;
+	var->hsync_len = 0;
+	var->vsync_len = 0;
+	var->sync = 0;
+	var->vmode = FB_VMODE_NONINTERLACED;
+	return 0;
+}
+
+static int
+anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static int
+anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			struct fb_info *info)
+{
+	if (con == currcon)
+		return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
+	else if (fb_display[con].cmap.len)
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+	else
+		fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+static int
+anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			struct fb_info *info)
+{
+	int err;
+
+	if (!fb_display[con].cmap.len) {
+		if ((err = fb_alloc_cmap(&fb_display[con].cmap, 16, 0)))
+			return err;
+	}
+	if (con == currcon)
+		return fb_set_cmap(cmap, kspc, anakinfb_setcolreg, info);
+	else
+		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+	return 0;
+}
+
+static int
+anakinfb_switch_con(int con, struct fb_info *info)
+{ 
+	currcon = con;
+	return 0;
+
+}
+
+static int
+anakinfb_updatevar(int con, struct fb_info *info)
+{
+	return 0;
+}
+
+static void
+anakinfb_blank(int blank, struct fb_info *info)
+{
+	/*
+	 * TODO: use I2C to blank/unblank the screen
+	 */
+}
+
+static struct fb_ops anakinfb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	anakinfb_get_fix,
+	fb_get_var:	anakinfb_get_var,
+	fb_set_var:	anakinfb_set_var,
+	fb_get_cmap:	anakinfb_get_cmap,
+	fb_set_cmap:	anakinfb_set_cmap,
+};
+
+int __init
+anakinfb_init(void)
+{
+	memset(&fb_info, 0, sizeof(struct fb_info));
+	strcpy(fb_info.modename, "AnakinFB");
+	fb_info.node = -1;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.fbops = &anakinfb_ops;
+	fb_info.disp = &display;
+	strcpy(fb_info.fontname, "VGA8x16");
+	fb_info.changevar = NULL;
+	fb_info.switch_con = &anakinfb_switch_con;
+	fb_info.updatevar = &anakinfb_updatevar;
+	fb_info.blank = &anakinfb_blank;
+
+	memset(&display, 0, sizeof(struct display));
+	anakinfb_get_var(&display.var, 0, &fb_info);
+	display.screen_base = ioremap(VGA_START, VGA_SIZE);
+	display.visual = FB_VISUAL_TRUECOLOR;
+	display.type = FB_TYPE_PACKED_PIXELS;
+	display.type_aux = 0;
+	display.ypanstep = 0;
+	display.ywrapstep = 0;
+	display.line_length = 400 * 2;
+	display.can_soft_blank = 1;
+	display.inverse = 0;
+
+#ifdef FBCON_HAS_CFB16
+	display.dispsw = &fbcon_cfb16;
+	display.dispsw_data = colreg;
+#else
+	display.dispsw = &fbcon_dummy;
+#endif
+
+	if (register_framebuffer(&fb_info) < 0)
+		return -EINVAL;
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
+MODULE_DESCRIPTION("Anakin framebuffer driver");
+MODULE_SUPPORTED_DEVICE("fb");
diff -Nru a/drivers/video/atafb.c b/drivers/video/atafb.c
--- a/drivers/video/atafb.c	Sun Apr 14 12:16:55 2002
+++ b/drivers/video/atafb.c	Sun Apr 14 12:16:55 2002
@@ -2860,28 +2860,6 @@
 	return 0;
 }
 
-/* a strtok which returns empty strings, too */
-
-static char * strtoke(char * s,const char * ct)
-{
-  char *sbegin, *send;
-  static char *ssave = NULL;
-  
-  sbegin  = s ? s : ssave;
-  if (!sbegin) {
-	  return NULL;
-  }
-  if (*sbegin == '\0') {
-    ssave = NULL;
-    return NULL;
-  }
-  send = strpbrk(sbegin, ct);
-  if (send && *send != '\0')
-    *send++ = '\0';
-  ssave = send;
-  return sbegin;
-}
-
 int __init atafb_setup( char *options )
 {
     char *this_opt;
@@ -2956,18 +2934,18 @@
 	int xres;
 	char *p;
 
-	if (!(p = strtoke(int_str, ";")) ||!*p) goto int_invalid;
+	if (!(p = strsep(&int_str, ";")) || !*p) goto int_invalid;
 	xres = simple_strtoul(p, NULL, 10);
-	if (!(p = strtoke(NULL, ";")) || !*p) goto int_invalid;
+	if (!(p = strsep(&int_str, ";")) || !*p) goto int_invalid;
 	sttt_xres=xres;
 	tt_yres=st_yres=simple_strtoul(p, NULL, 10);
-	if ((p=strtoke(NULL, ";")) && *p) {
+	if ((p=strsep(&int_str, ";")) && *p) {
 		sttt_xres_virtual=simple_strtoul(p, NULL, 10);
 	}
-	if ((p=strtoke(NULL, ";")) && *p) {
+	if ((p=strsep(&int_str, ";")) && *p) {
 		sttt_yres_virtual=simple_strtoul(p, NULL, 0);
 	}
-	if ((p=strtoke(NULL, ";")) && *p) {
+	if ((p=strsep(&int_str, ";")) && *p) {
 		ovsc_offset=simple_strtoul(p, NULL, 0);
 	}
 
@@ -2993,20 +2971,20 @@
 	 *
 	 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
 	 */
-	if (!(p = strtoke(ext_str, ";")) ||!*p) goto ext_invalid;
+	if (!(p = strsep(&ext_str, ";")) || !*p) goto ext_invalid;
 	xres_virtual = xres = simple_strtoul(p, NULL, 10);
 	if (xres <= 0) goto ext_invalid;
 
-	if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
+	if (!(p = strsep(&ext_str, ";")) || !*p) goto ext_invalid;
 	yres = simple_strtoul(p, NULL, 10);
 	if (yres <= 0) goto ext_invalid;
 
-	if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
+	if (!(p = strsep(&ext_str, ";")) || !*p) goto ext_invalid;
 	depth = simple_strtoul(p, NULL, 10);
 	if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
 		depth != 16 && depth != 24) goto ext_invalid;
 
-	if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
+	if (!(p = strsep(&ext_str, ";")) || !*p) goto ext_invalid;
 	if (*p == 'i')
 		planes = FB_TYPE_INTERLEAVED_PLANES;
 	else if (*p == 'p')
@@ -3019,19 +2997,19 @@
 		goto ext_invalid;
 
 
-	if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
+	if (!(p = strsep(&ext_str, ";")) || !*p) goto ext_invalid;
 	addr = simple_strtoul(p, NULL, 0);
 
-	if (!(p = strtoke(NULL, ";")) ||!*p)
+	if (!(p = strsep(&ext_str, ";")) || !*p)
 		len = xres*yres*depth/8;
 	else
 		len = simple_strtoul(p, NULL, 0);
 
-	if ((p = strtoke(NULL, ";")) && *p) {
+	if ((p = strsep(&ext_str, ";")) && *p) {
 		external_vgaiobase=simple_strtoul(p, NULL, 0);
 	}
 
-	if ((p = strtoke(NULL, ";")) && *p) {
+	if ((p = strsep(&ext_str, ";")) && *p) {
 		external_bitspercol = simple_strtoul(p, NULL, 0);
 		if (external_bitspercol > 8)
 			external_bitspercol = 8;
@@ -3039,14 +3017,14 @@
 			external_bitspercol = 1;
 	}
 	
-	if ((p = strtoke(NULL, ";")) && *p) {
+	if ((p = strsep(&ext_str, ";")) && *p) {
 		if (!strcmp(p, "vga"))
 			external_card_type = IS_VGA;
 		if (!strcmp(p, "mv300"))
 			external_card_type = IS_MV300;
 	}
 
-	if ((p = strtoke(NULL, ";")) && *p) {
+	if ((p = strsep(&ext_str, ";")) && *p) {
 		xres_virtual = simple_strtoul(p, NULL, 10);
 		if (xres_virtual < xres)
 			xres_virtual = xres;
@@ -3089,16 +3067,16 @@
 	 * <V*> vertical freq. in Hz
 	 * <H*> horizontal freq. in kHz
 	 */
-	if (!(p = strtoke(mcap_spec, ";")) || !*p) goto cap_invalid;
+	if (!(p = strsep(&mcap_spec, ";")) || !*p) goto cap_invalid;
 	vmin = simple_strtoul(p, NULL, 10);
 	if (vmin <= 0) goto cap_invalid;
-	if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
+	if (!(p = strsep(&mcap_spec, ";")) || !*p) goto cap_invalid;
 	vmax = simple_strtoul(p, NULL, 10);
 	if (vmax <= 0 || vmax <= vmin) goto cap_invalid;
-	if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
+	if (!(p = strsep(&mcap_spec, ";")) || !*p) goto cap_invalid;
 	hmin = 1000 * simple_strtoul(p, NULL, 10);
 	if (hmin <= 0) goto cap_invalid;
-	if (!(p = strtoke(NULL, "")) || !*p) goto cap_invalid;
+	if (!(p = strsep(&mcap_spec, "")) || !*p) goto cap_invalid;
 	hmax = 1000 * simple_strtoul(p, NULL, 10);
 	if (hmax <= 0 || hmax <= hmin) goto cap_invalid;
 
@@ -3117,11 +3095,11 @@
 		char *p;
 		int xres, yres, depth, temp;
 
-		if (!(p = strtoke(user_mode, ";")) || !*p) goto user_invalid;
+		if (!(p = strsep(&user_mode, ";")) || !*p) goto user_invalid;
 		xres = simple_strtoul(p, NULL, 10);
-		if (!(p = strtoke(NULL, ";")) || !*p) goto user_invalid;
+		if (!(p = strsep(&user_mode, ";")) || !*p) goto user_invalid;
 		yres = simple_strtoul(p, NULL, 10);
-		if (!(p = strtoke(NULL, "")) || !*p) goto user_invalid;
+		if (!(p = strsep(&user_mode, "")) || !*p) goto user_invalid;
 		depth = simple_strtoul(p, NULL, 10);
 		if ((temp=get_video_mode("user0"))) {
 			default_par=temp;
diff -Nru a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
--- a/drivers/video/aty/atyfb_base.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/video/aty/atyfb_base.c	Sun Apr 14 12:16:56 2002
@@ -178,7 +178,6 @@
 static int aty_init(struct fb_info_aty *info, const char *name);
 #ifdef CONFIG_ATARI
 static int store_video_par(char *videopar, unsigned char m64_num);
-static char *strtoke(char *s, const char *ct);
 #endif
 
 static void aty_set_crtc(const struct fb_info_aty *info,
@@ -2595,13 +2594,13 @@
 
     printk("store_video_par() '%s' \n", video_str);
 
-    if (!(p = strtoke(video_str, ";")) || !*p)
+    if (!(p = strsep(&video_str, ";")) || !*p)
 	goto mach64_invalid;
     vmembase = simple_strtoul(p, NULL, 0);
-    if (!(p = strtoke(NULL, ";")) || !*p)
+    if (!(p = strsep(&video_str, ";")) || !*p)
 	goto mach64_invalid;
     size = simple_strtoul(p, NULL, 0);
-    if (!(p = strtoke(NULL, ";")) || !*p)
+    if (!(p = strsep(&video_str, ";")) || !*p)
 	goto mach64_invalid;
     guiregbase = simple_strtoul(p, NULL, 0);
 
@@ -2615,25 +2614,6 @@
 mach64_invalid:
     phys_vmembase[m64_num]   = 0;
     return -1;
-}
-
-static char __init *strtoke(char *s, const char *ct)
-{
-    static char *ssave = NULL;
-    char *sbegin, *send;
-
-    sbegin  = s ? s : ssave;
-    if (!sbegin)
-	return NULL;
-    if (*sbegin == '\0') {
-	ssave = NULL;
-	return NULL;
-    }
-    send = strpbrk(sbegin, ct);
-    if (send && *send != '\0')
-	*send++ = '\0';
-    ssave = send;
-    return sbegin;
 }
 #endif /* CONFIG_ATARI */
 
diff -Nru a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/video/clps711xfb.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,524 @@
+/*
+ *  linux/drivers/video/clps711xfb.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or 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
+ *
+ *  Framebuffer driver for the CLPS7111 and EP7212 processors.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb4.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+
+#include <asm/hardware/clps7111.h>
+#include <asm/arch/syspld.h>
+
+static struct clps7111fb_info {
+	struct fb_info		fb;
+	int			currcon;
+} *cfb;
+
+#define CMAP_SIZE	16
+
+/* The /proc entry for the backlight. */
+static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
+
+static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
+		int count, int *eof, void *data);
+static int clps7111fb_proc_backlight_write(struct file *file, 
+		const char *buffer, unsigned long count, void *data);
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int
+clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		     u_int transp, struct fb_info *info)
+{
+	unsigned int level, mask, shift, pal;
+
+	if (regno >= CMAP_SIZE)
+		return 1;
+
+	/* gray = 0.30*R + 0.58*G + 0.11*B */
+	level = (red * 77 + green * 151 + blue * 28) >> 20;
+
+	/*
+	 * On an LCD, a high value is dark, while a low value is light. 
+	 * So we invert the level.
+	 *
+	 * This isn't true on all machines, so we only do it on EDB7211.
+	 *  --rmk
+	 */
+	if (machine_is_edb7211()) {
+		level = 15 - level;
+	}
+
+	shift = 4 * (regno & 7);
+	level <<= shift;
+	mask  = 15 << shift;
+	level &= mask;
+
+	regno = regno < 8 ? PALLSW : PALMSW;
+
+	pal = clps_readl(regno);
+	pal = (pal & ~mask) | level;
+	clps_writel(pal, regno);
+
+	return 0;
+}
+		    
+/*
+ * Set the colormap
+ */
+static int
+clps7111fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+		    struct fb_info *info)
+{
+	struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
+	struct fb_cmap *dcmap = &fb_display[con].cmap;
+	int err = 0;
+
+	/* no colormap allocated? */
+	if (!dcmap->len)
+		err = fb_alloc_cmap(dcmap, CMAP_SIZE, 0);
+
+	if (!err && con == cfb->currcon) {
+		err = fb_set_cmap(cmap, kspc, clps7111fb_setcolreg, &cfb->fb);
+		dcmap = &cfb->fb.cmap;
+	}
+
+	if (!err)
+		fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
+
+	return err;
+}
+
+/*
+ *    Set the User Defined Part of the Display
+ */
+static int
+clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
+		   struct fb_info *info)
+{
+	struct display *display;
+	unsigned int lcdcon, syscon;
+	int chgvar = 0;
+
+	if (var->activate & FB_ACTIVATE_TEST)
+		return 0;
+
+	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+		return -EINVAL;
+
+	if (cfb->fb.var.xres != var->xres)
+		chgvar = 1;
+	if (cfb->fb.var.yres != var->yres)
+		chgvar = 1;
+	if (cfb->fb.var.xres_virtual != var->xres_virtual)
+		chgvar = 1;
+	if (cfb->fb.var.yres_virtual != var->yres_virtual)
+		chgvar = 1;
+	if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
+		chgvar = 1;
+
+	if (con < 0) {
+		display = cfb->fb.disp;
+		chgvar = 0;
+	} else {
+		display = fb_display + con;
+	}
+
+	var->transp.msb_right	= 0;
+	var->transp.offset	= 0;
+	var->transp.length	= 0;
+	var->red.msb_right	= 0;
+	var->red.offset		= 0;
+	var->red.length		= var->bits_per_pixel;
+	var->green		= var->red;
+	var->blue		= var->red;
+
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+	case 1:
+		cfb->fb.fix.visual	= FB_VISUAL_MONO01;
+		display->dispsw		= &fbcon_mfb;
+		display->dispsw_data	= NULL;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB2
+	case 2:
+		cfb->fb.fix.visual	= FB_VISUAL_PSEUDOCOLOR;
+		display->dispsw		= &fbcon_cfb2;
+		display->dispsw_data	= NULL;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB4
+	case 4:
+		cfb->fb.fix.visual	= FB_VISUAL_PSEUDOCOLOR;
+		display->dispsw		= &fbcon_cfb4;
+		display->dispsw_data	= NULL;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	display->next_line	= var->xres_virtual * var->bits_per_pixel / 8;
+
+	cfb->fb.fix.line_length = display->next_line;
+
+	display->screen_base	= cfb->fb.screen_base;
+	display->line_length	= cfb->fb.fix.line_length;
+	display->visual		= cfb->fb.fix.visual;
+	display->type		= cfb->fb.fix.type;
+	display->type_aux	= cfb->fb.fix.type_aux;
+	display->ypanstep	= cfb->fb.fix.ypanstep;
+	display->ywrapstep	= cfb->fb.fix.ywrapstep;
+	display->can_soft_blank = 1;
+	display->inverse	= 0;
+
+	cfb->fb.var		= *var;
+	cfb->fb.var.activate	&= ~FB_ACTIVATE_ALL;
+
+	/*
+	 * Update the old var.  The fbcon drivers still use this.
+	 * Once they are using cfb->fb.var, this can be dropped.
+	 *                                      --rmk
+	 */
+	display->var		= cfb->fb.var;
+
+	/*
+	 * If we are setting all the virtual consoles, also set the
+	 * defaults used to create new consoles.
+	 */
+	if (var->activate & FB_ACTIVATE_ALL)
+		cfb->fb.disp->var = cfb->fb.var;
+
+	if (chgvar && info && cfb->fb.changevar)
+		cfb->fb.changevar(con);
+
+	/*
+	 * LCDCON must only be changed while the LCD is disabled
+	 */
+	lcdcon = (var->xres_virtual * var->yres_virtual * var->bits_per_pixel) / 128 - 1;
+	lcdcon |= ((var->xres_virtual / 16) - 1) << 13;
+	lcdcon |= 2 << 19;
+	lcdcon |= 13 << 25;
+	lcdcon |= LCDCON_GSEN;
+	lcdcon |= LCDCON_GSMD;
+
+	syscon = clps_readl(SYSCON1);
+	clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
+	clps_writel(lcdcon, LCDCON);
+	clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
+
+	fb_set_cmap(&cfb->fb.cmap, 1, clps7111fb_setcolreg, &cfb->fb);
+
+	return 0;
+}
+
+/*
+ * Get the currently displayed virtual consoles colormap.
+ */
+static int
+gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+	fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+/*
+ * Get the currently displayed virtual consoles fixed part of the display.
+ */
+static int
+gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	*fix = info->fix;
+	return 0;
+}
+
+/*
+ * Get the current user defined part of the display.
+ */
+static int
+gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	*var = info->var;
+	return 0;
+}
+
+static struct fb_ops clps7111fb_ops = {
+	owner:		THIS_MODULE,
+	fb_set_var:	clps7111fb_set_var,
+	fb_set_cmap:	clps7111fb_set_cmap,
+	fb_get_fix:	gen_get_fix,
+	fb_get_var:	gen_get_var,
+	fb_get_cmap:	gen_get_cmap,
+};
+
+static int clps7111fb_switch(int con, struct fb_info *info)
+{
+	struct clps7111fb_info *cfb = (struct clps7111fb_info *)info;
+	struct display *disp;
+	struct fb_cmap *cmap;
+
+	if (cfb->currcon >= 0) {
+		disp = fb_display + cfb->currcon;
+
+		/*
+		 * Save the old colormap and video mode.
+		 */
+		disp->var = cfb->fb.var;
+		if (disp->cmap.len)
+			fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
+	}
+
+	cfb->currcon = con;
+	disp = fb_display + con;
+
+	/*
+	 * Install the new colormap and change the video mode.  By default,
+	 * fbcon sets all the colormaps and video modes to the default
+	 * values at bootup.
+	 */
+	if (disp->cmap.len)
+		cmap = &disp->cmap;
+	else
+		cmap = fb_default_cmap(CMAP_SIZE);
+
+	fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
+
+	cfb->fb.var = disp->var;
+	cfb->fb.var.activate = FB_ACTIVATE_NOW;
+
+	clps7111fb_set_var(&cfb->fb.var, con, &cfb->fb);
+
+	return 0;
+}
+
+static int clps7111fb_updatevar(int con, struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static void clps7111fb_blank(int blank, struct fb_info *info)
+{
+    	if (blank) {
+		if (machine_is_edb7211()) {
+			int i;
+
+			/* Turn off the LCD backlight. */
+			clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
+
+			/* Power off the LCD DC-DC converter. */
+			clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
+
+			/* Delay for a little while (half a second). */
+			for (i=0; i<65536*4; i++);
+
+			/* Power off the LCD panel. */
+			clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
+
+			/* Power off the LCD controller. */
+			clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, 
+					SYSCON1);
+		}
+	} else {
+		if (machine_is_edb7211()) {
+				int i;
+
+				/* Power up the LCD controller. */
+				clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
+						SYSCON1);
+
+				/* Power up the LCD panel. */
+				clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
+
+				/* Delay for a little while. */
+				for (i=0; i<65536*4; i++);
+
+				/* Power up the LCD DC-DC converter. */
+				clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
+						PDDR);
+
+				/* Turn on the LCD backlight. */
+				clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
+		}
+	}
+}
+
+static int 
+clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
+		int count, int *eof, void *data)
+{
+	/* We need at least two characters, one for the digit, and one for
+	 * the terminating NULL. */
+	if (count < 2) 
+		return -EINVAL;
+
+	if (machine_is_edb7211()) {
+		return sprintf(page, "%d\n", 
+				(clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
+	}
+
+	return 0;
+}
+
+static int 
+clps7111fb_proc_backlight_write(struct file *file, const char *buffer, 
+		unsigned long count, void *data)
+{
+	unsigned char char_value;
+	int value;
+
+	if (count < 1) {
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&char_value, buffer, 1)) 
+		return -EFAULT;
+
+	value = char_value - '0';
+
+	if (machine_is_edb7211()) {
+		unsigned char port_d;
+
+		port_d = clps_readb(PDDR);
+
+		if (value) {
+			port_d |= EDB_PD3_LCDBL;
+		} else {
+			port_d &= ~EDB_PD3_LCDBL;
+		}
+
+		clps_writeb(port_d, PDDR);
+	}
+
+	return count;
+}
+
+
+int __init clps711xfb_init(void)
+{
+	int err = -ENOMEM;
+
+	cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
+	if (!cfb)
+		goto out;
+
+	memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
+	memset((void *)PAGE_OFFSET, 0, 0x14000);
+
+	cfb->currcon		= -1;
+
+	strcpy(cfb->fb.fix.id, "clps7111");
+	cfb->fb.screen_base	= (void *)PAGE_OFFSET;
+	cfb->fb.fix.smem_start	= PAGE_OFFSET;
+	cfb->fb.fix.smem_len	= 0x14000;
+	cfb->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+
+	cfb->fb.var.xres	 = 640;
+	cfb->fb.var.xres_virtual = 640;
+	cfb->fb.var.yres	 = 240;
+	cfb->fb.var.yres_virtual = 240;
+	cfb->fb.var.bits_per_pixel = 4;
+	cfb->fb.var.grayscale   = 1;
+	cfb->fb.var.activate	= FB_ACTIVATE_NOW;
+	cfb->fb.var.height	= -1;
+	cfb->fb.var.width	= -1;
+
+	cfb->fb.fbops		= &clps7111fb_ops;
+	cfb->fb.changevar	= NULL;
+	cfb->fb.switch_con	= clps7111fb_switch;
+	cfb->fb.updatevar	= clps7111fb_updatevar;
+	cfb->fb.blank		= clps7111fb_blank;
+	cfb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	cfb->fb.disp		= (struct display *)(cfb + 1);
+
+	fb_alloc_cmap(&cfb->fb.cmap, CMAP_SIZE, 0);
+
+	/* Register the /proc entries. */
+	clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
+		&proc_root);
+	if (clps7111fb_backlight_proc_entry == NULL) {
+		printk("Couldn't create the /proc entry for the backlight.\n");
+		return -EINVAL;
+	}
+
+	clps7111fb_backlight_proc_entry->read_proc = 
+		&clps7111fb_proc_backlight_read;
+	clps7111fb_backlight_proc_entry->write_proc = 
+		&clps7111fb_proc_backlight_write;
+
+	/*
+	 * Power up the LCD
+	 */
+	if (machine_is_p720t()) {
+		PLD_LCDEN = PLD_LCDEN_EN;
+		PLD_PWR |= (PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
+	}
+
+	if (machine_is_edb7211()) {
+		int i;
+
+		/* Power up the LCD panel. */
+		clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
+
+		/* Delay for a little while. */
+		for (i=0; i<65536*4; i++);
+
+		/* Power up the LCD DC-DC converter. */
+		clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
+
+		/* Turn on the LCD backlight. */
+		clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
+	}
+
+	clps7111fb_set_var(&cfb->fb.var, -1, &cfb->fb);
+	err = register_framebuffer(&cfb->fb);
+
+out:	return err;
+}
+
+static void __exit clps711xfb_exit(void)
+{
+	unregister_framebuffer(&cfb->fb);
+	kfree(cfb);
+
+	/*
+	 * Power down the LCD
+	 */
+	if (machine_is_p720t()) {
+		PLD_LCDEN = 0;
+		PLD_PWR &= ~(PLD_S4_ON|PLD_S3_ON|PLD_S2_ON|PLD_S1_ON);
+	}
+}
+
+#ifdef MODULE
+module_init(clps711xfb_init);
+#endif
+module_exit(clps711xfb_exit);
diff -Nru a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
--- a/drivers/video/cyber2000fb.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/video/cyber2000fb.c	Sun Apr 14 12:16:56 2002
@@ -16,8 +16,7 @@
  *
  * Note that we now use the new fbcon fix, var and cmap scheme.  We do still
  * have to check which console is the currently displayed one however, since
- * especially for the colourmap stuff.  Once fbcon has been fully migrated,
- * we can kill the last 5 references to cfb->currcon.
+ * especially for the colourmap stuff.
  *
  * We also use the new hotplug PCI subsystem.  I'm not sure if there are any
  * such cards, but I'm erring on the side of caution.  We don't want to go
@@ -61,10 +60,10 @@
 struct cfb_info {
 	struct fb_info		fb;
 	struct display_switch	*dispsw;
+	struct display		*display;
 	struct pci_dev		*dev;
 	unsigned char 		*region;
 	unsigned char		*regs;
-	signed int		currcon;
 	int			func_use_count;
 	u_long			ref_ps;
 
@@ -150,24 +149,24 @@
 	}
 }
 
-static void cyber2000_accel_setup(struct display *p)
+static void cyber2000_accel_setup(struct display *display)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
 
-	cfb->dispsw->setup(p);
+	cfb->dispsw->setup(display);
 }
 
 static void
-cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
+cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
 		      int height, int width)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-	struct fb_var_screeninfo *var = &p->fb_info->var;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
+	struct fb_var_screeninfo *var = &display->var;
 	u_long src, dst;
 	u_int fh, fw;
 	int cmd = CO_CMD_L_PATTERN_FGCOL;
 
-	fw    = fontwidth(p);
+	fw    = fontwidth(display);
 	sx    *= fw;
 	dx    *= fw;
 	width *= fw;
@@ -179,7 +178,7 @@
 		cmd |= CO_CMD_L_INC_LEFT;
 	}
 
-	fh     = fontheight(p);
+	fh     = fontheight(display);
 	sy     *= fh;
 	dy     *= fh;
 	height *= fh;
@@ -214,17 +213,17 @@
 }
 
 static void
-cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
-		      int height, int width)
+cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
+		      int sx, int height, int width)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
-	struct fb_var_screeninfo *var = &p->fb_info->var;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
+	struct fb_var_screeninfo *var = &display->var;
 	u_long dst;
 	u_int fw, fh;
-	u32 bgx = attr_bgcol_ec(p, conp);
+	u32 bgx = attr_bgcol_ec(display, conp);
 
-	fw = fontwidth(p);
-	fh = fontheight(p);
+	fw = fontwidth(display);
+	fh = fontheight(display);
 
 	dst    = sx * fw + sy * var->xres_virtual * fh;
 	width  = width * fw - 1;
@@ -237,9 +236,8 @@
 	cyber2000fb_writew(height, CO_REG_HEIGHT,   cfb);
 
 	switch (var->bits_per_pixel) {
-	case 15:
 	case 16:
-		bgx = ((u16 *)p->dispsw_data)[bgx];
+		bgx = ((u16 *)display->dispsw_data)[bgx];
 	case 8:
 		cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
 		break;
@@ -247,7 +245,7 @@
 	case 24:
 		cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
 		cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
-		bgx = ((u32 *)p->dispsw_data)[bgx];
+		bgx = ((u32 *)display->dispsw_data)[bgx];
 		break;
 	}
 
@@ -257,40 +255,40 @@
 }
 
 static void
-cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c,
+cyber2000_accel_putc(struct vc_data *conp, struct display *display, int c,
 		     int yy, int xx)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
 
 	cyber2000_accel_wait(cfb);
-	cfb->dispsw->putc(conp, p, c, yy, xx);
+	cfb->dispsw->putc(conp, display, c, yy, xx);
 }
 
 static void
-cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
+cyber2000_accel_putcs(struct vc_data *conp, struct display *display,
 		      const unsigned short *s, int count, int yy, int xx)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
 
 	cyber2000_accel_wait(cfb);
-	cfb->dispsw->putcs(conp, p, s, count, yy, xx);
+	cfb->dispsw->putcs(conp, display, s, count, yy, xx);
 }
 
-static void cyber2000_accel_revc(struct display *p, int xx, int yy)
+static void cyber2000_accel_revc(struct display *display, int xx, int yy)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
 
 	cyber2000_accel_wait(cfb);
-	cfb->dispsw->revc(p, xx, yy);
+	cfb->dispsw->revc(display, xx, yy);
 }
 
 static void
-cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p,
+cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
 			      int bottom_only)
 {
-	struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
+	struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
 
-	cfb->dispsw->clear_margins(conp, p, bottom_only);
+	cfb->dispsw->clear_margins(conp, display, bottom_only);
 }
 
 static struct display_switch fbcon_cyber_accel = {
@@ -312,6 +310,7 @@
 		    u_int transp, struct fb_info *info)
 {
 	struct cfb_info *cfb = (struct cfb_info *)info;
+	struct fb_var_screeninfo *var = &cfb->display->var;
 
 	if (regno >= NR_PALETTE)
 		return 1;
@@ -324,7 +323,7 @@
 	cfb->palette[regno].green = green;
 	cfb->palette[regno].blue  = blue;
 
-	switch (cfb->fb.var.bits_per_pixel) {
+	switch (var->bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
 		cyber2000fb_writeb(regno, 0x3c8, cfb);
@@ -337,29 +336,29 @@
 #ifdef FBCON_HAS_CFB16
 	case 16:
 #ifndef CFB16_IS_CFB15
-		if (regno < 64) {
-			/* write green */
-			cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
-			cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
-			cyber2000fb_writeb(green, 0x3c9, cfb);
-			cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
-		}
-
-		if (regno < 32) {
-			/* write red,blue */
-			cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
-			cyber2000fb_writeb(red, 0x3c9, cfb);
-			cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
-			cyber2000fb_writeb(blue, 0x3c9, cfb);
+		if (var->green.length == 6) {
+			if (regno < 64) {
+				/* write green */
+				cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
+				cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
+				cyber2000fb_writeb(green, 0x3c9, cfb);
+				cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
+			}
+
+			if (regno < 32) {
+				/* write red,blue */
+				cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
+				cyber2000fb_writeb(red, 0x3c9, cfb);
+				cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
+				cyber2000fb_writeb(blue, 0x3c9, cfb);
+			}
+
+			if (regno < 16)
+				((u16 *)cfb->fb.pseudo_palette)[regno] =
+					regno | regno << 5 | regno << 11;
+			break;
 		}
-
-		if (regno < 16)
-			((u16 *)cfb->fb.pseudo_palette)[regno] =
-				regno | regno << 5 | regno << 11;
-		break;
 #endif
-
-	case 15:
 		if (regno < 32) {
 			cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
 			cyber2000fb_writeb(red, 0x3c9, cfb);
@@ -399,7 +398,7 @@
 	 */
 	u_char	clock_mult;
 	u_char	clock_div;
-	u_char	visualid;
+	u_char	extseqmisc;
 	u_char	pixformat;
 	u_char	crtc_ofl;
 	u_char	crtc[19];
@@ -483,10 +482,10 @@
 	cyber2000fb_writeb(i, 0x3cf, cfb);
 
 	/* PLL registers */
-	cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
-	cyber2000_grphw(DCLK_DIV,  hw->clock_div, cfb);
-	cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
-	cyber2000_grphw(MCLK_DIV,  cfb->mclk_div, cfb);
+	cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
+	cyber2000_grphw(EXT_DCLK_DIV,  hw->clock_div, cfb);
+	cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
+	cyber2000_grphw(EXT_MCLK_DIV,  cfb->mclk_div, cfb);
 	cyber2000_grphw(0x90, 0x01, cfb);
 	cyber2000_grphw(0xb9, 0x80, cfb);
 	cyber2000_grphw(0xb9, 0x00, cfb);
@@ -503,10 +502,11 @@
 	cyber2000_grphw(0x14, hw->fetch, cfb);
 	cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
 			      ((hw->pitch >> 4) & 0x30), cfb);
-	cyber2000_grphw(0x77, hw->visualid, cfb);
+	cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
 
-	/* make sure we stay in linear mode */
-	cyber2000_grphw(0x33, 0x0d, cfb);
+	cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
+				      EXT_BIU_MISC_COP_ENABLE |
+				      EXT_BIU_MISC_COP_BFC, cfb);
 
 	/*
 	 * Set up accelerator registers
@@ -521,9 +521,14 @@
 {
 	u_int base;
 
-	base = var->yoffset * var->xres_virtual + var->xoffset;
+	base = var->yoffset * var->xres_virtual * var->bits_per_pixel +
+		var->xoffset * var->bits_per_pixel;
 
-	base >>= 2;
+	/*
+	 * Convert to bytes and shift two extra bits because DAC
+	 * can only start on 4 byte aligned data.
+	 */
+	base >>= 5;
 
 	if (base >= 1 << 20)
 		return -EINVAL;
@@ -543,26 +548,19 @@
 		     struct fb_info *info)
 {
 	struct cfb_info *cfb = (struct cfb_info *)info;
-	struct fb_cmap *dcmap = &fb_display[con].cmap;
+	struct display *display = fb_display + con;
+	struct fb_cmap *dcmap = &display->cmap;
 	int err = 0;
 
 	/* no colormap allocated? */
-	if (!dcmap->len) {
-		int size;
-
-		if (cfb->fb.var.bits_per_pixel == 16)
-			size = 32;
-		else
-			size = 256;
-
-		err = fb_alloc_cmap(dcmap, size, 0);
-	}
+	if (!dcmap->len)
+		err = fb_alloc_cmap(dcmap, 256, 0);
 
 	/*
 	 * we should be able to remove this test once fbcon has been
 	 * "improved" --rmk
 	 */
-	if (!err && con == cfb->currcon) {
+	if (!err && display == cfb->display) {
 		err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb);
 		dcmap = &cfb->fb.cmap;
 	}
@@ -754,7 +752,7 @@
 	vco = ref_ps * best_div1 / best_mult;
 	if ((ref_ps == 40690) && (vco < 5556))
 		/* Set VFSEL when VCO > 180MHz (5.556 ps). */
-		hw->clock_div |= DCLK_DIV_VFSEL;
+		hw->clock_div |= EXT_DCLK_DIV_VFSEL;
 
 	return 0;
 }
@@ -778,31 +776,32 @@
 #ifdef FBCON_HAS_CFB8
 	case 8:	/* PSEUDOCOLOUR, 256 */
 		hw->pixformat		= PIXFORMAT_8BPP;
-		hw->visualid		= VISUALID_256;
+		hw->extseqmisc		= EXT_SEQ_MISC_8;
 		hw->pitch		= hw->width >> 3;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	case 16:/* DIRECTCOLOUR, 64k */
-#ifndef CFB16_IS_CFB15
+	case 16:
 		hw->pixformat		= PIXFORMAT_16BPP;
-		hw->visualid		= VISUALID_64K;
 		hw->pitch		= hw->width >> 2;
 		hw->palette_ctrl	|= 0x10;
-		break;
+
+#ifndef CFB16_IS_CFB15
+		/* DIRECTCOLOUR, 64k */
+		if (var->green.length == 6) {
+			hw->extseqmisc		= EXT_SEQ_MISC_16_RGB565;
+			break;
+		}
 #endif
-	case 15:/* DIRECTCOLOUR, 32k */
-		hw->pixformat		= PIXFORMAT_16BPP;
-		hw->visualid		= VISUALID_32K;
-		hw->pitch		= hw->width >> 2;
-		hw->palette_ctrl	|= 0x10;
+		/* DIRECTCOLOUR, 32k */
+		hw->extseqmisc		= EXT_SEQ_MISC_16_RGB555;
 		break;
 
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 24:/* TRUECOLOUR, 16m */
 		hw->pixformat		= PIXFORMAT_24BPP;
-		hw->visualid		= VISUALID_16M;
+		hw->extseqmisc		= EXT_SEQ_MISC_24_RGB888;
 		hw->width		*= 3;
 		hw->pitch		= hw->width >> 3;
 		hw->palette_ctrl	|= 0x10;
@@ -847,8 +846,8 @@
 	 */
 	if (var->vmode & FB_VMODE_CONUPDATE) {
 		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = cfb->fb.var.xoffset;
-		var->yoffset = cfb->fb.var.yoffset;
+		var->xoffset = cfb->display->var.xoffset;
+		var->yoffset = cfb->display->var.yoffset;
 	}
 
 	err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
@@ -861,23 +860,26 @@
 	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
 		return -EINVAL;
 
-	if (cfb->fb.var.xres != var->xres)
+	if (con < 0) {
+		display = cfb->fb.disp;
+		chgvar = 0;
+	} else {
+		display = fb_display + con;
+	}
+
+	if (display->var.xres != var->xres)
 		chgvar = 1;
-	if (cfb->fb.var.yres != var->yres)
+	if (display->var.yres != var->yres)
 		chgvar = 1;
-	if (cfb->fb.var.xres_virtual != var->xres_virtual)
+	if (display->var.xres_virtual != var->xres_virtual)
 		chgvar = 1;
-	if (cfb->fb.var.yres_virtual != var->yres_virtual)
+	if (display->var.yres_virtual != var->yres_virtual)
 		chgvar = 1;
-	if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel)
+	if (display->var.bits_per_pixel != var->bits_per_pixel)
 		chgvar = 1;
 
-	if (con < 0) {
-		display = cfb->fb.disp;
+	if (con < 0)
 		chgvar = 0;
-	} else {
-		display = fb_display + con;
-	}
 
 	var->red.msb_right	= 0;
 	var->green.msb_right	= 0;
@@ -900,13 +902,10 @@
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	case 16:/* DIRECTCOLOUR, 64k */
-#ifndef CFB16_IS_CFB15
-		var->bits_per_pixel	= 15;
-		var->red.offset		= 11;
+	case 16:
+		var->bits_per_pixel	= 16;
 		var->red.length		= 5;
 		var->green.offset	= 5;
-		var->green.length	= 6;
 		var->blue.offset	= 0;
 		var->blue.length	= 5;
 
@@ -914,21 +913,18 @@
 		cfb->dispsw		= &fbcon_cfb16;
 		display->dispsw_data	= cfb->fb.pseudo_palette;
 		display->next_line	= var->xres_virtual * 2;
-		break;
+
+#ifndef CFB16_IS_CFB15
+		/* DIRECTCOLOUR, 64k */
+		if (var->green.length == 6) {
+			var->red.offset		= 11;
+			var->green.length	= 6;
+			break;
+		}
 #endif
-	case 15:/* DIRECTCOLOUR, 32k */
-		var->bits_per_pixel	= 15;
+		/* DIRECTCOLOUR, 32k */
 		var->red.offset		= 10;
-		var->red.length		= 5;
-		var->green.offset	= 5;
 		var->green.length	= 5;
-		var->blue.offset	= 0;
-		var->blue.length	= 5;
-
-		cfb->fb.fix.visual	= FB_VISUAL_DIRECTCOLOR;
-		cfb->dispsw		= &fbcon_cfb16;
-		display->dispsw_data	= cfb->fb.pseudo_palette;
-		display->next_line	= var->xres_virtual * 2;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB24
@@ -969,23 +965,17 @@
 	display->ywrapstep	= cfb->fb.fix.ywrapstep;
 	display->can_soft_blank = 1;
 	display->inverse	= 0;
+	display->var		= *var;
+	display->var.activate	&= ~FB_ACTIVATE_ALL;
 
-	cfb->fb.var = *var;
-	cfb->fb.var.activate &= ~FB_ACTIVATE_ALL;
-
-	/*
-	 * Update the old var.  The fbcon drivers still use this.
-	 * Once they are using cfb->fb.var, this can be dropped.
-	 *					--rmk
-	 */
-	display->var = cfb->fb.var;
+	cfb->fb.var = display->var;
 
 	/*
 	 * If we are setting all the virtual consoles, also set the
 	 * defaults used to create new consoles.
 	 */
 	if (var->activate & FB_ACTIVATE_ALL)
-		cfb->fb.disp->var = cfb->fb.var;
+		cfb->fb.disp->var = display->var;
 
 	if (chgvar && info && cfb->fb.changevar)
 		cfb->fb.changevar(con);
@@ -1015,18 +1005,18 @@
 
 	if (var->xoffset > (var->xres_virtual - var->xres))
 		return -EINVAL;
-	if (y_bottom > cfb->fb.var.yres_virtual)
+	if (y_bottom > cfb->display->var.yres_virtual)
 		return -EINVAL;
 
 	if (cyber2000fb_update_start(cfb, var))
 		return -EINVAL;
 
-	cfb->fb.var.xoffset = var->xoffset;
-	cfb->fb.var.yoffset = var->yoffset;
+	cfb->display->var.xoffset = var->xoffset;
+	cfb->display->var.yoffset = var->yoffset;
 	if (var->vmode & FB_VMODE_YWRAP) {
-		cfb->fb.var.vmode |= FB_VMODE_YWRAP;
+		cfb->display->var.vmode |= FB_VMODE_YWRAP;
 	} else {
-		cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
+		cfb->display->var.vmode &= ~FB_VMODE_YWRAP;
 	}
 
 	return 0;
@@ -1049,22 +1039,18 @@
 static int cyber2000fb_switch(int con, struct fb_info *info)
 {
 	struct cfb_info *cfb = (struct cfb_info *)info;
-	struct display *disp;
+	struct display *display = cfb->display;
 	struct fb_cmap *cmap;
 
-	if (cfb->currcon >= 0) {
-		disp = fb_display + cfb->currcon;
-
+	if (display) {
 		/*
 		 * Save the old colormap and video mode.
 		 */
-		disp->var = cfb->fb.var;
-		if (disp->cmap.len)
-			fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0);
+		if (display->cmap.len)
+			fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);
 	}
 
-	cfb->currcon = con;
-	disp = fb_display + con;
+	cfb->display = display = fb_display + con;
 
 	/*
 	 * Install the new colormap and change the video mode.  By default,
@@ -1075,17 +1061,15 @@
 	 * depth of the new video mode.  For now, we leave it at its
 	 * default 256 entry.
 	 */
-	if (disp->cmap.len)
-		cmap = &disp->cmap;
+	if (display->cmap.len)
+		cmap = &display->cmap;
 	else
-		cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
+		cmap = fb_default_cmap(1 << display->var.bits_per_pixel);
 
 	fb_copy_cmap(cmap, &cfb->fb.cmap, 0);
 
-	cfb->fb.var = disp->var;
-	cfb->fb.var.activate = FB_ACTIVATE_NOW;
-
-	cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb);
+	display->var.activate = FB_ACTIVATE_NOW;
+	cyber2000fb_set_var(&display->var, con, &cfb->fb);
 
 	return 0;
 }
@@ -1096,6 +1080,7 @@
 static void cyber2000fb_blank(int blank, struct fb_info *info)
 {
 	struct cfb_info *cfb = (struct cfb_info *)info;
+	unsigned int sync = 0;
 	int i;
 
 	/*
@@ -1116,16 +1101,26 @@
      
 	switch (blank) {
 	case 4:	/* powerdown - both sync lines down */
-    		cyber2000_grphw(0x16, 0x05, cfb);
+		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
 		break;	
 	case 3:	/* hsync off */
-    		cyber2000_grphw(0x16, 0x01, cfb);
+		sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
 		break;	
 	case 2:	/* vsync off */
-    		cyber2000_grphw(0x16, 0x04, cfb);
-		break;	
+		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
+		break;
+	case 1:	/* soft blank */
+		break;
+	default: /* unblank */
+		break;
+	}
+	cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
+
+	switch (blank) {
+	case 4:
+	case 3:
+	case 2:
 	case 1:	/* soft blank */
-		cyber2000_grphw(0x16, 0x00, cfb);
 		for (i = 0; i < NR_PALETTE; i++) {
 			cyber2000fb_writeb(i, 0x3c8, cfb);
 			cyber2000fb_writeb(0, 0x3c9, cfb);
@@ -1134,7 +1129,6 @@
 		}
 		break;
 	default: /* unblank */
-		cyber2000_grphw(0x16, 0x00, cfb);
 		for (i = 0; i < NR_PALETTE; i++) {
 			cyber2000fb_writeb(i, 0x3c8, cfb);
 			cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
@@ -1186,41 +1180,51 @@
 };
 
 /*
+ * This is the only "static" reference to the internal data structures
+ * of this driver.  It is here solely at the moment to support the other
+ * CyberPro modules external to this driver.
+ */
+static struct cfb_info		*int_cfb_info;
+
+/*
  * Enable access to the extended registers
  */
-static void cyber2000fb_enable_extregs(struct cfb_info *cfb)
+void cyber2000fb_enable_extregs(struct cfb_info *cfb)
 {
 	cfb->func_use_count += 1;
 
 	if (cfb->func_use_count == 1) {
 		int old;
 
-		old = cyber2000_grphr(FUNC_CTL, cfb);
-		cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
+		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
+		old |= EXT_FUNC_CTL_EXTREGENBL;
+		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
 	}
 }
 
 /*
  * Disable access to the extended registers
  */
-static void cyber2000fb_disable_extregs(struct cfb_info *cfb)
+void cyber2000fb_disable_extregs(struct cfb_info *cfb)
 {
 	if (cfb->func_use_count == 1) {
 		int old;
 
-		old = cyber2000_grphr(FUNC_CTL, cfb);
-		cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
+		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
+		old &= ~EXT_FUNC_CTL_EXTREGENBL;
+		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
 	}
 
-	cfb->func_use_count -= 1;
+	if (cfb->func_use_count == 0)
+		printk(KERN_ERR "disable_extregs: count = 0\n");
+	else
+		cfb->func_use_count -= 1;
 }
 
-/*
- * This is the only "static" reference to the internal data structures
- * of this driver.  It is here solely at the moment to support the other
- * CyberPro modules external to this driver.
- */
-static struct cfb_info		*int_cfb_info;
+void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
+{
+	memcpy(var, &cfb->display->var, sizeof(struct fb_var_screeninfo));
+}
 
 /*
  * Attach a capture/tv driver to the core CyberX0X0 driver.
@@ -1254,6 +1258,9 @@
 
 EXPORT_SYMBOL(cyber2000fb_attach);
 EXPORT_SYMBOL(cyber2000fb_detach);
+EXPORT_SYMBOL(cyber2000fb_enable_extregs);
+EXPORT_SYMBOL(cyber2000fb_disable_extregs);
+EXPORT_SYMBOL(cyber2000fb_get_fb_var);
 
 /*
  * These parameters give
@@ -1275,143 +1282,60 @@
 };
 
 static char igs_regs[] __devinitdata = {
-					0x12, 0x00,	0x13, 0x00,
-					0x16, 0x00,
-			0x31, 0x00,	0x32, 0x00,
-	0x50, 0x00,	0x51, 0x00,	0x52, 0x00,	0x53, 0x00,
-	0x54, 0x00,	0x55, 0x00,	0x56, 0x00,	0x57, 0x01,
-	0x58, 0x00,	0x59, 0x00,	0x5a, 0x00,
-	0x70, 0x0b,					0x73, 0x30,
-	0x74, 0x0b,	0x75, 0x17,	0x76, 0x00,	0x7a, 0xc8
+	EXT_CRT_IRQ,		0,
+	EXT_CRT_TEST,		0,
+	EXT_SYNC_CTL,		0,
+	EXT_SEG_WRITE_PTR,	0,
+	EXT_SEG_READ_PTR,	0,
+	EXT_BIU_MISC,		EXT_BIU_MISC_LIN_ENABLE |
+				EXT_BIU_MISC_COP_ENABLE |
+				EXT_BIU_MISC_COP_BFC,
+	EXT_FUNC_CTL,		0,
+	CURS_H_START,		0,
+	CURS_H_START + 1,	0,
+	CURS_H_PRESET,		0,
+	CURS_V_START,		0,
+	CURS_V_START + 1,	0,
+	CURS_V_PRESET,		0,
+	CURS_CTL,		0,
+	EXT_ATTRIB_CTL,		EXT_ATTRIB_CTL_EXT,
+	EXT_OVERSCAN_RED,	0,
+	EXT_OVERSCAN_GREEN,	0,
+	EXT_OVERSCAN_BLUE,	0,
+
+	/* some of these are questionable when we have a BIOS */
+	EXT_MEM_CTL0,		EXT_MEM_CTL0_7CLK |
+				EXT_MEM_CTL0_RAS_1 |
+				EXT_MEM_CTL0_MULTCAS,
+	EXT_HIDDEN_CTL1,	0x30,
+	EXT_FIFO_CTL,		0x0b,
+	EXT_FIFO_CTL + 1,	0x17,
+	0x76,			0x00,
+	EXT_HIDDEN_CTL4,	0xc8
 };
 
 /*
- * We need to wake up the CyberPro, and make sure its in linear memory
- * mode.  Unfortunately, this is specific to the platform and card that
- * we are running on.
- *
- * On x86 and ARM, should we be initialising the CyberPro first via the
- * IO registers, and then the MMIO registers to catch all cases?  Can we
- * end up in the situation where the chip is in MMIO mode, but not awake
- * on an x86 system?
- *
- * Note that on the NetWinder, the firmware automatically detects the
- * type, width and size, and leaves this in extended registers 0x71 and
- * 0x72 for us.
+ * Initialise the CyberPro hardware.  On the CyberPro5XXXX,
+ * ensure that we're using the correct PLL (5XXX's may be
+ * programmed to use an additional set of PLLs.)
  */
-static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
+static void cyberpro_init_hw(struct cfb_info *cfb)
 {
 	int i;
 
-	/*
-	 * Wake up the CyberPro.
-	 */
-#ifdef __sparc__
-#ifdef __sparc_v9__
-#error "You loose, consult DaveM."
-#else
-	/*
-	 * SPARC does not have an "outb" instruction, so we generate
-	 * I/O cycles storing into a reserved memory space at
-	 * physical address 0x3000000
-	 */
-	{
-		unsigned char *iop;
-
-		iop = ioremap(0x3000000, 0x5000);
-		if (iop == NULL) {
-			prom_printf("iga5000: cannot map I/O\n");
-			return -ENOMEM;
-		}
-
-		writeb(0x18, iop + 0x46e8);
-		writeb(0x01, iop + 0x102);
-		writeb(0x08, iop + 0x46e8);
-		writeb(0x33, iop + 0x3ce);
-		writeb(0x01, iop + 0x3cf);
-
-		iounmap((void *)iop);
-	}
-#endif
-
-	if (at_boot) {
-		/*
-		 * Use mclk from BIOS.  Only read this if we're
-		 * initialising this card for the first time.
-		 * FIXME: what about hotplug?
-		 */
-		cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
-		cfb->mclk_div  = cyber2000_grphr(MCLK_DIV, cfb);
-	}
-#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
-	/*
-	 * x86 and MIPS are simple, we just do regular
-	 * outb's instead of cyber2000fb_writeb.
-	 */
-	outb(0x18, 0x46e8);
-	outb(0x01, 0x102);
-	outb(0x08, 0x46e8);
-	outb(0x33, 0x3ce);
-	outb(0x01, 0x3cf);
-
-	if (at_boot) {
-		/*
-		 * Use mclk from BIOS.  Only read this if we're
-		 * initialising this card for the first time.
-		 * FIXME: what about hotplug?
-		 */
-		cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
-		cfb->mclk_div  = cyber2000_grphr(MCLK_DIV, cfb);
-	}
-#endif
-#ifdef __arm__
-	cyber2000fb_writeb(0x18, 0x46e8, cfb);
-	cyber2000fb_writeb(0x01, 0x102, cfb);
-	cyber2000fb_writeb(0x08, 0x46e8, cfb);
-	cyber2000fb_writeb(0x33, 0x3ce, cfb);
-	cyber2000fb_writeb(0x01, 0x3cf, cfb);
-
-	/*
-	 * MCLK on the NetWinder and the Shark is fixed at 75MHz
-	 */
-	cfb->mclk_mult = 0xdb;
-	cfb->mclk_div  = 0x54;
-#endif
-
-	/*
-	 * Initialise the CyberPro
-	 */
 	for (i = 0; i < sizeof(igs_regs); i += 2)
 		cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
 
-	if (at_boot) {
-		/*
-		 * get the video RAM size and width from the VGA register.
-		 * This should have been already initialised by the BIOS,
-		 * but if it's garbage, claim default 1MB VRAM (woody)
-		 */
-		cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
-		cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
-	} else {
-		/*
-		 * Reprogram the MEM_CTL1 and MEM_CTL2 registers
-		 */
-		cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
-		cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
+	if (cfb->fb.fix.accel == FB_ACCEL_IGS_CYBER5000) {
+		unsigned char val;
+		cyber2000fb_writeb(0xba, 0x3ce, cfb);
+		val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
+		cyber2000fb_writeb(val, 0x3cf, cfb);
 	}
-
-	/*
-	 * Ensure thatwe are using the correct PLL.
-	 * (CyberPro 5000's may be programmed to use
-	 * an additional set of PLLs.
-	 */
-	cyber2000fb_writeb(0xba, 0x3ce, cfb);
-	cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
 }
 
 static struct cfb_info * __devinit
-cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
+cyberpro_alloc_fb_info(unsigned int id, char *name)
 {
 	struct cfb_info *cfb;
 
@@ -1423,10 +1347,7 @@
 
 	memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
 
-	cfb->currcon		= -1;
-	cfb->dev		= dev;
-
-	if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
+	if (id == ID_CYBERPRO_5000)
 		cfb->ref_ps	= 40690; // 24.576 MHz
 	else
 		cfb->ref_ps	= 69842; // 14.31818 MHz (69841?)
@@ -1435,7 +1356,7 @@
 	cfb->divisors[1]	= 2;
 	cfb->divisors[2]	= 4;
 
-	if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
+	if (id == ID_CYBERPRO_2000)
 		cfb->divisors[3] = 8;
 	else
 		cfb->divisors[3] = 6;
@@ -1447,7 +1368,24 @@
 	cfb->fb.fix.xpanstep	= 0;
 	cfb->fb.fix.ypanstep	= 1;
 	cfb->fb.fix.ywrapstep	= 0;
-	cfb->fb.fix.accel	= id->driver_data;
+
+	switch (id) {
+	case ID_IGA_1682:
+		cfb->fb.fix.accel = 0;
+		break;
+
+	case ID_CYBERPRO_2000:
+		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
+		break;
+
+	case ID_CYBERPRO_2010:
+		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
+		break;
+
+	case ID_CYBERPRO_5000:
+		cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
+		break;
+	}
 
 	cfb->fb.var.nonstd	= 0;
 	cfb->fb.var.activate	= FB_ACTIVATE_NOW;
@@ -1464,6 +1402,7 @@
 	cfb->fb.updatevar	= cyber2000fb_updatevar;
 	cfb->fb.blank		= cyber2000fb_blank;
 	cfb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	cfb->fb.node		= NODEV;
 	cfb->fb.disp		= (struct display *)(cfb + 1);
 	cfb->fb.pseudo_palette	= (void *)(cfb->fb.disp + 1);
 
@@ -1512,55 +1451,43 @@
 	return 0;
 }
 
-static int __devinit
-cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
+/*
+ * The CyberPro chips can be placed on many different bus types.
+ * This probe function is common to all bus types.  The bus-specific
+ * probe function is expected to have:
+ *  - enabled access to the linear memory region
+ *  - memory mapped access to the registers
+ *  - initialised mem_ctl1 and mem_ctl2 appropriately.
+ */
+static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
 {
-	struct cfb_info *cfb;
-	u_int h_sync, v_sync;
 	u_long smem_size;
-	char name[16];
+	u_int h_sync, v_sync;
 	int err;
 
-	sprintf(name, "CyberPro%4X", id->device);
-
-	err = pci_enable_device(dev);
-	if (err)
-		return err;
-
-	err = pci_request_regions(dev, name);
-	if (err)
-		return err;
-
-	err = -ENOMEM;
-	cfb = cyberpro_alloc_fb_info(dev, id, name);
-	if (!cfb)
-		goto failed_release;
-
-	cfb->region = ioremap(pci_resource_start(dev, 0),
-			      pci_resource_len(dev, 0));
-	if (!cfb->region)
-		goto failed_ioremap;
-
-	cfb->regs = cfb->region + MMIO_OFFSET;
-
-	cyberpro_init_hw(cfb, 1);
+	/*
+	 * Get the video RAM size and width from the VGA register.
+	 * This should have been already initialised by the BIOS,
+	 * but if it's garbage, claim default 1MB VRAM (woody)
+	 */
+	cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
+	cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
 
+	/*
+	 * Determine the size of the memory.
+	 */
 	switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
 	case MEM_CTL2_SIZE_4MB:	smem_size = 0x00400000; break;
 	case MEM_CTL2_SIZE_2MB:	smem_size = 0x00200000; break;
+	case MEM_CTL2_SIZE_1MB: smem_size = 0x00100000; break;
 	default:		smem_size = 0x00100000; break;
 	}
 
-	/*
-	 * Hmm, we _need_ a portable way of finding the address for
-	 * the remap stuff, both for mmio and for smem.
-	 */
-	cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
-	cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
-	cfb->fb.fix.mmio_len   = MMIO_SIZE;
 	cfb->fb.fix.smem_len   = smem_size;
+	cfb->fb.fix.mmio_len   = MMIO_SIZE;
 	cfb->fb.screen_base    = cfb->region;
 
+	err = -EINVAL;
 	if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
 	    		  &cyber2000fb_default_mode, 8)) {
 		printk("%s: no valid mode found\n", cfb->fb.fix.id);
@@ -1587,13 +1514,210 @@
 	v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
 		 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
 
-	printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+	printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
 		cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
 		cfb->fb.var.xres, cfb->fb.var.yres,
 		h_sync / 1000, h_sync % 1000, v_sync);
 
 	err = register_framebuffer(&cfb->fb);
-	if (err < 0)
+
+failed:
+	return err;
+}
+
+static void cyberpro_common_resume(struct cfb_info *cfb)
+{
+	cyberpro_init_hw(cfb);
+
+	/*
+	 * Reprogram the MEM_CTL1 and MEM_CTL2 registers
+	 */
+	cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
+	cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
+
+	/*
+	 * Restore the old video mode and the palette.
+	 * We also need to tell fbcon to redraw the console.
+	 */
+	cfb->fb.var.activate = FB_ACTIVATE_NOW;
+	cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
+}
+
+#ifdef CONFIG_ARCH_SHARK
+
+#include <asm/arch/hardware.h>
+
+static int __devinit
+cyberpro_vl_probe(void)
+{
+	struct cfb_info *cfb;
+	int err = -ENOMEM;
+
+	if (!request_mem_region(FB_START,FB_SIZE,"CyberPro2010")) return err;
+
+	cfb = cyberpro_alloc_fb_info(ID_CYBERPRO_2010, "CyberPro2010");
+	if (!cfb)
+		goto failed_release;
+
+	cfb->dev = NULL;
+	cfb->region = ioremap(FB_START,FB_SIZE);
+	if (!cfb->region)
+		goto failed_ioremap;
+
+	cfb->regs = cfb->region + MMIO_OFFSET;
+	cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET;
+	cfb->fb.fix.smem_start = FB_START;
+
+	/*
+	 * Bring up the hardware.  This is expected to enable access
+	 * to the linear memory region, and allow access to the memory
+	 * mapped registers.  Also, mem_ctl1 and mem_ctl2 must be
+	 * initialised.
+	 */
+	cyber2000fb_writeb(0x18, 0x46e8, cfb);
+	cyber2000fb_writeb(0x01, 0x102, cfb);
+	cyber2000fb_writeb(0x08, 0x46e8, cfb);
+	cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
+	cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
+
+	cfb->mclk_mult = 0xdb;
+	cfb->mclk_div  = 0x54;
+
+	cyberpro_init_hw(cfb);
+
+	err = cyberpro_common_probe(cfb);
+	if (err)
+		goto failed;
+
+	if (int_cfb_info == NULL)
+		int_cfb_info = cfb;
+
+	return 0;
+
+failed:
+	iounmap(cfb->region);
+failed_ioremap:
+	cyberpro_free_fb_info(cfb);
+failed_release:
+	release_mem_region(FB_START,FB_SIZE);
+
+	return err;
+}
+#endif /* CONFIG_ARCH_SHARK */
+
+/*
+ * PCI specific support.
+ */
+#ifdef CONFIG_PCI
+/*
+ * We need to wake up the CyberPro, and make sure its in linear memory
+ * mode.  Unfortunately, this is specific to the platform and card that
+ * we are running on.
+ *
+ * On x86 and ARM, should we be initialising the CyberPro first via the
+ * IO registers, and then the MMIO registers to catch all cases?  Can we
+ * end up in the situation where the chip is in MMIO mode, but not awake
+ * on an x86 system?
+ */
+static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
+{
+#if defined(__sparc_v9__)
+#error "You loose, consult DaveM."
+#elif defined(__sparc__)
+	/*
+	 * SPARC does not have an "outb" instruction, so we generate
+	 * I/O cycles storing into a reserved memory space at
+	 * physical address 0x3000000
+	 */
+	unsigned char *iop;
+
+	iop = ioremap(0x3000000, 0x5000);
+	if (iop == NULL) {
+		prom_printf("iga5000: cannot map I/O\n");
+		return -ENOMEM;
+	}
+
+	writeb(0x18, iop + 0x46e8);
+	writeb(0x01, iop + 0x102);
+	writeb(0x08, iop + 0x46e8);
+	writeb(EXT_BIU_MISC, iop + 0x3ce);
+	writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
+
+	iounmap((void *)iop);
+#else
+	/*
+	 * Most other machine types are "normal", so
+	 * we use the standard IO-based wakeup.
+	 */
+	outb(0x18, 0x46e8);
+	outb(0x01, 0x102);
+	outb(0x08, 0x46e8);
+	outb(EXT_BIU_MISC, 0x3ce);
+	outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
+#endif
+	return 0;
+}
+
+static int __devinit
+cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct cfb_info *cfb;
+	char name[16];
+	int err;
+
+	sprintf(name, "CyberPro%4X", id->device);
+
+	err = pci_enable_device(dev);
+	if (err)
+		return err;
+
+	err = pci_request_regions(dev, name);
+	if (err)
+		return err;
+
+	err = -ENOMEM;
+	cfb = cyberpro_alloc_fb_info(id->driver_data, name);
+	if (!cfb)
+		goto failed_release;
+
+	cfb->dev = dev;
+	cfb->region = ioremap(pci_resource_start(dev, 0),
+			      pci_resource_len(dev, 0));
+	if (!cfb->region)
+		goto failed_ioremap;
+
+	cfb->regs = cfb->region + MMIO_OFFSET;
+	cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
+	cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+
+	/*
+	 * Bring up the hardware.  This is expected to enable access
+	 * to the linear memory region, and allow access to the memory
+	 * mapped registers.  Also, mem_ctl1 and mem_ctl2 must be
+	 * initialised.
+	 */
+	err = cyberpro_pci_enable_mmio(cfb);
+	if (err)
+		goto failed;
+
+	/*
+	 * Use MCLK from BIOS. FIXME: what about hotplug?
+	 */
+#ifndef __arm__
+	cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
+	cfb->mclk_div  = cyber2000_grphr(MCLK_DIV, cfb);
+#else
+	/*
+	 * MCLK on the NetWinder and the Shark is fixed at 75MHz
+	 */
+	cfb->mclk_mult = 0xdb;
+	cfb->mclk_div  = 0x54;
+#endif
+
+	cyberpro_init_hw(cfb);
+
+	err = cyberpro_common_probe(cfb);
+	if (err)
 		goto failed;
 
 	/*
@@ -1615,7 +1739,7 @@
 	return err;
 }
 
-static void __devexit cyberpro_remove(struct pci_dev *dev)
+static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
 {
 	struct cfb_info *cfb = pci_get_drvdata(dev);
 
@@ -1644,7 +1768,7 @@
 	}
 }
 
-static int cyberpro_suspend(struct pci_dev *dev, u32 state)
+static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
 {
 	return 0;
 }
@@ -1652,42 +1776,42 @@
 /*
  * Re-initialise the CyberPro hardware
  */
-static int cyberpro_resume(struct pci_dev *dev)
+static int cyberpro_pci_resume(struct pci_dev *dev)
 {
 	struct cfb_info *cfb = pci_get_drvdata(dev);
 
 	if (cfb) {
-		cyberpro_init_hw(cfb, 0);
-
-		/*
-		 * Restore the old video mode and the palette.
-		 * We also need to tell fbcon to redraw the console.
-		 */
-		cfb->fb.var.activate = FB_ACTIVATE_NOW;
-		cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb);
+		cyberpro_pci_enable_mmio(cfb);
+		cyberpro_common_resume(cfb);
 	}
 
 	return 0;
 }
 
 static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
+// Not yet
+//	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
+//		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
 	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
 	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
 	{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 },
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
 	{ 0, }
 };
 
+MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
+
 static struct pci_driver cyberpro_driver = {
 	name:		"CyberPro",
-	probe:		cyberpro_probe,
-	remove:		__devexit_p(cyberpro_remove),
-	suspend:	cyberpro_suspend,
-	resume:		cyberpro_resume,
+	probe:		cyberpro_pci_probe,
+	remove:		__devexit_p(cyberpro_pci_remove),
+	suspend:	cyberpro_pci_suspend,
+	resume:		cyberpro_pci_resume,
 	id_table:	cyberpro_pci_table
 };
+#endif
 
 /*
  * I don't think we can use the "module_init" stuff here because
@@ -1696,7 +1820,19 @@
  */
 int __init cyber2000fb_init(void)
 {
-	return pci_module_init(&cyberpro_driver);
+	int ret = -1, err = -ENODEV;
+#ifdef CONFIG_ARCH_SHARK
+	err = cyberpro_vl_probe();
+	if (!err) {
+		ret = err;
+		MOD_INC_USE_COUNT;
+	}
+#endif
+	err = pci_module_init(&cyberpro_driver);
+	if (!err)
+		ret = err;
+
+	return ret ? err : 0;
 }
 
 static void __exit cyberpro_exit(void)
@@ -1711,5 +1847,4 @@
 
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
-MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/cyber2000fb.h b/drivers/video/cyber2000fb.h
--- a/drivers/video/cyber2000fb.h	Sun Apr 14 12:16:56 2002
+++ b/drivers/video/cyber2000fb.h	Sun Apr 14 12:16:56 2002
@@ -40,18 +40,44 @@
 #define PIXFORMAT_16BPP		1
 #define PIXFORMAT_24BPP		2
 
-#define VISUALID_256		1
-#define VISUALID_64K		2
-#define VISUALID_16M		4
-#define VISUALID_32K		6
-
-#define FUNC_CTL		0x3c
-#define FUNC_CTL_EXTREGENBL		0x80	/* enable access to 0xbcxxx		*/
-
-#define BIU_BM_CONTROL		0x3e
-#define BIU_BM_CONTROL_ENABLE		0x01	/* enable bus-master			*/
-#define BIU_BM_CONTROL_BURST		0x02	/* enable burst				*/
-#define BIU_BM_CONTROL_BACK2BACK	0x04	/* enable back to back			*/
+#define EXT_CRT_IRQ		0x12
+#define EXT_CRT_IRQ_ENABLE		0x01
+#define EXT_CRT_IRQ_ACT_HIGH		0x04
+
+#define EXT_CRT_TEST		0x13
+
+#define EXT_SYNC_CTL		0x16
+#define EXT_SYNC_CTL_HS_NORMAL		0x00
+#define EXT_SYNC_CTL_HS_0		0x01
+#define EXT_SYNC_CTL_HS_1		0x02
+#define EXT_SYNC_CTL_HS_HSVS		0x03
+#define EXT_SYNC_CTL_VS_NORMAL		0x00
+#define EXT_SYNC_CTL_VS_0		0x04
+#define EXT_SYNC_CTL_VS_1		0x08
+#define EXT_SYNC_CTL_VS_COMP		0x0c
+
+#define EXT_BUS_CTL		0x30
+#define EXT_BUS_CTL_LIN_1MB		0x00
+#define EXT_BUS_CTL_LIN_2MB		0x01
+#define EXT_BUS_CTL_LIN_4MB		0x02
+#define EXT_BUS_CTL_ZEROWAIT		0x04
+#define EXT_BUS_CTL_PCIBURST		0x20
+
+#define EXT_SEG_WRITE_PTR	0x31
+#define EXT_SEG_READ_PTR	0x32
+#define EXT_BIU_MISC		0x33
+#define EXT_BIU_MISC_LIN_ENABLE		0x01
+#define EXT_BIU_MISC_COP_ENABLE		0x04
+#define EXT_BIU_MISC_COP_BFC		0x08
+
+#define EXT_FUNC_CTL		0x3c
+#define EXT_FUNC_CTL_EXTREGENBL		0x80	/* enable access to 0xbcxxx		*/
+
+#define PCI_BM_CTL		0x3e
+#define PCI_BM_CTL_ENABLE		0x01	/* enable bus-master			*/
+#define PCI_BM_CTL_BURST		0x02	/* enable burst				*/
+#define PCI_BM_CTL_BACK2BACK		0x04	/* enable back to back			*/
+#define PCI_BM_CTL_DUMMY		0x08	/* insert dummy cycle			*/
 
 #define X_V2_VID_MEM_START	0x40
 #define X_V2_VID_SRC_WIDTH	0x43
@@ -85,6 +111,19 @@
 
 #define K_CAP_X2_CTL1		0x49
 
+#define CURS_H_START		0x50
+#define CURS_H_PRESET		0x52
+#define CURS_V_START		0x53
+#define CURS_V_PRESET		0x55
+#define CURS_CTL		0x56
+
+#define EXT_ATTRIB_CTL		0x57
+#define EXT_ATTRIB_CTL_EXT		0x01
+
+#define EXT_OVERSCAN_RED	0x58
+#define EXT_OVERSCAN_GREEN	0x59
+#define EXT_OVERSCAN_BLUE	0x5a
+
 #define CAP_X_START		0x60
 #define CAP_X_END		0x62
 #define CAP_Y_START		0x64
@@ -94,46 +133,112 @@
 #define CAP_DDA_Y_INIT		0x6c
 #define CAP_DDA_Y_INC		0x6e
 
-#define MEM_CTL1		0x71
+#define EXT_MEM_CTL0		0x70
+#define EXT_MEM_CTL0_7CLK		0x01
+#define EXT_MEM_CTL0_RAS_1		0x02
+#define EXT_MEM_CTL0_RAS2CAS_1		0x04
+#define EXT_MEM_CTL0_MULTCAS		0x08
+#define EXT_MEM_CTL0_ASYM		0x10
+#define EXT_MEM_CTL0_CAS1ON		0x20
+#define EXT_MEM_CTL0_FIFOFLUSH		0x40
+#define EXT_MEM_CTL0_SEQRESET		0x80
+
+#define EXT_MEM_CTL1		0x71
+#define EXT_MEM_CTL1_PAR		0x00
+#define EXT_MEM_CTL1_SERPAR		0x01
+#define EXT_MEM_CTL1_SER		0x03
+#define EXT_MEM_CTL1_SYNC		0x04
+#define EXT_MEM_CTL1_VRAM		0x08
+#define EXT_MEM_CTL1_4K_REFRESH		0x10
+#define EXT_MEM_CTL1_256Kx4		0x00
+#define EXT_MEM_CTL1_512Kx8		0x40
+#define EXT_MEM_CTL1_1Mx16		0x60
 
-#define MEM_CTL2		0x72
+#define EXT_MEM_CTL2		0x72
+#define MEM_CTL2_SIZE_1MB		0x00
 #define MEM_CTL2_SIZE_2MB		0x01
 #define MEM_CTL2_SIZE_4MB		0x02
 #define MEM_CTL2_SIZE_MASK		0x03
 #define MEM_CTL2_64BIT			0x04
 
+#define EXT_HIDDEN_CTL1		0x73
+
 #define EXT_FIFO_CTL		0x74
 
+#define EXT_SEQ_MISC		0x77
+#define EXT_SEQ_MISC_8			0x01
+#define EXT_SEQ_MISC_16_RGB565		0x02
+#define EXT_SEQ_MISC_32			0x03
+#define EXT_SEQ_MISC_24_RGB888		0x04
+#define EXT_SEQ_MISC_16_RGB555		0x06
+#define EXT_SEQ_MISC_8_RGB332		0x09
+#define EXT_SEQ_MISC_16_RGB444		0x0a
+
+#define EXT_HIDDEN_CTL4		0x7a
+
+#define CURS_MEM_START		0x7e		/* bits 23..12 */
+
 #define CAP_PIP_X_START		0x80
 #define CAP_PIP_X_END		0x82
 #define CAP_PIP_Y_START		0x84
 #define CAP_PIP_Y_END		0x86
 
-#define CAP_NEW_CTL1		0x88
+#define EXT_CAP_CTL1		0x88
 
-#define CAP_NEW_CTL2		0x89
+#define EXT_CAP_CTL2		0x89
+#define EXT_CAP_CTL2_ODDFRAMEIRQ	0x01
+#define EXT_CAP_CTL2_ANYFRAMEIRQ	0x02
 
 #define BM_CTRL0		0x9c
 #define BM_CTRL1		0x9d
 
-#define CAP_MODE1		0xa4
-#define CAP_MODE1_8BIT			0x01	/* enable 8bit capture mode		*/
-#define CAP_MODE1_CCIR656		0x02	/* CCIR656 mode				*/
-#define CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT				*/
-#define CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture	*/
-#define CAP_MODE1_SWAPUV		0x20	/* swap UV bytes			*/
-#define CAP_MODE1_MIRRORY		0x40	/* mirror vertically			*/
-#define CAP_MODE1_MIRRORX		0x80	/* mirror horizontally			*/
-
-#define DCLK_MULT		0xb0
-#define DCLK_DIV		0xb1
-#define DCLK_DIV_VFSEL			0x20
-#define MCLK_MULT		0xb2
-#define MCLK_DIV		0xb3
-
-#define CAP_MODE2		0xa5
-
-#define Y_TV_CTL		0xae
+#define EXT_CAP_MODE1		0xa4
+#define EXT_CAP_MODE1_8BIT		0x01	/* enable 8bit capture mode		*/
+#define EXT_CAP_MODE1_CCIR656		0x02	/* CCIR656 mode				*/
+#define EXT_CAP_MODE1_IGNOREVGT		0x04	/* ignore VGT				*/
+#define EXT_CAP_MODE1_ALTFIFO		0x10	/* use alternate FIFO for capture	*/
+#define EXT_CAP_MODE1_SWAPUV		0x20	/* swap UV bytes			*/
+#define EXT_CAP_MODE1_MIRRORY		0x40	/* mirror vertically			*/
+#define EXT_CAP_MODE1_MIRRORX		0x80	/* mirror horizontally			*/
+
+#define EXT_CAP_MODE2		0xa5
+#define EXT_CAP_MODE2_CCIRINVOE		0x01
+#define EXT_CAP_MODE2_CCIRINVVGT	0x02
+#define EXT_CAP_MODE2_CCIRINVHGT	0x04
+#define EXT_CAP_MODE2_CCIRINVDG		0x08
+#define EXT_CAP_MODE2_DATEND		0x10
+#define EXT_CAP_MODE2_CCIRDGH		0x20
+#define EXT_CAP_MODE2_FIXSONY		0x40
+#define EXT_CAP_MODE2_SYNCFREEZE	0x80
+
+#define EXT_TV_CTL		0xae
+
+#define EXT_DCLK_MULT		0xb0
+#define EXT_DCLK_DIV		0xb1
+#define EXT_DCLK_DIV_VFSEL		0x20
+#define EXT_MCLK_MULT		0xb2
+#define EXT_MCLK_DIV		0xb3
+
+#define EXT_LATCH1		0xb5
+#define EXT_LATCH1_VAFC_EN		0x01	/* enable VAFC				*/
+
+#define EXT_FEATURE		0xb7
+#define EXT_FEATURE_BUS_MASK		0x07	/* host bus mask			*/
+#define EXT_FEATURE_BUS_PCI		0x00
+#define EXT_FEATURE_BUS_VL_STD		0x04
+#define EXT_FEATURE_BUS_VL_LINEAR	0x05
+#define EXT_FEATURE_1682		0x20	/* IGS 1682 compatibility		*/
+
+#define EXT_LATCH2		0xb6
+#define EXT_LATCH2_I2C_CLKEN		0x10
+#define EXT_LATCH2_I2C_CLK		0x20
+#define EXT_LATCH2_I2C_DATEN		0x40
+#define EXT_LATCH2_I2C_DAT		0x80
+
+#define EXT_XT_CTL		0xbe
+#define EXT_XT_CAP16			0x04
+#define EXT_XT_LINEARFB			0x08
+#define EXT_XT_PAL			0x10
 
 #define EXT_MEM_START		0xc0		/* ext start address 21 bits		*/
 #define HOR_PHASE_SHIFT		0xc2		/* high 3 bits				*/
@@ -158,25 +263,37 @@
 #define EXT_VID_FMT_RGB565		0x02
 #define EXT_VID_FMT_RGB888_24		0x03
 #define EXT_VID_FMT_RGB888_32		0x04
+#define EXT_VID_FMT_RGB8		0x05
+#define EXT_VID_FMT_RGB4444		0x06
+#define EXT_VID_FMT_RGB8T		0x07
 #define EXT_VID_FMT_DUP_PIX_ZOON	0x08	/* duplicate pixel zoom			*/
 #define EXT_VID_FMT_MOD_3RD_PIX		0x20	/* modify 3rd duplicated pixel		*/
 #define EXT_VID_FMT_DBL_H_PIX		0x40	/* double horiz pixels			*/
-#define EXT_VID_FMT_UV128		0x80	/* UV data offset by 128		*/
+#define EXT_VID_FMT_YUV128		0x80	/* YUV data offset by 128		*/
 
 #define EXT_VID_DISP_CTL1	0xdc
 #define EXT_VID_DISP_CTL1_INTRAM	0x01	/* video pixels go to internal RAM	*/
 #define EXT_VID_DISP_CTL1_IGNORE_CCOMP	0x02	/* ignore colour compare registers	*/
 #define EXT_VID_DISP_CTL1_NOCLIP	0x04	/* do not clip to 16235,16240		*/
 #define EXT_VID_DISP_CTL1_UV_AVG	0x08	/* U/V data is averaged			*/
-#define EXT_VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128			*/
-#define EXT_VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* vertical interpolation off		*/
+#define EXT_VID_DISP_CTL1_Y128		0x10	/* Y data offset by 128 (if YUV128 set)	*/
+#define EXT_VID_DISP_CTL1_VINTERPOL_OFF	0x20	/* disable vertical interpolation	*/
 #define EXT_VID_DISP_CTL1_FULL_WIN	0x40	/* video out window full		*/
 #define EXT_VID_DISP_CTL1_ENABLE_WINDOW	0x80	/* enable video window			*/
 
 #define EXT_VID_FIFO_CTL1	0xdd
+#define EXT_VID_FIFO_CTL1_OE_HIGH	0x02
+#define EXT_VID_FIFO_CTL1_INTERLEAVE	0x04	/* enable interleaved memory read	*/
+
+#define EXT_ROM_UCB4GH		0xe5
+#define EXT_ROM_UCB4GH_FREEZE		0x02	/* capture frozen			*/
+#define EXT_ROM_UCB4GH_ODDFRAME		0x04	/* 1 = odd frame captured		*/
+#define EXT_ROM_UCB4GH_1HL		0x08	/* first horizonal line after VGT falling edge */
+#define EXT_ROM_UCB4GH_ODD		0x10	/* odd frame indicator			*/
+#define EXT_ROM_UCB4GH_INTSTAT		0x20	/* video interrupt			*/
 
 #define VFAC_CTL1		0xe8
-#define VFAC_CTL1_CAPTURE		0x01	/* capture enable			*/
+#define VFAC_CTL1_CAPTURE		0x01	/* capture enable (only when VSYNC high)*/
 #define VFAC_CTL1_VFAC_ENABLE		0x02	/* vfac enable				*/
 #define VFAC_CTL1_FREEZE_CAPTURE	0x04	/* freeze capture			*/
 #define VFAC_CTL1_FREEZE_CAPTURE_SYNC	0x08	/* sync freeze capture			*/
@@ -195,6 +312,13 @@
 #define VFAC_CTL2_INVERT_OVSYNC		0x80	/* invert other vsync input		*/
 
 #define VFAC_CTL3		0xea
+#define VFAC_CTL3_CAP_LARGE_FIFO	0x01	/* large capture fifo			*/
+#define VFAC_CTL3_CAP_INTERLACE		0x02	/* capture odd and even fields		*/
+#define VFAC_CTL3_CAP_HOLD_4NS		0x00	/* hold capture data for 4ns		*/
+#define VFAC_CTL3_CAP_HOLD_2NS		0x04	/* hold capture data for 2ns		*/
+#define VFAC_CTL3_CAP_HOLD_6NS		0x08	/* hold capture data for 6ns		*/
+#define VFAC_CTL3_CAP_HOLD_0NS		0x0c	/* hold capture data for 0ns		*/
+#define VFAC_CTL3_CHROMAKEY		0x20	/* capture data will be chromakeyed	*/
 #define VFAC_CTL3_CAP_IRQ		0x40	/* enable capture interrupt		*/
 
 #define CAP_MEM_START		0xeb		/* 18 bits				*/
@@ -233,6 +357,48 @@
 #define BM_COUNT		0xbc090		/* read-only				*/
 
 /*
+ * TV registers
+ */
+#define TV_VBLANK_EVEN_START	0xbe43c
+#define TV_VBLANK_EVEN_END	0xbe440
+#define TV_VBLANK_ODD_START	0xbe444
+#define TV_VBLANK_ODD_END	0xbe448
+#define TV_SYNC_YGAIN		0xbe44c
+#define TV_UV_GAIN		0xbe450
+#define TV_PED_UVDET		0xbe454
+#define TV_UV_BURST_AMP		0xbe458
+#define TV_HSYNC_START		0xbe45c
+#define TV_HSYNC_END		0xbe460
+#define TV_Y_DELAY1		0xbe464
+#define TV_Y_DELAY2		0xbe468
+#define TV_UV_DELAY1		0xbe46c
+#define TV_BURST_START		0xbe470
+#define TV_BURST_END		0xbe474
+#define TV_HBLANK_START		0xbe478
+#define TV_HBLANK_END		0xbe47c
+#define TV_PED_EVEN_START	0xbe480
+#define TV_PED_EVEN_END		0xbe484
+#define TV_PED_ODD_START	0xbe488
+#define TV_PED_ODD_END		0xbe48c
+#define TV_VSYNC_EVEN_START	0xbe490
+#define TV_VSYNC_EVEN_END	0xbe494
+#define TV_VSYNC_ODD_START	0xbe498
+#define TV_VSYNC_ODD_END	0xbe49c
+#define TV_SCFL			0xbe4a0
+#define TV_SCFH			0xbe4a4
+#define TV_SCP			0xbe4a8
+#define TV_DELAYBYPASS		0xbe4b4
+#define TV_EQL_END		0xbe4bc
+#define TV_SERR_START		0xbe4c0
+#define TV_SERR_END		0xbe4c4
+#define TV_CTL			0xbe4dc	/* reflects a previous register- MVFCLR, MVPCLR etc P241*/
+#define TV_VSYNC_VGA_HS		0xbe4e8
+#define TV_FLICK_XMIN		0xbe514
+#define TV_FLICK_XMAX		0xbe518
+#define TV_FLICK_YMIN		0xbe51c
+#define TV_FLICK_YMAX		0xbe520
+
+/*
  * Graphics Co-processor
  */
 #define CO_CMD_L_PATTERN_FGCOL	0x8000
@@ -267,6 +433,7 @@
 	char		*fb;
 	char		dev_name[32];
 	unsigned int	fb_size;
+	unsigned int	chip_id;
 
 	/*
 	 * The following is a pointer to be passed into the
@@ -286,10 +453,19 @@
 	void (*disable_extregs)(struct cfb_info *);
 };
 
+#define ID_IGA_1682		0
+#define ID_CYBERPRO_2000	1
+#define ID_CYBERPRO_2010	2
+#define ID_CYBERPRO_5000	3
+
+struct fb_var_screeninfo;
+
 /*
  * Note! Writing to the Cyber20x0 registers from an interrupt
  * routine is definitely a bad idea atm.
  */
 int cyber2000fb_attach(struct cyberpro_info *info, int idx);
 void cyber2000fb_detach(int idx);
-
+void cyber2000fb_enable_extregs(struct cfb_info *cfb);
+void cyber2000fb_disable_extregs(struct cfb_info *cfb);
+void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	Sun Apr 14 12:16:54 2002
+++ b/drivers/video/fbmem.c	Sun Apr 14 12:16:54 2002
@@ -52,6 +52,7 @@
 extern int acornfb_setup(char*);
 extern int amifb_init(void);
 extern int amifb_setup(char*);
+extern int anakinfb_init(void);
 extern int atafb_init(void);
 extern int atafb_setup(char*);
 extern int macfb_init(void);
@@ -60,7 +61,9 @@
 extern int cyberfb_setup(char*);
 extern int pm2fb_init(void);
 extern int pm2fb_setup(char*);
+extern int clps711xfb_init(void);
 extern int cyber2000fb_init(void);
+extern int cyber2000fb_setup(char*);
 extern int retz3fb_init(void);
 extern int retz3fb_setup(char*);
 extern int clgenfb_init(void);
@@ -154,11 +157,17 @@
 #ifdef CONFIG_FB_AMIGA
 	{ "amifb", amifb_init, amifb_setup },
 #endif
+#ifdef CONFIG_FB_ANAKIN
+	{ "anakinfb", anakinfb_init, NULL },
+#endif
+#ifdef CONFIG_FB_CLPS711X
+	{ "clps711xfb", clps711xfb_init, NULL },
+#endif
 #ifdef CONFIG_FB_CYBER
 	{ "cyber", cyberfb_init, cyberfb_setup },
 #endif
 #ifdef CONFIG_FB_CYBER2000
-	{ "cyber2000", cyber2000fb_init, NULL },
+	{ "cyber2000", cyber2000fb_init, cyber2000fb_setup },
 #endif
 #ifdef CONFIG_FB_PM2
 	{ "pm2fb", pm2fb_init, pm2fb_setup },
diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
--- a/drivers/video/sa1100fb.c	Sun Apr 14 12:16:56 2002
+++ b/drivers/video/sa1100fb.c	Sun Apr 14 12:16:56 2002
@@ -23,11 +23,11 @@
  * Thank you.
  *
  * Known problems:
- *  - With the Neponset plugged into an Assabet, LCD powerdown
- *    doesn't work (LCD stays powered up).  Therefore we shouldn't
- *    blank the screen.
- *  - We don't limit the CPU clock rate nor the mode selection
- *    according to the available SDRAM bandwidth.
+ *	- With the Neponset plugged into an Assabet, LCD powerdown
+ *	  doesn't work (LCD stays powered up).  Therefore we shouldn't
+ *	  blank the screen.
+ *	- We don't limit the CPU clock rate nor the mode selection
+ *	  according to the available SDRAM bandwidth.
  *
  * Other notes:
  *	- Linear grayscale palettes and the kernel.
@@ -41,6 +41,17 @@
  *	  David Neuer.  It's around 8 lines of C code, plus another 4 to
  *	  detect if we are using grayscale.
  *
+ *	- The following must never be specified in a panel definition:
+ *	     LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL
+ *
+ *	- The following should be specified:
+ *	     either LCCR0_Color or LCCR0_Mono
+ *	     either LCCR0_Sngl or LCCR0_Dual
+ *	     either LCCR0_Act or LCCR0_Pas
+ *	     either LCCR3_OutEnH or LCCD3_OutEnL
+ *	     either LCCR3_PixRsEdg or LCCR3_PixFlEdg
+ *	     either LCCR3_ACBsDiv or LCCR3_ACBsCntOff
+ *
  * Code Status:
  * 1999/04/01:
  *	- Driver appears to be working for Brutus 320x200x8bpp mode.  Other
@@ -161,6 +172,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
@@ -169,6 +181,7 @@
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <asm/arch/assabet.h>
+#include <asm/arch/shannon.h>
 
 #include <video/fbcon.h>
 #include <video/fbcon-mfb.h>
@@ -177,11 +190,6 @@
 #include <video/fbcon-cfb16.h>
 
 /*
- * enable this if your panel appears to have broken
- */
-#undef CHECK_COMPAT
-
-/*
  * debugging?
  */
 #define DEBUG 0
@@ -194,246 +202,12 @@
 
 #include "sa1100fb.h"
 
+extern void (*sa1100fb_backlight_power)(int on);
+extern void (*sa1100fb_lcd_power)(int on);
+
 void (*sa1100fb_blank_helper)(int blank);
 EXPORT_SYMBOL(sa1100fb_blank_helper);
 
-
-#ifdef CHECK_COMPAT
-static void
-sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
-			   struct fb_var_screeninfo *var, u_int pcd)
-{
-	struct sa1100fb_lcd_reg shadow;
-	int different = 0;
-
-	/*
-	 * These machines are good machines!
-	 */
-	if (machine_is_assabet() || machine_is_h3600())
-		return;
-
-	/*
-	 * The following ones are bad, bad, bad.
-	 * Please make yours good!
-	 */
-	if (machine_is_pangolin()) {
-		DPRINTK("Configuring Pangolin LCD\n");
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
-		    LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
-		    LCCR0_LtlEnd + LCCR0_DMADel(0);
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
-		    LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
-		    LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
-		shadow.lccr3 =
-		    LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
-		    LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
-
-		DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
-			pcd, LCCR3_PixClkDiv(pcd));
-	}
-	if (machine_is_freebird()) {
-		DPRINTK("Configuring  Freebird LCD\n");
-#if 1
-		shadow.lccr0 = 0x00000038;
-		shadow.lccr1 = 0x010108e0;
-		shadow.lccr2 = 0x0000053f;
-		shadow.lccr3 = 0x00000c20;
-#else
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
-		    LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
-		    LCCR0_LtlEnd + LCCR0_DMADel(0);
-		/* Check ,Chester */
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
-		    LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
-		/* Check ,Chester */
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-		    LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
-		/* Check ,Chester */
-		shadow.lccr3 =
-		    LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
-		    LCCR3_HorSnchH + LCCR3_ACBsCntOff +
-		    LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
-#endif
-	}
-	if (machine_is_brutus()) {
-		DPRINTK("Configuring  Brutus LCD\n");
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
-		    LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-		    LCCR0_DMADel(0);
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
-		    LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-		    LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-		shadow.lccr3 =
-		    LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
-		    LCCR3_HorSnchH + LCCR3_ACBsCntOff +
-		    LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
-	}
-	if (machine_is_huw_webpanel()) {
-		DPRINTK("Configuring  HuW LCD\n");
-		shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
-		shadow.lccr1 = LCCR1_DisWdth(var->xres) +
-		    LCCR1_HorSnchWdth(3) +
-		    LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-		shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
-		shadow.lccr3 = 8 + LCCR3_OutEnH +
-		    LCCR3_PixRsEdg + LCCR3_VrtSnchH +
-		    LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
-	}
-	if (machine_is_lart()) {
-		DPRINTK("Configuring LART LCD\n");
-#if defined LART_GREY_LCD
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
-		    LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-		    LCCR0_DMADel(0);
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
-		    LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-		    LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-		shadow.lccr3 =
-		    LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-		    LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
-#endif
-#if defined LART_COLOR_LCD
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-		    LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-		    LCCR0_DMADel(0);
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
-		    LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
-		    LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
-		shadow.lccr3 =
-		    LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-		    LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
-		    LCCR3_PixFlEdg;
-#endif
-#if defined LART_VIDEO_OUT
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-		    LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
-		    LCCR0_DMADel(0);
-		shadow.lccr1 =
-		    LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
-		    LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
-		shadow.lccr2 =
-		    LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
-		    LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
-		shadow.lccr3 =
-		    LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
-		    LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
-		    LCCR3_PixFlEdg + LCCR3_OutEnL;
-#endif
-	}
-	if (machine_is_graphicsclient()) {
-		DPRINTK("Configuring GraphicsClient LCD\n");
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
-		    LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
-		    LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
-		shadow.lccr3 =
-		    LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
-		    LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-	}
-	if (machine_is_omnimeter()) {
-		DPRINTK("Configuring  OMNI LCD\n");
-		shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
-		shadow.lccr1 =
-		    LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
-		    LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
-		shadow.lccr2 = LCCR2_DisHght(var->yres);
-		shadow.lccr3 =
-		    LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
-//jca (GetPCD(25) << LCD3_V_PCD);
-	}
-	if (machine_is_xp860()) {
-		DPRINTK("Configuring XP860 LCD\n");
-		shadow.lccr0 =
-		    LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-		    LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
-		shadow.lccr1 =
-		    LCCR1_DisWdth(var->xres) +
-		    LCCR1_HorSnchWdth(var->hsync_len) +
-		    LCCR1_BegLnDel(var->left_margin) +
-		    LCCR1_EndLnDel(var->right_margin);
-		shadow.lccr2 =
-		    LCCR2_DisHght(var->yres) +
-		    LCCR2_VrtSnchWdth(var->vsync_len) +
-		    LCCR2_BegFrmDel(var->upper_margin) +
-		    LCCR2_EndFrmDel(var->lower_margin);
-		shadow.lccr3 =
-		    LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-	}
-
-	/*
-	 * Ok, since we're calculating these values, we want to know
-	 * if the calculation is correct.  If you see any of these
-	 * messages _PLEASE_ report the incident to me for diagnosis,
-	 * including details about what was happening when the
-	 * messages appeared. --rmk, 30 March 2001
-	 */
-	if (shadow.lccr0 != new_regs->lccr0) {
-		printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
-			shadow.lccr1, new_regs->lccr1);
-		different = 1;
-	}
-	if (shadow.lccr1 != new_regs->lccr1) {
-		printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
-			shadow.lccr1, new_regs->lccr1);
-		different = 1;
-	}
-	if (shadow.lccr2 != new_regs->lccr2) {
-		printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
-			shadow.lccr2, new_regs->lccr2);
-		different = 1;
-	}
-	if (shadow.lccr3 != new_regs->lccr3) {
-		printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
-			shadow.lccr3, new_regs->lccr3);
-		different = 1;
-	}
-	if (different) {
-		printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
-			var->xres, var->hsync_len,
-			var->left_margin, var->right_margin);
-		printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
-			var->yres, var->vsync_len,
-			var->upper_margin, var->lower_margin);
-
-		printk(KERN_ERR "Please report this to Russell King "
-			"<rmk@arm.linux.org.uk>\n");
-	}
-
-	DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
-	DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
-	DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
-	DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
-}
-#else
-#define sa1100fb_check_shadow(regs,var,pcd)
-#endif
-
-
-
 /*
  * IMHO this looks wrong.  In 8BPP, length should be 8.
  */
@@ -488,42 +262,56 @@
 #endif
 #endif
 
-#ifdef CONFIG_SA1100_H3600
-static struct sa1100fb_mach_info h3600_info __initdata = {
-#ifdef CONFIG_IPAQ_H3100
-	pixclock:	407766,		bpp:		4,
+#ifdef CONFIG_SA1100_H3XXX
+static struct sa1100fb_mach_info h3800_info __initdata = {
+	pixclock:	174757, 	bpp:		16,
 	xres:		320,		yres:		240,
 
-	hsync_len:	26,		vsync_len:	41,
-	left_margin:	4,		upper_margin:	0,
-	right_margin:	4,		lower_margin:	0,
+	hsync_len:	3,		vsync_len:	3,
+	left_margin:	12,		upper_margin:	10,
+	right_margin:	17,		lower_margin:	1,
 
-	sync:		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	cmap_greyscale:	1,		cmap_static:	1,
-	cmap_inverse:	1,
+	sync:		0,		cmap_static:	1,
 
-	lccr0:		LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
-	lccr3:		LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-#else
-	pixclock:	174757,		bpp:		16,
+	lccr0:		LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+	lccr3:		LCCR3_ACBsCntOff | LCCR3_PixFlEdg | LCCR3_OutEnH,
+};
+
+static struct sa1100fb_mach_info h3600_info __initdata = {
+	pixclock:	174757, 	bpp:		16,
 	xres:		320,		yres:		240,
 
 	hsync_len:	3,		vsync_len:	3,
 	left_margin:	12,		upper_margin:	10,
 	right_margin:	17,		lower_margin:	1,
 
-	sync:		0,
+	sync:		0,		cmap_static:	1,
 
 	lccr0:		LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-	lccr3:		LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
-#endif
+	lccr3:		LCCR3_ACBsCntOff | LCCR3_OutEnH | LCCR3_PixFlEdg,
 };
 
 static struct sa1100fb_rgb h3600_rgb_16 = {
 	red:	{ offset: 12, length: 4, },
 	green:	{ offset: 7,  length: 4, },
 	blue:	{ offset: 1,  length: 4, },
-	transp:	{ offset: 0,  length: 0, },
+	transp: { offset: 0,  length: 0, },
+};
+
+static struct sa1100fb_mach_info h3100_info __initdata = {
+	pixclock:	406977, 	bpp:		4,
+	xres:		320,		yres:		240,
+
+	hsync_len:	26,		vsync_len:	41,
+	left_margin:	4,		upper_margin:	0,
+	right_margin:	4,		lower_margin:	0,
+
+	sync:		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	cmap_greyscale: 1,
+	cmap_inverse:	1,
+
+	lccr0:		LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
+	lccr3:		LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
 };
 #endif
 
@@ -717,6 +505,22 @@
 };
 #endif
 
+#ifdef CONFIG_SA1100_SHANNON
+static struct sa1100fb_mach_info shannon_info __initdata = {
+	pixclock:	152500,		bpp:		8,
+	xres:		640,		yres:		480,
+
+	hsync_len:	4,		vsync_len:	3,
+	left_margin:	2,		upper_margin:	0,
+	right_margin:	1,		lower_margin:	0,
+
+	sync:		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 
+
+	lccr0:		LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+	lccr3:		LCCR3_ACBsDiv(512),
+};
+#endif
+
 #ifdef CONFIG_SA1100_OMNIMETER
 static struct sa1100fb_mach_info omnimeter_info __initdata = {
 	pixclock:	0,		bpp:		4,
@@ -752,7 +556,7 @@
 	sync:		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 
 	lccr0:		LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
-	lccr3:		LCCR3_OutEnH | LCCR3_PixFlEdg,
+	lccr3:		LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsCntOff,
 };
 #endif
 
@@ -811,6 +615,33 @@
 #endif
 #endif
 
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+/*
+ * 648 x 480 x 8bpp x 75Hz Dual Panel Color STN Display
+ *
+ * pixclock = 1/( 640*3/8*240 ), [pixclock]=1e-12s=ps
+ *	3 due to r,g,b lines
+ *	8 due to 8 bit data bus
+ *	640 due to 640 pixels per line
+ *	240 = 480/2 due to dual panel display
+ *	=>4.32Mhz => 231481E-12s
+ */
+static struct sa1100fb_mach_info system3_info __initdata = {
+	pixclock:	231481,		bpp:		8,
+	xres:		640,		yres:		480,
+
+	hsync_len:	2,		vsync_len:	2,
+	left_margin:	2,		upper_margin:	0,
+	right_margin:	2,		lower_margin:	0,
+
+	sync:		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+	lccr0:		LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+	lccr3:		LCCR3_OutEnH | LCCR3_PixRsEdg |	LCCR3_ACBsDiv(512) |
+			LCCR3_ACBsCntOff,
+};
+#endif
+
 #ifdef CONFIG_SA1100_XP860
 static struct sa1100fb_mach_info xp860_info __initdata = {
 	pixclock:	0,		bpp:		8,
@@ -849,11 +680,17 @@
 #endif
 	}
 #endif
-#ifdef CONFIG_SA1100_H3600
+#ifdef CONFIG_SA1100_H3XXX
 	if (machine_is_h3600()) {
 		inf = &h3600_info;
 		fbi->rgb[RGB_16] = &h3600_rgb_16;
 	}
+	if (machine_is_h3100()) {
+		inf = &h3100_info;
+	}
+	if (machine_is_h3800()) {
+		inf = &h3800_info;
+	}
 #endif
 #ifdef CONFIG_SA1100_BRUTUS
 	if (machine_is_brutus()) {
@@ -907,9 +744,14 @@
 		inf = &pangolin_info;
 	}
 #endif
-#ifdef CONFIG_SA1100_XP860
-	if (machine_is_xp860()) {
-		inf = &xp860_info;
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+	if (machine_is_pt_system3()) {
+		inf = &system3_info;
+	}
+#endif
+#ifdef CONFIG_SA1100_SHANNON
+	if (machine_is_shannon()) {
+		inf = &shannon_info;
 	}
 #endif
 #ifdef CONFIG_SA1100_STORK
@@ -923,6 +765,11 @@
 #endif
 	}
 #endif
+#ifdef CONFIG_SA1100_XP860
+	if (machine_is_xp860()) {
+		inf = &xp860_info;
+	}
+#endif
 	return inf;
 }
 
@@ -1556,7 +1403,8 @@
 	unsigned int pcd;
 
 	if (pixclock) {
-		pcd = get_cclk_frequency() * pixclock;
+		pcd = cpufreq_get(0) / 100;
+		pcd *= pixclock;
 		pcd /= 10000000;
 		pcd += 1;	/* make up for integer math truncations */
 	} else {
@@ -1659,8 +1507,6 @@
 	if (pcd)
 		new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
 
-	sa1100fb_check_shadow(&new_regs, var, pcd);
-
 	DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
 	DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
 	DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
@@ -1704,35 +1550,12 @@
  * Also, I'm expecting that the backlight stuff should
  * be handled differently.
  */
-static void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
+static inline void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
 {
 	DPRINTK("backlight on\n");
 
-#ifdef CONFIG_SA1100_FREEBIRD
-#error FIXME
-	if (machine_is_freebird()) {
-		BCR_set(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP);
-	}
-#endif
-#ifdef CONFIG_SA1100_FREEBIRD
-	if (machine_is_freebird()) {
-		/* Turn on backlight ,Chester */
-		BCR_set(BCR_FREEBIRD_LCD_BACKLIGHT);
-	}
-#endif
-#ifdef CONFIG_SA1100_HUW_WEBPANEL
-#error FIXME
-	if (machine_is_huw_webpanel()) {
-		BCR_set(BCR_CCFL_POW + BCR_PWM_BACKLIGHT);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_task(200 * HZ / 1000);
-		BCR_set(BCR_TFT_ENA);
-	}
-#endif
-#ifdef CONFIG_SA1100_OMNIMETER
-	if (machine_is_omnimeter())
-		LEDBacklightOn();
-#endif
+	if (sa1100fb_backlight_power)
+		sa1100fb_backlight_power(1);
 }
 
 /*
@@ -1740,47 +1563,21 @@
  * Also, I'm expecting that the backlight stuff should
  * be handled differently.
  */
-static void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
+static inline void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
 {
 	DPRINTK("backlight off\n");
 
-#ifdef CONFIG_SA1100_FREEBIRD
-#error FIXME
-	if (machine_is_freebird()) {
-		BCR_clear(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP
-			  /*| BCR_FREEBIRD_LCD_BACKLIGHT */ );
-	}
-#endif
-#ifdef CONFIG_SA1100_OMNIMETER
-	if (machine_is_omnimeter())
-		LEDBacklightOff();
-#endif
+	if (sa1100fb_backlight_power)
+		sa1100fb_backlight_power(0);
 }
 
-static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
+static inline void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
 {
 	DPRINTK("LCD power on\n");
 
-#ifndef ASSABET_PAL_VIDEO
-	if (machine_is_assabet())
-		ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
-#endif
-#ifdef CONFIG_SA1100_HUW_WEBPANEL
-	if (machine_is_huw_webpanel())
-		BCR_clear(BCR_TFT_NPWR);
-#endif
-#ifdef CONFIG_SA1100_OMNIMETER
-	if (machine_is_omnimeter())
-		LCDPowerOn();
-#endif
-#ifdef CONFIG_SA1100_H3600
-	if (machine_is_h3600()) {
-		set_h3600_egpio(EGPIO_H3600_LCD_ON |
-				EGPIO_H3600_LCD_PCI |
-				EGPIO_H3600_LCD_5V_ON |
-				EGPIO_H3600_LVDD_ON);
-	}
-#endif
+	if (sa1100fb_lcd_power)
+		sa1100fb_lcd_power(1);
+
 #ifdef CONFIG_SA1100_STORK
 	if (machine_is_stork()) {
 		storkSetLCDCPLD(0, 1);
@@ -1789,27 +1586,13 @@
 #endif
 }
 
-static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
+static inline void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
 {
 	DPRINTK("LCD power off\n");
 
-#ifndef ASSABET_PAL_VIDEO
-	if (machine_is_assabet())
-		ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
-#endif
-#ifdef CONFIG_SA1100_HUW_WEBPANEL
-	// dont forget to set the control lines to zero (?)
-	if (machine_is_huw_webpanel())
-		BCR_set(BCR_TFT_NPWR);
-#endif
-#ifdef CONFIG_SA1100_H3600
-	if (machine_is_h3600()) {
-		clr_h3600_egpio(EGPIO_H3600_LCD_ON |
-				EGPIO_H3600_LCD_PCI |
-				EGPIO_H3600_LCD_5V_ON |
-				EGPIO_H3600_LVDD_ON);
-	}
-#endif
+	if (sa1100fb_lcd_power)
+		sa1100fb_lcd_power(0);
+
 #ifdef CONFIG_SA1100_STORK
 	if (machine_is_stork()) {
 		storkSetLCDCPLD(0, 0);
@@ -1844,14 +1627,6 @@
 
 	}
 
-#ifdef CONFIG_SA1100_FREEBIRD
-#error Please contact <rmk@arm.linux.org.uk> about this
-	if (machine_is_freebird()) {
-		/* Color single passive */
-		mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
-			GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
-	}
-#endif
 	if (machine_is_cerf()) {
 		/* GPIO15 is used as a bypass for 3.8" displays */
 		mask |= GPIO_GPIO15;
@@ -1920,6 +1695,11 @@
 	}
 #endif
 
+	if (machine_is_shannon()) {
+		GPDR |= SHANNON_GPIO_DISP_EN;
+		GPSR |= SHANNON_GPIO_DISP_EN;
+	}	
+
 	DPRINTK("DBAR1 = %p\n", DBAR1);
 	DPRINTK("DBAR2 = %p\n", DBAR2);
 	DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
@@ -1958,12 +1738,15 @@
 	}
 #endif
 
+	if (machine_is_shannon()) {
+		GPCR |= SHANNON_GPIO_DISP_EN;
+	}	
+
 	add_wait_queue(&fbi->ctrlr_wait, &wait);
 	set_current_state(TASK_UNINTERRUPTIBLE);
 
 	LCSR = 0xffffffff;	/* Clear LCD Status Register */
 	LCCR0 &= ~LCCR0_LDM;	/* Enable LCD Disable Done Interrupt */
-	enable_irq(IRQ_LCD);	/* Enable LCD IRQ */
 	LCCR0 &= ~LCCR0_LEN;	/* Disable LCD Controller */
 
 	schedule_timeout(20 * HZ / 1000);
@@ -2006,12 +1789,13 @@
 		 * Disable controller for clock change.  If the
 		 * controller is already disabled, then do nothing.
 		 */
-		if (old_state != C_DISABLE) {
+		if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
 			fbi->state = state;
 			sa1100fb_disable_controller(fbi);
 		}
 		break;
 
+	case C_DISABLE_PM:
 	case C_DISABLE:
 		/*
 		 * Disable controller
@@ -2050,6 +1834,16 @@
 		}
 		break;
 
+	case C_ENABLE_PM:
+		/*
+		 * Re-enable the controller after PM.  This is not
+		 * perfect - think about the case where we were doing
+		 * a clock change, and we suspended half-way through.
+		 */
+		if (old_state != C_DISABLE_PM)
+			break;
+		/* fall through */
+
 	case C_ENABLE:
 		/*
 		 * Power up the LCD screen, enable controller, and
@@ -2162,10 +1956,10 @@
 
 		if (state == 0) {
 			/* Enter D0. */
-			set_ctrlr_state(fbi, C_ENABLE);
+			set_ctrlr_state(fbi, C_ENABLE_PM);
 		} else {
 			/* Enter D1-D3.  Disable the LCD controller.  */
-			set_ctrlr_state(fbi, C_DISABLE);
+			set_ctrlr_state(fbi, C_DISABLE_PM);
 		}
 	}
 	DPRINTK("done\n");
@@ -2245,7 +2039,7 @@
 	fbi->fb.updatevar	= sa1100fb_updatevar;
 	fbi->fb.blank		= sa1100fb_blank;
 	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
-	fbi->fb.node		= -1;
+	fbi->fb.node		= NODEV;
 	fbi->fb.monspecs	= monspecs;
 	fbi->fb.disp		= (struct display *)(fbi + 1);
 	fbi->fb.pseudo_palette	= (void *)(fbi->fb.disp + 1);
@@ -2293,6 +2087,9 @@
 	struct sa1100fb_info *fbi;
 	int ret;
 
+	if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
+		return -EBUSY;
+
 	fbi = sa1100fb_init_fbinfo();
 	ret = -ENOMEM;
 	if (!fbi)
@@ -2304,7 +2101,7 @@
 		goto failed;
 
 	ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
-			  fbi->fb.fix.id, fbi);
+			  "LCD", fbi);
 	if (ret) {
 		printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
 		goto failed;
@@ -2358,6 +2155,7 @@
 failed:
 	if (fbi)
 		kfree(fbi);
+	release_mem_region(0xb0100000, 0x10000);
 	return ret;
 }
 
diff -Nru a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
--- a/drivers/video/sa1100fb.h	Sun Apr 14 12:16:55 2002
+++ b/drivers/video/sa1100fb.h	Sun Apr 14 12:16:55 2002
@@ -127,6 +127,8 @@
 #define C_DISABLE_CLKCHANGE	(2)
 #define C_ENABLE_CLKCHANGE	(3)
 #define C_REENABLE		(4)
+#define C_DISABLE_PM		(5)
+#define C_ENABLE_PM		(6)
 
 #define SA1100_NAME	"SA1100"
 
diff -Nru a/fs/Config.help b/fs/Config.help
--- a/fs/Config.help	Sun Apr 14 12:16:59 2002
+++ b/fs/Config.help	Sun Apr 14 12:16:59 2002
@@ -59,12 +59,12 @@
   everyone should say N.
 
 CONFIG_REISERFS_PROC_INFO
-  Create under /proc/fs/reiserfs hierarchy of files, displaying
-  various ReiserFS statistics and internal data on the expense of
-  making your kernel or module slightly larger (+8 KB).  This also
-  increases amount of kernel memory required for each mount.  Almost
-  everyone but ReiserFS developers and people fine-tuning reiserfs or
-  tracing problems should say N.
+  Create under /proc/fs/reiserfs a hierarchy of files, displaying
+  various ReiserFS statistics and internal data at the expense of
+  making your kernel or module slightly larger (+8 KB). This also
+  increases the amount of kernel memory required for each mount.
+  Almost everyone but ReiserFS developers and people fine-tuning
+  reiserfs or tracing problems should say N.
 
 CONFIG_EXT2_FS
   This is the de facto standard Linux file system (method to organize
@@ -679,10 +679,12 @@
   answer N.
 
 CONFIG_QNX4FS_FS
-  This is the file system used by the operating system QNX 4. Say Y if
-  you intend to mount QNX hard disks or floppies. Unless you say Y to
-  "QNX4FS read-write support" below, you will only be able to read
-  these file systems.
+  This is the file system used by the real-time operating systems
+  QNX 4 and QNX 6 (the latter is also called QNX RTP).
+  Further information is available at <http://www.qnx.com/>.
+  Say Y if you intend to mount QNX hard disks or floppies.
+  Unless you say Y to "QNX4FS read-write support" below, you will
+  only be able to read these file systems.
 
   This file system support is also available as a module ( = code
   which can be inserted in and removed from the running kernel
@@ -695,6 +697,9 @@
 
 CONFIG_QNX4FS_RW
   Say Y if you want to test write support for QNX4 file systems.
+
+  It's currently broken, so for now:
+  answer N.
 
 CONFIG_AUTOFS_FS
   The automounter is a tool to automatically mount remote file systems
diff -Nru a/fs/Config.in b/fs/Config.in
--- a/fs/Config.in	Sun Apr 14 12:16:55 2002
+++ b/fs/Config.in	Sun Apr 14 12:16:55 2002
@@ -9,7 +9,7 @@
 tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
 
 tristate 'Reiserfs support' CONFIG_REISERFS_FS
-dep_mbool '  Have reiserfs do extra internal checking' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
+dep_mbool '  Enable reiserfs debug mode' CONFIG_REISERFS_CHECK $CONFIG_REISERFS_FS
 dep_mbool '  Stats in /proc/fs/reiserfs' CONFIG_REISERFS_PROC_INFO $CONFIG_REISERFS_FS
 
 dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
@@ -79,7 +79,7 @@
 # breaks.
 dep_bool '/dev/pts file system for Unix98 PTYs' CONFIG_DEVPTS_FS $CONFIG_UNIX98_PTYS
 
-dep_tristate 'QNX4 file system support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS $CONFIG_EXPERIMENTAL
+tristate 'QNX4 file system support (read only)' CONFIG_QNX4FS_FS
 dep_mbool '  QNX4FS write support (DANGEROUS)' CONFIG_QNX4FS_RW $CONFIG_QNX4FS_FS $CONFIG_EXPERIMENTAL
 
 tristate 'ROM file system support' CONFIG_ROMFS_FS
diff -Nru a/fs/Makefile b/fs/Makefile
--- a/fs/Makefile	Sun Apr 14 12:16:54 2002
+++ b/fs/Makefile	Sun Apr 14 12:16:54 2002
@@ -16,12 +16,6 @@
 		dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
 		filesystems.o namespace.o seq_file.o xattr.o libfs.o
 
-ifeq ($(CONFIG_QUOTA),y)
-obj-y += dquot.o
-else
-obj-y += noquot.o
-endif
-
 ifneq ($(CONFIG_NFSD),n)
 ifneq ($(CONFIG_NFSD),)
 obj-y += nfsctl.o
@@ -84,6 +78,8 @@
 obj-y				+= binfmt_script.o
 
 obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
+
+obj-$(CONFIG_QUOTA) += dquot.o
 
 # persistent filesystems
 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
diff -Nru a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
--- a/fs/adfs/dir_f.c	Sun Apr 14 12:16:59 2002
+++ b/fs/adfs/dir_f.c	Sun Apr 14 12:16:59 2002
@@ -468,11 +468,9 @@
 }
 
 struct adfs_dir_ops adfs_f_dir_ops = {
-	adfs_f_read,
-	adfs_f_setpos,
-	adfs_f_getnext,
-	adfs_f_update,
-	NULL,
-	NULL,
-	adfs_f_free
+	read:		adfs_f_read,
+	setpos:		adfs_f_setpos,
+	getnext:	adfs_f_getnext,
+	update:		adfs_f_update,
+	free:		adfs_f_free
 };
diff -Nru a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
--- a/fs/adfs/dir_fplus.c	Sun Apr 14 12:16:55 2002
+++ b/fs/adfs/dir_fplus.c	Sun Apr 14 12:16:55 2002
@@ -171,11 +171,8 @@
 }
 
 struct adfs_dir_ops adfs_fplus_dir_ops = {
-	adfs_fplus_read,
-	adfs_fplus_setpos,
-	adfs_fplus_getnext,
-	NULL,
-	NULL,
-	NULL,
-	adfs_fplus_free
+	read:		adfs_fplus_read,
+	setpos:		adfs_fplus_setpos,
+	getnext:	adfs_fplus_getnext,
+	free:		adfs_fplus_free
 };
diff -Nru a/fs/adfs/inode.c b/fs/adfs/inode.c
--- a/fs/adfs/inode.c	Sun Apr 14 12:16:57 2002
+++ b/fs/adfs/inode.c	Sun Apr 14 12:16:57 2002
@@ -302,6 +302,8 @@
 	struct super_block *sb = inode->i_sb;
 	unsigned int ia_valid = attr->ia_valid;
 	int error;
+	
+	lock_kernel();
 
 	error = inode_change_ok(inode, attr);
 
@@ -346,6 +348,7 @@
 	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
 		mark_inode_dirty(inode);
 out:
+	unlock_kernel();
 	return error;
 }
 
diff -Nru a/fs/adfs/super.c b/fs/adfs/super.c
--- a/fs/adfs/super.c	Sun Apr 14 12:16:54 2002
+++ b/fs/adfs/super.c	Sun Apr 14 12:16:54 2002
@@ -171,7 +171,9 @@
 	if (!options)
 		return 0;
 
-	for (opt = strtok(options, ","); opt != NULL; opt = strtok(NULL, ",")) {
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
 		value = strchr(opt, '=');
 		if (value)
 			*value++ = '\0';
diff -Nru a/fs/affs/inode.c b/fs/affs/inode.c
--- a/fs/affs/inode.c	Sun Apr 14 12:16:58 2002
+++ b/fs/affs/inode.c	Sun Apr 14 12:16:58 2002
@@ -235,6 +235,8 @@
 	struct inode *inode = dentry->d_inode;
 	int error;
 
+	lock_kernel();
+
 	pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
 
 	error = inode_change_ok(inode,attr);
@@ -254,6 +256,7 @@
 	if (!error && (attr->ia_valid & ATTR_MODE))
 		mode_to_prot(inode);
 out:
+	unlock_kernel();
 	return error;
 }
 
diff -Nru a/fs/affs/super.c b/fs/affs/super.c
--- a/fs/affs/super.c	Sun Apr 14 12:16:59 2002
+++ b/fs/affs/super.c	Sun Apr 14 12:16:59 2002
@@ -29,7 +29,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-extern int *blk_size[];
 extern struct timezone sys_tz;
 
 static int affs_statfs(struct super_block *sb, struct statfs *buf);
@@ -161,7 +160,9 @@
 	*mount_opts = 0;
 	if (!options)
 		return 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		f = 0;
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
@@ -291,7 +292,7 @@
 
 	sb->s_magic             = AFFS_SUPER_MAGIC;
 	sb->s_op                = &affs_sops;
-	
+
 	sbi = kmalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
@@ -319,7 +320,7 @@
 	 */
 
 	size = sb->s_bdev->bd_inode->i_size >> 9;
-	pr_debug("AFFS: initial blksize=%d, blocks=%d\n", 512, blocks);
+	pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size);
 
 	affs_set_blocksize(sb, PAGE_SIZE);
 	/* Try to find root block. Its location depends on the block size. */
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Sun Apr 14 12:16:55 2002
+++ b/fs/attr.c	Sun Apr 14 12:16:55 2002
@@ -21,6 +21,8 @@
 	int retval = -EPERM;
 	unsigned int ia_valid = attr->ia_valid;
 
+	lock_kernel();
+
 	/* If force is set do it anyway. */
 	if (ia_valid & ATTR_FORCE)
 		goto fine;
@@ -55,6 +57,7 @@
 fine:
 	retval = 0;
 error:
+	unlock_kernel();
 	return retval;
 }
 
@@ -62,7 +65,8 @@
 {
 	unsigned int ia_valid = attr->ia_valid;
 	int error = 0;
-
+	
+	lock_kernel();
 	if (ia_valid & ATTR_SIZE) {
 		error = vmtruncate(inode, attr->ia_size);
 		if (error)
@@ -86,6 +90,7 @@
 	}
 	mark_inode_dirty(inode);
 out:
+	unlock_kernel();
 	return error;
 }
 
@@ -114,6 +119,7 @@
 int notify_change(struct dentry * dentry, struct iattr * attr)
 {
 	struct inode *inode = dentry->d_inode;
+	mode_t mode = inode->i_mode;
 	int error;
 	time_t now = CURRENT_TIME;
 	unsigned int ia_valid = attr->ia_valid;
@@ -126,8 +132,25 @@
 		attr->ia_atime = now;
 	if (!(ia_valid & ATTR_MTIME_SET))
 		attr->ia_mtime = now;
+	if (ia_valid & ATTR_KILL_SUID) {
+		if (mode & S_ISUID) {
+			if (!ia_valid & ATTR_MODE) {
+				ia_valid = attr->ia_valid |= ATTR_MODE;
+				attr->ia_mode = inode->i_mode;
+			}
+			attr->ia_mode &= ~S_ISUID;
+		}
+	}
+	if (ia_valid & ATTR_KILL_SGID) {
+		if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+			if (!ia_valid & ATTR_MODE) {
+				ia_valid = attr->ia_valid |= ATTR_MODE;
+				attr->ia_mode = inode->i_mode;
+			}
+			attr->ia_mode &= ~S_ISGID;
+		}
+	}
 
-	lock_kernel();
 	if (inode->i_op && inode->i_op->setattr) 
 		error = inode->i_op->setattr(dentry, attr);
 	else {
@@ -140,7 +163,6 @@
 				error = inode_setattr(inode, attr);
 		}
 	}
-	unlock_kernel();
 	if (!error) {
 		unsigned long dn_mask = setattr_mask(ia_valid);
 		if (dn_mask)
diff -Nru a/fs/autofs/inode.c b/fs/autofs/inode.c
--- a/fs/autofs/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/autofs/inode.c	Sun Apr 14 12:16:59 2002
@@ -60,7 +60,9 @@
 	*pipefd = -1;
 
 	if ( !options ) return 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*value)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
 		if (!strcmp(this_char,"fd")) {
@@ -119,9 +121,10 @@
 	struct autofs_sb_info *sbi;
 	int minproto, maxproto;
 
-	sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL);
+	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if ( !sbi )
 		goto fail_unlock;
+	memset(sbi, 0, sizeof(*sbi));
 	DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
 
 	s->u.generic_sbp = sbi;
diff -Nru a/fs/autofs4/inode.c b/fs/autofs4/inode.c
--- a/fs/autofs4/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/autofs4/inode.c	Sun Apr 14 12:16:59 2002
@@ -110,7 +110,9 @@
 	*pipefd = -1;
 
 	if ( !options ) return 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
 		if (!strcmp(this_char,"fd")) {
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c	Sun Apr 14 12:16:56 2002
+++ b/fs/binfmt_aout.c	Sun Apr 14 12:16:56 2002
@@ -28,6 +28,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
@@ -36,7 +37,11 @@
 extern void dump_thread(struct pt_regs *, struct user *);
 
 static struct linux_binfmt aout_format = {
-	NULL, THIS_MODULE, load_aout_binary, load_aout_library, aout_core_dump, PAGE_SIZE
+	module:		THIS_MODULE,
+	load_binary:	load_aout_binary,
+	load_shlib:	load_aout_library,
+	core_dump:	aout_core_dump,
+	min_coredump:	PAGE_SIZE
 };
 
 static void set_brk(unsigned long start, unsigned long end)
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Sun Apr 14 12:16:58 2002
+++ b/fs/binfmt_elf.c	Sun Apr 14 12:16:58 2002
@@ -74,7 +74,11 @@
 #define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))
 
 static struct linux_binfmt elf_format = {
-	NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
+		module:		THIS_MODULE,
+		load_binary:	load_elf_binary,
+		load_shlib:	load_elf_library,
+		core_dump:	elf_core_dump,
+		min_coredump:	ELF_EXEC_PAGESIZE
 };
 
 #define BAD_ADDR(x)	((unsigned long)(x) > TASK_SIZE)
@@ -138,6 +142,21 @@
 	} else
 		u_platform = p;
 
+#if defined(__i386__) && defined(CONFIG_SMP)
+	/*
+	 * In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
+	 * by the processes running on the same package. One thing we can do
+	 * is to shuffle the initial stack for them.
+	 *
+	 * The conditionals here are unneeded, but kept in to make the
+	 * code behaviour the same as pre change unless we have hyperthreaded
+	 * processors. This should be cleaned up before 2.6
+	 */
+	 
+	if(smp_num_siblings > 1)
+		u_platform = u_platform - ((current->pid % 64) << 7);
+#endif	
+
 	/*
 	 * Force 16 byte _final_ alignment here for generality.
 	 */
@@ -552,7 +571,6 @@
 		/* Executables without an interpreter also need a personality  */
 		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
 	}
-
 
 	/* OK, we are done with that, now set up the arg stuff,
 	   and then start this sucker up */
diff -Nru a/fs/binfmt_em86.c b/fs/binfmt_em86.c
--- a/fs/binfmt_em86.c	Sun Apr 14 12:16:59 2002
+++ b/fs/binfmt_em86.c	Sun Apr 14 12:16:59 2002
@@ -95,7 +95,8 @@
 }
 
 struct linux_binfmt em86_format = {
-	NULL, THIS_MODULE, load_em86, NULL, NULL, 0
+	module:		THIS_MODULE,
+	load_binary:	load_em86,
 };
 
 static int __init init_em86_binfmt(void)
diff -Nru a/fs/binfmt_misc.c b/fs/binfmt_misc.c
--- a/fs/binfmt_misc.c	Sun Apr 14 12:16:57 2002
+++ b/fs/binfmt_misc.c	Sun Apr 14 12:16:57 2002
@@ -62,7 +62,7 @@
 	char *p = strrchr(bprm->filename, '.');
 	struct list_head *l;
 
-	for (l = entries.next; l != &entries; l = l->next) {
+	list_for_each(l, &entries) {
 		Node *e = list_entry(l, Node, list);
 		char *s;
 		int j;
diff -Nru a/fs/binfmt_script.c b/fs/binfmt_script.c
--- a/fs/binfmt_script.c	Sun Apr 14 12:16:55 2002
+++ b/fs/binfmt_script.c	Sun Apr 14 12:16:55 2002
@@ -95,7 +95,8 @@
 }
 
 struct linux_binfmt script_format = {
-	NULL, THIS_MODULE, load_script, NULL, NULL, 0
+	module:		THIS_MODULE,
+	load_binary:	load_script,
 };
 
 static int __init init_script_binfmt(void)
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	Sun Apr 14 12:16:55 2002
+++ b/fs/bio.c	Sun Apr 14 12:16:55 2002
@@ -328,7 +328,7 @@
  * ll_rw_kio - submit a &struct kiobuf for I/O
  * @rw:   %READ or %WRITE
  * @kio:   the kiobuf to do I/O on
- * @dev:   target device
+ * @bdev:   target device
  * @sector:   start location on disk
  *
  * Description:
@@ -336,11 +336,12 @@
  *   &struct bio and queue them for I/O. The kiobuf given must describe
  *   a continous range of data, and must be fully prepared for I/O.
  **/
-void ll_rw_kio(int rw, struct kiobuf *kio, kdev_t dev, sector_t sector)
+void ll_rw_kio(int rw, struct kiobuf *kio, struct block_device *bdev, sector_t sector)
 {
 	int i, offset, size, err, map_i, total_nr_pages, nr_pages;
 	struct bio_vec *bvec;
 	struct bio *bio;
+	kdev_t dev = to_kdev_t(bdev->bd_dev);
 
 	err = 0;
 	if ((rw & WRITE) && is_read_only(dev)) {
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Sun Apr 14 12:16:59 2002
+++ b/fs/block_dev.c	Sun Apr 14 12:16:59 2002
@@ -19,6 +19,7 @@
 #include <linux/highmem.h>
 #include <linux/blkdev.h>
 #include <linux/module.h>
+#include <linux/blkpg.h>
 
 #include <asm/uaccess.h>
 
@@ -27,33 +28,22 @@
 static unsigned long max_block(kdev_t dev)
 {
 	unsigned int retval = ~0U;
-	int major = major(dev);
+	loff_t sz = blkdev_size_in_bytes(dev);
 
-	if (blk_size[major]) {
-		int minor = minor(dev);
-		unsigned int blocks = blk_size[major][minor];
-		if (blocks) {
-			unsigned int size = block_size(dev);
-			unsigned int sizebits = blksize_bits(size);
-			blocks += (size-1) >> BLOCK_SIZE_BITS;
-			retval = blocks << (BLOCK_SIZE_BITS - sizebits);
-			if (sizebits > BLOCK_SIZE_BITS)
-				retval = blocks >> (sizebits - BLOCK_SIZE_BITS);
-		}
+	if (sz) {
+		unsigned int size = block_size(dev);
+		unsigned int sizebits = blksize_bits(size);
+		retval = (sz >> sizebits);
 	}
 	return retval;
 }
 
 static loff_t blkdev_size(kdev_t dev)
 {
-	unsigned int blocks = ~0U;
-	int major = major(dev);
-
-	if (blk_size[major]) {
-		int minor = minor(dev);
-		blocks = blk_size[major][minor];
-	}
-	return (loff_t) blocks << BLOCK_SIZE_BITS;
+	loff_t sz = blkdev_size_in_bytes(dev);
+	if (sz)
+		return sz;
+	return ~0ULL;
 }
 
 /* Kill _all_ buffers, dirty or not.. */
@@ -183,7 +173,6 @@
 	if (offset >= 0 && offset <= size) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
-			file->f_reada = 0;
 			file->f_version = ++event;
 		}
 		retval = offset;
@@ -337,7 +326,7 @@
 {
 	struct list_head *p;
 	struct block_device *bdev;
-	for (p=head->next; p!=head; p=p->next) {
+	list_for_each(p, head) {
 		bdev = list_entry(p, struct block_device, bd_hash);
 		if (bdev->bd_dev != dev)
 			continue;
@@ -703,9 +692,20 @@
 static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
 			unsigned long arg)
 {
-	if (inode->i_bdev->bd_op->ioctl)
-		return inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
-	return -EINVAL;
+	int ret = -EINVAL;
+	switch (cmd) {
+	case BLKRAGET:
+	case BLKFRAGET:
+	case BLKRASET:
+	case BLKFRASET:
+		ret = blk_ioctl(inode->i_bdev, cmd, arg);
+		break;
+	default:
+		if (inode->i_bdev->bd_op->ioctl)
+			ret =inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
+		break;
+	}
+	return ret;
 }
 
 struct address_space_operations def_blk_aops = {
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Sun Apr 14 12:16:54 2002
+++ b/fs/buffer.c	Sun Apr 14 12:16:54 2002
@@ -46,7 +46,6 @@
 #include <linux/iobuf.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
-#include <linux/completion.h>
 #include <linux/compiler.h>
 
 #include <asm/uaccess.h>
@@ -795,8 +794,11 @@
 	unlock_buffer(bh);
 	tmp = bh->b_this_page;
 	while (tmp != bh) {
-		if (buffer_async(tmp) && buffer_locked(tmp))
-			goto still_busy;
+		if (buffer_locked(tmp)) {
+			if (buffer_async(tmp))
+				goto still_busy;
+		} else if (!buffer_uptodate(tmp))
+			SetPageError(page);
 		tmp = tmp->b_this_page;
 	}
 
@@ -992,7 +994,7 @@
 
 	/* First, check for the "real" dirty limit. */
 	if (dirty > soft_dirty_limit) {
-		if (dirty > hard_dirty_limit)
+		if (dirty > hard_dirty_limit && !(current->flags & PF_NOIO))
 			return 1;
 		return 0;
 	}
@@ -1324,21 +1326,13 @@
 
 int try_to_release_page(struct page * page, int gfp_mask)
 {
+	struct address_space * const mapping = page->mapping;
+
 	if (!PageLocked(page))
 		BUG();
 	
-	if (!page->mapping)
-		goto try_to_free;
-	if (!page->mapping->a_ops->releasepage)
-		goto try_to_free;
-	if (page->mapping->a_ops->releasepage(page, gfp_mask))
-		goto try_to_free;
-	/*
-	 * We couldn't release buffer metadata; don't even bother trying
-	 * to release buffers.
-	 */
-	return 0;
-try_to_free:	
+	if (mapping && mapping->a_ops->releasepage)
+		return mapping->a_ops->releasepage(page, gfp_mask);
 	return try_to_free_buffers(page, gfp_mask);
 }
 
@@ -1356,10 +1350,10 @@
 
 	if (!PageLocked(page))
 		BUG();
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		return 1;
 
-	head = page->buffers;
+	head = page_buffers(page);
 	bh = head;
 	do {
 		unsigned int next_off = curr_off + bh->b_size;
@@ -1398,7 +1392,7 @@
 
 	/* FIXME: create_buffers should fail if there's no enough memory */
 	head = create_buffers(page, blocksize, 1);
-	if (page->buffers)
+	if (page_has_buffers(page))
 		BUG();
 
 	bh = head;
@@ -1408,7 +1402,7 @@
 		bh = bh->b_this_page;
 	} while (bh);
 	tail->b_this_page = head;
-	page->buffers = head;
+	set_page_buffers(page, head);
 	page_cache_get(page);
 }
 EXPORT_SYMBOL(create_empty_buffers);
@@ -1464,9 +1458,9 @@
 	if (!PageLocked(page))
 		BUG();
 
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, 1 << inode->i_blkbits);
-	head = page->buffers;
+	head = page_buffers(page);
 
 	block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
 
@@ -1557,9 +1551,9 @@
 	char *kaddr = kmap(page);
 
 	blocksize = 1 << inode->i_blkbits;
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize);
-	head = page->buffers;
+	head = page_buffers(page);
 
 	bbits = inode->i_blkbits;
 	block = page->index << (PAGE_CACHE_SHIFT - bbits);
@@ -1650,7 +1644,7 @@
 
 	blocksize = 1 << inode->i_blkbits;
 
-	for(bh = head = page->buffers, block_start = 0;
+	for(bh = head = page_buffers(page), block_start = 0;
 	    bh != head || !block_start;
 	    block_start=block_end, bh = bh->b_this_page) {
 		block_end = block_start + blocksize;
@@ -1698,9 +1692,9 @@
 	if (!PageLocked(page))
 		PAGE_BUG(page);
 	blocksize = 1 << inode->i_blkbits;
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize);
-	head = page->buffers;
+	head = page_buffers(page);
 
 	blocks = PAGE_CACHE_SIZE >> inode->i_blkbits;
 	iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
@@ -1716,7 +1710,7 @@
 		if (!buffer_mapped(bh)) {
 			if (iblock < lblock) {
 				if (get_block(inode, iblock, bh, 0))
-					continue;
+					SetPageError(page);
 			}
 			if (!buffer_mapped(bh)) {
 				memset(kmap(page) + i*blocksize, 0, blocksize);
@@ -1736,10 +1730,11 @@
 
 	if (!nr) {
 		/*
-		 * all buffers are uptodate - we can set the page
-		 * uptodate as well.
+		 * All buffers are uptodate - we can set the page uptodate
+		 * as well. But not if get_block() returned an error.
 		 */
-		SetPageUptodate(page);
+		if (!PageError(page))
+			SetPageUptodate(page);
 		UnlockPage(page);
 		return 0;
 	}
@@ -1949,11 +1944,11 @@
 	if (!page)
 		goto out;
 
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize);
 
 	/* Find the buffer that contains "offset" */
-	bh = page->buffers;
+	bh = page_buffers(page);
 	pos = blocksize;
 	while (offset >= pos) {
 		bh = bh->b_this_page;
@@ -2040,7 +2035,7 @@
  */
 int writeout_one_page(struct page *page)
 {
-	struct buffer_head *bh, *head = page->buffers;
+	struct buffer_head *bh, *head = page_buffers(page);
 
 	if (!PageLocked(page))
 		BUG();
@@ -2063,7 +2058,7 @@
 int waitfor_one_page(struct page *page)
 {
 	int error = 0;
-	struct buffer_head *bh, *head = page->buffers;
+	struct buffer_head *bh, *head = page_buffers(page);
 
 	bh = head;
 	do {
@@ -2122,7 +2117,7 @@
 	}
 
 	/* This does not understand multi-device filesystems currently */
-	retval = brw_kiovec(rw, 1, &iobuf, inode->i_dev, blocks, blocksize);
+	retval = brw_kiovec(rw, 1, &iobuf, inode->i_sb->s_bdev, blocks, blocksize);
 
  out:
 	return retval;
@@ -2138,8 +2133,8 @@
  * It is up to the caller to make sure that there are enough blocks
  * passed in to completely map the iobufs to disk.
  */
-int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], kdev_t dev, sector_t b[],
-	       int size)
+int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
+	       struct block_device *bdev, sector_t b[], int size)
 {
 	int		transferred;
 	int		i;
@@ -2167,7 +2162,7 @@
 		iobuf = iovec[i];
 		iobuf->errno = 0;
 
-		ll_rw_kio(rw, iobuf, dev, b[i] * (size >> 9));
+		ll_rw_kio(rw, iobuf, bdev, b[i] * (size >> 9));
 	}
 
 	/*
@@ -2206,9 +2201,9 @@
 	if (!PageLocked(page))
 		panic("brw_page: page not locked for I/O");
 
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, size);
-	head = bh = page->buffers;
+	head = bh = page_buffers(page);
 
 	/* Stage 1: lock all the buffers */
 	do {
@@ -2276,7 +2271,7 @@
 		bh = bh->b_this_page;
 	} while (bh);
 	tail->b_this_page = head;
-	page->buffers = head;
+	set_page_buffers(page, head);
 	page_cache_get(page);
 }
 
@@ -2295,8 +2290,8 @@
 	if (!PageLocked(page))
 		BUG();
 
-	bh = page->buffers;
-	if (bh) {
+	if (page_has_buffers(page)) {
+		bh = page_buffers(page);
 		if (bh->b_size == size)
 			return page;
 		if (!try_to_free_buffers(page, GFP_NOFS))
@@ -2317,7 +2312,7 @@
 
 static void hash_page_buffers(struct page *page, struct block_device *bdev, int block, int size)
 {
-	struct buffer_head *head = page->buffers;
+	struct buffer_head *head = page_buffers(page);
 	struct buffer_head *bh = head;
 	unsigned int uptodate;
 
@@ -2443,7 +2438,7 @@
  */
 int try_to_free_buffers(struct page * page, unsigned int gfp_mask)
 {
-	struct buffer_head * tmp, * bh = page->buffers;
+	struct buffer_head * tmp, * bh = page_buffers(page);
 
 	BUG_ON(!PageLocked(page));
 	BUG_ON(!bh);
@@ -2480,7 +2475,7 @@
 	wake_up(&buffer_wait);
 
 	/* And free the page */
-	page->buffers = NULL;
+	clear_page_buffers(page);
 	page_cache_release(page);
 	write_unlock(&hash_table_lock);
 	spin_unlock(&lru_list_lock);
@@ -2607,21 +2602,6 @@
 
 }
 
-
-/* ====================== bdflush support =================== */
-
-/* This is a simple kernel daemon, whose job it is to provide a dynamic
- * response to dirty buffers.  Once this process is activated, we write back
- * a limited number of buffers to the disks and then go back to sleep again.
- */
-
-DECLARE_WAIT_QUEUE_HEAD(bdflush_wait);
-
-void wakeup_bdflush(void)
-{
-	wake_up_interruptible(&bdflush_wait);
-}
-
 /* 
  * Here we attempt to write back old buffers.  We also try to flush inodes 
  * and supers as well, since this function is essentially "update", and 
@@ -2630,7 +2610,7 @@
  * and superblocks so that we could write back only the old ones as well
  */
 
-static int sync_old_buffers(void)
+static void sync_old_buffers(unsigned long dummy)
 {
 	lock_kernel();
 	sync_unlocked_inodes();
@@ -2646,10 +2626,9 @@
 			break;
 		if (write_some_buffers(NULL))
 			continue;
-		return 0;
+		return;
 	}
 	spin_unlock(&lru_list_lock);
-	return 0;
 }
 
 int block_sync_page(struct page *page)
@@ -2711,112 +2690,45 @@
 	return 0;
 }
 
-/*
- * This is the actual bdflush daemon itself. It used to be started from
- * the syscall above, but now we launch it ourselves internally with
- * kernel_thread(...)  directly after the first thread in init/main.c
- */
-int bdflush(void *startup)
+static void bdflush(unsigned long pexclude)
 {
-	struct task_struct *tsk = current;
-
-	/*
-	 *	We have a bare-bones task_struct, and really should fill
-	 *	in a few more things so "top" and /proc/2/{exe,root,cwd}
-	 *	display semi-sane things. Not real crucial though...  
-	 */
-
-	tsk->session = 1;
-	tsk->pgrp = 1;
-	strcpy(tsk->comm, "bdflush");
-
-	/* avoid getting signals */
-	spin_lock_irq(&tsk->sigmask_lock);
-	flush_signals(tsk);
-	sigfillset(&tsk->blocked);
-	recalc_sigpending();
-	spin_unlock_irq(&tsk->sigmask_lock);
-
-	complete((struct completion *)startup);
-
-	for (;;) {
-		CHECK_EMERGENCY_SYNC
-
+	while (balance_dirty_state() >= 0) {
 		spin_lock(&lru_list_lock);
-		if (!write_some_buffers(NULL) || balance_dirty_state() < 0) {
-			wait_for_some_buffers(NULL);
-			interruptible_sleep_on(&bdflush_wait);
-		}
+		if (write_some_buffers(NULL) == 0)
+			break;
 	}
+	clear_bit(0, (unsigned long *)pexclude);
 }
 
-/*
- * This is the kernel update daemon. It was used to live in userspace
- * but since it's need to run safely we want it unkillable by mistake.
- * You don't need to change your userspace configuration since
- * the userspace `update` will do_exit(0) at the first sys_bdflush().
- */
-int kupdate(void *startup)
+void wakeup_bdflush(void)
 {
-	struct task_struct * tsk = current;
-	int interval;
-
-	tsk->session = 1;
-	tsk->pgrp = 1;
-	strcpy(tsk->comm, "kupdated");
-
-	/* sigstop and sigcont will stop and wakeup kupdate */
-	spin_lock_irq(&tsk->sigmask_lock);
-	sigfillset(&tsk->blocked);
-	siginitsetinv(&current->blocked, sigmask(SIGCONT) | sigmask(SIGSTOP));
-	recalc_sigpending();
-	spin_unlock_irq(&tsk->sigmask_lock);
+	static unsigned long exclude;
 
-	complete((struct completion *)startup);
-
-	for (;;) {
-		wait_for_some_buffers(NULL);
-
-		/* update interval */
-		interval = bdf_prm.b_un.interval;
-		if (interval) {
-			tsk->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(interval);
-		} else {
-		stop_kupdate:
-			tsk->state = TASK_STOPPED;
-			schedule(); /* wait for SIGCONT */
-		}
-		/* check for sigstop */
-		if (signal_pending(tsk)) {
-			int stopped = 0;
-			spin_lock_irq(&tsk->sigmask_lock);
-			if (sigismember(&tsk->pending.signal, SIGSTOP)) {
-				sigdelset(&tsk->pending.signal, SIGSTOP);
-				stopped = 1;
-			}
-			recalc_sigpending();
-			spin_unlock_irq(&tsk->sigmask_lock);
-			if (stopped)
-				goto stop_kupdate;
-		}
-#ifdef DEBUG
-		printk(KERN_DEBUG "kupdate() activated...\n");
-#endif
-		sync_old_buffers();
+	if (!test_and_set_bit(0, &exclude)) {
+		if (pdflush_operation(bdflush, (unsigned long)&exclude))
+			clear_bit(0, &exclude);
 	}
 }
 
-static int __init bdflush_init(void)
+/*
+ * kupdate
+ */
+static struct timer_list kupdate_timer;
+static void kupdate_handler(unsigned long dummy)
 {
-	static struct completion startup __initdata = COMPLETION_INITIALIZER(startup);
+	pdflush_operation(sync_old_buffers, 0);
+	mod_timer(&kupdate_timer, jiffies + bdf_prm.b_un.interval);
+}
 
-	kernel_thread(bdflush, &startup, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
-	wait_for_completion(&startup);
-	kernel_thread(kupdate, &startup, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
-	wait_for_completion(&startup);
+static int __init kupdate_init(void)
+{
+	init_timer(&kupdate_timer);
+	kupdate_timer.expires = jiffies + bdf_prm.b_un.interval;
+	kupdate_timer.data = 0;
+	kupdate_timer.function = kupdate_handler;
+	add_timer(&kupdate_timer);
 	return 0;
 }
 
-module_init(bdflush_init)
+module_init(kupdate_init)
 
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	Sun Apr 14 12:16:57 2002
+++ b/fs/char_dev.c	Sun Apr 14 12:16:57 2002
@@ -67,7 +67,7 @@
 {
 	struct list_head *p;
 	struct char_device *cdev;
-	for (p=head->next; p!=head; p=p->next) {
+	list_for_each(p, head) {
 		cdev = list_entry(p, struct char_device, hash);
 		if (cdev->dev != dev)
 			continue;
diff -Nru a/fs/coda/inode.c b/fs/coda/inode.c
--- a/fs/coda/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/coda/inode.c	Sun Apr 14 12:16:59 2002
@@ -258,6 +258,8 @@
         struct coda_vattr vattr;
         int error;
 	
+	lock_kernel();
+	
         memset(&vattr, 0, sizeof(vattr)); 
 
 	inode->i_ctime = CURRENT_TIME;
@@ -271,6 +273,8 @@
 	        coda_vattr_to_iattr(inode, &vattr); 
 		coda_cache_clear_inode(inode);
 	}
+
+	unlock_kernel();
 
 	return error;
 }
diff -Nru a/fs/cramfs/inode.c b/fs/cramfs/inode.c
--- a/fs/cramfs/inode.c	Sun Apr 14 12:16:55 2002
+++ b/fs/cramfs/inode.c	Sun Apr 14 12:16:55 2002
@@ -112,8 +112,6 @@
 	struct buffer_head * read_array[BLKS_PER_BUF];
 	unsigned i, blocknr, buffer, unread;
 	unsigned long devsize;
-	unsigned int major, minor;
-
 	char *data;
 
 	if (!len)
@@ -136,12 +134,9 @@
 		return read_buffers[i] + blk_offset;
 	}
 
-	devsize = ~0UL;
-	major = major(sb->s_dev);
-	minor = minor(sb->s_dev);
-
-	if (blk_size[major])
-		devsize = blk_size[major][minor] >> 2;
+	devsize = sb->s_bdev->bd_inode->i_size >> 12;
+	if (!devsize)
+		devsize = ~0UL;
 
 	/* Ok, read in BLKS_PER_BUF pages completely first. */
 	unread = 0;
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Sun Apr 14 12:16:56 2002
+++ b/fs/devfs/base.c	Sun Apr 14 12:16:56 2002
@@ -612,6 +612,14 @@
 	       Added KERN_* to remaining messages.
 	       Cleaned up declaration of <stat_read>.
   v1.11
+    20020219   Richard Gooch <rgooch@atnf.csiro.au>
+	       Changed <devfs_rmdir> to allow later additions if not yet empty.
+  v1.12
+    20020406   Richard Gooch <rgooch@atnf.csiro.au>
+	       Removed silently introduced calls to lock_kernel() and
+	       unlock_kernel() due to recent VFS locking changes. BKL isn't
+	       required in devfs.
+  v1.13
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -644,7 +652,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "1.11 (20020129)"
+#define DEVFS_VERSION            "1.13 (20020406)"
 
 #define DEVFS_NAME "devfs"
 
@@ -2667,7 +2675,7 @@
       case 0:
 	scan_dir_for_removable (parent);
 	err = (*filldir) (dirent, "..", 2, file->f_pos,
-			  parent_ino(file->f_dentry), DT_DIR);
+			  parent_ino (file->f_dentry), DT_DIR);
 	if (err == -EINVAL) break;
 	if (err < 0) return err;
 	file->f_pos++;
@@ -2933,14 +2941,10 @@
 	up on any error  */
     dentry->d_op = &devfs_dops;
     /*  First try to get the devfs entry for this directory  */
-    lock_kernel();
     parent = get_devfs_entry_from_vfs_inode (dir);
     DPRINTK (DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n",
 	     dentry->d_name.name, dentry, parent, current->comm);
-    if (parent == NULL) {
-	unlock_kernel();
-	return ERR_PTR (-ENOENT);
-    }
+    if (parent == NULL) return ERR_PTR (-ENOENT);
     read_lock (&parent->u.dir.lock);
     de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
     read_unlock (&parent->u.dir.lock);
@@ -2965,7 +2969,6 @@
 	if (try_modload (parent, fs_info,
 			 dentry->d_name.name, dentry->d_name.len, &tmp) < 0)
 	{   /*  Lookup event was not queued to devfsd  */
-	    unlock_kernel();
 	    d_add (dentry, NULL);
 	    return NULL;
 	}
@@ -3008,7 +3011,6 @@
     wake_up (&lookup_info.wait_queue);
     write_unlock (&parent->u.dir.lock);
     devfs_put (de);
-    unlock_kernel();
     return retval;
 }   /*  End Function devfs_lookup  */
 
@@ -3019,30 +3021,19 @@
     struct inode *inode = dentry->d_inode;
     struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
 
-    lock_kernel();
     de = get_devfs_entry_from_vfs_inode (inode);
     DPRINTK (DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de);
-    if (de == NULL) {
-	unlock_kernel();
-	return -ENOENT;
-    }
-    if (!de->vfs_deletable) {
-	unlock_kernel();
-	return -EPERM;
-    }
+    if (de == NULL) return -ENOENT;
+    if (!de->vfs_deletable) return -EPERM;
     write_lock (&de->parent->u.dir.lock);
     unhooked = _devfs_unhook (de);
     write_unlock (&de->parent->u.dir.lock);
-    if (!unhooked) {
-	unlock_kernel();
-	return -ENOENT;
-    }
+    if (!unhooked) return -ENOENT;
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
 			  inode->i_uid, inode->i_gid, fs_info, 0);
     free_dentry (de);
     devfs_put (de);
-    unlock_kernel();
     return 0;
 }   /*  End Function devfs_unlink  */
 
@@ -3055,37 +3046,27 @@
     struct inode *inode;
 
     /*  First try to get the devfs entry for this directory  */
-    lock_kernel();
     parent = get_devfs_entry_from_vfs_inode (dir);
-    if (parent == NULL) {
-	unlock_kernel();
-	return -ENOENT;
-    }
+    if (parent == NULL) return -ENOENT;
     err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
 			    symname, &de, NULL);
     DPRINTK (DEBUG_DISABLED, "(%s): errcode from <devfs_do_symlink>: %d\n",
 	     dentry->d_name.name, err);
-    if (err < 0) {
-	unlock_kernel();
-	return err;
-    }
+    if (err < 0) return err;
     de->vfs_deletable = TRUE;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) {
-	unlock_kernel();
+    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
-    }
     DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p  dentry: %p\n",
 	     dentry->d_name.name, de->inode.ino, inode, dentry);
     d_instantiate (dentry, inode);
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
 			  inode->i_uid, inode->i_gid, fs_info, 0);
-    unlock_kernel();
     return 0;
 }   /*  End Function devfs_symlink  */
 
@@ -3097,38 +3078,26 @@
     struct inode *inode;
 
     mode = (mode & ~S_IFMT) | S_IFDIR;  /*  VFS doesn't pass S_IFMT part  */
-    lock_kernel();
     parent = get_devfs_entry_from_vfs_inode (dir);
-    if (parent == NULL) {
-	unlock_kernel();
-	return -ENOENT;
-    }
+    if (parent == NULL) return -ENOENT;
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
-    if (!de) {
-	unlock_kernel();
-	return -ENOMEM;
-    }
+    if (!de) return -ENOMEM;
     de->vfs_deletable = TRUE;
-    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 ) {
-	unlock_kernel();
+    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
 	return err;
-    }
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) {
-	unlock_kernel();
+    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
-    }
     DPRINTK (DEBUG_DISABLED, "(%s): new VFS inode(%u): %p  dentry: %p\n",
 	     dentry->d_name.name, de->inode.ino, inode, dentry);
     d_instantiate (dentry, inode);
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
 			  inode->i_uid, inode->i_gid, fs_info, 0);
-    unlock_kernel();
     return 0;
 }   /*  End Function devfs_mkdir  */
 
@@ -3139,45 +3108,27 @@
     struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
     struct inode *inode = dentry->d_inode;
 
-    /* WTF??? */
     if (dir->i_sb->u.generic_sbp != inode->i_sb->u.generic_sbp) return -EINVAL;
-    lock_kernel();
     de = get_devfs_entry_from_vfs_inode (inode);
-    if (de == NULL) {
-	unlock_kernel();
-	return -ENOENT;
-    }
-    if ( !S_ISDIR (de->mode) ) {
-	unlock_kernel();
-	return -ENOTDIR;
-    }
-    if (!de->vfs_deletable) {
-	unlock_kernel();
-	return -EPERM;
-    }
-    /*  First ensure the directory is empty and will stay thay way  */
+    if (de == NULL) return -ENOENT;
+    if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
+    if (!de->vfs_deletable) return -EPERM;
+    /*  First ensure the directory is empty and will stay that way  */
     write_lock (&de->u.dir.lock);
-    de->u.dir.no_more_additions = TRUE;
     if (de->u.dir.first) err = -ENOTEMPTY;
+    else de->u.dir.no_more_additions = TRUE;
     write_unlock (&de->u.dir.lock);
-    if (err) {
-	unlock_kernel();
-	return err;
-    }
+    if (err) return err;
     /*  Now unhook the directory from it's parent  */
     write_lock (&de->parent->u.dir.lock);
     if ( !_devfs_unhook (de) ) err = -ENOENT;
     write_unlock (&de->parent->u.dir.lock);
-    if (err) {
-	unlock_kernel();
-	return err;
-    }
+    if (err) return err;
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
 			  inode->i_uid, inode->i_gid, fs_info, 0);
     free_dentry (de);
     devfs_put (de);
-    unlock_kernel();
     return 0;
 }   /*  End Function devfs_rmdir  */
 
@@ -3191,43 +3142,31 @@
 
     DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o  dev: %d\n",
 	     dentry->d_name.name, mode, rdev);
-    lock_kernel();
     parent = get_devfs_entry_from_vfs_inode (dir);
-    if (parent == NULL) {
-	unlock_kernel();
-	return -ENOENT;
-    }
+    if (parent == NULL) return -ENOENT;
     de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
-    if (!de) {
-	unlock_kernel();
-	return -ENOMEM;
-    }
+    if (!de) return -ENOMEM;
     de->vfs_deletable = TRUE;
     if ( S_ISBLK (mode) || S_ISCHR (mode) )
     {
 	de->u.fcb.u.device.major = MAJOR (rdev);
 	de->u.fcb.u.device.minor = MINOR (rdev);
     }
-    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 ) {
-	unlock_kernel();
+    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
 	return err;
-    }
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL ) {
-	unlock_kernel();
+    if ( ( inode = _devfs_get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
-    }
     DPRINTK (DEBUG_I_MKNOD, ":   new VFS inode(%u): %p  dentry: %p\n",
 	     de->inode.ino, inode, dentry);
     d_instantiate (dentry, inode);
     if ( !is_devfsd_or_child (fs_info) )
 	devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
 			  inode->i_uid, inode->i_gid, fs_info, 0);
-    unlock_kernel();
     return 0;
 }   /*  End Function devfs_mknod  */
 
@@ -3301,18 +3240,19 @@
     PRINTK ("(): get root inode failed\n");
     if (root_inode) iput (root_inode);
     return -EINVAL;
-}   /*  End Function devfs_read_super  */
+}   /*  End Function devfs_fill_super  */
 
-static struct super_block *devfs_get_sb(struct file_system_type *fs_type,
-	int flags, char *dev_name, void *data)
+static struct super_block *devfs_get_sb (struct file_system_type *fs_type,
+					 int flags, char *dev_name, void *data)
 {
-	return get_sb_single(fs_type, flags, data, devfs_fill_super);
+    return get_sb_single (fs_type, flags, data, devfs_fill_super);
 }
 
-static struct file_system_type devfs_fs_type = {
-	name:		DEVFS_NAME,
-	get_sb:		devfs_get_sb,
-	kill_sb:	kill_anon_super,
+static struct file_system_type devfs_fs_type =
+{
+    name:	DEVFS_NAME,
+    get_sb:	devfs_get_sb,
+    kill_sb:	kill_anon_super,
 };
 
 /*  File operations for devfsd follow  */
diff -Nru a/fs/devfs/util.c b/fs/devfs/util.c
--- a/fs/devfs/util.c	Sun Apr 14 12:16:54 2002
+++ b/fs/devfs/util.c	Sun Apr 14 12:16:54 2002
@@ -1,6 +1,6 @@
 /*  devfs (Device FileSystem) utilities.
 
-    Copyright (C) 1999-2001  Richard Gooch
+    Copyright (C) 1999-2002  Richard Gooch
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
@@ -48,6 +48,12 @@
     20010818   Richard Gooch <rgooch@atnf.csiro.au>
                Updated major masks up to Linus' "no new majors" proclamation.
 	       Block: were 126 now 122 free, char: were 26 now 19 free.
+    20020324   Richard Gooch <rgooch@atnf.csiro.au>
+               Fixed bug in <devfs_alloc_unique_number>: was clearing beyond
+	       bitfield.
+    20020326   Richard Gooch <rgooch@atnf.csiro.au>
+               Fixed bitfield data type for <devfs_*alloc_devnum>.
+               Made major bitfield type and initialiser 64 bit safe.
 */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -125,8 +131,13 @@
 struct major_list
 {
     spinlock_t lock;
-    __u32 bits[8];
+    unsigned long bits[256 / BITS_PER_LONG];
 };
+#if BITS_PER_LONG == 32
+#  define INITIALISER64(low,high) (low), (high)
+#else
+#  define INITIALISER64(low,high) ( (high) << 32 | (low) )
+#endif
 
 /*  Block majors already assigned:
     0-3, 7-9, 11-63, 65-99, 101-113, 120-127, 199, 201, 240-255
@@ -134,14 +145,11 @@
 */
 static struct major_list block_major_list =
 {SPIN_LOCK_UNLOCKED,
-    {0xfffffb8f,  /*  Majors 0   to 31   */
-     0xffffffff,  /*  Majors 32  to 63   */
-     0xfffffffe,  /*  Majors 64  to 95   */
-     0xff03ffef,  /*  Majors 96  to 127  */
-     0x00000000,  /*  Majors 128 to 159  */
-     0x00000000,  /*  Majors 160 to 191  */
-     0x00000280,  /*  Majors 192 to 223  */
-     0xffff0000}  /*  Majors 224 to 255  */
+    {INITIALISER64 (0xfffffb8f, 0xffffffff),  /*  Majors 0-31,    32-63    */
+     INITIALISER64 (0xfffffffe, 0xff03ffef),  /*  Majors 64-95,   96-127   */
+     INITIALISER64 (0x00000000, 0x00000000),  /*  Majors 128-159, 160-191  */
+     INITIALISER64 (0x00000280, 0xffff0000),  /*  Majors 192-223, 224-255  */
+    }
 };
 
 /*  Char majors already assigned:
@@ -150,14 +158,11 @@
 */
 static struct major_list char_major_list =
 {SPIN_LOCK_UNLOCKED,
-    {0xfffffeff,  /*  Majors 0   to 31   */
-     0xffffffff,  /*  Majors 32  to 63   */
-     0xffffffff,  /*  Majors 64  to 95   */
-     0xffffffff,  /*  Majors 96  to 127  */
-     0x7cffffff,  /*  Majors 128 to 159  */
-     0xffffffff,  /*  Majors 160 to 191  */
-     0x3f0fffff,  /*  Majors 192 to 223  */
-     0xffff007f}  /*  Majors 224 to 255  */
+    {INITIALISER64 (0xfffffeff, 0xffffffff),  /*  Majors 0-31,    32-63    */
+     INITIALISER64 (0xffffffff, 0xffffffff),  /*  Majors 64-95,   96-127   */
+     INITIALISER64 (0x7cffffff, 0xffffffff),  /*  Majors 128-159, 160-191  */
+     INITIALISER64 (0x3f0fffff, 0xffff007f),  /*  Majors 192-223, 224-255  */
+    }
 };
 
 
@@ -212,7 +217,7 @@
 struct minor_list
 {
     int major;
-    __u32 bits[8];
+    unsigned long bits[256 / BITS_PER_LONG];
     struct minor_list *next;
 };
 
@@ -267,7 +272,7 @@
 	if (minor >= 256) continue;
 	__set_bit (minor, entry->bits);
 	up (semaphore);
-	return mk_kdev(entry->major, minor);
+	return mk_kdev (entry->major, minor);
     }
     /*  Need to allocate a new major  */
     if ( ( entry = kmalloc (sizeof *entry, GFP_KERNEL) ) == NULL )
@@ -289,7 +294,7 @@
     else list->last->next = entry;
     list->last = entry;
     up (semaphore);
-    return mk_kdev(entry->major, 0);
+    return mk_kdev (entry->major, 0);
 }   /*  End Function devfs_alloc_devnum  */
 EXPORT_SYMBOL(devfs_alloc_devnum);
 
@@ -309,7 +314,7 @@
     struct device_list *list;
     struct minor_list *entry;
 
-    if (kdev_none(devnum)) return;
+    if ( kdev_none (devnum) ) return;
     if (type == DEVFS_SPECIAL_CHR)
     {
 	semaphore = &char_semaphore;
@@ -355,7 +360,6 @@
 {
     int number;
     unsigned int length;
-    __u32 *bits;
 
     /*  Get around stupid lack of semaphore initialiser  */
     spin_lock (&space->init_lock);
@@ -368,6 +372,8 @@
     down (&space->semaphore);
     if (space->num_free < 1)
     {
+	void *bits;
+
 	if (space->length < 16) length = 16;
 	else length = space->length << 1;
 	if ( ( bits = vmalloc (length) ) == NULL )
diff -Nru a/fs/devpts/inode.c b/fs/devpts/inode.c
--- a/fs/devpts/inode.c	Sun Apr 14 12:16:56 2002
+++ b/fs/devpts/inode.c	Sun Apr 14 12:16:56 2002
@@ -66,9 +66,9 @@
 	char *this_char, *value;
 
 	this_char = NULL;
-	if ( options )
-		this_char = strtok(options,",");
-	for ( ; this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
 		if (!strcmp(this_char,"uid")) {
@@ -123,9 +123,10 @@
 	struct inode * inode;
 	struct devpts_sb_info *sbi;
 
-	sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info), GFP_KERNEL);
+	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if ( !sbi )
 		goto fail;
+	memset(sbi, 0, sizeof(*sbi));
 
 	sbi->magic  = DEVPTS_SBI_MAGIC;
 	sbi->max_ptys = unix98_max_ptys;
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	Sun Apr 14 12:16:55 2002
+++ b/fs/dquot.c	Sun Apr 14 12:16:55 2002
@@ -59,6 +59,7 @@
 #include <linux/tty.h>
 #include <linux/file.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 
@@ -336,7 +337,7 @@
 	struct list_head *head;
 
 restart:
-	for (head = inuse_list.next; head != &inuse_list; head = head->next) {
+	list_for_each(head, &inuse_list) {
 		dquot = list_entry(head, struct dquot, dq_inuse);
 		if (dquot->dq_sb != sb)
 			continue;
@@ -366,7 +367,7 @@
 
 	lock_kernel();
 restart:
-	for (head = inuse_list.next; head != &inuse_list; head = head->next) {
+	list_for_each(head, &inuse_list) {
 		dquot = list_entry(head, struct dquot, dq_inuse);
 		if (sb && dquot->dq_sb != sb)
 			continue;
@@ -578,7 +579,7 @@
 
 restart:
 	file_list_lock();
-	for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
+	list_for_each(p, &sb->s_files) {
 		struct file *filp = list_entry(p, struct file, f_list);
 		struct inode *inode = filp->f_dentry->d_inode;
 		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
@@ -1240,10 +1241,23 @@
 	return ret;
 }
 
+static ctl_table fs_table[] = {
+	{FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
+	 0444, NULL, &proc_dointvec},
+	{},
+};
+
+static ctl_table dquot_table[] = {
+	{CTL_FS, "fs", NULL, 0, 0555, fs_table},
+	{},
+};
+
 static int __init dquot_init(void)
 {
 	int i;
 
+	register_sysctl_table(dquot_table, 0);
+
 	for (i = 0; i < NR_DQHASH; i++)
 		INIT_LIST_HEAD(dquot_hash + i);
 	printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
@@ -1255,13 +1269,13 @@
  * Definitions of diskquota operations.
  */
 struct dquot_operations dquot_operations = {
-	dquot_initialize,		/* mandatory */
-	dquot_drop,			/* mandatory */
-	dquot_alloc_block,
-	dquot_alloc_inode,
-	dquot_free_block,
-	dquot_free_inode,
-	dquot_transfer
+	initialize:	dquot_initialize,		/* mandatory */
+	drop:		dquot_drop,			/* mandatory */
+	alloc_block:	dquot_alloc_block,
+	alloc_inode:	dquot_alloc_inode,
+	free_block:	dquot_free_block,
+	free_inode:	dquot_free_inode,
+	transfer:	dquot_transfer
 };
 
 static inline void set_enable_flags(struct quota_mount_options *dqopt, short type)
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
--- a/fs/ext2/ext2.h	Sun Apr 14 12:16:58 2002
+++ b/fs/ext2/ext2.h	Sun Apr 14 12:16:58 2002
@@ -10,7 +10,6 @@
 	__u32	i_faddr;
 	__u8	i_frag_no;
 	__u8	i_frag_size;
-	__u16	i_osync;
 	__u32	i_file_acl;
 	__u32	i_dir_acl;
 	__u32	i_dtime;
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
--- a/fs/ext2/ialloc.c	Sun Apr 14 12:16:59 2002
+++ b/fs/ext2/ialloc.c	Sun Apr 14 12:16:59 2002
@@ -393,7 +393,6 @@
 	ei->i_faddr = 0;
 	ei->i_frag_no = 0;
 	ei->i_frag_size = 0;
-	ei->i_osync = 0;
 	ei->i_file_acl = 0;
 	ei->i_dir_acl = 0;
 	ei->i_dtime = 0;
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	Sun Apr 14 12:16:55 2002
+++ b/fs/ext2/inode.c	Sun Apr 14 12:16:55 2002
@@ -405,10 +405,10 @@
 		mark_buffer_uptodate(bh, 1);
 		unlock_buffer(bh);
 		mark_buffer_dirty_inode(bh, inode);
-		if (IS_SYNC(inode) || EXT2_I(inode)->i_osync) {
-			ll_rw_block (WRITE, 1, &bh);
-			wait_on_buffer (bh);
-		}
+		/* We used to sync bh here if IS_SYNC(inode).
+		 * But we now rely upon generic_osync_inode()
+		 * and b_inode_buffers
+		 */
 		parent = nr;
 	}
 	if (n == num)
@@ -467,18 +467,10 @@
 	inode->i_ctime = CURRENT_TIME;
 
 	/* had we spliced it onto indirect block? */
-	if (where->bh) {
+	if (where->bh)
 		mark_buffer_dirty_inode(where->bh, inode);
-		if (IS_SYNC(inode) || ei->i_osync) {
-			ll_rw_block (WRITE, 1, &where->bh);
-			wait_on_buffer(where->bh);
-		}
-	}
 
-	if (IS_SYNC(inode) || ei->i_osync)
-		ext2_sync_inode (inode);
-	else
-		mark_inode_dirty(inode);
+	mark_inode_dirty(inode);
 	return 0;
 
 changed:
@@ -833,10 +825,6 @@
 				   (u32*)partial->bh->b_data + addr_per_block,
 				   (chain+n-1) - partial);
 		mark_buffer_dirty_inode(partial->bh, inode);
-		if (IS_SYNC(inode)) {
-			ll_rw_block (WRITE, 1, &partial->bh);
-			wait_on_buffer (partial->bh);
-		}
 		brelse (partial->bh);
 		partial--;
 	}
@@ -868,10 +856,12 @@
 			;
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	if (IS_SYNC(inode))
+	if (IS_SYNC(inode)) {
+		fsync_inode_buffers(inode);
 		ext2_sync_inode (inode);
-	else
+	} else {
 		mark_inode_dirty(inode);
+	}
 }
 
 static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,
@@ -958,7 +948,6 @@
 	ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
 	ei->i_frag_no = raw_inode->i_frag;
 	ei->i_frag_size = raw_inode->i_fsize;
-	ei->i_osync = 0;
 	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
 	ei->i_dir_acl = 0;
 	if (S_ISREG(inode->i_mode))
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	Sun Apr 14 12:16:59 2002
+++ b/fs/ext2/super.c	Sun Apr 14 12:16:59 2002
@@ -221,9 +221,9 @@
 
 	if (!options)
 		return 1;
-	for (this_char = strtok (options, ",");
-	     this_char != NULL;
-	     this_char = strtok (NULL, ",")) {
+	while ((this_char = strsep (&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr (this_char, '=')) != NULL)
 			*value++ = 0;
 		if (!strcmp (this_char, "bsddf"))
@@ -465,11 +465,11 @@
 	int db_count;
 	int i, j;
 
-	sbi = kmalloc(sizeof(struct ext2_super_block), GFP_KERNEL);
+	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
 	sb->u.generic_sbp = sbi;
-	memset(sbi, 0, sizeof(struct ext2_super_block));
+	memset(sbi, 0, sizeof(*sbi));
 
 	/*
 	 * See what the current blocksize for the device is, and
diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c
--- a/fs/ext3/balloc.c	Sun Apr 14 12:16:55 2002
+++ b/fs/ext3/balloc.c	Sun Apr 14 12:16:55 2002
@@ -542,6 +542,7 @@
 	int i, j, k, tmp, alloctmp;
 	int bitmap_nr;
 	int fatal = 0, err;
+	int performed_allocation = 0;
 	struct super_block * sb;
 	struct ext3_group_desc * gdp;
 	struct ext3_super_block * es;
@@ -644,8 +645,7 @@
 	}
 
 	/* No space left on the device */
-	unlock_super (sb);
-	return 0;
+	goto out;
 
 search_back:
 	/* 
@@ -694,6 +694,7 @@
 	J_ASSERT_BH(bh, !ext3_test_bit(j, bh->b_data));
 	BUFFER_TRACE(bh, "setting bitmap bit");
 	ext3_set_bit(j, bh->b_data);
+	performed_allocation = 1;
 
 #ifdef CONFIG_JBD_DEBUG
 	{
@@ -815,6 +816,11 @@
 		ext3_std_error(sb, fatal);
 	}
 	unlock_super (sb);
+	/*
+	 * Undo the block allocation
+	 */
+	if (!performed_allocation)
+		DQUOT_FREE_BLOCK(inode, 1);
 	return 0;
 	
 }
diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
--- a/fs/ext3/ialloc.c	Sun Apr 14 12:16:58 2002
+++ b/fs/ext3/ialloc.c	Sun Apr 14 12:16:58 2002
@@ -509,7 +509,7 @@
 	if (IS_SYNC(inode))
 		handle->h_sync = 1;
 	insert_inode_hash(inode);
-	inode->i_generation = event++;
+	inode->i_generation = sb->u.ext3_sb.s_next_generation++;
 
 	ei->i_state = EXT3_STATE_NEW;
 	err = ext3_mark_inode_dirty(handle, inode);
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/ext3/inode.c	Sun Apr 14 12:16:59 2002
@@ -584,8 +584,6 @@
 			
 			parent = nr;
 		}
-		if (IS_SYNC(inode))
-			handle->h_sync = 1;
 	}
 	if (n == num)
 		return 0;
@@ -1031,7 +1029,7 @@
 		goto prepare_write_failed;
 
 	if (ext3_should_journal_data(inode)) {
-		ret = walk_page_buffers(handle, page->buffers,
+		ret = walk_page_buffers(handle, page_buffers(page),
 				from, to, NULL, do_journal_get_write_access);
 		if (ret) {
 			/*
@@ -1104,7 +1102,7 @@
 		int partial = 0;
 		loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
-		ret = walk_page_buffers(handle, page->buffers,
+		ret = walk_page_buffers(handle, page_buffers(page),
 			from, to, &partial, commit_write_fn);
 		if (!partial)
 			SetPageUptodate(page);
@@ -1114,7 +1112,7 @@
 		EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
 	} else {
 		if (ext3_should_order_data(inode)) {
-			ret = walk_page_buffers(handle, page->buffers,
+			ret = walk_page_buffers(handle, page_buffers(page),
 				from, to, NULL, journal_dirty_sync_data);
 		}
 		/* Be careful here if generic_commit_write becomes a
@@ -1254,7 +1252,7 @@
 static int ext3_writepage(struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-	struct buffer_head *page_buffers;
+	struct buffer_head *page_bufs;
 	handle_t *handle = NULL;
 	int ret = 0, err;
 	int needed;
@@ -1287,14 +1285,14 @@
 
 	unlock_kernel();
 
-	page_buffers = NULL;	/* Purely to prevent compiler warning */
+	page_bufs = NULL;	/* Purely to prevent compiler warning */
 
 	/* bget() all the buffers */
 	if (order_data) {
-		if (!page->buffers)
+		if (!page_has_buffers(page))
 			create_empty_buffers(page, inode->i_sb->s_blocksize);
-		page_buffers = page->buffers;
-		walk_page_buffers(handle, page_buffers, 0,
+		page_bufs = page_buffers(page);
+		walk_page_buffers(handle, page_bufs, 0,
 				PAGE_CACHE_SIZE, NULL, bget_one);
 	}
 
@@ -1303,7 +1301,7 @@
 	/*
 	 * The page can become unlocked at any point now, and
 	 * truncate can then come in and change things.  So we
-	 * can't touch *page from now on.  But *page_buffers is
+	 * can't touch *page from now on.  But *page_bufs is
 	 * safe due to elevated refcount.
 	 */
 
@@ -1312,7 +1310,7 @@
 
 	/* And attach them to the current transaction */
 	if (order_data) {
-		err = walk_page_buffers(handle, page_buffers,
+		err = walk_page_buffers(handle, page_bufs,
 			0, PAGE_CACHE_SIZE, NULL, journal_dirty_async_data);
 		if (!ret)
 			ret = err;
@@ -1394,11 +1392,11 @@
 	if (!page)
 		goto out;
 
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		create_empty_buffers(page, blocksize);
 
 	/* Find the buffer that contains "offset" */
-	bh = page->buffers;
+	bh = page_buffers(page);
 	pos = blocksize;
 	while (offset >= pos) {
 		bh = bh->b_this_page;
@@ -2379,6 +2377,8 @@
 			return error;
 	}
 
+	lock_kernel();
+
 	if (attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
 		handle_t *handle;
 
@@ -2406,6 +2406,7 @@
 
 err_out:
 	ext3_std_error(inode->i_sb, error);
+	unlock_kernel();
 	if (!error)
 		error = rc;
 	return error;
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Sun Apr 14 12:16:59 2002
+++ b/fs/ext3/super.c	Sun Apr 14 12:16:59 2002
@@ -554,9 +554,9 @@
 
 	if (!options)
 		return 1;
-	for (this_char = strtok (options, ",");
-	     this_char != NULL;
-	     this_char = strtok (NULL, ",")) {
+	while ((this_char = strsep (&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr (this_char, '=')) != NULL)
 			*value++ = 0;
 		if (!strcmp (this_char, "bsddf"))
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	Sun Apr 14 12:16:58 2002
+++ b/fs/fat/inode.c	Sun Apr 14 12:16:58 2002
@@ -177,7 +177,6 @@
 		fat_clusters_flush(sb);
 	}
 	fat_cache_inval_dev(sb);
-	set_blocksize (sb->s_dev,BLOCK_SIZE);
 	if (sbi->nls_disk) {
 		unload_nls(sbi->nls_disk);
 		sbi->nls_disk = NULL;
@@ -225,8 +224,9 @@
 		goto out;
 	save = 0;
 	savep = NULL;
-	for (this_char = strtok(options,","); this_char;
-	     this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL) {
 			save = *value;
 			savep = value;
@@ -486,7 +486,7 @@
 	 * code.
 	 */
 	spin_lock(&dcache_lock);
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
+	list_for_each(lp, &inode->i_dentry) {
 		result = list_entry(lp,struct dentry, d_alias);
 		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
 			dget_locked(result);
@@ -1054,17 +1054,24 @@
 {
 	struct super_block *sb = dentry->d_sb;
 	struct inode *inode = dentry->d_inode;
-	int error;
+	int error = 0;
+
+	lock_kernel();
 
 	/* FAT cannot truncate to a longer file */
 	if (attr->ia_valid & ATTR_SIZE) {
-		if (attr->ia_size > inode->i_size)
-			return -EPERM;
+		if (attr->ia_size > inode->i_size) {
+			error = -EPERM;
+			goto out;
+		}
 	}
 
 	error = inode_change_ok(inode, attr);
-	if (error)
-		return MSDOS_SB(sb)->options.quiet ? 0 : error;
+	if (error) {
+		if( MSDOS_SB(sb)->options.quiet )
+		    error = 0; 
+ 		goto out;
+	}
 
 	if (((attr->ia_valid & ATTR_UID) && 
 	     (attr->ia_uid != MSDOS_SB(sb)->options.fs_uid)) ||
@@ -1074,12 +1081,14 @@
 	     (attr->ia_mode & ~MSDOS_VALID_MODE)))
 		error = -EPERM;
 
-	if (error)
-		return MSDOS_SB(sb)->options.quiet ? 0 : error;
-
+	if (error) {
+		if( MSDOS_SB(sb)->options.quiet )  
+			error = 0;
+		goto out;
+	}
 	error = inode_setattr(inode, attr);
 	if (error)
-		return error;
+		goto out;
 
 	if (S_ISDIR(inode->i_mode))
 		inode->i_mode |= S_IXUGO;
@@ -1087,6 +1096,8 @@
 	inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
 	    & ~MSDOS_SB(sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
 	    ~MSDOS_SB(sb)->options.fs_umask;
-	return 0;
+out:
+	unlock_kernel();
+	return error;
 }
 MODULE_LICENSE("GPL");
diff -Nru a/fs/file_table.c b/fs/file_table.c
--- a/fs/file_table.c	Sun Apr 14 12:16:55 2002
+++ b/fs/file_table.c	Sun Apr 14 12:16:55 2002
@@ -169,7 +169,7 @@
 
 	/* Check that no files are currently opened for writing. */
 	file_list_lock();
-	for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
+	list_for_each(p, &sb->s_files) {
 		struct file *file = list_entry(p, struct file, f_list);
 		struct inode *inode = file->f_dentry->d_inode;
 
diff -Nru a/fs/filesystems.c b/fs/filesystems.c
--- a/fs/filesystems.c	Sun Apr 14 12:16:59 2002
+++ b/fs/filesystems.c	Sun Apr 14 12:16:59 2002
@@ -6,10 +6,9 @@
  *  table of configured filesystems
  */
 
-#include <linux/config.h>
+#include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/kmod.h>
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
diff -Nru a/fs/hfs/file.c b/fs/hfs/file.c
--- a/fs/hfs/file.c	Sun Apr 14 12:16:57 2002
+++ b/fs/hfs/file.c	Sun Apr 14 12:16:57 2002
@@ -166,7 +166,6 @@
 	}
 	if ((read = hfs_do_read(inode, HFS_I(inode)->fork, pos, buf, left)) > 0) {
 	        *ppos += read;
-		filp->f_reada = 1;
 	}
 
 	return read;
diff -Nru a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c
--- a/fs/hfs/file_cap.c	Sun Apr 14 12:16:54 2002
+++ b/fs/hfs/file_cap.c	Sun Apr 14 12:16:54 2002
@@ -105,7 +105,6 @@
 	if (offset>=0 && offset<=HFS_FORK_MAX) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
-			file->f_reada = 0;
 		}
 		retval = offset;
 	}
diff -Nru a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c
--- a/fs/hfs/file_hdr.c	Sun Apr 14 12:16:55 2002
+++ b/fs/hfs/file_hdr.c	Sun Apr 14 12:16:55 2002
@@ -58,9 +58,9 @@
 };
 
 const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
-	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	6,					/* entries */
+	magic:		__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
+	version:	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
+	entries:	6,					/* entries */
 	{					/* descr[] */
 		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
 		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
@@ -80,9 +80,9 @@
 };
 
 const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {
-	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	5,					/* entries */
+	magic:		__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
+	version:	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
+	entries:	5,					/* entries */
 	{					/* descr[] */
 		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
 		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
@@ -100,9 +100,9 @@
 };
 
 const struct hfs_hdr_layout hfs_nat2_hdr_layout = {
-	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	9,					/* entries */
+	magic:		__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
+	version:	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
+	entries:	9,					/* entries */
 	{					/* descr[] */
 		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
 		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
@@ -128,9 +128,9 @@
 };
 
 const struct hfs_hdr_layout hfs_nat_hdr_layout = {
-	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
-	__constant_htonl(HFS_HDR_VERSION_1),	/* version */
-	5,					/* entries */
+	magic:		__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
+	version:	__constant_htonl(HFS_HDR_VERSION_1),	/* version */
+	entries:	5,					/* entries */
 	{					/* descr[] */
 		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
 		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
@@ -361,7 +361,6 @@
 	if (offset>=0 && offset<file->f_dentry->d_inode->i_size) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
-			file->f_reada = 0;
 		}
 		retval = offset;
 	}
@@ -594,7 +593,6 @@
 		} else if (fork) {
 			left = hfs_do_read(inode, fork, offset, buf, left);
 			if (left > 0) {
-				filp->f_reada = 1;
 			} else if (!read) {
 				return left;
 			} else {
diff -Nru a/fs/hfs/inode.c b/fs/hfs/inode.c
--- a/fs/hfs/inode.c	Sun Apr 14 12:16:58 2002
+++ b/fs/hfs/inode.c	Sun Apr 14 12:16:58 2002
@@ -117,17 +117,18 @@
 	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
 	struct dentry **de = entry->sys_entry;
 	struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
-	int error, i;
+	int error=0, i;
+
+	lock_kernel();
 
 	error = inode_change_ok(inode, attr); /* basic permission checks */
 	if (error) {
 		/* Let netatalk's afpd think chmod() always succeeds */
 		if (hsb->s_afpd &&
 		    (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) {
-			return 0;
-		} else {
-			return error;
+			error = 0;
 		}
+		goto out; 
 	}
 
 	/* no uig/gid changes and limit which mode bits can be set */
@@ -139,7 +140,10 @@
 	     (((entry->type == HFS_CDR_DIR) &&
 	       (attr->ia_mode != inode->i_mode))||
 	      (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
-		return hsb->s_quiet ? 0 : error;
+		if( hsb->s_quiet ) { 
+			error = 0;
+			goto out;
+		}
 	}
 	
 	if (entry->type == HFS_CDR_DIR) {
@@ -170,9 +174,9 @@
 		}
 	}
 	error = inode_setattr(inode, attr);
-	if (error)
-		return error;
-
+	if (error) 
+		goto out;
+	
 	/* We wouldn't want to mess with the sizes of the other fork */
 	attr->ia_valid &= ~ATTR_SIZE;
 
@@ -204,7 +208,9 @@
 	}
 	/* size changes handled in hfs_extent_adj() */
 
-	return 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
diff -Nru a/fs/hfs/super.c b/fs/hfs/super.c
--- a/fs/hfs/super.c	Sun Apr 14 12:16:57 2002
+++ b/fs/hfs/super.c	Sun Apr 14 12:16:57 2002
@@ -32,6 +32,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
+MODULE_LICENSE("GPL");
+
 /*================ Forward declarations ================*/
 
 static void hfs_read_inode(struct inode *);
@@ -176,9 +178,6 @@
 	/* release the MDB's resources */
 	hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY);
 
-	/* restore default blocksize for the device */
-	set_blocksize(sb->s_dev, BLOCK_SIZE);
-
 	kfree(sb->u.generic_sbp);
 	sb->u.generic_sbp = NULL;
 }
@@ -240,8 +239,9 @@
 	if (!options) {
 		goto done;
 	}
-	for (this_char = strtok(options,","); this_char;
-	     this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL) {
 			*value++ = 0;
 		}
@@ -449,7 +449,6 @@
 	struct hfs_sb_info *sbi;
 	struct hfs_mdb *mdb;
 	struct hfs_cat_key key;
-	kdev_t dev = s->s_dev;
 	hfs_s32 part_size, part_start;
 	struct inode *root_inode;
 	int part;
@@ -462,7 +461,7 @@
 
 	if (!parse_options((char *)data, sbi, &part)) {
 		hfs_warn("hfs_fs: unable to parse mount options.\n");
-		goto bail3;
+		goto bail2;
 	}
 
 	/* set the device driver to 512-byte blocks */
@@ -530,10 +529,8 @@
 bail1:
 	hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
 bail2:
-	set_blocksize(dev, BLOCK_SIZE);
-bail3:
 	kfree(sbi);
-	sb->u.generic_sbp = NULL;
+	s->u.generic_sbp = NULL;
 	return -EINVAL;	
 }
 
diff -Nru a/fs/hpfs/inode.c b/fs/hpfs/inode.c
--- a/fs/hpfs/inode.c	Sun Apr 14 12:16:57 2002
+++ b/fs/hpfs/inode.c	Sun Apr 14 12:16:57 2002
@@ -303,15 +303,18 @@
 int hpfs_notify_change(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
-	int error;
-	if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) 
-		return -EINVAL;
-	if (inode->i_sb->s_hpfs_root == inode->i_ino) return -EINVAL;
-	if ((error = inode_change_ok(inode, attr))) return error;
-	error = inode_setattr(inode, attr);
-	if (error) return error;
-	hpfs_write_inode(inode);
-	return 0;
+	int error=0;
+	lock_kernel();
+	if ( ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) ||
+	     (inode->i_sb->s_hpfs_root == inode->i_ino) ) {
+		error = -EINVAL;
+	} else if ((error = inode_change_ok(inode, attr))) {
+	} else if ((error = inode_setattr(inode, attr))) {
+	} else {
+		hpfs_write_inode(inode);
+	}
+	unlock_kernel();
+	return error;
 }
 
 void hpfs_write_if_changed(struct inode *inode)
diff -Nru a/fs/hpfs/namei.c b/fs/hpfs/namei.c
--- a/fs/hpfs/namei.c	Sun Apr 14 12:16:58 2002
+++ b/fs/hpfs/namei.c	Sun Apr 14 12:16:58 2002
@@ -365,11 +365,9 @@
 			goto ret;
 		}
 		/*printk("HPFS: truncating file before delete.\n");*/
-		down(&inode->i_sem);
 		newattrs.ia_size = 0;
 		newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 		err = notify_change(dentry, &newattrs);
-		up(&inode->i_sem);
 		put_write_access(inode);
 		if (err)
 			goto ret;
diff -Nru a/fs/hpfs/super.c b/fs/hpfs/super.c
--- a/fs/hpfs/super.c	Sun Apr 14 12:16:59 2002
+++ b/fs/hpfs/super.c	Sun Apr 14 12:16:59 2002
@@ -3,7 +3,7 @@
  *
  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  *
- *  mouning, unmounting, error handling
+ *  mounting, unmounting, error handling
  */
 
 #include <linux/string.h>
@@ -222,7 +222,9 @@
 
 	/*printk("Parsing opts: '%s'\n",opts);*/
 
-	for (p = strtok(opts, ","); p != 0; p = strtok(0, ",")) {
+	while ((p = strsep(&opts, ",")) != NULL) {
+		if (!*p)
+			continue;
 		if ((rhs = strchr(p, '=')) != 0)
 			*rhs++ = '\0';
 		if (!strcmp(p, "help")) return 2;
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Sun Apr 14 12:16:58 2002
+++ b/fs/inode.c	Sun Apr 14 12:16:58 2002
@@ -143,6 +143,8 @@
 	INIT_LIST_HEAD(&inode->i_dirty_data_buffers);
 	INIT_LIST_HEAD(&inode->i_devices);
 	sema_init(&inode->i_sem, 1);
+	INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
+	rwlock_init(&inode->i_data.page_lock);
 	spin_lock_init(&inode->i_data.i_shared_lock);
 	INIT_LIST_HEAD(&inode->i_data.i_mmap);
 	INIT_LIST_HEAD(&inode->i_data.i_mmap_shared);
@@ -431,7 +433,7 @@
 	}
 }
 
-static void try_to_sync_unused_inodes(void * arg)
+static void try_to_sync_unused_inodes(unsigned long pexclusive)
 {
 	struct super_block * sb;
 	int nr_inodes = inodes_stat.nr_unused;
@@ -448,10 +450,9 @@
 	}
 	spin_unlock(&sb_lock);
 	spin_unlock(&inode_lock);
+	clear_bit(0, (unsigned long *)pexclusive);
 }
 
-static struct tq_struct unused_inodes_flush_task;
-
 /**
  *	write_inode_now	-	write an inode to disk
  *	@inode: inode to write to disk
@@ -657,10 +658,14 @@
 int invalidate_device(kdev_t dev, int do_sync)
 {
 	struct super_block *sb;
+	struct block_device *bdev = bdget(kdev_t_to_nr(dev));
 	int res;
 
+	if (!bdev)
+		return 0;
+
 	if (do_sync)
-		fsync_dev(dev);
+		fsync_bdev(bdev);
 
 	res = 0;
 	sb = get_super(dev);
@@ -675,7 +680,8 @@
 		res = invalidate_inodes(sb);
 		drop_super(sb);
 	}
-	invalidate_buffers(dev);
+	invalidate_bdev(bdev, 0);
+	bdput(bdev);
 	return res;
 }
 
@@ -739,8 +745,15 @@
 	 * from here or we're either synchronously dogslow
 	 * or we deadlock with oom.
 	 */
-	if (goal)
-		schedule_task(&unused_inodes_flush_task);
+	if (goal) {
+		static unsigned long exclusive;
+
+		if (!test_and_set_bit(0, &exclusive)) {
+			if (pdflush_operation(try_to_sync_unused_inodes,
+						(unsigned long)&exclusive))
+				clear_bit(0, &exclusive);
+		}
+	}
 }
 /*
  * This is called from kswapd when we think we need some
@@ -1166,8 +1179,6 @@
 					 NULL);
 	if (!inode_cachep)
 		panic("cannot create inode slab cache");
-
-	unused_inodes_flush_task.routine = try_to_sync_unused_inodes;
 }
 
 static inline void do_atime_update(struct inode *inode)
@@ -1191,6 +1202,8 @@
  
 void update_atime (struct inode *inode)
 {
+	if (inode->i_atime == CURRENT_TIME)
+		return;
 	if ( IS_NOATIME (inode) ) return;
 	if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return;
 	if ( IS_RDONLY (inode) ) return;
diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
--- a/fs/intermezzo/dir.c	Sun Apr 14 12:16:56 2002
+++ b/fs/intermezzo/dir.c	Sun Apr 14 12:16:56 2002
@@ -282,11 +282,13 @@
         struct presto_file_set *fset;
         struct lento_vfs_context info = { 0, 0, 0 };
 
+	lock_kernel();	
+
         ENTRY;
         error = presto_prep(de, &cache, &fset);
         if ( error ) {
                 EXIT;
-                return error;
+                goto out;        
         }
 
         if (!iattr->ia_valid)
@@ -300,7 +302,8 @@
         
         if ( presto_get_permit(de->d_inode) < 0 ) {
                 EXIT;
-                return -EROFS;
+                error = -EROFS;
+                goto out;
         }
 
         if (!ISLENTO(presto_c2m(cache)))
@@ -308,6 +311,8 @@
 	info.flags |= LENTO_FL_IGNORE_TIME;
         error = presto_do_setattr(fset, de, iattr, &info);
         presto_put_permit(de->d_inode);
+out:
+        unlock_kernel();
         return error;
 }
 
diff -Nru a/fs/intermezzo/super.c b/fs/intermezzo/super.c
--- a/fs/intermezzo/super.c	Sun Apr 14 12:17:00 2002
+++ b/fs/intermezzo/super.c	Sun Apr 14 12:17:00 2002
@@ -120,12 +120,12 @@
         store_opt(prestodev, NULL, PRESTO_PSDEV_NAME "0"); 
 
         CDEBUG(D_SUPER, "parsing options\n");
-        for (this_char = strtok (options, ",");
-             this_char != NULL;
-             this_char = strtok (NULL, ",")) {
+        while ((this_char = strsep (&options, ",")) != NULL) {
                 char *opt;
                 CDEBUG(D_SUPER, "this_char %s\n", this_char);
 
+        	if (!*this_char)
+        		continue;
                 if ( (opt = read_opt("fileset", this_char)) ) {
                         store_opt(fileset, opt, NULL);
                         continue;
diff -Nru a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
--- a/fs/intermezzo/vfs.c	Sun Apr 14 12:16:57 2002
+++ b/fs/intermezzo/vfs.c	Sun Apr 14 12:16:57 2002
@@ -1884,7 +1884,6 @@
 
         f->f_dentry = dentry;
         f->f_pos = 0;
-        f->f_reada = 0;
         f->f_op = NULL;
         if (inode->i_op)
                 /* XXX should we set to presto ops, or leave at cache ops? */
diff -Nru a/fs/iobuf.c b/fs/iobuf.c
--- a/fs/iobuf.c	Sun Apr 14 12:16:56 2002
+++ b/fs/iobuf.c	Sun Apr 14 12:16:56 2002
@@ -28,11 +28,14 @@
 
 static void kiobuf_init(struct kiobuf *iobuf)
 {
-	memset(iobuf, 0, sizeof(*iobuf));
 	init_waitqueue_head(&iobuf->wait_queue);
 	atomic_set(&iobuf->io_count, 0);
 	iobuf->array_len = KIO_STATIC_PAGES;
 	iobuf->maplist   = iobuf->map_array;
+	iobuf->nr_pages   = 0;
+	iobuf->locked   = 0;
+	iobuf->io_count.counter   = 0;
+	iobuf->end_io = NULL;
 }
 
 int alloc_kiovec(int nr, struct kiobuf **bufp)
diff -Nru a/fs/isofs/compress.c b/fs/isofs/compress.c
--- a/fs/isofs/compress.c	Sun Apr 14 12:16:55 2002
+++ b/fs/isofs/compress.c	Sun Apr 14 12:16:55 2002
@@ -330,7 +330,7 @@
 	/* No bmap operation supported */
 };
 
-static int initialized = 0;
+static int initialized;
 
 int __init zisofs_init(void)
 {
diff -Nru a/fs/isofs/inode.c b/fs/isofs/inode.c
--- a/fs/isofs/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/isofs/inode.c	Sun Apr 14 12:16:59 2002
@@ -42,8 +42,8 @@
 #define BEQUIET
 
 #ifdef LEAK_CHECK
-static int check_malloc = 0;
-static int check_bread = 0;
+static int check_malloc;
+static int check_bread;
 #endif
 
 static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
@@ -341,7 +341,9 @@
 	popt->session=-1;
 	popt->sbsector=-1;
 	if (!options) return 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 	        if (strncmp(this_char,"norock",6) == 0) {
 		  popt->rock = 'n';
 		  continue;
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c	Sun Apr 14 12:16:56 2002
+++ b/fs/jbd/journal.c	Sun Apr 14 12:16:56 2002
@@ -267,6 +267,7 @@
 	journal->j_task = NULL;
 	wake_up(&journal->j_wait_done_commit);
 	jbd_debug(1, "Journal thread exiting.\n");
+	unlock_kernel();
 	return 0;
 }
 
@@ -894,7 +895,7 @@
 		__brelse(bh);
 	}
 
-	fsync_dev(to_kdev_t(journal->j_dev->bd_dev));
+	fsync_bdev(journal->j_dev);
 	jbd_debug(1, "JBD: journal cleared.\n");
 
 	/* OK, fill in the initial static fields in the new superblock */
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c	Sun Apr 14 12:16:57 2002
+++ b/fs/jbd/transaction.c	Sun Apr 14 12:16:57 2002
@@ -1661,10 +1661,11 @@
 	struct buffer_head *tmp;
 	int locked_or_dirty = 0;
 	int call_ttfb = 1;
+	int ret;
 
 	J_ASSERT(PageLocked(page));
 
-	bh = page->buffers;
+	bh = page_buffers(page);
 	tmp = bh;
 	spin_lock(&journal_datalist_lock);
 	do {
@@ -1688,7 +1689,10 @@
 	 */
 	call_ttfb = 1;
 out:
-	return call_ttfb;
+	ret = 0;
+	if (call_ttfb)
+		ret = try_to_free_buffers(page, gfp_mask);
+	return ret;
 }
 
 /*
@@ -1881,7 +1885,7 @@
 		
 	if (!PageLocked(page))
 		BUG();
-	if (!page->buffers)
+	if (!page_has_buffers(page))
 		return 1;
 
 	/* We will potentially be playing with lists other than just the
@@ -1889,7 +1893,7 @@
 	 * cautious in our locking. */
 	lock_journal(journal);
 
-	head = bh = page->buffers;
+	head = bh = page_buffers(page);
 	do {
 		unsigned int next_off = curr_off + bh->b_size;
 		next = bh->b_this_page;
@@ -1911,7 +1915,7 @@
 	if (!offset) {
 		if (!may_free || !try_to_free_buffers(page, 0))
 			return 0;
-		J_ASSERT(page->buffers == NULL);
+		J_ASSERT(!page_has_buffers(page));
 	}
 	return 1;
 }
diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
--- a/fs/jffs/inode-v23.c	Sun Apr 14 12:16:55 2002
+++ b/fs/jffs/inode-v23.c	Sun Apr 14 12:16:55 2002
@@ -196,11 +196,13 @@
 	struct jffs_file *f;
 	struct jffs_node *new_node;
 	int update_all;
-	int res;
+	int res = 0;
 	int recoverable = 0;
 
-	if ((res = inode_change_ok(inode, iattr)))
-		return res;
+	lock_kernel();
+
+	if ((res = inode_change_ok(inode, iattr))) 
+		goto out;
 
 	c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
 	fmc = c->fmc;
@@ -215,7 +217,8 @@
 		       inode->i_ino);
 		D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
 		up(&fmc->biglock);
-		return -EINVAL;
+		res = -EINVAL;
+		goto out;
 	});
 
 	D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
@@ -235,7 +238,8 @@
 		D(printk("jffs_setattr(): Allocation failed!\n"));
 		D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
 		up(&fmc->biglock);
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto out;
 	}
 
 	new_node->data_offset = 0;
@@ -321,7 +325,7 @@
 		jffs_free_node(new_node);
 		D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
 		up(&c->fmc->biglock);
-		return res;
+		goto out;
 	}
 
 	jffs_insert_node(c, f, &raw_inode, 0, new_node);
@@ -329,7 +333,9 @@
 	mark_inode_dirty(inode);
 	D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
 	up(&c->fmc->biglock);
-	return 0;
+out:
+	unlock_kernel();
+	return res;
 } /* jffs_notify_change()  */
 
 
diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c
--- a/fs/jffs2/file.c	Sun Apr 14 12:16:58 2002
+++ b/fs/jffs2/file.c	Sun Apr 14 12:16:58 2002
@@ -43,6 +43,7 @@
 #include <linux/pagemap.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
+#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
@@ -109,11 +110,12 @@
 	int mdatalen = 0;
 	unsigned int ivalid;
 	uint32_t phys_ofs, alloclen;
-	int ret;
+	int ret = 0;
+	lock_kernel();
 	D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
 	ret = inode_change_ok(inode, iattr);
 	if (ret) 
-		return ret;
+		goto out;
 
 	/* Special cases - we don't want more than one data node
 	   for these types on the medium at any time. So setattr
@@ -130,12 +132,14 @@
 	} else if (S_ISLNK(inode->i_mode)) {
 		mdatalen = f->metadata->size;
 		mdata = kmalloc(f->metadata->size, GFP_USER);
-		if (!mdata)
-			return -ENOMEM;
+		if (!mdata) {
+			ret = -ENOMEM;
+			goto out;
+		}
 		ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen);
 		if (ret) {
 			kfree(mdata);
-			return ret;
+			goto out;
 		}
 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
 	}
@@ -144,7 +148,8 @@
 	if (!ri) {
 		if (S_ISLNK(inode->i_mode))
 			kfree(mdata);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out;
 	}
 		
 	ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL);
@@ -152,7 +157,7 @@
 		jffs2_free_raw_inode(ri);
 		if (S_ISLNK(inode->i_mode & S_IFMT))
 			 kfree(mdata);
-		return ret;
+		goto out;
 	}
 	down(&f->sem);
 	ivalid = iattr->ia_valid;
@@ -201,7 +206,8 @@
 		jffs2_complete_reservation(c);
 		jffs2_free_raw_inode(ri);
 		up(&f->sem);
-		return PTR_ERR(new_metadata);
+		ret = PTR_ERR(new_metadata);
+		goto out;
 	}
 	/* It worked. Update the inode */
 	inode->i_atime = ri->atime;
@@ -235,7 +241,9 @@
 	up(&f->sem);
 	jffs2_complete_reservation(c);
 
-	return 0;
+out:
+	unlock_kernel();	
+	return ret;
 }
 
 int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c
--- a/fs/jffs2/super.c	Sun Apr 14 12:16:57 2002
+++ b/fs/jffs2/super.c	Sun Apr 14 12:16:57 2002
@@ -94,12 +94,12 @@
 
 static int jffs2_sb_compare(struct super_block *sb, void *data)
 {
-	struct mtd_info *mtd = data;
+	struct jffs2_sb_info *p = data;
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
 
 	/* The superblocks are considered to be equivalent if the underlying MTD
 	   device is the same one */
-	if (c->mtd == mtd) {
+	if (c->mtd == p->mtd) {
 		D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", mtd->index, mtd->name));
 		return 1;
 	} else {
@@ -111,12 +111,14 @@
 
 static int jffs2_sb_set(struct super_block *sb, void *data)
 {
-	struct mtd_info *mtd = data;
+	struct jffs2_sb_info *p = data;
 
 	/* For persistence of NFS exports etc. we use the same s_dev
 	   each time we mount the device, don't just use an anonymous
 	   device */
-	sb->s_dev = mk_kdev(MTD_BLOCK_MAJOR, mtd->index);
+	sb->u.generic_sbp = p;
+	p->os_priv = sb;
+	sb->s_dev = mk_kdev(MTD_BLOCK_MAJOR, p->mtd->index);
 
 	return 0;
 }
@@ -129,7 +131,13 @@
 	struct jffs2_sb_info *c;
 	int ret;
 
-	sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, mtd);
+	c = kmalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+	memset(c, 0, sizeof(*c));
+	c->mtd = mtd;
+
+	sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
 
 	if (IS_ERR(sb))
 		goto out_put;
@@ -144,19 +152,8 @@
 	D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n",
 		  mtd->index, mtd->name));
 
-	c = kmalloc(sizeof(*c), GFP_KERNEL);
-	if (!c) {
-		sb = ERR_PTR(-ENOMEM);
-		goto out_put;
-	}
-
-	sb->u.generic_sbp = c;
 	sb->s_op = &jffs2_super_operations;
 
-	memset(c, 0, sizeof(*c));
-	c->os_priv = sb;
-	c->mtd = mtd;
-
 	ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0);
 
 	if (ret) {
@@ -164,13 +161,15 @@
 		up_write(&sb->s_umount);
 		deactivate_super(sb);
 		sb = ERR_PTR(ret);
-		goto out_put;
+		goto out_put1;
 	}
 
 	sb->s_flags |= MS_ACTIVE;
 	return sb;
 
  out_put:
+	kfree(c);
+ out_put1:
 	put_mtd_device(mtd);
 
 	return sb;
@@ -288,18 +287,23 @@
 	kfree(c->blocks);
 	if (c->mtd->sync)
 		c->mtd->sync(c->mtd);
-	put_mtd_device(c->mtd);
-
-	kfree(c);
 
 	D1(printk(KERN_DEBUG "jffs2_put_super returning\n"));
 }
+
+static void jffs2_kill_sb(struct super_block *sb)
+{
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+	generic_shutdown_super(sb);
+	put_mtd_device(c->mtd);
+	kfree(c);
+}
  
 static struct file_system_type jffs2_fs_type = {
 	owner:		THIS_MODULE,
 	name:		"jffs2",
 	get_sb:		jffs2_get_sb,
-	kill_sb:	generic_shutdown_super
+	kill_sb:	jffs2_kill_sb,
 };
 
 
diff -Nru a/fs/jfs/endian24.h b/fs/jfs/endian24.h
--- a/fs/jfs/endian24.h	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/endian24.h	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,12 +15,11 @@
  *   along with this program;  if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-
 #ifndef _H_ENDIAN24
 #define	_H_ENDIAN24
 
 /*
- *	fs/jfs/endian24.h:
+ *	endian24.h:
  *
  * Endian conversion for 24-byte data
  *
diff -Nru a/fs/jfs/file.c b/fs/jfs/file.c
--- a/fs/jfs/file.c	Sun Apr 14 12:16:57 2002
+++ b/fs/jfs/file.c	Sun Apr 14 12:16:57 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	Sun Apr 14 12:16:54 2002
+++ b/fs/jfs/inode.c	Sun Apr 14 12:16:54 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -19,7 +18,6 @@
 
 #include <linux/fs.h>
 #include <linux/locks.h>
-#include <linux/slab.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
diff -Nru a/fs/jfs/jfs_btree.h b/fs/jfs/jfs_btree.h
--- a/fs/jfs/jfs_btree.h	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_btree.h	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,10 +14,10 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
  */
 #ifndef	_H_JFS_BTREE
 #define _H_JFS_BTREE
+
 /*
  *	jfs_btree.h: B+-tree
  *
diff -Nru a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
--- a/fs/jfs/jfs_debug.c	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_debug.c	Sun Apr 14 12:16:56 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -16,6 +15,7 @@
  *   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/fs.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
diff -Nru a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
--- a/fs/jfs/jfs_debug.h	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_debug.h	Sun Apr 14 12:16:56 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,8 +14,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
+ */
 #ifndef _H_JFS_DEBUG
 #define _H_JFS_DEBUG
 
diff -Nru a/fs/jfs/jfs_defragfs.h b/fs/jfs/jfs_defragfs.h
--- a/fs/jfs/jfs_defragfs.h	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_defragfs.h	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,14 +14,10 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
  */
 #ifndef	_H_JFS_DEFRAGFS
 #define _H_JFS_DEFRAGFS
 
-/*
- *	jfs_defragfs.h
- */
 /*
  *	defragfs parameter list
  */
diff -Nru a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h
--- a/fs/jfs/jfs_dinode.h	Sun Apr 14 12:16:57 2002
+++ b/fs/jfs/jfs_dinode.h	Sun Apr 14 12:16:57 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,15 +14,12 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
  */
-
 #ifndef _H_JFS_DINODE
 #define _H_JFS_DINODE
 
 /*
  *      jfs_dinode.h: on-disk inode manager
- *
  */
 
 #define INODESLOTSIZE           128
diff -Nru a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
--- a/fs/jfs/jfs_dmap.c	Sun Apr 14 12:16:57 2002
+++ b/fs/jfs/jfs_dmap.c	Sun Apr 14 12:16:57 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,23 +14,9 @@
  *   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
- *
- *
- *   MODULE_NAME:		jfs_dmap.c
- *
- *   COMPONENT_NAME: 	sysjfs
- *
- *   FUNCTION:			block allocation map manager
- *
-*/
-
-/*
- * Change History :
- *
  */
 
 #include <linux/fs.h>
-#include <linux/slab.h>
 #include "jfs_incore.h"
 #include "jfs_dmap.h"
 #include "jfs_imap.h"
diff -Nru a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
--- a/fs/jfs/jfs_dmap.h	Sun Apr 14 12:16:59 2002
+++ b/fs/jfs/jfs_dmap.h	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,10 +14,7 @@
  *   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
- *
- *	jfs_dmap.h: block allocation map manager
  */
-
 #ifndef	_H_JFS_DMAP
 #define _H_JFS_DMAP
 
diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_dtree.c	Sun Apr 14 12:16:56 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,9 +14,7 @@
  *   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
- *
- * 
-*/
+ */
 
 /*
  *	jfs_dtree.c: directory B+-tree manager
@@ -104,7 +101,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/slab.h>
 #include <linux/locks.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
@@ -3045,6 +3041,14 @@
 				t = (dtslot_t *) & p->slot[next];
 				name_ptr += outlen;
 				d_namleft -= len;
+				/* Sanity Check */
+				if (d_namleft == 0) {
+					jERROR(1,("JFS:Dtree error: "
+					  "ino = %ld, bn=%Ld, index = %d\n",
+						  ip->i_ino, bn, i));
+					updateSuper(ip->i_sb, FM_DIRTY);
+					goto skip_one;
+				}
 				len = min(d_namleft, DTSLOTDATALEN);
 				outlen = jfs_strfromUCS_le(name_ptr, t->name,
 							   len, codepage);
@@ -3056,6 +3060,7 @@
 			if (filldir(dirent, d_name, d_namlen, filp->f_pos,
 				    le32_to_cpu(d->inumber), DT_UNKNOWN))
 				goto out;
+skip_one:
 			if (!do_index)
 				dtoffset->index++;
 		}
@@ -3352,9 +3357,8 @@
 		     dtpage_t * p,	/* directory page */
 		     int si)
 {				/* entry slot index */
-	register int rc;
-	register wchar_t *kname, *name;
-	register int klen, namlen, len;
+	wchar_t *kname, *name;
+	int klen, namlen, len, rc;
 	idtentry_t *ih;
 	dtslot_t *t;
 
@@ -3429,9 +3433,8 @@
 		     int si,	/* entry slot index */
 		     int flag)
 {
-	register int rc;
-	register wchar_t *kname, *name, x;
-	register int klen, namlen, len;
+	wchar_t *kname, *name, x;
+	int klen, namlen, len, rc;
 	ldtentry_t *lh;
 	idtentry_t *ih;
 	dtslot_t *t;
@@ -3535,8 +3538,8 @@
 static void ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
 			       int ri, component_t * key, int flag)
 {
-	register int klen, namlen;
-	register wchar_t *pl, *pr, *kname;
+	int klen, namlen;
+	wchar_t *pl, *pr, *kname;
 	wchar_t lname[JFS_NAME_MAX + 1];
 	component_t lkey = { 0, lname };
 	wchar_t rname[JFS_NAME_MAX + 1];
diff -Nru a/fs/jfs/jfs_dtree.h b/fs/jfs/jfs_dtree.h
--- a/fs/jfs/jfs_dtree.h	Sun Apr 14 12:16:59 2002
+++ b/fs/jfs/jfs_dtree.h	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,12 +15,6 @@
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-
-/*
- * Change History :
- *
- */
-
 #ifndef _H_JFS_DTREE
 #define	_H_JFS_DTREE
 
diff -Nru a/fs/jfs/jfs_extendfs.h b/fs/jfs/jfs_extendfs.h
--- a/fs/jfs/jfs_extendfs.h	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_extendfs.h	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -18,9 +18,6 @@
 #ifndef	_H_JFS_EXTENDFS
 #define _H_JFS_EXTENDFS
 
-/*
- *	jfs_extendfs.h
- */
 /*
  *	extendfs parameter list
  */
diff -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
--- a/fs/jfs/jfs_extent.c	Sun Apr 14 12:16:54 2002
+++ b/fs/jfs/jfs_extent.c	Sun Apr 14 12:16:54 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,10 +14,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- *
- * Module: jfs_extent.c:
  */
 
 #include <linux/fs.h>
diff -Nru a/fs/jfs/jfs_extent.h b/fs/jfs/jfs_extent.h
--- a/fs/jfs/jfs_extent.h	Sun Apr 14 12:16:58 2002
+++ b/fs/jfs/jfs_extent.h	Sun Apr 14 12:16:58 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
--- a/fs/jfs/jfs_filsys.h	Sun Apr 14 12:16:58 2002
+++ b/fs/jfs/jfs_filsys.h	Sun Apr 14 12:16:58 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,9 +14,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
-
+ */
 #ifndef _H_JFS_FILSYS
 #define _H_JFS_FILSYS
 
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_imap.c	Sun Apr 14 12:16:56 2002
@@ -1,7 +1,5 @@
 /*
-
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -16,12 +14,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/*
- * Change History :
- *
  */
 
 /*
@@ -50,7 +42,6 @@
  */
 
 #include <linux/fs.h>
-#include <linux/slab.h>
 #include <linux/locks.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
diff -Nru a/fs/jfs/jfs_imap.h b/fs/jfs/jfs_imap.h
--- a/fs/jfs/jfs_imap.h	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_imap.h	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
--- a/fs/jfs/jfs_incore.h	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_incore.h	Sun Apr 14 12:16:55 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,8 +14,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/ 
+ */ 
 #ifndef _H_JFS_INCORE
 #define _H_JFS_INCORE
 
@@ -123,7 +121,7 @@
 	short		nbperpage;	/* 2: blocks per page		*/
 	short		l2nbperpage;	/* 2: log2 blocks per page	*/
 	short		l2niperblk;	/* 2: log2 inodes per page	*/
-	short		reserved;	/* 2: log2 inodes per page	*/
+	kdev_t		logdev;		/* 2: external log device	*/
 	pxd_t		logpxd;		/* 8: pxd describing log	*/
 	pxd_t		ait2;		/* 8: pxd describing AIT copy	*/
 	/* Formerly in ipimap */
diff -Nru a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
--- a/fs/jfs/jfs_inode.c	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_inode.c	Sun Apr 14 12:16:55 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
--- a/fs/jfs/jfs_inode.h	Sun Apr 14 12:16:54 2002
+++ b/fs/jfs/jfs_inode.h	Sun Apr 14 12:16:54 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/jfs_lock.h b/fs/jfs/jfs_lock.h
--- a/fs/jfs/jfs_lock.h	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_lock.h	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2001
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	Sun Apr 14 12:16:59 2002
+++ b/fs/jfs/jfs_logmgr.c	Sun Apr 14 12:16:59 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,8 +14,7 @@
  *   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
- *
-*/
+ */
 
 /*
  *	jfs_logmgr.c: log manager
@@ -62,10 +60,10 @@
 
 #include <linux/fs.h>
 #include <linux/locks.h>
-#include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/completion.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -159,7 +157,6 @@
 /*
  * external references
  */
-extern void vPut(struct inode *ip);
 extern void txLazyUnlock(tblock_t * tblk);
 extern int jfs_thread_stopped(void);
 extern struct task_struct *jfsIOtask;
@@ -172,6 +169,7 @@
 			 tlock_t * tlck);
 
 static int lmNextPage(log_t * log);
+static int lmLogFileSystem(log_t * log, kdev_t fsdev, int activate);
 static int lmLogInit(log_t * log);
 static int lmLogShutdown(log_t * log);
 
@@ -185,9 +183,7 @@
 static void lbmDirectWrite(log_t * log, lbuf_t * bp, int flag);
 static int lbmIOWait(lbuf_t * bp, int flag);
 static bio_end_io_t lbmIODone;
-#ifdef _STILL_TO_PORT
-static void lbmDirectIODone(iobuf_t * ddbp);
-#endif				/* _STILL_TO_PORT */
+
 void lbmStartIO(lbuf_t * bp);
 void lmGCwrite(log_t * log, int cant_block);
 
@@ -1059,46 +1055,36 @@
 int lmLogOpen(struct super_block *sb, log_t ** logptr)
 {
 	int rc;
-	kdev_t logdev;		/* dev_t of log device */
+	struct block_device *bdev;
 	log_t *log;
 
-	logdev = sb->s_dev;
+	if (!(log = kmalloc(sizeof(log_t), GFP_KERNEL)))
+		return ENOMEM;
+	memset(log, 0, sizeof(log_t));
 
-#ifdef _STILL_TO_PORT
-	/*
-	 * open the inode representing the log device (aka log inode)
-	 */
-	if (logdev != fsdev)
+	if (!(JFS_SBI(sb)->mntflag & JFS_INLINELOG))
 		goto externalLog;
-#endif				/* _STILL_TO_PORT */
 
 	/*
 	 *      in-line log in host file system
 	 *
 	 * file system to log have 1-to-1 relationship;
 	 */
-//    inlineLog:
 
-	*logptr = log = kmalloc(sizeof(log_t), GFP_KERNEL);
-	if (log == 0)
-		return ENOMEM;
-
-	memset(log, 0, sizeof(log_t));
 	log->sb = sb;		/* This should be a list */
 	log->flag = JFS_INLINELOG;
-	log->dev = logdev;
+	log->dev = sb->s_dev;
 	log->base = addressPXD(&JFS_SBI(sb)->logpxd);
 	log->size = lengthPXD(&JFS_SBI(sb)->logpxd) >>
 	    (L2LOGPSIZE - sb->s_blocksize_bits);
 	log->l2bsize = sb->s_blocksize_bits;
 	ASSERT(L2LOGPSIZE >= sb->s_blocksize_bits);
+
 	/*
 	 * initialize log.
 	 */
 	if ((rc = lmLogInit(log)))
 		goto errout10;
-
-#ifdef _STILL_TO_PORT
 	goto out;
 
 	/*
@@ -1107,103 +1093,47 @@
 	 * file systems to log may have n-to-1 relationship;
 	 */
       externalLog:
-	/*
-	 * open log inode
-	 *
-	 * log inode is reserved inode of (dev_t = log device,
-	 * fileset number = 0, i_number = 0), which acquire
-	 * one i_count for each open by file system.
-	 *
-	 * hand craft dummy vfs to force iget() the special case of
-	 * an in-memory inode allocation without on-disk inode
-	 */
-	memset(&dummyvfs, 0, sizeof(struct vfs));
-	dummyvfs.filesetvfs.vfs_data = NULL;
-	dummyvfs.dummyvfs.dev = logdev;
-	dummyvfs.dummyvfs.ipmnt = NULL;
-	ICACHE_LOCK();
-	rc = iget((struct vfs *) &dummyvfs, 0, (inode_t **) & log, 0);
-	ICACHE_UNLOCK();
-	if (rc)
-		return rc;
-
-	log->flag = 0;
-	log->dev = logdev;
-	log->base = 0;
-	log->size = 0;
-
-	/*
-	 * serialize open/close between multiple file systems
-	 * bound with the log;
-	 */
-	ip = (inode_t *) log;
-	IWRITE_LOCK(ip);
-
-	/*
-	 * subsequent open: add file system to log active file system list
-	 */
-#ifdef	_JFS_OS2
-	if (log->strat2p)
-#endif				/* _JFS_OS2 */
-	{
-		if (rc = lmLogFileSystem(log, fsdev, 1))
-			goto errout10;
-
-		IWRITE_UNLOCK(ip);
-
-		*iplog = ip;
-		jFYI(1, ("lmLogOpen: exit(0)\n"));
-		return 0;
+	if (!(bdev = bdget(kdev_t_to_nr(JFS_SBI(sb)->logdev)))) {
+		rc = ENODEV;
+		goto errout10;
 	}
 
-	/* decouple log inode from dummy vfs */
-	vPut(ip);
-
-	/*
-	 * first open:
-	 */
-#ifdef	_JFS_OS2
-	/*
-	 * establish access to the single/shared (already open) log device
-	 */
-	logdevfp = (void *) logStrat2;
-	log->strat2p = logStrat2;
-	log->strat3p = logStrat3;
-
-	log->l2pbsize = 9;	/* todo: when OS/2 have multiple external log */
-#endif				/* _JFS_OS2 */
+	if ((rc = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS))) {
+		rc = -rc;
+		goto errout10;
+	}
 
+	log->sb = sb;		/* This should be a list */
+	log->dev = JFS_SBI(sb)->logdev;
+	log->bdev = bdev;
+	
 	/*
 	 * initialize log:
 	 */
-	if (rc = lmLogInit(log))
+	if ((rc = lmLogInit(log)))
 		goto errout20;
 
 	/*
 	 * add file system to log active file system list
 	 */
-	if (rc = lmLogFileSystem(log, fsdev, 1))
+	if ((rc = lmLogFileSystem(log, sb->s_dev, 1)))
 		goto errout30;
 
-	/*
-	 *      insert log device into log device list
-	 */
       out:
-#endif				/*  _STILL_TO_PORT */
 	jFYI(1, ("lmLogOpen: exit(0)\n"));
+	*logptr = log;
 	return 0;
 
 	/*
 	 *      unwind on error
 	 */
-#ifdef _STILL_TO_PORT
       errout30:		/* unwind lbmLogInit() */
 	lbmLogShutdown(log);
 
       errout20:		/* close external log device */
+	blkdev_put(bdev, BDEV_FS);
 
-#endif				/* _STILL_TO_PORT */
-      errout10:		/* free log inode */
+      errout10:		/* free log descriptor */
 	kfree(log);
 
 	jFYI(1, ("lmLogOpen: exit(%d)\n", rc));
@@ -1255,6 +1185,10 @@
 	/*
 	 * validate log superblock
 	 */
+
+
+	if (!(log->flag & JFS_INLINELOG))
+		log->l2bsize = 12;	/* XXX kludge alert XXX */
 	if ((rc = lbmRead(log, 1, &bpsuper)))
 		goto errout10;
 
@@ -1284,6 +1218,7 @@
 		      log, (unsigned long long) log->base, log->size));
 	} else {
 		log->size = le32_to_cpu(logsuper->size);
+		log->l2bsize = le32_to_cpu(logsuper->l2bsize);
 		jFYI(0,
 		     ("lmLogInit: external log:0x%p base:0x%Lx size:0x%x\n",
 		      log, (unsigned long long) log->base, log->size));
@@ -1378,6 +1313,7 @@
 	logsuper->state = cpu_to_le32(LOGMOUNT);
 	log->serial = le32_to_cpu(logsuper->serial) + 1;
 	logsuper->serial = cpu_to_le32(log->serial);
+	logsuper->device = cpu_to_le32(kdev_t_to_nr(log->dev));
 	lbmDirectWrite(log, bpsuper, lbmWRITE | lbmRELEASE | lbmSYNC);
 	if ((rc = lbmIOWait(bpsuper, lbmFREE)))
 		goto errout30;
@@ -1421,47 +1357,24 @@
 
 	jFYI(1, ("lmLogClose: log:0x%p\n", log));
 
+	if (!(log->flag & JFS_INLINELOG))
+		goto externalLog;
+	
 	/*
 	 *      in-line log in host file system
 	 */
-//      inlineLog:
-#ifdef _STILL_TO_PORT
-	if (log->flag & JFS_INLINELOG) {
-		rc = lmLogShutdown(log);
-
-		goto out1;
-	}
+	rc = lmLogShutdown(log);
+	goto out;
 
 	/*
 	 *      external log as separate logical volume
 	 */
       externalLog:
-
-	/* serialize open/close between multiple file systems
-	 * associated with the log
-	 */
-	IWRITE_LOCK(iplog);
-
-	/*
-	 * remove file system from log active file system list
-	 */
-	rc = lmLogFileSystem(log, fsdev, 0);
-
-	if (iplog->i_count > 1)
-		goto out2;
-
-	/*
-	 *      last close: shut down log
-	 */
-	rc = ((rc1 = lmLogShutdown(log)) && rc == 0) ? rc1 : rc;
-
-      out1:
-#else				/* _STILL_TO_PORT */
+	lmLogFileSystem(log, sb->s_dev, 0);
 	rc = lmLogShutdown(log);
-#endif				/* _STILL_TO_PORT */
-
-//      out2:
+	blkdev_put(log->bdev, BDEV_FS);
 
+      out:
 	jFYI(0, ("lmLogClose: exit(%d)\n", rc));
 	return rc;
 }
@@ -1563,7 +1476,6 @@
 }
 
 
-#ifdef _STILL_TO_PORT
 /*
  * NAME:	lmLogFileSystem()
  *
@@ -1571,7 +1483,7 @@
  *	file system into/from log active file system list.
  *
  * PARAMETE:	log	- pointer to logs inode.
- *		fsdev	- dev_t of filesystem.
+ *		fsdev	- kdev_t of filesystem.
  *		serial  - pointer to returned log serial number
  *		activate - insert/remove device from active list.
  *
@@ -1580,10 +1492,11 @@
  *			
  * serialization: IWRITE_LOCK(log inode) held on entry/exit
  */
-static int lmLogFileSystem(log_t * log, dev_t fsdev, int activate)
+static int lmLogFileSystem(log_t * log, kdev_t fsdev, int activate)
 {
 	int rc = 0;
-	int bit, word;
+	int i;
+	u32 dev_le = cpu_to_le32(kdev_t_to_nr(fsdev));
 	logsuper_t *logsuper;
 	lbuf_t *bpsuper;
 
@@ -1594,15 +1507,25 @@
 		return rc;
 
 	logsuper = (logsuper_t *) bpsuper->l_ldata;
-	bit = MINOR(fsdev);
-	word = bit / 32;
-	bit -= 32 * word;
-	if (activate)
-		logsuper->active[word] |=
-		    cpu_to_le32((LEFTMOSTONE >> bit));
-	else
-		logsuper->active[word] &=
-		    cpu_to_le32((~(LEFTMOSTONE >> bit)));
+	if (activate) {
+		for (i = 0; i < MAX_ACTIVE; i++)
+			if (logsuper->active[i] == 0) {
+				logsuper->active[i] = dev_le;
+				break;
+			}
+		if (i == MAX_ACTIVE) {
+			jERROR(1,("Too many file systems sharing journal!\n"));
+			lbmFree(bpsuper);
+			return EMFILE;	/* Is there a better rc? */
+		}
+	} else {
+		for (i = 0; i < MAX_ACTIVE; i++)
+			if (logsuper->active[i] == dev_le) {
+				logsuper->active[i] = 0;
+				break;
+			}
+		assert(i < MAX_ACTIVE);
+	}
 
 	/*
 	 * synchronous write log superblock:
@@ -1620,7 +1543,6 @@
 
 	return rc;
 }
-#endif				/* _STILL_TO_PORT */
 
 
 /*
@@ -1810,42 +1732,6 @@
 }
 
 
-#ifdef _THIS_IS_NOT_USED
-/*
- *	lbmRelease()
- *
- * remove the log buffer from log device write queue;
- */
-static void lbmRelease(log_t * log, uint flag)
-{
-	lbuf_t *bp, *tail;
-	unsigned long flags;
-
-	bp = log->bp;
-
-	LCACHE_LOCK(flags);
-
-	tail = log->wqueue;
-
-	/* single element queue */
-	if (bp == tail) {
-		log->wqueue = NULL;
-		bp->l_wqnext = NULL;
-	}
-	/* multi element queue */
-	else {
-		tail->l_wqnext = bp->l_wqnext;
-		bp->l_wqnext = NULL;
-	}
-
-	if (flag & lbmFREE)
-		lbmfree(bp);
-
-	LCACHE_UNLOCK(flags);
-}
-#endif				/* _THIS_IS_NOT_USED */
-
-
 /*
  * NAME:	lbmRedrive
  *
@@ -2271,63 +2157,6 @@
 	return 0;
 }
 
-
-#ifdef _STILL_TO_PORT
-/*
- *	lbmDirectIODone()
- *
- * iodone() for lbmDirectWrite() to bypass write queue;
- * executed at INTIODONE level;
- */
-static void lbmDirectIODone(iobuf_t * iobp)
-{
-	lbuf_t *bp;
-	unsigned long flags;
-
-	/*
-	 * get back jfs buffer bound to the io buffer
-	 */
-	bp = (lbuf_t *) iobp->b_jfsbp;
-	jEVENT(0,
-	       ("lbmDirectIODone: bp:0x%p flag:0x%x\n", bp, bp->l_flag));
-
-	LCACHE_LOCK(flags);		/* disable+lock */
-
-	bp->l_flag |= lbmDONE;
-
-	if (iobp->b_flags & B_ERROR) {
-		bp->l_flag |= lbmERROR;
-#ifdef _JFS_OS2
-		SysLogError();
-#endif
-	}
-
-	/*
-	 *      pageout completion
-	 */
-	bp->l_flag &= ~lbmWRITE;
-
-	/*
-	 *      synchronous pageout:
-	 */
-	if (bp->l_flag & lbmSYNC) {
-		LCACHE_UNLOCK(flags);	/* unlock+enable */
-
-		/* wakeup I/O initiator */
-		LCACHE_WAKEUP(&bp->l_ioevent);
-	}
-	/*
-	 *      asynchronous pageout:
-	 */
-	else {
-		assert(bp->l_flag & lbmRELEASE);
-		assert(bp->l_flag & lbmFREE);
-		lbmfree(bp);
-
-		LCACHE_UNLOCK(flags);	/* unlock+enable */
-	}
-}
-#endif				/* _STILL_TO_PORT */
 
 #ifdef _STILL_TO_PORT
 /*
diff -Nru a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
--- a/fs/jfs/jfs_logmgr.h	Sun Apr 14 12:16:57 2002
+++ b/fs/jfs/jfs_logmgr.h	Sun Apr 14 12:16:57 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,11 +15,9 @@
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-
 #ifndef	_H_JFS_LOGMGR
 #define _H_JFS_LOGMGR
 
-
 #include "jfs_filsys.h"
 #include "jfs_lock.h"
 
@@ -60,6 +58,8 @@
 #define	LOGMAGIC	0x87654321
 #define	LOGVERSION	1
 
+#define MAX_ACTIVE	512	/* Max active file systems sharing log */
+
 typedef struct {
 	u32 magic;		/* 4: log lv identifier */
 	s32 version;		/* 4: version number */
@@ -72,8 +72,8 @@
 	u32 state;		/* 4: state - see below */
 
 	s32 end;		/* 4: addr of last log record set by logredo */
-	u32 active[8];		/* 32: active file systems bit vector */
-	s32 rsrvd[LOGPSIZE / 4 - 17];
+	u32 device;		/* 4: save device in case location changes */
+	u32 active[MAX_ACTIVE];	/* 2048: active file systems list */
 } logsuper_t;
 
 /* log flag: commit option (see jfs_filsys.h) */
@@ -200,7 +200,7 @@
 	s32 backchain;		/* 4: ptr to prev record of same transaction */
 	u16 type;		/* 2: record type */
 	s16 length;		/* 2: length of data in record (in byte) */
-	s32 aggregate;		/* 4: file system lv/aggregate */
+	u32 aggregate;		/* 4: file system lv/aggregate */
 	/* (16) */
 
 	/*
@@ -367,7 +367,7 @@
 				 *    the log between fs's
 				 */
 	kdev_t dev;		/* 4: log lv number */
-	struct file *devfp;	/* 4: log device file */
+	struct block_device *bdev; /* 4: log lv pointer */
 	s32 serial;		/* 4: log mount serial number */
 
 	s64 base;		/* @8: log extent address (inline log ) */
diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
--- a/fs/jfs/jfs_metapage.c	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_metapage.c	Sun Apr 14 12:16:56 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,9 +14,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Module: jfs/jfs_metapage.c
- *
  */
 
 #include <linux/fs.h>
@@ -511,10 +507,26 @@
 	jFYI(1, ("__write_metapage done\n"));
 }
 
+static inline void sync_metapage(metapage_t *mp)
+{
+	struct page *page = mp->page;
+
+	page_cache_get(page);
+	lock_page(page);
+
+	/* we're done with this page - no need to check for errors */
+	if (page->buffers) {
+		writeout_one_page(page);
+		waitfor_one_page(page);
+	}
+
+	UnlockPage(page);
+	page_cache_release(page);
+}
+
 void release_metapage(metapage_t * mp)
 {
 	log_t *log;
-	struct inode *ip;
 
 	jFYI(1,
 	     ("release_metapage: mp = 0x%p, flag = 0x%lx\n", mp,
@@ -527,8 +539,6 @@
 		spin_unlock(&meta_lock);
 		return;
 	}
-
-	ip = (struct inode *) mp->mapping->host;
 
 	assert(mp->count);
 	if (--mp->count || atomic_read(&mp->nohomeok)) {
diff -Nru a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
--- a/fs/jfs/jfs_metapage.h	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_metapage.h	Sun Apr 14 12:16:55 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -84,32 +84,26 @@
 	 __get_metapage(inode, lblock, size, absolute, TRUE)
 
 extern void release_metapage(metapage_t *);
+extern void hold_metapage(metapage_t *, int);
 
-#define flush_metapage(mp) \
-{\
-	set_bit(META_dirty, &(mp)->flag);\
-	set_bit(META_sync, &(mp)->flag);\
-	release_metapage(mp);\
+static inline void write_metapage(metapage_t *mp)
+{
+	set_bit(META_dirty, &mp->flag);
+	release_metapage(mp);
 }
 
-#define sync_metapage(mp) \
-	generic_buffer_fdatasync((struct inode *)mp->mapping->host,\
-				 mp->page->index, mp->page->index + 1)
-
-#define write_metapage(mp) \
-{\
-	set_bit(META_dirty, &(mp)->flag);\
-	release_metapage(mp);\
+static inline void flush_metapage(metapage_t *mp)
+{
+	set_bit(META_sync, &mp->flag);
+	write_metapage(mp);
 }
 
-#define discard_metapage(mp) \
-{\
-	clear_bit(META_dirty, &(mp)->flag);\
-	set_bit(META_discard, &(mp)->flag);\
-	release_metapage(mp);\
+static inline void discard_metapage(metapage_t *mp)
+{
+	clear_bit(META_dirty, &mp->flag);
+	set_bit(META_discard, &mp->flag);
+	release_metapage(mp);
 }
-
-extern void hold_metapage(metapage_t *, int);
 
 /*
  * This routine uses hash to explicitly find small number of pages
diff -Nru a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
--- a/fs/jfs/jfs_mount.c	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_mount.c	Sun Apr 14 12:16:56 2002
@@ -1,10 +1,5 @@
 /*
- *   MODULE_NAME:		jfs_mount.c
- *
- *   COMPONENT_NAME:		sysjfs
- *
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -22,11 +17,6 @@
  */
 
 /*
- * Change History :
- *
- */
-
-/*
  * Module: jfs_mount.c
  *
  * note: file system in transition to aggregate/fileset:
@@ -283,24 +273,6 @@
 			return rc;
 		}
 	}
-#ifdef _STILL_TO_PORT
-	/*
-	 * get log device associated with the fs being mounted;
-	 */
-	if (ipmnt->i_mntflag & JFS_INLINELOG) {
-		vfsp->vfs_logVPB = vfsp->vfs_hVPB;
-		vfsp->vfs_logvpfs = vfsp->vfs_vpfsi;
-	} else if (vfsp->vfs_logvpfs == NULL) {
-		/*
-		 * XXX: there's only one external log per system;
-		 */
-		jERROR(1, ("jfs_mount: Mount Failure! No Log Device.\n"));
-		goto errout30;
-	}
-
-	logdev = vfsp->vfs_logvpfs->vpi_unit;
-	ipmnt->i_logdev = logdev;
-#endif				/* _STILL_TO_PORT */
 
 	/*
 	 * open/initialize log
@@ -360,7 +332,7 @@
 	 */
 	/* validate fs signature */
 	if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
-	    j_sb->s_version != cpu_to_le32(JFS_VERSION)) {
+	    j_sb->s_version > cpu_to_le32(JFS_VERSION)) {
 		//rc = EFORMAT;
 		rc = EINVAL;
 		goto out;
@@ -398,10 +370,6 @@
 			j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
 	}
 
-	/* in release 1, the flag MUST reflect inline log, and group commit */
-	if ((j_sb->s_flag & cpu_to_le32(JFS_INLINELOG)) !=
-	    cpu_to_le32(JFS_INLINELOG))
-		j_sb->s_flag |= cpu_to_le32(JFS_INLINELOG);
 	if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
 	    cpu_to_le32(JFS_GROUPCOMMIT))
 		j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);
@@ -437,6 +405,8 @@
 	sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
 	if (sbi->mntflag & JFS_INLINELOG)
 		sbi->logpxd = j_sb->s_logpxd;
+	else
+		sbi->logdev = to_kdev_t(le32_to_cpu(j_sb->s_logdev));
 	sbi->ait2 = j_sb->s_ait2;
 
       out:
@@ -476,6 +446,10 @@
 		j_sb->s_logdev =
 			cpu_to_le32(kdev_t_to_nr(JFS_SBI(sb)->log->dev));
 		j_sb->s_logserial = cpu_to_le32(JFS_SBI(sb)->log->serial);
+		/* record our own device number in case the location
+		 * changes after a reboot
+		 */
+		j_sb->s_device = cpu_to_le32(kdev_t_to_nr(sb->s_dev));
 	} else if (state == FM_CLEAN) {
 		/*
 		 * If this volume is shared with OS/2, OS/2 will need to
diff -Nru a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
--- a/fs/jfs/jfs_superblock.h	Sun Apr 14 12:16:56 2002
+++ b/fs/jfs/jfs_superblock.h	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,20 +14,16 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
  */
 #ifndef	_H_JFS_SUPERBLOCK
 #define _H_JFS_SUPERBLOCK
-/*
- *	jfs_superblock.h
- */
 
 /*
  * make the magic number something a human could read
  */
-#define JFS_MAGIC 	"JFS1"	/* Magic word: Version 1 */
+#define JFS_MAGIC 	"JFS1"	/* Magic word */
 
-#define JFS_VERSION	1	/* Version number: Version 1 */
+#define JFS_VERSION	2	/* Version number: Version 2 */
 
 #define LV_NAME_SIZE	11	/* MUST BE 11 for OS/2 boot sector */
 
@@ -103,38 +99,10 @@
 	pxd_t s_xlogpxd;	/* 8: extendfs logpxd */
 	/* - 128 byte boundary - */
 
-	/*
-	 *      DFS VFS support (preliminary) 
-	 */
-	char s_attach;		/* 1: VFS: flag: set when aggregate is attached
-				 */
-	u8 rsrvd4[7];		/* 7: reserved - set to 0 */
-
-	u64 totalUsable;	/* 8: VFS: total of 1K blocks which are
-				 * available to "normal" (non-root) users.
-				 */
-	u64 minFree;		/* 8: VFS: # of 1K blocks held in reserve for 
-				 * exclusive use of root.  This value can be 0,
-				 * and if it is then totalUsable will be equal 
-				 * to # of blocks in aggregate.  I believe this
-				 * means that minFree + totalUsable = # blocks.
-				 * In that case, we don't need to store both 
-				 * totalUsable and minFree since we can compute
-				 * one from the other.  I would guess minFree 
-				 * would be the one we should store, and 
-				 * totalUsable would be the one we should 
-				 * compute.  (Just a guess...)
-				 */
-
-	u64 realFree;		/* 8: VFS: # of free 1K blocks can be used by 
-				 * "normal" users.  It may be this is something
-				 * we should compute when asked for instead of 
-				 * storing in the superblock.  I don't know how
-				 * often this information is needed.
-				 */
-	/*
-	 *      graffiti area
-	 */
+	u32 s_device;		/* Store device in case location changes
+				 * between reboots
+				 */
+
 };
 
 extern int readSuper(struct super_block *, struct metapage **);
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	Sun Apr 14 12:16:55 2002
+++ b/fs/jfs/jfs_txnmgr.c	Sun Apr 14 12:16:55 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -47,6 +46,7 @@
 #include <linux/locks.h>
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
+#include <linux/completion.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -81,9 +81,9 @@
 static int nTxBlock = 512;	/* number of transaction blocks */
 struct tblock *TxBlock;	        /* transaction block table */
 
-static int nTxLock = 2048;	/* number of transaction locks */
-static int TxLockLWM = 2048*.4;	/* Low water mark for number of txLocks used */
-static int TxLockHWM = 2048*.8;	/* High water mark for number of txLocks used */
+static int nTxLock = 4096;	/* number of transaction locks */
+static int TxLockLWM = 4096*.4;	/* Low water mark for number of txLocks used */
+static int TxLockHWM = 4096*.8;	/* High water mark for number of txLocks used */
 struct tlock *TxLock;           /* transaction lock table */
 static int TlocksLow = 0;	/* Indicates low number of available tlocks */
 
@@ -2777,6 +2777,7 @@
 	complete(&jfsIOwait);
 
 	do {
+		LAZY_LOCK(flags);
 restart:
 		WorkDone = 0;
 		while ((tblk = TxAnchor.unlock_queue)) {
@@ -2788,7 +2789,6 @@
 			 */
 			WorkDone = 1;
 
-			LAZY_LOCK(flags);
 			/*
 			 * Remove first transaction from queue
 			 */
@@ -2808,11 +2808,13 @@
 				current->state = TASK_RUNNING;
 				schedule();
 			}
+			LAZY_LOCK(flags);
 		}
 
 		if (WorkDone)
 			goto restart;
-		
+
+		LAZY_UNLOCK(flags);
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
 	} while (!jfs_thread_stopped());
diff -Nru a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
--- a/fs/jfs/jfs_txnmgr.h	Sun Apr 14 12:16:59 2002
+++ b/fs/jfs/jfs_txnmgr.h	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,17 +15,8 @@
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-
-/*
- * Change History :
- *
- */
-
 #ifndef _H_JFS_TXNMGR
 #define _H_JFS_TXNMGR
-/*
- *	jfs_txnmgr.h: transaction manager
- */
 
 #include "jfs_logmgr.h"
 
diff -Nru a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
--- a/fs/jfs/jfs_types.h	Sun Apr 14 12:16:58 2002
+++ b/fs/jfs/jfs_types.h	Sun Apr 14 12:16:58 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
  *   along with this program;  if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-
 #ifndef _H_JFS_TYPES
 #define	_H_JFS_TYPES
 
diff -Nru a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
--- a/fs/jfs/jfs_umount.c	Sun Apr 14 12:16:54 2002
+++ b/fs/jfs/jfs_umount.c	Sun Apr 14 12:16:54 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,10 +14,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Change History :
  */
 
 /*
diff -Nru a/fs/jfs/jfs_unicode.c b/fs/jfs/jfs_unicode.c
--- a/fs/jfs/jfs_unicode.c	Sun Apr 14 12:16:57 2002
+++ b/fs/jfs/jfs_unicode.c	Sun Apr 14 12:16:57 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -16,6 +15,7 @@
  *   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/fs.h>
 #include <linux/slab.h>
 #include "jfs_types.h"
diff -Nru a/fs/jfs/jfs_unicode.h b/fs/jfs/jfs_unicode.h
--- a/fs/jfs/jfs_unicode.h	Sun Apr 14 12:16:54 2002
+++ b/fs/jfs/jfs_unicode.h	Sun Apr 14 12:16:54 2002
@@ -1,11 +1,5 @@
 /*
- * unistrk:  Unicode kernel case support
- *
- * Function:
- *     Convert a unicode character to upper or lower case using
- *     compressed tables.
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -20,9 +14,9 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
  */
+#ifndef _H_JFS_UNICODE
+#define _H_JFS_UNICODE
 
 #include <asm/byteorder.h>
 #include "jfs_types.h"
@@ -106,9 +100,9 @@
 /*
  * UniToupper:  Convert a unicode character to upper case
  */
-static inline wchar_t UniToupper(register wchar_t uc)
+static inline wchar_t UniToupper(wchar_t uc)
 {
-	register UNICASERANGE *rp;
+	UNICASERANGE *rp;
 
 	if (uc < sizeof(UniUpperTable)) {	/* Latin characters */
 		return uc + UniUpperTable[uc];	/* Use base tables */
@@ -129,9 +123,9 @@
 /*
  * UniStrupr:  Upper case a unicode string
  */
-static inline wchar_t *UniStrupr(register wchar_t * upin)
+static inline wchar_t *UniStrupr(wchar_t * upin)
 {
-	register wchar_t *up;
+	wchar_t *up;
 
 	up = upin;
 	while (*up) {		/* For all characters */
@@ -141,3 +135,4 @@
 	return upin;		/* Return input pointer */
 }
 
+#endif				/* !_H_JFS_UNICODE */
diff -Nru a/fs/jfs/jfs_uniupr.c b/fs/jfs/jfs_uniupr.c
--- a/fs/jfs/jfs_uniupr.c	Sun Apr 14 12:16:59 2002
+++ b/fs/jfs/jfs_uniupr.c	Sun Apr 14 12:16:59 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,10 +14,7 @@
  *   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
- *
- * jfs_uniupr.c - Unicode compressed case ranges
- *
-*/
+ */
 
 #include <linux/fs.h>
 #include "jfs_unicode.h"
diff -Nru a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
--- a/fs/jfs/jfs_xtree.c	Sun Apr 14 12:16:58 2002
+++ b/fs/jfs/jfs_xtree.c	Sun Apr 14 12:16:58 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff -Nru a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
--- a/fs/jfs/jfs_xtree.h	Sun Apr 14 12:17:00 2002
+++ b/fs/jfs/jfs_xtree.h	Sun Apr 14 12:17:00 2002
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -14,12 +14,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-/*
- * Change History :
- *
-*/
-
+ */
 #ifndef _H_JFS_XTREE
 #define _H_JFS_XTREE
 
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	Sun Apr 14 12:16:59 2002
+++ b/fs/jfs/namei.c	Sun Apr 14 12:16:59 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -15,17 +14,10 @@
  *   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
- *
- * Module: jfs/namei.c
- *
- */
-
-/*
- * Change History :
- *
  */
 
 #include <linux/fs.h>
+#include <linux/locks.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
 #include "jfs_dinode.h"
@@ -33,8 +25,6 @@
 #include "jfs_unicode.h"
 #include "jfs_metapage.h"
 #include "jfs_debug.h"
-#include <linux/locks.h>
-#include <linux/slab.h>
 
 extern struct inode_operations jfs_file_inode_operations;
 extern struct inode_operations jfs_symlink_inode_operations;
@@ -588,7 +578,7 @@
  */
 s64 commitZeroLink(tid_t tid, struct inode *ip)
 {
-	int filetype, committype;
+	int filetype;
 	tblock_t *tblk;
 
 	jFYI(1, ("commitZeroLink: tid = %d, ip = 0x%p\n", tid, ip));
@@ -609,67 +599,26 @@
 		return 0;
 	}
 
-#ifdef _STILL_TO_PORT
-	/*
-	 *      free from block allocation map:
-	 *
-	 * if there is no cache control element associated with 
-	 * the file, free resources in both persistent and work map;
-	 * otherwise just persistent map. 
-	 */
-	if (ip->i_cacheid) {
-		committype = COMMIT_PMAP;
-
-		/* mark for iClose() to free from working map */
-		set_cflag(COMMIT_Freewmap, ip);
-	} else
-		committype = COMMIT_PWMAP;
-#else				/* _STILL_TO_PORT */
-
 	set_cflag(COMMIT_Freewmap, ip);
-	committype = COMMIT_PMAP;
-#endif				/* _STILL_TO_PORT */
 
 	/* mark transaction of block map update type */
 	tblk = tid_to_tblock(tid);
-	tblk->xflag |= committype;
+	tblk->xflag |= COMMIT_PMAP;
 
 	/*
 	 * free EA
 	 */
-	if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
-#ifdef _STILL_TO_PORT
-		/* free EA pages from cache */
-		if (committype == COMMIT_PWMAP)
-			bmExtentInvalidate(ip, addressDXD(&ip->i_ea),
-					   lengthDXD(&ip->i_ea));
-#endif				/* _STILL_TO_PORT */
-
+	if (JFS_IP(ip)->ea.flag & DXD_EXTENT)
 		/* acquire maplock on EA to be freed from block map */
 		txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
 
-		if (committype == COMMIT_PWMAP)
-			JFS_IP(ip)->ea.flag = 0;
-	}
-
 	/*
 	 * free ACL
 	 */
-	if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
-#ifdef _STILL_TO_PORT
-		/* free ACL pages from cache */
-		if (committype == COMMIT_PWMAP)
-			bmExtentInvalidate(ip, addressDXD(&ip->i_acl),
-					   lengthDXD(&ip->i_acl));
-#endif				/* _STILL_TO_PORT */
-
+	if (JFS_IP(ip)->acl.flag & DXD_EXTENT)
 		/* acquire maplock on EA to be freed from block map */
 		txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
 
-		if (committype == COMMIT_PWMAP)
-			JFS_IP(ip)->acl.flag = 0;
-	}
-
 	/*
 	 * free xtree/data (truncate to zero length):
 	 * free xtree/data pages from cache if COMMIT_PWMAP, 
@@ -1402,12 +1351,7 @@
 		goto out1;
 	}
 
-	if (S_ISREG(ip->i_mode)) {
-		ip->i_op = &jfs_file_inode_operations;
-		ip->i_fop = &jfs_file_operations;
-		ip->i_mapping->a_ops = &jfs_aops;
-	} else
-		init_special_inode(ip, ip->i_mode, rdev);
+	init_special_inode(ip, ip->i_mode, rdev);
 
 	insert_inode_hash(ip);
 	mark_inode_dirty(ip);
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	Sun Apr 14 12:16:58 2002
+++ b/fs/jfs/super.c	Sun Apr 14 12:16:58 2002
@@ -1,6 +1,5 @@
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -21,7 +20,7 @@
 #include <linux/locks.h>
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/completion.h>
 #include <asm/uaccess.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
@@ -170,9 +169,9 @@
 
 	if (!options)
 		return 1;
-	for (this_char = strtok (options, ",");
-	     this_char != NULL;
-	     this_char = strtok (NULL, ",")) {
+	while ((this_char = strsep (&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr (this_char, '=')) != NULL)
 			*value++ = 0;
 		if (!strcmp (this_char, "iocharset")) {
@@ -268,10 +267,7 @@
 	/*
 	 * Initialize blocksize to 4K.
 	 */
-	sb->s_blocksize = PSIZE;
-	sb->s_blocksize_bits = L2PSIZE;
-	set_blocksize(sb->s_dev, PSIZE);
-
+	sb_set_blocksize(sb, PSIZE);
 	sb->s_op = &jfs_sops;
 	/*
 	 * Initialize direct-mapping inode/address-space
diff -Nru a/fs/jfs/symlink.c b/fs/jfs/symlink.c
--- a/fs/jfs/symlink.c	Sun Apr 14 12:16:58 2002
+++ b/fs/jfs/symlink.c	Sun Apr 14 12:16:58 2002
@@ -1,7 +1,5 @@
-
 /*
- *
- *   Copyright (c) International Business Machines  Corp., 2000
+ *   Copyright (c) International Business Machines Corp., 2000-2002
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -16,8 +14,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program;  if not, write to the Free Software 
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *  JFS fast symlink handling code
  */
 
 #include <linux/fs.h>
diff -Nru a/fs/lockd/mon.c b/fs/lockd/mon.c
--- a/fs/lockd/mon.c	Sun Apr 14 12:16:56 2002
+++ b/fs/lockd/mon.c	Sun Apr 14 12:16:56 2002
@@ -205,33 +205,49 @@
 #endif
 
 static struct rpc_procinfo	nsm_procedures[] = {
-        { "sm_null",
-		(kxdrproc_t) xdr_error,
-		(kxdrproc_t) xdr_error, 0, 0 },
-        { "sm_stat",
-		(kxdrproc_t) xdr_error,
-		(kxdrproc_t) xdr_error, 0, 0 },
-        { "sm_mon",
-		(kxdrproc_t) xdr_encode_mon,
-		(kxdrproc_t) xdr_decode_stat_res, MAX(SM_mon_sz, SM_monres_sz) << 2, 0 },
-        { "sm_unmon",
-		(kxdrproc_t) xdr_encode_mon,
-		(kxdrproc_t) xdr_decode_stat, MAX(SM_mon_id_sz, SM_unmonres_sz) << 2, 0 },
-        { "sm_unmon_all",
-		(kxdrproc_t) xdr_error,
-		(kxdrproc_t) xdr_error, 0, 0 },
-        { "sm_simu_crash",
-		(kxdrproc_t) xdr_error,
-		(kxdrproc_t) xdr_error, 0, 0 },
-        { "sm_notify",
-		(kxdrproc_t) xdr_error,
-		(kxdrproc_t) xdr_error, 0, 0 },
+        {
+		p_procname:	"sm_null",
+		p_encode:	(kxdrproc_t) xdr_error,
+		p_decode:	(kxdrproc_t) xdr_error,
+	},
+        {
+		p_procname:	"sm_stat",
+		p_encode:	(kxdrproc_t) xdr_error,
+		p_decode:	(kxdrproc_t) xdr_error,
+	},
+        {
+		p_procname:	"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_procname:	"sm_unmon",
+		p_encode:	(kxdrproc_t) xdr_encode_mon,
+		p_decode:	(kxdrproc_t) xdr_decode_stat,
+		p_bufsiz:	MAX(SM_mon_id_sz, SM_unmonres_sz) << 2,
+	},
+        {
+		p_procname:	"sm_unmon_all",
+		p_encode:	(kxdrproc_t) xdr_error,
+		p_decode:	(kxdrproc_t) xdr_error,
+	},
+        {
+		p_procname:	"sm_simu_crash",
+		p_encode:	(kxdrproc_t) xdr_error,
+		p_decode:	(kxdrproc_t) xdr_error, 0, 0
+	},
+        {
+		p_procname:	"sm_notify",
+		p_encode:	(kxdrproc_t) xdr_error,
+		p_decode:	(kxdrproc_t) xdr_error,
+	},
 };
 
 static struct rpc_version	nsm_version1 = {
-	1, 
-	sizeof(nsm_procedures)/sizeof(nsm_procedures[0]),
-	nsm_procedures
+		number:		1, 
+		nrprocs:	sizeof(nsm_procedures)/sizeof(nsm_procedures[0]),
+		procs:		nsm_procedures
 };
 
 static struct rpc_version *	nsm_version[] = {
@@ -242,9 +258,9 @@
 static struct rpc_stat		nsm_stats;
 
 struct rpc_program		nsm_program = {
-	"statd",
-	SM_PROGRAM,
-	sizeof(nsm_version)/sizeof(nsm_version[0]),
-	nsm_version,
-	&nsm_stats
+		name:		"statd",
+		number:		SM_PROGRAM,
+		nrvers:		sizeof(nsm_version)/sizeof(nsm_version[0]),
+		version:	nsm_version,
+		stats:		&nsm_stats
 };
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	Sun Apr 14 12:16:59 2002
+++ b/fs/lockd/svc.c	Sun Apr 14 12:16:59 2002
@@ -369,14 +369,20 @@
  * Define NLM program and procedures
  */
 static struct svc_version	nlmsvc_version1 = {
-	1, 17, nlmsvc_procedures, NULL
+		vs_vers:	1,
+		vs_nproc:	17,
+		vs_proc:	nlmsvc_procedures,
 };
 static struct svc_version	nlmsvc_version3 = {
-	3, 24, nlmsvc_procedures, NULL
+		vs_vers:	3,
+		vs_nproc:	24,
+		vs_proc:	nlmsvc_procedures,
 };
 #ifdef CONFIG_LOCKD_V4
 static struct svc_version	nlmsvc_version4 = {
-	4, 24, nlmsvc_procedures4, NULL
+		vs_vers:	4,
+		vs_nproc:	24,
+		vs_proc:	nlmsvc_procedures4,
 };
 #endif
 static struct svc_version *	nlmsvc_version[] = {
@@ -392,11 +398,12 @@
 static struct svc_stat		nlmsvc_stats;
 
 #define NLM_NRVERS	(sizeof(nlmsvc_version)/sizeof(nlmsvc_version[0]))
-struct svc_program		nlmsvc_program = {
-	NLM_PROGRAM,		/* program number */
-	1, NLM_NRVERS-1,	/* version range */
-	NLM_NRVERS,		/* number of entries in nlmsvc_version */
-	nlmsvc_version,		/* version table */
-	"lockd",		/* service name */
-	&nlmsvc_stats,		/* stats table */
+struct svc_program	nlmsvc_program = {
+	pg_prog:	NLM_PROGRAM,		/* program number */
+	pg_lovers:	1,			// version
+	pg_hivers:	NLM_NRVERS-1,		// range
+	pg_nvers:	NLM_NRVERS,		/* number of entries in nlmsvc_version */
+	pg_vers:	nlmsvc_version,		/* version table */
+	pg_name:	"lockd",		/* service name */
+	pg_stats:	&nlmsvc_stats,		/* stats table */
 };
diff -Nru a/fs/lockd/xdr.c b/fs/lockd/xdr.c
--- a/fs/lockd/xdr.c	Sun Apr 14 12:16:55 2002
+++ b/fs/lockd/xdr.c	Sun Apr 14 12:16:55 2002
@@ -603,11 +603,15 @@
 };
 
 static struct rpc_version	nlm_version1 = {
-	1, 16, nlm_procedures,
+		number:		1,
+		nrprocs:	16,
+		procs:		nlm_procedures,
 };
 
 static struct rpc_version	nlm_version3 = {
-	3, 24, nlm_procedures,
+		number:		3,
+		nrprocs:	24,
+		procs:		nlm_procedures,
 };
 
 #ifdef 	CONFIG_LOCKD_V4
@@ -627,11 +631,11 @@
 static struct rpc_stat		nlm_stats;
 
 struct rpc_program		nlm_program = {
-	"lockd",
-	NLM_PROGRAM,
-	sizeof(nlm_versions) / sizeof(nlm_versions[0]),
-	nlm_versions,
-	&nlm_stats,
+		name:		"lockd",
+		number:		NLM_PROGRAM,
+		nrvers:		sizeof(nlm_versions) / sizeof(nlm_versions[0]),
+		version:	nlm_versions,
+		stats:		&nlm_stats,
 };
 
 #ifdef LOCKD_DEBUG
diff -Nru a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
--- a/fs/lockd/xdr4.c	Sun Apr 14 12:16:54 2002
+++ b/fs/lockd/xdr4.c	Sun Apr 14 12:16:54 2002
@@ -609,5 +609,7 @@
 };
 
 struct rpc_version	nlm_version4 = {
-	4, 24, nlm4_procedures,
+	number:		4,
+	nrprocs:	24,
+	procs:		nlm4_procedures,
 };
diff -Nru a/fs/minix/bitmap.c b/fs/minix/bitmap.c
--- a/fs/minix/bitmap.c	Sun Apr 14 12:16:56 2002
+++ b/fs/minix/bitmap.c	Sun Apr 14 12:16:56 2002
@@ -11,10 +11,8 @@
 
 /* bitmap.c contains the code that handles the inode and block bitmaps */
 
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-#include <linux/locks.h>
-
+#include "minix.h"
+#include <linux/smp_lock.h>
 #include <asm/bitops.h>
 
 static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
@@ -56,12 +54,7 @@
 	struct buffer_head * bh;
 	unsigned int bit,zone;
 
-	if (!sb) {
-		printk("trying to free block on nonexistent device\n");
-		return;
-	}
-	if (block < sbi->s_firstdatazone ||
-	    block >= sbi->s_nzones) {
+	if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
 		printk("trying to free block not in datazone\n");
 		return;
 	}
@@ -73,49 +66,41 @@
 		return;
 	}
 	bh = sbi->s_zmap[zone];
+	lock_kernel();
 	if (!minix_test_and_clear_bit(bit,bh->b_data))
 		printk("free_block (%s:%d): bit already cleared\n",
 		       sb->s_id, block);
+	unlock_kernel();
 	mark_buffer_dirty(bh);
 	return;
 }
 
 int minix_new_block(struct inode * inode)
 {
-	struct super_block * sb = inode->i_sb;
-	struct minix_sb_info * sbi = minix_sb(sb);
-	struct buffer_head * bh;
-	int i,j;
+	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+	int i;
 
-	if (!sb) {
-		printk("trying to get new block from nonexistent device\n");
-		return 0;
-	}
-repeat:
-	j = 8192;
-	bh = NULL;
 	for (i = 0; i < sbi->s_zmap_blocks; i++) {
-		bh = sbi->s_zmap[i];
-		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
-			break;
-	}
-	if (!bh || j >= 8192)
-		return 0;
-	if (minix_test_and_set_bit(j,bh->b_data)) {
-		printk("new_block: bit already set");
-		goto repeat;
+		struct buffer_head *bh = sbi->s_zmap[i];
+		int j;
+
+		lock_kernel();
+		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) {
+			minix_set_bit(j,bh->b_data);
+			unlock_kernel();
+			mark_buffer_dirty(bh);
+			j += i*8192 + sbi->s_firstdatazone-1;
+			if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
+				break;
+			return j;
+		}
+		unlock_kernel();
 	}
-	mark_buffer_dirty(bh);
-	j += i*8192 + sbi->s_firstdatazone-1;
-	if (j < sbi->s_firstdatazone ||
-	    j >= sbi->s_nzones)
-		return 0;
-	return j;
+	return 0;
 }
 
-unsigned long minix_count_free_blocks(struct super_block *sb)
+unsigned long minix_count_free_blocks(struct minix_sb_info *sbi)
 {
-	struct minix_sb_info *sbi = minix_sb(sb);
 	return (count_free(sbi->s_zmap, sbi->s_zmap_blocks,
 		sbi->s_nzones - sbi->s_firstdatazone + 1)
 		<< sbi->s_log_zone_size);
@@ -198,36 +183,38 @@
 
 void minix_free_inode(struct inode * inode)
 {
+	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
 	struct buffer_head * bh;
 	unsigned long ino;
 
-	if (inode->i_ino < 1 || inode->i_ino > minix_sb(inode->i_sb)->s_ninodes) {
+	if (inode->i_ino < 1 || inode->i_ino > sbi->s_ninodes) {
 		printk("free_inode: inode 0 or nonexistent inode\n");
 		return;
 	}
 	ino = inode->i_ino;
-	if ((ino >> 13) >= minix_sb(inode->i_sb)->s_imap_blocks) {
+	if ((ino >> 13) >= sbi->s_imap_blocks) {
 		printk("free_inode: nonexistent imap in superblock\n");
 		return;
 	}
 
-	bh = minix_sb(inode->i_sb)->s_imap[ino >> 13];
+	bh = sbi->s_imap[ino >> 13];
 	minix_clear_inode(inode);
 	clear_inode(inode);
+	lock_kernel();
 	if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
 		printk("free_inode: bit %lu already cleared.\n",ino);
+	unlock_kernel();
 	mark_buffer_dirty(bh);
 }
 
 struct inode * minix_new_inode(const struct inode * dir, int * error)
 {
-	struct super_block * sb;
-	struct inode * inode;
+	struct super_block *sb = dir->i_sb;
+	struct minix_sb_info *sbi = minix_sb(sb);
+	struct inode *inode = new_inode(sb);
 	struct buffer_head * bh;
 	int i,j;
 
-	sb = dir->i_sb;
-	inode = new_inode(sb);
 	if (!inode) {
 		*error = -ENOMEM;
 		return NULL;
@@ -235,28 +222,28 @@
 	j = 8192;
 	bh = NULL;
 	*error = -ENOSPC;
-	lock_super(sb);
-	for (i = 0; i < minix_sb(sb)->s_imap_blocks; i++) {
-		bh = minix_sb(inode->i_sb)->s_imap[i];
+	lock_kernel();
+	for (i = 0; i < sbi->s_imap_blocks; i++) {
+		bh = sbi->s_imap[i];
 		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
 			break;
 	}
 	if (!bh || j >= 8192) {
+		unlock_kernel();
 		iput(inode);
-		unlock_super(sb);
 		return NULL;
 	}
 	if (minix_test_and_set_bit(j,bh->b_data)) {	/* shouldn't happen */
 		printk("new_inode: bit already set");
+		unlock_kernel();
 		iput(inode);
-		unlock_super(sb);
 		return NULL;
 	}
+	unlock_kernel();
 	mark_buffer_dirty(bh);
 	j += i*8192;
-	if (!j || j > minix_sb(inode->i_sb)->s_ninodes) {
+	if (!j || j > sbi->s_ninodes) {
 		iput(inode);
-		unlock_super(sb);
 		return NULL;
 	}
 	inode->i_uid = current->fsuid;
@@ -268,13 +255,11 @@
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
 
-	unlock_super(sb);
 	*error = 0;
 	return inode;
 }
 
-unsigned long minix_count_free_inodes(struct super_block *sb)
+unsigned long minix_count_free_inodes(struct minix_sb_info *sbi)
 {
-	return count_free(minix_sb(sb)->s_imap, minix_sb(sb)->s_imap_blocks,
-		minix_sb(sb)->s_ninodes + 1);
+	return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1);
 }
diff -Nru a/fs/minix/dir.c b/fs/minix/dir.c
--- a/fs/minix/dir.c	Sun Apr 14 12:16:56 2002
+++ b/fs/minix/dir.c	Sun Apr 14 12:16:56 2002
@@ -6,9 +6,7 @@
  *  minix directory handling functions
  */
 
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-#include <linux/pagemap.h>
+#include "minix.h"
 
 typedef struct minix_dir_entry minix_dirent;
 
diff -Nru a/fs/minix/file.c b/fs/minix/file.c
--- a/fs/minix/file.c	Sun Apr 14 12:16:57 2002
+++ b/fs/minix/file.c	Sun Apr 14 12:16:57 2002
@@ -6,8 +6,7 @@
  *  minix regular file handling primitives
  */
 
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
+#include "minix.h"
 
 /*
  * We have mostly NULLs here: the current defaults are OK for
diff -Nru a/fs/minix/inode.c b/fs/minix/inode.c
--- a/fs/minix/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/minix/inode.c	Sun Apr 14 12:16:59 2002
@@ -10,15 +10,11 @@
  */
 
 #include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
+#include "minix.h"
 #include <linux/slab.h>
 #include <linux/locks.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/highuid.h>
-#include <linux/blkdev.h>
 
 static void minix_read_inode(struct inode * inode);
 static void minix_write_inode(struct inode * inode, int wait);
@@ -29,32 +25,9 @@
 {
 	inode->i_size = 0;
 	minix_truncate(inode);
-	lock_kernel();
 	minix_free_inode(inode);
-	unlock_kernel();
-}
-
-static void minix_commit_super(struct super_block * sb)
-{
-	mark_buffer_dirty(minix_sb(sb)->s_sbh);
-	sb->s_dirt = 0;
-}
-
-static void minix_write_super(struct super_block * sb)
-{
-	struct minix_super_block * ms;
-
-	if (!(sb->s_flags & MS_RDONLY)) {
-		ms = minix_sb(sb)->s_ms;
-
-		if (ms->s_state & MINIX_VALID_FS)
-			ms->s_state &= ~MINIX_VALID_FS;
-		minix_commit_super(sb);
-	}
-	sb->s_dirt = 0;
 }
 
-
 static void minix_put_super(struct super_block *sb)
 {
 	int i;
@@ -125,7 +98,6 @@
 	write_inode:	minix_write_inode,
 	delete_inode:	minix_delete_inode,
 	put_super:	minix_put_super,
-	write_super:	minix_write_super,
 	statfs:		minix_statfs,
 	remount_fs:	minix_remount,
 };
@@ -145,15 +117,11 @@
 		/* Mounting a rw partition read-only. */
 		ms->s_state = sbi->s_mount_state;
 		mark_buffer_dirty(sbi->s_sbh);
-		sb->s_dirt = 1;
-		minix_commit_super(sb);
-	}
-	else {
+	} else {
 	  	/* Mount a partition which is read-only, read-write. */
 		sbi->s_mount_state = ms->s_state;
 		ms->s_state &= ~MINIX_VALID_FS;
 		mark_buffer_dirty(sbi->s_sbh);
-		sb->s_dirt = 1;
 
 		if (!(sbi->s_mount_state & MINIX_VALID_FS))
 			printk ("MINIX-fs warning: remounting unchecked fs, "
@@ -272,7 +240,6 @@
 	if (!(s->s_flags & MS_RDONLY)) {
 		ms->s_state &= ~MINIX_VALID_FS;
 		mark_buffer_dirty(bh);
-		s->s_dirt = 1;
 	}
 	if (!(sbi->s_mount_state & MINIX_VALID_FS))
 		printk ("MINIX-fs: mounting unchecked file system, "
@@ -332,10 +299,10 @@
 	buf->f_type = sb->s_magic;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
-	buf->f_bfree = minix_count_free_blocks(sb);
+	buf->f_bfree = minix_count_free_blocks(sbi);
 	buf->f_bavail = buf->f_bfree;
 	buf->f_files = sbi->s_ninodes;
-	buf->f_ffree = minix_count_free_inodes(sb);
+	buf->f_ffree = minix_count_free_inodes(sbi);
 	buf->f_namelen = sbi->s_namelen;
 	return 0;
 }
@@ -526,12 +493,7 @@
 
 static void minix_write_inode(struct inode * inode, int wait)
 {
-	struct buffer_head *bh;
-
-	lock_kernel();
-	bh = minix_update_inode(inode);
-	unlock_kernel();
-	brelse(bh);
+	brelse(minix_update_inode(inode));
 }
 
 int minix_sync_inode(struct inode * inode)
@@ -562,12 +524,10 @@
  */
 void minix_truncate(struct inode * inode)
 {
-	lock_kernel();
 	if (INODE_VERSION(inode) == MINIX_V1)
 		V1_minix_truncate(inode);
 	else
 		V2_minix_truncate(inode);
-	unlock_kernel();
 }
 
 static struct super_block *minix_get_sb(struct file_system_type *fs_type,
diff -Nru a/fs/minix/itree_common.c b/fs/minix/itree_common.c
--- a/fs/minix/itree_common.c	Sun Apr 14 12:16:55 2002
+++ b/fs/minix/itree_common.c	Sun Apr 14 12:16:55 2002
@@ -6,6 +6,8 @@
 	struct buffer_head *bh;
 } Indirect;
 
+static rwlock_t pointers_lock = RW_LOCK_UNLOCKED;
+
 static inline void add_chain(Indirect *p, struct buffer_head *bh, block_t *v)
 {
 	p->key = *(p->p = v);
@@ -43,17 +45,18 @@
 		bh = sb_bread(sb, block_to_cpu(p->key));
 		if (!bh)
 			goto failure;
-		/* Reader: pointers */
+		read_lock(&pointers_lock);
 		if (!verify_chain(chain, p))
 			goto changed;
 		add_chain(++p, bh, (block_t *)bh->b_data + *++offsets);
-		/* Reader: end */
+		read_unlock(&pointers_lock);
 		if (!p->key)
 			goto no_block;
 	}
 	return NULL;
 
 changed:
+	read_unlock(&pointers_lock);
 	*err = -EAGAIN;
 	goto no_block;
 failure:
@@ -108,18 +111,15 @@
 {
 	int i;
 
-	/* Verify that place we are splicing to is still there and vacant */
+	write_lock(&pointers_lock);
 
-	/* Writer: pointers */
+	/* Verify that place we are splicing to is still there and vacant */
 	if (!verify_chain(chain, where-1) || *where->p)
-		/* Writer: end */
 		goto changed;
 
-	/* That's it */
-
 	*where->p = where->key;
 
-	/* Writer: end */
+	write_unlock(&pointers_lock);
 
 	/* We are done with atomic stuff, now do the rest of housekeeping */
 
@@ -133,6 +133,7 @@
 	return 0;
 
 changed:
+	write_unlock(&pointers_lock);
 	for (i = 1; i < num; i++)
 		bforget(where[i].bh);
 	for (i = 0; i < num; i++)
@@ -153,7 +154,6 @@
 	if (depth == 0)
 		goto out;
 
-	lock_kernel();
 reread:
 	partial = get_branch(inode, depth, offsets, chain, &err);
 
@@ -173,7 +173,6 @@
 			brelse(partial->bh);
 			partial--;
 		}
-		unlock_kernel();
 out:
 		return err;
 	}
@@ -226,12 +225,14 @@
 	for (k = depth; k > 1 && !offsets[k-1]; k--)
 		;
 	partial = get_branch(inode, k, offsets, chain, &err);
-	/* Writer: pointers */
+
+	write_lock(&pointers_lock);
 	if (!partial)
 		partial = chain + k-1;
-	if (!partial->key && *partial->p)
-		/* Writer: end */
+	if (!partial->key && *partial->p) {
+		write_unlock(&pointers_lock);
 		goto no_top;
+	}
 	for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--)
 		;
 	if (p == chain + k - 1 && p > chain) {
@@ -240,7 +241,7 @@
 		*top = *p->p;
 		*p->p = 0;
 	}
-	/* Writer: end */
+	write_unlock(&pointers_lock);
 
 	while(partial > p)
 	{
diff -Nru a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
--- a/fs/minix/itree_v1.c	Sun Apr 14 12:16:59 2002
+++ b/fs/minix/itree_v1.c	Sun Apr 14 12:16:59 2002
@@ -1,7 +1,5 @@
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
+#include "minix.h"
 #include <linux/locks.h>
-#include <linux/smp_lock.h>
 
 enum {DEPTH = 3, DIRECT = 7};	/* Only double indirect */
 
diff -Nru a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
--- a/fs/minix/itree_v2.c	Sun Apr 14 12:16:57 2002
+++ b/fs/minix/itree_v2.c	Sun Apr 14 12:16:57 2002
@@ -1,7 +1,5 @@
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
+#include "minix.h"
 #include <linux/locks.h>
-#include <linux/smp_lock.h>
 
 enum {DIRECT = 7, DEPTH = 4};	/* Have triple indirect */
 
diff -Nru a/fs/minix/minix.h b/fs/minix/minix.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/minix/minix.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,91 @@
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/minix_fs.h>
+
+/*
+ * change the define below to 0 if you want names > info->s_namelen chars to be
+ * truncated. Else they will be disallowed (ENAMETOOLONG).
+ */
+#define NO_TRUNCATE 1
+
+#define INODE_VERSION(inode)	minix_sb(inode->i_sb)->s_version
+
+#define MINIX_V1		0x0001		/* original minix fs */
+#define MINIX_V2		0x0002		/* minix V2 fs */
+
+/*
+ * minix fs inode data in memory
+ */
+struct minix_inode_info {
+	union {
+		__u16 i1_data[16];
+		__u32 i2_data[16];
+	} u;
+	struct inode vfs_inode;
+};
+
+/*
+ * minix super-block data in memory
+ */
+struct minix_sb_info {
+	unsigned long s_ninodes;
+	unsigned long s_nzones;
+	unsigned long s_imap_blocks;
+	unsigned long s_zmap_blocks;
+	unsigned long s_firstdatazone;
+	unsigned long s_log_zone_size;
+	unsigned long s_max_size;
+	int s_dirsize;
+	int s_namelen;
+	int s_link_max;
+	struct buffer_head ** s_imap;
+	struct buffer_head ** s_zmap;
+	struct buffer_head * s_sbh;
+	struct minix_super_block * s_ms;
+	unsigned short s_mount_state;
+	unsigned short s_version;
+};
+
+extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, struct buffer_head **);
+extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **);
+extern struct inode * minix_new_inode(const struct inode * dir, int * error);
+extern void minix_free_inode(struct inode * inode);
+extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
+extern int minix_new_block(struct inode * inode);
+extern void minix_free_block(struct inode * inode, int block);
+extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
+
+extern void V1_minix_truncate(struct inode *);
+extern void V2_minix_truncate(struct inode *);
+extern void minix_truncate(struct inode *);
+extern int minix_sync_inode(struct inode *);
+extern void minix_set_inode(struct inode *, dev_t);
+extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
+extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
+
+extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**);
+extern int minix_add_link(struct dentry*, struct inode*);
+extern int minix_delete_entry(struct minix_dir_entry*, struct page*);
+extern int minix_make_empty(struct inode*, struct inode*);
+extern int minix_empty_dir(struct inode*);
+extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
+extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
+extern ino_t minix_inode_by_name(struct dentry*);
+
+extern int minix_sync_file(struct file *, struct dentry *, int);
+
+extern struct inode_operations minix_file_inode_operations;
+extern struct inode_operations minix_dir_inode_operations;
+extern struct file_operations minix_file_operations;
+extern struct file_operations minix_dir_operations;
+extern struct dentry_operations minix_dentry_operations;
+
+static inline struct minix_sb_info *minix_sb(struct super_block *sb)
+{
+	return sb->u.generic_sbp;
+}
+
+static inline struct minix_inode_info *minix_i(struct inode *inode)
+{
+	return list_entry(inode, struct minix_inode_info, vfs_inode);
+}
diff -Nru a/fs/minix/namei.c b/fs/minix/namei.c
--- a/fs/minix/namei.c	Sun Apr 14 12:16:57 2002
+++ b/fs/minix/namei.c	Sun Apr 14 12:16:57 2002
@@ -4,9 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-#include <linux/pagemap.h>
+#include "minix.h"
 
 static inline void inc_count(struct inode *inode)
 {
diff -Nru a/fs/msdos/namei.c b/fs/msdos/namei.c
--- a/fs/msdos/namei.c	Sun Apr 14 12:16:58 2002
+++ b/fs/msdos/namei.c	Sun Apr 14 12:16:58 2002
@@ -34,9 +34,10 @@
 /***** Formats an MS-DOS file name. Rejects invalid names. */
 static int msdos_format_name(const char *name,int len,
 	char *res,struct fat_mount_options *opts)
-	/* conv is relaxed/normal/strict, name is proposed name,
-	 * len is the length of the proposed name, res is the result name,
-	 * dotsOK is if hidden files get dots.
+	/* name is the proposed name, len is its length, res is
+	 * the resulting name, opts->name_check is either (r)elaxed,
+	 * (n)ormal or (s)trict, opts->dotsOK allows dots at the
+	 * beginning of name (for hidden files)
 	 */
 {
 	char *walk;
@@ -58,11 +59,11 @@
 	for (walk = res; len && walk-res < 8; walk++) {
 	    	c = *name++;
 		len--;
-		if (opts->conversion != 'r' && strchr(bad_chars,c))
+		if (opts->name_check != 'r' && strchr(bad_chars,c))
 			return -EINVAL;
-		if (opts->conversion == 's' && strchr(bad_if_strict(opts),c))
+		if (opts->name_check == 's' && strchr(bad_if_strict(opts),c))
 			return -EINVAL;
-  		if (c >= 'A' && c <= 'Z' && opts->conversion == 's')
+  		if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
 			return -EINVAL;
 		if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
 /*  0xE5 is legal as a first character, but we must substitute 0x05     */
@@ -75,7 +76,7 @@
 		*walk = (!opts->nocase && c >= 'a' && c <= 'z') ? c-32 : c;
 	}
 	if (space) return -EINVAL;
-	if (opts->conversion == 's' && len && c != '.') {
+	if (opts->name_check == 's' && len && c != '.') {
 		c = *name++;
 		len--;
 		if (c != '.') return -EINVAL;
@@ -86,25 +87,25 @@
 		while (len > 0 && walk-res < MSDOS_NAME) {
 			c = *name++;
 			len--;
-			if (opts->conversion != 'r' && strchr(bad_chars,c))
+			if (opts->name_check != 'r' && strchr(bad_chars,c))
 				return -EINVAL;
-			if (opts->conversion == 's' &&
+			if (opts->name_check == 's' &&
 			    strchr(bad_if_strict(opts),c))
 				return -EINVAL;
 			if (c < ' ' || c == ':' || c == '\\')
 				return -EINVAL;
 			if (c == '.') {
-				if (opts->conversion == 's')
+				if (opts->name_check == 's')
 					return -EINVAL;
 				break;
 			}
-			if (c >= 'A' && c <= 'Z' && opts->conversion == 's')
+			if (c >= 'A' && c <= 'Z' && opts->name_check == 's')
 				return -EINVAL;
 			space = c == ' ';
 			*walk++ = (!opts->nocase && c >= 'a' && c <= 'z') ? c-32 : c;
 		}
 		if (space) return -EINVAL;
-		if (opts->conversion == 's' && len) return -EINVAL;
+		if (opts->name_check == 's' && len) return -EINVAL;
 	}
 	while (walk-res < MSDOS_NAME) *walk++ = ' ';
 	if (!opts->atari)
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Sun Apr 14 12:16:57 2002
+++ b/fs/namei.c	Sun Apr 14 12:16:57 2002
@@ -881,6 +881,8 @@
 			return -EBUSY;
 	} else if (S_ISDIR(victim->d_inode->i_mode))
 		return -EISDIR;
+	if (IS_DEADDIR(dir))
+		return -ENOENT;
 	return 0;
 }
 
@@ -986,6 +988,80 @@
 	return error;
 }
 
+int may_open(struct nameidata *nd, int acc_mode, int flag)
+{
+	struct dentry *dentry = nd->dentry;
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	if (!inode)
+		return -ENOENT;
+
+	if (S_ISLNK(inode->i_mode))
+		return -ELOOP;
+	
+	if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
+		return -EISDIR;
+
+	error = permission(inode, acc_mode);
+	if (error)
+		return error;
+
+	/*
+	 * FIFO's, sockets and device files are special: they don't
+	 * actually live on the filesystem itself, and as such you
+	 * can write to them even if the filesystem is read-only.
+	 */
+	if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+	    	flag &= ~O_TRUNC;
+	} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
+		if (nd->mnt->mnt_flags & MNT_NODEV)
+			return -EACCES;
+
+		flag &= ~O_TRUNC;
+	} else if (IS_RDONLY(inode) && (flag & FMODE_WRITE))
+		return -EROFS;
+	/*
+	 * An append-only file must be opened in append mode for writing.
+	 */
+	if (IS_APPEND(inode)) {
+		if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
+			return -EPERM;
+		if (flag & O_TRUNC)
+			return -EPERM;
+	}
+
+	/*
+	 * Ensure there are no outstanding leases on the file.
+	 */
+	error = get_lease(inode, flag);
+	if (error)
+		return error;
+
+	if (flag & O_TRUNC) {
+		error = get_write_access(inode);
+		if (error)
+			return error;
+
+		/*
+		 * Refuse to truncate files with mandatory locks held on them.
+		 */
+		error = locks_verify_locked(inode);
+		if (!error) {
+			DQUOT_INIT(inode);
+			
+			error = do_truncate(dentry, 0);
+		}
+		put_write_access(inode);
+		if (error)
+			return error;
+	} else
+		if (flag & FMODE_WRITE)
+			DQUOT_INIT(inode);
+
+	return 0;
+}
+
 /*
  *	open_namei()
  *
@@ -1003,7 +1079,6 @@
 int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
 {
 	int acc_mode, error = 0;
-	struct inode *inode;
 	struct dentry *dentry;
 	struct dentry *dir;
 	int count = 0;
@@ -1090,80 +1165,9 @@
 	if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
 		goto exit;
 ok:
-	error = -ENOENT;
-	inode = dentry->d_inode;
-	if (!inode)
-		goto exit;
-
-	error = -ELOOP;
-	if (S_ISLNK(inode->i_mode))
-		goto exit;
-	
-	error = -EISDIR;
-	if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
-		goto exit;
-
-	error = permission(inode,acc_mode);
-	if (error)
-		goto exit;
-
-	/*
-	 * FIFO's, sockets and device files are special: they don't
-	 * actually live on the filesystem itself, and as such you
-	 * can write to them even if the filesystem is read-only.
-	 */
-	if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
-	    	flag &= ~O_TRUNC;
-	} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
-		error = -EACCES;
-		if (nd->mnt->mnt_flags & MNT_NODEV)
-			goto exit;
-
-		flag &= ~O_TRUNC;
-	} else {
-		error = -EROFS;
-		if (IS_RDONLY(inode) && (flag & 2))
-			goto exit;
-	}
-	/*
-	 * An append-only file must be opened in append mode for writing.
-	 */
-	error = -EPERM;
-	if (IS_APPEND(inode)) {
-		if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
-			goto exit;
-		if (flag & O_TRUNC)
-			goto exit;
-	}
-
-	/*
-	 * Ensure there are no outstanding leases on the file.
-	 */
-	error = get_lease(inode, flag);
+	error = may_open(nd, acc_mode, flag);
 	if (error)
 		goto exit;
-
-	if (flag & O_TRUNC) {
-		error = get_write_access(inode);
-		if (error)
-			goto exit;
-
-		/*
-		 * Refuse to truncate files with mandatory locks held on them.
-		 */
-		error = locks_verify_locked(inode);
-		if (!error) {
-			DQUOT_INIT(inode);
-			
-			error = do_truncate(dentry, 0);
-		}
-		put_write_access(inode);
-		if (error)
-			goto exit;
-	} else
-		if (flag & FMODE_WRITE)
-			DQUOT_INIT(inode);
-
 	return 0;
 
 exit_dput:
@@ -1390,9 +1394,7 @@
 
 	down(&dentry->d_inode->i_sem);
 	d_unhash(dentry);
-	if (IS_DEADDIR(dir))
-		error = -ENOENT;
-	else if (d_mountpoint(dentry))
+	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
 		error = dir->i_op->rmdir(dir, dentry);
@@ -1776,8 +1778,6 @@
 	if (!old_dir->i_op || !old_dir->i_op->rename)
 		return -EPERM;
 
-	if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
-		return -ENOENT;
 	DQUOT_INIT(old_dir);
 	DQUOT_INIT(new_dir);
 
diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
--- a/fs/ncpfs/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/ncpfs/inode.c	Sun Apr 14 12:16:59 2002
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 
 #include <linux/ncp_fs.h>
 
@@ -592,6 +593,8 @@
 
 	result = -EIO;
 
+	lock_kernel();	
+
 	server = NCP_SERVER(inode);
 	if ((!server) || !ncp_conn_valid(server))
 		goto out;
@@ -636,7 +639,8 @@
 				info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
                 } else if (!S_ISREG(inode->i_mode))
                 {
-                        return -EPERM;
+			result = -EPERM;
+			goto out;
                 }
                 else
                 {
@@ -722,7 +726,8 @@
 			attr->ia_size);
 
 		if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
-			return -EACCES;
+			result = -EACCES;
+			goto out;
 		}
 		ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
 			  attr->ia_size, 0, "", &written);
@@ -735,6 +740,7 @@
 			result = vmtruncate(inode, attr->ia_size);
 	}
 out:
+	unlock_kernel();
 	return result;
 }
 
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nfs/inode.c	Sun Apr 14 12:16:59 2002
@@ -72,7 +72,9 @@
 /*
  * RPC cruft for NFS
  */
-struct rpc_stat			nfs_rpcstat = { &nfs_program };
+struct rpc_stat			nfs_rpcstat = {
+	program:		&nfs_program
+};
 static struct rpc_version *	nfs_version[] = {
 	NULL,
 	NULL,
@@ -83,11 +85,11 @@
 };
 
 struct rpc_program		nfs_program = {
-	"nfs",
-	NFS_PROGRAM,
-	sizeof(nfs_version) / sizeof(nfs_version[0]),
-	nfs_version,
-	&nfs_rpcstat,
+	name:			"nfs",
+	number:			NFS_PROGRAM,
+	nrvers:			sizeof(nfs_version) / sizeof(nfs_version[0]),
+	version:		nfs_version,
+	stats:			&nfs_rpcstat,
 };
 
 static inline unsigned long
@@ -633,7 +635,10 @@
 static struct inode *
 __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
-	struct nfs_find_desc desc = { fh, fattr };
+	struct nfs_find_desc desc = {
+		fh:	fh,
+		fattr:	fattr
+	};
 	struct inode *inode = NULL;
 	unsigned long ino;
 
@@ -728,6 +733,8 @@
 	struct nfs_fattr fattr;
 	int error;
 
+	lock_kernel();
+
 	/*
 	 * Make sure the inode is up-to-date.
 	 */
@@ -776,6 +783,7 @@
 	NFS_CACHEINV(inode);
 	error = nfs_refresh_inode(inode, &fattr);
 out:
+	unlock_kernel();
 	return error;
 }
 
diff -Nru a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
--- a/fs/nfs/mount_clnt.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nfs/mount_clnt.c	Sun Apr 14 12:16:55 2002
@@ -59,7 +59,9 @@
 nfs_gen_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh, int version)
 {
 	struct rpc_clnt		*mnt_clnt;
-	struct mnt_fhstatus	result = { 0, fh };
+	struct mnt_fhstatus	result = {
+		fh:		fh
+	};
 	char			hostname[32];
 	int			status;
 	int			call;
@@ -151,32 +153,40 @@
 #define MNT_fhstatus_sz		(1 + 8)
 
 static struct rpc_procinfo	mnt_procedures[2] = {
-	{ "mnt_null",
-		(kxdrproc_t) xdr_error,	
-		(kxdrproc_t) xdr_error,	0, 0 },
-	{ "mnt_mount",
-		(kxdrproc_t) xdr_encode_dirpath,	
-		(kxdrproc_t) xdr_decode_fhstatus,
-		MNT_dirpath_sz << 2, 0 },
+	{ p_procname:		"mnt_null",
+	  p_encode:		(kxdrproc_t) xdr_error,	
+	  p_decode:		(kxdrproc_t) xdr_error,
+	},
+	{ p_procname:		"mnt_mount",
+	  p_encode:		(kxdrproc_t) xdr_encode_dirpath,	
+	  p_decode:		(kxdrproc_t) xdr_decode_fhstatus,
+	  p_bufsiz:		MNT_dirpath_sz << 2,
+	},
 };
 
 static struct rpc_procinfo mnt3_procedures[2] = {
-	{ "mnt3_null",
-		(kxdrproc_t) xdr_error,
-		(kxdrproc_t) xdr_error, 0, 0 },
-	{ "mnt3_mount",
-		(kxdrproc_t) xdr_encode_dirpath,
-		(kxdrproc_t) xdr_decode_fhstatus3,
-		MNT_dirpath_sz << 2, 0 },
+	{ p_procname:		"mnt3_null",
+	  p_encode:		(kxdrproc_t) xdr_error,
+	  p_decode:		(kxdrproc_t) xdr_error,
+	},
+	{ p_procname:		"mnt3_mount",
+	  p_encode:		(kxdrproc_t) xdr_encode_dirpath,
+	  p_decode:		(kxdrproc_t) xdr_decode_fhstatus3,
+	  p_bufsiz:		MNT_dirpath_sz << 2,
+	},
 };
 
 
 static struct rpc_version	mnt_version1 = {
-	1, 2, mnt_procedures
+		number:		1,
+		nrprocs: 	2,
+		procs: 		mnt_procedures
 };
 
 static struct rpc_version       mnt_version3 = {
-	3, 2, mnt3_procedures
+		number:		3,
+		nrprocs:	2,
+		procs:		mnt3_procedures
 };
 
 static struct rpc_version *	mnt_version[] = {
@@ -189,9 +199,9 @@
 static struct rpc_stat		mnt_stats;
 
 struct rpc_program	mnt_program = {
-	"mount",
-	NFS_MNT_PROGRAM,
-	sizeof(mnt_version)/sizeof(mnt_version[0]),
-	mnt_version,
-	&mnt_stats,
+	name:		"mount",
+	number:		NFS_MNT_PROGRAM,
+	nrvers:		sizeof(mnt_version)/sizeof(mnt_version[0]),
+	version:	mnt_version,
+	stats:		&mnt_stats,
 };
diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
--- a/fs/nfs/nfs2xdr.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nfs/nfs2xdr.c	Sun Apr 14 12:16:57 2002
@@ -762,7 +762,7 @@
 };
 
 struct rpc_version		nfs_version2 = {
-	2,
-	sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
-	nfs_procedures
+	number:			2,
+	nrprocs:		sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
+	procs:			nfs_procedures
 };
diff -Nru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
--- a/fs/nfs/nfs3proc.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nfs/nfs3proc.c	Sun Apr 14 12:16:58 2002
@@ -39,7 +39,11 @@
 static inline int
 nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
-	struct rpc_message msg = { proc, argp, resp, NULL };
+	struct rpc_message msg = {
+		rpc_proc:	proc,
+		rpc_argp:	argp,
+		rpc_resp:	resp,
+	};
 	return nfs3_rpc_wrapper(clnt, &msg, flags);
 }
 
@@ -84,7 +88,10 @@
 nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
 			struct iattr *sattr)
 {
-	struct nfs3_sattrargs	arg = { NFS_FH(inode), sattr, 0, 0 };
+	struct nfs3_sattrargs	arg = {
+		fh:		NFS_FH(inode),
+		sattr:		sattr,
+	};
 	int	status;
 
 	dprintk("NFS call  setattr\n");
@@ -99,8 +106,16 @@
 		 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_diropargs	arg = { NFS_FH(dir), name->name, name->len };
-	struct nfs3_diropres	res = { &dir_attr, fhandle, fattr };
+	struct nfs3_diropargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len
+	};
+	struct nfs3_diropres	res = {
+		dir_attr:	&dir_attr,
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	dprintk("NFS call  lookup %s\n", name->name);
@@ -120,8 +135,12 @@
 nfs3_proc_access(struct inode *inode, int mode, int ruid)
 {
 	struct nfs_fattr	fattr;
-	struct nfs3_accessargs	arg = { NFS_FH(inode), 0 };
-	struct nfs3_accessres	res = { &fattr, 0 };
+	struct nfs3_accessargs	arg = {
+		fh:		NFS_FH(inode),
+	};
+	struct nfs3_accessres	res = {
+		fattr:		&fattr,
+	};
 	int	status, flags;
 
 	dprintk("NFS call  access\n");
@@ -154,8 +173,16 @@
 nfs3_proc_readlink(struct inode *inode, void *buffer, unsigned int buflen)
 {
 	struct nfs_fattr	fattr;
-	struct nfs3_readlinkargs args = { NFS_FH(inode), buffer, buflen };
-	struct nfs3_readlinkres	res = { &fattr, buffer, buflen };
+	struct nfs3_readlinkargs args = {
+		fh:		NFS_FH(inode),
+		buffer:		buffer,
+		bufsiz:		buflen
+	};
+	struct nfs3_readlinkres	res = {
+		fattr:		&fattr,
+		buffer:		buffer,
+		bufsiz:		buflen
+	};
 	int			status;
 
 	dprintk("NFS call  readlink\n");
@@ -172,11 +199,23 @@
 	       struct nfs_fattr *fattr, int flags,
 	       loff_t offset, unsigned int count, void *buffer, int *eofp)
 {
-	struct nfs_readargs	arg = { NFS_FH(inode), offset, count, 1,
-					{{buffer, count}, {0,0}, {0,0}, {0,0},
-					 {0,0}, {0,0}, {0,0}, {0,0}} };
-	struct nfs_readres	res = { fattr, count, 0 };
-	struct rpc_message	msg = { NFS3PROC_READ, &arg, &res, cred };
+	struct nfs_readargs	arg = {
+		fh:		NFS_FH(inode),
+		offset:		offset,
+		count:		count,
+		nriov:		1,
+		iov:		{{buffer, count}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
+	};
+	struct nfs_readres	res = {
+		fattr:		fattr,
+		count:		count,
+	};
+	struct rpc_message	msg = {
+		rpc_proc:	NFS3PROC_READ,
+		rpc_argp:	&arg,
+		rpc_resp:	&res,
+		rpc_cred:	cred
+	};
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
@@ -193,12 +232,24 @@
 		loff_t offset, unsigned int count,
 		void *buffer, struct nfs_writeverf *verf)
 {
-	struct nfs_writeargs	arg = { NFS_FH(inode), offset, count,
-					NFS_FILE_SYNC, 1,
-					{{buffer, count}, {0,0}, {0,0}, {0,0},
-					 {0,0}, {0,0}, {0,0}, {0,0}} };
-	struct nfs_writeres	res = { fattr, verf, 0 };
-	struct rpc_message	msg = { NFS3PROC_WRITE, &arg, &res, cred };
+	struct nfs_writeargs	arg = {
+		fh:		NFS_FH(inode),
+		offset:		offset,
+		count:		count,
+		stable:		NFS_FILE_SYNC,
+		nriov:		1,
+		iov:		{{buffer, count}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
+	};
+	struct nfs_writeres	res = {
+		fattr:		fattr,
+		verf:		verf,
+	};
+	struct rpc_message	msg = {
+		rpc_proc:	NFS3PROC_WRITE,
+		rpc_argp:	&arg,
+		rpc_resp:	&res,
+		rpc_cred:	cred
+	};
 	int			status, rpcflags = 0;
 
 	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
@@ -222,9 +273,17 @@
 		 int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_createargs	arg = { NFS_FH(dir), name->name, name->len,
-					sattr, 0, { 0, 0 } };
-	struct nfs3_diropres	res = { &dir_attr, fhandle, fattr };
+	struct nfs3_createargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len,
+		sattr:		sattr,
+	};
+	struct nfs3_diropres	res = {
+		dir_attr:	&dir_attr,
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	dprintk("NFS call  create %s\n", name->name);
@@ -265,7 +324,10 @@
 	/* When we created the file with exclusive semantics, make
 	 * sure we set the attributes afterwards. */
 	if (status == 0 && arg.createmode == NFS3_CREATE_EXCLUSIVE) {
-		struct nfs3_sattrargs	arg = { fhandle, sattr, 0, 0 };
+		struct nfs3_sattrargs	arg = {
+			fh:		fhandle,
+			sattr:		sattr,
+		};
 		dprintk("NFS call  setattr (post-create)\n");
 
 		/* Note: we could use a guarded setattr here, but I'm
@@ -284,8 +346,16 @@
 nfs3_proc_remove(struct inode *dir, struct qstr *name)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_diropargs	arg = { NFS_FH(dir), name->name, name->len };
-	struct rpc_message	msg = { NFS3PROC_REMOVE, &arg, &dir_attr, NULL };
+	struct nfs3_diropargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len
+	};
+	struct rpc_message	msg = {
+		rpc_proc:	NFS3PROC_REMOVE,
+		rpc_argp:	&arg,
+		rpc_resp:	&dir_attr,
+	};
 	int			status;
 
 	dprintk("NFS call  remove %s\n", name->name);
@@ -333,11 +403,18 @@
 		 struct inode *new_dir, struct qstr *new_name)
 {
 	struct nfs_fattr	old_dir_attr, new_dir_attr;
-	struct nfs3_renameargs	arg = { NFS_FH(old_dir),
-					old_name->name, old_name->len,
-					NFS_FH(new_dir),
-					new_name->name, new_name->len };
-	struct nfs3_renameres	res = { &old_dir_attr, &new_dir_attr };
+	struct nfs3_renameargs	arg = {
+		fromfh:		NFS_FH(old_dir),
+		fromname:	old_name->name,
+		fromlen:	old_name->len,
+		tofh:		NFS_FH(new_dir),
+		toname:		new_name->name,
+		tolen:		new_name->len
+	};
+	struct nfs3_renameres	res = {
+		fromattr:	&old_dir_attr,
+		toattr:		&new_dir_attr
+	};
 	int			status;
 
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
@@ -354,9 +431,16 @@
 nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
 	struct nfs_fattr	dir_attr, fattr;
-	struct nfs3_linkargs	arg = { NFS_FH(inode), NFS_FH(dir),
-					name->name, name->len };
-	struct nfs3_linkres	res = { &dir_attr, &fattr };
+	struct nfs3_linkargs	arg = {
+		fromfh:		NFS_FH(inode),
+		tofh:		NFS_FH(dir),
+		toname:		name->name,
+		tolen:		name->len
+	};
+	struct nfs3_linkres	res = {
+		dir_attr:	&dir_attr,
+		fattr:		&fattr
+	};
 	int			status;
 
 	dprintk("NFS call  link %s\n", name->name);
@@ -375,9 +459,19 @@
 		  struct nfs_fattr *fattr)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_symlinkargs	arg = { NFS_FH(dir), name->name, name->len,
-					path->name, path->len, sattr };
-	struct nfs3_diropres	res = { &dir_attr, fhandle, fattr };
+	struct nfs3_symlinkargs	arg = {
+		fromfh:		NFS_FH(dir),
+		fromname:	name->name,
+		fromlen:	name->len,
+		topath:		path->name,
+		tolen:		path->len,
+		sattr:		sattr
+	};
+	struct nfs3_diropres	res = {
+		dir_attr:	&dir_attr,
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
@@ -394,9 +488,17 @@
 		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_mkdirargs	arg = { NFS_FH(dir), name->name, name->len,
-					sattr };
-	struct nfs3_diropres	res = { &dir_attr, fhandle, fattr };
+	struct nfs3_mkdirargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len,
+		sattr:		sattr
+	};
+	struct nfs3_diropres	res = {
+		dir_attr:	&dir_attr,
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	dprintk("NFS call  mkdir %s\n", name->name);
@@ -412,7 +514,11 @@
 nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_diropargs	arg = { NFS_FH(dir), name->name, name->len };
+	struct nfs3_diropargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len
+	};
 	int			status;
 
 	dprintk("NFS call  rmdir %s\n", name->name);
@@ -438,9 +544,19 @@
 		  unsigned int size, int plus)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_readdirargs	arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 };
-	struct nfs3_readdirres	res = { &dir_attr, 0, 0, 0, 0 };
-	struct rpc_message	msg = { NFS3PROC_READDIR, &arg, &res, cred };
+	struct nfs3_readdirargs	arg = {
+		fh:		NFS_FH(dir),
+		cookie:		cookie,
+	};
+	struct nfs3_readdirres	res = {
+		dir_attr:	&dir_attr,
+	};
+	struct rpc_message	msg = {
+		rpc_proc:	NFS3PROC_READDIR,
+		rpc_argp:	&arg,
+		rpc_resp:	&res,
+		rpc_cred:	cred
+	};
 	u32			*verf = NFS_COOKIEVERF(dir);
 	int			status;
 
@@ -472,9 +588,18 @@
 		dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
 	struct nfs_fattr	dir_attr;
-	struct nfs3_mknodargs	arg = { NFS_FH(dir), name->name, name->len, 0,
-					sattr, rdev };
-	struct nfs3_diropres	res = { &dir_attr, fh, fattr };
+	struct nfs3_mknodargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len,
+		sattr:		sattr,
+		rdev:		rdev
+	};
+	struct nfs3_diropres	res = {
+		dir_attr:	&dir_attr,
+		fh:		fh,
+		fattr:		fattr
+	};
 	int			status;
 
 	switch (sattr->ia_mode & S_IFMT) {
@@ -518,27 +643,26 @@
 extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
 
 struct nfs_rpc_ops	nfs_v3_clientops = {
-	3,			/* protocol version */
-	nfs3_proc_get_root,
-	nfs3_proc_getattr,
-	nfs3_proc_setattr,
-	nfs3_proc_lookup,
-	nfs3_proc_access,
-	nfs3_proc_readlink,
-	nfs3_proc_read,
-	nfs3_proc_write,
-	NULL,			/* commit */
-	nfs3_proc_create,
-	nfs3_proc_remove,
-	nfs3_proc_unlink_setup,
-	nfs3_proc_unlink_done,
-	nfs3_proc_rename,
-	nfs3_proc_link,
-	nfs3_proc_symlink,
-	nfs3_proc_mkdir,
-	nfs3_proc_rmdir,
-	nfs3_proc_readdir,
-	nfs3_proc_mknod,
-	nfs3_proc_statfs,
-	nfs3_decode_dirent,
+	version:	3,			/* protocol version */
+	getroot:	nfs3_proc_get_root,
+	getattr:	nfs3_proc_getattr,
+	setattr:	nfs3_proc_setattr,
+	lookup:		nfs3_proc_lookup,
+	access:		nfs3_proc_access,
+	readlink:	nfs3_proc_readlink,
+	read:		nfs3_proc_read,
+	write:		nfs3_proc_write,
+	create:		nfs3_proc_create,
+	remove:		nfs3_proc_remove,
+	unlink_setup:	nfs3_proc_unlink_setup,
+	unlink_done:	nfs3_proc_unlink_done,
+	rename:		nfs3_proc_rename,
+	link:		nfs3_proc_link,
+	symlink:	nfs3_proc_symlink,
+	mkdir:		nfs3_proc_mkdir,
+	rmdir:		nfs3_proc_rmdir,
+	readdir:	nfs3_proc_readdir,
+	mknod:		nfs3_proc_mknod,
+	statfs:		nfs3_proc_statfs,
+	decode_dirent:	nfs3_decode_dirent,
 };
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nfs/nfs3xdr.c	Sun Apr 14 12:16:58 2002
@@ -1085,8 +1085,8 @@
 };
 
 struct rpc_version		nfs_version3 = {
-	3,
-	sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
-	nfs3_procedures
+	number:			3,
+	nrprocs:		sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
+	procs:			nfs3_procedures
 };
 
diff -Nru a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
--- a/fs/nfs/nfsroot.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nfs/nfsroot.c	Sun Apr 14 12:16:59 2002
@@ -202,8 +202,9 @@
 
 	if ((options = strchr(name, ','))) {
 		*options++ = 0;
-		cp = strtok(options, ",");
-		while (cp) {
+		while ((cp = strsep(&options, ",")) != NULL) {
+			if (!*cp)
+				continue;
 			if ((val = strchr(cp, '='))) {
 				struct nfs_int_opts *opts = root_int_opts;
 				*val++ = '\0';
@@ -220,7 +221,6 @@
 					nfs_data.flags |= opts->or_mask;
 				}
 			}
-			cp = strtok(NULL, ",");
 		}
 	}
 	if (name[0] && strcmp(name, "default")) {
diff -Nru a/fs/nfs/proc.c b/fs/nfs/proc.c
--- a/fs/nfs/proc.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nfs/proc.c	Sun Apr 14 12:16:57 2002
@@ -80,7 +80,10 @@
 nfs_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
 		 struct iattr *sattr)
 {
-	struct nfs_sattrargs	arg = { NFS_FH(inode), sattr };
+	struct nfs_sattrargs	arg = { 
+		fh:	NFS_FH(inode),
+		sattr:	sattr
+	};
 	int	status;
 
 	dprintk("NFS call  setattr\n");
@@ -94,8 +97,15 @@
 nfs_proc_lookup(struct inode *dir, struct qstr *name,
 		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	struct nfs_diropargs	arg = { NFS_FH(dir), name->name, name->len };
-	struct nfs_diropok	res = { fhandle, fattr };
+	struct nfs_diropargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len
+	};
+	struct nfs_diropok	res = {
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	dprintk("NFS call  lookup %s\n", name->name);
@@ -108,8 +118,15 @@
 static int
 nfs_proc_readlink(struct inode *inode, void *buffer, unsigned int bufsiz)
 {
-	struct nfs_readlinkargs	args = { NFS_FH(inode), buffer, bufsiz };
-	struct nfs_readlinkres	res = { buffer, bufsiz };
+	struct nfs_readlinkargs	args = {
+		fh:		NFS_FH(inode),
+		buffer:		buffer,
+		bufsiz:		bufsiz
+	};
+	struct nfs_readlinkres	res = {
+		buffer:		buffer,
+		bufsiz:		bufsiz
+	};
 	int			status;
 
 	dprintk("NFS call  readlink\n");
@@ -124,11 +141,23 @@
 	      struct nfs_fattr *fattr, int flags,
 	      loff_t offset, unsigned int count, void *buffer, int *eofp)
 {
-	struct nfs_readargs	arg = { NFS_FH(inode), offset, count, 1,
-				       {{ buffer, count }, {0,0}, {0,0}, {0,0},
-					{0,0}, {0,0}, {0,0}, {0,0}} };
-	struct nfs_readres	res = { fattr, count, 0};
-	struct rpc_message	msg = { NFSPROC_READ, &arg, &res, cred };
+	struct nfs_readargs	arg = {
+		fh:		NFS_FH(inode),
+		offset:		offset,
+		count:		count,
+		nriov:		1,
+		iov:		{{ buffer, count }, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
+	};
+	struct nfs_readres	res = {
+		fattr:		fattr,
+		count:		count
+	};
+	struct rpc_message	msg = {
+		rpc_proc:	NFSPROC_READ,
+		rpc_argp:	&arg,
+		rpc_resp:	&res,
+		rpc_cred:	cred
+	};
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
@@ -146,12 +175,25 @@
 	       loff_t offset, unsigned int count,
 	       void *buffer, struct nfs_writeverf *verf)
 {
-	struct nfs_writeargs	arg = {NFS_FH(inode), offset, count,
-					NFS_FILE_SYNC, 1,
-					{{buffer, count}, {0,0}, {0,0}, {0,0},
-					 {0,0}, {0,0}, {0,0}, {0,0}}};
-	struct nfs_writeres     res = {fattr, verf, count};
-	struct rpc_message	msg = { NFSPROC_WRITE, &arg, &res, cred };
+	struct nfs_writeargs	arg = {
+		fh:		NFS_FH(inode),
+		offset:		offset,
+		count:		count,
+		stable:		NFS_FILE_SYNC,
+		nriov:		1,
+		iov:		{{buffer, count}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
+	};
+	struct nfs_writeres     res = {
+		fattr:		fattr,
+		verf:		verf,
+		count:		count
+	};
+	struct rpc_message	msg = {
+		rpc_proc:	NFSPROC_WRITE,
+		rpc_argp:	&arg,
+		rpc_resp:	&res,
+		rpc_cred:	cred
+	};
 	int			status, flags = 0;
 
 	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
@@ -169,9 +211,16 @@
 nfs_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
 		int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	struct nfs_createargs	arg = { NFS_FH(dir), name->name,
-					name->len, sattr };
-	struct nfs_diropok	res = { fhandle, fattr };
+	struct nfs_createargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len,
+		sattr:		sattr
+	};
+	struct nfs_diropok	res = {
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	fattr->valid = 0;
@@ -188,9 +237,16 @@
 nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
 	       dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	struct nfs_createargs	arg = { NFS_FH(dir), name->name,
-						     name->len, sattr };
-	struct nfs_diropok	res = { fhandle, fattr };
+	struct nfs_createargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len,
+		sattr:		sattr
+	};
+	struct nfs_diropok	res = {
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status, mode;
 
 	dprintk("NFS call  mknod %s\n", name->name);
@@ -219,8 +275,17 @@
 static int
 nfs_proc_remove(struct inode *dir, struct qstr *name)
 {
-	struct nfs_diropargs	arg = { NFS_FH(dir), name->name, name->len };
-	struct rpc_message	msg = { NFSPROC_REMOVE, &arg, NULL, NULL };
+	struct nfs_diropargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len
+	};
+	struct rpc_message	msg = { 
+		rpc_proc:	NFSPROC_REMOVE,
+		rpc_argp:	&arg,
+		rpc_resp:	NULL,
+		rpc_cred:	NULL
+	};
 	int			status;
 
 	dprintk("NFS call  remove %s\n", name->name);
@@ -259,10 +324,14 @@
 nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		struct inode *new_dir, struct qstr *new_name)
 {
-	struct nfs_renameargs	arg = { NFS_FH(old_dir), old_name->name,
-					old_name->len,
-					NFS_FH(new_dir), new_name->name,
-					new_name->len};
+	struct nfs_renameargs	arg = {
+		fromfh:		NFS_FH(old_dir),
+		fromname:	old_name->name,
+		fromlen:	old_name->len,
+		tofh:		NFS_FH(new_dir),
+		toname:		new_name->name,
+		tolen:		new_name->len
+	};
 	int			status;
 
 	dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
@@ -274,8 +343,12 @@
 static int
 nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
-	struct nfs_linkargs	arg = { NFS_FH(inode), NFS_FH(dir),
-					name->name, name->len };
+	struct nfs_linkargs	arg = {
+		fromfh:		NFS_FH(inode),
+		tofh:		NFS_FH(dir),
+		toname:		name->name,
+		tolen:		name->len
+	};
 	int			status;
 
 	dprintk("NFS call  link %s\n", name->name);
@@ -289,8 +362,14 @@
 		 struct iattr *sattr, struct nfs_fh *fhandle,
 		 struct nfs_fattr *fattr)
 {
-	struct nfs_symlinkargs	arg = { NFS_FH(dir), name->name, name->len,
-					path->name, path->len, sattr };
+	struct nfs_symlinkargs	arg = {
+		fromfh:		NFS_FH(dir),
+		fromname:	name->name,
+		fromlen:	name->len,
+		topath:		path->name,
+		tolen:		path->len,
+		sattr:		sattr
+	};
 	int			status;
 
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
@@ -304,9 +383,16 @@
 nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
 	       struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	struct nfs_createargs	arg = { NFS_FH(dir), name->name, name->len,
-					sattr };
-	struct nfs_diropok	res = { fhandle, fattr };
+	struct nfs_createargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len,
+		sattr:		sattr
+	};
+	struct nfs_diropok	res = {
+		fh:		fhandle,
+		fattr:		fattr
+	};
 	int			status;
 
 	dprintk("NFS call  mkdir %s\n", name->name);
@@ -319,7 +405,11 @@
 static int
 nfs_proc_rmdir(struct inode *dir, struct qstr *name)
 {
-	struct nfs_diropargs	arg = { NFS_FH(dir), name->name, name->len };
+	struct nfs_diropargs	arg = {
+		fh:		NFS_FH(dir),
+		name:		name->name,
+		len:		name->len
+	};
 	int			status;
 
 	dprintk("NFS call  rmdir %s\n", name->name);
@@ -342,7 +432,12 @@
 {
 	struct nfs_readdirargs	arg;
 	struct nfs_readdirres	res;
-	struct rpc_message	msg = { NFSPROC_READDIR, &arg, &res, cred };
+	struct rpc_message	msg = {
+		rpc_proc:	NFSPROC_READDIR,
+		rpc_argp:	&arg,
+		rpc_resp:	&res,
+		rpc_cred:	cred
+	};
 	int			status;
 
 	arg.fh = NFS_FH(dir);
@@ -374,28 +469,28 @@
 
 extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
 
-struct nfs_rpc_ops     nfs_v2_clientops = {
-       2,		       /* protocol version */
-       nfs_proc_get_root,
-       nfs_proc_getattr,
-       nfs_proc_setattr,
-       nfs_proc_lookup,
-       NULL,		       /* access */
-       nfs_proc_readlink,
-       nfs_proc_read,
-       nfs_proc_write,
-       NULL,		       /* commit */
-       nfs_proc_create,
-       nfs_proc_remove,
-       nfs_proc_unlink_setup,
-       nfs_proc_unlink_done,
-       nfs_proc_rename,
-       nfs_proc_link,
-       nfs_proc_symlink,
-       nfs_proc_mkdir,
-       nfs_proc_rmdir,
-       nfs_proc_readdir,
-       nfs_proc_mknod,
-       nfs_proc_statfs,
-       nfs_decode_dirent,
+struct nfs_rpc_ops	nfs_v2_clientops = {
+	version:	2,		       /* protocol version */
+	getroot:	nfs_proc_get_root,
+	getattr:	nfs_proc_getattr,
+	setattr:	nfs_proc_setattr,
+	lookup:		nfs_proc_lookup,
+	access:		NULL,		       /* access */
+	readlink:	nfs_proc_readlink,
+	read:		nfs_proc_read,
+	write:		nfs_proc_write,
+	commit:		NULL,		       /* commit */
+	create:		nfs_proc_create,
+	remove:		nfs_proc_remove,
+	unlink_setup:	nfs_proc_unlink_setup,
+	unlink_done:	nfs_proc_unlink_done,
+	rename:		nfs_proc_rename,
+	link:		nfs_proc_link,
+	symlink:	nfs_proc_symlink,
+	mkdir:		nfs_proc_mkdir,
+	rmdir:		nfs_proc_rmdir,
+	readdir:	nfs_proc_readdir,
+	mknod:		nfs_proc_mknod,
+	statfs:		nfs_proc_statfs,
+	decode_dirent:	nfs_decode_dirent,
 };
diff -Nru a/fs/nfsctl.c b/fs/nfsctl.c
--- a/fs/nfsctl.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nfsctl.c	Sun Apr 14 12:16:58 2002
@@ -37,7 +37,16 @@
 	if (error)
 		return ERR_PTR(error);
 
-	return dentry_open(nd.dentry, nd.mnt, flags);
+	if (flags == O_RDWR)
+		error = may_open(&nd,MAY_READ|MAY_WRITE,FMODE_READ|FMODE_WRITE);
+	else
+		error = may_open(&nd, MAY_WRITE, FMODE_WRITE);
+
+	if (!error)
+		return dentry_open(nd.dentry, nd.mnt, flags);
+
+	path_release(&nd);
+	return ERR_PTR(error);
 }
 
 static struct {
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nfsd/export.c	Sun Apr 14 12:16:59 2002
@@ -304,9 +304,21 @@
 		goto finish;
 
 	err = -EINVAL;
-	if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) ||
-	    (inode->i_sb->s_op->read_inode == NULL
-	     && inode->i_sb->s_op->fh_to_dentry == NULL)) {
+	/* There are two requirements on a filesystem to be exportable.
+	 * 1:  We must be able to identify the filesystem from a number.
+	 *       either a device number (so FS_REQUIRES_DEV needed)
+	 *       or an FSID number (so NFSEXP_FSID needed).
+	 * 2:  We must be able to find an inode from a filehandle.
+	 *       either using fh_to_dentry (prefered)
+	 *       or using read_inode (the hack).
+	 */
+	if (((inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV)
+	      || (nxp->ex_flags & NFSEXP_FSID))
+	    &&
+	    (inode->i_sb->s_op->read_inode
+	     || inode->i_sb->s_op->fh_to_dentry)) 
+		/* Ok, we can export it */;
+	else {
 		dprintk("exp_export: export of invalid fs type.\n");
 		goto finish;
 	}
diff -Nru a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
--- a/fs/nfsd/lockd.c	Sun Apr 14 12:16:56 2002
+++ b/fs/nfsd/lockd.c	Sun Apr 14 12:16:56 2002
@@ -61,12 +61,12 @@
 }
 
 struct nlmsvc_binding		nfsd_nlm_ops = {
-	exp_readlock,		/* lock export table for reading */
-	exp_readunlock,		/* unlock export table */
-	exp_getclient,		/* look up NFS client */
-	nlm_fopen,		/* open file for locking */
-	nlm_fclose,		/* close file */
-	exp_nlmdetach,		/* lockd shutdown notification */
+	exp_readlock:		exp_readlock,		/* lock export table for reading */
+	exp_unlock:		exp_readunlock,		/* unlock export table */
+	exp_getclient:		exp_getclient,		/* look up NFS client */
+	fopen:			nlm_fopen,		/* open file for locking */
+	fclose:			nlm_fclose,		/* close file */
+	detach:			exp_nlmdetach,		/* lockd shutdown notification */
 };
 
 /*
diff -Nru a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
--- a/fs/nfsd/nfs3proc.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nfsd/nfs3proc.c	Sun Apr 14 12:16:57 2002
@@ -658,27 +658,34 @@
    cache,					\
    respsize,					\
  }
+
+#define ST 1		/* status*/
+#define FH 17		/* filehandle with length */
+#define AT 21		/* attributes */
+#define pAT (1+AT)	/* post attributes - conditional */
+#define WC (7+pAT)	/* WCC attributes */
+
 struct svc_procedure		nfsd_procedures3[22] = {
-  PROC(null,	 void,		void,		void,	 RC_NOCACHE, 1),
-  PROC(getattr,	 fhandle,	attrstat,	fhandle, RC_NOCACHE, 1+21),
-  PROC(setattr,  sattr,		wccstat,	fhandle,  RC_REPLBUFF, 1+7+22),
-  PROC(lookup,	 dirop,		dirop,		fhandle2, RC_NOCACHE, 1+9+22+22),
-  PROC(access,	 access,	access,		fhandle,  RC_NOCACHE, 1+22+1),
-  PROC(readlink, fhandle,	readlink,	fhandle,  RC_NOCACHE, 1+22+1+256),
-  PROC(read,	 read,		read,		fhandle, RC_NOCACHE, 1+22+4+NFSSVC_MAXBLKSIZE),
-  PROC(write,	 write,		write,		fhandle,  RC_REPLBUFF, 1+7+22+4),
-  PROC(create,	 create,	create,		fhandle2, RC_REPLBUFF, 1+(1+9+22)+7+22),
-  PROC(mkdir,	 mkdir,		create,		fhandle2, RC_REPLBUFF, 1+(1+9+22)+7+22),
-  PROC(symlink,	 symlink,	create,		fhandle2, RC_REPLBUFF, 1+(1+9+22)+7+22),
-  PROC(mknod,	 mknod,		create,		fhandle2, RC_REPLBUFF, 1+(1+9+22)+7+22),
-  PROC(remove,	 dirop,		wccstat,	fhandle,  RC_REPLBUFF, 1+7+22),
-  PROC(rmdir,	 dirop,		wccstat,	fhandle,  RC_REPLBUFF, 1+7+22),
-  PROC(rename,	 rename,	rename,		fhandle2, RC_REPLBUFF, 1+7+22+7+22),
-  PROC(link,	 link,		link,		fhandle2, RC_REPLBUFF, 1+22+7+22),
+  PROC(null,	 void,		void,		void,	  RC_NOCACHE, ST),
+  PROC(getattr,	 fhandle,	attrstat,	fhandle,  RC_NOCACHE, ST+AT),
+  PROC(setattr,  sattr,		wccstat,	fhandle,  RC_REPLBUFF, ST+WC),
+  PROC(lookup,	 dirop,		dirop,		fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
+  PROC(access,	 access,	access,		fhandle,  RC_NOCACHE, ST+pAT+1),
+  PROC(readlink, fhandle,	readlink,	fhandle,  RC_NOCACHE, ST+pAT+1+256),
+  PROC(read,	 read,		read,		fhandle,  RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
+  PROC(write,	 write,		write,		fhandle,  RC_REPLBUFF, ST+WC+4),
+  PROC(create,	 create,	create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+  PROC(mkdir,	 mkdir,		create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+  PROC(symlink,	 symlink,	create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+  PROC(mknod,	 mknod,		create,		fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
+  PROC(remove,	 dirop,		wccstat,	fhandle,  RC_REPLBUFF, ST+WC),
+  PROC(rmdir,	 dirop,		wccstat,	fhandle,  RC_REPLBUFF, ST+WC),
+  PROC(rename,	 rename,	rename,		fhandle2, RC_REPLBUFF, ST+WC+WC),
+  PROC(link,	 link,		link,		fhandle2, RC_REPLBUFF, ST+pAT+WC),
   PROC(readdir,	 readdir,	readdir,	fhandle,  RC_NOCACHE, 0),
   PROC(readdirplus,readdirplus,	readdir,	fhandle,  RC_NOCACHE, 0),
-  PROC(fsstat,	 fhandle,	fsstat,		void,     RC_NOCACHE, 1+14),
-  PROC(fsinfo,   fhandle,	fsinfo,		void,     RC_NOCACHE, 1+13),
-  PROC(pathconf, fhandle,	pathconf,	void,     RC_NOCACHE, 1+6),
-  PROC(commit,	 commit,	commit,		fhandle,  RC_NOCACHE, 1+7+22+2),
+  PROC(fsstat,	 fhandle,	fsstat,		void,     RC_NOCACHE, ST+pAT+2*6+1),
+  PROC(fsinfo,   fhandle,	fsinfo,		void,     RC_NOCACHE, ST+pAT+12),
+  PROC(pathconf, fhandle,	pathconf,	void,     RC_NOCACHE, ST+pAT+6),
+  PROC(commit,	 commit,	commit,		fhandle,  RC_NOCACHE, ST+WC+2),
 };
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nfsd/nfs3xdr.c	Sun Apr 14 12:16:54 2002
@@ -154,9 +154,9 @@
 }
 
 static inline u32 *
-encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
+encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
 {
-	struct inode	*inode = dentry->d_inode;
+	struct inode	*inode = fhp->fh_dentry->d_inode;
 
 	*p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
 	*p++ = htonl((u32) inode->i_mode);
@@ -175,7 +175,12 @@
 		p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
 	*p++ = htonl((u32) major(inode->i_rdev));
 	*p++ = htonl((u32) minor(inode->i_rdev));
-	p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
+	if (rqstp->rq_reffh->fh_version == 1
+	    && rqstp->rq_reffh->fh_fsid_type == 1
+	    && (fhp->fh_export->ex_flags & NFSEXP_FSID))
+		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
+	else
+		p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, inode->i_atime);
 	p = encode_time3(p, lease_get_mtime(inode));
@@ -205,7 +210,12 @@
 	p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
 	*p++ = htonl((u32) major(fhp->fh_post_rdev));
 	*p++ = htonl((u32) minor(fhp->fh_post_rdev));
-	p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
+	if (rqstp->rq_reffh->fh_version == 1
+	    && rqstp->rq_reffh->fh_fsid_type == 1
+	    && (fhp->fh_export->ex_flags & NFSEXP_FSID))
+		p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
+	else
+		p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
 	p = xdr_encode_hyper(p, (u64) inode->i_ino);
 	p = encode_time3(p, fhp->fh_post_atime);
 	p = encode_time3(p, fhp->fh_post_mtime);
@@ -220,11 +230,12 @@
  * handle. In this case, no attributes are returned.
  */
 static u32 *
-encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
+encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
 {
+	struct dentry *dentry = fhp->fh_dentry;
 	if (dentry && dentry->d_inode != NULL) {
 		*p++ = xdr_one;		/* attributes follow */
-		return encode_fattr3(rqstp, p, dentry);
+		return encode_fattr3(rqstp, p, fhp);
 	}
 	*p++ = xdr_zero;
 	return p;
@@ -251,7 +262,7 @@
 	}
 	/* no pre- or post-attrs */
 	*p++ = xdr_zero;
-	return encode_post_op_attr(rqstp, p, dentry);
+	return encode_post_op_attr(rqstp, p, fhp);
 }
 
 /*
@@ -509,7 +520,7 @@
 					struct nfsd3_attrstat *resp)
 {
 	if (resp->status == 0)
-		p = encode_fattr3(rqstp, p, resp->fh.fh_dentry);
+		p = encode_fattr3(rqstp, p, &resp->fh);
 	return xdr_ressize_check(rqstp, p);
 }
 
@@ -529,9 +540,9 @@
 {
 	if (resp->status == 0) {
 		p = encode_fh(p, &resp->fh);
-		p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+		p = encode_post_op_attr(rqstp, p, &resp->fh);
 	}
-	p = encode_post_op_attr(rqstp, p, resp->dirfh.fh_dentry);
+	p = encode_post_op_attr(rqstp, p, &resp->dirfh);
 	return xdr_ressize_check(rqstp, p);
 }
 
@@ -540,7 +551,7 @@
 nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd3_accessres *resp)
 {
-	p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+	p = encode_post_op_attr(rqstp, p, &resp->fh);
 	if (resp->status == 0)
 		*p++ = htonl(resp->access);
 	return xdr_ressize_check(rqstp, p);
@@ -551,7 +562,7 @@
 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd3_readlinkres *resp)
 {
-	p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+	p = encode_post_op_attr(rqstp, p, &resp->fh);
 	if (resp->status == 0) {
 		*p++ = htonl(resp->len);
 		p += XDR_QUADLEN(resp->len);
@@ -564,7 +575,7 @@
 nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd3_readres *resp)
 {
-	p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+	p = encode_post_op_attr(rqstp, p, &resp->fh);
 	if (resp->status == 0) {
 		*p++ = htonl(resp->count);
 		*p++ = htonl(resp->eof);
@@ -597,7 +608,7 @@
 	if (resp->status == 0) {
 		*p++ = xdr_one;
 		p = encode_fh(p, &resp->fh);
-		p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+		p = encode_post_op_attr(rqstp, p, &resp->fh);
 	}
 	p = encode_wcc_data(rqstp, p, &resp->dirfh);
 	return xdr_ressize_check(rqstp, p);
@@ -618,7 +629,7 @@
 nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd3_linkres *resp)
 {
-	p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+	p = encode_post_op_attr(rqstp, p, &resp->fh);
 	p = encode_wcc_data(rqstp, p, &resp->tfh);
 	return xdr_ressize_check(rqstp, p);
 }
@@ -628,7 +639,7 @@
 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd3_readdirres *resp)
 {
-	p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
+	p = encode_post_op_attr(rqstp, p, &resp->fh);
 	if (resp->status == 0) {
 		/* stupid readdir cookie */
 		memcpy(p, resp->verf, 8); p += 2;
@@ -711,7 +722,7 @@
 			goto noexec;
 		if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode)
 			goto noexec;
-		p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry);
+		p = encode_post_op_attr(cd->rqstp, p, &fh);
 		*p++ = xdr_one; /* yes, a file handle follows */
 		p = encode_fh(p, &fh);
 		fh_put(&fh);
diff -Nru a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
--- a/fs/nfsd/nfsctl.c	Sun Apr 14 12:16:56 2002
+++ b/fs/nfsd/nfsctl.c	Sun Apr 14 12:16:56 2002
@@ -22,6 +22,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
+#include <linux/init.h>
 
 #include <linux/nfs.h>
 #include <linux/sunrpc/svc.h>
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nfsd/nfsfh.c	Sun Apr 14 12:16:57 2002
@@ -160,7 +160,7 @@
 	 * If possible, get a well-connected one
 	 */
 	spin_lock(&dcache_lock);
-	for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
+	list_for_each(lp, &inode->i_dentry) {
 		result = list_entry(lp,struct dentry, d_alias);
 		if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
 			dget_locked(result);
@@ -545,6 +545,9 @@
 	u32		error = 0;
 
 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
+
+	/* keep this filehandle for possible reference  when encoding attributes */
+	rqstp->rq_reffh = fh;
 
 	if (!fhp->fh_dentry) {
 		kdev_t xdev = NODEV;
diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
--- a/fs/nfsd/nfsproc.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nfsd/nfsproc.c	Sun Apr 14 12:16:57 2002
@@ -534,25 +534,30 @@
    cache,					\
    respsize,				       	\
  }
+
+#define ST 1		/* status */
+#define FH 8		/* filehandle */
+#define	AT 18		/* attributes */
+
 struct svc_procedure		nfsd_procedures2[18] = {
-  PROC(null,	 void,		void,		none,		RC_NOCACHE, 1),
-  PROC(getattr,	 fhandle,	attrstat,	fhandle,	RC_NOCACHE, 1+18),
-  PROC(setattr,  sattrargs,	attrstat,	fhandle,	RC_REPLBUFF, 1+18),
-  PROC(none,	 void,		void,		none,		RC_NOCACHE, 1),
-  PROC(lookup,	 diropargs,	diropres,	fhandle,	RC_NOCACHE, 1+8+18),
-  PROC(readlink, fhandle,	readlinkres,	none,		RC_NOCACHE, 1+1+256),
-  PROC(read,	 readargs,	readres,	fhandle,	RC_NOCACHE, 1+18+1+NFSSVC_MAXBLKSIZE),
-  PROC(none,	 void,		void,		none,		RC_NOCACHE, 1),
-  PROC(write,	 writeargs,	attrstat,	fhandle,	RC_REPLBUFF, 1+18),
-  PROC(create,	 createargs,	diropres,	fhandle,	RC_REPLBUFF, 1+8+18),
-  PROC(remove,	 diropargs,	void,		none,		RC_REPLSTAT, 1),
-  PROC(rename,	 renameargs,	void,		none,		RC_REPLSTAT, 1),
-  PROC(link,	 linkargs,	void,		none,		RC_REPLSTAT, 1),
-  PROC(symlink,	 symlinkargs,	void,		none,		RC_REPLSTAT, 1),
-  PROC(mkdir,	 createargs,	diropres,	fhandle,	RC_REPLBUFF, 1+8+18),
-  PROC(rmdir,	 diropargs,	void,		none,		RC_REPLSTAT, 1),
+  PROC(null,	 void,		void,		none,		RC_NOCACHE, ST),
+  PROC(getattr,	 fhandle,	attrstat,	fhandle,	RC_NOCACHE, ST+AT),
+  PROC(setattr,  sattrargs,	attrstat,	fhandle,	RC_REPLBUFF, ST+AT),
+  PROC(none,	 void,		void,		none,		RC_NOCACHE, ST),
+  PROC(lookup,	 diropargs,	diropres,	fhandle,	RC_NOCACHE, ST+FH+AT),
+  PROC(readlink, fhandle,	readlinkres,	none,		RC_NOCACHE, ST+1+256),
+  PROC(read,	 readargs,	readres,	fhandle,	RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
+  PROC(none,	 void,		void,		none,		RC_NOCACHE, ST),
+  PROC(write,	 writeargs,	attrstat,	fhandle,	RC_REPLBUFF, ST+AT),
+  PROC(create,	 createargs,	diropres,	fhandle,	RC_REPLBUFF, ST+FH+AT),
+  PROC(remove,	 diropargs,	void,		none,		RC_REPLSTAT, ST),
+  PROC(rename,	 renameargs,	void,		none,		RC_REPLSTAT, ST),
+  PROC(link,	 linkargs,	void,		none,		RC_REPLSTAT, ST),
+  PROC(symlink,	 symlinkargs,	void,		none,		RC_REPLSTAT, ST),
+  PROC(mkdir,	 createargs,	diropres,	fhandle,	RC_REPLBUFF, ST+FH+AT),
+  PROC(rmdir,	 diropargs,	void,		none,		RC_REPLSTAT, ST),
   PROC(readdir,	 readdirargs,	readdirres,	none,		RC_REPLBUFF, 0),
-  PROC(statfs,	 fhandle,	statfsres,	none,		RC_NOCACHE, 1+5),
+  PROC(statfs,	 fhandle,	statfsres,	none,		RC_NOCACHE, ST+5),
 };
 
 
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nfsd/nfssvc.c	Sun Apr 14 12:16:54 2002
@@ -323,11 +323,17 @@
 }
 
 static struct svc_version	nfsd_version2 = {
-	2, 18, nfsd_procedures2, nfsd_dispatch
+		vs_vers:	2,
+		vs_nproc:	18,
+		vs_proc:	nfsd_procedures2,
+		vs_dispatch:	nfsd_dispatch
 };
 #ifdef CONFIG_NFSD_V3
 static struct svc_version	nfsd_version3 = {
-	3, 22, nfsd_procedures3, nfsd_dispatch
+		vs_vers:	3,
+		vs_nproc:	22,
+		vs_proc:	nfsd_procedures3,
+		vs_dispatch:	nfsd_dispatch
 };
 #endif
 static struct svc_version *	nfsd_version[] = {
@@ -341,10 +347,11 @@
 
 #define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
 struct svc_program		nfsd_program = {
-	NFS_PROGRAM,		/* program number */
-	2, NFSD_NRVERS-1,	/* version range */
-	NFSD_NRVERS,		/* nr of entries in nfsd_version */
-	nfsd_version,		/* version table */
-	"nfsd",			/* program name */
-	&nfsd_svcstats,		/* version table */
+	pg_prog:		NFS_PROGRAM,		/* program number */
+	pg_lovers:		2,			// version
+	pg_hivers:		NFSD_NRVERS-1,		// range
+	pg_nvers:		NFSD_NRVERS,		/* nr of entries in nfsd_version */
+	pg_vers:		nfsd_version,		/* version table */
+	pg_name:		"nfsd",			/* program name */
+	pg_stats:		&nfsd_svcstats,		/* version table */
 };
diff -Nru a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
--- a/fs/nfsd/nfsxdr.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nfsd/nfsxdr.c	Sun Apr 14 12:16:54 2002
@@ -132,8 +132,9 @@
 }
 
 static inline u32 *
-encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
+encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
 {
+	struct inode *inode = fhp->fh_dentry->d_inode;
 	int type = (inode->i_mode & S_IFMT);
 
 	*p++ = htonl(nfs_ftypes[type >> 12]);
@@ -153,7 +154,12 @@
 	else
 		*p++ = htonl(0xffffffff);
 	*p++ = htonl((u32) inode->i_blocks);
-	*p++ = htonl((u32) kdev_t_to_nr(inode->i_dev));
+	if (rqstp->rq_reffh->fh_version == 1 
+	    && rqstp->rq_reffh->fh_fsid_type == 1
+	    && (fhp->fh_export->ex_flags & NFSEXP_FSID))
+		*p++ = htonl((u32) fhp->fh_export->ex_fsid);
+	else
+		*p++ = htonl((u32) kdev_t_to_nr(inode->i_dev));
 	*p++ = htonl((u32) inode->i_ino);
 	*p++ = htonl((u32) inode->i_atime);
 	*p++ = 0;
@@ -332,7 +338,7 @@
 nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd_attrstat *resp)
 {
-	p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode);
+	p = encode_fattr(rqstp, p, &resp->fh);
 	return xdr_ressize_check(rqstp, p);
 }
 
@@ -341,7 +347,7 @@
 					struct nfsd_diropres *resp)
 {
 	p = encode_fh(p, &resp->fh);
-	p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode);
+	p = encode_fattr(rqstp, p, &resp->fh);
 	return xdr_ressize_check(rqstp, p);
 }
 
@@ -358,7 +364,7 @@
 nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
 					struct nfsd_readres *resp)
 {
-	p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode);
+	p = encode_fattr(rqstp, p, &resp->fh);
 	*p++ = htonl(resp->count);
 	p += XDR_QUADLEN(resp->count);
 
@@ -379,7 +385,7 @@
 {
 	struct statfs	*stat = &resp->stats;
 
-	*p++ = htonl(8 * 1024);		/* max transfer size */
+	*p++ = htonl(NFSSVC_MAXBLKSIZE);	/* max transfer size */
 	*p++ = htonl(stat->f_bsize);
 	*p++ = htonl(stat->f_blocks);
 	*p++ = htonl(stat->f_bfree);
diff -Nru a/fs/nfsd/stats.c b/fs/nfsd/stats.c
--- a/fs/nfsd/stats.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nfsd/stats.c	Sun Apr 14 12:16:54 2002
@@ -36,7 +36,9 @@
 #include <linux/nfsd/stats.h>
 
 struct nfsd_stats	nfsdstats;
-struct svc_stat		nfsd_svcstats = { &nfsd_program, };
+struct svc_stat		nfsd_svcstats = {
+	program:	&nfsd_program,
+};
 
 static int
 nfsd_proc_read(char *buffer, char **start, off_t offset, int count,
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nfsd/vfs.c	Sun Apr 14 12:16:57 2002
@@ -67,11 +67,7 @@
 	unsigned int		p_count;
 	ino_t			p_ino;
 	kdev_t			p_dev;
-	unsigned long		p_reada,
-				p_ramax,
-				p_raend,
-				p_ralen,
-				p_rawin;
+	struct file_ra_state	p_ra;
 };
 
 static struct raparms *		raparml;
@@ -264,6 +260,7 @@
 		if (err)
 			goto out_nfserr;
 
+		size_change = 1;
 		err = locks_verify_truncate(inode, NULL, iap->ia_size);
 		if (err) {
 			put_write_access(inode);
@@ -279,35 +276,24 @@
 	}
 
 	/* Revoke setuid/setgid bit on chown/chgrp */
-	if ((iap->ia_valid & ATTR_UID) && (imode & S_ISUID)
-	 && iap->ia_uid != inode->i_uid) {
-		iap->ia_valid |= ATTR_MODE;
-		iap->ia_mode = imode &= ~S_ISUID;
-	}
-	if ((iap->ia_valid & ATTR_GID) && (imode & S_ISGID)
-	 && iap->ia_gid != inode->i_gid) {
-		iap->ia_valid |= ATTR_MODE;
-		iap->ia_mode = imode &= ~S_ISGID;
-	}
+	if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
+		iap->ia_valid |= ATTR_KILL_SUID;
+	if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
+		iap->ia_valid |= ATTR_KILL_SGID;
 
 	/* Change the attributes. */
 
-
 	iap->ia_valid |= ATTR_CTIME;
 
-	if (iap->ia_valid & ATTR_SIZE) {
-		fh_lock(fhp);
-		size_change = 1;
-	}
 	err = nfserr_notsync;
 	if (!check_guard || guardtime == inode->i_ctime) {
+		fh_lock(fhp);
 		err = notify_change(dentry, iap);
 		err = nfserrno(err);
-	}
-	if (size_change) {
 		fh_unlock(fhp);
-		put_write_access(inode);
 	}
+	if (size_change)
+		put_write_access(inode);
 	if (!err)
 		if (EX_ISSYNC(fhp->fh_export))
 			write_inode_now(inode, 1);
@@ -574,11 +560,7 @@
 	ra = *frap;
 	ra->p_dev = dev;
 	ra->p_ino = ino;
-	ra->p_reada = 0;
-	ra->p_ramax = 0;
-	ra->p_raend = 0;
-	ra->p_ralen = 0;
-	ra->p_rawin = 0;
+	memset(&ra->p_ra, 0, sizeof(ra->p_ra));
 found:
 	if (rap != &raparm_cache) {
 		*rap = ra->p_next;
@@ -621,31 +603,18 @@
 
 	/* Get readahead parameters */
 	ra = nfsd_get_raparms(inode->i_dev, inode->i_ino);
-	if (ra) {
-		file.f_reada = ra->p_reada;
-		file.f_ramax = ra->p_ramax;
-		file.f_raend = ra->p_raend;
-		file.f_ralen = ra->p_ralen;
-		file.f_rawin = ra->p_rawin;
-	}
+	if (ra)
+		file.f_ra = ra->p_ra;
 	file.f_pos = offset;
 
-	oldfs = get_fs(); set_fs(KERNEL_DS);
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
 	err = file.f_op->read(&file, buf, *count, &file.f_pos);
 	set_fs(oldfs);
 
 	/* Write back readahead params */
-	if (ra != NULL) {
-		dprintk("nfsd: raparms %ld %ld %ld %ld %ld\n",
-			file.f_reada, file.f_ramax, file.f_raend,
-			file.f_ralen, file.f_rawin);
-		ra->p_reada = file.f_reada;
-		ra->p_ramax = file.f_ramax;
-		ra->p_raend = file.f_raend;
-		ra->p_ralen = file.f_ralen;
-		ra->p_rawin = file.f_rawin;
-		ra->p_count -= 1;
-	}
+	if (ra)
+		ra->p_ra = file.f_ra;
 
 	if (err >= 0) {
 		nfsdstats.io_read += err;
@@ -725,10 +694,11 @@
 	/* clear setuid/setgid flag after write */
 	if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
 		struct iattr	ia;
+		ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
 
-		ia.ia_valid = ATTR_MODE;
-		ia.ia_mode  = inode->i_mode & ~(S_ISUID | S_ISGID);
+		down(&inode->i_sem);
 		notify_change(dentry, &ia);
+		up(&inode->i_sem);
 	}
 
 	if (err >= 0 && stable) {
@@ -1157,7 +1127,9 @@
 				iap->ia_valid |= ATTR_CTIME;
 				iap->ia_mode = (iap->ia_mode&S_IALLUGO)
 					| S_IFLNK;
+				down(&dentry->d_inode->i_sem);
 				err = notify_change(dnew, iap);
+				up(&dentry->d_inode->i_sem);
 				if (!err && EX_ISSYNC(fhp->fh_export))
 					write_inode_now(dentry->d_inode, 1);
 		       }
diff -Nru a/fs/nls/Config.help b/fs/nls/Config.help
--- a/fs/nls/Config.help	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/Config.help	Sun Apr 14 12:16:59 2002
@@ -224,6 +224,15 @@
   say Y here if you want to include the DOS codepage for Traditional
   Chinese(Big5).
 
+CONFIG_NLS_CODEPAGE_1250
+  If you want to display filenames with native language characters
+  from the Microsoft FAT file system family or from JOLIET CDROMs
+  correctly on the screen, you need to include the appropriate
+  input/output character sets. Say Y here for the Windows CP-1250
+  character set, which works for most Latin-written Slavic and Central
+  European languages: Czech, German, Hungarian, Polish, Rumanian, Croatian,
+  Slovak, Slovene.
+
 CONFIG_NLS_ISO8859_1
   If you want to display filenames with native language characters
   from the Microsoft FAT file system family or from JOLIET CD-ROMs
diff -Nru a/fs/nls/Config.in b/fs/nls/Config.in
--- a/fs/nls/Config.in	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/Config.in	Sun Apr 14 12:16:57 2002
@@ -43,6 +43,7 @@
   tristate 'Korean charset (CP949, EUC-KR)'        CONFIG_NLS_CODEPAGE_949
   tristate 'Thai charset (CP874, TIS-620)'         CONFIG_NLS_CODEPAGE_874
   tristate 'Hebrew charsets (ISO-8859-8, CP1255)'  CONFIG_NLS_ISO8859_8
+  tristate 'Windows CP1250 (Slavic/Central European Languages)' CONFIG_NLS_CODEPAGE_1250
   tristate 'Windows CP1251 (Bulgarian, Belarusian)' CONFIG_NLS_CODEPAGE_1251
   tristate 'NLS ISO 8859-1  (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1
   tristate 'NLS ISO 8859-2  (Latin 2; Slavic/Central European Languages)' CONFIG_NLS_ISO8859_2
diff -Nru a/fs/nls/nls_base.c b/fs/nls/nls_base.c
--- a/fs/nls/nls_base.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nls/nls_base.c	Sun Apr 14 12:16:55 2002
@@ -470,12 +470,11 @@
 }
 
 static struct nls_table default_table = {
-	"default",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	NULL,
+	charset:	"default",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
 };
 
 /* Returns a simple default translation table */
diff -Nru a/fs/nls/nls_big5.c b/fs/nls/nls_big5.c
--- a/fs/nls/nls_big5.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_big5.c	Sun Apr 14 12:16:59 2002
@@ -11,12 +11,8 @@
 static struct nls_table *p_nls;
 
 static struct nls_table table = {
-	"big5",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"big5",
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_big5(void)
diff -Nru a/fs/nls/nls_cp1250.c b/fs/nls/nls_cp1250.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/nls/nls_cp1250.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,365 @@
+/*
+ * linux/fs/nls_cp1250.c
+ *
+ * Charset cp1250 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include <linux/errno.h>
+
+static wchar_t charset2uni[256] = {
+	/* 0x00*/
+	0x0000, 0x0001, 0x0002, 0x0003, 
+	0x0004, 0x0005, 0x0006, 0x0007, 
+	0x0008, 0x0009, 0x000a, 0x000b, 
+	0x000c, 0x000d, 0x000e, 0x000f, 
+	/* 0x10*/
+	0x0010, 0x0011, 0x0012, 0x0013, 
+	0x0014, 0x0015, 0x0016, 0x0017, 
+	0x0018, 0x0019, 0x001a, 0x001b, 
+	0x001c, 0x001d, 0x001e, 0x001f, 
+	/* 0x20*/
+	0x0020, 0x0021, 0x0022, 0x0023, 
+	0x0024, 0x0025, 0x0026, 0x0027, 
+	0x0028, 0x0029, 0x002a, 0x002b, 
+	0x002c, 0x002d, 0x002e, 0x002f, 
+	/* 0x30*/
+	0x0030, 0x0031, 0x0032, 0x0033, 
+	0x0034, 0x0035, 0x0036, 0x0037, 
+	0x0038, 0x0039, 0x003a, 0x003b, 
+	0x003c, 0x003d, 0x003e, 0x003f, 
+	/* 0x40*/
+	0x0040, 0x0041, 0x0042, 0x0043, 
+	0x0044, 0x0045, 0x0046, 0x0047, 
+	0x0048, 0x0049, 0x004a, 0x004b, 
+	0x004c, 0x004d, 0x004e, 0x004f, 
+	/* 0x50*/
+	0x0050, 0x0051, 0x0052, 0x0053, 
+	0x0054, 0x0055, 0x0056, 0x0057, 
+	0x0058, 0x0059, 0x005a, 0x005b, 
+	0x005c, 0x005d, 0x005e, 0x005f, 
+	/* 0x60*/
+	0x0060, 0x0061, 0x0062, 0x0063, 
+	0x0064, 0x0065, 0x0066, 0x0067, 
+	0x0068, 0x0069, 0x006a, 0x006b, 
+	0x006c, 0x006d, 0x006e, 0x006f, 
+	/* 0x70*/
+	0x0070, 0x0071, 0x0072, 0x0073, 
+	0x0074, 0x0075, 0x0076, 0x0077, 
+	0x0078, 0x0079, 0x007a, 0x007b, 
+	0x007c, 0x007d, 0x007e, 0x007f, 
+	/* 0x80*/
+	0x20ac, 0x0000, 0x201a, 0x0000, 
+	0x201e, 0x2026, 0x2020, 0x2021, 
+	0x0000, 0x2030, 0x0160, 0x2039, 
+	0x015a, 0x0164, 0x017d, 0x0179, 
+	/* 0x90*/
+	0x0000, 0x2018, 0x2019, 0x201c, 
+	0x201d, 0x2022, 0x2013, 0x2014, 
+	0x0000, 0x2122, 0x0161, 0x203a, 
+	0x015b, 0x0165, 0x017e, 0x017a, 
+	/* 0xa0*/
+	0x00a0, 0x02c7, 0x02d8, 0x0141, 
+	0x00a4, 0x0104, 0x00a6, 0x00a7, 
+	0x00a8, 0x00a9, 0x015e, 0x00ab, 
+	0x00ac, 0x00ad, 0x00ae, 0x017b, 
+	/* 0xb0*/
+	0x00b0, 0x00b1, 0x02db, 0x0142, 
+	0x00b4, 0x00b5, 0x00b6, 0x00b7, 
+	0x00b8, 0x0105, 0x015f, 0x00bb, 
+	0x013d, 0x02dd, 0x013e, 0x017c, 
+	/* 0xc0*/
+	0x0154, 0x00c1, 0x00c2, 0x0102, 
+	0x00c4, 0x0139, 0x0106, 0x00c7, 
+	0x010c, 0x00c9, 0x0118, 0x00cb, 
+	0x011a, 0x00cd, 0x00ce, 0x010e, 
+	/* 0xd0*/
+	0x0110, 0x0143, 0x0147, 0x00d3, 
+	0x00d4, 0x0150, 0x00d6, 0x00d7, 
+	0x0158, 0x016e, 0x00da, 0x0170, 
+	0x00dc, 0x00dd, 0x0162, 0x00df, 
+	/* 0xe0*/
+	0x0155, 0x00e1, 0x00e2, 0x0103, 
+	0x00e4, 0x013a, 0x0107, 0x00e7, 
+	0x010d, 0x00e9, 0x0119, 0x00eb, 
+	0x011b, 0x00ed, 0x00ee, 0x010f, 
+	/* 0xf0*/
+	0x0111, 0x0144, 0x0148, 0x00f3, 
+	0x00f4, 0x0151, 0x00f6, 0x00f7, 
+	0x0159, 0x016f, 0x00fa, 0x0171, 
+	0x00fc, 0x00fd, 0x0163, 0x02d9, 
+	};
+
+static unsigned char page00[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+	0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0xb8, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+	0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
+	0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
+	0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+	0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
+	0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
+	0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
+	0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
+	0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
+	};
+
+static unsigned char page01[256] = {
+	0x00, 0x00, 0xc3, 0xe3, 0xa5, 0xb9, 0xc6, 0xe6, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
+	0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0xc5, 0xe5, 0x00, 0x00, 0xbc, 0xbe, 0x00, /* 0x38-0x3f */
+	0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, /* 0x40-0x47 */
+	0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, /* 0x50-0x57 */
+	0xd8, 0xf8, 0x8c, 0x9c, 0x00, 0x00, 0xaa, 0xba, /* 0x58-0x5f */
+	0x8a, 0x9a, 0xde, 0xfe, 0x8d, 0x9d, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9, /* 0x68-0x6f */
+	0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x8f, 0x9f, 0xaf, 0xbf, 0x8e, 0x9e, 0x00, /* 0x78-0x7f */
+
+	};
+
+static unsigned char page02[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, /* 0xc0-0xc7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+	0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
+	};
+
+static unsigned char page20[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
+	0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+	0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+	};
+
+static unsigned char page21[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	};
+
+static unsigned char *page_uni2charset[256] = {
+	page00,	page01,	page02,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	page20,	page21,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	};
+
+static unsigned char charset2lower[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x80, 0x00, 0x82, 0x00, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+	0x00, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x88-0x8f */
+	0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+	0x00, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+	0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xb9, 0xa6, 0xa7, /* 0xa0-0xa7 */
+	0xa8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0xb8, 0xb9, 0xba, 0xbb, 0xbe, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+	};
+
+static unsigned char charset2upper[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+	0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x80, 0x00, 0x82, 0x00, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+	0x00, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+	0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+	0x00, 0x99, 0x8a, 0x9b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x98-0x9f */
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0xb2, 0xa3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0xb8, 0xa5, 0xaa, 0xbb, 0xbc, 0xbd, 0xbc, 0xaf, /* 0xb8-0xbf */
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
+	};
+
+static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
+{
+        unsigned char *uni2charset;
+        unsigned char cl = uni & 0x00ff;
+        unsigned char ch = (uni & 0xff00) >> 8;
+
+        if (boundlen <= 0)
+                return -ENAMETOOLONG;
+
+        uni2charset = page_uni2charset[ch];
+        if (uni2charset && uni2charset[cl])
+                out[0] = uni2charset[cl];
+        else
+                return -EINVAL;
+        return 1;
+}
+
+static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
+{
+        *uni = charset2uni[*rawstring];
+        if (*uni == 0x0000)
+                return -EINVAL;
+        return 1;
+}
+
+static struct nls_table table = {
+	charset:	"cp1250",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
+};
+
+static int __init init_nls_cp1250(void)
+{
+        return register_nls(&table);
+}
+static void __exit exit_nls_cp1250(void)
+{
+        unregister_nls(&table);
+}
+
+module_init(init_nls_cp1250)
+module_exit(exit_nls_cp1250)
+
+MODULE_LICENSE("BSD without advertising clause");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
+
diff -Nru a/fs/nls/nls_cp1251.c b/fs/nls/nls_cp1251.c
--- a/fs/nls/nls_cp1251.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_cp1251.c	Sun Apr 14 12:16:59 2002
@@ -278,12 +278,12 @@
 }
 
 static struct nls_table table = {
-	"cp1251",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp1251",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp1251(void)
diff -Nru a/fs/nls/nls_cp1255.c b/fs/nls/nls_cp1255.c
--- a/fs/nls/nls_cp1255.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_cp1255.c	Sun Apr 14 12:16:54 2002
@@ -359,12 +359,12 @@
 }
 
 static struct nls_table table = {
-	"cp1255",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp1255",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp1255(void)
diff -Nru a/fs/nls/nls_cp437.c b/fs/nls/nls_cp437.c
--- a/fs/nls/nls_cp437.c	Sun Apr 14 12:17:00 2002
+++ b/fs/nls/nls_cp437.c	Sun Apr 14 12:17:00 2002
@@ -364,12 +364,12 @@
 }
 
 static struct nls_table table = {
-	"cp437",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp437",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp437(void)
diff -Nru a/fs/nls/nls_cp737.c b/fs/nls/nls_cp737.c
--- a/fs/nls/nls_cp737.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nls/nls_cp737.c	Sun Apr 14 12:16:55 2002
@@ -327,12 +327,12 @@
 }
 
 static struct nls_table table = {
-	"cp737",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp737",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp737(void)
diff -Nru a/fs/nls/nls_cp775.c b/fs/nls/nls_cp775.c
--- a/fs/nls/nls_cp775.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_cp775.c	Sun Apr 14 12:16:57 2002
@@ -296,12 +296,12 @@
 }
 
 static struct nls_table table = {
-	"cp775",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp775",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp775(void)
diff -Nru a/fs/nls/nls_cp850.c b/fs/nls/nls_cp850.c
--- a/fs/nls/nls_cp850.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_cp850.c	Sun Apr 14 12:16:59 2002
@@ -292,12 +292,12 @@
 }
 
 static struct nls_table table = {
-	"cp850",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp850",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp850(void)
diff -Nru a/fs/nls/nls_cp852.c b/fs/nls/nls_cp852.c
--- a/fs/nls/nls_cp852.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_cp852.c	Sun Apr 14 12:16:59 2002
@@ -314,12 +314,12 @@
 }
 
 static struct nls_table table = {
-	"cp852",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp852",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp852(void)
diff -Nru a/fs/nls/nls_cp855.c b/fs/nls/nls_cp855.c
--- a/fs/nls/nls_cp855.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_cp855.c	Sun Apr 14 12:16:57 2002
@@ -276,12 +276,12 @@
 }
 
 static struct nls_table table = {
-	"cp855",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp855",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp855(void)
diff -Nru a/fs/nls/nls_cp857.c b/fs/nls/nls_cp857.c
--- a/fs/nls/nls_cp857.c	Sun Apr 14 12:16:56 2002
+++ b/fs/nls/nls_cp857.c	Sun Apr 14 12:16:56 2002
@@ -278,12 +278,12 @@
 }
 
 static struct nls_table table = {
-	"cp857",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp857",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp857(void)
diff -Nru a/fs/nls/nls_cp860.c b/fs/nls/nls_cp860.c
--- a/fs/nls/nls_cp860.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_cp860.c	Sun Apr 14 12:16:58 2002
@@ -341,12 +341,12 @@
 }
 
 static struct nls_table table = {
-	"cp860",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp860",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp860(void)
diff -Nru a/fs/nls/nls_cp861.c b/fs/nls/nls_cp861.c
--- a/fs/nls/nls_cp861.c	Sun Apr 14 12:16:56 2002
+++ b/fs/nls/nls_cp861.c	Sun Apr 14 12:16:56 2002
@@ -364,12 +364,12 @@
 }
 
 static struct nls_table table = {
-	"cp861",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp861",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp861(void)
diff -Nru a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c
--- a/fs/nls/nls_cp862.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_cp862.c	Sun Apr 14 12:16:59 2002
@@ -398,12 +398,12 @@
 }
 
 static struct nls_table table = {
-	"cp862",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp862",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp862(void)
diff -Nru a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c
--- a/fs/nls/nls_cp863.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nls/nls_cp863.c	Sun Apr 14 12:16:55 2002
@@ -358,12 +358,12 @@
 }
 
 static struct nls_table table = {
-	"cp863",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp863",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp863(void)
diff -Nru a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c
--- a/fs/nls/nls_cp864.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_cp864.c	Sun Apr 14 12:16:58 2002
@@ -384,12 +384,12 @@
 }
 
 static struct nls_table table = {
-	"cp864",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp864",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp864(void)
diff -Nru a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c
--- a/fs/nls/nls_cp865.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_cp865.c	Sun Apr 14 12:16:54 2002
@@ -364,12 +364,12 @@
 }
 
 static struct nls_table table = {
-	"cp865",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp865",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp865(void)
diff -Nru a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c
--- a/fs/nls/nls_cp866.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_cp866.c	Sun Apr 14 12:16:59 2002
@@ -282,12 +282,12 @@
 }
 
 static struct nls_table table = {
-	"cp866",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp866",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp866(void)
diff -Nru a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c
--- a/fs/nls/nls_cp869.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_cp869.c	Sun Apr 14 12:16:58 2002
@@ -292,12 +292,12 @@
 }
 
 static struct nls_table table = {
-	"cp869",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp869",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp869(void)
diff -Nru a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c
--- a/fs/nls/nls_cp874.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_cp874.c	Sun Apr 14 12:16:57 2002
@@ -250,12 +250,12 @@
 }
 
 static struct nls_table table = {
-	"cp874",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp874",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp874(void)
diff -Nru a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
--- a/fs/nls/nls_cp932.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_cp932.c	Sun Apr 14 12:16:57 2002
@@ -7884,12 +7884,12 @@
 }
 
 static struct nls_table table = {
-	"cp932",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp932",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp932(void)
diff -Nru a/fs/nls/nls_cp936.c b/fs/nls/nls_cp936.c
--- a/fs/nls/nls_cp936.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_cp936.c	Sun Apr 14 12:16:57 2002
@@ -11004,12 +11004,12 @@
 }
 
 static struct nls_table table = {
-	"cp936",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp936",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp936(void)
diff -Nru a/fs/nls/nls_cp949.c b/fs/nls/nls_cp949.c
--- a/fs/nls/nls_cp949.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_cp949.c	Sun Apr 14 12:16:58 2002
@@ -13921,12 +13921,12 @@
 }
 
 static struct nls_table table = {
-	"cp949",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp949",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp949(void)
diff -Nru a/fs/nls/nls_cp950.c b/fs/nls/nls_cp950.c
--- a/fs/nls/nls_cp950.c	Sun Apr 14 12:17:00 2002
+++ b/fs/nls/nls_cp950.c	Sun Apr 14 12:17:00 2002
@@ -9460,12 +9460,12 @@
 }
 
 static struct nls_table table = {
-	"cp950",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"cp950",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_cp950(void)
diff -Nru a/fs/nls/nls_euc-jp.c b/fs/nls/nls_euc-jp.c
--- a/fs/nls/nls_euc-jp.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nls/nls_euc-jp.c	Sun Apr 14 12:16:55 2002
@@ -552,12 +552,10 @@
 }
 
 static struct nls_table table = {
-	"euc-jp",
-	uni2char,
-	char2uni,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"euc-jp",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_euc_jp(void)
diff -Nru a/fs/nls/nls_euc-kr.c b/fs/nls/nls_euc-kr.c
--- a/fs/nls/nls_euc-kr.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_euc-kr.c	Sun Apr 14 12:16:58 2002
@@ -11,12 +11,8 @@
 static struct nls_table *p_nls;
 
 static struct nls_table table = {
-	"euc-kr",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"euc-kr",
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_euc_kr(void)
diff -Nru a/fs/nls/nls_gb2312.c b/fs/nls/nls_gb2312.c
--- a/fs/nls/nls_gb2312.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_gb2312.c	Sun Apr 14 12:16:58 2002
@@ -11,12 +11,8 @@
 static struct nls_table *p_nls;
 
 static struct nls_table table = {
-	"gb2312",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"gb2312",
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_gb2312(void)
diff -Nru a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c
--- a/fs/nls/nls_iso8859-1.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_iso8859-1.c	Sun Apr 14 12:16:55 2002
@@ -234,12 +234,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-1",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-1",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_1(void)
diff -Nru a/fs/nls/nls_iso8859-13.c b/fs/nls/nls_iso8859-13.c
--- a/fs/nls/nls_iso8859-13.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_iso8859-13.c	Sun Apr 14 12:16:59 2002
@@ -262,12 +262,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-13",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-13",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_13(void)
diff -Nru a/fs/nls/nls_iso8859-14.c b/fs/nls/nls_iso8859-14.c
--- a/fs/nls/nls_iso8859-14.c	Sun Apr 14 12:16:56 2002
+++ b/fs/nls/nls_iso8859-14.c	Sun Apr 14 12:16:56 2002
@@ -318,12 +318,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-14",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-14",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_14(void)
diff -Nru a/fs/nls/nls_iso8859-15.c b/fs/nls/nls_iso8859-15.c
--- a/fs/nls/nls_iso8859-15.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_iso8859-15.c	Sun Apr 14 12:16:59 2002
@@ -284,12 +284,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-15",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-15",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_15(void)
diff -Nru a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c
--- a/fs/nls/nls_iso8859-2.c	Sun Apr 14 12:16:58 2002
+++ b/fs/nls/nls_iso8859-2.c	Sun Apr 14 12:16:58 2002
@@ -285,12 +285,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-2",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-2",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_2(void)
diff -Nru a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c
--- a/fs/nls/nls_iso8859-3.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_iso8859-3.c	Sun Apr 14 12:16:57 2002
@@ -285,12 +285,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-3",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-3",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_3(void)
diff -Nru a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c
--- a/fs/nls/nls_iso8859-4.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nls/nls_iso8859-4.c	Sun Apr 14 12:16:55 2002
@@ -285,12 +285,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-4",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-4",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_4(void)
diff -Nru a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c
--- a/fs/nls/nls_iso8859-5.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_iso8859-5.c	Sun Apr 14 12:16:57 2002
@@ -249,12 +249,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-5",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-5",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_5(void)
diff -Nru a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c
--- a/fs/nls/nls_iso8859-6.c	Sun Apr 14 12:16:56 2002
+++ b/fs/nls/nls_iso8859-6.c	Sun Apr 14 12:16:56 2002
@@ -240,12 +240,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-6",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-6",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_6(void)
diff -Nru a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c
--- a/fs/nls/nls_iso8859-7.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_iso8859-7.c	Sun Apr 14 12:16:54 2002
@@ -294,12 +294,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-7",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-7",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_7(void)
diff -Nru a/fs/nls/nls_iso8859-8.c b/fs/nls/nls_iso8859-8.c
--- a/fs/nls/nls_iso8859-8.c	Sun Apr 14 12:16:59 2002
+++ b/fs/nls/nls_iso8859-8.c	Sun Apr 14 12:16:59 2002
@@ -11,12 +11,8 @@
 static struct nls_table *p_nls;
 
 static struct nls_table table = {
-	"iso8859-8",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"iso8859-8",
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_8(void)
diff -Nru a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c
--- a/fs/nls/nls_iso8859-9.c	Sun Apr 14 12:16:55 2002
+++ b/fs/nls/nls_iso8859-9.c	Sun Apr 14 12:16:55 2002
@@ -249,12 +249,12 @@
 }
 
 static struct nls_table table = {
-	"iso8859-9",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"iso8859-9",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_iso8859_9(void)
diff -Nru a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c
--- a/fs/nls/nls_koi8-r.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_koi8-r.c	Sun Apr 14 12:16:54 2002
@@ -300,12 +300,12 @@
 }
 
 static struct nls_table table = {
-	"koi8-r",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"koi8-r",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_koi8_r(void)
diff -Nru a/fs/nls/nls_koi8-ru.c b/fs/nls/nls_koi8-ru.c
--- a/fs/nls/nls_koi8-ru.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_koi8-ru.c	Sun Apr 14 12:16:54 2002
@@ -51,12 +51,10 @@
 }
 
 static struct nls_table table = {
-	"koi8-ru",
-	uni2char,
-	char2uni,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"koi8-ru",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_koi8_ru(void)
diff -Nru a/fs/nls/nls_koi8-u.c b/fs/nls/nls_koi8-u.c
--- a/fs/nls/nls_koi8-u.c	Sun Apr 14 12:17:00 2002
+++ b/fs/nls/nls_koi8-u.c	Sun Apr 14 12:17:00 2002
@@ -307,12 +307,12 @@
 }
 
 static struct nls_table table = {
-	"koi8-u",
-	uni2char,
-	char2uni,
-	charset2lower,
-	charset2upper,
-	THIS_MODULE,
+	charset:	"koi8-u",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	charset2lower,
+	charset2upper:	charset2upper,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_koi8_u(void)
diff -Nru a/fs/nls/nls_sjis.c b/fs/nls/nls_sjis.c
--- a/fs/nls/nls_sjis.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_sjis.c	Sun Apr 14 12:16:54 2002
@@ -11,12 +11,8 @@
 static struct nls_table *p_nls;
 
 static struct nls_table table = {
-	"sjis",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"sjis",
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_sjis(void)
diff -Nru a/fs/nls/nls_tis-620.c b/fs/nls/nls_tis-620.c
--- a/fs/nls/nls_tis-620.c	Sun Apr 14 12:16:54 2002
+++ b/fs/nls/nls_tis-620.c	Sun Apr 14 12:16:54 2002
@@ -11,12 +11,8 @@
 static struct nls_table *p_nls;
 
 static struct nls_table table = {
-	"tis-620",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	THIS_MODULE,
+	charset:	"tis-620",
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_tis_620(void)
diff -Nru a/fs/nls/nls_utf8.c b/fs/nls/nls_utf8.c
--- a/fs/nls/nls_utf8.c	Sun Apr 14 12:16:57 2002
+++ b/fs/nls/nls_utf8.c	Sun Apr 14 12:16:57 2002
@@ -34,12 +34,12 @@
 }
 
 static struct nls_table table = {
-	"utf8",
-	uni2char,
-	char2uni,
-	identity,	/* no conversion */
-	identity,
-	THIS_MODULE,
+	charset:	"utf8",
+	uni2char:	uni2char,
+	char2uni:	char2uni,
+	charset2lower:	identity,	/* no conversion */
+	charset2upper:	identity,
+	owner:		THIS_MODULE,
 };
 
 static int __init init_nls_utf8(void)
diff -Nru a/fs/noquot.c b/fs/noquot.c
--- a/fs/noquot.c	Sun Apr 14 12:16:55 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,15 +0,0 @@
-/* noquot.c: Quota stubs necessary for when quotas are not
- *           compiled into the kernel.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-
-int nr_dquots, nr_free_dquots;
-int max_dquots;
-
-asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
-{
-	return(-ENOSYS);
-}
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile	Sun Apr 14 12:16:57 2002
+++ b/fs/ntfs/Makefile	Sun Apr 14 12:16:57 2002
@@ -5,7 +5,7 @@
 obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o
 obj-m   := $(O_TARGET)
 # New version format started 3 February 2001.
-EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.21\" #-DDEBUG
+EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.22\" #-DDEBUG
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/fs/ntfs/fs.c b/fs/ntfs/fs.c
--- a/fs/ntfs/fs.c	Sun Apr 14 12:16:56 2002
+++ b/fs/ntfs/fs.c	Sun Apr 14 12:16:56 2002
@@ -360,10 +360,13 @@
 	int use_utf8 = -1;	/* If no NLS specified and loading the default
 				   NLS failed use utf8. */
 	int mft_zone_mul = -1;	/* 1 */
+	char *opts = opt;
 
 	if (!opt)
 		goto done;
-	for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {
+	while ((opt = strsep(&opts, ",")) != NULL) {
+		if (!*opt)
+			continue;
 		if ((value = strchr(opt, '=')) != NULL)
 			*value ++= '\0';
 		if (strcmp(opt, "uid") == 0) {
diff -Nru a/fs/ntfs/support.h b/fs/ntfs/support.h
--- a/fs/ntfs/support.h	Sun Apr 14 12:16:54 2002
+++ b/fs/ntfs/support.h	Sun Apr 14 12:16:54 2002
@@ -32,9 +32,39 @@
 
 #define ntfs_free(ptr)     kfree(ptr)
 
-#define ntfs_vmalloc(size)	vmalloc_32(size)
+/**
+ * ntfs_vmalloc - allocate memory in multiples of pages
+ * @size	number of bytes to allocate
+ *
+ * Allocates @size bytes of memory, rounded up to multiples of PAGE_SIZE and
+ * returns a pointer to the allocated memory.
+ *
+ * If there was insufficient memory to complete the request, return NULL.
+ */
+static inline void *ntfs_vmalloc(unsigned long size)
+{
+	if (size <= PAGE_SIZE) {
+		if (size) {
+			/* kmalloc() has per-CPU caches so if faster for now. */
+			return kmalloc(PAGE_SIZE, GFP_NOFS);
+			/* return (void *)__get_free_page(GFP_NOFS |
+					__GFP_HIGHMEM); */
+		}
+		BUG();
+	}
+	if (size >> PAGE_SHIFT < num_physpages)
+		return __vmalloc(size, GFP_NOFS | __GFP_HIGHMEM, PAGE_KERNEL);
+	return NULL;
+}
 
-#define ntfs_vfree(ptr)		vfree(ptr)
+static inline void ntfs_vfree(void *addr)
+{
+	if ((unsigned long)addr < VMALLOC_START) {
+		return kfree(addr);
+		/* return free_page((unsigned long)addr); */
+	}
+	vfree(addr);
+}
 
 void ntfs_bzero(void *s, int n);
 
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c	Sun Apr 14 12:16:55 2002
+++ b/fs/open.c	Sun Apr 14 12:16:55 2002
@@ -73,20 +73,19 @@
 
 int do_truncate(struct dentry *dentry, loff_t length)
 {
-	struct inode *inode = dentry->d_inode;
-	int error;
+	int err;
 	struct iattr newattrs;
 
 	/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
 	if (length < 0)
 		return -EINVAL;
 
-	down(&inode->i_sem);
 	newattrs.ia_size = length;
 	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-	error = notify_change(dentry, &newattrs);
-	up(&inode->i_sem);
-	return error;
+	down(&dentry->d_inode->i_sem);
+	err = notify_change(dentry, &newattrs);
+	up(&dentry->d_inode->i_sem);
+	return err;
 }
 
 static inline long do_sys_truncate(const char * path, loff_t length)
@@ -260,7 +259,9 @@
 		    (error = permission(inode,MAY_WRITE)) != 0)
 			goto dput_and_out;
 	}
+	down(&inode->i_sem);
 	error = notify_change(nd.dentry, &newattrs);
+	up(&inode->i_sem);
 dput_and_out:
 	path_release(&nd);
 out:
@@ -304,7 +305,9 @@
 		if ((error = permission(inode,MAY_WRITE)) != 0)
 			goto dput_and_out;
 	}
+	down(&inode->i_sem);
 	error = notify_change(nd.dentry, &newattrs);
+	up(&inode->i_sem);
 dput_and_out:
 	path_release(&nd);
 out:
@@ -454,11 +457,13 @@
 	err = -EPERM;
 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 		goto out_putf;
+	down(&inode->i_sem);
 	if (mode == (mode_t) -1)
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 	err = notify_change(dentry, &newattrs);
+	up(&inode->i_sem);
 
 out_putf:
 	fput(file);
@@ -486,11 +491,13 @@
 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 		goto dput_and_out;
 
+	down(&inode->i_sem);
 	if (mode == (mode_t) -1)
 		mode = inode->i_mode;
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 	error = notify_change(nd.dentry, &newattrs);
+	up(&inode->i_sem);
 
 dput_and_out:
 	path_release(&nd);
@@ -515,45 +522,20 @@
 	error = -EPERM;
 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 		goto out;
-	if (user == (uid_t) -1)
-		user = inode->i_uid;
-	if (group == (gid_t) -1)
-		group = inode->i_gid;
-	newattrs.ia_mode = inode->i_mode;
-	newattrs.ia_uid = user;
-	newattrs.ia_gid = group;
-	newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
-	/*
-	 * If the user or group of a non-directory has been changed by a
-	 * non-root user, remove the setuid bit.
-	 * 19981026	David C Niemi <niemi@tux.org>
-	 *
-	 * Changed this to apply to all users, including root, to avoid
-	 * some races. This is the behavior we had in 2.0. The check for
-	 * non-root was definitely wrong for 2.2 anyway, as it should
-	 * have been using CAP_FSETID rather than fsuid -- 19990830 SD.
-	 */
-	if ((inode->i_mode & S_ISUID) == S_ISUID &&
-		!S_ISDIR(inode->i_mode))
-	{
-		newattrs.ia_mode &= ~S_ISUID;
-		newattrs.ia_valid |= ATTR_MODE;
-	}
-	/*
-	 * Likewise, if the user or group of a non-directory has been changed
-	 * by a non-root user, remove the setgid bit UNLESS there is no group
-	 * execute bit (this would be a file marked for mandatory locking).
-	 * 19981026	David C Niemi <niemi@tux.org>
-	 *
-	 * Removed the fsuid check (see the comment above) -- 19990830 SD.
-	 */
-	if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) 
-		&& !S_ISDIR(inode->i_mode))
-	{
-		newattrs.ia_mode &= ~S_ISGID;
-		newattrs.ia_valid |= ATTR_MODE;
+	newattrs.ia_valid =  ATTR_CTIME;
+	if (user != (uid_t) -1) {
+		newattrs.ia_valid |= ATTR_UID;
+		newattrs.ia_uid = user;
+	}
+	if (group != (gid_t) -1) {
+		newattrs.ia_valid |= ATTR_GID;
+		newattrs.ia_gid = group;
 	}
+	if (!S_ISDIR(inode->i_mode))
+		newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
+	down(&inode->i_sem);
 	error = notify_change(dentry, &newattrs);
+	up(&inode->i_sem);
 out:
 	return error;
 }
@@ -653,7 +635,6 @@
 	f->f_dentry = dentry;
 	f->f_vfsmnt = mnt;
 	f->f_pos = 0;
-	f->f_reada = 0;
 	f->f_op = fops_get(inode->i_fop);
 	file_move(f, &inode->i_sb->s_files);
 
@@ -704,7 +685,7 @@
 	write_lock(&files->file_lock);
 
 repeat:
- 	fd = find_next_zero_bit(files->open_fds, 
+ 	fd = find_next_zero_bit(files->open_fds->fds_bits, 
 				files->max_fdset, 
 				files->next_fd);
 
diff -Nru a/fs/partitions/Config.help b/fs/partitions/Config.help
--- a/fs/partitions/Config.help	Sun Apr 14 12:16:58 2002
+++ b/fs/partitions/Config.help	Sun Apr 14 12:16:58 2002
@@ -115,6 +115,11 @@
   Say Y here if you would like to be able to read the hard disk
   partition table format used by SGI machines.
 
+CONFIG_EFI_PARTITION
+  Say Y here if you would like to use hard disks under Linux which
+  were partitioned using EFI GPT.  Presently only useful on the
+  IA-64 platform.
+
 CONFIG_ULTRIX_PARTITION
   Say Y here if you would like to be able to read the hard disk
   partition table format used by DEC (now Compaq) Ultrix machines.
diff -Nru a/fs/partitions/Config.in b/fs/partitions/Config.in
--- a/fs/partitions/Config.in	Sun Apr 14 12:16:57 2002
+++ b/fs/partitions/Config.in	Sun Apr 14 12:16:57 2002
@@ -32,6 +32,7 @@
    bool '  SGI partition support' CONFIG_SGI_PARTITION
    bool '  Ultrix partition table support' CONFIG_ULTRIX_PARTITION
    bool '  Sun partition tables support' CONFIG_SUN_PARTITION
+   bool '  EFI GUID Partition support' CONFIG_EFI_PARTITION
 else
    if [ "$ARCH" = "alpha" ]; then
       define_bool CONFIG_OSF_PARTITION y
diff -Nru a/fs/partitions/Makefile b/fs/partitions/Makefile
--- a/fs/partitions/Makefile	Sun Apr 14 12:16:58 2002
+++ b/fs/partitions/Makefile	Sun Apr 14 12:16:58 2002
@@ -24,6 +24,7 @@
 obj-$(CONFIG_SUN_PARTITION) += sun.o
 obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
 obj-$(CONFIG_IBM_PARTITION) += ibm.o
+obj-$(CONFIG_EFI_PARTITION) += efi.o
 
 include $(TOPDIR)/Rules.make
 
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Sun Apr 14 12:16:57 2002
+++ b/fs/partitions/check.c	Sun Apr 14 12:16:57 2002
@@ -35,6 +35,7 @@
 #include "sun.h"
 #include "ibm.h"
 #include "ultrix.h"
+#include "efi.h"
 
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
 
@@ -42,6 +43,9 @@
 			   unsigned long first_sect, int first_minor) = {
 #ifdef CONFIG_ACORN_PARTITION
 	acorn_partition,
+#endif
+#ifdef CONFIG_EFI_PARTITION
+	efi_partition,		/* this must come before msdos */
 #endif
 #ifdef CONFIG_LDM_PARTITION
 	ldm_partition,		/* this must come before msdos */
diff -Nru a/fs/partitions/efi.c b/fs/partitions/efi.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/partitions/efi.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,755 @@
+/************************************************************
+ * EFI GUID Partition Table handling
+ * Per Intel EFI Specification v1.02
+ * http://developer.intel.com/technology/efi/efi.htm
+ * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
+ *   Copyright 2000,2001,2002 Dell Computer Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * TODO:
+ *
+ * Changelog:
+ * Tue  Mar 26 2002 Matt Domsch <Matt_Domsch@dell.com>
+ * - Ported to 2.5.7-pre1 and 2.5.7-dj2
+ * - Applied patch to avoid fault in alternate header handling
+ * - cleaned up find_valid_gpt
+ * - On-disk structure and copy in memory is *always* LE now - 
+ *   swab fields as needed
+ * - remove print_gpt_header()
+ * - only use first max_p partition entries, to keep the kernel minor number
+ *   and partition numbers tied.
+ *
+ * Mon  Feb 04 2002 Matt Domsch <Matt_Domsch@dell.com>
+ * - Removed __PRIPTR_PREFIX - not being used
+ *
+ * Mon  Jan 14 2002 Matt Domsch <Matt_Domsch@dell.com>
+ * - Ported to 2.5.2-pre11 + library crc32 patch Linus applied
+ *
+ * Thu Dec 6 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Added compare_gpts().
+ * - moved le_efi_guid_to_cpus() back into this file.  GPT is the only
+ *   thing that keeps EFI GUIDs on disk.
+ * - Changed gpt structure names and members to be simpler and more Linux-like.
+ * 
+ * Wed Oct 17 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Removed CONFIG_DEVFS_VOLUMES_UUID code entirely per Martin Wilck
+ *
+ * Wed Oct 10 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Changed function comments to DocBook style per Andreas Dilger suggestion.
+ *
+ * Mon Oct 08 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Change read_lba() to use the page cache per Al Viro's work.
+ * - print u64s properly on all architectures
+ * - fixed debug_printk(), now Dprintk()
+ *
+ * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Style cleanups
+ * - made most functions static
+ * - Endianness addition
+ * - remove test for second alternate header, as it's not per spec,
+ *   and is unnecessary.  There's now a method to read/write the last
+ *   sector of an odd-sized disk from user space.  No tools have ever
+ *   been released which used this code, so it's effectively dead.
+ * - Per Asit Mallick of Intel, added a test for a valid PMBR.
+ * - Added kernel command line option 'gpt' to override valid PMBR test.
+ *
+ * Wed Jun  6 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>
+ * - added devfs volume UUID support (/dev/volumes/uuids) for
+ *   mounting file systems by the partition GUID. 
+ *
+ * Tue Dec  5 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Moved crc32() to linux/lib, added efi_crc32().
+ *
+ * Thu Nov 30 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Replaced Intel's CRC32 function with an equivalent
+ *   non-license-restricted version.
+ *
+ * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Fixed the last_lba() call to return the proper last block
+ *
+ * Thu Oct 12 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Thanks to Andries Brouwer for his debugging assistance.
+ * - Code works, detects all the partitions.
+ *
+ ************************************************************/
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/blkpg.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include "check.h"
+#include "efi.h"
+
+#if CONFIG_BLK_DEV_MD
+extern void md_autodetect_dev(kdev_t dev);
+#endif
+
+/* Handle printing of 64-bit values */
+/* Borrowed from /usr/include/inttypes.h */
+# if BITS_PER_LONG == 64 
+#  define __PRI64_PREFIX	"l"
+# else
+#  define __PRI64_PREFIX	"ll"
+# endif
+# define PRIx64		__PRI64_PREFIX "x"
+
+
+#undef EFI_DEBUG
+#ifdef EFI_DEBUG
+#define Dprintk(x...) printk(KERN_DEBUG x)
+#else
+#define Dprintk(x...)
+#endif
+
+/* This allows a kernel command line option 'gpt' to override
+ * the test for invalid PMBR.  Not __initdata because reloading
+ * the partition tables happens after init too.
+ */
+static int force_gpt;
+static int __init
+force_gpt_fn(char *str)
+{
+	force_gpt = 1;
+	return 1;
+}
+__setup("gpt", force_gpt_fn);
+
+
+/**
+ * efi_crc32() - EFI version of crc32 function
+ * @buf: buffer to calculate crc32 of
+ * @len - length of buf
+ *
+ * Description: Returns EFI-style CRC32 value for @buf
+ * 
+ * This function uses the little endian Ethernet polynomial
+ * but seeds the function with ~0, and xor's with ~0 at the end.
+ * Note, the EFI Specification, v1.02, has a reference to
+ * Dr. Dobbs Journal, May 1994 (actually it's in May 1992).
+ */
+static inline u32
+efi_crc32(const void *buf, unsigned long len)
+{
+	return (crc32(~0L, buf, len) ^ ~0L);
+}
+
+/**
+ * is_pmbr_valid(): test Protective MBR for validity
+ * @mbr: pointer to a legacy mbr structure
+ *
+ * Description: Returns 1 if PMBR is valid, 0 otherwise.
+ * Validity depends on two things:
+ *  1) MSDOS signature is in the last two bytes of the MBR
+ *  2) One partition of type 0xEE is found
+ */
+static int
+is_pmbr_valid(legacy_mbr *mbr)
+{
+	int i, found = 0, signature = 0;
+	if (!mbr)
+		return 0;
+	signature = (le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
+	for (i = 0; signature && i < 4; i++) {
+		if (mbr->partition_record[i].sys_ind ==
+                    EFI_PMBR_OSTYPE_EFI_GPT) {
+			found = 1;
+			break;
+		}
+	}
+	return (signature && found);
+}
+
+/**
+ * last_lba(): return number of last logical block of device
+ * @hd: gendisk with partition list
+ * @bdev: block device
+ * 
+ * Description: Returns last LBA value on success, 0 on error.
+ * This is stored (by sd and ide-geometry) in
+ *  the part[0] entry for this disk, and is the number of
+ *  physical sectors available on the disk.
+ */
+static u64
+last_lba(struct gendisk *hd, struct block_device *bdev)
+{
+	if (!hd || !hd->part || !bdev)
+		return 0;
+	return hd->part[minor(to_kdev_t(bdev->bd_dev))].nr_sects - 1;
+}
+
+/**
+ * read_lba(): Read bytes from disk, starting at given LBA
+ * @hd
+ * @bdev
+ * @lba
+ * @buffer
+ * @size_t
+ *
+ * Description:  Reads @count bytes from @bdev into @buffer.
+ * Returns number of bytes read on success, 0 on error.
+ */
+static size_t
+read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
+	 u8 * buffer, size_t count)
+{
+
+	size_t totalreadcount = 0, bytesread = 0;
+	unsigned long blocksize;
+	int i;
+	Sector sect;
+	unsigned char *data = NULL;
+
+	if (!hd || !bdev || !buffer || !count)
+		return 0;
+
+	blocksize = get_hardsect_size(to_kdev_t(bdev->bd_dev));
+	if (!blocksize)
+		blocksize = 512;
+
+	for (i = 0; count > 0; i++) {
+		data = read_dev_sector(bdev, lba, &sect);
+		if (!data)
+			return totalreadcount;
+
+		bytesread =
+		    PAGE_CACHE_SIZE - (data -
+				       (unsigned char *) page_address(sect.v));
+		bytesread = min(bytesread, count);
+		memcpy(buffer, data, bytesread);
+		put_dev_sector(sect);
+
+		buffer += bytesread;
+		totalreadcount += bytesread;
+		count -= bytesread;
+		lba += (bytesread / blocksize);
+	}
+	return totalreadcount;
+}
+
+
+/**
+ * alloc_read_gpt_entries(): reads partition entries from disk
+ * @hd
+ * @bdev
+ * @gpt - GPT header
+ * 
+ * Description: Returns ptes on success,  NULL on error.
+ * Allocates space for PTEs based on information found in @gpt.
+ * Notes: remember to free pte when you're done!
+ */
+static gpt_entry *
+alloc_read_gpt_entries(struct gendisk *hd,
+		       struct block_device *bdev, gpt_header *gpt)
+{
+	size_t count;
+	gpt_entry *pte;
+	if (!hd || !bdev || !gpt)
+		return NULL;
+
+	count = le32_to_cpu(gpt->num_partition_entries) *
+                le32_to_cpu(gpt->sizeof_partition_entry);
+	if (!count)
+		return NULL;
+	pte = kmalloc(count, GFP_KERNEL);
+	if (!pte)
+		return NULL;
+	memset(pte, 0, count);
+
+	if (read_lba(hd, bdev, le64_to_cpu(gpt->partition_entry_lba),
+                     (u8 *) pte,
+		     count) < count) {
+		kfree(pte);
+                pte=NULL;
+		return NULL;
+	}
+	return pte;
+}
+
+/**
+ * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
+ * @hd
+ * @bdev
+ * @lba is the Logical Block Address of the partition table
+ * 
+ * Description: returns GPT header on success, NULL on error.   Allocates
+ * and fills a GPT header starting at @ from @bdev.
+ * Note: remember to free gpt when finished with it.
+ */
+static gpt_header *
+alloc_read_gpt_header(struct gendisk *hd, struct block_device *bdev, u64 lba)
+{
+	gpt_header *gpt;
+	if (!hd || !bdev)
+		return NULL;
+
+	gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL);
+	if (!gpt)
+		return NULL;
+	memset(gpt, 0, sizeof (gpt_header));
+
+	if (read_lba(hd, bdev, lba, (u8 *) gpt,
+		     sizeof (gpt_header)) < sizeof (gpt_header)) {
+		kfree(gpt);
+                gpt=NULL;
+		return NULL;
+	}
+
+	return gpt;
+}
+
+/**
+ * is_gpt_valid() - tests one GPT header and PTEs for validity
+ * @hd
+ * @bdev
+ * @lba is the logical block address of the GPT header to test
+ * @gpt is a GPT header ptr, filled on return.
+ * @ptes is a PTEs ptr, filled on return.
+ *
+ * Description: returns 1 if valid,  0 on error.
+ * If valid, returns pointers to newly allocated GPT header and PTEs.
+ */
+static int
+is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
+	     gpt_header **gpt, gpt_entry **ptes)
+{
+	u32 crc, origcrc;
+
+	if (!hd || !bdev || !gpt || !ptes)
+		return 0;
+	if (!(*gpt = alloc_read_gpt_header(hd, bdev, lba)))
+		return 0;
+
+	/* Check the GUID Partition Table signature */
+	if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
+		Dprintk("GUID Partition Table Header signature is wrong: %"
+			PRIx64 " != %" PRIx64 "\n", le64_to_cpu((*gpt)->signature),
+			GPT_HEADER_SIGNATURE);
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+
+	/* Check the GUID Partition Table CRC */
+	origcrc = le32_to_cpu((*gpt)->header_crc32);
+	(*gpt)->header_crc32 = 0;
+	crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size));
+
+	if (crc != origcrc) {
+		Dprintk
+		    ("GUID Partition Table Header CRC is wrong: %x != %x\n",
+		     crc, origcrc);
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+	(*gpt)->header_crc32 = cpu_to_le32(origcrc);
+
+	/* Check that the my_lba entry points to the LBA that contains
+	 * the GUID Partition Table */
+	if (le64_to_cpu((*gpt)->my_lba) != lba) {
+		Dprintk("GPT my_lba incorrect: %" PRIx64 " != %" PRIx64 "\n",
+			le64_to_cpu((*gpt)->my_lba), lba);
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+
+	if (!(*ptes = alloc_read_gpt_entries(hd, bdev, *gpt))) {
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+
+	/* Check the GUID Partition Entry Array CRC */
+	crc = efi_crc32((const unsigned char *) (*ptes),
+			le32_to_cpu((*gpt)->num_partition_entries) *
+			le32_to_cpu((*gpt)->sizeof_partition_entry));
+
+	if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
+		Dprintk("GUID Partitition Entry Array CRC check failed.\n");
+		kfree(*gpt);
+		*gpt = NULL;
+		kfree(*ptes);
+		*ptes = NULL;
+		return 0;
+	}
+
+	/* We're done, all's well */
+	return 1;
+}
+
+/**
+ * compare_gpts() - Search disk for valid GPT headers and PTEs
+ * @pgpt is the primary GPT header
+ * @agpt is the alternate GPT header
+ * @lastlba is the last LBA number
+ * Description: Returns nothing.  Sanity checks pgpt and agpt fields
+ * and prints warnings on discrepancies.
+ * 
+ */
+static void
+compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba)
+{
+	int error_found = 0;
+	if (!pgpt || !agpt)
+		return;
+	if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) {
+		printk(KERN_WARNING
+		       "GPT:Primary header LBA != Alt. header alternate_lba\n");
+		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
+		       le64_to_cpu(pgpt->my_lba),
+                       le64_to_cpu(agpt->alternate_lba));
+		error_found++;
+	}
+	if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) {
+		printk(KERN_WARNING
+		       "GPT:Primary header alternate_lba != Alt. header my_lba\n");
+		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
+		       le64_to_cpu(pgpt->alternate_lba),
+                       le64_to_cpu(agpt->my_lba));
+		error_found++;
+	}
+	if (le64_to_cpu(pgpt->first_usable_lba) !=
+            le64_to_cpu(agpt->first_usable_lba)) {
+		printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n");
+		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
+		       le64_to_cpu(pgpt->first_usable_lba),
+                       le64_to_cpu(agpt->first_usable_lba));
+		error_found++;
+	}
+	if (le64_to_cpu(pgpt->last_usable_lba) !=
+            le64_to_cpu(agpt->last_usable_lba)) {
+		printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n");
+		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
+		       le64_to_cpu(pgpt->last_usable_lba),
+                       le64_to_cpu(agpt->last_usable_lba));
+		error_found++;
+	}
+	if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
+		printk(KERN_WARNING "GPT:disk_guids don't match.\n");
+		error_found++;
+	}
+	if (le32_to_cpu(pgpt->num_partition_entries) !=
+            le32_to_cpu(agpt->num_partition_entries)) {
+		printk(KERN_WARNING "GPT:num_partition_entries don't match: "
+		       "0x%x != 0x%x\n",
+		       le32_to_cpu(pgpt->num_partition_entries),
+		       le32_to_cpu(agpt->num_partition_entries));
+		error_found++;
+	}
+	if (le32_to_cpu(pgpt->sizeof_partition_entry) !=
+            le32_to_cpu(agpt->sizeof_partition_entry)) {
+		printk(KERN_WARNING
+		       "GPT:sizeof_partition_entry values don't match: "
+		       "0x%x != 0x%x\n",
+                       le32_to_cpu(pgpt->sizeof_partition_entry),
+		       le32_to_cpu(agpt->sizeof_partition_entry));
+		error_found++;
+	}
+	if (le32_to_cpu(pgpt->partition_entry_array_crc32) !=
+            le32_to_cpu(agpt->partition_entry_array_crc32)) {
+		printk(KERN_WARNING
+		       "GPT:partition_entry_array_crc32 values don't match: "
+		       "0x%x != 0x%x\n",
+                       le32_to_cpu(pgpt->partition_entry_array_crc32),
+		       le32_to_cpu(agpt->partition_entry_array_crc32));
+		error_found++;
+	}
+	if (le64_to_cpu(pgpt->alternate_lba) != lastlba) {
+		printk(KERN_WARNING
+		       "GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
+		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
+		       le64_to_cpu(pgpt->alternate_lba), lastlba);
+		error_found++;
+	}
+
+	if (le64_to_cpu(agpt->my_lba) != lastlba) {
+		printk(KERN_WARNING
+		       "GPT:Alternate GPT header not at the end of the disk.\n");
+		printk(KERN_WARNING "GPT:%" PRIx64 " != %" PRIx64 "\n",
+		       le64_to_cpu(agpt->my_lba), lastlba);
+		error_found++;
+	}
+
+	if (error_found)
+		printk(KERN_WARNING
+		       "GPT: Use GNU Parted to correct GPT errors.\n");
+	return;
+}
+
+/**
+ * find_valid_gpt() - Search disk for valid GPT headers and PTEs
+ * @hd
+ * @bdev
+ * @gpt is a GPT header ptr, filled on return.
+ * @ptes is a PTEs ptr, filled on return.
+ * Description: Returns 1 if valid, 0 on error.
+ * If valid, returns pointers to newly allocated GPT header and PTEs.
+ * Validity depends on finding either the Primary GPT header and PTEs valid,
+ * or the Alternate GPT header and PTEs valid, and the PMBR valid.
+ */
+static int
+find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
+	       gpt_header **gpt, gpt_entry **ptes)
+{
+	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
+	gpt_header *pgpt = NULL, *agpt = NULL;
+	gpt_entry *pptes = NULL, *aptes = NULL;
+	legacy_mbr *legacymbr = NULL;
+	u64 lastlba;
+	if (!hd || !bdev || !gpt || !ptes)
+		return 0;
+
+	lastlba = last_lba(hd, bdev);
+	good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
+				 &pgpt, &pptes);
+        if (good_pgpt) {
+		good_agpt = is_gpt_valid(hd, bdev,
+                                         le64_to_cpu(pgpt->alternate_lba),
+					 &agpt, &aptes);
+                if (!good_agpt) {
+                        good_agpt = is_gpt_valid(hd, bdev, lastlba,
+                                                 &agpt, &aptes);
+                }
+        }
+        else {
+                good_agpt = is_gpt_valid(hd, bdev, lastlba,
+                                         &agpt, &aptes);
+        }
+
+        /* The obviously unsuccessful case */
+        if (!good_pgpt && !good_agpt) {
+                goto fail;
+        }
+
+	/* This will be added to the EFI Spec. per Intel after v1.02. */
+        legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
+        if (legacymbr) {
+                memset(legacymbr, 0, sizeof (*legacymbr));
+                read_lba(hd, bdev, 0, (u8 *) legacymbr,
+                         sizeof (*legacymbr));
+                good_pmbr = is_pmbr_valid(legacymbr);
+                kfree(legacymbr);
+                legacymbr=NULL;
+        }
+
+        /* Failure due to bad PMBR */
+        if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
+                printk(KERN_WARNING 
+                       "  Warning: Disk has a valid GPT signature "
+                       "but invalid PMBR.\n");
+                printk(KERN_WARNING
+                       "  Assuming this disk is *not* a GPT disk anymore.\n");
+                printk(KERN_WARNING
+                       "  Use gpt kernel option to override.  "
+                       "Use GNU Parted to correct disk.\n");
+                goto fail;
+        }
+
+        /* Would fail due to bad PMBR, but force GPT anyhow */
+        if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
+                printk(KERN_WARNING
+                       "  Warning: Disk has a valid GPT signature but "
+                       "invalid PMBR.\n");
+                printk(KERN_WARNING
+                       "  Use GNU Parted to correct disk.\n");
+                printk(KERN_WARNING
+                       "  gpt option taken, disk treated as GPT.\n");
+        }
+
+        compare_gpts(pgpt, agpt, lastlba);
+
+        /* The good cases */
+        if (good_pgpt && (good_pmbr || force_gpt)) {
+                *gpt  = pgpt;
+                *ptes = pptes;
+                if (agpt)  { kfree(agpt);   agpt = NULL; }
+                if (aptes) { kfree(aptes); aptes = NULL; }
+                if (!good_agpt) {
+                        printk(KERN_WARNING 
+			       "Alternate GPT is invalid, "
+                               "using primary GPT.\n");
+                }
+                return 1;
+        }
+        else if (good_agpt && (good_pmbr || force_gpt)) {
+                *gpt  = agpt;
+                *ptes = aptes;
+                if (pgpt)  { kfree(pgpt);   pgpt = NULL; }
+                if (pptes) { kfree(pptes); pptes = NULL; }
+                printk(KERN_WARNING 
+                       "Primary GPT is invalid, using alternate GPT.\n");
+                return 1;
+        }
+
+ fail:
+        if (pgpt)  { kfree(pgpt);   pgpt=NULL; }
+        if (agpt)  { kfree(agpt);   agpt=NULL; }
+        if (pptes) { kfree(pptes); pptes=NULL; }
+        if (aptes) { kfree(aptes); aptes=NULL; }
+        *gpt = NULL;
+        *ptes = NULL;
+        return 0;
+}
+
+/**
+ * add_gpt_partitions(struct gendisk *hd, struct block_device *bdev,
+ * @hd
+ * @bdev
+ *
+ * Description: Create devices for each entry in the GUID Partition Table
+ * Entries.
+ *
+ * We do not create a Linux partition for GPT, but
+ * only for the actual data partitions.
+ * Returns:
+ * -1 if unable to read the partition table
+ *  0 if this isn't our partition table
+ *  1 if successful
+ *
+ */
+static int
+add_gpt_partitions(struct gendisk *hd, struct block_device *bdev, int nextminor)
+{
+	gpt_header *gpt = NULL;
+	gpt_entry *ptes = NULL;
+	u32 i;
+	int max_p; 
+
+	if (!hd || !bdev)
+		return -1;
+
+	if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
+		if (gpt) {
+			kfree(gpt);
+                        gpt = NULL;
+                }
+		if (ptes) {
+			kfree(ptes);
+                        ptes = NULL;
+                }
+		return 0;
+	}
+
+	Dprintk("GUID Partition Table is valid!  Yea!\n");
+
+	max_p = (1 << hd->minor_shift) - 1;
+	for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < max_p; i++) {
+		if (!efi_guidcmp(ptes[i].partition_type_guid, NULL_GUID))
+			continue;
+
+		add_gd_partition(hd, nextminor+i,
+                                 le64_to_cpu(ptes[i].starting_lba),
+				 (le64_to_cpu(ptes[i].ending_lba) -
+                                  le64_to_cpu(ptes[i].starting_lba) +
+				  1));
+
+		/* If there's this is a RAID volume, tell md */
+#if CONFIG_BLK_DEV_MD
+		if (!efi_guidcmp(ptes[i].partition_type_guid,
+                                 PARTITION_LINUX_RAID_GUID)) {
+			md_autodetect_dev(mk_kdev(hd->major,
+                                                  nextminor));
+		}
+#endif
+	}
+	kfree(ptes);
+        ptes=NULL;
+	kfree(gpt);
+        gpt=NULL;
+	printk("\n");
+	return 1;
+}
+
+/**
+ * efi_partition(): EFI GPT partition handling entry function
+ * @hd
+ * @bdev
+ * @first_sector: unused
+ * @first_part_minor: minor number assigned to first GPT partition found
+ *
+ * Description: called from check.c, if the disk contains GPT
+ * partitions, sets up partition entries in the kernel.
+ *
+ * If the first block on the disk is a legacy MBR,
+ * it will get handled by msdos_partition().
+ * If it's a Protective MBR, we'll handle it here.
+ *
+ * set_blocksize() calls are necessary to be able to read
+ * a disk with an odd number of 512-byte sectors, as the
+ * default BLOCK_SIZE of 1024 bytes won't let that last
+ * sector be read otherwise.
+ *
+ * Returns:
+ * -1 if unable to read the partition table
+ *  0 if this isn't our partitoin table
+ *  1 if successful
+ */
+int
+efi_partition(struct gendisk *hd, struct block_device *bdev,
+	      unsigned long first_sector, int first_part_minor)
+{
+
+	kdev_t dev = to_kdev_t(bdev->bd_dev);
+	int hardblocksize = get_hardsect_size(dev);
+	int orig_blksize_size = BLOCK_SIZE;
+	int rc = 0;
+
+	/* Need to change the block size that the block layer uses */
+	if (blksize_size[major(dev)]) {
+		orig_blksize_size = blksize_size[major(dev)][minor(dev)];
+	}
+
+	if (orig_blksize_size != hardblocksize)
+		set_blocksize(dev, hardblocksize);
+
+	rc = add_gpt_partitions(hd, bdev, first_part_minor);
+
+	/* change back */
+	if (orig_blksize_size != hardblocksize)
+		set_blocksize(dev, orig_blksize_size);
+
+	return rc;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -Nru a/fs/partitions/efi.h b/fs/partitions/efi.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/partitions/efi.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,138 @@
+/************************************************************
+ * EFI GUID Partition Table
+ * Per Intel EFI Specification v1.02
+ * http://developer.intel.com/technology/efi/efi.htm
+ *
+ * By Matt Domsch <Matt_Domsch@dell.com>  Fri Sep 22 22:15:56 CDT 2000  
+ *   Copyright 2000,2001 Dell Computer Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ ************************************************************/
+
+#ifndef FS_PART_EFI_H_INCLUDED
+#define FS_PART_EFI_H_INCLUDED
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+/*
+ * Yes, specifying asm-ia64 is ugly, but this lets it build on
+ * other platforms too, until efi.h moves to include/linux.
+ */
+#include <asm-ia64/efi.h>
+
+#define MSDOS_MBR_SIGNATURE 0xaa55
+#define EFI_PMBR_OSTYPE_EFI 0xEF
+#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
+
+#define GPT_BLOCK_SIZE 512
+#define GPT_HEADER_SIGNATURE 0x5452415020494645L
+#define GPT_HEADER_REVISION_V1 0x00010000
+#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
+
+#define PARTITION_SYSTEM_GUID \
+    EFI_GUID( 0xC12A7328, 0xF81F, 0x11d2, \
+              0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B) 
+#define LEGACY_MBR_PARTITION_GUID \
+    EFI_GUID( 0x024DEE41, 0x33E7, 0x11d3, \
+              0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F)
+#define PARTITION_MSFT_RESERVED_GUID \
+    EFI_GUID( 0xE3C9E316, 0x0B5C, 0x4DB8, \
+              0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE)
+#define PARTITION_BASIC_DATA_GUID \
+    EFI_GUID( 0xEBD0A0A2, 0xB9E5, 0x4433, \
+              0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7)
+#define PARTITION_LINUX_RAID_GUID \
+    EFI_GUID( 0xa19d880f, 0x05fc, 0x4d3b, \
+              0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e)
+#define PARTITION_LINUX_SWAP_GUID \
+    EFI_GUID( 0x0657fd6d, 0xa4ab, 0x43c4, \
+              0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f)
+#define PARTITION_LINUX_LVM_GUID \
+    EFI_GUID( 0xe6d6d379, 0xf507, 0x44c2, \
+              0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
+
+typedef struct _gpt_header {
+	u64 signature;
+	u32 revision;
+	u32 header_size;
+	u32 header_crc32;
+	u32 reserved1;
+	u64 my_lba;
+	u64 alternate_lba;
+	u64 first_usable_lba;
+	u64 last_usable_lba;
+	efi_guid_t disk_guid;
+	u64 partition_entry_lba;
+	u32 num_partition_entries;
+	u32 sizeof_partition_entry;
+	u32 partition_entry_array_crc32;
+	u8 reserved2[GPT_BLOCK_SIZE - 92];
+} __attribute__ ((packed)) gpt_header;
+
+typedef struct _gpt_entry_attributes {
+	u64 required_to_function:1;
+	u64 reserved:47;
+        u64 type_guid_specific:16;
+} __attribute__ ((packed)) gpt_entry_attributes;
+
+typedef struct _gpt_entry {
+	efi_guid_t partition_type_guid;
+	efi_guid_t unique_partition_guid;
+	u64 starting_lba;
+	u64 ending_lba;
+	gpt_entry_attributes attributes;
+	efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
+} __attribute__ ((packed)) gpt_entry;
+
+typedef struct _legacy_mbr {
+	u8 boot_code[440];
+	u32 unique_mbr_signature;
+	u16 unknown;
+	struct partition partition_record[4];
+	u16 signature;
+} __attribute__ ((packed)) legacy_mbr;
+
+/* Functions */
+extern int
+ efi_partition(struct gendisk *hd, struct block_device *bdev,
+	      unsigned long first_sector, int first_part_minor);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * --------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -Nru a/fs/partitions/msdos.c b/fs/partitions/msdos.c
--- a/fs/partitions/msdos.c	Sun Apr 14 12:16:55 2002
+++ b/fs/partitions/msdos.c	Sun Apr 14 12:16:55 2002
@@ -41,6 +41,7 @@
 
 #include "check.h"
 #include "msdos.h"
+#include "efi.h"
 
 #if CONFIG_BLK_DEV_MD
 extern void md_autodetect_dev(kdev_t dev);
@@ -536,6 +537,16 @@
 		return 0;
 	}
 	p = (struct partition *) (data + 0x1be);
+#ifdef CONFIG_EFI_PARTITION
+	for (i=1 ; i<=4 ; i++,p++) {
+		/* If this is an EFI GPT disk, msdos should ignore it. */
+		if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
+			put_dev_sector(sect);
+			return 0;
+		}
+	}
+	p = (struct partition *) (data + 0x1be);
+#endif
 
 	/*
 	 * Look for partitions in two passes:
diff -Nru a/fs/proc/array.c b/fs/proc/array.c
--- a/fs/proc/array.c	Sun Apr 14 12:16:55 2002
+++ b/fs/proc/array.c	Sun Apr 14 12:16:55 2002
@@ -227,6 +227,7 @@
 	sigemptyset(ign);
 	sigemptyset(catch);
 
+	spin_lock_irq(&p->sigmask_lock);
 	if (p->sig) {
 		k = p->sig->action;
 		for (i = 1; i <= _NSIG; ++i, ++k) {
@@ -236,6 +237,7 @@
 				sigaddset(catch, i);
 		}
 	}
+	spin_unlock_irq(&p->sigmask_lock);
 }
 
 static inline char * task_sig(struct task_struct *p, char *buffer)
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c	Sun Apr 14 12:16:58 2002
+++ b/fs/proc/generic.c	Sun Apr 14 12:16:58 2002
@@ -404,7 +404,7 @@
 	 * Actually it's a partial revoke().
 	 */
 	file_list_lock();
-	for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
+	list_for_each(p, &sb->s_files) {
 		struct file * filp = list_entry(p, struct file, f_list);
 		struct dentry * dentry = filp->f_dentry;
 		struct inode * inode;
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c	Sun Apr 14 12:16:57 2002
+++ b/fs/proc/inode.c	Sun Apr 14 12:16:57 2002
@@ -133,8 +133,11 @@
 
 	*uid = current->uid;
 	*gid = current->gid;
-	if (!options) return 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	if (!options)
+		return 1;
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
 		if (!strcmp(this_char,"uid")) {
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Sun Apr 14 12:16:56 2002
+++ b/fs/proc/proc_misc.c	Sun Apr 14 12:16:56 2002
@@ -51,7 +51,6 @@
  * wrappers, but this needs further analysis wrt potential overflows.
  */
 extern int get_device_list(char *);
-extern int get_partition_list(char *, char **, off_t, int);
 extern int get_filesystem_list(char *);
 extern int get_exec_domain_list(char *);
 extern int get_dma_list(char *);
@@ -199,6 +198,18 @@
 	release:	seq_release,
 };
 
+extern struct seq_operations partitions_op;
+static int partitions_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &partitions_op);
+}
+static struct file_operations proc_partitions_operations = {
+	open:		partitions_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
+
 #ifdef CONFIG_MODULES
 extern struct seq_operations modules_op;
 static int modules_open(struct inode *inode, struct file *file)
@@ -323,14 +334,6 @@
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-static int partitions_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
-{
-	int len = get_partition_list(page, start, off, count);
-	if (len < count) *eof = 1;
-	return len;
-}
-
 static void *single_start(struct seq_file *p, loff_t *pos)
 {
 	return NULL + (*pos == 0);
@@ -538,7 +541,6 @@
 		{"version",	version_read_proc},
 		{"stat",	kstat_read_proc},
 		{"devices",	devices_read_proc},
-		{"partitions",	partitions_read_proc},
 		{"filesystems",	filesystems_read_proc},
 		{"dma",		dma_read_proc},
 		{"ioports",	ioports_read_proc},
@@ -562,6 +564,7 @@
 	if (entry)
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+	create_seq_entry("partitions", 0, &proc_partitions_operations);
 	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
 	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 #ifdef CONFIG_MODULES
diff -Nru a/fs/qnx4/BUGS b/fs/qnx4/BUGS
--- a/fs/qnx4/BUGS	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,30 +0,0 @@
-Last update: 1999-12-23
-
-- Fragmented files and directories were incorrectly handled.
-  Fixed 1999-12-23, Anders.
-
-- readdir sometimes returned the same dir entry more than once.
-  Fixed 1999-12-13, Anders.
-
-- File names with a length of exactly 16 chars were handled incorrectly.
-  Fixed 1999-12-11, Anders.
-
-- Files in a subdir can't be accessed, I think that the inode information
-  is not correctly copied at some point. Solved 06-06-1998, Richard.
-  
-- At some point the mounted device can't be unmounted. I think that somewhere
-  in the code a buffer is not given free.
-
-- Make the '..' entry work, I give it a great chance that the above bug
-  (not given free) has something to do with this one, after a 'ls -l'
-  the mounted device can't be unmounted and that's where the '..' entry
-  is accessed.
-  Seems to be solved 21-06-1998, Frank.
-
-- File read function not correct, after the first block it goes beserk.
-  Solved 21-06-1998, Frank.
-
-- This fs will not work if not built as a module.
-  Solved 25-06-1998, Frank.
-
-- Write/truncate/delete functions don't update the bitmap.
diff -Nru a/fs/qnx4/TODO b/fs/qnx4/TODO
--- a/fs/qnx4/TODO	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,30 +0,0 @@
-Name       : QNX4 TODO list
-Last update: 1999-12-23
-
-    - Writing is still unsupported (it may compile, but it certainly won't
-      bring you any joy).
-
-    - qnx4_checkroot (inode.c), currently there's a look for the '/' in
-      the root direntry, if so then the current mounted device is a qnx4
-      partition. This has to be rewritten with a look for 'QNX4' in the
-      bootblock, it seems to me the savest way to ensure that the mounted
-      device is in fact a QNX4 partition.
-      Done 20-06-1998, Frank. But some disks (like QNX install floppies)
-      don't have 'QNX4' in their bootblock.
-      
-    - Bitmap functions. To find out the free space, largest free block, etc.
-      Partly done (RO), Richard, 05/06/1998. Optimized 20-06-1998, Frank.
-    
-    - Complete write, unlink and truncate functions : the bitmap should be
-updated.
-
-    - Porting to linux 2.1.99+ with dcache support. 20-06-1998, Frank.
-    
-    - Don't rewrite the file_read function : use the generic_file_read hook,
-      and write readpage instead. Done on 21-06-1998, Frank.
-
-    - Write dinit and dcheck.
-
-    - Solving the bugs.
-    
-    - Use le32_to_cpu and vice-versa for portability.
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Sun Apr 14 12:16:59 2002
+++ b/fs/read_write.c	Sun Apr 14 12:16:59 2002
@@ -37,7 +37,6 @@
 	if (offset>=0 && offset<=inode->i_sb->s_maxbytes) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
-			file->f_reada = 0;
 			file->f_version = ++event;
 		}
 		retval = offset;
@@ -62,7 +61,6 @@
 	if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
-			file->f_reada = 0;
 			file->f_version = ++event;
 		}
 		retval = offset;
@@ -92,7 +90,6 @@
 	if (offset >= 0) {
 		if (offset != file->f_pos) {
 			file->f_pos = offset;
-			file->f_reada = 0;
 			file->f_version = ++event;
 		}
 		retval = offset;
diff -Nru a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile
--- a/fs/reiserfs/Makefile	Sun Apr 14 12:16:58 2002
+++ b/fs/reiserfs/Makefile	Sun Apr 14 12:16:58 2002
@@ -9,7 +9,7 @@
 
 O_TARGET := reiserfs.o
 obj-y   := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o super.o prints.o objectid.o \
-lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o tail_conversion.o item_ops.o ioctl.o procfs.o
+lbalance.o ibalance.o stree.o hashes.o buffer2.o tail_conversion.o journal.o resize.o item_ops.o ioctl.o procfs.o
 
 obj-m   := $(O_TARGET)
 
diff -Nru a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c
--- a/fs/reiserfs/dir.c	Sun Apr 14 12:16:54 2002
+++ b/fs/reiserfs/dir.c	Sun Apr 14 12:16:54 2002
@@ -180,6 +180,7 @@
     filp->f_pos = next_pos;
     pathrelse (&path_to_entry);
     reiserfs_check_path(&path_to_entry) ;
+    UPDATE_ATIME(inode) ;
     return 0;
 }
 
diff -Nru a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
--- a/fs/reiserfs/do_balan.c	Sun Apr 14 12:16:56 2002
+++ b/fs/reiserfs/do_balan.c	Sun Apr 14 12:16:56 2002
@@ -1527,7 +1527,7 @@
     ** and then free them now
     */
 
-    tb->tb_sb->u.reiserfs_sb.s_do_balance ++;
+    REISERFS_SB(tb->tb_sb)->s_do_balance ++;
 
 
     /* release all nodes hold to perform the balancing */
diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c
--- a/fs/reiserfs/file.c	Sun Apr 14 12:16:54 2002
+++ b/fs/reiserfs/file.c	Sun Apr 14 12:16:54 2002
@@ -95,14 +95,16 @@
 static int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
     struct inode *inode = dentry->d_inode ;
     int error ;
+    lock_kernel();
     if (attr->ia_valid & ATTR_SIZE) {
 	/* version 2 items will be caught by the s_maxbytes check
 	** done for us in vmtruncate
 	*/
 	if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
-	    attr->ia_size > MAX_NON_LFS)
-            return -EFBIG ;
-
+	    attr->ia_size > MAX_NON_LFS) {
+	    error = -EFBIG ;
+	    goto out;
+	}
 	/* fill in hole pointers in the expanding truncate case. */
         if (attr->ia_size > inode->i_size) {
 	    error = generic_cont_expand(inode, attr->ia_size) ;
@@ -114,20 +116,24 @@
 		journal_end(&th, inode->i_sb, 4) ;
 	    }
 	    if (error)
-	        return error ;
+	        goto out;
 	}
     }
 
     if ((((attr->ia_valid & ATTR_UID) && (attr->ia_uid & ~0xffff)) ||
 	 ((attr->ia_valid & ATTR_GID) && (attr->ia_gid & ~0xffff))) &&
-	(get_inode_sd_version (inode) == STAT_DATA_V1))
+	(get_inode_sd_version (inode) == STAT_DATA_V1)) {
 		/* stat data of format v3.5 has 16 bit uid and gid */
-	    return -EINVAL;
+	    error = -EINVAL;
+	    goto out;	
+	}
 
     error = inode_change_ok(inode, attr) ;
     if (!error)
         inode_setattr(inode, attr) ;
 
+out:
+    unlock_kernel();
     return error ;
 }
 
diff -Nru a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
--- a/fs/reiserfs/fix_node.c	Sun Apr 14 12:16:57 2002
+++ b/fs/reiserfs/fix_node.c	Sun Apr 14 12:16:57 2002
@@ -1988,13 +1988,13 @@
 
     vp = kmalloc (size, flags);
     if (vp) {
-	s->u.reiserfs_sb.s_kmallocs += size;
-	if (s->u.reiserfs_sb.s_kmallocs > malloced + 200000) {
-	    reiserfs_warning ("vs-8301: reiserfs_kmalloc: allocated memory %d\n", s->u.reiserfs_sb.s_kmallocs);
-	    malloced = s->u.reiserfs_sb.s_kmallocs;
+	REISERFS_SB(s)->s_kmallocs += size;
+	if (REISERFS_SB(s)->s_kmallocs > malloced + 200000) {
+	    reiserfs_warning ("vs-8301: reiserfs_kmalloc: allocated memory %d\n", REISERFS_SB(s)->s_kmallocs);
+	    malloced = REISERFS_SB(s)->s_kmallocs;
 	}
     }
-/*printk ("malloc : size %d, allocated %d\n", size, s->u.reiserfs_sb.s_kmallocs);*/
+/*printk ("malloc : size %d, allocated %d\n", size, REISERFS_SB(s)->s_kmallocs);*/
     return vp;
 }
 
@@ -2002,9 +2002,9 @@
 {
     kfree (vp);
   
-    s->u.reiserfs_sb.s_kmallocs -= size;
-    if (s->u.reiserfs_sb.s_kmallocs < 0)
-	reiserfs_warning ("vs-8302: reiserfs_kfree: allocated memory %d\n", s->u.reiserfs_sb.s_kmallocs);
+    REISERFS_SB(s)->s_kmallocs -= size;
+    if (REISERFS_SB(s)->s_kmallocs < 0)
+	reiserfs_warning ("vs-8302: reiserfs_kfree: allocated memory %d\n", REISERFS_SB(s)->s_kmallocs);
 
 }
 #endif
@@ -2062,7 +2062,7 @@
 #ifdef CONFIG_REISERFS_CHECK
 		reiserfs_warning ("vs-8345: get_mem_for_virtual_node: "
 				  "kmalloc failed. reiserfs kmalloced %d bytes\n",
-				  tb->tb_sb->u.reiserfs_sb.s_kmallocs);
+				  REISERFS_SB(tb->tb_sb)->s_kmallocs);
 #endif
 		tb->vn_buf_size = 0;
 	    }
@@ -2290,7 +2290,7 @@
     int windex ;
     struct buffer_head  * p_s_tbS0 = PATH_PLAST_BUFFER(p_s_tb->tb_path);
 
-    ++ p_s_tb -> tb_sb -> u.reiserfs_sb.s_fix_nodes;
+    ++ REISERFS_SB(p_s_tb -> tb_sb) -> s_fix_nodes;
 
     n_pos_in_item = p_s_tb->tb_path->pos_in_item;
 
diff -Nru a/fs/reiserfs/ibalance.c b/fs/reiserfs/ibalance.c
--- a/fs/reiserfs/ibalance.c	Sun Apr 14 12:16:59 2002
+++ b/fs/reiserfs/ibalance.c	Sun Apr 14 12:16:59 2002
@@ -623,10 +623,10 @@
 		new_root = tb->L[h-1];
 	    /* switch super block's tree root block number to the new value */
             PUT_SB_ROOT_BLOCK( tb->tb_sb, new_root->b_blocknr );
-	    //tb->tb_sb->u.reiserfs_sb.s_rs->s_tree_height --;
+	    //REISERFS_SB(tb->tb_sb)->s_rs->s_tree_height --;
             PUT_SB_TREE_HEIGHT( tb->tb_sb, SB_TREE_HEIGHT(tb->tb_sb) - 1 );
 
-	    do_balance_mark_sb_dirty (tb, tb->tb_sb->u.reiserfs_sb.s_sbh, 1);
+	    do_balance_mark_sb_dirty (tb, REISERFS_SB(tb->tb_sb)->s_sbh, 1);
 	    /*&&&&&&&&&&&&&&&&&&&&&&*/
 	    if (h > 1)
 		/* use check_internal if new root is an internal node */
@@ -949,7 +949,7 @@
 	/* Change root in structure super block. */
         PUT_SB_ROOT_BLOCK( tb->tb_sb, tbSh->b_blocknr );
         PUT_SB_TREE_HEIGHT( tb->tb_sb, SB_TREE_HEIGHT(tb->tb_sb) + 1 );
-	do_balance_mark_sb_dirty (tb, tb->tb_sb->u.reiserfs_sb.s_sbh, 1);
+	do_balance_mark_sb_dirty (tb, REISERFS_SB(tb->tb_sb)->s_sbh, 1);
 	tb->tb_sb->s_dirt = 1;
     }
 	
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Sun Apr 14 12:16:57 2002
+++ b/fs/reiserfs/inode.c	Sun Apr 14 12:16:57 2002
@@ -146,8 +146,8 @@
 static inline void fix_tail_page_for_writing(struct page *page) {
     struct buffer_head *head, *next, *bh ;
 
-    if (page && page->buffers) {
-	head = page->buffers ;
+    if (page && page_has_buffers(page)) {
+	head = page_buffers(page) ;
 	bh = head ;
 	do {
 	    next = bh->b_this_page ;
@@ -745,13 +745,22 @@
 		if (retval) {
 		    if ( retval != -ENOSPC )
 			printk("clm-6004: convert tail failed inode %lu, error %d\n", inode->i_ino, retval) ;
-		    if (allocated_block_nr)
+		    if (allocated_block_nr) {
+			/* the bitmap, the super, and the stat data == 3 */
+			journal_begin(&th, inode->i_sb, 3) ;
 			reiserfs_free_block (&th, allocated_block_nr);
+			transaction_started = 1 ;
+		    }
 		    goto failure ;
 		}
 		goto research ;
 	    }
 	    retval = direct2indirect (&th, inode, &path, unbh, tail_offset);
+	    if (retval) {
+		reiserfs_unmap_buffer(unbh);
+		reiserfs_free_block (&th, allocated_block_nr);
+		goto failure;
+	    }
 	    /* it is important the mark_buffer_uptodate is done after
 	    ** the direct2indirect.  The buffer might contain valid
 	    ** data newer than the data on disk (read by readpage, changed,
@@ -761,10 +770,7 @@
 	    ** the disk
 	    */
 	    mark_buffer_uptodate (unbh, 1);
-	    if (retval) {
-		reiserfs_free_block (&th, allocated_block_nr);
-		goto failure;
-	    }
+
 	    /* we've converted the tail, so we must 
 	    ** flush unbh before the transaction commits
 	    */
@@ -933,9 +939,6 @@
 	// (directories and symlinks)
 	struct stat_data * sd = (struct stat_data *)B_I_PITEM (bh, ih);
 
-	/* both old and new directories have old keys */
-	//version = (S_ISDIR (sd->sd_mode) ? ITEM_VERSION_1 : ITEM_VERSION_2);
-
 	inode->i_mode   = sd_v2_mode(sd);
 	inode->i_nlink  = sd_v2_nlink(sd);
 	inode->i_uid    = sd_v2_uid(sd);
@@ -956,6 +959,7 @@
 	else
 	    set_inode_item_key_version (inode, KEY_FORMAT_3_6);
 	REISERFS_I(inode)->i_first_direct_byte = 0;
+	set_inode_sd_version (inode, STAT_DATA_V2);
     }
 
     pathrelse (path);
@@ -1107,8 +1111,19 @@
     return;
 }
 
+/* reiserfs_read_inode2 is called to read the inode off disk, and it
+** does a make_bad_inode when things go wrong.  But, we need to make sure
+** and clear the key in the private portion of the inode, otherwise a
+** corresponding iput might try to delete whatever object the inode last
+** represented.
+*/
+static void reiserfs_make_bad_inode(struct inode *inode) {
+    memset(INODE_PKEY(inode), 0, KEY_SIZE);
+    make_bad_inode(inode);
+}
+
 void reiserfs_read_inode(struct inode *inode) {
-    make_bad_inode(inode) ;
+    reiserfs_make_bad_inode(inode) ;
 }
 
 
@@ -1128,7 +1143,7 @@
     int retval;
 
     if (!p) {
-	make_bad_inode(inode) ;
+	reiserfs_make_bad_inode(inode) ;
 	return;
     }
 
@@ -1148,13 +1163,13 @@
 	reiserfs_warning ("vs-13070: reiserfs_read_inode2: "
                     "i/o failure occurred trying to find stat data of %K\n",
                     &key);
-	make_bad_inode(inode) ;
+	reiserfs_make_bad_inode(inode) ;
 	return;
     }
     if (retval != ITEM_FOUND) {
 	/* a stale NFS handle can trigger this without it being an error */
 	pathrelse (&path_to_sd);
-	make_bad_inode(inode) ;
+	reiserfs_make_bad_inode(inode) ;
 	inode->i_nlink = 0;
 	return;
     }
@@ -1176,12 +1191,12 @@
        nlink==0: processing of open-unlinked and half-truncated files
        during mount (fs/reiserfs/super.c:finish_unfinished()). */
     if( ( inode -> i_nlink == 0 ) && 
-	! inode -> i_sb -> u.reiserfs_sb.s_is_unlinked_ok ) {
+	! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) {
 	    reiserfs_warning( "vs-13075: reiserfs_read_inode2: "
 			      "dead inode read from disk %K. "
 			      "This is likely to be race with knfsd. Ignore\n", 
 			      &key );
-	    make_bad_inode( inode );
+	    reiserfs_make_bad_inode( inode );
     }
 
     reiserfs_check_path(&path_to_sd) ; /* init inode should be relsing */
@@ -1207,7 +1222,8 @@
     struct reiserfs_iget4_args *args;
 
     args = opaque;
-    return INODE_PKEY( inode ) -> k_dir_id == args -> objectid;
+    /* args is already in CPU order */
+    return le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args -> objectid;
 }
 
 struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key)
@@ -1289,7 +1305,7 @@
      * If possible, get a well-connected one
      */
     spin_lock(&dcache_lock);
-    for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
+    list_for_each(lp, &inode->i_dentry) {
 	    result = list_entry(lp,struct dentry, d_alias);
 	    if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
 		    dget_locked(result);
@@ -1515,7 +1531,7 @@
     else
 #if defined( USE_INODE_GENERATION_COUNTER )
       inode->i_generation = 
-	le32_to_cpu( sb -> u.reiserfs_sb.s_rs -> s_inode_generation );
+	le32_to_cpu( REISERFS_SB(sb) -> s_rs -> s_inode_generation );
 #else
       inode->i_generation = ++event;
 #endif
@@ -1685,7 +1701,7 @@
 
     kunmap(page) ; /* mapped by block_prepare_write */
 
-    head = page->buffers ;      
+    head = page_buffers(page) ;      
     bh = head;
     do {
 	if (pos >= start) {
@@ -1930,7 +1946,7 @@
     struct buffer_head *arr[PAGE_CACHE_SIZE/512] ;
     int nr = 0 ;
 
-    if (!page->buffers) {
+    if (!page_has_buffers(page)) {
         block_prepare_write(page, 0, 0, NULL) ;
 	kunmap(page) ;
     }
@@ -1948,7 +1964,7 @@
 	flush_dcache_page(page) ;
 	kunmap(page) ;
     }
-    head = page->buffers ;
+    head = page_buffers(page) ;
     bh = head ;
     block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits) ;
     do {
diff -Nru a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c
--- a/fs/reiserfs/item_ops.c	Sun Apr 14 12:16:56 2002
+++ b/fs/reiserfs/item_ops.c	Sun Apr 14 12:16:56 2002
@@ -111,18 +111,18 @@
 }
 
 struct item_operations stat_data_ops = {
-    sd_bytes_number,
-    sd_decrement_key,
-    sd_is_left_mergeable,
-    sd_print_item,
-    sd_check_item,
-
-    sd_create_vi,
-    sd_check_left,
-    sd_check_right,
-    sd_part_size,
-    sd_unit_num,
-    sd_print_vi
+	bytes_number:		sd_bytes_number,
+	decrement_key:		sd_decrement_key,
+	is_left_mergeable:	sd_is_left_mergeable,
+	print_item:		sd_print_item,
+	check_item:		sd_check_item,
+
+	create_vi:		sd_create_vi,
+	check_left:		sd_check_left,
+	check_right:		sd_check_right,
+	part_size:		sd_part_size,
+	unit_num:		sd_unit_num,
+	print_vi:		sd_print_vi
 };
 
 
@@ -214,18 +214,18 @@
 }
 
 struct item_operations direct_ops = {
-    direct_bytes_number,
-    direct_decrement_key,
-    direct_is_left_mergeable,
-    direct_print_item,
-    direct_check_item,
-
-    direct_create_vi,
-    direct_check_left,
-    direct_check_right,
-    direct_part_size,
-    direct_unit_num,
-    direct_print_vi
+	bytes_number:		direct_bytes_number,
+	decrement_key:		direct_decrement_key,
+	is_left_mergeable:	direct_is_left_mergeable,
+	print_item:		direct_print_item,
+	check_item:		direct_check_item,
+
+	create_vi:		direct_create_vi,
+	check_left:		direct_check_left,
+	check_right:		direct_check_right,
+	part_size:		direct_part_size,
+	unit_num:		direct_unit_num,
+	print_vi:		direct_print_vi
 };
 
 
@@ -368,18 +368,18 @@
 }
 
 struct item_operations indirect_ops = {
-    indirect_bytes_number,
-    indirect_decrement_key,
-    indirect_is_left_mergeable,
-    indirect_print_item,
-    indirect_check_item,
-
-    indirect_create_vi,
-    indirect_check_left,
-    indirect_check_right,
-    indirect_part_size,
-    indirect_unit_num,
-    indirect_print_vi
+	bytes_number:		indirect_bytes_number,
+	decrement_key:		indirect_decrement_key,
+	is_left_mergeable:	indirect_is_left_mergeable,
+	print_item:		indirect_print_item,
+	check_item:		indirect_check_item,
+
+	create_vi:		indirect_create_vi,
+	check_left:		indirect_check_left,
+	check_right:		indirect_check_right,
+	part_size:		indirect_part_size,
+	unit_num:		indirect_unit_num,
+	print_vi:		indirect_print_vi
 };
 
 
@@ -669,18 +669,18 @@
 }
 
 struct item_operations direntry_ops = {
-    direntry_bytes_number,
-    direntry_decrement_key,
-    direntry_is_left_mergeable,
-    direntry_print_item,
-    direntry_check_item,
-
-    direntry_create_vi,
-    direntry_check_left,
-    direntry_check_right,
-    direntry_part_size,
-    direntry_unit_num,
-    direntry_print_vi
+	bytes_number:		direntry_bytes_number,
+	decrement_key:		direntry_decrement_key,
+	is_left_mergeable:	direntry_is_left_mergeable,
+	print_item:		direntry_print_item,
+	check_item:		direntry_check_item,
+
+	create_vi:		direntry_create_vi,
+	check_left:		direntry_check_left,
+	check_right:		direntry_check_right,
+	part_size:		direntry_part_size,
+	unit_num:		direntry_unit_num,
+	print_vi:		direntry_print_vi
 };
 
 
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	Sun Apr 14 12:16:55 2002
+++ b/fs/reiserfs/journal.c	Sun Apr 14 12:16:55 2002
@@ -1651,11 +1651,9 @@
 }
 static int journal_read(struct super_block *p_s_sb) {
   struct reiserfs_journal_desc *desc ;
-  unsigned long last_flush_trans_id = 0 ;
   unsigned long oldest_trans_id = 0;
   unsigned long oldest_invalid_trans_id = 0 ;
   time_t start ;
-  unsigned long last_flush_start = 0;
   unsigned long oldest_start = 0;
   unsigned long cur_dblock = 0 ;
   unsigned long newest_mount_id = 9 ;
@@ -1685,13 +1683,14 @@
   if (le32_to_cpu(jh->j_first_unflushed_offset) >= 0 && 
       le32_to_cpu(jh->j_first_unflushed_offset) < SB_ONDISK_JOURNAL_SIZE(p_s_sb) && 
       le32_to_cpu(jh->j_last_flush_trans_id) > 0) {
-    last_flush_start = SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + 
+    oldest_start = SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + 
                        le32_to_cpu(jh->j_first_unflushed_offset) ;
-    last_flush_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) ;
+    oldest_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) + 1;
+    newest_mount_id = le32_to_cpu(jh->j_mount_id);
     reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1153: found in "
                    "header: first_unflushed_offset %d, last_flushed_trans_id "
 		   "%lu\n", le32_to_cpu(jh->j_first_unflushed_offset), 
-		   last_flush_trans_id) ;
+		   le32_to_cpu(jh->j_last_flush_trans_id)) ;
     valid_journal_header = 1 ;
 
     /* now, we try to read the first unflushed offset.  If it is not valid, 
@@ -1704,15 +1703,13 @@
       continue_replay = 0 ;
     }
     brelse(d_bh) ;
+    goto start_log_replay;
   }
 
   if (continue_replay && is_read_only(p_s_sb->s_dev)) {
     printk("clm-2076: device is readonly, unable to replay log\n") ;
     return -1 ;
   }
-  if (continue_replay && (p_s_sb->s_flags & MS_RDONLY)) {
-    printk("Warning, log replay starting on readonly filesystem\n") ;    
-  }
 
   /* ok, there are transactions that need to be replayed.  start with the first log block, find
   ** all the valid transactions, and pick out the oldest.
@@ -1746,17 +1743,13 @@
 	              "newest_mount_id to %d\n", le32_to_cpu(desc->j_mount_id));
       }
       cur_dblock += le32_to_cpu(desc->j_len) + 2 ;
-    } 
-    else {
+    } else {
       cur_dblock++ ;
     }
     brelse(d_bh) ;
   }
-  /* step three, starting at the oldest transaction, replay */
-  if (last_flush_start > 0) {
-    oldest_start = last_flush_start ;
-    oldest_trans_id = last_flush_trans_id + 1 ;
-  } 
+
+start_log_replay:
   cur_dblock = oldest_start ;
   if (oldest_trans_id)  {
     reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1206: Starting replay "
@@ -1958,8 +1951,7 @@
       		SB_ONDISK_JOURNAL_DEVICE( super ) ?
 		to_kdev_t(SB_ONDISK_JOURNAL_DEVICE( super )) : super -> s_dev;	
 	/* there is no "jdev" option and journal is on separate device */
-	if( ( !jdev_name || !jdev_name[ 0 ] ) && 
-	    SB_ONDISK_JOURNAL_DEVICE( super ) ) {
+	if( ( !jdev_name || !jdev_name[ 0 ] ) ) {
 		journal -> j_dev_bd = bdget( kdev_t_to_nr( jdev ) );
 		if( journal -> j_dev_bd )
 			result = blkdev_get( journal -> j_dev_bd, 
@@ -1974,9 +1966,6 @@
 		return result;
 	}
 
-	/* no "jdev" option and journal is on the host device */
-	if( !jdev_name || !jdev_name[ 0 ] )
-		return 0;
 	journal -> j_dev_file = filp_open( jdev_name, 0, 0 );
 	if( !IS_ERR( journal -> j_dev_file ) ) {
 		struct inode *jdev_inode;
@@ -2053,6 +2042,7 @@
 		   SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + SB_ONDISK_JOURNAL_SIZE(p_s_sb));
      if (!bhjh) {
 	 printk("sh-459: unable to read  journal header\n") ;
+	 release_journal_dev(p_s_sb, journal);
 	 return 1 ;
      }
      jh = (struct reiserfs_journal_header *)(bhjh->b_data);
@@ -2069,7 +2059,8 @@
 		jh->jh_journal.jp_journal_magic, jname,
 		sb_jp_journal_magic(rs), fname);
 	 brelse (bhjh);
-    return 1 ;
+	 release_journal_dev(p_s_sb, journal);
+	 return 1 ;
   }
      
   SB_JOURNAL_TRANS_MAX(p_s_sb)      = le32_to_cpu (jh->jh_journal.jp_journal_trans_max);
@@ -2169,11 +2160,13 @@
   SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap = get_list_bitmap(p_s_sb, SB_JOURNAL_LIST(p_s_sb)) ;
   if (!(SB_JOURNAL_LIST(p_s_sb)[0].j_list_bitmap)) {
     reiserfs_warning("journal-2005, get_list_bitmap failed for journal list 0\n") ;
+    release_journal_dev(p_s_sb, journal);
     return 1 ;
   }
   if (journal_read(p_s_sb) < 0) {
     reiserfs_warning("Replay Failure, unable to mount\n") ;
     free_journal_ram(p_s_sb) ;
+    release_journal_dev(p_s_sb, journal);
     return 1 ;
   }
   SB_JOURNAL_LIST_INDEX(p_s_sb) = 0 ; /* once the read is done, we can set this
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	Sun Apr 14 12:16:54 2002
+++ b/fs/reiserfs/namei.c	Sun Apr 14 12:16:54 2002
@@ -183,7 +183,7 @@
     if (len == 2 && name[0] == '.' && name[1] == '.')
 	return DOT_DOT_OFFSET;
 
-    res = s->u.reiserfs_sb.s_hash_function (name, len);
+    res = REISERFS_SB(s)->s_hash_function (name, len);
 
     // take bits from 7-th to 30-th including both bounds
     res = GET_HASH_VALUE(res);
diff -Nru a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
--- a/fs/reiserfs/prints.c	Sun Apr 14 12:16:55 2002
+++ b/fs/reiserfs/prints.c	Sun Apr 14 12:16:55 2002
@@ -592,7 +592,7 @@
 	     "MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n" 
 	     "=====================================================================\n"
 	     "* h *    S    *    L    *    R    *   F   *   FL  *   FR  *  CFL  *  CFR  *\n",
-	     tb->tb_sb->u.reiserfs_sb.s_do_balance,
+	     REISERFS_SB(tb->tb_sb)->s_do_balance,
 	     tb->tb_mode, PATH_LAST_POSITION (tb->tb_path), tb->tb_path->pos_in_item);
   
     for (h = 0; h < sizeof(tb->insert_size) / sizeof (tb->insert_size[0]); h ++) {
@@ -717,9 +717,9 @@
   /*
   printk ("reiserfs_put_super: session statistics: balances %d, fix_nodes %d, \
 bmap with search %d, without %d, dir2ind %d, ind2dir %d\n",
-	  s->u.reiserfs_sb.s_do_balance, s->u.reiserfs_sb.s_fix_nodes,
-	  s->u.reiserfs_sb.s_bmaps, s->u.reiserfs_sb.s_bmaps_without_search,
-	  s->u.reiserfs_sb.s_direct2indirect, s->u.reiserfs_sb.s_indirect2direct);
+	  REISERFS_SB(s)->s_do_balance, REISERFS_SB(s)->s_fix_nodes,
+	  REISERFS_SB(s)->s_bmaps, REISERFS_SB(s)->s_bmaps_without_search,
+	  REISERFS_SB(s)->s_direct2indirect, REISERFS_SB(s)->s_indirect2direct);
   */
 
 }
diff -Nru a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
--- a/fs/reiserfs/procfs.c	Sun Apr 14 12:16:57 2002
+++ b/fs/reiserfs/procfs.c	Sun Apr 14 12:16:57 2002
@@ -82,9 +82,9 @@
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	if ( sb->u.reiserfs_sb.s_properties & (1 << REISERFS_3_6) ) {
+	if ( REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6) ) {
 		format = "3.6";
-	} else if ( sb->u.reiserfs_sb.s_properties & (1 << REISERFS_3_5) ) {
+	} else if ( REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_5) ) {
 		format = "3.5";
 	} else {
 		format = "unknown";
@@ -140,7 +140,7 @@
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	r = &sb->u.reiserfs_sb;
+	r = REISERFS_SB(sb);
 	len += sprintf( &buffer[ len ], 
 			"state: \t%s\n"
 			"mount options: \t%s%s%s%s%s%s%s%s%s%s%s%s\n"
@@ -220,7 +220,7 @@
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	r = &sb->u.reiserfs_sb;
+	r = REISERFS_SB(sb);
 
 	len += sprintf( &buffer[ len ],
 			"level\t"
@@ -293,13 +293,13 @@
 			     int count, int *eof, void *data )
 {
 	struct super_block *sb;
-	struct reiserfs_sb_info *r = &sb->u.reiserfs_sb;
+	struct reiserfs_sb_info *r;
 	int len = 0;
     
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	r = &sb->u.reiserfs_sb;
+	r = REISERFS_SB(sb);
 
 	len += sprintf( &buffer[ len ], "free_block: %lu\n"
 			"find_forward:"
@@ -340,7 +340,7 @@
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	sb_info = &sb->u.reiserfs_sb;
+	sb_info = REISERFS_SB(sb);
 	rs = sb_info -> s_rs;
 	hash_code = DFL( s_hash_function_code );
 
@@ -397,7 +397,7 @@
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	sb_info = &sb->u.reiserfs_sb;
+	sb_info = REISERFS_SB(sb);
 	rs = sb_info -> s_rs;
 	mapsize = le16_to_cpu( rs -> s_v1.s_oid_cursize );
 	total_used = 0;
@@ -449,7 +449,7 @@
 	sb = procinfo_prologue( to_kdev_t((int)data) );
 	if( sb == NULL )
 		return -ENOENT;
-	r = &sb->u.reiserfs_sb;
+	r = REISERFS_SB(sb);
 	rs = r -> s_rs;
 	jp = &rs->s_v1.s_journal;
 
@@ -557,9 +557,9 @@
 int reiserfs_proc_info_init( struct super_block *sb )
 {
 	spin_lock_init( & __PINFO( sb ).lock );
-	sb->u.reiserfs_sb.procdir = proc_mkdir(sb->s_id, proc_info_root);
-	if( sb->u.reiserfs_sb.procdir ) {
-		sb->u.reiserfs_sb.procdir -> owner = THIS_MODULE;
+	REISERFS_SB(sb)->procdir = proc_mkdir(sb->s_id, proc_info_root);
+	if( REISERFS_SB(sb)->procdir ) {
+		REISERFS_SB(sb)->procdir -> owner = THIS_MODULE;
 		return 0;
 	}
 	reiserfs_warning( "reiserfs: cannot create /proc/%s/%s\n",
@@ -575,7 +575,7 @@
 	spin_unlock( & __PINFO( sb ).lock );
 	if ( proc_info_root ) {
 		remove_proc_entry( sb->s_id, proc_info_root );
-		sb->u.reiserfs_sb.procdir = NULL;
+		REISERFS_SB(sb)->procdir = NULL;
 	}
 	return 0;
 }
@@ -587,14 +587,14 @@
 struct proc_dir_entry *reiserfs_proc_register( struct super_block *sb, 
 					       char *name, read_proc_t *func )
 {
-	return ( sb->u.reiserfs_sb.procdir ) ? create_proc_read_entry
-		( name, 0, sb->u.reiserfs_sb.procdir, func, 
+	return ( REISERFS_SB(sb)->procdir ) ? create_proc_read_entry
+		( name, 0, REISERFS_SB(sb)->procdir, func, 
 		  ( void * ) kdev_t_to_nr( sb -> s_dev ) ) : NULL;
 }
 
 void reiserfs_proc_unregister( struct super_block *sb, const char *name )
 {
-	remove_proc_entry( name, sb->u.reiserfs_sb.procdir );
+	remove_proc_entry( name, REISERFS_SB(sb)->procdir );
 }
 
 struct proc_dir_entry *reiserfs_proc_register_global( char *name, 
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c	Sun Apr 14 12:16:59 2002
+++ b/fs/reiserfs/stree.c	Sun Apr 14 12:16:59 2002
@@ -1387,7 +1387,7 @@
        __u32 *inode_generation;
        
        inode_generation = 
-         &th -> t_super -> u.reiserfs_sb.s_rs -> s_inode_generation;
+         &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation;
        *inode_generation = cpu_to_le32( le32_to_cpu( *inode_generation ) + 1 );
       }
 /* USE_INODE_GENERATION_COUNTER */
diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c
--- a/fs/reiserfs/super.c	Sun Apr 14 12:16:58 2002
+++ b/fs/reiserfs/super.c	Sun Apr 14 12:16:58 2002
@@ -153,7 +153,7 @@
     max_cpu_key.key_length = 3;
  
     done = 0;
-    s -> u.reiserfs_sb.s_is_unlinked_ok = 1;
+    REISERFS_SB(s)->s_is_unlinked_ok = 1;
     while (1) {
         retval = search_item (s, &max_cpu_key, &path);
         if (retval != ITEM_NOT_FOUND) {
@@ -239,7 +239,7 @@
         printk ("done\n");
         done ++;
     }
-    s -> u.reiserfs_sb.s_is_unlinked_ok = 0;
+    REISERFS_SB(s)->s_is_unlinked_ok = 0;
      
     pathrelse (&path);
     if (done)
@@ -378,7 +378,7 @@
   if (!(s->s_flags & MS_RDONLY)) {
     journal_begin(&th, s, 10) ;
     reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
-    set_sb_umount_state( SB_DISK_SUPER_BLOCK(s), s->u.reiserfs_sb.s_mount_state );
+    set_sb_umount_state( SB_DISK_SUPER_BLOCK(s), REISERFS_SB(s)->s_mount_state );
     journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
   }
 
@@ -396,9 +396,9 @@
 
   print_statistics (s);
 
-  if (s->u.reiserfs_sb.s_kmallocs != 0) {
+  if (REISERFS_SB(s)->s_kmallocs != 0) {
     reiserfs_warning ("vs-2004: reiserfs_put_super: allocated memory left %d\n",
-		      s->u.reiserfs_sb.s_kmallocs);
+		      REISERFS_SB(s)->s_kmallocs);
   }
 
   reiserfs_proc_unregister( s, "journal" );
@@ -409,6 +409,10 @@
   reiserfs_proc_unregister( s, "super" );
   reiserfs_proc_unregister( s, "version" );
   reiserfs_proc_info_done( s );
+
+  kfree(s->u.generic_sbp);
+  s->u.generic_sbp = NULL;
+
   return;
 }
 
@@ -508,7 +512,9 @@
 	/* use default configuration: create tails, journaling on, no
            conversion to newest format */
 	return 1;
-    for (this_char = strtok (options, ","); this_char != NULL; this_char = strtok (NULL, ",")) {
+    while ((this_char = strsep (&options, ",")) != NULL) {
+	if (!*this_char)
+	    continue;
 	if ((value = strchr (this_char, '=')) != NULL)
 	    *value++ = 0;
 	if (!strcmp (this_char, "notail")) {
@@ -612,30 +618,30 @@
   
   if (*flags & MS_RDONLY) {
     /* try to remount file system with read-only permissions */
-    if (sb_umount_state(rs) == REISERFS_VALID_FS || s->u.reiserfs_sb.s_mount_state != REISERFS_VALID_FS) {
+    if (sb_umount_state(rs) == REISERFS_VALID_FS || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) {
       return 0;
     }
 
     journal_begin(&th, s, 10) ;
     /* Mounting a rw partition read-only. */
     reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
-    set_sb_umount_state( rs, s->u.reiserfs_sb.s_mount_state );
+    set_sb_umount_state( rs, REISERFS_SB(s)->s_mount_state );
     journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
     s->s_dirt = 0;
   } else {
-    s->u.reiserfs_sb.s_mount_state = sb_umount_state(rs) ;
+    REISERFS_SB(s)->s_mount_state = sb_umount_state(rs) ;
     s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
     journal_begin(&th, s, 10) ;
 
     /* Mount a partition which is read-only, read-write */
     reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
-    s->u.reiserfs_sb.s_mount_state = sb_umount_state(rs);
+    REISERFS_SB(s)->s_mount_state = sb_umount_state(rs);
     s->s_flags &= ~MS_RDONLY;
     set_sb_umount_state( rs, REISERFS_ERROR_FS );
     /* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
     journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
     s->s_dirt = 0;
-    s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
+    REISERFS_SB(s)->s_mount_state = REISERFS_VALID_FS ;
   }
   /* this will force a full flush of all journal lists */
   SB_JOURNAL(s)->j_must_wait = 1 ;
@@ -740,9 +746,8 @@
     //
     // ok, reiserfs signature (old or new) found in at the given offset
     //    
-    brelse (bh);
-    
     sb_set_blocksize (s, sb_blocksize(rs));
+    brelse (bh);
     
     bh = reiserfs_bread (s, offset / s->s_blocksize);
     if (!bh) {
@@ -764,7 +769,7 @@
     if ( rs->s_v1.s_root_block == -1 ) {
        brelse(bh) ;
        printk("dev %s: Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
-              "reiserfsck --rebuild-tree and wait for a completion. If that fais\n"
+              "reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
               "get newer reiserfsprogs package\n", s->s_id);
        return 1;
     }
@@ -991,7 +996,6 @@
 //
 static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 {
-    int size;
     struct inode *root_inode;
     int j;
     struct reiserfs_transaction_handle th ;
@@ -1001,10 +1005,16 @@
     struct reiserfs_iget4_args args ;
     struct reiserfs_super_block * rs;
     char *jdev_name;
+    struct reiserfs_sb_info *sbi;
+
+    sbi = kmalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
+    if (!sbi)
+	return -ENOMEM;
+    s->u.generic_sbp = sbi;
+    memset (sbi, 0, sizeof (struct reiserfs_sb_info));
 
-    memset (&s->u.reiserfs_sb, 0, sizeof (struct reiserfs_sb_info));
     jdev_name = NULL;
-    if (parse_options ((char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks, &jdev_name) == 0) {
+    if (parse_options ((char *) data, &(sbi->s_mount_opt), &blocks, &jdev_name) == 0) {
 	return -EINVAL;
     }
 
@@ -1013,9 +1023,6 @@
 	return -EINVAL;
     }	
 
-    size = block_size(s->s_dev);
-    sb_set_blocksize(s, size);
-    
     /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */
     if (!read_super_block (s, REISERFS_OLD_DISK_OFFSET_IN_BYTES)) 
       old_format = 1;
@@ -1024,8 +1031,8 @@
       printk("sh-2021: reiserfs_fill_super: can not find reiserfs on %s\n", s->s_id);
       goto error;    
     }
-    s->u.reiserfs_sb.s_mount_state = SB_REISERFS_STATE(s);
-    s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
+    sbi->s_mount_state = SB_REISERFS_STATE(s);
+    sbi->s_mount_state = REISERFS_VALID_FS ;
 
     if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) { 
 	printk ("reiserfs_fill_super: unable to read bitmap\n");
@@ -1071,8 +1078,8 @@
     }
 
     // define and initialize hash function
-    s->u.reiserfs_sb.s_hash_function = hash_function (s);
-    if (s->u.reiserfs_sb.s_hash_function == NULL) {
+    sbi->s_hash_function = hash_function (s);
+    if (sbi->s_hash_function == NULL) {
       dput(s->s_root) ;
       s->s_root = NULL ;
       goto error ;
@@ -1080,9 +1087,9 @@
 
     rs = SB_DISK_SUPER_BLOCK (s);
     if (is_reiserfs_3_5 (rs) || (is_reiserfs_jr (rs) && SB_VERSION (s) == REISERFS_VERSION_1))
-	set_bit(REISERFS_3_5, &(s->u.reiserfs_sb.s_properties));
+	set_bit(REISERFS_3_5, &(sbi->s_properties));
     else
-	set_bit(REISERFS_3_6, &(s->u.reiserfs_sb.s_properties));
+	set_bit(REISERFS_3_6, &(sbi->s_properties));
     
     if (!(s->s_flags & MS_RDONLY)) {
 
@@ -1107,8 +1114,8 @@
 	    
 	    set_sb_version(rs,REISERFS_VERSION_2);
 	    reiserfs_convert_objectid_map_v1(s) ;
-	    set_bit(REISERFS_3_6, &(s->u.reiserfs_sb.s_properties));
-	    clear_bit(REISERFS_3_5, &(s->u.reiserfs_sb.s_properties));
+	    set_bit(REISERFS_3_6, &(sbi->s_properties));
+	    clear_bit(REISERFS_3_5, &(sbi->s_properties));
 	  } else {
 	    reiserfs_warning("reiserfs: using 3.5.x disk format\n") ;
 	  }
@@ -1127,7 +1134,7 @@
 	}
     }
     // mark hash in super block: it could be unset. overwrite should be ok
-    set_sb_hash_function_code( rs, function2code(s->u.reiserfs_sb.s_hash_function ) );
+    set_sb_hash_function_code( rs, function2code(sbi->s_hash_function ) );
 
     reiserfs_proc_info_init( s );
     reiserfs_proc_register( s, "version", reiserfs_version_in_proc );
@@ -1137,7 +1144,7 @@
     reiserfs_proc_register( s, "on-disk-super", reiserfs_on_disk_super_in_proc );
     reiserfs_proc_register( s, "oidmap", reiserfs_oidmap_in_proc );
     reiserfs_proc_register( s, "journal", reiserfs_journal_in_proc );
-    init_waitqueue_head (&(s->u.reiserfs_sb.s_wait));
+    init_waitqueue_head (&(sbi->s_wait));
 
     return 0;
 
@@ -1155,6 +1162,9 @@
     }
     if (SB_BUFFER_WITH_SB (s))
 	brelse(SB_BUFFER_WITH_SB (s));
+
+    kfree(sbi);
+    s->u.generic_sbp = NULL;
 
     return -EINVAL;
 }
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c	Sun Apr 14 12:16:59 2002
+++ b/fs/reiserfs/tail_conversion.c	Sun Apr 14 12:16:59 2002
@@ -35,7 +35,7 @@
 				       tree. */
 
 
-    sb->u.reiserfs_sb.s_direct2indirect ++;
+    REISERFS_SB(sb)->s_direct2indirect ++;
 
     n_blk_size = sb->s_blocksize;
 
@@ -49,9 +49,13 @@
     make_cpu_key (&end_key, inode, tail_offset, TYPE_INDIRECT, 4);
 
     // FIXME: we could avoid this 
-    if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND )
-	reiserfs_panic (sb, "PAP-14030: direct2indirect: "
-			"pasted or inserted byte exists in the tree");
+    if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) {
+	reiserfs_warning ("PAP-14030: direct2indirect: "
+			"pasted or inserted byte exists in the tree %K. "
+			"Use fsck to repair.\n", &end_key);
+	pathrelse(path);
+	return -EIO;
+    }
     
     p_le_ih = PATH_PITEM_HEAD (path);
 
@@ -156,10 +160,10 @@
   unsigned long cur_index ;
 
   if (page) {
-    if (page->buffers) {
+    if (page_has_buffers(page)) {
       tail_index = pos & (PAGE_CACHE_SIZE - 1) ;
       cur_index = 0 ;
-      head = page->buffers ;
+      head = page_buffers(page) ;
       bh = head ;
       do {
 	next = bh->b_this_page ;
@@ -202,7 +206,7 @@
     loff_t pos, pos1; /* position of first byte of the tail */
     struct cpu_key key;
 
-    p_s_sb->u.reiserfs_sb.s_indirect2direct ++;
+    REISERFS_SB(p_s_sb)->s_indirect2direct ++;
 
     *p_c_mode = M_SKIP_BALANCING;
 
diff -Nru a/fs/romfs/inode.c b/fs/romfs/inode.c
--- a/fs/romfs/inode.c	Sun Apr 14 12:16:59 2002
+++ b/fs/romfs/inode.c	Sun Apr 14 12:16:59 2002
@@ -536,7 +536,51 @@
 	}
 }
 
+static kmem_cache_t * romfs_inode_cachep;
+
+static struct inode *romfs_alloc_inode(struct super_block *sb)
+{
+	struct romfs_inode_info *ei;
+	ei = (struct romfs_inode_info *)kmem_cache_alloc(romfs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void romfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct romfs_inode_info *ei = (struct romfs_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	romfs_inode_cachep = kmem_cache_create("romfs_inode_cache",
+					     sizeof(struct romfs_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (romfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(romfs_inode_cachep))
+		printk(KERN_INFO "romfs_inode_cache: not all structures were freed\n");
+}
+
 static struct super_operations romfs_ops = {
+	alloc_inode:	romfs_alloc_inode,
+	destroy_inode:	romfs_destroy_inode,
 	read_inode:	romfs_read_inode,
 	statfs:		romfs_statfs,
 };
@@ -557,12 +601,23 @@
 
 static int __init init_romfs_fs(void)
 {
-	return register_filesystem(&romfs_fs_type);
+	int err = init_inodecache();
+	if (err)
+		goto out1;
+        err = register_filesystem(&romfs_fs_type);
+	if (err)
+		goto out;
+	return 0;
+out:
+	destroy_inodecache();
+out1:
+	return err;
 }
 
 static void __exit exit_romfs_fs(void)
 {
 	unregister_filesystem(&romfs_fs_type);
+	destroy_inodecache();
 }
 
 /* Yes, works even as a module... :) */
diff -Nru a/fs/smbfs/inode.c b/fs/smbfs/inode.c
--- a/fs/smbfs/inode.c	Sun Apr 14 12:16:55 2002
+++ b/fs/smbfs/inode.c	Sun Apr 14 12:16:55 2002
@@ -621,6 +621,8 @@
 	int error, changed, refresh = 0;
 	struct smb_fattr fattr;
 
+	lock_kernel();
+
 	error = smb_revalidate_inode(dentry);
 	if (error)
 		goto out;
@@ -714,6 +716,7 @@
 out:
 	if (refresh)
 		smb_refresh_inode(dentry);
+	unlock_kernel();
 	return error;
 }
 
diff -Nru a/fs/smbfs/proc.c b/fs/smbfs/proc.c
--- a/fs/smbfs/proc.c	Sun Apr 14 12:16:55 2002
+++ b/fs/smbfs/proc.c	Sun Apr 14 12:16:55 2002
@@ -1898,7 +1898,10 @@
 	__u16 bcc;
 	__u16 count;
 	char status[SMB_STATUS_SIZE];
-	static struct qstr mask = { "*.*", 3, 0 };
+	static struct qstr mask = {
+		name:	"*.*",
+		len:	3,
+	};
 	unsigned char *last_status;
 
 	VERBOSE("%s/%s\n", DENTRY_PATH(dir));
@@ -2164,7 +2167,10 @@
 	int ff_dir_handle = 0;
 	int loop_count = 0;
 	int mask_len, i, result;
-	static struct qstr star = { "*", 1, 0 };
+	static struct qstr star = {
+		name:	"*",
+		len:	1,
+	};
 
 	/*
 	 * use info level 1 for older servers that don't do 260
diff -Nru a/fs/super.c b/fs/super.c
--- a/fs/super.c	Sun Apr 14 12:16:58 2002
+++ b/fs/super.c	Sun Apr 14 12:16:58 2002
@@ -26,6 +26,7 @@
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/acct.h>
+#include <linux/blkdev.h>
 #include <asm/uaccess.h>
 
 void get_filesystem(struct file_system_type *fs);
@@ -183,7 +184,7 @@
 	up_write(&s->s_umount);
 }
 
-static void generic_shutdown_super(struct super_block *sb)
+void generic_shutdown_super(struct super_block *sb)
 {
 	struct dentry *root = sb->s_root;
 	struct super_operations *sop = sb->s_op;
@@ -513,6 +514,8 @@
 	} else {
 		s->s_flags = flags;
 		strncpy(s->s_id, bdevname(dev), sizeof(s->s_id));
+		s->s_old_blocksize = block_size(dev);
+		sb_set_blocksize(s, s->s_old_blocksize);
 		error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 		if (error) {
 			up_write(&s->s_umount);
@@ -535,6 +538,7 @@
 {
 	struct block_device *bdev = sb->s_bdev;
 	generic_shutdown_super(sb);
+	set_blocksize(to_kdev_t(bdev->bd_dev), sb->s_old_blocksize);
 	bd_release(bdev);
 	blkdev_put(bdev, BDEV_FS);
 }
diff -Nru a/fs/udf/super.c b/fs/udf/super.c
--- a/fs/udf/super.c	Sun Apr 14 12:16:59 2002
+++ b/fs/udf/super.c	Sun Apr 14 12:16:59 2002
@@ -286,8 +286,9 @@
 	if (!options)
 		return 1;
 
-	for (opt = strtok(options, ","); opt; opt = strtok(NULL, ","))
-	{
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
 		/* Make "opt=val" into two strings */
 		val = strchr(opt, '=');
 		if (val)
diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c
--- a/fs/ufs/super.c	Sun Apr 14 12:16:54 2002
+++ b/fs/ufs/super.c	Sun Apr 14 12:16:54 2002
@@ -257,11 +257,10 @@
 	
 	if (!options)
 		return 1;
-		
-	for (this_char = strtok (options, ",");
-	     this_char != NULL;
-	     this_char = strtok (NULL, ",")) {
-	     
+
+	while ((this_char = strsep (&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr (this_char, '=')) != NULL)
 			*value++ = 0;
 		if (!strcmp (this_char, "ufstype")) {
diff -Nru a/fs/umsdos/inode.c b/fs/umsdos/inode.c
--- a/fs/umsdos/inode.c	Sun Apr 14 12:16:55 2002
+++ b/fs/umsdos/inode.c	Sun Apr 14 12:16:55 2002
@@ -165,6 +165,8 @@
 	struct dentry *temp, *old_dentry = NULL;
 	int ret;
 
+	lock_kernel();
+
 	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len,
 				&info);
 	if (ret)
@@ -208,14 +210,13 @@
 	if (ret)
 		goto out;
 
-	down(&dir->i_sem);
 	ret = umsdos_notify_change_locked(dentry, attr);
-	up(&dir->i_sem);
 	if (ret == 0)
 		ret = inode_setattr (inode, attr);
 out:
 	if (old_dentry)
 		dput (dentry);	/* if we had to use fake dentry for hardlinks, dput() it now */
+	unlock_kernel();
 	return ret;
 }
 
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	Sun Apr 14 12:16:55 2002
+++ b/fs/vfat/namei.c	Sun Apr 14 12:16:55 2002
@@ -115,7 +115,9 @@
 	save = 0;
 	savep = NULL;
 	ret = 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options,",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL) {
 			save = *value;
 			savep = value;
diff -Nru a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-alpha/cacheflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,64 @@
+#ifndef _ALPHA_CACHEFLUSH_H
+#define _ALPHA_CACHEFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+
+/* Caches aren't brain-dead on the Alpha. */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+
+/* Note that the following two definitions are _highly_ dependent
+   on the contexts in which they are used in the kernel.  I personally
+   think it is criminal how loosely defined these macros are.  */
+
+/* We need to flush the kernel's icache after loading modules.  The
+   only other use of this macro is in load_aout_interp which is not
+   used on Alpha. 
+
+   Note that this definition should *not* be used for userspace
+   icache flushing.  While functional, it is _way_ overkill.  The
+   icache is tagged with ASNs and it suffices to allocate a new ASN
+   for the process.  */
+#ifndef CONFIG_SMP
+#define flush_icache_range(start, end)		imb()
+#else
+#define flush_icache_range(start, end)		smp_imb()
+extern void smp_imb(void);
+#endif
+
+/* We need to flush the userspace icache after setting breakpoints in
+   ptrace.
+
+   Instead of indiscriminately using imb, take advantage of the fact
+   that icache entries are tagged with the ASN and load a new mm context.  */
+/* ??? Ought to use this in arch/alpha/kernel/signal.c too.  */
+
+#ifndef CONFIG_SMP
+extern void __load_new_mm_context(struct mm_struct *);
+static inline void
+flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+			unsigned long addr, int len)
+{
+	if (vma->vm_flags & VM_EXEC) {
+		struct mm_struct *mm = vma->vm_mm;
+		if (current->active_mm == mm)
+			__load_new_mm_context(mm);
+		else
+			mm->context[smp_processor_id()] = 0;
+	}
+}
+#else
+extern void flush_icache_user_range(struct vm_area_struct *vma,
+		struct page *page, unsigned long addr, int len);
+#endif
+
+/* This is used only in do_no_page and do_swap_page.  */
+#define flush_icache_page(vma, page) \
+  flush_icache_user_range((vma), (page), 0, 0)
+
+#endif /* _ALPHA_CACHEFLUSH_H */
diff -Nru a/include/asm-alpha/pgalloc.h b/include/asm-alpha/pgalloc.h
--- a/include/asm-alpha/pgalloc.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-alpha/pgalloc.h	Sun Apr 14 12:16:54 2002
@@ -3,228 +3,6 @@
 
 #include <linux/config.h>
 
-#ifndef __EXTERN_INLINE
-#define __EXTERN_INLINE extern inline
-#define __MMU_EXTERN_INLINE
-#endif
-
-extern void __load_new_mm_context(struct mm_struct *);
-
-
-/* Caches aren't brain-dead on the Alpha. */
-#define flush_cache_all()			do { } while (0)
-#define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
-#define flush_page_to_ram(page)			do { } while (0)
-#define flush_dcache_page(page)			do { } while (0)
-
-/* Note that the following two definitions are _highly_ dependent
-   on the contexts in which they are used in the kernel.  I personally
-   think it is criminal how loosely defined these macros are.  */
-
-/* We need to flush the kernel's icache after loading modules.  The
-   only other use of this macro is in load_aout_interp which is not
-   used on Alpha. 
-
-   Note that this definition should *not* be used for userspace
-   icache flushing.  While functional, it is _way_ overkill.  The
-   icache is tagged with ASNs and it suffices to allocate a new ASN
-   for the process.  */
-#ifndef CONFIG_SMP
-#define flush_icache_range(start, end)		imb()
-#else
-#define flush_icache_range(start, end)		smp_imb()
-extern void smp_imb(void);
-#endif
-
-
-/*
- * Use a few helper functions to hide the ugly broken ASN
- * numbers on early Alphas (ev4 and ev45)
- */
-
-__EXTERN_INLINE void
-ev4_flush_tlb_current(struct mm_struct *mm)
-{
-	__load_new_mm_context(mm);
-	tbiap();
-}
-
-__EXTERN_INLINE void
-ev5_flush_tlb_current(struct mm_struct *mm)
-{
-	__load_new_mm_context(mm);
-}
-
-static inline void
-flush_tlb_other(struct mm_struct *mm)
-{
-	long * mmc = &mm->context[smp_processor_id()];
-	/*
-	 * Check it's not zero first to avoid cacheline ping pong when
-	 * possible.
-	 */
-	if (*mmc)
-		*mmc = 0;
-}
-
-/* We need to flush the userspace icache after setting breakpoints in
-   ptrace.
-
-   Instead of indiscriminately using imb, take advantage of the fact
-   that icache entries are tagged with the ASN and load a new mm context.  */
-/* ??? Ought to use this in arch/alpha/kernel/signal.c too.  */
-
-#ifndef CONFIG_SMP
-static inline void
-flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
-			unsigned long addr, int len)
-{
-	if (vma->vm_flags & VM_EXEC) {
-		struct mm_struct *mm = vma->vm_mm;
-		if (current->active_mm == mm)
-			__load_new_mm_context(mm);
-		else
-			mm->context[smp_processor_id()] = 0;
-	}
-}
-#else
-extern void flush_icache_user_range(struct vm_area_struct *vma,
-		struct page *page, unsigned long addr, int len);
-#endif
-
-/* this is used only in do_no_page and do_swap_page */
-#define flush_icache_page(vma, page)	flush_icache_user_range((vma), (page), 0, 0)
-
-/*
- * Flush just one page in the current TLB set.
- * We need to be very careful about the icache here, there
- * is no way to invalidate a specific icache page..
- */
-
-__EXTERN_INLINE void
-ev4_flush_tlb_current_page(struct mm_struct * mm,
-			   struct vm_area_struct *vma,
-			   unsigned long addr)
-{
-	int tbi_flag = 2;
-	if (vma->vm_flags & VM_EXEC) {
-		__load_new_mm_context(mm);
-		tbi_flag = 3;
-	}
-	tbi(tbi_flag, addr);
-}
-
-__EXTERN_INLINE void
-ev5_flush_tlb_current_page(struct mm_struct * mm,
-			   struct vm_area_struct *vma,
-			   unsigned long addr)
-{
-	if (vma->vm_flags & VM_EXEC)
-		__load_new_mm_context(mm);
-	else
-		tbi(2, addr);
-}
-
-
-#ifdef CONFIG_ALPHA_GENERIC
-# define flush_tlb_current		alpha_mv.mv_flush_tlb_current
-# define flush_tlb_current_page		alpha_mv.mv_flush_tlb_current_page
-#else
-# ifdef CONFIG_ALPHA_EV4
-#  define flush_tlb_current		ev4_flush_tlb_current
-#  define flush_tlb_current_page	ev4_flush_tlb_current_page
-# else
-#  define flush_tlb_current		ev5_flush_tlb_current
-#  define flush_tlb_current_page	ev5_flush_tlb_current_page
-# endif
-#endif
-
-#ifdef __MMU_EXTERN_INLINE
-#undef __EXTERN_INLINE
-#undef __MMU_EXTERN_INLINE
-#endif
-
-/*
- * Flush current user mapping.
- */
-static inline void flush_tlb(void)
-{
-	flush_tlb_current(current->active_mm);
-}
-
-/*
- * Flush a specified range of user mapping page tables
- * from TLB.
- * Although Alpha uses VPTE caches, this can be a nop, as Alpha does
- * not have finegrained tlb flushing, so it will flush VPTE stuff
- * during next flush_tlb_range.
- */
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
-	unsigned long start, unsigned long end)
-{
-}
-
-#ifndef CONFIG_SMP
-/*
- * Flush everything (kernel mapping may also have
- * changed due to vmalloc/vfree)
- */
-static inline void flush_tlb_all(void)
-{
-	tbia();
-}
-
-/*
- * Flush a specified user mapping
- */
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-	if (mm == current->active_mm)
-		flush_tlb_current(mm);
-	else
-		flush_tlb_other(mm);
-}
-
-/*
- * Page-granular tlb flush.
- *
- * do a tbisd (type = 2) normally, and a tbis (type = 3)
- * if it is an executable mapping.  We want to avoid the
- * itlb flush, because that potentially also does a
- * icache flush.
- */
-static inline void flush_tlb_page(struct vm_area_struct *vma,
-	unsigned long addr)
-{
-	struct mm_struct * mm = vma->vm_mm;
-
-	if (mm == current->active_mm)
-		flush_tlb_current_page(mm, vma, addr);
-	else
-		flush_tlb_other(mm);
-}
-
-/*
- * Flush a specified range of user mapping:  on the
- * Alpha we flush the whole user tlb.
- */
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-	unsigned long start, unsigned long end)
-{
-	flush_tlb_mm(vma->vm_mm);
-}
-
-#else /* CONFIG_SMP */
-
-extern void flush_tlb_all(void);
-extern void flush_tlb_mm(struct mm_struct *);
-extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
-extern void flush_tlb_range(struct vm_area_struct *, unsigned long, unsigned long);
-
-#endif /* CONFIG_SMP */
-
 /*      
  * Allocate and free page tables. The xxx_kernel() versions are
  * used to allocate a kernel page table - this turns on ASN bits
@@ -291,5 +69,7 @@
 {
 	__free_page(page);
 }
+
+#define check_pgt_cache()	do { } while (0)
 
 #endif /* _ALPHA_PGALLOC_H */
diff -Nru a/include/asm-alpha/tlbflush.h b/include/asm-alpha/tlbflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-alpha/tlbflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,157 @@
+#ifndef _ALPHA_TLBFLUSH_H
+#define _ALPHA_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+
+#ifndef __EXTERN_INLINE
+#define __EXTERN_INLINE extern inline
+#define __MMU_EXTERN_INLINE
+#endif
+
+extern void __load_new_mm_context(struct mm_struct *);
+
+
+/* Use a few helper functions to hide the ugly broken ASN
+   numbers on early Alphas (ev4 and ev45).  */
+
+__EXTERN_INLINE void
+ev4_flush_tlb_current(struct mm_struct *mm)
+{
+	__load_new_mm_context(mm);
+	tbiap();
+}
+
+__EXTERN_INLINE void
+ev5_flush_tlb_current(struct mm_struct *mm)
+{
+	__load_new_mm_context(mm);
+}
+
+/* Flush just one page in the current TLB set.  We need to be very
+   careful about the icache here, there is no way to invalidate a
+   specific icache page.  */
+
+__EXTERN_INLINE void
+ev4_flush_tlb_current_page(struct mm_struct * mm,
+			   struct vm_area_struct *vma,
+			   unsigned long addr)
+{
+	int tbi_flag = 2;
+	if (vma->vm_flags & VM_EXEC) {
+		__load_new_mm_context(mm);
+		tbi_flag = 3;
+	}
+	tbi(tbi_flag, addr);
+}
+
+__EXTERN_INLINE void
+ev5_flush_tlb_current_page(struct mm_struct * mm,
+			   struct vm_area_struct *vma,
+			   unsigned long addr)
+{
+	if (vma->vm_flags & VM_EXEC)
+		__load_new_mm_context(mm);
+	else
+		tbi(2, addr);
+}
+
+
+#ifdef CONFIG_ALPHA_GENERIC
+# define flush_tlb_current		alpha_mv.mv_flush_tlb_current
+# define flush_tlb_current_page		alpha_mv.mv_flush_tlb_current_page
+#else
+# ifdef CONFIG_ALPHA_EV4
+#  define flush_tlb_current		ev4_flush_tlb_current
+#  define flush_tlb_current_page	ev4_flush_tlb_current_page
+# else
+#  define flush_tlb_current		ev5_flush_tlb_current
+#  define flush_tlb_current_page	ev5_flush_tlb_current_page
+# endif
+#endif
+
+#ifdef __MMU_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __MMU_EXTERN_INLINE
+#endif
+
+/* Flush current user mapping.  */
+static inline void
+flush_tlb(void)
+{
+	flush_tlb_current(current->active_mm);
+}
+
+/* Flush someone else's user mapping.  */
+static inline void
+flush_tlb_other(struct mm_struct *mm)
+{
+	long *mmc = &mm->context[smp_processor_id()];
+	/* Check it's not zero first to avoid cacheline ping pong
+	   when possible.  */
+	if (*mmc) *mmc = 0;
+}
+
+/* Flush a specified range of user mapping page tables from TLB.
+   Although Alpha uses VPTE caches, this can be a nop, as Alpha does
+   not have finegrained tlb flushing, so it will flush VPTE stuff
+   during next flush_tlb_range.  */
+
+static inline void
+flush_tlb_pgtables(struct mm_struct *mm, unsigned long start,
+		   unsigned long end)
+{
+}
+
+#ifndef CONFIG_SMP
+/* Flush everything (kernel mapping may also have changed
+   due to vmalloc/vfree).  */
+static inline void flush_tlb_all(void)
+{
+	tbia();
+}
+
+/* Flush a specified user mapping.  */
+static inline void
+flush_tlb_mm(struct mm_struct *mm)
+{
+	if (mm == current->active_mm)
+		flush_tlb_current(mm);
+	else
+		flush_tlb_other(mm);
+}
+
+/* Page-granular tlb flush.  */
+static inline void
+flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (mm == current->active_mm)
+		flush_tlb_current_page(mm, vma, addr);
+	else
+		flush_tlb_other(mm);
+}
+
+/* Flush a specified range of user mapping.  On the Alpha we flush
+   the whole user tlb.  */
+static inline void
+flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+		unsigned long end)
+{
+	flush_tlb_mm(vma->vm_mm);
+}
+
+#else /* CONFIG_SMP */
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *);
+extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+extern void flush_tlb_range(struct vm_area_struct *, unsigned long,
+			    unsigned long);
+
+#endif /* CONFIG_SMP */
+
+#define flush_tlb_kernel_range(start, end) flush_tlb_all()
+
+#endif /* _ALPHA_TLBFLUSH_H */
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-alpha/unistd.h	Sun Apr 14 12:16:58 2002
@@ -597,4 +597,12 @@
 
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ALPHA_UNISTD_H */
diff -Nru a/include/asm-arm/arch-cl7500/system.h b/include/asm-arm/arch-cl7500/system.h
--- a/include/asm-arm/arch-cl7500/system.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-arm/arch-cl7500/system.h	Sun Apr 14 12:16:59 2002
@@ -18,6 +18,6 @@
 	do {					\
 		iomd_writeb(0, IOMD_ROMCR0);	\
 		cpu_reset(0);			\
-	} while (0);
+	} while (0)
 
 #endif
diff -Nru a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/dma.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/dma.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+/* No DMA as the rest of the world see it */
+#define MAX_DMA_CHANNELS	0
+
+/*
+ * Descriptor structure for PXA's DMA engine
+ * Note: this structure must always be aligned to a 16-byte boundary.
+ */
+
+typedef struct {
+	volatile u32 ddadr;	/* Points to the next descriptor + flags */
+	volatile u32 dsadr;	/* DSADR value for the current transfer */
+	volatile u32 dtadr;	/* DTADR value for the current transfer */
+	volatile u32 dcmd;	/* DCMD value for the current transfer */
+} pxa_dma_desc;
+
+/*
+ * DMA registration
+ */
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 4,
+	DMA_PRIO_LOW = 8
+} pxa_dma_prio;
+
+int pxa_request_dma (char *name,
+			 pxa_dma_prio prio,
+			 void (*irq_handler)(int, void *, struct pt_regs *),
+			 void *data);
+
+void pxa_free_dma (int dma_ch);
+
+#endif /* _ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/hardware.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,97 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/hardware.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * These are statically mapped PCMCIA IO space for designs using it as a
+ * generic IO bus, typically with ISA parts, hardwired IDE interfaces, etc.
+ * The actual PCMCIA code is mapping required IO region at run time.
+ */
+#define PCMCIA_IO_0_BASE	0xf6000000
+#define PCMCIA_IO_1_BASE	0xf7000000
+
+
+/*
+ * Intel PXA internal I/O mappings
+ */
+
+#define io_p2v(x)	\
+	(((x) < 0x44000000) ? ((x) - 0x40000000 + 0xfc000000) :	\
+	 ((x) < 0x48000000) ? ((x) - 0x44000000 + 0xfe000000) :	\
+	 		      ((x) - 0x48000000 + 0xff000000))
+#define io_v2p( x )	\
+	(((x) < 0xfe000000) ? ((x) - 0xfc000000 + 0x40000000) :	\
+	 ((x) < 0xff000000) ? ((x) - 0xfe000000 + 0x44000000) :	\
+	 		      ((x) - 0xff000000 + 0x48000000))
+
+#ifndef __ASSEMBLY__
+
+#if 0
+# define __REG(x)	(*((volatile u32 *)io_p2v(x)))
+#else
+/*
+ * This __REG() version gives the same results as the one above,  except
+ * that we are fooling gcc somehow so it generates far better and smaller
+ * assembly code for access to contigous registers.  It's a shame that gcc
+ * doesn't guess this by itself.
+ */
+#include <asm/types.h>
+typedef struct { volatile u32 offset[1024]; } __regbase;
+# define __REGP(x)	((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
+# define __REG(x)	__REGP(io_p2v(x))
+#endif
+
+/* Let's kick gcc's ass again... */
+# define __REG2(x,y)	\
+	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
+				  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+
+# define __PREG(x)	(io_v2p((u32)&(x)))
+
+#else
+
+# define __REG(x)	io_p2v(x)
+# define __PREG(x)	io_v2p(x)
+
+#endif
+
+#include "pxa-regs.h"
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Handy routine to set GPIO alternate functions
+ */
+extern void pxa_gpio_mode( int gpio_mode );
+
+/*
+ * return current lclk frequency in units of 10kHz
+ */
+extern unsigned int get_lclk_frequency_10khz(void);
+
+#endif
+
+
+/*
+ * Implementation specifics
+ */
+
+#include "lubbock.h"
+#include "idp.h"
+
+#endif  /* _ASM_ARCH_HARDWARE_H */
diff -Nru a/include/asm-arm/arch-pxa/ide.h b/include/asm-arm/arch-pxa/ide.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/ide.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,57 @@
+/*
+ * linux/include/asm-arm/arch-pxa/ide.h
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * Originally based upon linux/include/asm-arm/arch-sa1100/ide.h
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
+{
+	ide_ioreg_t reg;
+	int i;
+	int regincr = 1;
+
+	memset(hw, 0, sizeof(*hw));
+
+	reg = (ide_ioreg_t)data_port;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += regincr;
+	}
+
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+
+	if (irq)
+		*irq = 0;
+}
+
+
+/*
+ * Register the standard ports for this architecture with the IDE driver.
+ */
+static __inline__ void
+ide_init_default_hwifs(void)
+{
+	/* Nothing to declare... */
+}
diff -Nru a/include/asm-arm/arch-pxa/idp.h b/include/asm-arm/arch-pxa/idp.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/idp.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,418 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/idp.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (c) 2001 Cliff Brake, Accelent Systems Inc.
+ *
+ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
+ *             Initial code
+ *
+ */
+
+
+/*
+ * Note: this file must be safe to include in assembly files
+ */
+
+/* comment out following if you have a rev01 board */
+#define PXA_IDP_REV02	1
+//#undef PXA_IDP_REV02
+
+#ifdef PXA_IDP_REV02
+
+#define IDP_FLASH_PHYS		(PXA_CS0_PHYS)
+#define IDP_ALT_FLASH_PHYS	(PXA_CS1_PHYS)
+#define IDP_MEDIAQ_PHYS		(PXA_CS3_PHYS)
+#define IDP_IDE_PHYS		(PXA_CS5_PHYS + 0x03000000)
+#define IDP_ETH_PHYS		(PXA_CS5_PHYS + 0x03400000)
+#define IDP_COREVOLT_PHYS	(PXA_CS5_PHYS + 0x03800000)
+#define IDP_CPLD_PHYS		(PXA_CS5_PHYS + 0x03C00000)
+
+
+/*
+ * virtual memory map
+ */
+
+#define IDP_IDE_BASE		(0xf0000000)
+#define IDP_IDE_SIZE		(1*1024*1024)
+
+#define IDP_ETH_BASE		(IDP_IDE_BASE + IDP_IDE_SIZE)
+#define IDP_ETH_SIZE		(1*1024*1024)
+#define ETH_BASE		IDP_ETH_BASE //smc9194 driver compatibility issue
+
+#define IDP_COREVOLT_BASE	(IDP_ETH_BASE + IDP_ETH_SIZE)
+#define IDP_COREVOLT_SIZE	(1*1024*1024)
+
+#define IDP_CPLD_BASE		(IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
+#define IDP_CPLD_SIZE		(1*1024*1024)
+
+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
+#error Your custom IO space is getting a bit large !!
+#endif
+
+#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
+#define CPLD_V2P(x)		((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __CPLD_REG(x)		(*((volatile unsigned long *)CPLD_P2V(x)))
+#else
+#  define __CPLD_REG(x)		CPLD_P2V(x)
+#endif
+
+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+
+#define _IDP_CPLD_REV			(IDP_CPLD_PHYS + 0x00)
+#define _IDP_CPLD_PERIPH_PWR		(IDP_CPLD_PHYS + 0x04)
+#define _IDP_CPLD_LED_CONTROL		(IDP_CPLD_PHYS + 0x08)
+#define _IDP_CPLD_KB_COL_HIGH		(IDP_CPLD_PHYS + 0x0C)
+#define _IDP_CPLD_KB_COL_LOW		(IDP_CPLD_PHYS + 0x10)
+#define _IDP_CPLD_PCCARD_EN		(IDP_CPLD_PHYS + 0x14)
+#define _IDP_CPLD_GPIOH_DIR		(IDP_CPLD_PHYS + 0x18)
+#define _IDP_CPLD_GPIOH_VALUE		(IDP_CPLD_PHYS + 0x1C)
+#define _IDP_CPLD_GPIOL_DIR		(IDP_CPLD_PHYS + 0x20)
+#define _IDP_CPLD_GPIOL_VALUE		(IDP_CPLD_PHYS + 0x24)
+#define _IDP_CPLD_PCCARD_PWR		(IDP_CPLD_PHYS + 0x28)
+#define _IDP_CPLD_MISC_CTRL		(IDP_CPLD_PHYS + 0x2C)
+#define _IDP_CPLD_LCD			(IDP_CPLD_PHYS + 0x30)
+#define _IDP_CPLD_FLASH_WE		(IDP_CPLD_PHYS + 0x34)
+
+#define _IDP_CPLD_KB_ROW		(IDP_CPLD_PHYS + 0x50)
+#define _IDP_CPLD_PCCARD0_STATUS	(IDP_CPLD_PHYS + 0x54)
+#define _IDP_CPLD_PCCARD1_STATUS	(IDP_CPLD_PHYS + 0x58)
+#define _IDP_CPLD_MISC_STATUS		(IDP_CPLD_PHYS + 0x5C)
+
+/* FPGA register virtual addresses */
+
+#define IDP_CPLD_REV			__CPLD_REG(_IDP_CPLD_REV)
+#define IDP_CPLD_PERIPH_PWR		__CPLD_REG(_IDP_CPLD_PERIPH_PWR)
+#define IDP_CPLD_LED_CONTROL		__CPLD_REG(_IDP_CPLD_LED_CONTROL)
+#define IDP_CPLD_KB_COL_HIGH		__CPLD_REG(_IDP_CPLD_KB_COL_HIGH)
+#define IDP_CPLD_KB_COL_LOW		__CPLD_REG(_IDP_CPLD_KB_COL_LOW)
+#define IDP_CPLD_PCCARD_EN		__CPLD_REG(_IDP_CPLD_PCCARD_EN)
+#define IDP_CPLD_GPIOH_DIR		__CPLD_REG(_IDP_CPLD_GPIOH_DIR)
+#define IDP_CPLD_GPIOH_VALUE		__CPLD_REG(_IDP_CPLD_GPIOH_VALUE)
+#define IDP_CPLD_GPIOL_DIR		__CPLD_REG(_IDP_CPLD_GPIOL_DIR)
+#define IDP_CPLD_GPIOL_VALUE		__CPLD_REG(_IDP_CPLD_GPIOL_VALUE)
+#define IDP_CPLD_PCCARD_PWR		__CPLD_REG(_IDP_CPLD_PCCARD_PWR)
+#define IDP_CPLD_MISC_CTRL		__CPLD_REG(_IDP_CPLD_MISC_CTRL)
+#define IDP_CPLD_LCD			__CPLD_REG(_IDP_CPLD_LCD)
+#define IDP_CPLD_FLASH_WE		__CPLD_REG(_IDP_CPLD_FLASH_WE)
+
+#define IDP_CPLD_KB_ROW		        __CPLD_REG(_IDP_CPLD_KB_ROW)
+#define IDP_CPLD_PCCARD0_STATUS	        __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)
+#define IDP_CPLD_PCCARD1_STATUS	        __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)
+#define IDP_CPLD_MISC_STATUS		__CPLD_REG(_IDP_CPLD_MISC_STATUS)
+
+
+/*
+ * Bit masks for various registers
+ */
+
+
+/*
+ * Macros for LCD Driver
+ */
+
+#ifdef CONFIG_FB_PXA
+
+#define FB_BACKLIGHT_ON()	(IDP_CPLD_LCD |= (1<<1))
+#define FB_BACKLIGHT_OFF() 	(IDP_CPLD_LCD &= ~(1<<1))
+
+#define FB_PWR_ON() 		(IDP_CPLD_LCD |= (1<< 0))
+#define FB_PWR_OFF() 		(IDP_CPLD_LCD &= ~(1<<0))
+
+#define FB_VLCD_ON()		(IDP_CPLD_LCD |= (1<<2))
+#define FB_VLCD_OFF() 		(IDP_CPLD_LCD &= ~(1<<2))
+
+#endif
+
+
+/*
+ * Macros for LED Driver
+ */
+
+/* leds 0 = ON */
+#define IDP_HB_LED	(1<<5)
+#define IDP_BUSY_LED	(1<<6)
+
+#define IDP_LEDS_MASK	(IDP_HB_LED | IDP_BUSY_LED)
+
+#define IDP_WRITE_LEDS(value)	(IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & (~(IDP_LEDS_MASK)) | value))
+
+/*
+ * macros for MTD driver
+ */
+
+#define FLASH_WRITE_PROTECT_DISABLE()	((IDP_CPLD_FLASH_WE) &= ~(0x1))
+#define FLASH_WRITE_PROTECT_ENABLE()	((IDP_CPLD_FLASH_WE) |= (0x1))
+
+/*
+ * macros for matrix keyboard driver
+ */
+
+#define KEYBD_MATRIX_NUMBER_INPUTS	7
+#define KEYBD_MATRIX_NUMBER_OUTPUTS	14
+
+#define KEYBD_MATRIX_INVERT_OUTPUT_LOGIC	FALSE
+#define KEYBD_MATRIX_INVERT_INPUT_LOGIC		FALSE
+
+#define KEYBD_MATRIX_SETTLING_TIME_US			100
+#define KEYBD_MATRIX_KEYSTATE_DEBOUNCE_CONSTANT		2
+
+#define KEYBD_MATRIX_SET_OUTPUTS(outputs) \
+{\
+	IDP_CPLD_KB_COL_LOW = outputs;\
+	IDP_CPLD_KB_COL_HIGH = outputs >> 7;\
+}
+
+#define KEYBD_MATRIX_GET_INPUTS(inputs) \
+{\
+	inputs = (IDP_CPLD_KB_ROW & 0x7f);\
+}
+
+/* A listing of interrupts used by external hardware devices */
+
+#define TOUCH_PANEL_IRQ			IRQ_GPIO(21)
+#define TOUCH_PANEL_IRQ_EGDE		GPIO_FALLING_EDGE
+
+#define ETHERNET_IRQ			IRQ_GPIO(4)
+#define ETHERNET_IRQ_EDGE		GPIO_RISING_EDGE
+
+#else
+
+/*
+ * following is for rev01 boards only
+ */
+
+#define IDP_FLASH_PHYS		(PXA_CS0_PHYS)
+#define IDP_ALT_FLASH_PHYS	(PXA_CS1_PHYS)
+#define IDP_MEDIAQ_PHYS		(PXA_CS3_PHYS)
+#define IDP_CTRL_PORT_PHYS	(PXA_CS5_PHYS + 0x02C00000)
+#define IDP_IDE_PHYS		(PXA_CS5_PHYS + 0x03000000)
+#define IDP_ETH_PHYS		(PXA_CS5_PHYS + 0x03400000)
+#define IDP_COREVOLT_PHYS	(PXA_CS5_PHYS + 0x03800000)
+#define IDP_CPLD_PHYS		(PXA_CS5_PHYS + 0x03C00000)
+
+
+/*
+ * virtual memory map
+ */
+
+#define IDP_CTRL_PORT_BASE	(0xf0000000)
+#define IDP_CTRL_PORT_SIZE	(1*1024*1024)
+
+#define IDP_IDE_BASE		(IDP_CTRL_PORT_BASE + IDP_CTRL_PORT_SIZE)
+#define IDP_IDE_SIZE		(1*1024*1024)
+
+#define IDP_ETH_BASE		(IDP_IDE_BASE + IDP_IDE_SIZE)
+#define IDP_ETH_SIZE		(1*1024*1024)
+
+#define IDP_COREVOLT_BASE	(IDP_ETH_BASE + IDP_ETH_SIZE)
+#define IDP_COREVOLT_SIZE	(1*1024*1024)
+
+#define IDP_CPLD_BASE		(IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
+#define IDP_CPLD_SIZE		(1*1024*1024)
+
+#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
+#error Your custom IO space is getting a bit large !!
+#endif
+
+#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
+#define CPLD_V2P(x)		((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __CPLD_REG(x)		(*((volatile unsigned long *)CPLD_P2V(x)))
+#else
+#  define __CPLD_REG(x)		CPLD_P2V(x)
+#endif
+
+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+
+#define _IDP_CPLD_LED_CONTROL		(IDP_CPLD_PHYS + 0x00)
+#define _IDP_CPLD_PERIPH_PWR		(IDP_CPLD_PHYS + 0x04)
+#define _IDP_CPLD_CIR			(IDP_CPLD_PHYS + 0x08)
+#define _IDP_CPLD_KB_COL_HIGH		(IDP_CPLD_PHYS + 0x0C)
+#define _IDP_CPLD_KB_COL_LOW		(IDP_CPLD_PHYS + 0x10)
+#define _IDP_CPLD_PCCARD_EN		(IDP_CPLD_PHYS + 0x14)
+#define _IDP_CPLD_GPIOH_DIR		(IDP_CPLD_PHYS + 0x18)
+#define _IDP_CPLD_GPIOH_VALUE		(IDP_CPLD_PHYS + 0x1C)
+#define _IDP_CPLD_GPIOL_DIR		(IDP_CPLD_PHYS + 0x20)
+#define _IDP_CPLD_GPIOL_VALUE		(IDP_CPLD_PHYS + 0x24)
+#define _IDP_CPLD_MISC			(IDP_CPLD_PHYS + 0x28)
+#define _IDP_CPLD_PCCARD0_STATUS	(IDP_CPLD_PHYS + 0x2C)
+#define _IDP_CPLD_PCCARD1_STATUS	(IDP_CPLD_PHYS + 0x30)
+
+/* FPGA register virtual addresses */
+#define IDP_CPLD_LED_CONTROL		__CPLD_REG(_IDP_CPLD_LED_CONTROL)	/* write only */
+#define IDP_CPLD_PERIPH_PWR		__CPLD_REG(_IDP_CPLD_PERIPH_PWR)	/* write only */
+#define IDP_CPLD_CIR			__CPLD_REG(_IDP_CPLD_CIR)		/* write only */
+#define IDP_CPLD_KB_COL_HIGH		__CPLD_REG(_IDP_CPLD_KB_COL_HIGH)	/* write only */
+#define IDP_CPLD_KB_COL_LOW		__CPLD_REG(_IDP_CPLD_KB_COL_LOW)	/* write only */
+#define IDP_CPLD_PCCARD_EN		__CPLD_REG(_IDP_CPLD_PCCARD_EN)		/* write only */
+#define IDP_CPLD_GPIOH_DIR		__CPLD_REG(_IDP_CPLD_GPIOH_DIR)		/* write only */
+#define IDP_CPLD_GPIOH_VALUE		__CPLD_REG(_IDP_CPLD_GPIOH_VALUE)	/* write only */
+#define IDP_CPLD_GPIOL_DIR		__CPLD_REG(_IDP_CPLD_GPIOL_DIR)		/* write only */
+#define IDP_CPLD_GPIOL_VALUE		__CPLD_REG(_IDP_CPLD_GPIOL_VALUE)	/* write only */
+#define IDP_CPLD_MISC			__CPLD_REG(_IDP_CPLD_MISC)		/* read only */
+#define IDP_CPLD_PCCARD0_STATUS		__CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)	/* read only */
+#define IDP_CPLD_PCCARD1_STATUS		__CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)	/* read only */
+
+
+#ifndef __ASSEMBLY__
+
+/* shadow registers for write only registers */
+extern unsigned int idp_cpld_led_control_shadow;
+extern unsigned int idp_cpld_periph_pwr_shadow;
+extern unsigned int idp_cpld_cir_shadow;
+extern unsigned int idp_cpld_kb_col_high_shadow;
+extern unsigned int idp_cpld_kb_col_low_shadow;
+extern unsigned int idp_cpld_pccard_en_shadow;
+extern unsigned int idp_cpld_gpioh_dir_shadow;
+extern unsigned int idp_cpld_gpioh_value_shadow;
+extern unsigned int idp_cpld_gpiol_dir_shadow;
+extern unsigned int idp_cpld_gpiol_value_shadow;
+
+extern unsigned int idp_control_port_shadow;
+
+/*
+ * macros to write to write only register
+ *
+ * none of these macros are protected from
+ * multiple drivers using them in interrupt context.
+ */
+
+#define WRITE_IDP_CPLD_LED_CONTROL(value, mask) \
+{\
+	idp_cpld_led_control_shadow = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
+	IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
+}
+#define WRITE_IDP_CPLD_PERIPH_PWR(value, mask) \
+{\
+	idp_cpld_periph_pwr_shadow = ((value & mask) | (idp_cpld_periph_pwr_shadow & ~mask));\
+	IDP_CPLD_PERIPH_PWR = idp_cpld_periph_pwr_shadow;\
+}
+#define WRITE_IDP_CPLD_CIR(value, mask) \
+{\
+	idp_cpld_cir_shadow = ((value & mask) | (idp_cpld_cir_shadow & ~mask));\
+	IDP_CPLD_CIR = idp_cpld_cir_shadow;\
+}
+#define WRITE_IDP_CPLD_KB_COL_HIGH(value, mask) \
+{\
+	idp_cpld_kb_col_high_shadow = ((value & mask) | (idp_cpld_kb_col_high_shadow & ~mask));\
+	IDP_CPLD_KB_COL_HIGH = idp_cpld_kb_col_high_shadow;\
+}
+#define WRITE_IDP_CPLD_KB_COL_LOW(value, mask) \
+{\
+	idp_cpld_kb_col_low_shadow = ((value & mask) | (idp_cpld_kb_col_low_shadow & ~mask));\
+	IDP_CPLD_KB_COL_LOW = idp_cpld_kb_col_low_shadow;\
+}
+#define WRITE_IDP_CPLD_PCCARD_EN(value, mask) \
+{\
+	idp_cpld_ = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
+	IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOH_DIR(value, mask) \
+{\
+	idp_cpld_gpioh_dir_shadow = ((value & mask) | (idp_cpld_gpioh_dir_shadow & ~mask));\
+	IDP_CPLD_GPIOH_DIR = idp_cpld_gpioh_dir_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOH_VALUE(value, mask) \
+{\
+	idp_cpld_gpioh_value_shadow = ((value & mask) | (idp_cpld_gpioh_value_shadow & ~mask));\
+	IDP_CPLD_GPIOH_VALUE = idp_cpld_gpioh_value_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOL_DIR(value, mask) \
+{\
+	idp_cpld_gpiol_dir_shadow = ((value & mask) | (idp_cpld_gpiol_dir_shadow & ~mask));\
+	IDP_CPLD_GPIOL_DIR = idp_cpld_gpiol_dir_shadow;\
+}
+#define WRITE_IDP_CPLD_GPIOL_VALUE(value, mask) \
+{\
+	idp_cpld_gpiol_value_shadow = ((value & mask) | (idp_cpld_gpiol_value_shadow & ~mask));\
+	IDP_CPLD_GPIOL_VALUE = idp_cpld_gpiol_value_shadow;\
+}
+
+#define WRITE_IDP_CONTROL_PORT(value, mask) \
+{\
+	idp_control_port_shadow = ((value & mask) | (idp_control_port_shadow & ~mask));\
+	(*((volatile unsigned long *)IDP_CTRL_PORT_BASE)) = idp_control_port_shadow;\
+}
+
+#endif
+
+/* A listing of interrupts used by external hardware devices */
+
+#define TOUCH_PANEL_IRQ			IRQ_GPIO(21)
+#define TOUCH_PANEL_IRQ_EGDE		GPIO_FALLING_EDGE
+
+#define ETHERNET_IRQ			IRQ_GPIO(4)
+#define ETHERNET_IRQ_EDGE		GPIO_RISING_EDGE
+
+/*
+ * Bit masks for various registers
+ */
+
+
+/* control port */
+#define IDP_CONTROL_PORT_PCSLOT0_0	(1 << 0)
+#define IDP_CONTROL_PORT_PCSLOT0_1	(1 << 1)
+#define IDP_CONTROL_PORT_PCSLOT0_2	(1 << 2)
+#define IDP_CONTROL_PORT_PCSLOT0_3	(1 << 3)
+#define IDP_CONTROL_PORT_PCSLOT1_1	(1 << 4)
+#define IDP_CONTROL_PORT_PCSLOT1_2	(1 << 5)
+#define IDP_CONTROL_PORT_PCSLOT1_3	(1 << 6)
+#define IDP_CONTROL_PORT_PCSLOT1_4	(1 << 7)
+#define IDP_CONTROL_PORT_SERIAL1_EN	(1 << 9)
+#define IDP_CONTROL_PORT_SERIAL2_EN	(1 << 10)
+#define IDP_CONTROL_PORT_SERIAL3_EN	(1 << 11)
+#define IDP_CONTROL_PORT_IRDA_FIR	(1 << 12)
+#define IDP_CONTROL_PORT_IRDA_M0	(1 << 13)
+#define IDP_CONTROL_PORT_IRDA_M1	(1 << 14)
+#define IDP_CONTROL_PORT_I2S_PWR	(1 << 15)
+#define IDP_CONTROL_PORT_FLASH_WP	(1 << 19)
+#define IDP_CONTROL_PORT_MILL_EN	(1 << 20)
+#define IDP_CONTROL_PORT_LCD_PWR	(1 << 21)
+#define IDP_CONTROL_PORT_LCD_BKLEN	(1 << 22)
+#define IDP_CONTROL_PORT_LCD_ENAVLCD	(1 << 23)
+
+/*
+ * Macros for LCD Driver
+ */
+
+#ifdef CONFIG_FB_PXA
+
+#define FB_BACKLIGHT_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_BKLEN, IDP_CONTROL_PORT_LCD_BKLEN)
+#define FB_BACKLIGHT_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_BKLEN)
+
+#define FB_PWR_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_PWR, IDP_CONTROL_PORT_LCD_PWR)
+#define FB_PWR_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_PWR)
+
+#define FB_VLCD_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_ENAVLCD, IDP_CONTROL_PORT_LCD_ENAVLCD)
+#define FB_VLCD_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_ENAVLCD)
+
+#endif
+
+
+/*
+ * Macros for LED Driver
+ */
+
+/* leds 0 = ON */
+#define IDP_HB_LED	0x1
+#define IDP_BUSY_LED	0x2
+
+#define IDP_LEDS_MASK	(IDP_HB_LED | IDP_BUSY_LED)
+
+#define IDP_WRITE_LEDS(value) 	WRITE_IDP_CPLD_LED_CONTROL(value, IDP_LEDS_MASK)
+
+/*
+ * macros for MTD driver
+ */
+
+#define FLASH_WRITE_PROTECT_DISABLE()	WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_FLASH_WP)
+#define FLASH_WRITE_PROTECT_ENABLE()	WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_FLASH_WP, IDP_CONTROL_PORT_FLASH_WP)
+
+#endif
diff -Nru a/include/asm-arm/arch-pxa/io.h b/include/asm-arm/arch-pxa/io.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/io.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-pxa/io.h
+ *
+ * Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a)			(a)
+#define __mem_pci(a)		((unsigned long)(a))
+#define __mem_isa(a)		((unsigned long)(a))
+
+#endif
diff -Nru a/include/asm-arm/arch-pxa/irq.h b/include/asm-arm/arch-pxa/irq.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/irq.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-pxa/irq.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define fixup_irq(x)	(x)
+
+/*
+ * This prototype is required for cascading of multiplexed interrupts.
+ * Since it doesn't exist elsewhere, we'll put it here for now.
+ */
+extern void do_IRQ(int irq, struct pt_regs *regs);
diff -Nru a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/irqs.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,132 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/irqs.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define PXA_IRQ_SKIP	8	/* The first 8 IRQs are reserved */
+#define PXA_IRQ(x)		((x) - PXA_IRQ_SKIP)
+
+#define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
+#define	IRQ_GPIO1	PXA_IRQ(9)	/* GPIO1 Edge Detect */
+#define	IRQ_GPIO_2_80	PXA_IRQ(10)	/* GPIO[2-80] Edge Detect */
+#define	IRQ_USB		PXA_IRQ(11)	/* USB Service */
+#define	IRQ_PMU		PXA_IRQ(12)	/* Performance Monitoring Unit */
+#define	IRQ_I2S		PXA_IRQ(13)	/* I2S Interrupt */
+#define	IRQ_AC97	PXA_IRQ(14)	/* AC97 Interrupt */
+#define	IRQ_LCD		PXA_IRQ(17)	/* LCD Controller Service Request */
+#define	IRQ_I2C		PXA_IRQ(18)	/* I2C Service Request */
+#define	IRQ_ICP		PXA_IRQ(19)	/* ICP Transmit/Receive/Error */
+#define	IRQ_STUART	PXA_IRQ(20)	/* STUART Transmit/Receive/Error */
+#define	IRQ_BTUART	PXA_IRQ(21)	/* BTUART Transmit/Receive/Error */
+#define	IRQ_FFUART	PXA_IRQ(22)	/* FFUART Transmit/Receive/Error*/
+#define	IRQ_MMC		PXA_IRQ(23)	/* MMC Status/Error Detection */
+#define	IRQ_SSP		PXA_IRQ(24)	/* SSP Service Request */
+#define	IRQ_DMA 	PXA_IRQ(25)	/* DMA Channel Service Request */
+#define	IRQ_OST0 	PXA_IRQ(26)	/* OS Timer match 0 */
+#define	IRQ_OST1 	PXA_IRQ(27)	/* OS Timer match 1 */
+#define	IRQ_OST2 	PXA_IRQ(28)	/* OS Timer match 2 */
+#define	IRQ_OST3 	PXA_IRQ(29)	/* OS Timer match 3 */
+#define	IRQ_RTC1Hz	PXA_IRQ(30)	/* RTC HZ Clock Tick */
+#define	IRQ_RTCAlrm	PXA_IRQ(31)	/* RTC Alarm */
+
+#define GPIO_2_80_TO_IRQ(x)	\
+			PXA_IRQ((x) - 2 + 32)
+#define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_80_TO_IRQ(x))
+
+#define IRQ_TO_GPIO_2_80(i)	\
+			((i) - PXA_IRQ(32) + 2)
+#define IRQ_TO_GPIO(i)	((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) : IRQ_GPIO(0)))
+
+#define	NR_IRQS		(IRQ_GPIO(80) + 1)
+
+#if defined(CONFIG_SA1111)
+
+#define IRQ_SA1111_START	(IRQ_GPIO(80) + 1)
+#define SA1111_IRQ(x)		(IRQ_SA1111_START + (x))
+
+#define IRQ_GPAIN0		SA1111_IRQ(0)
+#define IRQ_GPAIN1		SA1111_IRQ(1)
+#define IRQ_GPAIN2		SA1111_IRQ(2)
+#define IRQ_GPAIN3		SA1111_IRQ(3)
+#define IRQ_GPBIN0		SA1111_IRQ(4)
+#define IRQ_GPBIN1		SA1111_IRQ(5)
+#define IRQ_GPBIN2		SA1111_IRQ(6)
+#define IRQ_GPBIN3		SA1111_IRQ(7)
+#define IRQ_GPBIN4		SA1111_IRQ(8)
+#define IRQ_GPBIN5		SA1111_IRQ(9)
+#define IRQ_GPCIN0		SA1111_IRQ(10)
+#define IRQ_GPCIN1		SA1111_IRQ(11)
+#define IRQ_GPCIN2		SA1111_IRQ(12)
+#define IRQ_GPCIN3		SA1111_IRQ(13)
+#define IRQ_GPCIN4		SA1111_IRQ(14)
+#define IRQ_GPCIN5		SA1111_IRQ(15)
+#define IRQ_GPCIN6		SA1111_IRQ(16)
+#define IRQ_GPCIN7		SA1111_IRQ(17)
+#define IRQ_MSTXINT		SA1111_IRQ(18)
+#define IRQ_MSRXINT		SA1111_IRQ(19)
+#define IRQ_MSSTOPERRINT	SA1111_IRQ(20)
+#define IRQ_TPTXINT		SA1111_IRQ(21)
+#define IRQ_TPRXINT		SA1111_IRQ(22)
+#define IRQ_TPSTOPERRINT	SA1111_IRQ(23)
+#define SSPXMTINT	SA1111_IRQ(24)
+#define SSPRCVINT	SA1111_IRQ(25)
+#define SSPROR		SA1111_IRQ(26)
+#define AUDXMTDMADONEA	SA1111_IRQ(32)
+#define AUDRCVDMADONEA	SA1111_IRQ(33)
+#define AUDXMTDMADONEB	SA1111_IRQ(34)
+#define AUDRCVDMADONEB	SA1111_IRQ(35)
+#define AUDTFSR		SA1111_IRQ(36)
+#define AUDRFSR		SA1111_IRQ(37)
+#define AUDTUR		SA1111_IRQ(38)
+#define AUDROR		SA1111_IRQ(39)
+#define AUDDTS		SA1111_IRQ(40)
+#define AUDRDD		SA1111_IRQ(41)
+#define AUDSTO		SA1111_IRQ(42)
+#define USBPWR		SA1111_IRQ(43)
+#define NIRQHCIM	SA1111_IRQ(44)
+#define HCIBUFFACC	SA1111_IRQ(45)
+#define HCIRMTWKP	SA1111_IRQ(46)
+#define NHCIMFCIR	SA1111_IRQ(47)
+#define PORT_RESUME	SA1111_IRQ(48)
+#define S0_READY_NINT	SA1111_IRQ(49)
+#define S1_READY_NINT	SA1111_IRQ(50)
+#define S0_CD_VALID	SA1111_IRQ(51)
+#define S1_CD_VALID	SA1111_IRQ(52)
+#define S0_BVD1_STSCHG	SA1111_IRQ(53)
+#define S1_BVD1_STSCHG	SA1111_IRQ(54)
+
+#define SA1111_IRQ_MAX	SA1111_IRQ(54)
+
+#undef NR_IRQS
+#define NR_IRQS		(SA1111_IRQ_MAX + 1)
+
+#endif	// defined(CONFIG_SA1111)
+
+#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_PXA_IDP)
+#if CONFIG_SA1111
+#define LUBBOCK_IRQ(x)	(SA1111_IRQ_MAX + 1 + (x))
+#else
+#define LUBBOCK_IRQ(x)	(IRQ_GPIO(80) + 1 + (x))
+#endif
+
+#define LUBBOCK_SD_IRQ		LUBBOCK_IRQ(0)
+#define LUBBOCK_SA1111_IRQ	LUBBOCK_IRQ(1)
+#define LUBBOCK_USB_IRQ		LUBBOCK_IRQ(2)
+#define LUBBOCK_ETH_IRQ		LUBBOCK_IRQ(3)
+#define LUBBOCK_UCB1400_IRQ	LUBBOCK_IRQ(4)
+#define LUBBOCK_BB_IRQ		LUBBOCK_IRQ(5)
+
+#undef NR_IRQS
+#define NR_IRQS		(LUBBOCK_IRQ(5) + 1)
+
+#endif	// CONFIG_ARCH_LUBBOCK
+
+
+
diff -Nru a/include/asm-arm/arch-pxa/keyboard.h b/include/asm-arm/arch-pxa/keyboard.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/keyboard.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,29 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/keyboard.h
+ *
+ *  This file contains the architecture specific keyboard definitions
+ */
+
+#ifndef _PXA_KEYBOARD_H
+#define _PXA_KEYBOARD_H
+
+#include <linux/config.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+extern struct kbd_ops_struct *kbd_ops;
+
+#define kbd_disable_irq()	do { } while(0);
+#define kbd_enable_irq()	do { } while(0);
+
+extern int sa1111_kbd_init_hw(void);
+
+static inline void kbd_init_hw(void)
+{
+	if (machine_is_lubbock())
+		sa1111_kbd_init_hw();
+}
+
+
+#endif  /* _PXA_KEYBOARD_H */
+
diff -Nru a/include/asm-arm/arch-pxa/lubbock.h b/include/asm-arm/arch-pxa/lubbock.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/lubbock.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,112 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/lubbock.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define LUBBOCK_FPGA_PHYS	PXA_CS2_PHYS
+#define LUBBOCK_FPGA_VIRT	(0xf0000000)	/* phys 0x08000000 */
+#define LUBBOCK_ETH_BASE	(0xf1000000)	/* phys 0x0c000000 */
+#define LUBBOCK_SA1111_BASE	(0xf4000000)	/* phys 0x10000000 */
+
+#define LUB_P2V(x)		((x) - LUBBOCK_FPGA_PHYS + LUBBOCK_FPGA_VIRT)
+#define LUB_V2P(x)		((x) - LUBBOCK_FPGA_VIRT + LUBBOCK_FPGA_PHYS)
+
+#ifndef __ASSEMBLY__
+#  define __LUB_REG(x)		(*((volatile unsigned long *)LUB_P2V(x)))
+#else
+#  define __LUB_REG(x)		LUB_P2V(x)
+#endif
+
+/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+
+#define WHOAMI			0	// card ID's (see programmers manual)
+#define HEX_LED			0x10	// R/W access to 8 7 segment displays
+#define DISC_BLNK_LED		0x40 	// R/W [15-8] enables for hex leds, [7-0] discrete LEDs
+#define CONF_SWITCHES		0x50	// RO [1] flash wrt prot, [0] 0= boot from rom, 1= flash
+#define USER_SWITCHES		0x60	// RO [15-8] dip switches, [7-0] 2 hex encoding switches
+#define MISC_WR			0x80	// R/W various system controls -see manual
+#define MISC_RD			0x90	// RO various system status bits -see manual
+//#define LUB_IRQ_MASK_EN		0xC0    // R/W 0= mask, 1= enable of TS, codec, ethernet, USB, SA1111, and card det. irq's
+//#define LUB_IRQ_SET_CLR		0xD0	// R/W 1= set, 0 = clear IRQ's from TS, codec, etc...
+//#define LUB_GP			0x100	// R/W [15-0] 16 bits of general purpose I/o for hacking
+
+
+/* FPGA register physical addresses */
+#define _LUB_WHOAMI		(LUBBOCK_FPGA_PHYS + 0x000)
+#define _LUB_HEXLED		(LUBBOCK_FPGA_PHYS + 0x010)
+#define _LUB_DISC_BLNK_LED	(LUBBOCK_FPGA_PHYS + 0x040)
+#define _LUB_CONF_SWITCHES	(LUBBOCK_FPGA_PHYS + 0x050)
+#define _LUB_USER_SWITCHES	(LUBBOCK_FPGA_PHYS + 0x060)
+#define _LUB_MISC_WR		(LUBBOCK_FPGA_PHYS + 0x080)
+#define _LUB_MISC_RD		(LUBBOCK_FPGA_PHYS + 0x090)
+#define _LUB_IRQ_MASK_EN	(LUBBOCK_FPGA_PHYS + 0x0C0)
+#define _LUB_IRQ_SET_CLR	(LUBBOCK_FPGA_PHYS + 0x0D0)
+#define _LUB_GP			(LUBBOCK_FPGA_PHYS + 0x100)
+
+/* FPGA register virtual addresses */
+#define LUB_WHOAMI		__LUB_REG(_LUB_WHOAMI)
+#define LUB_HEXLED		__LUB_REG(_LUB_HEXLED)
+#define LUB_DISC_BLNK_LED	__LUB_REG(_LUB_DISC_BLNK_LED)
+#define LUB_CONF_SWITCHES	__LUB_REG(_LUB_CONF_SWITCHES)
+#define LUB_USER_SWITCHES	__LUB_REG(_LUB_USER_SWITCHES)
+#define LUB_MISC_WR		__LUB_REG(_LUB_MISC_WR)
+#define LUB_MISC_RD		__LUB_REG(_LUB_MISC_RD)
+#define LUB_IRQ_MASK_EN		__LUB_REG(_LUB_IRQ_MASK_EN)
+#define LUB_IRQ_SET_CLR		__LUB_REG(_LUB_IRQ_SET_CLR)
+#define LUB_GP			__LUB_REG(_LUB_GP)
+
+/* GPIOs */
+
+#define GPIO_LUBBOCK_IRQ	0
+#define IRQ_GPIO_LUBBOCK_IRQ	IRQ_GPIO0
+
+
+/*
+ * LED macros
+ */
+
+#define LEDS_BASE LUB_DISC_BLNK_LED
+
+// 8 discrete leds available for general use:
+
+#define D28	0x1
+#define D27	0x2
+#define D26	0x4
+#define D25	0x8
+#define D24	0x10
+#define D23	0x20
+#define D22	0x40
+#define D21	0x80
+
+/* Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays so
+*  be sure to not monkey with them here.
+*/
+
+#define HEARTBEAT_LED	D28
+#define SYS_BUSY_LED    D27
+#define HEXLEDS_BASE LUB_HEXLED
+
+#define HEARTBEAT_LED_ON  (LEDS_BASE &= ~HEARTBEAT_LED)
+#define HEARTBEAT_LED_OFF (LEDS_BASE |= HEARTBEAT_LED)
+#define SYS_BUSY_LED_OFF  (LEDS_BASE |= SYS_BUSY_LED)
+#define SYS_BUSY_LED_ON   (LEDS_BASE &= ~SYS_BUSY_LED)
+
+// use x = D26-D21 for these, please...
+#define DISCRETE_LED_ON(x) (LEDS_BASE &= ~(x))
+#define DISCRETE_LED_OFF(x) (LEDS_BASE |= (x))
+
+#ifndef __ASSEMBLY__
+
+//extern int hexled_val = 0;
+
+#endif
+
+#define BUMP_COUNTER (HEXLEDS_BASE = hexled_val++)
+#define DEC_COUNTER (HEXLEDS_BASE = hexled_val--)
diff -Nru a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/memory.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,59 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/memory.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE	(0xc0000000UL)
+#define TASK_SIZE_26	(0x04000000UL)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET	(0xc0000000UL)
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	(0xa0000000UL)
+#define PHYS_TO_NID(addr)	(0)
+
+/*
+ * physical vs virtual ram conversion
+ */
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *		address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *		to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __bus_to_virt__is_a_macro
+#define __virt_to_bus(x)	 __virt_to_phys(x)
+#define __bus_to_virt(x)	 __phys_to_virt(x)
+
+#endif
diff -Nru a/include/asm-arm/arch-pxa/param.h b/include/asm-arm/arch-pxa/param.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/param.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,3 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/param.h
+ */
diff -Nru a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/pxa-regs.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,1037 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/pxa-regs.h
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+// FIXME hack so that SA-1111.h will work [cb]
+
+#ifndef __ASSEMBLY__
+typedef unsigned short  Word16 ;
+typedef unsigned int    Word32 ;
+typedef Word32          Word ;
+typedef Word            Quad [4] ;
+typedef void            *Address ;
+typedef void            (*ExcpHndlr) (void) ;
+#endif
+
+/*
+ * PXA Chip selects
+ */
+
+#define PXA_CS0_PHYS	0x00000000
+#define PXA_CS1_PHYS	0x04000000
+#define PXA_CS2_PHYS	0x08000000
+#define PXA_CS3_PHYS	0x0C000000
+#define PXA_CS4_PHYS	0x10000000
+#define PXA_CS5_PHYS	0x14000000
+
+
+/*
+ * Personal Computer Memory Card International Association (PCMCIA) sockets
+ */
+
+#define PCMCIAPrtSp	0x04000000	/* PCMCIA Partition Space [byte]   */
+#define PCMCIASp	(4*PCMCIAPrtSp)	/* PCMCIA Space [byte]             */
+#define PCMCIAIOSp	PCMCIAPrtSp	/* PCMCIA I/O Space [byte]         */
+#define PCMCIAAttrSp	PCMCIAPrtSp	/* PCMCIA Attribute Space [byte]   */
+#define PCMCIAMemSp	PCMCIAPrtSp	/* PCMCIA Memory Space [byte]      */
+
+#define PCMCIA0Sp	PCMCIASp	/* PCMCIA 0 Space [byte]           */
+#define PCMCIA0IOSp	PCMCIAIOSp	/* PCMCIA 0 I/O Space [byte]       */
+#define PCMCIA0AttrSp	PCMCIAAttrSp	/* PCMCIA 0 Attribute Space [byte] */
+#define PCMCIA0MemSp	PCMCIAMemSp	/* PCMCIA 0 Memory Space [byte]    */
+
+#define PCMCIA1Sp	PCMCIASp	/* PCMCIA 1 Space [byte]           */
+#define PCMCIA1IOSp	PCMCIAIOSp	/* PCMCIA 1 I/O Space [byte]       */
+#define PCMCIA1AttrSp	PCMCIAAttrSp	/* PCMCIA 1 Attribute Space [byte] */
+#define PCMCIA1MemSp	PCMCIAMemSp	/* PCMCIA 1 Memory Space [byte]    */
+
+#define _PCMCIA(Nb)	        	/* PCMCIA [0..1]                   */ \
+                	(0x20000000 + (Nb)*PCMCIASp)
+#define _PCMCIAIO(Nb)	_PCMCIA (Nb)	/* PCMCIA I/O [0..1]               */
+#define _PCMCIAAttr(Nb)	        	/* PCMCIA Attribute [0..1]         */ \
+                	(_PCMCIA (Nb) + 2*PCMCIAPrtSp)
+#define _PCMCIAMem(Nb)	        	/* PCMCIA Memory [0..1]            */ \
+                	(_PCMCIA (Nb) + 3*PCMCIAPrtSp)
+
+#define _PCMCIA0	_PCMCIA (0)	/* PCMCIA 0                        */
+#define _PCMCIA0IO	_PCMCIAIO (0)	/* PCMCIA 0 I/O                    */
+#define _PCMCIA0Attr	_PCMCIAAttr (0)	/* PCMCIA 0 Attribute              */
+#define _PCMCIA0Mem	_PCMCIAMem (0)	/* PCMCIA 0 Memory                 */
+
+#define _PCMCIA1	_PCMCIA (1)	/* PCMCIA 1                        */
+#define _PCMCIA1IO	_PCMCIAIO (1)	/* PCMCIA 1 I/O                    */
+#define _PCMCIA1Attr	_PCMCIAAttr (1)	/* PCMCIA 1 Attribute              */
+#define _PCMCIA1Mem	_PCMCIAMem (1)	/* PCMCIA 1 Memory                 */
+
+
+
+/*
+ * DMA Controller
+ */
+
+#define DCSR0		__REG(0x40000000)  /* DMA Control / Status Register for Channel 0 */
+#define DCSR1		__REG(0x40000004)  /* DMA Control / Status Register for Channel 1 */
+#define DCSR2		__REG(0x40000008)  /* DMA Control / Status Register for Channel 2 */
+#define DCSR3		__REG(0x4000000c)  /* DMA Control / Status Register for Channel 3 */
+#define DCSR4		__REG(0x40000010)  /* DMA Control / Status Register for Channel 4 */
+#define DCSR5		__REG(0x40000014)  /* DMA Control / Status Register for Channel 5 */
+#define DCSR6		__REG(0x40000018)  /* DMA Control / Status Register for Channel 6 */
+#define DCSR7		__REG(0x4000001c)  /* DMA Control / Status Register for Channel 7 */
+#define DCSR8		__REG(0x40000020)  /* DMA Control / Status Register for Channel 8 */
+#define DCSR9		__REG(0x40000024)  /* DMA Control / Status Register for Channel 9 */
+#define DCSR10		__REG(0x40000028)  /* DMA Control / Status Register for Channel 10 */
+#define DCSR11		__REG(0x4000002c)  /* DMA Control / Status Register for Channel 11 */
+#define DCSR12		__REG(0x40000030)  /* DMA Control / Status Register for Channel 12 */
+#define DCSR13		__REG(0x40000034)  /* DMA Control / Status Register for Channel 13 */
+#define DCSR14		__REG(0x40000038)  /* DMA Control / Status Register for Channel 14 */
+#define DCSR15		__REG(0x4000003c)  /* DMA Control / Status Register for Channel 15 */
+
+#define DCSR(x)		__REG2(0x40000000, (x) << 2)
+
+#define DCSR_RUN	(1 << 31)	/* Run Bit (read / write) */
+#define DCSR_NODESC	(1 << 30)	/* No-Descriptor Fetch (read / write) */
+#define DCSR_STOPIRQEN	(1 << 29)	/* Stop Interrupt Enable (read / write) */
+#define DCSR_REQPEND	(1 << 8)	/* Request Pending (read-only) */
+#define DCSR_STOPSTATE	(1 << 3)	/* Stop State (read-only) */
+#define DCSR_ENDINTR	(1 << 2)	/* End Interrupt (read / write) */
+#define DCSR_STARTINTR	(1 << 1)	/* Start Interrupt (read / write) */
+#define DCSR_BUSERR	(1 << 0)	/* Bus Error Interrupt (read / write) */
+
+#define DINT		__REG(0x400000f0)  /* DMA Interrupt Register */
+
+#define DRCMR0		__REG(0x40000100)  /* Request to Channel Map Register for DREQ 0 */
+#define DRCMR1		__REG(0x40000104)  /* Request to Channel Map Register for DREQ 1 */
+#define DRCMR2		__REG(0x40000108)  /* Request to Channel Map Register for I2S receive Request */
+#define DRCMR3		__REG(0x4000010c)  /* Request to Channel Map Register for I2S transmit Request */
+#define DRCMR4		__REG(0x40000110)  /* Request to Channel Map Register for BTUART receive Request */
+#define DRCMR5		__REG(0x40000114)  /* Request to Channel Map Register for BTUART transmit Request. */
+#define DRCMR6		__REG(0x40000118)  /* Request to Channel Map Register for FFUART receive Request */
+#define DRCMR7		__REG(0x4000011c)  /* Request to Channel Map Register for FFUART transmit Request */
+#define DRCMR8		__REG(0x40000120)  /* Request to Channel Map Register for AC97 microphone Request */
+#define DRCMR9		__REG(0x40000124)  /* Request to Channel Map Register for AC97 modem receive Request */
+#define DRCMR10		__REG(0x40000128)  /* Request to Channel Map Register for AC97 modem transmit Request */
+#define DRCMR11		__REG(0x4000012c)  /* Request to Channel Map Register for AC97 audio receive Request */
+#define DRCMR12		__REG(0x40000130)  /* Request to Channel Map Register for AC97 audio transmit Request */
+#define DRCMR13		__REG(0x40000134)  /* Request to Channel Map Register for SSP receive Request */
+#define DRCMR14		__REG(0x40000138)  /* Request to Channel Map Register for SSP transmit Request */
+#define DRCMR15		__REG(0x4000013c)  /* Reserved */
+#define DRCMR16		__REG(0x40000140)  /* Reserved */
+#define DRCMR17		__REG(0x40000144)  /* Request to Channel Map Register for ICP receive Request */
+#define DRCMR18		__REG(0x40000148)  /* Request to Channel Map Register for ICP transmit Request */
+#define DRCMR19		__REG(0x4000014c)  /* Request to Channel Map Register for STUART receive Request */
+#define DRCMR20		__REG(0x40000150)  /* Request to Channel Map Register for STUART transmit Request */
+#define DRCMR21		__REG(0x40000154)  /* Request to Channel Map Register for MMC receive Request */
+#define DRCMR22		__REG(0x40000158)  /* Request to Channel Map Register for MMC transmit Request */
+#define DRCMR23		__REG(0x4000015c)  /* Reserved */
+#define DRCMR24		__REG(0x40000160)  /* Reserved */
+#define DRCMR25		__REG(0x40000164)  /* Request to Channel Map Register for USB endpoint 1 Request */
+#define DRCMR26		__REG(0x40000168)  /* Request to Channel Map Register for USB endpoint 2 Request */
+#define DRCMR27		__REG(0x4000016C)  /* Request to Channel Map Register for USB endpoint 3 Request */
+#define DRCMR28		__REG(0x40000170)  /* Request to Channel Map Register for USB endpoint 4 Request */
+#define DRCMR29		__REG(0x40000174)  /* Reserved */
+#define DRCMR30		__REG(0x40000178)  /* Request to Channel Map Register for USB endpoint 6 Request */
+#define DRCMR31		__REG(0x4000017C)  /* Request to Channel Map Register for USB endpoint 7 Request */
+#define DRCMR32		__REG(0x40000180)  /* Request to Channel Map Register for USB endpoint 8 Request */
+#define DRCMR33		__REG(0x40000184)  /* Request to Channel Map Register for USB endpoint 9 Request */
+#define DRCMR34		__REG(0x40000188)  /* Reserved */
+#define DRCMR35		__REG(0x4000018C)  /* Request to Channel Map Register for USB endpoint 11 Request */
+#define DRCMR36		__REG(0x40000190)  /* Request to Channel Map Register for USB endpoint 12 Request */
+#define DRCMR37		__REG(0x40000194)  /* Request to Channel Map Register for USB endpoint 13 Request */
+#define DRCMR38		__REG(0x40000198)  /* Request to Channel Map Register for USB endpoint 14 Request */
+#define DRCMR39		__REG(0x4000019C)  /* Reserved */
+
+#define DRCMRRXSADR	DRCMR2
+#define DRCMRTXSADR	DRCMR3
+#define DRCMRRXBTRBR	DRCMR4
+#define DRCMRTXBTTHR	DRCMR5
+#define DRCMRRXFFRBR	DRCMR6
+#define DRCMRTXFFTHR	DRCMR7
+#define DRCMRRXMCDR	DRCMR8
+#define DRCMRRXMODR	DRCMR9
+#define DRCMRTXMODR	DRCMR10
+#define DRCMRRXPCDR	DRCMR11
+#define DRCMRTXPCDR	DRCMR12
+#define DRCMRRXSSDR	DRCMR13
+#define DRCMRTXSSDR	DRCMR14
+#define DRCMRRXICDR	DRCMR17
+#define DRCMRTXICDR	DRCMR18
+#define DRCMRRXSTRBR	DRCMR19
+#define DRCMRTXSTTHR	DRCMR20
+#define DRCMRRXMMC	DRCMR21
+#define DRCMRTXMMC	DRCMR22
+
+#define DRCMR_MAPVLD	(1 << 7)	/* Map Valid (read / write) */
+#define DRCMR_CHLNUM	0x0f		/* mask for Channel Number (read / write) */
+
+#define DDADR0		__REG(0x40000200)  /* DMA Descriptor Address Register Channel 0 */
+#define DSADR0		__REG(0x40000204)  /* DMA Source Address Register Channel 0 */
+#define DTADR0		__REG(0x40000208)  /* DMA Target Address Register Channel 0 */
+#define DCMD0		__REG(0x4000020c)  /* DMA Command Address Register Channel 0 */
+#define DDADR1		__REG(0x40000210)  /* DMA Descriptor Address Register Channel 1 */
+#define DSADR1		__REG(0x40000214)  /* DMA Source Address Register Channel 1 */
+#define DTADR1		__REG(0x40000218)  /* DMA Target Address Register Channel 1 */
+#define DCMD1		__REG(0x4000021c)  /* DMA Command Address Register Channel 1 */
+#define DDADR2		__REG(0x40000220)  /* DMA Descriptor Address Register Channel 2 */
+#define DSADR2		__REG(0x40000224)  /* DMA Source Address Register Channel 2 */
+#define DTADR2		__REG(0x40000228)  /* DMA Target Address Register Channel 2 */
+#define DCMD2		__REG(0x4000022c)  /* DMA Command Address Register Channel 2 */
+#define DDADR3		__REG(0x40000230)  /* DMA Descriptor Address Register Channel 3 */
+#define DSADR3		__REG(0x40000234)  /* DMA Source Address Register Channel 3 */
+#define DTADR3		__REG(0x40000238)  /* DMA Target Address Register Channel 3 */
+#define DCMD3		__REG(0x4000023c)  /* DMA Command Address Register Channel 3 */
+#define DDADR4		__REG(0x40000240)  /* DMA Descriptor Address Register Channel 4 */
+#define DSADR4		__REG(0x40000244)  /* DMA Source Address Register Channel 4 */
+#define DTADR4		__REG(0x40000248)  /* DMA Target Address Register Channel 4 */
+#define DCMD4		__REG(0x4000024c)  /* DMA Command Address Register Channel 4 */
+#define DDADR5		__REG(0x40000250)  /* DMA Descriptor Address Register Channel 5 */
+#define DSADR5		__REG(0x40000254)  /* DMA Source Address Register Channel 5 */
+#define DTADR5		__REG(0x40000258)  /* DMA Target Address Register Channel 5 */
+#define DCMD5		__REG(0x4000025c)  /* DMA Command Address Register Channel 5 */
+#define DDADR6		__REG(0x40000260)  /* DMA Descriptor Address Register Channel 6 */
+#define DSADR6		__REG(0x40000264)  /* DMA Source Address Register Channel 6 */
+#define DTADR6		__REG(0x40000268)  /* DMA Target Address Register Channel 6 */
+#define DCMD6		__REG(0x4000026c)  /* DMA Command Address Register Channel 6 */
+#define DDADR7		__REG(0x40000270)  /* DMA Descriptor Address Register Channel 7 */
+#define DSADR7		__REG(0x40000274)  /* DMA Source Address Register Channel 7 */
+#define DTADR7		__REG(0x40000278)  /* DMA Target Address Register Channel 7 */
+#define DCMD7		__REG(0x4000027c)  /* DMA Command Address Register Channel 7 */
+#define DDADR8		__REG(0x40000280)  /* DMA Descriptor Address Register Channel 8 */
+#define DSADR8		__REG(0x40000284)  /* DMA Source Address Register Channel 8 */
+#define DTADR8		__REG(0x40000288)  /* DMA Target Address Register Channel 8 */
+#define DCMD8		__REG(0x4000028c)  /* DMA Command Address Register Channel 8 */
+#define DDADR9		__REG(0x40000290)  /* DMA Descriptor Address Register Channel 9 */
+#define DSADR9		__REG(0x40000294)  /* DMA Source Address Register Channel 9 */
+#define DTADR9		__REG(0x40000298)  /* DMA Target Address Register Channel 9 */
+#define DCMD9		__REG(0x4000029c)  /* DMA Command Address Register Channel 9 */
+#define DDADR10		__REG(0x400002a0)  /* DMA Descriptor Address Register Channel 10 */
+#define DSADR10		__REG(0x400002a4)  /* DMA Source Address Register Channel 10 */
+#define DTADR10		__REG(0x400002a8)  /* DMA Target Address Register Channel 10 */
+#define DCMD10		__REG(0x400002ac)  /* DMA Command Address Register Channel 10 */
+#define DDADR11		__REG(0x400002b0)  /* DMA Descriptor Address Register Channel 11 */
+#define DSADR11		__REG(0x400002b4)  /* DMA Source Address Register Channel 11 */
+#define DTADR11		__REG(0x400002b8)  /* DMA Target Address Register Channel 11 */
+#define DCMD11		__REG(0x400002bc)  /* DMA Command Address Register Channel 11 */
+#define DDADR12		__REG(0x400002c0)  /* DMA Descriptor Address Register Channel 12 */
+#define DSADR12		__REG(0x400002c4)  /* DMA Source Address Register Channel 12 */
+#define DTADR12		__REG(0x400002c8)  /* DMA Target Address Register Channel 12 */
+#define DCMD12		__REG(0x400002cc)  /* DMA Command Address Register Channel 12 */
+#define DDADR13		__REG(0x400002d0)  /* DMA Descriptor Address Register Channel 13 */
+#define DSADR13		__REG(0x400002d4)  /* DMA Source Address Register Channel 13 */
+#define DTADR13		__REG(0x400002d8)  /* DMA Target Address Register Channel 13 */
+#define DCMD13		__REG(0x400002dc)  /* DMA Command Address Register Channel 13 */
+#define DDADR14		__REG(0x400002e0)  /* DMA Descriptor Address Register Channel 14 */
+#define DSADR14		__REG(0x400002e4)  /* DMA Source Address Register Channel 14 */
+#define DTADR14		__REG(0x400002e8)  /* DMA Target Address Register Channel 14 */
+#define DCMD14		__REG(0x400002ec)  /* DMA Command Address Register Channel 14 */
+#define DDADR15		__REG(0x400002f0)  /* DMA Descriptor Address Register Channel 15 */
+#define DSADR15		__REG(0x400002f4)  /* DMA Source Address Register Channel 15 */
+#define DTADR15		__REG(0x400002f8)  /* DMA Target Address Register Channel 15 */
+#define DCMD15		__REG(0x400002fc)  /* DMA Command Address Register Channel 15 */
+
+#define DDADR(x)	__REG2(0x40000200, (x) << 4)
+#define DSADR(x)	__REG2(0x40000204, (x) << 4)
+#define DTADR(x)	__REG2(0x40000208, (x) << 4)
+#define DCMD(x)		__REG2(0x4000020c, (x) << 4)
+
+#define DDADR_DESCADDR	0xfffffff0	/* Address of next descriptor (mask) */
+#define DDADR_STOP	(1 << 0)	/* Stop (read / write) */
+
+#define DCMD_INCSRCADDR	(1 << 31)	/* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR	(1 << 30)	/* Target Address Increment Setting. */
+#define DCMD_FLOWSRC	(1 << 29)	/* Flow Control by the source. */
+#define DCMD_FLOWTRG	(1 << 28)	/* Flow Control by the target. */
+#define DCMD_STARTIRQEN	(1 << 22)	/* Start Interrupt Enable */
+#define DCMD_ENDIRQEN	(1 << 21)	/* End Interrupt Enable */
+#define DCMD_ENDIAN	(1 << 18)	/* Device Endian-ness. */
+#define DCMD_BURST8	(1 << 16)	/* 8 byte burst */
+#define DCMD_BURST16	(2 << 16)	/* 16 byte burst */
+#define DCMD_BURST32	(3 << 16)	/* 32 byte burst */
+#define DCMD_WIDTH1	(1 << 14)	/* 1 byte width */
+#define DCMD_WIDTH2	(2 << 14)	/* 2 byte width (HalfWord) */
+#define DCMD_WIDTH4	(3 << 14)	/* 4 byte width (Word) */
+#define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+
+/* default combinations */
+#define DCMD_RXPCDR	(DCMD_INCTRGADDR|DCMD_FLOWSRC|DCMD_BURST32|DCMD_WIDTH4)
+#define DCMD_TXPCDR	(DCMD_INCSRCADDR|DCMD_FLOWTRG|DCMD_BURST32|DCMD_WIDTH4)
+
+
+/*
+ * UARTs
+ */
+
+/* Full Function UART (FFUART) */
+#define FFUART		FFRBR
+#define FFRBR		__REG(0x40100000)  /* Receive Buffer Register (read only) */
+#define FFTHR		__REG(0x40100000)  /* Transmit Holding Register (write only) */
+#define FFIER		__REG(0x40100004)  /* Interrupt Enable Register (read/write) */
+#define FFIIR		__REG(0x40100008)  /* Interrupt ID Register (read only) */
+#define FFFCR		__REG(0x40100008)  /* FIFO Control Register (write only) */
+#define FFLCR		__REG(0x4010000C)  /* Line Control Register (read/write) */
+#define FFMCR		__REG(0x40100010)  /* Modem Control Register (read/write) */
+#define FFLSR		__REG(0x40100014)  /* Line Status Register (read only) */
+#define FFMSR		__REG(0x40100018)  /* Modem Status Register (read only) */
+#define FFSPR		__REG(0x4010001C)  /* Scratch Pad Register (read/write) */
+#define FFISR		__REG(0x40100020)  /* Infrared Selection Register (read/write) */
+#define FFDLL		__REG(0x40100000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define FFDLH		__REG(0x40100004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
+/* Bluetooth UART (BTUART) */
+#define BTUART		BTRBR
+#define BTRBR		__REG(0x40200000)  /* Receive Buffer Register (read only) */
+#define BTTHR		__REG(0x40200000)  /* Transmit Holding Register (write only) */
+#define BTIER		__REG(0x40200004)  /* Interrupt Enable Register (read/write) */
+#define BTIIR		__REG(0x40200008)  /* Interrupt ID Register (read only) */
+#define BTFCR		__REG(0x40200008)  /* FIFO Control Register (write only) */
+#define BTLCR		__REG(0x4020000C)  /* Line Control Register (read/write) */
+#define BTMCR		__REG(0x40200010)  /* Modem Control Register (read/write) */
+#define BTLSR		__REG(0x40200014)  /* Line Status Register (read only) */
+#define BTMSR		__REG(0x40200018)  /* Modem Status Register (read only) */
+#define BTSPR		__REG(0x4020001C)  /* Scratch Pad Register (read/write) */
+#define BTISR		__REG(0x40200020)  /* Infrared Selection Register (read/write) */
+#define BTDLL		__REG(0x40200000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define BTDLH		__REG(0x40200004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
+/* Standard UART (STUART) */
+#define STUART		STRBR
+#define STRBR		__REG(0x40700000)  /* Receive Buffer Register (read only) */
+#define STTHR		__REG(0x40700000)  /* Transmit Holding Register (write only) */
+#define STIER		__REG(0x40700004)  /* Interrupt Enable Register (read/write) */
+#define STIIR		__REG(0x40700008)  /* Interrupt ID Register (read only) */
+#define STFCR		__REG(0x40700008)  /* FIFO Control Register (write only) */
+#define STLCR		__REG(0x4070000C)  /* Line Control Register (read/write) */
+#define STMCR		__REG(0x40700010)  /* Modem Control Register (read/write) */
+#define STLSR		__REG(0x40700014)  /* Line Status Register (read only) */
+#define STMSR		__REG(0x40700018)  /* Reserved */
+#define STSPR		__REG(0x4070001C)  /* Scratch Pad Register (read/write) */
+#define STISR		__REG(0x40700020)  /* Infrared Selection Register (read/write) */
+#define STDLL		__REG(0x40700000)  /* Divisor Latch Low Register (DLAB = 1) (read/write) */
+#define STDLH		__REG(0x40700004)  /* Divisor Latch High Register (DLAB = 1) (read/write) */
+
+#define IER_DMAE	(1 << 7)	/* DMA Requests Enable */
+#define IER_UUE		(1 << 6)	/* UART Unit Enable */
+#define IER_NRZE	(1 << 5)	/* NRZ coding Enable */
+#define IER_RTIOE	(1 << 4)	/* Receiver Time Out Interrupt Enable */
+#define IER_MIE		(1 << 3)	/* Modem Interrupt Enable */
+#define IER_RLSE	(1 << 2)	/* Receiver Line Status Interrupt Enable */
+#define IER_TIE		(1 << 1)	/* Transmit Data request Interrupt Enable */
+#define IER_RAVIE	(1 << 0)	/* Receiver Data Available Interrupt Enable */
+
+#define IIR_FIFOES1	(1 << 7)	/* FIFO Mode Enable Status */
+#define IIR_FIFOES0	(1 << 6)	/* FIFO Mode Enable Status */
+#define IIR_TOD		(1 << 3)	/* Time Out Detected */
+#define IIR_IID2	(1 << 2)	/* Interrupt Source Encoded */
+#define IIR_IID1	(1 << 1)	/* Interrupt Source Encoded */
+#define IIR_IP		(1 << 0)	/* Interrupt Pending (active low) */
+
+#define FCR_ITL2	(1 << 7)	/* Interrupt Trigger Level */
+#define FCR_ITL1	(1 << 6)	/* Interrupt Trigger Level */
+#define FCR_RESETTF	(1 << 2)	/* Reset Transmitter FIFO */
+#define FCR_RESETRF	(1 << 1)	/* Reset Receiver FIFO */
+#define FCR_TRFIFOE	(1 << 0)	/* Transmit and Receive FIFO Enable */
+#define FCR_ITL_1	(0)
+#define FCR_ITL_8	(FCR_ITL1)
+#define FCR_ITL_16	(FCR_ITL2)
+#define FCR_ITL_32	(FCR_ITL2|FCR_ITL1)
+
+#define LCR_DLAB	(1 << 7)	/* Divisor Latch Access Bit */
+#define LCR_SB		(1 << 6)	/* Set Break */
+#define LCR_STKYP	(1 << 5)	/* Sticky Parity */
+#define LCR_EPS		(1 << 4)	/* Even Parity Select */
+#define LCR_PEN		(1 << 3)	/* Parity Enable */
+#define LCR_STB		(1 << 2)	/* Stop Bit */
+#define LCR_WLS1	(1 << 1)	/* Word Length Select */
+#define LCR_WLS0	(1 << 0)	/* Word Length Select */
+
+#define LSR_FIFOE	(1 << 7)	/* FIFO Error Status */
+#define LSR_TEMT	(1 << 6)	/* Transmitter Empty */
+#define LSR_TDRQ	(1 << 5)	/* Transmit Data Request */
+#define LSR_BI		(1 << 4)	/* Break Interrupt */
+#define LSR_FE		(1 << 3)	/* Framing Error */
+#define LSR_PE		(1 << 2)	/* Parity Error */
+#define LSR_OE		(1 << 1)	/* Overrun Error */
+#define LSR_DR		(1 << 0)	/* Data Ready */
+
+#define MCR_LOOP	(1 << 4)	*/
+#define MCR_OUT2	(1 << 3)	/* force MSR_DCD in loopback mode */
+#define MCR_OUT1	(1 << 2)	/* force MSR_RI in loopback mode */
+#define MCR_RTS		(1 << 1)	/* Request to Send */
+#define MCR_DTR		(1 << 0)	/* Data Terminal Ready */
+
+#define MSR_DCD		(1 << 7)	/* Data Carrier Detect */
+#define MSR_RI		(1 << 6)	/* Ring Indicator */
+#define MSR_DSR		(1 << 5)	/* Data Set Ready */
+#define MSR_CTS		(1 << 4)	/* Clear To Send */
+#define MSR_DDCD	(1 << 3)	/* Delta Data Carrier Detect */
+#define MSR_TERI	(1 << 2)	/* Trailing Edge Ring Indicator */
+#define MSR_DDSR	(1 << 1)	/* Delta Data Set Ready */
+#define MSR_DCTS	(1 << 0)	/* Delta Clear To Send */
+
+
+/*
+ * I2C registers
+ */
+
+#define IBMR		__REG(0x40301680)  /* I2C Bus Monitor Register - IBMR */
+#define IDBR		__REG(0x40301688)  /* I2C Data Buffer Register - IDBR */
+#define ICR		__REG(0x40301690)  /* I2C Control Register - ICR */
+#define ISR		__REG(0x40301698)  /* I2C Status Register - ISR */
+#define ISAR		__REG(0x403016A0)  /* I2C Slave Address Register - ISAR */
+
+
+/*
+ * Serial Audio Controller
+ */
+
+
+/* FIXME the audio defines collide w/ the SA1111 defines.  I don't like these
+ * short defines because there is too much chance of namespace collision */
+
+//#define SACR0		__REG(0x40400000)  /* Global Control Register */
+//#define SACR1		__REG(0x40400004)  /* Serial Audio I 2 S/MSB-Justified Control Register */
+//#define SASR0		__REG(0x4040000C)  /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
+//#define SAIMR		__REG(0x40400014)  /* Serial Audio Interrupt Mask Register */
+//#define SAICR		__REG(0x40400018)  /* Serial Audio Interrupt Clear Register */
+//#define SADIV		__REG(0x40400060)  /* Audio Clock Divider Register. */
+//#define SADR		__REG(0x40400080)  /* Serial Audio Data Register (TX and RX FIFO access Register). */
+
+
+/*
+ * AC97 Controller registers
+ */
+
+#define POCR		__REG(0x40500000)  /* PCM Out Control Register */
+#define POCR_FEIE	(1 << 3)	/* FIFO Error Interrupt Enable */
+
+#define PICR		__REG(0x40500004)  /* PCM In Control Register */
+#define PICR_FEIE	(1 << 3)	/* FIFO Error Interrupt Enable */
+
+#define MCCR		__REG(0x40500008)  /* Mic In Control Register */
+#define MCCR_FEIE	(1 << 3)	/* FIFO Error Interrupt Enable */
+
+#define GCR		__REG(0x4050000C)  /* Global Control Register */
+#define GCR_CDONE_IE	(1 << 19)	/* Command Done Interrupt Enable */
+#define GCR_SDONE_IE	(1 << 18)	/* Status Done Interrupt Enable */
+#define GCR_SECRDY_IEN	(1 << 9)	/* Secondary Ready Interrupt Enable */
+#define GCR_PRIRDY_IEN	(1 << 8)	/* Primary Ready Interrupt Enable */
+#define GCR_SECRES_IEN	(1 << 5)	/* Secondary Resume Interrupt Enable */
+#define GCR_PRIRES_IEN	(1 << 4)	/* Primary Resume Interrupt Enable */
+#define GCR_ACLINK_OFF	(1 << 3)	/* AC-link Shut Off */
+#define GCR_WARM_RST	(1 << 2)	/* AC97 Warm Reset */
+#define GCR_COLD_RST	(1 << 1)	/* AC'97 Cold Reset (0 = active) */
+#define GCR_GIE		(1 << 0)	/* Codec GPI Interrupt Enable */
+
+#define POSR		__REG(0x40500010)  /* PCM Out Status Register */
+#define POSR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define PISR		__REG(0x40500014)  /* PCM In Status Register */
+#define PISR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define MCSR		__REG(0x40500018)  /* Mic In Status Register */
+#define MCSR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define GSR		__REG(0x4050001C)  /* Global Status Register */
+#define GSR_CDONE	(1 << 19)	/* Command Done */
+#define GSR_SDONE	(1 << 18)	/* Status Done */
+#define GSR_RDCS	(1 << 15)	/* Read Completion Status */
+#define GSR_BIT3SLT12	(1 << 14)	/* Bit 3 of slot 12 */
+#define GSR_BIT2SLT12	(1 << 13)	/* Bit 2 of slot 12 */
+#define GSR_BIT1SLT12	(1 << 12)	/* Bit 1 of slot 12 */
+#define GSR_SECRES	(1 << 11)	/* Secondary Resume Interrupt */
+#define GSR_PRIRES	(1 << 10)	/* Primary Resume Interrupt */
+#define GSR_SCR		(1 << 9)	/* Secondary Codec Ready */
+#define GSR_PCR		(1 << 8)	/*  Primary Codec Ready */
+#define GSR_MINT	(1 << 7)	/* Mic In Interrupt */
+#define GSR_POINT	(1 << 6)	/* PCM Out Interrupt */
+#define GSR_PIINT	(1 << 5)	/* PCM In Interrupt */
+#define GSR_MOINT	(1 << 2)	/* Modem Out Interrupt */
+#define GSR_MIINT	(1 << 1)	/* Modem In Interrupt */
+#define GSR_GSCI	(1 << 0)	/* Codec GPI Status Change Interrupt */
+
+#define CAR		__REG(0x40500020)  /* CODEC Access Register */
+#define CAR_CAIP	(1 << 0)	/* Codec Access In Progress */
+
+#define PCDR		__REG(0x40500040)  /* PCM FIFO Data Register */
+#define MCDR		__REG(0x40500060)  /* Mic-in FIFO Data Register */
+
+#define MOCR		__REG(0x40500100)  /* Modem Out Control Register */
+#define MOCR_FEIE	(1 << 3)	/* FIFO Error */
+
+#define MICR		__REG(0x40500108)  /* Modem In Control Register */
+#define MICR_FEIE	(1 << 3)	/* FIFO Error */
+
+#define MOSR		__REG(0x40500110)  /* Modem Out Status Register */
+#define MOSR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define MISR		__REG(0x40500118)  /* Modem In Status Register */
+#define MISR_FIFOE	(1 << 4)	/* FIFO error */
+
+#define MODR		__REG(0x40500140)  /* Modem FIFO Data Register */
+
+#define PAC_REG_BASE	__REG(0x40500200)  /* Primary Audio Codec */
+#define SAC_REG_BASE	__REG(0x40500300)  /* Secondary Audio Codec */
+#define PMC_REG_BASE	__REG(0x40500400)  /* Primary Modem Codec */
+#define SMC_REG_BASE	__REG(0x40500500)  /* Secondary Modem Codec */
+
+
+/*
+ * USB Device Controller
+ */
+
+#define UDCCR		__REG(0x40600000)  /* UDC Control Register */
+#define UDCCS0		__REG(0x40600010)  /* UDC Endpoint 0 Control/Status Register */
+#define UDCCS1		__REG(0x40600014)  /* UDC Endpoint 1 (IN) Control/Status Register */
+#define UDCCS2		__REG(0x40600018)  /* UDC Endpoint 2 (OUT) Control/Status Register */
+#define UDCCS3		__REG(0x4060001C)  /* UDC Endpoint 3 (IN) Control/Status Register */
+#define UDCCS4		__REG(0x40600020)  /* UDC Endpoint 4 (OUT) Control/Status Register */
+#define UDCCS5		__REG(0x40600024)  /* UDC Endpoint 5 (Interrupt) Control/Status Register */
+#define UDCCS6		__REG(0x40600028)  /* UDC Endpoint 6 (IN) Control/Status Register */
+#define UDCCS7		__REG(0x4060002C)  /* UDC Endpoint 7 (OUT) Control/Status Register */
+#define UDCCS8		__REG(0x40600030)  /* UDC Endpoint 8 (IN) Control/Status Register */
+#define UDCCS9		__REG(0x40600034)  /* UDC Endpoint 9 (OUT) Control/Status Register */
+#define UDCCS10		__REG(0x40600038)  /* UDC Endpoint 10 (Interrupt) Control/Status Register */
+#define UDCCS11		__REG(0x4060003C)  /* UDC Endpoint 11 (IN) Control/Status Register */
+#define UDCCS12		__REG(0x40600040)  /* UDC Endpoint 12 (OUT) Control/Status Register */
+#define UDCCS13		__REG(0x40600044)  /* UDC Endpoint 13 (IN) Control/Status Register */
+#define UDCCS14		__REG(0x40600048)  /* UDC Endpoint 14 (OUT) Control/Status Register */
+#define UDCCS15		__REG(0x4060004C)  /* UDC Endpoint 15 (Interrupt) Control/Status Register */
+#define UFNRH		__REG(0x40600060)  /* UDC Frame Number Register High */
+#define UFNRL		__REG(0x40600064)  /* UDC Frame Number Register Low */
+#define UBCR2		__REG(0x40600068)  /* UDC Byte Count Reg 2 */
+#define UBCR4		__REG(0x4060006c)  /* UDC Byte Count Reg 4 */
+#define UBCR7		__REG(0x40600070)  /* UDC Byte Count Reg 7 */
+#define UBCR9		__REG(0x40600074)  /* UDC Byte Count Reg 9 */
+#define UBCR12		__REG(0x40600078)  /* UDC Byte Count Reg 12 */
+#define UBCR14		__REG(0x4060007c)  /* UDC Byte Count Reg 14 */
+#define UDDR0		__REG(0x40600080)  /* UDC Endpoint 0 Data Register */
+#define UDDR1		__REG(0x40600100)  /* UDC Endpoint 1 Data Register */
+#define UDDR2		__REG(0x40600180)  /* UDC Endpoint 2 Data Register */
+#define UDDR3		__REG(0x40600200)  /* UDC Endpoint 3 Data Register */
+#define UDDR4		__REG(0x40600400)  /* UDC Endpoint 4 Data Register */
+#define UDDR5		__REG(0x406000A0)  /* UDC Endpoint 5 Data Register */
+#define UDDR6		__REG(0x40600600)  /* UDC Endpoint 6 Data Register */
+#define UDDR7		__REG(0x40600680)  /* UDC Endpoint 7 Data Register */
+#define UDDR8		__REG(0x40600700)  /* UDC Endpoint 8 Data Register */
+#define UDDR9		__REG(0x40600900)  /* UDC Endpoint 9 Data Register */
+#define UDDR10		__REG(0x406000C0)  /* UDC Endpoint 10 Data Register */
+#define UDDR11		__REG(0x40600B00)  /* UDC Endpoint 11 Data Register */
+#define UDDR12		__REG(0x40600B80)  /* UDC Endpoint 12 Data Register */
+#define UDDR13		__REG(0x40600C00)  /* UDC Endpoint 13 Data Register */
+#define UDDR14		__REG(0x40600E00)  /* UDC Endpoint 14 Data Register */
+#define UDDR15		__REG(0x406000E0)  /* UDC Endpoint 15 Data Register */
+#define UICR0		__REG(0x40600050)  /* UDC Interrupt Control Register 0 */
+#define UICR1		__REG(0x40600054)  /* UDC Interrupt Control Register 1 */
+#define USIR0		__REG(0x40600058)  /* UDC Status Interrupt Register 0 */
+#define USIR1		__REG(0x4060005C)  /* UDC Status Interrupt Register 1 */
+
+
+/*
+ * Fast Infrared Communication Port
+ */
+
+#define ICCR0		__REG(0x40800000)  /* ICP Control Register 0 */
+#define ICCR1		__REG(0x40800004)  /* ICP Control Register 1 */
+#define ICCR2		__REG(0x40800008)  /* ICP Control Register 2 */
+#define ICDR		__REG(0x4080000c)  /* ICP Data Register */
+#define ICSR0		__REG(0x40800014)  /* ICP Status Register 0 */
+#define ICSR1		__REG(0x40800018)  /* ICP Status Register 1 */
+
+
+/*
+ * Real Time Clock
+ */
+
+#define RCNR		__REG(0x40900000)  /* RTC Count Register */
+#define RTAR		__REG(0x40900004)  /* RTC Alarm Register */
+#define RTSR		__REG(0x40900008)  /* RTC Status Register */
+#define RTTR		__REG(0x4090000C)  /* RTC Timer Trim Register */
+
+#define RTSR_HZE	(1 << 3)	/* HZ interrupt enable */
+#define RTSR_ALE	(1 << 2)	/* RTC alarm interrupt enable */
+#define RTSR_HZ		(1 << 1)	/* HZ rising-edge detected */
+#define RTSR_AL		(1 << 0)	/* RTC alarm detected */
+
+
+/*
+ * OS Timer & Match Registers
+ */
+
+#define OSMR0		__REG(0x40A00000)  /* */
+#define OSMR1		__REG(0x40A00004)  /* */
+#define OSMR2		__REG(0x40A00008)  /* */
+#define OSMR3		__REG(0x40A0000C)  /* */
+#define OSCR		__REG(0x40A00010)  /* OS Timer Counter Register */
+#define OSSR		__REG(0x40A00014)  /* OS Timer Status Register */
+#define OWER		__REG(0x40A00018)  /* OS Timer Watchdog Enable Register */
+#define OIER		__REG(0x40A0001C)  /* OS Timer Interrupt Enable Register */
+
+#define OSSR_M3		(1 << 3)	/* Match status channel 3 */
+#define OSSR_M2		(1 << 2)	/* Match status channel 2 */
+#define OSSR_M1		(1 << 1)	/* Match status channel 1 */
+#define OSSR_M0		(1 << 0)	/* Match status channel 0 */
+
+#define OWER_WME	(1 << 0)	/* Watchdog Match Enable */
+
+#define OIER_E3		(1 << 3)	/* Interrupt enable channel 3 */
+#define OIER_E2		(1 << 2)	/* Interrupt enable channel 2 */
+#define OIER_E1		(1 << 1)	/* Interrupt enable channel 1 */
+#define OIER_E0		(1 << 0)	/* Interrupt enable channel 0 */
+
+
+/*
+ * Pulse Width Modulator
+ */
+
+#define PWM_CTRL0	__REG(0x40B00000)  /* PWM 0 Control Register */
+#define PWM_PWDUTY0	__REG(0x40B00004)  /* PWM 0 Duty Cycle Register */
+#define PWM_PERVAL0	__REG(0x40B00008)  /* PWM 0 Period Control Register */
+
+#define PWM_CTRL1	__REG(0x40C00000)  /* PWM 1Control Register */
+#define PWM_PWDUTY1	__REG(0x40C00004)  /* PWM 1 Duty Cycle Register */
+#define PWM_PERVAL1	__REG(0x40C00008)  /* PWM 1 Period Control Register */
+
+
+/*
+ * Interrupt Controller
+ */
+
+#define ICIP		__REG(0x40D00000)  /* Interrupt Controller IRQ Pending Register */
+#define ICMR		__REG(0x40D00004)  /* Interrupt Controller Mask Register */
+#define ICLR		__REG(0x40D00008)  /* Interrupt Controller Level Register */
+#define ICFP		__REG(0x40D0000C)  /* Interrupt Controller FIQ Pending Register */
+#define ICPR		__REG(0x40D00010)  /* Interrupt Controller Pending Register */
+#define ICCR		__REG(0x40D00014)  /* Interrupt Controller Control Register */
+
+
+/*
+ * General Purpose I/O
+ */
+
+#define GPLR0		__REG(0x40E00000)  /* GPIO Pin-Level Register GPIO<31:0> */
+#define GPLR1		__REG(0x40E00004)  /* GPIO Pin-Level Register GPIO<63:32> */
+#define GPLR2		__REG(0x40E00008)  /* GPIO Pin-Level Register GPIO<80:64> */
+
+#define GPDR0		__REG(0x40E0000C)  /* GPIO Pin Direction Register GPIO<31:0> */
+#define GPDR1		__REG(0x40E00010)  /* GPIO Pin Direction Register GPIO<63:32> */
+#define GPDR2		__REG(0x40E00014)  /* GPIO Pin Direction Register GPIO<80:64> */
+
+#define GPSR0		__REG(0x40E00018)  /* GPIO Pin Output Set Register GPIO<31:0> */
+#define GPSR1		__REG(0x40E0001C)  /* GPIO Pin Output Set Register GPIO<63:32> */
+#define GPSR2		__REG(0x40E00020)  /* GPIO Pin Output Set Register GPIO<80:64> */
+
+#define GPCR0		__REG(0x40E00024)  /* GPIO Pin Output Clear Register GPIO<31:0> */
+#define GPCR1		__REG(0x40E00028)  /* GPIO Pin Output Clear Register GPIO <63:32> */
+#define GPCR2		__REG(0x40E0002C)  /* GPIO Pin Output Clear Register GPIO <80:64> */
+
+#define GRER0		__REG(0x40E00030)  /* GPIO Rising-Edge Detect Register GPIO<31:0> */
+#define GRER1		__REG(0x40E00034)  /* GPIO Rising-Edge Detect Register GPIO<63:32> */
+#define GRER2		__REG(0x40E00038)  /* GPIO Rising-Edge Detect Register GPIO<80:64> */
+
+#define GFER0		__REG(0x40E0003C)  /* GPIO Falling-Edge Detect Register GPIO<31:0> */
+#define GFER1		__REG(0x40E00040)  /* GPIO Falling-Edge Detect Register GPIO<63:32> */
+#define GFER2		__REG(0x40E00044)  /* GPIO Falling-Edge Detect Register GPIO<80:64> */
+
+#define GEDR0		__REG(0x40E00048)  /* GPIO Edge Detect Status Register GPIO<31:0> */
+#define GEDR1		__REG(0x40E0004C)  /* GPIO Edge Detect Status Register GPIO<63:32> */
+#define GEDR2		__REG(0x40E00050)  /* GPIO Edge Detect Status Register GPIO<80:64> */
+
+#define GAFR0_L		__REG(0x40E00054)  /* GPIO Alternate Function Select Register GPIO<15:0> */
+#define GAFR0_U		__REG(0x40E00058)  /* GPIO Alternate Function Select Register GPIO<31:16> */
+#define GAFR1_L		__REG(0x40E0005C)  /* GPIO Alternate Function Select Register GPIO<47:32> */
+#define GAFR1_U		__REG(0x40E00060)  /* GPIO Alternate Function Select Register GPIO<63:48> */
+#define GAFR2_L		__REG(0x40E00064)  /* GPIO Alternate Function Select Register GPIO<79:64> */
+#define GAFR2_U		__REG(0x40E00068)  /* GPIO Alternate Function Select Register GPIO 80 */
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+#define GPLR(x)		__REG2(0x40E00000, ((x) & 0x60) >> 3)
+#define GPDR(x)		__REG2(0x40E0000C, ((x) & 0x60) >> 3)
+#define GPSR(x)		__REG2(0x40E00018, ((x) & 0x60) >> 3)
+#define GPCR(x)		__REG2(0x40E00024, ((x) & 0x60) >> 3)
+#define GRER(x)		__REG2(0x40E00030, ((x) & 0x60) >> 3)
+#define GFER(x)		__REG2(0x40E0003C, ((x) & 0x60) >> 3)
+#define GEDR(x)		__REG2(0x40E00048, ((x) & 0x60) >> 3)
+#define GAFR(x)		__REG2(0x40E00054, ((x) & 0x70) >> 2)
+
+/* GPIO alternate function assignments */
+
+#define GPIO1_RST		1	/* reset */
+#define GPIO6_MMCCLK		6	/* MMC Clock */
+#define GPIO8_48MHz		7	/* 48 MHz clock output */
+#define GPIO8_MMCCS0		8	/* MMC Chip Select 0 */
+#define GPIO9_MMCCS1		9	/* MMC Chip Select 1 */
+#define GPIO10_RTCCLK		10	/* real time clock (1 Hz) */
+#define GPIO11_3_6MHz		11	/* 3.6 MHz oscillator out */
+#define GPIO12_32KHz		12	/* 32 kHz out */
+#define GPIO13_MBGNT		13	/* memory controller grant */
+#define GPIO14_MBREQ		14	/* alternate bus master request */
+#define GPIO15_nCS_1		15	/* chip select 1 */
+#define GPIO16_PWM0		16	/* PWM0 output */
+#define GPIO17_PWM1		17	/* PWM1 output */
+#define GPIO18_RDY		18	/* Ext. Bus Ready */
+#define GPIO19_DREQ1		19	/* External DMA Request */
+#define GPIO20_DREQ0		20	/* External DMA Request */
+#define GPIO23_SCLK		23	/* SSP clock */
+#define GPIO24_SFRM		24	/* SSP Frame */
+#define GPIO25_STXD		25	/* SSP transmit */
+#define GPIO26_SRXD		26	/* SSP receive */
+#define GPIO27_SEXTCLK		27	/* SSP ext_clk */
+#define GPIO28_BITCLK		28	/* AC97/I2S bit_clk */
+#define GPIO29_SDATA_IN		29	/* AC97 Sdata_in0 / I2S Sdata_in */
+#define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
+#define GPIO31_SYNC		31	/* AC97/I2S sync */
+#define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
+#define GPIO33_nCS_5		33	/* chip select 5 */
+#define GPIO34_FFRXD		34	/* FFUART receive */
+#define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
+#define GPIO35_FFCTS		35	/* FFUART Clear to send */
+#define GPIO36_FFDCD		36	/* FFUART Data carrier detect */
+#define GPIO37_FFDSR		37	/* FFUART data set ready */
+#define GPIO38_FFRI		38	/* FFUART Ring Indicator */
+#define GPIO39_MMCCS1		39	/* MMC Chip Select 1 */
+#define GPIO39_FFTXD		39	/* FFUART transmit data */
+#define GPIO40_FFDTR		40	/* FFUART data terminal Ready */
+#define GPIO41_FFRTS		41	/* FFUART request to send */
+#define GPIO42_BTRXD		42	/* BTUART receive data */
+#define GPIO43_BTTXD		43	/* BTUART transmit data */
+#define GPIO44_BTCTS		44	/* BTUART clear to send */
+#define GPIO45_BTRTS		45	/* BTUART request to send */
+#define GPIO46_ICPRXD		46	/* ICP receive data */
+#define GPIO46_STRXD		46	/* STD_UART receive data */
+#define GPIO47_ICPTXD		47	/* ICP transmit data */
+#define GPIO47_STTXD		47	/* STD_UART transmit data */
+#define GPIO48_nPOE		48	/* Output Enable for Card Space */
+#define GPIO49_nPWE		49	/* Write Enable for Card Space */
+#define GPIO50_nPIOR		50	/* I/O Read for Card Space */
+#define GPIO51_nPIOW		51	/* I/O Write for Card Space */
+#define GPIO52_nPCE_1		52	/* Card Enable for Card Space */
+#define GPIO53_nPCE_2		53	/* Card Enable for Card Space */
+#define GPIO53_MMCCLK		53	/* MMC Clock */
+#define GPIO54_MMCCLK		54	/* MMC Clock */
+#define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
+#define GPIO55_nPREG		55	/* Card Address bit 26 */
+#define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
+#define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
+#define GPIO58_LDD_0		58	/* LCD data pin 0 */
+#define GPIO59_LDD_1		59	/* LCD data pin 1 */
+#define GPIO60_LDD_2		60	/* LCD data pin 2 */
+#define GPIO61_LDD_3		61	/* LCD data pin 3 */
+#define GPIO62_LDD_4		62	/* LCD data pin 4 */
+#define GPIO63_LDD_5		63	/* LCD data pin 5 */
+#define GPIO64_LDD_6		64	/* LCD data pin 6 */
+#define GPIO65_LDD_7		65	/* LCD data pin 7 */
+#define GPIO66_LDD_8		66	/* LCD data pin 8 */
+#define GPIO66_MBREQ		66	/* alternate bus master req */
+#define GPIO67_LDD_9		67	/* LCD data pin 9 */
+#define GPIO67_MMCCS0		67	/* MMC Chip Select 0 */
+#define GPIO68_LDD_10		68	/* LCD data pin 10 */
+#define GPIO68_MMCCS1		68	/* MMC Chip Select 1 */
+#define GPIO69_LDD_11		69	/* LCD data pin 11 */
+#define GPIO69_MMCCLK		69	/* MMC_CLK */
+#define GPIO70_LDD_12		70	/* LCD data pin 12 */
+#define GPIO70_RTCCLK		70	/* Real Time clock (1 Hz) */
+#define GPIO71_LDD_13		71	/* LCD data pin 13 */
+#define GPIO71_3_6MHz		71	/* 3.6 MHz Oscillator clock */
+#define GPIO72_LDD_14		72	/* LCD data pin 14 */
+#define GPIO72_32kHz		72	/* 32 kHz clock */
+#define GPIO73_LDD_15		73	/* LCD data pin 15 */
+#define GPIO73_MBGNT		73	/* Memory controller grant */
+#define GPIO74_LCD_FCLK		74	/* LCD Frame clock */
+#define GPIO75_LCD_LCLK		75	/* LCD line clock */
+#define GPIO76_LCD_PCLK		76	/* LCD Pixel clock */
+#define GPIO77_LCD_ACBIAS	77	/* LCD AC Bias */
+#define GPIO78_nCS_2		78	/* chip select 2 */
+#define GPIO79_nCS_3		79	/* chip select 3 */
+#define GPIO80_nCS_4		80	/* chip select 4 */
+
+/* GPIO alternate function mode & direction */
+
+#define GPIO_IN			0x000
+#define GPIO_OUT		0x080
+#define GPIO_ALT_FN_1_IN	0x100
+#define GPIO_ALT_FN_1_OUT	0x180
+#define GPIO_ALT_FN_2_IN	0x200
+#define GPIO_ALT_FN_2_OUT	0x280
+#define GPIO_ALT_FN_3_IN	0x300
+#define GPIO_ALT_FN_3_OUT	0x380
+#define GPIO_MD_MASK_NR		0x07f
+#define GPIO_MD_MASK_DIR	0x080
+#define GPIO_MD_MASK_FN		0x300
+
+#define GPIO1_RTS_MD		( 1 | GPIO_ALT_FN_1_IN)
+#define GPIO6_MMCCLK_MD		( 6 | GPIO_ALT_FN_1_OUT)
+#define GPIO8_48MHz_MD		( 8 | GPIO_ALT_FN_1_OUT)
+#define GPIO8_MMCCS0_MD		( 8 | GPIO_ALT_FN_1_OUT)
+#define GPIO9_MMCCS1_MD		( 9 | GPIO_ALT_FN_1_OUT)
+#define GPIO10_RTCCLK_MD	(10 | GPIO_ALT_FN_1_OUT)
+#define GPIO11_3_6MHz_MD	(11 | GPIO_ALT_FN_1_OUT)
+#define GPIO12_32KHz_MD		(12 | GPIO_ALT_FN_1_OUT)
+#define GPIO13_MBGNT_MD		(13 | GPIO_ALT_FN_2_OUT)
+#define GPIO14_MBREQ_MD		(14 | GPIO_ALT_FN_1_IN)
+#define GPIO15_nCS_1_MD		(15 | GPIO_ALT_FN_2_OUT)
+#define GPIO16_PWM0_MD		(16 | GPIO_ALT_FN_2_OUT)
+#define GPIO17_PWM1_MD		(17 | GPIO_ALT_FN_2_OUT)
+#define GPIO18_RDY_MD		(18 | GPIO_ALT_FN_1_IN)
+#define GPIO19_DREQ1_MD		(19 | GPIO_ALT_FN_1_IN)
+#define GPIO20_DREQ0_MD		(20 | GPIO_ALT_FN_1_IN)
+#define GPIO23_SCLK_md		(23 | GPIO_ALT_FN_2_OUT)
+#define GPIO24_SFRM_MD		(24 | GPIO_ALT_FN_2_OUT)
+#define GPIO25_STXD_MD		(25 | GPIO_ALT_FN_2_OUT)
+#define GPIO26_SRXD_MD		(26 | GPIO_ALT_FN_1_IN)
+#define GPIO27_SEXTCLK_MD	(27 | GPIO_ALT_FN_1_IN)
+#define GPIO28_BITCLK_AC97_MD	(28 | GPIO_ALT_FN_1_IN)
+#define GPIO28_BITCLK_I2S_MD	(28 | GPIO_ALT_FN_2_IN)
+#define GPIO29_SDATA_IN_AC97_MD	(29 | GPIO_ALT_FN_1_IN)
+#define GPIO29_SDATA_IN_I2S_MD	(29 | GPIO_ALT_FN_2_IN)
+#define GPIO30_SDATA_OUT_AC97_MD	(30 | GPIO_ALT_FN_2_OUT)
+#define GPIO30_SDATA_OUT_I2S_MD	(30 | GPIO_ALT_FN_1_OUT)
+#define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
+#define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
+#define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
+#define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
+#define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
+#define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
+#define GPIO35_FFCTS_MD		(35 | GPIO_ALT_FN_1_IN)
+#define GPIO36_FFDCD_MD		(36 | GPIO_ALT_FN_1_IN)
+#define GPIO37_FFDSR_MD		(37 | GPIO_ALT_FN_1_IN)
+#define GPIO38_FFRI_MD		(38 | GPIO_ALT_FN_1_IN)
+#define GPIO39_MMCCS1_MD	(39 | GPIO_ALT_FN_1_OUT)
+#define GPIO39_FFTXD_MD		(39 | GPIO_ALT_FN_2_OUT)
+#define GPIO40_FFDTR_MD		(40 | GPIO_ALT_FN_2_OUT)
+#define GPIO41_FFRTS_MD		(41 | GPIO_ALT_FN_2_OUT)
+#define GPIO42_BTRXD_MD		(42 | GPIO_ALT_FN_1_IN)
+#define GPIO43_BTTXD_MD		(43 | GPIO_ALT_FN_2_OUT)
+#define GPIO44_BTCTS_MD		(44 | GPIO_ALT_FN_1_IN)
+#define GPIO45_BTRTS_MD		(45 | GPIO_ALT_FN_2_OUT)
+#define GPIO46_ICPRXD_MD	(46 | GPIO_ALT_FN_1_IN)
+#define GPIO46_STRXD_MD		(46 | GPIO_ALT_FN_2_IN)
+#define GPIO47_ICPTXD_MD	(47 | GPIO_ALT_FN_2_OUT)
+#define GPIO47_STTXD_MD		(47 | GPIO_ALT_FN_1_OUT)
+#define GPIO48_nPOE_MD		(48 | GPIO_ALT_FN_2_OUT)
+#define GPIO49_nPWE_MD		(49 | GPIO_ALT_FN_2_OUT)
+#define GPIO50_nPIOR_MD		(50 | GPIO_ALT_FN_2_OUT)
+#define GPIO51_nPIOW_MD		(51 | GPIO_ALT_FN_2_OUT)
+#define GPIO52_nPCE_1_MD	(52 | GPIO_ALT_FN_2_OUT)
+#define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
+#define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
+#define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
+#define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
+#define GPIO57_nIOIS16_MD	(57 | GPIO_ALT_FN_1_IN)
+#define GPIO58_LDD_0_MD		(58 | GPIO_ALT_FN_2_OUT)
+#define GPIO59_LDD_1_MD		(59 | GPIO_ALT_FN_2_OUT)
+#define GPIO60_LDD_2_MD		(60 | GPIO_ALT_FN_2_OUT)
+#define GPIO61_LDD_3_MD		(61 | GPIO_ALT_FN_2_OUT)
+#define GPIO62_LDD_4_MD		(62 | GPIO_ALT_FN_2_OUT)
+#define GPIO63_LDD_5_MD		(63 | GPIO_ALT_FN_2_OUT)
+#define GPIO64_LDD_6_MD		(64 | GPIO_ALT_FN_2_OUT)
+#define GPIO65_LDD_7_MD		(65 | GPIO_ALT_FN_2_OUT)
+#define GPIO66_LDD_8_MD		(66 | GPIO_ALT_FN_2_OUT)
+#define GPIO66_MBREQ_MD		(66 | GPIO_ALT_FN_1_IN)
+#define GPIO67_LDD_9_MD		(67 | GPIO_ALT_FN_2_OUT)
+#define GPIO67_MMCCS0_MD	(67 | GPIO_ALT_FN_1_OUT)
+#define GPIO68_LDD_10_MD	(68 | GPIO_ALT_FN_2_OUT)
+#define GPIO68_MMCCS1_MD	(68 | GPIO_ALT_FN_1_OUT)
+#define GPIO69_LDD_11_MD	(69 | GPIO_ALT_FN_2_OUT)
+#define GPIO69_MMCCLK_MD	(69 | GPIO_ALT_FN_1_OUT)
+#define GPIO70_LDD_12_MD	(70 | GPIO_ALT_FN_2_OUT)
+#define GPIO70_RTCCLK_MD	(70 | GPIO_ALT_FN_1_OUT)
+#define GPIO71_LDD_13_MD	(71 | GPIO_ALT_FN_2_OUT)
+#define GPIO71_3_6MHz_MD	(71 | GPIO_ALT_FN_1_OUT)
+#define GPIO72_LDD_14_MD	(72 | GPIO_ALT_FN_2_OUT)
+#define GPIO72_32kHz_MD		(72 | GPIO_ALT_FN_1_OUT)
+#define GPIO73_LDD_15_MD	(73 | GPIO_ALT_FN_2_OUT)
+#define GPIO73_MBGNT_MD		(73 | GPIO_ALT_FN_1_OUT)
+#define GPIO74_LCD_FCLK_MD	(74 | GPIO_ALT_FN_2_OUT)
+#define GPIO75_LCD_LCLK_MD	(75 | GPIO_ALT_FN_2_OUT)
+#define GPIO76_LCD_PCLK_MD	(76 | GPIO_ALT_FN_2_OUT)
+#define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
+#define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
+#define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
+#define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
+
+
+/*
+ * Power Manager
+ */
+
+#define PMCR		__REG(0x40F00000)  /* Power Manager Control Register */
+#define PSSR		__REG(0x40F00004)  /* Power Manager Sleep Status Register */
+#define PSPR		__REG(0x40F00008)  /* Power Manager Scratch Pad Register */
+#define PWER		__REG(0x40F0000C)  /* Power Manager Wake-up Enable Register */
+#define PRER		__REG(0x40F00010)  /* Power Manager GPIO Rising-Edge Detect Enable Register */
+#define PFER		__REG(0x40F00014)  /* Power Manager GPIO Falling-Edge Detect Enable Register */
+#define PEDR		__REG(0x40F00018)  /* Power Manager GPIO Edge Detect Status Register */
+#define PCFR		__REG(0x40F0001C)  /* Power Manager General Configuration Register */
+#define PGSR0		__REG(0x40F00020)  /* Power Manager GPIO Sleep State Register for GP[31-0] */
+#define PGSR1		__REG(0x40F00024)  /* Power Manager GPIO Sleep State Register for GP[63-32] */
+#define PGSR2		__REG(0x40F00028)  /* Power Manager GPIO Sleep State Register for GP[84-64] */
+#define RCSR		__REG(0x40F00030)  /* Reset Controller Status Register */
+
+
+/*
+ * SSP Serial Port Registers
+ */
+
+#define SSCR0		__REG(0x41000000)  /* SSP Control Register 0 */
+#define SSCR1		__REG(0x41000004)  /* SSP Control Register 1 */
+#define SSSR		__REG(0x41000008)  /* SSP Status Register */
+#define SSITR		__REG(0x4100000C)  /* SSP Interrupt Test Register */
+#define SSDR		__REG(0x41000010)  /* (Write / Read) SSP Data Write Register/SSP Data Read Register */
+
+
+/*
+ * MultiMediaCard (MMC) controller
+ */
+
+#define MMC_STRPCL	__REG(0x41100000)  /* Control to start and stop MMC clock */
+#define MMC_STAT	__REG(0x41100004)  /* MMC Status Register (read only) */
+#define MMC_CLKRT	__REG(0x41100008)  /* MMC clock rate */
+#define MMC_SPI		__REG(0x4110000c)  /* SPI mode control bits */
+#define MMC_CMDAT	__REG(0x41100010)  /* Command/response/data sequence control */
+#define MMC_RESTO	__REG(0x41100014)  /* Expected response time out */
+#define MMC_RDTO	__REG(0x41100018)  /* Expected data read time out */
+#define MMC_BLKLEN	__REG(0x4110001c)  /* Block length of data transaction */
+#define MMC_NOB		__REG(0x41100020)  /* Number of blocks, for block mode */
+#define MMC_PRTBUF	__REG(0x41100024)  /* Partial MMC_TXFIFO FIFO written */
+#define MMC_I_MASK	__REG(0x41100028)  /* Interrupt Mask */
+#define MMC_I_REG	__REG(0x4110002c)  /* Interrupt Register (read only) */
+#define MMC_CMD		__REG(0x41100030)  /* Index of current command */
+#define MMC_ARGH	__REG(0x41100034)  /* MSW part of the current command argument */
+#define MMC_ARGL	__REG(0x41100038)  /* LSW part of the current command argument */
+#define MMC_RES		__REG(0x4110003c)  /* Response FIFO (read only) */
+#define MMC_RXFIFO	__REG(0x41100040)  /* Receive FIFO (read only) */
+#define MMC_TXFIFO	__REG(0x41100044)  /* Transmit FIFO (write only) */
+
+
+/*
+ * Core Clock
+ */
+
+#define CCCR		__REG(0x41300000)  /* Core Clock Configuration Register */
+#define CKEN		__REG(0x41300004)  /* Clock Enable Register */
+#define OSCC		__REG(0x41300008)  /* Oscillator Configuration Register */
+
+#define CCCR_N_MASK	0x0380		/* Run Mode Frequency to Turbo Mode Frequency Multiplier */
+#define CCCR_M_MASK	0x0060		/* Memory Frequency to Run Mode Frequency Multiplier */
+#define CCCR_L_MASK	0x001f		/* Crystal Frequency to Memory Frequency Multiplier */
+
+#define CKEN16_LCD	(1 << 16)	/* LCD Unit Clock Enable */
+#define CKEN14_I2C	(1 << 14)	/* I2C Unit Clock Enable */
+#define CKEN13_FICP	(1 << 13)	/* FICP Unit Clock Enable */
+#define CKEN12_MMC	(1 << 12)	/* MMC Unit Clock Enable */
+#define CKEN11_USB	(1 << 11)	/* USB Unit Clock Enable */
+#define CKEN8_I2S	(1 << 8)	/* I2S Unit Clock Enable */
+#define CKEN7_BTUART	(1 << 7)	/* BTUART Unit Clock Enable */
+#define CKEN6_FFUART	(1 << 6)	/* FFUART Unit Clock Enable */
+#define CKEN5_STUART	(1 << 5)	/* STUART Unit Clock Enable */
+#define CKEN3_SSP	(1 << 3)	/* SSP Unit Clock Enable */
+#define CKEN2_AC97	(1 << 2)	/* AC97 Unit Clock Enable */
+#define CKEN1_PWM1	(1 << 1)	/* PWM1 Clock Enable */
+#define CKEN0_PWM0	(1 << 0)	/* PWM0 Clock Enable */
+
+#define OSCC_OON	(1 << 1)	/* 32.768kHz OON (write-once only bit) */
+#define OSCC_OOK	(1 << 0)	/* 32.768kHz OOK (read-only bit) */
+
+
+/*
+ * LCD
+ */
+
+#define LCCR0		__REG(0x44000000)  /* LCD Controller Control Register 0 */
+#define LCCR1		__REG(0x44000004)  /* LCD Controller Control Register 1 */
+#define LCCR2		__REG(0x44000008)  /* LCD Controller Control Register 2 */
+#define LCCR3		__REG(0x4400000C)  /* LCD Controller Control Register 3 */
+#define DFBR0		__REG(0x44000020)  /* DMA Channel 0 Frame Branch Register */
+#define DFBR1		__REG(0x44000024)  /* DMA Channel 1 Frame Branch Register */
+#define LCSR		__REG(0x44000038)  /* LCD Controller Status Register */
+#define LIIDR		__REG(0x4400003C)  /* LCD Controller Interrupt ID Register */
+#define TMEDRGBR	__REG(0x44000040)  /* TMED RGB Seed Register */
+#define TMEDCR		__REG(0x44000044)  /* TMED Control Register */
+
+#define FDADR0		__REG(0x44000200)  /* DMA Channel 0 Frame Descriptor Address Register */
+#define FSADR0		__REG(0x44000204)  /* DMA Channel 0 Frame Source Address Register */
+#define FIDR0		__REG(0x44000208)  /* DMA Channel 0 Frame ID Register */
+#define LDCMD0		__REG(0x4400020C)  /* DMA Channel 0 Command Register */
+#define FDADR1		__REG(0x44000210)  /* DMA Channel 1 Frame Descriptor Address Register */
+#define FSADR1		__REG(0x44000214)  /* DMA Channel 1 Frame Source Address Register */
+#define FIDR1		__REG(0x44000218)  /* DMA Channel 1 Frame ID Register */
+#define LDCMD1		__REG(0x4400021C)  /* DMA Channel 1 Command Register */
+
+#define LCCR0_ENB	(1 << 0)	/* LCD Controller enable */
+#define LCCR0_CMS	(1 << 1)	/* Color = 0, Monochrome = 1 */
+#define LCCR0_SDS	(1 << 2)	/* Single Panel = 0, Dual Panel = 1 */
+#define LCCR0_LDM	(1 << 3)	/* LCD Disable Done Mask */
+#define LCCR0_SFM	(1 << 4)	/* Start of frame mask */
+#define LCCR0_IUM	(1 << 5)	/* Input FIFO underrun mask */
+#define LCCR0_EFM	(1 << 6)	/* End of Frame mask */
+#define LCCR0_PAS	(1 << 7)	/* Passive = 0, Active = 1 */
+#define LCCR0_BLE	(1 << 8)	/* Little Endian = 0, Big Endian = 1 */
+#define LCCR0_DPD	(1 << 9)	/* Double Pixel mode, 4 pixel value = 0, 8 pixle values = 1 */
+#define LCCR0_DIS	(1 << 10)	/* LCD Disable */
+#define LCCR0_QDM	(1 << 11)	/* LCD Quick Disable mask */
+#define LCCR0_PDD	(0xff << 12)	/* Palette DMA request delay */
+#define LCCR0_PDD_S	12
+#define LCCR0_BM	(1 << 20) 	/* Branch mask */
+#define LCCR0_OUM	(1 << 21)	/* Output FIFO underrun mask */
+
+#define LCCR3_PCD	(0xff)		/* Pixel clock divisor */
+#define LCCR3_ACB	(0xff << 8)	/* AC Bias pin frequency */
+#define LCCR3_ACB_S	8
+#define LCCR3_API	(0xf << 16)	/* AC Bias pin trasitions per interrupt */
+#define LCCR3_API_S	16
+#define LCCR3_VSP	(1 << 20)	/* vertical sync polarity */
+#define LCCR3_HSP	(1 << 21)	/* horizontal sync polarity */
+#define LCCR3_PCP	(1 << 22)	/* pixel clock polarity */
+#define LCCR3_OEP	(1 << 23)	/* output enable polarity */
+#define LCCR3_BPP	(7 << 24)	/* bits per pixel */
+#define LCCR3_BPP_S	24
+#define LCCR3_DPC	(1 << 27)	/* double pixel clock mode */
+
+#define LCSR_LDD	(1 << 0)	/* LCD Disable Done */
+#define LCSR_SOF	(1 << 1)	/* Start of frame */
+#define LCSR_BER	(1 << 2)	/* Bus error */
+#define LCSR_ABC	(1 << 3)	/* AC Bias count */
+#define LCSR_IUL	(1 << 4)	/* input FIFO underrun Lower panel */
+#define LCSR_IUU	(1 << 5)	/* input FIFO underrun Upper panel */
+#define LCSR_OU		(1 << 6)	/* output FIFO underrun */
+#define LCSR_QD		(1 << 7)	/* quick disable */
+#define LCSR_EOF	(1 << 8)	/* end of frame */
+#define LCSR_BS		(1 << 9)	/* branch status */
+#define LCSR_SINT	(1 << 10)	/* subsequent interrupt */
+
+#define LDCMD_PAL	(1 << 26)	/* instructs DMA to load palette buffer */
+
+/*
+ * Memory controller
+ */
+
+#define MDCNFG		__REG(0x48000000)  /* SDRAM Configuration Register 0 */
+#define MDREFR		__REG(0x48000004)  /* SDRAM Refresh Control Register */
+#define MSC0		__REG(0x48000008)  /* Static Memory Control Register 0 */
+#define MSC1		__REG(0x4800000C)  /* Static Memory Control Register 1 */
+#define MSC2		__REG(0x48000010)  /* Static Memory Control Register 2 */
+#define MECR		__REG(0x48000014)  /* Expansion Memory (PCMCIA/Compact Flash) Bus Configuration */
+#define SXLCR		__REG(0x48000018)  /* LCR value to be written to SDRAM-Timing Synchronous Flash */
+#define SXCNFG		__REG(0x4800001C)  /* Synchronous Static Memory Control Register */
+#define SXMRS		__REG(0x48000024)  /* MRS value to be written to Synchronous Flash or SMROM */
+#define MCMEM0		__REG(0x48000028)  /* Card interface Common Memory Space Socket 0 Timing */
+#define MCMEM1		__REG(0x4800002C)  /* Card interface Common Memory Space Socket 1 Timing */
+#define MCATT0		__REG(0x48000030)  /* Card interface Attribute Space Socket 0 Timing Configuration */
+#define MCATT1		__REG(0x48000034)  /* Card interface Attribute Space Socket 1 Timing Configuration */
+#define MCIO0		__REG(0x48000038)  /* Card interface I/O Space Socket 0 Timing Configuration */
+#define MCIO1		__REG(0x4800003C)  /* Card interface I/O Space Socket 1 Timing Configuration */
+#define MDMRS		__REG(0x48000040)  /* MRS value to be written to SDRAM */
+#define BOOT_DEF	__REG(0x48000044)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
+
diff -Nru a/include/asm-arm/arch-pxa/serial.h b/include/asm-arm/arch-pxa/serial.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/serial.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,51 @@
+/*
+ *  linux/include/asm-arm/arch-pxa/serial.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#define BAUD_BASE	921600
+
+/* Standard COM flags */
+#define STD_COM_FLAGS (ASYNC_SKIP_TEST)
+
+#define RS_TABLE_SIZE	5
+
+#define STD_SERIAL_PORT_DEFNS	\
+	{	\
+		type:			PORT_PXA,	\
+		xmit_fifo_size:		64,		\
+		baud_base:		BAUD_BASE,	\
+		iomem_base:		&FFUART,	\
+		iomem_reg_shift:	2,		\
+		io_type:		SERIAL_IO_MEM,	\
+		irq:			IRQ_FFUART,	\
+		flags:			STD_COM_FLAGS,	\
+	}, {	\
+		type:			PORT_PXA,	\
+		xmit_fifo_size:		64,		\
+		baud_base:		BAUD_BASE,	\
+		iomem_base:		&STUART,	\
+		iomem_reg_shift:	2,		\
+		io_type:		SERIAL_IO_MEM,	\
+		irq:			IRQ_STUART,	\
+		flags:			STD_COM_FLAGS,	\
+	}, {	\
+		type:			PORT_PXA,	\
+		xmit_fifo_size:		64,		\
+		baud_base:		BAUD_BASE,	\
+		iomem_base:		&BTUART,	\
+		iomem_reg_shift:	2,		\
+		io_type:		SERIAL_IO_MEM,	\
+		irq:			IRQ_BTUART,	\
+		flags:			STD_COM_FLAGS,	\
+	}
+
+#define EXTRA_SERIAL_PORT_DEFNS
+
diff -Nru a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/system.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,39 @@
+/*
+ * linux/include/asm-arm/arch-pxa/system.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "hardware.h"
+
+static inline void arch_idle(void)
+{
+	if (!hlt_counter) {
+		int flags;
+		local_irq_save(flags);
+		if(!need_resched())
+			cpu_do_idle(0);
+		local_irq_restore(flags);
+	}
+}
+
+
+static inline void arch_reset(char mode)
+{
+	if (mode == 's') {
+		/* Jump into ROM at address 0 */
+		cpu_reset(0);
+	} else {
+		/* Initialize the watchdog and let it fire */
+		OWER = OWER_WME;
+		OSSR = OSSR_M3;
+		OSMR3 = OSCR + 36864;	/* ... in 10 ms */
+	}
+}
+
diff -Nru a/include/asm-arm/arch-pxa/time.h b/include/asm-arm/arch-pxa/time.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/time.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,84 @@
+/*
+ * linux/include/asm-arm/arch-pxa/time.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+static inline unsigned long pxa_get_rtc_time(void)
+{
+	return RCNR;
+}
+
+static int pxa_set_rtc(void)
+{
+	unsigned long current_time = xtime.tv_sec;
+
+	if (RTSR & RTSR_ALE) {
+		/* make sure not to forward the clock over an alarm */
+		unsigned long alarm = RTAR;
+		if (current_time >= alarm && alarm >= RCNR)
+			return -ERESTARTSYS;
+	}
+	RCNR = current_time;
+	return 0;
+}
+
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long pxa_gettimeoffset (void)
+{
+	unsigned long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match = OSMR0 - OSCR;
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* Now convert them to usec */
+	usec = (unsigned long)(elapsed*tick)/LATCH;
+
+	return usec;
+}
+
+static void pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	long flags;
+	int next_match;
+
+	/* Loop until we get ahead of the free running timer.
+	 * This ensures an exact clock tick count and time acuracy.
+	 * IRQs are disabled inside the loop to ensure coherence between
+	 * lost_ticks (updated in do_timer()) and the match reg value, so we
+	 * can use do_gettimeofday() from interrupt handlers.
+	 */
+	do {
+		do_leds();
+		do_set_rtc();
+		local_irq_save( flags );
+		do_timer(regs);
+		OSSR = OSSR_M0;  /* Clear match on timer 0 */
+		next_match = (OSMR0 += LATCH);
+		local_irq_restore( flags );
+	} while( (signed long)(next_match - OSCR) <= 0 );
+}
+
+void __init time_init(void)
+{
+	gettimeoffset = pxa_gettimeoffset;
+	set_rtc = pxa_set_rtc;
+	xtime.tv_sec = pxa_get_rtc_time();
+	timer_irq.handler = pxa_timer_interrupt;
+	OSMR0 = 0;		/* set initial match at 0 */
+	OSSR = 0xf;		/* clear status on all timers */
+	setup_irq(IRQ_OST0, &timer_irq);
+	OIER |= OIER_E0;	/* enable match on timer 0 to cause interrupts */
+	OSCR = 0;		/* initialize free-running timer, force first match */
+}
+
diff -Nru a/include/asm-arm/arch-pxa/timex.h b/include/asm-arm/arch-pxa/timex.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/timex.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,17 @@
+/*
+ * linux/include/asm-arm/arch-pxa/timex.h
+ *
+ * Author:	Nicolas Pitre
+ * Created:	Jun 15, 2001
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * PXA250/210 timer
+ */
+#define CLOCK_TICK_RATE		3686400
+#define CLOCK_TICK_FACTOR	80
diff -Nru a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/uncompress.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,42 @@
+/*
+ * linux/include/asm-arm/arch-pxa/uncompress.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define FFUART		((volatile unsigned long *)0x40100000)
+#define BTUART		((volatile unsigned long *)0x40200000)
+#define STUART		((volatile unsigned long *)0x40700000)
+
+#define UART		FFUART
+
+
+static __inline__ void putc(char c)
+{
+	while (!(UART[5] & 0x20));
+	UART[0] = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+	while (*s) {
+		putc(*s);
+		if (*s == '\n')
+			putc('\r');
+		s++;
+	}
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff -Nru a/include/asm-arm/arch-pxa/vmalloc.h b/include/asm-arm/arch-pxa/vmalloc.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-arm/arch-pxa/vmalloc.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-pxa/vmalloc.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (0xe8000000)
diff -Nru a/include/asm-arm/arch-sa1100/keyboard.h b/include/asm-arm/arch-sa1100/keyboard.h
--- a/include/asm-arm/arch-sa1100/keyboard.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-arm/arch-sa1100/keyboard.h	Sun Apr 14 12:16:58 2002
@@ -10,8 +10,8 @@
 #include <asm/mach-types.h>
 #include <asm/arch/assabet.h>
 
-#define kbd_disable_irq()	do { } while(0);
-#define kbd_enable_irq()	do { } while(0);
+#define kbd_disable_irq()	do { } while(0)
+#define kbd_enable_irq()	do { } while(0)
 
 extern int sa1111_kbd_init_hw(void);
 extern void gc_kbd_init_hw(void);
diff -Nru a/include/asm-arm/cpu-multi32.h b/include/asm-arm/cpu-multi32.h
--- a/include/asm-arm/cpu-multi32.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-arm/cpu-multi32.h	Sun Apr 14 12:16:55 2002
@@ -56,10 +56,6 @@
 		 * flush a specific page or pages
 		 */
 		void (*clean_invalidate_range)(unsigned long address, unsigned long end, int flags);
-		/*
-		 * flush a page to RAM
-		 */
-		void (*_flush_ram_page)(void *virt_page);
 	} cache;
 
 	struct {	/* D-cache */
@@ -121,7 +117,6 @@
 
 #define cpu_cache_clean_invalidate_all()	processor.cache.clean_invalidate_all()
 #define cpu_cache_clean_invalidate_range(s,e,f)	processor.cache.clean_invalidate_range(s,e,f)
-#define cpu_flush_ram_page(vp)			processor.cache._flush_ram_page(vp)
 
 #define cpu_dcache_clean_page(vp)		processor.dcache.clean_page(vp)
 #define cpu_dcache_clean_entry(addr)		processor.dcache.clean_entry(addr)
diff -Nru a/include/asm-arm/cpu-single.h b/include/asm-arm/cpu-single.h
--- a/include/asm-arm/cpu-single.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-arm/cpu-single.h	Sun Apr 14 12:16:55 2002
@@ -29,7 +29,6 @@
 #define cpu_do_idle			__cpu_fn(CPU_NAME,_do_idle)
 #define cpu_cache_clean_invalidate_all	__cpu_fn(CPU_NAME,_cache_clean_invalidate_all)
 #define cpu_cache_clean_invalidate_range __cpu_fn(CPU_NAME,_cache_clean_invalidate_range)
-#define cpu_flush_ram_page		__cpu_fn(CPU_NAME,_flush_ram_page)
 #define cpu_dcache_invalidate_range	__cpu_fn(CPU_NAME,_dcache_invalidate_range)
 #define cpu_dcache_clean_range		__cpu_fn(CPU_NAME,_dcache_clean_range)
 #define cpu_dcache_clean_page		__cpu_fn(CPU_NAME,_dcache_clean_page)
@@ -57,7 +56,6 @@
 
 extern void cpu_cache_clean_invalidate_all(void);
 extern void cpu_cache_clean_invalidate_range(unsigned long address, unsigned long end, int flags);
-extern void cpu_flush_ram_page(void *virt_page);
 
 extern void cpu_dcache_invalidate_range(unsigned long start, unsigned long end);
 extern void cpu_dcache_clean_range(unsigned long start, unsigned long end);
diff -Nru a/include/asm-arm/irq.h b/include/asm-arm/irq.h
--- a/include/asm-arm/irq.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-arm/irq.h	Sun Apr 14 12:16:59 2002
@@ -19,6 +19,8 @@
 #define NO_IRQ	((unsigned int)(-1))
 #endif
 
+struct irqaction;
+
 #define disable_irq_nosync(i) disable_irq(i)
 
 extern void disable_irq(unsigned int);
@@ -37,6 +39,8 @@
 #define IRQT_HIGH	(__IRQT_HIGHLVL)
 
 int set_irq_type(unsigned int irq, unsigned int type);
+
+int setup_irq(unsigned int, struct irqaction *);
 
 #endif
 
diff -Nru a/include/asm-arm/leds.h b/include/asm-arm/leds.h
--- a/include/asm-arm/leds.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-arm/leds.h	Sun Apr 14 12:16:57 2002
@@ -23,12 +23,16 @@
 	led_stop,
 	led_claim,		/* override idle & timer leds */
 	led_release,		/* restore idle & timer leds */
+	led_start_timer_mode,
+	led_stop_timer_mode,
 	led_green_on,
 	led_green_off,
 	led_amber_on,
 	led_amber_off,
 	led_red_on,
 	led_red_off,
+	led_blue_on,
+	led_blue_off,
 	/*
 	 * I want this between led_timer and led_start, but
 	 * someone has decided to export this to user space
diff -Nru a/include/asm-arm/mach/irq.h b/include/asm-arm/mach/irq.h
--- a/include/asm-arm/mach/irq.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-arm/mach/irq.h	Sun Apr 14 12:16:57 2002
@@ -75,7 +75,6 @@
 extern void init_FIQ(void);
 extern int show_fiq_list(struct seq_file *, void *);
 void __set_irq_handler(unsigned int irq, irq_handler_t, int);
-int setup_irq(unsigned int, struct irqaction *);
 
 /*
  * External stuff.
diff -Nru a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
--- a/include/asm-arm/mach/pci.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-arm/mach/pci.h	Sun Apr 14 12:16:58 2002
@@ -61,6 +61,7 @@
  */
 extern int iop310_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *);
+extern void iop310_init(void);
 
 extern int dc21285_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
@@ -75,4 +76,3 @@
 extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *);
 extern void pci_v3_preinit(void);
 extern void pci_v3_postinit(void);
-
diff -Nru a/include/asm-arm/mach/serial_sa1100.h b/include/asm-arm/mach/serial_sa1100.h
--- a/include/asm-arm/mach/serial_sa1100.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-arm/mach/serial_sa1100.h	Sun Apr 14 12:16:58 2002
@@ -26,13 +26,10 @@
 	void	(*close)(struct uart_port *, struct uart_info *);
 };
 
-#if defined(CONFIG_SERIAL_SA1100) && !defined(CONFIG_SERIAL_SA1100_OLD)
+#ifdef CONFIG_SERIAL_SA1100
 void sa1100_register_uart_fns(struct sa1100_port_fns *fns);
 void sa1100_register_uart(int idx, int port);
 #else
 #define sa1100_register_uart_fns(fns) do { } while (0)
 #define sa1100_register_uart(idx,port) do { } while (0)
 #endif
-
-void sa1100_uart1_altgpio(void);
-
diff -Nru a/include/asm-arm/mman.h b/include/asm-arm/mman.h
--- a/include/asm-arm/mman.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-arm/mman.h	Sun Apr 14 12:16:57 2002
@@ -4,6 +4,7 @@
 #define PROT_READ	0x1		/* page can be read */
 #define PROT_WRITE	0x2		/* page can be written */
 #define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_SEM	0x8		/* page may be used for atomic ops */
 #define PROT_NONE	0x0		/* page can not be accessed */
 
 #define MAP_SHARED	0x01		/* Share changes */
diff -Nru a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
--- a/include/asm-arm/pgalloc.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-arm/pgalloc.h	Sun Apr 14 12:16:59 2002
@@ -30,4 +30,6 @@
 #define pgd_alloc(mm)			get_pgd_slow(mm)
 #define pgd_free(pgd)			free_pgd_slow(pgd)
 
+#define check_pgt_cache()		do { } while (0)
+
 #endif
diff -Nru a/include/asm-arm/proc-armv/cache.h b/include/asm-arm/proc-armv/cache.h
--- a/include/asm-arm/proc-armv/cache.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-arm/proc-armv/cache.h	Sun Apr 14 12:16:58 2002
@@ -59,74 +59,6 @@
 	} while (0)
 
 /*
- * This flushes back any buffered write data.  We have to clean the entries
- * in the cache for this page.  This does not invalidate either I or D caches.
- *
- * Called from:
- *  1. fs/exec.c:put_dirty_page				- ok
- *     - page came from alloc_page(), so page->mapping = NULL.
- *     - flush_dcache_page called immediately prior.
- *
- *  2. kernel/ptrace.c:access_one_page			- flush_icache_page
- *     - flush_cache_page takes care of the user space side of the mapping.
- *     - page is either a page cache page (with page->mapping set, and
- *       hence page->mapping->i_mmap{,shared} also set) or an anonymous
- *       page.  I think this is ok.
- *
- *  3. kernel/ptrace.c:access_one_page			- bad
- *     - flush_cache_page takes care of the user space side of the mapping.
- *     - no apparant cache protection, reading the kernel virtual alias
- *
- *  4. mm/filemap.c:filemap_no_page			- ok
- *     - add_to_page_cache_* clears PG_arch_1.
- *     - page->mapping != NULL.
- *     - i_mmap or i_mmap_shared will be non-null if mmap'd
- *     - called from (8).
- *
- *  5. mm/memory.c:break_cow,do_wp_page			- {copy,clear}_user_page
- *     - need to ensure that copy_cow_page has pushed all data from the dcache
- *       to the page.
- *       - calls
- *         - clear_user_highpage -> clear_user_page
- *         - copy_user_highpage -> copy_user_page
- *
- *  6. mm/memory.c:do_swap_page				- flush_icache_page
- *     - flush_icache_page called afterwards - if flush_icache_page does the
- *       same as flush_dcache_page, update_mmu_cache will do the work for us.
- *     - update_mmu_cache called.
- *
- *  7. mm/memory.c:do_anonymous_page			- {copy,clear}_user_page
- *     - calls clear_user_highpage.  See (5)
- *
- *  8. mm/memory.c:do_no_page				- flush_icache_page
- *     - flush_icache_page called afterwards - if flush_icache_page does the
- *       same as flush_dcache_page, update_mmu_cache will do the work for us.
- *     - update_mmu_cache called.
- *     - When we place a user mapping, we will call update_mmu_cache,
- *       which will catch PG_arch_1 set.
- *
- *  9. mm/shmem.c:shmem_no_page				- ok
- *     - shmem_get_page clears PG_arch_1, as does add_to_page_cache (duplicate)
- *     - page->mapping != NULL.
- *     - i_mmap or i_mmap_shared will be non-null if mmap'd
- *     - called from (8).
- *
- * 10. mm/swapfile.c:try_to_unuse			- bad
- *     - this looks really dodgy - we're putting pages from the swap cache
- *       straight into processes, and the only cache handling appears to
- *       be flush_page_to_ram.
- */
-#define flush_page_to_ram_ok
-#ifdef flush_page_to_ram_ok
-#define flush_page_to_ram(page)	do { } while (0)
-#else
-static __inline__ void flush_page_to_ram(struct page *page)
-{
-	cpu_flush_ram_page(page_address(page));
-}
-#endif
-
-/*
  * D cache only
  */
 
@@ -134,8 +66,16 @@
 #define clean_dcache_range(_s,_e)	cpu_dcache_clean_range((_s),(_e))
 #define flush_dcache_range(_s,_e)	cpu_cache_clean_invalidate_range((_s),(_e),0)
 
-#define mapping_mapped(map)	(!list_empty(&(map)->i_mmap) || \
-				 !list_empty(&(map)->i_mmap_shared))
+#define clean_dcache_area(start,size) \
+	cpu_cache_clean_invalidate_range((unsigned long)start, \
+					 ((unsigned long)start) + size, 0);
+
+/*
+ * This is an obsolete interface; the functionality that was provided by this
+ * function is now merged into our flush_dcache_page, flush_icache_page,
+ * copy_user_page and clear_user_page functions.
+ */
+#define flush_page_to_ram(page)	do { } while (0)
 
 /*
  * flush_dcache_page is used when the kernel has written to the page
@@ -150,39 +90,31 @@
  * about to change to user space.  This is the same method as used on SPARC64.
  * See update_mmu_cache for the user space part.
  */
+#define mapping_mapped(map)	(!list_empty(&(map)->i_mmap) || \
+				 !list_empty(&(map)->i_mmap_shared))
+
+static inline void __flush_dcache_page(struct page *page)
+{
+	unsigned long virt = (unsigned long)page_address(page);
+	cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
+}
+
 static inline void flush_dcache_page(struct page *page)
 {
 	if (page->mapping && !mapping_mapped(page->mapping))
 		set_bit(PG_dcache_dirty, &page->flags);
-	else {
-		unsigned long virt = (unsigned long)page_address(page);
-		cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
-	}
+	else
+		__flush_dcache_page(page);
 }
 
+#define flush_icache_user_range(vma,page,addr,len) \
+	flush_dcache_page(page)
+
 /*
- * flush_icache_page makes the kernel page address consistent with the
- * user space mappings.  The functionality is the same as flush_dcache_page,
- * except we can do an optimisation and only clean the caches here if
- * vma->vm_mm == current->active_mm.
- *
- * This function is misnamed IMHO.  There are three places where it
- * is called, each of which is preceded immediately by a call to
- * flush_page_to_ram:
+ * We don't appear to need to do anything here.  In fact, if we did, we'd
+ * duplicate cache flushing elsewhere performed by flush_dcache_page().
  */
-#ifdef flush_page_to_ram_ok
-static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-	if (page->mapping && !mapping_mapped(page->mapping))
-		set_bit(PG_dcache_dirty, &page->flags);
-	else if (vma->vm_mm == current->active_mm) {
-		unsigned long virt = (unsigned long)page_address(page);
-		cpu_cache_clean_invalidate_range(virt, virt + PAGE_SIZE, 0);
-	}
-}
-#else
-#define flush_icache_page(vma,pg)	do { } while (0)
-#endif
+#define flush_icache_page(vma,page)	do { } while (0)
 
 #define clean_dcache_entry(_s)		cpu_dcache_clean_entry((unsigned long)(_s))
 
diff -Nru a/include/asm-arm/proc-armv/domain.h b/include/asm-arm/proc-armv/domain.h
--- a/include/asm-arm/proc-armv/domain.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-arm/proc-armv/domain.h	Sun Apr 14 12:16:56 2002
@@ -38,13 +38,13 @@
 	  : : "r" (x));					\
 	} while (0)
 
-#define modify_domain(dom,type)				\
-	do {						\
-	unsigned int domain = current->thread.domain;	\
-	domain &= ~domain_val(dom, DOMAIN_MANAGER);	\
-	domain |= domain_val(dom, type);		\
-	current->thread.domain = domain;		\
-	set_domain(current->thread.domain);		\
+#define modify_domain(dom,type)					\
+	do {							\
+	struct thread_info *thread = current_thread_info();	\
+	unsigned int domain = thread->cpu_domain;		\
+	domain &= ~domain_val(dom, DOMAIN_MANAGER);		\
+	thread->cpu_domain = domain | domain_val(dom, type);	\
+	set_domain(thread->cpu_domain);				\
 	} while (0)
 
 #endif
diff -Nru a/include/asm-arm/siginfo.h b/include/asm-arm/siginfo.h
--- a/include/asm-arm/siginfo.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-arm/siginfo.h	Sun Apr 14 12:16:54 2002
@@ -107,7 +107,8 @@
 #define SI_MESGQ	-3		/* sent by real time mesq state change */
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
-#define SI_TKILL        -6              /* sent by tkill system call */
+#define SI_TKILL	-6		/* sent by tkill system call */
+#define SI_DETHREAD	-7		/* sent by execve() killing subsidiary threads */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-arm/system.h	Sun Apr 14 12:16:55 2002
@@ -84,7 +84,6 @@
 #define stf()			__stf()
 #define save_flags(x)		__save_flags(x)
 #define restore_flags(x)	__restore_flags(x)
-#define save_flags_cli(x)	__save_flags_cli(x)
 
 #endif /* CONFIG_SMP */
 
diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
--- a/include/asm-arm/unistd.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-arm/unistd.h	Sun Apr 14 12:16:57 2002
@@ -466,4 +466,13 @@
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
 
 #endif
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* __ASM_ARM_UNISTD_H */
diff -Nru a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
--- a/include/asm-cris/unistd.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-cris/unistd.h	Sun Apr 14 12:16:57 2002
@@ -395,4 +395,12 @@
 
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_CRIS_UNISTD_H_ */
diff -Nru a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-generic/percpu.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,13 @@
+#ifndef _ASM_GENERIC_PERCPU_H_
+#define _ASM_GENERIC_PERCPU_H_
+
+#define __GENERIC_PER_CPU
+#include <linux/compiler.h>
+
+extern unsigned long __per_cpu_offset[NR_CPUS];
+
+/* var is in discarded region: offset to particular copy we want */
+#define per_cpu(var, cpu) (*RELOC_HIDE(&var, __per_cpu_offset[cpu]))
+#define this_cpu(var) per_cpu(var, smp_processor_id())
+
+#endif /* _ASM_GENERIC_PERCPU_H_ */
diff -Nru a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
--- a/include/asm-generic/tlb.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-generic/tlb.h	Sun Apr 14 12:16:54 2002
@@ -14,6 +14,7 @@
 #define _ASM_GENERIC__TLB_H
 
 #include <linux/config.h>
+#include <asm/tlbflush.h>
 
 #ifdef CONFIG_SMP
 /* aim for something that fits in the L1 cache */
diff -Nru a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
--- a/include/asm-i386/acpi.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-i386/acpi.h	Sun Apr 14 12:16:57 2002
@@ -33,10 +33,15 @@
 /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
 #define FIX_ACPI_PAGES		4
 
+extern int acpi_mp_config;
+
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 extern int acpi_find_rsdp (unsigned long *phys_addr);
 extern int acpi_parse_madt (unsigned long phys_addr, unsigned long size);
+extern int acpi_boot_init (char *cmdline);
 
+#else
+#define acpi_mp_config 0
 #endif /*CONFIG_ACPI_BOOT*/
 
 #ifdef CONFIG_ACPI_PCI
diff -Nru a/include/asm-i386/apic.h b/include/asm-i386/apic.h
--- a/include/asm-i386/apic.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-i386/apic.h	Sun Apr 14 12:16:58 2002
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/pm.h>
+#include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
diff -Nru a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
--- a/include/asm-i386/apicdef.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-i386/apicdef.h	Sun Apr 14 12:16:54 2002
@@ -71,6 +71,7 @@
 #define			GET_APIC_DEST_FIELD(x)	(((x)>>24)&0xFF)
 #define			SET_APIC_DEST_FIELD(x)	((x)<<24)
 #define		APIC_LVTT	0x320
+#define		APIC_LVTTHMR	0x330
 #define		APIC_LVTPC	0x340
 #define		APIC_LVT0	0x350
 #define			APIC_LVT_TIMER_BASE_MASK	(0x3<<18)
@@ -280,7 +281,16 @@
 		u32 __reserved_4[3];
 	} lvt_timer;
 
-/*330*/	struct { u32 __reserved[4]; } __reserved_15;
+/*330*/	struct { /* LVT - Thermal Sensor */
+		u32  vector		:  8,
+			delivery_mode	:  3,
+			__reserved_1	:  1,
+			delivery_status	:  1,
+			__reserved_2	:  3,
+			mask		:  1,
+			__reserved_3	: 15;
+		u32 __reserved_4[3];
+	} lvt_thermal;
 
 /*340*/	struct { /* LVT - Performance Counter */
 		u32   vector		:  8,
diff -Nru a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
--- a/include/asm-i386/bitops.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-i386/bitops.h	Sun Apr 14 12:16:59 2002
@@ -469,18 +469,23 @@
 
 #ifdef __KERNEL__
 
-#define ext2_set_bit                 __test_and_set_bit
-#define ext2_clear_bit               __test_and_clear_bit
-#define ext2_test_bit                test_bit
-#define ext2_find_first_zero_bit     find_first_zero_bit
-#define ext2_find_next_zero_bit      find_next_zero_bit
+#define ext2_set_bit(nr,addr) \
+	__test_and_set_bit((nr),(unsigned long*)addr)
+#define ext2_clear_bit(nr, addr) \
+	__test_and_clear_bit((nr),(unsigned long*)addr)
+#define ext2_test_bit(nr, addr)      test_bit((nr),(unsigned long*)addr)
+#define ext2_find_first_zero_bit(addr, size) \
+	find_first_zero_bit((unsigned long*)addr, size)
+#define ext2_find_next_zero_bit(addr, size, off) \
+	find_next_zero_bit((unsigned long*)addr, size, off)
 
 /* Bitmap functions for the minix filesystem.  */
-#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) __set_bit(nr,addr)
-#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,(void*)addr)
+#define minix_set_bit(nr,addr) __set_bit(nr,(void*)addr)
+#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,(void*)addr)
+#define minix_test_bit(nr,addr) test_bit(nr,(void*)addr)
+#define minix_find_first_zero_bit(addr,size) \
+	find_first_zero_bit((void*)addr,size)
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h
--- a/include/asm-i386/bugs.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-i386/bugs.h	Sun Apr 14 12:16:56 2002
@@ -194,7 +194,7 @@
  */
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
-	    && test_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability)
+	    && test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)
 	    && boot_cpu_data.x86 == 5
 	    && boot_cpu_data.x86_model == 2
 	    && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
diff -Nru a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/cacheflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,18 @@
+#ifndef _I386_CACHEFLUSH_H
+#define _I386_CACHEFLUSH_H
+
+/* Keep includes the same across arches.  */
+#include <linux/mm.h>
+
+/* Caches aren't brain-dead on the intel. */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
+#define flush_icache_page(vma,pg)		do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+
+#endif /* _I386_CACHEFLUSH_H */
diff -Nru a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
--- a/include/asm-i386/checksum.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-i386/checksum.h	Sun Apr 14 12:16:59 2002
@@ -1,6 +1,7 @@
 #ifndef _I386_CHECKSUM_H
 #define _I386_CHECKSUM_H
 
+#include <linux/in6.h>
 
 /*
  * computes the checksum of a memory block at buff, length len,
diff -Nru a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
--- a/include/asm-i386/highmem.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-i386/highmem.h	Sun Apr 14 12:16:55 2002
@@ -24,7 +24,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/kmap_types.h>
-#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 /* declarations for highmem.c */
 extern unsigned long highstart_pfn, highend_pfn;
diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
--- a/include/asm-i386/hw_irq.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-i386/hw_irq.h	Sun Apr 14 12:16:58 2002
@@ -17,56 +17,28 @@
 #include <asm/irq.h>
 
 /*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
- */
-#define FIRST_EXTERNAL_VECTOR	0x20
-
-#define SYSCALL_VECTOR		0x80
-
-/*
- * Vectors 0x20-0x2f are used for ISA interrupts.
- */
-
-/*
- * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
- *
- *  some of the following vectors are 'rare', they are merged
- *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
- *  TLB, reschedule and local APIC vectors are performance-critical.
+ * Various low-level irq details needed by irq.c, process.c,
+ * time.c, io_apic.c and smp.c
  *
- *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
- */
-#define SPURIOUS_APIC_VECTOR	0xff
-#define ERROR_APIC_VECTOR	0xfe
-#define INVALIDATE_TLB_VECTOR	0xfd
-#define RESCHEDULE_VECTOR	0xfc
-#define CALL_FUNCTION_VECTOR	0xfb
-
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR	0xef
-
-/*
- * First APIC vector available to drivers: (vectors 0x30-0xee)
- * we start at 0x31 to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
+ * Interrupt entry/exit code at both C and assembly level
  */
-#define FIRST_DEVICE_VECTOR	0x31
-#define FIRST_SYSTEM_VECTOR	0xef
 
 extern int irq_vector[NR_IRQS];
 #define IO_APIC_VECTOR(irq)	irq_vector[irq]
 
-/*
- * Various low-level irq details needed by irq.c, process.c,
- * time.c, io_apic.c and smp.c
- *
- * Interrupt entry/exit code at both C and assembly level
- */
+extern void (*interrupt[NR_IRQS])(void);
+
+#ifdef CONFIG_SMP
+extern asmlinkage void reschedule_interrupt(void);
+extern asmlinkage void invalidate_interrupt(void);
+extern asmlinkage void call_function_interrupt(void);
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+extern asmlinkage void apic_timer_interrupt(void);
+extern asmlinkage void error_interrupt(void);
+extern asmlinkage void spurious_interrupt(void);
+#endif
 
 extern void mask_irq(unsigned int irq);
 extern void unmask_irq(unsigned int irq);
@@ -91,92 +63,6 @@
 extern char _stext, _etext;
 
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
-
-#define __STR(x) #x
-#define STR(x) __STR(x)
-
-#define GET_THREAD_INFO \
-	"movl $-8192, %ebx\n\t" \
-	"andl %esp, %ebx\n\t"
-
-#ifdef CONFIG_PREEMPT
-#define BUMP_LOCK_COUNT \
-	GET_THREAD_INFO \
-	"incl 16(%ebx)\n\t"
-#else
-#define BUMP_LOCK_COUNT
-#endif
-
-#define SAVE_ALL \
-	"cld\n\t" \
-	"pushl %es\n\t" \
-	"pushl %ds\n\t" \
-	"pushl %eax\n\t" \
-	"pushl %ebp\n\t" \
-	"pushl %edi\n\t" \
-	"pushl %esi\n\t" \
-	"pushl %edx\n\t" \
-	"pushl %ecx\n\t" \
-	"pushl %ebx\n\t" \
-	"movl $" STR(__KERNEL_DS) ",%edx\n\t" \
-	"movl %edx,%ds\n\t" \
-	"movl %edx,%es\n\t" \
-	BUMP_LOCK_COUNT
-
-#define IRQ_NAME2(nr) nr##_interrupt(void)
-#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-
-#define GET_CURRENT \
-	"movl %esp, %ebx\n\t" \
-	"andl $-8192, %ebx\n\t" \
-	"movl (%ebx),%ebx\n\t"
-
-/*
- *	SMP has a few special interrupts for IPI messages
- */
-
-	/* there is a second layer of macro just to get the symbolic
-	   name for the vector evaluated. This change is for RTLinux */
-#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
-#define XBUILD_SMP_INTERRUPT(x,v)\
-asmlinkage void x(void); \
-asmlinkage void call_##x(void); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(x) ":\n\t" \
-	"pushl $"#v"-256\n\t" \
-	SAVE_ALL \
-	SYMBOL_NAME_STR(call_##x)":\n\t" \
-	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
-	"jmp ret_from_intr\n");
-
-#define BUILD_COMMON_IRQ() \
-asmlinkage void call_do_IRQ(void); \
-__asm__( \
-	"\n" __ALIGN_STR"\n" \
-	"common_interrupt:\n\t" \
-	SAVE_ALL \
-	SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \
-	"call " SYMBOL_NAME_STR(do_IRQ) "\n\t" \
-	"jmp ret_from_intr\n");
-
-/* 
- * subtle. orig_eax is used by the signal code to distinct between
- * system calls and interrupted 'random user-space'. Thus we have
- * to put a negative value into orig_eax here. (the problem is that
- * both system calls and IRQs want to have small integer numbers in
- * orig_eax, and the syscall code has won the optimization conflict ;)
- *
- * Subtle as a pigs ear.  VY
- */
-
-#define BUILD_IRQ(nr) \
-asmlinkage void IRQ_NAME(nr); \
-__asm__( \
-"\n"__ALIGN_STR"\n" \
-SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
-	"pushl $"#nr"-256\n\t" \
-	"jmp common_interrupt");
 
 extern unsigned long prof_cpu_mask;
 extern unsigned int * prof_buffer;
diff -Nru a/include/asm-i386/io.h b/include/asm-i386/io.h
--- a/include/asm-i386/io.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-i386/io.h	Sun Apr 14 12:16:58 2002
@@ -57,15 +57,37 @@
   #define __io_virt(x) ((void *)(x))
 #endif
 
-/*
- * Change virtual addresses to physical addresses and vv.
- * These are pretty trivial
+/**
+ *	virt_to_phys	-	map virtual addresses to physical
+ *	@address: address to remap
+ *
+ *	The returned physical address is the physical (CPU) mapping for
+ *	the memory address given. It is only valid to use this function on
+ *	addresses directly mapped or allocated via kmalloc. 
+ *
+ *	This function does not give bus mappings for DMA transfers. In
+ *	almost all conceivable cases a device driver should not be using
+ *	this function
  */
+ 
 static inline unsigned long virt_to_phys(volatile void * address)
 {
 	return __pa(address);
 }
 
+/**
+ *	phys_to_virt	-	map physical address to virtual
+ *	@address: address to remap
+ *
+ *	The returned virtual address is a current CPU mapping for
+ *	the memory address given. It is only valid to use this function on
+ *	addresses that have a kernel mapping
+ *
+ *	This function does not handle bus mappings for DMA transfers. In
+ *	almost all conceivable cases a device driver should not be using
+ *	this function
+ */
+
 static inline void * phys_to_virt(unsigned long address)
 {
 	return __va(address);
@@ -74,20 +96,51 @@
 /*
  * Change "struct page" to physical address.
  */
+#ifdef CONFIG_HIGHMEM64G
+#define page_to_phys(page)	((u64)(page - mem_map) << PAGE_SHIFT)
+#else
 #define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
+#endif
 
 extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
+/**
+ * ioremap     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address. 
+ */
+
 static inline void * ioremap (unsigned long offset, unsigned long size)
 {
 	return __ioremap(offset, size, 0);
 }
 
-/*
- * This one maps high address device memory and turns off caching for that area.
- * it's useful if some control registers are in such an area and write combining
- * or read caching is not desirable:
+/**
+ * ioremap_nocache     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_nocache performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address. 
+ *
+ * This version of ioremap ensures that the memory is marked uncachable
+ * on the CPU as well as honouring existing caching rules from things like
+ * the PCI bus. Note that there are other caches and buffers on many 
+ * busses. In paticular driver authors should read up on PCI writes
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
  */
+
 static inline void * ioremap_nocache (unsigned long offset, unsigned long size)
 {
         return __ioremap(offset, size, _PAGE_PCD);
@@ -113,11 +166,11 @@
 /*
  * However PCI ones are not necessarily 1:1 and therefore these interfaces
  * are forbidden in portable PCI drivers.
+ *
+ * Allow them on x86 for legacy drivers, though.
  */
-extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr);
-#define virt_to_bus virt_to_bus_not_defined_use_pci_map
-extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
-#define bus_to_virt bus_to_virt_not_defined_use_pci_map
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
@@ -172,6 +225,17 @@
 #define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),__io_virt(b),(c),(d))
 #define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
 
+/**
+ *	check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check 
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the mmio address io_addr. This
+ *	address should have been obtained by ioremap.
+ *	Returns 1 on a match.
+ */
+ 
 static inline int check_signature(unsigned long io_addr,
 	const unsigned char *signature, int length)
 {
@@ -187,6 +251,20 @@
 out:
 	return retval;
 }
+
+/**
+ *	isa_check_signature		-	find BIOS signatures
+ *	@io_addr: mmio address to check 
+ *	@signature:  signature block
+ *	@length: length of signature
+ *
+ *	Perform a signature comparison with the ISA mmio address io_addr.
+ *	Returns 1 on a match.
+ *
+ *	This function is deprecated. New drivers should use ioremap and
+ *	check_signature.
+ */
+ 
 
 static inline int isa_check_signature(unsigned long io_addr,
 	const unsigned char *signature, int length)
diff -Nru a/include/asm-i386/irq.h b/include/asm-i386/irq.h
--- a/include/asm-i386/irq.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-i386/irq.h	Sun Apr 14 12:16:55 2002
@@ -11,23 +11,8 @@
  */
 
 #include <linux/config.h>
-
-#define TIMER_IRQ 0
-
-/*
- * 16 8259A IRQ's, 208 potential APIC interrupt sources.
- * Right now the APIC is mostly only used for SMP.
- * 256 vectors is an architectural limit. (we can have
- * more than 256 devices theoretically, but they will
- * have to use shared interrupts)
- * Since vectors 0x00-0x1f are used/reserved for the CPU,
- * the usable vector space is 0x20-0xff (224 vectors)
- */
-#ifdef CONFIG_X86_IO_APIC
-#define NR_IRQS 224
-#else
-#define NR_IRQS 16
-#endif
+#include <linux/sched.h>
+#include <asm/irq_vectors.h>
 
 static __inline__ int irq_cannonicalize(int irq)
 {
diff -Nru a/include/asm-i386/irq_vectors.h b/include/asm-i386/irq_vectors.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/irq_vectors.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,64 @@
+#ifndef _ASM_IRQ_VECTORS_H
+#define _ASM_IRQ_VECTORS_H
+
+/*
+ * IDT vectors usable for external interrupt sources start
+ * at 0x20:
+ */
+#define FIRST_EXTERNAL_VECTOR	0x20
+
+#define SYSCALL_VECTOR		0x80
+
+/*
+ * Vectors 0x20-0x2f are used for ISA interrupts.
+ */
+
+/*
+ * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
+ *
+ *  some of the following vectors are 'rare', they are merged
+ *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
+ *  TLB, reschedule and local APIC vectors are performance-critical.
+ *
+ *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
+ */
+#define SPURIOUS_APIC_VECTOR	0xff
+#define ERROR_APIC_VECTOR	0xfe
+#define INVALIDATE_TLB_VECTOR	0xfd
+#define RESCHEDULE_VECTOR	0xfc
+#define CALL_FUNCTION_VECTOR	0xfb
+
+#define THERMAL_APIC_VECTOR	0xf0
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR	0xef
+
+/*
+ * First APIC vector available to drivers: (vectors 0x30-0xee)
+ * we start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR	0x31
+#define FIRST_SYSTEM_VECTOR	0xef
+
+#define TIMER_IRQ 0
+
+/*
+ * 16 8259A IRQ's, 208 potential APIC interrupt sources.
+ * Right now the APIC is mostly only used for SMP.
+ * 256 vectors is an architectural limit. (we can have
+ * more than 256 devices theoretically, but they will
+ * have to use shared interrupts)
+ * Since vectors 0x00-0x1f are used/reserved for the CPU,
+ * the usable vector space is 0x20-0xff (224 vectors)
+ */
+#ifdef CONFIG_X86_IO_APIC
+#define NR_IRQS 224
+#else
+#define NR_IRQS 16
+#endif
+
+#endif /* _ASM_IRQ_VECTORS_H */
diff -Nru a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
--- a/include/asm-i386/mmu_context.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-i386/mmu_context.h	Sun Apr 14 12:16:54 2002
@@ -5,6 +5,7 @@
 #include <asm/desc.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 /*
  * possibly do the LDT unload here?
diff -Nru a/include/asm-i386/msr.h b/include/asm-i386/msr.h
--- a/include/asm-i386/msr.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-i386/msr.h	Sun Apr 14 12:16:54 2002
@@ -48,8 +48,8 @@
 #define MSR_IA32_UCODE_WRITE		0x79
 #define MSR_IA32_UCODE_REV		0x8b
 
-#define MSR_IA32_PERFCTR0		0xc1
-#define MSR_IA32_PERFCTR1		0xc2
+#define MSR_P6_PERFCTR0		0xc1
+#define MSR_P6_PERFCTR1		0xc2
 
 #define MSR_IA32_BBL_CR_CTL		0x119
 
@@ -57,8 +57,13 @@
 #define MSR_IA32_MCG_STATUS		0x17a
 #define MSR_IA32_MCG_CTL		0x17b
 
-#define MSR_IA32_EVNTSEL0		0x186
-#define MSR_IA32_EVNTSEL1		0x187
+#define MSR_P6_EVNTSEL0		0x186
+#define MSR_P6_EVNTSEL1		0x187
+
+#define MSR_IA32_THERM_CONTROL		0x19a
+#define MSR_IA32_THERM_INTERRUPT	0x19b
+#define MSR_IA32_THERM_STATUS		0x19c
+#define MSR_IA32_MISC_ENABLE		0x1a0
 
 #define MSR_IA32_DEBUGCTLMSR		0x1d9
 #define MSR_IA32_LASTBRANCHFROMIP	0x1db
diff -Nru a/include/asm-i386/percpu.h b/include/asm-i386/percpu.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/percpu.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,6 @@
+#ifndef __ARCH_I386_PERCPU__
+#define __ARCH_I386_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_I386_PERCPU__ */
diff -Nru a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
--- a/include/asm-i386/pgalloc.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-i386/pgalloc.h	Sun Apr 14 12:16:55 2002
@@ -5,7 +5,6 @@
 #include <asm/processor.h>
 #include <asm/fixmap.h>
 #include <linux/threads.h>
-#include <linux/highmem.h>
 
 #define pmd_populate_kernel(mm, pmd, pte) \
 		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
@@ -20,109 +19,11 @@
  * Allocate and free page tables.
  */
 
-#if defined (CONFIG_X86_PAE)
-/*
- * We can't include <linux/slab.h> here, thus these uglinesses.
- */
-struct kmem_cache_s;
-
-extern struct kmem_cache_s *pae_pgd_cachep;
-extern void *kmem_cache_alloc(struct kmem_cache_s *, int);
-extern void kmem_cache_free(struct kmem_cache_s *, void *);
-
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	int i;
-	pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
-
-	if (pgd) {
-		for (i = 0; i < USER_PTRS_PER_PGD; i++) {
-			unsigned long pmd = __get_free_page(GFP_KERNEL);
-			if (!pmd)
-				goto out_oom;
-			clear_page(pmd);
-			set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
-		}
-		memcpy(pgd + USER_PTRS_PER_PGD,
-			swapper_pg_dir + USER_PTRS_PER_PGD,
-			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-	}
-	return pgd;
-out_oom:
-	for (i--; i >= 0; i--)
-		free_page((unsigned long)__va(pgd_val(pgd[i])-1));
-	kmem_cache_free(pae_pgd_cachep, pgd);
-	return NULL;
-}
-
-#else
+extern pgd_t *pgd_alloc(struct mm_struct *);
+extern void pgd_free(pgd_t *pgd);
 
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
-
-	if (pgd) {
-		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-		memcpy(pgd + USER_PTRS_PER_PGD,
-			swapper_pg_dir + USER_PTRS_PER_PGD,
-			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-	}
-	return pgd;
-}
-
-#endif /* CONFIG_X86_PAE */
-
-static inline void pgd_free(pgd_t *pgd)
-{
-#if defined(CONFIG_X86_PAE)
-	int i;
-
-	for (i = 0; i < USER_PTRS_PER_PGD; i++)
-		free_page((unsigned long)__va(pgd_val(pgd[i])-1));
-	kmem_cache_free(pae_pgd_cachep, pgd);
-#else
-	free_page((unsigned long)pgd);
-#endif
-}
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
-	int count = 0;
-	pte_t *pte;
-   
-   	do {
-		pte = (pte_t *) __get_free_page(GFP_KERNEL);
-		if (pte)
-			clear_page(pte);
-		else {
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(HZ);
-		}
-	} while (!pte && (count++ < 10));
-	return pte;
-}
-
-static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
-	int count = 0;
-	struct page *pte;
-   
-   	do {
-#if CONFIG_HIGHPTE
-		pte = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
-#else
-		pte = alloc_pages(GFP_KERNEL, 0);
-#endif
-		if (pte)
-			clear_highpage(pte);
-		else {
-			current->state = TASK_UNINTERRUPTIBLE;
-			schedule_timeout(HZ);
-		}
-	} while (!pte && (count++ < 10));
-	return pte;
-}
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
 
 static inline void pte_free_kernel(pte_t *pte)
 {
@@ -143,85 +44,6 @@
 #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
 #define pmd_free(x)			do { } while (0)
 #define pgd_populate(mm, pmd, pte)	BUG()
-
-/*
- * TLB flushing:
- *
- *  - flush_tlb() flushes the current mm struct TLBs
- *  - flush_tlb_all() flushes all processes TLBs
- *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
- *  - flush_tlb_page(vma, vmaddr) flushes one page
- *  - flush_tlb_range(vma, start, end) flushes a range of pages
- *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
- *
- * ..but the i386 has somewhat limited tlb flushing capabilities,
- * and page-granular flushes are available only on i486 and up.
- */
-
-#ifndef CONFIG_SMP
-
-#define flush_tlb() __flush_tlb()
-#define flush_tlb_all() __flush_tlb_all()
-#define local_flush_tlb() __flush_tlb()
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-	if (mm == current->active_mm)
-		__flush_tlb();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma,
-	unsigned long addr)
-{
-	if (vma->vm_mm == current->active_mm)
-		__flush_tlb_one(addr);
-}
-
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-	unsigned long start, unsigned long end)
-{
-	if (vma->vm_mm == current->active_mm)
-		__flush_tlb();
-}
-
-#else
-
-#include <asm/smp.h>
-
-#define local_flush_tlb() \
-	__flush_tlb()
-
-extern void flush_tlb_all(void);
-extern void flush_tlb_current_task(void);
-extern void flush_tlb_mm(struct mm_struct *);
-extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
-
-#define flush_tlb()	flush_tlb_current_task()
-
-static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
-{
-	flush_tlb_mm(vma->vm_mm);
-}
-
-#define TLBSTATE_OK	1
-#define TLBSTATE_LAZY	2
-
-struct tlb_state
-{
-	struct mm_struct *active_mm;
-	int state;
-	char __cacheline_padding[24];
-};
-extern struct tlb_state cpu_tlbstate[NR_CPUS];
-
-
-#endif
-
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
-				      unsigned long start, unsigned long end)
-{
-	/* i386 does not keep any page table caches in TLB */
-}
 
 #define check_pgt_cache()	do { } while (0)
 
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-i386/pgtable.h	Sun Apr 14 12:16:59 2002
@@ -24,71 +24,6 @@
 extern pgd_t swapper_pg_dir[1024];
 extern void paging_init(void);
 
-/* Caches aren't brain-dead on the intel. */
-#define flush_cache_all()			do { } while (0)
-#define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
-#define flush_page_to_ram(page)			do { } while (0)
-#define flush_dcache_page(page)			do { } while (0)
-#define flush_icache_range(start, end)		do { } while (0)
-#define flush_icache_page(vma,pg)		do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-
-#define __flush_tlb()							\
-	do {								\
-		unsigned int tmpreg;					\
-									\
-		__asm__ __volatile__(					\
-			"movl %%cr3, %0;  # flush TLB \n"		\
-			"movl %0, %%cr3;              \n"		\
-			: "=r" (tmpreg)					\
-			:: "memory");					\
-	} while (0)
-
-/*
- * Global pages have to be flushed a bit differently. Not a real
- * performance problem because this does not happen often.
- */
-#define __flush_tlb_global()						\
-	do {								\
-		unsigned int tmpreg;					\
-									\
-		__asm__ __volatile__(					\
-			"movl %1, %%cr4;  # turn off PGE     \n"	\
-			"movl %%cr3, %0;  # flush TLB        \n"	\
-			"movl %0, %%cr3;                     \n"	\
-			"movl %2, %%cr4;  # turn PGE back on \n"	\
-			: "=&r" (tmpreg)				\
-			: "r" (mmu_cr4_features & ~X86_CR4_PGE),	\
-			  "r" (mmu_cr4_features)			\
-			: "memory");					\
-	} while (0)
-
-extern unsigned long pgkern_mask;
-
-/*
- * Do not check the PGE bit unnecesserily if this is a PPro+ kernel.
- */
-#ifdef CONFIG_X86_PGE
-# define __flush_tlb_all() __flush_tlb_global()
-#else
-# define __flush_tlb_all()						\
-	do {								\
-		if (cpu_has_pge)					\
-			__flush_tlb_global();				\
-		else							\
-			__flush_tlb();					\
-	} while (0)
-#endif
-
-#ifndef CONFIG_X86_INVLPG
-#define __flush_tlb_one(addr) __flush_tlb()
-#else
-#define __flush_tlb_one(addr) \
-__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
-#endif
-
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
@@ -288,10 +223,10 @@
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
 
-static inline  int ptep_test_and_clear_dirty(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); }
-static inline  int ptep_test_and_clear_young(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); }
-static inline void ptep_set_wrprotect(pte_t *ptep)		{ clear_bit(_PAGE_BIT_RW, ptep); }
-static inline void ptep_mkdirty(pte_t *ptep)			{ set_bit(_PAGE_BIT_DIRTY, ptep); }
+static inline  int ptep_test_and_clear_dirty(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
+static inline  int ptep_test_and_clear_young(pte_t *ptep)	{ return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); }
+static inline void ptep_set_wrprotect(pte_t *ptep)		{ clear_bit(_PAGE_BIT_RW, &ptep->pte_low); }
+static inline void ptep_mkdirty(pte_t *ptep)			{ set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-i386/processor.h	Sun Apr 14 12:16:55 2002
@@ -40,7 +40,7 @@
 	char	hard_math;
 	char	rfu;
        	int	cpuid_level;	/* Maximum supported CPUID level, -1=no CPUID */
-	__u32	x86_capability[NCAPINTS];
+	unsigned long	x86_capability[NCAPINTS];
 	char	x86_vendor_id[16];
 	char	x86_model_id[64];
 	int 	x86_cache_size;  /* in KB - valid for CPUS which support this
@@ -59,6 +59,7 @@
 #define X86_VENDOR_CENTAUR 5
 #define X86_VENDOR_RISE 6
 #define X86_VENDOR_TRANSMETA 7
+#define X86_VENDOR_NSC 8
 #define X86_VENDOR_UNKNOWN 0xff
 
 /*
@@ -216,7 +217,7 @@
 }
 
 /*
- *      Cyrix CPU configuration register indexes
+ *      NSC/Cyrix CPU configuration register indexes
  */
 #define CX86_CCR0 0xc0
 #define CX86_CCR1 0xc1
@@ -232,7 +233,7 @@
 #define CX86_RCR_BASE 0xdc
 
 /*
- *      Cyrix CPU indexed register access macros
+ *      NSC/Cyrix CPU indexed register access macros
  */
 
 #define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
diff -Nru a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h
--- a/include/asm-i386/rwsem.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-i386/rwsem.h	Sun Apr 14 12:16:58 2002
@@ -164,7 +164,7 @@
 		"  jmp       1b\n"
 		LOCK_SECTION_END
 		"# ending __up_read\n"
-		: "+m"(sem->count), "+d"(tmp)
+		: /*"+m"(sem->count),*/ "+d"(tmp)
 		: "a"(sem)
 		: "memory", "cc");
 }
diff -Nru a/include/asm-i386/string-486.h b/include/asm-i386/string-486.h
--- a/include/asm-i386/string-486.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-i386/string-486.h	Sun Apr 14 12:16:57 2002
@@ -5,7 +5,7 @@
  * This string-include defines all string functions as inline
  * functions. Use gcc. It also assumes ds=es=data space, this should be
  * normal. Most of the string-functions are rather heavily hand-optimized,
- * see especially strtok,strstr,str[c]spn. They should work, but are not
+ * see especially strsep,strstr,str[c]spn. They should work, but are not
  * very easy to understand. Everything is done entirely within the register
  * set, making the functions fast and clean. 
  *
diff -Nru a/include/asm-i386/string.h b/include/asm-i386/string.h
--- a/include/asm-i386/string.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-i386/string.h	Sun Apr 14 12:16:58 2002
@@ -20,7 +20,7 @@
  * This string-include defines all string functions as inline
  * functions. Use gcc. It also assumes ds=es=data space, this should be
  * normal. Most of the string-functions are rather heavily hand-optimized,
- * see especially strtok,strstr,str[c]spn. They should work, but are not
+ * see especially strsep,strstr,str[c]spn. They should work, but are not
  * very easy to understand. Everything is done entirely within the register
  * set, making the functions fast and clean. String instructions have been
  * used through-out, making for "slightly" unclear code :-)
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-i386/thread_info.h	Sun Apr 14 12:16:55 2002
@@ -23,7 +23,7 @@
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
-	__u32			flags;		/* low level flags */
+	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
 	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
 
@@ -46,6 +46,8 @@
 #define TI_ADDR_LIMIT	0x00000014
 
 #endif
+
+#define PREEMPT_ACTIVE		0x4000000
 
 /*
  * macros/functions for gaining access to the thread information structure
diff -Nru a/include/asm-i386/timex.h b/include/asm-i386/timex.h
--- a/include/asm-i386/timex.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-i386/timex.h	Sun Apr 14 12:16:57 2002
@@ -9,7 +9,12 @@
 #include <linux/config.h>
 #include <asm/msr.h>
 
-#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#ifdef CONFIG_MELAN
+#  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
+#else
+#  define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
+#endif
+
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
 #define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
 	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
diff -Nru a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/tlbflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,144 @@
+#ifndef _I386_TLBFLUSH_H
+#define _I386_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+#define __flush_tlb()							\
+	do {								\
+		unsigned int tmpreg;					\
+									\
+		__asm__ __volatile__(					\
+			"movl %%cr3, %0;  # flush TLB \n"		\
+			"movl %0, %%cr3;              \n"		\
+			: "=r" (tmpreg)					\
+			:: "memory");					\
+	} while (0)
+
+/*
+ * Global pages have to be flushed a bit differently. Not a real
+ * performance problem because this does not happen often.
+ */
+#define __flush_tlb_global()						\
+	do {								\
+		unsigned int tmpreg;					\
+									\
+		__asm__ __volatile__(					\
+			"movl %1, %%cr4;  # turn off PGE     \n"	\
+			"movl %%cr3, %0;  # flush TLB        \n"	\
+			"movl %0, %%cr3;                     \n"	\
+			"movl %2, %%cr4;  # turn PGE back on \n"	\
+			: "=&r" (tmpreg)				\
+			: "r" (mmu_cr4_features & ~X86_CR4_PGE),	\
+			  "r" (mmu_cr4_features)			\
+			: "memory");					\
+	} while (0)
+
+extern unsigned long pgkern_mask;
+
+/*
+ * Do not check the PGE bit unnecesserily if this is a PPro+ kernel.
+ */
+#ifdef CONFIG_X86_PGE
+# define __flush_tlb_all() __flush_tlb_global()
+#else
+# define __flush_tlb_all()						\
+	do {								\
+		if (cpu_has_pge)					\
+			__flush_tlb_global();				\
+		else							\
+			__flush_tlb();					\
+	} while (0)
+#endif
+
+#ifndef CONFIG_X86_INVLPG
+#define __flush_tlb_one(addr) __flush_tlb()
+#else
+#define __flush_tlb_one(addr) \
+__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
+#endif
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ *
+ * ..but the i386 has somewhat limited tlb flushing capabilities,
+ * and page-granular flushes are available only on i486 and up.
+ */
+
+#ifndef CONFIG_SMP
+
+#define flush_tlb() __flush_tlb()
+#define flush_tlb_all() __flush_tlb_all()
+#define local_flush_tlb() __flush_tlb()
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	if (mm == current->active_mm)
+		__flush_tlb();
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+	unsigned long addr)
+{
+	if (vma->vm_mm == current->active_mm)
+		__flush_tlb_one(addr);
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+	unsigned long start, unsigned long end)
+{
+	if (vma->vm_mm == current->active_mm)
+		__flush_tlb();
+}
+
+#else
+
+#include <asm/smp.h>
+
+#define local_flush_tlb() \
+	__flush_tlb()
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_current_task(void);
+extern void flush_tlb_mm(struct mm_struct *);
+extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+
+#define flush_tlb()	flush_tlb_current_task()
+
+static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
+{
+	flush_tlb_mm(vma->vm_mm);
+}
+
+#define TLBSTATE_OK	1
+#define TLBSTATE_LAZY	2
+
+struct tlb_state
+{
+	struct mm_struct *active_mm;
+	int state;
+	char __cacheline_padding[24];
+};
+extern struct tlb_state cpu_tlbstate[NR_CPUS];
+
+
+#endif
+
+#define flush_tlb_kernel_range(start, end) flush_tlb_all()
+
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+	/* i386 does not keep any page table caches in TLB */
+}
+
+#endif /* _I386_TLBFLUSH_H */
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-i386/unistd.h	Sun Apr 14 12:16:59 2002
@@ -245,6 +245,8 @@
 #define __NR_tkill		238
 #define __NR_sendfile64		239
 #define __NR_futex		240
+#define __NR_sched_setaffinity	241
+#define __NR_sched_getaffinity	242
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
@@ -370,5 +372,13 @@
 }
 
 #endif
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
 #endif /* _ASM_I386_UNISTD_H_ */
diff -Nru a/include/asm-ia64/efi.h b/include/asm-ia64/efi.h
--- a/include/asm-ia64/efi.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ia64/efi.h	Sun Apr 14 12:16:58 2002
@@ -32,13 +32,18 @@
 typedef u8 efi_bool_t;
 typedef u16 efi_char16_t;		/* UNICODE character */
 
+
 typedef struct {
-	u32 data1;
-	u16 data2;
-	u16 data3;
-	u8 data4[8];
+	u8 b[16];
 } efi_guid_t;
 
+#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
+((efi_guid_t) \
+{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
+  (b) & 0xff, ((b) >> 8) & 0xff, \
+  (c) & 0xff, ((c) >> 8) & 0xff, \
+  (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
+
 /*
  * Generic EFI table header
  */
@@ -165,21 +170,23 @@
 /*
  *  EFI Configuration Table and GUID definitions
  */
+#define NULL_GUID \
+    EFI_GUID(  0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
 
 #define MPS_TABLE_GUID    \
-    ((efi_guid_t) { 0xeb9d2d2f, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+    EFI_GUID(  0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
 #define ACPI_TABLE_GUID    \
-    ((efi_guid_t) { 0xeb9d2d30, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+    EFI_GUID(  0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
 #define ACPI_20_TABLE_GUID    \
-    ((efi_guid_t) { 0x8868e871, 0xe4f1, 0x11d3, { 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }})
+    EFI_GUID(  0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
 
 #define SMBIOS_TABLE_GUID    \
-    ((efi_guid_t) { 0xeb9d2d31, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+    EFI_GUID(  0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
 #define SAL_SYSTEM_TABLE_GUID    \
-    ((efi_guid_t) { 0xeb9d2d32, 0x2d88, 0x11d3, { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }})
+    EFI_GUID(  0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
 typedef struct {
 	efi_guid_t guid;
@@ -231,6 +238,17 @@
 efi_guidcmp (efi_guid_t left, efi_guid_t right)
 {
 	return memcmp(&left, &right, sizeof (efi_guid_t));
+}
+
+static inline char *
+efi_guid_unparse(efi_guid_t *guid, char *out)
+{
+	sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+		guid->b[3], guid->b[2], guid->b[1], guid->b[0],
+		guid->b[5], guid->b[4], guid->b[7], guid->b[6],
+		guid->b[8], guid->b[9], guid->b[10], guid->b[11],
+		guid->b[12], guid->b[13], guid->b[14], guid->b[15]);
+        return out;
 }
 
 extern void efi_init (void);
diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
--- a/include/asm-ia64/sal.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ia64/sal.h	Sun Apr 14 12:16:58 2002
@@ -241,32 +241,32 @@
 
 /* SAL Error Record Section GUID Definitions */
 #define SAL_PROC_DEV_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf1, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID ( 0xe429faf1, 0x3cb7, 0x11d4,  0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_MEM_DEV_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf2, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf2, 0x3cb7, 0x11d4,  0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_SEL_DEV_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf3, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_PCI_BUS_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf4, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf5, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_PCI_COMP_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf6, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_SPECIFIC_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf7, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_HOST_CTLR_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf8, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 #define SAL_PLAT_BUS_ERR_SECT_GUID  \
-    ((efi_guid_t) { 0xe429faf9, 0x3cb7, 0x11d4, { 0xbc, 0xa7, 0x0, 0x80, \
-                    0xc7, 0x3c, 0x88, 0x81 }} )
+    EFI_GUID(  0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \
+                    0xc7, 0x3c, 0x88, 0x81 )
 
 #define MAX_CACHE_ERRORS			6
 #define MAX_TLB_ERRORS				6
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ia64/unistd.h	Sun Apr 14 12:16:55 2002
@@ -325,5 +325,14 @@
 }
 
 #endif /* __KERNEL_SYSCALLS__ */
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_UNISTD_H */
diff -Nru a/include/asm-m68k/string.h b/include/asm-m68k/string.h
--- a/include/asm-m68k/string.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-m68k/string.h	Sun Apr 14 12:16:59 2002
@@ -117,29 +117,6 @@
 }
 #endif
 
-#if 0
-#define __HAVE_ARCH_STRTOK
-extern inline char * strtok(char * s,const char * ct)
-{
-  char *sbegin, *send;
-  
-  sbegin  = s ? s : ___strtok;
-  if (!sbegin) {
-	  return NULL;
-  }
-  sbegin += strspn(sbegin,ct);
-  if (*sbegin == '\0') {
-    ___strtok = NULL;
-    return( NULL );
-  }
-  send = strpbrk( sbegin, ct);
-  if (send && *send != '\0')
-    *send++ = '\0';
-  ___strtok = send;
-  return (sbegin);
-}
-#endif
-
 /* strstr !! */
 
 #define __HAVE_ARCH_STRLEN
diff -Nru a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
--- a/include/asm-m68k/unistd.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-m68k/unistd.h	Sun Apr 14 12:16:58 2002
@@ -357,4 +357,12 @@
 
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_M68K_UNISTD_H_ */
diff -Nru a/include/asm-mips/spinlock.h b/include/asm-mips/spinlock.h
--- a/include/asm-mips/spinlock.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-mips/spinlock.h	Sun Apr 14 12:16:59 2002
@@ -19,10 +19,10 @@
 
 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
 
-#define spin_lock_init(x)	do { (x)->lock = 0; } while(0);
+#define spin_lock_init(x)	do { (x)->lock = 0; } while(0)
 
 #define spin_is_locked(x)	((x)->lock != 0)
-#define spin_unlock_wait(x)	({ do { barrier(); } while ((x)->lock); })
+#define spin_unlock_wait(x)	do { barrier(); } while ((x)->lock)
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
diff -Nru a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
--- a/include/asm-mips/unistd.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-mips/unistd.h	Sun Apr 14 12:16:54 2002
@@ -488,4 +488,12 @@
 #endif /* !defined (__KERNEL_SYSCALLS__) */
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_UNISTD_H */
diff -Nru a/include/asm-mips64/spinlock.h b/include/asm-mips64/spinlock.h
--- a/include/asm-mips64/spinlock.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-mips64/spinlock.h	Sun Apr 14 12:16:58 2002
@@ -19,10 +19,10 @@
 
 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
 
-#define spin_lock_init(x)	do { (x)->lock = 0; } while(0);
+#define spin_lock_init(x)	do { (x)->lock = 0; } while(0)
 
 #define spin_is_locked(x)	((x)->lock != 0)
-#define spin_unlock_wait(x)	({ do { barrier(); } while ((x)->lock); })
+#define spin_unlock_wait(x)	do { barrier(); } while ((x)->lock)
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
diff -Nru a/include/asm-mips64/unistd.h b/include/asm-mips64/unistd.h
--- a/include/asm-mips64/unistd.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-mips64/unistd.h	Sun Apr 14 12:16:56 2002
@@ -814,4 +814,12 @@
 #endif /* !defined (__KERNEL_SYSCALLS__) */
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_UNISTD_H */
diff -Nru a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h
--- a/include/asm-parisc/pgalloc.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-parisc/pgalloc.h	Sun Apr 14 12:16:59 2002
@@ -123,7 +123,7 @@
 #define flush_tlb() do { \
         flush_data_tlb(); \
 	flush_instruction_tlb(); \
-} while(0);
+} while(0)
 
 #define flush_tlb_all() 	flush_tlb()	/* XXX p[id]tlb */
 
diff -Nru a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
--- a/include/asm-parisc/unistd.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-parisc/unistd.h	Sun Apr 14 12:16:54 2002
@@ -900,4 +900,12 @@
 
 #undef STR
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_PARISC_UNISTD_H_ */
diff -Nru a/include/asm-ppc/bitops.h b/include/asm-ppc/bitops.h
--- a/include/asm-ppc/bitops.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc/bitops.h	Sun Apr 14 12:16:58 2002
@@ -394,8 +394,8 @@
 
 #ifdef __KERNEL__
 
-#define ext2_set_bit(nr, addr)		__test_and_set_bit((nr) ^ 0x18, addr)
-#define ext2_clear_bit(nr, addr)	__test_and_clear_bit((nr) ^ 0x18, addr)
+#define ext2_set_bit(nr, addr)	__test_and_set_bit((nr) ^ 0x18, (unsigned long *)(addr))
+#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 0x18, (unsigned long *)(addr))
 
 static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
 {
diff -Nru a/include/asm-ppc/cacheflush.h b/include/asm-ppc/cacheflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc/cacheflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,41 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * include/asm-ppc/cacheflush.h
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+#ifdef __KERNEL__
+#ifndef _PPC_CACHEFLUSH_H
+#define _PPC_CACHEFLUSH_H
+
+#include <linux/mm.h>
+
+/*
+ * No cache flushing is required when address mappings are
+ * changed, because the caches on PowerPCs are physically
+ * addressed.  -- paulus
+ * Also, when SMP we use the coherency (M) bit of the
+ * BATs and PTEs.  -- Cort
+ */
+#define flush_cache_all()		do { } while (0)
+#define flush_cache_mm(mm)		do { } while (0)
+#define flush_cache_range(vma, a, b)	do { } while (0)
+#define flush_cache_page(vma, p)	do { } while (0)
+#define flush_page_to_ram(page)		do { } while (0)
+
+extern void flush_dcache_page(struct page *page);
+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+extern void flush_icache_range(unsigned long, unsigned long);
+extern void flush_icache_user_range(struct vm_area_struct *vma,
+		struct page *page, unsigned long addr, int len);
+
+extern void __flush_dcache_icache(void *page_va);
+extern void __flush_dcache_icache_phys(unsigned long physaddr);
+
+#endif _PPC_CACHEFLUSH_H
+#endif __KERNEL__
diff -Nru a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h
--- a/include/asm-ppc/highmem.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc/highmem.h	Sun Apr 14 12:16:58 2002
@@ -28,7 +28,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/kmap_types.h>
-#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 /* undef for production */
 #define HIGHMEM_DEBUG 1
diff -Nru a/include/asm-ppc/percpu.h b/include/asm-ppc/percpu.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc/percpu.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,6 @@
+#ifndef __ARCH_PPC_PERCPU__
+#define __ARCH_PPC_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_PPC_PERCPU__ */
diff -Nru a/include/asm-ppc/pgalloc.h b/include/asm-ppc/pgalloc.h
--- a/include/asm-ppc/pgalloc.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-ppc/pgalloc.h	Sun Apr 14 12:16:54 2002
@@ -7,24 +7,12 @@
 
 #include <linux/config.h>
 #include <linux/threads.h>
-#include <linux/highmem.h>
 #include <asm/processor.h>
 
 extern void __bad_pte(pmd_t *pmd);
 
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	pgd_t *ret;
-
-	if ((ret = (pgd_t *)__get_free_page(GFP_KERNEL)) != NULL)
-		clear_page(ret);
-	return ret;
-}
-
-extern __inline__ void pgd_free(pgd_t *pgd)
-{
-	free_page((unsigned long)pgd);
-}
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(pgd_t *pgd);
 
 /*
  * We don't have any real pmd's, and this code never triggers because
@@ -34,64 +22,17 @@
 #define pmd_free(x)                     do { } while (0)
 #define pgd_populate(mm, pmd, pte)      BUG()
 
-static inline pte_t *
-pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
-	pte_t *pte;
-	extern int mem_init_done;
-	extern void *early_get_page(void);
-	int timeout = 0;
-
-	if (mem_init_done) {
-		while ((pte = (pte_t *) __get_free_page(GFP_KERNEL)) == NULL
-		       && ++timeout < 10) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ);
-		}
-	} else
-		pte = (pte_t *) early_get_page();
-	if (pte != NULL)
-		clear_page(pte);
-	return pte;
-}
-
-static inline struct page *
-pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
-	struct page *pte;
-	int timeout = 0;
-#ifdef CONFIG_HIGHPTE
-	int flags = GFP_KERNEL | __GFP_HIGHMEM;
-#else
-	int flags = GFP_KERNEL;
-#endif
-
-	while ((pte = alloc_pages(flags, 0)) == NULL) {
-		if (++timeout >= 10)
-			return NULL;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ);
-	}
-	clear_highpage(pte);
-	return pte;
-}
-
-static inline void pte_free_kernel(pte_t *pte)
-{
-	free_page((unsigned long)pte);
-}
-
-static inline void pte_free(struct page *pte)
-{
-	__free_page(pte);
-}
-
 #define pmd_populate_kernel(mm, pmd, pte)	\
 		(pmd_val(*(pmd)) = __pa(pte))
 #define pmd_populate(mm, pmd, pte)	\
 		(pmd_val(*(pmd)) = ((pte) - mem_map) << PAGE_SHIFT)
 
-extern int do_check_pgt_cache(int, int);
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+extern void pte_free_kernel(pte_t *pte);
+extern void pte_free(struct page *pte);
+
+#define check_pgt_cache()	do { } while (0)
 
 #endif /* _PPC_PGALLOC_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
--- a/include/asm-ppc/pgtable.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-ppc/pgtable.h	Sun Apr 14 12:16:56 2002
@@ -13,95 +13,6 @@
 #include <asm/processor.h>		/* For TASK_SIZE */
 #include <asm/mmu.h>
 #include <asm/page.h>
-#include <asm/kmap_types.h>
-
-extern void _tlbie(unsigned long address);
-extern void _tlbia(void);
-
-#if defined(CONFIG_4xx)
-#define __tlbia()	asm volatile ("tlbia; sync" : : : "memory")
-
-static inline void local_flush_tlb_all(void)
-	{ __tlbia(); }
-static inline void local_flush_tlb_mm(struct mm_struct *mm)
-	{ __tlbia(); }
-static inline void local_flush_tlb_page(struct vm_area_struct *vma,
-				unsigned long vmaddr)
-	{ _tlbie(vmaddr); }
-static inline void local_flush_tlb_range(struct mm_struct *mm,
-				unsigned long start, unsigned long end)
-	{ __tlbia(); }
-#define update_mmu_cache(vma, addr, pte)	do { } while (0)
-
-#elif defined(CONFIG_8xx)
-#define __tlbia()	asm volatile ("tlbia; sync" : : : "memory")
-
-static inline void local_flush_tlb_all(void)
-	{ __tlbia(); }
-static inline void local_flush_tlb_mm(struct mm_struct *mm)
-	{ __tlbia(); }
-static inline void local_flush_tlb_page(struct vm_area_struct *vma,
-				unsigned long vmaddr)
-	{ _tlbie(vmaddr); }
-static inline void local_flush_tlb_range(struct mm_struct *mm,
-				unsigned long start, unsigned long end)
-	{ __tlbia(); }
-#define update_mmu_cache(vma, addr, pte)	do { } while (0)
-
-#else	/* 6xx, 7xx, 7xxx cpus */
-struct mm_struct;
-struct vm_area_struct;
-extern void local_flush_tlb_all(void);
-extern void local_flush_tlb_mm(struct mm_struct *mm);
-extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-			    unsigned long end);
-
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to put a corresponding HPTE into the hash table
- * ahead of time, instead of waiting for the inevitable extra
- * hash-table miss exception.
- */
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-#endif
-
-#define flush_tlb_all local_flush_tlb_all
-#define flush_tlb_mm local_flush_tlb_mm
-#define flush_tlb_page local_flush_tlb_page
-#define flush_tlb_range local_flush_tlb_range
-
-/*
- * This is called in munmap when we have freed up some page-table
- * pages.  We don't need to do anything here, there's nothing special
- * about our page-table pages.  -- paulus
- */
-static inline void flush_tlb_pgtables(struct mm_struct *mm,
-				      unsigned long start, unsigned long end)
-{
-}
-
-/*
- * No cache flushing is required when address mappings are
- * changed, because the caches on PowerPCs are physically
- * addressed.  -- paulus
- * Also, when SMP we use the coherency (M) bit of the
- * BATs and PTEs.  -- Cort
- */
-#define flush_cache_all()		do { } while (0)
-#define flush_cache_mm(mm)		do { } while (0)
-#define flush_cache_range(vma, a, b)	do { } while (0)
-#define flush_cache_page(vma, p)	do { } while (0)
-#define flush_page_to_ram(page)		do { } while (0)
-
-extern void flush_icache_user_range(struct vm_area_struct *vma,
-		struct page *page, unsigned long addr, int len);
-extern void flush_icache_range(unsigned long, unsigned long);
-extern void __flush_dcache_icache(void *page_va);
-extern void __flush_dcache_icache_phys(unsigned long physaddr);
-extern void flush_dcache_page(struct page *page);
-extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
 
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
diff -Nru a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
--- a/include/asm-ppc/thread_info.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-ppc/thread_info.h	Sun Apr 14 12:16:56 2002
@@ -68,6 +68,8 @@
 #define TI_FLAGS	8
 #define TI_CPU		12
 
+#define PREEMPT_ACTIVE		0x4000000
+
 /*
  * thread information flag bit numbers
  */
diff -Nru a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc/tlbflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,90 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * include/asm-ppc/tlbflush.h
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+#ifdef __KERNEL__
+#ifndef _PPC_TLBFLUSH_H
+#define _PPC_TLBFLUSH_H
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <asm/processor.h>
+
+extern void _tlbie(unsigned long address);
+extern void _tlbia(void);
+
+#if defined(CONFIG_4xx)
+#define __tlbia()	asm volatile ("tlbia; sync" : : : "memory")
+
+static inline void flush_tlb_all(void)
+	{ __tlbia(); }
+static inline void flush_tlb_mm(struct mm_struct *mm)
+	{ __tlbia(); }
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				unsigned long vmaddr)
+	{ _tlbie(vmaddr); }
+static inline void flush_tlb_range(struct mm_struct *mm,
+				unsigned long start, unsigned long end)
+	{ __tlbia(); }
+static inline void flush_tlb_kernel_range(unsigned long start,
+				unsigned long end)
+	{ __tlbia(); }
+#define update_mmu_cache(vma, addr, pte)	do { } while (0)
+
+#elif defined(CONFIG_8xx)
+#define __tlbia()	asm volatile ("tlbia; sync" : : : "memory")
+
+static inline void flush_tlb_all(void)
+	{ __tlbia(); }
+static inline void flush_tlb_mm(struct mm_struct *mm)
+	{ __tlbia(); }
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				unsigned long vmaddr)
+	{ _tlbie(vmaddr); }
+static inline void flush_tlb_range(struct mm_struct *mm,
+				unsigned long start, unsigned long end)
+	{ __tlbia(); }
+static inline void flush_tlb_kernel_range(unsigned long start,
+				unsigned long end)
+	{ __tlbia(); }
+#define update_mmu_cache(vma, addr, pte)	do { } while (0)
+
+#else	/* 6xx, 7xx, 7xxx cpus */
+struct mm_struct;
+struct vm_area_struct;
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			    unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+/*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to put a corresponding HPTE into the hash table
+ * ahead of time, instead of waiting for the inevitable extra
+ * hash-table miss exception.
+ */
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+#endif
+
+/*
+ * This is called in munmap when we have freed up some page-table
+ * pages.  We don't need to do anything here, there's nothing special
+ * about our page-table pages.  -- paulus
+ */
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+}
+
+#endif _PPC_TLBFLUSH_H
+#endif __KERNEL__
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-ppc/unistd.h	Sun Apr 14 12:16:56 2002
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.unistd.h 1.11 10/18/01 17:29:53 trini
+ * BK Id: %F% %I% %G% %U% %#%
  */
 #ifndef _ASM_PPC_UNISTD_H_
 #define _ASM_PPC_UNISTD_H_
@@ -229,6 +229,8 @@
 #define __NR_lremovexattr	219
 #define __NR_fremovexattr	220
 #define __NR_futex		221
+#define __NR_sched_setaffinity	222
+#define __NR_sched_getaffinity	223
 
 #define __NR(n)	#n
 
@@ -432,9 +434,17 @@
 
 static inline pid_t wait(int * wait_stat) 
 {
-	return waitpid(-1,wait_stat,0);
+	return waitpid(-1, wait_stat, 0);
 }
 
 #endif /* __KERNEL_SYSCALLS__ */
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
 #endif /* _ASM_PPC_UNISTD_H_ */
diff -Nru a/include/asm-ppc64/Paca.h b/include/asm-ppc64/Paca.h
--- a/include/asm-ppc64/Paca.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-ppc64/Paca.h	Sun Apr 14 12:16:57 2002
@@ -92,10 +92,10 @@
  * CACHE_LINE_2 0x0080 - 0x00FF
  *=====================================================================================
  */
-	u64 *pgd_cache;			/*					0x00 */
-	u64 *pmd_cache;			/*					0x08 */
-	u64 *pte_cache;			/*					0x10 */
-	u64 pgtable_cache_sz;		/*					0x18 */
+	u64 spare1;			/*					0x00 */
+	u64 spare2;			/*					0x08 */
+	u64 spare3;			/*					0x10 */
+	u64 spare4;		/*					0x18 */
 	u64 next_jiffy_update_tb;	/* TB value for next jiffy update	0x20 */
 	u32 lpEvent_count;		/* lpEvents processed			0x28 */
 	u32 prof_multiplier;		/*					0x2C */
diff -Nru a/include/asm-ppc64/abs_addr.h b/include/asm-ppc64/abs_addr.h
--- a/include/asm-ppc64/abs_addr.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-ppc64/abs_addr.h	Sun Apr 14 12:16:57 2002
@@ -103,7 +103,7 @@
 #define physRpn_to_absRpn(rpn) (rpn)
 #define absolute_to_phys(aa) (aa)
 
-#endif /* CONFIG_MSCHUNKS */
+#endif /* !CONFIG_MSCHUNKS */
 
 
 static inline unsigned long
diff -Nru a/include/asm-ppc64/cacheflush.h b/include/asm-ppc64/cacheflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc64/cacheflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,26 @@
+#ifndef _PPC64_CACHEFLUSH_H
+#define _PPC64_CACHEFLUSH_H
+
+/* Keep includes the same across arches.  */
+#include <linux/mm.h>
+
+/*
+ * No cache flushing is required when address mappings are
+ * changed, because the caches on PowerPCs are physically
+ * addressed.
+ */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+
+extern void flush_dcache_page(struct page *page);
+extern void flush_icache_range(unsigned long, unsigned long);
+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+extern void flush_icache_user_range(struct vm_area_struct *vma,
+				    struct page *page, unsigned long addr,
+				    int len);
+extern void __flush_dcache_icache(void *page_va);
+
+#endif /* _PPC64_CACHEFLUSH_H */
diff -Nru a/include/asm-ppc64/floppy.h b/include/asm-ppc64/floppy.h
--- a/include/asm-ppc64/floppy.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-ppc64/floppy.h	Sun Apr 14 12:16:56 2002
@@ -36,8 +36,6 @@
 
 #define fd_dma_setup(addr,size,mode,io) ppc64_fd_dma_setup(addr,size,mode,io)
 
-extern struct pci_dev *ppc64_floppy_dev;
-
 static __inline__ int 
 ppc64_fd_dma_setup(char *addr, unsigned long size, int mode, int io)
 {
@@ -52,12 +50,12 @@
 	if (bus_addr 
 	    && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
 		/* different from last time -- unmap prev */
-		pci_unmap_single(ppc64_floppy_dev, bus_addr, prev_size, prev_dir);
+		pci_unmap_single(NULL, bus_addr, prev_size, prev_dir);
 		bus_addr = 0;
 	}
 
 	if (!bus_addr)	/* need to map it */ {
-		bus_addr = pci_map_single(ppc64_floppy_dev, addr, size, dir);
+		bus_addr = pci_map_single(NULL, addr, size, dir);
 	}
 
 	/* remember this one as prev */
diff -Nru a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h
--- a/include/asm-ppc64/hw_irq.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc64/hw_irq.h	Sun Apr 14 12:16:58 2002
@@ -35,13 +35,13 @@
 #else
 
 #define __save_flags(flags)	((flags) = mfmsr())
-#define __restore_flags(flags)	mtmsrd(flags)
+#define __restore_flags(flags)	__mtmsrd((flags), 1)
 
 static inline void __cli(void)
 {
 	unsigned long msr;
 	msr = mfmsr();
-	mtmsrd(msr & ~MSR_EE);
+	__mtmsrd(msr & ~MSR_EE, 1);
 	__asm__ __volatile__("": : :"memory");
 }
 
@@ -50,7 +50,7 @@
 	unsigned long msr;
 	__asm__ __volatile__("": : :"memory");
 	msr = mfmsr();
-	mtmsrd(msr | MSR_EE);
+	__mtmsrd(msr | MSR_EE, 1);
 }
 
 static inline void __do_save_and_cli(unsigned long *flags)
@@ -58,7 +58,7 @@
 	unsigned long msr;
 	msr = mfmsr();
 	*flags = msr;
-	mtmsrd(msr & ~MSR_EE);
+	__mtmsrd(msr & ~MSR_EE, 1);
 	__asm__ __volatile__("": : :"memory");
 }
 
diff -Nru a/include/asm-ppc64/iSeries/HvCallPci.h b/include/asm-ppc64/iSeries/HvCallPci.h
--- a/include/asm-ppc64/iSeries/HvCallPci.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ppc64/iSeries/HvCallPci.h	Sun Apr 14 12:16:55 2002
@@ -97,6 +97,8 @@
 	struct HvCallPci_BusUnitInfo busUnitInfo;  // Generic bus unit info
 	u8		subBusNumber;		// Bus number of secondary bus
 	u8		maxAgents;		// Max idsels on secondary bus
+        u8              maxSubBusNumber;        // Max Sub Bus
+	u8		logicalSlotNumber;	// Logical Slot Number for IOA 
 };
     
 
diff -Nru a/include/asm-ppc64/linux_logo.h b/include/asm-ppc64/linux_logo.h
--- a/include/asm-ppc64/linux_logo.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-ppc64/linux_logo.h	Sun Apr 14 12:16:57 2002
@@ -22,25 +22,5 @@
 
 #define LINUX_LOGO_HEIGHT	80
 #define LINUX_LOGO_WIDTH	80
-#define LINUX_LOGO_COLORS	214
 
-#ifdef INCLUDE_LINUX_LOGO_DATA
-
-#define INCLUDE_LINUX_LOGOBW
-#define INCLUDE_LINUX_LOGO16
 #include <linux/linux_logo.h>
-
-#else
-
-/* prototypes only */
-extern unsigned char linux_logo_red[];
-extern unsigned char linux_logo_green[];
-extern unsigned char linux_logo_blue[];
-extern unsigned char linux_logo[];
-extern unsigned char linux_logo_bw[];
-extern unsigned char linux_logo16_red[];
-extern unsigned char linux_logo16_green[];
-extern unsigned char linux_logo16_blue[];
-extern unsigned char linux_logo16[];
-
-#endif
diff -Nru a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
--- a/include/asm-ppc64/lmb.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-ppc64/lmb.h	Sun Apr 14 12:16:56 2002
@@ -17,7 +17,7 @@
 
 extern unsigned long reloc_offset(void);
 
-#define MAX_LMB_REGIONS 32
+#define MAX_LMB_REGIONS 64
 
 union lmb_reg_property { 
 	struct reg_property32 addr32[MAX_LMB_REGIONS];
@@ -37,6 +37,7 @@
 struct lmb_region {
 	unsigned long cnt;
 	unsigned long size;
+	unsigned long iosize;
 	unsigned long lcd_size;		/* Least Common Denominator */
 	struct lmb_property region[MAX_LMB_REGIONS+1];
 };
@@ -52,7 +53,9 @@
 extern void lmb_init(void);
 extern void lmb_analyze(void);
 extern long lmb_add(unsigned long, unsigned long);
+#ifdef CONFIG_MSCHUNKS
 extern long lmb_add_io(unsigned long base, unsigned long size);
+#endif /* CONFIG_MSCHUNKS */
 extern long lmb_reserve(unsigned long, unsigned long);
 extern unsigned long lmb_alloc(unsigned long, unsigned long);
 extern unsigned long lmb_phys_mem_size(void);
diff -Nru a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
--- a/include/asm-ppc64/machdep.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-ppc64/machdep.h	Sun Apr 14 12:16:57 2002
@@ -24,26 +24,33 @@
 	/* High use functions in the first cachelines, low use functions
 	 * follow.  DRENG collect profile data.
 	 */
-	void            (*hpte_invalidate)(unsigned long slot);
-
-	void            (*hpte_updatepp)(long slot, 
+	void            (*hpte_invalidate)(unsigned long slot,
+					   unsigned long va,
+					   int large,
+					   int local);
+	long		(*hpte_updatepp)(unsigned long slot, 
 					 unsigned long newpp, 
-					 unsigned long va);
+					 unsigned long va,
+					 int large);
 	void            (*hpte_updateboltedpp)(unsigned long newpp, 
 					       unsigned long ea);
-	unsigned long	(*hpte_getword0)(unsigned long slot);
-
-	long		(*hpte_find)( unsigned long vpn );
-
-	long		(*hpte_selectslot)(unsigned long vpn); 
+	long		(*insert_hpte)(unsigned long hpte_group,
+				       unsigned long vpn,
+				       unsigned long prpn,
+				       int secondary, 
+				       unsigned long hpteflags, 
+				       int bolted,
+				       int large);
+	long		(*remove_hpte)(unsigned long hpte_group);
+	void		(*flush_hash_range)(unsigned long context,
+					    unsigned long number,
+					    int local);
+	void		(*make_pte)(void *htab, unsigned long va,
+				    unsigned long pa,
+				    int mode,
+				    unsigned long hash_mask,
+				    int large);
 
-	void		(*hpte_create_valid)(unsigned long slot,
-					     unsigned long vpn,
-					     unsigned long prpn,
-					     unsigned hash, 
-					     void * ptep,
-					     unsigned hpteflags, 
-					     unsigned bolted);
 	void		(*tce_build)(struct TceTable * tbl,
 				     long tcenum,
 				     unsigned long uaddr,
@@ -147,18 +154,6 @@
 extern char cmd_line[512];
 
 extern void setup_pci_ptrs(void);
-
-/*
- * Power macintoshes have either a CUDA or a PMU controlling
- * system reset, power, NVRAM, RTC.
- */
-typedef enum sys_ctrler_kind {
-	SYS_CTRLER_UNKNOWN = 0,
-	SYS_CTRLER_CUDA = 1,
-	SYS_CTRLER_PMU = 2,
-} sys_ctrler_t;
-
-extern sys_ctrler_t sys_ctrler;
 
 #endif /* _PPC_MACHDEP_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc64/mman.h b/include/asm-ppc64/mman.h
--- a/include/asm-ppc64/mman.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc64/mman.h	Sun Apr 14 12:16:58 2002
@@ -11,6 +11,7 @@
 #define PROT_READ	0x1		/* page can be read */
 #define PROT_WRITE	0x2		/* page can be written */
 #define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_SEM	0x8		/* page may be used for atomic ops */
 #define PROT_NONE	0x0		/* page can not be accessed */
 
 #define MAP_SHARED	0x01		/* Share changes */
diff -Nru a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
--- a/include/asm-ppc64/mmu.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ppc64/mmu.h	Sun Apr 14 12:16:55 2002
@@ -77,7 +77,7 @@
 	unsigned long resv0: 7; /* Padding to a 64b boundary */
 } slb_dword1;
 
-typedef struct _SLBE {
+typedef struct {
 	union {
 		unsigned long dword0;
 		slb_dword0    dw0;
@@ -107,26 +107,13 @@
 	unsigned long avpn:57; /* vsid | api == avpn  */
 	unsigned long :     2; /* Software use */
 	unsigned long bolted: 1; /* HPTE is "bolted" */
-	unsigned long :     1; /* Software use */
-	unsigned long :     1; /* Reserved */
+	unsigned long lock: 1; /* lock on pSeries SMP */
+	unsigned long l:    1; /* Virtual page is large (L=1) or 4 KB (L=0) */
 	unsigned long h:    1; /* Hash function identifier */
 	unsigned long v:    1; /* Valid (v=1) or invalid (v=0) */
 } Hpte_dword0;
 
 typedef struct {
-	unsigned long :     6; /* unused - padding */
-	unsigned long ac:   1; /* Address compare */
-	unsigned long r:    1; /* Referenced */
-	unsigned long c:    1; /* Changed */
-	unsigned long w:	1; /* Write-thru cache mode */
-	unsigned long i:	1; /* Cache inhibited */
-	unsigned long m:	1; /* Memory coherence required */
-	unsigned long g:	1; /* Guarded */
-	unsigned long n:	1; /* No-execute */
-	unsigned long pp:   2; /* Page protection bits 1:2 */
-} Hpte_flags;
-
-typedef struct {
 	unsigned long pp0:  1; /* Page protection bit 0 */
 	unsigned long :     1; /* Reserved */
 	unsigned long rpn: 50; /* Real page number */
@@ -134,12 +121,12 @@
 	unsigned long ac:   1; /* Address compare */ 
 	unsigned long r:    1; /* Referenced */
 	unsigned long c:    1; /* Changed */
-	unsigned long w:	1; /* Write-thru cache mode */
-	unsigned long i:	1; /* Cache inhibited */
-	unsigned long m:	1; /* Memory coherence required */
-	unsigned long g:	1; /* Guarded */
-	unsigned long n:	1; /* No-execute */
-	unsigned long pp:	2; /* Page protection bits 1:2 */
+	unsigned long w:    1; /* Write-thru cache mode */
+	unsigned long i:    1; /* Cache inhibited */
+	unsigned long m:    1; /* Memory coherence required */
+	unsigned long g:    1; /* Guarded */
+	unsigned long n:    1; /* No-execute */
+	unsigned long pp:   2; /* Page protection bits 1:2 */
 } Hpte_dword1;
 
 typedef struct {
@@ -148,7 +135,7 @@
 	unsigned long flags: 10;	/* HPTE flags */
 } Hpte_dword1_flags;
 
-typedef struct _HPTE {
+typedef struct {
 	union {
 		unsigned long dword0;
 		Hpte_dword0   dw0;
@@ -156,21 +143,8 @@
 
 	union {
 		unsigned long dword1;
-		struct {
-			unsigned long pp0:  1; /* Page protection bit 0 */
-			unsigned long ts:   1; /* Tag set bit */ 
-			unsigned long rpn: 50; /* Real page number */
-			unsigned long :     2; /* Unused */
-			unsigned long ac:   1; /* Address compare bit */
-			unsigned long r:    1; /* Referenced */
-			unsigned long c:    1; /* Changed */
-			unsigned long w:    1; /* Write-thru cache mode */
-			unsigned long i:    1; /* Cache inhibited */
-			unsigned long m:    1; /* Memory coherence */
-			unsigned long g:    1; /* Guarded */
-			unsigned long n:    1; /* No-execute page if N=1 */
-			unsigned long pp:   2; /* Page protection bit 1:2 */
-		} dw1;
+		Hpte_dword1 dw1;
+		Hpte_dword1_flags flags;
 	} dw1;
 } HPTE; 
 
@@ -204,6 +178,8 @@
 #define PT_SHIFT (12)			/* Page Table */
 #define PT_MASK  0x02FF
 
+#define LARGE_PAGE_SHIFT 24
+
 static inline unsigned long hpt_hash(unsigned long vpn, int large)
 {
 	unsigned long vsid;
@@ -220,20 +196,36 @@
 	return (vsid & 0x7fffffffff) ^ page;
 }
 
-#define PG_SHIFT (12)			/* Page Entry */
+static inline void _tlbie(unsigned long va, int large)
+{
+	asm volatile("ptesync": : :"memory");
 
-extern __inline__ void _tlbie( unsigned long va )
+	if (large) {
+		asm volatile("clrldi	%0,%0,16\n\
+			      tlbie	%0,1" : : "r"(va) : "memory");
+	} else {
+		asm volatile("clrldi	%0,%0,16\n\
+			      tlbie	%0,0" : : "r"(va) : "memory");
+	}
+
+	asm volatile("eieio; tlbsync; ptesync": : :"memory");
+}
+
+static inline void _tlbiel(unsigned long va, int large)
 {
-	__asm__ __volatile__ ( " \n\
-		clrldi	%0,%0,16 \n\
-		ptesync		 \n\
-		tlbie	%0	 \n\
-		eieio		 \n\
-		tlbsync		 \n\
-		ptesync"
-		: : "r" (va) : "memory" );
+	asm volatile("ptesync": : :"memory");
+
+	if (large) {
+		asm volatile("clrldi	%0,%0,16\n\
+			      tlbiel	%0,1" : : "r"(va) : "memory");
+	} else {
+		asm volatile("clrldi	%0,%0,16\n\
+			      tlbiel	%0,0" : : "r"(va) : "memory");
+	}
+
+	asm volatile("ptesync": : :"memory");
 }
- 
+
 #endif /* __ASSEMBLY__ */
 
 /* Block size masks */
diff -Nru a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
--- a/include/asm-ppc64/mmu_context.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-ppc64/mmu_context.h	Sun Apr 14 12:16:57 2002
@@ -60,8 +60,6 @@
 {
 }
 
-extern void flush_stab(void);
-
 /*
  * The context number queue has underflowed.
  * Meaning: we tried to push a context number that was freed
@@ -133,6 +131,7 @@
 	spin_unlock( &mmu_context_queue.lock );
 }
 
+extern void flush_stab(struct task_struct *tsk, struct mm_struct *mm);
 
 /*
  * switch_mm is the entry point called from the architecture independent
@@ -142,22 +141,16 @@
 switch_mm(struct mm_struct *prev, struct mm_struct *next,
 	  struct task_struct *tsk, int cpu)
 {
-	tsk->thread.pgdir = next->pgd;	/* cache the pgdir in the thread 
-					   maybe not needed any more */
-	flush_stab();
+	flush_stab(tsk, next);
+	set_bit(cpu, &next->cpu_vm_mask);
 }
 
 /*
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
-static inline void
-activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
-{
-	current->thread.pgdir = mm->pgd;
-	flush_stab();
-}
-
+#define activate_mm(active_mm, mm) \
+	switch_mm(active_mm, mm, current, smp_processor_id());
 
 #define VSID_RANDOMIZER 42470972311
 #define VSID_MASK	0xfffffffff
diff -Nru a/include/asm-ppc64/nvram.h b/include/asm-ppc64/nvram.h
--- a/include/asm-ppc64/nvram.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc64/nvram.h	Sun Apr 14 12:16:58 2002
@@ -36,33 +36,4 @@
 #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
 #endif
 
-/* PowerMac specific nvram stuffs */
-
-enum {
-	pmac_nvram_OF,		/* Open Firmware partition */
-	pmac_nvram_XPRAM,	/* MacOS XPRAM partition */
-	pmac_nvram_NR		/* MacOS Name Registry partition */
-};
-
-/* Return partition offset in nvram */
-extern int	pmac_get_partition(int partition);
-
-/* Direct access to XPRAM */
-extern u8	pmac_xpram_read(int xpaddr);
-extern void	pmac_xpram_write(int xpaddr, u8 data);
-
-/* Some offsets in XPRAM */
-#define PMAC_XPRAM_MACHINE_LOC	0xe4
-#define PMAC_XPRAM_SOUND_VOLUME	0x08
-
-/* Machine location structure in XPRAM */
-struct pmac_machine_location {
-	u32	latitude;	/* 2+30 bit Fractional number */
-	u32	longitude;	/* 2+30 bit Fractional number */
-	u32	delta;		/* mix of GMT delta and DLS */
-};
-
-/* /dev/nvram ioctls */
-#define PMAC_NVRAM_GET_OFFSET   _IOWR('p', 0x40, int) /* Get NVRAM partition offset */
-
 #endif /* _PPC64_NVRAM_H */
diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
--- a/include/asm-ppc64/page.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-ppc64/page.h	Sun Apr 14 12:16:54 2002
@@ -130,6 +130,13 @@
 
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
+/*
+ * XXX A bug in the current ppc64 compiler prevents an optimisation
+ * where a divide is replaced by a multiply by shifted inverse. For
+ * the moment use page->virtaul
+ */
+#define WANT_PAGE_VIRTUAL 1
+
 /* Pure 2^n version of get_order */
 extern __inline__ int get_order(unsigned long size)
 {
diff -Nru a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
--- a/include/asm-ppc64/pgalloc.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ppc64/pgalloc.h	Sun Apr 14 12:16:55 2002
@@ -12,116 +12,83 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#define quicklists      get_paca()
 
-#define pgd_quicklist 		(quicklists->pgd_cache)
-#define pmd_quicklist 		(quicklists->pmd_cache)
-#define pte_quicklist 		(quicklists->pte_cache)
-#define pgtable_cache_size 	(quicklists->pgtable_cache_sz)
-
-static inline pgd_t*
-pgd_alloc_one_fast (struct mm_struct *mm)
-{
-	unsigned long *ret = pgd_quicklist;
-
-	if (ret != NULL) {
-		pgd_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		--pgtable_cache_size;
-	} else
-		ret = NULL;
-	return (pgd_t *) ret;
-}
-
-static inline pgd_t*
-pgd_alloc (struct mm_struct *mm)
-{
-	/* the VM system never calls pgd_alloc_one_fast(), so we do it here. */
-	pgd_t *pgd = pgd_alloc_one_fast(mm);
-
-	if (pgd == NULL) {
-		pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
-		if (pgd != NULL)
-			clear_page(pgd);
-	}
+static inline pgd_t *
+pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+	if (pgd != NULL)
+		clear_page(pgd);
 	return pgd;
 }
 
 static inline void
-pgd_free (pgd_t *pgd)
+pgd_free(pgd_t *pgd)
 {
-	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
-	pgd_quicklist = (unsigned long *) pgd;
-	++pgtable_cache_size;
+	free_page((unsigned long)pgd);
 }
 
 #define pgd_populate(MM, PGD, PMD)	pgd_set(PGD, PMD)
 
-static inline pmd_t*
-pmd_alloc_one_fast (struct mm_struct *mm, unsigned long addr)
+static inline pmd_t *
+pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	unsigned long *ret = (unsigned long *)pmd_quicklist;
-
-	if (ret != NULL) {
-		pmd_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		--pgtable_cache_size;
-	}
-	return (pmd_t *)ret;
-}
+	int count = 0;
+	pmd_t *pmd;
 
-static inline pmd_t*
-pmd_alloc_one (struct mm_struct *mm, unsigned long addr)
-{
-	pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+	do {
+		pmd = (pmd_t *)__get_free_page(GFP_KERNEL);
+		if (pmd)
+			clear_page(pmd);
+		else {
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+	} while (!pmd && (count++ < 10));
 
-	if (pmd != NULL)
-		clear_page(pmd);
 	return pmd;
 }
 
 static inline void
-pmd_free (pmd_t *pmd)
+pmd_free(pmd_t *pmd)
 {
-	*(unsigned long *)pmd = (unsigned long) pmd_quicklist;
-	pmd_quicklist = (unsigned long *) pmd;
-	++pgtable_cache_size;
+	free_page((unsigned long)pmd);
 }
 
-#define pmd_populate(MM, PMD, PTE)	pmd_set(PMD, PTE)
+#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte)
+#define pmd_populate(mm, pmd, pte_page) \
+	pmd_populate_kernel(mm, pmd, page_address(pte_page))
+
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
+{
+	int count = 0;
+	pte_t *pte;
+
+	do {
+		pte = (pte_t *)__get_free_page(GFP_KERNEL);
+		if (pte)
+			clear_page(pte);
+		else {
+			current->state = TASK_UNINTERRUPTIBLE;
+			schedule_timeout(HZ);
+		}
+	} while (!pte && (count++ < 10));
 
-static inline pte_t*
-pte_alloc_one_fast (struct mm_struct *mm, unsigned long addr)
-{
-	unsigned long *ret = (unsigned long *)pte_quicklist;
-
-	if (ret != NULL) {
-		pte_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		--pgtable_cache_size;
-	}
-	return (pte_t *)ret;
-}
-
-
-static inline pte_t*
-pte_alloc_one (struct mm_struct *mm, unsigned long addr)
-{
-	pte_t *pte = (pte_t *) __get_free_page(GFP_KERNEL);
-
-	if (pte != NULL)
-		clear_page(pte);
 	return pte;
 }
 
+#define pte_alloc_one(mm, address) \
+	virt_to_page(pte_alloc_one_kernel((mm), (address)))
+
 static inline void
-pte_free (pte_t *pte)
+pte_free_kernel(pte_t *pte)
 {
-	*(unsigned long *)pte = (unsigned long) pte_quicklist;
-	pte_quicklist = (unsigned long *) pte;
-	++pgtable_cache_size;
+	free_page((unsigned long)pte);
 }
 
-extern int do_check_pgt_cache(int, int);
+#define pte_free(pte_page)	pte_free_kernel(page_address(pte_page))
+
+#define check_pgt_cache()	do { } while (0)
 
 #endif /* _PPC64_PGALLOC_H */
diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
--- a/include/asm-ppc64/pgtable.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc64/pgtable.h	Sun Apr 14 12:16:58 2002
@@ -7,6 +7,7 @@
  */
 
 #ifndef __ASSEMBLY__
+#include <linux/threads.h>
 #include <asm/processor.h>		/* For TASK_SIZE */
 #include <asm/mmu.h>
 #include <asm/page.h>
@@ -93,13 +94,15 @@
 #define _PAGE_WRITETHRU	0x040UL	/* W: cache write-through */
 #define _PAGE_DIRTY	0x080UL	/* C: page changed */
 #define _PAGE_ACCESSED	0x100UL	/* R: page referenced */
+#if 0
 #define _PAGE_HPTENOIX	0x200UL /* software: pte HPTE slot unknown */
+#endif
 #define _PAGE_HASHPTE	0x400UL	/* software: pte has an associated HPTE */
 #define _PAGE_EXEC	0x800UL	/* software: i-cache coherence required */
 #define _PAGE_SECONDARY 0x8000UL /* software: HPTE is in secondary group */
 #define _PAGE_GROUP_IX  0x7000UL /* software: HPTE index within group */
 /* Bits 0x7000 identify the index within an HPT Group */
-#define _PAGE_HPTEFLAGS (_PAGE_HASHPTE | _PAGE_HPTENOIX | _PAGE_SECONDARY | _PAGE_GROUP_IX)
+#define _PAGE_HPTEFLAGS (_PAGE_HASHPTE | _PAGE_SECONDARY | _PAGE_GROUP_IX)
 /* PAGE_MASK gives the right answer below, but only by accident */
 /* It should be preserving the high 48 bits and then specifically */
 /* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
@@ -201,7 +204,8 @@
 #define	pmd_bad(pmd)		((pmd_val(pmd)) == 0)
 #define	pmd_present(pmd)	((pmd_val(pmd)) != 0)
 #define	pmd_clear(pmdp)		(pmd_val(*(pmdp)) = 0)
-#define pmd_page(pmd)		(__bpn_to_ba(pmd_val(pmd)))
+#define pmd_page_kernel(pmd)	(__bpn_to_ba(pmd_val(pmd)))
+#define pmd_page(pmd)		virt_to_page(pmd_page_kernel(pmd))
 #define pgd_set(pgdp, pmdp)	(pgd_val(*(pgdp)) = (__ba_to_bpn(pmdp)))
 #define pgd_none(pgd)		(!pgd_val(pgd))
 #define pgd_bad(pgd)		((pgd_val(pgd)) == 0)
@@ -222,8 +226,13 @@
   ((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
 
 /* Find an entry in the third-level page table.. */
-#define pte_offset(dir,addr) \
-  ((pte_t *) pmd_page(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+#define pte_offset_kernel(dir,addr) \
+  ((pte_t *) pmd_page_kernel(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+
+#define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
+#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
+#define pte_unmap(pte)			do { } while(0)
+#define pte_unmap_nested(pte)		do { } while(0)
 
 /* to find an entry in a kernel page-table-directory */
 /* This now only contains the vmalloc pages */
@@ -232,12 +241,6 @@
 /* to find an entry in the ioremap page-table-directory */
 #define pgd_offset_i(address) (ioremap_pgd + pgd_index(address))
 
-/*
- * Given a pointer to an mem_map[] entry, return the kernel virtual
- * address corresponding to that page.
- */
-#define page_address(page) ((page)->virtual)
-
 #define pages_to_mb(x)		((x) >> (20-PAGE_SHIFT))
 
 /*
@@ -336,43 +339,6 @@
 	pte_update(ptep, ~_PAGE_HPTEFLAGS, 0);
 }
 
-struct mm_struct;
-struct vm_area_struct;
-extern void local_flush_tlb_all(void);
-extern void local_flush_tlb_mm(struct mm_struct *mm);
-extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern void local_flush_tlb_range(struct mm_struct *mm,
-			    unsigned long start, unsigned long end);
-
-#define flush_tlb_all local_flush_tlb_all
-#define flush_tlb_mm local_flush_tlb_mm
-#define flush_tlb_page local_flush_tlb_page
-#define flush_tlb_range(vma, start, end) local_flush_tlb_range(vma->vm_mm, start, end)
-
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
-				unsigned long start, unsigned long end)
-{
-	/* PPC has hw page tables. */
-}
-
-/*
- * No cache flushing is required when address mappings are
- * changed, because the caches on PowerPCs are physically
- * addressed.
- */
-#define flush_cache_all()		do { } while (0)
-#define flush_cache_mm(mm)		do { } while (0)
-#define flush_cache_range(vma, a, b)	do { } while (0)
-#define flush_cache_page(vma, p)	do { } while (0)
-#define flush_page_to_ram(page)		do { } while (0)
-
-extern void flush_icache_user_range(struct vm_area_struct *vma,
-			struct page *page, unsigned long addr, int len);
-extern void flush_icache_range(unsigned long, unsigned long);
-extern void __flush_dcache_icache(void *page_va);
-extern void flush_dcache_page(struct page *page);
-extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
-
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
 extern unsigned long ioremap_bot, ioremap_base;
@@ -397,6 +363,7 @@
  * as entries are faulted into the hash table by the low-level
  * data/instruction access exception handlers.
  */
+#if 0
 /*
  * We won't be able to use update_mmu_cache to update the 
  * hardware page table because we need to update the pte
@@ -404,9 +371,16 @@
  * its value.
  */
 #define update_mmu_cache(vma, addr, pte)	do { } while (0)
-
-extern void flush_hash_segments(unsigned low_vsid, unsigned high_vsid);
-extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte);
+#else
+/*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to put a corresponding HPTE into the hash table
+ * ahead of time, instead of waiting for the inevitable extra
+ * hash-table miss exception.
+ */
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+#endif
 
 /* Encode and de-code a swap entry */
 #define SWP_TYPE(entry)			(((entry).val >> 1) & 0x3f)
diff -Nru a/include/asm-ppc64/ppcdebug.h b/include/asm-ppc64/ppcdebug.h
--- a/include/asm-ppc64/ppcdebug.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-ppc64/ppcdebug.h	Sun Apr 14 12:16:59 2002
@@ -108,4 +108,8 @@
 #define PPCDBG_ENTER_DEBUGGER() do {;} while(0)
 #endif
 
+#ifndef PPCDBG_ENTER_DEBUGGER_REGS
+#define PPCDBG_ENTER_DEBUGGER_REGS(A) do {;} while(0)
+#endif
+
 #endif /*__PPCDEBUG_H */
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ppc64/processor.h	Sun Apr 14 12:16:55 2002
@@ -53,36 +53,36 @@
 #define MSR_LE_LG	0 		/* Little Endian */
 
 #ifdef __ASSEMBLY__
-#define MASK(X)		(1<<(X))
+#define __MASK(X)	(1<<(X))
 #else
-#define MASK(X)		(1UL<<(X))
+#define __MASK(X)	(1UL<<(X))
 #endif
 
-#define MSR_SF		MASK(MSR_SF_LG)  /* Enable 64 bit mode */
-#define MSR_ISF		MASK(MSR_ISF_LG) /* Interrupt 64b mode valid on 630 */
-#define MSR_HV 		MASK(MSR_HV_LG)	 /* Hypervisor state */
-#define MSR_VEC		MASK(MSR_VEC_LG) /* Enable AltiVec */
-#define MSR_POW		MASK(MSR_POW_LG) /* Enable Power Management */
-#define MSR_WE		MASK(MSR_WE_LG)	 /* Wait State Enable */
-#define MSR_TGPR	MASK(MSR_TGPR_LG)/* TLB Update registers in use */
-#define MSR_CE		MASK(MSR_CE_LG)	 /* Critical Interrupt Enable */
-#define MSR_ILE		MASK(MSR_ILE_LG) /* Interrupt Little Endian */
-#define MSR_EE		MASK(MSR_EE_LG)	 /* External Interrupt Enable */
-#define MSR_PR		MASK(MSR_PR_LG)	 /* Problem State / Privilege Level */
-#define MSR_FP		MASK(MSR_FP_LG)	 /* Floating Point enable */
-#define MSR_ME		MASK(MSR_ME_LG)	 /* Machine Check Enable */
-#define MSR_FE0		MASK(MSR_FE0_LG) /* Floating Exception mode 0 */
-#define MSR_SE		MASK(MSR_SE_LG)	 /* Single Step */
-#define MSR_BE		MASK(MSR_BE_LG)	 /* Branch Trace */
-#define MSR_DE		MASK(MSR_DE_LG)	 /* Debug Exception Enable */
-#define MSR_FE1		MASK(MSR_FE1_LG) /* Floating Exception mode 1 */
-#define MSR_IP		MASK(MSR_IP_LG)	 /* Exception prefix 0x000/0xFFF */
-#define MSR_IR		MASK(MSR_IR_LG)	 /* Instruction Relocate */
-#define MSR_DR		MASK(MSR_DR_LG)	 /* Data Relocate */
-#define MSR_PE		MASK(MSR_PE_LG)	 /* Protection Enable */
-#define MSR_PX		MASK(MSR_PX_LG)	 /* Protection Exclusive Mode */
-#define MSR_RI		MASK(MSR_RI_LG)	 /* Recoverable Exception */
-#define MSR_LE		MASK(MSR_LE_LG)	 /* Little Endian */
+#define MSR_SF		__MASK(MSR_SF_LG)	/* Enable 64 bit mode */
+#define MSR_ISF		__MASK(MSR_ISF_LG)	/* Interrupt 64b mode valid on 630 */
+#define MSR_HV 		__MASK(MSR_HV_LG)	/* Hypervisor state */
+#define MSR_VEC		__MASK(MSR_VEC_LG)	/* Enable AltiVec */
+#define MSR_POW		__MASK(MSR_POW_LG)	/* Enable Power Management */
+#define MSR_WE		__MASK(MSR_WE_LG)	/* Wait State Enable */
+#define MSR_TGPR	__MASK(MSR_TGPR_LG)	/* TLB Update registers in use */
+#define MSR_CE		__MASK(MSR_CE_LG)	/* Critical Interrupt Enable */
+#define MSR_ILE		__MASK(MSR_ILE_LG)	/* Interrupt Little Endian */
+#define MSR_EE		__MASK(MSR_EE_LG)	/* External Interrupt Enable */
+#define MSR_PR		__MASK(MSR_PR_LG)	/* Problem State / Privilege Level */
+#define MSR_FP		__MASK(MSR_FP_LG)	/* Floating Point enable */
+#define MSR_ME		__MASK(MSR_ME_LG)	/* Machine Check Enable */
+#define MSR_FE0		__MASK(MSR_FE0_LG)	/* Floating Exception mode 0 */
+#define MSR_SE		__MASK(MSR_SE_LG)	/* Single Step */
+#define MSR_BE		__MASK(MSR_BE_LG)	/* Branch Trace */
+#define MSR_DE		__MASK(MSR_DE_LG)	/* Debug Exception Enable */
+#define MSR_FE1		__MASK(MSR_FE1_LG)	/* Floating Exception mode 1 */
+#define MSR_IP		__MASK(MSR_IP_LG)	/* Exception prefix 0x000/0xFFF */
+#define MSR_IR		__MASK(MSR_IR_LG)	/* Instruction Relocate */
+#define MSR_DR		__MASK(MSR_DR_LG)	/* Data Relocate */
+#define MSR_PE		__MASK(MSR_PE_LG)	/* Protection Enable */
+#define MSR_PX		__MASK(MSR_PX_LG)	/* Protection Exclusive Mode */
+#define MSR_RI		__MASK(MSR_RI_LG)	/* Recoverable Exception */
+#define MSR_LE		__MASK(MSR_LE_LG)	/* Little Endian */
 
 #define MSR_		MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF
 #define MSR_KERNEL      MSR_ | MSR_SF | MSR_HV
@@ -579,7 +579,9 @@
 #define mfmsr()		({unsigned long rval; \
 			asm volatile("mfmsr %0" : "=r" (rval)); rval;})
 
-#define mtmsrd(v)	asm volatile("mtmsrd %0" : : "r" (v))
+#define __mtmsrd(v, l)	asm volatile("mtmsrd %0," __stringify(l) \
+				     : : "r" (v))
+#define mtmsrd(v)	__mtmsrd((v), 0)
 
 #define mfspr(rn)	({unsigned long rval; \
 			asm volatile("mfspr %0," __stringify(rn) \
@@ -663,7 +665,6 @@
 	unsigned long	ksp;		/* Kernel stack pointer */
 	struct pt_regs	*regs;		/* Pointer to saved register state */
 	mm_segment_t	fs;		/* for get_fs() validation */
-	void		*pgdir;		/* root of page-table tree */
 	signed long     last_syscall;
 	double		fpr[32];	/* Complete floating point set */
 	unsigned long	fpscr_pad;	/* fpr ... fpscr must be contiguous */
@@ -676,7 +677,6 @@
 	INIT_SP, /* ksp */ \
 	(struct pt_regs *)INIT_SP - 1, /* regs */ \
 	KERNEL_DS, /*fs*/ \
-	swapper_pg_dir, /* pgdir */ \
 	0, /* last_syscall */ \
 	{0}, 0, 0 \
 }
@@ -694,10 +694,8 @@
 /*
  * Return saved PC of a blocked thread. For now, this is the "user" PC
  */
-static inline unsigned long thread_saved_pc(struct thread_struct *t)
-{
-	return (t->regs) ? t->regs->nip : 0;
-}
+#define thread_saved_pc(tsk)    \
+        ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
 
 #define copy_segments(tsk, mm)		do { } while (0)
 #define release_segments(mm)		do { } while (0)
diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h	Sun Apr 14 12:17:00 2002
+++ b/include/asm-ppc64/rtas.h	Sun Apr 14 12:17:00 2002
@@ -38,7 +38,9 @@
 	u32 nargs;
 	u32 nret; 
 	rtas_arg_t args[16];
+#if 0
 	spinlock_t lock;
+#endif
 	rtas_arg_t *rets;     /* Pointer to return values in args[]. */
 };  
 
diff -Nru a/include/asm-ppc64/siginfo.h b/include/asm-ppc64/siginfo.h
--- a/include/asm-ppc64/siginfo.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-ppc64/siginfo.h	Sun Apr 14 12:16:59 2002
@@ -113,6 +113,7 @@
 #define SI_ASYNCIO	-4		/* sent by AIO completion */
 #define SI_SIGIO	-5		/* sent by queued SIGIO */
 #define SI_TKILL	-6		/* sent by tkill system call */
+#define SI_DETHREAD	-7		/* sent by execve() killing subsidiary threads */
 
 #define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
diff -Nru a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h
--- a/include/asm-ppc64/spinlock.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ppc64/spinlock.h	Sun Apr 14 12:16:55 2002
@@ -67,7 +67,7 @@
 
 static __inline__ void _raw_spin_unlock(spinlock_t *lock)
 {
-	__asm__ __volatile__("eieio	# spin_unlock": : :"memory");
+	__asm__ __volatile__("lwsync	# spin_unlock": : :"memory");
 	lock->lock = 0;
 }
 
@@ -137,7 +137,7 @@
 	unsigned int tmp;
 
 	__asm__ __volatile__(
-	"eieio				# read_unlock\n\
+	"lwsync				# read_unlock\n\
 1:	lwarx		%0,0,%1\n\
 	addic		%0,%0,-1\n\
 	stwcx.		%0,0,%1\n\
@@ -192,7 +192,7 @@
 
 static __inline__ void _raw_write_unlock(rwlock_t *rw)
 {
-	__asm__ __volatile__("eieio		# write_unlock": : :"memory");
+	__asm__ __volatile__("lwsync		# write_unlock": : :"memory");
 	rw->lock = 0;
 }
 
diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
--- a/include/asm-ppc64/system.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc64/system.h	Sun Apr 14 12:16:58 2002
@@ -78,7 +78,6 @@
 extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
 extern void cvt_df(double *from, float *to, unsigned long *fpscr);
 extern int abs(int);
-extern void cacheable_memzero(void *p, unsigned int nb);
 
 struct device_node;
 
diff -Nru a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
--- a/include/asm-ppc64/thread_info.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-ppc64/thread_info.h	Sun Apr 14 12:16:55 2002
@@ -22,6 +22,7 @@
 	struct exec_domain *exec_domain;	/* execution domain */
 	unsigned long	flags;			/* low level flags */
 	int		cpu;			/* cpu we're on */
+	int		preempt_count;		/* not used at present */
 };
 
 /*
diff -Nru a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
--- a/include/asm-ppc64/time.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-ppc64/time.h	Sun Apr 14 12:16:58 2002
@@ -50,6 +50,7 @@
 	unsigned long tb_ticks_per_sec;
 	struct gettimeofday_vars vars[2];
 	struct gettimeofday_vars * volatile varp;
+	unsigned      var_idx;
 	unsigned      tb_to_us;
 };
 
diff -Nru a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ppc64/tlbflush.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,46 @@
+#ifndef _PPC64_TLBFLUSH_H
+#define _PPC64_TLBFLUSH_H
+
+#include <linux/threads.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ */
+
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void __flush_tlb_range(struct mm_struct *mm,
+			    unsigned long start, unsigned long end);
+#define flush_tlb_range(vma, start, end) \
+	__flush_tlb_range(vma->vm_mm, start, end)
+
+#define flush_tlb_kernel_range(start, end) \
+	__flush_tlb_range(&init_mm, (start), (end))
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+	/* PPC has hw page tables. */
+}
+
+extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
+			    int local);
+void flush_hash_range(unsigned long context, unsigned long number, int local);
+
+/* TLB flush batching */
+#define MAX_BATCH_FLUSH 128
+struct tlb_batch_data {
+	pte_t pte;
+	unsigned long addr;
+};
+extern struct tlb_batch_data tlb_batch_array[NR_CPUS][MAX_BATCH_FLUSH];
+
+#endif /* _PPC64_TLBFLUSH_H */
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-ppc64/unistd.h	Sun Apr 14 12:16:54 2002
@@ -217,22 +217,24 @@
 #define __NR_mincore		206
 #define __NR_gettid		207
 #define __NR_tkill		208
+#define __NR_setxattr		209
+#define __NR_lsetxattr		210
+#define __NR_fsetxattr		211
+#define __NR_getxattr		212
+#define __NR_lgetxattr		213
+#define __NR_fgetxattr		214
+#define __NR_listxattr		215
+#define __NR_llistxattr		216
+#define __NR_flistxattr		217
+#define __NR_removexattr	218
+#define __NR_lremovexattr	219
+#define __NR_fremovexattr	220
+#define __NR_futex		221
 
-#if 0 /* Remind paulus to add these into ppc32 */
+#if 0
+/* Remind paulus to add these into ppc32 */
 __NR_security
 __NR_readahead
-__NR_setxattr
-__NR_lsetxattr
-__NR_fsetxattr
-__NR_getxattr
-__NR_lgetxattr
-__NR_fgetxattr
-__NR_listxattr
-__NR_llistxattr
-__NR_flistxattr
-__NR_removexattr
-__NR_lremovexattr
-__NR_fremovexattr
 #endif
 
 #define __NR(n)	#n
@@ -441,5 +443,13 @@
 }
 
 #endif /* __KERNEL_SYSCALLS__ */
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",sys_ni_syscall");
 
 #endif /* _ASM_PPC_UNISTD_H_ */
diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-s390/pgtable.h	Sun Apr 14 12:16:59 2002
@@ -429,7 +429,7 @@
 	                                                                  \
 	if (__page != ZERO_PAGE(__physpage)) {                            \
 		int __users = page_count(__page);                         \
-		__users -= !!__page->buffers + !!__page->mapping;         \
+		__users -= !!PagePrivate(__page) + !!__page->mapping;     \
 	                                                                  \
 		if (__users == 1)                                         \
 			pte_val(__pte) |= _PAGE_MKCLEAR;                  \
diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
--- a/include/asm-s390/unistd.h	Sun Apr 14 12:16:59 2002
+++ b/include/asm-s390/unistd.h	Sun Apr 14 12:16:59 2002
@@ -375,4 +375,12 @@
 
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_S390_UNISTD_H_ */
diff -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h
--- a/include/asm-s390x/pgtable.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-s390x/pgtable.h	Sun Apr 14 12:16:58 2002
@@ -448,7 +448,7 @@
 	                                                                  \
 	if (__page != ZERO_PAGE(__physpage)) {                            \
 		int __users = page_count(__page);                         \
-		__users -= !!__page->buffers + !!__page->mapping;         \
+		__users -= !!PagePrivate(page) + !!__page->mapping;       \
 	                                                                  \
 		if (__users == 1)                                         \
 			pte_val(__pte) |= _PAGE_MKCLEAR;                  \
diff -Nru a/include/asm-s390x/unistd.h b/include/asm-s390x/unistd.h
--- a/include/asm-s390x/unistd.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-s390x/unistd.h	Sun Apr 14 12:16:56 2002
@@ -345,4 +345,12 @@
 
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _ASM_S390_UNISTD_H_ */
diff -Nru a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
--- a/include/asm-sh/unistd.h	Sun Apr 14 12:16:57 2002
+++ b/include/asm-sh/unistd.h	Sun Apr 14 12:16:57 2002
@@ -367,4 +367,12 @@
 }
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* __ASM_SH_UNISTD_H */
diff -Nru a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
--- a/include/asm-sparc/elf.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-sparc/elf.h	Sun Apr 14 12:16:56 2002
@@ -41,7 +41,7 @@
 	dest[34] = src->npc;				\
 	dest[35] = src->y;				\
 	dest[36] = dest[37] = 0; /* XXX */		\
-} while(0);
+} while(0)
 
 typedef struct {
 	union {
diff -Nru a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
--- a/include/asm-sparc/pgtable.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-sparc/pgtable.h	Sun Apr 14 12:16:54 2002
@@ -293,6 +293,9 @@
 #define page_pte_prot(page, prot)	mk_pte(page, prot)
 #define page_pte(page)			page_pte_prot(page, __pgprot(0))
 
+/* Permanent address of a page. */
+#define page_address(page)  ((page)->virtual)
+
 BTFIXUPDEF_CALL(struct page *, pte_page, pte_t)
 #define pte_page(pte) BTFIXUP_CALL(pte_page)(pte)
 
diff -Nru a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h
--- a/include/asm-sparc/sbus.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-sparc/sbus.h	Sun Apr 14 12:16:56 2002
@@ -94,7 +94,8 @@
         for((device) = (bus)->devices; (device); (device)=(device)->next)
         
 #define for_all_sbusdev(device, bus) \
-	for((bus) = sbus_root, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
+	for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \
+		for ((device) = (bus)->devices; (device); (device) = (device)->next)
 
 /* Driver DVMA interfaces. */
 #define sbus_can_dma_64bit(sdev)	(0) /* actually, sparc_cpu_model==sun4d */
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-sparc/unistd.h	Sun Apr 14 12:16:55 2002
@@ -437,4 +437,12 @@
 
 #endif /* __KERNEL_SYSCALLS__ */
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _SPARC_UNISTD_H */
diff -Nru a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
--- a/include/asm-sparc64/pgalloc.h	Sun Apr 14 12:16:58 2002
+++ b/include/asm-sparc64/pgalloc.h	Sun Apr 14 12:16:58 2002
@@ -10,13 +10,6 @@
 #include <asm/spitfire.h>
 #include <asm/pgtable.h>
 
-#define VPTE_BASE_SPITFIRE	0xfffffffe00000000
-#if 1
-#define VPTE_BASE_CHEETAH	VPTE_BASE_SPITFIRE
-#else
-#define VPTE_BASE_CHEETAH	0xffe0000000000000
-#endif
-
 static __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start,
 					  unsigned long end)
 {
@@ -42,8 +35,6 @@
 				vpte_base + (e >> (PAGE_SHIFT - 3)));
 	}
 }
-#undef VPTE_BASE_SPITFIRE
-#undef VPTE_BASE_CHEETAH
 
 /* Page table allocation/freeing. */
 #ifdef CONFIG_SMP
diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
--- a/include/asm-sparc64/pgtable.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-sparc64/pgtable.h	Sun Apr 14 12:16:54 2002
@@ -48,6 +48,8 @@
 	flush_cache_mm((vma)->vm_mm)
 
 
+struct page;
+
 /* 
  * On spitfire, the icache doesn't snoop local stores and we don't
  * use block commit stores (which invalidate icache lines) during
diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
--- a/include/asm-sparc64/processor.h	Sun Apr 14 12:16:54 2002
+++ b/include/asm-sparc64/processor.h	Sun Apr 14 12:16:54 2002
@@ -39,8 +39,24 @@
  * address that the kernel will allocate out.
  */
 #define VA_BITS		44
+#ifndef __ASSEMBLY__
 #define VPTE_SIZE	(1UL << (VA_BITS - PAGE_SHIFT + 3))
+#else
+#define VPTE_SIZE	(1 << (VA_BITS - PAGE_SHIFT + 3))
+#endif
 #define TASK_SIZE	((unsigned long)-VPTE_SIZE)
+
+/*
+ * The vpte base must be able to hold the entire vpte, half
+ * of which lives above, and half below, the base. And it
+ * is placed as close to the highest address range as possible.
+ */
+#define VPTE_BASE_SPITFIRE	(-(VPTE_SIZE/2))
+#if 1
+#define VPTE_BASE_CHEETAH	VPTE_BASE_SPITFIRE
+#else
+#define VPTE_BASE_CHEETAH	0xffe0000000000000
+#endif
 
 #ifndef __ASSEMBLY__
 
diff -Nru a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
--- a/include/asm-sparc64/sbus.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-sparc64/sbus.h	Sun Apr 14 12:16:56 2002
@@ -87,7 +87,8 @@
         for((device) = (bus)->devices; (device); (device)=(device)->next)
         
 #define for_all_sbusdev(device, bus) \
-	for((bus) = sbus_root, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
+	for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \
+		for ((device) = (bus)->devices; (device); (device) = (device)->next)
 
 /* Driver DVMA interfaces. */
 #define sbus_can_dma_64bit(sdev)	(1)
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	Sun Apr 14 12:16:56 2002
+++ b/include/asm-sparc64/unistd.h	Sun Apr 14 12:16:56 2002
@@ -439,4 +439,12 @@
 #define   _SC_VERSION             8
 #endif
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif /* _SPARC64_UNISTD_H */
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	Sun Apr 14 12:16:55 2002
+++ b/include/asm-x86_64/unistd.h	Sun Apr 14 12:16:55 2002
@@ -650,4 +650,12 @@
 
 #endif /* __NO_STUBS */
 
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
 #endif
diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h
--- a/include/linux/acpi.h	Sun Apr 14 12:16:54 2002
+++ b/include/linux/acpi.h	Sun Apr 14 12:16:54 2002
@@ -29,6 +29,12 @@
 #define _LINUX
 #endif
 
+/*
+ * YES this is ugly.
+ * But, moving all of ACPI's private headers to include/acpi isn't the right
+ * answer either.
+ * Please just ignore it for now.
+ */
 #include "../../drivers/acpi/include/acpi.h"
 #include <asm/acpi.h>
 
@@ -270,7 +276,7 @@
 	struct acpi_table_header header;
 	u64			localities;
 	u8			entry[1];	/* real size = localities^2 */
-};
+} __attribute__ ((packed));
 
 /* Smart Battery Description Table (SBST) */
 
@@ -283,7 +289,6 @@
 
 /* Embedded Controller Boot Resources Table (ECDT) */
 
-/* TBD: acpi_generic_address
 struct acpi_table_ecdt {
 	struct acpi_table_header header;
 	acpi_generic_address	ec_control;
@@ -292,7 +297,6 @@
 	u8			gpe_bit;
 	char			*ec_id;
 } __attribute__ ((packed));
-*/
 
 /* Table Handlers */
 
@@ -343,9 +347,9 @@
 
 #ifdef CONFIG_ACPI_PCI
 
-#define ACPI_PCI_ROUTING_PIC	0
-#define ACPI_PCI_ROUTING_IOAPIC 1
-#define ACPI_PCI_ROUTING_IOSAPIC 2
+#define ACPI_INT_MODEL_PIC	0
+#define ACPI_INT_MODEL_IOAPIC	1
+#define ACPI_INT_MODEL_IOSAPIC	2
 
 struct acpi_prt_entry {
 	struct list_head	node;
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/blkdev.h	Sun Apr 14 12:16:56 2002
@@ -153,6 +153,12 @@
 	prep_rq_fn		*prep_rq_fn;
 
 	/*
+	 * The VM-level readahead tunable for this device.  In
+	 * units of 512-byte sectors.
+	 */
+	unsigned ra_sectors;
+
+	/*
 	 * The queue owner gets to use this for whatever they like.
 	 * ll_rw_blk doesn't touch it.
 	 */
@@ -308,12 +314,14 @@
 extern void blk_queue_segment_boundary(request_queue_t *q, unsigned long);
 extern void blk_queue_assign_lock(request_queue_t *q, spinlock_t *);
 extern void blk_queue_prep_rq(request_queue_t *q, prep_rq_fn *pfn);
+extern int blk_set_readahead(kdev_t dev, unsigned sectors);
+extern unsigned blk_get_readahead(kdev_t dev);
 
 extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
 extern void generic_unplug_device(void *);
 
-extern int * blk_size[MAX_BLKDEV];
+extern int * blk_size[MAX_BLKDEV];	/* in units of 1024 bytes */
 extern int * blksize_size[MAX_BLKDEV];
 
 #define MAX_PHYS_SEGMENTS 128
@@ -322,10 +330,6 @@
 
 #define MAX_SEGMENT_SIZE	65536
 
-/* read-ahead in pages.. */
-#define MAX_READAHEAD	31
-#define MIN_READAHEAD	3
-
 #define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
 
 extern void drive_stat_acct(struct request *, int, int);
@@ -353,6 +357,7 @@
 #define blk_finished_io(nsects)	do { } while (0)
 #define blk_started_io(nsects)	do { } while (0)
 
+/* assumes size > 256 */
 extern inline unsigned int blksize_bits(unsigned int size)
 {
 	unsigned int bits = 8;
@@ -374,6 +379,20 @@
 			retval = blksize_size[major][minor];
 	}
 	return retval;
+}
+
+static inline loff_t blkdev_size_in_bytes(kdev_t dev)
+{
+#if 0
+	if (blk_size_in_bytes[major(dev)])
+		return blk_size_in_bytes[major(dev)][minor(dev)];
+	else
+#endif
+	if (blk_size[major(dev)])
+		return (loff_t) blk_size[major(dev)][minor(dev)]
+			<< BLOCK_SIZE_BITS;
+	else
+		return 0;
 }
 
 typedef struct {struct page *v;} Sector;
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/compiler.h	Sun Apr 14 12:16:55 2002
@@ -15,8 +15,8 @@
 
 /* This macro obfuscates arithmetic on a variable address so that gcc
    shouldn't recognize the original var, and make assumptions about it */
-#define RELOC_HIDE(var, off)					\
-  ({ __typeof__(&(var)) __ptr;					\
-    __asm__ ("" : "=g"(__ptr) : "0"((void *)&(var) + (off)));	\
-    *__ptr; })
+#define RELOC_HIDE(ptr, off)					\
+  ({ __typeof__(ptr) __ptr;					\
+    __asm__ ("" : "=g"(__ptr) : "0"((void *)(ptr) + (off)));	\
+    __ptr; })
 #endif /* __LINUX_COMPILER_H */
diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
--- a/include/linux/devfs_fs_kernel.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/devfs_fs_kernel.h	Sun Apr 14 12:16:59 2002
@@ -54,7 +54,7 @@
     unsigned char sem_initialised;
     unsigned int num_free;          /*  Num free in bits       */
     unsigned int length;            /*  Array length in bytes  */
-    __u32 *bits;
+    unsigned long *bits;
     struct semaphore semaphore;
 };
 
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/device.h	Sun Apr 14 12:16:57 2002
@@ -64,6 +64,7 @@
 };
 
 struct device {
+	struct list_head g_list;        /* node in depth-first order list */
 	struct list_head node;		/* node in sibling list */
 	struct list_head children;
 	struct device 	* parent;
@@ -83,7 +84,7 @@
 					   device */
 	void		*driver_data;	/* data private to the driver */
 	void		*platform_data;	/* Platform specific data (e.g. ACPI,
-					   BIOS data relevant to device */
+					   BIOS data relevant to device) */
 
 	u32		current_state;  /* Current operating state. In
 					   ACPI-speak, this is D0-D3, D0
@@ -99,6 +100,12 @@
 	return list_entry(node, struct device, node);
 }
 
+static inline struct device *
+g_list_to_dev(struct list_head *g_list)
+{
+	return list_entry(g_list, struct device, g_list);
+}
+
 /*
  * High level routines for use by the bus drivers
  */
@@ -142,5 +149,14 @@
 }
 
 extern void put_device(struct device * dev);
+
+/* drivers/base/sys.c */
+extern int register_sys_device(struct device * dev);
+extern void unregister_sys_device(struct device * dev);
+
+/* drivers/base/power.c */
+extern int device_suspend(u32 state, u32 level);
+extern void device_resume(u32 level);
+extern void device_shutdown(void);
 
 #endif /* _DEVICE_H_ */
diff -Nru a/include/linux/ethtool.h b/include/linux/ethtool.h
--- a/include/linux/ethtool.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/ethtool.h	Sun Apr 14 12:16:56 2002
@@ -36,7 +36,8 @@
 	char	bus_info[ETHTOOL_BUSINFO_LEN];	/* Bus info for this IF. */
 				/* For PCI devices, use pci_dev->slot_name. */
 	char	reserved1[32];
-	char	reserved2[24];
+	char	reserved2[20];
+	u32	testinfo_len;
 	u32	eedump_len;	/* Size of data from ETHTOOL_GEEPROM (bytes) */
 	u32	regdump_len;	/* Size of data from ETHTOOL_GREGS (bytes) */
 };
@@ -210,6 +211,34 @@
 	u32	tx_pause;
 };
 
+#define ETH_GSTRING_LEN		32
+enum ethtool_stringset {
+	ETH_SS_TEST		= 0,
+	ETH_SS_STATS,
+};
+
+/* for passing string sets for data tagging */
+struct ethtool_gstrings {
+	u32	cmd;		/* ETHTOOL_GSTRINGS */
+	u32	string_set;	/* string set id e.c. ETH_SS_TEST, etc*/
+	u32	len;		/* number of strings in the string set */
+	u8	data[0];
+};
+
+enum ethtool_test_flags {
+	ETH_TEST_FL_OFFLINE	= (1 << 0),	/* online / offline */
+	ETH_TEST_FL_FAILED	= (1 << 1),	/* test passed / failed */
+};
+
+/* for requesting NIC test and getting results*/
+struct ethtool_test {
+	u32	cmd;		/* ETHTOOL_TEST */
+	u32	flags;		/* ETH_TEST_FL_xxx */
+	u32	reserved;
+	u32	len;		/* result length, in number of u64 elements */
+	u64	data[0];
+};
+
 /* CMDs currently supported */
 #define ETHTOOL_GSET		0x00000001 /* Get settings. */
 #define ETHTOOL_SSET		0x00000002 /* Set settings, privileged. */
@@ -222,13 +251,13 @@
 #define ETHTOOL_NWAY_RST	0x00000009 /* Restart autonegotiation, priv. */
 #define ETHTOOL_GLINK		0x0000000a /* Get link status (ethtool_value) */
 #define ETHTOOL_GEEPROM		0x0000000b /* Get EEPROM data */
-#define ETHTOOL_SEEPROM		0x0000000c /* Set EEPROM data */
+#define ETHTOOL_SEEPROM		0x0000000c /* Set EEPROM data, priv. */
 #define ETHTOOL_GCOALESCE	0x0000000e /* Get coalesce config */
-#define ETHTOOL_SCOALESCE	0x0000000f /* Set coalesce config */
+#define ETHTOOL_SCOALESCE	0x0000000f /* Set coalesce config, priv. */
 #define ETHTOOL_GRINGPARAM	0x00000010 /* Get ring parameters */
-#define ETHTOOL_SRINGPARAM	0x00000011 /* Set ring parameters */
+#define ETHTOOL_SRINGPARAM	0x00000011 /* Set ring parameters, priv. */
 #define ETHTOOL_GPAUSEPARAM	0x00000012 /* Get pause parameters */
-#define ETHTOOL_SPAUSEPARAM	0x00000013 /* Set pause parameters */
+#define ETHTOOL_SPAUSEPARAM	0x00000013 /* Set pause parameters, priv. */
 #define ETHTOOL_GRXCSUM		0x00000014 /* Get RX hw csum enable (ethtool_value) */
 #define ETHTOOL_SRXCSUM		0x00000015 /* Set RX hw csum enable (ethtool_value) */
 #define ETHTOOL_GTXCSUM		0x00000016 /* Get TX hw csum enable (ethtool_value) */
@@ -236,7 +265,9 @@
 #define ETHTOOL_GSG		0x00000018 /* Get scatter-gather enable
 					    * (ethtool_value) */
 #define ETHTOOL_SSG		0x00000019 /* Set scatter-gather enable
-					    * (ethtool_value) */
+					    * (ethtool_value), priv. */
+#define ETHTOOL_TEST		0x0000001a /* execute NIC self-test, priv. */
+#define ETHTOOL_GSTRINGS	0x0000001b /* get specified string set */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff -Nru a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
--- a/include/linux/ext3_fs_sb.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/ext3_fs_sb.h	Sun Apr 14 12:16:59 2002
@@ -61,6 +61,7 @@
 	int s_desc_per_block_bits;
 	int s_inode_size;
 	int s_first_ino;
+	u32 s_next_generation;
 
 	/* Journaling */
 	struct inode * s_journal_inode;
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/fs.h	Sun Apr 14 12:16:56 2002
@@ -21,6 +21,7 @@
 #include <linux/cache.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
+#include <linux/radix-tree.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -172,12 +173,10 @@
 #define BLKRRPART  _IO(0x12,95)	/* re-read partition table */
 #define BLKGETSIZE _IO(0x12,96)	/* return device size /512 (long *arg) */
 #define BLKFLSBUF  _IO(0x12,97)	/* flush buffer cache */
-#if 0				/* Obsolete, these don't do anything. */
 #define BLKRASET   _IO(0x12,98)	/* set read ahead for block device */
 #define BLKRAGET   _IO(0x12,99)	/* get current read ahead setting */
 #define BLKFRASET  _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
 #define BLKFRAGET  _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
-#endif
 #define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
 #define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
 #define BLKSSZGET  _IO(0x12,104)/* get block device sector size */
@@ -286,6 +285,24 @@
 
 #define touch_buffer(bh)	mark_page_accessed(bh->b_page)
 
+/* If we *know* page->private refers to buffer_heads */
+#define page_buffers(page)					\
+	({							\
+		if (!PagePrivate(page))				\
+			BUG();					\
+		((struct buffer_head *)(page)->private);	\
+	})
+#define page_has_buffers(page)	PagePrivate(page)
+#define set_page_buffers(page, buffers)				\
+	do {							\
+		SetPagePrivate(page);				\
+		page->private = (unsigned long)buffers;		\
+	} while (0)
+#define clear_page_buffers(page)				\
+	do {							\
+		ClearPagePrivate(page);				\
+		page->private = 0;				\
+	} while (0)
 
 #include <linux/pipe_fs_i.h>
 /* #include <linux/umsdos_fs_i.h> */
@@ -305,6 +322,8 @@
 #define ATTR_MTIME_SET	256
 #define ATTR_FORCE	512	/* Not a change, but a change it */
 #define ATTR_ATTR_FLAG	1024
+#define ATTR_KILL_SUID	2048
+#define ATTR_KILL_SGID	4096
 
 /*
  * This is the Inode Attributes structure, used for notify_change().  It
@@ -368,6 +387,8 @@
 };
 
 struct address_space {
+	struct radix_tree_root	page_tree;	/* radix tree of all pages */
+	rwlock_t		page_lock;	/* and rwlock protecting it */
 	struct list_head	clean_pages;	/* list of clean pages */
 	struct list_head	dirty_pages;	/* list of dirty pages */
 	struct list_head	locked_pages;	/* list of locked pages */
@@ -482,6 +503,18 @@
 	int signum;		/* posix.1b rt signal to be delivered on IO */
 };
 
+/*
+ * Track a single file's readahead state
+ */
+struct file_ra_state {
+	unsigned long start;		/* Current window */
+	unsigned long size;
+	unsigned long next_size;	/* Next window size */
+	unsigned long prev_page;	/* Cache last read() position */
+	unsigned long ahead_start;	/* Ahead window */
+	unsigned long ahead_size;
+};
+
 struct file {
 	struct list_head	f_list;
 	struct dentry		*f_dentry;
@@ -491,10 +524,10 @@
 	unsigned int 		f_flags;
 	mode_t			f_mode;
 	loff_t			f_pos;
-	unsigned long 		f_reada, f_ramax, f_raend, f_ralen, f_rawin;
 	struct fown_struct	f_owner;
 	unsigned int		f_uid, f_gid;
 	int			f_error;
+	struct file_ra_state	f_ra;
 
 	unsigned long		f_version;
 
@@ -651,7 +684,6 @@
 #include <linux/ufs_fs_sb.h>
 #include <linux/romfs_fs_sb.h>
 #include <linux/adfs_fs_sb.h>
-#include <linux/reiserfs_fs_sb.h>
 #include <linux/bfs_fs_sb.h>
 
 extern struct list_head super_blocks;
@@ -664,6 +696,7 @@
 	kdev_t			s_dev;
 	unsigned long		s_blocksize;
 	unsigned char		s_blocksize_bits;
+	unsigned long		s_old_blocksize;
 	unsigned char		s_dirt;
 	unsigned long long	s_maxbytes;	/* Max file size */
 	struct file_system_type	*s_type;
@@ -695,7 +728,6 @@
 		struct ufs_sb_info	ufs_sb;
 		struct romfs_sb_info	romfs_sb;
 		struct adfs_sb_info	adfs_sb;
-		struct reiserfs_sb_info	reiserfs_sb;
 		struct bfs_sb_info	bfs_sb;
 		void			*generic_sbp;
 	} u;
@@ -924,6 +956,7 @@
 struct super_block *get_sb_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
+void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);
 void kill_litter_super(struct super_block *sb);
@@ -1232,6 +1265,7 @@
 extern int do_pipe(int *);
 
 extern int open_namei(const char *, int, int, struct nameidata *);
+extern int may_open(struct nameidata *, int, int);
 
 extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
 extern struct file * open_exec(const char *);
@@ -1314,7 +1348,7 @@
 
 extern void clear_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
-extern void remove_suid(struct inode *inode);
+extern void remove_suid(struct dentry *);
 extern void insert_inode_hash(struct inode *);
 extern void remove_inode_hash(struct inode *);
 extern struct file * get_empty_filp(void);
diff -Nru a/include/linux/hdreg.h b/include/linux/hdreg.h
--- a/include/linux/hdreg.h	Sun Apr 14 12:16:58 2002
+++ b/include/linux/hdreg.h	Sun Apr 14 12:16:58 2002
@@ -34,6 +34,7 @@
 #define ECC_STAT		0x04	/* Corrected error */
 #define DRQ_STAT		0x08
 #define SEEK_STAT		0x10
+#define SERVICE_STAT		SEEK_STAT
 #define WRERR_STAT		0x20
 #define READY_STAT		0x40
 #define BUSY_STAT		0x80
@@ -50,20 +51,20 @@
 #define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
 
 /*
+ * bits of NSECTOR reg
+ */
+#define NSEC_CD			0x1
+#define NSEC_IO			0x2
+#define NSEC_REL		0x4
+
+/*
  * Command Header sizes for IOCTL commands
  *	HDIO_DRIVE_CMD and HDIO_DRIVE_TASK
  */
 
-#if 0
-#include <asm/hdreg.h>
-typedef ide_ioreg_t task_ioreg_t;
-#else
-typedef unsigned char task_ioreg_t;
-#endif
-
-#define HDIO_DRIVE_CMD_HDR_SIZE		4*sizeof(task_ioreg_t)
-#define HDIO_DRIVE_TASK_HDR_SIZE	8*sizeof(task_ioreg_t)
-#define HDIO_DRIVE_HOB_HDR_SIZE		8*sizeof(task_ioreg_t)
+#define HDIO_DRIVE_CMD_HDR_SIZE		(4 * sizeof(u8))
+#define HDIO_DRIVE_TASK_HDR_SIZE	(8 * sizeof(u8))
+#define HDIO_DRIVE_HOB_HDR_SIZE		(8 * sizeof(u8))
 
 #define IDE_DRIVE_TASK_INVALID		-1
 #define IDE_DRIVE_TASK_NO_DATA		0
@@ -74,57 +75,27 @@
 #define IDE_DRIVE_TASK_OUT		3
 #define IDE_DRIVE_TASK_RAW_WRITE	4
 
-struct hd_drive_cmd_hdr {
-	task_ioreg_t command;
-	task_ioreg_t sector_number;
-	task_ioreg_t feature;
-	task_ioreg_t sector_count;
-};
-
-typedef struct hd_drive_task_hdr {
-	task_ioreg_t data;
-	task_ioreg_t feature;
-	task_ioreg_t sector_count;
-	task_ioreg_t sector_number;
-	task_ioreg_t low_cylinder;
-	task_ioreg_t high_cylinder;
-	task_ioreg_t device_head;
-	task_ioreg_t command;
-} task_struct_t;
-
-typedef struct hd_drive_hob_hdr {
-	task_ioreg_t data;
-	task_ioreg_t feature;
-	task_ioreg_t sector_count;
-	task_ioreg_t sector_number;
-	task_ioreg_t low_cylinder;
-	task_ioreg_t high_cylinder;
-	task_ioreg_t device_head;
-	task_ioreg_t control;
-} hob_struct_t;
-
-typedef union ide_reg_valid_s {
-	unsigned all				: 16;
-	struct {
-		unsigned data			: 1;
-		unsigned error_feature		: 1;
-		unsigned sector			: 1;
-		unsigned nsector		: 1;
-		unsigned lcyl			: 1;
-		unsigned hcyl			: 1;
-		unsigned select			: 1;
-		unsigned status_command		: 1;
-
-		unsigned data_hob		: 1;
-		unsigned error_feature_hob	: 1;
-		unsigned sector_hob		: 1;
-		unsigned nsector_hob		: 1;
-		unsigned lcyl_hob		: 1;
-		unsigned hcyl_hob		: 1;
-		unsigned select_hob		: 1;
-		unsigned control_hob		: 1;
-	} b;
-} ide_reg_valid_t;
+struct hd_drive_task_hdr {
+	u8 data;
+	u8 feature;
+	u8 sector_count;
+	u8 sector_number;
+	u8 low_cylinder;
+	u8 high_cylinder;
+	u8 device_head;
+	u8 command;
+} __attribute__((packed));
+
+struct hd_drive_hob_hdr {
+	u8 data;
+	u8 feature;
+	u8 sector_count;
+	u8 sector_number;
+	u8 low_cylinder;
+	u8 high_cylinder;
+	u8 device_head;
+	u8 control;
+} __attribute__((packed));
 
 /*
  * Define standard taskfile in/out register
@@ -134,23 +105,6 @@
 #define IDE_HOB_STD_OUT_FLAGS		0xC0
 #define IDE_HOB_STD_IN_FLAGS		0xC0
 
-typedef struct ide_task_request_s {
-	task_ioreg_t	io_ports[8];
-	task_ioreg_t	hob_ports[8];
-	ide_reg_valid_t	out_flags;
-	ide_reg_valid_t	in_flags;
-	int		data_phase;
-	int		req_cmd;
-	unsigned long	out_size;
-	unsigned long	in_size;
-} ide_task_request_t;
-
-typedef struct ide_ioctl_request_s {
-	ide_task_request_t	*task_request;
-	unsigned char		*out_buffer;
-	unsigned char		*in_buffer;
-} ide_ioctl_request_t;
-
 #define TASKFILE_INVALID		0x7fff
 #define TASKFILE_48			0x8000
 
@@ -212,7 +166,7 @@
 #define WIN_PIDENTIFY			0xA1 /* identify ATAPI device	*/
 #define WIN_QUEUED_SERVICE		0xA2
 #define WIN_SMART			0xB0 /* self-monitoring and reporting */
-#define CFA_ERASE_SECTORS       	0xC0
+#define CFA_ERASE_SECTORS		0xC0
 #define WIN_MULTREAD			0xC4 /* read sectors using multiple mode*/
 #define WIN_MULTWRITE			0xC5 /* write sectors using multiple mode */
 #define WIN_SETMULT			0xC6 /* enable/disable multiple mode */
@@ -221,12 +175,12 @@
 #define WIN_WRITEDMA			0xCA /* write sectors using DMA transfers */
 #define WIN_WRITEDMA_QUEUED		0xCC /* write sectors using Queued DMA transfers */
 #define CFA_WRITE_MULTI_WO_ERASE	0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS		0xDA	
+#define WIN_GETMEDIASTATUS		0xDA
 #define WIN_DOORLOCK			0xDE /* lock door on removable drives */
 #define WIN_DOORUNLOCK			0xDF /* unlock door on removable drives */
 #define WIN_STANDBYNOW1			0xE0
 #define WIN_IDLEIMMEDIATE		0xE1 /* force drive to become "ready" */
-#define WIN_STANDBY             	0xE2 /* Set device in Standby Mode */
+#define WIN_STANDBY			0xE2 /* Set device in Standby Mode */
 #define WIN_SETIDLE1			0xE3
 #define WIN_READ_BUFFER			0xE4 /* force read only 1 sector */
 #define WIN_CHECKPOWERMODE1		0xE5
@@ -268,7 +222,7 @@
 
 #define SMART_LCYL_PASS			0x4F
 #define SMART_HCYL_PASS			0xC2
-		
+
 /* WIN_SETFEATURES sub-commands */
 
 #define SETFEATURES_EN_WCACHE	0x02	/* Enable write cache */
@@ -638,8 +592,5 @@
  */
 #define IDE_NICE_DSC_OVERLAP	(0)	/* per the DSC overlap protocol */
 #define IDE_NICE_ATAPI_OVERLAP	(1)	/* not supported yet */
-#define IDE_NICE_0		(2)	/* when sure that it won't affect us */
-#define IDE_NICE_1		(3)	/* when probably won't affect us much */
-#define IDE_NICE_2		(4)	/* when we know it's on our expense */
 
 #endif	/* _LINUX_HDREG_H */
diff -Nru a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h
--- a/include/linux/hfs_sysdep.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/hfs_sysdep.h	Sun Apr 14 12:16:55 2002
@@ -200,16 +200,16 @@
 #endif
 
 static inline int hfs_clear_bit(int bitnr, hfs_u32 *lword) {
-	return test_and_clear_bit(BITNR(bitnr), lword);
+	return test_and_clear_bit(BITNR(bitnr), (unsigned long *)lword);
 }
 
 static inline int hfs_set_bit(int bitnr, hfs_u32 *lword) {
-	return test_and_set_bit(BITNR(bitnr), lword);
+	return test_and_set_bit(BITNR(bitnr), (unsigned long *)lword);
 }
 
 static inline int hfs_test_bit(int bitnr, const hfs_u32 *lword) {
 	/* the kernel should declare the second arg of test_bit as const */
-	return test_bit(BITNR(bitnr), (void *)lword);
+	return test_bit(BITNR(bitnr), (unsigned long *)lword);
 }
 
 #undef BITNR
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/hiddev.h	Sun Apr 14 12:16:56 2002
@@ -119,13 +119,17 @@
 	__s32 value;
 };
 
+/* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
+ * is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has
+ * been sent by the device 
+ */
 #define HID_FIELD_INDEX_NONE 0xffffffff
 
 /*
  * Protocol version.
  */
 
-#define HID_VERSION		0x010002
+#define HID_VERSION		0x010003
 
 /*
  * IOCTLs (0x00 - 0x7f)
@@ -139,20 +143,20 @@
 #define HIDIOCGNAME(len)	_IOC(_IOC_READ, 'H', 0x06, len)
 #define HIDIOCGREPORT		_IOW('H', 0x07, struct hiddev_report_info)
 #define HIDIOCSREPORT		_IOW('H', 0x08, struct hiddev_report_info)
-#define HIDIOCGREPORTINFO       _IOWR('H', 0x09, struct hiddev_report_info)
-#define HIDIOCGFIELDINFO        _IOWR('H', 0x0A, struct hiddev_field_info)
-#define HIDIOCGUSAGE            _IOWR('H', 0x0B, struct hiddev_usage_ref)
-#define HIDIOCSUSAGE            _IOW('H', 0x0C, struct hiddev_usage_ref)
-#define HIDIOCGUCODE            _IOWR('H', 0x0D, struct hiddev_usage_ref)
-#define HIDIOCGFLAG             _IOR('H', 0x0E, int)
-#define HIDIOCSFLAG             _IOW('H', 0x0F, int)
+#define HIDIOCGREPORTINFO	_IOWR('H', 0x09, struct hiddev_report_info)
+#define HIDIOCGFIELDINFO	_IOWR('H', 0x0A, struct hiddev_field_info)
+#define HIDIOCGUSAGE		_IOWR('H', 0x0B, struct hiddev_usage_ref)
+#define HIDIOCSUSAGE		_IOW('H', 0x0C, struct hiddev_usage_ref)
+#define HIDIOCGUCODE		_IOWR('H', 0x0D, struct hiddev_usage_ref)
+#define HIDIOCGFLAG		_IOR('H', 0x0E, int)
+#define HIDIOCSFLAG		_IOW('H', 0x0F, int)
 
 /* 
  * Flags to be used in HIDIOCSFLAG
  */
-#define HIDDEV_FLAG_UREF     0x1
-#define HIDDEV_FLAG_REPORT   0x2
-#define HIDDEV_FLAGS         0x3
+#define HIDDEV_FLAG_UREF	0x1
+#define HIDDEV_FLAG_REPORT	0x2
+#define HIDDEV_FLAGS		0x3
 
 /* To traverse the input report descriptor info for a HID device, perform the 
  * following:
diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h
--- a/include/linux/highmem.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/highmem.h	Sun Apr 14 12:16:56 2002
@@ -4,6 +4,7 @@
 #include <linux/config.h>
 #include <linux/bio.h>
 #include <linux/fs.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_HIGHMEM
 
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/ide.h	Sun Apr 14 12:16:56 2002
@@ -13,7 +13,9 @@
 #include <linux/proc_fs.h>
 #include <linux/device.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/interrupt.h>
 #include <asm/hdreg.h>
+#include <asm/bitops.h>
 
 /*
  * This is the multiple IDE interface driver, as evolved from hd.c.
@@ -68,8 +70,8 @@
  */
 #define DMA_PIO_RETRY	1	/* retrying in PIO */
 
-#define HWIF(drive)		((drive)->hwif)
-#define HWGROUP(drive)		(HWIF(drive)->hwgroup)
+#define HWIF(drive)		((drive)->channel)
+#define HWGROUP(drive)		(drive->channel->hwgroup)
 
 /*
  * Definitions for accessing IDE controller registers
@@ -90,37 +92,16 @@
 #define IDE_FEATURE_OFFSET	IDE_ERROR_OFFSET
 #define IDE_COMMAND_OFFSET	IDE_STATUS_OFFSET
 
-#define IDE_DATA_OFFSET_HOB	(0)
-#define IDE_ERROR_OFFSET_HOB	(1)
-#define IDE_NSECTOR_OFFSET_HOB	(2)
-#define IDE_SECTOR_OFFSET_HOB	(3)
-#define IDE_LCYL_OFFSET_HOB	(4)
-#define IDE_HCYL_OFFSET_HOB	(5)
-#define IDE_SELECT_OFFSET_HOB	(6)
-#define IDE_CONTROL_OFFSET_HOB	(7)
-
-#define IDE_FEATURE_OFFSET_HOB	IDE_ERROR_OFFSET_HOB
-
-#define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
-#define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
-#define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
-#define IDE_SECTOR_REG		(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
-#define IDE_LCYL_REG		(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
-#define IDE_HCYL_REG		(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
-#define IDE_SELECT_REG		(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
-#define IDE_STATUS_REG		(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
-#define IDE_CONTROL_REG		(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
-#define IDE_IRQ_REG		(HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
-
-#define IDE_DATA_REG_HOB	(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
-#define IDE_ERROR_REG_HOB	(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
-#define IDE_NSECTOR_REG_HOB	(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
-#define IDE_SECTOR_REG_HOB	(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
-#define IDE_LCYL_REG_HOB	(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
-#define IDE_HCYL_REG_HOB	(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
-#define IDE_SELECT_REG_HOB	(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
-#define IDE_STATUS_REG_HOB	(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
-#define IDE_CONTROL_REG_HOB	(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
+#define IDE_DATA_REG		(drive->channel->io_ports[IDE_DATA_OFFSET])
+#define IDE_ERROR_REG		(drive->channel->io_ports[IDE_ERROR_OFFSET])
+#define IDE_NSECTOR_REG		(drive->channel->io_ports[IDE_NSECTOR_OFFSET])
+#define IDE_SECTOR_REG		(drive->channel->io_ports[IDE_SECTOR_OFFSET])
+#define IDE_LCYL_REG		(drive->channel->io_ports[IDE_LCYL_OFFSET])
+#define IDE_HCYL_REG		(drive->channel->io_ports[IDE_HCYL_OFFSET])
+#define IDE_SELECT_REG		(drive->channel->io_ports[IDE_SELECT_OFFSET])
+#define IDE_STATUS_REG		(drive->channel->io_ports[IDE_STATUS_OFFSET])
+#define IDE_CONTROL_REG		(drive->channel->io_ports[IDE_CONTROL_OFFSET])
+#define IDE_IRQ_REG		(drive->channel->io_ports[IDE_IRQ_OFFSET])
 
 #define IDE_FEATURE_REG		IDE_ERROR_REG
 #define IDE_COMMAND_REG		IDE_STATUS_REG
@@ -132,10 +113,14 @@
 #define GET_ERR()		IN_BYTE(IDE_ERROR_REG)
 #define GET_STAT()		IN_BYTE(IDE_STATUS_REG)
 #define GET_ALTSTAT()		IN_BYTE(IDE_CONTROL_REG)
+#define GET_FEAT()		IN_BYTE(IDE_NSECTOR_REG)
+
 #define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
+
 #define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
 #define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
 #define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
+
 #define DRIVE_READY		(READY_STAT  | SEEK_STAT)
 #define DATA_READY		(DRQ_STAT)
 
@@ -153,6 +138,7 @@
  */
 #define PRD_BYTES	8
 #define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
+#define PRD_SEGMENTS	32
 
 /*
  * Some more useful definitions
@@ -175,24 +161,24 @@
 #define WAIT_CMD	(10*HZ)		/* 10sec  - maximum wait for an IRQ to happen */
 #define WAIT_MIN_SLEEP	(2*HZ/100)	/* 20msec - minimum sleep time */
 
-#define SELECT_DRIVE(hwif,drive)				\
+#define SELECT_DRIVE(channel, drive)				\
 {								\
-	if (hwif->selectproc)					\
-		hwif->selectproc(drive);			\
-	OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \
+	if (channel->selectproc)				\
+		channel->selectproc(drive);			\
+	OUT_BYTE((drive)->select.all, channel->io_ports[IDE_SELECT_OFFSET]); \
 }
 
-#define SELECT_MASK(hwif,drive,mask)				\
+#define SELECT_MASK(channel, drive, mask)			\
 {								\
-	if (hwif->maskproc)					\
-		hwif->maskproc(drive,mask);			\
+	if (channel->maskproc)					\
+		channel->maskproc(drive,mask);			\
 }
 
 /*
  * Check for an interrupt and acknowledge the interrupt status
  */
-struct hwif_s;
-typedef int (ide_ack_intr_t)(struct hwif_s *);
+struct ata_channel;
+typedef int (ide_ack_intr_t)(struct ata_channel *);
 
 #ifndef NO_DMA
 # define NO_DMA  255
@@ -235,7 +221,6 @@
 	int		irq;			/* our irq number */
 	int		dma;			/* our dma entry */
 	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
-	void		*priv;			/* interface specific data */
 	hwif_chipset_t  chipset;
 } hw_regs_t;
 
@@ -288,37 +273,81 @@
 	} b;
 } special_t;
 
+#define IDE_MAX_TAG	32		/* spec says 32 max */
+
+struct ata_request;
+typedef struct ide_tag_info_s {
+	unsigned long tag_mask;			/* next tag bit mask */
+	struct ata_request *ar[IDE_MAX_TAG];	/* in-progress requests */
+	int active_tag;				/* current active tag */
+	int queued;				/* current depth */
+
+	/*
+	 * stats ->
+	 */
+	int max_depth;				/* max depth ever */
+	int max_last_depth;			/* max since last check */
+
+	/*
+	 * Either the command completed immediately after being started
+	 * (immed_comp), or the device did a bus release before dma was
+	 * started (immed_rel).
+	 */
+	int immed_rel;
+	int immed_comp;
+} ide_tag_info_t;
+
+#define IDE_GET_AR(drive, tag)	((drive)->tcq->ar[(tag)])
+#define IDE_CUR_TAG(drive)	(IDE_GET_AR((drive), (drive)->tcq->active_tag))
+#define IDE_SET_CUR_TAG(drive, tag)	((drive)->tcq->active_tag = (tag))
+
+#define IDE_CUR_AR(drive)	\
+	((drive)->using_tcq ? IDE_CUR_TAG((drive)) : HWGROUP((drive))->rq->special)
+
 struct ide_settings_s;
 
 typedef struct ide_drive_s {
-	unsigned int	usage;		/* current "open()" count for drive */
+	struct ata_channel *channel;	/* parent pointer to the channel we are attached to  */
+
+	unsigned int usage;		/* current "open()" count for drive */
 	char type; /* distingiush different devices: disk, cdrom, tape, floppy, ... */
 
 	/* NOTE: If we had proper separation between channel and host chip, we
-	 * could move this to the chanell and many sync problems would
+	 * could move this to the channel and many sync problems would
 	 * magically just go away.
 	 */
-	request_queue_t		 queue;	/* per device request queue */
+	request_queue_t	queue;	/* per device request queue */
+
+	struct list_head free_req; /* free ata requests */
 
 	struct ide_drive_s	*next;	/* circular list of hwgroup drives */
-	unsigned long sleep;		/* sleep until this time */
-	unsigned long service_start;	/* time we started last request */
-	unsigned long service_time;	/* service time of last request */
-	unsigned long timeout;		/* max time to wait for irq */
+
+	/* Those are directly injected jiffie values. They should go away and
+	 * we should use generic timers instead!!!
+	 */
+
+	unsigned long PADAM_sleep;		/* sleep until this time */
+	unsigned long PADAM_service_start;	/* time we started last request */
+	unsigned long PADAM_service_time;	/* service time of last request */
+	unsigned long PADAM_timeout;		/* max time to wait for irq */
+
 	special_t	special;	/* special action flags */
 	byte     keep_settings;		/* restore settings after drive reset */
 	byte     using_dma;		/* disk is using dma for read/write */
+	byte	 using_tcq;		/* disk is using queued dma operations*/
 	byte	 retry_pio;		/* retrying dma capable host in pio */
 	byte	 state;			/* retry state */
 	byte     unmask;		/* flag: okay to unmask other irqs */
 	byte     slow;			/* flag: slow data port */
 	byte     bswap;			/* flag: byte swap data */
 	byte     dsc_overlap;		/* flag: DSC overlap */
-	byte     nice1;			/* flag: give potential excess bandwidth */
+
 	unsigned waiting_for_dma: 1;	/* dma currently in progress */
+	unsigned busy		: 1;	/* currently doing revalidate_disk() */
+	unsigned blocked        : 1;	/* 1=powermanagment told us not to do anything, so sleep nicely */
+
 	unsigned present	: 1;	/* drive is physically present */
 	unsigned noprobe	: 1;	/* from:  hdx=noprobe */
-	unsigned busy		: 1;	/* currently doing revalidate_disk() */
 	unsigned removable	: 1;	/* 1 if need to do check_media_change */
 	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
 	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
@@ -326,21 +355,18 @@
 	unsigned nobios		: 1;	/* flag: do not probe bios for drive */
 	unsigned revalidate	: 1;	/* request revalidation */
 	unsigned atapi_overlap	: 1;	/* flag: ATAPI overlap (not supported) */
-	unsigned nice0		: 1;	/* flag: give obvious excess bandwidth */
-	unsigned nice2		: 1;	/* flag: give a share in our own bandwidth */
 	unsigned doorlocking	: 1;	/* flag: for removable only: door lock/unlock works */
 	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
 	unsigned remap_0_to_1	: 2;	/* 0=remap if ezdrive, 1=remap, 2=noremap */
 	unsigned ata_flash	: 1;	/* 1=present, 0=default */
-	unsigned blocked        : 1;	/* 1=powermanagment told us not to do anything, so sleep nicely */
 	unsigned	addressing;	/* : 2; 0=28-bit, 1=48-bit, 2=64-bit */
 	byte		scsi;		/* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
 	select_t	select;		/* basic drive/head select reg value */
 	byte		ctl;		/* "normal" value for IDE_CONTROL_REG */
 	byte		ready_stat;	/* min status value for drive ready */
 	byte		mult_count;	/* current multiple sector setting */
-	byte 		mult_req;	/* requested multiple sector setting */
-	byte 		tune_req;	/* requested drive tuning setting */
+	byte		mult_req;	/* requested multiple sector setting */
+	byte		tune_req;	/* requested drive tuning setting */
 	byte		io_32bit;	/* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
 	byte		bad_wstat;	/* used for ignoring WRERR_STAT */
 	byte		nowerr;		/* used for ignoring WRERR_STAT */
@@ -354,20 +380,25 @@
 	unsigned long	capacity;	/* total number of sectors */
 	unsigned long long capacity48;	/* total number of sectors */
 	unsigned int	drive_data;	/* for use by tuneproc/selectproc as needed */
-	struct hwif_s   *hwif;		/* parent pointer to the interface we are attached to  */
+
 	wait_queue_head_t wqueue;	/* used to wait for drive in open() */
+
 	struct hd_driveid *id;		/* drive model identification info */
 	struct hd_struct  *part;	/* drive partition table */
-	char		name[4];	/* drive name, such as "hda" */
+
+	char		name[6];	/* drive name, such as "hda" */
 	struct ata_operations *driver;
+
 	void		*driver_data;	/* extra driver data */
 	devfs_handle_t	de;		/* directory for device */
 	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
 	struct ide_settings_s *settings;    /* /proc/ide/ drive settings */
 	char		driver_req[10];	/* requests specific driver */
+
 	int		last_lun;	/* last logical unit */
 	int		forced_lun;	/* if hdxlun was given at boot */
 	int		lun;		/* logical unit */
+
 	int		crc_count;	/* crc counter to reduce drive speed */
 	byte		quirk_list;	/* drive is considered quirky if set for a specific host */
 	byte		suspend_reset;	/* drive suspend mode flag, soft-reset recovers */
@@ -379,6 +410,8 @@
 	unsigned int	failures;	/* current failure count */
 	unsigned int	max_failures;	/* maximum allowed failure count */
 	struct device	device;		/* global device tree handle */
+	unsigned int	queue_depth;
+	ide_tag_info_t	*tcq;
 } ide_drive_t;
 
 /*
@@ -397,7 +430,10 @@
 		ide_dma_off,	ide_dma_off_quietly,	ide_dma_test_irq,
 		ide_dma_bad_drive,			ide_dma_good_drive,
 		ide_dma_verbose,			ide_dma_retune,
-		ide_dma_lostirq,			ide_dma_timeout
+		ide_dma_lostirq,			ide_dma_timeout,
+		ide_dma_read_queued,			ide_dma_write_queued,
+		ide_dma_queued_start,			ide_dma_queued_on,
+		ide_dma_queued_off,
 } ide_dma_action_t;
 
 typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
@@ -409,7 +445,7 @@
  *
  * If it is not defined for a controller, standard-code is used from ide.c.
  *
- * Controllers which are not memory-mapped in the standard way need to 
+ * Controllers which are not memory-mapped in the standard way need to
  * override that mechanism using this function to work.
  *
  */
@@ -443,16 +479,23 @@
 typedef void (ide_maskproc_t) (ide_drive_t *, int);
 typedef void (ide_rw_proc_t) (ide_drive_t *, ide_dma_action_t);
 
-/*
- * ide soft-power support
- */
-typedef int (ide_busproc_t) (ide_drive_t *, int);
+enum {
+	ATA_PRIMARY	= 0,
+	ATA_SECONDARY	= 1
+};
+
+struct ata_channel {
+	struct device	dev;		/* device handle */
+	int		unit;		/* channel number */
 
-typedef struct hwif_s {
-	struct hwif_s	*next;		/* for linked-list in ide_hwgroup_t */
+	struct ata_channel *next;	/* for linked-list in ide_hwgroup_t */
 	struct hwgroup_s *hwgroup;	/* actually (ide_hwgroup_t *) */
+
 	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
 	hw_regs_t	hw;		/* Hardware info */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+	struct pci_dev	*pci_dev;	/* for pci chipsets */
+#endif
 	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
 	struct gendisk	*gd;		/* gendisk structure */
 	ide_tuneproc_t	*tuneproc;	/* routine to tune PIO mode for drives */
@@ -465,12 +508,6 @@
 	ide_rw_proc_t	*rwproc;	/* adjust timing based upon rq->cmd direction */
 	ide_ideproc_t   *ideproc;       /* CPU-polled transfer routine */
 	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
-	unsigned int	*dmatable_cpu;	/* dma physical region descriptor table (cpu view) */
-	dma_addr_t	dmatable_dma;	/* dma physical region descriptor table (dma view) */
-	struct scatterlist *sg_table;	/* Scatter-gather list used to build the above */
-	int sg_nents;			/* Current number of entries in it */
-	int sg_dma_direction;		/* dma transfer direction */
-	struct hwif_s	*mate;		/* other hwif from same PCI chip */
 	unsigned long	dma_base;	/* base addr for dma ports */
 	unsigned	dma_extra;	/* extra addr for dma ports */
 	unsigned long	config_data;	/* for use by chipset-specific code */
@@ -478,50 +515,46 @@
 	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
 	int		irq;		/* our irq number */
 	int		major;		/* our major number */
-	char		name[80];	/* name of interface */
+	char		name[8];	/* name of interface */
 	int		index;		/* 0 for ide0; 1 for ide1; ... */
 	hwif_chipset_t	chipset;	/* sub-module for tuning.. */
 	unsigned	noprobe    : 1;	/* don't probe for this interface */
 	unsigned	present    : 1;	/* there is a device on this interface */
-	unsigned	serialized : 1;	/* serialized operation with mate hwif */
+	unsigned	serialized : 1;	/* serialized operation between channels */
 	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
 	unsigned	reset      : 1;	/* reset after probe */
 	unsigned	autodma    : 1;	/* automatically try to enable DMA at boot */
 	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
 	unsigned	highmem	   : 1; /* can do full 32-bit dma */
-	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	struct pci_dev	*pci_dev;	/* for pci chipsets */
-#endif
 #if (DISK_RECOVERY_TIME > 0)
 	unsigned long	last_time;	/* time when previous rq was done */
 #endif
 	byte		straight8;	/* Alan's straight 8 check */
-	ide_busproc_t	*busproc;	/* driver soft-power interface */
+	int (*busproc)(ide_drive_t *, int);	/* driver soft-power interface */
 	byte		bus_state;	/* power state of the IDE bus */
-	struct device	device;		/* global device tree handle */
-} ide_hwif_t;
+};
 
 /*
  * Register new hardware with ide
  */
-extern int ide_register_hw(hw_regs_t *hw, struct hwif_s **hwifp);
-extern void ide_unregister(ide_hwif_t *hwif);
+extern int ide_register_hw(hw_regs_t *hw, struct ata_channel **hwifp);
+extern void ide_unregister(struct ata_channel *hwif);
 
 /*
- * Status returned from various ide_ functions
+ * Status returned by various functions.
  */
 typedef enum {
 	ide_stopped,	/* no drive operation was started */
-	ide_started	/* a drive operation was started, and a handler was set */
+	ide_started,	/* a drive operation was started, and a handler was set */
+	ide_released	/* started and released bus */
 } ide_startstop_t;
 
 /*
- *  internal ide interrupt handler type
+ *  Interrupt handler types.
  */
+struct ata_taskfile;
 typedef ide_startstop_t (ide_pre_handler_t)(ide_drive_t *, struct request *);
 typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
-typedef ide_startstop_t (ide_post_handler_t)(ide_drive_t *);
 
 /*
  * when ide_timer_expiry fires, invoke a handler of this type
@@ -529,23 +562,24 @@
  */
 typedef int (ide_expiry_t)(ide_drive_t *);
 
-#define IDE_BUSY	0
+#define IDE_BUSY	0	/* awaiting an interrupt */
 #define IDE_SLEEP	1
+#define IDE_DMA		2	/* DMA in progress */
 
 typedef struct hwgroup_s {
-	ide_handler_t		*handler;/* irq handler, if active */
-	unsigned long		flags;	/* BUSY, SLEEPING */
-	ide_drive_t		*drive;	/* current drive */
-	ide_hwif_t		*hwif;	/* ptr to current hwif in linked-list */
-	struct request		*rq;	/* current request */
-	struct timer_list	timer;	/* failsafe timer */
-	struct request		wrq;	/* local copy of current write rq */
+	ide_handler_t		*handler;	/* irq handler, if active */
+	unsigned long		flags;		/* BUSY, SLEEPING */
+	ide_drive_t		*drive;		/* current drive */
+	struct ata_channel	*hwif;		/* ptr to current hwif in linked-list */
+
+	struct request		*rq;		/* current request */
+
+	struct timer_list	timer;		/* failsafe timer */
+	struct request		wrq;		/* local copy of current write rq */
 	unsigned long		poll_timeout;	/* timeout value during long polls */
 	ide_expiry_t		*expiry;	/* queried upon timeouts */
 } ide_hwgroup_t;
 
-/* structure attached to the request for IDE_TASK_CMDS */
-
 /*
  * configurable drive settings
  */
@@ -595,7 +629,7 @@
 #ifdef CONFIG_PROC_FS
 void proc_ide_create(void);
 void proc_ide_destroy(void);
-void destroy_proc_ide_drives(ide_hwif_t *);
+void destroy_proc_ide_drives(struct ata_channel *);
 void create_proc_ide_interfaces(void);
 void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
 void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
@@ -618,7 +652,7 @@
 	return len;			\
 }
 #else
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
+# define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
 #endif
 
 /*
@@ -630,7 +664,6 @@
 
 struct ata_operations {
 	struct module *owner;
-	unsigned busy: 1; /* FIXME: this will go soon away... */
 	int (*cleanup)(ide_drive_t *);
 	int (*standby)(ide_drive_t *);
 	ide_startstop_t	(*do_request)(ide_drive_t *, struct request *, unsigned long);
@@ -645,6 +678,7 @@
 	void (*pre_reset)(ide_drive_t *);
 	unsigned long (*capacity)(ide_drive_t *);
 	ide_startstop_t	(*special)(ide_drive_t *);
+
 	ide_proc_entry_t *proc;
 };
 
@@ -670,15 +704,7 @@
 
 #define ata_ops(drive)		((drive)->driver)
 
-/*
- * ide_hwifs[] is the master data structure used to keep track
- * of just about everything in ide.c.  Whenever possible, routines
- * should be using pointers to a drive (ide_drive_t *) or
- * pointers to a hwif (ide_hwif_t *), rather than indexing this
- * structure directly (the allocation/layout may change!).
- *
- */
-extern struct hwif_s ide_hwifs[];		/* master data repository */
+extern struct ata_channel ide_hwifs[];		/* master data repository */
 extern int noautodma;
 
 /*
@@ -690,6 +716,7 @@
 
 extern int __ide_end_request(ide_drive_t *drive, int uptodate, int nr_secs);
 extern int ide_end_request(ide_drive_t *drive, int uptodate);
+extern void ide_end_queued_request(ide_drive_t *drive, int, struct request *);
 
 /*
  * This is used on exit from the driver, to designate the next irq handler
@@ -712,7 +739,7 @@
  * Issue a simple drive command
  * The drive must be selected beforehand.
  */
-void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
+void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
 
 /*
  * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
@@ -720,7 +747,7 @@
  * It is primarily used to tidy up the model name/number fields as
  * returned by the WIN_[P]IDENTIFY commands.
  */
-void ide_fixstring (byte *s, const int bytecount, const int byteswap);
+void ide_fixstring(byte *s, const int bytecount, const int byteswap);
 
 /*
  * This routine busy-waits for the drive status to be not "busy".
@@ -730,31 +757,32 @@
  * caller should return the updated value of "startstop" in this case.
  * "startstop" is unchanged when the function returns 0;
  */
-int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
+int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
 
-int ide_wait_noerr (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
+int ide_wait_noerr(ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
 
 /*
  * This routine is called from the partition-table code in genhd.c
  * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
  */
-int ide_xlate_1024 (kdev_t, int, int, const char *);
+int ide_xlate_1024(kdev_t, int, int, const char *);
 
 /*
  * Convert kdev_t structure into ide_drive_t * one.
  */
-ide_drive_t *get_info_ptr (kdev_t i_rdev);
+ide_drive_t *get_info_ptr(kdev_t i_rdev);
 
 /*
  * Re-Start an operation for an IDE interface.
  * The caller should return immediately after invoking this.
  */
-ide_startstop_t restart_request (ide_drive_t *);
+ide_startstop_t restart_request(ide_drive_t *);
 
 /*
  * This function is intended to be used prior to invoking ide_do_drive_cmd().
  */
-void ide_init_drive_cmd (struct request *rq);
+extern void ide_init_drive_cmd(struct request *rq);
+extern void init_taskfile_request(struct request *rq);
 
 /*
  * "action" parameter type for ide_do_drive_cmd() below.
@@ -771,54 +799,45 @@
  */
 #define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
 
-#define task_rq_offset(rq) \
-	(((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE)
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed.  This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed.  As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
+extern int ide_do_drive_cmd(ide_drive_t *drive, struct request *rq, ide_action_t action);
 
 /*
  * Clean up after success/failure of an explicit drive cmd.
  */
 void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
 
-typedef struct ide_task_s {
-	task_ioreg_t		tfRegister[8];
-	task_ioreg_t		hobRegister[8];
-	ide_reg_valid_t		tf_out_flags;
-	ide_reg_valid_t		tf_in_flags;
-	int			data_phase;
+struct ata_taskfile {
+	struct hd_drive_task_hdr taskfile;
+	struct hd_drive_hob_hdr  hobfile;
 	int			command_type;
 	ide_pre_handler_t	*prehandler;
 	ide_handler_t		*handler;
-	void			*special;	/* valid_t generally */
-	struct request		*rq;		/* copy of request */
-	unsigned long		block;		/* copy of block */
-} ide_task_t;
+	struct ata_request	*ar;
+};
+
+/*
+ * Merge this with the above struct soon.
+ */
+struct ata_request {
+	struct request		*ar_rq;		/* real request */
+	struct ide_drive_s	*ar_drive;	/* associated drive */
+	unsigned long		ar_flags;	/* ATA_AR_* flags */
+	int			ar_tag;		/* tag number, if any */
+	struct list_head	ar_queue;	/* pending list */
+	struct ata_taskfile	ar_task;	/* associated taskfile */
+	unsigned long		ar_time;
+
+	/* DMA stuff, PCI layer */
+	struct scatterlist	*ar_sg_table;
+	int			ar_sg_nents;
+	int			ar_sg_ddir;
+
+	/* CPU related DMA stuff  */
+	unsigned int		*ar_dmatable_cpu;
+	dma_addr_t		ar_dmatable;
+};
+
+#define AR_TASK_CMD(ar)	((ar)->ar_task.taskfile.command)
 
 void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
 void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
@@ -827,15 +846,8 @@
 void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
 void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
 
-/*
- * taskfile io for disks for now...
- */
-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task);
-
-/*
- * Builds request from ide_ioctl
- */
-void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler);
+extern ide_startstop_t ata_taskfile(ide_drive_t *drive,
+		struct ata_taskfile *args, struct request *rq);
 
 /*
  * Special Flagged Register Validation Caller
@@ -846,24 +858,23 @@
 extern ide_startstop_t set_multmode_intr(ide_drive_t *drive);
 extern ide_startstop_t task_no_data_intr(ide_drive_t *drive);
 
-int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf);
 
-int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *cmd, byte *buf);
-
-/* Expects args is a full set of TF registers and parses the command type */
-extern void ide_cmd_type_parser(ide_task_t *args);
+/* This is setting up all fields in args, which depend upon the command type.
+ */
+extern void ide_cmd_type_parser(struct ata_taskfile *args);
+extern int ide_raw_taskfile(ide_drive_t *drive, struct ata_taskfile *cmd, byte *buf);
 
-int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+extern int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg);
+extern int ide_task_ioctl(ide_drive_t *drive, unsigned long arg);
 
-void ide_delay_50ms (void);
+void ide_delay_50ms(void);
 
 byte ide_auto_reduce_xfer (ide_drive_t *drive);
 int ide_driveid_update (ide_drive_t *drive);
-int ide_ata66_check (ide_drive_t *drive, ide_task_t *args);
+int ide_ata66_check (ide_drive_t *drive, struct ata_taskfile *args);
 int ide_config_drive_speed (ide_drive_t *drive, byte speed);
 byte eighty_ninty_three (ide_drive_t *drive);
-int set_transfer (ide_drive_t *drive, ide_task_t *args);
+int set_transfer (ide_drive_t *drive, struct ata_taskfile *args);
 
 extern int system_bus_speed;
 
@@ -871,7 +882,7 @@
  * idedisk_input_data() is a wrapper around ide_input_data() which copes
  * with byte-swapping the input data if required.
  */
-inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+extern void idedisk_input_data(ide_drive_t *drive, void *buffer, unsigned int wcount);
 
 /*
  * ide_stall_queue() can be used by a drive to give excess bandwidth back
@@ -928,31 +939,118 @@
 extern int ide_unregister_subdriver(ide_drive_t *drive);
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
-#define ON_BOARD		1
-#define NEVER_BOARD		0
-#ifdef CONFIG_BLK_DEV_OFFBOARD
-# define OFF_BOARD		ON_BOARD
-#else
-# define OFF_BOARD		NEVER_BOARD
-#endif
+# define ON_BOARD		1
+# define NEVER_BOARD		0
+# ifdef CONFIG_BLK_DEV_OFFBOARD
+#  define OFF_BOARD		ON_BOARD
+# else
+#  define OFF_BOARD		NEVER_BOARD
+# endif
 
-void __init ide_scan_pcibus(int scan_direction);
+/* FIXME: This should go away possible. */
+extern void __init ide_scan_pcibus(int scan_direction);
 #endif
 #ifdef CONFIG_BLK_DEV_IDEDMA
-# define BAD_DMA_DRIVE		0
-# define GOOD_DMA_DRIVE		1
-int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func);
-void ide_destroy_dmatable (ide_drive_t *drive);
-ide_startstop_t ide_dma_intr (ide_drive_t *drive);
-int check_drive_lists (ide_drive_t *drive, int good_bad);
-int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
-extern void ide_release_dma(ide_hwif_t *hwif);
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
+extern int ide_build_dmatable(ide_drive_t *drive, struct request *rq, ide_dma_action_t func);
+extern void ide_destroy_dmatable(ide_drive_t *drive);
+extern int ide_start_dma(struct ata_channel *, ide_drive_t *, ide_dma_action_t);
+extern ide_startstop_t ide_dma_intr(ide_drive_t *drive);
+extern int check_drive_lists(ide_drive_t *drive, int good_bad);
+extern int ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
+extern void ide_release_dma(struct ata_channel *hwif);
+extern void ide_setup_dma(struct ata_channel *hwif,
+		unsigned long dmabase, unsigned int num_ports) __init;
 #endif
 
 extern spinlock_t ide_lock;
 
+#define DRIVE_LOCK(drive)		((drive)->queue.queue_lock)
+
 extern int drive_is_ready(ide_drive_t *drive);
 extern void revalidate_drives(void);
 
-#endif /* _IDE_H */
+/*
+ * Tagged Command Queueing:
+ */
+
+/*
+ * ata_request flag bits
+ */
+#define ATA_AR_QUEUED	1
+#define ATA_AR_SETUP	2
+#define ATA_AR_RETURN	4
+
+#define list_ata_entry(entry) list_entry((entry), struct ata_request, ar_queue)
+
+static inline void ata_ar_init(ide_drive_t *drive, struct ata_request *ar)
+{
+	ar->ar_rq = NULL;
+	ar->ar_drive = drive;
+	ar->ar_flags = 0;
+	ar->ar_tag = 0;
+	memset(&ar->ar_task, 0, sizeof(ar->ar_task));
+	ar->ar_sg_nents = 0;
+	ar->ar_sg_ddir = 0;
+}
+
+/*
+ * Return a free command, automatically add it to busy list.
+ */
+static inline struct ata_request *ata_ar_get(ide_drive_t *drive)
+{
+	struct ata_request *ar = NULL;
+
+	if (drive->tcq && drive->tcq->queued >= drive->queue_depth)
+		return NULL;
+
+	if (!list_empty(&drive->free_req)) {
+		ar = list_ata_entry(drive->free_req.next);
+		list_del(&ar->ar_queue);
+		ata_ar_init(drive, ar);
+	}
+
+	return ar;
+}
+
+static inline void ata_ar_put(ide_drive_t *drive, struct ata_request *ar)
+{
+	list_add(&ar->ar_queue, &drive->free_req);
+
+	if (ar->ar_flags & ATA_AR_QUEUED) {
+		/* clear the tag */
+		drive->tcq->ar[ar->ar_tag] = NULL;
+		__clear_bit(ar->ar_tag, &drive->tcq->tag_mask);
+		drive->tcq->queued--;
+	}
+
+	ar->ar_rq = NULL;
+}
+
+extern inline int ide_get_tag(ide_drive_t *drive)
+{
+	int tag = ffz(drive->tcq->tag_mask);
+
+	BUG_ON(drive->tcq->tag_mask == 0xffffffff);
+
+	__set_bit(tag, &drive->tcq->tag_mask);
+
+	if (tag + 1 > drive->tcq->max_depth)
+		drive->tcq->max_depth = tag + 1;
+	if (tag + 1 > drive->tcq->max_last_depth)
+		drive->tcq->max_last_depth = tag + 1;
+
+	return tag;
+}
+
+#ifdef CONFIG_BLK_DEV_IDE_TCQ
+# define ide_pending_commands(drive)	((drive)->using_tcq && (drive)->tcq->queued)
+#else
+# define ide_pending_commands(drive)	0
+#endif
+
+int ide_build_commandlist(ide_drive_t *);
+void ide_teardown_commandlist(ide_drive_t *);
+int ide_tcq_dmaproc(ide_dma_action_t, ide_drive_t *);
+ide_startstop_t ide_start_tag(ide_dma_action_t, ide_drive_t *, struct ata_request *);
+
+#endif
diff -Nru a/include/linux/if_pppox.h b/include/linux/if_pppox.h
--- a/include/linux/if_pppox.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/if_pppox.h	Sun Apr 14 12:16:56 2002
@@ -147,13 +147,14 @@
 extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd,
 			       unsigned long arg);
 
-/* PPPoE socket states */
+/* PPPoX socket states */
 enum {
     PPPOX_NONE		= 0,  /* initial state */
     PPPOX_CONNECTED	= 1,  /* connection established ==TCP_ESTABLISHED */
     PPPOX_BOUND		= 2,  /* bound to ppp device */
     PPPOX_RELAY		= 4,  /* forwarding is enabled */
-    PPPOX_DEAD		= 8
+    PPPOX_ZOMBIE	= 8,  /* dead, but still bound to ppp device */
+    PPPOX_DEAD		= 16  /* dead, useless, please clean me up!*/
 };
 
 extern struct ppp_channel_ops pppoe_chan_ops;
diff -Nru a/include/linux/inetdevice.h b/include/linux/inetdevice.h
--- a/include/linux/inetdevice.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/inetdevice.h	Sun Apr 14 12:16:55 2002
@@ -18,6 +18,7 @@
 	int	mc_forwarding;
 	int	tag;
 	int     arp_filter;
+	int	medium_id;
 	void	*sysctl;
 };
 
@@ -48,6 +49,7 @@
 #define IN_DEV_TX_REDIRECTS(in_dev)	(ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects)
 #define IN_DEV_SEC_REDIRECTS(in_dev)	(ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
 #define IN_DEV_IDTAG(in_dev)		((in_dev)->cnf.tag)
+#define IN_DEV_MEDIUM_ID(in_dev)	((in_dev)->cnf.medium_id)
 
 #define IN_DEV_RX_REDIRECTS(in_dev) \
 	((IN_DEV_FORWARD(in_dev) && \
diff -Nru a/include/linux/iobuf.h b/include/linux/iobuf.h
--- a/include/linux/iobuf.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/iobuf.h	Sun Apr 14 12:16:56 2002
@@ -80,9 +80,9 @@
 /* fs/buffer.c */
 
 int	brw_kiovec(int rw, int nr, struct kiobuf *iovec[], 
-		   kdev_t dev, sector_t [], int size);
+		   struct block_device *bdev, sector_t [], int size);
 
 /* fs/bio.c */
-void	ll_rw_kio(int rw, struct kiobuf *kio, kdev_t dev, sector_t block);
+void	ll_rw_kio(int rw, struct kiobuf *kio, struct block_device *bdev, sector_t block);
 
 #endif /* __LINUX_IOBUF_H */
diff -Nru a/include/linux/minix_fs.h b/include/linux/minix_fs.h
--- a/include/linux/minix_fs.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/minix_fs.h	Sun Apr 14 12:16:55 2002
@@ -29,11 +29,6 @@
 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
 
-#define MINIX_V1		0x0001		/* original minix fs */
-#define MINIX_V2		0x0002		/* minix V2 fs */
-
-#define INODE_VERSION(inode)	minix_sb(inode->i_sb)->s_version
-
 /*
  * This is the original minix inode layout on disk.
  * Note the 8-bit gid and atime and ctime.
@@ -86,62 +81,5 @@
 	__u16 inode;
 	char name[0];
 };
-
-#ifdef __KERNEL__
-
-#include <linux/minix_fs_i.h>
-#include <linux/minix_fs_sb.h>
-
-/*
- * change the define below to 0 if you want names > info->s_namelen chars to be
- * truncated. Else they will be disallowed (ENAMETOOLONG).
- */
-#define NO_TRUNCATE 1
-
-extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, struct buffer_head **);
-extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **);
-extern struct inode * minix_new_inode(const struct inode * dir, int * error);
-extern void minix_free_inode(struct inode * inode);
-extern unsigned long minix_count_free_inodes(struct super_block *sb);
-extern int minix_new_block(struct inode * inode);
-extern void minix_free_block(struct inode * inode, int block);
-extern unsigned long minix_count_free_blocks(struct super_block *sb);
-
-extern void V1_minix_truncate(struct inode *);
-extern void V2_minix_truncate(struct inode *);
-extern void minix_truncate(struct inode *);
-extern int minix_sync_inode(struct inode *);
-extern void minix_set_inode(struct inode *, dev_t);
-extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
-extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
-
-extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**);
-extern int minix_add_link(struct dentry*, struct inode*);
-extern int minix_delete_entry(struct minix_dir_entry*, struct page*);
-extern int minix_make_empty(struct inode*, struct inode*);
-extern int minix_empty_dir(struct inode*);
-extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
-extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
-extern ino_t minix_inode_by_name(struct dentry*);
-
-extern int minix_sync_file(struct file *, struct dentry *, int);
-
-extern struct inode_operations minix_file_inode_operations;
-extern struct inode_operations minix_dir_inode_operations;
-extern struct file_operations minix_file_operations;
-extern struct file_operations minix_dir_operations;
-extern struct dentry_operations minix_dentry_operations;
-
-static inline struct minix_sb_info *minix_sb(struct super_block *sb)
-{
-	return sb->u.generic_sbp;
-}
-
-static inline struct minix_inode_info *minix_i(struct inode *inode)
-{
-	return list_entry(inode, struct minix_inode_info, vfs_inode);
-}
-
-#endif /* __KERNEL__ */
 
 #endif
diff -Nru a/include/linux/minix_fs_i.h b/include/linux/minix_fs_i.h
--- a/include/linux/minix_fs_i.h	Sun Apr 14 12:16:57 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,15 +0,0 @@
-#ifndef _MINIX_FS_I
-#define _MINIX_FS_I
-
-/*
- * minix fs inode data in memory
- */
-struct minix_inode_info {
-	union {
-		__u16 i1_data[16];
-		__u32 i2_data[16];
-	} u;
-	struct inode vfs_inode;
-};
-
-#endif
diff -Nru a/include/linux/minix_fs_sb.h b/include/linux/minix_fs_sb.h
--- a/include/linux/minix_fs_sb.h	Sun Apr 14 12:16:59 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-#ifndef _MINIX_FS_SB
-#define _MINIX_FS_SB
-
-/*
- * minix super-block data in memory
- */
-struct minix_sb_info {
-			unsigned long s_ninodes;
-			unsigned long s_nzones;
-			unsigned long s_imap_blocks;
-			unsigned long s_zmap_blocks;
-			unsigned long s_firstdatazone;
-			unsigned long s_log_zone_size;
-			unsigned long s_max_size;
-			int s_dirsize;
-			int s_namelen;
-			int s_link_max;
-			struct buffer_head ** s_imap;
-			struct buffer_head ** s_zmap;
-			struct buffer_head * s_sbh;
-			struct minix_super_block * s_ms;
-			unsigned short s_mount_state;
-			unsigned short s_version;
-};
-
-#endif
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/mm.h	Sun Apr 14 12:16:55 2002
@@ -149,15 +149,12 @@
 	struct list_head list;		/* ->mapping has some page lists. */
 	struct address_space *mapping;	/* The inode (or ...) we belong to. */
 	unsigned long index;		/* Our offset within mapping. */
-	struct page *next_hash;		/* Next page sharing our hash bucket in
-					   the pagecache hash table. */
 	atomic_t count;			/* Usage count, see below. */
 	unsigned long flags;		/* atomic flags, some possibly
 					   updated asynchronously */
 	struct list_head lru;		/* Pageout list, eg. active_list;
 					   protected by pagemap_lru_lock !! */
-	struct page **pprev_hash;	/* Complement to *next_hash. */
-	struct buffer_head * buffers;	/* Buffer maps us to a disk block. */
+	unsigned long private;		/* fs-private opaque data */
 
 	/*
 	 * On machines where all RAM is mapped into kernel address space,
@@ -180,7 +177,7 @@
  *
  * What counts for a page usage:
  * - cache mapping   (page->mapping)
- * - disk mapping    (page->buffers)
+ * - private data    (page->private)
  * - page mapped in a task's page tables, each mapping
  *   is counted separately
  *
@@ -223,22 +220,23 @@
  * page->mapping is the pointer to the inode, and page->index is the
  * file offset of the page, in units of PAGE_CACHE_SIZE.
  *
- * A page may have buffers allocated to it. In this case,
- * page->buffers is a circular list of these buffer heads. Else,
- * page->buffers == NULL.
+ * A page contains an opaque `private' member, which belongs to the
+ * page's address_space.  Usually, this is the address of a circular
+ * list of the page's disk buffers.
  *
+ * The PG_private bitflag is set if page->private contains a valid
+ * value.
  * For pages belonging to inodes, the page->count is the number of
- * attaches, plus 1 if buffers are allocated to the page, plus one
- * for the page cache itself.
+ * attaches, plus 1 if `private' contains something, plus one for
+ * the page cache itself.
  *
  * All pages belonging to an inode are in these doubly linked lists:
  * mapping->clean_pages, mapping->dirty_pages and mapping->locked_pages;
  * using the page->list list_head. These fields are also used for
  * freelist managemet (when page->count==0).
  *
- * There is also a hash table mapping (mapping,index) to the page
- * in memory if present. The lists for this hash table use the fields
- * page->next_hash and page->pprev_hash.
+ * There is also a per-mapping radix tree mapping index to the page
+ * in memory if present. The tree is rooted at mapping->root.  
  *
  * All process pages can do I/O:
  * - inode pages may need to be read from disk,
@@ -294,6 +292,8 @@
 #define PG_reserved		14
 #define PG_launder		15	/* written out by VM pressure.. */
 
+#define PG_private		16	/* Has something at ->private */
+
 /* Make it prettier to test the above... */
 #define UnlockPage(page)	unlock_page(page)
 #define Page_Uptodate(page)	test_bit(PG_uptodate, &(page)->flags)
@@ -310,6 +310,9 @@
 #define PageLaunder(page)	test_bit(PG_launder, &(page)->flags)
 #define SetPageLaunder(page)	set_bit(PG_launder, &(page)->flags)
 #define __SetPageReserved(page)	__set_bit(PG_reserved, &(page)->flags)
+#define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
+#define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
+#define PagePrivate(page)	test_bit(PG_private, &(page)->flags)
 
 /*
  * The zone field is never updated after free_area_init_core()
@@ -470,7 +473,7 @@
 
 static inline int is_page_cache_freeable(struct page * page)
 {
-	return page_count(page) - !!page->buffers == 1;
+	return page_count(page) - !!PagePrivate(page) == 1;
 }
 
 extern int can_share_swap_page(struct page *);
@@ -535,6 +538,13 @@
 extern int filemap_sync(struct vm_area_struct *, unsigned long,	size_t, unsigned int);
 extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int);
 
+/* readahead.c */
+void do_page_cache_readahead(struct file *file,
+			unsigned long offset, unsigned long nr_to_read);
+void page_cache_readahead(struct file *file, unsigned long offset);
+void page_cache_readaround(struct file *file, unsigned long offset);
+void handle_ra_thrashing(struct file *file);
+
 /* vma is the first one with  address < vma->vm_end,
  * and even  address < vma->vm_start. Have to extend vma. */
 static inline int expand_stack(struct vm_area_struct * vma, unsigned long address)
@@ -578,6 +588,9 @@
 }
 
 extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);
+
+extern int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
+extern int pdflush_flush(unsigned long nr_pages);
 
 extern struct page * vmalloc_to_page(void *addr);
 
diff -Nru a/include/linux/mtd/compatmac.h b/include/linux/mtd/compatmac.h
--- a/include/linux/mtd/compatmac.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/mtd/compatmac.h	Sun Apr 14 12:16:57 2002
@@ -190,8 +190,8 @@
 
 #if LINUX_VERSION_CODE < 0x20300
 #include <linux/interrupt.h>
-#define spin_lock_bh(lock) do {start_bh_atomic();spin_lock(lock);}while(0);
-#define spin_unlock_bh(lock) do {spin_unlock(lock);end_bh_atomic();}while(0);
+#define spin_lock_bh(lock) do {start_bh_atomic();spin_lock(lock);} while(0)
+#define spin_unlock_bh(lock) do {spin_unlock(lock);end_bh_atomic();} while(0)
 #else
 #include <asm/softirq.h>
 #include <linux/spinlock.h>
diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h
--- a/include/linux/nbd.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/nbd.h	Sun Apr 14 12:16:59 2002
@@ -70,7 +70,7 @@
 	struct file * file; 		/* If == NULL, device is not ready, yet	*/
 	int magic;			/* FIXME: not if debugging is off	*/
 	struct list_head queue_head;	/* Requests are added here...			*/
-	struct semaphore queue_lock;
+	struct semaphore tx_lock;
 };
 #endif
 
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/netdevice.h	Sun Apr 14 12:16:59 2002
@@ -246,8 +246,6 @@
 	 *	I/O specific fields
 	 *	FIXME: Merge these and struct ifmap into one
 	 */
-	unsigned long		rmem_end;	/* shmem "recv" end	*/
-	unsigned long		rmem_start;	/* shmem "recv" start	*/
 	unsigned long		mem_end;	/* shared mem end	*/
 	unsigned long		mem_start;	/* shared mem start	*/
 	unsigned long		base_addr;	/* device I/O address	*/
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h	Sun Apr 14 12:16:57 2002
@@ -6,6 +6,7 @@
 
 #include <linux/config.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <asm/atomic.h>
 
 enum ip_conntrack_info
 {
@@ -62,27 +63,58 @@
 #define IP_NF_ASSERT(x)
 #endif
 
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+#include <linux/netfilter_ipv4/ip_nat.h>
+#endif
+
+/* Add protocol helper include file here */
+#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+
 struct ip_conntrack_expect
 {
-	/* Internal linked list */
+	/* Internal linked list (global expectation list) */
 	struct list_head list;
 
+	/* expectation list for this master */
+	struct list_head expected_list;
+
+	/* The conntrack of the master connection */
+	struct ip_conntrack *expectant;
+
+	/* The conntrack of the sibling connection, set after
+	 * expectation arrived */
+	struct ip_conntrack *sibling;
+
+	/* Tuple saved for conntrack */
+	struct ip_conntrack_tuple ct_tuple;
+
+	/* Timer function; deletes the expectation. */
+	struct timer_list timeout;
+
+	/* Data filled out by the conntrack helpers follow: */
+
 	/* We expect this tuple, with the following mask */
 	struct ip_conntrack_tuple tuple, mask;
 
 	/* Function to call after setup and insertion */
 	int (*expectfn)(struct ip_conntrack *new);
 
-	/* The conntrack we are part of (set iff we're live) */
-	struct ip_conntrack *expectant;
-};
-
+	/* At which sequence number did this expectation occur */
+	u_int32_t seq;
+  
+	union {
+		/* insert conntrack helper private data (expect) here */
+		struct ip_ct_ftp_expect exp_ftp_info;
+		struct ip_ct_irc_expect exp_irc_info;
+  
 #ifdef CONFIG_IP_NF_NAT_NEEDED
-#include <linux/netfilter_ipv4/ip_nat.h>
+ 		union {
+			/* insert nat helper private data (expect) here */
+		} nat;
 #endif
-
-#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
-#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+	} help;
+};
 
 struct ip_conntrack
 {
@@ -101,10 +133,13 @@
 
 	/* If we're expecting another related connection, this will be
            in expected linked list */
-	struct ip_conntrack_expect expected;
+	struct list_head sibling_list;
+	
+	/* Current number of expected connections */
+	unsigned int expecting;
 
-	/* If we were expected by another connection, this will be it */
-	struct nf_ct_info master;
+	/* If we were expected by an expectation, this will be it */
+	struct ip_conntrack_expect *master;
 
 	/* Helper, if any. */
 	struct ip_conntrack_helper *helper;
@@ -121,8 +156,9 @@
 	} proto;
 
 	union {
-		struct ip_ct_ftp ct_ftp_info;
-		struct ip_ct_irc ct_irc_info;
+		/* insert conntrack helper private data (master) here */
+		struct ip_ct_ftp_master ct_ftp_info;
+		struct ip_ct_irc_master ct_irc_info;
 	} help;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
@@ -139,6 +175,9 @@
 #endif /* CONFIG_IP_NF_NAT_NEEDED */
 
 };
+
+/* get master conntrack via master expectation */
+#define master_ct(conntr) (conntr->master ? conntr->master->expectant : NULL)
 
 /* Alter reply tuple (maybe alter helper).  If it's already taken,
    return 0 and don't do alteration. */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h	Sun Apr 14 12:17:00 2002
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h	Sun Apr 14 12:17:00 2002
@@ -15,7 +15,7 @@
 extern void ip_conntrack_cleanup(void);
 
 struct ip_conntrack_protocol;
-extern struct ip_conntrack_protocol *find_proto(u_int8_t protocol);
+extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol);
 /* Like above, but you already have conntrack read lock. */
 extern struct ip_conntrack_protocol *__find_proto(u_int8_t protocol);
 extern struct list_head protocol_list;
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h	Sun Apr 14 12:16:58 2002
+++ b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h	Sun Apr 14 12:16:58 2002
@@ -11,6 +11,8 @@
 /* Protects ftp part of conntracks */
 DECLARE_LOCK_EXTERN(ip_ftp_lock);
 
+#define FTP_PORT	21
+
 enum ip_ct_ftp_type
 {
 	/* PORT command from client */
@@ -23,18 +25,20 @@
 	IP_CT_FTP_EPSV,
 };
 
-/* We record seq number and length of ftp ip/port text here: all in
-   host order. */
-struct ip_ct_ftp
+/* This structure is per expected connection */
+struct ip_ct_ftp_expect
 {
-	/* This tells NAT that this is an ftp connection */
-	int is_ftp;
-	u_int32_t seq;
-	/* 0 means not found yet */
-	u_int32_t len;
-	enum ip_ct_ftp_type ftptype;
-	/* Port that was to be used */
-	u_int16_t port;
+	/* We record seq number and length of ftp ip/port text here: all in
+	 * host order. */
+
+ 	/* sequence number of IP address in packet is in ip_conntrack_expect */
+	u_int32_t len;			/* length of IP address */
+	enum ip_ct_ftp_type ftptype;	/* PORT or PASV ? */
+	u_int16_t port; 		/* TCP port that was to be used */
+};
+
+/* This structure exists only once per master */
+struct ip_ct_ftp_master {
 	/* Next valid seq position for cmd matching after newline */
 	u_int32_t seq_aft_nl[IP_CT_DIR_MAX];
 	/* 0 means seq_match_aft_nl not set */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_helper.h b/include/linux/netfilter_ipv4/ip_conntrack_helper.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper.h	Sun Apr 14 12:16:56 2002
@@ -5,10 +5,19 @@
 
 struct module;
 
+/* Reuse expectation when max_expected reached */
+#define IP_CT_HELPER_F_REUSE_EXPECT	0x01
+
 struct ip_conntrack_helper
 {	
-	/* Internal use. */
-	struct list_head list;
+	struct list_head list; 		/* Internal use. */
+
+	const char *name;		/* name of the module */
+	unsigned char flags;		/* Flags (see above) */
+	struct module *me;		/* pointer to self */
+	unsigned int max_expected;	/* Maximum number of concurrent 
+					 * expected connections */
+	unsigned int timeout;		/* timeout for expecteds */
 
 	/* Mask of things we will help (compared against server response) */
 	struct ip_conntrack_tuple tuple;
@@ -24,11 +33,13 @@
 extern int ip_conntrack_helper_register(struct ip_conntrack_helper *);
 extern void ip_conntrack_helper_unregister(struct ip_conntrack_helper *);
 
-/* Add an expected connection: can only have one per connection */
+extern struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple);
+
+/* Add an expected connection: can have more than one per connection */
 extern int ip_conntrack_expect_related(struct ip_conntrack *related_to,
-				       const struct ip_conntrack_tuple *tuple,
-				       const struct ip_conntrack_tuple *mask,
-				       int (*expectfn)(struct ip_conntrack *));
-extern void ip_conntrack_unexpect_related(struct ip_conntrack *related_to);
+				       struct ip_conntrack_expect *exp);
+extern int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
+				      struct ip_conntrack_tuple *newtuple);
+extern void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp);
 
 #endif /*_IP_CONNTRACK_HELPER_H*/
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_irc.h b/include/linux/netfilter_ipv4/ip_conntrack_irc.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_irc.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/netfilter_ipv4/ip_conntrack_irc.h	Sun Apr 14 12:16:57 2002
@@ -20,7 +20,7 @@
 
 #include <linux/netfilter_ipv4/lockhelp.h>
 
-#define IP_CONNTR_IRC	2
+#define IRC_PORT	6667
 
 struct dccproto {
 	char* match;
@@ -32,16 +32,18 @@
 
 /* We record seq number and length of irc ip/port text here: all in
    host order. */
-struct ip_ct_irc
+
+/* This structure is per expected connection */
+struct ip_ct_irc_expect
 {
-	/* This tells NAT that this is an IRC connection */
-	int is_irc;
-	/* sequence number where address part of DCC command begins */
-	u_int32_t seq;
-	/* 0 means not found yet */
+	/* length of IP address */
 	u_int32_t len;
 	/* Port that was to be used */
 	u_int16_t port;
+};
+
+/* This structure exists only once per master */
+struct ip_ct_irc_master {
 };
 
 #endif /* _IP_CONNTRACK_IRC_H */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h	Sun Apr 14 12:16:59 2002
@@ -42,6 +42,13 @@
 	int (*new)(struct ip_conntrack *conntrack, struct iphdr *iph,
 		   size_t len);
 
+	/* Called when a conntrack entry is destroyed */
+	void (*destroy)(struct ip_conntrack *conntrack);
+
+	/* Has to decide if a expectation matches one packet or not */
+	int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
+			       struct sk_buff **pskb);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h
--- a/include/linux/netfilter_ipv4/ip_nat_helper.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/netfilter_ipv4/ip_nat_helper.h	Sun Apr 14 12:16:56 2002
@@ -6,23 +6,37 @@
 
 struct sk_buff;
 
+/* Flags */
+/* NAT helper must be called on every packet (for TCP) */
+#define IP_NAT_HELPER_F_ALWAYS		0x01
+/* Standalone NAT helper, without a conntrack part */
+#define IP_NAT_HELPER_F_STANDALONE	0x02
+
 struct ip_nat_helper
 {
-	/* Internal use */
-	struct list_head list;
+	struct list_head list;		/* Internal use */
 
+	const char *name;		/* name of the module */
+	unsigned char flags;		/* Flags (see above) */
+	struct module *me;		/* pointer to self */
+	
 	/* Mask of things we will help: vs. tuple from server */
 	struct ip_conntrack_tuple tuple;
 	struct ip_conntrack_tuple mask;
 	
 	/* Helper function: returns verdict */
 	unsigned int (*help)(struct ip_conntrack *ct,
+			     struct ip_conntrack_expect *exp,
 			     struct ip_nat_info *info,
 			     enum ip_conntrack_info ctinfo,
 			     unsigned int hooknum,
 			     struct sk_buff **pskb);
 
-	const char *name;
+	/* Returns verdict and sets up NAT for this connection */
+	unsigned int (*expect)(struct sk_buff **pskb,
+			       unsigned int hooknum,
+			       struct ip_conntrack *ct,
+			       struct ip_nat_info *info);
 };
 
 extern struct list_head helpers;
@@ -39,5 +53,5 @@
 extern int ip_nat_seq_adjust(struct sk_buff *skb,
 				struct ip_conntrack *ct,
 				enum ip_conntrack_info ctinfo);
-extern void ip_nat_delete_sack(struct sk_buff *skb, struct tcphdr *tcph);
+extern void ip_nat_delete_sack(struct sk_buff *skb);
 #endif
diff -Nru a/include/linux/netfilter_ipv4/ip_nat_rule.h b/include/linux/netfilter_ipv4/ip_nat_rule.h
--- a/include/linux/netfilter_ipv4/ip_nat_rule.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/netfilter_ipv4/ip_nat_rule.h	Sun Apr 14 12:16:57 2002
@@ -5,24 +5,7 @@
 #include <linux/netfilter_ipv4/ip_nat.h>
 
 #ifdef __KERNEL__
-/* Want to be told when we first NAT an expected packet for a conntrack? */
-struct ip_nat_expect
-{
-	struct list_head list;
 
-	/* Returns 1 (and sets verdict) if it has setup NAT for this
-           connection */
-	int (*expect)(struct sk_buff **pskb,
-		      unsigned int hooknum,
-		      struct ip_conntrack *ct,
-		      struct ip_nat_info *info,
-		      struct ip_conntrack *master,
-		      struct ip_nat_info *masterinfo,
-		      unsigned int *verdict);
-};
-
-extern int ip_nat_expect_register(struct ip_nat_expect *expect);
-extern void ip_nat_expect_unregister(struct ip_nat_expect *expect);
 extern int ip_nat_rule_init(void) __init;
 extern void ip_nat_rule_cleanup(void);
 extern int ip_nat_rule_find(struct sk_buff **pskb,
diff -Nru a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h
--- a/include/linux/nfsd/const.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/nfsd/const.h	Sun Apr 14 12:16:55 2002
@@ -19,9 +19,9 @@
 #define NFSSVC_MAXVERS		3
 
 /*
- * Maximum blocksize supported by daemon currently at 8K
+ * Maximum blocksize supported by daemon currently at 32K
  */
-#define NFSSVC_MAXBLKSIZE	8192
+#define NFSSVC_MAXBLKSIZE	(32*1024)
 
 #ifdef __KERNEL__
 
diff -Nru a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
--- a/include/linux/nfsd/syscall.h	Sun Apr 14 12:17:00 2002
+++ b/include/linux/nfsd/syscall.h	Sun Apr 14 12:17:00 2002
@@ -132,11 +132,7 @@
 /*
  * Kernel syscall implementation.
  */
-#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
 extern asmlinkage long	sys_nfsservctl(int, struct nfsctl_arg *, void *);
-#else
-#define sys_nfsservctl		sys_ni_syscall
-#endif
 extern int		exp_addclient(struct nfsctl_client *ncp);
 extern int		exp_delclient(struct nfsctl_client *ncp);
 extern int		exp_export(struct nfsctl_export *nxp);
diff -Nru a/include/linux/pagemap.h b/include/linux/pagemap.h
--- a/include/linux/pagemap.h	Sun Apr 14 12:16:54 2002
+++ b/include/linux/pagemap.h	Sun Apr 14 12:16:54 2002
@@ -41,53 +41,39 @@
  */
 #define page_cache_entry(x)	virt_to_page(x)
 
-extern unsigned int page_hash_bits;
-#define PAGE_HASH_BITS (page_hash_bits)
-#define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
-
-extern atomic_t page_cache_size; /* # of pages currently in the hash table */
-extern struct page **page_hash_table;
-
-extern void page_cache_init(unsigned long);
-
-/*
- * We use a power-of-two hash table to avoid a modulus,
- * and get a reasonable hash by knowing roughly how the
- * inode pointer and indexes are distributed (ie, we
- * roughly know which bits are "significant")
- *
- * For the time being it will work for struct address_space too (most of
- * them sitting inside the inodes). We might want to change it later.
- */
-static inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long index)
-{
-#define i (((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
-#define s(x) ((x)+((x)>>PAGE_HASH_BITS))
-	return s(i+index) & (PAGE_HASH_SIZE-1);
-#undef i
-#undef s
-}
+extern atomic_t page_cache_size; /* # of pages currently in the page cache */
 
-#define page_hash(mapping,index) (page_hash_table+_page_hashfn(mapping,index))
-
-extern struct page * __find_get_page(struct address_space *mapping,
-				unsigned long index, struct page **hash);
-#define find_get_page(mapping, index) \
-	__find_get_page(mapping, index, page_hash(mapping, index))
-extern struct page * __find_lock_page (struct address_space * mapping,
-				unsigned long index, struct page **hash);
+extern struct page * find_get_page(struct address_space *mapping,
+				unsigned long index);
+extern struct page * find_lock_page(struct address_space *mapping,
+				unsigned long index);
+extern struct page * find_trylock_page(struct address_space *mapping,
+				unsigned long index);
 extern struct page * find_or_create_page(struct address_space *mapping,
 				unsigned long index, unsigned int gfp_mask);
 
+extern struct page * grab_cache_page(struct address_space *mapping,
+				unsigned long index);
+extern struct page * grab_cache_page_nowait(struct address_space *mapping,
+				unsigned long index);
+
+extern int add_to_page_cache(struct page *page,
+		struct address_space *mapping, unsigned long index);
+extern int add_to_page_cache_unique(struct page *page,
+		struct address_space *mapping, unsigned long index);
+static inline void ___add_to_page_cache(struct page *page,
+		struct address_space *mapping, unsigned long index)
+{
+	list_add(&page->list, &mapping->clean_pages);
+	page->mapping = mapping;
+	page->index = index;
+
+	mapping->nrpages++;
+	atomic_inc(&page_cache_size);
+}
+
 extern void FASTCALL(lock_page(struct page *page));
 extern void FASTCALL(unlock_page(struct page *page));
-#define find_lock_page(mapping, index) \
-	__find_lock_page(mapping, index, page_hash(mapping, index))
-extern struct page *find_trylock_page(struct address_space *, unsigned long);
-
-extern void add_to_page_cache(struct page * page, struct address_space *mapping, unsigned long index);
-extern void add_to_page_cache_locked(struct page * page, struct address_space *mapping, unsigned long index);
-extern int add_to_page_cache_unique(struct page * page, struct address_space *mapping, unsigned long index, struct page **hash);
 
 extern void ___wait_on_page(struct page *);
 
@@ -98,9 +84,6 @@
 }
 
 extern void wake_up_page(struct page *);
-
-extern struct page * grab_cache_page (struct address_space *, unsigned long);
-extern struct page * grab_cache_page_nowait (struct address_space *, unsigned long);
 
 typedef int filler_t(void *, struct page*);
 
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Sun Apr 14 12:16:58 2002
+++ b/include/linux/pci_ids.h	Sun Apr 14 12:16:58 2002
@@ -133,6 +133,7 @@
 #define PCI_DEVICE_ID_COMPAQ_1280	0x3033
 #define PCI_DEVICE_ID_COMPAQ_TRIFLEX	0x4000
 #define PCI_DEVICE_ID_COMPAQ_6010	0x6010
+#define PCI_DEVICE_ID_COMPAQ_TACHYON	0xa0fc
 #define PCI_DEVICE_ID_COMPAQ_SMART2P	0xae10
 #define PCI_DEVICE_ID_COMPAQ_NETEL100	0xae32
 #define PCI_DEVICE_ID_COMPAQ_NETEL10	0xae34
@@ -355,6 +356,7 @@
 
 #define PCI_VENDOR_ID_WD		0x101c
 #define PCI_DEVICE_ID_WD_7197		0x3296
+#define PCI_DEVICE_ID_WD_90C		0xc24a
 
 #define PCI_VENDOR_ID_AMI		0x101e
 #define PCI_DEVICE_ID_AMI_MEGARAID3	0x1960
@@ -445,6 +447,7 @@
 #define PCI_DEVICE_ID_NEC_PCX2		0x0046
 #define PCI_DEVICE_ID_NEC_NILE4		0x005a
 #define PCI_DEVICE_ID_NEC_VRC5476       0x009b
+#define PCI_DEVICE_ID_NEC_VRC5477_AC97  0x00a6
 
 #define PCI_VENDOR_ID_FD		0x1036
 #define PCI_DEVICE_ID_FD_36C70		0x0000
@@ -537,10 +540,6 @@
 #define PCI_DEVICE_ID_ELSA_MICROLINK	0x1000
 #define PCI_DEVICE_ID_ELSA_QS3000	0x3000
 
-#define PCI_VENDOR_ID_ELSA		0x1048
-#define PCI_DEVICE_ID_ELSA_MICROLINK	0x1000
-#define PCI_DEVICE_ID_ELSA_QS3000	0x3000
-
 #define PCI_VENDOR_ID_SGS		0x104a
 #define PCI_DEVICE_ID_SGS_2000		0x0008
 #define PCI_DEVICE_ID_SGS_1764		0x0009
@@ -597,6 +596,7 @@
 #define PCI_DEVICE_ID_MOTOROLA_MPC106	0x0002
 #define PCI_DEVICE_ID_MOTOROLA_RAVEN	0x4801
 #define PCI_DEVICE_ID_MOTOROLA_FALCON	0x4802
+#define PCI_DEVICE_ID_MOTOROLA_HAWK	0x4803
 #define PCI_DEVICE_ID_MOTOROLA_CPX8216	0x4806
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
@@ -608,6 +608,7 @@
 #define PCI_DEVICE_ID_PROMISE_20268R	0x6268
 #define PCI_DEVICE_ID_PROMISE_20269	0x4d69
 #define PCI_DEVICE_ID_PROMISE_20275	0x1275
+#define PCI_DEVICE_ID_PROMISE_20276	0x5275
 #define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
 #define PCI_VENDOR_ID_N9		0x105d
@@ -649,6 +650,12 @@
 #define PCI_DEVICE_ID_APPLE_KL_USB	0x0019
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP	0x0020
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC	0x0021
+#define PCI_DEVICE_ID_APPLE_KEYLARGO	0x0022
+#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP	0x0024
+#define PCI_DEVICE_ID_APPLE_KEYLARGO_P	0x0025
+#define PCI_DEVICE_ID_APPLE_KL_USB_P	0x0026
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P	0x0027
+#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15	0x002d
 #define PCI_DEVICE_ID_APPLE_UNI_N_FW2	0x0030
 
 #define PCI_VENDOR_ID_YAMAHA		0x1073
@@ -860,12 +867,18 @@
 #define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX	0x0110
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO	0x0112
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
+#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE		0x01bc
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC		0x0203
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
@@ -1106,6 +1119,11 @@
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC95	0x060a
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC97	0x060f
 
+#define PCI_VENDOR_ID_TOSHIBA_2		0x102f
+#define PCI_DEVICE_ID_TOSHIBA_TX3927	0x000a
+#define PCI_DEVICE_ID_TOSHIBA_TC35815CF	0x0030
+#define PCI_DEVICE_ID_TOSHIBA_TX4927	0x0180
+
 #define PCI_VENDOR_ID_RICOH		0x1180
 #define PCI_DEVICE_ID_RICOH_RL5C465	0x0465
 #define PCI_DEVICE_ID_RICOH_RL5C466	0x0466
@@ -1118,6 +1136,8 @@
 #define PCI_DEVICE_ID_ARTOP_ATP850UF	0x0005
 #define PCI_DEVICE_ID_ARTOP_ATP860	0x0006
 #define PCI_DEVICE_ID_ARTOP_ATP860R	0x0007
+#define PCI_DEVICE_ID_ARTOP_ATP865	0x0008
+#define PCI_DEVICE_ID_ARTOP_ATP865R	0x0009
 #define PCI_DEVICE_ID_ARTOP_AEC7610	0x8002
 #define PCI_DEVICE_ID_ARTOP_AEC7612UW	0x8010
 #define PCI_DEVICE_ID_ARTOP_AEC7612U	0x8020
@@ -1279,13 +1299,8 @@
 #define PCI_VENDOR_ID_ITE		0x1283
 #define PCI_DEVICE_ID_ITE_IT8172G	0x8172
 #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801
-
-#define PCI_VENDOR_ID_ITE		0x1283
-#define PCI_DEVICE_ID_ITE_IT8172G	0x8172
-
-#define PCI_VENDOR_ID_ITE			0x1283
 #define PCI_DEVICE_ID_ITE_8872		0x8872
-
+#define PCI_DEVICE_ID_ITE_IT8330G_0	0xe886
 
 /* formerly Platform Tech */
 #define PCI_VENDOR_ID_ESS_OLD		0x1285
@@ -1450,6 +1465,8 @@
 #define PCI_DEVICE_ID_LAVA_DSERIAL	0x0100 /* 2x 16550 */
 #define PCI_DEVICE_ID_LAVA_QUATRO_A	0x0101 /* 2x 16550, half of 4 port */
 #define PCI_DEVICE_ID_LAVA_QUATRO_B	0x0102 /* 2x 16550, half of 4 port */
+#define PCI_DEVICE_ID_LAVA_OCTO_A	0x0180 /* 4x 16550A, half of 8 port */
+#define PCI_DEVICE_ID_LAVA_OCTO_B	0x0181 /* 4x 16550A, half of 8 port */
 #define PCI_DEVICE_ID_LAVA_PORT_PLUS	0x0200 /* 2x 16650 */
 #define PCI_DEVICE_ID_LAVA_QUAD_A	0x0201 /* 2x 16650, half of 4 port */
 #define PCI_DEVICE_ID_LAVA_QUAD_B	0x0202 /* 2x 16650, half of 4 port */
@@ -1639,16 +1656,6 @@
 #define PCI_DEVICE_ID_INTEL_82801BA_2	0x2443
 #define PCI_DEVICE_ID_INTEL_82801BA_3	0x2444
 #define PCI_DEVICE_ID_INTEL_82801BA_4	0x2445
-#define PCI_DEVICE_ID_INTEL_82801CA_0	0x2480
-#define PCI_DEVICE_ID_INTEL_82801CA_2	0x2482
-#define PCI_DEVICE_ID_INTEL_82801CA_3	0x2483
-#define PCI_DEVICE_ID_INTEL_82801CA_4	0x2484
-#define PCI_DEVICE_ID_INTEL_82801CA_5	0x2485
-#define PCI_DEVICE_ID_INTEL_82801CA_6	0x2486
-#define PCI_DEVICE_ID_INTEL_82801CA_7	0x2487
-#define PCI_DEVICE_ID_INTEL_82801CA_10	0x248a
-#define PCI_DEVICE_ID_INTEL_82801CA_11	0x248b
-#define PCI_DEVICE_ID_INTEL_82801CA_12	0x248c
 #define PCI_DEVICE_ID_INTEL_82801BA_5	0x2446
 #define PCI_DEVICE_ID_INTEL_82801BA_6	0x2448
 #define PCI_DEVICE_ID_INTEL_82801BA_7	0x2449
diff -Nru a/include/linux/percpu.h b/include/linux/percpu.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/percpu.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,14 @@
+#ifndef __LINUX_PERCPU_H
+#define __LINUX_PERCPU_H
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+#define __per_cpu_data	__attribute__((section(".data.percpu")))
+#include <asm/percpu.h>
+#else
+#define __per_cpu_data
+#define per_cpu(var, cpu)			var
+#define this_cpu(var)				var
+#endif
+
+#endif /* __LINUX_PERCPU_H */
diff -Nru a/include/linux/platform.h b/include/linux/platform.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/platform.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,43 @@
+/*
+ * include/linux/platform.h - platform driver definitions
+ *
+ * Because of the prolific consumerism of the average American,
+ * and the dominant marketing budgets of PC OEMs, we have been
+ * blessed with frequent updates of the PC architecture. 
+ *
+ * While most of these calls are singular per architecture, they 
+ * require an extra layer of abstraction on the x86 so the right
+ * subsystem gets the right call. 
+ *
+ * Basically, this consolidates the power off and reboot callbacks 
+ * into one structure, as well as adding power management hooks.
+ *
+ * When adding a platform driver, please make sure all callbacks are 
+ * filled. There are defaults defined below that do nothing; use those
+ * if you do not support that callback.
+ */ 
+
+#ifndef _PLATFORM_H_
+#define _PLATFORM_H_
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+struct platform_t {
+	char	* name;
+	u32	suspend_states;
+	void	(*reboot)(char * cmd);
+	void	(*halt)(void);
+	void	(*power_off)(void);
+	int	(*suspend)(int state, int flags);
+	void	(*idle)(void);
+};
+
+extern struct platform_t * platform;
+extern void default_reboot(char * cmd);
+extern void default_halt(void);
+extern int default_suspend(int state, int flags);
+extern void default_idle(void);
+
+#endif /* __KERNEL__ */
+#endif /* _PLATFORM_H */
diff -Nru a/include/linux/pnpbios.h b/include/linux/pnpbios.h
--- a/include/linux/pnpbios.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/pnpbios.h	Sun Apr 14 12:16:57 2002
@@ -143,20 +143,21 @@
 extern int  pnpbios_dont_use_current_config;
 extern void *pnpbios_kmalloc(size_t size, int f);
 extern int pnpbios_init (void);
-extern void pnpbios_proc_init (void);
+extern int pnpbios_proc_init (void);
+extern void pnpbios_proc_exit (void);
 
 extern int pnp_bios_dev_node_info (struct pnp_dev_node_info *data);
 extern int pnp_bios_get_dev_node (u8 *nodenum, char config, struct pnp_bios_node *data);
 extern int pnp_bios_set_dev_node (u8 nodenum, char config, struct pnp_bios_node *data);
+extern int pnp_bios_get_stat_res (char *info);
+extern int pnp_bios_isapnp_config (struct pnp_isa_config_struc *data);
+extern int pnp_bios_escd_info (struct escd_info_struc *data);
+extern int pnp_bios_read_escd (char *data, u32 nvram_base);
 #if needed
 extern int pnp_bios_get_event (u16 *message);
 extern int pnp_bios_send_message (u16 message);
 extern int pnp_bios_set_stat_res (char *info);
-extern int pnp_bios_get_stat_res (char *info);
 extern int pnp_bios_apm_id_table (char *table, u16 *size);
-extern int pnp_bios_isapnp_config (struct pnp_isa_config_struc *data);
-extern int pnp_bios_escd_info (struct escd_info_struc *data);
-extern int pnp_bios_read_escd (char *data, u32 nvram_base);
 extern int pnp_bios_write_escd (char *data, u32 nvram_base);
 #endif
 
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	Sun Apr 14 12:16:54 2002
+++ b/include/linux/proc_fs.h	Sun Apr 14 12:16:54 2002
@@ -27,7 +27,7 @@
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
-#define PROC_NDYNAMIC      4096
+#define PROC_NDYNAMIC      16384
 
 #define PROC_SUPER_MAGIC 0x9fa0
 
diff -Nru a/include/linux/quota.h b/include/linux/quota.h
--- a/include/linux/quota.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/quota.h	Sun Apr 14 12:16:56 2002
@@ -144,7 +144,6 @@
 
 #ifdef __KERNEL__
 
-extern int nr_dquots, nr_free_dquots;
 extern int dquot_root_squash;
 
 #define NR_DQHASH 43            /* Just an arbitrary number */
diff -Nru a/include/linux/radix-tree.h b/include/linux/radix-tree.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/radix-tree.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2001 Momchil Velikov
+ * Portions Copyright (C) 2001 Christoph Hellwig
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _LINUX_RADIX_TREE_H
+#define _LINUX_RADIX_TREE_H
+
+struct radix_tree_node;
+
+#define RADIX_TREE_SLOT_RESERVED ((void *)~0UL)
+
+struct radix_tree_root {
+	unsigned int		height;
+	int			gfp_mask;
+	struct radix_tree_node	*rnode;
+};
+
+#define RADIX_TREE_INIT(mask)	{0, (mask), NULL}
+
+#define RADIX_TREE(name, mask) \
+	struct radix_tree_root name = RADIX_TREE_INIT(mask)
+
+#define INIT_RADIX_TREE(root, mask)	\
+do {					\
+	(root)->height = 0;		\
+	(root)->gfp_mask = (mask);	\
+	(root)->rnode = NULL;		\
+} while (0)
+
+extern int radix_tree_reserve(struct radix_tree_root *, unsigned long, void ***);
+extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
+extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
+extern int radix_tree_delete(struct radix_tree_root *, unsigned long);
+
+#endif /* _LINUX_RADIX_TREE_H */
diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h
--- a/include/linux/raid/md.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/raid/md.h	Sun Apr 14 12:16:55 2002
@@ -18,8 +18,6 @@
 #ifndef _MD_H
 #define _MD_H
 
-#include <linux/mm.h>
-#include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <asm/semaphore.h>
 #include <linux/major.h>
diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
--- a/include/linux/raid/md_k.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/raid/md_k.h	Sun Apr 14 12:16:55 2002
@@ -91,7 +91,6 @@
 /*
  * default readahead
  */
-#define MD_READAHEAD	MAX_READAHEAD
 
 static inline int disk_faulty(mdp_disk_t * d)
 {
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/reiserfs_fs.h	Sun Apr 14 12:16:57 2002
@@ -21,6 +21,7 @@
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
 #include <linux/reiserfs_fs_i.h>
+#include <linux/reiserfs_fs_sb.h>
 #endif
 
 /*
@@ -96,7 +97,7 @@
 /***************************************************************************/
 
 /*
- * Structure of super block on disk, a version of which in RAM is often accessed as s->u.reiserfs_sb.s_rs
+ * Structure of super block on disk, a version of which in RAM is often accessed as REISERFS_SB(s)->s_rs
  * the version in RAM is part of a larger structure containing fields never written to disk.
  */
 #define UNSET_HASH 0 // read_super will guess about, what hash names
@@ -176,7 +177,7 @@
 
 
 // on-disk super block fields converted to cpu form
-#define SB_DISK_SUPER_BLOCK(s) ((s)->u.reiserfs_sb.s_rs)
+#define SB_DISK_SUPER_BLOCK(s) (REISERFS_SB(s)->s_rs)
 #define SB_V1_DISK_SUPER_BLOCK(s) (&(SB_DISK_SUPER_BLOCK(s)->s_v1))
 #define SB_BLOCKSIZE(s) \
         le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_blocksize))
@@ -287,6 +288,12 @@
 {
 	return list_entry(inode, struct reiserfs_inode_info, vfs_inode);
 }
+
+static inline struct reiserfs_sb_info *REISERFS_SB(const struct super_block *sb)
+{
+	return sb->u.generic_sbp;
+}
+
 /** this says about version of key of all items (but stat data) the
     object consists of */
 #define get_inode_item_key_version( inode )                                    \
@@ -1284,7 +1291,7 @@
 #define REISERFS_KERNEL_MEM		0	/* reiserfs kernel memory mode	*/
 #define REISERFS_USER_MEM		1	/* reiserfs user memory mode		*/
 
-#define fs_generation(s) ((s)->u.reiserfs_sb.s_generation_counter)
+#define fs_generation(s) (REISERFS_SB(s)->s_generation_counter)
 #define get_generation(s) atomic_read (&fs_generation(s))
 #define FILESYSTEM_CHANGED_TB(tb)  (get_generation((tb)->tb_sb) != (tb)->fs_gen)
 #define fs_changed(gen,s) (gen != get_generation (s))
@@ -1884,10 +1891,10 @@
 #define PROC_EXP( e )   e
 
 #define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
-#define __PINFO( sb ) ( sb ) -> u.reiserfs_sb.s_proc_info_data
+#define __PINFO( sb ) REISERFS_SB(sb) -> s_proc_info_data
 #define PROC_INFO_MAX( sb, field, value )								\
     __PINFO( sb ).field =												\
-        MAX( ( sb ) -> u.reiserfs_sb.s_proc_info_data.field, value )
+        MAX( REISERFS_SB( sb ) -> s_proc_info_data.field, value )
 #define PROC_INFO_INC( sb, field ) ( ++ ( __PINFO( sb ).field ) )
 #define PROC_INFO_ADD( sb, field, val ) ( __PINFO( sb ).field += ( val ) )
 #define PROC_INFO_BH_STAT( sb, bh, level )							\
diff -Nru a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
--- a/include/linux/reiserfs_fs_sb.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/reiserfs_fs_sb.h	Sun Apr 14 12:16:59 2002
@@ -412,20 +412,20 @@
 #define REISERFS_TEST3 13
 #define REISERFS_TEST4 14 
 
-#define reiserfs_r5_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_R5_HASH))
-#define reiserfs_rupasov_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_RUPASOV_HASH))
-#define reiserfs_tea_hash(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_TEA_HASH))
-#define reiserfs_hash_detect(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << FORCE_HASH_DETECT))
-#define reiserfs_no_border(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NO_BORDER))
-#define reiserfs_no_unhashed_relocation(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NO_UNHASHED_RELOCATION))
-#define reiserfs_hashed_relocation(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_HASHED_RELOCATION))
-#define reiserfs_test4(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_TEST4))
-
-#define dont_have_tails(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << NOTAIL))
-#define replay_only(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REPLAYONLY))
-#define reiserfs_dont_log(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_NOLOG))
-#define old_format_only(s) ((s)->u.reiserfs_sb.s_properties & (1 << REISERFS_3_5))
-#define convert_reiserfs(s) ((s)->u.reiserfs_sb.s_mount_opt & (1 << REISERFS_CONVERT))
+#define reiserfs_r5_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_R5_HASH))
+#define reiserfs_rupasov_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_RUPASOV_HASH))
+#define reiserfs_tea_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_TEA_HASH))
+#define reiserfs_hash_detect(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_HASH_DETECT))
+#define reiserfs_no_border(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NO_BORDER))
+#define reiserfs_no_unhashed_relocation(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NO_UNHASHED_RELOCATION))
+#define reiserfs_hashed_relocation(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_HASHED_RELOCATION))
+#define reiserfs_test4(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_TEST4))
+
+#define dont_have_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << NOTAIL))
+#define replay_only(s) (REISERFS_SB(s)->s_mount_opt & (1 << REPLAYONLY))
+#define reiserfs_dont_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NOLOG))
+#define old_format_only(s) (REISERFS_SB(s)->s_properties & (1 << REISERFS_3_5))
+#define convert_reiserfs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_CONVERT))
 
 
 void reiserfs_file_buffer (struct buffer_head * bh, int list);
@@ -439,13 +439,13 @@
 #define SCHEDULE_OCCURRED       1
 
 
-#define SB_BUFFER_WITH_SB(s) ((s)->u.reiserfs_sb.s_sbh)
-#define SB_JOURNAL(s) ((s)->u.reiserfs_sb.s_journal)
+#define SB_BUFFER_WITH_SB(s) (REISERFS_SB(s)->s_sbh)
+#define SB_JOURNAL(s) (REISERFS_SB(s)->s_journal)
 #define SB_JOURNAL_1st_RESERVED_BLOCK(s) (SB_JOURNAL(s)->j_1st_reserved_block)
 #define SB_JOURNAL_LIST(s) (SB_JOURNAL(s)->j_journal_list)
 #define SB_JOURNAL_LIST_INDEX(s) (SB_JOURNAL(s)->j_journal_list_index) 
 #define SB_JOURNAL_LEN_FREE(s) (SB_JOURNAL(s)->j_journal_len_free) 
-#define SB_AP_BITMAP(s) ((s)->u.reiserfs_sb.s_ap_bitmap)
+#define SB_AP_BITMAP(s) (REISERFS_SB(s)->s_ap_bitmap)
 
 #define SB_DISK_JOURNAL_HEAD(s) (SB_JOURNAL(s)->j_header_bh->)
 
diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
--- a/include/linux/rtnetlink.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/rtnetlink.h	Sun Apr 14 12:16:59 2002
@@ -589,7 +589,7 @@
 
 #define ASSERT_RTNL() do { if (down_trylock(&rtnl_sem) == 0)  { up(&rtnl_sem); \
 printk("RTNL: assertion failed at " __FILE__ "(%d)\n", __LINE__); } \
-		   } while(0);
+		   } while(0)
 #define BUG_TRAP(x) if (!(x)) { printk("KERNEL: assertion (" #x ") failed at " __FILE__ "(%d)\n", __LINE__); }
 
 
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/sched.h	Sun Apr 14 12:16:55 2002
@@ -79,7 +79,6 @@
 extern int last_pid;
 extern unsigned long nr_running(void);
 
-#include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/param.h>
 #include <linux/resource.h>
@@ -369,6 +368,7 @@
 #define PF_MEMDIE	0x00001000	/* Killed for out-of-memory */
 #define PF_FREE_PAGES	0x00002000	/* per process page freeing */
 #define PF_NOIO		0x00004000	/* avoid generating further I/O */
+#define PF_FLUSHER	0x00008000	/* responsible for disk writeback */
 
 /*
  * Ptrace flags
diff -Nru a/include/linux/securebits.h b/include/linux/securebits.h
--- a/include/linux/securebits.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/securebits.h	Sun Apr 14 12:16:56 2002
@@ -6,7 +6,7 @@
 extern unsigned securebits;
 
 /* When set UID 0 has no special privileges. When unset, we support
-   inheritance of root-permissions and suid-root executablew under
+   inheritance of root-permissions and suid-root executable under
    compatibility mode. We raise the effective and inheritable bitmasks
    *of the executable file* if the effective uid of the new process is
    0. If the real uid is 0, we raise the inheritable bitmask of the
diff -Nru a/include/linux/seq_file.h b/include/linux/seq_file.h
--- a/include/linux/seq_file.h	Sun Apr 14 12:16:58 2002
+++ b/include/linux/seq_file.h	Sun Apr 14 12:16:58 2002
@@ -3,6 +3,8 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <linux/string.h>
+#include <asm/semaphore.h>
 
 struct seq_operations;
 struct file;
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/skbuff.h	Sun Apr 14 12:16:55 2002
@@ -16,7 +16,6 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/cache.h>
 
@@ -590,7 +589,7 @@
 
 static inline struct sk_buff *skb_dequeue(struct sk_buff_head *list)
 {
-	long flags;
+	unsigned long flags;
 	struct sk_buff *result;
 
 	spin_lock_irqsave(&list->lock, flags);
@@ -739,7 +738,7 @@
 
 static inline struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
 {
-	long flags;
+	unsigned long flags;
 	struct sk_buff *result;
 
 	spin_lock_irqsave(&list->lock, flags);
diff -Nru a/include/linux/smb_fs.h b/include/linux/smb_fs.h
--- a/include/linux/smb_fs.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/smb_fs.h	Sun Apr 14 12:16:59 2002
@@ -12,6 +12,7 @@
 #include <linux/smb.h>
 #include <linux/smb_fs_i.h>
 #include <linux/smb_fs_sb.h>
+#include <linux/fs.h>
 
 /*
  * ioctl commands
diff -Nru a/include/linux/smp.h b/include/linux/smp.h
--- a/include/linux/smp.h	Sun Apr 14 12:16:54 2002
+++ b/include/linux/smp.h	Sun Apr 14 12:16:54 2002
@@ -72,16 +72,6 @@
 #define MSG_RESCHEDULE		0x0003	/* Reschedule request from master CPU*/
 #define MSG_CALL_FUNCTION       0x0004  /* Call function on all other CPUs */
 
-#define __per_cpu_data	__attribute__((section(".data.percpu")))
-
-#ifndef __HAVE_ARCH_PER_CPU
-extern unsigned long __per_cpu_offset[NR_CPUS];
-
-/* var is in discarded region: offset to particular copy we want */
-#define per_cpu(var, cpu) RELOC_HIDE(var, per_cpu_offset(cpu))
-
-#define this_cpu(var) per_cpu(var, smp_processor_id())
-#endif /* !__HAVE_ARCH_PER_CPU */
 #else /* !SMP */
 
 /*
diff -Nru a/include/linux/sonypi.h b/include/linux/sonypi.h
--- a/include/linux/sonypi.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/sonypi.h	Sun Apr 14 12:16:57 2002
@@ -73,11 +73,28 @@
 #define SONYPI_EVENT_BACK_PRESSED		35
 #define SONYPI_EVENT_LID_CLOSED			36
 #define SONYPI_EVENT_LID_OPENED			37
+#define SONYPI_EVENT_BLUETOOTH_ON		38
+#define SONYPI_EVENT_BLUETOOTH_OFF		39
 
+/* get/set brightness */
+#define SONYPI_IOCGBRT		_IOR('v', 0, __u8)
+#define SONYPI_IOCSBRT		_IOW('v', 0, __u8)
 
-/* brightness etc. ioctls */
-#define SONYPI_IOCGBRT	_IOR('v', 0, __u8)
-#define SONYPI_IOCSBRT	_IOW('v', 0, __u8)
+/* get battery full capacity/remaining capacity */
+#define SONYPI_IOCGBAT1CAP	_IOR('v', 2, __u16)
+#define SONYPI_IOCGBAT1REM	_IOR('v', 3, __u16)
+#define SONYPI_IOCGBAT2CAP	_IOR('v', 4, __u16)
+#define SONYPI_IOCGBAT2REM	_IOR('v', 5, __u16)
+
+/* get battery flags: battery1/battery2/ac adapter present */
+#define SONYPI_BFLAGS_B1	0x01
+#define SONYPI_BFLAGS_B2	0x02
+#define SONYPI_BFLAGS_AC	0x04
+#define SONYPI_IOCGBATFLAGS	_IOR('v', 7, __u8)
+
+/* get/set bluetooth subsystem state on/off */
+#define SONYPI_IOCGBLUE		_IOR('v', 8, __u8)
+#define SONYPI_IOCSBLUE		_IOW('v', 9, __u8)
 
 #ifdef __KERNEL__
 
diff -Nru a/include/linux/spinlock.h b/include/linux/spinlock.h
--- a/include/linux/spinlock.h	Sun Apr 14 12:16:58 2002
+++ b/include/linux/spinlock.h	Sun Apr 14 12:16:58 2002
@@ -204,7 +204,7 @@
 
 #else
 
-#define preempt_get_count()	do { } while (0)
+#define preempt_get_count()	(0)
 #define preempt_disable()	do { } while (0)
 #define preempt_enable_no_resched()	do {} while(0)
 #define preempt_enable()	do { } while (0)
diff -Nru a/include/linux/string.h b/include/linux/string.h
--- a/include/linux/string.h	Sun Apr 14 12:16:57 2002
+++ b/include/linux/string.h	Sun Apr 14 12:16:57 2002
@@ -12,9 +12,7 @@
 extern "C" {
 #endif
 
-extern char * ___strtok;
 extern char * strpbrk(const char *,const char *);
-extern char * strtok(char *,const char *);
 extern char * strsep(char **,const char *);
 extern __kernel_size_t strspn(const char *,const char *);
 
diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
--- a/include/linux/sunrpc/svc.h	Sun Apr 14 12:16:54 2002
+++ b/include/linux/sunrpc/svc.h	Sun Apr 14 12:16:54 2002
@@ -123,6 +123,10 @@
 	/* Catering to nfsd */
 	struct svc_client *	rq_client;	/* RPC peer info */
 	struct svc_cacherep *	rq_cacherep;	/* cache info */
+	struct knfsd_fh *	rq_reffh;	/* Referrence filehandle, used to
+						 * determine what device number
+						 * to report (real or virtual)
+						 */
 
 	wait_queue_head_t	rq_wait;	/* synchronozation */
 };
diff -Nru a/include/linux/swap.h b/include/linux/swap.h
--- a/include/linux/swap.h	Sun Apr 14 12:16:55 2002
+++ b/include/linux/swap.h	Sun Apr 14 12:16:55 2002
@@ -109,7 +109,7 @@
 struct task_struct;
 struct vm_area_struct;
 struct sysinfo;
-
+struct address_space;
 struct zone_t;
 
 /* linux/mm/swap.c */
@@ -139,6 +139,9 @@
 extern int add_to_swap_cache(struct page *, swp_entry_t);
 extern void __delete_from_swap_cache(struct page *page);
 extern void delete_from_swap_cache(struct page *page);
+extern int move_to_swap_cache(struct page *page, swp_entry_t entry);
+extern int move_from_swap_cache(struct page *page, unsigned long index,
+		struct address_space *mapping);
 extern void free_page_and_swap_cache(struct page *page);
 extern struct page * lookup_swap_cache(swp_entry_t);
 extern struct page * read_swap_cache_async(swp_entry_t);
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	Sun Apr 14 12:16:54 2002
+++ b/include/linux/sysctl.h	Sun Apr 14 12:16:54 2002
@@ -288,7 +288,8 @@
 	NET_TCP_ADV_WIN_SCALE=87,
 	NET_IPV4_NONLOCAL_BIND=88,
 	NET_IPV4_ICMP_RATELIMIT=89,
-	NET_IPV4_ICMP_RATEMASK=90
+	NET_IPV4_ICMP_RATEMASK=90,
+	NET_TCP_TW_REUSE=91
 };
 
 enum {
@@ -333,7 +334,8 @@
 	NET_IPV4_CONF_BOOTP_RELAY=10,
 	NET_IPV4_CONF_LOG_MARTIANS=11,
 	NET_IPV4_CONF_TAG=12,
-	NET_IPV4_CONF_ARPFILTER=13
+	NET_IPV4_CONF_ARPFILTER=13,
+	NET_IPV4_CONF_MEDIUM_ID=14,
 };
 
 /* /proc/sys/net/ipv6 */
diff -Nru a/include/linux/ticable.h b/include/linux/ticable.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/ticable.h	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,42 @@
+/* Hey EMACS -*- linux-c -*-
+ *
+ * tipar/tiser/tiusb - low level driver for handling link cables
+ * designed for Texas Instruments graphing calculators.
+ *
+ * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
+ *
+ * Redistribution of this file is permitted under the terms of the GNU
+ * Public License (GPL)
+ */
+
+#ifndef _TICABLE_H 
+#define _TICABLE_H 1
+
+/* Internal default constants for the kernel module */
+#define TIMAXTIME 15      /* 1.5 seconds       */
+#define IO_DELAY  10      /* 10 micro-seconds  */
+
+/* Major & minor number for character devices */
+#define TIPAR_MAJOR  115 /* 0 to 7 */
+#define TIPAR_MINOR    0
+
+#define TISER_MAJOR  115 /* 8 to 15 */
+#define TISER_MINOR    8
+
+#define TIUSB_MAJOR  115  /* 16 to 31 */
+#define TIUSB_MINOR   16
+
+/*
+ * Request values for the 'ioctl' function.
+ */
+#define IOCTL_TIPAR_DELAY     _IOW('p', 0xa8, int) /* set delay   */
+#define IOCTL_TIPAR_TIMEOUT   _IOW('p', 0xa9, int) /* set timeout */
+
+#define IOCTL_TISER_DELAY     _IOW('p', 0xa0, int) /* set delay   */
+#define IOCTL_TISER_TIMEOUT   _IOW('p', 0xa1, int) /* set timeout */
+
+#define IOCTL_TIUSB_TIMEOUT        _IOW('N', 0x20, int) /* set timeout */
+#define IOCTL_TIUSB_RESET_DEVICE   _IOW('N', 0x21, int) /* reset device */
+#define IOCTL_TIUSB_RESET_PIPES    _IOW('N', 0x22, int) /* reset both pipes*/
+
+#endif /* TICABLE_H */
diff -Nru a/include/linux/udf_fs.h b/include/linux/udf_fs.h
--- a/include/linux/udf_fs.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/udf_fs.h	Sun Apr 14 12:16:56 2002
@@ -34,6 +34,10 @@
 #ifndef _UDF_FS_H
 #define _UDF_FS_H 1
 
+#include <linux/config.h>
+
+#include <linux/config.h>
+
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS	8
 
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Sun Apr 14 12:16:58 2002
+++ b/include/linux/usb.h	Sun Apr 14 12:16:58 2002
@@ -305,6 +305,7 @@
 } __attribute__ ((packed));
 
 /* helpers for driver access to descriptors */
+extern int usb_ifnum_to_ifpos(struct usb_device *dev, unsigned ifnum);
 extern struct usb_interface *
 	usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
 extern struct usb_endpoint_descriptor *
@@ -470,8 +471,10 @@
 
 /**
  * struct usb_driver - identifies USB driver to usbcore
- * @owner: pointer to the module owner of this driver
- * @name: The driver name should be unique among USB drivers
+ * @owner: Pointer to the module owner of this driver; initialize
+ *	it using THIS_MODULE.
+ * @name: The driver name should be unique among USB drivers,
+ *	and should normally be the same as the module name.
  * @probe: Called to see if the driver is willing to manage a particular
  *	interface on a device.  The probe routine returns a handle that 
  *	will later be provided to disconnect(), or a null pointer to
@@ -506,7 +509,7 @@
  * is used by both user and kernel mode hotplugging support.
  *
  * The probe() and disconnect() methods are called in a context where
- * they can sleep, but they should avoid abusing the privilage.  Most
+ * they can sleep, but they should avoid abusing the privilege.  Most
  * work to connect to a device should be done when the device is opened,
  * and undone at the last close.  The disconnect code needs to address
  * concurrency issues with respect to open() and close() methods, as
@@ -588,7 +591,7 @@
 /**
  * struct urb - USB Request Block
  * @urb_list: For use by current owner of the URB.
- * @next: Used primarily to link ISO requests into rings.
+ * @next: Used to link ISO requests into rings.
  * @pipe: Holds endpoint number, direction, type, and max packet size.
  *	Create these values with the eight macros available;
  *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl"
@@ -627,8 +630,9 @@
  * @start_frame: Returns the initial frame for interrupt or isochronous
  *	transfers.
  * @number_of_packets: Lists the number of ISO transfer buffers.
- * @interval: Specifies the polling interval for interrupt transfers, in
- *	milliseconds.
+ * @interval: Specifies the polling interval for interrupt or isochronous
+ *	transfers.  The units are frames (milliseconds) for for full and low
+ *	speed devices, and microframes (1/8 millisecond) for highspeed ones.
  * @error_count: Returns the number of ISO transfers that reported errors.
  * @context: For use in completion functions.  This normally points to
  *	request-specific driver context.
@@ -668,12 +672,16 @@
  *
  * Control URBs must provide a setup_packet.
  *
- * Interupt UBS must provide an interval, saying how often (in milliseconds)
+ * Interrupt UBS must provide an interval, saying how often (in milliseconds
+ * or, for highspeed devices, 125 microsecond units)
  * to poll for transfers.  After the URB has been submitted, the interval
  * and start_frame fields reflect how the transfer was actually scheduled.
  * The polling interval may be more frequent than requested.
  * For example, some controllers have a maximum interval of 32 microseconds,
  * while others support intervals of up to 1024 microseconds.
+ * Isochronous URBs also have transfer intervals.  (Note that for isochronous
+ * endpoints, as well as high speed interrupt endpoints, the encoding of
+ * the transfer interval in the endpoint descriptor is logarithmic.)
  *
  * Isochronous URBs normally use the USB_ISO_ASAP transfer flag, telling
  * the host controller to schedule the transfer as soon as bandwidth
@@ -682,8 +690,8 @@
  * and handle the case where the transfer can't begin then.  However, drivers
  * won't know how bandwidth is currently allocated, and while they can
  * find the current frame using usb_get_current_frame_number () they can't
- * know the range for that frame number.  (Common ranges for the frame
- * counter include 256, 512, and 1024 frames.)
+ * know the range for that frame number.  (Ranges for frame counter values
+ * are HC-specific, and can go from 256 to 65536 frames from "now".)
  *
  * Isochronous URBs have a different data transfer model, in part because
  * the quality of service is only "best effort".  Callers provide specially
@@ -734,7 +742,7 @@
 	unsigned char *setup_packet;	/* (in) setup packet (control only) */
 	int start_frame;		/* (modify) start frame (INT/ISO) */
 	int number_of_packets;		/* (in) number of ISO packets */
-	int interval;                   /* (in) polling interval (INT only) */
+	int interval;                   /* (in) transfer interval (INT/ISO) */
 	int error_count;		/* (return) number of ISO errors */
 	int timeout;			/* (in) timeout, in jiffies */
 	void *context;			/* (in) context for completion */
@@ -956,24 +964,6 @@
 
 /* -------------------------------------------------------------------------- */
 
-/* Enumeration is only for the hub driver, or HCD virtual root hubs */
-extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
-	struct usb_bus *);
-extern void usb_free_dev(struct usb_device *);
-extern int usb_new_device(struct usb_device *dev);
-extern void usb_connect(struct usb_device *dev);
-extern void usb_disconnect(struct usb_device **);
-
-#ifndef _LINUX_HUB_H
-/* exported to hub driver ONLY to support usb_reset_device () */
-extern int usb_get_configuration(struct usb_device *dev);
-extern void usb_set_maxpacket(struct usb_device *dev);
-extern void usb_destroy_configuration(struct usb_device *dev);
-extern int usb_set_address(struct usb_device *dev);
-#endif /* _LINUX_HUB_H */
-
-/* -------------------------------------------------------------------------- */
-
 /* This is arbitrary.
  * From USB 2.0 spec Table 11-13, offset 7, a hub can
  * have up to 255 ports. The most yet reported is 10.
@@ -1042,11 +1032,52 @@
 /* for drivers using iso endpoints */
 extern int usb_get_current_frame_number (struct usb_device *usb_dev);
 
-/* drivers must track when they bind to a device's interfaces */
-extern void usb_inc_dev_use(struct usb_device *);
-#define usb_dec_dev_use usb_free_dev
+/**
+ * usb_inc_dev_use - record another reference to a device
+ * @dev: the device being referenced
+ *
+ * Each live reference to a device should be refcounted.
+ *
+ * Drivers for USB interfaces should normally record such references in
+ * their probe() methods, when they bind to an interface, and release
+ * them usb_dec_dev_use(), in their disconnect() methods.
+ */
+static inline void usb_inc_dev_use (struct usb_device *dev)
+{
+	atomic_inc (&dev->refcnt);
+}
+
+/**
+ * usb_dec_dev_use - drop a reference to a device
+ * @dev: the device no longer being referenced
+ *
+ * Each live reference to a device should be refcounted.
+ *
+ * Drivers for USB interfaces should normally release such references in
+ * their disconnect() methods, and record them in probe().
+ *
+ * Note that driver disconnect() methods must guarantee that when they
+ * return, all of their outstanding references to the device (and its
+ * interfaces) are cleaned up.  That means that all pending URBs from
+ * this driver must have completed, and that no more copies of the device
+ * handle are saved in driver records (including other kernel threads).
+ */
+static inline void usb_dec_dev_use (struct usb_device *dev)
+{
+	if (atomic_dec_and_test (&dev->refcnt)) {
+		/* May only go to zero when usbcore finishes
+		 * usb_disconnect() processing:  khubd or HCDs.
+		 *
+		 * If you hit this BUG() it's likely a problem
+		 * with some driver's disconnect() routine.
+		 */
+		BUG ();
+	}
+}
+
 
 /* used these for multi-interface device registration */
+extern int usb_find_interface_driver_for_ifnum(struct usb_device *dev, unsigned int ifnum);
 extern void usb_driver_claim_interface(struct usb_driver *driver,
 			struct usb_interface *iface, void* priv);
 extern int usb_interface_claimed(struct usb_interface *iface);
diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
--- a/include/linux/usbdevice_fs.h	Sun Apr 14 12:16:56 2002
+++ b/include/linux/usbdevice_fs.h	Sun Apr 14 12:16:56 2002
@@ -142,6 +142,8 @@
 #define USBDEVFS_HUB_PORTINFO      _IOR('U', 19, struct usbdevfs_hub_portinfo)
 #define USBDEVFS_RESET             _IO('U', 20)
 #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
+#define USBDEVFS_DISCONNECT        _IO('U', 22)
+#define USBDEVFS_CONNECT           _IO('U', 23)
 
 /* --------------------------------------------------------------------- */
 
diff -Nru a/include/linux/videodev.h b/include/linux/videodev.h
--- a/include/linux/videodev.h	Sun Apr 14 12:16:59 2002
+++ b/include/linux/videodev.h	Sun Apr 14 12:16:59 2002
@@ -37,8 +37,6 @@
  	 * video_generic_ioctl() does the userspace copying of the
  	 * ioctl arguments */
  	struct file_operations *fops;
- 	int (*kernel_ioctl)(struct inode *inode, struct file *file,
- 			    unsigned int cmd, void *arg);
 	void *priv;		/* Used to be 'private' but that upsets C++ */
 
 	/* for videodev.c intenal usage -- don't touch */
@@ -60,8 +58,10 @@
 
 extern int video_exclusive_open(struct inode *inode, struct file *file);
 extern int video_exclusive_release(struct inode *inode, struct file *file);
-extern int video_generic_ioctl(struct inode *inode, struct file *file,
-			       unsigned int cmd, unsigned long arg);
+extern int video_usercopy(struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg,
+			  int (*func)(struct inode *inode, struct file *file,
+				      unsigned int cmd, void *arg));
 #endif /* __KERNEL__ */
 
 #define VID_TYPE_CAPTURE	1	/* Can capture */
diff -Nru a/include/net/irda/discovery.h b/include/net/irda/discovery.h
--- a/include/net/irda/discovery.h	Sun Apr 14 12:16:59 2002
+++ b/include/net/irda/discovery.h	Sun Apr 14 12:16:59 2002
@@ -39,6 +39,14 @@
 #define DISCOVERY_EXPIRE_TIMEOUT 6*HZ
 #define DISCOVERY_DEFAULT_SLOTS  0
 
+/* Types of discovery */
+typedef enum {
+	DISCOVERY_LOG,		/* What's in our discovery log */
+	DISCOVERY_ACTIVE,	/* Doing our own discovery on the medium */
+	DISCOVERY_PASSIVE,	/* Peer doing discovery on the medium */
+	EXPIRY_TIMEOUT,		/* Entry expired due to timeout */
+} DISCOVERY_MODE;
+
 #define NICKNAME_MAX_LEN 21
 
 /*
diff -Nru a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
--- a/include/net/irda/ircomm_tty.h	Sun Apr 14 12:16:58 2002
+++ b/include/net/irda/ircomm_tty.h	Sun Apr 14 12:16:58 2002
@@ -44,6 +44,11 @@
 #define IRCOMM_TTY_MAJOR 161
 #define IRCOMM_TTY_MINOR 0
 
+/* This is used as an initial value to max_header_size before the proper
+ * value is filled in (5 for ttp, 4 for lmp). This allow us to detect
+ * the state of the underlying connection. - Jean II */
+#define IRCOMM_TTY_HDR_UNITIALISED	32
+
 /*
  * IrCOMM TTY driver state
  */
diff -Nru a/include/net/irda/irlan_client.h b/include/net/irda/irlan_client.h
--- a/include/net/irda/irlan_client.h	Sun Apr 14 12:16:59 2002
+++ b/include/net/irda/irlan_client.h	Sun Apr 14 12:16:59 2002
@@ -34,7 +34,7 @@
 #include <net/irda/irlan_event.h>
 
 void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout);
-void irlan_client_discovery_indication(discovery_t *, void *);
+void irlan_client_discovery_indication(discovery_t *, DISCOVERY_MODE, void *);
 void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr);
 
 void irlan_client_open_ctrl_tsap( struct irlan_cb *self);
diff -Nru a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
--- a/include/net/irda/irlmp.h	Sun Apr 14 12:16:54 2002
+++ b/include/net/irda/irlmp.h	Sun Apr 14 12:16:54 2002
@@ -72,7 +72,7 @@
 	S_END,
 } SERVICE;
 
-typedef void (*DISCOVERY_CALLBACK1) (discovery_t *, void *);
+typedef void (*DISCOVERY_CALLBACK1) (discovery_t *, DISCOVERY_MODE, void *);
 typedef void (*DISCOVERY_CALLBACK2) (hashbin_t *, void *);
 
 typedef struct {
@@ -214,7 +214,7 @@
 				 struct sk_buff *userdata);
 int  irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
 
-void irlmp_discovery_confirm(hashbin_t *discovery_log);
+void irlmp_discovery_confirm(hashbin_t *discovery_log, DISCOVERY_MODE);
 void irlmp_discovery_request(int nslots);
 struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask, int nslots);
 void irlmp_do_expiry(void);
diff -Nru a/include/net/ndisc.h b/include/net/ndisc.h
--- a/include/net/ndisc.h	Sun Apr 14 12:16:59 2002
+++ b/include/net/ndisc.h	Sun Apr 14 12:16:59 2002
@@ -42,11 +42,7 @@
 struct nd_msg {
         struct icmp6hdr	icmph;
         struct in6_addr	target;
-        struct {
-                __u8	opt_type;
-                __u8	opt_len;
-                __u8	link_addr[MAX_ADDR_LEN];
-        } opt;
+	__u8		opt[0];
 };
 
 struct ra_msg {
diff -Nru a/include/net/pkt_sched.h b/include/net/pkt_sched.h
--- a/include/net/pkt_sched.h	Sun Apr 14 12:16:56 2002
+++ b/include/net/pkt_sched.h	Sun Apr 14 12:16:56 2002
@@ -358,8 +358,8 @@
 #define PSCHED_TDIFF(tv1, tv2) (long)((tv1) - (tv2))
 #define PSCHED_TDIFF_SAFE(tv1, tv2, bound, guard) \
 ({ \
-	   long __delta = (tv1) - (tv2); \
-	   if ( __delta > (bound)) {  __delta = (bound); guard; } \
+	   long long __delta = (tv1) - (tv2); \
+	   if ( __delta > (long long)(bound)) {  __delta = (bound); guard; } \
 	   __delta; \
 })
 
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	Sun Apr 14 12:16:56 2002
+++ b/include/net/sock.h	Sun Apr 14 12:16:56 2002
@@ -80,7 +80,7 @@
 do {	spin_lock_init(&((__sk)->lock.slock)); \
 	(__sk)->lock.users = 0; \
 	init_waitqueue_head(&((__sk)->lock.wq)); \
-} while(0);
+} while(0)
 
 struct sock {
 	/* Begin of struct sock/struct tcp_tw_bucket shared layout */
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	Sun Apr 14 12:16:55 2002
+++ b/include/net/tcp.h	Sun Apr 14 12:16:55 2002
@@ -78,7 +78,7 @@
  */
 struct tcp_bind_bucket {
 	unsigned short		port;
-	unsigned short		fastreuse;
+	signed short		fastreuse;
 	struct tcp_bind_bucket	*next;
 	struct sock		*owners;
 	struct tcp_bind_bucket	**pprev;
@@ -469,6 +469,7 @@
 extern int sysctl_tcp_rmem[3];
 extern int sysctl_tcp_app_win;
 extern int sysctl_tcp_adv_win_scale;
+extern int sysctl_tcp_tw_reuse;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -507,7 +508,7 @@
 	__u16			rmt_port;
 	__u16			mss;
 	__u8			retrans;
-	__u8			index;
+	__u8			__pad;
 	__u16	snd_wscale : 4, 
 		rcv_wscale : 4, 
 		tstamp_ok : 1,
@@ -577,9 +578,7 @@
 							 struct sk_buff *skb,
 							 struct open_request *req,
 							 struct dst_entry *dst);
-	
-	int			(*hash_connecting)	(struct sock *sk);
-
+    
 	int			(*remember_stamp)	(struct sock *sk);
 
 	__u16			net_header_len;
@@ -781,8 +780,7 @@
 					       struct sockaddr *uaddr,
 					       int addr_len);
 
-extern int			tcp_connect(struct sock *sk,
-					    struct sk_buff *skb);
+extern int			tcp_connect(struct sock *sk);
 
 extern struct sk_buff *		tcp_make_synack(struct sock *sk,
 						struct dst_entry *dst,
@@ -1834,6 +1832,6 @@
 	return 1;
 }
 
-#define TCP_CHECK_TIMER(sk) do { } while (0);
+#define TCP_CHECK_TIMER(sk) do { } while (0)
 
 #endif	/* _TCP_H */
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Sun Apr 14 12:16:57 2002
+++ b/init/do_mounts.c	Sun Apr 14 12:16:57 2002
@@ -826,7 +826,7 @@
 
 	create_dev("/dev/root", ROOT_DEV, NULL);
 	if (mount_initrd) {
-		if (initrd_load() && kdev_same(ROOT_DEV, mk_kdev(RAMDISK_MAJOR, 0))) {
+		if (initrd_load() && !kdev_same(ROOT_DEV, mk_kdev(RAMDISK_MAJOR, 0))) {
 			handle_initrd();
 			goto out;
 		}
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Sun Apr 14 12:16:56 2002
+++ b/init/main.c	Sun Apr 14 12:16:56 2002
@@ -27,6 +27,7 @@
 #include <linux/iobuf.h>
 #include <linux/bootmem.h>
 #include <linux/tty.h>
+#include <linux/percpu.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -68,6 +69,7 @@
 extern void sysctl_init(void);
 extern void signals_init(void);
 
+extern void radix_tree_init(void);
 extern void free_initmem(void);
 
 #ifdef CONFIG_TC
@@ -270,12 +272,9 @@
 #define smp_init()	do { } while (0)
 #endif
 
-static inline void setup_per_cpu_areas(void)
-{
-}
 #else
 
-#ifndef __HAVE_ARCH_PER_CPU
+#ifdef __GENERIC_PER_CPU
 unsigned long __per_cpu_offset[NR_CPUS];
 
 static void __init setup_per_cpu_areas(void)
@@ -297,7 +296,11 @@
 		memcpy(ptr, __per_cpu_start, size);
 	}
 }
-#endif /* !__HAVE_ARCH_PER_CPU */
+#else
+static inline void setup_per_cpu_areas(void)
+{
+}
+#endif /* !__GENERIC_PER_CPU */
 
 /* Called by boot processor to activate the rest. */
 static void __init smp_init(void)
@@ -390,7 +393,7 @@
 	proc_caches_init();
 	vfs_caches_init(mempages);
 	buffer_init(mempages);
-	page_cache_init(mempages);
+	radix_tree_init();
 #if defined(CONFIG_ARCH_S390)
 	ccwcache_init();
 #endif
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	Sun Apr 14 12:16:57 2002
+++ b/ipc/sem.c	Sun Apr 14 12:16:57 2002
@@ -62,6 +62,7 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include "util.h"
 
@@ -995,6 +996,8 @@
 	struct sem_array *sma;
 	int nsems, i;
 
+	lock_kernel();
+
 	/* If the current process was sleeping for a semaphore,
 	 * remove it from the queue.
 	 */
@@ -1051,6 +1054,8 @@
 		sem_unlock(semid);
 	}
 	current->semundo = NULL;
+
+	unlock_kernel();
 }
 
 #ifdef CONFIG_PROC_FS
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Sun Apr 14 12:16:59 2002
+++ b/ipc/shm.c	Sun Apr 14 12:16:59 2002
@@ -674,16 +674,19 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *shmd, *shmdnext;
+	int retval = -EINVAL;
 
 	down_write(&mm->mmap_sem);
 	for (shmd = mm->mmap; shmd; shmd = shmdnext) {
 		shmdnext = shmd->vm_next;
 		if (shmd->vm_ops == &shm_vm_ops
-		    && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr)
+		    && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr) {
 			do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start);
+			retval = 0;
+		}
 	}
 	up_write(&mm->mmap_sem);
-	return 0;
+	return retval;
 }
 
 #ifdef CONFIG_PROC_FS
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	Sun Apr 14 12:16:56 2002
+++ b/kernel/Makefile	Sun Apr 14 12:16:56 2002
@@ -10,16 +10,17 @@
 O_TARGET := kernel.o
 
 export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
-		printk.o 
+		printk.o platform.o 
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
-	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o context.o futex.o
+	    sysctl.o capability.o ptrace.o timer.o user.o \
+	    signal.o sys.o kmod.o context.o futex.o platform.o
 
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	Sun Apr 14 12:16:59 2002
+++ b/kernel/acct.c	Sun Apr 14 12:16:59 2002
@@ -44,17 +44,11 @@
  */
 
 #include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/acct.h>
-#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/tty.h>
-
 #include <asm/uaccess.h>
 
 /*
@@ -397,15 +391,3 @@
 		spin_unlock(&acct_globals.lock);
 	return 0;
 }
-
-#else
-/*
- * Dummy system call when BSD process accounting is not configured
- * into the kernel.
- */
-
-asmlinkage long sys_acct(const char * filename)
-{
-	return -ENOSYS;
-}
-#endif
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Sun Apr 14 12:16:57 2002
+++ b/kernel/exit.c	Sun Apr 14 12:16:57 2002
@@ -14,9 +14,7 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/namespace.h>
-#ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
-#endif
 #include <linux/file.h>
 #include <linux/binfmts.h>
 
@@ -471,12 +469,15 @@
 			write_lock_irq(&tasklist_lock);
 		}
 	}
+
 	/*
 	 * No need to unlock IRQs, we'll schedule() immediately
 	 * anyway. In the preemption case this also makes it
-	 * impossible for the task to get runnable again.
+	 * impossible for the task to get runnable again (thus
+	 * the "_raw_" unlock - to make sure we don't try to
+	 * preempt here).
 	 */
-	write_unlock(&tasklist_lock);
+	_raw_write_unlock(&tasklist_lock);
 }
 
 NORET_TYPE void do_exit(long code)
@@ -492,13 +493,15 @@
 	tsk->flags |= PF_EXITING;
 	del_timer_sync(&tsk->real_timer);
 
+	if (unlikely(preempt_get_count()))
+		printk(KERN_ERR "error: %s[%d] exited with preempt_count %d\n",
+				current->comm, current->pid,
+				preempt_get_count());
+
 fake_volatile:
-#ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
-#endif
 	__exit_mm(tsk);
 
-	lock_kernel();
 	sem_exit();
 	__exit_files(tsk);
 	__exit_fs(tsk);
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Sun Apr 14 12:16:55 2002
+++ b/kernel/fork.c	Sun Apr 14 12:16:55 2002
@@ -29,6 +29,8 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 
 static kmem_cache_t *task_struct_cachep;
 
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sun Apr 14 12:16:54 2002
+++ b/kernel/ksyms.c	Sun Apr 14 12:16:54 2002
@@ -107,7 +107,7 @@
 EXPORT_SYMBOL(kfree);
 EXPORT_SYMBOL(vfree);
 EXPORT_SYMBOL(__vmalloc);
-EXPORT_SYMBOL_GPL(vmalloc_to_page);
+EXPORT_SYMBOL(vmalloc_to_page);
 EXPORT_SYMBOL(mem_map);
 EXPORT_SYMBOL(remap_page_range);
 EXPORT_SYMBOL(max_mapnr);
@@ -224,8 +224,6 @@
 EXPORT_SYMBOL(generic_file_mmap);
 EXPORT_SYMBOL(generic_ro_fops);
 EXPORT_SYMBOL(generic_buffer_fdatasync);
-EXPORT_SYMBOL(page_hash_bits);
-EXPORT_SYMBOL(page_hash_table);
 EXPORT_SYMBOL(file_lock_list);
 EXPORT_SYMBOL(locks_init_lock);
 EXPORT_SYMBOL(locks_copy_lock);
@@ -266,8 +264,8 @@
 EXPORT_SYMBOL(__pollwait);
 EXPORT_SYMBOL(poll_freewait);
 EXPORT_SYMBOL(ROOT_DEV);
-EXPORT_SYMBOL(__find_get_page);
-EXPORT_SYMBOL(__find_lock_page);
+EXPORT_SYMBOL(find_get_page);
+EXPORT_SYMBOL(find_lock_page);
 EXPORT_SYMBOL(grab_cache_page);
 EXPORT_SYMBOL(grab_cache_page_nowait);
 EXPORT_SYMBOL(read_cache_page);
@@ -295,6 +293,7 @@
 EXPORT_SYMBOL(get_sb_single);
 EXPORT_SYMBOL(kill_anon_super);
 EXPORT_SYMBOL(kill_litter_super);
+EXPORT_SYMBOL(generic_shutdown_super);
 EXPORT_SYMBOL(deactivate_super);
 EXPORT_SYMBOL(sget);
 EXPORT_SYMBOL(set_anon_super);
@@ -537,7 +536,6 @@
 EXPORT_SYMBOL(file_fsync);
 EXPORT_SYMBOL(fsync_buffers_list);
 EXPORT_SYMBOL(clear_inode);
-EXPORT_SYMBOL(___strtok);
 EXPORT_SYMBOL(init_special_inode);
 EXPORT_SYMBOL(__get_hash_table);
 EXPORT_SYMBOL(new_inode);
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Sun Apr 14 12:16:56 2002
+++ b/kernel/module.c	Sun Apr 14 12:16:56 2002
@@ -11,6 +11,7 @@
 #include <linux/kmod.h>
 #include <linux/seq_file.h>
 #include <linux/fs.h>
+#include <asm/cacheflush.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
diff -Nru a/kernel/platform.c b/kernel/platform.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/kernel/platform.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,73 @@
+/*
+ * platform driver support 
+ */
+
+#include <linux/platform.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+static struct platform_t default_platform;
+
+struct platform_t * platform = &default_platform;
+static spinlock_t platform_lock = SPIN_LOCK_UNLOCKED;
+
+void default_reboot(char * cmd)
+{
+	/* nothing */
+}
+
+void default_halt(void)
+{
+	/* nothing */
+}
+
+int default_suspend(int state, int flags)
+{
+	return -ENOSYS;
+}
+
+static struct platform_t default_platform = {
+	name:		"Default Platform",
+	suspend_states:	0,
+	reboot:		default_reboot,
+	halt:		default_halt,
+	power_off:	default_halt,
+	suspend:	default_suspend,
+	idle:		default_idle,
+};
+
+/**
+ * set_platform_driver - set the platform driver.
+ * @pf:	driver to set it to
+ *
+ * Return -EEXIST if someone else already owns it.
+ */
+int set_platform_driver(struct platform_t * pf)
+{
+	if (!pf)
+		return -EINVAL;
+	spin_lock(&platform_lock);
+	if (platform != &default_platform) {
+		spin_unlock(&platform_lock);
+		return -EEXIST;
+	}
+	platform = pf;
+	spin_unlock(&platform_lock);
+	return 0;
+}
+
+void remove_platform_driver(struct platform_t * pf)
+{
+	spin_lock(&platform_lock);
+	if (platform == pf)
+		platform = &default_platform;
+	spin_unlock(&platform_lock);
+}
+
+EXPORT_SYMBOL(default_reboot);
+EXPORT_SYMBOL(default_halt);
+EXPORT_SYMBOL(default_suspend);
+
+EXPORT_SYMBOL(platform);
+EXPORT_SYMBOL(set_platform_driver);
+EXPORT_SYMBOL(remove_platform_driver);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Sun Apr 14 12:16:56 2002
+++ b/kernel/sched.c	Sun Apr 14 12:16:56 2002
@@ -764,6 +764,13 @@
 	prev->sleep_timestamp = jiffies;
 	spin_lock_irq(&rq->lock);
 
+	/*
+	 * if entering from preempt_schedule, off a kernel preemption,
+	 * go straight to picking the next task.
+	 */
+	if (unlikely(preempt_get_count() & PREEMPT_ACTIVE))
+		goto pick_next_task;
+	
 	switch (prev->state) {
 	case TASK_INTERRUPTIBLE:
 		if (unlikely(signal_pending(prev))) {
@@ -775,9 +782,7 @@
 	case TASK_RUNNING:
 		;
 	}
-#if CONFIG_SMP
 pick_next_task:
-#endif
 	if (unlikely(!rq->nr_running)) {
 #if CONFIG_SMP
 		load_balance(rq, 1);
@@ -841,10 +846,15 @@
  */
 asmlinkage void preempt_schedule(void)
 {
-	if (unlikely(preempt_get_count()))
+	struct thread_info *ti = current_thread_info();
+
+	if (unlikely(ti->preempt_count))
 		return;
-	current->state = TASK_RUNNING;
+
+	ti->preempt_count = PREEMPT_ACTIVE;
 	schedule();
+	ti->preempt_count = 0;
+	barrier();
 }
 #endif /* CONFIG_PREEMPT */
 
@@ -1224,6 +1234,96 @@
 	return retval;
 }
 
+/**
+ * sys_sched_setaffinity - set the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length of new_mask
+ * @new_mask: user-space pointer to the new cpu mask
+ */
+asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
+				      unsigned long *new_mask_ptr)
+{
+	unsigned long new_mask;
+	task_t *p;
+	int retval;
+
+	if (len < sizeof(new_mask))
+		return -EINVAL;
+
+	if (copy_from_user(&new_mask, new_mask_ptr, sizeof(new_mask)))
+		return -EFAULT;
+
+	new_mask &= cpu_online_map;
+	if (!new_mask)
+		return -EINVAL;
+
+	read_lock(&tasklist_lock);
+
+	p = find_process_by_pid(pid);
+	if (!p) {
+		read_unlock(&tasklist_lock);
+		return -ESRCH;
+	}
+
+	/*
+	 * It is not safe to call set_cpus_allowed with the
+	 * tasklist_lock held.  We will bump the task_struct's
+	 * usage count and then drop tasklist_lock.
+	 */
+	get_task_struct(p);
+	read_unlock(&tasklist_lock);
+
+	retval = -EPERM;
+	if ((current->euid != p->euid) && (current->euid != p->uid) &&
+			!capable(CAP_SYS_NICE))
+		goto out_unlock;
+
+	retval = 0;
+	set_cpus_allowed(p, new_mask);
+
+out_unlock:
+	put_task_struct(p);
+	return retval;
+}
+
+/**
+ * sys_sched_getaffinity - get the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length of the new mask
+ * @user_mask_ptr: userspace pointer to the mask
+ */
+asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len,
+				      unsigned long *user_mask_ptr)
+{
+	unsigned long mask;
+	unsigned int real_len;
+	task_t *p;
+	int retval;
+
+	real_len = sizeof(mask);
+
+	if (len < real_len)
+		return -EINVAL;
+
+	read_lock(&tasklist_lock);
+
+	retval = -ESRCH;
+	p = find_process_by_pid(pid);
+	if (!p)
+		goto out_unlock;
+
+	retval = 0;
+	mask = p->cpus_allowed & cpu_online_map;
+
+out_unlock:
+	read_unlock(&tasklist_lock);
+	if (retval)
+		return retval;
+	if (copy_to_user(user_mask_ptr, &mask, real_len))
+		return -EFAULT;
+	return real_len;
+}
+
 asmlinkage long sys_sched_yield(void)
 {
 	runqueue_t *rq;
@@ -1679,8 +1779,10 @@
 	for (cpu = 0; cpu < smp_num_cpus; cpu++) {
 		int logical = cpu_logical_map(cpu);
 
-		while (!cpu_rq(logical)->migration_thread)
+		while (!cpu_rq(logical)->migration_thread) {
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(2);
+		}
 	}
 	if (migration_mask)
 		BUG();
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Sun Apr 14 12:16:55 2002
+++ b/kernel/sys.c	Sun Apr 14 12:16:55 2002
@@ -15,9 +15,11 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/unistd.h>
 
 /*
  * this is where the system-wide overflow UID and GID are defined, for
@@ -173,6 +175,10 @@
 	return -ENOSYS;
 }
 
+cond_syscall(sys_nfsservctl)
+cond_syscall(sys_quotactl)
+cond_syscall(sys_acct)
+
 static int proc_sel(struct task_struct *p, int which, int who)
 {
 	if(p->pid)
@@ -286,6 +292,7 @@
 	switch (cmd) {
 	case LINUX_REBOOT_CMD_RESTART:
 		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+		device_shutdown();
 		printk(KERN_EMERG "Restarting system.\n");
 		machine_restart(NULL);
 		break;
@@ -300,6 +307,7 @@
 
 	case LINUX_REBOOT_CMD_HALT:
 		notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
+		device_shutdown();
 		printk(KERN_EMERG "System halted.\n");
 		machine_halt();
 		do_exit(0);
@@ -307,6 +315,7 @@
 
 	case LINUX_REBOOT_CMD_POWER_OFF:
 		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
+		device_shutdown();
 		printk(KERN_EMERG "Power down.\n");
 		machine_power_off();
 		do_exit(0);
@@ -320,6 +329,7 @@
 		buffer[sizeof(buffer) - 1] = '\0';
 
 		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
+		device_shutdown();
 		printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
 		machine_restart(buffer);
 		break;
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Sun Apr 14 12:16:55 2002
+++ b/kernel/sysctl.c	Sun Apr 14 12:16:55 2002
@@ -284,8 +284,6 @@
 	 0444, NULL, &proc_dointvec},
 	{FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int),
 	 0644, NULL, &proc_dointvec},
-	{FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
-	 0444, NULL, &proc_dointvec},
 	{FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
 	 0444, NULL, &proc_dointvec},
 	{FS_OVERFLOWUID, "overflowuid", &fs_overflowuid, sizeof(int), 0644, NULL,
@@ -476,11 +474,11 @@
 }
 
 /**
- * register_sysctl_table - register a sysctl heirarchy
+ * register_sysctl_table - register a sysctl hierarchy
  * @table: the top-level table structure
  * @insert_at_head: whether the entry should be inserted in front or at the end
  *
- * Register a sysctl table heirarchy. @table should be a filled in ctl_table
+ * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. An entry with a ctl_name of 0 terminates the table. 
  *
  * The members of the &ctl_table structure are used as follows:
@@ -564,7 +562,7 @@
 }
 
 /**
- * unregister_sysctl_table - unregister a sysctl table heirarchy
+ * unregister_sysctl_table - unregister a sysctl table hierarchy
  * @header: the header returned from register_sysctl_table
  *
  * Unregisters the sysctl table and all children. proc entries may not
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c	Sun Apr 14 12:16:56 2002
+++ b/kernel/time.c	Sun Apr 14 12:16:56 2002
@@ -25,6 +25,7 @@
  */
 
 #include <linux/timex.h>
+#include <linux/errno.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
diff -Nru a/lib/Makefile b/lib/Makefile
--- a/lib/Makefile	Sun Apr 14 12:16:55 2002
+++ b/lib/Makefile	Sun Apr 14 12:16:55 2002
@@ -8,9 +8,11 @@
 
 L_TARGET := lib.a
 
-export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o crc32.o
+export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
+	       crc32.o rbtree.o radix-tree.o
 
-obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o bust_spinlocks.o rbtree.o
+obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
+	 bust_spinlocks.o rbtree.o radix-tree.o
 
 obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
@@ -28,7 +30,7 @@
 obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
 
 include $(TOPDIR)/drivers/net/Makefile.lib
-include $(TOPDIR)/drivers/usb/Makefile.lib
+include $(TOPDIR)/drivers/usb/class/Makefile.lib
 include $(TOPDIR)/fs/Makefile.lib
 
 include $(TOPDIR)/Rules.make
diff -Nru a/lib/radix-tree.c b/lib/radix-tree.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/lib/radix-tree.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2001 Momchil Velikov
+ * Portions Copyright (C) 2001 Christoph Hellwig
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/radix-tree.h>
+#include <linux/slab.h>
+
+/*
+ * Radix tree node definition.
+ */
+#define RADIX_TREE_MAP_SHIFT  7
+#define RADIX_TREE_MAP_SIZE  (1UL << RADIX_TREE_MAP_SHIFT)
+#define RADIX_TREE_MAP_MASK  (RADIX_TREE_MAP_SIZE-1)
+
+struct radix_tree_node {
+	unsigned int	count;
+	void		*slots[RADIX_TREE_MAP_SIZE];
+};
+
+struct radix_tree_path {
+	struct radix_tree_node *node, **slot;
+};
+
+#define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
+
+/*
+ * Radix tree node cache.
+ */
+static kmem_cache_t *radix_tree_node_cachep;
+static mempool_t *radix_tree_node_pool;
+
+#define radix_tree_node_alloc(root) \
+	mempool_alloc(radix_tree_node_pool, (root)->gfp_mask)
+#define radix_tree_node_free(node) \
+	mempool_free((node), radix_tree_node_pool);
+
+
+/*
+ *	Return the maximum key which can be store into a
+ *	radix tree with height HEIGHT.
+ */
+static inline unsigned long radix_tree_maxindex(unsigned int height)
+{
+	unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
+	unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;
+
+	if (tmp >= RADIX_TREE_INDEX_BITS)
+		index = ~0UL;
+	return index;
+}
+
+
+/*
+ *	Extend a radix tree so it can store key @index.
+ */
+static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
+{
+	struct radix_tree_node *node;
+	unsigned int height;
+
+	/* Figure out what the height should be.  */
+	height = root->height + 1;
+	while (index > radix_tree_maxindex(height))
+		height++;
+
+	if (root->rnode) {
+		do {
+			if (!(node = radix_tree_node_alloc(root)))
+				return -ENOMEM;
+
+			/* Increase the height.  */
+			node->slots[0] = root->rnode;
+			if (root->rnode)
+				node->count = 1;
+			root->rnode = node;
+			root->height++;
+		} while (height > root->height);
+	} else 
+		root->height = height;
+
+	return 0;
+}
+
+
+/**
+ *	radix_tree_reserve    -    reserve space in a radix tree
+ *	@root:		radix tree root
+ *	@index:		index key
+ *	@pslot:		pointer to reserved slot
+ *
+ *	Reserve a slot in a radix tree for the key @index.
+ */
+int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void ***pslot)
+{
+	struct radix_tree_node *node = NULL, *tmp, **slot;
+	unsigned int height, shift;
+	int error;
+
+	/* Make sure the tree is high enough.  */
+	if (index > radix_tree_maxindex(root->height)) {
+		error = radix_tree_extend(root, index);
+		if (error)
+			return error;
+	}
+    
+	slot = &root->rnode;
+	height = root->height;
+	shift = (height-1) * RADIX_TREE_MAP_SHIFT;
+
+	while (height > 0) {
+		if (*slot == NULL) {
+			/* Have to add a child node.  */
+			if (!(tmp = radix_tree_node_alloc(root)))
+				return -ENOMEM;
+			*slot = tmp;
+			if (node)
+				node->count++;
+		}
+
+		/* Go a level down.  */
+		node = *slot;
+		slot = (struct radix_tree_node **)
+			(node->slots + ((index >> shift) & RADIX_TREE_MAP_MASK));
+		shift -= RADIX_TREE_MAP_SHIFT;
+		height--;
+	}
+
+	if (*slot != NULL)
+		return -EEXIST;
+	if (node)
+		node->count++;
+
+	*pslot = (void **)slot;
+	**pslot = RADIX_TREE_SLOT_RESERVED;
+	return 0;
+}
+
+EXPORT_SYMBOL(radix_tree_reserve);
+
+
+/**
+ *	radix_tree_insert    -    insert into a radix tree
+ *	@root:		radix tree root
+ *	@index:		index key
+ *	@item:		item to insert
+ *
+ *	Insert an item into the radix tree at position @index.
+ */
+int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
+{
+	void **slot;
+	int error;
+
+	error = radix_tree_reserve(root, index, &slot);
+	if (!error)
+		*slot = item;
+	return error;
+}
+
+EXPORT_SYMBOL(radix_tree_insert);
+
+
+/**
+ *	radix_tree_lookup    -    perform lookup operation on a radix tree
+ *	@root:		radix tree root
+ *	@index:		index key
+ *
+ *	Lookup them item at the position @index in the radix tree @root.
+ */
+void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
+{
+	unsigned int height, shift;
+	struct radix_tree_node **slot;
+
+	height = root->height;
+	if (index > radix_tree_maxindex(height))
+		return NULL;
+
+	shift = (height-1) * RADIX_TREE_MAP_SHIFT;
+	slot = &root->rnode;
+
+	while (height > 0) {
+		if (*slot == NULL)
+			return NULL;
+
+		slot = (struct radix_tree_node **)
+			((*slot)->slots + ((index >> shift) & RADIX_TREE_MAP_MASK));
+		shift -= RADIX_TREE_MAP_SHIFT;
+		height--;
+	}
+
+	return (void *) *slot;
+}
+
+EXPORT_SYMBOL(radix_tree_lookup);
+
+
+/**
+ *	radix_tree_delete    -    delete an item from a radix tree
+ *	@root:		radix tree root
+ *	@index:		index key
+ *
+ *	Remove the item at @index from the radix tree rooted at @root.
+ */
+int radix_tree_delete(struct radix_tree_root *root, unsigned long index)
+{
+	struct radix_tree_path path[RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2], *pathp = path;
+	unsigned int height, shift;
+
+	height = root->height;
+	if (index > radix_tree_maxindex(height))
+		return -ENOENT;
+
+	shift = (height-1) * RADIX_TREE_MAP_SHIFT;
+	pathp->node = NULL;
+	pathp->slot = &root->rnode;
+
+	while (height > 0) {
+		if (*pathp->slot == NULL)
+			return -ENOENT;
+
+		pathp[1].node = *pathp[0].slot;
+		pathp[1].slot = (struct radix_tree_node **)
+		    (pathp[1].node->slots + ((index >> shift) & RADIX_TREE_MAP_MASK));
+		pathp++;
+		shift -= RADIX_TREE_MAP_SHIFT;
+		height--;
+	}
+
+	if (*pathp[0].slot == NULL)
+		return -ENOENT;
+
+	*pathp[0].slot = NULL;
+	while (pathp[0].node && --pathp[0].node->count == 0) {
+		pathp--;
+		*pathp[0].slot = NULL;
+		radix_tree_node_free(pathp[1].node);
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL(radix_tree_delete);
+
+static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
+{
+	memset(node, 0, sizeof(struct radix_tree_node));
+}
+
+static void *radix_tree_node_pool_alloc(int gfp_mask, void *data)
+{
+	return kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+}
+
+static void radix_tree_node_pool_free(void *node, void *data)
+{
+	kmem_cache_free(radix_tree_node_cachep, node);
+}
+
+/*
+ * FIXME!  512 nodes is 200-300k of memory.  This needs to be
+ * scaled by the amount of available memory, and hopefully
+ * reduced also.
+ */
+void __init radix_tree_init(void)
+{
+	radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
+			sizeof(struct radix_tree_node), 0,
+			SLAB_HWCACHE_ALIGN, radix_tree_node_ctor, NULL);
+	if (!radix_tree_node_cachep)
+		panic ("Failed to create radix_tree_node cache\n");
+	radix_tree_node_pool = mempool_create(512, radix_tree_node_pool_alloc,
+			radix_tree_node_pool_free, NULL);
+	if (!radix_tree_node_pool)
+		panic ("Failed to create radix_tree_node pool\n");
+}
diff -Nru a/lib/rbtree.c b/lib/rbtree.c
--- a/lib/rbtree.c	Sun Apr 14 12:16:55 2002
+++ b/lib/rbtree.c	Sun Apr 14 12:16:55 2002
@@ -20,6 +20,7 @@
 */
 
 #include <linux/rbtree.h>
+#include <linux/module.h>
 
 static void __rb_rotate_left(rb_node_t * node, rb_root_t * root)
 {
@@ -125,6 +126,7 @@
 
 	root->rb_node->rb_color = RB_BLACK;
 }
+EXPORT_SYMBOL(rb_insert_color);
 
 static void __rb_erase_color(rb_node_t * node, rb_node_t * parent,
 			     rb_root_t * root)
@@ -291,3 +293,4 @@
 	if (color == RB_BLACK)
 		__rb_erase_color(child, parent, root);
 }
+EXPORT_SYMBOL(rb_erase);
diff -Nru a/lib/string.c b/lib/string.c
--- a/lib/string.c	Sun Apr 14 12:16:57 2002
+++ b/lib/string.c	Sun Apr 14 12:16:57 2002
@@ -13,6 +13,10 @@
  * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
  * -  Added strsep() which will replace strtok() soon (because strsep() is
  *    reentrant and should be faster). Use only strsep() in new code, please.
+ *
+ * * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
+ *                    Matthew Hawkins <matt@mh.dropbear.id.au>
+ * -  Kissed strtok() goodbye
  */
  
 #include <linux/types.h>
@@ -52,8 +56,6 @@
 }
 #endif
 
-char * ___strtok;
-
 #ifndef __HAVE_ARCH_STRCPY
 /**
  * strcpy - Copy a %NUL terminated string
@@ -290,35 +292,6 @@
 }
 #endif
 
-#ifndef __HAVE_ARCH_STRTOK
-/**
- * strtok - Split a string into tokens
- * @s: The string to be searched
- * @ct: The characters to search for
- *
- * WARNING: strtok is deprecated, use strsep instead.
- */
-char * strtok(char * s,const char * ct)
-{
-	char *sbegin, *send;
-
-	sbegin  = s ? s : ___strtok;
-	if (!sbegin) {
-		return NULL;
-	}
-	sbegin += strspn(sbegin,ct);
-	if (*sbegin == '\0') {
-		___strtok = NULL;
-		return( NULL );
-	}
-	send = strpbrk( sbegin, ct);
-	if (send && *send != '\0')
-		*send++ = '\0';
-	___strtok = send;
-	return (sbegin);
-}
-#endif
-
 #ifndef __HAVE_ARCH_STRSEP
 /**
  * strsep - Split a string into tokens
@@ -452,7 +425,7 @@
 int memcmp(const void * cs,const void * ct,size_t count)
 {
 	const unsigned char *su1, *su2;
-	signed char res = 0;
+	int res = 0;
 
 	for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
 		if ((res = *su1 - *su2) != 0)
diff -Nru a/mm/Makefile b/mm/Makefile
--- a/mm/Makefile	Sun Apr 14 12:16:59 2002
+++ b/mm/Makefile	Sun Apr 14 12:16:59 2002
@@ -14,6 +14,7 @@
 obj-y	 := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
 	    vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \
 	    page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o \
-	    shmem.o highmem.o mempool.o msync.o mincore.o
+	    shmem.o highmem.o mempool.o msync.o mincore.o readahead.o \
+	    pdflush.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Sun Apr 14 12:16:57 2002
+++ b/mm/filemap.c	Sun Apr 14 12:16:57 2002
@@ -26,6 +26,7 @@
 #include <linux/compiler.h>
 #include <linux/fs.h>
 #include <linux/hash.h>
+#include <linux/blkdev.h>
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
@@ -46,89 +47,46 @@
  */
 
 atomic_t page_cache_size = ATOMIC_INIT(0);
-unsigned int page_hash_bits;
-struct page **page_hash_table;
 
-spinlock_t pagecache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 /*
- * NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock 
- *	with the pagecache_lock held.
- *
- * Ordering:
- *	swap_lock ->
- *		pagemap_lru_lock ->
- *			pagecache_lock
+ * Lock ordering:
+ *	pagemap_lru_lock ==> page_lock ==> i_shared_lock
  */
 spinlock_t pagemap_lru_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
 
-static void FASTCALL(add_page_to_hash_queue(struct page * page, struct page **p));
-static void add_page_to_hash_queue(struct page * page, struct page **p)
-{
-	struct page *next = *p;
-
-	*p = page;
-	page->next_hash = next;
-	page->pprev_hash = p;
-	if (next)
-		next->pprev_hash = &page->next_hash;
-	if (page->buffers)
-		PAGE_BUG(page);
-	atomic_inc(&page_cache_size);
-}
-
-static inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
+/*
+ * Remove a page from the page cache and free it. Caller has to make
+ * sure the page is locked and that nobody else uses it - or that usage
+ * is safe.  The caller must hold a write_lock on the mapping's page_lock.
+ */
+void __remove_inode_page(struct page *page)
 {
-	struct list_head *head = &mapping->clean_pages;
-
-	mapping->nrpages++;
-	list_add(&page->list, head);
-	page->mapping = mapping;
-}
+	struct address_space *mapping = page->mapping;
 
-static inline void remove_page_from_inode_queue(struct page * page)
-{
-	struct address_space * mapping = page->mapping;
+	if (unlikely(PageDirty(page)))
+		BUG();
 
-	mapping->nrpages--;
+	radix_tree_delete(&page->mapping->page_tree, page->index);
 	list_del(&page->list);
 	page->mapping = NULL;
-}
-
-static inline void remove_page_from_hash_queue(struct page * page)
-{
-	struct page *next = page->next_hash;
-	struct page **pprev = page->pprev_hash;
 
-	if (next)
-		next->pprev_hash = pprev;
-	*pprev = next;
-	page->pprev_hash = NULL;
+	mapping->nrpages--;
 	atomic_dec(&page_cache_size);
 }
 
-/*
- * Remove a page from the page cache and free it. Caller has to make
- * sure the page is locked and that nobody else uses it - or that usage
- * is safe.
- */
-void __remove_inode_page(struct page *page)
-{
-	if (PageDirty(page)) BUG();
-	remove_page_from_inode_queue(page);
-	remove_page_from_hash_queue(page);
-}
-
 void remove_inode_page(struct page *page)
 {
-	if (!PageLocked(page))
+	struct address_space *mapping = page->mapping;
+
+	if (unlikely(!PageLocked(page)))
 		PAGE_BUG(page);
 
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 	__remove_inode_page(page);
-	spin_unlock(&pagecache_lock);
+	write_unlock(&mapping->page_lock);
 }
 
 static inline int sync_page(struct page *page)
@@ -149,10 +107,10 @@
 		struct address_space *mapping = page->mapping;
 
 		if (mapping) {
-			spin_lock(&pagecache_lock);
+			write_lock(&mapping->page_lock);
 			list_del(&page->list);
 			list_add(&page->list, &mapping->dirty_pages);
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 
 			if (mapping->host)
 				mark_inode_dirty_pages(mapping->host);
@@ -172,11 +130,12 @@
 {
 	struct list_head *head, *curr;
 	struct page * page;
+	struct address_space *mapping = inode->i_mapping;
 
-	head = &inode->i_mapping->clean_pages;
+	head = &mapping->clean_pages;
 
 	spin_lock(&pagemap_lru_lock);
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 	curr = head->next;
 
 	while (curr != head) {
@@ -191,7 +150,7 @@
 		if (TryLockPage(page))
 			continue;
 
-		if (page->buffers && !try_to_free_buffers(page, 0))
+		if (PagePrivate(page) && !try_to_release_page(page, 0))
 			goto unlock;
 
 		if (page_count(page) != 1)
@@ -207,7 +166,7 @@
 		continue;
 	}
 
-	spin_unlock(&pagecache_lock);
+	write_unlock(&mapping->page_lock);
 	spin_unlock(&pagemap_lru_lock);
 }
 
@@ -223,14 +182,18 @@
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
 	memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
-	if (page->buffers)
+	if (PagePrivate(page))
 		do_flushpage(page, partial);
 }
 
+/*
+ * AKPM: the PagePrivate test here seems a bit bogus.  It bypasses the
+ * mapping's ->flushpage, which may still want to be called.
+ */
 static void truncate_complete_page(struct page *page)
 {
 	/* Leave it on the LRU if it gets converted into anonymous buffers */
-	if (!page->buffers || do_flushpage(page, 0))
+	if (!PagePrivate(page) || do_flushpage(page, 0))
 		lru_cache_del(page);
 
 	/*
@@ -246,8 +209,8 @@
 	page_cache_release(page);
 }
 
-static int FASTCALL(truncate_list_pages(struct list_head *, unsigned long, unsigned *));
-static int truncate_list_pages(struct list_head *head, unsigned long start, unsigned *partial)
+static int truncate_list_pages(struct address_space *mapping,
+	struct list_head *head, unsigned long start, unsigned *partial)
 {
 	struct list_head *curr;
 	struct page * page;
@@ -276,7 +239,7 @@
 				/* Restart on this page */
 				list_add(head, curr);
 
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			unlocked = 1;
 
  			if (!failed) {
@@ -297,7 +260,7 @@
 				schedule();
 			}
 
-			spin_lock(&pagecache_lock);
+			write_lock(&mapping->page_lock);
 			goto restart;
 		}
 		curr = curr->prev;
@@ -305,7 +268,6 @@
 	return unlocked;
 }
 
-
 /**
  * truncate_inode_pages - truncate *all* the pages from an offset
  * @mapping: mapping to truncate
@@ -321,42 +283,46 @@
 	unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
 	int unlocked;
 
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 	do {
-		unlocked = truncate_list_pages(&mapping->clean_pages, start, &partial);
-		unlocked |= truncate_list_pages(&mapping->dirty_pages, start, &partial);
-		unlocked |= truncate_list_pages(&mapping->locked_pages, start, &partial);
+		unlocked = truncate_list_pages(mapping,
+				&mapping->clean_pages, start, &partial);
+		unlocked |= truncate_list_pages(mapping,
+				&mapping->dirty_pages, start, &partial);
+		unlocked |= truncate_list_pages(mapping,
+				&mapping->locked_pages, start, &partial);
 	} while (unlocked);
 	/* Traversed all three lists without dropping the lock */
-	spin_unlock(&pagecache_lock);
+	write_unlock(&mapping->page_lock);
 }
 
-static inline int invalidate_this_page2(struct page * page,
+static inline int invalidate_this_page2(struct address_space * mapping,
+					struct page * page,
 					struct list_head * curr,
 					struct list_head * head)
 {
 	int unlocked = 1;
 
 	/*
-	 * The page is locked and we hold the pagecache_lock as well
-	 * so both page_count(page) and page->buffers stays constant here.
+	 * The page is locked and we hold the mapping lock as well
+	 * so both page_count(page) and page_buffers stays constant here.
 	 */
-	if (page_count(page) == 1 + !!page->buffers) {
+	if (page_count(page) == 1 + !!page_has_buffers(page)) {
 		/* Restart after this page */
 		list_del(head);
 		list_add_tail(head, curr);
 
 		page_cache_get(page);
-		spin_unlock(&pagecache_lock);
+		write_unlock(&mapping->page_lock);
 		truncate_complete_page(page);
 	} else {
-		if (page->buffers) {
+		if (page_has_buffers(page)) {
 			/* Restart after this page */
 			list_del(head);
 			list_add_tail(head, curr);
 
 			page_cache_get(page);
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			block_invalidate_page(page);
 		} else
 			unlocked = 0;
@@ -368,8 +334,8 @@
 	return unlocked;
 }
 
-static int FASTCALL(invalidate_list_pages2(struct list_head *));
-static int invalidate_list_pages2(struct list_head *head)
+static int invalidate_list_pages2(struct address_space * mapping,
+				  struct list_head * head)
 {
 	struct list_head *curr;
 	struct page * page;
@@ -383,7 +349,7 @@
 		if (!TryLockPage(page)) {
 			int __unlocked;
 
-			__unlocked = invalidate_this_page2(page, curr, head);
+			__unlocked = invalidate_this_page2(mapping, page, curr, head);
 			UnlockPage(page);
 			unlocked |= __unlocked;
 			if (!__unlocked) {
@@ -396,7 +362,7 @@
 			list_add(head, curr);
 
 			page_cache_get(page);
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			unlocked = 1;
 			wait_on_page(page);
 		}
@@ -407,7 +373,7 @@
 			schedule();
 		}
 
-		spin_lock(&pagecache_lock);
+		write_lock(&mapping->page_lock);
 		goto restart;
 	}
 	return unlocked;
@@ -422,46 +388,32 @@
 {
 	int unlocked;
 
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 	do {
-		unlocked = invalidate_list_pages2(&mapping->clean_pages);
-		unlocked |= invalidate_list_pages2(&mapping->dirty_pages);
-		unlocked |= invalidate_list_pages2(&mapping->locked_pages);
+		unlocked = invalidate_list_pages2(mapping,
+				&mapping->clean_pages);
+		unlocked |= invalidate_list_pages2(mapping,
+				&mapping->dirty_pages);
+		unlocked |= invalidate_list_pages2(mapping,
+				&mapping->locked_pages);
 	} while (unlocked);
-	spin_unlock(&pagecache_lock);
-}
-
-static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page)
-{
-	goto inside;
-
-	for (;;) {
-		page = page->next_hash;
-inside:
-		if (!page)
-			goto not_found;
-		if (page->mapping != mapping)
-			continue;
-		if (page->index == offset)
-			break;
-	}
-
-not_found:
-	return page;
+	write_unlock(&mapping->page_lock);
 }
 
-static int do_buffer_fdatasync(struct list_head *head, unsigned long start, unsigned long end, int (*fn)(struct page *))
+static int do_buffer_fdatasync(struct address_space *mapping,
+		struct list_head *head, unsigned long start,
+		unsigned long end, int (*fn)(struct page *))
 {
 	struct list_head *curr;
 	struct page *page;
 	int retval = 0;
 
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 	curr = head->next;
 	while (curr != head) {
 		page = list_entry(curr, struct page, list);
 		curr = curr->next;
-		if (!page->buffers)
+		if (!page_has_buffers(page))
 			continue;
 		if (page->index >= end)
 			continue;
@@ -469,19 +421,19 @@
 			continue;
 
 		page_cache_get(page);
-		spin_unlock(&pagecache_lock);
+		write_unlock(&mapping->page_lock);
 		lock_page(page);
 
 		/* The buffers could have been free'd while we waited for the page lock */
-		if (page->buffers)
+		if (page_has_buffers(page))
 			retval |= fn(page);
 
 		UnlockPage(page);
-		spin_lock(&pagecache_lock);
+		write_lock(&mapping->page_lock);
 		curr = page->list.next;
 		page_cache_release(page);
 	}
-	spin_unlock(&pagecache_lock);
+	write_unlock(&mapping->page_lock);
 
 	return retval;
 }
@@ -492,17 +444,24 @@
  */
 int generic_buffer_fdatasync(struct inode *inode, unsigned long start_idx, unsigned long end_idx)
 {
+	struct address_space *mapping = inode->i_mapping;
 	int retval;
 
 	/* writeout dirty buffers on pages from both clean and dirty lists */
-	retval = do_buffer_fdatasync(&inode->i_mapping->dirty_pages, start_idx, end_idx, writeout_one_page);
-	retval |= do_buffer_fdatasync(&inode->i_mapping->clean_pages, start_idx, end_idx, writeout_one_page);
-	retval |= do_buffer_fdatasync(&inode->i_mapping->locked_pages, start_idx, end_idx, writeout_one_page);
+	retval = do_buffer_fdatasync(mapping, &mapping->dirty_pages,
+			start_idx, end_idx, writeout_one_page);
+	retval |= do_buffer_fdatasync(mapping, &mapping->clean_pages,
+			start_idx, end_idx, writeout_one_page);
+	retval |= do_buffer_fdatasync(mapping, &mapping->locked_pages,
+			start_idx, end_idx, writeout_one_page);
 
 	/* now wait for locked buffers on pages from both clean and dirty lists */
-	retval |= do_buffer_fdatasync(&inode->i_mapping->dirty_pages, start_idx, end_idx, waitfor_one_page);
-	retval |= do_buffer_fdatasync(&inode->i_mapping->clean_pages, start_idx, end_idx, waitfor_one_page);
-	retval |= do_buffer_fdatasync(&inode->i_mapping->locked_pages, start_idx, end_idx, waitfor_one_page);
+	retval |= do_buffer_fdatasync(mapping, &mapping->dirty_pages,
+			start_idx, end_idx, waitfor_one_page);
+	retval |= do_buffer_fdatasync(mapping, &mapping->clean_pages,
+			start_idx, end_idx, waitfor_one_page);
+	retval |= do_buffer_fdatasync(mapping, &mapping->locked_pages,
+			start_idx, end_idx, waitfor_one_page);
 
 	return retval;
 }
@@ -548,7 +507,7 @@
 	int ret = 0;
 	int (*writepage)(struct page *) = mapping->a_ops->writepage;
 
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 
         while (!list_empty(&mapping->dirty_pages)) {
 		struct page *page = list_entry(mapping->dirty_pages.prev, struct page, list);
@@ -560,7 +519,7 @@
 			continue;
 
 		page_cache_get(page);
-		spin_unlock(&pagecache_lock);
+		write_unlock(&mapping->page_lock);
 
 		lock_page(page);
 
@@ -574,9 +533,9 @@
 			UnlockPage(page);
 
 		page_cache_release(page);
-		spin_lock(&pagecache_lock);
+		write_lock(&mapping->page_lock);
 	}
-	spin_unlock(&pagecache_lock);
+	write_unlock(&mapping->page_lock);
 	return ret;
 }
 
@@ -591,7 +550,7 @@
 {
 	int ret = 0;
 
-	spin_lock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
 
         while (!list_empty(&mapping->locked_pages)) {
 		struct page *page = list_entry(mapping->locked_pages.next, struct page, list);
@@ -603,86 +562,69 @@
 			continue;
 
 		page_cache_get(page);
-		spin_unlock(&pagecache_lock);
+		write_unlock(&mapping->page_lock);
 
 		___wait_on_page(page);
 		if (PageError(page))
 			ret = -EIO;
 
 		page_cache_release(page);
-		spin_lock(&pagecache_lock);
+		write_lock(&mapping->page_lock);
 	}
-	spin_unlock(&pagecache_lock);
+	write_unlock(&mapping->page_lock);
 	return ret;
 }
 
 /*
- * Add a page to the inode page cache.
- *
- * The caller must have locked the page and 
- * set all the page flags correctly..
- */
-void add_to_page_cache_locked(struct page * page, struct address_space *mapping, unsigned long index)
-{
-	if (!PageLocked(page))
-		BUG();
-
-	page->index = index;
-	page_cache_get(page);
-	spin_lock(&pagecache_lock);
-	add_page_to_inode_queue(mapping, page);
-	add_page_to_hash_queue(page, page_hash(mapping, index));
-	spin_unlock(&pagecache_lock);
-
-	lru_cache_add(page);
-}
-
-/*
  * This adds a page to the page cache, starting out as locked,
  * owned by us, but unreferenced, not uptodate and with no errors.
+ * The caller must hold a write_lock on the mapping->page_lock.
  */
-static inline void __add_to_page_cache(struct page * page,
-	struct address_space *mapping, unsigned long offset,
-	struct page **hash)
+static int __add_to_page_cache(struct page *page,
+		struct address_space *mapping, unsigned long offset)
 {
 	unsigned long flags;
 
+	page_cache_get(page);
+	if (radix_tree_insert(&mapping->page_tree, offset, page) < 0)
+		goto nomem;
 	flags = page->flags & ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_dirty | 1 << PG_referenced | 1 << PG_arch_1 | 1 << PG_checked);
 	page->flags = flags | (1 << PG_locked);
-	page_cache_get(page);
-	page->index = offset;
-	add_page_to_inode_queue(mapping, page);
-	add_page_to_hash_queue(page, hash);
+	___add_to_page_cache(page, mapping, offset);
+	return 0;
+ nomem:
+	page_cache_release(page);
+	return -ENOMEM;
 }
 
-void add_to_page_cache(struct page * page, struct address_space * mapping, unsigned long offset)
+int add_to_page_cache(struct page *page,
+		struct address_space *mapping, unsigned long offset)
 {
-	spin_lock(&pagecache_lock);
-	__add_to_page_cache(page, mapping, offset, page_hash(mapping, offset));
-	spin_unlock(&pagecache_lock);
+	write_lock(&mapping->page_lock);
+	if (__add_to_page_cache(page, mapping, offset) < 0)
+		goto nomem;
+	write_unlock(&mapping->page_lock);
 	lru_cache_add(page);
+	return 0;
+nomem:
+	write_unlock(&mapping->page_lock);
+	return -ENOMEM;
 }
 
-int add_to_page_cache_unique(struct page * page,
-	struct address_space *mapping, unsigned long offset,
-	struct page **hash)
+int add_to_page_cache_unique(struct page *page,
+		struct address_space *mapping, unsigned long offset)
 {
-	int err;
 	struct page *alias;
+	int error = -EEXIST;
 
-	spin_lock(&pagecache_lock);
-	alias = __find_page_nolock(mapping, offset, *hash);
+	write_lock(&mapping->page_lock);
+	if (!(alias = radix_tree_lookup(&mapping->page_tree, offset)))
+		error = __add_to_page_cache(page, mapping, offset);
+	write_unlock(&mapping->page_lock);
 
-	err = 1;
-	if (!alias) {
-		__add_to_page_cache(page,mapping,offset,hash);
-		err = 0;
-	}
-
-	spin_unlock(&pagecache_lock);
-	if (!err)
+	if (!error)
 		lru_cache_add(page);
-	return err;
+	return error;
 }
 
 /*
@@ -693,12 +635,12 @@
 static int page_cache_read(struct file * file, unsigned long offset)
 {
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
-	struct page **hash = page_hash(mapping, offset);
 	struct page *page; 
+	int error;
 
-	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(mapping, offset, *hash);
-	spin_unlock(&pagecache_lock);
+	read_lock(&mapping->page_lock);
+	page = radix_tree_lookup(&mapping->page_tree, offset);
+	read_unlock(&mapping->page_lock);
 	if (page)
 		return 0;
 
@@ -706,62 +648,23 @@
 	if (!page)
 		return -ENOMEM;
 
-	if (!add_to_page_cache_unique(page, mapping, offset, hash)) {
-		int error = mapping->a_ops->readpage(file, page);
+	error = add_to_page_cache_unique(page, mapping, offset);
+	if (!error) {
+		error = mapping->a_ops->readpage(file, page);
 		page_cache_release(page);
 		return error;
 	}
+
 	/*
 	 * We arrive here in the unlikely event that someone 
-	 * raced with us and added our page to the cache first.
+	 * raced with us and added our page to the cache first
+	 * or we are out of memory for radix-tree nodes.
 	 */
 	page_cache_release(page);
-	return 0;
+	return error == -EEXIST ? 0 : error;
 }
 
 /*
- * Read in an entire cluster at once.  A cluster is usually a 64k-
- * aligned block that includes the page requested in "offset."
- */
-static int FASTCALL(read_cluster_nonblocking(struct file * file, unsigned long offset,
-					     unsigned long filesize));
-static int read_cluster_nonblocking(struct file * file, unsigned long offset,
-	unsigned long filesize)
-{
-	unsigned long pages = CLUSTER_PAGES;
-
-	offset = CLUSTER_OFFSET(offset);
-	while ((pages-- > 0) && (offset < filesize)) {
-		int error = page_cache_read(file, offset);
-		if (error < 0)
-			return error;
-		offset ++;
-	}
-
-	return 0;
-}
-
-/*
- * Knuth recommends primes in approximately golden ratio to the maximum
- * integer representable by a machine word for multiplicative hashing.
- * Chuck Lever verified the effectiveness of this technique:
- * http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
- *
- * These primes are chosen to be bit-sparse, that is operations on
- * them can use shifts and additions instead of multiplications for
- * machines where multiplications are slow.
- */
-#if BITS_PER_LONG == 32
-/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
-#define GOLDEN_RATIO_PRIME 0x9e370001UL
-#elif BITS_PER_LONG == 64
-/*  2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
-#define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL
-#else
-#error Define GOLDEN_RATIO_PRIME for your wordsize.
-#endif
-
-/*
  * In order to wait for pages to become available there must be
  * waitqueues associated with pages. By using a hash table of
  * waitqueues where the bucket discipline is to maintain all
@@ -862,8 +765,7 @@
  * a rather lightweight function, finding and getting a reference to a
  * hashed page atomically.
  */
-struct page * __find_get_page(struct address_space *mapping,
-			      unsigned long offset, struct page **hash)
+struct page * find_get_page(struct address_space *mapping, unsigned long offset)
 {
 	struct page *page;
 
@@ -871,11 +773,11 @@
 	 * We scan the hash list read-only. Addition to and removal from
 	 * the hash-list needs a held write-lock.
 	 */
-	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(mapping, offset, *hash);
+	read_lock(&mapping->page_lock);
+	page = radix_tree_lookup(&mapping->page_tree, offset);
 	if (page)
 		page_cache_get(page);
-	spin_unlock(&pagecache_lock);
+	read_unlock(&mapping->page_lock);
 	return page;
 }
 
@@ -885,15 +787,12 @@
 struct page *find_trylock_page(struct address_space *mapping, unsigned long offset)
 {
 	struct page *page;
-	struct page **hash = page_hash(mapping, offset);
 
-	spin_lock(&pagecache_lock);
-	page = __find_page_nolock(mapping, offset, *hash);
-	if (page) {
-		if (TryLockPage(page))
-			page = NULL;
-	}
-	spin_unlock(&pagecache_lock);
+	read_lock(&mapping->page_lock);
+	page = radix_tree_lookup(&mapping->page_tree, offset);
+	if (page && TryLockPage(page))
+		page = NULL;
+	read_unlock(&mapping->page_lock);
 	return page;
 }
 
@@ -902,9 +801,8 @@
  * will return with it held (but it may be dropped
  * during blocking operations..
  */
-static struct page * FASTCALL(__find_lock_page_helper(struct address_space *, unsigned long, struct page *));
-static struct page * __find_lock_page_helper(struct address_space *mapping,
-					unsigned long offset, struct page *hash)
+static struct page *__find_lock_page(struct address_space *mapping,
+					unsigned long offset)
 {
 	struct page *page;
 
@@ -913,13 +811,13 @@
 	 * the hash-list needs a held write-lock.
 	 */
 repeat:
-	page = __find_page_nolock(mapping, offset, hash);
+	page = radix_tree_lookup(&mapping->page_tree, offset);
 	if (page) {
 		page_cache_get(page);
 		if (TryLockPage(page)) {
-			spin_unlock(&pagecache_lock);
+			read_unlock(&mapping->page_lock);
 			lock_page(page);
-			spin_lock(&pagecache_lock);
+			read_lock(&mapping->page_lock);
 
 			/* Has the page been re-allocated while we slept? */
 			if (page->mapping != mapping || page->index != offset) {
@@ -936,46 +834,50 @@
  * Same as the above, but lock the page too, verifying that
  * it's still valid once we own it.
  */
-struct page * __find_lock_page (struct address_space *mapping,
-				unsigned long offset, struct page **hash)
+struct page * find_lock_page(struct address_space *mapping, unsigned long offset)
 {
 	struct page *page;
 
-	spin_lock(&pagecache_lock);
-	page = __find_lock_page_helper(mapping, offset, *hash);
-	spin_unlock(&pagecache_lock);
+	read_lock(&mapping->page_lock);
+	page = __find_lock_page(mapping, offset);
+	read_unlock(&mapping->page_lock);
+
 	return page;
 }
 
 /*
  * Same as above, but create the page if required..
  */
-struct page * find_or_create_page(struct address_space *mapping, unsigned long index, unsigned int gfp_mask)
+struct page * find_or_create_page(struct address_space *mapping,
+		unsigned long index, unsigned int gfp_mask)
 {
 	struct page *page;
-	struct page **hash = page_hash(mapping, index);
 
-	spin_lock(&pagecache_lock);
-	page = __find_lock_page_helper(mapping, index, *hash);
-	spin_unlock(&pagecache_lock);
+	page = find_lock_page(mapping, index);
 	if (!page) {
 		struct page *newpage = alloc_page(gfp_mask);
 		if (newpage) {
-			spin_lock(&pagecache_lock);
-			page = __find_lock_page_helper(mapping, index, *hash);
+			write_lock(&mapping->page_lock);
+			page = __find_lock_page(mapping, index);
 			if (likely(!page)) {
 				page = newpage;
-				__add_to_page_cache(page, mapping, index, hash);
+				if (__add_to_page_cache(page, mapping, index)) {
+					write_unlock(&mapping->page_lock);
+					page_cache_release(page);
+					page = NULL;
+					goto out;
+				}
 				newpage = NULL;
 			}
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			if (newpage == NULL)
 				lru_cache_add(page);
 			else 
 				page_cache_release(newpage);
 		}
 	}
-	return page;	
+out:
+	return page;
 }
 
 /*
@@ -995,10 +897,9 @@
  */
 struct page *grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
 {
-	struct page *page, **hash;
+	struct page *page;
 
-	hash = page_hash(mapping, index);
-	page = __find_get_page(mapping, index, hash);
+	page = find_get_page(mapping, index);
 
 	if ( page ) {
 		if ( !TryLockPage(page) ) {
@@ -1020,11 +921,14 @@
 	}
 
 	page = page_cache_alloc(mapping);
-	if ( unlikely(!page) )
+	if (unlikely(!page))
 		return NULL;	/* Failed to allocate a page */
 
-	if ( unlikely(add_to_page_cache_unique(page, mapping, index, hash)) ) {
-		/* Someone else grabbed the page already. */
+	if (unlikely(add_to_page_cache_unique(page, mapping, index))) {
+		/*
+		 * Someone else grabbed the page already, or
+		 * failed to allocate a radix-tree node
+		 */
 		page_cache_release(page);
 		return NULL;
 	}
@@ -1032,232 +936,6 @@
 	return page;
 }
 
-#if 0
-#define PROFILE_READAHEAD
-#define DEBUG_READAHEAD
-#endif
-
-/*
- * Read-ahead profiling information
- * --------------------------------
- * Every PROFILE_MAXREADCOUNT, the following information is written 
- * to the syslog:
- *   Percentage of asynchronous read-ahead.
- *   Average of read-ahead fields context value.
- * If DEBUG_READAHEAD is defined, a snapshot of these fields is written 
- * to the syslog.
- */
-
-#ifdef PROFILE_READAHEAD
-
-#define PROFILE_MAXREADCOUNT 1000
-
-static unsigned long total_reada;
-static unsigned long total_async;
-static unsigned long total_ramax;
-static unsigned long total_ralen;
-static unsigned long total_rawin;
-
-static void profile_readahead(int async, struct file *filp)
-{
-	unsigned long flags;
-
-	++total_reada;
-	if (async)
-		++total_async;
-
-	total_ramax	+= filp->f_ramax;
-	total_ralen	+= filp->f_ralen;
-	total_rawin	+= filp->f_rawin;
-
-	if (total_reada > PROFILE_MAXREADCOUNT) {
-		save_flags(flags);
-		cli();
-		if (!(total_reada > PROFILE_MAXREADCOUNT)) {
-			restore_flags(flags);
-			return;
-		}
-
-		printk("Readahead average:  max=%ld, len=%ld, win=%ld, async=%ld%%\n",
-			total_ramax/total_reada,
-			total_ralen/total_reada,
-			total_rawin/total_reada,
-			(total_async*100)/total_reada);
-#ifdef DEBUG_READAHEAD
-		printk("Readahead snapshot: max=%ld, len=%ld, win=%ld, raend=%Ld\n",
-			filp->f_ramax, filp->f_ralen, filp->f_rawin, filp->f_raend);
-#endif
-
-		total_reada	= 0;
-		total_async	= 0;
-		total_ramax	= 0;
-		total_ralen	= 0;
-		total_rawin	= 0;
-
-		restore_flags(flags);
-	}
-}
-#endif  /* defined PROFILE_READAHEAD */
-
-/*
- * Read-ahead context:
- * -------------------
- * The read ahead context fields of the "struct file" are the following:
- * - f_raend : position of the first byte after the last page we tried to
- *	       read ahead.
- * - f_ramax : current read-ahead maximum size.
- * - f_ralen : length of the current IO read block we tried to read-ahead.
- * - f_rawin : length of the current read-ahead window.
- *		if last read-ahead was synchronous then
- *			f_rawin = f_ralen
- *		otherwise (was asynchronous)
- *			f_rawin = previous value of f_ralen + f_ralen
- *
- * Read-ahead limits:
- * ------------------
- * MIN_READAHEAD   : minimum read-ahead size when read-ahead.
- * MAX_READAHEAD   : maximum read-ahead size when read-ahead.
- *
- * Synchronous read-ahead benefits:
- * --------------------------------
- * Using reasonable IO xfer length from peripheral devices increase system 
- * performances.
- * Reasonable means, in this context, not too large but not too small.
- * The actual maximum value is:
- *	MAX_READAHEAD + PAGE_CACHE_SIZE = 76k is CONFIG_READA_SMALL is undefined
- *      and 32K if defined (4K page size assumed).
- *
- * Asynchronous read-ahead benefits:
- * ---------------------------------
- * Overlapping next read request and user process execution increase system 
- * performance.
- *
- * Read-ahead risks:
- * -----------------
- * We have to guess which further data are needed by the user process.
- * If these data are often not really needed, it's bad for system 
- * performances.
- * However, we know that files are often accessed sequentially by 
- * application programs and it seems that it is possible to have some good 
- * strategy in that guessing.
- * We only try to read-ahead files that seems to be read sequentially.
- *
- * Asynchronous read-ahead risks:
- * ------------------------------
- * In order to maximize overlapping, we must start some asynchronous read
- * request from the device, as soon as possible.
- * We must be very careful about:
- * - The number of effective pending IO read requests.
- *   ONE seems to be the only reasonable value.
- * - The total memory pool usage for the file access stream.
- *   This maximum memory usage is implicitly 2 IO read chunks:
- *   2*(MAX_READAHEAD + PAGE_CACHE_SIZE) = 156K if CONFIG_READA_SMALL is undefined,
- *   64k if defined (4K page size assumed).
- */
-
-static void generic_file_readahead(int reada_ok,
-	struct file * filp, struct inode * inode,
-	struct page * page)
-{
-	unsigned long end_index;
-	unsigned long index = page->index;
-	unsigned long max_ahead, ahead;
-	unsigned long raend;
-
-	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-
-	raend = filp->f_raend;
-	max_ahead = 0;
-
-/*
- * The current page is locked.
- * If the current position is inside the previous read IO request, do not
- * try to reread previously read ahead pages.
- * Otherwise decide or not to read ahead some pages synchronously.
- * If we are not going to read ahead, set the read ahead context for this 
- * page only.
- */
-	if (PageLocked(page)) {
-		if (!filp->f_ralen || index >= raend || index + filp->f_rawin < raend) {
-			raend = index;
-			if (raend < end_index)
-				max_ahead = filp->f_ramax;
-			filp->f_rawin = 0;
-			filp->f_ralen = 1;
-			if (!max_ahead) {
-				filp->f_raend  = index + filp->f_ralen;
-				filp->f_rawin += filp->f_ralen;
-			}
-		}
-	}
-/*
- * The current page is not locked.
- * If we were reading ahead and,
- * if the current max read ahead size is not zero and,
- * if the current position is inside the last read-ahead IO request,
- *   it is the moment to try to read ahead asynchronously.
- * We will later force unplug device in order to force asynchronous read IO.
- */
-	else if (reada_ok && filp->f_ramax && raend >= 1 &&
-		 index <= raend && index + filp->f_ralen >= raend) {
-/*
- * Add ONE page to max_ahead in order to try to have about the same IO max size
- * as synchronous read-ahead (MAX_READAHEAD + 1)*PAGE_CACHE_SIZE.
- * Compute the position of the last page we have tried to read in order to 
- * begin to read ahead just at the next page.
- */
-		raend -= 1;
-		if (raend < end_index)
-			max_ahead = filp->f_ramax + 1;
-
-		if (max_ahead) {
-			filp->f_rawin = filp->f_ralen;
-			filp->f_ralen = 0;
-			reada_ok      = 2;
-		}
-	}
-/*
- * Try to read ahead pages.
- * We hope that ll_rw_blk() plug/unplug, coalescence, requests sort and the
- * scheduler, will work enough for us to avoid too bad actuals IO requests.
- */
-	ahead = 0;
-	while (ahead < max_ahead) {
-		ahead ++;
-		if ((raend + ahead) >= end_index)
-			break;
-		if (page_cache_read(filp, raend + ahead) < 0)
-			break;
-	}
-/*
- * If we tried to read ahead some pages,
- * If we tried to read ahead asynchronously,
- *   Try to force unplug of the device in order to start an asynchronous
- *   read IO request.
- * Update the read-ahead context.
- * Store the length of the current read-ahead window.
- * Double the current max read ahead size.
- *   That heuristic avoid to do some large IO for files that are not really
- *   accessed sequentially.
- */
-	if (ahead) {
-		filp->f_ralen += ahead;
-		filp->f_rawin += filp->f_ralen;
-		filp->f_raend = raend + ahead + 1;
-
-		filp->f_ramax += filp->f_ramax;
-
-		if (filp->f_ramax > MAX_READAHEAD)
-			filp->f_ramax = MAX_READAHEAD;
-
-#ifdef PROFILE_READAHEAD
-		profile_readahead((reada_ok == 2), filp);
-#endif
-	}
-
-	return;
-}
-
 /*
  * Mark a page as having seen activity.
  *
@@ -1292,54 +970,14 @@
 	struct inode *inode = mapping->host;
 	unsigned long index, offset;
 	struct page *cached_page;
-	int reada_ok;
 	int error;
 
 	cached_page = NULL;
 	index = *ppos >> PAGE_CACHE_SHIFT;
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
-/*
- * If the current position is outside the previous read-ahead window, 
- * we reset the current read-ahead context and set read ahead max to zero
- * (will be set to just needed value later),
- * otherwise, we assume that the file accesses are sequential enough to
- * continue read-ahead.
- */
-	if (index > filp->f_raend || index + filp->f_rawin < filp->f_raend) {
-		reada_ok = 0;
-		filp->f_raend = 0;
-		filp->f_ralen = 0;
-		filp->f_ramax = 0;
-		filp->f_rawin = 0;
-	} else {
-		reada_ok = 1;
-	}
-/*
- * Adjust the current value of read-ahead max.
- * If the read operation stay in the first half page, force no readahead.
- * Otherwise try to increase read ahead max just enough to do the read request.
- * Then, at least MIN_READAHEAD if read ahead is ok,
- * and at most MAX_READAHEAD in all cases.
- */
-	if (!index && offset + desc->count <= (PAGE_CACHE_SIZE >> 1)) {
-		filp->f_ramax = 0;
-	} else {
-		unsigned long needed;
-
-		needed = ((offset + desc->count) >> PAGE_CACHE_SHIFT) + 1;
-
-		if (filp->f_ramax < needed)
-			filp->f_ramax = needed;
-
-		if (reada_ok && filp->f_ramax < MIN_READAHEAD)
-			filp->f_ramax = MIN_READAHEAD;
-		if (filp->f_ramax > MAX_READAHEAD)
-			filp->f_ramax = MAX_READAHEAD;
-	}
-
 	for (;;) {
-		struct page *page, **hash;
+		struct page *page;
 		unsigned long end_index, nr, ret;
 
 		end_index = inode->i_size >> PAGE_CACHE_SHIFT;
@@ -1353,24 +991,28 @@
 				break;
 		}
 
+		page_cache_readahead(filp, index);
+
 		nr = nr - offset;
 
 		/*
 		 * Try to find the data in the page cache..
 		 */
-		hash = page_hash(mapping, index);
 
-		spin_lock(&pagecache_lock);
-		page = __find_page_nolock(mapping, index, *hash);
-		if (!page)
+		write_lock(&mapping->page_lock);
+		page = radix_tree_lookup(&mapping->page_tree, index);
+		if (!page) {
+			write_unlock(&mapping->page_lock);
+			handle_ra_thrashing(filp);
+			write_lock(&mapping->page_lock);
 			goto no_cached_page;
+		}
 found_page:
 		page_cache_get(page);
-		spin_unlock(&pagecache_lock);
+		write_unlock(&mapping->page_lock);
 
 		if (!Page_Uptodate(page))
 			goto page_not_up_to_date;
-		generic_file_readahead(reada_ok, filp, inode, page);
 page_ok:
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
@@ -1380,10 +1022,9 @@
 			flush_dcache_page(page);
 
 		/*
-		 * Mark the page accessed if we read the
-		 * beginning or we just did an lseek.
+		 * Mark the page accessed if we read the beginning.
 		 */
-		if (!offset || !filp->f_reada)
+		if (!offset)
 			mark_page_accessed(page);
 
 		/*
@@ -1406,12 +1047,7 @@
 			continue;
 		break;
 
-/*
- * Ok, the page was not immediately readable, so let's try to read ahead while we're at it..
- */
 page_not_up_to_date:
-		generic_file_readahead(reada_ok, filp, inode, page);
-
 		if (Page_Uptodate(page))
 			goto page_ok;
 
@@ -1438,9 +1074,6 @@
 		if (!error) {
 			if (Page_Uptodate(page))
 				goto page_ok;
-
-			/* Again, try some read-ahead while waiting for the page to finish.. */
-			generic_file_readahead(reada_ok, filp, inode, page);
 			wait_on_page(page);
 			if (Page_Uptodate(page))
 				goto page_ok;
@@ -1460,7 +1093,7 @@
 		 * We get here with the page cache lock held.
 		 */
 		if (!cached_page) {
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			cached_page = page_cache_alloc(mapping);
 			if (!cached_page) {
 				desc->error = -ENOMEM;
@@ -1471,8 +1104,8 @@
 			 * Somebody may have added the page while we
 			 * dropped the page cache lock. Check for that.
 			 */
-			spin_lock(&pagecache_lock);
-			page = __find_page_nolock(mapping, index, *hash);
+			write_lock(&mapping->page_lock);
+			page = radix_tree_lookup(&mapping->page_tree, index);
 			if (page)
 				goto found_page;
 		}
@@ -1480,9 +1113,13 @@
 		/*
 		 * Ok, add the new page to the hash-queues...
 		 */
+		if (__add_to_page_cache(cached_page, mapping, index) < 0) {
+			write_unlock(&mapping->page_lock);
+			desc->error = -ENOMEM;
+			break;
+		}
 		page = cached_page;
-		__add_to_page_cache(page, mapping, index, hash);
-		spin_unlock(&pagecache_lock);
+		write_unlock(&mapping->page_lock);
 		lru_cache_add(page);		
 		cached_page = NULL;
 
@@ -1490,7 +1127,6 @@
 	}
 
 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
-	filp->f_reada = 1;
 	if (cached_page)
 		page_cache_release(cached_page);
 	UPDATE_ATIME(inode);
@@ -1815,24 +1451,12 @@
 	if (!mapping || !mapping->a_ops || !mapping->a_ops->readpage)
 		return -EINVAL;
 
-	/* Limit it to the size of the file.. */
-	max = (mapping->host->i_size + ~PAGE_CACHE_MASK) >> PAGE_CACHE_SHIFT;
-	if (index > max)
-		return 0;
-	max -= index;
-	if (nr > max)
-		nr = max;
-
-	/* And limit it to a sane percentage of the inactive list.. */
+	/* Limit it to a sane percentage of the inactive list.. */
 	max = nr_inactive_pages / 2;
 	if (nr > max)
 		nr = max;
 
-	while (nr) {
-		page_cache_read(file, index);
-		index++;
-		nr--;
-	}
+	do_page_cache_readahead(file, index, nr);
 	return 0;
 }
 
@@ -1846,7 +1470,8 @@
 	if (file) {
 		if (file->f_mode & FMODE_READ) {
 			unsigned long start = offset >> PAGE_CACHE_SHIFT;
-			unsigned long len = (count + ((long)offset & ~PAGE_CACHE_MASK)) >> PAGE_CACHE_SHIFT;
+			unsigned long end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
+			unsigned long len = end - start + 1;
 			ret = do_readahead(file, start, len);
 		}
 		fput(file);
@@ -1855,60 +1480,6 @@
 }
 
 /*
- * Read-ahead and flush behind for MADV_SEQUENTIAL areas.  Since we are
- * sure this is sequential access, we don't need a flexible read-ahead
- * window size -- we can always use a large fixed size window.
- */
-static void nopage_sequential_readahead(struct vm_area_struct * vma,
-	unsigned long pgoff, unsigned long filesize)
-{
-	unsigned long ra_window;
-
-	ra_window = CLUSTER_OFFSET(MAX_READAHEAD + CLUSTER_PAGES - 1);
-
-	/* vm_raend is zero if we haven't read ahead in this area yet.  */
-	if (vma->vm_raend == 0)
-		vma->vm_raend = vma->vm_pgoff + ra_window;
-
-	/*
-	 * If we've just faulted the page half-way through our window,
-	 * then schedule reads for the next window, and release the
-	 * pages in the previous window.
-	 */
-	if ((pgoff + (ra_window >> 1)) == vma->vm_raend) {
-		unsigned long start = vma->vm_pgoff + vma->vm_raend;
-		unsigned long end = start + ra_window;
-
-		if (end > ((vma->vm_end >> PAGE_SHIFT) + vma->vm_pgoff))
-			end = (vma->vm_end >> PAGE_SHIFT) + vma->vm_pgoff;
-		if (start > end)
-			return;
-
-		while ((start < end) && (start < filesize)) {
-			if (read_cluster_nonblocking(vma->vm_file,
-							start, filesize) < 0)
-				break;
-			start += CLUSTER_PAGES;
-		}
-		run_task_queue(&tq_disk);
-
-		/* if we're far enough past the beginning of this area,
-		   recycle pages that are in the previous window. */
-		if (vma->vm_raend > (vma->vm_pgoff + ra_window + ra_window)) {
-			unsigned long window = ra_window << PAGE_SHIFT;
-
-			end = vma->vm_start + (vma->vm_raend << PAGE_SHIFT);
-			end -= window + window;
-			filemap_sync(vma, end - window, window, MS_INVALIDATE);
-		}
-
-		vma->vm_raend += ra_window;
-	}
-
-	return;
-}
-
-/*
  * filemap_nopage() is invoked via the vma operations vector for a
  * mapped memory region to read in file data during a page fault.
  *
@@ -1916,13 +1487,14 @@
  * it in the page cache, and handles the special cases reasonably without
  * having a lot of duplicated code.
  */
+
 struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address, int unused)
 {
 	int error;
 	struct file *file = area->vm_file;
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	struct inode *inode = mapping->host;
-	struct page *page, **hash;
+	struct page *page;
 	unsigned long size, pgoff, endoff;
 
 	pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
@@ -1942,11 +1514,24 @@
 		size = endoff;
 
 	/*
+	 * The readahead code wants to be told about each and every page
+	 * so it can build and shrink its windows appropriately
+	 */
+	if (VM_SequentialReadHint(area))
+		page_cache_readahead(area->vm_file, pgoff);
+
+	/*
+	 * If the offset is outside the mapping size we're off the end
+	 * of a privately mapped file, so we need to map a zero page.
+	 */
+	if ((pgoff < size) && !VM_RandomReadHint(area))
+		page_cache_readaround(file, pgoff);
+
+	/*
 	 * Do we have something in the page cache already?
 	 */
-	hash = page_hash(mapping, pgoff);
 retry_find:
-	page = __find_get_page(mapping, pgoff, hash);
+	page = find_get_page(mapping, pgoff);
 	if (!page)
 		goto no_cached_page;
 
@@ -1958,12 +1543,6 @@
 		goto page_not_uptodate;
 
 success:
- 	/*
-	 * Try read-ahead for sequential areas.
-	 */
-	if (VM_SequentialReadHint(area))
-		nopage_sequential_readahead(area, pgoff, size);
-
 	/*
 	 * Found the page and have a reference on it, need to check sharing
 	 * and possibly copy it over to another page..
@@ -1974,16 +1553,10 @@
 
 no_cached_page:
 	/*
-	 * If the requested offset is within our file, try to read a whole 
-	 * cluster of pages at once.
-	 *
-	 * Otherwise, we're off the end of a privately mapped file,
-	 * so we need to map a zero page.
+	 * We're only likely to ever get here if MADV_RANDOM is in
+	 * effect.
 	 */
-	if ((pgoff < size) && !VM_RandomReadHint(area))
-		error = read_cluster_nonblocking(file, pgoff, size);
-	else
-		error = page_cache_read(file, pgoff);
+	error = page_cache_read(file, pgoff);
 
 	/*
 	 * The page we want has now been added to the page cache.
@@ -2228,7 +1801,7 @@
  * to make sure they are started.  Do not wait for completion.
  */
 static long madvise_willneed(struct vm_area_struct * vma,
-	unsigned long start, unsigned long end)
+				unsigned long start, unsigned long end)
 {
 	long error = -EBADF;
 	struct file * file;
@@ -2253,30 +1826,8 @@
 	if ((vma->vm_mm->rss + (end - start)) > rlim_rss)
 		return error;
 
-	/* round to cluster boundaries if this isn't a "random" area. */
-	if (!VM_RandomReadHint(vma)) {
-		start = CLUSTER_OFFSET(start);
-		end = CLUSTER_OFFSET(end + CLUSTER_PAGES - 1);
-
-		while ((start < end) && (start < size)) {
-			error = read_cluster_nonblocking(file, start, size);
-			start += CLUSTER_PAGES;
-			if (error < 0)
-				break;
-		}
-	} else {
-		while ((start < end) && (start < size)) {
-			error = page_cache_read(file, start);
-			start++;
-			if (error < 0)
-				break;
-		}
-	}
-
-	/* Don't wait for someone else to push these requests. */
-	run_task_queue(&tq_disk);
-
-	return error;
+	do_page_cache_readahead(file, start, end - start);
+	return 0;
 }
 
 /*
@@ -2438,20 +1989,25 @@
 				int (*filler)(void *,struct page*),
 				void *data)
 {
-	struct page **hash = page_hash(mapping, index);
 	struct page *page, *cached_page = NULL;
 	int err;
 repeat:
-	page = __find_get_page(mapping, index, hash);
+	page = find_get_page(mapping, index);
 	if (!page) {
 		if (!cached_page) {
 			cached_page = page_cache_alloc(mapping);
 			if (!cached_page)
 				return ERR_PTR(-ENOMEM);
 		}
-		page = cached_page;
-		if (add_to_page_cache_unique(page, mapping, index, hash))
+		err = add_to_page_cache_unique(cached_page, mapping, index);
+		if (err == -EEXIST)
 			goto repeat;
+		if (err < 0) {
+			/* Presumably ENOMEM for radix tree node */
+			page_cache_release(cached_page);
+			return ERR_PTR(err);
+		}
+		page = cached_page;
 		cached_page = NULL;
 		err = filler(data, page);
 		if (err < 0) {
@@ -2506,35 +2062,40 @@
 static inline struct page * __grab_cache_page(struct address_space *mapping,
 				unsigned long index, struct page **cached_page)
 {
-	struct page *page, **hash = page_hash(mapping, index);
+	int err;
+	struct page *page;
 repeat:
-	page = __find_lock_page(mapping, index, hash);
+	page = find_lock_page(mapping, index);
 	if (!page) {
 		if (!*cached_page) {
 			*cached_page = page_cache_alloc(mapping);
 			if (!*cached_page)
 				return NULL;
 		}
-		page = *cached_page;
-		if (add_to_page_cache_unique(page, mapping, index, hash))
+		err = add_to_page_cache_unique(*cached_page, mapping, index);
+		if (err == -EEXIST)
 			goto repeat;
-		*cached_page = NULL;
+		if (err == 0) {
+			page = *cached_page;
+			*cached_page = NULL;
+		}
 	}
 	return page;
 }
 
-inline void remove_suid(struct inode *inode)
+inline void remove_suid(struct dentry *dentry)
 {
-	unsigned int mode;
+	struct iattr newattrs;
+	struct inode *inode = dentry->d_inode;
+	unsigned int mode = inode->i_mode & (S_ISUID|S_ISGID|S_IXGRP);
 
-	/* set S_IGID if S_IXGRP is set, and always set S_ISUID */
-	mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
+	if (!(mode & S_IXGRP))
+		mode &= S_ISUID;
 
 	/* was any of the uid bits set? */
-	mode &= inode->i_mode;
 	if (mode && !capable(CAP_FSETID)) {
-		inode->i_mode &= ~mode;
-		mark_inode_dirty(inode);
+		newattrs.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
+		notify_change(dentry, &newattrs);
 	}
 }
 
@@ -2666,7 +2227,7 @@
 	if (count == 0)
 		goto out;
 
-	remove_suid(inode);
+	remove_suid(file->f_dentry);
 	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 	mark_inode_dirty_sync(inode);
 
@@ -2790,31 +2351,4 @@
 	if (written >= 0 && file->f_flags & O_SYNC)
 		status = generic_osync_inode(inode, OSYNC_METADATA);
 	goto out_status;
-}
-
-void __init page_cache_init(unsigned long mempages)
-{
-	unsigned long htable_size, order;
-
-	htable_size = mempages;
-	htable_size *= sizeof(struct page *);
-	for(order = 0; (PAGE_SIZE << order) < htable_size; order++)
-		;
-
-	do {
-		unsigned long tmp = (PAGE_SIZE << order) / sizeof(struct page *);
-
-		page_hash_bits = 0;
-		while((tmp >>= 1UL) != 0UL)
-			page_hash_bits++;
-
-		page_hash_table = (struct page **)
-			__get_free_pages(GFP_ATOMIC, order);
-	} while(page_hash_table == NULL && --order > 0);
-
-	printk("Page-cache hash table entries: %d (order: %ld, %ld bytes)\n",
-	       (1 << page_hash_bits), order, (PAGE_SIZE << order));
-	if (!page_hash_table)
-		panic("Failed to allocate page hash table\n");
-	memset((void *)page_hash_table, 0, PAGE_HASH_SIZE * sizeof(struct page *));
 }
diff -Nru a/mm/highmem.c b/mm/highmem.c
--- a/mm/highmem.c	Sun Apr 14 12:16:55 2002
+++ b/mm/highmem.c	Sun Apr 14 12:16:55 2002
@@ -88,7 +88,7 @@
 
 		page->virtual = NULL;
 	}
-	flush_tlb_all();
+	flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP));
 }
 
 static inline unsigned long map_new_virtual(struct page *page)
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Sun Apr 14 12:16:58 2002
+++ b/mm/memory.c	Sun Apr 14 12:16:58 2002
@@ -48,6 +48,7 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
+#include <asm/tlbflush.h>
 
 unsigned long max_mapnr;
 unsigned long num_physpages;
diff -Nru a/mm/mempool.c b/mm/mempool.c
--- a/mm/mempool.c	Sun Apr 14 12:16:55 2002
+++ b/mm/mempool.c	Sun Apr 14 12:16:55 2002
@@ -34,6 +34,9 @@
 	mempool_t *pool;
 	int i;
 
+	BUG_ON(!alloc_fn);
+	BUG_ON(!free_fn);
+
 	pool = kmalloc(sizeof(*pool), GFP_KERNEL);
 	if (!pool)
 		return NULL;
diff -Nru a/mm/mincore.c b/mm/mincore.c
--- a/mm/mincore.c	Sun Apr 14 12:17:00 2002
+++ b/mm/mincore.c	Sun Apr 14 12:17:00 2002
@@ -27,9 +27,9 @@
 {
 	unsigned char present = 0;
 	struct address_space * as = vma->vm_file->f_dentry->d_inode->i_mapping;
-	struct page * page, ** hash = page_hash(as, pgoff);
+	struct page * page;
 
-	page = __find_get_page(as, pgoff, hash);
+	page = find_get_page(as, pgoff);
 	if (page) {
 		present = Page_Uptodate(page);
 		page_cache_release(page);
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Sun Apr 14 12:16:55 2002
+++ b/mm/mmap.c	Sun Apr 14 12:16:55 2002
@@ -17,6 +17,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 /*
  * WARNING: the debugging will use recursive algorithms so never enable this
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	Sun Apr 14 12:16:58 2002
+++ b/mm/mprotect.c	Sun Apr 14 12:16:58 2002
@@ -9,11 +9,13 @@
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/fs.h>
+#include <linux/highmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
-#include <linux/highmem.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 
 static inline void change_pte_range(pmd_t * pmd, unsigned long address,
 	unsigned long size, pgprot_t newprot)
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	Sun Apr 14 12:16:59 2002
+++ b/mm/mremap.c	Sun Apr 14 12:16:59 2002
@@ -11,9 +11,12 @@
 #include <linux/mman.h>
 #include <linux/swap.h>
 #include <linux/fs.h>
+#include <linux/highmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
 
 extern int vm_enough_memory(long pages);
 
diff -Nru a/mm/msync.c b/mm/msync.c
--- a/mm/msync.c	Sun Apr 14 12:16:57 2002
+++ b/mm/msync.c	Sun Apr 14 12:16:57 2002
@@ -14,6 +14,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 /*
  * Called with mm->page_table_lock held to protect against other
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	Sun Apr 14 12:16:55 2002
+++ b/mm/page_alloc.c	Sun Apr 14 12:16:55 2002
@@ -97,7 +97,7 @@
 	struct page *base;
 	zone_t *zone;
 
-	if (page->buffers)
+	if (PagePrivate(page))
 		BUG();
 	if (page->mapping)
 		BUG();
@@ -290,7 +290,7 @@
 					set_page_count(tmp, 1);
 					page = tmp;
 
-					if (page->buffers)
+					if (PagePrivate(page))
 						BUG();
 					if (page->mapping)
 						BUG();
diff -Nru a/mm/pdflush.c b/mm/pdflush.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/mm/pdflush.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,216 @@
+/*
+ * mm/pdflush.c - worker threads for writing back filesystem data
+ *
+ * Copyright (C) 2002, Linus Torvalds.
+ *
+ * 09Apr2002	akpm@zip.com.au
+ *		Initial version
+ */
+
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/signal.h>
+#include <linux/spinlock.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+
+/*
+ * Minimum and maximum number of pdflush instances
+ */
+#define MIN_PDFLUSH_THREADS	2
+#define MAX_PDFLUSH_THREADS	8
+
+static void start_one_pdflush_thread(void);
+
+
+/*
+ * The pdflush threads are worker threads for writing back dirty data.
+ * Ideally, we'd like one thread per active disk spindle.  But the disk
+ * topology is very hard to divine at this level.   Instead, we take
+ * care in various places to prevent more than one pdflush thread from
+ * performing writeback against a single filesystem.  pdflush threads
+ * have the PF_FLUSHER flag set in current->flags to aid in this.
+ */
+
+/*
+ * All the pdflush threads.  Protected by pdflush_lock
+ */
+static LIST_HEAD(pdflush_list);
+static spinlock_t pdflush_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * The count of currently-running pdflush threads.  Protected
+ * by pdflush_lock.
+ */
+static int nr_pdflush_threads = 0;
+
+/*
+ * The time at which the pdflush thread pool last went empty
+ */
+static unsigned long last_empty_jifs;
+
+/*
+ * The pdflush thread.
+ *
+ * Thread pool management algorithm:
+ * 
+ * - The minumum and maximum number of pdflush instances are bound
+ *   by MIN_PDFLUSH_THREADS and MAX_PDFLUSH_THREADS.
+ * 
+ * - If there have been no idle pdflush instances for 1 second, create
+ *   a new one.
+ * 
+ * - If the least-recently-went-to-sleep pdflush thread has been asleep
+ *   for more than one second, terminate a thread.
+ */
+
+/*
+ * A structure for passing work to a pdflush thread.  Also for passing
+ * state information between pdflush threads.  Protected by pdflush_lock.
+ */
+struct pdflush_work {
+	struct task_struct *who;	/* The thread */
+	void (*fn)(unsigned long);	/* A callback function for pdflush to work on */
+	unsigned long arg0;		/* An argument to the callback function */
+	struct list_head list;		/* On pdflush_list, when the thread is idle */
+	unsigned long when_i_went_to_sleep;
+};
+
+/*
+ * preemption is disabled in pdflush.  There was a bug in preempt
+ * which was causing pdflush to get flipped into state TASK_RUNNING
+ * when it performed a spin_unlock.  That bug is probably fixed,
+ * but play it safe.  The preempt-off paths are very short.
+ */
+static int __pdflush(struct pdflush_work *my_work)
+{
+	daemonize();
+	reparent_to_init();
+	strcpy(current->comm, "pdflush");
+
+	/* interruptible sleep, so block all signals */
+	spin_lock_irq(&current->sigmask_lock);
+	siginitsetinv(&current->blocked, 0);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sigmask_lock);
+
+	current->flags |= PF_FLUSHER;
+	my_work->fn = NULL;
+	my_work->who = current;
+
+	preempt_disable();
+	spin_lock_irq(&pdflush_lock);
+	nr_pdflush_threads++;
+	for ( ; ; ) {
+		struct pdflush_work *pdf;
+
+		list_add(&my_work->list, &pdflush_list);
+		my_work->when_i_went_to_sleep = jiffies;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irq(&pdflush_lock);
+
+		schedule();
+
+		preempt_enable();
+		(*my_work->fn)(my_work->arg0);
+		preempt_disable();
+
+		/*
+		 * Thread creation: For how long have there been zero
+		 * available threads?
+		 */
+		if (jiffies - last_empty_jifs > 1 * HZ) {
+			/* unlocked list_empty() test is OK here */
+			if (list_empty(&pdflush_list)) {
+				/* unlocked nr_pdflush_threads test is OK here */
+				if (nr_pdflush_threads < MAX_PDFLUSH_THREADS)
+					start_one_pdflush_thread();
+			}
+		}
+
+		spin_lock_irq(&pdflush_lock);
+
+		/*
+		 * Thread destruction: For how long has the sleepiest
+		 * thread slept?
+		 */
+		if (list_empty(&pdflush_list))
+			continue;
+		if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS)
+			continue;
+		pdf = list_entry(pdflush_list.prev, struct pdflush_work, list);
+		if (jiffies - pdf->when_i_went_to_sleep > 1 * HZ) {
+			pdf->when_i_went_to_sleep = jiffies;	/* Limit exit rate */
+			break;					/* exeunt */
+		}
+	}
+	nr_pdflush_threads--;
+	spin_unlock_irq(&pdflush_lock);
+	preempt_enable();
+	return 0;
+}
+
+/*
+ * Of course, my_work wants to be just a local in __pdflush().  It is
+ * separated out in this manner to hopefully prevent the compiler from
+ * performing unfortunate optimisations agains the auto variables.  Because
+ * there are visible to other tasks and CPUs.  (No problem has actually
+ * been observed.  This is just paranoia).
+ */
+static int pdflush(void *dummy)
+{
+	struct pdflush_work my_work;
+	return __pdflush(&my_work);
+}
+
+/*
+ * Attempt to wake up a pdflush thread, and get it to do some work for you.
+ * Returns zero if it indeed managed to find a worker thread, and passed your
+ * payload to it.
+ */
+int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (fn == NULL)
+		BUG();		/* Hard to diagnose if it's deferred */
+
+	spin_lock_irqsave(&pdflush_lock, flags);
+	if (list_empty(&pdflush_list)) {
+		spin_unlock_irqrestore(&pdflush_lock, flags);
+		ret = -1;
+	} else {
+		struct pdflush_work *pdf;
+
+		pdf = list_entry(pdflush_list.next, struct pdflush_work, list);
+		list_del_init(&pdf->list);
+		if (list_empty(&pdflush_list))
+			last_empty_jifs = jiffies;
+		spin_unlock_irqrestore(&pdflush_lock, flags);
+		pdf->fn = fn;
+		pdf->arg0 = arg0;
+		wmb();			/* ? */
+		wake_up_process(pdf->who);
+	}
+	return ret;
+}
+
+static void start_one_pdflush_thread(void)
+{
+	kernel_thread(pdflush, NULL,
+			CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
+}
+
+static int __init pdflush_init(void)
+{
+	int i;
+
+	for (i = 0; i < MIN_PDFLUSH_THREADS; i++)
+		start_one_pdflush_thread();
+	return 0;
+}
+
+module_init(pdflush_init);
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/mm/readahead.c	Sun Apr 14 12:17:00 2002
@@ -0,0 +1,345 @@
+/*
+ * mm/readahead.c - address_space-level file readahead.
+ *
+ * Copyright (C) 2002, Linus Torvalds
+ *
+ * 09Apr2002	akpm@zip.com.au
+ *		Initial version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+
+/*
+ * The readahead logic manages two readahead windows.  The "current"
+ * and the "ahead" windows.
+ *
+ * VM_MAX_READAHEAD specifies, in kilobytes, the maximum size of
+ * each of the two windows.  So the amount of readahead which is
+ * in front of the file pointer varies between VM_MAX_READAHEAD and
+ * VM_MAX_READAHEAD * 2.
+ *
+ * VM_MAX_READAHEAD only applies if the underlying request queue
+ * has a zero value of ra_sectors.
+ */
+
+#define VM_MAX_READAHEAD	128	/* kbytes */
+#define VM_MIN_READAHEAD	16	/* kbytes (includes current page) */
+
+/*
+ * Return max readahead size for this inode in number-of-pages.
+ */
+static int get_max_readahead(struct inode *inode)
+{
+	unsigned blk_ra_kbytes = 0;
+
+	blk_ra_kbytes = blk_get_readahead(inode->i_dev) / 2;
+	if (blk_ra_kbytes < VM_MIN_READAHEAD)
+		blk_ra_kbytes = VM_MAX_READAHEAD;
+
+	return blk_ra_kbytes >> (PAGE_CACHE_SHIFT - 10);
+}
+
+static int get_min_readahead(struct inode *inode)
+{
+	int ret = VM_MIN_READAHEAD / PAGE_CACHE_SIZE;
+
+	if (ret < 2)
+		ret = 2;
+	return ret;
+}
+
+/*
+ * Readahead design.
+ *
+ * The fields in struct file_ra_state represent the most-recently-executed
+ * readahead attempt:
+ *
+ * start:	Page index at which we started the readahead
+ * size:	Number of pages in that read
+ *              Together, these form the "current window".
+ *              Together, start and size represent the `readahead window'.
+ * next_size:   The number of pages to read when we get the next readahead miss.
+ * prev_page:   The page which the readahead algorithm most-recently inspected.
+ *              prev_page is mainly an optimisation: if page_cache_readahead sees
+ *              that it is again being called for a page which it just looked at,
+ *              it can return immediately without making any state changes.
+ * ahead_start,
+ * ahead_size:  Together, these form the "ahead window".
+ *
+ * The readahead code manages two windows - the "current" and the "ahead"
+ * windows.  The intent is that while the application is walking the pages
+ * in the current window, I/O is underway on the ahead window.  When the
+ * current window is fully traversed, it is replaced by the ahead window
+ * and the ahead window is invalidated.  When this copying happens, the
+ * new current window's pages are probably still locked.  When I/O has
+ * completed, we submit a new batch of I/O, creating a new ahead window.
+ *
+ * So:
+ *
+ *   ----|----------------|----------------|-----
+ *       ^start           ^start+size
+ *                        ^ahead_start     ^ahead_start+ahead_size
+ *
+ *         ^ When this page is read, we submit I/O for the
+ *           ahead window.
+ *
+ * A `readahead hit' occurs when a read request is made against a page which is
+ * inside the current window.  Hits are good, and the window size (next_size) is
+ * grown aggressively when hits occur.  Two pages are added to the next window
+ * size on each hit, which will end up doubling the next window size by the time
+ * I/O is submitted for it.
+ *
+ * If readahead hits are more sparse (say, the application is only reading every
+ * second page) then the window will build more slowly.
+ *
+ * On a readahead miss (the application seeked away) the readahead window is shrunk
+ * by 25%.  We don't want to drop it too aggressively, because it's a good assumption
+ * that an application which has built a good readahead window will continue to
+ * perform linear reads.  Either at the new file position, or at the old one after
+ * another seek.
+ *
+ * There is a special-case: if the first page which the application tries to read
+ * happens to be the first page of the file, it is assumed that a linear read is
+ * about to happen and the window is immediately set to half of the device maximum.
+ * 
+ * A page request at (start + size) is not a miss at all - it's just a part of
+ * sequential file reading.
+ *
+ * This function is to be called for every page which is read, rather than when
+ * it is time to perform readahead.  This is so the readahead algorithm can centrally
+ * work out the access patterns.  This could be costly with many tiny read()s, so
+ * we specifically optimise for that case with prev_page.
+ */
+
+/*
+ * do_page_cache_readahead actually reads a chunk of disk.  It allocates all the
+ * pages first, then submits them all for I/O. This avoids the very bad behaviour
+ * which would occur if page allocations are causing VM writeback.  We really don't
+ * want to intermingle reads and writes like that.
+ */
+void do_page_cache_readahead(struct file *file,
+			unsigned long offset, unsigned long nr_to_read)
+{
+	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
+	struct inode *inode = mapping->host;
+	struct page *page;
+	unsigned long end_index;	/* The last page we want to read */
+	LIST_HEAD(page_pool);
+	int page_idx;
+	int nr_to_really_read = 0;
+
+	if (inode->i_size == 0)
+		return;
+
+ 	end_index = ((inode->i_size - 1) >> PAGE_CACHE_SHIFT);
+
+	/*
+	 * Preallocate as many pages as we will need.
+	 */
+	for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
+		unsigned long page_offset = offset + page_idx;
+		
+		if (page_offset > end_index)
+			break;
+
+		read_lock(&mapping->page_lock);
+		page = radix_tree_lookup(&mapping->page_tree, page_offset);
+		read_unlock(&mapping->page_lock);
+		if (page)
+			continue;
+
+		page = page_cache_alloc(mapping);
+		if (!page)
+			break;
+		page->index = page_offset;
+		list_add(&page->list, &page_pool);
+		nr_to_really_read++;
+	}
+
+	/*
+	 * Now start the IO.  We ignore I/O errors - if the page is not
+	 * uptodate then the caller will launch readpage again, and
+	 * will then handle the error.
+	 */
+	for (page_idx = 0; page_idx < nr_to_really_read; page_idx++) {
+		if (list_empty(&page_pool))
+			BUG();
+		page = list_entry(page_pool.prev, struct page, list);
+		list_del(&page->list);
+		if (!add_to_page_cache_unique(page, mapping, page->index))
+			mapping->a_ops->readpage(file, page);
+		page_cache_release(page);
+	}
+
+	/*
+	 * Do this now, rather than at the next wait_on_page().
+	 */
+	run_task_queue(&tq_disk);
+
+	if (!list_empty(&page_pool))
+		BUG();
+
+	return;
+}
+
+/*
+ * page_cache_readahead is the main function.  If performs the adaptive
+ * readahead window size management and submits the readahead I/O.
+ */
+void page_cache_readahead(struct file *file, unsigned long offset)
+{
+	struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+	struct file_ra_state *ra = &file->f_ra;
+	unsigned long max;
+	unsigned long min;
+
+	/*
+	 * Here we detect the case where the application is performing
+	 * sub-page sized reads.  We avoid doing extra work and bogusly
+	 * perturbing the readahead window expansion logic.
+	 * If next_size is zero, this is the very first read for this
+	 * file handle.
+	 */
+	if (offset == ra->prev_page) {
+		if (ra->next_size != 0)
+			goto out;
+	}
+
+	min = get_min_readahead(inode);
+	max = get_max_readahead(inode);
+
+	if (ra->next_size == 0 && offset == 0) {
+		/*
+		 * Special case - first read from first page.
+		 * We'll assume it's a whole-file read, and
+		 * grow the window fast.
+		 */
+		ra->next_size = max / 2;
+		goto do_io;
+	}
+
+	ra->prev_page = offset;
+
+	if (offset >= ra->start && offset <= (ra->start + ra->size)) {
+		/*
+		 * A readahead hit.  Either inside the window, or one
+		 * page beyond the end.  Expand the next readahead size.
+		 */
+		ra->next_size += 2;
+	} else {
+		/*
+		 * A miss - lseek, pread, etc.  Shrink the readahead window by 25%.
+		 */
+		ra->next_size -= ra->next_size / 4;
+		if (ra->next_size < min)
+			ra->next_size = min;
+	}
+
+	if (ra->next_size > max)
+		ra->next_size = max;
+	if (ra->next_size < min)
+		ra->next_size = min;
+
+	/*
+	 * Is this request outside the current window?
+	 */
+	if (offset < ra->start || offset >= (ra->start + ra->size)) {
+		/*
+		 * A miss against the current window.  Have we merely
+		 * advanced into the ahead window?
+		 */
+		if (offset == ra->ahead_start) {
+			/*
+			 * Yes, we have.  The ahead window now becomes
+			 * the current window.
+			 */
+			ra->start = ra->ahead_start;
+			ra->size = ra->ahead_size;
+			ra->prev_page = ra->start;
+			ra->ahead_start = 0;
+			ra->ahead_size = 0;
+			/*
+			 * Control now returns, probably to sleep until I/O
+			 * completes against the first ahead page.
+			 * When the second page in the old ahead window is
+			 * requested, control will return here and more I/O
+			 * will be submitted to build the new ahead window.
+			 */
+			goto out;
+		}
+do_io:
+		/*
+		 * This is the "unusual" path.  We come here during
+		 * startup or after an lseek.  We invalidate the
+		 * ahead window and get some I/O underway for the new
+		 * current window.
+		 */
+		ra->start = offset;
+		ra->size = ra->next_size;
+		ra->ahead_start = 0;		/* Invalidate these */
+		ra->ahead_size = 0;
+
+		do_page_cache_readahead(file, offset, ra->size);
+	} else {
+		/*
+		 * This read request is within the current window.  It
+		 * is time to submit I/O for the ahead window while
+		 * the application is crunching through the current
+		 * window.
+		 */
+		if (ra->ahead_start == 0) {
+			ra->ahead_start = ra->start + ra->size;
+			ra->ahead_size = ra->next_size;
+			do_page_cache_readahead(file,
+					ra->ahead_start, ra->ahead_size);
+		}
+	}
+out:
+	return;
+}
+
+/*
+ * For mmap reads (typically executables) the access pattern is fairly random,
+ * but somewhat ascending.  So readaround favours pages beyond the target one.
+ * We also boost the window size, as it can easily shrink due to misses.
+ */
+void page_cache_readaround(struct file *file, unsigned long offset)
+{
+	unsigned long target;
+	unsigned long backward;
+	const int min = get_min_readahead(file->f_dentry->d_inode->i_mapping->host) * 2;
+
+	if (file->f_ra.next_size < min)
+		file->f_ra.next_size = min;
+
+	target = offset;
+	backward = file->f_ra.next_size / 4;
+
+	if (backward > target)
+		target = 0;
+	else
+		target -= backward;
+	page_cache_readahead(file, target);
+}
+
+/*
+ * handle_ra_thrashing() is called when it is known that a page which should
+ * have been present (it's inside the readahead window) was in fact evicted by
+ * the VM.
+ *
+ * We shrink the readahead window by three pages.  This is because we grow it
+ * by two pages on a readahead hit.  Theory being that the readahead window size
+ * will stabilise around the maximum level at which there isn't any thrashing.
+ */
+void handle_ra_thrashing(struct file *file)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	const unsigned long min = get_min_readahead(inode);
+
+	file->f_ra.next_size -= 3;
+	if (file->f_ra.next_size < min)
+		file->f_ra.next_size = min;
+}
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Sun Apr 14 12:16:58 2002
+++ b/mm/shmem.c	Sun Apr 14 12:16:58 2002
@@ -370,9 +370,10 @@
 	swp_entry_t *ptr;
 	unsigned long idx;
 	int offset;
-	
-	idx = 0;
+
 	spin_lock (&info->lock);
+repeat:
+	idx = 0;
 	offset = shmem_clear_swp (entry, info->i_direct, SHMEM_NR_DIRECT);
 	if (offset >= 0)
 		goto found;
@@ -389,13 +390,16 @@
 	spin_unlock (&info->lock);
 	return 0;
 found:
-	delete_from_swap_cache(page);
-	add_to_page_cache(page, info->vfs_inode.i_mapping, offset + idx);
-	SetPageDirty(page);
-	SetPageUptodate(page);
-	info->swapped--;
-	spin_unlock(&info->lock);
-	return 1;
+	if (!move_from_swap_cache (page, offset+idx, info->vfs_inode.i_mapping)) {
+		info->swapped--;
+		SetPageUptodate (page);
+		spin_unlock (&info->lock);
+		return 1;
+	}
+
+	/* Yield for kswapd, and try again */
+	yield();
+	goto repeat;
 }
 
 /*
@@ -425,6 +429,7 @@
  */
 static int shmem_writepage(struct page * page)
 {
+	int err;
 	struct shmem_inode_info *info;
 	swp_entry_t *entry, swap;
 	struct address_space *mapping;
@@ -442,7 +447,6 @@
 	info = SHMEM_I(inode);
 	if (info->locked)
 		return fail_writepage(page);
-getswap:
 	swap = get_swap_page();
 	if (!swap.val)
 		return fail_writepage(page);
@@ -455,29 +459,20 @@
 	if (entry->val)
 		BUG();
 
-	/* Remove it from the page cache */
-	remove_inode_page(page);
-	page_cache_release(page);
-
-	/* Add it to the swap cache */
-	if (add_to_swap_cache(page, swap) != 0) {
-		/*
-		 * Raced with "speculative" read_swap_cache_async.
-		 * Add page back to page cache, unref swap, try again.
-		 */
-		add_to_page_cache_locked(page, mapping, index);
+	err = move_to_swap_cache(page, swap);
+	if (!err) {
+		*entry = swap;
+		info->swapped++;
 		spin_unlock(&info->lock);
-		swap_free(swap);
-		goto getswap;
+		SetPageUptodate(page);
+		set_page_dirty(page);
+		UnlockPage(page);
+		return 0;
 	}
 
-	*entry = swap;
-	info->swapped++;
 	spin_unlock(&info->lock);
-	SetPageUptodate(page);
-	set_page_dirty(page);
-	UnlockPage(page);
-	return 0;
+	swap_free(swap);
+	return fail_writepage(page);
 }
 
 /*
@@ -493,10 +488,11 @@
  */
 static struct page * shmem_getpage_locked(struct shmem_inode_info *info, struct inode * inode, unsigned long idx)
 {
-	struct address_space * mapping = inode->i_mapping;
+	struct address_space *mapping = inode->i_mapping;
 	struct shmem_sb_info *sbinfo;
-	struct page * page;
+	struct page *page;
 	swp_entry_t *entry;
+	int error;
 
 repeat:
 	page = find_lock_page(mapping, idx);
@@ -524,8 +520,6 @@
 	
 	shmem_recalc_inode(inode);
 	if (entry->val) {
-		unsigned long flags;
-
 		/* Look it up and read it in.. */
 		page = find_get_page(&swapper_space, entry->val);
 		if (!page) {
@@ -550,16 +544,18 @@
 			goto repeat;
 		}
 
-		/* We have to this with page locked to prevent races */
+		/* We have to do this with page locked to prevent races */
 		if (TryLockPage(page)) 
 			goto wait_retry;
 
+		error = move_from_swap_cache(page, idx, mapping);
+		if (error < 0) {
+			UnlockPage(page);
+			return ERR_PTR(error);
+		}
+
 		swap_free(*entry);
 		*entry = (swp_entry_t) {0};
-		delete_from_swap_cache(page);
-		flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced) | (1 << PG_arch_1));
-		page->flags = flags | (1 << PG_dirty);
-		add_to_page_cache_locked(page, mapping, idx);
 		info->swapped--;
 		spin_unlock (&info->lock);
 	} else {
@@ -581,9 +577,13 @@
 		page = page_cache_alloc(mapping);
 		if (!page)
 			return ERR_PTR(-ENOMEM);
+		error = add_to_page_cache(page, mapping, idx);
+		if (error < 0) {
+			page_cache_release(page);
+			return ERR_PTR(-ENOMEM);
+		}
 		clear_highpage(page);
 		inode->i_blocks += BLOCKS_PER_PAGE;
-		add_to_page_cache (page, mapping, idx);
 	}
 
 	/* We have the page */
@@ -802,7 +802,7 @@
 
 	status	= 0;
 	if (count) {
-		remove_suid(inode);
+		remove_suid(file->f_dentry);
 		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 	}
 
@@ -1203,10 +1203,9 @@
 {
 	char *this_char, *value, *rest;
 
-	this_char = NULL;
-	if ( options )
-		this_char = strtok(options,",");
-	for ( ; this_char; this_char = strtok(NULL,",")) {
+	while ((this_char = strsep(&options, ",")) != NULL) {
+		if (!*this_char)
+			continue;
 		if ((value = strchr(this_char,'=')) != NULL) {
 			*value++ = 0;
 		} else {
diff -Nru a/mm/swap_state.c b/mm/swap_state.c
--- a/mm/swap_state.c	Sun Apr 14 12:16:58 2002
+++ b/mm/swap_state.c	Sun Apr 14 12:16:58 2002
@@ -37,11 +37,13 @@
 };
 
 struct address_space swapper_space = {
-	LIST_HEAD_INIT(swapper_space.clean_pages),
-	LIST_HEAD_INIT(swapper_space.dirty_pages),
-	LIST_HEAD_INIT(swapper_space.locked_pages),
-	0,				/* nrpages	*/
-	&swap_aops,
+	page_tree:	RADIX_TREE_INIT(GFP_ATOMIC),
+	page_lock:	RW_LOCK_UNLOCKED,
+	clean_pages:	LIST_HEAD_INIT(swapper_space.clean_pages),
+	dirty_pages:	LIST_HEAD_INIT(swapper_space.dirty_pages),
+	locked_pages:	LIST_HEAD_INIT(swapper_space.locked_pages),
+	a_ops:		&swap_aops,
+	i_shared_lock:	SPIN_LOCK_UNLOCKED,
 };
 
 #ifdef SWAP_CACHE_INFO
@@ -69,17 +71,21 @@
 
 int add_to_swap_cache(struct page *page, swp_entry_t entry)
 {
+	int error;
+
 	if (page->mapping)
 		BUG();
 	if (!swap_duplicate(entry)) {
 		INC_CACHE_INFO(noent_race);
 		return -ENOENT;
 	}
-	if (add_to_page_cache_unique(page, &swapper_space, entry.val,
-			page_hash(&swapper_space, entry.val)) != 0) {
+
+	error = add_to_page_cache_unique(page, &swapper_space, entry.val);
+	if (error != 0) {
 		swap_free(entry);
-		INC_CACHE_INFO(exist_race);
-		return -EEXIST;
+		if (error == -EEXIST)
+			INC_CACHE_INFO(exist_race);
+		return error;
 	}
 	if (!PageLocked(page))
 		BUG();
@@ -121,14 +127,96 @@
 
 	entry.val = page->index;
 
-	spin_lock(&pagecache_lock);
+	write_lock(&swapper_space.page_lock);
 	__delete_from_swap_cache(page);
-	spin_unlock(&pagecache_lock);
+	write_unlock(&swapper_space.page_lock);
 
 	swap_free(entry);
 	page_cache_release(page);
 }
 
+int move_to_swap_cache(struct page *page, swp_entry_t entry)
+{
+	struct address_space *mapping = page->mapping;
+	void **pslot;
+	int err;
+
+	if (!mapping)
+		BUG();
+
+	if (!swap_duplicate(entry)) {
+		INC_CACHE_INFO(noent_race);
+		return -ENOENT;
+	}
+
+	write_lock(&swapper_space.page_lock);
+	write_lock(&mapping->page_lock);
+
+	err = radix_tree_reserve(&swapper_space.page_tree, entry.val, &pslot);
+	if (!err) {
+		/* Remove it from the page cache */
+		__remove_inode_page (page);
+
+		/* Add it to the swap cache */
+		*pslot = page;
+		page->flags = ((page->flags & ~(1 << PG_uptodate | 1 << PG_error
+						| 1 << PG_dirty  | 1 << PG_referenced
+						| 1 << PG_arch_1 | 1 << PG_checked))
+			       | (1 << PG_locked));
+		___add_to_page_cache(page, &swapper_space, entry.val);
+	}
+
+	write_unlock(&mapping->page_lock);
+	write_unlock(&swapper_space.page_lock);
+
+	if (!err) {
+		INC_CACHE_INFO(add_total);
+		return 0;
+	}
+
+	swap_free(entry);
+
+	if (err == -EEXIST)
+		INC_CACHE_INFO(exist_race);
+
+	return err;
+}
+
+int move_from_swap_cache(struct page *page, unsigned long index,
+		struct address_space *mapping)
+{
+	void **pslot;
+	int err;
+
+	if (!PageLocked(page))
+		BUG();
+
+	write_lock(&swapper_space.page_lock);
+	write_lock(&mapping->page_lock);
+
+	err = radix_tree_reserve(&mapping->page_tree, index, &pslot);
+	if (!err) {
+		swp_entry_t entry;
+
+		block_flushpage(page, 0);
+		entry.val = page->index;
+		__delete_from_swap_cache(page);
+		swap_free(entry);
+
+		*pslot = page;
+		page->flags &= ~(1 << PG_uptodate | 1 << PG_error |
+				 1 << PG_referenced | 1 << PG_arch_1 |
+				 1 << PG_checked);
+		page->flags |= (1 << PG_dirty);
+		___add_to_page_cache(page, mapping, index);
+	}
+
+	write_unlock(&mapping->page_lock);
+	write_unlock(&swapper_space.page_lock);
+
+	return err;
+}
+
 /* 
  * Perform a free_page(), also freeing any swap cache associated with
  * this page if it is the last user of the page. Can not do a lock_page,
@@ -213,6 +301,7 @@
 		 * swap cache: added by a racing read_swap_cache_async,
 		 * or by try_to_swap_out (or shmem_writepage) re-using
 		 * the just freed swap entry for an existing page.
+		 * May fail (-ENOMEM) if radix-tree node allocation failed.
 		 */
 		err = add_to_swap_cache(new_page, entry);
 		if (!err) {
@@ -222,7 +311,7 @@
 			rw_swap_page(READ, new_page);
 			return new_page;
 		}
-	} while (err != -ENOENT);
+	} while (err != -ENOENT && err != -ENOMEM);
 
 	if (new_page)
 		page_cache_release(new_page);
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Sun Apr 14 12:16:56 2002
+++ b/mm/swapfile.c	Sun Apr 14 12:16:56 2002
@@ -239,10 +239,10 @@
 		/* Is the only swap cache user the cache itself? */
 		if (p->swap_map[SWP_OFFSET(entry)] == 1) {
 			/* Recheck the page count with the pagecache lock held.. */
-			spin_lock(&pagecache_lock);
-			if (page_count(page) - !!page->buffers == 2)
+			read_lock(&swapper_space.page_lock);
+			if (page_count(page) - !!PagePrivate(page) == 2)
 				retval = 1;
-			spin_unlock(&pagecache_lock);
+			read_unlock(&swapper_space.page_lock);
 		}
 		swap_info_put(p);
 	}
@@ -265,7 +265,7 @@
 		BUG();
 	switch (page_count(page)) {
 	case 3:
-		if (!page->buffers)
+		if (!PagePrivate(page))
 			break;
 		/* Fallthrough */
 	case 2:
@@ -295,7 +295,7 @@
 		BUG();
 	if (!PageSwapCache(page))
 		return 0;
-	if (page_count(page) - !!page->buffers != 2)	/* 2: us + cache */
+	if (page_count(page) - !!PagePrivate(page) != 2) /* 2: us + cache */
 		return 0;
 
 	entry.val = page->index;
@@ -307,13 +307,13 @@
 	retval = 0;
 	if (p->swap_map[SWP_OFFSET(entry)] == 1) {
 		/* Recheck the page count with the pagecache lock held.. */
-		spin_lock(&pagecache_lock);
-		if (page_count(page) - !!page->buffers == 2) {
+		read_lock(&swapper_space.page_lock);
+		if (page_count(page) - !!PagePrivate(page) == 2) {
 			__delete_from_swap_cache(page);
 			SetPageDirty(page);
 			retval = 1;
 		}
-		spin_unlock(&pagecache_lock);
+		read_unlock(&swapper_space.page_lock);
 	}
 	swap_info_put(p);
 
@@ -344,7 +344,7 @@
 	if (page) {
 		page_cache_get(page);
 		/* Only cache user (+us), or swap space full? Free it! */
-		if (page_count(page) - !!page->buffers == 2 || vm_swap_full()) {
+		if (page_count(page) - !!PagePrivate(page) == 2 || vm_swap_full()) {
 			delete_from_swap_cache(page);
 			SetPageDirty(page);
 		}
@@ -959,7 +959,7 @@
 		p->lowest_bit = 0;
 		p->highest_bit = 0;
 		for (i = 1 ; i < 8*PAGE_SIZE ; i++) {
-			if (test_bit(i,(char *) swap_header)) {
+			if (test_bit(i,(unsigned long *) swap_header)) {
 				if (!p->lowest_bit)
 					p->lowest_bit = i;
 				p->highest_bit = i;
@@ -974,7 +974,7 @@
 			goto bad_swap;
 		}
 		for (i = 1 ; i < maxpages ; i++) {
-			if (test_bit(i,(char *) swap_header))
+			if (test_bit(i,(unsigned long *) swap_header))
 				p->swap_map[i] = 0;
 			else
 				p->swap_map[i] = SWAP_MAP_BAD;
diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c
--- a/mm/vmalloc.c	Sun Apr 14 12:16:54 2002
+++ b/mm/vmalloc.c	Sun Apr 14 12:16:54 2002
@@ -15,6 +15,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 rwlock_t vmlist_lock = RW_LOCK_UNLOCKED;
 struct vm_struct * vmlist;
@@ -80,6 +81,7 @@
 void vmfree_area_pages(unsigned long address, unsigned long size)
 {
 	pgd_t * dir;
+	unsigned long start = address;
 	unsigned long end = address + size;
 
 	dir = pgd_offset_k(address);
@@ -89,7 +91,7 @@
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	} while (address && (address < end));
-	flush_tlb_all();
+	flush_tlb_kernel_range(start, end);
 }
 
 static inline int alloc_area_pte (pte_t * pte, unsigned long address,
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Sun Apr 14 12:16:55 2002
+++ b/mm/vmscan.c	Sun Apr 14 12:16:56 2002
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 
 #include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
 
 /*
  * The "priority" of VM scanning is how much of the queues we
@@ -91,7 +92,8 @@
 		mm->rss--;
 		UnlockPage(page);
 		{
-			int freeable = page_count(page) - !!page->buffers <= 2;
+			int freeable = page_count(page) -
+				!!PagePrivate(page) <= 2;
 			page_cache_release(page);
 			return freeable;
 		}
@@ -120,7 +122,7 @@
 	 * Anonymous buffercache pages can be left behind by
 	 * concurrent truncate and pagefault.
 	 */
-	if (page->buffers)
+	if (PagePrivate(page))
 		goto preserve;
 
 	/*
@@ -137,10 +139,16 @@
 		 * (adding to the page cache will clear the dirty
 		 * and uptodate bits, so we need to do it again)
 		 */
-		if (add_to_swap_cache(page, entry) == 0) {
+		switch (add_to_swap_cache(page, entry)) {
+		case 0:				/* Success */
 			SetPageUptodate(page);
 			set_page_dirty(page);
 			goto set_swap_pte;
+		case -ENOMEM:			/* radix-tree allocation */
+			swap_free(entry);
+			goto preserve;
+		default:			/* ENOENT: raced */
+			break;
 		}
 		/* Raced with "speculative" read_swap_cache_async */
 		swap_free(entry);
@@ -340,6 +348,7 @@
 static int shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int priority)
 {
 	struct list_head * entry;
+	struct address_space *mapping;
 	int max_scan = nr_inactive_pages / priority;
 	int max_mapped = nr_pages << (9 - priority);
 
@@ -376,7 +385,7 @@
 			continue;
 
 		/* Racy check to avoid trylocking when not worthwhile */
-		if (!page->buffers && (page_count(page) != 1 || !page->mapping))
+		if (!PagePrivate(page) && (page_count(page) != 1 || !page->mapping))
 			goto page_mapped;
 
 		/*
@@ -394,7 +403,9 @@
 			continue;
 		}
 
-		if (PageDirty(page) && is_page_cache_freeable(page) && page->mapping) {
+		mapping = page->mapping;
+
+		if (PageDirty(page) && is_page_cache_freeable(page) && mapping) {
 			/*
 			 * It is not critical here to write it only if
 			 * the page is unmapped beause any direct writer
@@ -405,7 +416,7 @@
 			 */
 			int (*writepage)(struct page *);
 
-			writepage = page->mapping->a_ops->writepage;
+			writepage = mapping->a_ops->writepage;
 			if ((gfp_mask & __GFP_FS) && writepage) {
 				ClearPageDirty(page);
 				SetPageLaunder(page);
@@ -425,14 +436,14 @@
 		 * associated with this page. If we succeed we try to free
 		 * the page as well.
 		 */
-		if (page->buffers) {
+		if (PagePrivate(page)) {
 			spin_unlock(&pagemap_lru_lock);
 
 			/* avoid to free a locked page */
 			page_cache_get(page);
 
 			if (try_to_release_page(page, gfp_mask)) {
-				if (!page->mapping) {
+				if (!mapping) {
 					/*
 					 * We must not allow an anon page
 					 * with no buffers to be visible on
@@ -469,33 +480,35 @@
 			}
 		}
 
-		spin_lock(&pagecache_lock);
-
 		/*
-		 * this is the non-racy check for busy page.
+		 * This is the non-racy check for busy page.
 		 */
-		if (!page->mapping || !is_page_cache_freeable(page)) {
-			spin_unlock(&pagecache_lock);
-			UnlockPage(page);
+		if (mapping) {
+			write_lock(&mapping->page_lock);
+			if (is_page_cache_freeable(page))
+				goto page_freeable;
+			write_unlock(&mapping->page_lock);
+		}
+		UnlockPage(page);
 page_mapped:
-			if (--max_mapped >= 0)
-				continue;
+		if (--max_mapped >= 0)
+			continue;
 
-			/*
-			 * Alert! We've found too many mapped pages on the
-			 * inactive list, so we start swapping out now!
-			 */
-			spin_unlock(&pagemap_lru_lock);
-			swap_out(priority, gfp_mask, classzone);
-			return nr_pages;
-		}
+		/*
+		 * Alert! We've found too many mapped pages on the
+		 * inactive list, so we start swapping out now!
+		 */
+		spin_unlock(&pagemap_lru_lock);
+		swap_out(priority, gfp_mask, classzone);
+		return nr_pages;
 
+page_freeable:
 		/*
 		 * It is critical to check PageDirty _after_ we made sure
 		 * the page is freeable* so not in use by anybody.
 		 */
 		if (PageDirty(page)) {
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			UnlockPage(page);
 			continue;
 		}
@@ -503,12 +516,12 @@
 		/* point of no return */
 		if (likely(!PageSwapCache(page))) {
 			__remove_inode_page(page);
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 		} else {
 			swp_entry_t swap;
 			swap.val = page->index;
 			__delete_from_swap_cache(page);
-			spin_unlock(&pagecache_lock);
+			write_unlock(&mapping->page_lock);
 			swap_free(swap);
 		}
 
diff -Nru a/net/atm/pppoatm.c b/net/atm/pppoatm.c
--- a/net/atm/pppoatm.c	Sun Apr 14 12:16:55 2002
+++ b/net/atm/pppoatm.c	Sun Apr 14 12:16:55 2002
@@ -363,3 +363,4 @@
 
 MODULE_AUTHOR("Mitchell Blank Jr <mitch@sfgoth.com>");
 MODULE_DESCRIPTION("RFC2364 PPP over ATM/AAL5");
+MODULE_LICENSE("GPL");
diff -Nru a/net/atm/resources.c b/net/atm/resources.c
--- a/net/atm/resources.c	Sun Apr 14 12:16:59 2002
+++ b/net/atm/resources.c	Sun Apr 14 12:16:59 2002
@@ -31,95 +31,107 @@
 struct atm_vcc *nodev_vccs = NULL;
 extern spinlock_t atm_dev_lock;
 
-
-static struct atm_dev *alloc_atm_dev(const char *type)
+/* Caller must hold atm_dev_lock. */
+static struct atm_dev *__alloc_atm_dev(const char *type)
 {
 	struct atm_dev *dev;
 
-	dev = kmalloc(sizeof(*dev),GFP_KERNEL);
-	if (!dev) return NULL;
-	memset(dev,0,sizeof(*dev));
+	dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
 	dev->type = type;
 	dev->signal = ATM_PHY_SIG_UNKNOWN;
 	dev->link_rate = ATM_OC3_PCR;
 	dev->next = NULL;
 
-	spin_lock(&atm_dev_lock);
-
 	dev->prev = last_dev;
 
-	if (atm_devs) last_dev->next = dev;
-	else atm_devs = dev;
+	if (atm_devs)
+		last_dev->next = dev;
+	else
+		atm_devs = dev;
 	last_dev = dev;
-	spin_unlock(&atm_dev_lock);
+
 	return dev;
 }
 
-
-static void free_atm_dev(struct atm_dev *dev)
+/* Caller must hold atm_dev_lock. */
+static void __free_atm_dev(struct atm_dev *dev)
 {
-	spin_lock (&atm_dev_lock);
-	
-	if (dev->prev) dev->prev->next = dev->next;
-	else atm_devs = dev->next;
-	if (dev->next) dev->next->prev = dev->prev;
-	else last_dev = dev->prev;
+	if (dev->prev)
+		dev->prev->next = dev->next;
+	else
+		atm_devs = dev->next;
+	if (dev->next)
+		dev->next->prev = dev->prev;
+	else
+		last_dev = dev->prev;
 	kfree(dev);
-	
-	spin_unlock (&atm_dev_lock);
 }
 
-
+/* Caller must hold atm_dev_lock. */
 struct atm_dev *atm_find_dev(int number)
 {
 	struct atm_dev *dev;
 
 	for (dev = atm_devs; dev; dev = dev->next)
-		if (dev->ops && dev->number == number) return dev;
+		if (dev->ops && dev->number == number)
+			return dev;
 	return NULL;
 }
 
 
-struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
-    int number,atm_dev_flags_t *flags)
+struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
+				 int number, atm_dev_flags_t *flags)
 {
 	struct atm_dev *dev;
 
-	dev = alloc_atm_dev(type);
+	spin_lock(&atm_dev_lock);
+
+	dev = __alloc_atm_dev(type);
 	if (!dev) {
 		printk(KERN_ERR "atm_dev_register: no space for dev %s\n",
 		    type);
-		return NULL;
+		goto done;
 	}
 	if (number != -1) {
 		if (atm_find_dev(number)) {
-			free_atm_dev(dev);
-			return NULL;
+			__free_atm_dev(dev);
+			dev = NULL;
+			goto done;
 		}
 		dev->number = number;
-	}
-	else {
+	} else {
 		dev->number = 0;
-		while (atm_find_dev(dev->number)) dev->number++;
+		while (atm_find_dev(dev->number))
+			dev->number++;
 	}
 	dev->vccs = dev->last = NULL;
 	dev->dev_data = NULL;
 	barrier();
 	dev->ops = ops;
-	if (flags) dev->flags = *flags;
-	else memset(&dev->flags,0,sizeof(dev->flags));
-	memset((void *) &dev->stats,0,sizeof(dev->stats));
+	if (flags)
+		dev->flags = *flags;
+	else
+		memset(&dev->flags, 0, sizeof(dev->flags));
+	memset(&dev->stats, 0, sizeof(dev->stats));
+
 #ifdef CONFIG_PROC_FS
-	if (ops->proc_read)
+	if (ops->proc_read) {
 		if (atm_proc_dev_register(dev) < 0) {
 			printk(KERN_ERR "atm_dev_register: "
-			    "atm_proc_dev_register failed for dev %s\n",type);
-			spin_unlock (&atm_dev_lock);		
-			free_atm_dev(dev);
-			return NULL;
+			       "atm_proc_dev_register failed for dev %s\n",
+			       type);
+			__free_atm_dev(dev);
+			dev = NULL;
+			goto done;
 		}
+	}
 #endif
-	spin_unlock (&atm_dev_lock);		
+
+done:
+	spin_unlock(&atm_dev_lock);
 	return dev;
 }
 
@@ -127,19 +139,22 @@
 void atm_dev_deregister(struct atm_dev *dev)
 {
 #ifdef CONFIG_PROC_FS
-	if (dev->ops->proc_read) atm_proc_dev_deregister(dev);
+	if (dev->ops->proc_read)
+		atm_proc_dev_deregister(dev);
 #endif
-	free_atm_dev(dev);
+	spin_lock(&atm_dev_lock);
+	__free_atm_dev(dev);
+	spin_unlock(&atm_dev_lock);
 }
 
-
 void shutdown_atm_dev(struct atm_dev *dev)
 {
 	if (dev->vccs) {
-		set_bit(ATM_DF_CLOSE,&dev->flags);
+		set_bit(ATM_DF_CLOSE, &dev->flags);
 		return;
 	}
-	if (dev->ops->dev_close) dev->ops->dev_close(dev);
+	if (dev->ops->dev_close)
+		dev->ops->dev_close(dev);
 	atm_dev_deregister(dev);
 }
 
@@ -149,16 +164,18 @@
 	struct atm_vcc *vcc;
 
 	sk = sk_alloc(family, GFP_KERNEL, 1, NULL);
-	if (!sk) return NULL;
+	if (!sk)
+		return NULL;
 	vcc = atm_sk(sk) = kmalloc(sizeof(*vcc), GFP_KERNEL);
 	if (!vcc) {
 		sk_free(sk);
 		return NULL;
 	}
-	sock_init_data(NULL,sk);
-	memset(vcc,0,sizeof(*vcc));
+	sock_init_data(NULL, sk);
+	memset(vcc, 0, sizeof(*vcc));
 	vcc->sk = sk;
-	if (nodev_vccs) nodev_vccs->prev = vcc;
+	if (nodev_vccs)
+		nodev_vccs->prev = vcc;
 	vcc->prev = NULL;
 	vcc->next = nodev_vccs;
 	nodev_vccs = vcc;
@@ -168,11 +185,16 @@
 
 static void unlink_vcc(struct atm_vcc *vcc,struct atm_dev *hold_dev)
 {
-	if (vcc->prev) vcc->prev->next = vcc->next;
-	else if (vcc->dev) vcc->dev->vccs = vcc->next;
-	    else nodev_vccs = vcc->next;
-	if (vcc->next) vcc->next->prev = vcc->prev;
-	else if (vcc->dev) vcc->dev->last = vcc->prev;
+	if (vcc->prev)
+		vcc->prev->next = vcc->next;
+	else if (vcc->dev)
+		vcc->dev->vccs = vcc->next;
+	else
+		nodev_vccs = vcc->next;
+	if (vcc->next)
+		vcc->next->prev = vcc->prev;
+	else if (vcc->dev)
+		vcc->dev->last = vcc->prev;
 	if (vcc->dev && vcc->dev != hold_dev && !vcc->dev->vccs &&
 	    test_bit(ATM_DF_CLOSE,&vcc->dev->flags))
 		shutdown_atm_dev(vcc->dev);
@@ -185,7 +207,6 @@
 	sk_free(sk);
 }
 
-
 void bind_vcc(struct atm_vcc *vcc,struct atm_dev *dev)
 {
 	unlink_vcc(vcc,dev);
@@ -193,18 +214,19 @@
 	if (dev) {
 		vcc->next = NULL;
 		vcc->prev = dev->last;
-		if (dev->vccs) dev->last->next = vcc;
-		else dev->vccs = vcc;
+		if (dev->vccs)
+			dev->last->next = vcc;
+		else
+			dev->vccs = vcc;
 		dev->last = vcc;
-	}
-	else {
-		if (nodev_vccs) nodev_vccs->prev = vcc;
+	} else {
+		if (nodev_vccs)
+			nodev_vccs->prev = vcc;
 		vcc->next = nodev_vccs;
 		vcc->prev = NULL;
 		nodev_vccs = vcc;
 	}
 }
-
 
 EXPORT_SYMBOL(atm_dev_register);
 EXPORT_SYMBOL(atm_dev_deregister);
diff -Nru a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
--- a/net/ax25/af_ax25.c	Sun Apr 14 12:16:59 2002
+++ b/net/ax25/af_ax25.c	Sun Apr 14 12:16:59 2002
@@ -1889,6 +1889,7 @@
 
 MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol");
+MODULE_LICENSE("GPL");
 
 static void __exit ax25_exit(void)
 {
diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c
--- a/net/core/neighbour.c	Sun Apr 14 12:16:55 2002
+++ b/net/core/neighbour.c	Sun Apr 14 12:16:55 2002
@@ -1239,6 +1239,7 @@
 	read_lock(&neigh_tbl_lock);
 	for (tbl=neigh_tables; tbl; tbl = tbl->next) {
 		int err = 0;
+		int override = 1;
 		struct neighbour *n;
 
 		if (tbl->family != ndm->ndm_family)
@@ -1266,6 +1267,7 @@
 		if (n) {
 			if (nlh->nlmsg_flags&NLM_F_EXCL)
 				err = -EEXIST;
+			override = nlh->nlmsg_flags&NLM_F_REPLACE;
 		} else if (!(nlh->nlmsg_flags&NLM_F_CREATE))
 			err = -ENOENT;
 		else {
@@ -1278,7 +1280,7 @@
 		if (err == 0) {
 			err = neigh_update(n, nda[NDA_LLADDR-1] ? RTA_DATA(nda[NDA_LLADDR-1]) : NULL,
 					   ndm->ndm_state,
-					   nlh->nlmsg_flags&NLM_F_REPLACE, 0);
+					   override, 0);
 		}
 		if (n)
 			neigh_release(n);
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	Sun Apr 14 12:16:56 2002
+++ b/net/core/skbuff.c	Sun Apr 14 12:16:56 2002
@@ -748,7 +748,7 @@
 			if (skb_cloned(skb)) {
 				if (!realloc)
 					BUG();
-				if (!pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+				if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 					return -ENOMEM;
 			}
 			if (len <= offset) {
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	Sun Apr 14 12:16:59 2002
+++ b/net/core/sock.c	Sun Apr 14 12:16:59 2002
@@ -108,6 +108,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
+#include <linux/tcp.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	Sun Apr 14 12:16:58 2002
+++ b/net/econet/af_econet.c	Sun Apr 14 12:16:58 2002
@@ -1133,3 +1133,5 @@
 
 module_init(econet_proto_init);
 module_exit(econet_proto_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	Sun Apr 14 12:16:55 2002
+++ b/net/ipv4/af_inet.c	Sun Apr 14 12:16:55 2002
@@ -627,7 +627,6 @@
 			int addr_len, int flags)
 {
 	struct sock *sk=sock->sk;
-	struct inet_opt *inet = inet_sk(sk);
 	int err;
 	long timeo;
 
@@ -654,13 +653,6 @@
 		err = -EISCONN;
 		if (sk->state != TCP_CLOSE) 
 			goto out;
-
-		err = -EAGAIN;
-		if (!inet->num) {
-			if (sk->prot->get_port(sk, 0) != 0)
-				goto out;
-			inet->sport = htons(inet->num);
-		}
 
 		err = sk->prot->connect(sk, uaddr, addr_len);
 		if (err < 0)
diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c
--- a/net/ipv4/arp.c	Sun Apr 14 12:16:57 2002
+++ b/net/ipv4/arp.c	Sun Apr 14 12:16:57 2002
@@ -450,6 +450,32 @@
 }
 
 /*
+ * Check if we can use proxy ARP for this path
+ */
+
+static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt)
+{
+	struct in_device *out_dev;
+	int imi, omi = -1;
+
+	if (!IN_DEV_PROXY_ARP(in_dev))
+		return 0;
+
+	if ((imi = IN_DEV_MEDIUM_ID(in_dev)) == 0)
+		return 1;
+	if (imi == -1)
+		return 0;
+
+	/* place to check for proxy_arp for routes */
+
+	if ((out_dev = in_dev_get(rt->u.dst.dev)) != NULL) {
+		omi = IN_DEV_MEDIUM_ID(out_dev);
+		in_dev_put(out_dev);
+	}
+	return (omi != imi && omi != -1);
+}
+
+/*
  *	Interface to link layer: send routine and receive handler.
  */
 
@@ -755,7 +781,7 @@
 		} else if (IN_DEV_FORWARD(in_dev)) {
 			if ((rt->rt_flags&RTCF_DNAT) ||
 			    (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&
-			     (IN_DEV_PROXY_ARP(in_dev) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
+			     (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {
 				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 				if (n)
 					neigh_release(n);
diff -Nru a/net/ipv4/devinet.c b/net/ipv4/devinet.c
--- a/net/ipv4/devinet.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/devinet.c	Sun Apr 14 12:16:56 2002
@@ -1032,7 +1032,7 @@
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[14];
+	ctl_table devinet_vars[15];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -1065,6 +1065,9 @@
          &proc_dointvec},
 	{NET_IPV4_CONF_PROXY_ARP, "proxy_arp",
          &ipv4_devconf.proxy_arp, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+	{NET_IPV4_CONF_MEDIUM_ID, "medium_id",
+         &ipv4_devconf.medium_id, sizeof(int), 0644, NULL,
          &proc_dointvec},
 	{NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay",
          &ipv4_devconf.bootp_relay, sizeof(int), 0644, NULL,
diff -Nru a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
--- a/net/ipv4/fib_frontend.c	Sun Apr 14 12:16:58 2002
+++ b/net/ipv4/fib_frontend.c	Sun Apr 14 12:16:58 2002
@@ -579,6 +579,9 @@
 	switch (event) {
 	case NETDEV_UP:
 		fib_add_ifaddr(ifa);
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+		fib_sync_up(ifa->ifa_dev->dev);
+#endif
 		rt_cache_flush(-1);
 		break;
 	case NETDEV_DOWN:
diff -Nru a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
--- a/net/ipv4/fib_semantics.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/fib_semantics.c	Sun Apr 14 12:16:56 2002
@@ -56,6 +56,8 @@
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
+static spinlock_t fib_multipath_lock = SPIN_LOCK_UNLOCKED;
+
 #define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \
 for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
 
@@ -869,8 +871,14 @@
 					 nh->nh_scope != scope) {
 					nh->nh_flags |= RTNH_F_DEAD;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
+					spin_lock_bh(&fib_multipath_lock);
 					fi->fib_power -= nh->nh_power;
 					nh->nh_power = 0;
+					spin_unlock_bh(&fib_multipath_lock);
+					if (force && nh->nh_dev) {
+						dev_put(nh->nh_dev);
+						nh->nh_dev = NULL;
+					}
 #endif
 					dead++;
 				}
@@ -906,13 +914,19 @@
 				alive++;
 				continue;
 			}
+			if (nh->nh_dev == NULL && nh->nh_oif == dev->ifindex) {
+				dev_hold(dev);
+				nh->nh_dev = dev;
+			}
 			if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
 				continue;
 			if (nh->nh_dev != dev || __in_dev_get(dev) == NULL)
 				continue;
 			alive++;
+			spin_lock_bh(&fib_multipath_lock);
 			nh->nh_power = 0;
 			nh->nh_flags &= ~RTNH_F_DEAD;
+			spin_unlock_bh(&fib_multipath_lock);
 		} endfor_nexthops(fi)
 
 		if (alive > 0) {
@@ -933,6 +947,7 @@
 	struct fib_info *fi = res->fi;
 	int w;
 
+	spin_lock_bh(&fib_multipath_lock);
 	if (fi->fib_power <= 0) {
 		int power = 0;
 		change_nexthops(fi) {
@@ -942,12 +957,12 @@
 			}
 		} endfor_nexthops(fi);
 		fi->fib_power = power;
-#if 1
 		if (power <= 0) {
-			printk(KERN_CRIT "impossible 777\n");
+			spin_unlock_bh(&fib_multipath_lock);
+			/* Race condition: route has just become dead. */
+			res->nh_sel = 0;
 			return;
 		}
-#endif
 	}
 
 
@@ -963,15 +978,15 @@
 				nh->nh_power--;
 				fi->fib_power--;
 				res->nh_sel = nhsel;
+				spin_unlock_bh(&fib_multipath_lock);
 				return;
 			}
 		}
 	} endfor_nexthops(fi);
 
-#if 1
-	printk(KERN_CRIT "impossible 888\n");
-#endif
-	return;
+	/* Race condition: route has just become dead. */
+	res->nh_sel = 0;
+	spin_unlock_bh(&fib_multipath_lock);
 }
 #endif
 
diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c
--- a/net/ipv4/icmp.c	Sun Apr 14 12:16:57 2002
+++ b/net/ipv4/icmp.c	Sun Apr 14 12:16:57 2002
@@ -139,6 +139,8 @@
   { EHOSTUNREACH,	1 }	/*	ICMP_PREC_CUTOFF	*/
 };
 
+extern int sysctl_ip_default_ttl;
+
 /* Control parameters for ECHO replies. */
 int sysctl_icmp_echo_ignore_all;
 int sysctl_icmp_echo_ignore_broadcasts;
@@ -354,6 +356,7 @@
 	icmp_out_count(icmp_param->data.icmph.type);
 
 	inet->tos = skb->nh.iph->tos;
+	inet->ttl = sysctl_ip_default_ttl;
 	daddr = ipc.addr = rt->rt_src;
 	ipc.opt = NULL;
 	if (icmp_param->replyopts.optlen) {
@@ -498,6 +501,7 @@
 	icmp_param.offset=skb_in->nh.raw - skb_in->data;
 	icmp_out_count(icmp_param.data.icmph.type);
 	inet_sk(icmp_socket->sk)->tos = tos;
+	inet_sk(icmp_socket->sk)->ttl = sysctl_ip_default_ttl;
 	ipc.addr = iph->saddr;
 	ipc.opt = &icmp_param.replyopts;
 	if (icmp_param.replyopts.srr) {
@@ -876,7 +880,7 @@
  
 int icmp_rcv(struct sk_buff *skb)
 {
-	struct icmphdr *icmph = skb->h.icmph;
+	struct icmphdr *icmph;
 	struct rtable *rt = (struct rtable*)skb->dst;
 
 	ICMP_INC_STATS_BH(IcmpInMsgs);
@@ -894,6 +898,8 @@
 
 	if (!pskb_pull(skb, sizeof(struct icmphdr)))
 		goto error;
+
+	icmph = skb->h.icmph;
 
 	/*
 	 *	18 is the highest 'known' ICMP type. Anything else is a mystery
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/ip_gre.c	Sun Apr 14 12:16:59 2002
@@ -760,7 +760,10 @@
 	}
 
 	df = tiph->frag_off;
-	mtu = rt->u.dst.pmtu - tunnel->hlen;
+	if (df)
+		mtu = rt->u.dst.pmtu - tunnel->hlen;
+	else
+		mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
 
 	if (skb->protocol == __constant_htons(ETH_P_IP)) {
 		if (skb->dst && mtu < skb->dst->pmtu && mtu >= 68)
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c	Sun Apr 14 12:16:55 2002
+++ b/net/ipv4/ip_input.c	Sun Apr 14 12:16:55 2002
@@ -224,8 +224,6 @@
 	nf_debug_ip_local_deliver(skb);
 #endif /*CONFIG_NETFILTER_DEBUG*/
 
-	if (!pskb_may_pull(skb, ihl))
-		goto out;
 	__skb_pull(skb, ihl);
 
 #ifdef CONFIG_NETFILTER
@@ -279,7 +277,6 @@
 			sock_put(raw_sk);
 		} else if (!flag) {		/* Free and report errors */
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);	
-out:
 			kfree_skb(skb);
 		}
 	}
@@ -346,7 +343,6 @@
 			goto drop;
 		iph = skb->nh.iph;
 
-		skb->ip_summed = 0;
 		if (ip_options_compile(NULL, skb))
 			goto inhdr_error;
 
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
--- a/net/ipv4/ipip.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/ipip.c	Sun Apr 14 12:16:59 2002
@@ -572,7 +572,11 @@
 		goto tx_error;
 	}
 
-	mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
+	if (tiph->frag_off)
+		mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
+	else
+		mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
+
 	if (mtu < 68) {
 		tunnel->stat.collisions++;
 		ip_rt_put(rt);
diff -Nru a/net/ipv4/netfilter/Config.help b/net/ipv4/netfilter/Config.help
--- a/net/ipv4/netfilter/Config.help	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/netfilter/Config.help	Sun Apr 14 12:16:59 2002
@@ -160,6 +160,17 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+CONFIG_IP_NF_NAT_LOCAL
+  This option enables support for NAT of locally originated connections. 
+  Enable this if you need to use destination NAT on connections
+  originating from local processes on the nat box itself.
+
+  Please note that you will need a recent version (>= 1.2.6a)
+  of the iptables userspace program in order to use this feature.
+  See http://www.iptables.org/ for download instructions.
+
+  If unsure, say 'N'.
+
 CONFIG_IP_NF_TARGET_MASQUERADE
   Masquerading is a special case of NAT: all outgoing connections are
   changed to seem to come from a particular interface's address, and
diff -Nru a/net/ipv4/netfilter/Config.in b/net/ipv4/netfilter/Config.in
--- a/net/ipv4/netfilter/Config.in	Sun Apr 14 12:16:58 2002
+++ b/net/ipv4/netfilter/Config.in	Sun Apr 14 12:16:58 2002
@@ -47,7 +47,7 @@
       define_bool CONFIG_IP_NF_NAT_NEEDED y
       dep_tristate '    MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT
       dep_tristate '    REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT
-      bool '    NAT of local connections' CONFIG_IP_NF_NAT_LOCAL
+      bool '    NAT of local connections (READ HELP)' CONFIG_IP_NF_NAT_LOCAL
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         dep_tristate '    Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
       fi
diff -Nru a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
--- a/net/ipv4/netfilter/Makefile	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/netfilter/Makefile	Sun Apr 14 12:16:56 2002
@@ -9,18 +9,18 @@
 
 O_TARGET := netfilter.o
 
-export-objs = ip_conntrack_standalone.o ip_conntrack_ftp.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o arp_tables.o
+export-objs = ip_conntrack_standalone.o ip_fw_compat.o ip_nat_standalone.o ip_tables.o arp_tables.o
 
 # Multipart objects.
 list-multi		:= ip_conntrack.o iptable_nat.o ipfwadm.o ipchains.o
 
 # objects for the conntrack and NAT core (used by standalone and backw. compat)
 ip_nf_conntrack-objs	:= ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
-ip_nf_nat-objs		:= ip_nat_core.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
+ip_nf_nat-objs		:= ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
 
 # objects for the standalone - connection tracking / NAT
 ip_conntrack-objs	:= ip_conntrack_standalone.o $(ip_nf_conntrack-objs)
-iptable_nat-objs	:= ip_nat_standalone.o ip_nat_rule.o ip_nat_helper.o $(ip_nf_nat-objs)
+iptable_nat-objs	:= ip_nat_standalone.o ip_nat_rule.o $(ip_nf_nat-objs)
 
 # objects for backwards compatibility mode
 ip_nf_compat-objs	:= ip_fw_compat.o ip_fw_compat_redir.o ip_fw_compat_masq.o $(ip_nf_conntrack-objs) $(ip_nf_nat-objs)
@@ -33,7 +33,14 @@
 
 # connection tracking helpers
 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
+ifdef CONFIG_IP_NF_NAT_FTP
+	export-objs += ip_conntrack_ftp.o
+endif
+
 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+ifdef CONFIG_IP_NF_NAT_IRC
+	export-objs += ip_conntrack_irc.o
+endif
 
 # NAT helpers 
 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c	Sun Apr 14 12:16:54 2002
+++ b/net/ipv4/netfilter/ip_conntrack_core.c	Sun Apr 14 12:16:54 2002
@@ -3,7 +3,12 @@
    extension. */
 
 /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
-   Public Licence. */
+ * Public Licence. 
+ *
+ * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
+ * 	- new API and handling of conntrack/nat helpers
+ * 	- now capable of multiple expectations for one master
+ * */
 
 #ifdef MODULE
 #define __NO_VERSION__
@@ -38,6 +43,8 @@
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
+#define IP_CONNTRACK_VERSION	"2.0"
+
 #if 0
 #define DEBUGP printk
 #else
@@ -45,6 +52,7 @@
 #endif
 
 DECLARE_RWLOCK(ip_conntrack_lock);
+DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock);
 
 void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
 LIST_HEAD(expect_list);
@@ -77,7 +85,7 @@
 	return p;
 }
 
-struct ip_conntrack_protocol *find_proto(u_int8_t protocol)
+struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
 {
 	struct ip_conntrack_protocol *p;
 
@@ -151,9 +159,58 @@
 	return protocol->invert_tuple(inverse, orig);
 }
 
+/* remove one specific expectation from all lists and free it */
+static void unexpect_related(struct ip_conntrack_expect *expect)
+{
+	MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+	DEBUGP("unexpect_related(%p)\n", expect);
+	/* delete from global and local lists */
+	list_del(&expect->list);
+	list_del(&expect->expected_list);
+	if (!expect->sibling)
+		expect->expectant->expecting--;
+	kfree(expect);
+}
+
+/* delete all expectations for this conntrack */
+static void destroy_expectations(struct ip_conntrack *ct)
+{
+	struct list_head *exp_entry, *next;
+	struct ip_conntrack_expect *exp;
+
+	DEBUGP("destroy_expectations(%p)\n", ct);
+
+	for (exp_entry = ct->sibling_list.next;
+	     exp_entry != &ct->sibling_list; exp_entry = next) {
+		next = exp_entry->next;
+		exp = list_entry(exp_entry, struct ip_conntrack_expect,
+				 expected_list);
+
+		/* we skip established expectations, as we want to delete
+		 * the un-established ones only */
+		if (exp->sibling) {
+			DEBUGP("destroy_expectations: skipping established %p of %p\n", exp->sibling, ct);
+			continue;
+		}
+
+		IP_NF_ASSERT(list_inlist(&expect_list, exp));
+		IP_NF_ASSERT(exp->expectant == ct);
+
+		if (exp->expectant->helper->timeout
+		    && ! del_timer(&exp->timeout)) {
+		    	DEBUGP("destroy_expectations: skipping dying expectation %p of %p\n", exp, ct);
+		    	continue;
+		}
+		
+		/* delete expectation from global and private lists */
+		unexpect_related(exp);
+	}
+}
+
 static void
 clean_from_lists(struct ip_conntrack *ct)
 {
+	DEBUGP("clean_from_lists(%p)\n", ct);
 	MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
 	/* Remove from both hash lists: must not NULL out next ptrs,
            otherwise we'll look unconfirmed.  Fortunately, LIST_DELETE
@@ -164,27 +221,45 @@
 	LIST_DELETE(&ip_conntrack_hash
 		    [hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple)],
 		    &ct->tuplehash[IP_CT_DIR_REPLY]);
-	/* If our expected is in the list, take it out. */
-	if (ct->expected.expectant) {
-		IP_NF_ASSERT(list_inlist(&expect_list, &ct->expected));
-		IP_NF_ASSERT(ct->expected.expectant == ct);
-		LIST_DELETE(&expect_list, &ct->expected);
-	}
+
+	/* Destroy all un-established, pending expectations */
+	destroy_expectations(ct);
 }
 
 static void
 destroy_conntrack(struct nf_conntrack *nfct)
 {
 	struct ip_conntrack *ct = (struct ip_conntrack *)nfct;
+	struct ip_conntrack_protocol *proto;
 
+	DEBUGP("destroy_conntrack(%p)\n", ct);
 	IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
 	IP_NF_ASSERT(!timer_pending(&ct->timeout));
 
-	if (ct->master.master)
-		nf_conntrack_put(&ct->master);
+	if (ct->master && master_ct(ct))
+		ip_conntrack_put(master_ct(ct));
+
+	/* To make sure we don't get any weird locking issues here:
+	 * destroy_conntrack() MUST NOT be called with a write lock
+	 * to ip_conntrack_lock!!! -HW */
+	proto = ip_ct_find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+	if (proto && proto->destroy)
+		proto->destroy(ct);
 
 	if (ip_conntrack_destroyed)
 		ip_conntrack_destroyed(ct);
+
+	WRITE_LOCK(&ip_conntrack_lock);
+	/* Delete our master expectation from the local list
+	 * and destroy it, if we've been expected */
+	if (ct->master) {
+		list_del(&ct->master->expected_list);
+		kfree(ct->master);
+	}
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
+	
+	DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
 	kmem_cache_free(ip_conntrack_cachep, ct);
 	atomic_dec(&ip_conntrack_count);
 }
@@ -382,7 +457,7 @@
 		return NULL;
 	}
 
-	innerproto = find_proto(inner->protocol);
+	innerproto = ip_ct_find_proto(inner->protocol);
 	/* Are they talking about one of our connections? */
 	if (inner->ihl * 4 + 8 > datalen
 	    || !get_tuple(inner, datalen, &origtuple, innerproto)) {
@@ -462,10 +537,18 @@
 	return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
 }
 
+struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+	return LIST_FIND(&helpers, helper_cmp,
+			 struct ip_conntrack_helper *,
+			 tuple);
+}
+
 /* Compare parts depending on mask. */
 static inline int expect_cmp(const struct ip_conntrack_expect *i,
 			     const struct ip_conntrack_tuple *tuple)
 {
+	MUST_BE_READ_LOCKED(&ip_conntrack_expect_tuple_lock);
 	return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask);
 }
 
@@ -514,7 +597,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(conntrack, 0, sizeof(struct ip_conntrack));
+	memset(conntrack, 0, sizeof(*conntrack));
 	atomic_set(&conntrack->ct_general.use, 1);
 	conntrack->ct_general.destroy = destroy_conntrack;
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
@@ -533,31 +616,44 @@
 	conntrack->timeout.data = (unsigned long)conntrack;
 	conntrack->timeout.function = death_by_timeout;
 
+	INIT_LIST_HEAD(&conntrack->sibling_list);
+
 	/* Mark clearly that it's not in the hash table. */
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list.next = NULL;
 
-	/* Write lock required for deletion of expected.  Without
-           this, a read-lock would do. */
 	WRITE_LOCK(&ip_conntrack_lock);
-	conntrack->helper = LIST_FIND(&helpers, helper_cmp,
-				      struct ip_conntrack_helper *,
-				      &repl_tuple);
 	/* Need finding and deleting of expected ONLY if we win race */
+	READ_LOCK(&ip_conntrack_expect_tuple_lock);
 	expected = LIST_FIND(&expect_list, expect_cmp,
 			     struct ip_conntrack_expect *, tuple);
+	READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
+
+	/* Look up the conntrack helper for master connections only */
+	if (!expected)
+		conntrack->helper = ip_ct_find_helper(&repl_tuple);
+
+	/* If the expectation is dying, then this is a looser. */
+	if (expected
+	    && expected->expectant->helper->timeout
+	    && ! del_timer(&expected->timeout))
+		expected = NULL;
+
 	/* If master is not in hash table yet (ie. packet hasn't left
 	   this machine yet), how can other end know about expected?
 	   Hence these are not the droids you are looking for (if
 	   master ct never got confirmed, we'd hold a reference to it
 	   and weird things would happen to future packets). */
 	if (expected && is_confirmed(expected->expectant)) {
+		DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
+			conntrack, expected);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
+		IP_NF_ASSERT(master_ct(conntrack));
 		conntrack->status = IPS_EXPECTED;
-		conntrack->master.master = &expected->expectant->ct_general;
-		IP_NF_ASSERT(conntrack->master.master);
+		conntrack->master = expected;
+		expected->sibling = conntrack;
 		LIST_DELETE(&expect_list, expected);
-		expected->expectant = NULL;
-		nf_conntrack_get(&conntrack->master);
+		expected->expectant->expecting--;
+		nf_conntrack_get(&master_ct(conntrack)->infos[0]);
 	}
 	atomic_inc(&ip_conntrack_count);
 	WRITE_UNLOCK(&ip_conntrack_lock);
@@ -662,7 +758,7 @@
 			return NF_STOLEN;
 	}
 
-	proto = find_proto((*pskb)->nh.iph->protocol);
+	proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
 
 	/* It may be an icmp error... */
 	if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 
@@ -706,66 +802,210 @@
 int invert_tuplepr(struct ip_conntrack_tuple *inverse,
 		   const struct ip_conntrack_tuple *orig)
 {
-	return invert_tuple(inverse, orig, find_proto(orig->dst.protonum));
+	return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
 }
 
-static void unexpect_related(struct ip_conntrack *related_to)
-{
-	MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
-	list_del(&related_to->expected.list);
-	related_to->expected.expectant = NULL;
+static inline int resent_expect(const struct ip_conntrack_expect *i,
+			        const struct ip_conntrack_tuple *tuple,
+			        const struct ip_conntrack_tuple *mask)
+{
+	DEBUGP("resent_expect\n");
+	DEBUGP("   tuple:   "); DUMP_TUPLE(&i->tuple);
+	DEBUGP("ct_tuple:   "); DUMP_TUPLE(&i->ct_tuple);
+	DEBUGP("test tuple: "); DUMP_TUPLE(tuple);
+	return (((i->ct_tuple.dst.protonum == 0 && ip_ct_tuple_equal(&i->tuple, tuple))
+	         || (i->ct_tuple.dst.protonum && ip_ct_tuple_equal(&i->ct_tuple, tuple)))
+		&& ip_ct_tuple_equal(&i->mask, mask));
 }
 
 /* Would two expected things clash? */
 static inline int expect_clash(const struct ip_conntrack_expect *i,
-			       const struct ip_conntrack_expect *new)
+			       const struct ip_conntrack_tuple *tuple,
+			       const struct ip_conntrack_tuple *mask)
 {
 	/* Part covered by intersection of masks must be unequal,
            otherwise they clash */
 	struct ip_conntrack_tuple intersect_mask
-		= { { i->mask.src.ip & new->mask.src.ip,
-		      { i->mask.src.u.all & new->mask.src.u.all } },
-		    { i->mask.dst.ip & new->mask.dst.ip,
-		      { i->mask.dst.u.all & new->mask.dst.u.all },
-		      i->mask.dst.protonum & new->mask.dst.protonum } };
+		= { { i->mask.src.ip & mask->src.ip,
+		      { i->mask.src.u.all & mask->src.u.all } },
+		    { i->mask.dst.ip & mask->dst.ip,
+		      { i->mask.dst.u.all & mask->dst.u.all },
+		      i->mask.dst.protonum & mask->dst.protonum } };
+
+	return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
+}
+
+void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
+{
+	WRITE_LOCK(&ip_conntrack_lock);
+	unexpect_related(expect);
+	WRITE_UNLOCK(&ip_conntrack_lock);
+}
+	
+static void expectation_timed_out(unsigned long ul_expect)
+{
+	struct ip_conntrack_expect *expect = (void *) ul_expect;
 
-	return ip_ct_tuple_mask_cmp(&i->tuple, &new->tuple, &intersect_mask);
+	DEBUGP("expectation %p timed out\n", expect);	
+	ip_conntrack_unexpect_related(expect);
 }
 
 /* Add a related connection. */
 int ip_conntrack_expect_related(struct ip_conntrack *related_to,
-				const struct ip_conntrack_tuple *tuple,
-				const struct ip_conntrack_tuple *mask,
-				int (*expectfn)(struct ip_conntrack *))
+				struct ip_conntrack_expect *expect)
 {
-	WRITE_LOCK(&ip_conntrack_lock);
-	if (related_to->expected.expectant)
-		unexpect_related(related_to);
+	struct ip_conntrack_expect *new;
+	int ret = 0;
 
-	related_to->expected.tuple = *tuple;
-	related_to->expected.mask = *mask;
-	related_to->expected.expectfn = expectfn;
+	WRITE_LOCK(&ip_conntrack_lock);
+	/* Because of the write lock, no reader can walk the lists,
+	 * so there is no need to use the tuple lock too */
 
-	if (LIST_FIND(&expect_list, expect_clash,
-		      struct ip_conntrack_expect *, &related_to->expected)) {
+	DEBUGP("ip_conntrack_expect_related %p\n", related_to);
+	DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
+	DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask);
+
+	new = LIST_FIND(&expect_list, resent_expect,
+		        struct ip_conntrack_expect *, &expect->tuple, &expect->mask);
+	if (new) {
+		/* Helper private data may contain offsets but no pointers
+		   pointing into the payload - otherwise we should have to copy 
+		   the data filled out by the helper over the old one */
+		DEBUGP("expect_related: resent packet\n");
+		if (related_to->helper->timeout) {
+			/* Refresh timer, if possible... */
+			if (del_timer(&new->timeout)) {
+				new->timeout.expires = jiffies + related_to->helper->timeout * HZ;
+				add_timer(&new->timeout);
+				WRITE_UNLOCK(&ip_conntrack_lock);
+				return -EEXIST;
+			}
+			/* ... otherwise expectation is dying. Fall over and create a new one. */
+			new = NULL;
+		} else {
+			WRITE_UNLOCK(&ip_conntrack_lock);
+			return -EEXIST;
+		}
+	} else if (related_to->helper->max_expected
+	    	   && related_to->expecting >= related_to->helper->max_expected) {
+	    	if (net_ratelimit())
+		    	printk(KERN_WARNING 
+		    	       "ip_conntrack: max number of expected connections %i of %s reached for %u.%u.%u.%u->%u.%u.%u.%u%s\n",
+		    	       related_to->helper->max_expected, 
+		    	       related_to->helper->name,
+		    	       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
+		    	       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
+		    	       related_to->helper->flags & IP_CT_HELPER_F_REUSE_EXPECT ?
+		    	       ", reusing" : "");
+	    	if (related_to->helper->flags & IP_CT_HELPER_F_REUSE_EXPECT) {
+		    	struct list_head *cur_item;
+
+		    	/* Let's choose the the oldest expectation to overwrite */
+			list_for_each(cur_item, &related_to->sibling_list) { 
+				new = list_entry(cur_item, struct ip_conntrack_expect,
+						 expected_list);
+				if (new->sibling == NULL)
+					break;
+			}
+			IP_NF_ASSERT(new);
+			if (related_to->helper->timeout 
+			    &&  !del_timer(&new->timeout)) {
+				/* Expectation is dying. Fall over and create a new one */
+				new = NULL;
+			} else {
+				list_del(&new->list);
+				list_del(&new->expected_list);
+				related_to->expecting--;
+				ret = -EPERM;
+			}
+		} else {
+			WRITE_UNLOCK(&ip_conntrack_lock);
+			return -EPERM;
+		}
+	} else if (LIST_FIND(&expect_list, expect_clash,
+		      struct ip_conntrack_expect *, &expect->tuple, &expect->mask)) {
 		WRITE_UNLOCK(&ip_conntrack_lock);
+		DEBUGP("expect_related: busy!\n");
 		return -EBUSY;
 	}
+	
+	if (!new) {
+		new = (struct ip_conntrack_expect *) 
+		      kmalloc(sizeof(*expect), GFP_ATOMIC);
+		if (!new) {
+			WRITE_UNLOCK(&ip_conntrack_lock);
+			DEBUGP("expect_relaed: OOM allocating expect\n");
+			return -ENOMEM;
+		}
+	}
+	
+	/* Zero out the new structure, then fill out it with the data */
+	DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
+	memset(new, 0, sizeof(*expect));
+	INIT_LIST_HEAD(&new->list);
+	INIT_LIST_HEAD(&new->expected_list);
+	memcpy(new, expect, sizeof(*expect));
+	new->expectant = related_to;
+	new->sibling = NULL;
+	
+	/* add to expected list for this connection */	
+	list_add(&new->expected_list, &related_to->sibling_list);
+	/* add to global list of expectations */
+	list_prepend(&expect_list, &new->list);
+	/* add and start timer if required */
+	if (related_to->helper->timeout) {
+		init_timer(&new->timeout);
+		new->timeout.data = (unsigned long)new;
+		new->timeout.function = expectation_timed_out;
+		new->timeout.expires = jiffies + related_to->helper->timeout * HZ;
+		add_timer(&new->timeout);
+	}
+	related_to->expecting++;
 
-	list_prepend(&expect_list, &related_to->expected);
-	related_to->expected.expectant = related_to;
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
-	return 0;
+	return ret;
 }
 
-void ip_conntrack_unexpect_related(struct ip_conntrack *related_to)
+/* Change tuple in an existing expectation */
+int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
+			       struct ip_conntrack_tuple *newtuple)
 {
-	WRITE_LOCK(&ip_conntrack_lock);
-	unexpect_related(related_to);
-	WRITE_UNLOCK(&ip_conntrack_lock);
-}
+	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+
+	DEBUGP("change_expect:\n");
+	DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
+	DEBUGP("exp mask:  "); DUMP_TUPLE(&expect->mask);
+	DEBUGP("newtuple:  "); DUMP_TUPLE(newtuple);
+	if (expect->ct_tuple.dst.protonum == 0) {
+		/* Never seen before */
+		DEBUGP("change expect: never seen before\n");
+		if (!ip_ct_tuple_equal(&expect->tuple, newtuple) 
+		    && LIST_FIND(&expect_list, expect_clash,
+			         struct ip_conntrack_expect *, newtuple, &expect->mask)) {
+			/* Force NAT to find an unused tuple */
+			return -1;
+		} else {
+			WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
+			memcpy(&expect->ct_tuple, &expect->tuple, sizeof(expect->tuple));
+			memcpy(&expect->tuple, newtuple, sizeof(expect->tuple));
+			WRITE_UNLOCK(&ip_conntrack_expect_tuple_lock);
+			return 0;
+		}
+	} else {
+		/* Resent packet */
+		DEBUGP("change expect: resent packet\n");
+		if (ip_ct_tuple_equal(&expect->tuple, newtuple)) {
+			return 0;
+		} else {
+			/* Force NAT to choose again the same port */
+			return -1;
+		}
+	}
 	
+	return -1;
+}
+
 /* Alter reply tuple (maybe alter helper).  If it's already taken,
    return 0 and don't do alteration. */
 int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
@@ -783,10 +1023,12 @@
 	DUMP_TUPLE(newreply);
 
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
-	conntrack->helper = LIST_FIND(&helpers, helper_cmp,
-				      struct ip_conntrack_helper *,
-				      newreply);
+	if (!conntrack->master)
+		conntrack->helper = LIST_FIND(&helpers, helper_cmp,
+					      struct ip_conntrack_helper *,
+					      newreply);
 	WRITE_UNLOCK(&ip_conntrack_lock);
+
 	return 1;
 }
 
@@ -805,14 +1047,10 @@
 			 const struct ip_conntrack_helper *me)
 {
 	if (i->ctrack->helper == me) {
-		i->ctrack->helper = NULL;
 		/* Get rid of any expected. */
-		if (i->ctrack->expected.expectant) {
-			IP_NF_ASSERT(i->ctrack->expected.expectant
-				     == i->ctrack);
-			LIST_DELETE(&expect_list, &i->ctrack->expected);
-			i->ctrack->expected.expectant = NULL;
-		}
+		destroy_expectations(i->ctrack);
+		/* And *then* set helper to NULL */
+		i->ctrack->helper = NULL;
 	}
 	return 0;
 }
@@ -1096,8 +1334,10 @@
 	}
 	ip_conntrack_max = 8 * ip_conntrack_htable_size;
 
-	printk("ip_conntrack (%u buckets, %d max)\n",
-	       ip_conntrack_htable_size, ip_conntrack_max);
+	printk("ip_conntrack version %s (%u buckets, %d max)"
+	       " - %d bytes per conntrack\n", IP_CONNTRACK_VERSION,
+	       ip_conntrack_htable_size, ip_conntrack_max,
+	       sizeof(struct ip_conntrack));
 
 	ret = nf_register_sockopt(&so_getorigdst);
 	if (ret != 0)
diff -Nru a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c	Sun Apr 14 12:16:59 2002
@@ -1,4 +1,5 @@
 /* FTP extension for IP connection tracking. */
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
@@ -242,8 +243,10 @@
 	u_int32_t array[6] = { 0 };
 	int dir = CTINFO2DIR(ctinfo);
 	unsigned int matchlen, matchoff;
-	struct ip_conntrack_tuple t, mask;
-	struct ip_ct_ftp *info = &ct->help.ct_ftp_info;
+	struct ip_ct_ftp_master *ct_ftp_info = &ct->help.ct_ftp_info;
+	struct ip_conntrack_expect expect, *exp = &expect;
+	struct ip_ct_ftp_expect *exp_ftp_info = &exp->help.exp_ftp_info;
+
 	unsigned int i;
 	int found = 0;
 
@@ -271,8 +274,8 @@
 	}
 
 	LOCK_BH(&ip_ftp_lock);
-	old_seq_aft_nl_set = info->seq_aft_nl_set[dir];
-	old_seq_aft_nl = info->seq_aft_nl[dir];
+	old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir];
+	old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir];
 
 	DEBUGP("conntrack_ftp: datalen %u\n", datalen);
 	if ((datalen > 0) && (data[datalen-1] == '\n')) {
@@ -281,8 +284,9 @@
 		    || after(ntohl(tcph->seq) + datalen, old_seq_aft_nl)) {
 			DEBUGP("conntrack_ftp: updating nl to %u\n",
 			       ntohl(tcph->seq) + datalen);
-			info->seq_aft_nl[dir] = ntohl(tcph->seq) + datalen;
-			info->seq_aft_nl_set[dir] = 1;
+			ct_ftp_info->seq_aft_nl[dir] = 
+						ntohl(tcph->seq) + datalen;
+			ct_ftp_info->seq_aft_nl_set[dir] = 1;
 		}
 	}
 	UNLOCK_BH(&ip_ftp_lock);
@@ -330,16 +334,17 @@
 	DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
 	       (int)matchlen, data + matchoff,
 	       matchlen, ntohl(tcph->seq) + matchoff);
+	       
+	memset(&expect, 0, sizeof(expect));
 
 	/* Update the ftp info */
 	LOCK_BH(&ip_ftp_lock);
 	if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
 	    == ct->tuplehash[dir].tuple.src.ip) {
-		info->is_ftp = 21;
-		info->seq = ntohl(tcph->seq) + matchoff;
-		info->len = matchlen;
-		info->ftptype = search[i].ftptype;
-		info->port = array[4] << 8 | array[5];
+		exp->seq = ntohl(tcph->seq) + matchoff;
+		exp_ftp_info->len = matchlen;
+		exp_ftp_info->ftptype = search[i].ftptype;
+		exp_ftp_info->port = array[4] << 8 | array[5];
 	} else {
 		/* Enrico Scholz's passive FTP to partially RNAT'd ftp
 		   server: it really wants us to connect to a
@@ -356,18 +361,21 @@
 		if (!loose) goto out;
 	}
 
-	t = ((struct ip_conntrack_tuple)
+	exp->tuple = ((struct ip_conntrack_tuple)
 		{ { ct->tuplehash[!dir].tuple.src.ip,
 		    { 0 } },
 		  { htonl((array[0] << 24) | (array[1] << 16)
 			  | (array[2] << 8) | array[3]),
 		    { htons(array[4] << 8 | array[5]) },
 		    IPPROTO_TCP }});
-	mask = ((struct ip_conntrack_tuple)
+	exp->mask = ((struct ip_conntrack_tuple)
 		{ { 0xFFFFFFFF, { 0 } },
 		  { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
+
+	exp->expectfn = NULL;
+
 	/* Ignore failure; should only happen with NAT */
-	ip_conntrack_expect_related(ct, &t, &mask, NULL);
+	ip_conntrack_expect_related(ct, &expect);
  out:
 	UNLOCK_BH(&ip_ftp_lock);
 
@@ -375,6 +383,7 @@
 }
 
 static struct ip_conntrack_helper ftp[MAX_PORTS];
+static char ftp_names[MAX_PORTS][10];
 
 /* Not __exit: called from init() */
 static void fini(void)
@@ -390,9 +399,10 @@
 static int __init init(void)
 {
 	int i, ret;
+	char *tmpname;
 
 	if (ports[0] == 0)
-		ports[0] = 21;
+		ports[0] = FTP_PORT;
 
 	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
 		memset(&ftp[i], 0, sizeof(struct ip_conntrack_helper));
@@ -400,7 +410,19 @@
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
 		ftp[i].mask.src.u.tcp.port = 0xFFFF;
 		ftp[i].mask.dst.protonum = 0xFFFF;
+		ftp[i].max_expected = 1;
+		ftp[i].timeout = 0;
+		ftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
+		ftp[i].me = ip_conntrack_ftp;
 		ftp[i].help = help;
+
+		tmpname = &ftp_names[i][0];
+		if (ports[i] == FTP_PORT)
+			sprintf(tmpname, "ftp");
+		else
+			sprintf(tmpname, "ftp-%d", ports[i]);
+		ftp[i].name = tmpname;
+
 		DEBUGP("ip_ct_ftp: registering helper for port %d\n", 
 				ports[i]);
 		ret = ip_conntrack_helper_register(&ftp[i]);
@@ -414,10 +436,10 @@
 	return 0;
 }
 
-
+#ifdef CONFIG_IP_NF_NAT_NEEDED
 EXPORT_SYMBOL(ip_ftp_lock);
-EXPORT_SYMBOL(ip_conntrack_ftp);
-MODULE_LICENSE("GPL");
+#endif
 
+MODULE_LICENSE("GPL");
 module_init(init);
 module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
--- a/net/ipv4/netfilter/ip_conntrack_irc.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c	Sun Apr 14 12:16:59 2002
@@ -11,12 +11,18 @@
  **
  *	Module load syntax:
  * 	insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS>
+ *			    max_dcc_channels=n dcc_timeout=secs
  *	
  * 	please give the ports of all IRC servers You wish to connect to.
- *	If You don't specify ports, the default will be port 6667
+ *	If You don't specify ports, the default will be port 6667.
+ *	With max_dcc_channels you can define the maximum number of not
+ *	yet answered DCC channels per IRC session (default 8).
+ *	With dcc_timeout you can specify how long the system waits for 
+ *	an expected DCC channel (default 300 seconds).
  *
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
@@ -30,6 +36,8 @@
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_n_c = 0;
+static int max_dcc_channels = 8;
+static unsigned int dcc_timeout = 300;
 
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) connection tracking module");
@@ -37,6 +45,10 @@
 #ifdef MODULE_PARM
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
+MODULE_PARM(max_dcc_channels, "i");
+MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
+MODULE_PARM(dcc_timeout, "i");
+MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
 #endif
 
 #define NUM_DCCPROTO 	5
@@ -103,23 +115,15 @@
 	u_int32_t tcplen = len - iph->ihl * 4;
 	u_int32_t datalen = tcplen - tcph->doff * 4;
 	int dir = CTINFO2DIR(ctinfo);
-	struct ip_conntrack_tuple t, mask;
+	struct ip_conntrack_expect expect, *exp = &expect;
+	struct ip_ct_irc_expect *exp_irc_info = &exp->help.exp_irc_info;
 
 	u_int32_t dcc_ip;
 	u_int16_t dcc_port;
 	int i;
 	char *addr_beg_p, *addr_end_p;
 
-	struct ip_ct_irc *info = &ct->help.ct_irc_info;
-
-	mask = ((struct ip_conntrack_tuple)
-		{ { 0, { 0 } },
-		  { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
-
 	DEBUGP("entered\n");
-	/* Can't track connections formed before we registered */
-	if (!info)
-		return NF_ACCEPT;
 
 	/* If packet is coming from IRC server */
 	if (dir == IP_CT_DIR_REPLY)
@@ -189,33 +193,37 @@
 
 				continue;
 			}
+			
+			memset(&expect, 0, sizeof(expect));
 
 			LOCK_BH(&ip_irc_lock);
 
 			/* save position of address in dcc string,
 			 * neccessary for NAT */
-			info->is_irc = IP_CONNTR_IRC;
 			DEBUGP("tcph->seq = %u\n", tcph->seq);
-			info->seq = ntohl(tcph->seq) + (addr_beg_p - _data);
-			info->len = (addr_end_p - addr_beg_p);
-			info->port = dcc_port;
+			exp->seq = ntohl(tcph->seq) + (addr_beg_p - _data);
+			exp_irc_info->len = (addr_end_p - addr_beg_p);
+			exp_irc_info->port = dcc_port;
 			DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n",
-				info->seq, (addr_end_p - _data), info->len);
+				exp->seq, (addr_end_p - _data), exp_irc_info->len);
+
+			exp->tuple = ((struct ip_conntrack_tuple)
+				{ { 0, { 0 } },
+				  { htonl(dcc_ip), { htons(dcc_port) },
+				    IPPROTO_TCP }});
+			exp->mask = ((struct ip_conntrack_tuple)
+				{ { 0, { 0 } },
+				  { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
 
-			memset(&t, 0, sizeof(t));
-			t.src.ip = 0;
-			t.src.u.tcp.port = 0;
-			t.dst.ip = htonl(dcc_ip);
-			t.dst.u.tcp.port = htons(info->port);
-			t.dst.protonum = IPPROTO_TCP;
+			exp->expectfn = NULL;
 
 			DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
-				NIPQUAD(t.src.ip),
-				ntohs(t.src.u.tcp.port),
-				NIPQUAD(t.dst.ip),
-				ntohs(t.dst.u.tcp.port));
+				NIPQUAD(exp->tuple.src.ip),
+				ntohs(exp->tuple.src.u.tcp.port),
+				NIPQUAD(exp->tuple.dst.ip),
+				ntohs(exp->tuple.dst.u.tcp.port));
 
-			ip_conntrack_expect_related(ct, &t, &mask, NULL);
+			ip_conntrack_expect_related(ct, &expect);
 			UNLOCK_BH(&ip_irc_lock);
 
 			return NF_ACCEPT;
@@ -226,29 +234,53 @@
 }
 
 static struct ip_conntrack_helper irc_helpers[MAX_PORTS];
+static char irc_names[MAX_PORTS][10];
 
 static void fini(void);
 
 static int __init init(void)
 {
 	int i, ret;
+	struct ip_conntrack_helper *hlpr;
+	char *tmpname;
 
+	if (max_dcc_channels < 1) {
+		printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n");
+		return -EBUSY;
+	}
+	if (dcc_timeout < 0) {
+		printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n");
+		return -EBUSY;
+	}
+	
 	/* If no port given, default to standard irc port */
 	if (ports[0] == 0)
-		ports[0] = 6667;
+		ports[0] = IRC_PORT;
 
 	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
-		memset(&irc_helpers[i], 0,
+		hlpr = &irc_helpers[i];
+		memset(hlpr, 0,
 		       sizeof(struct ip_conntrack_helper));
-		irc_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
-		irc_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
-		irc_helpers[i].mask.src.u.tcp.port = 0xFFFF;
-		irc_helpers[i].mask.dst.protonum = 0xFFFF;
-		irc_helpers[i].help = help;
+		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
+		hlpr->tuple.dst.protonum = IPPROTO_TCP;
+		hlpr->mask.src.u.tcp.port = 0xFFFF;
+		hlpr->mask.dst.protonum = 0xFFFF;
+		hlpr->max_expected = max_dcc_channels;
+		hlpr->timeout = dcc_timeout;
+		hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
+		hlpr->me = ip_conntrack_irc;
+		hlpr->help = help;
+
+		tmpname = &irc_names[i][0];
+		if (ports[i] == IRC_PORT)
+			sprintf(tmpname, "irc");
+		else
+			sprintf(tmpname, "irc-%d", i);
+		hlpr->name = tmpname;
 
 		DEBUGP("port #%d: %d\n", i, ports[i]);
 
-		ret = ip_conntrack_helper_register(&irc_helpers[i]);
+		ret = ip_conntrack_helper_register(hlpr);
 
 		if (ret) {
 			printk("ip_conntrack_irc: ERROR registering port %d\n",
@@ -272,6 +304,10 @@
 		ip_conntrack_helper_unregister(&irc_helpers[i]);
 	}
 }
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+EXPORT_SYMBOL(ip_irc_lock);
+#endif
 
 module_init(init);
 module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c	Sun Apr 14 12:16:57 2002
+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c	Sun Apr 14 12:16:57 2002
@@ -57,5 +57,5 @@
 struct ip_conntrack_protocol ip_conntrack_generic_protocol
 = { { NULL, NULL }, 0, "unknown",
     generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
-    generic_print_conntrack, established, new, NULL };
+    generic_print_conntrack, established, new, NULL, NULL, NULL };
 
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	Sun Apr 14 12:16:54 2002
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c	Sun Apr 14 12:16:54 2002
@@ -113,4 +113,4 @@
 struct ip_conntrack_protocol ip_conntrack_protocol_icmp
 = { { NULL, NULL }, IPPROTO_ICMP, "icmp",
     icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
-    icmp_print_conntrack, icmp_packet, icmp_new, NULL };
+    icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Sun Apr 14 12:16:58 2002
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	Sun Apr 14 12:16:58 2002
@@ -7,6 +7,9 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+
+#include <net/tcp.h>
+
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/lockhelp.h>
@@ -227,7 +230,19 @@
 	return 1;
 }
 
+static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp,
+			       struct sk_buff **pskb)
+{
+	struct iphdr *iph = (*pskb)->nh.iph;
+	struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
+	unsigned int datalen;
+
+	datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
+
+	return between(exp->seq, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
+}
+
 struct ip_conntrack_protocol ip_conntrack_protocol_tcp
 = { { NULL, NULL }, IPPROTO_TCP, "tcp",
     tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
-    tcp_packet, tcp_new, NULL };
+    tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c	Sun Apr 14 12:16:54 2002
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c	Sun Apr 14 12:16:54 2002
@@ -71,4 +71,4 @@
 struct ip_conntrack_protocol ip_conntrack_protocol_udp
 = { { NULL, NULL }, IPPROTO_UDP, "udp",
     udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
-    udp_packet, udp_new, NULL };
+    udp_packet, udp_new, NULL, NULL, NULL };
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c	Sun Apr 14 12:16:58 2002
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c	Sun Apr 14 12:16:58 2002
@@ -62,7 +62,13 @@
 {
 	unsigned int len;
 
-	len = sprintf(buffer, "EXPECTING: proto=%u ",
+	if (expect->expectant->helper->timeout)
+		len = sprintf(buffer, "EXPECTING: %lu ",
+			      timer_pending(&expect->timeout)
+			      ? (expect->timeout.expires - jiffies)/HZ : 0);
+	else
+		len = sprintf(buffer, "EXPECTING: - ");
+	len += sprintf(buffer + len, "proto=%u ",
 		      expect->tuple.dst.protonum);
 	len += print_tuple(buffer + len, &expect->tuple,
 			   __find_proto(expect->tuple.dst.protonum));
@@ -314,7 +320,7 @@
 {
 	WRITE_LOCK(&ip_conntrack_lock);
 
-	/* find_proto() returns proto_generic in case there is no protocol 
+	/* ip_ct_find_proto() returns proto_generic in case there is no protocol 
 	 * helper. So this should be enough - HW */
 	LIST_DELETE(&protocol_list, proto);
 	WRITE_UNLOCK(&ip_conntrack_lock);
@@ -353,8 +359,12 @@
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
 EXPORT_SYMBOL(ip_ct_selective_cleanup);
 EXPORT_SYMBOL(ip_ct_refresh);
+EXPORT_SYMBOL(ip_ct_find_proto);
+EXPORT_SYMBOL(ip_ct_find_helper);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
+EXPORT_SYMBOL(ip_conntrack_change_expect);
 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
 EXPORT_SYMBOL(ip_conntrack_tuple_taken);
 EXPORT_SYMBOL(ip_ct_gather_frags);
 EXPORT_SYMBOL(ip_conntrack_htable_size);
+EXPORT_SYMBOL(ip_conntrack_lock);
diff -Nru a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c
--- a/net/ipv4/netfilter/ip_fw_compat_masq.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/netfilter/ip_fw_compat_masq.c	Sun Apr 14 12:16:56 2002
@@ -130,7 +130,7 @@
 	struct ip_conntrack *ct;
 	int ret;
 
-	protocol = find_proto(iph->protocol);
+	protocol = ip_ct_find_proto(iph->protocol);
 
 	/* We don't feed packets to conntrack system unless we know
            they're part of an connection already established by an
diff -Nru a/net/ipv4/netfilter/ip_fw_compat_redir.c b/net/ipv4/netfilter/ip_fw_compat_redir.c
--- a/net/ipv4/netfilter/ip_fw_compat_redir.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/netfilter/ip_fw_compat_redir.c	Sun Apr 14 12:16:59 2002
@@ -43,7 +43,7 @@
 		   netplay... */					 \
 		printk("ASSERT: %s:%i(%s)\n",				 \
 		       __FILE__, __LINE__, __FUNCTION__);		 \
-} while(0);
+} while(0)
 #else
 #define IP_NF_ASSERT(x)
 #endif
diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
--- a/net/ipv4/netfilter/ip_nat_core.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/netfilter/ip_nat_core.c	Sun Apr 14 12:16:56 2002
@@ -21,10 +21,14 @@
 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
 
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
 #include <linux/netfilter_ipv4/ip_nat_core.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
 #if 0
@@ -34,6 +38,7 @@
 #endif
 
 DECLARE_RWLOCK(ip_nat_lock);
+DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
 
 /* Calculated at init based on memory size */
 static unsigned int ip_nat_htable_size;
@@ -628,8 +633,9 @@
 	}
 
 	/* If there's a helper, assign it; based on new tuple. */
-	info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
-				 &reply);
+	if (!conntrack->master)
+		info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
+					 &reply);
 
 	/* It's done. */
 	info->initialized |= (1 << HOOK2MANIP(hooknum));
@@ -724,6 +730,21 @@
 #endif
 }
 
+static inline int exp_for_packet(struct ip_conntrack_expect *exp,
+			         struct sk_buff **pskb)
+{
+	struct ip_conntrack_protocol *proto;
+	int ret = 1;
+
+	READ_LOCK(&ip_conntrack_lock);
+	proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
+	if (proto->exp_matches_pkt)
+		ret = proto->exp_matches_pkt(exp, pskb);
+	READ_UNLOCK(&ip_conntrack_lock);
+
+	return ret;
+}
+
 /* Do packet manipulations according to binding. */
 unsigned int
 do_bindings(struct ip_conntrack *ct,
@@ -735,6 +756,7 @@
 	unsigned int i;
 	struct ip_nat_helper *helper;
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	int is_tcp = (*pskb)->nh.iph->protocol == IPPROTO_TCP;
 
 	/* Need nat lock to protect against modification, but neither
 	   conntrack (referenced) and helper (deleted with
@@ -773,11 +795,66 @@
 	READ_UNLOCK(&ip_nat_lock);
 
 	if (helper) {
+		struct ip_conntrack_expect *exp = NULL;
+		struct list_head *cur_item;
+		int ret = NF_ACCEPT;
+
+		DEBUGP("do_bindings: helper existing for (%p)\n", ct);
+
 		/* Always defragged for helpers */
 		IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
 			       & __constant_htons(IP_MF|IP_OFFSET)));
-		return helper->help(ct, info, ctinfo, hooknum, pskb);
-	} else return NF_ACCEPT;
+
+		/* Have to grab read lock before sibling_list traversal */
+		READ_LOCK(&ip_conntrack_lock);
+		list_for_each(cur_item, &ct->sibling_list) { 
+			exp = list_entry(cur_item, struct ip_conntrack_expect, 
+					 expected_list);
+					 
+			/* if this expectation is already established, skip */
+			if (exp->sibling)
+				continue;
+
+			if (exp_for_packet(exp, pskb)) {
+				/* FIXME: May be true multiple times in the case of UDP!! */
+				DEBUGP("calling nat helper (exp=%p) for packet\n",
+					exp);
+				ret = helper->help(ct, exp, info, ctinfo, 
+						   hooknum, pskb);
+				if (ret != NF_ACCEPT) {
+					READ_UNLOCK(&ip_conntrack_lock);
+					return ret;
+				}
+			}
+		}
+		/* Helper might want to manip the packet even when there is no expectation */
+		if (!exp && helper->flags & IP_NAT_HELPER_F_ALWAYS) {
+			DEBUGP("calling nat helper for packet without expectation\n");
+			ret = helper->help(ct, NULL, info, ctinfo, 
+					   hooknum, pskb);
+			if (ret != NF_ACCEPT) {
+				READ_UNLOCK(&ip_conntrack_lock);
+				return ret;
+			}
+		}
+		READ_UNLOCK(&ip_conntrack_lock);
+		
+		/* Adjust sequence number only once per packet 
+		 * (helper is called at all hooks) */
+		if (is_tcp && (hooknum == NF_IP_POST_ROUTING
+			       || hooknum == NF_IP_LOCAL_IN)) {
+			DEBUGP("ip_nat_core: adjusting sequence number\n");
+			/* future: put this in a l4-proto specific function,
+			 * and call this function here. */
+			ip_nat_seq_adjust(*pskb, ct, ctinfo);
+		}
+
+		return ret;
+
+	} else 
+		return NF_ACCEPT;
+
+	/* not reached */
 }
 
 unsigned int
diff -Nru a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
--- a/net/ipv4/netfilter/ip_nat_ftp.c	Sun Apr 14 12:16:55 2002
+++ b/net/ipv4/netfilter/ip_nat_ftp.c	Sun Apr 14 12:16:55 2002
@@ -28,38 +28,30 @@
 
 /* FIXME: Time out? --RR */
 
-static int
+static unsigned int
 ftp_nat_expected(struct sk_buff **pskb,
 		 unsigned int hooknum,
 		 struct ip_conntrack *ct,
-		 struct ip_nat_info *info,
-		 struct ip_conntrack *master,
-		 struct ip_nat_info *masterinfo,
-		 unsigned int *verdict)
+		 struct ip_nat_info *info)
 {
 	struct ip_nat_multi_range mr;
 	u_int32_t newdstip, newsrcip, newip;
-	struct ip_ct_ftp *ftpinfo;
+	struct ip_ct_ftp_expect *exp_ftp_info;
 
+	struct ip_conntrack *master = master_ct(ct);
+	
 	IP_NF_ASSERT(info);
 	IP_NF_ASSERT(master);
-	IP_NF_ASSERT(masterinfo);
 
 	IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
 
 	DEBUGP("nat_expected: We have a connection!\n");
-	/* Master must be an ftp connection */
-	ftpinfo = &master->help.ct_ftp_info;
+	exp_ftp_info = &ct->master->help.exp_ftp_info;
 
 	LOCK_BH(&ip_ftp_lock);
-	if (ftpinfo->is_ftp != 21) {
-		UNLOCK_BH(&ip_ftp_lock);
-		DEBUGP("nat_expected: master not ftp\n");
-		return 0;
-	}
 
-	if (ftpinfo->ftptype == IP_CT_FTP_PORT
-	    || ftpinfo->ftptype == IP_CT_FTP_EPRT) {
+	if (exp_ftp_info->ftptype == IP_CT_FTP_PORT
+	    || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) {
 		/* PORT command: make connection go to the client. */
 		newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
 		newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
@@ -92,11 +84,9 @@
 		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
 		mr.range[0].min = mr.range[0].max
 			= ((union ip_conntrack_manip_proto)
-				{ htons(ftpinfo->port) });
+				{ htons(exp_ftp_info->port) });
 	}
-	*verdict = ip_nat_setup_info(ct, &mr, hooknum);
-
-	return 1;
+	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
 static int
@@ -176,27 +166,22 @@
     [IP_CT_FTP_EPSV] mangle_epsv_packet
 };
 
-static int ftp_data_fixup(const struct ip_ct_ftp *ct_ftp_info,
+static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
 			  struct ip_conntrack *ct,
-			  unsigned int datalen,
 			  struct sk_buff **pskb,
-			  enum ip_conntrack_info ctinfo)
+			  enum ip_conntrack_info ctinfo,
+			  struct ip_conntrack_expect *expect)
 {
 	u_int32_t newip;
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
 	u_int16_t port;
-	struct ip_conntrack_tuple tuple;
-	/* Don't care about source port */
-	const struct ip_conntrack_tuple mask
-		= { { 0xFFFFFFFF, { 0 } },
-		    { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF } };
+	struct ip_conntrack_tuple newtuple;
 
-	memset(&tuple, 0, sizeof(tuple));
 	MUST_BE_LOCKED(&ip_ftp_lock);
-	DEBUGP("FTP_NAT: seq %u + %u in %u + %u\n",
-	       ct_ftp_info->seq, ct_ftp_info->len,
-	       ntohl(tcph->seq), datalen);
+	DEBUGP("FTP_NAT: seq %u + %u in %u\n",
+	       expect->seq, ct_ftp_info->len,
+	       ntohl(tcph->seq));
 
 	/* Change address inside packet to match way we're mapping
 	   this connection. */
@@ -206,29 +191,34 @@
 		   is */
 		newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
 		/* Expect something from client->server */
-		tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-		tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+		newtuple.src.ip = 
+			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
+		newtuple.dst.ip = 
+			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
 	} else {
 		/* PORT command: must be where server thinks client is */
 		newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 		/* Expect something from server->client */
-		tuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
-		tuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
+		newtuple.src.ip = 
+			ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
+		newtuple.dst.ip = 
+			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 	}
-	tuple.dst.protonum = IPPROTO_TCP;
+	newtuple.dst.protonum = IPPROTO_TCP;
+	newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
 
 	/* Try to get same port: if not, try to change it. */
 	for (port = ct_ftp_info->port; port != 0; port++) {
-		tuple.dst.u.tcp.port = htons(port);
+		newtuple.dst.u.tcp.port = htons(port);
 
-		if (ip_conntrack_expect_related(ct, &tuple, &mask, NULL) == 0)
+		if (ip_conntrack_change_expect(expect, &newtuple) == 0)
 			break;
 	}
 	if (port == 0)
 		return 0;
 
 	if (!mangle[ct_ftp_info->ftptype](pskb, newip, port,
-					  ct_ftp_info->seq - ntohl(tcph->seq),
+					  expect->seq - ntohl(tcph->seq),
 					  ct_ftp_info->len, ct, ctinfo))
 		return 0;
 
@@ -236,6 +226,7 @@
 }
 
 static unsigned int help(struct ip_conntrack *ct,
+			 struct ip_conntrack_expect *exp,
 			 struct ip_nat_info *info,
 			 enum ip_conntrack_info ctinfo,
 			 unsigned int hooknum,
@@ -245,13 +236,12 @@
 	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
 	unsigned int datalen;
 	int dir;
-	int score;
-	struct ip_ct_ftp *ct_ftp_info
-		= &ct->help.ct_ftp_info;
-
-	/* Delete SACK_OK on initial TCP SYNs. */
-	if (tcph->syn && !tcph->ack)
-		ip_nat_delete_sack(*pskb, tcph);
+	struct ip_ct_ftp_expect *ct_ftp_info;
+
+	if (!exp)
+		DEBUGP("ip_nat_ftp: no exp!!");
+
+	ct_ftp_info = &exp->help.exp_ftp_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -267,50 +257,34 @@
 	}
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	score = 0;
 	LOCK_BH(&ip_ftp_lock);
-	if (ct_ftp_info->len) {
-		/* If it's in the right range... */
-		score += between(ct_ftp_info->seq, ntohl(tcph->seq),
-				 ntohl(tcph->seq) + datalen);
-		score += between(ct_ftp_info->seq + ct_ftp_info->len,
-				 ntohl(tcph->seq),
-				 ntohl(tcph->seq) + datalen);
-		if (score == 1) {
-			/* Half a match?  This means a partial retransmisison.
-			   It's a cracker being funky. */
-			if (net_ratelimit()) {
-				printk("FTP_NAT: partial packet %u/%u in %u/%u\n",
-				       ct_ftp_info->seq, ct_ftp_info->len,
-				       ntohl(tcph->seq),
-				       ntohl(tcph->seq) + datalen);
-			}
+	/* If it's in the right range... */
+	if (between(exp->seq + ct_ftp_info->len,
+		    ntohl(tcph->seq),
+		    ntohl(tcph->seq) + datalen)) {
+		if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) {
 			UNLOCK_BH(&ip_ftp_lock);
 			return NF_DROP;
-		} else if (score == 2) {
-			if (!ftp_data_fixup(ct_ftp_info, ct, datalen,
-					    pskb, ctinfo)) {
-				UNLOCK_BH(&ip_ftp_lock);
-				return NF_DROP;
-			}
-			/* skb may have been reallocated */
-			iph = (*pskb)->nh.iph;
-			tcph = (void *)iph + iph->ihl*4;
 		}
+	} else {
+		/* Half a match?  This means a partial retransmisison.
+		   It's a cracker being funky. */
+		if (net_ratelimit()) {
+			printk("FTP_NAT: partial packet %u/%u in %u/%u\n",
+			       exp->seq, ct_ftp_info->len,
+			       ntohl(tcph->seq),
+			       ntohl(tcph->seq) + datalen);
+		}
+		UNLOCK_BH(&ip_ftp_lock);
+		return NF_DROP;
 	}
-
 	UNLOCK_BH(&ip_ftp_lock);
 
-	ip_nat_seq_adjust(*pskb, ct, ctinfo);
-
 	return NF_ACCEPT;
 }
 
 static struct ip_nat_helper ftp[MAX_PORTS];
-static char ftp_names[MAX_PORTS][6];
-
-static struct ip_nat_expect ftp_expect
-= { { NULL, NULL }, ftp_nat_expected };
+static char ftp_names[MAX_PORTS][10];
 
 /* Not __exit: called from init() */
 static void fini(void)
@@ -321,49 +295,49 @@
 		DEBUGP("ip_nat_ftp: unregistering port %d\n", ports[i]);
 		ip_nat_helper_unregister(&ftp[i]);
 	}
-
-	ip_nat_expect_unregister(&ftp_expect);
 }
 
 static int __init init(void)
 {
-	int i, ret;
+	int i, ret = 0;
 	char *tmpname;
 
-	ret = ip_nat_expect_register(&ftp_expect);
-	if (ret == 0) {
-		if (ports[0] == 0)
-			ports[0] = 21;
-
-		for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
-
-			memset(&ftp[i], 0, sizeof(struct ip_nat_helper));
-
-			ftp[i].tuple.dst.protonum = IPPROTO_TCP;
-			ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
-			ftp[i].mask.dst.protonum = 0xFFFF;
-			ftp[i].mask.src.u.tcp.port = 0xFFFF;
-			ftp[i].help = help;
-
-			tmpname = &ftp_names[i][0];
-			sprintf(tmpname, "ftp%2.2d", i);
-			ftp[i].name = tmpname;
-
-			DEBUGP("ip_nat_ftp: Trying to register for port %d\n",
-					ports[i]);
-			ret = ip_nat_helper_register(&ftp[i]);
-
-			if (ret) {
-				printk("ip_nat_ftp: error registering helper for port %d\n", ports[i]);
-				fini();
-				return ret;
-			}
-			ports_c++;
-		}
+	if (ports[0] == 0)
+		ports[0] = FTP_PORT;
 
-	} else {
-		ip_nat_expect_unregister(&ftp_expect);
+	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+
+		memset(&ftp[i], 0, sizeof(struct ip_nat_helper));
+
+		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
+		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
+		ftp[i].mask.dst.protonum = 0xFFFF;
+		ftp[i].mask.src.u.tcp.port = 0xFFFF;
+		ftp[i].help = help;
+		ftp[i].me = THIS_MODULE;
+		ftp[i].flags = 0;
+		ftp[i].expect = ftp_nat_expected;
+
+		tmpname = &ftp_names[i][0];
+		if (ports[i] == FTP_PORT)
+			sprintf(tmpname, "ftp");
+		else
+			sprintf(tmpname, "ftp-%d", i);
+		ftp[i].name = tmpname;
+
+		DEBUGP("ip_nat_ftp: Trying to register for port %d\n",
+				ports[i]);
+		ret = ip_nat_helper_register(&ftp[i]);
+
+		if (ret) {
+			printk("ip_nat_ftp: error registering "
+			       "helper for port %d\n", ports[i]);
+			fini();
+			return ret;
+		}
+		ports_c++;
 	}
+
 	return ret;
 }
 
diff -Nru a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
--- a/net/ipv4/netfilter/ip_nat_helper.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/netfilter/ip_nat_helper.c	Sun Apr 14 12:16:56 2002
@@ -1,11 +1,18 @@
 /* ip_nat_mangle.c - generic support functions for NAT helpers 
  *
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
  *
  * distributed under the terms of GNU GPL
+ *
+ * 	14 Jan 2002 Harald Welte <laforge@gnumonks.org>:
+ *		- add support for SACK adjustment 
+ *	14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
+ *		- merge SACK support into newnat API
  */
 #include <linux/version.h>
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/kmod.h>
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/skbuff.h>
@@ -19,6 +26,8 @@
 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
 
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
 #include <linux/netfilter_ipv4/ip_nat_core.h>
@@ -32,7 +41,7 @@
 #define DEBUGP(format, args...)
 #define DUMP_OFFSET(x)
 #endif
-	
+
 DECLARE_LOCK(ip_nat_seqofs_lock);
 			 
 static inline int 
@@ -199,6 +208,103 @@
 	return 1;
 }
 
+/* Adjust one found SACK option including checksum correction */
+static void
+sack_adjust(struct tcphdr *tcph, 
+	    unsigned char *ptr, 
+	    struct ip_nat_seq *natseq)
+{
+	struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
+	int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
+	int i;
+
+	for (i = 0; i < num_sacks; i++, sp++) {
+		u_int32_t new_start_seq, new_end_seq;
+
+		if (after(ntohl(sp->start_seq) - natseq->offset_before,
+			  natseq->correction_pos))
+			new_start_seq = ntohl(sp->start_seq) 
+					- natseq->offset_after;
+		else
+			new_start_seq = ntohl(sp->start_seq) 
+					- natseq->offset_before;
+		new_start_seq = htonl(new_start_seq);
+
+		if (after(ntohl(sp->end_seq) - natseq->offset_before,
+			  natseq->correction_pos))
+			new_end_seq = ntohl(sp->end_seq)
+				      - natseq->offset_after;
+		else
+			new_end_seq = ntohl(sp->end_seq)
+				      - natseq->offset_before;
+		new_end_seq = htonl(new_end_seq);
+
+		DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
+			ntohl(sp->start_seq), new_start_seq,
+			ntohl(sp->end_seq), new_end_seq);
+
+		tcph->check = 
+			ip_nat_cheat_check(~sp->start_seq, new_start_seq,
+					   ip_nat_cheat_check(~sp->end_seq, 
+						   	      new_end_seq,
+							      tcph->check));
+
+		sp->start_seq = new_start_seq;
+		sp->end_seq = new_end_seq;
+	}
+}
+			
+
+/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */
+static inline int
+ip_nat_sack_adjust(struct sk_buff *skb,
+			struct ip_conntrack *ct,
+			enum ip_conntrack_info ctinfo)
+{
+	struct iphdr *iph;
+	struct tcphdr *tcph;
+	unsigned char *ptr;
+	int length, dir, sack_adjusted = 0;
+
+	iph = skb->nh.iph;
+	tcph = (void *)iph + iph->ihl*4;
+	length = (tcph->doff*4)-sizeof(struct tcphdr);
+	ptr = (unsigned char *)(tcph+1);
+
+	dir = CTINFO2DIR(ctinfo);
+
+	while (length > 0) {
+		int opcode = *ptr++;
+		int opsize;
+
+		switch (opcode) {
+		case TCPOPT_EOL:
+			return !sack_adjusted;
+		case TCPOPT_NOP:
+			length--;
+			continue;
+		default:
+			opsize = *ptr++;
+			if (opsize > length) /* no partial opts */
+				return !sack_adjusted;
+			if (opcode == TCPOPT_SACK) {
+				/* found SACK */
+				if((opsize >= (TCPOLEN_SACK_BASE
+					       +TCPOLEN_SACK_PERBLOCK)) &&
+				   !((opsize - TCPOLEN_SACK_BASE)
+				     % TCPOLEN_SACK_PERBLOCK))
+					sack_adjust(tcph, ptr-2,
+						    &ct->nat.info.seq[!dir]);
+				
+				sack_adjusted = 1;
+			}
+			ptr += opsize-2;
+			length -= opsize;
+		}
+	}
+	return !sack_adjusted;
+}
+
 /* TCP sequence number adjustment */
 int 
 ip_nat_seq_adjust(struct sk_buff *skb, 
@@ -243,51 +349,9 @@
 	tcph->seq = newseq;
 	tcph->ack_seq = newack;
 
-	return 0;
-}
-
-/* Grrr... SACK.  Fuck me even harder.  Don't want to fix it on the
-   fly, so blow it away. */
-void
-ip_nat_delete_sack(struct sk_buff *skb, struct tcphdr *tcph)
-{
-	unsigned int i;
-	u_int8_t *opt = (u_int8_t *)tcph;
-
-	DEBUGP("Seeking SACKPERM in SYN packet (doff = %u).\n",
-	       tcph->doff * 4);
-	for (i = sizeof(struct tcphdr); i < tcph->doff * 4;) {
-		DEBUGP("%u ", opt[i]);
-		switch (opt[i]) {
-		case TCPOPT_NOP:
-		case TCPOPT_EOL:
-			i++;
-			break;
+	ip_nat_sack_adjust(skb, ct, ctinfo);
 
-		case TCPOPT_SACK_PERM:
-			goto found_opt;
-
-		default:
-			/* Worst that can happen: it will take us over. */
-			i += opt[i+1] ?: 1;
-		}
-	}
-	DEBUGP("\n");
-	return;
-
- found_opt:
-	DEBUGP("\n");
-	DEBUGP("Found SACKPERM at offset %u.\n", i);
-
-	/* Must be within TCP header, and valid SACK perm. */
-	if (i + opt[i+1] <= tcph->doff*4 && opt[i+1] == 2) {
-		/* Replace with NOPs. */
-		tcph->check
-			= ip_nat_cheat_check(*((u_int16_t *)(opt + i))^0xFFFF,
-					     (TCPOPT_NOP<<8)|TCPOPT_NOP, tcph->check);
-		opt[i] = opt[i+1] = TCPOPT_NOP;
-	}
-	else DEBUGP("Something wrong with SACK_PERM.\n");
+	return 0;
 }
 
 static inline int
@@ -297,10 +361,51 @@
 	return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
 }
 
+#define MODULE_MAX_NAMELEN		32
+
 int ip_nat_helper_register(struct ip_nat_helper *me)
 {
 	int ret = 0;
 
+	if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) {
+		struct ip_conntrack_helper *ct_helper;
+		
+		if ((ct_helper = ip_ct_find_helper(&me->tuple))
+		    && ct_helper->me) {
+			__MOD_INC_USE_COUNT(ct_helper->me);
+		} else {
+
+			/* We are a NAT helper for protocol X.  If we need
+			 * respective conntrack helper for protoccol X, compute
+			 * conntrack helper name and try to load module */
+			char name[MODULE_MAX_NAMELEN];
+			const char *tmp = me->me->name;
+			
+			if (strlen(tmp) + 6 > MODULE_MAX_NAMELEN) {
+				printk(__FUNCTION__ ": unable to "
+				       "compute conntrack helper name "
+				       "from %s\n", tmp);
+				return -EBUSY;
+			}
+			tmp += 6;
+			sprintf(name, "ip_conntrack%s", tmp);
+#ifdef CONFIG_KMOD
+			if (!request_module(name)
+			    && (ct_helper = ip_ct_find_helper(&me->tuple))
+			    && ct_helper->me) {
+				__MOD_INC_USE_COUNT(ct_helper->me);
+			} else {
+				printk("unable to load module %s\n", name);
+				return -EBUSY;
+			}
+#else
+			printk("unable to load module %s automatically "
+			       "because kernel was compiled without kernel "
+			       "module loader support\n", name);
+			return -EBUSY;
+#endif
+		}
+	}
 	WRITE_LOCK(&ip_nat_lock);
 	if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple))
 		ret = -EBUSY;
@@ -327,8 +432,14 @@
 
 void ip_nat_helper_unregister(struct ip_nat_helper *me)
 {
+	int found = 0;
+	
 	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&helpers, me);
+	/* Autoloading conntrack helper might have failed */
+	if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) {
+		LIST_DELETE(&helpers, me);
+		found = 1;
+	}
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	/* Someone could be still looking at the helper in a bh. */
@@ -344,5 +455,19 @@
 	   worse. --RR */
 	ip_ct_selective_cleanup(kill_helper, me);
 
-	MOD_DEC_USE_COUNT;
+	if (found)
+		MOD_DEC_USE_COUNT;
+
+	/* If we are no standalone NAT helper, we need to decrement usage count
+	 * on our conntrack helper */
+	if (me->me && !(me->flags & IP_NAT_HELPER_F_STANDALONE)) {
+		struct ip_conntrack_helper *ct_helper;
+		
+		if ((ct_helper = ip_ct_find_helper(&me->tuple))
+		    && ct_helper->me) {
+			__MOD_DEC_USE_COUNT(ct_helper->me);
+		} else 
+			printk(__FUNCTION__ ": unable to decrement usage count"
+			       " of conntrack helper %s\n", me->me->name);
+	}
 }
diff -Nru a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
--- a/net/ipv4/netfilter/ip_nat_irc.c	Sun Apr 14 12:17:00 2002
+++ b/net/ipv4/netfilter/ip_nat_irc.c	Sun Apr 14 12:17:00 2002
@@ -51,42 +51,29 @@
 
 /* FIXME: Time out? --RR */
 
-static int
+static unsigned int
 irc_nat_expected(struct sk_buff **pskb,
 		 unsigned int hooknum,
 		 struct ip_conntrack *ct,
-		 struct ip_nat_info *info,
-		 struct ip_conntrack *master,
-		 struct ip_nat_info *masterinfo, unsigned int *verdict)
+		 struct ip_nat_info *info)
 {
 	struct ip_nat_multi_range mr;
 	u_int32_t newdstip, newsrcip, newip;
-	struct ip_ct_irc *ircinfo;
+
+	struct ip_conntrack *master = master_ct(ct);
 
 	IP_NF_ASSERT(info);
 	IP_NF_ASSERT(master);
-	IP_NF_ASSERT(masterinfo);
 
 	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
 
 	DEBUGP("nat_expected: We have a connection!\n");
 
-	/* Master must be an irc connection */
-	ircinfo = &master->help.ct_irc_info;
-	LOCK_BH(&ip_irc_lock);
-	if (ircinfo->is_irc != IP_CONNTR_IRC) {
-		UNLOCK_BH(&ip_irc_lock);
-		DEBUGP("nat_expected: master not irc\n");
-		return 0;
-	}
-
 	newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
 	newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
 	DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
 	       NIPQUAD(newsrcip), NIPQUAD(newdstip));
 
-	UNLOCK_BH(&ip_irc_lock);
-
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
 		newip = newsrcip;
 	else
@@ -99,16 +86,14 @@
 	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
 	mr.range[0].min_ip = mr.range[0].max_ip = newip;
 
-	*verdict = ip_nat_setup_info(ct, &mr, hooknum);
-
-	return 1;
+	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
-static int irc_data_fixup(const struct ip_ct_irc *ct_irc_info,
+static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
 			  struct ip_conntrack *ct,
-			  unsigned int datalen,
 			  struct sk_buff **pskb,
-			  enum ip_conntrack_info ctinfo)
+			  enum ip_conntrack_info ctinfo,
+			  struct ip_conntrack_expect *expect)
 {
 	u_int32_t newip;
 	struct ip_conntrack_tuple t;
@@ -121,9 +106,9 @@
 
 	MUST_BE_LOCKED(&ip_irc_lock);
 
-	DEBUGP("IRC_NAT: info (seq %u + %u) packet(seq %u + %u)\n",
-	       ct_irc_info->seq, ct_irc_info->len,
-	       ntohl(tcph->seq), datalen);
+	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
+	       expect->seq, ct_irc_info->len,
+	       ntohl(tcph->seq));
 
 	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 
@@ -133,13 +118,11 @@
 	   only set in ip_conntrack_irc, with ip_irc_lock held
 	   writable */
 
-	t = ct->expected.tuple;
+	t = expect->tuple;
 	t.dst.ip = newip;
 	for (port = ct_irc_info->port; port != 0; port++) {
 		t.dst.u.tcp.port = htons(port);
-		if (ip_conntrack_expect_related(ct, &t,
-						&ct->expected.mask,
-						NULL) == 0) {
+		if (ip_conntrack_change_expect(expect, &t) == 0) {
 			DEBUGP("using port %d", port);
 			break;
 		}
@@ -166,26 +149,28 @@
 	       buffer, NIPQUAD(newip), port);
 
 	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
-					ct_irc_info->seq - ntohl(tcph->seq),
+					expect->seq - ntohl(tcph->seq),
 					ct_irc_info->len, buffer, 
 					strlen(buffer));
 }
 
 static unsigned int help(struct ip_conntrack *ct,
+			 struct ip_conntrack_expect *exp,
 			 struct ip_nat_info *info,
 			 enum ip_conntrack_info ctinfo,
-			 unsigned int hooknum, struct sk_buff **pskb)
+			 unsigned int hooknum, 
+			 struct sk_buff **pskb)
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
 	unsigned int datalen;
 	int dir;
-	int score;
-	struct ip_ct_irc *ct_irc_info = &ct->help.ct_irc_info;
+	struct ip_ct_irc_expect *ct_irc_info;
 
-	/* Delete SACK_OK on initial TCP SYNs. */
-	if (tcph->syn && !tcph->ack)
-		ip_nat_delete_sack(*pskb, tcph);
+	if (!exp)
+		DEBUGP("ip_nat_irc: no exp!!");
+		
+	ct_irc_info = &exp->help.exp_irc_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -202,55 +187,35 @@
 	DEBUGP("got beyond not touching\n");
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	score = 0;
 	LOCK_BH(&ip_irc_lock);
-	if (ct_irc_info->len) {
-		DEBUGP("got beyond ct_irc_info->len\n");
-
-		/* If it's in the right range... */
-		score += between(ct_irc_info->seq, ntohl(tcph->seq),
-				 ntohl(tcph->seq) + datalen);
-		score += between(ct_irc_info->seq + ct_irc_info->len,
-				 ntohl(tcph->seq),
-				 ntohl(tcph->seq) + datalen);
-		if (score == 1) {
-			/* Half a match?  This means a partial retransmisison.
-			   It's a cracker being funky. */
-			if (net_ratelimit()) {
-				printk
-				    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-				     ct_irc_info->seq, ct_irc_info->len,
-				     ntohl(tcph->seq),
-				     ntohl(tcph->seq) + datalen);
-			}
+	/* Check wether the whole IP/address pattern is carried in the payload */
+	if (between(exp->seq + ct_irc_info->len,
+		    ntohl(tcph->seq),
+		    ntohl(tcph->seq) + datalen)) {
+		if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
 			UNLOCK_BH(&ip_irc_lock);
 			return NF_DROP;
-		} else if (score == 2) {
-			DEBUGP("IRC_NAT: score=2, calling fixup\n");
-			if (!irc_data_fixup(ct_irc_info, ct, datalen,
-					    pskb, ctinfo)) {
-				UNLOCK_BH(&ip_irc_lock);
-				return NF_DROP;
-			}
-			/* skb may have been reallocated */
-			iph = (*pskb)->nh.iph;
-			tcph = (void *) iph + iph->ihl * 4;
 		}
+	} else { 
+		/* Half a match?  This means a partial retransmisison.
+		   It's a cracker being funky. */
+		if (net_ratelimit()) {
+			printk
+			    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
+			     exp->seq, ct_irc_info->len,
+			     ntohl(tcph->seq),
+			     ntohl(tcph->seq) + datalen);
+		}
+		UNLOCK_BH(&ip_irc_lock);
+		return NF_DROP;
 	}
-
 	UNLOCK_BH(&ip_irc_lock);
 
-	ip_nat_seq_adjust(*pskb, ct, ctinfo);
-
 	return NF_ACCEPT;
 }
 
 static struct ip_nat_helper ip_nat_irc_helpers[MAX_PORTS];
-static char ip_nih_names[MAX_PORTS][6];
-
-static struct ip_nat_expect irc_expect
-    = { {NULL, NULL}, irc_nat_expected };
-
+static char irc_names[MAX_PORTS][10];
 
 /* This function is intentionally _NOT_ defined as  __exit, because
  * it is needed by init() */
@@ -262,52 +227,54 @@
 		DEBUGP("ip_nat_irc: unregistering helper for port %d\n",
 		       ports[i]);
 		ip_nat_helper_unregister(&ip_nat_irc_helpers[i]);
-	}
-	ip_nat_expect_unregister(&irc_expect);
+	} 
 }
+
 static int __init init(void)
 {
-	int ret;
+	int ret = 0;
 	int i;
 	struct ip_nat_helper *hlpr;
 	char *tmpname;
 
-	ret = ip_nat_expect_register(&irc_expect);
-	if (ret == 0) {
-
-		if (ports[0] == 0) {
-			ports[0] = 6667;
-		}
+	if (ports[0] == 0) {
+		ports[0] = IRC_PORT;
+	}
 
-		for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
-			hlpr = &ip_nat_irc_helpers[i];
-			memset(hlpr, 0,
-			       sizeof(struct ip_nat_helper));
-
-			hlpr->tuple.dst.protonum = IPPROTO_TCP;
-			hlpr->tuple.src.u.tcp.port = htons(ports[i]);
-			hlpr->mask.src.u.tcp.port = 0xFFFF;
-			hlpr->mask.dst.protonum = 0xFFFF;
-			hlpr->help = help;
-
-			tmpname = &ip_nih_names[i][0];
-			sprintf(tmpname, "irc%2.2d", i);
-
-			hlpr->name = tmpname;
-			DEBUGP
-			    ("ip_nat_irc: Trying to register helper for port %d: name %s\n",
-			     ports[i], hlpr->name);
-			ret = ip_nat_helper_register(hlpr);
-
-			if (ret) {
-				printk
-				    ("ip_nat_irc: error registering helper for port %d\n",
-				     ports[i]);
-				fini();
-				return 1;
-			}
-			ports_c++;
+	for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
+		hlpr = &ip_nat_irc_helpers[i];
+		memset(hlpr, 0,
+		       sizeof(struct ip_nat_helper));
+
+		hlpr->tuple.dst.protonum = IPPROTO_TCP;
+		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
+		hlpr->mask.src.u.tcp.port = 0xFFFF;
+		hlpr->mask.dst.protonum = 0xFFFF;
+		hlpr->help = help;
+		hlpr->flags = 0;
+		hlpr->me = THIS_MODULE;
+		hlpr->expect = irc_nat_expected;
+
+		tmpname = &irc_names[i][0];
+		if (ports[i] == IRC_PORT)
+			sprintf(tmpname, "irc");
+		else
+			sprintf(tmpname, "irc-%d", i);
+		hlpr->name = tmpname;
+
+		DEBUGP
+		    ("ip_nat_irc: Trying to register helper for port %d: name %s\n",
+		     ports[i], hlpr->name);
+		ret = ip_nat_helper_register(hlpr);
+
+		if (ret) {
+			printk
+			    ("ip_nat_irc: error registering helper for port %d\n",
+			     ports[i]);
+			fini();
+			return 1;
 		}
+		ports_c++;
 	}
 	return ret;
 }
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c	Sun Apr 14 12:16:54 2002
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c	Sun Apr 14 12:16:54 2002
@@ -4,7 +4,6 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/if.h>
-
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_nat_protocol.h>
diff -Nru a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
--- a/net/ipv4/netfilter/ip_nat_proto_unknown.c	Sun Apr 14 12:16:54 2002
+++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c	Sun Apr 14 12:16:54 2002
@@ -1,5 +1,5 @@
 /* The "unknown" protocol.  This is what is used for protocols we
- * don't understand.  It's returned by find_proto().
+ * don't understand.  It's returned by ip_ct_find_proto().
  */
 
 #include <linux/types.h>
diff -Nru a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
--- a/net/ipv4/netfilter/ip_nat_rule.c	Sun Apr 14 12:16:58 2002
+++ b/net/ipv4/netfilter/ip_nat_rule.c	Sun Apr 14 12:16:58 2002
@@ -106,8 +106,6 @@
 = { { NULL, NULL }, "nat", &nat_initial_table.repl,
     NAT_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE };
 
-LIST_HEAD(nat_expect_list);
-
 /* Source NAT */
 static unsigned int ipt_snat_target(struct sk_buff **pskb,
 				    unsigned int hooknum,
@@ -254,19 +252,6 @@
 	return ip_nat_setup_info(conntrack, &mr, hooknum);
 }
 
-static inline int call_expect(const struct ip_nat_expect *i,
-			      struct sk_buff **pskb,
-			      unsigned int hooknum,
-			      struct ip_conntrack *ct,
-			      struct ip_nat_info *info,
-			      struct ip_conntrack *master,
-			      struct ip_nat_info *masterinfo,
-			      unsigned int *verdict)
-{
-	return i->expect(pskb, hooknum, ct, info, master, masterinfo,
-			 verdict);
-}
-
 int ip_nat_rule_find(struct sk_buff **pskb,
 		     unsigned int hooknum,
 		     const struct net_device *in,
@@ -276,41 +261,14 @@
 {
 	int ret;
 
-	/* Master won't vanish while this ctrack still alive */
-	if (ct->master.master) {
-		struct ip_conntrack *master;
-
-		master = (struct ip_conntrack *)ct->master.master;
-		if (LIST_FIND(&nat_expect_list,
-			      call_expect,
-			      struct ip_nat_expect *,
-			      pskb, hooknum, ct, info,
-			      master, &master->nat.info, &ret))
-			return ret;
-	}
 	ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL);
+
 	if (ret == NF_ACCEPT) {
 		if (!(info->initialized & (1 << HOOK2MANIP(hooknum))))
 			/* NUL mapping */
 			ret = alloc_null_binding(ct, info, hooknum);
 	}
 	return ret;
-}
-
-int ip_nat_expect_register(struct ip_nat_expect *expect)
-{
-	WRITE_LOCK(&ip_nat_lock);
-	list_prepend(&nat_expect_list, expect);
-	WRITE_UNLOCK(&ip_nat_lock);
-
-	return 0;
-}
-
-void ip_nat_expect_unregister(struct ip_nat_expect *expect)
-{
-	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&nat_expect_list, expect);
-	WRITE_UNLOCK(&ip_nat_lock);
 }
 
 static struct ipt_target ipt_snat_reg
diff -Nru a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c	Sun Apr 14 12:16:56 2002
@@ -1244,6 +1244,7 @@
  * NAT helper function, packets arrive here from NAT code.
  */
 static unsigned int nat_help(struct ip_conntrack *ct,
+			     struct ip_conntrack_expect *exp,
                              struct ip_nat_info *info,
                              enum ip_conntrack_info ctinfo,
                              unsigned int hooknum,
@@ -1304,19 +1305,27 @@
 	return NF_DROP;
 }
 
-static struct ip_nat_helper snmp = { { NULL, NULL },
+static struct ip_nat_helper snmp = { 
+	{ NULL, NULL },
+	"snmp",
+	IP_NAT_HELPER_F_STANDALONE,
+	THIS_MODULE,
 	{ { 0, { __constant_htons(SNMP_PORT) } },
 	  { 0, { 0 }, IPPROTO_UDP } },
 	{ { 0, { 0xFFFF } },
 	  { 0, { 0 }, 0xFFFF } },
-	  nat_help, "snmp" };
+	nat_help, NULL };
  
-static struct ip_nat_helper snmp_trap = { { NULL, NULL },
+static struct ip_nat_helper snmp_trap = { 
+	{ NULL, NULL },
+	"snmp_trap",
+	IP_NAT_HELPER_F_STANDALONE,
+	THIS_MODULE,
 	{ { 0, { __constant_htons(SNMP_TRAP_PORT) } },
 	  { 0, { 0 }, IPPROTO_UDP } },
 	{ { 0, { 0xFFFF } },
 	  { 0, { 0 }, 0xFFFF } },
-	nat_help, "snmp_trap" };
+	nat_help, NULL };
 
 /*****************************************************************************
  *
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/netfilter/ip_nat_standalone.c	Sun Apr 14 12:16:56 2002
@@ -5,7 +5,12 @@
 */
 
 /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
-   Public Licence. */
+ * Public Licence.
+ *
+ * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
+ * 	- new API and handling of conntrack/nat helpers
+ * 	- now capable of multiple expectations for one master
+ * */
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -45,6 +50,15 @@
 			         : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN"  \
 				    : "*ERROR*")))
 
+static inline int call_expect(struct ip_conntrack *master,
+			      struct sk_buff **pskb,
+			      unsigned int hooknum,
+			      struct ip_conntrack *ct,
+			      struct ip_nat_info *info)
+{
+	return master->nat.info.helper->expect(pskb, hooknum, ct, info);
+}
+
 static unsigned int
 ip_nat_fn(unsigned int hooknum,
 	  struct sk_buff **pskb,
@@ -111,8 +125,16 @@
 			int in_hashes = info->initialized;
 			unsigned int ret;
 
-			ret = ip_nat_rule_find(pskb, hooknum, in, out,
-					       ct, info);
+			if (ct->master
+			    && master_ct(ct)->nat.info.helper
+			    && master_ct(ct)->nat.info.helper->expect) {
+				ret = call_expect(master_ct(ct), pskb, 
+						  hooknum, ct, info);
+			} else {
+				ret = ip_nat_rule_find(pskb, hooknum, in, out,
+						       ct, info);
+			}
+
 			if (ret != NF_ACCEPT) {
 				WRITE_UNLOCK(&ip_nat_lock);
 				return ret;
@@ -335,11 +357,7 @@
 EXPORT_SYMBOL(ip_nat_protocol_unregister);
 EXPORT_SYMBOL(ip_nat_helper_register);
 EXPORT_SYMBOL(ip_nat_helper_unregister);
-EXPORT_SYMBOL(ip_nat_expect_register);
-EXPORT_SYMBOL(ip_nat_expect_unregister);
 EXPORT_SYMBOL(ip_nat_cheat_check);
 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
-EXPORT_SYMBOL(ip_nat_seq_adjust);
-EXPORT_SYMBOL(ip_nat_delete_sack);
 EXPORT_SYMBOL(ip_nat_used_tuple);
 MODULE_LICENSE("GPL");
diff -Nru a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
--- a/net/ipv4/netfilter/ip_queue.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/netfilter/ip_queue.c	Sun Apr 14 12:16:59 2002
@@ -464,7 +464,7 @@
 	return netlink_unicast(nfnl, skb, nlq->peer.pid, MSG_DONTWAIT);
 }
 
-#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0);
+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
 
 static __inline__ void netlink_receive_user_skb(struct sk_buff *skb)
 {
diff -Nru a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
--- a/net/ipv4/netfilter/ipt_ULOG.c	Sun Apr 14 12:16:57 2002
+++ b/net/ipv4/netfilter/ipt_ULOG.c	Sun Apr 14 12:16:57 2002
@@ -61,7 +61,7 @@
 #define DEBUGP(format, args...)
 #endif
 
-#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0);
+#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format, ## args); } while (0)
 
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IP tables userspace logging module");
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	Sun Apr 14 12:17:00 2002
+++ b/net/ipv4/route.c	Sun Apr 14 12:17:00 2002
@@ -583,7 +583,7 @@
 	if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
 		goto out;
 	if (net_ratelimit())
-		printk("dst cache overflow\n");
+		printk(KERN_WARNING "dst cache overflow\n");
 	return 1;
 
 work_done:
@@ -657,7 +657,7 @@
 			}
 
 			if (net_ratelimit())
-				printk("Neighbour table overflow.\n");
+				printk(KERN_WARNING "Neighbour table overflow.\n");
 			rt_drop(rt);
 			return -ENOBUFS;
 		}
@@ -667,8 +667,8 @@
 #if RT_CACHE_DEBUG >= 2
 	if (rt->u.rt_next) {
 		struct rtable *trt;
-		printk("rt_cache @%02x: %u.%u.%u.%u", hash,
-				NIPQUAD(rt->rt_dst));
+		printk(KERN_DEBUG "rt_cache @%02x: %u.%u.%u.%u", hash,
+		       NIPQUAD(rt->rt_dst));
 		for (trt = rt->u.rt_next; trt; trt = trt->u.rt_next)
 			printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
 		printk("\n");
@@ -2454,7 +2454,7 @@
 
 #ifdef CONFIG_NET_CLS_ROUTE
 	for (order = 0;
-	     (PAGE_SIZE << order) < 256 * sizeof(ip_rt_acct) * NR_CPUS; order++)
+	     (PAGE_SIZE << order) < 256 * sizeof(struct ip_rt_acct) * NR_CPUS; order++)
 		/* NOTHING */;
 	ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);
 	if (!ip_rt_acct)
@@ -2487,7 +2487,7 @@
 	if (!rt_hash_table)
 		panic("Failed to allocate IP route cache hash table\n");
 
-	printk("IP: routing cache hash table of %u buckets, %ldKbytes\n",
+	printk(KERN_INFO "IP: routing cache hash table of %u buckets, %ldKbytes\n",
 	       rt_hash_mask,
 	       (long) (rt_hash_mask * sizeof(struct rt_hash_bucket)) / 1024);
 
diff -Nru a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
--- a/net/ipv4/sysctl_net_ipv4.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/sysctl_net_ipv4.c	Sun Apr 14 12:16:59 2002
@@ -219,6 +219,8 @@
 	 &sysctl_icmp_ratelimit, sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_IPV4_ICMP_RATEMASK, "icmp_ratemask",
 	 &sysctl_icmp_ratemask, sizeof(int), 0644, NULL, &proc_dointvec},
+	{NET_TCP_TW_REUSE, "tcp_tw_reuse",
+	 &sysctl_tcp_tw_reuse, sizeof(int), 0644, NULL, &proc_dointvec},
 	{0}
 };
 
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/tcp.c	Sun Apr 14 12:16:56 2002
@@ -1792,7 +1792,7 @@
 
 #ifdef TCP_DEBUG
 	if (sk->zapped) {
-		printk("TCP: double destroy sk=%p\n", sk);
+		printk(KERN_DEBUG "TCP: double destroy sk=%p\n", sk);
 		sock_hold(sk);
 	}
 	sk->zapped = 1;
@@ -2558,7 +2558,7 @@
 		sysctl_tcp_rmem[2] = 2*43689;
 	}
 
-	printk("TCP: Hash tables configured (established %d bind %d)\n",
+	printk(KERN_INFO "TCP: Hash tables configured (established %d bind %d)\n",
 	       tcp_ehash_size<<1, tcp_bhash_size);
 
 	tcpdiag_init();
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/tcp_input.c	Sun Apr 14 12:16:56 2002
@@ -124,9 +124,6 @@
 	len = skb->len;
 	if (len >= tp->ack.rcv_mss) {
 		tp->ack.rcv_mss = len;
-		/* Dubious? Rather, it is final cut. 8) */
-		if (tcp_flag_word(skb->h.th)&TCP_REMNANT)
-			tp->ack.pending |= TCP_ACK_PUSHED;
 	} else {
 		/* Otherwise, we make more careful check taking into account,
 		 * that SACKs block is variable.
@@ -463,7 +460,7 @@
 		if (after(tp->snd_una, tp->rtt_seq)) {
 			if (tp->mdev_max < tp->rttvar)
 				tp->rttvar -= (tp->rttvar-tp->mdev_max)>>2;
-			tp->rtt_seq = tp->snd_una;
+			tp->rtt_seq = tp->snd_nxt;
 			tp->mdev_max = TCP_RTO_MIN;
 		}
 	} else {
@@ -1769,6 +1766,7 @@
 			acked |= FLAG_DATA_ACKED;
 		} else {
 			acked |= FLAG_SYN_ACKED;
+			tp->retrans_stamp = 0;
 		}
 
 		if (sacked) {
@@ -3873,6 +3871,7 @@
 	switch (sk->state) {
 	case TCP_CLOSE_WAIT:
 	case TCP_CLOSING:
+	case TCP_LAST_ACK:
 		if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
 			break;
 	case TCP_FIN_WAIT1:
@@ -3890,7 +3889,6 @@
 			}
 		}
 		/* Fall through */
-	case TCP_LAST_ACK:
 	case TCP_ESTABLISHED: 
 		tcp_data_queue(sk, skb);
 		queued = 1;
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	Sun Apr 14 12:16:57 2002
+++ b/net/ipv4/tcp_ipv4.c	Sun Apr 14 12:16:57 2002
@@ -64,6 +64,8 @@
 #include <linux/ipsec.h>
 
 extern int sysctl_ip_dynaddr;
+extern int sysctl_ip_default_ttl;
+int sysctl_tcp_tw_reuse = 0;
 
 /* Check TCP sequence numbers in ICMP packets. */
 #define ICMP_MIN_LENGTH 8
@@ -163,18 +165,18 @@
 	local_bh_enable();
 }
 
-static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, unsigned short snum) 
-{ 
-	inet_sk(sk)->num = snum; 
+static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, unsigned short snum)
+{
+	inet_sk(sk)->num = snum;
 	if ((sk->bind_next = tb->owners) != NULL)
 		tb->owners->bind_pprev = &sk->bind_next;
 	tb->owners = sk;
 	sk->bind_pprev = &tb->owners;
 	sk->prev = (struct sock *) tb;
-} 
+}
 
 static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
-{ 
+{
 	struct inet_opt *inet = inet_sk(sk);
 	struct sock *sk2 = tb->owners;
 	int sk_reuse = sk->reuse;
@@ -193,8 +195,8 @@
 			}
 		}
 	}
-	return sk2 != NULL; 
-} 
+	return sk2 != NULL;
+}
 
 /* Obtain a reference to a local port for the given sock,
  * if snum is zero it means select any available local port.
@@ -247,12 +249,14 @@
 				break;
 	}
 	if (tb != NULL && tb->owners != NULL) {
-		if (tb->fastreuse != 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
+		if (sk->reuse > 1)
+			goto success;
+		if (tb->fastreuse > 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
 			goto success;
 		} else {
-			ret = 1; 
+			ret = 1;
 			if (tcp_bind_conflict(sk, tb))
-				goto fail_unlock; 
+				goto fail_unlock;
 		}
 	}
 	ret = 1;
@@ -269,7 +273,7 @@
 		tb->fastreuse = 0;
 success:
 	if (sk->prev == NULL)
-		tcp_bind_hash(sk, tb, snum); 
+		tcp_bind_hash(sk, tb, snum);
 	BUG_TRAP(sk->prev == (struct sock *) tb);
  	ret = 0;
 
@@ -341,13 +345,13 @@
 	}
 }
 
-static __inline__ void __tcp_v4_hash(struct sock *sk)
+static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
 {
 	struct sock **skp;
 	rwlock_t *lock;
 
 	BUG_TRAP(sk->pprev==NULL);
-	if(sk->state == TCP_LISTEN) {
+	if(listen_possible && sk->state == TCP_LISTEN) {
 		skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
 		lock = &tcp_lhash_lock;
 		tcp_listen_wlock();
@@ -362,7 +366,7 @@
 	sk->pprev = skp;
 	sock_prot_inc_use(sk->prot);
 	write_unlock(lock);
-	if (sk->state == TCP_LISTEN)
+	if (listen_possible && sk->state == TCP_LISTEN)
 		wake_up(&tcp_lhash_wait);
 }
 
@@ -370,7 +374,7 @@
 {
 	if (sk->state != TCP_CLOSE) {
 		local_bh_disable();
-		__tcp_v4_hash(sk);
+		__tcp_v4_hash(sk, 1);
 		local_bh_enable();
 	}
 }
@@ -379,6 +383,9 @@
 {
 	rwlock_t *lock;
 
+	if (!sk->pprev)
+		goto ende;
+
 	if (sk->state == TCP_LISTEN) {
 		local_bh_disable();
 		tcp_listen_wlock();
@@ -397,6 +404,8 @@
 		sock_prot_dec_use(sk->prot);
 	}
 	write_unlock_bh(lock);
+
+ ende:
 	if (sk->state == TCP_LISTEN)
 		wake_up(&tcp_lhash_wait);
 }
@@ -538,20 +547,22 @@
 					  skb->h.th->source);
 }
 
-static int tcp_v4_check_established(struct sock *sk)
+/* called with local bh disabled */
+static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
+				      struct tcp_tw_bucket **twp)
 {
 	struct inet_opt *inet = inet_sk(sk);
 	u32 daddr = inet->rcv_saddr;
 	u32 saddr = inet->daddr;
 	int dif = sk->bound_dev_if;
 	TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
-	__u32 ports = TCP_COMBINED_PORTS(inet->dport, inet->num);
-	int hash = tcp_hashfn(daddr, inet->num, saddr, inet->dport);
+	__u32 ports = TCP_COMBINED_PORTS(inet->dport, lport);
+	int hash = tcp_hashfn(daddr, lport, saddr, inet->dport);
 	struct tcp_ehash_bucket *head = &tcp_ehash[hash];
 	struct sock *sk2, **skp;
 	struct tcp_tw_bucket *tw;
 
-	write_lock_bh(&head->lock);
+	write_lock(&head->lock);
 
 	/* Check TIME-WAIT sockets first. */
 	for(skp = &(head + tcp_ehash_size)->chain; (sk2=*skp) != NULL;
@@ -575,7 +586,9 @@
 			   fall back to VJ's scheme and use initial
 			   timestamp retrieved from peer table.
 			 */
-			if (tw->ts_recent_stamp) {
+			if (tw->ts_recent_stamp &&
+			    (!twp || (sysctl_tcp_tw_reuse &&
+				      xtime.tv_sec - tw->ts_recent_stamp > 1))) {
 				if ((tp->write_seq =
 						tw->snd_nxt + 65535 + 2) == 0)
 					tp->write_seq = 1;
@@ -597,6 +610,10 @@
 	}
 
 unique:
+	/* Must record num and sport now. Otherwise we will see
+	 * in hash table socket with a funny identity. */
+	inet->num = lport;
+	inet->sport = htons(lport);
 	BUG_TRAP(sk->pprev==NULL);
 	if ((sk->next = *skp) != NULL)
 		(*skp)->pprev = &sk->next;
@@ -605,15 +622,16 @@
 	sk->pprev = skp;
 	sk->hashent = hash;
 	sock_prot_inc_use(sk->prot);
-	write_unlock_bh(&head->lock);
+	write_unlock(&head->lock);
 
-	if (tw) {
+	if (twp) {
+		*twp = tw;
+		NET_INC_STATS_BH(TimeWaitRecycled);
+	} else if (tw) {
 		/* Silly. Should hash-dance instead... */
-		local_bh_disable();
 		tcp_tw_deschedule(tw);
 		tcp_timewait_kill(tw);
 		NET_INC_STATS_BH(TimeWaitRecycled);
-		local_bh_enable();
 
 		tcp_tw_put(tw);
 	}
@@ -621,34 +639,120 @@
 	return 0;
 
 not_unique:
-	write_unlock_bh(&head->lock);
+	write_unlock(&head->lock);
 	return -EADDRNOTAVAIL;
 }
 
-/* Hash SYN-SENT socket to established hash table after
- * checking that it is unique. Note, that without kernel lock
- * we MUST make these two operations atomically.
- *
- * Optimization: if it is bound and tcp_bind_bucket has the only
- * owner (us), we need not to scan established bucket.
+/*
+ * Bind a port for a connect operation and hash it.
  */
-
-int tcp_v4_hash_connecting(struct sock *sk)
+static int tcp_v4_hash_connect(struct sock *sk)
 {
 	unsigned short snum = inet_sk(sk)->num;
-	struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(snum)];
-	struct tcp_bind_bucket *tb = (struct tcp_bind_bucket *)sk->prev;
-
+ 	struct tcp_bind_hashbucket *head;
+ 	struct tcp_bind_bucket *tb;
+ 
+ 	if (snum == 0) {
+ 		int rover;
+ 		int low = sysctl_local_port_range[0];
+ 		int high = sysctl_local_port_range[1];
+ 		int remaining = (high - low) + 1;
+ 		struct tcp_tw_bucket *tw = NULL;
+ 
+ 		local_bh_disable();
+ 
+ 		/* TODO. Actually it is not so bad idea to remove
+ 		 * tcp_portalloc_lock before next submission to Linus.
+ 		 * As soon as we touch this place at all it is time to think.
+ 		 *
+ 		 * Now it protects single _advisory_ variable tcp_port_rover,
+ 		 * hence it is mostly useless.
+ 		 * Code will work nicely if we just delete it, but
+ 		 * I am afraid in contented case it will work not better or
+ 		 * even worse: another cpu just will hit the same bucket
+ 		 * and spin there.
+ 		 * So some cpu salt could remove both contention and
+ 		 * memory pingpong. Any ideas how to do this in a nice way?
+ 		 */
+ 		spin_lock(&tcp_portalloc_lock);
+ 		rover = tcp_port_rover;
+ 
+ 		do {
+ 			rover++;
+ 			if ((rover < low) || (rover > high))
+ 				rover = low;
+ 			head = &tcp_bhash[tcp_bhashfn(rover)];
+ 			spin_lock(&head->lock);		
+ 
+ 			/* Does not bother with rcv_saddr checks,
+ 			 * because the established check is already
+ 			 * unique enough.
+ 			 */
+ 			for (tb = head->chain; tb; tb = tb->next) {
+ 				if (tb->port == rover) {
+ 					BUG_TRAP(tb->owners != NULL);
+ 					if (tb->fastreuse >= 0)
+ 						goto next_port;
+ 					if (!__tcp_v4_check_established(sk, rover, &tw))
+ 						goto ok;
+ 					goto next_port;
+ 				}
+ 			}
+ 
+ 			tb = tcp_bucket_create(head, rover);
+ 			if (!tb) {
+ 				spin_unlock(&head->lock);
+ 				break;
+ 			}
+ 			tb->fastreuse = -1;
+ 			goto ok;
+ 
+ 		next_port:
+ 			spin_unlock(&head->lock);
+ 		} while (--remaining > 0);
+ 		tcp_port_rover = rover;
+ 		spin_unlock(&tcp_portalloc_lock);
+ 
+ 		local_bh_enable();
+ 
+ 		return -EADDRNOTAVAIL;
+ 
+ 	ok:
+ 		/* All locks still held and bhs disabled */
+ 		tcp_port_rover = rover;
+ 		spin_unlock(&tcp_portalloc_lock);
+ 
+ 		tcp_bind_hash(sk, tb, rover);
+ 		if (!sk->pprev) {
+ 			inet_sk(sk)->sport = htons(rover);
+ 			__tcp_v4_hash(sk, 0);
+ 		}
+ 		spin_unlock(&head->lock);
+
+ 		if (tw) {
+ 			tcp_tw_deschedule(tw);
+ 			tcp_timewait_kill(tw);
+ 			tcp_tw_put(tw);
+ 		}
+ 
+ 		local_bh_enable();
+ 		return 0;
+ 	}
+ 
+ 	head  = &tcp_bhash[tcp_bhashfn(snum)];
+ 	tb  = (struct tcp_bind_bucket *)sk->prev;
 	spin_lock_bh(&head->lock);
 	if (tb->owners == sk && sk->bind_next == NULL) {
-		__tcp_v4_hash(sk);
+		__tcp_v4_hash(sk, 0);
 		spin_unlock_bh(&head->lock);
 		return 0;
 	} else {
-		spin_unlock_bh(&head->lock);
-
+		int ret;
+		spin_unlock(&head->lock);
 		/* No definite answer... Walk to established hash table */
-		return tcp_v4_check_established(sk);
+		ret = __tcp_v4_check_established(sk, snum, NULL);
+		local_bh_enable();
+		return ret;
 	}
 }
 
@@ -658,7 +762,6 @@
 	struct inet_opt *inet = inet_sk(sk);
 	struct tcp_opt *tp = tcp_sk(sk);
 	struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
-	struct sk_buff *buff;
 	struct rtable *rt;
 	u32 daddr, nexthop;
 	int tmp;
@@ -693,12 +796,6 @@
 	if (!inet->opt || !inet->opt->srr)
 		daddr = rt->rt_dst;
 
-	err = -ENOBUFS;
-	buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
-
-	if (buff == NULL)
-		goto failure;
-
 	if (!inet->saddr)
 		inet->saddr = rt->rt_src;
 	inet->rcv_saddr = inet->saddr;
@@ -729,24 +826,38 @@
 	inet->dport = usin->sin_port;
 	inet->daddr = daddr;
 
+	tp->ext_header_len = 0;
+	if (inet->opt)
+		tp->ext_header_len = inet->opt->optlen;
+
+	tp->mss_clamp = 536;
+
+	/* Socket identity is still unknown (sport may be zero).
+	 * However we set state to SYN-SENT and not releasing socket
+	 * lock select source port, enter ourselves into the hash tables and
+	 * complete initalization after this.
+	 */
+	tcp_set_state(sk, TCP_SYN_SENT);
+	err = tcp_v4_hash_connect(sk);
+	if (err)
+		goto failure;
+
 	if (!tp->write_seq)
 		tp->write_seq = secure_tcp_sequence_number(inet->saddr,
 							   inet->daddr,
 							   inet->sport,
 							   usin->sin_port);
 
-	tp->ext_header_len = 0;
-	if (inet->opt)
-		tp->ext_header_len = inet->opt->optlen;
 	inet->id = tp->write_seq ^ jiffies;
 
-	tp->mss_clamp = 536;
+	err = tcp_connect(sk);
+	if (err)
+		goto failure;
 
-	err = tcp_connect(sk, buff);
-	if (err == 0)
-		return 0;
+	return 0;
 
 failure:
+	tcp_set_state(sk, TCP_CLOSE);
 	__sk_dst_reset(sk);
 	sk->route_caps = 0;
 	inet->dport = 0;
@@ -799,7 +910,6 @@
 	req->expires = jiffies + TCP_TIMEOUT_INIT;
 	req->retrans = 0;
 	req->sk = NULL;
-	req->index = h;
 	req->dl_next = lopt->syn_table[h];
 
 	write_lock(&tp->syn_wait_lock);
@@ -1092,6 +1202,7 @@
 	arg.n_iov = 1;
 	arg.csumoffset = offsetof(struct tcphdr, check) / 2; 
 
+	inet_sk(tcp_socket->sk)->ttl = sysctl_ip_default_ttl;
 	ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
 
 	TCP_INC_STATS_BH(TcpOutSegs);
@@ -1478,7 +1589,7 @@
 	newtp->advmss = dst->advmss;
 	tcp_initialize_rcv_mss(newsk);
 
-	__tcp_v4_hash(newsk);
+	__tcp_v4_hash(newsk, 0);
 	__tcp_inherit_port(sk, newsk);
 
 	return newsk;
@@ -1902,7 +2013,6 @@
 	tcp_v4_rebuild_header,
 	tcp_v4_conn_request,
 	tcp_v4_syn_recv_sock,
-	tcp_v4_hash_connecting,
 	tcp_v4_remember_stamp,
 	sizeof(struct iphdr),
 
diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
--- a/net/ipv4/tcp_minisocks.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/tcp_minisocks.c	Sun Apr 14 12:16:56 2002
@@ -786,6 +786,8 @@
 			newtp->ack.last_seg_size = skb->len-newtp->tcp_header_len;
 		newtp->mss_clamp = req->mss;
 		TCP_ECN_openreq_child(newtp, req);
+
+		TCP_INC_STATS_BH(TcpPassiveOpens);
 	}
 	return newsk;
 }
@@ -849,8 +851,38 @@
 	/* Further reproduces section "SEGMENT ARRIVES"
 	   for state SYN-RECEIVED of RFC793.
 	   It is broken, however, it does not work only
-	   when SYNs are crossed, which is impossible in our
-	   case.
+	   when SYNs are crossed.
+
+	   You would think that SYN crossing is impossible here, since
+	   we should have a SYN_SENT socket (from connect()) on our end,
+	   but this is not true if the crossed SYNs were sent to both
+	   ends by a malicious third party.  We must defend against this,
+	   and to do that we first verify the ACK (as per RFC793, page
+	   36) and reset if it is invalid.  Is this a true full defense?
+	   To convince ourselves, let us consider a way in which the ACK
+	   test can still pass in this 'malicious crossed SYNs' case.
+	   Malicious sender sends identical SYNs (and thus identical sequence
+	   numbers) to both A and B:
+
+		A: gets SYN, seq=7
+		B: gets SYN, seq=7
+
+	   By our good fortune, both A and B select the same initial
+	   send sequence number of seven :-)
+
+		A: sends SYN|ACK, seq=7, ack_seq=8
+		B: sends SYN|ACK, seq=7, ack_seq=8
+
+	   So we are now A eating this SYN|ACK, ACK test passes.  So
+	   does sequence test, SYN is truncated, and thus we consider
+	   it a bare ACK.
+
+	   If tp->defer_accept, we silently drop this bare ACK.  Otherwise,
+	   we create an established connection.  Both ends (listening sockets)
+	   accept the new incoming connection and try to talk to each other. 8-)
+
+	   Note: This case is both harmless, and rare.  Possibility is about the
+	   same as us discovering intelligent life on another plant tomorrow.
 
 	   But generally, we should (RFC lies!) to accept ACK
 	   from SYNACK both here and in tcp_rcv_state_process().
@@ -862,6 +894,22 @@
 	   before attempt to create socket.
 	 */
 
+	/* RFC793 page 36: "If the connection is in any non-synchronized state ...
+	 *                  and the incoming segment acknowledges something not yet
+	 *                  sent (the segment carries an unaccaptable ACK) ...
+	 *                  a reset is sent."
+	 */
+	if (!(flg & TCP_FLAG_ACK))
+		return NULL;
+
+	/* Invalid ACK: reset will be sent by listening socket */
+	if (TCP_SKB_CB(skb)->ack_seq != req->snt_isn+1)
+		return sk;
+	/* Also, it would be not so bad idea to check rcv_tsecr, which
+	 * is essentially ACK extension and too early or too late values
+	 * should cause reset in unsynchronized states.
+	 */
+
 	/* RFC793: "first check sequence number". */
 
 	if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
@@ -890,19 +938,6 @@
 	 */
 	if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN))
 		goto embryonic_reset;
-
-	/* RFC793: "fifth check the ACK field" */
-
-	if (!(flg & TCP_FLAG_ACK))
-		return NULL;
-
-	/* Invalid ACK: reset will be sent by listening socket */
-	if (TCP_SKB_CB(skb)->ack_seq != req->snt_isn+1)
-		return sk;
-	/* Also, it would be not so bad idea to check rcv_tsecr, which
-	 * is essentially ACK extension and too early or too late values
-	 * should cause reset in unsynchronized states.
-	 */
 
 	/* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
 	if (tp->defer_accept && TCP_SKB_CB(skb)->end_seq == req->rcv_isn+1) {
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv4/tcp_output.c	Sun Apr 14 12:16:59 2002
@@ -38,6 +38,7 @@
 
 #include <net/tcp.h>
 
+#include <linux/compiler.h>
 #include <linux/smp_lock.h>
 
 /* People can turn this off for buggy TCP's found in printers etc. */
@@ -1156,14 +1157,14 @@
 	return skb;
 }
 
-int tcp_connect(struct sock *sk, struct sk_buff *buff)
+/* 
+ * Do all connect socket setups that can be done AF independent.
+ */ 
+static inline void tcp_connect_init(struct sock *sk)
 {
 	struct dst_entry *dst = __sk_dst_get(sk);
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	/* Reserve space for headers. */
-	skb_reserve(buff, MAX_TCP_HEADER);
-
 	/* We'll fix this up when we get a response from the other end.
 	 * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
 	 */
@@ -1190,14 +1191,6 @@
 
 	tp->rcv_ssthresh = tp->rcv_wnd;
 
-	/* Socket identity change complete, no longer
-	 * in TCP_CLOSE, so enter ourselves into the
-	 * hash tables.
-	 */
-	tcp_set_state(sk,TCP_SYN_SENT);
-	if (tp->af_specific->hash_connecting(sk))
-		goto err_out;
-
 	sk->err = 0;
 	sk->done = 0;
 	tp->snd_wnd = 0;
@@ -1211,6 +1204,24 @@
 	tp->rto = TCP_TIMEOUT_INIT;
 	tp->retransmits = 0;
 	tcp_clear_retrans(tp);
+}
+
+/*
+ * Build a SYN and send it off.
+ */ 
+int tcp_connect(struct sock *sk)
+{
+	struct tcp_opt *tp = tcp_sk(sk);
+	struct sk_buff *buff;
+
+	tcp_connect_init(sk);
+
+	buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
+	if (unlikely(buff == NULL))
+		return -ENOBUFS;
+
+	/* Reserve space for headers. */
+	skb_reserve(buff, MAX_TCP_HEADER);
 
 	TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
 	TCP_ECN_send_syn(tp, buff);
@@ -1233,11 +1244,6 @@
 	/* Timer for repeating the SYN until an answer. */
 	tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
 	return 0;
-
-err_out:
-	tcp_set_state(sk,TCP_CLOSE);
-	kfree_skb(buff);
-	return -EADDRNOTAVAIL;
 }
 
 /* Send out a delayed ack, the caller does the policy checking
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv4/udp.c	Sun Apr 14 12:16:56 2002
@@ -725,6 +725,8 @@
 	struct inet_opt *inet = inet_sk(sk);
 	struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
 	struct rtable *rt;
+	u32 saddr;
+	int oif;
 	int err;
 
 	
@@ -736,8 +738,16 @@
 
 	sk_dst_reset(sk);
 
-	err = ip_route_connect(&rt, usin->sin_addr.s_addr, inet->saddr,
-			       RT_CONN_FLAGS(sk), sk->bound_dev_if);
+	oif = sk->bound_dev_if;
+	saddr = inet->saddr;
+	if (MULTICAST(usin->sin_addr.s_addr)) {
+		if (!oif)
+			oif = inet->mc_index;
+		if (!saddr)
+			saddr = inet->mc_addr;
+	}
+	err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
+			       RT_CONN_FLAGS(sk), oif);
 	if (err)
 		return err;
 	if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
--- a/net/ipv6/addrconf.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv6/addrconf.c	Sun Apr 14 12:16:59 2002
@@ -62,6 +62,8 @@
 
 #include <asm/uaccess.h>
 
+#define IPV6_MAX_ADDRESSES 16
+
 /* Set to 3 to get tracing... */
 #define ACONF_DEBUG 2
 
@@ -586,6 +588,18 @@
 	return err;
 }
 
+int ipv6_count_addresses(struct inet6_dev *idev)
+{
+	int cnt = 0;
+	struct inet6_ifaddr *ifp;
+
+	read_lock_bh(&idev->lock);
+	for (ifp=idev->addr_list; ifp; ifp=ifp->if_next)
+		cnt++;
+	read_unlock_bh(&idev->lock);
+	return cnt;
+}
+
 int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev)
 {
 	struct inet6_ifaddr * ifp;
@@ -895,8 +909,12 @@
 		ifp = ipv6_get_ifaddr(&addr, dev);
 
 		if (ifp == NULL && valid_lft) {
-			ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len,
-					    addr_type&IPV6_ADDR_SCOPE_MASK, 0);
+			/* Do not allow to create too much of autoconfigured
+			 * addresses; this would be too easy way to crash kernel.
+			 */
+			if (ipv6_count_addresses(in6_dev) < IPV6_MAX_ADDRESSES)
+				ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len,
+						    addr_type&IPV6_ADDR_SCOPE_MASK, 0);
 
 			if (ifp == NULL) {
 				in6_dev_put(in6_dev);
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	Sun Apr 14 12:16:55 2002
+++ b/net/ipv6/ndisc.c	Sun Apr 14 12:16:55 2002
@@ -361,7 +361,7 @@
 	ipv6_addr_copy(&msg->target, solicited_addr);
 
 	if (inc_opt)
-		ndisc_fill_option((void*)&msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, dev->addr_len);
+		ndisc_fill_option(msg->opt, ND_OPT_TARGET_LL_ADDR, dev->dev_addr, dev->addr_len);
 
 	/* checksum */
 	msg->icmph.icmp6_cksum = csum_ipv6_magic(solicited_addr, daddr, len, 
@@ -422,7 +422,7 @@
 	ipv6_addr_copy(&msg->target, solicit);
 
 	if (send_llinfo)
-		ndisc_fill_option((void*)&msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, dev->addr_len);
+		ndisc_fill_option(msg->opt, ND_OPT_SOURCE_LL_ADDR, dev->dev_addr, dev->addr_len);
 
 	/* checksum */
 	msg->icmph.icmp6_cksum = csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -572,6 +572,11 @@
 			printk(KERN_WARNING "ICMP RA: source address is not linklocal\n");
 		return;
 	}
+	if (optlen < 0) {
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP RA: packet too short\n");
+		return;
+	}
 
 	/*
 	 *	set the RA_RECV flag in the interface
@@ -928,7 +933,7 @@
 	u8 *opt;
 
 	opt = skb->h.raw;
-	opt += sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
+	opt += sizeof(struct nd_msg);
 	opt = ndisc_find_option(opt, skb->dev->addr_len+2, skb->tail - opt, ND_OPT_SOURCE_LL_ADDR);
 
 	return neigh_event_ns(&nd_tbl, opt, saddr, skb->dev);
@@ -936,12 +941,11 @@
 
 static __inline__ int ndisc_recv_na(struct neighbour *neigh, struct sk_buff *skb)
 {
-	struct nd_msg *msg = (struct nd_msg *) skb->h.raw;
 	u8 *opt;
+	struct nd_msg *msg = (struct nd_msg*) skb->h.raw;
 
-	opt = skb->h.raw;
-	opt += sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
-	opt = ndisc_find_option(opt, skb->dev->addr_len+2, skb->tail - opt, ND_OPT_TARGET_LL_ADDR);
+	opt = ndisc_find_option(msg->opt, skb->dev->addr_len+2,
+				skb->tail - msg->opt, ND_OPT_TARGET_LL_ADDR);
 
 	return neigh_update(neigh, opt,
 			    msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
@@ -962,7 +966,6 @@
 	struct nd_msg *msg = (struct nd_msg *) skb->h.raw;
 	struct neighbour *neigh;
 	struct inet6_ifaddr *ifp;
-	unsigned int payload_len;
 
 	__skb_push(skb, skb->data-skb->h.raw);
 
@@ -985,11 +988,9 @@
 	 *	(Some checking in ndisc_find_option)
 	 */
 
-	payload_len = ntohs(skb->nh.ipv6h->payload_len);
 	switch (msg->icmph.icmp6_type) {
 	case NDISC_NEIGHBOUR_SOLICITATION:
-		/* XXX: import nd_neighbor_solicit from glibc netinet/icmp6.h */
-		if (payload_len < 8+16) {
+		if (skb->len < sizeof(struct nd_msg)) {
 			if (net_ratelimit())
 				printk(KERN_WARNING "ICMP NS: packet too short\n");
 			return 0;
@@ -1069,12 +1070,13 @@
 
 				neigh = ndisc_recv_ns(saddr, skb);
 
-				if (neigh) {
+				if (neigh || !dev->hard_header) {
 					ndisc_send_na(dev, neigh, saddr, &ifp->addr, 
 						      ifp->idev->cnf.forwarding, 1, 
 						      ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, 
 						      1);
-					neigh_release(neigh);
+					if (neigh)
+						neigh_release(neigh);
 				}
 			}
 			in6_ifa_put(ifp);
@@ -1118,8 +1120,7 @@
 		return 0;
 
 	case NDISC_NEIGHBOUR_ADVERTISEMENT:
-		/* XXX: import nd_neighbor_advert from glibc netinet/icmp6.h */
-		if (payload_len < 16+8 ) {
+		if (skb->len < sizeof(struct nd_msg)) {
 			if (net_ratelimit())
 				printk(KERN_WARNING "ICMP NA: packet too short\n");
 			return 0;
@@ -1180,34 +1181,11 @@
 		break;
 
 	case NDISC_ROUTER_ADVERTISEMENT:
-		/* XXX: import nd_router_advert from glibc netinet/icmp6.h */
-		if (payload_len < 8+4+4) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "ICMP RA: packet too short\n");
-			return 0;
-		}
 		ndisc_router_discovery(skb);
 		break;
 
 	case NDISC_REDIRECT:
-		/* XXX: import nd_redirect from glibc netinet/icmp6.h */
-		if (payload_len < 8+16+16) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "ICMP redirect: packet too short\n");
-			return 0;
-		}
 		ndisc_redirect_rcv(skb);
-		break;
-
-	case NDISC_ROUTER_SOLICITATION:
-		/* No RS support in the kernel, but we do some required checks */
-
-		/* XXX: import nd_router_solicit from glibc netinet/icmp6.h */
-		if (payload_len < 8) {
-			if (net_ratelimit())
-				printk(KERN_WARNING "ICMP RS: packet too short\n");
-			return 0;
-		}
 		break;
 	};
 
diff -Nru a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
--- a/net/ipv6/netfilter/ip6_queue.c	Sun Apr 14 12:16:57 2002
+++ b/net/ipv6/netfilter/ip6_queue.c	Sun Apr 14 12:16:57 2002
@@ -518,7 +518,7 @@
 	return netlink_unicast(nfnl, skb, nlq6->peer.pid, MSG_DONTWAIT);
 }
 
-#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0);
+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
 
 static __inline__ void netlink_receive_user_skb(struct sk_buff *skb)
 {
diff -Nru a/net/ipv6/sit.c b/net/ipv6/sit.c
--- a/net/ipv6/sit.c	Sun Apr 14 12:16:59 2002
+++ b/net/ipv6/sit.c	Sun Apr 14 12:16:59 2002
@@ -517,7 +517,11 @@
 		goto tx_error;
 	}
 
-	mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
+	if (tiph->frag_off)
+		mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
+	else
+		mtu = skb->dst ? skb->dst->pmtu : dev->mtu;
+
 	if (mtu < 68) {
 		tunnel->stat.collisions++;
 		ip_rt_put(rt);
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	Sun Apr 14 12:16:54 2002
+++ b/net/ipv6/tcp_ipv6.c	Sun Apr 14 12:16:54 2002
@@ -136,7 +136,7 @@
 				break;
 	}
 	if (tb != NULL && tb->owners != NULL) {
-		if (tb->fastreuse != 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
+		if (tb->fastreuse > 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
 			goto success;
 		} else {
 			struct ipv6_pinfo *np = inet6_sk(sk);
@@ -377,22 +377,22 @@
 }
 
 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
-					      struct ipv6hdr *ip6h,
-					      struct tcphdr *th,
-					      int iif,
-					      struct open_request ***prevp)
+					      struct open_request ***prevp,
+					      __u16 rport,
+					      struct in6_addr *raddr,
+					      struct in6_addr *laddr,
+					      int iif)
 {
 	struct tcp_listen_opt *lopt = tp->listen_opt;
 	struct open_request *req, **prev;  
-	__u16 rport = th->source;
 
-	for (prev = &lopt->syn_table[tcp_v6_synq_hash(&ip6h->saddr, rport)];
+	for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport)];
 	     (req = *prev) != NULL;
 	     prev = &req->dl_next) {
 		if (req->rmt_port == rport &&
 		    req->class->family == AF_INET6 &&
-		    !ipv6_addr_cmp(&req->af.v6_req.rmt_addr, &ip6h->saddr) &&
-		    !ipv6_addr_cmp(&req->af.v6_req.loc_addr, &ip6h->daddr) &&
+		    !ipv6_addr_cmp(&req->af.v6_req.rmt_addr, raddr) &&
+		    !ipv6_addr_cmp(&req->af.v6_req.loc_addr, laddr) &&
 		    (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
 			BUG_TRAP(req->sk == NULL);
 			*prevp = prev;
@@ -499,11 +499,21 @@
 	return -EADDRNOTAVAIL;
 }
 
-static int tcp_v6_hash_connecting(struct sock *sk)
+static int tcp_v6_hash_connect(struct sock *sk)
 {
-	unsigned short snum = inet_sk(sk)->num;
-	struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(snum)];
-	struct tcp_bind_bucket *tb = head->chain;
+	struct tcp_bind_hashbucket *head;
+	struct tcp_bind_bucket *tb;
+
+	/* XXX */
+	if (inet_sk(sk)->num == 0) { 
+		int err = tcp_v6_get_port(sk, inet_sk(sk)->num);
+		if (err)
+			return err;
+		inet_sk(sk)->sport = htons(inet_sk(sk)->num);
+	}
+
+	head = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)];
+	tb = head->chain;
 
 	spin_lock_bh(&head->lock);
 
@@ -534,7 +544,6 @@
 	struct in6_addr saddr_buf;
 	struct flowi fl;
 	struct dst_entry *dst;
-	struct sk_buff *buff;
 	int addr_type;
 	int err;
 
@@ -675,17 +684,12 @@
 		tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
 	tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 
-	err = -ENOBUFS;
-	buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
-
-	if (buff == NULL)
-		goto failure;
-
 	inet->dport = usin->sin6_port;
 
-	/*
-	 *	Init variables
-	 */
+	tcp_set_state(sk, TCP_SYN_SENT);
+	err = tcp_v6_hash_connect(sk);
+	if (err)
+		goto late_failure;
 
 	if (!tp->write_seq)
 		tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
@@ -693,10 +697,14 @@
 							     inet->sport,
 							     inet->dport);
 
-	err = tcp_connect(sk, buff);
-	if (err == 0)
-		return 0;
+	err = tcp_connect(sk);
+	if (err)
+		goto late_failure;
+
+	return 0;
 
+late_failure:
+	tcp_set_state(sk, TCP_CLOSE);
 failure:
 	__sk_dst_reset(sk);
 	inet->dport = 0;
@@ -708,8 +716,6 @@
 		int type, int code, int offset, __u32 info)
 {
 	struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
-	struct in6_addr *saddr = &hdr->saddr;
-	struct in6_addr *daddr = &hdr->daddr;
 	struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
 	struct ipv6_pinfo *np;
 	struct sock *sk;
@@ -717,7 +723,7 @@
 	struct tcp_opt *tp; 
 	__u32 seq;
 
-	sk = tcp_v6_lookup(daddr, th->dest, saddr, th->source, skb->dev->ifindex);
+	sk = tcp_v6_lookup(&hdr->daddr, th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
 
 	if (sk == NULL) {
 		ICMP6_INC_STATS_BH(Icmp6InErrors);
@@ -790,15 +796,12 @@
 	/* Might be for an open_request */
 	switch (sk->state) {
 		struct open_request *req, **prev;
-		struct ipv6hdr hd;
 	case TCP_LISTEN:
 		if (sk->lock.users)
 			goto out;
 
-		/* Grrrr - fix this later. */
-		ipv6_addr_copy(&hd.saddr, saddr);
-		ipv6_addr_copy(&hd.daddr, daddr); 
-		req = tcp_v6_search_req(tp, &hd, th, tcp_v6_iif(skb), &prev);
+		req = tcp_v6_search_req(tp, &prev, th->dest, &hdr->daddr,
+					&hdr->saddr, tcp_v6_iif(skb));
 		if (!req)
 			goto out;
 
@@ -1107,7 +1110,8 @@
 	struct sock *nsk;
 
 	/* Find possible connection requests. */
-	req = tcp_v6_search_req(tp, skb->nh.ipv6h, th, tcp_v6_iif(skb), &prev);
+	req = tcp_v6_search_req(tp, &prev, th->source, &skb->nh.ipv6h->saddr,
+				&skb->nh.ipv6h->daddr, tcp_v6_iif(skb));
 	if (req)
 		return tcp_check_req(sk, skb, req, prev);
 
@@ -1142,7 +1146,6 @@
 	req->sk = NULL;
 	req->expires = jiffies + TCP_TIMEOUT_INIT;
 	req->retrans = 0;
-	req->index = h;
 	req->dl_next = lopt->syn_table[h];
 
 	write_lock(&tp->syn_wait_lock);
@@ -1790,7 +1793,6 @@
 	tcp_v6_rebuild_header,
 	tcp_v6_conn_request,
 	tcp_v6_syn_recv_sock,
-	tcp_v6_hash_connecting,
 	tcp_v6_remember_stamp,
 	sizeof(struct ipv6hdr),
 
@@ -1810,7 +1812,6 @@
 	tcp_v4_rebuild_header,
 	tcp_v6_conn_request,
 	tcp_v6_syn_recv_sock,
-	tcp_v4_hash_connecting,
 	tcp_v4_remember_stamp,
 	sizeof(struct iphdr),
 
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	Sun Apr 14 12:16:56 2002
+++ b/net/ipv6/udp.c	Sun Apr 14 12:16:56 2002
@@ -293,6 +293,8 @@
 				return -EINVAL;
 			}
 			sk->bound_dev_if = usin->sin6_scope_id;
+			if (!sk->bound_dev_if && (addr_type&IPV6_ADDR_MULTICAST))
+				fl.oif = np->mcast_oif;
 		}
 
 		/* Connect to link-local address requires an interface */
@@ -316,6 +318,9 @@
 	fl.oif = sk->bound_dev_if;
 	fl.uli_u.ports.dport = inet->dport;
 	fl.uli_u.ports.sport = inet->sport;
+
+	if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
+		fl.oif = np->mcast_oif;
 
 	if (flowlabel) {
 		if (flowlabel->opt && flowlabel->opt->srcrt) {
diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c
--- a/net/irda/af_irda.c	Sun Apr 14 12:16:57 2002
+++ b/net/irda/af_irda.c	Sun Apr 14 12:16:57 2002
@@ -415,6 +415,7 @@
  * hint bits), and then wake up any process waiting for answer...
  */
 static void irda_selective_discovery_indication(discovery_t *discovery,
+						DISCOVERY_MODE mode,
 						void *priv)
 {
 	struct irda_sock *self;
@@ -1286,6 +1287,9 @@
 		/* Check if we are still connected */
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
+		/* Handle signals */
+		if (signal_pending(current)) 
+			return -ERESTARTSYS;
 	}
 
 	/* Check that we don't send out to big frames */
diff -Nru a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
--- a/net/irda/ircomm/ircomm_tty.c	Sun Apr 14 12:16:57 2002
+++ b/net/irda/ircomm/ircomm_tty.c	Sun Apr 14 12:16:57 2002
@@ -416,7 +416,7 @@
 		self->line = line;
 		self->tqueue.routine = ircomm_tty_do_softint;
 		self->tqueue.data = self;
-		self->max_header_size = 5;
+		self->max_header_size = IRCOMM_TTY_HDR_UNITIALISED;
 		self->max_data_size = 64-self->max_header_size;
 		self->close_delay = 5*HZ/10;
 		self->closing_wait = 30*HZ;
@@ -695,6 +695,20 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
+	/* We may receive packets from the TTY even before we have finished
+	 * our setup. Not cool.
+	 * The problem is that we would allocate a skb with bogus header and
+	 * data size, and when adding data to it later we would get
+	 * confused.
+	 * Better to not accept data until we are properly setup. Use bogus
+	 * header size to check that (safest way to detect it).
+	 * Jean II */
+	if (self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED) {
+		/* TTY will retry */
+		IRDA_DEBUG(2, __FUNCTION__ "() : not initialised\n");
+		return len;
+	}
+
 	save_flags(flags);
 	cli();
 
@@ -791,8 +805,12 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-	/* Check if we are allowed to transmit any data */
-	if (tty->hw_stopped)
+	/* Check if we are allowed to transmit any data.
+	 * hw_stopped is the regular flow control.
+	 * max_header_size tells us if the channel is initialised or not.
+	 * Jean II */
+	if ((tty->hw_stopped) ||
+	    (self->max_header_size == IRCOMM_TTY_HDR_UNITIALISED))
 		ret = 0;
 	else {
 		save_flags(flags);
diff -Nru a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
--- a/net/irda/ircomm/ircomm_tty_attach.c	Sun Apr 14 12:16:57 2002
+++ b/net/irda/ircomm/ircomm_tty_attach.c	Sun Apr 14 12:16:57 2002
@@ -47,6 +47,7 @@
 
 static void ircomm_tty_ias_register(struct ircomm_tty_cb *self);
 static void ircomm_tty_discovery_indication(discovery_t *discovery,
+					    DISCOVERY_MODE mode,
 					    void *priv);
 static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
 					struct ias_value *value, void *priv);
@@ -305,12 +306,27 @@
  *
  */
 static void ircomm_tty_discovery_indication(discovery_t *discovery,
+					    DISCOVERY_MODE mode,
 					    void *priv)
 {
 	struct ircomm_tty_cb *self;
 	struct ircomm_tty_info info;
 
 	IRDA_DEBUG(2, __FUNCTION__"()\n");
+
+	/* Important note :
+	 * We need to drop all passive discoveries.
+	 * The LSAP management of IrComm is deficient and doesn't deal
+	 * with the case of two instance connecting to each other
+	 * simultaneously (it will deadlock in LMP).
+	 * The proper fix would be to use the same technique as in IrNET,
+	 * to have one server socket and separate instances for the
+	 * connecting/connected socket.
+	 * The workaround is to drop passive discovery, which drastically
+	 * reduce the probability of this happening.
+	 * Jean II */
+	if(mode == DISCOVERY_PASSIVE)
+		return;
 
 	info.daddr = discovery->daddr;
 	info.saddr = discovery->saddr;
diff -Nru a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
--- a/net/irda/ircomm/ircomm_tty_ioctl.c	Sun Apr 14 12:16:54 2002
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c	Sun Apr 14 12:16:54 2002
@@ -93,6 +93,9 @@
 	if (cflag & CRTSCTS) {
 		self->flags |= ASYNC_CTS_FLOW;
 		self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
+		/* This got me. Bummer. Jean II */
+		if (self->service_type == IRCOMM_3_WIRE_RAW)
+			WARNING(__FUNCTION__ "(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n");
 	} else {
 		self->flags &= ~ASYNC_CTS_FLOW;
 		self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
diff -Nru a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
--- a/net/irda/irlan/irlan_client.c	Sun Apr 14 12:16:54 2002
+++ b/net/irda/irlan/irlan_client.c	Sun Apr 14 12:16:54 2002
@@ -145,7 +145,9 @@
  *    Remote device with IrLAN server support discovered
  *
  */
-void irlan_client_discovery_indication(discovery_t *discovery, void *priv) 
+void irlan_client_discovery_indication(discovery_t *discovery,
+				       DISCOVERY_MODE mode,
+				       void *priv) 
 {
 	struct irlan_cb *self;
 	__u32 saddr, daddr;
@@ -154,6 +156,15 @@
 
 	ASSERT(irlan != NULL, return;);
 	ASSERT(discovery != NULL, return;);
+
+	/*
+	 * I didn't check it, but I bet that IrLAN suffer from the same
+	 * deficiency as IrComm and doesn't handle two instances
+	 * simultaneously connecting to each other.
+	 * Same workaround, drop passive discoveries.
+	 * Jean II */
+	if(mode == DISCOVERY_PASSIVE)
+		return;
 
 	saddr = discovery->saddr;
 	daddr = discovery->daddr;
diff -Nru a/net/irda/irlap_event.c b/net/irda/irlap_event.c
--- a/net/irda/irlap_event.c	Sun Apr 14 12:16:55 2002
+++ b/net/irda/irlap_event.c	Sun Apr 14 12:16:55 2002
@@ -174,6 +174,12 @@
 	irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
 }
 
+/*
+ * Calculate and set time before we will have to send back the pf bit
+ * to the peer. Use in primary.
+ * Make sure that state is XMIT_P/XMIT_S when calling this function
+ * (and that nobody messed up with the state). - Jean II
+ */
 void irlap_start_poll_timer(struct irlap_cb *self, int timeout)
 {
 	ASSERT(self != NULL, return;);
@@ -1163,15 +1169,26 @@
 				self->ack_required = TRUE;
 			
 				irlap_wait_min_turn_around(self, &self->qos_tx);
-				/* 
-				 * Important to switch state before calling
-				 * upper layers
-				 */
-				irlap_next_state(self, LAP_XMIT_P);
 
+				/* Call higher layer *before* changing state
+				 * to give them a chance to send data in the
+				 * next LAP frame.
+				 * Jean II */
 				irlap_data_indication(self, skb, FALSE);
 
-				/* This is the last frame */
+				/* XMIT states are the most dangerous state
+				 * to be in, because user requests are
+				 * processed directly and may change state.
+				 * On the other hand, in NDM_P, those
+				 * requests are queued and we will process
+				 * them when we return to irlap_do_event().
+				 * Jean II
+				 */
+				irlap_next_state(self, LAP_XMIT_P);
+
+				/* This is the last frame.
+				 * Make sure it's always called in XMIT state.
+				 * - Jean II */
 				irlap_start_poll_timer(self, self->poll_timeout);
 			}
 			break;
@@ -1309,6 +1326,7 @@
 		} else {
 			del_timer(&self->final_timer);
 			irlap_data_indication(self, skb, TRUE);
+			irlap_next_state(self, LAP_XMIT_P);
 			printk(__FUNCTION__ "(): RECV_UI_FRAME: next state %s\n", irlap_state[self->state]);
 			irlap_start_poll_timer(self, self->poll_timeout);
 		}
diff -Nru a/net/irda/irlmp.c b/net/irda/irlmp.c
--- a/net/irda/irlmp.c	Sun Apr 14 12:16:59 2002
+++ b/net/irda/irlmp.c	Sun Apr 14 12:16:59 2002
@@ -732,7 +732,9 @@
 	 * On links which are connected, we can't do discovery
 	 * anymore and can't refresh the log, so we freeze the
 	 * discovery log to keep info about the device we are
-	 * connected to. - Jean II
+	 * connected to.
+	 * This info is mandatory if we want irlmp_connect_request()
+	 * to work properly. - Jean II
 	 */
 	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
 	while (lap != NULL) {
@@ -804,7 +806,7 @@
 void irlmp_discovery_request(int nslots)
 {
 	/* Return current cached discovery log */
-	irlmp_discovery_confirm(irlmp->cachelog);
+	irlmp_discovery_confirm(irlmp->cachelog, DISCOVERY_LOG);
 
 	/* 
 	 * Start a single discovery operation if discovery is not already
@@ -907,7 +909,8 @@
  * partial/selective discovery based on the hints that it passed to IrLMP.
  */
 static inline void
-irlmp_notify_client(irlmp_client_t *client, hashbin_t *log)
+irlmp_notify_client(irlmp_client_t *client,
+		    hashbin_t *log, DISCOVERY_MODE mode)
 {
 	discovery_t *discovery;
 
@@ -930,7 +933,7 @@
 		 * bits ;-)
 		 */
 		if (client->hint_mask & discovery->hints.word & 0x7f7f)
-			client->disco_callback(discovery, client->priv);
+			client->disco_callback(discovery, mode, client->priv);
 
 		discovery = (discovery_t *) hashbin_get_next(log);
 	}
@@ -943,7 +946,7 @@
  *    device it is, and give indication to the client(s)
  * 
  */
-void irlmp_discovery_confirm(hashbin_t *log) 
+void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode) 
 {
 	irlmp_client_t *client;
 	
@@ -957,7 +960,7 @@
 	client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
 	while (client != NULL) {
 		/* Check if we should notify client */
-		irlmp_notify_client(client, log);
+		irlmp_notify_client(client, log, mode);
 			
 		client = (irlmp_client_t *) hashbin_get_next(irlmp->clients);
 	}
@@ -987,7 +990,8 @@
 		/* Check if we should notify client */
 		if ((client->expir_callback) &&
 		    (client->hint_mask & expiry->hints.word & 0x7f7f))
-			client->expir_callback(expiry, client->priv);
+			client->expir_callback(expiry, EXPIRY_TIMEOUT,
+					       client->priv);
 
 		/* Next client */
 		client = (irlmp_client_t *) hashbin_get_next(irlmp->clients);
diff -Nru a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
--- a/net/irda/irlmp_event.c	Sun Apr 14 12:16:56 2002
+++ b/net/irda/irlmp_event.c	Sun Apr 14 12:16:56 2002
@@ -459,6 +459,15 @@
 					    LM_LAP_DISCONNECT_INDICATION,
 					    NULL);
 		}
+
+		/* Force an expiry of the discovery log.
+		 * Now that the LAP is free, the system may attempt to
+		 * connect to another device. Unfortunately, our entries
+		 * are stale. There is a small window (<3s) before the
+		 * normal discovery will run and where irlmp_connect_request()
+		 * can get the wrong info, so make sure things get
+		 * cleaned *NOW* ;-) - Jean II */
+		irlmp_do_expiry();
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
diff -Nru a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
--- a/net/irda/irlmp_frame.c	Sun Apr 14 12:16:59 2002
+++ b/net/irda/irlmp_frame.c	Sun Apr 14 12:16:59 2002
@@ -378,7 +378,7 @@
 	
 	/* Just handle it the same way as a discovery confirm,
 	 * bypass the LM_LAP state machine (see below) */
-	irlmp_discovery_confirm(irlmp->cachelog);
+	irlmp_discovery_confirm(irlmp->cachelog, DISCOVERY_PASSIVE);
 }
 
 /*
@@ -404,7 +404,7 @@
 	 *	2) It doesn't affect the LM_LAP state
 	 *	3) Faster, slimer, simpler, ...
 	 * Jean II */
-	irlmp_discovery_confirm(irlmp->cachelog);
+	irlmp_discovery_confirm(irlmp->cachelog, DISCOVERY_ACTIVE);
 }
 
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
diff -Nru a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
--- a/net/irda/irnet/irnet.h	Sun Apr 14 12:16:59 2002
+++ b/net/irda/irnet/irnet.h	Sun Apr 14 12:16:59 2002
@@ -211,6 +211,12 @@
  *	o When receiving a disconnect indication, don't reenable the
  *	  PPP Tx queue, this will trigger a reconnect. Instead, close
  *	  the channel, which will kill pppd...
+ *
+ * v11 - 20.3.02 - Jean II
+ *	o Oops ! v10 fix disabled IrNET retries and passive behaviour.
+ *	  Better fix in irnet_disconnect_indication() :
+ *	  - if connected, kill pppd via hangup.
+ *	  - if not connected, reenable ppp Tx, which trigger IrNET retry.
  */
 
 /***************************** INCLUDES *****************************/
diff -Nru a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
--- a/net/irda/irnet/irnet_irda.c	Sun Apr 14 12:16:55 2002
+++ b/net/irda/irnet/irnet_irda.c	Sun Apr 14 12:16:55 2002
@@ -1070,7 +1070,7 @@
  *	o attempted to connect, timeout
  *	o connected, link is broken, LAP has timeout
  *	o connected, other side close the link
- *	o connection request on the server no handled
+ *	o connection request on the server not handled
  */
 static void
 irnet_disconnect_indication(void *	instance,
@@ -1121,20 +1121,31 @@
       DEBUG(IRDA_CB_INFO, "Closing our TTP connection.\n");
       irttp_close_tsap(self->tsap);
       self->tsap = NULL;
-
-      /* Cleanup & close the PPP channel, which will kill pppd and the rest */
-      if(self->ppp_open)
-	ppp_unregister_channel(&self->chan);
-      self->ppp_open = 0;
     }
-  /* Cleanup the socket in case we want to reconnect */
+  /* Cleanup the socket in case we want to reconnect in ppp_output_wakeup() */
   self->stsap_sel = 0;
   self->daddr = DEV_ADDR_ANY;
   self->tx_flow = FLOW_START;
 
-  /* Note : what should we say to ppp ?
-   * It seem the ppp_generic and pppd are happy that way and will eventually
-   * timeout gracefully, so don't bother them... */
+  /* Deal with the ppp instance if it's still alive */
+  if(self->ppp_open)
+    {
+      if(test_open)
+	{
+	  /* If we were connected, cleanup & close the PPP channel,
+	   * which will kill pppd (hangup) and the rest */
+	  ppp_unregister_channel(&self->chan);
+	  self->ppp_open = 0;
+	}
+      else
+	{
+	  /* If we were trying to connect, flush (drain) ppp_generic
+	   * Tx queue (most often we have blocked it), which will
+	   * trigger an other attempt to connect. If we are passive,
+	   * this will empty the Tx queue after last try. */
+	  ppp_output_wakeup(&self->chan);
+	}
+    }
 
   DEXIT(IRDA_TCB_TRACE, "\n");
 }
@@ -1588,8 +1599,9 @@
  * is to messy, so we leave that to user space...
  */
 static void
-irnet_discovery_indication(discovery_t *discovery,
-			   void *	priv)
+irnet_discovery_indication(discovery_t *	discovery,
+			   DISCOVERY_MODE	mode,
+			   void *		priv)
 {
   irnet_socket *	self = &irnet_server.s;
 	
@@ -1627,6 +1639,7 @@
  */
 static void
 irnet_expiry_indication(discovery_t *	expiry,
+			DISCOVERY_MODE	mode,
 			void *		priv)
 {
   irnet_socket *	self = &irnet_server.s;
diff -Nru a/net/irda/irnet/irnet_irda.h b/net/irda/irnet/irnet_irda.h
--- a/net/irda/irnet/irnet_irda.h	Sun Apr 14 12:16:55 2002
+++ b/net/irda/irnet/irnet_irda.h	Sun Apr 14 12:16:55 2002
@@ -151,9 +151,11 @@
 #ifdef DISCOVERY_EVENTS
 static void
 	irnet_discovery_indication(discovery_t *,
+				   DISCOVERY_MODE,
 				   void *);
 static void
 	irnet_expiry_indication(discovery_t *,
+				DISCOVERY_MODE,
 				void *);
 #endif
 /* -------------------------- PROC ENTRY -------------------------- */
diff -Nru a/net/irda/irsysctl.c b/net/irda/irsysctl.c
--- a/net/irda/irsysctl.c	Sun Apr 14 12:16:57 2002
+++ b/net/irda/irsysctl.c	Sun Apr 14 12:16:57 2002
@@ -34,17 +34,19 @@
 #define NET_IRDA 412 /* Random number */
 enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS,
        DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME,
-       MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME };
+       MAX_TX_DATA_SIZE, MAX_NOREPLY_TIME, WARN_NOREPLY_TIME,
+       LAP_KEEPALIVE_TIME };
 
 extern int  sysctl_discovery;
 extern int  sysctl_discovery_slots;
 extern int  sysctl_discovery_timeout;
-extern int  sysctl_slot_timeout;	/* Candidate */
+extern int  sysctl_slot_timeout;
 extern int  sysctl_fast_poll_increase;
 int         sysctl_compression = 0;
 extern char sysctl_devname[];
 extern int  sysctl_max_baud_rate;
 extern int  sysctl_min_tx_turn_time;
+extern int  sysctl_max_tx_data_size;
 extern int  sysctl_max_noreply_time;
 extern int  sysctl_warn_noreply_time;
 extern int  sysctl_lap_keepalive_time;
@@ -64,6 +66,8 @@
 static int min_max_baud_rate = 2400;
 static int max_min_tx_turn_time = 10000;	/* See qos.c - IrLAP spec */
 static int min_min_tx_turn_time = 0;
+static int max_max_tx_data_size = 2048;		/* See qos.c - IrLAP spec */
+static int min_max_tx_data_size = 64;
 static int max_max_noreply_time = 40;		/* See qos.c - IrLAP spec */
 static int min_max_noreply_time = 3;
 static int max_warn_noreply_time = 3;		/* 3s == standard */
@@ -117,6 +121,9 @@
 	{ MIN_TX_TURN_TIME, "min_tx_turn_time", &sysctl_min_tx_turn_time,
 	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
 	  NULL, &min_min_tx_turn_time, &max_min_tx_turn_time },
+	{ MAX_TX_DATA_SIZE, "max_tx_data_size", &sysctl_max_tx_data_size,
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_max_tx_data_size, &max_max_tx_data_size },
 	{ MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time,
 	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
 	  NULL, &min_max_noreply_time, &max_max_noreply_time },
diff -Nru a/net/irda/qos.c b/net/irda/qos.c
--- a/net/irda/qos.c	Sun Apr 14 12:16:57 2002
+++ b/net/irda/qos.c	Sun Apr 14 12:16:57 2002
@@ -57,10 +57,26 @@
  * Nonzero values (usec) are used as lower limit to the per-connection
  * mtt value which was announced by the other end during negotiation.
  * Might be helpful if the peer device provides too short mtt.
- * Default is 10 which means using the unmodified value given by the peer
- * except if it's 0 (0 is likely a bug in the other stack).
+ * Default is 10us which means using the unmodified value given by the
+ * peer except if it's 0 (0 is likely a bug in the other stack).
  */
 unsigned sysctl_min_tx_turn_time = 10;
+/*
+ * Maximum data size to be used in transmission in payload of LAP frame.
+ * There is a bit of confusion in the IrDA spec :
+ * The LAP spec defines the payload of a LAP frame (I field) to be
+ * 2048 bytes max (IrLAP 1.1, chapt 6.6.5, p40).
+ * On the other hand, the PHY mention frames of 2048 bytes max (IrPHY
+ * 1.2, chapt 5.3.2.1, p41). But, this number includes the LAP header
+ * (2 bytes), and CRC (32 bits at 4 Mb/s). So, for the I field (LAP
+ * payload), that's only 2042 bytes. Oups !
+ * I've had trouble trouble transmitting 2048 bytes frames with USB
+ * dongles and nsc-ircc at 4 Mb/s, so adjust to 2042... I don't know
+ * if this bug applies only for 2048 bytes frames or all negociated
+ * frame sizes, but all hardware seem to support "2048 bytes" frames.
+ * You can use the sysctl to play with this value anyway.
+ * Jean II */
+unsigned sysctl_max_tx_data_size = 2042;
 
 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
 static int irlap_param_link_disconnect(void *instance, irda_param_t *parm, 
@@ -355,10 +371,10 @@
 	while ((qos->data_size.value > line_capacity) && (index > 0)) {
 		qos->data_size.value = data_sizes[index--];
 		IRDA_DEBUG(2, __FUNCTION__ 
-			   "(), redusing data size to %d\n",
+			   "(), reducing data size to %d\n",
 			   qos->data_size.value);
 	}
-#else /* Use method descibed in section 6.6.11 of IrLAP */
+#else /* Use method described in section 6.6.11 of IrLAP */
 	while (irlap_requested_line_capacity(qos) > line_capacity) {
 		ASSERT(index != 0, return;);
 
@@ -366,18 +382,24 @@
 		if (qos->window_size.value > 1) {
 			qos->window_size.value--;
 			IRDA_DEBUG(2, __FUNCTION__ 
-				   "(), redusing window size to %d\n",
+				   "(), reducing window size to %d\n",
 				   qos->window_size.value);
 		} else if (index > 1) {
 			qos->data_size.value = data_sizes[index--];
 			IRDA_DEBUG(2, __FUNCTION__ 
-				   "(), redusing data size to %d\n",
+				   "(), reducing data size to %d\n",
 				   qos->data_size.value);
 		} else {
 			WARNING(__FUNCTION__ "(), nothing more we can do!\n");
 		}
 	}
 #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
+	/*
+	 * Fix tx data size according to user limits - Jean II
+	 */
+	if (qos->data_size.value > sysctl_max_tx_data_size)
+		/* Allow non discrete adjustement to avoid loosing capacity */
+		qos->data_size.value = sysctl_max_tx_data_size;
 }
 
 /*
diff -Nru a/net/khttpd/sockets.c b/net/khttpd/sockets.c
--- a/net/khttpd/sockets.c	Sun Apr 14 12:16:55 2002
+++ b/net/khttpd/sockets.c	Sun Apr 14 12:16:55 2002
@@ -82,7 +82,7 @@
 	
 	MainSocket = sock;
 	
-	EnterFunction("StartListening");
+	LeaveFunction("StartListening");
 	return 1; 
 }	
 
diff -Nru a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
--- a/net/lapb/lapb_iface.c	Sun Apr 14 12:16:58 2002
+++ b/net/lapb/lapb_iface.c	Sun Apr 14 12:16:58 2002
@@ -407,5 +407,6 @@
 
 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
+MODULE_LICENSE("GPL");
 
 module_init(lapb_init);
diff -Nru a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
--- a/net/netlink/netlink_dev.c	Sun Apr 14 12:16:57 2002
+++ b/net/netlink/netlink_dev.c	Sun Apr 14 12:16:57 2002
@@ -206,6 +206,8 @@
 
 #ifdef MODULE
 
+MODULE_LICENSE("GPL");
+
 int init_module(void)
 {
 	printk(KERN_INFO "Network Kernel/User communications module 0.04\n");
diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
--- a/net/netrom/af_netrom.c	Sun Apr 14 12:16:58 2002
+++ b/net/netrom/af_netrom.c	Sun Apr 14 12:16:58 2002
@@ -29,7 +29,7 @@
  *	NET/ROM 006	Alan(GW4PTS)	Brought in line with the ANK changes
  *			Jonathan(G4KLX)	Removed hdrincl.
  *	NET/ROM 007	Jonathan(G4KLX)	New timer architecture.
- *					Impmented Idle timer.
+ *					Implemented Idle timer.
  *			Arnaldo C. Melo s/suser/capable/, micro cleanups
  */
 
@@ -1338,6 +1338,7 @@
 
 MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol");
+MODULE_LICENSE("GPL");
 
 static void __exit nr_exit(void)
 {
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Sun Apr 14 12:16:58 2002
+++ b/net/netsyms.c	Sun Apr 14 12:16:58 2002
@@ -364,7 +364,6 @@
 EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
 EXPORT_SYMBOL(tcp_v4_do_rcv);
 EXPORT_SYMBOL(tcp_v4_connect);
-EXPORT_SYMBOL(tcp_v4_hash_connecting);
 EXPORT_SYMBOL(tcp_unhash);
 EXPORT_SYMBOL(udp_prot);
 EXPORT_SYMBOL(tcp_prot);
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	Sun Apr 14 12:16:55 2002
+++ b/net/packet/af_packet.c	Sun Apr 14 12:16:55 2002
@@ -358,6 +358,8 @@
 	if (dev->hard_header) {
 		skb->data -= dev->hard_header_len;
 		skb->tail -= dev->hard_header_len;
+		if (len < dev->hard_header_len)
+			skb->nh.raw = skb->data;
 	}
 
 	/* Returns -EFAULT on error */
diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c
--- a/net/rose/af_rose.c	Sun Apr 14 12:16:58 2002
+++ b/net/rose/af_rose.c	Sun Apr 14 12:16:58 2002
@@ -1519,6 +1519,7 @@
 
 MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The amateur radio ROSE network layer protocol");
+MODULE_LICENSE("GPL");
 
 static void __exit rose_exit(void)
 {
diff -Nru a/net/sched/sch_prio.c b/net/sched/sch_prio.c
--- a/net/sched/sch_prio.c	Sun Apr 14 12:16:58 2002
+++ b/net/sched/sch_prio.c	Sun Apr 14 12:16:58 2002
@@ -327,6 +327,7 @@
 
 	if (cl - 1 > q->bands)
 		return -ENOENT;
+	tcm->tcm_handle |= TC_H_MIN(cl);
 	if (q->queues[cl-1])
 		tcm->tcm_info = q->queues[cl-1]->handle;
 	return 0;
diff -Nru a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
--- a/net/sched/sch_sfq.c	Sun Apr 14 12:16:57 2002
+++ b/net/sched/sch_sfq.c	Sun Apr 14 12:16:57 2002
@@ -105,6 +105,7 @@
 /* Parameters */
 	int		perturb_period;
 	unsigned	quantum;	/* Allotment per round: MUST BE >= MTU */
+	int		limit;
 
 /* Variables */
 	struct timer_list perturb_timer;
@@ -275,7 +276,7 @@
 			q->tail = x;
 		}
 	}
-	if (++sch->q.qlen < SFQ_DEPTH-1) {
+	if (++sch->q.qlen < q->limit-1) {
 		sch->stats.bytes += skb->len;
 		sch->stats.packets++;
 		return 0;
@@ -310,7 +311,7 @@
 			q->tail = x;
 		}
 	}
-	if (++sch->q.qlen < SFQ_DEPTH-1)
+	if (++sch->q.qlen < q->limit - 1)
 		return 0;
 
 	sch->stats.drops++;
@@ -390,6 +391,11 @@
 	sch_tree_lock(sch);
 	q->quantum = ctl->quantum ? : psched_mtu(sch->dev);
 	q->perturb_period = ctl->perturb_period*HZ;
+	if (ctl->limit)
+		q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
+
+	while (sch->q.qlen >= q->limit-1)
+		sfq_drop(sch);
 
 	del_timer(&q->perturb_timer);
 	if (q->perturb_period) {
@@ -416,6 +422,7 @@
 		q->dep[i+SFQ_DEPTH].next = i+SFQ_DEPTH;
 		q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH;
 	}
+	q->limit = SFQ_DEPTH;
 	q->max_depth = 0;
 	q->tail = SFQ_DEPTH;
 	if (opt == NULL) {
@@ -448,9 +455,9 @@
 	opt.quantum = q->quantum;
 	opt.perturb_period = q->perturb_period/HZ;
 
-	opt.limit = SFQ_DEPTH;
+	opt.limit = q->limit;
 	opt.divisor = SFQ_HASH_DIVISOR;
-	opt.flows = SFQ_DEPTH;
+	opt.flows = q->limit;
 
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 
diff -Nru a/net/sunrpc/stats.c b/net/sunrpc/stats.c
--- a/net/sunrpc/stats.c	Sun Apr 14 12:16:58 2002
+++ b/net/sunrpc/stats.c	Sun Apr 14 12:16:58 2002
@@ -21,6 +21,7 @@
 #include <linux/proc_fs.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svcsock.h>
+#include <linux/init.h>
 
 #define RPCDBG_FACILITY	RPCDBG_MISC
 
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	Sun Apr 14 12:16:55 2002
+++ b/net/sunrpc/xprt.c	Sun Apr 14 12:16:55 2002
@@ -1097,7 +1097,7 @@
 		return;
 
 	/* Wait until we have enough socket memory. */
-	if (sock_writeable(sk))
+	if (!sock_writeable(sk))
 		return;
 
 	if (!xprt_test_and_set_wspace(xprt)) {
diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c
--- a/net/x25/af_x25.c	Sun Apr 14 12:16:58 2002
+++ b/net/x25/af_x25.c	Sun Apr 14 12:16:58 2002
@@ -1371,6 +1371,7 @@
 
 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol");
+MODULE_LICENSE("GPL");
 
 static void __exit x25_exit(void)
 {
diff -Nru a/scripts/mkspec b/scripts/mkspec
--- a/scripts/mkspec	Sun Apr 14 12:16:54 2002
+++ b/scripts/mkspec	Sun Apr 14 12:16:54 2002
@@ -6,9 +6,15 @@
 #	The only gothic bit here is redefining install_post to avoid 
 #	stripping the symbols from files in the kernel which we want
 #
+if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
+	PROVIDES=kernel-drm
+fi
+
+PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
 echo "Name: kernel"
 echo "Summary: The Linux Kernel"
-echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//"
+echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
 # we need to determine the NEXT version number so that uname and
 # rpm -q will agree
 echo "Release: `. scripts/mkversion`"
@@ -17,8 +23,9 @@
 echo "Vendor: The Linux Community"
 echo "URL: http://www.kernel.org"
 echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
-echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//"
+echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
 echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
+echo "Provides: $PROVIDES"
 echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
 echo ""
 echo "%description"
@@ -35,6 +42,7 @@
 echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
 echo 'cp arch/i386/boot/bzImage $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
 echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
 echo ""
 echo "%clean"
 echo '#echo -rf $RPM_BUILD_ROOT'
diff -Nru a/sound/core/rtctimer.c b/sound/core/rtctimer.c
--- a/sound/core/rtctimer.c	Sun Apr 14 12:16:56 2002
+++ b/sound/core/rtctimer.c	Sun Apr 14 12:16:56 2002
@@ -52,7 +52,7 @@
 
 
 /*
- * The hardware dependent description for this timer.
+ * The hardware dependant description for this timer.
  */
 static struct _snd_timer_hardware rtc_hw = {
 	flags:		SNDRV_TIMER_HW_FIRST|SNDRV_TIMER_HW_AUTO,
diff -Nru a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
--- a/sound/oss/ac97_codec.c	Sun Apr 14 12:16:56 2002
+++ b/sound/oss/ac97_codec.c	Sun Apr 14 12:16:56 2002
@@ -105,7 +105,9 @@
 	{0x41445340, "Analog Devices AD1881",	&null_ops},
 	{0x41445348, "Analog Devices AD1881A",	&null_ops},
 	{0x41445360, "Analog Devices AD1885",	&default_ops},
+	{0x41445361, "Analog Devices AD1886",	&default_ops},
 	{0x41445460, "Analog Devices AD1885",	&default_ops},
+	{0x41445461, "Analog Devices AD1886",	&default_ops},
 	{0x414B4D00, "Asahi Kasei AK4540",	&null_ops},
 	{0x414B4D01, "Asahi Kasei AK4542",	&null_ops},
 	{0x414B4D02, "Asahi Kasei AK4543",	&null_ops},
diff -Nru a/sound/oss/ad1848.h b/sound/oss/ad1848.h
--- a/sound/oss/ad1848.h	Sun Apr 14 12:16:54 2002
+++ b/sound/oss/ad1848.h	Sun Apr 14 12:16:54 2002
@@ -1,8 +1,3 @@
-/*
- * ad1848.c
- *
- * Copyright:	Christoph Hellwig <chhellwig@gmx.net>
- */
 
 #define AD_F_CS4231     0x0001  /* Returned if a CS4232 (or compatible) detected */
 #define AD_F_CS4248     0x0001  /* Returned if a CS4248 (or compatible) detected */
diff -Nru a/sound/oss/cs4232.h b/sound/oss/cs4232.h
--- a/sound/oss/cs4232.h	Sun Apr 14 12:16:56 2002
+++ b/sound/oss/cs4232.h	Sun Apr 14 12:16:56 2002
@@ -1,9 +1,3 @@
-/*
- *	cs4232.h
- *
- * Copyright: Christoph Hellwig <chhellwig@gmx.net>
- *
- */
 
 int probe_cs4232 (struct address_info *hw_config,int useisapnp);
 void attach_cs4232 (struct address_info *hw_config);
diff -Nru a/sound/oss/gus.h b/sound/oss/gus.h
--- a/sound/oss/gus.h	Sun Apr 14 12:16:57 2002
+++ b/sound/oss/gus.h	Sun Apr 14 12:16:57 2002
@@ -1,9 +1,3 @@
-/*
- * gus.h
- *
- * Copyright:	Christoph Hellwig <chhellwig@gmx.net>
- *
- */
 
 #include "ad1848.h"
 
diff -Nru a/sound/oss/mad16.c b/sound/oss/mad16.c
--- a/sound/oss/mad16.c	Sun Apr 14 12:16:56 2002
+++ b/sound/oss/mad16.c	Sun Apr 14 12:16:56 2002
@@ -42,6 +42,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/gameport.h>
 
 #include "sound_config.h"
 
@@ -51,6 +52,7 @@
 
 static int      mad16_conf;
 static int      mad16_cdsel;
+static struct gameport gameport;
 
 static int      already_initialized = 0;
 
@@ -664,13 +666,13 @@
 
 	outb((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("MAD16 WSS", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4,
 					  hw_config->irq,
 					  dma,
 					  dma2, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "MAD16 WSS config");
+	request_region(hw_config->io_base, 4, "mad16 WSS config");
 }
 
 static int __init probe_mad16_mpu(struct address_info *hw_config)
@@ -1010,14 +1012,6 @@
 	}
 
 	printk(".\n");
-        printk(KERN_INFO "Joystick port ");
-        if (joystick == 1)
-                printk("enabled.\n");
-        else
-        {
-                joystick = 0;
-                printk("disabled.\n");
-        }
 
 	cfg.io_base = io;
 	cfg.irq = irq;
@@ -1038,6 +1032,18 @@
 	attach_mad16(&cfg);
 
 	found_mpu = probe_mad16_mpu(&cfg_mpu);
+
+	if (joystick == 1) {
+	        /* register gameport */
+                if (!request_region(0x201, 1, "mad16 gameport"))
+                        printk(KERN_ERR "mad16: gameport address 0x201 already in use\n");
+                else {
+			printk(KERN_ERR "mad16: gameport enabled at 0x201\n");
+                        gameport.io = 0x201;
+		        gameport_register_port(&gameport);
+                }
+	}
+	else printk(KERN_ERR "mad16: gameport disabled.\n");
 	return 0;
 }
 
@@ -1055,16 +1061,17 @@
 static int __init setup_mad16(char *str)
 {
         /* io, irq */
-	int ints[7];
+	int ints[8];
 	
 	str = get_options(str, ARRAY_SIZE(ints), ints);
 
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma16	= ints[4];
-	mpu_io	= ints[5];
-	mpu_irq = ints[6];
+	io	 = ints[1];
+	irq	 = ints[2];
+	dma	 = ints[3];
+	dma16	 = ints[4];
+	mpu_io	 = ints[5];
+	mpu_irq  = ints[6];
+	joystick = ints[7];
 
 	return 1;
 }
diff -Nru a/sound/oss/mpu401.h b/sound/oss/mpu401.h
--- a/sound/oss/mpu401.h	Sun Apr 14 12:16:58 2002
+++ b/sound/oss/mpu401.h	Sun Apr 14 12:16:58 2002
@@ -1,9 +1,3 @@
-/*
- *	uart401.h 
- *
- * Copyright:	Christoph Hellwig <chhellwig@gmx.net>
- *
- */
 
 /*	From uart401.c */
 int probe_uart401 (struct address_info *hw_config, struct module *owner);
diff -Nru a/sound/oss/opl3.h b/sound/oss/opl3.h
--- a/sound/oss/opl3.h	Sun Apr 14 12:16:55 2002
+++ b/sound/oss/opl3.h	Sun Apr 14 12:16:55 2002
@@ -1,9 +1,3 @@
-/*
- *	opl3.h
- *
- * Copyright:	Christoph Hellwig <chhellwig@gmx.net>
- *
- */
 
 int opl3_detect (int ioaddr, int *osp);
 int opl3_init(int ioaddr, int *osp, struct module *owner);
diff -Nru a/sound/oss/pas2.h b/sound/oss/pas2.h
--- a/sound/oss/pas2.h	Sun Apr 14 12:16:56 2002
+++ b/sound/oss/pas2.h	Sun Apr 14 12:16:56 2002
@@ -1,9 +1,3 @@
-/*
- * pas2.h
- *
- * Copyright:	Christoph Hellwig <chhellwig@gmx.net>
- *
- */
 
 /*	From pas_card.c	*/
 int pas_set_intr(int mask);
diff -Nru a/sound/oss/pss.c b/sound/oss/pss.c
--- a/sound/oss/pss.c	Sun Apr 14 12:16:59 2002
+++ b/sound/oss/pss.c	Sun Apr 14 12:16:59 2002
@@ -48,7 +48,7 @@
  *          Added module parameter pss_firmware to allow the user to tell 
  *          the driver where the fireware file is located.  The default 
  *          setting is the previous hardcoded setting "/etc/sound/pss_synth".
- * 00-03-03: Christoph Hellwig <chhellwig@gmx.net>
+ * 00-03-03: Christoph Hellwig <chhellwig@infradead.org>
  *	    Adapted to module_init/module_exit
  * 11-10-2000: Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  *	    Added __init to probe_pss(), attach_pss() and probe_pss_mpu()
